commit 416bd537338abdf1227b3973d2cf48e239156b7e Author: Gatsby Van Date: Wed Dec 20 00:11:03 2023 +0800 Initial version. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..641db88 --- /dev/null +++ b/Makefile @@ -0,0 +1,12 @@ +DIR := $(shell pwd) + +compile_test: + cd $(DIR)/datalink814_ge/build && make all + cd $(DIR)/datalink814_sp/build && make all + cd $(DIR)/df_datalink/build && make all + +clean: + cd $(DIR)/datalink814_ge/build && make clean + cd $(DIR)/datalink814_sp/build && make clean + cd $(DIR)/df_datalink/build && make clean +.PHONY: clean compile_test \ No newline at end of file diff --git a/datalink814_ge/bsp/.cproject b/datalink814_ge/bsp/.cproject new file mode 100644 index 0000000..d93882f --- /dev/null +++ b/datalink814_ge/bsp/.cproject @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/datalink814_ge/bsp/.project b/datalink814_ge/bsp/.project new file mode 100644 index 0000000..8881082 --- /dev/null +++ b/datalink814_ge/bsp/.project @@ -0,0 +1,75 @@ + + + datalink814_ge_bsp + Created by SDK v2019.1 + + + + + org.eclipse.cdt.make.core.makeBuilder + + + org.eclipse.cdt.core.errorOutputParser + org.eclipse.cdt.core.GASErrorParser;org.eclipse.cdt.core.GLDErrorParser;org.eclipse.cdt.core.GCCErrorParser;org.eclipse.cdt.core.GmakeErrorParser;org.eclipse.cdt.core.VCErrorParser;org.eclipse.cdt.core.CWDLocator;org.eclipse.cdt.core.MakeErrorParser; + + + org.eclipse.cdt.make.core.append_environment + true + + + org.eclipse.cdt.make.core.build.arguments + + + + org.eclipse.cdt.make.core.build.command + make + + + org.eclipse.cdt.make.core.build.target.auto + all + + + org.eclipse.cdt.make.core.build.target.clean + clean + + + org.eclipse.cdt.make.core.build.target.inc + all + + + org.eclipse.cdt.make.core.enableAutoBuild + true + + + org.eclipse.cdt.make.core.enableCleanBuild + true + + + org.eclipse.cdt.make.core.enableFullBuild + true + + + org.eclipse.cdt.make.core.enabledIncrementalBuild + true + + + org.eclipse.cdt.make.core.environment + + + + org.eclipse.cdt.make.core.stopOnError + false + + + org.eclipse.cdt.make.core.useDefaultBuildCmd + true + + + + + + com.xilinx.sdk.sw.SwProjectNature + org.eclipse.cdt.core.cnature + org.eclipse.cdt.make.core.makeNature + + diff --git a/datalink814_ge/bsp/.sdkproject b/datalink814_ge/bsp/.sdkproject new file mode 100644 index 0000000..7e04c35 --- /dev/null +++ b/datalink814_ge/bsp/.sdkproject @@ -0,0 +1,4 @@ +THIRPARTY=false +HW_PROJECT_REFERENCE=system_top_hw_platform_0 +PROCESSOR=ps7_cortexa9_0 +MSS_FILE=system.mss diff --git a/datalink814_ge/bsp/Makefile b/datalink814_ge/bsp/Makefile new file mode 100644 index 0000000..c7117f5 --- /dev/null +++ b/datalink814_ge/bsp/Makefile @@ -0,0 +1,35 @@ +# Makefile generated by Xilinx. + +PROCESSOR = ps7_cortexa9_0 +LIBRARIES = ${PROCESSOR}/lib/libxil.a +BSP_MAKEFILES := $(wildcard $(PROCESSOR)/libsrc/*/src/Makefile) +SUBDIRS := $(patsubst %/Makefile, %, $(BSP_MAKEFILES)) + +ifneq (,$(findstring win,$(RDI_PLATFORM))) + SHELL = CMD +endif + +all: libs + @echo 'Finished building libraries' + +include: $(addsuffix /make.include,$(SUBDIRS)) + +libs: $(addsuffix /make.libs,$(SUBDIRS)) + +clean: $(addsuffix /make.clean,$(SUBDIRS)) + +$(PROCESSOR)/lib/libxil.a: $(PROCESSOR)/lib/libxil_init.a + cp -f $< $@ + +%/make.include: $(if $(wildcard $(PROCESSOR)/lib/libxil_init.a),$(PROCESSOR)/lib/libxil.a,) + @echo "Running Make include in $(subst /make.include,,$@)" + $(MAKE) -C $(subst /make.include,,$@) -s include "SHELL=$(SHELL)" "COMPILER=$(CC)" "ARCHIVER=arm-none-eabi-ar" "COMPILER_FLAGS= -O2 -c" "EXTRA_COMPILER_FLAGS=-mcpu=cortex-a9 -mfpu=vfpv3 -mfloat-abi=hard -nostartfiles -g -Wall -Wextra" + +%/make.libs: include + @echo "Running Make libs in $(subst /make.libs,,$@)" + $(MAKE) -C $(subst /make.libs,,$@) -s libs "SHELL=$(SHELL)" "COMPILER=$(CC)" "ARCHIVER=arm-none-eabi-ar" "COMPILER_FLAGS= -O2 -c" "EXTRA_COMPILER_FLAGS=-mcpu=cortex-a9 -mfpu=vfpv3 -mfloat-abi=hard -nostartfiles -g -Wall -Wextra" + +%/make.clean: + $(MAKE) -C $(subst /make.clean,,$@) -s clean +clean: + rm -f ${PROCESSOR}/lib/libxil.a diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/include/_profile_timer_hw.h b/datalink814_ge/bsp/ps7_cortexa9_0/include/_profile_timer_hw.h new file mode 100644 index 0000000..1647600 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/include/_profile_timer_hw.h @@ -0,0 +1,308 @@ +/****************************************************************************** +* +* Copyright (C) 2004 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +****************************************************************************** +* +* _program_timer_hw.h: +* Timer related functions +* +******************************************************************************/ + +#ifndef PROFILE_TIMER_HW_H +#define PROFILE_TIMER_HW_H + +#include "profile.h" + +#ifdef PROC_PPC +#if defined __GNUC__ +# define SYNCHRONIZE_IO __asm__ volatile ("eieio") +#elif defined __DCC__ +# define SYNCHRONIZE_IO __asm volatile(" eieio") +#else +# define SYNCHRONIZE_IO +#endif +#endif + +#ifdef PROC_PPC +#define ProfIo_In32(InputPtr) { (*(volatile u32 *)(InputPtr)); SYNCHRONIZE_IO; } +#define ProfIo_Out32(OutputPtr, Value) { (*(volatile u32 *)(OutputPtr) = Value); SYNCHRONIZE_IO; } +#else +#define ProfIo_In32(InputPtr) (*(volatile u32 *)(InputPtr)); +#define ProfIo_Out32(OutputPtr, Value) { (*(volatile u32 *)(OutputPtr) = (Value)); } +#endif + +#define ProfTmrCtr_mWriteReg(BaseAddress, TmrCtrNumber, RegOffset, ValueToWrite)\ + ProfIo_Out32(((u32)(BaseAddress) + (u32)XTmrCtr_Offsets[(TmrCtrNumber)] + \ + (u32)(RegOffset)), (u32)(ValueToWrite)) + +#define ProfTimerCtr_mReadReg(BaseAddress, TmrCtrNumber, RegOffset) \ + ProfIo_In32((u32)(BaseAddress) + (u32)XTmrCtr_Offsets[(TmrCtrNumber)] + (u32)(RegOffset)) + +#define ProfTmrCtr_mSetControlStatusReg(BaseAddress, TmrCtrNumber, RegisterValue)\ + ProfTmrCtr_mWriteReg((BaseAddress), (TmrCtrNumber), XTC_TCSR_OFFSET, \ + (RegisterValue)) + +#define ProfTmrCtr_mGetControlStatusReg(BaseAddress, TmrCtrNumber) \ + ProfTimerCtr_mReadReg((u32)(BaseAddress), (TmrCtrNumber), XTC_TCSR_OFFSET) + + + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef PROC_PPC +#include "xexception_l.h" +#include "xtime_l.h" +#include "xpseudo_asm.h" +#endif + +#ifdef TIMER_CONNECT_INTC +#include "xintc_l.h" +#include "xintc.h" +#endif /* TIMER_CONNECT_INTC */ + +#if (!defined PPC_PIT_INTERRUPT && !defined PROC_CORTEXA9) +#include "xtmrctr_l.h" +#endif + +#ifdef PROC_CORTEXA9 +#include "xscutimer_hw.h" +#include "xscugic.h" +#endif + +extern u32 timer_clk_ticks ; + +/*-------------------------------------------------------------------- + * PowerPC Target - Timer related functions + *-------------------------------------------------------------------- */ +#ifdef PROC_PPC + +#ifdef PPC_PIT_INTERRUPT +u32 timer_lo_clk_ticks ; /* Clk ticks when Timer is disabled in CG */ +#endif + +#ifdef PROC_PPC440 +#define XREG_TCR_PIT_INTERRUPT_ENABLE XREG_TCR_DEC_INTERRUPT_ENABLE +#define XREG_TSR_PIT_INTERRUPT_STATUS XREG_TSR_DEC_INTERRUPT_STATUS +#define XREG_SPR_PIT XREG_SPR_DEC +#define XEXC_ID_PIT_INT XEXC_ID_DEC_INT +#endif + +/* -------------------------------------------------------------------- + * Disable the Timer - During Profiling + * + * For PIT Timer - + * 1. XTime_PITDisableInterrupt() ; + * 2. Store the remaining timer clk tick + * 3. Stop the PIT Timer + *-------------------------------------------------------------------- */ + +#ifdef PPC_PIT_INTERRUPT +#define disable_timer() \ + { \ + u32 val; \ + val=mfspr(XREG_SPR_TCR); \ + mtspr(XREG_SPR_TCR, val & (~XREG_TCR_PIT_INTERRUPT_ENABLE)); \ + timer_lo_clk_ticks = mfspr(XREG_SPR_PIT); \ + mtspr(XREG_SPR_PIT, 0); \ + } +#else +#define disable_timer() \ + { \ + u32 addr = (PROFILE_TIMER_BASEADDR) + XTmrCtr_Offsets[(0)] + XTC_TCSR_OFFSET; \ + u32 tmp_v = ProfIo_In32(addr); \ + tmp_v = tmp_v & (~XTC_CSR_ENABLE_TMR_MASK); \ + ProfIo_Out32((PROFILE_TIMER_BASEADDR) + XTmrCtr_Offsets[(0)] + XTC_TCSR_OFFSET, tmp_v); \ + } +#endif + + + +/* -------------------------------------------------------------------- + * Enable the Timer + * + * For PIT Timer - + * 1. Load the remaining timer clk ticks + * 2. XTime_PITEnableInterrupt() ; + *-------------------------------------------------------------------- */ +#ifdef PPC_PIT_INTERRUPT +#define enable_timer() \ + { \ + u32 val; \ + val=mfspr(XREG_SPR_TCR); \ + mtspr(XREG_SPR_PIT, timer_lo_clk_ticks); \ + mtspr(XREG_SPR_TCR, val | XREG_TCR_PIT_INTERRUPT_ENABLE); \ + } +#else +#define enable_timer() \ + { \ + u32 addr = (PROFILE_TIMER_BASEADDR) + XTmrCtr_Offsets[(0)] + XTC_TCSR_OFFSET; \ + u32 tmp_v = ProfIo_In32(addr); \ + tmp_v = tmp_v | XTC_CSR_ENABLE_TMR_MASK; \ + ProfIo_Out32((PROFILE_TIMER_BASEADDR) + XTmrCtr_Offsets[(0)] + XTC_TCSR_OFFSET, tmp_v); \ + } +#endif + + + +/* -------------------------------------------------------------------- + * Send Ack to Timer Interrupt + * + * For PIT Timer - + * 1. Load the timer clk ticks + * 2. Enable AutoReload and Interrupt + * 3. Clear PIT Timer Status bits + *-------------------------------------------------------------------- */ +#ifdef PPC_PIT_INTERRUPT +#define timer_ack() \ + { \ + u32 val; \ + mtspr(XREG_SPR_PIT, timer_clk_ticks); \ + mtspr(XREG_SPR_TSR, XREG_TSR_PIT_INTERRUPT_STATUS); \ + val=mfspr(XREG_SPR_TCR); \ + mtspr(XREG_SPR_TCR, val| XREG_TCR_PIT_INTERRUPT_ENABLE| XREG_TCR_AUTORELOAD_ENABLE); \ + } +#else +#define timer_ack() \ + { \ + u32 csr; \ + csr = ProfTmrCtr_mGetControlStatusReg(PROFILE_TIMER_BASEADDR, 0); \ + ProfTmrCtr_mSetControlStatusReg(PROFILE_TIMER_BASEADDR, 0, csr); \ + } +#endif + +/*-------------------------------------------------------------------- */ +#endif /* PROC_PPC */ +/* -------------------------------------------------------------------- */ + + + + +/* -------------------------------------------------------------------- + * MicroBlaze Target - Timer related functions + *-------------------------------------------------------------------- */ +#ifdef PROC_MICROBLAZE + +/* -------------------------------------------------------------------- + * Disable the Timer during Call-Graph Data collection + * + *-------------------------------------------------------------------- */ +#define disable_timer() \ + { \ + u32 Addr = ((u32)PROFILE_TIMER_BASEADDR); \ + Addr += (u32)XTmrCtr_Offsets[(u16)(0)]; \ + Addr += (u32)XTC_TCSR_OFFSET; \ + u32 tmp_v = ProfIo_In32(Addr); \ + tmp_v = tmp_v & (u32)(~XTC_CSR_ENABLE_TMR_MASK); \ + u32 OutAddr = (u32)PROFILE_TIMER_BASEADDR; \ + OutAddr += (u32)XTmrCtr_Offsets[(u16)(0)]; \ + OutAddr += (u32)XTC_TCSR_OFFSET; \ + ProfIo_Out32(OutAddr, (u32)tmp_v); \ + } + + +/* -------------------------------------------------------------------- + * Enable the Timer after Call-Graph Data collection + * + *-------------------------------------------------------------------- */ +#define enable_timer() \ + { \ + u32 Addr = ((u32)PROFILE_TIMER_BASEADDR); \ + Addr += (u32)XTmrCtr_Offsets[(u16)(0)]; \ + Addr += (u32)XTC_TCSR_OFFSET; \ + u32 tmp_v = (u32)ProfIo_In32(Addr); \ + tmp_v = tmp_v | (u32)XTC_CSR_ENABLE_TMR_MASK; \ + ProfIo_Out32((u32)(PROFILE_TIMER_BASEADDR) + (u32)XTmrCtr_Offsets[(u16)(0)] + (u32)XTC_TCSR_OFFSET, (u32)tmp_v); \ + } + + +/* -------------------------------------------------------------------- + * Send Ack to Timer Interrupt + * + *-------------------------------------------------------------------- */ +#define timer_ack() \ + { \ + u32 csr; \ + csr = ProfTmrCtr_mGetControlStatusReg((u32)PROFILE_TIMER_BASEADDR, (u16)0); \ + ProfTmrCtr_mSetControlStatusReg((u32)PROFILE_TIMER_BASEADDR, (u16)0, (u32)csr); \ + } + +/*-------------------------------------------------------------------- */ +#endif /* PROC_MICROBLAZE */ +/*-------------------------------------------------------------------- */ + +/* -------------------------------------------------------------------- + * Cortex A9 Target - Timer related functions + *-------------------------------------------------------------------- */ +#ifdef PROC_CORTEXA9 + +/* -------------------------------------------------------------------- + * Disable the Timer during Call-Graph Data collection + * + *-------------------------------------------------------------------- */ +#define disable_timer() \ +{ \ + u32 Reg; \ + Reg = Xil_In32(PROFILE_TIMER_BASEADDR + XSCUTIMER_CONTROL_OFFSET); \ + Reg &= (~XSCUTIMER_CONTROL_ENABLE_MASK);\ + Xil_Out32(PROFILE_TIMER_BASEADDR + XSCUTIMER_CONTROL_OFFSET, Reg);\ +} + + +/* -------------------------------------------------------------------- + * Enable the Timer after Call-Graph Data collection + * + *-------------------------------------------------------------------- */ +#define enable_timer() \ +{ \ + u32 Reg; \ + Reg = Xil_In32(PROFILE_TIMER_BASEADDR + XSCUTIMER_CONTROL_OFFSET); \ + Reg |= XSCUTIMER_CONTROL_ENABLE_MASK; \ + Xil_Out32(PROFILE_TIMER_BASEADDR + XSCUTIMER_CONTROL_OFFSET, Reg);\ +} + + +/* -------------------------------------------------------------------- + * Send Ack to Timer Interrupt + * + *-------------------------------------------------------------------- */ +#define timer_ack() \ +{ \ + Xil_Out32((u32)PROFILE_TIMER_BASEADDR + (u32)XSCUTIMER_ISR_OFFSET, \ + (u32)XSCUTIMER_ISR_EVENT_FLAG_MASK);\ +} + +/*-------------------------------------------------------------------- */ +#endif /* PROC_CORTEXA9 */ +/*-------------------------------------------------------------------- */ + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/include/bspconfig.h b/datalink814_ge/bsp/ps7_cortexa9_0/include/bspconfig.h new file mode 100644 index 0000000..daa47a5 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/include/bspconfig.h @@ -0,0 +1,44 @@ + +/******************************************************************* +* +* CAUTION: This file is automatically generated by HSI. +* Version: 2019.1.3 +* DO NOT EDIT. +* +* Copyright (C) 2010-2023 Xilinx, Inc. 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 +*XILINX 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. +* +*Except as contained in this notice, the name of the Xilinx shall not be used +*in advertising or otherwise to promote the sale, use or other dealings in +*this Software without prior written authorization from Xilinx. +* + +* +* Description: Configurations for Standalone BSP +* +*******************************************************************/ + +#ifndef BSPCONFIG_H /* prevent circular inclusions */ +#define BSPCONFIG_H /* by using protection macros */ + +#define MICROBLAZE_PVR_NONE + +/* Definition for hard-float ABI */ +#define FPU_HARD_FLOAT_ABI_ENABLED 1 + +#endif /*end of __BSPCONFIG_H_*/ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/include/frame_uart.h b/datalink814_ge/bsp/ps7_cortexa9_0/include/frame_uart.h new file mode 100644 index 0000000..7c576cf --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/include/frame_uart.h @@ -0,0 +1,128 @@ +/*****************************************************************************/ +/** + * Description: A brief description of this file + * + * Author: Fan Hao + * Date: 2021-12-26 10:59 + * LastEditors: Fan Hao + * LastEditTime: 2022-01-16 21:48 + * Revisions: Rev 0.0 + * History: + * [2021-12-26]: Initial version. + * + * Copyright(c) 2022 Beijing Institute of Technology. + * Lab of Communication and Networking + * + ******************************************************************************/ + +#ifndef FRAME_UART_H +#define FRAME_UART_H + +/****************** Include Files ********************/ +#include +#include +#include + +#define FRAME_UART_PROTOCOL_OVERHEAD_LEN 4 + +#define FRAME_UART_BYTE_PER_REG 4 +// Control register +#define FRAME_UART_SEND_START_OFFSET 0 +#define FRAME_UART_STATUS_OFFSET 4 + +// Data buffer register +#define FRAME_UART_TXBUFF_OFFSET 1024 +#define FRAME_UART_TXBUFF_MAX 1024 +#define FRAME_UART_RXBUFF_OFFSET 2048 +#define FRAME_UART_RXBUFF_MAX 2048 +#define FRAME_UART_RECV_DLEN_OFFSET 0 + +// Status +#define FRAME_UART_RX_BUSY 0x00010000 +#define FRAME_UART_TX_BUSY 0x00000001 + +/**************************** Type Definitions *****************************/ +/** + * + * Write a value to a FRAME_UART register. A 32 bit write is performed. + * If the component is implemented in a smaller width, only the least + * significant data is written. + * + * @param BaseAddress is the base address of the FRAME_UARTdevice. + * @param RegOffset is the register offset from the base to write to. + * @param Data is the data written to the register. + * + * @return None. + * + * @note + * C-style signature: + * void FRAME_UART_mWriteReg(u32 BaseAddress, unsigned RegOffset, u32 Data) + * + */ +#define FRAME_UART_mWriteReg(BaseAddress, RegOffset, Data) \ + Xil_Out32((BaseAddress) + (RegOffset), (u32)(Data)) + +/** + * + * Read a value from a FRAME_UART register. A 32 bit read is performed. + * If the component is implemented in a smaller width, only the least + * significant data is read from the register. The most significant data + * will be read as 0. + * + * @param BaseAddress is the base address of the FRAME_UART device. + * @param RegOffset is the register offset from the base to write to. + * + * @return Data is the data from the register. + * + * @note + * C-style signature: + * u32 FRAME_UART_mReadReg(u32 BaseAddress, unsigned RegOffset) + * + */ +#define FRAME_UART_mReadReg(BaseAddress, RegOffset) \ + Xil_In32((BaseAddress) + (RegOffset)) + +/************************** Function Prototypes ****************************/ +/** + * + * Run a self-test on the driver/device. Note this may be a destructive test if + * resets of the device are performed. + * + * If the hardware system is not built correctly, this function may never + * return to the caller. + * + * @param baseaddr_p is the base address of the FRAME_UART instance to be worked on. + * + * @return + * + * - XST_SUCCESS if all self-test code passed + * - XST_FAILURE if any self-test code failed + * + * @note Caching must be turned off for this function to work. + * @note Self test may fail if data memory and device are not on the same bus. + * + */ + +/************************** Data Type Definitions ****************************/ +typedef struct { + u32 BaseAddr; + u32 TxOffset; + u32 RxOffset; +} FrameUart; + +/************************** Function Prototypes ******************************/ +// Instance initial +int FrameUart_Init(FrameUart* InstPtr, u32 BaseAddr); + +// Send a system bus frame. +int FrameUart_Send(FrameUart* InstPtr, u8* DataBuff, u32 DataLenByte); + +// Get last system bus frame. +int FrameUart_Recv(FrameUart* InstPtr, u8* DataBuff); + +// Get system bus rx channel status. +bool FrameUart_IsRxBusy(FrameUart* InstPtr); + +// Get system bus tx channel status. +bool FrameUart_IsTxBusy(FrameUart* InstPtr); +#endif // FRAME_UART_H diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/include/mblaze_nt_types.h b/datalink814_ge/bsp/ps7_cortexa9_0/include/mblaze_nt_types.h new file mode 100644 index 0000000..807dda3 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/include/mblaze_nt_types.h @@ -0,0 +1,50 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + + +#ifndef _MBLAZE_NT_TYPES_H +#define _MBLAZE_NT_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef char byte; +typedef short half; +typedef int word; +typedef unsigned char ubyte; +typedef unsigned short uhalf; +typedef unsigned int uword; +typedef ubyte boolean; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/include/profile.h b/datalink814_ge/bsp/ps7_cortexa9_0/include/profile.h new file mode 100644 index 0000000..63f503a --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/include/profile.h @@ -0,0 +1,127 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +#ifndef PROFILE_H +#define PROFILE_H 1 + +#include +#include "xil_types.h" +#include "profile_config.h" + +#ifdef PROC_MICROBLAZE +#include "mblaze_nt_types.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +void _system_init( void ) ; +void _system_clean( void ) ; +void mcount(u32 frompc, u32 selfpc); +void profile_intr_handler( void ) ; +void _profile_init( void ); + + + +/**************************************************************************** + * Profiling on hardware - Hash table maintained on hardware and data sent + * to xmd for gmon.out generation. + ****************************************************************************/ +/* + * histogram counters are unsigned shorts (according to the kernel). + */ +#define HISTCOUNTER u16 + +struct tostruct { + u32 selfpc; + s32 count; + s16 link; + u16 pad; +}; + +struct fromstruct { + u32 frompc ; + s16 link ; + u16 pad ; +} ; + +/* + * general rounding functions. + */ +#define ROUNDDOWN(x,y) (((x)/(y))*(y)) +#define ROUNDUP(x,y) ((((x)+(y)-1)/(y))*(y)) + +/* + * The profiling data structures are housed in this structure. + */ +struct gmonparam { + s32 state; + + /* Histogram Information */ + u16 *kcount; /* No. of bins in histogram */ + u32 kcountsize; /* Histogram samples */ + + /* Call-graph Information */ + struct fromstruct *froms; + u32 fromssize; + struct tostruct *tos; + u32 tossize; + + /* Initialization I/Ps */ + u32 lowpc; + u32 highpc; + u32 textsize; + /* u32 cg_froms, */ + /* u32 cg_tos, */ +}; +extern struct gmonparam *_gmonparam; +extern s32 n_gmon_sections; + +/* + * Possible states of profiling. + */ +#define GMON_PROF_ON 0 +#define GMON_PROF_BUSY 1 +#define GMON_PROF_ERROR 2 +#define GMON_PROF_OFF 3 + +/* + * Sysctl definitions for extracting profiling information from the kernel. + */ +#define GPROF_STATE 0 /* int: profiling enabling variable */ +#define GPROF_COUNT 1 /* struct: profile tick count buffer */ +#define GPROF_FROMS 2 /* struct: from location hash bucket */ +#define GPROF_TOS 3 /* struct: destination/count structure */ +#define GPROF_GMONPARAM 4 /* struct: profiling parameters (see above) */ + +#ifdef __cplusplus +} +#endif + +#endif /* PROFILE_H */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/include/sleep.h b/datalink814_ge/bsp/ps7_cortexa9_0/include/sleep.h new file mode 100644 index 0000000..f3a632b --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/include/sleep.h @@ -0,0 +1,115 @@ +/****************************************************************************** +* +* Copyright (C) 2014 - 2017 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +/*****************************************************************************/ +/** +* @file sleep.h +* +* This header file contains ARM Cortex A53,A9,R5,Microblaze specific sleep +* related APIs. +* +*
+* MODIFICATION HISTORY :
+*
+* Ver   Who  Date	 Changes
+* ----- ---- -------- -------------------------------------------------------
+* 6.6   srm  11/02/17 Added processor specific sleep rountines
+*								 function prototypes.
+*
+* 
+* +******************************************************************************/ + +#ifndef SLEEP_H +#define SLEEP_H + +#include "xil_types.h" +#include "xil_io.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*****************************************************************************/ +/** +* +* This macro polls an address periodically until a condition is met or till the +* timeout occurs. +* The minimum timeout for calling this macro is 100us. If the timeout is less +* than 100us, it still waits for 100us. Also the unit for the timeout is 100us. +* If the timeout is not a multiple of 100us, it waits for a timeout of +* the next usec value which is a multiple of 100us. +* +* @param IO_func - accessor function to read the register contents. +* Depends on the register width. +* @param ADDR - Address to be polled +* @param VALUE - variable to read the value +* @param COND - Condition to checked (usually involves VALUE) +* @param TIMEOUT_US - timeout in micro seconds +* +* @return 0 - when the condition is met +* -1 - when the condition is not met till the timeout period +* +* @note none +* +*****************************************************************************/ +#define Xil_poll_timeout(IO_func, ADDR, VALUE, COND, TIMEOUT_US) \ + ( { \ + u64 timeout = TIMEOUT_US/100; \ + if(TIMEOUT_US%100!=0) \ + timeout++; \ + for(;;) { \ + VALUE = IO_func(ADDR); \ + if(COND) \ + break; \ + else { \ + usleep(100); \ + timeout--; \ + if(timeout==0) \ + break; \ + } \ + } \ + (timeout>0) ? 0 : -1; \ + } ) + +void usleep(unsigned long useconds); +void sleep(unsigned int seconds); +int usleep_R5(unsigned long useconds); +unsigned sleep_R5(unsigned int seconds); +int usleep_MB(unsigned long useconds); +unsigned sleep_MB(unsigned int seconds); +int usleep_A53(unsigned long useconds); +unsigned sleep_A53(unsigned int seconds); +int usleep_A9(unsigned long useconds); +unsigned sleep_A9(unsigned int seconds); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/include/smc.h b/datalink814_ge/bsp/ps7_cortexa9_0/include/smc.h new file mode 100644 index 0000000..f7cc91c --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/include/smc.h @@ -0,0 +1,110 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file smc.h +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- ---------------------------------------------------
+* 1.00a sdm  11/03/09 Initial release.
+* 4.2	pkp	 08/04/14 Removed function definition of XSmc_NorInit and XSmc_NorInit
+*					  as smc.c is removed
+* 
+* +* @note None. +* +******************************************************************************/ + +#ifndef SMC_H /* prevent circular inclusions */ +#define SMC_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xparameters.h" +#include "xil_io.h" + +/***************** Macros (Inline Functions) Definitions *********************/ + +/**************************** Type Definitions *******************************/ + +/************************** Constant Definitions *****************************/ + +/* Memory controller configuration register offset */ +#define XSMCPSS_MC_STATUS 0x000U /* Controller status reg, RO */ +#define XSMCPSS_MC_INTERFACE_CONFIG 0x004U /* Interface config reg, RO */ +#define XSMCPSS_MC_SET_CONFIG 0x008U /* Set configuration reg, WO */ +#define XSMCPSS_MC_CLR_CONFIG 0x00CU /* Clear config reg, WO */ +#define XSMCPSS_MC_DIRECT_CMD 0x010U /* Direct command reg, WO */ +#define XSMCPSS_MC_SET_CYCLES 0x014U /* Set cycles register, WO */ +#define XSMCPSS_MC_SET_OPMODE 0x018U /* Set opmode register, WO */ +#define XSMCPSS_MC_REFRESH_PERIOD_0 0x020U /* Refresh period_0 reg, RW */ +#define XSMCPSS_MC_REFRESH_PERIOD_1 0x024U /* Refresh period_1 reg, RW */ + +/* Chip select configuration register offset */ +#define XSMCPSS_CS_IF0_CHIP_0_OFFSET 0x100U /* Interface 0 chip 0 config */ +#define XSMCPSS_CS_IF0_CHIP_1_OFFSET 0x120U /* Interface 0 chip 1 config */ +#define XSMCPSS_CS_IF0_CHIP_2_OFFSET 0x140U /* Interface 0 chip 2 config */ +#define XSMCPSS_CS_IF0_CHIP_3_OFFSET 0x160U /* Interface 0 chip 3 config */ +#define XSMCPSS_CS_IF1_CHIP_0_OFFSET 0x180U /* Interface 1 chip 0 config */ +#define XSMCPSS_CS_IF1_CHIP_1_OFFSET 0x1A0U /* Interface 1 chip 1 config */ +#define XSMCPSS_CS_IF1_CHIP_2_OFFSET 0x1C0U /* Interface 1 chip 2 config */ +#define XSMCPSS_CS_IF1_CHIP_3_OFFSET 0x1E0U /* Interface 1 chip 3 config */ + +/* User configuration register offset */ +#define XSMCPSS_UC_STATUS_OFFSET 0x200U /* User status reg, RO */ +#define XSMCPSS_UC_CONFIG_OFFSET 0x204U /* User config reg, WO */ + +/* Integration test register offset */ +#define XSMCPSS_IT_OFFSET 0xE00U + +/* ID configuration register offset */ +#define XSMCPSS_ID_PERIP_0_OFFSET 0xFE0U +#define XSMCPSS_ID_PERIP_1_OFFSET 0xFE4U +#define XSMCPSS_ID_PERIP_2_OFFSET 0xFE8U +#define XSMCPSS_ID_PERIP_3_OFFSET 0xFECU +#define XSMCPSS_ID_PCELL_0_OFFSET 0xFF0U +#define XSMCPSS_ID_PCELL_1_OFFSET 0xFF4U +#define XSMCPSS_ID_PCELL_2_OFFSET 0xFF8U +#define XSMCPSS_ID_PCELL_3_OFFSET 0xFFCU + +/************************** Variable Definitions *****************************/ + +/************************** Function Prototypes ******************************/ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* SMC_H */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/include/vectors.h b/datalink814_ge/bsp/ps7_cortexa9_0/include/vectors.h new file mode 100644 index 0000000..56bacbc --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/include/vectors.h @@ -0,0 +1,84 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2016 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file vectors.h +* +* This file contains the C level vector prototypes for the ARM Cortex A9 core. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- ---------------------------------------------------
+* 1.00a ecm  10/20/10 Initial version, moved over from bsp area
+* 6.0   mus  07/27/16 Consolidated vectors for a9,a53 and r5 processors
+* 
+* +* @note +* +* None. +* +******************************************************************************/ + +#ifndef _VECTORS_H_ +#define _VECTORS_H_ + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" + +#ifdef __cplusplus +extern "C" { +#endif +/***************** Macros (Inline Functions) Definitions *********************/ + +/**************************** Type Definitions *******************************/ + +/************************** Constant Definitions *****************************/ + +/************************** Function Prototypes ******************************/ + +void FIQInterrupt(void); +void IRQInterrupt(void); +#if !defined (__aarch64__) +void SWInterrupt(void); +void DataAbortInterrupt(void); +void PrefetchAbortInterrupt(void); +void UndefinedException(void); +#else +void SynchronousInterrupt(void); +void SErrorInterrupt(void); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* protection macro */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/include/xadcps.h b/datalink814_ge/bsp/ps7_cortexa9_0/include/xadcps.h new file mode 100644 index 0000000..900edf0 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/include/xadcps.h @@ -0,0 +1,589 @@ +/****************************************************************************** +* +* Copyright (C) 2011 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xadcps.h +* @addtogroup xadcps_v2_3 +* @{ +* @details +* +* The XAdcPs driver supports the Xilinx XADC/ADC device. +* +* The XADC/ADC device has the following features: +* - 10-bit, 200-KSPS (kilo samples per second) +* Analog-to-Digital Converter (ADC) +* - Monitoring of on-chip supply voltages and temperature +* - 1 dedicated differential analog-input pair and +* 16 auxiliary differential analog-input pairs +* - Automatic alarms based on user defined limits for the on-chip +* supply voltages and temperature +* - Automatic Channel Sequencer, programmable averaging, programmable +* acquisition time for the external inputs, unipolar or differential +* input selection for the external inputs +* - Inbuilt Calibration +* - Optional interrupt request generation +* +* +* The user should refer to the hardware device specification for detailed +* information about the device. +* +* This header file contains the prototypes of driver functions that can +* be used to access the XADC/ADC device. +* +* +* XADC Channel Sequencer Modes +* +* The XADC Channel Sequencer supports the following operating modes: +* +* - Default : This is the default mode after power up. +* In this mode of operation the XADC operates in +* a sequence mode, monitoring the on chip sensors: +* Temperature, VCCINT, and VCCAUX. +* - One pass through sequence : In this mode the XADC +* converts the channels enabled in the Sequencer Channel Enable +* registers for a single pass and then stops. +* - Continuous cycling of sequence : In this mode the XADC +* converts the channels enabled in the Sequencer Channel Enable +* registers continuously. +* - Single channel mode: In this mode the XADC Channel +* Sequencer is disabled and the XADC operates in a +* Single Channel Mode. +* The XADC can operate either in a Continuous or Event +* driven sampling mode in the single channel mode. +* - Simultaneous Sampling Mode: In this mode the XADC Channel +* Sequencer will automatically sequence through eight fixed pairs +* of auxiliary analog input channels for simulataneous conversion. +* - Independent ADC mode: In this mode the first ADC (A) is used to +* is used to implement a fixed monitoring mode similar to the +* default mode but the alarm fucntions ar eenabled. +* The second ADC (B) is available to be used with external analog +* input channels only. +* +* Read the XADC spec for more information about the sequencer modes. +* +* Initialization and Configuration +* +* The device driver enables higher layer software (e.g., an application) to +* communicate to the XADC/ADC device. +* +* XAdcPs_CfgInitialize() API is used to initialize the XADC/ADC +* device. The user needs to first call the XAdcPs_LookupConfig() API which +* returns the Configuration structure pointer which is passed as a parameter to +* the XAdcPs_CfgInitialize() API. +* +* +* Interrupts +* +* The XADC/ADC device supports interrupt driven mode and the default +* operation mode is polling mode. +* +* The interrupt mode is available only if hardware is configured to support +* interrupts. +* +* This driver does not provide a Interrupt Service Routine (ISR) for the device. +* It is the responsibility of the application to provide one if needed. Refer to +* the interrupt example provided with this driver for details on using the +* device in interrupt mode. +* +* +* Virtual Memory +* +* This driver supports Virtual Memory. The RTOS is responsible for calculating +* the correct device base address in Virtual Memory space. +* +* +* Threads +* +* This driver is not thread safe. Any needs for threads or thread mutual +* exclusion must be satisfied by the layer above this driver. +* +* +* Asserts +* +* Asserts are used within all Xilinx drivers to enforce constraints on argument +* values. Asserts can be turned off on a system-wide basis by defining, at +* compile time, the NDEBUG identifier. By default, asserts are turned on and it +* is recommended that users leave asserts on during development. +* +* +* Building the driver +* +* The XAdcPs driver is composed of several source files. This allows the user +* to build and link only those parts of the driver that are necessary. +* +* Limitations of the driver +* +* XADC/ADC device can be accessed through the JTAG port and the PLB +* interface. The driver implementation does not support the simultaneous access +* of the device by both these interfaces. The user has to care of this situation +* in the user application code. +* +*

+* +*
+*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- -----  -------- -----------------------------------------------------
+* 1.00a ssb    12/22/11 First release based on the XPS/AXI xadc driver
+* 1.01a bss    02/18/13	Modified XAdcPs_SetSeqChEnables,XAdcPs_SetSeqAvgEnables
+*			XAdcPs_SetSeqInputMode and XAdcPs_SetSeqAcqTime APIs
+*			in xadcps.c to fix CR #693371
+* 1.03a bss    11/01/13 Modified xadcps_hw.h to use correct Register offsets
+*			CR#749687
+* 2.1   bss    08/05/14 Added declarations for XAdcPs_SetSequencerEvent,
+*			XAdcPs_GetSamplingMode, XAdcPs_SetMuxMode,
+*			XAdcPs_SetPowerdownMode and XAdcPs_GetPowerdownMode
+*			functions.
+*			Modified Assert for XAdcPs_SetSingleChParams in
+*			xadcps.c to fix CR #807563.
+* 2.2   bss    04/27/14 Modified to use correct Device Config base address in
+*						xadcps.c (CR#854437).
+*       ms     01/23/17 Added xil_printf statement in main function for all
+*                       examples to ensure that "Successfully ran" and "Failed"
+*                       strings are available in all examples. This is a fix
+*                       for CR-965028.
+*       ms     03/17/17 Added readme.txt file in examples folder for doxygen
+*                       generation.
+*       ms     04/05/17 Modified Comment lines in functions of xadcps
+*                       examples to recognize it as documentation block
+*                       for doxygen generation.
+* 2.3   mn     07/09/18 Fix Doxygen warning
+*
+* 
+* +*****************************************************************************/ +#ifndef XADCPS_H /* Prevent circular inclusions */ +#define XADCPS_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files ********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xstatus.h" +#include "xadcps_hw.h" + +/************************** Constant Definitions ****************************/ + + +/** + * @name Indexes for the different channels. + * @{ + */ +#define XADCPS_CH_TEMP 0x0 /**< On Chip Temperature */ +#define XADCPS_CH_VCCINT 0x1 /**< VCCINT */ +#define XADCPS_CH_VCCAUX 0x2 /**< VCCAUX */ +#define XADCPS_CH_VPVN 0x3 /**< VP/VN Dedicated analog inputs */ +#define XADCPS_CH_VREFP 0x4 /**< VREFP */ +#define XADCPS_CH_VREFN 0x5 /**< VREFN */ +#define XADCPS_CH_VBRAM 0x6 /**< On-chip VBRAM Data Reg, 7 series */ +#define XADCPS_CH_SUPPLY_CALIB 0x07 /**< Supply Calib Data Reg */ +#define XADCPS_CH_ADC_CALIB 0x08 /**< ADC Offset Channel Reg */ +#define XADCPS_CH_GAINERR_CALIB 0x09 /**< Gain Error Channel Reg */ +#define XADCPS_CH_VCCPINT 0x0D /**< On-chip PS VCCPINT Channel , Zynq */ +#define XADCPS_CH_VCCPAUX 0x0E /**< On-chip PS VCCPAUX Channel , Zynq */ +#define XADCPS_CH_VCCPDRO 0x0F /**< On-chip PS VCCPDRO Channel , Zynq */ +#define XADCPS_CH_AUX_MIN 16 /**< Channel number for 1st Aux Channel */ +#define XADCPS_CH_AUX_MAX 31 /**< Channel number for Last Aux channel */ + +/*@}*/ + + +/** + * @name Indexes for reading the Calibration Coefficient Data. + * @{ + */ +#define XADCPS_CALIB_SUPPLY_COEFF 0 /**< Supply Offset Calib Coefficient */ +#define XADCPS_CALIB_ADC_COEFF 1 /**< ADC Offset Calib Coefficient */ +#define XADCPS_CALIB_GAIN_ERROR_COEFF 2 /**< Gain Error Calib Coefficient*/ +/*@}*/ + + +/** + * @name Indexes for reading the Minimum/Maximum Measurement Data. + * @{ + */ +#define XADCPS_MAX_TEMP 0 /**< Maximum Temperature Data */ +#define XADCPS_MAX_VCCINT 1 /**< Maximum VCCINT Data */ +#define XADCPS_MAX_VCCAUX 2 /**< Maximum VCCAUX Data */ +#define XADCPS_MAX_VBRAM 3 /**< Maximum VBRAM Data */ +#define XADCPS_MIN_TEMP 4 /**< Minimum Temperature Data */ +#define XADCPS_MIN_VCCINT 5 /**< Minimum VCCINT Data */ +#define XADCPS_MIN_VCCAUX 6 /**< Minimum VCCAUX Data */ +#define XADCPS_MIN_VBRAM 7 /**< Minimum VBRAM Data */ +#define XADCPS_MAX_VCCPINT 8 /**< Maximum VCCPINT Register , Zynq */ +#define XADCPS_MAX_VCCPAUX 9 /**< Maximum VCCPAUX Register , Zynq */ +#define XADCPS_MAX_VCCPDRO 0xA /**< Maximum VCCPDRO Register , Zynq */ +#define XADCPS_MIN_VCCPINT 0xC /**< Minimum VCCPINT Register , Zynq */ +#define XADCPS_MIN_VCCPAUX 0xD /**< Minimum VCCPAUX Register , Zynq */ +#define XADCPS_MIN_VCCPDRO 0xE /**< Minimum VCCPDRO Register , Zynq */ + +/*@}*/ + + +/** + * @name Alarm Threshold(Limit) Register (ATR) indexes. + * @{ + */ +#define XADCPS_ATR_TEMP_UPPER 0 /**< High user Temperature */ +#define XADCPS_ATR_VCCINT_UPPER 1 /**< VCCINT high voltage limit register */ +#define XADCPS_ATR_VCCAUX_UPPER 2 /**< VCCAUX high voltage limit register */ +#define XADCPS_ATR_OT_UPPER 3 /**< VCCAUX high voltage limit register */ +#define XADCPS_ATR_TEMP_LOWER 4 /**< Upper Over Temperature limit Reg */ +#define XADCPS_ATR_VCCINT_LOWER 5 /**< VCCINT high voltage limit register */ +#define XADCPS_ATR_VCCAUX_LOWER 6 /**< VCCAUX low voltage limit register */ +#define XADCPS_ATR_OT_LOWER 7 /**< Lower Over Temperature limit */ +#define XADCPS_ATR_VBRAM_UPPER_ 8 /**< VRBAM Upper Alarm Reg, 7 Series */ +#define XADCPS_ATR_VCCPINT_UPPER 9 /**< VCCPINT Upper Alarm Reg, Zynq */ +#define XADCPS_ATR_VCCPAUX_UPPER 0xA /**< VCCPAUX Upper Alarm Reg, Zynq */ +#define XADCPS_ATR_VCCPDRO_UPPER 0xB /**< VCCPDRO Upper Alarm Reg, Zynq */ +#define XADCPS_ATR_VBRAM_LOWER 0xC /**< VRBAM Lower Alarm Reg, 7 Series */ +#define XADCPS_ATR_VCCPINT_LOWER 0xD /**< VCCPINT Lower Alarm Reg , Zynq */ +#define XADCPS_ATR_VCCPAUX_LOWER 0xE /**< VCCPAUX Lower Alarm Reg , Zynq */ +#define XADCPS_ATR_VCCPDRO_LOWER 0xF /**< VCCPDRO Lower Alarm Reg , Zynq */ + +/*@}*/ + + +/** + * @name Averaging to be done for the channels. + * @{ + */ +#define XADCPS_AVG_0_SAMPLES 0 /**< No Averaging */ +#define XADCPS_AVG_16_SAMPLES 1 /**< Average 16 samples */ +#define XADCPS_AVG_64_SAMPLES 2 /**< Average 64 samples */ +#define XADCPS_AVG_256_SAMPLES 3 /**< Average 256 samples */ + +/*@}*/ + + +/** + * @name Channel Sequencer Modes of operation + * @{ + */ +#define XADCPS_SEQ_MODE_SAFE 0 /**< Default Safe Mode */ +#define XADCPS_SEQ_MODE_ONEPASS 1 /**< Onepass through Sequencer */ +#define XADCPS_SEQ_MODE_CONTINPASS 2 /**< Continuous Cycling Sequencer */ +#define XADCPS_SEQ_MODE_SINGCHAN 3 /**< Single channel -No Sequencing */ +#define XADCPS_SEQ_MODE_SIMUL_SAMPLING 4 /**< Simultaneous sampling */ +#define XADCPS_SEQ_MODE_INDEPENDENT 8 /**< Independent mode */ + +/*@}*/ + + + +/** + * @name Power Down Modes + * @{ + */ +#define XADCPS_PD_MODE_NONE 0 /**< No Power Down */ +#define XADCPS_PD_MODE_ADCB 1 /**< Power Down ADC B */ +#define XADCPS_PD_MODE_XADC 2 /**< Power Down ADC A and ADC B */ +/*@}*/ + +/**************************** Type Definitions ******************************/ + +/** + * This typedef contains configuration information for the XADC/ADC + * device. + */ +typedef struct { + u16 DeviceId; /**< Unique ID of device */ + u32 BaseAddress; /**< Device base address */ +} XAdcPs_Config; + + +/** + * The driver's instance data. The user is required to allocate a variable + * of this type for every XADC/ADC device in the system. A pointer to + * a variable of this type is then passed to the driver API functions. + */ +typedef struct { + XAdcPs_Config Config; /**< XAdcPs_Config of current device */ + u32 IsReady; /**< Device is initialized and ready */ + +} XAdcPs; + +/***************** Macros (Inline Functions) Definitions ********************/ + +/****************************************************************************/ +/** +* +* This macro checks if the XADC device is in Event Sampling mode. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @return +* - TRUE if the device is in Event Sampling Mode. +* - FALSE if the device is in Continuous Sampling Mode. +* +* @note C-Style signature: +* int XAdcPs_IsEventSamplingMode(XAdcPs *InstancePtr); +* +*****************************************************************************/ +#define XAdcPs_IsEventSamplingModeSet(InstancePtr) \ + (((XAdcPs_ReadInternalReg(InstancePtr, \ + XADCPS_CFR0_OFFSET) & XADCPS_CFR0_EC_MASK) ? \ + TRUE : FALSE)) + + +/****************************************************************************/ +/** +* +* This macro checks if the XADC device is in External Mux mode. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @return +* - TRUE if the device is in External Mux Mode. +* - FALSE if the device is NOT in External Mux Mode. +* +* @note C-Style signature: +* int XAdcPs_IsExternalMuxMode(XAdcPs *InstancePtr); +* +*****************************************************************************/ +#define XAdcPs_IsExternalMuxModeSet(InstancePtr) \ + (((XAdcPs_ReadInternalReg(InstancePtr, \ + XADCPS_CFR0_OFFSET) & XADCPS_CFR0_MUX_MASK) ? \ + TRUE : FALSE)) + +/****************************************************************************/ +/** +* +* This macro converts XADC Raw Data to Temperature(centigrades). +* +* @param AdcData is the Raw ADC Data from XADC. +* +* @return The Temperature in centigrades. +* +* @note C-Style signature: +* float XAdcPs_RawToTemperature(u32 AdcData); +* +*****************************************************************************/ +#define XAdcPs_RawToTemperature(AdcData) \ + ((((float)(AdcData)/65536.0f)/0.00198421639f ) - 273.15f) + +/****************************************************************************/ +/** +* +* This macro converts XADC/ADC Raw Data to Voltage(volts). +* +* @param AdcData is the XADC/ADC Raw Data. +* +* @return The Voltage in volts. +* +* @note C-Style signature: +* float XAdcPs_RawToVoltage(u32 AdcData); +* +*****************************************************************************/ +#define XAdcPs_RawToVoltage(AdcData) \ + ((((float)(AdcData))* (3.0f))/65536.0f) + +/****************************************************************************/ +/** +* +* This macro converts Temperature in centigrades to XADC/ADC Raw Data. +* +* @param Temperature is the Temperature in centigrades to be +* converted to XADC/ADC Raw Data. +* +* @return The XADC/ADC Raw Data. +* +* @note C-Style signature: +* int XAdcPs_TemperatureToRaw(float Temperature); +* +*****************************************************************************/ +#define XAdcPs_TemperatureToRaw(Temperature) \ + ((int)(((Temperature) + 273.15f)*65536.0f*0.00198421639f)) + +/****************************************************************************/ +/** +* +* This macro converts Voltage in Volts to XADC/ADC Raw Data. +* +* @param Voltage is the Voltage in volts to be converted to +* XADC/ADC Raw Data. +* +* @return The XADC/ADC Raw Data. +* +* @note C-Style signature: +* int XAdcPs_VoltageToRaw(float Voltage); +* +*****************************************************************************/ +#define XAdcPs_VoltageToRaw(Voltage) \ + ((int)((Voltage)*65536.0f/3.0f)) + + +/****************************************************************************/ +/** +* +* This macro is used for writing to the XADC Registers using the +* command FIFO. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param Data is the value to be written to XADC register. +* +* @return None. +* +* @note C-Style signature: +* void XAdcPs_WriteFifo(XAdcPs *InstancePtr, u32 Data); +* +*****************************************************************************/ +#define XAdcPs_WriteFifo(InstancePtr, Data) \ + XAdcPs_WriteReg((InstancePtr)->Config.BaseAddress, \ + XADCPS_CMDFIFO_OFFSET, Data); + + +/****************************************************************************/ +/** +* +* This macro is used for reading from the XADC Registers using the +* data FIFO. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @return Data read from the FIFO +* +* @note C-Style signature: +* u32 XAdcPs_ReadFifo(XAdcPs *InstancePtr); +* +*****************************************************************************/ +#define XAdcPs_ReadFifo(InstancePtr) \ + XAdcPs_ReadReg((InstancePtr)->Config.BaseAddress, \ + XADCPS_RDFIFO_OFFSET); + + +/************************** Function Prototypes *****************************/ + + + +/** + * Functions in xadcps_sinit.c + */ +XAdcPs_Config *XAdcPs_LookupConfig(u16 DeviceId); + +/** + * Functions in xadcps.c + */ +int XAdcPs_CfgInitialize(XAdcPs *InstancePtr, + XAdcPs_Config *ConfigPtr, + u32 EffectiveAddr); + + +u32 XAdcPs_GetStatus(XAdcPs *InstancePtr); + +u32 XAdcPs_GetAlarmOutputStatus(XAdcPs *InstancePtr); + +void XAdcPs_StartAdcConversion(XAdcPs *InstancePtr); + +void XAdcPs_Reset(XAdcPs *InstancePtr); + +u16 XAdcPs_GetAdcData(XAdcPs *InstancePtr, u8 Channel); + +u16 XAdcPs_GetCalibCoefficient(XAdcPs *InstancePtr, u8 CoeffType); + +u16 XAdcPs_GetMinMaxMeasurement(XAdcPs *InstancePtr, u8 MeasurementType); + +void XAdcPs_SetAvg(XAdcPs *InstancePtr, u8 Average); +u8 XAdcPs_GetAvg(XAdcPs *InstancePtr); + +int XAdcPs_SetSingleChParams(XAdcPs *InstancePtr, + u8 Channel, + int IncreaseAcqCycles, + int IsEventMode, + int IsDifferentialMode); + + +void XAdcPs_SetAlarmEnables(XAdcPs *InstancePtr, u16 AlmEnableMask); +u16 XAdcPs_GetAlarmEnables(XAdcPs *InstancePtr); + +void XAdcPs_SetCalibEnables(XAdcPs *InstancePtr, u16 Calibration); +u16 XAdcPs_GetCalibEnables(XAdcPs *InstancePtr); + +void XAdcPs_SetSequencerMode(XAdcPs *InstancePtr, u8 SequencerMode); +u8 XAdcPs_GetSequencerMode(XAdcPs *InstancePtr); + +void XAdcPs_SetAdcClkDivisor(XAdcPs *InstancePtr, u8 Divisor); +u8 XAdcPs_GetAdcClkDivisor(XAdcPs *InstancePtr); + +int XAdcPs_SetSeqChEnables(XAdcPs *InstancePtr, u32 ChEnableMask); +u32 XAdcPs_GetSeqChEnables(XAdcPs *InstancePtr); + +int XAdcPs_SetSeqAvgEnables(XAdcPs *InstancePtr, u32 AvgEnableChMask); +u32 XAdcPs_GetSeqAvgEnables(XAdcPs *InstancePtr); + +int XAdcPs_SetSeqInputMode(XAdcPs *InstancePtr, u32 InputModeChMask); +u32 XAdcPs_GetSeqInputMode(XAdcPs *InstancePtr); + +int XAdcPs_SetSeqAcqTime(XAdcPs *InstancePtr, u32 AcqCyclesChMask); +u32 XAdcPs_GetSeqAcqTime(XAdcPs *InstancePtr); + +void XAdcPs_SetAlarmThreshold(XAdcPs *InstancePtr, u8 AlarmThrReg, u16 Value); +u16 XAdcPs_GetAlarmThreshold(XAdcPs *InstancePtr, u8 AlarmThrReg); + +void XAdcPs_EnableUserOverTemp(XAdcPs *InstancePtr); +void XAdcPs_DisableUserOverTemp(XAdcPs *InstancePtr); + +void XAdcPs_SetSequencerEvent(XAdcPs *InstancePtr, int IsEventMode); + +int XAdcPs_GetSamplingMode(XAdcPs *InstancePtr); + +void XAdcPs_SetMuxMode(XAdcPs *InstancePtr, int MuxMode, u8 Channel); + +void XAdcPs_SetPowerdownMode(XAdcPs *InstancePtr, u32 Mode); + +u32 XAdcPs_GetPowerdownMode(XAdcPs *InstancePtr); + +/** + * Functions in xadcps_selftest.c + */ +int XAdcPs_SelfTest(XAdcPs *InstancePtr); + +/** + * Functions in xadcps_intr.c + */ +void XAdcPs_IntrEnable(XAdcPs *InstancePtr, u32 Mask); +void XAdcPs_IntrDisable(XAdcPs *InstancePtr, u32 Mask); +u32 XAdcPs_IntrGetEnabled(XAdcPs *InstancePtr); + +u32 XAdcPs_IntrGetStatus(XAdcPs *InstancePtr); +void XAdcPs_IntrClear(XAdcPs *InstancePtr, u32 Mask); + + +#ifdef __cplusplus +} +#endif + +#endif /* End of protection macro. */ +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/include/xadcps_hw.h b/datalink814_ge/bsp/ps7_cortexa9_0/include/xadcps_hw.h new file mode 100644 index 0000000..dd51473 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/include/xadcps_hw.h @@ -0,0 +1,498 @@ +/****************************************************************************** +* +* Copyright (C) 2011 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xadcps_hw.h +* @addtogroup xadcps_v2_3 +* @{ +* +* This header file contains identifiers and basic driver functions (or +* macros) that can be used to access the XADC device through the Device +* Config Interface of the Zynq. +* +* +* Refer to the device specification for more information about this driver. +* +* @note None. +* +* +*
+*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- -----  -------- -----------------------------------------------------
+* 1.00a bss    12/22/11 First release based on the XPS/AXI xadc driver
+* 1.03a bss    11/01/13 Modified macros to use correct Register offsets
+*			CR#749687
+*
+* 
+* +*****************************************************************************/ +#ifndef XADCPS_HW_H /* Prevent circular inclusions */ +#define XADCPS_HW_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files ********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_io.h" + +/************************** Constant Definitions ****************************/ + + +/**@name Register offsets of XADC in the Device Config + * + * The following constants provide access to each of the registers of the + * XADC device. + * @{ + */ + +#define XADCPS_CFG_OFFSET 0x00 /**< Configuration Register */ +#define XADCPS_INT_STS_OFFSET 0x04 /**< Interrupt Status Register */ +#define XADCPS_INT_MASK_OFFSET 0x08 /**< Interrupt Mask Register */ +#define XADCPS_MSTS_OFFSET 0x0C /**< Misc status register */ +#define XADCPS_CMDFIFO_OFFSET 0x10 /**< Command FIFO Register */ +#define XADCPS_RDFIFO_OFFSET 0x14 /**< Read FIFO Register */ +#define XADCPS_MCTL_OFFSET 0x18 /**< Misc control register */ + +/* @} */ + + + + + +/** @name XADC Config Register Bit definitions + * @{ + */ +#define XADCPS_CFG_ENABLE_MASK 0x80000000 /**< Enable access from PS mask */ +#define XADCPS_CFG_CFIFOTH_MASK 0x00F00000 /**< Command FIFO Threshold mask */ +#define XADCPS_CFG_DFIFOTH_MASK 0x000F0000 /**< Data FIFO Threshold mask */ +#define XADCPS_CFG_WEDGE_MASK 0x00002000 /**< Write Edge Mask */ +#define XADCPS_CFG_REDGE_MASK 0x00001000 /**< Read Edge Mask */ +#define XADCPS_CFG_TCKRATE_MASK 0x00000300 /**< Clock freq control */ +#define XADCPS_CFG_IGAP_MASK 0x0000001F /**< Idle Gap between + * successive commands */ +/* @} */ + + +/** @name XADC Interrupt Status/Mask Register Bit definitions + * + * The definitions are same for the Interrupt Status Register and + * Interrupt Mask Register. They are defined only once. + * @{ + */ +#define XADCPS_INTX_ALL_MASK 0x000003FF /**< Alarm Signals Mask */ +#define XADCPS_INTX_CFIFO_LTH_MASK 0x00000200 /**< CMD FIFO less than threshold */ +#define XADCPS_INTX_DFIFO_GTH_MASK 0x00000100 /**< Data FIFO greater than threshold */ +#define XADCPS_INTX_OT_MASK 0x00000080 /**< Over temperature Alarm Status */ +#define XADCPS_INTX_ALM_ALL_MASK 0x0000007F /**< Alarm Signals Mask */ +#define XADCPS_INTX_ALM6_MASK 0x00000040 /**< Alarm 6 Mask */ +#define XADCPS_INTX_ALM5_MASK 0x00000020 /**< Alarm 5 Mask */ +#define XADCPS_INTX_ALM4_MASK 0x00000010 /**< Alarm 4 Mask */ +#define XADCPS_INTX_ALM3_MASK 0x00000008 /**< Alarm 3 Mask */ +#define XADCPS_INTX_ALM2_MASK 0x00000004 /**< Alarm 2 Mask */ +#define XADCPS_INTX_ALM1_MASK 0x00000002 /**< Alarm 1 Mask */ +#define XADCPS_INTX_ALM0_MASK 0x00000001 /**< Alarm 0 Mask */ + +/* @} */ + + +/** @name XADC Miscellaneous Register Bit definitions + * @{ + */ +#define XADCPS_MSTS_CFIFO_LVL_MASK 0x000F0000 /**< Command FIFO Level mask */ +#define XADCPS_MSTS_DFIFO_LVL_MASK 0x0000F000 /**< Data FIFO Level Mask */ +#define XADCPS_MSTS_CFIFOF_MASK 0x00000800 /**< Command FIFO Full Mask */ +#define XADCPS_MSTS_CFIFOE_MASK 0x00000400 /**< Command FIFO Empty Mask */ +#define XADCPS_MSTS_DFIFOF_MASK 0x00000200 /**< Data FIFO Full Mask */ +#define XADCPS_MSTS_DFIFOE_MASK 0x00000100 /**< Data FIFO Empty Mask */ +#define XADCPS_MSTS_OT_MASK 0x00000080 /**< Over Temperature Mask */ +#define XADCPS_MSTS_ALM_MASK 0x0000007F /**< Alarms Mask */ +/* @} */ + + +/** @name XADC Miscellaneous Control Register Bit definitions + * @{ + */ +#define XADCPS_MCTL_RESET_MASK 0x00000010 /**< Reset XADC */ +#define XADCPS_MCTL_FLUSH_MASK 0x00000001 /**< Flush the FIFOs */ +/* @} */ + + +/**@name Internal Register offsets of the XADC + * + * The following constants provide access to each of the internal registers of + * the XADC device. + * @{ + */ + +/* + * XADC Internal Channel Registers + */ +#define XADCPS_TEMP_OFFSET 0x00 /**< On-chip Temperature Reg */ +#define XADCPS_VCCINT_OFFSET 0x01 /**< On-chip VCCINT Data Reg */ +#define XADCPS_VCCAUX_OFFSET 0x02 /**< On-chip VCCAUX Data Reg */ +#define XADCPS_VPVN_OFFSET 0x03 /**< ADC out of VP/VN */ +#define XADCPS_VREFP_OFFSET 0x04 /**< On-chip VREFP Data Reg */ +#define XADCPS_VREFN_OFFSET 0x05 /**< On-chip VREFN Data Reg */ +#define XADCPS_VBRAM_OFFSET 0x06 /**< On-chip VBRAM , 7 Series */ +#define XADCPS_ADC_A_SUPPLY_CALIB_OFFSET 0x08 /**< ADC A Supply Offset Reg */ +#define XADCPS_ADC_A_OFFSET_CALIB_OFFSET 0x09 /**< ADC A Offset Data Reg */ +#define XADCPS_ADC_A_GAINERR_CALIB_OFFSET 0x0A /**< ADC A Gain Error Reg */ +#define XADCPS_VCCPINT_OFFSET 0x0D /**< On-chip VCCPINT Reg, Zynq */ +#define XADCPS_VCCPAUX_OFFSET 0x0E /**< On-chip VCCPAUX Reg, Zynq */ +#define XADCPS_VCCPDRO_OFFSET 0x0F /**< On-chip VCCPDRO Reg, Zynq */ + +/* + * XADC External Channel Registers + */ +#define XADCPS_AUX00_OFFSET 0x10 /**< ADC out of VAUXP0/VAUXN0 */ +#define XADCPS_AUX01_OFFSET 0x11 /**< ADC out of VAUXP1/VAUXN1 */ +#define XADCPS_AUX02_OFFSET 0x12 /**< ADC out of VAUXP2/VAUXN2 */ +#define XADCPS_AUX03_OFFSET 0x13 /**< ADC out of VAUXP3/VAUXN3 */ +#define XADCPS_AUX04_OFFSET 0x14 /**< ADC out of VAUXP4/VAUXN4 */ +#define XADCPS_AUX05_OFFSET 0x15 /**< ADC out of VAUXP5/VAUXN5 */ +#define XADCPS_AUX06_OFFSET 0x16 /**< ADC out of VAUXP6/VAUXN6 */ +#define XADCPS_AUX07_OFFSET 0x17 /**< ADC out of VAUXP7/VAUXN7 */ +#define XADCPS_AUX08_OFFSET 0x18 /**< ADC out of VAUXP8/VAUXN8 */ +#define XADCPS_AUX09_OFFSET 0x19 /**< ADC out of VAUXP9/VAUXN9 */ +#define XADCPS_AUX10_OFFSET 0x1A /**< ADC out of VAUXP10/VAUXN10 */ +#define XADCPS_AUX11_OFFSET 0x1B /**< ADC out of VAUXP11/VAUXN11 */ +#define XADCPS_AUX12_OFFSET 0x1C /**< ADC out of VAUXP12/VAUXN12 */ +#define XADCPS_AUX13_OFFSET 0x1D /**< ADC out of VAUXP13/VAUXN13 */ +#define XADCPS_AUX14_OFFSET 0x1E /**< ADC out of VAUXP14/VAUXN14 */ +#define XADCPS_AUX15_OFFSET 0x1F /**< ADC out of VAUXP15/VAUXN15 */ + +/* + * XADC Registers for Maximum/Minimum data captured for the + * on chip Temperature/VCCINT/VCCAUX data. + */ +#define XADCPS_MAX_TEMP_OFFSET 0x20 /**< Max Temperature Reg */ +#define XADCPS_MAX_VCCINT_OFFSET 0x21 /**< Max VCCINT Register */ +#define XADCPS_MAX_VCCAUX_OFFSET 0x22 /**< Max VCCAUX Register */ +#define XADCPS_MAX_VCCBRAM_OFFSET 0x23 /**< Max BRAM Register, 7 series */ +#define XADCPS_MIN_TEMP_OFFSET 0x24 /**< Min Temperature Reg */ +#define XADCPS_MIN_VCCINT_OFFSET 0x25 /**< Min VCCINT Register */ +#define XADCPS_MIN_VCCAUX_OFFSET 0x26 /**< Min VCCAUX Register */ +#define XADCPS_MIN_VCCBRAM_OFFSET 0x27 /**< Min BRAM Register, 7 series */ +#define XADCPS_MAX_VCCPINT_OFFSET 0x28 /**< Max VCCPINT Register, Zynq */ +#define XADCPS_MAX_VCCPAUX_OFFSET 0x29 /**< Max VCCPAUX Register, Zynq */ +#define XADCPS_MAX_VCCPDRO_OFFSET 0x2A /**< Max VCCPDRO Register, Zynq */ +#define XADCPS_MIN_VCCPINT_OFFSET 0x2C /**< Min VCCPINT Register, Zynq */ +#define XADCPS_MIN_VCCPAUX_OFFSET 0x2D /**< Min VCCPAUX Register, Zynq */ +#define XADCPS_MIN_VCCPDRO_OFFSET 0x2E /**< Min VCCPDRO Register,Zynq */ + /* Undefined 0x2F to 0x3E */ +#define XADCPS_FLAG_OFFSET 0x3F /**< Flag Register */ + +/* + * XADC Configuration Registers + */ +#define XADCPS_CFR0_OFFSET 0x40 /**< Configuration Register 0 */ +#define XADCPS_CFR1_OFFSET 0x41 /**< Configuration Register 1 */ +#define XADCPS_CFR2_OFFSET 0x42 /**< Configuration Register 2 */ + +/* Test Registers 0x43 to 0x47 */ + +/* + * XADC Sequence Registers + */ +#define XADCPS_SEQ00_OFFSET 0x48 /**< Seq Reg 00 Adc Channel Selection */ +#define XADCPS_SEQ01_OFFSET 0x49 /**< Seq Reg 01 Adc Channel Selection */ +#define XADCPS_SEQ02_OFFSET 0x4A /**< Seq Reg 02 Adc Average Enable */ +#define XADCPS_SEQ03_OFFSET 0x4B /**< Seq Reg 03 Adc Average Enable */ +#define XADCPS_SEQ04_OFFSET 0x4C /**< Seq Reg 04 Adc Input Mode Select */ +#define XADCPS_SEQ05_OFFSET 0x4D /**< Seq Reg 05 Adc Input Mode Select */ +#define XADCPS_SEQ06_OFFSET 0x4E /**< Seq Reg 06 Adc Acquisition Select */ +#define XADCPS_SEQ07_OFFSET 0x4F /**< Seq Reg 07 Adc Acquisition Select */ + +/* + * XADC Alarm Threshold/Limit Registers (ATR) + */ +#define XADCPS_ATR_TEMP_UPPER_OFFSET 0x50 /**< Temp Upper Alarm Register */ +#define XADCPS_ATR_VCCINT_UPPER_OFFSET 0x51 /**< VCCINT Upper Alarm Reg */ +#define XADCPS_ATR_VCCAUX_UPPER_OFFSET 0x52 /**< VCCAUX Upper Alarm Reg */ +#define XADCPS_ATR_OT_UPPER_OFFSET 0x53 /**< Over Temp Upper Alarm Reg */ +#define XADCPS_ATR_TEMP_LOWER_OFFSET 0x54 /**< Temp Lower Alarm Register */ +#define XADCPS_ATR_VCCINT_LOWER_OFFSET 0x55 /**< VCCINT Lower Alarm Reg */ +#define XADCPS_ATR_VCCAUX_LOWER_OFFSET 0x56 /**< VCCAUX Lower Alarm Reg */ +#define XADCPS_ATR_OT_LOWER_OFFSET 0x57 /**< Over Temp Lower Alarm Reg */ +#define XADCPS_ATR_VBRAM_UPPER_OFFSET 0x58 /**< VBRAM Upper Alarm, 7 series */ +#define XADCPS_ATR_VCCPINT_UPPER_OFFSET 0x59 /**< VCCPINT Upper Alarm, Zynq */ +#define XADCPS_ATR_VCCPAUX_UPPER_OFFSET 0x5A /**< VCCPAUX Upper Alarm, Zynq */ +#define XADCPS_ATR_VCCPDRO_UPPER_OFFSET 0x5B /**< VCCPDRO Upper Alarm, Zynq */ +#define XADCPS_ATR_VBRAM_LOWER_OFFSET 0x5C /**< VRBAM Lower Alarm, 7 Series */ +#define XADCPS_ATR_VCCPINT_LOWER_OFFSET 0x5D /**< VCCPINT Lower Alarm, Zynq */ +#define XADCPS_ATR_VCCPAUX_LOWER_OFFSET 0x5E /**< VCCPAUX Lower Alarm, Zynq */ +#define XADCPS_ATR_VCCPDRO_LOWER_OFFSET 0x5F /**< VCCPDRO Lower Alarm, Zynq */ + +/* Undefined 0x60 to 0x7F */ + +/*@}*/ + + + +/** + * @name Configuration Register 0 (CFR0) mask(s) + * @{ + */ +#define XADCPS_CFR0_CAL_AVG_MASK 0x8000 /**< Averaging enable Mask */ +#define XADCPS_CFR0_AVG_VALID_MASK 0x3000 /**< Averaging bit Mask */ +#define XADCPS_CFR0_AVG1_MASK 0x0000 /**< No Averaging */ +#define XADCPS_CFR0_AVG16_MASK 0x1000 /**< Average 16 samples */ +#define XADCPS_CFR0_AVG64_MASK 0x2000 /**< Average 64 samples */ +#define XADCPS_CFR0_AVG256_MASK 0x3000 /**< Average 256 samples */ +#define XADCPS_CFR0_AVG_SHIFT 12 /**< Averaging bits shift */ +#define XADCPS_CFR0_MUX_MASK 0x0800 /**< External Mask Enable */ +#define XADCPS_CFR0_DU_MASK 0x0400 /**< Bipolar/Unipolar mode */ +#define XADCPS_CFR0_EC_MASK 0x0200 /**< Event driven/ + * Continuous mode selection + */ +#define XADCPS_CFR0_ACQ_MASK 0x0100 /**< Add acquisition by 6 ADCCLK */ +#define XADCPS_CFR0_CHANNEL_MASK 0x001F /**< Channel number bit Mask */ + +/*@}*/ + +/** + * @name Configuration Register 1 (CFR1) mask(s) + * @{ + */ +#define XADCPS_CFR1_SEQ_VALID_MASK 0xF000 /**< Sequence bit Mask */ +#define XADCPS_CFR1_SEQ_SAFEMODE_MASK 0x0000 /**< Default Safe Mode */ +#define XADCPS_CFR1_SEQ_ONEPASS_MASK 0x1000 /**< Onepass through Seq */ +#define XADCPS_CFR1_SEQ_CONTINPASS_MASK 0x2000 /**< Continuous Cycling Seq */ +#define XADCPS_CFR1_SEQ_SINGCHAN_MASK 0x3000 /**< Single channel - No Seq */ +#define XADCPS_CFR1_SEQ_SIMUL_SAMPLING_MASK 0x4000 /**< Simulataneous Sampling Mask */ +#define XADCPS_CFR1_SEQ_INDEPENDENT_MASK 0x8000 /**< Independent Mode */ +#define XADCPS_CFR1_SEQ_SHIFT 12 /**< Sequence bit shift */ +#define XADCPS_CFR1_ALM_VCCPDRO_MASK 0x0800 /**< Alm 6 - VCCPDRO, Zynq */ +#define XADCPS_CFR1_ALM_VCCPAUX_MASK 0x0400 /**< Alm 5 - VCCPAUX, Zynq */ +#define XADCPS_CFR1_ALM_VCCPINT_MASK 0x0200 /**< Alm 4 - VCCPINT, Zynq */ +#define XADCPS_CFR1_ALM_VBRAM_MASK 0x0100 /**< Alm 3 - VBRAM, 7 series */ +#define XADCPS_CFR1_CAL_VALID_MASK 0x00F0 /**< Valid Calibration Mask */ +#define XADCPS_CFR1_CAL_PS_GAIN_OFFSET_MASK 0x0080 /**< Calibration 3 -Power + Supply Gain/Offset + Enable */ +#define XADCPS_CFR1_CAL_PS_OFFSET_MASK 0x0040 /**< Calibration 2 -Power + Supply Offset Enable */ +#define XADCPS_CFR1_CAL_ADC_GAIN_OFFSET_MASK 0x0020 /**< Calibration 1 -ADC Gain + Offset Enable */ +#define XADCPS_CFR1_CAL_ADC_OFFSET_MASK 0x0010 /**< Calibration 0 -ADC Offset + Enable */ +#define XADCPS_CFR1_CAL_DISABLE_MASK 0x0000 /**< No Calibration */ +#define XADCPS_CFR1_ALM_ALL_MASK 0x0F0F /**< Mask for all alarms */ +#define XADCPS_CFR1_ALM_VCCAUX_MASK 0x0008 /**< Alarm 2 - VCCAUX Enable */ +#define XADCPS_CFR1_ALM_VCCINT_MASK 0x0004 /**< Alarm 1 - VCCINT Enable */ +#define XADCPS_CFR1_ALM_TEMP_MASK 0x0002 /**< Alarm 0 - Temperature */ +#define XADCPS_CFR1_OT_MASK 0x0001 /**< Over Temperature Enable */ + +/*@}*/ + +/** + * @name Configuration Register 2 (CFR2) mask(s) + * @{ + */ +#define XADCPS_CFR2_CD_VALID_MASK 0xFF00 /** +* MODIFICATION HISTORY: +* +* Ver Who Date Changes +* ----- ---- -------- ------------------------------------------------------- +* 1.00a adk 1/31/14 Added in bsp common folder for backward compatibility +* 7.0 aru 01/21/19 Modified the typedef of u32,u16,u8 +* 7.0 aru 02/06/19 Included stdint.h and stddef.h +* +* +******************************************************************************/ + +#ifndef XBASIC_TYPES_H /* prevent circular inclusions */ +#define XBASIC_TYPES_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +/** @name Legacy types + * Deprecated legacy types. + * @{ + */ +typedef uint8_t Xuint8; /**< unsigned 8-bit */ +typedef char Xint8; /**< signed 8-bit */ +typedef uint16_t Xuint16; /**< unsigned 16-bit */ +typedef short Xint16; /**< signed 16-bit */ +typedef uint32_t Xuint32; /**< unsigned 32-bit */ +typedef long Xint32; /**< signed 32-bit */ +typedef float Xfloat32; /**< 32-bit floating point */ +typedef double Xfloat64; /**< 64-bit double precision FP */ +typedef unsigned long Xboolean; /**< boolean (XTRUE or XFALSE) */ + +#if !defined __XUINT64__ +typedef struct +{ + Xuint32 Upper; + Xuint32 Lower; +} Xuint64; +#endif + +/** @name New types + * New simple types. + * @{ + */ +#ifndef __KERNEL__ +#ifndef XIL_TYPES_H +typedef Xuint32 u32; +typedef Xuint16 u16; +typedef Xuint8 u8; +#endif +#else +#include +#endif + +#ifndef TRUE +# define TRUE 1U +#endif + +#ifndef FALSE +# define FALSE 0U +#endif + +#ifndef NULL +#define NULL 0U +#endif + +/* + * Xilinx NULL, TRUE and FALSE legacy support. Deprecated. + * Please use NULL, TRUE and FALSE + */ +#define XNULL NULL +#define XTRUE TRUE +#define XFALSE FALSE + +/* + * This file is deprecated and users + * should use xil_types.h and xil_assert.h\n\r + */ +#warning The xbasics_type.h file is deprecated and users should use xil_types.h and xil_assert. +#warning Please refer the Standalone BSP UG647 for further details + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/include/xbram.h b/datalink814_ge/bsp/ps7_cortexa9_0/include/xbram.h new file mode 100644 index 0000000..246df6d --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/include/xbram.h @@ -0,0 +1,223 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file xbram.h +* @addtogroup bram_v4_2 +* @{ +* @details +* +* If ECC is not enabled, this driver exists only to allow the tools to +* create a memory test application and to populate xparameters.h with memory +* range constants. In this case there is no source code. +* +* If ECC is enabled, this file contains the software API definition of the +* Xilinx BRAM Interface Controller (XBram) device driver. +* +* The Xilinx BRAM controller is a soft IP core designed for Xilinx +* FPGAs and contains the following general features: +* - LMB v2.0 bus interfaces with byte enable support +* - Used in conjunction with bram_block peripheral to provide fast BRAM +* memory solution for MicroBlaze ILMB and DLMB ports +* - Supports byte, half-word, and word transfers +* - Supports optional BRAM error correction and detection. +* +* The driver provides interrupt management functions. Implementation of +* interrupt handlers is left to the user. Refer to the provided interrupt +* example in the examples directory for details. +* +* This driver is intended to be RTOS and processor independent. Any needs for +* dynamic memory management, threads or thread mutual exclusion, virtual +* memory, or cache control must be satisfied by the layer above this driver. +* +* Initialization & Configuration +* +* The XBram_Config structure is used by the driver to configure +* itself. This configuration structure is typically created by the tool-chain +* based on HW build properties. +* +* To support multiple runtime loading and initialization strategies employed +* by various operating systems, the driver instance can be initialized as +* follows: +* +* - XBram_CfgInitialize(InstancePtr, CfgPtr, EffectiveAddr) - +* Uses a configuration structure provided by the caller. If running in a +* system with address translation, the provided virtual memory base address +* replaces the physical address present in the configuration structure. +* +* @note +* +* This API utilizes 32 bit I/O to the BRAM registers. With less +* than 32 bits, the unused bits from registers are read as zero and written as +* don't cares. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 3.00a sa  05/11/10 Added ECC support
+* 3.01a sa  01/13/12  Changed Selftest API from
+*		      XBram_SelfTest(XBram *InstancePtr) to
+*		      XBram_SelfTest(XBram *InstancePtr, u8 IntMask) and
+*		      fixed a problem with interrupt generation for CR 639274
+*		      Modified Selftest example to return XST_SUCCESS when
+*		      ECC is not enabled and return XST_FAILURE when ECC is
+*		      enabled and Control Base Address is zero (CR 636581)
+*		      Modified Selftest to use correct CorrectableCounterBits
+*		      for CR 635655
+*		      Updated to check CorrectableFailingDataRegs in the case
+*		      of LMB BRAM.
+* 		      Added CorrectableFailingDataRegs and
+*		      UncorrectableFailingDataRegs to the config structure to
+*		      distinguish between AXI BRAM and LMB BRAM.
+*		      These registers are not present in the current version of
+*		      the AXI BRAM Controller.
+* 3.02a sa 04/16/12   Added test of byte and halfword read-modify-write
+* 3.02a sa 04/16/12   Modified driver tcl to sort the address parameters
+*  	       	      to support both xps and vivado designs.
+* 3.02a adk 24/4/13   Modified the tcl file to avoid warnings
+*	       	      when ecc is disabled cr:705002.
+* 3.03a bss 05/22/13  Added Xil_DCacheFlushRange in xbram_selftest.c to
+*		      flush the Cache after writing to BRAM in InjectErrors
+*		      API(CR #719011)
+* 4.0   adk  19/12/13 Updated as per the New Tcl API's
+* 4.1   sk   11/10/15 Used UINTPTR instead of u32 for Baseaddress CR# 867425.
+*                     Changed the prototype of XBram_CfgInitialize API.
+*       ms  01/23/17 Modified xil_printf statement in main function for all
+*                    examples to ensure that "Successfully ran" and "Failed"
+*                    strings are available in all examples. This is a fix
+*                    for CR-965028.
+*       ms  03/17/17 Added readme.txt file in examples folder for doxygen
+*                    generation.
+* 4.2   ms  04/18/17 Modified tcl file to add suffix U for all macro
+*                    definitions of bram in xparameters.h
+*       ms  08/07/17 Fixed compilation warnings in xbram_sinit.c
+* 4.3   aru 03/23/19 Used UINTPTR instead of u32 for MemBaseAddress and
+*                    MemHighAddress.
+* 
+*****************************************************************************/ +#ifndef XBRAM_H /* prevent circular inclusions */ +#define XBRAM_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files ********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xstatus.h" +#include "xbram_hw.h" + +/************************** Constant Definitions ****************************/ + + +/**************************** Type Definitions ******************************/ + +/** + * This typedef contains configuration information for the device. + */ +typedef struct { + u16 DeviceId; /**< Unique ID of device */ + u32 DataWidth; /**< BRAM data width */ + int EccPresent; /**< Is ECC supported in H/W */ + int FaultInjectionPresent; /**< Is Fault Injection + * supported in H/W */ + int CorrectableFailingRegisters; /**< Is Correctable Failing Registers + * supported in H/W */ + int CorrectableFailingDataRegs; /**< Is Correctable Failing Data + * Registers supported in H/W */ + int UncorrectableFailingRegisters; /**< Is Un-correctable Failing + * Registers supported in H/W */ + int UncorrectableFailingDataRegs; /**< Is Un-correctable Failing Data + * Registers supported in H/W */ + int EccStatusInterruptPresent; /**< Are ECC status and interrupts + * supported in H/W */ + int CorrectableCounterBits; /**< Number of bits in the + * Correctable Error Counter */ + int EccOnOffRegister; /**< Is ECC on/off register supported + * in h/w */ + int EccOnOffResetValue; /**< Reset value of the ECC on/off + * register in h/w */ + int WriteAccess; /**< Is write access enabled in + * h/w */ + UINTPTR MemBaseAddress; /**< Device memory base address */ + UINTPTR MemHighAddress; /**< Device memory high address */ + UINTPTR CtrlBaseAddress; /**< Device register base address.*/ + UINTPTR CtrlHighAddress; /**< Device register base address.*/ +} XBram_Config; + +/** + * The XBram driver instance data. The user is required to + * allocate a variable of this type for every BRAM device in the + * system. A pointer to a variable of this type is then passed to the driver + * API functions. + */ +typedef struct { + XBram_Config Config; /* BRAM config structure */ + u32 IsReady; /* Device is initialized and ready */ +} XBram; + +/***************** Macros (Inline Functions) Definitions ********************/ + + +/************************** Function Prototypes *****************************/ + +/* + * Functions in xbram_sinit.c + */ +XBram_Config *XBram_LookupConfig(u16 DeviceId); + +/* + * Functions implemented in xbram.c + */ +int XBram_CfgInitialize(XBram *InstancePtr, XBram_Config *Config, + UINTPTR EffectiveAddr); + +/* + * Functions implemented in xbram_selftest.c + */ +int XBram_SelfTest(XBram *InstancePtr, u8 IntMask); + +/* + * Functions implemented in xbram_intr.c + */ +void XBram_InterruptEnable(XBram *InstancePtr, u32 Mask); +void XBram_InterruptDisable(XBram *InstancePtr, u32 Mask); +void XBram_InterruptClear(XBram *InstancePtr, u32 Mask); +u32 XBram_InterruptGetEnabled(XBram *InstancePtr); +u32 XBram_InterruptGetStatus(XBram *InstancePtr); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/include/xbram_hw.h b/datalink814_ge/bsp/ps7_cortexa9_0/include/xbram_hw.h new file mode 100644 index 0000000..55a2505 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/include/xbram_hw.h @@ -0,0 +1,405 @@ +/****************************************************************************** +* +* Copyright (C) 2011 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xbram_hw.h +* @addtogroup bram_v4_2 +* @{ +* +* This header file contains identifiers and driver functions (or +* macros) that can be used to access the device. The user should refer to the +* hardware device specification for more details of the device operation. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a sa   24/11/10 First release
+* 
+* +******************************************************************************/ +#ifndef XBRAM_HW_H /* prevent circular inclusions */ +#define XBRAM_HW_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_io.h" + +/************************** Constant Definitions *****************************/ + +/** @name Registers + * + * Register offsets for this device. + * @{ + */ + +#define XBRAM_ECC_STATUS_OFFSET 0x0 /**< ECC status Register */ +#define XBRAM_ECC_EN_IRQ_OFFSET 0x4 /**< ECC interrupt enable Register */ +#define XBRAM_ECC_ON_OFF_OFFSET 0x8 /**< ECC on/off register */ +#define XBRAM_CE_CNT_OFFSET 0xC /**< Correctable error counter Register */ + +#define XBRAM_CE_FFD_0_OFFSET 0x100 /**< Correctable error first failing + * data Register, 31-0 */ +#define XBRAM_CE_FFD_1_OFFSET 0x104 /**< Correctable error first failing + * data Register, 63-32 */ +#define XBRAM_CE_FFD_2_OFFSET 0x108 /**< Correctable error first failing + * data Register, 95-64 */ +#define XBRAM_CE_FFD_3_OFFSET 0x10C /**< Correctable error first failing + * data Register, 127-96 */ +#define XBRAM_CE_FFD_4_OFFSET 0x110 /**< Correctable error first failing + * data Register, 159-128 */ +#define XBRAM_CE_FFD_5_OFFSET 0x114 /**< Correctable error first failing + * data Register, 191-160 */ +#define XBRAM_CE_FFD_6_OFFSET 0x118 /**< Correctable error first failing + * data Register, 223-192 */ +#define XBRAM_CE_FFD_7_OFFSET 0x11C /**< Correctable error first failing + * data Register, 255-224 */ +#define XBRAM_CE_FFD_8_OFFSET 0x120 /**< Correctable error first failing + * data Register, 287-256 */ +#define XBRAM_CE_FFD_9_OFFSET 0x124 /**< Correctable error first failing + * data Register, 319-288 */ +#define XBRAM_CE_FFD_10_OFFSET 0x128 /**< Correctable error first failing + * data Register, 351-320 */ +#define XBRAM_CE_FFD_11_OFFSET 0x12C /**< Correctable error first failing + * data Register, 383-352 */ +#define XBRAM_CE_FFD_12_OFFSET 0x130 /**< Correctable error first failing + * data Register, 415-384 */ +#define XBRAM_CE_FFD_13_OFFSET 0x134 /**< Correctable error first failing + * data Register, 447-416 */ +#define XBRAM_CE_FFD_14_OFFSET 0x138 /**< Correctable error first failing + * data Register, 479-448 */ +#define XBRAM_CE_FFD_15_OFFSET 0x13C /**< Correctable error first failing + * data Register, 511-480 */ +#define XBRAM_CE_FFD_16_OFFSET 0x140 /**< Correctable error first failing + * data Register, 543-512 */ +#define XBRAM_CE_FFD_17_OFFSET 0x144 /**< Correctable error first failing + * data Register, 575-544 */ +#define XBRAM_CE_FFD_18_OFFSET 0x148 /**< Correctable error first failing + * data Register, 607-576 */ +#define XBRAM_CE_FFD_19_OFFSET 0x14C /**< Correctable error first failing + * data Register, 639-608 */ +#define XBRAM_CE_FFD_20_OFFSET 0x150 /**< Correctable error first failing + * data Register, 671-640 */ +#define XBRAM_CE_FFD_21_OFFSET 0x154 /**< Correctable error first failing + * data Register, 703-672 */ +#define XBRAM_CE_FFD_22_OFFSET 0x158 /**< Correctable error first failing + * data Register, 735-704 */ +#define XBRAM_CE_FFD_23_OFFSET 0x15C /**< Correctable error first failing + * data Register, 767-736 */ +#define XBRAM_CE_FFD_24_OFFSET 0x160 /**< Correctable error first failing + * data Register, 799-768 */ +#define XBRAM_CE_FFD_25_OFFSET 0x164 /**< Correctable error first failing + * data Register, 831-800 */ +#define XBRAM_CE_FFD_26_OFFSET 0x168 /**< Correctable error first failing + * data Register, 863-832 */ +#define XBRAM_CE_FFD_27_OFFSET 0x16C /**< Correctable error first failing + * data Register, 895-864 */ +#define XBRAM_CE_FFD_28_OFFSET 0x170 /**< Correctable error first failing + * data Register, 927-896 */ +#define XBRAM_CE_FFD_29_OFFSET 0x174 /**< Correctable error first failing + * data Register, 959-928 */ +#define XBRAM_CE_FFD_30_OFFSET 0x178 /**< Correctable error first failing + * data Register, 991-960 */ +#define XBRAM_CE_FFD_31_OFFSET 0x17C /**< Correctable error first failing + * data Register, 1023-992 */ + +#define XBRAM_CE_FFE_0_OFFSET 0x180 /**< Correctable error first failing + * ECC Register, 31-0 */ +#define XBRAM_CE_FFE_1_OFFSET 0x184 /**< Correctable error first failing + * ECC Register, 63-32 */ +#define XBRAM_CE_FFE_2_OFFSET 0x188 /**< Correctable error first failing + * ECC Register, 95-64 */ +#define XBRAM_CE_FFE_3_OFFSET 0x18C /**< Correctable error first failing + * ECC Register, 127-96 */ +#define XBRAM_CE_FFE_4_OFFSET 0x190 /**< Correctable error first failing + * ECC Register, 159-128 */ +#define XBRAM_CE_FFE_5_OFFSET 0x194 /**< Correctable error first failing + * ECC Register, 191-160 */ +#define XBRAM_CE_FFE_6_OFFSET 0x198 /**< Correctable error first failing + * ECC Register, 223-192 */ +#define XBRAM_CE_FFE_7_OFFSET 0x19C /**< Correctable error first failing + * ECC Register, 255-224 */ + +#define XBRAM_CE_FFA_0_OFFSET 0x1C0 /**< Correctable error first failing + * address Register 31-0 */ +#define XBRAM_CE_FFA_1_OFFSET 0x1C4 /**< Correctable error first failing + * address Register 63-32 */ + +#define XBRAM_UE_FFD_0_OFFSET 0x200 /**< Uncorrectable error first failing + * data Register, 31-0 */ +#define XBRAM_UE_FFD_1_OFFSET 0x204 /**< Uncorrectable error first failing + * data Register, 63-32 */ +#define XBRAM_UE_FFD_2_OFFSET 0x208 /**< Uncorrectable error first failing + * data Register, 95-64 */ +#define XBRAM_UE_FFD_3_OFFSET 0x20C /**< Uncorrectable error first failing + * data Register, 127-96 */ +#define XBRAM_UE_FFD_4_OFFSET 0x210 /**< Uncorrectable error first failing + * data Register, 159-128 */ +#define XBRAM_UE_FFD_5_OFFSET 0x214 /**< Uncorrectable error first failing + * data Register, 191-160 */ +#define XBRAM_UE_FFD_6_OFFSET 0x218 /**< Uncorrectable error first failing + * data Register, 223-192 */ +#define XBRAM_UE_FFD_7_OFFSET 0x21C /**< Uncorrectable error first failing + * data Register, 255-224 */ +#define XBRAM_UE_FFD_8_OFFSET 0x220 /**< Uncorrectable error first failing + * data Register, 287-256 */ +#define XBRAM_UE_FFD_9_OFFSET 0x224 /**< Uncorrectable error first failing + * data Register, 319-288 */ +#define XBRAM_UE_FFD_10_OFFSET 0x228 /**< Uncorrectable error first failing + * data Register, 351-320 */ +#define XBRAM_UE_FFD_11_OFFSET 0x22C /**< Uncorrectable error first failing + * data Register, 383-352 */ +#define XBRAM_UE_FFD_12_OFFSET 0x230 /**< Uncorrectable error first failing + * data Register, 415-384 */ +#define XBRAM_UE_FFD_13_OFFSET 0x234 /**< Uncorrectable error first failing + * data Register, 447-416 */ +#define XBRAM_UE_FFD_14_OFFSET 0x238 /**< Uncorrectable error first failing + * data Register, 479-448 */ +#define XBRAM_UE_FFD_15_OFFSET 0x23C /**< Uncorrectable error first failing + * data Register, 511-480 */ +#define XBRAM_UE_FFD_16_OFFSET 0x240 /**< Uncorrectable error first failing + * data Register, 543-512 */ +#define XBRAM_UE_FFD_17_OFFSET 0x244 /**< Uncorrectable error first failing + * data Register, 575-544 */ +#define XBRAM_UE_FFD_18_OFFSET 0x248 /**< Uncorrectable error first failing + * data Register, 607-576 */ +#define XBRAM_UE_FFD_19_OFFSET 0x24C /**< Uncorrectable error first failing + * data Register, 639-608 */ +#define XBRAM_UE_FFD_20_OFFSET 0x250 /**< Uncorrectable error first failing + * data Register, 671-640 */ +#define XBRAM_UE_FFD_21_OFFSET 0x254 /**< Uncorrectable error first failing + * data Register, 703-672 */ +#define XBRAM_UE_FFD_22_OFFSET 0x258 /**< Uncorrectable error first failing + * data Register, 735-704 */ +#define XBRAM_UE_FFD_23_OFFSET 0x25C /**< Uncorrectable error first failing + * data Register, 767-736 */ +#define XBRAM_UE_FFD_24_OFFSET 0x260 /**< Uncorrectable error first failing + * data Register, 799-768 */ +#define XBRAM_UE_FFD_25_OFFSET 0x264 /**< Uncorrectable error first failing + * data Register, 831-800 */ +#define XBRAM_UE_FFD_26_OFFSET 0x268 /**< Uncorrectable error first failing + * data Register, 863-832 */ +#define XBRAM_UE_FFD_27_OFFSET 0x26C /**< Uncorrectable error first failing + * data Register, 895-864 */ +#define XBRAM_UE_FFD_28_OFFSET 0x270 /**< Uncorrectable error first failing + * data Register, 927-896 */ +#define XBRAM_UE_FFD_29_OFFSET 0x274 /**< Uncorrectable error first failing + * data Register, 959-928 */ +#define XBRAM_UE_FFD_30_OFFSET 0x278 /**< Uncorrectable error first failing + * data Register, 991-960 */ +#define XBRAM_UE_FFD_31_OFFSET 0x27C /**< Uncorrectable error first failing + * data Register, 1023-992 */ + +#define XBRAM_UE_FFE_0_OFFSET 0x280 /**< Uncorrectable error first failing + * ECC Register, 31-0 */ +#define XBRAM_UE_FFE_1_OFFSET 0x284 /**< Uncorrectable error first failing + * ECC Register, 63-32 */ +#define XBRAM_UE_FFE_2_OFFSET 0x288 /**< Uncorrectable error first failing + * ECC Register, 95-64 */ +#define XBRAM_UE_FFE_3_OFFSET 0x28C /**< Uncorrectable error first failing + * ECC Register, 127-96 */ +#define XBRAM_UE_FFE_4_OFFSET 0x290 /**< Uncorrectable error first failing + * ECC Register, 159-128 */ +#define XBRAM_UE_FFE_5_OFFSET 0x294 /**< Uncorrectable error first failing + * ECC Register, 191-160 */ +#define XBRAM_UE_FFE_6_OFFSET 0x298 /**< Uncorrectable error first failing + * ECC Register, 223-192 */ +#define XBRAM_UE_FFE_7_OFFSET 0x29C /**< Uncorrectable error first failing + * ECC Register, 255-224 */ + +#define XBRAM_UE_FFA_0_OFFSET 0x2C0 /**< Uncorrectable error first failing + * address Register 31-0 */ +#define XBRAM_UE_FFA_1_OFFSET 0x2C4 /**< Uncorrectable error first failing + * address Register 63-32 */ + +#define XBRAM_FI_D_0_OFFSET 0x300 /**< Fault injection Data Register, + * 31-0 */ +#define XBRAM_FI_D_1_OFFSET 0x304 /**< Fault injection Data Register, + * 63-32 */ +#define XBRAM_FI_D_2_OFFSET 0x308 /**< Fault injection Data Register, + * 95-64 */ +#define XBRAM_FI_D_3_OFFSET 0x30C /**< Fault injection Data Register, + * 127-96 */ +#define XBRAM_FI_D_4_OFFSET 0x310 /**< Fault injection Data Register, + * 159-128 */ +#define XBRAM_FI_D_5_OFFSET 0x314 /**< Fault injection Data Register, + * 191-160 */ +#define XBRAM_FI_D_6_OFFSET 0x318 /**< Fault injection Data Register, + * 223-192 */ +#define XBRAM_FI_D_7_OFFSET 0x31C /**< Fault injection Data Register, + * 255-224 */ +#define XBRAM_FI_D_8_OFFSET 0x320 /**< Fault injection Data Register, + * 287-256 */ +#define XBRAM_FI_D_9_OFFSET 0x324 /**< Fault injection Data Register, + * 319-288 */ +#define XBRAM_FI_D_10_OFFSET 0x328 /**< Fault injection Data Register, + * 351-320 */ +#define XBRAM_FI_D_11_OFFSET 0x32C /**< Fault injection Data Register, + * 383-352 */ +#define XBRAM_FI_D_12_OFFSET 0x330 /**< Fault injection Data Register, + * 415-384 */ +#define XBRAM_FI_D_13_OFFSET 0x334 /**< Fault injection Data Register, + * 447-416 */ +#define XBRAM_FI_D_14_OFFSET 0x338 /**< Fault injection Data Register, + * 479-448 */ +#define XBRAM_FI_D_15_OFFSET 0x33C /**< Fault injection Data Register, + * 511-480 */ +#define XBRAM_FI_D_16_OFFSET 0x340 /**< Fault injection Data Register, + * 543-512 */ +#define XBRAM_FI_D_17_OFFSET 0x344 /**< Fault injection Data Register, + * 575-544 */ +#define XBRAM_FI_D_18_OFFSET 0x348 /**< Fault injection Data Register, + * 607-576 */ +#define XBRAM_FI_D_19_OFFSET 0x34C /**< Fault injection Data Register, + * 639-608 */ +#define XBRAM_FI_D_20_OFFSET 0x350 /**< Fault injection Data Register, + * 671-640 */ +#define XBRAM_FI_D_21_OFFSET 0x354 /**< Fault injection Data Register, + * 703-672 */ +#define XBRAM_FI_D_22_OFFSET 0x358 /**< Fault injection Data Register, + * 735-704 */ +#define XBRAM_FI_D_23_OFFSET 0x35C /**< Fault injection Data Register, + * 767-736 */ +#define XBRAM_FI_D_24_OFFSET 0x360 /**< Fault injection Data Register, + * 799-768 */ +#define XBRAM_FI_D_25_OFFSET 0x364 /**< Fault injection Data Register, + * 831-800 */ +#define XBRAM_FI_D_26_OFFSET 0x368 /**< Fault injection Data Register, + * 863-832 */ +#define XBRAM_FI_D_27_OFFSET 0x36C /**< Fault injection Data Register, + * 895-864 */ +#define XBRAM_FI_D_28_OFFSET 0x370 /**< Fault injection Data Register, + * 927-896 */ +#define XBRAM_FI_D_29_OFFSET 0x374 /**< Fault injection Data Register, + * 959-928 */ +#define XBRAM_FI_D_30_OFFSET 0x378 /**< Fault injection Data Register, + * 991-960 */ +#define XBRAM_FI_D_31_OFFSET 0x37C /**< Fault injection Data Register, + * 1023-992 */ + +#define XBRAM_FI_ECC_0_OFFSET 0x380 /**< Fault injection ECC Register, + * 31-0 */ +#define XBRAM_FI_ECC_1_OFFSET 0x384 /**< Fault injection ECC Register, + * 63-32 */ +#define XBRAM_FI_ECC_2_OFFSET 0x388 /**< Fault injection ECC Register, + * 95-64 */ +#define XBRAM_FI_ECC_3_OFFSET 0x38C /**< Fault injection ECC Register, + * 127-96 */ +#define XBRAM_FI_ECC_4_OFFSET 0x390 /**< Fault injection ECC Register, + * 159-128 */ +#define XBRAM_FI_ECC_5_OFFSET 0x394 /**< Fault injection ECC Register, + * 191-160 */ +#define XBRAM_FI_ECC_6_OFFSET 0x398 /**< Fault injection ECC Register, + * 223-192 */ +#define XBRAM_FI_ECC_7_OFFSET 0x39C /**< Fault injection ECC Register, + * 255-224 */ + + +/* @} */ + +/** @name Interrupt Status and Enable Register bitmaps and masks + * + * Bit definitions for the ECC status register and ECC interrupt enable register. + * @{ + */ +#define XBRAM_IR_CE_MASK 0x2 /**< Mask for the correctable error */ +#define XBRAM_IR_UE_MASK 0x1 /**< Mask for the uncorrectable error */ +#define XBRAM_IR_ALL_MASK 0x3 /**< Mask of all bits */ +/*@}*/ + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + +#define XBram_In32 Xil_In32 +#define XBram_Out32 Xil_Out32 + +#define XBram_In16 Xil_In16 +#define XBram_Out16 Xil_Out16 + +#define XBram_In8 Xil_In8 +#define XBram_Out8 Xil_Out8 + + +/****************************************************************************/ +/** +* +* Write a value to a BRAM register. A 32 bit write is performed. +* +* @param BaseAddress is the base address of the BRAM device register. +* @param RegOffset is the register offset from the base to write to. +* @param Data is the data written to the register. +* +* @return None. +* +* @note C-style signature: +* void XBram_WriteReg(u32 BaseAddress, u32 RegOffset, u32 Data) +* +****************************************************************************/ +#define XBram_WriteReg(BaseAddress, RegOffset, Data) \ + XBram_Out32((BaseAddress) + (RegOffset), (u32)(Data)) + +/****************************************************************************/ +/** +* +* Read a value from a BRAM register. A 32 bit read is performed. +* +* @param BaseAddress is the base address of the BRAM device registers. +* @param RegOffset is the register offset from the base to read from. +* +* @return Data read from the register. +* +* @note C-style signature: +* u32 XBram_ReadReg(u32 BaseAddress, u32 RegOffset) +* +****************************************************************************/ +#define XBram_ReadReg(BaseAddress, RegOffset) \ + XBram_In32((BaseAddress) + (RegOffset)) + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + + + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/include/xcoresightpsdcc.h b/datalink814_ge/bsp/ps7_cortexa9_0/include/xcoresightpsdcc.h new file mode 100644 index 0000000..79bde0b --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/include/xcoresightpsdcc.h @@ -0,0 +1,74 @@ +/****************************************************************************** +* +* Copyright (C) 2015 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xcoresightpsdcc.h +* @addtogroup coresightps_dcc_v1_5 +* @{ +* @details +* +* CoreSight driver component. +* +* The coresight is a part of debug communication channel (DCC) group. Jtag UART +* for ARM uses DCC. Each ARM core has its own DCC, so one need to select an +* ARM target in XSDB console before running the jtag terminal command. Using the +* coresight driver component, the output stream can be directed to a log file. +* +* @note None. +* +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date		Changes
+* ----- -----  -------- -----------------------------------------------
+* 1.00  kvn    02/14/15 First release
+* 1.1   kvn    06/12/15 Add support for Zynq Ultrascale+ MP.
+*       kvn    08/18/15 Modified Makefile according to compiler changes.
+* 1.3   asa    07/01/16 Made changes to ensure that the file does not compile
+*                       for MB BSPs. Instead it throws up a warning. This
+*                       fixes the CR#953056.
+* 1.5   sne    01/19/19 Fixed MISRA-C Violations CR#1025101.
+*
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ +#ifndef XCORESIGHTPSDCC_H /* prevent circular inclusions */ +#define XCORESIGHTPSDCC_H /* by using protection macros */ +#ifndef __MICROBLAZE__ +#include + +void XCoresightPs_DccSendByte(u32 BaseAddress, u8 Data); + +u8 XCoresightPs_DccRecvByte(u32 BaseAddress); +#endif +#endif +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/include/xcpu_cortexa9.h b/datalink814_ge/bsp/ps7_cortexa9_0/include/xcpu_cortexa9.h new file mode 100644 index 0000000..e4a5e28 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/include/xcpu_cortexa9.h @@ -0,0 +1,47 @@ +/****************************************************************************** +* +* Copyright (C) 2011 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xcpu_cortexa9.h +* @addtogroup cpu_cortexa9_v2_7 +* @{ +* @details +* +* dummy file +* MODIFICATION HISTORY: +* +* Ver Who Date Changes +* ----- ---- -------- --------------------------------------------------------- +* 2.5 ms 04/18/17 Modified tcl file to add suffix U for XPAR_CPU_ID +* parameter of cpu_cortexa9 in xparameters.h +# 2.7 mus 07/03/18 Updated tcl to not to add default flags forcefully into +# extra compiler flags. Now, user can remove default flags +# from extra compiler flags. It fixes CR#998768. +******************************************************************************/ +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/include/xddrps.h b/datalink814_ge/bsp/ps7_cortexa9_0/include/xddrps.h new file mode 100644 index 0000000..b4d1f56 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/include/xddrps.h @@ -0,0 +1,62 @@ +/******************************************************************************* + * + * Copyright (C) 2015 Xilinx, Inc. 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 + * XILINX 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. + * + * Except as contained in this notice, the name of the Xilinx shall not be used + * in advertising or otherwise to promote the sale, use or other dealings in + * this Software without prior written authorization from Xilinx. + * +*******************************************************************************/ +/******************************************************************************/ +/** + * + * @file xddrps.h + * @addtogroup ddrps_v1_0 + * @{ + * @details + * + * The Xilinx DdrPs driver. This driver supports the Xilinx ddrps + * IP core. + * + * @note None. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -----------------------------------------------
+ * 1.0	 nsk  08/06/15 First Release
+ * 1.0	 nsk  08/20/15 Updated define_addr_params in ddrps.tcl
+ *		       to support PBD Designs (CR #876857)
+ *
+ * 
+ * +*******************************************************************************/ + +#ifndef XDDRPS_H_ +/* Prevent circular inclusions by using protection macros. */ +#define XDDRPS_H_ + +/******************************* Include Files ********************************/ + + +#endif /* XDDRPS_H_ */ +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/include/xdebug.h b/datalink814_ge/bsp/ps7_cortexa9_0/include/xdebug.h new file mode 100644 index 0000000..b09c02d --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/include/xdebug.h @@ -0,0 +1,40 @@ +#ifndef XDEBUG /* prevent circular inclusions */ +#define XDEBUG /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(DEBUG) && !defined(NDEBUG) + +#ifndef XDEBUG_WARNING +#define XDEBUG_WARNING +#warning DEBUG is enabled +#endif + +int printf(const char *format, ...); + +#define XDBG_DEBUG_ERROR 0x00000001U /* error condition messages */ +#define XDBG_DEBUG_GENERAL 0x00000002U /* general debug messages */ +#define XDBG_DEBUG_ALL 0xFFFFFFFFU /* all debugging data */ + +#define xdbg_current_types (XDBG_DEBUG_GENERAL) + +#define xdbg_stmnt(x) x + +#define xdbg_printf(type, ...) (((type) & xdbg_current_types) ? printf (__VA_ARGS__) : 0) + + +#else /* defined(DEBUG) && !defined(NDEBUG) */ + +#define xdbg_stmnt(x) + +#define xdbg_printf(...) + +#endif /* defined(DEBUG) && !defined(NDEBUG) */ + +#ifdef __cplusplus +} +#endif + +#endif /* XDEBUG */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/include/xdevcfg.h b/datalink814_ge/bsp/ps7_cortexa9_0/include/xdevcfg.h new file mode 100644 index 0000000..6586370 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/include/xdevcfg.h @@ -0,0 +1,399 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2017 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xdevcfg.h +* @addtogroup devcfg_v3_5 +* @{ +* @details +* +* The is the main header file for the Device Configuration Interface of the Zynq +* device. The device configuration interface has three main functionality. +* 1. AXI-PCAP +* 2. Security Policy +* 3. XADC +* This current version of the driver supports only the AXI-PCAP and Security +* Policy blocks. There is a separate driver for XADC. +* +* AXI-PCAP is used for download/upload an encrypted or decrypted bitstream. +* DMA embedded in the AXI PCAP provides the master interface to +* the Device configuration block for any DMA transfers. The data transfer can +* take place between the Tx/RxFIFOs of AXI-PCAP and memory (on chip +* RAM/DDR/peripheral memory). +* +* The current driver only supports the downloading the FPGA bitstream and +* readback of the decrypted image (sort of loopback). +* The driver does not know what information needs to be written to the FPGA to +* readback FPGA configuration register or memory data. The application above the +* driver should take care of creating the data that needs to be downloaded to +* the FPGA so that the bitstream can be readback. +* This driver also does not support the reading of the internal registers of the +* PCAP. The driver has no knowledge of the PCAP internals. +* +* Initialization and Configuration +* +* The device driver enables higher layer software (e.g., an application) to +* communicate with the Device Configuration device. +* +* XDcfg_CfgInitialize() API is used to initialize the Device Configuration +* Interface. The user needs to first call the XDcfg_LookupConfig() API which +* returns the Configuration structure pointer which is passed as a parameter to +* the XDcfg_CfgInitialize() API. +* +* Interrupts +* The Driver implements an interrupt handler to support the interrupts provided +* by this interface. +* +* Threads +* +* This driver is not thread safe. Any needs for threads or thread mutual +* exclusion must be satisfied by the layer above this driver. +* +* Asserts +* +* Asserts are used within all Xilinx drivers to enforce constraints on argument +* values. Asserts can be turned off on a system-wide basis by defining, at +* compile time, the NDEBUG identifier. By default, asserts are turned on and it +* is recommended that users leave asserts on during development. +* +* Building the driver +* +* The XDcfg driver is composed of several source files. This allows the user +* to build and link only those parts of the driver that are necessary. +* +*

+* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 1.00a hvm 02/07/11 First release
+* 2.00a nm  05/31/12 Updated the driver for CR 660835 so that input length for
+*		     source/destination to the XDcfg_InitiateDma, XDcfg_Transfer
+*		     APIs is words (32 bit) and not bytes.
+* 		     Updated the notes for XDcfg_InitiateDma/XDcfg_Transfer APIs
+*		     to add information that 2 LSBs of the Source/Destination
+*		     address when equal to 2�b01 indicate the last DMA command
+*		     of an overall transfer.
+*		     Destination Address passed to this API for secure transfers
+*		     instead of using 0xFFFFFFFF for CR 662197. This issue was
+*		     resulting in the failure of secure transfers of
+*		     non-bitstream images.
+* 2.01a nm  07/07/12 Updated the XDcfg_IntrClear function to directly
+*		     set the mask instead of oring it with the
+*		     value read from the interrupt status register
+* 		     Added defines for the PS Version bits,
+*	             removed the FIFO Flush bits from the
+*		     Miscellaneous Control Reg.
+*		     Added XDcfg_GetPsVersion, XDcfg_SelectIcapInterface
+*		     and XDcfg_SelectPcapInterface APIs for CR 643295
+*		     The user has to call the XDcfg_SelectIcapInterface API
+*		     for the PL reconfiguration using AXI HwIcap.
+*		     Updated the XDcfg_Transfer API to clear the
+*		     QUARTER_PCAP_RATE_EN bit in the control register for
+*		     non secure writes for CR 675543.
+* 2.02a nm  01/31/13 Fixed CR# 679335.
+* 		     Added Setting and Clearing the internal PCAP loopback.
+*		     Removed code for enabling/disabling AES engine as BootROM
+*		     locks down this setting.
+*		     Fixed CR# 681976.
+*		     Skip Checking the PCFG_INIT in case of non-secure DMA
+*		     loopback.
+*		     Fixed CR# 699558.
+*		     XDcfg_Transfer fails to transfer data in loopback mode.
+*		     Fixed CR# 701348.
+*                    Peripheral test fails with  Running
+* 		     DcfgSelfTestExample() in SECURE bootmode.
+* 2.03a nm  04/19/13 Fixed CR# 703728.
+*		     Updated the register definitions as per the latest TRM
+*		     version UG585 (v1.4) November 16, 2012.
+* 3.0   adk 10/12/13 Updated as per the New Tcl API's
+* 3.0   kpc 21/02/14 Added function prototype for XDcfg_ClearControlRegister
+* 3.2   sb  08/25/14 Fixed XDcfg_PcapReadback() function
+*		     updated driver code with != instead of ==,
+*		     while checking for Interrupt Status with DMA and
+*		     PCAP Done Mask
+*		     ((XDcfg_ReadReg(InstancePtr->Config.BaseAddr,
+*			XDCFG_INT_STS_OFFSET) &
+*			XDCFG_IXR_D_P_DONE_MASK) !=
+*			XDCFG_IXR_D_P_DONE_MASK);
+*		     A new example has been added to read back the
+*		     configuration registers from the PL region.
+*		     xdevcfg_reg_readback_example.c
+* 3.3   sk  04/06/15 Modified XDcfg_ReadMultiBootConfig Macro CR# 851335.
+*       ms  03/17/17 Added readme.txt file in examples folder for doxygen
+*                    generation.
+*       ms  04/10/17 Modified filename tag in interrupt and polled examples
+*                    to include them in doxygen examples.
+* 3.5   ms  04/18/17 Modified tcl file to add suffix U for all macros
+*                    definitions of devcfg in xparameters.h
+*       ms  08/07/17 Fixed compilation warnings in xdevcfg_sinit.c
+* 
+* +******************************************************************************/ +#ifndef XDCFG_H /* prevent circular inclusions */ +#define XDCFG_H /* by using protection macros */ + +/***************************** Include Files *********************************/ + +#include "xdevcfg_hw.h" +#include "xstatus.h" +#include "xil_assert.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************** Constant Definitions *****************************/ + +/* Types of PCAP transfers */ + +#define XDCFG_NON_SECURE_PCAP_WRITE 1 +#define XDCFG_SECURE_PCAP_WRITE 2 +#define XDCFG_PCAP_READBACK 3 +#define XDCFG_CONCURRENT_SECURE_READ_WRITE 4 +#define XDCFG_CONCURRENT_NONSEC_READ_WRITE 5 + + +/**************************** Type Definitions *******************************/ +/** +* The handler data type allows the user to define a callback function to +* respond to interrupt events in the system. This function is executed +* in interrupt context, so amount of processing should be minimized. +* +* @param CallBackRef is the callback reference passed in by the upper +* layer when setting the callback functions, and passed back to +* the upper layer when the callback is invoked. Its type is +* unimportant to the driver component, so it is a void pointer. +* @param Status is the Interrupt status of the XDcfg device. +*/ +typedef void (*XDcfg_IntrHandler) (void *CallBackRef, u32 Status); + +/** + * This typedef contains configuration information for the device. + */ +typedef struct { + u16 DeviceId; /**< Unique ID of device */ + u32 BaseAddr; /**< Base address of the device */ +} XDcfg_Config; + +/** + * The XDcfg driver instance data. + */ +typedef struct { + XDcfg_Config Config; /**< Hardware Configuration */ + u32 IsReady; /**< Device is initialized and ready */ + u32 IsStarted; /**< Device Configuration Interface + * is running + */ + XDcfg_IntrHandler StatusHandler; /* Event handler function */ + void *CallBackRef; /* Callback reference for event handler */ +} XDcfg; + +/****************************************************************************/ +/** +* +* Unlock the Device Config Interface block. +* +* @param InstancePtr is a pointer to the instance of XDcfg driver. +* +* @return None. +* +* @note C-style signature: +* void XDcfg_Unlock(XDcfg* InstancePtr) +* +*****************************************************************************/ +#define XDcfg_Unlock(InstancePtr) \ + XDcfg_WriteReg((InstancePtr)->Config.BaseAddr, \ + XDCFG_UNLOCK_OFFSET, XDCFG_UNLOCK_DATA) + + + +/****************************************************************************/ +/** +* +* Get the version number of the PS from the Miscellaneous Control Register. +* +* @param InstancePtr is a pointer to the instance of XDcfg driver. +* +* @return Version of the PS. +* +* @note C-style signature: +* void XDcfg_GetPsVersion(XDcfg* InstancePtr) +* +*****************************************************************************/ +#define XDcfg_GetPsVersion(InstancePtr) \ + ((XDcfg_ReadReg((InstancePtr)->Config.BaseAddr, \ + XDCFG_MCTRL_OFFSET)) & \ + XDCFG_MCTRL_PCAP_PS_VERSION_MASK) >> \ + XDCFG_MCTRL_PCAP_PS_VERSION_SHIFT + + + +/****************************************************************************/ +/** +* +* Read the multiboot config register value. +* +* @param InstancePtr is a pointer to the instance of XDcfg driver. +* +* @return None. +* +* @note C-style signature: +* u32 XDcfg_ReadMultiBootConfig(XDcfg* InstancePtr) +* +*****************************************************************************/ +#define XDcfg_ReadMultiBootConfig(InstancePtr) \ + XDcfg_ReadReg((InstancePtr)->Config.BaseAddr, \ + XDCFG_MULTIBOOT_ADDR_OFFSET) + + +/****************************************************************************/ +/** +* +* Selects ICAP interface for reconfiguration after the initial configuration +* of the PL. +* +* @param InstancePtr is a pointer to the instance of XDcfg driver. +* +* @return None. +* +* @note C-style signature: +* void XDcfg_SelectIcapInterface(XDcfg* InstancePtr) +* +*****************************************************************************/ +#define XDcfg_SelectIcapInterface(InstancePtr) \ + XDcfg_WriteReg((InstancePtr)->Config.BaseAddr, XDCFG_CTRL_OFFSET, \ + ((XDcfg_ReadReg((InstancePtr)->Config.BaseAddr, XDCFG_CTRL_OFFSET)) \ + & ( ~XDCFG_CTRL_PCAP_PR_MASK))) + +/****************************************************************************/ +/** +* +* Selects PCAP interface for reconfiguration after the initial configuration +* of the PL. +* +* @param InstancePtr is a pointer to the instance of XDcfg driver. +* +* @return None. +* +* @note C-style signature: +* void XDcfg_SelectPcapInterface(XDcfg* InstancePtr) +* +*****************************************************************************/ +#define XDcfg_SelectPcapInterface(InstancePtr) \ + XDcfg_WriteReg((InstancePtr)->Config.BaseAddr, XDCFG_CTRL_OFFSET, \ + ((XDcfg_ReadReg((InstancePtr)->Config.BaseAddr, XDCFG_CTRL_OFFSET)) \ + | XDCFG_CTRL_PCAP_PR_MASK)) + + + +/************************** Function Prototypes ******************************/ + +/* + * Lookup configuration in xdevcfg_sinit.c. + */ +XDcfg_Config *XDcfg_LookupConfig(u16 DeviceId); + +/* + * Selftest function in xdevcfg_selftest.c + */ +int XDcfg_SelfTest(XDcfg *InstancePtr); + +/* + * Interface functions in xdevcfg.c + */ +int XDcfg_CfgInitialize(XDcfg *InstancePtr, + XDcfg_Config *ConfigPtr, u32 EffectiveAddress); + +void XDcfg_EnablePCAP(XDcfg *InstancePtr); + +void XDcfg_DisablePCAP(XDcfg *InstancePtr); + +void XDcfg_SetControlRegister(XDcfg *InstancePtr, u32 Mask); + +void XDcfg_ClearControlRegister(XDcfg *InstancePtr, u32 Mask); + +u32 XDcfg_GetControlRegister(XDcfg *InstancePtr); + +void XDcfg_SetLockRegister(XDcfg *InstancePtr, u32 Data); + +u32 XDcfg_GetLockRegister(XDcfg *InstancePtr); + +void XDcfg_SetConfigRegister(XDcfg *InstancePtr, u32 Data); + +u32 XDcfg_GetConfigRegister(XDcfg *InstancePtr); + +void XDcfg_SetStatusRegister(XDcfg *InstancePtr, u32 Data); + +u32 XDcfg_GetStatusRegister(XDcfg *InstancePtr); + +void XDcfg_SetRomShadowRegister(XDcfg *InstancePtr, u32 Data); + +u32 XDcfg_GetSoftwareIdRegister(XDcfg *InstancePtr); + +void XDcfg_SetMiscControlRegister(XDcfg *InstancePtr, u32 Mask); + +u32 XDcfg_GetMiscControlRegister(XDcfg *InstancePtr); + +u32 XDcfg_IsDmaBusy(XDcfg *InstancePtr); + +void XDcfg_InitiateDma(XDcfg *InstancePtr, u32 SourcePtr, u32 DestPtr, + u32 SrcWordLength, u32 DestWordLength); + +u32 XDcfg_Transfer(XDcfg *InstancePtr, + void *SourcePtr, u32 SrcWordLength, + void *DestPtr, u32 DestWordLength, + u32 TransferType); + +/* + * Interrupt related function prototypes implemented in xdevcfg_intr.c + */ +void XDcfg_IntrEnable(XDcfg *InstancePtr, u32 Mask); + +void XDcfg_IntrDisable(XDcfg *InstancePtr, u32 Mask); + +u32 XDcfg_IntrGetEnabled(XDcfg *InstancePtr); + +u32 XDcfg_IntrGetStatus(XDcfg *InstancePtr); + +void XDcfg_IntrClear(XDcfg *InstancePtr, u32 Mask); + +void XDcfg_InterruptHandler(XDcfg *InstancePtr); + +void XDcfg_SetHandler(XDcfg *InstancePtr, void *CallBackFunc, + void *CallBackRef); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/include/xdevcfg_hw.h b/datalink814_ge/bsp/ps7_cortexa9_0/include/xdevcfg_hw.h new file mode 100644 index 0000000..80b6678 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/include/xdevcfg_hw.h @@ -0,0 +1,391 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xdevcfg_hw.h +* @addtogroup devcfg_v3_3 +* @{ +* +* This file contains the hardware interface to the Device Config Interface. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 1.00a hvm 02/07/11 First release
+* 2.01a nm  08/01/12 Added defines for the PS Version bits,
+*	             removed the FIFO Flush bits from the
+*		     Miscellaneous Control Reg
+* 2.03a nm  04/19/13 Fixed CR# 703728.
+*		     Updated the register definitions as per the latest TRM
+*		     version UG585 (v1.4) November 16, 2012.
+* 2.04a	kpc	10/07/13 Added function prototype.
+* 3.00a	kpc	25/02/14 Corrected the XDCFG_BASE_ADDRESS macro value.
+* 
+* +******************************************************************************/ +#ifndef XDCFG_HW_H /* prevent circular inclusions */ +#define XDCFG_HW_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_io.h" + +/************************** Constant Definitions *****************************/ + +/** @name Register Map + * Offsets of registers from the start of the device + * @{ + */ + +#define XDCFG_CTRL_OFFSET 0x00 /**< Control Register */ +#define XDCFG_LOCK_OFFSET 0x04 /**< Lock Register */ +#define XDCFG_CFG_OFFSET 0x08 /**< Configuration Register */ +#define XDCFG_INT_STS_OFFSET 0x0C /**< Interrupt Status Register */ +#define XDCFG_INT_MASK_OFFSET 0x10 /**< Interrupt Mask Register */ +#define XDCFG_STATUS_OFFSET 0x14 /**< Status Register */ +#define XDCFG_DMA_SRC_ADDR_OFFSET 0x18 /**< DMA Source Address Register */ +#define XDCFG_DMA_DEST_ADDR_OFFSET 0x1C /**< DMA Destination Address Reg */ +#define XDCFG_DMA_SRC_LEN_OFFSET 0x20 /**< DMA Source Transfer Length */ +#define XDCFG_DMA_DEST_LEN_OFFSET 0x24 /**< DMA Destination Transfer */ +#define XDCFG_ROM_SHADOW_OFFSET 0x28 /**< DMA ROM Shadow Register */ +#define XDCFG_MULTIBOOT_ADDR_OFFSET 0x2C /**< Multi BootAddress Pointer */ +#define XDCFG_SW_ID_OFFSET 0x30 /**< Software ID Register */ +#define XDCFG_UNLOCK_OFFSET 0x34 /**< Unlock Register */ +#define XDCFG_MCTRL_OFFSET 0x80 /**< Miscellaneous Control Reg */ + +/* @} */ + +/** @name Control Register Bit definitions + * @{ + */ + +#define XDCFG_CTRL_FORCE_RST_MASK 0x80000000 /**< Force into + * Secure Reset + */ +#define XDCFG_CTRL_PCFG_PROG_B_MASK 0x40000000 /**< Program signal to + * Reset FPGA + */ +#define XDCFG_CTRL_PCFG_POR_CNT_4K_MASK 0x20000000 /**< Control PL POR timer */ +#define XDCFG_CTRL_PCAP_PR_MASK 0x08000000 /**< Enable PCAP for PR */ +#define XDCFG_CTRL_PCAP_MODE_MASK 0x04000000 /**< Enable PCAP */ +#define XDCFG_CTRL_PCAP_RATE_EN_MASK 0x02000000 /**< Enable PCAP send data + * to FPGA every 4 PCAP + * cycles + */ +#define XDCFG_CTRL_MULTIBOOT_EN_MASK 0x01000000 /**< Multiboot Enable */ +#define XDCFG_CTRL_JTAG_CHAIN_DIS_MASK 0x00800000 /**< JTAG Chain Disable */ +#define XDCFG_CTRL_USER_MODE_MASK 0x00008000 /**< User Mode Mask */ +#define XDCFG_CTRL_PCFG_AES_FUSE_MASK 0x00001000 /**< AES key source */ +#define XDCFG_CTRL_PCFG_AES_EN_MASK 0x00000E00 /**< AES Enable Mask */ +#define XDCFG_CTRL_SEU_EN_MASK 0x00000100 /**< SEU Enable Mask */ +#define XDCFG_CTRL_SEC_EN_MASK 0x00000080 /**< Secure/Non Secure + * Status mask + */ +#define XDCFG_CTRL_SPNIDEN_MASK 0x00000040 /**< Secure Non Invasive + * Debug Enable + */ +#define XDCFG_CTRL_SPIDEN_MASK 0x00000020 /**< Secure Invasive + * Debug Enable + */ +#define XDCFG_CTRL_NIDEN_MASK 0x00000010 /**< Non-Invasive Debug + * Enable + */ +#define XDCFG_CTRL_DBGEN_MASK 0x00000008 /**< Invasive Debug + * Enable + */ +#define XDCFG_CTRL_DAP_EN_MASK 0x00000007 /**< DAP Enable Mask */ + +/* @} */ + +/** @name Lock register bit definitions + * @{ + */ + +#define XDCFG_LOCK_AES_EFUSE_MASK 0x00000010 /**< Lock AES Efuse bit */ +#define XDCFG_LOCK_AES_EN_MASK 0x00000008 /**< Lock AES_EN update */ +#define XDCFG_LOCK_SEU_MASK 0x00000004 /**< Lock SEU_En update */ +#define XDCFG_LOCK_SEC_MASK 0x00000002 /**< Lock SEC_EN and + * USER_MODE + */ +#define XDCFG_LOCK_DBG_MASK 0x00000001 /**< This bit locks + * security config + * including: DAP_En, + * DBGEN,, + * NIDEN, SPNIEN + */ +/*@}*/ + + + +/** @name Config Register Bit definitions + * @{ + */ +#define XDCFG_CFG_RFIFO_TH_MASK 0x00000C00 /**< Read FIFO + * Threshold Mask + */ +#define XDCFG_CFG_WFIFO_TH_MASK 0x00000300 /**< Write FIFO Threshold + * Mask + */ +#define XDCFG_CFG_RCLK_EDGE_MASK 0x00000080 /**< Read data active + * clock edge + */ +#define XDCFG_CFG_WCLK_EDGE_MASK 0x00000040 /**< Write data active + * clock edge + */ +#define XDCFG_CFG_DISABLE_SRC_INC_MASK 0x00000020 /**< Disable Source address + * increment mask + */ +#define XDCFG_CFG_DISABLE_DST_INC_MASK 0x00000010 /**< Disable Destination + * address increment + * mask + */ +/* @} */ + + +/** @name Interrupt Status/Mask Register Bit definitions + * @{ + */ +#define XDCFG_IXR_PSS_GTS_USR_B_MASK 0x80000000 /**< Tri-state IO during + * HIZ + */ +#define XDCFG_IXR_PSS_FST_CFG_B_MASK 0x40000000 /**< First configuration + * done + */ +#define XDCFG_IXR_PSS_GPWRDWN_B_MASK 0x20000000 /**< Global power down */ +#define XDCFG_IXR_PSS_GTS_CFG_B_MASK 0x10000000 /**< Tri-state IO during + * configuration + */ +#define XDCFG_IXR_PSS_CFG_RESET_B_MASK 0x08000000 /**< PL configuration + * reset + */ +#define XDCFG_IXR_AXI_WTO_MASK 0x00800000 /**< AXI Write Address + * or Data or response + * timeout + */ +#define XDCFG_IXR_AXI_WERR_MASK 0x00400000 /**< AXI Write response + * error + */ +#define XDCFG_IXR_AXI_RTO_MASK 0x00200000 /**< AXI Read Address or + * response timeout + */ +#define XDCFG_IXR_AXI_RERR_MASK 0x00100000 /**< AXI Read response + * error + */ +#define XDCFG_IXR_RX_FIFO_OV_MASK 0x00040000 /**< Rx FIFO Overflow */ +#define XDCFG_IXR_WR_FIFO_LVL_MASK 0x00020000 /**< Tx FIFO less than + * threshold */ +#define XDCFG_IXR_RD_FIFO_LVL_MASK 0x00010000 /**< Rx FIFO greater than + * threshold */ +#define XDCFG_IXR_DMA_CMD_ERR_MASK 0x00008000 /**< Illegal DMA command */ +#define XDCFG_IXR_DMA_Q_OV_MASK 0x00004000 /**< DMA command queue + * overflow + */ +#define XDCFG_IXR_DMA_DONE_MASK 0x00002000 /**< DMA Command Done */ +#define XDCFG_IXR_D_P_DONE_MASK 0x00001000 /**< DMA and PCAP + * transfers Done + */ +#define XDCFG_IXR_P2D_LEN_ERR_MASK 0x00000800 /**< PCAP to DMA transfer + * length error + */ +#define XDCFG_IXR_PCFG_HMAC_ERR_MASK 0x00000040 /**< HMAC error mask */ +#define XDCFG_IXR_PCFG_SEU_ERR_MASK 0x00000020 /**< SEU Error mask */ +#define XDCFG_IXR_PCFG_POR_B_MASK 0x00000010 /**< FPGA POR mask */ +#define XDCFG_IXR_PCFG_CFG_RST_MASK 0x00000008 /**< FPGA Reset mask */ +#define XDCFG_IXR_PCFG_DONE_MASK 0x00000004 /**< Done Signal Mask */ +#define XDCFG_IXR_PCFG_INIT_PE_MASK 0x00000002 /**< Detect Positive edge + * of Init Signal + */ +#define XDCFG_IXR_PCFG_INIT_NE_MASK 0x00000001 /**< Detect Negative edge + * of Init Signal + */ +#define XDCFG_IXR_ERROR_FLAGS_MASK (XDCFG_IXR_AXI_WTO_MASK | \ + XDCFG_IXR_AXI_WERR_MASK | \ + XDCFG_IXR_AXI_RTO_MASK | \ + XDCFG_IXR_AXI_RERR_MASK | \ + XDCFG_IXR_RX_FIFO_OV_MASK | \ + XDCFG_IXR_DMA_CMD_ERR_MASK |\ + XDCFG_IXR_DMA_Q_OV_MASK | \ + XDCFG_IXR_P2D_LEN_ERR_MASK |\ + XDCFG_IXR_PCFG_HMAC_ERR_MASK) + + +#define XDCFG_IXR_ALL_MASK 0x00F7F8EF + + + +/* @} */ + + +/** @name Status Register Bit definitions + * @{ + */ +#define XDCFG_STATUS_DMA_CMD_Q_F_MASK 0x80000000 /**< DMA command + * Queue full + */ +#define XDCFG_STATUS_DMA_CMD_Q_E_MASK 0x40000000 /**< DMA command + * Queue empty + */ +#define XDCFG_STATUS_DMA_DONE_CNT_MASK 0x30000000 /**< Number of + * completed DMA + * transfers + */ +#define XDCFG_STATUS_RX_FIFO_LVL_MASK 0x01F000000 /**< Rx FIFO level */ +#define XDCFG_STATUS_TX_FIFO_LVL_MASK 0x0007F000 /**< Tx FIFO level */ + +#define XDCFG_STATUS_PSS_GTS_USR_B 0x00000800 /**< Tri-state IO + * during HIZ + */ +#define XDCFG_STATUS_PSS_FST_CFG_B 0x00000400 /**< First PL config + * done + */ +#define XDCFG_STATUS_PSS_GPWRDWN_B 0x00000200 /**< Global power down */ +#define XDCFG_STATUS_PSS_GTS_CFG_B 0x00000100 /**< Tri-state IO during + * config + */ +#define XDCFG_STATUS_SECURE_RST_MASK 0x00000080 /**< Secure Reset + * POR Status + */ +#define XDCFG_STATUS_ILLEGAL_APB_ACCESS_MASK 0x00000040 /**< Illegal APB + * access + */ +#define XDCFG_STATUS_PSS_CFG_RESET_B 0x00000020 /**< PL config + * reset status + */ +#define XDCFG_STATUS_PCFG_INIT_MASK 0x00000010 /**< FPGA Init + * Status + */ +#define XDCFG_STATUS_EFUSE_BBRAM_KEY_DISABLE_MASK 0x00000008 + /**< BBRAM key + * disable + */ +#define XDCFG_STATUS_EFUSE_SEC_EN_MASK 0x00000004 /**< Efuse Security + * Enable Status + */ +#define XDCFG_STATUS_EFUSE_JTAG_DIS_MASK 0x00000002 /**< EFuse JTAG + * Disable + * status + */ +/* @} */ + + +/** @name DMA Source/Destination Transfer Length Register Bit definitions + * @{ + */ +#define XDCFG_DMA_LEN_MASK 0x7FFFFFF /**< Length Mask */ +/*@}*/ + + + + +/** @name Miscellaneous Control Register Bit definitions + * @{ + */ +#define XDCFG_MCTRL_PCAP_PS_VERSION_MASK 0xF0000000 /**< PS Version Mask */ +#define XDCFG_MCTRL_PCAP_PS_VERSION_SHIFT 28 /**< PS Version Shift */ +#define XDCFG_MCTRL_PCAP_LPBK_MASK 0x00000010 /**< PCAP loopback mask */ +/* @} */ + +/** @name FIFO Threshold Bit definitions + * @{ + */ + +#define XDCFG_CFG_FIFO_QUARTER 0x0 /**< Quarter empty */ +#define XDCFG_CFG_FIFO_HALF 0x1 /**< Half empty */ +#define XDCFG_CFG_FIFO_3QUARTER 0x2 /**< 3/4 empty */ +#define XDCFG_CFG_FIFO_EMPTY 0x4 /**< Empty */ +/* @}*/ + + +/* Miscellaneous constant values */ +#define XDCFG_DMA_INVALID_ADDRESS 0xFFFFFFFF /**< Invalid DMA address */ +#define XDCFG_UNLOCK_DATA 0x757BDF0D /**< First APB access data*/ +#define XDCFG_BASE_ADDRESS 0xF8007000 /**< Device Config base + * address + */ +#define XDCFG_CONFIG_RESET_VALUE 0x508 /**< Config reg reset value */ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/****************************************************************************/ +/** +* +* Read the given register. +* +* @param BaseAddr is the base address of the device +* @param RegOffset is the register offset to be read +* +* @return The 32-bit value of the register +* +* @note C-style signature: +* u32 XDcfg_ReadReg(u32 BaseAddr, u32 RegOffset) +* +*****************************************************************************/ +#define XDcfg_ReadReg(BaseAddr, RegOffset) \ + Xil_In32((BaseAddr) + (RegOffset)) + +/****************************************************************************/ +/** +* +* Write to the given register. +* +* @param BaseAddr is the base address of the device +* @param RegOffset is the register offset to be written +* @param Data is the 32-bit value to write to the register +* +* @return None. +* +* @note C-style signature: +* void XDcfg_WriteReg(u32 BaseAddr, u32 RegOffset, u32 Data) +* +*****************************************************************************/ +#define XDcfg_WriteReg(BaseAddr, RegOffset, Data) \ + Xil_Out32((BaseAddr) + (RegOffset), (Data)) + +/************************** Function Prototypes ******************************/ +/* + * Perform reset operation to the devcfg interface + */ +void XDcfg_ResetHw(u32 BaseAddr); +/************************** Variable Definitions *****************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/include/xdmaps.h b/datalink814_ge/bsp/ps7_cortexa9_0/include/xdmaps.h new file mode 100644 index 0000000..73e2b1e --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/include/xdmaps.h @@ -0,0 +1,349 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xdmaps.h +* @addtogroup dmaps_v2_4 +* @{ +* @details +* +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  	Date     Changes
+* ----- ------ -------- ----------------------------------------------
+* 1.00	hbm    08/19/10 First Release
+* 1.01a nm     12/20/12 Added definition XDMAPS_CHANNELS_PER_DEV which specifies
+*		        the maximum number of channels.
+*		        Replaced the usage of XPAR_XDMAPS_CHANNELS_PER_DEV
+*                       with XDMAPS_CHANNELS_PER_DEV defined in xdmaps_hw.h.
+*			Added the tcl file to automatically generate the
+*			xparameters.h
+* 1.02a sg     05/16/12 Made changes for doxygen and moved some function
+*			header from the xdmaps.h file to xdmaps.c file
+*			Other cleanup for coding guidelines and CR 657109
+*			and CR 657898
+*			The xdmaps_example_no_intr.c example is removed
+*			as it is using interrupts  and is similar to
+*			the interrupt example - CR 652477
+* 1.03a sg     07/16/2012 changed inline to __inline for CR665681
+* 1.04a nm     10/22/2012 Fixed CR# 681671.
+* 1.05a nm     04/15/2013 Fixed CR# 704396. Removed warnings when compiled
+*			  with -Wall and -Wextra option in bsp.
+*	       05/01/2013 Fixed CR# 700189. Changed XDmaPs_BuildDmaProg()
+*			  function description.
+*			  Fixed CR# 704396. Removed unused variables
+*			  UseM2MByte & MemBurstLen from XDmaPs_BuildDmaProg()
+*			  function.
+* 1.07a asa    11/02/13. Made changes to fix compilation issues for iarcc.
+*			   Removed the PDBG prints. By default they were always
+*			   defined out and never used. The PDBG is non-standard for
+*			   Xilinx drivers and no other driver does something similar.
+*			   Since there is no easy way to fix compilation issues with
+*			   the IARCC compiler around PDBG, it is better to remove it.
+*			   Users can always use xil_printfs if they want to debug.
+* 2.0   adk    10/12/13  Updated as per the New Tcl API's
+* 2.01  kpc    08/23/14  Fixed the IAR compiler reported errors
+* 2.2   mus    08/12/16  Declared all inline functions in xdmaps.c as extern, to avoid
+*                        linker error for IAR compiler
+* 2.3   ms     01/23/17 Modified xil_printf statement in main function for all
+*                       examples to ensure that "Successfully ran" and "Failed"
+*                       strings are available in all examples. This is a fix
+*                       for CR-965028.
+*       ms     03/17/17 Added readme.txt file in examples folder for doxygen
+*                       generation.
+* 2.4   adk    13/08/18 Fixed armcc compiler warnings in the driver CR-1008310.
+* 
+* +*****************************************************************************/ + +#ifndef XDMAPS_H /* prevent circular inclusions */ +#define XDMAPS_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files ********************************/ + +#include "xparameters.h" +#include "xil_types.h" +#include "xil_assert.h" +#include "xstatus.h" + +#include "xdmaps_hw.h" + +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + +/** + * This typedef contains configuration information for the device. + */ +typedef struct { + u16 DeviceId; /**< Unique ID of device */ + u32 BaseAddress; /**< Base address of device (IPIF) */ +} XDmaPs_Config; + + +/** DMA channle control structure. It's for AXI bus transaction. + * This struct will be translated into a 32-bit channel control register value. + */ +typedef struct { + unsigned int EndianSwapSize; /**< Endian swap size. */ + unsigned int DstCacheCtrl; /**< Destination cache control */ + unsigned int DstProtCtrl; /**< Destination protection control */ + unsigned int DstBurstLen; /**< Destination burst length */ + unsigned int DstBurstSize; /**< Destination burst size */ + unsigned int DstInc; /**< Destination incrementing or fixed + * address */ + unsigned int SrcCacheCtrl; /**< Source cache control */ + unsigned int SrcProtCtrl; /**< Source protection control */ + unsigned int SrcBurstLen; /**< Source burst length */ + unsigned int SrcBurstSize; /**< Source burst size */ + unsigned int SrcInc; /**< Source incrementing or fixed + * address */ +} XDmaPs_ChanCtrl; + +/** DMA block descriptor stucture. + */ +typedef struct { + u32 SrcAddr; /**< Source starting address */ + u32 DstAddr; /**< Destination starting address */ + unsigned int Length; /**< Number of bytes for the block */ +} XDmaPs_BD; + +/** + * A DMA command consisits of a channel control struct, a block descriptor, + * a user defined program, a pointer pointing to generated DMA program, and + * execution result. + * + */ +typedef struct { + XDmaPs_ChanCtrl ChanCtrl; /**< Channel Control Struct */ + XDmaPs_BD BD; /**< Together with SgLength field, + * it's a scatter-gather list. + */ + void *UserDmaProg; /**< If user wants the driver to + * execute their own DMA program, + * this field points to the DMA + * program. + */ + int UserDmaProgLength; /**< The length of user defined + * DMA program. + */ + + void *GeneratedDmaProg; /**< The DMA program genreated + * by the driver. This field will be + * set if a user invokes the DMA + * program generation function. Or + * the DMA command is finished and + * a user informs the driver not to + * release the program buffer. + * This field has two purposes, one + * is to ask the driver to generate + * a DMA program while the DMAC is + * performaning DMA transactions. The + * other purpose is to debug the + * driver. + */ + int GeneratedDmaProgLength; /**< The length of the DMA program + * generated by the driver + */ + int DmaStatus; /**< 0 on success, otherwise error code + */ + u32 ChanFaultType; /**< Channel fault type in case of fault + */ + u32 ChanFaultPCAddr; /**< Channel fault PC address + */ +} XDmaPs_Cmd; + +/** + * It's the done handler a user can set for a channel + */ +typedef void (*XDmaPsDoneHandler) (unsigned int Channel, + XDmaPs_Cmd *DmaCmd, + void *CallbackRef); + +/** + * It's the fault handler a user can set for a channel + */ +typedef void (*XDmaPsFaultHandler) (unsigned int Channel, + XDmaPs_Cmd *DmaCmd, + void *CallbackRef); + +#define XDMAPS_MAX_CHAN_BUFS 2 +#define XDMAPS_CHAN_BUF_LEN 128 + +/** + * The XDmaPs_ProgBuf is the struct for a DMA program buffer. + */ +typedef struct { + char Buf[XDMAPS_CHAN_BUF_LEN]; /**< The actual buffer the holds the + * content */ + unsigned Len; /**< The actual length of the DMA + * program in bytes. */ + int Allocated; /**< A tag indicating whether the + * buffer is allocated or not */ +} XDmaPs_ProgBuf; + +/** + * The XDmaPs_ChannelData is a struct to book keep individual channel of + * the DMAC. + */ +typedef struct { + unsigned DevId; /**< Device id indicating which DMAC */ + unsigned ChanId; /**< Channel number of the DMAC */ + XDmaPs_ProgBuf ProgBufPool[XDMAPS_MAX_CHAN_BUFS]; /**< A pool of + program buffers*/ + XDmaPsDoneHandler DoneHandler; /**< Done interrupt handler */ + void *DoneRef; /**< Done interrupt callback data */ + XDmaPs_Cmd *DmaCmdToHw; /**< DMA command being executed */ + XDmaPs_Cmd *DmaCmdFromHw; /**< DMA command that is finished. + * This field is for debugging purpose + */ + int HoldDmaProg; /**< A tag indicating whether to hold the + * DMA program after the DMA is done. + */ + +} XDmaPs_ChannelData; + +/** + * The XDmaPs driver instance data structure. A pointer to an instance data + * structure is passed around by functions to refer to a specific driver + * instance. + */ +typedef struct { + XDmaPs_Config Config; /**< Configuration data structure */ + int IsReady; /**< Device is Ready */ + int CacheLength; /**< icache length */ + XDmaPsFaultHandler FaultHandler; /**< fault interrupt handler */ + void *FaultRef; /**< fault call back data */ + XDmaPs_ChannelData Chans[XDMAPS_CHANNELS_PER_DEV]; + /**< + * channel data + */ +} XDmaPs; + +/* + * Functions implemented in xdmaps.c + */ +int XDmaPs_CfgInitialize(XDmaPs *InstPtr, + XDmaPs_Config *Config, + u32 EffectiveAddr); + +int XDmaPs_Start(XDmaPs *InstPtr, unsigned int Channel, + XDmaPs_Cmd *Cmd, + int HoldDmaProg); + +int XDmaPs_IsActive(XDmaPs *InstPtr, unsigned int Channel); +int XDmaPs_GenDmaProg(XDmaPs *InstPtr, unsigned int Channel, + XDmaPs_Cmd *Cmd); +int XDmaPs_FreeDmaProg(XDmaPs *InstPtr, unsigned int Channel, + XDmaPs_Cmd *Cmd); +void XDmaPs_Print_DmaProg(XDmaPs_Cmd *Cmd); + + +int XDmaPs_ResetManager(XDmaPs *InstPtr); +int XDmaPs_ResetChannel(XDmaPs *InstPtr, unsigned int Channel); + + +int XDmaPs_SetDoneHandler(XDmaPs *InstPtr, + unsigned Channel, + XDmaPsDoneHandler DoneHandler, + void *CallbackRef); + +int XDmaPs_SetFaultHandler(XDmaPs *InstPtr, + XDmaPsFaultHandler FaultHandler, + void *CallbackRef); + +void XDmaPs_Print_DmaProg(XDmaPs_Cmd *Cmd); +int XDmaPs_Instr_DMARMB(char *DmaProg); +int XDmaPs_Instr_DMAWMB(char *DmaProg); + +/** + * To avoid linking error,Declare all inline functions as extern for + * IAR compiler + */ +#ifdef __ICCARM__ +extern INLINE int XDmaPs_Instr_DMAEND(char *DmaProg); +extern INLINE void XDmaPs_Memcpy4(char *Dst, char *Src); +extern INLINE int XDmaPs_Instr_DMAGO(char *DmaProg, unsigned int Cn, + u32 Imm, unsigned int Ns); +extern INLINE int XDmaPs_Instr_DMALD(char *DmaProg); +extern INLINE int XDmaPs_Instr_DMALP(char *DmaProg, unsigned Lc, + unsigned LoopIterations); +extern INLINE int XDmaPs_Instr_DMALPEND(char *DmaProg, char *BodyStart, unsigned Lc); +extern INLINE int XDmaPs_Instr_DMAMOV(char *DmaProg, unsigned Rd, u32 Imm); +extern INLINE int XDmaPs_Instr_DMANOP(char *DmaProg); +extern INLINE int XDmaPs_Instr_DMASEV(char *DmaProg, unsigned int EventNumber); +extern INLINE int XDmaPs_Instr_DMAST(char *DmaProg); +extern INLINE unsigned XDmaPs_ToEndianSwapSizeBits(unsigned int EndianSwapSize); +extern INLINE unsigned XDmaPs_ToBurstSizeBits(unsigned BurstSize); +#endif + +/** + * Driver done interrupt service routines for the channels. + * We need this done ISR mainly because the driver needs to release the + * DMA program buffer. This is the one that connects the GIC + */ +void XDmaPs_DoneISR_0(XDmaPs *InstPtr); +void XDmaPs_DoneISR_1(XDmaPs *InstPtr); +void XDmaPs_DoneISR_2(XDmaPs *InstPtr); +void XDmaPs_DoneISR_3(XDmaPs *InstPtr); +void XDmaPs_DoneISR_4(XDmaPs *InstPtr); +void XDmaPs_DoneISR_5(XDmaPs *InstPtr); +void XDmaPs_DoneISR_6(XDmaPs *InstPtr); +void XDmaPs_DoneISR_7(XDmaPs *InstPtr); + +/** + * Driver fault interrupt service routine + */ +void XDmaPs_FaultISR(XDmaPs *InstPtr); + + +/* + * Static loopup function implemented in xdmaps_sinit.c + */ +XDmaPs_Config *XDmaPs_LookupConfig(u16 DeviceId); + + +/* + * self-test functions in xdmaps_selftest.c + */ +int XDmaPs_SelfTest(XDmaPs *InstPtr); + + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/include/xdmaps_hw.h b/datalink814_ge/bsp/ps7_cortexa9_0/include/xdmaps_hw.h new file mode 100644 index 0000000..42dfe69 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/include/xdmaps_hw.h @@ -0,0 +1,289 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xdmaps_hw.h +* @addtogroup dmaps_v2_4 +* @{ +* +* This header file contains the hardware interface of an XDmaPs device. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who   Date     Changes
+* ----- ----  -------- ----------------------------------------------
+* 1.00a	hbm   08/18/10 First Release
+* 1.01a nm    12/20/12 Added definition XDMAPS_CHANNELS_PER_DEV which specifies
+*		       the maximum number of channels.
+*		       Replaced the usage of XPAR_XDMAPS_CHANNELS_PER_DEV
+*                      with XDMAPS_CHANNELS_PER_DEV defined in xdmaps_hw.h
+* 1.02a sg    05/16/12 Made changes for doxygen
+* 1.06a kpc   07/10/13 Added function prototype
+* 
+* +******************************************************************************/ + +#ifndef XDMAPS_HW_H /* prevent circular inclusions */ +#define XDMAPS_HW_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_io.h" + +/************************** Constant Definitions *****************************/ + +/** @name Register Map + * + * Register offsets for the DMAC. + * @{ + */ + +#define XDMAPS_DS_OFFSET 0x000 /* DMA Status Register */ +#define XDMAPS_DPC_OFFSET 0x004 /* DMA Program Counter Rregister */ +#define XDMAPS_INTEN_OFFSET 0X020 /* DMA Interrupt Enable Register */ +#define XDMAPS_ES_OFFSET 0x024 /* DMA Event Status Register */ +#define XDMAPS_INTSTATUS_OFFSET 0x028 /* DMA Interrupt Status Register + */ +#define XDMAPS_INTCLR_OFFSET 0x02c /* DMA Interrupt Clear Register */ +#define XDMAPS_FSM_OFFSET 0x030 /* DMA Fault Status DMA Manager + * Register + */ +#define XDMAPS_FSC_OFFSET 0x034 /* DMA Fault Status DMA Chanel Register + */ +#define XDMAPS_FTM_OFFSET 0x038 /* DMA Fault Type DMA Manager Register */ + +#define XDMAPS_FTC0_OFFSET 0x040 /* DMA Fault Type for DMA Channel 0 */ +/* + * The offset for the rest of the FTC registers is calculated as + * FTC0 + dev_chan_num * 4 + */ +#define XDmaPs_FTCn_OFFSET(ch) (XDMAPS_FTC0_OFFSET + (ch) * 4) + +#define XDMAPS_CS0_OFFSET 0x100 /* Channel Status for DMA Channel 0 */ +/* + * The offset for the rest of the CS registers is calculated as + * CS0 + * dev_chan_num * 0x08 + */ +#define XDmaPs_CSn_OFFSET(ch) (XDMAPS_CS0_OFFSET + (ch) * 8) + +#define XDMAPS_CPC0_OFFSET 0x104 /* Channel Program Counter for DMA + * Channel 0 + */ +/* + * The offset for the rest of the CPC registers is calculated as + * CPC0 + dev_chan_num * 0x08 + */ +#define XDmaPs_CPCn_OFFSET(ch) (XDMAPS_CPC0_OFFSET + (ch) * 8) + +#define XDMAPS_SA_0_OFFSET 0x400 /* Source Address Register for DMA + * Channel 0 + */ +/* The offset for the rest of the SA registers is calculated as + * SA_0 + dev_chan_num * 0x20 + */ +#define XDmaPs_SA_n_OFFSET(ch) (XDMAPS_SA_0_OFFSET + (ch) * 0x20) + +#define XDMAPS_DA_0_OFFSET 0x404 /* Destination Address Register for + * DMA Channel 0 + */ +/* The offset for the rest of the DA registers is calculated as + * DA_0 + dev_chan_num * 0x20 + */ +#define XDmaPs_DA_n_OFFSET(ch) (XDMAPS_DA_0_OFFSET + (ch) * 0x20) + +#define XDMAPS_CC_0_OFFSET 0x408 /* Channel Control Register for + * DMA Channel 0 + */ +/* + * The offset for the rest of the CC registers is calculated as + * CC_0 + dev_chan_num * 0x20 + */ +#define XDmaPs_CC_n_OFFSET(ch) (XDMAPS_CC_0_OFFSET + (ch) * 0x20) + +#define XDMAPS_LC0_0_OFFSET 0x40C /* Loop Counter 0 for DMA Channel 0 */ +/* + * The offset for the rest of the LC0 registers is calculated as + * LC_0 + dev_chan_num * 0x20 + */ +#define XDmaPs_LC0_n_OFFSET(ch) (XDMAPS_LC0_0_OFFSET + (ch) * 0x20) +#define XDMAPS_LC1_0_OFFSET 0x410 /* Loop Counter 1 for DMA Channel 0 */ +/* + * The offset for the rest of the LC1 registers is calculated as + * LC_0 + dev_chan_num * 0x20 + */ +#define XDmaPs_LC1_n_OFFSET(ch) (XDMAPS_LC1_0_OFFSET + (ch) * 0x20) + +#define XDMAPS_DBGSTATUS_OFFSET 0xD00 /* Debug Status Register */ +#define XDMAPS_DBGCMD_OFFSET 0xD04 /* Debug Command Register */ +#define XDMAPS_DBGINST0_OFFSET 0xD08 /* Debug Instruction 0 Register */ +#define XDMAPS_DBGINST1_OFFSET 0xD0C /* Debug Instruction 1 Register */ + +#define XDMAPS_CR0_OFFSET 0xE00 /* Configuration Register 0 */ +#define XDMAPS_CR1_OFFSET 0xE04 /* Configuration Register 1 */ +#define XDMAPS_CR2_OFFSET 0xE08 /* Configuration Register 2 */ +#define XDMAPS_CR3_OFFSET 0xE0C /* Configuration Register 3 */ +#define XDMAPS_CR4_OFFSET 0xE10 /* Configuration Register 4 */ +#define XDMAPS_CRDN_OFFSET 0xE14 /* Configuration Register Dn */ + +#define XDMAPS_PERIPH_ID_0_OFFSET 0xFE0 /* Peripheral Identification + * Register 0 + */ +#define XDMAPS_PERIPH_ID_1_OFFSET 0xFE4 /* Peripheral Identification + * Register 1 + */ +#define XDMAPS_PERIPH_ID_2_OFFSET 0xFE8 /* Peripheral Identification + * Register 2 + */ +#define XDMAPS_PERIPH_ID_3_OFFSET 0xFEC /* Peripheral Identification + * Register 3 + */ +#define XDMAPS_PCELL_ID_0_OFFSET 0xFF0 /* PrimeCell Identification + * Register 0 + */ +#define XDMAPS_PCELL_ID_1_OFFSET 0xFF4 /* PrimeCell Identification + * Register 1 + */ +#define XDMAPS_PCELL_ID_2_OFFSET 0xFF8 /* PrimeCell Identification + * Register 2 + */ +#define XDMAPS_PCELL_ID_3_OFFSET 0xFFC /* PrimeCell Identification + * Register 3 + */ + +/* + * Some useful register masks + */ +#define XDMAPS_DS_DMA_STATUS 0x0F /* DMA status mask */ +#define XDMAPS_DS_DMA_STATUS_STOPPED 0x00 /* debug status busy mask */ + +#define XDMAPS_DBGSTATUS_BUSY 0x01 /* debug status busy mask */ + +#define XDMAPS_CS_ACTIVE_MASK 0x07 /* channel status active mask, + * llast 3 bits of CS register + */ + +#define XDMAPS_CR1_I_CACHE_LEN_MASK 0x07 /* i_cache_len mask */ + + +/* + * XDMAPS_DBGINST0 - constructs the word for the Debug Instruction-0 Register. + * @b1: Instruction byte 1 + * @b0: Instruction byte 0 + * @ch: Channel number + * @dbg_th: Debug thread encoding: 0 = DMA manager thread, 1 = DMA channel + */ +#define XDmaPs_DBGINST0(b1, b0, ch, dbg_th) \ + (((b1) << 24) | ((b0) << 16) | (((ch) & 0x7) << 8) | ((dbg_th & 0x1))) + +/* @} */ + +/** @name Control Register + * + * The Control register (CR) controls the major functions of the device. + * + * Control Register Bit Definition + */ + +/* @}*/ + + +#define XDMAPS_CHANNELS_PER_DEV 8 + + +/** @name Mode Register + * + * The mode register (MR) defines the mode of transfer as well as the data + * format. If this register is modified during transmission or reception, + * data validity cannot be guaranteed. + * + * Mode Register Bit Definition + * @{ + */ + +/* @} */ + + +/** @name Interrupt Registers + * + * Interrupt control logic uses the interrupt enable register (IER) and the + * interrupt disable register (IDR) to set the value of the bits in the + * interrupt mask register (IMR). The IMR determines whether to pass an + * interrupt to the interrupt status register (ISR). + * Writing a 1 to IER Enbables an interrupt, writing a 1 to IDR disables an + * interrupt. IMR and ISR are read only, and IER and IDR are write only. + * Reading either IER or IDR returns 0x00. + * + * All four registers have the same bit definitions. + * + * @{ + */ + +/* @} */ +#define XDMAPS_INTCLR_ALL_MASK 0xFF + +#define XDmaPs_ReadReg(BaseAddress, RegOffset) \ + Xil_In32((BaseAddress) + (RegOffset)) + +/***************************************************************************/ +/** +* Write a DMAC register. +* +* @param BaseAddress contains the base address of the device. +* @param RegOffset contains the offset from the base address of the device. +* @param RegisterValue is the value to be written to the register. +* +* @return None. +* +* @note +* C-Style signature: +* void XDmaPs_WriteReg(u32 BaseAddress, int RegOffset, +* u32 RegisterValue) +******************************************************************************/ +#define XDmaPs_WriteReg(BaseAddress, RegOffset, RegisterValue) \ + Xil_Out32((BaseAddress) + (RegOffset), (RegisterValue)) +/************************** Variable Definitions *****************************/ + +/************************** Function Prototypes *****************************/ +/* + * Perform reset operation to the dmaps interface + */ +void XDmaPs_ResetHw(u32 BaseAddr); +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/include/xenv.h b/datalink814_ge/bsp/ps7_cortexa9_0/include/xenv.h new file mode 100644 index 0000000..9c7c4c3 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/include/xenv.h @@ -0,0 +1,183 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xenv.h +* +* Defines common services that are typically found in a host operating. +* environment. This include file simply includes an OS specific file based +* on the compile-time constant BUILD_ENV_*, where * is the name of the target +* environment. +* +* All services are defined as macros. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00b ch   10/24/02 Added XENV_LINUX
+* 1.00a rmm  04/17/02 First release
+* 
+* +******************************************************************************/ + +#ifndef XENV_H /* prevent circular inclusions */ +#define XENV_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Select which target environment we are operating under + */ + +/* VxWorks target environment */ +#if defined XENV_VXWORKS +#include "xenv_vxworks.h" + +/* Linux target environment */ +#elif defined XENV_LINUX +#include "xenv_linux.h" + +/* Unit test environment */ +#elif defined XENV_UNITTEST +#include "ut_xenv.h" + +/* Integration test environment */ +#elif defined XENV_INTTEST +#include "int_xenv.h" + +/* Standalone environment selected */ +#else +#include "xenv_standalone.h" +#endif + + +/* + * The following comments specify the types and macro wrappers that are + * expected to be defined by the target specific header files + */ + +/**************************** Type Definitions *******************************/ + +/*****************************************************************************/ +/** + * + * XENV_TIME_STAMP + * + * A structure that contains a time stamp used by other time stamp macros + * defined below. This structure is processor dependent. + */ + + +/***************** Macros (Inline Functions) Definitions *********************/ + +/*****************************************************************************/ +/** + * + * XENV_MEM_COPY(void *DestPtr, void *SrcPtr, unsigned Bytes) + * + * Copies a non-overlapping block of memory. + * + * @param DestPtr is the destination address to copy data to. + * @param SrcPtr is the source address to copy data from. + * @param Bytes is the number of bytes to copy. + * + * @return None + */ + +/*****************************************************************************/ +/** + * + * XENV_MEM_FILL(void *DestPtr, char Data, unsigned Bytes) + * + * Fills an area of memory with constant data. + * + * @param DestPtr is the destination address to set. + * @param Data contains the value to set. + * @param Bytes is the number of bytes to set. + * + * @return None + */ +/*****************************************************************************/ +/** + * + * XENV_TIME_STAMP_GET(XTIME_STAMP *StampPtr) + * + * Samples the processor's or external timer's time base counter. + * + * @param StampPtr is the storage for the retrieved time stamp. + * + * @return None + */ + +/*****************************************************************************/ +/** + * + * XENV_TIME_STAMP_DELTA_US(XTIME_STAMP *Stamp1Ptr, XTIME_STAMP* Stamp2Ptr) + * + * Computes the delta between the two time stamps. + * + * @param Stamp1Ptr - First sampled time stamp. + * @param Stamp1Ptr - Sedond sampled time stamp. + * + * @return An unsigned int value with units of microseconds. + */ + +/*****************************************************************************/ +/** + * + * XENV_TIME_STAMP_DELTA_MS(XTIME_STAMP *Stamp1Ptr, XTIME_STAMP* Stamp2Ptr) + * + * Computes the delta between the two time stamps. + * + * @param Stamp1Ptr - First sampled time stamp. + * @param Stamp1Ptr - Sedond sampled time stamp. + * + * @return An unsigned int value with units of milliseconds. + */ + +/*****************************************************************************//** + * + * XENV_USLEEP(unsigned delay) + * + * Delay the specified number of microseconds. + * + * @param delay is the number of microseconds to delay. + * + * @return None + */ + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/include/xenv_standalone.h b/datalink814_ge/bsp/ps7_cortexa9_0/include/xenv_standalone.h new file mode 100644 index 0000000..ef905af --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/include/xenv_standalone.h @@ -0,0 +1,364 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xenv_standalone.h +* +* Defines common services specified by xenv.h. +* +* @note +* This file is not intended to be included directly by driver code. +* Instead, the generic xenv.h file is intended to be included by driver +* code. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a wgr  02/28/07 Added cache handling macros.
+* 1.00a wgr  02/27/07 Simplified code. Deprecated old-style macro names.
+* 1.00a rmm  01/24/06 Implemented XENV_USLEEP. Assume implementation is being
+*                     used under Xilinx standalone BSP.
+* 1.00a xd   11/03/04 Improved support for doxygen.
+* 1.00a rmm  03/21/02 First release
+* 1.00a wgr  03/22/07 Converted to new coding style.
+* 1.00a rpm  06/29/07 Added udelay macro for standalone
+* 1.00a xd   07/19/07 Included xparameters.h as XPAR_ constants are referred
+*                     to in MICROBLAZE section
+* 1.00a ecm  09/19/08 updated for v7.20 of Microblaze, new functionality
+*
+* 
+* +* +******************************************************************************/ + +#ifndef XENV_STANDALONE_H +#define XENV_STANDALONE_H + +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ +/****************************************************************************** + * + * Get the processor dependent includes + * + ******************************************************************************/ + +#include + +#if defined __MICROBLAZE__ +# include "mb_interface.h" +# include "xparameters.h" /* XPAR constants used below in MB section */ + +#elif defined __PPC__ +# include "sleep.h" +# include "xcache_l.h" /* also include xcache_l.h for caching macros */ +#endif + +/****************************************************************************** + * + * MEMCPY / MEMSET related macros. + * + * The following are straight forward implementations of memset and memcpy. + * + * NOTE: memcpy may not work if source and target memory area are overlapping. + * + ******************************************************************************/ +/*****************************************************************************/ +/** + * + * Copies a non-overlapping block of memory. + * + * @param DestPtr + * Destination address to copy data to. + * + * @param SrcPtr + * Source address to copy data from. + * + * @param Bytes + * Number of bytes to copy. + * + * @return None. + * + * @note + * The use of XENV_MEM_COPY is deprecated. Use memcpy() instead. + * + * @note + * This implemention MAY BREAK work if source and target memory + * area are overlapping. + * + *****************************************************************************/ + +#define XENV_MEM_COPY(DestPtr, SrcPtr, Bytes) \ + memcpy((void *) DestPtr, (const void *) SrcPtr, (size_t) Bytes) + + + +/*****************************************************************************/ +/** + * + * Fills an area of memory with constant data. + * + * @param DestPtr + * Destination address to copy data to. + * + * @param Data + * Value to set. + * + * @param Bytes + * Number of bytes to copy. + * + * @return None. + * + * @note + * The use of XENV_MEM_FILL is deprecated. Use memset() instead. + * + *****************************************************************************/ + +#define XENV_MEM_FILL(DestPtr, Data, Bytes) \ + memset((void *) DestPtr, (s32) Data, (size_t) Bytes) + + + +/****************************************************************************** + * + * TIME related macros + * + ******************************************************************************/ + +/** + * A structure that contains a time stamp used by other time stamp macros + * defined below. This structure is processor dependent. + */ +typedef s32 XENV_TIME_STAMP; + +/*****************************************************************************/ +/** + * + * Time is derived from the 64 bit PPC timebase register + * + * @param StampPtr is the storage for the retrieved time stamp. + * + * @return None. + * + * @note + * + * Signature: void XENV_TIME_STAMP_GET(XTIME_STAMP *StampPtr) + *

+ * This macro must be implemented by the user. + * + *****************************************************************************/ +#define XENV_TIME_STAMP_GET(StampPtr) + +/*****************************************************************************/ +/** + * + * This macro is not yet implemented and always returns 0. + * + * @param Stamp1Ptr is the first sampled time stamp. + * @param Stamp2Ptr is the second sampled time stamp. + * + * @return 0 + * + * @note + * + * This macro must be implemented by the user. + * + *****************************************************************************/ +#define XENV_TIME_STAMP_DELTA_US(Stamp1Ptr, Stamp2Ptr) (0) + +/*****************************************************************************/ +/** + * + * This macro is not yet implemented and always returns 0. + * + * @param Stamp1Ptr is the first sampled time stamp. + * @param Stamp2Ptr is the second sampled time stamp. + * + * @return 0 + * + * @note + * + * This macro must be implemented by the user. + * + *****************************************************************************/ +#define XENV_TIME_STAMP_DELTA_MS(Stamp1Ptr, Stamp2Ptr) (0) + +/*****************************************************************************/ +/** + * XENV_USLEEP(unsigned delay) + * + * Delay the specified number of microseconds. Not implemented without OS + * support. + * + * @param delay + * Number of microseconds to delay. + * + * @return None. + * + *****************************************************************************/ + +#ifdef __PPC__ +#define XENV_USLEEP(delay) usleep(delay) +#define udelay(delay) usleep(delay) +#else +#define XENV_USLEEP(delay) +#define udelay(delay) +#endif + + +/****************************************************************************** + * + * CACHE handling macros / mappings + * + ******************************************************************************/ +/****************************************************************************** + * + * Processor independent macros + * + ******************************************************************************/ + +#define XCACHE_ENABLE_CACHE() \ + { XCACHE_ENABLE_DCACHE(); XCACHE_ENABLE_ICACHE(); } + +#define XCACHE_DISABLE_CACHE() \ + { XCACHE_DISABLE_DCACHE(); XCACHE_DISABLE_ICACHE(); } + + +/****************************************************************************** + * + * MicroBlaze case + * + * NOTE: Currently the following macros will only work on systems that contain + * only ONE MicroBlaze processor. Also, the macros will only be enabled if the + * system is built using a xparameters.h file. + * + ******************************************************************************/ + +#if defined __MICROBLAZE__ + +/* Check if MicroBlaze data cache was built into the core. + */ +#if (XPAR_MICROBLAZE_USE_DCACHE == 1) +# define XCACHE_ENABLE_DCACHE() microblaze_enable_dcache() +# define XCACHE_DISABLE_DCACHE() microblaze_disable_dcache() +# define XCACHE_INVALIDATE_DCACHE() microblaze_invalidate_dcache() + +# define XCACHE_INVALIDATE_DCACHE_RANGE(Addr, Len) \ + microblaze_invalidate_dcache_range((s32)(Addr), (s32)(Len)) + +#if (XPAR_MICROBLAZE_DCACHE_USE_WRITEBACK == 1) +# define XCACHE_FLUSH_DCACHE() microblaze_flush_dcache() +# define XCACHE_FLUSH_DCACHE_RANGE(Addr, Len) \ + microblaze_flush_dcache_range((s32)(Addr), (s32)(Len)) +#else +# define XCACHE_FLUSH_DCACHE() microblaze_invalidate_dcache() +# define XCACHE_FLUSH_DCACHE_RANGE(Addr, Len) \ + microblaze_invalidate_dcache_range((s32)(Addr), (s32)(Len)) +#endif /*XPAR_MICROBLAZE_DCACHE_USE_WRITEBACK*/ + +#else +# define XCACHE_ENABLE_DCACHE() +# define XCACHE_DISABLE_DCACHE() +# define XCACHE_INVALIDATE_DCACHE_RANGE(Addr, Len) +# define XCACHE_FLUSH_DCACHE_RANGE(Addr, Len) +#endif /*XPAR_MICROBLAZE_USE_DCACHE*/ + + +/* Check if MicroBlaze instruction cache was built into the core. + */ +#if (XPAR_MICROBLAZE_USE_ICACHE == 1) +# define XCACHE_ENABLE_ICACHE() microblaze_enable_icache() +# define XCACHE_DISABLE_ICACHE() microblaze_disable_icache() + +# define XCACHE_INVALIDATE_ICACHE() microblaze_invalidate_icache() + +# define XCACHE_INVALIDATE_ICACHE_RANGE(Addr, Len) \ + microblaze_invalidate_icache_range((s32)(Addr), (s32)(Len)) + +#else +# define XCACHE_ENABLE_ICACHE() +# define XCACHE_DISABLE_ICACHE() +#endif /*XPAR_MICROBLAZE_USE_ICACHE*/ + + +/****************************************************************************** + * + * PowerPC case + * + * Note that the XCACHE_ENABLE_xxx functions are hardcoded to enable a + * specific memory region (0x80000001). Each bit (0-30) in the regions + * bitmask stands for 128MB of memory. Bit 31 stands for the upper 2GB + * range. + * + * regions --> cached address range + * ------------|-------------------------------------------------- + * 0x80000000 | [0, 0x7FFFFFF] + * 0x00000001 | [0xF8000000, 0xFFFFFFFF] + * 0x80000001 | [0, 0x7FFFFFF],[0xF8000000, 0xFFFFFFFF] + * + ******************************************************************************/ + +#elif defined __PPC__ + +#define XCACHE_ENABLE_DCACHE() XCache_EnableDCache(0x80000001) +#define XCACHE_DISABLE_DCACHE() XCache_DisableDCache() +#define XCACHE_ENABLE_ICACHE() XCache_EnableICache(0x80000001) +#define XCACHE_DISABLE_ICACHE() XCache_DisableICache() + +#define XCACHE_INVALIDATE_DCACHE_RANGE(Addr, Len) \ + XCache_InvalidateDCacheRange((u32)(Addr), (u32)(Len)) + +#define XCACHE_FLUSH_DCACHE_RANGE(Addr, Len) \ + XCache_FlushDCacheRange((u32)(Addr), (u32)(Len)) + +#define XCACHE_INVALIDATE_ICACHE() XCache_InvalidateICache() + + +/****************************************************************************** + * + * Unknown processor / architecture + * + ******************************************************************************/ + +#else +/* #error "Unknown processor / architecture. Must be MicroBlaze or PowerPC." */ +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* #ifndef XENV_STANDALONE_H */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/include/xgpio.h b/datalink814_ge/bsp/ps7_cortexa9_0/include/xgpio.h new file mode 100644 index 0000000..b498fe0 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/include/xgpio.h @@ -0,0 +1,211 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file xgpio.h +* @addtogroup gpio_v4_4 +* @{ +* @details +* +* This file contains the software API definition of the Xilinx General Purpose +* I/O (XGpio) device driver. +* +* The Xilinx GPIO controller is a soft IP core designed for Xilinx FPGAs and +* contains the following general features: +* - Support for up to 32 I/O discretes for each channel (64 bits total). +* - Each of the discretes can be configured for input or output. +* - Configurable support for dual channels and interrupt generation. +* +* The driver provides interrupt management functions. Implementation of +* interrupt handlers is left to the user. Refer to the provided interrupt +* example in the examples directory for details. +* +* This driver is intended to be RTOS and processor independent. Any needs for +* dynamic memory management, threads or thread mutual exclusion, virtual +* memory, or cache control must be satisfied by the layer above this driver. +* +* Initialization & Configuration +* +* The XGpio_Config structure is used by the driver to configure itself. This +* configuration structure is typically created by the tool-chain based on HW +* build properties. +* +* To support multiple runtime loading and initialization strategies employed +* by various operating systems, the driver instance can be initialized in one +* of the following ways: +* +* - XGpio_Initialize(InstancePtr, DeviceId) - The driver looks up its own +* configuration structure created by the tool-chain based on an ID provided +* by the tool-chain. +* +* - XGpio_CfgInitialize(InstancePtr, CfgPtr, EffectiveAddr) - Uses a +* configuration structure provided by the caller. If running in a system +* with address translation, the provided virtual memory base address +* replaces the physical address present in the configuration structure. +* +* @note +* +* This API utilizes 32 bit I/O to the GPIO registers. With less than 32 bits, +* the unused bits from registers are read as zero and written as don't cares. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a rmm  03/13/02 First release
+* 2.00a jhl  11/26/03 Added support for dual channels and interrupts
+* 2.01a jvb  12/14/05 I separated dependency on the static config table and
+*                     xparameters.h from the driver initialization by moving
+*                     _Initialize and _LookupConfig to _sinit.c. I also added
+*                     the new _CfgInitialize routine.
+* 2.11a mta  03/21/07 Updated to new coding style, added GetDataDirection
+* 2.12a sv   11/21/07 Updated driver to support access through DCR bus
+* 2.12a sv   06/05/08 Updated driver to fix the XGpio_InterruptDisable function
+*		      to properly update the Interrupt Enable register
+* 2.13a sdm  08/22/08 Removed support for static interrupt handlers from the MDD
+*		      file
+* 3.00a sv   11/21/09 Updated to use HAL Processor APIs.
+*		      Renamed the macros XGpio_mWriteReg to XGpio_WriteReg and
+*		      XGpio_mReadReg to XGpio_ReadReg. Removed the macros
+*		      XGpio_mSetDataDirection, XGpio_mGetDataReg and
+*		      XGpio_mSetDataReg. Users should use XGpio_WriteReg and
+*		      XGpio_ReadReg to achieve the same functionality.
+* 3.01a bss  04/18/13 Updated driver tcl to generate Canonical params in
+*		      xparameters.h. CR#698589
+* 4.0   adk  19/12/13 Updated as per the New Tcl API's
+* 4.1   lks  11/18/15 Updated to use cannonical xparameters in examples and
+*		      clean up of the comments, removed support for DCR bridge
+*		      and removed xgpio_intr_example for CR 900381
+* 4.2   sk   08/16/16 Used UINTPTR instead of u32 for Baseaddress as part of
+*                     adding 64 bit support. CR# 867425.
+*                     Changed the prototype of XGpio_CfgInitialize API.
+* 4.3   sk   09/29/16 Modified the example to make it work when LED_bits are
+*                     configured as an output. CR# 958644
+*       ms   01/23/17 Added xil_printf statement in main function for all
+*                     examples to ensure that "Successfully ran" and "Failed"
+*                     strings are available in all examples. This is a fix
+*                     for CR-965028.
+*       ms   03/17/17 Added readme.txt file in examples folder for doxygen
+*                     generation.
+* 4.4   sne  04/25/19 Updated Makefile for IAR compier (CR-1029421).
+*
+* 
+*****************************************************************************/ + +#ifndef XGPIO_H /* prevent circular inclusions */ +#define XGPIO_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files ********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xstatus.h" +#include "xgpio_l.h" + +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + +/** + * This typedef contains configuration information for the device. + */ +typedef struct { + u16 DeviceId; /* Unique ID of device */ + UINTPTR BaseAddress; /* Device base address */ + int InterruptPresent; /* Are interrupts supported in h/w */ + int IsDual; /* Are 2 channels supported in h/w */ +} XGpio_Config; + +/** + * The XGpio driver instance data. The user is required to allocate a + * variable of this type for every GPIO device in the system. A pointer + * to a variable of this type is then passed to the driver API functions. + */ +typedef struct { + UINTPTR BaseAddress; /* Device base address */ + u32 IsReady; /* Device is initialized and ready */ + int InterruptPresent; /* Are interrupts supported in h/w */ + int IsDual; /* Are 2 channels supported in h/w */ +} XGpio; + +/***************** Macros (Inline Functions) Definitions ********************/ + + +/************************** Function Prototypes *****************************/ + +/* + * Initialization functions in xgpio_sinit.c + */ +int XGpio_Initialize(XGpio *InstancePtr, u16 DeviceId); +XGpio_Config *XGpio_LookupConfig(u16 DeviceId); + +/* + * API Basic functions implemented in xgpio.c + */ +int XGpio_CfgInitialize(XGpio *InstancePtr, XGpio_Config * Config, + UINTPTR EffectiveAddr); +void XGpio_SetDataDirection(XGpio *InstancePtr, unsigned Channel, + u32 DirectionMask); +u32 XGpio_GetDataDirection(XGpio *InstancePtr, unsigned Channel); +u32 XGpio_DiscreteRead(XGpio *InstancePtr, unsigned Channel); +void XGpio_DiscreteWrite(XGpio *InstancePtr, unsigned Channel, u32 Mask); + + +/* + * API Functions implemented in xgpio_extra.c + */ +void XGpio_DiscreteSet(XGpio *InstancePtr, unsigned Channel, u32 Mask); +void XGpio_DiscreteClear(XGpio *InstancePtr, unsigned Channel, u32 Mask); + +/* + * API Functions implemented in xgpio_selftest.c + */ +int XGpio_SelfTest(XGpio *InstancePtr); + +/* + * API Functions implemented in xgpio_intr.c + */ +void XGpio_InterruptGlobalEnable(XGpio *InstancePtr); +void XGpio_InterruptGlobalDisable(XGpio *InstancePtr); +void XGpio_InterruptEnable(XGpio *InstancePtr, u32 Mask); +void XGpio_InterruptDisable(XGpio *InstancePtr, u32 Mask); +void XGpio_InterruptClear(XGpio *InstancePtr, u32 Mask); +u32 XGpio_InterruptGetEnabled(XGpio *InstancePtr); +u32 XGpio_InterruptGetStatus(XGpio *InstancePtr); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/include/xgpio_i.h b/datalink814_ge/bsp/ps7_cortexa9_0/include/xgpio_i.h new file mode 100644 index 0000000..7938b0f --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/include/xgpio_i.h @@ -0,0 +1,83 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/******************************************************************************/ +/** +* @file xgpio_i.h +* @addtogroup gpio_v4_3 +* @{ +* +* This header file contains internal identifiers, which are those shared +* between the files of the driver. It is intended for internal use only. +* +* NOTES: +* +* None. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a rmm  03/13/02 First release
+* 2.11a mta  03/21/07 Updated to new coding style
+* 
+******************************************************************************/ + +#ifndef XGPIO_I_H /* prevent circular inclusions */ +#define XGPIO_I_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xgpio.h" + +/************************** Constant Definitions ****************************/ + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + + +/************************** Variable Definitions ****************************/ + +extern XGpio_Config XGpio_ConfigTable[]; + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/include/xgpio_l.h b/datalink814_ge/bsp/ps7_cortexa9_0/include/xgpio_l.h new file mode 100644 index 0000000..be6d04a --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/include/xgpio_l.h @@ -0,0 +1,189 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xgpio_l.h +* @addtogroup gpio_v4_4 +* @{ +* +* This header file contains identifiers and driver functions (or +* macros) that can be used to access the device. The user should refer to the +* hardware device specification for more details of the device operation. +* +* The macros that are available in this file use a multiply to calculate the +* addresses of registers. The user can control whether that multiply is done +* at run time or at compile time. A constant passed as the channel parameter +* will cause the multiply to be done at compile time. A variable passed as the +* channel parameter will cause it to occur at run time. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a jhl  04/24/02 First release of low level driver
+* 2.00a jhl  11/26/03 Added support for dual channels and interrupts. This
+*                     change required the functions to be changed such that
+*                     the interface is not compatible with previous versions.
+*                     See the examples in the example directory for macros
+*                     to help compile an application that was designed for
+*                     previous versions of the driver. The interrupt registers
+*                     are accessible using the ReadReg and WriteReg macros and
+*                     a channel parameter was added to the other macros.
+* 2.11a mta  03/21/07 Updated to new coding style
+* 2.12a sv   11/21/07 Updated driver to support access through DCR bus.
+* 3.00a sv   11/21/09 Renamed the macros XGpio_mWriteReg to XGpio_WriteReg
+*		      XGpio_mReadReg to XGpio_ReadReg.
+*		      Removed the macros XGpio_mSetDataDirection,
+*		      XGpio_mGetDataReg and XGpio_mSetDataReg. Users
+*		      should use XGpio_WriteReg/XGpio_ReadReg to achieve the
+*		      same functionality.
+* 4.1  lks   11/18/15 Removed support for DCR bridge
+* 
+* +******************************************************************************/ + +#ifndef XGPIO_L_H /* prevent circular inclusions */ +#define XGPIO_L_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_io.h" + + +/************************** Constant Definitions *****************************/ + +/** @name Registers + * + * Register offsets for this device. + * @{ + */ +#define XGPIO_DATA_OFFSET 0x0 /**< Data register for 1st channel */ +#define XGPIO_TRI_OFFSET 0x4 /**< I/O direction reg for 1st channel */ +#define XGPIO_DATA2_OFFSET 0x8 /**< Data register for 2nd channel */ +#define XGPIO_TRI2_OFFSET 0xC /**< I/O direction reg for 2nd channel */ + +#define XGPIO_GIE_OFFSET 0x11C /**< Glogal interrupt enable register */ +#define XGPIO_ISR_OFFSET 0x120 /**< Interrupt status register */ +#define XGPIO_IER_OFFSET 0x128 /**< Interrupt enable register */ + +/* @} */ + +/* The following constant describes the offset of each channels data and + * tristate register from the base address. + */ +#define XGPIO_CHAN_OFFSET 8 + +/** @name Interrupt Status and Enable Register bitmaps and masks + * + * Bit definitions for the interrupt status register and interrupt enable + * registers. + * @{ + */ +#define XGPIO_IR_MASK 0x3 /**< Mask of all bits */ +#define XGPIO_IR_CH1_MASK 0x1 /**< Mask for the 1st channel */ +#define XGPIO_IR_CH2_MASK 0x2 /**< Mask for the 2nd channel */ +/*@}*/ + + +/** @name Global Interrupt Enable Register bitmaps and masks + * + * Bit definitions for the Global Interrupt Enable register + * @{ + */ +#define XGPIO_GIE_GINTR_ENABLE_MASK 0x80000000 +/*@}*/ + + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + +#define XGpio_In32 Xil_In32 +#define XGpio_Out32 Xil_Out32 + + +/****************************************************************************/ +/** +* +* Write a value to a GPIO register. A 32 bit write is performed. If the +* GPIO core is implemented in a smaller width, only the least significant data +* is written. +* +* @param BaseAddress is the base address of the GPIO device. +* @param RegOffset is the register offset from the base to write to. +* @param Data is the data written to the register. +* +* @return None. +* +* @note C-style signature: +* void XGpio_WriteReg(u32 BaseAddress, u32 RegOffset, u32 Data) +* +****************************************************************************/ +#define XGpio_WriteReg(BaseAddress, RegOffset, Data) \ + XGpio_Out32((BaseAddress) + (RegOffset), (u32)(Data)) + +/****************************************************************************/ +/** +* +* Read a value from a GPIO register. A 32 bit read is performed. If the +* GPIO core is implemented in a smaller width, only the least +* significant data is read from the register. The most significant data +* will be read as 0. +* +* @param BaseAddress is the base address of the GPIO device. +* @param RegOffset is the register offset from the base to read from. +* +* @return Data read from the register. +* +* @note C-style signature: +* u32 XGpio_ReadReg(u32 BaseAddress, u32 RegOffset) +* +****************************************************************************/ +#define XGpio_ReadReg(BaseAddress, RegOffset) \ + XGpio_In32((BaseAddress) + (RegOffset)) + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/include/xgpiops.h b/datalink814_ge/bsp/ps7_cortexa9_0/include/xgpiops.h new file mode 100644 index 0000000..d0ff132 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/include/xgpiops.h @@ -0,0 +1,283 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xgpiops.h +* @addtogroup gpiops_v3_5 +* @{ +* @details +* +* The Xilinx PS GPIO driver. This driver supports the Xilinx PS GPIO +* Controller. +* +* The GPIO Controller supports the following features: +* - 4 banks +* - Masked writes (There are no masked reads) +* - Bypass mode +* - Configurable Interrupts (Level/Edge) +* +* This driver is intended to be RTOS and processor independent. Any needs for +* dynamic memory management, threads or thread mutual exclusion, virtual +* memory, or cache control must be satisfied by the layer above this driver. + +* This driver supports all the features listed above, if applicable. +* +* Driver Description +* +* The device driver enables higher layer software (e.g., an application) to +* communicate to the GPIO. +* +* Interrupts +* +* The driver provides interrupt management functions and an interrupt handler. +* Users of this driver need to provide callback functions. An interrupt handler +* example is available with the driver. +* +* Threads +* +* This driver is not thread safe. Any needs for threads or thread mutual +* exclusion must be satisfied by the layer above this driver. +* +* Asserts +* +* Asserts are used within all Xilinx drivers to enforce constraints on argument +* values. Asserts can be turned off on a system-wide basis by defining, at +* compile time, the NDEBUG identifier. By default, asserts are turned on and it +* is recommended that users leave asserts on during development. +* +* Building the driver +* +* The XGpioPs driver is composed of several source files. This allows the user +* to build and link only those parts of the driver that are necessary. +*

+* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a sv   01/15/10 First Release
+* 1.01a sv   04/15/12 Removed the APIs XGpioPs_SetMode, XGpioPs_SetModePin
+*                     XGpioPs_GetMode, XGpioPs_GetModePin as they are not
+*		      relevant to Zynq device.The interrupts are disabled
+*		      for output pins on all banks during initialization.
+* 1.02a hk   08/22/13 Added low level reset API
+* 2.1   hk   04/29/14 Use Input data register DATA_RO for read. CR# 771667.
+* 2.2	sk	 10/13/14 Used Pin number in Bank instead of pin number
+* 					  passed to APIs. CR# 822636
+* 3.00  kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.1	kvn  04/13/15 Add support for Zynq Ultrascale+ MP. CR# 856980.
+*       ms   03/17/17 Added readme.txt file in examples folder for doxygen
+*                     generation.
+*       ms   04/05/17 Added tabspace for return statements in functions of
+*                     gpiops examples for proper documentation while
+*                     generating doxygen.
+* 3.3   ms   04/17/17 Added notes about gpio input and output pin description
+*                     for zcu102 and zc702 boards in polled and interrupt
+*                     example, configured Interrupt pin to input pin for
+*                     proper functioning of interrupt example.
+* 3.4   aru  08/17/18 Resolved MISRA-C mandatory violations. CR# 1007751
+* 3.5   sne  03/01/19 Fixes violations according to MISRAC-2012
+*                     in saftey mode and modified the code such as
+*                     Use of mixed mode arithmetic,Declared the poiner param
+*                     as Pointer to const,Casting operation to a pointer,
+*                     Literal value requires a U suffix.
+* 3.5   sne  03/14/19 Added Versal support.
+* 
+* +******************************************************************************/ +#ifndef XGPIOPS_H /* prevent circular inclusions */ +#define XGPIOPS_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xstatus.h" +#include "xgpiops_hw.h" +#include "xplatform_info.h" + +/************************** Constant Definitions *****************************/ + +/** @name Interrupt types + * @{ + * The following constants define the interrupt types that can be set for each + * GPIO pin. + */ +#define XGPIOPS_IRQ_TYPE_EDGE_RISING 0x00U /**< Interrupt on Rising edge */ +#define XGPIOPS_IRQ_TYPE_EDGE_FALLING 0x01U /**< Interrupt Falling edge */ +#define XGPIOPS_IRQ_TYPE_EDGE_BOTH 0x02U /**< Interrupt on both edges */ +#define XGPIOPS_IRQ_TYPE_LEVEL_HIGH 0x03U /**< Interrupt on high level */ +#define XGPIOPS_IRQ_TYPE_LEVEL_LOW 0x04U /**< Interrupt on low level */ +/*@}*/ + +#define XGPIOPS_BANK_MAX_PINS (u32)32 /**< Max pins in a GPIO bank */ +#define XGPIOPS_BANK0 0x00U /**< GPIO Bank 0 */ +#define XGPIOPS_BANK1 0x01U /**< GPIO Bank 1 */ +#define XGPIOPS_BANK2 0x02U /**< GPIO Bank 2 */ +#define XGPIOPS_BANK3 0x03U /**< GPIO Bank 3 */ + +#ifdef XPAR_PSU_GPIO_0_BASEADDR +#define XGPIOPS_BANK4 0x04U /**< GPIO Bank 4 */ +#define XGPIOPS_BANK5 0x05U /**< GPIO Bank 5 */ +#endif + +#define XGPIOPS_MAX_BANKS_ZYNQMP 0x06U /**< Max banks in a + * Zynq Ultrascale+ MP GPIO device + */ +#define XGPIOPS_MAX_BANKS 0x04U /**< Max banks in a Zynq GPIO device */ + +#define XGPIOPS_DEVICE_MAX_PIN_NUM_ZYNQMP (u32)174 /**< Max pins in the + * Zynq Ultrascale+ MP GPIO device + * 0 - 25, Bank 0 + * 26 - 51, Bank 1 + * 52 - 77, Bank 2 + * 78 - 109, Bank 3 + * 110 - 141, Bank 4 + * 142 - 173, Bank 5 + */ +#define XGPIOPS_DEVICE_MAX_PIN_NUM (u32)118 /**< Max pins in the Zynq GPIO device + * 0 - 31, Bank 0 + * 32 - 53, Bank 1 + * 54 - 85, Bank 2 + * 86 - 117, Bank 3 + */ + +/**************************** Type Definitions *******************************/ + +/****************************************************************************/ +/** + * This handler data type allows the user to define a callback function to + * handle the interrupts for the GPIO device. The application using this + * driver is expected to define a handler of this type, to support interrupt + * driven mode. The handler executes in an interrupt context such that minimal + * processing should be performed. + * + * @param CallBackRef is a callback reference passed in by the upper layer + * when setting the callback functions for a GPIO bank. It is + * passed back to the upper layer when the callback is invoked. Its + * type is not important to the driver component, so it is a void + * pointer. + * @param Bank is the bank for which the interrupt status has changed. + * @param Status is the Interrupt status of the GPIO bank. + * + *****************************************************************************/ +typedef void (*XGpioPs_Handler) (void *CallBackRef, u32 Bank, u32 Status); + +/** + * This typedef contains configuration information for a device. + */ +typedef struct { + u16 DeviceId; /**< Unique ID of device */ + u32 BaseAddr; /**< Register base address */ +} XGpioPs_Config; + +/** + * The XGpioPs driver instance data. The user is required to allocate a + * variable of this type for the GPIO device in the system. A pointer + * to a variable of this type is then passed to the driver API functions. + */ +typedef struct { + XGpioPs_Config GpioConfig; /**< Device configuration */ + u32 IsReady; /**< Device is initialized and ready */ + XGpioPs_Handler Handler; /**< Status handlers for all banks */ + void *CallBackRef; /**< Callback ref for bank handlers */ + u32 Platform; /**< Platform data */ + u32 MaxPinNum; /**< Max pins in the GPIO device */ + u8 MaxBanks; /**< Max banks in a GPIO device */ + u32 PmcGpio; /**< Flag for accessing PS GPIO for versal*/ +} XGpioPs; + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/* Functions in xgpiops.c */ +s32 XGpioPs_CfgInitialize(XGpioPs *InstancePtr, const XGpioPs_Config *ConfigPtr, + u32 EffectiveAddr); + +/* Bank APIs in xgpiops.c */ +u32 XGpioPs_Read(const XGpioPs *InstancePtr, u8 Bank); +void XGpioPs_Write(const XGpioPs *InstancePtr, u8 Bank, u32 Data); +void XGpioPs_SetDirection(const XGpioPs *InstancePtr, u8 Bank, u32 Direction); +u32 XGpioPs_GetDirection(const XGpioPs *InstancePtr, u8 Bank); +void XGpioPs_SetOutputEnable(const XGpioPs *InstancePtr, u8 Bank, u32 OpEnable); +u32 XGpioPs_GetOutputEnable(const XGpioPs *InstancePtr, u8 Bank); +#ifdef versal +void XGpioPs_GetBankPin(const XGpioPs *InstancePtr,u8 PinNumber,u8 *BankNumber, u8 *PinNumberInBank); +#else +void XGpioPs_GetBankPin(u8 PinNumber,u8 *BankNumber, u8 *PinNumberInBank); +#endif + +/* Pin APIs in xgpiops.c */ +u32 XGpioPs_ReadPin(const XGpioPs *InstancePtr, u32 Pin); +void XGpioPs_WritePin(const XGpioPs *InstancePtr, u32 Pin, u32 Data); +void XGpioPs_SetDirectionPin(const XGpioPs *InstancePtr, u32 Pin, u32 Direction); +u32 XGpioPs_GetDirectionPin(const XGpioPs *InstancePtr, u32 Pin); +void XGpioPs_SetOutputEnablePin(const XGpioPs *InstancePtr, u32 Pin, u32 OpEnable); +u32 XGpioPs_GetOutputEnablePin(const XGpioPs *InstancePtr, u32 Pin); + +/* Diagnostic functions in xgpiops_selftest.c */ +s32 XGpioPs_SelfTest(const XGpioPs *InstancePtr); + +/* Functions in xgpiops_intr.c */ +/* Bank APIs in xgpiops_intr.c */ +void XGpioPs_IntrEnable(const XGpioPs *InstancePtr, u8 Bank, u32 Mask); +void XGpioPs_IntrDisable(const XGpioPs *InstancePtr, u8 Bank, u32 Mask); +u32 XGpioPs_IntrGetEnabled(const XGpioPs *InstancePtr, u8 Bank); +u32 XGpioPs_IntrGetStatus(const XGpioPs *InstancePtr, u8 Bank); +void XGpioPs_IntrClear(const XGpioPs *InstancePtr, u8 Bank, u32 Mask); +void XGpioPs_SetIntrType(const XGpioPs *InstancePtr, u8 Bank, u32 IntrType, + u32 IntrPolarity, u32 IntrOnAny); +void XGpioPs_GetIntrType(const XGpioPs *InstancePtr, u8 Bank, u32 *IntrType, + u32 *IntrPolarity, u32 *IntrOnAny); +void XGpioPs_SetCallbackHandler(XGpioPs *InstancePtr, void *CallBackRef, + XGpioPs_Handler FuncPointer); +void XGpioPs_IntrHandler(const XGpioPs *InstancePtr); + +/* Pin APIs in xgpiops_intr.c */ +void XGpioPs_SetIntrTypePin(const XGpioPs *InstancePtr, u32 Pin, u8 IrqType); +u8 XGpioPs_GetIntrTypePin(const XGpioPs *InstancePtr, u32 Pin); + +void XGpioPs_IntrEnablePin(const XGpioPs *InstancePtr, u32 Pin); +void XGpioPs_IntrDisablePin(const XGpioPs *InstancePtr, u32 Pin); +u32 XGpioPs_IntrGetEnabledPin(const XGpioPs *InstancePtr, u32 Pin); +u32 XGpioPs_IntrGetStatusPin(const XGpioPs *InstancePtr, u32 Pin); +void XGpioPs_IntrClearPin(const XGpioPs *InstancePtr, u32 Pin); + +/* Functions in xgpiops_sinit.c */ +XGpioPs_Config *XGpioPs_LookupConfig(u16 DeviceId); +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/include/xgpiops_hw.h b/datalink814_ge/bsp/ps7_cortexa9_0/include/xgpiops_hw.h new file mode 100644 index 0000000..599c7db --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/include/xgpiops_hw.h @@ -0,0 +1,168 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xgpiops_hw.h +* @addtogroup gpiops_v3_5 +* @{ +* +* This header file contains the identifiers and basic driver functions (or +* macros) that can be used to access the device. Other driver functions +* are defined in xgpiops.h. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------
+* 1.00a sv   01/15/10 First Release
+* 1.02a hk   08/22/13 Added low level reset API function prototype and
+*                     related constant definitions
+* 3.00  kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.1	kvn  04/13/15 Corrected reset values of banks.
+* 3.5   sne  03/14/19 Added versal support.
+* 
+* +******************************************************************************/ +#ifndef XGPIOPS_HW_H /* prevent circular inclusions */ +#define XGPIOPS_HW_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_io.h" + +/************************** Constant Definitions *****************************/ + +/** @name Register offsets for the GPIO. Each register is 32 bits. + * @{ + */ +#define XGPIOPS_DATA_LSW_OFFSET 0x00000000U /* Mask and Data Register LSW, WO */ +#define XGPIOPS_DATA_MSW_OFFSET 0x00000004U /* Mask and Data Register MSW, WO */ +#define XGPIOPS_DATA_OFFSET 0x00000040U /* Data Register, RW */ +#define XGPIOPS_DATA_RO_OFFSET 0x00000060U /* Data Register - Input, RO */ +#define XGPIOPS_DIRM_OFFSET 0x00000204U /* Direction Mode Register, RW */ +#define XGPIOPS_OUTEN_OFFSET 0x00000208U /* Output Enable Register, RW */ +#define XGPIOPS_INTMASK_OFFSET 0x0000020CU /* Interrupt Mask Register, RO */ +#define XGPIOPS_INTEN_OFFSET 0x00000210U /* Interrupt Enable Register, WO */ +#define XGPIOPS_INTDIS_OFFSET 0x00000214U /* Interrupt Disable Register, WO*/ +#define XGPIOPS_INTSTS_OFFSET 0x00000218U /* Interrupt Status Register, RO */ +#define XGPIOPS_INTTYPE_OFFSET 0x0000021CU /* Interrupt Type Register, RW */ +#define XGPIOPS_INTPOL_OFFSET 0x00000220U /* Interrupt Polarity Register, RW */ +#define XGPIOPS_INTANY_OFFSET 0x00000224U /* Interrupt On Any Register, RW */ +/* @} */ + +/** @name Register offsets for each Bank. + * @{ + */ +#define XGPIOPS_DATA_MASK_OFFSET 0x00000008U /* Data/Mask Registers offset */ +#define XGPIOPS_DATA_BANK_OFFSET 0x00000004U /* Data Registers offset */ +#define XGPIOPS_REG_MASK_OFFSET 0x00000040U /* Registers offset */ +/* @} */ + +/* For backwards compatibility */ +#define XGPIOPS_BYPM_MASK_OFFSET (u32)0x40 + +/** @name Interrupt type reset values for each bank + * @{ + */ +#ifdef XPAR_PSU_GPIO_0_BASEADDR +#define XGPIOPS_INTTYPE_BANK0_RESET 0x03FFFFFFU /* Resets specific to Zynq Ultrascale+ MP */ +#define XGPIOPS_INTTYPE_BANK1_RESET 0x03FFFFFFU +#define XGPIOPS_INTTYPE_BANK2_RESET 0x03FFFFFFU +#else +#define XGPIOPS_INTTYPE_BANK0_RESET 0xFFFFFFFFU /* Resets specific to Zynq */ +#define XGPIOPS_INTTYPE_BANK1_RESET 0x003FFFFFU +#define XGPIOPS_INTTYPE_BANK2_RESET 0xFFFFFFFFU +#endif + +#define XGPIOPS_INTTYPE_BANK3_RESET 0xFFFFFFFFU /* Reset common to both platforms */ +#define XGPIOPS_INTTYPE_BANK4_RESET 0xFFFFFFFFU /* Resets specific to Zynq Ultrascale+ MP */ +#define XGPIOPS_INTTYPE_BANK5_RESET 0xFFFFFFFFU +/* @} */ +#define XGPIOPS_PS_GPIO_BASEADDR 0xFF0B0000U /* Flag for Base Address for PS_GPIO in Versal */ +#define XGPIOPS_ZERO 0U /* Flag for 0 Value */ +#define XGPIOPS_ONE 1U /* Flag for 1 Value */ +#define XGPIOPS_TWO 2U /* Flag for 2 Value */ +#define XGPIOPS_THREE 3U /* Flag for 3 Value */ +#define XGPIOPS_FOUR 4U /* Flag for 4 Value */ +#define XGPIOPS_SIX 6U /* Flag for 6 Value */ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/****************************************************************************/ +/** +* +* This macro reads the given register. +* +* @param BaseAddr is the base address of the device. +* @param RegOffset is the register offset to be read. +* +* @return The 32-bit value of the register +* +* @note None. +* +*****************************************************************************/ +#define XGpioPs_ReadReg(BaseAddr, RegOffset) \ + Xil_In32((BaseAddr) + (u32)(RegOffset)) + +/****************************************************************************/ +/** +* +* This macro writes to the given register. +* +* @param BaseAddr is the base address of the device. +* @param RegOffset is the offset of the register to be written. +* @param Data is the 32-bit value to write to the register. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +#define XGpioPs_WriteReg(BaseAddr, RegOffset, Data) \ + Xil_Out32((BaseAddr) + (u32)(RegOffset), (u32)(Data)) + +/************************** Function Prototypes ******************************/ + +void XGpioPs_ResetHw(u32 BaseAddress); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* XGPIOPS_HW_H */ +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/include/xil_assert.h b/datalink814_ge/bsp/ps7_cortexa9_0/include/xil_assert.h new file mode 100644 index 0000000..917de31 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/include/xil_assert.h @@ -0,0 +1,191 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_assert.h +* +* @addtogroup common_assert_apis Assert APIs and Macros +* +* The xil_assert.h file contains assert related functions and macros. +* Assert APIs/Macros specifies that a application program satisfies certain +* conditions at particular points in its execution. These function can be +* used by application programs to ensure that, application code is satisfying +* certain conditions. +* +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date   Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a hbm  07/14/09 First release
+* 6.0   kvn  05/31/16 Make Xil_AsserWait a global variable
+* 
+* +******************************************************************************/ + +#ifndef XIL_ASSERT_H /* prevent circular inclusions */ +#define XIL_ASSERT_H /* by using protection macros */ + +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/***************************** Include Files *********************************/ + + +/************************** Constant Definitions *****************************/ + +#define XIL_ASSERT_NONE 0U +#define XIL_ASSERT_OCCURRED 1U +#define XNULL NULL + +extern u32 Xil_AssertStatus; +extern s32 Xil_AssertWait; +extern void Xil_Assert(const char8 *File, s32 Line); +void XNullHandler(void *NullParameter); + +/** + * This data type defines a callback to be invoked when an + * assert occurs. The callback is invoked only when asserts are enabled + */ +typedef void (*Xil_AssertCallback) (const char8 *File, s32 Line); + +/***************** Macros (Inline Functions) Definitions *********************/ + +#ifndef NDEBUG + +/*****************************************************************************/ +/** +* @brief This assert macro is to be used for void functions. This in +* conjunction with the Xil_AssertWait boolean can be used to +* accomodate tests so that asserts which fail allow execution to +* continue. +* +* @param Expression: expression to be evaluated. If it evaluates to +* false, the assert occurs. +* +* @return Returns void unless the Xil_AssertWait variable is true, in which +* case no return is made and an infinite loop is entered. +* +******************************************************************************/ +#define Xil_AssertVoid(Expression) \ +{ \ + if (Expression) { \ + Xil_AssertStatus = XIL_ASSERT_NONE; \ + } else { \ + Xil_Assert(__FILE__, __LINE__); \ + Xil_AssertStatus = XIL_ASSERT_OCCURRED; \ + return; \ + } \ +} + +/*****************************************************************************/ +/** +* @brief This assert macro is to be used for functions that do return a +* value. This in conjunction with the Xil_AssertWait boolean can be +* used to accomodate tests so that asserts which fail allow execution +* to continue. +* +* @param Expression: expression to be evaluated. If it evaluates to false, +* the assert occurs. +* +* @return Returns 0 unless the Xil_AssertWait variable is true, in which +* case no return is made and an infinite loop is entered. +* +******************************************************************************/ +#define Xil_AssertNonvoid(Expression) \ +{ \ + if (Expression) { \ + Xil_AssertStatus = XIL_ASSERT_NONE; \ + } else { \ + Xil_Assert(__FILE__, __LINE__); \ + Xil_AssertStatus = XIL_ASSERT_OCCURRED; \ + return 0; \ + } \ +} + +/*****************************************************************************/ +/** +* @brief Always assert. This assert macro is to be used for void functions. +* Use for instances where an assert should always occur. +* +* @return Returns void unless the Xil_AssertWait variable is true, in which +* case no return is made and an infinite loop is entered. +* +******************************************************************************/ +#define Xil_AssertVoidAlways() \ +{ \ + Xil_Assert(__FILE__, __LINE__); \ + Xil_AssertStatus = XIL_ASSERT_OCCURRED; \ + return; \ +} + +/*****************************************************************************/ +/** +* @brief Always assert. This assert macro is to be used for functions that +* do return a value. Use for instances where an assert should always +* occur. +* +* @return Returns void unless the Xil_AssertWait variable is true, in which +* case no return is made and an infinite loop is entered. +* +******************************************************************************/ +#define Xil_AssertNonvoidAlways() \ +{ \ + Xil_Assert(__FILE__, __LINE__); \ + Xil_AssertStatus = XIL_ASSERT_OCCURRED; \ + return 0; \ +} + + +#else + +#define Xil_AssertVoid(Expression) +#define Xil_AssertVoidAlways() +#define Xil_AssertNonvoid(Expression) +#define Xil_AssertNonvoidAlways() + +#endif + +/************************** Function Prototypes ******************************/ + +void Xil_AssertSetCallback(Xil_AssertCallback Routine); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** +* @} End of "addtogroup common_assert_apis". +*/ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/include/xil_cache.h b/datalink814_ge/bsp/ps7_cortexa9_0/include/xil_cache.h new file mode 100644 index 0000000..ce6fcf4 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/include/xil_cache.h @@ -0,0 +1,118 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_cache.h +* +* @addtogroup a9_cache_apis Cortex A9 Processor Cache Functions +* +* Cache functions provide access to cache related operations such as flush +* and invalidate for instruction and data caches. It gives option to perform +* the cache operations on a single cacheline, a range of memory and an entire +* cache. +* +* @{ +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a ecm  01/29/10 First release
+* 3.04a sdm  01/02/12 Remove redundant dsb/dmb instructions in cache maintenance
+*		      APIs.
+* 6.8   aru  09/06/18 Removed compilation warnings for ARMCC toolchain.
+* 
+* +******************************************************************************/ +#ifndef XIL_CACHE_H +#define XIL_CACHE_H + +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __GNUC__ + +#define asm_cp15_inval_dc_line_mva_poc(param) __asm__ __volatile__("mcr " \ + XREG_CP15_INVAL_DC_LINE_MVA_POC :: "r" (param)); + +#define asm_cp15_clean_inval_dc_line_mva_poc(param) __asm__ __volatile__("mcr " \ + XREG_CP15_CLEAN_INVAL_DC_LINE_MVA_POC :: "r" (param)); + +#define asm_cp15_inval_ic_line_mva_pou(param) __asm__ __volatile__("mcr " \ + XREG_CP15_INVAL_IC_LINE_MVA_POU :: "r" (param)); + +#define asm_cp15_inval_dc_line_sw(param) __asm__ __volatile__("mcr " \ + XREG_CP15_INVAL_DC_LINE_SW :: "r" (param)); + +#define asm_cp15_clean_inval_dc_line_sw(param) __asm__ __volatile__("mcr " \ + XREG_CP15_CLEAN_INVAL_DC_LINE_SW :: "r" (param)); + +#elif defined (__ICCARM__) + +#define asm_cp15_inval_dc_line_mva_poc(param) __asm volatile ("mcr " \ + XREG_CP15_INVAL_DC_LINE_MVA_POC :: "r" (param)); + +#define asm_cp15_clean_inval_dc_line_mva_poc(param) __asm volatile ("mcr " \ + XREG_CP15_CLEAN_INVAL_DC_LINE_MVA_POC :: "r" (param)); + +#define asm_cp15_inval_ic_line_mva_pou(param) __asm volatile ("mcr " \ + XREG_CP15_INVAL_IC_LINE_MVA_POU :: "r" (param)); + +#define asm_cp15_inval_dc_line_sw(param) __asm volatile ("mcr " \ + XREG_CP15_INVAL_DC_LINE_SW :: "r" (param)); + +#define asm_cp15_clean_inval_dc_line_sw(param) __asm volatile ("mcr " \ + XREG_CP15_CLEAN_INVAL_DC_LINE_SW :: "r" (param)); + +#endif + +void Xil_DCacheEnable(void); +void Xil_DCacheDisable(void); +void Xil_DCacheInvalidate(void); +void Xil_DCacheInvalidateRange(INTPTR adr, u32 len); +void Xil_DCacheFlush(void); +void Xil_DCacheFlushRange(INTPTR adr, u32 len); + +void Xil_ICacheEnable(void); +void Xil_ICacheDisable(void); +void Xil_ICacheInvalidate(void); +void Xil_ICacheInvalidateRange(INTPTR adr, u32 len); + +#ifdef __cplusplus +} +#endif + +#endif +/** +* @} End of "addtogroup a9_cache_apis". +*/ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/include/xil_cache_l.h b/datalink814_ge/bsp/ps7_cortexa9_0/include/xil_cache_l.h new file mode 100644 index 0000000..b6ff809 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/include/xil_cache_l.h @@ -0,0 +1,97 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_cache_l.h +* +* Contains L1 and L2 specific functions for the ARM cache functionality +* used by xcache.c. This functionality is being made available here for +* more sophisticated users. +* +* @addtogroup a9_cache_apis +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a ecm  01/24/10 First release
+* 6.8   aru  09/06/18 Removed compilation warnings for ARMCC toolchain.
+* 
+* +******************************************************************************/ +#ifndef XIL_CACHE_MACH_H +#define XIL_CACHE_MACH_H + +#include "xil_types.h" +#ifdef __cplusplus +extern "C" { +#endif + +/************************** Function Prototypes ******************************/ + +void Xil_DCacheInvalidateLine(u32 adr); +void Xil_DCacheFlushLine(u32 adr); +void Xil_DCacheStoreLine(u32 adr); +void Xil_ICacheInvalidateLine(u32 adr); + +void Xil_L1DCacheEnable(void); +void Xil_L1DCacheDisable(void); +void Xil_L1DCacheInvalidate(void); +void Xil_L1DCacheInvalidateLine(u32 adr); +void Xil_L1DCacheInvalidateRange(u32 adr, u32 len); +void Xil_L1DCacheFlush(void); +void Xil_L1DCacheFlushLine(u32 adr); +void Xil_L1DCacheFlushRange(u32 adr, u32 len); +void Xil_L1DCacheStoreLine(u32 adr); + +void Xil_L1ICacheEnable(void); +void Xil_L1ICacheDisable(void); +void Xil_L1ICacheInvalidate(void); +void Xil_L1ICacheInvalidateLine(u32 adr); +void Xil_L1ICacheInvalidateRange(u32 adr, u32 len); + +void Xil_L2CacheEnable(void); +void Xil_L2CacheDisable(void); +void Xil_L2CacheInvalidate(void); +void Xil_L2CacheInvalidateLine(u32 adr); +void Xil_L2CacheInvalidateRange(u32 adr, u32 len); +void Xil_L2CacheFlush(void); +void Xil_L2CacheFlushLine(u32 adr); +void Xil_L2CacheFlushRange(u32 adr, u32 len); +void Xil_L2CacheStoreLine(u32 adr); + +#ifdef __cplusplus +} +#endif + +#endif +/** +* @} End of "addtogroup a9_cache_apis". +*/ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/include/xil_cache_vxworks.h b/datalink814_ge/bsp/ps7_cortexa9_0/include/xil_cache_vxworks.h new file mode 100644 index 0000000..7e2a7d9 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/include/xil_cache_vxworks.h @@ -0,0 +1,89 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_cache_vxworks.h +* +* Contains the cache related functions for VxWorks that is wrapped by +* xil_cache. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date	 Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a hbm  12/11/09 Initial release
+*
+* 
+* +* @note +* +******************************************************************************/ + +#ifndef XIL_CACHE_VXWORKS_H +#define XIL_CACHE_VXWORKS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "vxWorks.h" +#include "vxLib.h" +#include "sysLibExtra.h" +#include "cacheLib.h" + +#if (CPU_FAMILY==PPC) + +#define Xil_DCacheEnable() cacheEnable(DATA_CACHE) + +#define Xil_DCacheDisable() cacheDisable(DATA_CACHE) + +#define Xil_DCacheInvalidateRange(Addr, Len) \ + cacheInvalidate(DATA_CACHE, (void *)(Addr), (Len)) + +#define Xil_DCacheFlushRange(Addr, Len) \ + cacheFlush(DATA_CACHE, (void *)(Addr), (Len)) + +#define Xil_ICacheEnable() cacheEnable(INSTRUCTION_CACHE) + +#define Xil_ICacheDisable() cacheDisable(INSTRUCTION_CACHE) + +#define Xil_ICacheInvalidateRange(Addr, Len) \ + cacheInvalidate(INSTRUCTION_CACHE, (void *)(Addr), (Len)) + + +#else +#error "Unknown processor / architecture. Must be PPC for VxWorks." +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/include/xil_errata.h b/datalink814_ge/bsp/ps7_cortexa9_0/include/xil_errata.h new file mode 100644 index 0000000..c839b63 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/include/xil_errata.h @@ -0,0 +1,127 @@ +/****************************************************************************** +* +* Copyright (C) 2013 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_errata.h +* +* @addtogroup a9_errata Cortex A9 Processor and pl310 Errata Support +* @{ +* Various ARM errata are handled in the standalone BSP. The implementation for +* errata handling follows ARM guidelines and is based on the open source Linux +* support for these errata. +* +* @note +* The errata handling is enabled by default. To disable handling of all the +* errata globally, un-define the macro ENABLE_ARM_ERRATA in xil_errata.h. To +* disable errata on a per-erratum basis, un-define relevant macros in +* xil_errata.h. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a srt  04/18/13 First release
+* 6.6   mus  12/07/17 Removed errata 753970, It fixes CR#989132.
+* 
+* +******************************************************************************/ +#ifndef XIL_ERRATA_H +#define XIL_ERRATA_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @name errata_definitions + * + * The errata conditions handled in the standalone BSP are listed below + * @{ + */ + +#define ENABLE_ARM_ERRATA 1 + +#ifdef ENABLE_ARM_ERRATA + +/** + * Errata No: 742230 + * Description: DMB operation may be faulty + */ +#define CONFIG_ARM_ERRATA_742230 1 + +/** + * Errata No: 743622 + * Description: Faulty hazard checking in the Store Buffer may lead + * to data corruption. + */ +#define CONFIG_ARM_ERRATA_743622 1 + +/** + * Errata No: 775420 + * Description: A data cache maintenance operation which aborts, + * might lead to deadlock + */ +#define CONFIG_ARM_ERRATA_775420 1 + +/** + * Errata No: 794073 + * Description: Speculative instruction fetches with MMU disabled + * might not comply with architectural requirements + */ +#define CONFIG_ARM_ERRATA_794073 1 + + +/** PL310 L2 Cache Errata */ + +/** + * Errata No: 588369 + * Description: Clean & Invalidate maintenance operations do not + * invalidate clean lines + */ +#define CONFIG_PL310_ERRATA_588369 1 + +/** + * Errata No: 727915 + * Description: Background Clean and Invalidate by Way operation + * can cause data corruption + */ +#define CONFIG_PL310_ERRATA_727915 1 + +/*@}*/ +#endif /* ENABLE_ARM_ERRATA */ + +#ifdef __cplusplus +} +#endif + +#endif /* XIL_ERRATA_H */ +/** +* @} End of "addtogroup a9_errata". +*/ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/include/xil_exception.h b/datalink814_ge/bsp/ps7_cortexa9_0/include/xil_exception.h new file mode 100644 index 0000000..807f310 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/include/xil_exception.h @@ -0,0 +1,285 @@ +/****************************************************************************** +* +* Copyright (C) 2015 - 2016 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_exception.h +* +* This header file contains ARM Cortex A53,A9,R5 specific exception related APIs. +* For exception related functions that can be used across all Xilinx supported +* processors, please use xil_exception.h. +* +* @addtogroup arm_exception_apis ARM Processor Exception Handling +* @{ +* ARM processors specific exception related APIs for cortex A53,A9 and R5 can +* utilized for enabling/disabling IRQ, registering/removing handler for +* exceptions or initializing exception vector table with null handler. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 5.2	pkp  	 28/05/15 First release
+* 6.0   mus      27/07/16 Consolidated file for a53,a9 and r5 processors
+* 6.7   mna      26/04/18 Add API Xil_GetExceptionRegisterHandler.
+* 6.7   asa      18/05/18 Update signature of API Xil_GetExceptionRegisterHandler.
+* 7.0   mus      01/03/19 Tweak Xil_ExceptionEnableMask and
+*                         Xil_ExceptionDisableMask macros to support legacy
+*                         examples for Cortexa72 EL3 exception level.
+* 
+* +******************************************************************************/ + +#ifndef XIL_EXCEPTION_H /* prevent circular inclusions */ +#define XIL_EXCEPTION_H /* by using protection macros */ + +/***************************** Include Files ********************************/ + +#include "xil_types.h" +#include "xpseudo_asm.h" +#include "bspconfig.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************** Constant Definitions ****************************/ + +#define XIL_EXCEPTION_FIQ XREG_CPSR_FIQ_ENABLE +#define XIL_EXCEPTION_IRQ XREG_CPSR_IRQ_ENABLE +#define XIL_EXCEPTION_ALL (XREG_CPSR_FIQ_ENABLE | XREG_CPSR_IRQ_ENABLE) + +#define XIL_EXCEPTION_ID_FIRST 0U +#if defined (__aarch64__) +#define XIL_EXCEPTION_ID_SYNC_INT 1U +#define XIL_EXCEPTION_ID_IRQ_INT 2U +#define XIL_EXCEPTION_ID_FIQ_INT 3U +#define XIL_EXCEPTION_ID_SERROR_ABORT_INT 4U +#define XIL_EXCEPTION_ID_LAST 5U +#else +#define XIL_EXCEPTION_ID_RESET 0U +#define XIL_EXCEPTION_ID_UNDEFINED_INT 1U +#define XIL_EXCEPTION_ID_SWI_INT 2U +#define XIL_EXCEPTION_ID_PREFETCH_ABORT_INT 3U +#define XIL_EXCEPTION_ID_DATA_ABORT_INT 4U +#define XIL_EXCEPTION_ID_IRQ_INT 5U +#define XIL_EXCEPTION_ID_FIQ_INT 6U +#define XIL_EXCEPTION_ID_LAST 6U +#endif + +/* + * XIL_EXCEPTION_ID_INT is defined for all Xilinx processors. + */ +#if defined (versal) && !defined(ARMR5) && EL3 +#define XIL_EXCEPTION_ID_INT XIL_EXCEPTION_ID_FIQ_INT +#else +#define XIL_EXCEPTION_ID_INT XIL_EXCEPTION_ID_IRQ_INT +#endif + +/**************************** Type Definitions ******************************/ + +/** + * This typedef is the exception handler function. + */ +typedef void (*Xil_ExceptionHandler)(void *data); +typedef void (*Xil_InterruptHandler)(void *data); + +/***************** Macros (Inline Functions) Definitions ********************/ + +/****************************************************************************/ +/** +* @brief Enable Exceptions. +* +* @param Mask: Value for enabling the exceptions. +* +* @return None. +* +* @note If bit is 0, exception is enabled. +* C-Style signature: void Xil_ExceptionEnableMask(Mask) +* +******************************************************************************/ +#if defined (versal) && !defined(ARMR5) && EL3 +/* + * Cortexa72 processor in versal is coupled with GIC-500, and GIC-500 supports + * only FIQ at EL3. Hence, tweaking this macro to always enable FIQ + * ignoring argument passed by user. + */ +#define Xil_ExceptionEnableMask(Mask) \ + mtcpsr(mfcpsr() & ~ ((XIL_EXCEPTION_FIQ) & XIL_EXCEPTION_ALL)) +#elif defined (__GNUC__) || defined (__ICCARM__) +#define Xil_ExceptionEnableMask(Mask) \ + mtcpsr(mfcpsr() & ~ ((Mask) & XIL_EXCEPTION_ALL)) +#else +#define Xil_ExceptionEnableMask(Mask) \ + { \ + register u32 Reg __asm("cpsr"); \ + mtcpsr((Reg) & (~((Mask) & XIL_EXCEPTION_ALL))); \ + } +#endif +/****************************************************************************/ +/** +* @brief Enable the IRQ exception. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +#if defined (versal) && !defined(ARMR5) && EL3 +#define Xil_ExceptionEnable() \ + Xil_ExceptionEnableMask(XIL_EXCEPTION_FIQ) +#else +#define Xil_ExceptionEnable() \ + Xil_ExceptionEnableMask(XIL_EXCEPTION_IRQ) +#endif + +/****************************************************************************/ +/** +* @brief Disable Exceptions. +* +* @param Mask: Value for disabling the exceptions. +* +* @return None. +* +* @note If bit is 1, exception is disabled. +* C-Style signature: Xil_ExceptionDisableMask(Mask) +* +******************************************************************************/ +#if defined (versal) && !defined(ARMR5) && EL3 +/* + * Cortexa72 processor in versal is coupled with GIC-500, and GIC-500 supports + * only FIQ at EL3. Hence, tweaking this macro to always disable FIQ + * ignoring argument passed by user. + */ +#define Xil_ExceptionDisableMask(Mask) \ + mtcpsr(mfcpsr() | ((XIL_EXCEPTION_FIQ) & XIL_EXCEPTION_ALL)) +#elif defined (__GNUC__) || defined (__ICCARM__) +#define Xil_ExceptionDisableMask(Mask) \ + mtcpsr(mfcpsr() | ((Mask) & XIL_EXCEPTION_ALL)) +#else +#define Xil_ExceptionDisableMask(Mask) \ + { \ + register u32 Reg __asm("cpsr"); \ + mtcpsr((Reg) | ((Mask) & XIL_EXCEPTION_ALL)); \ + } +#endif +/****************************************************************************/ +/** +* Disable the IRQ exception. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +#define Xil_ExceptionDisable() \ + Xil_ExceptionDisableMask(XIL_EXCEPTION_IRQ) + +#if !defined (__aarch64__) && !defined (ARMA53_32) +/****************************************************************************/ +/** +* @brief Enable nested interrupts by clearing the I and F bits in CPSR. This +* API is defined for cortex-a9 and cortex-r5. +* +* @return None. +* +* @note This macro is supposed to be used from interrupt handlers. In the +* interrupt handler the interrupts are disabled by default (I and F +* are 1). To allow nesting of interrupts, this macro should be +* used. It clears the I and F bits by changing the ARM mode to +* system mode. Once these bits are cleared and provided the +* preemption of interrupt conditions are met in the GIC, nesting of +* interrupts will start happening. +* Caution: This macro must be used with caution. Before calling this +* macro, the user must ensure that the source of the current IRQ +* is appropriately cleared. Otherwise, as soon as we clear the I and +* F bits, there can be an infinite loop of interrupts with an +* eventual crash (all the stack space getting consumed). +******************************************************************************/ +#define Xil_EnableNestedInterrupts() \ + __asm__ __volatile__ ("stmfd sp!, {lr}"); \ + __asm__ __volatile__ ("mrs lr, spsr"); \ + __asm__ __volatile__ ("stmfd sp!, {lr}"); \ + __asm__ __volatile__ ("msr cpsr_c, #0x1F"); \ + __asm__ __volatile__ ("stmfd sp!, {lr}"); + +/****************************************************************************/ +/** +* @brief Disable the nested interrupts by setting the I and F bits. This API +* is defined for cortex-a9 and cortex-r5. +* +* @return None. +* +* @note This macro is meant to be called in the interrupt service routines. +* This macro cannot be used independently. It can only be used when +* nesting of interrupts have been enabled by using the macro +* Xil_EnableNestedInterrupts(). In a typical flow, the user first +* calls the Xil_EnableNestedInterrupts in the ISR at the appropriate +* point. The user then must call this macro before exiting the interrupt +* service routine. This macro puts the ARM back in IRQ/FIQ mode and +* hence sets back the I and F bits. +******************************************************************************/ +#define Xil_DisableNestedInterrupts() \ + __asm__ __volatile__ ("ldmfd sp!, {lr}"); \ + __asm__ __volatile__ ("msr cpsr_c, #0x92"); \ + __asm__ __volatile__ ("ldmfd sp!, {lr}"); \ + __asm__ __volatile__ ("msr spsr_cxsf, lr"); \ + __asm__ __volatile__ ("ldmfd sp!, {lr}"); \ + +#endif +/************************** Variable Definitions ****************************/ + +/************************** Function Prototypes *****************************/ + +extern void Xil_ExceptionRegisterHandler(u32 Exception_id, + Xil_ExceptionHandler Handler, + void *Data); + +extern void Xil_ExceptionRemoveHandler(u32 Exception_id); +extern void Xil_GetExceptionRegisterHandler(u32 Exception_id, + Xil_ExceptionHandler *Handler, void **Data); + +extern void Xil_ExceptionInit(void); +#if defined (__aarch64__) +void Xil_SyncAbortHandler(void *CallBackRef); +void Xil_SErrorAbortHandler(void *CallBackRef); +#else +extern void Xil_DataAbortHandler(void *CallBackRef); +extern void Xil_PrefetchAbortHandler(void *CallBackRef); +extern void Xil_UndefinedExceptionHandler(void *CallBackRef); +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* XIL_EXCEPTION_H */ +/** +* @} End of "addtogroup arm_exception_apis". +*/ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/include/xil_hal.h b/datalink814_ge/bsp/ps7_cortexa9_0/include/xil_hal.h new file mode 100644 index 0000000..e8971c9 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/include/xil_hal.h @@ -0,0 +1,65 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_hal.h +* +* Contains all the HAL header files. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date	 Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a hbm  07/28/09 Initial release
+*
+* 
+* +* @note +* +******************************************************************************/ + +#ifndef XIL_HAL_H +#define XIL_HAL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "xil_cache.h" +#include "xil_io.h" +#include "xil_assert.h" +#include "xil_exception.h" +#include "xil_types.h" + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/include/xil_io.h b/datalink814_ge/bsp/ps7_cortexa9_0/include/xil_io.h new file mode 100644 index 0000000..00207cf --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/include/xil_io.h @@ -0,0 +1,341 @@ +/****************************************************************************** +* +* Copyright (C) 2014 - 2016 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_io.h +* +* @addtogroup common_io_interfacing_apis Register IO interfacing APIs +* +* The xil_io.h file contains the interface for the general I/O component, which +* encapsulates the Input/Output functions for the processors that do not +* require any special I/O handling. +* +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 5.00 	pkp  	 05/29/14 First release
+* 6.00  mus      08/19/16 Remove checking of __LITTLE_ENDIAN__ flag for
+*                         ARM processors
+* 
+******************************************************************************/ + +#ifndef XIL_IO_H /* prevent circular inclusions */ +#define XIL_IO_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_printf.h" + +#if defined (__MICROBLAZE__) +#include "mb_interface.h" +#else +#include "xpseudo_asm.h" +#endif + +/************************** Function Prototypes ******************************/ +u16 Xil_EndianSwap16(u16 Data); +u32 Xil_EndianSwap32(u32 Data); +#ifdef ENABLE_SAFETY +extern u32 XStl_RegUpdate(u32 RegAddr, u32 RegVal); +#endif + +/***************** Macros (Inline Functions) Definitions *********************/ +#if defined __GNUC__ +#if defined (__MICROBLAZE__) +# define INST_SYNC mbar(0) +# define DATA_SYNC mbar(1) +# else +# define SYNCHRONIZE_IO dmb() +# define INST_SYNC isb() +# define DATA_SYNC dsb() +# endif +#else +# define SYNCHRONIZE_IO +# define INST_SYNC +# define DATA_SYNC +# define INST_SYNC +# define DATA_SYNC +#endif + +#if defined (__GNUC__) || defined (__ICCARM__) || defined (__MICROBLAZE__) +#define INLINE inline +#else +#define INLINE __inline +#endif + +/*****************************************************************************/ +/** +* +* @brief Performs an input operation for a memory location by reading +* from the specified address and returning the 8 bit Value read from +* that address. +* +* @param Addr: contains the address to perform the input operation +* +* @return The 8 bit Value read from the specified input address. + +* +******************************************************************************/ +static INLINE u8 Xil_In8(UINTPTR Addr) +{ + return *(volatile u8 *) Addr; +} + +/*****************************************************************************/ +/** +* +* @brief Performs an input operation for a memory location by reading from +* the specified address and returning the 16 bit Value read from that +* address. +* +* @param Addr: contains the address to perform the input operation +* +* @return The 16 bit Value read from the specified input address. +* +******************************************************************************/ +static INLINE u16 Xil_In16(UINTPTR Addr) +{ + return *(volatile u16 *) Addr; +} + +/*****************************************************************************/ +/** +* +* @brief Performs an input operation for a memory location by +* reading from the specified address and returning the 32 bit Value +* read from that address. +* +* @param Addr: contains the address to perform the input operation +* +* @return The 32 bit Value read from the specified input address. +* +******************************************************************************/ +static INLINE u32 Xil_In32(UINTPTR Addr) +{ + return *(volatile u32 *) Addr; +} + +/*****************************************************************************/ +/** +* +* @brief Performs an input operation for a memory location by reading the +* 64 bit Value read from that address. +* +* +* @param Addr: contains the address to perform the input operation +* +* @return The 64 bit Value read from the specified input address. +* +******************************************************************************/ +static INLINE u64 Xil_In64(UINTPTR Addr) +{ + return *(volatile u64 *) Addr; +} + +/*****************************************************************************/ +/** +* +* @brief Performs an output operation for an memory location by +* writing the 8 bit Value to the the specified address. +* +* @param Addr: contains the address to perform the output operation +* @param Value: contains the 8 bit Value to be written at the specified +* address. +* +* @return None. +* +******************************************************************************/ +static INLINE void Xil_Out8(UINTPTR Addr, u8 Value) +{ + volatile u8 *LocalAddr = (volatile u8 *)Addr; + *LocalAddr = Value; +} + +/*****************************************************************************/ +/** +* +* @brief Performs an output operation for a memory location by writing the +* 16 bit Value to the the specified address. +* +* @param Addr contains the address to perform the output operation +* @param Value contains the Value to be written at the specified address. +* +* @return None. +* +******************************************************************************/ +static INLINE void Xil_Out16(UINTPTR Addr, u16 Value) +{ + volatile u16 *LocalAddr = (volatile u16 *)Addr; + *LocalAddr = Value; +} + +/*****************************************************************************/ +/** +* +* @brief Performs an output operation for a memory location by writing the +* 32 bit Value to the the specified address. +* +* @param Addr contains the address to perform the output operation +* @param Value contains the 32 bit Value to be written at the specified +* address. +* +* @return None. +* +******************************************************************************/ +static INLINE void Xil_Out32(UINTPTR Addr, u32 Value) +{ +#ifndef ENABLE_SAFETY + volatile u32 *LocalAddr = (volatile u32 *)Addr; + *LocalAddr = Value; +#else + XStl_RegUpdate(Addr, Value); +#endif +} + +/*****************************************************************************/ +/** +* +* @brief Performs an output operation for a memory location by writing the +* 64 bit Value to the the specified address. +* +* @param Addr contains the address to perform the output operation +* @param Value contains 64 bit Value to be written at the specified address. +* +* @return None. +* +******************************************************************************/ +static INLINE void Xil_Out64(UINTPTR Addr, u64 Value) +{ + volatile u64 *LocalAddr = (volatile u64 *)Addr; + *LocalAddr = Value; +} + +#if defined (__MICROBLAZE__) +#ifdef __LITTLE_ENDIAN__ +# define Xil_In16LE Xil_In16 +# define Xil_In32LE Xil_In32 +# define Xil_Out16LE Xil_Out16 +# define Xil_Out32LE Xil_Out32 +# define Xil_Htons Xil_EndianSwap16 +# define Xil_Htonl Xil_EndianSwap32 +# define Xil_Ntohs Xil_EndianSwap16 +# define Xil_Ntohl Xil_EndianSwap32 +# else +# define Xil_In16BE Xil_In16 +# define Xil_In32BE Xil_In32 +# define Xil_Out16BE Xil_Out16 +# define Xil_Out32BE Xil_Out32 +# define Xil_Htons(Data) (Data) +# define Xil_Htonl(Data) (Data) +# define Xil_Ntohs(Data) (Data) +# define Xil_Ntohl(Data) (Data) +#endif +#else +# define Xil_In16LE Xil_In16 +# define Xil_In32LE Xil_In32 +# define Xil_Out16LE Xil_Out16 +# define Xil_Out32LE Xil_Out32 +# define Xil_Htons Xil_EndianSwap16 +# define Xil_Htonl Xil_EndianSwap32 +# define Xil_Ntohs Xil_EndianSwap16 +# define Xil_Ntohl Xil_EndianSwap32 +#endif + +#if defined (__MICROBLAZE__) +#ifdef __LITTLE_ENDIAN__ +static INLINE u16 Xil_In16BE(UINTPTR Addr) +#else +static INLINE u16 Xil_In16LE(UINTPTR Addr) +#endif +#else +static INLINE u16 Xil_In16BE(UINTPTR Addr) +#endif +{ + u16 value = Xil_In16(Addr); + return Xil_EndianSwap16(value); +} + +#if defined (__MICROBLAZE__) +#ifdef __LITTLE_ENDIAN__ +static INLINE u32 Xil_In32BE(UINTPTR Addr) +#else +static INLINE u32 Xil_In32LE(UINTPTR Addr) +#endif +#else +static INLINE u32 Xil_In32BE(UINTPTR Addr) +#endif +{ + u32 value = Xil_In32(Addr); + return Xil_EndianSwap32(value); +} + +#if defined (__MICROBLAZE__) +#ifdef __LITTLE_ENDIAN__ +static INLINE void Xil_Out16BE(UINTPTR Addr, u16 Value) +#else +static INLINE void Xil_Out16LE(UINTPTR Addr, u16 Value) +#endif +#else +static INLINE void Xil_Out16BE(UINTPTR Addr, u16 Value) +#endif +{ + Value = Xil_EndianSwap16(Value); + Xil_Out16(Addr, Value); +} + +#if defined (__MICROBLAZE__) +#ifdef __LITTLE_ENDIAN__ +static INLINE void Xil_Out32BE(UINTPTR Addr, u32 Value) +#else +static INLINE void Xil_Out32LE(UINTPTR Addr, u32 Value) +#endif +#else +static INLINE void Xil_Out32BE(UINTPTR Addr, u32 Value) +#endif +{ + Value = Xil_EndianSwap32(Value); + Xil_Out32(Addr, Value); +} + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** +* @} End of "addtogroup common_io_interfacing_apis". +*/ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/include/xil_macroback.h b/datalink814_ge/bsp/ps7_cortexa9_0/include/xil_macroback.h new file mode 100644 index 0000000..b245c18 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/include/xil_macroback.h @@ -0,0 +1,1056 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +/*********************************************************************/ +/** + * @file xil_macroback.h + * + * This header file is meant to bring back the removed _m macros. + * This header file must be included last. + * The following macros are not defined here due to the driver change: + * XGpio_mSetDataDirection + * XGpio_mGetDataReg + * XGpio_mSetDataReg + * XIIC_RESET + * XIIC_CLEAR_STATS + * XSpi_mReset + * XSysAce_mSetCfgAddr + * XSysAce_mIsCfgDone + * XTft_mSetPixel + * XTft_mGetPixel + * XWdtTb_mEnableWdt + * XWdtTb_mDisbleWdt + * XWdtTb_mRestartWdt + * XWdtTb_mGetTimebaseReg + * XWdtTb_mHasReset + * + * Please refer the corresonding driver document for replacement. + * + *********************************************************************/ + +#ifndef XIL_MACROBACK_H +#define XIL_MACROBACK_H + +#ifdef __cplusplus +extern "C" { +#endif + +/*********************************************************************/ +/** + * Macros for Driver XCan + * + *********************************************************************/ +#ifndef XCan_mReadReg +#define XCan_mReadReg XCan_ReadReg +#endif + +#ifndef XCan_mWriteReg +#define XCan_mWriteReg XCan_WriteReg +#endif + +#ifndef XCan_mIsTxDone +#define XCan_mIsTxDone XCan_IsTxDone +#endif + +#ifndef XCan_mIsTxFifoFull +#define XCan_mIsTxFifoFull XCan_IsTxFifoFull +#endif + +#ifndef XCan_mIsHighPriorityBufFull +#define XCan_mIsHighPriorityBufFull XCan_IsHighPriorityBufFull +#endif + +#ifndef XCan_mIsRxEmpty +#define XCan_mIsRxEmpty XCan_IsRxEmpty +#endif + +#ifndef XCan_mIsAcceptFilterBusy +#define XCan_mIsAcceptFilterBusy XCan_IsAcceptFilterBusy +#endif + +#ifndef XCan_mCreateIdValue +#define XCan_mCreateIdValue XCan_CreateIdValue +#endif + +#ifndef XCan_mCreateDlcValue +#define XCan_mCreateDlcValue XCan_CreateDlcValue +#endif + +/*********************************************************************/ +/** + * Macros for Driver XDmaCentral + * + *********************************************************************/ +#ifndef XDmaCentral_mWriteReg +#define XDmaCentral_mWriteReg XDmaCentral_WriteReg +#endif + +#ifndef XDmaCentral_mReadReg +#define XDmaCentral_mReadReg XDmaCentral_ReadReg +#endif + +/*********************************************************************/ +/** + * Macros for Driver XDsAdc + * + *********************************************************************/ +#ifndef XDsAdc_mWriteReg +#define XDsAdc_mWriteReg XDsAdc_WriteReg +#endif + +#ifndef XDsAdc_mReadReg +#define XDsAdc_mReadReg XDsAdc_ReadReg +#endif + +#ifndef XDsAdc_mIsEmpty +#define XDsAdc_mIsEmpty XDsAdc_IsEmpty +#endif + +#ifndef XDsAdc_mSetFstmReg +#define XDsAdc_mSetFstmReg XDsAdc_SetFstmReg +#endif + +#ifndef XDsAdc_mGetFstmReg +#define XDsAdc_mGetFstmReg XDsAdc_GetFstmReg +#endif + +#ifndef XDsAdc_mEnableConversion +#define XDsAdc_mEnableConversion XDsAdc_EnableConversion +#endif + +#ifndef XDsAdc_mDisableConversion +#define XDsAdc_mDisableConversion XDsAdc_DisableConversion +#endif + +#ifndef XDsAdc_mGetFifoOccyReg +#define XDsAdc_mGetFifoOccyReg XDsAdc_GetFifoOccyReg +#endif + +/*********************************************************************/ +/** + * Macros for Driver XDsDac + * + *********************************************************************/ +#ifndef XDsDac_mWriteReg +#define XDsDac_mWriteReg XDsDac_WriteReg +#endif + +#ifndef XDsDac_mReadReg +#define XDsDac_mReadReg XDsDac_ReadReg +#endif + +#ifndef XDsDac_mIsEmpty +#define XDsDac_mIsEmpty XDsDac_IsEmpty +#endif + +#ifndef XDsDac_mFifoIsFull +#define XDsDac_mFifoIsFull XDsDac_FifoIsFull +#endif + +#ifndef XDsDac_mGetVacancy +#define XDsDac_mGetVacancy XDsDac_GetVacancy +#endif + +/*********************************************************************/ +/** + * Macros for Driver XEmacLite + * + *********************************************************************/ +#ifndef XEmacLite_mReadReg +#define XEmacLite_mReadReg XEmacLite_ReadReg +#endif + +#ifndef XEmacLite_mWriteReg +#define XEmacLite_mWriteReg XEmacLite_WriteReg +#endif + +#ifndef XEmacLite_mGetTxStatus +#define XEmacLite_mGetTxStatus XEmacLite_GetTxStatus +#endif + +#ifndef XEmacLite_mSetTxStatus +#define XEmacLite_mSetTxStatus XEmacLite_SetTxStatus +#endif + +#ifndef XEmacLite_mGetRxStatus +#define XEmacLite_mGetRxStatus XEmacLite_GetRxStatus +#endif + +#ifndef XEmacLite_mSetRxStatus +#define XEmacLite_mSetRxStatus XEmacLite_SetRxStatus +#endif + +#ifndef XEmacLite_mIsTxDone +#define XEmacLite_mIsTxDone XEmacLite_IsTxDone +#endif + +#ifndef XEmacLite_mIsRxEmpty +#define XEmacLite_mIsRxEmpty XEmacLite_IsRxEmpty +#endif + +#ifndef XEmacLite_mNextTransmitAddr +#define XEmacLite_mNextTransmitAddr XEmacLite_NextTransmitAddr +#endif + +#ifndef XEmacLite_mNextReceiveAddr +#define XEmacLite_mNextReceiveAddr XEmacLite_NextReceiveAddr +#endif + +#ifndef XEmacLite_mIsMdioConfigured +#define XEmacLite_mIsMdioConfigured XEmacLite_IsMdioConfigured +#endif + +#ifndef XEmacLite_mIsLoopbackConfigured +#define XEmacLite_mIsLoopbackConfigured XEmacLite_IsLoopbackConfigured +#endif + +#ifndef XEmacLite_mGetReceiveDataLength +#define XEmacLite_mGetReceiveDataLength XEmacLite_GetReceiveDataLength +#endif + +#ifndef XEmacLite_mGetTxActive +#define XEmacLite_mGetTxActive XEmacLite_GetTxActive +#endif + +#ifndef XEmacLite_mSetTxActive +#define XEmacLite_mSetTxActive XEmacLite_SetTxActive +#endif + +/*********************************************************************/ +/** + * Macros for Driver XGpio + * + *********************************************************************/ +#ifndef XGpio_mWriteReg +#define XGpio_mWriteReg XGpio_WriteReg +#endif + +#ifndef XGpio_mReadReg +#define XGpio_mReadReg XGpio_ReadReg +#endif + +/*********************************************************************/ +/** + * Macros for Driver XHwIcap + * + *********************************************************************/ +#ifndef XHwIcap_mFifoWrite +#define XHwIcap_mFifoWrite XHwIcap_FifoWrite +#endif + +#ifndef XHwIcap_mFifoRead +#define XHwIcap_mFifoRead XHwIcap_FifoRead +#endif + +#ifndef XHwIcap_mSetSizeReg +#define XHwIcap_mSetSizeReg XHwIcap_SetSizeReg +#endif + +#ifndef XHwIcap_mGetControlReg +#define XHwIcap_mGetControlReg XHwIcap_GetControlReg +#endif + +#ifndef XHwIcap_mStartConfig +#define XHwIcap_mStartConfig XHwIcap_StartConfig +#endif + +#ifndef XHwIcap_mStartReadBack +#define XHwIcap_mStartReadBack XHwIcap_StartReadBack +#endif + +#ifndef XHwIcap_mGetStatusReg +#define XHwIcap_mGetStatusReg XHwIcap_GetStatusReg +#endif + +#ifndef XHwIcap_mIsTransferDone +#define XHwIcap_mIsTransferDone XHwIcap_IsTransferDone +#endif + +#ifndef XHwIcap_mIsDeviceBusy +#define XHwIcap_mIsDeviceBusy XHwIcap_IsDeviceBusy +#endif + +#ifndef XHwIcap_mIntrGlobalEnable +#define XHwIcap_mIntrGlobalEnable XHwIcap_IntrGlobalEnable +#endif + +#ifndef XHwIcap_mIntrGlobalDisable +#define XHwIcap_mIntrGlobalDisable XHwIcap_IntrGlobalDisable +#endif + +#ifndef XHwIcap_mIntrGetStatus +#define XHwIcap_mIntrGetStatus XHwIcap_IntrGetStatus +#endif + +#ifndef XHwIcap_mIntrDisable +#define XHwIcap_mIntrDisable XHwIcap_IntrDisable +#endif + +#ifndef XHwIcap_mIntrEnable +#define XHwIcap_mIntrEnable XHwIcap_IntrEnable +#endif + +#ifndef XHwIcap_mIntrGetEnabled +#define XHwIcap_mIntrGetEnabled XHwIcap_IntrGetEnabled +#endif + +#ifndef XHwIcap_mIntrClear +#define XHwIcap_mIntrClear XHwIcap_IntrClear +#endif + +#ifndef XHwIcap_mGetWrFifoVacancy +#define XHwIcap_mGetWrFifoVacancy XHwIcap_GetWrFifoVacancy +#endif + +#ifndef XHwIcap_mGetRdFifoOccupancy +#define XHwIcap_mGetRdFifoOccupancy XHwIcap_GetRdFifoOccupancy +#endif + +#ifndef XHwIcap_mSliceX2Col +#define XHwIcap_mSliceX2Col XHwIcap_SliceX2Col +#endif + +#ifndef XHwIcap_mSliceY2Row +#define XHwIcap_mSliceY2Row XHwIcap_SliceY2Row +#endif + +#ifndef XHwIcap_mSliceXY2Slice +#define XHwIcap_mSliceXY2Slice XHwIcap_SliceXY2Slice +#endif + +#ifndef XHwIcap_mReadReg +#define XHwIcap_mReadReg XHwIcap_ReadReg +#endif + +#ifndef XHwIcap_mWriteReg +#define XHwIcap_mWriteReg XHwIcap_WriteReg +#endif + +/*********************************************************************/ +/** + * Macros for Driver XIic + * + *********************************************************************/ +#ifndef XIic_mReadReg +#define XIic_mReadReg XIic_ReadReg +#endif + +#ifndef XIic_mWriteReg +#define XIic_mWriteReg XIic_WriteReg +#endif + +#ifndef XIic_mEnterCriticalRegion +#define XIic_mEnterCriticalRegion XIic_IntrGlobalDisable +#endif + +#ifndef XIic_mExitCriticalRegion +#define XIic_mExitCriticalRegion XIic_IntrGlobalEnable +#endif + +#ifndef XIIC_GINTR_DISABLE +#define XIIC_GINTR_DISABLE XIic_IntrGlobalDisable +#endif + +#ifndef XIIC_GINTR_ENABLE +#define XIIC_GINTR_ENABLE XIic_IntrGlobalEnable +#endif + +#ifndef XIIC_IS_GINTR_ENABLED +#define XIIC_IS_GINTR_ENABLED XIic_IsIntrGlobalEnabled +#endif + +#ifndef XIIC_WRITE_IISR +#define XIIC_WRITE_IISR XIic_WriteIisr +#endif + +#ifndef XIIC_READ_IISR +#define XIIC_READ_IISR XIic_ReadIisr +#endif + +#ifndef XIIC_WRITE_IIER +#define XIIC_WRITE_IIER XIic_WriteIier +#endif + +#ifndef XIic_mClearIisr +#define XIic_mClearIisr XIic_ClearIisr +#endif + +#ifndef XIic_mSend7BitAddress +#define XIic_mSend7BitAddress XIic_Send7BitAddress +#endif + +#ifndef XIic_mDynSend7BitAddress +#define XIic_mDynSend7BitAddress XIic_DynSend7BitAddress +#endif + +#ifndef XIic_mDynSendStartStopAddress +#define XIic_mDynSendStartStopAddress XIic_DynSendStartStopAddress +#endif + +#ifndef XIic_mDynSendStop +#define XIic_mDynSendStop XIic_DynSendStop +#endif + +#ifndef XIic_mSend10BitAddrByte1 +#define XIic_mSend10BitAddrByte1 XIic_Send10BitAddrByte1 +#endif + +#ifndef XIic_mSend10BitAddrByte2 +#define XIic_mSend10BitAddrByte2 XIic_Send10BitAddrByte2 +#endif + +#ifndef XIic_mSend7BitAddr +#define XIic_mSend7BitAddr XIic_Send7BitAddr +#endif + +#ifndef XIic_mDisableIntr +#define XIic_mDisableIntr XIic_DisableIntr +#endif + +#ifndef XIic_mEnableIntr +#define XIic_mEnableIntr XIic_EnableIntr +#endif + +#ifndef XIic_mClearIntr +#define XIic_mClearIntr XIic_ClearIntr +#endif + +#ifndef XIic_mClearEnableIntr +#define XIic_mClearEnableIntr XIic_ClearEnableIntr +#endif + +#ifndef XIic_mFlushRxFifo +#define XIic_mFlushRxFifo XIic_FlushRxFifo +#endif + +#ifndef XIic_mFlushTxFifo +#define XIic_mFlushTxFifo XIic_FlushTxFifo +#endif + +#ifndef XIic_mReadRecvByte +#define XIic_mReadRecvByte XIic_ReadRecvByte +#endif + +#ifndef XIic_mWriteSendByte +#define XIic_mWriteSendByte XIic_WriteSendByte +#endif + +#ifndef XIic_mSetControlRegister +#define XIic_mSetControlRegister XIic_SetControlRegister +#endif + +/*********************************************************************/ +/** + * Macros for Driver XIntc + * + *********************************************************************/ +#ifndef XIntc_mMasterEnable +#define XIntc_mMasterEnable XIntc_MasterEnable +#endif + +#ifndef XIntc_mMasterDisable +#define XIntc_mMasterDisable XIntc_MasterDisable +#endif + +#ifndef XIntc_mEnableIntr +#define XIntc_mEnableIntr XIntc_EnableIntr +#endif + +#ifndef XIntc_mDisableIntr +#define XIntc_mDisableIntr XIntc_DisableIntr +#endif + +#ifndef XIntc_mAckIntr +#define XIntc_mAckIntr XIntc_AckIntr +#endif + +#ifndef XIntc_mGetIntrStatus +#define XIntc_mGetIntrStatus XIntc_GetIntrStatus +#endif + +/*********************************************************************/ +/** + * Macros for Driver XLlDma + * + *********************************************************************/ +#ifndef XLlDma_mBdRead +#define XLlDma_mBdRead XLlDma_BdRead +#endif + +#ifndef XLlDma_mBdWrite +#define XLlDma_mBdWrite XLlDma_BdWrite +#endif + +#ifndef XLlDma_mWriteReg +#define XLlDma_mWriteReg XLlDma_WriteReg +#endif + +#ifndef XLlDma_mReadReg +#define XLlDma_mReadReg XLlDma_ReadReg +#endif + +#ifndef XLlDma_mBdClear +#define XLlDma_mBdClear XLlDma_BdClear +#endif + +#ifndef XLlDma_mBdSetStsCtrl +#define XLlDma_mBdSetStsCtrl XLlDma_BdSetStsCtrl +#endif + +#ifndef XLlDma_mBdGetStsCtrl +#define XLlDma_mBdGetStsCtrl XLlDma_BdGetStsCtrl +#endif + +#ifndef XLlDma_mBdSetLength +#define XLlDma_mBdSetLength XLlDma_BdSetLength +#endif + +#ifndef XLlDma_mBdGetLength +#define XLlDma_mBdGetLength XLlDma_BdGetLength +#endif + +#ifndef XLlDma_mBdSetId +#define XLlDma_mBdSetId XLlDma_BdSetId +#endif + +#ifndef XLlDma_mBdGetId +#define XLlDma_mBdGetId XLlDma_BdGetId +#endif + +#ifndef XLlDma_mBdSetBufAddr +#define XLlDma_mBdSetBufAddr XLlDma_BdSetBufAddr +#endif + +#ifndef XLlDma_mBdGetBufAddr +#define XLlDma_mBdGetBufAddr XLlDma_BdGetBufAddr +#endif + +#ifndef XLlDma_mBdGetLength +#define XLlDma_mBdGetLength XLlDma_BdGetLength +#endif + +#ifndef XLlDma_mGetTxRing +#define XLlDma_mGetTxRing XLlDma_GetTxRing +#endif + +#ifndef XLlDma_mGetRxRing +#define XLlDma_mGetRxRing XLlDma_GetRxRing +#endif + +#ifndef XLlDma_mGetCr +#define XLlDma_mGetCr XLlDma_GetCr +#endif + +#ifndef XLlDma_mSetCr +#define XLlDma_mSetCr XLlDma_SetCr +#endif + +#ifndef XLlDma_mBdRingCntCalc +#define XLlDma_mBdRingCntCalc XLlDma_BdRingCntCalc +#endif + +#ifndef XLlDma_mBdRingMemCalc +#define XLlDma_mBdRingMemCalc XLlDma_BdRingMemCalc +#endif + +#ifndef XLlDma_mBdRingGetCnt +#define XLlDma_mBdRingGetCnt XLlDma_BdRingGetCnt +#endif + +#ifndef XLlDma_mBdRingGetFreeCnt +#define XLlDma_mBdRingGetFreeCnt XLlDma_BdRingGetFreeCnt +#endif + +#ifndef XLlDma_mBdRingSnapShotCurrBd +#define XLlDma_mBdRingSnapShotCurrBd XLlDma_BdRingSnapShotCurrBd +#endif + +#ifndef XLlDma_mBdRingNext +#define XLlDma_mBdRingNext XLlDma_BdRingNext +#endif + +#ifndef XLlDma_mBdRingPrev +#define XLlDma_mBdRingPrev XLlDma_BdRingPrev +#endif + +#ifndef XLlDma_mBdRingGetSr +#define XLlDma_mBdRingGetSr XLlDma_BdRingGetSr +#endif + +#ifndef XLlDma_mBdRingSetSr +#define XLlDma_mBdRingSetSr XLlDma_BdRingSetSr +#endif + +#ifndef XLlDma_mBdRingGetCr +#define XLlDma_mBdRingGetCr XLlDma_BdRingGetCr +#endif + +#ifndef XLlDma_mBdRingSetCr +#define XLlDma_mBdRingSetCr XLlDma_BdRingSetCr +#endif + +#ifndef XLlDma_mBdRingBusy +#define XLlDma_mBdRingBusy XLlDma_BdRingBusy +#endif + +#ifndef XLlDma_mBdRingIntEnable +#define XLlDma_mBdRingIntEnable XLlDma_BdRingIntEnable +#endif + +#ifndef XLlDma_mBdRingIntDisable +#define XLlDma_mBdRingIntDisable XLlDma_BdRingIntDisable +#endif + +#ifndef XLlDma_mBdRingIntGetEnabled +#define XLlDma_mBdRingIntGetEnabled XLlDma_BdRingIntGetEnabled +#endif + +#ifndef XLlDma_mBdRingGetIrq +#define XLlDma_mBdRingGetIrq XLlDma_BdRingGetIrq +#endif + +#ifndef XLlDma_mBdRingAckIrq +#define XLlDma_mBdRingAckIrq XLlDma_BdRingAckIrq +#endif + +/*********************************************************************/ +/** + * Macros for Driver XMbox + * + *********************************************************************/ +#ifndef XMbox_mWriteReg +#define XMbox_mWriteReg XMbox_WriteReg +#endif + +#ifndef XMbox_mReadReg +#define XMbox_mReadReg XMbox_ReadReg +#endif + +#ifndef XMbox_mWriteMBox +#define XMbox_mWriteMBox XMbox_WriteMBox +#endif + +#ifndef XMbox_mReadMBox +#define XMbox_mReadMBox XMbox_ReadMBox +#endif + +#ifndef XMbox_mFSLReadMBox +#define XMbox_mFSLReadMBox XMbox_FSLReadMBox +#endif + +#ifndef XMbox_mFSLWriteMBox +#define XMbox_mFSLWriteMBox XMbox_FSLWriteMBox +#endif + +#ifndef XMbox_mFSLIsEmpty +#define XMbox_mFSLIsEmpty XMbox_FSLIsEmpty +#endif + +#ifndef XMbox_mFSLIsFull +#define XMbox_mFSLIsFull XMbox_FSLIsFull +#endif + +#ifndef XMbox_mIsEmpty +#define XMbox_mIsEmpty XMbox_IsEmptyHw +#endif + +#ifndef XMbox_mIsFull +#define XMbox_mIsFull XMbox_IsFullHw +#endif + +/*********************************************************************/ +/** + * Macros for Driver XMpmc + * + *********************************************************************/ +#ifndef XMpmc_mReadReg +#define XMpmc_mReadReg XMpmc_ReadReg +#endif + +#ifndef XMpmc_mWriteReg +#define XMpmc_mWriteReg XMpmc_WriteReg +#endif + +/*********************************************************************/ +/** + * Macros for Driver XMutex + * + *********************************************************************/ +#ifndef XMutex_mWriteReg +#define XMutex_mWriteReg XMutex_WriteReg +#endif + +#ifndef XMutex_mReadReg +#define XMutex_mReadReg XMutex_ReadReg +#endif + +/*********************************************************************/ +/** + * Macros for Driver XPcie + * + *********************************************************************/ +#ifndef XPcie_mReadReg +#define XPcie_mReadReg XPcie_ReadReg +#endif + +#ifndef XPcie_mWriteReg +#define XPcie_mWriteReg XPcie_WriteReg +#endif + +/*********************************************************************/ +/** + * Macros for Driver XSpi + * + *********************************************************************/ +#ifndef XSpi_mIntrGlobalEnable +#define XSpi_mIntrGlobalEnable XSpi_IntrGlobalEnable +#endif + +#ifndef XSpi_mIntrGlobalDisable +#define XSpi_mIntrGlobalDisable XSpi_IntrGlobalDisable +#endif + +#ifndef XSpi_mIsIntrGlobalEnabled +#define XSpi_mIsIntrGlobalEnabled XSpi_IsIntrGlobalEnabled +#endif + +#ifndef XSpi_mIntrGetStatus +#define XSpi_mIntrGetStatus XSpi_IntrGetStatus +#endif + +#ifndef XSpi_mIntrClear +#define XSpi_mIntrClear XSpi_IntrClear +#endif + +#ifndef XSpi_mIntrEnable +#define XSpi_mIntrEnable XSpi_IntrEnable +#endif + +#ifndef XSpi_mIntrDisable +#define XSpi_mIntrDisable XSpi_IntrDisable +#endif + +#ifndef XSpi_mIntrGetEnabled +#define XSpi_mIntrGetEnabled XSpi_IntrGetEnabled +#endif + +#ifndef XSpi_mSetControlReg +#define XSpi_mSetControlReg XSpi_SetControlReg +#endif + +#ifndef XSpi_mGetControlReg +#define XSpi_mGetControlReg XSpi_GetControlReg +#endif + +#ifndef XSpi_mGetStatusReg +#define XSpi_mGetStatusReg XSpi_GetStatusReg +#endif + +#ifndef XSpi_mSetSlaveSelectReg +#define XSpi_mSetSlaveSelectReg XSpi_SetSlaveSelectReg +#endif + +#ifndef XSpi_mGetSlaveSelectReg +#define XSpi_mGetSlaveSelectReg XSpi_GetSlaveSelectReg +#endif + +#ifndef XSpi_mEnable +#define XSpi_mEnable XSpi_Enable +#endif + +#ifndef XSpi_mDisable +#define XSpi_mDisable XSpi_Disable +#endif + +/*********************************************************************/ +/** + * Macros for Driver XSysAce + * + *********************************************************************/ +#ifndef XSysAce_mGetControlReg +#define XSysAce_mGetControlReg XSysAce_GetControlReg +#endif + +#ifndef XSysAce_mSetControlReg +#define XSysAce_mSetControlReg XSysAce_SetControlReg +#endif + +#ifndef XSysAce_mOrControlReg +#define XSysAce_mOrControlReg XSysAce_OrControlReg +#endif + +#ifndef XSysAce_mAndControlReg +#define XSysAce_mAndControlReg XSysAce_AndControlReg +#endif + +#ifndef XSysAce_mGetErrorReg +#define XSysAce_mGetErrorReg XSysAce_GetErrorReg +#endif + +#ifndef XSysAce_mGetStatusReg +#define XSysAce_mGetStatusReg XSysAce_GetStatusReg +#endif + +#ifndef XSysAce_mWaitForLock +#define XSysAce_mWaitForLock XSysAce_WaitForLock +#endif + +#ifndef XSysAce_mEnableIntr +#define XSysAce_mEnableIntr XSysAce_EnableIntr +#endif + +#ifndef XSysAce_mDisableIntr +#define XSysAce_mDisableIntr XSysAce_DisableIntr +#endif + +#ifndef XSysAce_mIsReadyForCmd +#define XSysAce_mIsReadyForCmd XSysAce_IsReadyForCmd +#endif + +#ifndef XSysAce_mIsMpuLocked +#define XSysAce_mIsMpuLocked XSysAce_IsMpuLocked +#endif + +#ifndef XSysAce_mIsIntrEnabled +#define XSysAce_mIsIntrEnabled XSysAce_IsIntrEnabled +#endif + +/*********************************************************************/ +/** + * Macros for Driver XSysMon + * + *********************************************************************/ +#ifndef XSysMon_mIsEventSamplingModeSet +#define XSysMon_mIsEventSamplingModeSet XSysMon_IsEventSamplingModeSet +#endif + +#ifndef XSysMon_mIsDrpBusy +#define XSysMon_mIsDrpBusy XSysMon_IsDrpBusy +#endif + +#ifndef XSysMon_mIsDrpLocked +#define XSysMon_mIsDrpLocked XSysMon_IsDrpLocked +#endif + +#ifndef XSysMon_mRawToTemperature +#define XSysMon_mRawToTemperature XSysMon_RawToTemperature +#endif + +#ifndef XSysMon_mRawToVoltage +#define XSysMon_mRawToVoltage XSysMon_RawToVoltage +#endif + +#ifndef XSysMon_mTemperatureToRaw +#define XSysMon_mTemperatureToRaw XSysMon_TemperatureToRaw +#endif + +#ifndef XSysMon_mVoltageToRaw +#define XSysMon_mVoltageToRaw XSysMon_VoltageToRaw +#endif + +#ifndef XSysMon_mReadReg +#define XSysMon_mReadReg XSysMon_ReadReg +#endif + +#ifndef XSysMon_mWriteReg +#define XSysMon_mWriteReg XSysMon_WriteReg +#endif + +/*********************************************************************/ +/** + * Macros for Driver XTmrCtr + * + *********************************************************************/ +#ifndef XTimerCtr_mReadReg +#define XTimerCtr_mReadReg XTimerCtr_ReadReg +#endif + +#ifndef XTmrCtr_mWriteReg +#define XTmrCtr_mWriteReg XTmrCtr_WriteReg +#endif + +#ifndef XTmrCtr_mSetControlStatusReg +#define XTmrCtr_mSetControlStatusReg XTmrCtr_SetControlStatusReg +#endif + +#ifndef XTmrCtr_mGetControlStatusReg +#define XTmrCtr_mGetControlStatusReg XTmrCtr_GetControlStatusReg +#endif + +#ifndef XTmrCtr_mGetTimerCounterReg +#define XTmrCtr_mGetTimerCounterReg XTmrCtr_GetTimerCounterReg +#endif + +#ifndef XTmrCtr_mSetLoadReg +#define XTmrCtr_mSetLoadReg XTmrCtr_SetLoadReg +#endif + +#ifndef XTmrCtr_mGetLoadReg +#define XTmrCtr_mGetLoadReg XTmrCtr_GetLoadReg +#endif + +#ifndef XTmrCtr_mEnable +#define XTmrCtr_mEnable XTmrCtr_Enable +#endif + +#ifndef XTmrCtr_mDisable +#define XTmrCtr_mDisable XTmrCtr_Disable +#endif + +#ifndef XTmrCtr_mEnableIntr +#define XTmrCtr_mEnableIntr XTmrCtr_EnableIntr +#endif + +#ifndef XTmrCtr_mDisableIntr +#define XTmrCtr_mDisableIntr XTmrCtr_DisableIntr +#endif + +#ifndef XTmrCtr_mLoadTimerCounterReg +#define XTmrCtr_mLoadTimerCounterReg XTmrCtr_LoadTimerCounterReg +#endif + +#ifndef XTmrCtr_mHasEventOccurred +#define XTmrCtr_mHasEventOccurred XTmrCtr_HasEventOccurred +#endif + +/*********************************************************************/ +/** + * Macros for Driver XUartLite + * + *********************************************************************/ +#ifndef XUartLite_mUpdateStats +#define XUartLite_mUpdateStats XUartLite_UpdateStats +#endif + +#ifndef XUartLite_mWriteReg +#define XUartLite_mWriteReg XUartLite_WriteReg +#endif + +#ifndef XUartLite_mReadReg +#define XUartLite_mReadReg XUartLite_ReadReg +#endif + +#ifndef XUartLite_mClearStats +#define XUartLite_mClearStats XUartLite_ClearStats +#endif + +#ifndef XUartLite_mSetControlReg +#define XUartLite_mSetControlReg XUartLite_SetControlReg +#endif + +#ifndef XUartLite_mGetStatusReg +#define XUartLite_mGetStatusReg XUartLite_GetStatusReg +#endif + +#ifndef XUartLite_mIsReceiveEmpty +#define XUartLite_mIsReceiveEmpty XUartLite_IsReceiveEmpty +#endif + +#ifndef XUartLite_mIsTransmitFull +#define XUartLite_mIsTransmitFull XUartLite_IsTransmitFull +#endif + +#ifndef XUartLite_mIsIntrEnabled +#define XUartLite_mIsIntrEnabled XUartLite_IsIntrEnabled +#endif + +#ifndef XUartLite_mEnableIntr +#define XUartLite_mEnableIntr XUartLite_EnableIntr +#endif + +#ifndef XUartLite_mDisableIntr +#define XUartLite_mDisableIntr XUartLite_DisableIntr +#endif + +/*********************************************************************/ +/** + * Macros for Driver XUartNs550 + * + *********************************************************************/ +#ifndef XUartNs550_mUpdateStats +#define XUartNs550_mUpdateStats XUartNs550_UpdateStats +#endif + +#ifndef XUartNs550_mReadReg +#define XUartNs550_mReadReg XUartNs550_ReadReg +#endif + +#ifndef XUartNs550_mWriteReg +#define XUartNs550_mWriteReg XUartNs550_WriteReg +#endif + +#ifndef XUartNs550_mClearStats +#define XUartNs550_mClearStats XUartNs550_ClearStats +#endif + +#ifndef XUartNs550_mGetLineStatusReg +#define XUartNs550_mGetLineStatusReg XUartNs550_GetLineStatusReg +#endif + +#ifndef XUartNs550_mGetLineControlReg +#define XUartNs550_mGetLineControlReg XUartNs550_GetLineControlReg +#endif + +#ifndef XUartNs550_mSetLineControlReg +#define XUartNs550_mSetLineControlReg XUartNs550_SetLineControlReg +#endif + +#ifndef XUartNs550_mEnableIntr +#define XUartNs550_mEnableIntr XUartNs550_EnableIntr +#endif + +#ifndef XUartNs550_mDisableIntr +#define XUartNs550_mDisableIntr XUartNs550_DisableIntr +#endif + +#ifndef XUartNs550_mIsReceiveData +#define XUartNs550_mIsReceiveData XUartNs550_IsReceiveData +#endif + +#ifndef XUartNs550_mIsTransmitEmpty +#define XUartNs550_mIsTransmitEmpty XUartNs550_IsTransmitEmpty +#endif + +/*********************************************************************/ +/** + * Macros for Driver XUsb + * + *********************************************************************/ +#ifndef XUsb_mReadReg +#define XUsb_mReadReg XUsb_ReadReg +#endif + +#ifndef XUsb_mWriteReg +#define XUsb_mWriteReg XUsb_WriteReg +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/include/xil_mem.h b/datalink814_ge/bsp/ps7_cortexa9_0/include/xil_mem.h new file mode 100644 index 0000000..9aae942 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/include/xil_mem.h @@ -0,0 +1,68 @@ +/******************************************************************************/ +/** +* Copyright (C) 2015 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* @file xil_mem.h +* +* @addtogroup common_mem_operation_api Customized APIs for Memory Operations +* +* The xil_mem.h file contains prototype for functions related +* to memory operations. These APIs are applicable for all processors supported +* by Xilinx. +* +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 6.1   nsk      11/07/16 First release.
+* 7.0   mus      01/07/19 Add cpp extern macro
+*
+* 
+* +*****************************************************************************/ +#ifndef XIL_MEM_H /* prevent circular inclusions */ +#define XIL_MEM_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/************************** Function Prototypes *****************************/ + +void Xil_MemCpy(void* dst, const void* src, u32 cnt); + +#ifdef __cplusplus +} +#endif + +#endif /* XIL_MEM_H */ +/** +* @} End of "addtogroup common_mem_operation_api". +*/ \ No newline at end of file diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/include/xil_misc_psreset_api.h b/datalink814_ge/bsp/ps7_cortexa9_0/include/xil_misc_psreset_api.h new file mode 100644 index 0000000..3a26175 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/include/xil_misc_psreset_api.h @@ -0,0 +1,273 @@ +/****************************************************************************** +* +* Copyright (C) 2013 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file xil_misc_psreset_api.h +* +* This file contains the various register defintions and function prototypes for +* implementing the reset functionality of zynq ps devices +* +* MODIFICATION HISTORY: +* +* Ver Who Date Changes +* ----- ---- -------- ------------------------------------------------------- +* 1.00b kpc 03/07/13 First release. +* +* +******************************************************************************/ + +#ifndef XIL_MISC_RESET_H /* prevent circular inclusions */ +#define XIL_MISC_RESET_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + + +/***************************** Include Files *********************************/ +#include "xil_types.h" +#include "xil_io.h" + +/************************** Constant Definitions *****************************/ +#define XDDRC_CTRL_BASEADDR 0xF8006000U +#define XSLCR_BASEADDR 0xF8000000U +/**< OCM configuration register */ +#define XSLCR_OCM_CFG_ADDR (XSLCR_BASEADDR + 0x00000910U) +/**< SLCR unlock register */ +#define XSLCR_UNLOCK_ADDR (XSLCR_BASEADDR + 0x00000008U) +/**< SLCR GEM0 rx clock control register */ +#define XSLCR_GEM0_RCLK_CTRL_ADDR (XSLCR_BASEADDR + 0x00000138U) +/**< SLCR GEM1 rx clock control register */ +#define XSLCR_GEM1_RCLK_CTRL_ADDR (XSLCR_BASEADDR + 0x0000013CU) +/**< SLCR GEM0 clock control register */ +#define XSLCR_GEM0_CLK_CTRL_ADDR (XSLCR_BASEADDR + 0x00000140U) +/**< SLCR GEM1 clock control register */ +#define XSLCR_GEM1_CLK_CTRL_ADDR (XSLCR_BASEADDR + 0x00000144U) +/**< SLCR SMC clock control register */ +#define XSLCR_SMC_CLK_CTRL_ADDR (XSLCR_BASEADDR + 0x00000148U) +/**< SLCR GEM reset control register */ +#define XSLCR_GEM_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000214U) +/**< SLCR USB0 clock control register */ +#define XSLCR_USB0_CLK_CTRL_ADDR (XSLCR_BASEADDR + 0x00000130U) +/**< SLCR USB1 clock control register */ +#define XSLCR_USB1_CLK_CTRL_ADDR (XSLCR_BASEADDR + 0x00000134U) +/**< SLCR USB1 reset control register */ +#define XSLCR_USB_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000210U) +/**< SLCR SMC reset control register */ +#define XSLCR_SMC_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000234U) +/**< SLCR Level shifter enable register */ +#define XSLCR_LVL_SHFTR_EN_ADDR (XSLCR_BASEADDR + 0x00000900U) +/**< SLCR ARM pll control register */ +#define XSLCR_ARM_PLL_CTRL_ADDR (XSLCR_BASEADDR + 0x00000100U) +/**< SLCR DDR pll control register */ +#define XSLCR_DDR_PLL_CTRL_ADDR (XSLCR_BASEADDR + 0x00000104U) +/**< SLCR IO pll control register */ +#define XSLCR_IO_PLL_CTRL_ADDR (XSLCR_BASEADDR + 0x00000108U) +/**< SLCR ARM pll configuration register */ +#define XSLCR_ARM_PLL_CFG_ADDR (XSLCR_BASEADDR + 0x00000110U) +/**< SLCR DDR pll configuration register */ +#define XSLCR_DDR_PLL_CFG_ADDR (XSLCR_BASEADDR + 0x00000114U) +/**< SLCR IO pll configuration register */ +#define XSLCR_IO_PLL_CFG_ADDR (XSLCR_BASEADDR + 0x00000118U) +/**< SLCR ARM clock control register */ +#define XSLCR_ARM_CLK_CTRL_ADDR (XSLCR_BASEADDR + 0x00000120U) +/**< SLCR DDR clock control register */ +#define XSLCR_DDR_CLK_CTRL_ADDR (XSLCR_BASEADDR + 0x00000124U) +/**< SLCR MIO pin address register */ +#define XSLCR_MIO_PIN_00_ADDR (XSLCR_BASEADDR + 0x00000700U) +/**< SLCR DMAC reset control address register */ +#define XSLCR_DMAC_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x0000020CU) +/**< SLCR USB reset control address register */ +/*#define XSLCR_USB_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000210U)*/ +/**< SLCR GEM reset control address register */ +/*#define XSLCR_GEM_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000214U)*/ +/**< SLCR SDIO reset control address register */ +#define XSLCR_SDIO_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000218U) +/**< SLCR SPI reset control address register */ +#define XSLCR_SPI_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x0000021CU) +/**< SLCR CAN reset control address register */ +#define XSLCR_CAN_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000220U) +/**< SLCR I2C reset control address register */ +#define XSLCR_I2C_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000224U) +/**< SLCR UART reset control address register */ +#define XSLCR_UART_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000228U) +/**< SLCR GPIO reset control address register */ +#define XSLCR_GPIO_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x0000022CU) +/**< SLCR LQSPI reset control address register */ +#define XSLCR_LQSPI_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000230U) +/**< SLCR SMC reset control address register */ +/*#define XSLCR_SMC_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000234U)*/ +/**< SLCR OCM reset control address register */ +#define XSLCR_OCM_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000238U) + +/**< SMC mem controller clear config register */ +#define XSMC_MEMC_CLR_CONFIG_OFFSET 0x0000000CU +/**< SMC idlecount configuration register */ +#define XSMC_REFRESH_PERIOD_0_OFFSET 0x00000020U +#define XSMC_REFRESH_PERIOD_1_OFFSET 0x00000024U +/**< SMC ECC configuration register */ +#define XSMC_ECC_MEMCFG1_OFFSET 0x00000404U +/**< SMC ECC command 1 register */ +#define XSMC_ECC_MEMCMD1_OFFSET 0x00000404U +/**< SMC ECC command 2 register */ +#define XSMC_ECC_MEMCMD2_OFFSET 0x00000404U + +/**< SLCR unlock code */ +#define XSLCR_UNLOCK_CODE 0x0000DF0DU + +/**< SMC mem clear configuration mask */ +#define XSMC_MEMC_CLR_CONFIG_MASK 0x000005FU +/**< SMC ECC memconfig 1 reset value */ +#define XSMC_ECC_MEMCFG1_RESET_VAL 0x0000043U +/**< SMC ECC memcommand 1 reset value */ +#define XSMC_ECC_MEMCMD1_RESET_VAL 0x01300080U +/**< SMC ECC memcommand 2 reset value */ +#define XSMC_ECC_MEMCMD2_RESET_VAL 0x01E00585U + +/**< DDR controller reset bit mask */ +#define XDDRPS_CTRL_RESET_MASK 0x00000001U +/**< SLCR OCM configuration reset value*/ +#define XSLCR_OCM_CFG_RESETVAL 0x00000008U +/**< SLCR OCM bank selection mask*/ +#define XSLCR_OCM_CFG_HIADDR_MASK 0x0000000FU +/**< SLCR level shifter enable mask*/ +#define XSLCR_LVL_SHFTR_EN_MASK 0x0000000FU + +/**< SLCR PLL register reset values */ +#define XSLCR_ARM_PLL_CTRL_RESET_VAL 0x0001A008U +#define XSLCR_DDR_PLL_CTRL_RESET_VAL 0x0001A008U +#define XSLCR_IO_PLL_CTRL_RESET_VAL 0x0001A008U +#define XSLCR_ARM_PLL_CFG_RESET_VAL 0x00177EA0U +#define XSLCR_DDR_PLL_CFG_RESET_VAL 0x00177EA0U +#define XSLCR_IO_PLL_CFG_RESET_VAL 0x00177EA0U +#define XSLCR_ARM_CLK_CTRL_RESET_VAL 0x1F000400U +#define XSLCR_DDR_CLK_CTRL_RESET_VAL 0x18400003U + +/**< SLCR MIO register default values */ +#define XSLCR_MIO_PIN_00_RESET_VAL 0x00001601U +#define XSLCR_MIO_PIN_02_RESET_VAL 0x00000601U + +/**< SLCR Reset control registers default values */ +#define XSLCR_DMAC_RST_CTRL_VAL 0x00000001U +#define XSLCR_GEM_RST_CTRL_VAL 0x000000F3U +#define XSLCR_USB_RST_CTRL_VAL 0x00000003U +#define XSLCR_I2C_RST_CTRL_VAL 0x00000003U +#define XSLCR_SPI_RST_CTRL_VAL 0x0000000FU +#define XSLCR_UART_RST_CTRL_VAL 0x0000000FU +#define XSLCR_QSPI_RST_CTRL_VAL 0x00000003U +#define XSLCR_GPIO_RST_CTRL_VAL 0x00000001U +#define XSLCR_SMC_RST_CTRL_VAL 0x00000003U +#define XSLCR_OCM_RST_CTRL_VAL 0x00000001U +#define XSLCR_SDIO_RST_CTRL_VAL 0x00000033U +#define XSLCR_CAN_RST_CTRL_VAL 0x00000003U +/**************************** Type Definitions *******************************/ + +/* the following data type is used to hold a null terminated version string + * consisting of the following format, "X.YYX" + */ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ +/* + * Performs reset operation to the ddr interface + */ +void XDdr_ResetHw(void); +/* + * Map the ocm region to post bootrom state + */ +void XOcm_Remap(void); +/* + * Performs the smc interface reset + */ +void XSmc_ResetHw(u32 BaseAddress); +/* + * updates the MIO registers with reset values + */ +void XSlcr_MioWriteResetValues(void); +/* + * updates the PLL and clock registers with reset values + */ +void XSlcr_PllWriteResetValues(void); +/* + * Disables the level shifters + */ +void XSlcr_DisableLevelShifters(void); +/* + * provides softreset to the GPIO interface + */ +void XSlcr_GpioPsReset(void); +/* + * provides softreset to the DMA interface + */ +void XSlcr_DmaPsReset(void); +/* + * provides softreset to the SMC interface + */ +void XSlcr_SmcPsReset(void); +/* + * provides softreset to the CAN interface + */ +void XSlcr_CanPsReset(void); +/* + * provides softreset to the Uart interface + */ +void XSlcr_UartPsReset(void); +/* + * provides softreset to the I2C interface + */ +void XSlcr_I2cPsReset(void); +/* + * provides softreset to the SPI interface + */ +void XSlcr_SpiPsReset(void); +/* + * provides softreset to the QSPI interface + */ +void XSlcr_QspiPsReset(void); +/* + * provides softreset to the USB interface + */ +void XSlcr_UsbPsReset(void); +/* + * provides softreset to the GEM interface + */ +void XSlcr_EmacPsReset(void); +/* + * provides softreset to the OCM interface + */ +void XSlcr_OcmReset(void); + + +#ifdef __cplusplus +} +#endif + +#endif /* XIL_MISC_RESET_H */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/include/xil_mmu.h b/datalink814_ge/bsp/ps7_cortexa9_0/include/xil_mmu.h new file mode 100644 index 0000000..3b63c0b --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/include/xil_mmu.h @@ -0,0 +1,106 @@ +/****************************************************************************** +* +* Copyright (C) 2012 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file xil_mmu.h +* +* @addtogroup a9_mmu_apis Cortex A9 Processor MMU Functions +* +* MMU functions equip users to enable MMU, disable MMU and modify default +* memory attributes of MMU table as per the need. +* +* @{ +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- ---------------------------------------------------
+* 1.00a sdm  01/12/12 Initial version
+* 4.2	pkp	 07/21/14 Included xil_types.h file which contains definition for
+*					  u32 which resolves issue of CR#805869
+* 5.4	pkp	 23/11/15 Added attribute definitions for Xil_SetTlbAttributes API
+* 6.8   aru  09/06/18 Removed compilation warnings for ARMCC toolchain.
+* 
+* +* +******************************************************************************/ + +#ifndef XIL_MMU_H +#define XIL_MMU_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/***************************** Include Files *********************************/ + +#include "xil_types.h" + +/***************** Macros (Inline Functions) Definitions *********************/ + +/**************************** Type Definitions *******************************/ + +/************************** Constant Definitions *****************************/ + +/* Memory type */ +#define NORM_NONCACHE 0x11DE2 /* Normal Non-cacheable */ +#define STRONG_ORDERED 0xC02 /* Strongly ordered */ +#define DEVICE_MEMORY 0xC06 /* Device memory */ +#define RESERVED 0x0 /* reserved memory */ + +/* Normal write-through cacheable shareable */ +#define NORM_WT_CACHE 0x16DEA + +/* Normal write back cacheable shareable */ +#define NORM_WB_CACHE 0x15DE6 + +/* shareability attribute */ +#define SHAREABLE (0x1 << 16) +#define NON_SHAREABLE (~(0x1 << 16)) + +/* Execution type */ +#define EXECUTE_NEVER ((0x1 << 4) | (0x1 << 0)) + +/************************** Variable Definitions *****************************/ + +/************************** Function Prototypes ******************************/ + +void Xil_SetTlbAttributes(INTPTR Addr, u32 attrib); +void Xil_EnableMMU(void); +void Xil_DisableMMU(void); +void* Xil_MemMap(UINTPTR PhysAddr, size_t size, u32 flags); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* XIL_MMU_H */ +/** +* @} End of "addtogroup a9_mmu_apis". +*/ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/include/xil_printf.h b/datalink814_ge/bsp/ps7_cortexa9_0/include/xil_printf.h new file mode 100644 index 0000000..a0177fc --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/include/xil_printf.h @@ -0,0 +1,48 @@ + #ifndef XIL_PRINTF_H + #define XIL_PRINTF_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include "xil_types.h" +#include "xparameters.h" +#include "bspconfig.h" +#if defined (__aarch64__) && HYP_GUEST && EL1_NONSECURE && XEN_USE_PV_CONSOLE +#include "xen_console.h" +#endif + +/*----------------------------------------------------*/ +/* Use the following parameter passing structure to */ +/* make xil_printf re-entrant. */ +/*----------------------------------------------------*/ + +struct params_s; + + +/*---------------------------------------------------*/ +/* The purpose of this routine is to output data the */ +/* same as the standard printf function without the */ +/* overhead most run-time libraries involve. Usually */ +/* the printf brings in many kilobytes of code and */ +/* that is unacceptable in most embedded systems. */ +/*---------------------------------------------------*/ + +typedef char8* charptr; +typedef s32 (*func_ptr)(int c); + +/* */ + +void xil_printf( const char8 *ctrl1, ...); +void print( const char8 *ptr); +extern void outbyte (char8 c); +extern char8 inbyte(void); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/include/xil_sleeptimer.h b/datalink814_ge/bsp/ps7_cortexa9_0/include/xil_sleeptimer.h new file mode 100644 index 0000000..08f64ba --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/include/xil_sleeptimer.h @@ -0,0 +1,128 @@ +/****************************************************************************** +* +* Copyright (C) 2017 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_sleeptimer.h +* +* This header file contains ARM Cortex A53,A9,R5 specific sleep related APIs. +* For sleep related functions that can be used across all Xilinx supported +* processors, please use xil_sleeptimer.h. +* +* +*
+* MODIFICATION HISTORY :
+*
+* Ver   Who  Date	 Changes
+* ----- ---- -------- -------------------------------------------------------
+* 6.6	srm  10/18/17 First Release.
+* 7.0   mus  01/07/19 Add cpp extern macro
+*
+* 
+*****************************************************************************/ + +#ifndef XIL_SLEEPTIMER_H /* prevent circular inclusions */ +#define XIL_SLEEPTIMER_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/**************************** Include Files ********************************/ + +#include "xil_io.h" +#include "xparameters.h" +#include "bspconfig.h" + +/************************** Constant Definitions *****************************/ + +#if defined (ARMR5) || (__aarch64__) || (ARMA53_32) +#define XSLEEP_TIMER_REG_SHIFT 32U +#define XSleep_ReadCounterVal Xil_In32 +#define XCntrVal u32 +#else +#define XSLEEP_TIMER_REG_SHIFT 16U +#define XSleep_ReadCounterVal Xil_In16 +#define XCntrVal u16 +#endif + +#if defined(ARMR5) || (defined (__aarch64__) && EL3==1) || defined (ARMA53_32) +#if defined (versal) +#define CRL_TTC_RST 0xFF5E0344U +#define CRL_TTC_BASE_RST_MASK 0x1U +#else +#define RST_LPD_IOU2 0xFF5E0238U +#define RST_LPD_IOU2_TTC_BASE_RESET_MASK 0x00000800U +#endif +#endif + +#if defined (SLEEP_TIMER_BASEADDR) +/** @name Register Map +* +* Register offsets from the base address of the TTC device +* +* @{ +*/ + #define XSLEEP_TIMER_TTC_CLK_CNTRL_OFFSET 0x00000000U + /**< Clock Control Register */ + #define XSLEEP_TIMER_TTC_CNT_CNTRL_OFFSET 0x0000000CU + /**< Counter Control Register*/ + #define XSLEEP_TIMER_TTC_COUNT_VALUE_OFFSET 0x00000018U + /**< Current Counter Value */ +/* @} */ +/** @name Clock Control Register +* Clock Control Register definitions of TTC +* @{ +*/ + #define XSLEEP_TIMER_TTC_CLK_CNTRL_PS_EN_MASK 0x00000001U + /**< Prescale enable */ +/* @} */ +/** @name Counter Control Register +* Counter Control Register definitions of TTC +* @{ +*/ +#define XSLEEP_TIMER_TTC_CNT_CNTRL_DIS_MASK 0x00000001U + /**< Disable the counter */ +#define XSLEEP_TIMER_TTC_CNT_CNTRL_RST_MASK 0x00000010U + /**< Reset counter */ +/* @} */ + +/**************************** Type Definitions *******************************/ + +/************************** Function Prototypes ******************************/ + +void Xil_SleepTTCCommon(u32 delay, u64 frequency); +void XTime_StartTTCTimer(); + +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* XIL_SLEEPTIMER_H */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/include/xil_testcache.h b/datalink814_ge/bsp/ps7_cortexa9_0/include/xil_testcache.h new file mode 100644 index 0000000..8289ca9 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/include/xil_testcache.h @@ -0,0 +1,67 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_testcache.h +* +* @addtogroup common_test_utils +*

Cache test

+* The xil_testcache.h file contains utility functions to test cache. +* +* @{ +*
+* Ver    Who    Date    Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a hbm  07/29/09 First release
+* 
+* +******************************************************************************/ + +#ifndef XIL_TESTCACHE_H /* prevent circular inclusions */ +#define XIL_TESTCACHE_H /* by using protection macros */ + +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern s32 Xil_TestDCacheRange(void); +extern s32 Xil_TestDCacheAll(void); +extern s32 Xil_TestICacheRange(void); +extern s32 Xil_TestICacheAll(void); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** +* @} End of "addtogroup common_test_utils". +*/ \ No newline at end of file diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/include/xil_testio.h b/datalink814_ge/bsp/ps7_cortexa9_0/include/xil_testio.h new file mode 100644 index 0000000..6f0fc1c --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/include/xil_testio.h @@ -0,0 +1,90 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_testio.h +* +* @addtogroup common_test_utils Test Utilities +*

I/O test

+* The xil_testio.h file contains utility functions to test endian related memory +* IO functions. +* +* A subset of the memory tests can be selected or all of the tests can be run +* in order. If there is an error detected by a subtest, the test stops and the +* failure code is returned. Further tests are not run even if all of the tests +* are selected. +* +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver    Who    Date    Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00 hbm  08/05/09 First release
+* 
+* +******************************************************************************/ + +#ifndef XIL_TESTIO_H /* prevent circular inclusions */ +#define XIL_TESTIO_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ +#include "xil_types.h" + +/************************** Constant Definitions *****************************/ + + +#define XIL_TESTIO_DEFAULT 0 +#define XIL_TESTIO_LE 1 +#define XIL_TESTIO_BE 2 + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + +extern s32 Xil_TestIO8(u8 *Addr, s32 Length, u8 Value); +extern s32 Xil_TestIO16(u16 *Addr, s32 Length, u16 Value, s32 Kind, s32 Swap); +extern s32 Xil_TestIO32(u32 *Addr, s32 Length, u32 Value, s32 Kind, s32 Swap); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** +* @} End of "addtogroup common_test_utils". +*/ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/include/xil_testmem.h b/datalink814_ge/bsp/ps7_cortexa9_0/include/xil_testmem.h new file mode 100644 index 0000000..ecce6b7 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/include/xil_testmem.h @@ -0,0 +1,154 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_testmem.h +* @addtogroup common_test_utils +* +*

Memory test

+* +* The xil_testmem.h file contains utility functions to test memory. +* A subset of the memory tests can be selected or all of the tests can be run +* in order. If there is an error detected by a subtest, the test stops and the +* failure code is returned. Further tests are not run even if all of the tests +* are selected. +* Following list describes the supported memory tests: +* +* - XIL_TESTMEM_ALLMEMTESTS: This test runs all of the subtests. +* +* - XIL_TESTMEM_INCREMENT: This test +* starts at 'XIL_TESTMEM_INIT_VALUE' and uses the incrementing value as the +* test value for memory. +* +* - XIL_TESTMEM_WALKONES: Also known as the Walking ones test. This test +* uses a walking '1' as the test value for memory. +* @code +* location 1 = 0x00000001 +* location 2 = 0x00000002 +* ... +* @endcode +* +* - XIL_TESTMEM_WALKZEROS: Also known as the Walking zero's test. +* This test uses the inverse value of the walking ones test +* as the test value for memory. +* @code +* location 1 = 0xFFFFFFFE +* location 2 = 0xFFFFFFFD +* ... +*@endcode +* +* - XIL_TESTMEM_INVERSEADDR: Also known as the inverse address test. +* This test uses the inverse of the address of the location under test +* as the test value for memory. +* +* - XIL_TESTMEM_FIXEDPATTERN: Also known as the fixed pattern test. +* This test uses the provided patters as the test value for memory. +* If zero is provided as the pattern the test uses '0xDEADBEEF". +* +* @warning +* The tests are DESTRUCTIVE. Run before any initialized memory spaces +* have been set up. +* The address provided to the memory tests is not checked for +* validity except for the NULL case. It is possible to provide a code-space +* pointer for this test to start with and ultimately destroy executable code +* causing random failures. +* +* @note +* Used for spaces where the address range of the region is smaller than +* the data width. If the memory range is greater than 2 ** width, +* the patterns used in XIL_TESTMEM_WALKONES and XIL_TESTMEM_WALKZEROS will +* repeat on a boundry of a power of two making it more difficult to detect +* addressing errors. The XIL_TESTMEM_INCREMENT and XIL_TESTMEM_INVERSEADDR +* tests suffer the same problem. Ideally, if large blocks of memory are to be +* tested, break them up into smaller regions of memory to allow the test +* patterns used not to repeat over the region tested. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver    Who    Date    Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a hbm  08/25/09 First release
+* 
+* +******************************************************************************/ + +#ifndef XIL_TESTMEM_H /* prevent circular inclusions */ +#define XIL_TESTMEM_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ +#include "xil_types.h" + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + +/* xutil_memtest defines */ + +#define XIL_TESTMEM_INIT_VALUE 1U + +/** @name Memory subtests + * @{ + */ +/** + * See the detailed description of the subtests in the file description. + */ +#define XIL_TESTMEM_ALLMEMTESTS 0x00U +#define XIL_TESTMEM_INCREMENT 0x01U +#define XIL_TESTMEM_WALKONES 0x02U +#define XIL_TESTMEM_WALKZEROS 0x03U +#define XIL_TESTMEM_INVERSEADDR 0x04U +#define XIL_TESTMEM_FIXEDPATTERN 0x05U +#define XIL_TESTMEM_MAXTEST XIL_TESTMEM_FIXEDPATTERN +/* @} */ + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + +/* xutil_testmem prototypes */ + +extern s32 Xil_TestMem32(u32 *Addr, u32 Words, u32 Pattern, u8 Subtest); +extern s32 Xil_TestMem16(u16 *Addr, u32 Words, u16 Pattern, u8 Subtest); +extern s32 Xil_TestMem8(u8 *Addr, u32 Words, u8 Pattern, u8 Subtest); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** +* @} End of "addtogroup common_test_utils". +*/ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/include/xil_types.h b/datalink814_ge/bsp/ps7_cortexa9_0/include/xil_types.h new file mode 100644 index 0000000..625ff8c --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/include/xil_types.h @@ -0,0 +1,214 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_types.h +* +* @addtogroup common_types Basic Data types for Xilinx® Software IP +* +* The xil_types.h file contains basic types for Xilinx software IP. These data types +* are applicable for all processors supported by Xilinx. +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date   Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a hbm  07/14/09 First release
+* 3.03a sdm  05/30/11 Added Xuint64 typedef and XUINT64_MSW/XUINT64_LSW macros
+* 5.00 	pkp  05/29/14 Made changes for 64 bit architecture
+*	srt  07/14/14 Use standard definitions from stdint.h and stddef.h
+*		      Define LONG and ULONG datatypes and mask values
+* 7.00  mus  01/07/19 Add cpp extern macro
+* 
+* +******************************************************************************/ + +#ifndef XIL_TYPES_H /* prevent circular inclusions */ +#define XIL_TYPES_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +/************************** Constant Definitions *****************************/ + +#ifndef TRUE +# define TRUE 1U +#endif + +#ifndef FALSE +# define FALSE 0U +#endif + +#ifndef NULL +#define NULL 0U +#endif + +#define XIL_COMPONENT_IS_READY 0x11111111U /**< In device drivers, This macro will be + assigend to "IsReady" member of driver + instance to indicate that driver + instance is initialized and ready to use. */ +#define XIL_COMPONENT_IS_STARTED 0x22222222U /**< In device drivers, This macro will be assigend to + "IsStarted" member of driver instance + to indicate that driver instance is + started and it can be enabled. */ + +/* @name New types + * New simple types. + * @{ + */ +#ifndef __KERNEL__ +#ifndef XBASIC_TYPES_H +/* + * guarded against xbasic_types.h. + */ +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; +/** @}*/ +#define __XUINT64__ +typedef struct +{ + u32 Upper; + u32 Lower; +} Xuint64; + + +/*****************************************************************************/ +/** +* @brief Return the most significant half of the 64 bit data type. +* +* @param x is the 64 bit word. +* +* @return The upper 32 bits of the 64 bit word. +* +******************************************************************************/ +#define XUINT64_MSW(x) ((x).Upper) + +/*****************************************************************************/ +/** +* @brief Return the least significant half of the 64 bit data type. +* +* @param x is the 64 bit word. +* +* @return The lower 32 bits of the 64 bit word. +* +******************************************************************************/ +#define XUINT64_LSW(x) ((x).Lower) + +#endif /* XBASIC_TYPES_H */ + +/* + * xbasic_types.h does not typedef s* or u64 + */ +/** @{ */ +typedef char char8; +typedef int8_t s8; +typedef int16_t s16; +typedef int32_t s32; +typedef int64_t s64; +typedef uint64_t u64; +typedef int sint32; + +typedef intptr_t INTPTR; +typedef uintptr_t UINTPTR; +typedef ptrdiff_t PTRDIFF; +/** @}*/ +#if !defined(LONG) || !defined(ULONG) +typedef long LONG; +typedef unsigned long ULONG; +#endif + +#define ULONG64_HI_MASK 0xFFFFFFFF00000000U +#define ULONG64_LO_MASK ~ULONG64_HI_MASK + +#else +#include +#endif + +/** @{ */ +/** + * This data type defines an interrupt handler for a device. + * The argument points to the instance of the component + */ +typedef void (*XInterruptHandler) (void *InstancePtr); + +/** + * This data type defines an exception handler for a processor. + * The argument points to the instance of the component + */ +typedef void (*XExceptionHandler) (void *InstancePtr); + +/** + * @brief Returns 32-63 bits of a number. + * @param n : Number being accessed. + * @return Bits 32-63 of number. + * + * @note A basic shift-right of a 64- or 32-bit quantity. + * Use this to suppress the "right shift count >= width of type" + * warning when that quantity is 32-bits. + */ +#define UPPER_32_BITS(n) ((u32)(((n) >> 16) >> 16)) + +/** + * @brief Returns 0-31 bits of a number + * @param n : Number being accessed. + * @return Bits 0-31 of number + */ +#define LOWER_32_BITS(n) ((u32)(n)) + + + + +/************************** Constant Definitions *****************************/ + +#ifndef TRUE +#define TRUE 1U +#endif + +#ifndef FALSE +#define FALSE 0U +#endif + +#ifndef NULL +#define NULL 0U +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** +* @} End of "addtogroup common_types". +*/ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/include/xil_util.h b/datalink814_ge/bsp/ps7_cortexa9_0/include/xil_util.h new file mode 100644 index 0000000..194c425 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/include/xil_util.h @@ -0,0 +1,57 @@ +/******************************************************************************/ +/** +* Copyright (C) 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* @file xil_util.h +* +* This file contains xil utility functions declaration +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 6.4   mmd      04/21/19 First release.
+*
+* 
+* +*****************************************************************************/ + +#ifndef XIL_UTIL_H_ +#define XIL_UTIL_H_ + +/* Converts input character to nibble */ +u32 Xil_ConvertCharToNibble(u8 InChar, u8 *Num); + +/* Conver input hex string to array of 32-bits integers */ +u32 Xil_ConvertStringToHex(const char *Str, u32 *buf, u8 Len); + +/* Waits for specified event */ +u32 Xil_WaitForEvent(u32 RegAddr, u32 EventMask, u32 Event, u32 Timeout); + +#endif /* XIL_UTIL_H_ */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/include/xl2cc.h b/datalink814_ge/bsp/ps7_cortexa9_0/include/xl2cc.h new file mode 100644 index 0000000..22373c1 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/include/xl2cc.h @@ -0,0 +1,168 @@ +/****************************************************************************** +* +* Copyright (C) 2011 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file xl2cc.h +* +* This file contains the address definitions for the PL310 Level-2 Cache +* Controller. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- ---------------------------------------------------
+* 1.00a sdm  02/01/10 Initial version
+* 3.10a srt 04/18/13 Implemented ARM Erratas. Please refer to file
+*		      'xil_errata.h' for errata description
+* 
+* +* @note +* +* None. +* +******************************************************************************/ + +#ifndef _XL2CC_H_ +#define _XL2CC_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/************************** Constant Definitions *****************************/ +/* L2CC Register Offsets */ +#define XPS_L2CC_ID_OFFSET 0x0000U +#define XPS_L2CC_TYPE_OFFSET 0x0004U +#define XPS_L2CC_CNTRL_OFFSET 0x0100U +#define XPS_L2CC_AUX_CNTRL_OFFSET 0x0104U +#define XPS_L2CC_TAG_RAM_CNTRL_OFFSET 0x0108U +#define XPS_L2CC_DATA_RAM_CNTRL_OFFSET 0x010CU + +#define XPS_L2CC_EVNT_CNTRL_OFFSET 0x0200U +#define XPS_L2CC_EVNT_CNT1_CTRL_OFFSET 0x0204U +#define XPS_L2CC_EVNT_CNT0_CTRL_OFFSET 0x0208U +#define XPS_L2CC_EVNT_CNT1_VAL_OFFSET 0x020CU +#define XPS_L2CC_EVNT_CNT0_VAL_OFFSET 0x0210U + +#define XPS_L2CC_IER_OFFSET 0x0214U /* Interrupt Mask */ +#define XPS_L2CC_IPR_OFFSET 0x0218U /* Masked interrupt status */ +#define XPS_L2CC_ISR_OFFSET 0x021CU /* Raw Interrupt Status */ +#define XPS_L2CC_IAR_OFFSET 0x0220U /* Interrupt Clear */ + +#define XPS_L2CC_CACHE_SYNC_OFFSET 0x0730U /* Cache Sync */ +#define XPS_L2CC_DUMMY_CACHE_SYNC_OFFSET 0x0740U /* Dummy Register for Cache Sync */ +#define XPS_L2CC_CACHE_INVLD_PA_OFFSET 0x0770U /* Cache Invalid by PA */ +#define XPS_L2CC_CACHE_INVLD_WAY_OFFSET 0x077CU /* Cache Invalid by Way */ +#define XPS_L2CC_CACHE_CLEAN_PA_OFFSET 0x07B0U /* Cache Clean by PA */ +#define XPS_L2CC_CACHE_CLEAN_INDX_OFFSET 0x07B8U /* Cache Clean by Index */ +#define XPS_L2CC_CACHE_CLEAN_WAY_OFFSET 0x07BCU /* Cache Clean by Way */ +#define XPS_L2CC_CACHE_INV_CLN_PA_OFFSET 0x07F0U /* Cache Invalidate and Clean by PA */ +#define XPS_L2CC_CACHE_INV_CLN_INDX_OFFSET 0x07F8U /* Cache Invalidate and Clean by Index */ +#define XPS_L2CC_CACHE_INV_CLN_WAY_OFFSET 0x07FCU /* Cache Invalidate and Clean by Way */ + +#define XPS_L2CC_CACHE_DLCKDWN_0_WAY_OFFSET 0x0900U /* Cache Data Lockdown 0 by Way */ +#define XPS_L2CC_CACHE_ILCKDWN_0_WAY_OFFSET 0x0904U /* Cache Instruction Lockdown 0 by Way */ +#define XPS_L2CC_CACHE_DLCKDWN_1_WAY_OFFSET 0x0908U /* Cache Data Lockdown 1 by Way */ +#define XPS_L2CC_CACHE_ILCKDWN_1_WAY_OFFSET 0x090CU /* Cache Instruction Lockdown 1 by Way */ +#define XPS_L2CC_CACHE_DLCKDWN_2_WAY_OFFSET 0x0910U /* Cache Data Lockdown 2 by Way */ +#define XPS_L2CC_CACHE_ILCKDWN_2_WAY_OFFSET 0x0914U /* Cache Instruction Lockdown 2 by Way */ +#define XPS_L2CC_CACHE_DLCKDWN_3_WAY_OFFSET 0x0918U /* Cache Data Lockdown 3 by Way */ +#define XPS_L2CC_CACHE_ILCKDWN_3_WAY_OFFSET 0x091CU /* Cache Instruction Lockdown 3 by Way */ +#define XPS_L2CC_CACHE_DLCKDWN_4_WAY_OFFSET 0x0920U /* Cache Data Lockdown 4 by Way */ +#define XPS_L2CC_CACHE_ILCKDWN_4_WAY_OFFSET 0x0924U /* Cache Instruction Lockdown 4 by Way */ +#define XPS_L2CC_CACHE_DLCKDWN_5_WAY_OFFSET 0x0928U /* Cache Data Lockdown 5 by Way */ +#define XPS_L2CC_CACHE_ILCKDWN_5_WAY_OFFSET 0x092CU /* Cache Instruction Lockdown 5 by Way */ +#define XPS_L2CC_CACHE_DLCKDWN_6_WAY_OFFSET 0x0930U /* Cache Data Lockdown 6 by Way */ +#define XPS_L2CC_CACHE_ILCKDWN_6_WAY_OFFSET 0x0934U /* Cache Instruction Lockdown 6 by Way */ +#define XPS_L2CC_CACHE_DLCKDWN_7_WAY_OFFSET 0x0938U /* Cache Data Lockdown 7 by Way */ +#define XPS_L2CC_CACHE_ILCKDWN_7_WAY_OFFSET 0x093CU /* Cache Instruction Lockdown 7 by Way */ + +#define XPS_L2CC_CACHE_LCKDWN_LINE_ENABLE_OFFSET 0x0950U /* Cache Lockdown Line Enable */ +#define XPS_L2CC_CACHE_UUNLOCK_ALL_WAY_OFFSET 0x0954U /* Cache Unlock All Lines by Way */ + +#define XPS_L2CC_ADDR_FILTER_START_OFFSET 0x0C00U /* Start of address filtering */ +#define XPS_L2CC_ADDR_FILTER_END_OFFSET 0x0C04U /* Start of address filtering */ + +#define XPS_L2CC_DEBUG_CTRL_OFFSET 0x0F40U /* Debug Control Register */ + +/* XPS_L2CC_CNTRL_OFFSET bit masks */ +#define XPS_L2CC_ENABLE_MASK 0x00000001U /* enables the L2CC */ + +/* XPS_L2CC_AUX_CNTRL_OFFSET bit masks */ +#define XPS_L2CC_AUX_EBRESPE_MASK 0x40000000U /* Early BRESP Enable */ +#define XPS_L2CC_AUX_IPFE_MASK 0x20000000U /* Instruction Prefetch Enable */ +#define XPS_L2CC_AUX_DPFE_MASK 0x10000000U /* Data Prefetch Enable */ +#define XPS_L2CC_AUX_NSIC_MASK 0x08000000U /* Non-secure interrupt access control */ +#define XPS_L2CC_AUX_NSLE_MASK 0x04000000U /* Non-secure lockdown enable */ +#define XPS_L2CC_AUX_CRP_MASK 0x02000000U /* Cache replacement policy */ +#define XPS_L2CC_AUX_FWE_MASK 0x01800000U /* Force write allocate */ +#define XPS_L2CC_AUX_SAOE_MASK 0x00400000U /* Shared attribute override enable */ +#define XPS_L2CC_AUX_PE_MASK 0x00200000U /* Parity enable */ +#define XPS_L2CC_AUX_EMBE_MASK 0x00100000U /* Event monitor bus enable */ +#define XPS_L2CC_AUX_WAY_SIZE_MASK 0x000E0000U /* Way-size */ +#define XPS_L2CC_AUX_ASSOC_MASK 0x00010000U /* Associativity */ +#define XPS_L2CC_AUX_SAIE_MASK 0x00002000U /* Shared attribute invalidate enable */ +#define XPS_L2CC_AUX_EXCL_CACHE_MASK 0x00001000U /* Exclusive cache configuration */ +#define XPS_L2CC_AUX_SBDLE_MASK 0x00000800U /* Store buffer device limitation Enable */ +#define XPS_L2CC_AUX_HPSODRE_MASK 0x00000400U /* High Priority for SO and Dev Reads Enable */ +#define XPS_L2CC_AUX_FLZE_MASK 0x00000001U /* Full line of zero enable */ + +#define XPS_L2CC_AUX_REG_DEFAULT_MASK 0x72360000U /* Enable all prefetching, */ + /* Cache replacement policy, Parity enable, */ + /* Event monitor bus enable and Way Size (64 KB) */ +#define XPS_L2CC_AUX_REG_ZERO_MASK 0xFFF1FFFFU /* */ + +#define XPS_L2CC_TAG_RAM_DEFAULT_MASK 0x00000111U /* latency for TAG RAM */ +#define XPS_L2CC_DATA_RAM_DEFAULT_MASK 0x00000121U /* latency for DATA RAM */ + +/* Interrupt bit masks */ +#define XPS_L2CC_IXR_DECERR_MASK 0x00000100U /* DECERR from L3 */ +#define XPS_L2CC_IXR_SLVERR_MASK 0x00000080U /* SLVERR from L3 */ +#define XPS_L2CC_IXR_ERRRD_MASK 0x00000040U /* Error on L2 data RAM (Read) */ +#define XPS_L2CC_IXR_ERRRT_MASK 0x00000020U /* Error on L2 tag RAM (Read) */ +#define XPS_L2CC_IXR_ERRWD_MASK 0x00000010U /* Error on L2 data RAM (Write) */ +#define XPS_L2CC_IXR_ERRWT_MASK 0x00000008U /* Error on L2 tag RAM (Write) */ +#define XPS_L2CC_IXR_PARRD_MASK 0x00000004U /* Parity Error on L2 data RAM (Read) */ +#define XPS_L2CC_IXR_PARRT_MASK 0x00000002U /* Parity Error on L2 tag RAM (Read) */ +#define XPS_L2CC_IXR_ECNTR_MASK 0x00000001U /* Event Counter1/0 Overflow Increment */ + +/* Address filtering mask and enable bit */ +#define XPS_L2CC_ADDR_FILTER_VALID_MASK 0xFFF00000U /* Address filtering valid bits*/ +#define XPS_L2CC_ADDR_FILTER_ENABLE_MASK 0x00000001U /* Address filtering enable bit*/ + +/* Debug control bits */ +#define XPS_L2CC_DEBUG_SPIDEN_MASK 0x00000004U /* Debug SPIDEN bit */ +#define XPS_L2CC_DEBUG_DWB_MASK 0x00000002U /* Debug DWB bit, forces write through */ +#define XPS_L2CC_DEBUG_DCL_MASK 0x00000002U /* Debug DCL bit, disables cache line fill */ + +#ifdef __cplusplus +} +#endif + +#endif /* protection macro */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/include/xl2cc_counter.h b/datalink814_ge/bsp/ps7_cortexa9_0/include/xl2cc_counter.h new file mode 100644 index 0000000..b8d768f --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/include/xl2cc_counter.h @@ -0,0 +1,110 @@ +/****************************************************************************** +* +* Copyright (C) 2011 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xl2cc_counter.h +* +* @addtogroup l2_event_counter_apis PL310 L2 Event Counters Functions +* +* xl2cc_counter.h contains APIs for configuring and controlling the event +* counters in PL310 L2 cache controller. +* PL310 has two event counters which can be used to count variety of events +* like DRHIT, DRREQ, DWHIT, DWREQ, etc. xl2cc_counter.h contains definitions +* for different configurations which can be used for the event counters to +* count a set of events. +* +* +* @{ +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a sdm  07/11/11 First release
+* 3.07a asa  08/30/12 Updated for CR 675636 to provide the L2 Base Address
+*		      inside the APIs
+* 6.8   aru  09/06/18 Removed compilation warnings for ARMCC toolchain.
+* 
+* +******************************************************************************/ + +#ifndef L2CCCOUNTER_H /* prevent circular inclusions */ +#define L2CCCOUNTER_H /* by using protection macros */ + +/***************************** Include Files ********************************/ + +#include "xpseudo_asm.h" +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/************************** Constant Definitions ****************************/ + +/* + * The following constants define the event codes for the event counters. + */ +#define XL2CC_CO 0x1 +#define XL2CC_DRHIT 0x2 +#define XL2CC_DRREQ 0x3 +#define XL2CC_DWHIT 0x4 +#define XL2CC_DWREQ 0x5 +#define XL2CC_DWTREQ 0x6 +#define XL2CC_IRHIT 0x7 +#define XL2CC_IRREQ 0x8 +#define XL2CC_WA 0x9 +#define XL2CC_IPFALLOC 0xa +#define XL2CC_EPFHIT 0xb +#define XL2CC_EPFALLOC 0xc +#define XL2CC_SRRCVD 0xd +#define XL2CC_SRCONF 0xe +#define XL2CC_EPFRCVD 0xf + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Variable Definitions ****************************/ + +/************************** Function Prototypes *****************************/ + +void XL2cc_EventCtrInit(s32 Event0, s32 Event1); +void XL2cc_EventCtrStart(void); +void XL2cc_EventCtrStop(u32 *EveCtr0, u32 *EveCtr1); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* L2CCCOUNTER_H */ +/** +* @} End of "addtogroup l2_event_counter_apis". +*/ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/include/xparameters.h b/datalink814_ge/bsp/ps7_cortexa9_0/include/xparameters.h new file mode 100644 index 0000000..a9a9a96 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/include/xparameters.h @@ -0,0 +1,575 @@ +#ifndef XPARAMETERS_H /* prevent circular inclusions */ +#define XPARAMETERS_H /* by using protection macros */ + +/* Definition for CPU ID */ +#define XPAR_CPU_ID 0U + +/* Definitions for peripheral PS7_CORTEXA9_0 */ +#define XPAR_PS7_CORTEXA9_0_CPU_CLK_FREQ_HZ 666666687 + + +/******************************************************************/ + +/* Canonical definitions for peripheral PS7_CORTEXA9_0 */ +#define XPAR_CPU_CORTEXA9_0_CPU_CLK_FREQ_HZ 666666687 + + +/******************************************************************/ + + +/* Definitions for interface TMC */ +#define XPAR_TMC_BASEADDR 0x43C40000 +#define XPAR_TMC_HIGHADDR 0x43C4FFFF + + +/* Definitions for interface PHYC */ +#define XPAR_PHYC_BASEADDR 0x43C60000 +#define XPAR_PHYC_HIGHADDR 0x43C60FFF + +#include "xparameters_ps.h" + +#define STDIN_BASEADDRESS 0xE0001000 +#define STDOUT_BASEADDRESS 0xE0001000 + +/******************************************************************/ + +/* Platform specific definitions */ +#define PLATFORM_ZYNQ + +/* Definitions for sleep timer configuration */ +#define XSLEEP_TIMER_IS_DEFAULT_TIMER + + +/******************************************************************/ +/* Definitions for driver BRAM */ +#define XPAR_XBRAM_NUM_INSTANCES 4U + +/* Definitions for peripheral MPC_BRAM_INTERFACE_MPC_BRAM_CTRL */ +#define XPAR_MPC_BRAM_INTERFACE_MPC_BRAM_CTRL_DEVICE_ID 0U +#define XPAR_MPC_BRAM_INTERFACE_MPC_BRAM_CTRL_DATA_WIDTH 32U +#define XPAR_MPC_BRAM_INTERFACE_MPC_BRAM_CTRL_ECC 0U +#define XPAR_MPC_BRAM_INTERFACE_MPC_BRAM_CTRL_FAULT_INJECT 0U +#define XPAR_MPC_BRAM_INTERFACE_MPC_BRAM_CTRL_CE_FAILING_REGISTERS 0U +#define XPAR_MPC_BRAM_INTERFACE_MPC_BRAM_CTRL_UE_FAILING_REGISTERS 0U +#define XPAR_MPC_BRAM_INTERFACE_MPC_BRAM_CTRL_ECC_STATUS_REGISTERS 0U +#define XPAR_MPC_BRAM_INTERFACE_MPC_BRAM_CTRL_CE_COUNTER_WIDTH 0U +#define XPAR_MPC_BRAM_INTERFACE_MPC_BRAM_CTRL_ECC_ONOFF_REGISTER 0U +#define XPAR_MPC_BRAM_INTERFACE_MPC_BRAM_CTRL_ECC_ONOFF_RESET_VALUE 0U +#define XPAR_MPC_BRAM_INTERFACE_MPC_BRAM_CTRL_WRITE_ACCESS 0U +#define XPAR_MPC_BRAM_INTERFACE_MPC_BRAM_CTRL_S_AXI_BASEADDR 0x44000000U +#define XPAR_MPC_BRAM_INTERFACE_MPC_BRAM_CTRL_S_AXI_HIGHADDR 0x44007FFFU +#define XPAR_MPC_BRAM_INTERFACE_MPC_BRAM_CTRL_S_AXI_CTRL_BASEADDR 0xFFFFFFFFU +#define XPAR_MPC_BRAM_INTERFACE_MPC_BRAM_CTRL_S_AXI_CTRL_HIGHADDR 0xFFFFFFFFU + + +/* Definitions for peripheral PHY_DATA_INTERFACE_ANT_INFO_BRAM_CTRL */ +#define XPAR_PHY_DATA_INTERFACE_ANT_INFO_BRAM_CTRL_DEVICE_ID 1U +#define XPAR_PHY_DATA_INTERFACE_ANT_INFO_BRAM_CTRL_DATA_WIDTH 32U +#define XPAR_PHY_DATA_INTERFACE_ANT_INFO_BRAM_CTRL_ECC 0U +#define XPAR_PHY_DATA_INTERFACE_ANT_INFO_BRAM_CTRL_FAULT_INJECT 0U +#define XPAR_PHY_DATA_INTERFACE_ANT_INFO_BRAM_CTRL_CE_FAILING_REGISTERS 0U +#define XPAR_PHY_DATA_INTERFACE_ANT_INFO_BRAM_CTRL_UE_FAILING_REGISTERS 0U +#define XPAR_PHY_DATA_INTERFACE_ANT_INFO_BRAM_CTRL_ECC_STATUS_REGISTERS 0U +#define XPAR_PHY_DATA_INTERFACE_ANT_INFO_BRAM_CTRL_CE_COUNTER_WIDTH 0U +#define XPAR_PHY_DATA_INTERFACE_ANT_INFO_BRAM_CTRL_ECC_ONOFF_REGISTER 0U +#define XPAR_PHY_DATA_INTERFACE_ANT_INFO_BRAM_CTRL_ECC_ONOFF_RESET_VALUE 0U +#define XPAR_PHY_DATA_INTERFACE_ANT_INFO_BRAM_CTRL_WRITE_ACCESS 0U +#define XPAR_PHY_DATA_INTERFACE_ANT_INFO_BRAM_CTRL_S_AXI_BASEADDR 0x42000000U +#define XPAR_PHY_DATA_INTERFACE_ANT_INFO_BRAM_CTRL_S_AXI_HIGHADDR 0x42001FFFU +#define XPAR_PHY_DATA_INTERFACE_ANT_INFO_BRAM_CTRL_S_AXI_CTRL_BASEADDR 0xFFFFFFFFU +#define XPAR_PHY_DATA_INTERFACE_ANT_INFO_BRAM_CTRL_S_AXI_CTRL_HIGHADDR 0xFFFFFFFFU + + +/* Definitions for peripheral PHY_DATA_INTERFACE_RX_FRAME_BRAM_CTRL */ +#define XPAR_PHY_DATA_INTERFACE_RX_FRAME_BRAM_CTRL_DEVICE_ID 2U +#define XPAR_PHY_DATA_INTERFACE_RX_FRAME_BRAM_CTRL_DATA_WIDTH 32U +#define XPAR_PHY_DATA_INTERFACE_RX_FRAME_BRAM_CTRL_ECC 0U +#define XPAR_PHY_DATA_INTERFACE_RX_FRAME_BRAM_CTRL_FAULT_INJECT 0U +#define XPAR_PHY_DATA_INTERFACE_RX_FRAME_BRAM_CTRL_CE_FAILING_REGISTERS 0U +#define XPAR_PHY_DATA_INTERFACE_RX_FRAME_BRAM_CTRL_UE_FAILING_REGISTERS 0U +#define XPAR_PHY_DATA_INTERFACE_RX_FRAME_BRAM_CTRL_ECC_STATUS_REGISTERS 0U +#define XPAR_PHY_DATA_INTERFACE_RX_FRAME_BRAM_CTRL_CE_COUNTER_WIDTH 0U +#define XPAR_PHY_DATA_INTERFACE_RX_FRAME_BRAM_CTRL_ECC_ONOFF_REGISTER 0U +#define XPAR_PHY_DATA_INTERFACE_RX_FRAME_BRAM_CTRL_ECC_ONOFF_RESET_VALUE 0U +#define XPAR_PHY_DATA_INTERFACE_RX_FRAME_BRAM_CTRL_WRITE_ACCESS 0U +#define XPAR_PHY_DATA_INTERFACE_RX_FRAME_BRAM_CTRL_S_AXI_BASEADDR 0x46000000U +#define XPAR_PHY_DATA_INTERFACE_RX_FRAME_BRAM_CTRL_S_AXI_HIGHADDR 0x46001FFFU +#define XPAR_PHY_DATA_INTERFACE_RX_FRAME_BRAM_CTRL_S_AXI_CTRL_BASEADDR 0xFFFFFFFFU +#define XPAR_PHY_DATA_INTERFACE_RX_FRAME_BRAM_CTRL_S_AXI_CTRL_HIGHADDR 0xFFFFFFFFU + + +/* Definitions for peripheral PHY_DATA_INTERFACE_TX_FRAME_BRAM_CTRL */ +#define XPAR_PHY_DATA_INTERFACE_TX_FRAME_BRAM_CTRL_DEVICE_ID 3U +#define XPAR_PHY_DATA_INTERFACE_TX_FRAME_BRAM_CTRL_DATA_WIDTH 32U +#define XPAR_PHY_DATA_INTERFACE_TX_FRAME_BRAM_CTRL_ECC 0U +#define XPAR_PHY_DATA_INTERFACE_TX_FRAME_BRAM_CTRL_FAULT_INJECT 0U +#define XPAR_PHY_DATA_INTERFACE_TX_FRAME_BRAM_CTRL_CE_FAILING_REGISTERS 0U +#define XPAR_PHY_DATA_INTERFACE_TX_FRAME_BRAM_CTRL_UE_FAILING_REGISTERS 0U +#define XPAR_PHY_DATA_INTERFACE_TX_FRAME_BRAM_CTRL_ECC_STATUS_REGISTERS 0U +#define XPAR_PHY_DATA_INTERFACE_TX_FRAME_BRAM_CTRL_CE_COUNTER_WIDTH 0U +#define XPAR_PHY_DATA_INTERFACE_TX_FRAME_BRAM_CTRL_ECC_ONOFF_REGISTER 0U +#define XPAR_PHY_DATA_INTERFACE_TX_FRAME_BRAM_CTRL_ECC_ONOFF_RESET_VALUE 0U +#define XPAR_PHY_DATA_INTERFACE_TX_FRAME_BRAM_CTRL_WRITE_ACCESS 0U +#define XPAR_PHY_DATA_INTERFACE_TX_FRAME_BRAM_CTRL_S_AXI_BASEADDR 0x40000000U +#define XPAR_PHY_DATA_INTERFACE_TX_FRAME_BRAM_CTRL_S_AXI_HIGHADDR 0x40001FFFU +#define XPAR_PHY_DATA_INTERFACE_TX_FRAME_BRAM_CTRL_S_AXI_CTRL_BASEADDR 0xFFFFFFFFU +#define XPAR_PHY_DATA_INTERFACE_TX_FRAME_BRAM_CTRL_S_AXI_CTRL_HIGHADDR 0xFFFFFFFFU + + +/******************************************************************/ + +/* Canonical definitions for peripheral MPC_BRAM_INTERFACE_MPC_BRAM_CTRL */ +#define XPAR_BRAM_0_DEVICE_ID XPAR_MPC_BRAM_INTERFACE_MPC_BRAM_CTRL_DEVICE_ID +#define XPAR_BRAM_0_DATA_WIDTH 32U +#define XPAR_BRAM_0_ECC 0U +#define XPAR_BRAM_0_FAULT_INJECT 0U +#define XPAR_BRAM_0_CE_FAILING_REGISTERS 0U +#define XPAR_BRAM_0_UE_FAILING_REGISTERS 0U +#define XPAR_BRAM_0_ECC_STATUS_REGISTERS 0U +#define XPAR_BRAM_0_CE_COUNTER_WIDTH 0U +#define XPAR_BRAM_0_ECC_ONOFF_REGISTER 0U +#define XPAR_BRAM_0_ECC_ONOFF_RESET_VALUE 0U +#define XPAR_BRAM_0_WRITE_ACCESS 0U +#define XPAR_BRAM_0_BASEADDR 0x44000000U +#define XPAR_BRAM_0_HIGHADDR 0x44007FFFU +#define XPAR_BRAM_0_CTRL_BASEADDR 0xFFFFFFFFU +#define XPAR_BRAM_0_CTRL_HIGHADDR 0xFFFFFFFEU + +/* Canonical definitions for peripheral PHY_DATA_INTERFACE_ANT_INFO_BRAM_CTRL */ +#define XPAR_BRAM_1_DEVICE_ID XPAR_PHY_DATA_INTERFACE_ANT_INFO_BRAM_CTRL_DEVICE_ID +#define XPAR_BRAM_1_DATA_WIDTH 32U +#define XPAR_BRAM_1_ECC 0U +#define XPAR_BRAM_1_FAULT_INJECT 0U +#define XPAR_BRAM_1_CE_FAILING_REGISTERS 0U +#define XPAR_BRAM_1_UE_FAILING_REGISTERS 0U +#define XPAR_BRAM_1_ECC_STATUS_REGISTERS 0U +#define XPAR_BRAM_1_CE_COUNTER_WIDTH 0U +#define XPAR_BRAM_1_ECC_ONOFF_REGISTER 0U +#define XPAR_BRAM_1_ECC_ONOFF_RESET_VALUE 0U +#define XPAR_BRAM_1_WRITE_ACCESS 0U +#define XPAR_BRAM_1_BASEADDR 0x42000000U +#define XPAR_BRAM_1_HIGHADDR 0x42001FFFU +#define XPAR_BRAM_1_CTRL_BASEADDR 0xFFFFFFFFU +#define XPAR_BRAM_1_CTRL_HIGHADDR 0xFFFFFFFEU + +/* Canonical definitions for peripheral PHY_DATA_INTERFACE_RX_FRAME_BRAM_CTRL */ +#define XPAR_BRAM_2_DEVICE_ID XPAR_PHY_DATA_INTERFACE_RX_FRAME_BRAM_CTRL_DEVICE_ID +#define XPAR_BRAM_2_DATA_WIDTH 32U +#define XPAR_BRAM_2_ECC 0U +#define XPAR_BRAM_2_FAULT_INJECT 0U +#define XPAR_BRAM_2_CE_FAILING_REGISTERS 0U +#define XPAR_BRAM_2_UE_FAILING_REGISTERS 0U +#define XPAR_BRAM_2_ECC_STATUS_REGISTERS 0U +#define XPAR_BRAM_2_CE_COUNTER_WIDTH 0U +#define XPAR_BRAM_2_ECC_ONOFF_REGISTER 0U +#define XPAR_BRAM_2_ECC_ONOFF_RESET_VALUE 0U +#define XPAR_BRAM_2_WRITE_ACCESS 0U +#define XPAR_BRAM_2_BASEADDR 0x46000000U +#define XPAR_BRAM_2_HIGHADDR 0x46001FFFU +#define XPAR_BRAM_2_CTRL_BASEADDR 0xFFFFFFFFU +#define XPAR_BRAM_2_CTRL_HIGHADDR 0xFFFFFFFEU + +/* Canonical definitions for peripheral PHY_DATA_INTERFACE_TX_FRAME_BRAM_CTRL */ +#define XPAR_BRAM_3_DEVICE_ID XPAR_PHY_DATA_INTERFACE_TX_FRAME_BRAM_CTRL_DEVICE_ID +#define XPAR_BRAM_3_DATA_WIDTH 32U +#define XPAR_BRAM_3_ECC 0U +#define XPAR_BRAM_3_FAULT_INJECT 0U +#define XPAR_BRAM_3_CE_FAILING_REGISTERS 0U +#define XPAR_BRAM_3_UE_FAILING_REGISTERS 0U +#define XPAR_BRAM_3_ECC_STATUS_REGISTERS 0U +#define XPAR_BRAM_3_CE_COUNTER_WIDTH 0U +#define XPAR_BRAM_3_ECC_ONOFF_REGISTER 0U +#define XPAR_BRAM_3_ECC_ONOFF_RESET_VALUE 0U +#define XPAR_BRAM_3_WRITE_ACCESS 0U +#define XPAR_BRAM_3_BASEADDR 0x40000000U +#define XPAR_BRAM_3_HIGHADDR 0x40001FFFU +#define XPAR_BRAM_3_CTRL_BASEADDR 0xFFFFFFFFU +#define XPAR_BRAM_3_CTRL_HIGHADDR 0xFFFFFFFEU + + +/******************************************************************/ + + +/* Definitions for peripheral PS7_DDR_0 */ +#define XPAR_PS7_DDR_0_S_AXI_BASEADDR 0x00100000 +#define XPAR_PS7_DDR_0_S_AXI_HIGHADDR 0x1FFFFFFF + + +/******************************************************************/ + +/* Definitions for driver DEVCFG */ +#define XPAR_XDCFG_NUM_INSTANCES 1U + +/* Definitions for peripheral PS7_DEV_CFG_0 */ +#define XPAR_PS7_DEV_CFG_0_DEVICE_ID 0U +#define XPAR_PS7_DEV_CFG_0_BASEADDR 0xF8007000U +#define XPAR_PS7_DEV_CFG_0_HIGHADDR 0xF80070FFU + + +/******************************************************************/ + +/* Canonical definitions for peripheral PS7_DEV_CFG_0 */ +#define XPAR_XDCFG_0_DEVICE_ID XPAR_PS7_DEV_CFG_0_DEVICE_ID +#define XPAR_XDCFG_0_BASEADDR 0xF8007000U +#define XPAR_XDCFG_0_HIGHADDR 0xF80070FFU + + +/******************************************************************/ + +/* Definitions for driver DMAPS */ +#define XPAR_XDMAPS_NUM_INSTANCES 2 + +/* Definitions for peripheral PS7_DMA_NS */ +#define XPAR_PS7_DMA_NS_DEVICE_ID 0 +#define XPAR_PS7_DMA_NS_BASEADDR 0xF8004000 +#define XPAR_PS7_DMA_NS_HIGHADDR 0xF8004FFF + + +/* Definitions for peripheral PS7_DMA_S */ +#define XPAR_PS7_DMA_S_DEVICE_ID 1 +#define XPAR_PS7_DMA_S_BASEADDR 0xF8003000 +#define XPAR_PS7_DMA_S_HIGHADDR 0xF8003FFF + + +/******************************************************************/ + +/* Canonical definitions for peripheral PS7_DMA_NS */ +#define XPAR_XDMAPS_0_DEVICE_ID XPAR_PS7_DMA_NS_DEVICE_ID +#define XPAR_XDMAPS_0_BASEADDR 0xF8004000 +#define XPAR_XDMAPS_0_HIGHADDR 0xF8004FFF + +/* Canonical definitions for peripheral PS7_DMA_S */ +#define XPAR_XDMAPS_1_DEVICE_ID XPAR_PS7_DMA_S_DEVICE_ID +#define XPAR_XDMAPS_1_BASEADDR 0xF8003000 +#define XPAR_XDMAPS_1_HIGHADDR 0xF8003FFF + + +/******************************************************************/ + +/* Definitions for driver FRAME_UART */ +#define XPAR_FRAME_UART_NUM_INSTANCES 1 + +/* Definitions for peripheral FRAME_UART_0 */ +#define XPAR_FRAME_UART_0_DEVICE_ID 0 +#define XPAR_FRAME_UART_0_S00_AXI_BASEADDR 0x43C30000 +#define XPAR_FRAME_UART_0_S00_AXI_HIGHADDR 0x43C3FFFF + + +/******************************************************************/ + + +/* Definitions for peripheral JESD_JESD204_PHY */ +#define XPAR_JESD_JESD204_PHY_BASEADDR 0x43C00000 +#define XPAR_JESD_JESD204_PHY_HIGHADDR 0x43C0FFFF + + +/* Definitions for peripheral JESD_JESD204_RX */ +#define XPAR_JESD_JESD204_RX_BASEADDR 0x43C10000 +#define XPAR_JESD_JESD204_RX_HIGHADDR 0x43C1FFFF + + +/* Definitions for peripheral JESD_JESD204_TX */ +#define XPAR_JESD_JESD204_TX_BASEADDR 0x43C20000 +#define XPAR_JESD_JESD204_TX_HIGHADDR 0x43C2FFFF + + +/* Definitions for peripheral PS7_AFI_0 */ +#define XPAR_PS7_AFI_0_S_AXI_BASEADDR 0xF8008000 +#define XPAR_PS7_AFI_0_S_AXI_HIGHADDR 0xF8008FFF + + +/* Definitions for peripheral PS7_AFI_1 */ +#define XPAR_PS7_AFI_1_S_AXI_BASEADDR 0xF8009000 +#define XPAR_PS7_AFI_1_S_AXI_HIGHADDR 0xF8009FFF + + +/* Definitions for peripheral PS7_AFI_2 */ +#define XPAR_PS7_AFI_2_S_AXI_BASEADDR 0xF800A000 +#define XPAR_PS7_AFI_2_S_AXI_HIGHADDR 0xF800AFFF + + +/* Definitions for peripheral PS7_AFI_3 */ +#define XPAR_PS7_AFI_3_S_AXI_BASEADDR 0xF800B000 +#define XPAR_PS7_AFI_3_S_AXI_HIGHADDR 0xF800BFFF + + +/* Definitions for peripheral PS7_DDRC_0 */ +#define XPAR_PS7_DDRC_0_S_AXI_BASEADDR 0xF8006000 +#define XPAR_PS7_DDRC_0_S_AXI_HIGHADDR 0xF8006FFF + + +/* Definitions for peripheral PS7_GLOBALTIMER_0 */ +#define XPAR_PS7_GLOBALTIMER_0_S_AXI_BASEADDR 0xF8F00200 +#define XPAR_PS7_GLOBALTIMER_0_S_AXI_HIGHADDR 0xF8F002FF + + +/* Definitions for peripheral PS7_GPV_0 */ +#define XPAR_PS7_GPV_0_S_AXI_BASEADDR 0xF8900000 +#define XPAR_PS7_GPV_0_S_AXI_HIGHADDR 0xF89FFFFF + + +/* Definitions for peripheral PS7_INTC_DIST_0 */ +#define XPAR_PS7_INTC_DIST_0_S_AXI_BASEADDR 0xF8F01000 +#define XPAR_PS7_INTC_DIST_0_S_AXI_HIGHADDR 0xF8F01FFF + + +/* Definitions for peripheral PS7_IOP_BUS_CONFIG_0 */ +#define XPAR_PS7_IOP_BUS_CONFIG_0_S_AXI_BASEADDR 0xE0200000 +#define XPAR_PS7_IOP_BUS_CONFIG_0_S_AXI_HIGHADDR 0xE0200FFF + + +/* Definitions for peripheral PS7_L2CACHEC_0 */ +#define XPAR_PS7_L2CACHEC_0_S_AXI_BASEADDR 0xF8F02000 +#define XPAR_PS7_L2CACHEC_0_S_AXI_HIGHADDR 0xF8F02FFF + + +/* Definitions for peripheral PS7_OCMC_0 */ +#define XPAR_PS7_OCMC_0_S_AXI_BASEADDR 0xF800C000 +#define XPAR_PS7_OCMC_0_S_AXI_HIGHADDR 0xF800CFFF + + +/* Definitions for peripheral PS7_PL310_0 */ +#define XPAR_PS7_PL310_0_S_AXI_BASEADDR 0xF8F02000 +#define XPAR_PS7_PL310_0_S_AXI_HIGHADDR 0xF8F02FFF + + +/* Definitions for peripheral PS7_PMU_0 */ +#define XPAR_PS7_PMU_0_S_AXI_BASEADDR 0xF8891000 +#define XPAR_PS7_PMU_0_S_AXI_HIGHADDR 0xF8891FFF +#define XPAR_PS7_PMU_0_PMU1_S_AXI_BASEADDR 0xF8893000 +#define XPAR_PS7_PMU_0_PMU1_S_AXI_HIGHADDR 0xF8893FFF + + +/* Definitions for peripheral PS7_QSPI_LINEAR_0 */ +#define XPAR_PS7_QSPI_LINEAR_0_S_AXI_BASEADDR 0xFC000000 +#define XPAR_PS7_QSPI_LINEAR_0_S_AXI_HIGHADDR 0xFCFFFFFF + + +/* Definitions for peripheral PS7_RAM_0 */ +#define XPAR_PS7_RAM_0_S_AXI_BASEADDR 0x00000000 +#define XPAR_PS7_RAM_0_S_AXI_HIGHADDR 0x0003FFFF + + +/* Definitions for peripheral PS7_RAM_1 */ +#define XPAR_PS7_RAM_1_S_AXI_BASEADDR 0xFFFC0000 +#define XPAR_PS7_RAM_1_S_AXI_HIGHADDR 0xFFFFFFFF + + +/* Definitions for peripheral PS7_SCUC_0 */ +#define XPAR_PS7_SCUC_0_S_AXI_BASEADDR 0xF8F00000 +#define XPAR_PS7_SCUC_0_S_AXI_HIGHADDR 0xF8F000FC + + +/* Definitions for peripheral PS7_SLCR_0 */ +#define XPAR_PS7_SLCR_0_S_AXI_BASEADDR 0xF8000000 +#define XPAR_PS7_SLCR_0_S_AXI_HIGHADDR 0xF8000FFF + + +/******************************************************************/ + +/* Definitions for driver GPIO */ +#define XPAR_XGPIO_NUM_INSTANCES 1 + +/* Definitions for peripheral CONFIG_GPIO */ +#define XPAR_CONFIG_GPIO_BASEADDR 0x41200000 +#define XPAR_CONFIG_GPIO_HIGHADDR 0x4120FFFF +#define XPAR_CONFIG_GPIO_DEVICE_ID 0 +#define XPAR_CONFIG_GPIO_INTERRUPT_PRESENT 0 +#define XPAR_CONFIG_GPIO_IS_DUAL 1 + + +/******************************************************************/ + +/* Canonical definitions for peripheral CONFIG_GPIO */ +#define XPAR_GPIO_0_BASEADDR 0x41200000 +#define XPAR_GPIO_0_HIGHADDR 0x4120FFFF +#define XPAR_GPIO_0_DEVICE_ID XPAR_CONFIG_GPIO_DEVICE_ID +#define XPAR_GPIO_0_INTERRUPT_PRESENT 0 +#define XPAR_GPIO_0_IS_DUAL 1 + + +/******************************************************************/ + +/* Definitions for driver GPIOPS */ +#define XPAR_XGPIOPS_NUM_INSTANCES 1 + +/* Definitions for peripheral PS7_GPIO_0 */ +#define XPAR_PS7_GPIO_0_DEVICE_ID 0 +#define XPAR_PS7_GPIO_0_BASEADDR 0xE000A000 +#define XPAR_PS7_GPIO_0_HIGHADDR 0xE000AFFF + + +/******************************************************************/ + +/* Canonical definitions for peripheral PS7_GPIO_0 */ +#define XPAR_XGPIOPS_0_DEVICE_ID XPAR_PS7_GPIO_0_DEVICE_ID +#define XPAR_XGPIOPS_0_BASEADDR 0xE000A000 +#define XPAR_XGPIOPS_0_HIGHADDR 0xE000AFFF + + +/******************************************************************/ + +/* Definitions for driver QSPIPS */ +#define XPAR_XQSPIPS_NUM_INSTANCES 1 + +/* Definitions for peripheral PS7_QSPI_0 */ +#define XPAR_PS7_QSPI_0_DEVICE_ID 0 +#define XPAR_PS7_QSPI_0_BASEADDR 0xE000D000 +#define XPAR_PS7_QSPI_0_HIGHADDR 0xE000DFFF +#define XPAR_PS7_QSPI_0_QSPI_CLK_FREQ_HZ 200000000 +#define XPAR_PS7_QSPI_0_QSPI_MODE 0 +#define XPAR_PS7_QSPI_0_QSPI_BUS_WIDTH 2 + + +/******************************************************************/ + +/* Canonical definitions for peripheral PS7_QSPI_0 */ +#define XPAR_XQSPIPS_0_DEVICE_ID XPAR_PS7_QSPI_0_DEVICE_ID +#define XPAR_XQSPIPS_0_BASEADDR 0xE000D000 +#define XPAR_XQSPIPS_0_HIGHADDR 0xE000DFFF +#define XPAR_XQSPIPS_0_QSPI_CLK_FREQ_HZ 200000000 +#define XPAR_XQSPIPS_0_QSPI_MODE 0 +#define XPAR_XQSPIPS_0_QSPI_BUS_WIDTH 2 + + +/******************************************************************/ + +/* Definitions for Fabric interrupts connected to ps7_scugic_0 */ +#define XPAR_FABRIC_PHY_IRQ_INTR 61U +#define XPAR_FABRIC_FRAME_UART_0_RX_INTR_INTR 62U +#define XPAR_FABRIC_FRAME_UART_0_TX_INTR_INTR 63U +#define XPAR_FABRIC_MPC_IRQ_INTR 64U +#define XPAR_FABRIC_PHY_5MS_INTR 65U +#define XPAR_FABRIC_PHY_5MS_DELAY_2MS_INTR 66U + +/******************************************************************/ + +/* Canonical definitions for Fabric interrupts connected to ps7_scugic_0 */ +#define XPAR_FABRIC_FRAME_UART_0_RX_INTR_VEC_ID XPAR_FABRIC_FRAME_UART_0_RX_INTR_INTR +#define XPAR_FABRIC_FRAME_UART_0_TX_INTR_VEC_ID XPAR_FABRIC_FRAME_UART_0_TX_INTR_INTR + +/******************************************************************/ + +/* Definitions for driver SCUGIC */ +#define XPAR_XSCUGIC_NUM_INSTANCES 1U + +/* Definitions for peripheral PS7_SCUGIC_0 */ +#define XPAR_PS7_SCUGIC_0_DEVICE_ID 0U +#define XPAR_PS7_SCUGIC_0_BASEADDR 0xF8F00100U +#define XPAR_PS7_SCUGIC_0_HIGHADDR 0xF8F001FFU +#define XPAR_PS7_SCUGIC_0_DIST_BASEADDR 0xF8F01000U + + +/******************************************************************/ + +/* Canonical definitions for peripheral PS7_SCUGIC_0 */ +#define XPAR_SCUGIC_0_DEVICE_ID 0U +#define XPAR_SCUGIC_0_CPU_BASEADDR 0xF8F00100U +#define XPAR_SCUGIC_0_CPU_HIGHADDR 0xF8F001FFU +#define XPAR_SCUGIC_0_DIST_BASEADDR 0xF8F01000U + + +/******************************************************************/ + +/* Definitions for driver SCUTIMER */ +#define XPAR_XSCUTIMER_NUM_INSTANCES 1 + +/* Definitions for peripheral PS7_SCUTIMER_0 */ +#define XPAR_PS7_SCUTIMER_0_DEVICE_ID 0 +#define XPAR_PS7_SCUTIMER_0_BASEADDR 0xF8F00600 +#define XPAR_PS7_SCUTIMER_0_HIGHADDR 0xF8F0061F + + +/******************************************************************/ + +/* Canonical definitions for peripheral PS7_SCUTIMER_0 */ +#define XPAR_XSCUTIMER_0_DEVICE_ID XPAR_PS7_SCUTIMER_0_DEVICE_ID +#define XPAR_XSCUTIMER_0_BASEADDR 0xF8F00600 +#define XPAR_XSCUTIMER_0_HIGHADDR 0xF8F0061F + + +/******************************************************************/ + +/* Definitions for driver SCUWDT */ +#define XPAR_XSCUWDT_NUM_INSTANCES 1 + +/* Definitions for peripheral PS7_SCUWDT_0 */ +#define XPAR_PS7_SCUWDT_0_DEVICE_ID 0 +#define XPAR_PS7_SCUWDT_0_BASEADDR 0xF8F00620 +#define XPAR_PS7_SCUWDT_0_HIGHADDR 0xF8F006FF + + +/******************************************************************/ + +/* Canonical definitions for peripheral PS7_SCUWDT_0 */ +#define XPAR_SCUWDT_0_DEVICE_ID XPAR_PS7_SCUWDT_0_DEVICE_ID +#define XPAR_SCUWDT_0_BASEADDR 0xF8F00620 +#define XPAR_SCUWDT_0_HIGHADDR 0xF8F006FF + + +/******************************************************************/ + +/* Definitions for driver SPIPS */ +#define XPAR_XSPIPS_NUM_INSTANCES 1 + +/* Definitions for peripheral PS7_SPI_0 */ +#define XPAR_PS7_SPI_0_DEVICE_ID 0 +#define XPAR_PS7_SPI_0_BASEADDR 0xE0006000 +#define XPAR_PS7_SPI_0_HIGHADDR 0xE0006FFF +#define XPAR_PS7_SPI_0_SPI_CLK_FREQ_HZ 166666672 + + +/******************************************************************/ + +/* Canonical definitions for peripheral PS7_SPI_0 */ +#define XPAR_XSPIPS_0_DEVICE_ID XPAR_PS7_SPI_0_DEVICE_ID +#define XPAR_XSPIPS_0_BASEADDR 0xE0006000 +#define XPAR_XSPIPS_0_HIGHADDR 0xE0006FFF +#define XPAR_XSPIPS_0_SPI_CLK_FREQ_HZ 166666672 + + +/******************************************************************/ + +/* Definitions for driver UARTPS */ +#define XPAR_XUARTPS_NUM_INSTANCES 1 + +/* Definitions for peripheral PS7_UART_1 */ +#define XPAR_PS7_UART_1_DEVICE_ID 0 +#define XPAR_PS7_UART_1_BASEADDR 0xE0001000 +#define XPAR_PS7_UART_1_HIGHADDR 0xE0001FFF +#define XPAR_PS7_UART_1_UART_CLK_FREQ_HZ 100000000 +#define XPAR_PS7_UART_1_HAS_MODEM 0 + + +/******************************************************************/ + +/* Canonical definitions for peripheral PS7_UART_1 */ +#define XPAR_XUARTPS_0_DEVICE_ID XPAR_PS7_UART_1_DEVICE_ID +#define XPAR_XUARTPS_0_BASEADDR 0xE0001000 +#define XPAR_XUARTPS_0_HIGHADDR 0xE0001FFF +#define XPAR_XUARTPS_0_UART_CLK_FREQ_HZ 100000000 +#define XPAR_XUARTPS_0_HAS_MODEM 0 + + +/******************************************************************/ + +/* Definitions for driver XADCPS */ +#define XPAR_XADCPS_NUM_INSTANCES 1 + +/* Definitions for peripheral PS7_XADC_0 */ +#define XPAR_PS7_XADC_0_DEVICE_ID 0 +#define XPAR_PS7_XADC_0_BASEADDR 0xF8007100 +#define XPAR_PS7_XADC_0_HIGHADDR 0xF8007120 + + +/******************************************************************/ + +/* Canonical definitions for peripheral PS7_XADC_0 */ +#define XPAR_XADCPS_0_DEVICE_ID XPAR_PS7_XADC_0_DEVICE_ID +#define XPAR_XADCPS_0_BASEADDR 0xF8007100 +#define XPAR_XADCPS_0_HIGHADDR 0xF8007120 + + +/******************************************************************/ + +#endif /* end of protection macro */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/include/xparameters_ps.h b/datalink814_ge/bsp/ps7_cortexa9_0/include/xparameters_ps.h new file mode 100644 index 0000000..2a6a0e0 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/include/xparameters_ps.h @@ -0,0 +1,334 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2017 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file xparameters_ps.h +* +* This file contains the address definitions for the hard peripherals +* attached to the ARM Cortex A9 core. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who     Date     Changes
+* ----- ------- -------- ---------------------------------------------------
+* 1.00a ecm/sdm 02/01/10 Initial version
+* 3.04a sdm     02/02/12 Removed some of the defines as they are being generated through
+*                        driver tcl
+* 5.0	pkp		01/16/15 Added interrupt ID definition of ttc for TEST APP
+* 6.6   srm     10/18/17 Added ARMA9 macro to identify CortexA9
+*
+* 
+* +* @note +* +* None. +* +******************************************************************************/ + +#ifndef _XPARAMETERS_PS_H_ +#define _XPARAMETERS_PS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/**************************** Include Files *******************************/ + + +/************************** Constant Definitions *****************************/ + +/* + * This block contains constant declarations for the peripherals + * within the hardblock + */ + +/* Canonical definitions for DDR MEMORY */ +#define XPAR_DDR_MEM_BASEADDR 0x00000000U +#define XPAR_DDR_MEM_HIGHADDR 0x3FFFFFFFU + +/* Canonical definitions for Interrupts */ +#define XPAR_XUARTPS_0_INTR XPS_UART0_INT_ID +#define XPAR_XUARTPS_1_INTR XPS_UART1_INT_ID +#define XPAR_XUSBPS_0_INTR XPS_USB0_INT_ID +#define XPAR_XUSBPS_1_INTR XPS_USB1_INT_ID +#define XPAR_XIICPS_0_INTR XPS_I2C0_INT_ID +#define XPAR_XIICPS_1_INTR XPS_I2C1_INT_ID +#define XPAR_XSPIPS_0_INTR XPS_SPI0_INT_ID +#define XPAR_XSPIPS_1_INTR XPS_SPI1_INT_ID +#define XPAR_XCANPS_0_INTR XPS_CAN0_INT_ID +#define XPAR_XCANPS_1_INTR XPS_CAN1_INT_ID +#define XPAR_XGPIOPS_0_INTR XPS_GPIO_INT_ID +#define XPAR_XEMACPS_0_INTR XPS_GEM0_INT_ID +#define XPAR_XEMACPS_0_WAKE_INTR XPS_GEM0_WAKE_INT_ID +#define XPAR_XEMACPS_1_INTR XPS_GEM1_INT_ID +#define XPAR_XEMACPS_1_WAKE_INTR XPS_GEM1_WAKE_INT_ID +#define XPAR_XSDIOPS_0_INTR XPS_SDIO0_INT_ID +#define XPAR_XQSPIPS_0_INTR XPS_QSPI_INT_ID +#define XPAR_XSDIOPS_1_INTR XPS_SDIO1_INT_ID +#define XPAR_XWDTPS_0_INTR XPS_WDT_INT_ID +#define XPAR_XDCFG_0_INTR XPS_DVC_INT_ID +#define XPAR_SCUTIMER_INTR XPS_SCU_TMR_INT_ID +#define XPAR_SCUWDT_INTR XPS_SCU_WDT_INT_ID +#define XPAR_XTTCPS_0_INTR XPS_TTC0_0_INT_ID +#define XPAR_XTTCPS_1_INTR XPS_TTC0_1_INT_ID +#define XPAR_XTTCPS_2_INTR XPS_TTC0_2_INT_ID +#define XPAR_XTTCPS_3_INTR XPS_TTC1_0_INT_ID +#define XPAR_XTTCPS_4_INTR XPS_TTC1_1_INT_ID +#define XPAR_XTTCPS_5_INTR XPS_TTC1_2_INT_ID +#define XPAR_XDMAPS_0_FAULT_INTR XPS_DMA0_ABORT_INT_ID +#define XPAR_XDMAPS_0_DONE_INTR_0 XPS_DMA0_INT_ID +#define XPAR_XDMAPS_0_DONE_INTR_1 XPS_DMA1_INT_ID +#define XPAR_XDMAPS_0_DONE_INTR_2 XPS_DMA2_INT_ID +#define XPAR_XDMAPS_0_DONE_INTR_3 XPS_DMA3_INT_ID +#define XPAR_XDMAPS_0_DONE_INTR_4 XPS_DMA4_INT_ID +#define XPAR_XDMAPS_0_DONE_INTR_5 XPS_DMA5_INT_ID +#define XPAR_XDMAPS_0_DONE_INTR_6 XPS_DMA6_INT_ID +#define XPAR_XDMAPS_0_DONE_INTR_7 XPS_DMA7_INT_ID + + +#define XPAR_XQSPIPS_0_LINEAR_BASEADDR XPS_QSPI_LINEAR_BASEADDR +#define XPAR_XPARPORTPS_CTRL_BASEADDR XPS_PARPORT_CRTL_BASEADDR + + + +/* Canonical definitions for DMAC */ + + +/* Canonical definitions for WDT */ + +/* Canonical definitions for SLCR */ +#define XPAR_XSLCR_NUM_INSTANCES 1U +#define XPAR_XSLCR_0_DEVICE_ID 0U +#define XPAR_XSLCR_0_BASEADDR XPS_SYS_CTRL_BASEADDR + +/* Canonical definitions for SCU GIC */ +#define XPAR_SCUGIC_NUM_INSTANCES 1U +#define XPAR_SCUGIC_SINGLE_DEVICE_ID 0U +#define XPAR_SCUGIC_CPU_BASEADDR (XPS_SCU_PERIPH_BASE + 0x00000100U) +#define XPAR_SCUGIC_DIST_BASEADDR (XPS_SCU_PERIPH_BASE + 0x00001000U) +#define XPAR_SCUGIC_ACK_BEFORE 0U + +/* Canonical definitions for Global Timer */ +#define XPAR_GLOBAL_TMR_NUM_INSTANCES 1U +#define XPAR_GLOBAL_TMR_DEVICE_ID 0U +#define XPAR_GLOBAL_TMR_BASEADDR (XPS_SCU_PERIPH_BASE + 0x00000200U) +#define XPAR_GLOBAL_TMR_INTR XPS_GLOBAL_TMR_INT_ID + + +/* Xilinx Parallel Flash Library (XilFlash) User Settings */ +#define XPAR_AXI_EMC + + +#define XPAR_CPU_CORTEXA9_CORE_CLOCK_FREQ_HZ XPAR_CPU_CORTEXA9_0_CPU_CLK_FREQ_HZ + + +/* + * This block contains constant declarations for the peripherals + * within the hardblock. These have been put for bacwards compatibilty + */ + +#define XPS_PERIPHERAL_BASEADDR 0xE0000000U +#define XPS_UART0_BASEADDR 0xE0000000U +#define XPS_UART1_BASEADDR 0xE0001000U +#define XPS_USB0_BASEADDR 0xE0002000U +#define XPS_USB1_BASEADDR 0xE0003000U +#define XPS_I2C0_BASEADDR 0xE0004000U +#define XPS_I2C1_BASEADDR 0xE0005000U +#define XPS_SPI0_BASEADDR 0xE0006000U +#define XPS_SPI1_BASEADDR 0xE0007000U +#define XPS_CAN0_BASEADDR 0xE0008000U +#define XPS_CAN1_BASEADDR 0xE0009000U +#define XPS_GPIO_BASEADDR 0xE000A000U +#define XPS_GEM0_BASEADDR 0xE000B000U +#define XPS_GEM1_BASEADDR 0xE000C000U +#define XPS_QSPI_BASEADDR 0xE000D000U +#define XPS_PARPORT_CRTL_BASEADDR 0xE000E000U +#define XPS_SDIO0_BASEADDR 0xE0100000U +#define XPS_SDIO1_BASEADDR 0xE0101000U +#define XPS_IOU_BUS_CFG_BASEADDR 0xE0200000U +#define XPS_NAND_BASEADDR 0xE1000000U +#define XPS_PARPORT0_BASEADDR 0xE2000000U +#define XPS_PARPORT1_BASEADDR 0xE4000000U +#define XPS_QSPI_LINEAR_BASEADDR 0xFC000000U +#define XPS_SYS_CTRL_BASEADDR 0xF8000000U /* AKA SLCR */ +#define XPS_TTC0_BASEADDR 0xF8001000U +#define XPS_TTC1_BASEADDR 0xF8002000U +#define XPS_DMAC0_SEC_BASEADDR 0xF8003000U +#define XPS_DMAC0_NON_SEC_BASEADDR 0xF8004000U +#define XPS_WDT_BASEADDR 0xF8005000U +#define XPS_DDR_CTRL_BASEADDR 0xF8006000U +#define XPS_DEV_CFG_APB_BASEADDR 0xF8007000U +#define XPS_AFI0_BASEADDR 0xF8008000U +#define XPS_AFI1_BASEADDR 0xF8009000U +#define XPS_AFI2_BASEADDR 0xF800A000U +#define XPS_AFI3_BASEADDR 0xF800B000U +#define XPS_OCM_BASEADDR 0xF800C000U +#define XPS_EFUSE_BASEADDR 0xF800D000U +#define XPS_CORESIGHT_BASEADDR 0xF8800000U +#define XPS_TOP_BUS_CFG_BASEADDR 0xF8900000U +#define XPS_SCU_PERIPH_BASE 0xF8F00000U +#define XPS_L2CC_BASEADDR 0xF8F02000U +#define XPS_SAM_RAM_BASEADDR 0xFFFC0000U +#define XPS_FPGA_AXI_S0_BASEADDR 0x40000000U +#define XPS_FPGA_AXI_S1_BASEADDR 0x80000000U +#define XPS_IOU_S_SWITCH_BASEADDR 0xE0000000U +#define XPS_PERIPH_APB_BASEADDR 0xF8000000U + +/* Shared Peripheral Interrupts (SPI) */ +#define XPS_CORE_PARITY0_INT_ID 32U +#define XPS_CORE_PARITY1_INT_ID 33U +#define XPS_L2CC_INT_ID 34U +#define XPS_OCMINTR_INT_ID 35U +#define XPS_ECC_INT_ID 36U +#define XPS_PMU0_INT_ID 37U +#define XPS_PMU1_INT_ID 38U +#define XPS_SYSMON_INT_ID 39U +#define XPS_DVC_INT_ID 40U +#define XPS_WDT_INT_ID 41U +#define XPS_TTC0_0_INT_ID 42U +#define XPS_TTC0_1_INT_ID 43U +#define XPS_TTC0_2_INT_ID 44U +#define XPS_DMA0_ABORT_INT_ID 45U +#define XPS_DMA0_INT_ID 46U +#define XPS_DMA1_INT_ID 47U +#define XPS_DMA2_INT_ID 48U +#define XPS_DMA3_INT_ID 49U +#define XPS_SMC_INT_ID 50U +#define XPS_QSPI_INT_ID 51U +#define XPS_GPIO_INT_ID 52U +#define XPS_USB0_INT_ID 53U +#define XPS_GEM0_INT_ID 54U +#define XPS_GEM0_WAKE_INT_ID 55U +#define XPS_SDIO0_INT_ID 56U +#define XPS_I2C0_INT_ID 57U +#define XPS_SPI0_INT_ID 58U +#define XPS_UART0_INT_ID 59U +#define XPS_CAN0_INT_ID 60U +#define XPS_FPGA0_INT_ID 61U +#define XPS_FPGA1_INT_ID 62U +#define XPS_FPGA2_INT_ID 63U +#define XPS_FPGA3_INT_ID 64U +#define XPS_FPGA4_INT_ID 65U +#define XPS_FPGA5_INT_ID 66U +#define XPS_FPGA6_INT_ID 67U +#define XPS_FPGA7_INT_ID 68U +#define XPS_TTC1_0_INT_ID 69U +#define XPS_TTC1_1_INT_ID 70U +#define XPS_TTC1_2_INT_ID 71U +#define XPS_DMA4_INT_ID 72U +#define XPS_DMA5_INT_ID 73U +#define XPS_DMA6_INT_ID 74U +#define XPS_DMA7_INT_ID 75U +#define XPS_USB1_INT_ID 76U +#define XPS_GEM1_INT_ID 77U +#define XPS_GEM1_WAKE_INT_ID 78U +#define XPS_SDIO1_INT_ID 79U +#define XPS_I2C1_INT_ID 80U +#define XPS_SPI1_INT_ID 81U +#define XPS_UART1_INT_ID 82U +#define XPS_CAN1_INT_ID 83U +#define XPS_FPGA8_INT_ID 84U +#define XPS_FPGA9_INT_ID 85U +#define XPS_FPGA10_INT_ID 86U +#define XPS_FPGA11_INT_ID 87U +#define XPS_FPGA12_INT_ID 88U +#define XPS_FPGA13_INT_ID 89U +#define XPS_FPGA14_INT_ID 90U +#define XPS_FPGA15_INT_ID 91U + +/* Private Peripheral Interrupts (PPI) */ +#define XPS_GLOBAL_TMR_INT_ID 27U /* SCU Global Timer interrupt */ +#define XPS_FIQ_INT_ID 28U /* FIQ from FPGA fabric */ +#define XPS_SCU_TMR_INT_ID 29U /* SCU Private Timer interrupt */ +#define XPS_SCU_WDT_INT_ID 30U /* SCU Private WDT interrupt */ +#define XPS_IRQ_INT_ID 31U /* IRQ from FPGA fabric */ + + +/* REDEFINES for TEST APP */ +/* Definitions for UART */ +#define XPAR_PS7_UART_0_INTR XPS_UART0_INT_ID +#define XPAR_PS7_UART_1_INTR XPS_UART1_INT_ID +#define XPAR_PS7_USB_0_INTR XPS_USB0_INT_ID +#define XPAR_PS7_USB_1_INTR XPS_USB1_INT_ID +#define XPAR_PS7_I2C_0_INTR XPS_I2C0_INT_ID +#define XPAR_PS7_I2C_1_INTR XPS_I2C1_INT_ID +#define XPAR_PS7_SPI_0_INTR XPS_SPI0_INT_ID +#define XPAR_PS7_SPI_1_INTR XPS_SPI1_INT_ID +#define XPAR_PS7_CAN_0_INTR XPS_CAN0_INT_ID +#define XPAR_PS7_CAN_1_INTR XPS_CAN1_INT_ID +#define XPAR_PS7_GPIO_0_INTR XPS_GPIO_INT_ID +#define XPAR_PS7_ETHERNET_0_INTR XPS_GEM0_INT_ID +#define XPAR_PS7_ETHERNET_0_WAKE_INTR XPS_GEM0_WAKE_INT_ID +#define XPAR_PS7_ETHERNET_1_INTR XPS_GEM1_INT_ID +#define XPAR_PS7_ETHERNET_1_WAKE_INTR XPS_GEM1_WAKE_INT_ID +#define XPAR_PS7_QSPI_0_INTR XPS_QSPI_INT_ID +#define XPAR_PS7_WDT_0_INTR XPS_WDT_INT_ID +#define XPAR_PS7_SCUWDT_0_INTR XPS_SCU_WDT_INT_ID +#define XPAR_PS7_SCUTIMER_0_INTR XPS_SCU_TMR_INT_ID +#define XPAR_PS7_XADC_0_INTR XPS_SYSMON_INT_ID +#define XPAR_PS7_TTC_0_INTR XPS_TTC0_0_INT_ID +#define XPAR_PS7_TTC_1_INTR XPS_TTC0_1_INT_ID +#define XPAR_PS7_TTC_2_INTR XPS_TTC0_2_INT_ID +#define XPAR_PS7_TTC_3_INTR XPS_TTC1_0_INT_ID +#define XPAR_PS7_TTC_4_INTR XPS_TTC1_1_INT_ID +#define XPAR_PS7_TTC_5_INTR XPS_TTC1_2_INT_ID + +#define XPAR_XADCPS_INT_ID XPS_SYSMON_INT_ID + +/* For backwards compatibilty */ +#define XPAR_XUARTPS_0_CLOCK_HZ XPAR_XUARTPS_0_UART_CLK_FREQ_HZ +#define XPAR_XUARTPS_1_CLOCK_HZ XPAR_XUARTPS_1_UART_CLK_FREQ_HZ +#define XPAR_XTTCPS_0_CLOCK_HZ XPAR_XTTCPS_0_TTC_CLK_FREQ_HZ +#define XPAR_XTTCPS_1_CLOCK_HZ XPAR_XTTCPS_1_TTC_CLK_FREQ_HZ +#define XPAR_XTTCPS_2_CLOCK_HZ XPAR_XTTCPS_2_TTC_CLK_FREQ_HZ +#define XPAR_XTTCPS_3_CLOCK_HZ XPAR_XTTCPS_3_TTC_CLK_FREQ_HZ +#define XPAR_XTTCPS_4_CLOCK_HZ XPAR_XTTCPS_4_TTC_CLK_FREQ_HZ +#define XPAR_XTTCPS_5_CLOCK_HZ XPAR_XTTCPS_5_TTC_CLK_FREQ_HZ +#define XPAR_XIICPS_0_CLOCK_HZ XPAR_XIICPS_0_I2C_CLK_FREQ_HZ +#define XPAR_XIICPS_1_CLOCK_HZ XPAR_XIICPS_1_I2C_CLK_FREQ_HZ + +#define XPAR_XQSPIPS_0_CLOCK_HZ XPAR_XQSPIPS_0_QSPI_CLK_FREQ_HZ + +#ifdef XPAR_CPU_CORTEXA9_0_CPU_CLK_FREQ_HZ +#define XPAR_CPU_CORTEXA9_CORE_CLOCK_FREQ_HZ XPAR_CPU_CORTEXA9_0_CPU_CLK_FREQ_HZ +#endif + +#ifdef XPAR_CPU_CORTEXA9_1_CPU_CLK_FREQ_HZ +#define XPAR_CPU_CORTEXA9_CORE_CLOCK_FREQ_HZ XPAR_CPU_CORTEXA9_1_CPU_CLK_FREQ_HZ +#endif + +#define XPAR_SCUTIMER_DEVICE_ID 0U +#define XPAR_SCUWDT_DEVICE_ID 0U + + +#ifdef __cplusplus +} +#endif + +#endif /* protection macro */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/include/xplatform_info.h b/datalink814_ge/bsp/ps7_cortexa9_0/include/xplatform_info.h new file mode 100644 index 0000000..88851bb --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/include/xplatform_info.h @@ -0,0 +1,120 @@ +/****************************************************************************** +* +* Copyright (C) 2014 - 2017 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xplatform_info.h +* +* @addtogroup common_platform_info APIs to Get Platform Information +* +* The xplatform_info.h file contains definitions for various available Xilinx® +* platforms. Also, it contains prototype of APIs, which can be used to get the +* platform information. +* +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date    Changes
+* ----- ---- --------- -------------------------------------------------------
+* 6.4    ms   05/23/17 Added PSU_PMU macro to support XGetPSVersion_Info
+*                      function for PMUFW.
+* 
+* +******************************************************************************/ + +#ifndef XPLATFORM_INFO_H /* prevent circular inclusions */ +#define XPLATFORM_INFO_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" + +/************************** Constant Definitions *****************************/ +#if defined (versal) +#define XPAR_PMC_TAP_BASEADDR 0xF11A0000U +#define XPAR_PMC_TAP_VERSION_OFFSET 0x00000004U +#define XPLAT_PS_VERSION_ADDRESS (XPAR_PMC_TAP_BASEADDR + \ + XPAR_PMC_TAP_VERSION_OFFSET) +#else +#define XPAR_CSU_BASEADDR 0xFFCA0000U +#define XPAR_CSU_VER_OFFSET 0x00000044U +#define XPLAT_PS_VERSION_ADDRESS (XPAR_CSU_BASEADDR + \ + XPAR_CSU_VER_OFFSET) +#endif +#define XPLAT_ZYNQ_ULTRA_MP_SILICON 0x0 +#define XPLAT_ZYNQ_ULTRA_MP 0x1 +#define XPLAT_ZYNQ_ULTRA_MPVEL 0x2 +#define XPLAT_ZYNQ_ULTRA_MPQEMU 0x3 +#define XPLAT_ZYNQ 0x4 +#define XPLAT_MICROBLAZE 0x5 +#define XPLAT_versal 0x6U + +#define XPS_VERSION_1 0x0 +#define XPS_VERSION_2 0x1 +#define XPLAT_INFO_MASK (0xF) + +#if defined (versal) +#define XPS_VERSION_INFO_MASK 0xFF00U +#define XPS_VERSION_INFO_SHIFT 0x8U +#define XPLAT_INFO_SHIFT 0x18U +#else +#define XPS_VERSION_INFO_MASK (0xF) +#define XPS_VERSION_INFO_SHIFT 0x0U +#define XPLAT_INFO_SHIFT 0xCU +#endif + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + + +u32 XGetPlatform_Info(void); + +#if defined (ARMR5) || (__aarch64__) || (ARMA53_32) || (PSU_PMU) +u32 XGetPSVersion_Info(); +#endif + +#if defined (ARMR5) || (__aarch64__) || (ARMA53_32) +u32 XGet_Zynq_UltraMp_Platform_info(); +#endif +/************************** Function Prototypes ******************************/ + + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** +* @} End of "addtogroup common_platform_info". +*/ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/include/xpm_counter.h b/datalink814_ge/bsp/ps7_cortexa9_0/include/xpm_counter.h new file mode 100644 index 0000000..39db7d8 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/include/xpm_counter.h @@ -0,0 +1,572 @@ +/****************************************************************************** +* +* Copyright (C) 2011 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xpm_counter.h +* +* @addtogroup a9_event_counter_apis Cortex A9 Event Counters Functions +* +* Cortex A9 event counter functions can be utilized to configure and control +* the Cortex-A9 performance monitor events. +* +* Cortex-A9 performance monitor has six event counters which can be used to +* count a variety of events described in Coretx-A9 TRM. xpm_counter.h defines +* configurations XPM_CNTRCFGx which can be used to program the event counters +* to count a set of events. +* +* @note +* It doesn't handle the Cortex-A9 cycle counter, as the cycle counter is +* being used for time keeping. +* +* @{ +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a sdm  07/11/11 First release
+* 6.8   aru  09/06/18 Removed compilation warnings for ARMCC toolchain.
+* 
+* +******************************************************************************/ + +#ifndef XPMCOUNTER_H /* prevent circular inclusions */ +#define XPMCOUNTER_H /* by using protection macros */ + +/***************************** Include Files ********************************/ + +#include +#include "xpseudo_asm.h" +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/************************** Constant Definitions ****************************/ + +/* Number of performance counters */ +#define XPM_CTRCOUNT 6U + +/* The following constants define the Cortex-A9 Performance Monitor Events */ + +/* + * Software increment. The register is incremented only on writes to the + * Software Increment Register + */ +#define XPM_EVENT_SOFTINCR 0x00U + +/* + * Instruction fetch that causes a refill at (at least) the lowest level(s) of + * instruction or unified cache. Includes the speculative linefills in the + * count + */ +#define XPM_EVENT_INSRFETCH_CACHEREFILL 0x01U + +/* + * Instruction fetch that causes a TLB refill at (at least) the lowest level of + * TLB. Includes the speculative requests in the count + */ +#define XPM_EVENT_INSTRFECT_TLBREFILL 0x02U + +/* + * Data read or write operation that causes a refill at (at least) the lowest + * level(s)of data or unified cache. Counts the number of allocations performed + * in the Data Cache due to a read or a write + */ +#define XPM_EVENT_DATA_CACHEREFILL 0x03U + +/* + * Data read or write operation that causes a cache access at (at least) the + * lowest level(s) of data or unified cache. This includes speculative reads + */ +#define XPM_EVENT_DATA_CACHEACCESS 0x04U + +/* + * Data read or write operation that causes a TLB refill at (at least) the + * lowest level of TLB. This does not include micro TLB misses due to PLD, PLI, + * CP15 Cache operation by MVA and CP15 VA to PA operations + */ +#define XPM_EVENT_DATA_TLBREFILL 0x05U + +/* + * Data read architecturally executed. Counts the number of data read + * instructions accepted by the Load Store Unit. This includes counting the + * speculative and aborted LDR/LDM, as well as the reads due to the SWP + * instructions + */ +#define XPM_EVENT_DATA_READS 0x06U + +/* + * Data write architecturally executed. Counts the number of data write + * instructions accepted by the Load Store Unit. This includes counting the + * speculative and aborted STR/STM, as well as the writes due to the SWP + * instructions + */ +#define XPM_EVENT_DATA_WRITE 0x07U + +/* Exception taken. Counts the number of exceptions architecturally taken.*/ +#define XPM_EVENT_EXCEPTION 0x09U + +/* Exception return architecturally executed.*/ +#define XPM_EVENT_EXCEPRETURN 0x0AU + +/* + * Change to ContextID retired. Counts the number of instructions + * architecturally executed writing into the ContextID Register + */ +#define XPM_EVENT_CHANGECONTEXT 0x0BU + +/* + * Software change of PC, except by an exception, architecturally executed. + * Count the number of PC changes architecturally executed, excluding the PC + * changes due to taken exceptions + */ +#define XPM_EVENT_SW_CHANGEPC 0x0CU + +/* + * Immediate branch architecturally executed (taken or not taken). This includes + * the branches which are flushed due to a previous load/store which aborts + * late + */ +#define XPM_EVENT_IMMEDBRANCH 0x0DU + +/* + * Unaligned access architecturally executed. Counts the number of aborted + * unaligned accessed architecturally executed, and the number of not-aborted + * unaligned accesses, including the speculative ones + */ +#define XPM_EVENT_UNALIGNEDACCESS 0x0FU + +/* + * Branch mispredicted/not predicted. Counts the number of mispredicted or + * not-predicted branches executed. This includes the branches which are flushed + * due to a previous load/store which aborts late + */ +#define XPM_EVENT_BRANCHMISS 0x10U + +/* + * Counts clock cycles when the Cortex-A9 processor is not in WFE/WFI. This + * event is not exported on the PMUEVENT bus + */ +#define XPM_EVENT_CLOCKCYCLES 0x11U + +/* + * Branches or other change in program flow that could have been predicted by + * the branch prediction resources of the processor. This includes the branches + * which are flushed due to a previous load/store which aborts late + */ +#define XPM_EVENT_BRANCHPREDICT 0x12U + +/* + * Java bytecode execute. Counts the number of Java bytecodes being decoded, + * including speculative ones + */ +#define XPM_EVENT_JAVABYTECODE 0x40U + +/* + * Software Java bytecode executed. Counts the number of software java bytecodes + * being decoded, including speculative ones + */ +#define XPM_EVENT_SWJAVABYTECODE 0x41U + +/* + * Jazelle backward branches executed. Counts the number of Jazelle taken + * branches being executed. This includes the branches which are flushed due + * to a previous load/store which aborts late + */ +#define XPM_EVENT_JAVABACKBRANCH 0x42U + +/* + * Coherent linefill miss Counts the number of coherent linefill requests + * performed by the Cortex-A9 processor which also miss in all the other + * Cortex-A9 processors, meaning that the request is sent to the external + * memory + */ +#define XPM_EVENT_COHERLINEMISS 0x50U + +/* + * Coherent linefill hit. Counts the number of coherent linefill requests + * performed by the Cortex-A9 processor which hit in another Cortex-A9 + * processor, meaning that the linefill data is fetched directly from the + * relevant Cortex-A9 cache + */ +#define XPM_EVENT_COHERLINEHIT 0x51U + +/* + * Instruction cache dependent stall cycles. Counts the number of cycles where + * the processor is ready to accept new instructions, but does not receive any + * due to the instruction side not being able to provide any and the + * instruction cache is currently performing at least one linefill + */ +#define XPM_EVENT_INSTRSTALL 0x60U + +/* + * Data cache dependent stall cycles. Counts the number of cycles where the core + * has some instructions that it cannot issue to any pipeline, and the Load + * Store unit has at least one pending linefill request, and no pending + */ +#define XPM_EVENT_DATASTALL 0x61U + +/* + * Main TLB miss stall cycles. Counts the number of cycles where the processor + * is stalled waiting for the completion of translation table walks from the + * main TLB. The processor stalls can be due to the instruction side not being + * able to provide the instructions, or to the data side not being able to + * provide the necessary data, due to them waiting for the main TLB translation + * table walk to complete + */ +#define XPM_EVENT_MAINTLBSTALL 0x62U + +/* + * Counts the number of STREX instructions architecturally executed and + * passed + */ +#define XPM_EVENT_STREXPASS 0x63U + +/* + * Counts the number of STREX instructions architecturally executed and + * failed + */ +#define XPM_EVENT_STREXFAIL 0x64U + +/* + * Data eviction. Counts the number of eviction requests due to a linefill in + * the data cache + */ +#define XPM_EVENT_DATAEVICT 0x65U + +/* + * Counts the number of cycles where the issue stage does not dispatch any + * instruction because it is empty or cannot dispatch any instructions + */ +#define XPM_EVENT_NODISPATCH 0x66U + +/* + * Counts the number of cycles where the issue stage is empty + */ +#define XPM_EVENT_ISSUEEMPTY 0x67U + +/* + * Counts the number of instructions going through the Register Renaming stage. + * This number is an approximate number of the total number of instructions + * speculatively executed, and even more approximate of the total number of + * instructions architecturally executed. The approximation depends mainly on + * the branch misprediction rate. + * The renaming stage can handle two instructions in the same cycle so the event + * is two bits long: + * - b00 no instructions renamed + * - b01 one instruction renamed + * - b10 two instructions renamed + */ +#define XPM_EVENT_INSTRRENAME 0x68U + +/* + * Counts the number of procedure returns whose condition codes do not fail, + * excluding all returns from exception. This count includes procedure returns + * which are flushed due to a previous load/store which aborts late. + * Only the following instructions are reported: + * - BX R14 + * - MOV PC LR + * - POP {..,pc} + * - LDR pc,[sp],#offset + * The following instructions are not reported: + * - LDMIA R9!,{..,PC} (ThumbEE state only) + * - LDR PC,[R9],#offset (ThumbEE state only) + * - BX R0 (Rm != R14) + * - MOV PC,R0 (Rm != R14) + * - LDM SP,{...,PC} (writeback not specified) + * - LDR PC,[SP,#offset] (wrong addressing mode) + */ +#define XPM_EVENT_PREDICTFUNCRET 0x6EU + +/* + * Counts the number of instructions being executed in the main execution + * pipeline of the processor, the multiply pipeline and arithmetic logic unit + * pipeline. The counted instructions are still speculative + */ +#define XPM_EVENT_MAINEXEC 0x70U + +/* + * Counts the number of instructions being executed in the processor second + * execution pipeline (ALU). The counted instructions are still speculative + */ +#define XPM_EVENT_SECEXEC 0x71U + +/* + * Counts the number of instructions being executed in the Load/Store unit. The + * counted instructions are still speculative + */ +#define XPM_EVENT_LDRSTR 0x72U + +/* + * Counts the number of Floating-point instructions going through the Register + * Rename stage. Instructions are still speculative in this stage. + *Two floating-point instructions can be renamed in the same cycle so the event + * is two bitslong: + *0b00 no floating-point instruction renamed + *0b01 one floating-point instruction renamed + *0b10 two floating-point instructions renamed + */ +#define XPM_EVENT_FLOATRENAME 0x73U + +/* + * Counts the number of Neon instructions going through the Register Rename + * stage.Instructions are still speculative in this stage. + * Two NEON instructions can be renamed in the same cycle so the event is two + * bits long: + *0b00 no NEON instruction renamed + *0b01 one NEON instruction renamed + *0b10 two NEON instructions renamed + */ +#define XPM_EVENT_NEONRENAME 0x74U + +/* + * Counts the number of cycles where the processor is stalled because PLD slots + * are all full + */ +#define XPM_EVENT_PLDSTALL 0x80U + +/* + * Counts the number of cycles when the processor is stalled and the data side + * is stalled too because it is full and executing writes to the external + * memory + */ +#define XPM_EVENT_WRITESTALL 0x81U + +/* + * Counts the number of stall cycles due to main TLB misses on requests issued + * by the instruction side + */ +#define XPM_EVENT_INSTRTLBSTALL 0x82U + +/* + * Counts the number of stall cycles due to main TLB misses on requests issued + * by the data side + */ +#define XPM_EVENT_DATATLBSTALL 0x83U + +/* + * Counts the number of stall cycles due to micro TLB misses on the instruction + * side. This event does not include main TLB miss stall cycles that are already + * counted in the corresponding main TLB event + */ +#define XPM_EVENT_INSTR_uTLBSTALL 0x84U + +/* + * Counts the number of stall cycles due to micro TLB misses on the data side. + * This event does not include main TLB miss stall cycles that are already + * counted in the corresponding main TLB event + */ +#define XPM_EVENT_DATA_uTLBSTALL 0x85U + +/* + * Counts the number of stall cycles because of the execution of a DMB memory + * barrier. This includes all DMB instructions being executed, even + * speculatively + */ +#define XPM_EVENT_DMB_STALL 0x86U + +/* + * Counts the number of cycles during which the integer core clock is enabled + */ +#define XPM_EVENT_INT_CLKEN 0x8AU + +/* + * Counts the number of cycles during which the Data Engine clock is enabled + */ +#define XPM_EVENT_DE_CLKEN 0x8BU + +/* + * Counts the number of ISB instructions architecturally executed + */ +#define XPM_EVENT_INSTRISB 0x90U + +/* + * Counts the number of DSB instructions architecturally executed + */ +#define XPM_EVENT_INSTRDSB 0x91U + +/* + * Counts the number of DMB instructions speculatively executed + */ +#define XPM_EVENT_INSTRDMB 0x92U + +/* + * Counts the number of external interrupts executed by the processor + */ +#define XPM_EVENT_EXTINT 0x93U + +/* + * PLE cache line request completed + */ +#define XPM_EVENT_PLE_LRC 0xA0U + +/* + * PLE cache line request skipped + */ +#define XPM_EVENT_PLE_LRS 0xA1U + +/* + * PLE FIFO flush + */ +#define XPM_EVENT_PLE_FLUSH 0xA2U + +/* + * PLE request complete + */ +#define XPM_EVENT_PLE_CMPL 0xA3U + +/* + * PLE FIFO overflow + */ +#define XPM_EVENT_PLE_OVFL 0xA4U + +/* + * PLE request programmed + */ +#define XPM_EVENT_PLE_PROG 0xA5U + +/* + * The following constants define the configurations for Cortex-A9 Performance + * Monitor Events. Each configuration configures the event counters for a set + * of events. + * ----------------------------------------------- + * Config PmCtr0... PmCtr5 + * ----------------------------------------------- + * XPM_CNTRCFG1 { XPM_EVENT_SOFTINCR, + * XPM_EVENT_INSRFETCH_CACHEREFILL, + * XPM_EVENT_INSTRFECT_TLBREFILL, + * XPM_EVENT_DATA_CACHEREFILL, + * XPM_EVENT_DATA_CACHEACCESS, + * XPM_EVENT_DATA_TLBREFILL } + * + * XPM_CNTRCFG2 { XPM_EVENT_DATA_READS, + * XPM_EVENT_DATA_WRITE, + * XPM_EVENT_EXCEPTION, + * XPM_EVENT_EXCEPRETURN, + * XPM_EVENT_CHANGECONTEXT, + * XPM_EVENT_SW_CHANGEPC } + * + * XPM_CNTRCFG3 { XPM_EVENT_IMMEDBRANCH, + * XPM_EVENT_UNALIGNEDACCESS, + * XPM_EVENT_BRANCHMISS, + * XPM_EVENT_CLOCKCYCLES, + * XPM_EVENT_BRANCHPREDICT, + * XPM_EVENT_JAVABYTECODE } + * + * XPM_CNTRCFG4 { XPM_EVENT_SWJAVABYTECODE, + * XPM_EVENT_JAVABACKBRANCH, + * XPM_EVENT_COHERLINEMISS, + * XPM_EVENT_COHERLINEHIT, + * XPM_EVENT_INSTRSTALL, + * XPM_EVENT_DATASTALL } + * + * XPM_CNTRCFG5 { XPM_EVENT_MAINTLBSTALL, + * XPM_EVENT_STREXPASS, + * XPM_EVENT_STREXFAIL, + * XPM_EVENT_DATAEVICT, + * XPM_EVENT_NODISPATCH, + * XPM_EVENT_ISSUEEMPTY } + * + * XPM_CNTRCFG6 { XPM_EVENT_INSTRRENAME, + * XPM_EVENT_PREDICTFUNCRET, + * XPM_EVENT_MAINEXEC, + * XPM_EVENT_SECEXEC, + * XPM_EVENT_LDRSTR, + * XPM_EVENT_FLOATRENAME } + * + * XPM_CNTRCFG7 { XPM_EVENT_NEONRENAME, + * XPM_EVENT_PLDSTALL, + * XPM_EVENT_WRITESTALL, + * XPM_EVENT_INSTRTLBSTALL, + * XPM_EVENT_DATATLBSTALL, + * XPM_EVENT_INSTR_uTLBSTALL } + * + * XPM_CNTRCFG8 { XPM_EVENT_DATA_uTLBSTALL, + * XPM_EVENT_DMB_STALL, + * XPM_EVENT_INT_CLKEN, + * XPM_EVENT_DE_CLKEN, + * XPM_EVENT_INSTRISB, + * XPM_EVENT_INSTRDSB } + * + * XPM_CNTRCFG9 { XPM_EVENT_INSTRDMB, + * XPM_EVENT_EXTINT, + * XPM_EVENT_PLE_LRC, + * XPM_EVENT_PLE_LRS, + * XPM_EVENT_PLE_FLUSH, + * XPM_EVENT_PLE_CMPL } + * + * XPM_CNTRCFG10 { XPM_EVENT_PLE_OVFL, + * XPM_EVENT_PLE_PROG, + * XPM_EVENT_PLE_LRC, + * XPM_EVENT_PLE_LRS, + * XPM_EVENT_PLE_FLUSH, + * XPM_EVENT_PLE_CMPL } + * + * XPM_CNTRCFG11 { XPM_EVENT_DATASTALL, + * XPM_EVENT_INSRFETCH_CACHEREFILL, + * XPM_EVENT_INSTRFECT_TLBREFILL, + * XPM_EVENT_DATA_CACHEREFILL, + * XPM_EVENT_DATA_CACHEACCESS, + * XPM_EVENT_DATA_TLBREFILL } + */ +#define XPM_CNTRCFG1 0 +#define XPM_CNTRCFG2 1 +#define XPM_CNTRCFG3 2 +#define XPM_CNTRCFG4 3 +#define XPM_CNTRCFG5 4 +#define XPM_CNTRCFG6 5 +#define XPM_CNTRCFG7 6 +#define XPM_CNTRCFG8 7 +#define XPM_CNTRCFG9 8 +#define XPM_CNTRCFG10 9 +#define XPM_CNTRCFG11 10 + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Variable Definitions ****************************/ + +/************************** Function Prototypes *****************************/ + +/* Interface fuctions to access perfromance counters from abstraction layer */ +void Xpm_SetEvents(s32 PmcrCfg); +void Xpm_GetEventCounters(u32 *PmCtrValue); + +#ifdef __cplusplus +} +#endif + +#endif +/** +* @} End of "addtogroup a9_event_counter_apis". +*/ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/include/xpseudo_asm.h b/datalink814_ge/bsp/ps7_cortexa9_0/include/xpseudo_asm.h new file mode 100644 index 0000000..c7123a0 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/include/xpseudo_asm.h @@ -0,0 +1,82 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xpseudo_asm.h +* +* @addtogroup a9_specific Cortex A9 Processor Specific Include Files +* +* The xpseudo_asm.h includes xreg_cortexa9.h and xpseudo_asm_gcc.h. +* +* The xreg_cortexa9.h file contains definitions for inline assembler code. +* It provides inline definitions for Cortex A9 GPRs, SPRs, MPE registers, +* co-processor registers and Debug registers. +* +* The xpseudo_asm_gcc.h contains the definitions for the most often used inline +* assembler instructions, available as macros. These can be very useful for +* tasks such as setting or getting special purpose registers, synchronization, +* or cache manipulation etc. These inline assembler instructions can be used +* from drivers and user applications written in C. +* +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a ecm  10/18/09 First release
+* 3.04a sdm  01/02/12 Remove redundant dsb in mcr instruction.
+* 6.8   aru  09/06/18 Removed compilation warnings for ARMCC toolchain.
+* 
+* +******************************************************************************/ +#ifndef XPSEUDO_ASM_H +#define XPSEUDO_ASM_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "xreg_cortexa9.h" +#ifdef __GNUC__ + #include "xpseudo_asm_gcc.h" +#elif defined (__ICCARM__) + #include "xpseudo_asm_iccarm.h" +#else + #include "xpseudo_asm_rvct.h" +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* XPSEUDO_ASM_H */ +/** +* @} End of "addtogroup a9_specific". +*/ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/include/xpseudo_asm_gcc.h b/datalink814_ge/bsp/ps7_cortexa9_0/include/xpseudo_asm_gcc.h new file mode 100644 index 0000000..85b067d --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/include/xpseudo_asm_gcc.h @@ -0,0 +1,252 @@ +/****************************************************************************** +* +* Copyright (C) 2014 - 2016 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xpseudo_asm_gcc.h +* +* This header file contains macros for using inline assembler code. It is +* written specifically for the GNU compiler. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 5.00 	pkp		 05/21/14 First release
+* 6.0   mus      07/27/16 Consolidated file for a53,a9 and r5 processors
+* 
+* +******************************************************************************/ + +#ifndef XPSEUDO_ASM_GCC_H /* prevent circular inclusions */ +#define XPSEUDO_ASM_GCC_H /* by using protection macros */ + +/***************************** Include Files ********************************/ + +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/* necessary for pre-processor */ +#define stringify(s) tostring(s) +#define tostring(s) #s + +#if defined (__aarch64__) +/* pseudo assembler instructions */ +#define mfcpsr() ({u32 rval = 0U; \ + asm volatile("mrs %0, DAIF" : "=r" (rval));\ + rval;\ + }) + +#define mtcpsr(v) __asm__ __volatile__ ("msr DAIF, %0" : : "r" (v)) + +#define cpsiei() //__asm__ __volatile__("cpsie i\n") +#define cpsidi() //__asm__ __volatile__("cpsid i\n") + +#define cpsief() //__asm__ __volatile__("cpsie f\n") +#define cpsidf() //__asm__ __volatile__("cpsid f\n") + + + +#define mtgpr(rn, v) /*__asm__ __volatile__(\ + "mov r" stringify(rn) ", %0 \n"\ + : : "r" (v)\ + )*/ + +#define mfgpr(rn) /*({u32 rval; \ + __asm__ __volatile__(\ + "mov %0,r" stringify(rn) "\n"\ + : "=r" (rval)\ + );\ + rval;\ + })*/ + +/* memory synchronization operations */ + +/* Instruction Synchronization Barrier */ +#define isb() __asm__ __volatile__ ("isb sy") + +/* Data Synchronization Barrier */ +#define dsb() __asm__ __volatile__("dsb sy") + +/* Data Memory Barrier */ +#define dmb() __asm__ __volatile__("dmb sy") + + +/* Memory Operations */ +#define ldr(adr) ({u64 rval; \ + __asm__ __volatile__(\ + "ldr %0,[%1]"\ + : "=r" (rval) : "r" (adr)\ + );\ + rval;\ + }) + +#define mfelrel3() ({u64 rval = 0U; \ + asm volatile("mrs %0, ELR_EL3" : "=r" (rval));\ + rval;\ + }) + +#define mtelrel3(v) __asm__ __volatile__ ("msr ELR_EL3, %0" : : "r" (v)) + +#else + +/* pseudo assembler instructions */ +#define mfcpsr() ({u32 rval = 0U; \ + __asm__ __volatile__(\ + "mrs %0, cpsr\n"\ + : "=r" (rval)\ + );\ + rval;\ + }) + +#define mtcpsr(v) __asm__ __volatile__(\ + "msr cpsr,%0\n"\ + : : "r" (v)\ + ) + +#define cpsiei() __asm__ __volatile__("cpsie i\n") +#define cpsidi() __asm__ __volatile__("cpsid i\n") + +#define cpsief() __asm__ __volatile__("cpsie f\n") +#define cpsidf() __asm__ __volatile__("cpsid f\n") + + + +#define mtgpr(rn, v) __asm__ __volatile__(\ + "mov r" stringify(rn) ", %0 \n"\ + : : "r" (v)\ + ) + +#define mfgpr(rn) ({u32 rval; \ + __asm__ __volatile__(\ + "mov %0,r" stringify(rn) "\n"\ + : "=r" (rval)\ + );\ + rval;\ + }) + +/* memory synchronization operations */ + +/* Instruction Synchronization Barrier */ +#define isb() __asm__ __volatile__ ("isb" : : : "memory") + +/* Data Synchronization Barrier */ +#define dsb() __asm__ __volatile__ ("dsb" : : : "memory") + +/* Data Memory Barrier */ +#define dmb() __asm__ __volatile__ ("dmb" : : : "memory") + + +/* Memory Operations */ +#define ldr(adr) ({u32 rval; \ + __asm__ __volatile__(\ + "ldr %0,[%1]"\ + : "=r" (rval) : "r" (adr)\ + );\ + rval;\ + }) + +#endif + +#define ldrb(adr) ({u8 rval; \ + __asm__ __volatile__(\ + "ldrb %0,[%1]"\ + : "=r" (rval) : "r" (adr)\ + );\ + rval;\ + }) + +#define str(adr, val) __asm__ __volatile__(\ + "str %0,[%1]\n"\ + : : "r" (val), "r" (adr)\ + ) + +#define strb(adr, val) __asm__ __volatile__(\ + "strb %0,[%1]\n"\ + : : "r" (val), "r" (adr)\ + ) + +/* Count leading zeroes (clz) */ +#define clz(arg) ({u8 rval; \ + __asm__ __volatile__(\ + "clz %0,%1"\ + : "=r" (rval) : "r" (arg)\ + );\ + rval;\ + }) + +#if defined (__aarch64__) +#define mtcpdc(reg,val) __asm__ __volatile__("dc " #reg ",%0" : : "r" (val)) +#define mtcpic(reg,val) __asm__ __volatile__("ic " #reg ",%0" : : "r" (val)) + +#define mtcpicall(reg) __asm__ __volatile__("ic " #reg) +#define mtcptlbi(reg) __asm__ __volatile__("tlbi " #reg) +#define mtcpat(reg,val) __asm__ __volatile__("at " #reg ",%0" : : "r" (val)) +/* CP15 operations */ +#define mfcp(reg) ({u64 rval = 0U;\ + __asm__ __volatile__("mrs %0, " #reg : "=r" (rval));\ + rval;\ + }) + +#define mtcp(reg,val) __asm__ __volatile__("msr " #reg ",%0" : : "r" (val)) + +#else +/* CP15 operations */ +#define mtcp(rn, v) __asm__ __volatile__(\ + "mcr " rn "\n"\ + : : "r" (v)\ + ); + +#define mfcp(rn) ({u32 rval = 0U; \ + __asm__ __volatile__(\ + "mrc " rn "\n"\ + : "=r" (rval)\ + );\ + rval;\ + }) +#endif + +/************************** Variable Definitions ****************************/ + +/************************** Function Prototypes *****************************/ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* XPSEUDO_ASM_GCC_H */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/include/xqspips.h b/datalink814_ge/bsp/ps7_cortexa9_0/include/xqspips.h new file mode 100644 index 0000000..0255bc2 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/include/xqspips.h @@ -0,0 +1,804 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xqspips.h +* @addtogroup qspips_v3_6 +* @{ +* @details +* +* This file contains the implementation of the XQspiPs driver. It supports only +* master mode. User documentation for the driver functions is contained in this +* file in the form of comment blocks at the front of each function. +* +* A QSPI device connects to an QSPI bus through a 4-wire serial interface. +* The QSPI bus is a full-duplex, synchronous bus that facilitates communication +* between one master and one slave. The device is always full-duplex, +* which means that for every byte sent, one is received, and vice-versa. +* The master controls the clock, so it can regulate when it wants to +* send or receive data. The slave is under control of the master, it must +* respond quickly since it has no control of the clock and must send/receive +* data as fast or as slow as the master does. +* +* Linear Mode +* The Linear Quad-SPI Controller extends the existing Quad-SPI Controller�s +* functionality by adding a linear addressing scheme that allows the SPI flash +* memory subsystem to behave like a typical ROM device. The new feature hides +* the normal SPI protocol from a master reading from the SPI flash memory. The +* feature improves both the user friendliness and the overall read memory +* throughput over that of the current Quad-SPI Controller by lessening the +* amount of software overheads required and by the use of the faster AXI +* interface. +* +* Initialization & Configuration +* +* The XQspiPs_Config structure is used by the driver to configure itself. This +* configuration structure is typically created by the tool-chain based on HW +* build properties. +* +* To support multiple runtime loading and initialization strategies employed by +* various operating systems, the driver instance can be initialized in the +* following way: +* - XQspiPs_LookupConfig(DeviceId) - Use the device identifier to find +* static configuration structure defined in xqspips_g.c. This is setup +* by the tools. For some operating systems the config structure will be +* initialized by the software and this call is not needed. +* - XQspiPs_CfgInitialize(InstancePtr, CfgPtr, EffectiveAddr) - Uses a +* configuration structure provided by the caller. If running in a system +* with address translation, the provided virtual memory base address +* replaces the physical address present in the configuration structure. +* +* Multiple Masters +* +* More than one master can exist, but arbitration is the responsibility of +* the higher layer software. The device driver does not perform any type of +* arbitration. +* +* Modes of Operation +* +* There are four modes to perform a data transfer and the selection of a mode +* is based on Chip Select(CS) and Start. These two options individually, can +* be controlled either by software(Manual) or hardware(Auto). +* - Auto CS: Chip select is automatically asserted as soon as the first word +* is written into the TXFIFO and de asserted when the TXFIFO becomes +* empty +* - Manual CS: Software must assert and de assert CS. +* - Auto Start: Data transmission starts as soon as there is data in the +* TXFIFO and stalls when the TXFIFO is empty +* - Manual Start: Software must start data transmission at the beginning of +* the transaction or whenever the TXFIFO has become empty +* +* The preferred combination is Manual CS and Auto Start. +* In this combination, the software asserts CS before loading any data into +* TXFIFO. In Auto Start mode, whenever data is in TXFIFO, controller sends it +* out until TXFIFO becomes empty. The software reads the RXFIFO whenever the +* data is available. If no further data, software disables CS. +* +* Risks/challenges of other combinations: +* - Manual CS and Manual Start: Manual Start bit should be set after each +* TXFIFO write otherwise there could be a race condition where the TXFIFO +* becomes empty before the new word is written. In that case the +* transmission stops. +* - Auto CS with Manual or Auto Start: It is very difficult for software to +* keep the TXFIFO filled. Whenever the TXFIFO runs empty, CS is de asserted. +* This results in a single transaction to be split into multiple pieces each +* with its own chip select. This will result in garbage data to be sent. +* +* Interrupts +* +* The user must connect the interrupt handler of the driver, +* XQspiPs_InterruptHandler, to an interrupt system such that it will be +* called when an interrupt occurs. This function does not save and restore +* the processor context such that the user must provide this processing. +* +* The driver handles the following interrupts: +* - Data Transmit Register/FIFO Underflow +* - Data Receive Register/FIFO Not Empty +* - Data Transmit Register/FIFO Overwater +* - Data Receive Register/FIFO Overrun +* +* The Data Transmit Register/FIFO Overwater interrupt -- indicates that the +* QSPI device has transmitted the data available to transmit, and now its data +* register and FIFO is ready to accept more data. The driver uses this +* interrupt to indicate progress while sending data. The driver may have +* more data to send, in which case the data transmit register and FIFO is +* filled for subsequent transmission. When this interrupt arrives and all +* the data has been sent, the driver invokes the status callback with a +* value of XST_SPI_TRANSFER_DONE to inform the upper layer software that +* all data has been sent. +* +* The Data Transmit Register/FIFO Underflow interrupt -- indicates that, +* as slave, the QSPI device was required to transmit but there was no data +* available to transmit in the transmit register (or FIFO). This may not +* be an error if the master is not expecting data. But in the case where +* the master is expecting data, this serves as a notification of such a +* condition. The driver reports this condition to the upper layer +* software through the status handler. +* +* The Data Receive Register/FIFO Overrun interrupt -- indicates that the QSPI +* device received data and subsequently dropped the data because the data +* receive register and FIFO was full. The driver reports this condition to the +* upper layer software through the status handler. This likely indicates a +* problem with the higher layer protocol, or a problem with the slave +* performance. +* +* +* Polled Operation +* +* Transfer in polled mode is supported through a separate interface function +* XQspiPs_PolledTransfer(). Unlike the transfer function in the interrupt mode, +* this function blocks until all data has been sent/received. +* +* Device Busy +* +* Some operations are disallowed when the device is busy. The driver tracks +* whether a device is busy. The device is considered busy when a data transfer +* request is outstanding, and is considered not busy only when that transfer +* completes (or is aborted with a mode fault error). +* +* Device Configuration +* +* The device can be configured in various ways during the FPGA implementation +* process. Configuration parameters are stored in the xqspips_g.c file or +* passed in via XQspiPs_CfgInitialize(). A table is defined where each entry +* contains configuration information for an QSPI device, including the base +* address for the device. +* +* RTOS Independence +* +* This driver is intended to be RTOS and processor independent. It works with +* physical addresses only. Any needs for dynamic memory management, threads or +* thread mutual exclusion, virtual memory, or cache control must be satisfied +* by the layer above this driver. +* +* NOTE: This driver was always tested with endianess set to little-endian. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- -----------------------------------------------
+* 1.00a sdm 11/25/10 First release, based on the PS SPI driver...
+* 1.01a sdm 11/22/11 Added TCL file for generating QSPI parameters
+*		     in xparameters.h
+* 2.00a kka 07/25/12 Added a few register defines for CR 670297
+* 		     Removed code related to mode fault for CR 671468
+*		     The XQspiPs_SetSlaveSelect has been modified to remove
+*		     the argument of the slave select as the QSPI controller
+*		     only supports one slave.
+* 		     XQspiPs_GetSlaveSelect API has been removed
+* 		     Added a flag ShiftReadData to the instance structure
+*.		     and is used in the XQspiPs_GetReadData API.
+*		     The ShiftReadData Flag indicates whether the data
+*		     read from the Rx FIFO needs to be shifted
+*		     in cases where the data is less than 4  bytes
+* 		     Removed the selection for the following options:
+*		     Master mode (XQSPIPS_MASTER_OPTION) and
+*		     Flash interface mode (XQSPIPS_FLASH_MODE_OPTION) option
+*		     as the QSPI driver supports the Master mode
+*		     and Flash Interface mode and doesnot support
+*		     Slave mode or the legacy mode.
+*		     Modified the XQspiPs_PolledTransfer and XQspiPs_Transfer
+*		     APIs so that the last argument (IsInst) specifying whether
+*		     it is instruction or data has been removed. The first byte
+*		     in the SendBufPtr argument of these APIs specify the
+*		     instruction to be sent to the Flash Device.
+*		     This version of the driver fixes CRs 670197/663787/
+*		     670297/671468.
+* 		     Added the option for setting the Holdb_dr bit in the
+*		     configuration options, XQSPIPS_HOLD_B_DRIVE_OPTION
+*		     is the option to be used for setting this bit in the
+*		     configuration register.
+*		     The XQspiPs_PolledTransfer function has been updated
+*		     to fill the data to fifo depth.
+* 2.01a sg  02/03/13 Added flash opcodes for DUAL_IO_READ,QUAD_IO_READ.
+*		     Added macros for Set/Get Rx Watermark. Changed QSPI
+*		     Enable/Disable macro argument from BaseAddress to
+*		     Instance Pointer. Added DelayNss argument to SetDelays
+*		     and GetDelays API's.
+*		     Created macros XQspiPs_IsManualStart and
+*		     XQspiPs_IsManualChipSelect.
+*		     Changed QSPI transfer logic for polled and interrupt
+*		     modes to be based on filled tx fifo count and receive
+*		     based on it. RXNEMPTY interrupt is not used.
+*		     Added assertions to XQspiPs_LqspiRead function.
+*		     SetDelays and GetDelays API's include DelayNss parameter.
+*		     Added defines for DelayNss,Rx Watermark,Interrupts
+*		     which need write to clear. Removed Read zeros mask from
+*		     LQSPI Config register. Renamed Fixed burst error to
+*		     data FSM error in  LQSPI Status register.
+*
+* 2.02a hk  05/07/13 Added ConnectionMode to config structure.
+*			 Corresponds to C_QSPI_MODE - 0:Single, 1:Stacked, 2:Parallel
+*			 Added enable and disable to the XQspiPs_LqspiRead() function
+*			 Removed XQspi_Reset() in Set_Options() function when
+*			 LQSPI_MODE_OPTION is set.
+*            Added instructions for bank selection, die erase and
+*            flag status register to the flash instruction table
+*            Handling for instructions not in flash instruction
+*			 table added. Checking for Tx FIFO empty when switching from
+*			 TXD1/2/3 to TXD0 added. If WRSR instruction is sent with
+*            byte count 3 (spansion), instruction size and TXD register
+*			 changed accordingly. CR# 712502 and 703869.
+*            Added prefix to constant definitions for ConnectionMode
+*            Added (#ifdef linear base address) in the Linear read function.
+*            Changed  XPAR_XQSPIPS_0_LINEAR_BASEADDR to
+*            XPAR_PS7_QSPI_LINEAR_0_S_AXI_BASEADDR in
+*            XQspiPs_LqspiRead function. Fix for CR#718141.
+*
+* 2.03a hk  09/17/13 Modified polled and interrupt transfers to make use of
+*                    thresholds. This is to improve performance.
+*                    Added API's for QSPI reset and
+*                    linear mode initialization for boot.
+*                    Added RX and TX threshold reset to one in XQspiPs_Abort.
+*                    Added RX threshold reset(1) after transfer in polled and
+*                    interrupt transfers. Made changes to make sure threshold
+*                    change is done only when no transfer is in progress.
+*                    Updated linear init API for parallel and stacked modes.
+*                    CR#737760.
+* 3.1   hk  08/13/14 When writing to the configuration register, set/reset
+*                    required bits leaving reserved bits untouched. CR# 796813.
+* 3.2	sk	02/05/15 Add SLCR reset in abort function as a workaround because
+* 					 controller does not update FIFO status flags as expected
+* 					 when thresholds are used.
+* 3.3   sk  11/07/15 Modified the API prototypes according to MISRAC standards
+*                    to remove compilation warnings. CR# 868893.
+*       ms  03/17/17 Added readme.txt file in examples folder for doxygen
+*                    generation.
+*       ms  04/05/17 Modified Comment lines in functions of qspips
+*                    examples to recognize it as documentation block
+*                    and modified filename tag in
+*                    xqspips_dual_flash_stack_lqspi_example.c to include it in
+*                    doxygen examples.
+* 3.4   nsk 31/07/17 Added QSPI_BUS_WIDTH parameter in xparameters.h file
+* 3.5	tjs 08/21/18 Fixed compilation warnings for the ARMCC.
+* 3.5	tjs 07/16/18 Added support for low density ISSI flash parts.
+* 3.6   akm 03/28/19 Fixed memory leak issue while reading from qspi.(CR#1016357)
+* 3.6   akm 04/15/19 Modified FlashQuadEnable, FlashWrie and FlashErase APIs,
+*                    to wait for the on going operation to complete before
+*                    performing the next operation.
+* 3.6   akm 04/15/19 Modified the mask in XQspiPs_GetReadData() API to retrieve
+*                    configuration register values of both the Flashes in dual
+*                    parellel connection.
+*
+* 
+* +******************************************************************************/ +#ifndef XQSPIPS_H /* prevent circular inclusions */ +#define XQSPIPS_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xstatus.h" +#include "xqspips_hw.h" +#include + +/************************** Constant Definitions *****************************/ + +/** @name Configuration options + * + * The following options are supported to enable/disable certain features of + * an QSPI device. Each of the options is a bit mask, so more than one may be + * specified. + * + * + * The Active Low Clock option configures the device's clock polarity. + * Setting this option means the clock is active low and the SCK signal idles + * high. By default, the clock is active high and SCK idles low. + * + * The Clock Phase option configures the QSPI device for one of two + * transfer formats. A clock phase of 0, the default, means data is valid on + * the first SCK edge (rising or falling) after the slave select (SS) signal + * has been asserted. A clock phase of 1 means data is valid on the second SCK + * edge (rising or falling) after SS has been asserted. + * + * + * The QSPI Force Slave Select option is used to enable manual control of + * the slave select signal. + * 0: The SPI_SS signal is controlled by the QSPI controller during + * transfers. (Default) + * 1: The SPI_SS signal is forced active (driven low) regardless of any + * transfers in progress. + * + * NOTE: The driver will handle setting and clearing the Slave Select when + * the user sets the "FORCE_SSELECT_OPTION". Using this option will allow the + * QSPI clock to be set to a faster speed. If the QSPI clock is too fast, the + * processor cannot empty and refill the FIFOs before the TX FIFO is empty + * When the QSPI hardware is controlling the Slave Select signals, this + * will cause slave to be de-selected and terminate the transfer. + * + * The Manual Start option is used to enable manual control of + * the Start command to perform data transfer. + * 0: The Start command is controlled by the QSPI controller during + * transfers(Default). Data transmission starts as soon as there is data in + * the TXFIFO and stalls when the TXFIFO is empty + * 1: The Start command must be issued by software to perform data transfer. + * Bit 15 of Configuration register is used to issue Start command. This bit + * must be set whenever TXFIFO is filled with new data. + * + * NOTE: The driver will set the Manual Start Enable bit in Configuration + * Register, if Manual Start option is selected. Software will issue + * Manual Start command whenever TXFIFO is filled with data. When there is + * no further data, driver will clear the Manual Start Enable bit. + * + * @{ + */ +#define XQSPIPS_CLK_ACTIVE_LOW_OPTION 0x2 /**< Active Low Clock option */ +#define XQSPIPS_CLK_PHASE_1_OPTION 0x4 /**< Clock Phase one option */ +#define XQSPIPS_FORCE_SSELECT_OPTION 0x10 /**< Force Slave Select */ +#define XQSPIPS_MANUAL_START_OPTION 0x20 /**< Manual Start enable */ +#define XQSPIPS_LQSPI_MODE_OPTION 0x80 /**< Linear QPSI mode */ +#define XQSPIPS_HOLD_B_DRIVE_OPTION 0x100 /**< Drive HOLD_B Pin */ +/*@}*/ + + +/** @name QSPI Clock Prescaler options + * The QSPI Clock Prescaler Configuration bits are used to program master mode + * bit rate. The bit rate can be programmed in divide-by-two decrements from + * pclk/2 to pclk/256. + * + * @{ + */ +#define XQSPIPS_CLK_PRESCALE_2 0x00 /**< PCLK/2 Prescaler */ +#define XQSPIPS_CLK_PRESCALE_4 0x01 /**< PCLK/4 Prescaler */ +#define XQSPIPS_CLK_PRESCALE_8 0x02 /**< PCLK/8 Prescaler */ +#define XQSPIPS_CLK_PRESCALE_16 0x03 /**< PCLK/16 Prescaler */ +#define XQSPIPS_CLK_PRESCALE_32 0x04 /**< PCLK/32 Prescaler */ +#define XQSPIPS_CLK_PRESCALE_64 0x05 /**< PCLK/64 Prescaler */ +#define XQSPIPS_CLK_PRESCALE_128 0x06 /**< PCLK/128 Prescaler */ +#define XQSPIPS_CLK_PRESCALE_256 0x07 /**< PCLK/256 Prescaler */ + +/*@}*/ + + +/** @name Callback events + * + * These constants specify the handler events that are passed to + * a handler from the driver. These constants are not bit masks such that + * only one will be passed at a time to the handler. + * + * @{ + */ +#define XQSPIPS_EVENT_TRANSFER_DONE 2 /**< Transfer done */ +#define XQSPIPS_EVENT_TRANSMIT_UNDERRUN 3 /**< TX FIFO empty */ +#define XQSPIPS_EVENT_RECEIVE_OVERRUN 4 /**< Receive data loss because + * RX FIFO full + */ +/*@}*/ + +/** @name Flash commands + * + * The following constants define most of the commands supported by flash + * devices. Users can add more commands supported by the flash devices + * + * @{ + */ +#define XQSPIPS_FLASH_OPCODE_WRSR 0x01 /* Write status register */ +#define XQSPIPS_FLASH_OPCODE_PP 0x02 /* Page program */ +#define XQSPIPS_FLASH_OPCODE_NORM_READ 0x03 /* Normal read data bytes */ +#define XQSPIPS_FLASH_OPCODE_WRDS 0x04 /* Write disable */ +#define XQSPIPS_FLASH_OPCODE_RDSR1 0x05 /* Read status register 1 */ +#define XQSPIPS_FLASH_OPCODE_WREN 0x06 /* Write enable */ +#define XQSPIPS_FLASH_OPCODE_FAST_READ 0x0B /* Fast read data bytes */ +#define XQSPIPS_FLASH_OPCODE_BE_4K 0x20 /* Erase 4KiB block */ +#define XQSPIPS_FLASH_OPCODE_RDSR2 0x35 /* Read status register 2 */ +#define XQSPIPS_FLASH_OPCODE_DUAL_READ 0x3B /* Dual read data bytes */ +#define XQSPIPS_FLASH_OPCODE_BE_32K 0x52 /* Erase 32KiB block */ +#define XQSPIPS_FLASH_OPCODE_QUAD_READ 0x6B /* Quad read data bytes */ +#define XQSPIPS_FLASH_OPCODE_ERASE_SUS 0x75 /* Erase suspend */ +#define XQSPIPS_FLASH_OPCODE_ERASE_RES 0x7A /* Erase resume */ +#define XQSPIPS_FLASH_OPCODE_RDID 0x9F /* Read JEDEC ID */ +#define XQSPIPS_FLASH_OPCODE_BE 0xC7 /* Erase whole flash block */ +#define XQSPIPS_FLASH_OPCODE_SE 0xD8 /* Sector erase (usually 64KB)*/ +#define XQSPIPS_FLASH_OPCODE_DUAL_IO_READ 0xBB /* Read data using Dual I/O */ +#define XQSPIPS_FLASH_OPCODE_QUAD_IO_READ 0xEB /* Read data using Quad I/O */ +#define XQSPIPS_FLASH_OPCODE_BRWR 0x17 /* Bank Register Write */ +#define XQSPIPS_FLASH_OPCODE_BRRD 0x16 /* Bank Register Read */ +/* Extende Address Register Write - Micron's equivalent of Bank Register */ +#define XQSPIPS_FLASH_OPCODE_EARWR 0xC5 +/* Extende Address Register Read - Micron's equivalent of Bank Register */ +#define XQSPIPS_FLASH_OPCODE_EARRD 0xC8 +#define XQSPIPS_FLASH_OPCODE_DIE_ERASE 0xC4 +#define XQSPIPS_FLASH_OPCODE_READ_FLAG_SR 0x70 +#define XQSPIPS_FLASH_OPCODE_CLEAR_FLAG_SR 0x50 +#define XQSPIPS_FLASH_OPCODE_READ_LOCK_REG 0xE8 /* Lock Reg Read */ +#define XQSPIPS_FLASH_OPCODE_WRITE_LOCK_REG 0xE5 /* Lock Reg Write */ + +/*@}*/ + +/** @name Instruction size + * + * The following constants define numbers 1 to 4. + * Used to identify whether TXD0,1,2 or 3 is to be used. + * + * @{ + */ +#define XQSPIPS_SIZE_ONE 1 +#define XQSPIPS_SIZE_TWO 2 +#define XQSPIPS_SIZE_THREE 3 +#define XQSPIPS_SIZE_FOUR 4 + +/*@}*/ + +/** @name ConnectionMode + * + * The following constants are the possible values of ConnectionMode in + * Config structure. + * + * @{ + */ +#define XQSPIPS_CONNECTION_MODE_SINGLE 0 +#define XQSPIPS_CONNECTION_MODE_STACKED 1 +#define XQSPIPS_CONNECTION_MODE_PARALLEL 2 + +/*@}*/ + +/** @name FIFO threshold value + * + * This is the Rx FIFO threshold (in words) that was found to be most + * optimal in terms of performance + * + * @{ + */ +#define XQSPIPS_RXFIFO_THRESHOLD_OPT 32 + +/*@}*/ + +/**************************** Type Definitions *******************************/ +/** + * The handler data type allows the user to define a callback function to + * handle the asynchronous processing for the QSPI device. The application + * using this driver is expected to define a handler of this type to support + * interrupt driven mode. The handler executes in an interrupt context, so + * only minimal processing should be performed. + * + * @param CallBackRef is the callback reference passed in by the upper + * layer when setting the callback functions, and passed back to + * the upper layer when the callback is invoked. Its type is + * not important to the driver, so it is a void pointer. + * @param StatusEvent holds one or more status events that have occurred. + * See the XQspiPs_SetStatusHandler() for details on the status + * events that can be passed in the callback. + * @param ByteCount indicates how many bytes of data were successfully + * transferred. This may be less than the number of bytes + * requested if the status event indicates an error. + */ +typedef void (*XQspiPs_StatusHandler) (void *CallBackRef, u32 StatusEvent, + unsigned ByteCount); + +/** + * This typedef contains configuration information for the device. + */ +typedef struct { + u16 DeviceId; /**< Unique ID of device */ + u32 BaseAddress; /**< Base address of the device */ + u32 InputClockHz; /**< Input clock frequency */ + u8 ConnectionMode; /**< Single, Stacked and Parallel mode */ +} XQspiPs_Config; + +/** + * The XQspiPs driver instance data. The user is required to allocate a + * variable of this type for every QSPI device in the system. A pointer + * to a variable of this type is then passed to the driver API functions. + */ +typedef struct { + XQspiPs_Config Config; /**< Configuration structure */ + u32 IsReady; /**< Device is initialized and ready */ + + u8 *SendBufferPtr; /**< Buffer to send (state) */ + u8 *RecvBufferPtr; /**< Buffer to receive (state) */ + int RequestedBytes; /**< Number of bytes to transfer (state) */ + int RemainingBytes; /**< Number of bytes left to transfer(state) */ + u32 IsBusy; /**< A transfer is in progress (state) */ + XQspiPs_StatusHandler StatusHandler; + void *StatusRef; /**< Callback reference for status handler */ + u32 ShiftReadData; /**< Flag to indicate whether the data + * read from the Rx FIFO needs to be shifted + * in cases where the data is less than 4 + * bytes + */ +} XQspiPs; + +/***************** Macros (Inline Functions) Definitions *********************/ + +/****************************************************************************/ +/* +* +* Check in OptionsTable if Manual Start Option is enabled or disabled. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* +* @return +* - TRUE if option is set +* - FALSE if option is not set +* +* @note C-Style signature: +* u8 XQspiPs_IsManualStart(XQspiPs *InstancePtr); +* +*****************************************************************************/ +#define XQspiPs_IsManualStart(InstancePtr) \ + ((XQspiPs_GetOptions(InstancePtr) & \ + XQSPIPS_MANUAL_START_OPTION) ? TRUE : FALSE) + +/****************************************************************************/ +/* +* +* Check in OptionsTable if Manual Chip Select Option is enabled or disabled. +* +* @param InstancePtr is a pointer to the XSpiPs instance. +* +* @return +* - TRUE if option is set +* - FALSE if option is not set +* +* @note C-Style signature: +* u8 XQspiPs_IsManualChipSelect(XQspiPs *InstancePtr); +* +*****************************************************************************/ +#define XQspiPs_IsManualChipSelect(InstancePtr) \ + ((XQspiPs_GetOptions(InstancePtr) & \ + XQSPIPS_FORCE_SSELECT_OPTION) ? TRUE : FALSE) + +/****************************************************************************/ +/** +* +* Set the contents of the slave idle count register. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* @param RegisterValue is the value to be written, valid values are +* 0-255. +* +* @return None +* +* @note C-Style signature: +* void XQspiPs_SetSlaveIdle(XQspiPs *InstancePtr, +* u32 RegisterValue) +* +*****************************************************************************/ +#define XQspiPs_SetSlaveIdle(InstancePtr, RegisterValue) \ + XQspiPs_Out32(((InstancePtr)->Config.BaseAddress) + \ + XQSPIPS_SICR_OFFSET, (RegisterValue)) + +/****************************************************************************/ +/** +* +* Get the contents of the slave idle count register. Use the XQSPIPS_SICR_* +* constants defined in xqspips_hw.h to interpret the bit-mask returned. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* +* @return An 8-bit value representing Slave Idle Count. +* +* @note C-Style signature: +* u32 XQspiPs_GetSlaveIdle(XQspiPs *InstancePtr) +* +*****************************************************************************/ +#define XQspiPs_GetSlaveIdle(InstancePtr) \ + XQspiPs_In32(((InstancePtr)->Config.BaseAddress) + \ + XQSPIPS_SICR_OFFSET) + +/****************************************************************************/ +/** +* +* Set the contents of the transmit FIFO watermark register. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* @param RegisterValue is the value to be written, valid values are 1-63. +* +* @return None. +* +* @note C-Style signature: +* void XQspiPs_SetTXWatermark(XQspiPs *InstancePtr, +* u32 RegisterValue) +* +*****************************************************************************/ +#define XQspiPs_SetTXWatermark(InstancePtr, RegisterValue) \ + XQspiPs_Out32(((InstancePtr)->Config.BaseAddress) + \ + XQSPIPS_TXWR_OFFSET, (RegisterValue)) + +/****************************************************************************/ +/** +* +* Get the contents of the transmit FIFO watermark register. +* Valid values are in the range 1-63. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* +* @return A 6-bit value representing Tx Watermark level. +* +* @note C-Style signature: +* u32 XQspiPs_GetTXWatermark(XQspiPs *InstancePtr) +* +*****************************************************************************/ +#define XQspiPs_GetTXWatermark(InstancePtr) \ + XQspiPs_In32((InstancePtr->Config.BaseAddress) + XQSPIPS_TXWR_OFFSET) + +/****************************************************************************/ +/** +* +* Set the contents of the receive FIFO watermark register. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* @param RegisterValue is the value to be written, valid values are 1-63. +* +* @return None. +* +* @note C-Style signature: +* void XQspiPs_SetRXWatermark(XQspiPs *InstancePtr, +* u32 RegisterValue) +* +*****************************************************************************/ +#define XQspiPs_SetRXWatermark(InstancePtr, RegisterValue) \ + XQspiPs_Out32(((InstancePtr)->Config.BaseAddress) + \ + XQSPIPS_RXWR_OFFSET, (RegisterValue)) + +/****************************************************************************/ +/** +* +* Get the contents of the receive FIFO watermark register. +* Valid values are in the range 1-63. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* +* @return A 6-bit value representing Rx Watermark level. +* +* @note C-Style signature: +* u32 XQspiPs_GetRXWatermark(XQspiPs *InstancePtr) +* +*****************************************************************************/ +#define XQspiPs_GetRXWatermark(InstancePtr) \ + XQspiPs_In32((InstancePtr->Config.BaseAddress) + XQSPIPS_RXWR_OFFSET) + +/****************************************************************************/ +/** +* +* Enable the device and uninhibit master transactions. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* +* @return None. +* +* @note C-Style signature: +* void XQspiPs_Enable(XQspiPs *InstancePtr) +* +*****************************************************************************/ +#define XQspiPs_Enable(InstancePtr) \ + XQspiPs_Out32((InstancePtr->Config.BaseAddress) + XQSPIPS_ER_OFFSET, \ + XQSPIPS_ER_ENABLE_MASK) + +/****************************************************************************/ +/** +* +* Disable the device. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* +* @return None. +* +* @note C-Style signature: +* void XQspiPs_Disable(XQspiPs *InstancePtr) +* +*****************************************************************************/ +#define XQspiPs_Disable(InstancePtr) \ + XQspiPs_Out32((InstancePtr->Config.BaseAddress) + XQSPIPS_ER_OFFSET, 0) + +/****************************************************************************/ +/** +* +* Set the contents of the Linear QSPI Configuration register. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* @param RegisterValue is the value to be written to the Linear QSPI +* configuration register. +* +* @return None. +* +* @note C-Style signature: +* void XQspiPs_SetLqspiConfigReg(XQspiPs *InstancePtr, +* u32 RegisterValue) +* +*****************************************************************************/ +#define XQspiPs_SetLqspiConfigReg(InstancePtr, RegisterValue) \ + XQspiPs_Out32(((InstancePtr)->Config.BaseAddress) + \ + XQSPIPS_LQSPI_CR_OFFSET, (RegisterValue)) + +/****************************************************************************/ +/** +* +* Get the contents of the Linear QSPI Configuration register. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* +* @return A 32-bit value representing the contents of the LQSPI Config +* register. +* +* @note C-Style signature: +* u32 XQspiPs_GetLqspiConfigReg(u32 *InstancePtr) +* +*****************************************************************************/ +#define XQspiPs_GetLqspiConfigReg(InstancePtr) \ + XQspiPs_In32((InstancePtr->Config.BaseAddress) + \ + XQSPIPS_LQSPI_CR_OFFSET) + +/************************** Function Prototypes ******************************/ + +/* + * Initialization function, implemented in xqspips_sinit.c + */ +XQspiPs_Config *XQspiPs_LookupConfig(u16 DeviceId); + +/* + * Functions implemented in xqspips.c + */ +int XQspiPs_CfgInitialize(XQspiPs *InstancePtr, XQspiPs_Config *Config, + u32 EffectiveAddr); +void XQspiPs_Reset(XQspiPs *InstancePtr); +void XQspiPs_Abort(XQspiPs *InstancePtr); + +s32 XQspiPs_Transfer(XQspiPs *InstancePtr, u8 *SendBufPtr, u8 *RecvBufPtr, + u32 ByteCount); +s32 XQspiPs_PolledTransfer(XQspiPs *InstancePtr, u8 *SendBufPtr, + u8 *RecvBufPtr, u32 ByteCount); +int XQspiPs_LqspiRead(XQspiPs *InstancePtr, u8 *RecvBufPtr, + u32 Address, unsigned ByteCount); + +int XQspiPs_SetSlaveSelect(XQspiPs *InstancePtr); + +void XQspiPs_SetStatusHandler(XQspiPs *InstancePtr, void *CallBackRef, + XQspiPs_StatusHandler FuncPtr); +void XQspiPs_InterruptHandler(void *InstancePtr); + +/* + * Functions for selftest, in xqspips_selftest.c + */ +int XQspiPs_SelfTest(XQspiPs *InstancePtr); + +/* + * Functions for options, in xqspips_options.c + */ +s32 XQspiPs_SetOptions(XQspiPs *InstancePtr, u32 Options); +u32 XQspiPs_GetOptions(XQspiPs *InstancePtr); + +s32 XQspiPs_SetClkPrescaler(XQspiPs *InstancePtr, u8 Prescaler); +u8 XQspiPs_GetClkPrescaler(XQspiPs *InstancePtr); + +int XQspiPs_SetDelays(XQspiPs *InstancePtr, u8 DelayNss, u8 DelayBtwn, + u8 DelayAfter, u8 DelayInit); +void XQspiPs_GetDelays(XQspiPs *InstancePtr, u8 *DelayNss, u8 *DelayBtwn, + u8 *DelayAfter, u8 *DelayInit); +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/include/xqspips_hw.h b/datalink814_ge/bsp/ps7_cortexa9_0/include/xqspips_hw.h new file mode 100644 index 0000000..88c232e --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/include/xqspips_hw.h @@ -0,0 +1,421 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xqspips_hw.h +* @addtogroup qspips_v3_6 +* @{ +* +* This header file contains the identifiers and basic HW access driver +* functions (or macros) that can be used to access the device. Other driver +* functions are defined in xqspips.h. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- -----------------------------------------------
+* 1.00  sdm 11/25/10 First release
+* 2.00a ka  07/25/12 Added a few register defines for CR 670297
+*		     and removed some defines of reserved fields for
+*		     CR 671468
+*		     Added define XQSPIPS_CR_HOLD_B_MASK for Holdb_dr
+*		     bit in Configuration register.
+* 2.01a sg  02/03/13 Added defines for DelayNss,Rx Watermark,Interrupts
+*		     which need write to clear. Removed Read zeros mask from
+*		     LQSPI Config register.
+* 2.03a hk  08/22/13 Added prototypes of API's for QSPI reset and
+*                    linear mode initialization for boot. Added related
+*                    constant definitions.
+* 3.1   hk  08/13/14 Changed definition of CR reset value masks to set/reset
+*                    required bits leaving reserved bits untouched. CR# 796813.
+* 3.2	sk	02/05/15 Add SLCR reset in abort function as a workaround because
+* 					 controller does not update FIFO status flags as expected
+* 					 when thresholds are used.
+* 3.6   akm 03/28/19 Fixed memory leak issue while reading from qspi.(CR#1016357)
+*
+* 
+* +******************************************************************************/ +#ifndef XQSPIPS_HW_H /* prevent circular inclusions */ +#define XQSPIPS_HW_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_io.h" +#include "xparameters.h" + +/************************** Constant Definitions *****************************/ + +/** @name Register Map + * + * Register offsets from the base address of an QSPI device. + * @{ + */ +#define XQSPIPS_CR_OFFSET 0x00 /**< Configuration Register */ +#define XQSPIPS_SR_OFFSET 0x04 /**< Interrupt Status */ +#define XQSPIPS_IER_OFFSET 0x08 /**< Interrupt Enable */ +#define XQSPIPS_IDR_OFFSET 0x0c /**< Interrupt Disable */ +#define XQSPIPS_IMR_OFFSET 0x10 /**< Interrupt Enabled Mask */ +#define XQSPIPS_ER_OFFSET 0x14 /**< Enable/Disable Register */ +#define XQSPIPS_DR_OFFSET 0x18 /**< Delay Register */ +#define XQSPIPS_TXD_00_OFFSET 0x1C /**< Transmit 4-byte inst/data */ +#define XQSPIPS_RXD_OFFSET 0x20 /**< Data Receive Register */ +#define XQSPIPS_SICR_OFFSET 0x24 /**< Slave Idle Count */ +#define XQSPIPS_TXWR_OFFSET 0x28 /**< Transmit FIFO Watermark */ +#define XQSPIPS_RXWR_OFFSET 0x2C /**< Receive FIFO Watermark */ +#define XQSPIPS_GPIO_OFFSET 0x30 /**< GPIO Register */ +#define XQSPIPS_LPBK_DLY_ADJ_OFFSET 0x38 /**< Loopback Delay Adjust Reg */ +#define XQSPIPS_TXD_01_OFFSET 0x80 /**< Transmit 1-byte inst */ +#define XQSPIPS_TXD_10_OFFSET 0x84 /**< Transmit 2-byte inst */ +#define XQSPIPS_TXD_11_OFFSET 0x88 /**< Transmit 3-byte inst */ +#define XQSPIPS_LQSPI_CR_OFFSET 0xA0 /**< Linear QSPI config register */ +#define XQSPIPS_LQSPI_SR_OFFSET 0xA4 /**< Linear QSPI status register */ +#define XQSPIPS_MOD_ID_OFFSET 0xFC /**< Module ID register */ + +/* @} */ + +/** @name Configuration Register + * + * This register contains various control bits that + * affect the operation of the QSPI device. Read/Write. + * @{ + */ + +#define XQSPIPS_CR_IFMODE_MASK 0x80000000 /**< Flash mem interface mode */ +#define XQSPIPS_CR_ENDIAN_MASK 0x04000000 /**< Tx/Rx FIFO endianness */ +#define XQSPIPS_CR_MANSTRT_MASK 0x00010000 /**< Manual Transmission Start */ +#define XQSPIPS_CR_MANSTRTEN_MASK 0x00008000 /**< Manual Transmission Start + Enable */ +#define XQSPIPS_CR_SSFORCE_MASK 0x00004000 /**< Force Slave Select */ +#define XQSPIPS_CR_SSCTRL_MASK 0x00000400 /**< Slave Select Decode */ +#define XQSPIPS_CR_SSCTRL_SHIFT 10 /**< Slave Select Decode shift */ +#define XQSPIPS_CR_DATA_SZ_MASK 0x000000C0 /**< Size of word to be + transferred */ +#define XQSPIPS_CR_PRESC_MASK 0x00000038 /**< Prescaler Setting */ +#define XQSPIPS_CR_PRESC_SHIFT 3 /**< Prescaler shift */ +#define XQSPIPS_CR_PRESC_MAXIMUM 0x07 /**< Prescaler maximum value */ + +#define XQSPIPS_CR_CPHA_MASK 0x00000004 /**< Phase Configuration */ +#define XQSPIPS_CR_CPOL_MASK 0x00000002 /**< Polarity Configuration */ + +#define XQSPIPS_CR_MSTREN_MASK 0x00000001 /**< Master Mode Enable */ + +#define XQSPIPS_CR_HOLD_B_MASK 0x00080000 /**< HOLD_B Pin Drive Enable */ + +#define XQSPIPS_CR_REF_CLK_MASK 0x00000100 /**< Ref clk bit - should be 0 */ + +/* Deselect the Slave select line and set the transfer size to 32 at reset */ +#define XQSPIPS_CR_RESET_MASK_SET XQSPIPS_CR_IFMODE_MASK | \ + XQSPIPS_CR_SSCTRL_MASK | \ + XQSPIPS_CR_DATA_SZ_MASK | \ + XQSPIPS_CR_MSTREN_MASK | \ + XQSPIPS_CR_SSFORCE_MASK | \ + XQSPIPS_CR_HOLD_B_MASK +#define XQSPIPS_CR_RESET_MASK_CLR XQSPIPS_CR_CPOL_MASK | \ + XQSPIPS_CR_CPHA_MASK | \ + XQSPIPS_CR_PRESC_MASK | \ + XQSPIPS_CR_MANSTRTEN_MASK | \ + XQSPIPS_CR_MANSTRT_MASK | \ + XQSPIPS_CR_ENDIAN_MASK | \ + XQSPIPS_CR_REF_CLK_MASK +/* @} */ + + +/** @name QSPI Interrupt Registers + * + * QSPI Status Register + * + * This register holds the interrupt status flags for an QSPI device. Some + * of the flags are level triggered, which means that they are set as long + * as the interrupt condition exists. Other flags are edge triggered, + * which means they are set once the interrupt condition occurs and remain + * set until they are cleared by software. The interrupts are cleared by + * writing a '1' to the interrupt bit position in the Status Register. + * Read/Write. + * + * QSPI Interrupt Enable Register + * + * This register is used to enable chosen interrupts for an QSPI device. + * Writing a '1' to a bit in this register sets the corresponding bit in the + * QSPI Interrupt Mask register. Write only. + * + * QSPI Interrupt Disable Register + * + * This register is used to disable chosen interrupts for an QSPI device. + * Writing a '1' to a bit in this register clears the corresponding bit in the + * QSPI Interrupt Mask register. Write only. + * + * QSPI Interrupt Mask Register + * + * This register shows the enabled/disabled interrupts of an QSPI device. + * Read only. + * + * All four registers have the same bit definitions. They are only defined once + * for each of the Interrupt Enable Register, Interrupt Disable Register, + * Interrupt Mask Register, and Channel Interrupt Status Register + * @{ + */ + +#define XQSPIPS_IXR_TXUF_MASK 0x00000040 /**< QSPI Tx FIFO Underflow */ +#define XQSPIPS_IXR_RXFULL_MASK 0x00000020 /**< QSPI Rx FIFO Full */ +#define XQSPIPS_IXR_RXNEMPTY_MASK 0x00000010 /**< QSPI Rx FIFO Not Empty */ +#define XQSPIPS_IXR_TXFULL_MASK 0x00000008 /**< QSPI Tx FIFO Full */ +#define XQSPIPS_IXR_TXOW_MASK 0x00000004 /**< QSPI Tx FIFO Overwater */ +#define XQSPIPS_IXR_RXOVR_MASK 0x00000001 /**< QSPI Rx FIFO Overrun */ +#define XQSPIPS_IXR_DFLT_MASK 0x00000025 /**< QSPI default interrupts + mask */ +#define XQSPIPS_IXR_WR_TO_CLR_MASK 0x00000041 /**< Interrupts which + need write to clear */ +#define XQSPIPS_ISR_RESET_STATE 0x00000004 /**< Default to tx/rx empty */ +#define XQSPIPS_IXR_DISABLE_ALL 0x0000007D /**< Disable all interrupts */ +/* @} */ + + +/** @name Enable Register + * + * This register is used to enable or disable an QSPI device. + * Read/Write + * @{ + */ +#define XQSPIPS_ER_ENABLE_MASK 0x00000001 /**< QSPI Enable Bit Mask */ +/* @} */ + + +/** @name Delay Register + * + * This register is used to program timing delays in + * slave mode. Read/Write + * @{ + */ +#define XQSPIPS_DR_NSS_MASK 0xFF000000 /**< Delay to de-assert slave select + between two words mask */ +#define XQSPIPS_DR_NSS_SHIFT 24 /**< Delay to de-assert slave select + between two words shift */ +#define XQSPIPS_DR_BTWN_MASK 0x00FF0000 /**< Delay Between Transfers + mask */ +#define XQSPIPS_DR_BTWN_SHIFT 16 /**< Delay Between Transfers shift */ +#define XQSPIPS_DR_AFTER_MASK 0x0000FF00 /**< Delay After Transfers mask */ +#define XQSPIPS_DR_AFTER_SHIFT 8 /**< Delay After Transfers shift */ +#define XQSPIPS_DR_INIT_MASK 0x000000FF /**< Delay Initially mask */ +/* @} */ + +/** @name Slave Idle Count Registers + * + * This register defines the number of pclk cycles the slave waits for a the + * QSPI clock to become stable in quiescent state before it can detect the start + * of the next transfer in CPHA = 1 mode. + * Read/Write + * + * @{ + */ +#define XQSPIPS_SICR_MASK 0x000000FF /**< Slave Idle Count Mask */ +/* @} */ + + +/** @name Transmit FIFO Watermark Register + * + * This register defines the watermark setting for the Transmit FIFO. + * + * @{ + */ +#define XQSPIPS_TXWR_MASK 0x0000003F /**< Transmit Watermark Mask */ +#define XQSPIPS_TXWR_RESET_VALUE 0x00000001 /**< Transmit Watermark + * register reset value */ + +/* @} */ + +/** @name Receive FIFO Watermark Register + * + * This register defines the watermark setting for the Receive FIFO. + * + * @{ + */ +#define XQSPIPS_RXWR_MASK 0x0000003F /**< Receive Watermark Mask */ +#define XQSPIPS_RXWR_RESET_VALUE 0x00000001 /**< Receive Watermark + * register reset value */ + +/* @} */ + +/** @name FIFO Depth + * + * This macro provides the depth of transmit FIFO and receive FIFO. + * + * @{ + */ +#define XQSPIPS_FIFO_DEPTH 63 /**< FIFO depth (words) */ +/* @} */ + + +/** @name Linear QSPI Configuration Register + * + * This register contains various control bits that + * affect the operation of the Linear QSPI controller. Read/Write. + * + * @{ + */ +#define XQSPIPS_LQSPI_CR_LINEAR_MASK 0x80000000 /**< LQSPI mode enable */ +#define XQSPIPS_LQSPI_CR_TWO_MEM_MASK 0x40000000 /**< Both memories or one */ +#define XQSPIPS_LQSPI_CR_SEP_BUS_MASK 0x20000000 /**< Seperate memory bus */ +#define XQSPIPS_LQSPI_CR_U_PAGE_MASK 0x10000000 /**< Upper memory page */ +#define XQSPIPS_LQSPI_CR_MODE_EN_MASK 0x02000000 /**< Enable mode bits */ +#define XQSPIPS_LQSPI_CR_MODE_ON_MASK 0x01000000 /**< Mode on */ +#define XQSPIPS_LQSPI_CR_MODE_BITS_MASK 0x00FF0000 /**< Mode value for dual I/O + or quad I/O */ +#define XQSPIPS_LQSPI_CR_DUMMY_MASK 0x00000700 /**< Number of dummy bytes + between addr and return + read data */ +#define XQSPIPS_LQSPI_CR_INST_MASK 0x000000FF /**< Read instr code */ +#define XQSPIPS_LQSPI_CR_RST_STATE 0x8000016B /**< Default CR value */ +/* @} */ + +/** @name Linear QSPI Status Register + * + * This register contains various status bits of the Linear QSPI controller. + * Read/Write. + * + * @{ + */ +#define XQSPIPS_LQSPI_SR_D_FSM_ERR_MASK 0x00000004 /**< AXI Data FSM Error + received */ +#define XQSPIPS_LQSPI_SR_WR_RECVD_MASK 0x00000002 /**< AXI write command + received */ +/* @} */ + + +/** @name Loopback Delay Adjust Register + * + * This register contains various bit masks of Loopback Delay Adjust Register. + * + * @{ + */ + +#define XQSPIPS_LPBK_DLY_ADJ_USE_LPBK_MASK 0x00000020 /**< Loopback Bit */ + +/* @} */ + + +/** @name SLCR Register + * + * Register offsets from SLCR base address. + * + * @{ + */ + +#define SLCR_LOCK 0x00000004 /**< SLCR Write Protection Lock */ +#define SLCR_UNLOCK 0x00000008 /**< SLCR Write Protection Unlock */ +#define LQSPI_RST_CTRL 0x00000230 /**< Quad SPI Software Reset Control */ +#define SLCR_LOCKSTA 0x0000000C /**< SLCR Write Protection status */ + +/* @} */ + + +/** @name SLCR Register + * + * Bit Masks of above SLCR Registers . + * + * @{ + */ + +#ifndef XPAR_XSLCR_0_BASEADDR +#define XPAR_XSLCR_0_BASEADDR 0xF8000000 +#endif +#define SLCR_LOCK_MASK 0x767B /**< Write Protection Lock mask*/ +#define SLCR_UNLOCK_MASK 0xDF0D /**< SLCR Write Protection Unlock */ +#define LQSPI_RST_CTRL_MASK 0x3 /**< Quad SPI Software Reset Control */ + +/* @} */ + + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +#define XQspiPs_In32 Xil_In32 +#define XQspiPs_Out32 Xil_Out32 +#define XQSPIPS_DUMMY_TX_DATA 0xFFFFFFFF + +/****************************************************************************/ +/** +* Read a register. +* +* @param BaseAddress contains the base address of the device. +* @param RegOffset contains the offset from the 1st register of the +* device to the target register. +* +* @return The value read from the register. +* +* @note C-Style signature: +* u32 XQspiPs_ReadReg(u32 BaseAddress. int RegOffset) +* +******************************************************************************/ +#define XQspiPs_ReadReg(BaseAddress, RegOffset) \ + XQspiPs_In32((BaseAddress) + (RegOffset)) + +/***************************************************************************/ +/** +* Write to a register. +* +* @param BaseAddress contains the base address of the device. +* @param RegOffset contains the offset from the 1st register of the +* device to target register. +* @param RegisterValue is the value to be written to the register. +* +* @return None. +* +* @note C-Style signature: +* void XQspiPs_WriteReg(u32 BaseAddress, int RegOffset, +* u32 RegisterValue) +* +******************************************************************************/ +#define XQspiPs_WriteReg(BaseAddress, RegOffset, RegisterValue) \ + XQspiPs_Out32((BaseAddress) + (RegOffset), (RegisterValue)) + +/************************** Function Prototypes ******************************/ + +/* + * Functions implemented in xqspips_hw.c + */ +void XQspiPs_ResetHw(u32 BaseAddress); +void XQspiPs_LinearInit(u32 BaseAddress); + +/************************** Variable Definitions *****************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/include/xreg_cortexa9.h b/datalink814_ge/bsp/ps7_cortexa9_0/include/xreg_cortexa9.h new file mode 100644 index 0000000..ad93665 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/include/xreg_cortexa9.h @@ -0,0 +1,587 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xreg_cortexa9.h +* +* This header file contains definitions for using inline assembler code. It is +* written specifically for the GNU, ARMCC compiler. +* +* All of the ARM Cortex A9 GPRs, SPRs, and Debug Registers are defined along +* with the positions of the bits within the registers. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 1.00a ecm/sdm  10/20/09 First release
+* 
+* +******************************************************************************/ +#ifndef XREG_CORTEXA9_H +#define XREG_CORTEXA9_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* GPRs */ +#define XREG_GPR0 r0 +#define XREG_GPR1 r1 +#define XREG_GPR2 r2 +#define XREG_GPR3 r3 +#define XREG_GPR4 r4 +#define XREG_GPR5 r5 +#define XREG_GPR6 r6 +#define XREG_GPR7 r7 +#define XREG_GPR8 r8 +#define XREG_GPR9 r9 +#define XREG_GPR10 r10 +#define XREG_GPR11 r11 +#define XREG_GPR12 r12 +#define XREG_GPR13 r13 +#define XREG_GPR14 r14 +#define XREG_GPR15 r15 +#define XREG_CPSR cpsr + +/* Coprocessor number defines */ +#define XREG_CP0 0 +#define XREG_CP1 1 +#define XREG_CP2 2 +#define XREG_CP3 3 +#define XREG_CP4 4 +#define XREG_CP5 5 +#define XREG_CP6 6 +#define XREG_CP7 7 +#define XREG_CP8 8 +#define XREG_CP9 9 +#define XREG_CP10 10 +#define XREG_CP11 11 +#define XREG_CP12 12 +#define XREG_CP13 13 +#define XREG_CP14 14 +#define XREG_CP15 15 + +/* Coprocessor control register defines */ +#define XREG_CR0 cr0 +#define XREG_CR1 cr1 +#define XREG_CR2 cr2 +#define XREG_CR3 cr3 +#define XREG_CR4 cr4 +#define XREG_CR5 cr5 +#define XREG_CR6 cr6 +#define XREG_CR7 cr7 +#define XREG_CR8 cr8 +#define XREG_CR9 cr9 +#define XREG_CR10 cr10 +#define XREG_CR11 cr11 +#define XREG_CR12 cr12 +#define XREG_CR13 cr13 +#define XREG_CR14 cr14 +#define XREG_CR15 cr15 + +/* Current Processor Status Register (CPSR) Bits */ +#define XREG_CPSR_THUMB_MODE 0x20 +#define XREG_CPSR_MODE_BITS 0x1F +#define XREG_CPSR_SYSTEM_MODE 0x1F +#define XREG_CPSR_UNDEFINED_MODE 0x1B +#define XREG_CPSR_DATA_ABORT_MODE 0x17 +#define XREG_CPSR_SVC_MODE 0x13 +#define XREG_CPSR_IRQ_MODE 0x12 +#define XREG_CPSR_FIQ_MODE 0x11 +#define XREG_CPSR_USER_MODE 0x10 + +#define XREG_CPSR_IRQ_ENABLE 0x80 +#define XREG_CPSR_FIQ_ENABLE 0x40 + +#define XREG_CPSR_N_BIT 0x80000000 +#define XREG_CPSR_Z_BIT 0x40000000 +#define XREG_CPSR_C_BIT 0x20000000 +#define XREG_CPSR_V_BIT 0x10000000 + + +/* CP15 defines */ +#if defined (__GNUC__) || defined (__ICCARM__) +/* C0 Register defines */ +#define XREG_CP15_MAIN_ID "p15, 0, %0, c0, c0, 0" +#define XREG_CP15_CACHE_TYPE "p15, 0, %0, c0, c0, 1" +#define XREG_CP15_TCM_TYPE "p15, 0, %0, c0, c0, 2" +#define XREG_CP15_TLB_TYPE "p15, 0, %0, c0, c0, 3" +#define XREG_CP15_MULTI_PROC_AFFINITY "p15, 0, %0, c0, c0, 5" + +#define XREG_CP15_PROC_FEATURE_0 "p15, 0, %0, c0, c1, 0" +#define XREG_CP15_PROC_FEATURE_1 "p15, 0, %0, c0, c1, 1" +#define XREG_CP15_DEBUG_FEATURE_0 "p15, 0, %0, c0, c1, 2" +#define XREG_CP15_MEMORY_FEATURE_0 "p15, 0, %0, c0, c1, 4" +#define XREG_CP15_MEMORY_FEATURE_1 "p15, 0, %0, c0, c1, 5" +#define XREG_CP15_MEMORY_FEATURE_2 "p15, 0, %0, c0, c1, 6" +#define XREG_CP15_MEMORY_FEATURE_3 "p15, 0, %0, c0, c1, 7" + +#define XREG_CP15_INST_FEATURE_0 "p15, 0, %0, c0, c2, 0" +#define XREG_CP15_INST_FEATURE_1 "p15, 0, %0, c0, c2, 1" +#define XREG_CP15_INST_FEATURE_2 "p15, 0, %0, c0, c2, 2" +#define XREG_CP15_INST_FEATURE_3 "p15, 0, %0, c0, c2, 3" +#define XREG_CP15_INST_FEATURE_4 "p15, 0, %0, c0, c2, 4" + +#define XREG_CP15_CACHE_SIZE_ID "p15, 1, %0, c0, c0, 0" +#define XREG_CP15_CACHE_LEVEL_ID "p15, 1, %0, c0, c0, 1" +#define XREG_CP15_AUXILARY_ID "p15, 1, %0, c0, c0, 7" + +#define XREG_CP15_CACHE_SIZE_SEL "p15, 2, %0, c0, c0, 0" + +/* C1 Register Defines */ +#define XREG_CP15_SYS_CONTROL "p15, 0, %0, c1, c0, 0" +#define XREG_CP15_AUX_CONTROL "p15, 0, %0, c1, c0, 1" +#define XREG_CP15_CP_ACCESS_CONTROL "p15, 0, %0, c1, c0, 2" + +#define XREG_CP15_SECURE_CONFIG "p15, 0, %0, c1, c1, 0" +#define XREG_CP15_SECURE_DEBUG_ENABLE "p15, 0, %0, c1, c1, 1" +#define XREG_CP15_NS_ACCESS_CONTROL "p15, 0, %0, c1, c1, 2" +#define XREG_CP15_VIRTUAL_CONTROL "p15, 0, %0, c1, c1, 3" + +#else /* RVCT */ +/* C0 Register defines */ +#define XREG_CP15_MAIN_ID "cp15:0:c0:c0:0" +#define XREG_CP15_CACHE_TYPE "cp15:0:c0:c0:1" +#define XREG_CP15_TCM_TYPE "cp15:0:c0:c0:2" +#define XREG_CP15_TLB_TYPE "cp15:0:c0:c0:3" +#define XREG_CP15_MULTI_PROC_AFFINITY "cp15:0:c0:c0:5" + +#define XREG_CP15_PROC_FEATURE_0 "cp15:0:c0:c1:0" +#define XREG_CP15_PROC_FEATURE_1 "cp15:0:c0:c1:1" +#define XREG_CP15_DEBUG_FEATURE_0 "cp15:0:c0:c1:2" +#define XREG_CP15_MEMORY_FEATURE_0 "cp15:0:c0:c1:4" +#define XREG_CP15_MEMORY_FEATURE_1 "cp15:0:c0:c1:5" +#define XREG_CP15_MEMORY_FEATURE_2 "cp15:0:c0:c1:6" +#define XREG_CP15_MEMORY_FEATURE_3 "cp15:0:c0:c1:7" + +#define XREG_CP15_INST_FEATURE_0 "cp15:0:c0:c2:0" +#define XREG_CP15_INST_FEATURE_1 "cp15:0:c0:c2:1" +#define XREG_CP15_INST_FEATURE_2 "cp15:0:c0:c2:2" +#define XREG_CP15_INST_FEATURE_3 "cp15:0:c0:c2:3" +#define XREG_CP15_INST_FEATURE_4 "cp15:0:c0:c2:4" + +#define XREG_CP15_CACHE_SIZE_ID "cp15:1:c0:c0:0" +#define XREG_CP15_CACHE_LEVEL_ID "cp15:1:c0:c0:1" +#define XREG_CP15_AUXILARY_ID "cp15:1:c0:c0:7" + +#define XREG_CP15_CACHE_SIZE_SEL "cp15:2:c0:c0:0" + +/* C1 Register Defines */ +#define XREG_CP15_SYS_CONTROL "cp15:0:c1:c0:0" +#define XREG_CP15_AUX_CONTROL "cp15:0:c1:c0:1" +#define XREG_CP15_CP_ACCESS_CONTROL "cp15:0:c1:c0:2" + +#define XREG_CP15_SECURE_CONFIG "cp15:0:c1:c1:0" +#define XREG_CP15_SECURE_DEBUG_ENABLE "cp15:0:c1:c1:1" +#define XREG_CP15_NS_ACCESS_CONTROL "cp15:0:c1:c1:2" +#define XREG_CP15_VIRTUAL_CONTROL "cp15:0:c1:c1:3" +#endif + +/* XREG_CP15_CONTROL bit defines */ +#define XREG_CP15_CONTROL_TE_BIT 0x40000000U +#define XREG_CP15_CONTROL_AFE_BIT 0x20000000U +#define XREG_CP15_CONTROL_TRE_BIT 0x10000000U +#define XREG_CP15_CONTROL_NMFI_BIT 0x08000000U +#define XREG_CP15_CONTROL_EE_BIT 0x02000000U +#define XREG_CP15_CONTROL_HA_BIT 0x00020000U +#define XREG_CP15_CONTROL_RR_BIT 0x00004000U +#define XREG_CP15_CONTROL_V_BIT 0x00002000U +#define XREG_CP15_CONTROL_I_BIT 0x00001000U +#define XREG_CP15_CONTROL_Z_BIT 0x00000800U +#define XREG_CP15_CONTROL_SW_BIT 0x00000400U +#define XREG_CP15_CONTROL_B_BIT 0x00000080U +#define XREG_CP15_CONTROL_C_BIT 0x00000004U +#define XREG_CP15_CONTROL_A_BIT 0x00000002U +#define XREG_CP15_CONTROL_M_BIT 0x00000001U + +#if defined (__GNUC__) || defined (__ICCARM__) +/* C2 Register Defines */ +#define XREG_CP15_TTBR0 "p15, 0, %0, c2, c0, 0" +#define XREG_CP15_TTBR1 "p15, 0, %0, c2, c0, 1" +#define XREG_CP15_TTB_CONTROL "p15, 0, %0, c2, c0, 2" + +/* C3 Register Defines */ +#define XREG_CP15_DOMAIN_ACCESS_CTRL "p15, 0, %0, c3, c0, 0" + +/* C4 Register Defines */ +/* Not Used */ + +/* C5 Register Defines */ +#define XREG_CP15_DATA_FAULT_STATUS "p15, 0, %0, c5, c0, 0" +#define XREG_CP15_INST_FAULT_STATUS "p15, 0, %0, c5, c0, 1" + +#define XREG_CP15_AUX_DATA_FAULT_STATUS "p15, 0, %0, c5, c1, 0" +#define XREG_CP15_AUX_INST_FAULT_STATUS "p15, 0, %0, c5, c1, 1" + +/* C6 Register Defines */ +#define XREG_CP15_DATA_FAULT_ADDRESS "p15, 0, %0, c6, c0, 0" +#define XREG_CP15_INST_FAULT_ADDRESS "p15, 0, %0, c6, c0, 2" + +/* C7 Register Defines */ +#define XREG_CP15_NOP "p15, 0, %0, c7, c0, 4" + +#define XREG_CP15_INVAL_IC_POU_IS "p15, 0, %0, c7, c1, 0" +#define XREG_CP15_INVAL_BRANCH_ARRAY_IS "p15, 0, %0, c7, c1, 6" + +#define XREG_CP15_PHYS_ADDR "p15, 0, %0, c7, c4, 0" + +#define XREG_CP15_INVAL_IC_POU "p15, 0, %0, c7, c5, 0" +#define XREG_CP15_INVAL_IC_LINE_MVA_POU "p15, 0, %0, c7, c5, 1" + +/* The CP15 register access below has been deprecated in favor of the new + * isb instruction in Cortex A9. + */ +#define XREG_CP15_INST_SYNC_BARRIER "p15, 0, %0, c7, c5, 4" +#define XREG_CP15_INVAL_BRANCH_ARRAY "p15, 0, %0, c7, c5, 6" + +#define XREG_CP15_INVAL_DC_LINE_MVA_POC "p15, 0, %0, c7, c6, 1" +#define XREG_CP15_INVAL_DC_LINE_SW "p15, 0, %0, c7, c6, 2" + +#define XREG_CP15_VA_TO_PA_CURRENT_0 "p15, 0, %0, c7, c8, 0" +#define XREG_CP15_VA_TO_PA_CURRENT_1 "p15, 0, %0, c7, c8, 1" +#define XREG_CP15_VA_TO_PA_CURRENT_2 "p15, 0, %0, c7, c8, 2" +#define XREG_CP15_VA_TO_PA_CURRENT_3 "p15, 0, %0, c7, c8, 3" + +#define XREG_CP15_VA_TO_PA_OTHER_0 "p15, 0, %0, c7, c8, 4" +#define XREG_CP15_VA_TO_PA_OTHER_1 "p15, 0, %0, c7, c8, 5" +#define XREG_CP15_VA_TO_PA_OTHER_2 "p15, 0, %0, c7, c8, 6" +#define XREG_CP15_VA_TO_PA_OTHER_3 "p15, 0, %0, c7, c8, 7" + +#define XREG_CP15_CLEAN_DC_LINE_MVA_POC "p15, 0, %0, c7, c10, 1" +#define XREG_CP15_CLEAN_DC_LINE_SW "p15, 0, %0, c7, c10, 2" + +/* The next two CP15 register accesses below have been deprecated in favor + * of the new dsb and dmb instructions in Cortex A9. + */ +#define XREG_CP15_DATA_SYNC_BARRIER "p15, 0, %0, c7, c10, 4" +#define XREG_CP15_DATA_MEMORY_BARRIER "p15, 0, %0, c7, c10, 5" + +#define XREG_CP15_CLEAN_DC_LINE_MVA_POU "p15, 0, %0, c7, c11, 1" + +#define XREG_CP15_NOP2 "p15, 0, %0, c7, c13, 1" + +#define XREG_CP15_CLEAN_INVAL_DC_LINE_MVA_POC "p15, 0, %0, c7, c14, 1" +#define XREG_CP15_CLEAN_INVAL_DC_LINE_SW "p15, 0, %0, c7, c14, 2" + +/* C8 Register Defines */ +#define XREG_CP15_INVAL_TLB_IS "p15, 0, %0, c8, c3, 0" +#define XREG_CP15_INVAL_TLB_MVA_IS "p15, 0, %0, c8, c3, 1" +#define XREG_CP15_INVAL_TLB_ASID_IS "p15, 0, %0, c8, c3, 2" +#define XREG_CP15_INVAL_TLB_MVA_ASID_IS "p15, 0, %0, c8, c3, 3" + +#define XREG_CP15_INVAL_ITLB_UNLOCKED "p15, 0, %0, c8, c5, 0" +#define XREG_CP15_INVAL_ITLB_MVA "p15, 0, %0, c8, c5, 1" +#define XREG_CP15_INVAL_ITLB_ASID "p15, 0, %0, c8, c5, 2" + +#define XREG_CP15_INVAL_DTLB_UNLOCKED "p15, 0, %0, c8, c6, 0" +#define XREG_CP15_INVAL_DTLB_MVA "p15, 0, %0, c8, c6, 1" +#define XREG_CP15_INVAL_DTLB_ASID "p15, 0, %0, c8, c6, 2" + +#define XREG_CP15_INVAL_UTLB_UNLOCKED "p15, 0, %0, c8, c7, 0" +#define XREG_CP15_INVAL_UTLB_MVA "p15, 0, %0, c8, c7, 1" +#define XREG_CP15_INVAL_UTLB_ASID "p15, 0, %0, c8, c7, 2" +#define XREG_CP15_INVAL_UTLB_MVA_ASID "p15, 0, %0, c8, c7, 3" + +/* C9 Register Defines */ +#define XREG_CP15_PERF_MONITOR_CTRL "p15, 0, %0, c9, c12, 0" +#define XREG_CP15_COUNT_ENABLE_SET "p15, 0, %0, c9, c12, 1" +#define XREG_CP15_COUNT_ENABLE_CLR "p15, 0, %0, c9, c12, 2" +#define XREG_CP15_V_FLAG_STATUS "p15, 0, %0, c9, c12, 3" +#define XREG_CP15_SW_INC "p15, 0, %0, c9, c12, 4" +#define XREG_CP15_EVENT_CNTR_SEL "p15, 0, %0, c9, c12, 5" + +#define XREG_CP15_PERF_CYCLE_COUNTER "p15, 0, %0, c9, c13, 0" +#define XREG_CP15_EVENT_TYPE_SEL "p15, 0, %0, c9, c13, 1" +#define XREG_CP15_PERF_MONITOR_COUNT "p15, 0, %0, c9, c13, 2" + +#define XREG_CP15_USER_ENABLE "p15, 0, %0, c9, c14, 0" +#define XREG_CP15_INTR_ENABLE_SET "p15, 0, %0, c9, c14, 1" +#define XREG_CP15_INTR_ENABLE_CLR "p15, 0, %0, c9, c14, 2" + +/* C10 Register Defines */ +#define XREG_CP15_TLB_LOCKDWN "p15, 0, %0, c10, c0, 0" + +#define XREG_CP15_PRI_MEM_REMAP "p15, 0, %0, c10, c2, 0" +#define XREG_CP15_NORM_MEM_REMAP "p15, 0, %0, c10, c2, 1" + +/* C11 Register Defines */ +/* Not used */ + +/* C12 Register Defines */ +#define XREG_CP15_VEC_BASE_ADDR "p15, 0, %0, c12, c0, 0" +#define XREG_CP15_MONITOR_VEC_BASE_ADDR "p15, 0, %0, c12, c0, 1" + +#define XREG_CP15_INTERRUPT_STATUS "p15, 0, %0, c12, c1, 0" +#define XREG_CP15_VIRTUALIZATION_INTR "p15, 0, %0, c12, c1, 1" + +/* C13 Register Defines */ +#define XREG_CP15_CONTEXT_ID "p15, 0, %0, c13, c0, 1" +#define USER_RW_THREAD_PID "p15, 0, %0, c13, c0, 2" +#define USER_RO_THREAD_PID "p15, 0, %0, c13, c0, 3" +#define USER_PRIV_THREAD_PID "p15, 0, %0, c13, c0, 4" + +/* C14 Register Defines */ +/* not used */ + +/* C15 Register Defines */ +#define XREG_CP15_POWER_CTRL "p15, 0, %0, c15, c0, 0" +#define XREG_CP15_CONFIG_BASE_ADDR "p15, 4, %0, c15, c0, 0" + +#define XREG_CP15_READ_TLB_ENTRY "p15, 5, %0, c15, c4, 2" +#define XREG_CP15_WRITE_TLB_ENTRY "p15, 5, %0, c15, c4, 4" + +#define XREG_CP15_MAIN_TLB_VA "p15, 5, %0, c15, c5, 2" + +#define XREG_CP15_MAIN_TLB_PA "p15, 5, %0, c15, c6, 2" + +#define XREG_CP15_MAIN_TLB_ATTR "p15, 5, %0, c15, c7, 2" + +#else +/* C2 Register Defines */ +#define XREG_CP15_TTBR0 "cp15:0:c2:c0:0" +#define XREG_CP15_TTBR1 "cp15:0:c2:c0:1" +#define XREG_CP15_TTB_CONTROL "cp15:0:c2:c0:2" + +/* C3 Register Defines */ +#define XREG_CP15_DOMAIN_ACCESS_CTRL "cp15:0:c3:c0:0" + +/* C4 Register Defines */ +/* Not Used */ + +/* C5 Register Defines */ +#define XREG_CP15_DATA_FAULT_STATUS "cp15:0:c5:c0:0" +#define XREG_CP15_INST_FAULT_STATUS "cp15:0:c5:c0:1" + +#define XREG_CP15_AUX_DATA_FAULT_STATUS "cp15:0:c5:c1:0" +#define XREG_CP15_AUX_INST_FAULT_STATUS "cp15:0:c5:c1:1" + +/* C6 Register Defines */ +#define XREG_CP15_DATA_FAULT_ADDRESS "cp15:0:c6:c0:0" +#define XREG_CP15_INST_FAULT_ADDRESS "cp15:0:c6:c0:2" + +/* C7 Register Defines */ +#define XREG_CP15_NOP "cp15:0:c7:c0:4" + +#define XREG_CP15_INVAL_IC_POU_IS "cp15:0:c7:c1:0" +#define XREG_CP15_INVAL_BRANCH_ARRAY_IS "cp15:0:c7:c1:6" + +#define XREG_CP15_PHYS_ADDR "cp15:0:c7:c4:0" + +#define XREG_CP15_INVAL_IC_POU "cp15:0:c7:c5:0" +#define XREG_CP15_INVAL_IC_LINE_MVA_POU "cp15:0:c7:c5:1" + +/* The CP15 register access below has been deprecated in favor of the new + * isb instruction in Cortex A9. + */ +#define XREG_CP15_INST_SYNC_BARRIER "cp15:0:c7:c5:4" +#define XREG_CP15_INVAL_BRANCH_ARRAY "cp15:0:c7:c5:6" + +#define XREG_CP15_INVAL_DC_LINE_MVA_POC "cp15:0:c7:c6:1" +#define XREG_CP15_INVAL_DC_LINE_SW "cp15:0:c7:c6:2" + +#define XREG_CP15_VA_TO_PA_CURRENT_0 "cp15:0:c7:c8:0" +#define XREG_CP15_VA_TO_PA_CURRENT_1 "cp15:0:c7:c8:1" +#define XREG_CP15_VA_TO_PA_CURRENT_2 "cp15:0:c7:c8:2" +#define XREG_CP15_VA_TO_PA_CURRENT_3 "cp15:0:c7:c8:3" + +#define XREG_CP15_VA_TO_PA_OTHER_0 "cp15:0:c7:c8:4" +#define XREG_CP15_VA_TO_PA_OTHER_1 "cp15:0:c7:c8:5" +#define XREG_CP15_VA_TO_PA_OTHER_2 "cp15:0:c7:c8:6" +#define XREG_CP15_VA_TO_PA_OTHER_3 "cp15:0:c7:c8:7" + +#define XREG_CP15_CLEAN_DC_LINE_MVA_POC "cp15:0:c7:c10:1" +#define XREG_CP15_CLEAN_DC_LINE_SW "cp15:0:c7:c10:2" + +/* The next two CP15 register accesses below have been deprecated in favor + * of the new dsb and dmb instructions in Cortex A9. + */ +#define XREG_CP15_DATA_SYNC_BARRIER "cp15:0:c7:c10:4" +#define XREG_CP15_DATA_MEMORY_BARRIER "cp15:0:c7:c10:5" + +#define XREG_CP15_CLEAN_DC_LINE_MVA_POU "cp15:0:c7:c11:1" + +#define XREG_CP15_NOP2 "cp15:0:c7:c13:1" + +#define XREG_CP15_CLEAN_INVAL_DC_LINE_MVA_POC "cp15:0:c7:c14:1" +#define XREG_CP15_CLEAN_INVAL_DC_LINE_SW "cp15:0:c7:c14:2" + +/* C8 Register Defines */ +#define XREG_CP15_INVAL_TLB_IS "cp15:0:c8:c3:0" +#define XREG_CP15_INVAL_TLB_MVA_IS "cp15:0:c8:c3:1" +#define XREG_CP15_INVAL_TLB_ASID_IS "cp15:0:c8:c3:2" +#define XREG_CP15_INVAL_TLB_MVA_ASID_IS "cp15:0:c8:c3:3" + +#define XREG_CP15_INVAL_ITLB_UNLOCKED "cp15:0:c8:c5:0" +#define XREG_CP15_INVAL_ITLB_MVA "cp15:0:c8:c5:1" +#define XREG_CP15_INVAL_ITLB_ASID "cp15:0:c8:c5:2" + +#define XREG_CP15_INVAL_DTLB_UNLOCKED "cp15:0:c8:c6:0" +#define XREG_CP15_INVAL_DTLB_MVA "cp15:0:c8:c6:1" +#define XREG_CP15_INVAL_DTLB_ASID "cp15:0:c8:c6:2" + +#define XREG_CP15_INVAL_UTLB_UNLOCKED "cp15:0:c8:c7:0" +#define XREG_CP15_INVAL_UTLB_MVA "cp15:0:c8:c7:1" +#define XREG_CP15_INVAL_UTLB_ASID "cp15:0:c8:c7:2" +#define XREG_CP15_INVAL_UTLB_MVA_ASID "cp15:0:c8:c7:3" + +/* C9 Register Defines */ +#define XREG_CP15_PERF_MONITOR_CTRL "cp15:0:c9:c12:0" +#define XREG_CP15_COUNT_ENABLE_SET "cp15:0:c9:c12:1" +#define XREG_CP15_COUNT_ENABLE_CLR "cp15:0:c9:c12:2" +#define XREG_CP15_V_FLAG_STATUS "cp15:0:c9:c12:3" +#define XREG_CP15_SW_INC "cp15:0:c9:c12:4" +#define XREG_CP15_EVENT_CNTR_SEL "cp15:0:c9:c12:5" + +#define XREG_CP15_PERF_CYCLE_COUNTER "cp15:0:c9:c13:0" +#define XREG_CP15_EVENT_TYPE_SEL "cp15:0:c9:c13:1" +#define XREG_CP15_PERF_MONITOR_COUNT "cp15:0:c9:c13:2" + +#define XREG_CP15_USER_ENABLE "cp15:0:c9:c14:0" +#define XREG_CP15_INTR_ENABLE_SET "cp15:0:c9:c14:1" +#define XREG_CP15_INTR_ENABLE_CLR "cp15:0:c9:c14:2" + +/* C10 Register Defines */ +#define XREG_CP15_TLB_LOCKDWN "cp15:0:c10:c0:0" + +#define XREG_CP15_PRI_MEM_REMAP "cp15:0:c10:c2:0" +#define XREG_CP15_NORM_MEM_REMAP "cp15:0:c10:c2:1" + +/* C11 Register Defines */ +/* Not used */ + +/* C12 Register Defines */ +#define XREG_CP15_VEC_BASE_ADDR "cp15:0:c12:c0:0" +#define XREG_CP15_MONITOR_VEC_BASE_ADDR "cp15:0:c12:c0:1" + +#define XREG_CP15_INTERRUPT_STATUS "cp15:0:c12:c1:0" +#define XREG_CP15_VIRTUALIZATION_INTR "cp15:0:c12:c1:1" + +/* C13 Register Defines */ +#define XREG_CP15_CONTEXT_ID "cp15:0:c13:c0:1" +#define USER_RW_THREAD_PID "cp15:0:c13:c0:2" +#define USER_RO_THREAD_PID "cp15:0:c13:c0:3" +#define USER_PRIV_THREAD_PID "cp15:0:c13:c0:4" + +/* C14 Register Defines */ +/* not used */ + +/* C15 Register Defines */ +#define XREG_CP15_POWER_CTRL "cp15:0:c15:c0:0" +#define XREG_CP15_CONFIG_BASE_ADDR "cp15:4:c15:c0:0" + +#define XREG_CP15_READ_TLB_ENTRY "cp15:5:c15:c4:2" +#define XREG_CP15_WRITE_TLB_ENTRY "cp15:5:c15:c4:4" + +#define XREG_CP15_MAIN_TLB_VA "cp15:5:c15:c5:2" + +#define XREG_CP15_MAIN_TLB_PA "cp15:5:c15:c6:2" + +#define XREG_CP15_MAIN_TLB_ATTR "cp15:5:c15:c7:2" +#endif + + +/* MPE register definitions */ +#define XREG_FPSID c0 +#define XREG_FPSCR c1 +#define XREG_MVFR1 c6 +#define XREG_MVFR0 c7 +#define XREG_FPEXC c8 +#define XREG_FPINST c9 +#define XREG_FPINST2 c10 + +/* FPSID bits */ +#define XREG_FPSID_IMPLEMENTER_BIT (24) +#define XREG_FPSID_IMPLEMENTER_MASK (0xFF << FPSID_IMPLEMENTER_BIT) +#define XREG_FPSID_SOFTWARE (1<<23) +#define XREG_FPSID_ARCH_BIT (16) +#define XREG_FPSID_ARCH_MASK (0xF << FPSID_ARCH_BIT) +#define XREG_FPSID_PART_BIT (8) +#define XREG_FPSID_PART_MASK (0xFF << FPSID_PART_BIT) +#define XREG_FPSID_VARIANT_BIT (4) +#define XREG_FPSID_VARIANT_MASK (0xF << FPSID_VARIANT_BIT) +#define XREG_FPSID_REV_BIT (0) +#define XREG_FPSID_REV_MASK (0xF << FPSID_REV_BIT) + +/* FPSCR bits */ +#define XREG_FPSCR_N_BIT (1 << 31) +#define XREG_FPSCR_Z_BIT (1 << 30) +#define XREG_FPSCR_C_BIT (1 << 29) +#define XREG_FPSCR_V_BIT (1 << 28) +#define XREG_FPSCR_QC (1 << 27) +#define XREG_FPSCR_AHP (1 << 26) +#define XREG_FPSCR_DEFAULT_NAN (1 << 25) +#define XREG_FPSCR_FLUSHTOZERO (1 << 24) +#define XREG_FPSCR_ROUND_NEAREST (0 << 22) +#define XREG_FPSCR_ROUND_PLUSINF (1 << 22) +#define XREG_FPSCR_ROUND_MINUSINF (2 << 22) +#define XREG_FPSCR_ROUND_TOZERO (3 << 22) +#define XREG_FPSCR_RMODE_BIT (22) +#define XREG_FPSCR_RMODE_MASK (3 << FPSCR_RMODE_BIT) +#define XREG_FPSCR_STRIDE_BIT (20) +#define XREG_FPSCR_STRIDE_MASK (3 << FPSCR_STRIDE_BIT) +#define XREG_FPSCR_LENGTH_BIT (16) +#define XREG_FPSCR_LENGTH_MASK (7 << FPSCR_LENGTH_BIT) +#define XREG_FPSCR_IDC (1 << 7) +#define XREG_FPSCR_IXC (1 << 4) +#define XREG_FPSCR_UFC (1 << 3) +#define XREG_FPSCR_OFC (1 << 2) +#define XREG_FPSCR_DZC (1 << 1) +#define XREG_FPSCR_IOC (1 << 0) + +/* MVFR0 bits */ +#define XREG_MVFR0_RMODE_BIT (28) +#define XREG_MVFR0_RMODE_MASK (0xF << XREG_MVFR0_RMODE_BIT) +#define XREG_MVFR0_SHORT_VEC_BIT (24) +#define XREG_MVFR0_SHORT_VEC_MASK (0xF << XREG_MVFR0_SHORT_VEC_BIT) +#define XREG_MVFR0_SQRT_BIT (20) +#define XREG_MVFR0_SQRT_MASK (0xF << XREG_MVFR0_SQRT_BIT) +#define XREG_MVFR0_DIVIDE_BIT (16) +#define XREG_MVFR0_DIVIDE_MASK (0xF << XREG_MVFR0_DIVIDE_BIT) +#define XREG_MVFR0_EXEC_TRAP_BIT (12) +#define XREG_MVFR0_EXEC_TRAP_MASK (0xF << XREG_MVFR0_EXEC_TRAP_BIT) +#define XREG_MVFR0_DP_BIT (8) +#define XREG_MVFR0_DP_MASK (0xF << XREG_MVFR0_DP_BIT) +#define XREG_MVFR0_SP_BIT (4) +#define XREG_MVFR0_SP_MASK (0xF << XREG_MVFR0_SP_BIT) +#define XREG_MVFR0_A_SIMD_BIT (0) +#define XREG_MVFR0_A_SIMD_MASK (0xF << MVFR0_A_SIMD_BIT) + +/* FPEXC bits */ +#define XREG_FPEXC_EX (1 << 31) +#define XREG_FPEXC_EN (1 << 30) +#define XREG_FPEXC_DEX (1 << 29) + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* XREG_CORTEXA9_H */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/include/xscugic.h b/datalink814_ge/bsp/ps7_cortexa9_0/include/xscugic.h new file mode 100644 index 0000000..5502a20 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/include/xscugic.h @@ -0,0 +1,598 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xscugic.h +* @addtogroup scugic_v4_0 +* @{ +* @details +* +* The generic interrupt controller driver component. +* +* The interrupt controller driver uses the idea of priority for the various +* handlers. Priority is an integer within the range of 1 and 31 inclusive with +* default of 1 being the highest priority interrupt source. The priorities +* of the various sources can be dynamically altered as needed through +* hardware configuration. +* +* The generic interrupt controller supports the following +* features: +* +* - specific individual interrupt enabling/disabling +* - specific individual interrupt acknowledging +* - attaching specific callback function to handle interrupt source +* - assigning desired priority to interrupt source if default is not +* acceptable. +* +* Details about connecting the interrupt handler of the driver are contained +* in the source file specific to interrupt processing, xscugic_intr.c. +* +* This driver is intended to be RTOS and processor independent. It works with +* physical addresses only. Any needs for dynamic memory management, threads +* or thread mutual exclusion, virtual memory, or cache control must be +* satisfied by the layer above this driver. +* +* Interrupt Vector Tables +* +* The device ID of the interrupt controller device is used by the driver as a +* direct index into the configuration data table. The user should populate the +* vector table with handlers and callbacks at run-time using the +* XScuGic_Connect() and XScuGic_Disconnect() functions. +* +* Each vector table entry corresponds to a device that can generate an +* interrupt. Each entry contains an interrupt handler function and an +* argument to be passed to the handler when an interrupt occurs. The +* user must use XScuGic_Connect() when the interrupt handler takes an +* argument other than the base address. +* +* Nested Interrupts Processing +* +* Nested interrupts are not supported by this driver. +* +* NOTE: +* The generic interrupt controller is not a part of the snoop control unit +* as indicated by the prefix "scu" in the name of the driver. +* It is an independent module in APU. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- ---------------------------------------------------------
+* 1.00a drg  01/19/00 First release
+* 1.01a sdm  11/09/11 The XScuGic and XScuGic_Config structures have changed.
+*		      The HandlerTable (of type XScuGic_VectorTableEntry) is
+*		      moved to XScuGic_Config structure from XScuGic structure.
+*
+*		      The "Config" entry in XScuGic structure is made as
+*		      pointer for better efficiency.
+*
+*		      A new file named as xscugic_hw.c is now added. It is
+*		      to implement low level driver routines without using
+*		      any xscugic instance pointer. They are useful when the
+*		      user wants to use xscugic through device id or
+*		      base address. The driver routines provided are explained
+*		      below.
+*		      XScuGic_DeviceInitialize that takes device id as
+*		      argument and initializes the device (without calling
+*		      XScuGic_CfgInitialize).
+*		      XScuGic_DeviceInterruptHandler that takes device id
+*		      as argument and calls appropriate handlers from the
+*		      HandlerTable.
+*		      XScuGic_RegisterHandler that registers a new handler
+*		      by taking xscugic hardware base address as argument.
+*		      LookupConfigByBaseAddress is used to return the
+*		      corresponding config structure from XScuGic_ConfigTable
+*		      based on the scugic base address passed.
+* 1.02a sdm  12/20/11 Removed AckBeforeService from the XScuGic_Config
+*		      structure.
+* 1.03a srt  02/27/13 Moved Offset calculation macros from *.c and *_hw.c to
+*		      *_hw.h
+*		      Added APIs
+*			- XScuGic_SetPriTrigTypeByDistAddr()
+*			- XScuGic_GetPriTrigTypeByDistAddr()
+*		      (CR 702687)
+*			Added support to direct interrupts to the appropriate CPU. Earlier
+*			  interrupts were directed to CPU1 (hard coded). Now depending
+*			  upon the CPU selected by the user (xparameters.h), interrupts
+*			  will be directed to the relevant CPU. This fixes CR 699688.
+* 1.04a hk   05/04/13 Assigned EffectiveAddr to CpuBaseAddress in
+*			  XScuGic_CfgInitialize. Fix for CR#704400 to remove warnings.
+*			  Moved functions XScuGic_SetPriTrigTypeByDistAddr and
+*             XScuGic_GetPriTrigTypeByDistAddr to xscugic_hw.c.
+*			  This is fix for CR#705621.
+* 1.05a hk   06/26/13 Modified tcl to export external interrupts correctly to
+*                     xparameters.h. Fix for CR's 690505, 708928 & 719359.
+* 2.0   adk  12/10/13 Updated as per the New Tcl API's
+* 2.1   adk  25/04/14 Fixed the CR:789373 changes are made in the driver tcl file.
+* 3.00  kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.2   asa  02/29/16 Modified DistributorInit function for Zynq AMP case. The
+*			  distributor is left uninitialized for Zynq AMP. It is assumed
+*             that the distributor will be initialized by Linux master. However
+*             for CortexR5 case, the earlier code is left unchanged where the
+*             the interrupt processor target registers in the distributor is
+*             initialized with the corresponding CPU ID on which the application
+*             built over the scugic driver runs.
+*             These changes fix CR#937243.
+*
+* 3.4   asa  04/07/16 Created a new static function DoDistributorInit to simplify
+*            the flow and avoid code duplication. Changes are made for
+*            USE_AMP use case for R5. In a scenario (in R5 split mode) when
+*            one R5 is operating with A53 in open amp config and other
+*            R5 running baremetal app, the existing code
+*            had the potential to stop the whole AMP solution to work (if
+*            for some reason the R5 running the baremetal app tasked to
+*            initialize the Distributor hangs or crashes before initializing).
+*            Changes are made so that the R5 under AMP first checks if
+*            the distributor is enabled or not and if not, it does the
+*            standard Distributor initialization.
+*            This fixes the CR#952962.
+* 3.6   ms   01/23/17 Modified xil_printf statement in main function for all
+*                     examples to ensure that "Successfully ran" and "Failed"
+*                     strings are available in all examples. This is a fix
+*                     for CR-965028.
+*       kvn  02/17/17 Add support for changing GIC CPU master at run time.
+*       kvn  02/28/17 Make the CpuId as static variable and Added new
+*                     XScugiC_GetCpuId to access CpuId.
+*       ms   03/17/17 Added readme.txt file in examples folder for doxygen
+*                     generation.
+* 3.7   ms   04/11/17 Modified tcl file to add suffix U for all macro
+*                     definitions of scugic in xparameters.h
+* 3.8   mus  07/05/17 Updated scugic.tcl to add support for intrrupts connected
+*                     through util_reduced_vector IP(OR gate)
+*       mus  07/05/17 Updated xdefine_zynq_canonical_xpars proc to initialize
+*                     the HandlerTable in XScuGic_ConfigTable to 0, it removes
+*                     the compilation warning in xscugic_g.c. Fix for CR#978736.
+*       mus  07/25/17 Updated xdefine_gic_params proc to export correct canonical
+*                     definitions for pl to ps interrupts.Fix for CR#980534
+* 3.9   mus  02/21/18 Added new API's XScuGic_UnmapAllInterruptsFromCpu and
+*                     XScuGic_InterruptUnmapFromCpu, These API's can be used
+*                     by applications to unmap specific/all interrupts from
+*                     target CPU.
+* 3.10  aru  08/23/18 Resolved MISRA-C:2012 compliance mandatory violations
+* 4.0   mus  11/22/18 Fixed bugs in software interrupt generation through 
+*                      XScuGic_SoftwareIntr API
+*
+* 
+* +******************************************************************************/ + +#ifndef XSCUGIC_H /* prevent circular inclusions */ +#define XSCUGIC_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + + +/***************************** Include Files *********************************/ + +#include "xstatus.h" +#include "xil_io.h" +#include "xscugic_hw.h" +#include "xil_exception.h" + +/************************** Constant Definitions *****************************/ + +#define EFUSE_STATUS_OFFSET 0x10 +#define EFUSE_STATUS_CPU_MASK 0x80 + +#if !defined (ARMR5) && !defined (__aarch64__) && !defined (ARMA53_32) +#define ARMA9 +#endif + +#define XSCUGIC500_DCTLR_ARE_NS_ENABLE 0x20 +#define XSCUGIC500_DCTLR_ARE_S_ENABLE 0x10 +/**************************** Type Definitions *******************************/ + +/* The following data type defines each entry in an interrupt vector table. + * The callback reference is the base address of the interrupting device + * for the low level driver and an instance pointer for the high level driver. + */ +typedef struct +{ + Xil_InterruptHandler Handler; + void *CallBackRef; +} XScuGic_VectorTableEntry; + +/** + * This typedef contains configuration information for the device. + */ +typedef struct +{ + u16 DeviceId; /**< Unique ID of device */ + u32 CpuBaseAddress; /**< CPU Interface Register base address */ + u32 DistBaseAddress; /**< Distributor Register base address */ + XScuGic_VectorTableEntry HandlerTable[XSCUGIC_MAX_NUM_INTR_INPUTS];/**< + Vector table of interrupt handlers */ +} XScuGic_Config; + +/** + * The XScuGic driver instance data. The user is required to allocate a + * variable of this type for every intc device in the system. A pointer + * to a variable of this type is then passed to the driver API functions. + */ +typedef struct +{ + XScuGic_Config *Config; /**< Configuration table entry */ + u32 IsReady; /**< Device is initialized and ready */ + u32 UnhandledInterrupts; /**< Intc Statistics */ +} XScuGic; + +/***************** Macros (Inline Functions) Definitions *********************/ + +/****************************************************************************/ +/** +* +* Write the given CPU Interface register +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param RegOffset is the register offset to be written +* @param Data is the 32-bit value to write to the register +* +* @return None. +* +* @note +* C-style signature: +* void XScuGic_CPUWriteReg(XScuGic *InstancePtr, u32 RegOffset, u32 Data) +* +*****************************************************************************/ +#define XScuGic_CPUWriteReg(InstancePtr, RegOffset, Data) \ +(XScuGic_WriteReg(((InstancePtr)->Config->CpuBaseAddress), (RegOffset), \ + ((u32)(Data)))) + +/****************************************************************************/ +/** +* +* Read the given CPU Interface register +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param RegOffset is the register offset to be read +* +* @return The 32-bit value of the register +* +* @note +* C-style signature: +* u32 XScuGic_CPUReadReg(XScuGic *InstancePtr, u32 RegOffset) +* +*****************************************************************************/ +#define XScuGic_CPUReadReg(InstancePtr, RegOffset) \ + (XScuGic_ReadReg(((InstancePtr)->Config->CpuBaseAddress), (RegOffset))) + +/****************************************************************************/ +/** +* +* Write the given Distributor Interface register +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param RegOffset is the register offset to be written +* @param Data is the 32-bit value to write to the register +* +* @return None. +* +* @note +* C-style signature: +* void XScuGic_DistWriteReg(XScuGic *InstancePtr, u32 RegOffset, u32 Data) +* +*****************************************************************************/ +#define XScuGic_DistWriteReg(InstancePtr, RegOffset, Data) \ +(XScuGic_WriteReg(((InstancePtr)->Config->DistBaseAddress), (RegOffset), \ + ((u32)(Data)))) + +/****************************************************************************/ +/** +* +* Read the given Distributor Interface register +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param RegOffset is the register offset to be read +* +* @return The 32-bit value of the register +* +* @note +* C-style signature: +* u32 XScuGic_DistReadReg(XScuGic *InstancePtr, u32 RegOffset) +* +*****************************************************************************/ +#define XScuGic_DistReadReg(InstancePtr, RegOffset) \ +(XScuGic_ReadReg(((InstancePtr)->Config->DistBaseAddress), (RegOffset))) + +/****************************************************************************/ +/** +* +* Write the given ReDistributor Interface register +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param RegOffset is the register offset to be written +* @param Data is the 32-bit value to write to the register +* +* @return None. +* +* @note +* C-style signature: +* void XScuGic_DistWriteReg(XScuGic *InstancePtr, u32 RegOffset, u32 Data) +* +*****************************************************************************/ +#define XScuGic_ReDistWriteReg(InstancePtr, RegOffset, Data) \ +(XScuGic_WriteReg(((InstancePtr)->Config->DistBaseAddress)+ \ + XSCUGIC_RDIST_OFFSET, (RegOffset), ((u32)(Data)))) + +/****************************************************************************/ +/** +* +* Read the given ReDistributor Interface register +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param RegOffset is the register offset to be read +* +* @return The 32-bit value of the register +* +* @note +* C-style signature: +* u32 XScuGic_DistReadReg(XScuGic *InstancePtr, u32 RegOffset) +* +*****************************************************************************/ +#define XScuGic_ReDistReadReg(InstancePtr, RegOffset) \ +(XScuGic_ReadReg((((InstancePtr)->Config->DistBaseAddress)+ \ +XSCUGIC_RDIST_OFFSET), (RegOffset))) + +/****************************************************************************/ +/** +* +* Write the given ReDistributor SGI PPI Interface register +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param RegOffset is the register offset to be written +* @param Data is the 32-bit value to write to the register +* +* @return None. +* +* @note +* C-style signature: +* void XScuGic_DistWriteReg(XScuGic *InstancePtr, u32 RegOffset, u32 Data) +* +*****************************************************************************/ +#define XScuGic_ReDistSGIPPIWriteReg(InstancePtr, RegOffset, Data) \ +(XScuGic_WriteReg(((InstancePtr)->Config->DistBaseAddress)+ \ + XSCUGIC_RDIST_SGI_PPI_OFFSET, (RegOffset), ((u32)(Data)))) + +/****************************************************************************/ +/** +* +* Read the given ReDistributor SGI PPI Interface register +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param RegOffset is the register offset to be read +* +* @return The 32-bit value of the register +* +* @note +* C-style signature: +* u32 XScuGic_DistReadReg(XScuGic *InstancePtr, u32 RegOffset) +* +*****************************************************************************/ +#define XScuGic_ReDistSGIPPIReadReg(InstancePtr, RegOffset) \ +(XScuGic_ReadReg((((InstancePtr)->Config->DistBaseAddress)+ \ + XSCUGIC_RDIST_SGI_PPI_OFFSET), (RegOffset))) + +/****************************************************************************/ +/** +* This function enables system register interface for GIC CPU Interface +* +* @param value to be written +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +#define XScuGic_Enable_SystemReg_CPU_Interface_EL3() mtcp(S3_6_C12_C12_5, 0xF); +#define XScuGic_Enable_SystemReg_CPU_Interface_EL1() mtcp(S3_0_C12_C12_5, 0xF); +/****************************************************************************/ +/** +* This function enables Grou0 interrupts +* +* @param None. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +#define XScuGic_Enable_Group0_Interrupts() mtcp(S3_0_C12_C12_6,0x1); +/****************************************************************************/ +/** +* This function enables Group1 interrupts +* +* @param None. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +#if defined (__aarch64__) +#if EL1_NONSECURE +#define XScuGic_Enable_Group1_Interrupts() \ + mtcp (S3_0_C12_C12_7, 0x1 | mfcp(S3_0_C12_C12_7) ); +#else +#define XScuGic_Enable_Group1_Interrupts() \ + mtcp (S3_6_C12_C12_7, 0x1 | mfcp(S3_6_C12_C12_7) ); +#endif +#endif +/****************************************************************************/ +/** +* This function writes to ICC_SGI0R_EL1 +* +* @param value to be written +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +#define XScuGic_WriteICC_SGI0R_EL1(val) mtcp(S3_0_C12_C11_7,val) + +/****************************************************************************/ +/** +* This function writes to ICC_SGI1R_EL1 +* +* @param value to be written +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +#define XScuGic_WriteICC_SGI1R_EL1(val) mtcp(S3_0_C12_C11_5,val) + +/****************************************************************************/ +/** +* This function reads ICC_SGI1R_EL1 register +* +* @param None +* +* @return Value of ICC_SGI1R_EL1 register +* +* @note None. +* +*****************************************************************************/ +#define XScuGic_ReadICC_SGI1R_EL1() mfcp(S3_0_C12_C11_5) +/****************************************************************************/ +/** +* This function sets interrupt priority filter +* +* @param None. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +#define XScuGic_set_priority_filter(val) __asm__ __volatile__("msr S3_0_C4_C6_0,%0" : : "r" (val)) +/****************************************************************************/ +/** +* This function returns interrupt id of highest priority pending interrupt +* +* @param None. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +#if defined (__aarch64__) +#if EL3 +#define XScuGic_get_IntID() mfcp(S3_0_C12_C8_0) +#else +#define XScuGic_get_IntID() mfcp(S3_0_C12_C12_0) +#endif +#endif +/****************************************************************************/ +/** +* This function acks the interrupt +* +* @param None. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +#if defined (__aarch64__) +#if EL3 +#define XScuGic_ack_Int(val) mtcp(S3_0_C12_C8_1,val) +#else +#define XScuGic_ack_Int(val) mtcp(S3_0_C12_C12_1,val) +#endif +#endif +/****************************************************************************/ +/** +* This macro returns bit position for the specific interrupt's trigger type +* configuration within GICR_ICFGR0/GICR_ICFGR1 register +* +* @param None. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +#define XScuGic_Get_Rdist_Int_Trigger_Index(IntrId) (((Int_Id%16) & 0x1f) << 2) +1 +/************************** Function Prototypes ******************************/ + +/* + * Required functions in xscugic.c + */ + +s32 XScuGic_Connect(XScuGic *InstancePtr, u32 Int_Id, + Xil_InterruptHandler Handler, void *CallBackRef); +void XScuGic_Disconnect(XScuGic *InstancePtr, u32 Int_Id); + +void XScuGic_Enable(XScuGic *InstancePtr, u32 Int_Id); +void XScuGic_Disable(XScuGic *InstancePtr, u32 Int_Id); + +s32 XScuGic_CfgInitialize(XScuGic *InstancePtr, XScuGic_Config *ConfigPtr, + u32 EffectiveAddr); + +s32 XScuGic_SoftwareIntr(XScuGic *InstancePtr, u32 Int_Id, u32 Cpu_Id); + +void XScuGic_GetPriorityTriggerType(XScuGic *InstancePtr, u32 Int_Id, + u8 *Priority, u8 *Trigger); +void XScuGic_SetPriorityTriggerType(XScuGic *InstancePtr, u32 Int_Id, + u8 Priority, u8 Trigger); +void XScuGic_InterruptMaptoCpu(XScuGic *InstancePtr, u8 Cpu_Id, u32 Int_Id); +void XScuGic_InterruptUnmapFromCpu(XScuGic *InstancePtr, u8 Cpu_Id, u32 Int_Id); +void XScuGic_UnmapAllInterruptsFromCpu(XScuGic *InstancePtr, u8 Cpu_Id); +void XScuGic_Stop(XScuGic *InstancePtr); +void XScuGic_SetCpuID(u32 CpuCoreId); +u32 XScuGic_GetCpuID(void); +/* + * Initialization functions in xscugic_sinit.c + */ +XScuGic_Config *XScuGic_LookupConfig(u16 DeviceId); + +/* + * Interrupt functions in xscugic_intr.c + */ +void XScuGic_InterruptHandler(XScuGic *InstancePtr); + +/* + * Self-test functions in xscugic_selftest.c + */ +s32 XScuGic_SelfTest(XScuGic *InstancePtr); + +void XScuGic_EnableSGI_PPI(XScuGic *InstancePtr,u32 ID); +void XScuGic_SetPPI_SGI_Priority(XScuGic *InstancePtr,u32 ID, u32 priority); +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/include/xscugic_hw.h b/datalink814_ge/bsp/ps7_cortexa9_0/include/xscugic_hw.h new file mode 100644 index 0000000..60d111f --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/include/xscugic_hw.h @@ -0,0 +1,753 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xscugic_hw.h +* @addtogroup scugic_v4_0 +* @{ +* +* This header file contains identifiers and HW access functions (or +* macros) that can be used to access the device. The user should refer to the +* hardware device specification for more details of the device operation. +* The driver functions/APIs are defined in xscugic.h. +* +* This GIC device has two parts, a distributor and CPU interface(s). Each part +* has separate register definition sections. +* +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------------
+* 1.00a drg  01/19/10 First release
+* 1.01a sdm  11/09/11 "xil_exception.h" added as include.
+*		      Macros XScuGic_EnableIntr and XScuGic_DisableIntr are
+*		      added to enable or disable interrupts based on
+*		      Distributor Register base address. Normally users use
+*		      XScuGic instance and call XScuGic_Enable or
+*		      XScuGic_Disable to enable/disable interrupts. These
+*		      new macros are provided when user does not want to
+*		      use an instance pointer but still wants to enable or
+*		      disable interrupts.
+*		      Function prototypes for functions (present in newly
+*		      added file xscugic_hw.c) are added.
+* 1.03a srt  02/27/13 Moved Offset calculation macros from *_hw.c (CR
+*		      702687).
+* 1.04a hk   05/04/13 Fix for CR#705621. Moved function prototypes
+*		      XScuGic_SetPriTrigTypeByDistAddr and
+*         	      XScuGic_GetPriTrigTypeByDistAddr here from xscugic.h
+* 3.0	pkp  12/09/14 changed XSCUGIC_MAX_NUM_INTR_INPUTS for
+*		      Zynq Ultrascale Mp
+* 3.0   kvn  02/13/14 Modified code for MISRA-C:2012 compliance.
+* 3.2	pkp  11/09/15 Corrected the interrupt processsor target mask value
+*					  for CPU interface 2 i.e. XSCUGIC_SPI_CPU2_MASK
+* 3.9   mus  02/21/18 Added new API's XScuGic_InterruptUnmapFromCpuByDistAddr
+*					  and XScuGic_UnmapAllInterruptsFromCpuByDistAddr, These
+*					  API's can be used by applications to unmap specific/all
+*					  interrupts from target CPU. It fixes CR#992490.
+* 3.10  aru  08/23/18 Resolved MISRA-C:2012 compliance mandatory violations
+*
+* 
+* +******************************************************************************/ + +#ifndef XSCUGIC_HW_H /* prevent circular inclusions */ +#define XSCUGIC_HW_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_io.h" +#include "xil_exception.h" +#include "bspconfig.h" + +/************************** Constant Definitions *****************************/ + +/* + * The maximum number of interrupts supported by the hardware. + */ +#ifdef PLATFORM_ZYNQ +#define XSCUGIC_MAX_NUM_INTR_INPUTS 95U /* Maximum number of interrupt defined by Zynq */ +#elif defined (versal) && !defined(ARMR5) +#define XSCUGIC_MAX_NUM_INTR_INPUTS 191U +#else +#define XSCUGIC_MAX_NUM_INTR_INPUTS 195U /* Maximum number of interrupt defined by Zynq Ultrascale Mp */ +#endif + +/* + * First Interrupt Id for SPI interrupts. + */ +#define XSCUGIC_SPI_INT_ID_START 0x20 +/* + * The maximum priority value that can be used in the GIC. + */ +#define XSCUGIC_MAX_INTR_PRIO_VAL 248U +#define XSCUGIC_INTR_PRIO_MASK 0x000000F8U + +/** @name Distributor Interface Register Map + * + * Define the offsets from the base address for all Distributor registers of + * the interrupt controller, some registers may be reserved in the hardware + * device. + * @{ + */ +#define XSCUGIC_DIST_EN_OFFSET 0x00000000U /**< Distributor Enable + Register */ +#define XSCUGIC_IC_TYPE_OFFSET 0x00000004U /**< Interrupt Controller + Type Register */ +#define XSCUGIC_DIST_IDENT_OFFSET 0x00000008U /**< Implementor ID + Register */ +#define XSCUGIC_SECURITY_OFFSET 0x00000080U /**< Interrupt Security + Register */ +#define XSCUGIC_ENABLE_SET_OFFSET 0x00000100U /**< Enable Set + Register */ +#define XSCUGIC_DISABLE_OFFSET 0x00000180U /**< Enable Clear Register */ +#define XSCUGIC_PENDING_SET_OFFSET 0x00000200U /**< Pending Set + Register */ +#define XSCUGIC_PENDING_CLR_OFFSET 0x00000280U /**< Pending Clear + Register */ +#define XSCUGIC_ACTIVE_OFFSET 0x00000300U /**< Active Status Register */ +#define XSCUGIC_PRIORITY_OFFSET 0x00000400U /**< Priority Level Register */ +#define XSCUGIC_SPI_TARGET_OFFSET 0x00000800U /**< SPI Target + Register 0x800-0x8FB */ +#define XSCUGIC_INT_CFG_OFFSET 0x00000C00U /**< Interrupt Configuration + Register 0xC00-0xCFC */ +#define XSCUGIC_PPI_STAT_OFFSET 0x00000D00U /**< PPI Status Register */ +#define XSCUGIC_SPI_STAT_OFFSET 0x00000D04U /**< SPI Status Register + 0xd04-0xd7C */ +#define XSCUGIC_AHB_CONFIG_OFFSET 0x00000D80U /**< AHB Configuration + Register */ +#define XSCUGIC_SFI_TRIG_OFFSET 0x00000F00U /**< Software Triggered + Interrupt Register */ +#define XSCUGIC_PERPHID_OFFSET 0x00000FD0U /**< Peripheral ID Reg */ +#if defined (versal) && !defined(ARMR5) +#define XSCUGIC_PCELLID_OFFSET 0x0000FFF0U /**< Pcell ID Register */ +#else +#define XSCUGIC_PCELLID_OFFSET 0x00000FF0U /**< Pcell ID Register */ +#endif +/* @} */ + +/** @name Distributor Enable Register + * Controls if the distributor response to external interrupt inputs. + * @{ + */ +#if defined (versal) && !defined(ARMR5) +#define XSCUGIC_EN_INT_MASK 0x00000003U /**< Interrupt In Enable */ +#else +#define XSCUGIC_EN_INT_MASK 0x00000001U /**< Interrupt In Enable */ +#endif +/* @} */ + +/** @name Interrupt Controller Type Register + * @{ + */ +#define XSCUGIC_LSPI_MASK 0x0000F800U /**< Number of Lockable + Shared Peripheral + Interrupts*/ +#define XSCUGIC_DOMAIN_MASK 0x00000400U /**< Number os Security domains*/ +#define XSCUGIC_CPU_NUM_MASK 0x000000E0U /**< Number of CPU Interfaces */ +#define XSCUGIC_NUM_INT_MASK 0x0000001FU /**< Number of Interrupt IDs */ +/* @} */ + +/** @name Implementor ID Register + * Implementor and revision information. + * @{ + */ +#define XSCUGIC_REV_MASK 0x00FFF000U /**< Revision Number */ +#define XSCUGIC_IMPL_MASK 0x00000FFFU /**< Implementor */ +/* @} */ + +/** @name Interrupt Security Registers + * Each bit controls the security level of an interrupt, either secure or non + * secure. These registers can only be accessed using secure read and write. + * There are registers for each of the CPU interfaces at offset 0x080. A + * register set for the SPI interrupts is available to all CPU interfaces. + * There are up to 32 of these registers staring at location 0x084. + * @{ + */ +#define XSCUGIC_INT_NS_MASK 0x00000001U /**< Each bit corresponds to an + INT_ID */ +/* @} */ + +/** @name Enable Set Register + * Each bit controls the enabling of an interrupt, a 0 is disabled, a 1 is + * enabled. Writing a 0 has no effect. Use the ENABLE_CLR register to set a + * bit to 0. + * There are registers for each of the CPU interfaces at offset 0x100. With up + * to 8 registers aliased to the same address. A register set for the SPI + * interrupts is available to all CPU interfaces. + * There are up to 32 of these registers staring at location 0x104. + * @{ + */ +#define XSCUGIC_INT_EN_MASK 0x00000001U /**< Each bit corresponds to an + INT_ID */ +/* @} */ + +/** @name Enable Clear Register + * Each bit controls the disabling of an interrupt, a 0 is disabled, a 1 is + * enabled. Writing a 0 has no effect. Writing a 1 disables an interrupt and + * sets the corresponding bit to 0. + * There are registers for each of the CPU interfaces at offset 0x180. With up + * to 8 registers aliased to the same address. + * A register set for the SPI interrupts is available to all CPU interfaces. + * There are up to 32 of these registers staring at location 0x184. + * @{ + */ +#define XSCUGIC_INT_CLR_MASK 0x00000001U /**< Each bit corresponds to an + INT_ID */ +/* @} */ + +/** @name Pending Set Register + * Each bit controls the Pending or Active and Pending state of an interrupt, a + * 0 is not pending, a 1 is pending. Writing a 0 has no effect. Writing a 1 sets + * an interrupt to the pending state. + * There are registers for each of the CPU interfaces at offset 0x200. With up + * to 8 registers aliased to the same address. + * A register set for the SPI interrupts is available to all CPU interfaces. + * There are up to 32 of these registers staring at location 0x204. + * @{ + */ +#define XSCUGIC_PEND_SET_MASK 0x00000001U /**< Each bit corresponds to an + INT_ID */ +/* @} */ + +/** @name Pending Clear Register + * Each bit can clear the Pending or Active and Pending state of an interrupt, a + * 0 is not pending, a 1 is pending. Writing a 0 has no effect. Writing a 1 + * clears the pending state of an interrupt. + * There are registers for each of the CPU interfaces at offset 0x280. With up + * to 8 registers aliased to the same address. + * A register set for the SPI interrupts is available to all CPU interfaces. + * There are up to 32 of these registers staring at location 0x284. + * @{ + */ +#define XSCUGIC_PEND_CLR_MASK 0x00000001U /**< Each bit corresponds to an + INT_ID */ +/* @} */ + +/** @name Active Status Register + * Each bit provides the Active status of an interrupt, a + * 0 is not Active, a 1 is Active. This is a read only register. + * There are registers for each of the CPU interfaces at offset 0x300. With up + * to 8 registers aliased to each address. + * A register set for the SPI interrupts is available to all CPU interfaces. + * There are up to 32 of these registers staring at location 0x380. + * @{ + */ +#define XSCUGIC_ACTIVE_MASK 0x00000001U /**< Each bit corresponds to an + INT_ID */ +/* @} */ + +/** @name Priority Level Register + * Each byte in a Priority Level Register sets the priority level of an + * interrupt. Reading the register provides the priority level of an interrupt. + * There are registers for each of the CPU interfaces at offset 0x400 through + * 0x41C. With up to 8 registers aliased to each address. + * 0 is highest priority, 0xFF is lowest. + * A register set for the SPI interrupts is available to all CPU interfaces. + * There are up to 255 of these registers staring at location 0x420. + * @{ + */ +#define XSCUGIC_PRIORITY_MASK 0x000000FFU /**< Each Byte corresponds to an + INT_ID */ +#define XSCUGIC_PRIORITY_MAX 0x000000FFU /**< Highest value of a priority + actually the lowest priority*/ +/* @} */ + +/** @name SPI Target Register 0x800-0x8FB + * Each byte references a separate SPI and programs which of the up to 8 CPU + * interfaces are sent a Pending interrupt. + * There are registers for each of the CPU interfaces at offset 0x800 through + * 0x81C. With up to 8 registers aliased to each address. + * A register set for the SPI interrupts is available to all CPU interfaces. + * There are up to 255 of these registers staring at location 0x820. + * + * This driver does not support multiple CPU interfaces. These are included + * for complete documentation. + * @{ + */ +#define XSCUGIC_SPI_CPU7_MASK 0x00000080U /**< CPU 7 Mask*/ +#define XSCUGIC_SPI_CPU6_MASK 0x00000040U /**< CPU 6 Mask*/ +#define XSCUGIC_SPI_CPU5_MASK 0x00000020U /**< CPU 5 Mask*/ +#define XSCUGIC_SPI_CPU4_MASK 0x00000010U /**< CPU 4 Mask*/ +#define XSCUGIC_SPI_CPU3_MASK 0x00000008U /**< CPU 3 Mask*/ +#define XSCUGIC_SPI_CPU2_MASK 0x00000004U /**< CPU 2 Mask*/ +#define XSCUGIC_SPI_CPU1_MASK 0x00000002U /**< CPU 1 Mask*/ +#define XSCUGIC_SPI_CPU0_MASK 0x00000001U /**< CPU 0 Mask*/ +/* @} */ + +/** @name Interrupt Configuration Register 0xC00-0xCFC + * The interrupt configuration registers program an SFI to be active HIGH level + * sensitive or rising edge sensitive. + * Each bit pair describes the configuration for an INT_ID. + * SFI Read Only b10 always + * PPI Read Only depending on how the PPIs are configured. + * b01 Active HIGH level sensitive + * b11 Rising edge sensitive + * SPI LSB is read only. + * b01 Active HIGH level sensitive + * b11 Rising edge sensitive/ + * There are registers for each of the CPU interfaces at offset 0xC00 through + * 0xC04. With up to 8 registers aliased to each address. + * A register set for the SPI interrupts is available to all CPU interfaces. + * There are up to 255 of these registers staring at location 0xC08. + * @{ + */ +#define XSCUGIC_INT_CFG_MASK 0x00000003U /**< */ +/* @} */ + +/** @name PPI Status Register + * Enables an external AMBA master to access the status of the PPI inputs. + * A CPU can only read the status of its local PPI signals and cannot read the + * status for other CPUs. + * This register is aliased for each CPU interface. + * @{ + */ +#define XSCUGIC_PPI_C15_MASK 0x00008000U /**< PPI Status */ +#define XSCUGIC_PPI_C14_MASK 0x00004000U /**< PPI Status */ +#define XSCUGIC_PPI_C13_MASK 0x00002000U /**< PPI Status */ +#define XSCUGIC_PPI_C12_MASK 0x00001000U /**< PPI Status */ +#define XSCUGIC_PPI_C11_MASK 0x00000800U /**< PPI Status */ +#define XSCUGIC_PPI_C10_MASK 0x00000400U /**< PPI Status */ +#define XSCUGIC_PPI_C09_MASK 0x00000200U /**< PPI Status */ +#define XSCUGIC_PPI_C08_MASK 0x00000100U /**< PPI Status */ +#define XSCUGIC_PPI_C07_MASK 0x00000080U /**< PPI Status */ +#define XSCUGIC_PPI_C06_MASK 0x00000040U /**< PPI Status */ +#define XSCUGIC_PPI_C05_MASK 0x00000020U /**< PPI Status */ +#define XSCUGIC_PPI_C04_MASK 0x00000010U /**< PPI Status */ +#define XSCUGIC_PPI_C03_MASK 0x00000008U /**< PPI Status */ +#define XSCUGIC_PPI_C02_MASK 0x00000004U /**< PPI Status */ +#define XSCUGIC_PPI_C01_MASK 0x00000002U /**< PPI Status */ +#define XSCUGIC_PPI_C00_MASK 0x00000001U /**< PPI Status */ +/* @} */ + +/** @name SPI Status Register 0xd04-0xd7C + * Enables an external AMBA master to access the status of the SPI inputs. + * There are up to 63 registers if the maximum number of SPI inputs are + * configured. + * @{ + */ +#define XSCUGIC_SPI_N_MASK 0x00000001U /**< Each bit corresponds to an SPI + input */ +/* @} */ + +/** @name AHB Configuration Register + * Provides the status of the CFGBIGEND input signal and allows the endianess + * of the GIC to be set. + * @{ + */ +#define XSCUGIC_AHB_END_MASK 0x00000004U /**< 0-GIC uses little Endian, + 1-GIC uses Big Endian */ +#define XSCUGIC_AHB_ENDOVR_MASK 0x00000002U /**< 0-Uses CFGBIGEND control, + 1-use the AHB_END bit */ +#define XSCUGIC_AHB_TIE_OFF_MASK 0x00000001U /**< State of CFGBIGEND */ + +/* @} */ + +/** @name Software Triggered Interrupt Register + * Controls issueing of software interrupts. + * @{ + */ +#define XSCUGIC_SFI_SELFTRIG_MASK 0x02010000U +#define XSCUGIC_SFI_TRIG_TRGFILT_MASK 0x03000000U /**< Target List filter + b00-Use the target List + b01-All CPUs except requester + b10-To Requester + b11-reserved */ +#define XSCUGIC_SFI_TRIG_CPU_MASK 0x00FF0000U /**< CPU Target list */ +#define XSCUGIC_SFI_TRIG_SATT_MASK 0x00008000U /**< 0= Use a secure interrupt */ +#define XSCUGIC_SFI_TRIG_INTID_MASK 0x0000000FU /**< Set to the INTID + signaled to the CPU*/ +/* @} */ + +/** @name CPU Interface Register Map + * + * Define the offsets from the base address for all CPU registers of the + * interrupt controller, some registers may be reserved in the hardware device. + * @{ + */ +#define XSCUGIC_CONTROL_OFFSET 0x00000000U /**< CPU Interface Control + Register */ +#define XSCUGIC_CPU_PRIOR_OFFSET 0x00000004U /**< Priority Mask Reg */ +#define XSCUGIC_BIN_PT_OFFSET 0x00000008U /**< Binary Point Register */ +#define XSCUGIC_INT_ACK_OFFSET 0x0000000CU /**< Interrupt ACK Reg */ +#define XSCUGIC_EOI_OFFSET 0x00000010U /**< End of Interrupt Reg */ +#define XSCUGIC_RUN_PRIOR_OFFSET 0x00000014U /**< Running Priority Reg */ +#define XSCUGIC_HI_PEND_OFFSET 0x00000018U /**< Highest Pending Interrupt + Register */ +#define XSCUGIC_ALIAS_BIN_PT_OFFSET 0x0000001CU /**< Aliased non-Secure + Binary Point Register */ + +/**< 0x00000020 to 0x00000FBC are reserved and should not be read or written + * to. */ +/* @} */ + + +/** @name Control Register + * CPU Interface Control register definitions + * All bits are defined here although some are not available in the non-secure + * mode. + * @{ + */ +#define XSCUGIC_CNTR_SBPR_MASK 0x00000010U /**< Secure Binary Pointer, + 0=separate registers, + 1=both use bin_pt_s */ +#define XSCUGIC_CNTR_FIQEN_MASK 0x00000008U /**< Use nFIQ_C for secure + interrupts, + 0= use IRQ for both, + 1=Use FIQ for secure, IRQ for non*/ +#define XSCUGIC_CNTR_ACKCTL_MASK 0x00000004U /**< Ack control for secure or non secure */ +#define XSCUGIC_CNTR_EN_NS_MASK 0x00000002U /**< Non Secure enable */ +#define XSCUGIC_CNTR_EN_S_MASK 0x00000001U /**< Secure enable, 0=Disabled, 1=Enabled */ +/* @} */ + +/** @name Priority Mask Register + * Priority Mask register definitions + * The CPU interface does not send interrupt if the level of the interrupt is + * lower than the level of the register. + * @{ + */ +/*#define XSCUGIC_PRIORITY_MASK 0x000000FFU*/ /**< All interrupts */ +/* @} */ + +/** @name Binary Point Register + * Binary Point register definitions + * @{ + */ + +#define XSCUGIC_BIN_PT_MASK 0x00000007U /**< Binary point mask value + Value Secure Non-secure + b000 0xFE 0xFF + b001 0xFC 0xFE + b010 0xF8 0xFC + b011 0xF0 0xF8 + b100 0xE0 0xF0 + b101 0xC0 0xE0 + b110 0x80 0xC0 + b111 0x00 0x80 + */ +/*@}*/ + +/** @name Interrupt Acknowledge Register + * Interrupt Acknowledge register definitions + * Identifies the current Pending interrupt, and the CPU ID for software + * interrupts. + */ +#define XSCUGIC_ACK_INTID_MASK 0x000003FFU /**< Interrupt ID */ +#define XSCUGIC_CPUID_MASK 0x00000C00U /**< CPU ID */ +/* @} */ + +/** @name End of Interrupt Register + * End of Interrupt register definitions + * Allows the CPU to signal the GIC when it completes an interrupt service + * routine. + */ +#define XSCUGIC_EOI_INTID_MASK 0x000003FFU /**< Interrupt ID */ + +/* @} */ + +/** @name Running Priority Register + * Running Priority register definitions + * Identifies the interrupt priority level of the highest priority active + * interrupt. + */ +#define XSCUGIC_RUN_PRIORITY_MASK 0x000000FFU /**< Interrupt Priority */ +/* @} */ + +#if defined (versal) && !defined(ARMR5) +#define XSCUGIC_IROUTER_BASE_OFFSET 0x6000U +#endif +/* + * Highest Pending Interrupt register definitions + * Identifies the interrupt priority of the highest priority pending interupt + */ +#define XSCUGIC_PEND_INTID_MASK 0x000003FFU /**< Pending Interrupt ID */ +/*#define XSCUGIC_CPUID_MASK 0x00000C00U */ /**< CPU ID */ +/* @} */ +#if defined (versal) && !defined(ARMR5) +/** @name ReDistributor Interface Register Map + * + * @{ + */ +#define XSCUGIC_RDIST_OFFSET 0x80000U +#define XSCUGIC_RDIST_BASE_ADDRESS (XPAR_SCUGIC_0_DIST_BASEADDR + XSCUGIC_RDIST_OFFSET) +#define XSCUGIC_RDIST_SGI_PPI_OFFSET 0x90000U +#define XSCUGIC_RDIST_SGI_PPI_BASE_ADDRESS (XPAR_SCUGIC_0_DIST_BASEADDR + XSCUGIC_RDIST_SGI_PPI_OFFSET) +#define XSCUGIC_RDIST_ISENABLE_OFFSET 0x100U +#define XSCUGIC_RDIST_IPRIORITYR_OFFSET 0x400U +#define XSCUGIC_RDIST_IGROUPR_OFFSET 0x80U +#define XSCUGIC_RDIST_GRPMODR_OFFSET 0xD00U +#define XSCUGIC_RDIST_INT_CONFIG_OFFSET 0xC00U +#define XSCUGIC_RDIST_WAKER_OFFSET 0x14U +#define XSCUGIC_SGIR_EL1_INITID_SHIFT 24U + +/* + * GICR_IGROUPR register definitions + */ +#if EL3 +#define XSCUGIC_DEFAULT_SECURITY 0x0U +#else +#define XSCUGIC_DEFAULT_SECURITY 0xFFFFFFFFU +#endif +/* + * GICR_WAKER register definitions + */ +#define XSCUGIC_RDIST_WAKER_LOW_POWER_STATE_MASK 0x7 +#endif +/***************** Macros (Inline Functions) Definitions *********************/ + +/****************************************************************************/ +/** +* +* Read the Interrupt Configuration Register offset for an interrupt id. +* +* @param InterruptID is the interrupt number. +* +* @return The 32-bit value of the offset +* +* @note +* +*****************************************************************************/ +#define XSCUGIC_INT_CFG_OFFSET_CALC(InterruptID) \ + ((u32)XSCUGIC_INT_CFG_OFFSET + (((InterruptID)/16U) * 4U)) + +/****************************************************************************/ +/** +* +* Read the Interrupt Priority Register offset for an interrupt id. +* +* @param InterruptID is the interrupt number. +* +* @return The 32-bit value of the offset +* +* @note +* +*****************************************************************************/ +#define XSCUGIC_PRIORITY_OFFSET_CALC(InterruptID) \ + ((u32)XSCUGIC_PRIORITY_OFFSET + (((InterruptID)/4U) * 4U)) + +/****************************************************************************/ +/** +* +* Read the Interrupt Routing Register offset for an interrupt id. +* +* @param InterruptID is the interrupt number. +* +* @return The 32-bit value of the offset +* +* @note +* +*****************************************************************************/ +#define XSCUGIC_IROUTER_OFFSET_CALC(InterruptID) \ + ((u32)XSCUGIC_IROUTER_BASE_OFFSET + (InterruptID * 8)) + +/****************************************************************************/ +/** +* +* Read the SPI Target Register offset for an interrupt id. +* +* @param InterruptID is the interrupt number. +* +* @return The 32-bit value of the offset +* +* @note +* +*****************************************************************************/ +#define XSCUGIC_SPI_TARGET_OFFSET_CALC(InterruptID) \ + ((u32)XSCUGIC_SPI_TARGET_OFFSET + (((InterruptID)/4U) * 4U)) +/****************************************************************************/ +/** +* +* Read the SPI Target Register offset for an interrupt id. +* +* @param InterruptID is the interrupt number. +* +* @return The 32-bit value of the offset +* +* @note +* +*****************************************************************************/ +#define XSCUGIC_SECURITY_TARGET_OFFSET_CALC(InterruptID) \ + ((u32)XSCUGIC_SECURITY_OFFSET + (((InterruptID)/32U)*4U)) + +/****************************************************************************/ +/** +* +* Read the Re-distributor Interrupt configuration register offset +* +* @param InterruptID is the interrupt number. +* +* @return The 32-bit value of the offset +* +* @note +* +*****************************************************************************/ +#define XSCUGIC_RDIST_INT_CONFIG_OFFSET_CALC(InterruptID) \ + ((u32)XSCUGIC_RDIST_INT_CONFIG_OFFSET + ((InterruptID /16)*4)) + +/****************************************************************************/ +/** +* +* Read the Re-distributor Interrupt Priority register offset +* +* @param InterruptID is the interrupt number. +* +* @return The 32-bit value of the offset +* +* @note +* +*****************************************************************************/ +#define XSCUGIC_RDIST_INT_PRIORITY_OFFSET_CALC(InterruptID) \ + ((u32)XSCUGIC_RDIST_IPRIORITYR_OFFSET + (InterruptID * 4)) +/****************************************************************************/ +/** +* +* Read the Interrupt Clear-Enable Register offset for an interrupt ID +* +* @param Register is the register offset for the clear/enable bank. +* @param InterruptID is the interrupt number. +* +* @return The 32-bit value of the offset +* +* @note +* +*****************************************************************************/ +#define XSCUGIC_EN_DIS_OFFSET_CALC(Register, InterruptID) \ + ((Register) + (((InterruptID)/32U) * 4U)) + +/****************************************************************************/ +/** +* +* Read the given Intc register. +* +* @param BaseAddress is the base address of the device. +* @param RegOffset is the register offset to be read +* +* @return The 32-bit value of the register +* +* @note +* C-style signature: +* u32 XScuGic_ReadReg(u32 BaseAddress, u32 RegOffset) +* +*****************************************************************************/ +#define XScuGic_ReadReg(BaseAddress, RegOffset) \ + (Xil_In32((BaseAddress) + (RegOffset))) + + +/****************************************************************************/ +/** +* +* Write the given Intc register. +* +* @param BaseAddress is the base address of the device. +* @param RegOffset is the register offset to be written +* @param Data is the 32-bit value to write to the register +* +* @return None. +* +* @note +* C-style signature: +* void XScuGic_WriteReg(u32 BaseAddress, u32 RegOffset, u32 Data) +* +*****************************************************************************/ +#define XScuGic_WriteReg(BaseAddress, RegOffset, Data) \ + (Xil_Out32(((BaseAddress) + (RegOffset)), ((u32)(Data)))) + + +/****************************************************************************/ +/** +* +* Enable specific interrupt(s) in the interrupt controller. +* +* @param DistBaseAddress is the Distributor Register base address of the +* device +* @param Int_Id is the ID of the interrupt source and should be in the +* range of 0 to XSCUGIC_MAX_NUM_INTR_INPUTS - 1 +* +* @return None. +* +* @note C-style signature: +* void XScuGic_EnableIntr(u32 DistBaseAddress, u32 Int_Id) +* +*****************************************************************************/ +#define XScuGic_EnableIntr(DistBaseAddress, Int_Id) \ + XScuGic_WriteReg((DistBaseAddress), \ + XSCUGIC_ENABLE_SET_OFFSET + (((Int_Id) / 32U) * 4U), \ + (0x00000001U << ((Int_Id) % 32U))) + +/****************************************************************************/ +/** +* +* Disable specific interrupt(s) in the interrupt controller. +* +* @param DistBaseAddress is the Distributor Register base address of the +* device +* @param Int_Id is the ID of the interrupt source and should be in the +* range of 0 to XSCUGIC_MAX_NUM_INTR_INPUTS - 1 +* +* +* @return None. +* +* @note C-style signature: +* void XScuGic_DisableIntr(u32 DistBaseAddress, u32 Int_Id) +* +*****************************************************************************/ +#define XScuGic_DisableIntr(DistBaseAddress, Int_Id) \ + XScuGic_WriteReg((DistBaseAddress), \ + XSCUGIC_DISABLE_OFFSET + (((Int_Id) / 32U) * 4U), \ + (0x00000001U << ((Int_Id) % 32U))) + + +/************************** Function Prototypes ******************************/ + +void XScuGic_DeviceInterruptHandler(void *DeviceId); +s32 XScuGic_DeviceInitialize(u32 DeviceId); +void XScuGic_RegisterHandler(u32 BaseAddress, s32 InterruptID, + Xil_InterruptHandler Handler, void *CallBackRef); +void XScuGic_SetPriTrigTypeByDistAddr(u32 DistBaseAddress, u32 Int_Id, + u8 Priority, u8 Trigger); +void XScuGic_GetPriTrigTypeByDistAddr(u32 DistBaseAddress, u32 Int_Id, + u8 *Priority, u8 *Trigger); +void XScuGic_InterruptUnmapFromCpuByDistAddr(u32 DistBaseAddress, + u8 Cpu_Id, u32 Int_Id); +void XScuGic_UnmapAllInterruptsFromCpuByDistAddr(u32 DistBaseAddress, + u8 Cpu_Id); +/************************** Variable Definitions *****************************/ +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/include/xscutimer.h b/datalink814_ge/bsp/ps7_cortexa9_0/include/xscutimer.h new file mode 100644 index 0000000..5434684 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/include/xscutimer.h @@ -0,0 +1,364 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xscutimer.h +* @addtogroup scutimer_v2_1 +* @{ +* @details +* +* The timer driver supports the Cortex A9 private timer. +* +* The timer driver supports the following features: +* - Normal mode and Auto reload mode +* - Interrupts (Interrupt handler is not provided in this driver. Application +* has to register it's own handler) +* +* Initialization and Configuration +* +* The device driver enables higher layer software (e.g., an application) to +* communicate with the Timer. +* +* XScuTimer_CfgInitialize() API is used to initialize the Timer. The +* user needs to first call the XScuTimer_LookupConfig() API which returns +* the Configuration structure pointer which is passed as a parameter to +* the XScuTimer_CfgInitialize() API. +* +* Interrupts +* +* The Timer hardware supports interrupts. +* +* This driver does not provide a Interrupt Service Routine (ISR) for the device. +* It is the responsibility of the application to provide one if needed. Refer to +* the interrupt example provided with this driver for details on using the +* Timer in interrupt mode. +* +* Virtual Memory +* +* This driver supports Virtual Memory. The RTOS is responsible for calculating +* the correct device base address in Virtual Memory space. +* +* Threads +* +* This driver is not thread safe. Any needs for threads or thread mutual +* exclusion must be satisfied by the layer above this driver. +* +* Asserts +* +* Asserts are used within all Xilinx drivers to enforce constraints on argument +* values. Asserts can be turned off on a system-wide basis by defining, at +* compile time, the NDEBUG identifier. By default, asserts are turned on and it +* is recommended that users leave asserts on during development. +* +* Building the driver +* +* The XScuTimer driver is composed of several source files. This allows the user +* to build and link only those parts of the driver that are necessary. +* +*

+* +* NOTE: +* The timer is not a part of the snoop control unit as indicated by the +* prefix "scu" in the name of the driver. +* It is an independent module in APU. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 1.00a nm  03/10/10 First release
+* 1.02a sg  07/17/12 Included xil_assert.h for CR 667947. This is an issue
+*		     when the xstatus.h in the common driver overwrites
+*		     the xstatus.h of the standalone BSP during the
+*		     libgen.
+* 2.1 	sk  02/26/15 Modified the code for MISRA-C:2012 compliance.
+*       ms  03/17/17 Added readme.txt file in examples folder for doxygen
+*                    generation.
+* 
+* +******************************************************************************/ +#ifndef XSCUTIMER_H /* prevent circular inclusions */ +#define XSCUTIMER_H /* by using protection macros */ + +/***************************** Include Files *********************************/ + +#include "xstatus.h" +#include "xscutimer_hw.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/** + * This typedef contains configuration information for the device. + */ +typedef struct { + u16 DeviceId; /**< Unique ID of device */ + u32 BaseAddr; /**< Base address of the device */ +} XScuTimer_Config; + +/** + * The XScuTimer driver instance data. The user is required to allocate a + * variable of this type for every timer device in the system. + * A pointer to a variable of this type is then passed to the driver API + * functions. + */ +typedef struct { + XScuTimer_Config Config; /**< Hardware Configuration */ + u32 IsReady; /**< Device is initialized and ready */ + u32 IsStarted; /**< Device timer is running */ +} XScuTimer; + +/***************** Macros (Inline Functions) Definitions *********************/ + +/****************************************************************************/ +/** +* +* Check if the timer has expired. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* +* @return +* - TRUE if the timer has expired. +* - FALSE if the timer has not expired. +* +* @note C-style signature: +* int XScuTimer_IsExpired(XScuTimer *InstancePtr) +* +******************************************************************************/ +#define XScuTimer_IsExpired(InstancePtr) \ + ((XScuTimer_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_ISR_OFFSET) & \ + XSCUTIMER_ISR_EVENT_FLAG_MASK) == \ + XSCUTIMER_ISR_EVENT_FLAG_MASK) + +/****************************************************************************/ +/** +* +* Re-start the timer. This macro will read the timer load register +* and writes the same value to load register to update the counter register. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_RestartTimer(XScuTimer *InstancePtr) +* +******************************************************************************/ +#define XScuTimer_RestartTimer(InstancePtr) \ + XScuTimer_LoadTimer((InstancePtr), \ + XScuTimer_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_LOAD_OFFSET)) + +/****************************************************************************/ +/** +* +* Write to the timer load register. This will also update the +* timer counter register with the new value. This macro can be used to +* change the time-out value. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* @param Value is the count to be loaded in to the load register. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_LoadTimer(XScuTimer *InstancePtr, u32 Value) +* +******************************************************************************/ +#define XScuTimer_LoadTimer(InstancePtr, Value) \ + XScuTimer_WriteReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_LOAD_OFFSET, (Value)) + +/****************************************************************************/ +/** +* +* Returns the current timer counter register value. It can be called at any +* time. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* +* @return Contents of the timer counter register. +* +* @note C-style signature: + u32 XScuTimer_GetCounterValue(XScuTimer *InstancePtr) +* +******************************************************************************/ +#define XScuTimer_GetCounterValue(InstancePtr) \ + XScuTimer_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_COUNTER_OFFSET) + +/****************************************************************************/ +/** +* +* Enable auto-reload mode. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_EnableAutoReload(XScuTimer *InstancePtr) +* +******************************************************************************/ +#define XScuTimer_EnableAutoReload(InstancePtr) \ + XScuTimer_WriteReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_CONTROL_OFFSET, \ + (XScuTimer_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_CONTROL_OFFSET) | \ + XSCUTIMER_CONTROL_AUTO_RELOAD_MASK)) + +/****************************************************************************/ +/** +* +* Disable auto-reload mode. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_DisableAutoReload(XScuTimer *InstancePtr) +* +******************************************************************************/ +#define XScuTimer_DisableAutoReload(InstancePtr) \ + XScuTimer_WriteReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_CONTROL_OFFSET, \ + (XScuTimer_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_CONTROL_OFFSET) & \ + ~(XSCUTIMER_CONTROL_AUTO_RELOAD_MASK))) + +/****************************************************************************/ +/** +* +* Enable the Timer interrupt. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_EnableInterrupt(XScuTimer *InstancePtr) +* +******************************************************************************/ +#define XScuTimer_EnableInterrupt(InstancePtr) \ + XScuTimer_WriteReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_CONTROL_OFFSET, \ + (XScuTimer_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_CONTROL_OFFSET) | \ + XSCUTIMER_CONTROL_IRQ_ENABLE_MASK)) + +/****************************************************************************/ +/** +* +* Disable the Timer interrupt. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_DisableInterrupt(XScuTimer *InstancePtr) +* +******************************************************************************/ +#define XScuTimer_DisableInterrupt(InstancePtr) \ + XScuTimer_WriteReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_CONTROL_OFFSET, \ + (XScuTimer_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_CONTROL_OFFSET) & \ + ~(XSCUTIMER_CONTROL_IRQ_ENABLE_MASK))) + +/*****************************************************************************/ +/** +* +* This function reads the interrupt status. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_GetInterruptStatus(XScuTimer *InstancePtr) +* +******************************************************************************/ +#define XScuTimer_GetInterruptStatus(InstancePtr) \ + XScuTimer_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_ISR_OFFSET) + +/*****************************************************************************/ +/** +* +* This function clears the interrupt status. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_ClearInterruptStatus(XScuTimer *InstancePtr) +* +******************************************************************************/ +#define XScuTimer_ClearInterruptStatus(InstancePtr) \ + XScuTimer_WriteReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_ISR_OFFSET, XSCUTIMER_ISR_EVENT_FLAG_MASK) + +/************************** Function Prototypes ******************************/ + +/* + * Lookup configuration in xscutimer_sinit.c + */ +XScuTimer_Config *XScuTimer_LookupConfig(u16 DeviceId); + +/* + * Selftest function in xscutimer_selftest.c + */ +s32 XScuTimer_SelfTest(XScuTimer *InstancePtr); + +/* + * Interface functions in xscutimer.c + */ +s32 XScuTimer_CfgInitialize(XScuTimer *InstancePtr, + XScuTimer_Config *ConfigPtr, u32 EffectiveAddress); +void XScuTimer_Start(XScuTimer *InstancePtr); +void XScuTimer_Stop(XScuTimer *InstancePtr); +void XScuTimer_SetPrescaler(XScuTimer *InstancePtr, u8 PrescalerValue); +u8 XScuTimer_GetPrescaler(XScuTimer *InstancePtr); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/include/xscutimer_hw.h b/datalink814_ge/bsp/ps7_cortexa9_0/include/xscutimer_hw.h new file mode 100644 index 0000000..d577784 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/include/xscutimer_hw.h @@ -0,0 +1,283 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xscutimer_hw.h +* @addtogroup scutimer_v2_1 +* @{ +* +* This file contains the hardware interface to the Timer. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 1.00a nm  03/10/10 First release
+* 1.01a sdm 02/02/12 Added low level macros to read/write load, counter, control
+*		     and interrupt registers
+* 1.02a  sg 07/17/12 Included xil_assert.h for CR 667947. This is an issue
+*		     when the xstatus.h in the common driver overwrites
+*		     the xstatus.h of the standalone BSP during the
+*		     libgen.
+* 2.1 	sk  02/26/15 Modified the code for MISRA-C:2012 compliance.
+* 
+* +******************************************************************************/ +#ifndef XSCUTIMER_HW_H /* prevent circular inclusions */ +#define XSCUTIMER_HW_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ +#include "xil_types.h" +#include "xil_io.h" +#include "xil_assert.h" +/************************** Constant Definitions *****************************/ + +/** @name Register Map + * Offsets of registers from the start of the device + * @{ + */ + +#define XSCUTIMER_LOAD_OFFSET 0x00U /**< Timer Load Register */ +#define XSCUTIMER_COUNTER_OFFSET 0x04U /**< Timer Counter Register */ +#define XSCUTIMER_CONTROL_OFFSET 0x08U /**< Timer Control Register */ +#define XSCUTIMER_ISR_OFFSET 0x0CU /**< Timer Interrupt + Status Register */ +/* @} */ + +/** @name Timer Control register + * This register bits control the prescaler, Intr enable, + * auto-reload and timer enable. + * @{ + */ + +#define XSCUTIMER_CONTROL_PRESCALER_MASK 0x0000FF00U /**< Prescaler */ +#define XSCUTIMER_CONTROL_PRESCALER_SHIFT 8U +#define XSCUTIMER_CONTROL_IRQ_ENABLE_MASK 0x00000004U /**< Intr enable */ +#define XSCUTIMER_CONTROL_AUTO_RELOAD_MASK 0x00000002U /**< Auto-reload */ +#define XSCUTIMER_CONTROL_ENABLE_MASK 0x00000001U /**< Timer enable */ +/* @} */ + +/** @name Interrupt Status register + * This register indicates the Timer counter register has reached zero. + * @{ + */ + +#define XSCUTIMER_ISR_EVENT_FLAG_MASK 0x00000001U /**< Event flag */ +/*@}*/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/****************************************************************************/ +/** +* +* Write to the timer load register. This will also update the +* timer counter register with the new value. This macro can be used to +* change the time-out value. +* +* @param BaseAddr is the base address of the scu timer. +* @param Value is the count to be loaded in to the load register. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_SetLoadReg(u32 BaseAddr, u32 Value) +* +******************************************************************************/ +#define XScuTimer_SetLoadReg(BaseAddr, Value) \ + XScuTimer_WriteReg(BaseAddr, XSCUTIMER_LOAD_OFFSET, (Value)) + +/****************************************************************************/ +/** +* +* Returns the current timer load register value. +* +* @param BaseAddr is the base address of the scu timer. +* +* @return Contents of the timer load register. +* +* @note C-style signature: +* u32 XScuTimer_GetLoadReg(u32 BaseAddr) +* +******************************************************************************/ +#define XScuTimer_GetLoadReg(BaseAddr) \ + XScuTimer_ReadReg(BaseAddr, XSCUTIMER_LOAD_OFFSET) + +/****************************************************************************/ +/** +* +* Write to the timer counter register. +* +* @param BaseAddr is the base address of the scu timer. +* @param Value is the count to be loaded in to the counter register. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_SetCounterReg(u32 BaseAddr, u32 Value) +* +******************************************************************************/ +#define XScuTimer_SetCounterReg(BaseAddr, Value) \ + XScuTimer_WriteReg(BaseAddr, XSCUTIMER_COUNTER_OFFSET, (Value)) + +/****************************************************************************/ +/** +* +* Returns the current timer counter register value. +* +* @param BaseAddr is the base address of the scu timer. +* +* @return Contents of the timer counter register. +* +* @note C-style signature: + u32 XScuTimer_GetCounterReg(u32 BaseAddr) +* +******************************************************************************/ +#define XScuTimer_GetCounterReg(BaseAddr) \ + XScuTimer_ReadReg(BaseAddr, XSCUTIMER_COUNTER_OFFSET) + +/****************************************************************************/ +/** +* +* Write to the timer load register. This will also update the +* timer counter register with the new value. This macro can be used to +* change the time-out value. +* +* @param BaseAddr is the base address of the scu timer. +* @param Value is the count to be loaded in to the load register. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_SetControlReg(u32 BaseAddr, u32 Value) +* +******************************************************************************/ +#define XScuTimer_SetControlReg(BaseAddr, Value) \ + XScuTimer_WriteReg(BaseAddr, XSCUTIMER_CONTROL_OFFSET, (Value)) + +/****************************************************************************/ +/** +* +* Returns the current timer load register value. +* +* @param BaseAddr is the base address of the scu timer. +* +* @return Contents of the timer load register. +* +* @note C-style signature: + u32 XScuTimer_GetControlReg(u32 BaseAddr) +* +******************************************************************************/ +#define XScuTimer_GetControlReg(BaseAddr) \ + XScuTimer_ReadReg(BaseAddr, XSCUTIMER_CONTROL_OFFSET) + +/****************************************************************************/ +/** +* +* Write to the timer counter register. +* +* @param BaseAddr is the base address of the scu timer. +* @param Value is the count to be loaded in to the counter register. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_SetIntrReg(u32 BaseAddr, u32 Value) +* +******************************************************************************/ +#define XScuTimer_SetIntrReg(BaseAddr, Value) \ + XScuTimer_WriteReg(BaseAddr, XSCUTIMER_ISR_OFFSET, (Value)) + +/****************************************************************************/ +/** +* +* Returns the current timer counter register value. +* +* @param BaseAddr is the base address of the scu timer. +* +* @return Contents of the timer counter register. +* +* @note C-style signature: + u32 XScuTimer_GetIntrReg(u32 BaseAddr) +* +******************************************************************************/ +#define XScuTimer_GetIntrReg(BaseAddr) \ + XScuTimer_ReadReg(BaseAddr, XSCUTIMER_ISR_OFFSET) + +/****************************************************************************/ +/** +* +* Read from the given Timer register. +* +* @param BaseAddr is the base address of the device +* @param RegOffset is the register offset to be read +* +* @return The 32-bit value of the register +* +* @note C-style signature: +* u32 XScuTimer_ReadReg(u32 BaseAddr, u32 RegOffset) +* +*****************************************************************************/ +#define XScuTimer_ReadReg(BaseAddr, RegOffset) \ + Xil_In32((BaseAddr) + (RegOffset)) + +/****************************************************************************/ +/** +* +* Write to the given Timer register. +* +* @param BaseAddr is the base address of the device +* @param RegOffset is the register offset to be written +* @param Data is the 32-bit value to write to the register +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_WriteReg(u32 BaseAddr, u32 RegOffset, u32 Data) +* +*****************************************************************************/ +#define XScuTimer_WriteReg(BaseAddr, RegOffset, Data) \ + Xil_Out32((BaseAddr) + (RegOffset), (Data)) + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/include/xscuwdt.h b/datalink814_ge/bsp/ps7_cortexa9_0/include/xscuwdt.h new file mode 100644 index 0000000..551eaf5 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/include/xscuwdt.h @@ -0,0 +1,379 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xscuwdt.h +* @addtogroup scuwdt_v2_1 +* @{ +* @details +* +* The Xilinx SCU watchdog timer driver (XScuWdt) supports the Xilinx SCU private +* watchdog timer hardware. +* +* The XScuWdt driver supports the following features: +* - Watchdog mode +* - Timer mode +* - Auto reload (timer mode only) +* +* The watchdog counter register is a down counter and starts decrementing when +* the watchdog is started. +* In watchdog mode, when the counter reaches 0, the Reset flag is set in the +* Reset status register and the WDRESETREQ pin is asserted, causing a system +* reset. The Reset flag is not reset by normal processor reset and is cleared +* when written with a value of 1. This enables the user to differentiate a +* normal reset and a reset caused by watchdog time-out. The user needs to call +* XScuWdt_RestartWdt() periodically, to avoid the watchdog from being timed-out. +* +* The IsWdtExpired function can be used to check if the watchdog was the cause +* of the last reset. In this situation, call Initialize then call IsWdtExpired. +* If the result is true, watchdog timeout caused the last system reset. The +* application then needs to clear the Reset flag. +* +* In timer mode, when the counter reaches 0, the Event flag is set in the +* Interrupt status register and if interrupts are enabled, interrupt ID 30 is +* set as pending in the interrupt distributor. The IsTimerExpired function +* is used to check if the watchdog counter has decremented to 0 in timer mode. +* If auto-reload mode is enabled, the Counter register is automatically reloaded +* from the Load register. +* +* Initialization and Configuration +* +* The device driver enables higher layer software (e.g., an application) to +* communicate with the Watchdog Timer. +* +* XScuWdt_CfgInitialize() API is used to initialize the Watchdog Timer. The +* user needs to first call the XScuWdt_LookupConfig() API which returns +* the Configuration structure pointer which is passed as a parameter to +* the XScuWdt_CfgInitialize() API. +* +* Interrupts +* +* The SCU Watchdog Timer supports interrupts in Timer mode. +* +* This driver does not provide a Interrupt Service Routine (ISR) for the device. +* It is the responsibility of the application to provide one if needed. Refer to +* the interrupt example provided with this driver for details on using the +* Timer in interrupt mode. +* +* Virtual Memory +* +* This driver supports Virtual Memory. The RTOS is responsible for calculating +* the correct device base address in Virtual Memory space. +* +* Threads +* +* This driver is not thread safe. Any needs for threads or thread mutual +* exclusion must be satisfied by the layer above this driver. +* +* Asserts +* +* Asserts are used within all Xilinx drivers to enforce constraints on argument +* values. Asserts can be turned off on a system-wide basis by defining, at +* compile time, the NDEBUG identifier. By default, asserts are turned on and it +* is recommended that users leave asserts on during development. +* +* Building the driver +* +* The XScuWdt driver is composed of several source files. This allows the user +* to build and link only those parts of the driver that are necessary. +* +*

+* +* NOTE: +* The watchdog timer is not a part of the snoop control unit as indicated +* by the prefix "scu" in the name of the driver. +* It is an independent module in APU. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 1.00a sdm 01/15/10 First release
+* 1.02a  sg 07/17/12 Included xil_assert.h for CR 667947. This is an issue
+*		     when the xstatus.h in the common driver overwrites
+*		     the xstatus.h of the standalone BSP during the
+*		     libgen.
+* 2.1 	sk  02/26/15 Modified the code for MISRA-C:2012 compliance.
+*       ms  03/17/17 Added readme.txt file in examples folder for doxygen
+*                    generation.
+* 
+* +******************************************************************************/ +#ifndef XSCUWDT_H /* prevent circular inclusions */ +#define XSCUWDT_H /* by using protection macros */ + +/***************************** Include Files *********************************/ + +#include "xstatus.h" +#include "xscuwdt_hw.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/** + * This typedef contains configuration information for the device. + */ +typedef struct { + u16 DeviceId; /**< Unique ID of device */ + u32 BaseAddr; /**< Base address of the device */ +} XScuWdt_Config; + +/** + * The XScuWdt driver instance data. The user is required to allocate a + * variable of this type for every watchdog/timer device in the system. + * A pointer to a variable of this type is then passed to the driver API + * functions. + */ +typedef struct { + XScuWdt_Config Config;/**< Hardware Configuration */ + u32 IsReady; /**< Device is initialized and ready */ + u32 IsStarted; /**< Device watchdog timer is running */ +} XScuWdt; + +/***************** Macros (Inline Functions) Definitions *********************/ +/****************************************************************************/ +/** +* +* This function is used to check if the watchdog has timed-out and the last +* reset was caused by the watchdog reset. +* +* @param InstancePtr is a pointer to the XScuWdt instance. +* +* @return +* - TRUE if the watchdog has expired. +* - FALSE if the watchdog has not expired. +* +* @note C-style signature: +* int XScuWdt_IsWdtExpired(XScuWdt *InstancePtr) +* +******************************************************************************/ +#define XScuWdt_IsWdtExpired(InstancePtr) \ + ((XScuWdt_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUWDT_RST_STS_OFFSET) & \ + XSCUWDT_RST_STS_RESET_FLAG_MASK) == XSCUWDT_RST_STS_RESET_FLAG_MASK) + +/****************************************************************************/ +/** +* +* This function is used to check if the watchdog counter has reached 0 in timer +* mode. +* +* @param InstancePtr is a pointer to the XScuWdt instance. +* +* @return +* - TRUE if the watchdog has expired. +* - FALSE if the watchdog has not expired. +* +* @note C-style signature: +* int XScuWdt_IsTimerExpired(XScuWdt *InstancePtr) +* +******************************************************************************/ +#define XScuWdt_IsTimerExpired(InstancePtr) \ + ((XScuWdt_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUWDT_ISR_OFFSET) & \ + XSCUWDT_ISR_EVENT_FLAG_MASK) == XSCUWDT_ISR_EVENT_FLAG_MASK) + +/****************************************************************************/ +/** +* +* Re-start the watchdog timer. This macro will read the watchdog load register +* and write the same value to load register to update the counter register. +* An application needs to call this function periodically to keep the watchdog +* from asserting the WDRESETREQ reset request output pin. +* +* @param InstancePtr is a pointer to the XScuWdt instance. +* +* @return None. +* +* @note C-style signature: +* void XScuWdt_RestartWdt(XScuWdt *InstancePtr) +* +******************************************************************************/ +#define XScuWdt_RestartWdt(InstancePtr) \ + XScuWdt_LoadWdt((InstancePtr), \ + (XScuWdt_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUWDT_LOAD_OFFSET))) + +/****************************************************************************/ +/** +* +* Write to the watchdog timer load register. This will also update the +* watchdog counter register with the new value. This macro can be used to +* change the time-out value. +* +* @param InstancePtr is a pointer to the XScuWdt instance. +* @param Value is the value to be written to the Watchdog Load register. +* +* @return None. +* +* @note C-style signature: +* void XScuWdt_LoadWdt(XScuWdt *InstancePtr, u32 Value) +* +******************************************************************************/ +#define XScuWdt_LoadWdt(InstancePtr, Value) \ + XScuWdt_WriteReg((InstancePtr)->Config.BaseAddr, \ + XSCUWDT_LOAD_OFFSET, (Value)) + +/****************************************************************************/ +/** +* +* Put the watchdog timer in Watchdog mode by setting the WD mode bit of the +* Watchdog control register. +* +* @param InstancePtr is a pointer to the XScuWdt instance. +* +* @return None. +* +* @note C-style signature: +* void XScuWdt_SetWdMode(XScuWdt *InstancePtr) +* +******************************************************************************/ +#define XScuWdt_SetWdMode(InstancePtr) \ + XScuWdt_WriteReg((InstancePtr)->Config.BaseAddr, \ + XSCUWDT_CONTROL_OFFSET, \ + (XScuWdt_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUWDT_CONTROL_OFFSET) | \ + (XSCUWDT_CONTROL_WD_MODE_MASK))) + +/****************************************************************************/ +/** +* +* Put the watchdog timer in Timer mode by writing 0x12345678 and 0x87654321 +* successively to the Watchdog Disable Register. +* The software must write 0x12345678 and 0x87654321 successively to the +* Watchdog Disable Register so that the watchdog mode bit in the Watchdog +* Control Register is set to zero. +* +* @param InstancePtr is a pointer to the XScuWdt instance. +* +* @return None. +* +* @note C-style signature: +* void XScuWdt_SetTimerMode(XScuWdt *InstancePtr) +* +******************************************************************************/ +#define XScuWdt_SetTimerMode(InstancePtr) \ +{ \ + XScuWdt_WriteReg((InstancePtr)->Config.BaseAddr, \ + XSCUWDT_DISABLE_OFFSET, \ + XSCUWDT_DISABLE_VALUE1); \ + XScuWdt_WriteReg((InstancePtr)->Config.BaseAddr, \ + XSCUWDT_DISABLE_OFFSET, \ + XSCUWDT_DISABLE_VALUE2); \ +} + +/****************************************************************************/ +/** +* +* Get the contents of the watchdog control register. +* +* @param InstancePtr is a pointer to the XScuWdt instance. +* +* @return Contents of the watchdog control register. +* +* @note C-style signature: + u32 XScuWdt_GetControlReg(XScuWdt *InstancePtr) +* +******************************************************************************/ +#define XScuWdt_GetControlReg(InstancePtr) \ + XScuWdt_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUWDT_CONTROL_OFFSET) + +/****************************************************************************/ +/** +* +* Write to the watchdog control register. +* +* @param InstancePtr is a pointer to the XScuWdt instance. +* @param ControlReg is the value to be written to the watchdog control +* register. +* +* @return None. +* +* @note C-style signature: + void XScuWdt_SetControlReg(XScuWdt *InstancePtr, u32 ControlReg) +* +******************************************************************************/ +#define XScuWdt_SetControlReg(InstancePtr, ControlReg) \ + XScuWdt_WriteReg((InstancePtr)->Config.BaseAddr, \ + XSCUWDT_CONTROL_OFFSET, (ControlReg)) + +/****************************************************************************/ +/** +* +* Enable auto-reload mode. +* +* @param InstancePtr is a pointer to the XScuWdt instance. +* +* @return None. +* +* @note C-style signature: +* void XScuWdt_EnableAutoReload(XScuWdt *InstancePtr) +* +******************************************************************************/ +#define XScuWdt_EnableAutoReload(InstancePtr) \ + XScuWdt_SetControlReg((InstancePtr), \ + (XScuWdt_GetControlReg(InstancePtr) | \ + XSCUWDT_CONTROL_AUTO_RELOAD_MASK)) + +/************************** Function Prototypes ******************************/ + +/* + * Lookup configuration in xscuwdt_sinit.c. + */ +XScuWdt_Config *XScuWdt_LookupConfig(u16 DeviceId); + +/* + * Selftest function in xscuwdt_selftest.c + */ +s32 XScuWdt_SelfTest(XScuWdt *InstancePtr); + +/* + * Interface functions in xscuwdt.c + */ +s32 XScuWdt_CfgInitialize(XScuWdt *InstancePtr, + XScuWdt_Config *ConfigPtr, u32 EffectiveAddress); + +void XScuWdt_Start(XScuWdt *InstancePtr); + +void XScuWdt_Stop(XScuWdt *InstancePtr); + + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/include/xscuwdt_hw.h b/datalink814_ge/bsp/ps7_cortexa9_0/include/xscuwdt_hw.h new file mode 100644 index 0000000..ad87a05 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/include/xscuwdt_hw.h @@ -0,0 +1,178 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xscuwdt_hw.h +* @addtogroup scuwdt_v2_1 +* @{ +* +* This file contains the hardware interface to the Xilinx SCU private Watch Dog +* Timer (XSCUWDT). +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 1.00a sdm 01/15/10 First release
+* 1.01a bss 02/27/12 Updated the register offsets to start at 0x0 instead
+*                    of 0x20 as the base address obtained from the tools
+*		     starts at 0x20.
+* 1.02a  sg 07/17/12 Included xil_assert.h for CR 667947. This is an issue
+*		     when the xstatus.h in the common driver overwrites
+*		     the xstatus.h of the standalone BSP during the
+*		     libgen.
+* 2.1 	sk  02/26/15 Modified the code for MISRA-C:2012 compliance.
+* 
+* +******************************************************************************/ +#ifndef XSCUWDT_HW_H /* prevent circular inclusions */ +#define XSCUWDT_HW_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_io.h" +#include "xil_assert.h" +/************************** Constant Definitions *****************************/ + +/** @name Register Map + * Offsets of registers from the start of the device. The WDT registers start at + * an offset 0x20 + * @{ + */ + +#define XSCUWDT_LOAD_OFFSET 0x00U /**< Watchdog Load Register */ +#define XSCUWDT_COUNTER_OFFSET 0x04U /**< Watchdog Counter Register */ +#define XSCUWDT_CONTROL_OFFSET 0x08U /**< Watchdog Control Register */ +#define XSCUWDT_ISR_OFFSET 0x0CU /**< Watchdog Interrupt Status Register */ +#define XSCUWDT_RST_STS_OFFSET 0x10U /**< Watchdog Reset Status Register */ +#define XSCUWDT_DISABLE_OFFSET 0x14U /**< Watchdog Disable Register */ +/* @} */ + +/** @name Watchdog Control register + * This register bits control the prescaler, WD/Timer mode, Intr enable, + * auto-reload, watchdog enable. + * @{ + */ + +#define XSCUWDT_CONTROL_PRESCALER_MASK 0x0000FF00U /**< Prescaler */ +#define XSCUWDT_CONTROL_PRESCALER_SHIFT 8U +#define XSCUWDT_CONTROL_WD_MODE_MASK 0x00000008U /**< Watchdog/Timer mode */ +#define XSCUWDT_CONTROL_IT_ENABLE_MASK 0x00000004U /**< Intr enable (in + timer mode) */ +#define XSCUWDT_CONTROL_AUTO_RELOAD_MASK 0x00000002U /**< Auto-reload (in + timer mode) */ +#define XSCUWDT_CONTROL_WD_ENABLE_MASK 0x00000001U /**< Watchdog enable */ +/* @} */ + +/** @name Interrupt Status register + * This register indicates the Counter register has reached zero in Counter + * mode. + * @{ + */ + +#define XSCUWDT_ISR_EVENT_FLAG_MASK 0x00000001U /**< Event flag */ +/*@}*/ + +/** @name Reset Status register + * This register indicates the Counter register has reached zero in Watchdog + * mode and a reset request is sent. + * @{ + */ + +#define XSCUWDT_RST_STS_RESET_FLAG_MASK 0x00000001U /**< Time out occured */ +/*@}*/ + +/** @name Disable register + * This register is used to switch from watchdog mode to timer mode. + * The software must write 0x12345678 and 0x87654321 successively to the + * Watchdog Disable Register so that the watchdog mode bit in the Watchdog + * Control Register is set to zero. + * @{ + */ +#define XSCUWDT_DISABLE_VALUE1 0x12345678U /**< Watchdog mode disable + value 1 */ +#define XSCUWDT_DISABLE_VALUE2 0x87654321U /**< Watchdog mode disable + value 2 */ +/*@}*/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/****************************************************************************/ +/** +* +* Read the given register. +* +* @param BaseAddr is the base address of the device +* @param RegOffset is the register offset to be read +* +* @return The 32-bit value of the register +* +* @note C-style signature: +* u32 XScuWdt_ReadReg(u32 BaseAddr, u32 RegOffset) +* +*****************************************************************************/ +#define XScuWdt_ReadReg(BaseAddr, RegOffset) \ + Xil_In32((BaseAddr) + ((u32)RegOffset)) + +/****************************************************************************/ +/** +* +* Write the given register. +* +* @param BaseAddr is the base address of the device +* @param RegOffset is the register offset to be written +* @param Data is the 32-bit value to write to the register +* +* @return None. +* +* @note C-style signature: +* void XScuWdt_WriteReg(u32 BaseAddr, u32 RegOffset, u32 Data) +* +*****************************************************************************/ +#define XScuWdt_WriteReg(BaseAddr, RegOffset, Data) \ + Xil_Out32((BaseAddr) + ((u32)RegOffset), ((u32)Data)) + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/include/xspips.h b/datalink814_ge/bsp/ps7_cortexa9_0/include/xspips.h new file mode 100644 index 0000000..1daee72 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/include/xspips.h @@ -0,0 +1,703 @@ +/****************************************************************************** +* +* Copyright (C) 2017 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xspips.h +* @addtogroup spips_v3_2 +* @{ +* @details +* +* This file contains the implementation of the XSpiPs driver. It works for +* both the master and slave mode. User documentation for the driver functions +* is contained in this file in the form of comment blocks at the front of each +* function. +* +* An SPI device connects to an SPI bus through a 4-wire serial interface. +* The SPI bus is a full-duplex, synchronous bus that facilitates communication +* between one master and one slave. The device is always full-duplex, +* which means that for every byte sent, one is received, and vice-versa. +* The master controls the clock, so it can regulate when it wants to +* send or receive data. The slave is under control of the master, it must +* respond quickly since it has no control of the clock and must send/receive +* data as fast or as slow as the master does. +* +* Initialization & Configuration +* +* The XSpiPs_Config structure is used by the driver to configure itself. This +* configuration structure is typically created by the tool-chain based on HW +* build properties. +* +* To support multiple runtime loading and initialization strategies employed by +* various operating systems, the driver instance can be initialized in the +* following way: +* - XSpiPs_LookupConfig(DeviceId) - Use the devide identifier to find the +* static configuration structure defined in xspips_g.c. This is setup by +* the tools. For some operating systems the config structure will be +* initialized by the software and this call is not needed. +* - XSpiPs_CfgInitialize(InstancePtr, CfgPtr, EffectiveAddr) - Uses a +* configuration structure provided by the caller. If running in a system +* with address translation, the provided virtual memory base address +* replaces the physical address present in the configuration structure. +* +* Multiple Masters +* +* More than one master can exist, but arbitration is the responsibility of +* the higher layer software. The device driver does not perform any type of +* arbitration. +* +* Multiple Slaves +* +* Contention between multiple masters is detected by the hardware, in which +* case a mode fault occurs on the device. The device is disabled immediately +* by hardware, and the current word transfer is stopped. The Aborted word +* transfer due to the mode fault is resumed once the devie is enabled again. +* +* Modes of Operation +* +* There are four modes to perform a data transfer and the selection of a mode +* is based on Chip Select(CS) and Start. These two options individually, can +* be controlled either by software(Manual) or hardware(Auto). +* - Auto CS: Chip select is automatically asserted as soon as the first word +* is written into the TXFIFO and deasserted when the TXFIFO becomes +* empty +* - Manual CS: Software must assert and deassert CS. +* - Auto Start: Data transmission starts as soon as there is data in the +* TXFIFO and stalls when the TXFIFO is empty +* - Manual Start: Software must start data transmission at the beginning of +* the transaction or whenever the TXFIFO has become empty +* +* The preferred combination is Manual CS and Auto Start. +* In this combination, the software asserts CS before loading any data into +* TXFIFO. In Auto Start mode, whenever data is in TXFIFO, controller sends it +* out until TXFIFO becomes empty. The software reads the RXFIFO whenever the +* data is available. If no further data, software disables CS. +* +* Risks/challenges of other combinations: +* - Manual CS and Manual Start: Manual Start bit should be set after each +* TXFIFO write otherwise there could be a race condition where the TXFIFO +* becomes empty before the new word is written. In that case the +* transmission stops. +* - Auto CS with Manual or Auto Start: It is very difficult for software to +* keep the TXFIFO filled. Whenever the TXFIFO runs empty, CS is deasserted. +* This results in a single transaction to be split into multiple pieces each +* with its own chip select. This will result in garbage data to be sent. +* +* Interrupts +* +* The user must connect the interrupt handler of the driver, +* XSpiPs_InterruptHandler, to an interrupt system such that it will be +* called when an interrupt occurs. This function does not save and restore +* the processor context such that the user must provide this processing. +* +* The driver handles the following interrupts: +* - Data Transmit Register/FIFO Underflow +* - Data Receive Register/FIFO Full +* - Data Receive Register/FIFO Not Empty +* - Data Transmit Register/FIFO Full +* - Data Transmit Register/FIFO Overwater +* - Mode Fault Error +* - Data Receive Register/FIFO Overrun +* +* The Data Transmit Register/FIFO Overwater interrupt -- indicates that the +* SPI device has transmitted the data available to transmit, and now its data +* register and FIFO is ready to accept more data. The driver uses this +* interrupt to indicate progress while sending data. The driver may have +* more data to send, in which case the data transmit register and FIFO is +* filled for subsequent transmission. When this interrupt arrives and all +* the data has been sent, the driver invokes the status callback with a +* value of XST_SPI_TRANSFER_DONE to inform the upper layer software that +* all data has been sent. +* +* The Data Transmit Register/FIFO Underflow interrupt -- indicates that, +* as slave, the SPI device was required to transmit but there was no data +* available to transmit in the transmit register (or FIFO). This may not +* be an error if the master is not expecting data. But in the case where +* the master is expecting data, this serves as a notification of such a +* condition. The driver reports this condition to the upper layer +* software through the status handler. +* +* The Data Receive Register/FIFO Overrun interrupt -- indicates that the SPI +* device received data and subsequently dropped the data because the data +* receive register and FIFO was full. The interrupt applies to both master +* and slave operation. The driver reports this condition to the upper layer +* software through the status handler. This likely indicates a problem with +* the higher layer protocol, or a problem with the slave performance. +* +* The Mode Fault Error interrupt -- indicates that while configured as a +* master, the device was selected as a slave by another master. This can be +* used by the application for arbitration in a multimaster environment or to +* indicate a problem with arbitration. When this interrupt occurs, the +* driver invokes the status callback with a status value of +* XST_SPI_MODE_FAULT. It is up to the application to resolve the conflict. +* When configured as a slave, Mode Fault Error interrupt indicates that a slave +* device was selected as a slave by a master, but the slave device was +* disabled. When configured as a master, Mode Fault Error interrupt indicates +* that another SPI device is acting as a master on the bus. +* +* +* Polled Operation +* +* Transfer in polled mode is supported through a separate interface function +* XSpiPs_PolledTransfer(). Unlike the transfer function in the interrupt mode, +* this function blocks until all data has been sent/received. +* +* Device Busy +* +* Some operations are disallowed when the device is busy. The driver tracks +* whether a device is busy. The device is considered busy when a data transfer +* request is outstanding, and is considered not busy only when that transfer +* completes (or is aborted with a mode fault error). This applies to both +* master and slave devices. +* +* Device Configuration +* +* The device can be configured in various ways during the FPGA implementation +* process. Configuration parameters are stored in the xspips_g.c file or +* passed in via XSpiPs_CfgInitialize(). A table is defined where each entry +* contains configuration information for an SPI device, including the base +* address for the device. +* +* RTOS Independence +* +* This driver is intended to be RTOS and processor independent. It works with +* physical addresses only. Any needs for dynamic memory management, threads or +* thread mutual exclusion, virtual memory, or cache control must be satisfied +* by the layer above this driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ------ -------- -----------------------------------------------
+* 1.00	drg/jz 01/25/10 First release
+* 1.00	sdm    10/25/11 Removed the Divide by 2 in the SPI Clock Prescaler
+*			options as this is not supported in the device.
+* 1.01	sg     03/07/12 Updated the code to always clear the relevant bits
+*			before writing to config register.
+*			Always clear the slave select bits before write and
+*			clear the bits to no slave at the end of transfer
+*			Modified the Polled transfer transmit/receive logic.
+*			Tx should wait on TXOW Interrupt and Rx on RXNEMTY.
+* 1.02	sg     05/31/12 Updated XSPIPS_FIFO_DEPTH to 128 from 32 to match HW
+*			for CR 658289
+* 1.03	sg     09/21/12 Added memory barrier dmb in polled transfer and
+*			interrupt handler to overcome the clock domain
+*			crossing issue in the controller. For CR #679252.
+* 1.04a	sg     01/30/13 Created XSPIPS_MANUAL_START_OPTION. Created macros
+*			XSpiPs_IsMaster, XSpiPs_IsManualStart and
+*			XSpiPs_IsManualChipSelect. Changed SPI
+*			Enable/Disable macro argument from BaseAddress to
+*			Instance Pointer. Added DelayNss argument to SetDelays
+*			and GetDelays API's. Added macros to set/get the
+*			RX Watermark value.Created macros XSpiPs_IsMaster,
+*			XSpiPs_IsManualStart and XSpiPs_IsManualChipSelect.
+*			Changed SPI transfer logic for polled and interrupt
+*			modes to be based on filled tx fifo count and receive
+*			based on it. RXNEMPTY interrupt is not used.
+*			SetSlaveSelect API logic is modified to drive the bit
+*			position low based on the slave select value
+*			requested. GetSlaveSelect API will return the value
+*			based on bit position that is low.
+*			Created XSPIPS_CR_MODF_GEN_EN_MASK macro and added it
+*			to XSPIPS_CR_RESET_STATE. Created
+* 			XSPIPS_IXR_WR_TO_CLR_MASK for interrupts which need
+*			write-to-clear. Added shift and mask macros for d_nss
+*			parameter. Added Rx Watermark mask.
+* 1.05a hk 	   26/04/13 Added disable and enable in XSpiPs_SetOptions when
+*				CPOL/CPHA bits are set/reset. Fix for CR#707669.
+* 1.06a hk     08/22/13 Changed GetSlaveSelect function. CR# 727866.
+*                       Added masking ConfigReg before writing in SetSlaveSel
+*                       Added extended slave select support - CR#722569.
+*                       Added prototypes of reset API and related constant
+*                       definitions.
+*                       Added check for MODF in polled transfer function.
+* 3.0   vm    12/09/14	Modified driver source code for MISRA-C:2012 compliance.
+*			Support for Zynq Ultrascale Mp added.
+*       ms     03/17/17 Added readme.txt file in examples folder for doxygen
+*                       generation.
+*       ms     04/05/17 Modified Comment lines in functions of spips
+*                       examples to recognize it as documentation block
+*                       for doxygen generation and also modified filename tag
+*                       in eeprom interrupt, eeprom polled and flash polled
+*                       files to include them in doxygen examples.
+* 3.1	tjs    04/12/18 InputClockHz parameter copied in instance for use in
+* 						application. CR#998910
+* 3.2   aru    01/20/19 Fixes violations according to MISRAC-2012
+*                       in safety mode and done changes such as
+*                       Declared the pointer param as Pointer to const.
+* 3.2   nsk    03/26/19 Add support for versal - CR #1025583.
+* 
+* +******************************************************************************/ +#ifndef XSPIPS_H /* prevent circular inclusions */ +#define XSPIPS_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xstatus.h" +#include "xspips_hw.h" + +/************************** Constant Definitions *****************************/ + +/** @name Configuration options + * + * The following options are supported to enable/disable certain features of + * an SPI device. Each of the options is a bit mask, so more than one may be + * specified. + * + * The Master option configures the SPI device as a master. + * By default, the device is a slave. + * + * The Active Low Clock option configures the device's clock polarity. + * Setting this option means the clock is active low and the SCK signal idles + * high. By default, the clock is active high and SCK idles low. + * + * The Clock Phase option configures the SPI device for one of two + * transfer formats. A clock phase of 0, the default, means data is valid on + * the first SCK edge (rising or falling) after the slave select (SS) signal + * has been asserted. A clock phase of 1 means data is valid on the second SCK + * edge (rising or falling) after SS has been asserted. + * + * The Slave Select Decode Enable option selects how the SPI_SS_outN are + * controlled by the SPI Slave Select Decode bits. + * 0: Use this setting for the standard configuration of up to three slave + * select outputs. Only one of the three slave select outputs will be low. + * (Default) + * 1: Use this setting for the optional configuration of an additional decoder + * to support 8 slave select outputs. SPI_SS_outN reflects the value in the + * register. + * + * The SPI Force Slave Select option is used to enable manual control of + * the signals SPI_SS_outN. + * 0: The SPI_SS_outN signals are controlled by the SPI controller during + * transfers. (Default) + * 1: The SPI_SS_outN signal indicated by the Slave Select Control bit is + * forced active (driven low) regardless of any transfers in progress. + * + * NOTE: The driver will handle setting and clearing the Slave Select when + * the user sets the "FORCE_SSELECT_OPTION". Using this option will allow the + * SPI clock to be set to a faster speed. If the SPI clock is too fast, the + * processor cannot empty and refill the FIFOs before the TX FIFO is empty + * When the SPI hardware is controlling the Slave Select signals, this + * will cause slave to be de-selected and terminate the transfer. + * + * The Manual Start option is used to enable manual control of + * the Start command to perform data transfer. + * 0: The Start command is controlled by the SPI controller during + * transfers(Default). Data transmission starts as soon as there is data in + * the TXFIFO and stalls when the TXFIFO is empty + * 1: The Start command must be issued by software to perform data transfer. + * Bit 15 of Configuration register is used to issue Start command. This bit + * must be set whenever TXFIFO is filled with new data. + * + * NOTE: The driver will set the Manual Start Enable bit in Configuration + * Register, if Manual Start option is selected. Software will issue + * Manual Start command whenever TXFIFO is filled with data. When there is + * no further data, driver will clear the Manual Start Enable bit. + * + * @{ + */ +#define XSPIPS_MASTER_OPTION 0x00000001U /**< Master mode option */ +#define XSPIPS_CLK_ACTIVE_LOW_OPTION 0x00000002U /**< Active Low Clock option */ +#define XSPIPS_CLK_PHASE_1_OPTION 0x00000004U /**< Clock Phase one option */ +#define XSPIPS_DECODE_SSELECT_OPTION 0x00000008U /**< Select 16 slaves Option */ +#define XSPIPS_FORCE_SSELECT_OPTION 0x00000010U /**< Force Slave Select */ +#define XSPIPS_MANUAL_START_OPTION 0x00000020U /**< Manual Start mode option */ +/*@}*/ + + +/** @name SPI Clock Prescaler options + * The SPI Clock Prescaler Configuration bits are used to program master mode + * bit rate. The bit rate can be programmed in divide-by-two decrements from + * pclk/4 to pclk/256. + * + * @{ + */ + +#define XSPIPS_CLK_PRESCALE_4 0x01U /**< PCLK/4 Prescaler */ +#define XSPIPS_CLK_PRESCALE_8 0x02U /**< PCLK/8 Prescaler */ +#define XSPIPS_CLK_PRESCALE_16 0x03U /**< PCLK/16 Prescaler */ +#define XSPIPS_CLK_PRESCALE_32 0x04U /**< PCLK/32 Prescaler */ +#define XSPIPS_CLK_PRESCALE_64 0x05U /**< PCLK/64 Prescaler */ +#define XSPIPS_CLK_PRESCALE_128 0x06U /**< PCLK/128 Prescaler */ +#define XSPIPS_CLK_PRESCALE_256 0x07U /**< PCLK/256 Prescaler */ +/*@}*/ + + +/** @name Callback events + * + * These constants specify the handler events that are passed to + * a handler from the driver. These constants are not bit masks such that + * only one will be passed at a time to the handler. + * + * @{ + */ +#define XSPIPS_EVENT_MODE_FAULT 1U /**< Mode fault error */ +#define XSPIPS_EVENT_TRANSFER_DONE 2U /**< Transfer done */ +#define XSPIPS_EVENT_TRANSMIT_UNDERRUN 3U /**< TX FIFO empty */ +#define XSPIPS_EVENT_RECEIVE_OVERRUN 4U /**< Receive data loss because + RX FIFO full */ +/*@}*/ + + +/**************************** Type Definitions *******************************/ +/** + * The handler data type allows the user to define a callback function to + * handle the asynchronous processing for the SPI device. The application + * using this driver is expected to define a handler of this type to support + * interrupt driven mode. The handler executes in an interrupt context, so + * only minimal processing should be performed. + * + * @param CallBackRef is the callback reference passed in by the upper + * layer when setting the callback functions, and passed back to + * the upper layer when the callback is invoked. Its type is + * not important to the driver, so it is a void pointer. + * @param StatusEvent holds one or more status events that have occurred. + * See the XSpiPs_SetStatusHandler() for details on the status + * events that can be passed in the callback. + * @param ByteCount indicates how many bytes of data were successfully + * transferred. This may be less than the number of bytes + * requested if the status event indicates an error. + */ +typedef void (*XSpiPs_StatusHandler) (const void *CallBackRef, u32 StatusEvent, + u32 ByteCount); + +/** + * This typedef contains configuration information for the device. + */ +typedef struct { + u16 DeviceId; /**< Unique ID of device */ + u32 BaseAddress; /**< Base address of the device */ + u32 InputClockHz; /**< Input clock frequency */ +} XSpiPs_Config; + +/** + * The XSpiPs driver instance data. The user is required to allocate a + * variable of this type for every SPI device in the system. A pointer + * to a variable of this type is then passed to the driver API functions. + */ +typedef struct { + XSpiPs_Config Config; /**< Configuration structure */ + u32 IsReady; /**< Device is initialized and ready */ + + u8 *SendBufferPtr; /**< Buffer to send (state) */ + u8 *RecvBufferPtr; /**< Buffer to receive (state) */ + u32 RequestedBytes; /**< Number of bytes to transfer (state) */ + u32 RemainingBytes; /**< Number of bytes left to transfer(state) */ + u32 IsBusy; /**< A transfer is in progress (state) */ + u32 SlaveSelect; /**< The slave select value when + XSPIPS_FORCE_SSELECT_OPTION is set */ + + XSpiPs_StatusHandler StatusHandler; + void *StatusRef; /**< Callback reference for status handler */ + +} XSpiPs; + +/***************** Macros (Inline Functions) Definitions *********************/ +/****************************************************************************/ +/* +* +* Check in OptionsTable if Manual Start Option is enabled or disabled. +* +* @param InstancePtr is a pointer to the XSpiPs instance. +* +* @return +* - TRUE if option is set +* - FALSE if option is not set +* +* @note C-Style signature: +* u8 XSpiPs_IsManualStart(XSpiPs *InstancePtr) +* +*****************************************************************************/ +#define XSpiPs_IsManualStart(InstancePtr) \ + (((XSpiPs_GetOptions(InstancePtr) & \ + XSPIPS_MANUAL_START_OPTION) != (u32)0U) ? TRUE : FALSE) + +/****************************************************************************/ +/* +* +* Check in OptionsTable if Manual Chip Select Option is enabled or disabled. +* +* @param InstancePtr is a pointer to the XSpiPs instance. +* +* @return +* - TRUE if option is set +* - FALSE if option is not set +* +* @note C-Style signature: +* u8 XSpiPs_IsManualChipSelect(XSpiPs *InstancePtr) +* +*****************************************************************************/ +#define XSpiPs_IsManualChipSelect(InstancePtr) \ + (((XSpiPs_GetOptions(InstancePtr) & \ + XSPIPS_FORCE_SSELECT_OPTION) != (u32)0U) ? TRUE : FALSE) + +/****************************************************************************/ +/* +* +* Check in OptionsTable if Decode Slave Select option is enabled or disabled. +* +* @param InstancePtr is a pointer to the XSpiPs instance. +* +* @return +* - TRUE if option is set +* - FALSE if option is not set +* +* @note C-Style signature: +* u8 XSpiPs_IsDecodeSSelect(XSpiPs *InstancePtr) +* +*****************************************************************************/ +#define XSpiPs_IsDecodeSSelect(InstancePtr) \ + (((XSpiPs_GetOptions(InstancePtr) & \ + XSPIPS_DECODE_SSELECT_OPTION) != (u32)0U) ? TRUE : FALSE) + +/****************************************************************************/ +/* +* +* Check in OptionsTable if Master Option is enabled or disabled. +* +* @param InstancePtr is a pointer to the XSpiPs instance. +* +* @return +* - TRUE if option is set +* - FALSE if option is not set +* +* @note C-Style signature: +* u8 XSpiPs_IsMaster(XSpiPs *InstancePtr) +* +*****************************************************************************/ +#define XSpiPs_IsMaster(InstancePtr) \ + (((XSpiPs_GetOptions(InstancePtr) & \ + XSPIPS_MASTER_OPTION) != (u32)0U) ? TRUE : FALSE) + +/****************************************************************************/ +/** +* +* Set the contents of the slave idle count register. +* +* @param InstancePtr is a pointer to the XSpiPs instance. +* @param RegisterValue is the value to be writen, valid values are +* 0-255. +* +* @return None +* +* @note +* C-Style signature: +* void XSpiPs_SetSlaveIdle(XSpiPs *InstancePtr, u32 RegisterValue) +* +*****************************************************************************/ +#define XSpiPs_SetSlaveIdle(InstancePtr, RegisterValue) \ + XSpiPs_Out32(((InstancePtr)->Config.BaseAddress) + \ + XSPIPS_SICR_OFFSET, (RegisterValue)) + +/****************************************************************************/ +/** +* +* Get the contents of the slave idle count register. Use the XSPIPS_SICR_* +* constants defined in xspips_hw.h to interpret the bit-mask returned. +* +* @param InstancePtr is a pointer to the XSpiPs instance. +* +* @return 8-bit value representing the contents of the SIC register. +* +* @note C-Style signature: +* u32 XSpiPs_GetSlaveIdle(XSpiPs *InstancePtr) +* +*****************************************************************************/ +#define XSpiPs_GetSlaveIdle(InstancePtr) \ + XSpiPs_In32(((InstancePtr)->Config.BaseAddress) + \ + XSPIPS_SICR_OFFSET) + +/****************************************************************************/ +/** +* +* Set the contents of the transmit FIFO watermark register. +* +* @param InstancePtr is a pointer to the XSpiPs instance. +* @param RegisterValue is the value to be written, valid values +* are 1-128. +* +* @return None. +* +* @note +* C-Style signature: +* void XSpiPs_SetTXWatermark(XSpiPs *InstancePtr, u32 RegisterValue) +* +*****************************************************************************/ +#define XSpiPs_SetTXWatermark(InstancePtr, RegisterValue) \ + XSpiPs_Out32(((InstancePtr)->Config.BaseAddress) + \ + XSPIPS_TXWR_OFFSET, (RegisterValue)) + +/****************************************************************************/ +/** +* +* Get the contents of the transmit FIFO watermark register. +* Use the XSPIPS_TXWR_* constants defined xspips_hw.h to interpret +* the bit-mask returned. +* +* @param InstancePtr is a pointer to the XSpiPs instance. +* +* @return 8-bit value representing the contents of the TXWR register. +* +* @note C-Style signature: +* u32 XSpiPs_GetTXWatermark(u32 *InstancePtr) +* +*****************************************************************************/ +#define XSpiPs_GetTXWatermark(InstancePtr) \ + XSpiPs_In32(((InstancePtr)->Config.BaseAddress) + XSPIPS_TXWR_OFFSET) + +/****************************************************************************/ +/** +* +* Set the contents of the receive FIFO watermark register. +* +* @param InstancePtr is a pointer to the XSpiPs instance. +* @param RegisterValue is the value to be written, valid values +* are 1-128. +* +* @return None. +* +* @note +* C-Style signature: +* void XSpiPs_SetRXWatermark(XSpiPs *InstancePtr, u32 RegisterValue) +* +*****************************************************************************/ +#define XSpiPs_SetRXWatermark(InstancePtr, RegisterValue) \ + XSpiPs_Out32(((InstancePtr)->Config.BaseAddress) + \ + XSPIPS_RXWR_OFFSET, (RegisterValue)) + +/****************************************************************************/ +/** +* +* Get the contents of the receive FIFO watermark register. +* Use the XSPIPS_RXWR_* constants defined xspips_hw.h to interpret +* the bit-mask returned. +* +* @param InstancePtr is a pointer to the XSpiPs instance. +* +* @return A 8-bit value representing the contents of the RXWR register. +* +* @note C-Style signature: +* u32 XSpiPs_GetRXWatermark(u32 *InstancePtr) +* +*****************************************************************************/ +#define XSpiPs_GetRXWatermark(InstancePtr) \ + XSpiPs_In32(((InstancePtr)->Config.BaseAddress) + XSPIPS_RXWR_OFFSET) + +/****************************************************************************/ +/** +* +* Enable the device and uninhibit master transactions. +* +* @param InstancePtr is a pointer to the XSpiPs instance. +* +* @return None. +* +* @note C-Style signature: +* void XSpiPs_Enable(u32 *InstancePtr) +* +*****************************************************************************/ +#define XSpiPs_Enable(InstancePtr) \ + XSpiPs_Out32(((InstancePtr)->Config.BaseAddress) + XSPIPS_ER_OFFSET, \ + XSPIPS_ER_ENABLE_MASK) + +/****************************************************************************/ +/** +* +* Disable the device. +* +* @param InstancePtr is a pointer to the XSpiPs instance. +* +* @return None. +* +* @note C-Style signature: +* void XSpiPs_Disable(u32 *InstancePtr) +* +*****************************************************************************/ +#define XSpiPs_Disable(InstancePtr) \ + XSpiPs_Out32(((InstancePtr)->Config.BaseAddress) + XSPIPS_ER_OFFSET, 0U) + +/************************** Function Prototypes ******************************/ + +/* + * Initialization function, implemented in xspips_sinit.c + */ +XSpiPs_Config *XSpiPs_LookupConfig(u16 DeviceId); + +/* + * Functions implemented in xspips.c + */ +s32 XSpiPs_CfgInitialize(XSpiPs *InstancePtr, const XSpiPs_Config * ConfigPtr, + u32 EffectiveAddr); + +void XSpiPs_Reset(XSpiPs *InstancePtr); + +s32 XSpiPs_Transfer(XSpiPs *InstancePtr, u8 *SendBufPtr, u8 *RecvBufPtr, + u32 ByteCount); + +s32 XSpiPs_PolledTransfer(XSpiPs *InstancePtr, u8 *SendBufPtr, + u8 *RecvBufPtr, u32 ByteCount); + +void XSpiPs_SetStatusHandler(XSpiPs *InstancePtr, void *CallBackRef, + XSpiPs_StatusHandler FunctionPtr); +void XSpiPs_InterruptHandler(XSpiPs *InstancePtr); + +void XSpiPs_Abort(XSpiPs *InstancePtr); + +s32 XSpiPs_SetSlaveSelect(XSpiPs *InstancePtr, u8 SlaveSel); +u8 XSpiPs_GetSlaveSelect(const XSpiPs *InstancePtr); + +/* + * Functions for selftest, in xspips_selftest.c + */ +s32 XSpiPs_SelfTest(XSpiPs *InstancePtr); + +/* + * Functions for options, in xspips_options.c + */ +s32 XSpiPs_SetOptions(const XSpiPs *InstancePtr, u32 Options); +u32 XSpiPs_GetOptions(const XSpiPs *InstancePtr); + +s32 XSpiPs_SetClkPrescaler(const XSpiPs *InstancePtr, u8 Prescaler); +u8 XSpiPs_GetClkPrescaler(const XSpiPs *InstancePtr); + +s32 XSpiPs_SetDelays(const XSpiPs *InstancePtr, u8 DelayNss, u8 DelayBtwn, + u8 DelayAfter, u8 DelayInit); +void XSpiPs_GetDelays(const XSpiPs *InstancePtr, u8 *DelayNss, u8 *DelayBtwn, + u8 *DelayAfter, u8 *DelayInit); +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/include/xspips_hw.h b/datalink814_ge/bsp/ps7_cortexa9_0/include/xspips_hw.h new file mode 100644 index 0000000..07b0687 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/include/xspips_hw.h @@ -0,0 +1,309 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xspips_hw.h +* @addtogroup spips_v3_2 +* @{ +* +* This header file contains the identifiers and basic driver functions (or +* macros) that can be used to access the device. Other driver functions +* are defined in xspips.h. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ------ -------- -----------------------------------------------
+* 1.00   drg/jz 01/25/10 First release
+* 1.02a  sg     05/31/12 Updated XSPIPS_FIFO_DEPTH to 128 from 32 to match HW
+*			 for CR 658289
+* 1.04a	 sg     01/30/13 Created XSPIPS_CR_MODF_GEN_EN_MASK macro and added it
+*			 to XSPIPS_CR_RESET_STATE. Created
+* 			 XSPIPS_IXR_WR_TO_CLR_MASK for interrupts which need
+*			 write-to-clear. Added shift and mask macros for d_nss
+*			 parameter. Added Rx Watermark mask.
+* 1.06a hk      08/22/13 Added prototypes of reset API and related constant
+*                        definitions.
+* 3.00  kvn     02/13/15 Modified code for MISRA-C:2012 compliance.
+*
+* 
+* +******************************************************************************/ + +#ifndef XSPIPS_HW_H /* prevent circular inclusions */ +#define XSPIPS_HW_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_io.h" + +/************************** Constant Definitions *****************************/ + +/** @name Register Map + * + * Register offsets from the base address of an SPI device. + * @{ + */ +#define XSPIPS_CR_OFFSET 0x00U /**< Configuration */ +#define XSPIPS_SR_OFFSET 0x04U /**< Interrupt Status */ +#define XSPIPS_IER_OFFSET 0x08U /**< Interrupt Enable */ +#define XSPIPS_IDR_OFFSET 0x0CU /**< Interrupt Disable */ +#define XSPIPS_IMR_OFFSET 0x10U /**< Interrupt Enabled Mask */ +#define XSPIPS_ER_OFFSET 0x14U /**< Enable/Disable Register */ +#define XSPIPS_DR_OFFSET 0x18U /**< Delay Register */ +#define XSPIPS_TXD_OFFSET 0x1CU /**< Data Transmit Register */ +#define XSPIPS_RXD_OFFSET 0x20U /**< Data Receive Register */ +#define XSPIPS_SICR_OFFSET 0x24U /**< Slave Idle Count */ +#define XSPIPS_TXWR_OFFSET 0x28U /**< Transmit FIFO Watermark */ +#define XSPIPS_RXWR_OFFSET 0x2CU /**< Receive FIFO Watermark */ +/* @} */ + +/** @name Configuration Register + * + * This register contains various control bits that + * affects the operation of an SPI device. Read/Write. + * @{ + */ +#define XSPIPS_CR_MODF_GEN_EN_MASK 0x00020000U /**< Modefail Generation + Enable */ +#define XSPIPS_CR_MANSTRT_MASK 0x00010000U /**< Manual Transmission Start */ +#define XSPIPS_CR_MANSTRTEN_MASK 0x00008000U /**< Manual Transmission Start + Enable */ +#define XSPIPS_CR_SSFORCE_MASK 0x00004000U /**< Force Slave Select */ +#define XSPIPS_CR_SSCTRL_MASK 0x00003C00U /**< Slave Select Decode */ +#define XSPIPS_CR_SSCTRL_SHIFT 10U /**< Slave Select Decode shift */ +#define XSPIPS_CR_SSCTRL_MAXIMUM 0xFU /**< Slave Select maximum value */ +#define XSPIPS_CR_SSDECEN_MASK 0x00000200U /**< Slave Select Decode Enable */ + +#define XSPIPS_CR_PRESC_MASK 0x00000038U /**< Prescaler Setting */ +#define XSPIPS_CR_PRESC_SHIFT 3U /**< Prescaler shift */ +#define XSPIPS_CR_PRESC_MAXIMUM 0x07U /**< Prescaler maximum value */ + +#define XSPIPS_CR_CPHA_MASK 0x00000004U /**< Phase Configuration */ +#define XSPIPS_CR_CPOL_MASK 0x00000002U /**< Polarity Configuration */ + +#define XSPIPS_CR_MSTREN_MASK 0x00000001U /**< Master Mode Enable */ +#define XSPIPS_CR_RESET_STATE 0x00020000U /**< Mode Fail Generation Enable */ +/* @} */ + + +/** @name SPI Interrupt Registers + * + * SPI Status Register + * + * This register holds the interrupt status flags for an SPI device. Some + * of the flags are level triggered, which means that they are set as long + * as the interrupt condition exists. Other flags are edge triggered, + * which means they are set once the interrupt condition occurs and remain + * set until they are cleared by software. The interrupts are cleared by + * writing a '1' to the interrupt bit position in the Status Register. + * Read/Write. + * + * SPI Interrupt Enable Register + * + * This register is used to enable chosen interrupts for an SPI device. + * Writing a '1' to a bit in this register sets the corresponding bit in the + * SPI Interrupt Mask register. Write only. + * + * SPI Interrupt Disable Register + * + * This register is used to disable chosen interrupts for an SPI device. + * Writing a '1' to a bit in this register clears the corresponding bit in the + * SPI Interrupt Mask register. Write only. + * + * SPI Interrupt Mask Register + * + * This register shows the enabled/disabled interrupts of an SPI device. + * Read only. + * + * All four registers have the same bit definitions. They are only defined once + * for each of the Interrupt Enable Register, Interrupt Disable Register, + * Interrupt Mask Register, and Channel Interrupt Status Register + * @{ + */ + +#define XSPIPS_IXR_TXUF_MASK 0x00000040U /**< Tx FIFO Underflow */ +#define XSPIPS_IXR_RXFULL_MASK 0x00000020U /**< Rx FIFO Full */ +#define XSPIPS_IXR_RXNEMPTY_MASK 0x00000010U /**< Rx FIFO Not Empty */ +#define XSPIPS_IXR_TXFULL_MASK 0x00000008U /**< Tx FIFO Full */ +#define XSPIPS_IXR_TXOW_MASK 0x00000004U /**< Tx FIFO Overwater */ +#define XSPIPS_IXR_MODF_MASK 0x00000002U /**< Mode Fault */ +#define XSPIPS_IXR_RXOVR_MASK 0x00000001U /**< Rx FIFO Overrun */ +#define XSPIPS_IXR_DFLT_MASK 0x00000027U /**< Default interrupts + mask */ +#define XSPIPS_IXR_WR_TO_CLR_MASK 0x00000043U /**< Interrupts which + need write to clear */ +#define XSPIPS_ISR_RESET_STATE 0x04U /**< Default to tx/rx + * reg empty */ +#define XSPIPS_IXR_DISABLE_ALL_MASK 0x00000043U /**< Disable all + * interrupts */ +/* @} */ + + +/** @name Enable Register + * + * This register is used to enable or disable an SPI device. + * Read/Write + * @{ + */ +#define XSPIPS_ER_ENABLE_MASK 0x00000001U /**< SPI Enable Bit Mask */ +/* @} */ + + +/** @name Delay Register + * + * This register is used to program timing delays in + * slave mode. Read/Write + * @{ + */ +#define XSPIPS_DR_NSS_MASK 0xFF000000U /**< Delay for slave select + * de-assertion between + * word transfers mask */ +#define XSPIPS_DR_NSS_SHIFT 24U /**< Delay for slave select + * de-assertion between + * word transfers shift */ +#define XSPIPS_DR_BTWN_MASK 0x00FF0000U /**< Delay Between Transfers mask */ +#define XSPIPS_DR_BTWN_SHIFT 16U /**< Delay Between Transfers shift */ +#define XSPIPS_DR_AFTER_MASK 0x0000FF00U /**< Delay After Transfers mask */ +#define XSPIPS_DR_AFTER_SHIFT 8U /**< Delay After Transfers shift */ +#define XSPIPS_DR_INIT_MASK 0x000000FFU /**< Delay Initially mask */ +/* @} */ + + +/** @name Slave Idle Count Registers + * + * This register defines the number of pclk cycles the slave waits for a the + * SPI clock to become stable in quiescent state before it can detect the start + * of the next transfer in CPHA = 1 mode. + * Read/Write + * + * @{ + */ +#define XSPIPS_SICR_MASK 0x000000FFU /**< Slave Idle Count Mask */ +/* @} */ + + + +/** @name Transmit FIFO Watermark Register + * + * This register defines the watermark setting for the Transmit FIFO. The + * transmit FIFO is 128 bytes deep, so the register is 7 bits. Valid values + * are 1 to 128. + * + * @{ + */ +#define XSPIPS_TXWR_MASK 0x0000007FU /**< Transmit Watermark Mask */ +#define XSPIPS_TXWR_RESET_VALUE 0x00000001U /**< Transmit Watermark + * register reset value */ +/* @} */ + +/** @name Receive FIFO Watermark Register + * + * This register defines the watermark setting for the Receive FIFO. The + * receive FIFO is 128 bytes deep, so the register is 7 bits. Valid values + * are 1 to 128. + * + * @{ + */ +#define XSPIPS_RXWR_MASK 0x0000007FU /**< Receive Watermark Mask */ +#define XSPIPS_RXWR_RESET_VALUE 0x00000001U /**< Receive Watermark + * register reset value */ +/* @} */ + +/** @name FIFO Depth + * + * This macro provides the depth of transmit FIFO and receive FIFO. + * + * @{ + */ +#define XSPIPS_FIFO_DEPTH 128U /**< FIFO depth of Tx and Rx */ +/* @} */ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +#define XSpiPs_In32 Xil_In32 +#define XSpiPs_Out32 Xil_Out32 + +/****************************************************************************/ +/** +* Read a register. +* +* @param BaseAddress contains the base address of the device. +* @param RegOffset contains the offset from the 1st register of the +* device to the target register. +* +* @return The value read from the register. +* +* @note C-Style signature: +* u32 XSpiPs_ReadReg(u32 BaseAddress. int RegOffset) +* +******************************************************************************/ +#define XSpiPs_ReadReg(BaseAddress, RegOffset) \ + XSpiPs_In32((BaseAddress) + (RegOffset)) + +/***************************************************************************/ +/** +* Write to a register. +* +* @param BaseAddress contains the base address of the device. +* @param RegOffset contains the offset from the 1st register of the +* device to target register. +* @param RegisterValue is the value to be written to the register. +* +* @return None. +* +* @note C-Style signature: +* void XSpiPs_WriteReg(u32 BaseAddress, int RegOffset, +* u32 RegisterValue) +* +******************************************************************************/ +#define XSpiPs_WriteReg(BaseAddress, RegOffset, RegisterValue) \ + XSpiPs_Out32((BaseAddress) + (RegOffset), (RegisterValue)) + +/************************** Function Prototypes ******************************/ + +void XSpiPs_ResetHw(u32 BaseAddress); + +/************************** Variable Definitions *****************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/include/xstatus.h b/datalink814_ge/bsp/ps7_cortexa9_0/include/xstatus.h new file mode 100644 index 0000000..1a212bf --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/include/xstatus.h @@ -0,0 +1,533 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xstatus.h +* +* @addtogroup common_status_codes Xilinx® software status codes +* +* The xstatus.h file contains the Xilinx® software status codes.These codes are +* used throughout the Xilinx device drivers. +* +* @{ +******************************************************************************/ + +#ifndef XSTATUS_H /* prevent circular inclusions */ +#define XSTATUS_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" + +/************************** Constant Definitions *****************************/ + +/*********************** Common statuses 0 - 500 *****************************/ +/** +@name Common Status Codes for All Device Drivers +@{ +*/ +#define XST_SUCCESS 0L +#define XST_FAILURE 1L +#define XST_DEVICE_NOT_FOUND 2L +#define XST_DEVICE_BLOCK_NOT_FOUND 3L +#define XST_INVALID_VERSION 4L +#define XST_DEVICE_IS_STARTED 5L +#define XST_DEVICE_IS_STOPPED 6L +#define XST_FIFO_ERROR 7L /*!< An error occurred during an + operation with a FIFO such as + an underrun or overrun, this + error requires the device to + be reset */ +#define XST_RESET_ERROR 8L /*!< An error occurred which requires + the device to be reset */ +#define XST_DMA_ERROR 9L /*!< A DMA error occurred, this error + typically requires the device + using the DMA to be reset */ +#define XST_NOT_POLLED 10L /*!< The device is not configured for + polled mode operation */ +#define XST_FIFO_NO_ROOM 11L /*!< A FIFO did not have room to put + the specified data into */ +#define XST_BUFFER_TOO_SMALL 12L /*!< The buffer is not large enough + to hold the expected data */ +#define XST_NO_DATA 13L /*!< There was no data available */ +#define XST_REGISTER_ERROR 14L /*!< A register did not contain the + expected value */ +#define XST_INVALID_PARAM 15L /*!< An invalid parameter was passed + into the function */ +#define XST_NOT_SGDMA 16L /*!< The device is not configured for + scatter-gather DMA operation */ +#define XST_LOOPBACK_ERROR 17L /*!< A loopback test failed */ +#define XST_NO_CALLBACK 18L /*!< A callback has not yet been + registered */ +#define XST_NO_FEATURE 19L /*!< Device is not configured with + the requested feature */ +#define XST_NOT_INTERRUPT 20L /*!< Device is not configured for + interrupt mode operation */ +#define XST_DEVICE_BUSY 21L /*!< Device is busy */ +#define XST_ERROR_COUNT_MAX 22L /*!< The error counters of a device + have maxed out */ +#define XST_IS_STARTED 23L /*!< Used when part of device is + already started i.e. + sub channel */ +#define XST_IS_STOPPED 24L /*!< Used when part of device is + already stopped i.e. + sub channel */ +#define XST_DATA_LOST 26L /*!< Driver defined error */ +#define XST_RECV_ERROR 27L /*!< Generic receive error */ +#define XST_SEND_ERROR 28L /*!< Generic transmit error */ +#define XST_NOT_ENABLED 29L /*!< A requested service is not + available because it has not + been enabled */ +#define XST_NO_ACCESS 30L /* Generic access error */ +/** @} */ +/***************** Utility Component statuses 401 - 500 *********************/ +/** +@name Utility Component Status Codes 401 - 500 +@{ +*/ +#define XST_MEMTEST_FAILED 401L /*!< Memory test failed */ + +/** @} */ +/***************** Common Components statuses 501 - 1000 *********************/ +/** +@name Packet Fifo Status Codes 501 - 510 +@{ +*/ +/********************* Packet Fifo statuses 501 - 510 ************************/ + +#define XST_PFIFO_LACK_OF_DATA 501L /*!< Not enough data in FIFO */ +#define XST_PFIFO_NO_ROOM 502L /*!< Not enough room in FIFO */ +#define XST_PFIFO_BAD_REG_VALUE 503L /*!< Self test, a register value + was invalid after reset */ +#define XST_PFIFO_ERROR 504L /*!< Generic packet FIFO error */ +#define XST_PFIFO_DEADLOCK 505L /*!< Packet FIFO is reporting + * empty and full simultaneously + */ +/** @} */ +/** +@name DMA Status Codes 511 - 530 +@{ +*/ +/************************** DMA statuses 511 - 530 ***************************/ + +#define XST_DMA_TRANSFER_ERROR 511L /*!< Self test, DMA transfer + failed */ +#define XST_DMA_RESET_REGISTER_ERROR 512L /*!< Self test, a register value + was invalid after reset */ +#define XST_DMA_SG_LIST_EMPTY 513L /*!< Scatter gather list contains + no buffer descriptors ready + to be processed */ +#define XST_DMA_SG_IS_STARTED 514L /*!< Scatter gather not stopped */ +#define XST_DMA_SG_IS_STOPPED 515L /*!< Scatter gather not running */ +#define XST_DMA_SG_LIST_FULL 517L /*!< All the buffer desciptors of + the scatter gather list are + being used */ +#define XST_DMA_SG_BD_LOCKED 518L /*!< The scatter gather buffer + descriptor which is to be + copied over in the scatter + list is locked */ +#define XST_DMA_SG_NOTHING_TO_COMMIT 519L /*!< No buffer descriptors have been + put into the scatter gather + list to be commited */ +#define XST_DMA_SG_COUNT_EXCEEDED 521L /*!< The packet count threshold + specified was larger than the + total # of buffer descriptors + in the scatter gather list */ +#define XST_DMA_SG_LIST_EXISTS 522L /*!< The scatter gather list has + already been created */ +#define XST_DMA_SG_NO_LIST 523L /*!< No scatter gather list has + been created */ +#define XST_DMA_SG_BD_NOT_COMMITTED 524L /*!< The buffer descriptor which was + being started was not committed + to the list */ +#define XST_DMA_SG_NO_DATA 525L /*!< The buffer descriptor to start + has already been used by the + hardware so it can't be reused + */ +#define XST_DMA_SG_LIST_ERROR 526L /*!< General purpose list access + error */ +#define XST_DMA_BD_ERROR 527L /*!< General buffer descriptor + error */ +/** @} */ +/** +@name IPIF Status Codes Codes 531 - 550 +@{ +*/ +/************************** IPIF statuses 531 - 550 ***************************/ + +#define XST_IPIF_REG_WIDTH_ERROR 531L /*!< An invalid register width + was passed into the function */ +#define XST_IPIF_RESET_REGISTER_ERROR 532L /*!< The value of a register at + reset was not valid */ +#define XST_IPIF_DEVICE_STATUS_ERROR 533L /*!< A write to the device interrupt + status register did not read + back correctly */ +#define XST_IPIF_DEVICE_ACK_ERROR 534L /*!< The device interrupt status + register did not reset when + acked */ +#define XST_IPIF_DEVICE_ENABLE_ERROR 535L /*!< The device interrupt enable + register was not updated when + other registers changed */ +#define XST_IPIF_IP_STATUS_ERROR 536L /*!< A write to the IP interrupt + status register did not read + back correctly */ +#define XST_IPIF_IP_ACK_ERROR 537L /*!< The IP interrupt status register + did not reset when acked */ +#define XST_IPIF_IP_ENABLE_ERROR 538L /*!< IP interrupt enable register was + not updated correctly when other + registers changed */ +#define XST_IPIF_DEVICE_PENDING_ERROR 539L /*!< The device interrupt pending + register did not indicate the + expected value */ +#define XST_IPIF_DEVICE_ID_ERROR 540L /*!< The device interrupt ID register + did not indicate the expected + value */ +#define XST_IPIF_ERROR 541L /*!< Generic ipif error */ +/** @} */ + +/****************** Device specific statuses 1001 - 4095 *********************/ +/** +@name Ethernet Status Codes 1001 - 1050 +@{ +*/ +/********************* Ethernet statuses 1001 - 1050 *************************/ + +#define XST_EMAC_MEMORY_SIZE_ERROR 1001L /*!< Memory space is not big enough + * to hold the minimum number of + * buffers or descriptors */ +#define XST_EMAC_MEMORY_ALLOC_ERROR 1002L /*!< Memory allocation failed */ +#define XST_EMAC_MII_READ_ERROR 1003L /*!< MII read error */ +#define XST_EMAC_MII_BUSY 1004L /*!< An MII operation is in progress */ +#define XST_EMAC_OUT_OF_BUFFERS 1005L /*!< Driver is out of buffers */ +#define XST_EMAC_PARSE_ERROR 1006L /*!< Invalid driver init string */ +#define XST_EMAC_COLLISION_ERROR 1007L /*!< Excess deferral or late + * collision on polled send */ +/** @} */ +/** +@name UART Status Codes 1051 - 1075 +@{ +*/ +/*********************** UART statuses 1051 - 1075 ***************************/ +#define XST_UART + +#define XST_UART_INIT_ERROR 1051L +#define XST_UART_START_ERROR 1052L +#define XST_UART_CONFIG_ERROR 1053L +#define XST_UART_TEST_FAIL 1054L +#define XST_UART_BAUD_ERROR 1055L +#define XST_UART_BAUD_RANGE 1056L + +/** @} */ +/** +@name IIC Status Codes 1076 - 1100 +@{ +*/ +/************************ IIC statuses 1076 - 1100 ***************************/ + +#define XST_IIC_SELFTEST_FAILED 1076 /*!< self test failed */ +#define XST_IIC_BUS_BUSY 1077 /*!< bus found busy */ +#define XST_IIC_GENERAL_CALL_ADDRESS 1078 /*!< mastersend attempted with */ + /* general call address */ +#define XST_IIC_STAND_REG_RESET_ERROR 1079 /*!< A non parameterizable reg */ + /* value after reset not valid */ +#define XST_IIC_TX_FIFO_REG_RESET_ERROR 1080 /*!< Tx fifo included in design */ + /* value after reset not valid */ +#define XST_IIC_RX_FIFO_REG_RESET_ERROR 1081 /*!< Rx fifo included in design */ + /* value after reset not valid */ +#define XST_IIC_TBA_REG_RESET_ERROR 1082 /*!< 10 bit addr incl in design */ + /* value after reset not valid */ +#define XST_IIC_CR_READBACK_ERROR 1083 /*!< Read of the control register */ + /* didn't return value written */ +#define XST_IIC_DTR_READBACK_ERROR 1084 /*!< Read of the data Tx reg */ + /* didn't return value written */ +#define XST_IIC_DRR_READBACK_ERROR 1085 /*!< Read of the data Receive reg */ + /* didn't return value written */ +#define XST_IIC_ADR_READBACK_ERROR 1086 /*!< Read of the data Tx reg */ + /* didn't return value written */ +#define XST_IIC_TBA_READBACK_ERROR 1087 /*!< Read of the 10 bit addr reg */ + /* didn't return written value */ +#define XST_IIC_NOT_SLAVE 1088 /*!< The device isn't a slave */ +#define XST_IIC_ARB_LOST 1089 /*!< Arbitration lost for master */ +/** @} */ +/** +@name ATMC Status Codes 1101 - 1125 +@{ +*/ +/*********************** ATMC statuses 1101 - 1125 ***************************/ + +#define XST_ATMC_ERROR_COUNT_MAX 1101L /*!< the error counters in the ATM + controller hit the max value + which requires the statistics + to be cleared */ +/** @} */ +/** +@name Flash Status Codes 1126 - 1150 +@{ +*/ +/*********************** Flash statuses 1126 - 1150 **************************/ + +#define XST_FLASH_BUSY 1126L /*!< Flash is erasing or programming + */ +#define XST_FLASH_READY 1127L /*!< Flash is ready for commands */ +#define XST_FLASH_ERROR 1128L /*!< Flash had detected an internal + error. Use XFlash_DeviceControl + to retrieve device specific codes + */ +#define XST_FLASH_ERASE_SUSPENDED 1129L /*!< Flash is in suspended erase state + */ +#define XST_FLASH_WRITE_SUSPENDED 1130L /*!< Flash is in suspended write state + */ +#define XST_FLASH_PART_NOT_SUPPORTED 1131L /*!< Flash type not supported by + driver */ +#define XST_FLASH_NOT_SUPPORTED 1132L /*!< Operation not supported */ +#define XST_FLASH_TOO_MANY_REGIONS 1133L /*!< Too many erase regions */ +#define XST_FLASH_TIMEOUT_ERROR 1134L /*!< Programming or erase operation + aborted due to a timeout */ +#define XST_FLASH_ADDRESS_ERROR 1135L /*!< Accessed flash outside its + addressible range */ +#define XST_FLASH_ALIGNMENT_ERROR 1136L /*!< Write alignment error */ +#define XST_FLASH_BLOCKING_CALL_ERROR 1137L /*!< Couldn't return immediately from + write/erase function with + XFL_NON_BLOCKING_WRITE/ERASE + option cleared */ +#define XST_FLASH_CFI_QUERY_ERROR 1138L /*!< Failed to query the device */ +/** @} */ +/** +@name SPI Status Codes 1151 - 1175 +@{ +*/ +/*********************** SPI statuses 1151 - 1175 ****************************/ + +#define XST_SPI_MODE_FAULT 1151 /*!< master was selected as slave */ +#define XST_SPI_TRANSFER_DONE 1152 /*!< data transfer is complete */ +#define XST_SPI_TRANSMIT_UNDERRUN 1153 /*!< slave underruns transmit register */ +#define XST_SPI_RECEIVE_OVERRUN 1154 /*!< device overruns receive register */ +#define XST_SPI_NO_SLAVE 1155 /*!< no slave has been selected yet */ +#define XST_SPI_TOO_MANY_SLAVES 1156 /*!< more than one slave is being + * selected */ +#define XST_SPI_NOT_MASTER 1157 /*!< operation is valid only as master */ +#define XST_SPI_SLAVE_ONLY 1158 /*!< device is configured as slave-only + */ +#define XST_SPI_SLAVE_MODE_FAULT 1159 /*!< slave was selected while disabled */ +#define XST_SPI_SLAVE_MODE 1160 /*!< device has been addressed as slave */ +#define XST_SPI_RECEIVE_NOT_EMPTY 1161 /*!< device received data in slave mode */ + +#define XST_SPI_COMMAND_ERROR 1162 /*!< unrecognised command - qspi only */ +#define XST_SPI_POLL_DONE 1163 /*!< controller completed polling the + device for status */ +/** @} */ +/** +@name OPB Arbiter Status Codes 1176 - 1200 +@{ +*/ +/********************** OPB Arbiter statuses 1176 - 1200 *********************/ + +#define XST_OPBARB_INVALID_PRIORITY 1176 /*!< the priority registers have either + * one master assigned to two or more + * priorities, or one master not + * assigned to any priority + */ +#define XST_OPBARB_NOT_SUSPENDED 1177 /*!< an attempt was made to modify the + * priority levels without first + * suspending the use of priority + * levels + */ +#define XST_OPBARB_PARK_NOT_ENABLED 1178 /*!< bus parking by id was enabled but + * bus parking was not enabled + */ +#define XST_OPBARB_NOT_FIXED_PRIORITY 1179 /*!< the arbiter must be in fixed + * priority mode to allow the + * priorities to be changed + */ +/** @} */ +/** +@name INTC Status Codes 1201 - 1225 +@{ +*/ +/************************ Intc statuses 1201 - 1225 **************************/ + +#define XST_INTC_FAIL_SELFTEST 1201 /*!< self test failed */ +#define XST_INTC_CONNECT_ERROR 1202 /*!< interrupt already in use */ +/** @} */ +/** +@name TmrCtr Status Codes 1226 - 1250 +@{ +*/ +/********************** TmrCtr statuses 1226 - 1250 **************************/ + +#define XST_TMRCTR_TIMER_FAILED 1226 /*!< self test failed */ +/** @} */ +/** +@name WdtTb Status Codes 1251 - 1275 +@{ +*/ +/********************** WdtTb statuses 1251 - 1275 ***************************/ + +#define XST_WDTTB_TIMER_FAILED 1251L +/** @} */ +/** +@name PlbArb status Codes 1276 - 1300 +@{ +*/ +/********************** PlbArb statuses 1276 - 1300 **************************/ + +#define XST_PLBARB_FAIL_SELFTEST 1276L +/** @} */ +/** +@name Plb2Opb Status Codes 1301 - 1325 +@{ +*/ +/********************** Plb2Opb statuses 1301 - 1325 *************************/ + +#define XST_PLB2OPB_FAIL_SELFTEST 1301L +/** @} */ +/** +@name Opb2Plb Status 1326 - 1350 +@{ +*/ +/********************** Opb2Plb statuses 1326 - 1350 *************************/ + +#define XST_OPB2PLB_FAIL_SELFTEST 1326L +/** @} */ +/** +@name SysAce Status Codes 1351 - 1360 +@{ +*/ +/********************** SysAce statuses 1351 - 1360 **************************/ + +#define XST_SYSACE_NO_LOCK 1351L /*!< No MPU lock has been granted */ +/** @} */ +/** +@name PCI Bridge Status Codes 1361 - 1375 +@{ +*/ +/********************** PCI Bridge statuses 1361 - 1375 **********************/ + +#define XST_PCI_INVALID_ADDRESS 1361L +/** @} */ +/** +@name FlexRay Constants 1400 - 1409 +@{ +*/ +/********************** FlexRay constants 1400 - 1409 *************************/ + +#define XST_FR_TX_ERROR 1400 +#define XST_FR_TX_BUSY 1401 +#define XST_FR_BUF_LOCKED 1402 +#define XST_FR_NO_BUF 1403 +/** @} */ +/** +@name USB constants 1410 - 1420 +@{ +*/ +/****************** USB constants 1410 - 1420 *******************************/ + +#define XST_USB_ALREADY_CONFIGURED 1410 +#define XST_USB_BUF_ALIGN_ERROR 1411 +#define XST_USB_NO_DESC_AVAILABLE 1412 +#define XST_USB_BUF_TOO_BIG 1413 +#define XST_USB_NO_BUF 1414 +/** @} */ +/** +@name HWICAP constants 1421 - 1429 +@{ +*/ +/****************** HWICAP constants 1421 - 1429 *****************************/ + +#define XST_HWICAP_WRITE_DONE 1421 + +/** @} */ +/** +@name AXI VDMA constants 1430 - 1440 +@{ +*/ +/****************** AXI VDMA constants 1430 - 1440 *****************************/ + +#define XST_VDMA_MISMATCH_ERROR 1430 +/** @} */ +/** +@name NAND Flash Status Codes 1441 - 1459 +@{ +*/ +/*********************** NAND Flash statuses 1441 - 1459 *********************/ + +#define XST_NAND_BUSY 1441L /*!< Flash is erasing or + * programming + */ +#define XST_NAND_READY 1442L /*!< Flash is ready for commands + */ +#define XST_NAND_ERROR 1443L /*!< Flash had detected an + * internal error. + */ +#define XST_NAND_PART_NOT_SUPPORTED 1444L /*!< Flash type not supported by + * driver + */ +#define XST_NAND_OPT_NOT_SUPPORTED 1445L /*!< Operation not supported + */ +#define XST_NAND_TIMEOUT_ERROR 1446L /*!< Programming or erase + * operation aborted due to a + * timeout + */ +#define XST_NAND_ADDRESS_ERROR 1447L /*!< Accessed flash outside its + * addressible range + */ +#define XST_NAND_ALIGNMENT_ERROR 1448L /*!< Write alignment error + */ +#define XST_NAND_PARAM_PAGE_ERROR 1449L /*!< Failed to read parameter + * page of the device + */ +#define XST_NAND_CACHE_ERROR 1450L /*!< Flash page buffer error + */ + +#define XST_NAND_WRITE_PROTECTED 1451L /*!< Flash is write protected + */ +/** @} */ + +/**************************** Type Definitions *******************************/ + +typedef s32 XStatus; + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** +* @} End of "addtogroup common_status_codes". +*/ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/include/xtime_l.h b/datalink814_ge/bsp/ps7_cortexa9_0/include/xtime_l.h new file mode 100644 index 0000000..12004e1 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/include/xtime_l.h @@ -0,0 +1,104 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file xtime_l.h +* @addtogroup a9_time_apis Cortex A9 Time Functions +* +* xtime_l.h provides access to the 64-bit Global Counter in the PMU. This +* counter increases by one at every two processor cycles. These functions can +* be used to get/set time in the global timer. +* +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ------ -------- ---------------------------------------------------
+* 1.00a rp/sdm 11/03/09 Initial release.
+* 3.06a sgd    05/15/12 Upadted get/set time functions to make use Global Timer
+* 3.06a asa    06/17/12 Reverted back the changes to make use Global Timer.
+* 3.07a sgd    07/05/12 Upadted get/set time functions to make use Global Timer
+* 6.6   srm    10/23/17 Updated the macros to support user configurable sleep
+*						implementation
+* 6.8   aru  09/06/18 Removed compilation warnings for ARMCC toolchain.
+* 
+* +******************************************************************************/ + +#ifndef XTIME_H /* prevent circular inclusions */ +#define XTIME_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xparameters.h" + +/***************** Macros (Inline Functions) Definitions *********************/ + +/**************************** Type Definitions *******************************/ + +typedef u64 XTime; + +/************************** Constant Definitions *****************************/ +#define GLOBAL_TMR_BASEADDR XPAR_GLOBAL_TMR_BASEADDR +#define GTIMER_COUNTER_LOWER_OFFSET 0x00U +#define GTIMER_COUNTER_UPPER_OFFSET 0x04U +#define GTIMER_CONTROL_OFFSET 0x08U + +#if defined (SLEEP_TIMER_BASEADDR) +#define COUNTS_PER_SECOND (SLEEP_TIMER_FREQUENCY) +#else +/* Global Timer is always clocked at half of the CPU frequency */ +#define COUNTS_PER_SECOND (XPAR_CPU_CORTEXA9_CORE_CLOCK_FREQ_HZ /2) +#endif + +#if defined (XSLEEP_TIMER_IS_DEFAULT_TIMER) +#ifdef __GNUC__ +#pragma message ("For the sleep routines, Global timer is being used") +#endif +#endif +/************************** Variable Definitions *****************************/ + +/************************** Function Prototypes ******************************/ + +void XTime_SetTime(XTime Xtime_Global); +void XTime_GetTime(XTime *Xtime_Global); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* XTIME_H */ +/** +* @} End of "addtogroup a9_time_apis". +*/ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/include/xuartps.h b/datalink814_ge/bsp/ps7_cortexa9_0/include/xuartps.h new file mode 100644 index 0000000..c6c2a0a --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/include/xuartps.h @@ -0,0 +1,517 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xuartps.h +* @addtogroup uartps_v3_5 +* @{ +* @details +* +* This driver supports the following features: +* +* - Dynamic data format (baud rate, data bits, stop bits, parity) +* - Polled mode +* - Interrupt driven mode +* - Transmit and receive FIFOs (32 byte FIFO depth) +* - Access to the external modem control lines +* +* Initialization & Configuration +* +* The XUartPs_Config structure is used by the driver to configure itself. +* Fields inside this structure are properties of XUartPs based on its hardware +* build. +* +* To support multiple runtime loading and initialization strategies employed +* by various operating systems, the driver instance can be initialized in the +* following way: +* +* - XUartPs_CfgInitialize(InstancePtr, CfgPtr, EffectiveAddr) - Uses a +* configuration structure provided by the caller. If running in a system +* with address translation, the parameter EffectiveAddr should be the +* virtual address. +* +* Baud Rate +* +* The UART has an internal baud rate generator, which furnishes the baud rate +* clock for both the receiver and the transmitter. Ther input clock frequency +* can be either the master clock or the master clock divided by 8, configured +* through the mode register. +* +* Accompanied with the baud rate divider register, the baud rate is determined +* by: +*
+*	baud_rate = input_clock / (bgen * (bdiv + 1)
+* 
+* where bgen is the value of the baud rate generator, and bdiv is the value of +* baud rate divider. +* +* Interrupts +* +* The FIFOs are not flushed when the driver is initialized, but a function is +* provided to allow the user to reset the FIFOs if desired. +* +* The driver defaults to no interrupts at initialization such that interrupts +* must be enabled if desired. An interrupt is generated for one of the +* following conditions. +* +* - A change in the modem signals +* - Data in the receive FIFO for a configuable time without receiver activity +* - A parity error +* - A framing error +* - An overrun error +* - Transmit FIFO is full +* - Transmit FIFO is empty +* - Receive FIFO is full +* - Receive FIFO is empty +* - Data in the receive FIFO equal to the receive threshold +* +* The application can control which interrupts are enabled using the +* XUartPs_SetInterruptMask() function. +* +* In order to use interrupts, it is necessary for the user to connect the +* driver interrupt handler, XUartPs_InterruptHandler(), to the interrupt +* system of the application. A separate handler should be provided by the +* application to communicate with the interrupt system, and conduct +* application specific interrupt handling. An application registers its own +* handler through the XUartPs_SetHandler() function. +* +* Data Transfer +* +* The functions, XUartPs_Send() and XUartPs_Recv(), are provided in the +* driver to allow data to be sent and received. They can be used in either +* polled or interrupt mode. +* +* @note +* +* The default configuration for the UART after initialization is: +* +* - 9,600 bps or XPAR_DFT_BAUDRATE if defined +* - 8 data bits +* - 1 stop bit +* - no parity +* - FIFO's are enabled with a receive threshold of 8 bytes +* - The RX timeout is enabled with a timeout of 1 (4 char times) +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date	Changes
+* ----- ------ -------- ----------------------------------------------
+* 1.00a	drg/jz 01/12/10 First Release
+* 1.00a sdm    09/27/11 Fixed compiler warnings and also a bug
+*		        in XUartPs_SetFlowDelay where the value was not
+*			being written to the register.
+* 1.01a sdm    12/20/11 Removed the InputClockHz parameter from the XUartPs
+*			instance structure and the driver is updated to use
+*			InputClockHz parameter from the XUartPs_Config config
+*			structure.
+*			Added a parameter to XUartPs_Config structure which
+*			specifies whether the user has selected Modem pins
+*			to be connected to MIO or FMIO.
+*			Added the tcl file to generate the xparameters.h
+* 1.02a sg     05/16/12	Changed XUARTPS_RXWM_MASK to 0x3F for CR 652540 fix.
+* 1.03a sg     07/16/12 Updated XUARTPS_FORMAT_7_BITS and XUARTPS_FORMAT_6_BITS
+*			with the correct values for CR 666724
+* 			Added defines for XUARTPS_IXR_TOVR,  XUARTPS_IXR_TNFUL
+*			and XUARTPS_IXR_TTRIG.
+*			Modified the name of these defines
+*			XUARTPS_MEDEMSR_DCDX to XUARTPS_MODEMSR_DDCD
+*			XUARTPS_MEDEMSR_RIX to XUARTPS_MODEMSR_TERI
+*			XUARTPS_MEDEMSR_DSRX to XUARTPS_MODEMSR_DDSR
+*			XUARTPS_MEDEMSR_CTSX to XUARTPS_MODEMSR_DCTS
+* 1.05a hk     08/22/13 Added API for uart reset and related
+*			constant definitions.
+* 2.0   hk      03/07/14 Version number revised.
+* 2.1   hk     04/16/14 Change XUARTPS_MAX_RATE to 921600. CR# 780625.
+* 2.2   hk     06/23/14 SW reset of RX and TX should be done when changing
+*                       baud rate. CR# 804281.
+* 3.0   vm     12/09/14 Modified source code according to misrac guideline.
+*			Support for Zynq Ultrascale Mp added.
+* 3.1	kvn    04/10/15 Modified code for latest RTL changes. Also added
+*						platform variable in driver instance structure.
+* 3.1   adk   14/03/16  Include interrupt examples in the peripheral test when
+*			uart is connected to a valid interrupt controller CR#946803.
+* 3.2   rk     07/20/16 Modified the logic for transmission break bit set
+* 3.4   ms     01/23/17 Added xil_printf statement in main function for all
+*                       examples to ensure that "Successfully ran" and "Failed"
+*                       strings are available in all examples. This is a fix
+*                       for CR-965028.
+*       ms     03/17/17 Added readme.txt file in examples folder for doxygen
+*                       generation.
+* 3.6   ms     02/16/18 Updates the flow control mode offset value in modem
+*                       control register.
+* 3.7   aru    08/17/18 Resolved MISRA-C:2012 compliance mandatory violations.
+*
+* 
+* +*****************************************************************************/ + +#ifndef XUARTPS_H /* prevent circular inclusions */ +#define XUARTPS_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files ********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xstatus.h" +#include "xuartps_hw.h" +#include "xplatform_info.h" + +/************************** Constant Definitions ****************************/ + +/* + * The following constants indicate the max and min baud rates and these + * numbers are based only on the testing that has been done. The hardware + * is capable of other baud rates. + */ +#define XUARTPS_MAX_RATE 921600U +#define XUARTPS_MIN_RATE 110U + +#define XUARTPS_DFT_BAUDRATE 115200U /* Default baud rate */ + +/** @name Configuration options + * @{ + */ +/** + * These constants specify the options that may be set or retrieved + * with the driver, each is a unique bit mask such that multiple options + * may be specified. These constants indicate the available options + * in active state. + * + */ + +#define XUARTPS_OPTION_SET_BREAK 0x0080U /**< Starts break transmission */ +#define XUARTPS_OPTION_STOP_BREAK 0x0040U /**< Stops break transmission */ +#define XUARTPS_OPTION_RESET_TMOUT 0x0020U /**< Reset the receive timeout */ +#define XUARTPS_OPTION_RESET_TX 0x0010U /**< Reset the transmitter */ +#define XUARTPS_OPTION_RESET_RX 0x0008U /**< Reset the receiver */ +#define XUARTPS_OPTION_ASSERT_RTS 0x0004U /**< Assert the RTS bit */ +#define XUARTPS_OPTION_ASSERT_DTR 0x0002U /**< Assert the DTR bit */ +#define XUARTPS_OPTION_SET_FCM 0x0001U /**< Turn on flow control mode */ +/*@}*/ + + +/** @name Channel Operational Mode + * + * The UART can operate in one of four modes: Normal, Local Loopback, Remote + * Loopback, or automatic echo. + * + * @{ + */ + +#define XUARTPS_OPER_MODE_NORMAL (u8)0x00U /**< Normal Mode */ +#define XUARTPS_OPER_MODE_AUTO_ECHO (u8)0x01U /**< Auto Echo Mode */ +#define XUARTPS_OPER_MODE_LOCAL_LOOP (u8)0x02U /**< Local Loopback Mode */ +#define XUARTPS_OPER_MODE_REMOTE_LOOP (u8)0x03U /**< Remote Loopback Mode */ + +/* @} */ + +/** @name Data format values + * + * These constants specify the data format that the driver supports. + * The data format includes the number of data bits, the number of stop + * bits and parity. + * + * @{ + */ +#define XUARTPS_FORMAT_8_BITS 0U /**< 8 data bits */ +#define XUARTPS_FORMAT_7_BITS 2U /**< 7 data bits */ +#define XUARTPS_FORMAT_6_BITS 3U /**< 6 data bits */ + +#define XUARTPS_FORMAT_NO_PARITY 4U /**< No parity */ +#define XUARTPS_FORMAT_MARK_PARITY 3U /**< Mark parity */ +#define XUARTPS_FORMAT_SPACE_PARITY 2U /**< parity */ +#define XUARTPS_FORMAT_ODD_PARITY 1U /**< Odd parity */ +#define XUARTPS_FORMAT_EVEN_PARITY 0U /**< Even parity */ + +#define XUARTPS_FORMAT_2_STOP_BIT 2U /**< 2 stop bits */ +#define XUARTPS_FORMAT_1_5_STOP_BIT 1U /**< 1.5 stop bits */ +#define XUARTPS_FORMAT_1_STOP_BIT 0U /**< 1 stop bit */ +/*@}*/ + +/** @name Callback events + * + * These constants specify the handler events that an application can handle + * using its specific handler function. Note that these constants are not bit + * mask, so only one event can be passed to an application at a time. + * + * @{ + */ +#define XUARTPS_EVENT_RECV_DATA 1U /**< Data receiving done */ +#define XUARTPS_EVENT_RECV_TOUT 2U /**< A receive timeout occurred */ +#define XUARTPS_EVENT_SENT_DATA 3U /**< Data transmission done */ +#define XUARTPS_EVENT_RECV_ERROR 4U /**< A receive error detected */ +#define XUARTPS_EVENT_MODEM 5U /**< Modem status changed */ +#define XUARTPS_EVENT_PARE_FRAME_BRKE 6U /**< A receive parity, frame, break + * error detected */ +#define XUARTPS_EVENT_RECV_ORERR 7U /**< A receive overrun error detected */ +/*@}*/ + + +/**************************** Type Definitions ******************************/ + +/** + * This typedef contains configuration information for the device. + */ +typedef struct { + u16 DeviceId; /**< Unique ID of device */ + u32 BaseAddress; /**< Base address of device (IPIF) */ + u32 InputClockHz;/**< Input clock frequency */ + s32 ModemPinsConnected; /** Specifies whether modem pins are connected + * to MIO or FMIO */ +} XUartPs_Config; + +/* Keep track of state information about a data buffer in the interrupt mode. */ +typedef struct { + u8 *NextBytePtr; + u32 RequestedBytes; + u32 RemainingBytes; +} XUartPsBuffer; + +/** + * Keep track of data format setting of a device. + */ +typedef struct { + u32 BaudRate; /**< In bps, ie 1200 */ + u32 DataBits; /**< Number of data bits */ + u32 Parity; /**< Parity */ + u8 StopBits; /**< Number of stop bits */ +} XUartPsFormat; + +/******************************************************************************/ +/** + * This data type defines a handler that an application defines to communicate + * with interrupt system to retrieve state information about an application. + * + * @param CallBackRef is a callback reference passed in by the upper layer + * when setting the handler, and is passed back to the upper layer + * when the handler is called. It is used to find the device driver + * instance. + * @param Event contains one of the event constants indicating events that + * have occurred. + * @param EventData contains the number of bytes sent or received at the + * time of the call for send and receive events and contains the + * modem status for modem events. + * + ******************************************************************************/ +typedef void (*XUartPs_Handler) (void *CallBackRef, u32 Event, + u32 EventData); + +/** + * The XUartPs driver instance data structure. A pointer to an instance data + * structure is passed around by functions to refer to a specific driver + * instance. + */ +typedef struct { + XUartPs_Config Config; /* Configuration data structure */ + u32 InputClockHz; /* Input clock frequency */ + u32 IsReady; /* Device is initialized and ready */ + u32 BaudRate; /* Current baud rate */ + + XUartPsBuffer SendBuffer; + XUartPsBuffer ReceiveBuffer; + + XUartPs_Handler Handler; + void *CallBackRef; /* Callback reference for event handler */ + u32 Platform; + u8 is_rxbs_error; +} XUartPs; + + +/***************** Macros (Inline Functions) Definitions ********************/ + +/****************************************************************************/ +/** +* Get the UART Channel Status Register. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* +* @return The value read from the register. +* +* @note C-Style signature: +* u16 XUartPs_GetChannelStatus(XUartPs *InstancePtr) +* +******************************************************************************/ +#define XUartPs_GetChannelStatus(InstancePtr) \ + Xil_In32(((InstancePtr)->Config.BaseAddress) + (u32)XUARTPS_SR_OFFSET) + +/****************************************************************************/ +/** +* Get the UART Mode Control Register. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* +* @return The value read from the register. +* +* @note C-Style signature: +* u32 XUartPs_GetControl(XUartPs *InstancePtr) +* +******************************************************************************/ +#define XUartPs_GetModeControl(InstancePtr) \ + Xil_In32(((InstancePtr)->Config.BaseAddress) + (u32)XUARTPS_CR_OFFSET) + +/****************************************************************************/ +/** +* Set the UART Mode Control Register. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* @param RegisterValue is the value to be written to the register. +* +* @return None. +* +* @note C-Style signature: +* void XUartPs_SetModeControl(XUartPs *InstancePtr, u16 RegisterValue) +* +******************************************************************************/ +#define XUartPs_SetModeControl(InstancePtr, RegisterValue) \ + Xil_Out32(((InstancePtr)->Config.BaseAddress) + (u32)XUARTPS_CR_OFFSET, \ + (u32)(RegisterValue)) + +/****************************************************************************/ +/** +* Enable the transmitter and receiver of the UART. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* +* @return None. +* +* @note C-Style signature: +* void XUartPs_EnableUart(XUartPs *InstancePtr) +* +******************************************************************************/ +#define XUartPs_EnableUart(InstancePtr) \ + Xil_Out32(((InstancePtr)->Config.BaseAddress + (u32)XUARTPS_CR_OFFSET), \ + ((Xil_In32((InstancePtr)->Config.BaseAddress + (u32)XUARTPS_CR_OFFSET) & \ + (u32)(~XUARTPS_CR_EN_DIS_MASK)) | ((u32)XUARTPS_CR_RX_EN | (u32)XUARTPS_CR_TX_EN))) + +/****************************************************************************/ +/** +* Disable the transmitter and receiver of the UART. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* +* @return None. +* +* @note C-Style signature: +* void XUartPs_DisableUart(XUartPs *InstancePtr) +* +******************************************************************************/ +#define XUartPs_DisableUart(InstancePtr) \ + Xil_Out32(((InstancePtr)->Config.BaseAddress + (u32)XUARTPS_CR_OFFSET), \ + (((Xil_In32((InstancePtr)->Config.BaseAddress + (u32)XUARTPS_CR_OFFSET)) & \ + (u32)(~XUARTPS_CR_EN_DIS_MASK)) | ((u32)XUARTPS_CR_RX_DIS | (u32)XUARTPS_CR_TX_DIS))) + +/****************************************************************************/ +/** +* Determine if the transmitter FIFO is empty. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* +* @return +* - TRUE if a byte can be sent +* - FALSE if the Transmitter Fifo is not empty +* +* @note C-Style signature: +* u32 XUartPs_IsTransmitEmpty(XUartPs InstancePtr) +* +******************************************************************************/ +#define XUartPs_IsTransmitEmpty(InstancePtr) \ + ((Xil_In32(((InstancePtr)->Config.BaseAddress) + (u32)XUARTPS_SR_OFFSET) & \ + (u32)XUARTPS_SR_TXEMPTY) == (u32)XUARTPS_SR_TXEMPTY) + + +/************************** Function Prototypes *****************************/ + +/* Static lookup function implemented in xuartps_sinit.c */ +XUartPs_Config *XUartPs_LookupConfig(u16 DeviceId); + +/* Interface functions implemented in xuartps.c */ +s32 XUartPs_CfgInitialize(XUartPs *InstancePtr, + XUartPs_Config * Config, u32 EffectiveAddr); + +u32 XUartPs_Send(XUartPs *InstancePtr,u8 *BufferPtr, + u32 NumBytes); + +u32 XUartPs_Recv(XUartPs *InstancePtr,u8 *BufferPtr, + u32 NumBytes); + +s32 XUartPs_SetBaudRate(XUartPs *InstancePtr, u32 BaudRate); + +/* Options functions in xuartps_options.c */ +void XUartPs_SetOptions(XUartPs *InstancePtr, u16 Options); + +u16 XUartPs_GetOptions(XUartPs *InstancePtr); + +void XUartPs_SetFifoThreshold(XUartPs *InstancePtr, u8 TriggerLevel); + +u8 XUartPs_GetFifoThreshold(XUartPs *InstancePtr); + +u16 XUartPs_GetModemStatus(XUartPs *InstancePtr); + +u32 XUartPs_IsSending(XUartPs *InstancePtr); + +u8 XUartPs_GetOperMode(XUartPs *InstancePtr); + +void XUartPs_SetOperMode(XUartPs *InstancePtr, u8 OperationMode); + +u8 XUartPs_GetFlowDelay(XUartPs *InstancePtr); + +void XUartPs_SetFlowDelay(XUartPs *InstancePtr, u8 FlowDelayValue); + +u8 XUartPs_GetRecvTimeout(XUartPs *InstancePtr); + +void XUartPs_SetRecvTimeout(XUartPs *InstancePtr, u8 RecvTimeout); + +s32 XUartPs_SetDataFormat(XUartPs *InstancePtr, XUartPsFormat * FormatPtr); + +void XUartPs_GetDataFormat(XUartPs *InstancePtr, XUartPsFormat * FormatPtr); + +/* interrupt functions in xuartps_intr.c */ +u32 XUartPs_GetInterruptMask(XUartPs *InstancePtr); + +void XUartPs_SetInterruptMask(XUartPs *InstancePtr, u32 Mask); + +void XUartPs_InterruptHandler(XUartPs *InstancePtr); + +void XUartPs_SetHandler(XUartPs *InstancePtr, XUartPs_Handler FuncPtr, + void *CallBackRef); + +/* self-test functions in xuartps_selftest.c */ +s32 XUartPs_SelfTest(XUartPs *InstancePtr); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/include/xuartps_hw.h b/datalink814_ge/bsp/ps7_cortexa9_0/include/xuartps_hw.h new file mode 100644 index 0000000..8c46ecf --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/include/xuartps_hw.h @@ -0,0 +1,447 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2017 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xuartps_hw.h +* @addtogroup uartps_v3_5 +* @{ +* +* This header file contains the hardware interface of an XUartPs device. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date	Changes
+* ----- ------ -------- ----------------------------------------------
+* 1.00	drg/jz 01/12/10 First Release
+* 1.03a sg     09/04/12 Added defines for XUARTPS_IXR_TOVR,  XUARTPS_IXR_TNFUL
+*			and XUARTPS_IXR_TTRIG.
+*			Modified the names of these defines
+*			XUARTPS_MEDEMSR_DCDX to XUARTPS_MODEMSR_DDCD
+*			XUARTPS_MEDEMSR_RIX to XUARTPS_MODEMSR_TERI
+*			XUARTPS_MEDEMSR_DSRX to XUARTPS_MODEMSR_DDSR
+*			XUARTPS_MEDEMSR_CTSX to XUARTPS_MODEMSR_DCTS
+* 1.05a hk     08/22/13 Added prototype for uart reset and related
+*			constant definitions.
+* 3.00  kvn    02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.1	kvn    04/10/15 Modified code for latest RTL changes.
+* 3.6   ms     02/16/18 Updates flow control mode offset value in
+*			modem control register.
+*
+* 
+* +******************************************************************************/ +#ifndef XUARTPS_HW_H /* prevent circular inclusions */ +#define XUARTPS_HW_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_io.h" + +/************************** Constant Definitions *****************************/ + +/** @name Register Map + * + * Register offsets for the UART. + * @{ + */ +#define XUARTPS_CR_OFFSET 0x0000U /**< Control Register [8:0] */ +#define XUARTPS_MR_OFFSET 0x0004U /**< Mode Register [9:0] */ +#define XUARTPS_IER_OFFSET 0x0008U /**< Interrupt Enable [12:0] */ +#define XUARTPS_IDR_OFFSET 0x000CU /**< Interrupt Disable [12:0] */ +#define XUARTPS_IMR_OFFSET 0x0010U /**< Interrupt Mask [12:0] */ +#define XUARTPS_ISR_OFFSET 0x0014U /**< Interrupt Status [12:0]*/ +#define XUARTPS_BAUDGEN_OFFSET 0x0018U /**< Baud Rate Generator [15:0] */ +#define XUARTPS_RXTOUT_OFFSET 0x001CU /**< RX Timeout [7:0] */ +#define XUARTPS_RXWM_OFFSET 0x0020U /**< RX FIFO Trigger Level [5:0] */ +#define XUARTPS_MODEMCR_OFFSET 0x0024U /**< Modem Control [5:0] */ +#define XUARTPS_MODEMSR_OFFSET 0x0028U /**< Modem Status [8:0] */ +#define XUARTPS_SR_OFFSET 0x002CU /**< Channel Status [14:0] */ +#define XUARTPS_FIFO_OFFSET 0x0030U /**< FIFO [7:0] */ +#define XUARTPS_BAUDDIV_OFFSET 0x0034U /**< Baud Rate Divider [7:0] */ +#define XUARTPS_FLOWDEL_OFFSET 0x0038U /**< Flow Delay [5:0] */ +#define XUARTPS_TXWM_OFFSET 0x0044U /**< TX FIFO Trigger Level [5:0] */ +#define XUARTPS_RXBS_OFFSET 0x0048U /**< RX FIFO Byte Status [11:0] */ +/* @} */ + +/** @name Control Register + * + * The Control register (CR) controls the major functions of the device. + * + * Control Register Bit Definition + */ + +#define XUARTPS_CR_STOPBRK 0x00000100U /**< Stop transmission of break */ +#define XUARTPS_CR_STARTBRK 0x00000080U /**< Set break */ +#define XUARTPS_CR_TORST 0x00000040U /**< RX timeout counter restart */ +#define XUARTPS_CR_TX_DIS 0x00000020U /**< TX disabled. */ +#define XUARTPS_CR_TX_EN 0x00000010U /**< TX enabled */ +#define XUARTPS_CR_RX_DIS 0x00000008U /**< RX disabled. */ +#define XUARTPS_CR_RX_EN 0x00000004U /**< RX enabled */ +#define XUARTPS_CR_EN_DIS_MASK 0x0000003CU /**< Enable/disable Mask */ +#define XUARTPS_CR_TXRST 0x00000002U /**< TX logic reset */ +#define XUARTPS_CR_RXRST 0x00000001U /**< RX logic reset */ +/* @}*/ + + +/** @name Mode Register + * + * The mode register (MR) defines the mode of transfer as well as the data + * format. If this register is modified during transmission or reception, + * data validity cannot be guaranteed. + * + * Mode Register Bit Definition + * @{ + */ +#define XUARTPS_MR_CCLK 0x00000400U /**< Input clock selection */ +#define XUARTPS_MR_CHMODE_R_LOOP 0x00000300U /**< Remote loopback mode */ +#define XUARTPS_MR_CHMODE_L_LOOP 0x00000200U /**< Local loopback mode */ +#define XUARTPS_MR_CHMODE_ECHO 0x00000100U /**< Auto echo mode */ +#define XUARTPS_MR_CHMODE_NORM 0x00000000U /**< Normal mode */ +#define XUARTPS_MR_CHMODE_SHIFT 8U /**< Mode shift */ +#define XUARTPS_MR_CHMODE_MASK 0x00000300U /**< Mode mask */ +#define XUARTPS_MR_STOPMODE_2_BIT 0x00000080U /**< 2 stop bits */ +#define XUARTPS_MR_STOPMODE_1_5_BIT 0x00000040U /**< 1.5 stop bits */ +#define XUARTPS_MR_STOPMODE_1_BIT 0x00000000U /**< 1 stop bit */ +#define XUARTPS_MR_STOPMODE_SHIFT 6U /**< Stop bits shift */ +#define XUARTPS_MR_STOPMODE_MASK 0x000000A0U /**< Stop bits mask */ +#define XUARTPS_MR_PARITY_NONE 0x00000020U /**< No parity mode */ +#define XUARTPS_MR_PARITY_MARK 0x00000018U /**< Mark parity mode */ +#define XUARTPS_MR_PARITY_SPACE 0x00000010U /**< Space parity mode */ +#define XUARTPS_MR_PARITY_ODD 0x00000008U /**< Odd parity mode */ +#define XUARTPS_MR_PARITY_EVEN 0x00000000U /**< Even parity mode */ +#define XUARTPS_MR_PARITY_SHIFT 3U /**< Parity setting shift */ +#define XUARTPS_MR_PARITY_MASK 0x00000038U /**< Parity mask */ +#define XUARTPS_MR_CHARLEN_6_BIT 0x00000006U /**< 6 bits data */ +#define XUARTPS_MR_CHARLEN_7_BIT 0x00000004U /**< 7 bits data */ +#define XUARTPS_MR_CHARLEN_8_BIT 0x00000000U /**< 8 bits data */ +#define XUARTPS_MR_CHARLEN_SHIFT 1U /**< Data Length shift */ +#define XUARTPS_MR_CHARLEN_MASK 0x00000006U /**< Data length mask */ +#define XUARTPS_MR_CLKSEL 0x00000001U /**< Input clock selection */ +/* @} */ + + +/** @name Interrupt Registers + * + * Interrupt control logic uses the interrupt enable register (IER) and the + * interrupt disable register (IDR) to set the value of the bits in the + * interrupt mask register (IMR). The IMR determines whether to pass an + * interrupt to the interrupt status register (ISR). + * Writing a 1 to IER Enbables an interrupt, writing a 1 to IDR disables an + * interrupt. IMR and ISR are read only, and IER and IDR are write only. + * Reading either IER or IDR returns 0x00. + * + * All four registers have the same bit definitions. + * + * @{ + */ +#define XUARTPS_IXR_RBRK 0x00002000U /**< Rx FIFO break detect interrupt */ +#define XUARTPS_IXR_TOVR 0x00001000U /**< Tx FIFO Overflow interrupt */ +#define XUARTPS_IXR_TNFUL 0x00000800U /**< Tx FIFO Nearly Full interrupt */ +#define XUARTPS_IXR_TTRIG 0x00000400U /**< Tx Trig interrupt */ +#define XUARTPS_IXR_DMS 0x00000200U /**< Modem status change interrupt */ +#define XUARTPS_IXR_TOUT 0x00000100U /**< Timeout error interrupt */ +#define XUARTPS_IXR_PARITY 0x00000080U /**< Parity error interrupt */ +#define XUARTPS_IXR_FRAMING 0x00000040U /**< Framing error interrupt */ +#define XUARTPS_IXR_OVER 0x00000020U /**< Overrun error interrupt */ +#define XUARTPS_IXR_TXFULL 0x00000010U /**< TX FIFO full interrupt. */ +#define XUARTPS_IXR_TXEMPTY 0x00000008U /**< TX FIFO empty interrupt. */ +#define XUARTPS_IXR_RXFULL 0x00000004U /**< RX FIFO full interrupt. */ +#define XUARTPS_IXR_RXEMPTY 0x00000002U /**< RX FIFO empty interrupt. */ +#define XUARTPS_IXR_RXOVR 0x00000001U /**< RX FIFO trigger interrupt. */ +#define XUARTPS_IXR_MASK 0x00003FFFU /**< Valid bit mask */ +/* @} */ + + +/** @name Baud Rate Generator Register + * + * The baud rate generator control register (BRGR) is a 16 bit register that + * controls the receiver bit sample clock and baud rate. + * Valid values are 1 - 65535. + * + * Bit Sample Rate = CCLK / BRGR, where the CCLK is selected by the MR_CCLK bit + * in the MR register. + * @{ + */ +#define XUARTPS_BAUDGEN_DISABLE 0x00000000U /**< Disable clock */ +#define XUARTPS_BAUDGEN_MASK 0x0000FFFFU /**< Valid bits mask */ +#define XUARTPS_BAUDGEN_RESET_VAL 0x0000028BU /**< Reset value */ + +/** @name Baud Divisor Rate register + * + * The baud rate divider register (BDIV) controls how much the bit sample + * rate is divided by. It sets the baud rate. + * Valid values are 0x04 to 0xFF. Writing a value less than 4 will be ignored. + * + * Baud rate = CCLK / ((BAUDDIV + 1) x BRGR), where the CCLK is selected by + * the MR_CCLK bit in the MR register. + * @{ + */ +#define XUARTPS_BAUDDIV_MASK 0x000000FFU /**< 8 bit baud divider mask */ +#define XUARTPS_BAUDDIV_RESET_VAL 0x0000000FU /**< Reset value */ +/* @} */ + + +/** @name Receiver Timeout Register + * + * Use the receiver timeout register (RTR) to detect an idle condition on + * the receiver data line. + * + * @{ + */ +#define XUARTPS_RXTOUT_DISABLE 0x00000000U /**< Disable time out */ +#define XUARTPS_RXTOUT_MASK 0x000000FFU /**< Valid bits mask */ + +/** @name Receiver FIFO Trigger Level Register + * + * Use the Receiver FIFO Trigger Level Register (RTRIG) to set the value at + * which the RX FIFO triggers an interrupt event. + * @{ + */ + +#define XUARTPS_RXWM_DISABLE 0x00000000U /**< Disable RX trigger interrupt */ +#define XUARTPS_RXWM_MASK 0x0000003FU /**< Valid bits mask */ +#define XUARTPS_RXWM_RESET_VAL 0x00000020U /**< Reset value */ +/* @} */ + +/** @name Transmit FIFO Trigger Level Register + * + * Use the Transmit FIFO Trigger Level Register (TTRIG) to set the value at + * which the TX FIFO triggers an interrupt event. + * @{ + */ + +#define XUARTPS_TXWM_MASK 0x0000003FU /**< Valid bits mask */ +#define XUARTPS_TXWM_RESET_VAL 0x00000020U /**< Reset value */ +/* @} */ + +/** @name Modem Control Register + * + * This register (MODEMCR) controls the interface with the modem or data set, + * or a peripheral device emulating a modem. + * + * @{ + */ +#define XUARTPS_MODEMCR_FCM 0x00000020U /**< Flow control mode */ +#define XUARTPS_MODEMCR_RTS 0x00000002U /**< Request to send */ +#define XUARTPS_MODEMCR_DTR 0x00000001U /**< Data terminal ready */ +/* @} */ + +/** @name Modem Status Register + * + * This register (MODEMSR) indicates the current state of the control lines + * from a modem, or another peripheral device, to the CPU. In addition, four + * bits of the modem status register provide change information. These bits + * are set to a logic 1 whenever a control input from the modem changes state. + * + * Note: Whenever the DCTS, DDSR, TERI, or DDCD bit is set to logic 1, a modem + * status interrupt is generated and this is reflected in the modem status + * register. + * + * @{ + */ +#define XUARTPS_MODEMSR_FCMS 0x00000100U /**< Flow control mode (FCMS) */ +#define XUARTPS_MODEMSR_DCD 0x00000080U /**< Complement of DCD input */ +#define XUARTPS_MODEMSR_RI 0x00000040U /**< Complement of RI input */ +#define XUARTPS_MODEMSR_DSR 0x00000020U /**< Complement of DSR input */ +#define XUARTPS_MODEMSR_CTS 0x00000010U /**< Complement of CTS input */ +#define XUARTPS_MODEMSR_DDCD 0x00000008U /**< Delta DCD indicator */ +#define XUARTPS_MODEMSR_TERI 0x00000004U /**< Trailing Edge Ring Indicator */ +#define XUARTPS_MODEMSR_DDSR 0x00000002U /**< Change of DSR */ +#define XUARTPS_MODEMSR_DCTS 0x00000001U /**< Change of CTS */ +/* @} */ + +/** @name Channel Status Register + * + * The channel status register (CSR) is provided to enable the control logic + * to monitor the status of bits in the channel interrupt status register, + * even if these are masked out by the interrupt mask register. + * + * @{ + */ +#define XUARTPS_SR_TNFUL 0x00004000U /**< TX FIFO Nearly Full Status */ +#define XUARTPS_SR_TTRIG 0x00002000U /**< TX FIFO Trigger Status */ +#define XUARTPS_SR_FLOWDEL 0x00001000U /**< RX FIFO fill over flow delay */ +#define XUARTPS_SR_TACTIVE 0x00000800U /**< TX active */ +#define XUARTPS_SR_RACTIVE 0x00000400U /**< RX active */ +#define XUARTPS_SR_TXFULL 0x00000010U /**< TX FIFO full */ +#define XUARTPS_SR_TXEMPTY 0x00000008U /**< TX FIFO empty */ +#define XUARTPS_SR_RXFULL 0x00000004U /**< RX FIFO full */ +#define XUARTPS_SR_RXEMPTY 0x00000002U /**< RX FIFO empty */ +#define XUARTPS_SR_RXOVR 0x00000001U /**< RX FIFO fill over trigger */ +/* @} */ + +/** @name Flow Delay Register + * + * Operation of the flow delay register (FLOWDEL) is very similar to the + * receive FIFO trigger register. An internal trigger signal activates when the + * FIFO is filled to the level set by this register. This trigger will not + * cause an interrupt, although it can be read through the channel status + * register. In hardware flow control mode, RTS is deactivated when the trigger + * becomes active. RTS only resets when the FIFO level is four less than the + * level of the flow delay trigger and the flow delay trigger is not activated. + * A value less than 4 disables the flow delay. + * @{ + */ +#define XUARTPS_FLOWDEL_MASK XUARTPS_RXWM_MASK /**< Valid bit mask */ +/* @} */ + +/** @name Receiver FIFO Byte Status Register + * + * The Receiver FIFO Status register is used to have a continuous + * monitoring of the raw unmasked byte status information. The register + * contains frame, parity and break status information for the top + * four bytes in the RX FIFO. + * + * Receiver FIFO Byte Status Register Bit Definition + * @{ + */ +#define XUARTPS_RXBS_BYTE3_BRKE 0x00000800U /**< Byte3 Break Error */ +#define XUARTPS_RXBS_BYTE3_FRME 0x00000400U /**< Byte3 Frame Error */ +#define XUARTPS_RXBS_BYTE3_PARE 0x00000200U /**< Byte3 Parity Error */ +#define XUARTPS_RXBS_BYTE2_BRKE 0x00000100U /**< Byte2 Break Error */ +#define XUARTPS_RXBS_BYTE2_FRME 0x00000080U /**< Byte2 Frame Error */ +#define XUARTPS_RXBS_BYTE2_PARE 0x00000040U /**< Byte2 Parity Error */ +#define XUARTPS_RXBS_BYTE1_BRKE 0x00000020U /**< Byte1 Break Error */ +#define XUARTPS_RXBS_BYTE1_FRME 0x00000010U /**< Byte1 Frame Error */ +#define XUARTPS_RXBS_BYTE1_PARE 0x00000008U /**< Byte1 Parity Error */ +#define XUARTPS_RXBS_BYTE0_BRKE 0x00000004U /**< Byte0 Break Error */ +#define XUARTPS_RXBS_BYTE0_FRME 0x00000002U /**< Byte0 Frame Error */ +#define XUARTPS_RXBS_BYTE0_PARE 0x00000001U /**< Byte0 Parity Error */ +#define XUARTPS_RXBS_MASK 0x00000007U /**< 3 bit RX byte status mask */ +/* @} */ + + +/* + * Defines for backwards compatabilty, will be removed + * in the next version of the driver + */ +#define XUARTPS_MEDEMSR_DCDX XUARTPS_MODEMSR_DDCD +#define XUARTPS_MEDEMSR_RIX XUARTPS_MODEMSR_TERI +#define XUARTPS_MEDEMSR_DSRX XUARTPS_MODEMSR_DDSR +#define XUARTPS_MEDEMSR_CTSX XUARTPS_MODEMSR_DCTS + + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + +/****************************************************************************/ +/** +* Read a UART register. +* +* @param BaseAddress contains the base address of the device. +* @param RegOffset contains the offset from the base address of the +* device. +* +* @return The value read from the register. +* +* @note C-Style signature: +* u32 XUartPs_ReadReg(u32 BaseAddress, int RegOffset) +* +******************************************************************************/ +#define XUartPs_ReadReg(BaseAddress, RegOffset) \ + Xil_In32((BaseAddress) + (u32)(RegOffset)) + +/***************************************************************************/ +/** +* Write a UART register. +* +* @param BaseAddress contains the base address of the device. +* @param RegOffset contains the offset from the base address of the +* device. +* @param RegisterValue is the value to be written to the register. +* +* @return None. +* +* @note C-Style signature: +* void XUartPs_WriteReg(u32 BaseAddress, int RegOffset, +* u16 RegisterValue) +* +******************************************************************************/ +#define XUartPs_WriteReg(BaseAddress, RegOffset, RegisterValue) \ + Xil_Out32((BaseAddress) + (u32)(RegOffset), (u32)(RegisterValue)) + +/****************************************************************************/ +/** +* Determine if there is receive data in the receiver and/or FIFO. +* +* @param BaseAddress contains the base address of the device. +* +* @return TRUE if there is receive data, FALSE otherwise. +* +* @note C-Style signature: +* u32 XUartPs_IsReceiveData(u32 BaseAddress) +* +******************************************************************************/ +#define XUartPs_IsReceiveData(BaseAddress) \ + !((Xil_In32((BaseAddress) + XUARTPS_SR_OFFSET) & \ + (u32)XUARTPS_SR_RXEMPTY) == (u32)XUARTPS_SR_RXEMPTY) + +/****************************************************************************/ +/** +* Determine if a byte of data can be sent with the transmitter. +* +* @param BaseAddress contains the base address of the device. +* +* @return TRUE if the TX FIFO is full, FALSE if a byte can be put in the +* FIFO. +* +* @note C-Style signature: +* u32 XUartPs_IsTransmitFull(u32 BaseAddress) +* +******************************************************************************/ +#define XUartPs_IsTransmitFull(BaseAddress) \ + ((Xil_In32((BaseAddress) + XUARTPS_SR_OFFSET) & \ + (u32)XUARTPS_SR_TXFULL) == (u32)XUARTPS_SR_TXFULL) + +/************************** Function Prototypes ******************************/ + +void XUartPs_SendByte(u32 BaseAddress, u8 Data); + +u8 XUartPs_RecvByte(u32 BaseAddress); + +void XUartPs_ResetHw(u32 BaseAddress); + +/************************** Variable Definitions *****************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/bram_v4_3/src/Makefile b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/bram_v4_3/src/Makefile new file mode 100644 index 0000000..dce15aa --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/bram_v4_3/src/Makefile @@ -0,0 +1,28 @@ +COMPILER= +ARCHIVER= +CP=cp +COMPILER_FLAGS= +EXTRA_COMPILER_FLAGS= +LIB=libxil.a + +RELEASEDIR=../../../lib +INCLUDEDIR=../../../include +INCLUDES=-I./. -I${INCLUDEDIR} + +INCLUDEFILES=*.h + +LIBSOURCES=*.c +OUTS = *.o +OBJECTS = $(addsuffix .o, $(basename $(wildcard *.c))) + +libs: + echo "Compiling bram" + $(COMPILER) $(COMPILER_FLAGS) $(EXTRA_COMPILER_FLAGS) $(INCLUDES) $(LIBSOURCES) + $(ARCHIVER) -r ${RELEASEDIR}/${LIB} $(OBJECTS) + make clean + +include: + ${CP} ${INCLUDEFILES} ${INCLUDEDIR} + +clean: + rm -rf ${OBJECTS} diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/bram_v4_3/src/xbram.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/bram_v4_3/src/xbram.c new file mode 100644 index 0000000..0976b82 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/bram_v4_3/src/xbram.c @@ -0,0 +1,145 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +/** +* @file xbram.c +* @addtogroup bram_v4_2 +* @{ +* +* The implementation of the XBram driver's basic functionality. +* See xbram.h for more information about the driver. +* +* @note +* +* None +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a sa   05/11/10 First release
+* 3.01a sa   13/01/12 Added CorrectableFailingDataRegs and
+*                     UncorrectableFailingDataRegs in
+*					  XBram_CfgInitialize API.
+* 4.1   sk   11/10/15 Used UINTPTR instead of u32 for Baseaddress CR# 867425.
+*                     Changed the prototype of XBram_CfgInitialize API.
+*
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ + +#include "xbram.h" +#include "xstatus.h" + +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Variable Definitions ****************************/ + + +/************************** Function Prototypes *****************************/ + + +/****************************************************************************/ +/** +* Initialize the XBram instance provided by the caller based on the given +* configuration data. +* +* Nothing is done except to initialize the InstancePtr. +* +* @param InstancePtr is a pointer to an XBram instance. +* The memory the pointer references must be pre-allocated by +* the caller. Further calls to manipulate the driver through +* the XBram API must be made with this pointer. +* @param Config is a reference to a structure containing information +* about a specific BRAM device. This function +* initializes an InstancePtr object for a specific device +* specified by the contents of Config. This function can +* initialize multiple instance objects with the use of multiple +* calls giving different Config information on each call. +* @param EffectiveAddr is the device base address in the virtual memory +* address space. The caller is responsible for keeping the +* address mapping from EffectiveAddr to the device physical base +* address unchanged once this function is invoked. Unexpected +* errors may occur if the address mapping changes after this +* function is called. If address translation is not used, use +* Config->BaseAddress for this parameters, passing the physical +* address instead. +* +* @return +* - XST_SUCCESS Initialization was successful. +* +* @note None. +* +*****************************************************************************/ +int XBram_CfgInitialize(XBram *InstancePtr, + XBram_Config *Config, + UINTPTR EffectiveAddr) +{ + /* + * Assert arguments + */ + Xil_AssertNonvoid(InstancePtr != NULL); + + /* + * Set some default values. + */ + InstancePtr->Config.CtrlBaseAddress = EffectiveAddr; + InstancePtr->Config.MemBaseAddress = Config->MemBaseAddress; + InstancePtr->Config.MemHighAddress = Config->MemHighAddress; + InstancePtr->Config.DataWidth = Config->DataWidth; + InstancePtr->Config.EccPresent = Config->EccPresent; + InstancePtr->Config.FaultInjectionPresent = + Config->FaultInjectionPresent; + InstancePtr->Config.CorrectableFailingRegisters = + Config->CorrectableFailingRegisters; + InstancePtr->Config.CorrectableFailingDataRegs = + Config->CorrectableFailingDataRegs; + InstancePtr->Config.UncorrectableFailingRegisters = + Config->UncorrectableFailingRegisters; + InstancePtr->Config.UncorrectableFailingDataRegs = + Config->UncorrectableFailingDataRegs; + InstancePtr->Config.EccStatusInterruptPresent = + Config->EccStatusInterruptPresent; + InstancePtr->Config.CorrectableCounterBits = + Config->CorrectableCounterBits; + InstancePtr->Config.WriteAccess = Config->WriteAccess; + + /* + * Indicate the instance is now ready to use, initialized without error + */ + InstancePtr->IsReady = XIL_COMPONENT_IS_READY; + return (XST_SUCCESS); +} + +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/bram_v4_3/src/xbram.h b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/bram_v4_3/src/xbram.h new file mode 100644 index 0000000..246df6d --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/bram_v4_3/src/xbram.h @@ -0,0 +1,223 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file xbram.h +* @addtogroup bram_v4_2 +* @{ +* @details +* +* If ECC is not enabled, this driver exists only to allow the tools to +* create a memory test application and to populate xparameters.h with memory +* range constants. In this case there is no source code. +* +* If ECC is enabled, this file contains the software API definition of the +* Xilinx BRAM Interface Controller (XBram) device driver. +* +* The Xilinx BRAM controller is a soft IP core designed for Xilinx +* FPGAs and contains the following general features: +* - LMB v2.0 bus interfaces with byte enable support +* - Used in conjunction with bram_block peripheral to provide fast BRAM +* memory solution for MicroBlaze ILMB and DLMB ports +* - Supports byte, half-word, and word transfers +* - Supports optional BRAM error correction and detection. +* +* The driver provides interrupt management functions. Implementation of +* interrupt handlers is left to the user. Refer to the provided interrupt +* example in the examples directory for details. +* +* This driver is intended to be RTOS and processor independent. Any needs for +* dynamic memory management, threads or thread mutual exclusion, virtual +* memory, or cache control must be satisfied by the layer above this driver. +* +* Initialization & Configuration +* +* The XBram_Config structure is used by the driver to configure +* itself. This configuration structure is typically created by the tool-chain +* based on HW build properties. +* +* To support multiple runtime loading and initialization strategies employed +* by various operating systems, the driver instance can be initialized as +* follows: +* +* - XBram_CfgInitialize(InstancePtr, CfgPtr, EffectiveAddr) - +* Uses a configuration structure provided by the caller. If running in a +* system with address translation, the provided virtual memory base address +* replaces the physical address present in the configuration structure. +* +* @note +* +* This API utilizes 32 bit I/O to the BRAM registers. With less +* than 32 bits, the unused bits from registers are read as zero and written as +* don't cares. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 3.00a sa  05/11/10 Added ECC support
+* 3.01a sa  01/13/12  Changed Selftest API from
+*		      XBram_SelfTest(XBram *InstancePtr) to
+*		      XBram_SelfTest(XBram *InstancePtr, u8 IntMask) and
+*		      fixed a problem with interrupt generation for CR 639274
+*		      Modified Selftest example to return XST_SUCCESS when
+*		      ECC is not enabled and return XST_FAILURE when ECC is
+*		      enabled and Control Base Address is zero (CR 636581)
+*		      Modified Selftest to use correct CorrectableCounterBits
+*		      for CR 635655
+*		      Updated to check CorrectableFailingDataRegs in the case
+*		      of LMB BRAM.
+* 		      Added CorrectableFailingDataRegs and
+*		      UncorrectableFailingDataRegs to the config structure to
+*		      distinguish between AXI BRAM and LMB BRAM.
+*		      These registers are not present in the current version of
+*		      the AXI BRAM Controller.
+* 3.02a sa 04/16/12   Added test of byte and halfword read-modify-write
+* 3.02a sa 04/16/12   Modified driver tcl to sort the address parameters
+*  	       	      to support both xps and vivado designs.
+* 3.02a adk 24/4/13   Modified the tcl file to avoid warnings
+*	       	      when ecc is disabled cr:705002.
+* 3.03a bss 05/22/13  Added Xil_DCacheFlushRange in xbram_selftest.c to
+*		      flush the Cache after writing to BRAM in InjectErrors
+*		      API(CR #719011)
+* 4.0   adk  19/12/13 Updated as per the New Tcl API's
+* 4.1   sk   11/10/15 Used UINTPTR instead of u32 for Baseaddress CR# 867425.
+*                     Changed the prototype of XBram_CfgInitialize API.
+*       ms  01/23/17 Modified xil_printf statement in main function for all
+*                    examples to ensure that "Successfully ran" and "Failed"
+*                    strings are available in all examples. This is a fix
+*                    for CR-965028.
+*       ms  03/17/17 Added readme.txt file in examples folder for doxygen
+*                    generation.
+* 4.2   ms  04/18/17 Modified tcl file to add suffix U for all macro
+*                    definitions of bram in xparameters.h
+*       ms  08/07/17 Fixed compilation warnings in xbram_sinit.c
+* 4.3   aru 03/23/19 Used UINTPTR instead of u32 for MemBaseAddress and
+*                    MemHighAddress.
+* 
+*****************************************************************************/ +#ifndef XBRAM_H /* prevent circular inclusions */ +#define XBRAM_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files ********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xstatus.h" +#include "xbram_hw.h" + +/************************** Constant Definitions ****************************/ + + +/**************************** Type Definitions ******************************/ + +/** + * This typedef contains configuration information for the device. + */ +typedef struct { + u16 DeviceId; /**< Unique ID of device */ + u32 DataWidth; /**< BRAM data width */ + int EccPresent; /**< Is ECC supported in H/W */ + int FaultInjectionPresent; /**< Is Fault Injection + * supported in H/W */ + int CorrectableFailingRegisters; /**< Is Correctable Failing Registers + * supported in H/W */ + int CorrectableFailingDataRegs; /**< Is Correctable Failing Data + * Registers supported in H/W */ + int UncorrectableFailingRegisters; /**< Is Un-correctable Failing + * Registers supported in H/W */ + int UncorrectableFailingDataRegs; /**< Is Un-correctable Failing Data + * Registers supported in H/W */ + int EccStatusInterruptPresent; /**< Are ECC status and interrupts + * supported in H/W */ + int CorrectableCounterBits; /**< Number of bits in the + * Correctable Error Counter */ + int EccOnOffRegister; /**< Is ECC on/off register supported + * in h/w */ + int EccOnOffResetValue; /**< Reset value of the ECC on/off + * register in h/w */ + int WriteAccess; /**< Is write access enabled in + * h/w */ + UINTPTR MemBaseAddress; /**< Device memory base address */ + UINTPTR MemHighAddress; /**< Device memory high address */ + UINTPTR CtrlBaseAddress; /**< Device register base address.*/ + UINTPTR CtrlHighAddress; /**< Device register base address.*/ +} XBram_Config; + +/** + * The XBram driver instance data. The user is required to + * allocate a variable of this type for every BRAM device in the + * system. A pointer to a variable of this type is then passed to the driver + * API functions. + */ +typedef struct { + XBram_Config Config; /* BRAM config structure */ + u32 IsReady; /* Device is initialized and ready */ +} XBram; + +/***************** Macros (Inline Functions) Definitions ********************/ + + +/************************** Function Prototypes *****************************/ + +/* + * Functions in xbram_sinit.c + */ +XBram_Config *XBram_LookupConfig(u16 DeviceId); + +/* + * Functions implemented in xbram.c + */ +int XBram_CfgInitialize(XBram *InstancePtr, XBram_Config *Config, + UINTPTR EffectiveAddr); + +/* + * Functions implemented in xbram_selftest.c + */ +int XBram_SelfTest(XBram *InstancePtr, u8 IntMask); + +/* + * Functions implemented in xbram_intr.c + */ +void XBram_InterruptEnable(XBram *InstancePtr, u32 Mask); +void XBram_InterruptDisable(XBram *InstancePtr, u32 Mask); +void XBram_InterruptClear(XBram *InstancePtr, u32 Mask); +u32 XBram_InterruptGetEnabled(XBram *InstancePtr); +u32 XBram_InterruptGetStatus(XBram *InstancePtr); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/bram_v4_3/src/xbram_g.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/bram_v4_3/src/xbram_g.c new file mode 100644 index 0000000..9c185d1 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/bram_v4_3/src/xbram_g.c @@ -0,0 +1,123 @@ + +/******************************************************************* +* +* CAUTION: This file is automatically generated by HSI. +* Version: 2019.1.3 +* DO NOT EDIT. +* +* Copyright (C) 2010-2023 Xilinx, Inc. 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 +*XILINX 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. +* +*Except as contained in this notice, the name of the Xilinx shall not be used +*in advertising or otherwise to promote the sale, use or other dealings in +*this Software without prior written authorization from Xilinx. +* + +* +* Description: Driver configuration +* +*******************************************************************/ + +#include "xparameters.h" +#include "xbram.h" + +/* +* The configuration table for devices +*/ + +XBram_Config XBram_ConfigTable[] = +{ + { + XPAR_MPC_BRAM_INTERFACE_MPC_BRAM_CTRL_DEVICE_ID, + XPAR_MPC_BRAM_INTERFACE_MPC_BRAM_CTRL_DATA_WIDTH, + XPAR_MPC_BRAM_INTERFACE_MPC_BRAM_CTRL_ECC, + XPAR_MPC_BRAM_INTERFACE_MPC_BRAM_CTRL_FAULT_INJECT, + XPAR_MPC_BRAM_INTERFACE_MPC_BRAM_CTRL_CE_FAILING_REGISTERS, + 0, + XPAR_MPC_BRAM_INTERFACE_MPC_BRAM_CTRL_UE_FAILING_REGISTERS, + 0, + XPAR_MPC_BRAM_INTERFACE_MPC_BRAM_CTRL_ECC_STATUS_REGISTERS, + XPAR_MPC_BRAM_INTERFACE_MPC_BRAM_CTRL_CE_COUNTER_WIDTH, + XPAR_MPC_BRAM_INTERFACE_MPC_BRAM_CTRL_ECC_ONOFF_REGISTER, + XPAR_MPC_BRAM_INTERFACE_MPC_BRAM_CTRL_ECC_ONOFF_RESET_VALUE, + XPAR_MPC_BRAM_INTERFACE_MPC_BRAM_CTRL_WRITE_ACCESS, + XPAR_MPC_BRAM_INTERFACE_MPC_BRAM_CTRL_S_AXI_BASEADDR, + XPAR_MPC_BRAM_INTERFACE_MPC_BRAM_CTRL_S_AXI_HIGHADDR, + XPAR_MPC_BRAM_INTERFACE_MPC_BRAM_CTRL_S_AXI_CTRL_BASEADDR, + XPAR_MPC_BRAM_INTERFACE_MPC_BRAM_CTRL_S_AXI_CTRL_HIGHADDR + }, + { + XPAR_PHY_DATA_INTERFACE_ANT_INFO_BRAM_CTRL_DEVICE_ID, + XPAR_PHY_DATA_INTERFACE_ANT_INFO_BRAM_CTRL_DATA_WIDTH, + XPAR_PHY_DATA_INTERFACE_ANT_INFO_BRAM_CTRL_ECC, + XPAR_PHY_DATA_INTERFACE_ANT_INFO_BRAM_CTRL_FAULT_INJECT, + XPAR_PHY_DATA_INTERFACE_ANT_INFO_BRAM_CTRL_CE_FAILING_REGISTERS, + 0, + XPAR_PHY_DATA_INTERFACE_ANT_INFO_BRAM_CTRL_UE_FAILING_REGISTERS, + 0, + XPAR_PHY_DATA_INTERFACE_ANT_INFO_BRAM_CTRL_ECC_STATUS_REGISTERS, + XPAR_PHY_DATA_INTERFACE_ANT_INFO_BRAM_CTRL_CE_COUNTER_WIDTH, + XPAR_PHY_DATA_INTERFACE_ANT_INFO_BRAM_CTRL_ECC_ONOFF_REGISTER, + XPAR_PHY_DATA_INTERFACE_ANT_INFO_BRAM_CTRL_ECC_ONOFF_RESET_VALUE, + XPAR_PHY_DATA_INTERFACE_ANT_INFO_BRAM_CTRL_WRITE_ACCESS, + XPAR_PHY_DATA_INTERFACE_ANT_INFO_BRAM_CTRL_S_AXI_BASEADDR, + XPAR_PHY_DATA_INTERFACE_ANT_INFO_BRAM_CTRL_S_AXI_HIGHADDR, + XPAR_PHY_DATA_INTERFACE_ANT_INFO_BRAM_CTRL_S_AXI_CTRL_BASEADDR, + XPAR_PHY_DATA_INTERFACE_ANT_INFO_BRAM_CTRL_S_AXI_CTRL_HIGHADDR + }, + { + XPAR_PHY_DATA_INTERFACE_RX_FRAME_BRAM_CTRL_DEVICE_ID, + XPAR_PHY_DATA_INTERFACE_RX_FRAME_BRAM_CTRL_DATA_WIDTH, + XPAR_PHY_DATA_INTERFACE_RX_FRAME_BRAM_CTRL_ECC, + XPAR_PHY_DATA_INTERFACE_RX_FRAME_BRAM_CTRL_FAULT_INJECT, + XPAR_PHY_DATA_INTERFACE_RX_FRAME_BRAM_CTRL_CE_FAILING_REGISTERS, + 0, + XPAR_PHY_DATA_INTERFACE_RX_FRAME_BRAM_CTRL_UE_FAILING_REGISTERS, + 0, + XPAR_PHY_DATA_INTERFACE_RX_FRAME_BRAM_CTRL_ECC_STATUS_REGISTERS, + XPAR_PHY_DATA_INTERFACE_RX_FRAME_BRAM_CTRL_CE_COUNTER_WIDTH, + XPAR_PHY_DATA_INTERFACE_RX_FRAME_BRAM_CTRL_ECC_ONOFF_REGISTER, + XPAR_PHY_DATA_INTERFACE_RX_FRAME_BRAM_CTRL_ECC_ONOFF_RESET_VALUE, + XPAR_PHY_DATA_INTERFACE_RX_FRAME_BRAM_CTRL_WRITE_ACCESS, + XPAR_PHY_DATA_INTERFACE_RX_FRAME_BRAM_CTRL_S_AXI_BASEADDR, + XPAR_PHY_DATA_INTERFACE_RX_FRAME_BRAM_CTRL_S_AXI_HIGHADDR, + XPAR_PHY_DATA_INTERFACE_RX_FRAME_BRAM_CTRL_S_AXI_CTRL_BASEADDR, + XPAR_PHY_DATA_INTERFACE_RX_FRAME_BRAM_CTRL_S_AXI_CTRL_HIGHADDR + }, + { + XPAR_PHY_DATA_INTERFACE_TX_FRAME_BRAM_CTRL_DEVICE_ID, + XPAR_PHY_DATA_INTERFACE_TX_FRAME_BRAM_CTRL_DATA_WIDTH, + XPAR_PHY_DATA_INTERFACE_TX_FRAME_BRAM_CTRL_ECC, + XPAR_PHY_DATA_INTERFACE_TX_FRAME_BRAM_CTRL_FAULT_INJECT, + XPAR_PHY_DATA_INTERFACE_TX_FRAME_BRAM_CTRL_CE_FAILING_REGISTERS, + 0, + XPAR_PHY_DATA_INTERFACE_TX_FRAME_BRAM_CTRL_UE_FAILING_REGISTERS, + 0, + XPAR_PHY_DATA_INTERFACE_TX_FRAME_BRAM_CTRL_ECC_STATUS_REGISTERS, + XPAR_PHY_DATA_INTERFACE_TX_FRAME_BRAM_CTRL_CE_COUNTER_WIDTH, + XPAR_PHY_DATA_INTERFACE_TX_FRAME_BRAM_CTRL_ECC_ONOFF_REGISTER, + XPAR_PHY_DATA_INTERFACE_TX_FRAME_BRAM_CTRL_ECC_ONOFF_RESET_VALUE, + XPAR_PHY_DATA_INTERFACE_TX_FRAME_BRAM_CTRL_WRITE_ACCESS, + XPAR_PHY_DATA_INTERFACE_TX_FRAME_BRAM_CTRL_S_AXI_BASEADDR, + XPAR_PHY_DATA_INTERFACE_TX_FRAME_BRAM_CTRL_S_AXI_HIGHADDR, + XPAR_PHY_DATA_INTERFACE_TX_FRAME_BRAM_CTRL_S_AXI_CTRL_BASEADDR, + XPAR_PHY_DATA_INTERFACE_TX_FRAME_BRAM_CTRL_S_AXI_CTRL_HIGHADDR + } +}; + + diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/bram_v4_3/src/xbram_hw.h b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/bram_v4_3/src/xbram_hw.h new file mode 100644 index 0000000..55a2505 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/bram_v4_3/src/xbram_hw.h @@ -0,0 +1,405 @@ +/****************************************************************************** +* +* Copyright (C) 2011 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xbram_hw.h +* @addtogroup bram_v4_2 +* @{ +* +* This header file contains identifiers and driver functions (or +* macros) that can be used to access the device. The user should refer to the +* hardware device specification for more details of the device operation. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a sa   24/11/10 First release
+* 
+* +******************************************************************************/ +#ifndef XBRAM_HW_H /* prevent circular inclusions */ +#define XBRAM_HW_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_io.h" + +/************************** Constant Definitions *****************************/ + +/** @name Registers + * + * Register offsets for this device. + * @{ + */ + +#define XBRAM_ECC_STATUS_OFFSET 0x0 /**< ECC status Register */ +#define XBRAM_ECC_EN_IRQ_OFFSET 0x4 /**< ECC interrupt enable Register */ +#define XBRAM_ECC_ON_OFF_OFFSET 0x8 /**< ECC on/off register */ +#define XBRAM_CE_CNT_OFFSET 0xC /**< Correctable error counter Register */ + +#define XBRAM_CE_FFD_0_OFFSET 0x100 /**< Correctable error first failing + * data Register, 31-0 */ +#define XBRAM_CE_FFD_1_OFFSET 0x104 /**< Correctable error first failing + * data Register, 63-32 */ +#define XBRAM_CE_FFD_2_OFFSET 0x108 /**< Correctable error first failing + * data Register, 95-64 */ +#define XBRAM_CE_FFD_3_OFFSET 0x10C /**< Correctable error first failing + * data Register, 127-96 */ +#define XBRAM_CE_FFD_4_OFFSET 0x110 /**< Correctable error first failing + * data Register, 159-128 */ +#define XBRAM_CE_FFD_5_OFFSET 0x114 /**< Correctable error first failing + * data Register, 191-160 */ +#define XBRAM_CE_FFD_6_OFFSET 0x118 /**< Correctable error first failing + * data Register, 223-192 */ +#define XBRAM_CE_FFD_7_OFFSET 0x11C /**< Correctable error first failing + * data Register, 255-224 */ +#define XBRAM_CE_FFD_8_OFFSET 0x120 /**< Correctable error first failing + * data Register, 287-256 */ +#define XBRAM_CE_FFD_9_OFFSET 0x124 /**< Correctable error first failing + * data Register, 319-288 */ +#define XBRAM_CE_FFD_10_OFFSET 0x128 /**< Correctable error first failing + * data Register, 351-320 */ +#define XBRAM_CE_FFD_11_OFFSET 0x12C /**< Correctable error first failing + * data Register, 383-352 */ +#define XBRAM_CE_FFD_12_OFFSET 0x130 /**< Correctable error first failing + * data Register, 415-384 */ +#define XBRAM_CE_FFD_13_OFFSET 0x134 /**< Correctable error first failing + * data Register, 447-416 */ +#define XBRAM_CE_FFD_14_OFFSET 0x138 /**< Correctable error first failing + * data Register, 479-448 */ +#define XBRAM_CE_FFD_15_OFFSET 0x13C /**< Correctable error first failing + * data Register, 511-480 */ +#define XBRAM_CE_FFD_16_OFFSET 0x140 /**< Correctable error first failing + * data Register, 543-512 */ +#define XBRAM_CE_FFD_17_OFFSET 0x144 /**< Correctable error first failing + * data Register, 575-544 */ +#define XBRAM_CE_FFD_18_OFFSET 0x148 /**< Correctable error first failing + * data Register, 607-576 */ +#define XBRAM_CE_FFD_19_OFFSET 0x14C /**< Correctable error first failing + * data Register, 639-608 */ +#define XBRAM_CE_FFD_20_OFFSET 0x150 /**< Correctable error first failing + * data Register, 671-640 */ +#define XBRAM_CE_FFD_21_OFFSET 0x154 /**< Correctable error first failing + * data Register, 703-672 */ +#define XBRAM_CE_FFD_22_OFFSET 0x158 /**< Correctable error first failing + * data Register, 735-704 */ +#define XBRAM_CE_FFD_23_OFFSET 0x15C /**< Correctable error first failing + * data Register, 767-736 */ +#define XBRAM_CE_FFD_24_OFFSET 0x160 /**< Correctable error first failing + * data Register, 799-768 */ +#define XBRAM_CE_FFD_25_OFFSET 0x164 /**< Correctable error first failing + * data Register, 831-800 */ +#define XBRAM_CE_FFD_26_OFFSET 0x168 /**< Correctable error first failing + * data Register, 863-832 */ +#define XBRAM_CE_FFD_27_OFFSET 0x16C /**< Correctable error first failing + * data Register, 895-864 */ +#define XBRAM_CE_FFD_28_OFFSET 0x170 /**< Correctable error first failing + * data Register, 927-896 */ +#define XBRAM_CE_FFD_29_OFFSET 0x174 /**< Correctable error first failing + * data Register, 959-928 */ +#define XBRAM_CE_FFD_30_OFFSET 0x178 /**< Correctable error first failing + * data Register, 991-960 */ +#define XBRAM_CE_FFD_31_OFFSET 0x17C /**< Correctable error first failing + * data Register, 1023-992 */ + +#define XBRAM_CE_FFE_0_OFFSET 0x180 /**< Correctable error first failing + * ECC Register, 31-0 */ +#define XBRAM_CE_FFE_1_OFFSET 0x184 /**< Correctable error first failing + * ECC Register, 63-32 */ +#define XBRAM_CE_FFE_2_OFFSET 0x188 /**< Correctable error first failing + * ECC Register, 95-64 */ +#define XBRAM_CE_FFE_3_OFFSET 0x18C /**< Correctable error first failing + * ECC Register, 127-96 */ +#define XBRAM_CE_FFE_4_OFFSET 0x190 /**< Correctable error first failing + * ECC Register, 159-128 */ +#define XBRAM_CE_FFE_5_OFFSET 0x194 /**< Correctable error first failing + * ECC Register, 191-160 */ +#define XBRAM_CE_FFE_6_OFFSET 0x198 /**< Correctable error first failing + * ECC Register, 223-192 */ +#define XBRAM_CE_FFE_7_OFFSET 0x19C /**< Correctable error first failing + * ECC Register, 255-224 */ + +#define XBRAM_CE_FFA_0_OFFSET 0x1C0 /**< Correctable error first failing + * address Register 31-0 */ +#define XBRAM_CE_FFA_1_OFFSET 0x1C4 /**< Correctable error first failing + * address Register 63-32 */ + +#define XBRAM_UE_FFD_0_OFFSET 0x200 /**< Uncorrectable error first failing + * data Register, 31-0 */ +#define XBRAM_UE_FFD_1_OFFSET 0x204 /**< Uncorrectable error first failing + * data Register, 63-32 */ +#define XBRAM_UE_FFD_2_OFFSET 0x208 /**< Uncorrectable error first failing + * data Register, 95-64 */ +#define XBRAM_UE_FFD_3_OFFSET 0x20C /**< Uncorrectable error first failing + * data Register, 127-96 */ +#define XBRAM_UE_FFD_4_OFFSET 0x210 /**< Uncorrectable error first failing + * data Register, 159-128 */ +#define XBRAM_UE_FFD_5_OFFSET 0x214 /**< Uncorrectable error first failing + * data Register, 191-160 */ +#define XBRAM_UE_FFD_6_OFFSET 0x218 /**< Uncorrectable error first failing + * data Register, 223-192 */ +#define XBRAM_UE_FFD_7_OFFSET 0x21C /**< Uncorrectable error first failing + * data Register, 255-224 */ +#define XBRAM_UE_FFD_8_OFFSET 0x220 /**< Uncorrectable error first failing + * data Register, 287-256 */ +#define XBRAM_UE_FFD_9_OFFSET 0x224 /**< Uncorrectable error first failing + * data Register, 319-288 */ +#define XBRAM_UE_FFD_10_OFFSET 0x228 /**< Uncorrectable error first failing + * data Register, 351-320 */ +#define XBRAM_UE_FFD_11_OFFSET 0x22C /**< Uncorrectable error first failing + * data Register, 383-352 */ +#define XBRAM_UE_FFD_12_OFFSET 0x230 /**< Uncorrectable error first failing + * data Register, 415-384 */ +#define XBRAM_UE_FFD_13_OFFSET 0x234 /**< Uncorrectable error first failing + * data Register, 447-416 */ +#define XBRAM_UE_FFD_14_OFFSET 0x238 /**< Uncorrectable error first failing + * data Register, 479-448 */ +#define XBRAM_UE_FFD_15_OFFSET 0x23C /**< Uncorrectable error first failing + * data Register, 511-480 */ +#define XBRAM_UE_FFD_16_OFFSET 0x240 /**< Uncorrectable error first failing + * data Register, 543-512 */ +#define XBRAM_UE_FFD_17_OFFSET 0x244 /**< Uncorrectable error first failing + * data Register, 575-544 */ +#define XBRAM_UE_FFD_18_OFFSET 0x248 /**< Uncorrectable error first failing + * data Register, 607-576 */ +#define XBRAM_UE_FFD_19_OFFSET 0x24C /**< Uncorrectable error first failing + * data Register, 639-608 */ +#define XBRAM_UE_FFD_20_OFFSET 0x250 /**< Uncorrectable error first failing + * data Register, 671-640 */ +#define XBRAM_UE_FFD_21_OFFSET 0x254 /**< Uncorrectable error first failing + * data Register, 703-672 */ +#define XBRAM_UE_FFD_22_OFFSET 0x258 /**< Uncorrectable error first failing + * data Register, 735-704 */ +#define XBRAM_UE_FFD_23_OFFSET 0x25C /**< Uncorrectable error first failing + * data Register, 767-736 */ +#define XBRAM_UE_FFD_24_OFFSET 0x260 /**< Uncorrectable error first failing + * data Register, 799-768 */ +#define XBRAM_UE_FFD_25_OFFSET 0x264 /**< Uncorrectable error first failing + * data Register, 831-800 */ +#define XBRAM_UE_FFD_26_OFFSET 0x268 /**< Uncorrectable error first failing + * data Register, 863-832 */ +#define XBRAM_UE_FFD_27_OFFSET 0x26C /**< Uncorrectable error first failing + * data Register, 895-864 */ +#define XBRAM_UE_FFD_28_OFFSET 0x270 /**< Uncorrectable error first failing + * data Register, 927-896 */ +#define XBRAM_UE_FFD_29_OFFSET 0x274 /**< Uncorrectable error first failing + * data Register, 959-928 */ +#define XBRAM_UE_FFD_30_OFFSET 0x278 /**< Uncorrectable error first failing + * data Register, 991-960 */ +#define XBRAM_UE_FFD_31_OFFSET 0x27C /**< Uncorrectable error first failing + * data Register, 1023-992 */ + +#define XBRAM_UE_FFE_0_OFFSET 0x280 /**< Uncorrectable error first failing + * ECC Register, 31-0 */ +#define XBRAM_UE_FFE_1_OFFSET 0x284 /**< Uncorrectable error first failing + * ECC Register, 63-32 */ +#define XBRAM_UE_FFE_2_OFFSET 0x288 /**< Uncorrectable error first failing + * ECC Register, 95-64 */ +#define XBRAM_UE_FFE_3_OFFSET 0x28C /**< Uncorrectable error first failing + * ECC Register, 127-96 */ +#define XBRAM_UE_FFE_4_OFFSET 0x290 /**< Uncorrectable error first failing + * ECC Register, 159-128 */ +#define XBRAM_UE_FFE_5_OFFSET 0x294 /**< Uncorrectable error first failing + * ECC Register, 191-160 */ +#define XBRAM_UE_FFE_6_OFFSET 0x298 /**< Uncorrectable error first failing + * ECC Register, 223-192 */ +#define XBRAM_UE_FFE_7_OFFSET 0x29C /**< Uncorrectable error first failing + * ECC Register, 255-224 */ + +#define XBRAM_UE_FFA_0_OFFSET 0x2C0 /**< Uncorrectable error first failing + * address Register 31-0 */ +#define XBRAM_UE_FFA_1_OFFSET 0x2C4 /**< Uncorrectable error first failing + * address Register 63-32 */ + +#define XBRAM_FI_D_0_OFFSET 0x300 /**< Fault injection Data Register, + * 31-0 */ +#define XBRAM_FI_D_1_OFFSET 0x304 /**< Fault injection Data Register, + * 63-32 */ +#define XBRAM_FI_D_2_OFFSET 0x308 /**< Fault injection Data Register, + * 95-64 */ +#define XBRAM_FI_D_3_OFFSET 0x30C /**< Fault injection Data Register, + * 127-96 */ +#define XBRAM_FI_D_4_OFFSET 0x310 /**< Fault injection Data Register, + * 159-128 */ +#define XBRAM_FI_D_5_OFFSET 0x314 /**< Fault injection Data Register, + * 191-160 */ +#define XBRAM_FI_D_6_OFFSET 0x318 /**< Fault injection Data Register, + * 223-192 */ +#define XBRAM_FI_D_7_OFFSET 0x31C /**< Fault injection Data Register, + * 255-224 */ +#define XBRAM_FI_D_8_OFFSET 0x320 /**< Fault injection Data Register, + * 287-256 */ +#define XBRAM_FI_D_9_OFFSET 0x324 /**< Fault injection Data Register, + * 319-288 */ +#define XBRAM_FI_D_10_OFFSET 0x328 /**< Fault injection Data Register, + * 351-320 */ +#define XBRAM_FI_D_11_OFFSET 0x32C /**< Fault injection Data Register, + * 383-352 */ +#define XBRAM_FI_D_12_OFFSET 0x330 /**< Fault injection Data Register, + * 415-384 */ +#define XBRAM_FI_D_13_OFFSET 0x334 /**< Fault injection Data Register, + * 447-416 */ +#define XBRAM_FI_D_14_OFFSET 0x338 /**< Fault injection Data Register, + * 479-448 */ +#define XBRAM_FI_D_15_OFFSET 0x33C /**< Fault injection Data Register, + * 511-480 */ +#define XBRAM_FI_D_16_OFFSET 0x340 /**< Fault injection Data Register, + * 543-512 */ +#define XBRAM_FI_D_17_OFFSET 0x344 /**< Fault injection Data Register, + * 575-544 */ +#define XBRAM_FI_D_18_OFFSET 0x348 /**< Fault injection Data Register, + * 607-576 */ +#define XBRAM_FI_D_19_OFFSET 0x34C /**< Fault injection Data Register, + * 639-608 */ +#define XBRAM_FI_D_20_OFFSET 0x350 /**< Fault injection Data Register, + * 671-640 */ +#define XBRAM_FI_D_21_OFFSET 0x354 /**< Fault injection Data Register, + * 703-672 */ +#define XBRAM_FI_D_22_OFFSET 0x358 /**< Fault injection Data Register, + * 735-704 */ +#define XBRAM_FI_D_23_OFFSET 0x35C /**< Fault injection Data Register, + * 767-736 */ +#define XBRAM_FI_D_24_OFFSET 0x360 /**< Fault injection Data Register, + * 799-768 */ +#define XBRAM_FI_D_25_OFFSET 0x364 /**< Fault injection Data Register, + * 831-800 */ +#define XBRAM_FI_D_26_OFFSET 0x368 /**< Fault injection Data Register, + * 863-832 */ +#define XBRAM_FI_D_27_OFFSET 0x36C /**< Fault injection Data Register, + * 895-864 */ +#define XBRAM_FI_D_28_OFFSET 0x370 /**< Fault injection Data Register, + * 927-896 */ +#define XBRAM_FI_D_29_OFFSET 0x374 /**< Fault injection Data Register, + * 959-928 */ +#define XBRAM_FI_D_30_OFFSET 0x378 /**< Fault injection Data Register, + * 991-960 */ +#define XBRAM_FI_D_31_OFFSET 0x37C /**< Fault injection Data Register, + * 1023-992 */ + +#define XBRAM_FI_ECC_0_OFFSET 0x380 /**< Fault injection ECC Register, + * 31-0 */ +#define XBRAM_FI_ECC_1_OFFSET 0x384 /**< Fault injection ECC Register, + * 63-32 */ +#define XBRAM_FI_ECC_2_OFFSET 0x388 /**< Fault injection ECC Register, + * 95-64 */ +#define XBRAM_FI_ECC_3_OFFSET 0x38C /**< Fault injection ECC Register, + * 127-96 */ +#define XBRAM_FI_ECC_4_OFFSET 0x390 /**< Fault injection ECC Register, + * 159-128 */ +#define XBRAM_FI_ECC_5_OFFSET 0x394 /**< Fault injection ECC Register, + * 191-160 */ +#define XBRAM_FI_ECC_6_OFFSET 0x398 /**< Fault injection ECC Register, + * 223-192 */ +#define XBRAM_FI_ECC_7_OFFSET 0x39C /**< Fault injection ECC Register, + * 255-224 */ + + +/* @} */ + +/** @name Interrupt Status and Enable Register bitmaps and masks + * + * Bit definitions for the ECC status register and ECC interrupt enable register. + * @{ + */ +#define XBRAM_IR_CE_MASK 0x2 /**< Mask for the correctable error */ +#define XBRAM_IR_UE_MASK 0x1 /**< Mask for the uncorrectable error */ +#define XBRAM_IR_ALL_MASK 0x3 /**< Mask of all bits */ +/*@}*/ + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + +#define XBram_In32 Xil_In32 +#define XBram_Out32 Xil_Out32 + +#define XBram_In16 Xil_In16 +#define XBram_Out16 Xil_Out16 + +#define XBram_In8 Xil_In8 +#define XBram_Out8 Xil_Out8 + + +/****************************************************************************/ +/** +* +* Write a value to a BRAM register. A 32 bit write is performed. +* +* @param BaseAddress is the base address of the BRAM device register. +* @param RegOffset is the register offset from the base to write to. +* @param Data is the data written to the register. +* +* @return None. +* +* @note C-style signature: +* void XBram_WriteReg(u32 BaseAddress, u32 RegOffset, u32 Data) +* +****************************************************************************/ +#define XBram_WriteReg(BaseAddress, RegOffset, Data) \ + XBram_Out32((BaseAddress) + (RegOffset), (u32)(Data)) + +/****************************************************************************/ +/** +* +* Read a value from a BRAM register. A 32 bit read is performed. +* +* @param BaseAddress is the base address of the BRAM device registers. +* @param RegOffset is the register offset from the base to read from. +* +* @return Data read from the register. +* +* @note C-style signature: +* u32 XBram_ReadReg(u32 BaseAddress, u32 RegOffset) +* +****************************************************************************/ +#define XBram_ReadReg(BaseAddress, RegOffset) \ + XBram_In32((BaseAddress) + (RegOffset)) + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + + + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/bram_v4_3/src/xbram_intr.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/bram_v4_3/src/xbram_intr.c new file mode 100644 index 0000000..50644aa --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/bram_v4_3/src/xbram_intr.c @@ -0,0 +1,234 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +/*****************************************************************************/ +/** +* @file xbram_intr.c +* @addtogroup bram_v4_2 +* @{ +* +* Implements BRAM interrupt processing functions for the +* XBram driver. See xbram.h for more information +* about the driver. +* +* The functions in this file require the hardware device to be built with +* interrupt capabilities. The functions will assert if called using hardware +* that does not have interrupt capabilities. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a sa   05/11/10 Initial release
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ +#include "xbram.h" + + +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Variable Definitions ****************************/ + +/************************** Function Prototypes *****************************/ + + +/****************************************************************************/ +/** +* Enable interrupts. This function will assert if the hardware device has not +* been built with interrupt capabilities. +* +* @param InstancePtr is the BRAM instance to operate on. +* @param Mask is the mask to enable. Bit positions of 1 are enabled. +* This mask is formed by OR'ing bits from XBRAM_IR* +* bits which are contained in xbram_hw.h. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XBram_InterruptEnable(XBram *InstancePtr, u32 Mask) +{ + u32 Register; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(InstancePtr->Config.CtrlBaseAddress != 0); + + /* + * Read the interrupt enable register and only enable the specified + * interrupts without disabling or enabling any others. + */ + Register = XBram_ReadReg(InstancePtr->Config.CtrlBaseAddress, + XBRAM_ECC_EN_IRQ_OFFSET); + XBram_WriteReg(InstancePtr->Config.CtrlBaseAddress, + XBRAM_ECC_EN_IRQ_OFFSET, + Register | Mask); +} + + +/****************************************************************************/ +/** +* Disable interrupts. This function allows each specific interrupt to be +* disabled. This function will assert if the hardware device has not been +* built with interrupt capabilities. +* +* @param InstancePtr is the BRAM instance to operate on. +* @param Mask is the mask to disable. Bits set to 1 are disabled. This +* mask is formed by OR'ing bits from XBRAM_IR* bits +* which are contained in xbram_hw.h. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XBram_InterruptDisable(XBram *InstancePtr, u32 Mask) +{ + u32 Register; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(InstancePtr->Config.CtrlBaseAddress != 0); + + /* + * Read the interrupt enable register and only disable the specified + * interrupts without enabling or disabling any others. + */ + Register = XBram_ReadReg(InstancePtr->Config.CtrlBaseAddress, + XBRAM_ECC_EN_IRQ_OFFSET); + XBram_WriteReg(InstancePtr->Config.CtrlBaseAddress, + XBRAM_ECC_EN_IRQ_OFFSET, + Register & (~Mask)); +} + +/****************************************************************************/ +/** +* Clear pending interrupts with the provided mask. This function should be +* called after the software has serviced the interrupts that are pending. +* This function will assert if the hardware device has not been built with +* interrupt capabilities. +* +* @param InstancePtr is the BRAM instance to operate on. +* @param Mask is the mask to clear pending interrupts for. Bit positions +* of 1 are cleared. This mask is formed by OR'ing bits from +* XBRAM_IR* bits which are contained in +* xbram_hw.h. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XBram_InterruptClear(XBram *InstancePtr, u32 Mask) +{ + u32 Register; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(InstancePtr->Config.CtrlBaseAddress != 0); + + /* + * Read the interrupt status register and only clear the interrupts + * that are specified without affecting any others. Since the register + * is a toggle on write, make sure any bits to be written are already + * set. + */ + Register = XBram_ReadReg(InstancePtr->Config.CtrlBaseAddress, + XBRAM_ECC_STATUS_OFFSET); + XBram_WriteReg(InstancePtr->Config.CtrlBaseAddress, + XBRAM_ECC_STATUS_OFFSET, + Register & Mask); + + +} + + +/****************************************************************************/ +/** +* Returns the interrupt enable mask. This function will assert if the +* hardware device has not been built with interrupt capabilities. +* +* @param InstancePtr is the BRAM instance to operate on. +* +* @return A mask of bits made from XBRAM_IR* bits which +* are contained in xbram_hw.h. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +u32 XBram_InterruptGetEnabled(XBram * InstancePtr) +{ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(InstancePtr->Config.CtrlBaseAddress != 0); + + return XBram_ReadReg(InstancePtr->Config.CtrlBaseAddress, + XBRAM_ECC_EN_IRQ_OFFSET); +} + + +/****************************************************************************/ +/** +* Returns the status of interrupt signals. Any bit in the mask set to 1 +* indicates that the channel associated with the bit has asserted an interrupt +* condition. This function will assert if the hardware device has not been +* built with interrupt capabilities. +* +* @param InstancePtr is the BRAM instance to operate on. +* +* @return A pointer to a mask of bits made from XBRAM_IR* +* bits which are contained in xbram_hw.h. +* +* @note +* +* The interrupt status indicates the status of the device irregardless if +* the interrupts from the devices have been enabled or not through +* XBram_InterruptEnable(). +* +*****************************************************************************/ +u32 XBram_InterruptGetStatus(XBram * InstancePtr) +{ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(InstancePtr->Config.CtrlBaseAddress != 0); + + return XBram_ReadReg(InstancePtr->Config.CtrlBaseAddress, + XBRAM_ECC_EN_IRQ_OFFSET); +} +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/bram_v4_3/src/xbram_selftest.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/bram_v4_3/src/xbram_selftest.c new file mode 100644 index 0000000..e57e09c --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/bram_v4_3/src/xbram_selftest.c @@ -0,0 +1,557 @@ +/****************************************************************************** +* +* Copyright (C) 2011 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file xbram_selftest.c +* @addtogroup bram_v4_2 +* @{ +* +* The implementation of the XBram driver's self test function. This SelfTest +* is only applicable if ECC is enabled. +* If ECC is not enabled then this function will return XST_SUCCESS. +* See xbram.h for more information about the driver. +* Temp change +* +* @note +* +* None +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a sa   11/24/10 First release
+* 3.01a sa   01/13/12  Changed Selftest API from
+*		       XBram_SelfTest(XBram *InstancePtr) to
+*		       XBram_SelfTest(XBram *InstancePtr, u8 IntMask) and
+*		       fixed a problem with interrupt generation for CR 639274
+*		       Modified Selftest example to return XST_SUCCESS when
+*		       ECC is not enabled and return XST_FAILURE when ECC is
+*		       enabled and Control Base Address is zero (CR 636581)
+*		       Modified Selftest to use correct CorrectableCounterBits
+*		       for CR 635655
+*		       Updated to check CorrectableFailingDataRegs in the case
+*		       of LMB BRAM.
+* 3.02a sa  04/16/12   Added test of byte and halfword read-modify-write
+* 3.03a bss 05/22/13   Added Xil_DCacheFlushRange in InjectErrors API to
+*		       flush the Cache after writing to BRAM (CR #719011)
+* 4.3   aru 04/09/19   Used UINTPTR instead of u32 for Addr in XBram_SelfTest()
+*
+* 
+*****************************************************************************/ + +/***************************** Include Files ********************************/ +#include "xbram.h" +#include "xil_cache.h" +/************************** Constant Definitions ****************************/ +#define TOTAL_BITS 39 + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ +#define RD(reg) XBram_ReadReg(InstancePtr->Config.CtrlBaseAddress, \ + XBRAM_ ## reg) +#define WR(reg, data) XBram_WriteReg(InstancePtr->Config.CtrlBaseAddress, \ + XBRAM_ ## reg, data) + +#define CHECK(reg, data, result) if (result!=XST_SUCCESS || RD(reg)!=data) \ + result = XST_FAILURE; + +/************************** Variable Definitions ****************************/ +static u32 PrngResult; + +/************************** Function Prototypes *****************************/ +static inline u32 PrngData(u32 *PrngResult); + +static inline u32 CalculateEcc(u32 Data); + +static void InjectErrors(XBram * InstancePtr, UINTPTR Addr, + int Index1, int Index2, int Width, + u32 *ActualData, u32 *ActualEcc); + + +/*****************************************************************************/ +/** +* Generate a pseudo random number. +* +* @param The PrngResult is the previous random number in the pseudo +* random sequence, also knwon as the seed. It is modified to +* the calculated pseudo random number by the function. +* +* @return The generated pseudo random number +* +* @note None. +* +******************************************************************************/ +static inline u32 PrngData(u32 *PrngResult) +{ + *PrngResult = *PrngResult * 0x77D15E25 + 0x3617C161; + return *PrngResult; +} + + +/*****************************************************************************/ +/** +* Calculate ECC from Data. +* +* @param The Data Value +* +* @return The calculated ECC +* +* @note None. +* +******************************************************************************/ +static inline u32 CalculateEcc(u32 Data) +{ + unsigned char c[7], d[32]; + u32 Result = 0; + int Index; + + for (Index = 0; Index < 32; Index++) { + d[31 - Index] = Data & 1; + Data = Data >> 1; + } + + c[0] = d[0] ^ d[1] ^ d[3] ^ d[4] ^ d[6] ^ d[8] ^ d[10] ^ d[11] ^ + d[13] ^ d[15] ^ d[17] ^ d[19] ^ d[21] ^ d[23] ^ d[25] ^ d[26] ^ + d[28] ^ d[30]; + + c[1] = d[0] ^ d[2] ^ d[3] ^ d[5] ^ d[6] ^ d[9] ^ d[10] ^ d[12] ^ + d[13] ^ d[16] ^ d[17] ^ d[20] ^ d[21] ^ d[24] ^ d[25] ^ d[27] ^ + d[28] ^ d[31]; + + c[2] = d[1] ^ d[2] ^ d[3] ^ d[7] ^ d[8] ^ d[9] ^ d[10] ^ d[14] ^ + d[15] ^ d[16] ^ d[17] ^ d[22] ^ d[23] ^ d[24] ^ d[25] ^ d[29] ^ + d[30] ^ d[31]; + + c[3] = d[4] ^ d[5] ^ d[6] ^ d[7] ^ d[8] ^ d[9] ^ d[10] ^ d[18] ^ + d[19] ^ d[20] ^ d[21] ^ d[22] ^ d[23] ^ d[24] ^ d[25]; + + c[4] = d[11] ^ d[12] ^ d[13] ^ d[14] ^ d[15] ^ d[16] ^ d[17] ^ d[18] ^ + d[19] ^ d[20] ^ d[21] ^ d[22] ^ d[23] ^ d[24] ^ d[25]; + + c[5] = d[26] ^ d[27] ^ d[28] ^ d[29] ^ d[30] ^ d[31]; + + c[6] = d[0] ^ d[1] ^ d[2] ^ d[3] ^ d[4] ^ d[5] ^ d[6] ^ d[7] ^ + d[8] ^ d[9] ^ d[10] ^ d[11] ^ d[12] ^ d[13] ^ d[14] ^ d[15] ^ + d[16] ^ d[17] ^ d[18] ^ d[19] ^ d[20] ^ d[21] ^ d[22] ^ d[23] ^ + d[24] ^ d[25] ^ d[26] ^ d[27] ^ d[28] ^ d[29] ^ d[30] ^ d[31] ^ + c[5] ^ c[4] ^ c[3] ^ c[2] ^ c[1] ^ c[0]; + + for (Index = 0; Index < 7; Index++) { + Result = Result << 1; + Result |= c[Index] & 1; + } + + return Result; +} + +/*****************************************************************************/ +/** +* Get the expected actual data read in case of uncorrectable errors. +* +* @param The injected data value including errors (if any) +* @param The syndrome (calculated ecc ^ actual ecc read) +* +* @return The actual data value read +* +* @note None. +* +******************************************************************************/ +static inline u32 UncorrectableData(u32 Data, u8 Syndrome) +{ + switch (Syndrome) { + case 0x03: return Data ^ 0x00000034; + case 0x05: return Data ^ 0x001a2000; + case 0x09: return Data ^ 0x0d000000; + case 0x0d: return Data ^ 0x00001a00; + + case 0x11: return Data ^ 0x60000000; + case 0x13: return Data ^ 0x00000003; + case 0x15: return Data ^ 0x00018000; + case 0x19: return Data ^ 0x00c00000; + case 0x1d: return Data ^ 0x00000180; + + case 0x21: return Data ^ 0x80000000; + case 0x23: return Data ^ 0x00000008; + case 0x25: return Data ^ 0x00040000; + case 0x29: return Data ^ 0x02000000; + case 0x2d: return Data ^ 0x00000400; + + case 0x31: return Data ^ 0x10000000; + case 0x35: return Data ^ 0x00004000; + case 0x39: return Data ^ 0x00200000; + case 0x3d: return Data ^ 0x00000040; + } + return Data; +} + +/*****************************************************************************/ +/** +* Inject errors using the hardware fault injection functionality, and write +* random data and read it back using the indicated location. +* +* @param InstancePtr is a pointer to the XBram instance to +* be worked on. +* @param The Addr is the indicated memory location to use +* @param The Index1 is the bit location of the first injected error +* @param The Index2 is the bit location of the second injected error +* @param The Width is the data byte width +* @param The ActualData is filled in with expected data for checking +* @param The ActualEcc is filled in with expected ECC for checking +* +* @return None +* +* @note None. +* +******************************************************************************/ +static void InjectErrors(XBram * InstancePtr, UINTPTR Addr, + int Index1, int Index2, int Width, + u32 *ActualData, u32 *ActualEcc) +{ + u32 InjectedData = 0; + u32 InjectedEcc = 0; + u32 RandomData = PrngData(&PrngResult); + + if (Index1 < 32) { + InjectedData = 1 << Index1; + } else { + InjectedEcc = 1 << (Index1 - 32); + } + + if (Index2 < 32) { + InjectedData |= (1 << Index2); + } else { + InjectedEcc |= 1 << (Index2 - 32); + } + + WR(FI_D_0_OFFSET, InjectedData); + WR(FI_ECC_0_OFFSET, InjectedEcc); + + XBram_Out32(Addr, RandomData); + Xil_DCacheFlushRange(Addr, 4); + switch (Width) { + case 1: /* Byte - Write to do Read-Modify-Write */ + XBram_Out8(Addr, PrngData(&PrngResult) & 0xFF); + break; + case 2: /* Halfword - Write to do Read-Modify-Write */ + XBram_Out16(Addr, PrngData(&PrngResult) & 0xFFFF); + break; + case 4: /* Word - Read */ + (void) XBram_In32(Addr); + break; + } + *ActualData = InjectedData ^ RandomData; + *ActualEcc = InjectedEcc ^ CalculateEcc(RandomData); +} + + +/*****************************************************************************/ +/** +* Run a self-test on the driver/device. Unless fault injection is implemented +* in hardware, this function only does a minimal test in which available +* registers (if any) are written and read. +* +* With fault injection, all possible single-bit and double-bit errors are +* injected, and checked to the extent possible, given the implemented hardware. +* +* @param InstancePtr is a pointer to the XBram instance. +* @param IntMask is the interrupt mask to use. When testing +* with interrupts, this should be set to allow interrupt +* generation, otherwise it should be 0. +* +* @return +* - XST_SUCCESS if fault injection/detection is working properly OR +* if ECC is Not Enabled in the HW. +* - XST_FAILURE if the injected fault is not correctly detected or +* the Control Base Address is Zero when ECC is enabled. +* . +* +* If the BRAM device is not present in the +* hardware a bus error could be generated. Other indicators of a +* bus error, such as registers in bridges or buses, may be +* necessary to determine if this function caused a bus error. +* +* @note None. +* +******************************************************************************/ +int XBram_SelfTest(XBram *InstancePtr, u8 IntMask) +{ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + + + if (InstancePtr->Config.EccPresent == 0) { + return (XST_SUCCESS); + } + + if (InstancePtr->Config.CtrlBaseAddress == 0) { + return (XST_SUCCESS); + } + + /* + * Only 32-bit data width is supported as of yet. 64-bit and 128-bit + * widths will be supported in future. + */ + if (InstancePtr->Config.DataWidth != 32) + return (XST_SUCCESS); + + /* + * Read from the implemented readable registers in the hardware device. + */ + if (InstancePtr->Config.CorrectableFailingRegisters) { + (void) RD(CE_FFA_0_OFFSET); + } + if (InstancePtr->Config.CorrectableFailingDataRegs) { + (void) RD(CE_FFD_0_OFFSET); + (void) RD(CE_FFE_0_OFFSET); + } + if (InstancePtr->Config.UncorrectableFailingRegisters) { + (void) RD(UE_FFA_0_OFFSET); + } + if (InstancePtr->Config.UncorrectableFailingDataRegs) { + (void) RD(UE_FFD_0_OFFSET); + (void) RD(UE_FFE_0_OFFSET); + } + + /* + * Write and read the implemented read/write registers in the hardware + * device. + */ + if (InstancePtr->Config.EccStatusInterruptPresent) { + WR(ECC_EN_IRQ_OFFSET, 0); + if (RD(ECC_EN_IRQ_OFFSET) != 0) { + return (XST_FAILURE); + } + } + + if (InstancePtr->Config.CorrectableCounterBits > 0) { + u32 Value; + + /* Calculate counter max value */ + if (InstancePtr->Config.CorrectableCounterBits == 32) { + Value = 0xFFFFFFFF; + } else { + Value = (1 << + InstancePtr->Config.CorrectableCounterBits) - 1; + } + + WR(CE_CNT_OFFSET, Value); + if (RD(CE_CNT_OFFSET) != Value) { + return (XST_FAILURE); + } + + WR(CE_CNT_OFFSET, 0); + if (RD(CE_CNT_OFFSET) != 0) { + return (XST_FAILURE); + } + } + + /* + * If fault injection is implemented, inject all possible single-bit + * and double-bit errors, and check all observable effects. + */ + if (InstancePtr->Config.FaultInjectionPresent && + InstancePtr->Config.WriteAccess != 0) { + + const UINTPTR Addr[2] = {InstancePtr->Config.MemBaseAddress & + (UINTPTR)0xfffffffffffffffc, + InstancePtr->Config.MemHighAddress & + (UINTPTR)0xfffffffffffffffc}; + u32 SavedWords[2]; + u32 ActualData; + u32 ActualEcc; + u32 CounterValue = 0; + u32 CounterMax; + int WordIndex = 0; + int Result = XST_SUCCESS; + int Index1; + int Index2; + int Width; + + PrngResult = 42; /* Random seed */ + + /* Save two words in BRAM used for test */ + SavedWords[0] = XBram_In32(Addr[0]); + SavedWords[1] = XBram_In32(Addr[1]); + + for (Width = 1; Width <= 4; Width <<= 1) { + /* Calculate counter max value */ + if (InstancePtr->Config.CorrectableCounterBits == 32) { + CounterMax = 0xFFFFFFFF; + } else { + CounterMax =(1 << + InstancePtr->Config.CorrectableCounterBits) - 1; + } + + /* Inject and check all single bit errors */ + for (Index1 = 0; Index1 < TOTAL_BITS; Index1++) { + /* Save counter value */ + if (InstancePtr->Config.CorrectableCounterBits > 0) { + CounterValue = RD(CE_CNT_OFFSET); + } + + /* Inject single bit error */ + InjectErrors(InstancePtr, Addr[WordIndex], Index1, + Index1, Width, &ActualData, &ActualEcc); + + /* Check that CE is set */ + if (InstancePtr->Config.EccStatusInterruptPresent) { + CHECK(ECC_STATUS_OFFSET, + XBRAM_IR_CE_MASK, Result); + } + + /* Check that address, data, ECC are correct */ + if (InstancePtr->Config.CorrectableFailingRegisters) { + CHECK(CE_FFA_0_OFFSET, Addr[WordIndex], Result); + } + /* Checks are only for LMB BRAM */ + if (InstancePtr->Config.CorrectableFailingDataRegs) { + CHECK(CE_FFD_0_OFFSET, ActualData, Result); + CHECK(CE_FFE_0_OFFSET, ActualEcc, Result); + } + + /* Check that counter has incremented */ + if (InstancePtr->Config.CorrectableCounterBits > 0 && + CounterValue < CounterMax) { + CHECK(CE_CNT_OFFSET, + CounterValue + 1, Result); + } + + /* Restore correct data in the used word */ + XBram_Out32(Addr[WordIndex], SavedWords[WordIndex]); + + /* Allow interrupts to occur */ + /* Clear status register */ + if (InstancePtr->Config.EccStatusInterruptPresent) { + WR(ECC_EN_IRQ_OFFSET, IntMask); + WR(ECC_STATUS_OFFSET, XBRAM_IR_ALL_MASK); + WR(ECC_EN_IRQ_OFFSET, 0); + } + + /* Switch to the other word */ + WordIndex = WordIndex ^ 1; + + if (Result != XST_SUCCESS) break; + + } + + if (Result != XST_SUCCESS) { + return XST_FAILURE; + } + + for (Index1 = 0; Index1 < TOTAL_BITS; Index1++) { + for (Index2 = 0; Index2 < TOTAL_BITS; Index2++) { + if (Index1 != Index2) { + /* Inject double bit error */ + InjectErrors(InstancePtr, + Addr[WordIndex], + Index1, Index2, Width, + &ActualData, + &ActualEcc); + + /* Check that UE is set */ + if (InstancePtr->Config. + EccStatusInterruptPresent) { + CHECK(ECC_STATUS_OFFSET, + XBRAM_IR_UE_MASK, + Result); + } + + /* Check that address, data, ECC are correct */ + if (InstancePtr->Config. + UncorrectableFailingRegisters) { + CHECK(UE_FFA_0_OFFSET, Addr[WordIndex], + Result); + CHECK(UE_FFD_0_OFFSET, + ActualData, Result); + CHECK(UE_FFE_0_OFFSET, ActualEcc, + Result); + } + + /* Restore correct data in the used word */ + XBram_Out32(Addr[WordIndex], + SavedWords[WordIndex]); + + /* Allow interrupts to occur */ + /* Clear status register */ + if (InstancePtr->Config. + EccStatusInterruptPresent) { + WR(ECC_EN_IRQ_OFFSET, IntMask); + WR(ECC_STATUS_OFFSET, + XBRAM_IR_ALL_MASK); + WR(ECC_EN_IRQ_OFFSET, 0); + } + + /* Switch to the other word */ + WordIndex = WordIndex ^ 1; + } + if (Result != XST_SUCCESS) break; + } + if (Result != XST_SUCCESS) break; + } + + /* Check saturation of correctable error counter */ + if (InstancePtr->Config.CorrectableCounterBits > 0 && + Result == XST_SUCCESS) { + + WR(CE_CNT_OFFSET, CounterMax); + + InjectErrors(InstancePtr, Addr[WordIndex], 0, 0, + 4, &ActualData, &ActualEcc); + + CHECK(CE_CNT_OFFSET, CounterMax, Result); + } + + /* Restore the two words used for test */ + XBram_Out32(Addr[0], SavedWords[0]); + XBram_Out32(Addr[1], SavedWords[1]); + + /* Clear the Status Register. */ + if (InstancePtr->Config.EccStatusInterruptPresent) { + WR(ECC_STATUS_OFFSET, XBRAM_IR_ALL_MASK); + } + + /* Set Correctable Counter to zero */ + if (InstancePtr->Config.CorrectableCounterBits > 0) { + WR(CE_CNT_OFFSET, 0); + } + + if (Result != XST_SUCCESS) break; + + } /* Width loop */ + + return (Result); + } + + return (XST_SUCCESS); +} + +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/bram_v4_3/src/xbram_sinit.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/bram_v4_3/src/xbram_sinit.c new file mode 100644 index 0000000..adc560e --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/bram_v4_3/src/xbram_sinit.c @@ -0,0 +1,101 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2017 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file xbram_sinit.c +* @addtogroup bram_v4_2 +* @{ +* +* The implementation of the XBram driver's static initialzation +* functionality. +* +* @note +* +* None +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 2.01a jvb  10/13/05 First release
+* 2.11a mta  03/21/07 Updated to new coding style
+* 4.2   ms   08/07/17 Fixed compilation warnings.
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ + +#include "xstatus.h" +#include "xparameters.h" +#include "xbram.h" + +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Variable Definitions ****************************/ +extern XBram_Config XBram_ConfigTable[]; + +/************************** Function Prototypes *****************************/ + + +/*****************************************************************************/ +/** +* Lookup the device configuration based on the unique device ID. The table +* ConfigTable contains the configuration info for each device in the system. +* +* @param DeviceId is the device identifier to lookup. +* +* @return +* - A pointer of data type XBram_Config which +* points to the device configuration if DeviceID is found. +* - NULL if DeviceID is not found. +* +* @note None. +* +******************************************************************************/ +XBram_Config *XBram_LookupConfig(u16 DeviceId) +{ + XBram_Config *CfgPtr = NULL; + + u32 Index; + + for (Index = 0U; Index < XPAR_XBRAM_NUM_INSTANCES; Index++) { + if (XBram_ConfigTable[Index].DeviceId == DeviceId) { + CfgPtr = &XBram_ConfigTable[Index]; + break; + } + } + + return CfgPtr; +} +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/coresightps_dcc_v1_5/src/Makefile b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/coresightps_dcc_v1_5/src/Makefile new file mode 100644 index 0000000..007162d --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/coresightps_dcc_v1_5/src/Makefile @@ -0,0 +1,40 @@ +COMPILER= +ARCHIVER= +CP=cp +COMPILER_FLAGS= +EXTRA_COMPILER_FLAGS= +LIB=libxil.a + +CC_FLAGS = $(COMPILER_FLAGS) +ECC_FLAGS = $(EXTRA_COMPILER_FLAGS) + +RELEASEDIR=../../../lib +INCLUDEDIR=../../../include +INCLUDES=-I./. -I${INCLUDEDIR} + +OUTS = *.o + +LIBSOURCES:=*.c +INCLUDEFILES:=*.h + +OBJECTS = $(addsuffix .o, $(basename $(wildcard *.c))) + +libs: banner coresightps_dcc_comp_libs clean + +%.o: %.c + ${COMPILER} $(CC_FLAGS) $(ECC_FLAGS) $(INCLUDES) -o $@ $< + +banner: + echo "Compiling coresightps_dcc" + +coresightps_dcc_comp_libs: ${OBJECTS} + $(ARCHIVER) -r ${RELEASEDIR}/${LIB} ${OBJECTS} + +.PHONY: include +include: coresightps_dcc_includes + +coresightps_dcc_includes: + ${CP} ${INCLUDEFILES} ${INCLUDEDIR} + +clean: + rm -rf ${OBJECTS} diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/coresightps_dcc_v1_5/src/xcoresightpsdcc.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/coresightps_dcc_v1_5/src/xcoresightpsdcc.c new file mode 100644 index 0000000..235eb8e --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/coresightps_dcc_v1_5/src/xcoresightpsdcc.c @@ -0,0 +1,186 @@ +/****************************************************************************** +* +* Copyright (C) 2015-2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xcoresightpsdcc.c +* @addtogroup coresightps_dcc_v1_5 +* @{ +* +* Functions in this file are the minimum required functions for the +* XCoreSightPs driver. +* +* @note None. +* +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date		Changes
+* ----- -----  -------- -----------------------------------------------
+* 1.00  kvn    02/14/15 First release
+* 1.1   kvn    06/12/15 Add support for Zynq Ultrascale+ MP.
+*       kvn    08/18/15 Modified Makefile according to compiler changes.
+* 1.2   kvn    10/09/15 Add support for IAR Compiler.
+* 1.3   asa    07/01/16 Made changes to ensure that the file does not compile
+*                       for MB BSPs. Instead it throws up a warning. This
+*                       fixes the CR#953056.
+* 1.5   sne    01/19/19 Fixed MISRA-C Violations CR#1025101.
+*
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ +#ifdef __MICROBLAZE__ +#warning "The driver is supported only for ARM architecture" +#else + +#include "xil_types.h" +#include "xpseudo_asm.h" +#include "xcoresightpsdcc.h" + +#ifdef __ICCARM__ +#define INLINE +#else +#define INLINE __inline +#endif + +/* DCC Status Bits */ +#define XCORESIGHTPS_DCC_STATUS_RX (1 << 30) +#define XCORESIGHTPS_DCC_STATUS_TX (1 << 29) + +static INLINE u32 XCoresightPs_DccGetStatus(void); + +/****************************************************************************/ +/** +* +* This functions sends a single byte using the DCC. It is blocking in that it +* waits for the transmitter to become non-full before it writes the byte to +* the transmit register. +* +* @param BaseAddress is a dummy parameter to match the function proto +* of functions for other stdio devices. +* @param Data is the byte of data to send +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XCoresightPs_DccSendByte(u32 BaseAddress, u8 Data) +{ + (void) BaseAddress; + while (XCoresightPs_DccGetStatus() & XCORESIGHTPS_DCC_STATUS_TX) + {dsb();} +#ifdef __aarch64__ + asm volatile ("msr dbgdtrtx_el0, %0" : : "r" (Data)); +#elif defined (__GNUC__) || defined (__ICCARM__) + asm volatile("mcr p14, 0, %0, c0, c5, 0" + : : "r" (Data)); +#else + { + volatile register u32 Reg __asm("cp14:0:c0:c5:0"); + Reg = Data; + } +#endif + isb(); + +} + +/****************************************************************************/ +/** +* +* This functions receives a single byte using the DCC. It is blocking in that +* it waits for the receiver to become non-empty before it reads from the +* receive register. +* +* @param BaseAddress is a dummy parameter to match the function proto +* of functions for other stdio devices. +* +* @return The byte of data received. +* +* @note None. +* +******************************************************************************/ +u8 XCoresightPs_DccRecvByte(u32 BaseAddress) +{ + u8 Data = 0U; + (void) BaseAddress; + + while (!(XCoresightPs_DccGetStatus() & XCORESIGHTPS_DCC_STATUS_RX)) + {dsb();} + +#ifdef __aarch64__ + asm volatile ("mrs %0, dbgdtrrx_el0" : "=r" (Data)); +#elif defined (__GNUC__) || defined (__ICCARM__) + asm volatile("mrc p14, 0, %0, c0, c5, 0" + : "=r" (Data)); +#else + { + volatile register u32 Reg __asm("cp14:0:c0:c5:0"); + Data = Reg; + } +#endif + isb(); + + return Data; +} + + +/****************************************************************************/ +/**INLINE +* +* This functions read the status register of the DCC. +* +* @param BaseAddress is the base address of the device +* +* @return The contents of the Status Register. +* +* @note None. +* +******************************************************************************/ +static INLINE u32 XCoresightPs_DccGetStatus(void) +{ + u32 Status = 0U; + +#ifdef __aarch64__ + asm volatile ("mrs %0, mdccsr_el0" : "=r" (Status)); +#elif defined (__GNUC__) || defined (__ICCARM__) + asm volatile("mrc p14, 0, %0, c0, c1, 0" + : "=r" (Status) : : "cc"); +#else + { + volatile register u32 Reg __asm("cp14:0:c0:c1:0"); + Status = Reg; + } +#endif + return Status; +#endif +} +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/coresightps_dcc_v1_5/src/xcoresightpsdcc.h b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/coresightps_dcc_v1_5/src/xcoresightpsdcc.h new file mode 100644 index 0000000..79bde0b --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/coresightps_dcc_v1_5/src/xcoresightpsdcc.h @@ -0,0 +1,74 @@ +/****************************************************************************** +* +* Copyright (C) 2015 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xcoresightpsdcc.h +* @addtogroup coresightps_dcc_v1_5 +* @{ +* @details +* +* CoreSight driver component. +* +* The coresight is a part of debug communication channel (DCC) group. Jtag UART +* for ARM uses DCC. Each ARM core has its own DCC, so one need to select an +* ARM target in XSDB console before running the jtag terminal command. Using the +* coresight driver component, the output stream can be directed to a log file. +* +* @note None. +* +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date		Changes
+* ----- -----  -------- -----------------------------------------------
+* 1.00  kvn    02/14/15 First release
+* 1.1   kvn    06/12/15 Add support for Zynq Ultrascale+ MP.
+*       kvn    08/18/15 Modified Makefile according to compiler changes.
+* 1.3   asa    07/01/16 Made changes to ensure that the file does not compile
+*                       for MB BSPs. Instead it throws up a warning. This
+*                       fixes the CR#953056.
+* 1.5   sne    01/19/19 Fixed MISRA-C Violations CR#1025101.
+*
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ +#ifndef XCORESIGHTPSDCC_H /* prevent circular inclusions */ +#define XCORESIGHTPSDCC_H /* by using protection macros */ +#ifndef __MICROBLAZE__ +#include + +void XCoresightPs_DccSendByte(u32 BaseAddress, u8 Data); + +u8 XCoresightPs_DccRecvByte(u32 BaseAddress); +#endif +#endif +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/cpu_cortexa9_v2_7/src/Makefile b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/cpu_cortexa9_v2_7/src/Makefile new file mode 100644 index 0000000..7ea505c --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/cpu_cortexa9_v2_7/src/Makefile @@ -0,0 +1,25 @@ +COMPILER= +ARCHIVER= +CP=cp +COMPILER_FLAGS= +EXTRA_COMPILER_FLAGS= +LIB=libxil.a + +RELEASEDIR=../../../lib +INCLUDEDIR=../../../include +INCLUDES=-I${INCLUDEDIR} + +OUTS = *.o +OBJECTS = $(addsuffix .o, $(basename $(wildcard *.c))) +LIBSOURCES=*.c +INCLUDEFILES=*.h + +libs: + echo "Compiling cpu_cortexa9" + +.PHONY: include +include: + ${CP} $(INCLUDEFILES) $(INCLUDEDIR) + +clean: + rm -rf ${OBJECTS} diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/cpu_cortexa9_v2_7/src/xcpu_cortexa9.h b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/cpu_cortexa9_v2_7/src/xcpu_cortexa9.h new file mode 100644 index 0000000..e4a5e28 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/cpu_cortexa9_v2_7/src/xcpu_cortexa9.h @@ -0,0 +1,47 @@ +/****************************************************************************** +* +* Copyright (C) 2011 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xcpu_cortexa9.h +* @addtogroup cpu_cortexa9_v2_7 +* @{ +* @details +* +* dummy file +* MODIFICATION HISTORY: +* +* Ver Who Date Changes +* ----- ---- -------- --------------------------------------------------------- +* 2.5 ms 04/18/17 Modified tcl file to add suffix U for XPAR_CPU_ID +* parameter of cpu_cortexa9 in xparameters.h +# 2.7 mus 07/03/18 Updated tcl to not to add default flags forcefully into +# extra compiler flags. Now, user can remove default flags +# from extra compiler flags. It fixes CR#998768. +******************************************************************************/ +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/ddrps_v1_0/src/Makefile b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/ddrps_v1_0/src/Makefile new file mode 100644 index 0000000..7b191dd --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/ddrps_v1_0/src/Makefile @@ -0,0 +1,40 @@ +COMPILER= +ARCHIVER= +CP=cp +COMPILER_FLAGS= +EXTRA_COMPILER_FLAGS= +LIB=libxil.a + +CC_FLAGS = $(COMPILER_FLAGS) +ECC_FLAGS = $(EXTRA_COMPILER_FLAGS) + +RELEASEDIR=../../../lib +INCLUDEDIR=../../../include +INCLUDES=-I./. -I${INCLUDEDIR} + +OUTS = *.o + +LIBSOURCES:=*.c +INCLUDEFILES:=*.h + +OBJECTS = $(addsuffix .o, $(basename $(wildcard *.c))) + +libs: banner xddrps_libs clean + +%.o: %.c + ${COMPILER} $(CC_FLAGS) $(ECC_FLAGS) $(INCLUDES) -o $@ $< + +banner: + echo "Compiling ddrps" + +xddrps_libs: ${OBJECTS} + $(ARCHIVER) -r ${RELEASEDIR}/${LIB} ${OBJECTS} + +.PHONY: include +include: xddrps_includes + +xddrps_includes: + ${CP} ${INCLUDEFILES} ${INCLUDEDIR} + +clean: + rm -rf ${OBJECTS} diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/ddrps_v1_0/src/xddrps.h b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/ddrps_v1_0/src/xddrps.h new file mode 100644 index 0000000..b4d1f56 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/ddrps_v1_0/src/xddrps.h @@ -0,0 +1,62 @@ +/******************************************************************************* + * + * Copyright (C) 2015 Xilinx, Inc. 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 + * XILINX 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. + * + * Except as contained in this notice, the name of the Xilinx shall not be used + * in advertising or otherwise to promote the sale, use or other dealings in + * this Software without prior written authorization from Xilinx. + * +*******************************************************************************/ +/******************************************************************************/ +/** + * + * @file xddrps.h + * @addtogroup ddrps_v1_0 + * @{ + * @details + * + * The Xilinx DdrPs driver. This driver supports the Xilinx ddrps + * IP core. + * + * @note None. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -----------------------------------------------
+ * 1.0	 nsk  08/06/15 First Release
+ * 1.0	 nsk  08/20/15 Updated define_addr_params in ddrps.tcl
+ *		       to support PBD Designs (CR #876857)
+ *
+ * 
+ * +*******************************************************************************/ + +#ifndef XDDRPS_H_ +/* Prevent circular inclusions by using protection macros. */ +#define XDDRPS_H_ + +/******************************* Include Files ********************************/ + + +#endif /* XDDRPS_H_ */ +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/devcfg_v3_5/src/Makefile b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/devcfg_v3_5/src/Makefile new file mode 100644 index 0000000..25ff740 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/devcfg_v3_5/src/Makefile @@ -0,0 +1,40 @@ +COMPILER= +ARCHIVER= +CP=cp +COMPILER_FLAGS= +EXTRA_COMPILER_FLAGS= +LIB=libxil.a + +CC_FLAGS = $(COMPILER_FLAGS) +ECC_FLAGS = $(EXTRA_COMPILER_FLAGS) + +RELEASEDIR=../../../lib +INCLUDEDIR=../../../include +INCLUDES=-I./. -I${INCLUDEDIR} + +OUTS = *.o + +LIBSOURCES:=*.c +INCLUDEFILES:=*.h + +OBJECTS = $(addsuffix .o, $(basename $(wildcard *.c))) + +libs: banner xdevcfg_libs clean + +%.o: %.c + ${COMPILER} $(CC_FLAGS) $(ECC_FLAGS) $(INCLUDES) -o $@ $< + +banner: + echo "Compiling devcfg" + +xdevcfg_libs: ${OBJECTS} + $(ARCHIVER) -r ${RELEASEDIR}/${LIB} ${OBJECTS} + +.PHONY: include +include: xdevcfg_includes + +xdevcfg_includes: + ${CP} ${INCLUDEFILES} ${INCLUDEDIR} + +clean: + rm -rf ${OBJECTS} diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/devcfg_v3_5/src/xdevcfg.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/devcfg_v3_5/src/xdevcfg.c new file mode 100644 index 0000000..74e1d59 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/devcfg_v3_5/src/xdevcfg.c @@ -0,0 +1,941 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xdevcfg.c +* @addtogroup devcfg_v3_5 +* @{ +* +* This file contains the implementation of the interface functions for XDcfg +* driver. Refer to the header file xdevcfg.h for more detailed information. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 1.00a hvm 02/07/11 First release
+* 2.00a nm  05/31/12 Updated the driver for CR 660835 so that input length for
+*		     source/destination to the XDcfg_InitiateDma, XDcfg_Transfer
+*		     APIs is words (32 bit) and not bytes.
+* 		     Updated the notes for XDcfg_InitiateDma/XDcfg_Transfer APIs
+*		     to add information that 2 LSBs of the Source/Destination
+*		     address when equal to 2�b01 indicate the last DMA command
+*		     of an overall transfer.
+*		     Updated the XDcfg_Transfer function to use the
+*		     Destination Address passed to this API for secure transfers
+*		     instead of using 0xFFFFFFFF for CR 662197. This issue was
+*		     resulting in the failure of secure transfers of
+*		     non-bitstream images.
+* 2.01a nm  08/27/12 Updated the XDcfg_Transfer API to clear the
+*		     QUARTER_PCAP_RATE_EN bit in the control register for
+*		     non secure writes for CR 675543.
+* 2.02a nm  01/31/13 Fixed CR# 679335.
+* 		     Added Setting and Clearing the internal PCAP loopback.
+*		     Removed code for enabling/disabling AES engine as BootROM
+*		     locks down this setting.
+*		     Fixed CR# 681976.
+*		     Skip Checking the PCFG_INIT in case of non-secure DMA
+*		     loopback.
+*		     Fixed CR# 699558.
+*		     XDcfg_Transfer fails to transfer data in loopback mode.
+* 2.03a nm  04/19/13 Fixed CR# 703728.
+*		     Updated the register definitions as per the latest TRM
+*		     version UG585 (v1.4) November 16, 2012.
+* 3.0   kpc 21/02/14 Implemented new function XDcfg_ClearControlRegister
+* 3.2   sb  08/25/14 Fixed XDcfg_PcapReadback() function
+*		     updated driver code with != instead of ==,
+*		     while checking for Interrupt Status with DMA and
+*		     PCAP Done Mask
+*		     ((XDcfg_ReadReg(InstancePtr->Config.BaseAddr,
+*			XDCFG_INT_STS_OFFSET) &
+*			XDCFG_IXR_D_P_DONE_MASK) !=
+*			XDCFG_IXR_D_P_DONE_MASK);
+*
+*
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xdevcfg.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +/****************************************************************************/ +/** +* +* Initialize the Device Config Interface driver. This function +* must be called before other functions of the driver are called. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* @param ConfigPtr is the config structure. +* @param EffectiveAddress is the base address for the device. It could be +* a virtual address if address translation is supported in the +* system, otherwise it is the physical address. +* +* @return +* - XST_SUCCESS if initialization was successful. +* - XST_DEVICE_IS_STARTED if the device has already been started. +* +* @note The very first APB access to the Device Configuration Interface +* block needs to be a write to the UNLOCK register with the value +* of 0x757BDF0D. This step is to be done once after reset, any +* other APB access has to come after this. The APB access is +* considered illegal if the step is not done or if it is done +* incorrectly. Furthermore, if any of efuse_sec_cfg[5:0] is high, +* the following additional actions would be carried out. +* In other words, if all bits are low, the following steps are not +* done. +* 1. AES is disabled +* 2. All APB writes disabled +* 3. SoC debug fully enabled +* +******************************************************************************/ +int XDcfg_CfgInitialize(XDcfg *InstancePtr, + XDcfg_Config *ConfigPtr, u32 EffectiveAddress) +{ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(ConfigPtr != NULL); + + /* + * If the device is started, disallow the initialize and return a + * status indicating it is started. This allows the user to stop the + * device and reinitialize, but prevents a user from inadvertently + * initializing. + */ + if (InstancePtr->IsStarted == XIL_COMPONENT_IS_STARTED) { + return XST_DEVICE_IS_STARTED; + } + + /* + * Copy configuration into instance. + */ + InstancePtr->Config.DeviceId = ConfigPtr->DeviceId; + + /* + * Save the base address pointer such that the registers of the block + * can be accessed and indicate it has not been started yet. + */ + InstancePtr->Config.BaseAddr = EffectiveAddress; + InstancePtr->IsStarted = 0; + + + /* Unlock the Device Configuration Interface */ + XDcfg_Unlock(InstancePtr); + + /* + * Indicate the instance is ready to use, successfully initialized. + */ + InstancePtr->IsReady = XIL_COMPONENT_IS_READY; + + return XST_SUCCESS; +} + +/****************************************************************************/ +/** +* +* The functions enables the PCAP interface by setting the PCAP mode bit in the +* control register. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* +* @return None. +* +* @note Enable FPGA programming from PCAP interface. Enabling this bit +* disables all the external interfaces from programming of FPGA +* except for ICAP. The user needs to ensure that the FPGA is +* programmed through either PCAP or ICAP. +* +*****************************************************************************/ +void XDcfg_EnablePCAP(XDcfg *InstancePtr) +{ + u32 CtrlReg; + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + + CtrlReg = XDcfg_ReadReg(InstancePtr->Config.BaseAddr, + XDCFG_CTRL_OFFSET); + + XDcfg_WriteReg(InstancePtr->Config.BaseAddr, XDCFG_CTRL_OFFSET, + (CtrlReg | XDCFG_CTRL_PCAP_MODE_MASK)); + +} + +/****************************************************************************/ +/** +* +* The functions disables the PCAP interface by clearing the PCAP mode bit in +* the control register. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XDcfg_DisablePCAP(XDcfg *InstancePtr) +{ + u32 CtrlReg; + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + + CtrlReg = XDcfg_ReadReg(InstancePtr->Config.BaseAddr, + XDCFG_CTRL_OFFSET); + + XDcfg_WriteReg(InstancePtr->Config.BaseAddr, XDCFG_CTRL_OFFSET, + (CtrlReg & ( ~XDCFG_CTRL_PCAP_MODE_MASK))); + +} + +/****************************************************************************/ +/** +* +* The function sets the contents of the Control Register. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* @param Mask is the 32 bit mask data to be written to the Register. +* The mask definitions are defined in the xdevcfg_hw.h file. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XDcfg_SetControlRegister(XDcfg *InstancePtr, u32 Mask) +{ + u32 CtrlReg; + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + + CtrlReg = XDcfg_ReadReg(InstancePtr->Config.BaseAddr, + XDCFG_CTRL_OFFSET); + + XDcfg_WriteReg(InstancePtr->Config.BaseAddr, XDCFG_CTRL_OFFSET, + (CtrlReg | Mask)); + +} + +/****************************************************************************/ +/** +* +* The function Clears the specified bit positions of the Control Register. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* @param Mask is the 32 bit value which holds the bit positions to be cleared. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XDcfg_ClearControlRegister(XDcfg *InstancePtr, u32 Mask) +{ + u32 CtrlReg; + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + + CtrlReg = XDcfg_ReadReg(InstancePtr->Config.BaseAddr, + XDCFG_CTRL_OFFSET); + + XDcfg_WriteReg(InstancePtr->Config.BaseAddr, XDCFG_CTRL_OFFSET, + (CtrlReg & ~Mask)); + +} + +/****************************************************************************/ +/** +* +* The function reads the contents of the Control Register. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* +* @return A 32-bit value representing the contents of the Control +* Register. +* Use the XDCFG_CTRL_*_MASK constants defined in xdevcfg_hw.h to +* interpret the returned value. +* +* @note None. +* +*****************************************************************************/ +u32 XDcfg_GetControlRegister(XDcfg *InstancePtr) +{ + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the Control Register and return the value. + */ + return XDcfg_ReadReg(InstancePtr->Config.BaseAddr, XDCFG_CTRL_OFFSET); +} + +/****************************************************************************/ +/** +* +* The function sets the contents of the Lock Register. These bits +* can only be set to a 1. They will be cleared after a Power On Reset. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* @param Data is the 32 bit data to be written to the Register. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XDcfg_SetLockRegister(XDcfg *InstancePtr, u32 Data) +{ + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + XDcfg_WriteReg(InstancePtr->Config.BaseAddr, XDCFG_LOCK_OFFSET, Data); + +} + +/****************************************************************************/ +/** +* +* The function reads the contents of the Lock Register. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* +* @return A 32-bit value representing the contents of the Lock +* Register. +* Use the XDCFG_CR_*_MASK constants defined in xdevcfg_hw.h to +* interpret the returned value. +* +* @note None. +* +*****************************************************************************/ +u32 XDcfg_GetLockRegister(XDcfg *InstancePtr) +{ + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the Lock Register and return the value. + */ + return XDcfg_ReadReg(InstancePtr->Config.BaseAddr, XDCFG_LOCK_OFFSET); +} + +/****************************************************************************/ +/** +* +* The function sets the contents of the Configuration Register with the +* given value. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* @param Data is the 32 bit data to be written to the Register. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XDcfg_SetConfigRegister(XDcfg *InstancePtr, u32 Data) +{ + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + XDcfg_WriteReg(InstancePtr->Config.BaseAddr, XDCFG_CFG_OFFSET, Data); + +} + +/****************************************************************************/ +/** +* +* The function reads the contents of the Configuration Register with the +* given value. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* +* @return A 32-bit value representing the contents of the Config +* Register. +* Use the XDCFG_CFG_*_MASK constants defined in xdevcfg_hw.h to +* interpret the returned value. +* +* @note None. +* +*****************************************************************************/ +u32 XDcfg_GetConfigRegister(XDcfg *InstancePtr) +{ + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + return XDcfg_ReadReg(InstancePtr->Config.BaseAddr, XDCFG_CFG_OFFSET); + +} + +/****************************************************************************/ +/** +* +* The function sets the contents of the Status Register. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* @param Data is the 32 bit data to be written to the Register. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XDcfg_SetStatusRegister(XDcfg *InstancePtr, u32 Data) +{ + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + XDcfg_WriteReg(InstancePtr->Config.BaseAddr, XDCFG_STATUS_OFFSET, Data); + +} + +/****************************************************************************/ +/** +* +* The function reads the contents of the Status Register. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* +* @return A 32-bit value representing the contents of the Status +* Register. +* Use the XDCFG_STATUS_*_MASK constants defined in +* xdevcfg_hw.h to interpret the returned value. +* +* @note None. +* +*****************************************************************************/ +u32 XDcfg_GetStatusRegister(XDcfg *InstancePtr) +{ + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the Status Register and return the value. + */ + return XDcfg_ReadReg(InstancePtr->Config.BaseAddr, XDCFG_STATUS_OFFSET); +} + +/****************************************************************************/ +/** +* +* The function sets the contents of the ROM Shadow Control Register. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* @param Data is the 32 bit data to be written to the Register. +* +* @return None. +* +* @note This register is can only be written and is used to control the +* RAM shadow of 32 bit 4K page ROM pages in user mode +* +*****************************************************************************/ +void XDcfg_SetRomShadowRegister(XDcfg *InstancePtr, u32 Data) +{ + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + XDcfg_WriteReg(InstancePtr->Config.BaseAddr, XDCFG_ROM_SHADOW_OFFSET, + Data); + +} + +/****************************************************************************/ +/** +* +* The function reads the contents of the Software ID Register. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* +* @return 32 Bit boot software ID. +* +* @note This register is locked for write once the system enters +* usermode. Hence API for reading the register only is provided. +* +*****************************************************************************/ +u32 XDcfg_GetSoftwareIdRegister(XDcfg *InstancePtr) +{ + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the Software ID Register and return the value. + */ + return XDcfg_ReadReg(InstancePtr->Config.BaseAddr, XDCFG_SW_ID_OFFSET); +} + +/****************************************************************************/ +/** +* +* The function sets the bit mask for the feature in Miscellaneous Control +* Register. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* @param Mask is the bit-mask of the feature to be set. +* +* @return None. +* +* @note None +* +*****************************************************************************/ +void XDcfg_SetMiscControlRegister(XDcfg *InstancePtr, u32 Mask) +{ + u32 RegData; + + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + + RegData = XDcfg_ReadReg(InstancePtr->Config.BaseAddr, + XDCFG_MCTRL_OFFSET); + + XDcfg_WriteReg(InstancePtr->Config.BaseAddr, XDCFG_MCTRL_OFFSET, + (RegData | Mask)); +} + +/****************************************************************************/ +/** +* +* The function reads the contents of the Miscellaneous Control Register. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* +* @return 32 Bit boot software ID. +* +* @note This register is locked for write once the system enters +* usermode. Hence API to reading the register only is provided. +* +*****************************************************************************/ +u32 XDcfg_GetMiscControlRegister(XDcfg *InstancePtr) +{ + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the Miscellaneous Control Register and return the value. + */ + return XDcfg_ReadReg(InstancePtr->Config.BaseAddr, XDCFG_MCTRL_OFFSET); +} + +/******************************************************************************/ +/** +* +* This function checks if DMA command queue is full. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* +* @return XST_SUCCESS is the DMA is busy +* XST_FAILURE if the DMA is idle +* +* @note The DMA queue has a depth of two. +* +****************************************************************************/ +u32 XDcfg_IsDmaBusy(XDcfg *InstancePtr) +{ + + u32 RegData; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* Read the PCAP status register for DMA status */ + RegData = XDcfg_ReadReg(InstancePtr->Config.BaseAddr, + XDCFG_STATUS_OFFSET); + + if ((RegData & XDCFG_STATUS_DMA_CMD_Q_F_MASK) == + XDCFG_STATUS_DMA_CMD_Q_F_MASK){ + return XST_SUCCESS; + } + + return XST_FAILURE; +} + +/******************************************************************************/ +/** +* +* This function initiates the DMA transfer. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* @param SourcePtr contains a pointer to the source memory where the data +* is to be transferred from. +* @param SrcWordLength is the number of words (32 bit) to be transferred +* for the source transfer. +* @param DestPtr contains a pointer to the destination memory +* where the data is to be transferred to. +* @param DestWordLength is the number of words (32 bit) to be transferred +* for the Destination transfer. +* +* @return None. +* +* @note It is the responsibility of the caller function to ensure that +* correct values are passed to this function. +* +* The 2 LSBs of the SourcePtr (Source)/ DestPtr (Destination) +* address when equal to 2�b01 indicates the last DMA command of +* an overall transfer. +* +****************************************************************************/ +void XDcfg_InitiateDma(XDcfg *InstancePtr, u32 SourcePtr, u32 DestPtr, + u32 SrcWordLength, u32 DestWordLength) +{ + + XDcfg_WriteReg(InstancePtr->Config.BaseAddr, + XDCFG_DMA_SRC_ADDR_OFFSET, + SourcePtr); + + XDcfg_WriteReg(InstancePtr->Config.BaseAddr, + XDCFG_DMA_DEST_ADDR_OFFSET, + DestPtr); + + XDcfg_WriteReg(InstancePtr->Config.BaseAddr, + XDCFG_DMA_SRC_LEN_OFFSET, + SrcWordLength); + + XDcfg_WriteReg(InstancePtr->Config.BaseAddr, + XDCFG_DMA_DEST_LEN_OFFSET, + DestWordLength); +} + +/******************************************************************************/ +/** +* +* This function Implements the DMA Read Command. This command is used to +* transfer the image data from FPGA to the external memory. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* @param SourcePtr contains a pointer to the source memory where the data +* is to be transferred from. +* @param SrcWordLength is the number of words (32 bit) to be transferred +* for the source transfer. +* @param DestPtr contains a pointer to the destination memory +* where the data is to be transferred to. +* @param DestWordLength is the number of words (32 bit) to be transferred +* for the Destination transfer. +* +* @return - XST_INVALID_PARAM if source address/length is invalid. +* - XST_SUCCESS if DMA transfer initiated properly. +* +* @note None. +* +****************************************************************************/ +static u32 XDcfg_PcapReadback(XDcfg *InstancePtr, u32 SourcePtr, + u32 SrcWordLength, u32 DestPtr, + u32 DestWordLength) +{ + u32 IntrReg; + + /* + * Send READ Frame command to FPGA + */ + XDcfg_InitiateDma(InstancePtr, SourcePtr, XDCFG_DMA_INVALID_ADDRESS, + SrcWordLength, 0); + + /* + * Store the enabled interrupts to enable before the actual read + * transfer is initiated and Disable all the interrupts temporarily. + */ + IntrReg = XDcfg_IntrGetEnabled(InstancePtr); + XDcfg_IntrDisable(InstancePtr, XDCFG_IXR_ALL_MASK); + + /* + * Wait till you get the DMA done for the read command sent + */ + while ((XDcfg_ReadReg(InstancePtr->Config.BaseAddr, + XDCFG_INT_STS_OFFSET) & + XDCFG_IXR_D_P_DONE_MASK) != + XDCFG_IXR_D_P_DONE_MASK); + /* + * Enable the previously stored Interrupts . + */ + XDcfg_IntrEnable(InstancePtr, IntrReg); + + /* + * Initiate the DMA write command. + */ + XDcfg_InitiateDma(InstancePtr, XDCFG_DMA_INVALID_ADDRESS, (u32)DestPtr, + 0, DestWordLength); + + return XST_SUCCESS; +} + + +/****************************************************************************/ +/** +* +* This function starts the DMA transfer. This function only starts the +* operation and returns before the operation may be completed. +* If the interrupt is enabled, an interrupt will be generated when the +* operation is completed, otherwise it is necessary to poll the Status register +* to determine when it is completed. It is the responsibility of the caller to +* determine when the operation is completed by handling the generated interrupt +* or polling the Status Register. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* @param SourcePtr contains a pointer to the source memory where the data +* is to be transferred from. +* @param SrcWordLength is the number of words (32 bit) to be transferred +* for the source transfer. +* @param DestPtr contains a pointer to the destination memory +* where the data is to be transferred to. +* @param DestWordLength is the number of words (32 bit) to be transferred +* for the Destination transfer. +* @param TransferType contains the type of PCAP transfer being requested. +* The definitions can be found in the xdevcfg.h file. +* @return +* - XST_SUCCESS.if DMA transfer initiated successfully +* - XST_DEVICE_BUSY if DMA is busy +* - XST_INVALID_PARAM if invalid Source / Destination address +* is sent or an invalid Source / Destination length is +* sent +* +* @note It is the responsibility of the caller to ensure that the cache +* is flushed and invalidated both before the DMA operation is +* started and after the DMA operation completes if the memory +* pointed to is cached. The caller must also ensure that the +* pointers contain physical address rather than a virtual address +* if address translation is being used. +* +* The 2 LSBs of the SourcePtr (Source)/ DestPtr (Destination) +* address when equal to 2�b01 indicates the last DMA command of +* an overall transfer. +* +*****************************************************************************/ +u32 XDcfg_Transfer(XDcfg *InstancePtr, + void *SourcePtr, u32 SrcWordLength, + void *DestPtr, u32 DestWordLength, + u32 TransferType) +{ + + u32 CtrlReg; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + + if (XDcfg_IsDmaBusy(InstancePtr) == XST_SUCCESS) { + return XST_DEVICE_BUSY; + } + + /* + * Check whether the fabric is in initialized state + */ + if ((XDcfg_ReadReg(InstancePtr->Config.BaseAddr, XDCFG_STATUS_OFFSET) + & XDCFG_STATUS_PCFG_INIT_MASK) == 0) { + /* + * We don't need to check PCFG_INIT to be high for + * non-encrypted loopback transfers. + */ + if (TransferType != XDCFG_CONCURRENT_NONSEC_READ_WRITE) { + return XST_FAILURE; + } + } + + if ((TransferType == XDCFG_SECURE_PCAP_WRITE) || + (TransferType == XDCFG_NON_SECURE_PCAP_WRITE)) { + + /* Check for valid source pointer and length */ + if ((!SourcePtr) || (SrcWordLength == 0)) { + return XST_INVALID_PARAM; + } + + /* Clear internal PCAP loopback */ + CtrlReg = XDcfg_ReadReg(InstancePtr->Config.BaseAddr, + XDCFG_MCTRL_OFFSET); + XDcfg_WriteReg(InstancePtr->Config.BaseAddr, + XDCFG_MCTRL_OFFSET, (CtrlReg & + ~(XDCFG_MCTRL_PCAP_LPBK_MASK))); + + if (TransferType == XDCFG_NON_SECURE_PCAP_WRITE) { + /* + * Clear QUARTER_PCAP_RATE_EN bit + * so that the PCAP data is transmitted every clock + */ + CtrlReg = XDcfg_ReadReg(InstancePtr->Config.BaseAddr, + XDCFG_CTRL_OFFSET); + + XDcfg_WriteReg(InstancePtr->Config.BaseAddr, + XDCFG_CTRL_OFFSET, (CtrlReg & + ~XDCFG_CTRL_PCAP_RATE_EN_MASK)); + + } + if (TransferType == XDCFG_SECURE_PCAP_WRITE) { + /* + * AES engine handles only 8 bit data every clock cycle. + * Hence, Encrypted PCAP data which is 32 bit data can + * only be sent in every 4 clock cycles. Set the control + * register QUARTER_PCAP_RATE_EN bit to achieve this + * operation. + */ + XDcfg_SetControlRegister(InstancePtr, + XDCFG_CTRL_PCAP_RATE_EN_MASK); + } + + XDcfg_InitiateDma(InstancePtr, (u32)SourcePtr, + (u32)DestPtr, SrcWordLength, DestWordLength); + + } + + if (TransferType == XDCFG_PCAP_READBACK) { + + if ((!DestPtr) || (DestWordLength == 0)) { + + return XST_INVALID_PARAM; + } + + /* Clear internal PCAP loopback */ + CtrlReg = XDcfg_ReadReg(InstancePtr->Config.BaseAddr, + XDCFG_MCTRL_OFFSET); + XDcfg_WriteReg(InstancePtr->Config.BaseAddr, + XDCFG_MCTRL_OFFSET, (CtrlReg & + ~(XDCFG_MCTRL_PCAP_LPBK_MASK))); + + /* + * For PCAP readback of FPGA configuration register or memory, + * the read command is first sent (written) to the FPGA fabric + * which responds by returning the required read data. Read data + * from the FPGA is captured if pcap_radata_v is active.A DMA + * read transfer is required to obtain the readback command, + * which is then sent to the FPGA, followed by a DMA write + * transfer to support this mode of operation. + */ + return XDcfg_PcapReadback(InstancePtr, + (u32)SourcePtr, SrcWordLength, + (u32)DestPtr, DestWordLength); + } + + + if ((TransferType == XDCFG_CONCURRENT_SECURE_READ_WRITE) || + (TransferType == XDCFG_CONCURRENT_NONSEC_READ_WRITE)) { + + if ((!SourcePtr) || (SrcWordLength == 0) || + (!DestPtr) || (DestWordLength == 0)) { + return XST_INVALID_PARAM; + } + + if (TransferType == XDCFG_CONCURRENT_NONSEC_READ_WRITE) { + /* Enable internal PCAP loopback */ + CtrlReg = XDcfg_ReadReg(InstancePtr->Config.BaseAddr, + XDCFG_MCTRL_OFFSET); + XDcfg_WriteReg(InstancePtr->Config.BaseAddr, + XDCFG_MCTRL_OFFSET, (CtrlReg | + XDCFG_MCTRL_PCAP_LPBK_MASK)); + + /* + * Clear QUARTER_PCAP_RATE_EN bit + * so that the PCAP data is transmitted every clock + */ + CtrlReg = XDcfg_ReadReg(InstancePtr->Config.BaseAddr, + XDCFG_CTRL_OFFSET); + + XDcfg_WriteReg(InstancePtr->Config.BaseAddr, + XDCFG_CTRL_OFFSET, (CtrlReg & + ~XDCFG_CTRL_PCAP_RATE_EN_MASK)); + + } + if (TransferType == XDCFG_CONCURRENT_SECURE_READ_WRITE) { + /* Clear internal PCAP loopback */ + CtrlReg = XDcfg_ReadReg(InstancePtr->Config.BaseAddr, + XDCFG_MCTRL_OFFSET); + XDcfg_WriteReg(InstancePtr->Config.BaseAddr, + XDCFG_MCTRL_OFFSET, (CtrlReg & + ~(XDCFG_MCTRL_PCAP_LPBK_MASK))); + + /* + * Set the QUARTER_PCAP_RATE_EN bit + * so that the PCAP data is transmitted every 4 clock + * cycles, this is required for encrypted data. + */ + XDcfg_SetControlRegister(InstancePtr, + XDCFG_CTRL_PCAP_RATE_EN_MASK); + } + + XDcfg_InitiateDma(InstancePtr, (u32)SourcePtr, + (u32)DestPtr, SrcWordLength, DestWordLength); + } + + return XST_SUCCESS; +} +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/devcfg_v3_5/src/xdevcfg.h b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/devcfg_v3_5/src/xdevcfg.h new file mode 100644 index 0000000..6586370 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/devcfg_v3_5/src/xdevcfg.h @@ -0,0 +1,399 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2017 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xdevcfg.h +* @addtogroup devcfg_v3_5 +* @{ +* @details +* +* The is the main header file for the Device Configuration Interface of the Zynq +* device. The device configuration interface has three main functionality. +* 1. AXI-PCAP +* 2. Security Policy +* 3. XADC +* This current version of the driver supports only the AXI-PCAP and Security +* Policy blocks. There is a separate driver for XADC. +* +* AXI-PCAP is used for download/upload an encrypted or decrypted bitstream. +* DMA embedded in the AXI PCAP provides the master interface to +* the Device configuration block for any DMA transfers. The data transfer can +* take place between the Tx/RxFIFOs of AXI-PCAP and memory (on chip +* RAM/DDR/peripheral memory). +* +* The current driver only supports the downloading the FPGA bitstream and +* readback of the decrypted image (sort of loopback). +* The driver does not know what information needs to be written to the FPGA to +* readback FPGA configuration register or memory data. The application above the +* driver should take care of creating the data that needs to be downloaded to +* the FPGA so that the bitstream can be readback. +* This driver also does not support the reading of the internal registers of the +* PCAP. The driver has no knowledge of the PCAP internals. +* +* Initialization and Configuration +* +* The device driver enables higher layer software (e.g., an application) to +* communicate with the Device Configuration device. +* +* XDcfg_CfgInitialize() API is used to initialize the Device Configuration +* Interface. The user needs to first call the XDcfg_LookupConfig() API which +* returns the Configuration structure pointer which is passed as a parameter to +* the XDcfg_CfgInitialize() API. +* +* Interrupts +* The Driver implements an interrupt handler to support the interrupts provided +* by this interface. +* +* Threads +* +* This driver is not thread safe. Any needs for threads or thread mutual +* exclusion must be satisfied by the layer above this driver. +* +* Asserts +* +* Asserts are used within all Xilinx drivers to enforce constraints on argument +* values. Asserts can be turned off on a system-wide basis by defining, at +* compile time, the NDEBUG identifier. By default, asserts are turned on and it +* is recommended that users leave asserts on during development. +* +* Building the driver +* +* The XDcfg driver is composed of several source files. This allows the user +* to build and link only those parts of the driver that are necessary. +* +*

+* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 1.00a hvm 02/07/11 First release
+* 2.00a nm  05/31/12 Updated the driver for CR 660835 so that input length for
+*		     source/destination to the XDcfg_InitiateDma, XDcfg_Transfer
+*		     APIs is words (32 bit) and not bytes.
+* 		     Updated the notes for XDcfg_InitiateDma/XDcfg_Transfer APIs
+*		     to add information that 2 LSBs of the Source/Destination
+*		     address when equal to 2�b01 indicate the last DMA command
+*		     of an overall transfer.
+*		     Destination Address passed to this API for secure transfers
+*		     instead of using 0xFFFFFFFF for CR 662197. This issue was
+*		     resulting in the failure of secure transfers of
+*		     non-bitstream images.
+* 2.01a nm  07/07/12 Updated the XDcfg_IntrClear function to directly
+*		     set the mask instead of oring it with the
+*		     value read from the interrupt status register
+* 		     Added defines for the PS Version bits,
+*	             removed the FIFO Flush bits from the
+*		     Miscellaneous Control Reg.
+*		     Added XDcfg_GetPsVersion, XDcfg_SelectIcapInterface
+*		     and XDcfg_SelectPcapInterface APIs for CR 643295
+*		     The user has to call the XDcfg_SelectIcapInterface API
+*		     for the PL reconfiguration using AXI HwIcap.
+*		     Updated the XDcfg_Transfer API to clear the
+*		     QUARTER_PCAP_RATE_EN bit in the control register for
+*		     non secure writes for CR 675543.
+* 2.02a nm  01/31/13 Fixed CR# 679335.
+* 		     Added Setting and Clearing the internal PCAP loopback.
+*		     Removed code for enabling/disabling AES engine as BootROM
+*		     locks down this setting.
+*		     Fixed CR# 681976.
+*		     Skip Checking the PCFG_INIT in case of non-secure DMA
+*		     loopback.
+*		     Fixed CR# 699558.
+*		     XDcfg_Transfer fails to transfer data in loopback mode.
+*		     Fixed CR# 701348.
+*                    Peripheral test fails with  Running
+* 		     DcfgSelfTestExample() in SECURE bootmode.
+* 2.03a nm  04/19/13 Fixed CR# 703728.
+*		     Updated the register definitions as per the latest TRM
+*		     version UG585 (v1.4) November 16, 2012.
+* 3.0   adk 10/12/13 Updated as per the New Tcl API's
+* 3.0   kpc 21/02/14 Added function prototype for XDcfg_ClearControlRegister
+* 3.2   sb  08/25/14 Fixed XDcfg_PcapReadback() function
+*		     updated driver code with != instead of ==,
+*		     while checking for Interrupt Status with DMA and
+*		     PCAP Done Mask
+*		     ((XDcfg_ReadReg(InstancePtr->Config.BaseAddr,
+*			XDCFG_INT_STS_OFFSET) &
+*			XDCFG_IXR_D_P_DONE_MASK) !=
+*			XDCFG_IXR_D_P_DONE_MASK);
+*		     A new example has been added to read back the
+*		     configuration registers from the PL region.
+*		     xdevcfg_reg_readback_example.c
+* 3.3   sk  04/06/15 Modified XDcfg_ReadMultiBootConfig Macro CR# 851335.
+*       ms  03/17/17 Added readme.txt file in examples folder for doxygen
+*                    generation.
+*       ms  04/10/17 Modified filename tag in interrupt and polled examples
+*                    to include them in doxygen examples.
+* 3.5   ms  04/18/17 Modified tcl file to add suffix U for all macros
+*                    definitions of devcfg in xparameters.h
+*       ms  08/07/17 Fixed compilation warnings in xdevcfg_sinit.c
+* 
+* +******************************************************************************/ +#ifndef XDCFG_H /* prevent circular inclusions */ +#define XDCFG_H /* by using protection macros */ + +/***************************** Include Files *********************************/ + +#include "xdevcfg_hw.h" +#include "xstatus.h" +#include "xil_assert.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************** Constant Definitions *****************************/ + +/* Types of PCAP transfers */ + +#define XDCFG_NON_SECURE_PCAP_WRITE 1 +#define XDCFG_SECURE_PCAP_WRITE 2 +#define XDCFG_PCAP_READBACK 3 +#define XDCFG_CONCURRENT_SECURE_READ_WRITE 4 +#define XDCFG_CONCURRENT_NONSEC_READ_WRITE 5 + + +/**************************** Type Definitions *******************************/ +/** +* The handler data type allows the user to define a callback function to +* respond to interrupt events in the system. This function is executed +* in interrupt context, so amount of processing should be minimized. +* +* @param CallBackRef is the callback reference passed in by the upper +* layer when setting the callback functions, and passed back to +* the upper layer when the callback is invoked. Its type is +* unimportant to the driver component, so it is a void pointer. +* @param Status is the Interrupt status of the XDcfg device. +*/ +typedef void (*XDcfg_IntrHandler) (void *CallBackRef, u32 Status); + +/** + * This typedef contains configuration information for the device. + */ +typedef struct { + u16 DeviceId; /**< Unique ID of device */ + u32 BaseAddr; /**< Base address of the device */ +} XDcfg_Config; + +/** + * The XDcfg driver instance data. + */ +typedef struct { + XDcfg_Config Config; /**< Hardware Configuration */ + u32 IsReady; /**< Device is initialized and ready */ + u32 IsStarted; /**< Device Configuration Interface + * is running + */ + XDcfg_IntrHandler StatusHandler; /* Event handler function */ + void *CallBackRef; /* Callback reference for event handler */ +} XDcfg; + +/****************************************************************************/ +/** +* +* Unlock the Device Config Interface block. +* +* @param InstancePtr is a pointer to the instance of XDcfg driver. +* +* @return None. +* +* @note C-style signature: +* void XDcfg_Unlock(XDcfg* InstancePtr) +* +*****************************************************************************/ +#define XDcfg_Unlock(InstancePtr) \ + XDcfg_WriteReg((InstancePtr)->Config.BaseAddr, \ + XDCFG_UNLOCK_OFFSET, XDCFG_UNLOCK_DATA) + + + +/****************************************************************************/ +/** +* +* Get the version number of the PS from the Miscellaneous Control Register. +* +* @param InstancePtr is a pointer to the instance of XDcfg driver. +* +* @return Version of the PS. +* +* @note C-style signature: +* void XDcfg_GetPsVersion(XDcfg* InstancePtr) +* +*****************************************************************************/ +#define XDcfg_GetPsVersion(InstancePtr) \ + ((XDcfg_ReadReg((InstancePtr)->Config.BaseAddr, \ + XDCFG_MCTRL_OFFSET)) & \ + XDCFG_MCTRL_PCAP_PS_VERSION_MASK) >> \ + XDCFG_MCTRL_PCAP_PS_VERSION_SHIFT + + + +/****************************************************************************/ +/** +* +* Read the multiboot config register value. +* +* @param InstancePtr is a pointer to the instance of XDcfg driver. +* +* @return None. +* +* @note C-style signature: +* u32 XDcfg_ReadMultiBootConfig(XDcfg* InstancePtr) +* +*****************************************************************************/ +#define XDcfg_ReadMultiBootConfig(InstancePtr) \ + XDcfg_ReadReg((InstancePtr)->Config.BaseAddr, \ + XDCFG_MULTIBOOT_ADDR_OFFSET) + + +/****************************************************************************/ +/** +* +* Selects ICAP interface for reconfiguration after the initial configuration +* of the PL. +* +* @param InstancePtr is a pointer to the instance of XDcfg driver. +* +* @return None. +* +* @note C-style signature: +* void XDcfg_SelectIcapInterface(XDcfg* InstancePtr) +* +*****************************************************************************/ +#define XDcfg_SelectIcapInterface(InstancePtr) \ + XDcfg_WriteReg((InstancePtr)->Config.BaseAddr, XDCFG_CTRL_OFFSET, \ + ((XDcfg_ReadReg((InstancePtr)->Config.BaseAddr, XDCFG_CTRL_OFFSET)) \ + & ( ~XDCFG_CTRL_PCAP_PR_MASK))) + +/****************************************************************************/ +/** +* +* Selects PCAP interface for reconfiguration after the initial configuration +* of the PL. +* +* @param InstancePtr is a pointer to the instance of XDcfg driver. +* +* @return None. +* +* @note C-style signature: +* void XDcfg_SelectPcapInterface(XDcfg* InstancePtr) +* +*****************************************************************************/ +#define XDcfg_SelectPcapInterface(InstancePtr) \ + XDcfg_WriteReg((InstancePtr)->Config.BaseAddr, XDCFG_CTRL_OFFSET, \ + ((XDcfg_ReadReg((InstancePtr)->Config.BaseAddr, XDCFG_CTRL_OFFSET)) \ + | XDCFG_CTRL_PCAP_PR_MASK)) + + + +/************************** Function Prototypes ******************************/ + +/* + * Lookup configuration in xdevcfg_sinit.c. + */ +XDcfg_Config *XDcfg_LookupConfig(u16 DeviceId); + +/* + * Selftest function in xdevcfg_selftest.c + */ +int XDcfg_SelfTest(XDcfg *InstancePtr); + +/* + * Interface functions in xdevcfg.c + */ +int XDcfg_CfgInitialize(XDcfg *InstancePtr, + XDcfg_Config *ConfigPtr, u32 EffectiveAddress); + +void XDcfg_EnablePCAP(XDcfg *InstancePtr); + +void XDcfg_DisablePCAP(XDcfg *InstancePtr); + +void XDcfg_SetControlRegister(XDcfg *InstancePtr, u32 Mask); + +void XDcfg_ClearControlRegister(XDcfg *InstancePtr, u32 Mask); + +u32 XDcfg_GetControlRegister(XDcfg *InstancePtr); + +void XDcfg_SetLockRegister(XDcfg *InstancePtr, u32 Data); + +u32 XDcfg_GetLockRegister(XDcfg *InstancePtr); + +void XDcfg_SetConfigRegister(XDcfg *InstancePtr, u32 Data); + +u32 XDcfg_GetConfigRegister(XDcfg *InstancePtr); + +void XDcfg_SetStatusRegister(XDcfg *InstancePtr, u32 Data); + +u32 XDcfg_GetStatusRegister(XDcfg *InstancePtr); + +void XDcfg_SetRomShadowRegister(XDcfg *InstancePtr, u32 Data); + +u32 XDcfg_GetSoftwareIdRegister(XDcfg *InstancePtr); + +void XDcfg_SetMiscControlRegister(XDcfg *InstancePtr, u32 Mask); + +u32 XDcfg_GetMiscControlRegister(XDcfg *InstancePtr); + +u32 XDcfg_IsDmaBusy(XDcfg *InstancePtr); + +void XDcfg_InitiateDma(XDcfg *InstancePtr, u32 SourcePtr, u32 DestPtr, + u32 SrcWordLength, u32 DestWordLength); + +u32 XDcfg_Transfer(XDcfg *InstancePtr, + void *SourcePtr, u32 SrcWordLength, + void *DestPtr, u32 DestWordLength, + u32 TransferType); + +/* + * Interrupt related function prototypes implemented in xdevcfg_intr.c + */ +void XDcfg_IntrEnable(XDcfg *InstancePtr, u32 Mask); + +void XDcfg_IntrDisable(XDcfg *InstancePtr, u32 Mask); + +u32 XDcfg_IntrGetEnabled(XDcfg *InstancePtr); + +u32 XDcfg_IntrGetStatus(XDcfg *InstancePtr); + +void XDcfg_IntrClear(XDcfg *InstancePtr, u32 Mask); + +void XDcfg_InterruptHandler(XDcfg *InstancePtr); + +void XDcfg_SetHandler(XDcfg *InstancePtr, void *CallBackFunc, + void *CallBackRef); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/devcfg_v3_5/src/xdevcfg_g.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/devcfg_v3_5/src/xdevcfg_g.c new file mode 100644 index 0000000..3cc639c --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/devcfg_v3_5/src/xdevcfg_g.c @@ -0,0 +1,51 @@ + +/******************************************************************* +* +* CAUTION: This file is automatically generated by HSI. +* Version: 2019.1.3 +* DO NOT EDIT. +* +* Copyright (C) 2010-2023 Xilinx, Inc. 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 +*XILINX 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. +* +*Except as contained in this notice, the name of the Xilinx shall not be used +*in advertising or otherwise to promote the sale, use or other dealings in +*this Software without prior written authorization from Xilinx. +* + +* +* Description: Driver configuration +* +*******************************************************************/ + +#include "xparameters.h" +#include "xdevcfg.h" + +/* +* The configuration table for devices +*/ + +XDcfg_Config XDcfg_ConfigTable[] = +{ + { + XPAR_PS7_DEV_CFG_0_DEVICE_ID, + XPAR_PS7_DEV_CFG_0_BASEADDR + } +}; + + diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/devcfg_v3_5/src/xdevcfg_hw.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/devcfg_v3_5/src/xdevcfg_hw.c new file mode 100644 index 0000000..8a1379a --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/devcfg_v3_5/src/xdevcfg_hw.c @@ -0,0 +1,109 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xdevcfg_hw.c +* @addtogroup devcfg_v3_5 +* @{ +* +* This file contains the implementation of the interface reset functionality +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 2.04a kpc 10/07/13 First release
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xdevcfg_hw.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +/*****************************************************************************/ +/** +* This function perform the reset sequence to the given devcfg interface by +* configuring the appropriate control bits in the devcfg specifc registers +* the devcfg reset squence involves the following steps +* Disable all the interuupts +* Clear the status +* Update relevant config registers with reset values +* Disbale the looopback mode and pcap rate enable +* +* @param BaseAddress of the interface +* +* @return N/A +* +* @note +* This function will not modify the slcr registers that are relavant for +* devcfg controller +******************************************************************************/ +void XDcfg_ResetHw(u32 BaseAddr) +{ + u32 Regval = 0; + + /* Mask the interrupts */ + XDcfg_WriteReg(BaseAddr, XDCFG_INT_MASK_OFFSET, + XDCFG_IXR_ALL_MASK); + /* Clear the interuupt status */ + Regval = XDcfg_ReadReg(BaseAddr, XDCFG_INT_STS_OFFSET); + XDcfg_WriteReg(BaseAddr, XDCFG_INT_STS_OFFSET, Regval); + /* Clear the source address register */ + XDcfg_WriteReg(BaseAddr, XDCFG_DMA_SRC_ADDR_OFFSET, 0x0); + /* Clear the destination address register */ + XDcfg_WriteReg(BaseAddr, XDCFG_DMA_DEST_ADDR_OFFSET, 0x0); + /* Clear the source length register */ + XDcfg_WriteReg(BaseAddr, XDCFG_DMA_SRC_LEN_OFFSET, 0x0); + /* Clear the destination length register */ + XDcfg_WriteReg(BaseAddr, XDCFG_DMA_DEST_LEN_OFFSET, 0x0); + /* Clear the loopback enable bit */ + Regval = XDcfg_ReadReg(BaseAddr, XDCFG_MCTRL_OFFSET); + Regval = Regval & ~XDCFG_MCTRL_PCAP_LPBK_MASK; + XDcfg_WriteReg(BaseAddr, XDCFG_MCTRL_OFFSET, Regval); + /*Reset the configuration register to reset value */ + XDcfg_WriteReg(BaseAddr, XDCFG_CFG_OFFSET, + XDCFG_CONFIG_RESET_VALUE); + /*Disable the PCAP rate enable bit */ + Regval = XDcfg_ReadReg(BaseAddr, XDCFG_CTRL_OFFSET); + Regval = Regval & ~XDCFG_CTRL_PCAP_RATE_EN_MASK; + XDcfg_WriteReg(BaseAddr, XDCFG_CTRL_OFFSET, Regval); + +} +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/devcfg_v3_5/src/xdevcfg_hw.h b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/devcfg_v3_5/src/xdevcfg_hw.h new file mode 100644 index 0000000..80b6678 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/devcfg_v3_5/src/xdevcfg_hw.h @@ -0,0 +1,391 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xdevcfg_hw.h +* @addtogroup devcfg_v3_3 +* @{ +* +* This file contains the hardware interface to the Device Config Interface. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 1.00a hvm 02/07/11 First release
+* 2.01a nm  08/01/12 Added defines for the PS Version bits,
+*	             removed the FIFO Flush bits from the
+*		     Miscellaneous Control Reg
+* 2.03a nm  04/19/13 Fixed CR# 703728.
+*		     Updated the register definitions as per the latest TRM
+*		     version UG585 (v1.4) November 16, 2012.
+* 2.04a	kpc	10/07/13 Added function prototype.
+* 3.00a	kpc	25/02/14 Corrected the XDCFG_BASE_ADDRESS macro value.
+* 
+* +******************************************************************************/ +#ifndef XDCFG_HW_H /* prevent circular inclusions */ +#define XDCFG_HW_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_io.h" + +/************************** Constant Definitions *****************************/ + +/** @name Register Map + * Offsets of registers from the start of the device + * @{ + */ + +#define XDCFG_CTRL_OFFSET 0x00 /**< Control Register */ +#define XDCFG_LOCK_OFFSET 0x04 /**< Lock Register */ +#define XDCFG_CFG_OFFSET 0x08 /**< Configuration Register */ +#define XDCFG_INT_STS_OFFSET 0x0C /**< Interrupt Status Register */ +#define XDCFG_INT_MASK_OFFSET 0x10 /**< Interrupt Mask Register */ +#define XDCFG_STATUS_OFFSET 0x14 /**< Status Register */ +#define XDCFG_DMA_SRC_ADDR_OFFSET 0x18 /**< DMA Source Address Register */ +#define XDCFG_DMA_DEST_ADDR_OFFSET 0x1C /**< DMA Destination Address Reg */ +#define XDCFG_DMA_SRC_LEN_OFFSET 0x20 /**< DMA Source Transfer Length */ +#define XDCFG_DMA_DEST_LEN_OFFSET 0x24 /**< DMA Destination Transfer */ +#define XDCFG_ROM_SHADOW_OFFSET 0x28 /**< DMA ROM Shadow Register */ +#define XDCFG_MULTIBOOT_ADDR_OFFSET 0x2C /**< Multi BootAddress Pointer */ +#define XDCFG_SW_ID_OFFSET 0x30 /**< Software ID Register */ +#define XDCFG_UNLOCK_OFFSET 0x34 /**< Unlock Register */ +#define XDCFG_MCTRL_OFFSET 0x80 /**< Miscellaneous Control Reg */ + +/* @} */ + +/** @name Control Register Bit definitions + * @{ + */ + +#define XDCFG_CTRL_FORCE_RST_MASK 0x80000000 /**< Force into + * Secure Reset + */ +#define XDCFG_CTRL_PCFG_PROG_B_MASK 0x40000000 /**< Program signal to + * Reset FPGA + */ +#define XDCFG_CTRL_PCFG_POR_CNT_4K_MASK 0x20000000 /**< Control PL POR timer */ +#define XDCFG_CTRL_PCAP_PR_MASK 0x08000000 /**< Enable PCAP for PR */ +#define XDCFG_CTRL_PCAP_MODE_MASK 0x04000000 /**< Enable PCAP */ +#define XDCFG_CTRL_PCAP_RATE_EN_MASK 0x02000000 /**< Enable PCAP send data + * to FPGA every 4 PCAP + * cycles + */ +#define XDCFG_CTRL_MULTIBOOT_EN_MASK 0x01000000 /**< Multiboot Enable */ +#define XDCFG_CTRL_JTAG_CHAIN_DIS_MASK 0x00800000 /**< JTAG Chain Disable */ +#define XDCFG_CTRL_USER_MODE_MASK 0x00008000 /**< User Mode Mask */ +#define XDCFG_CTRL_PCFG_AES_FUSE_MASK 0x00001000 /**< AES key source */ +#define XDCFG_CTRL_PCFG_AES_EN_MASK 0x00000E00 /**< AES Enable Mask */ +#define XDCFG_CTRL_SEU_EN_MASK 0x00000100 /**< SEU Enable Mask */ +#define XDCFG_CTRL_SEC_EN_MASK 0x00000080 /**< Secure/Non Secure + * Status mask + */ +#define XDCFG_CTRL_SPNIDEN_MASK 0x00000040 /**< Secure Non Invasive + * Debug Enable + */ +#define XDCFG_CTRL_SPIDEN_MASK 0x00000020 /**< Secure Invasive + * Debug Enable + */ +#define XDCFG_CTRL_NIDEN_MASK 0x00000010 /**< Non-Invasive Debug + * Enable + */ +#define XDCFG_CTRL_DBGEN_MASK 0x00000008 /**< Invasive Debug + * Enable + */ +#define XDCFG_CTRL_DAP_EN_MASK 0x00000007 /**< DAP Enable Mask */ + +/* @} */ + +/** @name Lock register bit definitions + * @{ + */ + +#define XDCFG_LOCK_AES_EFUSE_MASK 0x00000010 /**< Lock AES Efuse bit */ +#define XDCFG_LOCK_AES_EN_MASK 0x00000008 /**< Lock AES_EN update */ +#define XDCFG_LOCK_SEU_MASK 0x00000004 /**< Lock SEU_En update */ +#define XDCFG_LOCK_SEC_MASK 0x00000002 /**< Lock SEC_EN and + * USER_MODE + */ +#define XDCFG_LOCK_DBG_MASK 0x00000001 /**< This bit locks + * security config + * including: DAP_En, + * DBGEN,, + * NIDEN, SPNIEN + */ +/*@}*/ + + + +/** @name Config Register Bit definitions + * @{ + */ +#define XDCFG_CFG_RFIFO_TH_MASK 0x00000C00 /**< Read FIFO + * Threshold Mask + */ +#define XDCFG_CFG_WFIFO_TH_MASK 0x00000300 /**< Write FIFO Threshold + * Mask + */ +#define XDCFG_CFG_RCLK_EDGE_MASK 0x00000080 /**< Read data active + * clock edge + */ +#define XDCFG_CFG_WCLK_EDGE_MASK 0x00000040 /**< Write data active + * clock edge + */ +#define XDCFG_CFG_DISABLE_SRC_INC_MASK 0x00000020 /**< Disable Source address + * increment mask + */ +#define XDCFG_CFG_DISABLE_DST_INC_MASK 0x00000010 /**< Disable Destination + * address increment + * mask + */ +/* @} */ + + +/** @name Interrupt Status/Mask Register Bit definitions + * @{ + */ +#define XDCFG_IXR_PSS_GTS_USR_B_MASK 0x80000000 /**< Tri-state IO during + * HIZ + */ +#define XDCFG_IXR_PSS_FST_CFG_B_MASK 0x40000000 /**< First configuration + * done + */ +#define XDCFG_IXR_PSS_GPWRDWN_B_MASK 0x20000000 /**< Global power down */ +#define XDCFG_IXR_PSS_GTS_CFG_B_MASK 0x10000000 /**< Tri-state IO during + * configuration + */ +#define XDCFG_IXR_PSS_CFG_RESET_B_MASK 0x08000000 /**< PL configuration + * reset + */ +#define XDCFG_IXR_AXI_WTO_MASK 0x00800000 /**< AXI Write Address + * or Data or response + * timeout + */ +#define XDCFG_IXR_AXI_WERR_MASK 0x00400000 /**< AXI Write response + * error + */ +#define XDCFG_IXR_AXI_RTO_MASK 0x00200000 /**< AXI Read Address or + * response timeout + */ +#define XDCFG_IXR_AXI_RERR_MASK 0x00100000 /**< AXI Read response + * error + */ +#define XDCFG_IXR_RX_FIFO_OV_MASK 0x00040000 /**< Rx FIFO Overflow */ +#define XDCFG_IXR_WR_FIFO_LVL_MASK 0x00020000 /**< Tx FIFO less than + * threshold */ +#define XDCFG_IXR_RD_FIFO_LVL_MASK 0x00010000 /**< Rx FIFO greater than + * threshold */ +#define XDCFG_IXR_DMA_CMD_ERR_MASK 0x00008000 /**< Illegal DMA command */ +#define XDCFG_IXR_DMA_Q_OV_MASK 0x00004000 /**< DMA command queue + * overflow + */ +#define XDCFG_IXR_DMA_DONE_MASK 0x00002000 /**< DMA Command Done */ +#define XDCFG_IXR_D_P_DONE_MASK 0x00001000 /**< DMA and PCAP + * transfers Done + */ +#define XDCFG_IXR_P2D_LEN_ERR_MASK 0x00000800 /**< PCAP to DMA transfer + * length error + */ +#define XDCFG_IXR_PCFG_HMAC_ERR_MASK 0x00000040 /**< HMAC error mask */ +#define XDCFG_IXR_PCFG_SEU_ERR_MASK 0x00000020 /**< SEU Error mask */ +#define XDCFG_IXR_PCFG_POR_B_MASK 0x00000010 /**< FPGA POR mask */ +#define XDCFG_IXR_PCFG_CFG_RST_MASK 0x00000008 /**< FPGA Reset mask */ +#define XDCFG_IXR_PCFG_DONE_MASK 0x00000004 /**< Done Signal Mask */ +#define XDCFG_IXR_PCFG_INIT_PE_MASK 0x00000002 /**< Detect Positive edge + * of Init Signal + */ +#define XDCFG_IXR_PCFG_INIT_NE_MASK 0x00000001 /**< Detect Negative edge + * of Init Signal + */ +#define XDCFG_IXR_ERROR_FLAGS_MASK (XDCFG_IXR_AXI_WTO_MASK | \ + XDCFG_IXR_AXI_WERR_MASK | \ + XDCFG_IXR_AXI_RTO_MASK | \ + XDCFG_IXR_AXI_RERR_MASK | \ + XDCFG_IXR_RX_FIFO_OV_MASK | \ + XDCFG_IXR_DMA_CMD_ERR_MASK |\ + XDCFG_IXR_DMA_Q_OV_MASK | \ + XDCFG_IXR_P2D_LEN_ERR_MASK |\ + XDCFG_IXR_PCFG_HMAC_ERR_MASK) + + +#define XDCFG_IXR_ALL_MASK 0x00F7F8EF + + + +/* @} */ + + +/** @name Status Register Bit definitions + * @{ + */ +#define XDCFG_STATUS_DMA_CMD_Q_F_MASK 0x80000000 /**< DMA command + * Queue full + */ +#define XDCFG_STATUS_DMA_CMD_Q_E_MASK 0x40000000 /**< DMA command + * Queue empty + */ +#define XDCFG_STATUS_DMA_DONE_CNT_MASK 0x30000000 /**< Number of + * completed DMA + * transfers + */ +#define XDCFG_STATUS_RX_FIFO_LVL_MASK 0x01F000000 /**< Rx FIFO level */ +#define XDCFG_STATUS_TX_FIFO_LVL_MASK 0x0007F000 /**< Tx FIFO level */ + +#define XDCFG_STATUS_PSS_GTS_USR_B 0x00000800 /**< Tri-state IO + * during HIZ + */ +#define XDCFG_STATUS_PSS_FST_CFG_B 0x00000400 /**< First PL config + * done + */ +#define XDCFG_STATUS_PSS_GPWRDWN_B 0x00000200 /**< Global power down */ +#define XDCFG_STATUS_PSS_GTS_CFG_B 0x00000100 /**< Tri-state IO during + * config + */ +#define XDCFG_STATUS_SECURE_RST_MASK 0x00000080 /**< Secure Reset + * POR Status + */ +#define XDCFG_STATUS_ILLEGAL_APB_ACCESS_MASK 0x00000040 /**< Illegal APB + * access + */ +#define XDCFG_STATUS_PSS_CFG_RESET_B 0x00000020 /**< PL config + * reset status + */ +#define XDCFG_STATUS_PCFG_INIT_MASK 0x00000010 /**< FPGA Init + * Status + */ +#define XDCFG_STATUS_EFUSE_BBRAM_KEY_DISABLE_MASK 0x00000008 + /**< BBRAM key + * disable + */ +#define XDCFG_STATUS_EFUSE_SEC_EN_MASK 0x00000004 /**< Efuse Security + * Enable Status + */ +#define XDCFG_STATUS_EFUSE_JTAG_DIS_MASK 0x00000002 /**< EFuse JTAG + * Disable + * status + */ +/* @} */ + + +/** @name DMA Source/Destination Transfer Length Register Bit definitions + * @{ + */ +#define XDCFG_DMA_LEN_MASK 0x7FFFFFF /**< Length Mask */ +/*@}*/ + + + + +/** @name Miscellaneous Control Register Bit definitions + * @{ + */ +#define XDCFG_MCTRL_PCAP_PS_VERSION_MASK 0xF0000000 /**< PS Version Mask */ +#define XDCFG_MCTRL_PCAP_PS_VERSION_SHIFT 28 /**< PS Version Shift */ +#define XDCFG_MCTRL_PCAP_LPBK_MASK 0x00000010 /**< PCAP loopback mask */ +/* @} */ + +/** @name FIFO Threshold Bit definitions + * @{ + */ + +#define XDCFG_CFG_FIFO_QUARTER 0x0 /**< Quarter empty */ +#define XDCFG_CFG_FIFO_HALF 0x1 /**< Half empty */ +#define XDCFG_CFG_FIFO_3QUARTER 0x2 /**< 3/4 empty */ +#define XDCFG_CFG_FIFO_EMPTY 0x4 /**< Empty */ +/* @}*/ + + +/* Miscellaneous constant values */ +#define XDCFG_DMA_INVALID_ADDRESS 0xFFFFFFFF /**< Invalid DMA address */ +#define XDCFG_UNLOCK_DATA 0x757BDF0D /**< First APB access data*/ +#define XDCFG_BASE_ADDRESS 0xF8007000 /**< Device Config base + * address + */ +#define XDCFG_CONFIG_RESET_VALUE 0x508 /**< Config reg reset value */ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/****************************************************************************/ +/** +* +* Read the given register. +* +* @param BaseAddr is the base address of the device +* @param RegOffset is the register offset to be read +* +* @return The 32-bit value of the register +* +* @note C-style signature: +* u32 XDcfg_ReadReg(u32 BaseAddr, u32 RegOffset) +* +*****************************************************************************/ +#define XDcfg_ReadReg(BaseAddr, RegOffset) \ + Xil_In32((BaseAddr) + (RegOffset)) + +/****************************************************************************/ +/** +* +* Write to the given register. +* +* @param BaseAddr is the base address of the device +* @param RegOffset is the register offset to be written +* @param Data is the 32-bit value to write to the register +* +* @return None. +* +* @note C-style signature: +* void XDcfg_WriteReg(u32 BaseAddr, u32 RegOffset, u32 Data) +* +*****************************************************************************/ +#define XDcfg_WriteReg(BaseAddr, RegOffset, Data) \ + Xil_Out32((BaseAddr) + (RegOffset), (Data)) + +/************************** Function Prototypes ******************************/ +/* + * Perform reset operation to the devcfg interface + */ +void XDcfg_ResetHw(u32 BaseAddr); +/************************** Variable Definitions *****************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/devcfg_v3_5/src/xdevcfg_intr.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/devcfg_v3_5/src/xdevcfg_intr.c new file mode 100644 index 0000000..f0e5044 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/devcfg_v3_5/src/xdevcfg_intr.c @@ -0,0 +1,306 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xdevcfg_intr.c +* @addtogroup devcfg_v3_5 +* @{ +* +* Contains the implementation of interrupt related functions of the XDcfg +* driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 1.00a hvm 02/07/11 First release
+* 2.01a nm  07/07/12 Updated the XDcfg_IntrClear function to directly
+*		     set the mask instead of oring it with the
+*		     value read from the interrupt status register
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xdevcfg.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +/****************************************************************************/ +/** +* +* This function enables the specified interrupts in the device. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* @param Mask is the bit-mask of the interrupts to be enabled. +* Bit positions of 1 will be enabled. Bit positions of 0 will +* keep the previous setting. This mask is formed by OR'ing +* XDCFG_INT_* bits defined in xdevcfg_hw.h. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XDcfg_IntrEnable(XDcfg *InstancePtr, u32 Mask) +{ + u32 RegValue; + + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Enable the specified interrupts in the Interrupt Mask Register. + */ + RegValue = XDcfg_ReadReg(InstancePtr->Config.BaseAddr, + XDCFG_INT_MASK_OFFSET); + RegValue &= ~(Mask & XDCFG_IXR_ALL_MASK); + XDcfg_WriteReg(InstancePtr->Config.BaseAddr, + XDCFG_INT_MASK_OFFSET, + RegValue); +} + + +/****************************************************************************/ +/** +* +* This function disables the specified interrupts in the device. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* @param Mask is the bit-mask of the interrupts to be disabled. +* Bit positions of 1 will be disabled. Bit positions of 0 will +* keep the previous setting. This mask is formed by OR'ing +* XDCFG_INT_* bits defined in xdevcfg_hw.h. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XDcfg_IntrDisable(XDcfg *InstancePtr, u32 Mask) +{ + u32 RegValue; + + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Disable the specified interrupts in the Interrupt Mask Register. + */ + RegValue = XDcfg_ReadReg(InstancePtr->Config.BaseAddr, + XDCFG_INT_MASK_OFFSET); + RegValue |= (Mask & XDCFG_IXR_ALL_MASK); + XDcfg_WriteReg(InstancePtr->Config.BaseAddr, + XDCFG_INT_MASK_OFFSET, + RegValue); +} +/****************************************************************************/ +/** +* +* This function returns the enabled interrupts read from the Interrupt Mask +* Register. Use the XDCFG_INT_* constants defined in xdevcfg_hw.h +* to interpret the returned value. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* +* @return A 32-bit value representing the contents of the IMR. +* +* @note None. +* +*****************************************************************************/ +u32 XDcfg_IntrGetEnabled(XDcfg *InstancePtr) +{ + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Return the value read from the Interrupt Mask Register. + */ + return (~ XDcfg_ReadReg(InstancePtr->Config.BaseAddr, + XDCFG_INT_MASK_OFFSET)); +} + +/****************************************************************************/ +/** +* +* This function returns the interrupt status read from Interrupt Status +* Register. Use the XDCFG_INT_* constants defined in xdevcfg_hw.h +* to interpret the returned value. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* +* @return A 32-bit value representing the contents of the Interrupt +* Status register. +* +* @note None. +* +*****************************************************************************/ +u32 XDcfg_IntrGetStatus(XDcfg *InstancePtr) +{ + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Return the value read from the Interrupt Status register. + */ + return XDcfg_ReadReg(InstancePtr->Config.BaseAddr, + XDCFG_INT_STS_OFFSET); +} + +/****************************************************************************/ +/** +* +* This function clears the specified interrupts in the Interrupt Status +* Register. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* @param Mask is the bit-mask of the interrupts to be cleared. +* Bit positions of 1 will be cleared. Bit positions of 0 will not +* change the previous interrupt status. This mask is formed by +* OR'ing XDCFG_INT_* bits which are defined in xdevcfg_hw.h. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XDcfg_IntrClear(XDcfg *InstancePtr, u32 Mask) +{ + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + XDcfg_WriteReg(InstancePtr->Config.BaseAddr, + XDCFG_INT_STS_OFFSET, + Mask); + +} + +/*****************************************************************************/ +/** +* The interrupt handler for the Device Config Interface. +* +* Events are signaled to upper layer for proper handling. +* +* +* @param InstancePtr is a pointer to the XDcfg instance. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void XDcfg_InterruptHandler(XDcfg *InstancePtr) +{ + u32 IntrStatusReg; + + /* + * Assert validates the input arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the Interrupt status register. + */ + IntrStatusReg = XDcfg_ReadReg(InstancePtr->Config.BaseAddr, + XDCFG_INT_STS_OFFSET); + + /* + * Write the status back to clear the interrupts so that no + * subsequent interrupts are missed while processing this interrupt. + * This also does the DMA acknowledgment automatically. + */ + XDcfg_WriteReg(InstancePtr->Config.BaseAddr, + XDCFG_INT_STS_OFFSET, IntrStatusReg); + + /* + * Signal application that there are events to handle. + */ + InstancePtr->StatusHandler(InstancePtr->CallBackRef, + IntrStatusReg); + +} + +/****************************************************************************/ +/** +* +* This function sets the handler that will be called when an event (interrupt) +* occurs that needs application's attention. +* +* @param InstancePtr is a pointer to the XDcfg instance +* @param CallBackFunc is the address of the callback function. +* @param CallBackRef is a user data item that will be passed to the +* callback function when it is invoked. +* +* @return None. +* +* @note None. +* +* +*****************************************************************************/ +void XDcfg_SetHandler(XDcfg *InstancePtr, void *CallBackFunc, + void *CallBackRef) +{ + /* + * Asserts validate the input arguments + * CallBackRef not checked, no way to know what is valid + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(CallBackFunc != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + InstancePtr->StatusHandler = (XDcfg_IntrHandler) CallBackFunc; + InstancePtr->CallBackRef = CallBackRef; +} +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/devcfg_v3_5/src/xdevcfg_selftest.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/devcfg_v3_5/src/xdevcfg_selftest.c new file mode 100644 index 0000000..e8fc663 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/devcfg_v3_5/src/xdevcfg_selftest.c @@ -0,0 +1,110 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xdevcfg_selftest.c +* @addtogroup devcfg_v3_5 +* @{ +* +* Contains diagnostic self-test functions for the XDcfg driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 1.00a hvm 02/07/11 First release
+* 2.02a nm  02/27/13 Fixed CR# 701348.
+*                    Peripheral test fails with  Running
+* 		     DcfgSelfTestExample() in SECURE bootmode.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xdevcfg.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +/****************************************************************************/ +/** +* +* Run a self-test on the Device Configuration Interface. This test does a +* control register write and reads back the same value. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* +* @return +* - XST_SUCCESS if self-test was successful. +* - XST_FAILURE if fails. +* +* @note None. +* +******************************************************************************/ +int XDcfg_SelfTest(XDcfg *InstancePtr) +{ + u32 OldCfgReg; + u32 CfgReg; + int Status = XST_SUCCESS; + + /* + * Assert to ensure the inputs are valid and the instance has been + * initialized. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + OldCfgReg = XDcfg_GetControlRegister(InstancePtr); + + XDcfg_SetControlRegister(InstancePtr, XDCFG_CTRL_NIDEN_MASK); + + CfgReg = XDcfg_GetControlRegister(InstancePtr); + + if ((CfgReg & XDCFG_CTRL_NIDEN_MASK) != XDCFG_CTRL_NIDEN_MASK) { + + Status = XST_FAILURE; + } + + /* + * Restore the original values of the register + */ + XDcfg_SetControlRegister(InstancePtr, OldCfgReg); + + return Status; +} +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/devcfg_v3_5/src/xdevcfg_sinit.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/devcfg_v3_5/src/xdevcfg_sinit.c new file mode 100644 index 0000000..838db3a --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/devcfg_v3_5/src/xdevcfg_sinit.c @@ -0,0 +1,90 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2017 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xdevcfg_sinit.c +* @addtogroup devcfg_v3_5 +* @{ +* +* This file contains method for static initialization (compile-time) of the +* driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 1.00a hvm 02/07/11 First release
+* 3.5   ms  08/07/17 Fixed compilation warnings.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xdevcfg.h" +#include "xparameters.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/*****************************************************************************/ +/** +* Lookup the device configuration based on the unique device ID. The table +* contains the configuration info for each device in the system. +* +* @param DeviceId is the unique device ID of the device being looked up. +* +* @return A pointer to the configuration table entry corresponding to the +* given device ID, or NULL if no match is found. +* +* @note None. +* +******************************************************************************/ +XDcfg_Config *XDcfg_LookupConfig(u16 DeviceId) +{ + extern XDcfg_Config XDcfg_ConfigTable[]; + XDcfg_Config *CfgPtr = NULL; + u32 Index; + + for (Index = 0U; Index < XPAR_XDCFG_NUM_INSTANCES; Index++) { + if (XDcfg_ConfigTable[Index].DeviceId == DeviceId) { + CfgPtr = &XDcfg_ConfigTable[Index]; + break; + } + } + + return (CfgPtr); +} +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/dmaps_v2_4/src/Makefile b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/dmaps_v2_4/src/Makefile new file mode 100644 index 0000000..d1240c5 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/dmaps_v2_4/src/Makefile @@ -0,0 +1,41 @@ +COMPILER= +ARCHIVER= +CP=cp +COMPILER_FLAGS= +EXTRA_COMPILER_FLAGS= +LIB=libxil.a + +CC_FLAGS = $(COMPILER_FLAGS) +ECC_FLAGS = $(EXTRA_COMPILER_FLAGS) + +RELEASEDIR=../../../lib +INCLUDEDIR=../../../include +INCLUDES=-I./. -I${INCLUDEDIR} + +OUTS = *.o + +LIBSOURCES:=*.c +INCLUDEFILES:=*.h + +OBJECTS = $(addsuffix .o, $(basename $(wildcard *.c))) + +libs: banner xdmaps_libs clean + +%.o: %.c + ${COMPILER} $(CC_FLAGS) $(ECC_FLAGS) $(INCLUDES) -o $@ $< + +banner: + echo "Compiling dmaps" + +xdmaps_libs: ${OBJECTS} + $(ARCHIVER) -r ${RELEASEDIR}/${LIB} ${OBJECTS} + +.PHONY: include +include: xdmaps_includes + +xdmaps_includes: + ${CP} ${INCLUDEFILES} ${INCLUDEDIR} + +clean: + rm -rf ${OBJECTS} + diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/dmaps_v2_4/src/xdmaps.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/dmaps_v2_4/src/xdmaps.c new file mode 100644 index 0000000..b30a66f --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/dmaps_v2_4/src/xdmaps.c @@ -0,0 +1,1978 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xdmaps.c +* @addtogroup dmaps_v2_4 +* @{ +* +* This file contains the implementation of the interface functions for XDmaPs +* driver. Refer to the header file xdmaps.h for more detailed information. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  	Date     Changes
+* ----- ------ -------- ----------------------------------------------
+* 1.00	hbm    08/19/2010 First Release
+* 1.00  nm     05/25/2011 Updated for minor doxygen corrections
+* 1.02a sg     05/16/2012 Made changes for doxygen and moved some function
+*			  header from the xdmaps.h file to xdmaps.c file
+*			  Other cleanup for coding guidelines and CR 657109
+*			  and CR 657898
+* 1.03a sg     07/16/2012 changed inline to __inline for CR665681
+* 1.04a nm     10/22/2012 Fixed CR# 681671.
+* 1.05a nm     04/15/2013 Fixed CR# 704396. Removed warnings when compiled
+*			  with -Wall and -Wextra option in bsp.
+*	       05/01/2013 Fixed CR# 700189. Changed XDmaPs_BuildDmaProg()
+*			  function description.
+*			  Fixed CR# 704396. Removed unused variables
+*			  UseM2MByte & MemBurstLen from XDmaPs_BuildDmaProg()
+*			  function.
+* 1.07a asa    11/02/13. Made changes to fix compilation issues for iarcc.
+*			   Removed the PDBG prints. By default they were always
+*			   defined out and never used. The PDBG is non-standard for
+*			   Xilinx drivers and no other driver does something similar.
+*			   Since there is no easy way to fix compilation issues with
+*			   the IARCC compiler around PDBG, it is better to remove it.
+*			   Users can always use xil_printfs if they want to debug.
+* 2.01 kpc    08/23/14   Fixed the IAR compiler reported errors
+* 2.2  mus    12/08/16   Remove definition of INLINE macro to avoid re-definition,
+*                         since it is being defined in xil_io.h
+* 2.3 kpc     14/10/16   Fixed the compiler error when optimization O0 is used.
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ + +#include + +#include "xstatus.h" +#include "xdmaps.h" +#include "xil_io.h" +#include "xil_cache.h" + +#include "xil_printf.h" + + +/************************** Constant Definitions ****************************/ + +/* The following constant defines the amount of error that is allowed for + * a specified baud rate. This error is the difference between the actual + * baud rate that will be generated using the specified clock and the + * desired baud rate. + */ + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + + +/************************** Function Prototypes *****************************/ +static int XDmaPs_Exec_DMAKILL(u32 BaseAddr, + unsigned int Channel, + unsigned int Thread); + +static void XDmaPs_BufPool_Free(XDmaPs_ProgBuf *Pool, void *Buf); + +static int XDmaPs_Exec_DMAGO(u32 BaseAddr, unsigned int Channel, u32 DmaProg); + +static void XDmaPs_DoneISR_n(XDmaPs *InstPtr, unsigned Channel); +static void *XDmaPs_BufPool_Allocate(XDmaPs_ProgBuf *Pool); +static int XDmaPs_BuildDmaProg(unsigned Channel, XDmaPs_Cmd *Cmd, + unsigned CacheLength); + +static void XDmaPs_Print_DmaProgBuf(char *Buf, int Length); + + + +/************************** Variable Definitions ****************************/ + +/****************************************************************************/ +/** +* +* Initializes a specific XDmaPs instance such that it is ready to be used. +* The data format of the device is setup for 8 data bits, 1 stop bit, and no +* parity by default. The baud rate is set to a default value specified by +* Config->DefaultBaudRate if set, otherwise it is set to 19.2K baud. The +* receive FIFO threshold is set for 8 bytes. The default operating mode of the +* driver is polled mode. +* +* @param InstPtr is a pointer to the XDmaPs instance. +* @param Config is a reference to a structure containing information +* about a specific XDmaPs driver. +* @param EffectiveAddr is the device base address in the virtual memory +* address space. The caller is responsible for keeping the +* address mapping from EffectiveAddr to the device physical base +* address unchanged once this function is invoked. Unexpected +* errors may occur if the address mapping changes after this +* function is called. If address translation is not used, pass in +* the physical address instead. +* +* @return +* +* - XST_SUCCESS on initialization completion +* +* @note None. +* +*****************************************************************************/ +int XDmaPs_CfgInitialize(XDmaPs *InstPtr, + XDmaPs_Config *Config, + u32 EffectiveAddr) +{ + int Status = XST_SUCCESS; + unsigned int CacheLength = 0; + u32 CfgReg; + unsigned Channel; + XDmaPs_ChannelData *ChanData; + + /* + * Assert validates the input arguments + */ + Xil_AssertNonvoid(InstPtr != NULL); + Xil_AssertNonvoid(Config != NULL); + + /* + * Setup the driver instance using passed in parameters + */ + InstPtr->Config.DeviceId = Config->DeviceId; + InstPtr->Config.BaseAddress = EffectiveAddr; + + CfgReg = XDmaPs_ReadReg(EffectiveAddr, XDMAPS_CR1_OFFSET); + CacheLength = CfgReg & XDMAPS_CR1_I_CACHE_LEN_MASK; + if (CacheLength < 2 || CacheLength > 5) + CacheLength = 0; + else + CacheLength = 1 << CacheLength; + + InstPtr->CacheLength = CacheLength; + + memset(InstPtr->Chans, 0, + sizeof(XDmaPs_ChannelData[XDMAPS_CHANNELS_PER_DEV])); + + for (Channel = 0; Channel < XDMAPS_CHANNELS_PER_DEV; Channel++) { + ChanData = InstPtr->Chans + Channel; + ChanData->ChanId = Channel; + ChanData->DevId = Config->DeviceId; + } + + InstPtr->IsReady = 1; + + return Status; +} + +/****************************************************************************/ +/** +* +* Reset the DMA Manager. +* +* @param InstPtr is the DMA instance. +* +* @return 0 on success, -1 on time out +* +* @note None. +* +*****************************************************************************/ +int XDmaPs_ResetManager(XDmaPs *InstPtr) +{ + int Status; + Status = XDmaPs_Exec_DMAKILL(InstPtr->Config.BaseAddress, + 0, 0); + + return Status; +} + +/****************************************************************************/ +/** +* +* Reset the specified DMA Channel. +* +* @param InstPtr is the DMA instance. +* @param Channel is the channel to be reset. +* +* @return 0 on success, -1 on time out +* +* @note None. +* +*****************************************************************************/ +int XDmaPs_ResetChannel(XDmaPs *InstPtr, unsigned int Channel) +{ + int Status; + Status = XDmaPs_Exec_DMAKILL(InstPtr->Config.BaseAddress, + Channel, 1); + + return Status; + +} + +/*****************************************************************************/ +/** +* +* Driver fault interrupt service routine +* This is the one that connects the GIC +* +* @param InstPtr is the DMA instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XDmaPs_FaultISR(XDmaPs *InstPtr) +{ + + void *DmaProgBuf; + u32 Fsm; /* Fault status DMA manager register value */ + u32 Fsc; /* Fault status DMA channel register value */ + u32 FaultType; /* Fault type DMA manager register value */ + + u32 BaseAddr = InstPtr->Config.BaseAddress; + + u32 Pc; /* DMA Pc or channel Pc */ + XDmaPs_ChannelData *ChanData; + + unsigned Chan; + unsigned DevId; + + XDmaPs_Cmd *DmaCmd; + + Fsm = XDmaPs_ReadReg(BaseAddr, XDMAPS_FSM_OFFSET) & 0x01; + Fsc = XDmaPs_ReadReg(BaseAddr, XDMAPS_FSC_OFFSET) & 0xFF; + + + DevId = InstPtr->Config.DeviceId; + + if (Fsm) { + /* + * if DMA manager is fault + */ + FaultType = XDmaPs_ReadReg(BaseAddr, XDMAPS_FTM_OFFSET); + Pc = XDmaPs_ReadReg(BaseAddr, XDMAPS_DPC_OFFSET); + + xil_printf("PL330 device %d fault with type: %x at Pc %x\n", + DevId, + FaultType, Pc); + + /* kill the DMA manager thread */ + /* Should we disable interrupt?*/ + XDmaPs_Exec_DMAKILL(BaseAddr, 0, 0); + } + + /* + * check which channel faults and kill the channel thread + */ + for (Chan = 0; + Chan < XDMAPS_CHANNELS_PER_DEV; + Chan++) { + if (Fsc & (0x01 << Chan)) { + FaultType = + XDmaPs_ReadReg(BaseAddr, + XDmaPs_FTCn_OFFSET(Chan)); + Pc = XDmaPs_ReadReg(BaseAddr, + XDmaPs_CPCn_OFFSET(Chan)); + + /* kill the channel thread */ + /* Should we disable interrupt? */ + XDmaPs_Exec_DMAKILL(BaseAddr, Chan, 1); + + /* + * get the fault type and fault Pc and invoke the + * fault callback. + */ + ChanData = InstPtr->Chans + Chan; + + DmaCmd = ChanData->DmaCmdToHw; + + /* Should we check DmaCmd is not null */ + DmaCmd->DmaStatus = -1; + DmaCmd->ChanFaultType = FaultType; + DmaCmd->ChanFaultPCAddr = Pc; + ChanData->DmaCmdFromHw = DmaCmd; + ChanData->DmaCmdToHw = NULL; + + if (!ChanData->HoldDmaProg) { + DmaProgBuf = (void *)DmaCmd->GeneratedDmaProg; + if (DmaProgBuf) + XDmaPs_BufPool_Free(ChanData->ProgBufPool, + DmaProgBuf); + DmaCmd->GeneratedDmaProg = NULL; + } + + if (InstPtr->FaultHandler) + InstPtr->FaultHandler(Chan, + DmaCmd, + InstPtr->FaultRef); + + } + } + +} + +/*****************************************************************************/ +/** +* +* Set the done handler for a channel. +* +* @param InstPtr is the DMA instance. +* @param Channel is the channel number. +* @param DoneHandler is the done interrupt handler. +* @param CallbackRef is the callback reference data. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +int XDmaPs_SetDoneHandler(XDmaPs *InstPtr, + unsigned Channel, + XDmaPsDoneHandler DoneHandler, + void *CallbackRef) +{ + XDmaPs_ChannelData *ChanData; + + Xil_AssertNonvoid(InstPtr != NULL); + + if (Channel >= XDMAPS_CHANNELS_PER_DEV) + return XST_FAILURE; + + + ChanData = InstPtr->Chans + Channel; + + ChanData->DoneHandler = DoneHandler; + ChanData->DoneRef = CallbackRef; + + return 0; +} + +/*****************************************************************************/ +/** +* +* Set the fault handler for a channel. +* +* @param InstPtr is the DMA instance. +* @param FaultHandler is the fault interrupt handler. +* @param CallbackRef is the callback reference data. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +int XDmaPs_SetFaultHandler(XDmaPs *InstPtr, + XDmaPsFaultHandler FaultHandler, + void *CallbackRef) +{ + Xil_AssertNonvoid(InstPtr != NULL); + + InstPtr->FaultHandler = FaultHandler; + InstPtr->FaultRef = CallbackRef; + + return XST_SUCCESS; +} + + + +/****************************************************************************/ +/** +* Construction function for DMAEND instruction. This function fills the program +* buffer with the constructed instruction. +* +* @param DmaProg the DMA program buffer, it's the starting address for +* the instruction being constructed +* +* @return The number of bytes for this instruction which is 1. +* +* @note None. +* +*****************************************************************************/ +static INLINE int XDmaPs_Instr_DMAEND(char *DmaProg) +{ + /* + * DMAEND encoding: + * 7 6 5 4 3 2 1 0 + * 0 0 0 0 0 0 0 0 + */ + *DmaProg = 0x0; + + return 1; +} + +static INLINE void XDmaPs_Memcpy4(char *Dst, char *Src) +{ + *Dst = *Src; + *(Dst + 1) = *(Src + 1); + *(Dst + 2) = *(Src + 2); + *(Dst + 3) = *(Src + 3); +} + +/****************************************************************************/ +/** +* +* Construction function for DMAGO instruction. This function fills the program +* buffer with the constructed instruction. +* +* @param DmaProg is the DMA program buffer, it's the starting address +* for the instruction being constructed +* @param Cn is the Channel number, 0 - 7 +* @param Imm is 32-bit immediate number written to the Channel Program +* Counter. +* @param Ns is Non-secure flag. If Ns is 1, the DMA channel operates in +* the Non-secure state. If Ns is 0, the execution depends on the +* security state of the DMA manager: +* DMA manager is in the Secure state, DMA channel operates in the +* Secure state. +* DMA manager is in the Non-secure state, DMAC aborts. +* +* @return The number of bytes for this instruction which is 6. +* +* @note None +* +*****************************************************************************/ +static INLINE int XDmaPs_Instr_DMAGO(char *DmaProg, unsigned int Cn, + u32 Imm, unsigned int Ns) +{ + /* + * DMAGO encoding: + * 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 + * 0 0 0 0 0 |cn[2:0]| 1 0 1 0 0 0 ns 0 + * + * 47 ... 16 + * imm[32:0] + */ + *DmaProg = 0xA0 | ((Ns << 1) & 0x02); + + *(DmaProg + 1) = (u8)(Cn & 0x07); + + // *((u32 *)(DmaProg + 2)) = Imm; + XDmaPs_Memcpy4(DmaProg + 2, (char *)&Imm); + + /* success */ + return 6; +} + +/****************************************************************************/ +/** +* +* Construction function for DMALD instruction. This function fills the program +* buffer with the constructed instruction. +* +* @param DmaProg the DMA program buffer, it's the starting address for the +* instruction being constructed +* +* @return The number of bytes for this instruction which is 1. +* +* @note None. +* +*****************************************************************************/ +static INLINE int XDmaPs_Instr_DMALD(char *DmaProg) +{ + /* + * DMALD encoding + * 7 6 5 4 3 2 1 0 + * 0 0 0 0 0 1 bs x + * + * Note: this driver doesn't support conditional load or store, + * so the bs bit is 0 and x bit is 0. + */ + *DmaProg = 0x04; + return 1; +} + +/****************************************************************************/ +/** +* +* Construction function for DMALP instruction. This function fills the program +* buffer with the constructed instruction. +* +* @param DmaProg is the DMA program buffer, it's the starting address +* for the instruction being constructed +* @param Lc is the Loop counter register, can either be 0 or 1. +* @param LoopIterations: the number of interations, LoopInterations - 1 +* will be encoded in the DMALP instruction. +* +* @return The number of bytes for this instruction which is 2. +* +* @note None. +* +*****************************************************************************/ +static INLINE int XDmaPs_Instr_DMALP(char *DmaProg, unsigned Lc, + unsigned LoopIterations) +{ + /* + * DMALP encoding + * 15 ... 8 7 6 5 4 3 2 1 0 + * | iter[7:0] |0 0 1 0 0 0 lc 0 + */ + *DmaProg = (u8)(0x20 | ((Lc & 1) << 1)); + *(DmaProg + 1) = (u8)(LoopIterations - 1); + return 2; +} + +/****************************************************************************/ +/** +* +* Construction function for DMALPEND instruction. This function fills the +* program buffer with the constructed instruction. +* +* @param DmaProg is the DMA program buffer, it's the starting address +* for the instruction being constructed +* @param BodyStart is the starting address of the loop body. It is used +* to calculate the bytes of backward jump. +* @param Lc is the Loop counter register, can either be 0 or 1. +* +* @return The number of bytes for this instruction which is 2. +* +* @note None. +* +*****************************************************************************/ +static INLINE int XDmaPs_Instr_DMALPEND(char *DmaProg, char *BodyStart, unsigned Lc) +{ + /* + * DMALPEND encoding + * 15 ... 8 7 6 5 4 3 2 1 0 + * | backward_jump[7:0] |0 0 1 nf 1 lc bs x + * + * lc: loop counter + * nf is for loop forever. The driver does not support loop forever, + * so nf is 1. + * The driver does not support conditional LPEND, so bs is 0, x is 0. + */ + *DmaProg = 0x38 | ((Lc & 1) << 2); + *(DmaProg + 1) = (u8)(DmaProg - BodyStart); + + return 2; +} + +/* + * Register number for the DMAMOV instruction + */ +#define XDMAPS_MOV_SAR 0x0 +#define XDMAPS_MOV_CCR 0x1 +#define XDMAPS_MOV_DAR 0x2 + +/****************************************************************************/ +/** +* +* Construction function for DMAMOV instruction. This function fills the +* program buffer with the constructed instruction. +* +* @param DmaProg is the DMA program buffer, it's the starting address +* for the instruction being constructed +* @param Rd is the register id, 0 for SAR, 1 for CCR, and 2 for DAR +* @param Imm is the 32-bit immediate number +* +* @return The number of bytes for this instruction which is 6. +* +* @note None. +* +*****************************************************************************/ +static INLINE int XDmaPs_Instr_DMAMOV(char *DmaProg, unsigned Rd, u32 Imm) +{ + /* + * DMAMOV encoding + * 15 4 3 2 1 10 ... 8 7 6 5 4 3 2 1 0 + * 0 0 0 0 0 |rd[2:0]|1 0 1 1 1 1 0 0 + * + * 47 ... 16 + * imm[32:0] + * + * rd: b000 for SAR, b001 CCR, b010 DAR + */ + *DmaProg = 0xBC; + *(DmaProg + 1) = Rd & 0x7; + // *((u32 *)(DmaProg + 2)) = Imm; + XDmaPs_Memcpy4(DmaProg + 2, (char *)&Imm); + + return 6; +} + +/****************************************************************************/ +/** +* +* Construction function for DMANOP instruction. This function fills the +* program buffer with the constructed instruction. +* +* @param DmaProg is the DMA program buffer, it's the starting address +* for the instruction being constructed +* @return The number of bytes for this instruction which is 1. +* +* @note None. +* +*****************************************************************************/ +static INLINE int XDmaPs_Instr_DMANOP(char *DmaProg) +{ + /* + * DMANOP encoding + * 7 6 5 4 3 2 1 0 + * 0 0 0 1 1 0 0 0 + */ + *DmaProg = 0x18; + return 1; +} + +/****************************************************************************/ +/** +* +* Construction function for DMARMB instruction. This function fills the +* program buffer with the constructed instruction. +* +* @param DmaProg is the DMA program buffer, it's the starting address +* for the instruction being constructed +* +* @return The number of bytes for this instruction which is 1. +* +* @note None. +* +*****************************************************************************/ +int XDmaPs_Instr_DMARMB(char *DmaProg) +{ + /* + * DMARMB encoding + * 7 6 5 4 3 2 1 0 + * 0 0 0 1 0 0 1 0 + */ + *DmaProg = 0x12; + return 1; +} + +/****************************************************************************/ +/** +* +* Construction function for DMASEV instruction. This function fills the +* program buffer with the constructed instruction. +* +* @param DmaProg is the DMA program buffer, it's the starting address +* for the instruction being constructed +* @param EventNumber is the Event number to signal. +* +* @return The number of bytes for this instruction which is 2. +* +* @note None. +* +*****************************************************************************/ +static INLINE int XDmaPs_Instr_DMASEV(char *DmaProg, unsigned int EventNumber) +{ + /* + * DMASEV encoding + * 15 4 3 2 1 10 9 8 7 6 5 4 3 2 1 0 + * |event[4:0]| 0 0 0 0 0 1 1 0 1 0 0 + */ + *DmaProg = 0x34; + *(DmaProg + 1) = (u8)(EventNumber << 3); + + return 2; +} + + +/****************************************************************************/ +/** +* +* Construction function for DMAST instruction. This function fills the +* program buffer with the constructed instruction. +* +* @param DmaProg is the DMA program buffer, it's the starting address +* for the instruction being constructed +* +* @return The number of bytes for this instruction which is 1. +* +* @note None. +* +*****************************************************************************/ +static INLINE int XDmaPs_Instr_DMAST(char *DmaProg) +{ + /* + * DMAST encoding + * 7 6 5 4 3 2 1 0 + * 0 0 0 0 1 0 bs x + * + * Note: this driver doesn't support conditional load or store, + * so the bs bit is 0 and x bit is 0. + */ + *DmaProg = 0x08; + return 1; +} + + +/****************************************************************************/ +/** +* +* Construction function for DMAWMB instruction. This function fills the +* program buffer with the constructed instruction. +* +* @param DmaProg is the DMA program buffer, it's the starting address +* for the instruction being constructed +* +* @return The number of bytes for this instruction which is 1. +* +* @note None. +* +*****************************************************************************/ +int XDmaPs_Instr_DMAWMB(char *DmaProg) +{ + /* + * DMAWMB encoding + * 7 6 5 4 3 2 1 0 + * 0 0 0 1 0 0 1 0 + */ + *DmaProg = 0x13; + return 1; +} + +/****************************************************************************/ +/** +* +* Conversion function from the endian swap size to the bit encoding of the CCR +* +* @param EndianSwapSize is the endian swap size, in terms of bits, it +* could be 8, 16, 32, 64, or 128(We are using DMA assembly syntax) +* +* @return The endian swap size bit encoding for the CCR. +* +* @note None. +* +*****************************************************************************/ +static INLINE unsigned XDmaPs_ToEndianSwapSizeBits(unsigned int EndianSwapSize) +{ + switch (EndianSwapSize) { + case 0: + case 8: + return 0; + case 16: + return 1; + case 32: + return 2; + case 64: + return 3; + case 128: + return 4; + default: + return 0; + } + +} + +/****************************************************************************/ +/** +* +* Conversion function from the burst size to the bit encoding of the CCR +* +* @param BurstSize is the burst size. It's the data width. +* In terms of bytes, it could be 1, 2, 4, 8, 16, 32, 64, or 128. +* It must be no larger than the bus width. +* (We are using DMA assembly syntax.) +* +* @note None. +* +*****************************************************************************/ +static INLINE unsigned XDmaPs_ToBurstSizeBits(unsigned BurstSize) +{ + switch (BurstSize) { + case 1: + return 0; + case 2: + return 1; + case 4: + return 2; + case 8: + return 3; + case 16: + return 4; + case 32: + return 5; + case 64: + return 6; + case 128: + return 7; + default: + return 0; + } +} + + +/****************************************************************************/ +/** +* +* Conversion function from PL330 bus transfer descriptors to CCR value. All the +* values passed to the functions are in terms of assembly languages, not in +* terms of the register bit encoding. +* +* @param ChanCtrl is the Instance of XDmaPs_ChanCtrl. +* +* @return The 32-bit CCR value. +* +* @note None. +* +*****************************************************************************/ +u32 XDmaPs_ToCCRValue(XDmaPs_ChanCtrl *ChanCtrl) +{ + /* + * Channel Control Register encoding + * [31:28] - endian_swap_size + * [27:25] - dst_cache_ctrl + * [24:22] - dst_prot_ctrl + * [21:18] - dst_burst_len + * [17:15] - dst_burst_size + * [14] - dst_inc + * [13:11] - src_cache_ctrl + * [10:8] - src_prot_ctrl + * [7:4] - src_burst_len + * [3:1] - src_burst_size + * [0] - src_inc + */ + + unsigned es = + XDmaPs_ToEndianSwapSizeBits(ChanCtrl->EndianSwapSize); + + unsigned dst_burst_size = + XDmaPs_ToBurstSizeBits(ChanCtrl->DstBurstSize); + unsigned dst_burst_len = (ChanCtrl->DstBurstLen - 1) & 0x0F; + unsigned dst_cache_ctrl = (ChanCtrl->DstCacheCtrl & 0x03) + | ((ChanCtrl->DstCacheCtrl & 0x08) >> 1); + unsigned dst_prot_ctrl = ChanCtrl->DstProtCtrl & 0x07; + unsigned dst_inc_bit = ChanCtrl->DstInc & 1; + + unsigned src_burst_size = + XDmaPs_ToBurstSizeBits(ChanCtrl->SrcBurstSize); + unsigned src_burst_len = (ChanCtrl->SrcBurstLen - 1) & 0x0F; + unsigned src_cache_ctrl = (ChanCtrl->SrcCacheCtrl & 0x03) + | ((ChanCtrl->SrcCacheCtrl & 0x08) >> 1); + unsigned src_prot_ctrl = ChanCtrl->SrcProtCtrl & 0x07; + unsigned src_inc_bit = ChanCtrl->SrcInc & 1; + + u32 ccr_value = (es << 28) + | (dst_cache_ctrl << 25) + | (dst_prot_ctrl << 22) + | (dst_burst_len << 18) + | (dst_burst_size << 15) + | (dst_inc_bit << 14) + | (src_cache_ctrl << 11) + | (src_prot_ctrl << 8) + | (src_burst_len << 4) + | (src_burst_size << 1) + | (src_inc_bit); + + return ccr_value; +} + +/****************************************************************************/ +/** +* Construct a loop with only DMALD and DMAST as the body using loop counter 0. +* The function also makes sure the loop body and the lpend is in the same +* cache line. +* +* @param DmaProgStart is the very start address of the DMA program. +* This is used to calculate whether the loop is in a cache line. +* @param CacheLength is the icache line length, in terms of bytes. +* If it's zero, the performance enhancement feature will be +* turned off. +* @param DmaProgLoopStart The starting address of the loop (DMALP). +* @param LoopCount The inner loop count. Loop count - 1 will be used to +* initialize the loop counter. +* +* @return The number of bytes the loop has. +* +* @note None. +* +*****************************************************************************/ +int XDmaPs_ConstructSingleLoop(char *DmaProgStart, + int CacheLength, + char *DmaProgLoopStart, + int LoopCount) +{ + int CacheStartOffset; + int CacheEndOffset; + int NumNops; + char *DmaProgBuf = DmaProgLoopStart; + + DmaProgBuf += XDmaPs_Instr_DMALP(DmaProgBuf, 0, LoopCount); + + if (CacheLength > 0) { + /* + * the CacheLength > 0 switch is ued to turn on/off nop + * insertion + */ + CacheStartOffset = DmaProgBuf - DmaProgStart; + CacheEndOffset = CacheStartOffset + 3; + + /* + * check whether the body and lpend fit in one cache line + */ + if (CacheStartOffset / CacheLength + != CacheEndOffset / CacheLength) { + /* insert the nops */ + NumNops = CacheLength + - CacheStartOffset % CacheLength; + while (NumNops--) { + DmaProgBuf += + XDmaPs_Instr_DMANOP(DmaProgBuf); + } + } + } + + DmaProgBuf += XDmaPs_Instr_DMALD(DmaProgBuf); + DmaProgBuf += XDmaPs_Instr_DMAST(DmaProgBuf); + DmaProgBuf += XDmaPs_Instr_DMALPEND(DmaProgBuf, + DmaProgBuf - 2, 0); + + return DmaProgBuf - DmaProgLoopStart; +} + +/****************************************************************************/ +/** +* Construct a nested loop with only DMALD and DMAST in the inner loop body. +* It uses loop counter 1 for the outer loop and loop counter 0 for the +* inner loop. +* +* @param DmaProgStart is the very start address of the DMA program. +* This is used to calculate whether the loop is in a cache line. +* @param CacheLength is the icache line length, in terms of bytes. +* If it's zero, the performance enhancement feature will be +* turned off. +* @param DmaProgLoopStart The starting address of the loop (DMALP). +* @param LoopCountOuter The outer loop count. Loop count - 1 will be +* used to initialize the loop counter. +* @param LoopCountInner The inner loop count. Loop count - 1 will be +* used to initialize the loop counter. +* +* @return The number byes the nested loop program has. +* +* @note None. +* +*****************************************************************************/ +int XDmaPs_ConstructNestedLoop(char *DmaProgStart, + int CacheLength, + char *DmaProgLoopStart, + unsigned int LoopCountOuter, + unsigned int LoopCountInner) +{ + int CacheStartOffset; + int CacheEndOffset; + int NumNops; + char *InnerLoopStart; + char *DmaProgBuf = DmaProgLoopStart; + + DmaProgBuf += XDmaPs_Instr_DMALP(DmaProgBuf, 1, LoopCountOuter); + InnerLoopStart = DmaProgBuf; + + if (CacheLength > 0) { + /* + * the CacheLength > 0 switch is ued to turn on/off nop + * insertion + */ + if (CacheLength < 8) { + /* + * if the cache line is too small to fit both loops + * just align the inner loop + */ + DmaProgBuf += + XDmaPs_ConstructSingleLoop(DmaProgStart, + CacheLength, + DmaProgBuf, + LoopCountInner); + /* outer loop end */ + DmaProgBuf += + XDmaPs_Instr_DMALPEND(DmaProgBuf, + InnerLoopStart, + 1); + + /* + * the nested loop is constructed for + * smaller cache line + */ + return DmaProgBuf - DmaProgLoopStart; + } + + /* + * Now let's handle the case where a cache line can + * fit the nested loops. + */ + CacheStartOffset = DmaProgBuf - DmaProgStart; + CacheEndOffset = CacheStartOffset + 7; + + /* + * check whether the body and lpend fit in one cache line + */ + if (CacheStartOffset / CacheLength + != CacheEndOffset / CacheLength) { + /* insert the nops */ + NumNops = CacheLength + - CacheStartOffset % CacheLength; + while (NumNops--) { + DmaProgBuf += + XDmaPs_Instr_DMANOP(DmaProgBuf); + } + } + } + + /* insert the inner DMALP */ + DmaProgBuf += XDmaPs_Instr_DMALP(DmaProgBuf, 0, LoopCountInner); + + /* DMALD and DMAST instructions */ + DmaProgBuf += XDmaPs_Instr_DMALD(DmaProgBuf); + DmaProgBuf += XDmaPs_Instr_DMAST(DmaProgBuf); + + /* inner DMALPEND */ + DmaProgBuf += XDmaPs_Instr_DMALPEND(DmaProgBuf, + DmaProgBuf - 2, 0); + /* outer DMALPEND */ + DmaProgBuf += XDmaPs_Instr_DMALPEND(DmaProgBuf, + InnerLoopStart, 1); + + /* return the number of bytes */ + return DmaProgBuf - DmaProgLoopStart; +} + +/* + * [31:28] endian_swap_size b0000 + * [27:25] dst_cache_ctrl b000 + * [24:22] dst_prot_ctrl b000 + * [21:18] dst_burst_len b0000 + * [17:15] dst_burst_size b000 + * [14] dst_inc b0 + * [27:25] src_cache_ctrl b000 + * [24:22] src_prot_ctrl b000 + * [21:18] src_burst_len b0000 + * [17:15] src_burst_size b000 + * [14] src_inc b0 + */ +#define XDMAPS_CCR_SINGLE_BYTE (0x0) +#define XDMAPS_CCR_M2M_SINGLE_BYTE ((0x1 << 14) | 0x1) + + +/****************************************************************************/ +/** +* +* Construct the DMA program based on the descriptions of the DMA transfer. +* The function handles memory to memory DMA transfers. +* It also handles unalgined head and small amount of residue tail. +* +* @param Channel DMA channel number +* @param Cmd is the DMA command. +* @param CacheLength is the icache line length, in terms of bytes. +* If it's zero, the performance enhancement feature will be +* turned off. +* +* @returns The number of bytes for the program. +* +* @note None. +* +*****************************************************************************/ +static int XDmaPs_BuildDmaProg(unsigned Channel, XDmaPs_Cmd *Cmd, + unsigned CacheLength) +{ + /* + * unpack arguments + */ + char *DmaProgBuf = (char *)Cmd->GeneratedDmaProg; + unsigned DevChan = Channel; + unsigned long DmaLength = Cmd->BD.Length; + u32 SrcAddr = Cmd->BD.SrcAddr; + + unsigned SrcInc = Cmd->ChanCtrl.SrcInc; + u32 DstAddr = Cmd->BD.DstAddr; + unsigned DstInc = Cmd->ChanCtrl.DstInc; + + char *DmaProgStart = DmaProgBuf; + + unsigned int BurstBytes; + unsigned int LoopCount; + unsigned int LoopCount1 = 0; + unsigned int LoopResidue = 0; + unsigned int TailBytes; + unsigned int TailWords; + int DmaProgBytes; + u32 CCRValue; + unsigned int Unaligned; + unsigned int UnalignedCount; + unsigned int MemBurstSize = 1; + u32 MemAddr = 0; + unsigned int Index; + unsigned int SrcUnaligned = 0; + unsigned int DstUnaligned = 0; + + XDmaPs_ChanCtrl *ChanCtrl; + XDmaPs_ChanCtrl WordChanCtrl; + static XDmaPs_ChanCtrl Mem2MemByteCC; + + Mem2MemByteCC.EndianSwapSize = 0; + Mem2MemByteCC.DstCacheCtrl = 0; + Mem2MemByteCC.DstProtCtrl = 0; + Mem2MemByteCC.DstBurstLen = 1; + Mem2MemByteCC.DstBurstSize = 1; + Mem2MemByteCC.DstInc = 1; + Mem2MemByteCC.SrcCacheCtrl = 0; + Mem2MemByteCC.SrcProtCtrl = 0; + Mem2MemByteCC.SrcBurstLen = 1; + Mem2MemByteCC.SrcBurstSize = 1; + Mem2MemByteCC.SrcInc = 1; + + ChanCtrl = &Cmd->ChanCtrl; + + /* insert DMAMOV for SAR and DAR */ + DmaProgBuf += XDmaPs_Instr_DMAMOV(DmaProgBuf, + XDMAPS_MOV_SAR, + SrcAddr); + DmaProgBuf += XDmaPs_Instr_DMAMOV(DmaProgBuf, + XDMAPS_MOV_DAR, + DstAddr); + + + if (ChanCtrl->SrcInc) + SrcUnaligned = SrcAddr % ChanCtrl->SrcBurstSize; + + if (ChanCtrl->DstInc) + DstUnaligned = DstAddr % ChanCtrl->DstBurstSize; + + if ((SrcUnaligned && DstInc) || (DstUnaligned && SrcInc)) { + ChanCtrl = &Mem2MemByteCC; + } + + if (ChanCtrl->SrcInc) { + MemBurstSize = ChanCtrl->SrcBurstSize; + MemAddr = SrcAddr; + + } else if (ChanCtrl->DstInc) { + MemBurstSize = ChanCtrl->DstBurstSize; + MemAddr = DstAddr; + } + + /* check whether the head is aligned or not */ + Unaligned = MemAddr % MemBurstSize; + + if (Unaligned) { + /* if head is unaligned, transfer head in bytes */ + UnalignedCount = MemBurstSize - Unaligned; + CCRValue = XDMAPS_CCR_SINGLE_BYTE + | (SrcInc & 1) + | ((DstInc & 1) << 14); + + DmaProgBuf += XDmaPs_Instr_DMAMOV(DmaProgBuf, + XDMAPS_MOV_CCR, + CCRValue); + + for (Index = 0; Index < UnalignedCount; Index++) { + DmaProgBuf += XDmaPs_Instr_DMALD(DmaProgBuf); + DmaProgBuf += XDmaPs_Instr_DMAST(DmaProgBuf); + } + + DmaLength -= UnalignedCount; + } + + /* now the burst transfer part */ + CCRValue = XDmaPs_ToCCRValue(ChanCtrl); + DmaProgBuf += XDmaPs_Instr_DMAMOV(DmaProgBuf, + XDMAPS_MOV_CCR, + CCRValue); + + BurstBytes = ChanCtrl->SrcBurstSize * ChanCtrl->SrcBurstLen; + + LoopCount = DmaLength / BurstBytes; + TailBytes = DmaLength % BurstBytes; + + /* + * the loop count register is 8-bit wide, so if we need + * a larger loop, we need to have nested loops + */ + if (LoopCount > 256) { + LoopCount1 = LoopCount / 256; + if (LoopCount1 > 256) { + xil_printf("DMA operation cannot fit in a 2-level " + "loop for channel %d, please reduce the " + "DMA length or increase the burst size or " + "length", + Channel); + return 0; + } + LoopResidue = LoopCount % 256; + + if (LoopCount1 > 1) + DmaProgBuf += + XDmaPs_ConstructNestedLoop(DmaProgStart, + CacheLength, + DmaProgBuf, + LoopCount1, + 256); + else + DmaProgBuf += + XDmaPs_ConstructSingleLoop(DmaProgStart, + CacheLength, + DmaProgBuf, + 256); + + /* there will be some that cannot be covered by + * nested loops + */ + LoopCount = LoopResidue; + } + + if (LoopCount > 0) { + DmaProgBuf += XDmaPs_ConstructSingleLoop(DmaProgStart, + CacheLength, + DmaProgBuf, + LoopCount); + } + + if (TailBytes) { + /* handle the tail */ + TailWords = TailBytes / MemBurstSize; + TailBytes = TailBytes % MemBurstSize; + + if (TailWords) { + WordChanCtrl = *ChanCtrl; + /* + * if we can transfer the tail in words, we will + * transfer words as much as possible + */ + WordChanCtrl.SrcBurstSize = MemBurstSize; + WordChanCtrl.SrcBurstLen = 1; + WordChanCtrl.DstBurstSize = MemBurstSize; + WordChanCtrl.DstBurstLen = 1; + + + /* + * the burst length is 1 + */ + CCRValue = XDmaPs_ToCCRValue(&WordChanCtrl); + + DmaProgBuf += + XDmaPs_Instr_DMAMOV(DmaProgBuf, + XDMAPS_MOV_CCR, + CCRValue); + DmaProgBuf += + XDmaPs_ConstructSingleLoop(DmaProgStart, + CacheLength, + DmaProgBuf, + TailWords); + + } + + if (TailBytes) { + /* + * for the rest, we'll tranfer in bytes + */ + /* + * So far just to be safe, the tail bytes + * are transfered in a loop. We can optimize a little + * to perform a burst. + */ + CCRValue = XDMAPS_CCR_SINGLE_BYTE + | (SrcInc & 1) + | ((DstInc & 1) << 14); + + DmaProgBuf += + XDmaPs_Instr_DMAMOV(DmaProgBuf, + XDMAPS_MOV_CCR, + CCRValue); + + DmaProgBuf += + XDmaPs_ConstructSingleLoop(DmaProgStart, + CacheLength, + DmaProgBuf, + TailBytes); + + } + } + + DmaProgBuf += XDmaPs_Instr_DMASEV(DmaProgBuf, DevChan); + DmaProgBuf += XDmaPs_Instr_DMAEND(DmaProgBuf); + + DmaProgBytes = DmaProgBuf - DmaProgStart; + + Xil_DCacheFlushRange((u32)DmaProgStart, DmaProgBytes); + + return DmaProgBytes; + +} + + +/****************************************************************************/ +/** +* +* Generate a DMA program based for the DMA command, the buffer will be pointed +* by the GeneratedDmaProg field of the command. +* +* @param InstPtr is then DMA instance. +* @param Channel is the DMA channel number. +* @param Cmd is the DMA command. +* +* @return - XST_SUCCESS on success. +* - XST_FAILURE if it fails +* +* @note None. +* +*****************************************************************************/ +int XDmaPs_GenDmaProg(XDmaPs *InstPtr, unsigned int Channel, XDmaPs_Cmd *Cmd) +{ + void *Buf; + int ProgLen; + XDmaPs_ChannelData *ChanData; + XDmaPs_ChanCtrl *ChanCtrl; + + Xil_AssertNonvoid(InstPtr != NULL); + Xil_AssertNonvoid(Cmd != NULL); + + + if (Channel > XDMAPS_CHANNELS_PER_DEV) + return XST_FAILURE; + + ChanData = InstPtr->Chans + Channel; + ChanCtrl = &Cmd->ChanCtrl; + + if (ChanCtrl->SrcBurstSize * ChanCtrl->SrcBurstLen + != ChanCtrl->DstBurstSize * ChanCtrl->DstBurstLen) { + return XST_FAILURE; + } + + + /* + * unaligned fixed address is not supported + */ + if (!ChanCtrl->SrcInc && Cmd->BD.SrcAddr % ChanCtrl->SrcBurstSize) { + return XST_FAILURE; + } + + if (!ChanCtrl->DstInc && Cmd->BD.DstAddr % ChanCtrl->DstBurstSize) { + return XST_FAILURE; + } + + Buf = XDmaPs_BufPool_Allocate(ChanData->ProgBufPool); + if (Buf == NULL) { + return XST_FAILURE; + } + + Cmd->GeneratedDmaProg = Buf; + ProgLen = XDmaPs_BuildDmaProg(Channel, Cmd, + InstPtr->CacheLength); + Cmd->GeneratedDmaProgLength = ProgLen; + + +#ifdef XDMAPS_DEBUG + XDmaPs_Print_DmaProg(Cmd); +#endif + + if (ProgLen <= 0) { + /* something wrong, release the buffer */ + XDmaPs_BufPool_Free(ChanData->ProgBufPool, Buf); + Cmd->GeneratedDmaProgLength = 0; + Cmd->GeneratedDmaProg = NULL; + return XST_FAILURE; + } + + return XST_SUCCESS; +} + + +/****************************************************************************/ +/** + * Free the DMA program buffer that is pointed by the GeneratedDmaProg field + * of the command. + * + * @param InstPtr is then DMA instance. + * @param Channel is the DMA channel number. + * @param Cmd is the DMA command. + * + * @return XST_SUCCESS on success. + * XST_FAILURE if there is any error. + * + * @note None. + * + ****************************************************************************/ +int XDmaPs_FreeDmaProg(XDmaPs *InstPtr, unsigned int Channel, XDmaPs_Cmd *Cmd) +{ + + void *Buf; + XDmaPs_ChannelData *ChanData; + + Xil_AssertNonvoid(InstPtr != NULL); + Xil_AssertNonvoid(Cmd != NULL); + + if (Channel > XDMAPS_CHANNELS_PER_DEV) + return XST_FAILURE; + + Buf = (void *)Cmd->GeneratedDmaProg; + ChanData = InstPtr->Chans + Channel; + + if (Buf) { + XDmaPs_BufPool_Free(ChanData->ProgBufPool, Buf); + Cmd->GeneratedDmaProg = 0; + Cmd->GeneratedDmaProgLength = 0; + } + + return XST_SUCCESS; +} + + +/****************************************************************************/ +/** +* +* Start a DMA command. The command can only be invoked when the channel +* is idle. The driver takes the command, generates DMA program if needed, +* then pass the program to DMAC to execute. +* +* @param InstPtr is then DMA instance. +* @param Channel is the DMA channel number. +* @param Cmd is the DMA command. +* @param HoldDmaProg is tag indicating whether the driver can release +* the allocated DMA buffer or not. If a user wants to examine the +* generated DMA program, the flag should be set to 1. After the +* DMA program is finished, a user needs to explicity free the +* buffer. +* +* @return +* - XST_SUCCESS on success +* - XST_DEVICE_BUSY if DMA is busy +* - XST_FAILURE on other failures +* +* @note None. +* +****************************************************************************/ +int XDmaPs_Start(XDmaPs *InstPtr, unsigned int Channel, + XDmaPs_Cmd *Cmd, + int HoldDmaProg) +{ + int Status; + u32 DmaProg = 0; + u32 Inten; + + Xil_AssertNonvoid(InstPtr != NULL); + Xil_AssertNonvoid(Cmd != NULL); + + + Cmd->DmaStatus = XST_FAILURE; + + if (XDmaPs_IsActive(InstPtr, Channel)) + return XST_DEVICE_BUSY; + + if (!Cmd->UserDmaProg && !Cmd->GeneratedDmaProg) { + Status = XDmaPs_GenDmaProg(InstPtr, Channel, Cmd); + if (Status) + return XST_FAILURE; + } + + InstPtr->Chans[Channel].HoldDmaProg = HoldDmaProg; + + if (Cmd->UserDmaProg) + DmaProg = (u32)Cmd->UserDmaProg; + else if (Cmd->GeneratedDmaProg) + DmaProg = (u32)Cmd->GeneratedDmaProg; + + if (DmaProg) { + /* enable the interrupt */ + Inten = XDmaPs_ReadReg(InstPtr->Config.BaseAddress, + XDMAPS_INTEN_OFFSET); + Inten |= 0x01 << Channel; /* set the correpsonding bit */ + XDmaPs_WriteReg(InstPtr->Config.BaseAddress, + XDMAPS_INTEN_OFFSET, + Inten); + Inten = XDmaPs_ReadReg(InstPtr->Config.BaseAddress, + XDMAPS_INTEN_OFFSET); + + InstPtr->Chans[Channel].DmaCmdToHw = Cmd; + + if (Cmd->ChanCtrl.SrcInc) { + Xil_DCacheFlushRange(Cmd->BD.SrcAddr, Cmd->BD.Length); + } + if (Cmd->ChanCtrl.DstInc) { + Xil_DCacheInvalidateRange(Cmd->BD.DstAddr, + Cmd->BD.Length); + } + + Status = XDmaPs_Exec_DMAGO(InstPtr->Config.BaseAddress, + Channel, DmaProg); + } + else { + InstPtr->Chans[Channel].DmaCmdToHw = NULL; + Status = XST_FAILURE; + } + + return Status; +} + +/****************************************************************************/ +/** +* +* Checks whether the DMA channel is active or idle. +* +* @param InstPtr is the DMA instance. +* @param Channel is the DMA channel number. +* +* @return 0: if the channel is idle +* 1: otherwise +* +* @note None. +* +*****************************************************************************/ +int XDmaPs_IsActive(XDmaPs *InstPtr, unsigned int Channel) +{ + Xil_AssertNonvoid(InstPtr != NULL); + + /* Need to assert Channel is in range */ + if (Channel > XDMAPS_CHANNELS_PER_DEV) + return 0; + + return InstPtr->Chans[Channel].DmaCmdToHw != NULL; +} + + + +/****************************************************************************/ +/** +* +* Allocate a buffer of the DMA program buffer from the pool. +* +* @param Pool the DMA program pool. +* +* @return The allocated buffer, NULL if there is any error. +* +* @note None. +* +*****************************************************************************/ +static void *XDmaPs_BufPool_Allocate(XDmaPs_ProgBuf *Pool) +{ + int Index; + + Xil_AssertNonvoid(Pool != NULL); + + for (Index = 0; Index < XDMAPS_MAX_CHAN_BUFS; Index++) { + if (!Pool[Index].Allocated) { + Pool[Index].Allocated = 1; + return Pool[Index].Buf; + } + } + + return NULL; + +} + +/*****************************************************************************/ +/** +* +* Driver done interrupt service routine for channel 0. We need this done ISR +* mainly because the driver needs to release the DMA program buffer. +* This is the one that connects the GIC +* +* @param InstPtr is the DMA instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XDmaPs_DoneISR_0(XDmaPs *InstPtr) +{ + XDmaPs_DoneISR_n(InstPtr, 0); +} + +/*****************************************************************************/ +/** +* +* Driver done interrupt service routine for channel 1. We need this done ISR +* mainly because the driver needs to release the DMA program buffer. +* This is the one that connects the GIC +* +* @param InstPtr is the DMA instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XDmaPs_DoneISR_1(XDmaPs *InstPtr) +{ + XDmaPs_DoneISR_n(InstPtr, 1); +} + +/*****************************************************************************/ +/** +* +* Driver done interrupt service routine for channel 2. We need this done ISR +* mainly because the driver needs to release the DMA program buffer. +* This is the one that connects the GIC +* +* @param InstPtr is the DMA instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XDmaPs_DoneISR_2(XDmaPs *InstPtr) +{ + XDmaPs_DoneISR_n(InstPtr, 2); +} + +/*****************************************************************************/ +/** +* +* Driver done interrupt service routine for channel 3. We need this done ISR +* mainly because the driver needs to release the DMA program buffer. +* This is the one that connects the GIC +* +* @param InstPtr is the DMA instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XDmaPs_DoneISR_3(XDmaPs *InstPtr) +{ + XDmaPs_DoneISR_n(InstPtr, 3); +} + +/*****************************************************************************/ +/** +* +* Driver done interrupt service routine for channel 4. We need this done ISR +* mainly because the driver needs to release the DMA program buffer. +* This is the one that connects the GIC +* +* @param InstPtr is the DMA instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XDmaPs_DoneISR_4(XDmaPs *InstPtr) +{ + XDmaPs_DoneISR_n(InstPtr, 4); +} + +/*****************************************************************************/ +/** +* +* Driver done interrupt service routine for channel 5. We need this done ISR +* mainly because the driver needs to release the DMA program buffer. +* This is the one that connects the GIC +* +* @param InstPtr is the DMA instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XDmaPs_DoneISR_5(XDmaPs *InstPtr) +{ + XDmaPs_DoneISR_n(InstPtr, 5); +} + +/*****************************************************************************/ +/** +* +* Driver done interrupt service routine for channel 6. We need this done ISR +* mainly because the driver needs to release the DMA program buffer. +* This is the one that connects the GIC +* +* @param InstPtr is the DMA instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XDmaPs_DoneISR_6(XDmaPs *InstPtr) +{ + XDmaPs_DoneISR_n(InstPtr, 6); +} + +/*****************************************************************************/ +/** +* +* Driver done interrupt service routine for channel 7. We need this done ISR +* mainly because the driver needs to release the DMA program buffer. +* This is the one that connects the GIC +* +* @param InstPtr is the DMA instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XDmaPs_DoneISR_7(XDmaPs *InstPtr) +{ + XDmaPs_DoneISR_n(InstPtr, 7); +} + +#ifndef XDMAPS_MAX_WAIT +#define XDMAPS_MAX_WAIT 4000 +#endif + +/****************************************************************************/ +/** +* Use the debug registers to kill the DMA thread. +* +* @param BaseAddr is DMA device base address. +* @param Channel is the DMA channel number. +* @param Thread is Debug thread encoding. +* 0: DMA manager thread, 1: DMA channel. +* +* @return 0 on success, -1 on time out +* +* @note None. +* +*****************************************************************************/ +static int XDmaPs_Exec_DMAKILL(u32 BaseAddr, + unsigned int Channel, + unsigned int Thread) +{ + u32 DbgInst0; + int WaitCount; + + DbgInst0 = XDmaPs_DBGINST0(0, 0x01, Channel, Thread); + + /* wait while debug status is busy */ + WaitCount = 0; + while ((XDmaPs_ReadReg(BaseAddr, XDMAPS_DBGSTATUS_OFFSET) + & XDMAPS_DBGSTATUS_BUSY) + && (WaitCount < XDMAPS_MAX_WAIT)) + WaitCount++; + + if (WaitCount >= XDMAPS_MAX_WAIT) { + /* wait time out */ + xil_printf("PL330 device at %x debug status busy time out\n", + BaseAddr); + + return -1; + } + + /* write debug instruction 0 */ + XDmaPs_WriteReg(BaseAddr, XDMAPS_DBGINST0_OFFSET, DbgInst0); + + XDmaPs_WriteReg(BaseAddr, XDMAPS_DBGINST1_OFFSET, 0); + + + /* run the command in DbgInst0 and DbgInst1 */ + XDmaPs_WriteReg(BaseAddr, XDMAPS_DBGCMD_OFFSET, 0); + + return 0; +} + +/****************************************************************************/ +/** +* +* +* Free a buffer of the DMA program buffer. +* @param Pool the DMA program pool. +* @param Buf the DMA program buffer to be release. +* +* @return None +* +* @note None. +* +*****************************************************************************/ +static void XDmaPs_BufPool_Free(XDmaPs_ProgBuf *Pool, void *Buf) +{ + int Index; + Xil_AssertVoid(Pool != NULL); + + for (Index = 0; Index < XDMAPS_MAX_CHAN_BUFS; Index++) { + if (Pool[Index].Buf == Buf) { + if (Pool[Index].Allocated) { + Pool[Index].Allocated = 0; + } + } + } +} + +/*****************************************************************************/ +/** +* XDmaPs_Exec_DMAGO - Execute the DMAGO to start a channel. +* +* @param BaseAddr PL330 device base address +* @param Channel Channel number for the device +* @param DmaProg DMA program starting address, this should be DMA address +* +* @return 0 on success, -1 on time out +* +* @note None. +* +****************************************************************************/ +static int XDmaPs_Exec_DMAGO(u32 BaseAddr, unsigned int Channel, u32 DmaProg) +{ + char DmaGoProg[8]; + u32 DbgInst0; + u32 DbgInst1; + + int WaitCount; + + XDmaPs_Instr_DMAGO(DmaGoProg, Channel, DmaProg, 0); + + DbgInst0 = XDmaPs_DBGINST0(*(DmaGoProg + 1), *DmaGoProg, 0, 0); + DbgInst1 = (u32)DmaProg; + + /* wait while debug status is busy */ + WaitCount = 0; + while ((XDmaPs_ReadReg(BaseAddr, XDMAPS_DBGSTATUS_OFFSET) + & XDMAPS_DBGSTATUS_BUSY) + && (WaitCount < XDMAPS_MAX_WAIT)) { + + WaitCount++; + } + + if (WaitCount >= XDMAPS_MAX_WAIT) { + xil_printf("PL330 device at %x debug status busy time out\r\n", + BaseAddr); + return -1; + } + + /* write debug instruction 0 */ + XDmaPs_WriteReg(BaseAddr, XDMAPS_DBGINST0_OFFSET, DbgInst0); + /* write debug instruction 1 */ + XDmaPs_WriteReg(BaseAddr, XDMAPS_DBGINST1_OFFSET, DbgInst1); + + + /* wait while the DMA Manager is busy */ + WaitCount = 0; + while ((XDmaPs_ReadReg(BaseAddr, + XDMAPS_DS_OFFSET) & XDMAPS_DS_DMA_STATUS) + != XDMAPS_DS_DMA_STATUS_STOPPED + && WaitCount <= XDMAPS_MAX_WAIT) { + WaitCount++; + } + + if (WaitCount >= XDMAPS_MAX_WAIT) { + xil_printf("PL330 device at %x debug status busy time out\r\n", + BaseAddr); + return -1; + } + + /* run the command in DbgInst0 and DbgInst1 */ + XDmaPs_WriteReg(BaseAddr, XDMAPS_DBGCMD_OFFSET, 0); + + return 0; +} + + +/****************************************************************************/ +/** +* +* It's the generic Done ISR. +* @param InstPtr is the DMA instance. +* @param Channel is the DMA channel numer. +* +* @return None.* +* +* @note None. +* +*****************************************************************************/ +static void XDmaPs_DoneISR_n(XDmaPs *InstPtr, unsigned Channel) +{ + + void *DmaProgBuf; + XDmaPs_ChannelData *ChanData; + XDmaPs_Cmd *DmaCmd; + //u32 Value; + + ChanData = InstPtr->Chans + Channel; + + /*Value = XDmaPs_ReadReg(InstPtr->Config.BaseAddress, + XDMAPS_INTSTATUS_OFFSET);*/ + + /* clear the interrupt status */ + XDmaPs_WriteReg(InstPtr->Config.BaseAddress, + XDMAPS_INTCLR_OFFSET, + 1 << ChanData->ChanId); + + /*Value = XDmaPs_ReadReg(InstPtr->Config.BaseAddress, + XDMAPS_INTSTATUS_OFFSET);*/ + + + DmaCmd = ChanData->DmaCmdToHw; + if (DmaCmd) { + if (!ChanData->HoldDmaProg) { + DmaProgBuf = (void *)DmaCmd->GeneratedDmaProg; + if (DmaProgBuf) + XDmaPs_BufPool_Free(ChanData->ProgBufPool, + DmaProgBuf); + DmaCmd->GeneratedDmaProg = NULL; + } + + DmaCmd->DmaStatus = 0; + ChanData->DmaCmdToHw = NULL; + ChanData->DmaCmdFromHw = DmaCmd; + + if (ChanData->DoneHandler) + ChanData->DoneHandler(Channel, DmaCmd, + ChanData->DoneRef); + } + +} + + +/****************************************************************************/ +/** +* Prints the content of the buffer in bytes +* @param Buf is the buffer. +* @param Length is the length of the DMA program. +* +* @return None. +* +* @note None. +****************************************************************************/ +static void XDmaPs_Print_DmaProgBuf(char *Buf, int Length) +{ + int Index; + for (Index = 0; Index < Length; Index++) + xil_printf("[%x] %x\r\n", Index, Buf[Index]); + +} +/****************************************************************************/ +/** +* Print the Dma Prog Contents. +* +* @param Cmd is the command buffer. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ + void XDmaPs_Print_DmaProg(XDmaPs_Cmd *Cmd) +{ + if (Cmd->GeneratedDmaProg && Cmd->GeneratedDmaProgLength) { + xil_printf("Generated DMA program (%d):\r\n", + Cmd->GeneratedDmaProgLength); + XDmaPs_Print_DmaProgBuf((char *)Cmd->GeneratedDmaProg, + Cmd->GeneratedDmaProgLength); + } + + if (Cmd->UserDmaProg && Cmd->UserDmaProgLength) { + xil_printf("User defined DMA program (%d):\r\n", + Cmd->UserDmaProgLength); + XDmaPs_Print_DmaProgBuf((char *)Cmd->UserDmaProg, + Cmd->UserDmaProgLength); + } +} + + +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/dmaps_v2_4/src/xdmaps.h b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/dmaps_v2_4/src/xdmaps.h new file mode 100644 index 0000000..73e2b1e --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/dmaps_v2_4/src/xdmaps.h @@ -0,0 +1,349 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xdmaps.h +* @addtogroup dmaps_v2_4 +* @{ +* @details +* +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  	Date     Changes
+* ----- ------ -------- ----------------------------------------------
+* 1.00	hbm    08/19/10 First Release
+* 1.01a nm     12/20/12 Added definition XDMAPS_CHANNELS_PER_DEV which specifies
+*		        the maximum number of channels.
+*		        Replaced the usage of XPAR_XDMAPS_CHANNELS_PER_DEV
+*                       with XDMAPS_CHANNELS_PER_DEV defined in xdmaps_hw.h.
+*			Added the tcl file to automatically generate the
+*			xparameters.h
+* 1.02a sg     05/16/12 Made changes for doxygen and moved some function
+*			header from the xdmaps.h file to xdmaps.c file
+*			Other cleanup for coding guidelines and CR 657109
+*			and CR 657898
+*			The xdmaps_example_no_intr.c example is removed
+*			as it is using interrupts  and is similar to
+*			the interrupt example - CR 652477
+* 1.03a sg     07/16/2012 changed inline to __inline for CR665681
+* 1.04a nm     10/22/2012 Fixed CR# 681671.
+* 1.05a nm     04/15/2013 Fixed CR# 704396. Removed warnings when compiled
+*			  with -Wall and -Wextra option in bsp.
+*	       05/01/2013 Fixed CR# 700189. Changed XDmaPs_BuildDmaProg()
+*			  function description.
+*			  Fixed CR# 704396. Removed unused variables
+*			  UseM2MByte & MemBurstLen from XDmaPs_BuildDmaProg()
+*			  function.
+* 1.07a asa    11/02/13. Made changes to fix compilation issues for iarcc.
+*			   Removed the PDBG prints. By default they were always
+*			   defined out and never used. The PDBG is non-standard for
+*			   Xilinx drivers and no other driver does something similar.
+*			   Since there is no easy way to fix compilation issues with
+*			   the IARCC compiler around PDBG, it is better to remove it.
+*			   Users can always use xil_printfs if they want to debug.
+* 2.0   adk    10/12/13  Updated as per the New Tcl API's
+* 2.01  kpc    08/23/14  Fixed the IAR compiler reported errors
+* 2.2   mus    08/12/16  Declared all inline functions in xdmaps.c as extern, to avoid
+*                        linker error for IAR compiler
+* 2.3   ms     01/23/17 Modified xil_printf statement in main function for all
+*                       examples to ensure that "Successfully ran" and "Failed"
+*                       strings are available in all examples. This is a fix
+*                       for CR-965028.
+*       ms     03/17/17 Added readme.txt file in examples folder for doxygen
+*                       generation.
+* 2.4   adk    13/08/18 Fixed armcc compiler warnings in the driver CR-1008310.
+* 
+* +*****************************************************************************/ + +#ifndef XDMAPS_H /* prevent circular inclusions */ +#define XDMAPS_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files ********************************/ + +#include "xparameters.h" +#include "xil_types.h" +#include "xil_assert.h" +#include "xstatus.h" + +#include "xdmaps_hw.h" + +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + +/** + * This typedef contains configuration information for the device. + */ +typedef struct { + u16 DeviceId; /**< Unique ID of device */ + u32 BaseAddress; /**< Base address of device (IPIF) */ +} XDmaPs_Config; + + +/** DMA channle control structure. It's for AXI bus transaction. + * This struct will be translated into a 32-bit channel control register value. + */ +typedef struct { + unsigned int EndianSwapSize; /**< Endian swap size. */ + unsigned int DstCacheCtrl; /**< Destination cache control */ + unsigned int DstProtCtrl; /**< Destination protection control */ + unsigned int DstBurstLen; /**< Destination burst length */ + unsigned int DstBurstSize; /**< Destination burst size */ + unsigned int DstInc; /**< Destination incrementing or fixed + * address */ + unsigned int SrcCacheCtrl; /**< Source cache control */ + unsigned int SrcProtCtrl; /**< Source protection control */ + unsigned int SrcBurstLen; /**< Source burst length */ + unsigned int SrcBurstSize; /**< Source burst size */ + unsigned int SrcInc; /**< Source incrementing or fixed + * address */ +} XDmaPs_ChanCtrl; + +/** DMA block descriptor stucture. + */ +typedef struct { + u32 SrcAddr; /**< Source starting address */ + u32 DstAddr; /**< Destination starting address */ + unsigned int Length; /**< Number of bytes for the block */ +} XDmaPs_BD; + +/** + * A DMA command consisits of a channel control struct, a block descriptor, + * a user defined program, a pointer pointing to generated DMA program, and + * execution result. + * + */ +typedef struct { + XDmaPs_ChanCtrl ChanCtrl; /**< Channel Control Struct */ + XDmaPs_BD BD; /**< Together with SgLength field, + * it's a scatter-gather list. + */ + void *UserDmaProg; /**< If user wants the driver to + * execute their own DMA program, + * this field points to the DMA + * program. + */ + int UserDmaProgLength; /**< The length of user defined + * DMA program. + */ + + void *GeneratedDmaProg; /**< The DMA program genreated + * by the driver. This field will be + * set if a user invokes the DMA + * program generation function. Or + * the DMA command is finished and + * a user informs the driver not to + * release the program buffer. + * This field has two purposes, one + * is to ask the driver to generate + * a DMA program while the DMAC is + * performaning DMA transactions. The + * other purpose is to debug the + * driver. + */ + int GeneratedDmaProgLength; /**< The length of the DMA program + * generated by the driver + */ + int DmaStatus; /**< 0 on success, otherwise error code + */ + u32 ChanFaultType; /**< Channel fault type in case of fault + */ + u32 ChanFaultPCAddr; /**< Channel fault PC address + */ +} XDmaPs_Cmd; + +/** + * It's the done handler a user can set for a channel + */ +typedef void (*XDmaPsDoneHandler) (unsigned int Channel, + XDmaPs_Cmd *DmaCmd, + void *CallbackRef); + +/** + * It's the fault handler a user can set for a channel + */ +typedef void (*XDmaPsFaultHandler) (unsigned int Channel, + XDmaPs_Cmd *DmaCmd, + void *CallbackRef); + +#define XDMAPS_MAX_CHAN_BUFS 2 +#define XDMAPS_CHAN_BUF_LEN 128 + +/** + * The XDmaPs_ProgBuf is the struct for a DMA program buffer. + */ +typedef struct { + char Buf[XDMAPS_CHAN_BUF_LEN]; /**< The actual buffer the holds the + * content */ + unsigned Len; /**< The actual length of the DMA + * program in bytes. */ + int Allocated; /**< A tag indicating whether the + * buffer is allocated or not */ +} XDmaPs_ProgBuf; + +/** + * The XDmaPs_ChannelData is a struct to book keep individual channel of + * the DMAC. + */ +typedef struct { + unsigned DevId; /**< Device id indicating which DMAC */ + unsigned ChanId; /**< Channel number of the DMAC */ + XDmaPs_ProgBuf ProgBufPool[XDMAPS_MAX_CHAN_BUFS]; /**< A pool of + program buffers*/ + XDmaPsDoneHandler DoneHandler; /**< Done interrupt handler */ + void *DoneRef; /**< Done interrupt callback data */ + XDmaPs_Cmd *DmaCmdToHw; /**< DMA command being executed */ + XDmaPs_Cmd *DmaCmdFromHw; /**< DMA command that is finished. + * This field is for debugging purpose + */ + int HoldDmaProg; /**< A tag indicating whether to hold the + * DMA program after the DMA is done. + */ + +} XDmaPs_ChannelData; + +/** + * The XDmaPs driver instance data structure. A pointer to an instance data + * structure is passed around by functions to refer to a specific driver + * instance. + */ +typedef struct { + XDmaPs_Config Config; /**< Configuration data structure */ + int IsReady; /**< Device is Ready */ + int CacheLength; /**< icache length */ + XDmaPsFaultHandler FaultHandler; /**< fault interrupt handler */ + void *FaultRef; /**< fault call back data */ + XDmaPs_ChannelData Chans[XDMAPS_CHANNELS_PER_DEV]; + /**< + * channel data + */ +} XDmaPs; + +/* + * Functions implemented in xdmaps.c + */ +int XDmaPs_CfgInitialize(XDmaPs *InstPtr, + XDmaPs_Config *Config, + u32 EffectiveAddr); + +int XDmaPs_Start(XDmaPs *InstPtr, unsigned int Channel, + XDmaPs_Cmd *Cmd, + int HoldDmaProg); + +int XDmaPs_IsActive(XDmaPs *InstPtr, unsigned int Channel); +int XDmaPs_GenDmaProg(XDmaPs *InstPtr, unsigned int Channel, + XDmaPs_Cmd *Cmd); +int XDmaPs_FreeDmaProg(XDmaPs *InstPtr, unsigned int Channel, + XDmaPs_Cmd *Cmd); +void XDmaPs_Print_DmaProg(XDmaPs_Cmd *Cmd); + + +int XDmaPs_ResetManager(XDmaPs *InstPtr); +int XDmaPs_ResetChannel(XDmaPs *InstPtr, unsigned int Channel); + + +int XDmaPs_SetDoneHandler(XDmaPs *InstPtr, + unsigned Channel, + XDmaPsDoneHandler DoneHandler, + void *CallbackRef); + +int XDmaPs_SetFaultHandler(XDmaPs *InstPtr, + XDmaPsFaultHandler FaultHandler, + void *CallbackRef); + +void XDmaPs_Print_DmaProg(XDmaPs_Cmd *Cmd); +int XDmaPs_Instr_DMARMB(char *DmaProg); +int XDmaPs_Instr_DMAWMB(char *DmaProg); + +/** + * To avoid linking error,Declare all inline functions as extern for + * IAR compiler + */ +#ifdef __ICCARM__ +extern INLINE int XDmaPs_Instr_DMAEND(char *DmaProg); +extern INLINE void XDmaPs_Memcpy4(char *Dst, char *Src); +extern INLINE int XDmaPs_Instr_DMAGO(char *DmaProg, unsigned int Cn, + u32 Imm, unsigned int Ns); +extern INLINE int XDmaPs_Instr_DMALD(char *DmaProg); +extern INLINE int XDmaPs_Instr_DMALP(char *DmaProg, unsigned Lc, + unsigned LoopIterations); +extern INLINE int XDmaPs_Instr_DMALPEND(char *DmaProg, char *BodyStart, unsigned Lc); +extern INLINE int XDmaPs_Instr_DMAMOV(char *DmaProg, unsigned Rd, u32 Imm); +extern INLINE int XDmaPs_Instr_DMANOP(char *DmaProg); +extern INLINE int XDmaPs_Instr_DMASEV(char *DmaProg, unsigned int EventNumber); +extern INLINE int XDmaPs_Instr_DMAST(char *DmaProg); +extern INLINE unsigned XDmaPs_ToEndianSwapSizeBits(unsigned int EndianSwapSize); +extern INLINE unsigned XDmaPs_ToBurstSizeBits(unsigned BurstSize); +#endif + +/** + * Driver done interrupt service routines for the channels. + * We need this done ISR mainly because the driver needs to release the + * DMA program buffer. This is the one that connects the GIC + */ +void XDmaPs_DoneISR_0(XDmaPs *InstPtr); +void XDmaPs_DoneISR_1(XDmaPs *InstPtr); +void XDmaPs_DoneISR_2(XDmaPs *InstPtr); +void XDmaPs_DoneISR_3(XDmaPs *InstPtr); +void XDmaPs_DoneISR_4(XDmaPs *InstPtr); +void XDmaPs_DoneISR_5(XDmaPs *InstPtr); +void XDmaPs_DoneISR_6(XDmaPs *InstPtr); +void XDmaPs_DoneISR_7(XDmaPs *InstPtr); + +/** + * Driver fault interrupt service routine + */ +void XDmaPs_FaultISR(XDmaPs *InstPtr); + + +/* + * Static loopup function implemented in xdmaps_sinit.c + */ +XDmaPs_Config *XDmaPs_LookupConfig(u16 DeviceId); + + +/* + * self-test functions in xdmaps_selftest.c + */ +int XDmaPs_SelfTest(XDmaPs *InstPtr); + + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/dmaps_v2_4/src/xdmaps_g.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/dmaps_v2_4/src/xdmaps_g.c new file mode 100644 index 0000000..1492a06 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/dmaps_v2_4/src/xdmaps_g.c @@ -0,0 +1,55 @@ + +/******************************************************************* +* +* CAUTION: This file is automatically generated by HSI. +* Version: 2019.1.3 +* DO NOT EDIT. +* +* Copyright (C) 2010-2023 Xilinx, Inc. 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 +*XILINX 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. +* +*Except as contained in this notice, the name of the Xilinx shall not be used +*in advertising or otherwise to promote the sale, use or other dealings in +*this Software without prior written authorization from Xilinx. +* + +* +* Description: Driver configuration +* +*******************************************************************/ + +#include "xparameters.h" +#include "xdmaps.h" + +/* +* The configuration table for devices +*/ + +XDmaPs_Config XDmaPs_ConfigTable[XPAR_XDMAPS_NUM_INSTANCES] = +{ + { + XPAR_PS7_DMA_NS_DEVICE_ID, + XPAR_PS7_DMA_NS_BASEADDR + }, + { + XPAR_PS7_DMA_S_DEVICE_ID, + XPAR_PS7_DMA_S_BASEADDR + } +}; + + diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/dmaps_v2_4/src/xdmaps_hw.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/dmaps_v2_4/src/xdmaps_hw.c new file mode 100644 index 0000000..5fbe4ca --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/dmaps_v2_4/src/xdmaps_hw.c @@ -0,0 +1,112 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xdmaps_hw.c +* @addtogroup dmaps_v2_4 +* @{ +* +* This file contains the implementation of the interface reset functionality +* for XDmaPs driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  	Date     Changes
+* ----- ------ -------- ----------------------------------------------
+* 1.06a kpc 10/07/13 First release
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ +#include "xdmaps_hw.h" + +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ +#ifndef XDMAPS_MAX_WAIT +#define XDMAPS_MAX_WAIT 4000 +#endif +/************************** Function Prototypes *****************************/ + +/************************** Variable Definitions ****************************/ + +/*****************************************************************************/ +/** +* This function perform the reset sequence to the given dmaps interface by +* configuring the appropriate control bits in the dmaps specifc registers +* the dmaps reset squence involves the following steps +* Disable all the interuupts +* Clear the pending interrupts +* Kill all the active channel threads +* Kill the manager thread +* +* @param BaseAddress of the interface +* +* @return N/A +* +* @note +* This function will not modify the slcr registers that are relavant for +* dmaps controller +******************************************************************************/ +void XDmaPs_ResetHw(u32 BaseAddress) +{ + u32 DbgInst; + u32 WaitCount = 0; + u32 ChanIndex; + + /* Disable all the interrupts */ + XDmaPs_WriteReg(BaseAddress, XDMAPS_INTEN_OFFSET, 0x00); + /* Clear the interrupts */ + XDmaPs_WriteReg(BaseAddress, XDMAPS_INTCLR_OFFSET, XDMAPS_INTCLR_ALL_MASK); + /* Kill the dma channel threads */ + for (ChanIndex=0; ChanIndex < XDMAPS_CHANNELS_PER_DEV; ChanIndex++) { + while ((XDmaPs_ReadReg(BaseAddress, XDMAPS_DBGSTATUS_OFFSET) + & XDMAPS_DBGSTATUS_BUSY) + && (WaitCount < XDMAPS_MAX_WAIT)) + WaitCount++; + + DbgInst = XDmaPs_DBGINST0(0, 0x01, ChanIndex, 1); + XDmaPs_WriteReg(BaseAddress, XDMAPS_DBGINST0_OFFSET, DbgInst); + XDmaPs_WriteReg(BaseAddress, XDMAPS_DBGINST1_OFFSET, 0x0); + XDmaPs_WriteReg(BaseAddress, XDMAPS_DBGCMD_OFFSET, 0x0); + } + /* Kill the manager thread */ + DbgInst = XDmaPs_DBGINST0(0, 0x01, 0, 0); + XDmaPs_WriteReg(BaseAddress, XDMAPS_DBGINST0_OFFSET, DbgInst); + XDmaPs_WriteReg(BaseAddress, XDMAPS_DBGINST1_OFFSET, 0x0); + XDmaPs_WriteReg(BaseAddress, XDMAPS_DBGCMD_OFFSET, 0x0); +} + + + +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/dmaps_v2_4/src/xdmaps_hw.h b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/dmaps_v2_4/src/xdmaps_hw.h new file mode 100644 index 0000000..42dfe69 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/dmaps_v2_4/src/xdmaps_hw.h @@ -0,0 +1,289 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xdmaps_hw.h +* @addtogroup dmaps_v2_4 +* @{ +* +* This header file contains the hardware interface of an XDmaPs device. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who   Date     Changes
+* ----- ----  -------- ----------------------------------------------
+* 1.00a	hbm   08/18/10 First Release
+* 1.01a nm    12/20/12 Added definition XDMAPS_CHANNELS_PER_DEV which specifies
+*		       the maximum number of channels.
+*		       Replaced the usage of XPAR_XDMAPS_CHANNELS_PER_DEV
+*                      with XDMAPS_CHANNELS_PER_DEV defined in xdmaps_hw.h
+* 1.02a sg    05/16/12 Made changes for doxygen
+* 1.06a kpc   07/10/13 Added function prototype
+* 
+* +******************************************************************************/ + +#ifndef XDMAPS_HW_H /* prevent circular inclusions */ +#define XDMAPS_HW_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_io.h" + +/************************** Constant Definitions *****************************/ + +/** @name Register Map + * + * Register offsets for the DMAC. + * @{ + */ + +#define XDMAPS_DS_OFFSET 0x000 /* DMA Status Register */ +#define XDMAPS_DPC_OFFSET 0x004 /* DMA Program Counter Rregister */ +#define XDMAPS_INTEN_OFFSET 0X020 /* DMA Interrupt Enable Register */ +#define XDMAPS_ES_OFFSET 0x024 /* DMA Event Status Register */ +#define XDMAPS_INTSTATUS_OFFSET 0x028 /* DMA Interrupt Status Register + */ +#define XDMAPS_INTCLR_OFFSET 0x02c /* DMA Interrupt Clear Register */ +#define XDMAPS_FSM_OFFSET 0x030 /* DMA Fault Status DMA Manager + * Register + */ +#define XDMAPS_FSC_OFFSET 0x034 /* DMA Fault Status DMA Chanel Register + */ +#define XDMAPS_FTM_OFFSET 0x038 /* DMA Fault Type DMA Manager Register */ + +#define XDMAPS_FTC0_OFFSET 0x040 /* DMA Fault Type for DMA Channel 0 */ +/* + * The offset for the rest of the FTC registers is calculated as + * FTC0 + dev_chan_num * 4 + */ +#define XDmaPs_FTCn_OFFSET(ch) (XDMAPS_FTC0_OFFSET + (ch) * 4) + +#define XDMAPS_CS0_OFFSET 0x100 /* Channel Status for DMA Channel 0 */ +/* + * The offset for the rest of the CS registers is calculated as + * CS0 + * dev_chan_num * 0x08 + */ +#define XDmaPs_CSn_OFFSET(ch) (XDMAPS_CS0_OFFSET + (ch) * 8) + +#define XDMAPS_CPC0_OFFSET 0x104 /* Channel Program Counter for DMA + * Channel 0 + */ +/* + * The offset for the rest of the CPC registers is calculated as + * CPC0 + dev_chan_num * 0x08 + */ +#define XDmaPs_CPCn_OFFSET(ch) (XDMAPS_CPC0_OFFSET + (ch) * 8) + +#define XDMAPS_SA_0_OFFSET 0x400 /* Source Address Register for DMA + * Channel 0 + */ +/* The offset for the rest of the SA registers is calculated as + * SA_0 + dev_chan_num * 0x20 + */ +#define XDmaPs_SA_n_OFFSET(ch) (XDMAPS_SA_0_OFFSET + (ch) * 0x20) + +#define XDMAPS_DA_0_OFFSET 0x404 /* Destination Address Register for + * DMA Channel 0 + */ +/* The offset for the rest of the DA registers is calculated as + * DA_0 + dev_chan_num * 0x20 + */ +#define XDmaPs_DA_n_OFFSET(ch) (XDMAPS_DA_0_OFFSET + (ch) * 0x20) + +#define XDMAPS_CC_0_OFFSET 0x408 /* Channel Control Register for + * DMA Channel 0 + */ +/* + * The offset for the rest of the CC registers is calculated as + * CC_0 + dev_chan_num * 0x20 + */ +#define XDmaPs_CC_n_OFFSET(ch) (XDMAPS_CC_0_OFFSET + (ch) * 0x20) + +#define XDMAPS_LC0_0_OFFSET 0x40C /* Loop Counter 0 for DMA Channel 0 */ +/* + * The offset for the rest of the LC0 registers is calculated as + * LC_0 + dev_chan_num * 0x20 + */ +#define XDmaPs_LC0_n_OFFSET(ch) (XDMAPS_LC0_0_OFFSET + (ch) * 0x20) +#define XDMAPS_LC1_0_OFFSET 0x410 /* Loop Counter 1 for DMA Channel 0 */ +/* + * The offset for the rest of the LC1 registers is calculated as + * LC_0 + dev_chan_num * 0x20 + */ +#define XDmaPs_LC1_n_OFFSET(ch) (XDMAPS_LC1_0_OFFSET + (ch) * 0x20) + +#define XDMAPS_DBGSTATUS_OFFSET 0xD00 /* Debug Status Register */ +#define XDMAPS_DBGCMD_OFFSET 0xD04 /* Debug Command Register */ +#define XDMAPS_DBGINST0_OFFSET 0xD08 /* Debug Instruction 0 Register */ +#define XDMAPS_DBGINST1_OFFSET 0xD0C /* Debug Instruction 1 Register */ + +#define XDMAPS_CR0_OFFSET 0xE00 /* Configuration Register 0 */ +#define XDMAPS_CR1_OFFSET 0xE04 /* Configuration Register 1 */ +#define XDMAPS_CR2_OFFSET 0xE08 /* Configuration Register 2 */ +#define XDMAPS_CR3_OFFSET 0xE0C /* Configuration Register 3 */ +#define XDMAPS_CR4_OFFSET 0xE10 /* Configuration Register 4 */ +#define XDMAPS_CRDN_OFFSET 0xE14 /* Configuration Register Dn */ + +#define XDMAPS_PERIPH_ID_0_OFFSET 0xFE0 /* Peripheral Identification + * Register 0 + */ +#define XDMAPS_PERIPH_ID_1_OFFSET 0xFE4 /* Peripheral Identification + * Register 1 + */ +#define XDMAPS_PERIPH_ID_2_OFFSET 0xFE8 /* Peripheral Identification + * Register 2 + */ +#define XDMAPS_PERIPH_ID_3_OFFSET 0xFEC /* Peripheral Identification + * Register 3 + */ +#define XDMAPS_PCELL_ID_0_OFFSET 0xFF0 /* PrimeCell Identification + * Register 0 + */ +#define XDMAPS_PCELL_ID_1_OFFSET 0xFF4 /* PrimeCell Identification + * Register 1 + */ +#define XDMAPS_PCELL_ID_2_OFFSET 0xFF8 /* PrimeCell Identification + * Register 2 + */ +#define XDMAPS_PCELL_ID_3_OFFSET 0xFFC /* PrimeCell Identification + * Register 3 + */ + +/* + * Some useful register masks + */ +#define XDMAPS_DS_DMA_STATUS 0x0F /* DMA status mask */ +#define XDMAPS_DS_DMA_STATUS_STOPPED 0x00 /* debug status busy mask */ + +#define XDMAPS_DBGSTATUS_BUSY 0x01 /* debug status busy mask */ + +#define XDMAPS_CS_ACTIVE_MASK 0x07 /* channel status active mask, + * llast 3 bits of CS register + */ + +#define XDMAPS_CR1_I_CACHE_LEN_MASK 0x07 /* i_cache_len mask */ + + +/* + * XDMAPS_DBGINST0 - constructs the word for the Debug Instruction-0 Register. + * @b1: Instruction byte 1 + * @b0: Instruction byte 0 + * @ch: Channel number + * @dbg_th: Debug thread encoding: 0 = DMA manager thread, 1 = DMA channel + */ +#define XDmaPs_DBGINST0(b1, b0, ch, dbg_th) \ + (((b1) << 24) | ((b0) << 16) | (((ch) & 0x7) << 8) | ((dbg_th & 0x1))) + +/* @} */ + +/** @name Control Register + * + * The Control register (CR) controls the major functions of the device. + * + * Control Register Bit Definition + */ + +/* @}*/ + + +#define XDMAPS_CHANNELS_PER_DEV 8 + + +/** @name Mode Register + * + * The mode register (MR) defines the mode of transfer as well as the data + * format. If this register is modified during transmission or reception, + * data validity cannot be guaranteed. + * + * Mode Register Bit Definition + * @{ + */ + +/* @} */ + + +/** @name Interrupt Registers + * + * Interrupt control logic uses the interrupt enable register (IER) and the + * interrupt disable register (IDR) to set the value of the bits in the + * interrupt mask register (IMR). The IMR determines whether to pass an + * interrupt to the interrupt status register (ISR). + * Writing a 1 to IER Enbables an interrupt, writing a 1 to IDR disables an + * interrupt. IMR and ISR are read only, and IER and IDR are write only. + * Reading either IER or IDR returns 0x00. + * + * All four registers have the same bit definitions. + * + * @{ + */ + +/* @} */ +#define XDMAPS_INTCLR_ALL_MASK 0xFF + +#define XDmaPs_ReadReg(BaseAddress, RegOffset) \ + Xil_In32((BaseAddress) + (RegOffset)) + +/***************************************************************************/ +/** +* Write a DMAC register. +* +* @param BaseAddress contains the base address of the device. +* @param RegOffset contains the offset from the base address of the device. +* @param RegisterValue is the value to be written to the register. +* +* @return None. +* +* @note +* C-Style signature: +* void XDmaPs_WriteReg(u32 BaseAddress, int RegOffset, +* u32 RegisterValue) +******************************************************************************/ +#define XDmaPs_WriteReg(BaseAddress, RegOffset, RegisterValue) \ + Xil_Out32((BaseAddress) + (RegOffset), (RegisterValue)) +/************************** Variable Definitions *****************************/ + +/************************** Function Prototypes *****************************/ +/* + * Perform reset operation to the dmaps interface + */ +void XDmaPs_ResetHw(u32 BaseAddr); +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/dmaps_v2_4/src/xdmaps_selftest.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/dmaps_v2_4/src/xdmaps_selftest.c new file mode 100644 index 0000000..37e70f8 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/dmaps_v2_4/src/xdmaps_selftest.c @@ -0,0 +1,106 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xdmaps_selftest.c +* @addtogroup dmaps_v2_4 +* @{ +* +* This file contains the self-test functions for the XDmaPs driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who     Date     Changes
+* ----- ------ -------- -----------------------------------------------
+* 1.00	hbm 	03/29/2010 First Release
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xstatus.h" +#include "xdmaps.h" + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Variable Definitions *****************************/ + + +/************************** Function Prototypes ******************************/ + + +/****************************************************************************/ +/** +* +* This function runs a self-test on the driver and hardware device. This self +* test performs a local loopback and verifies data can be sent and received. +* +* The time for this test is proportional to the baud rate that has been set +* prior to calling this function. +* +* The mode and control registers are restored before return. +* +* @param InstPtr is a pointer to the XDmaPs instance +* +* @return +* +* - XST_SUCCESS if the test was successful +* - XST_FAILURE if the test failed +* +* @note +* +* This function can hang if the hardware is not functioning properly. +* +******************************************************************************/ +int XDmaPs_SelfTest(XDmaPs *InstPtr) +{ + u32 BaseAddr = InstPtr->Config.BaseAddress; + int i; + + if (XDmaPs_ReadReg(BaseAddr, XDMAPS_DBGSTATUS_OFFSET) + & XDMAPS_DBGSTATUS_BUSY) + return XST_FAILURE; + + for (i = 0; i < XDMAPS_CHANNELS_PER_DEV; i++) { + if (XDmaPs_ReadReg(BaseAddr, + XDmaPs_CSn_OFFSET(i))) + return XST_FAILURE; + } + return XST_SUCCESS; +} +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/dmaps_v2_4/src/xdmaps_sinit.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/dmaps_v2_4/src/xdmaps_sinit.c new file mode 100644 index 0000000..e0b6fae --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/dmaps_v2_4/src/xdmaps_sinit.c @@ -0,0 +1,100 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xdmaps_sinit.c +* @addtogroup dmaps_v2_4 +* @{ +* +* The implementation of the XDmaPs driver's static initialzation +* functionality. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00  hbm  08/13/10 First Release
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ + +#include "xstatus.h" +#include "xparameters.h" +#include "xdmaps.h" + +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + + +/***************** Macros (Inline Functions) Definitions ********************/ + + +/************************** Variable Definitions ****************************/ +extern XDmaPs_Config XDmaPs_ConfigTable[]; + +/************************** Function Prototypes *****************************/ + +/****************************************************************************/ +/** +* +* Looks up the device configuration based on the unique device ID. The table +* contains the configuration info for each device in the system. +* +* @param DeviceId contains the ID of the device +* +* @return +* +* A pointer to the configuration structure or NULL if the specified device +* is not in the system. +* +* @note +* +* None. +* +******************************************************************************/ +XDmaPs_Config *XDmaPs_LookupConfig(u16 DeviceId) +{ + XDmaPs_Config *CfgPtr = NULL; + + int i; + + for (i = 0; i < XPAR_XDMAPS_NUM_INSTANCES; i++) { + if (XDmaPs_ConfigTable[i].DeviceId == DeviceId) { + CfgPtr = &XDmaPs_ConfigTable[i]; + break; + } + } + + return CfgPtr; +} +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/frame_uart_v1_0/src/Makefile b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/frame_uart_v1_0/src/Makefile new file mode 100644 index 0000000..0bbff44 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/frame_uart_v1_0/src/Makefile @@ -0,0 +1,26 @@ +COMPILER= +ARCHIVER= +CP=cp +COMPILER_FLAGS= +EXTRA_COMPILER_FLAGS= +LIB=libxil.a + +RELEASEDIR=../../../lib +INCLUDEDIR=../../../include +INCLUDES=-I./. -I${INCLUDEDIR} + +INCLUDEFILES=*.h +LIBSOURCES=*.c +OUTS = *.o + +libs: + echo "Compiling Frame_Uart..." + $(COMPILER) $(COMPILER_FLAGS) $(EXTRA_COMPILER_FLAGS) $(INCLUDES) $(LIBSOURCES) + $(ARCHIVER) -r ${RELEASEDIR}/${LIB} ${OUTS} + make clean + +include: + ${CP} $(INCLUDEFILES) $(INCLUDEDIR) + +clean: + rm -rf ${OUTS} diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/frame_uart_v1_0/src/frame_uart.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/frame_uart_v1_0/src/frame_uart.c new file mode 100644 index 0000000..17f1674 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/frame_uart_v1_0/src/frame_uart.c @@ -0,0 +1,138 @@ +/*****************************************************************************/ +/** + * Description: A brief description of this file + * + * Author: Fan Hao + * Date: 2021-12-26 10:59 + * LastEditors: Fan Hao + * LastEditTime: 2022-01-16 21:56 + * Revisions: Rev 0.0 + * History: + * [2022-01-16]: Initial version. + * + * Copyright(c) 2022 Beijing Institute of Technology. + * Lab of Communication and Networking + * + ******************************************************************************/ + +/***************************** Include Files *******************************/ +#include +#include +#include +#include +#include "frame_uart.h" + +/*************************** Function Definitions ****************************/ + +/*****************************************************************************/ +/** + * @brief Instance initial + * + * @param InstPtr A pointer to frame uart instance structure. + * @param BaseAddr Base address of frame uart, refer to "xparameters.h" + * + * @return None. + * + ******************************************************************************/ +int FrameUart_Init(FrameUart* InstPtr, u32 BaseAddr) { + Xil_AssertNonvoid(InstPtr != NULL); + InstPtr->BaseAddr = BaseAddr; + InstPtr->TxOffset = BaseAddr + FRAME_UART_TXBUFF_OFFSET; + InstPtr->RxOffset = BaseAddr + FRAME_UART_RXBUFF_OFFSET; + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** + * @brief Send a system bus frame. + * + * @param InstPtr A pointer to FrameUart instance structure. + * @param DataBuff A pointer to send data buffer + * @param DataLenByte A integer indicate the send data buffer length in byte. + * + * @return + * + ******************************************************************************/ +int FrameUart_Send(FrameUart* InstPtr, u8* DataBuff, u32 DataLenByte) { + Xil_AssertNonvoid(InstPtr != NULL); + Xil_AssertNonvoid(DataBuff != NULL); + if (DataLenByte > FRAME_UART_TXBUFF_MAX) { + return XST_FAILURE; + } + + memcpy((u8*) (InstPtr->TxOffset), (u8*) DataBuff, DataLenByte); +// Start Sending + Xil_Out32(InstPtr->BaseAddr + FRAME_UART_SEND_START_OFFSET, DataLenByte); + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** + * @brief Get last system bus frame. + * + * @param InstPtr A pointer to FrameUart instance structure. + * @param DataBuff A pointer to receive data buffer. + * + * @return + * + ******************************************************************************/ +int FrameUart_Recv(FrameUart* InstPtr, u8* DataBuff) { + Xil_AssertNonvoid(InstPtr != NULL); + Xil_AssertNonvoid(DataBuff != NULL); + + u32 Temp = 0; + u32 DataLenByte = 0; + Temp = Xil_In32(InstPtr->RxOffset) & 0xFFFF0000; + DataLenByte = (Temp >> 24) & 0x000000FF; + DataLenByte |= (Temp >> 8) & 0x0000FF00; + if (DataLenByte > FRAME_UART_RXBUFF_MAX - FRAME_UART_PROTOCOL_OVERHEAD_LEN + || DataLenByte == 0) { + return XST_FAILURE; + } + DataLenByte += FRAME_UART_PROTOCOL_OVERHEAD_LEN; + memcpy((u8*) (DataBuff), (u8*) (InstPtr->RxOffset), DataLenByte); + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** + * @brief Get rx channel status. + * + * @param InstPtr A pointer to FrameUart instance structure. + * + * @return true - FrameUart rx busy. + * false - FrameUart rx not busy. + * + ******************************************************************************/ +bool FrameUart_IsRxBusy(FrameUart* InstPtr) { + Xil_AssertNonvoid(InstPtr != NULL); + u32 Status = Xil_In32(InstPtr->BaseAddr + FRAME_UART_STATUS_OFFSET); + + if (Status & FRAME_UART_RX_BUSY) { + return true; + } + else { + return false; + } +} + +/*****************************************************************************/ +/** + * @brief Get tx channel status. + * + * @param InstPtr A pointer to FrameUart instance structure. + * + * @return true - FrameUart tx busy. + * false - FrameUart tx not busy. + * + ******************************************************************************/ +bool FrameUart_IsTxBusy(FrameUart* InstPtr) { + Xil_AssertNonvoid(InstPtr != NULL); + u32 Status = Xil_In32(InstPtr->BaseAddr + FRAME_UART_STATUS_OFFSET); + if (Status & FRAME_UART_TX_BUSY) { + return true; + } + else { + return false; + } +} diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/frame_uart_v1_0/src/frame_uart.h b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/frame_uart_v1_0/src/frame_uart.h new file mode 100644 index 0000000..7c576cf --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/frame_uart_v1_0/src/frame_uart.h @@ -0,0 +1,128 @@ +/*****************************************************************************/ +/** + * Description: A brief description of this file + * + * Author: Fan Hao + * Date: 2021-12-26 10:59 + * LastEditors: Fan Hao + * LastEditTime: 2022-01-16 21:48 + * Revisions: Rev 0.0 + * History: + * [2021-12-26]: Initial version. + * + * Copyright(c) 2022 Beijing Institute of Technology. + * Lab of Communication and Networking + * + ******************************************************************************/ + +#ifndef FRAME_UART_H +#define FRAME_UART_H + +/****************** Include Files ********************/ +#include +#include +#include + +#define FRAME_UART_PROTOCOL_OVERHEAD_LEN 4 + +#define FRAME_UART_BYTE_PER_REG 4 +// Control register +#define FRAME_UART_SEND_START_OFFSET 0 +#define FRAME_UART_STATUS_OFFSET 4 + +// Data buffer register +#define FRAME_UART_TXBUFF_OFFSET 1024 +#define FRAME_UART_TXBUFF_MAX 1024 +#define FRAME_UART_RXBUFF_OFFSET 2048 +#define FRAME_UART_RXBUFF_MAX 2048 +#define FRAME_UART_RECV_DLEN_OFFSET 0 + +// Status +#define FRAME_UART_RX_BUSY 0x00010000 +#define FRAME_UART_TX_BUSY 0x00000001 + +/**************************** Type Definitions *****************************/ +/** + * + * Write a value to a FRAME_UART register. A 32 bit write is performed. + * If the component is implemented in a smaller width, only the least + * significant data is written. + * + * @param BaseAddress is the base address of the FRAME_UARTdevice. + * @param RegOffset is the register offset from the base to write to. + * @param Data is the data written to the register. + * + * @return None. + * + * @note + * C-style signature: + * void FRAME_UART_mWriteReg(u32 BaseAddress, unsigned RegOffset, u32 Data) + * + */ +#define FRAME_UART_mWriteReg(BaseAddress, RegOffset, Data) \ + Xil_Out32((BaseAddress) + (RegOffset), (u32)(Data)) + +/** + * + * Read a value from a FRAME_UART register. A 32 bit read is performed. + * If the component is implemented in a smaller width, only the least + * significant data is read from the register. The most significant data + * will be read as 0. + * + * @param BaseAddress is the base address of the FRAME_UART device. + * @param RegOffset is the register offset from the base to write to. + * + * @return Data is the data from the register. + * + * @note + * C-style signature: + * u32 FRAME_UART_mReadReg(u32 BaseAddress, unsigned RegOffset) + * + */ +#define FRAME_UART_mReadReg(BaseAddress, RegOffset) \ + Xil_In32((BaseAddress) + (RegOffset)) + +/************************** Function Prototypes ****************************/ +/** + * + * Run a self-test on the driver/device. Note this may be a destructive test if + * resets of the device are performed. + * + * If the hardware system is not built correctly, this function may never + * return to the caller. + * + * @param baseaddr_p is the base address of the FRAME_UART instance to be worked on. + * + * @return + * + * - XST_SUCCESS if all self-test code passed + * - XST_FAILURE if any self-test code failed + * + * @note Caching must be turned off for this function to work. + * @note Self test may fail if data memory and device are not on the same bus. + * + */ + +/************************** Data Type Definitions ****************************/ +typedef struct { + u32 BaseAddr; + u32 TxOffset; + u32 RxOffset; +} FrameUart; + +/************************** Function Prototypes ******************************/ +// Instance initial +int FrameUart_Init(FrameUart* InstPtr, u32 BaseAddr); + +// Send a system bus frame. +int FrameUart_Send(FrameUart* InstPtr, u8* DataBuff, u32 DataLenByte); + +// Get last system bus frame. +int FrameUart_Recv(FrameUart* InstPtr, u8* DataBuff); + +// Get system bus rx channel status. +bool FrameUart_IsRxBusy(FrameUart* InstPtr); + +// Get system bus tx channel status. +bool FrameUart_IsTxBusy(FrameUart* InstPtr); +#endif // FRAME_UART_H diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/gpio_v4_4/src/Makefile b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/gpio_v4_4/src/Makefile new file mode 100644 index 0000000..a98e2a0 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/gpio_v4_4/src/Makefile @@ -0,0 +1,40 @@ +COMPILER= +ARCHIVER= +CP=cp +COMPILER_FLAGS= +EXTRA_COMPILER_FLAGS= +LIB=libxil.a + +CC_FLAGS = $(COMPILER_FLAGS) +ECC_FLAGS = $(EXTRA_COMPILER_FLAGS) + +RELEASEDIR=../../../lib +INCLUDEDIR=../../../include +INCLUDES=-I./. -I${INCLUDEDIR} + +OUTS = *.o + +LIBSOURCES:=*.c +INCLUDEFILES:=*.h + +OBJECTS = $(addsuffix .o, $(basename $(wildcard *.c))) + +libs: banner xgpio_libs clean + +%.o: %.c + ${COMPILER} $(CC_FLAGS) $(ECC_FLAGS) $(INCLUDES) -o $@ $< + +banner: + echo "Compiling gpio" + +xgpio_libs: ${OBJECTS} + $(ARCHIVER) -r ${RELEASEDIR}/${LIB} ${OBJECTS} + +.PHONY: include +include: xgpio_includes + +xgpio_includes: + ${CP} ${INCLUDEFILES} ${INCLUDEDIR} + +clean: + rm -rf ${OBJECTS} diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/gpio_v4_4/src/xgpio.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/gpio_v4_4/src/xgpio.c new file mode 100644 index 0000000..a07e914 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/gpio_v4_4/src/xgpio.c @@ -0,0 +1,251 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file xgpio.c +* @addtogroup gpio_v4_4 +* @{ +* +* The implementation of the XGpio driver's basic functionality. See xgpio.h +* for more information about the driver. +* +* @note +* +* None +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a rmm  02/04/02 First release
+* 2.00a jhl  12/16/02 Update for dual channel and interrupt support
+* 2.01a jvb  12/13/05 Changed Initialize() into CfgInitialize(), and made
+*                     CfgInitialize() take a pointer to a config structure
+*                     instead of a device id. Moved Initialize() into
+*                     xgpio_sinit.c, and had Initialize() call CfgInitialize()
+*                     after it retrieved the config structure using the device
+*                     id. Removed include of xparameters.h along with any
+*                     dependencies on xparameters.h and the _g.c config table.
+* 2.11a mta  03/21/07 Updated to new coding style, added GetDataDirection
+* 2.12a sv   11/21/07 Updated driver to support access through DCR bus
+* 3.00a sv   11/21/09 Updated to use HAL Processor APIs. Renamed the
+*		      macros to remove _m from the name.
+* 4.1   lks  11/18/15 Clean up of the comments in the code and
+*		      removed support for DCR bridge
+* 4.2   sk   08/16/16 Used UINTPTR instead of u32 for Baseaddress as part of
+*                     adding 64 bit support. CR# 867425.
+*                     Changed the prototype of XGpio_CfgInitialize API.
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ + +#include "xgpio.h" +#include "xstatus.h" + +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Variable Definitions ****************************/ + + +/************************** Function Prototypes *****************************/ + + +/****************************************************************************/ +/** +* Initialize the XGpio instance provided by the caller based on the +* given configuration data. +* +* Nothing is done except to initialize the InstancePtr. +* +* @param InstancePtr is a pointer to an XGpio instance. The memory the +* pointer references must be pre-allocated by the caller. Further +* calls to manipulate the driver through the XGpio API must be +* made with this pointer. +* @param Config is a reference to a structure containing information +* about a specific GPIO device. This function initializes an +* InstancePtr object for a specific device specified by the +* contents of Config. This function can initialize multiple +* instance objects with the use of multiple calls giving different +* Config information on each call. +* @param EffectiveAddr is the device base address in the virtual memory +* address space. The caller is responsible for keeping the address +* mapping from EffectiveAddr to the device physical base address +* unchanged once this function is invoked. Unexpected errors may +* occur if the address mapping changes after this function is +* called. If address translation is not used, use +* Config->BaseAddress for this parameters, passing the physical +* address instead. +* +* @return +* - XST_SUCCESS if the initialization is successfull. +* +* @note None. +* +*****************************************************************************/ +int XGpio_CfgInitialize(XGpio * InstancePtr, XGpio_Config * Config, + UINTPTR EffectiveAddr) +{ + /* Assert arguments */ + Xil_AssertNonvoid(InstancePtr != NULL); + + /* Set some default values. */ + InstancePtr->BaseAddress = EffectiveAddr; + + InstancePtr->InterruptPresent = Config->InterruptPresent; + InstancePtr->IsDual = Config->IsDual; + + /* + * Indicate the instance is now ready to use, initialized without error + */ + InstancePtr->IsReady = XIL_COMPONENT_IS_READY; + return (XST_SUCCESS); +} + + +/****************************************************************************/ +/** +* Set the input/output direction of all discrete signals for the specified +* GPIO channel. +* +* @param InstancePtr is a pointer to an XGpio instance to be worked on. +* @param Channel contains the channel of the GPIO (1 or 2) to operate on. +* @param DirectionMask is a bitmask specifying which discretes are input +* and which are output. Bits set to 0 are output and bits set to 1 +* are input. +* +* @return None. +* +* @note The hardware must be built for dual channels if this function +* is used with any channel other than 1. If it is not, this +* function will assert. +* +*****************************************************************************/ +void XGpio_SetDataDirection(XGpio *InstancePtr, unsigned Channel, + u32 DirectionMask) +{ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid((Channel == 1) || + ((Channel == 2) && (InstancePtr->IsDual == TRUE))); + + XGpio_WriteReg(InstancePtr->BaseAddress, + ((Channel - 1) * XGPIO_CHAN_OFFSET) + XGPIO_TRI_OFFSET, + DirectionMask); +} + +/****************************************************************************/ +/** +* Get the input/output direction of all discrete signals for the specified +* GPIO channel. +* +* @param InstancePtr is a pointer to an XGpio instance to be worked on. +* @param Channel contains the channel of the GPIO (1 or 2) to operate on. +* +* @return Bitmask specifying which discretes are input and +* which are output. Bits set to 0 are output and bits set to 1 are +* input. +* +* @note +* +* The hardware must be built for dual channels if this function is used +* with any channel other than 1. If it is not, this function will assert. +* +*****************************************************************************/ +u32 XGpio_GetDataDirection(XGpio *InstancePtr, unsigned Channel) +{ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid((Channel == 1) || + ((Channel == 2) && + (InstancePtr->IsDual == TRUE))); + + return XGpio_ReadReg(InstancePtr->BaseAddress, + ((Channel - 1) * XGPIO_CHAN_OFFSET) + XGPIO_TRI_OFFSET); +} + +/****************************************************************************/ +/** +* Read state of discretes for the specified GPIO channnel. +* +* @param InstancePtr is a pointer to an XGpio instance to be worked on. +* @param Channel contains the channel of the GPIO (1 or 2) to operate on. +* +* @return Current copy of the discretes register. +* +* @note The hardware must be built for dual channels if this function +* is used with any channel other than 1. If it is not, this +* function will assert. +* +*****************************************************************************/ +u32 XGpio_DiscreteRead(XGpio * InstancePtr, unsigned Channel) +{ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid((Channel == 1) || + ((Channel == 2) && (InstancePtr->IsDual == TRUE))); + + return XGpio_ReadReg(InstancePtr->BaseAddress, + ((Channel - 1) * XGPIO_CHAN_OFFSET) + + XGPIO_DATA_OFFSET); +} + +/****************************************************************************/ +/** +* Write to discretes register for the specified GPIO channel. +* +* @param InstancePtr is a pointer to an XGpio instance to be worked on. +* @param Channel contains the channel of the GPIO (1 or 2) to operate on. +* @param Data is the value to be written to the discretes register. +* +* @return None. +* +* @note The hardware must be built for dual channels if this function +* is used with any channel other than 1. If it is not, this +* function will assert. See also XGpio_DiscreteSet() and +* XGpio_DiscreteClear(). +* +*****************************************************************************/ +void XGpio_DiscreteWrite(XGpio * InstancePtr, unsigned Channel, u32 Data) +{ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid((Channel == 1) || + ((Channel == 2) && (InstancePtr->IsDual == TRUE))); + + XGpio_WriteReg(InstancePtr->BaseAddress, + ((Channel - 1) * XGPIO_CHAN_OFFSET) + XGPIO_DATA_OFFSET, + Data); +} +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/gpio_v4_4/src/xgpio.h b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/gpio_v4_4/src/xgpio.h new file mode 100644 index 0000000..b498fe0 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/gpio_v4_4/src/xgpio.h @@ -0,0 +1,211 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file xgpio.h +* @addtogroup gpio_v4_4 +* @{ +* @details +* +* This file contains the software API definition of the Xilinx General Purpose +* I/O (XGpio) device driver. +* +* The Xilinx GPIO controller is a soft IP core designed for Xilinx FPGAs and +* contains the following general features: +* - Support for up to 32 I/O discretes for each channel (64 bits total). +* - Each of the discretes can be configured for input or output. +* - Configurable support for dual channels and interrupt generation. +* +* The driver provides interrupt management functions. Implementation of +* interrupt handlers is left to the user. Refer to the provided interrupt +* example in the examples directory for details. +* +* This driver is intended to be RTOS and processor independent. Any needs for +* dynamic memory management, threads or thread mutual exclusion, virtual +* memory, or cache control must be satisfied by the layer above this driver. +* +* Initialization & Configuration +* +* The XGpio_Config structure is used by the driver to configure itself. This +* configuration structure is typically created by the tool-chain based on HW +* build properties. +* +* To support multiple runtime loading and initialization strategies employed +* by various operating systems, the driver instance can be initialized in one +* of the following ways: +* +* - XGpio_Initialize(InstancePtr, DeviceId) - The driver looks up its own +* configuration structure created by the tool-chain based on an ID provided +* by the tool-chain. +* +* - XGpio_CfgInitialize(InstancePtr, CfgPtr, EffectiveAddr) - Uses a +* configuration structure provided by the caller. If running in a system +* with address translation, the provided virtual memory base address +* replaces the physical address present in the configuration structure. +* +* @note +* +* This API utilizes 32 bit I/O to the GPIO registers. With less than 32 bits, +* the unused bits from registers are read as zero and written as don't cares. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a rmm  03/13/02 First release
+* 2.00a jhl  11/26/03 Added support for dual channels and interrupts
+* 2.01a jvb  12/14/05 I separated dependency on the static config table and
+*                     xparameters.h from the driver initialization by moving
+*                     _Initialize and _LookupConfig to _sinit.c. I also added
+*                     the new _CfgInitialize routine.
+* 2.11a mta  03/21/07 Updated to new coding style, added GetDataDirection
+* 2.12a sv   11/21/07 Updated driver to support access through DCR bus
+* 2.12a sv   06/05/08 Updated driver to fix the XGpio_InterruptDisable function
+*		      to properly update the Interrupt Enable register
+* 2.13a sdm  08/22/08 Removed support for static interrupt handlers from the MDD
+*		      file
+* 3.00a sv   11/21/09 Updated to use HAL Processor APIs.
+*		      Renamed the macros XGpio_mWriteReg to XGpio_WriteReg and
+*		      XGpio_mReadReg to XGpio_ReadReg. Removed the macros
+*		      XGpio_mSetDataDirection, XGpio_mGetDataReg and
+*		      XGpio_mSetDataReg. Users should use XGpio_WriteReg and
+*		      XGpio_ReadReg to achieve the same functionality.
+* 3.01a bss  04/18/13 Updated driver tcl to generate Canonical params in
+*		      xparameters.h. CR#698589
+* 4.0   adk  19/12/13 Updated as per the New Tcl API's
+* 4.1   lks  11/18/15 Updated to use cannonical xparameters in examples and
+*		      clean up of the comments, removed support for DCR bridge
+*		      and removed xgpio_intr_example for CR 900381
+* 4.2   sk   08/16/16 Used UINTPTR instead of u32 for Baseaddress as part of
+*                     adding 64 bit support. CR# 867425.
+*                     Changed the prototype of XGpio_CfgInitialize API.
+* 4.3   sk   09/29/16 Modified the example to make it work when LED_bits are
+*                     configured as an output. CR# 958644
+*       ms   01/23/17 Added xil_printf statement in main function for all
+*                     examples to ensure that "Successfully ran" and "Failed"
+*                     strings are available in all examples. This is a fix
+*                     for CR-965028.
+*       ms   03/17/17 Added readme.txt file in examples folder for doxygen
+*                     generation.
+* 4.4   sne  04/25/19 Updated Makefile for IAR compier (CR-1029421).
+*
+* 
+*****************************************************************************/ + +#ifndef XGPIO_H /* prevent circular inclusions */ +#define XGPIO_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files ********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xstatus.h" +#include "xgpio_l.h" + +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + +/** + * This typedef contains configuration information for the device. + */ +typedef struct { + u16 DeviceId; /* Unique ID of device */ + UINTPTR BaseAddress; /* Device base address */ + int InterruptPresent; /* Are interrupts supported in h/w */ + int IsDual; /* Are 2 channels supported in h/w */ +} XGpio_Config; + +/** + * The XGpio driver instance data. The user is required to allocate a + * variable of this type for every GPIO device in the system. A pointer + * to a variable of this type is then passed to the driver API functions. + */ +typedef struct { + UINTPTR BaseAddress; /* Device base address */ + u32 IsReady; /* Device is initialized and ready */ + int InterruptPresent; /* Are interrupts supported in h/w */ + int IsDual; /* Are 2 channels supported in h/w */ +} XGpio; + +/***************** Macros (Inline Functions) Definitions ********************/ + + +/************************** Function Prototypes *****************************/ + +/* + * Initialization functions in xgpio_sinit.c + */ +int XGpio_Initialize(XGpio *InstancePtr, u16 DeviceId); +XGpio_Config *XGpio_LookupConfig(u16 DeviceId); + +/* + * API Basic functions implemented in xgpio.c + */ +int XGpio_CfgInitialize(XGpio *InstancePtr, XGpio_Config * Config, + UINTPTR EffectiveAddr); +void XGpio_SetDataDirection(XGpio *InstancePtr, unsigned Channel, + u32 DirectionMask); +u32 XGpio_GetDataDirection(XGpio *InstancePtr, unsigned Channel); +u32 XGpio_DiscreteRead(XGpio *InstancePtr, unsigned Channel); +void XGpio_DiscreteWrite(XGpio *InstancePtr, unsigned Channel, u32 Mask); + + +/* + * API Functions implemented in xgpio_extra.c + */ +void XGpio_DiscreteSet(XGpio *InstancePtr, unsigned Channel, u32 Mask); +void XGpio_DiscreteClear(XGpio *InstancePtr, unsigned Channel, u32 Mask); + +/* + * API Functions implemented in xgpio_selftest.c + */ +int XGpio_SelfTest(XGpio *InstancePtr); + +/* + * API Functions implemented in xgpio_intr.c + */ +void XGpio_InterruptGlobalEnable(XGpio *InstancePtr); +void XGpio_InterruptGlobalDisable(XGpio *InstancePtr); +void XGpio_InterruptEnable(XGpio *InstancePtr, u32 Mask); +void XGpio_InterruptDisable(XGpio *InstancePtr, u32 Mask); +void XGpio_InterruptClear(XGpio *InstancePtr, u32 Mask); +u32 XGpio_InterruptGetEnabled(XGpio *InstancePtr); +u32 XGpio_InterruptGetStatus(XGpio *InstancePtr); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/gpio_v4_4/src/xgpio_extra.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/gpio_v4_4/src/xgpio_extra.c new file mode 100644 index 0000000..af9a44b --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/gpio_v4_4/src/xgpio_extra.c @@ -0,0 +1,160 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file xgpio_extra.c +* @addtogroup gpio_v4_4 +* @{ +* +* The implementation of the XGpio driver's advanced discrete functions. +* See xgpio.h for more information about the driver. +* +* @note +* +* These APIs can only be used if the GPIO_IO ports in the IP are used for +* connecting to the external output ports. +* +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a rmm  02/04/02 First release
+* 2.00a jhl  12/16/02 Update for dual channel and interrupt support
+* 2.11a mta  03/21/07 Updated to new coding style
+* 3.00a sv   11/21/09 Updated to use HAL Processor APIs. Renamed the macros
+*		      XGpio_mWriteReg to XGpio_WriteReg, and XGpio_mReadReg
+*		      to XGpio_ReadReg.
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ + +#include "xgpio.h" +#include "xgpio_i.h" + +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Variable Definitions ****************************/ + +/************************** Function Prototypes *****************************/ + + +/****************************************************************************/ +/** +* Set output discrete(s) to logic 1 for the specified GPIO channel. +* +* @param InstancePtr is a pointer to an XGpio instance to be worked on. +* @param Channel contains the channel of the GPIO (1 or 2) to operate on. +* @param Mask is the set of bits that will be set to 1 in the discrete +* data register. All other bits in the data register are +* unaffected. +* +* @return None. +* +* @note +* +* The hardware must be built for dual channels if this function is used +* with any channel other than 1. If it is not, this function will assert. +* +* This API can only be used if the GPIO_IO ports in the IP are used for +* connecting to the external output ports. +* +*****************************************************************************/ +void XGpio_DiscreteSet(XGpio * InstancePtr, unsigned Channel, u32 Mask) +{ + u32 Current; + unsigned DataOffset; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid((Channel == 1) || + ((Channel == 2) && (InstancePtr->IsDual == TRUE))); + + /* Calculate the offset to the data register of the GPIO */ + DataOffset = ((Channel - 1) * XGPIO_CHAN_OFFSET) + XGPIO_DATA_OFFSET; + + /* + * Read the contents of the data register, merge in Mask and write + * back results + */ + Current = XGpio_ReadReg(InstancePtr->BaseAddress, DataOffset); + Current |= Mask; + XGpio_WriteReg(InstancePtr->BaseAddress, DataOffset, Current); +} + + +/****************************************************************************/ +/** +* Set output discrete(s) to logic 0 for the specified GPIO channel. +* +* @param InstancePtr is a pointer to an XGpio instance to be worked on. +* @param Channel contains the channel of the GPIO (1 or 2) to operate on. +* @param Mask is the set of bits that will be set to 0 in the discrete +* data register. All other bits in the data register are +* unaffected. +* +* @return None. +* +* @note +* +* The hardware must be built for dual channels if this function is used +* with any channel other than 1. If it is not, this function will assert. +* +* This API can only be used if the GPIO_IO ports in the IP are used for +* connecting to the external output ports. +* +*****************************************************************************/ +void XGpio_DiscreteClear(XGpio * InstancePtr, unsigned Channel, u32 Mask) +{ + u32 Current; + unsigned DataOffset; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid((Channel == 1) || + ((Channel == 2) && (InstancePtr->IsDual == TRUE))); + + /* Calculate the offset to the data register of the GPIO */ + DataOffset = ((Channel - 1) * XGPIO_CHAN_OFFSET) + XGPIO_DATA_OFFSET; + + /* + * Read the contents of the data register, merge in Mask and write + * back results + */ + Current = XGpio_ReadReg(InstancePtr->BaseAddress, DataOffset); + Current &= ~Mask; + XGpio_WriteReg(InstancePtr->BaseAddress, DataOffset, Current); +} +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/gpio_v4_4/src/xgpio_g.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/gpio_v4_4/src/xgpio_g.c new file mode 100644 index 0000000..f875ce3 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/gpio_v4_4/src/xgpio_g.c @@ -0,0 +1,53 @@ + +/******************************************************************* +* +* CAUTION: This file is automatically generated by HSI. +* Version: 2019.1.3 +* DO NOT EDIT. +* +* Copyright (C) 2010-2023 Xilinx, Inc. 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 +*XILINX 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. +* +*Except as contained in this notice, the name of the Xilinx shall not be used +*in advertising or otherwise to promote the sale, use or other dealings in +*this Software without prior written authorization from Xilinx. +* + +* +* Description: Driver configuration +* +*******************************************************************/ + +#include "xparameters.h" +#include "xgpio.h" + +/* +* The configuration table for devices +*/ + +XGpio_Config XGpio_ConfigTable[XPAR_XGPIO_NUM_INSTANCES] = +{ + { + XPAR_CONFIG_GPIO_DEVICE_ID, + XPAR_CONFIG_GPIO_BASEADDR, + XPAR_CONFIG_GPIO_INTERRUPT_PRESENT, + XPAR_CONFIG_GPIO_IS_DUAL + } +}; + + diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/gpio_v4_4/src/xgpio_i.h b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/gpio_v4_4/src/xgpio_i.h new file mode 100644 index 0000000..7938b0f --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/gpio_v4_4/src/xgpio_i.h @@ -0,0 +1,83 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/******************************************************************************/ +/** +* @file xgpio_i.h +* @addtogroup gpio_v4_3 +* @{ +* +* This header file contains internal identifiers, which are those shared +* between the files of the driver. It is intended for internal use only. +* +* NOTES: +* +* None. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a rmm  03/13/02 First release
+* 2.11a mta  03/21/07 Updated to new coding style
+* 
+******************************************************************************/ + +#ifndef XGPIO_I_H /* prevent circular inclusions */ +#define XGPIO_I_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xgpio.h" + +/************************** Constant Definitions ****************************/ + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + + +/************************** Variable Definitions ****************************/ + +extern XGpio_Config XGpio_ConfigTable[]; + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/gpio_v4_4/src/xgpio_intr.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/gpio_v4_4/src/xgpio_intr.c new file mode 100644 index 0000000..acbb084 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/gpio_v4_4/src/xgpio_intr.c @@ -0,0 +1,290 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file xgpio_intr.c +* @addtogroup gpio_v4_4 +* @{ +* +* Implements GPIO interrupt processing functions for the XGpio driver. +* See xgpio.h for more information about the driver. +* +* The functions in this file require the hardware device to be built with +* interrupt capabilities. The functions will assert if called using hardware +* that does not have interrupt capabilities. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 2.00a jhl  11/26/03 Initial release
+* 2.11a mta  03/21/07 Updated to new coding style
+* 2.12a sv   06/05/08 Updated driver to fix the XGpio_InterruptDisable function
+*		      to properly update the Interrupt Enable register
+* 3.00a sv   11/21/09 Updated to use HAL Processor APIs. Renamed the macros
+*		      XGpio_mWriteReg to XGpio_WriteReg, and XGpio_mReadReg
+*		      to XGpio_ReadReg.
+
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ +#include "xgpio.h" + + +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Variable Definitions ****************************/ + +/************************** Function Prototypes *****************************/ + + +/****************************************************************************/ +/** +* Enable the interrupt output signal. Interrupts enabled through +* XGpio_InterruptEnable() will not be passed through until the global enable +* bit is set by this function. This function is designed to allow all +* interrupts (both channels) to be enabled easily for exiting a critical +* section. This function will assert if the hardware device has not been +* built with interrupt capabilities. +* +* @param InstancePtr is the GPIO instance to operate on. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XGpio_InterruptGlobalEnable(XGpio *InstancePtr) +{ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(InstancePtr->InterruptPresent == TRUE); + + XGpio_WriteReg(InstancePtr->BaseAddress, XGPIO_GIE_OFFSET, + XGPIO_GIE_GINTR_ENABLE_MASK); +} + + +/****************************************************************************/ +/** +* Disable the interrupt output signal. Interrupts enabled through +* XGpio_InterruptEnable() will no longer be passed through until the global +* enable bit is set by XGpio_InterruptGlobalEnable(). This function is +* designed to allow all interrupts (both channels) to be disabled easily for +* entering a critical section. This function will assert if the hardware +* device has not been built with interrupt capabilities. +* +* @param InstancePtr is the GPIO instance to operate on. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XGpio_InterruptGlobalDisable(XGpio *InstancePtr) +{ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(InstancePtr->InterruptPresent == TRUE); + + + XGpio_WriteReg(InstancePtr->BaseAddress, XGPIO_GIE_OFFSET, 0x0); + +} + + +/****************************************************************************/ +/** +* Enable interrupts. The global interrupt must also be enabled by calling +* XGpio_InterruptGlobalEnable() for interrupts to occur. This function will +* assert if the hardware device has not been built with interrupt capabilities. +* +* @param InstancePtr is the GPIO instance to operate on. +* @param Mask is the mask to enable. Bit positions of 1 are enabled. +* This mask is formed by OR'ing bits from XGPIO_IR* bits which +* are contained in xgpio_l.h. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XGpio_InterruptEnable(XGpio *InstancePtr, u32 Mask) +{ + u32 Register; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(InstancePtr->InterruptPresent == TRUE); + + /* + * Read the interrupt enable register and only enable the specified + * interrupts without disabling or enabling any others. + */ + + Register = XGpio_ReadReg(InstancePtr->BaseAddress, XGPIO_IER_OFFSET); + XGpio_WriteReg(InstancePtr->BaseAddress, XGPIO_IER_OFFSET, + Register | Mask); + +} + + +/****************************************************************************/ +/** +* Disable interrupts. This function allows specific interrupts for each +* channel to be disabled. This function will assert if the hardware device +* has not been built with interrupt capabilities. +* +* @param InstancePtr is the GPIO instance to operate on. +* @param Mask is the mask to disable. Bits set to 1 are disabled. This +* mask is formed by OR'ing bits from XGPIO_IR* bits which are +* contained in xgpio_l.h. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XGpio_InterruptDisable(XGpio *InstancePtr, u32 Mask) +{ + u32 Register; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(InstancePtr->InterruptPresent == TRUE); + + /* + * Read the interrupt enable register and only disable the specified + * interrupts without enabling or disabling any others. + */ + Register = XGpio_ReadReg(InstancePtr->BaseAddress, XGPIO_IER_OFFSET); + XGpio_WriteReg(InstancePtr->BaseAddress, XGPIO_IER_OFFSET, + Register & (~Mask)); + +} + +/****************************************************************************/ +/** +* Clear pending interrupts with the provided mask. This function should be +* called after the software has serviced the interrupts that are pending. +* This function will assert if the hardware device has not been built with +* interrupt capabilities. +* +* @param InstancePtr is the GPIO instance to operate on. +* @param Mask is the mask to clear pending interrupts for. Bit positions +* of 1 are cleared. This mask is formed by OR'ing bits from +* XGPIO_IR* bits which are contained in xgpio_l.h. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XGpio_InterruptClear(XGpio * InstancePtr, u32 Mask) +{ + u32 Register; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(InstancePtr->InterruptPresent == TRUE); + + /* + * Read the interrupt status register and only clear the interrupts + * that are specified without affecting any others. Since the register + * is a toggle on write, make sure any bits to be written are already + * set. + */ + Register = XGpio_ReadReg(InstancePtr->BaseAddress, XGPIO_ISR_OFFSET); + XGpio_WriteReg(InstancePtr->BaseAddress, XGPIO_ISR_OFFSET, + Register & Mask); + + +} + + +/****************************************************************************/ +/** +* Returns the interrupt enable mask. This function will assert if the +* hardware device has not been built with interrupt capabilities. +* +* @param InstancePtr is the GPIO instance to operate on. +* +* @return A mask of bits made from XGPIO_IR* bits which are contained in +* xgpio_l.h. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +u32 XGpio_InterruptGetEnabled(XGpio * InstancePtr) +{ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(InstancePtr->InterruptPresent == TRUE); + + return XGpio_ReadReg(InstancePtr->BaseAddress, XGPIO_IER_OFFSET); +} + + +/****************************************************************************/ +/** +* Returns the status of interrupt signals. Any bit in the mask set to 1 +* indicates that the channel associated with the bit has asserted an interrupt +* condition. This function will assert if the hardware device has not been +* built with interrupt capabilities. +* +* @param InstancePtr is the GPIO instance to operate on. +* +* @return A pointer to a mask of bits made from XGPIO_IR* bits which are +* contained in xgpio_l.h. +* +* @note +* +* The interrupt status indicates the status of the device irregardless if +* the interrupts from the devices have been enabled or not through +* XGpio_InterruptEnable(). +* +*****************************************************************************/ +u32 XGpio_InterruptGetStatus(XGpio * InstancePtr) +{ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(InstancePtr->InterruptPresent == TRUE); + + + return XGpio_ReadReg(InstancePtr->BaseAddress, XGPIO_ISR_OFFSET); +} +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/gpio_v4_4/src/xgpio_l.h b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/gpio_v4_4/src/xgpio_l.h new file mode 100644 index 0000000..be6d04a --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/gpio_v4_4/src/xgpio_l.h @@ -0,0 +1,189 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xgpio_l.h +* @addtogroup gpio_v4_4 +* @{ +* +* This header file contains identifiers and driver functions (or +* macros) that can be used to access the device. The user should refer to the +* hardware device specification for more details of the device operation. +* +* The macros that are available in this file use a multiply to calculate the +* addresses of registers. The user can control whether that multiply is done +* at run time or at compile time. A constant passed as the channel parameter +* will cause the multiply to be done at compile time. A variable passed as the +* channel parameter will cause it to occur at run time. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a jhl  04/24/02 First release of low level driver
+* 2.00a jhl  11/26/03 Added support for dual channels and interrupts. This
+*                     change required the functions to be changed such that
+*                     the interface is not compatible with previous versions.
+*                     See the examples in the example directory for macros
+*                     to help compile an application that was designed for
+*                     previous versions of the driver. The interrupt registers
+*                     are accessible using the ReadReg and WriteReg macros and
+*                     a channel parameter was added to the other macros.
+* 2.11a mta  03/21/07 Updated to new coding style
+* 2.12a sv   11/21/07 Updated driver to support access through DCR bus.
+* 3.00a sv   11/21/09 Renamed the macros XGpio_mWriteReg to XGpio_WriteReg
+*		      XGpio_mReadReg to XGpio_ReadReg.
+*		      Removed the macros XGpio_mSetDataDirection,
+*		      XGpio_mGetDataReg and XGpio_mSetDataReg. Users
+*		      should use XGpio_WriteReg/XGpio_ReadReg to achieve the
+*		      same functionality.
+* 4.1  lks   11/18/15 Removed support for DCR bridge
+* 
+* +******************************************************************************/ + +#ifndef XGPIO_L_H /* prevent circular inclusions */ +#define XGPIO_L_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_io.h" + + +/************************** Constant Definitions *****************************/ + +/** @name Registers + * + * Register offsets for this device. + * @{ + */ +#define XGPIO_DATA_OFFSET 0x0 /**< Data register for 1st channel */ +#define XGPIO_TRI_OFFSET 0x4 /**< I/O direction reg for 1st channel */ +#define XGPIO_DATA2_OFFSET 0x8 /**< Data register for 2nd channel */ +#define XGPIO_TRI2_OFFSET 0xC /**< I/O direction reg for 2nd channel */ + +#define XGPIO_GIE_OFFSET 0x11C /**< Glogal interrupt enable register */ +#define XGPIO_ISR_OFFSET 0x120 /**< Interrupt status register */ +#define XGPIO_IER_OFFSET 0x128 /**< Interrupt enable register */ + +/* @} */ + +/* The following constant describes the offset of each channels data and + * tristate register from the base address. + */ +#define XGPIO_CHAN_OFFSET 8 + +/** @name Interrupt Status and Enable Register bitmaps and masks + * + * Bit definitions for the interrupt status register and interrupt enable + * registers. + * @{ + */ +#define XGPIO_IR_MASK 0x3 /**< Mask of all bits */ +#define XGPIO_IR_CH1_MASK 0x1 /**< Mask for the 1st channel */ +#define XGPIO_IR_CH2_MASK 0x2 /**< Mask for the 2nd channel */ +/*@}*/ + + +/** @name Global Interrupt Enable Register bitmaps and masks + * + * Bit definitions for the Global Interrupt Enable register + * @{ + */ +#define XGPIO_GIE_GINTR_ENABLE_MASK 0x80000000 +/*@}*/ + + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + +#define XGpio_In32 Xil_In32 +#define XGpio_Out32 Xil_Out32 + + +/****************************************************************************/ +/** +* +* Write a value to a GPIO register. A 32 bit write is performed. If the +* GPIO core is implemented in a smaller width, only the least significant data +* is written. +* +* @param BaseAddress is the base address of the GPIO device. +* @param RegOffset is the register offset from the base to write to. +* @param Data is the data written to the register. +* +* @return None. +* +* @note C-style signature: +* void XGpio_WriteReg(u32 BaseAddress, u32 RegOffset, u32 Data) +* +****************************************************************************/ +#define XGpio_WriteReg(BaseAddress, RegOffset, Data) \ + XGpio_Out32((BaseAddress) + (RegOffset), (u32)(Data)) + +/****************************************************************************/ +/** +* +* Read a value from a GPIO register. A 32 bit read is performed. If the +* GPIO core is implemented in a smaller width, only the least +* significant data is read from the register. The most significant data +* will be read as 0. +* +* @param BaseAddress is the base address of the GPIO device. +* @param RegOffset is the register offset from the base to read from. +* +* @return Data read from the register. +* +* @note C-style signature: +* u32 XGpio_ReadReg(u32 BaseAddress, u32 RegOffset) +* +****************************************************************************/ +#define XGpio_ReadReg(BaseAddress, RegOffset) \ + XGpio_In32((BaseAddress) + (RegOffset)) + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/gpio_v4_4/src/xgpio_selftest.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/gpio_v4_4/src/xgpio_selftest.c new file mode 100644 index 0000000..50d8d4f --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/gpio_v4_4/src/xgpio_selftest.c @@ -0,0 +1,106 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file xgpio_selftest.c +* @addtogroup gpio_v4_4 +* @{ +* +* The implementation of the XGpio driver's self test function. +* See xgpio.h for more information about the driver. +* +* @note +* +* None +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a rmm  02/04/02 First release
+* 2.00a jhl  01/13/04 Addition of dual channels and interrupts.
+* 2.11a mta  03/21/07 Updated to new coding style
+* 3.00a sv   11/21/09 Updated to use HAL Processor APIs.
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ +#include "xgpio.h" + +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Variable Definitions ****************************/ + +/************************** Function Prototypes *****************************/ + + +/******************************************************************************/ +/** +* Run a self-test on the driver/device. This function does a minimal test +* in which the data register is read. It only does a read without any kind +* of test because the hardware has been parameterized such that it may be only +* an input such that the state of the inputs won't be known. +* +* All other hardware features of the device are not guaranteed to be in the +* hardware since they are parameterizable. +* +* +* @param InstancePtr is a pointer to the XGpio instance to be worked on. +* This parameter must have been previously initialized with +* XGpio_Initialize(). +* +* @return XST_SUCCESS always. If the GPIO device was not present in the +* hardware a bus error could be generated. Other indicators of a +* bus error, such as registers in bridges or buses, may be +* necessary to determine if this function caused a bus error. +* +* @note None. +* +******************************************************************************/ +int XGpio_SelfTest(XGpio * InstancePtr) +{ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read from the data register of channel 1 which is always guaranteed + * to be in the hardware device. Since the data may be configured as + * all inputs, there is not way to guarantee the value read so don't + * test it. + */ + (void) XGpio_DiscreteRead(InstancePtr, 1); + + return (XST_SUCCESS); +} +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/gpio_v4_4/src/xgpio_sinit.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/gpio_v4_4/src/xgpio_sinit.c new file mode 100644 index 0000000..0be44bd --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/gpio_v4_4/src/xgpio_sinit.c @@ -0,0 +1,155 @@ +/****************************************************************************** +* +* Copyright (C) 2003 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file xgpio_sinit.c +* @addtogroup gpio_v4_4 +* @{ +* +* The implementation of the XGpio driver's static initialzation +* functionality. +* +* @note +* +* None +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 2.01a jvb  10/13/05 First release
+* 2.11a mta  03/21/07 Updated to new coding style
+* 4.0   sha  07/15/15 Defined macro XPAR_XGPIO_NUM_INSTANCES if not
+*		      defined in xparameters.h
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ + +#include "xstatus.h" +#include "xparameters.h" +#include "xgpio_i.h" + +/************************** Constant Definitions ****************************/ + +#ifndef XPAR_XGPIO_NUM_INSTANCES +#define XPAR_XGPIO_NUM_INSTANCES 0 +#endif + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Variable Definitions ****************************/ + + +/************************** Function Prototypes *****************************/ + + +/******************************************************************************/ +/** +* Lookup the device configuration based on the unique device ID. The table +* ConfigTable contains the configuration info for each device in the system. +* +* @param DeviceId is the device identifier to lookup. +* +* @return +* - A pointer of data type XGpio_Config which points to the +* device configuration if DeviceID is found. +* - NULL if DeviceID is not found. +* +* @note None. +* +******************************************************************************/ +XGpio_Config *XGpio_LookupConfig(u16 DeviceId) +{ + XGpio_Config *CfgPtr = NULL; + + int Index; + + for (Index = 0; Index < XPAR_XGPIO_NUM_INSTANCES; Index++) { + if (XGpio_ConfigTable[Index].DeviceId == DeviceId) { + CfgPtr = &XGpio_ConfigTable[Index]; + break; + } + } + + return CfgPtr; +} + + +/****************************************************************************/ +/** +* Initialize the XGpio instance provided by the caller based on the +* given DeviceID. +* +* Nothing is done except to initialize the InstancePtr. +* +* @param InstancePtr is a pointer to an XGpio instance. The memory the +* pointer references must be pre-allocated by the caller. Further +* calls to manipulate the instance/driver through the XGpio API +* must be made with this pointer. +* @param DeviceId is the unique id of the device controlled by this XGpio +* instance. Passing in a device id associates the generic XGpio +* instance to a specific device, as chosen by the caller or +* application developer. +* +* @return +* - XST_SUCCESS if the initialization was successfull. +* - XST_DEVICE_NOT_FOUND if the device configuration data was not +* found for a device with the supplied device ID. +* +* @note None. +* +*****************************************************************************/ +int XGpio_Initialize(XGpio * InstancePtr, u16 DeviceId) +{ + XGpio_Config *ConfigPtr; + + /* + * Assert arguments + */ + Xil_AssertNonvoid(InstancePtr != NULL); + + /* + * Lookup configuration data in the device configuration table. + * Use this configuration info down below when initializing this + * driver. + */ + ConfigPtr = XGpio_LookupConfig(DeviceId); + if (ConfigPtr == (XGpio_Config *) NULL) { + InstancePtr->IsReady = 0; + return (XST_DEVICE_NOT_FOUND); + } + + return XGpio_CfgInitialize(InstancePtr, ConfigPtr, + ConfigPtr->BaseAddress); +} +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/gpiops_v3_5/src/Makefile b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/gpiops_v3_5/src/Makefile new file mode 100644 index 0000000..8601ce4 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/gpiops_v3_5/src/Makefile @@ -0,0 +1,40 @@ +COMPILER= +ARCHIVER= +CP=cp +COMPILER_FLAGS= +EXTRA_COMPILER_FLAGS= +LIB=libxil.a + +CC_FLAGS = $(COMPILER_FLAGS) +ECC_FLAGS = $(EXTRA_COMPILER_FLAGS) + +RELEASEDIR=../../../lib +INCLUDEDIR=../../../include +INCLUDES=-I./. -I${INCLUDEDIR} + +OUTS = *.o + +LIBSOURCES:=*.c +INCLUDEFILES:=*.h + +OBJECTS = $(addsuffix .o, $(basename $(wildcard *.c))) + +libs: banner xgpiops_libs clean + +%.o: %.c + ${COMPILER} $(CC_FLAGS) $(ECC_FLAGS) $(INCLUDES) -o $@ $< + +banner: + echo "Compiling gpiops" + +xgpiops_libs: ${OBJECTS} + $(ARCHIVER) -r ${RELEASEDIR}/${LIB} ${OBJECTS} + +.PHONY: include +include: xgpiops_includes + +xgpiops_includes: + ${CP} ${INCLUDEFILES} ${INCLUDEDIR} + +clean: + rm -rf ${OBJECTS} diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/gpiops_v3_5/src/xgpiops.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/gpiops_v3_5/src/xgpiops.c new file mode 100644 index 0000000..39bcc94 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/gpiops_v3_5/src/xgpiops.c @@ -0,0 +1,830 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xgpiops.c +* @addtogroup gpiops_v3_5 +* @{ +* +* The XGpioPs driver. Functions in this file are the minimum required functions +* for this driver. See xgpiops.h for a detailed description of the driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a sv   01/15/10 First Release
+* 1.01a sv   04/15/12 Removed the APIs XGpioPs_SetMode, XGpioPs_SetModePin
+*                     XGpioPs_GetMode, XGpioPs_GetModePin as they are not
+*		      relevant to Zynq device. The interrupts are disabled
+*		      for output pins on all banks during initialization.
+* 2.1   hk   04/29/14 Use Input data register DATA_RO for read. CR# 771667.
+* 3.00  kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.1	kvn  04/13/15 Add support for Zynq Ultrascale+ MP. CR# 856980.
+* 3.1   aru  07/13/18 Resolved doxygen reported warnings. CR# 1006331.
+* 3.4   aru  08/17/18 Resolved MISRA-C mandatory violations. CR# 1007751
+* 3.5   sne  03/01/19 Fixes violations according to MISRAC-2012
+*                     in saftey mode and modified the code such as
+*                     Use of mixed mode arithmetic,Declared the poiner param
+*                     as Pointer to const,Casting operation to a pointer,
+*                     Literal value requires a U suffix.
+* 3.5   sne  03/13/19 Added Versal support.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xgpiops.h" + +/************************** Constant Definitions *****************************/ +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Variable Definitions *****************************/ + + +/************************** Function Prototypes ******************************/ + +extern void StubHandler(void *CallBackRef, u32 Bank, u32 Status); + +/*****************************************************************************/ +/* +* +* This function initializes a XGpioPs instance/driver. +* All members of the XGpioPs instance structure are initialized and +* StubHandlers are assigned to the Bank Status Handlers. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param ConfigPtr points to the XGpioPs device configuration structure. +* @param EffectiveAddr is the device base address in the virtual memory +* address space. If the address translation is not used then the +* physical address should be passed. +* Unexpected errors may occur if the address mapping is changed +* after this function is invoked. +* +* @return XST_SUCCESS always. +* +* @note None. +* +******************************************************************************/ +s32 XGpioPs_CfgInitialize(XGpioPs *InstancePtr, const XGpioPs_Config *ConfigPtr, + u32 EffectiveAddr) +{ + s32 Status = XST_SUCCESS; + u8 i; + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(ConfigPtr != NULL); + Xil_AssertNonvoid(EffectiveAddr != (u32)0); + /* + * Set some default values for instance data, don't indicate the device + * is ready to use until everything has been initialized successfully. + */ + InstancePtr->IsReady = 0U; + InstancePtr->GpioConfig.BaseAddr = EffectiveAddr; + InstancePtr->GpioConfig.DeviceId = ConfigPtr->DeviceId; + InstancePtr->Handler = (XGpioPs_Handler)StubHandler; + InstancePtr->Platform = XGetPlatform_Info(); + + /* Initialize the Bank data based on platform */ + if (InstancePtr->Platform == (u32)XPLAT_ZYNQ_ULTRA_MP) { + /* + * Max pins in the ZynqMP GPIO device + * 0 - 25, Bank 0 + * 26 - 51, Bank 1 + * 52 - 77, Bank 2 + * 78 - 109, Bank 3 + * 110 - 141, Bank 4 + * 142 - 173, Bank 5 + */ + InstancePtr->MaxPinNum = (u32)174; + InstancePtr->MaxBanks = (u8)6; + } + else if (InstancePtr->Platform == (u32)XPLAT_versal) + { + if(InstancePtr->PmcGpio == (u32)FALSE) + { + /* Max pins in the PS_GPIO devices + * 0 -25, Bank 0 + * 26-57, Bank 3 + */ + InstancePtr->MaxPinNum = (u32)58; + InstancePtr->MaxBanks = (u8)4; + } + else + { + /* Max pins in the PMC_GPIO devices + * 0 - 25,Bank 0 + * 26 - 51,Bank 1 + * 52 - 83,Bank 3 + * 84 - 115, Bank 4 + */ + InstancePtr->MaxPinNum = (u32)116; + InstancePtr->MaxBanks = (u8)5; + } + } + else { + /* + * Max pins in the GPIO device + * 0 - 31, Bank 0 + * 32 - 53, Bank 1 + * 54 - 85, Bank 2 + * 86 - 117, Bank 3 + */ + InstancePtr->MaxPinNum = (u32)118; + InstancePtr->MaxBanks = (u8)4; + } + + /* + * By default, interrupts are not masked in GPIO. Disable + * interrupts for all pins in all the 4 banks. + */ + for (i=(u8)0U;iMaxBanks;i++) { + if (InstancePtr->Platform == XPLAT_versal){ + if(InstancePtr->PmcGpio == (u32)FALSE) + { + if((i== (u8)XGPIOPS_ONE)||(i== (u8)XGPIOPS_TWO)) + { + continue; + } + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(i) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTDIS_OFFSET, 0xFFFFFFFFU); + } + else + { + if(i==(u32)XGPIOPS_TWO) + { + continue; + } + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(i) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTDIS_OFFSET, 0xFFFFFFFFU); + + } + } + else + { + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(i) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTDIS_OFFSET, 0xFFFFFFFFU); + } + } + + /* Indicate the component is now ready to use. */ + InstancePtr->IsReady = XIL_COMPONENT_IS_READY; + + return Status; +} + +/****************************************************************************/ +/** +* +* Read the Data register of the specified GPIO bank. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Bank is the bank number of the GPIO to operate on. +* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. +* +* @return Current value of the Data register. +* +* @note This function is used for reading the state of all the GPIO pins +* of specified bank. +* +*****************************************************************************/ +u32 XGpioPs_Read(const XGpioPs *InstancePtr, u8 Bank) +{ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(Bank < InstancePtr->MaxBanks); +#ifdef versal + if(InstancePtr->PmcGpio == TRUE) { + Xil_AssertNonvoid(Bank != XGPIOPS_TWO); + } else { + Xil_AssertNonvoid((Bank !=XGPIOPS_ONE) && (Bank !=XGPIOPS_TWO)); + } +#endif + + return XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_DATA_BANK_OFFSET) + + XGPIOPS_DATA_RO_OFFSET); +} + +/****************************************************************************/ +/** +* +* Read Data from the specified pin. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Pin is the pin number for which the data has to be read. +* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. +* See xgpiops.h for the mapping of the pin numbers in the banks. +* +* @return Current value of the Pin (0 or 1). +* +* @note This function is used for reading the state of the specified +* GPIO pin. +* +*****************************************************************************/ +u32 XGpioPs_ReadPin(const XGpioPs *InstancePtr, u32 Pin) +{ + u8 Bank; + u8 PinNumber; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(Pin < InstancePtr->MaxPinNum); + + /* Get the Bank number and Pin number within the bank. */ +#ifdef versal + XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); +#else + XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber); +#endif + return (XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_DATA_BANK_OFFSET) + + XGPIOPS_DATA_RO_OFFSET) >> (u32)PinNumber) & (u32)1; + +} + +/****************************************************************************/ +/** +* +* Write to the Data register of the specified GPIO bank. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Bank is the bank number of the GPIO to operate on. +* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. +* @param Data is the value to be written to the Data register. +* +* @return None. +* +* @note This function is used for writing to all the GPIO pins of +* the bank. The previous state of the pins is not maintained. +* +*****************************************************************************/ +void XGpioPs_Write(const XGpioPs *InstancePtr, u8 Bank, u32 Data) +{ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Bank < InstancePtr->MaxBanks); +#ifdef versal + if(InstancePtr->PmcGpio == TRUE) { + Xil_AssertVoid(Bank != XGPIOPS_TWO); + } else { + Xil_AssertVoid((Bank !=XGPIOPS_ONE) && (Bank !=XGPIOPS_TWO)); + } +#endif + + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_DATA_BANK_OFFSET) + + XGPIOPS_DATA_OFFSET, Data); +} + +/****************************************************************************/ +/** +* +* Write data to the specified pin. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Pin is the pin number to which the Data is to be written. +* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. +* @param Data is the data to be written to the specified pin (0 or 1). +* +* @return None. +* +* @note This function does a masked write to the specified pin of +* the specified GPIO bank. The previous state of other pins +* is maintained. +* +*****************************************************************************/ +void XGpioPs_WritePin(const XGpioPs *InstancePtr, u32 Pin, u32 Data) +{ + u32 RegOffset; + u32 Value; + u8 Bank; + u8 PinNumber; + u32 DataVar = Data; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Pin < InstancePtr->MaxPinNum); + + /* Get the Bank number and Pin number within the bank. */ +#ifdef versal + XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); +#else + XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber); +#endif + + if (PinNumber > 15U) { + /* There are only 16 data bits in bit maskable register. */ + PinNumber -= (u8)16; + RegOffset = XGPIOPS_DATA_MSW_OFFSET; + } else { + RegOffset = XGPIOPS_DATA_LSW_OFFSET; + } + + /* + * Get the 32 bit value to be written to the Mask/Data register where + * the upper 16 bits is the mask and lower 16 bits is the data. + */ + DataVar &= (u32)0x01; + Value = ~((u32)1 << (PinNumber + 16U)) & ((DataVar << PinNumber) | 0xFFFF0000U); + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_DATA_MASK_OFFSET) + + RegOffset, Value); + +} + + + +/****************************************************************************/ +/** +* +* Set the Direction of the pins of the specified GPIO Bank. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Bank is the bank number of the GPIO to operate on. +* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. +* @param Direction is the 32 bit mask of the Pin direction to be set for +* all the pins in the Bank. Bits with 0 are set to Input mode, +* bits with 1 are set to Output Mode. +* +* @return None. +* +* @note This function is used for setting the direction of all the pins +* in the specified bank. The previous state of the pins is +* not maintained. +* +*****************************************************************************/ +void XGpioPs_SetDirection(const XGpioPs *InstancePtr, u8 Bank, u32 Direction) +{ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Bank < InstancePtr->MaxBanks); +#ifdef versal + if(InstancePtr->PmcGpio == TRUE) { + Xil_AssertVoid(Bank != XGPIOPS_TWO); + } else { + Xil_AssertVoid((Bank !=XGPIOPS_ONE) && (Bank !=XGPIOPS_TWO)); + } +#endif + + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_DIRM_OFFSET, Direction); +} + +/****************************************************************************/ +/** +* +* Set the Direction of the specified pin. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Pin is the pin number to which the Data is to be written. +* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. +* @param Direction is the direction to be set for the specified pin. +* Valid values are 0 for Input Direction, 1 for Output Direction. +* +* @return None. +* +*****************************************************************************/ +void XGpioPs_SetDirectionPin(const XGpioPs *InstancePtr, u32 Pin, u32 Direction) +{ + u8 Bank; + u8 PinNumber; + u32 DirModeReg; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Pin < InstancePtr->MaxPinNum); + Xil_AssertVoid(Direction <= (u32)1); + + /* Get the Bank number and Pin number within the bank. */ +#ifdef versal + XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); +#else + XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber); +#endif + DirModeReg = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_DIRM_OFFSET); + + if (Direction!=(u32)0) { /* Output Direction */ + DirModeReg |= ((u32)1 << (u32)PinNumber); + } else { /* Input Direction */ + DirModeReg &= ~ ((u32)1 << (u32)PinNumber); + } + + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_DIRM_OFFSET, DirModeReg); +} + +/****************************************************************************/ +/** +* +* Get the Direction of the pins of the specified GPIO Bank. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Bank is the bank number of the GPIO to operate on. +* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. +* +* @return Returns a 32 bit mask of the Direction register. Bits with 0 are +* in Input mode, bits with 1 are in Output Mode. +* +* @note None. +* +*****************************************************************************/ +u32 XGpioPs_GetDirection(const XGpioPs *InstancePtr, u8 Bank) +{ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(Bank < InstancePtr->MaxBanks); +#ifdef versal + if(InstancePtr->PmcGpio == TRUE) { + Xil_AssertNonvoid(Bank != XGPIOPS_TWO); + } else { + Xil_AssertNonvoid((Bank !=XGPIOPS_ONE) && (Bank !=XGPIOPS_TWO)); + } +#endif + + return XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_DIRM_OFFSET); +} + +/****************************************************************************/ +/** +* +* Get the Direction of the specified pin. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Pin is the pin number for which the Direction is to be +* retrieved. +* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. +* +* @return Direction of the specified pin. +* - 0 for Input Direction +* - 1 for Output Direction +* +* @note None. +* +*****************************************************************************/ +u32 XGpioPs_GetDirectionPin(const XGpioPs *InstancePtr, u32 Pin) +{ + u8 Bank; + u8 PinNumber; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(Pin < InstancePtr->MaxPinNum); + + /* Get the Bank number and Pin number within the bank. */ +#ifdef versal + XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); +#else + XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber); +#endif + + return (XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_DIRM_OFFSET) >> (u32)PinNumber) & (u32)1; +} + +/****************************************************************************/ +/** +* +* Set the Output Enable of the pins of the specified GPIO Bank. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Bank is the bank number of the GPIO to operate on. +* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. +* @param OpEnable is the 32 bit mask of the Output Enables to be set for +* all the pins in the Bank. The Output Enable of bits with 0 are +* disabled, the Output Enable of bits with 1 are enabled. +* +* @return None. +* +* @note This function is used for setting the Output Enables of all the +* pins in the specified bank. The previous state of the Output +* Enables is not maintained. +* +*****************************************************************************/ +void XGpioPs_SetOutputEnable(const XGpioPs *InstancePtr, u8 Bank, u32 OpEnable) +{ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Bank < InstancePtr->MaxBanks); +#ifdef versal + if(InstancePtr->PmcGpio == TRUE) { + Xil_AssertVoid(Bank != XGPIOPS_TWO); + } else { + Xil_AssertVoid((Bank !=XGPIOPS_ONE) && (Bank !=XGPIOPS_TWO)); + } +#endif + + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_OUTEN_OFFSET, OpEnable); +} + +/****************************************************************************/ +/** +* +* Set the Output Enable of the specified pin. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Pin is the pin number to which the Data is to be written. +* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. +* @param OpEnable specifies whether the Output Enable for the specified +* pin should be enabled. +* Valid values are 0 for Disabling Output Enable, +* 1 for Enabling Output Enable. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XGpioPs_SetOutputEnablePin(const XGpioPs *InstancePtr, u32 Pin, u32 OpEnable) +{ + u8 Bank; + u8 PinNumber; + u32 OpEnableReg; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Pin < InstancePtr->MaxPinNum); + Xil_AssertVoid(OpEnable <= (u32)1); + + /* Get the Bank number and Pin number within the bank. */ +#ifdef versal + XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); +#else + XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber); +#endif + + OpEnableReg = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_OUTEN_OFFSET); + + if (OpEnable != (u32)0) { /* Enable Output Enable */ + OpEnableReg |= ((u32)1 << (u32)PinNumber); + } else { /* Disable Output Enable */ + OpEnableReg &= ~ ((u32)1 << (u32)PinNumber); + } + + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_OUTEN_OFFSET, OpEnableReg); +} +/****************************************************************************/ +/** +* +* Get the Output Enable status of the pins of the specified GPIO Bank. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Bank is the bank number of the GPIO to operate on. +* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. +* +* @return Returns a a 32 bit mask of the Output Enable register. +* Bits with 0 are in Disabled state, bits with 1 are in +* Enabled State. +* +* @note None. +* +*****************************************************************************/ +u32 XGpioPs_GetOutputEnable(const XGpioPs *InstancePtr, u8 Bank) +{ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(Bank < InstancePtr->MaxBanks); +#ifdef versal + if(InstancePtr->PmcGpio == TRUE) { + Xil_AssertNonvoid(Bank != XGPIOPS_TWO); + } else { + Xil_AssertNonvoid((Bank !=XGPIOPS_ONE) && (Bank !=XGPIOPS_TWO)); + } +#endif + + return XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_OUTEN_OFFSET); +} + +/****************************************************************************/ +/** +* +* Get the Output Enable status of the specified pin. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Pin is the pin number for which the Output Enable status is to +* be retrieved. +* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. +* +* @return Output Enable of the specified pin. +* - 0 if Output Enable is disabled for this pin +* - 1 if Output Enable is enabled for this pin +* +* @note None. +* +*****************************************************************************/ +u32 XGpioPs_GetOutputEnablePin(const XGpioPs *InstancePtr, u32 Pin) +{ + u8 Bank; + u8 PinNumber; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(Pin < InstancePtr->MaxPinNum); + + /* Get the Bank number and Pin number within the bank. */ +#ifdef versal + XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); +#else + XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber); +#endif + + return (XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_OUTEN_OFFSET) >> (u32)PinNumber) & (u32)1; +} + +/****************************************************************************/ +/* +* +* Get the Bank number and the Pin number in the Bank, for the given PinNumber +* in the GPIO device. +* +* @param PinNumber is the Pin number in the GPIO device. +* @param BankNumber returns the Bank in which this GPIO pin is present. +* Valid values are 0 to XGPIOPS_MAX_BANKS - 1. +* @param PinNumberInBank returns the Pin Number within the Bank. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +#ifdef versal +void XGpioPs_GetBankPin(const XGpioPs *InstancePtr,u8 PinNumber, u8 *BankNumber, u8 *PinNumberInBank) +#else +void XGpioPs_GetBankPin(u8 PinNumber, u8 *BankNumber, u8 *PinNumberInBank) +#endif +{ + u32 XGpioPsPinTable[6] = {0}; +#ifdef versal + u8 i=(u8)0; +#endif + u32 Platform = XGetPlatform_Info(); + + if (Platform == (u32)XPLAT_ZYNQ_ULTRA_MP) { + /* + * This structure defines the mapping of the pin numbers to the banks when + * the driver APIs are used for working on the individual pins. + */ + + XGpioPsPinTable[0] = (u32)25; /* 0 - 25, Bank 0 */ + XGpioPsPinTable[1] = (u32)51; /* 26 - 51, Bank 1 */ + XGpioPsPinTable[2] = (u32)77; /* 52 - 77, Bank 2 */ + XGpioPsPinTable[3] = (u32)109; /* 78 - 109, Bank 3 */ + XGpioPsPinTable[4] = (u32)141; /* 110 - 141, Bank 4 */ + XGpioPsPinTable[5] = (u32)173; /* 142 - 173 Bank 5 */ + + *BankNumber = 0U; + while (*BankNumber < XGPIOPS_SIX) { + if (PinNumber <= XGpioPsPinTable[*BankNumber]) { + break; + } + (*BankNumber)++; + } + } +#ifdef versal + else if(Platform == XPLAT_versal) + { + if(InstancePtr->PmcGpio == (u32)(FALSE)) + { + XGpioPsPinTable[0] = (u32)25; /* 0 - 25, Bank 0 */ + XGpioPsPinTable[1] = (u32)57; /* 26 - 57, Bank 3 */ + *BankNumber =0U; + if(PinNumber <= XGpioPsPinTable[*BankNumber]) + { + *BankNumber = (u8)XGPIOPS_ZERO; + } + else + { + *BankNumber = (u8)XGPIOPS_THREE; + } + + } + else + { + XGpioPsPinTable[0] = (u32)25; /* 0 - 25, Bank 0 */ + XGpioPsPinTable[1] = (u32)51; /* 26 - 51, Bank 1 */ + XGpioPsPinTable[2] = (u32)83; /* 52 - 83, Bank 3 */ + XGpioPsPinTable[3] = (u32)115; /*84 - 115, Bank 4 */ + + *BankNumber =0U; + while(i < XGPIOPS_FOUR) + { + if(i <= (u8)XGPIOPS_ONE) + { + if (PinNumber <= XGpioPsPinTable[i]) + { + *BankNumber = (u8)i; + break; + } + i++; + } + else + { + if (PinNumber <= XGpioPsPinTable[i]) + { + *BankNumber = (u8)i+1U; + break; + } + i++; + } + + } + } + + } +#endif + else { + XGpioPsPinTable[0] = (u32)31; /* 0 - 31, Bank 0 */ + XGpioPsPinTable[1] = (u32)53; /* 32 - 53, Bank 1 */ + XGpioPsPinTable[2] = (u32)85; /* 54 - 85, Bank 2 */ + XGpioPsPinTable[3] = (u32)117; /* 86 - 117 Bank 3 */ + + *BankNumber = 0U; + while (*BankNumber < XGPIOPS_FOUR) { + if (PinNumber <= XGpioPsPinTable[*BankNumber]) { + break; + } + (*BankNumber)++; + } + } + if (*BankNumber == (u8)0) { + *PinNumberInBank = PinNumber; + } + +#ifdef versal + else if(Platform == XPLAT_versal) + { + if(InstancePtr->PmcGpio == (u32)(FALSE)) + { + *PinNumberInBank = (u8)((u32)PinNumber - (XGpioPsPinTable[0] + (u32)1)); + } + else { + if((*BankNumber ==(u8)XGPIOPS_THREE) || (*BankNumber ==(u8)XGPIOPS_FOUR)) + { + *PinNumberInBank = (u8)((u32)PinNumber % + (XGpioPsPinTable[*BankNumber - (u8)XGPIOPS_TWO] + (u32)1)); + } + else + { + *PinNumberInBank = (u8)((u32)PinNumber % + (XGpioPsPinTable[*BankNumber - (u8)1] + (u32)1)); + } + } + + } +#endif + + else { + *PinNumberInBank = (u8)((u32)PinNumber % + (XGpioPsPinTable[*BankNumber - (u8)1] + (u32)1)); + } +} +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/gpiops_v3_5/src/xgpiops.h b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/gpiops_v3_5/src/xgpiops.h new file mode 100644 index 0000000..d0ff132 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/gpiops_v3_5/src/xgpiops.h @@ -0,0 +1,283 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xgpiops.h +* @addtogroup gpiops_v3_5 +* @{ +* @details +* +* The Xilinx PS GPIO driver. This driver supports the Xilinx PS GPIO +* Controller. +* +* The GPIO Controller supports the following features: +* - 4 banks +* - Masked writes (There are no masked reads) +* - Bypass mode +* - Configurable Interrupts (Level/Edge) +* +* This driver is intended to be RTOS and processor independent. Any needs for +* dynamic memory management, threads or thread mutual exclusion, virtual +* memory, or cache control must be satisfied by the layer above this driver. + +* This driver supports all the features listed above, if applicable. +* +* Driver Description +* +* The device driver enables higher layer software (e.g., an application) to +* communicate to the GPIO. +* +* Interrupts +* +* The driver provides interrupt management functions and an interrupt handler. +* Users of this driver need to provide callback functions. An interrupt handler +* example is available with the driver. +* +* Threads +* +* This driver is not thread safe. Any needs for threads or thread mutual +* exclusion must be satisfied by the layer above this driver. +* +* Asserts +* +* Asserts are used within all Xilinx drivers to enforce constraints on argument +* values. Asserts can be turned off on a system-wide basis by defining, at +* compile time, the NDEBUG identifier. By default, asserts are turned on and it +* is recommended that users leave asserts on during development. +* +* Building the driver +* +* The XGpioPs driver is composed of several source files. This allows the user +* to build and link only those parts of the driver that are necessary. +*

+* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a sv   01/15/10 First Release
+* 1.01a sv   04/15/12 Removed the APIs XGpioPs_SetMode, XGpioPs_SetModePin
+*                     XGpioPs_GetMode, XGpioPs_GetModePin as they are not
+*		      relevant to Zynq device.The interrupts are disabled
+*		      for output pins on all banks during initialization.
+* 1.02a hk   08/22/13 Added low level reset API
+* 2.1   hk   04/29/14 Use Input data register DATA_RO for read. CR# 771667.
+* 2.2	sk	 10/13/14 Used Pin number in Bank instead of pin number
+* 					  passed to APIs. CR# 822636
+* 3.00  kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.1	kvn  04/13/15 Add support for Zynq Ultrascale+ MP. CR# 856980.
+*       ms   03/17/17 Added readme.txt file in examples folder for doxygen
+*                     generation.
+*       ms   04/05/17 Added tabspace for return statements in functions of
+*                     gpiops examples for proper documentation while
+*                     generating doxygen.
+* 3.3   ms   04/17/17 Added notes about gpio input and output pin description
+*                     for zcu102 and zc702 boards in polled and interrupt
+*                     example, configured Interrupt pin to input pin for
+*                     proper functioning of interrupt example.
+* 3.4   aru  08/17/18 Resolved MISRA-C mandatory violations. CR# 1007751
+* 3.5   sne  03/01/19 Fixes violations according to MISRAC-2012
+*                     in saftey mode and modified the code such as
+*                     Use of mixed mode arithmetic,Declared the poiner param
+*                     as Pointer to const,Casting operation to a pointer,
+*                     Literal value requires a U suffix.
+* 3.5   sne  03/14/19 Added Versal support.
+* 
+* +******************************************************************************/ +#ifndef XGPIOPS_H /* prevent circular inclusions */ +#define XGPIOPS_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xstatus.h" +#include "xgpiops_hw.h" +#include "xplatform_info.h" + +/************************** Constant Definitions *****************************/ + +/** @name Interrupt types + * @{ + * The following constants define the interrupt types that can be set for each + * GPIO pin. + */ +#define XGPIOPS_IRQ_TYPE_EDGE_RISING 0x00U /**< Interrupt on Rising edge */ +#define XGPIOPS_IRQ_TYPE_EDGE_FALLING 0x01U /**< Interrupt Falling edge */ +#define XGPIOPS_IRQ_TYPE_EDGE_BOTH 0x02U /**< Interrupt on both edges */ +#define XGPIOPS_IRQ_TYPE_LEVEL_HIGH 0x03U /**< Interrupt on high level */ +#define XGPIOPS_IRQ_TYPE_LEVEL_LOW 0x04U /**< Interrupt on low level */ +/*@}*/ + +#define XGPIOPS_BANK_MAX_PINS (u32)32 /**< Max pins in a GPIO bank */ +#define XGPIOPS_BANK0 0x00U /**< GPIO Bank 0 */ +#define XGPIOPS_BANK1 0x01U /**< GPIO Bank 1 */ +#define XGPIOPS_BANK2 0x02U /**< GPIO Bank 2 */ +#define XGPIOPS_BANK3 0x03U /**< GPIO Bank 3 */ + +#ifdef XPAR_PSU_GPIO_0_BASEADDR +#define XGPIOPS_BANK4 0x04U /**< GPIO Bank 4 */ +#define XGPIOPS_BANK5 0x05U /**< GPIO Bank 5 */ +#endif + +#define XGPIOPS_MAX_BANKS_ZYNQMP 0x06U /**< Max banks in a + * Zynq Ultrascale+ MP GPIO device + */ +#define XGPIOPS_MAX_BANKS 0x04U /**< Max banks in a Zynq GPIO device */ + +#define XGPIOPS_DEVICE_MAX_PIN_NUM_ZYNQMP (u32)174 /**< Max pins in the + * Zynq Ultrascale+ MP GPIO device + * 0 - 25, Bank 0 + * 26 - 51, Bank 1 + * 52 - 77, Bank 2 + * 78 - 109, Bank 3 + * 110 - 141, Bank 4 + * 142 - 173, Bank 5 + */ +#define XGPIOPS_DEVICE_MAX_PIN_NUM (u32)118 /**< Max pins in the Zynq GPIO device + * 0 - 31, Bank 0 + * 32 - 53, Bank 1 + * 54 - 85, Bank 2 + * 86 - 117, Bank 3 + */ + +/**************************** Type Definitions *******************************/ + +/****************************************************************************/ +/** + * This handler data type allows the user to define a callback function to + * handle the interrupts for the GPIO device. The application using this + * driver is expected to define a handler of this type, to support interrupt + * driven mode. The handler executes in an interrupt context such that minimal + * processing should be performed. + * + * @param CallBackRef is a callback reference passed in by the upper layer + * when setting the callback functions for a GPIO bank. It is + * passed back to the upper layer when the callback is invoked. Its + * type is not important to the driver component, so it is a void + * pointer. + * @param Bank is the bank for which the interrupt status has changed. + * @param Status is the Interrupt status of the GPIO bank. + * + *****************************************************************************/ +typedef void (*XGpioPs_Handler) (void *CallBackRef, u32 Bank, u32 Status); + +/** + * This typedef contains configuration information for a device. + */ +typedef struct { + u16 DeviceId; /**< Unique ID of device */ + u32 BaseAddr; /**< Register base address */ +} XGpioPs_Config; + +/** + * The XGpioPs driver instance data. The user is required to allocate a + * variable of this type for the GPIO device in the system. A pointer + * to a variable of this type is then passed to the driver API functions. + */ +typedef struct { + XGpioPs_Config GpioConfig; /**< Device configuration */ + u32 IsReady; /**< Device is initialized and ready */ + XGpioPs_Handler Handler; /**< Status handlers for all banks */ + void *CallBackRef; /**< Callback ref for bank handlers */ + u32 Platform; /**< Platform data */ + u32 MaxPinNum; /**< Max pins in the GPIO device */ + u8 MaxBanks; /**< Max banks in a GPIO device */ + u32 PmcGpio; /**< Flag for accessing PS GPIO for versal*/ +} XGpioPs; + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/* Functions in xgpiops.c */ +s32 XGpioPs_CfgInitialize(XGpioPs *InstancePtr, const XGpioPs_Config *ConfigPtr, + u32 EffectiveAddr); + +/* Bank APIs in xgpiops.c */ +u32 XGpioPs_Read(const XGpioPs *InstancePtr, u8 Bank); +void XGpioPs_Write(const XGpioPs *InstancePtr, u8 Bank, u32 Data); +void XGpioPs_SetDirection(const XGpioPs *InstancePtr, u8 Bank, u32 Direction); +u32 XGpioPs_GetDirection(const XGpioPs *InstancePtr, u8 Bank); +void XGpioPs_SetOutputEnable(const XGpioPs *InstancePtr, u8 Bank, u32 OpEnable); +u32 XGpioPs_GetOutputEnable(const XGpioPs *InstancePtr, u8 Bank); +#ifdef versal +void XGpioPs_GetBankPin(const XGpioPs *InstancePtr,u8 PinNumber,u8 *BankNumber, u8 *PinNumberInBank); +#else +void XGpioPs_GetBankPin(u8 PinNumber,u8 *BankNumber, u8 *PinNumberInBank); +#endif + +/* Pin APIs in xgpiops.c */ +u32 XGpioPs_ReadPin(const XGpioPs *InstancePtr, u32 Pin); +void XGpioPs_WritePin(const XGpioPs *InstancePtr, u32 Pin, u32 Data); +void XGpioPs_SetDirectionPin(const XGpioPs *InstancePtr, u32 Pin, u32 Direction); +u32 XGpioPs_GetDirectionPin(const XGpioPs *InstancePtr, u32 Pin); +void XGpioPs_SetOutputEnablePin(const XGpioPs *InstancePtr, u32 Pin, u32 OpEnable); +u32 XGpioPs_GetOutputEnablePin(const XGpioPs *InstancePtr, u32 Pin); + +/* Diagnostic functions in xgpiops_selftest.c */ +s32 XGpioPs_SelfTest(const XGpioPs *InstancePtr); + +/* Functions in xgpiops_intr.c */ +/* Bank APIs in xgpiops_intr.c */ +void XGpioPs_IntrEnable(const XGpioPs *InstancePtr, u8 Bank, u32 Mask); +void XGpioPs_IntrDisable(const XGpioPs *InstancePtr, u8 Bank, u32 Mask); +u32 XGpioPs_IntrGetEnabled(const XGpioPs *InstancePtr, u8 Bank); +u32 XGpioPs_IntrGetStatus(const XGpioPs *InstancePtr, u8 Bank); +void XGpioPs_IntrClear(const XGpioPs *InstancePtr, u8 Bank, u32 Mask); +void XGpioPs_SetIntrType(const XGpioPs *InstancePtr, u8 Bank, u32 IntrType, + u32 IntrPolarity, u32 IntrOnAny); +void XGpioPs_GetIntrType(const XGpioPs *InstancePtr, u8 Bank, u32 *IntrType, + u32 *IntrPolarity, u32 *IntrOnAny); +void XGpioPs_SetCallbackHandler(XGpioPs *InstancePtr, void *CallBackRef, + XGpioPs_Handler FuncPointer); +void XGpioPs_IntrHandler(const XGpioPs *InstancePtr); + +/* Pin APIs in xgpiops_intr.c */ +void XGpioPs_SetIntrTypePin(const XGpioPs *InstancePtr, u32 Pin, u8 IrqType); +u8 XGpioPs_GetIntrTypePin(const XGpioPs *InstancePtr, u32 Pin); + +void XGpioPs_IntrEnablePin(const XGpioPs *InstancePtr, u32 Pin); +void XGpioPs_IntrDisablePin(const XGpioPs *InstancePtr, u32 Pin); +u32 XGpioPs_IntrGetEnabledPin(const XGpioPs *InstancePtr, u32 Pin); +u32 XGpioPs_IntrGetStatusPin(const XGpioPs *InstancePtr, u32 Pin); +void XGpioPs_IntrClearPin(const XGpioPs *InstancePtr, u32 Pin); + +/* Functions in xgpiops_sinit.c */ +XGpioPs_Config *XGpioPs_LookupConfig(u16 DeviceId); +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/gpiops_v3_5/src/xgpiops_g.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/gpiops_v3_5/src/xgpiops_g.c new file mode 100644 index 0000000..0585a64 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/gpiops_v3_5/src/xgpiops_g.c @@ -0,0 +1,51 @@ + +/******************************************************************* +* +* CAUTION: This file is automatically generated by HSI. +* Version: 2019.1.3 +* DO NOT EDIT. +* +* Copyright (C) 2010-2023 Xilinx, Inc. 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 +*XILINX 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. +* +*Except as contained in this notice, the name of the Xilinx shall not be used +*in advertising or otherwise to promote the sale, use or other dealings in +*this Software without prior written authorization from Xilinx. +* + +* +* Description: Driver configuration +* +*******************************************************************/ + +#include "xparameters.h" +#include "xgpiops.h" + +/* +* The configuration table for devices +*/ + +XGpioPs_Config XGpioPs_ConfigTable[XPAR_XGPIOPS_NUM_INSTANCES] = +{ + { + XPAR_PS7_GPIO_0_DEVICE_ID, + XPAR_PS7_GPIO_0_BASEADDR + } +}; + + diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/gpiops_v3_5/src/xgpiops_hw.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/gpiops_v3_5/src/xgpiops_hw.c new file mode 100644 index 0000000..4885c29 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/gpiops_v3_5/src/xgpiops_hw.c @@ -0,0 +1,262 @@ +/****************************************************************************** +* +* Copyright (C) 2013 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xgpiops_hw.c +* @addtogroup gpiops_v3_5 +* @{ +* +* This file contains low level GPIO functions. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.02a hk   08/22/13 First Release
+* 3.00  kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.1	kvn  04/13/15 Add support for Zynq Ultrascale+ MP. CR# 856980.
+* 3.5   sne  03/01/19 Fixes violations according to MISRAC-2012
+*                     in saftey mode and modified the code such as
+*                     Use of mixed mode arithmetic,Declared the poiner param
+*                     as Pointer to const,Casting operation to a pointer,
+*                     Literal value requires a U suffix.
+* 3.5   sne  03/14/19 Added versal support.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xgpiops_hw.h" +#include "xgpiops.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Variable Definitions *****************************/ + +/************************** Function Prototypes ******************************/ + + +/*****************************************************************************/ +/* +* +* This function resets the GPIO module by writing reset values to +* all registers +* +* @param Base address of GPIO module +* +* @return None +* +* @note None. +* +******************************************************************************/ +void XGpioPs_ResetHw(u32 BaseAddress) +{ + u32 BankCount; + u32 Platform,MaxBanks; + + Platform = XGetPlatform_Info(); + if (Platform == (u32)XPLAT_ZYNQ_ULTRA_MP) { + MaxBanks = (u32)6; + } + else if(Platform == (u32)XPLAT_versal) + { + if (BaseAddress == (u32)XGPIOPS_PS_GPIO_BASEADDR) + { + MaxBanks = (u32)4; + } + else + { + MaxBanks = (u32)5; + } + } + else { + MaxBanks = (u32)4; + } + + if (Platform == (u32)XPLAT_versal) + { + /* Write reset values to all mask data registers */ + for(BankCount = 3U; BankCount < (u32)MaxBanks; BankCount++) { + + XGpioPs_WriteReg(BaseAddress, + ((BankCount * XGPIOPS_DATA_MASK_OFFSET) + + XGPIOPS_DATA_LSW_OFFSET), 0x0U); + XGpioPs_WriteReg(BaseAddress, + ((BankCount * XGPIOPS_DATA_MASK_OFFSET) + + XGPIOPS_DATA_MSW_OFFSET), 0x0U); + } + /* Write reset values to all output data registers */ + for(BankCount = 3U; BankCount < (u32)MaxBanks; BankCount++) { + + XGpioPs_WriteReg(BaseAddress, + ((BankCount * XGPIOPS_DATA_BANK_OFFSET) + + XGPIOPS_DATA_OFFSET), 0x0U); + } + + /* Reset all registers of all GPIO banks */ + for(BankCount = 0U; BankCount < (u32)MaxBanks; BankCount++) { + + + if((BaseAddress == (u32)XGPIOPS_PS_GPIO_BASEADDR) && ((BankCount == (u32)XGPIOPS_ONE) ||(BankCount == (u32)XGPIOPS_TWO))) + { + continue; + } + else + { + if((BaseAddress != (u32)XGPIOPS_PS_GPIO_BASEADDR) && (BankCount == (u32)XGPIOPS_ONE)) + { + continue; + } + } + XGpioPs_WriteReg(BaseAddress, + ((BankCount * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_DIRM_OFFSET), 0x0U); + XGpioPs_WriteReg(BaseAddress, + ((BankCount * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_OUTEN_OFFSET), 0x0U); + XGpioPs_WriteReg(BaseAddress, + ((BankCount * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTMASK_OFFSET), 0x0U); + XGpioPs_WriteReg(BaseAddress, + ((BankCount * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTEN_OFFSET), 0x0U); + XGpioPs_WriteReg(BaseAddress, + ((BankCount * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTDIS_OFFSET), 0x0U); + XGpioPs_WriteReg(BaseAddress, + ((BankCount * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTSTS_OFFSET), 0x0U); + XGpioPs_WriteReg(BaseAddress, + ((BankCount * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTPOL_OFFSET), 0x0U); + XGpioPs_WriteReg(BaseAddress, + ((BankCount * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTANY_OFFSET), 0x0U); + + } + + /* Bank 0 Int type */ + XGpioPs_WriteReg(BaseAddress, XGPIOPS_INTTYPE_OFFSET, + XGPIOPS_INTTYPE_BANK0_RESET); + /* Bank 1 Int type */ + XGpioPs_WriteReg(BaseAddress, + ((u32)XGPIOPS_REG_MASK_OFFSET + (u32)XGPIOPS_INTTYPE_OFFSET), + XGPIOPS_INTTYPE_BANK1_RESET); + /* Bank 3 Int type */ + XGpioPs_WriteReg(BaseAddress, + (((u32)3 * XGPIOPS_REG_MASK_OFFSET) + XGPIOPS_INTTYPE_OFFSET), + XGPIOPS_INTTYPE_BANK3_RESET); + /* Bank 4 Int type */ + XGpioPs_WriteReg(BaseAddress, + (((u32)4 * XGPIOPS_REG_MASK_OFFSET) + XGPIOPS_INTTYPE_OFFSET), + XGPIOPS_INTTYPE_BANK4_RESET); + } + else + { + /* Write reset values to all mask data registers */ + for(BankCount = 2U; BankCount < (u32)MaxBanks; BankCount++) { + + XGpioPs_WriteReg(BaseAddress, + ((BankCount * XGPIOPS_DATA_MASK_OFFSET) + + XGPIOPS_DATA_LSW_OFFSET), 0x0U); + XGpioPs_WriteReg(BaseAddress, + ((BankCount * XGPIOPS_DATA_MASK_OFFSET) + + XGPIOPS_DATA_MSW_OFFSET), 0x0U); + } + /* Write reset values to all output data registers */ + for(BankCount = 2U; BankCount < (u32)MaxBanks; BankCount++) { + + XGpioPs_WriteReg(BaseAddress, + ((BankCount * XGPIOPS_DATA_BANK_OFFSET) + + XGPIOPS_DATA_OFFSET), 0x0U); + } + /* Reset all registers of all GPIO banks */ + for(BankCount = 0U; BankCount < (u32)MaxBanks; BankCount++) { + + XGpioPs_WriteReg(BaseAddress, + ((BankCount * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_DIRM_OFFSET), 0x0U); + XGpioPs_WriteReg(BaseAddress, + ((BankCount * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_OUTEN_OFFSET), 0x0U); + XGpioPs_WriteReg(BaseAddress, + ((BankCount * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTMASK_OFFSET), 0x0U); + XGpioPs_WriteReg(BaseAddress, + ((BankCount * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTEN_OFFSET), 0x0U); + XGpioPs_WriteReg(BaseAddress, + ((BankCount * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTDIS_OFFSET), 0x0U); + XGpioPs_WriteReg(BaseAddress, + ((BankCount * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTSTS_OFFSET), 0x0U); + XGpioPs_WriteReg(BaseAddress, + ((BankCount * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTPOL_OFFSET), 0x0U); + XGpioPs_WriteReg(BaseAddress, + ((BankCount * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTANY_OFFSET), 0x0U); + } + /* Bank 0 Int type */ + XGpioPs_WriteReg(BaseAddress, XGPIOPS_INTTYPE_OFFSET, + XGPIOPS_INTTYPE_BANK0_RESET); + /* Bank 1 Int type */ + XGpioPs_WriteReg(BaseAddress, + ((u32)XGPIOPS_REG_MASK_OFFSET + (u32)XGPIOPS_INTTYPE_OFFSET), + XGPIOPS_INTTYPE_BANK1_RESET); + /* Bank 2 Int type */ + XGpioPs_WriteReg(BaseAddress, + (((u32)2 * XGPIOPS_REG_MASK_OFFSET) + XGPIOPS_INTTYPE_OFFSET), + XGPIOPS_INTTYPE_BANK2_RESET); + /* Bank 3 Int type */ + XGpioPs_WriteReg(BaseAddress, + (((u32)3 * XGPIOPS_REG_MASK_OFFSET) + XGPIOPS_INTTYPE_OFFSET), + XGPIOPS_INTTYPE_BANK3_RESET); + + if (Platform == (u32)XPLAT_ZYNQ_ULTRA_MP) { + /* Bank 4 Int type */ + XGpioPs_WriteReg(BaseAddress, + (((u32)4 * XGPIOPS_REG_MASK_OFFSET) + XGPIOPS_INTTYPE_OFFSET), + XGPIOPS_INTTYPE_BANK4_RESET); + /* Bank 5 Int type */ + XGpioPs_WriteReg(BaseAddress, + (((u32)5 * XGPIOPS_REG_MASK_OFFSET) + XGPIOPS_INTTYPE_OFFSET), + XGPIOPS_INTTYPE_BANK5_RESET); + } + } + +} +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/gpiops_v3_5/src/xgpiops_hw.h b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/gpiops_v3_5/src/xgpiops_hw.h new file mode 100644 index 0000000..599c7db --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/gpiops_v3_5/src/xgpiops_hw.h @@ -0,0 +1,168 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xgpiops_hw.h +* @addtogroup gpiops_v3_5 +* @{ +* +* This header file contains the identifiers and basic driver functions (or +* macros) that can be used to access the device. Other driver functions +* are defined in xgpiops.h. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------
+* 1.00a sv   01/15/10 First Release
+* 1.02a hk   08/22/13 Added low level reset API function prototype and
+*                     related constant definitions
+* 3.00  kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.1	kvn  04/13/15 Corrected reset values of banks.
+* 3.5   sne  03/14/19 Added versal support.
+* 
+* +******************************************************************************/ +#ifndef XGPIOPS_HW_H /* prevent circular inclusions */ +#define XGPIOPS_HW_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_io.h" + +/************************** Constant Definitions *****************************/ + +/** @name Register offsets for the GPIO. Each register is 32 bits. + * @{ + */ +#define XGPIOPS_DATA_LSW_OFFSET 0x00000000U /* Mask and Data Register LSW, WO */ +#define XGPIOPS_DATA_MSW_OFFSET 0x00000004U /* Mask and Data Register MSW, WO */ +#define XGPIOPS_DATA_OFFSET 0x00000040U /* Data Register, RW */ +#define XGPIOPS_DATA_RO_OFFSET 0x00000060U /* Data Register - Input, RO */ +#define XGPIOPS_DIRM_OFFSET 0x00000204U /* Direction Mode Register, RW */ +#define XGPIOPS_OUTEN_OFFSET 0x00000208U /* Output Enable Register, RW */ +#define XGPIOPS_INTMASK_OFFSET 0x0000020CU /* Interrupt Mask Register, RO */ +#define XGPIOPS_INTEN_OFFSET 0x00000210U /* Interrupt Enable Register, WO */ +#define XGPIOPS_INTDIS_OFFSET 0x00000214U /* Interrupt Disable Register, WO*/ +#define XGPIOPS_INTSTS_OFFSET 0x00000218U /* Interrupt Status Register, RO */ +#define XGPIOPS_INTTYPE_OFFSET 0x0000021CU /* Interrupt Type Register, RW */ +#define XGPIOPS_INTPOL_OFFSET 0x00000220U /* Interrupt Polarity Register, RW */ +#define XGPIOPS_INTANY_OFFSET 0x00000224U /* Interrupt On Any Register, RW */ +/* @} */ + +/** @name Register offsets for each Bank. + * @{ + */ +#define XGPIOPS_DATA_MASK_OFFSET 0x00000008U /* Data/Mask Registers offset */ +#define XGPIOPS_DATA_BANK_OFFSET 0x00000004U /* Data Registers offset */ +#define XGPIOPS_REG_MASK_OFFSET 0x00000040U /* Registers offset */ +/* @} */ + +/* For backwards compatibility */ +#define XGPIOPS_BYPM_MASK_OFFSET (u32)0x40 + +/** @name Interrupt type reset values for each bank + * @{ + */ +#ifdef XPAR_PSU_GPIO_0_BASEADDR +#define XGPIOPS_INTTYPE_BANK0_RESET 0x03FFFFFFU /* Resets specific to Zynq Ultrascale+ MP */ +#define XGPIOPS_INTTYPE_BANK1_RESET 0x03FFFFFFU +#define XGPIOPS_INTTYPE_BANK2_RESET 0x03FFFFFFU +#else +#define XGPIOPS_INTTYPE_BANK0_RESET 0xFFFFFFFFU /* Resets specific to Zynq */ +#define XGPIOPS_INTTYPE_BANK1_RESET 0x003FFFFFU +#define XGPIOPS_INTTYPE_BANK2_RESET 0xFFFFFFFFU +#endif + +#define XGPIOPS_INTTYPE_BANK3_RESET 0xFFFFFFFFU /* Reset common to both platforms */ +#define XGPIOPS_INTTYPE_BANK4_RESET 0xFFFFFFFFU /* Resets specific to Zynq Ultrascale+ MP */ +#define XGPIOPS_INTTYPE_BANK5_RESET 0xFFFFFFFFU +/* @} */ +#define XGPIOPS_PS_GPIO_BASEADDR 0xFF0B0000U /* Flag for Base Address for PS_GPIO in Versal */ +#define XGPIOPS_ZERO 0U /* Flag for 0 Value */ +#define XGPIOPS_ONE 1U /* Flag for 1 Value */ +#define XGPIOPS_TWO 2U /* Flag for 2 Value */ +#define XGPIOPS_THREE 3U /* Flag for 3 Value */ +#define XGPIOPS_FOUR 4U /* Flag for 4 Value */ +#define XGPIOPS_SIX 6U /* Flag for 6 Value */ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/****************************************************************************/ +/** +* +* This macro reads the given register. +* +* @param BaseAddr is the base address of the device. +* @param RegOffset is the register offset to be read. +* +* @return The 32-bit value of the register +* +* @note None. +* +*****************************************************************************/ +#define XGpioPs_ReadReg(BaseAddr, RegOffset) \ + Xil_In32((BaseAddr) + (u32)(RegOffset)) + +/****************************************************************************/ +/** +* +* This macro writes to the given register. +* +* @param BaseAddr is the base address of the device. +* @param RegOffset is the offset of the register to be written. +* @param Data is the 32-bit value to write to the register. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +#define XGpioPs_WriteReg(BaseAddr, RegOffset, Data) \ + Xil_Out32((BaseAddr) + (u32)(RegOffset), (u32)(Data)) + +/************************** Function Prototypes ******************************/ + +void XGpioPs_ResetHw(u32 BaseAddress); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* XGPIOPS_HW_H */ +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/gpiops_v3_5/src/xgpiops_intr.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/gpiops_v3_5/src/xgpiops_intr.c new file mode 100644 index 0000000..0730c91 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/gpiops_v3_5/src/xgpiops_intr.c @@ -0,0 +1,813 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xgpiops_intr.c +* @addtogroup gpiops_v3_5 +* @{ +* +* This file contains functions related to GPIO interrupt handling. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a sv   01/18/10 First Release
+* 2.2	sk	 10/13/14 Used Pin number in Bank instead of pin number
+* 					  passed to API's. CR# 822636
+* 3.00  kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.1	kvn  04/13/15 Add support for Zynq Ultrascale+ MP. CR# 856980.
+* 3.1   aru  07/13/18 Ressolved doxygen reported warnings. CR# 1006331.
+* 3.4   aru  08/09/18 Ressolved cppcheck warnings.
+* 3.4   aru  08/17/18 Resolved MISRA-C mandatory violations. CR# 1007751
+* 3.5   sne  03/01/19 Fixes violations according to MISRAC-2012
+*                     in saftey mode and modified the code such as
+*                     Use of mixed mode arithmetic,Declared the poiner param
+*                     as Pointer to const,Casting operation to a pointer,
+*                     Literal value requires a U suffix.
+* 3.5   sne  03/14/19 Added Versal support.
+* 3.5   sne  03/20/19 Fixed multiple interrupts problem CR#1024556.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xgpiops.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Variable Definitions *****************************/ + +/************************** Function Prototypes ******************************/ + +void StubHandler(const void *CallBackRef, u32 Bank, u32 Status); + +/****************************************************************************/ +/** +* +* This function enables the interrupts for the specified pins in the specified +* bank. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Bank is the bank number of the GPIO to operate on. +* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. +* @param Mask is the bit mask of the pins for which interrupts are to +* be enabled. Bit positions of 1 will be enabled. Bit positions +* of 0 will keep the previous setting. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XGpioPs_IntrEnable(const XGpioPs *InstancePtr, u8 Bank, u32 Mask) +{ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Bank < InstancePtr->MaxBanks); +#ifdef versal + if(InstancePtr->PmcGpio == TRUE) { + Xil_AssertVoid(Bank != XGPIOPS_TWO); + } else { + Xil_AssertVoid((Bank !=XGPIOPS_ONE) && (Bank !=XGPIOPS_TWO)); + } +#endif + + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTEN_OFFSET, Mask); +} + +/****************************************************************************/ +/** +* +* This function enables the interrupt for the specified pin. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Pin is the pin number for which the interrupt is to be enabled. +* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XGpioPs_IntrEnablePin(const XGpioPs *InstancePtr, u32 Pin) +{ + u8 Bank; + u8 PinNumber; + u32 IntrReg; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Pin < InstancePtr->MaxPinNum); + + /* Get the Bank number and Pin number within the bank. */ +#ifdef versal + XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); +#else + XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber); +#endif + + IntrReg = ((u32)1 << (u32)PinNumber); + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTEN_OFFSET, IntrReg); +} + +/****************************************************************************/ +/** +* +* This function disables the interrupts for the specified pins in the specified +* bank. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Bank is the bank number of the GPIO to operate on. +* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. +* @param Mask is the bit mask of the pins for which interrupts are +* to be disabled. Bit positions of 1 will be disabled. Bit +* positions of 0 will keep the previous setting. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XGpioPs_IntrDisable(const XGpioPs *InstancePtr, u8 Bank, u32 Mask) +{ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Bank < InstancePtr->MaxBanks); +#ifdef versal + if(InstancePtr->PmcGpio == TRUE) { + Xil_AssertVoid(Bank != XGPIOPS_TWO); + } else { + Xil_AssertVoid((Bank !=XGPIOPS_ONE) && (Bank !=XGPIOPS_TWO)); + } +#endif + + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTDIS_OFFSET, Mask); +} + +/****************************************************************************/ +/** +* +* This function disables the interrupts for the specified pin. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Pin is the pin number for which the interrupt is to be disabled. +* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XGpioPs_IntrDisablePin(const XGpioPs *InstancePtr, u32 Pin) +{ + u8 Bank; + u8 PinNumber; + u32 IntrReg; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Pin < InstancePtr->MaxPinNum); + + /* Get the Bank number and Pin number within the bank. */ +#ifdef versal + XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); +#else + XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber); +#endif + + IntrReg = ((u32)1 << (u32)PinNumber); + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTDIS_OFFSET, IntrReg); +} + +/****************************************************************************/ +/** +* +* This function returns the interrupt enable status for a bank. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Bank is the bank number of the GPIO to operate on. +* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. +* +* @return Enabled interrupt(s) in a 32-bit format. Bit positions with 1 +* indicate that the interrupt for that pin is enabled, bit +* positions with 0 indicate that the interrupt for that pin is +* disabled. +* +* @note None. +* +*****************************************************************************/ +u32 XGpioPs_IntrGetEnabled(const XGpioPs *InstancePtr, u8 Bank) +{ + u32 IntrMask; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(Bank < InstancePtr->MaxBanks); +#ifdef versal + if(InstancePtr->PmcGpio == TRUE) { + Xil_AssertNonvoid(Bank != XGPIOPS_TWO); + } else { + Xil_AssertNonvoid((Bank !=XGPIOPS_ONE) && (Bank !=XGPIOPS_TWO)); + } +#endif + + IntrMask = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTMASK_OFFSET); + return (~IntrMask); +} + +/****************************************************************************/ +/** +* +* This function returns whether interrupts are enabled for the specified pin. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Pin is the pin number for which the interrupt enable status +* is to be known. +* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. +* +* @return +* - TRUE if the interrupt is enabled. +* - FALSE if the interrupt is disabled. +* +* @note None. +* +*****************************************************************************/ +u32 XGpioPs_IntrGetEnabledPin(const XGpioPs *InstancePtr, u32 Pin) +{ + u8 Bank; + u8 PinNumber; + u32 IntrReg; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(Pin < InstancePtr->MaxPinNum); + + /* Get the Bank number and Pin number within the bank. */ +#ifdef versal + XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); +#else + XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber); +#endif + + IntrReg = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTMASK_OFFSET); + + return (((IntrReg & ((u32)1 << PinNumber)) != (u32)0)? FALSE : TRUE); +} + +/****************************************************************************/ +/** +* +* This function returns interrupt status read from Interrupt Status Register. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Bank is the bank number of the GPIO to operate on. +* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. +* +* @return The value read from Interrupt Status Register. +* +* @note None. +* +*****************************************************************************/ +u32 XGpioPs_IntrGetStatus(const XGpioPs *InstancePtr, u8 Bank) +{ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(Bank < InstancePtr->MaxBanks); +#ifdef versal + if(InstancePtr->PmcGpio == TRUE) { + Xil_AssertNonvoid(Bank != XGPIOPS_TWO); + } else { + Xil_AssertNonvoid((Bank !=XGPIOPS_ONE) && (Bank !=XGPIOPS_TWO)); + } +#endif + + return XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTSTS_OFFSET); +} + +/****************************************************************************/ +/** +* +* This function returns interrupt enable status of the specified pin. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Pin is the pin number for which the interrupt enable status +* is to be known. +* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. +* +* @return +* - TRUE if the interrupt has occurred. +* - FALSE if the interrupt has not occurred. +* +* @note None. +* +*****************************************************************************/ +u32 XGpioPs_IntrGetStatusPin(const XGpioPs *InstancePtr, u32 Pin) +{ + u8 Bank; + u8 PinNumber; + u32 IntrReg; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(Pin < InstancePtr->MaxPinNum); + + /* Get the Bank number and Pin number within the bank. */ +#ifdef versal + XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); +#else + XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber); +#endif + + IntrReg = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTSTS_OFFSET); + + return (((IntrReg & ((u32)1 << PinNumber)) != (u32)0)? TRUE : FALSE); +} + +/****************************************************************************/ +/** +* +* This function clears pending interrupt(s) with the provided mask. This +* function should be called after the software has serviced the interrupts +* that are pending. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Bank is the bank number of the GPIO to operate on. +* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. +* @param Mask is the mask of the interrupts to be cleared. Bit positions +* of 1 will be cleared. Bit positions of 0 will not change the +* previous interrupt status. +* +* @note None. +* +*****************************************************************************/ +void XGpioPs_IntrClear(const XGpioPs *InstancePtr, u8 Bank, u32 Mask) +{ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Bank < InstancePtr->MaxBanks); +#ifdef versal + if(InstancePtr->PmcGpio == TRUE) { + Xil_AssertVoid(Bank != XGPIOPS_TWO); + } else { + Xil_AssertVoid((Bank !=XGPIOPS_ONE) && (Bank !=XGPIOPS_TWO)); + } +#endif + + /* Clear the currently pending interrupts. */ + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTSTS_OFFSET, Mask); +} + +/****************************************************************************/ +/** +* +* This function clears the specified pending interrupt. This function should be +* called after the software has serviced the interrupts that are pending. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Pin is the pin number for which the interrupt status is to be +* cleared. Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. +* +* @note None. +* +*****************************************************************************/ +void XGpioPs_IntrClearPin(const XGpioPs *InstancePtr, u32 Pin) +{ + u8 Bank; + u8 PinNumber; + u32 IntrReg; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Pin < InstancePtr->MaxPinNum); + + /* Get the Bank number and Pin number within the bank. */ +#ifdef versal + XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); +#else + XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber); +#endif + + /* Clear the specified pending interrupts. */ + IntrReg = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTSTS_OFFSET); + + IntrReg &= ((u32)1 << PinNumber); + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTSTS_OFFSET, IntrReg); +} + +/****************************************************************************/ +/** +* +* This function is used for setting the Interrupt Type, Interrupt Polarity and +* Interrupt On Any for the specified GPIO Bank pins. +* +* @param InstancePtr is a pointer to an XGpioPs instance. +* @param Bank is the bank number of the GPIO to operate on. +* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. +* @param IntrType is the 32 bit mask of the interrupt type. +* 0 means Level Sensitive and 1 means Edge Sensitive. +* @param IntrPolarity is the 32 bit mask of the interrupt polarity. +* 0 means Active Low or Falling Edge and 1 means Active High or +* Rising Edge. +* @param IntrOnAny is the 32 bit mask of the interrupt trigger for +* edge triggered interrupts. 0 means trigger on single edge using +* the configured interrupt polarity and 1 means trigger on both +* edges. +* +* @return None. +* +* @note This function is used for setting the interrupt related +* properties of all the pins in the specified bank. The previous +* state of the pins is not maintained. +* To change the Interrupt properties of a single GPIO pin, use the +* function XGpioPs_SetPinIntrType(). +* +*****************************************************************************/ +void XGpioPs_SetIntrType(const XGpioPs *InstancePtr, u8 Bank, u32 IntrType, + u32 IntrPolarity, u32 IntrOnAny) +{ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Bank < InstancePtr->MaxBanks); +#ifdef versal + if(InstancePtr->PmcGpio == TRUE) { + Xil_AssertVoid(Bank != XGPIOPS_TWO); + } else { + Xil_AssertVoid((Bank !=XGPIOPS_ONE) && (Bank !=XGPIOPS_TWO)); + } +#endif + + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTTYPE_OFFSET, IntrType); + + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTPOL_OFFSET, IntrPolarity); + + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTANY_OFFSET, IntrOnAny); +} + +/****************************************************************************/ +/** +* +* This function is used for getting the Interrupt Type, Interrupt Polarity and +* Interrupt On Any for the specified GPIO Bank pins. +* +* @param InstancePtr is a pointer to an XGpioPs instance. +* @param Bank is the bank number of the GPIO to operate on. +* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. +* @param IntrType returns the 32 bit mask of the interrupt type. +* 0 means Level Sensitive and 1 means Edge Sensitive. +* @param IntrPolarity returns the 32 bit mask of the interrupt +* polarity. 0 means Active Low or Falling Edge and 1 means +* Active High or Rising Edge. +* @param IntrOnAny returns the 32 bit mask of the interrupt trigger for +* edge triggered interrupts. 0 means trigger on single edge using +* the configured interrupt polarity and 1 means trigger on both +* edges. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XGpioPs_GetIntrType(const XGpioPs *InstancePtr, u8 Bank, u32 *IntrType, + u32 *IntrPolarity, u32 *IntrOnAny) + +{ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Bank < InstancePtr->MaxBanks); +#ifdef versal + if(InstancePtr->PmcGpio == TRUE) { + Xil_AssertVoid(Bank != XGPIOPS_TWO); + } else { + Xil_AssertVoid((Bank !=XGPIOPS_ONE) && (Bank !=XGPIOPS_TWO)); + } +#endif + + *IntrType = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTTYPE_OFFSET); + + *IntrPolarity = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTPOL_OFFSET); + + *IntrOnAny = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTANY_OFFSET); +} + +/****************************************************************************/ +/** +* +* This function is used for setting the IRQ Type of a single GPIO pin. +* +* @param InstancePtr is a pointer to an XGpioPs instance. +* @param Pin is the pin number whose IRQ type is to be set. +* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. +* @param IrqType is the IRQ type for GPIO Pin. Use XGPIOPS_IRQ_TYPE_* +* defined in xgpiops.h to specify the IRQ type. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XGpioPs_SetIntrTypePin(const XGpioPs *InstancePtr, u32 Pin, u8 IrqType) +{ + u32 IntrTypeReg; + u32 IntrPolReg; + u32 IntrOnAnyReg; + u8 Bank; + u8 PinNumber; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Pin < InstancePtr->MaxPinNum); + Xil_AssertVoid(IrqType <= XGPIOPS_IRQ_TYPE_LEVEL_LOW); + + /* Get the Bank number and Pin number within the bank. */ +#ifdef versal + XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); +#else + XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber); +#endif + + IntrTypeReg = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTTYPE_OFFSET); + + IntrPolReg = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTPOL_OFFSET); + + IntrOnAnyReg = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTANY_OFFSET); + + switch (IrqType) { + case XGPIOPS_IRQ_TYPE_EDGE_RISING: + IntrTypeReg |= ((u32)1 << (u32)PinNumber); + IntrPolReg |= ((u32)1 << (u32)PinNumber); + IntrOnAnyReg &= ~((u32)1 << (u32)PinNumber); + break; + case XGPIOPS_IRQ_TYPE_EDGE_FALLING: + IntrTypeReg |= ((u32)1 << (u32)PinNumber); + IntrPolReg &= ~((u32)1 << (u32)PinNumber); + IntrOnAnyReg &= ~((u32)1 << (u32)PinNumber); + break; + case XGPIOPS_IRQ_TYPE_EDGE_BOTH: + IntrTypeReg |= ((u32)1 << (u32)PinNumber); + IntrOnAnyReg |= ((u32)1 << (u32)PinNumber); + break; + case XGPIOPS_IRQ_TYPE_LEVEL_HIGH: + IntrTypeReg &= ~((u32)1 << (u32)PinNumber); + IntrPolReg |= ((u32)1 << (u32)PinNumber); + break; + case XGPIOPS_IRQ_TYPE_LEVEL_LOW: + IntrTypeReg &= ~((u32)1 << (u32)PinNumber); + IntrPolReg &= ~((u32)1 << (u32)PinNumber); + break; + default: + /**< Default statement is added for MISRA C compliance. */ + break; + } + + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTTYPE_OFFSET, IntrTypeReg); + + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTPOL_OFFSET, IntrPolReg); + + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTANY_OFFSET, IntrOnAnyReg); +} + +/****************************************************************************/ +/** +* +* This function returns the IRQ Type of a given GPIO pin. +* +* @param InstancePtr is a pointer to an XGpioPs instance. +* @param Pin is the pin number whose IRQ type is to be obtained. +* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. +* +* @return None. +* +* @note Use XGPIOPS_IRQ_TYPE_* defined in xgpiops.h for the IRQ type +* returned by this function. +* +*****************************************************************************/ +u8 XGpioPs_GetIntrTypePin(const XGpioPs *InstancePtr, u32 Pin) +{ + u32 IntrType; + u32 IntrPol; + u32 IntrOnAny; + u8 Bank; + u8 PinNumber; + u8 IrqType; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(Pin < InstancePtr->MaxPinNum); + + /* Get the Bank number and Pin number within the bank. */ +#ifdef versal + XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); +#else + XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber); +#endif + + IntrType = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTTYPE_OFFSET) & ((u32)1 << PinNumber); + + if (IntrType == ((u32)1 << PinNumber)) { + + IntrOnAny = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTANY_OFFSET) & ((u32)1 << PinNumber); + + IntrPol = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTPOL_OFFSET) & ((u32)1 << PinNumber); + + + if (IntrOnAny == ((u32)1 << PinNumber)) { + IrqType = XGPIOPS_IRQ_TYPE_EDGE_BOTH; + } else if (IntrPol == ((u32)1 << PinNumber)) { + IrqType = XGPIOPS_IRQ_TYPE_EDGE_RISING; + } else { + IrqType = XGPIOPS_IRQ_TYPE_EDGE_FALLING; + } + } else { + + IntrPol = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTPOL_OFFSET) & ((u32)1 << PinNumber); + + if (IntrPol == ((u32)1 << PinNumber)) { + IrqType = XGPIOPS_IRQ_TYPE_LEVEL_HIGH; + } else { + IrqType = XGPIOPS_IRQ_TYPE_LEVEL_LOW; + } + } + + return IrqType; +} + +/*****************************************************************************/ +/** +* +* This function sets the status callback function. The callback function is +* called by the XGpioPs_IntrHandler when an interrupt occurs. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param CallBackRef is the upper layer callback reference passed back +* when the callback function is invoked. +* @param FuncPointer is the pointer to the callback function. +* +* +* @return None. +* +* @note The handler is called within interrupt context, so it should do +* its work quickly and queue potentially time-consuming work to a +* task-level thread. +* +******************************************************************************/ +void XGpioPs_SetCallbackHandler(XGpioPs *InstancePtr, void *CallBackRef, + XGpioPs_Handler FuncPointer) +{ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(FuncPointer != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + InstancePtr->Handler = FuncPointer; + InstancePtr->CallBackRef = CallBackRef; +} + +/*****************************************************************************/ +/** +* +* This function is the interrupt handler for GPIO interrupts.It checks the +* interrupt status registers of all the banks to determine the actual bank in +* which an interrupt has been triggered. It then calls the upper layer callback +* handler set by the function XGpioPs_SetBankHandler(). The callback is called +* when an interrupt +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* +* @return None. +* +* @note This function does not save and restore the processor context +* such that the user must provide this processing. +* +******************************************************************************/ +void XGpioPs_IntrHandler(const XGpioPs *InstancePtr) +{ + u8 Bank; + u32 IntrStatus; + u32 IntrEnabled; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + for (Bank = 0U; Bank < InstancePtr->MaxBanks; Bank++) { + IntrStatus = XGpioPs_IntrGetStatus(InstancePtr, Bank); + IntrEnabled = XGpioPs_IntrGetEnabled(InstancePtr,Bank); + if ((IntrStatus & IntrEnabled) != (u32)0) { + XGpioPs_IntrClear(InstancePtr, Bank, + (IntrStatus & IntrEnabled)); + InstancePtr->Handler(InstancePtr-> + CallBackRef, Bank, + (IntrStatus & IntrEnabled)); + } + } +} + +/*****************************************************************************/ +/** +* +* This is a stub for the status callback. The stub is here in case the upper +* layers do not set the handler. +* +* @param CallBackRef is a pointer to the upper layer callback reference +* @param Bank is the GPIO Bank in which an interrupt occurred. +* @param Status is the Interrupt status of the GPIO bank. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void StubHandler(const void *CallBackRef, u32 Bank, u32 Status) +{ + (const void) CallBackRef; + (void) Bank; + (void) Status; + + Xil_AssertVoidAlways(); +} +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/gpiops_v3_5/src/xgpiops_selftest.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/gpiops_v3_5/src/xgpiops_selftest.c new file mode 100644 index 0000000..322ca74 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/gpiops_v3_5/src/xgpiops_selftest.c @@ -0,0 +1,134 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xgpiops_selftest.c +* @addtogroup gpiops_v3_5 +* @{ +* +* This file contains a diagnostic self-test function for the XGpioPs driver. +* +* Read xgpiops.h file for more information. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a sv   01/18/10 First Release
+* 3.00  kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.5   sne  03/01/19 Fixes violations according to MISRAC-2012
+*                     in saftey mode and modified the code such as
+*                     Use of mixed mode arithmetic,Declared the poiner param
+*                     as Pointer to const,Casting operation to a pointer,
+*                     Literal value requires a U suffix.
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ + +#include "xstatus.h" +#include "xgpiops.h" + +/************************** Constant Definitions ****************************/ + + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Variable Definitions ****************************/ + +/************************** Function Prototypes *****************************/ + +/*****************************************************************************/ +/** +* +* This function runs a self-test on the GPIO driver/device. This function +* does a register read/write test on some of the Interrupt Registers. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* +* @return +* - XST_SUCCESS if the self-test passed. +* - XST_FAILURE otherwise. +* +* +******************************************************************************/ +s32 XGpioPs_SelfTest(const XGpioPs *InstancePtr) +{ + s32 Status = XST_SUCCESS; + u32 IntrEnabled; + u32 CurrentIntrType = 0U; + u32 CurrentIntrPolarity = 0U; + u32 CurrentIntrOnAny = 0U; + u32 IntrType = 0U; + u32 IntrPolarity = 0U; + u32 IntrOnAny = 0U; + u32 IntrTestValue = 0x22U; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* Disable the Interrupts for Bank 0 . */ + IntrEnabled = XGpioPs_IntrGetEnabled(InstancePtr, XGPIOPS_BANK0); + XGpioPs_IntrDisable(InstancePtr, XGPIOPS_BANK0, IntrEnabled); + + /* + * Get the Current Interrupt properties for Bank 0. + * Set them to a known value, read it back and compare. + */ + XGpioPs_GetIntrType(InstancePtr, XGPIOPS_BANK0, &CurrentIntrType, + &CurrentIntrPolarity, &CurrentIntrOnAny); + + XGpioPs_SetIntrType(InstancePtr, XGPIOPS_BANK0, IntrTestValue, + IntrTestValue, IntrTestValue); + + XGpioPs_GetIntrType(InstancePtr, XGPIOPS_BANK0, &IntrType, + &IntrPolarity, &IntrOnAny); + + if ((IntrType != IntrTestValue) && (IntrPolarity != IntrTestValue) && + (IntrOnAny != IntrTestValue)) { + + Status = XST_FAILURE; + } + + /* + * Restore the contents of all the interrupt registers modified in this + * test. + */ + XGpioPs_SetIntrType(InstancePtr, XGPIOPS_BANK0, CurrentIntrType, + CurrentIntrPolarity, CurrentIntrOnAny); + + XGpioPs_IntrEnable(InstancePtr, XGPIOPS_BANK0, IntrEnabled); + + return Status; +} +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/gpiops_v3_5/src/xgpiops_sinit.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/gpiops_v3_5/src/xgpiops_sinit.c new file mode 100644 index 0000000..58ce55e --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/gpiops_v3_5/src/xgpiops_sinit.c @@ -0,0 +1,97 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xgpiops_sinit.c +* @addtogroup gpiops_v3_5 +* @{ +* +* This file contains the implementation of the XGpioPs driver's static +* initialization functionality. +* +* @note None. +* +*
+*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a sv   01/15/10 First Release
+* 3.00  kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xgpiops.h" +#include "xparameters.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ +extern XGpioPs_Config XGpioPs_ConfigTable[XPAR_XGPIOPS_NUM_INSTANCES]; + +/*****************************************************************************/ +/** +* +* This function looks for the device configuration based on the unique device +* ID. The table XGpioPs_ConfigTable[] contains the configuration information +* for each device in the system. +* +* @param DeviceId is the unique device ID of the device being looked up. +* +* @return A pointer to the configuration table entry corresponding to the +* given device ID, or NULL if no match is found. +* +* @note None. +* +******************************************************************************/ +XGpioPs_Config *XGpioPs_LookupConfig(u16 DeviceId) +{ + XGpioPs_Config *CfgPtr = NULL; + u32 Index; + + for (Index = 0U; Index < (u32)XPAR_XGPIOPS_NUM_INSTANCES; Index++) { + if (XGpioPs_ConfigTable[Index].DeviceId == DeviceId) { + CfgPtr = &XGpioPs_ConfigTable[Index]; + break; + } + } + + return (XGpioPs_Config *)CfgPtr; +} +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/qspips_v3_6/src/Makefile b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/qspips_v3_6/src/Makefile new file mode 100644 index 0000000..3600928 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/qspips_v3_6/src/Makefile @@ -0,0 +1,40 @@ +COMPILER= +ARCHIVER= +CP=cp +COMPILER_FLAGS= +EXTRA_COMPILER_FLAGS= +LIB=libxil.a + +CC_FLAGS = $(COMPILER_FLAGS) +ECC_FLAGS = $(EXTRA_COMPILER_FLAGS) + +RELEASEDIR=../../../lib +INCLUDEDIR=../../../include +INCLUDES=-I./. -I${INCLUDEDIR} + +OUTS = *.o + +LIBSOURCES:=*.c +INCLUDEFILES:=*.h + +OBJECTS = $(addsuffix .o, $(basename $(wildcard *.c))) + +libs: banner xqspips_libs clean + +%.o: %.c + ${COMPILER} $(CC_FLAGS) $(ECC_FLAGS) $(INCLUDES) -o $@ $< + +banner: + echo "Compiling qspips" + +xqspips_libs: ${OBJECTS} + $(ARCHIVER) -r ${RELEASEDIR}/${LIB} ${OBJECTS} + +.PHONY: include +include: xqspips_includes + +xqspips_includes: + ${CP} ${INCLUDEFILES} ${INCLUDEDIR} + +clean: + rm -rf ${OBJECTS} diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/qspips_v3_6/src/xqspips.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/qspips_v3_6/src/xqspips.c new file mode 100644 index 0000000..e82cab6 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/qspips_v3_6/src/xqspips.c @@ -0,0 +1,1611 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xqspips.c +* @addtogroup qspips_v3_6 +* @{ +* +* Contains implements the interface functions of the XQspiPs driver. +* See xqspips.h for a detailed description of the device and driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- -----------------------------------------------
+* 1.00  sdm 11/25/10 First release
+* 2.00a kka 07/25/12 Removed XQspiPs_GetWriteData API.
+*		     The XQspiPs_SetSlaveSelect has been modified to remove
+*		     the argument of the slave select as the QSPI controller
+*		     only supports one slave.
+* 		     XQspiPs_GetSlaveSelect API has been removed
+* 		     Added logic to XQspiPs_GetReadData to handle data
+*		     shift for normal data reads and instruction/status
+*		     reads differently based on the ShiftReadData flag.
+* 		     Removed the selection for the following options:
+*		     Master mode (XQSPIPS_MASTER_OPTION) and
+*		     Flash interface mode (XQSPIPS_FLASH_MODE_OPTION) option
+*		     as the QSPI driver supports the Master mode
+*		     and Flash Interface mode and doesnot support
+*		     Slave mode or the legacy mode.
+*		     Modified the XQspiPs_PolledTransfer and XQspiPs_Transfer
+*		     APIs so that the last argument (IsInst) specifying whether
+*		     it is instruction or data has been removed. The first byte
+*		     in the SendBufPtr argument of these APIs specify the
+*		     instruction to be sent to the Flash Device.
+*		     The XQspiPs_PolledTransfer function has been updated
+*		     to fill the data to fifo depth.
+*		     This version of the driver fixes CRs 670197/663787.
+* 2.01a sg  02/03/13 Added flash opcodes for DUAL_IO_READ,QUAD_IO_READ.
+*		     Created macros XQspiPs_IsManualStart and
+*		     XQspiPs_IsManualChipSelect.
+*		     Changed QSPI transfer logic for polled and interrupt
+*		     modes to be based on filled tx fifo count and receive
+*		     based on it. RXNEMPTY interrupt is not used.
+*		     Added assertions to XQspiPs_LqspiRead function.
+*
+* 2.02a hk  05/14/13 Added enable and disable to the XQspiPs_LqspiRead()
+*			 function
+*            Added instructions for bank selection, die erase and
+*            flag status register to the flash instruction table
+*            Handling for instructions not in flash instruction
+*			 table added. Checking for Tx FIFO empty when switching from
+*			 TXD1/2/3 to TXD0 added. If WRSR instruction is sent with
+*            byte count 3 (spansion), instruction size and TXD register
+*			 changed accordingly. CR# 712502 and 703869.
+*            Added (#ifdef linear base address) in the Linear read function.
+*            Changed  XPAR_XQSPIPS_0_LINEAR_BASEADDR to
+*            XPAR_PS7_QSPI_LINEAR_0_S_AXI_BASEADDR in
+*            XQspiPs_LqspiRead function. Fix for CR#718141
+*
+* 2.03a hk  09/05/13 Modified polled and interrupt transfers to make use of
+*                    thresholds. This is to improve performance.
+*                    Added RX and TX threshold reset to one in XQspiPs_Abort.
+*                    Added RX threshold reset(1) after transfer in polled and
+*                    interrupt transfers. Made changes to make sure threshold
+*                    change is done only when no transfer is in progress.
+* 3.1   hk  08/13/14 When writing to the configuration register, set/reset
+*                    required bits leaving reserved bits untouched. CR# 796813.
+* 3.2	sk	02/05/15 Add SLCR reset in abort function as a workaround because
+* 					 controller does not update FIFO status flags as expected
+* 					 when thresholds are used.
+* 3.3   sk  11/07/15 Modified the API prototypes according to MISRAC standards
+*                    to remove compilation warnings. CR# 868893.
+* 3.5	tjs 13/08/18 Fixed compilation warnings for ARMCC.
+* 3.6	akm 03/28/19 Fixed memory leak issue while reading from qspi.(CR#1016357)
+* 3.6 	akm 04/15/19 Modified the mask in XQspiPs_GetReadData() API to retrieve
+*		     configuration register values of both the Flashes in dual
+*		     parellel connection.
+*
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xqspips.h" + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + +/** + * This typedef defines qspi flash instruction format + */ +typedef struct { + u8 OpCode; /**< Operational code of the instruction */ + u8 InstSize; /**< Size of the instruction including address bytes */ + u8 TxOffset; /**< Register address where instruction has to be + written */ +} XQspiPsInstFormat; + +/***************** Macros (Inline Functions) Definitions *********************/ + +#define ARRAY_SIZE(Array) (sizeof(Array) / sizeof((Array)[0])) + +/************************** Function Prototypes ******************************/ +static void XQspiPs_GetReadData(XQspiPs *InstancePtr, u32 Data, u8 Size); +static void StubStatusHandler(void *CallBackRef, u32 StatusEvent, + unsigned ByteCount); + +/************************** Variable Definitions *****************************/ + +/* + * List of all the QSPI instructions and its format + */ +static XQspiPsInstFormat FlashInst[] = { + { XQSPIPS_FLASH_OPCODE_WREN, 1, XQSPIPS_TXD_01_OFFSET }, + { XQSPIPS_FLASH_OPCODE_WRDS, 1, XQSPIPS_TXD_01_OFFSET }, + { XQSPIPS_FLASH_OPCODE_RDSR1, 2, XQSPIPS_TXD_10_OFFSET }, + { XQSPIPS_FLASH_OPCODE_RDSR2, 2, XQSPIPS_TXD_10_OFFSET }, + { XQSPIPS_FLASH_OPCODE_WRSR, 2, XQSPIPS_TXD_10_OFFSET }, + { XQSPIPS_FLASH_OPCODE_PP, 4, XQSPIPS_TXD_00_OFFSET }, + { XQSPIPS_FLASH_OPCODE_SE, 4, XQSPIPS_TXD_00_OFFSET }, + { XQSPIPS_FLASH_OPCODE_BE_32K, 4, XQSPIPS_TXD_00_OFFSET }, + { XQSPIPS_FLASH_OPCODE_BE_4K, 4, XQSPIPS_TXD_00_OFFSET }, + { XQSPIPS_FLASH_OPCODE_BE, 1, XQSPIPS_TXD_01_OFFSET }, + { XQSPIPS_FLASH_OPCODE_ERASE_SUS, 1, XQSPIPS_TXD_01_OFFSET }, + { XQSPIPS_FLASH_OPCODE_ERASE_RES, 1, XQSPIPS_TXD_01_OFFSET }, + { XQSPIPS_FLASH_OPCODE_RDID, 4, XQSPIPS_TXD_00_OFFSET }, + { XQSPIPS_FLASH_OPCODE_NORM_READ, 4, XQSPIPS_TXD_00_OFFSET }, + { XQSPIPS_FLASH_OPCODE_FAST_READ, 4, XQSPIPS_TXD_00_OFFSET }, + { XQSPIPS_FLASH_OPCODE_DUAL_READ, 4, XQSPIPS_TXD_00_OFFSET }, + { XQSPIPS_FLASH_OPCODE_QUAD_READ, 4, XQSPIPS_TXD_00_OFFSET }, + { XQSPIPS_FLASH_OPCODE_DUAL_IO_READ, 4, XQSPIPS_TXD_00_OFFSET }, + { XQSPIPS_FLASH_OPCODE_QUAD_IO_READ, 4, XQSPIPS_TXD_00_OFFSET }, + { XQSPIPS_FLASH_OPCODE_BRWR, 2, XQSPIPS_TXD_10_OFFSET }, + { XQSPIPS_FLASH_OPCODE_BRRD, 2, XQSPIPS_TXD_10_OFFSET }, + { XQSPIPS_FLASH_OPCODE_EARWR, 2, XQSPIPS_TXD_10_OFFSET }, + { XQSPIPS_FLASH_OPCODE_EARRD, 2, XQSPIPS_TXD_10_OFFSET }, + { XQSPIPS_FLASH_OPCODE_DIE_ERASE, 4, XQSPIPS_TXD_00_OFFSET }, + { XQSPIPS_FLASH_OPCODE_READ_FLAG_SR, 2, XQSPIPS_TXD_10_OFFSET }, + { XQSPIPS_FLASH_OPCODE_CLEAR_FLAG_SR, 1, XQSPIPS_TXD_01_OFFSET }, + /* Add all the instructions supported by the flash device */ +}; + +/*****************************************************************************/ +/** +* +* Initializes a specific XQspiPs instance such that the driver is ready to use. +* +* The state of the device after initialization is: +* - Master mode +* - Active high clock polarity +* - Clock phase 0 +* - Baud rate divisor 2 +* - Transfer width 32 +* - Master reference clock = pclk +* - No chip select active +* - Manual CS and Manual Start disabled +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* @param ConfigPtr is a reference to a structure containing information +* about a specific QSPI device. This function initializes an +* InstancePtr object for a specific device specified by the +* contents of Config. +* @param EffectiveAddr is the device base address in the virtual memory +* address space. The caller is responsible for keeping the address +* mapping from EffectiveAddr to the device physical base address +* unchanged once this function is invoked. Unexpected errors may +* occur if the address mapping changes after this function is +* called. If address translation is not used, use +* ConfigPtr->Config.BaseAddress for this device. +* +* @return +* - XST_SUCCESS if successful. +* - XST_DEVICE_IS_STARTED if the device is already started. +* It must be stopped to re-initialize. +* +* @note None. +* +******************************************************************************/ +int XQspiPs_CfgInitialize(XQspiPs *InstancePtr, XQspiPs_Config *ConfigPtr, + u32 EffectiveAddr) +{ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(ConfigPtr != NULL); + + /* + * If the device is busy, disallow the initialize and return a status + * indicating it is already started. This allows the user to stop the + * device and re-initialize, but prevents a user from inadvertently + * initializing. This assumes the busy flag is cleared at startup. + */ + if (InstancePtr->IsBusy == TRUE) { + return XST_DEVICE_IS_STARTED; + } + + /* + * Set some default values. + */ + InstancePtr->IsBusy = FALSE; + + InstancePtr->Config.BaseAddress = EffectiveAddr; + InstancePtr->StatusHandler = StubStatusHandler; + + InstancePtr->SendBufferPtr = NULL; + InstancePtr->RecvBufferPtr = NULL; + InstancePtr->RequestedBytes = 0; + InstancePtr->RemainingBytes = 0; + InstancePtr->IsReady = XIL_COMPONENT_IS_READY; + + InstancePtr->Config.ConnectionMode = ConfigPtr->ConnectionMode; + + /* + * Reset the QSPI device to get it into its initial state. It is + * expected that device configuration will take place after this + * initialization is done, but before the device is started. + */ + XQspiPs_Reset(InstancePtr); + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* Resets the QSPI device. Reset must only be called after the driver has been +* initialized. Any data transfer that is in progress is aborted. +* +* The upper layer software is responsible for re-configuring (if necessary) +* and restarting the QSPI device after the reset. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XQspiPs_Reset(XQspiPs *InstancePtr) +{ + u32 ConfigReg; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Abort any transfer that is in progress + */ + XQspiPs_Abort(InstancePtr); + + /* + * Write default value to configuration register. + * Do not modify reserved bits. + */ + ConfigReg = XQspiPs_ReadReg(InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET); + ConfigReg |= XQSPIPS_CR_RESET_MASK_SET; + ConfigReg &= ~XQSPIPS_CR_RESET_MASK_CLR; + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPS_CR_OFFSET, + ConfigReg); +} + +/*****************************************************************************/ +/** +* +* Aborts a transfer in progress by disabling the device and flush the RxFIFO. +* The byte counts are cleared, the busy flag is cleared. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* +* @return None. +* +* @note +* +* This function does a read/modify/write of the config register. The user of +* this function needs to take care of critical sections. +* +******************************************************************************/ +void XQspiPs_Abort(XQspiPs *InstancePtr) +{ + u32 ConfigReg; + u32 IsLock; + + XQspiPs_Disable(InstancePtr); + + /* + * De-assert slave select lines. + */ + ConfigReg = XQspiPs_ReadReg(InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET); + ConfigReg |= (XQSPIPS_CR_SSCTRL_MASK | XQSPIPS_CR_SSFORCE_MASK); + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET, ConfigReg); + + /* + * QSPI Software Reset + */ + IsLock = XQspiPs_ReadReg(XPAR_XSLCR_0_BASEADDR, SLCR_LOCKSTA); + if (IsLock) { + XQspiPs_WriteReg(XPAR_XSLCR_0_BASEADDR, SLCR_UNLOCK, + SLCR_UNLOCK_MASK); + } + XQspiPs_WriteReg(XPAR_XSLCR_0_BASEADDR, LQSPI_RST_CTRL, + LQSPI_RST_CTRL_MASK); + XQspiPs_WriteReg(XPAR_XSLCR_0_BASEADDR, LQSPI_RST_CTRL, 0x0); + if (IsLock) { + XQspiPs_WriteReg(XPAR_XSLCR_0_BASEADDR, SLCR_LOCK, + SLCR_LOCK_MASK); + } + + /* + * Set the RX and TX FIFO threshold to reset value (one) + */ + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_RXWR_OFFSET, XQSPIPS_RXWR_RESET_VALUE); + + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_TXWR_OFFSET, XQSPIPS_TXWR_RESET_VALUE); + + InstancePtr->RemainingBytes = 0; + InstancePtr->RequestedBytes = 0; + InstancePtr->IsBusy = FALSE; +} + +/*****************************************************************************/ +/** +* +* Transfers specified data on the QSPI bus. Initiates bus communication and +* sends/receives data to/from the selected QSPI slave. For every byte sent, +* a byte is received. +* +* The caller has the option of providing two different buffers for send and +* receive, or one buffer for both send and receive, or no buffer for receive. +* The receive buffer must be at least as big as the send buffer to prevent +* unwanted memory writes. This implies that the byte count passed in as an +* argument must be the smaller of the two buffers if they differ in size. +* Here are some sample usages: +*
+*   XQspiPs_Transfer(InstancePtr, SendBuf, RecvBuf, ByteCount)
+*	The caller wishes to send and receive, and provides two different
+*	buffers for send and receive.
+*
+*   XQspiPs_Transfer(InstancePtr, SendBuf, NULL, ByteCount)
+*	The caller wishes only to send and does not care about the received
+*	data. The driver ignores the received data in this case.
+*
+*   XQspiPs_Transfer(InstancePtr, SendBuf, SendBuf, ByteCount)
+*	The caller wishes to send and receive, but provides the same buffer
+*	for doing both. The driver sends the data and overwrites the send
+*	buffer with received data as it transfers the data.
+*
+*   XQspiPs_Transfer(InstancePtr, RecvBuf, RecvBuf, ByteCount)
+*	The caller wishes to only receive and does not care about sending
+*	data.  In this case, the caller must still provide a send buffer, but
+*	it can be the same as the receive buffer if the caller does not care
+*	what it sends.  The device must send N bytes of data if it wishes to
+*	receive N bytes of data.
+* 
+* Although this function takes entire buffers as arguments, the driver can only +* transfer a limited number of bytes at a time, limited by the size of the +* FIFO. A call to this function only starts the transfer, then subsequent +* transfers of the data is performed by the interrupt service routine until +* the entire buffer has been transferred. The status callback function is +* called when the entire buffer has been sent/received. +* +* This function is non-blocking. The SetSlaveSelect function must be called +* prior to this function. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* @param SendBufPtr is a pointer to a data buffer that needs to be +* transmitted. This buffer must not be NULL. +* @param RecvBufPtr is a pointer to a buffer for received data. +* This argument can be NULL if do not care about receiving. +* @param ByteCount contains the number of bytes to send/receive. +* The number of bytes received always equals the number of bytes +* sent. +* +* @return +* - XST_SUCCESS if the buffers are successfully handed off to the +* device for transfer. +* - XST_DEVICE_BUSY indicates that a data transfer is already in +* progress. This is determined by the driver. +* +* @note +* +* This function is not thread-safe. The higher layer software must ensure that +* no two threads are transferring data on the QSPI bus at the same time. +* +******************************************************************************/ +s32 XQspiPs_Transfer(XQspiPs *InstancePtr, u8 *SendBufPtr, u8 *RecvBufPtr, + u32 ByteCount) +{ + u32 StatusReg; + u32 ConfigReg; + u8 Instruction; + u32 Data; + unsigned int Index; + u8 TransCount = 0; + XQspiPsInstFormat *CurrInst; + XQspiPsInstFormat NewInst[2]; + u8 SwitchFlag = 0; + + CurrInst = &NewInst[0]; + + /* + * The RecvBufPtr argument can be null + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(SendBufPtr != NULL); + Xil_AssertNonvoid(ByteCount > 0); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Check whether there is another transfer in progress. Not thread-safe. + */ + if (InstancePtr->IsBusy) { + return XST_DEVICE_BUSY; + } + + /* + * Set the busy flag, which will be cleared in the ISR when the + * transfer is entirely done. + */ + InstancePtr->IsBusy = TRUE; + + /* + * Set up buffer pointers. + */ + InstancePtr->SendBufferPtr = SendBufPtr; + InstancePtr->RecvBufferPtr = RecvBufPtr; + + InstancePtr->RequestedBytes = ByteCount; + InstancePtr->RemainingBytes = ByteCount; + + /* + * The first byte with every chip-select assertion is always + * expected to be an instruction for flash interface mode + */ + Instruction = *InstancePtr->SendBufferPtr; + + for (Index = 0 ; Index < ARRAY_SIZE(FlashInst); Index++) { + if (Instruction == FlashInst[Index].OpCode) { + break; + } + } + + /* + * Set the RX FIFO threshold + */ + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_RXWR_OFFSET, XQSPIPS_RXFIFO_THRESHOLD_OPT); + + /* + * If the slave select is "Forced" or under manual control, + * set the slave select now, before beginning the transfer. + */ + if (XQspiPs_IsManualChipSelect(InstancePtr)) { + ConfigReg = XQspiPs_ReadReg(InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET); + ConfigReg &= ~XQSPIPS_CR_SSCTRL_MASK; + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET, + ConfigReg); + } + + /* + * Enable the device. + */ + XQspiPs_Enable(InstancePtr); + + /* + * Clear all the interrrupts. + */ + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPS_SR_OFFSET, + XQSPIPS_IXR_WR_TO_CLR_MASK); + + if (Index < ARRAY_SIZE(FlashInst)) { + CurrInst = &FlashInst[Index]; + /* + * Check for WRSR instruction which has different size for + * Spansion (3 bytes) and Micron (2 bytes) + */ + if ((CurrInst->OpCode == XQSPIPS_FLASH_OPCODE_WRSR) && + (ByteCount == 3)) { + CurrInst->InstSize = 3; + CurrInst->TxOffset = XQSPIPS_TXD_11_OFFSET; + } + } + + /* + * If instruction not present in table + */ + if (Index == ARRAY_SIZE(FlashInst)) { + /* + * Assign current instruction, size and TXD register to be used + * The InstSize mentioned in case of instructions greater than + * 4 bytes is not the actual size, but is indicative of + * the TXD register used. + * The remaining bytes of the instruction will be transmitted + * through TXD0 below. + */ + switch (ByteCount%4) { + case XQSPIPS_SIZE_ONE: + CurrInst->OpCode = Instruction; + CurrInst->InstSize = XQSPIPS_SIZE_ONE; + CurrInst->TxOffset = XQSPIPS_TXD_01_OFFSET; + if (ByteCount > 4) { + SwitchFlag = 1; + } + break; + case XQSPIPS_SIZE_TWO: + CurrInst->OpCode = Instruction; + CurrInst->InstSize = XQSPIPS_SIZE_TWO; + CurrInst->TxOffset = XQSPIPS_TXD_10_OFFSET; + if (ByteCount > 4) { + SwitchFlag = 1; + } + break; + case XQSPIPS_SIZE_THREE: + CurrInst->OpCode = Instruction; + CurrInst->InstSize = XQSPIPS_SIZE_THREE; + CurrInst->TxOffset = XQSPIPS_TXD_11_OFFSET; + if (ByteCount > 4) { + SwitchFlag = 1; + } + break; + default: + CurrInst->OpCode = Instruction; + CurrInst->InstSize = XQSPIPS_SIZE_FOUR; + CurrInst->TxOffset = XQSPIPS_TXD_00_OFFSET; + break; + } + } + + /* + * If the instruction size in not 4 bytes then the data received needs + * to be shifted + */ + if (CurrInst->InstSize != 4) { + InstancePtr->ShiftReadData = 1; + } else { + InstancePtr->ShiftReadData = 0; + } + + /* Get the complete command (flash inst + address/data) */ + Data = *((u32 *)InstancePtr->SendBufferPtr); + InstancePtr->SendBufferPtr += CurrInst->InstSize; + InstancePtr->RemainingBytes -= CurrInst->InstSize; + if (InstancePtr->RemainingBytes < 0) { + InstancePtr->RemainingBytes = 0; + } + + /* Write the command to the FIFO */ + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + CurrInst->TxOffset, Data); + TransCount++; + + /* + * If switching from TXD1/2/3 to TXD0, then start transfer and + * check for FIFO empty + */ + if (SwitchFlag == 1) { + SwitchFlag = 0; + /* + * If, in Manual Start mode, start the transfer. + */ + if (XQspiPs_IsManualStart(InstancePtr)) { + ConfigReg = XQspiPs_ReadReg( + InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET); + ConfigReg |= XQSPIPS_CR_MANSTRT_MASK; + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET, ConfigReg); + } + /* + * Wait for the transfer to finish by polling Tx fifo status. + */ + do { + StatusReg = XQspiPs_ReadReg( + InstancePtr->Config.BaseAddress, + XQSPIPS_SR_OFFSET); + } while ((StatusReg & XQSPIPS_IXR_TXOW_MASK) == 0); + + } + + /* + * Fill the Tx FIFO with as many bytes as it takes (or as many as + * we have to send). + */ + while ((InstancePtr->RemainingBytes > 0) && + (TransCount < XQSPIPS_FIFO_DEPTH)) { + /* + * In case of Write fill the Tx FIFO with data to be transmitted. + * In case of Read fill the Tx FIFO with DUMMY bytes. + */ + if (!InstancePtr->RecvBufferPtr) { + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_TXD_00_OFFSET, + *((u32 *)InstancePtr->SendBufferPtr)); + InstancePtr->SendBufferPtr += 4; + } else { + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_TXD_00_OFFSET, + XQSPIPS_DUMMY_TX_DATA); + } + InstancePtr->RemainingBytes -= 4; + if (InstancePtr->RemainingBytes < 0) { + InstancePtr->RemainingBytes = 0; + } + TransCount++; + } + + /* + * Enable QSPI interrupts (connecting to the interrupt controller and + * enabling interrupts should have been done by the caller). + */ + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_IER_OFFSET, XQSPIPS_IXR_RXNEMPTY_MASK | + XQSPIPS_IXR_TXOW_MASK | XQSPIPS_IXR_RXOVR_MASK | + XQSPIPS_IXR_TXUF_MASK); + + /* + * If, in Manual Start mode, Start the transfer. + */ + if (XQspiPs_IsManualStart(InstancePtr)) { + ConfigReg = XQspiPs_ReadReg(InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET); + ConfigReg |= XQSPIPS_CR_MANSTRT_MASK; + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET, ConfigReg); + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* Transfers specified data on the QSPI bus in polled mode. +* +* The caller has the option of providing two different buffers for send and +* receive, or one buffer for both send and receive, or no buffer for receive. +* The receive buffer must be at least as big as the send buffer to prevent +* unwanted memory writes. This implies that the byte count passed in as an +* argument must be the smaller of the two buffers if they differ in size. +* Here are some sample usages: +*
+*   XQspiPs_PolledTransfer(InstancePtr, SendBuf, RecvBuf, ByteCount)
+*	The caller wishes to send and receive, and provides two different
+*	buffers for send and receive.
+*
+*   XQspiPs_PolledTransfer(InstancePtr, SendBuf, NULL, ByteCount)
+*	The caller wishes only to send and does not care about the received
+*	data. The driver ignores the received data in this case.
+*
+*   XQspiPs_PolledTransfer(InstancePtr, SendBuf, SendBuf, ByteCount)
+*	The caller wishes to send and receive, but provides the same buffer
+*	for doing both. The driver sends the data and overwrites the send
+*	buffer with received data as it transfers the data.
+*
+*   XQspiPs_PolledTransfer(InstancePtr, RecvBuf, RecvBuf, ByteCount)
+*	The caller wishes to only receive and does not care about sending
+*	data.  In this case, the caller must still provide a send buffer, but
+*	it can be the same as the receive buffer if the caller does not care
+*	what it sends.  The device must send N bytes of data if it wishes to
+*	receive N bytes of data.
+*
+* 
+* +* @param InstancePtr is a pointer to the XQspiPs instance. +* @param SendBufPtr is a pointer to a data buffer that needs to be +* transmitted. This buffer must not be NULL. +* @param RecvBufPtr is a pointer to a buffer for received data. +* This argument can be NULL if do not care about receiving. +* @param ByteCount contains the number of bytes to send/receive. +* The number of bytes received always equals the number of bytes +* sent. +* @return +* - XST_SUCCESS if the buffers are successfully handed off to the +* device for transfer. +* - XST_DEVICE_BUSY indicates that a data transfer is already in +* progress. This is determined by the driver. +* +* @note +* +* This function is not thread-safe. The higher layer software must ensure that +* no two threads are transferring data on the QSPI bus at the same time. +* +******************************************************************************/ +s32 XQspiPs_PolledTransfer(XQspiPs *InstancePtr, u8 *SendBufPtr, + u8 *RecvBufPtr, u32 ByteCount) +{ + u32 StatusReg; + u32 ConfigReg; + u8 Instruction; + u32 Data; + u8 TransCount; + unsigned int Index; + XQspiPsInstFormat *CurrInst; + XQspiPsInstFormat NewInst[2]; + u8 SwitchFlag = 0; + u8 IsManualStart = FALSE; + u32 RxCount = 0; + + CurrInst = &NewInst[0]; + /* + * The RecvBufPtr argument can be NULL. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(SendBufPtr != NULL); + Xil_AssertNonvoid(ByteCount > 0); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Check whether there is another transfer in progress. Not thread-safe. + */ + if (InstancePtr->IsBusy) { + return XST_DEVICE_BUSY; + } + + /* + * Set the busy flag, which will be cleared when the transfer is + * entirely done. + */ + InstancePtr->IsBusy = TRUE; + + /* + * Set up buffer pointers. + */ + InstancePtr->SendBufferPtr = SendBufPtr; + InstancePtr->RecvBufferPtr = RecvBufPtr; + + InstancePtr->RequestedBytes = ByteCount; + InstancePtr->RemainingBytes = ByteCount; + + /* + * The first byte with every chip-select assertion is always + * expected to be an instruction for flash interface mode + */ + Instruction = *InstancePtr->SendBufferPtr; + + for (Index = 0 ; Index < ARRAY_SIZE(FlashInst); Index++) { + if (Instruction == FlashInst[Index].OpCode) { + break; + } + } + + /* + * Set the RX FIFO threshold + */ + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_RXWR_OFFSET, XQSPIPS_RXFIFO_THRESHOLD_OPT); + + /* + * If the slave select is "Forced" or under manual control, + * set the slave select now, before beginning the transfer. + */ + if (XQspiPs_IsManualChipSelect(InstancePtr)) { + ConfigReg = XQspiPs_ReadReg(InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET); + ConfigReg &= ~XQSPIPS_CR_SSCTRL_MASK; + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET, + ConfigReg); + } + + /* + * Enable the device. + */ + XQspiPs_Enable(InstancePtr); + + if (Index < ARRAY_SIZE(FlashInst)) { + + CurrInst = &FlashInst[Index]; + /* + * Check for WRSR instruction which has different size for + * Spansion (3 bytes) and Micron (2 bytes) + */ + if ((CurrInst->OpCode == XQSPIPS_FLASH_OPCODE_WRSR) && + (ByteCount == 3)) { + CurrInst->InstSize = 3; + CurrInst->TxOffset = XQSPIPS_TXD_11_OFFSET; + } + } + + /* + * If instruction not present in table + */ + if (Index == ARRAY_SIZE(FlashInst)) { + /* + * Assign current instruction, size and TXD register to be used. + * The InstSize mentioned in case of instructions greater than 4 bytes + * is not the actual size, but is indicative of the TXD register used. + * The remaining bytes of the instruction will be transmitted + * through TXD0 below. + */ + switch (ByteCount % 4) { + case XQSPIPS_SIZE_ONE: + CurrInst->OpCode = Instruction; + CurrInst->InstSize = XQSPIPS_SIZE_ONE; + CurrInst->TxOffset = XQSPIPS_TXD_01_OFFSET; + if (ByteCount > 4) { + SwitchFlag = 1; + } + break; + case XQSPIPS_SIZE_TWO: + CurrInst->OpCode = Instruction; + CurrInst->InstSize = XQSPIPS_SIZE_TWO; + CurrInst->TxOffset = XQSPIPS_TXD_10_OFFSET; + if (ByteCount > 4) { + SwitchFlag = 1; + } + break; + case XQSPIPS_SIZE_THREE: + CurrInst->OpCode = Instruction; + CurrInst->InstSize = XQSPIPS_SIZE_THREE; + CurrInst->TxOffset = XQSPIPS_TXD_11_OFFSET; + if (ByteCount > 4) { + SwitchFlag = 1; + } + break; + default: + CurrInst->OpCode = Instruction; + CurrInst->InstSize = XQSPIPS_SIZE_FOUR; + CurrInst->TxOffset = XQSPIPS_TXD_00_OFFSET; + break; + } + } + + /* + * If the instruction size in not 4 bytes then the data received needs + * to be shifted + */ + if (CurrInst->InstSize != 4) { + InstancePtr->ShiftReadData = 1; + } else { + InstancePtr->ShiftReadData = 0; + } + TransCount = 0; + /* Get the complete command (flash inst + address/data) */ + Data = *((u32 *)InstancePtr->SendBufferPtr); + InstancePtr->SendBufferPtr += CurrInst->InstSize; + InstancePtr->RemainingBytes -= CurrInst->InstSize; + if (InstancePtr->RemainingBytes < 0) { + InstancePtr->RemainingBytes = 0; + } + + /* Write the command to the FIFO */ + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + CurrInst->TxOffset, Data); + ++TransCount; + + /* + * If switching from TXD1/2/3 to TXD0, then start transfer and + * check for FIFO empty + */ + if (SwitchFlag == 1) { + SwitchFlag = 0; + /* + * If, in Manual Start mode, start the transfer. + */ + if (XQspiPs_IsManualStart(InstancePtr)) { + ConfigReg = XQspiPs_ReadReg( + InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET); + ConfigReg |= XQSPIPS_CR_MANSTRT_MASK; + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET, ConfigReg); + } + /* + * Wait for the transfer to finish by polling Tx fifo status. + */ + do { + StatusReg = XQspiPs_ReadReg( + InstancePtr->Config.BaseAddress, + XQSPIPS_SR_OFFSET); + } while ((StatusReg & XQSPIPS_IXR_TXOW_MASK) == 0); + + } + + /* + * Check if manual start is selected and store it in a + * local varibale for reference. This is to avoid reading + * the config register everytime. + */ + IsManualStart = XQspiPs_IsManualStart(InstancePtr); + + /* + * Fill the DTR/FIFO with as many bytes as it will take (or as + * many as we have to send). + */ + while ((InstancePtr->RemainingBytes > 0) && + (TransCount < XQSPIPS_FIFO_DEPTH)) { + /* + * In case of Write fill the Tx FIFO with data to be transmitted. + * In case of Read fill the Tx FIFO with DUMMY bytes. + */ + if (!InstancePtr->RecvBufferPtr) { + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_TXD_00_OFFSET, + *((u32 *)InstancePtr->SendBufferPtr)); + InstancePtr->SendBufferPtr += 4; + } else { + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_TXD_00_OFFSET, + XQSPIPS_DUMMY_TX_DATA); + } + InstancePtr->RemainingBytes -= 4; + if (InstancePtr->RemainingBytes < 0) { + InstancePtr->RemainingBytes = 0; + } + ++TransCount; + } + + while ((InstancePtr->RemainingBytes > 0) || + (InstancePtr->RequestedBytes > 0)) { + + /* + * Fill the TX FIFO with RX threshold no. of entries (or as + * many as we have to send, in case that's less). + */ + while ((InstancePtr->RemainingBytes > 0) && + (TransCount < XQSPIPS_RXFIFO_THRESHOLD_OPT)) { + /* + * In case of Write fill the Tx FIFO with data to be transmitted. + * In case of Read fill the Tx FIFO with DUMMY bytes. + */ + if (!InstancePtr->RecvBufferPtr) { + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_TXD_00_OFFSET, + *((u32 *)InstancePtr->SendBufferPtr)); + InstancePtr->SendBufferPtr += 4; + } else { + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_TXD_00_OFFSET, + XQSPIPS_DUMMY_TX_DATA); + } + InstancePtr->RemainingBytes -= 4; + if (InstancePtr->RemainingBytes < 0) { + InstancePtr->RemainingBytes = 0; + } + ++TransCount; + } + + /* + * If, in Manual Start mode, start the transfer. + */ + if (IsManualStart == TRUE) { + ConfigReg = XQspiPs_ReadReg( + InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET); + ConfigReg |= XQSPIPS_CR_MANSTRT_MASK; + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET, ConfigReg); + } + + /* + * Reset TransCount - this is only used to fill TX FIFO + * in the above loop; + * RxCount is used to keep track of data received + */ + TransCount = 0; + + /* + * Wait for RX FIFO to reach threshold (or) + * TX FIFO to become empty. + * The latter check is required for + * small transfers (<32 words) and + * when the last chunk in a large data transfer is < 32 words. + */ + + do { + StatusReg = XQspiPs_ReadReg( + InstancePtr->Config.BaseAddress, + XQSPIPS_SR_OFFSET); + } while (((StatusReg & XQSPIPS_IXR_TXOW_MASK) == 0) && + ((StatusReg & XQSPIPS_IXR_RXNEMPTY_MASK) == 0)); + + /* + * A transmit has just completed. Process received data + * and check for more data to transmit. + * First get the data received as a result of the + * transmit that just completed. Receive data based on the + * count obtained while filling tx fifo. Always get + * the received data, but only fill the receive + * buffer if it points to something (the upper layer + * software may not care to receive data). + */ + while ((InstancePtr->RequestedBytes > 0) && + (RxCount < XQSPIPS_RXFIFO_THRESHOLD_OPT)) { + u32 Data; + + RxCount++; + + if (InstancePtr->RecvBufferPtr != NULL) { + if (InstancePtr->RequestedBytes < 4) { + Data = XQspiPs_ReadReg(InstancePtr->Config.BaseAddress, + XQSPIPS_RXD_OFFSET); + XQspiPs_GetReadData(InstancePtr, Data, + InstancePtr->RequestedBytes); + } else { + (*(u32 *)InstancePtr->RecvBufferPtr) = + XQspiPs_ReadReg(InstancePtr->Config.BaseAddress, + XQSPIPS_RXD_OFFSET); + InstancePtr->RecvBufferPtr += 4; + InstancePtr->RequestedBytes -= 4; + if (InstancePtr->RequestedBytes < 0) { + InstancePtr->RequestedBytes = 0; + } + } + } else { + Data = XQspiPs_ReadReg(InstancePtr->Config.BaseAddress, + XQSPIPS_RXD_OFFSET); + InstancePtr->RequestedBytes -= 4; + } + } + RxCount = 0; + } + + /* + * If the Slave select lines are being manually controlled, disable + * them because the transfer is complete. + */ + if (XQspiPs_IsManualChipSelect(InstancePtr)) { + ConfigReg = XQspiPs_ReadReg(InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET); + ConfigReg |= XQSPIPS_CR_SSCTRL_MASK; + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET, ConfigReg); + } + + /* + * Clear the busy flag. + */ + InstancePtr->IsBusy = FALSE; + + /* + * Disable the device. + */ + XQspiPs_Disable(InstancePtr); + + /* + * Reset the RX FIFO threshold to one + */ + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_RXWR_OFFSET, XQSPIPS_RXWR_RESET_VALUE); + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* Read the flash in Linear QSPI mode. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* @param RecvBufPtr is a pointer to a buffer for received data. +* @param Address is the starting address within the flash from +* from where data needs to be read. +* @param ByteCount contains the number of bytes to receive. +* +* @return +* - XST_SUCCESS if read is performed +* - XST_FAILURE if Linear mode is not set +* +* @note None. +* +* +******************************************************************************/ +int XQspiPs_LqspiRead(XQspiPs *InstancePtr, u8 *RecvBufPtr, + u32 Address, unsigned ByteCount) +{ + int Status = (int)XST_SUCCESS; + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(RecvBufPtr != NULL); + Xil_AssertNonvoid(ByteCount > 0); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + +#ifndef XPAR_PS7_QSPI_LINEAR_0_S_AXI_BASEADDR +#define XPAR_PS7_QSPI_LINEAR_0_S_AXI_BASEADDR 0xFC000000 +#endif + /* + * Enable the controller + */ + XQspiPs_Enable(InstancePtr); + + if (XQspiPs_GetLqspiConfigReg(InstancePtr) & + XQSPIPS_LQSPI_CR_LINEAR_MASK) { + memcpy((void *)RecvBufPtr, + (const void *)(XPAR_PS7_QSPI_LINEAR_0_S_AXI_BASEADDR + + Address), + (size_t)ByteCount); + Status = (int)XST_SUCCESS; + } else { + Status = (int)XST_FAILURE; + } + + /* + * Disable the controller + */ + XQspiPs_Disable(InstancePtr); + + return Status; +} + +/*****************************************************************************/ +/** +* +* Selects the slave with which the master communicates. +* +* The user is not allowed to select the slave while a transfer is in progress. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* +* @return +* - XST_SUCCESS if the slave is selected or deselected +* successfully. +* - XST_DEVICE_BUSY if a transfer is in progress, slave cannot be +* changed. +* +* @note +* +* This function only sets the slave which will be selected when a transfer +* occurs. The slave is not selected when the QSPI is idle. +* +******************************************************************************/ +int XQspiPs_SetSlaveSelect(XQspiPs *InstancePtr) +{ + u32 ConfigReg; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Do not allow the slave select to change while a transfer is in + * progress. Not thread-safe. + */ + if (InstancePtr->IsBusy) { + return XST_DEVICE_BUSY; + } + + /* + * Select the slave + */ + ConfigReg = XQspiPs_ReadReg(InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET); + ConfigReg &= ~XQSPIPS_CR_SSCTRL_MASK; + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET, ConfigReg); + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* Sets the status callback function, the status handler, which the driver +* calls when it encounters conditions that should be reported to upper +* layer software. The handler executes in an interrupt context, so it must +* minimize the amount of processing performed. One of the following status +* events is passed to the status handler. +* +*
+*
+* XST_SPI_TRANSFER_DONE		The requested data transfer is done
+*
+* XST_SPI_TRANSMIT_UNDERRUN	As a slave device, the master clocked data
+*				but there were none available in the transmit
+*				register/FIFO. This typically means the slave
+*				application did not issue a transfer request
+*				fast enough, or the processor/driver could not
+*				fill the transmit register/FIFO fast enough.
+*
+* XST_SPI_RECEIVE_OVERRUN	The QSPI device lost data. Data was received
+*				but the receive data register/FIFO was full.
+*
+* 
+* @param InstancePtr is a pointer to the XQspiPs instance. +* @param CallBackRef is the upper layer callback reference passed back +* when the callback function is invoked. +* @param FuncPtr is the pointer to the callback function. +* +* @return None. +* +* @note +* +* The handler is called within interrupt context, so it should do its work +* quickly and queue potentially time-consuming work to a task-level thread. +* +******************************************************************************/ +void XQspiPs_SetStatusHandler(XQspiPs *InstancePtr, void *CallBackRef, + XQspiPs_StatusHandler FuncPtr) +{ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(FuncPtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + InstancePtr->StatusHandler = FuncPtr; + InstancePtr->StatusRef = CallBackRef; +} + +/*****************************************************************************/ +/** +* +* This is a stub for the status callback. The stub is here in case the upper +* layers forget to set the handler. +* +* @param CallBackRef is a pointer to the upper layer callback reference +* @param StatusEvent is the event that just occurred. +* @param ByteCount is the number of bytes transferred up until the event +* occurred. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +static void StubStatusHandler(void *CallBackRef, u32 StatusEvent, + unsigned ByteCount) +{ + (void) CallBackRef; + (void) StatusEvent; + (void) ByteCount; + + Xil_AssertVoidAlways(); +} + +/*****************************************************************************/ +/** +* +* The interrupt handler for QSPI interrupts. This function must be connected +* by the user to an interrupt controller. +* +* The interrupts that are handled are: +* +* +* - Data Transmit Register (FIFO) Empty. This interrupt is generated when the +* transmit register or FIFO is empty. The driver uses this interrupt during a +* transmission to continually send/receive data until the transfer is done. +* +* - Data Transmit Register (FIFO) Underflow. This interrupt is generated when +* the QSPI device, when configured as a slave, attempts to read an empty +* DTR/FIFO. An empty DTR/FIFO usually means that software is not giving the +* device data in a timely manner. No action is taken by the driver other than +* to inform the upper layer software of the error. +* +* - Data Receive Register (FIFO) Overflow. This interrupt is generated when the +* QSPI device attempts to write a received byte to an already full DRR/FIFO. +* A full DRR/FIFO usually means software is not emptying the data in a timely +* manner. No action is taken by the driver other than to inform the upper +* layer software of the error. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* +* @return None. +* +* @note +* +* The slave select register is being set to deselect the slave when a transfer +* is complete. +* +******************************************************************************/ +void XQspiPs_InterruptHandler(void *InstancePtr) +{ + XQspiPs *QspiPtr = (XQspiPs *)InstancePtr; + u32 IntrStatus; + u32 ConfigReg; + u32 Data; + u32 TransCount; + u32 Count = 0; + unsigned BytesDone; /* Number of bytes done so far. */ + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(QspiPtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Immediately clear the interrupts in case the ISR causes another + * interrupt to be generated. If we clear at the end of the ISR, + * we may miss newly generated interrupts. This occurs because we + * transmit from within the ISR, which could potentially cause another + * TX_EMPTY interrupt. + */ + IntrStatus = XQspiPs_ReadReg(QspiPtr->Config.BaseAddress, + XQSPIPS_SR_OFFSET); + XQspiPs_WriteReg(QspiPtr->Config.BaseAddress, XQSPIPS_SR_OFFSET, + (IntrStatus & XQSPIPS_IXR_WR_TO_CLR_MASK)); + XQspiPs_WriteReg(QspiPtr->Config.BaseAddress, XQSPIPS_IDR_OFFSET, + XQSPIPS_IXR_TXOW_MASK | XQSPIPS_IXR_RXNEMPTY_MASK | + XQSPIPS_IXR_RXOVR_MASK | XQSPIPS_IXR_TXUF_MASK); + + if ((IntrStatus & XQSPIPS_IXR_TXOW_MASK) || + (IntrStatus & XQSPIPS_IXR_RXNEMPTY_MASK)) { + + /* + * Rx FIFO has just reached threshold no. of entries. + * Read threshold no. of entries from RX FIFO + * Another possiblity of entering this loop is when + * the last byte has been transmitted and TX FIFO is empty, + * in which case, read all the data from RX FIFO. + * Always get the received data, but only fill the + * receive buffer if it is not null (it can be null when + * the device does not care to receive data). + */ + TransCount = QspiPtr->RequestedBytes - QspiPtr->RemainingBytes; + if (TransCount % 4) { + TransCount = TransCount/4 + 1; + } else { + TransCount = TransCount/4; + } + + while ((Count < TransCount) && + (Count < XQSPIPS_RXFIFO_THRESHOLD_OPT)) { + + if (QspiPtr->RecvBufferPtr != NULL) { + if (QspiPtr->RequestedBytes < 4) { + Data = XQspiPs_ReadReg(QspiPtr->Config.BaseAddress, + XQSPIPS_RXD_OFFSET); + XQspiPs_GetReadData(QspiPtr, Data, + QspiPtr->RequestedBytes); + } else { + (*(u32 *)QspiPtr->RecvBufferPtr) = + XQspiPs_ReadReg(QspiPtr->Config.BaseAddress, + XQSPIPS_RXD_OFFSET); + QspiPtr->RecvBufferPtr += 4; + QspiPtr->RequestedBytes -= 4; + if (QspiPtr->RequestedBytes < 0) { + QspiPtr->RequestedBytes = 0; + } + } + } else { + XQspiPs_ReadReg(QspiPtr->Config.BaseAddress, + XQSPIPS_RXD_OFFSET); + QspiPtr->RequestedBytes -= 4; + if (QspiPtr->RequestedBytes < 0) { + QspiPtr->RequestedBytes = 0; + } + + } + Count++; + } + Count = 0; + /* + * Interrupt asserted as TX_OW got asserted + * See if there is more data to send. + * Fill TX FIFO with RX threshold no. of entries or + * remaining entries (in case that is less than threshold) + */ + while ((QspiPtr->RemainingBytes > 0) && + (Count < XQSPIPS_RXFIFO_THRESHOLD_OPT)) { + /* + * Send more data. + * In case of Write fill the Tx FIFO with data to be transmitted. + * In case of Read fill the Tx FIFO with DUMMY bytes. + */ + if (!QspiPtr->RecvBufferPtr) { + XQspiPs_WriteReg(QspiPtr->Config.BaseAddress, + XQSPIPS_TXD_00_OFFSET, + *((u32 *)QspiPtr->SendBufferPtr)); + QspiPtr->SendBufferPtr += 4; + } else { + XQspiPs_WriteReg(QspiPtr->Config.BaseAddress, + XQSPIPS_TXD_00_OFFSET, + XQSPIPS_DUMMY_TX_DATA); + } + QspiPtr->RemainingBytes -= 4; + if (QspiPtr->RemainingBytes < 0) { + QspiPtr->RemainingBytes = 0; + } + + Count++; + } + + if ((QspiPtr->RemainingBytes == 0) && + (QspiPtr->RequestedBytes == 0)) { + /* + * No more data to send. Disable the interrupt + * and inform the upper layer software that the + * transfer is done. The interrupt will be re-enabled + * when another transfer is initiated. + */ + XQspiPs_WriteReg(QspiPtr->Config.BaseAddress, + XQSPIPS_IDR_OFFSET, + XQSPIPS_IXR_RXNEMPTY_MASK | + XQSPIPS_IXR_TXOW_MASK | + XQSPIPS_IXR_RXOVR_MASK | + XQSPIPS_IXR_TXUF_MASK); + + /* + * If the Slave select is being manually controlled, + * disable it because the transfer is complete. + */ + if (XQspiPs_IsManualChipSelect(InstancePtr)) { + ConfigReg = XQspiPs_ReadReg( + QspiPtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET); + ConfigReg |= XQSPIPS_CR_SSCTRL_MASK; + XQspiPs_WriteReg(QspiPtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET, + ConfigReg); + } + + /* + * Clear the busy flag. + */ + QspiPtr->IsBusy = FALSE; + + /* + * Disable the device. + */ + XQspiPs_Disable(QspiPtr); + + /* + * Reset the RX FIFO threshold to one + */ + XQspiPs_WriteReg(QspiPtr->Config.BaseAddress, + XQSPIPS_RXWR_OFFSET, XQSPIPS_RXWR_RESET_VALUE); + + QspiPtr->StatusHandler(QspiPtr->StatusRef, + XST_SPI_TRANSFER_DONE, + QspiPtr->RequestedBytes); + } else { + /* + * Enable the TXOW interrupt. + */ + XQspiPs_WriteReg(QspiPtr->Config.BaseAddress, + XQSPIPS_IER_OFFSET, + XQSPIPS_IXR_RXNEMPTY_MASK | + XQSPIPS_IXR_TXOW_MASK | + XQSPIPS_IXR_RXOVR_MASK | + XQSPIPS_IXR_TXUF_MASK); + /* + * If, in Manual Start mode, start the transfer. + */ + if (XQspiPs_IsManualStart(QspiPtr)) { + ConfigReg = XQspiPs_ReadReg( + QspiPtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET); + ConfigReg |= XQSPIPS_CR_MANSTRT_MASK; + XQspiPs_WriteReg( + QspiPtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET, ConfigReg); + } + } + } + + /* + * Check for overflow and underflow errors. + */ + if (IntrStatus & XQSPIPS_IXR_RXOVR_MASK) { + BytesDone = QspiPtr->RequestedBytes - QspiPtr->RemainingBytes; + QspiPtr->IsBusy = FALSE; + + /* + * If the Slave select lines is being manually controlled, + * disable it because the transfer is complete. + */ + if (XQspiPs_IsManualChipSelect(InstancePtr)) { + ConfigReg = XQspiPs_ReadReg( + QspiPtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET); + ConfigReg |= XQSPIPS_CR_SSCTRL_MASK; + XQspiPs_WriteReg(QspiPtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET, ConfigReg); + } + + /* + * Disable the device. + */ + XQspiPs_Disable(QspiPtr); + + /* + * Reset the RX FIFO threshold to one + */ + XQspiPs_WriteReg(QspiPtr->Config.BaseAddress, + XQSPIPS_RXWR_OFFSET, XQSPIPS_RXWR_RESET_VALUE); + + QspiPtr->StatusHandler(QspiPtr->StatusRef, + XST_SPI_RECEIVE_OVERRUN, BytesDone); + } + + if (IntrStatus & XQSPIPS_IXR_TXUF_MASK) { + BytesDone = QspiPtr->RequestedBytes - QspiPtr->RemainingBytes; + + QspiPtr->IsBusy = FALSE; + /* + * If the Slave select lines is being manually controlled, + * disable it because the transfer is complete. + */ + if (XQspiPs_IsManualChipSelect(InstancePtr)) { + ConfigReg = XQspiPs_ReadReg( + QspiPtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET); + ConfigReg |= XQSPIPS_CR_SSCTRL_MASK; + XQspiPs_WriteReg(QspiPtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET, ConfigReg); + } + + /* + * Disable the device. + */ + XQspiPs_Disable(QspiPtr); + + /* + * Reset the RX FIFO threshold to one + */ + XQspiPs_WriteReg(QspiPtr->Config.BaseAddress, + XQSPIPS_RXWR_OFFSET, XQSPIPS_RXWR_RESET_VALUE); + + QspiPtr->StatusHandler(QspiPtr->StatusRef, + XST_SPI_TRANSMIT_UNDERRUN, BytesDone); + } +} + + +/*****************************************************************************/ +/** +* +* Copies data from Data to the Receive buffer. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* @param Data is the data which needs to be copied to the Rx buffer. +* @param Size is the number of bytes to be copied to the Receive buffer. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +static void XQspiPs_GetReadData(XQspiPs *InstancePtr, u32 Data, u8 Size) +{ + u8 DataByte3; + + if (InstancePtr->RecvBufferPtr) { + switch (Size) { + case 1: + if (InstancePtr->ShiftReadData == 1) { + *((u8 *)InstancePtr->RecvBufferPtr) = + ((Data & 0xFF000000) >> 24); + } else { + *((u8 *)InstancePtr->RecvBufferPtr) = + (Data & 0xFF); + } + InstancePtr->RecvBufferPtr += 1; + break; + case 2: + if (InstancePtr->ShiftReadData == 1) { + *((u16 *)InstancePtr->RecvBufferPtr) = + ((Data >> 16) & 0xFF00) | + ((Data >> 8) & 0xFF); + } else { + *((u16 *)InstancePtr->RecvBufferPtr) = + (Data & 0xFFFF); + } + InstancePtr->RecvBufferPtr += 2; + break; + case 3: + if (InstancePtr->ShiftReadData == 1) { + *((u16 *)InstancePtr->RecvBufferPtr) = + ((Data & 0x00FFFF00) >> 8); + InstancePtr->RecvBufferPtr += 2; + DataByte3 = ((Data & 0xFF000000) >> 24); + *((u8 *)InstancePtr->RecvBufferPtr) = DataByte3; + } else { + *((u16 *)InstancePtr->RecvBufferPtr) = + (Data & 0xFFFF); + InstancePtr->RecvBufferPtr += 2; + DataByte3 = ((Data & 0x00FF0000) >> 16); + *((u8 *)InstancePtr->RecvBufferPtr) = DataByte3; + } + InstancePtr->RecvBufferPtr += 1; + break; + default: + /* This will never execute */ + break; + } + } + InstancePtr->ShiftReadData = 0; + InstancePtr->RequestedBytes -= Size; + if (InstancePtr->RequestedBytes < 0) { + InstancePtr->RequestedBytes = 0; + } +} +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/qspips_v3_6/src/xqspips.h b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/qspips_v3_6/src/xqspips.h new file mode 100644 index 0000000..0255bc2 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/qspips_v3_6/src/xqspips.h @@ -0,0 +1,804 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xqspips.h +* @addtogroup qspips_v3_6 +* @{ +* @details +* +* This file contains the implementation of the XQspiPs driver. It supports only +* master mode. User documentation for the driver functions is contained in this +* file in the form of comment blocks at the front of each function. +* +* A QSPI device connects to an QSPI bus through a 4-wire serial interface. +* The QSPI bus is a full-duplex, synchronous bus that facilitates communication +* between one master and one slave. The device is always full-duplex, +* which means that for every byte sent, one is received, and vice-versa. +* The master controls the clock, so it can regulate when it wants to +* send or receive data. The slave is under control of the master, it must +* respond quickly since it has no control of the clock and must send/receive +* data as fast or as slow as the master does. +* +* Linear Mode +* The Linear Quad-SPI Controller extends the existing Quad-SPI Controller�s +* functionality by adding a linear addressing scheme that allows the SPI flash +* memory subsystem to behave like a typical ROM device. The new feature hides +* the normal SPI protocol from a master reading from the SPI flash memory. The +* feature improves both the user friendliness and the overall read memory +* throughput over that of the current Quad-SPI Controller by lessening the +* amount of software overheads required and by the use of the faster AXI +* interface. +* +* Initialization & Configuration +* +* The XQspiPs_Config structure is used by the driver to configure itself. This +* configuration structure is typically created by the tool-chain based on HW +* build properties. +* +* To support multiple runtime loading and initialization strategies employed by +* various operating systems, the driver instance can be initialized in the +* following way: +* - XQspiPs_LookupConfig(DeviceId) - Use the device identifier to find +* static configuration structure defined in xqspips_g.c. This is setup +* by the tools. For some operating systems the config structure will be +* initialized by the software and this call is not needed. +* - XQspiPs_CfgInitialize(InstancePtr, CfgPtr, EffectiveAddr) - Uses a +* configuration structure provided by the caller. If running in a system +* with address translation, the provided virtual memory base address +* replaces the physical address present in the configuration structure. +* +* Multiple Masters +* +* More than one master can exist, but arbitration is the responsibility of +* the higher layer software. The device driver does not perform any type of +* arbitration. +* +* Modes of Operation +* +* There are four modes to perform a data transfer and the selection of a mode +* is based on Chip Select(CS) and Start. These two options individually, can +* be controlled either by software(Manual) or hardware(Auto). +* - Auto CS: Chip select is automatically asserted as soon as the first word +* is written into the TXFIFO and de asserted when the TXFIFO becomes +* empty +* - Manual CS: Software must assert and de assert CS. +* - Auto Start: Data transmission starts as soon as there is data in the +* TXFIFO and stalls when the TXFIFO is empty +* - Manual Start: Software must start data transmission at the beginning of +* the transaction or whenever the TXFIFO has become empty +* +* The preferred combination is Manual CS and Auto Start. +* In this combination, the software asserts CS before loading any data into +* TXFIFO. In Auto Start mode, whenever data is in TXFIFO, controller sends it +* out until TXFIFO becomes empty. The software reads the RXFIFO whenever the +* data is available. If no further data, software disables CS. +* +* Risks/challenges of other combinations: +* - Manual CS and Manual Start: Manual Start bit should be set after each +* TXFIFO write otherwise there could be a race condition where the TXFIFO +* becomes empty before the new word is written. In that case the +* transmission stops. +* - Auto CS with Manual or Auto Start: It is very difficult for software to +* keep the TXFIFO filled. Whenever the TXFIFO runs empty, CS is de asserted. +* This results in a single transaction to be split into multiple pieces each +* with its own chip select. This will result in garbage data to be sent. +* +* Interrupts +* +* The user must connect the interrupt handler of the driver, +* XQspiPs_InterruptHandler, to an interrupt system such that it will be +* called when an interrupt occurs. This function does not save and restore +* the processor context such that the user must provide this processing. +* +* The driver handles the following interrupts: +* - Data Transmit Register/FIFO Underflow +* - Data Receive Register/FIFO Not Empty +* - Data Transmit Register/FIFO Overwater +* - Data Receive Register/FIFO Overrun +* +* The Data Transmit Register/FIFO Overwater interrupt -- indicates that the +* QSPI device has transmitted the data available to transmit, and now its data +* register and FIFO is ready to accept more data. The driver uses this +* interrupt to indicate progress while sending data. The driver may have +* more data to send, in which case the data transmit register and FIFO is +* filled for subsequent transmission. When this interrupt arrives and all +* the data has been sent, the driver invokes the status callback with a +* value of XST_SPI_TRANSFER_DONE to inform the upper layer software that +* all data has been sent. +* +* The Data Transmit Register/FIFO Underflow interrupt -- indicates that, +* as slave, the QSPI device was required to transmit but there was no data +* available to transmit in the transmit register (or FIFO). This may not +* be an error if the master is not expecting data. But in the case where +* the master is expecting data, this serves as a notification of such a +* condition. The driver reports this condition to the upper layer +* software through the status handler. +* +* The Data Receive Register/FIFO Overrun interrupt -- indicates that the QSPI +* device received data and subsequently dropped the data because the data +* receive register and FIFO was full. The driver reports this condition to the +* upper layer software through the status handler. This likely indicates a +* problem with the higher layer protocol, or a problem with the slave +* performance. +* +* +* Polled Operation +* +* Transfer in polled mode is supported through a separate interface function +* XQspiPs_PolledTransfer(). Unlike the transfer function in the interrupt mode, +* this function blocks until all data has been sent/received. +* +* Device Busy +* +* Some operations are disallowed when the device is busy. The driver tracks +* whether a device is busy. The device is considered busy when a data transfer +* request is outstanding, and is considered not busy only when that transfer +* completes (or is aborted with a mode fault error). +* +* Device Configuration +* +* The device can be configured in various ways during the FPGA implementation +* process. Configuration parameters are stored in the xqspips_g.c file or +* passed in via XQspiPs_CfgInitialize(). A table is defined where each entry +* contains configuration information for an QSPI device, including the base +* address for the device. +* +* RTOS Independence +* +* This driver is intended to be RTOS and processor independent. It works with +* physical addresses only. Any needs for dynamic memory management, threads or +* thread mutual exclusion, virtual memory, or cache control must be satisfied +* by the layer above this driver. +* +* NOTE: This driver was always tested with endianess set to little-endian. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- -----------------------------------------------
+* 1.00a sdm 11/25/10 First release, based on the PS SPI driver...
+* 1.01a sdm 11/22/11 Added TCL file for generating QSPI parameters
+*		     in xparameters.h
+* 2.00a kka 07/25/12 Added a few register defines for CR 670297
+* 		     Removed code related to mode fault for CR 671468
+*		     The XQspiPs_SetSlaveSelect has been modified to remove
+*		     the argument of the slave select as the QSPI controller
+*		     only supports one slave.
+* 		     XQspiPs_GetSlaveSelect API has been removed
+* 		     Added a flag ShiftReadData to the instance structure
+*.		     and is used in the XQspiPs_GetReadData API.
+*		     The ShiftReadData Flag indicates whether the data
+*		     read from the Rx FIFO needs to be shifted
+*		     in cases where the data is less than 4  bytes
+* 		     Removed the selection for the following options:
+*		     Master mode (XQSPIPS_MASTER_OPTION) and
+*		     Flash interface mode (XQSPIPS_FLASH_MODE_OPTION) option
+*		     as the QSPI driver supports the Master mode
+*		     and Flash Interface mode and doesnot support
+*		     Slave mode or the legacy mode.
+*		     Modified the XQspiPs_PolledTransfer and XQspiPs_Transfer
+*		     APIs so that the last argument (IsInst) specifying whether
+*		     it is instruction or data has been removed. The first byte
+*		     in the SendBufPtr argument of these APIs specify the
+*		     instruction to be sent to the Flash Device.
+*		     This version of the driver fixes CRs 670197/663787/
+*		     670297/671468.
+* 		     Added the option for setting the Holdb_dr bit in the
+*		     configuration options, XQSPIPS_HOLD_B_DRIVE_OPTION
+*		     is the option to be used for setting this bit in the
+*		     configuration register.
+*		     The XQspiPs_PolledTransfer function has been updated
+*		     to fill the data to fifo depth.
+* 2.01a sg  02/03/13 Added flash opcodes for DUAL_IO_READ,QUAD_IO_READ.
+*		     Added macros for Set/Get Rx Watermark. Changed QSPI
+*		     Enable/Disable macro argument from BaseAddress to
+*		     Instance Pointer. Added DelayNss argument to SetDelays
+*		     and GetDelays API's.
+*		     Created macros XQspiPs_IsManualStart and
+*		     XQspiPs_IsManualChipSelect.
+*		     Changed QSPI transfer logic for polled and interrupt
+*		     modes to be based on filled tx fifo count and receive
+*		     based on it. RXNEMPTY interrupt is not used.
+*		     Added assertions to XQspiPs_LqspiRead function.
+*		     SetDelays and GetDelays API's include DelayNss parameter.
+*		     Added defines for DelayNss,Rx Watermark,Interrupts
+*		     which need write to clear. Removed Read zeros mask from
+*		     LQSPI Config register. Renamed Fixed burst error to
+*		     data FSM error in  LQSPI Status register.
+*
+* 2.02a hk  05/07/13 Added ConnectionMode to config structure.
+*			 Corresponds to C_QSPI_MODE - 0:Single, 1:Stacked, 2:Parallel
+*			 Added enable and disable to the XQspiPs_LqspiRead() function
+*			 Removed XQspi_Reset() in Set_Options() function when
+*			 LQSPI_MODE_OPTION is set.
+*            Added instructions for bank selection, die erase and
+*            flag status register to the flash instruction table
+*            Handling for instructions not in flash instruction
+*			 table added. Checking for Tx FIFO empty when switching from
+*			 TXD1/2/3 to TXD0 added. If WRSR instruction is sent with
+*            byte count 3 (spansion), instruction size and TXD register
+*			 changed accordingly. CR# 712502 and 703869.
+*            Added prefix to constant definitions for ConnectionMode
+*            Added (#ifdef linear base address) in the Linear read function.
+*            Changed  XPAR_XQSPIPS_0_LINEAR_BASEADDR to
+*            XPAR_PS7_QSPI_LINEAR_0_S_AXI_BASEADDR in
+*            XQspiPs_LqspiRead function. Fix for CR#718141.
+*
+* 2.03a hk  09/17/13 Modified polled and interrupt transfers to make use of
+*                    thresholds. This is to improve performance.
+*                    Added API's for QSPI reset and
+*                    linear mode initialization for boot.
+*                    Added RX and TX threshold reset to one in XQspiPs_Abort.
+*                    Added RX threshold reset(1) after transfer in polled and
+*                    interrupt transfers. Made changes to make sure threshold
+*                    change is done only when no transfer is in progress.
+*                    Updated linear init API for parallel and stacked modes.
+*                    CR#737760.
+* 3.1   hk  08/13/14 When writing to the configuration register, set/reset
+*                    required bits leaving reserved bits untouched. CR# 796813.
+* 3.2	sk	02/05/15 Add SLCR reset in abort function as a workaround because
+* 					 controller does not update FIFO status flags as expected
+* 					 when thresholds are used.
+* 3.3   sk  11/07/15 Modified the API prototypes according to MISRAC standards
+*                    to remove compilation warnings. CR# 868893.
+*       ms  03/17/17 Added readme.txt file in examples folder for doxygen
+*                    generation.
+*       ms  04/05/17 Modified Comment lines in functions of qspips
+*                    examples to recognize it as documentation block
+*                    and modified filename tag in
+*                    xqspips_dual_flash_stack_lqspi_example.c to include it in
+*                    doxygen examples.
+* 3.4   nsk 31/07/17 Added QSPI_BUS_WIDTH parameter in xparameters.h file
+* 3.5	tjs 08/21/18 Fixed compilation warnings for the ARMCC.
+* 3.5	tjs 07/16/18 Added support for low density ISSI flash parts.
+* 3.6   akm 03/28/19 Fixed memory leak issue while reading from qspi.(CR#1016357)
+* 3.6   akm 04/15/19 Modified FlashQuadEnable, FlashWrie and FlashErase APIs,
+*                    to wait for the on going operation to complete before
+*                    performing the next operation.
+* 3.6   akm 04/15/19 Modified the mask in XQspiPs_GetReadData() API to retrieve
+*                    configuration register values of both the Flashes in dual
+*                    parellel connection.
+*
+* 
+* +******************************************************************************/ +#ifndef XQSPIPS_H /* prevent circular inclusions */ +#define XQSPIPS_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xstatus.h" +#include "xqspips_hw.h" +#include + +/************************** Constant Definitions *****************************/ + +/** @name Configuration options + * + * The following options are supported to enable/disable certain features of + * an QSPI device. Each of the options is a bit mask, so more than one may be + * specified. + * + * + * The Active Low Clock option configures the device's clock polarity. + * Setting this option means the clock is active low and the SCK signal idles + * high. By default, the clock is active high and SCK idles low. + * + * The Clock Phase option configures the QSPI device for one of two + * transfer formats. A clock phase of 0, the default, means data is valid on + * the first SCK edge (rising or falling) after the slave select (SS) signal + * has been asserted. A clock phase of 1 means data is valid on the second SCK + * edge (rising or falling) after SS has been asserted. + * + * + * The QSPI Force Slave Select option is used to enable manual control of + * the slave select signal. + * 0: The SPI_SS signal is controlled by the QSPI controller during + * transfers. (Default) + * 1: The SPI_SS signal is forced active (driven low) regardless of any + * transfers in progress. + * + * NOTE: The driver will handle setting and clearing the Slave Select when + * the user sets the "FORCE_SSELECT_OPTION". Using this option will allow the + * QSPI clock to be set to a faster speed. If the QSPI clock is too fast, the + * processor cannot empty and refill the FIFOs before the TX FIFO is empty + * When the QSPI hardware is controlling the Slave Select signals, this + * will cause slave to be de-selected and terminate the transfer. + * + * The Manual Start option is used to enable manual control of + * the Start command to perform data transfer. + * 0: The Start command is controlled by the QSPI controller during + * transfers(Default). Data transmission starts as soon as there is data in + * the TXFIFO and stalls when the TXFIFO is empty + * 1: The Start command must be issued by software to perform data transfer. + * Bit 15 of Configuration register is used to issue Start command. This bit + * must be set whenever TXFIFO is filled with new data. + * + * NOTE: The driver will set the Manual Start Enable bit in Configuration + * Register, if Manual Start option is selected. Software will issue + * Manual Start command whenever TXFIFO is filled with data. When there is + * no further data, driver will clear the Manual Start Enable bit. + * + * @{ + */ +#define XQSPIPS_CLK_ACTIVE_LOW_OPTION 0x2 /**< Active Low Clock option */ +#define XQSPIPS_CLK_PHASE_1_OPTION 0x4 /**< Clock Phase one option */ +#define XQSPIPS_FORCE_SSELECT_OPTION 0x10 /**< Force Slave Select */ +#define XQSPIPS_MANUAL_START_OPTION 0x20 /**< Manual Start enable */ +#define XQSPIPS_LQSPI_MODE_OPTION 0x80 /**< Linear QPSI mode */ +#define XQSPIPS_HOLD_B_DRIVE_OPTION 0x100 /**< Drive HOLD_B Pin */ +/*@}*/ + + +/** @name QSPI Clock Prescaler options + * The QSPI Clock Prescaler Configuration bits are used to program master mode + * bit rate. The bit rate can be programmed in divide-by-two decrements from + * pclk/2 to pclk/256. + * + * @{ + */ +#define XQSPIPS_CLK_PRESCALE_2 0x00 /**< PCLK/2 Prescaler */ +#define XQSPIPS_CLK_PRESCALE_4 0x01 /**< PCLK/4 Prescaler */ +#define XQSPIPS_CLK_PRESCALE_8 0x02 /**< PCLK/8 Prescaler */ +#define XQSPIPS_CLK_PRESCALE_16 0x03 /**< PCLK/16 Prescaler */ +#define XQSPIPS_CLK_PRESCALE_32 0x04 /**< PCLK/32 Prescaler */ +#define XQSPIPS_CLK_PRESCALE_64 0x05 /**< PCLK/64 Prescaler */ +#define XQSPIPS_CLK_PRESCALE_128 0x06 /**< PCLK/128 Prescaler */ +#define XQSPIPS_CLK_PRESCALE_256 0x07 /**< PCLK/256 Prescaler */ + +/*@}*/ + + +/** @name Callback events + * + * These constants specify the handler events that are passed to + * a handler from the driver. These constants are not bit masks such that + * only one will be passed at a time to the handler. + * + * @{ + */ +#define XQSPIPS_EVENT_TRANSFER_DONE 2 /**< Transfer done */ +#define XQSPIPS_EVENT_TRANSMIT_UNDERRUN 3 /**< TX FIFO empty */ +#define XQSPIPS_EVENT_RECEIVE_OVERRUN 4 /**< Receive data loss because + * RX FIFO full + */ +/*@}*/ + +/** @name Flash commands + * + * The following constants define most of the commands supported by flash + * devices. Users can add more commands supported by the flash devices + * + * @{ + */ +#define XQSPIPS_FLASH_OPCODE_WRSR 0x01 /* Write status register */ +#define XQSPIPS_FLASH_OPCODE_PP 0x02 /* Page program */ +#define XQSPIPS_FLASH_OPCODE_NORM_READ 0x03 /* Normal read data bytes */ +#define XQSPIPS_FLASH_OPCODE_WRDS 0x04 /* Write disable */ +#define XQSPIPS_FLASH_OPCODE_RDSR1 0x05 /* Read status register 1 */ +#define XQSPIPS_FLASH_OPCODE_WREN 0x06 /* Write enable */ +#define XQSPIPS_FLASH_OPCODE_FAST_READ 0x0B /* Fast read data bytes */ +#define XQSPIPS_FLASH_OPCODE_BE_4K 0x20 /* Erase 4KiB block */ +#define XQSPIPS_FLASH_OPCODE_RDSR2 0x35 /* Read status register 2 */ +#define XQSPIPS_FLASH_OPCODE_DUAL_READ 0x3B /* Dual read data bytes */ +#define XQSPIPS_FLASH_OPCODE_BE_32K 0x52 /* Erase 32KiB block */ +#define XQSPIPS_FLASH_OPCODE_QUAD_READ 0x6B /* Quad read data bytes */ +#define XQSPIPS_FLASH_OPCODE_ERASE_SUS 0x75 /* Erase suspend */ +#define XQSPIPS_FLASH_OPCODE_ERASE_RES 0x7A /* Erase resume */ +#define XQSPIPS_FLASH_OPCODE_RDID 0x9F /* Read JEDEC ID */ +#define XQSPIPS_FLASH_OPCODE_BE 0xC7 /* Erase whole flash block */ +#define XQSPIPS_FLASH_OPCODE_SE 0xD8 /* Sector erase (usually 64KB)*/ +#define XQSPIPS_FLASH_OPCODE_DUAL_IO_READ 0xBB /* Read data using Dual I/O */ +#define XQSPIPS_FLASH_OPCODE_QUAD_IO_READ 0xEB /* Read data using Quad I/O */ +#define XQSPIPS_FLASH_OPCODE_BRWR 0x17 /* Bank Register Write */ +#define XQSPIPS_FLASH_OPCODE_BRRD 0x16 /* Bank Register Read */ +/* Extende Address Register Write - Micron's equivalent of Bank Register */ +#define XQSPIPS_FLASH_OPCODE_EARWR 0xC5 +/* Extende Address Register Read - Micron's equivalent of Bank Register */ +#define XQSPIPS_FLASH_OPCODE_EARRD 0xC8 +#define XQSPIPS_FLASH_OPCODE_DIE_ERASE 0xC4 +#define XQSPIPS_FLASH_OPCODE_READ_FLAG_SR 0x70 +#define XQSPIPS_FLASH_OPCODE_CLEAR_FLAG_SR 0x50 +#define XQSPIPS_FLASH_OPCODE_READ_LOCK_REG 0xE8 /* Lock Reg Read */ +#define XQSPIPS_FLASH_OPCODE_WRITE_LOCK_REG 0xE5 /* Lock Reg Write */ + +/*@}*/ + +/** @name Instruction size + * + * The following constants define numbers 1 to 4. + * Used to identify whether TXD0,1,2 or 3 is to be used. + * + * @{ + */ +#define XQSPIPS_SIZE_ONE 1 +#define XQSPIPS_SIZE_TWO 2 +#define XQSPIPS_SIZE_THREE 3 +#define XQSPIPS_SIZE_FOUR 4 + +/*@}*/ + +/** @name ConnectionMode + * + * The following constants are the possible values of ConnectionMode in + * Config structure. + * + * @{ + */ +#define XQSPIPS_CONNECTION_MODE_SINGLE 0 +#define XQSPIPS_CONNECTION_MODE_STACKED 1 +#define XQSPIPS_CONNECTION_MODE_PARALLEL 2 + +/*@}*/ + +/** @name FIFO threshold value + * + * This is the Rx FIFO threshold (in words) that was found to be most + * optimal in terms of performance + * + * @{ + */ +#define XQSPIPS_RXFIFO_THRESHOLD_OPT 32 + +/*@}*/ + +/**************************** Type Definitions *******************************/ +/** + * The handler data type allows the user to define a callback function to + * handle the asynchronous processing for the QSPI device. The application + * using this driver is expected to define a handler of this type to support + * interrupt driven mode. The handler executes in an interrupt context, so + * only minimal processing should be performed. + * + * @param CallBackRef is the callback reference passed in by the upper + * layer when setting the callback functions, and passed back to + * the upper layer when the callback is invoked. Its type is + * not important to the driver, so it is a void pointer. + * @param StatusEvent holds one or more status events that have occurred. + * See the XQspiPs_SetStatusHandler() for details on the status + * events that can be passed in the callback. + * @param ByteCount indicates how many bytes of data were successfully + * transferred. This may be less than the number of bytes + * requested if the status event indicates an error. + */ +typedef void (*XQspiPs_StatusHandler) (void *CallBackRef, u32 StatusEvent, + unsigned ByteCount); + +/** + * This typedef contains configuration information for the device. + */ +typedef struct { + u16 DeviceId; /**< Unique ID of device */ + u32 BaseAddress; /**< Base address of the device */ + u32 InputClockHz; /**< Input clock frequency */ + u8 ConnectionMode; /**< Single, Stacked and Parallel mode */ +} XQspiPs_Config; + +/** + * The XQspiPs driver instance data. The user is required to allocate a + * variable of this type for every QSPI device in the system. A pointer + * to a variable of this type is then passed to the driver API functions. + */ +typedef struct { + XQspiPs_Config Config; /**< Configuration structure */ + u32 IsReady; /**< Device is initialized and ready */ + + u8 *SendBufferPtr; /**< Buffer to send (state) */ + u8 *RecvBufferPtr; /**< Buffer to receive (state) */ + int RequestedBytes; /**< Number of bytes to transfer (state) */ + int RemainingBytes; /**< Number of bytes left to transfer(state) */ + u32 IsBusy; /**< A transfer is in progress (state) */ + XQspiPs_StatusHandler StatusHandler; + void *StatusRef; /**< Callback reference for status handler */ + u32 ShiftReadData; /**< Flag to indicate whether the data + * read from the Rx FIFO needs to be shifted + * in cases where the data is less than 4 + * bytes + */ +} XQspiPs; + +/***************** Macros (Inline Functions) Definitions *********************/ + +/****************************************************************************/ +/* +* +* Check in OptionsTable if Manual Start Option is enabled or disabled. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* +* @return +* - TRUE if option is set +* - FALSE if option is not set +* +* @note C-Style signature: +* u8 XQspiPs_IsManualStart(XQspiPs *InstancePtr); +* +*****************************************************************************/ +#define XQspiPs_IsManualStart(InstancePtr) \ + ((XQspiPs_GetOptions(InstancePtr) & \ + XQSPIPS_MANUAL_START_OPTION) ? TRUE : FALSE) + +/****************************************************************************/ +/* +* +* Check in OptionsTable if Manual Chip Select Option is enabled or disabled. +* +* @param InstancePtr is a pointer to the XSpiPs instance. +* +* @return +* - TRUE if option is set +* - FALSE if option is not set +* +* @note C-Style signature: +* u8 XQspiPs_IsManualChipSelect(XQspiPs *InstancePtr); +* +*****************************************************************************/ +#define XQspiPs_IsManualChipSelect(InstancePtr) \ + ((XQspiPs_GetOptions(InstancePtr) & \ + XQSPIPS_FORCE_SSELECT_OPTION) ? TRUE : FALSE) + +/****************************************************************************/ +/** +* +* Set the contents of the slave idle count register. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* @param RegisterValue is the value to be written, valid values are +* 0-255. +* +* @return None +* +* @note C-Style signature: +* void XQspiPs_SetSlaveIdle(XQspiPs *InstancePtr, +* u32 RegisterValue) +* +*****************************************************************************/ +#define XQspiPs_SetSlaveIdle(InstancePtr, RegisterValue) \ + XQspiPs_Out32(((InstancePtr)->Config.BaseAddress) + \ + XQSPIPS_SICR_OFFSET, (RegisterValue)) + +/****************************************************************************/ +/** +* +* Get the contents of the slave idle count register. Use the XQSPIPS_SICR_* +* constants defined in xqspips_hw.h to interpret the bit-mask returned. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* +* @return An 8-bit value representing Slave Idle Count. +* +* @note C-Style signature: +* u32 XQspiPs_GetSlaveIdle(XQspiPs *InstancePtr) +* +*****************************************************************************/ +#define XQspiPs_GetSlaveIdle(InstancePtr) \ + XQspiPs_In32(((InstancePtr)->Config.BaseAddress) + \ + XQSPIPS_SICR_OFFSET) + +/****************************************************************************/ +/** +* +* Set the contents of the transmit FIFO watermark register. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* @param RegisterValue is the value to be written, valid values are 1-63. +* +* @return None. +* +* @note C-Style signature: +* void XQspiPs_SetTXWatermark(XQspiPs *InstancePtr, +* u32 RegisterValue) +* +*****************************************************************************/ +#define XQspiPs_SetTXWatermark(InstancePtr, RegisterValue) \ + XQspiPs_Out32(((InstancePtr)->Config.BaseAddress) + \ + XQSPIPS_TXWR_OFFSET, (RegisterValue)) + +/****************************************************************************/ +/** +* +* Get the contents of the transmit FIFO watermark register. +* Valid values are in the range 1-63. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* +* @return A 6-bit value representing Tx Watermark level. +* +* @note C-Style signature: +* u32 XQspiPs_GetTXWatermark(XQspiPs *InstancePtr) +* +*****************************************************************************/ +#define XQspiPs_GetTXWatermark(InstancePtr) \ + XQspiPs_In32((InstancePtr->Config.BaseAddress) + XQSPIPS_TXWR_OFFSET) + +/****************************************************************************/ +/** +* +* Set the contents of the receive FIFO watermark register. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* @param RegisterValue is the value to be written, valid values are 1-63. +* +* @return None. +* +* @note C-Style signature: +* void XQspiPs_SetRXWatermark(XQspiPs *InstancePtr, +* u32 RegisterValue) +* +*****************************************************************************/ +#define XQspiPs_SetRXWatermark(InstancePtr, RegisterValue) \ + XQspiPs_Out32(((InstancePtr)->Config.BaseAddress) + \ + XQSPIPS_RXWR_OFFSET, (RegisterValue)) + +/****************************************************************************/ +/** +* +* Get the contents of the receive FIFO watermark register. +* Valid values are in the range 1-63. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* +* @return A 6-bit value representing Rx Watermark level. +* +* @note C-Style signature: +* u32 XQspiPs_GetRXWatermark(XQspiPs *InstancePtr) +* +*****************************************************************************/ +#define XQspiPs_GetRXWatermark(InstancePtr) \ + XQspiPs_In32((InstancePtr->Config.BaseAddress) + XQSPIPS_RXWR_OFFSET) + +/****************************************************************************/ +/** +* +* Enable the device and uninhibit master transactions. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* +* @return None. +* +* @note C-Style signature: +* void XQspiPs_Enable(XQspiPs *InstancePtr) +* +*****************************************************************************/ +#define XQspiPs_Enable(InstancePtr) \ + XQspiPs_Out32((InstancePtr->Config.BaseAddress) + XQSPIPS_ER_OFFSET, \ + XQSPIPS_ER_ENABLE_MASK) + +/****************************************************************************/ +/** +* +* Disable the device. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* +* @return None. +* +* @note C-Style signature: +* void XQspiPs_Disable(XQspiPs *InstancePtr) +* +*****************************************************************************/ +#define XQspiPs_Disable(InstancePtr) \ + XQspiPs_Out32((InstancePtr->Config.BaseAddress) + XQSPIPS_ER_OFFSET, 0) + +/****************************************************************************/ +/** +* +* Set the contents of the Linear QSPI Configuration register. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* @param RegisterValue is the value to be written to the Linear QSPI +* configuration register. +* +* @return None. +* +* @note C-Style signature: +* void XQspiPs_SetLqspiConfigReg(XQspiPs *InstancePtr, +* u32 RegisterValue) +* +*****************************************************************************/ +#define XQspiPs_SetLqspiConfigReg(InstancePtr, RegisterValue) \ + XQspiPs_Out32(((InstancePtr)->Config.BaseAddress) + \ + XQSPIPS_LQSPI_CR_OFFSET, (RegisterValue)) + +/****************************************************************************/ +/** +* +* Get the contents of the Linear QSPI Configuration register. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* +* @return A 32-bit value representing the contents of the LQSPI Config +* register. +* +* @note C-Style signature: +* u32 XQspiPs_GetLqspiConfigReg(u32 *InstancePtr) +* +*****************************************************************************/ +#define XQspiPs_GetLqspiConfigReg(InstancePtr) \ + XQspiPs_In32((InstancePtr->Config.BaseAddress) + \ + XQSPIPS_LQSPI_CR_OFFSET) + +/************************** Function Prototypes ******************************/ + +/* + * Initialization function, implemented in xqspips_sinit.c + */ +XQspiPs_Config *XQspiPs_LookupConfig(u16 DeviceId); + +/* + * Functions implemented in xqspips.c + */ +int XQspiPs_CfgInitialize(XQspiPs *InstancePtr, XQspiPs_Config *Config, + u32 EffectiveAddr); +void XQspiPs_Reset(XQspiPs *InstancePtr); +void XQspiPs_Abort(XQspiPs *InstancePtr); + +s32 XQspiPs_Transfer(XQspiPs *InstancePtr, u8 *SendBufPtr, u8 *RecvBufPtr, + u32 ByteCount); +s32 XQspiPs_PolledTransfer(XQspiPs *InstancePtr, u8 *SendBufPtr, + u8 *RecvBufPtr, u32 ByteCount); +int XQspiPs_LqspiRead(XQspiPs *InstancePtr, u8 *RecvBufPtr, + u32 Address, unsigned ByteCount); + +int XQspiPs_SetSlaveSelect(XQspiPs *InstancePtr); + +void XQspiPs_SetStatusHandler(XQspiPs *InstancePtr, void *CallBackRef, + XQspiPs_StatusHandler FuncPtr); +void XQspiPs_InterruptHandler(void *InstancePtr); + +/* + * Functions for selftest, in xqspips_selftest.c + */ +int XQspiPs_SelfTest(XQspiPs *InstancePtr); + +/* + * Functions for options, in xqspips_options.c + */ +s32 XQspiPs_SetOptions(XQspiPs *InstancePtr, u32 Options); +u32 XQspiPs_GetOptions(XQspiPs *InstancePtr); + +s32 XQspiPs_SetClkPrescaler(XQspiPs *InstancePtr, u8 Prescaler); +u8 XQspiPs_GetClkPrescaler(XQspiPs *InstancePtr); + +int XQspiPs_SetDelays(XQspiPs *InstancePtr, u8 DelayNss, u8 DelayBtwn, + u8 DelayAfter, u8 DelayInit); +void XQspiPs_GetDelays(XQspiPs *InstancePtr, u8 *DelayNss, u8 *DelayBtwn, + u8 *DelayAfter, u8 *DelayInit); +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/qspips_v3_6/src/xqspips_g.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/qspips_v3_6/src/xqspips_g.c new file mode 100644 index 0000000..f8f344e --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/qspips_v3_6/src/xqspips_g.c @@ -0,0 +1,53 @@ + +/******************************************************************* +* +* CAUTION: This file is automatically generated by HSI. +* Version: 2019.1.3 +* DO NOT EDIT. +* +* Copyright (C) 2010-2023 Xilinx, Inc. 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 +*XILINX 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. +* +*Except as contained in this notice, the name of the Xilinx shall not be used +*in advertising or otherwise to promote the sale, use or other dealings in +*this Software without prior written authorization from Xilinx. +* + +* +* Description: Driver configuration +* +*******************************************************************/ + +#include "xparameters.h" +#include "xqspips.h" + +/* +* The configuration table for devices +*/ + +XQspiPs_Config XQspiPs_ConfigTable[XPAR_XQSPIPS_NUM_INSTANCES] = +{ + { + XPAR_PS7_QSPI_0_DEVICE_ID, + XPAR_PS7_QSPI_0_BASEADDR, + XPAR_PS7_QSPI_0_QSPI_CLK_FREQ_HZ, + XPAR_PS7_QSPI_0_QSPI_MODE + } +}; + + diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/qspips_v3_6/src/xqspips_hw.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/qspips_v3_6/src/xqspips_hw.c new file mode 100644 index 0000000..d5e0789 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/qspips_v3_6/src/xqspips_hw.c @@ -0,0 +1,220 @@ +/****************************************************************************** +* +* Copyright (C) 2013 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xqspips_hw.c +* @addtogroup qspips_v3_6 +* @{ +* +* Contains low level functions, primarily reset related. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- -----------------------------------------------
+* 2.03a hk  09/17/13 First release
+* 3.1   hk  06/19/14 When writing to the configuration register, set/reset
+*                    required bits leaving reserved bits untouched. CR# 796813.
+*
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xqspips_hw.h" +#include "xqspips.h" + +/************************** Constant Definitions *****************************/ + +/** @name Pre-scaler value for divided by 4 + * + * Pre-scaler value for divided by 4 + * + * @{ + */ +#define XQSPIPS_CR_PRESC_DIV_BY_4 0x01 +/* @} */ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + + +/*****************************************************************************/ +/** +* +* Resets QSPI by disabling the device and bringing it to reset state through +* register writes. +* +* @param None +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XQspiPs_ResetHw(u32 BaseAddress) +{ + u32 ConfigReg; + + /* + * Disable interrupts + */ + XQspiPs_WriteReg(BaseAddress, XQSPIPS_IDR_OFFSET, + XQSPIPS_IXR_DISABLE_ALL); + + /* + * Disable device + */ + XQspiPs_WriteReg(BaseAddress, XQSPIPS_ER_OFFSET, + 0); + + /* + * De-assert slave select lines. + */ + ConfigReg = XQspiPs_ReadReg(BaseAddress, XQSPIPS_CR_OFFSET); + ConfigReg |= (XQSPIPS_CR_SSCTRL_MASK | XQSPIPS_CR_SSFORCE_MASK); + XQspiPs_WriteReg(BaseAddress, XQSPIPS_CR_OFFSET, ConfigReg); + + /* + * Write default value to RX and TX threshold registers + * RX threshold should be set to 1 here because the corresponding + * status bit is used next to clear the RXFIFO + */ + XQspiPs_WriteReg(BaseAddress, XQSPIPS_TXWR_OFFSET, + (XQSPIPS_TXWR_RESET_VALUE & XQSPIPS_TXWR_MASK)); + XQspiPs_WriteReg(BaseAddress, XQSPIPS_RXWR_OFFSET, + (XQSPIPS_RXWR_RESET_VALUE & XQSPIPS_RXWR_MASK)); + + /* + * Clear RXFIFO + */ + while ((XQspiPs_ReadReg(BaseAddress,XQSPIPS_SR_OFFSET) & + XQSPIPS_IXR_RXNEMPTY_MASK) != 0) { + XQspiPs_ReadReg(BaseAddress, XQSPIPS_RXD_OFFSET); + } + + /* + * Clear status register by reading register and + * writing 1 to clear the write to clear bits + */ + XQspiPs_ReadReg(BaseAddress, XQSPIPS_SR_OFFSET); + XQspiPs_WriteReg(BaseAddress, XQSPIPS_SR_OFFSET, + XQSPIPS_IXR_WR_TO_CLR_MASK); + + /* + * Write default value to configuration register + */ + ConfigReg = XQspiPs_ReadReg(BaseAddress, XQSPIPS_CR_OFFSET); + ConfigReg |= XQSPIPS_CR_RESET_MASK_SET; + ConfigReg &= ~XQSPIPS_CR_RESET_MASK_CLR; + XQspiPs_WriteReg(BaseAddress, XQSPIPS_CR_OFFSET, ConfigReg); + + /* + * De-select linear mode + */ + XQspiPs_WriteReg(BaseAddress, XQSPIPS_LQSPI_CR_OFFSET, + 0x0); + +} + +/*****************************************************************************/ +/** +* +* Initializes QSPI to Linear mode with default QSPI boot settings. +* +* @param None +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XQspiPs_LinearInit(u32 BaseAddress) +{ + u32 BaudRateDiv; + u32 LinearCfg; + u32 ConfigReg; + + /* + * Baud rate divisor for dividing by 4. Value of CR bits [5:3] + * should be set to 0x001; hence shift the value and use the mask. + */ + BaudRateDiv = ( (XQSPIPS_CR_PRESC_DIV_BY_4) << + XQSPIPS_CR_PRESC_SHIFT) & XQSPIPS_CR_PRESC_MASK; + /* + * Write configuration register with default values, slave selected & + * pre-scaler value for divide by 4 + */ + ConfigReg = XQspiPs_ReadReg(BaseAddress, XQSPIPS_CR_OFFSET); + ConfigReg |= (XQSPIPS_CR_RESET_MASK_SET | BaudRateDiv); + ConfigReg &= ~(XQSPIPS_CR_RESET_MASK_CLR | XQSPIPS_CR_SSCTRL_MASK); + XQspiPs_WriteReg(BaseAddress, XQSPIPS_CR_OFFSET, ConfigReg); + + /* + * Write linear configuration register with default value - + * enable linear mode and use fast read. + */ + + if(XPAR_XQSPIPS_0_QSPI_MODE == XQSPIPS_CONNECTION_MODE_SINGLE){ + + LinearCfg = XQSPIPS_LQSPI_CR_RST_STATE; + + }else if(XPAR_XQSPIPS_0_QSPI_MODE == + XQSPIPS_CONNECTION_MODE_STACKED){ + + LinearCfg = XQSPIPS_LQSPI_CR_RST_STATE | + XQSPIPS_LQSPI_CR_TWO_MEM_MASK; + + }else if(XPAR_XQSPIPS_0_QSPI_MODE == + XQSPIPS_CONNECTION_MODE_PARALLEL){ + + LinearCfg = XQSPIPS_LQSPI_CR_RST_STATE | + XQSPIPS_LQSPI_CR_TWO_MEM_MASK | + XQSPIPS_LQSPI_CR_SEP_BUS_MASK; + + } + + XQspiPs_WriteReg(BaseAddress, XQSPIPS_LQSPI_CR_OFFSET, + LinearCfg); + + /* + * Enable device + */ + XQspiPs_WriteReg(BaseAddress, XQSPIPS_ER_OFFSET, + XQSPIPS_ER_ENABLE_MASK); + +} +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/qspips_v3_6/src/xqspips_hw.h b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/qspips_v3_6/src/xqspips_hw.h new file mode 100644 index 0000000..88c232e --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/qspips_v3_6/src/xqspips_hw.h @@ -0,0 +1,421 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xqspips_hw.h +* @addtogroup qspips_v3_6 +* @{ +* +* This header file contains the identifiers and basic HW access driver +* functions (or macros) that can be used to access the device. Other driver +* functions are defined in xqspips.h. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- -----------------------------------------------
+* 1.00  sdm 11/25/10 First release
+* 2.00a ka  07/25/12 Added a few register defines for CR 670297
+*		     and removed some defines of reserved fields for
+*		     CR 671468
+*		     Added define XQSPIPS_CR_HOLD_B_MASK for Holdb_dr
+*		     bit in Configuration register.
+* 2.01a sg  02/03/13 Added defines for DelayNss,Rx Watermark,Interrupts
+*		     which need write to clear. Removed Read zeros mask from
+*		     LQSPI Config register.
+* 2.03a hk  08/22/13 Added prototypes of API's for QSPI reset and
+*                    linear mode initialization for boot. Added related
+*                    constant definitions.
+* 3.1   hk  08/13/14 Changed definition of CR reset value masks to set/reset
+*                    required bits leaving reserved bits untouched. CR# 796813.
+* 3.2	sk	02/05/15 Add SLCR reset in abort function as a workaround because
+* 					 controller does not update FIFO status flags as expected
+* 					 when thresholds are used.
+* 3.6   akm 03/28/19 Fixed memory leak issue while reading from qspi.(CR#1016357)
+*
+* 
+* +******************************************************************************/ +#ifndef XQSPIPS_HW_H /* prevent circular inclusions */ +#define XQSPIPS_HW_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_io.h" +#include "xparameters.h" + +/************************** Constant Definitions *****************************/ + +/** @name Register Map + * + * Register offsets from the base address of an QSPI device. + * @{ + */ +#define XQSPIPS_CR_OFFSET 0x00 /**< Configuration Register */ +#define XQSPIPS_SR_OFFSET 0x04 /**< Interrupt Status */ +#define XQSPIPS_IER_OFFSET 0x08 /**< Interrupt Enable */ +#define XQSPIPS_IDR_OFFSET 0x0c /**< Interrupt Disable */ +#define XQSPIPS_IMR_OFFSET 0x10 /**< Interrupt Enabled Mask */ +#define XQSPIPS_ER_OFFSET 0x14 /**< Enable/Disable Register */ +#define XQSPIPS_DR_OFFSET 0x18 /**< Delay Register */ +#define XQSPIPS_TXD_00_OFFSET 0x1C /**< Transmit 4-byte inst/data */ +#define XQSPIPS_RXD_OFFSET 0x20 /**< Data Receive Register */ +#define XQSPIPS_SICR_OFFSET 0x24 /**< Slave Idle Count */ +#define XQSPIPS_TXWR_OFFSET 0x28 /**< Transmit FIFO Watermark */ +#define XQSPIPS_RXWR_OFFSET 0x2C /**< Receive FIFO Watermark */ +#define XQSPIPS_GPIO_OFFSET 0x30 /**< GPIO Register */ +#define XQSPIPS_LPBK_DLY_ADJ_OFFSET 0x38 /**< Loopback Delay Adjust Reg */ +#define XQSPIPS_TXD_01_OFFSET 0x80 /**< Transmit 1-byte inst */ +#define XQSPIPS_TXD_10_OFFSET 0x84 /**< Transmit 2-byte inst */ +#define XQSPIPS_TXD_11_OFFSET 0x88 /**< Transmit 3-byte inst */ +#define XQSPIPS_LQSPI_CR_OFFSET 0xA0 /**< Linear QSPI config register */ +#define XQSPIPS_LQSPI_SR_OFFSET 0xA4 /**< Linear QSPI status register */ +#define XQSPIPS_MOD_ID_OFFSET 0xFC /**< Module ID register */ + +/* @} */ + +/** @name Configuration Register + * + * This register contains various control bits that + * affect the operation of the QSPI device. Read/Write. + * @{ + */ + +#define XQSPIPS_CR_IFMODE_MASK 0x80000000 /**< Flash mem interface mode */ +#define XQSPIPS_CR_ENDIAN_MASK 0x04000000 /**< Tx/Rx FIFO endianness */ +#define XQSPIPS_CR_MANSTRT_MASK 0x00010000 /**< Manual Transmission Start */ +#define XQSPIPS_CR_MANSTRTEN_MASK 0x00008000 /**< Manual Transmission Start + Enable */ +#define XQSPIPS_CR_SSFORCE_MASK 0x00004000 /**< Force Slave Select */ +#define XQSPIPS_CR_SSCTRL_MASK 0x00000400 /**< Slave Select Decode */ +#define XQSPIPS_CR_SSCTRL_SHIFT 10 /**< Slave Select Decode shift */ +#define XQSPIPS_CR_DATA_SZ_MASK 0x000000C0 /**< Size of word to be + transferred */ +#define XQSPIPS_CR_PRESC_MASK 0x00000038 /**< Prescaler Setting */ +#define XQSPIPS_CR_PRESC_SHIFT 3 /**< Prescaler shift */ +#define XQSPIPS_CR_PRESC_MAXIMUM 0x07 /**< Prescaler maximum value */ + +#define XQSPIPS_CR_CPHA_MASK 0x00000004 /**< Phase Configuration */ +#define XQSPIPS_CR_CPOL_MASK 0x00000002 /**< Polarity Configuration */ + +#define XQSPIPS_CR_MSTREN_MASK 0x00000001 /**< Master Mode Enable */ + +#define XQSPIPS_CR_HOLD_B_MASK 0x00080000 /**< HOLD_B Pin Drive Enable */ + +#define XQSPIPS_CR_REF_CLK_MASK 0x00000100 /**< Ref clk bit - should be 0 */ + +/* Deselect the Slave select line and set the transfer size to 32 at reset */ +#define XQSPIPS_CR_RESET_MASK_SET XQSPIPS_CR_IFMODE_MASK | \ + XQSPIPS_CR_SSCTRL_MASK | \ + XQSPIPS_CR_DATA_SZ_MASK | \ + XQSPIPS_CR_MSTREN_MASK | \ + XQSPIPS_CR_SSFORCE_MASK | \ + XQSPIPS_CR_HOLD_B_MASK +#define XQSPIPS_CR_RESET_MASK_CLR XQSPIPS_CR_CPOL_MASK | \ + XQSPIPS_CR_CPHA_MASK | \ + XQSPIPS_CR_PRESC_MASK | \ + XQSPIPS_CR_MANSTRTEN_MASK | \ + XQSPIPS_CR_MANSTRT_MASK | \ + XQSPIPS_CR_ENDIAN_MASK | \ + XQSPIPS_CR_REF_CLK_MASK +/* @} */ + + +/** @name QSPI Interrupt Registers + * + * QSPI Status Register + * + * This register holds the interrupt status flags for an QSPI device. Some + * of the flags are level triggered, which means that they are set as long + * as the interrupt condition exists. Other flags are edge triggered, + * which means they are set once the interrupt condition occurs and remain + * set until they are cleared by software. The interrupts are cleared by + * writing a '1' to the interrupt bit position in the Status Register. + * Read/Write. + * + * QSPI Interrupt Enable Register + * + * This register is used to enable chosen interrupts for an QSPI device. + * Writing a '1' to a bit in this register sets the corresponding bit in the + * QSPI Interrupt Mask register. Write only. + * + * QSPI Interrupt Disable Register + * + * This register is used to disable chosen interrupts for an QSPI device. + * Writing a '1' to a bit in this register clears the corresponding bit in the + * QSPI Interrupt Mask register. Write only. + * + * QSPI Interrupt Mask Register + * + * This register shows the enabled/disabled interrupts of an QSPI device. + * Read only. + * + * All four registers have the same bit definitions. They are only defined once + * for each of the Interrupt Enable Register, Interrupt Disable Register, + * Interrupt Mask Register, and Channel Interrupt Status Register + * @{ + */ + +#define XQSPIPS_IXR_TXUF_MASK 0x00000040 /**< QSPI Tx FIFO Underflow */ +#define XQSPIPS_IXR_RXFULL_MASK 0x00000020 /**< QSPI Rx FIFO Full */ +#define XQSPIPS_IXR_RXNEMPTY_MASK 0x00000010 /**< QSPI Rx FIFO Not Empty */ +#define XQSPIPS_IXR_TXFULL_MASK 0x00000008 /**< QSPI Tx FIFO Full */ +#define XQSPIPS_IXR_TXOW_MASK 0x00000004 /**< QSPI Tx FIFO Overwater */ +#define XQSPIPS_IXR_RXOVR_MASK 0x00000001 /**< QSPI Rx FIFO Overrun */ +#define XQSPIPS_IXR_DFLT_MASK 0x00000025 /**< QSPI default interrupts + mask */ +#define XQSPIPS_IXR_WR_TO_CLR_MASK 0x00000041 /**< Interrupts which + need write to clear */ +#define XQSPIPS_ISR_RESET_STATE 0x00000004 /**< Default to tx/rx empty */ +#define XQSPIPS_IXR_DISABLE_ALL 0x0000007D /**< Disable all interrupts */ +/* @} */ + + +/** @name Enable Register + * + * This register is used to enable or disable an QSPI device. + * Read/Write + * @{ + */ +#define XQSPIPS_ER_ENABLE_MASK 0x00000001 /**< QSPI Enable Bit Mask */ +/* @} */ + + +/** @name Delay Register + * + * This register is used to program timing delays in + * slave mode. Read/Write + * @{ + */ +#define XQSPIPS_DR_NSS_MASK 0xFF000000 /**< Delay to de-assert slave select + between two words mask */ +#define XQSPIPS_DR_NSS_SHIFT 24 /**< Delay to de-assert slave select + between two words shift */ +#define XQSPIPS_DR_BTWN_MASK 0x00FF0000 /**< Delay Between Transfers + mask */ +#define XQSPIPS_DR_BTWN_SHIFT 16 /**< Delay Between Transfers shift */ +#define XQSPIPS_DR_AFTER_MASK 0x0000FF00 /**< Delay After Transfers mask */ +#define XQSPIPS_DR_AFTER_SHIFT 8 /**< Delay After Transfers shift */ +#define XQSPIPS_DR_INIT_MASK 0x000000FF /**< Delay Initially mask */ +/* @} */ + +/** @name Slave Idle Count Registers + * + * This register defines the number of pclk cycles the slave waits for a the + * QSPI clock to become stable in quiescent state before it can detect the start + * of the next transfer in CPHA = 1 mode. + * Read/Write + * + * @{ + */ +#define XQSPIPS_SICR_MASK 0x000000FF /**< Slave Idle Count Mask */ +/* @} */ + + +/** @name Transmit FIFO Watermark Register + * + * This register defines the watermark setting for the Transmit FIFO. + * + * @{ + */ +#define XQSPIPS_TXWR_MASK 0x0000003F /**< Transmit Watermark Mask */ +#define XQSPIPS_TXWR_RESET_VALUE 0x00000001 /**< Transmit Watermark + * register reset value */ + +/* @} */ + +/** @name Receive FIFO Watermark Register + * + * This register defines the watermark setting for the Receive FIFO. + * + * @{ + */ +#define XQSPIPS_RXWR_MASK 0x0000003F /**< Receive Watermark Mask */ +#define XQSPIPS_RXWR_RESET_VALUE 0x00000001 /**< Receive Watermark + * register reset value */ + +/* @} */ + +/** @name FIFO Depth + * + * This macro provides the depth of transmit FIFO and receive FIFO. + * + * @{ + */ +#define XQSPIPS_FIFO_DEPTH 63 /**< FIFO depth (words) */ +/* @} */ + + +/** @name Linear QSPI Configuration Register + * + * This register contains various control bits that + * affect the operation of the Linear QSPI controller. Read/Write. + * + * @{ + */ +#define XQSPIPS_LQSPI_CR_LINEAR_MASK 0x80000000 /**< LQSPI mode enable */ +#define XQSPIPS_LQSPI_CR_TWO_MEM_MASK 0x40000000 /**< Both memories or one */ +#define XQSPIPS_LQSPI_CR_SEP_BUS_MASK 0x20000000 /**< Seperate memory bus */ +#define XQSPIPS_LQSPI_CR_U_PAGE_MASK 0x10000000 /**< Upper memory page */ +#define XQSPIPS_LQSPI_CR_MODE_EN_MASK 0x02000000 /**< Enable mode bits */ +#define XQSPIPS_LQSPI_CR_MODE_ON_MASK 0x01000000 /**< Mode on */ +#define XQSPIPS_LQSPI_CR_MODE_BITS_MASK 0x00FF0000 /**< Mode value for dual I/O + or quad I/O */ +#define XQSPIPS_LQSPI_CR_DUMMY_MASK 0x00000700 /**< Number of dummy bytes + between addr and return + read data */ +#define XQSPIPS_LQSPI_CR_INST_MASK 0x000000FF /**< Read instr code */ +#define XQSPIPS_LQSPI_CR_RST_STATE 0x8000016B /**< Default CR value */ +/* @} */ + +/** @name Linear QSPI Status Register + * + * This register contains various status bits of the Linear QSPI controller. + * Read/Write. + * + * @{ + */ +#define XQSPIPS_LQSPI_SR_D_FSM_ERR_MASK 0x00000004 /**< AXI Data FSM Error + received */ +#define XQSPIPS_LQSPI_SR_WR_RECVD_MASK 0x00000002 /**< AXI write command + received */ +/* @} */ + + +/** @name Loopback Delay Adjust Register + * + * This register contains various bit masks of Loopback Delay Adjust Register. + * + * @{ + */ + +#define XQSPIPS_LPBK_DLY_ADJ_USE_LPBK_MASK 0x00000020 /**< Loopback Bit */ + +/* @} */ + + +/** @name SLCR Register + * + * Register offsets from SLCR base address. + * + * @{ + */ + +#define SLCR_LOCK 0x00000004 /**< SLCR Write Protection Lock */ +#define SLCR_UNLOCK 0x00000008 /**< SLCR Write Protection Unlock */ +#define LQSPI_RST_CTRL 0x00000230 /**< Quad SPI Software Reset Control */ +#define SLCR_LOCKSTA 0x0000000C /**< SLCR Write Protection status */ + +/* @} */ + + +/** @name SLCR Register + * + * Bit Masks of above SLCR Registers . + * + * @{ + */ + +#ifndef XPAR_XSLCR_0_BASEADDR +#define XPAR_XSLCR_0_BASEADDR 0xF8000000 +#endif +#define SLCR_LOCK_MASK 0x767B /**< Write Protection Lock mask*/ +#define SLCR_UNLOCK_MASK 0xDF0D /**< SLCR Write Protection Unlock */ +#define LQSPI_RST_CTRL_MASK 0x3 /**< Quad SPI Software Reset Control */ + +/* @} */ + + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +#define XQspiPs_In32 Xil_In32 +#define XQspiPs_Out32 Xil_Out32 +#define XQSPIPS_DUMMY_TX_DATA 0xFFFFFFFF + +/****************************************************************************/ +/** +* Read a register. +* +* @param BaseAddress contains the base address of the device. +* @param RegOffset contains the offset from the 1st register of the +* device to the target register. +* +* @return The value read from the register. +* +* @note C-Style signature: +* u32 XQspiPs_ReadReg(u32 BaseAddress. int RegOffset) +* +******************************************************************************/ +#define XQspiPs_ReadReg(BaseAddress, RegOffset) \ + XQspiPs_In32((BaseAddress) + (RegOffset)) + +/***************************************************************************/ +/** +* Write to a register. +* +* @param BaseAddress contains the base address of the device. +* @param RegOffset contains the offset from the 1st register of the +* device to target register. +* @param RegisterValue is the value to be written to the register. +* +* @return None. +* +* @note C-Style signature: +* void XQspiPs_WriteReg(u32 BaseAddress, int RegOffset, +* u32 RegisterValue) +* +******************************************************************************/ +#define XQspiPs_WriteReg(BaseAddress, RegOffset, RegisterValue) \ + XQspiPs_Out32((BaseAddress) + (RegOffset), (RegisterValue)) + +/************************** Function Prototypes ******************************/ + +/* + * Functions implemented in xqspips_hw.c + */ +void XQspiPs_ResetHw(u32 BaseAddress); +void XQspiPs_LinearInit(u32 BaseAddress); + +/************************** Variable Definitions *****************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/qspips_v3_6/src/xqspips_options.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/qspips_v3_6/src/xqspips_options.c new file mode 100644 index 0000000..14d0ca0 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/qspips_v3_6/src/xqspips_options.c @@ -0,0 +1,426 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xqspips_options.c +* @addtogroup qspips_v3_6 +* @{ +* +* Contains functions for the configuration of the XQspiPs driver component. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- -----------------------------------------------
+* 1.00  sdm 11/25/10 First release
+* 2.00a kka 07/25/12 Removed the selection for the following options:
+*		     Master mode (XQSPIPS_MASTER_OPTION) and
+*		     Flash interface mode (XQSPIPS_FLASH_MODE_OPTION) option
+*		     as the QSPI driver supports the Master mode
+*		     and Flash Interface mode. The driver doesnot support
+*		     Slave mode or the legacy mode.
+* 		     Added the option for setting the Holdb_dr bit in the
+*		     configuration options, XQSPIPS_HOLD_B_DRIVE_OPTION
+*		     is the option to be used for setting this bit in the
+*		     configuration register.
+* 2.01a sg  02/03/13 SetDelays and GetDelays API's include DelayNss parameter.
+*
+* 2.02a hk  26/03/13 Removed XQspi_Reset() in Set_Options() function when
+*			 LQSPI_MODE_OPTION is set. Moved Enable() to XQpsiPs_LqspiRead().
+* 3.3   sk  11/07/15 Modified the API prototypes according to MISRAC standards
+*                    to remove compilation warnings. CR# 868893.
+*
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xqspips.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +/* + * Create the table of options which are processed to get/set the device + * options. These options are table driven to allow easy maintenance and + * expansion of the options. + */ +typedef struct { + u32 Option; + u32 Mask; +} OptionsMap; + +static OptionsMap OptionsTable[] = { + {XQSPIPS_CLK_ACTIVE_LOW_OPTION, XQSPIPS_CR_CPOL_MASK}, + {XQSPIPS_CLK_PHASE_1_OPTION, XQSPIPS_CR_CPHA_MASK}, + {XQSPIPS_FORCE_SSELECT_OPTION, XQSPIPS_CR_SSFORCE_MASK}, + {XQSPIPS_MANUAL_START_OPTION, XQSPIPS_CR_MANSTRTEN_MASK}, + {XQSPIPS_HOLD_B_DRIVE_OPTION, XQSPIPS_CR_HOLD_B_MASK}, +}; + +#define XQSPIPS_NUM_OPTIONS (sizeof(OptionsTable) / sizeof(OptionsMap)) + +/*****************************************************************************/ +/** +* +* This function sets the options for the QSPI device driver. The options control +* how the device behaves relative to the QSPI bus. The device must be idle +* rather than busy transferring data before setting these device options. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* @param Options contains the specified options to be set. This is a bit +* mask where a 1 means to turn the option on, and a 0 means to +* turn the option off. One or more bit values may be contained in +* the mask. See the bit definitions named XQSPIPS_*_OPTIONS in +* the file xqspips.h. +* +* @return +* - XST_SUCCESS if options are successfully set. +* - XST_DEVICE_BUSY if the device is currently transferring data. +* The transfer must complete or be aborted before setting options. +* +* @note +* This function is not thread-safe. +* +******************************************************************************/ +s32 XQspiPs_SetOptions(XQspiPs *InstancePtr, u32 Options) +{ + u32 ConfigReg; + unsigned int Index; + u32 QspiOptions; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Do not allow to modify the Control Register while a transfer is in + * progress. Not thread-safe. + */ + if (InstancePtr->IsBusy) { + return XST_DEVICE_BUSY; + } + + QspiOptions = Options & XQSPIPS_LQSPI_MODE_OPTION; + Options &= ~XQSPIPS_LQSPI_MODE_OPTION; + + ConfigReg = XQspiPs_ReadReg(InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET); + + /* + * Loop through the options table, turning the option on or off + * depending on whether the bit is set in the incoming options flag. + */ + for (Index = 0; Index < XQSPIPS_NUM_OPTIONS; Index++) { + if (Options & OptionsTable[Index].Option) { + /* Turn it on */ + ConfigReg |= OptionsTable[Index].Mask; + } else { + /* Turn it off */ + ConfigReg &= ~(OptionsTable[Index].Mask); + } + } + + /* + * Now write the control register. Leave it to the upper layers + * to restart the device. + */ + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPS_CR_OFFSET, + ConfigReg); + + /* + * Check for the LQSPI configuration options. + */ + ConfigReg = XQspiPs_ReadReg(InstancePtr->Config.BaseAddress, + XQSPIPS_LQSPI_CR_OFFSET); + + + if (QspiOptions & XQSPIPS_LQSPI_MODE_OPTION) { + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_LQSPI_CR_OFFSET, + XQSPIPS_LQSPI_CR_RST_STATE); + XQspiPs_SetSlaveSelect(InstancePtr); + } else { + ConfigReg &= ~XQSPIPS_LQSPI_CR_LINEAR_MASK; + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_LQSPI_CR_OFFSET, ConfigReg); + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function gets the options for the QSPI device. The options control how +* the device behaves relative to the QSPI bus. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* +* @return +* +* Options contains the specified options currently set. This is a bit value +* where a 1 means the option is on, and a 0 means the option is off. +* See the bit definitions named XQSPIPS_*_OPTIONS in file xqspips.h. +* +* @note None. +* +******************************************************************************/ +u32 XQspiPs_GetOptions(XQspiPs *InstancePtr) +{ + u32 OptionsFlag = 0; + u32 ConfigReg; + unsigned int Index; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Get the current options from QSPI configuration register. + */ + ConfigReg = XQspiPs_ReadReg(InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET); + + /* + * Loop through the options table to grab options + */ + for (Index = 0; Index < XQSPIPS_NUM_OPTIONS; Index++) { + if (ConfigReg & OptionsTable[Index].Mask) { + OptionsFlag |= OptionsTable[Index].Option; + } + } + + /* + * Check for the LQSPI configuration options. + */ + ConfigReg = XQspiPs_ReadReg(InstancePtr->Config.BaseAddress, + XQSPIPS_LQSPI_CR_OFFSET); + + if ((ConfigReg & XQSPIPS_LQSPI_CR_LINEAR_MASK) != 0) { + OptionsFlag |= XQSPIPS_LQSPI_MODE_OPTION; + } + + return OptionsFlag; +} + +/*****************************************************************************/ +/** +* +* This function sets the clock prescaler for an QSPI device. The device +* must be idle rather than busy transferring data before setting these device +* options. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* @param Prescaler is the value that determine how much the clock should +* be divided by. Use the XQSPIPS_CLK_PRESCALE_* constants defined +* in xqspips.h for this setting. +* +* @return +* - XST_SUCCESS if options are successfully set. +* - XST_DEVICE_BUSY if the device is currently transferring data. +* The transfer must complete or be aborted before setting options. +* +* @note +* This function is not thread-safe. +* +******************************************************************************/ +s32 XQspiPs_SetClkPrescaler(XQspiPs *InstancePtr, u8 Prescaler) +{ + u32 ConfigReg; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(Prescaler <= XQSPIPS_CR_PRESC_MAXIMUM); + + /* + * Do not allow the slave select to change while a transfer is in + * progress. Not thread-safe. + */ + if (InstancePtr->IsBusy) { + return XST_DEVICE_BUSY; + } + + /* + * Read the configuration register, mask out the interesting bits, and set + * them with the shifted value passed into the function. Write the + * results back to the configuration register. + */ + ConfigReg = XQspiPs_ReadReg(InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET); + + ConfigReg &= ~XQSPIPS_CR_PRESC_MASK; + ConfigReg |= (u32) (Prescaler & XQSPIPS_CR_PRESC_MAXIMUM) << + XQSPIPS_CR_PRESC_SHIFT; + + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET, + ConfigReg); + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function gets the clock prescaler of an QSPI device. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* +* @return The prescaler value. +* +* @note None. +* +* +******************************************************************************/ +u8 XQspiPs_GetClkPrescaler(XQspiPs *InstancePtr) +{ + u32 ConfigReg; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + ConfigReg = XQspiPs_ReadReg(InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET); + + ConfigReg &= XQSPIPS_CR_PRESC_MASK; + + return (u8)(ConfigReg >> XQSPIPS_CR_PRESC_SHIFT); +} + +/*****************************************************************************/ +/** +* +* This function sets the delay register for the QSPI device driver. +* The delay register controls the Delay Between Transfers, Delay After +* Transfers, and the Delay Initially. The default value is 0x0. The range of +* each delay value is 0-255. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* @param DelayNss is the delay to de-assert slave select between +* two word transfers. +* @param DelayBtwn is the delay between one Slave Select being +* de-activated and the activation of another slave. The delay is +* the number of master clock periods given by DelayBtwn + 2. +* @param DelayAfter define the delay between the last bit of the current +* byte transfer and the first bit of the next byte transfer. +* The delay in number of master clock periods is given as: +* CHPA=0:DelayInit+DelayAfter+3 +* CHPA=1:DelayAfter+1 +* @param DelayInit is the delay between asserting the slave select signal +* and the first bit transfer. The delay int number of master clock +* periods is DelayInit+1. +* +* @return +* - XST_SUCCESS if delays are successfully set. +* - XST_DEVICE_BUSY if the device is currently transferring data. +* The transfer must complete or be aborted before setting options. +* +* @note None. +* +******************************************************************************/ +int XQspiPs_SetDelays(XQspiPs *InstancePtr, u8 DelayNss, u8 DelayBtwn, + u8 DelayAfter, u8 DelayInit) +{ + u32 DelayRegister; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Do not allow the delays to change while a transfer is in + * progress. Not thread-safe. + */ + if (InstancePtr->IsBusy) { + return XST_DEVICE_BUSY; + } + + /* Shift, Mask and OR the values to build the register settings */ + DelayRegister = (u32) DelayNss << XQSPIPS_DR_NSS_SHIFT; + DelayRegister |= (u32) DelayBtwn << XQSPIPS_DR_BTWN_SHIFT; + DelayRegister |= (u32) DelayAfter << XQSPIPS_DR_AFTER_SHIFT; + DelayRegister |= (u32) DelayInit; + + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_DR_OFFSET, DelayRegister); + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function gets the delay settings for an QSPI device. +* The delay register controls the Delay Between Transfers, Delay After +* Transfers, and the Delay Initially. The default value is 0x0. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* @param DelayNss is a pointer to the Delay to de-assert slave select +* between two word transfers. +* @param DelayBtwn is a pointer to the Delay Between transfers value. +* This is a return parameter. +* @param DelayAfter is a pointer to the Delay After transfer value. +* This is a return parameter. +* @param DelayInit is a pointer to the Delay Initially value. This is +* a return parameter. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XQspiPs_GetDelays(XQspiPs *InstancePtr, u8 *DelayNss, u8 *DelayBtwn, + u8 *DelayAfter, u8 *DelayInit) +{ + u32 DelayRegister; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + DelayRegister = XQspiPs_ReadReg(InstancePtr->Config.BaseAddress, + XQSPIPS_DR_OFFSET); + + *DelayInit = (u8)(DelayRegister & XQSPIPS_DR_INIT_MASK); + + *DelayAfter = (u8)((DelayRegister & XQSPIPS_DR_AFTER_MASK) >> + XQSPIPS_DR_AFTER_SHIFT); + + *DelayBtwn = (u8)((DelayRegister & XQSPIPS_DR_BTWN_MASK) >> + XQSPIPS_DR_BTWN_SHIFT); + + *DelayNss = (u8)((DelayRegister & XQSPIPS_DR_NSS_MASK) >> + XQSPIPS_DR_NSS_SHIFT); +} +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/qspips_v3_6/src/xqspips_selftest.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/qspips_v3_6/src/xqspips_selftest.c new file mode 100644 index 0000000..c72e952 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/qspips_v3_6/src/xqspips_selftest.c @@ -0,0 +1,135 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xqspips_selftest.c +* @addtogroup qspips_v3_6 +* @{ +* +* This file contains the implementation of selftest function for the QSPI +* device. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- -----------------------------------------------
+* 1.00  sdm 11/25/10 First release
+* 2.01a sg  02/03/13 Delay Register test is added with DelayNss parameter.
+* 3.1   hk  06/19/14 Remove checks for CR and ISR register values as they are
+*                    reset in the previous step.
+*
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xqspips.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +/*****************************************************************************/ +/** +* +* Runs a self-test on the driver/device. The self-test is destructive in that +* a reset of the device is performed in order to check the reset values of +* the registers and to get the device into a known state. +* +* Upon successful return from the self-test, the device is reset. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* +* @return +* - XST_SUCCESS if successful +* - XST_REGISTER_ERROR indicates a register did not read or write +* correctly. +* +* @note None. +* +******************************************************************************/ +int XQspiPs_SelfTest(XQspiPs *InstancePtr) +{ + int Status; + u8 DelayTestNss; + u8 DelayTestBtwn; + u8 DelayTestAfter; + u8 DelayTestInit; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Reset the QSPI device to leave it in a known good state + */ + XQspiPs_Reset(InstancePtr); + + DelayTestNss = 0x5A; + DelayTestBtwn = 0xA5; + DelayTestAfter = 0xAA; + DelayTestInit = 0x55; + + /* + * Write and read the delay register, just to be sure there is some + * hardware out there. + */ + Status = XQspiPs_SetDelays(InstancePtr, DelayTestNss, DelayTestBtwn, + DelayTestAfter, DelayTestInit); + if (Status != XST_SUCCESS) { + return Status; + } + + XQspiPs_GetDelays(InstancePtr, &DelayTestNss, &DelayTestBtwn, + &DelayTestAfter, &DelayTestInit); + if ((0x5A != DelayTestNss) || (0xA5 != DelayTestBtwn) || + (0xAA != DelayTestAfter) || (0x55 != DelayTestInit)) { + return XST_REGISTER_ERROR; + } + + Status = XQspiPs_SetDelays(InstancePtr, 0, 0, 0, 0); + if (Status != XST_SUCCESS) { + return Status; + } + + /* + * Reset the QSPI device to leave it in a known good state + */ + XQspiPs_Reset(InstancePtr); + + return XST_SUCCESS; +} +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/qspips_v3_6/src/xqspips_sinit.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/qspips_v3_6/src/xqspips_sinit.c new file mode 100644 index 0000000..da2dc1e --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/qspips_v3_6/src/xqspips_sinit.c @@ -0,0 +1,96 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xqspips_sinit.c +* @addtogroup qspips_v3_6 +* @{ +* +* The implementation of the XQspiPs component's static initialization +* functionality. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- -----------------------------------------------
+* 1.00  sdm 11/25/10 First release
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xstatus.h" +#include "xqspips.h" +#include "xparameters.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +extern XQspiPs_Config XQspiPs_ConfigTable[]; + +/*****************************************************************************/ +/** +* +* Looks up the device configuration based on the unique device ID. A table +* contains the configuration info for each device in the system. +* +* @param DeviceId contains the ID of the device to look up the +* configuration for. +* +* @return +* +* A pointer to the configuration found or NULL if the specified device ID was +* not found. See xqspips.h for the definition of XQspiPs_Config. +* +* @note None. +* +******************************************************************************/ +XQspiPs_Config *XQspiPs_LookupConfig(u16 DeviceId) +{ + XQspiPs_Config *CfgPtr = NULL; + int Index; + + for (Index = 0; Index < XPAR_XQSPIPS_NUM_INSTANCES; Index++) { + if (XQspiPs_ConfigTable[Index].DeviceId == DeviceId) { + CfgPtr = &XQspiPs_ConfigTable[Index]; + break; + } + } + return CfgPtr; +} +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/scugic_v4_0/src/Makefile b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/scugic_v4_0/src/Makefile new file mode 100644 index 0000000..04867a4 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/scugic_v4_0/src/Makefile @@ -0,0 +1,40 @@ +COMPILER= +ARCHIVER= +CP=cp +COMPILER_FLAGS= +EXTRA_COMPILER_FLAGS= +LIB=libxil.a + +CC_FLAGS = $(COMPILER_FLAGS) +ECC_FLAGS = $(EXTRA_COMPILER_FLAGS) + +RELEASEDIR=../../../lib +INCLUDEDIR=../../../include +INCLUDES=-I./. -I${INCLUDEDIR} + +OUTS = *.o + +LIBSOURCES:=*.c +INCLUDEFILES:=*.h + +OBJECTS = $(addsuffix .o, $(basename $(wildcard *.c))) + +libs: banner scugic_libs clean + +%.o: %.c + ${COMPILER} $(CC_FLAGS) $(ECC_FLAGS) $(INCLUDES) -o $@ $< + +banner: + echo "Compiling scugic" + +scugic_libs: ${OBJECTS} + $(ARCHIVER) -r ${RELEASEDIR}/${LIB} ${OBJECTS} + +.PHONY: include +include: scugic_includes + +scugic_includes: + ${CP} ${INCLUDEFILES} ${INCLUDEDIR} + +clean: + rm -rf ${OBJECTS} diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/scugic_v4_0/src/xscugic.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/scugic_v4_0/src/xscugic.c new file mode 100644 index 0000000..8a73638 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/scugic_v4_0/src/xscugic.c @@ -0,0 +1,1133 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xscugic.c +* @addtogroup scugic_v4_0 +* @{ +* +* Contains required functions for the XScuGic driver for the Interrupt +* Controller. See xscugic.h for a detailed description of the driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- --------------------------------------------------------
+* 1.00a drg  01/19/10 First release
+* 1.01a sdm  11/09/11 Changes are made in function XScuGic_CfgInitialize
+*                     Since entry is now made as pointer in the XScuGic
+*                     structure, necessary changes are made.
+*                     The HandlerTable can now be populated through the low
+*                     level routine XScuGic_RegisterHandler added in this
+*                     release. Hence necessary checks are added not to
+*                     overwrite the HandlerTable entriesin function
+*                     XScuGic_CfgInitialize.
+* 1.03a srt  02/27/13 Added APIs
+*                       -XScuGic_SetPriTrigTypeByDistAddr()
+*                       -XScuGic_GetPriTrigTypeByDistAddr()
+*                     Removed Offset calculation macros, defined in _hw.h
+*                     (CR 702687)
+*                     added support to direct interrupts  to the appropriate
+*                     CPU Earlier interrupts were directed to CPU1
+*                     (hard coded).Now depending upon the CPU selected by the
+*                     user(xparameters.h), interrupts will be directed to
+*                     the  relevant CPU. This fixes CR 699688.
+*
+* 1.04a hk   05/04/13 Assigned EffectiveAddr to CpuBaseAddress in
+*                     XScuGic_CfgInitialize. Fix for CR#704400 to remove
+*                     warnings.
+*                     Moved functions XScuGic_SetPriTrigTypeByDistAddr and
+*                    XScuGic_GetPriTrigTypeByDistAddr to xscugic_hw.c.
+*                    This is fix for CR#705621.
+* 1.06a asa  16/11/13 Fix for CR#749178. Assignment for EffectiveAddr
+*                     in function XScuGic_CfgInitialize is removed as it was
+*                     a bug.
+* 3.00  kvn  02/13/14 Modified code for MISRA-C:2012 compliance.
+* 3.01  pkp  06/19/15 Added XScuGic_InterruptMaptoCpu API for an interrupt
+*                     target CPU mapping
+* 3.02  pkp  11/09/15 Modified DistributorInit function for AMP case to add
+*                     the current cpu to interrupt processor targets registers
+* 3.2   asa  02/29/16 Modified DistributorInit function for Zynq AMP case. The
+*                     distributor is left uninitialized for Zynq AMP. It is
+*                     assumed that the distributor will be initialized by
+*                     Linux master. However for CortexR5 case, the earlier code
+*                     is left unchanged where the the interrupt processor target
+*                     registers in the distributor is initialized with the
+*                     corresponding CPU ID on which the application built over
+*                     the scugic driver runs. These changes fix CR#937243.
+* 3.3   pkp  05/12/16 Modified XScuGic_InterruptMaptoCpu to write proper value
+*                     to interrupt target register to fix CR#951848
+*
+* 3.4   asa  04/07/16 Created a new static function DoDistributorInit to
+*                     simplify the flow and avoid code duplication. Changes are
+*                     made for USE_AMP use case for R5. In a scenario
+*                     (in R5 split mode) when one R5 is operating with A53 in
+*                     open amp config and other R5 running baremetal app, the
+*                     existing code had the potential to stop the whole AMP
+*                     solution to work(if for some reason the R5 running the
+*                     baremetal app tasked to initialize the Distributor hangs
+*                     or crashes before initializing).Changes are made so that
+*                     the R5 under AMP first checks if the distributor is
+*                     enabled or not and if not, it does the standard
+*                     Distributor initialization.This fixes the CR#952962.
+* 3.4   mus  09/08/16 Added assert to avoid invalid access of GIC from CPUID 1
+*                     for single core zynq-7000s
+* 3.5   mus  10/05/16 Modified DistributorInit function to avoid
+*                     re-initialization of distributor, If it is already
+*                     initialized by other CPU.
+* 3.5   pkp  10/17/16 Modified XScuGic_InterruptMaptoCpu to correct the CPU Id
+*                     value and properly mask interrupt target processor value
+*                     to modify interrupt target processor register for a given
+*                     interrupt ID and cpu ID
+* 3.6   pkp  20/01/17 Added new API XScuGic_Stop to Disable distributor and
+*                     interrupts in case they are being used only by current
+*                     cpu. It also removes current cpu from interrupt target
+*                     registers for all interrupts.
+*       kvn  02/17/17 Add support for changing GIC CPU master at run time.
+*       kvn  02/28/17 Make the CpuId as static variable and Added new
+*                     XScugiC_GetCpuId to access CpuId.
+* 3.9   mus  02/21/18 Added new API's XScuGic_UnmapAllInterruptsFromCpu and
+*                     XScuGic_InterruptUnmapFromCpu, These API's can be used
+*                     by applications to unmap specific/all interrupts from
+*                     target CPU. It fixes CR#992490.
+* 3.10  mus  07/17/18 Updated file to fix the various coding style issues
+*                     reported by checkpatch. It fixes CR#1006344.
+* 3.10  aru  08/23/18 Resolved MISRA-C:2012 compliance mandatory violations
+*                     It fixes CR#1007753.
+* 3.10  mus  09/19/18 Fix cppcheck warnings
+* 4.0   mus  11/22/18 Fixed bugs in software interrupt generation through 
+*                      XScuGic_SoftwareIntr API
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ +#include "xil_types.h" +#include "xil_assert.h" +#include "xscugic.h" + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Variable Definitions *****************************/ +static u32 CpuId = XPAR_CPU_ID; /**< CPU Core identifier */ + +/************************** Function Prototypes ******************************/ + +static void StubHandler(void *CallBackRef); + +/*****************************************************************************/ +/** +* +* DoDistributorInit initializes the distributor of the GIC. The +* initialization entails: +* +* - Write the trigger mode, priority and target CPU +* - All interrupt sources are disabled +* - Enable the distributor +* +* @param InstancePtr is a pointer to the XScuGic instance. +* @param CpuID is the Cpu ID to be initialized. +* +* @return None +* +* @note None. +* +******************************************************************************/ +static void DoDistributorInit(XScuGic *InstancePtr, u32 CpuID) +{ + u32 Int_Id; +#if !defined (versal) || defined (ARMR5) + u32 LocalCpuID = CpuID; +#endif + +#if defined (versal) && !defined(ARMR5) + u32 temp; + + temp = XScuGic_DistReadReg(InstancePtr, XSCUGIC_DIST_EN_OFFSET); + temp = (XSCUGIC500_DCTLR_ARE_NS_ENABLE | XSCUGIC500_DCTLR_ARE_S_ENABLE); + temp &= ~(XSCUGIC_EN_INT_MASK); + XScuGic_DistWriteReg(InstancePtr, XSCUGIC_DIST_EN_OFFSET, temp); +#else + XScuGic_DistWriteReg(InstancePtr, XSCUGIC_DIST_EN_OFFSET, 0U); +#endif + + /* + * Set the security domains in the int_security registers for + * non-secure interrupts + * All are secure, so leave at the default. Set to 1 for non-secure + * interrupts. + */ + + /* + * For the Shared Peripheral Interrupts INT_ID[MAX..32], set: + */ + + /* + * 1. The trigger mode in the int_config register + * Only write to the SPI interrupts, so start at 32 + */ + for (Int_Id = 32U; Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS; + Int_Id = Int_Id+16U) { + /* + * Each INT_ID uses two bits, or 16 INT_ID per register + * Set them all to be level sensitive, active HIGH. + */ + XScuGic_DistWriteReg(InstancePtr, + XSCUGIC_INT_CFG_OFFSET_CALC(Int_Id), + 0U); + } + + +#define DEFAULT_PRIORITY 0xa0a0a0a0U + for (Int_Id = 0U; Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS; + Int_Id = Int_Id+4U) { + /* + * 2. The priority using int the priority_level register + * The priority_level and spi_target registers use one byte per + * INT_ID. + * Write a default value that can be changed elsewhere. + */ + XScuGic_DistWriteReg(InstancePtr, + XSCUGIC_PRIORITY_OFFSET_CALC(Int_Id), + DEFAULT_PRIORITY); + } + +#if defined (versal) && !defined(ARMR5) +for (Int_Id = 32U; Int_IdBaseAddress for this parameters, passing the physical +* address instead. +* +* @return +* - XST_SUCCESS if initialization was successful +* +* @note None. +* +******************************************************************************/ +s32 XScuGic_CfgInitialize(XScuGic *InstancePtr, + XScuGic_Config *ConfigPtr, + u32 EffectiveAddr) +{ + u32 Int_Id; + u32 Cpu_Id = CpuId + (u32)1; + (void) EffectiveAddr; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(ConfigPtr != NULL); + /* + * Detect Zynq-7000 base silicon configuration,Dual or Single CPU. + * If it is single CPU cnfiguration then invoke assert for CPU ID=1 + */ +#ifdef ARMA9 + if (XPAR_CPU_ID == 0x01) { + Xil_AssertNonvoid((Xil_In32(XPS_EFUSE_BASEADDR + + EFUSE_STATUS_OFFSET) & EFUSE_STATUS_CPU_MASK) == 0); + } +#endif + + if(InstancePtr->IsReady != XIL_COMPONENT_IS_READY) { + + InstancePtr->IsReady = 0U; + InstancePtr->Config = ConfigPtr; + + + for (Int_Id = 0U; Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS; + Int_Id++) { + /* + * Initalize the handler to point to a stub to handle an + * interrupt which has not been connected to a handler + * Only initialize it if the handler is 0 which means it + * was not initialized statically by the tools/user. Set + * the callback reference to this instance so that + * unhandled interrupts can be tracked. + */ + if ((InstancePtr->Config->HandlerTable[Int_Id].Handler + == (Xil_InterruptHandler)NULL)) { + InstancePtr->Config->HandlerTable[Int_Id].Handler + = (Xil_InterruptHandler)StubHandler; + } + InstancePtr->Config->HandlerTable[Int_Id].CallBackRef = + InstancePtr; + } +#if defined (versal) && !defined(ARMR5) + u32 Waker_State; + xil_printf("Execuing on the a72\n"); + Waker_State = XScuGic_ReDistReadReg(InstancePtr,XSCUGIC_RDIST_WAKER_OFFSET); + XScuGic_ReDistWriteReg(InstancePtr,XSCUGIC_RDIST_WAKER_OFFSET, + Waker_State & (~ XSCUGIC_RDIST_WAKER_LOW_POWER_STATE_MASK)); + /* Enable system reg interface through ICC_SRE_EL1 */ + #if EL3 + XScuGic_Enable_SystemReg_CPU_Interface_EL3(); + #endif + XScuGic_Enable_SystemReg_CPU_Interface_EL1(); + isb(); +#endif + XScuGic_Stop(InstancePtr); + DistributorInit(InstancePtr, Cpu_Id); +#if defined (versal) && !defined(ARMR5) + XScuGic_set_priority_filter(0xff); +#else + CPUInitialize(InstancePtr); +#endif + + InstancePtr->IsReady = XIL_COMPONENT_IS_READY; + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* Makes the connection between the Int_Id of the interrupt source and the +* associated handler that is to run when the interrupt is recognized. The +* argument provided in this call as the Callbackref is used as the argument +* for the handler when it is called. +* +* @param InstancePtr is a pointer to the XScuGic instance. +* @param Int_Id contains the ID of the interrupt source and should be +* in the range of 0 to XSCUGIC_MAX_NUM_INTR_INPUTS - 1 +* @param Handler to the handler for that interrupt. +* @param CallBackRef is the callback reference, usually the instance +* pointer of the connecting driver. +* +* @return +* +* - XST_SUCCESS if the handler was connected correctly. +* +* @note +* +* WARNING: The handler provided as an argument will overwrite any handler +* that was previously connected. +* +****************************************************************************/ +s32 XScuGic_Connect(XScuGic *InstancePtr, u32 Int_Id, + Xil_InterruptHandler Handler, void *CallBackRef) +{ + /* + * Assert the arguments + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS); + Xil_AssertNonvoid(Handler != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * The Int_Id is used as an index into the table to select the proper + * handler + */ + InstancePtr->Config->HandlerTable[Int_Id].Handler = (Xil_InterruptHandler)Handler; + InstancePtr->Config->HandlerTable[Int_Id].CallBackRef = CallBackRef; + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* Updates the interrupt table with the Null Handler and NULL arguments at the +* location pointed at by the Int_Id. This effectively disconnects that interrupt +* source from any handler. The interrupt is disabled also. +* +* @param InstancePtr is a pointer to the XScuGic instance to be worked on. +* @param Int_Id contains the ID of the interrupt source and should +* be in the range of 0 to XSCUGIC_MAX_NUM_INTR_INPUTS - 1 +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void XScuGic_Disconnect(XScuGic *InstancePtr, u32 Int_Id) +{ + u32 Mask; + + /* + * Assert the arguments + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * The Int_Id is used to create the appropriate mask for the + * desired bit position. Int_Id currently limited to 0 - 31 + */ + Mask = 0x00000001U << (Int_Id % 32U); + + /* + * Disable the interrupt such that it won't occur while disconnecting + * the handler, only disable the specified interrupt id without + * modifying the other interrupt ids + */ + XScuGic_DistWriteReg(InstancePtr, (u32)XSCUGIC_DISABLE_OFFSET + + ((Int_Id / 32U) * 4U), Mask); + + /* + * Disconnect the handler and connect a stub, the callback reference + * must be set to this instance to allow unhandled interrupts to be + * tracked + */ + InstancePtr->Config->HandlerTable[Int_Id].Handler = (Xil_InterruptHandler)StubHandler; + InstancePtr->Config->HandlerTable[Int_Id].CallBackRef = InstancePtr; +} + +/*****************************************************************************/ +/** +* +* Enables the interrupt source provided as the argument Int_Id. Any pending +* interrupt condition for the specified Int_Id will occur after this function is +* called. +* +* @param InstancePtr is a pointer to the XScuGic instance. +* @param Int_Id contains the ID of the interrupt source and should be +* in the range of 0 to XSCUGIC_MAX_NUM_INTR_INPUTS - 1 +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void XScuGic_Enable(XScuGic *InstancePtr, u32 Int_Id) +{ + u32 Mask; +#if defined (versal) && !defined(ARMR5) + u32 temp; +#endif + /* + * Assert the arguments + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + +#if defined (versal) && !defined(ARMR5) + if (Int_Id < XSCUGIC_SPI_INT_ID_START) + { + + Int_Id &= 0x1f; + Int_Id = 1 << Int_Id; + + temp = XScuGic_ReDistSGIPPIReadReg(InstancePtr,XSCUGIC_RDIST_ISENABLE_OFFSET); + temp |= Int_Id; + XScuGic_ReDistSGIPPIWriteReg(InstancePtr,XSCUGIC_RDIST_ISENABLE_OFFSET,temp); + return; + } +#endif + /* + * The Int_Id is used to create the appropriate mask for the + * desired bit position. Int_Id currently limited to 0 - 31 + */ + Mask = 0x00000001U << (Int_Id % 32U); + + /* + * Enable the selected interrupt source by setting the + * corresponding bit in the Enable Set register. + */ + XScuGic_DistWriteReg(InstancePtr, (u32)XSCUGIC_ENABLE_SET_OFFSET + + ((Int_Id / 32U) * 4U), Mask); +} + +/*****************************************************************************/ +/** +* +* Disables the interrupt source provided as the argument Int_Id such that the +* interrupt controller will not cause interrupts for the specified Int_Id. The +* interrupt controller will continue to hold an interrupt condition for the +* Int_Id, but will not cause an interrupt. +* +* @param InstancePtr is a pointer to the XScuGic instance. +* @param Int_Id contains the ID of the interrupt source and should be +* in the range of 0 to XSCUGIC_MAX_NUM_INTR_INPUTS - 1 +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void XScuGic_Disable(XScuGic *InstancePtr, u32 Int_Id) +{ + u32 Mask; + + /* + * Assert the arguments + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * The Int_Id is used to create the appropriate mask for the + * desired bit position. Int_Id currently limited to 0 - 31 + */ + Mask = 0x00000001U << (Int_Id % 32U); + + /* + * Disable the selected interrupt source by setting the + * corresponding bit in the IDR. + */ + XScuGic_DistWriteReg(InstancePtr, (u32)XSCUGIC_DISABLE_OFFSET + + ((Int_Id / 32U) * 4U), Mask); +} + +/*****************************************************************************/ +/** +* +* Allows software to simulate an interrupt in the interrupt controller. This +* function will only be successful when the interrupt controller has been +* started in simulation mode. A simulated interrupt allows the interrupt +* controller to be tested without any device to drive an interrupt input +* signal into it. +* +* @param InstancePtr is a pointer to the XScuGic instance. +* @param Int_Id is the software interrupt ID to simulate an interrupt. +* @param Cpu_Id is the list of CPUs to send the interrupt. +* +* @return +* +* XST_SUCCESS if successful, or XST_FAILURE if the interrupt could not be +* simulated +* +* @note None. +* +******************************************************************************/ +s32 XScuGic_SoftwareIntr(XScuGic *InstancePtr, u32 Int_Id, u32 Cpu_Id) +{ + u32 Mask; + + /* + * Assert the arguments + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(Int_Id <= 15U); + Xil_AssertNonvoid(Cpu_Id <= 255U); + +#if defined (versal) && !defined(ARMR5) + Mask = (Cpu_Id | (Int_Id << XSCUGIC_SGIR_EL1_INITID_SHIFT)); +#if EL3 + XScuGic_WriteICC_SGI0R_EL1(Mask); +#else + XScuGic_WriteICC_SGI1R_EL1(Mask); +#endif +#else + + /* + * The Int_Id is used to create the appropriate mask for the + * desired interrupt. Int_Id currently limited to 0 - 15 + * Use the target list for the Cpu ID. + */ + Mask = ((Cpu_Id << 16U) | Int_Id) & + (XSCUGIC_SFI_TRIG_CPU_MASK | XSCUGIC_SFI_TRIG_INTID_MASK); + + /* + * Write to the Software interrupt trigger register. Use the appropriate + * CPU Int_Id. + */ + XScuGic_DistWriteReg(InstancePtr, XSCUGIC_SFI_TRIG_OFFSET, Mask); + + /* Indicate the interrupt was successfully simulated */ +#endif + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* A stub for the asynchronous callback. The stub is here in case the upper +* layers forget to set the handler. +* +* @param CallBackRef is a pointer to the upper layer callback reference +* +* @return None. +* +* @note None. +* +******************************************************************************/ +static void StubHandler(void *CallBackRef) +{ + /* + * verify that the inputs are valid + */ + Xil_AssertVoid(CallBackRef != NULL); + + /* + * Indicate another unhandled interrupt for stats + */ + ((XScuGic *)((void *)CallBackRef))->UnhandledInterrupts++; +} + +/****************************************************************************/ +/** +* Sets the interrupt priority and trigger type for the specificd IRQ source. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param Int_Id is the IRQ source number to modify +* @param Priority is the new priority for the IRQ source. 0 is highest +* priority, 0xF8(248) is lowest. There are 32 priority levels +* supported with a step of 8. Hence the supported priorities are +* 0, 8, 16, 32, 40 ..., 248. +* @param Trigger is the new trigger type for the IRQ source. +* Each bit pair describes the configuration for an INT_ID. +* SFI Read Only b10 always +* PPI Read Only depending on how the PPIs are configured. +* b01 Active HIGH level sensitive +* b11 Rising edge sensitive +* SPI LSB is read only. +* b01 Active HIGH level sensitive +* b11 Rising edge sensitive/ +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XScuGic_SetPriorityTriggerType(XScuGic *InstancePtr, u32 Int_Id, + u8 Priority, u8 Trigger) +{ + u32 RegValue; +#if defined (versal) && !defined(ARMR5) + u32 temp,Index; +#endif + u8 LocalPriority; + LocalPriority = Priority; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS); + Xil_AssertVoid(Trigger <= (u8)XSCUGIC_INT_CFG_MASK); + Xil_AssertVoid(LocalPriority <= (u8)XSCUGIC_MAX_INTR_PRIO_VAL); +#if defined (versal) && !defined(ARMR5) + if (Int_Id < XSCUGIC_SPI_INT_ID_START ) + { + XScuGic_ReDistSGIPPIWriteReg(InstancePtr,XSCUGIC_RDIST_INT_PRIORITY_OFFSET_CALC(Int_Id),Priority); + temp = XScuGic_ReDistSGIPPIReadReg(InstancePtr,XSCUGIC_RDIST_INT_CONFIG_OFFSET_CALC(Int_Id)); + Index = XScuGic_Get_Rdist_Int_Trigger_Index(Int_Id); + temp |= (Trigger << Index); + XScuGic_ReDistSGIPPIWriteReg(InstancePtr,XSCUGIC_RDIST_INT_CONFIG_OFFSET_CALC(Int_Id),temp); + return; + } +#endif + + /* + * Determine the register to write to using the Int_Id. + */ + RegValue = XScuGic_DistReadReg(InstancePtr, + XSCUGIC_PRIORITY_OFFSET_CALC(Int_Id)); + + /* + * The priority bits are Bits 7 to 3 in GIC Priority Register. This + * means the number of priority levels supported are 32 and they are + * in steps of 8. The priorities can be 0, 8, 16, 32, 48, ... etc. + * The lower order 3 bits are masked before putting it in the register. + */ + LocalPriority = LocalPriority & (u8)XSCUGIC_INTR_PRIO_MASK; + /* + * Shift and Mask the correct bits for the priority and trigger in the + * register + */ + RegValue &= ~(XSCUGIC_PRIORITY_MASK << ((Int_Id%4U)*8U)); + RegValue |= (u32)LocalPriority << ((Int_Id%4U)*8U); + + /* + * Write the value back to the register. + */ + XScuGic_DistWriteReg(InstancePtr, XSCUGIC_PRIORITY_OFFSET_CALC(Int_Id), + RegValue); + + /* + * Determine the register to write to using the Int_Id. + */ + RegValue = XScuGic_DistReadReg(InstancePtr, + XSCUGIC_INT_CFG_OFFSET_CALC(Int_Id)); + + /* + * Shift and Mask the correct bits for the priority and trigger in the + * register + */ + RegValue &= ~(XSCUGIC_INT_CFG_MASK << ((Int_Id%16U)*2U)); + RegValue |= (u32)Trigger << ((Int_Id%16U)*2U); + + /* + * Write the value back to the register. + */ + XScuGic_DistWriteReg(InstancePtr, XSCUGIC_INT_CFG_OFFSET_CALC(Int_Id), + RegValue); + +} + +/****************************************************************************/ +/** +* Gets the interrupt priority and trigger type for the specificd IRQ source. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param Int_Id is the IRQ source number to modify +* @param Priority is a pointer to the value of the priority of the IRQ +* source. This is a return value. +* @param Trigger is pointer to the value of the trigger of the IRQ +* source. This is a return value. +* +* @return None. +* +* @note None +* +*****************************************************************************/ +void XScuGic_GetPriorityTriggerType(XScuGic *InstancePtr, u32 Int_Id, + u8 *Priority, u8 *Trigger) +{ + u32 RegValue; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS); + Xil_AssertVoid(Priority != NULL); + Xil_AssertVoid(Trigger != NULL); + + /* + * Determine the register to read to using the Int_Id. + */ + RegValue = XScuGic_DistReadReg(InstancePtr, + XSCUGIC_PRIORITY_OFFSET_CALC(Int_Id)); + + /* + * Shift and Mask the correct bits for the priority and trigger in the + * register + */ + RegValue = RegValue >> ((Int_Id%4U)*8U); + *Priority = (u8)(RegValue & XSCUGIC_PRIORITY_MASK); + + /* + * Determine the register to read to using the Int_Id. + */ + RegValue = XScuGic_DistReadReg(InstancePtr, + XSCUGIC_INT_CFG_OFFSET_CALC(Int_Id)); + + /* + * Shift and Mask the correct bits for the priority and trigger in the + * register + */ + RegValue = RegValue >> ((Int_Id%16U)*2U); + + *Trigger = (u8)(RegValue & XSCUGIC_INT_CFG_MASK); +} +/****************************************************************************/ +/** +* Sets the target CPU for the interrupt of a peripheral +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param Cpu_Id is a CPU number for which the interrupt has to be targeted +* @param Int_Id is the IRQ source number to modify +* +* @return None. +* +* @note None +* +*****************************************************************************/ +void XScuGic_InterruptMaptoCpu(XScuGic *InstancePtr, u8 Cpu_Id, u32 Int_Id) +{ + u32 RegValue; + u32 Offset; + RegValue = XScuGic_DistReadReg(InstancePtr, + XSCUGIC_SPI_TARGET_OFFSET_CALC(Int_Id)); + + Offset = (Int_Id & 0x3U); + Cpu_Id = (0x1U << Cpu_Id); + + RegValue = (RegValue & (~(0xFFU << (Offset*8U)))); + RegValue |= ((Cpu_Id) << (Offset*8U)); + + XScuGic_DistWriteReg(InstancePtr, + XSCUGIC_SPI_TARGET_OFFSET_CALC(Int_Id), + RegValue); +} +/****************************************************************************/ +/** +* Unmaps specific SPI interrupt from the target CPU +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param Cpu_Id is a CPU number from which the interrupt has to be +* unmapped +* @param Int_Id is the IRQ source number to modify +* +* @return None. +* +* @note None +* +*****************************************************************************/ +void XScuGic_InterruptUnmapFromCpu(XScuGic *InstancePtr, u8 Cpu_Id, u32 Int_Id) +{ + u32 RegValue; + u8 BitPos; + + Xil_AssertVoid(InstancePtr != NULL); + + RegValue = XScuGic_DistReadReg(InstancePtr, + XSCUGIC_SPI_TARGET_OFFSET_CALC(Int_Id)); + + /* + * Identify bit position corresponding to Int_Id and Cpu_Id, + * in interrupt target register and clear it + */ + BitPos = ((Int_Id % 4U) * 8U) + Cpu_Id; + RegValue &= (~(1U << BitPos)); + XScuGic_DistWriteReg(InstancePtr, + XSCUGIC_SPI_TARGET_OFFSET_CALC(Int_Id), + RegValue); +} +/****************************************************************************/ +/** +* Unmaps all SPI interrupts from the target CPU +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param Cpu_Id is a CPU number from which the interrupts has to be +* unmapped +* +* @return None. +* +* @note None +* +*****************************************************************************/ +void XScuGic_UnmapAllInterruptsFromCpu(XScuGic *InstancePtr, u8 Cpu_Id) +{ + u32 Int_Id; + u32 Target_Cpu; + u32 LocalCpuID = (1U << Cpu_Id); + + Xil_AssertVoid(InstancePtr != NULL); + + LocalCpuID |= LocalCpuID << 8U; + LocalCpuID |= LocalCpuID << 16U; + + for (Int_Id = 32U; Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS; + Int_Id = Int_Id+4U) { + + Target_Cpu = XScuGic_DistReadReg(InstancePtr, + XSCUGIC_SPI_TARGET_OFFSET_CALC(Int_Id)); + /* Remove LocalCpuID from interrupt target register */ + Target_Cpu &= (~LocalCpuID); + XScuGic_DistWriteReg(InstancePtr, + XSCUGIC_SPI_TARGET_OFFSET_CALC(Int_Id), Target_Cpu); + + } +} +/****************************************************************************/ +/** +* It checks if the interrupt target register contains all interrupts to be +* targeted for current CPU. If they are programmed to be forwarded to current +* cpu, this API disable all interrupts and disable GIC distributor. +* This API also removes current CPU from interrupt target registers for all +* interrupt. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* +* @return None. +* +* @note None +* +*****************************************************************************/ +void XScuGic_Stop(XScuGic *InstancePtr) +{ + u32 Int_Id; + u32 RegValue; + u32 Target_Cpu; + u32 DistDisable = 1; /* Track distributor status*/ + u32 LocalCpuID = ((u32)0x1 << CpuId); + + Xil_AssertVoid(InstancePtr != NULL); + + /* If distributor is already disabled, no need to do anything */ + RegValue = XScuGic_DistReadReg(InstancePtr, XSCUGIC_DIST_EN_OFFSET); + if ((RegValue & XSCUGIC_EN_INT_MASK) == 0U) { + return; + } + + LocalCpuID |= LocalCpuID << 8U; + LocalCpuID |= LocalCpuID << 16U; + + /* + * Check if the interrupt are targeted to current cpu only or not. + * Also remove current cpu from interrupt target register for all + * interrupts. + */ + for (Int_Id = 32U; Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS; + Int_Id = Int_Id+4U) { + + Target_Cpu = XScuGic_DistReadReg(InstancePtr, + XSCUGIC_SPI_TARGET_OFFSET_CALC(Int_Id)); + if ((Target_Cpu != LocalCpuID) && (Target_Cpu != 0)) { + /* + * If any other CPU is also programmed to target + * register, GIC distributor can not be disabled. + */ + DistDisable = 0; + } + + /* Remove current CPU from interrupt target register */ + Target_Cpu &= (~LocalCpuID); + XScuGic_DistWriteReg(InstancePtr, + XSCUGIC_SPI_TARGET_OFFSET_CALC(Int_Id), Target_Cpu); + + } + + /* + * If GIC distributor is safe to be disabled, disable all the interrupt + * and then disable distributor. + */ + if (DistDisable == 1) { + for (Int_Id = 0U; Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS; + Int_Id = Int_Id+32U) { + /* + * Disable all the interrupts + */ + XScuGic_DistWriteReg(InstancePtr, + XSCUGIC_EN_DIS_OFFSET_CALC(XSCUGIC_DISABLE_OFFSET, + Int_Id), + 0xFFFFFFFFU); + } + XScuGic_DistWriteReg(InstancePtr, XSCUGIC_DIST_EN_OFFSET, 0U); + } +} + +/****************************************************************************/ +/** +* This updates the CpuId global variable. +* +* @param CpuCoreId is the CPU core number. +* +* @return None. +* +* @note None +* +*****************************************************************************/ +void XScuGic_SetCpuID(u32 CpuCoreId) +{ + Xil_AssertVoid(CpuCoreId <= 1U); + + CpuId = CpuCoreId; +} + +/****************************************************************************/ +/** +* This function returns the CpuId variable. +* +* @return The CPU core number. +* +* @note None. +* +*****************************************************************************/ +u32 XScuGic_GetCpuID(void) +{ + return CpuId; +} +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/scugic_v4_0/src/xscugic.h b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/scugic_v4_0/src/xscugic.h new file mode 100644 index 0000000..5502a20 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/scugic_v4_0/src/xscugic.h @@ -0,0 +1,598 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xscugic.h +* @addtogroup scugic_v4_0 +* @{ +* @details +* +* The generic interrupt controller driver component. +* +* The interrupt controller driver uses the idea of priority for the various +* handlers. Priority is an integer within the range of 1 and 31 inclusive with +* default of 1 being the highest priority interrupt source. The priorities +* of the various sources can be dynamically altered as needed through +* hardware configuration. +* +* The generic interrupt controller supports the following +* features: +* +* - specific individual interrupt enabling/disabling +* - specific individual interrupt acknowledging +* - attaching specific callback function to handle interrupt source +* - assigning desired priority to interrupt source if default is not +* acceptable. +* +* Details about connecting the interrupt handler of the driver are contained +* in the source file specific to interrupt processing, xscugic_intr.c. +* +* This driver is intended to be RTOS and processor independent. It works with +* physical addresses only. Any needs for dynamic memory management, threads +* or thread mutual exclusion, virtual memory, or cache control must be +* satisfied by the layer above this driver. +* +* Interrupt Vector Tables +* +* The device ID of the interrupt controller device is used by the driver as a +* direct index into the configuration data table. The user should populate the +* vector table with handlers and callbacks at run-time using the +* XScuGic_Connect() and XScuGic_Disconnect() functions. +* +* Each vector table entry corresponds to a device that can generate an +* interrupt. Each entry contains an interrupt handler function and an +* argument to be passed to the handler when an interrupt occurs. The +* user must use XScuGic_Connect() when the interrupt handler takes an +* argument other than the base address. +* +* Nested Interrupts Processing +* +* Nested interrupts are not supported by this driver. +* +* NOTE: +* The generic interrupt controller is not a part of the snoop control unit +* as indicated by the prefix "scu" in the name of the driver. +* It is an independent module in APU. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- ---------------------------------------------------------
+* 1.00a drg  01/19/00 First release
+* 1.01a sdm  11/09/11 The XScuGic and XScuGic_Config structures have changed.
+*		      The HandlerTable (of type XScuGic_VectorTableEntry) is
+*		      moved to XScuGic_Config structure from XScuGic structure.
+*
+*		      The "Config" entry in XScuGic structure is made as
+*		      pointer for better efficiency.
+*
+*		      A new file named as xscugic_hw.c is now added. It is
+*		      to implement low level driver routines without using
+*		      any xscugic instance pointer. They are useful when the
+*		      user wants to use xscugic through device id or
+*		      base address. The driver routines provided are explained
+*		      below.
+*		      XScuGic_DeviceInitialize that takes device id as
+*		      argument and initializes the device (without calling
+*		      XScuGic_CfgInitialize).
+*		      XScuGic_DeviceInterruptHandler that takes device id
+*		      as argument and calls appropriate handlers from the
+*		      HandlerTable.
+*		      XScuGic_RegisterHandler that registers a new handler
+*		      by taking xscugic hardware base address as argument.
+*		      LookupConfigByBaseAddress is used to return the
+*		      corresponding config structure from XScuGic_ConfigTable
+*		      based on the scugic base address passed.
+* 1.02a sdm  12/20/11 Removed AckBeforeService from the XScuGic_Config
+*		      structure.
+* 1.03a srt  02/27/13 Moved Offset calculation macros from *.c and *_hw.c to
+*		      *_hw.h
+*		      Added APIs
+*			- XScuGic_SetPriTrigTypeByDistAddr()
+*			- XScuGic_GetPriTrigTypeByDistAddr()
+*		      (CR 702687)
+*			Added support to direct interrupts to the appropriate CPU. Earlier
+*			  interrupts were directed to CPU1 (hard coded). Now depending
+*			  upon the CPU selected by the user (xparameters.h), interrupts
+*			  will be directed to the relevant CPU. This fixes CR 699688.
+* 1.04a hk   05/04/13 Assigned EffectiveAddr to CpuBaseAddress in
+*			  XScuGic_CfgInitialize. Fix for CR#704400 to remove warnings.
+*			  Moved functions XScuGic_SetPriTrigTypeByDistAddr and
+*             XScuGic_GetPriTrigTypeByDistAddr to xscugic_hw.c.
+*			  This is fix for CR#705621.
+* 1.05a hk   06/26/13 Modified tcl to export external interrupts correctly to
+*                     xparameters.h. Fix for CR's 690505, 708928 & 719359.
+* 2.0   adk  12/10/13 Updated as per the New Tcl API's
+* 2.1   adk  25/04/14 Fixed the CR:789373 changes are made in the driver tcl file.
+* 3.00  kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.2   asa  02/29/16 Modified DistributorInit function for Zynq AMP case. The
+*			  distributor is left uninitialized for Zynq AMP. It is assumed
+*             that the distributor will be initialized by Linux master. However
+*             for CortexR5 case, the earlier code is left unchanged where the
+*             the interrupt processor target registers in the distributor is
+*             initialized with the corresponding CPU ID on which the application
+*             built over the scugic driver runs.
+*             These changes fix CR#937243.
+*
+* 3.4   asa  04/07/16 Created a new static function DoDistributorInit to simplify
+*            the flow and avoid code duplication. Changes are made for
+*            USE_AMP use case for R5. In a scenario (in R5 split mode) when
+*            one R5 is operating with A53 in open amp config and other
+*            R5 running baremetal app, the existing code
+*            had the potential to stop the whole AMP solution to work (if
+*            for some reason the R5 running the baremetal app tasked to
+*            initialize the Distributor hangs or crashes before initializing).
+*            Changes are made so that the R5 under AMP first checks if
+*            the distributor is enabled or not and if not, it does the
+*            standard Distributor initialization.
+*            This fixes the CR#952962.
+* 3.6   ms   01/23/17 Modified xil_printf statement in main function for all
+*                     examples to ensure that "Successfully ran" and "Failed"
+*                     strings are available in all examples. This is a fix
+*                     for CR-965028.
+*       kvn  02/17/17 Add support for changing GIC CPU master at run time.
+*       kvn  02/28/17 Make the CpuId as static variable and Added new
+*                     XScugiC_GetCpuId to access CpuId.
+*       ms   03/17/17 Added readme.txt file in examples folder for doxygen
+*                     generation.
+* 3.7   ms   04/11/17 Modified tcl file to add suffix U for all macro
+*                     definitions of scugic in xparameters.h
+* 3.8   mus  07/05/17 Updated scugic.tcl to add support for intrrupts connected
+*                     through util_reduced_vector IP(OR gate)
+*       mus  07/05/17 Updated xdefine_zynq_canonical_xpars proc to initialize
+*                     the HandlerTable in XScuGic_ConfigTable to 0, it removes
+*                     the compilation warning in xscugic_g.c. Fix for CR#978736.
+*       mus  07/25/17 Updated xdefine_gic_params proc to export correct canonical
+*                     definitions for pl to ps interrupts.Fix for CR#980534
+* 3.9   mus  02/21/18 Added new API's XScuGic_UnmapAllInterruptsFromCpu and
+*                     XScuGic_InterruptUnmapFromCpu, These API's can be used
+*                     by applications to unmap specific/all interrupts from
+*                     target CPU.
+* 3.10  aru  08/23/18 Resolved MISRA-C:2012 compliance mandatory violations
+* 4.0   mus  11/22/18 Fixed bugs in software interrupt generation through 
+*                      XScuGic_SoftwareIntr API
+*
+* 
+* +******************************************************************************/ + +#ifndef XSCUGIC_H /* prevent circular inclusions */ +#define XSCUGIC_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + + +/***************************** Include Files *********************************/ + +#include "xstatus.h" +#include "xil_io.h" +#include "xscugic_hw.h" +#include "xil_exception.h" + +/************************** Constant Definitions *****************************/ + +#define EFUSE_STATUS_OFFSET 0x10 +#define EFUSE_STATUS_CPU_MASK 0x80 + +#if !defined (ARMR5) && !defined (__aarch64__) && !defined (ARMA53_32) +#define ARMA9 +#endif + +#define XSCUGIC500_DCTLR_ARE_NS_ENABLE 0x20 +#define XSCUGIC500_DCTLR_ARE_S_ENABLE 0x10 +/**************************** Type Definitions *******************************/ + +/* The following data type defines each entry in an interrupt vector table. + * The callback reference is the base address of the interrupting device + * for the low level driver and an instance pointer for the high level driver. + */ +typedef struct +{ + Xil_InterruptHandler Handler; + void *CallBackRef; +} XScuGic_VectorTableEntry; + +/** + * This typedef contains configuration information for the device. + */ +typedef struct +{ + u16 DeviceId; /**< Unique ID of device */ + u32 CpuBaseAddress; /**< CPU Interface Register base address */ + u32 DistBaseAddress; /**< Distributor Register base address */ + XScuGic_VectorTableEntry HandlerTable[XSCUGIC_MAX_NUM_INTR_INPUTS];/**< + Vector table of interrupt handlers */ +} XScuGic_Config; + +/** + * The XScuGic driver instance data. The user is required to allocate a + * variable of this type for every intc device in the system. A pointer + * to a variable of this type is then passed to the driver API functions. + */ +typedef struct +{ + XScuGic_Config *Config; /**< Configuration table entry */ + u32 IsReady; /**< Device is initialized and ready */ + u32 UnhandledInterrupts; /**< Intc Statistics */ +} XScuGic; + +/***************** Macros (Inline Functions) Definitions *********************/ + +/****************************************************************************/ +/** +* +* Write the given CPU Interface register +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param RegOffset is the register offset to be written +* @param Data is the 32-bit value to write to the register +* +* @return None. +* +* @note +* C-style signature: +* void XScuGic_CPUWriteReg(XScuGic *InstancePtr, u32 RegOffset, u32 Data) +* +*****************************************************************************/ +#define XScuGic_CPUWriteReg(InstancePtr, RegOffset, Data) \ +(XScuGic_WriteReg(((InstancePtr)->Config->CpuBaseAddress), (RegOffset), \ + ((u32)(Data)))) + +/****************************************************************************/ +/** +* +* Read the given CPU Interface register +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param RegOffset is the register offset to be read +* +* @return The 32-bit value of the register +* +* @note +* C-style signature: +* u32 XScuGic_CPUReadReg(XScuGic *InstancePtr, u32 RegOffset) +* +*****************************************************************************/ +#define XScuGic_CPUReadReg(InstancePtr, RegOffset) \ + (XScuGic_ReadReg(((InstancePtr)->Config->CpuBaseAddress), (RegOffset))) + +/****************************************************************************/ +/** +* +* Write the given Distributor Interface register +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param RegOffset is the register offset to be written +* @param Data is the 32-bit value to write to the register +* +* @return None. +* +* @note +* C-style signature: +* void XScuGic_DistWriteReg(XScuGic *InstancePtr, u32 RegOffset, u32 Data) +* +*****************************************************************************/ +#define XScuGic_DistWriteReg(InstancePtr, RegOffset, Data) \ +(XScuGic_WriteReg(((InstancePtr)->Config->DistBaseAddress), (RegOffset), \ + ((u32)(Data)))) + +/****************************************************************************/ +/** +* +* Read the given Distributor Interface register +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param RegOffset is the register offset to be read +* +* @return The 32-bit value of the register +* +* @note +* C-style signature: +* u32 XScuGic_DistReadReg(XScuGic *InstancePtr, u32 RegOffset) +* +*****************************************************************************/ +#define XScuGic_DistReadReg(InstancePtr, RegOffset) \ +(XScuGic_ReadReg(((InstancePtr)->Config->DistBaseAddress), (RegOffset))) + +/****************************************************************************/ +/** +* +* Write the given ReDistributor Interface register +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param RegOffset is the register offset to be written +* @param Data is the 32-bit value to write to the register +* +* @return None. +* +* @note +* C-style signature: +* void XScuGic_DistWriteReg(XScuGic *InstancePtr, u32 RegOffset, u32 Data) +* +*****************************************************************************/ +#define XScuGic_ReDistWriteReg(InstancePtr, RegOffset, Data) \ +(XScuGic_WriteReg(((InstancePtr)->Config->DistBaseAddress)+ \ + XSCUGIC_RDIST_OFFSET, (RegOffset), ((u32)(Data)))) + +/****************************************************************************/ +/** +* +* Read the given ReDistributor Interface register +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param RegOffset is the register offset to be read +* +* @return The 32-bit value of the register +* +* @note +* C-style signature: +* u32 XScuGic_DistReadReg(XScuGic *InstancePtr, u32 RegOffset) +* +*****************************************************************************/ +#define XScuGic_ReDistReadReg(InstancePtr, RegOffset) \ +(XScuGic_ReadReg((((InstancePtr)->Config->DistBaseAddress)+ \ +XSCUGIC_RDIST_OFFSET), (RegOffset))) + +/****************************************************************************/ +/** +* +* Write the given ReDistributor SGI PPI Interface register +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param RegOffset is the register offset to be written +* @param Data is the 32-bit value to write to the register +* +* @return None. +* +* @note +* C-style signature: +* void XScuGic_DistWriteReg(XScuGic *InstancePtr, u32 RegOffset, u32 Data) +* +*****************************************************************************/ +#define XScuGic_ReDistSGIPPIWriteReg(InstancePtr, RegOffset, Data) \ +(XScuGic_WriteReg(((InstancePtr)->Config->DistBaseAddress)+ \ + XSCUGIC_RDIST_SGI_PPI_OFFSET, (RegOffset), ((u32)(Data)))) + +/****************************************************************************/ +/** +* +* Read the given ReDistributor SGI PPI Interface register +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param RegOffset is the register offset to be read +* +* @return The 32-bit value of the register +* +* @note +* C-style signature: +* u32 XScuGic_DistReadReg(XScuGic *InstancePtr, u32 RegOffset) +* +*****************************************************************************/ +#define XScuGic_ReDistSGIPPIReadReg(InstancePtr, RegOffset) \ +(XScuGic_ReadReg((((InstancePtr)->Config->DistBaseAddress)+ \ + XSCUGIC_RDIST_SGI_PPI_OFFSET), (RegOffset))) + +/****************************************************************************/ +/** +* This function enables system register interface for GIC CPU Interface +* +* @param value to be written +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +#define XScuGic_Enable_SystemReg_CPU_Interface_EL3() mtcp(S3_6_C12_C12_5, 0xF); +#define XScuGic_Enable_SystemReg_CPU_Interface_EL1() mtcp(S3_0_C12_C12_5, 0xF); +/****************************************************************************/ +/** +* This function enables Grou0 interrupts +* +* @param None. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +#define XScuGic_Enable_Group0_Interrupts() mtcp(S3_0_C12_C12_6,0x1); +/****************************************************************************/ +/** +* This function enables Group1 interrupts +* +* @param None. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +#if defined (__aarch64__) +#if EL1_NONSECURE +#define XScuGic_Enable_Group1_Interrupts() \ + mtcp (S3_0_C12_C12_7, 0x1 | mfcp(S3_0_C12_C12_7) ); +#else +#define XScuGic_Enable_Group1_Interrupts() \ + mtcp (S3_6_C12_C12_7, 0x1 | mfcp(S3_6_C12_C12_7) ); +#endif +#endif +/****************************************************************************/ +/** +* This function writes to ICC_SGI0R_EL1 +* +* @param value to be written +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +#define XScuGic_WriteICC_SGI0R_EL1(val) mtcp(S3_0_C12_C11_7,val) + +/****************************************************************************/ +/** +* This function writes to ICC_SGI1R_EL1 +* +* @param value to be written +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +#define XScuGic_WriteICC_SGI1R_EL1(val) mtcp(S3_0_C12_C11_5,val) + +/****************************************************************************/ +/** +* This function reads ICC_SGI1R_EL1 register +* +* @param None +* +* @return Value of ICC_SGI1R_EL1 register +* +* @note None. +* +*****************************************************************************/ +#define XScuGic_ReadICC_SGI1R_EL1() mfcp(S3_0_C12_C11_5) +/****************************************************************************/ +/** +* This function sets interrupt priority filter +* +* @param None. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +#define XScuGic_set_priority_filter(val) __asm__ __volatile__("msr S3_0_C4_C6_0,%0" : : "r" (val)) +/****************************************************************************/ +/** +* This function returns interrupt id of highest priority pending interrupt +* +* @param None. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +#if defined (__aarch64__) +#if EL3 +#define XScuGic_get_IntID() mfcp(S3_0_C12_C8_0) +#else +#define XScuGic_get_IntID() mfcp(S3_0_C12_C12_0) +#endif +#endif +/****************************************************************************/ +/** +* This function acks the interrupt +* +* @param None. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +#if defined (__aarch64__) +#if EL3 +#define XScuGic_ack_Int(val) mtcp(S3_0_C12_C8_1,val) +#else +#define XScuGic_ack_Int(val) mtcp(S3_0_C12_C12_1,val) +#endif +#endif +/****************************************************************************/ +/** +* This macro returns bit position for the specific interrupt's trigger type +* configuration within GICR_ICFGR0/GICR_ICFGR1 register +* +* @param None. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +#define XScuGic_Get_Rdist_Int_Trigger_Index(IntrId) (((Int_Id%16) & 0x1f) << 2) +1 +/************************** Function Prototypes ******************************/ + +/* + * Required functions in xscugic.c + */ + +s32 XScuGic_Connect(XScuGic *InstancePtr, u32 Int_Id, + Xil_InterruptHandler Handler, void *CallBackRef); +void XScuGic_Disconnect(XScuGic *InstancePtr, u32 Int_Id); + +void XScuGic_Enable(XScuGic *InstancePtr, u32 Int_Id); +void XScuGic_Disable(XScuGic *InstancePtr, u32 Int_Id); + +s32 XScuGic_CfgInitialize(XScuGic *InstancePtr, XScuGic_Config *ConfigPtr, + u32 EffectiveAddr); + +s32 XScuGic_SoftwareIntr(XScuGic *InstancePtr, u32 Int_Id, u32 Cpu_Id); + +void XScuGic_GetPriorityTriggerType(XScuGic *InstancePtr, u32 Int_Id, + u8 *Priority, u8 *Trigger); +void XScuGic_SetPriorityTriggerType(XScuGic *InstancePtr, u32 Int_Id, + u8 Priority, u8 Trigger); +void XScuGic_InterruptMaptoCpu(XScuGic *InstancePtr, u8 Cpu_Id, u32 Int_Id); +void XScuGic_InterruptUnmapFromCpu(XScuGic *InstancePtr, u8 Cpu_Id, u32 Int_Id); +void XScuGic_UnmapAllInterruptsFromCpu(XScuGic *InstancePtr, u8 Cpu_Id); +void XScuGic_Stop(XScuGic *InstancePtr); +void XScuGic_SetCpuID(u32 CpuCoreId); +u32 XScuGic_GetCpuID(void); +/* + * Initialization functions in xscugic_sinit.c + */ +XScuGic_Config *XScuGic_LookupConfig(u16 DeviceId); + +/* + * Interrupt functions in xscugic_intr.c + */ +void XScuGic_InterruptHandler(XScuGic *InstancePtr); + +/* + * Self-test functions in xscugic_selftest.c + */ +s32 XScuGic_SelfTest(XScuGic *InstancePtr); + +void XScuGic_EnableSGI_PPI(XScuGic *InstancePtr,u32 ID); +void XScuGic_SetPPI_SGI_Priority(XScuGic *InstancePtr,u32 ID, u32 priority); +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/scugic_v4_0/src/xscugic_g.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/scugic_v4_0/src/xscugic_g.c new file mode 100644 index 0000000..397d26d --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/scugic_v4_0/src/xscugic_g.c @@ -0,0 +1,53 @@ + +/******************************************************************* +* +* CAUTION: This file is automatically generated by HSI. +* Version: 2019.1.3 +* DO NOT EDIT. +* +* Copyright (C) 2010-2023 Xilinx, Inc. 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 +*XILINX 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. +* +*Except as contained in this notice, the name of the Xilinx shall not be used +*in advertising or otherwise to promote the sale, use or other dealings in +*this Software without prior written authorization from Xilinx. +* + +* +* Description: Driver configuration +* +*******************************************************************/ + +#include "xparameters.h" +#include "xscugic.h" + +/* +* The configuration table for devices +*/ + +XScuGic_Config XScuGic_ConfigTable[XPAR_XSCUGIC_NUM_INSTANCES] = +{ + { + XPAR_PS7_SCUGIC_0_DEVICE_ID, + XPAR_PS7_SCUGIC_0_BASEADDR, + XPAR_PS7_SCUGIC_0_DIST_BASEADDR, + {{0}} /**< Initialize the HandlerTable to 0 */ + } +}; + + diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/scugic_v4_0/src/xscugic_hw.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/scugic_v4_0/src/xscugic_hw.c new file mode 100644 index 0000000..4193e80 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/scugic_v4_0/src/xscugic_hw.c @@ -0,0 +1,652 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xscugic_hw.c +* @addtogroup scugic_v4_0 +* @{ +* +* This file contains low-level driver functions that can be used to access the +* device. The user should refer to the hardware device specification for more +* details of the device operation. +* These routines are used when the user does not want to create an instance of +* XScuGic structure but still wants to use the ScuGic device. Hence the +* routines provided here take device id or scugic base address as arguments. +* Separate static versions of DistInit and CPUInit are provided to implement +* the low level driver routines. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.01a sdm  07/18/11 First release
+* 1.03a srt  02/27/13 Moved Offset calculation macros from *_hw.c (CR
+*                     702687).
+*                     Added support to direct interrupts to the appropriate
+*                     CPU. Earlier interrupts were directed to CPU1
+*                     (hard coded). Now depending upon the CPU selected by
+*                     the user (xparameters.h), interrupts will be directed
+*                     to the relevant CPU.This fixes CR 699688.
+* 1.04a hk   05/04/13 Fix for CR#705621. Moved functions
+*                     XScuGic_SetPriTrigTypeByDistAddr and
+*                     XScuGic_GetPriTrigTypeByDistAddr here from xscugic.c
+* 3.00  kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.6   kvn  02/17/17 Add support for changing GIC CPU master at run time.
+*       kvn  02/28/17 Make the CpuId as static variable and Added new
+*                     XScugiC_GetCpuId to access CpuId.
+* 3.9   mus  02/21/18 Added new API's
+*                     XScuGic_InterruptUnmapFromCpuByDistAddr and
+*                     XScuGic_UnmapAllInterruptsFromCpuByDistAddr, These
+*                     API's can be used by applications to unmap
+*                     specific/all interrupts from target CPU. It fixes
+*                     CR#992490.
+* 3.10  mus  07/17/18 Updated XScuGic_DeviceInterruptHandler to fix array
+*                     overrun reported by coverity tool. It fixes
+*                     CR#1006344.
+* 3.10  mus  07/17/18 Updated file to fix the various coding style issues
+*                     reported by checkpatch. It fixes CR#1006344.
+* 3.10  aru  08/23/18 Resolved MISRA-C:2012 compliance mandatory violations
+*                     It fixes CR#1007753
+* 3.10  mus  09/19/18 Update documentation for XScuGic_RegisterHandler to
+*                     fix doxygen warnings.
+* 
+* +******************************************************************************/ + + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xscugic.h" +#include "xparameters.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +static void DistInit(XScuGic_Config *Config, u32 CpuID); +static void CPUInit(XScuGic_Config *Config); +static XScuGic_Config *LookupConfigByBaseAddress(u32 CpuBaseAddress); + +/************************** Variable Definitions *****************************/ + +extern XScuGic_Config XScuGic_ConfigTable[XPAR_XSCUGIC_NUM_INSTANCES]; +extern u32 CpuId; + +/*****************************************************************************/ +/** +* +* DistInit initializes the distributor of the GIC. The +* initialization entails: +* +* - Write the trigger mode, priority and target CPU +* - All interrupt sources are disabled +* - Enable the distributor +* +* @param InstancePtr is a pointer to the XScuGic instance. +* @param CpuID is the Cpu ID to be initialized. +* +* @return None +* +* @note None. +* +******************************************************************************/ +static void DistInit(XScuGic_Config *Config, u32 CpuID) +{ + u32 Int_Id; + u32 LocalCpuID = CpuID; + +#if USE_AMP == 1 + #warning "Building GIC for AMP" + + /* + * The distrubutor should not be initialized by FreeRTOS in the case of + * AMP -- it is assumed that Linux is the master of this device in that + * case. + */ + return; +#endif + + XScuGic_WriteReg(Config->DistBaseAddress, XSCUGIC_DIST_EN_OFFSET, 0U); + + /* + * Set the security domains in the int_security registers for non-secure + * interrupts. All are secure, so leave at the default. Set to 1 for + * non-secure interrupts. + */ + + + /* + * For the Shared Peripheral Interrupts INT_ID[MAX..32], set: + */ + + /* + * 1. The trigger mode in the int_config register + * Only write to the SPI interrupts, so start at 32 + */ + for (Int_Id = 32U; Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS; + Int_Id = Int_Id+16U) { + /* + * Each INT_ID uses two bits, or 16 INT_ID per register + * Set them all to be level sensitive, active HIGH. + */ + XScuGic_WriteReg(Config->DistBaseAddress, + XSCUGIC_INT_CFG_OFFSET_CALC(Int_Id), 0U); + } + + +#define DEFAULT_PRIORITY 0xa0a0a0a0U + for (Int_Id = 0U; Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS; + Int_Id = Int_Id+4U) { + /* + * 2. The priority using int the priority_level register + * The priority_level and spi_target registers use one byte per + * INT_ID. + * Write a default value that can be changed elsewhere. + */ + XScuGic_WriteReg(Config->DistBaseAddress, + XSCUGIC_PRIORITY_OFFSET_CALC(Int_Id), + DEFAULT_PRIORITY); + } + + for (Int_Id = 32U; Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS; + Int_Id = Int_Id+4U) { + /* + * 3. The CPU interface in the spi_target register + * Only write to the SPI interrupts, so start at 32 + */ + LocalCpuID |= LocalCpuID << 8U; + LocalCpuID |= LocalCpuID << 16U; + + XScuGic_WriteReg(Config->DistBaseAddress, + XSCUGIC_SPI_TARGET_OFFSET_CALC(Int_Id), LocalCpuID); + } + + for (Int_Id = 0U; Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS; + Int_Id = Int_Id+32U) { + /* + * 4. Enable the SPI using the enable_set register. + * Leave all disabled for now. + */ + XScuGic_WriteReg(Config->DistBaseAddress, + XSCUGIC_EN_DIS_OFFSET_CALC(XSCUGIC_DISABLE_OFFSET, + Int_Id), + 0xFFFFFFFFU); + + } + + XScuGic_WriteReg(Config->DistBaseAddress, XSCUGIC_DIST_EN_OFFSET, + XSCUGIC_EN_INT_MASK); + +} + +/*****************************************************************************/ +/** +* +* CPUInit initializes the CPU Interface of the GIC. The initialization entails: +* +* - Set the priority of the CPU. +* - Enable the CPU interface +* +* @param ConfigPtr is a pointer to a config table for the particular +* device this driver is associated with. +* +* @return None +* +* @note None. +* +******************************************************************************/ +static void CPUInit(XScuGic_Config *Config) +{ + /* + * Program the priority mask of the CPU using the Priority mask + * register + */ + XScuGic_WriteReg(Config->CpuBaseAddress, XSCUGIC_CPU_PRIOR_OFFSET, + 0xF0U); + + /* + * If the CPU operates in both security domains, set parameters in the + * control_s register. + * 1. Set FIQen=1 to use FIQ for secure interrupts, + * 2. Program the AckCtl bit + * 3. Program the SBPR bit to select the binary pointer behavior + * 4. Set EnableS = 1 to enable secure interrupts + * 5. Set EnbleNS = 1 to enable non secure interrupts + */ + + /* + * If the CPU operates only in the secure domain, setup the + * control_s register. + * 1. Set FIQen=1, + * 2. Set EnableS=1, to enable the CPU interface to signal secure . + * interrupts Only enable the IRQ output unless secure interrupts + * are needed. + */ + XScuGic_WriteReg(Config->CpuBaseAddress, XSCUGIC_CONTROL_OFFSET, 0x07U); + +} + +/*****************************************************************************/ +/** +* +* Initialize the GIC based on the device id. The +* initialization entails: +* +* - Initialize distributor interface +* - Initialize cpu interface +* +* @param DeviceId is device id to be worked on. +* +* @return +* +* - XST_SUCCESS if initialization was successful +* +* @note +* +* None. +* +******************************************************************************/ +s32 XScuGic_DeviceInitialize(u32 DeviceId) +{ + XScuGic_Config *Config; + u32 Cpu_Id = XScuGic_GetCpuID() + (u32)1; + + Config = &XScuGic_ConfigTable[(u32)DeviceId]; + + DistInit(Config, Cpu_Id); + + CPUInit(Config); + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* This function is the primary interrupt handler for the driver. It must be +* connected to the interrupt source such that it is called when an interrupt of +* the interrupt controller is active. It will resolve which interrupts are +* active and enabled and call the appropriate interrupt handler. It uses +* the Interrupt Type information to determine when to acknowledge the +* interrupt.Highest priority interrupts are serviced first. +* +* This function assumes that an interrupt vector table has been previously +* initialized. It does not verify that entries in the table are valid before +* calling an interrupt handler. +* +* @param DeviceId is the unique identifier for the ScuGic device. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XScuGic_DeviceInterruptHandler(void *DeviceId) +{ + + u32 InterruptID; + u32 IntIDFull; + XScuGic_VectorTableEntry *TablePtr; + XScuGic_Config *CfgPtr; + + CfgPtr = &XScuGic_ConfigTable[(INTPTR)DeviceId]; + + /* + * Read the int_ack register to identify the highest priority + * interrupt ID and make sure it is valid. Reading Int_Ack will + * clear the interrupt in the GIC. + */ + IntIDFull = XScuGic_ReadReg(CfgPtr->CpuBaseAddress, + XSCUGIC_INT_ACK_OFFSET); + InterruptID = IntIDFull & XSCUGIC_ACK_INTID_MASK; + if (XSCUGIC_MAX_NUM_INTR_INPUTS <= InterruptID) { + goto IntrExit; + } + + /* + * If the interrupt is shared, do some locking here if there are + * multiple processors. + */ + /* + * If pre-eption is required: + * Re-enable pre-emption by setting the CPSR I bit for non-secure , + * interrupts or the F bit for secure interrupts + */ + + /* + * If we need to change security domains, issue a SMC instruction here. + */ + + /* + * Execute the ISR. Jump into the Interrupt service routine based on + * the IRQSource. A software trigger is cleared by the ACK. + */ + TablePtr = &(CfgPtr->HandlerTable[InterruptID]); + if (TablePtr != NULL) { + TablePtr->Handler(TablePtr->CallBackRef); + } + +IntrExit: + /* + * Write to the EOI register, we are all done here. + * Let this function return, the boot code will restore the stack. + */ + XScuGic_WriteReg(CfgPtr->CpuBaseAddress, XSCUGIC_EOI_OFFSET, IntIDFull); + + /* + * Return from the interrupt. Change security domains could happen + * here. + */ +} + +/*****************************************************************************/ +/** +* +* Register a handler function for a specific interrupt ID. The vector table +* of the interrupt controller is updated, overwriting any previous handler. +* The handler function will be called when an interrupt occurs for the given +* interrupt ID. +* +* @param BaseAddress is the CPU Interface Register base address of the +* interrupt controller whose vector table will be modified. +* @param InterruptID is the interrupt ID to be associated with the input +* handler. +* @param IntrHandler is the function pointer that will be added to +* the vector table for the given interrupt ID. +* @param CallBackRef is the argument that will be passed to the new +* handler function when it is called. This is user-specific. +* +* @return None. +* +* @note +* +* Note that this function has no effect if the input base address is invalid. +* +******************************************************************************/ +void XScuGic_RegisterHandler(u32 BaseAddress, s32 InterruptID, + Xil_InterruptHandler IntrHandler, void *CallBackRef) +{ + XScuGic_Config *CfgPtr; + CfgPtr = LookupConfigByBaseAddress(BaseAddress); + + if (CfgPtr != NULL) { + if (IntrHandler != NULL) { + CfgPtr->HandlerTable[InterruptID].Handler = + (Xil_InterruptHandler)IntrHandler; + } + if (CallBackRef != NULL) { + CfgPtr->HandlerTable[InterruptID].CallBackRef = + CallBackRef; + } + } +} + +/*****************************************************************************/ +/** +* +* Looks up the device configuration based on the CPU interface base address of +* the device. A table contains the configuration info for each device in the +* system. +* +* @param CpuBaseAddress is the CPU Interface Register base address. +* +* @return A pointer to the configuration structure for the specified +* device, or NULL if the device was not found. +* +* @note None. +* +******************************************************************************/ +static XScuGic_Config *LookupConfigByBaseAddress(u32 CpuBaseAddress) +{ + XScuGic_Config *CfgPtr = NULL; + u32 Index; + + for (Index = 0U; Index < XPAR_SCUGIC_NUM_INSTANCES; Index++) { + if (XScuGic_ConfigTable[Index].CpuBaseAddress == + CpuBaseAddress) { + CfgPtr = &XScuGic_ConfigTable[Index]; + break; + } + } + + return (XScuGic_Config *)CfgPtr; +} + +/****************************************************************************/ +/** +* Sets the interrupt priority and trigger type for the specificd IRQ source. +* +* @param DistBaseAddress is the distributor base address +* @param Int_Id is the IRQ source number to modify +* @param Priority is the new priority for the IRQ source. 0 is highest +* priority, 0xF8(248) is lowest. There are 32 priority +* levels supported with a step of 8. Hence the supported +* priorities are 0, 8, 16, 32, 40 ..., 248. +* @param Trigger is the new trigger type for the IRQ source. +* Each bit pair describes the configuration for an INT_ID. +* SFI Read Only b10 always +* PPI Read Only depending on how the PPIs are configured. +* b01 Active HIGH level sensitive +* b11 Rising edge sensitive +* SPI LSB is read only. +* b01 Active HIGH level sensitive +* b11 Rising edge sensitive/ +* +* @return None. +* +* @note This API has the similar functionality of XScuGic_SetPriority +* TriggerType() and should be used when there is no InstancePtr. +* +*****************************************************************************/ +void XScuGic_SetPriTrigTypeByDistAddr(u32 DistBaseAddress, u32 Int_Id, + u8 Priority, u8 Trigger) +{ + u32 RegValue; + u8 LocalPriority = Priority; + + Xil_AssertVoid(Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS); + Xil_AssertVoid(Trigger <= XSCUGIC_INT_CFG_MASK); + Xil_AssertVoid(LocalPriority <= XSCUGIC_MAX_INTR_PRIO_VAL); + + /* + * Determine the register to write to using the Int_Id. + */ + RegValue = XScuGic_ReadReg(DistBaseAddress, + XSCUGIC_PRIORITY_OFFSET_CALC(Int_Id)); + + /* + * The priority bits are Bits 7 to 3 in GIC Priority Register. This + * means the number of priority levels supported are 32 and they are + * in steps of 8. The priorities can be 0, 8, 16, 32, 48, ... etc. + * The lower order 3 bits are masked before putting it in the register. + */ + LocalPriority = LocalPriority & XSCUGIC_INTR_PRIO_MASK; + /* + * Shift and Mask the correct bits for the priority and trigger in the + * register + */ + RegValue &= ~(XSCUGIC_PRIORITY_MASK << ((Int_Id%4U)*8U)); + RegValue |= (u32)LocalPriority << ((Int_Id%4U)*8U); + + /* + * Write the value back to the register. + */ + XScuGic_WriteReg(DistBaseAddress, XSCUGIC_PRIORITY_OFFSET_CALC(Int_Id), + RegValue); + /* + * Determine the register to write to using the Int_Id. + */ + RegValue = XScuGic_ReadReg(DistBaseAddress, + XSCUGIC_INT_CFG_OFFSET_CALC(Int_Id)); + + /* + * Shift and Mask the correct bits for the priority and trigger in the + * register + */ + RegValue &= ~(XSCUGIC_INT_CFG_MASK << ((Int_Id%16U)*2U)); + RegValue |= (u32)Trigger << ((Int_Id%16U)*2U); + + /* + * Write the value back to the register. + */ + XScuGic_WriteReg(DistBaseAddress, XSCUGIC_INT_CFG_OFFSET_CALC(Int_Id), + RegValue); +} + +/****************************************************************************/ +/** +* Gets the interrupt priority and trigger type for the specificd IRQ source. +* +* @param DistBaseAddress is the distributor base address +* @param Int_Id is the IRQ source number to modify +* @param Priority is a pointer to the value of the priority of the IRQ +* source. This is a return value. +* @param Trigger is pointer to the value of the trigger of the IRQ +* source. This is a return value. +* +* @return None. +* +* @note This API has the similar functionality of XScuGic_GetPriority +* TriggerType() and should be used when there is no InstancePtr. +* +*****************************************************************************/ +void XScuGic_GetPriTrigTypeByDistAddr(u32 DistBaseAddress, u32 Int_Id, + u8 *Priority, u8 *Trigger) +{ + u32 RegValue; + + Xil_AssertVoid(Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS); + Xil_AssertVoid(Priority != NULL); + Xil_AssertVoid(Trigger != NULL); + + /* + * Determine the register to read to using the Int_Id. + */ + RegValue = XScuGic_ReadReg(DistBaseAddress, + XSCUGIC_PRIORITY_OFFSET_CALC(Int_Id)); + + /* + * Shift and Mask the correct bits for the priority and trigger in the + * register + */ + RegValue = RegValue >> ((Int_Id%4U)*8U); + *Priority = (u8)(RegValue & XSCUGIC_PRIORITY_MASK); + + /* + * Determine the register to read to using the Int_Id. + */ + RegValue = XScuGic_ReadReg(DistBaseAddress, + XSCUGIC_INT_CFG_OFFSET_CALC(Int_Id)); + + /* + * Shift and Mask the correct bits for the priority and trigger in the + * register + */ + RegValue = RegValue >> ((Int_Id%16U)*2U); + + *Trigger = (u8)(RegValue & XSCUGIC_INT_CFG_MASK); +} + +/****************************************************************************/ +/** +* Unmaps specific SPI interrupt from the target CPU +* +* @param DistBaseAddress is the device base address +* @param Cpu_Id is a CPU number from which the interrupt has to be +* unmapped +* @param Int_Id is the IRQ source number to modify +* +* @return None. +* +* @note None +* +*****************************************************************************/ +void XScuGic_InterruptUnmapFromCpuByDistAddr(u32 DistBaseAddress, + u8 Cpu_Id, u32 Int_Id) +{ + u32 RegValue; + u8 BitPos; + + Xil_AssertVoid(Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS); + + RegValue = XScuGic_ReadReg(DistBaseAddress, + XSCUGIC_SPI_TARGET_OFFSET_CALC(Int_Id)); + + /* + * Identify bit position corresponding to Int_Id and Cpu_Id, + * in interrupt target register and clear it + */ + BitPos = ((Int_Id % 4U) * 8U) + Cpu_Id; + RegValue &= (~(1U << BitPos)); + XScuGic_WriteReg(DistBaseAddress, + XSCUGIC_SPI_TARGET_OFFSET_CALC(Int_Id), RegValue); +} + +/****************************************************************************/ +/** +* Unmaps all SPI interrupts from the target CPU +* +* @param DistBaseAddress is the device base address +* @param Cpu_Id is a CPU number from which the interrupts has to be +* unmapped +* +* @return None. +* +* @note None +* +*****************************************************************************/ +void XScuGic_UnmapAllInterruptsFromCpuByDistAddr(u32 DistBaseAddress, + u8 Cpu_Id) +{ + u32 Int_Id; + u32 Target_Cpu; + u32 LocalCpuID = (1U << Cpu_Id); + + LocalCpuID |= LocalCpuID << 8U; + LocalCpuID |= LocalCpuID << 16U; + + for (Int_Id = 32U; Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS; + Int_Id = Int_Id+4U) { + + Target_Cpu = XScuGic_ReadReg(DistBaseAddress, + XSCUGIC_SPI_TARGET_OFFSET_CALC(Int_Id)); + /* Remove LocalCpuID from interrupt target register */ + Target_Cpu &= (~LocalCpuID); + XScuGic_WriteReg(DistBaseAddress, + XSCUGIC_SPI_TARGET_OFFSET_CALC(Int_Id), Target_Cpu); + + } +} +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/scugic_v4_0/src/xscugic_hw.h b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/scugic_v4_0/src/xscugic_hw.h new file mode 100644 index 0000000..60d111f --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/scugic_v4_0/src/xscugic_hw.h @@ -0,0 +1,753 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xscugic_hw.h +* @addtogroup scugic_v4_0 +* @{ +* +* This header file contains identifiers and HW access functions (or +* macros) that can be used to access the device. The user should refer to the +* hardware device specification for more details of the device operation. +* The driver functions/APIs are defined in xscugic.h. +* +* This GIC device has two parts, a distributor and CPU interface(s). Each part +* has separate register definition sections. +* +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------------
+* 1.00a drg  01/19/10 First release
+* 1.01a sdm  11/09/11 "xil_exception.h" added as include.
+*		      Macros XScuGic_EnableIntr and XScuGic_DisableIntr are
+*		      added to enable or disable interrupts based on
+*		      Distributor Register base address. Normally users use
+*		      XScuGic instance and call XScuGic_Enable or
+*		      XScuGic_Disable to enable/disable interrupts. These
+*		      new macros are provided when user does not want to
+*		      use an instance pointer but still wants to enable or
+*		      disable interrupts.
+*		      Function prototypes for functions (present in newly
+*		      added file xscugic_hw.c) are added.
+* 1.03a srt  02/27/13 Moved Offset calculation macros from *_hw.c (CR
+*		      702687).
+* 1.04a hk   05/04/13 Fix for CR#705621. Moved function prototypes
+*		      XScuGic_SetPriTrigTypeByDistAddr and
+*         	      XScuGic_GetPriTrigTypeByDistAddr here from xscugic.h
+* 3.0	pkp  12/09/14 changed XSCUGIC_MAX_NUM_INTR_INPUTS for
+*		      Zynq Ultrascale Mp
+* 3.0   kvn  02/13/14 Modified code for MISRA-C:2012 compliance.
+* 3.2	pkp  11/09/15 Corrected the interrupt processsor target mask value
+*					  for CPU interface 2 i.e. XSCUGIC_SPI_CPU2_MASK
+* 3.9   mus  02/21/18 Added new API's XScuGic_InterruptUnmapFromCpuByDistAddr
+*					  and XScuGic_UnmapAllInterruptsFromCpuByDistAddr, These
+*					  API's can be used by applications to unmap specific/all
+*					  interrupts from target CPU. It fixes CR#992490.
+* 3.10  aru  08/23/18 Resolved MISRA-C:2012 compliance mandatory violations
+*
+* 
+* +******************************************************************************/ + +#ifndef XSCUGIC_HW_H /* prevent circular inclusions */ +#define XSCUGIC_HW_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_io.h" +#include "xil_exception.h" +#include "bspconfig.h" + +/************************** Constant Definitions *****************************/ + +/* + * The maximum number of interrupts supported by the hardware. + */ +#ifdef PLATFORM_ZYNQ +#define XSCUGIC_MAX_NUM_INTR_INPUTS 95U /* Maximum number of interrupt defined by Zynq */ +#elif defined (versal) && !defined(ARMR5) +#define XSCUGIC_MAX_NUM_INTR_INPUTS 191U +#else +#define XSCUGIC_MAX_NUM_INTR_INPUTS 195U /* Maximum number of interrupt defined by Zynq Ultrascale Mp */ +#endif + +/* + * First Interrupt Id for SPI interrupts. + */ +#define XSCUGIC_SPI_INT_ID_START 0x20 +/* + * The maximum priority value that can be used in the GIC. + */ +#define XSCUGIC_MAX_INTR_PRIO_VAL 248U +#define XSCUGIC_INTR_PRIO_MASK 0x000000F8U + +/** @name Distributor Interface Register Map + * + * Define the offsets from the base address for all Distributor registers of + * the interrupt controller, some registers may be reserved in the hardware + * device. + * @{ + */ +#define XSCUGIC_DIST_EN_OFFSET 0x00000000U /**< Distributor Enable + Register */ +#define XSCUGIC_IC_TYPE_OFFSET 0x00000004U /**< Interrupt Controller + Type Register */ +#define XSCUGIC_DIST_IDENT_OFFSET 0x00000008U /**< Implementor ID + Register */ +#define XSCUGIC_SECURITY_OFFSET 0x00000080U /**< Interrupt Security + Register */ +#define XSCUGIC_ENABLE_SET_OFFSET 0x00000100U /**< Enable Set + Register */ +#define XSCUGIC_DISABLE_OFFSET 0x00000180U /**< Enable Clear Register */ +#define XSCUGIC_PENDING_SET_OFFSET 0x00000200U /**< Pending Set + Register */ +#define XSCUGIC_PENDING_CLR_OFFSET 0x00000280U /**< Pending Clear + Register */ +#define XSCUGIC_ACTIVE_OFFSET 0x00000300U /**< Active Status Register */ +#define XSCUGIC_PRIORITY_OFFSET 0x00000400U /**< Priority Level Register */ +#define XSCUGIC_SPI_TARGET_OFFSET 0x00000800U /**< SPI Target + Register 0x800-0x8FB */ +#define XSCUGIC_INT_CFG_OFFSET 0x00000C00U /**< Interrupt Configuration + Register 0xC00-0xCFC */ +#define XSCUGIC_PPI_STAT_OFFSET 0x00000D00U /**< PPI Status Register */ +#define XSCUGIC_SPI_STAT_OFFSET 0x00000D04U /**< SPI Status Register + 0xd04-0xd7C */ +#define XSCUGIC_AHB_CONFIG_OFFSET 0x00000D80U /**< AHB Configuration + Register */ +#define XSCUGIC_SFI_TRIG_OFFSET 0x00000F00U /**< Software Triggered + Interrupt Register */ +#define XSCUGIC_PERPHID_OFFSET 0x00000FD0U /**< Peripheral ID Reg */ +#if defined (versal) && !defined(ARMR5) +#define XSCUGIC_PCELLID_OFFSET 0x0000FFF0U /**< Pcell ID Register */ +#else +#define XSCUGIC_PCELLID_OFFSET 0x00000FF0U /**< Pcell ID Register */ +#endif +/* @} */ + +/** @name Distributor Enable Register + * Controls if the distributor response to external interrupt inputs. + * @{ + */ +#if defined (versal) && !defined(ARMR5) +#define XSCUGIC_EN_INT_MASK 0x00000003U /**< Interrupt In Enable */ +#else +#define XSCUGIC_EN_INT_MASK 0x00000001U /**< Interrupt In Enable */ +#endif +/* @} */ + +/** @name Interrupt Controller Type Register + * @{ + */ +#define XSCUGIC_LSPI_MASK 0x0000F800U /**< Number of Lockable + Shared Peripheral + Interrupts*/ +#define XSCUGIC_DOMAIN_MASK 0x00000400U /**< Number os Security domains*/ +#define XSCUGIC_CPU_NUM_MASK 0x000000E0U /**< Number of CPU Interfaces */ +#define XSCUGIC_NUM_INT_MASK 0x0000001FU /**< Number of Interrupt IDs */ +/* @} */ + +/** @name Implementor ID Register + * Implementor and revision information. + * @{ + */ +#define XSCUGIC_REV_MASK 0x00FFF000U /**< Revision Number */ +#define XSCUGIC_IMPL_MASK 0x00000FFFU /**< Implementor */ +/* @} */ + +/** @name Interrupt Security Registers + * Each bit controls the security level of an interrupt, either secure or non + * secure. These registers can only be accessed using secure read and write. + * There are registers for each of the CPU interfaces at offset 0x080. A + * register set for the SPI interrupts is available to all CPU interfaces. + * There are up to 32 of these registers staring at location 0x084. + * @{ + */ +#define XSCUGIC_INT_NS_MASK 0x00000001U /**< Each bit corresponds to an + INT_ID */ +/* @} */ + +/** @name Enable Set Register + * Each bit controls the enabling of an interrupt, a 0 is disabled, a 1 is + * enabled. Writing a 0 has no effect. Use the ENABLE_CLR register to set a + * bit to 0. + * There are registers for each of the CPU interfaces at offset 0x100. With up + * to 8 registers aliased to the same address. A register set for the SPI + * interrupts is available to all CPU interfaces. + * There are up to 32 of these registers staring at location 0x104. + * @{ + */ +#define XSCUGIC_INT_EN_MASK 0x00000001U /**< Each bit corresponds to an + INT_ID */ +/* @} */ + +/** @name Enable Clear Register + * Each bit controls the disabling of an interrupt, a 0 is disabled, a 1 is + * enabled. Writing a 0 has no effect. Writing a 1 disables an interrupt and + * sets the corresponding bit to 0. + * There are registers for each of the CPU interfaces at offset 0x180. With up + * to 8 registers aliased to the same address. + * A register set for the SPI interrupts is available to all CPU interfaces. + * There are up to 32 of these registers staring at location 0x184. + * @{ + */ +#define XSCUGIC_INT_CLR_MASK 0x00000001U /**< Each bit corresponds to an + INT_ID */ +/* @} */ + +/** @name Pending Set Register + * Each bit controls the Pending or Active and Pending state of an interrupt, a + * 0 is not pending, a 1 is pending. Writing a 0 has no effect. Writing a 1 sets + * an interrupt to the pending state. + * There are registers for each of the CPU interfaces at offset 0x200. With up + * to 8 registers aliased to the same address. + * A register set for the SPI interrupts is available to all CPU interfaces. + * There are up to 32 of these registers staring at location 0x204. + * @{ + */ +#define XSCUGIC_PEND_SET_MASK 0x00000001U /**< Each bit corresponds to an + INT_ID */ +/* @} */ + +/** @name Pending Clear Register + * Each bit can clear the Pending or Active and Pending state of an interrupt, a + * 0 is not pending, a 1 is pending. Writing a 0 has no effect. Writing a 1 + * clears the pending state of an interrupt. + * There are registers for each of the CPU interfaces at offset 0x280. With up + * to 8 registers aliased to the same address. + * A register set for the SPI interrupts is available to all CPU interfaces. + * There are up to 32 of these registers staring at location 0x284. + * @{ + */ +#define XSCUGIC_PEND_CLR_MASK 0x00000001U /**< Each bit corresponds to an + INT_ID */ +/* @} */ + +/** @name Active Status Register + * Each bit provides the Active status of an interrupt, a + * 0 is not Active, a 1 is Active. This is a read only register. + * There are registers for each of the CPU interfaces at offset 0x300. With up + * to 8 registers aliased to each address. + * A register set for the SPI interrupts is available to all CPU interfaces. + * There are up to 32 of these registers staring at location 0x380. + * @{ + */ +#define XSCUGIC_ACTIVE_MASK 0x00000001U /**< Each bit corresponds to an + INT_ID */ +/* @} */ + +/** @name Priority Level Register + * Each byte in a Priority Level Register sets the priority level of an + * interrupt. Reading the register provides the priority level of an interrupt. + * There are registers for each of the CPU interfaces at offset 0x400 through + * 0x41C. With up to 8 registers aliased to each address. + * 0 is highest priority, 0xFF is lowest. + * A register set for the SPI interrupts is available to all CPU interfaces. + * There are up to 255 of these registers staring at location 0x420. + * @{ + */ +#define XSCUGIC_PRIORITY_MASK 0x000000FFU /**< Each Byte corresponds to an + INT_ID */ +#define XSCUGIC_PRIORITY_MAX 0x000000FFU /**< Highest value of a priority + actually the lowest priority*/ +/* @} */ + +/** @name SPI Target Register 0x800-0x8FB + * Each byte references a separate SPI and programs which of the up to 8 CPU + * interfaces are sent a Pending interrupt. + * There are registers for each of the CPU interfaces at offset 0x800 through + * 0x81C. With up to 8 registers aliased to each address. + * A register set for the SPI interrupts is available to all CPU interfaces. + * There are up to 255 of these registers staring at location 0x820. + * + * This driver does not support multiple CPU interfaces. These are included + * for complete documentation. + * @{ + */ +#define XSCUGIC_SPI_CPU7_MASK 0x00000080U /**< CPU 7 Mask*/ +#define XSCUGIC_SPI_CPU6_MASK 0x00000040U /**< CPU 6 Mask*/ +#define XSCUGIC_SPI_CPU5_MASK 0x00000020U /**< CPU 5 Mask*/ +#define XSCUGIC_SPI_CPU4_MASK 0x00000010U /**< CPU 4 Mask*/ +#define XSCUGIC_SPI_CPU3_MASK 0x00000008U /**< CPU 3 Mask*/ +#define XSCUGIC_SPI_CPU2_MASK 0x00000004U /**< CPU 2 Mask*/ +#define XSCUGIC_SPI_CPU1_MASK 0x00000002U /**< CPU 1 Mask*/ +#define XSCUGIC_SPI_CPU0_MASK 0x00000001U /**< CPU 0 Mask*/ +/* @} */ + +/** @name Interrupt Configuration Register 0xC00-0xCFC + * The interrupt configuration registers program an SFI to be active HIGH level + * sensitive or rising edge sensitive. + * Each bit pair describes the configuration for an INT_ID. + * SFI Read Only b10 always + * PPI Read Only depending on how the PPIs are configured. + * b01 Active HIGH level sensitive + * b11 Rising edge sensitive + * SPI LSB is read only. + * b01 Active HIGH level sensitive + * b11 Rising edge sensitive/ + * There are registers for each of the CPU interfaces at offset 0xC00 through + * 0xC04. With up to 8 registers aliased to each address. + * A register set for the SPI interrupts is available to all CPU interfaces. + * There are up to 255 of these registers staring at location 0xC08. + * @{ + */ +#define XSCUGIC_INT_CFG_MASK 0x00000003U /**< */ +/* @} */ + +/** @name PPI Status Register + * Enables an external AMBA master to access the status of the PPI inputs. + * A CPU can only read the status of its local PPI signals and cannot read the + * status for other CPUs. + * This register is aliased for each CPU interface. + * @{ + */ +#define XSCUGIC_PPI_C15_MASK 0x00008000U /**< PPI Status */ +#define XSCUGIC_PPI_C14_MASK 0x00004000U /**< PPI Status */ +#define XSCUGIC_PPI_C13_MASK 0x00002000U /**< PPI Status */ +#define XSCUGIC_PPI_C12_MASK 0x00001000U /**< PPI Status */ +#define XSCUGIC_PPI_C11_MASK 0x00000800U /**< PPI Status */ +#define XSCUGIC_PPI_C10_MASK 0x00000400U /**< PPI Status */ +#define XSCUGIC_PPI_C09_MASK 0x00000200U /**< PPI Status */ +#define XSCUGIC_PPI_C08_MASK 0x00000100U /**< PPI Status */ +#define XSCUGIC_PPI_C07_MASK 0x00000080U /**< PPI Status */ +#define XSCUGIC_PPI_C06_MASK 0x00000040U /**< PPI Status */ +#define XSCUGIC_PPI_C05_MASK 0x00000020U /**< PPI Status */ +#define XSCUGIC_PPI_C04_MASK 0x00000010U /**< PPI Status */ +#define XSCUGIC_PPI_C03_MASK 0x00000008U /**< PPI Status */ +#define XSCUGIC_PPI_C02_MASK 0x00000004U /**< PPI Status */ +#define XSCUGIC_PPI_C01_MASK 0x00000002U /**< PPI Status */ +#define XSCUGIC_PPI_C00_MASK 0x00000001U /**< PPI Status */ +/* @} */ + +/** @name SPI Status Register 0xd04-0xd7C + * Enables an external AMBA master to access the status of the SPI inputs. + * There are up to 63 registers if the maximum number of SPI inputs are + * configured. + * @{ + */ +#define XSCUGIC_SPI_N_MASK 0x00000001U /**< Each bit corresponds to an SPI + input */ +/* @} */ + +/** @name AHB Configuration Register + * Provides the status of the CFGBIGEND input signal and allows the endianess + * of the GIC to be set. + * @{ + */ +#define XSCUGIC_AHB_END_MASK 0x00000004U /**< 0-GIC uses little Endian, + 1-GIC uses Big Endian */ +#define XSCUGIC_AHB_ENDOVR_MASK 0x00000002U /**< 0-Uses CFGBIGEND control, + 1-use the AHB_END bit */ +#define XSCUGIC_AHB_TIE_OFF_MASK 0x00000001U /**< State of CFGBIGEND */ + +/* @} */ + +/** @name Software Triggered Interrupt Register + * Controls issueing of software interrupts. + * @{ + */ +#define XSCUGIC_SFI_SELFTRIG_MASK 0x02010000U +#define XSCUGIC_SFI_TRIG_TRGFILT_MASK 0x03000000U /**< Target List filter + b00-Use the target List + b01-All CPUs except requester + b10-To Requester + b11-reserved */ +#define XSCUGIC_SFI_TRIG_CPU_MASK 0x00FF0000U /**< CPU Target list */ +#define XSCUGIC_SFI_TRIG_SATT_MASK 0x00008000U /**< 0= Use a secure interrupt */ +#define XSCUGIC_SFI_TRIG_INTID_MASK 0x0000000FU /**< Set to the INTID + signaled to the CPU*/ +/* @} */ + +/** @name CPU Interface Register Map + * + * Define the offsets from the base address for all CPU registers of the + * interrupt controller, some registers may be reserved in the hardware device. + * @{ + */ +#define XSCUGIC_CONTROL_OFFSET 0x00000000U /**< CPU Interface Control + Register */ +#define XSCUGIC_CPU_PRIOR_OFFSET 0x00000004U /**< Priority Mask Reg */ +#define XSCUGIC_BIN_PT_OFFSET 0x00000008U /**< Binary Point Register */ +#define XSCUGIC_INT_ACK_OFFSET 0x0000000CU /**< Interrupt ACK Reg */ +#define XSCUGIC_EOI_OFFSET 0x00000010U /**< End of Interrupt Reg */ +#define XSCUGIC_RUN_PRIOR_OFFSET 0x00000014U /**< Running Priority Reg */ +#define XSCUGIC_HI_PEND_OFFSET 0x00000018U /**< Highest Pending Interrupt + Register */ +#define XSCUGIC_ALIAS_BIN_PT_OFFSET 0x0000001CU /**< Aliased non-Secure + Binary Point Register */ + +/**< 0x00000020 to 0x00000FBC are reserved and should not be read or written + * to. */ +/* @} */ + + +/** @name Control Register + * CPU Interface Control register definitions + * All bits are defined here although some are not available in the non-secure + * mode. + * @{ + */ +#define XSCUGIC_CNTR_SBPR_MASK 0x00000010U /**< Secure Binary Pointer, + 0=separate registers, + 1=both use bin_pt_s */ +#define XSCUGIC_CNTR_FIQEN_MASK 0x00000008U /**< Use nFIQ_C for secure + interrupts, + 0= use IRQ for both, + 1=Use FIQ for secure, IRQ for non*/ +#define XSCUGIC_CNTR_ACKCTL_MASK 0x00000004U /**< Ack control for secure or non secure */ +#define XSCUGIC_CNTR_EN_NS_MASK 0x00000002U /**< Non Secure enable */ +#define XSCUGIC_CNTR_EN_S_MASK 0x00000001U /**< Secure enable, 0=Disabled, 1=Enabled */ +/* @} */ + +/** @name Priority Mask Register + * Priority Mask register definitions + * The CPU interface does not send interrupt if the level of the interrupt is + * lower than the level of the register. + * @{ + */ +/*#define XSCUGIC_PRIORITY_MASK 0x000000FFU*/ /**< All interrupts */ +/* @} */ + +/** @name Binary Point Register + * Binary Point register definitions + * @{ + */ + +#define XSCUGIC_BIN_PT_MASK 0x00000007U /**< Binary point mask value + Value Secure Non-secure + b000 0xFE 0xFF + b001 0xFC 0xFE + b010 0xF8 0xFC + b011 0xF0 0xF8 + b100 0xE0 0xF0 + b101 0xC0 0xE0 + b110 0x80 0xC0 + b111 0x00 0x80 + */ +/*@}*/ + +/** @name Interrupt Acknowledge Register + * Interrupt Acknowledge register definitions + * Identifies the current Pending interrupt, and the CPU ID for software + * interrupts. + */ +#define XSCUGIC_ACK_INTID_MASK 0x000003FFU /**< Interrupt ID */ +#define XSCUGIC_CPUID_MASK 0x00000C00U /**< CPU ID */ +/* @} */ + +/** @name End of Interrupt Register + * End of Interrupt register definitions + * Allows the CPU to signal the GIC when it completes an interrupt service + * routine. + */ +#define XSCUGIC_EOI_INTID_MASK 0x000003FFU /**< Interrupt ID */ + +/* @} */ + +/** @name Running Priority Register + * Running Priority register definitions + * Identifies the interrupt priority level of the highest priority active + * interrupt. + */ +#define XSCUGIC_RUN_PRIORITY_MASK 0x000000FFU /**< Interrupt Priority */ +/* @} */ + +#if defined (versal) && !defined(ARMR5) +#define XSCUGIC_IROUTER_BASE_OFFSET 0x6000U +#endif +/* + * Highest Pending Interrupt register definitions + * Identifies the interrupt priority of the highest priority pending interupt + */ +#define XSCUGIC_PEND_INTID_MASK 0x000003FFU /**< Pending Interrupt ID */ +/*#define XSCUGIC_CPUID_MASK 0x00000C00U */ /**< CPU ID */ +/* @} */ +#if defined (versal) && !defined(ARMR5) +/** @name ReDistributor Interface Register Map + * + * @{ + */ +#define XSCUGIC_RDIST_OFFSET 0x80000U +#define XSCUGIC_RDIST_BASE_ADDRESS (XPAR_SCUGIC_0_DIST_BASEADDR + XSCUGIC_RDIST_OFFSET) +#define XSCUGIC_RDIST_SGI_PPI_OFFSET 0x90000U +#define XSCUGIC_RDIST_SGI_PPI_BASE_ADDRESS (XPAR_SCUGIC_0_DIST_BASEADDR + XSCUGIC_RDIST_SGI_PPI_OFFSET) +#define XSCUGIC_RDIST_ISENABLE_OFFSET 0x100U +#define XSCUGIC_RDIST_IPRIORITYR_OFFSET 0x400U +#define XSCUGIC_RDIST_IGROUPR_OFFSET 0x80U +#define XSCUGIC_RDIST_GRPMODR_OFFSET 0xD00U +#define XSCUGIC_RDIST_INT_CONFIG_OFFSET 0xC00U +#define XSCUGIC_RDIST_WAKER_OFFSET 0x14U +#define XSCUGIC_SGIR_EL1_INITID_SHIFT 24U + +/* + * GICR_IGROUPR register definitions + */ +#if EL3 +#define XSCUGIC_DEFAULT_SECURITY 0x0U +#else +#define XSCUGIC_DEFAULT_SECURITY 0xFFFFFFFFU +#endif +/* + * GICR_WAKER register definitions + */ +#define XSCUGIC_RDIST_WAKER_LOW_POWER_STATE_MASK 0x7 +#endif +/***************** Macros (Inline Functions) Definitions *********************/ + +/****************************************************************************/ +/** +* +* Read the Interrupt Configuration Register offset for an interrupt id. +* +* @param InterruptID is the interrupt number. +* +* @return The 32-bit value of the offset +* +* @note +* +*****************************************************************************/ +#define XSCUGIC_INT_CFG_OFFSET_CALC(InterruptID) \ + ((u32)XSCUGIC_INT_CFG_OFFSET + (((InterruptID)/16U) * 4U)) + +/****************************************************************************/ +/** +* +* Read the Interrupt Priority Register offset for an interrupt id. +* +* @param InterruptID is the interrupt number. +* +* @return The 32-bit value of the offset +* +* @note +* +*****************************************************************************/ +#define XSCUGIC_PRIORITY_OFFSET_CALC(InterruptID) \ + ((u32)XSCUGIC_PRIORITY_OFFSET + (((InterruptID)/4U) * 4U)) + +/****************************************************************************/ +/** +* +* Read the Interrupt Routing Register offset for an interrupt id. +* +* @param InterruptID is the interrupt number. +* +* @return The 32-bit value of the offset +* +* @note +* +*****************************************************************************/ +#define XSCUGIC_IROUTER_OFFSET_CALC(InterruptID) \ + ((u32)XSCUGIC_IROUTER_BASE_OFFSET + (InterruptID * 8)) + +/****************************************************************************/ +/** +* +* Read the SPI Target Register offset for an interrupt id. +* +* @param InterruptID is the interrupt number. +* +* @return The 32-bit value of the offset +* +* @note +* +*****************************************************************************/ +#define XSCUGIC_SPI_TARGET_OFFSET_CALC(InterruptID) \ + ((u32)XSCUGIC_SPI_TARGET_OFFSET + (((InterruptID)/4U) * 4U)) +/****************************************************************************/ +/** +* +* Read the SPI Target Register offset for an interrupt id. +* +* @param InterruptID is the interrupt number. +* +* @return The 32-bit value of the offset +* +* @note +* +*****************************************************************************/ +#define XSCUGIC_SECURITY_TARGET_OFFSET_CALC(InterruptID) \ + ((u32)XSCUGIC_SECURITY_OFFSET + (((InterruptID)/32U)*4U)) + +/****************************************************************************/ +/** +* +* Read the Re-distributor Interrupt configuration register offset +* +* @param InterruptID is the interrupt number. +* +* @return The 32-bit value of the offset +* +* @note +* +*****************************************************************************/ +#define XSCUGIC_RDIST_INT_CONFIG_OFFSET_CALC(InterruptID) \ + ((u32)XSCUGIC_RDIST_INT_CONFIG_OFFSET + ((InterruptID /16)*4)) + +/****************************************************************************/ +/** +* +* Read the Re-distributor Interrupt Priority register offset +* +* @param InterruptID is the interrupt number. +* +* @return The 32-bit value of the offset +* +* @note +* +*****************************************************************************/ +#define XSCUGIC_RDIST_INT_PRIORITY_OFFSET_CALC(InterruptID) \ + ((u32)XSCUGIC_RDIST_IPRIORITYR_OFFSET + (InterruptID * 4)) +/****************************************************************************/ +/** +* +* Read the Interrupt Clear-Enable Register offset for an interrupt ID +* +* @param Register is the register offset for the clear/enable bank. +* @param InterruptID is the interrupt number. +* +* @return The 32-bit value of the offset +* +* @note +* +*****************************************************************************/ +#define XSCUGIC_EN_DIS_OFFSET_CALC(Register, InterruptID) \ + ((Register) + (((InterruptID)/32U) * 4U)) + +/****************************************************************************/ +/** +* +* Read the given Intc register. +* +* @param BaseAddress is the base address of the device. +* @param RegOffset is the register offset to be read +* +* @return The 32-bit value of the register +* +* @note +* C-style signature: +* u32 XScuGic_ReadReg(u32 BaseAddress, u32 RegOffset) +* +*****************************************************************************/ +#define XScuGic_ReadReg(BaseAddress, RegOffset) \ + (Xil_In32((BaseAddress) + (RegOffset))) + + +/****************************************************************************/ +/** +* +* Write the given Intc register. +* +* @param BaseAddress is the base address of the device. +* @param RegOffset is the register offset to be written +* @param Data is the 32-bit value to write to the register +* +* @return None. +* +* @note +* C-style signature: +* void XScuGic_WriteReg(u32 BaseAddress, u32 RegOffset, u32 Data) +* +*****************************************************************************/ +#define XScuGic_WriteReg(BaseAddress, RegOffset, Data) \ + (Xil_Out32(((BaseAddress) + (RegOffset)), ((u32)(Data)))) + + +/****************************************************************************/ +/** +* +* Enable specific interrupt(s) in the interrupt controller. +* +* @param DistBaseAddress is the Distributor Register base address of the +* device +* @param Int_Id is the ID of the interrupt source and should be in the +* range of 0 to XSCUGIC_MAX_NUM_INTR_INPUTS - 1 +* +* @return None. +* +* @note C-style signature: +* void XScuGic_EnableIntr(u32 DistBaseAddress, u32 Int_Id) +* +*****************************************************************************/ +#define XScuGic_EnableIntr(DistBaseAddress, Int_Id) \ + XScuGic_WriteReg((DistBaseAddress), \ + XSCUGIC_ENABLE_SET_OFFSET + (((Int_Id) / 32U) * 4U), \ + (0x00000001U << ((Int_Id) % 32U))) + +/****************************************************************************/ +/** +* +* Disable specific interrupt(s) in the interrupt controller. +* +* @param DistBaseAddress is the Distributor Register base address of the +* device +* @param Int_Id is the ID of the interrupt source and should be in the +* range of 0 to XSCUGIC_MAX_NUM_INTR_INPUTS - 1 +* +* +* @return None. +* +* @note C-style signature: +* void XScuGic_DisableIntr(u32 DistBaseAddress, u32 Int_Id) +* +*****************************************************************************/ +#define XScuGic_DisableIntr(DistBaseAddress, Int_Id) \ + XScuGic_WriteReg((DistBaseAddress), \ + XSCUGIC_DISABLE_OFFSET + (((Int_Id) / 32U) * 4U), \ + (0x00000001U << ((Int_Id) % 32U))) + + +/************************** Function Prototypes ******************************/ + +void XScuGic_DeviceInterruptHandler(void *DeviceId); +s32 XScuGic_DeviceInitialize(u32 DeviceId); +void XScuGic_RegisterHandler(u32 BaseAddress, s32 InterruptID, + Xil_InterruptHandler Handler, void *CallBackRef); +void XScuGic_SetPriTrigTypeByDistAddr(u32 DistBaseAddress, u32 Int_Id, + u8 Priority, u8 Trigger); +void XScuGic_GetPriTrigTypeByDistAddr(u32 DistBaseAddress, u32 Int_Id, + u8 *Priority, u8 *Trigger); +void XScuGic_InterruptUnmapFromCpuByDistAddr(u32 DistBaseAddress, + u8 Cpu_Id, u32 Int_Id); +void XScuGic_UnmapAllInterruptsFromCpuByDistAddr(u32 DistBaseAddress, + u8 Cpu_Id); +/************************** Variable Definitions *****************************/ +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/scugic_v4_0/src/xscugic_intr.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/scugic_v4_0/src/xscugic_intr.c new file mode 100644 index 0000000..2157b4f --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/scugic_v4_0/src/xscugic_intr.c @@ -0,0 +1,185 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xscugic_intr.c +* @addtogroup scugic_v4_0 +* @{ +* +* This file contains the interrupt processing for the driver for the Xilinx +* Interrupt Controller. The interrupt processing is partitioned separately such +* that users are not required to use the provided interrupt processing. This +* file requires other files of the driver to be linked in also. +* +* The interrupt handler, XScuGic_InterruptHandler, uses an input argument which +* is an instance pointer to an interrupt controller driver such that multiple +* interrupt controllers can be supported. This handler requires the calling +* function to pass it the appropriate argument, so another level of indirection +* may be required. +* +* The interrupt processing may be used by connecting the interrupt handler to +* the interrupt system. The handler does not save and restore the processor +* context but only handles the processing of the Interrupt Controller. The user +* is encouraged to supply their own interrupt handler when performance tuning is +* deemed necessary. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- ---------------------------------------------------------
+* 1.00a drg  01/19/10 First release
+* 1.01a sdm  11/09/11 XScuGic_InterruptHandler has changed correspondingly
+*		      since the HandlerTable has now moved to XScuGic_Config.
+* 3.00  kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.10  mus  07/17/18 Updated XScuGic_InterruptHandler to fix array overrun
+*                     reported by coverity tool. It fixes CR#1006344.
+* 3.10  mus  07/17/18 Updated file to fix the various coding style issues
+*                     reported by checkpatch. It fixes CR#1006344.
+*
+* 
+* +* @internal +* +* This driver assumes that the context of the processor has been saved prior to +* the calling of the Interrupt Controller interrupt handler and then restored +* after the handler returns. This requires either the running RTOS to save the +* state of the machine or that a wrapper be used as the destination of the +* interrupt vector to save the state of the processor and restore the state +* after the interrupt handler returns. +* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xscugic.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +/*****************************************************************************/ +/** +* This function is the primary interrupt handler for the driver. It must be +* connected to the interrupt source such that it is called when an interrupt of +* the interrupt controller is active. It will resolve which interrupts are +* active and enabled and call the appropriate interrupt handler. It uses +* the Interrupt Type information to determine when to acknowledge the interrupt. +* Highest priority interrupts are serviced first. +* +* This function assumes that an interrupt vector table has been previously +* initialized. It does not verify that entries in the table are valid before +* calling an interrupt handler. +* +* +* @param InstancePtr is a pointer to the XScuGic instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XScuGic_InterruptHandler(XScuGic *InstancePtr) +{ + + u32 InterruptID; +#if !defined (versal) || defined (ARMR5) + u32 IntIDFull; +#endif + XScuGic_VectorTableEntry *TablePtr; + + /* Assert that the pointer to the instance is valid + */ + Xil_AssertVoid(InstancePtr != NULL); + + /* + * Read the int_ack register to identify the highest priority + * interrupt ID and make sure it is valid. Reading Int_Ack will + * clear the interrupt in the GIC. + */ +#if defined (versal) && !defined(ARMR5) + InterruptID = XScuGic_get_IntID(); +#else + IntIDFull = XScuGic_CPUReadReg(InstancePtr, XSCUGIC_INT_ACK_OFFSET); + InterruptID = IntIDFull & XSCUGIC_ACK_INTID_MASK; +#endif + if (XSCUGIC_MAX_NUM_INTR_INPUTS <= InterruptID) { + goto IntrExit; + } + + /* + * If the interrupt is shared, do some locking here if + * there are multiple processors. + */ + /* + * If pre-eption is required: + * Re-enable pre-emption by setting the CPSR I bit for non-secure , + * interrupts or the F bit for secure interrupts + */ + + /* + * If we need to change security domains, issue a SMC + * instruction here. + */ + + /* + * Execute the ISR. Jump into the Interrupt service routine + * based on the IRQSource. A software trigger is cleared by + *.the ACK. + */ + TablePtr = &(InstancePtr->Config->HandlerTable[InterruptID]); + if (TablePtr != NULL) { + TablePtr->Handler(TablePtr->CallBackRef); + } + +IntrExit: + /* + * Write to the EOI register, we are all done here. + * Let this function return, the boot code will restore the stack. + */ +#if defined (versal) && !defined(ARMR5) + XScuGic_ack_Int(InterruptID); + +#else + XScuGic_CPUWriteReg(InstancePtr, XSCUGIC_EOI_OFFSET, IntIDFull); +#endif + /* + * Return from the interrupt. Change security domains + * could happen here. + */ +} +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/scugic_v4_0/src/xscugic_selftest.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/scugic_v4_0/src/xscugic_selftest.c new file mode 100644 index 0000000..052ef43 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/scugic_v4_0/src/xscugic_selftest.c @@ -0,0 +1,114 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xscugic_selftest.c +* @addtogroup scugic_v4_0 +* @{ +* +* Contains diagnostic self-test functions for the XScuGic driver. +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a drg  01/19/10 First release
+* 3.00  kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.10  mus  07/17/18 Updated file to fix the various coding style issues
+*                     reported by checkpatch. It fixes CR#1006344.
+*
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xscugic.h" + +/************************** Constant Definitions *****************************/ + +#define XSCUGIC_PCELL_ID 0xB105F00DU + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +/*****************************************************************************/ +/** +* +* Run a self-test on the driver/device. This test reads the ID registers and +* compares them. +* +* @param InstancePtr is a pointer to the XScuGic instance. +* +* @return +* +* -XST_SUCCESS if self-test is successful. +* -XST_FAILURE if the self-test is not successful. +* +* @note None. +* +******************************************************************************/ +s32 XScuGic_SelfTest(XScuGic *InstancePtr) +{ + u32 RegValue1 = 0U; + u32 Index; + s32 Status; + + /* + * Assert the arguments + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the ID registers. + */ + for (Index = 0U; Index <= 3U; Index++) { + RegValue1 |= XScuGic_DistReadReg(InstancePtr, + ((u32)XSCUGIC_PCELLID_OFFSET + (Index * 4U))) << + (Index * 8U); + } + + if (XSCUGIC_PCELL_ID != RegValue1) { + Status = XST_FAILURE; + } else { + Status = XST_SUCCESS; + } + return Status; +} +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/scugic_v4_0/src/xscugic_sinit.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/scugic_v4_0/src/xscugic_sinit.c new file mode 100644 index 0000000..3a3d710 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/scugic_v4_0/src/xscugic_sinit.c @@ -0,0 +1,101 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xscugic_sinit.c +* @addtogroup scugic_v4_0 +* @{ +* +* Contains static init functions for the XScuGic driver for the Interrupt +* Controller. See xscugic.h for a detailed description of the driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- --------------------------------------------------------
+* 1.00a drg  01/19/10 First release
+* 3.00  kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.10  mus  07/17/18 Updated file to fix the various coding style issues
+*                     reported by checkpatch. It fixes CR#1006344.
+*
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xparameters.h" +#include "xscugic.h" + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Variable Definitions *****************************/ + +extern XScuGic_Config XScuGic_ConfigTable[XPAR_SCUGIC_NUM_INSTANCES]; + +/************************** Function Prototypes ******************************/ + +/*****************************************************************************/ +/** +* +* Looks up the device configuration based on the unique device ID. A table +* contains the configuration info for each device in the system. +* +* @param DeviceId is the unique identifier for a device. +* +* @return A pointer to the XScuGic configuration structure for the +* specified device, or NULL if the device was not found. +* +* @note None. +* +******************************************************************************/ +XScuGic_Config *XScuGic_LookupConfig(u16 DeviceId) +{ + XScuGic_Config *CfgPtr = NULL; + u32 Index; + + for (Index = 0U; Index < (u32)XPAR_SCUGIC_NUM_INSTANCES; Index++) { + if (XScuGic_ConfigTable[Index].DeviceId == DeviceId) { + CfgPtr = &XScuGic_ConfigTable[Index]; + break; + } + } + + return (XScuGic_Config *)CfgPtr; +} +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/scutimer_v2_1/src/Makefile b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/scutimer_v2_1/src/Makefile new file mode 100644 index 0000000..7c673d4 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/scutimer_v2_1/src/Makefile @@ -0,0 +1,40 @@ +COMPILER= +ARCHIVER= +CP=cp +COMPILER_FLAGS= +EXTRA_COMPILER_FLAGS= +LIB=libxil.a + +CC_FLAGS = $(COMPILER_FLAGS) +ECC_FLAGS = $(EXTRA_COMPILER_FLAGS) + +RELEASEDIR=../../../lib +INCLUDEDIR=../../../include +INCLUDES=-I./. -I${INCLUDEDIR} + +OUTS = *.o + +LIBSOURCES:=*.c +INCLUDEFILES:=*.h + +OBJECTS = $(addsuffix .o, $(basename $(wildcard *.c))) + +libs: banner scutimer_libs clean + +%.o: %.c + ${COMPILER} $(CC_FLAGS) $(ECC_FLAGS) $(INCLUDES) -o $@ $< + +banner: + echo "Compiling scutimer" + +scutimer_libs: ${OBJECTS} + $(ARCHIVER) -r ${RELEASEDIR}/${LIB} ${OBJECTS} + +.PHONY: include +include: scutimer_includes + +scutimer_includes: + ${CP} ${INCLUDEFILES} ${INCLUDEDIR} + +clean: + rm -rf ${OBJECTS} diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/scutimer_v2_1/src/xscutimer.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/scutimer_v2_1/src/xscutimer.c new file mode 100644 index 0000000..d7f6348 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/scutimer_v2_1/src/xscutimer.c @@ -0,0 +1,282 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xscutimer.c +* @addtogroup scutimer_v2_1 +* @{ +* +* Contains the implementation of interface functions of the SCU Timer driver. +* See xscutimer.h for a description of the driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 1.00a nm  03/10/10 First release
+* 2.1 	sk  02/26/15 Modified the code for MISRA-C:2012 compliance.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xscutimer.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +/****************************************************************************/ +/** +* +* Initialize a specific timer instance/driver. This function must be called +* before other functions of the driver are called. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* @param ConfigPtr points to the XScuTimer configuration structure. +* @param EffectiveAddress is the base address for the device. It could be +* a virtual address if address translation is supported in the +* system, otherwise it is the physical address. +* +* @return +* - XST_SUCCESS if initialization was successful. +* - XST_DEVICE_IS_STARTED if the device has already been started. +* +* @note None. +* +******************************************************************************/ +s32 XScuTimer_CfgInitialize(XScuTimer *InstancePtr, + XScuTimer_Config *ConfigPtr, u32 EffectiveAddress) +{ + s32 Status; + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(ConfigPtr != NULL); + + /* + * If the device is started, disallow the initialize and return a + * status indicating it is started. This allows the user to stop the + * device and reinitialize, but prevents a user from inadvertently + * initializing. + */ + if (InstancePtr->IsStarted != XIL_COMPONENT_IS_STARTED) { + /* + * Copy configuration into the instance structure. + */ + InstancePtr->Config.DeviceId = ConfigPtr->DeviceId; + + /* + * Save the base address pointer such that the registers of the block + * can be accessed and indicate it has not been started yet. + */ + InstancePtr->Config.BaseAddr = EffectiveAddress; + + InstancePtr->IsStarted = (u32)0; + + /* + * Indicate the instance is ready to use, successfully initialized. + */ + InstancePtr->IsReady = XIL_COMPONENT_IS_READY; + + Status =(s32)XST_SUCCESS; + } + else { + Status = (s32)XST_DEVICE_IS_STARTED; + } + return Status; +} + +/****************************************************************************/ +/** +* +* Start the timer. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XScuTimer_Start(XScuTimer *InstancePtr) +{ + u32 Register; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the contents of the Control register. + */ + Register = XScuTimer_ReadReg(InstancePtr->Config.BaseAddr, + XSCUTIMER_CONTROL_OFFSET); + + /* + * Set the 'timer enable' bit in the register. + */ + Register |= XSCUTIMER_CONTROL_ENABLE_MASK; + + /* + * Update the Control register with the new value. + */ + XScuTimer_WriteReg(InstancePtr->Config.BaseAddr, + XSCUTIMER_CONTROL_OFFSET, Register); + + /* + * Indicate that the device is started. + */ + InstancePtr->IsStarted = XIL_COMPONENT_IS_STARTED; +} + +/****************************************************************************/ +/** +* +* Stop the timer. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XScuTimer_Stop(XScuTimer *InstancePtr) +{ + u32 Register; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the contents of the Control register. + */ + Register = XScuTimer_ReadReg(InstancePtr->Config.BaseAddr, + XSCUTIMER_CONTROL_OFFSET); + + /* + * Clear the 'timer enable' bit in the register. + */ + Register &= (u32)(~XSCUTIMER_CONTROL_ENABLE_MASK); + + /* + * Update the Control register with the new value. + */ + XScuTimer_WriteReg(InstancePtr->Config.BaseAddr, + XSCUTIMER_CONTROL_OFFSET, Register); + + /* + * Indicate that the device is stopped. + */ + InstancePtr->IsStarted = (u32)0; +} + +/*****************************************************************************/ +/** +* +* This function sets the prescaler bits in the timer control register. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* @param PrescalerValue is a 8 bit value that sets the prescaler to use. +* +* @return None +* +* @note None +* +****************************************************************************/ +void XScuTimer_SetPrescaler(XScuTimer *InstancePtr, u8 PrescalerValue) +{ + u32 ControlReg; + + /* + * Assert to validate input arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + /* + * Read the Timer control register. + */ + ControlReg = XScuTimer_ReadReg(InstancePtr->Config.BaseAddr, + XSCUTIMER_CONTROL_OFFSET); + + /* + * Clear all of the prescaler control bits in the register. + */ + ControlReg &= (u32)(~XSCUTIMER_CONTROL_PRESCALER_MASK); + + /* + * Set the prescaler value. + */ + ControlReg |= (((u32)PrescalerValue) << XSCUTIMER_CONTROL_PRESCALER_SHIFT); + + /* + * Write the register with the new values. + */ + XScuTimer_WriteReg(InstancePtr->Config.BaseAddr, + XSCUTIMER_CONTROL_OFFSET, ControlReg); +} + +/*****************************************************************************/ +/** +* +* This function returns the current prescaler value. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* +* @return The prescaler value. +* +* @note None. +* +****************************************************************************/ +u8 XScuTimer_GetPrescaler(XScuTimer *InstancePtr) +{ + u32 ControlReg; + + /* + * Assert to validate input arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the Timer control register. + */ + ControlReg = XScuTimer_ReadReg(InstancePtr->Config.BaseAddr, + XSCUTIMER_CONTROL_OFFSET); + ControlReg &= XSCUTIMER_CONTROL_PRESCALER_MASK; + + return (u8)(ControlReg >> XSCUTIMER_CONTROL_PRESCALER_SHIFT); +} +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/scutimer_v2_1/src/xscutimer.h b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/scutimer_v2_1/src/xscutimer.h new file mode 100644 index 0000000..5434684 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/scutimer_v2_1/src/xscutimer.h @@ -0,0 +1,364 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xscutimer.h +* @addtogroup scutimer_v2_1 +* @{ +* @details +* +* The timer driver supports the Cortex A9 private timer. +* +* The timer driver supports the following features: +* - Normal mode and Auto reload mode +* - Interrupts (Interrupt handler is not provided in this driver. Application +* has to register it's own handler) +* +* Initialization and Configuration +* +* The device driver enables higher layer software (e.g., an application) to +* communicate with the Timer. +* +* XScuTimer_CfgInitialize() API is used to initialize the Timer. The +* user needs to first call the XScuTimer_LookupConfig() API which returns +* the Configuration structure pointer which is passed as a parameter to +* the XScuTimer_CfgInitialize() API. +* +* Interrupts +* +* The Timer hardware supports interrupts. +* +* This driver does not provide a Interrupt Service Routine (ISR) for the device. +* It is the responsibility of the application to provide one if needed. Refer to +* the interrupt example provided with this driver for details on using the +* Timer in interrupt mode. +* +* Virtual Memory +* +* This driver supports Virtual Memory. The RTOS is responsible for calculating +* the correct device base address in Virtual Memory space. +* +* Threads +* +* This driver is not thread safe. Any needs for threads or thread mutual +* exclusion must be satisfied by the layer above this driver. +* +* Asserts +* +* Asserts are used within all Xilinx drivers to enforce constraints on argument +* values. Asserts can be turned off on a system-wide basis by defining, at +* compile time, the NDEBUG identifier. By default, asserts are turned on and it +* is recommended that users leave asserts on during development. +* +* Building the driver +* +* The XScuTimer driver is composed of several source files. This allows the user +* to build and link only those parts of the driver that are necessary. +* +*

+* +* NOTE: +* The timer is not a part of the snoop control unit as indicated by the +* prefix "scu" in the name of the driver. +* It is an independent module in APU. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 1.00a nm  03/10/10 First release
+* 1.02a sg  07/17/12 Included xil_assert.h for CR 667947. This is an issue
+*		     when the xstatus.h in the common driver overwrites
+*		     the xstatus.h of the standalone BSP during the
+*		     libgen.
+* 2.1 	sk  02/26/15 Modified the code for MISRA-C:2012 compliance.
+*       ms  03/17/17 Added readme.txt file in examples folder for doxygen
+*                    generation.
+* 
+* +******************************************************************************/ +#ifndef XSCUTIMER_H /* prevent circular inclusions */ +#define XSCUTIMER_H /* by using protection macros */ + +/***************************** Include Files *********************************/ + +#include "xstatus.h" +#include "xscutimer_hw.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/** + * This typedef contains configuration information for the device. + */ +typedef struct { + u16 DeviceId; /**< Unique ID of device */ + u32 BaseAddr; /**< Base address of the device */ +} XScuTimer_Config; + +/** + * The XScuTimer driver instance data. The user is required to allocate a + * variable of this type for every timer device in the system. + * A pointer to a variable of this type is then passed to the driver API + * functions. + */ +typedef struct { + XScuTimer_Config Config; /**< Hardware Configuration */ + u32 IsReady; /**< Device is initialized and ready */ + u32 IsStarted; /**< Device timer is running */ +} XScuTimer; + +/***************** Macros (Inline Functions) Definitions *********************/ + +/****************************************************************************/ +/** +* +* Check if the timer has expired. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* +* @return +* - TRUE if the timer has expired. +* - FALSE if the timer has not expired. +* +* @note C-style signature: +* int XScuTimer_IsExpired(XScuTimer *InstancePtr) +* +******************************************************************************/ +#define XScuTimer_IsExpired(InstancePtr) \ + ((XScuTimer_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_ISR_OFFSET) & \ + XSCUTIMER_ISR_EVENT_FLAG_MASK) == \ + XSCUTIMER_ISR_EVENT_FLAG_MASK) + +/****************************************************************************/ +/** +* +* Re-start the timer. This macro will read the timer load register +* and writes the same value to load register to update the counter register. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_RestartTimer(XScuTimer *InstancePtr) +* +******************************************************************************/ +#define XScuTimer_RestartTimer(InstancePtr) \ + XScuTimer_LoadTimer((InstancePtr), \ + XScuTimer_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_LOAD_OFFSET)) + +/****************************************************************************/ +/** +* +* Write to the timer load register. This will also update the +* timer counter register with the new value. This macro can be used to +* change the time-out value. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* @param Value is the count to be loaded in to the load register. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_LoadTimer(XScuTimer *InstancePtr, u32 Value) +* +******************************************************************************/ +#define XScuTimer_LoadTimer(InstancePtr, Value) \ + XScuTimer_WriteReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_LOAD_OFFSET, (Value)) + +/****************************************************************************/ +/** +* +* Returns the current timer counter register value. It can be called at any +* time. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* +* @return Contents of the timer counter register. +* +* @note C-style signature: + u32 XScuTimer_GetCounterValue(XScuTimer *InstancePtr) +* +******************************************************************************/ +#define XScuTimer_GetCounterValue(InstancePtr) \ + XScuTimer_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_COUNTER_OFFSET) + +/****************************************************************************/ +/** +* +* Enable auto-reload mode. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_EnableAutoReload(XScuTimer *InstancePtr) +* +******************************************************************************/ +#define XScuTimer_EnableAutoReload(InstancePtr) \ + XScuTimer_WriteReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_CONTROL_OFFSET, \ + (XScuTimer_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_CONTROL_OFFSET) | \ + XSCUTIMER_CONTROL_AUTO_RELOAD_MASK)) + +/****************************************************************************/ +/** +* +* Disable auto-reload mode. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_DisableAutoReload(XScuTimer *InstancePtr) +* +******************************************************************************/ +#define XScuTimer_DisableAutoReload(InstancePtr) \ + XScuTimer_WriteReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_CONTROL_OFFSET, \ + (XScuTimer_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_CONTROL_OFFSET) & \ + ~(XSCUTIMER_CONTROL_AUTO_RELOAD_MASK))) + +/****************************************************************************/ +/** +* +* Enable the Timer interrupt. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_EnableInterrupt(XScuTimer *InstancePtr) +* +******************************************************************************/ +#define XScuTimer_EnableInterrupt(InstancePtr) \ + XScuTimer_WriteReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_CONTROL_OFFSET, \ + (XScuTimer_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_CONTROL_OFFSET) | \ + XSCUTIMER_CONTROL_IRQ_ENABLE_MASK)) + +/****************************************************************************/ +/** +* +* Disable the Timer interrupt. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_DisableInterrupt(XScuTimer *InstancePtr) +* +******************************************************************************/ +#define XScuTimer_DisableInterrupt(InstancePtr) \ + XScuTimer_WriteReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_CONTROL_OFFSET, \ + (XScuTimer_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_CONTROL_OFFSET) & \ + ~(XSCUTIMER_CONTROL_IRQ_ENABLE_MASK))) + +/*****************************************************************************/ +/** +* +* This function reads the interrupt status. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_GetInterruptStatus(XScuTimer *InstancePtr) +* +******************************************************************************/ +#define XScuTimer_GetInterruptStatus(InstancePtr) \ + XScuTimer_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_ISR_OFFSET) + +/*****************************************************************************/ +/** +* +* This function clears the interrupt status. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_ClearInterruptStatus(XScuTimer *InstancePtr) +* +******************************************************************************/ +#define XScuTimer_ClearInterruptStatus(InstancePtr) \ + XScuTimer_WriteReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_ISR_OFFSET, XSCUTIMER_ISR_EVENT_FLAG_MASK) + +/************************** Function Prototypes ******************************/ + +/* + * Lookup configuration in xscutimer_sinit.c + */ +XScuTimer_Config *XScuTimer_LookupConfig(u16 DeviceId); + +/* + * Selftest function in xscutimer_selftest.c + */ +s32 XScuTimer_SelfTest(XScuTimer *InstancePtr); + +/* + * Interface functions in xscutimer.c + */ +s32 XScuTimer_CfgInitialize(XScuTimer *InstancePtr, + XScuTimer_Config *ConfigPtr, u32 EffectiveAddress); +void XScuTimer_Start(XScuTimer *InstancePtr); +void XScuTimer_Stop(XScuTimer *InstancePtr); +void XScuTimer_SetPrescaler(XScuTimer *InstancePtr, u8 PrescalerValue); +u8 XScuTimer_GetPrescaler(XScuTimer *InstancePtr); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/scutimer_v2_1/src/xscutimer_g.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/scutimer_v2_1/src/xscutimer_g.c new file mode 100644 index 0000000..96e564a --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/scutimer_v2_1/src/xscutimer_g.c @@ -0,0 +1,51 @@ + +/******************************************************************* +* +* CAUTION: This file is automatically generated by HSI. +* Version: 2019.1.3 +* DO NOT EDIT. +* +* Copyright (C) 2010-2023 Xilinx, Inc. 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 +*XILINX 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. +* +*Except as contained in this notice, the name of the Xilinx shall not be used +*in advertising or otherwise to promote the sale, use or other dealings in +*this Software without prior written authorization from Xilinx. +* + +* +* Description: Driver configuration +* +*******************************************************************/ + +#include "xparameters.h" +#include "xscutimer.h" + +/* +* The configuration table for devices +*/ + +XScuTimer_Config XScuTimer_ConfigTable[XPAR_XSCUTIMER_NUM_INSTANCES] = +{ + { + XPAR_PS7_SCUTIMER_0_DEVICE_ID, + XPAR_PS7_SCUTIMER_0_BASEADDR + } +}; + + diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/scutimer_v2_1/src/xscutimer_hw.h b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/scutimer_v2_1/src/xscutimer_hw.h new file mode 100644 index 0000000..d577784 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/scutimer_v2_1/src/xscutimer_hw.h @@ -0,0 +1,283 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xscutimer_hw.h +* @addtogroup scutimer_v2_1 +* @{ +* +* This file contains the hardware interface to the Timer. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 1.00a nm  03/10/10 First release
+* 1.01a sdm 02/02/12 Added low level macros to read/write load, counter, control
+*		     and interrupt registers
+* 1.02a  sg 07/17/12 Included xil_assert.h for CR 667947. This is an issue
+*		     when the xstatus.h in the common driver overwrites
+*		     the xstatus.h of the standalone BSP during the
+*		     libgen.
+* 2.1 	sk  02/26/15 Modified the code for MISRA-C:2012 compliance.
+* 
+* +******************************************************************************/ +#ifndef XSCUTIMER_HW_H /* prevent circular inclusions */ +#define XSCUTIMER_HW_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ +#include "xil_types.h" +#include "xil_io.h" +#include "xil_assert.h" +/************************** Constant Definitions *****************************/ + +/** @name Register Map + * Offsets of registers from the start of the device + * @{ + */ + +#define XSCUTIMER_LOAD_OFFSET 0x00U /**< Timer Load Register */ +#define XSCUTIMER_COUNTER_OFFSET 0x04U /**< Timer Counter Register */ +#define XSCUTIMER_CONTROL_OFFSET 0x08U /**< Timer Control Register */ +#define XSCUTIMER_ISR_OFFSET 0x0CU /**< Timer Interrupt + Status Register */ +/* @} */ + +/** @name Timer Control register + * This register bits control the prescaler, Intr enable, + * auto-reload and timer enable. + * @{ + */ + +#define XSCUTIMER_CONTROL_PRESCALER_MASK 0x0000FF00U /**< Prescaler */ +#define XSCUTIMER_CONTROL_PRESCALER_SHIFT 8U +#define XSCUTIMER_CONTROL_IRQ_ENABLE_MASK 0x00000004U /**< Intr enable */ +#define XSCUTIMER_CONTROL_AUTO_RELOAD_MASK 0x00000002U /**< Auto-reload */ +#define XSCUTIMER_CONTROL_ENABLE_MASK 0x00000001U /**< Timer enable */ +/* @} */ + +/** @name Interrupt Status register + * This register indicates the Timer counter register has reached zero. + * @{ + */ + +#define XSCUTIMER_ISR_EVENT_FLAG_MASK 0x00000001U /**< Event flag */ +/*@}*/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/****************************************************************************/ +/** +* +* Write to the timer load register. This will also update the +* timer counter register with the new value. This macro can be used to +* change the time-out value. +* +* @param BaseAddr is the base address of the scu timer. +* @param Value is the count to be loaded in to the load register. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_SetLoadReg(u32 BaseAddr, u32 Value) +* +******************************************************************************/ +#define XScuTimer_SetLoadReg(BaseAddr, Value) \ + XScuTimer_WriteReg(BaseAddr, XSCUTIMER_LOAD_OFFSET, (Value)) + +/****************************************************************************/ +/** +* +* Returns the current timer load register value. +* +* @param BaseAddr is the base address of the scu timer. +* +* @return Contents of the timer load register. +* +* @note C-style signature: +* u32 XScuTimer_GetLoadReg(u32 BaseAddr) +* +******************************************************************************/ +#define XScuTimer_GetLoadReg(BaseAddr) \ + XScuTimer_ReadReg(BaseAddr, XSCUTIMER_LOAD_OFFSET) + +/****************************************************************************/ +/** +* +* Write to the timer counter register. +* +* @param BaseAddr is the base address of the scu timer. +* @param Value is the count to be loaded in to the counter register. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_SetCounterReg(u32 BaseAddr, u32 Value) +* +******************************************************************************/ +#define XScuTimer_SetCounterReg(BaseAddr, Value) \ + XScuTimer_WriteReg(BaseAddr, XSCUTIMER_COUNTER_OFFSET, (Value)) + +/****************************************************************************/ +/** +* +* Returns the current timer counter register value. +* +* @param BaseAddr is the base address of the scu timer. +* +* @return Contents of the timer counter register. +* +* @note C-style signature: + u32 XScuTimer_GetCounterReg(u32 BaseAddr) +* +******************************************************************************/ +#define XScuTimer_GetCounterReg(BaseAddr) \ + XScuTimer_ReadReg(BaseAddr, XSCUTIMER_COUNTER_OFFSET) + +/****************************************************************************/ +/** +* +* Write to the timer load register. This will also update the +* timer counter register with the new value. This macro can be used to +* change the time-out value. +* +* @param BaseAddr is the base address of the scu timer. +* @param Value is the count to be loaded in to the load register. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_SetControlReg(u32 BaseAddr, u32 Value) +* +******************************************************************************/ +#define XScuTimer_SetControlReg(BaseAddr, Value) \ + XScuTimer_WriteReg(BaseAddr, XSCUTIMER_CONTROL_OFFSET, (Value)) + +/****************************************************************************/ +/** +* +* Returns the current timer load register value. +* +* @param BaseAddr is the base address of the scu timer. +* +* @return Contents of the timer load register. +* +* @note C-style signature: + u32 XScuTimer_GetControlReg(u32 BaseAddr) +* +******************************************************************************/ +#define XScuTimer_GetControlReg(BaseAddr) \ + XScuTimer_ReadReg(BaseAddr, XSCUTIMER_CONTROL_OFFSET) + +/****************************************************************************/ +/** +* +* Write to the timer counter register. +* +* @param BaseAddr is the base address of the scu timer. +* @param Value is the count to be loaded in to the counter register. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_SetIntrReg(u32 BaseAddr, u32 Value) +* +******************************************************************************/ +#define XScuTimer_SetIntrReg(BaseAddr, Value) \ + XScuTimer_WriteReg(BaseAddr, XSCUTIMER_ISR_OFFSET, (Value)) + +/****************************************************************************/ +/** +* +* Returns the current timer counter register value. +* +* @param BaseAddr is the base address of the scu timer. +* +* @return Contents of the timer counter register. +* +* @note C-style signature: + u32 XScuTimer_GetIntrReg(u32 BaseAddr) +* +******************************************************************************/ +#define XScuTimer_GetIntrReg(BaseAddr) \ + XScuTimer_ReadReg(BaseAddr, XSCUTIMER_ISR_OFFSET) + +/****************************************************************************/ +/** +* +* Read from the given Timer register. +* +* @param BaseAddr is the base address of the device +* @param RegOffset is the register offset to be read +* +* @return The 32-bit value of the register +* +* @note C-style signature: +* u32 XScuTimer_ReadReg(u32 BaseAddr, u32 RegOffset) +* +*****************************************************************************/ +#define XScuTimer_ReadReg(BaseAddr, RegOffset) \ + Xil_In32((BaseAddr) + (RegOffset)) + +/****************************************************************************/ +/** +* +* Write to the given Timer register. +* +* @param BaseAddr is the base address of the device +* @param RegOffset is the register offset to be written +* @param Data is the 32-bit value to write to the register +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_WriteReg(u32 BaseAddr, u32 RegOffset, u32 Data) +* +*****************************************************************************/ +#define XScuTimer_WriteReg(BaseAddr, RegOffset, Data) \ + Xil_Out32((BaseAddr) + (RegOffset), (Data)) + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/scutimer_v2_1/src/xscutimer_selftest.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/scutimer_v2_1/src/xscutimer_selftest.c new file mode 100644 index 0000000..b3464b6 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/scutimer_v2_1/src/xscutimer_selftest.c @@ -0,0 +1,135 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xscutimer_selftest.c +* @addtogroup scutimer_v2_1 +* @{ +* +* Contains diagnostic self-test functions for the XScuTimer driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 1.00a nm  03/10/10 First release
+* 2.1 	sk  02/26/15 Modified the code for MISRA-C:2012 compliance.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xscutimer.h" + +/************************** Constant Definitions *****************************/ + +#define XSCUTIMER_SELFTEST_VALUE 0xA55AF00FU + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +/****************************************************************************/ +/** +* +* Run a self-test on the timer. This test clears the timer enable bit in +* the control register, writes to the timer load register and verifies the +* value read back matches the value written and restores the control register +* and the timer load register. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* +* @return +* - XST_SUCCESS if self-test was successful. +* - XST_FAILURE if self test was not successful. +* +* @note None. +* +******************************************************************************/ +s32 XScuTimer_SelfTest(XScuTimer *InstancePtr) +{ + u32 Register; + u32 CtrlOrig; + u32 LoadOrig; + s32 Status; + + /* + * Assert to ensure the inputs are valid and the instance has been + * initialized. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Save the contents of the Control Register and stop the timer. + */ + CtrlOrig = XScuTimer_ReadReg(InstancePtr->Config.BaseAddr, + XSCUTIMER_CONTROL_OFFSET); + Register = CtrlOrig & (u32)(~XSCUTIMER_CONTROL_ENABLE_MASK); + XScuTimer_WriteReg(InstancePtr->Config.BaseAddr, + XSCUTIMER_CONTROL_OFFSET, Register); + + /* + * Save the contents of the Load Register. + * Load a new test value in the Load Register, read it back and + * compare it with the written value. + */ + LoadOrig = XScuTimer_ReadReg((InstancePtr)->Config.BaseAddr, + XSCUTIMER_LOAD_OFFSET); + XScuTimer_LoadTimer(InstancePtr, XSCUTIMER_SELFTEST_VALUE); + Register = XScuTimer_ReadReg((InstancePtr)->Config.BaseAddr, + XSCUTIMER_LOAD_OFFSET); + + /* + * Restore the contents of the Load Register and Control Register. + */ + XScuTimer_LoadTimer(InstancePtr, LoadOrig); + XScuTimer_WriteReg(InstancePtr->Config.BaseAddr, + XSCUTIMER_CONTROL_OFFSET, CtrlOrig); + + /* + * Return a Failure if the contents of the Load Register do not + * match with the value written to it. + */ + if (Register != XSCUTIMER_SELFTEST_VALUE) { + Status = (s32)XST_FAILURE; + } + else { + Status = (s32)XST_SUCCESS; + } + + return Status; +} +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/scutimer_v2_1/src/xscutimer_sinit.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/scutimer_v2_1/src/xscutimer_sinit.c new file mode 100644 index 0000000..0c5f671 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/scutimer_v2_1/src/xscutimer_sinit.c @@ -0,0 +1,92 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xscutimer_sinit.c +* @addtogroup scutimer_v2_1 +* @{ +* +* This file contains method for static initialization (compile-time) of the +* driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 1.00a nm  03/10/10 First release
+* 2.1 	sk  02/26/15 Modified the code for MISRA-C:2012 compliance.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xscutimer.h" +#include "xparameters.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Variable Definitions ****************************/ +extern XScuTimer_Config XScuTimer_ConfigTable[XPAR_XSCUTIMER_NUM_INSTANCES]; + +/************************** Function Prototypes ******************************/ + +/*****************************************************************************/ +/** +* Lookup the device configuration based on the unique device ID. The table +* contains the configuration info for each device in the system. +* +* @param DeviceId is the unique device ID of the device being looked up. +* +* @return A pointer to the configuration table entry corresponding to the +* given device ID, or NULL if no match is found. +* +* @note None. +* +******************************************************************************/ +XScuTimer_Config *XScuTimer_LookupConfig(u16 DeviceId) +{ + XScuTimer_Config *CfgPtr = NULL; + u32 Index; + + for (Index = 0U; Index < XPAR_XSCUTIMER_NUM_INSTANCES; Index++) { + if (XScuTimer_ConfigTable[Index].DeviceId == DeviceId) { + CfgPtr = &XScuTimer_ConfigTable[Index]; + break; + } + } + + return (XScuTimer_Config *)CfgPtr; +} +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/scuwdt_v2_1/src/Makefile b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/scuwdt_v2_1/src/Makefile new file mode 100644 index 0000000..493ad9a --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/scuwdt_v2_1/src/Makefile @@ -0,0 +1,40 @@ +COMPILER= +ARCHIVER= +CP=cp +COMPILER_FLAGS= +EXTRA_COMPILER_FLAGS= +LIB=libxil.a + +CC_FLAGS = $(COMPILER_FLAGS) +ECC_FLAGS = $(EXTRA_COMPILER_FLAGS) + +RELEASEDIR=../../../lib +INCLUDEDIR=../../../include +INCLUDES=-I./. -I${INCLUDEDIR} + +OUTS = *.o + +LIBSOURCES:=*.c +INCLUDEFILES:=*.h + +OBJECTS = $(addsuffix .o, $(basename $(wildcard *.c))) + +libs: banner scuwdt_libs clean + +%.o: %.c + ${COMPILER} $(CC_FLAGS) $(ECC_FLAGS) $(INCLUDES) -o $@ $< + +banner: + echo "Compiling scuwdt" + +scuwdt_libs: ${OBJECTS} + $(ARCHIVER) -r ${RELEASEDIR}/${LIB} ${OBJECTS} + +.PHONY: include +include: scuwdt_includes + +scuwdt_includes: + ${CP} ${INCLUDEFILES} ${INCLUDEDIR} + +clean: + rm -rf ${OBJECTS} diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/scuwdt_v2_1/src/xscuwdt.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/scuwdt_v2_1/src/xscuwdt.c new file mode 100644 index 0000000..85f0507 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/scuwdt_v2_1/src/xscuwdt.c @@ -0,0 +1,213 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xscuwdt.c +* @addtogroup scuwdt_v2_1 +* @{ +* +* Contains the implementation of interface functions of the XScuWdt driver. +* See xscuwdt.h for a description of the driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 1.00a sdm 01/15/10 First release
+* 2.1 	sk  02/26/15 Modified the code for MISRA-C:2012 compliance.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xscuwdt.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +/****************************************************************************/ +/** +* +* Initialize a specific watchdog timer instance/driver. This function +* must be called before other functions of the driver are called. +* +* @param InstancePtr is a pointer to the XScuWdt instance. +* @param ConfigPtr is the config structure. +* @param EffectiveAddress is the base address for the device. It could be +* a virtual address if address translation is supported in the +* system, otherwise it is the physical address. +* +* @return +* - XST_SUCCESS if initialization was successful. +* - XST_DEVICE_IS_STARTED if the device has already been started. +* +* @note This function enables the watchdog mode. +* +******************************************************************************/ +s32 XScuWdt_CfgInitialize(XScuWdt *InstancePtr, + XScuWdt_Config *ConfigPtr, u32 EffectiveAddress) +{ + s32 CfgStatus; + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(ConfigPtr != NULL); + Xil_AssertNonvoid(EffectiveAddress != 0x00U); + + /* + * If the device is started, disallow the initialize and return a + * status indicating it is started. This allows the user to stop the + * device and reinitialize, but prevents a user from inadvertently + * initializing. + */ + if (InstancePtr->IsStarted == XIL_COMPONENT_IS_STARTED) { + CfgStatus = (s32)XST_DEVICE_IS_STARTED; + } + else { + /* + * Copy configuration into instance. + */ + InstancePtr->Config.DeviceId = ConfigPtr->DeviceId; + + /* + * Save the base address pointer such that the registers of the block + * can be accessed and indicate it has not been started yet. + */ + InstancePtr->Config.BaseAddr = EffectiveAddress; + InstancePtr->IsStarted = 0U; + + /* + * Put the watchdog timer in Watchdog mode. + */ + XScuWdt_SetWdMode(InstancePtr); + + /* + * Indicate the instance is ready to use, successfully initialized. + */ + InstancePtr->IsReady = XIL_COMPONENT_IS_READY; + + CfgStatus =(s32)XST_SUCCESS; + } + return CfgStatus; +} + +/****************************************************************************/ +/** +* +* Start the watchdog counter of the device. +* +* @param InstancePtr is a pointer to the XScuWdt instance. +* +* @return None. +* +* @note User needs to select the appropriate mode (watchdog/timer) +* before using this API. +* See XScuWdt_SetWdMode/XScuWdt_SetTimerMode macros in +* xscuwdt.h. +* +******************************************************************************/ +void XScuWdt_Start(XScuWdt *InstancePtr) +{ + u32 Register; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the contents of the Control register. + */ + Register = XScuWdt_ReadReg(InstancePtr->Config.BaseAddr, + XSCUWDT_CONTROL_OFFSET); + + /* + * Set the 'watchdog enable' bit in the register. + */ + Register |= XSCUWDT_CONTROL_WD_ENABLE_MASK; + + /* + * Update the Control register with the new value. + */ + XScuWdt_WriteReg(InstancePtr->Config.BaseAddr, + XSCUWDT_CONTROL_OFFSET, Register); + + /* + * Indicate that the device is started. + */ + InstancePtr->IsStarted = XIL_COMPONENT_IS_STARTED; +} + +/****************************************************************************/ +/** +* +* Stop the watchdog timer. +* +* @param InstancePtr is a pointer to the XScuWdt instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XScuWdt_Stop(XScuWdt *InstancePtr) +{ + u32 Register; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the contents of the Control register. + */ + Register = XScuWdt_ReadReg(InstancePtr->Config.BaseAddr, + XSCUWDT_CONTROL_OFFSET); + + /* + * Clear the 'watchdog enable' bit in the register. + */ + Register &= (u32)(~XSCUWDT_CONTROL_WD_ENABLE_MASK); + + /* + * Update the Control register with the new value. + */ + XScuWdt_WriteReg(InstancePtr->Config.BaseAddr, + XSCUWDT_CONTROL_OFFSET, Register); + + /* + * Indicate that the device is stopped. + */ + InstancePtr->IsStarted = 0U; +} +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/scuwdt_v2_1/src/xscuwdt.h b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/scuwdt_v2_1/src/xscuwdt.h new file mode 100644 index 0000000..551eaf5 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/scuwdt_v2_1/src/xscuwdt.h @@ -0,0 +1,379 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xscuwdt.h +* @addtogroup scuwdt_v2_1 +* @{ +* @details +* +* The Xilinx SCU watchdog timer driver (XScuWdt) supports the Xilinx SCU private +* watchdog timer hardware. +* +* The XScuWdt driver supports the following features: +* - Watchdog mode +* - Timer mode +* - Auto reload (timer mode only) +* +* The watchdog counter register is a down counter and starts decrementing when +* the watchdog is started. +* In watchdog mode, when the counter reaches 0, the Reset flag is set in the +* Reset status register and the WDRESETREQ pin is asserted, causing a system +* reset. The Reset flag is not reset by normal processor reset and is cleared +* when written with a value of 1. This enables the user to differentiate a +* normal reset and a reset caused by watchdog time-out. The user needs to call +* XScuWdt_RestartWdt() periodically, to avoid the watchdog from being timed-out. +* +* The IsWdtExpired function can be used to check if the watchdog was the cause +* of the last reset. In this situation, call Initialize then call IsWdtExpired. +* If the result is true, watchdog timeout caused the last system reset. The +* application then needs to clear the Reset flag. +* +* In timer mode, when the counter reaches 0, the Event flag is set in the +* Interrupt status register and if interrupts are enabled, interrupt ID 30 is +* set as pending in the interrupt distributor. The IsTimerExpired function +* is used to check if the watchdog counter has decremented to 0 in timer mode. +* If auto-reload mode is enabled, the Counter register is automatically reloaded +* from the Load register. +* +* Initialization and Configuration +* +* The device driver enables higher layer software (e.g., an application) to +* communicate with the Watchdog Timer. +* +* XScuWdt_CfgInitialize() API is used to initialize the Watchdog Timer. The +* user needs to first call the XScuWdt_LookupConfig() API which returns +* the Configuration structure pointer which is passed as a parameter to +* the XScuWdt_CfgInitialize() API. +* +* Interrupts +* +* The SCU Watchdog Timer supports interrupts in Timer mode. +* +* This driver does not provide a Interrupt Service Routine (ISR) for the device. +* It is the responsibility of the application to provide one if needed. Refer to +* the interrupt example provided with this driver for details on using the +* Timer in interrupt mode. +* +* Virtual Memory +* +* This driver supports Virtual Memory. The RTOS is responsible for calculating +* the correct device base address in Virtual Memory space. +* +* Threads +* +* This driver is not thread safe. Any needs for threads or thread mutual +* exclusion must be satisfied by the layer above this driver. +* +* Asserts +* +* Asserts are used within all Xilinx drivers to enforce constraints on argument +* values. Asserts can be turned off on a system-wide basis by defining, at +* compile time, the NDEBUG identifier. By default, asserts are turned on and it +* is recommended that users leave asserts on during development. +* +* Building the driver +* +* The XScuWdt driver is composed of several source files. This allows the user +* to build and link only those parts of the driver that are necessary. +* +*

+* +* NOTE: +* The watchdog timer is not a part of the snoop control unit as indicated +* by the prefix "scu" in the name of the driver. +* It is an independent module in APU. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 1.00a sdm 01/15/10 First release
+* 1.02a  sg 07/17/12 Included xil_assert.h for CR 667947. This is an issue
+*		     when the xstatus.h in the common driver overwrites
+*		     the xstatus.h of the standalone BSP during the
+*		     libgen.
+* 2.1 	sk  02/26/15 Modified the code for MISRA-C:2012 compliance.
+*       ms  03/17/17 Added readme.txt file in examples folder for doxygen
+*                    generation.
+* 
+* +******************************************************************************/ +#ifndef XSCUWDT_H /* prevent circular inclusions */ +#define XSCUWDT_H /* by using protection macros */ + +/***************************** Include Files *********************************/ + +#include "xstatus.h" +#include "xscuwdt_hw.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/** + * This typedef contains configuration information for the device. + */ +typedef struct { + u16 DeviceId; /**< Unique ID of device */ + u32 BaseAddr; /**< Base address of the device */ +} XScuWdt_Config; + +/** + * The XScuWdt driver instance data. The user is required to allocate a + * variable of this type for every watchdog/timer device in the system. + * A pointer to a variable of this type is then passed to the driver API + * functions. + */ +typedef struct { + XScuWdt_Config Config;/**< Hardware Configuration */ + u32 IsReady; /**< Device is initialized and ready */ + u32 IsStarted; /**< Device watchdog timer is running */ +} XScuWdt; + +/***************** Macros (Inline Functions) Definitions *********************/ +/****************************************************************************/ +/** +* +* This function is used to check if the watchdog has timed-out and the last +* reset was caused by the watchdog reset. +* +* @param InstancePtr is a pointer to the XScuWdt instance. +* +* @return +* - TRUE if the watchdog has expired. +* - FALSE if the watchdog has not expired. +* +* @note C-style signature: +* int XScuWdt_IsWdtExpired(XScuWdt *InstancePtr) +* +******************************************************************************/ +#define XScuWdt_IsWdtExpired(InstancePtr) \ + ((XScuWdt_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUWDT_RST_STS_OFFSET) & \ + XSCUWDT_RST_STS_RESET_FLAG_MASK) == XSCUWDT_RST_STS_RESET_FLAG_MASK) + +/****************************************************************************/ +/** +* +* This function is used to check if the watchdog counter has reached 0 in timer +* mode. +* +* @param InstancePtr is a pointer to the XScuWdt instance. +* +* @return +* - TRUE if the watchdog has expired. +* - FALSE if the watchdog has not expired. +* +* @note C-style signature: +* int XScuWdt_IsTimerExpired(XScuWdt *InstancePtr) +* +******************************************************************************/ +#define XScuWdt_IsTimerExpired(InstancePtr) \ + ((XScuWdt_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUWDT_ISR_OFFSET) & \ + XSCUWDT_ISR_EVENT_FLAG_MASK) == XSCUWDT_ISR_EVENT_FLAG_MASK) + +/****************************************************************************/ +/** +* +* Re-start the watchdog timer. This macro will read the watchdog load register +* and write the same value to load register to update the counter register. +* An application needs to call this function periodically to keep the watchdog +* from asserting the WDRESETREQ reset request output pin. +* +* @param InstancePtr is a pointer to the XScuWdt instance. +* +* @return None. +* +* @note C-style signature: +* void XScuWdt_RestartWdt(XScuWdt *InstancePtr) +* +******************************************************************************/ +#define XScuWdt_RestartWdt(InstancePtr) \ + XScuWdt_LoadWdt((InstancePtr), \ + (XScuWdt_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUWDT_LOAD_OFFSET))) + +/****************************************************************************/ +/** +* +* Write to the watchdog timer load register. This will also update the +* watchdog counter register with the new value. This macro can be used to +* change the time-out value. +* +* @param InstancePtr is a pointer to the XScuWdt instance. +* @param Value is the value to be written to the Watchdog Load register. +* +* @return None. +* +* @note C-style signature: +* void XScuWdt_LoadWdt(XScuWdt *InstancePtr, u32 Value) +* +******************************************************************************/ +#define XScuWdt_LoadWdt(InstancePtr, Value) \ + XScuWdt_WriteReg((InstancePtr)->Config.BaseAddr, \ + XSCUWDT_LOAD_OFFSET, (Value)) + +/****************************************************************************/ +/** +* +* Put the watchdog timer in Watchdog mode by setting the WD mode bit of the +* Watchdog control register. +* +* @param InstancePtr is a pointer to the XScuWdt instance. +* +* @return None. +* +* @note C-style signature: +* void XScuWdt_SetWdMode(XScuWdt *InstancePtr) +* +******************************************************************************/ +#define XScuWdt_SetWdMode(InstancePtr) \ + XScuWdt_WriteReg((InstancePtr)->Config.BaseAddr, \ + XSCUWDT_CONTROL_OFFSET, \ + (XScuWdt_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUWDT_CONTROL_OFFSET) | \ + (XSCUWDT_CONTROL_WD_MODE_MASK))) + +/****************************************************************************/ +/** +* +* Put the watchdog timer in Timer mode by writing 0x12345678 and 0x87654321 +* successively to the Watchdog Disable Register. +* The software must write 0x12345678 and 0x87654321 successively to the +* Watchdog Disable Register so that the watchdog mode bit in the Watchdog +* Control Register is set to zero. +* +* @param InstancePtr is a pointer to the XScuWdt instance. +* +* @return None. +* +* @note C-style signature: +* void XScuWdt_SetTimerMode(XScuWdt *InstancePtr) +* +******************************************************************************/ +#define XScuWdt_SetTimerMode(InstancePtr) \ +{ \ + XScuWdt_WriteReg((InstancePtr)->Config.BaseAddr, \ + XSCUWDT_DISABLE_OFFSET, \ + XSCUWDT_DISABLE_VALUE1); \ + XScuWdt_WriteReg((InstancePtr)->Config.BaseAddr, \ + XSCUWDT_DISABLE_OFFSET, \ + XSCUWDT_DISABLE_VALUE2); \ +} + +/****************************************************************************/ +/** +* +* Get the contents of the watchdog control register. +* +* @param InstancePtr is a pointer to the XScuWdt instance. +* +* @return Contents of the watchdog control register. +* +* @note C-style signature: + u32 XScuWdt_GetControlReg(XScuWdt *InstancePtr) +* +******************************************************************************/ +#define XScuWdt_GetControlReg(InstancePtr) \ + XScuWdt_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUWDT_CONTROL_OFFSET) + +/****************************************************************************/ +/** +* +* Write to the watchdog control register. +* +* @param InstancePtr is a pointer to the XScuWdt instance. +* @param ControlReg is the value to be written to the watchdog control +* register. +* +* @return None. +* +* @note C-style signature: + void XScuWdt_SetControlReg(XScuWdt *InstancePtr, u32 ControlReg) +* +******************************************************************************/ +#define XScuWdt_SetControlReg(InstancePtr, ControlReg) \ + XScuWdt_WriteReg((InstancePtr)->Config.BaseAddr, \ + XSCUWDT_CONTROL_OFFSET, (ControlReg)) + +/****************************************************************************/ +/** +* +* Enable auto-reload mode. +* +* @param InstancePtr is a pointer to the XScuWdt instance. +* +* @return None. +* +* @note C-style signature: +* void XScuWdt_EnableAutoReload(XScuWdt *InstancePtr) +* +******************************************************************************/ +#define XScuWdt_EnableAutoReload(InstancePtr) \ + XScuWdt_SetControlReg((InstancePtr), \ + (XScuWdt_GetControlReg(InstancePtr) | \ + XSCUWDT_CONTROL_AUTO_RELOAD_MASK)) + +/************************** Function Prototypes ******************************/ + +/* + * Lookup configuration in xscuwdt_sinit.c. + */ +XScuWdt_Config *XScuWdt_LookupConfig(u16 DeviceId); + +/* + * Selftest function in xscuwdt_selftest.c + */ +s32 XScuWdt_SelfTest(XScuWdt *InstancePtr); + +/* + * Interface functions in xscuwdt.c + */ +s32 XScuWdt_CfgInitialize(XScuWdt *InstancePtr, + XScuWdt_Config *ConfigPtr, u32 EffectiveAddress); + +void XScuWdt_Start(XScuWdt *InstancePtr); + +void XScuWdt_Stop(XScuWdt *InstancePtr); + + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/scuwdt_v2_1/src/xscuwdt_g.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/scuwdt_v2_1/src/xscuwdt_g.c new file mode 100644 index 0000000..8b0af3b --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/scuwdt_v2_1/src/xscuwdt_g.c @@ -0,0 +1,51 @@ + +/******************************************************************* +* +* CAUTION: This file is automatically generated by HSI. +* Version: 2019.1.3 +* DO NOT EDIT. +* +* Copyright (C) 2010-2023 Xilinx, Inc. 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 +*XILINX 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. +* +*Except as contained in this notice, the name of the Xilinx shall not be used +*in advertising or otherwise to promote the sale, use or other dealings in +*this Software without prior written authorization from Xilinx. +* + +* +* Description: Driver configuration +* +*******************************************************************/ + +#include "xparameters.h" +#include "xscuwdt.h" + +/* +* The configuration table for devices +*/ + +XScuWdt_Config XScuWdt_ConfigTable[XPAR_XSCUWDT_NUM_INSTANCES] = +{ + { + XPAR_PS7_SCUWDT_0_DEVICE_ID, + XPAR_PS7_SCUWDT_0_BASEADDR + } +}; + + diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/scuwdt_v2_1/src/xscuwdt_hw.h b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/scuwdt_v2_1/src/xscuwdt_hw.h new file mode 100644 index 0000000..ad87a05 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/scuwdt_v2_1/src/xscuwdt_hw.h @@ -0,0 +1,178 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xscuwdt_hw.h +* @addtogroup scuwdt_v2_1 +* @{ +* +* This file contains the hardware interface to the Xilinx SCU private Watch Dog +* Timer (XSCUWDT). +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 1.00a sdm 01/15/10 First release
+* 1.01a bss 02/27/12 Updated the register offsets to start at 0x0 instead
+*                    of 0x20 as the base address obtained from the tools
+*		     starts at 0x20.
+* 1.02a  sg 07/17/12 Included xil_assert.h for CR 667947. This is an issue
+*		     when the xstatus.h in the common driver overwrites
+*		     the xstatus.h of the standalone BSP during the
+*		     libgen.
+* 2.1 	sk  02/26/15 Modified the code for MISRA-C:2012 compliance.
+* 
+* +******************************************************************************/ +#ifndef XSCUWDT_HW_H /* prevent circular inclusions */ +#define XSCUWDT_HW_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_io.h" +#include "xil_assert.h" +/************************** Constant Definitions *****************************/ + +/** @name Register Map + * Offsets of registers from the start of the device. The WDT registers start at + * an offset 0x20 + * @{ + */ + +#define XSCUWDT_LOAD_OFFSET 0x00U /**< Watchdog Load Register */ +#define XSCUWDT_COUNTER_OFFSET 0x04U /**< Watchdog Counter Register */ +#define XSCUWDT_CONTROL_OFFSET 0x08U /**< Watchdog Control Register */ +#define XSCUWDT_ISR_OFFSET 0x0CU /**< Watchdog Interrupt Status Register */ +#define XSCUWDT_RST_STS_OFFSET 0x10U /**< Watchdog Reset Status Register */ +#define XSCUWDT_DISABLE_OFFSET 0x14U /**< Watchdog Disable Register */ +/* @} */ + +/** @name Watchdog Control register + * This register bits control the prescaler, WD/Timer mode, Intr enable, + * auto-reload, watchdog enable. + * @{ + */ + +#define XSCUWDT_CONTROL_PRESCALER_MASK 0x0000FF00U /**< Prescaler */ +#define XSCUWDT_CONTROL_PRESCALER_SHIFT 8U +#define XSCUWDT_CONTROL_WD_MODE_MASK 0x00000008U /**< Watchdog/Timer mode */ +#define XSCUWDT_CONTROL_IT_ENABLE_MASK 0x00000004U /**< Intr enable (in + timer mode) */ +#define XSCUWDT_CONTROL_AUTO_RELOAD_MASK 0x00000002U /**< Auto-reload (in + timer mode) */ +#define XSCUWDT_CONTROL_WD_ENABLE_MASK 0x00000001U /**< Watchdog enable */ +/* @} */ + +/** @name Interrupt Status register + * This register indicates the Counter register has reached zero in Counter + * mode. + * @{ + */ + +#define XSCUWDT_ISR_EVENT_FLAG_MASK 0x00000001U /**< Event flag */ +/*@}*/ + +/** @name Reset Status register + * This register indicates the Counter register has reached zero in Watchdog + * mode and a reset request is sent. + * @{ + */ + +#define XSCUWDT_RST_STS_RESET_FLAG_MASK 0x00000001U /**< Time out occured */ +/*@}*/ + +/** @name Disable register + * This register is used to switch from watchdog mode to timer mode. + * The software must write 0x12345678 and 0x87654321 successively to the + * Watchdog Disable Register so that the watchdog mode bit in the Watchdog + * Control Register is set to zero. + * @{ + */ +#define XSCUWDT_DISABLE_VALUE1 0x12345678U /**< Watchdog mode disable + value 1 */ +#define XSCUWDT_DISABLE_VALUE2 0x87654321U /**< Watchdog mode disable + value 2 */ +/*@}*/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/****************************************************************************/ +/** +* +* Read the given register. +* +* @param BaseAddr is the base address of the device +* @param RegOffset is the register offset to be read +* +* @return The 32-bit value of the register +* +* @note C-style signature: +* u32 XScuWdt_ReadReg(u32 BaseAddr, u32 RegOffset) +* +*****************************************************************************/ +#define XScuWdt_ReadReg(BaseAddr, RegOffset) \ + Xil_In32((BaseAddr) + ((u32)RegOffset)) + +/****************************************************************************/ +/** +* +* Write the given register. +* +* @param BaseAddr is the base address of the device +* @param RegOffset is the register offset to be written +* @param Data is the 32-bit value to write to the register +* +* @return None. +* +* @note C-style signature: +* void XScuWdt_WriteReg(u32 BaseAddr, u32 RegOffset, u32 Data) +* +*****************************************************************************/ +#define XScuWdt_WriteReg(BaseAddr, RegOffset, Data) \ + Xil_Out32((BaseAddr) + ((u32)RegOffset), ((u32)Data)) + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/scuwdt_v2_1/src/xscuwdt_selftest.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/scuwdt_v2_1/src/xscuwdt_selftest.c new file mode 100644 index 0000000..aa0cd39 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/scuwdt_v2_1/src/xscuwdt_selftest.c @@ -0,0 +1,127 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xscuwdt_selftest.c +* @addtogroup scuwdt_v2_1 +* @{ +* +* Contains diagnostic self-test functions for the XScuWdt driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 1.00a sdm 01/15/10 First release
+* 2.1 	sk  02/26/15 Modified the code for MISRA-C:2012 compliance.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xscuwdt.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +/****************************************************************************/ +/** +* +* Run a self-test on the WDT. This test stops the watchdog, writes a value to +* the watchdog load register, starts the watchdog and verifies that the value +* read from the counter register is less that the value written to the load +* register. It then restores the control register and the watchdog load +* register. +* +* @param InstancePtr is a pointer to the XScuWdt instance. +* +* @return +* - XST_SUCCESS if self-test was successful. +* - XST_FAILURE if the WDT is not decrementing. +* +* @note None. +* +******************************************************************************/ +s32 XScuWdt_SelfTest(XScuWdt *InstancePtr) +{ + s32 SelfTestStatus; + u32 Register; + u32 CtrlOrig; + u32 LoadOrig; + + /* + * Assert to ensure the inputs are valid and the instance has been + * initialized. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Stop the watchdog timer. + */ + CtrlOrig = XScuWdt_GetControlReg(InstancePtr); + XScuWdt_SetControlReg(InstancePtr, + CtrlOrig & (u32)(~XSCUWDT_CONTROL_WD_ENABLE_MASK)); + + LoadOrig = XScuWdt_ReadReg((InstancePtr)->Config.BaseAddr, + XSCUWDT_LOAD_OFFSET); + XScuWdt_LoadWdt(InstancePtr, 0xFFFFFFFFU); + + /* + * Start the watchdog timer and check if the watchdog counter is + * decrementing. + */ + XScuWdt_SetControlReg(InstancePtr, + CtrlOrig | (u32)XSCUWDT_CONTROL_WD_ENABLE_MASK); + + Register = XScuWdt_ReadReg((InstancePtr)->Config.BaseAddr, + XSCUWDT_COUNTER_OFFSET); + + XScuWdt_LoadWdt(InstancePtr, LoadOrig); + XScuWdt_SetControlReg(InstancePtr, CtrlOrig); + + if (Register == 0xFFFFFFFFU) { + SelfTestStatus = (s32)XST_FAILURE; + } + else { + SelfTestStatus = (s32)XST_SUCCESS; + } + + return SelfTestStatus; +} +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/scuwdt_v2_1/src/xscuwdt_sinit.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/scuwdt_v2_1/src/xscuwdt_sinit.c new file mode 100644 index 0000000..e311a04 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/scuwdt_v2_1/src/xscuwdt_sinit.c @@ -0,0 +1,92 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xscuwdt_sinit.c +* @addtogroup scuwdt_v2_1 +* @{ +* +* This file contains method for static initialization (compile-time) of the +* driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 1.00a sdm 01/15/10 First release
+* 2.1 	sk  02/26/15 Modified the code for MISRA-C:2012 compliance.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xscuwdt.h" +#include "xparameters.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ +extern XScuWdt_Config XScuWdt_ConfigTable[XPAR_XSCUWDT_NUM_INSTANCES]; + +/*****************************************************************************/ +/** +* Lookup the device configuration based on the unique device ID. The table +* contains the configuration info for each device in the system. +* +* @param DeviceId is the unique device ID of the device being looked up. +* +* @return A pointer to the configuration table entry corresponding to the +* given device ID, or NULL if no match is found. +* +* @note None. +* +******************************************************************************/ +XScuWdt_Config *XScuWdt_LookupConfig(u16 DeviceId) +{ + XScuWdt_Config *CfgPtr = NULL; + u32 Index; + + for (Index = 0U; Index < XPAR_XSCUWDT_NUM_INSTANCES; Index++) { + if (XScuWdt_ConfigTable[Index].DeviceId == DeviceId) { + CfgPtr = &XScuWdt_ConfigTable[Index]; + break; + } + } + + return (XScuWdt_Config *)CfgPtr; +} +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/spips_v3_2/src/Makefile b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/spips_v3_2/src/Makefile new file mode 100644 index 0000000..10d24d7 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/spips_v3_2/src/Makefile @@ -0,0 +1,40 @@ +COMPILER= +ARCHIVER= +CP=cp +COMPILER_FLAGS= +EXTRA_COMPILER_FLAGS= +LIB=libxil.a + +CC_FLAGS = $(COMPILER_FLAGS) +ECC_FLAGS = $(EXTRA_COMPILER_FLAGS) + +RELEASEDIR=../../../lib +INCLUDEDIR=../../../include +INCLUDES=-I./. -I${INCLUDEDIR} + +OUTS = *.o + +LIBSOURCES:=*.c +INCLUDEFILES:=*.h + +OBJECTS = $(addsuffix .o, $(basename $(wildcard *.c))) + +libs: banner xspips_libs clean + +%.o: %.c + ${COMPILER} $(CC_FLAGS) $(ECC_FLAGS) $(INCLUDES) -o $@ $< + +banner: + echo "Compiling spips" + +xspips_libs: ${OBJECTS} + $(ARCHIVER) -r ${RELEASEDIR}/${LIB} ${OBJECTS} + +.PHONY: include +include: xspips_includes + +xspips_includes: + ${CP} ${INCLUDEFILES} ${INCLUDEDIR} + +clean: + rm -rf ${OBJECTS} diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/spips_v3_2/src/xspips.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/spips_v3_2/src/xspips.c new file mode 100644 index 0000000..42bd5d1 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/spips_v3_2/src/xspips.c @@ -0,0 +1,1154 @@ +/****************************************************************************** +* +* Copyright (C) 2017 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xspips.c +* @addtogroup spips_v3_2 +* @{ +* +* Contains implements the interface functions of the XSpiPs driver. +* See xspips.h for a detailed description of the device and driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ------ -------- -----------------------------------------------
+* 1.00  drg/jz 01/25/10 First release
+* 1.01	sg     03/07/12 Updated the code to always clear the relevant bits
+*			before writing to config register.
+*			Always clear the slave select bits before write and
+*			clear the bits to no slave at the end of transfer
+*			Modified the Polled transfer transmit/receive logic.
+*			Tx should wait on TXOW Interrupt and Rx on RXNEMTY.
+* 1.03	sg     09/21/12 Added memory barrier dmb in polled transfer and
+*			interrupt handler to overcome the clock domain
+*			crossing issue in the controller. For CR #679252.
+* 1.04a	sg     01/30/13 Changed SPI transfer logic for polled and interrupt
+*			modes to be based on filled tx fifo count and receive
+*			based on it. RXNEMPTY interrupt is not used.
+*			SetSlaveSelect API logic is modified to drive the bit
+*			position low based on the slave select value
+*			requested. GetSlaveSelect API will return the value
+*			based on bit position that is low.
+* 1.06a hk     08/22/13 Changed GetSlaveSelect function. CR# 727866.
+*                       Added masking ConfigReg before writing in SetSlaveSel
+*                       Added extended slave select support - CR#722569.
+*                       Added check for MODF in polled transfer function.
+* 3.00  kvn    02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.02  raw    11/23/15 Updated XSpiPs_Abort() to read all RXFIFO entries.
+* 			This change is to tackle CR#910231.
+* 3.1	tjs    04/12/18 InputClockHz parameter copied in instance for use in
+* 						application. CR#998910
+* 3.1   tjs    11/23/18 Added a check for A72 and R5 processor to
+*                       avoid changes made for the workaround DT#842463.
+* 3.2	aru    01/20/19 Fixes violations according to MISRAC-2012
+*                       in safety mode and done changes such as
+*                       Declared the pointer param as Pointer to const,
+*			added goto statements.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xspips.h" + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + +/****************************************************************************/ +/* +* +* Send one byte to the currently selected slave. A byte of data is written to +* transmit FIFO/register. +* +* @param BaseAddress is the base address of the device +* +* @return None. +* +* @note C-Style signature: +* void XSpiPs_SendByte(u32 BaseAddress, u8 Data) +* +*****************************************************************************/ +#define XSpiPs_SendByte(BaseAddress, Data) \ + XSpiPs_Out32((BaseAddress) + (u32)XSPIPS_TXD_OFFSET, (u32)(Data)) + +/****************************************************************************/ +/* +* +* Receive one byte from the device's receive FIFO/register. It is assumed +* that the byte is already available. +* +* @param BaseAddress is the base address of the device +* +* @return The byte retrieved from the receive FIFO/register. +* +* @note C-Style signature: +* u8 XSpiPs_RecvByte(u32 BaseAddress) +* +*****************************************************************************/ +#define XSpiPs_RecvByte(BaseAddress) \ + XSpiPs_In32((u32)((BaseAddress) + (u32)XSPIPS_RXD_OFFSET)) + +/************************** Function Prototypes ******************************/ + +static void StubStatusHandler(const void *CallBackRef, u32 StatusEvent, + u32 ByteCount); + +/************************** Variable Definitions *****************************/ + + +/*****************************************************************************/ +/** +* +* Initializes a specific XSpiPs instance such that the driver is ready to use. +* +* The state of the device after initialization is: +* - Device is disabled +* - Slave mode +* - Active high clock polarity +* - Clock phase 0 +* +* @param InstancePtr is a pointer to the XSpiPs instance. +* @param ConfigPtr is a reference to a structure containing information +* about a specific SPI device. This function initializes an +* InstancePtr object for a specific device specified by the +* contents of Config. This function can initialize multiple +* instance objects with the use of multiple calls giving different +* Config information on each call. +* @param EffectiveAddr is the device base address in the virtual memory +* address space. The caller is responsible for keeping the address +* mapping from EffectiveAddr to the device physical base address +* unchanged once this function is invoked. Unexpected errors may +* occur if the address mapping changes after this function is +* called. If address translation is not used, use +* ConfigPtr->Config.BaseAddress for this device. +* +* @return +* - XST_SUCCESS if successful. +* - XST_DEVICE_IS_STARTED if the device is already started. +* It must be stopped to re-initialize. +* +* @note None. +* +******************************************************************************/ +s32 XSpiPs_CfgInitialize(XSpiPs *InstancePtr, const XSpiPs_Config *ConfigPtr, + u32 EffectiveAddr) +{ + s32 Status; + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(ConfigPtr != NULL); + + /* + * If the device is busy, disallow the initialize and return a status + * indicating it is already started. This allows the user to stop the + * device and re-initialize, but prevents a user from inadvertently + * initializing. This assumes the busy flag is cleared at startup. + */ + if (InstancePtr->IsBusy == TRUE) { + Status = (s32)XST_DEVICE_IS_STARTED; + } else { + + /* + * Set some default values. + */ + InstancePtr->IsBusy = FALSE; + + InstancePtr->Config.BaseAddress = EffectiveAddr; + InstancePtr->Config.InputClockHz = ConfigPtr->InputClockHz; + InstancePtr->StatusHandler = StubStatusHandler; + + InstancePtr->SendBufferPtr = NULL; + InstancePtr->RecvBufferPtr = NULL; + InstancePtr->RequestedBytes = 0U; + InstancePtr->RemainingBytes = 0U; + InstancePtr->IsReady = XIL_COMPONENT_IS_READY; + + /* + * Reset the SPI device to get it into its initial state. It is + * expected that device configuration will take place after this + * initialization is done, but before the device is started. + */ + XSpiPs_Reset(InstancePtr); + Status = (s32)XST_SUCCESS; + } + + return Status; +} + + +/*****************************************************************************/ +/** +* +* Resets the SPI device. Reset must only be called after the driver has been +* initialized. The configuration of the device after reset is the same as its +* configuration after initialization. Any data transfer that is in progress +* is aborted. +* +* The upper layer software is responsible for re-configuring (if necessary) +* and restarting the SPI device after the reset. +* +* @param InstancePtr is a pointer to the XSpiPs instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XSpiPs_Reset(XSpiPs *InstancePtr) +{ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Abort any transfer that is in progress + */ + XSpiPs_Abort(InstancePtr); + + /* + * Reset any values that are not reset by the hardware reset such that + * the software state matches the hardware device + */ + XSpiPs_WriteReg(InstancePtr->Config.BaseAddress, XSPIPS_CR_OFFSET, + XSPIPS_CR_RESET_STATE); + +} + +/*****************************************************************************/ +/** +* +* Transfers specified data on the SPI bus. If the SPI device is configured as +* a master, this function initiates bus communication and sends/receives the +* data to/from the selected SPI slave. If the SPI device is configured as a +* slave, this function prepares the buffers to be sent/received when selected +* by a master. For every byte sent, a byte is received. This function should +* be used to perform interrupt based transfers. +* +* The caller has the option of providing two different buffers for send and +* receive, or one buffer for both send and receive, or no buffer for receive. +* The receive buffer must be at least as big as the send buffer to prevent +* unwanted memory writes. This implies that the byte count passed in as an +* argument must be the smaller of the two buffers if they differ in size. +* Here are some sample usages: +*
+*   XSpiPs_Transfer(InstancePtr, SendBuf, RecvBuf, ByteCount)
+*	The caller wishes to send and receive, and provides two different
+*	buffers for send and receive.
+*
+*   XSpiPs_Transfer(InstancePtr, SendBuf, NULL, ByteCount)
+*	The caller wishes only to send and does not care about the received
+*	data. The driver ignores the received data in this case.
+*
+*   XSpiPs_Transfer(InstancePtr, SendBuf, SendBuf, ByteCount)
+*	The caller wishes to send and receive, but provides the same buffer
+*	for doing both. The driver sends the data and overwrites the send
+*	buffer with received data as it transfers the data.
+*
+*   XSpiPs_Transfer(InstancePtr, RecvBuf, RecvBuf, ByteCount)
+*	The caller wishes to only receive and does not care about sending
+*	data.  In this case, the caller must still provide a send buffer, but
+*	it can be the same as the receive buffer if the caller does not care
+*	what it sends.  The device must send N bytes of data if it wishes to
+*	receive N bytes of data.
+* 
+* Although this function takes entire buffers as arguments, the driver can only +* transfer a limited number of bytes at a time, limited by the size of the +* FIFO. A call to this function only starts the transfer, then subsequent +* transfers of the data is performed by the interrupt service routine until +* the entire buffer has been transferred. The status callback function is +* called when the entire buffer has been sent/received. +* +* This function is non-blocking. As a master, the SetSlaveSelect function must +* be called prior to this function. +* +* @param InstancePtr is a pointer to the XSpiPs instance. +* @param SendBufPtr is a pointer to a buffer of data for sending. +* This buffer must not be NULL. +* @param RecvBufPtr is a pointer to a buffer for received data. +* This argument can be NULL if do not care about receiving. +* @param ByteCount contains the number of bytes to send/receive. +* The number of bytes received always equals the number of bytes +* sent. +* +* @return +* - XST_SUCCESS if the buffers are successfully handed off to the +* device for transfer. +* - XST_DEVICE_BUSY indicates that a data transfer is already in +* progress. This is determined by the driver. +* +* @note +* +* This function is not thread-safe. The higher layer software must ensure that +* no two threads are transferring data on the SPI bus at the same time. +* +******************************************************************************/ +s32 XSpiPs_Transfer(XSpiPs *InstancePtr, u8 *SendBufPtr, + u8 *RecvBufPtr, u32 ByteCount) +{ + u32 ConfigReg; + u8 TransCount = 0U; + s32 StatusTransfer; + + /* + * The RecvBufPtr argument can be null + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(SendBufPtr != NULL); + Xil_AssertNonvoid(ByteCount > 0U); + Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); + + /* + * Check whether there is another transfer in progress. Not thread-safe. + */ + if (InstancePtr->IsBusy == TRUE) { + StatusTransfer = (s32)XST_DEVICE_BUSY; + } else { + + /* + * Set the busy flag, which will be cleared in the ISR when the + * transfer is entirely done. + */ + InstancePtr->IsBusy = TRUE; + + /* + * Set up buffer pointers. + */ + InstancePtr->SendBufferPtr = SendBufPtr; + InstancePtr->RecvBufferPtr = RecvBufPtr; + + InstancePtr->RequestedBytes = ByteCount; + InstancePtr->RemainingBytes = ByteCount; + + /* + * If manual chip select mode, initialize the slave select value. + */ + if (XSpiPs_IsManualChipSelect(InstancePtr) != FALSE) { + ConfigReg = XSpiPs_ReadReg(InstancePtr->Config.BaseAddress, + XSPIPS_CR_OFFSET); + /* + * Set the slave select value. + */ + ConfigReg &= (u32)(~XSPIPS_CR_SSCTRL_MASK); + ConfigReg |= InstancePtr->SlaveSelect; + XSpiPs_WriteReg(InstancePtr->Config.BaseAddress, + XSPIPS_CR_OFFSET, ConfigReg); + } + + /* + * Enable the device. + */ + XSpiPs_Enable(InstancePtr); + + /* + * Clear all the interrrupts. + */ + XSpiPs_WriteReg(InstancePtr->Config.BaseAddress, XSPIPS_SR_OFFSET, + XSPIPS_IXR_WR_TO_CLR_MASK); + + /* + * Fill the TXFIFO with as many bytes as it will take (or as many as + * we have to send). + */ + while ((InstancePtr->RemainingBytes > 0U) && + (TransCount < XSPIPS_FIFO_DEPTH)) { + XSpiPs_SendByte(InstancePtr->Config.BaseAddress, + *InstancePtr->SendBufferPtr); + InstancePtr->SendBufferPtr += 1; + InstancePtr->RemainingBytes--; + TransCount++; + } + + /* + * Enable interrupts (connecting to the interrupt controller and + * enabling interrupts should have been done by the caller). + */ + XSpiPs_WriteReg(InstancePtr->Config.BaseAddress, + XSPIPS_IER_OFFSET, XSPIPS_IXR_DFLT_MASK); + + /* + * If master mode and manual start mode, issue manual start command + * to start the transfer. + */ + if ((XSpiPs_IsManualStart(InstancePtr) == TRUE) + && (XSpiPs_IsMaster(InstancePtr) == TRUE)) { + ConfigReg = XSpiPs_ReadReg(InstancePtr->Config.BaseAddress, + XSPIPS_CR_OFFSET); + ConfigReg |= XSPIPS_CR_MANSTRT_MASK; + XSpiPs_WriteReg(InstancePtr->Config.BaseAddress, + XSPIPS_CR_OFFSET, ConfigReg); + } + StatusTransfer = (s32)XST_SUCCESS; + } + return StatusTransfer; +} + +/*****************************************************************************/ +/** +* Transfers specified data on the SPI bus in polled mode. +* +* The caller has the option of providing two different buffers for send and +* receive, or one buffer for both send and receive, or no buffer for receive. +* The receive buffer must be at least as big as the send buffer to prevent +* unwanted memory writes. This implies that the byte count passed in as an +* argument must be the smaller of the two buffers if they differ in size. +* Here are some sample usages: +*
+*   XSpiPs_PolledTransfer(InstancePtr, SendBuf, RecvBuf, ByteCount)
+*	The caller wishes to send and receive, and provides two different
+*	buffers for send and receive.
+*
+*   XSpiPs_PolledTransfer(InstancePtr, SendBuf, NULL, ByteCount)
+*	The caller wishes only to send and does not care about the received
+*	data. The driver ignores the received data in this case.
+*
+*   XSpiPs_PolledTransfer(InstancePtr, SendBuf, SendBuf, ByteCount)
+*	The caller wishes to send and receive, but provides the same buffer
+*	for doing both. The driver sends the data and overwrites the send
+*	buffer with received data as it transfers the data.
+*
+*   XSpiPs_PolledTransfer(InstancePtr, RecvBuf, RecvBuf, ByteCount)
+*	The caller wishes to only receive and does not care about sending
+*	data.  In this case, the caller must still provide a send buffer, but
+*	it can be the same as the receive buffer if the caller does not care
+*	what it sends.  The device must send N bytes of data if it wishes to
+*	receive N bytes of data.
+*
+* 
+* +* @param InstancePtr is a pointer to the XSpiPs instance. +* @param SendBufPtr is a pointer to a buffer of data for sending. +* This buffer must not be NULL. +* @param RecvBufPtr is a pointer to a buffer for received data. +* This argument can be NULL if do not care about receiving. +* @param ByteCount contains the number of bytes to send/receive. +* The number of bytes received always equals the number of bytes +* sent. + +* @return +* - XST_SUCCESS if the buffers are successfully handed off to the +* device for transfer. +* - XST_DEVICE_BUSY indicates that a data transfer is already in +* progress. This is determined by the driver. +* +* @note +* +* This function is not thread-safe. The higher layer software must ensure that +* no two threads are transferring data on the SPI bus at the same time. +* +******************************************************************************/ +s32 XSpiPs_PolledTransfer(XSpiPs *InstancePtr, u8 *SendBufPtr, + u8 *RecvBufPtr, u32 ByteCount) +{ + u32 StatusReg; + u32 ConfigReg; + u32 TransCount; + u32 CheckTransfer; + s32 Status_Polled; + u8 TempData; + + /* + * The RecvBufPtr argument can be NULL. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(SendBufPtr != NULL); + Xil_AssertNonvoid(ByteCount > 0U); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Check whether there is another transfer in progress. Not thread-safe. + */ + if (InstancePtr->IsBusy == TRUE) { + Status_Polled = (s32)XST_DEVICE_BUSY; + } else { + + /* + * Set the busy flag, which will be cleared when the transfer is + * entirely done. + */ + InstancePtr->IsBusy = TRUE; + + /* + * Set up buffer pointers. + */ + InstancePtr->SendBufferPtr = SendBufPtr; + InstancePtr->RecvBufferPtr = RecvBufPtr; + + InstancePtr->RequestedBytes = ByteCount; + InstancePtr->RemainingBytes = ByteCount; + + /* + * If manual chip select mode, initialize the slave select value. + */ + if (XSpiPs_IsManualChipSelect(InstancePtr) == TRUE) { + ConfigReg = XSpiPs_ReadReg(InstancePtr->Config.BaseAddress, + XSPIPS_CR_OFFSET); + /* + * Set the slave select value. + */ + ConfigReg &= (u32)(~XSPIPS_CR_SSCTRL_MASK); + ConfigReg |= InstancePtr->SlaveSelect; + XSpiPs_WriteReg(InstancePtr->Config.BaseAddress, + XSPIPS_CR_OFFSET, ConfigReg); + } + + /* + * Enable the device. + */ + XSpiPs_Enable(InstancePtr); + + while((InstancePtr->RemainingBytes > (u32)0U) || + (InstancePtr->RequestedBytes > (u32)0U)) { + TransCount = 0U; + /* + * Fill the TXFIFO with as many bytes as it will take (or as + * many as we have to send). + */ + while ((InstancePtr->RemainingBytes > (u32)0U) && + ((u32)TransCount < (u32)XSPIPS_FIFO_DEPTH)) { + XSpiPs_SendByte(InstancePtr->Config.BaseAddress, + *InstancePtr->SendBufferPtr); + InstancePtr->SendBufferPtr += 1; + InstancePtr->RemainingBytes--; + ++TransCount; + } + + /* + * If master mode and manual start mode, issue manual start + * command to start the transfer. + */ + if ((XSpiPs_IsManualStart(InstancePtr) == TRUE) + && (XSpiPs_IsMaster(InstancePtr) == TRUE)) { + ConfigReg = XSpiPs_ReadReg( + InstancePtr->Config.BaseAddress, + XSPIPS_CR_OFFSET); + ConfigReg |= XSPIPS_CR_MANSTRT_MASK; + XSpiPs_WriteReg(InstancePtr->Config.BaseAddress, + XSPIPS_CR_OFFSET, ConfigReg); + } + + /* + * Wait for the transfer to finish by polling Tx fifo status. + */ + CheckTransfer = (u32)0U; + while (CheckTransfer == 0U){ + StatusReg = XSpiPs_ReadReg( + InstancePtr->Config.BaseAddress, + XSPIPS_SR_OFFSET); + if ( (StatusReg & XSPIPS_IXR_MODF_MASK) != 0U) { + /* + * Clear the mode fail bit + */ + XSpiPs_WriteReg( + InstancePtr->Config.BaseAddress, + XSPIPS_SR_OFFSET, + XSPIPS_IXR_MODF_MASK); + Status_Polled = (s32)XST_SEND_ERROR; + goto END; + } + CheckTransfer = (StatusReg & + XSPIPS_IXR_TXOW_MASK); + } + + /* + * A transmit has just completed. Process received data and + * check for more data to transmit. + * First get the data received as a result of the transmit + * that just completed. Receive data based on the + * count obtained while filling tx fifo. Always get the + * received data, but only fill the receive buffer if it + * points to something (the upper layer software may not + * care to receive data). + */ + while (TransCount != (u32)0U) { + TempData = (u8)XSpiPs_RecvByte( + InstancePtr->Config.BaseAddress); + if (InstancePtr->RecvBufferPtr != NULL) { + *(InstancePtr->RecvBufferPtr) = TempData; + InstancePtr->RecvBufferPtr += 1; + } + InstancePtr->RequestedBytes--; + --TransCount; + } + } + + /* + * Clear the slave selects now, before terminating the transfer. + */ + if (XSpiPs_IsManualChipSelect(InstancePtr) == TRUE) { + ConfigReg = XSpiPs_ReadReg(InstancePtr->Config.BaseAddress, + XSPIPS_CR_OFFSET); + ConfigReg |= XSPIPS_CR_SSCTRL_MASK; + XSpiPs_WriteReg(InstancePtr->Config.BaseAddress, + XSPIPS_CR_OFFSET, ConfigReg); + } + + /* + * Clear the busy flag. + */ + InstancePtr->IsBusy = FALSE; + + /* + * Disable the device. + */ + XSpiPs_Disable(InstancePtr); + Status_Polled = (s32)XST_SUCCESS; + } + + END: + return Status_Polled; +} + +/*****************************************************************************/ +/** +* +* Selects or deselect the slave with which the master communicates. This setting +* affects the SPI_ss_outN signals. The behavior depends on the setting of the +* CR_SSDECEN bit. If CR_SSDECEN is 0, the SPI_ss_outN bits will be output with a +* single signal low. If CR_SSDECEN is 1, the SPI_ss_outN bits will reflect the +* value set. +* +* The user is not allowed to deselect the slave while a transfer is in progress. +* If no transfer is in progress, the user can select a new slave, which +* implicitly deselects the current slave. In order to explicitly deselect the +* current slave, a value of all 1's, 0x0F can be passed in as the argument to +* the function. +* +* @param InstancePtr is a pointer to the XSpiPs instance. +* @param SlaveSel is the slave number to be selected. +* Normally, 3 slaves can be selected with values 0-2. +* In case, 3-8 decode option is set, then upto 8 slaves +* can be selected. Only one slave can be selected at a time. +* +* @return +* - XST_SUCCESS if the slave is selected or deselected +* successfully. +* - XST_DEVICE_BUSY if a transfer is in progress, slave cannot be +* changed. +* +* @note +* +* This function only sets the slave which will be selected when a transfer +* occurs. The slave is not selected when the SPI is idle. The slave select +* has no affect when the device is configured as a slave. +* +******************************************************************************/ +s32 XSpiPs_SetSlaveSelect(XSpiPs *InstancePtr, u8 SlaveSel) +{ + u32 ConfigReg; + s32 Status_Slave; + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(SlaveSel <= XSPIPS_CR_SSCTRL_MAXIMUM); + + /* + * Do not allow the slave select to change while a transfer is in + * progress. Not thread-safe. + */ + if (InstancePtr->IsBusy == TRUE) { + Status_Slave = (s32)XST_DEVICE_BUSY; + } else { + /* + * If decode slave select option is set, + * then set slave select value directly. + * Update the Instance structure member. + */ + if ( XSpiPs_IsDecodeSSelect( InstancePtr ) == TRUE) { + InstancePtr->SlaveSelect = ((u32)SlaveSel) << XSPIPS_CR_SSCTRL_SHIFT; + } + else { + /* + * Set the bit position to low using SlaveSel. Update the Instance + * structure member. + */ + InstancePtr->SlaveSelect = ((~(1U << SlaveSel)) & \ + XSPIPS_CR_SSCTRL_MAXIMUM) << XSPIPS_CR_SSCTRL_SHIFT; + } + + /* + * Read the config register, update the slave select value and write + * back to config register. + */ + ConfigReg = XSpiPs_ReadReg(InstancePtr->Config.BaseAddress, + XSPIPS_CR_OFFSET); + ConfigReg &= (u32)(~XSPIPS_CR_SSCTRL_MASK); + ConfigReg |= InstancePtr->SlaveSelect; + XSpiPs_WriteReg(InstancePtr->Config.BaseAddress, XSPIPS_CR_OFFSET, + ConfigReg); + Status_Slave = (s32)XST_SUCCESS; + } + return Status_Slave; +} + +/*****************************************************************************/ +/** +* +* Gets the current slave select setting for the SPI device. +* +* @param InstancePtr is a pointer to the XSpiPs instance. +* +* @return The slave number selected (starting from 0). +* +* @note None. +* +******************************************************************************/ +u8 XSpiPs_GetSlaveSelect(const XSpiPs *InstancePtr) +{ + u32 ConfigReg; + u32 SlaveSel; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + ConfigReg = InstancePtr->SlaveSelect; + ConfigReg &= XSPIPS_CR_SSCTRL_MASK; + ConfigReg >>= XSPIPS_CR_SSCTRL_SHIFT; + ConfigReg &= XSPIPS_CR_SSCTRL_MAXIMUM; + + /* + * If decode slave select option is set, then read value directly. + */ + if ( XSpiPs_IsDecodeSSelect( InstancePtr ) == TRUE) { + SlaveSel = ConfigReg; + } + else { + + /* + * Get the slave select value + */ + if(ConfigReg == 0x0FU) { + /* + * No slave selected + */ + SlaveSel = 0xFU; + }else { + /* + * Get selected slave number (0,1 or 2) + */ + SlaveSel = ((~ConfigReg) & XSPIPS_CR_SSCTRL_MAXIMUM)/2U; + } + } + return (u8)SlaveSel; +} + +/*****************************************************************************/ +/** +* +* Sets the status callback function, the status handler, which the driver +* calls when it encounters conditions that should be reported to upper +* layer software. The handler executes in an interrupt context, so it must +* minimize the amount of processing performed. One of the following status +* events is passed to the status handler. +* +*
+* XST_SPI_MODE_FAULT		A mode fault error occurred, meaning the device
+*				is selected as slave while being a master.
+*
+* XST_SPI_TRANSFER_DONE		The requested data transfer is done
+*
+* XST_SPI_TRANSMIT_UNDERRUN	As a slave device, the master clocked data
+*				but there were none available in the transmit
+*				register/FIFO. This typically means the slave
+*				application did not issue a transfer request
+*				fast enough, or the processor/driver could not
+*				fill the transmit register/FIFO fast enough.
+*
+* XST_SPI_RECEIVE_OVERRUN	The SPI device lost data. Data was received
+*				but the receive data register/FIFO was full.
+*
+* XST_SPI_SLAVE_MODE_FAULT	A slave SPI device was selected as a slave
+*				while it was disabled. This indicates the
+*				master is already transferring data (which is
+*				being dropped until the slave application
+*				issues a transfer).
+* 
+* @param InstancePtr is a pointer to the XSpiPs instance. +* @param CallBackRef is the upper layer callback reference passed back +* when the callback function is invoked. +* @param FunctionPtr is the pointer to the callback function. +* +* @return None. +* +* @note +* +* The handler is called within interrupt context, so it should do its work +* quickly and queue potentially time-consuming work to a task-level thread. +* +******************************************************************************/ +void XSpiPs_SetStatusHandler(XSpiPs *InstancePtr, void *CallBackRef, + XSpiPs_StatusHandler FunctionPtr) +{ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(FunctionPtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + InstancePtr->StatusHandler = FunctionPtr; + InstancePtr->StatusRef = CallBackRef; +} + +/*****************************************************************************/ +/** +* +* This is a stub for the status callback. The stub is here in case the upper +* layers forget to set the handler. +* +* @param CallBackRef is a pointer to the upper layer callback reference +* @param StatusEvent is the event that just occurred. +* @param ByteCount is the number of bytes transferred up until the event +* occurred. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +static void StubStatusHandler(const void *CallBackRef, u32 StatusEvent, + u32 ByteCount) +{ + (const void) CallBackRef; + (void) StatusEvent; + (void) ByteCount; + + Xil_AssertVoidAlways(); +} + +/*****************************************************************************/ +/** +* +* The interrupt handler for SPI interrupts. This function must be connected +* by the user to an interrupt controller. +* +* The interrupts that are handled are: +* +* - Mode Fault Error. This interrupt is generated if this device is selected +* as a slave when it is configured as a master. The driver aborts any data +* transfer that is in progress by resetting FIFOs (if present) and resetting +* its buffer pointers. The upper layer software is informed of the error. +* +* - Data Transmit Register (FIFO) Empty. This interrupt is generated when the +* transmit register or FIFO is empty. The driver uses this interrupt during a +* transmission to continually send/receive data until the transfer is done. +* +* - Data Transmit Register (FIFO) Underflow. This interrupt is generated when +* the SPI device, when configured as a slave, attempts to read an empty +* DTR/FIFO. An empty DTR/FIFO usually means that software is not giving the +* device data in a timely manner. No action is taken by the driver other than +* to inform the upper layer software of the error. +* +* - Data Receive Register (FIFO) Overflow. This interrupt is generated when the +* SPI device attempts to write a received byte to an already full DRR/FIFO. +* A full DRR/FIFO usually means software is not emptying the data in a timely +* manner. No action is taken by the driver other than to inform the upper +* layer software of the error. +* +* - Slave Mode Fault Error. This interrupt is generated if a slave device is +* selected as a slave while it is disabled. No action is taken by the driver +* other than to inform the upper layer software of the error. +* +* @param InstancePtr is a pointer to the XSpiPs instance. +* +* @return None. +* +* @note +* +* The slave select register is being set to deselect the slave when a transfer +* is complete. This is being done regardless of whether it is a slave or a +* master since the hardware does not drive the slave select as a slave. +* +******************************************************************************/ +void XSpiPs_InterruptHandler(XSpiPs *InstancePtr) +{ + XSpiPs *SpiPtr = InstancePtr; + u32 IntrStatus; + u32 ConfigReg; + u32 BytesDone; /* Number of bytes done so far. */ + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(SpiPtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Immediately clear the interrupts in case the ISR causes another + * interrupt to be generated. If we clear at the end of the ISR, + * we may miss newly generated interrupts. + * Disable the TXOW interrupt because we transmit from within the ISR, + * which could potentially cause another TX_OW interrupt. + */ + IntrStatus = + XSpiPs_ReadReg(SpiPtr->Config.BaseAddress, XSPIPS_SR_OFFSET); + XSpiPs_WriteReg(SpiPtr->Config.BaseAddress, XSPIPS_SR_OFFSET, + (IntrStatus & XSPIPS_IXR_WR_TO_CLR_MASK)); + XSpiPs_WriteReg(SpiPtr->Config.BaseAddress, XSPIPS_IDR_OFFSET, + XSPIPS_IXR_TXOW_MASK); + + /* + * Check for mode fault error. We want to check for this error first, + * before checking for progress of a transfer, since this error needs + * to abort any operation in progress. + */ + if ((u32)XSPIPS_IXR_MODF_MASK == (u32)(IntrStatus & XSPIPS_IXR_MODF_MASK)) { + BytesDone = SpiPtr->RequestedBytes - SpiPtr->RemainingBytes; + + /* + * Abort any operation currently in progress. This includes + * clearing the mode fault condition by reading the status + * register. Note that the status register should be read after + * the abort, since reading the status register clears the mode + * fault condition and would cause the device to restart any + * transfer that may be in progress. + */ + XSpiPs_Abort(SpiPtr); + + SpiPtr->StatusHandler(SpiPtr->StatusRef, XST_SPI_MODE_FAULT, + BytesDone); + + goto END; /* Do not continue servicing other interrupts. */ + } + + + if ((IntrStatus & XSPIPS_IXR_TXOW_MASK) != 0U) { + u8 TempData; + u32 TransCount; + /* + * A transmit has just completed. Process received data and + * check for more data to transmit. + * First get the data received as a result of the transmit that + * just completed. Always get the received data, but only fill + * the receive buffer if it is not null (it can be null when + * the device does not care to receive data). + * Initialize the TransCount based on the requested bytes. + * Loop on receive FIFO based on TransCount. + */ + TransCount = SpiPtr->RequestedBytes - SpiPtr->RemainingBytes; + + while (TransCount != 0U) { + TempData = (u8)XSpiPs_RecvByte(SpiPtr->Config.BaseAddress); + if (SpiPtr->RecvBufferPtr != NULL) { + *SpiPtr->RecvBufferPtr = TempData; + SpiPtr->RecvBufferPtr += 1; + } + SpiPtr->RequestedBytes--; + --TransCount; + } + + /* + * Fill the TXFIFO until data exists, otherwise fill upto + * FIFO depth. + */ + while ((SpiPtr->RemainingBytes > 0U) && + (TransCount < XSPIPS_FIFO_DEPTH)) { + XSpiPs_SendByte(SpiPtr->Config.BaseAddress, + *SpiPtr->SendBufferPtr); + SpiPtr->SendBufferPtr += 1; + SpiPtr->RemainingBytes--; + ++TransCount; + } + + if ((SpiPtr->RemainingBytes == 0U) && + (SpiPtr->RequestedBytes == 0U)) { + /* + * No more data to send. Disable the interrupt and + * inform the upper layer software that the transfer + * is done. The interrupt will be re-enabled when + * another transfer is initiated. + */ + XSpiPs_WriteReg(SpiPtr->Config.BaseAddress, + XSPIPS_IDR_OFFSET, XSPIPS_IXR_DFLT_MASK); + + /* + * Disable slave select lines as the transfer + * is complete. + */ + if (XSpiPs_IsManualChipSelect(InstancePtr) == TRUE) { + ConfigReg = XSpiPs_ReadReg( + SpiPtr->Config.BaseAddress, + XSPIPS_CR_OFFSET); + ConfigReg |= XSPIPS_CR_SSCTRL_MASK; + XSpiPs_WriteReg( + SpiPtr->Config.BaseAddress, + XSPIPS_CR_OFFSET, ConfigReg); + } + + /* + * Clear the busy flag. + */ + SpiPtr->IsBusy = FALSE; + + /* + * Disable the device. + */ + XSpiPs_Disable(SpiPtr); + + /* + * Inform the Transfer done to upper layers. + */ + SpiPtr->StatusHandler(SpiPtr->StatusRef, + XST_SPI_TRANSFER_DONE, + SpiPtr->RequestedBytes); + } else { + /* + * Enable the TXOW interrupt. + */ + XSpiPs_WriteReg(SpiPtr->Config.BaseAddress, + XSPIPS_IER_OFFSET, XSPIPS_IXR_TXOW_MASK); + /* + * Start the transfer by not inhibiting the transmitter + * any longer. + */ + if ((XSpiPs_IsManualStart(SpiPtr) == TRUE) + && (XSpiPs_IsMaster(SpiPtr) == TRUE)) { + ConfigReg = XSpiPs_ReadReg( + SpiPtr->Config.BaseAddress, + XSPIPS_CR_OFFSET); + ConfigReg |= XSPIPS_CR_MANSTRT_MASK; + XSpiPs_WriteReg( + SpiPtr->Config.BaseAddress, + XSPIPS_CR_OFFSET, ConfigReg); + } + } + } + + /* + * Check for overflow and underflow errors. + */ + if ((IntrStatus & XSPIPS_IXR_RXOVR_MASK) != 0U) { + BytesDone = SpiPtr->RequestedBytes - SpiPtr->RemainingBytes; + SpiPtr->IsBusy = FALSE; + + /* + * The Slave select lines are being manually controlled. + * Disable them because the transfer is complete. + */ + if (XSpiPs_IsManualChipSelect(SpiPtr) == TRUE) { + ConfigReg = XSpiPs_ReadReg( + SpiPtr->Config.BaseAddress, + XSPIPS_CR_OFFSET); + ConfigReg |= XSPIPS_CR_SSCTRL_MASK; + XSpiPs_WriteReg( + SpiPtr->Config.BaseAddress, + XSPIPS_CR_OFFSET, ConfigReg); + } + + SpiPtr->StatusHandler(SpiPtr->StatusRef, + XST_SPI_RECEIVE_OVERRUN, BytesDone); + } + + if ((IntrStatus & XSPIPS_IXR_TXUF_MASK) != 0U) { + BytesDone = SpiPtr->RequestedBytes - SpiPtr->RemainingBytes; + + SpiPtr->IsBusy = FALSE; + /* + * The Slave select lines are being manually controlled. + * Disable them because the transfer is complete. + */ + if (XSpiPs_IsManualChipSelect(SpiPtr) == TRUE) { + ConfigReg = XSpiPs_ReadReg( + SpiPtr->Config.BaseAddress, + XSPIPS_CR_OFFSET); + ConfigReg |= XSPIPS_CR_SSCTRL_MASK; + XSpiPs_WriteReg( + SpiPtr->Config.BaseAddress, + XSPIPS_CR_OFFSET, ConfigReg); + } + + SpiPtr->StatusHandler(SpiPtr->StatusRef, + XST_SPI_TRANSMIT_UNDERRUN, BytesDone); + } + + END: + return; + +} + +/*****************************************************************************/ +/** +* +* Aborts a transfer in progress by disabling the device and resetting the FIFOs +* if present. The byte counts are cleared, the busy flag is cleared, and mode +* fault is cleared. +* +* @param InstancePtr is a pointer to the XSpiPs instance. +* +* @return None. +* +* @note +* +* This function does a read/modify/write of the Config register. The user of +* this function needs to take care of critical sections. +* +******************************************************************************/ +void XSpiPs_Abort(XSpiPs *InstancePtr) +{ + + u8 Temp; + u32 Check; +#if !defined(versal) + u32 Count; +#endif + XSpiPs_Disable(InstancePtr); + + /* + * Clear the RX FIFO and drop any data. + */ + Check = (XSpiPs_ReadReg(InstancePtr->Config.BaseAddress, + XSPIPS_SR_OFFSET) & XSPIPS_IXR_RXNEMPTY_MASK); + while (Check != (u32)0U) { + Temp = (u8)XSpiPs_RecvByte(InstancePtr->Config.BaseAddress); + if(Temp != (u8)0U){ + } + Check = (XSpiPs_ReadReg(InstancePtr->Config.BaseAddress, + XSPIPS_SR_OFFSET) & XSPIPS_IXR_RXNEMPTY_MASK); + } + + /* + * Read all RX_FIFO entries + */ +#if !defined(versal) + for (Count = 0U; Count < XSPIPS_FIFO_DEPTH; Count++) { + (void)XSpiPs_ReadReg(InstancePtr->Config.BaseAddress, + XSPIPS_RXD_OFFSET); + } +#endif + /* + * Clear mode fault condition. + */ + XSpiPs_WriteReg(InstancePtr->Config.BaseAddress, + XSPIPS_SR_OFFSET, + XSPIPS_IXR_MODF_MASK); + + InstancePtr->RemainingBytes = 0U; + InstancePtr->RequestedBytes = 0U; + InstancePtr->IsBusy = FALSE; +} + +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/spips_v3_2/src/xspips.h b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/spips_v3_2/src/xspips.h new file mode 100644 index 0000000..1daee72 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/spips_v3_2/src/xspips.h @@ -0,0 +1,703 @@ +/****************************************************************************** +* +* Copyright (C) 2017 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xspips.h +* @addtogroup spips_v3_2 +* @{ +* @details +* +* This file contains the implementation of the XSpiPs driver. It works for +* both the master and slave mode. User documentation for the driver functions +* is contained in this file in the form of comment blocks at the front of each +* function. +* +* An SPI device connects to an SPI bus through a 4-wire serial interface. +* The SPI bus is a full-duplex, synchronous bus that facilitates communication +* between one master and one slave. The device is always full-duplex, +* which means that for every byte sent, one is received, and vice-versa. +* The master controls the clock, so it can regulate when it wants to +* send or receive data. The slave is under control of the master, it must +* respond quickly since it has no control of the clock and must send/receive +* data as fast or as slow as the master does. +* +* Initialization & Configuration +* +* The XSpiPs_Config structure is used by the driver to configure itself. This +* configuration structure is typically created by the tool-chain based on HW +* build properties. +* +* To support multiple runtime loading and initialization strategies employed by +* various operating systems, the driver instance can be initialized in the +* following way: +* - XSpiPs_LookupConfig(DeviceId) - Use the devide identifier to find the +* static configuration structure defined in xspips_g.c. This is setup by +* the tools. For some operating systems the config structure will be +* initialized by the software and this call is not needed. +* - XSpiPs_CfgInitialize(InstancePtr, CfgPtr, EffectiveAddr) - Uses a +* configuration structure provided by the caller. If running in a system +* with address translation, the provided virtual memory base address +* replaces the physical address present in the configuration structure. +* +* Multiple Masters +* +* More than one master can exist, but arbitration is the responsibility of +* the higher layer software. The device driver does not perform any type of +* arbitration. +* +* Multiple Slaves +* +* Contention between multiple masters is detected by the hardware, in which +* case a mode fault occurs on the device. The device is disabled immediately +* by hardware, and the current word transfer is stopped. The Aborted word +* transfer due to the mode fault is resumed once the devie is enabled again. +* +* Modes of Operation +* +* There are four modes to perform a data transfer and the selection of a mode +* is based on Chip Select(CS) and Start. These two options individually, can +* be controlled either by software(Manual) or hardware(Auto). +* - Auto CS: Chip select is automatically asserted as soon as the first word +* is written into the TXFIFO and deasserted when the TXFIFO becomes +* empty +* - Manual CS: Software must assert and deassert CS. +* - Auto Start: Data transmission starts as soon as there is data in the +* TXFIFO and stalls when the TXFIFO is empty +* - Manual Start: Software must start data transmission at the beginning of +* the transaction or whenever the TXFIFO has become empty +* +* The preferred combination is Manual CS and Auto Start. +* In this combination, the software asserts CS before loading any data into +* TXFIFO. In Auto Start mode, whenever data is in TXFIFO, controller sends it +* out until TXFIFO becomes empty. The software reads the RXFIFO whenever the +* data is available. If no further data, software disables CS. +* +* Risks/challenges of other combinations: +* - Manual CS and Manual Start: Manual Start bit should be set after each +* TXFIFO write otherwise there could be a race condition where the TXFIFO +* becomes empty before the new word is written. In that case the +* transmission stops. +* - Auto CS with Manual or Auto Start: It is very difficult for software to +* keep the TXFIFO filled. Whenever the TXFIFO runs empty, CS is deasserted. +* This results in a single transaction to be split into multiple pieces each +* with its own chip select. This will result in garbage data to be sent. +* +* Interrupts +* +* The user must connect the interrupt handler of the driver, +* XSpiPs_InterruptHandler, to an interrupt system such that it will be +* called when an interrupt occurs. This function does not save and restore +* the processor context such that the user must provide this processing. +* +* The driver handles the following interrupts: +* - Data Transmit Register/FIFO Underflow +* - Data Receive Register/FIFO Full +* - Data Receive Register/FIFO Not Empty +* - Data Transmit Register/FIFO Full +* - Data Transmit Register/FIFO Overwater +* - Mode Fault Error +* - Data Receive Register/FIFO Overrun +* +* The Data Transmit Register/FIFO Overwater interrupt -- indicates that the +* SPI device has transmitted the data available to transmit, and now its data +* register and FIFO is ready to accept more data. The driver uses this +* interrupt to indicate progress while sending data. The driver may have +* more data to send, in which case the data transmit register and FIFO is +* filled for subsequent transmission. When this interrupt arrives and all +* the data has been sent, the driver invokes the status callback with a +* value of XST_SPI_TRANSFER_DONE to inform the upper layer software that +* all data has been sent. +* +* The Data Transmit Register/FIFO Underflow interrupt -- indicates that, +* as slave, the SPI device was required to transmit but there was no data +* available to transmit in the transmit register (or FIFO). This may not +* be an error if the master is not expecting data. But in the case where +* the master is expecting data, this serves as a notification of such a +* condition. The driver reports this condition to the upper layer +* software through the status handler. +* +* The Data Receive Register/FIFO Overrun interrupt -- indicates that the SPI +* device received data and subsequently dropped the data because the data +* receive register and FIFO was full. The interrupt applies to both master +* and slave operation. The driver reports this condition to the upper layer +* software through the status handler. This likely indicates a problem with +* the higher layer protocol, or a problem with the slave performance. +* +* The Mode Fault Error interrupt -- indicates that while configured as a +* master, the device was selected as a slave by another master. This can be +* used by the application for arbitration in a multimaster environment or to +* indicate a problem with arbitration. When this interrupt occurs, the +* driver invokes the status callback with a status value of +* XST_SPI_MODE_FAULT. It is up to the application to resolve the conflict. +* When configured as a slave, Mode Fault Error interrupt indicates that a slave +* device was selected as a slave by a master, but the slave device was +* disabled. When configured as a master, Mode Fault Error interrupt indicates +* that another SPI device is acting as a master on the bus. +* +* +* Polled Operation +* +* Transfer in polled mode is supported through a separate interface function +* XSpiPs_PolledTransfer(). Unlike the transfer function in the interrupt mode, +* this function blocks until all data has been sent/received. +* +* Device Busy +* +* Some operations are disallowed when the device is busy. The driver tracks +* whether a device is busy. The device is considered busy when a data transfer +* request is outstanding, and is considered not busy only when that transfer +* completes (or is aborted with a mode fault error). This applies to both +* master and slave devices. +* +* Device Configuration +* +* The device can be configured in various ways during the FPGA implementation +* process. Configuration parameters are stored in the xspips_g.c file or +* passed in via XSpiPs_CfgInitialize(). A table is defined where each entry +* contains configuration information for an SPI device, including the base +* address for the device. +* +* RTOS Independence +* +* This driver is intended to be RTOS and processor independent. It works with +* physical addresses only. Any needs for dynamic memory management, threads or +* thread mutual exclusion, virtual memory, or cache control must be satisfied +* by the layer above this driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ------ -------- -----------------------------------------------
+* 1.00	drg/jz 01/25/10 First release
+* 1.00	sdm    10/25/11 Removed the Divide by 2 in the SPI Clock Prescaler
+*			options as this is not supported in the device.
+* 1.01	sg     03/07/12 Updated the code to always clear the relevant bits
+*			before writing to config register.
+*			Always clear the slave select bits before write and
+*			clear the bits to no slave at the end of transfer
+*			Modified the Polled transfer transmit/receive logic.
+*			Tx should wait on TXOW Interrupt and Rx on RXNEMTY.
+* 1.02	sg     05/31/12 Updated XSPIPS_FIFO_DEPTH to 128 from 32 to match HW
+*			for CR 658289
+* 1.03	sg     09/21/12 Added memory barrier dmb in polled transfer and
+*			interrupt handler to overcome the clock domain
+*			crossing issue in the controller. For CR #679252.
+* 1.04a	sg     01/30/13 Created XSPIPS_MANUAL_START_OPTION. Created macros
+*			XSpiPs_IsMaster, XSpiPs_IsManualStart and
+*			XSpiPs_IsManualChipSelect. Changed SPI
+*			Enable/Disable macro argument from BaseAddress to
+*			Instance Pointer. Added DelayNss argument to SetDelays
+*			and GetDelays API's. Added macros to set/get the
+*			RX Watermark value.Created macros XSpiPs_IsMaster,
+*			XSpiPs_IsManualStart and XSpiPs_IsManualChipSelect.
+*			Changed SPI transfer logic for polled and interrupt
+*			modes to be based on filled tx fifo count and receive
+*			based on it. RXNEMPTY interrupt is not used.
+*			SetSlaveSelect API logic is modified to drive the bit
+*			position low based on the slave select value
+*			requested. GetSlaveSelect API will return the value
+*			based on bit position that is low.
+*			Created XSPIPS_CR_MODF_GEN_EN_MASK macro and added it
+*			to XSPIPS_CR_RESET_STATE. Created
+* 			XSPIPS_IXR_WR_TO_CLR_MASK for interrupts which need
+*			write-to-clear. Added shift and mask macros for d_nss
+*			parameter. Added Rx Watermark mask.
+* 1.05a hk 	   26/04/13 Added disable and enable in XSpiPs_SetOptions when
+*				CPOL/CPHA bits are set/reset. Fix for CR#707669.
+* 1.06a hk     08/22/13 Changed GetSlaveSelect function. CR# 727866.
+*                       Added masking ConfigReg before writing in SetSlaveSel
+*                       Added extended slave select support - CR#722569.
+*                       Added prototypes of reset API and related constant
+*                       definitions.
+*                       Added check for MODF in polled transfer function.
+* 3.0   vm    12/09/14	Modified driver source code for MISRA-C:2012 compliance.
+*			Support for Zynq Ultrascale Mp added.
+*       ms     03/17/17 Added readme.txt file in examples folder for doxygen
+*                       generation.
+*       ms     04/05/17 Modified Comment lines in functions of spips
+*                       examples to recognize it as documentation block
+*                       for doxygen generation and also modified filename tag
+*                       in eeprom interrupt, eeprom polled and flash polled
+*                       files to include them in doxygen examples.
+* 3.1	tjs    04/12/18 InputClockHz parameter copied in instance for use in
+* 						application. CR#998910
+* 3.2   aru    01/20/19 Fixes violations according to MISRAC-2012
+*                       in safety mode and done changes such as
+*                       Declared the pointer param as Pointer to const.
+* 3.2   nsk    03/26/19 Add support for versal - CR #1025583.
+* 
+* +******************************************************************************/ +#ifndef XSPIPS_H /* prevent circular inclusions */ +#define XSPIPS_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xstatus.h" +#include "xspips_hw.h" + +/************************** Constant Definitions *****************************/ + +/** @name Configuration options + * + * The following options are supported to enable/disable certain features of + * an SPI device. Each of the options is a bit mask, so more than one may be + * specified. + * + * The Master option configures the SPI device as a master. + * By default, the device is a slave. + * + * The Active Low Clock option configures the device's clock polarity. + * Setting this option means the clock is active low and the SCK signal idles + * high. By default, the clock is active high and SCK idles low. + * + * The Clock Phase option configures the SPI device for one of two + * transfer formats. A clock phase of 0, the default, means data is valid on + * the first SCK edge (rising or falling) after the slave select (SS) signal + * has been asserted. A clock phase of 1 means data is valid on the second SCK + * edge (rising or falling) after SS has been asserted. + * + * The Slave Select Decode Enable option selects how the SPI_SS_outN are + * controlled by the SPI Slave Select Decode bits. + * 0: Use this setting for the standard configuration of up to three slave + * select outputs. Only one of the three slave select outputs will be low. + * (Default) + * 1: Use this setting for the optional configuration of an additional decoder + * to support 8 slave select outputs. SPI_SS_outN reflects the value in the + * register. + * + * The SPI Force Slave Select option is used to enable manual control of + * the signals SPI_SS_outN. + * 0: The SPI_SS_outN signals are controlled by the SPI controller during + * transfers. (Default) + * 1: The SPI_SS_outN signal indicated by the Slave Select Control bit is + * forced active (driven low) regardless of any transfers in progress. + * + * NOTE: The driver will handle setting and clearing the Slave Select when + * the user sets the "FORCE_SSELECT_OPTION". Using this option will allow the + * SPI clock to be set to a faster speed. If the SPI clock is too fast, the + * processor cannot empty and refill the FIFOs before the TX FIFO is empty + * When the SPI hardware is controlling the Slave Select signals, this + * will cause slave to be de-selected and terminate the transfer. + * + * The Manual Start option is used to enable manual control of + * the Start command to perform data transfer. + * 0: The Start command is controlled by the SPI controller during + * transfers(Default). Data transmission starts as soon as there is data in + * the TXFIFO and stalls when the TXFIFO is empty + * 1: The Start command must be issued by software to perform data transfer. + * Bit 15 of Configuration register is used to issue Start command. This bit + * must be set whenever TXFIFO is filled with new data. + * + * NOTE: The driver will set the Manual Start Enable bit in Configuration + * Register, if Manual Start option is selected. Software will issue + * Manual Start command whenever TXFIFO is filled with data. When there is + * no further data, driver will clear the Manual Start Enable bit. + * + * @{ + */ +#define XSPIPS_MASTER_OPTION 0x00000001U /**< Master mode option */ +#define XSPIPS_CLK_ACTIVE_LOW_OPTION 0x00000002U /**< Active Low Clock option */ +#define XSPIPS_CLK_PHASE_1_OPTION 0x00000004U /**< Clock Phase one option */ +#define XSPIPS_DECODE_SSELECT_OPTION 0x00000008U /**< Select 16 slaves Option */ +#define XSPIPS_FORCE_SSELECT_OPTION 0x00000010U /**< Force Slave Select */ +#define XSPIPS_MANUAL_START_OPTION 0x00000020U /**< Manual Start mode option */ +/*@}*/ + + +/** @name SPI Clock Prescaler options + * The SPI Clock Prescaler Configuration bits are used to program master mode + * bit rate. The bit rate can be programmed in divide-by-two decrements from + * pclk/4 to pclk/256. + * + * @{ + */ + +#define XSPIPS_CLK_PRESCALE_4 0x01U /**< PCLK/4 Prescaler */ +#define XSPIPS_CLK_PRESCALE_8 0x02U /**< PCLK/8 Prescaler */ +#define XSPIPS_CLK_PRESCALE_16 0x03U /**< PCLK/16 Prescaler */ +#define XSPIPS_CLK_PRESCALE_32 0x04U /**< PCLK/32 Prescaler */ +#define XSPIPS_CLK_PRESCALE_64 0x05U /**< PCLK/64 Prescaler */ +#define XSPIPS_CLK_PRESCALE_128 0x06U /**< PCLK/128 Prescaler */ +#define XSPIPS_CLK_PRESCALE_256 0x07U /**< PCLK/256 Prescaler */ +/*@}*/ + + +/** @name Callback events + * + * These constants specify the handler events that are passed to + * a handler from the driver. These constants are not bit masks such that + * only one will be passed at a time to the handler. + * + * @{ + */ +#define XSPIPS_EVENT_MODE_FAULT 1U /**< Mode fault error */ +#define XSPIPS_EVENT_TRANSFER_DONE 2U /**< Transfer done */ +#define XSPIPS_EVENT_TRANSMIT_UNDERRUN 3U /**< TX FIFO empty */ +#define XSPIPS_EVENT_RECEIVE_OVERRUN 4U /**< Receive data loss because + RX FIFO full */ +/*@}*/ + + +/**************************** Type Definitions *******************************/ +/** + * The handler data type allows the user to define a callback function to + * handle the asynchronous processing for the SPI device. The application + * using this driver is expected to define a handler of this type to support + * interrupt driven mode. The handler executes in an interrupt context, so + * only minimal processing should be performed. + * + * @param CallBackRef is the callback reference passed in by the upper + * layer when setting the callback functions, and passed back to + * the upper layer when the callback is invoked. Its type is + * not important to the driver, so it is a void pointer. + * @param StatusEvent holds one or more status events that have occurred. + * See the XSpiPs_SetStatusHandler() for details on the status + * events that can be passed in the callback. + * @param ByteCount indicates how many bytes of data were successfully + * transferred. This may be less than the number of bytes + * requested if the status event indicates an error. + */ +typedef void (*XSpiPs_StatusHandler) (const void *CallBackRef, u32 StatusEvent, + u32 ByteCount); + +/** + * This typedef contains configuration information for the device. + */ +typedef struct { + u16 DeviceId; /**< Unique ID of device */ + u32 BaseAddress; /**< Base address of the device */ + u32 InputClockHz; /**< Input clock frequency */ +} XSpiPs_Config; + +/** + * The XSpiPs driver instance data. The user is required to allocate a + * variable of this type for every SPI device in the system. A pointer + * to a variable of this type is then passed to the driver API functions. + */ +typedef struct { + XSpiPs_Config Config; /**< Configuration structure */ + u32 IsReady; /**< Device is initialized and ready */ + + u8 *SendBufferPtr; /**< Buffer to send (state) */ + u8 *RecvBufferPtr; /**< Buffer to receive (state) */ + u32 RequestedBytes; /**< Number of bytes to transfer (state) */ + u32 RemainingBytes; /**< Number of bytes left to transfer(state) */ + u32 IsBusy; /**< A transfer is in progress (state) */ + u32 SlaveSelect; /**< The slave select value when + XSPIPS_FORCE_SSELECT_OPTION is set */ + + XSpiPs_StatusHandler StatusHandler; + void *StatusRef; /**< Callback reference for status handler */ + +} XSpiPs; + +/***************** Macros (Inline Functions) Definitions *********************/ +/****************************************************************************/ +/* +* +* Check in OptionsTable if Manual Start Option is enabled or disabled. +* +* @param InstancePtr is a pointer to the XSpiPs instance. +* +* @return +* - TRUE if option is set +* - FALSE if option is not set +* +* @note C-Style signature: +* u8 XSpiPs_IsManualStart(XSpiPs *InstancePtr) +* +*****************************************************************************/ +#define XSpiPs_IsManualStart(InstancePtr) \ + (((XSpiPs_GetOptions(InstancePtr) & \ + XSPIPS_MANUAL_START_OPTION) != (u32)0U) ? TRUE : FALSE) + +/****************************************************************************/ +/* +* +* Check in OptionsTable if Manual Chip Select Option is enabled or disabled. +* +* @param InstancePtr is a pointer to the XSpiPs instance. +* +* @return +* - TRUE if option is set +* - FALSE if option is not set +* +* @note C-Style signature: +* u8 XSpiPs_IsManualChipSelect(XSpiPs *InstancePtr) +* +*****************************************************************************/ +#define XSpiPs_IsManualChipSelect(InstancePtr) \ + (((XSpiPs_GetOptions(InstancePtr) & \ + XSPIPS_FORCE_SSELECT_OPTION) != (u32)0U) ? TRUE : FALSE) + +/****************************************************************************/ +/* +* +* Check in OptionsTable if Decode Slave Select option is enabled or disabled. +* +* @param InstancePtr is a pointer to the XSpiPs instance. +* +* @return +* - TRUE if option is set +* - FALSE if option is not set +* +* @note C-Style signature: +* u8 XSpiPs_IsDecodeSSelect(XSpiPs *InstancePtr) +* +*****************************************************************************/ +#define XSpiPs_IsDecodeSSelect(InstancePtr) \ + (((XSpiPs_GetOptions(InstancePtr) & \ + XSPIPS_DECODE_SSELECT_OPTION) != (u32)0U) ? TRUE : FALSE) + +/****************************************************************************/ +/* +* +* Check in OptionsTable if Master Option is enabled or disabled. +* +* @param InstancePtr is a pointer to the XSpiPs instance. +* +* @return +* - TRUE if option is set +* - FALSE if option is not set +* +* @note C-Style signature: +* u8 XSpiPs_IsMaster(XSpiPs *InstancePtr) +* +*****************************************************************************/ +#define XSpiPs_IsMaster(InstancePtr) \ + (((XSpiPs_GetOptions(InstancePtr) & \ + XSPIPS_MASTER_OPTION) != (u32)0U) ? TRUE : FALSE) + +/****************************************************************************/ +/** +* +* Set the contents of the slave idle count register. +* +* @param InstancePtr is a pointer to the XSpiPs instance. +* @param RegisterValue is the value to be writen, valid values are +* 0-255. +* +* @return None +* +* @note +* C-Style signature: +* void XSpiPs_SetSlaveIdle(XSpiPs *InstancePtr, u32 RegisterValue) +* +*****************************************************************************/ +#define XSpiPs_SetSlaveIdle(InstancePtr, RegisterValue) \ + XSpiPs_Out32(((InstancePtr)->Config.BaseAddress) + \ + XSPIPS_SICR_OFFSET, (RegisterValue)) + +/****************************************************************************/ +/** +* +* Get the contents of the slave idle count register. Use the XSPIPS_SICR_* +* constants defined in xspips_hw.h to interpret the bit-mask returned. +* +* @param InstancePtr is a pointer to the XSpiPs instance. +* +* @return 8-bit value representing the contents of the SIC register. +* +* @note C-Style signature: +* u32 XSpiPs_GetSlaveIdle(XSpiPs *InstancePtr) +* +*****************************************************************************/ +#define XSpiPs_GetSlaveIdle(InstancePtr) \ + XSpiPs_In32(((InstancePtr)->Config.BaseAddress) + \ + XSPIPS_SICR_OFFSET) + +/****************************************************************************/ +/** +* +* Set the contents of the transmit FIFO watermark register. +* +* @param InstancePtr is a pointer to the XSpiPs instance. +* @param RegisterValue is the value to be written, valid values +* are 1-128. +* +* @return None. +* +* @note +* C-Style signature: +* void XSpiPs_SetTXWatermark(XSpiPs *InstancePtr, u32 RegisterValue) +* +*****************************************************************************/ +#define XSpiPs_SetTXWatermark(InstancePtr, RegisterValue) \ + XSpiPs_Out32(((InstancePtr)->Config.BaseAddress) + \ + XSPIPS_TXWR_OFFSET, (RegisterValue)) + +/****************************************************************************/ +/** +* +* Get the contents of the transmit FIFO watermark register. +* Use the XSPIPS_TXWR_* constants defined xspips_hw.h to interpret +* the bit-mask returned. +* +* @param InstancePtr is a pointer to the XSpiPs instance. +* +* @return 8-bit value representing the contents of the TXWR register. +* +* @note C-Style signature: +* u32 XSpiPs_GetTXWatermark(u32 *InstancePtr) +* +*****************************************************************************/ +#define XSpiPs_GetTXWatermark(InstancePtr) \ + XSpiPs_In32(((InstancePtr)->Config.BaseAddress) + XSPIPS_TXWR_OFFSET) + +/****************************************************************************/ +/** +* +* Set the contents of the receive FIFO watermark register. +* +* @param InstancePtr is a pointer to the XSpiPs instance. +* @param RegisterValue is the value to be written, valid values +* are 1-128. +* +* @return None. +* +* @note +* C-Style signature: +* void XSpiPs_SetRXWatermark(XSpiPs *InstancePtr, u32 RegisterValue) +* +*****************************************************************************/ +#define XSpiPs_SetRXWatermark(InstancePtr, RegisterValue) \ + XSpiPs_Out32(((InstancePtr)->Config.BaseAddress) + \ + XSPIPS_RXWR_OFFSET, (RegisterValue)) + +/****************************************************************************/ +/** +* +* Get the contents of the receive FIFO watermark register. +* Use the XSPIPS_RXWR_* constants defined xspips_hw.h to interpret +* the bit-mask returned. +* +* @param InstancePtr is a pointer to the XSpiPs instance. +* +* @return A 8-bit value representing the contents of the RXWR register. +* +* @note C-Style signature: +* u32 XSpiPs_GetRXWatermark(u32 *InstancePtr) +* +*****************************************************************************/ +#define XSpiPs_GetRXWatermark(InstancePtr) \ + XSpiPs_In32(((InstancePtr)->Config.BaseAddress) + XSPIPS_RXWR_OFFSET) + +/****************************************************************************/ +/** +* +* Enable the device and uninhibit master transactions. +* +* @param InstancePtr is a pointer to the XSpiPs instance. +* +* @return None. +* +* @note C-Style signature: +* void XSpiPs_Enable(u32 *InstancePtr) +* +*****************************************************************************/ +#define XSpiPs_Enable(InstancePtr) \ + XSpiPs_Out32(((InstancePtr)->Config.BaseAddress) + XSPIPS_ER_OFFSET, \ + XSPIPS_ER_ENABLE_MASK) + +/****************************************************************************/ +/** +* +* Disable the device. +* +* @param InstancePtr is a pointer to the XSpiPs instance. +* +* @return None. +* +* @note C-Style signature: +* void XSpiPs_Disable(u32 *InstancePtr) +* +*****************************************************************************/ +#define XSpiPs_Disable(InstancePtr) \ + XSpiPs_Out32(((InstancePtr)->Config.BaseAddress) + XSPIPS_ER_OFFSET, 0U) + +/************************** Function Prototypes ******************************/ + +/* + * Initialization function, implemented in xspips_sinit.c + */ +XSpiPs_Config *XSpiPs_LookupConfig(u16 DeviceId); + +/* + * Functions implemented in xspips.c + */ +s32 XSpiPs_CfgInitialize(XSpiPs *InstancePtr, const XSpiPs_Config * ConfigPtr, + u32 EffectiveAddr); + +void XSpiPs_Reset(XSpiPs *InstancePtr); + +s32 XSpiPs_Transfer(XSpiPs *InstancePtr, u8 *SendBufPtr, u8 *RecvBufPtr, + u32 ByteCount); + +s32 XSpiPs_PolledTransfer(XSpiPs *InstancePtr, u8 *SendBufPtr, + u8 *RecvBufPtr, u32 ByteCount); + +void XSpiPs_SetStatusHandler(XSpiPs *InstancePtr, void *CallBackRef, + XSpiPs_StatusHandler FunctionPtr); +void XSpiPs_InterruptHandler(XSpiPs *InstancePtr); + +void XSpiPs_Abort(XSpiPs *InstancePtr); + +s32 XSpiPs_SetSlaveSelect(XSpiPs *InstancePtr, u8 SlaveSel); +u8 XSpiPs_GetSlaveSelect(const XSpiPs *InstancePtr); + +/* + * Functions for selftest, in xspips_selftest.c + */ +s32 XSpiPs_SelfTest(XSpiPs *InstancePtr); + +/* + * Functions for options, in xspips_options.c + */ +s32 XSpiPs_SetOptions(const XSpiPs *InstancePtr, u32 Options); +u32 XSpiPs_GetOptions(const XSpiPs *InstancePtr); + +s32 XSpiPs_SetClkPrescaler(const XSpiPs *InstancePtr, u8 Prescaler); +u8 XSpiPs_GetClkPrescaler(const XSpiPs *InstancePtr); + +s32 XSpiPs_SetDelays(const XSpiPs *InstancePtr, u8 DelayNss, u8 DelayBtwn, + u8 DelayAfter, u8 DelayInit); +void XSpiPs_GetDelays(const XSpiPs *InstancePtr, u8 *DelayNss, u8 *DelayBtwn, + u8 *DelayAfter, u8 *DelayInit); +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/spips_v3_2/src/xspips_g.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/spips_v3_2/src/xspips_g.c new file mode 100644 index 0000000..138556a --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/spips_v3_2/src/xspips_g.c @@ -0,0 +1,52 @@ + +/******************************************************************* +* +* CAUTION: This file is automatically generated by HSI. +* Version: 2019.1.3 +* DO NOT EDIT. +* +* Copyright (C) 2010-2023 Xilinx, Inc. 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 +*XILINX 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. +* +*Except as contained in this notice, the name of the Xilinx shall not be used +*in advertising or otherwise to promote the sale, use or other dealings in +*this Software without prior written authorization from Xilinx. +* + +* +* Description: Driver configuration +* +*******************************************************************/ + +#include "xparameters.h" +#include "xspips.h" + +/* +* The configuration table for devices +*/ + +XSpiPs_Config XSpiPs_ConfigTable[XPAR_XSPIPS_NUM_INSTANCES] = +{ + { + XPAR_PS7_SPI_0_DEVICE_ID, + XPAR_PS7_SPI_0_BASEADDR, + XPAR_PS7_SPI_0_SPI_CLK_FREQ_HZ + } +}; + + diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/spips_v3_2/src/xspips_hw.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/spips_v3_2/src/xspips_hw.c new file mode 100644 index 0000000..ede1d7c --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/spips_v3_2/src/xspips_hw.c @@ -0,0 +1,143 @@ +/****************************************************************************** +* +* Copyright (C) 2013 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xspips_hw.c +* @addtogroup spips_v3_2 +* @{ +* +* Contains the reset and post boot rom state initialization. +* Function prototypes in xspips_hw.h +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ------ -------- -----------------------------------------------
+* 1.06a hk     08/22/13 First release.
+* 3.00  kvn    02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.02  raw    11/23/15 Updated XSpiPs_ResetHw() to read all RXFIFO
+* 			entries. This change is to tackle CR#910231.
+* 3.1   tjs    11/23/18 Added a check for A72 and R5 processor to
+*                       avoid changes made for the workaround DT#842463.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xspips_hw.h" + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Variable Definitions *****************************/ + + +/*****************************************************************************/ +/** +* +* Resets the spi module +* +* @param BaseAddress is the base address of the device. +* +* @return None +* +* @note None. +* +******************************************************************************/ +void XSpiPs_ResetHw(u32 BaseAddress) +{ + u32 Check; +#if !defined(versal) + u32 Count; +#endif + + /* + * Disable Interrupts + */ + XSpiPs_WriteReg(BaseAddress, XSPIPS_IDR_OFFSET, + XSPIPS_IXR_DISABLE_ALL_MASK); + + /* + * Disable device + */ + XSpiPs_WriteReg(BaseAddress, XSPIPS_ER_OFFSET, + 0U); + /* + * Write default value to RX and TX threshold registers + * RX threshold should be set to 1 here as the corresponding + * status bit is used to clear the FIFO next + */ + XSpiPs_WriteReg(BaseAddress, XSPIPS_TXWR_OFFSET, + (XSPIPS_TXWR_RESET_VALUE & XSPIPS_TXWR_MASK)); + XSpiPs_WriteReg(BaseAddress, XSPIPS_RXWR_OFFSET, + (XSPIPS_RXWR_RESET_VALUE & XSPIPS_RXWR_MASK)); + + /* + * Clear RXFIFO + */ + Check = (XSpiPs_ReadReg(BaseAddress,XSPIPS_SR_OFFSET) & + XSPIPS_IXR_RXNEMPTY_MASK); + while (Check != 0U) { + (void)XSpiPs_ReadReg(BaseAddress, XSPIPS_RXD_OFFSET); + Check = (XSpiPs_ReadReg(BaseAddress,XSPIPS_SR_OFFSET) & + XSPIPS_IXR_RXNEMPTY_MASK); + } + + /* + * Read all RXFIFO entries + */ +#if !defined(versal) + for (Count = 0U; Count < XSPIPS_FIFO_DEPTH; Count++) { + (void)XSpiPs_ReadReg(BaseAddress, XSPIPS_RXD_OFFSET); + } +#endif + /* + * Clear status register by writing 1 to the write to clear bits + */ + XSpiPs_WriteReg(BaseAddress, XSPIPS_SR_OFFSET, + XSPIPS_IXR_WR_TO_CLR_MASK); + + /* + * Write default value to configuration register + * De-select all slaves + */ + XSpiPs_WriteReg(BaseAddress, XSPIPS_CR_OFFSET, + XSPIPS_CR_RESET_STATE | + XSPIPS_CR_SSCTRL_MASK); + +} +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/spips_v3_2/src/xspips_hw.h b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/spips_v3_2/src/xspips_hw.h new file mode 100644 index 0000000..07b0687 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/spips_v3_2/src/xspips_hw.h @@ -0,0 +1,309 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xspips_hw.h +* @addtogroup spips_v3_2 +* @{ +* +* This header file contains the identifiers and basic driver functions (or +* macros) that can be used to access the device. Other driver functions +* are defined in xspips.h. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ------ -------- -----------------------------------------------
+* 1.00   drg/jz 01/25/10 First release
+* 1.02a  sg     05/31/12 Updated XSPIPS_FIFO_DEPTH to 128 from 32 to match HW
+*			 for CR 658289
+* 1.04a	 sg     01/30/13 Created XSPIPS_CR_MODF_GEN_EN_MASK macro and added it
+*			 to XSPIPS_CR_RESET_STATE. Created
+* 			 XSPIPS_IXR_WR_TO_CLR_MASK for interrupts which need
+*			 write-to-clear. Added shift and mask macros for d_nss
+*			 parameter. Added Rx Watermark mask.
+* 1.06a hk      08/22/13 Added prototypes of reset API and related constant
+*                        definitions.
+* 3.00  kvn     02/13/15 Modified code for MISRA-C:2012 compliance.
+*
+* 
+* +******************************************************************************/ + +#ifndef XSPIPS_HW_H /* prevent circular inclusions */ +#define XSPIPS_HW_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_io.h" + +/************************** Constant Definitions *****************************/ + +/** @name Register Map + * + * Register offsets from the base address of an SPI device. + * @{ + */ +#define XSPIPS_CR_OFFSET 0x00U /**< Configuration */ +#define XSPIPS_SR_OFFSET 0x04U /**< Interrupt Status */ +#define XSPIPS_IER_OFFSET 0x08U /**< Interrupt Enable */ +#define XSPIPS_IDR_OFFSET 0x0CU /**< Interrupt Disable */ +#define XSPIPS_IMR_OFFSET 0x10U /**< Interrupt Enabled Mask */ +#define XSPIPS_ER_OFFSET 0x14U /**< Enable/Disable Register */ +#define XSPIPS_DR_OFFSET 0x18U /**< Delay Register */ +#define XSPIPS_TXD_OFFSET 0x1CU /**< Data Transmit Register */ +#define XSPIPS_RXD_OFFSET 0x20U /**< Data Receive Register */ +#define XSPIPS_SICR_OFFSET 0x24U /**< Slave Idle Count */ +#define XSPIPS_TXWR_OFFSET 0x28U /**< Transmit FIFO Watermark */ +#define XSPIPS_RXWR_OFFSET 0x2CU /**< Receive FIFO Watermark */ +/* @} */ + +/** @name Configuration Register + * + * This register contains various control bits that + * affects the operation of an SPI device. Read/Write. + * @{ + */ +#define XSPIPS_CR_MODF_GEN_EN_MASK 0x00020000U /**< Modefail Generation + Enable */ +#define XSPIPS_CR_MANSTRT_MASK 0x00010000U /**< Manual Transmission Start */ +#define XSPIPS_CR_MANSTRTEN_MASK 0x00008000U /**< Manual Transmission Start + Enable */ +#define XSPIPS_CR_SSFORCE_MASK 0x00004000U /**< Force Slave Select */ +#define XSPIPS_CR_SSCTRL_MASK 0x00003C00U /**< Slave Select Decode */ +#define XSPIPS_CR_SSCTRL_SHIFT 10U /**< Slave Select Decode shift */ +#define XSPIPS_CR_SSCTRL_MAXIMUM 0xFU /**< Slave Select maximum value */ +#define XSPIPS_CR_SSDECEN_MASK 0x00000200U /**< Slave Select Decode Enable */ + +#define XSPIPS_CR_PRESC_MASK 0x00000038U /**< Prescaler Setting */ +#define XSPIPS_CR_PRESC_SHIFT 3U /**< Prescaler shift */ +#define XSPIPS_CR_PRESC_MAXIMUM 0x07U /**< Prescaler maximum value */ + +#define XSPIPS_CR_CPHA_MASK 0x00000004U /**< Phase Configuration */ +#define XSPIPS_CR_CPOL_MASK 0x00000002U /**< Polarity Configuration */ + +#define XSPIPS_CR_MSTREN_MASK 0x00000001U /**< Master Mode Enable */ +#define XSPIPS_CR_RESET_STATE 0x00020000U /**< Mode Fail Generation Enable */ +/* @} */ + + +/** @name SPI Interrupt Registers + * + * SPI Status Register + * + * This register holds the interrupt status flags for an SPI device. Some + * of the flags are level triggered, which means that they are set as long + * as the interrupt condition exists. Other flags are edge triggered, + * which means they are set once the interrupt condition occurs and remain + * set until they are cleared by software. The interrupts are cleared by + * writing a '1' to the interrupt bit position in the Status Register. + * Read/Write. + * + * SPI Interrupt Enable Register + * + * This register is used to enable chosen interrupts for an SPI device. + * Writing a '1' to a bit in this register sets the corresponding bit in the + * SPI Interrupt Mask register. Write only. + * + * SPI Interrupt Disable Register + * + * This register is used to disable chosen interrupts for an SPI device. + * Writing a '1' to a bit in this register clears the corresponding bit in the + * SPI Interrupt Mask register. Write only. + * + * SPI Interrupt Mask Register + * + * This register shows the enabled/disabled interrupts of an SPI device. + * Read only. + * + * All four registers have the same bit definitions. They are only defined once + * for each of the Interrupt Enable Register, Interrupt Disable Register, + * Interrupt Mask Register, and Channel Interrupt Status Register + * @{ + */ + +#define XSPIPS_IXR_TXUF_MASK 0x00000040U /**< Tx FIFO Underflow */ +#define XSPIPS_IXR_RXFULL_MASK 0x00000020U /**< Rx FIFO Full */ +#define XSPIPS_IXR_RXNEMPTY_MASK 0x00000010U /**< Rx FIFO Not Empty */ +#define XSPIPS_IXR_TXFULL_MASK 0x00000008U /**< Tx FIFO Full */ +#define XSPIPS_IXR_TXOW_MASK 0x00000004U /**< Tx FIFO Overwater */ +#define XSPIPS_IXR_MODF_MASK 0x00000002U /**< Mode Fault */ +#define XSPIPS_IXR_RXOVR_MASK 0x00000001U /**< Rx FIFO Overrun */ +#define XSPIPS_IXR_DFLT_MASK 0x00000027U /**< Default interrupts + mask */ +#define XSPIPS_IXR_WR_TO_CLR_MASK 0x00000043U /**< Interrupts which + need write to clear */ +#define XSPIPS_ISR_RESET_STATE 0x04U /**< Default to tx/rx + * reg empty */ +#define XSPIPS_IXR_DISABLE_ALL_MASK 0x00000043U /**< Disable all + * interrupts */ +/* @} */ + + +/** @name Enable Register + * + * This register is used to enable or disable an SPI device. + * Read/Write + * @{ + */ +#define XSPIPS_ER_ENABLE_MASK 0x00000001U /**< SPI Enable Bit Mask */ +/* @} */ + + +/** @name Delay Register + * + * This register is used to program timing delays in + * slave mode. Read/Write + * @{ + */ +#define XSPIPS_DR_NSS_MASK 0xFF000000U /**< Delay for slave select + * de-assertion between + * word transfers mask */ +#define XSPIPS_DR_NSS_SHIFT 24U /**< Delay for slave select + * de-assertion between + * word transfers shift */ +#define XSPIPS_DR_BTWN_MASK 0x00FF0000U /**< Delay Between Transfers mask */ +#define XSPIPS_DR_BTWN_SHIFT 16U /**< Delay Between Transfers shift */ +#define XSPIPS_DR_AFTER_MASK 0x0000FF00U /**< Delay After Transfers mask */ +#define XSPIPS_DR_AFTER_SHIFT 8U /**< Delay After Transfers shift */ +#define XSPIPS_DR_INIT_MASK 0x000000FFU /**< Delay Initially mask */ +/* @} */ + + +/** @name Slave Idle Count Registers + * + * This register defines the number of pclk cycles the slave waits for a the + * SPI clock to become stable in quiescent state before it can detect the start + * of the next transfer in CPHA = 1 mode. + * Read/Write + * + * @{ + */ +#define XSPIPS_SICR_MASK 0x000000FFU /**< Slave Idle Count Mask */ +/* @} */ + + + +/** @name Transmit FIFO Watermark Register + * + * This register defines the watermark setting for the Transmit FIFO. The + * transmit FIFO is 128 bytes deep, so the register is 7 bits. Valid values + * are 1 to 128. + * + * @{ + */ +#define XSPIPS_TXWR_MASK 0x0000007FU /**< Transmit Watermark Mask */ +#define XSPIPS_TXWR_RESET_VALUE 0x00000001U /**< Transmit Watermark + * register reset value */ +/* @} */ + +/** @name Receive FIFO Watermark Register + * + * This register defines the watermark setting for the Receive FIFO. The + * receive FIFO is 128 bytes deep, so the register is 7 bits. Valid values + * are 1 to 128. + * + * @{ + */ +#define XSPIPS_RXWR_MASK 0x0000007FU /**< Receive Watermark Mask */ +#define XSPIPS_RXWR_RESET_VALUE 0x00000001U /**< Receive Watermark + * register reset value */ +/* @} */ + +/** @name FIFO Depth + * + * This macro provides the depth of transmit FIFO and receive FIFO. + * + * @{ + */ +#define XSPIPS_FIFO_DEPTH 128U /**< FIFO depth of Tx and Rx */ +/* @} */ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +#define XSpiPs_In32 Xil_In32 +#define XSpiPs_Out32 Xil_Out32 + +/****************************************************************************/ +/** +* Read a register. +* +* @param BaseAddress contains the base address of the device. +* @param RegOffset contains the offset from the 1st register of the +* device to the target register. +* +* @return The value read from the register. +* +* @note C-Style signature: +* u32 XSpiPs_ReadReg(u32 BaseAddress. int RegOffset) +* +******************************************************************************/ +#define XSpiPs_ReadReg(BaseAddress, RegOffset) \ + XSpiPs_In32((BaseAddress) + (RegOffset)) + +/***************************************************************************/ +/** +* Write to a register. +* +* @param BaseAddress contains the base address of the device. +* @param RegOffset contains the offset from the 1st register of the +* device to target register. +* @param RegisterValue is the value to be written to the register. +* +* @return None. +* +* @note C-Style signature: +* void XSpiPs_WriteReg(u32 BaseAddress, int RegOffset, +* u32 RegisterValue) +* +******************************************************************************/ +#define XSpiPs_WriteReg(BaseAddress, RegOffset, RegisterValue) \ + XSpiPs_Out32((BaseAddress) + (RegOffset), (RegisterValue)) + +/************************** Function Prototypes ******************************/ + +void XSpiPs_ResetHw(u32 BaseAddress); + +/************************** Variable Definitions *****************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/spips_v3_2/src/xspips_options.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/spips_v3_2/src/xspips_options.c new file mode 100644 index 0000000..b5710aa --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/spips_v3_2/src/xspips_options.c @@ -0,0 +1,431 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xspips_options.c +* @addtogroup spips_v3_2 +* @{ +* +* Contains functions for the configuration of the XSpiPs driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ------ -------- -----------------------------------------------
+* 1.00  drg/jz 01/25/10 First release
+* 1.00	sdm    10/25/11 Removed the Divide by 2 in the SPI Clock Prescaler
+*			options as this is not supported in the device
+* 1.04a	sg     01/30/13 Added XSPIPS_MANUAL_START_OPTION. SetDelays and
+*			GetDelays API's include DelayNss parameter.
+* 1.05a hk 	   26/04/13 Added disable and enable in XSpiPs_SetOptions when
+*				CPOL/CPHA bits are set/reset. Fix for CR#707669.
+* 3.00  kvn    02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.2   aru    01/20/19 Fixes violations according to MISRAC-2012
+*                       in safety mode and done changes such as
+*                       Declared the pointer param as Pointer to const
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xspips.h" + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + + +/************************** Variable Definitions *****************************/ + +/* + * Create the table of options which are processed to get/set the device + * options. These options are table driven to allow easy maintenance and + * expansion of the options. + */ +typedef struct { + u32 Option; + u32 Mask; +} OptionsMap; + +static OptionsMap OptionsTable[] = { + {XSPIPS_MASTER_OPTION, XSPIPS_CR_MSTREN_MASK}, + {XSPIPS_CLK_ACTIVE_LOW_OPTION, XSPIPS_CR_CPOL_MASK}, + {XSPIPS_CLK_PHASE_1_OPTION, XSPIPS_CR_CPHA_MASK}, + {XSPIPS_DECODE_SSELECT_OPTION, XSPIPS_CR_SSDECEN_MASK}, + {XSPIPS_FORCE_SSELECT_OPTION, XSPIPS_CR_SSFORCE_MASK}, + {XSPIPS_MANUAL_START_OPTION, XSPIPS_CR_MANSTRTEN_MASK} +}; + +#define XSPIPS_NUM_OPTIONS (sizeof(OptionsTable) / sizeof(OptionsMap)) + +/*****************************************************************************/ +/** +* +* This function sets the options for the SPI device driver. The options control +* how the device behaves relative to the SPI bus. The device must be idle +* rather than busy transferring data before setting these device options. +* +* @param InstancePtr is a pointer to the XSpiPs instance. +* @param Options contains the specified options to be set. This is a bit +* mask where a 1 means to turn the option on, and a 0 means to +* turn the option off. One or more bit values may be contained in +* the mask. See the bit definitions named XSPIPS_*_OPTIONS in the +* file xspips.h. +* +* @return +* - XST_SUCCESS if options are successfully set. +* - XST_DEVICE_BUSY if the device is currently transferring data. +* The transfer must complete or be aborted before setting options. +* +* @note +* This function is not thread-safe. +* +******************************************************************************/ +s32 XSpiPs_SetOptions(const XSpiPs *InstancePtr, u32 Options) +{ + u32 ConfigReg; + u32 Index; + u32 CurrentConfigReg; + s32 Status; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Do not allow the slave select to change while a transfer is in + * progress. Not thread-safe. + */ + if (InstancePtr->IsBusy == TRUE) { + Status = (s32)XST_DEVICE_BUSY; + } else { + + ConfigReg = XSpiPs_ReadReg(InstancePtr->Config.BaseAddress, + XSPIPS_CR_OFFSET); + + CurrentConfigReg = ConfigReg; + + /* + * Loop through the options table, turning the option on or off + * depending on whether the bit is set in the incoming options flag. + */ + for (Index = 0U; Index < XSPIPS_NUM_OPTIONS; Index++) { + if ((Options & OptionsTable[Index].Option) != (u32)0U) { + /* Turn it on */ + ConfigReg |= OptionsTable[Index].Mask; + } + else { + /* Turn it off */ + ConfigReg &= ~(OptionsTable[Index].Mask); + } + } + + + /* + * If CPOL-CPHA bits are toggled from previous state, + * disable before writing the configuration register and then enable. + */ + if( ((CurrentConfigReg & XSPIPS_CR_CPOL_MASK) != + (ConfigReg & XSPIPS_CR_CPOL_MASK)) || + ((CurrentConfigReg & XSPIPS_CR_CPHA_MASK) != + (ConfigReg & XSPIPS_CR_CPHA_MASK)) ) { + XSpiPs_Disable(InstancePtr); + } + + /* + * Now write the Config register. Leave it to the upper layers + * to restart the device. + */ + XSpiPs_WriteReg(InstancePtr->Config.BaseAddress, + XSPIPS_CR_OFFSET, ConfigReg); + + /* + * Enable + */ + if( ((CurrentConfigReg & XSPIPS_CR_CPOL_MASK) != + (ConfigReg & XSPIPS_CR_CPOL_MASK)) || + ((CurrentConfigReg & XSPIPS_CR_CPHA_MASK) != + (ConfigReg & XSPIPS_CR_CPHA_MASK)) ) { + XSpiPs_Enable(InstancePtr); + } + + Status = (s32)XST_SUCCESS; + } + return Status; +} + +/*****************************************************************************/ +/** +* +* This function gets the options for the SPI device. The options control how +* the device behaves relative to the SPI bus. +* +* @param InstancePtr is a pointer to the XSpiPs instance. +* +* @return +* +* Options contains the specified options currently set. This is a bit value +* where a 1 means the option is on, and a 0 means the option is off. +* See the bit definitions named XSPIPS_*_OPTIONS in file xspips.h. +* +* @note None. +* +******************************************************************************/ +u32 XSpiPs_GetOptions(const XSpiPs *InstancePtr) +{ + u32 OptionsFlag = 0U; + u32 ConfigReg; + u32 Index; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Get the current options + */ + ConfigReg = + XSpiPs_ReadReg(InstancePtr->Config.BaseAddress, + XSPIPS_CR_OFFSET); + + /* + * Loop through the options table to grab options + */ + for (Index = 0U; Index < XSPIPS_NUM_OPTIONS; Index++) { + if ((ConfigReg & OptionsTable[Index].Mask) != FALSE) { + OptionsFlag |= OptionsTable[Index].Option; + } + } + + return OptionsFlag; +} + +/*****************************************************************************/ +/** +* +* This function sets the clock prescaler for an SPI device. The device +* must be idle rather than busy transferring data before setting these device +* options. +* +* @param InstancePtr is a pointer to the XSpiPs instance. +* @param Prescaler is the value that determine how much the clock should +* be divided by. Use the XSPIPS_CLK_PRESCALE_* constants defined +* in xspips.h for this setting. +* +* @return +* - XST_SUCCESS if options are successfully set. +* - XST_DEVICE_BUSY if the device is currently transferring data. +* The transfer must complete or be aborted before setting options. +* +* @note +* This function is not thread-safe. +* +******************************************************************************/ +s32 XSpiPs_SetClkPrescaler(const XSpiPs *InstancePtr, u8 Prescaler) +{ + u32 ConfigReg; + s32 Status; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid((Prescaler > 0U) && (Prescaler <= XSPIPS_CR_PRESC_MAXIMUM)); + + /* + * Do not allow the prescaler to be changed while a transfer is in + * progress. Not thread-safe. + */ + if (InstancePtr->IsBusy == TRUE) { + Status = (s32)XST_DEVICE_BUSY; + } else { + + /* + * Read the Config register, mask out the interesting bits, and set + * them with the shifted value passed into the function. Write the + * results back to the Config register. + */ + ConfigReg = XSpiPs_ReadReg(InstancePtr->Config.BaseAddress, + XSPIPS_CR_OFFSET); + + ConfigReg &= (u32)(~XSPIPS_CR_PRESC_MASK); + ConfigReg |= (u32) ((u32)Prescaler & (u32)XSPIPS_CR_PRESC_MAXIMUM) << + XSPIPS_CR_PRESC_SHIFT; + + XSpiPs_WriteReg(InstancePtr->Config.BaseAddress, + XSPIPS_CR_OFFSET, + ConfigReg); + + Status = (s32)XST_SUCCESS; + } + return Status; +} + +/*****************************************************************************/ +/** +* +* This function gets the clock prescaler of an SPI device. +* +* @param InstancePtr is a pointer to the XSpiPs instance. +* +* @return The prescaler value. +* +* @note None. +* +* +******************************************************************************/ +u8 XSpiPs_GetClkPrescaler(const XSpiPs *InstancePtr) +{ + u32 ConfigReg; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + ConfigReg = XSpiPs_ReadReg(InstancePtr->Config.BaseAddress, + XSPIPS_CR_OFFSET); + + ConfigReg &= XSPIPS_CR_PRESC_MASK; + + return (u8)(ConfigReg >> XSPIPS_CR_PRESC_SHIFT); + +} + +/*****************************************************************************/ +/** +* +* This function sets the delay register for the SPI device driver. +* The delay register controls the Delay Between Transfers, Delay After +* Transfers, and the Delay Initially. The default value is 0x0. The range of +* each delay value is 0-255. +* +* @param InstancePtr is a pointer to the XSpiPs instance. +* @param DelayNss is the delay for which the chip select outputs will +* be de-asserted between words when CPHA=0. +* @param DelayBtwn is the delay between one Slave Select being +* de-activated and the activation of another slave. The delay is +* the number of master clock periods given by DelayBtwn + 2. +* @param DelayAfter define the delay between the last bit of the current +* byte transfer and the first bit of the next byte transfer. +* The delay in number of master clock periods is given as: +* CPHA=0:DelayInit+DelayAfter+3 +* CPHA=1:DelayAfter+1 +* @param DelayInit is the delay between asserting the slave select signal +* and the first bit transfer. The delay int number of master clock +* periods is DelayInit+1. +* +* @return +* - XST_SUCCESS if delays are successfully set. +* - XST_DEVICE_BUSY if the device is currently transferring data. +* The transfer must complete or be aborted before setting options. +* +* @note None. +* +******************************************************************************/ +s32 XSpiPs_SetDelays(const XSpiPs *InstancePtr, u8 DelayNss, u8 DelayBtwn, + u8 DelayAfter, u8 DelayInit) +{ + u32 DelayRegister; + s32 Status; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Do not allow the delays to change while a transfer is in + * progress. Not thread-safe. + */ + if (InstancePtr->IsBusy == TRUE) { + Status = (s32)XST_DEVICE_BUSY; + } else { + + /* Shift, Mask and OR the values to build the register settings */ + DelayRegister = (u32) DelayNss << XSPIPS_DR_NSS_SHIFT; + DelayRegister |= (u32) DelayBtwn << XSPIPS_DR_BTWN_SHIFT; + DelayRegister |= (u32) DelayAfter << XSPIPS_DR_AFTER_SHIFT; + DelayRegister |= (u32) DelayInit; + + XSpiPs_WriteReg(InstancePtr->Config.BaseAddress, + XSPIPS_DR_OFFSET, DelayRegister); + + Status = (s32)XST_SUCCESS; + } + return Status; +} + +/*****************************************************************************/ +/** +* +* This function gets the delay settings for an SPI device. +* The delay register controls the Delay Between Transfers, Delay After +* Transfers, and the Delay Initially. The default value is 0x0. +* +* @param InstancePtr is a pointer to the XSpiPs instance. +* @param DelayNss is a pointer to the delay for which the chip select +* outputs will be de-asserted between words when CPHA=0. +* @param DelayBtwn is a pointer to the Delay Between transfers value. +* This is a return parameter. +* @param DelayAfter is a pointer to the Delay After transfer value. +* This is a return parameter. +* @param DelayInit is a pointer to the Delay Initially value. This is +* a return parameter. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XSpiPs_GetDelays(const XSpiPs *InstancePtr,u8 *DelayNss, u8 *DelayBtwn, + u8 *DelayAfter, u8 *DelayInit) +{ + u32 DelayRegister; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + DelayRegister = XSpiPs_ReadReg(InstancePtr->Config.BaseAddress, + XSPIPS_DR_OFFSET); + + *DelayInit = (u8)(DelayRegister & XSPIPS_DR_INIT_MASK); + + *DelayAfter = (u8)((DelayRegister & XSPIPS_DR_AFTER_MASK) >> + XSPIPS_DR_AFTER_SHIFT); + + *DelayBtwn = (u8)((DelayRegister & XSPIPS_DR_BTWN_MASK) >> + XSPIPS_DR_BTWN_SHIFT); + + *DelayNss = (u8)((DelayRegister & XSPIPS_DR_NSS_MASK) >> + XSPIPS_DR_NSS_SHIFT); + +} +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/spips_v3_2/src/xspips_selftest.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/spips_v3_2/src/xspips_selftest.c new file mode 100644 index 0000000..9b62a05 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/spips_v3_2/src/xspips_selftest.c @@ -0,0 +1,163 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xspips_selftest.c +* @addtogroup spips_v3_2 +* @{ +* +* This component contains the implementation of selftest functions for an SPI +* device. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ------ -------- ----------------------------------------------
+* 1.00  drg/jz 01/25/10 First release
+* 1.04a	sg     01/30/13 SetDelays test includes DelayTestNss parameter.
+* 3.00  kvn    02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.2   aru    01/20/19 Fixes violations according to MISRAC-2012
+*                       in safety mode and done changes such as
+*                       Added goto statements.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xspips.h" + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + + +/************************** Variable Definitions *****************************/ + + +/*****************************************************************************/ +/** +* +* Runs a self-test on the driver/device. The self-test is destructive in that +* a reset of the device is performed in order to check the reset values of +* the registers and to get the device into a known state. +* +* Upon successful return from the self-test, the device is reset. +* +* @param InstancePtr is a pointer to the XSpiPs instance. +* +* @return +* - XST_SUCCESS if successful +* - XST_REGISTER_ERROR indicates a register did not read or write +* correctly. +* +* @note None. +* +******************************************************************************/ +s32 XSpiPs_SelfTest(XSpiPs *InstancePtr) +{ + s32 Status; + u32 Register; + u8 DelayTestNss; + u8 DelayTestBtwn; + u8 DelayTestAfter; + u8 DelayTestInit; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Reset the SPI device to leave it in a known good state + */ + XSpiPs_Reset(InstancePtr); + + /* + * All the SPI registers should be in their default state right now. + */ + Register = XSpiPs_ReadReg(InstancePtr->Config.BaseAddress, + XSPIPS_CR_OFFSET); + if (Register != XSPIPS_CR_RESET_STATE) { + Status = (s32)XST_REGISTER_ERROR; + goto END; + } + + Register = XSpiPs_ReadReg(InstancePtr->Config.BaseAddress, + XSPIPS_SR_OFFSET); + if (Register != XSPIPS_ISR_RESET_STATE) { + Status = (s32)XST_REGISTER_ERROR; + goto END;; + } + + DelayTestNss = 0x5AU; + DelayTestBtwn = 0xA5U; + DelayTestAfter = 0xAAU; + DelayTestInit = 0x55U; + + /* + * Write and read the delay register, just to be sure there is some + * hardware out there. + */ + Status = XSpiPs_SetDelays(InstancePtr, DelayTestNss, DelayTestBtwn, + DelayTestAfter, DelayTestInit); + if (Status != (s32)XST_SUCCESS) { + goto END; + } + + XSpiPs_GetDelays(InstancePtr, &DelayTestNss, &DelayTestBtwn, + &DelayTestAfter, &DelayTestInit); + if ((0x5AU != DelayTestNss) || (0xA5U != DelayTestBtwn) || + (0xAAU != DelayTestAfter) || (0x55U != DelayTestInit)) { + Status = (s32)XST_REGISTER_ERROR; + goto END; + } + + Status = XSpiPs_SetDelays(InstancePtr, 0U, 0U, 0U, 0U); + if (Status != (s32)XST_SUCCESS) { + goto END; + } + + /* + * Reset the SPI device to leave it in a known good state + */ + XSpiPs_Reset(InstancePtr); + + Status = (s32)XST_SUCCESS; + + END: + return Status; +} +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/spips_v3_2/src/xspips_sinit.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/spips_v3_2/src/xspips_sinit.c new file mode 100644 index 0000000..52c92f5 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/spips_v3_2/src/xspips_sinit.c @@ -0,0 +1,96 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xspips_sinit.c +* @addtogroup spips_v3_2 +* @{ +* +* The implementation of the XSpiPs driver's static initialization +* functionality. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ------ -------- -----------------------------------------------
+* 1.00  drg/jz 01/25/10 First release
+* 3.00  kvn    02/13/15 Modified code for MISRA-C:2012 compliance.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xstatus.h" +#include "xspips.h" +#include "xparameters.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ +extern XSpiPs_Config XSpiPs_ConfigTable[XPAR_XSPIPS_NUM_INSTANCES]; + +/*****************************************************************************/ +/** +* +* Looks up the device configuration based on the unique device ID. A table +* contains the configuration info for each device in the system. +* +* @param DeviceId contains the ID of the device to look up the +* configuration for. +* +* @return +* +* A pointer to the configuration found or NULL if the specified device ID was +* not found. See xspips.h for the definition of XSpiPs_Config. +* +* @note None. +* +******************************************************************************/ +XSpiPs_Config *XSpiPs_LookupConfig(u16 DeviceId) +{ + XSpiPs_Config *CfgPtr = NULL; + u32 Index; + + for (Index = 0U; Index < (u32)XPAR_XSPIPS_NUM_INSTANCES; Index++) { + if (XSpiPs_ConfigTable[Index].DeviceId == DeviceId) { + CfgPtr = &XSpiPs_ConfigTable[Index]; + break; + } + } + return (XSpiPs_Config *)CfgPtr; +} +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/Makefile b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/Makefile new file mode 100644 index 0000000..186606f --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/Makefile @@ -0,0 +1,83 @@ +############################################################################### +# +# Copyright (C) 2011 - 2015 Xilinx, Inc. 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 +# XILINX 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. +# +# Except as contained in this notice, the name of the Xilinx shall not be used +# in advertising or otherwise to promote the sale, use or other dealings in +# this Software without prior written authorization from Xilinx. +# +############################################################################### + +include config.make + +CC=$(COMPILER) +AR=$(ARCHIVER) +CP=cp +COMPILER_FLAGS= +EXTRA_COMPILER_FLAGS= +LIB=libxil.a + +CC_FLAGS = $(subst -pg, -DPROFILING, $(COMPILER_FLAGS)) +ECC_FLAGS = $(subst -pg, -DPROFILING, $(EXTRA_COMPILER_FLAGS)) + +ifeq (($(notdir $(CC))) , arm-xilinx-eabi-gcc) +ECC_FLAGS += -nostartfiles\ + -march=armv7-a \ + -mfloat-abi=soft \ + -mfpu=neon +endif + +ifeq (($(notdir $(CC))) , $(CC)) +ECC_FLAGS += -nostartfiles +endif + +RELEASEDIR=../../../lib +INCLUDEDIR=../../../include +INCLUDES=-I./. -I${INCLUDEDIR} + +OUTS = *.o +OBJECTS = $(addsuffix .o, $(basename $(wildcard *.c))) +ASSEMBLY_OBJECTS = $(addsuffix .o, $(basename $(wildcard *.S))) +INCLUDEFILES=*.h + +libs: $(LIBS) + +standalone_libs: $(LIBSOURCES) + echo "Compiling standalone" + $(CC) $(CC_FLAGS) $(ECC_FLAGS) $(INCLUDES) $^ + $(AR) -r ${RELEASEDIR}/${LIB} ${OBJECTS} ${ASSEMBLY_OBJECTS} + +profile_libs: + $(MAKE) -C profile COMPILER_FLAGS="$(COMPILER_FLAGS)" EXTRA_COMPILER_FLAGS="$(EXTRA_COMPILER_FLAGS)" COMPILER="$(CC)" ARCHIVER="$(AR)" libs + +.PHONY: include +include: standalone_includes profile_includes + +standalone_includes: + ${CP} ${INCLUDEFILES} ${INCLUDEDIR} + +profile_includes: + $(MAKE) -C profile COMPILER_FLAGS="$(COMPILER_FLAGS)" EXTRA_COMPILER_FLAGS="$(EXTRA_COMPILER_FLAGS)" COMPILER="$(CC)" ARCHIVER="$(AR)" include + +clean: + rm -rf ${OBJECTS} + rm -rf ${ASSEMBLY_OBJECTS} + $(MAKE) -C profile COMPILER_FLAGS="$(COMPILER_FLAGS)" EXTRA_COMPILER_FLAGS="$(EXTRA_COMPILER_FLAGS)" COMPILER="$(CC)" ARCHIVER="$(AR)" clean diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/_exit.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/_exit.c new file mode 100644 index 0000000..87271ae --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/_exit.c @@ -0,0 +1,40 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +#include +#include "xil_types.h" + +/* _exit - Simple implementation. Does not return. +*/ +__attribute__((weak)) void _exit (sint32 status) +{ + (void)status; + while (1) { + ; + } +} diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/_open.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/_open.c new file mode 100644 index 0000000..4ef7441 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/_open.c @@ -0,0 +1,50 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +#ifndef UNDEFINE_FILE_OPS +#include +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { + __attribute__((weak)) s32 _open(const char8 *buf, s32 flags, s32 mode); +} +#endif + +/* + * _open -- open a file descriptor. We don't have a filesystem, so + * we return an error. + */ +__attribute__((weak)) s32 _open(const char8 *buf, s32 flags, s32 mode) +{ + (void)buf; + (void)flags; + (void)mode; + errno = EIO; + return (-1); +} +#endif diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/_sbrk.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/_sbrk.c new file mode 100644 index 0000000..1c39e3a --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/_sbrk.c @@ -0,0 +1,61 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +#include +#include "xil_types.h" + +extern u8 _heap_start[]; +extern u8 _heap_end[]; + +#ifdef __cplusplus +extern "C" { + __attribute__((weak)) caddr_t _sbrk ( s32 incr ); +} +#endif + +__attribute__((weak)) caddr_t _sbrk ( s32 incr ) +{ + static u8 *heap = NULL; + u8 *prev_heap; + static u8 *HeapEndPtr = (u8 *)&_heap_end; + caddr_t Status; + + if (heap == NULL) { + heap = (u8 *)&_heap_start; + } + prev_heap = heap; + + if (((heap + incr) <= HeapEndPtr) && (prev_heap != NULL)) { + heap += incr; + Status = (caddr_t) ((void *)prev_heap); + } else { + Status = (caddr_t) -1; + } + + return Status; +} diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/abort.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/abort.c new file mode 100644 index 0000000..78d3839 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/abort.c @@ -0,0 +1,38 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +#include +#include + +/* + * abort -- go out via exit... + */ +__attribute__((weak)) void abort(void) +{ + _exit(1); +} diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/asm_vectors.S b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/asm_vectors.S new file mode 100644 index 0000000..4fbfa2d --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/asm_vectors.S @@ -0,0 +1,199 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file asm_vectors.s +* +* This file contains the initial vector table for the Cortex A9 processor +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who     Date     Changes
+* ----- ------- -------- ---------------------------------------------------
+* 1.00a ecm/sdm 10/20/09 Initial version
+* 3.05a sdm	02/02/12 Save lr when profiling is enabled
+* 3.10a srt     04/18/13 Implemented ARM Erratas. Please refer to file
+*			 'xil_errata.h' for errata description
+* 4.00a pkp	22/01/14 Modified return addresses for interrupt
+*			 handlers (DataAbortHandler and SVCHandler)
+*			 to fix CR#767251
+* 5.1	pkp	05/13/15 Saved the addresses of instruction causing data
+*			 abort and prefetch abort into DataAbortAddr and
+*			 PrefetchAbortAddr for further use to fix CR#854523
+* 5.4	pkp	12/03/15 Added handler for undefined exception
+* 6.8	mus	04/27/18 Removed __ARM_NEON__ flag definition. Now,
+*			 saving/restoring of of HW floating point register
+*			 would be done through newly introduced flag
+*			 FPU_HARD_FLOAT_ABI_ENABLED. This new flag will be
+*			 configured based on the -mfpu-abi option in extra
+*			 compiler flags.
+* 
+* +* @note +* +* None. +* +******************************************************************************/ +#include "xil_errata.h" +#include "bspconfig.h" + +.org 0 +.text + +.globl _vector_table + +.section .vectors +_vector_table: + B _boot + B Undefined + B SVCHandler + B PrefetchAbortHandler + B DataAbortHandler + NOP /* Placeholder for address exception vector*/ + B IRQHandler + B FIQHandler + + +IRQHandler: /* IRQ vector handler */ + + stmdb sp!,{r0-r3,r12,lr} /* state save from compiled code*/ +#if FPU_HARD_FLOAT_ABI_ENABLED + vpush {d0-d7} + vpush {d16-d31} + vmrs r1, FPSCR + push {r1} + vmrs r1, FPEXC + push {r1} +#endif + +#ifdef PROFILING + ldr r2, =prof_pc + subs r3, lr, #0 + str r3, [r2] +#endif + + bl IRQInterrupt /* IRQ vector */ + +#if FPU_HARD_FLOAT_ABI_ENABLED + pop {r1} + vmsr FPEXC, r1 + pop {r1} + vmsr FPSCR, r1 + vpop {d16-d31} + vpop {d0-d7} +#endif + ldmia sp!,{r0-r3,r12,lr} /* state restore from compiled code */ + + + subs pc, lr, #4 /* adjust return */ + + +FIQHandler: /* FIQ vector handler */ + stmdb sp!,{r0-r3,r12,lr} /* state save from compiled code */ +#if FPU_HARD_FLOAT_ABI_ENABLED + vpush {d0-d7} + vpush {d16-d31} + vmrs r1, FPSCR + push {r1} + vmrs r1, FPEXC + push {r1} +#endif + +FIQLoop: + bl FIQInterrupt /* FIQ vector */ + +#if FPU_HARD_FLOAT_ABI_ENABLED + pop {r1} + vmsr FPEXC, r1 + pop {r1} + vmsr FPSCR, r1 + vpop {d16-d31} + vpop {d0-d7} +#endif + ldmia sp!,{r0-r3,r12,lr} /* state restore from compiled code */ + subs pc, lr, #4 /* adjust return */ + + +Undefined: /* Undefined handler */ + stmdb sp!,{r0-r3,r12,lr} /* state save from compiled code */ + ldr r0, =UndefinedExceptionAddr + sub r1, lr, #4 + str r1, [r0] /* Store address of instruction causing undefined exception */ + + bl UndefinedException /* UndefinedException: call C function here */ + ldmia sp!,{r0-r3,r12,lr} /* state restore from compiled code */ + movs pc, lr + +SVCHandler: /* SWI handler */ + stmdb sp!,{r0-r3,r12,lr} /* state save from compiled code */ + + tst r0, #0x20 /* check the T bit */ + ldrneh r0, [lr,#-2] /* Thumb mode */ + bicne r0, r0, #0xff00 /* Thumb mode */ + ldreq r0, [lr,#-4] /* ARM mode */ + biceq r0, r0, #0xff000000 /* ARM mode */ + + bl SWInterrupt /* SWInterrupt: call C function here */ + + ldmia sp!,{r0-r3,r12,lr} /* state restore from compiled code */ + + movs pc, lr /*return to the next instruction after the SWI instruction */ + + +DataAbortHandler: /* Data Abort handler */ +#ifdef CONFIG_ARM_ERRATA_775420 + dsb +#endif + stmdb sp!,{r0-r3,r12,lr} /* state save from compiled code */ + ldr r0, =DataAbortAddr + sub r1, lr, #8 + str r1, [r0] /* Stores instruction causing data abort */ + + bl DataAbortInterrupt /*DataAbortInterrupt :call C function here */ + + ldmia sp!,{r0-r3,r12,lr} /* state restore from compiled code */ + + subs pc, lr, #8 /* points to the instruction that caused the Data Abort exception */ + +PrefetchAbortHandler: /* Prefetch Abort handler */ +#ifdef CONFIG_ARM_ERRATA_775420 + dsb +#endif + stmdb sp!,{r0-r3,r12,lr} /* state save from compiled code */ + ldr r0, =PrefetchAbortAddr + sub r1, lr, #4 + str r1, [r0] /* Stores instruction causing prefetch abort */ + + bl PrefetchAbortInterrupt /* PrefetchAbortInterrupt: call C function here */ + + ldmia sp!,{r0-r3,r12,lr} /* state restore from compiled code */ + + subs pc, lr, #4 /* points to the instruction that caused the Prefetch Abort exception */ + +.end diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/boot.S b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/boot.S new file mode 100644 index 0000000..c8ebfd1 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/boot.S @@ -0,0 +1,492 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2016 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file boot.S +* +* @addtogroup a9_boot_code Cortex A9 Processor Boot Code +* @{ +*

boot.S

+* The boot code performs minimum configuration which is required for an +* application to run starting from processor's reset state. Below is a +* sequence illustrating what all configuration is performed before control +* reaches to main function. +* +* 1. Program vector table base for exception handling +* 2. Invalidate instruction cache, data cache and TLBs +* 3. Program stack pointer for various modes (IRQ, FIQ, supervisor, undefine, +* abort, system) +* 4. Configure MMU with short descriptor translation table format and program +* base address of translation table +* 5. Enable data cache, instruction cache and MMU +* 6. Enable Floating point unit +* 7. Transfer control to _start which clears BSS sections, initializes +* global timer and runs global constructor before jumping to main +* application +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who     Date     Changes
+* ----- ------- -------- ---------------------------------------------------
+* 1.00a ecm/sdm 10/20/09 Initial version
+* 3.06a sgd     05/15/12 Updated L2CC Auxiliary and Tag RAM Latency control
+*			 register settings.
+* 3.06a asa 	06/17/12 Modified the TTBR settings and L2 Cache auxiliary
+*		         register settings.
+* 3.07a asa     07/16/12 Modified the L2 Cache controller settings to improve
+*			 performance. Changed the property of the ".boot"
+*			 section.
+* 3.07a sgd     08/21/12 Modified the L2 Cache controller and cp15 Aux Control
+*               Register settings
+* 3.09a sgd     02/06/13 Updated SLCR l2c Ram Control register to a
+*               value of 0x00020202. Fix for CR 697094 (SI#687034).
+* 3.10a srt     04/18/13 Implemented ARM Erratas. Please refer to file
+*			 'xil_errata.h' for errata description
+* 4.2   pkp	06/19/14 Enabled asynchronous abort exception
+* 5.0	pkp	16/15/14 Modified initialization code to enable scu after
+*			 MMU is enabled
+* 5.1   pkp	05/13/15 Changed the initialization order so to first invalidate
+*			 caches and TLB, enable MMU and caches, then enable SMP
+*			 bit in ACTLR. L2Cache invalidation and enabling of L2Cache
+*			 is done later.
+* 5.4   asa     12/6/15  Added code to initialize SPSR for all relevant modes.
+* 6.0   mus     08/04/16 Added code to detect zynq-7000 base silicon configuration and
+*                        attempt to enable dual core behavior on single cpu zynq-7000s
+*                        devices is prevented from corrupting system behavior.
+* 6.0   mus     08/24/16 Check CPU core before putting cpu1 to reset for single core
+*                        zynq-7000s devices
+*
+* 
+* +* @note +* +* None. +* +******************************************************************************/ + +#include "xparameters.h" +#include "xil_errata.h" + +.globl MMUTable +.global _prestart +.global _boot +.global __stack +.global __irq_stack +.global __supervisor_stack +.global __abort_stack +.global __fiq_stack +.global __undef_stack +.global _vector_table + +.set PSS_L2CC_BASE_ADDR, 0xF8F02000 +.set PSS_SLCR_BASE_ADDR, 0xF8000000 + +.set RESERVED, 0x0fffff00 +.set TblBase , MMUTable +.set LRemap, 0xFE00000F /* set the base address of the peripheral block as not shared */ +.set L2CCWay, (PSS_L2CC_BASE_ADDR + 0x077C) /*(PSS_L2CC_BASE_ADDR + PSS_L2CC_CACHE_INVLD_WAY_OFFSET)*/ +.set L2CCSync, (PSS_L2CC_BASE_ADDR + 0x0730) /*(PSS_L2CC_BASE_ADDR + PSS_L2CC_CACHE_SYNC_OFFSET)*/ +.set L2CCCrtl, (PSS_L2CC_BASE_ADDR + 0x0100) /*(PSS_L2CC_BASE_ADDR + PSS_L2CC_CNTRL_OFFSET)*/ +.set L2CCAuxCrtl, (PSS_L2CC_BASE_ADDR + 0x0104) /*(PSS_L2CC_BASE_ADDR + XPSS_L2CC_AUX_CNTRL_OFFSET)*/ +.set L2CCTAGLatReg, (PSS_L2CC_BASE_ADDR + 0x0108) /*(PSS_L2CC_BASE_ADDR + XPSS_L2CC_TAG_RAM_CNTRL_OFFSET)*/ +.set L2CCDataLatReg, (PSS_L2CC_BASE_ADDR + 0x010C) /*(PSS_L2CC_BASE_ADDR + XPSS_L2CC_DATA_RAM_CNTRL_OFFSET)*/ +.set L2CCIntClear, (PSS_L2CC_BASE_ADDR + 0x0220) /*(PSS_L2CC_BASE_ADDR + XPSS_L2CC_IAR_OFFSET)*/ +.set L2CCIntRaw, (PSS_L2CC_BASE_ADDR + 0x021C) /*(PSS_L2CC_BASE_ADDR + XPSS_L2CC_ISR_OFFSET)*/ + +.set SLCRlockReg, (PSS_SLCR_BASE_ADDR + 0x04) /*(PSS_SLCR_BASE_ADDR + XPSS_SLCR_LOCK_OFFSET)*/ +.set SLCRUnlockReg, (PSS_SLCR_BASE_ADDR + 0x08) /*(PSS_SLCR_BASE_ADDR + XPSS_SLCR_UNLOCK_OFFSET)*/ +.set SLCRL2cRamReg, (PSS_SLCR_BASE_ADDR + 0xA1C) /*(PSS_SLCR_BASE_ADDR + XPSS_SLCR_L2C_RAM_OFFSET)*/ +.set SLCRCPURSTReg, (0xF8000000 + 0x244) /*(XPS_SYS_CTRL_BASEADDR + A9_CPU_RST_CTRL_OFFSET)*/ +.set EFUSEStaus, (0xF800D000 + 0x10) /*(XPS_EFUSE_BASEADDR + EFUSE_STATUS_OFFSET)*/ + +/* workaround for simulation not working when L1 D and I caches,MMU and L2 cache enabled - DT568997 */ +.if SIM_MODE == 1 +.set CRValMmuCac, 0b00000000000000 /* Disable IDC, and MMU */ +.else +.set CRValMmuCac, 0b01000000000101 /* Enable IDC, and MMU */ +.endif + +.set CRValHiVectorAddr, 0b10000000000000 /* Set the Vector address to high, 0xFFFF0000 */ + +.set L2CCAuxControl, 0x72360000 /* Enable all prefetching, Cache replacement policy, Parity enable, + Event monitor bus enable and Way Size (64 KB) */ +.set L2CCControl, 0x01 /* Enable L2CC */ +.set L2CCTAGLatency, 0x0111 /* latency for TAG RAM */ +.set L2CCDataLatency, 0x0121 /* latency for DATA RAM */ + +.set SLCRlockKey, 0x767B /* SLCR lock key */ +.set SLCRUnlockKey, 0xDF0D /* SLCR unlock key */ +.set SLCRL2cRamConfig, 0x00020202 /* SLCR L2C ram configuration */ + +/* Stack Pointer locations for boot code */ +.set Undef_stack, __undef_stack +.set FIQ_stack, __fiq_stack +.set Abort_stack, __abort_stack +.set SPV_stack, __supervisor_stack +.set IRQ_stack, __irq_stack +.set SYS_stack, __stack + +.set vector_base, _vector_table + +.set FPEXC_EN, 0x40000000 /* FPU enable bit, (1 << 30) */ + +.section .boot,"ax" + + +/* this initializes the various processor modes */ + +_prestart: +_boot: + +#if XPAR_CPU_ID==0 + /* only allow cpu0 through */ + mrc p15,0,r1,c0,c0,5 + and r1, r1, #0xf + cmp r1, #0 + beq CheckEFUSE + EndlessLoop0: + wfe + b EndlessLoop0 + +CheckEFUSE: + ldr r0,=EFUSEStaus + ldr r1,[r0] /* Read eFuse setting */ + ands r1,r1,#0x80 /* Check whether device is having single core */ + beq OKToRun + + /* single core device, reset cpu1 */ + ldr r0,=SLCRUnlockReg /* Load SLCR base address base + unlock register */ + ldr r1,=SLCRUnlockKey /* set unlock key */ + str r1, [r0] /* Unlock SLCR */ + + ldr r0,=SLCRCPURSTReg + ldr r1,[r0] /* Read CPU Software Reset Control register */ + orr r1,r1,#0x22 + str r1,[r0] /* Reset CPU1 */ + + ldr r0,=SLCRlockReg /* Load SLCR base address base + lock register */ + ldr r1,=SLCRlockKey /* set lock key */ + str r1, [r0] /* lock SLCR */ + +#elif XPAR_CPU_ID==1 + /* only allow cpu1 through */ + mrc p15,0,r1,c0,c0,5 + and r1, r1, #0xf + cmp r1, #1 + beq CheckEFUSE1 + b EndlessLoop1 + +CheckEFUSE1: + ldr r0,=EFUSEStaus + ldr r1,[r0] /* Read eFuse setting */ + ands r1,r1,#0x80 /* Check whether device is having single core */ + beq OKToRun + EndlessLoop1: + wfe + b EndlessLoop1 +#endif + +OKToRun: + mrc p15, 0, r0, c0, c0, 0 /* Get the revision */ + and r5, r0, #0x00f00000 + and r6, r0, #0x0000000f + orr r6, r6, r5, lsr #20-4 + +#ifdef CONFIG_ARM_ERRATA_742230 + cmp r6, #0x22 /* only present up to r2p2 */ + mrcle p15, 0, r10, c15, c0, 1 /* read diagnostic register */ + orrle r10, r10, #1 << 4 /* set bit #4 */ + mcrle p15, 0, r10, c15, c0, 1 /* write diagnostic register */ +#endif + +#ifdef CONFIG_ARM_ERRATA_743622 + teq r5, #0x00200000 /* only present in r2p* */ + mrceq p15, 0, r10, c15, c0, 1 /* read diagnostic register */ + orreq r10, r10, #1 << 6 /* set bit #6 */ + mcreq p15, 0, r10, c15, c0, 1 /* write diagnostic register */ +#endif + + /* set VBAR to the _vector_table address in linker script */ + ldr r0, =vector_base + mcr p15, 0, r0, c12, c0, 0 + + /*invalidate scu*/ + ldr r7, =0xf8f0000c + ldr r6, =0xffff + str r6, [r7] + + /* Invalidate caches and TLBs */ + mov r0,#0 /* r0 = 0 */ + mcr p15, 0, r0, c8, c7, 0 /* invalidate TLBs */ + mcr p15, 0, r0, c7, c5, 0 /* invalidate icache */ + mcr p15, 0, r0, c7, c5, 6 /* Invalidate branch predictor array */ + bl invalidate_dcache /* invalidate dcache */ + + /* Disable MMU, if enabled */ + mrc p15, 0, r0, c1, c0, 0 /* read CP15 register 1 */ + bic r0, r0, #0x1 /* clear bit 0 */ + mcr p15, 0, r0, c1, c0, 0 /* write value back */ + +#ifdef SHAREABLE_DDR + /* Mark the entire DDR memory as shareable */ + ldr r3, =0x3ff /* 1024 entries to cover 1G DDR */ + ldr r0, =TblBase /* MMU Table address in memory */ + ldr r2, =0x15de6 /* S=b1 TEX=b101 AP=b11, Domain=b1111, C=b0, B=b1 */ +shareable_loop: + str r2, [r0] /* write the entry to MMU table */ + add r0, r0, #0x4 /* next entry in the table */ + add r2, r2, #0x100000 /* next section */ + subs r3, r3, #1 + bge shareable_loop /* loop till 1G is covered */ +#endif + + mrs r0, cpsr /* get the current PSR */ + mvn r1, #0x1f /* set up the irq stack pointer */ + and r2, r1, r0 + orr r2, r2, #0x12 /* IRQ mode */ + msr cpsr, r2 + ldr r13,=IRQ_stack /* IRQ stack pointer */ + bic r2, r2, #(0x1 << 9) /* Set EE bit to little-endian */ + msr spsr_fsxc,r2 + + mrs r0, cpsr /* get the current PSR */ + mvn r1, #0x1f /* set up the supervisor stack pointer */ + and r2, r1, r0 + orr r2, r2, #0x13 /* supervisor mode */ + msr cpsr, r2 + ldr r13,=SPV_stack /* Supervisor stack pointer */ + bic r2, r2, #(0x1 << 9) /* Set EE bit to little-endian */ + msr spsr_fsxc,r2 + + mrs r0, cpsr /* get the current PSR */ + mvn r1, #0x1f /* set up the Abort stack pointer */ + and r2, r1, r0 + orr r2, r2, #0x17 /* Abort mode */ + msr cpsr, r2 + ldr r13,=Abort_stack /* Abort stack pointer */ + bic r2, r2, #(0x1 << 9) /* Set EE bit to little-endian */ + msr spsr_fsxc,r2 + + mrs r0, cpsr /* get the current PSR */ + mvn r1, #0x1f /* set up the FIQ stack pointer */ + and r2, r1, r0 + orr r2, r2, #0x11 /* FIQ mode */ + msr cpsr, r2 + ldr r13,=FIQ_stack /* FIQ stack pointer */ + bic r2, r2, #(0x1 << 9) /* Set EE bit to little-endian */ + msr spsr_fsxc,r2 + + mrs r0, cpsr /* get the current PSR */ + mvn r1, #0x1f /* set up the Undefine stack pointer */ + and r2, r1, r0 + orr r2, r2, #0x1b /* Undefine mode */ + msr cpsr, r2 + ldr r13,=Undef_stack /* Undefine stack pointer */ + bic r2, r2, #(0x1 << 9) /* Set EE bit to little-endian */ + msr spsr_fsxc,r2 + + mrs r0, cpsr /* get the current PSR */ + mvn r1, #0x1f /* set up the system stack pointer */ + and r2, r1, r0 + orr r2, r2, #0x1F /* SYS mode */ + msr cpsr, r2 + ldr r13,=SYS_stack /* SYS stack pointer */ + + /*set scu enable bit in scu*/ + ldr r7, =0xf8f00000 + ldr r0, [r7] + orr r0, r0, #0x1 + str r0, [r7] + + /* enable MMU and cache */ + + ldr r0,=TblBase /* Load MMU translation table base */ + orr r0, r0, #0x5B /* Outer-cacheable, WB */ + mcr 15, 0, r0, c2, c0, 0 /* TTB0 */ + + mvn r0,#0 /* Load MMU domains -- all ones=manager */ + mcr p15,0,r0,c3,c0,0 + + /* Enable mmu, icahce and dcache */ + ldr r0,=CRValMmuCac + mcr p15,0,r0,c1,c0,0 /* Enable cache and MMU */ + dsb /* dsb allow the MMU to start up */ + isb /* isb flush prefetch buffer */ + + /* Write to ACTLR */ + mrc p15, 0, r0, c1, c0, 1 /* Read ACTLR*/ + orr r0, r0, #(0x01 << 6) /* set SMP bit */ + orr r0, r0, #(0x01 ) /* Cache/TLB maintenance broadcast */ + mcr p15, 0, r0, c1, c0, 1 /* Write ACTLR*/ + +/* Invalidate L2 Cache and enable L2 Cache*/ +/* For AMP, assume running on CPU1. Don't initialize L2 Cache (up to Linux) */ +#if USE_AMP!=1 + ldr r0,=L2CCCrtl /* Load L2CC base address base + control register */ + mov r1, #0 /* force the disable bit */ + str r1, [r0] /* disable the L2 Caches */ + + ldr r0,=L2CCAuxCrtl /* Load L2CC base address base + Aux control register */ + ldr r1,[r0] /* read the register */ + ldr r2,=L2CCAuxControl /* set the default bits */ + orr r1,r1,r2 + str r1, [r0] /* store the Aux Control Register */ + + ldr r0,=L2CCTAGLatReg /* Load L2CC base address base + TAG Latency address */ + ldr r1,=L2CCTAGLatency /* set the latencies for the TAG*/ + str r1, [r0] /* store the TAG Latency register Register */ + + ldr r0,=L2CCDataLatReg /* Load L2CC base address base + Data Latency address */ + ldr r1,=L2CCDataLatency /* set the latencies for the Data*/ + str r1, [r0] /* store the Data Latency register Register */ + + ldr r0,=L2CCWay /* Load L2CC base address base + way register*/ + ldr r2, =0xFFFF + str r2, [r0] /* force invalidate */ + + ldr r0,=L2CCSync /* need to poll 0x730, PSS_L2CC_CACHE_SYNC_OFFSET */ + /* Load L2CC base address base + sync register*/ + /* poll for completion */ +Sync: ldr r1, [r0] + cmp r1, #0 + bne Sync + + ldr r0,=L2CCIntRaw /* clear pending interrupts */ + ldr r1,[r0] + ldr r0,=L2CCIntClear + str r1,[r0] + + ldr r0,=SLCRUnlockReg /* Load SLCR base address base + unlock register */ + ldr r1,=SLCRUnlockKey /* set unlock key */ + str r1, [r0] /* Unlock SLCR */ + + ldr r0,=SLCRL2cRamReg /* Load SLCR base address base + l2c Ram Control register */ + ldr r1,=SLCRL2cRamConfig /* set the configuration value */ + str r1, [r0] /* store the L2c Ram Control Register */ + + ldr r0,=SLCRlockReg /* Load SLCR base address base + lock register */ + ldr r1,=SLCRlockKey /* set lock key */ + str r1, [r0] /* lock SLCR */ + + ldr r0,=L2CCCrtl /* Load L2CC base address base + control register */ + ldr r1,[r0] /* read the register */ + mov r2, #L2CCControl /* set the enable bit */ + orr r1,r1,r2 + str r1, [r0] /* enable the L2 Caches */ +#endif + + mov r0, r0 + mrc p15, 0, r1, c1, c0, 2 /* read cp access control register (CACR) into r1 */ + orr r1, r1, #(0xf << 20) /* enable full access for p10 & p11 */ + mcr p15, 0, r1, c1, c0, 2 /* write back into CACR */ + + /* enable vfp */ + fmrx r1, FPEXC /* read the exception register */ + orr r1,r1, #FPEXC_EN /* set VFP enable bit, leave the others in orig state */ + fmxr FPEXC, r1 /* write back the exception register */ + + mrc p15,0,r0,c1,c0,0 /* flow prediction enable */ + orr r0, r0, #(0x01 << 11) /* #0x8000 */ + mcr p15,0,r0,c1,c0,0 + + mrc p15,0,r0,c1,c0,1 /* read Auxiliary Control Register */ + orr r0, r0, #(0x1 << 2) /* enable Dside prefetch */ + orr r0, r0, #(0x1 << 1) /* enable L2 Prefetch hint */ + mcr p15,0,r0,c1,c0,1 /* write Auxiliary Control Register */ + + mrs r0, cpsr /* get the current PSR */ + bic r0, r0, #0x100 /* enable asynchronous abort exception */ + msr cpsr_xsf, r0 + + + b _start /* jump to C startup code */ + and r0, r0, r0 /* no op */ + +.Ldone: b .Ldone /* Paranoia: we should never get here */ + + +/* + ************************************************************************* + * + * invalidate_dcache - invalidate the entire d-cache by set/way + * + * Note: for Cortex-A9, there is no cp instruction for invalidating + * the whole D-cache. Need to invalidate each line. + * + ************************************************************************* + */ +invalidate_dcache: + mrc p15, 1, r0, c0, c0, 1 /* read CLIDR */ + ands r3, r0, #0x7000000 + mov r3, r3, lsr #23 /* cache level value (naturally aligned) */ + beq finished + mov r10, #0 /* start with level 0 */ +loop1: + add r2, r10, r10, lsr #1 /* work out 3xcachelevel */ + mov r1, r0, lsr r2 /* bottom 3 bits are the Cache type for this level */ + and r1, r1, #7 /* get those 3 bits alone */ + cmp r1, #2 + blt skip /* no cache or only instruction cache at this level */ + mcr p15, 2, r10, c0, c0, 0 /* write the Cache Size selection register */ + isb /* isb to sync the change to the CacheSizeID reg */ + mrc p15, 1, r1, c0, c0, 0 /* reads current Cache Size ID register */ + and r2, r1, #7 /* extract the line length field */ + add r2, r2, #4 /* add 4 for the line length offset (log2 16 bytes) */ + ldr r4, =0x3ff + ands r4, r4, r1, lsr #3 /* r4 is the max number on the way size (right aligned) */ + clz r5, r4 /* r5 is the bit position of the way size increment */ + ldr r7, =0x7fff + ands r7, r7, r1, lsr #13 /* r7 is the max number of the index size (right aligned) */ +loop2: + mov r9, r4 /* r9 working copy of the max way size (right aligned) */ +loop3: + orr r11, r10, r9, lsl r5 /* factor in the way number and cache number into r11 */ + orr r11, r11, r7, lsl r2 /* factor in the index number */ + mcr p15, 0, r11, c7, c6, 2 /* invalidate by set/way */ + subs r9, r9, #1 /* decrement the way number */ + bge loop3 + subs r7, r7, #1 /* decrement the index */ + bge loop2 +skip: + add r10, r10, #2 /* increment the cache number */ + cmp r3, r10 + bgt loop1 + +finished: + mov r10, #0 /* swith back to cache level 0 */ + mcr p15, 2, r10, c0, c0, 0 /* select current cache level in cssr */ + dsb + isb + + bx lr + +.end +/** +* @} End of "addtogroup a9_boot_code". +*/ \ No newline at end of file diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/bspconfig.h b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/bspconfig.h new file mode 100644 index 0000000..daa47a5 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/bspconfig.h @@ -0,0 +1,44 @@ + +/******************************************************************* +* +* CAUTION: This file is automatically generated by HSI. +* Version: 2019.1.3 +* DO NOT EDIT. +* +* Copyright (C) 2010-2023 Xilinx, Inc. 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 +*XILINX 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. +* +*Except as contained in this notice, the name of the Xilinx shall not be used +*in advertising or otherwise to promote the sale, use or other dealings in +*this Software without prior written authorization from Xilinx. +* + +* +* Description: Configurations for Standalone BSP +* +*******************************************************************/ + +#ifndef BSPCONFIG_H /* prevent circular inclusions */ +#define BSPCONFIG_H /* by using protection macros */ + +#define MICROBLAZE_PVR_NONE + +/* Definition for hard-float ABI */ +#define FPU_HARD_FLOAT_ABI_ENABLED 1 + +#endif /*end of __BSPCONFIG_H_*/ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/changelog.txt b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/changelog.txt new file mode 100644 index 0000000..cdefb9f --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/changelog.txt @@ -0,0 +1,593 @@ +/***************************************************************************** + * MODIFICATION HISTORY: + * + * Ver Who Date Changes + * ----- ---- -------- --------------------------------------------------- + * 3.02a sdm 05/30/11 Added Xuint64 typedef and XUINT64_MSW/XUINT64_LSW macros + * 3.02a sdm 06/27/11 Added INST_SYNC and DATA_SYNC macros for all the CPUs + * 3.02a sdm 07/07/11 Updated ppc440 boot.S to set guarded bit for all but + * cacheable regions + * Update ppc440/xil_cache.c to use CACHEABLE_REGION_MASK + * generated by the cpu driver, for enabling caches + * 3.02a sdm 07/08/11 Updated microblaze cache flush APIs based on write-back/ + * write-thru caches + * 3.03a sdm 08/20/11 Updated the tag/data RAM latency values for L2CC + * Updated the MMU table to mark OCM in high address space + * as inner cacheable and reserved space as Invalid + * 3.03a sdm 08/20/11 Changes to support FreeRTOS + * Updated the MMU table to mark upper half of the DDR as + * non-cacheable + * Setup supervisor and abort mode stacks + * Do not initialize/enable L2CC in case of AMP + * Initialize UART1 for 9600bps in case of AMP + * 3.03a sdm 08/27/11 Setup abort and supervisor mode stacks and don't init SMC + * in case of AMP + * 3.03a sdm 09/14/11 Added code for performance monitor and L2CC event + * counters + * 3.03a sdm 11/08/11 Updated microblaze xil_cache.h file to include + * xparameters.h file for CR630532 - Xil_DCacheFlush()/ + * Xil_DCacheFlushRange() functions in standalone BSP v3_02a + * for MicroBlaze will invalidate data in the cache instead + * of flushing it for writeback caches + * 3.04a sdm 11/21/11 Updated to initialize stdio device for 115200bps, for PS7 + * 3.04a sdm 01/02/12 Updated to clear cp15 regs with unknown reset values + * Remove redundant dsb/dmb instructions in cache maintenance + * APIs + * Remove redundant dsb in mcr instruction + * 3.04a sdm 01/13/12 Updated MMU table to mark DDR memory as Shareable + * 3.05a sdm 02/02/12 Removed some of the defines as they are being generated through + * driver tcl in xparameters.h. Update the gcc/translationtable.s + * for the QSPI complete address range - DT644567 + * Removed profile directory for armcc compiler and changed + * profiling setting to false in standalone_v2_1_0.tcl file + * Deleting boot.S file after preprocessing for armcc compiler + * 3.05a asa 03/11/12 Updated the function Xil_EnableMMU in file xil_mmu.c to + * invalidate the caches before enabling back the MMU and + * D cache. + * 3.05a asa 04/15/12 Updated the function Xil_SetTlbAttributes in file + * xil_mmu.c. Now we invalidate UTLB, Branch predictor + * array, flush the D-cache before changing the attributes + * in translation table. The user need not call Xil_DisableMMU + * before calling Xil_SetTlbAttributes. + * 3.06a asa/ 06/17/12 Removed the UART initialization for Zynq. For PEEP, the UART + * sgd initialization is present. Changes for this were done in + * uart.c and xil-crt0.s. + * Made changes in xil_io.c to use volatile pointers. + * Made changes in xil_mmu.c to correct the function + * Xil_SetTlbAttributes. + * Changes are made xil-crt0.s to initialize the static + * C++ constructors. + * Changes are made in boot.s, to fix the TTBR settings, + * correct the L2 Cache Auxiliary register settings, L2 cache + * latency settings. + * 3.07a asa/ 07/16/12 Made changes in cortexa9/xtime_l.c, xtime_l.h, sleep.c + * sgd usleep.c to use global timer intstead of CP15. + * Made changes in cortexa9/gcc/translation_table.s to map + * the peripheral devices as shareable device memory. + * Made changes in cortexa9/gcc/xil-crt0.s to initialize + * the global timer. + * Made changes in cortexa9/armcc/boot.S to initialize + * the global timer. + * Made changes in cortexa9/armcc/translation_table.s to + * map the peripheral devices as shareable device memory. + * Made changes in cortexa9/gcc/boot.S to optimize the + * L2 cache settings. Changes the section properties for + * ".mmu_tbl" and ".boot" sections in cortexa9/gcc/boot.S + * and cortexa9/gcc/translation_table.S. + * Made changes in cortexa9/xil_cache.c to change the + * cache invalidation order. + * 3.07a asa 08/17/12 Made changes across files for Cortexa9 to remove + * compilation/linking issues for C++ compiler. + * Made changes in mb_interface.h to remove compilation/ + * linking issues for C++ compiler. + * Added macros for swapb and swaph microblaze instructions + * mb_interface.h + * Remove barrier usage (SYNCHRONIZE_IO) from xil_io.c + * for CortexA9. + * 3.07a asa 08/30/12 Updated for CR 675636 to provide the L2 Base Address + * 3.07a asa 08/31/12 Added xil_printf.h include + * 3.07a sgd 09/18/12 Corrected the L2 cache enable settings + * Corrected L2 cache sequence disable sequence + * 3.07a sgd 10/19/12 SMC NOR and SRAM initialization with compiler option + * 3.09a asa 01/25/13 Updated to push and pop neon registers into stack for + * irq/fiq handling. + * Relocated COUNTS_PER_SECOND from sleep.c to xtime_l.h. This + * fixes the CR #692094. + * 3.09a sgd 02/14/13 Fix for CRs 697094 (SI#687034) and 675552. + * 3.10a srt 04/18/13 Implemented ARM Erratas. + * Cortex A9 Errata - 742230, 743622, 775420, 794073 + * L2Cache PL310 Errata - 588369, 727915, 759370 + * Please refer to file 'xil_errata.h' for errata + * description. + * 3.10a asa 05/04/13 Added support for L2 cache in MicroBlaze BSP. The older + * cache APIs were corresponding to only Layer 1 cache + * memories. New APIs were now added and the existing cache + * related APIs were changed to provide a uniform interface + * to flush/invalidate/enable/disable the complete cache + * system which includes both L1 and L2 caches. The changes + * for these were done in: + * src/microblaze/xil_cache.c and src/microblaze/xil_cache.h + * files. + * Four new files were added for supporting L2 cache. They are: + * microblaze_flush_cache_ext.S-> Flushes L2 cache + * microblaze_flush_cache_ext_range.S -> Flushes a range of + * memory in L2 cache. + * microblaze_invalidate_cache_ext.S-> Invalidates L2 cache + * microblaze_invalidate_cache_ext_range -> Invalidates a + * range of memory in L2 cache. + * These changes are done to implement PR #697214. + * 3.10a asa 05/13/13 Modified cache disable APIs at src/cortexa9/xil_cache.c to + * fix the CR #706464. L2 cache disabling happens independent + * of L1 data cache disable operation. Changes are done in the + * same file in cache handling APIs to do a L2 cache sync + * (poll reg7_?cache_?sync). This fixes CR #700542. + * 3.10a asa 05/20/13 Added API/Macros for enabling and disabling nested + * interrupts for ARM. These are done to fix the CR#699680. + * 3.10a srt 05/20/13 Made changes in cache maintenance APIs to do a proper cach + * sync operation. This fixes the CR# 716781. + * 3.11a asa 09/07/13 Updated armcc specific BSP files to have proper support + * for armcc toolchain. + * Modified asm_vectors.S (gcc) and asm_vectors.s (armcc) to + * fix issues related to NEON context saving. The assembly + * routines for IRQ and FIQ handling are modified. + * Deprecated the older BSP (3.10a). + * 3.11a asa 09/22/13 Fix for CR#732704. Cache APIs are modified to avoid + * various potential issues. Made changes in the function + * Xil_SetAttributes in file xil_mmu.c. + * 3.11a asa 09/23/13 Added files xil_misc_psreset_api.c and xil_misc_psreset_api.h + * in src\cortexa9 and src\microblaze folders. + * 3.11a asa 09/28/13 Modified the cache APIs (src\cortexa9) to fix handling of + * L2 cache sync operation and to fix issues around complete + * L2 cache flush/invalidation by ways. + * 3.12a asa 10/22/13 Modified the files xpseudo_asm_rvct.c and xpseudo_asm_rvct.h + * to fix linking issues with armcc/DS-5. Modified the armcc + * makefile to fix issues. + * 3.12a asa 11/15/13 Fix for CR#754800. It fixes issues around profiling for MB. + * 4.0 hk 12/13/13 Added check for STDOUT_BASEADDRESS where outbyte is used. + * 4.0 pkp 22/01/14 Modified return addresses for interrupt handlers (DataAbortHandler + * and SWIHandler) in asm_vector.S (src\cortexa9\gcc\ and + * src\cortexa9\armcc\) to fix CR#767251 + * 4.0 pkp 24/01/14 Modified cache APIs (Xil_DCacheInvalidateRange and + * Xil_L1DCacheInvalidate) in xil_cache.c (src\cortexa9) to fix the bugs. + * Few cache lines were missed to invalidate when unaligned address + * invalidation was accommodated in Xil_DCacheInvalidateRange. + * In Xil_L1DCacheInvalidate, while invalidating all L1D cache + * stack memory (which contains return address) was invalidated. So + * stack memory is flushed first and then L1D cache is invalidated. + * This is done to fix CR #763829 + * 4.0 adk 22/02/2014 Fixed the CR:775379 removed unnecessay _t(unit32_t etc) from + * mblaze_nt_types.h file and replace uint32_t with u32 in the + * profile_hist.c to fix the above CR. + * 4.1 bss 04/14/14 Updated driver tcl to remove _interrupt_handler.o from libgloss.a + * instead of libxil.a and added prototypes for + * microblaze_invalidate_cache_ext and microblaze_flush_cache_ext in + * mb_interface.h + * 4.1 hk 04/18/14 Add sleep function. + * 4.1 asa 04/21/14 Fix for CR#764881. Added support for msrset and msrclr. Renamed + * some of the *.s files inMB BSP source to *.S. + * 4.1 asa 04/28/14 Fix for CR#772280. Made changes in file cortexa9/gcc/read.c. + * 4.1 bss 04/29/14 Modified driver tcl to use libxil.a if libgloss.a does not exist + * CR#794205 + * 4.1 asa 05/09/14 Fix for CR#798230. Made changes in cortexa9/xil_cache.c and + * common/xil_testcache.c + * Fix for CR#764881. + * 4.1 srt 06/27/14 Remove '#undef DEBUG' from src/common/xdebug.h, which allows to + * output the DEBUG logs when -DDEBUG flag is enabled in BSP. + * 4.2 pkp 06/27/14 Added support for IAR compiler in src/cortexa9/iccarm. + * Also added explanatory notes in cortexa9/xil_cache.c for CR#785243. + * 4.2 pkp 06/19/14 Asynchronous abort has been enabled into cortexa9/gcc/boot.s and + * cortexa9/armcc/boot.s. Added default exception handlers for data + * abort and prefetch abort using handlers called + * DataAbortHandler and PrefetchAbortHandler respectively in + * cortexa9/xil_exception.c to fix CR#802862. + * 4.2 pkp 06/30/14 MakeFile for cortexa9/armcc has been changed to fixes the + * issue of improper linking of translation_table.s + * 4.2 pkp 07/04/14 added weak attribute for the function in BSP which are also present + * in tool chain to avoid conflicts into some special cases + * 4.2 pkp 07/21/14 Corrected reset value of event counter in function + * Xpm_ResetEventCounters in src/cortexa9/xpm_counter.c to fix CR#796275 + * 4.2 pkp 07/21/14 Included xil_types.h file in xil_mmu.h which had contained a function + * containing type def u32 defined in xil_types.g to resolve issue of + * CR#805869 + * 4.2 pkp 08/04/14 Removed unimplemented nanosleep routine from cortexa9/usleep.c as + * it is not possible to generate timer in nanosecond due to limited + * cpu frequency + * 4.2 pkp 08/04/14 Removed PEEP board related code which contained initialization of + * uart, smc nor and sram from cortexa9/gcc/xil-crt0.s and armcc/boot.s + * and iccarm/boot.s. Also uart.c and smc.c have been removed. Also + * removed function definition of XSmc_NorInit and XSmc_NorInit from + * cortexa9/smc.h + * 4.2 bss 08/11/14 Added microblaze_flush_cache_ext_range and microblaze_invalidate_ + * cache_ext_range declarations in mb_interface.h CR#783821. + * Modified profile_mcount_mb.S to fix CR#808412. + * 4.2 pkp 08/21/14 modified makefile of iccarm for proper linking of objectfiles in + * cortexa9/iccarm to fix CR#816701 + * 4.2 pkp 09/02/14 modified translation table entries in cortexa9/gcc/translation_table.s, + * armcc/translation_table.s and iccarm/translation_table.s + * to properly defined reserved entries according to address map for + * fixing CR#820146 + * 4.2 pkp 09/11/14 modified translation table entries in cortexa9/iccarm/translation_table.s + * and cortexa9/armcc/translation_table.s to resolve compilation + * error for solving CR#822897 + * 5.0 kvn 12/9/14 Support for Zync Ultrascale Mp.Also modified code for + * MISRA-C:2012 compliance. + * 5.0 pkp 12/15/14 Added APIs to get information about the platforms running the code by + * adding src/common/xplatform_info.*s + * 5.0 pkp 16/12/14 Modified boot code to enable scu after MMU is enabled and + * removed incorrect initialization of TLB lockdown register to fix + * CR#830580 in cortexa9/gcc/boot.S & cpu_init.S, armcc/boot.S + * and iccarm/boot.s + * 5.0 pkp 25/02/15 Modified floating point flag to vfpv3 from vfpv3_d16 in BSP MakeFile + * for iccarm and armcc compiler of cortexA9 + * 5.1 pkp 05/13/15 Changed the initialization order in cortexa9/gcc/boot.S, iccarm/boot.s + * and armcc/boot.s so to first invalidate caches and TLB, enable MMU and + * caches, then enable SMP bit in ACTLR. L2Cache invalidation and enabling + * of L2Cache is done later. + * 5.1 pkp 12/05/15 Modified cortexa9/xil_cache.c to modify Xil_DCacheInvalidateRange and + * Xil_DCacheFlushRange to remove unnecessary dsb which is unnecessarily + * taking long time to fix CR#853097. L2CacheSync is added into + * Xil_L2CacheInvalidateRange API. Xil_L1DCacheInvalidate and + * Xil_L2CacheInvalidate APIs are modified to flush the complete stack + * instead of just System Stack + * 5.1 pkp 14/05/15 Modified cortexa9/gcc/Makefile to keep a correct check of a compiler + * to update ECC_FLAGS and also take the compiler and archiver as specified + * in settings instead of hardcoding it. + * 5.2 pkp 06/08/15 Modified cortexa9/gcc/translation_table.S to put a check for + * XPAR_PS7_DDR_0_S_AXI_BASEADDR to confirm if DDR is present or not and + * accordingly generate the translation table + * 5.2 pkp 23/07/15 Modified cortexa9/gcc/Makefile to keep a correct check of a compiler + * to update ECC_FLAGS to fix a bug introduced during new version creation + * of BSP. + * 5.3 pkp 10/07/15 Modified cortexa9/xil_cache.c file to change cache API so that L2 Cache + * functionalities are avoided for the OpenAMP slave application(when + * USE_AMP flag is defined for BSP) as master CPU would be utilizing L2 + * cache for its operation. Also file operations such as read, write, + * close, open are also avoided for OpenAMP support(when USE_AMP flag is + * defined for BSP) because XilOpenAMP library contains own file operation. + * The xil-crt0.S file is modified for not initializing global timer for + * OpenAMP application as it might be already in use by master CPU + * 5.3 pkp 10/09/15 Modified cortexa9/iccarm/xpseudo_asm_iccarm.h file to change function + * definition for dsb, isb and dmb to fix the compilation error when used + * kvn 16/10/15 Encapsulated assembly code into macros for R5 xil_cache file. + * 5.4 pkp 09/11/15 Modified cortexr5/gcc/boot.S to disable ACTLR.DBWR bit to avoid potential + * R5 deadlock for errata 780125 + * 5.4 pkp 09/11/15 Modified cortexa53/32bit/gcc/boot.S to enable I-Cache and D-Cache for a53 + * 32 bit BSP in the initialization + * 5.4 pkp 09/11/15 Modified cortexa9/xil_misc_psreset_api.c file to change the description + * for XOcm_Remap function + * 5.4 pkp 16/11/15 Modified microblaze/xil_misc_psreset_api.c file to change the description + * for XOcm_Remap function + * kvn 21/11/15 Added volatile keyword for ADDR varibles in Xil_Out API + * kvn 21/11/15 Changed ADDR variable type from u32 to UINTPTR. This is + * required for MISRA-C:2012 Compliance. + * 5.4 pkp 23/11/15 Added attribute definitions for Xil_SetTlbAttributes API of Cortex-A9 + * in cortexa9/xil_mmu.h + * 5.4 pkp 23/11/15 Added default undefined exception handler for Cortex-A9 + * 5.4 pkp 11/12/15 Modified common/xplatform_info.h to add #defines for silicon for + * checking the current executing platform + * 5.4 pkp 18/12/15 Modified cortexa53/32bit/gcc/xil-crt0.S and 64bit/gcc/xil-crt0.S + * to initialize global constructor for C++ applications + * 5.4 pkp 18/12/15 Modified cortexr5/gcc/xil-crt0.S to initialize global constructor for + * C++ applications + * 5.4 pkp 18/12/15 Modified cortexa53/32bit/gcc/translation_table.S and 64bit/gcc/ + * translation_table.S to update the translation table according to proper + * address map + * 5.4 pkp 18/12/15 Modified cortexar5/mpu.c to initialize the MPU according to proper + * address map + * 5.4 pkp 05/01/16 Modified cortexa53/64bit/boot.S to set the reset vector register RVBAR + * equivalent to vector table base address + * 5.4 pkp 08/01/16 Modified cortexa9/gcc/Makefile to update the extra compiler flag + * as per the toolchain update + * 5.4 pkp 12/01/16 Changed common/xplatform_info.* to add platform information support + * for Cortex-A53 32bit mode + * 5.4 pkp 28/01/16 Modified cortexa53/32bit/sleep.c and usleep.c & cortexa53/64bit/sleep.c + * and usleep.c to correct routines to avoid hardcoding the timer frequency, + * instead take it from xparameters.h to properly configure the timestamp + * clock frequency + * 5.4 asa 29/01/16 Modified microblaze/mb_interface.h to add macros that support the + * new instructions for MB address extension feature + * 5.4 kvn 30/01/16 Modified xparameters_ps.h file to add interrupt ID number for + * system monitor. + * 5.4 pkp 04/02/16 Modified cortexr5/gcc/boot.S to enable fault log for lock-step mode + * 5.4 pkp 19/02/16 Modified cortexr5/xtime_l.c to add an API XTime_StartTimer and updated + * cortexr5/xil-crt0.S to configure the TTC3 timer when present. Modified + * cortexr5/sleep.c, cortexr5/usleep.c to use TTC3 when present otherwise + * use set of assembly instructions to provide required delay to fix + * CR#913249. + * 5.4 asa 25/02/16 Made changes in xil-crt0.S for R5, A53 64 and 32 bit BSPs, to replace + * _exit with exit. We should not be directly calling _exit and should + * always use the library exit. This fixes the CR#937036. + * 5.4 pkp 25/02/16 Made change to cortexr5/gcc/boot.S to initialize the floating point + * registers, banked registers for various modes and enabled + * the cache ECC check before enabling the fault log for lock step mode + * Also modified the cortexr5/gcc/Makefile to support floating point + * registers initialization in boot code. + * 5.4 pkp 03/01/16 Updated the exit function in cortexr5/gcc/_exit.c to enable the debug + * logic in case of lock-step mode when fault log is enabled to fix + * CR#938281 + * 5.4 pkp 03/02/16 Modified cortexa9/iccarm/xpseudo_asm_iccarm.h file to include + * header file instrinsics.h which contains assembly instructions + * definitions which can be used by C + * 5.4 asa 03/02/16 Added print.c in MB BSP. Made other cosmetic changes to have uniform + * proto for all print.c across the BSPs. This patch fixes CR#938738. + * 5.4 pkp 03/09/16 Modified cortexr5/sleep.c and usleep.c to avoid disabling the + * interrupts when sleep/usleep is being executed using assembly + * instructions to fix CR#913249. + * 5.4 pkp 03/11/16 Modified cortexr5/xtime_l.c to avoid enabling overflow interrupt, + * instead modified cortexr5/sleep.c and usleep.c to poll the counter + * value and compare it with previous value to detect the overflow + * to fix CR#940209. + * 5.4 pkp 03/24/16 Modified cortexr5/boot.S to reset the dbg_lpd_reset before enabling + * the fault log to avoid intervention for lock-step mode and cortexr5/ + * _exit.c to enable the dbg_lpd_reset once the fault log is disabled + * to fix CR#947335 + * 5.5 pkp 04/11/16 Modified cortexr5/boot.S to enable comparators for non-JTAG bootmode + * in lock-step to avoid resetting the debug logic which restricts the + * access for debugger and removed enabling back of debug modules in + * cortexr5/_exit.c + * 5.5 pkp 04/13/16 Modified cortexa9/gcc/read.c to return correct number of bytes when + * read buffer is filled and removed the redundant NULL checking for + * buffer to simplify the code + * 5.5 pkp 04/13/16 Modified cortexa53/64bit/gcc/read.c and cortexa53/32bit/gcc/read.c + * to return correct number of bytes when read buffer is filled and + * removed the redundant NULL checking for buffer to simplify the code + * 5.5 pkp 04/13/16 Modified cortexr5/gcc/read.c to return correct number of bytes when + * read buffer is filled and removed the redundant NULL checking for + * buffer to simplify the code + * 5.5 pkp 04/13/16 Modified cortexa53/64bit/xpseudo_asm_gcc.h to add volatile to asm + * instruction macros to disable certain optimizations which may move + * code out of loops if optimizers believe that the code will always + * return the same result or discard asm statements if optimizers + * determine there is no need for the output variables + * 5.5 pkp 04/13/16 Modified cortexa53/64bit/xtime_l.c to add XTime_StartTimer which + * starts the timer if it is disabled and modified XTime_GetTime to + * enable the timer if it is not enabled. Also modified cortexa53/64bit/ + * sleep.c and cortexa53/64bit/usleep.c to enable the timer if it is + * disabled and read the counter value directly from register instead + * of using XTime_GetTime for optimization + * 5.5 pkp 04/13/16 Modified cortexa53/32bit/xtime_l.c to add XTime_StartTimer which + * starts the timer if it is disabled and modified XTime_GetTime to + * enable the timer if it is not enabled. Also modified cortexa53/32bit/ + * sleep.c and cortexa53/32bit/usleep.c to enable the timer if it is + * disabled and read the counter value directly from register instead + * of using XTime_GetTime for optimization + * 5.5 pkp 04/13/16 Modified cortexa53/32bit/xil_cache.c and cortexa53/64bit/xil_cache.c + * to update the Xil_DCacheInvalidate, Xil_DCacheInvalidateLine and + * Xil_DCacheInvalidateRange functions description for proper + * explaination to fix CR#949801 + * 5.5 asa 04/20/16 Added missing macros for hibernate and suspend in Microblaze BSP + * file mb_interface.h. This fixes the CR#949503. + * 5.5 asa 04/29/16 Fix for CR#951080. Updated cache APIs for HW designs where cache + * memory is not included for MicroBlaze. + * 5.5 pkp 05/06/16 Modified the cortexa9/xil_exception.h to update the macros + * Xil_EnableNestedInterrupts and Xil_DisableNestedInterrupts for fixing + * the issue of lr being corrupted to resolve CR#950468 + * 5.5 pkp 05/06/16 Modified the cortexr5/xil_exception.h to update the macros + * Xil_EnableNestedInterrupts and Xil_DisableNestedInterrupts for fixing + * the issue of lr being corrupted to resolve CR#950468 + * 6.0 kvn 05/31/16 Make Xil_AsserWait a global variable + * 6.0 pkp 06/27/16 Updated cortexr5/mpu.c to move the code related to Init_MPU to .boot + * section since it is part of boot process to fix CR#949555 + * hk 07/12/16 Correct masks for IOU SLCR GEM registers + * 6.0 pkp 07/25/16 Program the counter frequency in boot code for CortexA53 + * 6.0 asa 08/03/16 Updated sleep_common function in microblaze_sleep.c to improve the + * the accuracy of MB sleep functionality. This fixes the CR#954191. + * 6.0 mus 08/03/16 Restructured the BSP to avoid code duplication across all BSPs. + * Source code directories specific to ARM processor's are moved to src/arm + * directory(i.e. src/cortexa53,src/cortexa9 and src/cortexr5 moved to src/arm/cortexa53, + * src/arm/cortexa9 and src/arm/cortexr5 respectively).Files xil_printf.c,xil_printf.h, + * print.c,xil_io.c and xil_io.h are consolidated across all BSPs into common file each and + * consolidated files are kept at src/common directory.Files putnum.c,vectors.c,vectors.h, + * xil_exception.c and xil_exception.h are consolidated across all ARM BSPs + * into common file each and consolidated files are kept at src/arm/common directory. + * GCC source files related to file operations are consolidated and kept + * at src/arm/common/gcc directory. + * All io interfacing functions (i.e. All variants of xil_out, xil_in ) + * are made as static inline and implementation is kept in consolidated common/xil_io.h, + * xil_io.h must be included as a header file to access io interfacing functions. + * Added undefined exception handler for A53 32 bit and R5 processor + * 6.0 mus 08/11/16 Updated xtime_l.c in R5 BSP to remove implementation of XTime_SetTime API, since + * TTC counter value register is read only. + * 6.0 asa 08/15/16 Modified the signatures for functions sleep and usleep. This fixes + * the CR#956899. + * 6.0 mus 08/18/16 Defined ARMA53_32 flag in cortexa53/32bit/xparameters_ps.h and ARMR5 flag + * in cortexr5/xparameters_ps.h + * 6.0 mus 08/18/16 Added support for the the Zynq 7000s devices + * 6.0 mus 08/18/16 Removed unused variables from xil_printf.c and xplatform_info.c + * 6.0 mus 08/19/16 Modified xil_io.h to remove __LITTLE_ENDIAN__ flag check for all ARM processors + * 6.1 mus 11/03/16 Added APIs handle_stdin_parameter and handle_stdout_parameter in standalone tcl. + * ::hsi::utils::handle_stdin and ::hsi::utils::handle_stdout are taken as a base for + * these APIs and modifications are done on top of it to handle stdout/stdin + * parameters for design which doesnt have UART.It fixes CR#953681 + * 6.1 nsk 11/07/16 Added two new files xil_mem.c and xil_mem.h for xil_memcpy + * 6.2 pkp 12/14/16 Updated cortexa53/64bit/translation_table.S for upper ps DDR. The 0x800000000 - + * 0xFFFFFFFFF range is marked normal memory for the DDR size defined in hdf + * and rest of the memory in that 32GB region is marked as reserved to avoid + * any speculative access + * 6.2 pkp 12/23/16 Added support for floating point operation to Cortex-A53 64bit mode. It modified + * asm_vectors.S to implement lazy floating point context saving i.e. floating point + * access is enabled if there is any floating point operation, it is disabled by + * default. Also FPU is initally disabled for IRQ and none of the floating point + * registers are saved during normal context saving. If IRQ handler does not require + * floating point operation, the floating point registers are untouched and no need + * for saving/restoring. If IRQ handler uses any floating point operation, then floating + * point registers are saved and FPU is enabled for IRQ handler. Then floating point + * registers are restored back after servicing IRQ during normal context restoring. + * 6.2 mus 01/01/17 Updated makefiles of R5 and a53 64 bit/32 bit processors to fix error in clean + * target.It fixes the CR#966900 + * 6.2 pkp 01/22/17 Added support for EL1 non-secure execution and Hypervisor Baremetal for Cortex-A53 + * 64bit Mode. If Hypervisor_guest is selected as true in BSP settings, BSP will be built + * for EL1 Non-secure, else BSP will be built for EL3. By default hypervisor_guest is + * as false i.e. default bsp is EL3. + * 6.2 pkp 01/24/17 Updated cortexa53/64bit/boot.S to clear FPUStatus variable to make sure that it + * contains initial status of FPU i.e. disabled. In case of a warm restart execution + * when bss sections are not cleared, it may contain previously updated value which + * does not hold true once processor resumes. This fixes CR#966826. + * 6.2 asa 01/31/17 The existing Xil_DCacheDisable API first flushes the + * D caches and then disables it. The problem with that is, + * potentially there will be a small window after the cache + * flush operation and before the we disable D caches where + * we might have valid data in cache lines. In such a + * scenario disabling the D cache can lead to unknown behavior. + * The ideal solution to this is to use assembly code for + * the complete API and avoid any memory accesses. But with + * that we will end up having a huge amount on assembly code + * which is not maintainable. Changes are done to use a mix + * of assembly and C code. All local variables are put in + * registers. Also function calls are avoided in the API to + * avoid using stack memory. + * 6.2 mus 02/13/17 A53 CPU cache system can pre-fetch catch lines.So there are + * scenarios when an invalidated cache line can get pre fetched to cache. + * If that happens, the coherency between cache and memory is lost + * resulting in lost data. To avoid this kind of issue either + * user has to use dsb() or disable pre-fetching for L1 cache + * or else reduce maximum number of outstanding data prefetches allowed. + * Using dsb() while comparing data costing more performance compared to + * disabling pre-fetching/reducing maximum number of outstanding data + * prefetches for L1 Cache.The new api Xil_ConfigureL1Prefetch is added + * to disable pre-fetching/configure maximum number of outstanding data + * prefetches allowed in L1 cache system.This fixes CR#967864. + * 6.2 pkp 02/16/17 Added xil_smc.c file to provide a C wrapper for smc calling which can be + * used by cortex-A53 64bit EL1 Non-secure application. + * 6.2 kvn 03/03/17 Added support thumb mode + * 6.2 mus 03/13/17 Fixed MISRA C mandatory standard violations in ARM cortexr5 and cortexa53 BSP. + * It fixes CR#970543 + * 6.2 asa 03/16/17 Fix for CR#970859. For Mcroblaze BSP, when we enable intrusive + * profiling we see a crash. That is because the the tcl uses invalid + * HSI command. This change fixes it. + * 6.2 mus 03/22/17 Updated standalone tcl to generate xparameter XPAR_FPD_IS_CACHE_COHERENT, if + * any FPD peripheral is configured to use CCI.It fixes CR#972638 + * 6.3 mus 03/20/17 Updated cortex-r5 BSP, to add hard floating point support. + * 6.3 mus 04/17/17 Updated Cortex-a53 32 bit BSP boot code to fix bug in + * the HW coherency enablement. It fixes the CR#973287 + * 6.3 mus 04/20/17 Updated Cortex-A53 64 bit BSP boot code, to remove redundant write to the + * L2CTLR_EL1 register. It fixes the CR#974698 + * 6.4 mus 06/08/17 Updated arm/common/xil_exception.c to fix warnings in C level exception handlers + * of ARM 32 bit processor's. + * 6.4 mus 06/14/17 Updated cortexa53/64bit/gcc/asm_vectors.S to fix bug in IRQInterruptHandler code + * snippet, which checks for the FPEN bit of CPACR_EL1 register. + * 6.4 ms 05/23/17 Added PSU_PMU macro in xplatform_info.c, xparameters.h to support + * XGetPSVersion_Info function for PMUFW. + * ms 06/13/17 Added PSU_PMU macro in xplatform_info.c to support XGetPlatform_Info + * function for PMUFW. + * 6.4 mus 07/05/17 Updated Xil_In32BE function in xil_io.h to fix bug.It fixes CR#979740. + * 6.4 mus 07/25/17 Updated a53 32 bit boot code and vectors to support hard floating point + * operations.Now,VFP is being enabled in FPEXC register, through boot code + * and FPU registers are being saved/restored when irq/fiq vector is invoked. + * 6.4 adk 08/01/17 Updated standalone tcl to generate xparameter XPAR_PL_IS_CACHE_COHERENT, + * if h/w design configured with HPC port. + * 6.4 mus 08/10/17 Updated a53 64 bit translation table to mark memory as a outer shareable for + * EL1 NS execution. This change has been done to support CCI enabled IP's. + * 6.4 mus 08/11/17 Updated a53 64 bit boot code to implement ARM erratum 855873.This fixes + * CR#982209. + * 6.4 asa 08/16/17 Made several changes in the R5 MPU handling logic. Added new APIs to + * make RPU MPU handling user-friendly. This also fixes the CR-981028. + * 6.4 mus 08/17/17 Updated XGet_Zynq_UltraMp_Platform_info and XGetPSVersion_Info APIs to read + * version register through SMC call, over EL1 NS mode. This change has been done to + * support these APIs over EL1 NS mode. + * 6.5 mus 10/20/17 Updated standalone.tcl to fix bug in mb_can_handle_exceptions_in_delay_slots proc, + * it fixes CR#987464. + * 6.6 mus 12/07/17 Updated cortexa9/xil_errata.h and cortexa9/xil_cache.c to remove Errata 753970. + * It fixes CR#989132. + * srm 10/18/17 Updated all the sleep routines in a9,a53,R5,microblaze. Now the sleep routines + * will use the timer specified by the user to provide delay. A9 and A53 can use + * Global timer or TTC. R5 can use TTC or the machine cycles. Microblaze can use + * machine cycles or Axi timer. Updated standalone.tcl and standalone.mld files + * to support the sleep configuration Added new API's for the Axi timer in + * microblaze and TTC in ARM. Added two new files, xil_sleeptimer.c and + * xil_sleeptimer.h in ARM for the common sleep routines and 1 new file, + * xil_sleepcommon.c in Standalone-common for sleep/usleep API's. + * 6.6 hk 12/15/17 Export platform macros to bspconfig.h based on the processor. + * 6.6 asa 1/16/18 Ensure C stack information for A9 are flushed out from L1 D cache + * or L2 cache only when the respective caches are enabled. This fixes CR-922023. + * 6.6 mus 01/19/18 Updated asm_vectors.S and boot.S in Cortexa53 64 bit BSP, to add isb + * after writing to cpacr_el1/cptr_el3 registers. It would ensure + * disabling/enabling of floating-point unit, before any subsequent + * instruction. + * 6.6 hk 12/15/17 Export platform macros to xparameters.h based on the processor. + * 6.6 asa 1/16/18 Ensure C stack information for A9 are flushed out from L1 D cache + * or L2 cache only when the respective caches are enabled.This fixes CR-922023. + * + * 6.6 mus 01/19/18 Updated asm_vectors.S and boot.S in Cortexa53 64 bit BSP, to add isb + * after writing to cpacr_el1/cptr_el3 registers. It would ensure + * disabling/enabling of floating-point unit, before any subsequent + * instruction. + * 6.6 mus 01/30/18 Updated hypervisor enabled Cortexa53 64 bit BSP, to add xen PV console + * support. Now, xil_printf would use PV console instead of UART in case of + * hypervisor enabled BSP. + * 6.6 mus 02/02/18 Updated get_connected_if proc in standalone tcl to detect the HPC port + * configured with smart interconnect.It fixes CR#990318. + * 6.6 srm 02/10/18 Updated csu_wdt interrupt to the correct value. Fixes CR#992229 + * 6.6 asa 02/12/18 Fix for heap handling for ARM platforms. CR#993932. + * 6.6 mus 02/19/18 Updated standalone.tcl to fix bug in handle_profile_opbtimer proc, + * CR#995014. + * 6.6 mus 02/23/18 Presently Cortex R5 BSP boot code is disabling the debug logic in + * non-JTAG boot mode, when processor is in lockstep configuration. + * This behavior is restricting application debugging in non-JTAG boot + * mode. To get rid of this restriction, added new mld parameter + * "lockstep_mode_debug", to enable/disable debug logic from BSP + * settings. Now, debug logic can be enabled through BSP settings, + * by modifying value of parameter "lockstep_mode_debug" as "true". + * It fixes CR#993896. + * 6.6.mus 02/27/18 Updated Xil_DCacheInvalidateRange and + * Xil_ICacheInvalidateRange APIs in Cortexa53 64 bit BSP, to fix bug + * in handling upper DDR addresses.It fixes CR#995581. + * 6.6 mus 03/12/18 Updated makefile of Cortexa53 32bit BSP to add includes_ps directory + * in the list of include paths. This change allows applications/BSP + * files to include .h files in include_ps directory. + * 6.6 mus 03/16/18 By default CPUACTLR_EL1 is accessible only from EL3, it + * results into abort if accessed from EL1 non secure privilege + * level. Updated Xil_ConfigureL1Prefetch function in Cortexa53 64 bit BSP + * to avoid CPUACTLR_EL1 access from privile levels other than EL3. + * 6.6 mus 03/16/18 Updated hypervisor enabled BSP to use PV console, based on the + * XEN_USE_PV_CONSOLE flag. By deafault hypervisor enabled BSP would + * use UART console, PV console can be enabled by appending + * "-DXEN_USE_PV_CONSOLE" to the BSP extra compiler flags. + * 6.7 asa 04/26/18 Added API Xil_GetExceptionRegisterHandler for obtaining information + * on an already registered exception vector. + * 6.7 asa 05/18/18 Fixed bugss in the API Xil_GetExceptionRegisterHandler. + * 6.8 mus 04/27/18 Removed __ARM_NEON__ flag definition. Now, saving/restoring of of HW + * floating point register would be done through newly introduced flag + * FPU_HARD_FLOAT_ABI_ENABLED. This new flag will be configured based on + * the -mfpu-abi option in extra compiler flags.. This change has + * been done to avoid saving/restoring of HW floating point registers, + * when BSP is not compiled with HW floating point configuration. + * 6.8 aru 06/15/18 Removed unused variable in xil_cache.c for A53-32. It + * fixes CR1005118. + * 6.8 aru 07/02/18 Returned the pointer instead of address of that pointer in xil_mpu.c + * for R5 processor.It Fixes CR#1005119. + * 6.8 mus 07/12/18 Updated Cortexa9 translation table to mark DDR memory as inner cacheable, + * if BSP is built with the USE_AMP flag. It fixes CR#1006745. + * + * 6.8 aru 07/04/18 Optimized the code to use a loop and to remove redundant code + * in Xil_DCacheFlush() and Xil_DCacheInvalidate() + * of xil_cache.c for A53-32. + * 6.8 aru 07/26/18 added support in xil_printf.c to print u64 variabbles + * correctly in 32 bit processor.It fixes CR#1007207. + * 6.8 aru 09/03/18 Optimized the code to use a single function and removed + * code redundancy in xil_printf.c . It Fixes CR#1009654. + * 6.8 aru 09/06/18 Removed the compiler warnings for ARMCC toolchain. + * It fixes CR#1008309. + * 6.8 mus 09/20/18 Updated CortexR5 boot code to initialize CortexR5 core with LOVEC + * on reset. It fixes CR#1010656. + * 6.8 mus 10/04/18 Updated microblaze sleep functinality to execute default method of + * sleep implementation, incase of FreeRTOS BSP. + * 6.8 mus 10/25/18 Updated assembly code for cache APIs and inline assemby macros to + * to support 64 bit addresses. + * 6.8 asa 10/11/18 Updated the A53 32 bit cache APIs for Xil_DCacheFlush and + * Xil_DCacheInvalidate to fix various issues. These issues were not + * present in the previous releases but got introduced as part of + * optimization patches that got applied for 6.8 BSP version. These + * changes fix the CR#1016012. + * 7.0 rp 10/25/18 Added XST_NO_ACCESS status macros for generic access error. + * 7.0 mus 02/01/19 Added support for Versal. Cortea53 BSP will be re-used by Cortexa72, + * re-named cortexa53 directory as ARMv8, since files are generic for + * ARMv8 based processors. Created "platform" directory to place + * SoC based files. + * 7.0 mus 02/05/19 Updated Xil_MemCpy API to copy two bytes at a time from source to + * destination if byte count is <= 2. + * 7.0 mus 02/28/19 Added armclang complier support to the Cortexa53 64 bit BSP. + * 7.0 mus 04/08/19 Fix microblaze_disable_dcache for 64 bit microblaze + * 7.0 mus 04/26/19 Added frequently used functions in common area in xil_utils.c, + * so that other modules can make use of it. + *****************************************************************************************/ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/close.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/close.c new file mode 100644 index 0000000..64f7f49 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/close.c @@ -0,0 +1,45 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +#ifndef UNDEFINE_FILE_OPS +#include "xil_types.h" +#ifdef __cplusplus +extern "C" { + __attribute__((weak)) s32 _close(s32 fd); +} +#endif + +/* + * close -- We don't need to do anything, but pretend we did. + */ + +__attribute__((weak)) s32 _close(s32 fd) +{ + (void)fd; + return (0); +} +#endif diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/config.make b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/config.make new file mode 100644 index 0000000..7ca8d6d --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/config.make @@ -0,0 +1,3 @@ +LIBSOURCES = *.c *.S +PROFILE_ARCH_OBJS = profile_mcount_arm.o +LIBS = standalone_libs diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/cpu_init.S b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/cpu_init.S new file mode 100644 index 0000000..5b597be --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/cpu_init.S @@ -0,0 +1,76 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file cpu_init.s +* +* This file contains CPU specific initialization. Invoked from main CRT +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who     Date     Changes
+* ----- ------- -------- ---------------------------------------------------
+* 1.00a ecm/sdm 10/20/09 Initial version
+* 3.04a sdm	01/02/12 Updated to clear cp15 regs with unknown reset values
+* 5.0   pkp	12/16/14 removed incorrect initialization of TLB lockdown
+*			 register to fix CR#830580
+* 
+* +* @note +* +* None. +* +******************************************************************************/ + + .text + .global __cpu_init + .align 2 +__cpu_init: + +/* Clear cp15 regs with unknown reset values */ + mov r0, #0x0 + mcr p15, 0, r0, c5, c0, 0 /* DFSR */ + mcr p15, 0, r0, c5, c0, 1 /* IFSR */ + mcr p15, 0, r0, c6, c0, 0 /* DFAR */ + mcr p15, 0, r0, c6, c0, 2 /* IFAR */ + mcr p15, 0, r0, c9, c13, 2 /* PMXEVCNTR */ + mcr p15, 0, r0, c13, c0, 2 /* TPIDRURW */ + mcr p15, 0, r0, c13, c0, 3 /* TPIDRURO */ + +/* Reset and start Cycle Counter */ + mov r2, #0x80000000 /* clear overflow */ + mcr p15, 0, r2, c9, c12, 3 + mov r2, #0xd /* D, C, E */ + mcr p15, 0, r2, c9, c12, 0 + mov r2, #0x80000000 /* enable cycle counter */ + mcr p15, 0, r2, c9, c12, 1 + + bx lr + +.end diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/errno.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/errno.c new file mode 100644 index 0000000..3cdb751 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/errno.c @@ -0,0 +1,47 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +/* The errno variable is stored in the reentrancy structure. This + function returns its address for use by the macro errno defined in + errno.h. */ + +#include +#include +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { + __attribute__((weak)) sint32 * __errno (void); +} +#endif + +__attribute__((weak)) sint32 * +__errno (void) +{ + return &_REENT->_errno; +} diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/fcntl.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/fcntl.c new file mode 100644 index 0000000..42c2bff --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/fcntl.c @@ -0,0 +1,42 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +#include +#include "xil_types.h" + +/* + * fcntl -- Manipulate a file descriptor. + * We don't have a filesystem, so we do nothing. + */ +__attribute__((weak)) sint32 fcntl (sint32 fd, sint32 cmd, long arg) +{ + (void)fd; + (void)cmd; + (void)arg; + return 0; +} diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/fstat.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/fstat.c new file mode 100644 index 0000000..92a3ebf --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/fstat.c @@ -0,0 +1,46 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +#include +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { + __attribute__((weak)) s32 _fstat(s32 fd, struct stat *buf); +} +#endif +/* + * fstat -- Since we have no file system, we just return an error. + */ +__attribute__((weak)) s32 _fstat(s32 fd, struct stat *buf) +{ + (void)fd; + buf->st_mode = S_IFCHR; /* Always pretend to be a tty */ + + return (0); +} diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/getpid.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/getpid.c new file mode 100644 index 0000000..36c8769 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/getpid.c @@ -0,0 +1,47 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +#include "xil_types.h" +/* + * getpid -- only one process, so just return 1. + */ +#ifdef __cplusplus +extern "C" { + __attribute__((weak)) s32 _getpid(void); +} +#endif + +__attribute__((weak)) s32 getpid(void) +{ + return 1; +} + +__attribute__((weak)) s32 _getpid(void) +{ + return 1; +} diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/inbyte.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/inbyte.c new file mode 100644 index 0000000..a5a6448 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/inbyte.c @@ -0,0 +1,14 @@ +#include "xparameters.h" +#include "xuartps_hw.h" + +#ifdef __cplusplus +extern "C" { +#endif +char inbyte(void); +#ifdef __cplusplus +} +#endif + +char inbyte(void) { + return XUartPs_RecvByte(STDIN_BASEADDRESS); +} diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/isatty.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/isatty.c new file mode 100644 index 0000000..d1ef081 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/isatty.c @@ -0,0 +1,52 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +#include +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { + __attribute__((weak)) sint32 _isatty(sint32 fd); +} +#endif + +/* + * isatty -- returns 1 if connected to a terminal device, + * returns 0 if not. Since we're hooked up to a + * serial port, we'll say yes _AND return a 1. + */ +__attribute__((weak)) sint32 isatty(sint32 fd) +{ + (void)fd; + return (1); +} + +__attribute__((weak)) sint32 _isatty(sint32 fd) +{ + (void)fd; + return (1); +} diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/kill.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/kill.c new file mode 100644 index 0000000..22b66a2 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/kill.c @@ -0,0 +1,56 @@ +/****************************************************************************** +* +* Copyright (C) 2014 - 2016 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +#include +#include +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { + __attribute__((weak)) int _kill(pid_t pid, int sig); +} +#endif + +/* + * kill -- go out via exit... + */ + +__attribute__((weak)) int kill(pid_t pid, int sig) +{ + if(pid == 1) { + _exit(sig); + } + return 0; +} + +__attribute__((weak)) int _kill(pid_t pid, int sig) +{ + if(pid == 1) { + _exit(sig); + } + return 0; +} diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/lseek.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/lseek.c new file mode 100644 index 0000000..400d4cc --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/lseek.c @@ -0,0 +1,57 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +#include +#include +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { + __attribute__((weak)) off_t _lseek(s32 fd, off_t offset, s32 whence); +} +#endif +/* + * lseek -- Since a serial port is non-seekable, we return an error. + */ +__attribute__((weak)) off_t lseek(s32 fd, off_t offset, s32 whence) +{ + (void)fd; + (void)offset; + (void)whence; + errno = ESPIPE; + return ((off_t)-1); +} + +__attribute__((weak)) off_t _lseek(s32 fd, off_t offset, s32 whence) +{ + (void)fd; + (void)offset; + (void)whence; + errno = ESPIPE; + return ((off_t)-1); +} diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/open.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/open.c new file mode 100644 index 0000000..4c46b67 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/open.c @@ -0,0 +1,49 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +#ifndef UNDEFINE_FILE_OPS +#include +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { + __attribute__((weak)) s32 open(char8 *buf, s32 flags, s32 mode); +} +#endif +/* + * open -- open a file descriptor. We don't have a filesystem, so + * we return an error. + */ +__attribute__((weak)) s32 open(char8 *buf, s32 flags, s32 mode) +{ + (void)buf; + (void)flags; + (void)mode; + errno = EIO; + return (-1); +} +#endif diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/outbyte.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/outbyte.c new file mode 100644 index 0000000..3c64308 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/outbyte.c @@ -0,0 +1,15 @@ +#include "xparameters.h" +#include "xuartps_hw.h" + +#ifdef __cplusplus +extern "C" { +#endif +void outbyte(char c); + +#ifdef __cplusplus +} +#endif + +void outbyte(char c) { + XUartPs_SendByte(STDOUT_BASEADDRESS, c); +} diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/print.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/print.c new file mode 100644 index 0000000..da7e768 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/print.c @@ -0,0 +1,36 @@ +/* print.c -- print a string on the output device. + * + * Copyright (c) 1995 Cygnus Support + * + * The authors hereby grant permission to use, copy, modify, distribute, + * and license this software and its documentation for any purpose, provided + * that existing copyright notices are retained in all copies and that this + * notice is included verbatim in any distributions. No written agreement, + * license, or royalty fee is required for any of the authorized uses. + * Modifications to this software may be copyrighted by their authors + * and need not follow the licensing terms described here, provided that + * the new terms are clearly indicated on the first page of each file where + * they apply. + * + */ + +/* + * print -- do a raw print of a string + */ +#include "xil_printf.h" + +void print(const char8 *ptr) +{ +#if HYP_GUEST && EL1_NONSECURE && XEN_USE_PV_CONSOLE + XPVXenConsole_Write(ptr); +#else +#ifdef STDOUT_BASEADDRESS + while (*ptr != (char8)0) { + outbyte (*ptr); + ptr++; + } +#else +(void)ptr; +#endif +#endif +} diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/Makefile b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/Makefile new file mode 100644 index 0000000..53a288e --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/Makefile @@ -0,0 +1,74 @@ +############################################################################### +# +# Copyright (C) 2002 - 2014 Xilinx, Inc. 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 +# XILINX 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. +# +# Except as contained in this notice, the name of the Xilinx shall not be used +# in advertising or otherwise to promote the sale, use or other dealings in +# this Software without prior written authorization from Xilinx. +# +############################################################################### +# +# Makefile for profiler +# +####################################################################### + +# PROFILE_ARCH_OBJS - Processor Architecture Dependent files defined here +include ../config.make + +AS=mb-as +COMPILER = mb-gcc +ARCHIVER = mb-ar +CP = cp +COMPILER_FLAGS=-O2 +EXTRA_COMPILER_FLAGS= +LIB = libxil.a +DUMMYLIB = libxilprofile.a + +CC_FLAGS = $(subst -pg, , $(COMPILER_FLAGS)) +ECC_FLAGS = $(subst -pg, , $(EXTRA_COMPILER_FLAGS)) + +RELEASEDIR = ../../../../lib +INCLUDEDIR = ../../../../include +INCLUDES = -I./. -I${INCLUDEDIR} + +OBJS = _profile_init.o _profile_clean.o _profile_timer_hw.o profile_hist.o profile_cg.o +DUMMYOBJ = dummy.o +INCLUDEFILES = profile.h mblaze_nt_types.h _profile_timer_hw.h + +libs : reallibs dummylibs + +reallibs : $(OBJS) $(PROFILE_ARCH_OBJS) + $(ARCHIVER) -r $(RELEASEDIR)/$(LIB) $(OBJS) $(PROFILE_ARCH_OBJS) + +dummylibs : $(DUMMYOBJ) + $(ARCHIVER) -r $(RELEASEDIR)/$(DUMMYLIB) $(DUMMYOBJ) + +%.o:%.c + $(COMPILER) $(CC_FLAGS) $(ECC_FLAGS) -c $< -o $@ $(INCLUDES) + +%.o:%.S + $(COMPILER) $(CC_FLAGS) $(ECC_FLAGS) -c $< -o $@ $(INCLUDES) + +include: + $(CP) -rf $(INCLUDEFILES) $(INCLUDEDIR) + +clean: + rm -f $(OBJS) $(PROFILE_ARCH_OBJS) $(LIB) diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/_profile_clean.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/_profile_clean.c new file mode 100644 index 0000000..b1c61f8 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/_profile_clean.c @@ -0,0 +1,43 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +#include "profile.h" +#include "_profile_timer_hw.h" +#include "xil_exception.h" + +void _profile_clean( void ); + +/* + * This function is the exit routine and is called by the crtinit, when the + * program terminates. The name needs to be changed later.. + */ +void _profile_clean( void ) +{ + Xil_ExceptionDisable(); + disable_timer(); +} diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/_profile_init.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/_profile_init.c new file mode 100644 index 0000000..050b0a7 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/_profile_init.c @@ -0,0 +1,86 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +****************************************************************************** +* +* _program_init.c: +* Initialize the Profiling Structures. +* +******************************************************************************/ + +#include "profile.h" + +/* XMD Initializes the following Global Variables Value during Program + * Download with appropriate values. */ + +#ifdef PROC_MICROBLAZE + +extern s32 microblaze_init(void); + +#elif defined PROC_PPC + +extern s32 powerpc405_init(void); + +#else + +extern s32 cortexa9_init(void); + +#endif + +s32 profile_version = 1; /* Version of S/W Intrusive Profiling library */ + +u32 binsize = (u32)BINSIZE; /* Histogram Bin Size */ +u32 cpu_clk_freq = (u32)CPU_FREQ_HZ ; /* CPU Clock Frequency */ +u32 sample_freq_hz = (u32)SAMPLE_FREQ_HZ ; /* Histogram Sampling Frequency */ +u32 timer_clk_ticks = (u32)TIMER_CLK_TICKS ;/* Timer Clock Ticks for the Timer */ + +/* Structure for Storing the Profiling Data */ +struct gmonparam *_gmonparam = (struct gmonparam *)(0xffffffffU); +s32 n_gmon_sections = 1; + +/* This is the initialization code, which is called from the crtinit. */ + +void _profile_init( void ) +{ +/* print("Gmon Init called....\r\n") */ +/* putnum(n_gmon_sections) , print("\r\n") */ +/* if( _gmonparam == 0xffffffff ) */ +/* printf("Gmonparam is NULL !!\r\n") */ +/* for( i = 0, i < n_gmon_sections, i++ )[ */ +/* putnum( _gmonparam[i].lowpc) , print("\t") */ +/* putnum( _gmonparam[i].highpc) , print("\r\n") */ +/* putnum( _gmonparam[i].textsize ), print("\r\n") */ +/* putnum( _gmonparam[i].kcountsize * sizeof(unsigned short)), print("\r\n") */ +/* ] */ + +#ifdef PROC_MICROBLAZE + (void)microblaze_init(); +#elif defined PROC_PPC + powerpc405_init(); +#else + (void)cortexa9_init(); +#endif +} diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/_profile_timer_hw.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/_profile_timer_hw.c new file mode 100644 index 0000000..c8243e5 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/_profile_timer_hw.c @@ -0,0 +1,383 @@ +/****************************************************************************** +* +* Copyright (C) 2004 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +****************************************************************************** +* +* _program_timer_hw.c: +* Timer related functions +* +******************************************************************************/ + +#include "profile.h" +#include "_profile_timer_hw.h" + +#include "xil_exception.h" + +#ifdef PROC_PPC +#include "xtime_l.h" +#include "xpseudo_asm.h" +#endif + +#ifdef TIMER_CONNECT_INTC +#include "xintc_l.h" +#include "xintc.h" +#endif /* TIMER_CONNECT_INTC */ + +/* #ifndef PPC_PIT_INTERRUPT */ +#if (!defined PPC_PIT_INTERRUPT && !defined PROC_CORTEXA9) +#include "xtmrctr_l.h" +#endif + +/* extern u32 timer_clk_ticks, */ + +#ifdef PROC_PPC405 +#ifdef PPC_PIT_INTERRUPT +s32 ppc_pit_init( void ); +#endif +s32 powerpc405_init() +#endif /* PROC_CORTEXA9 */ + +#ifdef PROC_PPC440 +#ifdef PPC_PIT_INTERRUPT +s32 ppc_dec_init( void ); +#endif +s32 powerpc405_init(void); +#endif /* PROC_PPC440 */ + +#if (!defined PPC_PIT_INTERRUPT && !defined PROC_CORTEXA9) +s32 opb_timer_init( void ); +#endif + +#ifdef PROC_MICROBLAZE +s32 microblaze_init(void); +#endif /* PROC_MICROBLAZE */ + +#ifdef PROC_CORTEXA9 +s32 scu_timer_init( void ); +s32 cortexa9_init(void); +#endif /* PROC_CORTEXA9 */ + + +/*-------------------------------------------------------------------- + * PowerPC Target - Timer related functions + *-------------------------------------------------------------------- */ +#ifdef PROC_PPC405 + + +/*-------------------------------------------------------------------- +* PowerPC PIT Timer Init. +* Defined only if PIT Timer is used for Profiling +* +*-------------------------------------------------------------------- */ +#ifdef PPC_PIT_INTERRUPT +int ppc_pit_init( void ) +{ + /* 1. Register Profile_intr_handler as Interrupt handler */ + /* 2. Set PIT Timer Interrupt and Enable it. */ + Xil_ExceptionRegisterHandler( XIL_EXCEPTION_ID_PIT_INT, + (Xil_ExceptionHandler)profile_intr_handler,NULL); + XTime_PITSetInterval( timer_clk_ticks ) ; + XTime_PITEnableAutoReload() ; + return 0; +} +#endif + + +/* -------------------------------------------------------------------- +* PowerPC Timer Initialization functions. +* For PowerPC, PIT and opb_timer can be used for Profiling. This +* is selected by the user in standalone BSP +* +*-------------------------------------------------------------------- */ +s32 powerpc405_init() +{ + Xil_ExceptionInit() ; + Xil_ExceptionDisableMask( XIL_EXCEPTION_NON_CRITICAL ) ; + + /* Initialize the Timer. + * 1. If PowerPC PIT Timer has to be used, initialize PIT timer. + * 2. Else use opb_timer. It can be directly connected or thru intc to PowerPC */ +#ifdef PPC_PIT_INTERRUPT + ppc_pit_init(); +#else +#ifdef TIMER_CONNECT_INTC + Xil_ExceptionRegisterHandler( XIL_EXCEPTION_ID_NON_CRITICAL_INT, + (Xil_ExceptionHandler)XIntc_DeviceInterruptHandler,NULL); + XIntc_RegisterHandler( INTC_BASEADDR, PROFILE_TIMER_INTR_ID, + (XInterruptHandler)profile_intr_handler,NULL); +#else + Xil_ExceptionRegisterHandler( XIL_EXCEPTION_ID_NON_CRITICAL_INT, + (Xil_ExceptionHandler)profile_intr_handler,NULL); +#endif + /* Initialize the timer with Timer Ticks */ + opb_timer_init() ; +#endif + + /* Enable Interrupts in the System, if Profile Timer is the only Interrupt + * in the System. */ +#ifdef ENABLE_SYS_INTR +#ifdef PPC_PIT_INTERRUPT + XTime_PITEnableInterrupt() ; +#elif TIMER_CONNECT_INTC + XIntc_MasterEnable( INTC_BASEADDR ); + XIntc_SetIntrSvcOption( INTC_BASEADDR, XIN_SVC_ALL_ISRS_OPTION); + XIntc_EnableIntr( INTC_BASEADDR, PROFILE_TIMER_INTR_MASK ); +#endif + Xil_ExceptionEnableMask( XIL_EXCEPTION_NON_CRITICAL ) ; +#endif + return 0; +} + +#endif /* PROC_PPC */ + + + +/*-------------------------------------------------------------------- + * PowerPC440 Target - Timer related functions + * -------------------------------------------------------------------- */ +#ifdef PROC_PPC440 + + +/*-------------------------------------------------------------------- + * PowerPC DEC Timer Init. + * Defined only if DEC Timer is used for Profiling + * + *-------------------------------------------------------------------- */ +#ifdef PPC_PIT_INTERRUPT +s32 ppc_dec_init( void ) +{ + /* 1. Register Profile_intr_handler as Interrupt handler */ + /* 2. Set DEC Timer Interrupt and Enable it. */ + Xil_ExceptionRegisterHandler( XIL_EXCEPTION_ID_DEC_INT, + (Xil_ExceptionHandler)profile_intr_handler,NULL); + XTime_DECSetInterval( timer_clk_ticks ) ; + XTime_DECEnableAutoReload() ; + return 0; +} +#endif + + +/*-------------------------------------------------------------------- + * PowerPC Timer Initialization functions. + * For PowerPC, DEC and opb_timer can be used for Profiling. This + * is selected by the user in standalone BSP + * + *-------------------------------------------------------------------- */ +s32 powerpc405_init(void) +{ + Xil_ExceptionInit(); + Xil_ExceptionDisableMask( XIL_EXCEPTION_NON_CRITICAL ) ; + + /* Initialize the Timer. + * 1. If PowerPC DEC Timer has to be used, initialize DEC timer. + * 2. Else use opb_timer. It can be directly connected or thru intc to PowerPC */ +#ifdef PPC_PIT_INTERRUPT + ppc_dec_init(); +#else +#ifdef TIMER_CONNECT_INTC + Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_NON_CRITICAL_INT, + (Xil_ExceptionHandler)XIntc_DeviceInterruptHandler,NULL); + + XIntc_RegisterHandler( INTC_BASEADDR, PROFILE_TIMER_INTR_ID, + (XInterruptHandler)profile_intr_handler,NULL); +#else + Xil_ExceptionRegisterHandler( XIL_EXCEPTION_ID_NON_CRITICAL_INT, + (Xil_ExceptionHandler)profile_intr_handler,NULL); + Xil_ExceptionRegisterHandler( XIL_EXCEPTION_ID_NON_CRITICAL_INT, + (Xil_ExceptionHandler)profile_intr_handler,NULL); +#endif + /* Initialize the timer with Timer Ticks */ + opb_timer_init() ; +#endif + + /* Enable Interrupts in the System, if Profile Timer is the only Interrupt + * in the System. */ +#ifdef ENABLE_SYS_INTR +#ifdef PPC_PIT_INTERRUPT + XTime_DECEnableInterrupt() ; +#elif TIMER_CONNECT_INTC + XIntc_MasterEnable( INTC_BASEADDR ); + XIntc_SetIntrSvcOption( INTC_BASEADDR, XIN_SVC_ALL_ISRS_OPTION); + XIntc_EnableIntr( INTC_BASEADDR, PROFILE_TIMER_INTR_MASK ); +#endif + Xil_ExceptionEnableMask( XEXC_NON_CRITICAL ) ; +#endif + return 0; +} + +#endif /* PROC_PPC440 */ + +/* -------------------------------------------------------------------- + * opb_timer Initialization for PowerPC and MicroBlaze. This function + * is not needed if DEC timer is used in PowerPC + * + *-------------------------------------------------------------------- */ +/* #ifndef PPC_PIT_INTERRUPT */ +#if (!defined PPC_PIT_INTERRUPT && !defined PROC_CORTEXA9) +s32 opb_timer_init( void ) +{ + /* set the number of cycles the timer counts before interrupting */ + XTmrCtr_SetLoadReg((u32)PROFILE_TIMER_BASEADDR, (u16)0, (u32)timer_clk_ticks); + + /* reset the timers, and clear interrupts */ + XTmrCtr_SetControlStatusReg((u32)PROFILE_TIMER_BASEADDR, (u16)0, + (u32)XTC_CSR_INT_OCCURED_MASK | (u32)XTC_CSR_LOAD_MASK ); + + /* start the timers */ + XTmrCtr_SetControlStatusReg((u32)PROFILE_TIMER_BASEADDR, (u16)0, (u32)XTC_CSR_ENABLE_TMR_MASK + | (u32)XTC_CSR_ENABLE_INT_MASK | (u32)XTC_CSR_AUTO_RELOAD_MASK | (u32)XTC_CSR_DOWN_COUNT_MASK); + return 0; +} +#endif + + +/*-------------------------------------------------------------------- + * MicroBlaze Target - Timer related functions + *-------------------------------------------------------------------- */ +#ifdef PROC_MICROBLAZE + +/* -------------------------------------------------------------------- + * Initialize the Profile Timer for MicroBlaze Target. + * For MicroBlaze, opb_timer is used. The opb_timer can be directly + * connected to MicroBlaze or connected through Interrupt Controller. + * + *-------------------------------------------------------------------- */ +s32 microblaze_init(void) +{ + /* Register profile_intr_handler + * 1. If timer is connected to Interrupt Controller, register the handler + * to Interrupt Controllers vector table. + * 2. If timer is directly connected to MicroBlaze, register the handler + * as Interrupt handler */ + Xil_ExceptionInit(); + +#ifdef TIMER_CONNECT_INTC + XIntc_RegisterHandler( INTC_BASEADDR, PROFILE_TIMER_INTR_ID, + (XInterruptHandler)profile_intr_handler,NULL); +#else + Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, + (Xil_ExceptionHandler)profile_intr_handler, + NULL) ; +#endif + + /* Initialize the timer with Timer Ticks */ + (void)opb_timer_init() ; + + /* Enable Interrupts in the System, if Profile Timer is the only Interrupt + * in the System. */ +#ifdef ENABLE_SYS_INTR +#ifdef TIMER_CONNECT_INTC + XIntc_MasterEnable((u32)INTC_BASEADDR ); + XIntc_SetIntrSvcOption( INTC_BASEADDR, XIN_SVC_ALL_ISRS_OPTION); + XIntc_EnableIntr( (u32)INTC_BASEADDR, PROFILE_TIMER_INTR_MASK ); + Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, + (Xil_ExceptionHandler)XIntc_DeviceInterruptHandler,NULL); +#endif + +#endif + + Xil_ExceptionEnable(); + + return 0; + +} + +#endif /* PROC_MICROBLAZE */ + + + +/* -------------------------------------------------------------------- + * Cortex A9 Target - Timer related functions + *-------------------------------------------------------------------- */ +#ifdef PROC_CORTEXA9 + +/* -------------------------------------------------------------------- + * Initialize the Profile Timer for Cortex A9 Target. + * The scu private timer is connected to the Scu GIC controller. + * + *-------------------------------------------------------------------- */ +s32 scu_timer_init( void ) +{ + /* set the number of cycles the timer counts before interrupting + * scu timer runs at half the cpu clock */ + XScuTimer_SetLoadReg(PROFILE_TIMER_BASEADDR, timer_clk_ticks/2U); + + /* clear any pending interrupts */ + XScuTimer_SetIntrReg(PROFILE_TIMER_BASEADDR, 1U); + + /* enable interrupts, auto-reload mode and start the timer */ + XScuTimer_SetControlReg(PROFILE_TIMER_BASEADDR, XSCUTIMER_CONTROL_IRQ_ENABLE_MASK | + XSCUTIMER_CONTROL_AUTO_RELOAD_MASK | XSCUTIMER_CONTROL_ENABLE_MASK); + + return 0; +} + +s32 cortexa9_init(void) +{ + + Xil_ExceptionInit(); + + XScuGic_DeviceInitialize(0); + + /* + * Connect the interrupt controller interrupt handler to the hardware + * interrupt handling logic in the processor. + */ + Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_IRQ_INT, + (Xil_ExceptionHandler)XScuGic_DeviceInterruptHandler, + NULL); + + /* + * Connect the device driver handler that will be called when an + * interrupt for the device occurs, the handler defined above performs + * the specific interrupt processing for the device. + */ + XScuGic_RegisterHandler(SCUGIC_CPU_BASEADDR, + PROFILE_TIMER_INTR_ID, + (Xil_ExceptionHandler)profile_intr_handler, + NULL); + + /* + * Enable the interrupt for scu timer. + */ + XScuGic_EnableIntr(SCUGIC_DIST_BASEADDR, PROFILE_TIMER_INTR_ID); + + /* + * Enable interrupts in the Processor. + */ + Xil_ExceptionEnableMask(XIL_EXCEPTION_IRQ); + + /* + * Initialize the timer with Timer Ticks + */ + (void)scu_timer_init() ; + + Xil_ExceptionEnable(); + + return 0; +} + +#endif /* PROC_CORTEXA9 */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/_profile_timer_hw.h b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/_profile_timer_hw.h new file mode 100644 index 0000000..1647600 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/_profile_timer_hw.h @@ -0,0 +1,308 @@ +/****************************************************************************** +* +* Copyright (C) 2004 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +****************************************************************************** +* +* _program_timer_hw.h: +* Timer related functions +* +******************************************************************************/ + +#ifndef PROFILE_TIMER_HW_H +#define PROFILE_TIMER_HW_H + +#include "profile.h" + +#ifdef PROC_PPC +#if defined __GNUC__ +# define SYNCHRONIZE_IO __asm__ volatile ("eieio") +#elif defined __DCC__ +# define SYNCHRONIZE_IO __asm volatile(" eieio") +#else +# define SYNCHRONIZE_IO +#endif +#endif + +#ifdef PROC_PPC +#define ProfIo_In32(InputPtr) { (*(volatile u32 *)(InputPtr)); SYNCHRONIZE_IO; } +#define ProfIo_Out32(OutputPtr, Value) { (*(volatile u32 *)(OutputPtr) = Value); SYNCHRONIZE_IO; } +#else +#define ProfIo_In32(InputPtr) (*(volatile u32 *)(InputPtr)); +#define ProfIo_Out32(OutputPtr, Value) { (*(volatile u32 *)(OutputPtr) = (Value)); } +#endif + +#define ProfTmrCtr_mWriteReg(BaseAddress, TmrCtrNumber, RegOffset, ValueToWrite)\ + ProfIo_Out32(((u32)(BaseAddress) + (u32)XTmrCtr_Offsets[(TmrCtrNumber)] + \ + (u32)(RegOffset)), (u32)(ValueToWrite)) + +#define ProfTimerCtr_mReadReg(BaseAddress, TmrCtrNumber, RegOffset) \ + ProfIo_In32((u32)(BaseAddress) + (u32)XTmrCtr_Offsets[(TmrCtrNumber)] + (u32)(RegOffset)) + +#define ProfTmrCtr_mSetControlStatusReg(BaseAddress, TmrCtrNumber, RegisterValue)\ + ProfTmrCtr_mWriteReg((BaseAddress), (TmrCtrNumber), XTC_TCSR_OFFSET, \ + (RegisterValue)) + +#define ProfTmrCtr_mGetControlStatusReg(BaseAddress, TmrCtrNumber) \ + ProfTimerCtr_mReadReg((u32)(BaseAddress), (TmrCtrNumber), XTC_TCSR_OFFSET) + + + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef PROC_PPC +#include "xexception_l.h" +#include "xtime_l.h" +#include "xpseudo_asm.h" +#endif + +#ifdef TIMER_CONNECT_INTC +#include "xintc_l.h" +#include "xintc.h" +#endif /* TIMER_CONNECT_INTC */ + +#if (!defined PPC_PIT_INTERRUPT && !defined PROC_CORTEXA9) +#include "xtmrctr_l.h" +#endif + +#ifdef PROC_CORTEXA9 +#include "xscutimer_hw.h" +#include "xscugic.h" +#endif + +extern u32 timer_clk_ticks ; + +/*-------------------------------------------------------------------- + * PowerPC Target - Timer related functions + *-------------------------------------------------------------------- */ +#ifdef PROC_PPC + +#ifdef PPC_PIT_INTERRUPT +u32 timer_lo_clk_ticks ; /* Clk ticks when Timer is disabled in CG */ +#endif + +#ifdef PROC_PPC440 +#define XREG_TCR_PIT_INTERRUPT_ENABLE XREG_TCR_DEC_INTERRUPT_ENABLE +#define XREG_TSR_PIT_INTERRUPT_STATUS XREG_TSR_DEC_INTERRUPT_STATUS +#define XREG_SPR_PIT XREG_SPR_DEC +#define XEXC_ID_PIT_INT XEXC_ID_DEC_INT +#endif + +/* -------------------------------------------------------------------- + * Disable the Timer - During Profiling + * + * For PIT Timer - + * 1. XTime_PITDisableInterrupt() ; + * 2. Store the remaining timer clk tick + * 3. Stop the PIT Timer + *-------------------------------------------------------------------- */ + +#ifdef PPC_PIT_INTERRUPT +#define disable_timer() \ + { \ + u32 val; \ + val=mfspr(XREG_SPR_TCR); \ + mtspr(XREG_SPR_TCR, val & (~XREG_TCR_PIT_INTERRUPT_ENABLE)); \ + timer_lo_clk_ticks = mfspr(XREG_SPR_PIT); \ + mtspr(XREG_SPR_PIT, 0); \ + } +#else +#define disable_timer() \ + { \ + u32 addr = (PROFILE_TIMER_BASEADDR) + XTmrCtr_Offsets[(0)] + XTC_TCSR_OFFSET; \ + u32 tmp_v = ProfIo_In32(addr); \ + tmp_v = tmp_v & (~XTC_CSR_ENABLE_TMR_MASK); \ + ProfIo_Out32((PROFILE_TIMER_BASEADDR) + XTmrCtr_Offsets[(0)] + XTC_TCSR_OFFSET, tmp_v); \ + } +#endif + + + +/* -------------------------------------------------------------------- + * Enable the Timer + * + * For PIT Timer - + * 1. Load the remaining timer clk ticks + * 2. XTime_PITEnableInterrupt() ; + *-------------------------------------------------------------------- */ +#ifdef PPC_PIT_INTERRUPT +#define enable_timer() \ + { \ + u32 val; \ + val=mfspr(XREG_SPR_TCR); \ + mtspr(XREG_SPR_PIT, timer_lo_clk_ticks); \ + mtspr(XREG_SPR_TCR, val | XREG_TCR_PIT_INTERRUPT_ENABLE); \ + } +#else +#define enable_timer() \ + { \ + u32 addr = (PROFILE_TIMER_BASEADDR) + XTmrCtr_Offsets[(0)] + XTC_TCSR_OFFSET; \ + u32 tmp_v = ProfIo_In32(addr); \ + tmp_v = tmp_v | XTC_CSR_ENABLE_TMR_MASK; \ + ProfIo_Out32((PROFILE_TIMER_BASEADDR) + XTmrCtr_Offsets[(0)] + XTC_TCSR_OFFSET, tmp_v); \ + } +#endif + + + +/* -------------------------------------------------------------------- + * Send Ack to Timer Interrupt + * + * For PIT Timer - + * 1. Load the timer clk ticks + * 2. Enable AutoReload and Interrupt + * 3. Clear PIT Timer Status bits + *-------------------------------------------------------------------- */ +#ifdef PPC_PIT_INTERRUPT +#define timer_ack() \ + { \ + u32 val; \ + mtspr(XREG_SPR_PIT, timer_clk_ticks); \ + mtspr(XREG_SPR_TSR, XREG_TSR_PIT_INTERRUPT_STATUS); \ + val=mfspr(XREG_SPR_TCR); \ + mtspr(XREG_SPR_TCR, val| XREG_TCR_PIT_INTERRUPT_ENABLE| XREG_TCR_AUTORELOAD_ENABLE); \ + } +#else +#define timer_ack() \ + { \ + u32 csr; \ + csr = ProfTmrCtr_mGetControlStatusReg(PROFILE_TIMER_BASEADDR, 0); \ + ProfTmrCtr_mSetControlStatusReg(PROFILE_TIMER_BASEADDR, 0, csr); \ + } +#endif + +/*-------------------------------------------------------------------- */ +#endif /* PROC_PPC */ +/* -------------------------------------------------------------------- */ + + + + +/* -------------------------------------------------------------------- + * MicroBlaze Target - Timer related functions + *-------------------------------------------------------------------- */ +#ifdef PROC_MICROBLAZE + +/* -------------------------------------------------------------------- + * Disable the Timer during Call-Graph Data collection + * + *-------------------------------------------------------------------- */ +#define disable_timer() \ + { \ + u32 Addr = ((u32)PROFILE_TIMER_BASEADDR); \ + Addr += (u32)XTmrCtr_Offsets[(u16)(0)]; \ + Addr += (u32)XTC_TCSR_OFFSET; \ + u32 tmp_v = ProfIo_In32(Addr); \ + tmp_v = tmp_v & (u32)(~XTC_CSR_ENABLE_TMR_MASK); \ + u32 OutAddr = (u32)PROFILE_TIMER_BASEADDR; \ + OutAddr += (u32)XTmrCtr_Offsets[(u16)(0)]; \ + OutAddr += (u32)XTC_TCSR_OFFSET; \ + ProfIo_Out32(OutAddr, (u32)tmp_v); \ + } + + +/* -------------------------------------------------------------------- + * Enable the Timer after Call-Graph Data collection + * + *-------------------------------------------------------------------- */ +#define enable_timer() \ + { \ + u32 Addr = ((u32)PROFILE_TIMER_BASEADDR); \ + Addr += (u32)XTmrCtr_Offsets[(u16)(0)]; \ + Addr += (u32)XTC_TCSR_OFFSET; \ + u32 tmp_v = (u32)ProfIo_In32(Addr); \ + tmp_v = tmp_v | (u32)XTC_CSR_ENABLE_TMR_MASK; \ + ProfIo_Out32((u32)(PROFILE_TIMER_BASEADDR) + (u32)XTmrCtr_Offsets[(u16)(0)] + (u32)XTC_TCSR_OFFSET, (u32)tmp_v); \ + } + + +/* -------------------------------------------------------------------- + * Send Ack to Timer Interrupt + * + *-------------------------------------------------------------------- */ +#define timer_ack() \ + { \ + u32 csr; \ + csr = ProfTmrCtr_mGetControlStatusReg((u32)PROFILE_TIMER_BASEADDR, (u16)0); \ + ProfTmrCtr_mSetControlStatusReg((u32)PROFILE_TIMER_BASEADDR, (u16)0, (u32)csr); \ + } + +/*-------------------------------------------------------------------- */ +#endif /* PROC_MICROBLAZE */ +/*-------------------------------------------------------------------- */ + +/* -------------------------------------------------------------------- + * Cortex A9 Target - Timer related functions + *-------------------------------------------------------------------- */ +#ifdef PROC_CORTEXA9 + +/* -------------------------------------------------------------------- + * Disable the Timer during Call-Graph Data collection + * + *-------------------------------------------------------------------- */ +#define disable_timer() \ +{ \ + u32 Reg; \ + Reg = Xil_In32(PROFILE_TIMER_BASEADDR + XSCUTIMER_CONTROL_OFFSET); \ + Reg &= (~XSCUTIMER_CONTROL_ENABLE_MASK);\ + Xil_Out32(PROFILE_TIMER_BASEADDR + XSCUTIMER_CONTROL_OFFSET, Reg);\ +} + + +/* -------------------------------------------------------------------- + * Enable the Timer after Call-Graph Data collection + * + *-------------------------------------------------------------------- */ +#define enable_timer() \ +{ \ + u32 Reg; \ + Reg = Xil_In32(PROFILE_TIMER_BASEADDR + XSCUTIMER_CONTROL_OFFSET); \ + Reg |= XSCUTIMER_CONTROL_ENABLE_MASK; \ + Xil_Out32(PROFILE_TIMER_BASEADDR + XSCUTIMER_CONTROL_OFFSET, Reg);\ +} + + +/* -------------------------------------------------------------------- + * Send Ack to Timer Interrupt + * + *-------------------------------------------------------------------- */ +#define timer_ack() \ +{ \ + Xil_Out32((u32)PROFILE_TIMER_BASEADDR + (u32)XSCUTIMER_ISR_OFFSET, \ + (u32)XSCUTIMER_ISR_EVENT_FLAG_MASK);\ +} + +/*-------------------------------------------------------------------- */ +#endif /* PROC_CORTEXA9 */ +/*-------------------------------------------------------------------- */ + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/dummy.S b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/dummy.S new file mode 100644 index 0000000..f4ff406 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/dummy.S @@ -0,0 +1,60 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + + .globl dummy_f + +#ifdef PROC_MICROBLAZE + .text + .align 2 + .ent dummy_f + +dummy_f: + nop + + .end dummy_f +#endif + +#ifdef PROC_PPC + .section .text + .align 2 + .type dummy_f@function + +dummy_f: + b dummy_f + +#endif + +#ifdef PROC_CORTEXA9 + .section .text + .align 2 + .type dummy_f, %function + +dummy_f: + b dummy_f + +#endif diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/mblaze_nt_types.h b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/mblaze_nt_types.h new file mode 100644 index 0000000..807dda3 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/mblaze_nt_types.h @@ -0,0 +1,50 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + + +#ifndef _MBLAZE_NT_TYPES_H +#define _MBLAZE_NT_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef char byte; +typedef short half; +typedef int word; +typedef unsigned char ubyte; +typedef unsigned short uhalf; +typedef unsigned int uword; +typedef ubyte boolean; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/profile.h b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/profile.h new file mode 100644 index 0000000..63f503a --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/profile.h @@ -0,0 +1,127 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +#ifndef PROFILE_H +#define PROFILE_H 1 + +#include +#include "xil_types.h" +#include "profile_config.h" + +#ifdef PROC_MICROBLAZE +#include "mblaze_nt_types.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +void _system_init( void ) ; +void _system_clean( void ) ; +void mcount(u32 frompc, u32 selfpc); +void profile_intr_handler( void ) ; +void _profile_init( void ); + + + +/**************************************************************************** + * Profiling on hardware - Hash table maintained on hardware and data sent + * to xmd for gmon.out generation. + ****************************************************************************/ +/* + * histogram counters are unsigned shorts (according to the kernel). + */ +#define HISTCOUNTER u16 + +struct tostruct { + u32 selfpc; + s32 count; + s16 link; + u16 pad; +}; + +struct fromstruct { + u32 frompc ; + s16 link ; + u16 pad ; +} ; + +/* + * general rounding functions. + */ +#define ROUNDDOWN(x,y) (((x)/(y))*(y)) +#define ROUNDUP(x,y) ((((x)+(y)-1)/(y))*(y)) + +/* + * The profiling data structures are housed in this structure. + */ +struct gmonparam { + s32 state; + + /* Histogram Information */ + u16 *kcount; /* No. of bins in histogram */ + u32 kcountsize; /* Histogram samples */ + + /* Call-graph Information */ + struct fromstruct *froms; + u32 fromssize; + struct tostruct *tos; + u32 tossize; + + /* Initialization I/Ps */ + u32 lowpc; + u32 highpc; + u32 textsize; + /* u32 cg_froms, */ + /* u32 cg_tos, */ +}; +extern struct gmonparam *_gmonparam; +extern s32 n_gmon_sections; + +/* + * Possible states of profiling. + */ +#define GMON_PROF_ON 0 +#define GMON_PROF_BUSY 1 +#define GMON_PROF_ERROR 2 +#define GMON_PROF_OFF 3 + +/* + * Sysctl definitions for extracting profiling information from the kernel. + */ +#define GPROF_STATE 0 /* int: profiling enabling variable */ +#define GPROF_COUNT 1 /* struct: profile tick count buffer */ +#define GPROF_FROMS 2 /* struct: from location hash bucket */ +#define GPROF_TOS 3 /* struct: destination/count structure */ +#define GPROF_GMONPARAM 4 /* struct: profiling parameters (see above) */ + +#ifdef __cplusplus +} +#endif + +#endif /* PROFILE_H */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/profile_cg.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/profile_cg.c new file mode 100644 index 0000000..328e6fc --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/profile_cg.c @@ -0,0 +1,167 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +#include "profile.h" +#include "_profile_timer_hw.h" +#ifdef PROC_MICROBLAZE +#include "mblaze_nt_types.h" +#endif + +/* + * The mcount fucntion is excluded from the library, if the user defines + * PROFILE_NO_GRAPH. + */ +#ifndef PROFILE_NO_GRAPH + +#include +#include +#include + +#ifdef PROFILE_NO_FUNCPTR +s32 searchpc(const struct fromto_struct *cgtable, s32 cgtable_size, u32 frompc ); +#else +s32 searchpc(const struct fromstruct *froms, s32 fromssize, u32 frompc ); +#endif + +/*extern struct gmonparam *_gmonparam, */ + +#ifdef PROFILE_NO_FUNCPTR +s32 searchpc(const struct fromto_struct *cgtable, s32 cgtable_size, u32 frompc ) +{ + s32 index = 0 ; + + while( (index < cgtable_size) && (cgtable[index].frompc != frompc) ){ + index++ ; + } + if( index == cgtable_size ) { + return -1 ; + } else { + return index ; + } +} +#else +s32 searchpc(const struct fromstruct *froms, s32 fromssize, u32 frompc ) +{ + s32 index = 0 ; + s32 Status; + + while( (index < fromssize) && (froms[index].frompc != frompc) ){ + index++ ; + } + if( index == fromssize ) { + Status = -1 ; + } else { + Status = index ; + } + return Status; +} +#endif /* PROFILE_NO_FUNCPTR */ + + +void mcount( u32 frompc, u32 selfpc ) +{ + register struct gmonparam *p = NULL; + register s32 toindex, fromindex; + s32 j; + + disable_timer(); + + /*print("CG: "), putnum(frompc), print("->"), putnum(selfpc), print("\r\n") , + * check that frompcindex is a reasonable pc value. + * for example: signal catchers get called from the stack, + * not from text space. too bad. + */ + for(j = 0; j < n_gmon_sections; j++ ){ + if((frompc >= _gmonparam[j].lowpc) && (frompc < _gmonparam[j].highpc)) { + p = &_gmonparam[j]; + break; + } + } + if( j == n_gmon_sections ) { + goto done; + } + +#ifdef PROFILE_NO_FUNCPTR + fromindex = searchpc( p->cgtable, p->cgtable_size, frompc ) ; + if( fromindex == -1 ) { + fromindex = p->cgtable_size ; + p->cgtable_size++ ; + p->cgtable[fromindex].frompc = frompc ; + p->cgtable[fromindex].selfpc = selfpc ; + p->cgtable[fromindex].count = 1 ; + goto done ; + } + p->cgtable[fromindex].count++ ; +#else + fromindex = (s32)searchpc( p->froms, ((s32)p->fromssize), frompc ) ; + if( fromindex == -1 ) { + fromindex = (s32)p->fromssize ; + p->fromssize++ ; + /*if( fromindex >= N_FROMS ) { + * print("Error : From PC table overflow\r\n") + * goto overflow + *}*/ + p->froms[fromindex].frompc = frompc ; + p->froms[fromindex].link = -1 ; + }else { + toindex = ((s32)(p->froms[fromindex].link)); + while(toindex != -1) { + toindex = (((s32)p->tossize) - toindex)-1 ; + if( p->tos[toindex].selfpc == selfpc ) { + p->tos[toindex].count++ ; + goto done ; + } + toindex = ((s32)(p->tos[toindex].link)) ; + } + } + + /*if( toindex == -1 ) { */ + p->tos-- ; + p->tossize++ ; + /* if( toindex >= N_TOS ) { + * print("Error : To PC table overflow\r\n") + * goto overflow + *} */ + p->tos[0].selfpc = selfpc ; + p->tos[0].count = 1 ; + p->tos[0].link = p->froms[fromindex].link ; + p->froms[fromindex].link = ((s32)(p->tossize))-((s32)1); +#endif + + done: + p->state = GMON_PROF_ON; + goto enable_timer_label ; + /* overflow: */ + /*p->state = GMON_PROF_ERROR */ + enable_timer_label: + enable_timer(); + return ; +} + + +#endif /* PROFILE_NO_GRAPH */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/profile_config.h b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/profile_config.h new file mode 100644 index 0000000..5d66311 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/profile_config.h @@ -0,0 +1,52 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + + +#ifndef _PROFILE_CONFIG_H +#define _PROFILE_CONFIG_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define BINSIZE 4U +#define SAMPLE_FREQ_HZ 100000U +#define TIMER_CLK_TICKS 1000U + +#define PROFILE_NO_FUNCPTR_FLAG 0 + +#define PROFILE_TIMER_BASEADDR 0x00608000U +#define PROFILE_TIMER_INTR_ID 0U + +#define TIMER_CONNECT_INTC + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/profile_hist.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/profile_hist.c new file mode 100644 index 0000000..b3e237b --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/profile_hist.c @@ -0,0 +1,67 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +#include "profile.h" +#include "_profile_timer_hw.h" + +#ifdef PROC_MICROBLAZE +#include "mblaze_nt_types.h" +#endif + +#ifdef PROC_PPC +#include "xpseudo_asm.h" +#define SPR_SRR0 0x01A +#endif + +#include "xil_types.h" + +extern u32 binsize ; +u32 prof_pc ; + +void profile_intr_handler( void ) +{ + + s32 j; + +#ifdef PROC_MICROBLAZE + asm( "swi r14, r0, prof_pc" ) ; +#elif defined PROC_PPC + prof_pc = mfspr(SPR_SRR0); +#else + /* for cortexa9, lr is saved in asm interrupt handler */ +#endif + /* print("PC: "), putnum(prof_pc), print("\r\n"), */ + for(j = 0; j < n_gmon_sections; j++ ){ + if((prof_pc >= ((u32)_gmonparam[j].lowpc)) && (prof_pc < ((u32)_gmonparam[j].highpc))) { + _gmonparam[j].kcount[(prof_pc-_gmonparam[j].lowpc)/((u32)4 * binsize)]++; + break; + } + } + /* Ack the Timer Interrupt */ + timer_ack(); +} diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/profile_mcount_arm.S b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/profile_mcount_arm.S new file mode 100644 index 0000000..9a84363 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/profile_mcount_arm.S @@ -0,0 +1,41 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +// based on "ARM Profiling Implementation" from Sourcery G++ Lite for ARM EABI + +.globl __gnu_mcount_nc +.type __gnu_mcount_nc, %function + +__gnu_mcount_nc: + push {r0, r1, r2, r3, lr} + subs r1, lr, #0 /* callee - current lr */ + ldr r0, [sp, #20] /* caller - at the top of the stack */ + bl mcount /* when __gnu_mcount_nc is called */ + pop {r0, r1, r2, r3, ip, lr} + bx ip + + .end __gnu_mcount_nc diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/profile_mcount_mb.S b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/profile_mcount_mb.S new file mode 100644 index 0000000..21ab5b4 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/profile_mcount_mb.S @@ -0,0 +1,65 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + + .globl _mcount + .text + .align 2 + .ent _mcount + + #ifndef PROFILE_NO_GRAPH + +_mcount: + addi r1, r1, -48 + swi r11, r1, 44 + swi r12, r1, 40 + swi r5, r1, 36 + swi r6, r1, 32 + swi r7, r1, 28 + swi r8, r1, 24 + swi r9, r1, 20 + swi r10, r1, 16 + swi r15, r1, 12 + add r5, r0, r15 + brlid r15, mcount + add r6, r0, r16 + + lwi r11, r1, 44 + lwi r12, r1, 40 + lwi r5, r1, 36 + lwi r6, r1, 32 + lwi r7, r1, 28 + lwi r8, r1, 24 + lwi r9, r1, 20 + lwi r10, r1, 16 + lwi r15, r1, 12 + rtsd r15, 4 + addi r1, r1, 48 + + #endif /* PROFILE_NO_GRAPH */ + + .end _mcount diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/profile_mcount_ppc.S b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/profile_mcount_ppc.S new file mode 100644 index 0000000..230df08 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/profile_mcount_ppc.S @@ -0,0 +1,67 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + + .globl _mcount + + #define _MCOUNT_STACK_FRAME 48 + .section .text + .align 2 + .type _mcount@function + + +_mcount: + stwu 1, -_MCOUNT_STACK_FRAME(1) + stw 3, 8(1) + stw 4, 12(1) + stw 5, 16(1) + stw 6, 20(1) + stw 7, 24(1) + stw 8, 28(1) + stw 9, 32(1) + stw 10, 36(1) + stw 11, 40(1) + stw 12, 44(1) + mflr 4 + stw 4, (_MCOUNT_STACK_FRAME+4)(1) + lwz 3, (_MCOUNT_STACK_FRAME)(1) + lwz 3, 4(3) + bl mcount + lwz 4, (_MCOUNT_STACK_FRAME+4)(1) + mtlr 4 + lwz 12, 44(1) + lwz 11, 40(1) + lwz 10, 36(1) + lwz 9, 32(1) + lwz 8, 28(1) + lwz 7, 24(1) + lwz 6, 20(1) + lwz 5, 16(1) + lwz 4, 12(1) + lwz 3, 8(1) + addi 1,1, _MCOUNT_STACK_FRAME + blr diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/putnum.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/putnum.c new file mode 100644 index 0000000..aaf9ede --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/putnum.c @@ -0,0 +1,59 @@ +/* putnum.c -- put a hex number on the output device. + * + * Copyright (c) 1995 Cygnus Support + * + * The authors hereby grant permission to use, copy, modify, distribute, + * and license this software and its documentation for any purpose, provided + * that existing copyright notices are retained in all copies and that this + * notice is included verbatim in any distributions. No written agreement, + * license, or royalty fee is required for any of the authorized uses. + * Modifications to this software may be copyrighted by their authors + * and need not follow the licensing terms described here, provided that + * the new terms are clearly indicated on the first page of each file where + * they apply. + */ + +/* + * putnum -- print a 32 bit number in hex + */ + +/***************************** Include Files *********************************/ +#include "xil_types.h" + +/************************** Function Prototypes ******************************/ +extern void print (const char8 *ptr); +void putnum(u32 num); + +void putnum(u32 num) +{ + char8 buf[9]; + s32 cnt; + s32 i; + char8 *ptr; + u32 digit; + for(i = 0; i<9; i++) { + buf[i] = '0'; + } + + ptr = buf; + for (cnt = 7 ; cnt >= 0 ; cnt--) { + digit = (num >> (cnt * 4U)) & 0x0000000fU; + + if ((digit <= 9U) && (ptr != NULL)) { + digit += (u32)'0'; + *ptr = ((char8) digit); + ptr += 1; + } else if (ptr != NULL) { + digit += ((u32)'a' - (u32)10); + *ptr = ((char8)digit); + ptr += 1; + } else { + /*Made for MisraC Compliance*/; + } + } + + if(ptr != NULL) { + *ptr = (char8) 0; + } + print (buf); +} diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/read.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/read.c new file mode 100644 index 0000000..9900842 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/read.c @@ -0,0 +1,100 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +/* read.c -- read bytes from a input device. + */ +#ifndef UNDEFINE_FILE_OPS +#include "xil_printf.h" +#include "xparameters.h" + +#ifdef __cplusplus +extern "C" { + __attribute__((weak)) s32 _read (s32 fd, char8* buf, s32 nbytes); +} +#endif + +/* + * read -- read bytes from the serial port. Ignore fd, since + * we only have stdin. + */ +__attribute__((weak)) s32 +read (s32 fd, char8* buf, s32 nbytes) +{ +#ifdef STDIN_BASEADDRESS + s32 i; + s32 numbytes = 0; + char8* LocalBuf = buf; + + (void)fd; + if(LocalBuf != NULL) { + for (i = 0; i < nbytes; i++) { + numbytes++; + *(LocalBuf + i) = inbyte(); + if ((*(LocalBuf + i) == '\n' )|| (*(LocalBuf + i) == '\r')) { + break; + } + } + } + + return numbytes; +#else + (void)fd; + (void)buf; + (void)nbytes; + return 0; +#endif +} + +__attribute__((weak)) s32 +_read (s32 fd, char8* buf, s32 nbytes) +{ +#ifdef STDIN_BASEADDRESS + s32 i; + s32 numbytes = 0; + char8* LocalBuf = buf; + + (void)fd; + if(LocalBuf != NULL) { + for (i = 0; i < nbytes; i++) { + numbytes++; + *(LocalBuf + i) = inbyte(); + if ((*(LocalBuf + i) == '\n' )|| (*(LocalBuf + i) == '\r')) { + break; + } + } + } + + return numbytes; +#else + (void)fd; + (void)buf; + (void)nbytes; + return 0; +#endif +} +#endif diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/sbrk.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/sbrk.c new file mode 100644 index 0000000..7f91b9c --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/sbrk.c @@ -0,0 +1,57 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +#include +#include "xil_types.h" +#ifdef __cplusplus +extern "C" { + __attribute__((weak)) char8 *sbrk (s32 nbytes); +} +#endif + +extern u8 _heap_start[]; +extern u8 _heap_end[]; +extern char8 HeapBase[]; +extern char8 HeapLimit[]; + + + +__attribute__((weak)) char8 *sbrk (s32 nbytes) +{ + char8 *base; + static char8 *heap_ptr = HeapBase; + + base = heap_ptr; + if((heap_ptr != NULL) && (heap_ptr + nbytes <= (char8 *)&HeapLimit + 1)) { + heap_ptr += nbytes; + return base; + } else { + errno = ENOMEM; + return ((char8 *)-1); + } +} diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/sleep.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/sleep.c new file mode 100644 index 0000000..659c21b --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/sleep.c @@ -0,0 +1,88 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2017 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/***************************************************************************** +* +* @file sleep.c +* +* This function provides a second delay using the Global Timer register in +* the ARM Cortex A9 MP core. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 1.00a ecm/sdm  11/11/09 First release
+* 3.07a sgd      07/05/12 Updated sleep function to make use Global
+* 6.0   asa      08/15/16 Updated the sleep signature. Fix for CR#956899.
+* 6.6	srm      10/18/17 Updated sleep routines to support user configurable
+*			  implementation. Now sleep routines will use Timer
+*                         specified by the user (i.e. Global timer/TTC timer)
+*
+* 
+* +******************************************************************************/ +/***************************** Include Files *********************************/ + +#include "sleep.h" +#include "xtime_l.h" +#include "xparameters.h" + +#if defined (SLEEP_TIMER_BASEADDR) +#include "xil_sleeptimer.h" +#endif + +/*****************************************************************************/ +/* +* +* This API is used to provide delays in seconds +* +* @param seconds requested +* +* @return 0 always +* +* @note None. +* +****************************************************************************/ +unsigned sleep_A9(unsigned int seconds) +{ +#if defined (SLEEP_TIMER_BASEADDR) + Xil_SleepTTCCommon(seconds, COUNTS_PER_SECOND); +#else + XTime tEnd, tCur; + + XTime_GetTime(&tCur); + tEnd = tCur + (((XTime) seconds) * COUNTS_PER_SECOND); + do + { + XTime_GetTime(&tCur); + } while (tCur < tEnd); +#endif + + return 0; +} diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/sleep.h b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/sleep.h new file mode 100644 index 0000000..f3a632b --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/sleep.h @@ -0,0 +1,115 @@ +/****************************************************************************** +* +* Copyright (C) 2014 - 2017 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +/*****************************************************************************/ +/** +* @file sleep.h +* +* This header file contains ARM Cortex A53,A9,R5,Microblaze specific sleep +* related APIs. +* +*
+* MODIFICATION HISTORY :
+*
+* Ver   Who  Date	 Changes
+* ----- ---- -------- -------------------------------------------------------
+* 6.6   srm  11/02/17 Added processor specific sleep rountines
+*								 function prototypes.
+*
+* 
+* +******************************************************************************/ + +#ifndef SLEEP_H +#define SLEEP_H + +#include "xil_types.h" +#include "xil_io.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*****************************************************************************/ +/** +* +* This macro polls an address periodically until a condition is met or till the +* timeout occurs. +* The minimum timeout for calling this macro is 100us. If the timeout is less +* than 100us, it still waits for 100us. Also the unit for the timeout is 100us. +* If the timeout is not a multiple of 100us, it waits for a timeout of +* the next usec value which is a multiple of 100us. +* +* @param IO_func - accessor function to read the register contents. +* Depends on the register width. +* @param ADDR - Address to be polled +* @param VALUE - variable to read the value +* @param COND - Condition to checked (usually involves VALUE) +* @param TIMEOUT_US - timeout in micro seconds +* +* @return 0 - when the condition is met +* -1 - when the condition is not met till the timeout period +* +* @note none +* +*****************************************************************************/ +#define Xil_poll_timeout(IO_func, ADDR, VALUE, COND, TIMEOUT_US) \ + ( { \ + u64 timeout = TIMEOUT_US/100; \ + if(TIMEOUT_US%100!=0) \ + timeout++; \ + for(;;) { \ + VALUE = IO_func(ADDR); \ + if(COND) \ + break; \ + else { \ + usleep(100); \ + timeout--; \ + if(timeout==0) \ + break; \ + } \ + } \ + (timeout>0) ? 0 : -1; \ + } ) + +void usleep(unsigned long useconds); +void sleep(unsigned int seconds); +int usleep_R5(unsigned long useconds); +unsigned sleep_R5(unsigned int seconds); +int usleep_MB(unsigned long useconds); +unsigned sleep_MB(unsigned int seconds); +int usleep_A53(unsigned long useconds); +unsigned sleep_A53(unsigned int seconds); +int usleep_A9(unsigned long useconds); +unsigned sleep_A9(unsigned int seconds); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/smc.h b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/smc.h new file mode 100644 index 0000000..f7cc91c --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/smc.h @@ -0,0 +1,110 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file smc.h +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- ---------------------------------------------------
+* 1.00a sdm  11/03/09 Initial release.
+* 4.2	pkp	 08/04/14 Removed function definition of XSmc_NorInit and XSmc_NorInit
+*					  as smc.c is removed
+* 
+* +* @note None. +* +******************************************************************************/ + +#ifndef SMC_H /* prevent circular inclusions */ +#define SMC_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xparameters.h" +#include "xil_io.h" + +/***************** Macros (Inline Functions) Definitions *********************/ + +/**************************** Type Definitions *******************************/ + +/************************** Constant Definitions *****************************/ + +/* Memory controller configuration register offset */ +#define XSMCPSS_MC_STATUS 0x000U /* Controller status reg, RO */ +#define XSMCPSS_MC_INTERFACE_CONFIG 0x004U /* Interface config reg, RO */ +#define XSMCPSS_MC_SET_CONFIG 0x008U /* Set configuration reg, WO */ +#define XSMCPSS_MC_CLR_CONFIG 0x00CU /* Clear config reg, WO */ +#define XSMCPSS_MC_DIRECT_CMD 0x010U /* Direct command reg, WO */ +#define XSMCPSS_MC_SET_CYCLES 0x014U /* Set cycles register, WO */ +#define XSMCPSS_MC_SET_OPMODE 0x018U /* Set opmode register, WO */ +#define XSMCPSS_MC_REFRESH_PERIOD_0 0x020U /* Refresh period_0 reg, RW */ +#define XSMCPSS_MC_REFRESH_PERIOD_1 0x024U /* Refresh period_1 reg, RW */ + +/* Chip select configuration register offset */ +#define XSMCPSS_CS_IF0_CHIP_0_OFFSET 0x100U /* Interface 0 chip 0 config */ +#define XSMCPSS_CS_IF0_CHIP_1_OFFSET 0x120U /* Interface 0 chip 1 config */ +#define XSMCPSS_CS_IF0_CHIP_2_OFFSET 0x140U /* Interface 0 chip 2 config */ +#define XSMCPSS_CS_IF0_CHIP_3_OFFSET 0x160U /* Interface 0 chip 3 config */ +#define XSMCPSS_CS_IF1_CHIP_0_OFFSET 0x180U /* Interface 1 chip 0 config */ +#define XSMCPSS_CS_IF1_CHIP_1_OFFSET 0x1A0U /* Interface 1 chip 1 config */ +#define XSMCPSS_CS_IF1_CHIP_2_OFFSET 0x1C0U /* Interface 1 chip 2 config */ +#define XSMCPSS_CS_IF1_CHIP_3_OFFSET 0x1E0U /* Interface 1 chip 3 config */ + +/* User configuration register offset */ +#define XSMCPSS_UC_STATUS_OFFSET 0x200U /* User status reg, RO */ +#define XSMCPSS_UC_CONFIG_OFFSET 0x204U /* User config reg, WO */ + +/* Integration test register offset */ +#define XSMCPSS_IT_OFFSET 0xE00U + +/* ID configuration register offset */ +#define XSMCPSS_ID_PERIP_0_OFFSET 0xFE0U +#define XSMCPSS_ID_PERIP_1_OFFSET 0xFE4U +#define XSMCPSS_ID_PERIP_2_OFFSET 0xFE8U +#define XSMCPSS_ID_PERIP_3_OFFSET 0xFECU +#define XSMCPSS_ID_PCELL_0_OFFSET 0xFF0U +#define XSMCPSS_ID_PCELL_1_OFFSET 0xFF4U +#define XSMCPSS_ID_PCELL_2_OFFSET 0xFF8U +#define XSMCPSS_ID_PCELL_3_OFFSET 0xFFCU + +/************************** Variable Definitions *****************************/ + +/************************** Function Prototypes ******************************/ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* SMC_H */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/translation_table.S b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/translation_table.S new file mode 100644 index 0000000..418ded8 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/translation_table.S @@ -0,0 +1,226 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file translation_table.s +* +* @addtogroup a9_boot_code +* @{ +*

translation_table.S

+* translation_table.S contains a static page table required by MMU for +* cortex-A9. This translation table is flat mapped (input address = output +* address) with default memory attributes defined for zynq architecture. It +* utilizes short descriptor translation table format with each section defining +* 1MB of memory. +* +* The overview of translation table memory attributes is described below. +* +*| | Memory Range | Definition in Translation Table | +*|-----------------------|-------------------------|-----------------------------------| +*| DDR | 0x00000000 - 0x3FFFFFFF | Normal write-back Cacheable | +*| PL | 0x40000000 - 0xBFFFFFFF | Strongly Ordered | +*| Reserved | 0xC0000000 - 0xDFFFFFFF | Unassigned | +*| Memory mapped devices | 0xE0000000 - 0xE02FFFFF | Device Memory | +*| Reserved | 0xE0300000 - 0xE0FFFFFF | Unassigned | +*| NAND, NOR | 0xE1000000 - 0xE3FFFFFF | Device memory | +*| SRAM | 0xE4000000 - 0xE5FFFFFF | Normal write-back Cacheable | +*| Reserved | 0xE6000000 - 0xF7FFFFFF | Unassigned | +*| AMBA APB Peripherals | 0xF8000000 - 0xF8FFFFFF | Device Memory | +*| Reserved | 0xF9000000 - 0xFBFFFFFF | Unassigned | +*| Linear QSPI - XIP | 0xFC000000 - 0xFDFFFFFF | Normal write-through cacheable | +*| Reserved | 0xFE000000 - 0xFFEFFFFF | Unassigned | +*| OCM | 0xFFF00000 - 0xFFFFFFFF | Normal inner write-back cacheable | +* +* @note +* +* For region 0x00000000 - 0x3FFFFFFF, a system where DDR is less than 1GB, +* region after DDR and before PL is marked as undefined/reserved in translation +* table. In 0xF8000000 - 0xF8FFFFFF, 0xF8000C00 - 0xF8000FFF, 0xF8010000 - +* 0xF88FFFFF and 0xF8F03000 to 0xF8FFFFFF are reserved but due to granual size +* of 1MB, it is not possible to define separate regions for them. For region +* 0xFFF00000 - 0xFFFFFFFF, 0xFFF00000 to 0xFFFB0000 is reserved but due to 1MB +* granual size, it is not possible to define separate region for it +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- ---------------------------------------------------
+* 1.00a ecm  10/20/09 Initial version
+* 3.04a sdm  01/13/12 Updated MMU table to mark DDR memory as Shareable
+* 3.07a sgd  07/05/2012 Configuring device address spaces as shareable device
+*		       instead of strongly-ordered.
+* 3.07a asa  07/17/2012 Changed the property of the ".mmu_tbl" section.
+* 4.2	pkp  09/02/2014 added entries for 0xfe000000 to 0xffefffff as reserved
+*			and  0xe0000000 - 0xe1ffffff is broken down into
+*			0xe0000000 - 0xe02fffff (memory mapped devides)
+*			0xe0300000 - 0xe0ffffff (reserved) and
+*			0xe1000000 - 0xe1ffffff (NAND)
+* 5.2	pkp  06/08/2015 put a check for XPAR_PS7_DDR_0_S_AXI_BASEADDR to confirm
+*			if DDR is present or not and accordingly generate the
+*			translation table
+* 6.1	pkp  07/11/2016 Corrected comments for memory attributes
+* 6.8   mus  07/12/2018 Mark DDR memory as inner cacheable, if BSP is built
+*			with the USE_AMP flag.
+* 
+* +* +******************************************************************************/ +#include "xparameters.h" + .globl MMUTable + + .section .mmu_tbl,"a" + +MMUTable: + /* Each table entry occupies one 32-bit word and there are + * 4096 entries, so the entire table takes up 16KB. + * Each entry covers a 1MB section. + */ +.set SECT, 0 + +#ifdef XPAR_PS7_DDR_0_S_AXI_BASEADDR +.set DDR_START, XPAR_PS7_DDR_0_S_AXI_BASEADDR +.set DDR_END, XPAR_PS7_DDR_0_S_AXI_HIGHADDR +.set DDR_SIZE, (DDR_END - DDR_START)+1 +.set DDR_REG, DDR_SIZE/0x100000 +#else +.set DDR_REG, 0 +#endif + +.set UNDEF_REG, 0x3FF - DDR_REG + +#ifndef USE_AMP + /*0x00000000 - 0x00100000 (inner and outer cacheable )*/ +.word SECT + 0x15de6 /* S=b1 TEX=b101 AP=b11, Domain=b1111, C=b0, B=b1 */ +#else + /*0x00000000 - 0x00100000 (inner cacheable )*/ +.word SECT + 0x14de6 /* S=b1 TEX=b100 AP=b11, Domain=b1111, C=b0, B=b1 */ +#endif +.set SECT, SECT+0x100000 + +.rept DDR_REG /* (DDR Cacheable) */ +.word SECT + 0x15de6 /* S=b1 TEX=b101 AP=b11, Domain=b1111, C=b0, B=b1 */ +.set SECT, SECT+0x100000 +.endr + +.rept UNDEF_REG /* (unassigned/reserved). + * Generates a translation fault if accessed */ +.word SECT + 0x0 /* S=b0 TEX=b000 AP=b00, Domain=b0, C=b0, B=b0 */ +.set SECT, SECT+0x100000 +.endr + + +.rept 0x0400 /* 0x40000000 - 0x7fffffff (FPGA slave0) */ +.word SECT + 0xc02 /* S=b0 TEX=b000 AP=b11, Domain=b0, C=b0, B=b0 */ +.set SECT, SECT+0x100000 +.endr + +.rept 0x0400 /* 0x80000000 - 0xbfffffff (FPGA slave1) */ +.word SECT + 0xc02 /* S=b0 TEX=b000 AP=b11, Domain=b0, C=b0, B=b0 */ +.set SECT, SECT+0x100000 +.endr + +.rept 0x0200 /* 0xc0000000 - 0xdfffffff (unassigned/reserved). + * Generates a translation fault if accessed */ +.word SECT + 0x0 /* S=b0 TEX=b000 AP=b00, Domain=b0, C=b0, B=b0 */ +.set SECT, SECT+0x100000 +.endr + +.rept 0x003 /* 0xe0000000 - 0xe02fffff (Memory mapped devices) + * UART/USB/IIC/SPI/CAN/GEM/GPIO/QSPI/SD/NAND */ +.word SECT + 0xc06 /* S=b0 TEX=b000 AP=b11, Domain=b0, C=b0, B=b1 */ +.set SECT, SECT+0x100000 +.endr + +.rept 0x0D /* 0xe0300000 - 0xe0ffffff (unassigned/reserved). + * Generates a translation fault if accessed */ +.word SECT + 0x0 /* S=b0 TEX=b000 AP=b00, Domain=b0, C=b0, B=b0 */ +.set SECT, SECT+0x100000 +.endr + +.rept 0x0010 /* 0xe1000000 - 0xe1ffffff (NAND) */ +.word SECT + 0xc06 /* S=b0 TEX=b000 AP=b11, Domain=b0, C=b0, B=b1 */ +.set SECT, SECT+0x100000 +.endr + +.rept 0x0020 /* 0xe2000000 - 0xe3ffffff (NOR) */ +.word SECT + 0xc06 /* S=b0 TEX=b000 AP=b11, Domain=b0, C=b0, B=b1 */ +.set SECT, SECT+0x100000 +.endr + +.rept 0x0020 /* 0xe4000000 - 0xe5ffffff (SRAM) */ +.word SECT + 0xc0e /* S=b0 TEX=b000 AP=b11, Domain=b0, C=b1, B=b1 */ +.set SECT, SECT+0x100000 +.endr + +.rept 0x0120 /* 0xe6000000 - 0xf7ffffff (unassigned/reserved). + * Generates a translation fault if accessed */ +.word SECT + 0x0 /* S=b0 TEX=b000 AP=b00, Domain=b0, C=b0, B=b0 */ +.set SECT, SECT+0x100000 +.endr + +/* 0xf8000c00 to 0xf8000fff, 0xf8010000 to 0xf88fffff and + 0xf8f03000 to 0xf8ffffff are reserved but due to granual size of + 1MB, it is not possible to define separate regions for them */ + +.rept 0x0010 /* 0xf8000000 - 0xf8ffffff (AMBA APB Peripherals) */ + +.word SECT + 0xc06 /* S=b0 TEX=b000 AP=b11, Domain=b0, C=b0, B=b1 */ +.set SECT, SECT+0x100000 +.endr + +.rept 0x0030 /* 0xf9000000 - 0xfbffffff (unassigned/reserved). + * Generates a translation fault if accessed */ +.word SECT + 0x0 /* S=b0 TEX=b000 AP=b00, Domain=b0, C=b0, B=b0 */ +.set SECT, SECT+0x100000 +.endr + +.rept 0x0020 /* 0xfc000000 - 0xfdffffff (Linear QSPI - XIP) */ +.word SECT + 0xc0a /* S=b0 TEX=b000 AP=b11, Domain=b0, C=b1, B=b0 */ +.set SECT, SECT+0x100000 +.endr + +.rept 0x001F /* 0xfe000000 - 0xffefffff (unassigned/reserved). + * Generates a translation fault if accessed */ +.word SECT + 0x0 /* S=b0 TEX=b000 AP=b00, Domain=b0, C=b0, B=b0 */ +.set SECT, SECT+0x100000 +.endr + +/* 0xfff00000 to 0xfffb0000 is reserved but due to granual size of + 1MB, it is not possible to define separate region for it + + 0xfff00000 - 0xffffffff + 256K OCM when mapped to high address space + inner-cacheable */ +.word SECT + 0x4c0e /* S=b0 TEX=b100 AP=b11, Domain=b0, C=b1, B=b1 */ +.set SECT, SECT+0x100000 + +.end +/** +* @} End of "addtogroup a9_boot_code". +*/ \ No newline at end of file diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/unlink.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/unlink.c new file mode 100644 index 0000000..abd0d87 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/unlink.c @@ -0,0 +1,46 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +#include +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { + __attribute__((weak)) sint32 unlink(char8 *path); +} +#endif +/* + * unlink -- since we have no file system, + * we just return an error. + */ +__attribute__((weak)) sint32 unlink(char8 *path) +{ + (void) path; + errno = EIO; + return (-1); +} diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/usleep.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/usleep.c new file mode 100644 index 0000000..0965233 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/usleep.c @@ -0,0 +1,103 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2017 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file usleep.c +* +* This function provides a microsecond delay using the Global Timer register in +* the ARM Cortex A9 MP core. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 1.00a ecm/sdm  11/11/09 First release
+* 3.07a sgd      07/05/12 Upadted micro sleep function to make use Global Timer
+* 4.2	pkp		 08/04/14 Removed unimplemented nanosleep routine as it is not
+*						  possible to generate timer in nanosecond due to
+*						  limited cpu frequency
+* 6.0   asa      08/15/16 Updated the usleep signature. Fix for CR#956899.
+* 6.6	srm	 10/18/17 Updated sleep routines to support user configurable
+*			  implementation. Now sleep routines will use Timer
+*                         specified by the user (i.e. Global timer/TTC timer)
+* 
+* +******************************************************************************/ +/***************************** Include Files *********************************/ + +#include "sleep.h" +#include "xtime_l.h" +#include "xparameters.h" +#include "xil_types.h" +#include "xpseudo_asm.h" +#include "xreg_cortexa9.h" + +#if defined (SLEEP_TIMER_BASEADDR) +#include "xil_sleeptimer.h" +#endif + +/**************************** Constant Definitions ************************/ +#if defined (SLEEP_TIMER_BASEADDR) +#define COUNTS_PER_USECOND (SLEEP_TIMER_FREQUENCY / 1000000) +#else +/* Global Timer is always clocked at half of the CPU frequency */ +#define COUNTS_PER_USECOND (XPAR_CPU_CORTEXA9_CORE_CLOCK_FREQ_HZ / (2U*1000000U)) +#endif + +/*****************************************************************************/ +/** +* +* This API gives a delay in microseconds +* +* @param useconds requested +* +* @return 0 if the delay can be achieved, -1 if the requested delay +* is out of range +* +* @note None. +* +****************************************************************************/ +int usleep_A9(unsigned long useconds) +{ +#if defined (SLEEP_TIMER_BASEADDR) + Xil_SleepTTCCommon(useconds, COUNTS_PER_USECOND); +#else + XTime tEnd, tCur; + + XTime_GetTime(&tCur); + tEnd = tCur + (((XTime) useconds) * COUNTS_PER_USECOND); + do + { + XTime_GetTime(&tCur); + } while (tCur < tEnd); +#endif + + return 0; +} diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/vectors.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/vectors.c new file mode 100644 index 0000000..2e23fc9 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/vectors.c @@ -0,0 +1,227 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2016 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file vectors.c +* +* This file contains the C level vectors for the ARM Cortex A9 core. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- ---------------------------------------------------
+* 1.00a ecm  10/20/09 Initial version, moved over from bsp area
+* 6.0   mus  27/07/16 Consolidated vectors for a53,a9 and r5 processor
+*                     and added UndefinedException for a53 32 bit and r5
+*                     processor
+* 
+* +* @note +* +* None. +* +******************************************************************************/ +/***************************** Include Files *********************************/ + +#include "xil_exception.h" +#include "vectors.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +typedef struct { + Xil_ExceptionHandler Handler; + void *Data; +} XExc_VectorTableEntry; + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Variable Definitions *****************************/ + +extern XExc_VectorTableEntry XExc_VectorTable[]; + +/************************** Function Prototypes ******************************/ + + +/*****************************************************************************/ +/** +* +* This is the C level wrapper for the FIQ interrupt called from the vectors.s +* file. +* +* @param None. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void FIQInterrupt(void) +{ + XExc_VectorTable[XIL_EXCEPTION_ID_FIQ_INT].Handler(XExc_VectorTable[ + XIL_EXCEPTION_ID_FIQ_INT].Data); +} + +/*****************************************************************************/ +/** +* +* This is the C level wrapper for the IRQ interrupt called from the vectors.s +* file. +* +* @param None. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void IRQInterrupt(void) +{ + XExc_VectorTable[XIL_EXCEPTION_ID_IRQ_INT].Handler(XExc_VectorTable[ + XIL_EXCEPTION_ID_IRQ_INT].Data); +} + +#if !defined (__aarch64__) +/*****************************************************************************/ +/** +* +* This is the C level wrapper for the Undefined exception called from the +* vectors.s file. +* +* @param None. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void UndefinedException(void) +{ + XExc_VectorTable[XIL_EXCEPTION_ID_UNDEFINED_INT].Handler(XExc_VectorTable[ + XIL_EXCEPTION_ID_UNDEFINED_INT].Data); +} + +/*****************************************************************************/ +/** +* +* This is the C level wrapper for the SW Interrupt called from the vectors.s +* file. +* +* @param None. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void SWInterrupt(void) +{ + XExc_VectorTable[XIL_EXCEPTION_ID_SWI_INT].Handler(XExc_VectorTable[ + XIL_EXCEPTION_ID_SWI_INT].Data); +} + +/*****************************************************************************/ +/** +* +* This is the C level wrapper for the DataAbort Interrupt called from the +* vectors.s file. +* +* @param None. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void DataAbortInterrupt(void) +{ + XExc_VectorTable[XIL_EXCEPTION_ID_DATA_ABORT_INT].Handler( + XExc_VectorTable[XIL_EXCEPTION_ID_DATA_ABORT_INT].Data); +} + +/*****************************************************************************/ +/** +* +* This is the C level wrapper for the PrefetchAbort Interrupt called from the +* vectors.s file. +* +* @param None. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void PrefetchAbortInterrupt(void) +{ + XExc_VectorTable[XIL_EXCEPTION_ID_PREFETCH_ABORT_INT].Handler( + XExc_VectorTable[XIL_EXCEPTION_ID_PREFETCH_ABORT_INT].Data); +} +#else + +/*****************************************************************************/ +/** +* +* This is the C level wrapper for the Synchronous Interrupt called from the vectors.s +* file. +* +* @param None. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void SynchronousInterrupt(void) +{ + XExc_VectorTable[XIL_EXCEPTION_ID_SYNC_INT].Handler(XExc_VectorTable[ + XIL_EXCEPTION_ID_SYNC_INT].Data); +} + +/*****************************************************************************/ +/** +* +* This is the C level wrapper for the SError Interrupt called from the +* vectors.s file. +* +* @param None. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void SErrorInterrupt(void) +{ + XExc_VectorTable[XIL_EXCEPTION_ID_SERROR_ABORT_INT].Handler( + XExc_VectorTable[XIL_EXCEPTION_ID_SERROR_ABORT_INT].Data); +} + +#endif diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/vectors.h b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/vectors.h new file mode 100644 index 0000000..56bacbc --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/vectors.h @@ -0,0 +1,84 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2016 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file vectors.h +* +* This file contains the C level vector prototypes for the ARM Cortex A9 core. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- ---------------------------------------------------
+* 1.00a ecm  10/20/10 Initial version, moved over from bsp area
+* 6.0   mus  07/27/16 Consolidated vectors for a9,a53 and r5 processors
+* 
+* +* @note +* +* None. +* +******************************************************************************/ + +#ifndef _VECTORS_H_ +#define _VECTORS_H_ + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" + +#ifdef __cplusplus +extern "C" { +#endif +/***************** Macros (Inline Functions) Definitions *********************/ + +/**************************** Type Definitions *******************************/ + +/************************** Constant Definitions *****************************/ + +/************************** Function Prototypes ******************************/ + +void FIQInterrupt(void); +void IRQInterrupt(void); +#if !defined (__aarch64__) +void SWInterrupt(void); +void DataAbortInterrupt(void); +void PrefetchAbortInterrupt(void); +void UndefinedException(void); +#else +void SynchronousInterrupt(void); +void SErrorInterrupt(void); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* protection macro */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/write.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/write.c new file mode 100644 index 0000000..dc10ed7 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/write.c @@ -0,0 +1,117 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +/* write.c -- write bytes to an output device. + */ +#ifndef UNDEFINE_FILE_OPS +#include "xil_printf.h" +#include "xparameters.h" + +#ifdef __cplusplus +extern "C" { + __attribute__((weak)) sint32 _write (sint32 fd, char8* buf, sint32 nbytes); +} +#endif + +/* + * write -- write bytes to the serial port. Ignore fd, since + * stdout and stderr are the same. Since we have no filesystem, + * open will only return an error. + */ +__attribute__((weak)) sint32 +write (sint32 fd, char8* buf, sint32 nbytes) + +{ +#ifdef STDOUT_BASEADDRESS + s32 i; + char8* LocalBuf = buf; + + (void)fd; + for (i = 0; i < nbytes; i++) { + if(LocalBuf != NULL) { + LocalBuf += i; + } + if(LocalBuf != NULL) { + if (*LocalBuf == '\n') { + outbyte ('\r'); + } + outbyte (*LocalBuf); + } + if(LocalBuf != NULL) { + LocalBuf -= i; + } + } + return (nbytes); +#else + (void)fd; + (void)buf; + (void)nbytes; + return 0; +#endif +} + +__attribute__((weak)) sint32 +_write (sint32 fd, char8* buf, sint32 nbytes) +{ +#if HYP_GUEST && EL1_NONSECURE && XEN_USE_PV_CONSOLE + sint32 length; + + (void)fd; + (void)nbytes; + length = XPVXenConsole_Write(buf); + return length; +#else +#ifdef STDOUT_BASEADDRESS + s32 i; + char8* LocalBuf = buf; + + (void)fd; + for (i = 0; i < nbytes; i++) { + if(LocalBuf != NULL) { + LocalBuf += i; + } + if(LocalBuf != NULL) { + if (*LocalBuf == '\n') { + outbyte ('\r'); + } + outbyte (*LocalBuf); + } + if(LocalBuf != NULL) { + LocalBuf -= i; + } + } + return (nbytes); +#else + (void)fd; + (void)buf; + (void)nbytes; + return 0; +#endif +#endif +} +#endif diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xbasic_types.h b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xbasic_types.h new file mode 100644 index 0000000..2d9b245 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xbasic_types.h @@ -0,0 +1,127 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xbasic_types.h +* +* +* @note Dummy File for backwards compatibility +* + +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date   Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a adk   1/31/14  Added in bsp common folder for backward compatibility
+* 7.0   aru   01/21/19 Modified the typedef of u32,u16,u8
+* 7.0 	aru   02/06/19 Included stdint.h and stddef.h
+* 
+* +******************************************************************************/ + +#ifndef XBASIC_TYPES_H /* prevent circular inclusions */ +#define XBASIC_TYPES_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +/** @name Legacy types + * Deprecated legacy types. + * @{ + */ +typedef uint8_t Xuint8; /**< unsigned 8-bit */ +typedef char Xint8; /**< signed 8-bit */ +typedef uint16_t Xuint16; /**< unsigned 16-bit */ +typedef short Xint16; /**< signed 16-bit */ +typedef uint32_t Xuint32; /**< unsigned 32-bit */ +typedef long Xint32; /**< signed 32-bit */ +typedef float Xfloat32; /**< 32-bit floating point */ +typedef double Xfloat64; /**< 64-bit double precision FP */ +typedef unsigned long Xboolean; /**< boolean (XTRUE or XFALSE) */ + +#if !defined __XUINT64__ +typedef struct +{ + Xuint32 Upper; + Xuint32 Lower; +} Xuint64; +#endif + +/** @name New types + * New simple types. + * @{ + */ +#ifndef __KERNEL__ +#ifndef XIL_TYPES_H +typedef Xuint32 u32; +typedef Xuint16 u16; +typedef Xuint8 u8; +#endif +#else +#include +#endif + +#ifndef TRUE +# define TRUE 1U +#endif + +#ifndef FALSE +# define FALSE 0U +#endif + +#ifndef NULL +#define NULL 0U +#endif + +/* + * Xilinx NULL, TRUE and FALSE legacy support. Deprecated. + * Please use NULL, TRUE and FALSE + */ +#define XNULL NULL +#define XTRUE TRUE +#define XFALSE FALSE + +/* + * This file is deprecated and users + * should use xil_types.h and xil_assert.h\n\r + */ +#warning The xbasics_type.h file is deprecated and users should use xil_types.h and xil_assert. +#warning Please refer the Standalone BSP UG647 for further details + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xdebug.h b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xdebug.h new file mode 100644 index 0000000..b09c02d --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xdebug.h @@ -0,0 +1,40 @@ +#ifndef XDEBUG /* prevent circular inclusions */ +#define XDEBUG /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(DEBUG) && !defined(NDEBUG) + +#ifndef XDEBUG_WARNING +#define XDEBUG_WARNING +#warning DEBUG is enabled +#endif + +int printf(const char *format, ...); + +#define XDBG_DEBUG_ERROR 0x00000001U /* error condition messages */ +#define XDBG_DEBUG_GENERAL 0x00000002U /* general debug messages */ +#define XDBG_DEBUG_ALL 0xFFFFFFFFU /* all debugging data */ + +#define xdbg_current_types (XDBG_DEBUG_GENERAL) + +#define xdbg_stmnt(x) x + +#define xdbg_printf(type, ...) (((type) & xdbg_current_types) ? printf (__VA_ARGS__) : 0) + + +#else /* defined(DEBUG) && !defined(NDEBUG) */ + +#define xdbg_stmnt(x) + +#define xdbg_printf(...) + +#endif /* defined(DEBUG) && !defined(NDEBUG) */ + +#ifdef __cplusplus +} +#endif + +#endif /* XDEBUG */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xenv.h b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xenv.h new file mode 100644 index 0000000..9c7c4c3 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xenv.h @@ -0,0 +1,183 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xenv.h +* +* Defines common services that are typically found in a host operating. +* environment. This include file simply includes an OS specific file based +* on the compile-time constant BUILD_ENV_*, where * is the name of the target +* environment. +* +* All services are defined as macros. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00b ch   10/24/02 Added XENV_LINUX
+* 1.00a rmm  04/17/02 First release
+* 
+* +******************************************************************************/ + +#ifndef XENV_H /* prevent circular inclusions */ +#define XENV_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Select which target environment we are operating under + */ + +/* VxWorks target environment */ +#if defined XENV_VXWORKS +#include "xenv_vxworks.h" + +/* Linux target environment */ +#elif defined XENV_LINUX +#include "xenv_linux.h" + +/* Unit test environment */ +#elif defined XENV_UNITTEST +#include "ut_xenv.h" + +/* Integration test environment */ +#elif defined XENV_INTTEST +#include "int_xenv.h" + +/* Standalone environment selected */ +#else +#include "xenv_standalone.h" +#endif + + +/* + * The following comments specify the types and macro wrappers that are + * expected to be defined by the target specific header files + */ + +/**************************** Type Definitions *******************************/ + +/*****************************************************************************/ +/** + * + * XENV_TIME_STAMP + * + * A structure that contains a time stamp used by other time stamp macros + * defined below. This structure is processor dependent. + */ + + +/***************** Macros (Inline Functions) Definitions *********************/ + +/*****************************************************************************/ +/** + * + * XENV_MEM_COPY(void *DestPtr, void *SrcPtr, unsigned Bytes) + * + * Copies a non-overlapping block of memory. + * + * @param DestPtr is the destination address to copy data to. + * @param SrcPtr is the source address to copy data from. + * @param Bytes is the number of bytes to copy. + * + * @return None + */ + +/*****************************************************************************/ +/** + * + * XENV_MEM_FILL(void *DestPtr, char Data, unsigned Bytes) + * + * Fills an area of memory with constant data. + * + * @param DestPtr is the destination address to set. + * @param Data contains the value to set. + * @param Bytes is the number of bytes to set. + * + * @return None + */ +/*****************************************************************************/ +/** + * + * XENV_TIME_STAMP_GET(XTIME_STAMP *StampPtr) + * + * Samples the processor's or external timer's time base counter. + * + * @param StampPtr is the storage for the retrieved time stamp. + * + * @return None + */ + +/*****************************************************************************/ +/** + * + * XENV_TIME_STAMP_DELTA_US(XTIME_STAMP *Stamp1Ptr, XTIME_STAMP* Stamp2Ptr) + * + * Computes the delta between the two time stamps. + * + * @param Stamp1Ptr - First sampled time stamp. + * @param Stamp1Ptr - Sedond sampled time stamp. + * + * @return An unsigned int value with units of microseconds. + */ + +/*****************************************************************************/ +/** + * + * XENV_TIME_STAMP_DELTA_MS(XTIME_STAMP *Stamp1Ptr, XTIME_STAMP* Stamp2Ptr) + * + * Computes the delta between the two time stamps. + * + * @param Stamp1Ptr - First sampled time stamp. + * @param Stamp1Ptr - Sedond sampled time stamp. + * + * @return An unsigned int value with units of milliseconds. + */ + +/*****************************************************************************//** + * + * XENV_USLEEP(unsigned delay) + * + * Delay the specified number of microseconds. + * + * @param delay is the number of microseconds to delay. + * + * @return None + */ + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xenv_standalone.h b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xenv_standalone.h new file mode 100644 index 0000000..ef905af --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xenv_standalone.h @@ -0,0 +1,364 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xenv_standalone.h +* +* Defines common services specified by xenv.h. +* +* @note +* This file is not intended to be included directly by driver code. +* Instead, the generic xenv.h file is intended to be included by driver +* code. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a wgr  02/28/07 Added cache handling macros.
+* 1.00a wgr  02/27/07 Simplified code. Deprecated old-style macro names.
+* 1.00a rmm  01/24/06 Implemented XENV_USLEEP. Assume implementation is being
+*                     used under Xilinx standalone BSP.
+* 1.00a xd   11/03/04 Improved support for doxygen.
+* 1.00a rmm  03/21/02 First release
+* 1.00a wgr  03/22/07 Converted to new coding style.
+* 1.00a rpm  06/29/07 Added udelay macro for standalone
+* 1.00a xd   07/19/07 Included xparameters.h as XPAR_ constants are referred
+*                     to in MICROBLAZE section
+* 1.00a ecm  09/19/08 updated for v7.20 of Microblaze, new functionality
+*
+* 
+* +* +******************************************************************************/ + +#ifndef XENV_STANDALONE_H +#define XENV_STANDALONE_H + +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ +/****************************************************************************** + * + * Get the processor dependent includes + * + ******************************************************************************/ + +#include + +#if defined __MICROBLAZE__ +# include "mb_interface.h" +# include "xparameters.h" /* XPAR constants used below in MB section */ + +#elif defined __PPC__ +# include "sleep.h" +# include "xcache_l.h" /* also include xcache_l.h for caching macros */ +#endif + +/****************************************************************************** + * + * MEMCPY / MEMSET related macros. + * + * The following are straight forward implementations of memset and memcpy. + * + * NOTE: memcpy may not work if source and target memory area are overlapping. + * + ******************************************************************************/ +/*****************************************************************************/ +/** + * + * Copies a non-overlapping block of memory. + * + * @param DestPtr + * Destination address to copy data to. + * + * @param SrcPtr + * Source address to copy data from. + * + * @param Bytes + * Number of bytes to copy. + * + * @return None. + * + * @note + * The use of XENV_MEM_COPY is deprecated. Use memcpy() instead. + * + * @note + * This implemention MAY BREAK work if source and target memory + * area are overlapping. + * + *****************************************************************************/ + +#define XENV_MEM_COPY(DestPtr, SrcPtr, Bytes) \ + memcpy((void *) DestPtr, (const void *) SrcPtr, (size_t) Bytes) + + + +/*****************************************************************************/ +/** + * + * Fills an area of memory with constant data. + * + * @param DestPtr + * Destination address to copy data to. + * + * @param Data + * Value to set. + * + * @param Bytes + * Number of bytes to copy. + * + * @return None. + * + * @note + * The use of XENV_MEM_FILL is deprecated. Use memset() instead. + * + *****************************************************************************/ + +#define XENV_MEM_FILL(DestPtr, Data, Bytes) \ + memset((void *) DestPtr, (s32) Data, (size_t) Bytes) + + + +/****************************************************************************** + * + * TIME related macros + * + ******************************************************************************/ + +/** + * A structure that contains a time stamp used by other time stamp macros + * defined below. This structure is processor dependent. + */ +typedef s32 XENV_TIME_STAMP; + +/*****************************************************************************/ +/** + * + * Time is derived from the 64 bit PPC timebase register + * + * @param StampPtr is the storage for the retrieved time stamp. + * + * @return None. + * + * @note + * + * Signature: void XENV_TIME_STAMP_GET(XTIME_STAMP *StampPtr) + *

+ * This macro must be implemented by the user. + * + *****************************************************************************/ +#define XENV_TIME_STAMP_GET(StampPtr) + +/*****************************************************************************/ +/** + * + * This macro is not yet implemented and always returns 0. + * + * @param Stamp1Ptr is the first sampled time stamp. + * @param Stamp2Ptr is the second sampled time stamp. + * + * @return 0 + * + * @note + * + * This macro must be implemented by the user. + * + *****************************************************************************/ +#define XENV_TIME_STAMP_DELTA_US(Stamp1Ptr, Stamp2Ptr) (0) + +/*****************************************************************************/ +/** + * + * This macro is not yet implemented and always returns 0. + * + * @param Stamp1Ptr is the first sampled time stamp. + * @param Stamp2Ptr is the second sampled time stamp. + * + * @return 0 + * + * @note + * + * This macro must be implemented by the user. + * + *****************************************************************************/ +#define XENV_TIME_STAMP_DELTA_MS(Stamp1Ptr, Stamp2Ptr) (0) + +/*****************************************************************************/ +/** + * XENV_USLEEP(unsigned delay) + * + * Delay the specified number of microseconds. Not implemented without OS + * support. + * + * @param delay + * Number of microseconds to delay. + * + * @return None. + * + *****************************************************************************/ + +#ifdef __PPC__ +#define XENV_USLEEP(delay) usleep(delay) +#define udelay(delay) usleep(delay) +#else +#define XENV_USLEEP(delay) +#define udelay(delay) +#endif + + +/****************************************************************************** + * + * CACHE handling macros / mappings + * + ******************************************************************************/ +/****************************************************************************** + * + * Processor independent macros + * + ******************************************************************************/ + +#define XCACHE_ENABLE_CACHE() \ + { XCACHE_ENABLE_DCACHE(); XCACHE_ENABLE_ICACHE(); } + +#define XCACHE_DISABLE_CACHE() \ + { XCACHE_DISABLE_DCACHE(); XCACHE_DISABLE_ICACHE(); } + + +/****************************************************************************** + * + * MicroBlaze case + * + * NOTE: Currently the following macros will only work on systems that contain + * only ONE MicroBlaze processor. Also, the macros will only be enabled if the + * system is built using a xparameters.h file. + * + ******************************************************************************/ + +#if defined __MICROBLAZE__ + +/* Check if MicroBlaze data cache was built into the core. + */ +#if (XPAR_MICROBLAZE_USE_DCACHE == 1) +# define XCACHE_ENABLE_DCACHE() microblaze_enable_dcache() +# define XCACHE_DISABLE_DCACHE() microblaze_disable_dcache() +# define XCACHE_INVALIDATE_DCACHE() microblaze_invalidate_dcache() + +# define XCACHE_INVALIDATE_DCACHE_RANGE(Addr, Len) \ + microblaze_invalidate_dcache_range((s32)(Addr), (s32)(Len)) + +#if (XPAR_MICROBLAZE_DCACHE_USE_WRITEBACK == 1) +# define XCACHE_FLUSH_DCACHE() microblaze_flush_dcache() +# define XCACHE_FLUSH_DCACHE_RANGE(Addr, Len) \ + microblaze_flush_dcache_range((s32)(Addr), (s32)(Len)) +#else +# define XCACHE_FLUSH_DCACHE() microblaze_invalidate_dcache() +# define XCACHE_FLUSH_DCACHE_RANGE(Addr, Len) \ + microblaze_invalidate_dcache_range((s32)(Addr), (s32)(Len)) +#endif /*XPAR_MICROBLAZE_DCACHE_USE_WRITEBACK*/ + +#else +# define XCACHE_ENABLE_DCACHE() +# define XCACHE_DISABLE_DCACHE() +# define XCACHE_INVALIDATE_DCACHE_RANGE(Addr, Len) +# define XCACHE_FLUSH_DCACHE_RANGE(Addr, Len) +#endif /*XPAR_MICROBLAZE_USE_DCACHE*/ + + +/* Check if MicroBlaze instruction cache was built into the core. + */ +#if (XPAR_MICROBLAZE_USE_ICACHE == 1) +# define XCACHE_ENABLE_ICACHE() microblaze_enable_icache() +# define XCACHE_DISABLE_ICACHE() microblaze_disable_icache() + +# define XCACHE_INVALIDATE_ICACHE() microblaze_invalidate_icache() + +# define XCACHE_INVALIDATE_ICACHE_RANGE(Addr, Len) \ + microblaze_invalidate_icache_range((s32)(Addr), (s32)(Len)) + +#else +# define XCACHE_ENABLE_ICACHE() +# define XCACHE_DISABLE_ICACHE() +#endif /*XPAR_MICROBLAZE_USE_ICACHE*/ + + +/****************************************************************************** + * + * PowerPC case + * + * Note that the XCACHE_ENABLE_xxx functions are hardcoded to enable a + * specific memory region (0x80000001). Each bit (0-30) in the regions + * bitmask stands for 128MB of memory. Bit 31 stands for the upper 2GB + * range. + * + * regions --> cached address range + * ------------|-------------------------------------------------- + * 0x80000000 | [0, 0x7FFFFFF] + * 0x00000001 | [0xF8000000, 0xFFFFFFFF] + * 0x80000001 | [0, 0x7FFFFFF],[0xF8000000, 0xFFFFFFFF] + * + ******************************************************************************/ + +#elif defined __PPC__ + +#define XCACHE_ENABLE_DCACHE() XCache_EnableDCache(0x80000001) +#define XCACHE_DISABLE_DCACHE() XCache_DisableDCache() +#define XCACHE_ENABLE_ICACHE() XCache_EnableICache(0x80000001) +#define XCACHE_DISABLE_ICACHE() XCache_DisableICache() + +#define XCACHE_INVALIDATE_DCACHE_RANGE(Addr, Len) \ + XCache_InvalidateDCacheRange((u32)(Addr), (u32)(Len)) + +#define XCACHE_FLUSH_DCACHE_RANGE(Addr, Len) \ + XCache_FlushDCacheRange((u32)(Addr), (u32)(Len)) + +#define XCACHE_INVALIDATE_ICACHE() XCache_InvalidateICache() + + +/****************************************************************************** + * + * Unknown processor / architecture + * + ******************************************************************************/ + +#else +/* #error "Unknown processor / architecture. Must be MicroBlaze or PowerPC." */ +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* #ifndef XENV_STANDALONE_H */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil-crt0.S b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil-crt0.S new file mode 100644 index 0000000..8ea3a09 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil-crt0.S @@ -0,0 +1,155 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2017 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file xil-crt0.S +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- ---------------------------------------------------
+* 1.00a ecm  10/20/09 Initial version
+* 3.05a sdm  02/02/12 Added code for profiling
+* 3.06a sgd  05/16/12 Added global constructors and cleanup code
+*                     Uart initialization based on compiler flag
+* 3.07a sgd  07/05/12 Updated with reset and start Global Timer
+* 3.07a sgd  10/19/12 SMC NOR and SRAM initialization with build option
+* 4.2	pkp  08/04/14 Removed PEEP board related code which contained
+*		      initialization of uart smc nor and sram
+* 5.3	pkp  10/07/15 Added support for OpenAMP by not initializing global
+*		      timer when USE_AMP flag is defined
+* 6.6   srm  10/18/17 Added timer configuration using XTime_StartTTCTimer API.
+*		      Now the TTC instance as specified by the user will be
+*		      started.
+* 
+* +* @note +* +* None. +* +******************************************************************************/ +#include "bspconfig.h" + + .file "xil-crt0.S" + .section ".got2","aw" + .align 2 + + .text +.Lsbss_start: + .long __sbss_start + +.Lsbss_end: + .long __sbss_end + +.Lbss_start: + .long __bss_start + +.Lbss_end: + .long __bss_end + +.Lstack: + .long __stack + + + .globl _start +_start: + bl __cpu_init /* Initialize the CPU first (BSP provides this) */ + + mov r0, #0 + + /* clear sbss */ + ldr r1,.Lsbss_start /* calculate beginning of the SBSS */ + ldr r2,.Lsbss_end /* calculate end of the SBSS */ + +.Lloop_sbss: + cmp r1,r2 + bge .Lenclsbss /* If no SBSS, no clearing required */ + str r0, [r1], #4 + b .Lloop_sbss + +.Lenclsbss: + /* clear bss */ + ldr r1,.Lbss_start /* calculate beginning of the BSS */ + ldr r2,.Lbss_end /* calculate end of the BSS */ + +.Lloop_bss: + cmp r1,r2 + bge .Lenclbss /* If no BSS, no clearing required */ + str r0, [r1], #4 + b .Lloop_bss + +.Lenclbss: + + /* set stack pointer */ + ldr r13,.Lstack /* stack address */ + + /* Reset and start Global Timer */ + mov r0, #0x0 + mov r1, #0x0 + + /* Reset and start Triple Timer Counter */ + #if defined SLEEP_TIMER_BASEADDR + bl XTime_StartTTCTimer + #endif + +#if USE_AMP != 1 + bl XTime_SetTime +#endif + +#ifdef PROFILING /* defined in Makefile */ + /* Setup profiling stuff */ + bl _profile_init +#endif /* PROFILING */ + + /* run global constructors */ + bl __libc_init_array + + /* make sure argc and argv are valid */ + mov r0, #0 + mov r1, #0 + + /* Let her rip */ + bl main + + /* Cleanup global constructors */ + bl __libc_fini_array + +#ifdef PROFILING + /* Cleanup profiling stuff */ + bl _profile_clean +#endif /* PROFILING */ + + /* All done */ + bl exit + +.Lexit: /* should never get here */ + b .Lexit + +.Lstart: + .size _start,.Lstart-_start diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_assert.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_assert.c new file mode 100644 index 0000000..f6ec066 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_assert.c @@ -0,0 +1,143 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2016 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_assert.c +* +* This file contains basic assert related functions for Xilinx software IP. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date   Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a hbm  07/14/09 Initial release
+* 6.0   kvn  05/31/16 Make Xil_AsserWait a global variable
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Variable Definitions *****************************/ + +/** + * This variable allows testing to be done easier with asserts. An assert + * sets this variable such that a driver can evaluate this variable + * to determine if an assert occurred. + */ +u32 Xil_AssertStatus; + +/** + * This variable allows the assert functionality to be changed for testing + * such that it does not wait infinitely. Use the debugger to disable the + * waiting during testing of asserts. + */ +s32 Xil_AssertWait = 1; + +/* The callback function to be invoked when an assert is taken */ +static Xil_AssertCallback Xil_AssertCallbackRoutine = NULL; + +/************************** Function Prototypes ******************************/ + +/*****************************************************************************/ +/** +* +* @brief Implement assert. Currently, it calls a user-defined callback +* function if one has been set. Then, it potentially enters an +* infinite loop depending on the value of the Xil_AssertWait +* variable. +* +* @param file: filename of the source +* @param line: linenumber within File +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void Xil_Assert(const char8 *File, s32 Line) +{ + /* if the callback has been set then invoke it */ + if (Xil_AssertCallbackRoutine != 0) { + (*Xil_AssertCallbackRoutine)(File, Line); + } + + /* if specified, wait indefinitely such that the assert will show up + * in testing + */ + while (Xil_AssertWait != 0) { + } +} + +/*****************************************************************************/ +/** +* +* @brief Set up a callback function to be invoked when an assert occurs. +* If a callback is already installed, then it will be replaced. +* +* @param routine: callback to be invoked when an assert is taken +* +* @return None. +* +* @note This function has no effect if NDEBUG is set +* +******************************************************************************/ +void Xil_AssertSetCallback(Xil_AssertCallback Routine) +{ + Xil_AssertCallbackRoutine = Routine; +} + +/*****************************************************************************/ +/** +* +* @brief Null handler function. This follows the XInterruptHandler +* signature for interrupt handlers. It can be used to assign a null +* handler (a stub) to an interrupt controller vector table. +* +* @param NullParameter: arbitrary void pointer and not used. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XNullHandler(void *NullParameter) +{ + (void) NullParameter; +} diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_assert.h b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_assert.h new file mode 100644 index 0000000..917de31 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_assert.h @@ -0,0 +1,191 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_assert.h +* +* @addtogroup common_assert_apis Assert APIs and Macros +* +* The xil_assert.h file contains assert related functions and macros. +* Assert APIs/Macros specifies that a application program satisfies certain +* conditions at particular points in its execution. These function can be +* used by application programs to ensure that, application code is satisfying +* certain conditions. +* +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date   Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a hbm  07/14/09 First release
+* 6.0   kvn  05/31/16 Make Xil_AsserWait a global variable
+* 
+* +******************************************************************************/ + +#ifndef XIL_ASSERT_H /* prevent circular inclusions */ +#define XIL_ASSERT_H /* by using protection macros */ + +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/***************************** Include Files *********************************/ + + +/************************** Constant Definitions *****************************/ + +#define XIL_ASSERT_NONE 0U +#define XIL_ASSERT_OCCURRED 1U +#define XNULL NULL + +extern u32 Xil_AssertStatus; +extern s32 Xil_AssertWait; +extern void Xil_Assert(const char8 *File, s32 Line); +void XNullHandler(void *NullParameter); + +/** + * This data type defines a callback to be invoked when an + * assert occurs. The callback is invoked only when asserts are enabled + */ +typedef void (*Xil_AssertCallback) (const char8 *File, s32 Line); + +/***************** Macros (Inline Functions) Definitions *********************/ + +#ifndef NDEBUG + +/*****************************************************************************/ +/** +* @brief This assert macro is to be used for void functions. This in +* conjunction with the Xil_AssertWait boolean can be used to +* accomodate tests so that asserts which fail allow execution to +* continue. +* +* @param Expression: expression to be evaluated. If it evaluates to +* false, the assert occurs. +* +* @return Returns void unless the Xil_AssertWait variable is true, in which +* case no return is made and an infinite loop is entered. +* +******************************************************************************/ +#define Xil_AssertVoid(Expression) \ +{ \ + if (Expression) { \ + Xil_AssertStatus = XIL_ASSERT_NONE; \ + } else { \ + Xil_Assert(__FILE__, __LINE__); \ + Xil_AssertStatus = XIL_ASSERT_OCCURRED; \ + return; \ + } \ +} + +/*****************************************************************************/ +/** +* @brief This assert macro is to be used for functions that do return a +* value. This in conjunction with the Xil_AssertWait boolean can be +* used to accomodate tests so that asserts which fail allow execution +* to continue. +* +* @param Expression: expression to be evaluated. If it evaluates to false, +* the assert occurs. +* +* @return Returns 0 unless the Xil_AssertWait variable is true, in which +* case no return is made and an infinite loop is entered. +* +******************************************************************************/ +#define Xil_AssertNonvoid(Expression) \ +{ \ + if (Expression) { \ + Xil_AssertStatus = XIL_ASSERT_NONE; \ + } else { \ + Xil_Assert(__FILE__, __LINE__); \ + Xil_AssertStatus = XIL_ASSERT_OCCURRED; \ + return 0; \ + } \ +} + +/*****************************************************************************/ +/** +* @brief Always assert. This assert macro is to be used for void functions. +* Use for instances where an assert should always occur. +* +* @return Returns void unless the Xil_AssertWait variable is true, in which +* case no return is made and an infinite loop is entered. +* +******************************************************************************/ +#define Xil_AssertVoidAlways() \ +{ \ + Xil_Assert(__FILE__, __LINE__); \ + Xil_AssertStatus = XIL_ASSERT_OCCURRED; \ + return; \ +} + +/*****************************************************************************/ +/** +* @brief Always assert. This assert macro is to be used for functions that +* do return a value. Use for instances where an assert should always +* occur. +* +* @return Returns void unless the Xil_AssertWait variable is true, in which +* case no return is made and an infinite loop is entered. +* +******************************************************************************/ +#define Xil_AssertNonvoidAlways() \ +{ \ + Xil_Assert(__FILE__, __LINE__); \ + Xil_AssertStatus = XIL_ASSERT_OCCURRED; \ + return 0; \ +} + + +#else + +#define Xil_AssertVoid(Expression) +#define Xil_AssertVoidAlways() +#define Xil_AssertNonvoid(Expression) +#define Xil_AssertNonvoidAlways() + +#endif + +/************************** Function Prototypes ******************************/ + +void Xil_AssertSetCallback(Xil_AssertCallback Routine); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** +* @} End of "addtogroup common_assert_apis". +*/ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_cache.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_cache.c new file mode 100644 index 0000000..536800f --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_cache.c @@ -0,0 +1,1637 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_cache.c +* +* Contains required functions for the ARM cache functionality. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver    Who Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a  ecm 01/29/10 First release
+* 1.00a  ecm 06/24/10 Moved the L1 and L2 specific function prototypes
+*		      		  to xil_cache_mach.h to give access to sophisticated users
+* 3.02a  sdm 04/07/11 Updated Flush/InvalidateRange APIs to flush/invalidate
+*		      		  L1 and L2 caches in a single loop and used dsb, L2 sync
+*		      		  at the end of the loop.
+* 3.04a  sdm 01/02/12 Remove redundant dsb/dmb instructions in cache maintenance
+*		      		  APIs.
+* 3.07a  asa 07/16/12 Corrected the L1 and L2 cache invalidation order.
+* 3.07a  sgd 09/18/12 Corrected the L2 cache enable and disable sequence.
+* 3.10a  srt 04/18/13 Implemented ARM Erratas. Please refer to file
+*		      		  'xil_errata.h' for errata description
+* 3.10a  asa 05/13/13 Modified cache disable APIs. The L2 cache disable
+*			  		  operation was being done with L1 Data cache disabled. This is
+*			  		  fixed so that L2 cache disable operation happens independent of
+*			  		  L1 cache disable operation. This fixes CR #706464.
+*			  		  Changes are done to do a L2 cache sync (poll reg7_?cache_?sync).
+*			  		  This is done to fix the CR #700542.
+* 3.11a  asa 09/23/13 Modified the Xil_DCacheFlushRange and
+*			 		  Xil_DCacheInvalidateRange to fix potential issues. Fixed other
+*			 		  relevant cache APIs to disable and enable back the interrupts.
+*			 		  This fixes CR #663885.
+* 3.11a  asa 09/28/13 Made changes for L2 cache sync operation. It is found
+*			 		  out that for L2 cache flush/clean/invalidation by cache lines
+*			 		  does not need a cache sync as these are atomic nature. Similarly
+*			 		  figured out that for complete L2 cache flush/invalidation by way
+*			 		  we need to wait for some more time in a loop till the status
+*			 		  shows that the cache operation is completed.
+* 4.00	 pkp 24/01/14 Modified Xil_DCacheInvalidateRange to fix the bug. Few
+*			 		  cache lines were missed to invalidate when unaligned address
+*			 		  invalidation was accommodated. That fixes CR #766768.
+*			 		  Also in Xil_L1DCacheInvalidate, while invalidating all L1D cache
+*			 		  stack memory which contains return address was invalidated. So
+*			 		  stack memory was flushed first and then L1D cache is invalidated.
+*			 		  This is done to fix CR #763829
+* 4.01   asa 05/09/14 Made changes in cortexa9/xil_cache.c to fix CR# 798230.
+* 4.02	 pkp 06/27/14 Added notes to Xil_L1DCacheInvalidateRange function for
+*					  explanation of CR#785243
+* 5.00   kvn 12/15/14 Xil_L2CacheInvalidate was modified to fix CR# 838835. L2 Cache
+*					  has stack memory which has return address. Before invalidating
+*					  cache, stack memory was flushed first and L2 Cache is invalidated.
+* 5.01	 pkp 05/12/15 Xil_DCacheInvalidateRange and Xil_DCacheFlushRange is modified
+*					  to remove unnecessary dsb in the APIs. Instead of using dsb
+*					  for L2 Cache, L2CacheSync has been used for each L2 cache line
+*					  and single dsb has been used for L1 cache. Also L2CacheSync is
+*					  added into Xil_L2CacheInvalidateRange API. Xil_L1DCacheInvalidate
+*					  and Xil_L2CacheInvalidate APIs are modified to flush the complete
+*					  stack instead of just System Stack
+* 5.03	 pkp 10/07/15 L2 Cache functionalities are avoided for the OpenAMP slave
+*					  application(when USE_AMP flag is defined for BSP) as master CPU
+*					  would be utilizing L2 cache for its operation
+* 6.6    mus 12/07/17 Errata 753970 is not applicable for the PL130 cache controller
+*                     version r0p2, which is present in zynq. So,removed the handling
+*                     related to same.It fixes CR#989132.
+* 6.6    asa 16/01/18 Changes made in Xil_L1DCacheInvalidate and Xil_L2CacheInvalidate
+*					  routines to ensure the stack data flushed only when the respective
+*					  caches are enabled. This fixes CR-992023.
+*
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xil_cache.h" +#include "xil_cache_l.h" +#include "xil_io.h" +#include "xpseudo_asm.h" +#include "xparameters.h" +#include "xreg_cortexa9.h" +#include "xl2cc.h" +#include "xil_errata.h" +#include "xil_exception.h" + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +#define IRQ_FIQ_MASK 0xC0U /* Mask IRQ and FIQ interrupts in cpsr */ + +#ifdef __GNUC__ + extern s32 _stack_end; + extern s32 __undef_stack; +#endif + +#ifndef USE_AMP +/**************************************************************************** +* +* Access L2 Debug Control Register. +* +* @param Value, value to be written to Debug Control Register. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +#ifdef __GNUC__ +static inline void Xil_L2WriteDebugCtrl(u32 Value) +#else +static void Xil_L2WriteDebugCtrl(u32 Value) +#endif +{ +#if defined(CONFIG_PL310_ERRATA_588369) || defined(CONFIG_PL310_ERRATA_727915) + Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_DEBUG_CTRL_OFFSET, Value); +#else + (void)(Value); +#endif +} + +/**************************************************************************** +* +* Perform L2 Cache Sync Operation. +* +* @param None. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +#ifdef __GNUC__ +static inline void Xil_L2CacheSync(void) +#else +static void Xil_L2CacheSync(void) +#endif +{ + Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_CACHE_SYNC_OFFSET, 0x0U); +} +#endif +/****************************************************************************/ +/** +* @brief Enable the Data cache. +* +* @param None. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void Xil_DCacheEnable(void) +{ + Xil_L1DCacheEnable(); +#ifndef USE_AMP + Xil_L2CacheEnable(); +#endif +} + +/****************************************************************************/ +/** +* @brief Disable the Data cache. +* +* @param None. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void Xil_DCacheDisable(void) +{ +#ifndef USE_AMP + Xil_L2CacheDisable(); +#endif + Xil_L1DCacheDisable(); +} + +/****************************************************************************/ +/** +* @brief Invalidate the entire Data cache. +* +* @param None. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void Xil_DCacheInvalidate(void) +{ + u32 currmask; + + currmask = mfcpsr(); + mtcpsr(currmask | IRQ_FIQ_MASK); +#ifndef USE_AMP + Xil_L2CacheInvalidate(); +#endif + Xil_L1DCacheInvalidate(); + + mtcpsr(currmask); +} + +/*****************************************************************************/ +/** +* @brief Invalidate a Data cache line. If the byte specified by the address +* (adr) is cached by the Data cache, the cacheline containing that +* byte is invalidated. If the cacheline is modified (dirty), the +* modified contents are lost and are NOT written to the system memory +* before the line is invalidated. +* +* @param adr: 32bit address of the data to be flushed. +* +* @return None. +* +* @note The bottom 4 bits are set to 0, forced by architecture. +* +****************************************************************************/ +void Xil_DCacheInvalidateLine(u32 adr) +{ + u32 currmask; + + currmask = mfcpsr(); + mtcpsr(currmask | IRQ_FIQ_MASK); +#ifndef USE_AMP + Xil_L2CacheInvalidateLine(adr); +#endif + Xil_L1DCacheInvalidateLine(adr); + + mtcpsr(currmask); +} + + +/*****************************************************************************/ +/** +* @brief Invalidate the Data cache for the given address range. +* If the bytes specified by the address range are cached by the Data +* cache, the cachelines containing those bytes are invalidated. If +* the cachelines are modified (dirty), the modified contents are lost +* and NOT written to the system memory before the lines are +* invalidated. +* +* In this function, if start address or end address is not aligned to +* cache-line, particular cache-line containing unaligned start or end +* address is flush first and then invalidated the others as +* invalidating the same unaligned cache line may result into loss of +* data. This issue raises few possibilities. +* +* If the address to be invalidated is not cache-line aligned, the +* following choices are available: +* 1. Invalidate the cache line when required and do not bother much +* for the side effects. Though it sounds good, it can result in +* hard-to-debug issues. The problem is, if some other variable are +* allocated in the same cache line and had been recently updated +* (in cache), the invalidation would result in loss of data. +* 2. Flush the cache line first. This will ensure that if any other +* variable present in the same cache line and updated recently are +* flushed out to memory. Then it can safely be invalidated. Again it +* sounds good, but this can result in issues. For example, when the +* invalidation happens in a typical ISR (after a DMA transfer has +* updated the memory), then flushing the cache line means, loosing +* data that were updated recently before the ISR got invoked. +* +* Linux prefers the second one. To have uniform implementation +* (across standalone and Linux), the second option is implemented. +* This being the case, follwoing needs to be taken care of: +* 1. Whenever possible, the addresses must be cache line aligned. +* Please nore that, not just start address, even the end address must +* be cache line aligned. If that is taken care of, this will always +* work. +* 2. Avoid situations where invalidation has to be done after the +* data is updated by peripheral/DMA directly into the memory. It is +* not tough to achieve (may be a bit risky). The common use case to +* do invalidation is when a DMA happens. Generally for such use +* cases, buffers can be allocated first and then start the DMA. The +* practice that needs to be followed here is, immediately after +* buffer allocation and before starting the DMA, do the invalidation. +* With this approach, invalidation need not to be done after the DMA +* transfer is over. +* +* This is going to always work if done carefully. +* However, the concern is, there is no guarantee that invalidate has +* not needed to be done after DMA is complete. For example, because +* of some reasons if the first cache line or last cache line +* (assuming the buffer in question comprises of multiple cache lines) +* are brought into cache (between the time it is invalidated and DMA +* completes) because of some speculative prefetching or reading data +* for a variable present in the same cache line, then we will have to +* invalidate the cache after DMA is complete. +* +* +* @param adr: 32bit start address of the range to be invalidated. +* @param len: Length of the range to be invalidated in bytes. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void Xil_DCacheInvalidateRange(INTPTR adr, u32 len) +{ + const u32 cacheline = 32U; + u32 end; + u32 tempadr = adr; + u32 tempend; + u32 currmask; + volatile u32 *L2CCOffset = (volatile u32 *)(XPS_L2CC_BASEADDR + + XPS_L2CC_CACHE_INVLD_PA_OFFSET); + + currmask = mfcpsr(); + mtcpsr(currmask | IRQ_FIQ_MASK); + + if (len != 0U) { + end = tempadr + len; + tempend = end; + /* Select L1 Data cache in CSSR */ + mtcp(XREG_CP15_CACHE_SIZE_SEL, 0U); + + if ((tempadr & (cacheline-1U)) != 0U) { + tempadr &= (~(cacheline - 1U)); + + Xil_L1DCacheFlushLine(tempadr); +#ifndef USE_AMP + /* Disable Write-back and line fills */ + Xil_L2WriteDebugCtrl(0x3U); + Xil_L2CacheFlushLine(tempadr); + /* Enable Write-back and line fills */ + Xil_L2WriteDebugCtrl(0x0U); + Xil_L2CacheSync(); +#endif + tempadr += cacheline; + } + if ((tempend & (cacheline-1U)) != 0U) { + tempend &= (~(cacheline - 1U)); + + Xil_L1DCacheFlushLine(tempend); +#ifndef USE_AMP + /* Disable Write-back and line fills */ + Xil_L2WriteDebugCtrl(0x3U); + Xil_L2CacheFlushLine(tempend); + /* Enable Write-back and line fills */ + Xil_L2WriteDebugCtrl(0x0U); + Xil_L2CacheSync(); +#endif + } + + while (tempadr < tempend) { +#ifndef USE_AMP + /* Invalidate L2 cache line */ + *L2CCOffset = tempadr; + Xil_L2CacheSync(); +#endif + + /* Invalidate L1 Data cache line */ +#if defined (__GNUC__) || defined (__ICCARM__) + asm_cp15_inval_dc_line_mva_poc(tempadr); +#else + { volatile register u32 Reg + __asm(XREG_CP15_INVAL_DC_LINE_MVA_POC); + Reg = tempadr; } +#endif + tempadr += cacheline; + } + } + + dsb(); + mtcpsr(currmask); +} + +/****************************************************************************/ +/** +* @brief Flush the entire Data cache. +* +* @param None. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void Xil_DCacheFlush(void) +{ + u32 currmask; + + currmask = mfcpsr(); + mtcpsr(currmask | IRQ_FIQ_MASK); + Xil_L1DCacheFlush(); +#ifndef USE_AMP + Xil_L2CacheFlush(); +#endif + mtcpsr(currmask); +} + + +/****************************************************************************/ +/** +* @brief Flush a Data cache line. If the byte specified by the address (adr) +* is cached by the Data cache, the cacheline containing that byte is +* invalidated. If the cacheline is modified (dirty), the entire +* contents of the cacheline are written to system memory before the +* line is invalidated. +* +* @param adr: 32bit address of the data to be flushed. +* +* @return None. +* +* @note The bottom 4 bits are set to 0, forced by architecture. +* +****************************************************************************/ +void Xil_DCacheFlushLine(u32 adr) +{ + u32 currmask; + + currmask = mfcpsr(); + mtcpsr(currmask | IRQ_FIQ_MASK); + Xil_L1DCacheFlushLine(adr); +#ifndef USE_AMP + /* Disable Write-back and line fills */ + Xil_L2WriteDebugCtrl(0x3U); + + Xil_L2CacheFlushLine(adr); + + /* Enable Write-back and line fills */ + Xil_L2WriteDebugCtrl(0x0U); + Xil_L2CacheSync(); +#endif + mtcpsr(currmask); +} + +/****************************************************************************/ +/** +* @brief Flush the Data cache for the given address range. +* If the bytes specified by the address range are cached by the +* data cache, the cachelines containing those bytes are invalidated. +* If the cachelines are modified (dirty), they are written to the +* system memory before the lines are invalidated. +* +* @param adr: 32bit start address of the range to be flushed. +* @param len: Length of the range to be flushed in bytes. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void Xil_DCacheFlushRange(INTPTR adr, u32 len) +{ + u32 LocalAddr = adr; + const u32 cacheline = 32U; + u32 end; + u32 currmask; + volatile u32 *L2CCOffset = (volatile u32 *)(XPS_L2CC_BASEADDR + + XPS_L2CC_CACHE_INV_CLN_PA_OFFSET); + + currmask = mfcpsr(); + mtcpsr(currmask | IRQ_FIQ_MASK); + + if (len != 0U) { + /* Back the starting address up to the start of a cache line + * perform cache operations until adr+len + */ + end = LocalAddr + len; + LocalAddr &= ~(cacheline - 1U); + + while (LocalAddr < end) { + + /* Flush L1 Data cache line */ +#if defined (__GNUC__) || defined (__ICCARM__) + asm_cp15_clean_inval_dc_line_mva_poc(LocalAddr); +#else + { volatile register u32 Reg + __asm(XREG_CP15_CLEAN_INVAL_DC_LINE_MVA_POC); + Reg = LocalAddr; } +#endif +#ifndef USE_AMP + /* Flush L2 cache line */ + *L2CCOffset = LocalAddr; + Xil_L2CacheSync(); +#endif + LocalAddr += cacheline; + } + } + dsb(); + mtcpsr(currmask); +} +/****************************************************************************/ +/** +* @brief Store a Data cache line. If the byte specified by the address (adr) +* is cached by the Data cache and the cacheline is modified (dirty), +* the entire contents of the cacheline are written to system memory. +* After the store completes, the cacheline is marked as unmodified +* (not dirty). +* +* @param adr: 32bit address of the data to be stored. +* +* @return None. +* +* @note The bottom 4 bits are set to 0, forced by architecture. +* +****************************************************************************/ +void Xil_DCacheStoreLine(u32 adr) +{ + u32 currmask; + + currmask = mfcpsr(); + mtcpsr(currmask | IRQ_FIQ_MASK); + + Xil_L1DCacheStoreLine(adr); +#ifndef USE_AMP + Xil_L2CacheStoreLine(adr); +#endif + mtcpsr(currmask); +} + +/***************************************************************************/ +/** +* @brief Enable the instruction cache. +* +* @param None. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void Xil_ICacheEnable(void) +{ + Xil_L1ICacheEnable(); +#ifndef USE_AMP + Xil_L2CacheEnable(); +#endif +} + +/***************************************************************************/ +/** +* @brief Disable the instruction cache. +* +* @param None. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void Xil_ICacheDisable(void) +{ +#ifndef USE_AMP + Xil_L2CacheDisable(); +#endif + Xil_L1ICacheDisable(); +} + + +/****************************************************************************/ +/** +* @brief Invalidate the entire instruction cache. +* +* @param None. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void Xil_ICacheInvalidate(void) +{ + u32 currmask; + + currmask = mfcpsr(); + mtcpsr(currmask | IRQ_FIQ_MASK); +#ifndef USE_AMP + Xil_L2CacheInvalidate(); +#endif + Xil_L1ICacheInvalidate(); + + mtcpsr(currmask); +} + +/****************************************************************************/ +/** +* @brief Invalidate an instruction cache line. If the instruction specified +* by the address is cached by the instruction cache, the cacheline +* containing that instruction is invalidated. +* +* @param adr: 32bit address of the instruction to be invalidated. +* +* @return None. +* +* @note The bottom 4 bits are set to 0, forced by architecture. +* +****************************************************************************/ +void Xil_ICacheInvalidateLine(u32 adr) +{ + u32 currmask; + + currmask = mfcpsr(); + mtcpsr(currmask | IRQ_FIQ_MASK); +#ifndef USE_AMP + Xil_L2CacheInvalidateLine(adr); +#endif + Xil_L1ICacheInvalidateLine(adr); + mtcpsr(currmask); +} + +/****************************************************************************/ +/** +* @brief Invalidate the instruction cache for the given address range. +* If the instructions specified by the address range are cached by +* the instrunction cache, the cachelines containing those +* instructions are invalidated. +* +* @param adr: 32bit start address of the range to be invalidated. +* @param len: Length of the range to be invalidated in bytes. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void Xil_ICacheInvalidateRange(INTPTR adr, u32 len) +{ + u32 LocalAddr = adr; + const u32 cacheline = 32U; + u32 end; + volatile u32 *L2CCOffset = (volatile u32 *)(XPS_L2CC_BASEADDR + + XPS_L2CC_CACHE_INVLD_PA_OFFSET); + + u32 currmask; + + currmask = mfcpsr(); + mtcpsr(currmask | IRQ_FIQ_MASK); + if (len != 0U) { + /* Back the starting address up to the start of a cache line + * perform cache operations until adr+len + */ + end = LocalAddr + len; + LocalAddr = LocalAddr & ~(cacheline - 1U); + + /* Select cache L0 I-cache in CSSR */ + mtcp(XREG_CP15_CACHE_SIZE_SEL, 1U); + + while (LocalAddr < end) { +#ifndef USE_AMP + /* Invalidate L2 cache line */ + *L2CCOffset = LocalAddr; + dsb(); +#endif + + /* Invalidate L1 I-cache line */ +#if defined (__GNUC__) || defined (__ICCARM__) + asm_cp15_inval_ic_line_mva_pou(LocalAddr); +#else + { volatile register u32 Reg + __asm(XREG_CP15_INVAL_IC_LINE_MVA_POU); + Reg = LocalAddr; } +#endif + + LocalAddr += cacheline; + } + } + + /* Wait for L1 and L2 invalidate to complete */ + dsb(); + mtcpsr(currmask); +} + +/****************************************************************************/ +/** +* @brief Enable the level 1 Data cache. +* +* @param None. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void Xil_L1DCacheEnable(void) +{ + register u32 CtrlReg; + + /* enable caches only if they are disabled */ +#ifdef __GNUC__ + CtrlReg = mfcp(XREG_CP15_SYS_CONTROL); +#elif defined (__ICCARM__) + mfcp(XREG_CP15_SYS_CONTROL, CtrlReg); +#else + { volatile register u32 Reg __asm(XREG_CP15_SYS_CONTROL); + CtrlReg = Reg; } +#endif + if ((CtrlReg & (XREG_CP15_CONTROL_C_BIT)) != 0U) { + return; + } + + /* clean and invalidate the Data cache */ + Xil_L1DCacheInvalidate(); + + /* enable the Data cache */ + CtrlReg |= (XREG_CP15_CONTROL_C_BIT); + + mtcp(XREG_CP15_SYS_CONTROL, CtrlReg); +} + +/***************************************************************************/ +/** +* @brief Disable the level 1 Data cache. +* +* @param None. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void Xil_L1DCacheDisable(void) +{ + register u32 CtrlReg; + + /* clean and invalidate the Data cache */ + Xil_L1DCacheFlush(); + +#ifdef __GNUC__ + /* disable the Data cache */ + CtrlReg = mfcp(XREG_CP15_SYS_CONTROL); +#elif defined (__ICCARM__) + mfcp(XREG_CP15_SYS_CONTROL, CtrlReg); +#else + { volatile register u32 Reg __asm(XREG_CP15_SYS_CONTROL); + CtrlReg = Reg; } +#endif + + CtrlReg &= ~(XREG_CP15_CONTROL_C_BIT); + + mtcp(XREG_CP15_SYS_CONTROL, CtrlReg); +} + +/****************************************************************************/ +/** +* @brief Invalidate the level 1 Data cache. +* +* @param None. +* +* @return None. +* +* @note In Cortex A9, there is no cp instruction for invalidating +* the whole D-cache. This function invalidates each line by +* set/way. +* +****************************************************************************/ +void Xil_L1DCacheInvalidate(void) +{ + register u32 CsidReg, C7Reg; + u32 CacheSize, LineSize, NumWays; + u32 Way, WayIndex, Set, SetIndex, NumSet; + u32 currmask; + +#ifdef __GNUC__ + u32 stack_start,stack_end,stack_size; + register u32 CtrlReg; +#endif + + currmask = mfcpsr(); + mtcpsr(currmask | IRQ_FIQ_MASK); + +#ifdef __GNUC__ + stack_end = (u32)&_stack_end; + stack_start = (u32)&__undef_stack; + stack_size=stack_start-stack_end; + + /* Check for the cache status. If cache is enabled, then only + * flush stack memory to save return address. If cache is disabled, + * dont flush anything as it might result in flushing stale date into + * memory which is undesirable. + * */ + CtrlReg = mfcp(XREG_CP15_SYS_CONTROL); + if ((CtrlReg & (XREG_CP15_CONTROL_C_BIT)) != 0U) { + Xil_DCacheFlushRange(stack_end, stack_size); + } +#endif + + /* Select cache level 0 and D cache in CSSR */ + mtcp(XREG_CP15_CACHE_SIZE_SEL, 0U); + +#ifdef __GNUC__ + CsidReg = mfcp(XREG_CP15_CACHE_SIZE_ID); +#elif defined (__ICCARM__) + mfcp(XREG_CP15_CACHE_SIZE_ID, CsidReg); +#else + { volatile register u32 Reg __asm(XREG_CP15_CACHE_SIZE_ID); + CsidReg = Reg; } +#endif + /* Determine Cache Size */ + CacheSize = (CsidReg >> 13U) & 0x1FFU; + CacheSize +=1U; + CacheSize *=128U; /* to get number of bytes */ + + /* Number of Ways */ + NumWays = (CsidReg & 0x3ffU) >> 3U; + NumWays += 1U; + + /* Get the cacheline size, way size, index size from csidr */ + LineSize = (CsidReg & 0x07U) + 4U; + + NumSet = CacheSize/NumWays; + NumSet /= (0x00000001U << LineSize); + + Way = 0U; + Set = 0U; + + /* Invalidate all the cachelines */ + for (WayIndex =0U; WayIndex < NumWays; WayIndex++) { + for (SetIndex =0U; SetIndex < NumSet; SetIndex++) { + C7Reg = Way | Set; + + /* Invalidate by Set/Way */ +#if defined (__GNUC__) || defined (__ICCARM__) + asm_cp15_inval_dc_line_sw(C7Reg); +#else + /*mtcp(XREG_CP15_INVAL_DC_LINE_SW, C7Reg), */ + { volatile register u32 Reg + __asm(XREG_CP15_INVAL_DC_LINE_SW); + Reg = C7Reg; } +#endif + Set += (0x00000001U << LineSize); + } + Set=0U; + Way += 0x40000000U; + } + + /* Wait for L1 invalidate to complete */ + dsb(); + mtcpsr(currmask); +} + +/****************************************************************************/ +/** +* @brief Invalidate a level 1 Data cache line. If the byte specified by the +* address (Addr) is cached by the Data cache, the cacheline +* containing that byte is invalidated. If the cacheline is modified +* (dirty), the modified contents are lost and are NOT written to +* system memory before the line is invalidated. +* +* @param adr: 32bit address of the data to be invalidated. +* +* @return None. +* +* @note The bottom 5 bits are set to 0, forced by architecture. +* +****************************************************************************/ +void Xil_L1DCacheInvalidateLine(u32 adr) +{ + mtcp(XREG_CP15_CACHE_SIZE_SEL, 0U); + mtcp(XREG_CP15_INVAL_DC_LINE_MVA_POC, (adr & (~0x1FU))); + + /* Wait for L1 invalidate to complete */ + dsb(); +} + +/****************************************************************************/ +/** +* @brief Invalidate the level 1 Data cache for the given address range. +* If the bytes specified by the address range are cached by the Data +* cache, the cachelines containing those bytes are invalidated. If the +* cachelines are modified (dirty), the modified contents are lost and +* NOT written to the system memory before the lines are invalidated. +* +* @param adr: 32bit start address of the range to be invalidated. +* @param len: Length of the range to be invalidated in bytes. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void Xil_L1DCacheInvalidateRange(u32 adr, u32 len) +{ + u32 LocalAddr = adr; + const u32 cacheline = 32U; + u32 end; + u32 currmask; + + currmask = mfcpsr(); + mtcpsr(currmask | IRQ_FIQ_MASK); + + if (len != 0U) { + /* Back the starting address up to the start of a cache line + * perform cache operations until adr+len + */ + end = LocalAddr + len; + LocalAddr = LocalAddr & ~(cacheline - 1U); + + /* Select cache L0 D-cache in CSSR */ + mtcp(XREG_CP15_CACHE_SIZE_SEL, 0); + + while (LocalAddr < end) { + +#if defined (__GNUC__) || defined (__ICCARM__) + asm_cp15_inval_dc_line_mva_poc(LocalAddr); +#else + { volatile register u32 Reg + __asm(XREG_CP15_INVAL_DC_LINE_MVA_POC); + Reg = LocalAddr; } +#endif + LocalAddr += cacheline; + } + } + + /* Wait for L1 invalidate to complete */ + dsb(); + mtcpsr(currmask); +} + +/****************************************************************************/ +/** +* @brief Flush the level 1 Data cache. +* +* @param None. +* +* @return None. +* +* @note In Cortex A9, there is no cp instruction for flushing +* the whole D-cache. Need to flush each line. +* +****************************************************************************/ +void Xil_L1DCacheFlush(void) +{ + register u32 CsidReg, C7Reg; + u32 CacheSize, LineSize, NumWays; + u32 Way; + u32 WayIndex, Set, SetIndex, NumSet; + u32 currmask; + + currmask = mfcpsr(); + mtcpsr(currmask | IRQ_FIQ_MASK); + + /* Select cache level 0 and D cache in CSSR */ + mtcp(XREG_CP15_CACHE_SIZE_SEL, 0); + +#ifdef __GNUC__ + CsidReg = mfcp(XREG_CP15_CACHE_SIZE_ID); +#elif defined (__ICCARM__) + mfcp(XREG_CP15_CACHE_SIZE_ID, CsidReg); +#else + { volatile register u32 Reg __asm(XREG_CP15_CACHE_SIZE_ID); + CsidReg = Reg; } +#endif + + /* Determine Cache Size */ + + CacheSize = (CsidReg >> 13U) & 0x1FFU; + CacheSize +=1U; + CacheSize *=128U; /* to get number of bytes */ + + /* Number of Ways */ + NumWays = (CsidReg & 0x3ffU) >> 3U; + NumWays += 1U; + + /* Get the cacheline size, way size, index size from csidr */ + LineSize = (CsidReg & 0x07U) + 4U; + + NumSet = CacheSize/NumWays; + NumSet /= (0x00000001U << LineSize); + + Way = 0U; + Set = 0U; + + /* Invalidate all the cachelines */ + for (WayIndex =0U; WayIndex < NumWays; WayIndex++) { + for (SetIndex =0U; SetIndex < NumSet; SetIndex++) { + C7Reg = Way | Set; + /* Flush by Set/Way */ + +#if defined (__GNUC__) || defined (__ICCARM__) + asm_cp15_clean_inval_dc_line_sw(C7Reg); +#else + { volatile register u32 Reg + __asm(XREG_CP15_CLEAN_INVAL_DC_LINE_SW); + Reg = C7Reg; } +#endif + Set += (0x00000001U << LineSize); + } + Set = 0U; + Way += 0x40000000U; + } + + /* Wait for L1 flush to complete */ + dsb(); + mtcpsr(currmask); +} + +/****************************************************************************/ +/** +* @brief Flush a level 1 Data cache line. If the byte specified by the +* address (adr) is cached by the Data cache, the cacheline containing +* that byte is invalidated. If the cacheline is modified (dirty), the +* entire contents of the cacheline are written to system memory +* before the line is invalidated. +* +* @param adr: 32bit address of the data to be flushed. +* +* @return None. +* +* @note The bottom 5 bits are set to 0, forced by architecture. +* +****************************************************************************/ +void Xil_L1DCacheFlushLine(u32 adr) +{ + mtcp(XREG_CP15_CACHE_SIZE_SEL, 0U); + mtcp(XREG_CP15_CLEAN_INVAL_DC_LINE_MVA_POC, (adr & (~0x1FU))); + + /* Wait for L1 flush to complete */ + dsb(); +} + +/****************************************************************************/ +/** +* @brief Flush the level 1 Data cache for the given address range. +* If the bytes specified by the address range are cached by the Data +* cache, the cacheline containing those bytes are invalidated. If the +* cachelines are modified (dirty), they are written to system memory +* before the lines are invalidated. +* +* @param adr: 32bit start address of the range to be flushed. +* @param len: Length of the range to be flushed in bytes. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void Xil_L1DCacheFlushRange(u32 adr, u32 len) +{ + u32 LocalAddr = adr; + const u32 cacheline = 32U; + u32 end; + u32 currmask; + + currmask = mfcpsr(); + mtcpsr(currmask | IRQ_FIQ_MASK); + + if (len != 0U) { + /* Back the starting address up to the start of a cache line + * perform cache operations until adr+len + */ + end = LocalAddr + len; + LocalAddr = LocalAddr & ~(cacheline - 1U); + + /* Select cache L0 D-cache in CSSR */ + mtcp(XREG_CP15_CACHE_SIZE_SEL, 0U); + + while (LocalAddr < end) { + +#if defined (__GNUC__) || defined (__ICCARM__) + asm_cp15_clean_inval_dc_line_mva_poc(LocalAddr); +#else + { volatile register u32 Reg + __asm(XREG_CP15_CLEAN_INVAL_DC_LINE_MVA_POC); + Reg = LocalAddr; } +#endif + LocalAddr += cacheline; + } + } + + /* Wait for L1 flush to complete */ + dsb(); + mtcpsr(currmask); +} + +/****************************************************************************/ +/** +* @brief Store a level 1 Data cache line. If the byte specified by the +* address (adr) is cached by the Data cache and the cacheline is +* modified (dirty), the entire contents of the cacheline are written +* to system memory. After the store completes, the cacheline is +* marked as unmodified (not dirty). +* +* @param Address to be stored. +* +* @return None. +* +* @note The bottom 5 bits are set to 0, forced by architecture. +* +****************************************************************************/ +void Xil_L1DCacheStoreLine(u32 adr) +{ + mtcp(XREG_CP15_CACHE_SIZE_SEL, 0U); + mtcp(XREG_CP15_CLEAN_DC_LINE_MVA_POC, (adr & (~0x1FU))); + + /* Wait for L1 store to complete */ + dsb(); +} + + +/****************************************************************************/ +/** +* @brief Enable the level 1 instruction cache. +* +* @param None. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void Xil_L1ICacheEnable(void) +{ + register u32 CtrlReg; + + /* enable caches only if they are disabled */ +#ifdef __GNUC__ + CtrlReg = mfcp(XREG_CP15_SYS_CONTROL); +#elif defined (__ICCARM__) + mfcp(XREG_CP15_SYS_CONTROL, CtrlReg); +#else + { volatile register u32 Reg __asm(XREG_CP15_SYS_CONTROL); + CtrlReg = Reg; } +#endif + if ((CtrlReg & (XREG_CP15_CONTROL_I_BIT)) != 0U) { + return; + } + + /* invalidate the instruction cache */ + mtcp(XREG_CP15_INVAL_IC_POU, 0U); + + /* enable the instruction cache */ + CtrlReg |= (XREG_CP15_CONTROL_I_BIT); + + mtcp(XREG_CP15_SYS_CONTROL, CtrlReg); +} + +/****************************************************************************/ +/** +* @brief Disable level 1 the instruction cache. +* +* @param None. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void Xil_L1ICacheDisable(void) +{ + register u32 CtrlReg; + + dsb(); + + /* invalidate the instruction cache */ + mtcp(XREG_CP15_INVAL_IC_POU, 0U); + + /* disable the instruction cache */ +#ifdef __GNUC__ + CtrlReg = mfcp(XREG_CP15_SYS_CONTROL); +#elif defined (__ICCARM__) + mfcp(XREG_CP15_SYS_CONTROL, CtrlReg); +#else + { volatile register u32 Reg __asm(XREG_CP15_SYS_CONTROL); + CtrlReg = Reg; } +#endif + CtrlReg &= ~(XREG_CP15_CONTROL_I_BIT); + + mtcp(XREG_CP15_SYS_CONTROL, CtrlReg); +} + +/****************************************************************************/ +/** +* @brief Invalidate the entire level 1 instruction cache. +* +* @param None. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void Xil_L1ICacheInvalidate(void) +{ + mtcp(XREG_CP15_CACHE_SIZE_SEL, 1U); + /* invalidate the instruction cache */ + mtcp(XREG_CP15_INVAL_IC_POU, 0U); + + /* Wait for L1 invalidate to complete */ + dsb(); +} + +/****************************************************************************/ +/** +* @brief Invalidate a level 1 instruction cache line. If the instruction +* specified by the address is cached by the instruction cache, the +* cacheline containing that instruction is invalidated. +* +* @param adr: 32bit address of the instruction to be invalidated. +* +* @return None. +* +* @note The bottom 5 bits are set to 0, forced by architecture. +* +****************************************************************************/ +void Xil_L1ICacheInvalidateLine(u32 adr) +{ + mtcp(XREG_CP15_CACHE_SIZE_SEL, 1U); + mtcp(XREG_CP15_INVAL_IC_LINE_MVA_POU, (adr & (~0x1FU))); + + /* Wait for L1 invalidate to complete */ + dsb(); +} + +/****************************************************************************/ +/** +* @brief Invalidate the level 1 instruction cache for the given address +* range. If the instrucions specified by the address range are cached +* by the instruction cache, the cacheline containing those bytes are +* invalidated. +* +* @param adr: 32bit start address of the range to be invalidated. +* @param len: Length of the range to be invalidated in bytes. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void Xil_L1ICacheInvalidateRange(u32 adr, u32 len) +{ + u32 LocalAddr = adr; + const u32 cacheline = 32U; + u32 end; + u32 currmask; + + currmask = mfcpsr(); + mtcpsr(currmask | IRQ_FIQ_MASK); + + if (len != 0U) { + /* Back the starting address up to the start of a cache line + * perform cache operations until adr+len + */ + end = LocalAddr + len; + LocalAddr = LocalAddr & ~(cacheline - 1U); + + /* Select cache L0 I-cache in CSSR */ + mtcp(XREG_CP15_CACHE_SIZE_SEL, 1U); + + while (LocalAddr < end) { + +#if defined (__GNUC__) || defined (__ICCARM__) + asm_cp15_inval_ic_line_mva_pou(LocalAddr); +#else + { volatile register u32 Reg + __asm(XREG_CP15_INVAL_IC_LINE_MVA_POU); + Reg = LocalAddr; } +#endif + LocalAddr += cacheline; + } + } + + /* Wait for L1 invalidate to complete */ + dsb(); + mtcpsr(currmask); +} + +#ifndef USE_AMP +/****************************************************************************/ +/** +* @brief Enable the L2 cache. +* +* @param None. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void Xil_L2CacheEnable(void) +{ + register u32 L2CCReg; + + L2CCReg = Xil_In32(XPS_L2CC_BASEADDR + XPS_L2CC_CNTRL_OFFSET); + + /* only enable if L2CC is currently disabled */ + if ((L2CCReg & 0x01U) == 0U) { + /* set up the way size and latencies */ + L2CCReg = Xil_In32(XPS_L2CC_BASEADDR + + XPS_L2CC_AUX_CNTRL_OFFSET); + L2CCReg &= XPS_L2CC_AUX_REG_ZERO_MASK; + L2CCReg |= XPS_L2CC_AUX_REG_DEFAULT_MASK; + Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_AUX_CNTRL_OFFSET, + L2CCReg); + Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_TAG_RAM_CNTRL_OFFSET, + XPS_L2CC_TAG_RAM_DEFAULT_MASK); + Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_DATA_RAM_CNTRL_OFFSET, + XPS_L2CC_DATA_RAM_DEFAULT_MASK); + + /* Clear the pending interrupts */ + L2CCReg = Xil_In32(XPS_L2CC_BASEADDR + + XPS_L2CC_ISR_OFFSET); + Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_IAR_OFFSET, L2CCReg); + + Xil_L2CacheInvalidate(); + /* Enable the L2CC */ + L2CCReg = Xil_In32(XPS_L2CC_BASEADDR + + XPS_L2CC_CNTRL_OFFSET); + Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_CNTRL_OFFSET, + (L2CCReg | (0x01U))); + + Xil_L2CacheSync(); + /* synchronize the processor */ + dsb(); + + } +} + +/****************************************************************************/ +/** +* @brief Disable the L2 cache. +* +* @param None. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void Xil_L2CacheDisable(void) +{ + register u32 L2CCReg; + + L2CCReg = Xil_In32(XPS_L2CC_BASEADDR + XPS_L2CC_CNTRL_OFFSET); + + if((L2CCReg & 0x1U) != 0U) { + + /* Clean and Invalidate L2 Cache */ + Xil_L2CacheFlush(); + + /* Disable the L2CC */ + L2CCReg = Xil_In32(XPS_L2CC_BASEADDR + XPS_L2CC_CNTRL_OFFSET); + Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_CNTRL_OFFSET, + (L2CCReg & (~0x01U))); + /* Wait for the cache operations to complete */ + + dsb(); + } +} + +/*****************************************************************************/ +/** +* @brief Invalidate the entire level 2 cache. +* +* @param None. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void Xil_L2CacheInvalidate(void) +{ + #ifdef __GNUC__ + u32 stack_start,stack_end,stack_size; + register u32 L2CCReg; + stack_end = (u32)&_stack_end; + stack_start = (u32)&__undef_stack; + stack_size=stack_start-stack_end; + + /* Check for the cache status. If cache is enabled, then only + * flush stack memory to save return address. If cache is disabled, + * dont flush anything as it might result in flushing stale date into + * memory which is undesirable. + */ + L2CCReg = Xil_In32(XPS_L2CC_BASEADDR + XPS_L2CC_CNTRL_OFFSET); + if ((L2CCReg & 0x01U) != 0U) { + /*Flush stack memory to save return address*/ + Xil_DCacheFlushRange(stack_end, stack_size); + } + + #endif + u32 ResultDCache; + /* Invalidate the caches */ + Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_CACHE_INVLD_WAY_OFFSET, + 0x0000FFFFU); + ResultDCache = Xil_In32(XPS_L2CC_BASEADDR + XPS_L2CC_CACHE_INVLD_WAY_OFFSET) + & 0x0000FFFFU; + while(ResultDCache != (u32)0U) { + ResultDCache = Xil_In32(XPS_L2CC_BASEADDR + XPS_L2CC_CACHE_INVLD_WAY_OFFSET) + & 0x0000FFFFU; + } + + /* Wait for the invalidate to complete */ + Xil_L2CacheSync(); + + /* synchronize the processor */ + dsb(); +} + +/*****************************************************************************/ +/** +* @brief Invalidate a level 2 cache line. If the byte specified by the +* address (adr) is cached by the Data cache, the cacheline containing +* that byte is invalidated. If the cacheline is modified (dirty), +* the modified contents are lost and are NOT written to system memory +* before the line is invalidated. +* +* @param adr: 32bit address of the data/instruction to be invalidated. +* +* @return None. +* +* @note The bottom 4 bits are set to 0, forced by architecture. +* +****************************************************************************/ +void Xil_L2CacheInvalidateLine(u32 adr) +{ + Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_CACHE_INVLD_PA_OFFSET, (u32)adr); + /* synchronize the processor */ + dsb(); +} + +/****************************************************************************/ +/** +* @brief Invalidate the level 2 cache for the given address range. +* If the bytes specified by the address range are cached by the L2 +* cache, the cacheline containing those bytes are invalidated. If the +* cachelines are modified (dirty), the modified contents are lost and +* are NOT written to system memory before the lines are invalidated. +* +* @param adr: 32bit start address of the range to be invalidated. +* @param len: Length of the range to be invalidated in bytes. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void Xil_L2CacheInvalidateRange(u32 adr, u32 len) +{ + u32 LocalAddr = adr; + const u32 cacheline = 32U; + u32 end; + volatile u32 *L2CCOffset = (volatile u32 *)(XPS_L2CC_BASEADDR + + XPS_L2CC_CACHE_INVLD_PA_OFFSET); + + u32 currmask; + + currmask = mfcpsr(); + mtcpsr(currmask | IRQ_FIQ_MASK); + + if (len != 0U) { + /* Back the starting address up to the start of a cache line + * perform cache operations until adr+len + */ + end = LocalAddr + len; + LocalAddr = LocalAddr & ~(cacheline - 1U); + + /* Disable Write-back and line fills */ + Xil_L2WriteDebugCtrl(0x3U); + + while (LocalAddr < end) { + *L2CCOffset = LocalAddr; + Xil_L2CacheSync(); + LocalAddr += cacheline; + } + + /* Enable Write-back and line fills */ + Xil_L2WriteDebugCtrl(0x0U); + } + + /* synchronize the processor */ + dsb(); + mtcpsr(currmask); +} + +/****************************************************************************/ +/** +* @brief Flush the entire level 2 cache. +* +* @param None. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void Xil_L2CacheFlush(void) +{ + u32 ResultL2Cache; + + /* Flush the caches */ + + /* Disable Write-back and line fills */ + Xil_L2WriteDebugCtrl(0x3U); + + Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_CACHE_INV_CLN_WAY_OFFSET, + 0x0000FFFFU); + ResultL2Cache = Xil_In32(XPS_L2CC_BASEADDR + XPS_L2CC_CACHE_INV_CLN_WAY_OFFSET) + & 0x0000FFFFU; + + while(ResultL2Cache != (u32)0U) { + ResultL2Cache = Xil_In32(XPS_L2CC_BASEADDR + XPS_L2CC_CACHE_INV_CLN_WAY_OFFSET) + & 0x0000FFFFU; + } + + Xil_L2CacheSync(); + /* Enable Write-back and line fills */ + Xil_L2WriteDebugCtrl(0x0U); + + /* synchronize the processor */ + dsb(); +} + +/****************************************************************************/ +/** +* @brief Flush a level 2 cache line. If the byte specified by the address +* (adr) is cached by the L2 cache, the cacheline containing that +* byte is invalidated. If the cacheline is modified (dirty), the +* entire contents of the cacheline are written to system memory +* before the line is invalidated. +* +* @param adr: 32bit address of the data/instruction to be flushed. +* +* @return None. +* +* @note The bottom 4 bits are set to 0, forced by architecture. +* +****************************************************************************/ +void Xil_L2CacheFlushLine(u32 adr) +{ +#ifdef CONFIG_PL310_ERRATA_588369 + Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_CACHE_CLEAN_PA_OFFSET, adr); + Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_CACHE_INVLD_PA_OFFSET, adr); +#else + Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_CACHE_INV_CLN_PA_OFFSET, adr); +#endif + /* synchronize the processor */ + dsb(); +} + +/****************************************************************************/ +/** +* @brief Flush the level 2 cache for the given address range. +* If the bytes specified by the address range are cached by the L2 +* cache, the cacheline containing those bytes are invalidated. If the +* cachelines are modified (dirty), they are written to the system +* memory before the lines are invalidated. +* +* @param adr: 32bit start address of the range to be flushed. +* @param len: Length of the range to be flushed in bytes. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void Xil_L2CacheFlushRange(u32 adr, u32 len) +{ + u32 LocalAddr = adr; + const u32 cacheline = 32U; + u32 end; + volatile u32 *L2CCOffset = (volatile u32 *)(XPS_L2CC_BASEADDR + + XPS_L2CC_CACHE_INV_CLN_PA_OFFSET); + + u32 currmask; + + currmask = mfcpsr(); + mtcpsr(currmask | IRQ_FIQ_MASK); + if (len != 0U) { + /* Back the starting address up to the start of a cache line + * perform cache operations until adr+len + */ + end = LocalAddr + len; + LocalAddr = LocalAddr & ~(cacheline - 1U); + + /* Disable Write-back and line fills */ + Xil_L2WriteDebugCtrl(0x3U); + + while (LocalAddr < end) { + *L2CCOffset = LocalAddr; + Xil_L2CacheSync(); + LocalAddr += cacheline; + } + + /* Enable Write-back and line fills */ + Xil_L2WriteDebugCtrl(0x0U); + } + /* synchronize the processor */ + dsb(); + mtcpsr(currmask); +} + +/****************************************************************************/ +/** +* @brief Store a level 2 cache line. If the byte specified by the address +* (adr) is cached by the L2 cache and the cacheline is modified +* (dirty), the entire contents of the cacheline are written to +* system memory. After the store completes, the cacheline is marked +* as unmodified (not dirty). +* +* @param adr: 32bit address of the data/instruction to be stored. +* +* @return None. +* +* @note The bottom 4 bits are set to 0, forced by architecture. +* +****************************************************************************/ +void Xil_L2CacheStoreLine(u32 adr) +{ + Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_CACHE_CLEAN_PA_OFFSET, adr); + /* synchronize the processor */ + dsb(); +} +#endif diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_cache.h b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_cache.h new file mode 100644 index 0000000..ce6fcf4 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_cache.h @@ -0,0 +1,118 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_cache.h +* +* @addtogroup a9_cache_apis Cortex A9 Processor Cache Functions +* +* Cache functions provide access to cache related operations such as flush +* and invalidate for instruction and data caches. It gives option to perform +* the cache operations on a single cacheline, a range of memory and an entire +* cache. +* +* @{ +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a ecm  01/29/10 First release
+* 3.04a sdm  01/02/12 Remove redundant dsb/dmb instructions in cache maintenance
+*		      APIs.
+* 6.8   aru  09/06/18 Removed compilation warnings for ARMCC toolchain.
+* 
+* +******************************************************************************/ +#ifndef XIL_CACHE_H +#define XIL_CACHE_H + +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __GNUC__ + +#define asm_cp15_inval_dc_line_mva_poc(param) __asm__ __volatile__("mcr " \ + XREG_CP15_INVAL_DC_LINE_MVA_POC :: "r" (param)); + +#define asm_cp15_clean_inval_dc_line_mva_poc(param) __asm__ __volatile__("mcr " \ + XREG_CP15_CLEAN_INVAL_DC_LINE_MVA_POC :: "r" (param)); + +#define asm_cp15_inval_ic_line_mva_pou(param) __asm__ __volatile__("mcr " \ + XREG_CP15_INVAL_IC_LINE_MVA_POU :: "r" (param)); + +#define asm_cp15_inval_dc_line_sw(param) __asm__ __volatile__("mcr " \ + XREG_CP15_INVAL_DC_LINE_SW :: "r" (param)); + +#define asm_cp15_clean_inval_dc_line_sw(param) __asm__ __volatile__("mcr " \ + XREG_CP15_CLEAN_INVAL_DC_LINE_SW :: "r" (param)); + +#elif defined (__ICCARM__) + +#define asm_cp15_inval_dc_line_mva_poc(param) __asm volatile ("mcr " \ + XREG_CP15_INVAL_DC_LINE_MVA_POC :: "r" (param)); + +#define asm_cp15_clean_inval_dc_line_mva_poc(param) __asm volatile ("mcr " \ + XREG_CP15_CLEAN_INVAL_DC_LINE_MVA_POC :: "r" (param)); + +#define asm_cp15_inval_ic_line_mva_pou(param) __asm volatile ("mcr " \ + XREG_CP15_INVAL_IC_LINE_MVA_POU :: "r" (param)); + +#define asm_cp15_inval_dc_line_sw(param) __asm volatile ("mcr " \ + XREG_CP15_INVAL_DC_LINE_SW :: "r" (param)); + +#define asm_cp15_clean_inval_dc_line_sw(param) __asm volatile ("mcr " \ + XREG_CP15_CLEAN_INVAL_DC_LINE_SW :: "r" (param)); + +#endif + +void Xil_DCacheEnable(void); +void Xil_DCacheDisable(void); +void Xil_DCacheInvalidate(void); +void Xil_DCacheInvalidateRange(INTPTR adr, u32 len); +void Xil_DCacheFlush(void); +void Xil_DCacheFlushRange(INTPTR adr, u32 len); + +void Xil_ICacheEnable(void); +void Xil_ICacheDisable(void); +void Xil_ICacheInvalidate(void); +void Xil_ICacheInvalidateRange(INTPTR adr, u32 len); + +#ifdef __cplusplus +} +#endif + +#endif +/** +* @} End of "addtogroup a9_cache_apis". +*/ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_cache_l.h b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_cache_l.h new file mode 100644 index 0000000..b6ff809 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_cache_l.h @@ -0,0 +1,97 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_cache_l.h +* +* Contains L1 and L2 specific functions for the ARM cache functionality +* used by xcache.c. This functionality is being made available here for +* more sophisticated users. +* +* @addtogroup a9_cache_apis +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a ecm  01/24/10 First release
+* 6.8   aru  09/06/18 Removed compilation warnings for ARMCC toolchain.
+* 
+* +******************************************************************************/ +#ifndef XIL_CACHE_MACH_H +#define XIL_CACHE_MACH_H + +#include "xil_types.h" +#ifdef __cplusplus +extern "C" { +#endif + +/************************** Function Prototypes ******************************/ + +void Xil_DCacheInvalidateLine(u32 adr); +void Xil_DCacheFlushLine(u32 adr); +void Xil_DCacheStoreLine(u32 adr); +void Xil_ICacheInvalidateLine(u32 adr); + +void Xil_L1DCacheEnable(void); +void Xil_L1DCacheDisable(void); +void Xil_L1DCacheInvalidate(void); +void Xil_L1DCacheInvalidateLine(u32 adr); +void Xil_L1DCacheInvalidateRange(u32 adr, u32 len); +void Xil_L1DCacheFlush(void); +void Xil_L1DCacheFlushLine(u32 adr); +void Xil_L1DCacheFlushRange(u32 adr, u32 len); +void Xil_L1DCacheStoreLine(u32 adr); + +void Xil_L1ICacheEnable(void); +void Xil_L1ICacheDisable(void); +void Xil_L1ICacheInvalidate(void); +void Xil_L1ICacheInvalidateLine(u32 adr); +void Xil_L1ICacheInvalidateRange(u32 adr, u32 len); + +void Xil_L2CacheEnable(void); +void Xil_L2CacheDisable(void); +void Xil_L2CacheInvalidate(void); +void Xil_L2CacheInvalidateLine(u32 adr); +void Xil_L2CacheInvalidateRange(u32 adr, u32 len); +void Xil_L2CacheFlush(void); +void Xil_L2CacheFlushLine(u32 adr); +void Xil_L2CacheFlushRange(u32 adr, u32 len); +void Xil_L2CacheStoreLine(u32 adr); + +#ifdef __cplusplus +} +#endif + +#endif +/** +* @} End of "addtogroup a9_cache_apis". +*/ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_cache_vxworks.h b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_cache_vxworks.h new file mode 100644 index 0000000..7e2a7d9 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_cache_vxworks.h @@ -0,0 +1,89 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_cache_vxworks.h +* +* Contains the cache related functions for VxWorks that is wrapped by +* xil_cache. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date	 Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a hbm  12/11/09 Initial release
+*
+* 
+* +* @note +* +******************************************************************************/ + +#ifndef XIL_CACHE_VXWORKS_H +#define XIL_CACHE_VXWORKS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "vxWorks.h" +#include "vxLib.h" +#include "sysLibExtra.h" +#include "cacheLib.h" + +#if (CPU_FAMILY==PPC) + +#define Xil_DCacheEnable() cacheEnable(DATA_CACHE) + +#define Xil_DCacheDisable() cacheDisable(DATA_CACHE) + +#define Xil_DCacheInvalidateRange(Addr, Len) \ + cacheInvalidate(DATA_CACHE, (void *)(Addr), (Len)) + +#define Xil_DCacheFlushRange(Addr, Len) \ + cacheFlush(DATA_CACHE, (void *)(Addr), (Len)) + +#define Xil_ICacheEnable() cacheEnable(INSTRUCTION_CACHE) + +#define Xil_ICacheDisable() cacheDisable(INSTRUCTION_CACHE) + +#define Xil_ICacheInvalidateRange(Addr, Len) \ + cacheInvalidate(INSTRUCTION_CACHE, (void *)(Addr), (Len)) + + +#else +#error "Unknown processor / architecture. Must be PPC for VxWorks." +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_errata.h b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_errata.h new file mode 100644 index 0000000..c839b63 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_errata.h @@ -0,0 +1,127 @@ +/****************************************************************************** +* +* Copyright (C) 2013 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_errata.h +* +* @addtogroup a9_errata Cortex A9 Processor and pl310 Errata Support +* @{ +* Various ARM errata are handled in the standalone BSP. The implementation for +* errata handling follows ARM guidelines and is based on the open source Linux +* support for these errata. +* +* @note +* The errata handling is enabled by default. To disable handling of all the +* errata globally, un-define the macro ENABLE_ARM_ERRATA in xil_errata.h. To +* disable errata on a per-erratum basis, un-define relevant macros in +* xil_errata.h. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a srt  04/18/13 First release
+* 6.6   mus  12/07/17 Removed errata 753970, It fixes CR#989132.
+* 
+* +******************************************************************************/ +#ifndef XIL_ERRATA_H +#define XIL_ERRATA_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @name errata_definitions + * + * The errata conditions handled in the standalone BSP are listed below + * @{ + */ + +#define ENABLE_ARM_ERRATA 1 + +#ifdef ENABLE_ARM_ERRATA + +/** + * Errata No: 742230 + * Description: DMB operation may be faulty + */ +#define CONFIG_ARM_ERRATA_742230 1 + +/** + * Errata No: 743622 + * Description: Faulty hazard checking in the Store Buffer may lead + * to data corruption. + */ +#define CONFIG_ARM_ERRATA_743622 1 + +/** + * Errata No: 775420 + * Description: A data cache maintenance operation which aborts, + * might lead to deadlock + */ +#define CONFIG_ARM_ERRATA_775420 1 + +/** + * Errata No: 794073 + * Description: Speculative instruction fetches with MMU disabled + * might not comply with architectural requirements + */ +#define CONFIG_ARM_ERRATA_794073 1 + + +/** PL310 L2 Cache Errata */ + +/** + * Errata No: 588369 + * Description: Clean & Invalidate maintenance operations do not + * invalidate clean lines + */ +#define CONFIG_PL310_ERRATA_588369 1 + +/** + * Errata No: 727915 + * Description: Background Clean and Invalidate by Way operation + * can cause data corruption + */ +#define CONFIG_PL310_ERRATA_727915 1 + +/*@}*/ +#endif /* ENABLE_ARM_ERRATA */ + +#ifdef __cplusplus +} +#endif + +#endif /* XIL_ERRATA_H */ +/** +* @} End of "addtogroup a9_errata". +*/ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_exception.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_exception.c new file mode 100644 index 0000000..16facac --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_exception.c @@ -0,0 +1,379 @@ +/****************************************************************************** +* +* Copyright (C) 2015 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xil_exception.c +* +* This file contains low-level driver functions for the Cortex A53,A9,R5 exception +* Handler. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 5.2	pkp  	 28/05/15 First release
+* 6.0   mus      27/07/16 Consolidated exceptions for a53,a9 and r5
+*                         processors and added Xil_UndefinedExceptionHandler
+*                         for a53 32 bit and r5 as well.
+* 6.4   mus      08/06/17 Updated debug prints to replace %x with the %lx, to
+*                         fix the warnings.
+* 6.7   mna      26/04/18 Add an API to obtain a corresponding
+*                         Xil_ExceptionHandler entry from XExc_VectorTable.
+* 6.7  asa       18/05/18 Fix bugs in the API Xil_GetExceptionRegisterHandler.
+* 7.0  mus       07/03/19 Tweak Xil_ExceptionRegisterHandler and
+*                         Xil_GetExceptionRegisterHandler to support legacy
+*                         examples for Cortexa72 EL3 exception level.
+*
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_exception.h" +#include "xpseudo_asm.h" +#include "xdebug.h" +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + +typedef struct { + Xil_ExceptionHandler Handler; + void *Data; +} XExc_VectorTableEntry; + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Function Prototypes *****************************/ +static void Xil_ExceptionNullHandler(void *Data); +/************************** Variable Definitions *****************************/ +/* + * Exception vector table to store handlers for each exception vector. + */ +#if defined (__aarch64__) +XExc_VectorTableEntry XExc_VectorTable[XIL_EXCEPTION_ID_LAST + 1] = +{ + {Xil_ExceptionNullHandler, NULL}, + {Xil_SyncAbortHandler, NULL}, + {Xil_ExceptionNullHandler, NULL}, + {Xil_ExceptionNullHandler, NULL}, + {Xil_SErrorAbortHandler, NULL}, + +}; +#else +XExc_VectorTableEntry XExc_VectorTable[XIL_EXCEPTION_ID_LAST + 1] = +{ + {Xil_ExceptionNullHandler, NULL}, + {Xil_UndefinedExceptionHandler, NULL}, + {Xil_ExceptionNullHandler, NULL}, + {Xil_PrefetchAbortHandler, NULL}, + {Xil_DataAbortHandler, NULL}, + {Xil_ExceptionNullHandler, NULL}, + {Xil_ExceptionNullHandler, NULL}, +}; +#endif +#if !defined (__aarch64__) +u32 DataAbortAddr; /* Address of instruction causing data abort */ +u32 PrefetchAbortAddr; /* Address of instruction causing prefetch abort */ +u32 UndefinedExceptionAddr; /* Address of instruction causing Undefined + exception */ +#endif + +/*****************************************************************************/ + +/****************************************************************************/ +/** +* +* This function is a stub Handler that is the default Handler that gets called +* if the application has not setup a Handler for a specific exception. The +* function interface has to match the interface specified for a Handler even +* though none of the arguments are used. +* +* @param Data is unused by this function. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +static void Xil_ExceptionNullHandler(void *Data) +{ + (void) Data; +DieLoop: goto DieLoop; +} + +/****************************************************************************/ +/** +* @brief The function is a common API used to initialize exception handlers +* across all supported arm processors. For ARM Cortex-A53, Cortex-R5, +* and Cortex-A9, the exception handlers are being initialized +* statically and this function does not do anything. +* However, it is still present to take care of backward compatibility +* issues (in earlier versions of BSPs, this API was being used to +* initialize exception handlers). +* +* @param None. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void Xil_ExceptionInit(void) +{ + return; +} + +/*****************************************************************************/ +/** +* @brief Register a handler for a specific exception. This handler is being +* called when the processor encounters the specified exception. +* +* @param exception_id contains the ID of the exception source and should +* be in the range of 0 to XIL_EXCEPTION_ID_LAST. +* See xil_exception.h for further information. +* @param Handler to the Handler for that exception. +* @param Data is a reference to Data that will be passed to the +* Handler when it gets called. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void Xil_ExceptionRegisterHandler(u32 Exception_id, + Xil_ExceptionHandler Handler, + void *Data) +{ +#if defined (versal) && !defined(ARMR5) && EL3 +/* + * Cortexa72 processor in versal is coupled with GIC-500, and GIC-500 supports + * only FIQ at EL3. Hence, tweaking this API to always act on FIQ, + * ignoring argument passed by user. + */ + Exception_id = XIL_EXCEPTION_ID_FIQ_INT; +#endif + XExc_VectorTable[Exception_id].Handler = Handler; + XExc_VectorTable[Exception_id].Data = Data; +} + +/*****************************************************************************/ +/** +* @brief Get a handler for a specific exception. This handler is being +* called when the processor encounters the specified exception. +* +* @param exception_id contains the ID of the exception source and should +* be in the range of 0 to XIL_EXCEPTION_ID_LAST. +* See xil_exception.h for further information. +* @param Handler to the Handler for that exception. +* @param Data is a reference to Data that will be passed to the +* Handler when it gets called. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void Xil_GetExceptionRegisterHandler(u32 Exception_id, + Xil_ExceptionHandler *Handler, + void **Data) +{ +#if defined (versal) && !defined(ARMR5) && EL3 +/* + * Cortexa72 processor in versal is coupled with GIC-500, and GIC-500 supports + * only FIQ at EL3. Hence, tweaking this API to always act on FIQ, + * ignoring argument passed by user. + */ + Exception_id = XIL_EXCEPTION_ID_FIQ_INT; +#endif + + *Handler = XExc_VectorTable[Exception_id].Handler; + *Data = XExc_VectorTable[Exception_id].Data; +} + +/*****************************************************************************/ +/** +* +* @brief Removes the Handler for a specific exception Id. The stub Handler +* is then registered for this exception Id. +* +* @param exception_id contains the ID of the exception source and should +* be in the range of 0 to XIL_EXCEPTION_ID_LAST. +* See xil_exception.h for further information. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void Xil_ExceptionRemoveHandler(u32 Exception_id) +{ + Xil_ExceptionRegisterHandler(Exception_id, + Xil_ExceptionNullHandler, + NULL); +} + +#if defined (__aarch64__) +/*****************************************************************************/ +/** +* +* Default Synchronous abort handler which prints a debug message on console if +* Debug flag is enabled +* +* @param None +* +* @return None. +* +* @note None. +* +****************************************************************************/ + +void Xil_SyncAbortHandler(void *CallBackRef){ + (void) CallBackRef; + xdbg_printf(XDBG_DEBUG_ERROR, "Synchronous abort \n"); + while(1) { + ; + } +} + +/*****************************************************************************/ +/** +* +* Default SError abort handler which prints a debug message on console if +* Debug flag is enabled +* +* @param None +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void Xil_SErrorAbortHandler(void *CallBackRef){ + (void) CallBackRef; + xdbg_printf(XDBG_DEBUG_ERROR, "Synchronous abort \n"); + while(1) { + ; + } +} +#else +/*****************************************************************************/ +/* +* +* Default Data abort handler which prints data fault status register through +* which information about data fault can be acquired +* +* @param None +* +* @return None. +* +* @note None. +* +****************************************************************************/ + +void Xil_DataAbortHandler(void *CallBackRef){ + (void) CallBackRef; +#ifdef DEBUG + u32 FaultStatus; + + xdbg_printf(XDBG_DEBUG_ERROR, "Data abort \n"); + #ifdef __GNUC__ + FaultStatus = mfcp(XREG_CP15_DATA_FAULT_STATUS); + #elif defined (__ICCARM__) + mfcp(XREG_CP15_DATA_FAULT_STATUS,FaultStatus); + #else + { volatile register u32 Reg __asm(XREG_CP15_DATA_FAULT_STATUS); + FaultStatus = Reg; } + #endif + xdbg_printf(XDBG_DEBUG_GENERAL, "Data abort with Data Fault Status Register %lx\n",FaultStatus); + xdbg_printf(XDBG_DEBUG_GENERAL, "Address of Instruction causing Data abort %lx\n",DataAbortAddr); +#endif + while(1) { + ; + } +} + +/*****************************************************************************/ +/* +* +* Default Prefetch abort handler which prints prefetch fault status register through +* which information about instruction prefetch fault can be acquired +* +* @param None +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void Xil_PrefetchAbortHandler(void *CallBackRef){ + (void) CallBackRef; +#ifdef DEBUG + u32 FaultStatus; + + xdbg_printf(XDBG_DEBUG_ERROR, "Prefetch abort \n"); + #ifdef __GNUC__ + FaultStatus = mfcp(XREG_CP15_INST_FAULT_STATUS); + #elif defined (__ICCARM__) + mfcp(XREG_CP15_INST_FAULT_STATUS,FaultStatus); + #else + { volatile register u32 Reg __asm(XREG_CP15_INST_FAULT_STATUS); + FaultStatus = Reg; } + #endif + xdbg_printf(XDBG_DEBUG_GENERAL, "Prefetch abort with Instruction Fault Status Register %lx\n",FaultStatus); + xdbg_printf(XDBG_DEBUG_GENERAL, "Address of Instruction causing Prefetch abort %lx\n",PrefetchAbortAddr); +#endif + while(1) { + ; + } +} +/*****************************************************************************/ +/* +* +* Default undefined exception handler which prints address of the undefined +* instruction if debug prints are enabled +* +* @param None +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void Xil_UndefinedExceptionHandler(void *CallBackRef){ + (void) CallBackRef; + xdbg_printf(XDBG_DEBUG_GENERAL, "Address of the undefined instruction %lx\n",UndefinedExceptionAddr); + while(1) { + ; + } +} +#endif diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_exception.h b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_exception.h new file mode 100644 index 0000000..807f310 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_exception.h @@ -0,0 +1,285 @@ +/****************************************************************************** +* +* Copyright (C) 2015 - 2016 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_exception.h +* +* This header file contains ARM Cortex A53,A9,R5 specific exception related APIs. +* For exception related functions that can be used across all Xilinx supported +* processors, please use xil_exception.h. +* +* @addtogroup arm_exception_apis ARM Processor Exception Handling +* @{ +* ARM processors specific exception related APIs for cortex A53,A9 and R5 can +* utilized for enabling/disabling IRQ, registering/removing handler for +* exceptions or initializing exception vector table with null handler. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 5.2	pkp  	 28/05/15 First release
+* 6.0   mus      27/07/16 Consolidated file for a53,a9 and r5 processors
+* 6.7   mna      26/04/18 Add API Xil_GetExceptionRegisterHandler.
+* 6.7   asa      18/05/18 Update signature of API Xil_GetExceptionRegisterHandler.
+* 7.0   mus      01/03/19 Tweak Xil_ExceptionEnableMask and
+*                         Xil_ExceptionDisableMask macros to support legacy
+*                         examples for Cortexa72 EL3 exception level.
+* 
+* +******************************************************************************/ + +#ifndef XIL_EXCEPTION_H /* prevent circular inclusions */ +#define XIL_EXCEPTION_H /* by using protection macros */ + +/***************************** Include Files ********************************/ + +#include "xil_types.h" +#include "xpseudo_asm.h" +#include "bspconfig.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************** Constant Definitions ****************************/ + +#define XIL_EXCEPTION_FIQ XREG_CPSR_FIQ_ENABLE +#define XIL_EXCEPTION_IRQ XREG_CPSR_IRQ_ENABLE +#define XIL_EXCEPTION_ALL (XREG_CPSR_FIQ_ENABLE | XREG_CPSR_IRQ_ENABLE) + +#define XIL_EXCEPTION_ID_FIRST 0U +#if defined (__aarch64__) +#define XIL_EXCEPTION_ID_SYNC_INT 1U +#define XIL_EXCEPTION_ID_IRQ_INT 2U +#define XIL_EXCEPTION_ID_FIQ_INT 3U +#define XIL_EXCEPTION_ID_SERROR_ABORT_INT 4U +#define XIL_EXCEPTION_ID_LAST 5U +#else +#define XIL_EXCEPTION_ID_RESET 0U +#define XIL_EXCEPTION_ID_UNDEFINED_INT 1U +#define XIL_EXCEPTION_ID_SWI_INT 2U +#define XIL_EXCEPTION_ID_PREFETCH_ABORT_INT 3U +#define XIL_EXCEPTION_ID_DATA_ABORT_INT 4U +#define XIL_EXCEPTION_ID_IRQ_INT 5U +#define XIL_EXCEPTION_ID_FIQ_INT 6U +#define XIL_EXCEPTION_ID_LAST 6U +#endif + +/* + * XIL_EXCEPTION_ID_INT is defined for all Xilinx processors. + */ +#if defined (versal) && !defined(ARMR5) && EL3 +#define XIL_EXCEPTION_ID_INT XIL_EXCEPTION_ID_FIQ_INT +#else +#define XIL_EXCEPTION_ID_INT XIL_EXCEPTION_ID_IRQ_INT +#endif + +/**************************** Type Definitions ******************************/ + +/** + * This typedef is the exception handler function. + */ +typedef void (*Xil_ExceptionHandler)(void *data); +typedef void (*Xil_InterruptHandler)(void *data); + +/***************** Macros (Inline Functions) Definitions ********************/ + +/****************************************************************************/ +/** +* @brief Enable Exceptions. +* +* @param Mask: Value for enabling the exceptions. +* +* @return None. +* +* @note If bit is 0, exception is enabled. +* C-Style signature: void Xil_ExceptionEnableMask(Mask) +* +******************************************************************************/ +#if defined (versal) && !defined(ARMR5) && EL3 +/* + * Cortexa72 processor in versal is coupled with GIC-500, and GIC-500 supports + * only FIQ at EL3. Hence, tweaking this macro to always enable FIQ + * ignoring argument passed by user. + */ +#define Xil_ExceptionEnableMask(Mask) \ + mtcpsr(mfcpsr() & ~ ((XIL_EXCEPTION_FIQ) & XIL_EXCEPTION_ALL)) +#elif defined (__GNUC__) || defined (__ICCARM__) +#define Xil_ExceptionEnableMask(Mask) \ + mtcpsr(mfcpsr() & ~ ((Mask) & XIL_EXCEPTION_ALL)) +#else +#define Xil_ExceptionEnableMask(Mask) \ + { \ + register u32 Reg __asm("cpsr"); \ + mtcpsr((Reg) & (~((Mask) & XIL_EXCEPTION_ALL))); \ + } +#endif +/****************************************************************************/ +/** +* @brief Enable the IRQ exception. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +#if defined (versal) && !defined(ARMR5) && EL3 +#define Xil_ExceptionEnable() \ + Xil_ExceptionEnableMask(XIL_EXCEPTION_FIQ) +#else +#define Xil_ExceptionEnable() \ + Xil_ExceptionEnableMask(XIL_EXCEPTION_IRQ) +#endif + +/****************************************************************************/ +/** +* @brief Disable Exceptions. +* +* @param Mask: Value for disabling the exceptions. +* +* @return None. +* +* @note If bit is 1, exception is disabled. +* C-Style signature: Xil_ExceptionDisableMask(Mask) +* +******************************************************************************/ +#if defined (versal) && !defined(ARMR5) && EL3 +/* + * Cortexa72 processor in versal is coupled with GIC-500, and GIC-500 supports + * only FIQ at EL3. Hence, tweaking this macro to always disable FIQ + * ignoring argument passed by user. + */ +#define Xil_ExceptionDisableMask(Mask) \ + mtcpsr(mfcpsr() | ((XIL_EXCEPTION_FIQ) & XIL_EXCEPTION_ALL)) +#elif defined (__GNUC__) || defined (__ICCARM__) +#define Xil_ExceptionDisableMask(Mask) \ + mtcpsr(mfcpsr() | ((Mask) & XIL_EXCEPTION_ALL)) +#else +#define Xil_ExceptionDisableMask(Mask) \ + { \ + register u32 Reg __asm("cpsr"); \ + mtcpsr((Reg) | ((Mask) & XIL_EXCEPTION_ALL)); \ + } +#endif +/****************************************************************************/ +/** +* Disable the IRQ exception. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +#define Xil_ExceptionDisable() \ + Xil_ExceptionDisableMask(XIL_EXCEPTION_IRQ) + +#if !defined (__aarch64__) && !defined (ARMA53_32) +/****************************************************************************/ +/** +* @brief Enable nested interrupts by clearing the I and F bits in CPSR. This +* API is defined for cortex-a9 and cortex-r5. +* +* @return None. +* +* @note This macro is supposed to be used from interrupt handlers. In the +* interrupt handler the interrupts are disabled by default (I and F +* are 1). To allow nesting of interrupts, this macro should be +* used. It clears the I and F bits by changing the ARM mode to +* system mode. Once these bits are cleared and provided the +* preemption of interrupt conditions are met in the GIC, nesting of +* interrupts will start happening. +* Caution: This macro must be used with caution. Before calling this +* macro, the user must ensure that the source of the current IRQ +* is appropriately cleared. Otherwise, as soon as we clear the I and +* F bits, there can be an infinite loop of interrupts with an +* eventual crash (all the stack space getting consumed). +******************************************************************************/ +#define Xil_EnableNestedInterrupts() \ + __asm__ __volatile__ ("stmfd sp!, {lr}"); \ + __asm__ __volatile__ ("mrs lr, spsr"); \ + __asm__ __volatile__ ("stmfd sp!, {lr}"); \ + __asm__ __volatile__ ("msr cpsr_c, #0x1F"); \ + __asm__ __volatile__ ("stmfd sp!, {lr}"); + +/****************************************************************************/ +/** +* @brief Disable the nested interrupts by setting the I and F bits. This API +* is defined for cortex-a9 and cortex-r5. +* +* @return None. +* +* @note This macro is meant to be called in the interrupt service routines. +* This macro cannot be used independently. It can only be used when +* nesting of interrupts have been enabled by using the macro +* Xil_EnableNestedInterrupts(). In a typical flow, the user first +* calls the Xil_EnableNestedInterrupts in the ISR at the appropriate +* point. The user then must call this macro before exiting the interrupt +* service routine. This macro puts the ARM back in IRQ/FIQ mode and +* hence sets back the I and F bits. +******************************************************************************/ +#define Xil_DisableNestedInterrupts() \ + __asm__ __volatile__ ("ldmfd sp!, {lr}"); \ + __asm__ __volatile__ ("msr cpsr_c, #0x92"); \ + __asm__ __volatile__ ("ldmfd sp!, {lr}"); \ + __asm__ __volatile__ ("msr spsr_cxsf, lr"); \ + __asm__ __volatile__ ("ldmfd sp!, {lr}"); \ + +#endif +/************************** Variable Definitions ****************************/ + +/************************** Function Prototypes *****************************/ + +extern void Xil_ExceptionRegisterHandler(u32 Exception_id, + Xil_ExceptionHandler Handler, + void *Data); + +extern void Xil_ExceptionRemoveHandler(u32 Exception_id); +extern void Xil_GetExceptionRegisterHandler(u32 Exception_id, + Xil_ExceptionHandler *Handler, void **Data); + +extern void Xil_ExceptionInit(void); +#if defined (__aarch64__) +void Xil_SyncAbortHandler(void *CallBackRef); +void Xil_SErrorAbortHandler(void *CallBackRef); +#else +extern void Xil_DataAbortHandler(void *CallBackRef); +extern void Xil_PrefetchAbortHandler(void *CallBackRef); +extern void Xil_UndefinedExceptionHandler(void *CallBackRef); +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* XIL_EXCEPTION_H */ +/** +* @} End of "addtogroup arm_exception_apis". +*/ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_hal.h b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_hal.h new file mode 100644 index 0000000..e8971c9 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_hal.h @@ -0,0 +1,65 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_hal.h +* +* Contains all the HAL header files. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date	 Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a hbm  07/28/09 Initial release
+*
+* 
+* +* @note +* +******************************************************************************/ + +#ifndef XIL_HAL_H +#define XIL_HAL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "xil_cache.h" +#include "xil_io.h" +#include "xil_assert.h" +#include "xil_exception.h" +#include "xil_types.h" + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_io.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_io.c new file mode 100644 index 0000000..6ed1559 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_io.c @@ -0,0 +1,98 @@ +/****************************************************************************** +* +* Copyright (C) 2014 - 2016 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_io.c +* +* Contains I/O functions for memory-mapped or non-memory-mapped I/O +* architectures. +* +* @note +* +* This file contains architecture-dependent code. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 5.00 	pkp  	 05/29/14 First release
+* 
+******************************************************************************/ + + +/***************************** Include Files *********************************/ +#include "xil_io.h" +#include "xil_types.h" +#include "xil_assert.h" + +/*****************************************************************************/ +/** +* +* @brief Perform a 16-bit endian converion. +* +* @param Data: 16 bit value to be converted +* +* @return 16 bit Data with converted endianess +* +******************************************************************************/ +u16 Xil_EndianSwap16(u16 Data) +{ + return (u16) (((Data & 0xFF00U) >> 8U) | ((Data & 0x00FFU) << 8U)); +} + +/*****************************************************************************/ +/** +* +* @brief Perform a 32-bit endian converion. +* +* @param Data: 32 bit value to be converted +* +* @return 32 bit data with converted endianess +* +******************************************************************************/ +u32 Xil_EndianSwap32(u32 Data) +{ + u16 LoWord; + u16 HiWord; + + /* get each of the half words from the 32 bit word */ + + LoWord = (u16) (Data & 0x0000FFFFU); + HiWord = (u16) ((Data & 0xFFFF0000U) >> 16U); + + /* byte swap each of the 16 bit half words */ + + LoWord = (((LoWord & 0xFF00U) >> 8U) | ((LoWord & 0x00FFU) << 8U)); + HiWord = (((HiWord & 0xFF00U) >> 8U) | ((HiWord & 0x00FFU) << 8U)); + + /* swap the half words before returning the value */ + + return ((((u32)LoWord) << (u32)16U) | (u32)HiWord); +} diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_io.h b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_io.h new file mode 100644 index 0000000..00207cf --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_io.h @@ -0,0 +1,341 @@ +/****************************************************************************** +* +* Copyright (C) 2014 - 2016 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_io.h +* +* @addtogroup common_io_interfacing_apis Register IO interfacing APIs +* +* The xil_io.h file contains the interface for the general I/O component, which +* encapsulates the Input/Output functions for the processors that do not +* require any special I/O handling. +* +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 5.00 	pkp  	 05/29/14 First release
+* 6.00  mus      08/19/16 Remove checking of __LITTLE_ENDIAN__ flag for
+*                         ARM processors
+* 
+******************************************************************************/ + +#ifndef XIL_IO_H /* prevent circular inclusions */ +#define XIL_IO_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_printf.h" + +#if defined (__MICROBLAZE__) +#include "mb_interface.h" +#else +#include "xpseudo_asm.h" +#endif + +/************************** Function Prototypes ******************************/ +u16 Xil_EndianSwap16(u16 Data); +u32 Xil_EndianSwap32(u32 Data); +#ifdef ENABLE_SAFETY +extern u32 XStl_RegUpdate(u32 RegAddr, u32 RegVal); +#endif + +/***************** Macros (Inline Functions) Definitions *********************/ +#if defined __GNUC__ +#if defined (__MICROBLAZE__) +# define INST_SYNC mbar(0) +# define DATA_SYNC mbar(1) +# else +# define SYNCHRONIZE_IO dmb() +# define INST_SYNC isb() +# define DATA_SYNC dsb() +# endif +#else +# define SYNCHRONIZE_IO +# define INST_SYNC +# define DATA_SYNC +# define INST_SYNC +# define DATA_SYNC +#endif + +#if defined (__GNUC__) || defined (__ICCARM__) || defined (__MICROBLAZE__) +#define INLINE inline +#else +#define INLINE __inline +#endif + +/*****************************************************************************/ +/** +* +* @brief Performs an input operation for a memory location by reading +* from the specified address and returning the 8 bit Value read from +* that address. +* +* @param Addr: contains the address to perform the input operation +* +* @return The 8 bit Value read from the specified input address. + +* +******************************************************************************/ +static INLINE u8 Xil_In8(UINTPTR Addr) +{ + return *(volatile u8 *) Addr; +} + +/*****************************************************************************/ +/** +* +* @brief Performs an input operation for a memory location by reading from +* the specified address and returning the 16 bit Value read from that +* address. +* +* @param Addr: contains the address to perform the input operation +* +* @return The 16 bit Value read from the specified input address. +* +******************************************************************************/ +static INLINE u16 Xil_In16(UINTPTR Addr) +{ + return *(volatile u16 *) Addr; +} + +/*****************************************************************************/ +/** +* +* @brief Performs an input operation for a memory location by +* reading from the specified address and returning the 32 bit Value +* read from that address. +* +* @param Addr: contains the address to perform the input operation +* +* @return The 32 bit Value read from the specified input address. +* +******************************************************************************/ +static INLINE u32 Xil_In32(UINTPTR Addr) +{ + return *(volatile u32 *) Addr; +} + +/*****************************************************************************/ +/** +* +* @brief Performs an input operation for a memory location by reading the +* 64 bit Value read from that address. +* +* +* @param Addr: contains the address to perform the input operation +* +* @return The 64 bit Value read from the specified input address. +* +******************************************************************************/ +static INLINE u64 Xil_In64(UINTPTR Addr) +{ + return *(volatile u64 *) Addr; +} + +/*****************************************************************************/ +/** +* +* @brief Performs an output operation for an memory location by +* writing the 8 bit Value to the the specified address. +* +* @param Addr: contains the address to perform the output operation +* @param Value: contains the 8 bit Value to be written at the specified +* address. +* +* @return None. +* +******************************************************************************/ +static INLINE void Xil_Out8(UINTPTR Addr, u8 Value) +{ + volatile u8 *LocalAddr = (volatile u8 *)Addr; + *LocalAddr = Value; +} + +/*****************************************************************************/ +/** +* +* @brief Performs an output operation for a memory location by writing the +* 16 bit Value to the the specified address. +* +* @param Addr contains the address to perform the output operation +* @param Value contains the Value to be written at the specified address. +* +* @return None. +* +******************************************************************************/ +static INLINE void Xil_Out16(UINTPTR Addr, u16 Value) +{ + volatile u16 *LocalAddr = (volatile u16 *)Addr; + *LocalAddr = Value; +} + +/*****************************************************************************/ +/** +* +* @brief Performs an output operation for a memory location by writing the +* 32 bit Value to the the specified address. +* +* @param Addr contains the address to perform the output operation +* @param Value contains the 32 bit Value to be written at the specified +* address. +* +* @return None. +* +******************************************************************************/ +static INLINE void Xil_Out32(UINTPTR Addr, u32 Value) +{ +#ifndef ENABLE_SAFETY + volatile u32 *LocalAddr = (volatile u32 *)Addr; + *LocalAddr = Value; +#else + XStl_RegUpdate(Addr, Value); +#endif +} + +/*****************************************************************************/ +/** +* +* @brief Performs an output operation for a memory location by writing the +* 64 bit Value to the the specified address. +* +* @param Addr contains the address to perform the output operation +* @param Value contains 64 bit Value to be written at the specified address. +* +* @return None. +* +******************************************************************************/ +static INLINE void Xil_Out64(UINTPTR Addr, u64 Value) +{ + volatile u64 *LocalAddr = (volatile u64 *)Addr; + *LocalAddr = Value; +} + +#if defined (__MICROBLAZE__) +#ifdef __LITTLE_ENDIAN__ +# define Xil_In16LE Xil_In16 +# define Xil_In32LE Xil_In32 +# define Xil_Out16LE Xil_Out16 +# define Xil_Out32LE Xil_Out32 +# define Xil_Htons Xil_EndianSwap16 +# define Xil_Htonl Xil_EndianSwap32 +# define Xil_Ntohs Xil_EndianSwap16 +# define Xil_Ntohl Xil_EndianSwap32 +# else +# define Xil_In16BE Xil_In16 +# define Xil_In32BE Xil_In32 +# define Xil_Out16BE Xil_Out16 +# define Xil_Out32BE Xil_Out32 +# define Xil_Htons(Data) (Data) +# define Xil_Htonl(Data) (Data) +# define Xil_Ntohs(Data) (Data) +# define Xil_Ntohl(Data) (Data) +#endif +#else +# define Xil_In16LE Xil_In16 +# define Xil_In32LE Xil_In32 +# define Xil_Out16LE Xil_Out16 +# define Xil_Out32LE Xil_Out32 +# define Xil_Htons Xil_EndianSwap16 +# define Xil_Htonl Xil_EndianSwap32 +# define Xil_Ntohs Xil_EndianSwap16 +# define Xil_Ntohl Xil_EndianSwap32 +#endif + +#if defined (__MICROBLAZE__) +#ifdef __LITTLE_ENDIAN__ +static INLINE u16 Xil_In16BE(UINTPTR Addr) +#else +static INLINE u16 Xil_In16LE(UINTPTR Addr) +#endif +#else +static INLINE u16 Xil_In16BE(UINTPTR Addr) +#endif +{ + u16 value = Xil_In16(Addr); + return Xil_EndianSwap16(value); +} + +#if defined (__MICROBLAZE__) +#ifdef __LITTLE_ENDIAN__ +static INLINE u32 Xil_In32BE(UINTPTR Addr) +#else +static INLINE u32 Xil_In32LE(UINTPTR Addr) +#endif +#else +static INLINE u32 Xil_In32BE(UINTPTR Addr) +#endif +{ + u32 value = Xil_In32(Addr); + return Xil_EndianSwap32(value); +} + +#if defined (__MICROBLAZE__) +#ifdef __LITTLE_ENDIAN__ +static INLINE void Xil_Out16BE(UINTPTR Addr, u16 Value) +#else +static INLINE void Xil_Out16LE(UINTPTR Addr, u16 Value) +#endif +#else +static INLINE void Xil_Out16BE(UINTPTR Addr, u16 Value) +#endif +{ + Value = Xil_EndianSwap16(Value); + Xil_Out16(Addr, Value); +} + +#if defined (__MICROBLAZE__) +#ifdef __LITTLE_ENDIAN__ +static INLINE void Xil_Out32BE(UINTPTR Addr, u32 Value) +#else +static INLINE void Xil_Out32LE(UINTPTR Addr, u32 Value) +#endif +#else +static INLINE void Xil_Out32BE(UINTPTR Addr, u32 Value) +#endif +{ + Value = Xil_EndianSwap32(Value); + Xil_Out32(Addr, Value); +} + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** +* @} End of "addtogroup common_io_interfacing_apis". +*/ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_macroback.h b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_macroback.h new file mode 100644 index 0000000..b245c18 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_macroback.h @@ -0,0 +1,1056 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +/*********************************************************************/ +/** + * @file xil_macroback.h + * + * This header file is meant to bring back the removed _m macros. + * This header file must be included last. + * The following macros are not defined here due to the driver change: + * XGpio_mSetDataDirection + * XGpio_mGetDataReg + * XGpio_mSetDataReg + * XIIC_RESET + * XIIC_CLEAR_STATS + * XSpi_mReset + * XSysAce_mSetCfgAddr + * XSysAce_mIsCfgDone + * XTft_mSetPixel + * XTft_mGetPixel + * XWdtTb_mEnableWdt + * XWdtTb_mDisbleWdt + * XWdtTb_mRestartWdt + * XWdtTb_mGetTimebaseReg + * XWdtTb_mHasReset + * + * Please refer the corresonding driver document for replacement. + * + *********************************************************************/ + +#ifndef XIL_MACROBACK_H +#define XIL_MACROBACK_H + +#ifdef __cplusplus +extern "C" { +#endif + +/*********************************************************************/ +/** + * Macros for Driver XCan + * + *********************************************************************/ +#ifndef XCan_mReadReg +#define XCan_mReadReg XCan_ReadReg +#endif + +#ifndef XCan_mWriteReg +#define XCan_mWriteReg XCan_WriteReg +#endif + +#ifndef XCan_mIsTxDone +#define XCan_mIsTxDone XCan_IsTxDone +#endif + +#ifndef XCan_mIsTxFifoFull +#define XCan_mIsTxFifoFull XCan_IsTxFifoFull +#endif + +#ifndef XCan_mIsHighPriorityBufFull +#define XCan_mIsHighPriorityBufFull XCan_IsHighPriorityBufFull +#endif + +#ifndef XCan_mIsRxEmpty +#define XCan_mIsRxEmpty XCan_IsRxEmpty +#endif + +#ifndef XCan_mIsAcceptFilterBusy +#define XCan_mIsAcceptFilterBusy XCan_IsAcceptFilterBusy +#endif + +#ifndef XCan_mCreateIdValue +#define XCan_mCreateIdValue XCan_CreateIdValue +#endif + +#ifndef XCan_mCreateDlcValue +#define XCan_mCreateDlcValue XCan_CreateDlcValue +#endif + +/*********************************************************************/ +/** + * Macros for Driver XDmaCentral + * + *********************************************************************/ +#ifndef XDmaCentral_mWriteReg +#define XDmaCentral_mWriteReg XDmaCentral_WriteReg +#endif + +#ifndef XDmaCentral_mReadReg +#define XDmaCentral_mReadReg XDmaCentral_ReadReg +#endif + +/*********************************************************************/ +/** + * Macros for Driver XDsAdc + * + *********************************************************************/ +#ifndef XDsAdc_mWriteReg +#define XDsAdc_mWriteReg XDsAdc_WriteReg +#endif + +#ifndef XDsAdc_mReadReg +#define XDsAdc_mReadReg XDsAdc_ReadReg +#endif + +#ifndef XDsAdc_mIsEmpty +#define XDsAdc_mIsEmpty XDsAdc_IsEmpty +#endif + +#ifndef XDsAdc_mSetFstmReg +#define XDsAdc_mSetFstmReg XDsAdc_SetFstmReg +#endif + +#ifndef XDsAdc_mGetFstmReg +#define XDsAdc_mGetFstmReg XDsAdc_GetFstmReg +#endif + +#ifndef XDsAdc_mEnableConversion +#define XDsAdc_mEnableConversion XDsAdc_EnableConversion +#endif + +#ifndef XDsAdc_mDisableConversion +#define XDsAdc_mDisableConversion XDsAdc_DisableConversion +#endif + +#ifndef XDsAdc_mGetFifoOccyReg +#define XDsAdc_mGetFifoOccyReg XDsAdc_GetFifoOccyReg +#endif + +/*********************************************************************/ +/** + * Macros for Driver XDsDac + * + *********************************************************************/ +#ifndef XDsDac_mWriteReg +#define XDsDac_mWriteReg XDsDac_WriteReg +#endif + +#ifndef XDsDac_mReadReg +#define XDsDac_mReadReg XDsDac_ReadReg +#endif + +#ifndef XDsDac_mIsEmpty +#define XDsDac_mIsEmpty XDsDac_IsEmpty +#endif + +#ifndef XDsDac_mFifoIsFull +#define XDsDac_mFifoIsFull XDsDac_FifoIsFull +#endif + +#ifndef XDsDac_mGetVacancy +#define XDsDac_mGetVacancy XDsDac_GetVacancy +#endif + +/*********************************************************************/ +/** + * Macros for Driver XEmacLite + * + *********************************************************************/ +#ifndef XEmacLite_mReadReg +#define XEmacLite_mReadReg XEmacLite_ReadReg +#endif + +#ifndef XEmacLite_mWriteReg +#define XEmacLite_mWriteReg XEmacLite_WriteReg +#endif + +#ifndef XEmacLite_mGetTxStatus +#define XEmacLite_mGetTxStatus XEmacLite_GetTxStatus +#endif + +#ifndef XEmacLite_mSetTxStatus +#define XEmacLite_mSetTxStatus XEmacLite_SetTxStatus +#endif + +#ifndef XEmacLite_mGetRxStatus +#define XEmacLite_mGetRxStatus XEmacLite_GetRxStatus +#endif + +#ifndef XEmacLite_mSetRxStatus +#define XEmacLite_mSetRxStatus XEmacLite_SetRxStatus +#endif + +#ifndef XEmacLite_mIsTxDone +#define XEmacLite_mIsTxDone XEmacLite_IsTxDone +#endif + +#ifndef XEmacLite_mIsRxEmpty +#define XEmacLite_mIsRxEmpty XEmacLite_IsRxEmpty +#endif + +#ifndef XEmacLite_mNextTransmitAddr +#define XEmacLite_mNextTransmitAddr XEmacLite_NextTransmitAddr +#endif + +#ifndef XEmacLite_mNextReceiveAddr +#define XEmacLite_mNextReceiveAddr XEmacLite_NextReceiveAddr +#endif + +#ifndef XEmacLite_mIsMdioConfigured +#define XEmacLite_mIsMdioConfigured XEmacLite_IsMdioConfigured +#endif + +#ifndef XEmacLite_mIsLoopbackConfigured +#define XEmacLite_mIsLoopbackConfigured XEmacLite_IsLoopbackConfigured +#endif + +#ifndef XEmacLite_mGetReceiveDataLength +#define XEmacLite_mGetReceiveDataLength XEmacLite_GetReceiveDataLength +#endif + +#ifndef XEmacLite_mGetTxActive +#define XEmacLite_mGetTxActive XEmacLite_GetTxActive +#endif + +#ifndef XEmacLite_mSetTxActive +#define XEmacLite_mSetTxActive XEmacLite_SetTxActive +#endif + +/*********************************************************************/ +/** + * Macros for Driver XGpio + * + *********************************************************************/ +#ifndef XGpio_mWriteReg +#define XGpio_mWriteReg XGpio_WriteReg +#endif + +#ifndef XGpio_mReadReg +#define XGpio_mReadReg XGpio_ReadReg +#endif + +/*********************************************************************/ +/** + * Macros for Driver XHwIcap + * + *********************************************************************/ +#ifndef XHwIcap_mFifoWrite +#define XHwIcap_mFifoWrite XHwIcap_FifoWrite +#endif + +#ifndef XHwIcap_mFifoRead +#define XHwIcap_mFifoRead XHwIcap_FifoRead +#endif + +#ifndef XHwIcap_mSetSizeReg +#define XHwIcap_mSetSizeReg XHwIcap_SetSizeReg +#endif + +#ifndef XHwIcap_mGetControlReg +#define XHwIcap_mGetControlReg XHwIcap_GetControlReg +#endif + +#ifndef XHwIcap_mStartConfig +#define XHwIcap_mStartConfig XHwIcap_StartConfig +#endif + +#ifndef XHwIcap_mStartReadBack +#define XHwIcap_mStartReadBack XHwIcap_StartReadBack +#endif + +#ifndef XHwIcap_mGetStatusReg +#define XHwIcap_mGetStatusReg XHwIcap_GetStatusReg +#endif + +#ifndef XHwIcap_mIsTransferDone +#define XHwIcap_mIsTransferDone XHwIcap_IsTransferDone +#endif + +#ifndef XHwIcap_mIsDeviceBusy +#define XHwIcap_mIsDeviceBusy XHwIcap_IsDeviceBusy +#endif + +#ifndef XHwIcap_mIntrGlobalEnable +#define XHwIcap_mIntrGlobalEnable XHwIcap_IntrGlobalEnable +#endif + +#ifndef XHwIcap_mIntrGlobalDisable +#define XHwIcap_mIntrGlobalDisable XHwIcap_IntrGlobalDisable +#endif + +#ifndef XHwIcap_mIntrGetStatus +#define XHwIcap_mIntrGetStatus XHwIcap_IntrGetStatus +#endif + +#ifndef XHwIcap_mIntrDisable +#define XHwIcap_mIntrDisable XHwIcap_IntrDisable +#endif + +#ifndef XHwIcap_mIntrEnable +#define XHwIcap_mIntrEnable XHwIcap_IntrEnable +#endif + +#ifndef XHwIcap_mIntrGetEnabled +#define XHwIcap_mIntrGetEnabled XHwIcap_IntrGetEnabled +#endif + +#ifndef XHwIcap_mIntrClear +#define XHwIcap_mIntrClear XHwIcap_IntrClear +#endif + +#ifndef XHwIcap_mGetWrFifoVacancy +#define XHwIcap_mGetWrFifoVacancy XHwIcap_GetWrFifoVacancy +#endif + +#ifndef XHwIcap_mGetRdFifoOccupancy +#define XHwIcap_mGetRdFifoOccupancy XHwIcap_GetRdFifoOccupancy +#endif + +#ifndef XHwIcap_mSliceX2Col +#define XHwIcap_mSliceX2Col XHwIcap_SliceX2Col +#endif + +#ifndef XHwIcap_mSliceY2Row +#define XHwIcap_mSliceY2Row XHwIcap_SliceY2Row +#endif + +#ifndef XHwIcap_mSliceXY2Slice +#define XHwIcap_mSliceXY2Slice XHwIcap_SliceXY2Slice +#endif + +#ifndef XHwIcap_mReadReg +#define XHwIcap_mReadReg XHwIcap_ReadReg +#endif + +#ifndef XHwIcap_mWriteReg +#define XHwIcap_mWriteReg XHwIcap_WriteReg +#endif + +/*********************************************************************/ +/** + * Macros for Driver XIic + * + *********************************************************************/ +#ifndef XIic_mReadReg +#define XIic_mReadReg XIic_ReadReg +#endif + +#ifndef XIic_mWriteReg +#define XIic_mWriteReg XIic_WriteReg +#endif + +#ifndef XIic_mEnterCriticalRegion +#define XIic_mEnterCriticalRegion XIic_IntrGlobalDisable +#endif + +#ifndef XIic_mExitCriticalRegion +#define XIic_mExitCriticalRegion XIic_IntrGlobalEnable +#endif + +#ifndef XIIC_GINTR_DISABLE +#define XIIC_GINTR_DISABLE XIic_IntrGlobalDisable +#endif + +#ifndef XIIC_GINTR_ENABLE +#define XIIC_GINTR_ENABLE XIic_IntrGlobalEnable +#endif + +#ifndef XIIC_IS_GINTR_ENABLED +#define XIIC_IS_GINTR_ENABLED XIic_IsIntrGlobalEnabled +#endif + +#ifndef XIIC_WRITE_IISR +#define XIIC_WRITE_IISR XIic_WriteIisr +#endif + +#ifndef XIIC_READ_IISR +#define XIIC_READ_IISR XIic_ReadIisr +#endif + +#ifndef XIIC_WRITE_IIER +#define XIIC_WRITE_IIER XIic_WriteIier +#endif + +#ifndef XIic_mClearIisr +#define XIic_mClearIisr XIic_ClearIisr +#endif + +#ifndef XIic_mSend7BitAddress +#define XIic_mSend7BitAddress XIic_Send7BitAddress +#endif + +#ifndef XIic_mDynSend7BitAddress +#define XIic_mDynSend7BitAddress XIic_DynSend7BitAddress +#endif + +#ifndef XIic_mDynSendStartStopAddress +#define XIic_mDynSendStartStopAddress XIic_DynSendStartStopAddress +#endif + +#ifndef XIic_mDynSendStop +#define XIic_mDynSendStop XIic_DynSendStop +#endif + +#ifndef XIic_mSend10BitAddrByte1 +#define XIic_mSend10BitAddrByte1 XIic_Send10BitAddrByte1 +#endif + +#ifndef XIic_mSend10BitAddrByte2 +#define XIic_mSend10BitAddrByte2 XIic_Send10BitAddrByte2 +#endif + +#ifndef XIic_mSend7BitAddr +#define XIic_mSend7BitAddr XIic_Send7BitAddr +#endif + +#ifndef XIic_mDisableIntr +#define XIic_mDisableIntr XIic_DisableIntr +#endif + +#ifndef XIic_mEnableIntr +#define XIic_mEnableIntr XIic_EnableIntr +#endif + +#ifndef XIic_mClearIntr +#define XIic_mClearIntr XIic_ClearIntr +#endif + +#ifndef XIic_mClearEnableIntr +#define XIic_mClearEnableIntr XIic_ClearEnableIntr +#endif + +#ifndef XIic_mFlushRxFifo +#define XIic_mFlushRxFifo XIic_FlushRxFifo +#endif + +#ifndef XIic_mFlushTxFifo +#define XIic_mFlushTxFifo XIic_FlushTxFifo +#endif + +#ifndef XIic_mReadRecvByte +#define XIic_mReadRecvByte XIic_ReadRecvByte +#endif + +#ifndef XIic_mWriteSendByte +#define XIic_mWriteSendByte XIic_WriteSendByte +#endif + +#ifndef XIic_mSetControlRegister +#define XIic_mSetControlRegister XIic_SetControlRegister +#endif + +/*********************************************************************/ +/** + * Macros for Driver XIntc + * + *********************************************************************/ +#ifndef XIntc_mMasterEnable +#define XIntc_mMasterEnable XIntc_MasterEnable +#endif + +#ifndef XIntc_mMasterDisable +#define XIntc_mMasterDisable XIntc_MasterDisable +#endif + +#ifndef XIntc_mEnableIntr +#define XIntc_mEnableIntr XIntc_EnableIntr +#endif + +#ifndef XIntc_mDisableIntr +#define XIntc_mDisableIntr XIntc_DisableIntr +#endif + +#ifndef XIntc_mAckIntr +#define XIntc_mAckIntr XIntc_AckIntr +#endif + +#ifndef XIntc_mGetIntrStatus +#define XIntc_mGetIntrStatus XIntc_GetIntrStatus +#endif + +/*********************************************************************/ +/** + * Macros for Driver XLlDma + * + *********************************************************************/ +#ifndef XLlDma_mBdRead +#define XLlDma_mBdRead XLlDma_BdRead +#endif + +#ifndef XLlDma_mBdWrite +#define XLlDma_mBdWrite XLlDma_BdWrite +#endif + +#ifndef XLlDma_mWriteReg +#define XLlDma_mWriteReg XLlDma_WriteReg +#endif + +#ifndef XLlDma_mReadReg +#define XLlDma_mReadReg XLlDma_ReadReg +#endif + +#ifndef XLlDma_mBdClear +#define XLlDma_mBdClear XLlDma_BdClear +#endif + +#ifndef XLlDma_mBdSetStsCtrl +#define XLlDma_mBdSetStsCtrl XLlDma_BdSetStsCtrl +#endif + +#ifndef XLlDma_mBdGetStsCtrl +#define XLlDma_mBdGetStsCtrl XLlDma_BdGetStsCtrl +#endif + +#ifndef XLlDma_mBdSetLength +#define XLlDma_mBdSetLength XLlDma_BdSetLength +#endif + +#ifndef XLlDma_mBdGetLength +#define XLlDma_mBdGetLength XLlDma_BdGetLength +#endif + +#ifndef XLlDma_mBdSetId +#define XLlDma_mBdSetId XLlDma_BdSetId +#endif + +#ifndef XLlDma_mBdGetId +#define XLlDma_mBdGetId XLlDma_BdGetId +#endif + +#ifndef XLlDma_mBdSetBufAddr +#define XLlDma_mBdSetBufAddr XLlDma_BdSetBufAddr +#endif + +#ifndef XLlDma_mBdGetBufAddr +#define XLlDma_mBdGetBufAddr XLlDma_BdGetBufAddr +#endif + +#ifndef XLlDma_mBdGetLength +#define XLlDma_mBdGetLength XLlDma_BdGetLength +#endif + +#ifndef XLlDma_mGetTxRing +#define XLlDma_mGetTxRing XLlDma_GetTxRing +#endif + +#ifndef XLlDma_mGetRxRing +#define XLlDma_mGetRxRing XLlDma_GetRxRing +#endif + +#ifndef XLlDma_mGetCr +#define XLlDma_mGetCr XLlDma_GetCr +#endif + +#ifndef XLlDma_mSetCr +#define XLlDma_mSetCr XLlDma_SetCr +#endif + +#ifndef XLlDma_mBdRingCntCalc +#define XLlDma_mBdRingCntCalc XLlDma_BdRingCntCalc +#endif + +#ifndef XLlDma_mBdRingMemCalc +#define XLlDma_mBdRingMemCalc XLlDma_BdRingMemCalc +#endif + +#ifndef XLlDma_mBdRingGetCnt +#define XLlDma_mBdRingGetCnt XLlDma_BdRingGetCnt +#endif + +#ifndef XLlDma_mBdRingGetFreeCnt +#define XLlDma_mBdRingGetFreeCnt XLlDma_BdRingGetFreeCnt +#endif + +#ifndef XLlDma_mBdRingSnapShotCurrBd +#define XLlDma_mBdRingSnapShotCurrBd XLlDma_BdRingSnapShotCurrBd +#endif + +#ifndef XLlDma_mBdRingNext +#define XLlDma_mBdRingNext XLlDma_BdRingNext +#endif + +#ifndef XLlDma_mBdRingPrev +#define XLlDma_mBdRingPrev XLlDma_BdRingPrev +#endif + +#ifndef XLlDma_mBdRingGetSr +#define XLlDma_mBdRingGetSr XLlDma_BdRingGetSr +#endif + +#ifndef XLlDma_mBdRingSetSr +#define XLlDma_mBdRingSetSr XLlDma_BdRingSetSr +#endif + +#ifndef XLlDma_mBdRingGetCr +#define XLlDma_mBdRingGetCr XLlDma_BdRingGetCr +#endif + +#ifndef XLlDma_mBdRingSetCr +#define XLlDma_mBdRingSetCr XLlDma_BdRingSetCr +#endif + +#ifndef XLlDma_mBdRingBusy +#define XLlDma_mBdRingBusy XLlDma_BdRingBusy +#endif + +#ifndef XLlDma_mBdRingIntEnable +#define XLlDma_mBdRingIntEnable XLlDma_BdRingIntEnable +#endif + +#ifndef XLlDma_mBdRingIntDisable +#define XLlDma_mBdRingIntDisable XLlDma_BdRingIntDisable +#endif + +#ifndef XLlDma_mBdRingIntGetEnabled +#define XLlDma_mBdRingIntGetEnabled XLlDma_BdRingIntGetEnabled +#endif + +#ifndef XLlDma_mBdRingGetIrq +#define XLlDma_mBdRingGetIrq XLlDma_BdRingGetIrq +#endif + +#ifndef XLlDma_mBdRingAckIrq +#define XLlDma_mBdRingAckIrq XLlDma_BdRingAckIrq +#endif + +/*********************************************************************/ +/** + * Macros for Driver XMbox + * + *********************************************************************/ +#ifndef XMbox_mWriteReg +#define XMbox_mWriteReg XMbox_WriteReg +#endif + +#ifndef XMbox_mReadReg +#define XMbox_mReadReg XMbox_ReadReg +#endif + +#ifndef XMbox_mWriteMBox +#define XMbox_mWriteMBox XMbox_WriteMBox +#endif + +#ifndef XMbox_mReadMBox +#define XMbox_mReadMBox XMbox_ReadMBox +#endif + +#ifndef XMbox_mFSLReadMBox +#define XMbox_mFSLReadMBox XMbox_FSLReadMBox +#endif + +#ifndef XMbox_mFSLWriteMBox +#define XMbox_mFSLWriteMBox XMbox_FSLWriteMBox +#endif + +#ifndef XMbox_mFSLIsEmpty +#define XMbox_mFSLIsEmpty XMbox_FSLIsEmpty +#endif + +#ifndef XMbox_mFSLIsFull +#define XMbox_mFSLIsFull XMbox_FSLIsFull +#endif + +#ifndef XMbox_mIsEmpty +#define XMbox_mIsEmpty XMbox_IsEmptyHw +#endif + +#ifndef XMbox_mIsFull +#define XMbox_mIsFull XMbox_IsFullHw +#endif + +/*********************************************************************/ +/** + * Macros for Driver XMpmc + * + *********************************************************************/ +#ifndef XMpmc_mReadReg +#define XMpmc_mReadReg XMpmc_ReadReg +#endif + +#ifndef XMpmc_mWriteReg +#define XMpmc_mWriteReg XMpmc_WriteReg +#endif + +/*********************************************************************/ +/** + * Macros for Driver XMutex + * + *********************************************************************/ +#ifndef XMutex_mWriteReg +#define XMutex_mWriteReg XMutex_WriteReg +#endif + +#ifndef XMutex_mReadReg +#define XMutex_mReadReg XMutex_ReadReg +#endif + +/*********************************************************************/ +/** + * Macros for Driver XPcie + * + *********************************************************************/ +#ifndef XPcie_mReadReg +#define XPcie_mReadReg XPcie_ReadReg +#endif + +#ifndef XPcie_mWriteReg +#define XPcie_mWriteReg XPcie_WriteReg +#endif + +/*********************************************************************/ +/** + * Macros for Driver XSpi + * + *********************************************************************/ +#ifndef XSpi_mIntrGlobalEnable +#define XSpi_mIntrGlobalEnable XSpi_IntrGlobalEnable +#endif + +#ifndef XSpi_mIntrGlobalDisable +#define XSpi_mIntrGlobalDisable XSpi_IntrGlobalDisable +#endif + +#ifndef XSpi_mIsIntrGlobalEnabled +#define XSpi_mIsIntrGlobalEnabled XSpi_IsIntrGlobalEnabled +#endif + +#ifndef XSpi_mIntrGetStatus +#define XSpi_mIntrGetStatus XSpi_IntrGetStatus +#endif + +#ifndef XSpi_mIntrClear +#define XSpi_mIntrClear XSpi_IntrClear +#endif + +#ifndef XSpi_mIntrEnable +#define XSpi_mIntrEnable XSpi_IntrEnable +#endif + +#ifndef XSpi_mIntrDisable +#define XSpi_mIntrDisable XSpi_IntrDisable +#endif + +#ifndef XSpi_mIntrGetEnabled +#define XSpi_mIntrGetEnabled XSpi_IntrGetEnabled +#endif + +#ifndef XSpi_mSetControlReg +#define XSpi_mSetControlReg XSpi_SetControlReg +#endif + +#ifndef XSpi_mGetControlReg +#define XSpi_mGetControlReg XSpi_GetControlReg +#endif + +#ifndef XSpi_mGetStatusReg +#define XSpi_mGetStatusReg XSpi_GetStatusReg +#endif + +#ifndef XSpi_mSetSlaveSelectReg +#define XSpi_mSetSlaveSelectReg XSpi_SetSlaveSelectReg +#endif + +#ifndef XSpi_mGetSlaveSelectReg +#define XSpi_mGetSlaveSelectReg XSpi_GetSlaveSelectReg +#endif + +#ifndef XSpi_mEnable +#define XSpi_mEnable XSpi_Enable +#endif + +#ifndef XSpi_mDisable +#define XSpi_mDisable XSpi_Disable +#endif + +/*********************************************************************/ +/** + * Macros for Driver XSysAce + * + *********************************************************************/ +#ifndef XSysAce_mGetControlReg +#define XSysAce_mGetControlReg XSysAce_GetControlReg +#endif + +#ifndef XSysAce_mSetControlReg +#define XSysAce_mSetControlReg XSysAce_SetControlReg +#endif + +#ifndef XSysAce_mOrControlReg +#define XSysAce_mOrControlReg XSysAce_OrControlReg +#endif + +#ifndef XSysAce_mAndControlReg +#define XSysAce_mAndControlReg XSysAce_AndControlReg +#endif + +#ifndef XSysAce_mGetErrorReg +#define XSysAce_mGetErrorReg XSysAce_GetErrorReg +#endif + +#ifndef XSysAce_mGetStatusReg +#define XSysAce_mGetStatusReg XSysAce_GetStatusReg +#endif + +#ifndef XSysAce_mWaitForLock +#define XSysAce_mWaitForLock XSysAce_WaitForLock +#endif + +#ifndef XSysAce_mEnableIntr +#define XSysAce_mEnableIntr XSysAce_EnableIntr +#endif + +#ifndef XSysAce_mDisableIntr +#define XSysAce_mDisableIntr XSysAce_DisableIntr +#endif + +#ifndef XSysAce_mIsReadyForCmd +#define XSysAce_mIsReadyForCmd XSysAce_IsReadyForCmd +#endif + +#ifndef XSysAce_mIsMpuLocked +#define XSysAce_mIsMpuLocked XSysAce_IsMpuLocked +#endif + +#ifndef XSysAce_mIsIntrEnabled +#define XSysAce_mIsIntrEnabled XSysAce_IsIntrEnabled +#endif + +/*********************************************************************/ +/** + * Macros for Driver XSysMon + * + *********************************************************************/ +#ifndef XSysMon_mIsEventSamplingModeSet +#define XSysMon_mIsEventSamplingModeSet XSysMon_IsEventSamplingModeSet +#endif + +#ifndef XSysMon_mIsDrpBusy +#define XSysMon_mIsDrpBusy XSysMon_IsDrpBusy +#endif + +#ifndef XSysMon_mIsDrpLocked +#define XSysMon_mIsDrpLocked XSysMon_IsDrpLocked +#endif + +#ifndef XSysMon_mRawToTemperature +#define XSysMon_mRawToTemperature XSysMon_RawToTemperature +#endif + +#ifndef XSysMon_mRawToVoltage +#define XSysMon_mRawToVoltage XSysMon_RawToVoltage +#endif + +#ifndef XSysMon_mTemperatureToRaw +#define XSysMon_mTemperatureToRaw XSysMon_TemperatureToRaw +#endif + +#ifndef XSysMon_mVoltageToRaw +#define XSysMon_mVoltageToRaw XSysMon_VoltageToRaw +#endif + +#ifndef XSysMon_mReadReg +#define XSysMon_mReadReg XSysMon_ReadReg +#endif + +#ifndef XSysMon_mWriteReg +#define XSysMon_mWriteReg XSysMon_WriteReg +#endif + +/*********************************************************************/ +/** + * Macros for Driver XTmrCtr + * + *********************************************************************/ +#ifndef XTimerCtr_mReadReg +#define XTimerCtr_mReadReg XTimerCtr_ReadReg +#endif + +#ifndef XTmrCtr_mWriteReg +#define XTmrCtr_mWriteReg XTmrCtr_WriteReg +#endif + +#ifndef XTmrCtr_mSetControlStatusReg +#define XTmrCtr_mSetControlStatusReg XTmrCtr_SetControlStatusReg +#endif + +#ifndef XTmrCtr_mGetControlStatusReg +#define XTmrCtr_mGetControlStatusReg XTmrCtr_GetControlStatusReg +#endif + +#ifndef XTmrCtr_mGetTimerCounterReg +#define XTmrCtr_mGetTimerCounterReg XTmrCtr_GetTimerCounterReg +#endif + +#ifndef XTmrCtr_mSetLoadReg +#define XTmrCtr_mSetLoadReg XTmrCtr_SetLoadReg +#endif + +#ifndef XTmrCtr_mGetLoadReg +#define XTmrCtr_mGetLoadReg XTmrCtr_GetLoadReg +#endif + +#ifndef XTmrCtr_mEnable +#define XTmrCtr_mEnable XTmrCtr_Enable +#endif + +#ifndef XTmrCtr_mDisable +#define XTmrCtr_mDisable XTmrCtr_Disable +#endif + +#ifndef XTmrCtr_mEnableIntr +#define XTmrCtr_mEnableIntr XTmrCtr_EnableIntr +#endif + +#ifndef XTmrCtr_mDisableIntr +#define XTmrCtr_mDisableIntr XTmrCtr_DisableIntr +#endif + +#ifndef XTmrCtr_mLoadTimerCounterReg +#define XTmrCtr_mLoadTimerCounterReg XTmrCtr_LoadTimerCounterReg +#endif + +#ifndef XTmrCtr_mHasEventOccurred +#define XTmrCtr_mHasEventOccurred XTmrCtr_HasEventOccurred +#endif + +/*********************************************************************/ +/** + * Macros for Driver XUartLite + * + *********************************************************************/ +#ifndef XUartLite_mUpdateStats +#define XUartLite_mUpdateStats XUartLite_UpdateStats +#endif + +#ifndef XUartLite_mWriteReg +#define XUartLite_mWriteReg XUartLite_WriteReg +#endif + +#ifndef XUartLite_mReadReg +#define XUartLite_mReadReg XUartLite_ReadReg +#endif + +#ifndef XUartLite_mClearStats +#define XUartLite_mClearStats XUartLite_ClearStats +#endif + +#ifndef XUartLite_mSetControlReg +#define XUartLite_mSetControlReg XUartLite_SetControlReg +#endif + +#ifndef XUartLite_mGetStatusReg +#define XUartLite_mGetStatusReg XUartLite_GetStatusReg +#endif + +#ifndef XUartLite_mIsReceiveEmpty +#define XUartLite_mIsReceiveEmpty XUartLite_IsReceiveEmpty +#endif + +#ifndef XUartLite_mIsTransmitFull +#define XUartLite_mIsTransmitFull XUartLite_IsTransmitFull +#endif + +#ifndef XUartLite_mIsIntrEnabled +#define XUartLite_mIsIntrEnabled XUartLite_IsIntrEnabled +#endif + +#ifndef XUartLite_mEnableIntr +#define XUartLite_mEnableIntr XUartLite_EnableIntr +#endif + +#ifndef XUartLite_mDisableIntr +#define XUartLite_mDisableIntr XUartLite_DisableIntr +#endif + +/*********************************************************************/ +/** + * Macros for Driver XUartNs550 + * + *********************************************************************/ +#ifndef XUartNs550_mUpdateStats +#define XUartNs550_mUpdateStats XUartNs550_UpdateStats +#endif + +#ifndef XUartNs550_mReadReg +#define XUartNs550_mReadReg XUartNs550_ReadReg +#endif + +#ifndef XUartNs550_mWriteReg +#define XUartNs550_mWriteReg XUartNs550_WriteReg +#endif + +#ifndef XUartNs550_mClearStats +#define XUartNs550_mClearStats XUartNs550_ClearStats +#endif + +#ifndef XUartNs550_mGetLineStatusReg +#define XUartNs550_mGetLineStatusReg XUartNs550_GetLineStatusReg +#endif + +#ifndef XUartNs550_mGetLineControlReg +#define XUartNs550_mGetLineControlReg XUartNs550_GetLineControlReg +#endif + +#ifndef XUartNs550_mSetLineControlReg +#define XUartNs550_mSetLineControlReg XUartNs550_SetLineControlReg +#endif + +#ifndef XUartNs550_mEnableIntr +#define XUartNs550_mEnableIntr XUartNs550_EnableIntr +#endif + +#ifndef XUartNs550_mDisableIntr +#define XUartNs550_mDisableIntr XUartNs550_DisableIntr +#endif + +#ifndef XUartNs550_mIsReceiveData +#define XUartNs550_mIsReceiveData XUartNs550_IsReceiveData +#endif + +#ifndef XUartNs550_mIsTransmitEmpty +#define XUartNs550_mIsTransmitEmpty XUartNs550_IsTransmitEmpty +#endif + +/*********************************************************************/ +/** + * Macros for Driver XUsb + * + *********************************************************************/ +#ifndef XUsb_mReadReg +#define XUsb_mReadReg XUsb_ReadReg +#endif + +#ifndef XUsb_mWriteReg +#define XUsb_mWriteReg XUsb_WriteReg +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_mem.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_mem.c new file mode 100644 index 0000000..e089bb5 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_mem.c @@ -0,0 +1,85 @@ +/******************************************************************************/ +/** +* Copyright (C) 2015 - 2016 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* @file xil_mem.c +* +* This file contains xil mem copy function to use in case of word aligned +* data copies. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 6.1   nsk      11/07/16 First release.
+*
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ + +#include "xil_types.h" + +/***************** Inline Functions Definitions ********************/ +/*****************************************************************************/ +/** +* @brief This function copies memory from once location to other. +* +* @param dst: pointer pointing to destination memory +* +* @param src: pointer pointing to source memory +* +* @param cnt: 32 bit length of bytes to be copied +* +*****************************************************************************/ +void Xil_MemCpy(void* dst, const void* src, u32 cnt) +{ + char *d = (char*)(void *)dst; + const char *s = src; + + while (cnt >= sizeof (int)) { + *(int*)d = *(int*)s; + d += sizeof (int); + s += sizeof (int); + cnt -= sizeof (int); + } + while (cnt >= sizeof (u16)) { + *(u16*)d = *(u16*)s; + d += sizeof (u16); + s += sizeof (u16); + cnt -= sizeof (u16); + } + while ((cnt) > 0U){ + *d = *s; + d += 1U; + s += 1U; + cnt -= 1U; + } +} diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_mem.h b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_mem.h new file mode 100644 index 0000000..9aae942 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_mem.h @@ -0,0 +1,68 @@ +/******************************************************************************/ +/** +* Copyright (C) 2015 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* @file xil_mem.h +* +* @addtogroup common_mem_operation_api Customized APIs for Memory Operations +* +* The xil_mem.h file contains prototype for functions related +* to memory operations. These APIs are applicable for all processors supported +* by Xilinx. +* +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 6.1   nsk      11/07/16 First release.
+* 7.0   mus      01/07/19 Add cpp extern macro
+*
+* 
+* +*****************************************************************************/ +#ifndef XIL_MEM_H /* prevent circular inclusions */ +#define XIL_MEM_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/************************** Function Prototypes *****************************/ + +void Xil_MemCpy(void* dst, const void* src, u32 cnt); + +#ifdef __cplusplus +} +#endif + +#endif /* XIL_MEM_H */ +/** +* @} End of "addtogroup common_mem_operation_api". +*/ \ No newline at end of file diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_misc_psreset_api.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_misc_psreset_api.c new file mode 100644 index 0000000..77d6fc1 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_misc_psreset_api.c @@ -0,0 +1,520 @@ +/****************************************************************************** +* +* Copyright (C) 2013 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_misc_reset.c +* +* This file contains the implementation of the reset sequence for various +* zynq ps devices like DDR,OCM,Slcr,Ethernet,Usb.. controllers. The reset +* sequence provided to the interfaces is based on the provision in +* slcr reset functional blcok. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date   Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00b kpc   03/07/13 First release
+* 5.4	pkp	  09/11/15 Change the description for XOcm_Remap function
+* 
+* +******************************************************************************/ + + +/***************************** Include Files *********************************/ +#include "xil_misc_psreset_api.h" + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + + +/*****************************************************************************/ +/** +* This function contains the implementation for ddr reset. +* +* @param N/A. +* +* @return N/A. +* +* @note None. +* +******************************************************************************/ +void XDdr_ResetHw(void) +{ + u32 RegVal; + + /* Unlock the slcr register access lock */ + Xil_Out32(XSLCR_UNLOCK_ADDR, XSLCR_UNLOCK_CODE); + /* Assert and deassert the ddr softreset bit */ + RegVal = Xil_In32(XDDRC_CTRL_BASEADDR); + RegVal &= (u32)(~XDDRPS_CTRL_RESET_MASK); + Xil_Out32(XDDRC_CTRL_BASEADDR,RegVal); + RegVal |= ((u32)XDDRPS_CTRL_RESET_MASK); + Xil_Out32(XDDRC_CTRL_BASEADDR,RegVal); + +} + +/*****************************************************************************/ +/** +* This function contains the implementation for remapping the ocm memory region +* to postbootrom state. +* +* @param N/A. +* +* @return N/A. +* +* @note None. +* +******************************************************************************/ +void XOcm_Remap(void) +{ + u32 RegVal; + + /* Unlock the slcr register access lock */ + Xil_Out32(XSLCR_UNLOCK_ADDR, XSLCR_UNLOCK_CODE); + /* Map the ocm region to postbootrom state */ + RegVal = Xil_In32(XSLCR_OCM_CFG_ADDR); + RegVal = (RegVal & (u32)(~XSLCR_OCM_CFG_HIADDR_MASK)) | (u32)XSLCR_OCM_CFG_RESETVAL; + Xil_Out32(XSLCR_OCM_CFG_ADDR, RegVal); +} + +/*****************************************************************************/ +/** +* This function contains the implementation for SMC reset sequence +* +* @param BaseAddress of the interface +* +* @return N/A. +* +* @note None. +* +******************************************************************************/ +void XSmc_ResetHw(u32 BaseAddress) +{ + u32 RegVal; + + /* Clear the interuupts */ + RegVal = Xil_In32(BaseAddress + XSMC_MEMC_CLR_CONFIG_OFFSET); + RegVal = RegVal | (u32)XSMC_MEMC_CLR_CONFIG_MASK; + Xil_Out32(BaseAddress + XSMC_MEMC_CLR_CONFIG_OFFSET, RegVal); + /* Clear the idle counter registers */ + Xil_Out32(BaseAddress + XSMC_REFRESH_PERIOD_0_OFFSET, 0x0U); + Xil_Out32(BaseAddress + XSMC_REFRESH_PERIOD_1_OFFSET, 0x0U); + /* Update the ecc registers with reset values */ + Xil_Out32(BaseAddress + XSMC_ECC_MEMCFG1_OFFSET, + XSMC_ECC_MEMCFG1_RESET_VAL); + Xil_Out32(BaseAddress + XSMC_ECC_MEMCMD1_OFFSET, + XSMC_ECC_MEMCMD1_RESET_VAL); + Xil_Out32(BaseAddress + XSMC_ECC_MEMCMD2_OFFSET, + XSMC_ECC_MEMCMD2_RESET_VAL); + +} + +/*****************************************************************************/ +/** +* This function contains the implementation for updating the slcr mio registers +* with reset values +* @param N/A. +* +* @return N/A. +* +* @note None. +* +******************************************************************************/ +void XSlcr_MioWriteResetValues(void) +{ + u32 i; + + /* Unlock the slcr register access lock */ + Xil_Out32(XSLCR_UNLOCK_ADDR, XSLCR_UNLOCK_CODE); + /* Update all the MIO registers with reset values */ + for (i=0U; i<=1U;i++) + { + Xil_Out32((XSLCR_MIO_PIN_00_ADDR + (i * 4U)), + XSLCR_MIO_PIN_00_RESET_VAL); + } + for (; i<=8U;i++) + { + Xil_Out32((XSLCR_MIO_PIN_00_ADDR + (i * 4U)), + XSLCR_MIO_PIN_02_RESET_VAL); + } + for (; i<=53U ;i++) + { + Xil_Out32((XSLCR_MIO_PIN_00_ADDR + (i * 4U)), + XSLCR_MIO_PIN_00_RESET_VAL); + } + + +} + +/*****************************************************************************/ +/** +* This function contains the implementation for updating the slcr pll registers +* with reset values +* @param N/A. +* +* @return N/A. +* +* @note None. +* +******************************************************************************/ +void XSlcr_PllWriteResetValues(void) +{ + + /* Unlock the slcr register access lock */ + Xil_Out32(XSLCR_UNLOCK_ADDR, XSLCR_UNLOCK_CODE); + + /* update the pll control registers with reset values */ + Xil_Out32(XSLCR_IO_PLL_CTRL_ADDR, XSLCR_IO_PLL_CTRL_RESET_VAL); + Xil_Out32(XSLCR_ARM_PLL_CTRL_ADDR, XSLCR_ARM_PLL_CTRL_RESET_VAL); + Xil_Out32(XSLCR_DDR_PLL_CTRL_ADDR, XSLCR_DDR_PLL_CTRL_RESET_VAL); + /* update the pll config registers with reset values */ + Xil_Out32(XSLCR_IO_PLL_CFG_ADDR, XSLCR_IO_PLL_CFG_RESET_VAL); + Xil_Out32(XSLCR_ARM_PLL_CFG_ADDR, XSLCR_ARM_PLL_CFG_RESET_VAL); + Xil_Out32(XSLCR_DDR_PLL_CFG_ADDR, XSLCR_DDR_PLL_CFG_RESET_VAL); + /* update the clock control registers with reset values */ + Xil_Out32(XSLCR_ARM_CLK_CTRL_ADDR, XSLCR_ARM_CLK_CTRL_RESET_VAL); + Xil_Out32(XSLCR_DDR_CLK_CTRL_ADDR, XSLCR_DDR_CLK_CTRL_RESET_VAL); +} + +/*****************************************************************************/ +/** +* This function contains the implementation for disabling the level shifters +* +* @param N/A. +* +* @return N/A. +* +* @note None. +* +******************************************************************************/ +void XSlcr_DisableLevelShifters(void) +{ + u32 RegVal; + /* Unlock the slcr register access lock */ + Xil_Out32(XSLCR_UNLOCK_ADDR, XSLCR_UNLOCK_CODE); + /* Disable the level shifters */ + RegVal = Xil_In32(XSLCR_LVL_SHFTR_EN_ADDR); + RegVal = RegVal & (u32)(~XSLCR_LVL_SHFTR_EN_MASK); + Xil_Out32(XSLCR_LVL_SHFTR_EN_ADDR, RegVal); + +} +/*****************************************************************************/ +/** +* This function contains the implementation for OCM software reset from the +* slcr +* +* @param N/A. +* +* @return N/A. +* +* @note None. +* +******************************************************************************/ +void XSlcr_OcmReset(void) +{ + u32 RegVal; + /* Unlock the slcr register access lock */ + Xil_Out32(XSLCR_UNLOCK_ADDR, XSLCR_UNLOCK_CODE); + /* Assert the reset */ + RegVal = Xil_In32(XSLCR_OCM_RST_CTRL_ADDR); + RegVal = RegVal | ((u32)XSLCR_OCM_RST_CTRL_VAL); + Xil_Out32(XSLCR_OCM_RST_CTRL_ADDR, RegVal); + /* Release the reset */ + RegVal = Xil_In32(XSLCR_OCM_RST_CTRL_ADDR); + RegVal = RegVal & (u32)(~XSLCR_OCM_RST_CTRL_VAL); + Xil_Out32(XSLCR_OCM_RST_CTRL_ADDR, RegVal); +} + +/*****************************************************************************/ +/** +* This function contains the implementation for Ethernet software reset from +* the slcr +* @param N/A. +* +* @return N/A. +* +* @note None. +* +******************************************************************************/ +void XSlcr_EmacPsReset(void) +{ + u32 RegVal; + /* Unlock the slcr register access lock */ + Xil_Out32(XSLCR_UNLOCK_ADDR, XSLCR_UNLOCK_CODE); + /* Assert the reset */ + RegVal = Xil_In32(XSLCR_GEM_RST_CTRL_ADDR); + RegVal = RegVal | ((u32)XSLCR_GEM_RST_CTRL_VAL); + Xil_Out32(XSLCR_GEM_RST_CTRL_ADDR, RegVal); + /* Release the reset */ + RegVal = Xil_In32(XSLCR_GEM_RST_CTRL_ADDR); + RegVal = RegVal & (u32)(~XSLCR_GEM_RST_CTRL_VAL); + Xil_Out32(XSLCR_GEM_RST_CTRL_ADDR, RegVal); +} + +/*****************************************************************************/ +/** +* This function contains the implementation for USB software reset from the +* slcr +* +* @param N/A. +* +* @return N/A. +* +* @note None. +* +******************************************************************************/ +void XSlcr_UsbPsReset(void) +{ + u32 RegVal; + /* Unlock the slcr register access lock */ + Xil_Out32(XSLCR_UNLOCK_ADDR, XSLCR_UNLOCK_CODE); + /* Assert the reset */ + RegVal = Xil_In32(XSLCR_USB_RST_CTRL_ADDR); + RegVal = RegVal | ((u32)XSLCR_USB_RST_CTRL_VAL); + Xil_Out32(XSLCR_USB_RST_CTRL_ADDR, RegVal); + /* Release the reset */ + RegVal = Xil_In32(XSLCR_USB_RST_CTRL_ADDR); + RegVal = RegVal & (u32)(~XSLCR_USB_RST_CTRL_VAL); + Xil_Out32(XSLCR_USB_RST_CTRL_ADDR, RegVal); +} +/*****************************************************************************/ +/** +* This function contains the implementation for QSPI software reset from the +* slcr +* +* @param N/A. +* +* @return N/A. +* +* @note None. +* +******************************************************************************/ +void XSlcr_QspiPsReset(void) +{ + u32 RegVal; + /* Unlock the slcr register access lock */ + Xil_Out32(XSLCR_UNLOCK_ADDR, XSLCR_UNLOCK_CODE); + /* Assert the reset */ + RegVal = Xil_In32(XSLCR_LQSPI_RST_CTRL_ADDR); + RegVal = RegVal | ((u32)XSLCR_QSPI_RST_CTRL_VAL); + Xil_Out32(XSLCR_LQSPI_RST_CTRL_ADDR, RegVal); + /* Release the reset */ + RegVal = Xil_In32(XSLCR_LQSPI_RST_CTRL_ADDR); + RegVal = RegVal & (u32)(~XSLCR_QSPI_RST_CTRL_VAL); + Xil_Out32(XSLCR_LQSPI_RST_CTRL_ADDR, RegVal); +} +/*****************************************************************************/ +/** +* This function contains the implementation for SPI software reset from the +* slcr +* +* @param N/A. +* +* @return N/A. +* +* @note None. +* +******************************************************************************/ +void XSlcr_SpiPsReset(void) +{ + u32 RegVal; + /* Unlock the slcr register access lock */ + Xil_Out32(XSLCR_UNLOCK_ADDR, XSLCR_UNLOCK_CODE); + /* Assert the reset */ + RegVal = Xil_In32(XSLCR_SPI_RST_CTRL_ADDR); + RegVal = RegVal | ((u32)XSLCR_SPI_RST_CTRL_VAL); + Xil_Out32(XSLCR_SPI_RST_CTRL_ADDR, RegVal); + /* Release the reset */ + RegVal = Xil_In32(XSLCR_SPI_RST_CTRL_ADDR); + RegVal = RegVal & (u32)(~XSLCR_SPI_RST_CTRL_VAL); + Xil_Out32(XSLCR_SPI_RST_CTRL_ADDR, RegVal); +} +/*****************************************************************************/ +/** +* This function contains the implementation for i2c software reset from the slcr +* +* @param N/A. +* +* @return N/A. +* +* @note None. +* +******************************************************************************/ +void XSlcr_I2cPsReset(void) +{ + u32 RegVal; + /* Unlock the slcr register access lock */ + Xil_Out32(XSLCR_UNLOCK_ADDR, XSLCR_UNLOCK_CODE); + /* Assert the reset */ + RegVal = Xil_In32(XSLCR_I2C_RST_CTRL_ADDR); + RegVal = RegVal | ((u32)XSLCR_I2C_RST_CTRL_VAL); + Xil_Out32(XSLCR_I2C_RST_CTRL_ADDR, RegVal); + /* Release the reset */ + RegVal = Xil_In32(XSLCR_I2C_RST_CTRL_ADDR); + RegVal = RegVal & (u32)(~XSLCR_I2C_RST_CTRL_VAL); + Xil_Out32(XSLCR_I2C_RST_CTRL_ADDR, RegVal); +} +/*****************************************************************************/ +/** +* This function contains the implementation for UART software reset from the +* slcr +* +* @param N/A. +* +* @return N/A. +* +* @note None. +* +******************************************************************************/ +void XSlcr_UartPsReset(void) +{ + u32 RegVal; + /* Unlock the slcr register access lock */ + Xil_Out32(XSLCR_UNLOCK_ADDR, XSLCR_UNLOCK_CODE); + /* Assert the reset */ + RegVal = Xil_In32(XSLCR_UART_RST_CTRL_ADDR); + RegVal = RegVal | ((u32)XSLCR_UART_RST_CTRL_VAL); + Xil_Out32(XSLCR_UART_RST_CTRL_ADDR, RegVal); + /* Release the reset */ + RegVal = Xil_In32(XSLCR_UART_RST_CTRL_ADDR); + RegVal = RegVal & (u32)(~XSLCR_UART_RST_CTRL_VAL); + Xil_Out32(XSLCR_UART_RST_CTRL_ADDR, RegVal); +} +/*****************************************************************************/ +/** +* This function contains the implementation for CAN software reset from slcr +* registers +* +* @param N/A. +* +* @return N/A. +* +* @note None. +* +******************************************************************************/ +void XSlcr_CanPsReset(void) +{ + u32 RegVal; + /* Unlock the slcr register access lock */ + Xil_Out32(XSLCR_UNLOCK_ADDR, XSLCR_UNLOCK_CODE); + /* Assert the reset */ + RegVal = Xil_In32(XSLCR_CAN_RST_CTRL_ADDR); + RegVal = RegVal | ((u32)XSLCR_CAN_RST_CTRL_VAL); + Xil_Out32(XSLCR_CAN_RST_CTRL_ADDR, RegVal); + /* Release the reset */ + RegVal = Xil_In32(XSLCR_CAN_RST_CTRL_ADDR); + RegVal = RegVal & (u32)(~XSLCR_CAN_RST_CTRL_VAL); + Xil_Out32(XSLCR_CAN_RST_CTRL_ADDR, RegVal); +} +/*****************************************************************************/ +/** +* This function contains the implementation for SMC software reset from the slcr +* +* @param N/A. +* +* @return N/A. +* +* @note None. +* +******************************************************************************/ +void XSlcr_SmcPsReset(void) +{ + u32 RegVal; + /* Unlock the slcr register access lock */ + Xil_Out32(XSLCR_UNLOCK_ADDR, XSLCR_UNLOCK_CODE); + /* Assert the reset */ + RegVal = Xil_In32(XSLCR_SMC_RST_CTRL_ADDR); + RegVal = RegVal | ((u32)XSLCR_SMC_RST_CTRL_VAL); + Xil_Out32(XSLCR_SMC_RST_CTRL_ADDR, RegVal); + /* Release the reset */ + RegVal = Xil_In32(XSLCR_SMC_RST_CTRL_ADDR); + RegVal = RegVal & (u32)(~XSLCR_SMC_RST_CTRL_VAL); + Xil_Out32(XSLCR_SMC_RST_CTRL_ADDR, RegVal); +} +/*****************************************************************************/ +/** +* This function contains the implementation for DMA controller software reset +* from the slcr +* +* @param N/A. +* +* @return N/A. +* +* @note None. +* +******************************************************************************/ +void XSlcr_DmaPsReset(void) +{ + u32 RegVal; + /* Unlock the slcr register access lock */ + Xil_Out32(XSLCR_UNLOCK_ADDR, XSLCR_UNLOCK_CODE); + /* Assert the reset */ + RegVal = Xil_In32(XSLCR_DMAC_RST_CTRL_ADDR); + RegVal = RegVal | ((u32)XSLCR_DMAC_RST_CTRL_VAL); + Xil_Out32(XSLCR_DMAC_RST_CTRL_ADDR, RegVal); + /* Release the reset */ + RegVal = Xil_In32(XSLCR_DMAC_RST_CTRL_ADDR); + RegVal = RegVal & (u32)(~XSLCR_DMAC_RST_CTRL_VAL); + Xil_Out32(XSLCR_DMAC_RST_CTRL_ADDR, RegVal); +} +/*****************************************************************************/ +/** +* This function contains the implementation for Gpio AMBA software reset from +* the slcr +* +* @param N/A. +* +* @return N/A. +* +* @note None. +* +******************************************************************************/ +void XSlcr_GpioPsReset(void) +{ + u32 RegVal; + /* Unlock the slcr register access lock */ + Xil_Out32(XSLCR_UNLOCK_ADDR, XSLCR_UNLOCK_CODE); + /* Assert the reset */ + RegVal = Xil_In32(XSLCR_GPIO_RST_CTRL_ADDR); + RegVal = RegVal | ((u32)XSLCR_GPIO_RST_CTRL_VAL); + Xil_Out32(XSLCR_GPIO_RST_CTRL_ADDR, RegVal); + /* Release the reset */ + RegVal = Xil_In32(XSLCR_GPIO_RST_CTRL_ADDR); + RegVal = RegVal & (u32)(~XSLCR_GPIO_RST_CTRL_VAL); + Xil_Out32(XSLCR_GPIO_RST_CTRL_ADDR, RegVal); +} diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_misc_psreset_api.h b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_misc_psreset_api.h new file mode 100644 index 0000000..3a26175 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_misc_psreset_api.h @@ -0,0 +1,273 @@ +/****************************************************************************** +* +* Copyright (C) 2013 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file xil_misc_psreset_api.h +* +* This file contains the various register defintions and function prototypes for +* implementing the reset functionality of zynq ps devices +* +* MODIFICATION HISTORY: +* +* Ver Who Date Changes +* ----- ---- -------- ------------------------------------------------------- +* 1.00b kpc 03/07/13 First release. +* +* +******************************************************************************/ + +#ifndef XIL_MISC_RESET_H /* prevent circular inclusions */ +#define XIL_MISC_RESET_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + + +/***************************** Include Files *********************************/ +#include "xil_types.h" +#include "xil_io.h" + +/************************** Constant Definitions *****************************/ +#define XDDRC_CTRL_BASEADDR 0xF8006000U +#define XSLCR_BASEADDR 0xF8000000U +/**< OCM configuration register */ +#define XSLCR_OCM_CFG_ADDR (XSLCR_BASEADDR + 0x00000910U) +/**< SLCR unlock register */ +#define XSLCR_UNLOCK_ADDR (XSLCR_BASEADDR + 0x00000008U) +/**< SLCR GEM0 rx clock control register */ +#define XSLCR_GEM0_RCLK_CTRL_ADDR (XSLCR_BASEADDR + 0x00000138U) +/**< SLCR GEM1 rx clock control register */ +#define XSLCR_GEM1_RCLK_CTRL_ADDR (XSLCR_BASEADDR + 0x0000013CU) +/**< SLCR GEM0 clock control register */ +#define XSLCR_GEM0_CLK_CTRL_ADDR (XSLCR_BASEADDR + 0x00000140U) +/**< SLCR GEM1 clock control register */ +#define XSLCR_GEM1_CLK_CTRL_ADDR (XSLCR_BASEADDR + 0x00000144U) +/**< SLCR SMC clock control register */ +#define XSLCR_SMC_CLK_CTRL_ADDR (XSLCR_BASEADDR + 0x00000148U) +/**< SLCR GEM reset control register */ +#define XSLCR_GEM_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000214U) +/**< SLCR USB0 clock control register */ +#define XSLCR_USB0_CLK_CTRL_ADDR (XSLCR_BASEADDR + 0x00000130U) +/**< SLCR USB1 clock control register */ +#define XSLCR_USB1_CLK_CTRL_ADDR (XSLCR_BASEADDR + 0x00000134U) +/**< SLCR USB1 reset control register */ +#define XSLCR_USB_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000210U) +/**< SLCR SMC reset control register */ +#define XSLCR_SMC_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000234U) +/**< SLCR Level shifter enable register */ +#define XSLCR_LVL_SHFTR_EN_ADDR (XSLCR_BASEADDR + 0x00000900U) +/**< SLCR ARM pll control register */ +#define XSLCR_ARM_PLL_CTRL_ADDR (XSLCR_BASEADDR + 0x00000100U) +/**< SLCR DDR pll control register */ +#define XSLCR_DDR_PLL_CTRL_ADDR (XSLCR_BASEADDR + 0x00000104U) +/**< SLCR IO pll control register */ +#define XSLCR_IO_PLL_CTRL_ADDR (XSLCR_BASEADDR + 0x00000108U) +/**< SLCR ARM pll configuration register */ +#define XSLCR_ARM_PLL_CFG_ADDR (XSLCR_BASEADDR + 0x00000110U) +/**< SLCR DDR pll configuration register */ +#define XSLCR_DDR_PLL_CFG_ADDR (XSLCR_BASEADDR + 0x00000114U) +/**< SLCR IO pll configuration register */ +#define XSLCR_IO_PLL_CFG_ADDR (XSLCR_BASEADDR + 0x00000118U) +/**< SLCR ARM clock control register */ +#define XSLCR_ARM_CLK_CTRL_ADDR (XSLCR_BASEADDR + 0x00000120U) +/**< SLCR DDR clock control register */ +#define XSLCR_DDR_CLK_CTRL_ADDR (XSLCR_BASEADDR + 0x00000124U) +/**< SLCR MIO pin address register */ +#define XSLCR_MIO_PIN_00_ADDR (XSLCR_BASEADDR + 0x00000700U) +/**< SLCR DMAC reset control address register */ +#define XSLCR_DMAC_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x0000020CU) +/**< SLCR USB reset control address register */ +/*#define XSLCR_USB_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000210U)*/ +/**< SLCR GEM reset control address register */ +/*#define XSLCR_GEM_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000214U)*/ +/**< SLCR SDIO reset control address register */ +#define XSLCR_SDIO_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000218U) +/**< SLCR SPI reset control address register */ +#define XSLCR_SPI_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x0000021CU) +/**< SLCR CAN reset control address register */ +#define XSLCR_CAN_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000220U) +/**< SLCR I2C reset control address register */ +#define XSLCR_I2C_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000224U) +/**< SLCR UART reset control address register */ +#define XSLCR_UART_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000228U) +/**< SLCR GPIO reset control address register */ +#define XSLCR_GPIO_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x0000022CU) +/**< SLCR LQSPI reset control address register */ +#define XSLCR_LQSPI_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000230U) +/**< SLCR SMC reset control address register */ +/*#define XSLCR_SMC_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000234U)*/ +/**< SLCR OCM reset control address register */ +#define XSLCR_OCM_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000238U) + +/**< SMC mem controller clear config register */ +#define XSMC_MEMC_CLR_CONFIG_OFFSET 0x0000000CU +/**< SMC idlecount configuration register */ +#define XSMC_REFRESH_PERIOD_0_OFFSET 0x00000020U +#define XSMC_REFRESH_PERIOD_1_OFFSET 0x00000024U +/**< SMC ECC configuration register */ +#define XSMC_ECC_MEMCFG1_OFFSET 0x00000404U +/**< SMC ECC command 1 register */ +#define XSMC_ECC_MEMCMD1_OFFSET 0x00000404U +/**< SMC ECC command 2 register */ +#define XSMC_ECC_MEMCMD2_OFFSET 0x00000404U + +/**< SLCR unlock code */ +#define XSLCR_UNLOCK_CODE 0x0000DF0DU + +/**< SMC mem clear configuration mask */ +#define XSMC_MEMC_CLR_CONFIG_MASK 0x000005FU +/**< SMC ECC memconfig 1 reset value */ +#define XSMC_ECC_MEMCFG1_RESET_VAL 0x0000043U +/**< SMC ECC memcommand 1 reset value */ +#define XSMC_ECC_MEMCMD1_RESET_VAL 0x01300080U +/**< SMC ECC memcommand 2 reset value */ +#define XSMC_ECC_MEMCMD2_RESET_VAL 0x01E00585U + +/**< DDR controller reset bit mask */ +#define XDDRPS_CTRL_RESET_MASK 0x00000001U +/**< SLCR OCM configuration reset value*/ +#define XSLCR_OCM_CFG_RESETVAL 0x00000008U +/**< SLCR OCM bank selection mask*/ +#define XSLCR_OCM_CFG_HIADDR_MASK 0x0000000FU +/**< SLCR level shifter enable mask*/ +#define XSLCR_LVL_SHFTR_EN_MASK 0x0000000FU + +/**< SLCR PLL register reset values */ +#define XSLCR_ARM_PLL_CTRL_RESET_VAL 0x0001A008U +#define XSLCR_DDR_PLL_CTRL_RESET_VAL 0x0001A008U +#define XSLCR_IO_PLL_CTRL_RESET_VAL 0x0001A008U +#define XSLCR_ARM_PLL_CFG_RESET_VAL 0x00177EA0U +#define XSLCR_DDR_PLL_CFG_RESET_VAL 0x00177EA0U +#define XSLCR_IO_PLL_CFG_RESET_VAL 0x00177EA0U +#define XSLCR_ARM_CLK_CTRL_RESET_VAL 0x1F000400U +#define XSLCR_DDR_CLK_CTRL_RESET_VAL 0x18400003U + +/**< SLCR MIO register default values */ +#define XSLCR_MIO_PIN_00_RESET_VAL 0x00001601U +#define XSLCR_MIO_PIN_02_RESET_VAL 0x00000601U + +/**< SLCR Reset control registers default values */ +#define XSLCR_DMAC_RST_CTRL_VAL 0x00000001U +#define XSLCR_GEM_RST_CTRL_VAL 0x000000F3U +#define XSLCR_USB_RST_CTRL_VAL 0x00000003U +#define XSLCR_I2C_RST_CTRL_VAL 0x00000003U +#define XSLCR_SPI_RST_CTRL_VAL 0x0000000FU +#define XSLCR_UART_RST_CTRL_VAL 0x0000000FU +#define XSLCR_QSPI_RST_CTRL_VAL 0x00000003U +#define XSLCR_GPIO_RST_CTRL_VAL 0x00000001U +#define XSLCR_SMC_RST_CTRL_VAL 0x00000003U +#define XSLCR_OCM_RST_CTRL_VAL 0x00000001U +#define XSLCR_SDIO_RST_CTRL_VAL 0x00000033U +#define XSLCR_CAN_RST_CTRL_VAL 0x00000003U +/**************************** Type Definitions *******************************/ + +/* the following data type is used to hold a null terminated version string + * consisting of the following format, "X.YYX" + */ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ +/* + * Performs reset operation to the ddr interface + */ +void XDdr_ResetHw(void); +/* + * Map the ocm region to post bootrom state + */ +void XOcm_Remap(void); +/* + * Performs the smc interface reset + */ +void XSmc_ResetHw(u32 BaseAddress); +/* + * updates the MIO registers with reset values + */ +void XSlcr_MioWriteResetValues(void); +/* + * updates the PLL and clock registers with reset values + */ +void XSlcr_PllWriteResetValues(void); +/* + * Disables the level shifters + */ +void XSlcr_DisableLevelShifters(void); +/* + * provides softreset to the GPIO interface + */ +void XSlcr_GpioPsReset(void); +/* + * provides softreset to the DMA interface + */ +void XSlcr_DmaPsReset(void); +/* + * provides softreset to the SMC interface + */ +void XSlcr_SmcPsReset(void); +/* + * provides softreset to the CAN interface + */ +void XSlcr_CanPsReset(void); +/* + * provides softreset to the Uart interface + */ +void XSlcr_UartPsReset(void); +/* + * provides softreset to the I2C interface + */ +void XSlcr_I2cPsReset(void); +/* + * provides softreset to the SPI interface + */ +void XSlcr_SpiPsReset(void); +/* + * provides softreset to the QSPI interface + */ +void XSlcr_QspiPsReset(void); +/* + * provides softreset to the USB interface + */ +void XSlcr_UsbPsReset(void); +/* + * provides softreset to the GEM interface + */ +void XSlcr_EmacPsReset(void); +/* + * provides softreset to the OCM interface + */ +void XSlcr_OcmReset(void); + + +#ifdef __cplusplus +} +#endif + +#endif /* XIL_MISC_RESET_H */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_mmu.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_mmu.c new file mode 100644 index 0000000..ef5bbfe --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_mmu.c @@ -0,0 +1,227 @@ +/****************************************************************************** +* +* Copyright (C) 2012 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file xil_mmu.c +* +* This file provides APIs for enabling/disabling MMU and setting the memory +* attributes for sections, in the MMU translation table. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- ---------------------------------------------------
+* 1.00a sdm  01/12/12 Initial version
+* 3.05a asa  03/10/12 Modified the Xil_EnableMMU to invalidate the caches
+*		      before enabling back.
+* 3.05a asa  04/15/12 Modified the Xil_SetTlbAttributes routine so that
+*		      translation table and branch predictor arrays are
+*		      invalidated, D-cache flushed before the attribute
+*		      change is applied. This is done so that the user
+*		      need not call Xil_DisableMMU before calling
+*		      Xil_SetTlbAttributes.
+* 3.10a  srt 04/18/13 Implemented ARM Erratas. Please refer to file
+*		      'xil_errata.h' for errata description
+* 3.11a  asa 09/23/13 Modified Xil_SetTlbAttributes to flush the complete
+*			 D cache after the translation table update. Removed the
+*			 redundant TLB invalidation in the same API at the beginning.
+* 6.8   aru  09/06/18 Removed compilation warnings for ARMCC toolchain.
+*                     It fixes CR#1008309.
+* 
+* +* @note +* +* None. +* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xil_cache.h" +#include "xpseudo_asm.h" +#include "xil_types.h" +#include "xil_mmu.h" +#include "xil_errata.h" + +/***************** Macros (Inline Functions) Definitions *********************/ + +/**************************** Type Definitions *******************************/ + +/************************** Constant Definitions *****************************/ +#define ARM_AR_MEM_TTB_SECT_SIZE 1024*1024 +#define ARM_AR_MEM_TTB_SECT_SIZE_MASK (~(ARM_AR_MEM_TTB_SECT_SIZE-1UL)) +/************************** Variable Definitions *****************************/ + +extern u32 MMUTable; + +/************************** Function Prototypes ******************************/ + +/*****************************************************************************/ +/** +* @brief This function sets the memory attributes for a section covering 1MB +* of memory in the translation table. +* +* @param Addr: 32-bit address for which memory attributes need to be set. +* @param attrib: Attribute for the given memory region. xil_mmu.h contains +* definitions of commonly used memory attributes which can be +* utilized for this function. +* +* +* @return None. +* +* @note The MMU or D-cache does not need to be disabled before changing a +* translation table entry. +* +******************************************************************************/ +void Xil_SetTlbAttributes(INTPTR Addr, u32 attrib) +{ + u32 *ptr; + u32 section; + + section = Addr / 0x100000U; + ptr = &MMUTable; + ptr += section; + if(ptr != NULL) { + *ptr = (Addr & 0xFFF00000U) | attrib; + } + + Xil_DCacheFlush(); + + mtcp(XREG_CP15_INVAL_UTLB_UNLOCKED, 0U); + /* Invalidate all branch predictors */ + mtcp(XREG_CP15_INVAL_BRANCH_ARRAY, 0U); + + dsb(); /* ensure completion of the BP and TLB invalidation */ + isb(); /* synchronize context on this processor */ +} + +/*****************************************************************************/ +/** +* @brief Enable MMU for cortex A9 processor. This function invalidates the +* instruction and data caches, and then enables MMU. +* +* @param None. +* @return None. +* +******************************************************************************/ +void Xil_EnableMMU(void) +{ + u32 Reg; + Xil_DCacheInvalidate(); + Xil_ICacheInvalidate(); + +#ifdef __GNUC__ + Reg = mfcp(XREG_CP15_SYS_CONTROL); +#elif defined (__ICCARM__) + mfcp(XREG_CP15_SYS_CONTROL, Reg); +#else + { volatile register u32 Cp15Reg __asm(XREG_CP15_SYS_CONTROL); + Reg = Cp15Reg; } +#endif + Reg |= (u32)0x05U; + mtcp(XREG_CP15_SYS_CONTROL, Reg); + + dsb(); + isb(); +} + +/*****************************************************************************/ +/** +* @brief Disable MMU for Cortex A9 processors. This function invalidates +* the TLBs, Branch Predictor Array and flushed the D Caches before +* disabling the MMU. +* +* @param None. +* +* @return None. +* +* @note When the MMU is disabled, all the memory accesses are treated as +* strongly ordered. +******************************************************************************/ +void Xil_DisableMMU(void) +{ + u32 Reg; + + mtcp(XREG_CP15_INVAL_UTLB_UNLOCKED, 0U); + mtcp(XREG_CP15_INVAL_BRANCH_ARRAY, 0U); + Xil_DCacheFlush(); + +#ifdef __GNUC__ + Reg = mfcp(XREG_CP15_SYS_CONTROL); +#elif defined (__ICCARM__) + mfcp(XREG_CP15_SYS_CONTROL, Reg); +#else + { volatile register u32 Cp15Reg __asm(XREG_CP15_SYS_CONTROL); + Reg = Cp15Reg; } +#endif + Reg &= (u32)(~0x05U); +#ifdef CONFIG_ARM_ERRATA_794073 + /* Disable Branch Prediction */ + Reg &= (u32)(~0x800U); +#endif + mtcp(XREG_CP15_SYS_CONTROL, Reg); +} + +/*****************************************************************************/ +/** +* @brief Memory mapping for Cortex A9 processor. +* +* @param PhysAddr is physical address. +* @param size is size of region. +* @param flags is flags used to set translation table. +* +* @return Pointer to virtual address. +* +* @note: Previously this was implemented in libmetal. Move to embeddedsw as this +* functionality is specific to A9 processor. +* +******************************************************************************/ +void* Xil_MemMap(UINTPTR PhysAddr, size_t size, u32 flags) +{ + u32 Sectionoffset; + u32 Ttbaddr; + + if (!flags) + return (void*)PhysAddr; + + /* Ensure alignement on a section boundary */ + PhysAddr &= ARM_AR_MEM_TTB_SECT_SIZE_MASK; + + /* Loop through entire region of memory (one MMU section at a time). + Each section requires a TTB entry. */ + for (Sectionoffset = 0; Sectionoffset < size; + Sectionoffset += ARM_AR_MEM_TTB_SECT_SIZE) { + /* Calculate translation table entry for this memory section */ + Ttbaddr = (PhysAddr + Sectionoffset); + + /* Write translation table entry value to entry address */ + Xil_SetTlbAttributes(Ttbaddr, flags); + } + return (void*)PhysAddr; +} diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_mmu.h b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_mmu.h new file mode 100644 index 0000000..3b63c0b --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_mmu.h @@ -0,0 +1,106 @@ +/****************************************************************************** +* +* Copyright (C) 2012 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file xil_mmu.h +* +* @addtogroup a9_mmu_apis Cortex A9 Processor MMU Functions +* +* MMU functions equip users to enable MMU, disable MMU and modify default +* memory attributes of MMU table as per the need. +* +* @{ +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- ---------------------------------------------------
+* 1.00a sdm  01/12/12 Initial version
+* 4.2	pkp	 07/21/14 Included xil_types.h file which contains definition for
+*					  u32 which resolves issue of CR#805869
+* 5.4	pkp	 23/11/15 Added attribute definitions for Xil_SetTlbAttributes API
+* 6.8   aru  09/06/18 Removed compilation warnings for ARMCC toolchain.
+* 
+* +* +******************************************************************************/ + +#ifndef XIL_MMU_H +#define XIL_MMU_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/***************************** Include Files *********************************/ + +#include "xil_types.h" + +/***************** Macros (Inline Functions) Definitions *********************/ + +/**************************** Type Definitions *******************************/ + +/************************** Constant Definitions *****************************/ + +/* Memory type */ +#define NORM_NONCACHE 0x11DE2 /* Normal Non-cacheable */ +#define STRONG_ORDERED 0xC02 /* Strongly ordered */ +#define DEVICE_MEMORY 0xC06 /* Device memory */ +#define RESERVED 0x0 /* reserved memory */ + +/* Normal write-through cacheable shareable */ +#define NORM_WT_CACHE 0x16DEA + +/* Normal write back cacheable shareable */ +#define NORM_WB_CACHE 0x15DE6 + +/* shareability attribute */ +#define SHAREABLE (0x1 << 16) +#define NON_SHAREABLE (~(0x1 << 16)) + +/* Execution type */ +#define EXECUTE_NEVER ((0x1 << 4) | (0x1 << 0)) + +/************************** Variable Definitions *****************************/ + +/************************** Function Prototypes ******************************/ + +void Xil_SetTlbAttributes(INTPTR Addr, u32 attrib); +void Xil_EnableMMU(void); +void Xil_DisableMMU(void); +void* Xil_MemMap(UINTPTR PhysAddr, size_t size, u32 flags); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* XIL_MMU_H */ +/** +* @} End of "addtogroup a9_mmu_apis". +*/ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_printf.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_printf.c new file mode 100644 index 0000000..3113269 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_printf.c @@ -0,0 +1,443 @@ +/*---------------------------------------------------*/ +/* Modified from : */ +/* Public Domain version of printf */ +/* Rud Merriam, Compsult, Inc. Houston, Tx. */ +/* For Embedded Systems Programming, 1991 */ +/* */ +/*---------------------------------------------------*/ +#include "xil_printf.h" +#include "xil_types.h" +#include "xil_assert.h" +#include +#include +#include + +static void padding( const s32 l_flag,const struct params_s *par); +static void outs(const charptr lp, struct params_s *par); +static s32 getnum( charptr* linep); + +typedef struct params_s { + s32 len; + s32 num1; + s32 num2; + char8 pad_character; + s32 do_padding; + s32 left_flag; + s32 unsigned_flag; +} params_t; + + +/*---------------------------------------------------*/ +/* The purpose of this routine is to output data the */ +/* same as the standard printf function without the */ +/* overhead most run-time libraries involve. Usually */ +/* the printf brings in many kilobytes of code and */ +/* that is unacceptable in most embedded systems. */ +/*---------------------------------------------------*/ + + +/*---------------------------------------------------*/ +/* */ +/* This routine puts pad characters into the output */ +/* buffer. */ +/* */ +static void padding( const s32 l_flag, const struct params_s *par) +{ + s32 i; + + if ((par->do_padding != 0) && (l_flag != 0) && (par->len < par->num1)) { + i=(par->len); + for (; i<(par->num1); i++) { +#ifdef STDOUT_BASEADDRESS + outbyte( par->pad_character); +#endif + } + } +} + +/*---------------------------------------------------*/ +/* */ +/* This routine moves a string to the output buffer */ +/* as directed by the padding and positioning flags. */ +/* */ +static void outs(const charptr lp, struct params_s *par) +{ + charptr LocalPtr; + LocalPtr = lp; + /* pad on left if needed */ + if(LocalPtr != NULL) { + par->len = (s32)strlen( LocalPtr); + } + padding( !(par->left_flag), par); + + /* Move string to the buffer */ + while (((*LocalPtr) != (char8)0) && ((par->num2) != 0)) { + (par->num2)--; +#ifdef STDOUT_BASEADDRESS + outbyte(*LocalPtr); +#endif + LocalPtr += 1; +} + + /* Pad on right if needed */ + /* CR 439175 - elided next stmt. Seemed bogus. */ + /* par->len = strlen( lp) */ + padding( par->left_flag, par); +} + +/*---------------------------------------------------*/ +/* */ +/* This routine moves a number to the output buffer */ +/* as directed by the padding and positioning flags. */ +/* */ + +static void outnum( const s32 n, const s32 base, struct params_s *par) +{ + s32 negative; + s32 i; + char8 outbuf[32]; + const char8 digits[] = "0123456789ABCDEF"; + u32 num; + for(i = 0; i<32; i++) { + outbuf[i] = '0'; + } + + /* Check if number is negative */ + if ((par->unsigned_flag == 0) && (base == 10) && (n < 0L)) { + negative = 1; + num =(-(n)); + } + else{ + num = n; + negative = 0; + } + + /* Build number (backwards) in outbuf */ + i = 0; + do { + outbuf[i] = digits[(num % base)]; + i++; + num /= base; + } while (num > 0); + + if (negative != 0) { + outbuf[i] = '-'; + i++; + } + + outbuf[i] = '\0'; + i--; + + /* Move the converted number to the buffer and */ + /* add in the padding where needed. */ + par->len = (s32)strlen(outbuf); + padding( !(par->left_flag), par); + while (&outbuf[i] >= outbuf) { +#ifdef STDOUT_BASEADDRESS + outbyte( outbuf[i] ); +#endif + i--; +} + padding( par->left_flag, par); +} +/*---------------------------------------------------*/ +/* */ +/* This routine moves a 64-bit number to the output */ +/* buffer as directed by the padding and positioning */ +/* flags. */ +/* */ +#if defined (__aarch64__) || defined (__arch64__) +static void outnum1( const s64 n, const s32 base, params_t *par) +{ + s32 negative; + s32 i; + char8 outbuf[64]; + const char8 digits[] = "0123456789ABCDEF"; + u64 num; + for(i = 0; i<64; i++) { + outbuf[i] = '0'; + } + + /* Check if number is negative */ + if ((par->unsigned_flag == 0) && (base == 10) && (n < 0L)) { + negative = 1; + num =(-(n)); + } + else{ + num = (n); + negative = 0; + } + + /* Build number (backwards) in outbuf */ + i = 0; + do { + outbuf[i] = digits[(num % base)]; + i++; + num /= base; + } while (num > 0); + + if (negative != 0) { + outbuf[i] = '-'; + i++; + } + + outbuf[i] = '\0'; + i--; + + /* Move the converted number to the buffer and */ + /* add in the padding where needed. */ + par->len = (s32)strlen(outbuf); + padding( !(par->left_flag), par); + while (&outbuf[i] >= outbuf) { + outbyte( outbuf[i] ); + i--; +} + padding( par->left_flag, par); +} +#endif +/*---------------------------------------------------*/ +/* */ +/* This routine gets a number from the format */ +/* string. */ +/* */ +static s32 getnum( charptr* linep) +{ + s32 n; + s32 ResultIsDigit = 0; + charptr cptr; + n = 0; + cptr = *linep; + if(cptr != NULL){ + ResultIsDigit = isdigit(((s32)*cptr)); + } + while (ResultIsDigit != 0) { + if(cptr != NULL){ + n = ((n*10) + (((s32)*cptr) - (s32)'0')); + cptr += 1; + if(cptr != NULL){ + ResultIsDigit = isdigit(((s32)*cptr)); + } + } + ResultIsDigit = isdigit(((s32)*cptr)); + } + *linep = ((charptr )(cptr)); + return(n); +} + +/*---------------------------------------------------*/ +/* */ +/* This routine operates just like a printf/sprintf */ +/* routine. It outputs a set of data under the */ +/* control of a formatting string. Not all of the */ +/* standard C format control are supported. The ones */ +/* provided are primarily those needed for embedded */ +/* systems work. Primarily the floating point */ +/* routines are omitted. Other formats could be */ +/* added easily by following the examples shown for */ +/* the supported formats. */ +/* */ + +/* void esp_printf( const func_ptr f_ptr, + const charptr ctrl1, ...) */ +#if defined (__aarch64__) && HYP_GUEST && EL1_NONSECURE && XEN_USE_PV_CONSOLE +void xil_printf( const char8 *ctrl1, ...){ + XPVXenConsole_Printf(ctrl1); +} +#else +void xil_printf( const char8 *ctrl1, ...) +{ + s32 Check; +#if defined (__aarch64__) || defined (__arch64__) + s32 long_flag; +#endif + s32 dot_flag; + + params_t par; + + char8 ch; + va_list argp; + char8 *ctrl = (char8 *)ctrl1; + + va_start( argp, ctrl1); + + while ((ctrl != NULL) && (*ctrl != (char8)0)) { + + /* move format string chars to buffer until a */ + /* format control is found. */ + if (*ctrl != '%') { +#ifdef STDOUT_BASEADDRESS + outbyte(*ctrl); +#endif + ctrl += 1; + continue; + } + + /* initialize all the flags for this format. */ + dot_flag = 0; +#if defined (__aarch64__) || defined (__arch64__) + long_flag = 0; +#endif + par.unsigned_flag = 0; + par.left_flag = 0; + par.do_padding = 0; + par.pad_character = ' '; + par.num2=32767; + par.num1=0; + par.len=0; + + try_next: + if(ctrl != NULL) { + ctrl += 1; + } + if(ctrl != NULL) { + ch = *ctrl; + } + else { + ch = *ctrl; + } + + if (isdigit((s32)ch) != 0) { + if (dot_flag != 0) { + par.num2 = getnum(&ctrl); + } + else { + if (ch == '0') { + par.pad_character = '0'; + } + if(ctrl != NULL) { + par.num1 = getnum(&ctrl); + } + par.do_padding = 1; + } + if(ctrl != NULL) { + ctrl -= 1; + } + goto try_next; + } + + switch (tolower((s32)ch)) { + case '%': +#ifdef STDOUT_BASEADDRESS + outbyte( '%'); +#endif + Check = 1; + break; + + case '-': + par.left_flag = 1; + Check = 0; + break; + + case '.': + dot_flag = 1; + Check = 0; + break; + + case 'l': + #if defined (__aarch64__) || defined (__arch64__) + long_flag = 1; + #endif + Check = 0; + break; + + case 'u': + par.unsigned_flag = 1; + /* fall through */ + case 'i': + case 'd': + #if defined (__aarch64__) || defined (__arch64__) + if (long_flag != 0){ + outnum1((s64)va_arg(argp, s64), 10L, &par); + } + else { + outnum( va_arg(argp, s32), 10L, &par); + } + #else + outnum( va_arg(argp, s32), 10L, &par); + #endif + Check = 1; + break; + case 'p': + #if defined (__aarch64__) || defined (__arch64__) + par.unsigned_flag = 1; + outnum1((s64)va_arg(argp, s64), 16L, &par); + Check = 1; + break; + #endif + case 'X': + case 'x': + par.unsigned_flag = 1; + #if defined (__aarch64__) || defined (__arch64__) + if (long_flag != 0) { + outnum1((s64)va_arg(argp, s64), 16L, &par); + } + else { + outnum((s32)va_arg(argp, s32), 16L, &par); + } + #else + outnum((s32)va_arg(argp, s32), 16L, &par); + #endif + Check = 1; + break; + + case 's': + outs( va_arg( argp, char *), &par); + Check = 1; + break; + + case 'c': +#ifdef STDOUT_BASEADDRESS + outbyte( va_arg( argp, s32)); +#endif + Check = 1; + break; + + case '\\': + switch (*ctrl) { + case 'a': +#ifdef STDOUT_BASEADDRESS + outbyte( ((char8)0x07)); +#endif + break; + case 'h': +#ifdef STDOUT_BASEADDRESS + outbyte( ((char8)0x08)); +#endif + break; + case 'r': +#ifdef STDOUT_BASEADDRESS + outbyte( ((char8)0x0D)); +#endif + break; + case 'n': +#ifdef STDOUT_BASEADDRESS + outbyte( ((char8)0x0D)); + outbyte( ((char8)0x0A)); +#endif + break; + default: +#ifdef STDOUT_BASEADDRESS + outbyte( *ctrl); +#endif + break; + } + ctrl += 1; + Check = 0; + break; + + default: + Check = 1; + break; + } + if(Check == 1) { + if(ctrl != NULL) { + ctrl += 1; + } + continue; + } + goto try_next; + } + va_end( argp); +} +#endif +/*---------------------------------------------------*/ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_printf.h b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_printf.h new file mode 100644 index 0000000..a0177fc --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_printf.h @@ -0,0 +1,48 @@ + #ifndef XIL_PRINTF_H + #define XIL_PRINTF_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include "xil_types.h" +#include "xparameters.h" +#include "bspconfig.h" +#if defined (__aarch64__) && HYP_GUEST && EL1_NONSECURE && XEN_USE_PV_CONSOLE +#include "xen_console.h" +#endif + +/*----------------------------------------------------*/ +/* Use the following parameter passing structure to */ +/* make xil_printf re-entrant. */ +/*----------------------------------------------------*/ + +struct params_s; + + +/*---------------------------------------------------*/ +/* The purpose of this routine is to output data the */ +/* same as the standard printf function without the */ +/* overhead most run-time libraries involve. Usually */ +/* the printf brings in many kilobytes of code and */ +/* that is unacceptable in most embedded systems. */ +/*---------------------------------------------------*/ + +typedef char8* charptr; +typedef s32 (*func_ptr)(int c); + +/* */ + +void xil_printf( const char8 *ctrl1, ...); +void print( const char8 *ptr); +extern void outbyte (char8 c); +extern char8 inbyte(void); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_sleepcommon.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_sleepcommon.c new file mode 100644 index 0000000..cb28204 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_sleepcommon.c @@ -0,0 +1,102 @@ +/****************************************************************************** +* +* Copyright (C) 2017 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +*@file xil_sleepcommon.c +* +* This file contains the sleep API's +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 6.6 	srm  	 11/02/17 First release
+* 
+******************************************************************************/ + + +/***************************** Include Files *********************************/ +#include "xil_io.h" +#include "sleep.h" + +/**************************** Constant Definitions *************************/ + + +/*****************************************************************************/ +/** +* +* This API gives delay in sec +* +* @param seconds - delay time in seconds +* +* @return none +* +* @note none +* +*****************************************************************************/ + void sleep(unsigned int seconds) + { +#if defined (ARMR5) + sleep_R5(seconds); +#elif defined (__aarch64__) || defined (ARMA53_32) + sleep_A53(seconds); +#elif defined (__MICROBLAZE__) + sleep_MB(seconds); +#else + sleep_A9(seconds); +#endif + + } + +/****************************************************************************/ +/** +* +* This API gives delay in usec +* +* @param useconds - delay time in useconds +* +* @return none +* +* @note none +* +*****************************************************************************/ + void usleep(unsigned long useconds) + { +#if defined (ARMR5) + usleep_R5(useconds); +#elif defined (__aarch64__) || defined (ARMA53_32) + usleep_A53(useconds); +#elif defined (__MICROBLAZE__) + usleep_MB(useconds); +#else + usleep_A9(useconds); +#endif + + } diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_sleeptimer.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_sleeptimer.c new file mode 100644 index 0000000..316efd5 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_sleeptimer.c @@ -0,0 +1,162 @@ +/****************************************************************************** +* +* Copyright (C) 2017 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xil_sleeptimer.c +* +* This file provides the common helper routines for the sleep API's +* +*
+* MODIFICATION HISTORY :
+*
+* Ver   Who  Date	 Changes
+* ----- ---- -------- -------------------------------------------------------
+* 6.6	srm  10/18/17 First Release.
+* 6.6   srm  04/20/18 Fixed compilation warning in Xil_SleepTTCCommon API
+*
+* 
+*****************************************************************************/ + +/**************************** Include Files ********************************/ + +#include "xil_io.h" +#include "xil_sleeptimer.h" +#include "xtime_l.h" + +/**************************** Constant Definitions *************************/ + + +/* Function definitions are applicable only when TTC3 is present*/ +#if defined (SLEEP_TIMER_BASEADDR) +/****************************************************************************/ +/** +* +* This is a helper function used by sleep/usleep APIs to +* have delay in sec/usec +* +* @param delay - delay time in seconds/micro seconds +* +* @param frequency - Number of counts per second/micro second +* +* @return none +* +* @note none +* +*****************************************************************************/ +void Xil_SleepTTCCommon(u32 delay, u64 frequency) +{ + u64 tEnd = 0U; + u64 tCur = 0U; + XCntrVal TimeHighVal = 0U; + XCntrVal TimeLowVal1 = 0U; + XCntrVal TimeLowVal2 = 0U; + + TimeLowVal1 = XSleep_ReadCounterVal(SLEEP_TIMER_BASEADDR + + XSLEEP_TIMER_TTC_COUNT_VALUE_OFFSET); + tEnd = (u64)TimeLowVal1 + ((u64)(delay) * frequency); + do + { + TimeLowVal2 = XSleep_ReadCounterVal(SLEEP_TIMER_BASEADDR + + XSLEEP_TIMER_TTC_COUNT_VALUE_OFFSET); + if (TimeLowVal2 < TimeLowVal1) { + TimeHighVal++; + } + TimeLowVal1 = TimeLowVal2; + tCur = (((u64) TimeHighVal) << XSLEEP_TIMER_REG_SHIFT) | + (u64)TimeLowVal2; + }while (tCur < tEnd); +} + + +/*****************************************************************************/ +/** +* +* This API starts the Triple Timer Counter +* +* @param none +* +* @return none +* +* @note none +* +*****************************************************************************/ +void XTime_StartTTCTimer() +{ + u32 TimerPrescalar; + u32 TimerCntrl; + +#if (defined (__aarch64__) && EL3==1) || defined (ARMR5) || defined (ARMA53_32) + u32 LpdRst; + +#if defined (versal) + u32 RstAddr = CRL_TTC_RST; + u32 RstMask = CRL_TTC_BASE_RST_MASK << XSLEEP_TTC_INSTANCE; +#else + u32 RstAddr = RST_LPD_IOU2; + u32 RstMask = RST_LPD_IOU2_TTC_BASE_RESET_MASK << XSLEEP_TTC_INSTANCE; +#endif + /* check if the timer is reset */ + LpdRst = XSleep_ReadCounterVal(RstAddr); + if ((LpdRst & RstMask) != 0 ) { + LpdRst = LpdRst & (~RstMask); + Xil_Out32(RstAddr, LpdRst); + } else { +#endif + TimerCntrl = XSleep_ReadCounterVal(SLEEP_TIMER_BASEADDR + + XSLEEP_TIMER_TTC_CNT_CNTRL_OFFSET); + /* check if Timer is disabled */ + if ((TimerCntrl & XSLEEP_TIMER_TTC_CNT_CNTRL_DIS_MASK) == 0) { + TimerPrescalar = XSleep_ReadCounterVal(SLEEP_TIMER_BASEADDR + + XSLEEP_TIMER_TTC_CLK_CNTRL_OFFSET); + /* check if Timer is configured with proper functionalty for sleep */ + if ((TimerPrescalar & XSLEEP_TIMER_TTC_CLK_CNTRL_PS_EN_MASK) == 0) + return; + } +#if (defined (__aarch64__) && EL3==1) || defined (ARMR5) || defined (ARMA53_32) + } +#endif + /* Disable the timer to configure */ + TimerCntrl = XSleep_ReadCounterVal(SLEEP_TIMER_BASEADDR + + XSLEEP_TIMER_TTC_CNT_CNTRL_OFFSET); + TimerCntrl = TimerCntrl | XSLEEP_TIMER_TTC_CNT_CNTRL_DIS_MASK; + Xil_Out32(SLEEP_TIMER_BASEADDR + XSLEEP_TIMER_TTC_CNT_CNTRL_OFFSET, + TimerCntrl); + /* Disable the prescalar */ + TimerPrescalar = XSleep_ReadCounterVal(SLEEP_TIMER_BASEADDR + + XSLEEP_TIMER_TTC_CLK_CNTRL_OFFSET); + TimerPrescalar = TimerPrescalar & (~XSLEEP_TIMER_TTC_CLK_CNTRL_PS_EN_MASK); + Xil_Out32(SLEEP_TIMER_BASEADDR + XSLEEP_TIMER_TTC_CLK_CNTRL_OFFSET, + TimerPrescalar); + /* Enable the Timer */ + TimerCntrl = TimerCntrl & (~XSLEEP_TIMER_TTC_CNT_CNTRL_DIS_MASK); + Xil_Out32(SLEEP_TIMER_BASEADDR + XSLEEP_TIMER_TTC_CNT_CNTRL_OFFSET, + TimerCntrl); +} +#endif diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_sleeptimer.h b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_sleeptimer.h new file mode 100644 index 0000000..08f64ba --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_sleeptimer.h @@ -0,0 +1,128 @@ +/****************************************************************************** +* +* Copyright (C) 2017 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_sleeptimer.h +* +* This header file contains ARM Cortex A53,A9,R5 specific sleep related APIs. +* For sleep related functions that can be used across all Xilinx supported +* processors, please use xil_sleeptimer.h. +* +* +*
+* MODIFICATION HISTORY :
+*
+* Ver   Who  Date	 Changes
+* ----- ---- -------- -------------------------------------------------------
+* 6.6	srm  10/18/17 First Release.
+* 7.0   mus  01/07/19 Add cpp extern macro
+*
+* 
+*****************************************************************************/ + +#ifndef XIL_SLEEPTIMER_H /* prevent circular inclusions */ +#define XIL_SLEEPTIMER_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/**************************** Include Files ********************************/ + +#include "xil_io.h" +#include "xparameters.h" +#include "bspconfig.h" + +/************************** Constant Definitions *****************************/ + +#if defined (ARMR5) || (__aarch64__) || (ARMA53_32) +#define XSLEEP_TIMER_REG_SHIFT 32U +#define XSleep_ReadCounterVal Xil_In32 +#define XCntrVal u32 +#else +#define XSLEEP_TIMER_REG_SHIFT 16U +#define XSleep_ReadCounterVal Xil_In16 +#define XCntrVal u16 +#endif + +#if defined(ARMR5) || (defined (__aarch64__) && EL3==1) || defined (ARMA53_32) +#if defined (versal) +#define CRL_TTC_RST 0xFF5E0344U +#define CRL_TTC_BASE_RST_MASK 0x1U +#else +#define RST_LPD_IOU2 0xFF5E0238U +#define RST_LPD_IOU2_TTC_BASE_RESET_MASK 0x00000800U +#endif +#endif + +#if defined (SLEEP_TIMER_BASEADDR) +/** @name Register Map +* +* Register offsets from the base address of the TTC device +* +* @{ +*/ + #define XSLEEP_TIMER_TTC_CLK_CNTRL_OFFSET 0x00000000U + /**< Clock Control Register */ + #define XSLEEP_TIMER_TTC_CNT_CNTRL_OFFSET 0x0000000CU + /**< Counter Control Register*/ + #define XSLEEP_TIMER_TTC_COUNT_VALUE_OFFSET 0x00000018U + /**< Current Counter Value */ +/* @} */ +/** @name Clock Control Register +* Clock Control Register definitions of TTC +* @{ +*/ + #define XSLEEP_TIMER_TTC_CLK_CNTRL_PS_EN_MASK 0x00000001U + /**< Prescale enable */ +/* @} */ +/** @name Counter Control Register +* Counter Control Register definitions of TTC +* @{ +*/ +#define XSLEEP_TIMER_TTC_CNT_CNTRL_DIS_MASK 0x00000001U + /**< Disable the counter */ +#define XSLEEP_TIMER_TTC_CNT_CNTRL_RST_MASK 0x00000010U + /**< Reset counter */ +/* @} */ + +/**************************** Type Definitions *******************************/ + +/************************** Function Prototypes ******************************/ + +void Xil_SleepTTCCommon(u32 delay, u64 frequency); +void XTime_StartTTCTimer(); + +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* XIL_SLEEPTIMER_H */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_testcache.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_testcache.c new file mode 100644 index 0000000..6ea52a8 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_testcache.c @@ -0,0 +1,367 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_testcache.c +* +* Contains utility functions to test cache. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date	 Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a hbm  07/28/09 Initial release
+* 4.1   asa  05/09/14 Ensured that the address uses for cache test is aligned
+*				      cache line.
+* 
+* +* @note +* This file contain functions that all operate on HAL. +* +******************************************************************************/ +#ifdef __ARM__ +#include "xil_cache.h" +#include "xil_testcache.h" +#include "xil_types.h" +#include "xpseudo_asm.h" +#ifdef __aarch64__ +#include "xreg_cortexa53.h" +#else +#include "xreg_cortexr5.h" +#endif + +#include "xil_types.h" + +extern void xil_printf(const char8 *ctrl1, ...); + +#define DATA_LENGTH 128 + +#ifdef __aarch64__ +static INTPTR Data[DATA_LENGTH] __attribute__ ((aligned(64))); +#else +static INTPTR Data[DATA_LENGTH] __attribute__ ((aligned(32))); +#endif + + +/*****************************************************************************/ +/** +* +* @brief Perform DCache range related API test such as Xil_DCacheFlushRange +* and Xil_DCacheInvalidateRange. This test function writes a constant +* value to the Data array, flushes the range, writes a new value, then +* invalidates the corresponding range. +* @param None +* +* @return +* - -1 is returned for a failure +* - 0 is returned for a pass +* +*****************************************************************************/ +s32 Xil_TestDCacheRange(void) +{ + s32 Index; + s32 Status = 0; + u32 CtrlReg; + INTPTR Value; + + xil_printf("-- Cache Range Test --\n\r"); + + for (Index = 0; Index < DATA_LENGTH; Index++) + Data[Index] = 0xA0A00505; + + xil_printf(" initialize Data done:\r\n"); + + Xil_DCacheFlushRange((INTPTR)Data, DATA_LENGTH * sizeof(INTPTR)); + + xil_printf(" flush range done\r\n"); + + dsb(); + #ifdef __aarch64__ + CtrlReg = mfcp(SCTLR_EL3); + CtrlReg &= ~(XREG_CONTROL_DCACHE_BIT); + mtcp(SCTLR_EL3,CtrlReg); + #else + CtrlReg = mfcp(XREG_CP15_SYS_CONTROL); + CtrlReg &= ~(XREG_CP15_CONTROL_C_BIT); + mtcp(XREG_CP15_SYS_CONTROL, CtrlReg); + #endif + dsb(); + + Status = 0; + + for (Index = 0; Index < DATA_LENGTH; Index++) { + Value = Data[Index]; + if (Value != 0xA0A00505) { + Status = -1; + xil_printf("Data[%d] = %x\r\n", Index, Value); + break; + } + } + + if (!Status) { + xil_printf(" Flush worked\r\n"); + } + else { + xil_printf("Error: flush dcache range not working\r\n"); + } + dsb(); + #ifdef __aarch64__ + CtrlReg = mfcp(SCTLR_EL3); + CtrlReg |= (XREG_CONTROL_DCACHE_BIT); + mtcp(SCTLR_EL3,CtrlReg); + #else + CtrlReg = mfcp(XREG_CP15_SYS_CONTROL); + CtrlReg |= (XREG_CP15_CONTROL_C_BIT); + mtcp(XREG_CP15_SYS_CONTROL, CtrlReg); + #endif + dsb(); + for (Index = 0; Index < DATA_LENGTH; Index++) + Data[Index] = 0xA0A0C505; + + + + Xil_DCacheFlushRange((INTPTR)Data, DATA_LENGTH * sizeof(INTPTR)); + + for (Index = 0; Index < DATA_LENGTH; Index++) + Data[Index] = Index + 3; + + Xil_DCacheInvalidateRange((INTPTR)Data, DATA_LENGTH * sizeof(INTPTR)); + + xil_printf(" invalidate dcache range done\r\n"); + dsb(); + #ifdef __aarch64__ + CtrlReg = mfcp(SCTLR_EL3); + CtrlReg &= ~(XREG_CONTROL_DCACHE_BIT); + mtcp(SCTLR_EL3,CtrlReg); + #else + CtrlReg = mfcp(XREG_CP15_SYS_CONTROL); + CtrlReg &= ~(XREG_CP15_CONTROL_C_BIT); + mtcp(XREG_CP15_SYS_CONTROL, CtrlReg); + #endif + dsb(); + for (Index = 0; Index < DATA_LENGTH; Index++) + Data[Index] = 0xA0A0A05; + dsb(); + #ifdef __aarch64__ + CtrlReg = mfcp(SCTLR_EL3); + CtrlReg |= (XREG_CONTROL_DCACHE_BIT); + mtcp(SCTLR_EL3,CtrlReg); + #else + CtrlReg = mfcp(XREG_CP15_SYS_CONTROL); + CtrlReg |= (XREG_CP15_CONTROL_C_BIT); + mtcp(XREG_CP15_SYS_CONTROL, CtrlReg); + #endif + dsb(); + + Status = 0; + + for (Index = 0; Index < DATA_LENGTH; Index++) { + Value = Data[Index]; + if (Value != 0xA0A0A05) { + Status = -1; + xil_printf("Data[%d] = %x\r\n", Index, Value); + break; + } + } + + + if (!Status) { + xil_printf(" Invalidate worked\r\n"); + } + else { + xil_printf("Error: Invalidate dcache range not working\r\n"); + } + xil_printf("-- Cache Range Test Complete --\r\n"); + return Status; + +} + +/*****************************************************************************/ +/** +* @brief Perform DCache all related API test such as Xil_DCacheFlush and +* Xil_DCacheInvalidate. This test function writes a constant value +* to the Data array, flushes the DCache, writes a new value, +* then invalidates the DCache. +* +* @return +* - 0 is returned for a pass +* - -1 is returned for a failure +*****************************************************************************/ +s32 Xil_TestDCacheAll(void) +{ + s32 Index; + s32 Status; + INTPTR Value; + u32 CtrlReg; + + xil_printf("-- Cache All Test --\n\r"); + + for (Index = 0; Index < DATA_LENGTH; Index++) + Data[Index] = 0x50500A0A; + xil_printf(" initialize Data done:\r\n"); + + Xil_DCacheFlush(); + xil_printf(" flush all done\r\n"); + dsb(); + #ifdef __aarch64__ + CtrlReg = mfcp(SCTLR_EL3); + CtrlReg &= ~(XREG_CONTROL_DCACHE_BIT); + mtcp(SCTLR_EL3,CtrlReg); + #else + CtrlReg = mfcp(XREG_CP15_SYS_CONTROL); + CtrlReg &= ~(XREG_CP15_CONTROL_C_BIT); + mtcp(XREG_CP15_SYS_CONTROL, CtrlReg); + #endif + dsb(); + Status = 0; + + for (Index = 0; Index < DATA_LENGTH; Index++) { + Value = Data[Index]; + + if (Value != 0x50500A0A) { + Status = -1; + xil_printf("Data[%d] = %x\r\n", Index, Value); + break; + } + } + + if (!Status) { + xil_printf(" Flush all worked\r\n"); + } + else { + xil_printf("Error: Flush dcache all not working\r\n"); + } + dsb(); + #ifdef __aarch64__ + CtrlReg = mfcp(SCTLR_EL3); + CtrlReg |= (XREG_CONTROL_DCACHE_BIT); + mtcp(SCTLR_EL3,CtrlReg); + #else + CtrlReg = mfcp(XREG_CP15_SYS_CONTROL); + CtrlReg |= (XREG_CP15_CONTROL_C_BIT); + mtcp(XREG_CP15_SYS_CONTROL, CtrlReg); + #endif + dsb(); + for (Index = 0; Index < DATA_LENGTH; Index++) + Data[Index] = 0x505FFA0A; + + Xil_DCacheFlush(); + + + for (Index = 0; Index < DATA_LENGTH; Index++) + Data[Index] = Index + 3; + + Xil_DCacheInvalidate(); + + xil_printf(" invalidate all done\r\n"); + dsb(); + #ifdef __aarch64__ + CtrlReg = mfcp(SCTLR_EL3); + CtrlReg &= ~(XREG_CONTROL_DCACHE_BIT); + mtcp(SCTLR_EL3,CtrlReg); + #else + CtrlReg = mfcp(XREG_CP15_SYS_CONTROL); + CtrlReg &= ~(XREG_CP15_CONTROL_C_BIT); + mtcp(XREG_CP15_SYS_CONTROL, CtrlReg); + #endif + dsb(); + for (Index = 0; Index < DATA_LENGTH; Index++) + Data[Index] = 0x50CFA0A; + dsb(); + #ifdef __aarch64__ + CtrlReg = mfcp(SCTLR_EL3); + CtrlReg |= (XREG_CONTROL_DCACHE_BIT); + mtcp(SCTLR_EL3,CtrlReg); + #else + CtrlReg = mfcp(XREG_CP15_SYS_CONTROL); + CtrlReg |= (XREG_CP15_CONTROL_C_BIT); + mtcp(XREG_CP15_SYS_CONTROL, CtrlReg); + #endif + dsb(); + Status = 0; + + for (Index = 0; Index < DATA_LENGTH; Index++) { + Value = Data[Index]; + if (Value != 0x50CFA0A) { + Status = -1; + xil_printf("Data[%d] = %x\r\n", Index, Value); + break; + } + } + + if (!Status) { + xil_printf(" Invalidate all worked\r\n"); + } + else { + xil_printf("Error: Invalidate dcache all not working\r\n"); + } + + xil_printf("-- DCache all Test Complete --\n\r"); + + return Status; +} + +/*****************************************************************************/ +/** +* @brief Perform Xil_ICacheInvalidateRange() on a few function pointers. +* +* @return +* - 0 is returned for a pass +* @note +* The function will hang if it fails. +*****************************************************************************/ +s32 Xil_TestICacheRange(void) +{ + + Xil_ICacheInvalidateRange((INTPTR)Xil_TestICacheRange, 1024); + Xil_ICacheInvalidateRange((INTPTR)Xil_TestDCacheRange, 1024); + Xil_ICacheInvalidateRange((INTPTR)Xil_TestDCacheAll, 1024); + + xil_printf("-- Invalidate icache range done --\r\n"); + + return 0; +} + +/*****************************************************************************/ +/** +* @brief Perform Xil_ICacheInvalidate() on a few function pointers. +* +* @return +* - 0 is returned for a pass +* @note +* The function will hang if it fails. +*****************************************************************************/ +s32 Xil_TestICacheAll(void) +{ + Xil_ICacheInvalidate(); + xil_printf("-- Invalidate icache all done --\r\n"); + return 0; +} +#endif diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_testcache.h b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_testcache.h new file mode 100644 index 0000000..8289ca9 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_testcache.h @@ -0,0 +1,67 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_testcache.h +* +* @addtogroup common_test_utils +*

Cache test

+* The xil_testcache.h file contains utility functions to test cache. +* +* @{ +*
+* Ver    Who    Date    Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a hbm  07/29/09 First release
+* 
+* +******************************************************************************/ + +#ifndef XIL_TESTCACHE_H /* prevent circular inclusions */ +#define XIL_TESTCACHE_H /* by using protection macros */ + +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern s32 Xil_TestDCacheRange(void); +extern s32 Xil_TestDCacheAll(void); +extern s32 Xil_TestICacheRange(void); +extern s32 Xil_TestICacheAll(void); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** +* @} End of "addtogroup common_test_utils". +*/ \ No newline at end of file diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_testio.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_testio.c new file mode 100644 index 0000000..9a13a64 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_testio.c @@ -0,0 +1,295 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_testio.c +* +* Contains the memory test utility functions. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver    Who    Date    Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a hbm  08/25/09 First release
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ +#include "xil_testio.h" +#include "xil_assert.h" +#include "xil_io.h" + +/************************** Constant Definitions ****************************/ +/************************** Function Prototypes *****************************/ + + + +/** + * + * Endian swap a 16-bit word. + * @param Data is the 16-bit word to be swapped. + * @return The endian swapped value. + * + */ +static u16 Swap16(u16 Data) +{ + return ((Data >> 8U) & 0x00FFU) | ((Data << 8U) & 0xFF00U); +} + +/** + * + * Endian swap a 32-bit word. + * @param Data is the 32-bit word to be swapped. + * @return The endian swapped value. + * + */ +static u32 Swap32(u32 Data) +{ + u16 Lo16; + u16 Hi16; + + u16 Swap16Lo; + u16 Swap16Hi; + + Hi16 = (u16)((Data >> 16U) & 0x0000FFFFU); + Lo16 = (u16)(Data & 0x0000FFFFU); + + Swap16Lo = Swap16(Lo16); + Swap16Hi = Swap16(Hi16); + + return (((u32)(Swap16Lo)) << 16U) | ((u32)Swap16Hi); +} + +/*****************************************************************************/ +/** +* +* @brief Perform a destructive 8-bit wide register IO test where the +* register is accessed using Xil_Out8 and Xil_In8, and comparing +* the written values by reading them back. +* +* @param Addr: a pointer to the region of memory to be tested. +* @param Length: Length of the block. +* @param Value: constant used for writting the memory. +* +* @return +* - -1 is returned for a failure +* - 0 is returned for a pass +* +*****************************************************************************/ + +s32 Xil_TestIO8(u8 *Addr, s32 Length, u8 Value) +{ + u8 ValueIn; + s32 Index; + s32 Status = 0; + + for (Index = 0; Index < Length; Index++) { + Xil_Out8((INTPTR)Addr, Value); + + ValueIn = Xil_In8((INTPTR)Addr); + + if ((Value != ValueIn) && (Status == 0)) { + Status = -1; + break; + } + } + return Status; + +} + +/*****************************************************************************/ +/** +* +* @brief Perform a destructive 16-bit wide register IO test. Each location +* is tested by sequentially writing a 16-bit wide register, reading +* the register, and comparing value. This function tests three kinds +* of register IO functions, normal register IO, little-endian register +* IO, and big-endian register IO. When testing little/big-endian IO, +* the function performs the following sequence, Xil_Out16LE/Xil_Out16BE, +* Xil_In16, Compare In-Out values, Xil_Out16, Xil_In16LE/Xil_In16BE, +* Compare In-Out values. Whether to swap the read-in value before +* comparing is controlled by the 5th argument. +* +* @param Addr: a pointer to the region of memory to be tested. +* @param Length: Length of the block. +* @param Value: constant used for writting the memory. +* @param Kind: Type of test. Acceptable values are: +* XIL_TESTIO_DEFAULT, XIL_TESTIO_LE, XIL_TESTIO_BE. +* @param Swap: indicates whether to byte swap the read-in value. +* +* @return +* - -1 is returned for a failure +* - 0 is returned for a pass +* +*****************************************************************************/ + +s32 Xil_TestIO16(u16 *Addr, s32 Length, u16 Value, s32 Kind, s32 Swap) +{ + u16 *TempAddr16; + u16 ValueIn = 0U; + s32 Index; + TempAddr16 = Addr; + Xil_AssertNonvoid(TempAddr16 != NULL); + + for (Index = 0; Index < Length; Index++) { + switch (Kind) { + case XIL_TESTIO_LE: + Xil_Out16LE((INTPTR)TempAddr16, Value); + break; + case XIL_TESTIO_BE: + Xil_Out16BE((INTPTR)TempAddr16, Value); + break; + default: + Xil_Out16((INTPTR)TempAddr16, Value); + break; + } + + ValueIn = Xil_In16((INTPTR)TempAddr16); + + if ((Kind != 0) && (Swap != 0)) { + ValueIn = Swap16(ValueIn); + } + + if (Value != ValueIn) { + return -1; + } + + /* second round */ + Xil_Out16((INTPTR)TempAddr16, Value); + + switch (Kind) { + case XIL_TESTIO_LE: + ValueIn = Xil_In16LE((INTPTR)TempAddr16); + break; + case XIL_TESTIO_BE: + ValueIn = Xil_In16BE((INTPTR)TempAddr16); + break; + default: + ValueIn = Xil_In16((INTPTR)TempAddr16); + break; + } + + + if ((Kind != 0) && (Swap != 0)) { + ValueIn = Swap16(ValueIn); + } + + if (Value != ValueIn) { + return -1; + } + TempAddr16 += sizeof(u16); + } + return 0; +} + + +/*****************************************************************************/ +/** +* +* @brief Perform a destructive 32-bit wide register IO test. Each location +* is tested by sequentially writing a 32-bit wide regsiter, reading +* the register, and comparing value. This function tests three kinds +* of register IO functions, normal register IO, little-endian register IO, +* and big-endian register IO. When testing little/big-endian IO, +* the function perform the following sequence, Xil_Out32LE/ +* Xil_Out32BE, Xil_In32, Compare, Xil_Out32, Xil_In32LE/Xil_In32BE, Compare. +* Whether to swap the read-in value *before comparing is controlled +* by the 5th argument. +* @param Addr: a pointer to the region of memory to be tested. +* @param Length: Length of the block. +* @param Value: constant used for writting the memory. +* @param Kind: type of test. Acceptable values are: +* XIL_TESTIO_DEFAULT, XIL_TESTIO_LE, XIL_TESTIO_BE. +* @param Swap: indicates whether to byte swap the read-in value. +* +* @return +* - -1 is returned for a failure +* - 0 is returned for a pass +* +*****************************************************************************/ +s32 Xil_TestIO32(u32 *Addr, s32 Length, u32 Value, s32 Kind, s32 Swap) +{ + u32 *TempAddr; + u32 ValueIn = 0U; + s32 Index; + TempAddr = Addr; + Xil_AssertNonvoid(TempAddr != NULL); + + for (Index = 0; Index < Length; Index++) { + switch (Kind) { + case XIL_TESTIO_LE: + Xil_Out32LE((INTPTR)TempAddr, Value); + break; + case XIL_TESTIO_BE: + Xil_Out32BE((INTPTR)TempAddr, Value); + break; + default: + Xil_Out32((INTPTR)TempAddr, Value); + break; + } + + ValueIn = Xil_In32((INTPTR)TempAddr); + + if ((Kind != 0) && (Swap != 0)) { + ValueIn = Swap32(ValueIn); + } + + if (Value != ValueIn) { + return -1; + } + + /* second round */ + Xil_Out32((INTPTR)TempAddr, Value); + + + switch (Kind) { + case XIL_TESTIO_LE: + ValueIn = Xil_In32LE((INTPTR)TempAddr); + break; + case XIL_TESTIO_BE: + ValueIn = Xil_In32BE((INTPTR)TempAddr); + break; + default: + ValueIn = Xil_In32((INTPTR)TempAddr); + break; + } + + if ((Kind != 0) && (Swap != 0)) { + ValueIn = Swap32(ValueIn); + } + + if (Value != ValueIn) { + return -1; + } + TempAddr += sizeof(u32); + } + return 0; +} diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_testio.h b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_testio.h new file mode 100644 index 0000000..6f0fc1c --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_testio.h @@ -0,0 +1,90 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_testio.h +* +* @addtogroup common_test_utils Test Utilities +*

I/O test

+* The xil_testio.h file contains utility functions to test endian related memory +* IO functions. +* +* A subset of the memory tests can be selected or all of the tests can be run +* in order. If there is an error detected by a subtest, the test stops and the +* failure code is returned. Further tests are not run even if all of the tests +* are selected. +* +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver    Who    Date    Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00 hbm  08/05/09 First release
+* 
+* +******************************************************************************/ + +#ifndef XIL_TESTIO_H /* prevent circular inclusions */ +#define XIL_TESTIO_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ +#include "xil_types.h" + +/************************** Constant Definitions *****************************/ + + +#define XIL_TESTIO_DEFAULT 0 +#define XIL_TESTIO_LE 1 +#define XIL_TESTIO_BE 2 + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + +extern s32 Xil_TestIO8(u8 *Addr, s32 Length, u8 Value); +extern s32 Xil_TestIO16(u16 *Addr, s32 Length, u16 Value, s32 Kind, s32 Swap); +extern s32 Xil_TestIO32(u32 *Addr, s32 Length, u32 Value, s32 Kind, s32 Swap); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** +* @} End of "addtogroup common_test_utils". +*/ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_testmem.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_testmem.c new file mode 100644 index 0000000..b7eb68b --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_testmem.c @@ -0,0 +1,864 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_testmem.c +* +* Contains the memory test utility functions. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver    Who    Date    Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a hbm  08/25/09 First release
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ +#include "xil_testmem.h" +#include "xil_io.h" +#include "xil_assert.h" + +/************************** Constant Definitions ****************************/ +/************************** Function Prototypes *****************************/ + +static u32 RotateLeft(u32 Input, u8 Width); + +/* define ROTATE_RIGHT to give access to this functionality */ +/* #define ROTATE_RIGHT */ +#ifdef ROTATE_RIGHT +static u32 RotateRight(u32 Input, u8 Width); +#endif /* ROTATE_RIGHT */ + + +/*****************************************************************************/ +/** +* +* @brief Perform a destructive 32-bit wide memory test. +* +* @param Addr: pointer to the region of memory to be tested. +* @param Words: length of the block. +* @param Pattern: constant used for the constant pattern test, if 0, +* 0xDEADBEEF is used. +* @param Subtest: test type selected. See xil_testmem.h for possible +* values. +* +* @return +* - 0 is returned for a pass +* - 1 is returned for a failure +* +* @note +* Used for spaces where the address range of the region is smaller than +* the data width. If the memory range is greater than 2 ** Width, +* the patterns used in XIL_TESTMEM_WALKONES and XIL_TESTMEM_WALKZEROS will +* repeat on a boundry of a power of two making it more difficult to detect +* addressing errors. The XIL_TESTMEM_INCREMENT and XIL_TESTMEM_INVERSEADDR +* tests suffer the same problem. Ideally, if large blocks of memory are to be +* tested, break them up into smaller regions of memory to allow the test +* patterns used not to repeat over the region tested. +* +*****************************************************************************/ +s32 Xil_TestMem32(u32 *Addr, u32 Words, u32 Pattern, u8 Subtest) +{ + u32 I; + u32 j; + u32 Val; + u32 FirtVal; + u32 WordMem32; + s32 Status = 0; + + Xil_AssertNonvoid(Words != (u32)0); + Xil_AssertNonvoid(Subtest <= (u8)XIL_TESTMEM_MAXTEST); + Xil_AssertNonvoid(Addr != NULL); + + /* + * variable initialization + */ + Val = XIL_TESTMEM_INIT_VALUE; + FirtVal = XIL_TESTMEM_INIT_VALUE; + + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_INCREMENT)) { + /* + * Fill the memory with incrementing + * values starting from 'FirtVal' + */ + for (I = 0U; I < Words; I++) { + *(Addr+I) = Val; + Val++; + } + + /* + * Restore the reference 'Val' to the + * initial value + */ + Val = FirtVal; + + /* + * Check every word within the words + * of tested memory and compare it + * with the incrementing reference + * Val + */ + + for (I = 0U; I < Words; I++) { + WordMem32 = *(Addr+I); + + if (WordMem32 != Val) { + Status = -1; + goto End_Label; + } + + Val++; + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_WALKONES)) { + /* + * set up to cycle through all possible initial + * test Patterns for walking ones test + */ + + for (j = 0U; j < (u32)32; j++) { + /* + * Generate an initial value for walking ones test + * to test for bad data bits + */ + + Val = (1U << j); + + /* + * START walking ones test + * Write a one to each data bit indifferent locations + */ + + for (I = 0U; I < (u32)32; I++) { + /* write memory location */ + *(Addr+I) = Val; + Val = (u32) RotateLeft(Val, 32U); + } + + /* + * Restore the reference 'val' to the + * initial value + */ + Val = 1U << j; + + /* Read the values from each location that was + * written */ + for (I = 0U; I < (u32)32; I++) { + /* read memory location */ + + WordMem32 = *(Addr+I); + + if (WordMem32 != Val) { + Status = -1; + goto End_Label; + } + + Val = (u32)RotateLeft(Val, 32U); + } + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_WALKZEROS)) { + /* + * set up to cycle through all possible + * initial test Patterns for walking zeros test + */ + + for (j = 0U; j < (u32)32; j++) { + + /* + * Generate an initial value for walking ones test + * to test for bad data bits + */ + + Val = ~(1U << j); + + /* + * START walking zeros test + * Write a one to each data bit indifferent locations + */ + + for (I = 0U; I < (u32)32; I++) { + /* write memory location */ + *(Addr+I) = Val; + Val = ~((u32)RotateLeft(~Val, 32U)); + } + + /* + * Restore the reference 'Val' to the + * initial value + */ + + Val = ~(1U << j); + + /* Read the values from each location that was + * written */ + for (I = 0U; I < (u32)32; I++) { + /* read memory location */ + WordMem32 = *(Addr+I); + if (WordMem32 != Val) { + Status = -1; + goto End_Label; + } + Val = ~((u32)RotateLeft(~Val, 32U)); + } + + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_INVERSEADDR)) { + /* Fill the memory with inverse of address */ + for (I = 0U; I < Words; I++) { + /* write memory location */ + Val = (u32) (~((INTPTR) (&Addr[I]))); + *(Addr+I) = Val; + } + + /* + * Check every word within the words + * of tested memory + */ + + for (I = 0U; I < Words; I++) { + /* Read the location */ + WordMem32 = *(Addr+I); + Val = (u32) (~((INTPTR) (&Addr[I]))); + + if ((WordMem32 ^ Val) != 0x00000000U) { + Status = -1; + goto End_Label; + } + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_FIXEDPATTERN)) { + /* + * Generate an initial value for + * memory testing + */ + + if (Pattern == (u32)0) { + Val = 0xDEADBEEFU; + } + else { + Val = Pattern; + } + + /* + * Fill the memory with fixed Pattern + */ + + for (I = 0U; I < Words; I++) { + /* write memory location */ + *(Addr+I) = Val; + } + + /* + * Check every word within the words + * of tested memory and compare it + * with the fixed Pattern + */ + + for (I = 0U; I < Words; I++) { + + /* read memory location */ + + WordMem32 = *(Addr+I); + if (WordMem32 != Val) { + Status = -1; + goto End_Label; + } + } + } + +End_Label: + return Status; +} + +/*****************************************************************************/ +/** +* +* @brief Perform a destructive 16-bit wide memory test. +* +* @param Addr: pointer to the region of memory to be tested. +* @param Words: length of the block. +* @param Pattern: constant used for the constant Pattern test, if 0, +* 0xDEADBEEF is used. +* @param Subtest: type of test selected. See xil_testmem.h for possible +* values. +* +* @return +* +* - -1 is returned for a failure +* - 0 is returned for a pass +* +* @note +* Used for spaces where the address range of the region is smaller than +* the data width. If the memory range is greater than 2 ** Width, +* the patterns used in XIL_TESTMEM_WALKONES and XIL_TESTMEM_WALKZEROS will +* repeat on a boundry of a power of two making it more difficult to detect +* addressing errors. The XIL_TESTMEM_INCREMENT and XIL_TESTMEM_INVERSEADDR +* tests suffer the same problem. Ideally, if large blocks of memory are to be +* tested, break them up into smaller regions of memory to allow the test +* patterns used not to repeat over the region tested. +* +*****************************************************************************/ +s32 Xil_TestMem16(u16 *Addr, u32 Words, u16 Pattern, u8 Subtest) +{ + u32 I; + u32 j; + u16 Val; + u16 FirtVal; + u16 WordMem16; + s32 Status = 0; + + Xil_AssertNonvoid(Words != (u32)0); + Xil_AssertNonvoid(Subtest <= XIL_TESTMEM_MAXTEST); + Xil_AssertNonvoid(Addr != NULL); + + /* + * variable initialization + */ + Val = XIL_TESTMEM_INIT_VALUE; + FirtVal = XIL_TESTMEM_INIT_VALUE; + + /* + * selectthe proper Subtest(s) + */ + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_INCREMENT)) { + /* + * Fill the memory with incrementing + * values starting from 'FirtVal' + */ + for (I = 0U; I < Words; I++) { + /* write memory location */ + *(Addr+I) = Val; + Val++; + } + /* + * Restore the reference 'Val' to the + * initial value + */ + Val = FirtVal; + + /* + * Check every word within the words + * of tested memory and compare it + * with the incrementing reference val + */ + + for (I = 0U; I < Words; I++) { + /* read memory location */ + WordMem16 = *(Addr+I); + if (WordMem16 != Val) { + Status = -1; + goto End_Label; + } + Val++; + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_WALKONES)) { + /* + * set up to cycle through all possible initial test + * Patterns for walking ones test + */ + + for (j = 0U; j < (u32)16; j++) { + /* + * Generate an initial value for walking ones test + * to test for bad data bits + */ + + Val = (u16)((u32)1 << j); + /* + * START walking ones test + * Write a one to each data bit indifferent locations + */ + + for (I = 0U; I < (u32)16; I++) { + /* write memory location */ + *(Addr+I) = Val; + Val = (u16)RotateLeft(Val, 16U); + } + /* + * Restore the reference 'Val' to the + * initial value + */ + Val = (u16)((u32)1 << j); + /* Read the values from each location that was written */ + for (I = 0U; I < (u32)16; I++) { + /* read memory location */ + WordMem16 = *(Addr+I); + if (WordMem16 != Val) { + Status = -1; + goto End_Label; + } + Val = (u16)RotateLeft(Val, 16U); + } + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_WALKZEROS)) { + /* + * set up to cycle through all possible initial + * test Patterns for walking zeros test + */ + + for (j = 0U; j < (u32)16; j++) { + /* + * Generate an initial value for walking ones + * test to test for bad + * data bits + */ + + Val = ~(1U << j); + /* + * START walking zeros test + * Write a one to each data bit indifferent locations + */ + + for (I = 0U; I < (u32)16; I++) { + /* write memory location */ + *(Addr+I) = Val; + Val = ~((u16)RotateLeft(~Val, 16U)); + } + /* + * Restore the reference 'Val' to the + * initial value + */ + Val = ~(1U << j); + /* Read the values from each location that was written */ + for (I = 0U; I < (u32)16; I++) { + /* read memory location */ + WordMem16 = *(Addr+I); + if (WordMem16 != Val) { + Status = -1; + goto End_Label; + } + Val = ~((u16)RotateLeft(~Val, 16U)); + } + + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_INVERSEADDR)) { + /* Fill the memory with inverse of address */ + for (I = 0U; I < Words; I++) { + /* write memory location */ + Val = (u16) (~((INTPTR)(&Addr[I]))); + *(Addr+I) = Val; + } + /* + * Check every word within the words + * of tested memory + */ + + for (I = 0U; I < Words; I++) { + /* read memory location */ + WordMem16 = *(Addr+I); + Val = (u16) (~((INTPTR) (&Addr[I]))); + if ((WordMem16 ^ Val) != 0x0000U) { + Status = -1; + goto End_Label; + } + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_FIXEDPATTERN)) { + /* + * Generate an initial value for + * memory testing + */ + if (Pattern == (u16)0) { + Val = 0xDEADU; + } + else { + Val = Pattern; + } + + /* + * Fill the memory with fixed pattern + */ + + for (I = 0U; I < Words; I++) { + /* write memory location */ + *(Addr+I) = Val; + } + + /* + * Check every word within the words + * of tested memory and compare it + * with the fixed pattern + */ + + for (I = 0U; I < Words; I++) { + /* read memory location */ + WordMem16 = *(Addr+I); + if (WordMem16 != Val) { + Status = -1; + goto End_Label; + } + } + } + +End_Label: + return Status; +} + + +/*****************************************************************************/ +/** +* +* @brief Perform a destructive 8-bit wide memory test. +* +* @param Addr: pointer to the region of memory to be tested. +* @param Words: length of the block. +* @param Pattern: constant used for the constant pattern test, if 0, +* 0xDEADBEEF is used. +* @param Subtest: type of test selected. See xil_testmem.h for possible +* values. +* +* @return +* - -1 is returned for a failure +* - 0 is returned for a pass +* +* @note +* Used for spaces where the address range of the region is smaller than +* the data width. If the memory range is greater than 2 ** Width, +* the patterns used in XIL_TESTMEM_WALKONES and XIL_TESTMEM_WALKZEROS will +* repeat on a boundry of a power of two making it more difficult to detect +* addressing errors. The XIL_TESTMEM_INCREMENT and XIL_TESTMEM_INVERSEADDR +* tests suffer the same problem. Ideally, if large blocks of memory are to be +* tested, break them up into smaller regions of memory to allow the test +* patterns used not to repeat over the region tested. +* +*****************************************************************************/ +s32 Xil_TestMem8(u8 *Addr, u32 Words, u8 Pattern, u8 Subtest) +{ + u32 I; + u32 j; + u8 Val; + u8 FirtVal; + u8 WordMem8; + s32 Status = 0; + + Xil_AssertNonvoid(Words != (u32)0); + Xil_AssertNonvoid(Subtest <= XIL_TESTMEM_MAXTEST); + Xil_AssertNonvoid(Addr != NULL); + + /* + * variable initialization + */ + Val = XIL_TESTMEM_INIT_VALUE; + FirtVal = XIL_TESTMEM_INIT_VALUE; + + /* + * select the proper Subtest(s) + */ + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_INCREMENT)) { + /* + * Fill the memory with incrementing + * values starting from 'FirtVal' + */ + for (I = 0U; I < Words; I++) { + /* write memory location */ + *(Addr+I) = Val; + Val++; + } + /* + * Restore the reference 'Val' to the + * initial value + */ + Val = FirtVal; + /* + * Check every word within the words + * of tested memory and compare it + * with the incrementing reference + * Val + */ + + for (I = 0U; I < Words; I++) { + /* read memory location */ + WordMem8 = *(Addr+I); + if (WordMem8 != Val) { + Status = -1; + goto End_Label; + } + Val++; + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_WALKONES)) { + /* + * set up to cycle through all possible initial + * test Patterns for walking ones test + */ + + for (j = 0U; j < (u32)8; j++) { + /* + * Generate an initial value for walking ones test + * to test for bad data bits + */ + Val = (u8)((u32)1 << j); + /* + * START walking ones test + * Write a one to each data bit indifferent locations + */ + for (I = 0U; I < (u32)8; I++) { + /* write memory location */ + *(Addr+I) = Val; + Val = (u8)RotateLeft(Val, 8U); + } + /* + * Restore the reference 'Val' to the + * initial value + */ + Val = (u8)((u32)1 << j); + /* Read the values from each location that was written */ + for (I = 0U; I < (u32)8; I++) { + /* read memory location */ + WordMem8 = *(Addr+I); + if (WordMem8 != Val) { + Status = -1; + goto End_Label; + } + Val = (u8)RotateLeft(Val, 8U); + } + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_WALKZEROS)) { + /* + * set up to cycle through all possible initial test + * Patterns for walking zeros test + */ + + for (j = 0U; j < (u32)8; j++) { + /* + * Generate an initial value for walking ones test to test + * for bad data bits + */ + Val = ~(1U << j); + /* + * START walking zeros test + * Write a one to each data bit indifferent locations + */ + for (I = 0U; I < (u32)8; I++) { + /* write memory location */ + *(Addr+I) = Val; + Val = ~((u8)RotateLeft(~Val, 8U)); + } + /* + * Restore the reference 'Val' to the + * initial value + */ + Val = ~(1U << j); + /* Read the values from each location that was written */ + for (I = 0U; I < (u32)8; I++) { + /* read memory location */ + WordMem8 = *(Addr+I); + if (WordMem8 != Val) { + Status = -1; + goto End_Label; + } + + Val = ~((u8)RotateLeft(~Val, 8U)); + } + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_INVERSEADDR)) { + /* Fill the memory with inverse of address */ + for (I = 0U; I < Words; I++) { + /* write memory location */ + Val = (u8) (~((INTPTR) (&Addr[I]))); + *(Addr+I) = Val; + } + + /* + * Check every word within the words + * of tested memory + */ + + for (I = 0U; I < Words; I++) { + /* read memory location */ + WordMem8 = *(Addr+I); + Val = (u8) (~((INTPTR) (&Addr[I]))); + if ((WordMem8 ^ Val) != 0x00U) { + Status = -1; + goto End_Label; + } + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_FIXEDPATTERN)) { + /* + * Generate an initial value for + * memory testing + */ + + if (Pattern == (u8)0) { + Val = 0xA5U; + } + else { + Val = Pattern; + } + /* + * Fill the memory with fixed Pattern + */ + for (I = 0U; I < Words; I++) { + /* write memory location */ + *(Addr+I) = Val; + } + /* + * Check every word within the words + * of tested memory and compare it + * with the fixed Pattern + */ + + for (I = 0U; I < Words; I++) { + /* read memory location */ + WordMem8 = *(Addr+I); + if (WordMem8 != Val) { + Status = -1; + goto End_Label; + } + } + } + +End_Label: + return Status; +} + + +/*****************************************************************************/ +/** +* +* @brief Rotates the provided value to the left one bit position +* +* @param Input is value to be rotated to the left +* @param Width is the number of bits in the input data +* +* @return +* The resulting unsigned long value of the rotate left +* +* +*****************************************************************************/ +static u32 RotateLeft(u32 Input, u8 Width) +{ + u32 Msb; + u32 ReturnVal; + u32 WidthMask; + u32 MsbMask; + u32 LocalInput = Input; + + /* + * set up the WidthMask and the MsbMask + */ + + MsbMask = 1U << (Width - 1U); + + WidthMask = (MsbMask << (u32)1) - (u32)1; + + /* + * set the Width of the Input to the correct width + */ + + LocalInput = LocalInput & WidthMask; + + Msb = LocalInput & MsbMask; + + ReturnVal = LocalInput << 1U; + + if (Msb != 0x00000000U) { + ReturnVal = ReturnVal | (u32)0x00000001; + } + + ReturnVal = ReturnVal & WidthMask; + + return ReturnVal; + +} + +#ifdef ROTATE_RIGHT +/*****************************************************************************/ +/** +* +* @brief Rotates the provided value to the right one bit position +* +* @param Input: value to be rotated to the right +* @param Width: number of bits in the input data +* +* @return +* The resulting u32 value of the rotate right +* +*****************************************************************************/ +static u32 RotateRight(u32 Input, u8 Width) +{ + u32 Lsb; + u32 ReturnVal; + u32 WidthMask; + u32 MsbMask; + u32 LocalInput = Input; + /* + * set up the WidthMask and the MsbMask + */ + + MsbMask = 1U << (Width - 1U); + + WidthMask = (MsbMask << 1U) - 1U; + + /* + * set the width of the input to the correct width + */ + + LocalInput = LocalInput & WidthMask; + + ReturnVal = LocalInput >> 1U; + + Lsb = LocalInput & 0x00000001U; + + if (Lsb != 0x00000000U) { + ReturnVal = ReturnVal | MsbMask; + } + + ReturnVal = ReturnVal & WidthMask; + + return ReturnVal; + +} +#endif /* ROTATE_RIGHT */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_testmem.h b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_testmem.h new file mode 100644 index 0000000..ecce6b7 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_testmem.h @@ -0,0 +1,154 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_testmem.h +* @addtogroup common_test_utils +* +*

Memory test

+* +* The xil_testmem.h file contains utility functions to test memory. +* A subset of the memory tests can be selected or all of the tests can be run +* in order. If there is an error detected by a subtest, the test stops and the +* failure code is returned. Further tests are not run even if all of the tests +* are selected. +* Following list describes the supported memory tests: +* +* - XIL_TESTMEM_ALLMEMTESTS: This test runs all of the subtests. +* +* - XIL_TESTMEM_INCREMENT: This test +* starts at 'XIL_TESTMEM_INIT_VALUE' and uses the incrementing value as the +* test value for memory. +* +* - XIL_TESTMEM_WALKONES: Also known as the Walking ones test. This test +* uses a walking '1' as the test value for memory. +* @code +* location 1 = 0x00000001 +* location 2 = 0x00000002 +* ... +* @endcode +* +* - XIL_TESTMEM_WALKZEROS: Also known as the Walking zero's test. +* This test uses the inverse value of the walking ones test +* as the test value for memory. +* @code +* location 1 = 0xFFFFFFFE +* location 2 = 0xFFFFFFFD +* ... +*@endcode +* +* - XIL_TESTMEM_INVERSEADDR: Also known as the inverse address test. +* This test uses the inverse of the address of the location under test +* as the test value for memory. +* +* - XIL_TESTMEM_FIXEDPATTERN: Also known as the fixed pattern test. +* This test uses the provided patters as the test value for memory. +* If zero is provided as the pattern the test uses '0xDEADBEEF". +* +* @warning +* The tests are DESTRUCTIVE. Run before any initialized memory spaces +* have been set up. +* The address provided to the memory tests is not checked for +* validity except for the NULL case. It is possible to provide a code-space +* pointer for this test to start with and ultimately destroy executable code +* causing random failures. +* +* @note +* Used for spaces where the address range of the region is smaller than +* the data width. If the memory range is greater than 2 ** width, +* the patterns used in XIL_TESTMEM_WALKONES and XIL_TESTMEM_WALKZEROS will +* repeat on a boundry of a power of two making it more difficult to detect +* addressing errors. The XIL_TESTMEM_INCREMENT and XIL_TESTMEM_INVERSEADDR +* tests suffer the same problem. Ideally, if large blocks of memory are to be +* tested, break them up into smaller regions of memory to allow the test +* patterns used not to repeat over the region tested. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver    Who    Date    Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a hbm  08/25/09 First release
+* 
+* +******************************************************************************/ + +#ifndef XIL_TESTMEM_H /* prevent circular inclusions */ +#define XIL_TESTMEM_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ +#include "xil_types.h" + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + +/* xutil_memtest defines */ + +#define XIL_TESTMEM_INIT_VALUE 1U + +/** @name Memory subtests + * @{ + */ +/** + * See the detailed description of the subtests in the file description. + */ +#define XIL_TESTMEM_ALLMEMTESTS 0x00U +#define XIL_TESTMEM_INCREMENT 0x01U +#define XIL_TESTMEM_WALKONES 0x02U +#define XIL_TESTMEM_WALKZEROS 0x03U +#define XIL_TESTMEM_INVERSEADDR 0x04U +#define XIL_TESTMEM_FIXEDPATTERN 0x05U +#define XIL_TESTMEM_MAXTEST XIL_TESTMEM_FIXEDPATTERN +/* @} */ + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + +/* xutil_testmem prototypes */ + +extern s32 Xil_TestMem32(u32 *Addr, u32 Words, u32 Pattern, u8 Subtest); +extern s32 Xil_TestMem16(u16 *Addr, u32 Words, u16 Pattern, u8 Subtest); +extern s32 Xil_TestMem8(u8 *Addr, u32 Words, u8 Pattern, u8 Subtest); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** +* @} End of "addtogroup common_test_utils". +*/ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_types.h b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_types.h new file mode 100644 index 0000000..625ff8c --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_types.h @@ -0,0 +1,214 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_types.h +* +* @addtogroup common_types Basic Data types for Xilinx® Software IP +* +* The xil_types.h file contains basic types for Xilinx software IP. These data types +* are applicable for all processors supported by Xilinx. +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date   Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a hbm  07/14/09 First release
+* 3.03a sdm  05/30/11 Added Xuint64 typedef and XUINT64_MSW/XUINT64_LSW macros
+* 5.00 	pkp  05/29/14 Made changes for 64 bit architecture
+*	srt  07/14/14 Use standard definitions from stdint.h and stddef.h
+*		      Define LONG and ULONG datatypes and mask values
+* 7.00  mus  01/07/19 Add cpp extern macro
+* 
+* +******************************************************************************/ + +#ifndef XIL_TYPES_H /* prevent circular inclusions */ +#define XIL_TYPES_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +/************************** Constant Definitions *****************************/ + +#ifndef TRUE +# define TRUE 1U +#endif + +#ifndef FALSE +# define FALSE 0U +#endif + +#ifndef NULL +#define NULL 0U +#endif + +#define XIL_COMPONENT_IS_READY 0x11111111U /**< In device drivers, This macro will be + assigend to "IsReady" member of driver + instance to indicate that driver + instance is initialized and ready to use. */ +#define XIL_COMPONENT_IS_STARTED 0x22222222U /**< In device drivers, This macro will be assigend to + "IsStarted" member of driver instance + to indicate that driver instance is + started and it can be enabled. */ + +/* @name New types + * New simple types. + * @{ + */ +#ifndef __KERNEL__ +#ifndef XBASIC_TYPES_H +/* + * guarded against xbasic_types.h. + */ +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; +/** @}*/ +#define __XUINT64__ +typedef struct +{ + u32 Upper; + u32 Lower; +} Xuint64; + + +/*****************************************************************************/ +/** +* @brief Return the most significant half of the 64 bit data type. +* +* @param x is the 64 bit word. +* +* @return The upper 32 bits of the 64 bit word. +* +******************************************************************************/ +#define XUINT64_MSW(x) ((x).Upper) + +/*****************************************************************************/ +/** +* @brief Return the least significant half of the 64 bit data type. +* +* @param x is the 64 bit word. +* +* @return The lower 32 bits of the 64 bit word. +* +******************************************************************************/ +#define XUINT64_LSW(x) ((x).Lower) + +#endif /* XBASIC_TYPES_H */ + +/* + * xbasic_types.h does not typedef s* or u64 + */ +/** @{ */ +typedef char char8; +typedef int8_t s8; +typedef int16_t s16; +typedef int32_t s32; +typedef int64_t s64; +typedef uint64_t u64; +typedef int sint32; + +typedef intptr_t INTPTR; +typedef uintptr_t UINTPTR; +typedef ptrdiff_t PTRDIFF; +/** @}*/ +#if !defined(LONG) || !defined(ULONG) +typedef long LONG; +typedef unsigned long ULONG; +#endif + +#define ULONG64_HI_MASK 0xFFFFFFFF00000000U +#define ULONG64_LO_MASK ~ULONG64_HI_MASK + +#else +#include +#endif + +/** @{ */ +/** + * This data type defines an interrupt handler for a device. + * The argument points to the instance of the component + */ +typedef void (*XInterruptHandler) (void *InstancePtr); + +/** + * This data type defines an exception handler for a processor. + * The argument points to the instance of the component + */ +typedef void (*XExceptionHandler) (void *InstancePtr); + +/** + * @brief Returns 32-63 bits of a number. + * @param n : Number being accessed. + * @return Bits 32-63 of number. + * + * @note A basic shift-right of a 64- or 32-bit quantity. + * Use this to suppress the "right shift count >= width of type" + * warning when that quantity is 32-bits. + */ +#define UPPER_32_BITS(n) ((u32)(((n) >> 16) >> 16)) + +/** + * @brief Returns 0-31 bits of a number + * @param n : Number being accessed. + * @return Bits 0-31 of number + */ +#define LOWER_32_BITS(n) ((u32)(n)) + + + + +/************************** Constant Definitions *****************************/ + +#ifndef TRUE +#define TRUE 1U +#endif + +#ifndef FALSE +#define FALSE 0U +#endif + +#ifndef NULL +#define NULL 0U +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** +* @} End of "addtogroup common_types". +*/ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_util.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_util.c new file mode 100644 index 0000000..d9282ca --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_util.c @@ -0,0 +1,175 @@ +/******************************************************************************/ +/** +* Copyright (C) 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* @file xil_util.c +* +* This file contains xil utility functions +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 6.4   mmd      04/21/19 First release.
+*
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ +#include "xil_types.h" +#include "xil_io.h" +#include "xstatus.h" + +/************************** Constant Definitions ****************************/ +#define MAX_NIBBLES 8U + +/************************** Function Prototypes *****************************/ +/****************************************************************************/ +/** + * Converts the char into the equivalent nibble. + * Ex: 'a' -> 0xa, 'A' -> 0xa, '9'->0x9 + * + * @param InChar is input character. It has to be between 0-9,a-f,A-F + * @param Num is the output nibble. + * + * @return + * - XST_SUCCESS no errors occured. + * - ERROR when input parameters are not valid + * + * @note None. + * + *****************************************************************************/ + +u32 Xil_ConvertCharToNibble(u8 InChar, u8 *Num) +{ + u32 Status; + + /* Convert the char to nibble */ + if ((InChar >= (u8)'0') && (InChar <= (u8)'9')) { + *Num = InChar - (u8)'0'; + Status = XST_SUCCESS; + } + else if ((InChar >= (u8)'a') && (InChar <= (u8)'f')) { + *Num = InChar - (u8)'a' + 10U; + Status = XST_SUCCESS; + } + else if ((InChar >= (u8)'A') && (InChar <= (u8)'F')) { + *Num = InChar - (u8)'A' + 10U; + Status = XST_SUCCESS; + } + else { + Status = XST_FAILURE; + } + + return Status; +} + +/****************************************************************************/ +/* + * Converts the string into the equivalent Hex buffer. + * Ex: "abc123" -> {0xab, 0xc1, 0x23} + * + * @param Str is a Input String. Will support the lower and upper + * case values. Value should be between 0-9, a-f and A-F + * + * @param Buf is Output buffer. + * @param Len of the input string. Should have even values + * + * @return + * - XST_SUCCESS no errors occured. + * - ERROR when input parameters are not valid + * - an error when input buffer has invalid values + * + * @note None. + * + *****************************************************************************/ +u32 Xil_ConvertStringToHex(const char *Str, u32 *buf, u8 Len) +{ + u32 Status = XST_FAILURE; + u8 ConvertedLen = 0U, index = 0U; + u8 Nibble[MAX_NIBBLES] = {0U}; + u8 i; + + while (ConvertedLen < Len) { + /* Convert char to nibble */ + for (i = 0U; i < MAX_NIBBLES; i++) { + Status = Xil_ConvertCharToNibble( + Str[ConvertedLen], &Nibble[i]); + ConvertedLen = ConvertedLen +1U; + if (Status != XST_SUCCESS) { + /* Error converting char to nibble */ + goto END; + } + } + + buf[index] = ((Nibble[0] << (u8)28U )| (Nibble[1] << (u8)24U) | + (Nibble[2] << (u8)20U) | (Nibble[3] << (u8)16U) | + (Nibble[4] << (u8)12U) | (Nibble[5] << (u8)8U)| + (Nibble[6] << (u8)4U) | (u32)Nibble[7]); + index++; + } +END: + return Status; +} + +/****************************************************************************/ +/* + * Waits for the event + * + * @param RegAddr Address of register to be checked for event(s) occurance + * @param EventMask Mask indicating event(s) to be checked + * @param Event Specific event(s) value to be checked + * @param Timeout Free counter decremented on each event(s) check and + * declared timeout when reaches 0 + * + * @return + * - XST_SUCCESS On occurance of the event(s). + * - XST_FAILURE Event did not occur before counter reaches 0 + * + * @note None. + * + *****************************************************************************/ +u32 Xil_WaitForEvent(u32 RegAddr, u32 EventMask, u32 Event, u32 Timeout) +{ + u32 RegVal; + u32 PollCount = Timeout; + u32 Status = XST_FAILURE; + + while(PollCount > 0) { + RegVal = Xil_In32(RegAddr) & EventMask; + if (RegVal == Event) { + Status = XST_SUCCESS; + break; + } + PollCount--; + } + + return Status; +} diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_util.h b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_util.h new file mode 100644 index 0000000..194c425 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_util.h @@ -0,0 +1,57 @@ +/******************************************************************************/ +/** +* Copyright (C) 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* @file xil_util.h +* +* This file contains xil utility functions declaration +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 6.4   mmd      04/21/19 First release.
+*
+* 
+* +*****************************************************************************/ + +#ifndef XIL_UTIL_H_ +#define XIL_UTIL_H_ + +/* Converts input character to nibble */ +u32 Xil_ConvertCharToNibble(u8 InChar, u8 *Num); + +/* Conver input hex string to array of 32-bits integers */ +u32 Xil_ConvertStringToHex(const char *Str, u32 *buf, u8 Len); + +/* Waits for specified event */ +u32 Xil_WaitForEvent(u32 RegAddr, u32 EventMask, u32 Event, u32 Timeout); + +#endif /* XIL_UTIL_H_ */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xl2cc.h b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xl2cc.h new file mode 100644 index 0000000..22373c1 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xl2cc.h @@ -0,0 +1,168 @@ +/****************************************************************************** +* +* Copyright (C) 2011 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file xl2cc.h +* +* This file contains the address definitions for the PL310 Level-2 Cache +* Controller. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- ---------------------------------------------------
+* 1.00a sdm  02/01/10 Initial version
+* 3.10a srt 04/18/13 Implemented ARM Erratas. Please refer to file
+*		      'xil_errata.h' for errata description
+* 
+* +* @note +* +* None. +* +******************************************************************************/ + +#ifndef _XL2CC_H_ +#define _XL2CC_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/************************** Constant Definitions *****************************/ +/* L2CC Register Offsets */ +#define XPS_L2CC_ID_OFFSET 0x0000U +#define XPS_L2CC_TYPE_OFFSET 0x0004U +#define XPS_L2CC_CNTRL_OFFSET 0x0100U +#define XPS_L2CC_AUX_CNTRL_OFFSET 0x0104U +#define XPS_L2CC_TAG_RAM_CNTRL_OFFSET 0x0108U +#define XPS_L2CC_DATA_RAM_CNTRL_OFFSET 0x010CU + +#define XPS_L2CC_EVNT_CNTRL_OFFSET 0x0200U +#define XPS_L2CC_EVNT_CNT1_CTRL_OFFSET 0x0204U +#define XPS_L2CC_EVNT_CNT0_CTRL_OFFSET 0x0208U +#define XPS_L2CC_EVNT_CNT1_VAL_OFFSET 0x020CU +#define XPS_L2CC_EVNT_CNT0_VAL_OFFSET 0x0210U + +#define XPS_L2CC_IER_OFFSET 0x0214U /* Interrupt Mask */ +#define XPS_L2CC_IPR_OFFSET 0x0218U /* Masked interrupt status */ +#define XPS_L2CC_ISR_OFFSET 0x021CU /* Raw Interrupt Status */ +#define XPS_L2CC_IAR_OFFSET 0x0220U /* Interrupt Clear */ + +#define XPS_L2CC_CACHE_SYNC_OFFSET 0x0730U /* Cache Sync */ +#define XPS_L2CC_DUMMY_CACHE_SYNC_OFFSET 0x0740U /* Dummy Register for Cache Sync */ +#define XPS_L2CC_CACHE_INVLD_PA_OFFSET 0x0770U /* Cache Invalid by PA */ +#define XPS_L2CC_CACHE_INVLD_WAY_OFFSET 0x077CU /* Cache Invalid by Way */ +#define XPS_L2CC_CACHE_CLEAN_PA_OFFSET 0x07B0U /* Cache Clean by PA */ +#define XPS_L2CC_CACHE_CLEAN_INDX_OFFSET 0x07B8U /* Cache Clean by Index */ +#define XPS_L2CC_CACHE_CLEAN_WAY_OFFSET 0x07BCU /* Cache Clean by Way */ +#define XPS_L2CC_CACHE_INV_CLN_PA_OFFSET 0x07F0U /* Cache Invalidate and Clean by PA */ +#define XPS_L2CC_CACHE_INV_CLN_INDX_OFFSET 0x07F8U /* Cache Invalidate and Clean by Index */ +#define XPS_L2CC_CACHE_INV_CLN_WAY_OFFSET 0x07FCU /* Cache Invalidate and Clean by Way */ + +#define XPS_L2CC_CACHE_DLCKDWN_0_WAY_OFFSET 0x0900U /* Cache Data Lockdown 0 by Way */ +#define XPS_L2CC_CACHE_ILCKDWN_0_WAY_OFFSET 0x0904U /* Cache Instruction Lockdown 0 by Way */ +#define XPS_L2CC_CACHE_DLCKDWN_1_WAY_OFFSET 0x0908U /* Cache Data Lockdown 1 by Way */ +#define XPS_L2CC_CACHE_ILCKDWN_1_WAY_OFFSET 0x090CU /* Cache Instruction Lockdown 1 by Way */ +#define XPS_L2CC_CACHE_DLCKDWN_2_WAY_OFFSET 0x0910U /* Cache Data Lockdown 2 by Way */ +#define XPS_L2CC_CACHE_ILCKDWN_2_WAY_OFFSET 0x0914U /* Cache Instruction Lockdown 2 by Way */ +#define XPS_L2CC_CACHE_DLCKDWN_3_WAY_OFFSET 0x0918U /* Cache Data Lockdown 3 by Way */ +#define XPS_L2CC_CACHE_ILCKDWN_3_WAY_OFFSET 0x091CU /* Cache Instruction Lockdown 3 by Way */ +#define XPS_L2CC_CACHE_DLCKDWN_4_WAY_OFFSET 0x0920U /* Cache Data Lockdown 4 by Way */ +#define XPS_L2CC_CACHE_ILCKDWN_4_WAY_OFFSET 0x0924U /* Cache Instruction Lockdown 4 by Way */ +#define XPS_L2CC_CACHE_DLCKDWN_5_WAY_OFFSET 0x0928U /* Cache Data Lockdown 5 by Way */ +#define XPS_L2CC_CACHE_ILCKDWN_5_WAY_OFFSET 0x092CU /* Cache Instruction Lockdown 5 by Way */ +#define XPS_L2CC_CACHE_DLCKDWN_6_WAY_OFFSET 0x0930U /* Cache Data Lockdown 6 by Way */ +#define XPS_L2CC_CACHE_ILCKDWN_6_WAY_OFFSET 0x0934U /* Cache Instruction Lockdown 6 by Way */ +#define XPS_L2CC_CACHE_DLCKDWN_7_WAY_OFFSET 0x0938U /* Cache Data Lockdown 7 by Way */ +#define XPS_L2CC_CACHE_ILCKDWN_7_WAY_OFFSET 0x093CU /* Cache Instruction Lockdown 7 by Way */ + +#define XPS_L2CC_CACHE_LCKDWN_LINE_ENABLE_OFFSET 0x0950U /* Cache Lockdown Line Enable */ +#define XPS_L2CC_CACHE_UUNLOCK_ALL_WAY_OFFSET 0x0954U /* Cache Unlock All Lines by Way */ + +#define XPS_L2CC_ADDR_FILTER_START_OFFSET 0x0C00U /* Start of address filtering */ +#define XPS_L2CC_ADDR_FILTER_END_OFFSET 0x0C04U /* Start of address filtering */ + +#define XPS_L2CC_DEBUG_CTRL_OFFSET 0x0F40U /* Debug Control Register */ + +/* XPS_L2CC_CNTRL_OFFSET bit masks */ +#define XPS_L2CC_ENABLE_MASK 0x00000001U /* enables the L2CC */ + +/* XPS_L2CC_AUX_CNTRL_OFFSET bit masks */ +#define XPS_L2CC_AUX_EBRESPE_MASK 0x40000000U /* Early BRESP Enable */ +#define XPS_L2CC_AUX_IPFE_MASK 0x20000000U /* Instruction Prefetch Enable */ +#define XPS_L2CC_AUX_DPFE_MASK 0x10000000U /* Data Prefetch Enable */ +#define XPS_L2CC_AUX_NSIC_MASK 0x08000000U /* Non-secure interrupt access control */ +#define XPS_L2CC_AUX_NSLE_MASK 0x04000000U /* Non-secure lockdown enable */ +#define XPS_L2CC_AUX_CRP_MASK 0x02000000U /* Cache replacement policy */ +#define XPS_L2CC_AUX_FWE_MASK 0x01800000U /* Force write allocate */ +#define XPS_L2CC_AUX_SAOE_MASK 0x00400000U /* Shared attribute override enable */ +#define XPS_L2CC_AUX_PE_MASK 0x00200000U /* Parity enable */ +#define XPS_L2CC_AUX_EMBE_MASK 0x00100000U /* Event monitor bus enable */ +#define XPS_L2CC_AUX_WAY_SIZE_MASK 0x000E0000U /* Way-size */ +#define XPS_L2CC_AUX_ASSOC_MASK 0x00010000U /* Associativity */ +#define XPS_L2CC_AUX_SAIE_MASK 0x00002000U /* Shared attribute invalidate enable */ +#define XPS_L2CC_AUX_EXCL_CACHE_MASK 0x00001000U /* Exclusive cache configuration */ +#define XPS_L2CC_AUX_SBDLE_MASK 0x00000800U /* Store buffer device limitation Enable */ +#define XPS_L2CC_AUX_HPSODRE_MASK 0x00000400U /* High Priority for SO and Dev Reads Enable */ +#define XPS_L2CC_AUX_FLZE_MASK 0x00000001U /* Full line of zero enable */ + +#define XPS_L2CC_AUX_REG_DEFAULT_MASK 0x72360000U /* Enable all prefetching, */ + /* Cache replacement policy, Parity enable, */ + /* Event monitor bus enable and Way Size (64 KB) */ +#define XPS_L2CC_AUX_REG_ZERO_MASK 0xFFF1FFFFU /* */ + +#define XPS_L2CC_TAG_RAM_DEFAULT_MASK 0x00000111U /* latency for TAG RAM */ +#define XPS_L2CC_DATA_RAM_DEFAULT_MASK 0x00000121U /* latency for DATA RAM */ + +/* Interrupt bit masks */ +#define XPS_L2CC_IXR_DECERR_MASK 0x00000100U /* DECERR from L3 */ +#define XPS_L2CC_IXR_SLVERR_MASK 0x00000080U /* SLVERR from L3 */ +#define XPS_L2CC_IXR_ERRRD_MASK 0x00000040U /* Error on L2 data RAM (Read) */ +#define XPS_L2CC_IXR_ERRRT_MASK 0x00000020U /* Error on L2 tag RAM (Read) */ +#define XPS_L2CC_IXR_ERRWD_MASK 0x00000010U /* Error on L2 data RAM (Write) */ +#define XPS_L2CC_IXR_ERRWT_MASK 0x00000008U /* Error on L2 tag RAM (Write) */ +#define XPS_L2CC_IXR_PARRD_MASK 0x00000004U /* Parity Error on L2 data RAM (Read) */ +#define XPS_L2CC_IXR_PARRT_MASK 0x00000002U /* Parity Error on L2 tag RAM (Read) */ +#define XPS_L2CC_IXR_ECNTR_MASK 0x00000001U /* Event Counter1/0 Overflow Increment */ + +/* Address filtering mask and enable bit */ +#define XPS_L2CC_ADDR_FILTER_VALID_MASK 0xFFF00000U /* Address filtering valid bits*/ +#define XPS_L2CC_ADDR_FILTER_ENABLE_MASK 0x00000001U /* Address filtering enable bit*/ + +/* Debug control bits */ +#define XPS_L2CC_DEBUG_SPIDEN_MASK 0x00000004U /* Debug SPIDEN bit */ +#define XPS_L2CC_DEBUG_DWB_MASK 0x00000002U /* Debug DWB bit, forces write through */ +#define XPS_L2CC_DEBUG_DCL_MASK 0x00000002U /* Debug DCL bit, disables cache line fill */ + +#ifdef __cplusplus +} +#endif + +#endif /* protection macro */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xl2cc_counter.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xl2cc_counter.c new file mode 100644 index 0000000..465be05 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xl2cc_counter.c @@ -0,0 +1,165 @@ +/****************************************************************************** +* +* Copyright (C) 2011 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xl2cc_counter.c +* +* This file contains APIs for configuring and controlling the event counters +* in PL310 L2 cache controller. For more information about the event counters, +* see xl2cc_counter.h. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a sdm  07/11/11 First release
+* 3.07a asa  08/30/12 Updated for CR 675636 to provide the L2 Base Address
+*		      inside the APIs
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include +#include "xparameters_ps.h" +#include "xl2cc_counter.h" +#include "xl2cc.h" + +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Variable Definitions *****************************/ + +/************************** Function Prototypes ******************************/ + +void XL2cc_EventCtrReset(void); + +/******************************************************************************/ + +/****************************************************************************/ +/** +* +* @brief This function initializes the event counters in L2 Cache controller +* with a set of event codes specified by the user. +* +* @param Event0: Event code for counter 0. +* @param Event1: Event code for counter 1. +* +* @return None. +* +* @note The definitions for event codes XL2CC_* can be found in +* xl2cc_counter.h. +* +*****************************************************************************/ +void XL2cc_EventCtrInit(s32 Event0, s32 Event1) +{ + + /* Write event code into cnt1 cfg reg */ + *((volatile u32*)(XPS_L2CC_BASEADDR + XPS_L2CC_EVNT_CNT1_CTRL_OFFSET)) = (((u32)Event1) << 2); + + /* Write event code into cnt0 cfg reg */ + *((volatile u32*)(XPS_L2CC_BASEADDR + XPS_L2CC_EVNT_CNT0_CTRL_OFFSET)) = (((u32)Event0) << 2); + + /* Reset counters */ + XL2cc_EventCtrReset(); +} + + +/****************************************************************************/ +/** +* +* @brief This function starts the event counters in L2 Cache controller. +* +* @param None. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XL2cc_EventCtrStart(void) +{ + u32 *LocalPtr; + LocalPtr = (u32 *)(XPS_L2CC_BASEADDR + XPS_L2CC_EVNT_CNTRL_OFFSET); + XL2cc_EventCtrReset(); + + /* Enable counter */ + /* *((volatile u32*)((void *)(XPS_L2CC_BASEADDR + XPS_L2CC_EVNT_CNTRL_OFFSET))) = 1 */ + *LocalPtr = (u32)1; +} + +/****************************************************************************/ +/** +* +* @brief This function disables the event counters in L2 Cache controller, +* saves the counter values and resets the counters. +* +* @param EveCtr0: Output parameter which is used to return the value +* in event counter 0. +* EveCtr1: Output parameter which is used to return the value +* in event counter 1. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XL2cc_EventCtrStop(u32 *EveCtr0, u32 *EveCtr1) +{ + /* Disable counter */ + *((volatile u32*) (XPS_L2CC_BASEADDR + XPS_L2CC_EVNT_CNTRL_OFFSET)) = 0U; + + /* Save counter values */ + *EveCtr1 = *((volatile u32*)(XPS_L2CC_BASEADDR + XPS_L2CC_EVNT_CNT1_VAL_OFFSET)); + *EveCtr0 = *((volatile u32*)(XPS_L2CC_BASEADDR + XPS_L2CC_EVNT_CNT0_VAL_OFFSET)); + + XL2cc_EventCtrReset(); +} + +/****************************************************************************/ +/** +* +* @brief This function resets the event counters in L2 Cache controller. +* +* @param None. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XL2cc_EventCtrReset(void) +{ + *((volatile u32*)(XPS_L2CC_BASEADDR + XPS_L2CC_EVNT_CNTRL_OFFSET)) = 0x6U; +} diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xl2cc_counter.h b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xl2cc_counter.h new file mode 100644 index 0000000..b8d768f --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xl2cc_counter.h @@ -0,0 +1,110 @@ +/****************************************************************************** +* +* Copyright (C) 2011 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xl2cc_counter.h +* +* @addtogroup l2_event_counter_apis PL310 L2 Event Counters Functions +* +* xl2cc_counter.h contains APIs for configuring and controlling the event +* counters in PL310 L2 cache controller. +* PL310 has two event counters which can be used to count variety of events +* like DRHIT, DRREQ, DWHIT, DWREQ, etc. xl2cc_counter.h contains definitions +* for different configurations which can be used for the event counters to +* count a set of events. +* +* +* @{ +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a sdm  07/11/11 First release
+* 3.07a asa  08/30/12 Updated for CR 675636 to provide the L2 Base Address
+*		      inside the APIs
+* 6.8   aru  09/06/18 Removed compilation warnings for ARMCC toolchain.
+* 
+* +******************************************************************************/ + +#ifndef L2CCCOUNTER_H /* prevent circular inclusions */ +#define L2CCCOUNTER_H /* by using protection macros */ + +/***************************** Include Files ********************************/ + +#include "xpseudo_asm.h" +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/************************** Constant Definitions ****************************/ + +/* + * The following constants define the event codes for the event counters. + */ +#define XL2CC_CO 0x1 +#define XL2CC_DRHIT 0x2 +#define XL2CC_DRREQ 0x3 +#define XL2CC_DWHIT 0x4 +#define XL2CC_DWREQ 0x5 +#define XL2CC_DWTREQ 0x6 +#define XL2CC_IRHIT 0x7 +#define XL2CC_IRREQ 0x8 +#define XL2CC_WA 0x9 +#define XL2CC_IPFALLOC 0xa +#define XL2CC_EPFHIT 0xb +#define XL2CC_EPFALLOC 0xc +#define XL2CC_SRRCVD 0xd +#define XL2CC_SRCONF 0xe +#define XL2CC_EPFRCVD 0xf + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Variable Definitions ****************************/ + +/************************** Function Prototypes *****************************/ + +void XL2cc_EventCtrInit(s32 Event0, s32 Event1); +void XL2cc_EventCtrStart(void); +void XL2cc_EventCtrStop(u32 *EveCtr0, u32 *EveCtr1); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* L2CCCOUNTER_H */ +/** +* @} End of "addtogroup l2_event_counter_apis". +*/ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xparameters_ps.h b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xparameters_ps.h new file mode 100644 index 0000000..2a6a0e0 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xparameters_ps.h @@ -0,0 +1,334 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2017 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file xparameters_ps.h +* +* This file contains the address definitions for the hard peripherals +* attached to the ARM Cortex A9 core. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who     Date     Changes
+* ----- ------- -------- ---------------------------------------------------
+* 1.00a ecm/sdm 02/01/10 Initial version
+* 3.04a sdm     02/02/12 Removed some of the defines as they are being generated through
+*                        driver tcl
+* 5.0	pkp		01/16/15 Added interrupt ID definition of ttc for TEST APP
+* 6.6   srm     10/18/17 Added ARMA9 macro to identify CortexA9
+*
+* 
+* +* @note +* +* None. +* +******************************************************************************/ + +#ifndef _XPARAMETERS_PS_H_ +#define _XPARAMETERS_PS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/**************************** Include Files *******************************/ + + +/************************** Constant Definitions *****************************/ + +/* + * This block contains constant declarations for the peripherals + * within the hardblock + */ + +/* Canonical definitions for DDR MEMORY */ +#define XPAR_DDR_MEM_BASEADDR 0x00000000U +#define XPAR_DDR_MEM_HIGHADDR 0x3FFFFFFFU + +/* Canonical definitions for Interrupts */ +#define XPAR_XUARTPS_0_INTR XPS_UART0_INT_ID +#define XPAR_XUARTPS_1_INTR XPS_UART1_INT_ID +#define XPAR_XUSBPS_0_INTR XPS_USB0_INT_ID +#define XPAR_XUSBPS_1_INTR XPS_USB1_INT_ID +#define XPAR_XIICPS_0_INTR XPS_I2C0_INT_ID +#define XPAR_XIICPS_1_INTR XPS_I2C1_INT_ID +#define XPAR_XSPIPS_0_INTR XPS_SPI0_INT_ID +#define XPAR_XSPIPS_1_INTR XPS_SPI1_INT_ID +#define XPAR_XCANPS_0_INTR XPS_CAN0_INT_ID +#define XPAR_XCANPS_1_INTR XPS_CAN1_INT_ID +#define XPAR_XGPIOPS_0_INTR XPS_GPIO_INT_ID +#define XPAR_XEMACPS_0_INTR XPS_GEM0_INT_ID +#define XPAR_XEMACPS_0_WAKE_INTR XPS_GEM0_WAKE_INT_ID +#define XPAR_XEMACPS_1_INTR XPS_GEM1_INT_ID +#define XPAR_XEMACPS_1_WAKE_INTR XPS_GEM1_WAKE_INT_ID +#define XPAR_XSDIOPS_0_INTR XPS_SDIO0_INT_ID +#define XPAR_XQSPIPS_0_INTR XPS_QSPI_INT_ID +#define XPAR_XSDIOPS_1_INTR XPS_SDIO1_INT_ID +#define XPAR_XWDTPS_0_INTR XPS_WDT_INT_ID +#define XPAR_XDCFG_0_INTR XPS_DVC_INT_ID +#define XPAR_SCUTIMER_INTR XPS_SCU_TMR_INT_ID +#define XPAR_SCUWDT_INTR XPS_SCU_WDT_INT_ID +#define XPAR_XTTCPS_0_INTR XPS_TTC0_0_INT_ID +#define XPAR_XTTCPS_1_INTR XPS_TTC0_1_INT_ID +#define XPAR_XTTCPS_2_INTR XPS_TTC0_2_INT_ID +#define XPAR_XTTCPS_3_INTR XPS_TTC1_0_INT_ID +#define XPAR_XTTCPS_4_INTR XPS_TTC1_1_INT_ID +#define XPAR_XTTCPS_5_INTR XPS_TTC1_2_INT_ID +#define XPAR_XDMAPS_0_FAULT_INTR XPS_DMA0_ABORT_INT_ID +#define XPAR_XDMAPS_0_DONE_INTR_0 XPS_DMA0_INT_ID +#define XPAR_XDMAPS_0_DONE_INTR_1 XPS_DMA1_INT_ID +#define XPAR_XDMAPS_0_DONE_INTR_2 XPS_DMA2_INT_ID +#define XPAR_XDMAPS_0_DONE_INTR_3 XPS_DMA3_INT_ID +#define XPAR_XDMAPS_0_DONE_INTR_4 XPS_DMA4_INT_ID +#define XPAR_XDMAPS_0_DONE_INTR_5 XPS_DMA5_INT_ID +#define XPAR_XDMAPS_0_DONE_INTR_6 XPS_DMA6_INT_ID +#define XPAR_XDMAPS_0_DONE_INTR_7 XPS_DMA7_INT_ID + + +#define XPAR_XQSPIPS_0_LINEAR_BASEADDR XPS_QSPI_LINEAR_BASEADDR +#define XPAR_XPARPORTPS_CTRL_BASEADDR XPS_PARPORT_CRTL_BASEADDR + + + +/* Canonical definitions for DMAC */ + + +/* Canonical definitions for WDT */ + +/* Canonical definitions for SLCR */ +#define XPAR_XSLCR_NUM_INSTANCES 1U +#define XPAR_XSLCR_0_DEVICE_ID 0U +#define XPAR_XSLCR_0_BASEADDR XPS_SYS_CTRL_BASEADDR + +/* Canonical definitions for SCU GIC */ +#define XPAR_SCUGIC_NUM_INSTANCES 1U +#define XPAR_SCUGIC_SINGLE_DEVICE_ID 0U +#define XPAR_SCUGIC_CPU_BASEADDR (XPS_SCU_PERIPH_BASE + 0x00000100U) +#define XPAR_SCUGIC_DIST_BASEADDR (XPS_SCU_PERIPH_BASE + 0x00001000U) +#define XPAR_SCUGIC_ACK_BEFORE 0U + +/* Canonical definitions for Global Timer */ +#define XPAR_GLOBAL_TMR_NUM_INSTANCES 1U +#define XPAR_GLOBAL_TMR_DEVICE_ID 0U +#define XPAR_GLOBAL_TMR_BASEADDR (XPS_SCU_PERIPH_BASE + 0x00000200U) +#define XPAR_GLOBAL_TMR_INTR XPS_GLOBAL_TMR_INT_ID + + +/* Xilinx Parallel Flash Library (XilFlash) User Settings */ +#define XPAR_AXI_EMC + + +#define XPAR_CPU_CORTEXA9_CORE_CLOCK_FREQ_HZ XPAR_CPU_CORTEXA9_0_CPU_CLK_FREQ_HZ + + +/* + * This block contains constant declarations for the peripherals + * within the hardblock. These have been put for bacwards compatibilty + */ + +#define XPS_PERIPHERAL_BASEADDR 0xE0000000U +#define XPS_UART0_BASEADDR 0xE0000000U +#define XPS_UART1_BASEADDR 0xE0001000U +#define XPS_USB0_BASEADDR 0xE0002000U +#define XPS_USB1_BASEADDR 0xE0003000U +#define XPS_I2C0_BASEADDR 0xE0004000U +#define XPS_I2C1_BASEADDR 0xE0005000U +#define XPS_SPI0_BASEADDR 0xE0006000U +#define XPS_SPI1_BASEADDR 0xE0007000U +#define XPS_CAN0_BASEADDR 0xE0008000U +#define XPS_CAN1_BASEADDR 0xE0009000U +#define XPS_GPIO_BASEADDR 0xE000A000U +#define XPS_GEM0_BASEADDR 0xE000B000U +#define XPS_GEM1_BASEADDR 0xE000C000U +#define XPS_QSPI_BASEADDR 0xE000D000U +#define XPS_PARPORT_CRTL_BASEADDR 0xE000E000U +#define XPS_SDIO0_BASEADDR 0xE0100000U +#define XPS_SDIO1_BASEADDR 0xE0101000U +#define XPS_IOU_BUS_CFG_BASEADDR 0xE0200000U +#define XPS_NAND_BASEADDR 0xE1000000U +#define XPS_PARPORT0_BASEADDR 0xE2000000U +#define XPS_PARPORT1_BASEADDR 0xE4000000U +#define XPS_QSPI_LINEAR_BASEADDR 0xFC000000U +#define XPS_SYS_CTRL_BASEADDR 0xF8000000U /* AKA SLCR */ +#define XPS_TTC0_BASEADDR 0xF8001000U +#define XPS_TTC1_BASEADDR 0xF8002000U +#define XPS_DMAC0_SEC_BASEADDR 0xF8003000U +#define XPS_DMAC0_NON_SEC_BASEADDR 0xF8004000U +#define XPS_WDT_BASEADDR 0xF8005000U +#define XPS_DDR_CTRL_BASEADDR 0xF8006000U +#define XPS_DEV_CFG_APB_BASEADDR 0xF8007000U +#define XPS_AFI0_BASEADDR 0xF8008000U +#define XPS_AFI1_BASEADDR 0xF8009000U +#define XPS_AFI2_BASEADDR 0xF800A000U +#define XPS_AFI3_BASEADDR 0xF800B000U +#define XPS_OCM_BASEADDR 0xF800C000U +#define XPS_EFUSE_BASEADDR 0xF800D000U +#define XPS_CORESIGHT_BASEADDR 0xF8800000U +#define XPS_TOP_BUS_CFG_BASEADDR 0xF8900000U +#define XPS_SCU_PERIPH_BASE 0xF8F00000U +#define XPS_L2CC_BASEADDR 0xF8F02000U +#define XPS_SAM_RAM_BASEADDR 0xFFFC0000U +#define XPS_FPGA_AXI_S0_BASEADDR 0x40000000U +#define XPS_FPGA_AXI_S1_BASEADDR 0x80000000U +#define XPS_IOU_S_SWITCH_BASEADDR 0xE0000000U +#define XPS_PERIPH_APB_BASEADDR 0xF8000000U + +/* Shared Peripheral Interrupts (SPI) */ +#define XPS_CORE_PARITY0_INT_ID 32U +#define XPS_CORE_PARITY1_INT_ID 33U +#define XPS_L2CC_INT_ID 34U +#define XPS_OCMINTR_INT_ID 35U +#define XPS_ECC_INT_ID 36U +#define XPS_PMU0_INT_ID 37U +#define XPS_PMU1_INT_ID 38U +#define XPS_SYSMON_INT_ID 39U +#define XPS_DVC_INT_ID 40U +#define XPS_WDT_INT_ID 41U +#define XPS_TTC0_0_INT_ID 42U +#define XPS_TTC0_1_INT_ID 43U +#define XPS_TTC0_2_INT_ID 44U +#define XPS_DMA0_ABORT_INT_ID 45U +#define XPS_DMA0_INT_ID 46U +#define XPS_DMA1_INT_ID 47U +#define XPS_DMA2_INT_ID 48U +#define XPS_DMA3_INT_ID 49U +#define XPS_SMC_INT_ID 50U +#define XPS_QSPI_INT_ID 51U +#define XPS_GPIO_INT_ID 52U +#define XPS_USB0_INT_ID 53U +#define XPS_GEM0_INT_ID 54U +#define XPS_GEM0_WAKE_INT_ID 55U +#define XPS_SDIO0_INT_ID 56U +#define XPS_I2C0_INT_ID 57U +#define XPS_SPI0_INT_ID 58U +#define XPS_UART0_INT_ID 59U +#define XPS_CAN0_INT_ID 60U +#define XPS_FPGA0_INT_ID 61U +#define XPS_FPGA1_INT_ID 62U +#define XPS_FPGA2_INT_ID 63U +#define XPS_FPGA3_INT_ID 64U +#define XPS_FPGA4_INT_ID 65U +#define XPS_FPGA5_INT_ID 66U +#define XPS_FPGA6_INT_ID 67U +#define XPS_FPGA7_INT_ID 68U +#define XPS_TTC1_0_INT_ID 69U +#define XPS_TTC1_1_INT_ID 70U +#define XPS_TTC1_2_INT_ID 71U +#define XPS_DMA4_INT_ID 72U +#define XPS_DMA5_INT_ID 73U +#define XPS_DMA6_INT_ID 74U +#define XPS_DMA7_INT_ID 75U +#define XPS_USB1_INT_ID 76U +#define XPS_GEM1_INT_ID 77U +#define XPS_GEM1_WAKE_INT_ID 78U +#define XPS_SDIO1_INT_ID 79U +#define XPS_I2C1_INT_ID 80U +#define XPS_SPI1_INT_ID 81U +#define XPS_UART1_INT_ID 82U +#define XPS_CAN1_INT_ID 83U +#define XPS_FPGA8_INT_ID 84U +#define XPS_FPGA9_INT_ID 85U +#define XPS_FPGA10_INT_ID 86U +#define XPS_FPGA11_INT_ID 87U +#define XPS_FPGA12_INT_ID 88U +#define XPS_FPGA13_INT_ID 89U +#define XPS_FPGA14_INT_ID 90U +#define XPS_FPGA15_INT_ID 91U + +/* Private Peripheral Interrupts (PPI) */ +#define XPS_GLOBAL_TMR_INT_ID 27U /* SCU Global Timer interrupt */ +#define XPS_FIQ_INT_ID 28U /* FIQ from FPGA fabric */ +#define XPS_SCU_TMR_INT_ID 29U /* SCU Private Timer interrupt */ +#define XPS_SCU_WDT_INT_ID 30U /* SCU Private WDT interrupt */ +#define XPS_IRQ_INT_ID 31U /* IRQ from FPGA fabric */ + + +/* REDEFINES for TEST APP */ +/* Definitions for UART */ +#define XPAR_PS7_UART_0_INTR XPS_UART0_INT_ID +#define XPAR_PS7_UART_1_INTR XPS_UART1_INT_ID +#define XPAR_PS7_USB_0_INTR XPS_USB0_INT_ID +#define XPAR_PS7_USB_1_INTR XPS_USB1_INT_ID +#define XPAR_PS7_I2C_0_INTR XPS_I2C0_INT_ID +#define XPAR_PS7_I2C_1_INTR XPS_I2C1_INT_ID +#define XPAR_PS7_SPI_0_INTR XPS_SPI0_INT_ID +#define XPAR_PS7_SPI_1_INTR XPS_SPI1_INT_ID +#define XPAR_PS7_CAN_0_INTR XPS_CAN0_INT_ID +#define XPAR_PS7_CAN_1_INTR XPS_CAN1_INT_ID +#define XPAR_PS7_GPIO_0_INTR XPS_GPIO_INT_ID +#define XPAR_PS7_ETHERNET_0_INTR XPS_GEM0_INT_ID +#define XPAR_PS7_ETHERNET_0_WAKE_INTR XPS_GEM0_WAKE_INT_ID +#define XPAR_PS7_ETHERNET_1_INTR XPS_GEM1_INT_ID +#define XPAR_PS7_ETHERNET_1_WAKE_INTR XPS_GEM1_WAKE_INT_ID +#define XPAR_PS7_QSPI_0_INTR XPS_QSPI_INT_ID +#define XPAR_PS7_WDT_0_INTR XPS_WDT_INT_ID +#define XPAR_PS7_SCUWDT_0_INTR XPS_SCU_WDT_INT_ID +#define XPAR_PS7_SCUTIMER_0_INTR XPS_SCU_TMR_INT_ID +#define XPAR_PS7_XADC_0_INTR XPS_SYSMON_INT_ID +#define XPAR_PS7_TTC_0_INTR XPS_TTC0_0_INT_ID +#define XPAR_PS7_TTC_1_INTR XPS_TTC0_1_INT_ID +#define XPAR_PS7_TTC_2_INTR XPS_TTC0_2_INT_ID +#define XPAR_PS7_TTC_3_INTR XPS_TTC1_0_INT_ID +#define XPAR_PS7_TTC_4_INTR XPS_TTC1_1_INT_ID +#define XPAR_PS7_TTC_5_INTR XPS_TTC1_2_INT_ID + +#define XPAR_XADCPS_INT_ID XPS_SYSMON_INT_ID + +/* For backwards compatibilty */ +#define XPAR_XUARTPS_0_CLOCK_HZ XPAR_XUARTPS_0_UART_CLK_FREQ_HZ +#define XPAR_XUARTPS_1_CLOCK_HZ XPAR_XUARTPS_1_UART_CLK_FREQ_HZ +#define XPAR_XTTCPS_0_CLOCK_HZ XPAR_XTTCPS_0_TTC_CLK_FREQ_HZ +#define XPAR_XTTCPS_1_CLOCK_HZ XPAR_XTTCPS_1_TTC_CLK_FREQ_HZ +#define XPAR_XTTCPS_2_CLOCK_HZ XPAR_XTTCPS_2_TTC_CLK_FREQ_HZ +#define XPAR_XTTCPS_3_CLOCK_HZ XPAR_XTTCPS_3_TTC_CLK_FREQ_HZ +#define XPAR_XTTCPS_4_CLOCK_HZ XPAR_XTTCPS_4_TTC_CLK_FREQ_HZ +#define XPAR_XTTCPS_5_CLOCK_HZ XPAR_XTTCPS_5_TTC_CLK_FREQ_HZ +#define XPAR_XIICPS_0_CLOCK_HZ XPAR_XIICPS_0_I2C_CLK_FREQ_HZ +#define XPAR_XIICPS_1_CLOCK_HZ XPAR_XIICPS_1_I2C_CLK_FREQ_HZ + +#define XPAR_XQSPIPS_0_CLOCK_HZ XPAR_XQSPIPS_0_QSPI_CLK_FREQ_HZ + +#ifdef XPAR_CPU_CORTEXA9_0_CPU_CLK_FREQ_HZ +#define XPAR_CPU_CORTEXA9_CORE_CLOCK_FREQ_HZ XPAR_CPU_CORTEXA9_0_CPU_CLK_FREQ_HZ +#endif + +#ifdef XPAR_CPU_CORTEXA9_1_CPU_CLK_FREQ_HZ +#define XPAR_CPU_CORTEXA9_CORE_CLOCK_FREQ_HZ XPAR_CPU_CORTEXA9_1_CPU_CLK_FREQ_HZ +#endif + +#define XPAR_SCUTIMER_DEVICE_ID 0U +#define XPAR_SCUWDT_DEVICE_ID 0U + + +#ifdef __cplusplus +} +#endif + +#endif /* protection macro */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xplatform_info.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xplatform_info.c new file mode 100644 index 0000000..03b1742 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xplatform_info.c @@ -0,0 +1,162 @@ +/****************************************************************************** +* +* Copyright (C) 2014 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xplatform_info.c +* +* This file contains information about hardware for which the code is built +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date   Changes
+* ----- ---- -------- -------------------------------------------------------
+* 5.00  pkp  12/15/14 Initial release
+* 5.04  pkp  01/12/16 Added platform information support for Cortex-A53 32bit
+*					  mode
+* 6.00  mus  17/08/16 Removed unused variable from XGetPlatform_Info
+* 6.4   ms   05/23/17 Added PSU_PMU macro to support XGetPSVersion_Info
+*                     function for PMUFW.
+*       ms   06/13/17 Added PSU_PMU macro to provide support of
+*                     XGetPlatform_Info function for PMUFW.
+*       mus  08/17/17 Add EL1 NS mode support for
+*                     XGet_Zynq_UltraMp_Platform_info and XGetPSVersion_Info
+*                     APIs.
+* 7.0	aru 03/15/19  Check for versal before aarch64 and armr5
+*		      in XGetPlatform_Info()
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_io.h" +#include "xplatform_info.h" +#if defined (__aarch64__) +#include "bspconfig.h" +#include "xil_smc.h" +#endif +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Variable Definitions *****************************/ + + +/************************** Function Prototypes ******************************/ + +/*****************************************************************************/ +/** +* +* @brief This API is used to provide information about platform +* +* @param None. +* +* @return The information about platform defined in xplatform_info.h +* +******************************************************************************/ +u32 XGetPlatform_Info() +{ +#if defined (versal) + return XPLAT_versal; +#elif defined (ARMR5) || (__aarch64__) || (ARMA53_32) || (PSU_PMU) + return XPLAT_ZYNQ_ULTRA_MP; +#elif (__microblaze__) + return XPLAT_MICROBLAZE; +#else + return XPLAT_ZYNQ; +#endif +} + +/*****************************************************************************/ +/** +* +* @brief This API is used to provide information about zynq ultrascale MP platform +* +* @param None. +* +* @return The information about zynq ultrascale MP platform defined in +* xplatform_info.h +* +******************************************************************************/ +#if defined (ARMR5) || (__aarch64__) || (ARMA53_32) +u32 XGet_Zynq_UltraMp_Platform_info() +{ +#if EL1_NONSECURE + XSmc_OutVar reg; + /* + * This SMC call will return, + * idcode - upper 32 bits of reg.Arg0 + * version - lower 32 bits of reg.Arg1 + */ + reg = Xil_Smc(GET_CHIPID_SMC_FID,0,0, 0, 0, 0, 0, 0); + return (u32)((reg.Arg1 >> XPLAT_INFO_SHIFT) & XPLAT_INFO_MASK); +#else + u32 reg; + reg = ((Xil_In32(XPLAT_PS_VERSION_ADDRESS) >> XPLAT_INFO_SHIFT ) + & XPLAT_INFO_MASK); + return reg; +#endif +} +#endif + +/*****************************************************************************/ +/** +* +* @brief This API is used to provide information about PS Silicon version +* +* @param None. +* +* @return The information about PS Silicon version. +* +******************************************************************************/ +#if defined (ARMR5) || (__aarch64__) || (ARMA53_32) || (PSU_PMU) +u32 XGetPSVersion_Info() +{ +#if EL1_NONSECURE + /* + * This SMC call will return, + * idcode - upper 32 bits of reg.Arg0 + * version - lower 32 bits of reg.Arg1 + */ + XSmc_OutVar reg; + reg = Xil_Smc(GET_CHIPID_SMC_FID,0,0, 0, 0, 0, 0, 0); + return (u32)((reg.Arg1 & XPS_VERSION_INFO_MASK) >> + XPS_VERSION_INFO_SHIFT); +#else + u32 reg; + reg = (Xil_In32(XPLAT_PS_VERSION_ADDRESS) + & XPS_VERSION_INFO_MASK); + return (reg >> XPS_VERSION_INFO_SHIFT); +#endif +} +#endif diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xplatform_info.h b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xplatform_info.h new file mode 100644 index 0000000..88851bb --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xplatform_info.h @@ -0,0 +1,120 @@ +/****************************************************************************** +* +* Copyright (C) 2014 - 2017 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xplatform_info.h +* +* @addtogroup common_platform_info APIs to Get Platform Information +* +* The xplatform_info.h file contains definitions for various available Xilinx® +* platforms. Also, it contains prototype of APIs, which can be used to get the +* platform information. +* +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date    Changes
+* ----- ---- --------- -------------------------------------------------------
+* 6.4    ms   05/23/17 Added PSU_PMU macro to support XGetPSVersion_Info
+*                      function for PMUFW.
+* 
+* +******************************************************************************/ + +#ifndef XPLATFORM_INFO_H /* prevent circular inclusions */ +#define XPLATFORM_INFO_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" + +/************************** Constant Definitions *****************************/ +#if defined (versal) +#define XPAR_PMC_TAP_BASEADDR 0xF11A0000U +#define XPAR_PMC_TAP_VERSION_OFFSET 0x00000004U +#define XPLAT_PS_VERSION_ADDRESS (XPAR_PMC_TAP_BASEADDR + \ + XPAR_PMC_TAP_VERSION_OFFSET) +#else +#define XPAR_CSU_BASEADDR 0xFFCA0000U +#define XPAR_CSU_VER_OFFSET 0x00000044U +#define XPLAT_PS_VERSION_ADDRESS (XPAR_CSU_BASEADDR + \ + XPAR_CSU_VER_OFFSET) +#endif +#define XPLAT_ZYNQ_ULTRA_MP_SILICON 0x0 +#define XPLAT_ZYNQ_ULTRA_MP 0x1 +#define XPLAT_ZYNQ_ULTRA_MPVEL 0x2 +#define XPLAT_ZYNQ_ULTRA_MPQEMU 0x3 +#define XPLAT_ZYNQ 0x4 +#define XPLAT_MICROBLAZE 0x5 +#define XPLAT_versal 0x6U + +#define XPS_VERSION_1 0x0 +#define XPS_VERSION_2 0x1 +#define XPLAT_INFO_MASK (0xF) + +#if defined (versal) +#define XPS_VERSION_INFO_MASK 0xFF00U +#define XPS_VERSION_INFO_SHIFT 0x8U +#define XPLAT_INFO_SHIFT 0x18U +#else +#define XPS_VERSION_INFO_MASK (0xF) +#define XPS_VERSION_INFO_SHIFT 0x0U +#define XPLAT_INFO_SHIFT 0xCU +#endif + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + + +u32 XGetPlatform_Info(void); + +#if defined (ARMR5) || (__aarch64__) || (ARMA53_32) || (PSU_PMU) +u32 XGetPSVersion_Info(); +#endif + +#if defined (ARMR5) || (__aarch64__) || (ARMA53_32) +u32 XGet_Zynq_UltraMp_Platform_info(); +#endif +/************************** Function Prototypes ******************************/ + + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** +* @} End of "addtogroup common_platform_info". +*/ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xpm_counter.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xpm_counter.c new file mode 100644 index 0000000..482671e --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xpm_counter.c @@ -0,0 +1,293 @@ +/****************************************************************************** +* +* Copyright (C) 2011 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xpm_counter.c +* +* This file contains APIs for configuring and controlling the Cortex-A9 +* Performance Monitor Events. For more information about the event counters, +* see xpm_counter.h. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a sdm  07/11/11 First release
+* 4.2	pkp	 07/21/14 Corrected reset value of event counter in function
+*					  Xpm_ResetEventCounters to fix CR#796275
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xpm_counter.h" + +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + +typedef const u32 PmcrEventCfg32[XPM_CTRCOUNT]; + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Variable Definitions *****************************/ + +/************************** Function Prototypes ******************************/ + +void Xpm_DisableEventCounters(void); +void Xpm_EnableEventCounters (void); +void Xpm_ResetEventCounters (void); + +/******************************************************************************/ + +/****************************************************************************/ +/** +* +* @brief This function disables the Cortex A9 event counters. +* +* @param None. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void Xpm_DisableEventCounters(void) +{ + /* Disable the event counters */ + mtcp(XREG_CP15_COUNT_ENABLE_CLR, 0x3f); +} + +/****************************************************************************/ +/** +* +* @brief This function enables the Cortex A9 event counters. +* +* @param None. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void Xpm_EnableEventCounters(void) +{ + /* Enable the event counters */ + mtcp(XREG_CP15_COUNT_ENABLE_SET, 0x3f); +} + +/****************************************************************************/ +/** +* +* @brief This function resets the Cortex A9 event counters. +* +* @param None. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void Xpm_ResetEventCounters(void) +{ + u32 Reg; +#ifdef __GNUC__ + Reg = mfcp(XREG_CP15_PERF_MONITOR_CTRL); +#elif defined (__ICCARM__) + mfcp(XREG_CP15_PERF_MONITOR_CTRL, Reg); +#else + { register u32 C15Reg __asm(XREG_CP15_PERF_MONITOR_CTRL); + Reg = C15Reg; } +#endif + Reg |= (1U << 1U); /* reset event counters */ + mtcp(XREG_CP15_PERF_MONITOR_CTRL, Reg); + +} + +/****************************************************************************/ +/** +* @brief This function configures the Cortex A9 event counters controller, +* with the event codes, in a configuration selected by the user and +* enables the counters. +* +* @param PmcrCfg: Configuration value based on which the event counters +* are configured. XPM_CNTRCFG* values defined in xpm_counter.h can +* be utilized for setting configuration. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void Xpm_SetEvents(s32 PmcrCfg) +{ + u32 Counter; + static PmcrEventCfg32 PmcrEvents[] = { + { + XPM_EVENT_SOFTINCR, + XPM_EVENT_INSRFETCH_CACHEREFILL, + XPM_EVENT_INSTRFECT_TLBREFILL, + XPM_EVENT_DATA_CACHEREFILL, + XPM_EVENT_DATA_CACHEACCESS, + XPM_EVENT_DATA_TLBREFILL + }, + { + XPM_EVENT_DATA_READS, + XPM_EVENT_DATA_WRITE, + XPM_EVENT_EXCEPTION, + XPM_EVENT_EXCEPRETURN, + XPM_EVENT_CHANGECONTEXT, + XPM_EVENT_SW_CHANGEPC + }, + { + XPM_EVENT_IMMEDBRANCH, + XPM_EVENT_UNALIGNEDACCESS, + XPM_EVENT_BRANCHMISS, + XPM_EVENT_CLOCKCYCLES, + XPM_EVENT_BRANCHPREDICT, + XPM_EVENT_JAVABYTECODE + }, + { + XPM_EVENT_SWJAVABYTECODE, + XPM_EVENT_JAVABACKBRANCH, + XPM_EVENT_COHERLINEMISS, + XPM_EVENT_COHERLINEHIT, + XPM_EVENT_INSTRSTALL, + XPM_EVENT_DATASTALL + }, + { + XPM_EVENT_MAINTLBSTALL, + XPM_EVENT_STREXPASS, + XPM_EVENT_STREXFAIL, + XPM_EVENT_DATAEVICT, + XPM_EVENT_NODISPATCH, + XPM_EVENT_ISSUEEMPTY + }, + { + XPM_EVENT_INSTRRENAME, + XPM_EVENT_PREDICTFUNCRET, + XPM_EVENT_MAINEXEC, + XPM_EVENT_SECEXEC, + XPM_EVENT_LDRSTR, + XPM_EVENT_FLOATRENAME + }, + { + XPM_EVENT_NEONRENAME, + XPM_EVENT_PLDSTALL, + XPM_EVENT_WRITESTALL, + XPM_EVENT_INSTRTLBSTALL, + XPM_EVENT_DATATLBSTALL, + XPM_EVENT_INSTR_uTLBSTALL + }, + { + XPM_EVENT_DATA_uTLBSTALL, + XPM_EVENT_DMB_STALL, + XPM_EVENT_INT_CLKEN, + XPM_EVENT_DE_CLKEN, + XPM_EVENT_INSTRISB, + XPM_EVENT_INSTRDSB + }, + { + XPM_EVENT_INSTRDMB, + XPM_EVENT_EXTINT, + XPM_EVENT_PLE_LRC, + XPM_EVENT_PLE_LRS, + XPM_EVENT_PLE_FLUSH, + XPM_EVENT_PLE_CMPL + }, + { + XPM_EVENT_PLE_OVFL, + XPM_EVENT_PLE_PROG, + XPM_EVENT_PLE_LRC, + XPM_EVENT_PLE_LRS, + XPM_EVENT_PLE_FLUSH, + XPM_EVENT_PLE_CMPL + }, + { + XPM_EVENT_DATASTALL, + XPM_EVENT_INSRFETCH_CACHEREFILL, + XPM_EVENT_INSTRFECT_TLBREFILL, + XPM_EVENT_DATA_CACHEREFILL, + XPM_EVENT_DATA_CACHEACCESS, + XPM_EVENT_DATA_TLBREFILL + }, + }; + const u32 *ptr = PmcrEvents[PmcrCfg]; + + Xpm_DisableEventCounters(); + + for(Counter = 0U; Counter < XPM_CTRCOUNT; Counter++) { + + /* Selecet event counter */ + mtcp(XREG_CP15_EVENT_CNTR_SEL, Counter); + + /* Set the event */ + mtcp(XREG_CP15_EVENT_TYPE_SEL, ptr[Counter]); + } + + Xpm_ResetEventCounters(); + Xpm_EnableEventCounters(); +} + +/****************************************************************************/ +/** +* +* @brief This function disables the event counters and returns the counter +* values. +* +* @param PmCtrValue: Pointer to an array of type u32 PmCtrValue[6]. +* It is an output parameter which is used to return the PM +* counter values. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void Xpm_GetEventCounters(u32 *PmCtrValue) +{ + u32 Counter; + + Xpm_DisableEventCounters(); + + for(Counter = 0U; Counter < XPM_CTRCOUNT; Counter++) { + + mtcp(XREG_CP15_EVENT_CNTR_SEL, Counter); +#ifdef __GNUC__ + PmCtrValue[Counter] = mfcp(XREG_CP15_PERF_MONITOR_COUNT); +#elif defined (__ICCARM__) + mfcp(XREG_CP15_PERF_MONITOR_COUNT, PmCtrValue[Counter]); +#else + { register u32 Cp15Reg __asm(XREG_CP15_PERF_MONITOR_COUNT); + PmCtrValue[Counter] = Cp15Reg; } +#endif + } +} diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xpm_counter.h b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xpm_counter.h new file mode 100644 index 0000000..39db7d8 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xpm_counter.h @@ -0,0 +1,572 @@ +/****************************************************************************** +* +* Copyright (C) 2011 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xpm_counter.h +* +* @addtogroup a9_event_counter_apis Cortex A9 Event Counters Functions +* +* Cortex A9 event counter functions can be utilized to configure and control +* the Cortex-A9 performance monitor events. +* +* Cortex-A9 performance monitor has six event counters which can be used to +* count a variety of events described in Coretx-A9 TRM. xpm_counter.h defines +* configurations XPM_CNTRCFGx which can be used to program the event counters +* to count a set of events. +* +* @note +* It doesn't handle the Cortex-A9 cycle counter, as the cycle counter is +* being used for time keeping. +* +* @{ +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a sdm  07/11/11 First release
+* 6.8   aru  09/06/18 Removed compilation warnings for ARMCC toolchain.
+* 
+* +******************************************************************************/ + +#ifndef XPMCOUNTER_H /* prevent circular inclusions */ +#define XPMCOUNTER_H /* by using protection macros */ + +/***************************** Include Files ********************************/ + +#include +#include "xpseudo_asm.h" +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/************************** Constant Definitions ****************************/ + +/* Number of performance counters */ +#define XPM_CTRCOUNT 6U + +/* The following constants define the Cortex-A9 Performance Monitor Events */ + +/* + * Software increment. The register is incremented only on writes to the + * Software Increment Register + */ +#define XPM_EVENT_SOFTINCR 0x00U + +/* + * Instruction fetch that causes a refill at (at least) the lowest level(s) of + * instruction or unified cache. Includes the speculative linefills in the + * count + */ +#define XPM_EVENT_INSRFETCH_CACHEREFILL 0x01U + +/* + * Instruction fetch that causes a TLB refill at (at least) the lowest level of + * TLB. Includes the speculative requests in the count + */ +#define XPM_EVENT_INSTRFECT_TLBREFILL 0x02U + +/* + * Data read or write operation that causes a refill at (at least) the lowest + * level(s)of data or unified cache. Counts the number of allocations performed + * in the Data Cache due to a read or a write + */ +#define XPM_EVENT_DATA_CACHEREFILL 0x03U + +/* + * Data read or write operation that causes a cache access at (at least) the + * lowest level(s) of data or unified cache. This includes speculative reads + */ +#define XPM_EVENT_DATA_CACHEACCESS 0x04U + +/* + * Data read or write operation that causes a TLB refill at (at least) the + * lowest level of TLB. This does not include micro TLB misses due to PLD, PLI, + * CP15 Cache operation by MVA and CP15 VA to PA operations + */ +#define XPM_EVENT_DATA_TLBREFILL 0x05U + +/* + * Data read architecturally executed. Counts the number of data read + * instructions accepted by the Load Store Unit. This includes counting the + * speculative and aborted LDR/LDM, as well as the reads due to the SWP + * instructions + */ +#define XPM_EVENT_DATA_READS 0x06U + +/* + * Data write architecturally executed. Counts the number of data write + * instructions accepted by the Load Store Unit. This includes counting the + * speculative and aborted STR/STM, as well as the writes due to the SWP + * instructions + */ +#define XPM_EVENT_DATA_WRITE 0x07U + +/* Exception taken. Counts the number of exceptions architecturally taken.*/ +#define XPM_EVENT_EXCEPTION 0x09U + +/* Exception return architecturally executed.*/ +#define XPM_EVENT_EXCEPRETURN 0x0AU + +/* + * Change to ContextID retired. Counts the number of instructions + * architecturally executed writing into the ContextID Register + */ +#define XPM_EVENT_CHANGECONTEXT 0x0BU + +/* + * Software change of PC, except by an exception, architecturally executed. + * Count the number of PC changes architecturally executed, excluding the PC + * changes due to taken exceptions + */ +#define XPM_EVENT_SW_CHANGEPC 0x0CU + +/* + * Immediate branch architecturally executed (taken or not taken). This includes + * the branches which are flushed due to a previous load/store which aborts + * late + */ +#define XPM_EVENT_IMMEDBRANCH 0x0DU + +/* + * Unaligned access architecturally executed. Counts the number of aborted + * unaligned accessed architecturally executed, and the number of not-aborted + * unaligned accesses, including the speculative ones + */ +#define XPM_EVENT_UNALIGNEDACCESS 0x0FU + +/* + * Branch mispredicted/not predicted. Counts the number of mispredicted or + * not-predicted branches executed. This includes the branches which are flushed + * due to a previous load/store which aborts late + */ +#define XPM_EVENT_BRANCHMISS 0x10U + +/* + * Counts clock cycles when the Cortex-A9 processor is not in WFE/WFI. This + * event is not exported on the PMUEVENT bus + */ +#define XPM_EVENT_CLOCKCYCLES 0x11U + +/* + * Branches or other change in program flow that could have been predicted by + * the branch prediction resources of the processor. This includes the branches + * which are flushed due to a previous load/store which aborts late + */ +#define XPM_EVENT_BRANCHPREDICT 0x12U + +/* + * Java bytecode execute. Counts the number of Java bytecodes being decoded, + * including speculative ones + */ +#define XPM_EVENT_JAVABYTECODE 0x40U + +/* + * Software Java bytecode executed. Counts the number of software java bytecodes + * being decoded, including speculative ones + */ +#define XPM_EVENT_SWJAVABYTECODE 0x41U + +/* + * Jazelle backward branches executed. Counts the number of Jazelle taken + * branches being executed. This includes the branches which are flushed due + * to a previous load/store which aborts late + */ +#define XPM_EVENT_JAVABACKBRANCH 0x42U + +/* + * Coherent linefill miss Counts the number of coherent linefill requests + * performed by the Cortex-A9 processor which also miss in all the other + * Cortex-A9 processors, meaning that the request is sent to the external + * memory + */ +#define XPM_EVENT_COHERLINEMISS 0x50U + +/* + * Coherent linefill hit. Counts the number of coherent linefill requests + * performed by the Cortex-A9 processor which hit in another Cortex-A9 + * processor, meaning that the linefill data is fetched directly from the + * relevant Cortex-A9 cache + */ +#define XPM_EVENT_COHERLINEHIT 0x51U + +/* + * Instruction cache dependent stall cycles. Counts the number of cycles where + * the processor is ready to accept new instructions, but does not receive any + * due to the instruction side not being able to provide any and the + * instruction cache is currently performing at least one linefill + */ +#define XPM_EVENT_INSTRSTALL 0x60U + +/* + * Data cache dependent stall cycles. Counts the number of cycles where the core + * has some instructions that it cannot issue to any pipeline, and the Load + * Store unit has at least one pending linefill request, and no pending + */ +#define XPM_EVENT_DATASTALL 0x61U + +/* + * Main TLB miss stall cycles. Counts the number of cycles where the processor + * is stalled waiting for the completion of translation table walks from the + * main TLB. The processor stalls can be due to the instruction side not being + * able to provide the instructions, or to the data side not being able to + * provide the necessary data, due to them waiting for the main TLB translation + * table walk to complete + */ +#define XPM_EVENT_MAINTLBSTALL 0x62U + +/* + * Counts the number of STREX instructions architecturally executed and + * passed + */ +#define XPM_EVENT_STREXPASS 0x63U + +/* + * Counts the number of STREX instructions architecturally executed and + * failed + */ +#define XPM_EVENT_STREXFAIL 0x64U + +/* + * Data eviction. Counts the number of eviction requests due to a linefill in + * the data cache + */ +#define XPM_EVENT_DATAEVICT 0x65U + +/* + * Counts the number of cycles where the issue stage does not dispatch any + * instruction because it is empty or cannot dispatch any instructions + */ +#define XPM_EVENT_NODISPATCH 0x66U + +/* + * Counts the number of cycles where the issue stage is empty + */ +#define XPM_EVENT_ISSUEEMPTY 0x67U + +/* + * Counts the number of instructions going through the Register Renaming stage. + * This number is an approximate number of the total number of instructions + * speculatively executed, and even more approximate of the total number of + * instructions architecturally executed. The approximation depends mainly on + * the branch misprediction rate. + * The renaming stage can handle two instructions in the same cycle so the event + * is two bits long: + * - b00 no instructions renamed + * - b01 one instruction renamed + * - b10 two instructions renamed + */ +#define XPM_EVENT_INSTRRENAME 0x68U + +/* + * Counts the number of procedure returns whose condition codes do not fail, + * excluding all returns from exception. This count includes procedure returns + * which are flushed due to a previous load/store which aborts late. + * Only the following instructions are reported: + * - BX R14 + * - MOV PC LR + * - POP {..,pc} + * - LDR pc,[sp],#offset + * The following instructions are not reported: + * - LDMIA R9!,{..,PC} (ThumbEE state only) + * - LDR PC,[R9],#offset (ThumbEE state only) + * - BX R0 (Rm != R14) + * - MOV PC,R0 (Rm != R14) + * - LDM SP,{...,PC} (writeback not specified) + * - LDR PC,[SP,#offset] (wrong addressing mode) + */ +#define XPM_EVENT_PREDICTFUNCRET 0x6EU + +/* + * Counts the number of instructions being executed in the main execution + * pipeline of the processor, the multiply pipeline and arithmetic logic unit + * pipeline. The counted instructions are still speculative + */ +#define XPM_EVENT_MAINEXEC 0x70U + +/* + * Counts the number of instructions being executed in the processor second + * execution pipeline (ALU). The counted instructions are still speculative + */ +#define XPM_EVENT_SECEXEC 0x71U + +/* + * Counts the number of instructions being executed in the Load/Store unit. The + * counted instructions are still speculative + */ +#define XPM_EVENT_LDRSTR 0x72U + +/* + * Counts the number of Floating-point instructions going through the Register + * Rename stage. Instructions are still speculative in this stage. + *Two floating-point instructions can be renamed in the same cycle so the event + * is two bitslong: + *0b00 no floating-point instruction renamed + *0b01 one floating-point instruction renamed + *0b10 two floating-point instructions renamed + */ +#define XPM_EVENT_FLOATRENAME 0x73U + +/* + * Counts the number of Neon instructions going through the Register Rename + * stage.Instructions are still speculative in this stage. + * Two NEON instructions can be renamed in the same cycle so the event is two + * bits long: + *0b00 no NEON instruction renamed + *0b01 one NEON instruction renamed + *0b10 two NEON instructions renamed + */ +#define XPM_EVENT_NEONRENAME 0x74U + +/* + * Counts the number of cycles where the processor is stalled because PLD slots + * are all full + */ +#define XPM_EVENT_PLDSTALL 0x80U + +/* + * Counts the number of cycles when the processor is stalled and the data side + * is stalled too because it is full and executing writes to the external + * memory + */ +#define XPM_EVENT_WRITESTALL 0x81U + +/* + * Counts the number of stall cycles due to main TLB misses on requests issued + * by the instruction side + */ +#define XPM_EVENT_INSTRTLBSTALL 0x82U + +/* + * Counts the number of stall cycles due to main TLB misses on requests issued + * by the data side + */ +#define XPM_EVENT_DATATLBSTALL 0x83U + +/* + * Counts the number of stall cycles due to micro TLB misses on the instruction + * side. This event does not include main TLB miss stall cycles that are already + * counted in the corresponding main TLB event + */ +#define XPM_EVENT_INSTR_uTLBSTALL 0x84U + +/* + * Counts the number of stall cycles due to micro TLB misses on the data side. + * This event does not include main TLB miss stall cycles that are already + * counted in the corresponding main TLB event + */ +#define XPM_EVENT_DATA_uTLBSTALL 0x85U + +/* + * Counts the number of stall cycles because of the execution of a DMB memory + * barrier. This includes all DMB instructions being executed, even + * speculatively + */ +#define XPM_EVENT_DMB_STALL 0x86U + +/* + * Counts the number of cycles during which the integer core clock is enabled + */ +#define XPM_EVENT_INT_CLKEN 0x8AU + +/* + * Counts the number of cycles during which the Data Engine clock is enabled + */ +#define XPM_EVENT_DE_CLKEN 0x8BU + +/* + * Counts the number of ISB instructions architecturally executed + */ +#define XPM_EVENT_INSTRISB 0x90U + +/* + * Counts the number of DSB instructions architecturally executed + */ +#define XPM_EVENT_INSTRDSB 0x91U + +/* + * Counts the number of DMB instructions speculatively executed + */ +#define XPM_EVENT_INSTRDMB 0x92U + +/* + * Counts the number of external interrupts executed by the processor + */ +#define XPM_EVENT_EXTINT 0x93U + +/* + * PLE cache line request completed + */ +#define XPM_EVENT_PLE_LRC 0xA0U + +/* + * PLE cache line request skipped + */ +#define XPM_EVENT_PLE_LRS 0xA1U + +/* + * PLE FIFO flush + */ +#define XPM_EVENT_PLE_FLUSH 0xA2U + +/* + * PLE request complete + */ +#define XPM_EVENT_PLE_CMPL 0xA3U + +/* + * PLE FIFO overflow + */ +#define XPM_EVENT_PLE_OVFL 0xA4U + +/* + * PLE request programmed + */ +#define XPM_EVENT_PLE_PROG 0xA5U + +/* + * The following constants define the configurations for Cortex-A9 Performance + * Monitor Events. Each configuration configures the event counters for a set + * of events. + * ----------------------------------------------- + * Config PmCtr0... PmCtr5 + * ----------------------------------------------- + * XPM_CNTRCFG1 { XPM_EVENT_SOFTINCR, + * XPM_EVENT_INSRFETCH_CACHEREFILL, + * XPM_EVENT_INSTRFECT_TLBREFILL, + * XPM_EVENT_DATA_CACHEREFILL, + * XPM_EVENT_DATA_CACHEACCESS, + * XPM_EVENT_DATA_TLBREFILL } + * + * XPM_CNTRCFG2 { XPM_EVENT_DATA_READS, + * XPM_EVENT_DATA_WRITE, + * XPM_EVENT_EXCEPTION, + * XPM_EVENT_EXCEPRETURN, + * XPM_EVENT_CHANGECONTEXT, + * XPM_EVENT_SW_CHANGEPC } + * + * XPM_CNTRCFG3 { XPM_EVENT_IMMEDBRANCH, + * XPM_EVENT_UNALIGNEDACCESS, + * XPM_EVENT_BRANCHMISS, + * XPM_EVENT_CLOCKCYCLES, + * XPM_EVENT_BRANCHPREDICT, + * XPM_EVENT_JAVABYTECODE } + * + * XPM_CNTRCFG4 { XPM_EVENT_SWJAVABYTECODE, + * XPM_EVENT_JAVABACKBRANCH, + * XPM_EVENT_COHERLINEMISS, + * XPM_EVENT_COHERLINEHIT, + * XPM_EVENT_INSTRSTALL, + * XPM_EVENT_DATASTALL } + * + * XPM_CNTRCFG5 { XPM_EVENT_MAINTLBSTALL, + * XPM_EVENT_STREXPASS, + * XPM_EVENT_STREXFAIL, + * XPM_EVENT_DATAEVICT, + * XPM_EVENT_NODISPATCH, + * XPM_EVENT_ISSUEEMPTY } + * + * XPM_CNTRCFG6 { XPM_EVENT_INSTRRENAME, + * XPM_EVENT_PREDICTFUNCRET, + * XPM_EVENT_MAINEXEC, + * XPM_EVENT_SECEXEC, + * XPM_EVENT_LDRSTR, + * XPM_EVENT_FLOATRENAME } + * + * XPM_CNTRCFG7 { XPM_EVENT_NEONRENAME, + * XPM_EVENT_PLDSTALL, + * XPM_EVENT_WRITESTALL, + * XPM_EVENT_INSTRTLBSTALL, + * XPM_EVENT_DATATLBSTALL, + * XPM_EVENT_INSTR_uTLBSTALL } + * + * XPM_CNTRCFG8 { XPM_EVENT_DATA_uTLBSTALL, + * XPM_EVENT_DMB_STALL, + * XPM_EVENT_INT_CLKEN, + * XPM_EVENT_DE_CLKEN, + * XPM_EVENT_INSTRISB, + * XPM_EVENT_INSTRDSB } + * + * XPM_CNTRCFG9 { XPM_EVENT_INSTRDMB, + * XPM_EVENT_EXTINT, + * XPM_EVENT_PLE_LRC, + * XPM_EVENT_PLE_LRS, + * XPM_EVENT_PLE_FLUSH, + * XPM_EVENT_PLE_CMPL } + * + * XPM_CNTRCFG10 { XPM_EVENT_PLE_OVFL, + * XPM_EVENT_PLE_PROG, + * XPM_EVENT_PLE_LRC, + * XPM_EVENT_PLE_LRS, + * XPM_EVENT_PLE_FLUSH, + * XPM_EVENT_PLE_CMPL } + * + * XPM_CNTRCFG11 { XPM_EVENT_DATASTALL, + * XPM_EVENT_INSRFETCH_CACHEREFILL, + * XPM_EVENT_INSTRFECT_TLBREFILL, + * XPM_EVENT_DATA_CACHEREFILL, + * XPM_EVENT_DATA_CACHEACCESS, + * XPM_EVENT_DATA_TLBREFILL } + */ +#define XPM_CNTRCFG1 0 +#define XPM_CNTRCFG2 1 +#define XPM_CNTRCFG3 2 +#define XPM_CNTRCFG4 3 +#define XPM_CNTRCFG5 4 +#define XPM_CNTRCFG6 5 +#define XPM_CNTRCFG7 6 +#define XPM_CNTRCFG8 7 +#define XPM_CNTRCFG9 8 +#define XPM_CNTRCFG10 9 +#define XPM_CNTRCFG11 10 + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Variable Definitions ****************************/ + +/************************** Function Prototypes *****************************/ + +/* Interface fuctions to access perfromance counters from abstraction layer */ +void Xpm_SetEvents(s32 PmcrCfg); +void Xpm_GetEventCounters(u32 *PmCtrValue); + +#ifdef __cplusplus +} +#endif + +#endif +/** +* @} End of "addtogroup a9_event_counter_apis". +*/ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xpseudo_asm.h b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xpseudo_asm.h new file mode 100644 index 0000000..c7123a0 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xpseudo_asm.h @@ -0,0 +1,82 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xpseudo_asm.h +* +* @addtogroup a9_specific Cortex A9 Processor Specific Include Files +* +* The xpseudo_asm.h includes xreg_cortexa9.h and xpseudo_asm_gcc.h. +* +* The xreg_cortexa9.h file contains definitions for inline assembler code. +* It provides inline definitions for Cortex A9 GPRs, SPRs, MPE registers, +* co-processor registers and Debug registers. +* +* The xpseudo_asm_gcc.h contains the definitions for the most often used inline +* assembler instructions, available as macros. These can be very useful for +* tasks such as setting or getting special purpose registers, synchronization, +* or cache manipulation etc. These inline assembler instructions can be used +* from drivers and user applications written in C. +* +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a ecm  10/18/09 First release
+* 3.04a sdm  01/02/12 Remove redundant dsb in mcr instruction.
+* 6.8   aru  09/06/18 Removed compilation warnings for ARMCC toolchain.
+* 
+* +******************************************************************************/ +#ifndef XPSEUDO_ASM_H +#define XPSEUDO_ASM_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "xreg_cortexa9.h" +#ifdef __GNUC__ + #include "xpseudo_asm_gcc.h" +#elif defined (__ICCARM__) + #include "xpseudo_asm_iccarm.h" +#else + #include "xpseudo_asm_rvct.h" +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* XPSEUDO_ASM_H */ +/** +* @} End of "addtogroup a9_specific". +*/ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xpseudo_asm_gcc.h b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xpseudo_asm_gcc.h new file mode 100644 index 0000000..85b067d --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xpseudo_asm_gcc.h @@ -0,0 +1,252 @@ +/****************************************************************************** +* +* Copyright (C) 2014 - 2016 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xpseudo_asm_gcc.h +* +* This header file contains macros for using inline assembler code. It is +* written specifically for the GNU compiler. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 5.00 	pkp		 05/21/14 First release
+* 6.0   mus      07/27/16 Consolidated file for a53,a9 and r5 processors
+* 
+* +******************************************************************************/ + +#ifndef XPSEUDO_ASM_GCC_H /* prevent circular inclusions */ +#define XPSEUDO_ASM_GCC_H /* by using protection macros */ + +/***************************** Include Files ********************************/ + +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/* necessary for pre-processor */ +#define stringify(s) tostring(s) +#define tostring(s) #s + +#if defined (__aarch64__) +/* pseudo assembler instructions */ +#define mfcpsr() ({u32 rval = 0U; \ + asm volatile("mrs %0, DAIF" : "=r" (rval));\ + rval;\ + }) + +#define mtcpsr(v) __asm__ __volatile__ ("msr DAIF, %0" : : "r" (v)) + +#define cpsiei() //__asm__ __volatile__("cpsie i\n") +#define cpsidi() //__asm__ __volatile__("cpsid i\n") + +#define cpsief() //__asm__ __volatile__("cpsie f\n") +#define cpsidf() //__asm__ __volatile__("cpsid f\n") + + + +#define mtgpr(rn, v) /*__asm__ __volatile__(\ + "mov r" stringify(rn) ", %0 \n"\ + : : "r" (v)\ + )*/ + +#define mfgpr(rn) /*({u32 rval; \ + __asm__ __volatile__(\ + "mov %0,r" stringify(rn) "\n"\ + : "=r" (rval)\ + );\ + rval;\ + })*/ + +/* memory synchronization operations */ + +/* Instruction Synchronization Barrier */ +#define isb() __asm__ __volatile__ ("isb sy") + +/* Data Synchronization Barrier */ +#define dsb() __asm__ __volatile__("dsb sy") + +/* Data Memory Barrier */ +#define dmb() __asm__ __volatile__("dmb sy") + + +/* Memory Operations */ +#define ldr(adr) ({u64 rval; \ + __asm__ __volatile__(\ + "ldr %0,[%1]"\ + : "=r" (rval) : "r" (adr)\ + );\ + rval;\ + }) + +#define mfelrel3() ({u64 rval = 0U; \ + asm volatile("mrs %0, ELR_EL3" : "=r" (rval));\ + rval;\ + }) + +#define mtelrel3(v) __asm__ __volatile__ ("msr ELR_EL3, %0" : : "r" (v)) + +#else + +/* pseudo assembler instructions */ +#define mfcpsr() ({u32 rval = 0U; \ + __asm__ __volatile__(\ + "mrs %0, cpsr\n"\ + : "=r" (rval)\ + );\ + rval;\ + }) + +#define mtcpsr(v) __asm__ __volatile__(\ + "msr cpsr,%0\n"\ + : : "r" (v)\ + ) + +#define cpsiei() __asm__ __volatile__("cpsie i\n") +#define cpsidi() __asm__ __volatile__("cpsid i\n") + +#define cpsief() __asm__ __volatile__("cpsie f\n") +#define cpsidf() __asm__ __volatile__("cpsid f\n") + + + +#define mtgpr(rn, v) __asm__ __volatile__(\ + "mov r" stringify(rn) ", %0 \n"\ + : : "r" (v)\ + ) + +#define mfgpr(rn) ({u32 rval; \ + __asm__ __volatile__(\ + "mov %0,r" stringify(rn) "\n"\ + : "=r" (rval)\ + );\ + rval;\ + }) + +/* memory synchronization operations */ + +/* Instruction Synchronization Barrier */ +#define isb() __asm__ __volatile__ ("isb" : : : "memory") + +/* Data Synchronization Barrier */ +#define dsb() __asm__ __volatile__ ("dsb" : : : "memory") + +/* Data Memory Barrier */ +#define dmb() __asm__ __volatile__ ("dmb" : : : "memory") + + +/* Memory Operations */ +#define ldr(adr) ({u32 rval; \ + __asm__ __volatile__(\ + "ldr %0,[%1]"\ + : "=r" (rval) : "r" (adr)\ + );\ + rval;\ + }) + +#endif + +#define ldrb(adr) ({u8 rval; \ + __asm__ __volatile__(\ + "ldrb %0,[%1]"\ + : "=r" (rval) : "r" (adr)\ + );\ + rval;\ + }) + +#define str(adr, val) __asm__ __volatile__(\ + "str %0,[%1]\n"\ + : : "r" (val), "r" (adr)\ + ) + +#define strb(adr, val) __asm__ __volatile__(\ + "strb %0,[%1]\n"\ + : : "r" (val), "r" (adr)\ + ) + +/* Count leading zeroes (clz) */ +#define clz(arg) ({u8 rval; \ + __asm__ __volatile__(\ + "clz %0,%1"\ + : "=r" (rval) : "r" (arg)\ + );\ + rval;\ + }) + +#if defined (__aarch64__) +#define mtcpdc(reg,val) __asm__ __volatile__("dc " #reg ",%0" : : "r" (val)) +#define mtcpic(reg,val) __asm__ __volatile__("ic " #reg ",%0" : : "r" (val)) + +#define mtcpicall(reg) __asm__ __volatile__("ic " #reg) +#define mtcptlbi(reg) __asm__ __volatile__("tlbi " #reg) +#define mtcpat(reg,val) __asm__ __volatile__("at " #reg ",%0" : : "r" (val)) +/* CP15 operations */ +#define mfcp(reg) ({u64 rval = 0U;\ + __asm__ __volatile__("mrs %0, " #reg : "=r" (rval));\ + rval;\ + }) + +#define mtcp(reg,val) __asm__ __volatile__("msr " #reg ",%0" : : "r" (val)) + +#else +/* CP15 operations */ +#define mtcp(rn, v) __asm__ __volatile__(\ + "mcr " rn "\n"\ + : : "r" (v)\ + ); + +#define mfcp(rn) ({u32 rval = 0U; \ + __asm__ __volatile__(\ + "mrc " rn "\n"\ + : "=r" (rval)\ + );\ + rval;\ + }) +#endif + +/************************** Variable Definitions ****************************/ + +/************************** Function Prototypes *****************************/ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* XPSEUDO_ASM_GCC_H */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xreg_cortexa9.h b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xreg_cortexa9.h new file mode 100644 index 0000000..ad93665 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xreg_cortexa9.h @@ -0,0 +1,587 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xreg_cortexa9.h +* +* This header file contains definitions for using inline assembler code. It is +* written specifically for the GNU, ARMCC compiler. +* +* All of the ARM Cortex A9 GPRs, SPRs, and Debug Registers are defined along +* with the positions of the bits within the registers. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 1.00a ecm/sdm  10/20/09 First release
+* 
+* +******************************************************************************/ +#ifndef XREG_CORTEXA9_H +#define XREG_CORTEXA9_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* GPRs */ +#define XREG_GPR0 r0 +#define XREG_GPR1 r1 +#define XREG_GPR2 r2 +#define XREG_GPR3 r3 +#define XREG_GPR4 r4 +#define XREG_GPR5 r5 +#define XREG_GPR6 r6 +#define XREG_GPR7 r7 +#define XREG_GPR8 r8 +#define XREG_GPR9 r9 +#define XREG_GPR10 r10 +#define XREG_GPR11 r11 +#define XREG_GPR12 r12 +#define XREG_GPR13 r13 +#define XREG_GPR14 r14 +#define XREG_GPR15 r15 +#define XREG_CPSR cpsr + +/* Coprocessor number defines */ +#define XREG_CP0 0 +#define XREG_CP1 1 +#define XREG_CP2 2 +#define XREG_CP3 3 +#define XREG_CP4 4 +#define XREG_CP5 5 +#define XREG_CP6 6 +#define XREG_CP7 7 +#define XREG_CP8 8 +#define XREG_CP9 9 +#define XREG_CP10 10 +#define XREG_CP11 11 +#define XREG_CP12 12 +#define XREG_CP13 13 +#define XREG_CP14 14 +#define XREG_CP15 15 + +/* Coprocessor control register defines */ +#define XREG_CR0 cr0 +#define XREG_CR1 cr1 +#define XREG_CR2 cr2 +#define XREG_CR3 cr3 +#define XREG_CR4 cr4 +#define XREG_CR5 cr5 +#define XREG_CR6 cr6 +#define XREG_CR7 cr7 +#define XREG_CR8 cr8 +#define XREG_CR9 cr9 +#define XREG_CR10 cr10 +#define XREG_CR11 cr11 +#define XREG_CR12 cr12 +#define XREG_CR13 cr13 +#define XREG_CR14 cr14 +#define XREG_CR15 cr15 + +/* Current Processor Status Register (CPSR) Bits */ +#define XREG_CPSR_THUMB_MODE 0x20 +#define XREG_CPSR_MODE_BITS 0x1F +#define XREG_CPSR_SYSTEM_MODE 0x1F +#define XREG_CPSR_UNDEFINED_MODE 0x1B +#define XREG_CPSR_DATA_ABORT_MODE 0x17 +#define XREG_CPSR_SVC_MODE 0x13 +#define XREG_CPSR_IRQ_MODE 0x12 +#define XREG_CPSR_FIQ_MODE 0x11 +#define XREG_CPSR_USER_MODE 0x10 + +#define XREG_CPSR_IRQ_ENABLE 0x80 +#define XREG_CPSR_FIQ_ENABLE 0x40 + +#define XREG_CPSR_N_BIT 0x80000000 +#define XREG_CPSR_Z_BIT 0x40000000 +#define XREG_CPSR_C_BIT 0x20000000 +#define XREG_CPSR_V_BIT 0x10000000 + + +/* CP15 defines */ +#if defined (__GNUC__) || defined (__ICCARM__) +/* C0 Register defines */ +#define XREG_CP15_MAIN_ID "p15, 0, %0, c0, c0, 0" +#define XREG_CP15_CACHE_TYPE "p15, 0, %0, c0, c0, 1" +#define XREG_CP15_TCM_TYPE "p15, 0, %0, c0, c0, 2" +#define XREG_CP15_TLB_TYPE "p15, 0, %0, c0, c0, 3" +#define XREG_CP15_MULTI_PROC_AFFINITY "p15, 0, %0, c0, c0, 5" + +#define XREG_CP15_PROC_FEATURE_0 "p15, 0, %0, c0, c1, 0" +#define XREG_CP15_PROC_FEATURE_1 "p15, 0, %0, c0, c1, 1" +#define XREG_CP15_DEBUG_FEATURE_0 "p15, 0, %0, c0, c1, 2" +#define XREG_CP15_MEMORY_FEATURE_0 "p15, 0, %0, c0, c1, 4" +#define XREG_CP15_MEMORY_FEATURE_1 "p15, 0, %0, c0, c1, 5" +#define XREG_CP15_MEMORY_FEATURE_2 "p15, 0, %0, c0, c1, 6" +#define XREG_CP15_MEMORY_FEATURE_3 "p15, 0, %0, c0, c1, 7" + +#define XREG_CP15_INST_FEATURE_0 "p15, 0, %0, c0, c2, 0" +#define XREG_CP15_INST_FEATURE_1 "p15, 0, %0, c0, c2, 1" +#define XREG_CP15_INST_FEATURE_2 "p15, 0, %0, c0, c2, 2" +#define XREG_CP15_INST_FEATURE_3 "p15, 0, %0, c0, c2, 3" +#define XREG_CP15_INST_FEATURE_4 "p15, 0, %0, c0, c2, 4" + +#define XREG_CP15_CACHE_SIZE_ID "p15, 1, %0, c0, c0, 0" +#define XREG_CP15_CACHE_LEVEL_ID "p15, 1, %0, c0, c0, 1" +#define XREG_CP15_AUXILARY_ID "p15, 1, %0, c0, c0, 7" + +#define XREG_CP15_CACHE_SIZE_SEL "p15, 2, %0, c0, c0, 0" + +/* C1 Register Defines */ +#define XREG_CP15_SYS_CONTROL "p15, 0, %0, c1, c0, 0" +#define XREG_CP15_AUX_CONTROL "p15, 0, %0, c1, c0, 1" +#define XREG_CP15_CP_ACCESS_CONTROL "p15, 0, %0, c1, c0, 2" + +#define XREG_CP15_SECURE_CONFIG "p15, 0, %0, c1, c1, 0" +#define XREG_CP15_SECURE_DEBUG_ENABLE "p15, 0, %0, c1, c1, 1" +#define XREG_CP15_NS_ACCESS_CONTROL "p15, 0, %0, c1, c1, 2" +#define XREG_CP15_VIRTUAL_CONTROL "p15, 0, %0, c1, c1, 3" + +#else /* RVCT */ +/* C0 Register defines */ +#define XREG_CP15_MAIN_ID "cp15:0:c0:c0:0" +#define XREG_CP15_CACHE_TYPE "cp15:0:c0:c0:1" +#define XREG_CP15_TCM_TYPE "cp15:0:c0:c0:2" +#define XREG_CP15_TLB_TYPE "cp15:0:c0:c0:3" +#define XREG_CP15_MULTI_PROC_AFFINITY "cp15:0:c0:c0:5" + +#define XREG_CP15_PROC_FEATURE_0 "cp15:0:c0:c1:0" +#define XREG_CP15_PROC_FEATURE_1 "cp15:0:c0:c1:1" +#define XREG_CP15_DEBUG_FEATURE_0 "cp15:0:c0:c1:2" +#define XREG_CP15_MEMORY_FEATURE_0 "cp15:0:c0:c1:4" +#define XREG_CP15_MEMORY_FEATURE_1 "cp15:0:c0:c1:5" +#define XREG_CP15_MEMORY_FEATURE_2 "cp15:0:c0:c1:6" +#define XREG_CP15_MEMORY_FEATURE_3 "cp15:0:c0:c1:7" + +#define XREG_CP15_INST_FEATURE_0 "cp15:0:c0:c2:0" +#define XREG_CP15_INST_FEATURE_1 "cp15:0:c0:c2:1" +#define XREG_CP15_INST_FEATURE_2 "cp15:0:c0:c2:2" +#define XREG_CP15_INST_FEATURE_3 "cp15:0:c0:c2:3" +#define XREG_CP15_INST_FEATURE_4 "cp15:0:c0:c2:4" + +#define XREG_CP15_CACHE_SIZE_ID "cp15:1:c0:c0:0" +#define XREG_CP15_CACHE_LEVEL_ID "cp15:1:c0:c0:1" +#define XREG_CP15_AUXILARY_ID "cp15:1:c0:c0:7" + +#define XREG_CP15_CACHE_SIZE_SEL "cp15:2:c0:c0:0" + +/* C1 Register Defines */ +#define XREG_CP15_SYS_CONTROL "cp15:0:c1:c0:0" +#define XREG_CP15_AUX_CONTROL "cp15:0:c1:c0:1" +#define XREG_CP15_CP_ACCESS_CONTROL "cp15:0:c1:c0:2" + +#define XREG_CP15_SECURE_CONFIG "cp15:0:c1:c1:0" +#define XREG_CP15_SECURE_DEBUG_ENABLE "cp15:0:c1:c1:1" +#define XREG_CP15_NS_ACCESS_CONTROL "cp15:0:c1:c1:2" +#define XREG_CP15_VIRTUAL_CONTROL "cp15:0:c1:c1:3" +#endif + +/* XREG_CP15_CONTROL bit defines */ +#define XREG_CP15_CONTROL_TE_BIT 0x40000000U +#define XREG_CP15_CONTROL_AFE_BIT 0x20000000U +#define XREG_CP15_CONTROL_TRE_BIT 0x10000000U +#define XREG_CP15_CONTROL_NMFI_BIT 0x08000000U +#define XREG_CP15_CONTROL_EE_BIT 0x02000000U +#define XREG_CP15_CONTROL_HA_BIT 0x00020000U +#define XREG_CP15_CONTROL_RR_BIT 0x00004000U +#define XREG_CP15_CONTROL_V_BIT 0x00002000U +#define XREG_CP15_CONTROL_I_BIT 0x00001000U +#define XREG_CP15_CONTROL_Z_BIT 0x00000800U +#define XREG_CP15_CONTROL_SW_BIT 0x00000400U +#define XREG_CP15_CONTROL_B_BIT 0x00000080U +#define XREG_CP15_CONTROL_C_BIT 0x00000004U +#define XREG_CP15_CONTROL_A_BIT 0x00000002U +#define XREG_CP15_CONTROL_M_BIT 0x00000001U + +#if defined (__GNUC__) || defined (__ICCARM__) +/* C2 Register Defines */ +#define XREG_CP15_TTBR0 "p15, 0, %0, c2, c0, 0" +#define XREG_CP15_TTBR1 "p15, 0, %0, c2, c0, 1" +#define XREG_CP15_TTB_CONTROL "p15, 0, %0, c2, c0, 2" + +/* C3 Register Defines */ +#define XREG_CP15_DOMAIN_ACCESS_CTRL "p15, 0, %0, c3, c0, 0" + +/* C4 Register Defines */ +/* Not Used */ + +/* C5 Register Defines */ +#define XREG_CP15_DATA_FAULT_STATUS "p15, 0, %0, c5, c0, 0" +#define XREG_CP15_INST_FAULT_STATUS "p15, 0, %0, c5, c0, 1" + +#define XREG_CP15_AUX_DATA_FAULT_STATUS "p15, 0, %0, c5, c1, 0" +#define XREG_CP15_AUX_INST_FAULT_STATUS "p15, 0, %0, c5, c1, 1" + +/* C6 Register Defines */ +#define XREG_CP15_DATA_FAULT_ADDRESS "p15, 0, %0, c6, c0, 0" +#define XREG_CP15_INST_FAULT_ADDRESS "p15, 0, %0, c6, c0, 2" + +/* C7 Register Defines */ +#define XREG_CP15_NOP "p15, 0, %0, c7, c0, 4" + +#define XREG_CP15_INVAL_IC_POU_IS "p15, 0, %0, c7, c1, 0" +#define XREG_CP15_INVAL_BRANCH_ARRAY_IS "p15, 0, %0, c7, c1, 6" + +#define XREG_CP15_PHYS_ADDR "p15, 0, %0, c7, c4, 0" + +#define XREG_CP15_INVAL_IC_POU "p15, 0, %0, c7, c5, 0" +#define XREG_CP15_INVAL_IC_LINE_MVA_POU "p15, 0, %0, c7, c5, 1" + +/* The CP15 register access below has been deprecated in favor of the new + * isb instruction in Cortex A9. + */ +#define XREG_CP15_INST_SYNC_BARRIER "p15, 0, %0, c7, c5, 4" +#define XREG_CP15_INVAL_BRANCH_ARRAY "p15, 0, %0, c7, c5, 6" + +#define XREG_CP15_INVAL_DC_LINE_MVA_POC "p15, 0, %0, c7, c6, 1" +#define XREG_CP15_INVAL_DC_LINE_SW "p15, 0, %0, c7, c6, 2" + +#define XREG_CP15_VA_TO_PA_CURRENT_0 "p15, 0, %0, c7, c8, 0" +#define XREG_CP15_VA_TO_PA_CURRENT_1 "p15, 0, %0, c7, c8, 1" +#define XREG_CP15_VA_TO_PA_CURRENT_2 "p15, 0, %0, c7, c8, 2" +#define XREG_CP15_VA_TO_PA_CURRENT_3 "p15, 0, %0, c7, c8, 3" + +#define XREG_CP15_VA_TO_PA_OTHER_0 "p15, 0, %0, c7, c8, 4" +#define XREG_CP15_VA_TO_PA_OTHER_1 "p15, 0, %0, c7, c8, 5" +#define XREG_CP15_VA_TO_PA_OTHER_2 "p15, 0, %0, c7, c8, 6" +#define XREG_CP15_VA_TO_PA_OTHER_3 "p15, 0, %0, c7, c8, 7" + +#define XREG_CP15_CLEAN_DC_LINE_MVA_POC "p15, 0, %0, c7, c10, 1" +#define XREG_CP15_CLEAN_DC_LINE_SW "p15, 0, %0, c7, c10, 2" + +/* The next two CP15 register accesses below have been deprecated in favor + * of the new dsb and dmb instructions in Cortex A9. + */ +#define XREG_CP15_DATA_SYNC_BARRIER "p15, 0, %0, c7, c10, 4" +#define XREG_CP15_DATA_MEMORY_BARRIER "p15, 0, %0, c7, c10, 5" + +#define XREG_CP15_CLEAN_DC_LINE_MVA_POU "p15, 0, %0, c7, c11, 1" + +#define XREG_CP15_NOP2 "p15, 0, %0, c7, c13, 1" + +#define XREG_CP15_CLEAN_INVAL_DC_LINE_MVA_POC "p15, 0, %0, c7, c14, 1" +#define XREG_CP15_CLEAN_INVAL_DC_LINE_SW "p15, 0, %0, c7, c14, 2" + +/* C8 Register Defines */ +#define XREG_CP15_INVAL_TLB_IS "p15, 0, %0, c8, c3, 0" +#define XREG_CP15_INVAL_TLB_MVA_IS "p15, 0, %0, c8, c3, 1" +#define XREG_CP15_INVAL_TLB_ASID_IS "p15, 0, %0, c8, c3, 2" +#define XREG_CP15_INVAL_TLB_MVA_ASID_IS "p15, 0, %0, c8, c3, 3" + +#define XREG_CP15_INVAL_ITLB_UNLOCKED "p15, 0, %0, c8, c5, 0" +#define XREG_CP15_INVAL_ITLB_MVA "p15, 0, %0, c8, c5, 1" +#define XREG_CP15_INVAL_ITLB_ASID "p15, 0, %0, c8, c5, 2" + +#define XREG_CP15_INVAL_DTLB_UNLOCKED "p15, 0, %0, c8, c6, 0" +#define XREG_CP15_INVAL_DTLB_MVA "p15, 0, %0, c8, c6, 1" +#define XREG_CP15_INVAL_DTLB_ASID "p15, 0, %0, c8, c6, 2" + +#define XREG_CP15_INVAL_UTLB_UNLOCKED "p15, 0, %0, c8, c7, 0" +#define XREG_CP15_INVAL_UTLB_MVA "p15, 0, %0, c8, c7, 1" +#define XREG_CP15_INVAL_UTLB_ASID "p15, 0, %0, c8, c7, 2" +#define XREG_CP15_INVAL_UTLB_MVA_ASID "p15, 0, %0, c8, c7, 3" + +/* C9 Register Defines */ +#define XREG_CP15_PERF_MONITOR_CTRL "p15, 0, %0, c9, c12, 0" +#define XREG_CP15_COUNT_ENABLE_SET "p15, 0, %0, c9, c12, 1" +#define XREG_CP15_COUNT_ENABLE_CLR "p15, 0, %0, c9, c12, 2" +#define XREG_CP15_V_FLAG_STATUS "p15, 0, %0, c9, c12, 3" +#define XREG_CP15_SW_INC "p15, 0, %0, c9, c12, 4" +#define XREG_CP15_EVENT_CNTR_SEL "p15, 0, %0, c9, c12, 5" + +#define XREG_CP15_PERF_CYCLE_COUNTER "p15, 0, %0, c9, c13, 0" +#define XREG_CP15_EVENT_TYPE_SEL "p15, 0, %0, c9, c13, 1" +#define XREG_CP15_PERF_MONITOR_COUNT "p15, 0, %0, c9, c13, 2" + +#define XREG_CP15_USER_ENABLE "p15, 0, %0, c9, c14, 0" +#define XREG_CP15_INTR_ENABLE_SET "p15, 0, %0, c9, c14, 1" +#define XREG_CP15_INTR_ENABLE_CLR "p15, 0, %0, c9, c14, 2" + +/* C10 Register Defines */ +#define XREG_CP15_TLB_LOCKDWN "p15, 0, %0, c10, c0, 0" + +#define XREG_CP15_PRI_MEM_REMAP "p15, 0, %0, c10, c2, 0" +#define XREG_CP15_NORM_MEM_REMAP "p15, 0, %0, c10, c2, 1" + +/* C11 Register Defines */ +/* Not used */ + +/* C12 Register Defines */ +#define XREG_CP15_VEC_BASE_ADDR "p15, 0, %0, c12, c0, 0" +#define XREG_CP15_MONITOR_VEC_BASE_ADDR "p15, 0, %0, c12, c0, 1" + +#define XREG_CP15_INTERRUPT_STATUS "p15, 0, %0, c12, c1, 0" +#define XREG_CP15_VIRTUALIZATION_INTR "p15, 0, %0, c12, c1, 1" + +/* C13 Register Defines */ +#define XREG_CP15_CONTEXT_ID "p15, 0, %0, c13, c0, 1" +#define USER_RW_THREAD_PID "p15, 0, %0, c13, c0, 2" +#define USER_RO_THREAD_PID "p15, 0, %0, c13, c0, 3" +#define USER_PRIV_THREAD_PID "p15, 0, %0, c13, c0, 4" + +/* C14 Register Defines */ +/* not used */ + +/* C15 Register Defines */ +#define XREG_CP15_POWER_CTRL "p15, 0, %0, c15, c0, 0" +#define XREG_CP15_CONFIG_BASE_ADDR "p15, 4, %0, c15, c0, 0" + +#define XREG_CP15_READ_TLB_ENTRY "p15, 5, %0, c15, c4, 2" +#define XREG_CP15_WRITE_TLB_ENTRY "p15, 5, %0, c15, c4, 4" + +#define XREG_CP15_MAIN_TLB_VA "p15, 5, %0, c15, c5, 2" + +#define XREG_CP15_MAIN_TLB_PA "p15, 5, %0, c15, c6, 2" + +#define XREG_CP15_MAIN_TLB_ATTR "p15, 5, %0, c15, c7, 2" + +#else +/* C2 Register Defines */ +#define XREG_CP15_TTBR0 "cp15:0:c2:c0:0" +#define XREG_CP15_TTBR1 "cp15:0:c2:c0:1" +#define XREG_CP15_TTB_CONTROL "cp15:0:c2:c0:2" + +/* C3 Register Defines */ +#define XREG_CP15_DOMAIN_ACCESS_CTRL "cp15:0:c3:c0:0" + +/* C4 Register Defines */ +/* Not Used */ + +/* C5 Register Defines */ +#define XREG_CP15_DATA_FAULT_STATUS "cp15:0:c5:c0:0" +#define XREG_CP15_INST_FAULT_STATUS "cp15:0:c5:c0:1" + +#define XREG_CP15_AUX_DATA_FAULT_STATUS "cp15:0:c5:c1:0" +#define XREG_CP15_AUX_INST_FAULT_STATUS "cp15:0:c5:c1:1" + +/* C6 Register Defines */ +#define XREG_CP15_DATA_FAULT_ADDRESS "cp15:0:c6:c0:0" +#define XREG_CP15_INST_FAULT_ADDRESS "cp15:0:c6:c0:2" + +/* C7 Register Defines */ +#define XREG_CP15_NOP "cp15:0:c7:c0:4" + +#define XREG_CP15_INVAL_IC_POU_IS "cp15:0:c7:c1:0" +#define XREG_CP15_INVAL_BRANCH_ARRAY_IS "cp15:0:c7:c1:6" + +#define XREG_CP15_PHYS_ADDR "cp15:0:c7:c4:0" + +#define XREG_CP15_INVAL_IC_POU "cp15:0:c7:c5:0" +#define XREG_CP15_INVAL_IC_LINE_MVA_POU "cp15:0:c7:c5:1" + +/* The CP15 register access below has been deprecated in favor of the new + * isb instruction in Cortex A9. + */ +#define XREG_CP15_INST_SYNC_BARRIER "cp15:0:c7:c5:4" +#define XREG_CP15_INVAL_BRANCH_ARRAY "cp15:0:c7:c5:6" + +#define XREG_CP15_INVAL_DC_LINE_MVA_POC "cp15:0:c7:c6:1" +#define XREG_CP15_INVAL_DC_LINE_SW "cp15:0:c7:c6:2" + +#define XREG_CP15_VA_TO_PA_CURRENT_0 "cp15:0:c7:c8:0" +#define XREG_CP15_VA_TO_PA_CURRENT_1 "cp15:0:c7:c8:1" +#define XREG_CP15_VA_TO_PA_CURRENT_2 "cp15:0:c7:c8:2" +#define XREG_CP15_VA_TO_PA_CURRENT_3 "cp15:0:c7:c8:3" + +#define XREG_CP15_VA_TO_PA_OTHER_0 "cp15:0:c7:c8:4" +#define XREG_CP15_VA_TO_PA_OTHER_1 "cp15:0:c7:c8:5" +#define XREG_CP15_VA_TO_PA_OTHER_2 "cp15:0:c7:c8:6" +#define XREG_CP15_VA_TO_PA_OTHER_3 "cp15:0:c7:c8:7" + +#define XREG_CP15_CLEAN_DC_LINE_MVA_POC "cp15:0:c7:c10:1" +#define XREG_CP15_CLEAN_DC_LINE_SW "cp15:0:c7:c10:2" + +/* The next two CP15 register accesses below have been deprecated in favor + * of the new dsb and dmb instructions in Cortex A9. + */ +#define XREG_CP15_DATA_SYNC_BARRIER "cp15:0:c7:c10:4" +#define XREG_CP15_DATA_MEMORY_BARRIER "cp15:0:c7:c10:5" + +#define XREG_CP15_CLEAN_DC_LINE_MVA_POU "cp15:0:c7:c11:1" + +#define XREG_CP15_NOP2 "cp15:0:c7:c13:1" + +#define XREG_CP15_CLEAN_INVAL_DC_LINE_MVA_POC "cp15:0:c7:c14:1" +#define XREG_CP15_CLEAN_INVAL_DC_LINE_SW "cp15:0:c7:c14:2" + +/* C8 Register Defines */ +#define XREG_CP15_INVAL_TLB_IS "cp15:0:c8:c3:0" +#define XREG_CP15_INVAL_TLB_MVA_IS "cp15:0:c8:c3:1" +#define XREG_CP15_INVAL_TLB_ASID_IS "cp15:0:c8:c3:2" +#define XREG_CP15_INVAL_TLB_MVA_ASID_IS "cp15:0:c8:c3:3" + +#define XREG_CP15_INVAL_ITLB_UNLOCKED "cp15:0:c8:c5:0" +#define XREG_CP15_INVAL_ITLB_MVA "cp15:0:c8:c5:1" +#define XREG_CP15_INVAL_ITLB_ASID "cp15:0:c8:c5:2" + +#define XREG_CP15_INVAL_DTLB_UNLOCKED "cp15:0:c8:c6:0" +#define XREG_CP15_INVAL_DTLB_MVA "cp15:0:c8:c6:1" +#define XREG_CP15_INVAL_DTLB_ASID "cp15:0:c8:c6:2" + +#define XREG_CP15_INVAL_UTLB_UNLOCKED "cp15:0:c8:c7:0" +#define XREG_CP15_INVAL_UTLB_MVA "cp15:0:c8:c7:1" +#define XREG_CP15_INVAL_UTLB_ASID "cp15:0:c8:c7:2" +#define XREG_CP15_INVAL_UTLB_MVA_ASID "cp15:0:c8:c7:3" + +/* C9 Register Defines */ +#define XREG_CP15_PERF_MONITOR_CTRL "cp15:0:c9:c12:0" +#define XREG_CP15_COUNT_ENABLE_SET "cp15:0:c9:c12:1" +#define XREG_CP15_COUNT_ENABLE_CLR "cp15:0:c9:c12:2" +#define XREG_CP15_V_FLAG_STATUS "cp15:0:c9:c12:3" +#define XREG_CP15_SW_INC "cp15:0:c9:c12:4" +#define XREG_CP15_EVENT_CNTR_SEL "cp15:0:c9:c12:5" + +#define XREG_CP15_PERF_CYCLE_COUNTER "cp15:0:c9:c13:0" +#define XREG_CP15_EVENT_TYPE_SEL "cp15:0:c9:c13:1" +#define XREG_CP15_PERF_MONITOR_COUNT "cp15:0:c9:c13:2" + +#define XREG_CP15_USER_ENABLE "cp15:0:c9:c14:0" +#define XREG_CP15_INTR_ENABLE_SET "cp15:0:c9:c14:1" +#define XREG_CP15_INTR_ENABLE_CLR "cp15:0:c9:c14:2" + +/* C10 Register Defines */ +#define XREG_CP15_TLB_LOCKDWN "cp15:0:c10:c0:0" + +#define XREG_CP15_PRI_MEM_REMAP "cp15:0:c10:c2:0" +#define XREG_CP15_NORM_MEM_REMAP "cp15:0:c10:c2:1" + +/* C11 Register Defines */ +/* Not used */ + +/* C12 Register Defines */ +#define XREG_CP15_VEC_BASE_ADDR "cp15:0:c12:c0:0" +#define XREG_CP15_MONITOR_VEC_BASE_ADDR "cp15:0:c12:c0:1" + +#define XREG_CP15_INTERRUPT_STATUS "cp15:0:c12:c1:0" +#define XREG_CP15_VIRTUALIZATION_INTR "cp15:0:c12:c1:1" + +/* C13 Register Defines */ +#define XREG_CP15_CONTEXT_ID "cp15:0:c13:c0:1" +#define USER_RW_THREAD_PID "cp15:0:c13:c0:2" +#define USER_RO_THREAD_PID "cp15:0:c13:c0:3" +#define USER_PRIV_THREAD_PID "cp15:0:c13:c0:4" + +/* C14 Register Defines */ +/* not used */ + +/* C15 Register Defines */ +#define XREG_CP15_POWER_CTRL "cp15:0:c15:c0:0" +#define XREG_CP15_CONFIG_BASE_ADDR "cp15:4:c15:c0:0" + +#define XREG_CP15_READ_TLB_ENTRY "cp15:5:c15:c4:2" +#define XREG_CP15_WRITE_TLB_ENTRY "cp15:5:c15:c4:4" + +#define XREG_CP15_MAIN_TLB_VA "cp15:5:c15:c5:2" + +#define XREG_CP15_MAIN_TLB_PA "cp15:5:c15:c6:2" + +#define XREG_CP15_MAIN_TLB_ATTR "cp15:5:c15:c7:2" +#endif + + +/* MPE register definitions */ +#define XREG_FPSID c0 +#define XREG_FPSCR c1 +#define XREG_MVFR1 c6 +#define XREG_MVFR0 c7 +#define XREG_FPEXC c8 +#define XREG_FPINST c9 +#define XREG_FPINST2 c10 + +/* FPSID bits */ +#define XREG_FPSID_IMPLEMENTER_BIT (24) +#define XREG_FPSID_IMPLEMENTER_MASK (0xFF << FPSID_IMPLEMENTER_BIT) +#define XREG_FPSID_SOFTWARE (1<<23) +#define XREG_FPSID_ARCH_BIT (16) +#define XREG_FPSID_ARCH_MASK (0xF << FPSID_ARCH_BIT) +#define XREG_FPSID_PART_BIT (8) +#define XREG_FPSID_PART_MASK (0xFF << FPSID_PART_BIT) +#define XREG_FPSID_VARIANT_BIT (4) +#define XREG_FPSID_VARIANT_MASK (0xF << FPSID_VARIANT_BIT) +#define XREG_FPSID_REV_BIT (0) +#define XREG_FPSID_REV_MASK (0xF << FPSID_REV_BIT) + +/* FPSCR bits */ +#define XREG_FPSCR_N_BIT (1 << 31) +#define XREG_FPSCR_Z_BIT (1 << 30) +#define XREG_FPSCR_C_BIT (1 << 29) +#define XREG_FPSCR_V_BIT (1 << 28) +#define XREG_FPSCR_QC (1 << 27) +#define XREG_FPSCR_AHP (1 << 26) +#define XREG_FPSCR_DEFAULT_NAN (1 << 25) +#define XREG_FPSCR_FLUSHTOZERO (1 << 24) +#define XREG_FPSCR_ROUND_NEAREST (0 << 22) +#define XREG_FPSCR_ROUND_PLUSINF (1 << 22) +#define XREG_FPSCR_ROUND_MINUSINF (2 << 22) +#define XREG_FPSCR_ROUND_TOZERO (3 << 22) +#define XREG_FPSCR_RMODE_BIT (22) +#define XREG_FPSCR_RMODE_MASK (3 << FPSCR_RMODE_BIT) +#define XREG_FPSCR_STRIDE_BIT (20) +#define XREG_FPSCR_STRIDE_MASK (3 << FPSCR_STRIDE_BIT) +#define XREG_FPSCR_LENGTH_BIT (16) +#define XREG_FPSCR_LENGTH_MASK (7 << FPSCR_LENGTH_BIT) +#define XREG_FPSCR_IDC (1 << 7) +#define XREG_FPSCR_IXC (1 << 4) +#define XREG_FPSCR_UFC (1 << 3) +#define XREG_FPSCR_OFC (1 << 2) +#define XREG_FPSCR_DZC (1 << 1) +#define XREG_FPSCR_IOC (1 << 0) + +/* MVFR0 bits */ +#define XREG_MVFR0_RMODE_BIT (28) +#define XREG_MVFR0_RMODE_MASK (0xF << XREG_MVFR0_RMODE_BIT) +#define XREG_MVFR0_SHORT_VEC_BIT (24) +#define XREG_MVFR0_SHORT_VEC_MASK (0xF << XREG_MVFR0_SHORT_VEC_BIT) +#define XREG_MVFR0_SQRT_BIT (20) +#define XREG_MVFR0_SQRT_MASK (0xF << XREG_MVFR0_SQRT_BIT) +#define XREG_MVFR0_DIVIDE_BIT (16) +#define XREG_MVFR0_DIVIDE_MASK (0xF << XREG_MVFR0_DIVIDE_BIT) +#define XREG_MVFR0_EXEC_TRAP_BIT (12) +#define XREG_MVFR0_EXEC_TRAP_MASK (0xF << XREG_MVFR0_EXEC_TRAP_BIT) +#define XREG_MVFR0_DP_BIT (8) +#define XREG_MVFR0_DP_MASK (0xF << XREG_MVFR0_DP_BIT) +#define XREG_MVFR0_SP_BIT (4) +#define XREG_MVFR0_SP_MASK (0xF << XREG_MVFR0_SP_BIT) +#define XREG_MVFR0_A_SIMD_BIT (0) +#define XREG_MVFR0_A_SIMD_MASK (0xF << MVFR0_A_SIMD_BIT) + +/* FPEXC bits */ +#define XREG_FPEXC_EX (1 << 31) +#define XREG_FPEXC_EN (1 << 30) +#define XREG_FPEXC_DEX (1 << 29) + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* XREG_CORTEXA9_H */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xstatus.h b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xstatus.h new file mode 100644 index 0000000..1a212bf --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xstatus.h @@ -0,0 +1,533 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xstatus.h +* +* @addtogroup common_status_codes Xilinx® software status codes +* +* The xstatus.h file contains the Xilinx® software status codes.These codes are +* used throughout the Xilinx device drivers. +* +* @{ +******************************************************************************/ + +#ifndef XSTATUS_H /* prevent circular inclusions */ +#define XSTATUS_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" + +/************************** Constant Definitions *****************************/ + +/*********************** Common statuses 0 - 500 *****************************/ +/** +@name Common Status Codes for All Device Drivers +@{ +*/ +#define XST_SUCCESS 0L +#define XST_FAILURE 1L +#define XST_DEVICE_NOT_FOUND 2L +#define XST_DEVICE_BLOCK_NOT_FOUND 3L +#define XST_INVALID_VERSION 4L +#define XST_DEVICE_IS_STARTED 5L +#define XST_DEVICE_IS_STOPPED 6L +#define XST_FIFO_ERROR 7L /*!< An error occurred during an + operation with a FIFO such as + an underrun or overrun, this + error requires the device to + be reset */ +#define XST_RESET_ERROR 8L /*!< An error occurred which requires + the device to be reset */ +#define XST_DMA_ERROR 9L /*!< A DMA error occurred, this error + typically requires the device + using the DMA to be reset */ +#define XST_NOT_POLLED 10L /*!< The device is not configured for + polled mode operation */ +#define XST_FIFO_NO_ROOM 11L /*!< A FIFO did not have room to put + the specified data into */ +#define XST_BUFFER_TOO_SMALL 12L /*!< The buffer is not large enough + to hold the expected data */ +#define XST_NO_DATA 13L /*!< There was no data available */ +#define XST_REGISTER_ERROR 14L /*!< A register did not contain the + expected value */ +#define XST_INVALID_PARAM 15L /*!< An invalid parameter was passed + into the function */ +#define XST_NOT_SGDMA 16L /*!< The device is not configured for + scatter-gather DMA operation */ +#define XST_LOOPBACK_ERROR 17L /*!< A loopback test failed */ +#define XST_NO_CALLBACK 18L /*!< A callback has not yet been + registered */ +#define XST_NO_FEATURE 19L /*!< Device is not configured with + the requested feature */ +#define XST_NOT_INTERRUPT 20L /*!< Device is not configured for + interrupt mode operation */ +#define XST_DEVICE_BUSY 21L /*!< Device is busy */ +#define XST_ERROR_COUNT_MAX 22L /*!< The error counters of a device + have maxed out */ +#define XST_IS_STARTED 23L /*!< Used when part of device is + already started i.e. + sub channel */ +#define XST_IS_STOPPED 24L /*!< Used when part of device is + already stopped i.e. + sub channel */ +#define XST_DATA_LOST 26L /*!< Driver defined error */ +#define XST_RECV_ERROR 27L /*!< Generic receive error */ +#define XST_SEND_ERROR 28L /*!< Generic transmit error */ +#define XST_NOT_ENABLED 29L /*!< A requested service is not + available because it has not + been enabled */ +#define XST_NO_ACCESS 30L /* Generic access error */ +/** @} */ +/***************** Utility Component statuses 401 - 500 *********************/ +/** +@name Utility Component Status Codes 401 - 500 +@{ +*/ +#define XST_MEMTEST_FAILED 401L /*!< Memory test failed */ + +/** @} */ +/***************** Common Components statuses 501 - 1000 *********************/ +/** +@name Packet Fifo Status Codes 501 - 510 +@{ +*/ +/********************* Packet Fifo statuses 501 - 510 ************************/ + +#define XST_PFIFO_LACK_OF_DATA 501L /*!< Not enough data in FIFO */ +#define XST_PFIFO_NO_ROOM 502L /*!< Not enough room in FIFO */ +#define XST_PFIFO_BAD_REG_VALUE 503L /*!< Self test, a register value + was invalid after reset */ +#define XST_PFIFO_ERROR 504L /*!< Generic packet FIFO error */ +#define XST_PFIFO_DEADLOCK 505L /*!< Packet FIFO is reporting + * empty and full simultaneously + */ +/** @} */ +/** +@name DMA Status Codes 511 - 530 +@{ +*/ +/************************** DMA statuses 511 - 530 ***************************/ + +#define XST_DMA_TRANSFER_ERROR 511L /*!< Self test, DMA transfer + failed */ +#define XST_DMA_RESET_REGISTER_ERROR 512L /*!< Self test, a register value + was invalid after reset */ +#define XST_DMA_SG_LIST_EMPTY 513L /*!< Scatter gather list contains + no buffer descriptors ready + to be processed */ +#define XST_DMA_SG_IS_STARTED 514L /*!< Scatter gather not stopped */ +#define XST_DMA_SG_IS_STOPPED 515L /*!< Scatter gather not running */ +#define XST_DMA_SG_LIST_FULL 517L /*!< All the buffer desciptors of + the scatter gather list are + being used */ +#define XST_DMA_SG_BD_LOCKED 518L /*!< The scatter gather buffer + descriptor which is to be + copied over in the scatter + list is locked */ +#define XST_DMA_SG_NOTHING_TO_COMMIT 519L /*!< No buffer descriptors have been + put into the scatter gather + list to be commited */ +#define XST_DMA_SG_COUNT_EXCEEDED 521L /*!< The packet count threshold + specified was larger than the + total # of buffer descriptors + in the scatter gather list */ +#define XST_DMA_SG_LIST_EXISTS 522L /*!< The scatter gather list has + already been created */ +#define XST_DMA_SG_NO_LIST 523L /*!< No scatter gather list has + been created */ +#define XST_DMA_SG_BD_NOT_COMMITTED 524L /*!< The buffer descriptor which was + being started was not committed + to the list */ +#define XST_DMA_SG_NO_DATA 525L /*!< The buffer descriptor to start + has already been used by the + hardware so it can't be reused + */ +#define XST_DMA_SG_LIST_ERROR 526L /*!< General purpose list access + error */ +#define XST_DMA_BD_ERROR 527L /*!< General buffer descriptor + error */ +/** @} */ +/** +@name IPIF Status Codes Codes 531 - 550 +@{ +*/ +/************************** IPIF statuses 531 - 550 ***************************/ + +#define XST_IPIF_REG_WIDTH_ERROR 531L /*!< An invalid register width + was passed into the function */ +#define XST_IPIF_RESET_REGISTER_ERROR 532L /*!< The value of a register at + reset was not valid */ +#define XST_IPIF_DEVICE_STATUS_ERROR 533L /*!< A write to the device interrupt + status register did not read + back correctly */ +#define XST_IPIF_DEVICE_ACK_ERROR 534L /*!< The device interrupt status + register did not reset when + acked */ +#define XST_IPIF_DEVICE_ENABLE_ERROR 535L /*!< The device interrupt enable + register was not updated when + other registers changed */ +#define XST_IPIF_IP_STATUS_ERROR 536L /*!< A write to the IP interrupt + status register did not read + back correctly */ +#define XST_IPIF_IP_ACK_ERROR 537L /*!< The IP interrupt status register + did not reset when acked */ +#define XST_IPIF_IP_ENABLE_ERROR 538L /*!< IP interrupt enable register was + not updated correctly when other + registers changed */ +#define XST_IPIF_DEVICE_PENDING_ERROR 539L /*!< The device interrupt pending + register did not indicate the + expected value */ +#define XST_IPIF_DEVICE_ID_ERROR 540L /*!< The device interrupt ID register + did not indicate the expected + value */ +#define XST_IPIF_ERROR 541L /*!< Generic ipif error */ +/** @} */ + +/****************** Device specific statuses 1001 - 4095 *********************/ +/** +@name Ethernet Status Codes 1001 - 1050 +@{ +*/ +/********************* Ethernet statuses 1001 - 1050 *************************/ + +#define XST_EMAC_MEMORY_SIZE_ERROR 1001L /*!< Memory space is not big enough + * to hold the minimum number of + * buffers or descriptors */ +#define XST_EMAC_MEMORY_ALLOC_ERROR 1002L /*!< Memory allocation failed */ +#define XST_EMAC_MII_READ_ERROR 1003L /*!< MII read error */ +#define XST_EMAC_MII_BUSY 1004L /*!< An MII operation is in progress */ +#define XST_EMAC_OUT_OF_BUFFERS 1005L /*!< Driver is out of buffers */ +#define XST_EMAC_PARSE_ERROR 1006L /*!< Invalid driver init string */ +#define XST_EMAC_COLLISION_ERROR 1007L /*!< Excess deferral or late + * collision on polled send */ +/** @} */ +/** +@name UART Status Codes 1051 - 1075 +@{ +*/ +/*********************** UART statuses 1051 - 1075 ***************************/ +#define XST_UART + +#define XST_UART_INIT_ERROR 1051L +#define XST_UART_START_ERROR 1052L +#define XST_UART_CONFIG_ERROR 1053L +#define XST_UART_TEST_FAIL 1054L +#define XST_UART_BAUD_ERROR 1055L +#define XST_UART_BAUD_RANGE 1056L + +/** @} */ +/** +@name IIC Status Codes 1076 - 1100 +@{ +*/ +/************************ IIC statuses 1076 - 1100 ***************************/ + +#define XST_IIC_SELFTEST_FAILED 1076 /*!< self test failed */ +#define XST_IIC_BUS_BUSY 1077 /*!< bus found busy */ +#define XST_IIC_GENERAL_CALL_ADDRESS 1078 /*!< mastersend attempted with */ + /* general call address */ +#define XST_IIC_STAND_REG_RESET_ERROR 1079 /*!< A non parameterizable reg */ + /* value after reset not valid */ +#define XST_IIC_TX_FIFO_REG_RESET_ERROR 1080 /*!< Tx fifo included in design */ + /* value after reset not valid */ +#define XST_IIC_RX_FIFO_REG_RESET_ERROR 1081 /*!< Rx fifo included in design */ + /* value after reset not valid */ +#define XST_IIC_TBA_REG_RESET_ERROR 1082 /*!< 10 bit addr incl in design */ + /* value after reset not valid */ +#define XST_IIC_CR_READBACK_ERROR 1083 /*!< Read of the control register */ + /* didn't return value written */ +#define XST_IIC_DTR_READBACK_ERROR 1084 /*!< Read of the data Tx reg */ + /* didn't return value written */ +#define XST_IIC_DRR_READBACK_ERROR 1085 /*!< Read of the data Receive reg */ + /* didn't return value written */ +#define XST_IIC_ADR_READBACK_ERROR 1086 /*!< Read of the data Tx reg */ + /* didn't return value written */ +#define XST_IIC_TBA_READBACK_ERROR 1087 /*!< Read of the 10 bit addr reg */ + /* didn't return written value */ +#define XST_IIC_NOT_SLAVE 1088 /*!< The device isn't a slave */ +#define XST_IIC_ARB_LOST 1089 /*!< Arbitration lost for master */ +/** @} */ +/** +@name ATMC Status Codes 1101 - 1125 +@{ +*/ +/*********************** ATMC statuses 1101 - 1125 ***************************/ + +#define XST_ATMC_ERROR_COUNT_MAX 1101L /*!< the error counters in the ATM + controller hit the max value + which requires the statistics + to be cleared */ +/** @} */ +/** +@name Flash Status Codes 1126 - 1150 +@{ +*/ +/*********************** Flash statuses 1126 - 1150 **************************/ + +#define XST_FLASH_BUSY 1126L /*!< Flash is erasing or programming + */ +#define XST_FLASH_READY 1127L /*!< Flash is ready for commands */ +#define XST_FLASH_ERROR 1128L /*!< Flash had detected an internal + error. Use XFlash_DeviceControl + to retrieve device specific codes + */ +#define XST_FLASH_ERASE_SUSPENDED 1129L /*!< Flash is in suspended erase state + */ +#define XST_FLASH_WRITE_SUSPENDED 1130L /*!< Flash is in suspended write state + */ +#define XST_FLASH_PART_NOT_SUPPORTED 1131L /*!< Flash type not supported by + driver */ +#define XST_FLASH_NOT_SUPPORTED 1132L /*!< Operation not supported */ +#define XST_FLASH_TOO_MANY_REGIONS 1133L /*!< Too many erase regions */ +#define XST_FLASH_TIMEOUT_ERROR 1134L /*!< Programming or erase operation + aborted due to a timeout */ +#define XST_FLASH_ADDRESS_ERROR 1135L /*!< Accessed flash outside its + addressible range */ +#define XST_FLASH_ALIGNMENT_ERROR 1136L /*!< Write alignment error */ +#define XST_FLASH_BLOCKING_CALL_ERROR 1137L /*!< Couldn't return immediately from + write/erase function with + XFL_NON_BLOCKING_WRITE/ERASE + option cleared */ +#define XST_FLASH_CFI_QUERY_ERROR 1138L /*!< Failed to query the device */ +/** @} */ +/** +@name SPI Status Codes 1151 - 1175 +@{ +*/ +/*********************** SPI statuses 1151 - 1175 ****************************/ + +#define XST_SPI_MODE_FAULT 1151 /*!< master was selected as slave */ +#define XST_SPI_TRANSFER_DONE 1152 /*!< data transfer is complete */ +#define XST_SPI_TRANSMIT_UNDERRUN 1153 /*!< slave underruns transmit register */ +#define XST_SPI_RECEIVE_OVERRUN 1154 /*!< device overruns receive register */ +#define XST_SPI_NO_SLAVE 1155 /*!< no slave has been selected yet */ +#define XST_SPI_TOO_MANY_SLAVES 1156 /*!< more than one slave is being + * selected */ +#define XST_SPI_NOT_MASTER 1157 /*!< operation is valid only as master */ +#define XST_SPI_SLAVE_ONLY 1158 /*!< device is configured as slave-only + */ +#define XST_SPI_SLAVE_MODE_FAULT 1159 /*!< slave was selected while disabled */ +#define XST_SPI_SLAVE_MODE 1160 /*!< device has been addressed as slave */ +#define XST_SPI_RECEIVE_NOT_EMPTY 1161 /*!< device received data in slave mode */ + +#define XST_SPI_COMMAND_ERROR 1162 /*!< unrecognised command - qspi only */ +#define XST_SPI_POLL_DONE 1163 /*!< controller completed polling the + device for status */ +/** @} */ +/** +@name OPB Arbiter Status Codes 1176 - 1200 +@{ +*/ +/********************** OPB Arbiter statuses 1176 - 1200 *********************/ + +#define XST_OPBARB_INVALID_PRIORITY 1176 /*!< the priority registers have either + * one master assigned to two or more + * priorities, or one master not + * assigned to any priority + */ +#define XST_OPBARB_NOT_SUSPENDED 1177 /*!< an attempt was made to modify the + * priority levels without first + * suspending the use of priority + * levels + */ +#define XST_OPBARB_PARK_NOT_ENABLED 1178 /*!< bus parking by id was enabled but + * bus parking was not enabled + */ +#define XST_OPBARB_NOT_FIXED_PRIORITY 1179 /*!< the arbiter must be in fixed + * priority mode to allow the + * priorities to be changed + */ +/** @} */ +/** +@name INTC Status Codes 1201 - 1225 +@{ +*/ +/************************ Intc statuses 1201 - 1225 **************************/ + +#define XST_INTC_FAIL_SELFTEST 1201 /*!< self test failed */ +#define XST_INTC_CONNECT_ERROR 1202 /*!< interrupt already in use */ +/** @} */ +/** +@name TmrCtr Status Codes 1226 - 1250 +@{ +*/ +/********************** TmrCtr statuses 1226 - 1250 **************************/ + +#define XST_TMRCTR_TIMER_FAILED 1226 /*!< self test failed */ +/** @} */ +/** +@name WdtTb Status Codes 1251 - 1275 +@{ +*/ +/********************** WdtTb statuses 1251 - 1275 ***************************/ + +#define XST_WDTTB_TIMER_FAILED 1251L +/** @} */ +/** +@name PlbArb status Codes 1276 - 1300 +@{ +*/ +/********************** PlbArb statuses 1276 - 1300 **************************/ + +#define XST_PLBARB_FAIL_SELFTEST 1276L +/** @} */ +/** +@name Plb2Opb Status Codes 1301 - 1325 +@{ +*/ +/********************** Plb2Opb statuses 1301 - 1325 *************************/ + +#define XST_PLB2OPB_FAIL_SELFTEST 1301L +/** @} */ +/** +@name Opb2Plb Status 1326 - 1350 +@{ +*/ +/********************** Opb2Plb statuses 1326 - 1350 *************************/ + +#define XST_OPB2PLB_FAIL_SELFTEST 1326L +/** @} */ +/** +@name SysAce Status Codes 1351 - 1360 +@{ +*/ +/********************** SysAce statuses 1351 - 1360 **************************/ + +#define XST_SYSACE_NO_LOCK 1351L /*!< No MPU lock has been granted */ +/** @} */ +/** +@name PCI Bridge Status Codes 1361 - 1375 +@{ +*/ +/********************** PCI Bridge statuses 1361 - 1375 **********************/ + +#define XST_PCI_INVALID_ADDRESS 1361L +/** @} */ +/** +@name FlexRay Constants 1400 - 1409 +@{ +*/ +/********************** FlexRay constants 1400 - 1409 *************************/ + +#define XST_FR_TX_ERROR 1400 +#define XST_FR_TX_BUSY 1401 +#define XST_FR_BUF_LOCKED 1402 +#define XST_FR_NO_BUF 1403 +/** @} */ +/** +@name USB constants 1410 - 1420 +@{ +*/ +/****************** USB constants 1410 - 1420 *******************************/ + +#define XST_USB_ALREADY_CONFIGURED 1410 +#define XST_USB_BUF_ALIGN_ERROR 1411 +#define XST_USB_NO_DESC_AVAILABLE 1412 +#define XST_USB_BUF_TOO_BIG 1413 +#define XST_USB_NO_BUF 1414 +/** @} */ +/** +@name HWICAP constants 1421 - 1429 +@{ +*/ +/****************** HWICAP constants 1421 - 1429 *****************************/ + +#define XST_HWICAP_WRITE_DONE 1421 + +/** @} */ +/** +@name AXI VDMA constants 1430 - 1440 +@{ +*/ +/****************** AXI VDMA constants 1430 - 1440 *****************************/ + +#define XST_VDMA_MISMATCH_ERROR 1430 +/** @} */ +/** +@name NAND Flash Status Codes 1441 - 1459 +@{ +*/ +/*********************** NAND Flash statuses 1441 - 1459 *********************/ + +#define XST_NAND_BUSY 1441L /*!< Flash is erasing or + * programming + */ +#define XST_NAND_READY 1442L /*!< Flash is ready for commands + */ +#define XST_NAND_ERROR 1443L /*!< Flash had detected an + * internal error. + */ +#define XST_NAND_PART_NOT_SUPPORTED 1444L /*!< Flash type not supported by + * driver + */ +#define XST_NAND_OPT_NOT_SUPPORTED 1445L /*!< Operation not supported + */ +#define XST_NAND_TIMEOUT_ERROR 1446L /*!< Programming or erase + * operation aborted due to a + * timeout + */ +#define XST_NAND_ADDRESS_ERROR 1447L /*!< Accessed flash outside its + * addressible range + */ +#define XST_NAND_ALIGNMENT_ERROR 1448L /*!< Write alignment error + */ +#define XST_NAND_PARAM_PAGE_ERROR 1449L /*!< Failed to read parameter + * page of the device + */ +#define XST_NAND_CACHE_ERROR 1450L /*!< Flash page buffer error + */ + +#define XST_NAND_WRITE_PROTECTED 1451L /*!< Flash is write protected + */ +/** @} */ + +/**************************** Type Definitions *******************************/ + +typedef s32 XStatus; + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** +* @} End of "addtogroup common_status_codes". +*/ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xtime_l.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xtime_l.c new file mode 100644 index 0000000..a687473 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xtime_l.c @@ -0,0 +1,118 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file xtime_l.c +* +* This file contains low level functions to get/set time from the Global Timer +* register in the ARM Cortex A9 MP core. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ------ -------- ---------------------------------------------------
+* 1.00a rp/sdm 11/03/09 Initial release.
+* 3.07a sgd    07/05/12 Upadted get/set time functions to make use Global Timer
+* 
+* +* @note None. +* +******************************************************************************/ +/***************************** Include Files *********************************/ + +#include "xtime_l.h" +#include "xpseudo_asm.h" +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_io.h" + +/***************** Macros (Inline Functions) Definitions *********************/ + +/**************************** Type Definitions *******************************/ + +/************************** Constant Definitions *****************************/ + +/************************** Variable Definitions *****************************/ + +/************************** Function Prototypes ******************************/ + +/****************************************************************************/ +/** +* @brief Set the time in the Global Timer Counter Register. +* +* @param Xtime_Global: 64-bit Value to be written to the Global Timer +* Counter Register. +* +* @return None. +* +* @note When this function is called by any one processor in a multi- +* processor environment, reference time will reset/lost for all +* processors. +* +****************************************************************************/ +void XTime_SetTime(XTime Xtime_Global) +{ + /* Disable Global Timer */ + Xil_Out32((u32)GLOBAL_TMR_BASEADDR + (u32)GTIMER_CONTROL_OFFSET, (u32)0x0); + + /* Updating Global Timer Counter Register */ + Xil_Out32((u32)GLOBAL_TMR_BASEADDR + (u32)GTIMER_COUNTER_LOWER_OFFSET, (u32)Xtime_Global); + Xil_Out32((u32)GLOBAL_TMR_BASEADDR + (u32)GTIMER_COUNTER_UPPER_OFFSET, + (u32)((u32)(Xtime_Global>>32U))); + + /* Enable Global Timer */ + Xil_Out32((u32)GLOBAL_TMR_BASEADDR + (u32)GTIMER_CONTROL_OFFSET, (u32)0x1); +} + +/****************************************************************************/ +/** +* @brief Get the time from the Global Timer Counter Register. +* +* @param Xtime_Global: Pointer to the 64-bit location which will be +* updated with the current timer value. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void XTime_GetTime(XTime *Xtime_Global) +{ + u32 low; + u32 high; + + /* Reading Global Timer Counter Register */ + do + { + high = Xil_In32(GLOBAL_TMR_BASEADDR + GTIMER_COUNTER_UPPER_OFFSET); + low = Xil_In32(GLOBAL_TMR_BASEADDR + GTIMER_COUNTER_LOWER_OFFSET); + } while(Xil_In32(GLOBAL_TMR_BASEADDR + GTIMER_COUNTER_UPPER_OFFSET) != high); + + *Xtime_Global = (((XTime) high) << 32U) | (XTime) low; +} diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xtime_l.h b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xtime_l.h new file mode 100644 index 0000000..12004e1 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xtime_l.h @@ -0,0 +1,104 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file xtime_l.h +* @addtogroup a9_time_apis Cortex A9 Time Functions +* +* xtime_l.h provides access to the 64-bit Global Counter in the PMU. This +* counter increases by one at every two processor cycles. These functions can +* be used to get/set time in the global timer. +* +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ------ -------- ---------------------------------------------------
+* 1.00a rp/sdm 11/03/09 Initial release.
+* 3.06a sgd    05/15/12 Upadted get/set time functions to make use Global Timer
+* 3.06a asa    06/17/12 Reverted back the changes to make use Global Timer.
+* 3.07a sgd    07/05/12 Upadted get/set time functions to make use Global Timer
+* 6.6   srm    10/23/17 Updated the macros to support user configurable sleep
+*						implementation
+* 6.8   aru  09/06/18 Removed compilation warnings for ARMCC toolchain.
+* 
+* +******************************************************************************/ + +#ifndef XTIME_H /* prevent circular inclusions */ +#define XTIME_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xparameters.h" + +/***************** Macros (Inline Functions) Definitions *********************/ + +/**************************** Type Definitions *******************************/ + +typedef u64 XTime; + +/************************** Constant Definitions *****************************/ +#define GLOBAL_TMR_BASEADDR XPAR_GLOBAL_TMR_BASEADDR +#define GTIMER_COUNTER_LOWER_OFFSET 0x00U +#define GTIMER_COUNTER_UPPER_OFFSET 0x04U +#define GTIMER_CONTROL_OFFSET 0x08U + +#if defined (SLEEP_TIMER_BASEADDR) +#define COUNTS_PER_SECOND (SLEEP_TIMER_FREQUENCY) +#else +/* Global Timer is always clocked at half of the CPU frequency */ +#define COUNTS_PER_SECOND (XPAR_CPU_CORTEXA9_CORE_CLOCK_FREQ_HZ /2) +#endif + +#if defined (XSLEEP_TIMER_IS_DEFAULT_TIMER) +#ifdef __GNUC__ +#pragma message ("For the sleep routines, Global timer is being used") +#endif +#endif +/************************** Variable Definitions *****************************/ + +/************************** Function Prototypes ******************************/ + +void XTime_SetTime(XTime Xtime_Global); +void XTime_GetTime(XTime *Xtime_Global); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* XTIME_H */ +/** +* @} End of "addtogroup a9_time_apis". +*/ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/uartps_v3_7/src/Makefile b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/uartps_v3_7/src/Makefile new file mode 100644 index 0000000..88b1e62 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/uartps_v3_7/src/Makefile @@ -0,0 +1,40 @@ +COMPILER= +ARCHIVER= +CP=cp +COMPILER_FLAGS= +EXTRA_COMPILER_FLAGS= +LIB=libxil.a + +CC_FLAGS = $(COMPILER_FLAGS) +ECC_FLAGS = $(EXTRA_COMPILER_FLAGS) + +RELEASEDIR=../../../lib +INCLUDEDIR=../../../include +INCLUDES=-I./. -I${INCLUDEDIR} + +OUTS = *.o + +LIBSOURCES:=*.c +INCLUDEFILES:=*.h + +OBJECTS = $(addsuffix .o, $(basename $(wildcard *.c))) + +libs: banner xuartps_libs clean + +%.o: %.c + ${COMPILER} $(CC_FLAGS) $(ECC_FLAGS) $(INCLUDES) -o $@ $< + +banner: + echo "Compiling uartps" + +xuartps_libs: ${OBJECTS} + $(ARCHIVER) -r ${RELEASEDIR}/${LIB} ${OBJECTS} + +.PHONY: include +include: xuartps_includes + +xuartps_includes: + ${CP} ${INCLUDEFILES} ${INCLUDEDIR} + +clean: + rm -rf ${OBJECTS} diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/uartps_v3_7/src/xuartps.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/uartps_v3_7/src/xuartps.c new file mode 100644 index 0000000..944afa1 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/uartps_v3_7/src/xuartps.c @@ -0,0 +1,642 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xuartps.c +* @addtogroup uartps_v3_5 +* @{ +* +* This file contains the implementation of the interface functions for XUartPs +* driver. Refer to the header file xuartps.h for more detailed information. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date	 Changes
+* ----- ------ -------- ----------------------------------------------
+* 1.00	drg/jz 01/13/10 First Release
+* 2.2   hk     06/23/14 SW reset of RX and TX should be done when changing
+*                       baud rate. CR# 804281.
+* 3.00  kvn    02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.1	kvn    04/10/15 Modified code for latest RTL changes.
+* 3.5	NK     09/26/17 Fix the RX Buffer Overflow issue.
+* 3.7   aru    08/17/18 Resolved MISRA-C mandatory violations.(CR#1007755)
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ + +#include "xstatus.h" +#include "xuartps.h" +#include "xil_io.h" + +/************************** Constant Definitions ****************************/ + +/* The following constant defines the amount of error that is allowed for + * a specified baud rate. This error is the difference between the actual + * baud rate that will be generated using the specified clock and the + * desired baud rate. + */ +#define XUARTPS_MAX_BAUD_ERROR_RATE 3U /* max % error allowed */ + +/**************************** Type Definitions ******************************/ + + +/***************** Macros (Inline Functions) Definitions ********************/ + + +/************************** Function Prototypes *****************************/ + +static void XUartPs_StubHandler(void *CallBackRef, u32 Event, + u32 ByteCount); + +u32 XUartPs_SendBuffer(XUartPs *InstancePtr); + +u32 XUartPs_ReceiveBuffer(XUartPs *InstancePtr); + +/************************** Variable Definitions ****************************/ + +/****************************************************************************/ +/** +* +* Initializes a specific XUartPs instance such that it is ready to be used. +* The data format of the device is setup for 8 data bits, 1 stop bit, and no +* parity by default. The baud rate is set to a default value specified by +* Config->DefaultBaudRate if set, otherwise it is set to 19.2K baud. The +* receive FIFO threshold is set for 8 bytes. The default operating mode of the +* driver is polled mode. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* @param Config is a reference to a structure containing information +* about a specific XUartPs driver. +* @param EffectiveAddr is the device base address in the virtual memory +* address space. The caller is responsible for keeping the address +* mapping from EffectiveAddr to the device physical base address +* unchanged once this function is invoked. Unexpected errors may +* occur if the address mapping changes after this function is +* called. If address translation is not used, pass in the physical +* address instead. +* +* @return +* +* - XST_SUCCESS if initialization was successful +* - XST_UART_BAUD_ERROR if the baud rate is not possible because +* the inputclock frequency is not divisible with an acceptable +* amount of error +* +* @note +* +* The default configuration for the UART after initialization is: +* +* - 19,200 bps or XPAR_DFT_BAUDRATE if defined +* - 8 data bits +* - 1 stop bit +* - no parity +* - FIFO's are enabled with a receive threshold of 8 bytes +* - The RX timeout is enabled with a timeout of 1 (4 char times) +* +* All interrupts are disabled. +* +*****************************************************************************/ +s32 XUartPs_CfgInitialize(XUartPs *InstancePtr, + XUartPs_Config * Config, u32 EffectiveAddr) +{ + s32 Status; + u32 ModeRegister; + u32 BaudRate; + + /* Assert validates the input arguments */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(Config != NULL); + + /* Setup the driver instance using passed in parameters */ + InstancePtr->Config.BaseAddress = EffectiveAddr; + InstancePtr->Config.InputClockHz = Config->InputClockHz; + InstancePtr->Config.ModemPinsConnected = Config->ModemPinsConnected; + + /* Initialize other instance data to default values */ + InstancePtr->Handler = (XUartPs_Handler)XUartPs_StubHandler; + + InstancePtr->SendBuffer.NextBytePtr = NULL; + InstancePtr->SendBuffer.RemainingBytes = 0U; + InstancePtr->SendBuffer.RequestedBytes = 0U; + + InstancePtr->ReceiveBuffer.NextBytePtr = NULL; + InstancePtr->ReceiveBuffer.RemainingBytes = 0U; + InstancePtr->ReceiveBuffer.RequestedBytes = 0U; + + /* Initialize the platform data */ + InstancePtr->Platform = XGetPlatform_Info(); + + InstancePtr->is_rxbs_error = 0U; + + /* Flag that the driver instance is ready to use */ + InstancePtr->IsReady = XIL_COMPONENT_IS_READY; + + /* + * Set the default baud rate here, can be changed prior to + * starting the device + */ + BaudRate = (u32)XUARTPS_DFT_BAUDRATE; + Status = XUartPs_SetBaudRate(InstancePtr, BaudRate); + if (Status != (s32)XST_SUCCESS) { + InstancePtr->IsReady = 0U; + } else { + + /* + * Set up the default data format: 8 bit data, 1 stop bit, no + * parity + */ + ModeRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress, + XUARTPS_MR_OFFSET); + + /* Mask off what's already there */ + ModeRegister &= (~((u32)XUARTPS_MR_CHARLEN_MASK | + (u32)XUARTPS_MR_STOPMODE_MASK | + (u32)XUARTPS_MR_PARITY_MASK)); + + /* Set the register value to the desired data format */ + ModeRegister |= ((u32)XUARTPS_MR_CHARLEN_8_BIT | + (u32)XUARTPS_MR_STOPMODE_1_BIT | + (u32)XUARTPS_MR_PARITY_NONE); + + /* Write the mode register out */ + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_MR_OFFSET, + ModeRegister); + + /* Set the RX FIFO trigger at 8 data bytes. */ + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, + XUARTPS_RXWM_OFFSET, 0x08U); + + /* Set the RX timeout to 1, which will be 4 character time */ + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, + XUARTPS_RXTOUT_OFFSET, 0x01U); + + /* Disable all interrupts, polled mode is the default */ + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_IDR_OFFSET, + XUARTPS_IXR_MASK); + + Status = XST_SUCCESS; + } + return Status; +} + +/****************************************************************************/ +/** +* +* This functions sends the specified buffer using the device in either +* polled or interrupt driven mode. This function is non-blocking, if the device +* is busy sending data, it will return and indicate zero bytes were sent. +* Otherwise, it fills the TX FIFO as much as it can, and return the number of +* bytes sent. +* +* In a polled mode, this function will only send as much data as TX FIFO can +* buffer. The application may need to call it repeatedly to send the entire +* buffer. +* +* In interrupt mode, this function will start sending the specified buffer, +* then the interrupt handler will continue sending data until the entire +* buffer has been sent. A callback function, as specified by the application, +* will be called to indicate the completion of sending. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* @param BufferPtr is pointer to a buffer of data to be sent. +* @param NumBytes contains the number of bytes to be sent. A value of +* zero will stop a previous send operation that is in progress +* in interrupt mode. Any data that was already put into the +* transmit FIFO will be sent. +* +* @return The number of bytes actually sent. +* +* @note +* +* The number of bytes is not asserted so that this function may be called with +* a value of zero to stop an operation that is already in progress. +*

+* +*****************************************************************************/ +u32 XUartPs_Send(XUartPs *InstancePtr, u8 *BufferPtr, + u32 NumBytes) +{ + u32 BytesSent; + + /* Asserts validate the input arguments */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(BufferPtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Disable the UART transmit interrupts to allow this call to stop a + * previous operation that may be interrupt driven. + */ + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_IDR_OFFSET, + (XUARTPS_IXR_TXEMPTY | XUARTPS_IXR_TXFULL)); + + /* Setup the buffer parameters */ + InstancePtr->SendBuffer.RequestedBytes = NumBytes; + InstancePtr->SendBuffer.RemainingBytes = NumBytes; + InstancePtr->SendBuffer.NextBytePtr = BufferPtr; + + /* + * Transmit interrupts will be enabled in XUartPs_SendBuffer(), after + * filling the TX FIFO. + */ + BytesSent = XUartPs_SendBuffer(InstancePtr); + + return BytesSent; +} + +/****************************************************************************/ +/** +* +* This function attempts to receive a specified number of bytes of data +* from the device and store it into the specified buffer. This function works +* for both polled or interrupt driven modes. It is non-blocking. +* +* In a polled mode, this function will only receive the data already in the +* RX FIFO. The application may need to call it repeatedly to receive the +* entire buffer. Polled mode is the default mode of operation for the device. +* +* In interrupt mode, this function will start the receiving, if not the entire +* buffer has been received, the interrupt handler will continue receiving data +* until the entire buffer has been received. A callback function, as specified +* by the application, will be called to indicate the completion of the +* receiving or error conditions. +* +* @param InstancePtr is a pointer to the XUartPs instance +* @param BufferPtr is pointer to buffer for data to be received into +* @param NumBytes is the number of bytes to be received. A value of zero +* will stop a previous receive operation that is in progress in +* interrupt mode. +* +* @return The number of bytes received. +* +* @note +* +* The number of bytes is not asserted so that this function may be called +* with a value of zero to stop an operation that is already in progress. +* +*****************************************************************************/ +u32 XUartPs_Recv(XUartPs *InstancePtr, + u8 *BufferPtr, u32 NumBytes) +{ + u32 ReceivedCount; + u32 ImrRegister; + + /* Assert validates the input arguments */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(BufferPtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Disable all the interrupts. + * This stops a previous operation that may be interrupt driven + */ + ImrRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress, + XUARTPS_IMR_OFFSET); + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_IDR_OFFSET, + XUARTPS_IXR_MASK); + + /* Setup the buffer parameters */ + InstancePtr->ReceiveBuffer.RequestedBytes = NumBytes; + InstancePtr->ReceiveBuffer.RemainingBytes = NumBytes; + InstancePtr->ReceiveBuffer.NextBytePtr = BufferPtr; + + /* Receive the data from the device */ + ReceivedCount = XUartPs_ReceiveBuffer(InstancePtr); + + /* Restore the interrupt state */ + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_IER_OFFSET, + ImrRegister); + + return ReceivedCount; +} + +/****************************************************************************/ +/* +* +* This function sends a buffer that has been previously specified by setting +* up the instance variables of the instance. This function is an internal +* function for the XUartPs driver such that it may be called from a shell +* function that sets up the buffer or from an interrupt handler. +* +* This function sends the specified buffer in either polled or interrupt +* driven modes. This function is non-blocking. +* +* In a polled mode, this function only sends as much data as the TX FIFO +* can buffer. The application may need to call it repeatedly to send the +* entire buffer. +* +* In interrupt mode, this function starts the sending of the buffer, if not +* the entire buffer has been sent, then the interrupt handler continues the +* sending until the entire buffer has been sent. A callback function, as +* specified by the application, will be called to indicate the completion of +* sending. +* +* @param InstancePtr is a pointer to the XUartPs instance +* +* @return The number of bytes actually sent +* +* @note None. +* +*****************************************************************************/ +u32 XUartPs_SendBuffer(XUartPs *InstancePtr) +{ + u32 SentCount = 0U; + u32 ImrRegister; + + /* + * If the TX FIFO is full, send nothing. + * Otherwise put bytes into the TX FIFO unil it is full, or all of the + * data has been put into the FIFO. + */ + while ((!XUartPs_IsTransmitFull(InstancePtr->Config.BaseAddress)) && + (InstancePtr->SendBuffer.RemainingBytes > SentCount)) { + + /* Fill the FIFO from the buffer */ + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, + XUARTPS_FIFO_OFFSET, + ((u32)InstancePtr->SendBuffer. + NextBytePtr[SentCount])); + + /* Increment the send count. */ + SentCount++; + } + + /* Update the buffer to reflect the bytes that were sent from it */ + InstancePtr->SendBuffer.NextBytePtr += SentCount; + InstancePtr->SendBuffer.RemainingBytes -= SentCount; + + /* + * If interrupts are enabled as indicated by the receive interrupt, then + * enable the TX FIFO empty interrupt, so further action can be taken + * for this sending. + */ + ImrRegister = + XUartPs_ReadReg(InstancePtr->Config.BaseAddress, + XUARTPS_IMR_OFFSET); + if (((ImrRegister & XUARTPS_IXR_RXFULL) != (u32)0) || + ((ImrRegister & XUARTPS_IXR_RXEMPTY) != (u32)0)|| + ((ImrRegister & XUARTPS_IXR_RXOVR) != (u32)0)) { + + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, + XUARTPS_IER_OFFSET, + ImrRegister | (u32)XUARTPS_IXR_TXEMPTY); + } + + return SentCount; +} + +/****************************************************************************/ +/* +* +* This function receives a buffer that has been previously specified by setting +* up the instance variables of the instance. This function is an internal +* function, and it may be called from a shell function that sets up the buffer +* or from an interrupt handler. +* +* This function attempts to receive a specified number of bytes from the +* device and store it into the specified buffer. This function works for +* either polled or interrupt driven modes. It is non-blocking. +* +* In polled mode, this function only receives as much data as in the RX FIFO. +* The application may need to call it repeatedly to receive the entire buffer. +* Polled mode is the default mode for the driver. +* +* In interrupt mode, this function starts the receiving, if not the entire +* buffer has been received, the interrupt handler will continue until the +* entire buffer has been received. A callback function, as specified by the +* application, will be called to indicate the completion of the receiving or +* error conditions. +* +* @param InstancePtr is a pointer to the XUartPs instance +* +* @return The number of bytes received. +* +* @note None. +* +*****************************************************************************/ +u32 XUartPs_ReceiveBuffer(XUartPs *InstancePtr) +{ + u32 CsrRegister; + u32 ReceivedCount = 0U; + u32 ByteStatusValue, EventData; + u32 Event; + + /* + * Read the Channel Status Register to determine if there is any data in + * the RX FIFO + */ + CsrRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress, + XUARTPS_SR_OFFSET); + + /* + * Loop until there is no more data in RX FIFO or the specified + * number of bytes has been received + */ + while((ReceivedCount < InstancePtr->ReceiveBuffer.RemainingBytes)&& + (((CsrRegister & XUARTPS_SR_RXEMPTY) == (u32)0))){ + + if (InstancePtr->is_rxbs_error) { + ByteStatusValue = XUartPs_ReadReg( + InstancePtr->Config.BaseAddress, + XUARTPS_RXBS_OFFSET); + if((ByteStatusValue & XUARTPS_RXBS_MASK)!= (u32)0) { + EventData = ByteStatusValue; + Event = XUARTPS_EVENT_PARE_FRAME_BRKE; + /* + * Call the application handler to indicate that there is a receive + * error or a break interrupt, if the application cares about the + * error it call a function to get the last errors. + */ + InstancePtr->Handler(InstancePtr->CallBackRef, + Event, EventData); + } + } + + InstancePtr->ReceiveBuffer.NextBytePtr[ReceivedCount] = + XUartPs_ReadReg(InstancePtr->Config. + BaseAddress, + XUARTPS_FIFO_OFFSET); + + ReceivedCount++; + + CsrRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress, + XUARTPS_SR_OFFSET); + } + InstancePtr->is_rxbs_error = 0; + /* + * Update the receive buffer to reflect the number of bytes just + * received + */ + if(InstancePtr->ReceiveBuffer.NextBytePtr != NULL){ + InstancePtr->ReceiveBuffer.NextBytePtr += ReceivedCount; + } + InstancePtr->ReceiveBuffer.RemainingBytes -= ReceivedCount; + + return ReceivedCount; +} + +/*****************************************************************************/ +/** +* +* Sets the baud rate for the device. Checks the input value for +* validity and also verifies that the requested rate can be configured to +* within the maximum error range specified by XUARTPS_MAX_BAUD_ERROR_RATE. +* If the provided rate is not possible, the current setting is unchanged. +* +* @param InstancePtr is a pointer to the XUartPs instance +* @param BaudRate to be set +* +* @return +* - XST_SUCCESS if everything configured as expected +* - XST_UART_BAUD_ERROR if the requested rate is not available +* because there was too much error +* +* @note None. +* +*****************************************************************************/ +s32 XUartPs_SetBaudRate(XUartPs *InstancePtr, u32 BaudRate) +{ + u32 IterBAUDDIV; /* Iterator for available baud divisor values */ + u32 BRGR_Value; /* Calculated value for baud rate generator */ + u32 CalcBaudRate; /* Calculated baud rate */ + u32 BaudError; /* Diff between calculated and requested baud rate */ + u32 Best_BRGR = 0U; /* Best value for baud rate generator */ + u8 Best_BAUDDIV = 0U; /* Best value for baud divisor */ + u32 Best_Error = 0xFFFFFFFFU; + u32 PercentError; + u32 ModeReg; + u32 InputClk; + + /* Asserts validate the input arguments */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(BaudRate <= (u32)XUARTPS_MAX_RATE); + Xil_AssertNonvoid(BaudRate >= (u32)XUARTPS_MIN_RATE); + + /* + * Make sure the baud rate is not impossilby large. + * Fastest possible baud rate is Input Clock / 2. + */ + if ((BaudRate * 2) > InstancePtr->Config.InputClockHz) { + return XST_UART_BAUD_ERROR; + } + /* Check whether the input clock is divided by 8 */ + ModeReg = XUartPs_ReadReg( InstancePtr->Config.BaseAddress, + XUARTPS_MR_OFFSET); + + InputClk = InstancePtr->Config.InputClockHz; + if(ModeReg & XUARTPS_MR_CLKSEL) { + InputClk = InstancePtr->Config.InputClockHz / 8; + } + + /* + * Determine the Baud divider. It can be 4to 254. + * Loop through all possible combinations + */ + for (IterBAUDDIV = 4; IterBAUDDIV < 255; IterBAUDDIV++) { + + /* Calculate the value for BRGR register */ + BRGR_Value = InputClk / (BaudRate * (IterBAUDDIV + 1)); + + /* Calculate the baud rate from the BRGR value */ + CalcBaudRate = InputClk/ (BRGR_Value * (IterBAUDDIV + 1)); + + /* Avoid unsigned integer underflow */ + if (BaudRate > CalcBaudRate) { + BaudError = BaudRate - CalcBaudRate; + } + else { + BaudError = CalcBaudRate - BaudRate; + } + + /* Find the calculated baud rate closest to requested baud rate. */ + if (Best_Error > BaudError) { + + Best_BRGR = BRGR_Value; + Best_BAUDDIV = IterBAUDDIV; + Best_Error = BaudError; + } + } + + /* Make sure the best error is not too large. */ + PercentError = (Best_Error * 100) / BaudRate; + if (XUARTPS_MAX_BAUD_ERROR_RATE < PercentError) { + return XST_UART_BAUD_ERROR; + } + + /* Disable TX and RX to avoid glitches when setting the baud rate. */ + XUartPs_DisableUart(InstancePtr); + + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, + XUARTPS_BAUDGEN_OFFSET, Best_BRGR); + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, + XUARTPS_BAUDDIV_OFFSET, Best_BAUDDIV); + + /* RX and TX SW reset */ + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_CR_OFFSET, + XUARTPS_CR_TXRST | XUARTPS_CR_RXRST); + + /* Enable device */ + XUartPs_EnableUart(InstancePtr); + + InstancePtr->BaudRate = BaudRate; + + return XST_SUCCESS; + +} + +/****************************************************************************/ +/** +* +* This function is a stub handler that is the default handler such that if the +* application has not set the handler when interrupts are enabled, this +* function will be called. +* +* @param CallBackRef is unused by this function. +* @param Event is unused by this function. +* @param ByteCount is unused by this function. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +static void XUartPs_StubHandler(void *CallBackRef, u32 Event, + u32 ByteCount) +{ + (void) CallBackRef; + (void) Event; + (void) ByteCount; + /* Assert occurs always since this is a stub and should never be called */ + Xil_AssertVoidAlways(); +} +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/uartps_v3_7/src/xuartps.h b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/uartps_v3_7/src/xuartps.h new file mode 100644 index 0000000..c6c2a0a --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/uartps_v3_7/src/xuartps.h @@ -0,0 +1,517 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xuartps.h +* @addtogroup uartps_v3_5 +* @{ +* @details +* +* This driver supports the following features: +* +* - Dynamic data format (baud rate, data bits, stop bits, parity) +* - Polled mode +* - Interrupt driven mode +* - Transmit and receive FIFOs (32 byte FIFO depth) +* - Access to the external modem control lines +* +* Initialization & Configuration +* +* The XUartPs_Config structure is used by the driver to configure itself. +* Fields inside this structure are properties of XUartPs based on its hardware +* build. +* +* To support multiple runtime loading and initialization strategies employed +* by various operating systems, the driver instance can be initialized in the +* following way: +* +* - XUartPs_CfgInitialize(InstancePtr, CfgPtr, EffectiveAddr) - Uses a +* configuration structure provided by the caller. If running in a system +* with address translation, the parameter EffectiveAddr should be the +* virtual address. +* +* Baud Rate +* +* The UART has an internal baud rate generator, which furnishes the baud rate +* clock for both the receiver and the transmitter. Ther input clock frequency +* can be either the master clock or the master clock divided by 8, configured +* through the mode register. +* +* Accompanied with the baud rate divider register, the baud rate is determined +* by: +*
+*	baud_rate = input_clock / (bgen * (bdiv + 1)
+* 
+* where bgen is the value of the baud rate generator, and bdiv is the value of +* baud rate divider. +* +* Interrupts +* +* The FIFOs are not flushed when the driver is initialized, but a function is +* provided to allow the user to reset the FIFOs if desired. +* +* The driver defaults to no interrupts at initialization such that interrupts +* must be enabled if desired. An interrupt is generated for one of the +* following conditions. +* +* - A change in the modem signals +* - Data in the receive FIFO for a configuable time without receiver activity +* - A parity error +* - A framing error +* - An overrun error +* - Transmit FIFO is full +* - Transmit FIFO is empty +* - Receive FIFO is full +* - Receive FIFO is empty +* - Data in the receive FIFO equal to the receive threshold +* +* The application can control which interrupts are enabled using the +* XUartPs_SetInterruptMask() function. +* +* In order to use interrupts, it is necessary for the user to connect the +* driver interrupt handler, XUartPs_InterruptHandler(), to the interrupt +* system of the application. A separate handler should be provided by the +* application to communicate with the interrupt system, and conduct +* application specific interrupt handling. An application registers its own +* handler through the XUartPs_SetHandler() function. +* +* Data Transfer +* +* The functions, XUartPs_Send() and XUartPs_Recv(), are provided in the +* driver to allow data to be sent and received. They can be used in either +* polled or interrupt mode. +* +* @note +* +* The default configuration for the UART after initialization is: +* +* - 9,600 bps or XPAR_DFT_BAUDRATE if defined +* - 8 data bits +* - 1 stop bit +* - no parity +* - FIFO's are enabled with a receive threshold of 8 bytes +* - The RX timeout is enabled with a timeout of 1 (4 char times) +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date	Changes
+* ----- ------ -------- ----------------------------------------------
+* 1.00a	drg/jz 01/12/10 First Release
+* 1.00a sdm    09/27/11 Fixed compiler warnings and also a bug
+*		        in XUartPs_SetFlowDelay where the value was not
+*			being written to the register.
+* 1.01a sdm    12/20/11 Removed the InputClockHz parameter from the XUartPs
+*			instance structure and the driver is updated to use
+*			InputClockHz parameter from the XUartPs_Config config
+*			structure.
+*			Added a parameter to XUartPs_Config structure which
+*			specifies whether the user has selected Modem pins
+*			to be connected to MIO or FMIO.
+*			Added the tcl file to generate the xparameters.h
+* 1.02a sg     05/16/12	Changed XUARTPS_RXWM_MASK to 0x3F for CR 652540 fix.
+* 1.03a sg     07/16/12 Updated XUARTPS_FORMAT_7_BITS and XUARTPS_FORMAT_6_BITS
+*			with the correct values for CR 666724
+* 			Added defines for XUARTPS_IXR_TOVR,  XUARTPS_IXR_TNFUL
+*			and XUARTPS_IXR_TTRIG.
+*			Modified the name of these defines
+*			XUARTPS_MEDEMSR_DCDX to XUARTPS_MODEMSR_DDCD
+*			XUARTPS_MEDEMSR_RIX to XUARTPS_MODEMSR_TERI
+*			XUARTPS_MEDEMSR_DSRX to XUARTPS_MODEMSR_DDSR
+*			XUARTPS_MEDEMSR_CTSX to XUARTPS_MODEMSR_DCTS
+* 1.05a hk     08/22/13 Added API for uart reset and related
+*			constant definitions.
+* 2.0   hk      03/07/14 Version number revised.
+* 2.1   hk     04/16/14 Change XUARTPS_MAX_RATE to 921600. CR# 780625.
+* 2.2   hk     06/23/14 SW reset of RX and TX should be done when changing
+*                       baud rate. CR# 804281.
+* 3.0   vm     12/09/14 Modified source code according to misrac guideline.
+*			Support for Zynq Ultrascale Mp added.
+* 3.1	kvn    04/10/15 Modified code for latest RTL changes. Also added
+*						platform variable in driver instance structure.
+* 3.1   adk   14/03/16  Include interrupt examples in the peripheral test when
+*			uart is connected to a valid interrupt controller CR#946803.
+* 3.2   rk     07/20/16 Modified the logic for transmission break bit set
+* 3.4   ms     01/23/17 Added xil_printf statement in main function for all
+*                       examples to ensure that "Successfully ran" and "Failed"
+*                       strings are available in all examples. This is a fix
+*                       for CR-965028.
+*       ms     03/17/17 Added readme.txt file in examples folder for doxygen
+*                       generation.
+* 3.6   ms     02/16/18 Updates the flow control mode offset value in modem
+*                       control register.
+* 3.7   aru    08/17/18 Resolved MISRA-C:2012 compliance mandatory violations.
+*
+* 
+* +*****************************************************************************/ + +#ifndef XUARTPS_H /* prevent circular inclusions */ +#define XUARTPS_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files ********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xstatus.h" +#include "xuartps_hw.h" +#include "xplatform_info.h" + +/************************** Constant Definitions ****************************/ + +/* + * The following constants indicate the max and min baud rates and these + * numbers are based only on the testing that has been done. The hardware + * is capable of other baud rates. + */ +#define XUARTPS_MAX_RATE 921600U +#define XUARTPS_MIN_RATE 110U + +#define XUARTPS_DFT_BAUDRATE 115200U /* Default baud rate */ + +/** @name Configuration options + * @{ + */ +/** + * These constants specify the options that may be set or retrieved + * with the driver, each is a unique bit mask such that multiple options + * may be specified. These constants indicate the available options + * in active state. + * + */ + +#define XUARTPS_OPTION_SET_BREAK 0x0080U /**< Starts break transmission */ +#define XUARTPS_OPTION_STOP_BREAK 0x0040U /**< Stops break transmission */ +#define XUARTPS_OPTION_RESET_TMOUT 0x0020U /**< Reset the receive timeout */ +#define XUARTPS_OPTION_RESET_TX 0x0010U /**< Reset the transmitter */ +#define XUARTPS_OPTION_RESET_RX 0x0008U /**< Reset the receiver */ +#define XUARTPS_OPTION_ASSERT_RTS 0x0004U /**< Assert the RTS bit */ +#define XUARTPS_OPTION_ASSERT_DTR 0x0002U /**< Assert the DTR bit */ +#define XUARTPS_OPTION_SET_FCM 0x0001U /**< Turn on flow control mode */ +/*@}*/ + + +/** @name Channel Operational Mode + * + * The UART can operate in one of four modes: Normal, Local Loopback, Remote + * Loopback, or automatic echo. + * + * @{ + */ + +#define XUARTPS_OPER_MODE_NORMAL (u8)0x00U /**< Normal Mode */ +#define XUARTPS_OPER_MODE_AUTO_ECHO (u8)0x01U /**< Auto Echo Mode */ +#define XUARTPS_OPER_MODE_LOCAL_LOOP (u8)0x02U /**< Local Loopback Mode */ +#define XUARTPS_OPER_MODE_REMOTE_LOOP (u8)0x03U /**< Remote Loopback Mode */ + +/* @} */ + +/** @name Data format values + * + * These constants specify the data format that the driver supports. + * The data format includes the number of data bits, the number of stop + * bits and parity. + * + * @{ + */ +#define XUARTPS_FORMAT_8_BITS 0U /**< 8 data bits */ +#define XUARTPS_FORMAT_7_BITS 2U /**< 7 data bits */ +#define XUARTPS_FORMAT_6_BITS 3U /**< 6 data bits */ + +#define XUARTPS_FORMAT_NO_PARITY 4U /**< No parity */ +#define XUARTPS_FORMAT_MARK_PARITY 3U /**< Mark parity */ +#define XUARTPS_FORMAT_SPACE_PARITY 2U /**< parity */ +#define XUARTPS_FORMAT_ODD_PARITY 1U /**< Odd parity */ +#define XUARTPS_FORMAT_EVEN_PARITY 0U /**< Even parity */ + +#define XUARTPS_FORMAT_2_STOP_BIT 2U /**< 2 stop bits */ +#define XUARTPS_FORMAT_1_5_STOP_BIT 1U /**< 1.5 stop bits */ +#define XUARTPS_FORMAT_1_STOP_BIT 0U /**< 1 stop bit */ +/*@}*/ + +/** @name Callback events + * + * These constants specify the handler events that an application can handle + * using its specific handler function. Note that these constants are not bit + * mask, so only one event can be passed to an application at a time. + * + * @{ + */ +#define XUARTPS_EVENT_RECV_DATA 1U /**< Data receiving done */ +#define XUARTPS_EVENT_RECV_TOUT 2U /**< A receive timeout occurred */ +#define XUARTPS_EVENT_SENT_DATA 3U /**< Data transmission done */ +#define XUARTPS_EVENT_RECV_ERROR 4U /**< A receive error detected */ +#define XUARTPS_EVENT_MODEM 5U /**< Modem status changed */ +#define XUARTPS_EVENT_PARE_FRAME_BRKE 6U /**< A receive parity, frame, break + * error detected */ +#define XUARTPS_EVENT_RECV_ORERR 7U /**< A receive overrun error detected */ +/*@}*/ + + +/**************************** Type Definitions ******************************/ + +/** + * This typedef contains configuration information for the device. + */ +typedef struct { + u16 DeviceId; /**< Unique ID of device */ + u32 BaseAddress; /**< Base address of device (IPIF) */ + u32 InputClockHz;/**< Input clock frequency */ + s32 ModemPinsConnected; /** Specifies whether modem pins are connected + * to MIO or FMIO */ +} XUartPs_Config; + +/* Keep track of state information about a data buffer in the interrupt mode. */ +typedef struct { + u8 *NextBytePtr; + u32 RequestedBytes; + u32 RemainingBytes; +} XUartPsBuffer; + +/** + * Keep track of data format setting of a device. + */ +typedef struct { + u32 BaudRate; /**< In bps, ie 1200 */ + u32 DataBits; /**< Number of data bits */ + u32 Parity; /**< Parity */ + u8 StopBits; /**< Number of stop bits */ +} XUartPsFormat; + +/******************************************************************************/ +/** + * This data type defines a handler that an application defines to communicate + * with interrupt system to retrieve state information about an application. + * + * @param CallBackRef is a callback reference passed in by the upper layer + * when setting the handler, and is passed back to the upper layer + * when the handler is called. It is used to find the device driver + * instance. + * @param Event contains one of the event constants indicating events that + * have occurred. + * @param EventData contains the number of bytes sent or received at the + * time of the call for send and receive events and contains the + * modem status for modem events. + * + ******************************************************************************/ +typedef void (*XUartPs_Handler) (void *CallBackRef, u32 Event, + u32 EventData); + +/** + * The XUartPs driver instance data structure. A pointer to an instance data + * structure is passed around by functions to refer to a specific driver + * instance. + */ +typedef struct { + XUartPs_Config Config; /* Configuration data structure */ + u32 InputClockHz; /* Input clock frequency */ + u32 IsReady; /* Device is initialized and ready */ + u32 BaudRate; /* Current baud rate */ + + XUartPsBuffer SendBuffer; + XUartPsBuffer ReceiveBuffer; + + XUartPs_Handler Handler; + void *CallBackRef; /* Callback reference for event handler */ + u32 Platform; + u8 is_rxbs_error; +} XUartPs; + + +/***************** Macros (Inline Functions) Definitions ********************/ + +/****************************************************************************/ +/** +* Get the UART Channel Status Register. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* +* @return The value read from the register. +* +* @note C-Style signature: +* u16 XUartPs_GetChannelStatus(XUartPs *InstancePtr) +* +******************************************************************************/ +#define XUartPs_GetChannelStatus(InstancePtr) \ + Xil_In32(((InstancePtr)->Config.BaseAddress) + (u32)XUARTPS_SR_OFFSET) + +/****************************************************************************/ +/** +* Get the UART Mode Control Register. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* +* @return The value read from the register. +* +* @note C-Style signature: +* u32 XUartPs_GetControl(XUartPs *InstancePtr) +* +******************************************************************************/ +#define XUartPs_GetModeControl(InstancePtr) \ + Xil_In32(((InstancePtr)->Config.BaseAddress) + (u32)XUARTPS_CR_OFFSET) + +/****************************************************************************/ +/** +* Set the UART Mode Control Register. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* @param RegisterValue is the value to be written to the register. +* +* @return None. +* +* @note C-Style signature: +* void XUartPs_SetModeControl(XUartPs *InstancePtr, u16 RegisterValue) +* +******************************************************************************/ +#define XUartPs_SetModeControl(InstancePtr, RegisterValue) \ + Xil_Out32(((InstancePtr)->Config.BaseAddress) + (u32)XUARTPS_CR_OFFSET, \ + (u32)(RegisterValue)) + +/****************************************************************************/ +/** +* Enable the transmitter and receiver of the UART. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* +* @return None. +* +* @note C-Style signature: +* void XUartPs_EnableUart(XUartPs *InstancePtr) +* +******************************************************************************/ +#define XUartPs_EnableUart(InstancePtr) \ + Xil_Out32(((InstancePtr)->Config.BaseAddress + (u32)XUARTPS_CR_OFFSET), \ + ((Xil_In32((InstancePtr)->Config.BaseAddress + (u32)XUARTPS_CR_OFFSET) & \ + (u32)(~XUARTPS_CR_EN_DIS_MASK)) | ((u32)XUARTPS_CR_RX_EN | (u32)XUARTPS_CR_TX_EN))) + +/****************************************************************************/ +/** +* Disable the transmitter and receiver of the UART. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* +* @return None. +* +* @note C-Style signature: +* void XUartPs_DisableUart(XUartPs *InstancePtr) +* +******************************************************************************/ +#define XUartPs_DisableUart(InstancePtr) \ + Xil_Out32(((InstancePtr)->Config.BaseAddress + (u32)XUARTPS_CR_OFFSET), \ + (((Xil_In32((InstancePtr)->Config.BaseAddress + (u32)XUARTPS_CR_OFFSET)) & \ + (u32)(~XUARTPS_CR_EN_DIS_MASK)) | ((u32)XUARTPS_CR_RX_DIS | (u32)XUARTPS_CR_TX_DIS))) + +/****************************************************************************/ +/** +* Determine if the transmitter FIFO is empty. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* +* @return +* - TRUE if a byte can be sent +* - FALSE if the Transmitter Fifo is not empty +* +* @note C-Style signature: +* u32 XUartPs_IsTransmitEmpty(XUartPs InstancePtr) +* +******************************************************************************/ +#define XUartPs_IsTransmitEmpty(InstancePtr) \ + ((Xil_In32(((InstancePtr)->Config.BaseAddress) + (u32)XUARTPS_SR_OFFSET) & \ + (u32)XUARTPS_SR_TXEMPTY) == (u32)XUARTPS_SR_TXEMPTY) + + +/************************** Function Prototypes *****************************/ + +/* Static lookup function implemented in xuartps_sinit.c */ +XUartPs_Config *XUartPs_LookupConfig(u16 DeviceId); + +/* Interface functions implemented in xuartps.c */ +s32 XUartPs_CfgInitialize(XUartPs *InstancePtr, + XUartPs_Config * Config, u32 EffectiveAddr); + +u32 XUartPs_Send(XUartPs *InstancePtr,u8 *BufferPtr, + u32 NumBytes); + +u32 XUartPs_Recv(XUartPs *InstancePtr,u8 *BufferPtr, + u32 NumBytes); + +s32 XUartPs_SetBaudRate(XUartPs *InstancePtr, u32 BaudRate); + +/* Options functions in xuartps_options.c */ +void XUartPs_SetOptions(XUartPs *InstancePtr, u16 Options); + +u16 XUartPs_GetOptions(XUartPs *InstancePtr); + +void XUartPs_SetFifoThreshold(XUartPs *InstancePtr, u8 TriggerLevel); + +u8 XUartPs_GetFifoThreshold(XUartPs *InstancePtr); + +u16 XUartPs_GetModemStatus(XUartPs *InstancePtr); + +u32 XUartPs_IsSending(XUartPs *InstancePtr); + +u8 XUartPs_GetOperMode(XUartPs *InstancePtr); + +void XUartPs_SetOperMode(XUartPs *InstancePtr, u8 OperationMode); + +u8 XUartPs_GetFlowDelay(XUartPs *InstancePtr); + +void XUartPs_SetFlowDelay(XUartPs *InstancePtr, u8 FlowDelayValue); + +u8 XUartPs_GetRecvTimeout(XUartPs *InstancePtr); + +void XUartPs_SetRecvTimeout(XUartPs *InstancePtr, u8 RecvTimeout); + +s32 XUartPs_SetDataFormat(XUartPs *InstancePtr, XUartPsFormat * FormatPtr); + +void XUartPs_GetDataFormat(XUartPs *InstancePtr, XUartPsFormat * FormatPtr); + +/* interrupt functions in xuartps_intr.c */ +u32 XUartPs_GetInterruptMask(XUartPs *InstancePtr); + +void XUartPs_SetInterruptMask(XUartPs *InstancePtr, u32 Mask); + +void XUartPs_InterruptHandler(XUartPs *InstancePtr); + +void XUartPs_SetHandler(XUartPs *InstancePtr, XUartPs_Handler FuncPtr, + void *CallBackRef); + +/* self-test functions in xuartps_selftest.c */ +s32 XUartPs_SelfTest(XUartPs *InstancePtr); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/uartps_v3_7/src/xuartps_g.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/uartps_v3_7/src/xuartps_g.c new file mode 100644 index 0000000..6980b9d --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/uartps_v3_7/src/xuartps_g.c @@ -0,0 +1,53 @@ + +/******************************************************************* +* +* CAUTION: This file is automatically generated by HSI. +* Version: 2019.1.3 +* DO NOT EDIT. +* +* Copyright (C) 2010-2023 Xilinx, Inc. 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 +*XILINX 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. +* +*Except as contained in this notice, the name of the Xilinx shall not be used +*in advertising or otherwise to promote the sale, use or other dealings in +*this Software without prior written authorization from Xilinx. +* + +* +* Description: Driver configuration +* +*******************************************************************/ + +#include "xparameters.h" +#include "xuartps.h" + +/* +* The configuration table for devices +*/ + +XUartPs_Config XUartPs_ConfigTable[XPAR_XUARTPS_NUM_INSTANCES] = +{ + { + XPAR_PS7_UART_1_DEVICE_ID, + XPAR_PS7_UART_1_BASEADDR, + XPAR_PS7_UART_1_UART_CLK_FREQ_HZ, + XPAR_PS7_UART_1_HAS_MODEM + } +}; + + diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/uartps_v3_7/src/xuartps_hw.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/uartps_v3_7/src/xuartps_hw.c new file mode 100644 index 0000000..11462ba --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/uartps_v3_7/src/xuartps_hw.c @@ -0,0 +1,176 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xuartps_hw.c +* @addtogroup uartps_v3_5 +* @{ +* +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date	Changes
+* ----- ------ -------- ----------------------------------------------
+* 1.00	drg/jz 01/12/10 First Release
+* 1.05a hk     08/22/13 Added reset function
+* 3.00  kvn    02/13/15 Modified code for MISRA-C:2012 compliance.
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ +#include "xuartps_hw.h" + +/************************** Constant Definitions ****************************/ + + +/***************** Macros (Inline Functions) Definitions ********************/ + + +/************************** Function Prototypes ******************************/ + + +/************************** Variable Definitions *****************************/ + +/****************************************************************************/ +/** +* +* This function sends one byte using the device. This function operates in +* polled mode and blocks until the data has been put into the TX FIFO register. +* +* @param BaseAddress contains the base address of the device. +* @param Data contains the byte to be sent. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XUartPs_SendByte(u32 BaseAddress, u8 Data) +{ + /* Wait until there is space in TX FIFO */ + while (XUartPs_IsTransmitFull(BaseAddress)) { + ; + } + + /* Write the byte into the TX FIFO */ + XUartPs_WriteReg(BaseAddress, XUARTPS_FIFO_OFFSET, (u32)Data); +} + +/****************************************************************************/ +/** +* +* This function receives a byte from the device. It operates in polled mode +* and blocks until a byte has received. +* +* @param BaseAddress contains the base address of the device. +* +* @return The data byte received. +* +* @note None. +* +*****************************************************************************/ +u8 XUartPs_RecvByte(u32 BaseAddress) +{ + u32 RecievedByte; + /* Wait until there is data */ + while (!XUartPs_IsReceiveData(BaseAddress)) { + ; + } + RecievedByte = XUartPs_ReadReg(BaseAddress, XUARTPS_FIFO_OFFSET); + /* Return the byte received */ + return (u8)RecievedByte; +} + +/****************************************************************************/ +/** +* +* This function resets UART +* +* @param BaseAddress contains the base address of the device. +* +* @return None +* +* @note None. +* +*****************************************************************************/ +void XUartPs_ResetHw(u32 BaseAddress) +{ + + /* Disable interrupts */ + XUartPs_WriteReg(BaseAddress, XUARTPS_IDR_OFFSET, XUARTPS_IXR_MASK); + + /* Disable receive and transmit */ + XUartPs_WriteReg(BaseAddress, XUARTPS_CR_OFFSET, + ((u32)XUARTPS_CR_RX_DIS | (u32)XUARTPS_CR_TX_DIS)); + + /* + * Software reset of receive and transmit + * This clears the FIFO. + */ + XUartPs_WriteReg(BaseAddress, XUARTPS_CR_OFFSET, + ((u32)XUARTPS_CR_TXRST | (u32)XUARTPS_CR_RXRST)); + + /* Clear status flags - SW reset wont clear sticky flags. */ + XUartPs_WriteReg(BaseAddress, XUARTPS_ISR_OFFSET, XUARTPS_IXR_MASK); + + /* + * Mode register reset value : All zeroes + * Normal mode, even parity, 1 stop bit + */ + XUartPs_WriteReg(BaseAddress, XUARTPS_MR_OFFSET, + XUARTPS_MR_CHMODE_NORM); + + /* Rx and TX trigger register reset values */ + XUartPs_WriteReg(BaseAddress, XUARTPS_RXWM_OFFSET, + XUARTPS_RXWM_RESET_VAL); + XUartPs_WriteReg(BaseAddress, XUARTPS_TXWM_OFFSET, + XUARTPS_TXWM_RESET_VAL); + + /* Rx timeout disabled by default */ + XUartPs_WriteReg(BaseAddress, XUARTPS_RXTOUT_OFFSET, + XUARTPS_RXTOUT_DISABLE); + + /* Baud rate generator and dividor reset values */ + XUartPs_WriteReg(BaseAddress, XUARTPS_BAUDGEN_OFFSET, + XUARTPS_BAUDGEN_RESET_VAL); + XUartPs_WriteReg(BaseAddress, XUARTPS_BAUDDIV_OFFSET, + XUARTPS_BAUDDIV_RESET_VAL); + + /* + * Control register reset value - + * RX and TX are disable by default + */ + XUartPs_WriteReg(BaseAddress, XUARTPS_CR_OFFSET, + ((u32)XUARTPS_CR_RX_DIS | (u32)XUARTPS_CR_TX_DIS | + (u32)XUARTPS_CR_STOPBRK)); + +} +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/uartps_v3_7/src/xuartps_hw.h b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/uartps_v3_7/src/xuartps_hw.h new file mode 100644 index 0000000..8c46ecf --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/uartps_v3_7/src/xuartps_hw.h @@ -0,0 +1,447 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2017 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xuartps_hw.h +* @addtogroup uartps_v3_5 +* @{ +* +* This header file contains the hardware interface of an XUartPs device. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date	Changes
+* ----- ------ -------- ----------------------------------------------
+* 1.00	drg/jz 01/12/10 First Release
+* 1.03a sg     09/04/12 Added defines for XUARTPS_IXR_TOVR,  XUARTPS_IXR_TNFUL
+*			and XUARTPS_IXR_TTRIG.
+*			Modified the names of these defines
+*			XUARTPS_MEDEMSR_DCDX to XUARTPS_MODEMSR_DDCD
+*			XUARTPS_MEDEMSR_RIX to XUARTPS_MODEMSR_TERI
+*			XUARTPS_MEDEMSR_DSRX to XUARTPS_MODEMSR_DDSR
+*			XUARTPS_MEDEMSR_CTSX to XUARTPS_MODEMSR_DCTS
+* 1.05a hk     08/22/13 Added prototype for uart reset and related
+*			constant definitions.
+* 3.00  kvn    02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.1	kvn    04/10/15 Modified code for latest RTL changes.
+* 3.6   ms     02/16/18 Updates flow control mode offset value in
+*			modem control register.
+*
+* 
+* +******************************************************************************/ +#ifndef XUARTPS_HW_H /* prevent circular inclusions */ +#define XUARTPS_HW_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_io.h" + +/************************** Constant Definitions *****************************/ + +/** @name Register Map + * + * Register offsets for the UART. + * @{ + */ +#define XUARTPS_CR_OFFSET 0x0000U /**< Control Register [8:0] */ +#define XUARTPS_MR_OFFSET 0x0004U /**< Mode Register [9:0] */ +#define XUARTPS_IER_OFFSET 0x0008U /**< Interrupt Enable [12:0] */ +#define XUARTPS_IDR_OFFSET 0x000CU /**< Interrupt Disable [12:0] */ +#define XUARTPS_IMR_OFFSET 0x0010U /**< Interrupt Mask [12:0] */ +#define XUARTPS_ISR_OFFSET 0x0014U /**< Interrupt Status [12:0]*/ +#define XUARTPS_BAUDGEN_OFFSET 0x0018U /**< Baud Rate Generator [15:0] */ +#define XUARTPS_RXTOUT_OFFSET 0x001CU /**< RX Timeout [7:0] */ +#define XUARTPS_RXWM_OFFSET 0x0020U /**< RX FIFO Trigger Level [5:0] */ +#define XUARTPS_MODEMCR_OFFSET 0x0024U /**< Modem Control [5:0] */ +#define XUARTPS_MODEMSR_OFFSET 0x0028U /**< Modem Status [8:0] */ +#define XUARTPS_SR_OFFSET 0x002CU /**< Channel Status [14:0] */ +#define XUARTPS_FIFO_OFFSET 0x0030U /**< FIFO [7:0] */ +#define XUARTPS_BAUDDIV_OFFSET 0x0034U /**< Baud Rate Divider [7:0] */ +#define XUARTPS_FLOWDEL_OFFSET 0x0038U /**< Flow Delay [5:0] */ +#define XUARTPS_TXWM_OFFSET 0x0044U /**< TX FIFO Trigger Level [5:0] */ +#define XUARTPS_RXBS_OFFSET 0x0048U /**< RX FIFO Byte Status [11:0] */ +/* @} */ + +/** @name Control Register + * + * The Control register (CR) controls the major functions of the device. + * + * Control Register Bit Definition + */ + +#define XUARTPS_CR_STOPBRK 0x00000100U /**< Stop transmission of break */ +#define XUARTPS_CR_STARTBRK 0x00000080U /**< Set break */ +#define XUARTPS_CR_TORST 0x00000040U /**< RX timeout counter restart */ +#define XUARTPS_CR_TX_DIS 0x00000020U /**< TX disabled. */ +#define XUARTPS_CR_TX_EN 0x00000010U /**< TX enabled */ +#define XUARTPS_CR_RX_DIS 0x00000008U /**< RX disabled. */ +#define XUARTPS_CR_RX_EN 0x00000004U /**< RX enabled */ +#define XUARTPS_CR_EN_DIS_MASK 0x0000003CU /**< Enable/disable Mask */ +#define XUARTPS_CR_TXRST 0x00000002U /**< TX logic reset */ +#define XUARTPS_CR_RXRST 0x00000001U /**< RX logic reset */ +/* @}*/ + + +/** @name Mode Register + * + * The mode register (MR) defines the mode of transfer as well as the data + * format. If this register is modified during transmission or reception, + * data validity cannot be guaranteed. + * + * Mode Register Bit Definition + * @{ + */ +#define XUARTPS_MR_CCLK 0x00000400U /**< Input clock selection */ +#define XUARTPS_MR_CHMODE_R_LOOP 0x00000300U /**< Remote loopback mode */ +#define XUARTPS_MR_CHMODE_L_LOOP 0x00000200U /**< Local loopback mode */ +#define XUARTPS_MR_CHMODE_ECHO 0x00000100U /**< Auto echo mode */ +#define XUARTPS_MR_CHMODE_NORM 0x00000000U /**< Normal mode */ +#define XUARTPS_MR_CHMODE_SHIFT 8U /**< Mode shift */ +#define XUARTPS_MR_CHMODE_MASK 0x00000300U /**< Mode mask */ +#define XUARTPS_MR_STOPMODE_2_BIT 0x00000080U /**< 2 stop bits */ +#define XUARTPS_MR_STOPMODE_1_5_BIT 0x00000040U /**< 1.5 stop bits */ +#define XUARTPS_MR_STOPMODE_1_BIT 0x00000000U /**< 1 stop bit */ +#define XUARTPS_MR_STOPMODE_SHIFT 6U /**< Stop bits shift */ +#define XUARTPS_MR_STOPMODE_MASK 0x000000A0U /**< Stop bits mask */ +#define XUARTPS_MR_PARITY_NONE 0x00000020U /**< No parity mode */ +#define XUARTPS_MR_PARITY_MARK 0x00000018U /**< Mark parity mode */ +#define XUARTPS_MR_PARITY_SPACE 0x00000010U /**< Space parity mode */ +#define XUARTPS_MR_PARITY_ODD 0x00000008U /**< Odd parity mode */ +#define XUARTPS_MR_PARITY_EVEN 0x00000000U /**< Even parity mode */ +#define XUARTPS_MR_PARITY_SHIFT 3U /**< Parity setting shift */ +#define XUARTPS_MR_PARITY_MASK 0x00000038U /**< Parity mask */ +#define XUARTPS_MR_CHARLEN_6_BIT 0x00000006U /**< 6 bits data */ +#define XUARTPS_MR_CHARLEN_7_BIT 0x00000004U /**< 7 bits data */ +#define XUARTPS_MR_CHARLEN_8_BIT 0x00000000U /**< 8 bits data */ +#define XUARTPS_MR_CHARLEN_SHIFT 1U /**< Data Length shift */ +#define XUARTPS_MR_CHARLEN_MASK 0x00000006U /**< Data length mask */ +#define XUARTPS_MR_CLKSEL 0x00000001U /**< Input clock selection */ +/* @} */ + + +/** @name Interrupt Registers + * + * Interrupt control logic uses the interrupt enable register (IER) and the + * interrupt disable register (IDR) to set the value of the bits in the + * interrupt mask register (IMR). The IMR determines whether to pass an + * interrupt to the interrupt status register (ISR). + * Writing a 1 to IER Enbables an interrupt, writing a 1 to IDR disables an + * interrupt. IMR and ISR are read only, and IER and IDR are write only. + * Reading either IER or IDR returns 0x00. + * + * All four registers have the same bit definitions. + * + * @{ + */ +#define XUARTPS_IXR_RBRK 0x00002000U /**< Rx FIFO break detect interrupt */ +#define XUARTPS_IXR_TOVR 0x00001000U /**< Tx FIFO Overflow interrupt */ +#define XUARTPS_IXR_TNFUL 0x00000800U /**< Tx FIFO Nearly Full interrupt */ +#define XUARTPS_IXR_TTRIG 0x00000400U /**< Tx Trig interrupt */ +#define XUARTPS_IXR_DMS 0x00000200U /**< Modem status change interrupt */ +#define XUARTPS_IXR_TOUT 0x00000100U /**< Timeout error interrupt */ +#define XUARTPS_IXR_PARITY 0x00000080U /**< Parity error interrupt */ +#define XUARTPS_IXR_FRAMING 0x00000040U /**< Framing error interrupt */ +#define XUARTPS_IXR_OVER 0x00000020U /**< Overrun error interrupt */ +#define XUARTPS_IXR_TXFULL 0x00000010U /**< TX FIFO full interrupt. */ +#define XUARTPS_IXR_TXEMPTY 0x00000008U /**< TX FIFO empty interrupt. */ +#define XUARTPS_IXR_RXFULL 0x00000004U /**< RX FIFO full interrupt. */ +#define XUARTPS_IXR_RXEMPTY 0x00000002U /**< RX FIFO empty interrupt. */ +#define XUARTPS_IXR_RXOVR 0x00000001U /**< RX FIFO trigger interrupt. */ +#define XUARTPS_IXR_MASK 0x00003FFFU /**< Valid bit mask */ +/* @} */ + + +/** @name Baud Rate Generator Register + * + * The baud rate generator control register (BRGR) is a 16 bit register that + * controls the receiver bit sample clock and baud rate. + * Valid values are 1 - 65535. + * + * Bit Sample Rate = CCLK / BRGR, where the CCLK is selected by the MR_CCLK bit + * in the MR register. + * @{ + */ +#define XUARTPS_BAUDGEN_DISABLE 0x00000000U /**< Disable clock */ +#define XUARTPS_BAUDGEN_MASK 0x0000FFFFU /**< Valid bits mask */ +#define XUARTPS_BAUDGEN_RESET_VAL 0x0000028BU /**< Reset value */ + +/** @name Baud Divisor Rate register + * + * The baud rate divider register (BDIV) controls how much the bit sample + * rate is divided by. It sets the baud rate. + * Valid values are 0x04 to 0xFF. Writing a value less than 4 will be ignored. + * + * Baud rate = CCLK / ((BAUDDIV + 1) x BRGR), where the CCLK is selected by + * the MR_CCLK bit in the MR register. + * @{ + */ +#define XUARTPS_BAUDDIV_MASK 0x000000FFU /**< 8 bit baud divider mask */ +#define XUARTPS_BAUDDIV_RESET_VAL 0x0000000FU /**< Reset value */ +/* @} */ + + +/** @name Receiver Timeout Register + * + * Use the receiver timeout register (RTR) to detect an idle condition on + * the receiver data line. + * + * @{ + */ +#define XUARTPS_RXTOUT_DISABLE 0x00000000U /**< Disable time out */ +#define XUARTPS_RXTOUT_MASK 0x000000FFU /**< Valid bits mask */ + +/** @name Receiver FIFO Trigger Level Register + * + * Use the Receiver FIFO Trigger Level Register (RTRIG) to set the value at + * which the RX FIFO triggers an interrupt event. + * @{ + */ + +#define XUARTPS_RXWM_DISABLE 0x00000000U /**< Disable RX trigger interrupt */ +#define XUARTPS_RXWM_MASK 0x0000003FU /**< Valid bits mask */ +#define XUARTPS_RXWM_RESET_VAL 0x00000020U /**< Reset value */ +/* @} */ + +/** @name Transmit FIFO Trigger Level Register + * + * Use the Transmit FIFO Trigger Level Register (TTRIG) to set the value at + * which the TX FIFO triggers an interrupt event. + * @{ + */ + +#define XUARTPS_TXWM_MASK 0x0000003FU /**< Valid bits mask */ +#define XUARTPS_TXWM_RESET_VAL 0x00000020U /**< Reset value */ +/* @} */ + +/** @name Modem Control Register + * + * This register (MODEMCR) controls the interface with the modem or data set, + * or a peripheral device emulating a modem. + * + * @{ + */ +#define XUARTPS_MODEMCR_FCM 0x00000020U /**< Flow control mode */ +#define XUARTPS_MODEMCR_RTS 0x00000002U /**< Request to send */ +#define XUARTPS_MODEMCR_DTR 0x00000001U /**< Data terminal ready */ +/* @} */ + +/** @name Modem Status Register + * + * This register (MODEMSR) indicates the current state of the control lines + * from a modem, or another peripheral device, to the CPU. In addition, four + * bits of the modem status register provide change information. These bits + * are set to a logic 1 whenever a control input from the modem changes state. + * + * Note: Whenever the DCTS, DDSR, TERI, or DDCD bit is set to logic 1, a modem + * status interrupt is generated and this is reflected in the modem status + * register. + * + * @{ + */ +#define XUARTPS_MODEMSR_FCMS 0x00000100U /**< Flow control mode (FCMS) */ +#define XUARTPS_MODEMSR_DCD 0x00000080U /**< Complement of DCD input */ +#define XUARTPS_MODEMSR_RI 0x00000040U /**< Complement of RI input */ +#define XUARTPS_MODEMSR_DSR 0x00000020U /**< Complement of DSR input */ +#define XUARTPS_MODEMSR_CTS 0x00000010U /**< Complement of CTS input */ +#define XUARTPS_MODEMSR_DDCD 0x00000008U /**< Delta DCD indicator */ +#define XUARTPS_MODEMSR_TERI 0x00000004U /**< Trailing Edge Ring Indicator */ +#define XUARTPS_MODEMSR_DDSR 0x00000002U /**< Change of DSR */ +#define XUARTPS_MODEMSR_DCTS 0x00000001U /**< Change of CTS */ +/* @} */ + +/** @name Channel Status Register + * + * The channel status register (CSR) is provided to enable the control logic + * to monitor the status of bits in the channel interrupt status register, + * even if these are masked out by the interrupt mask register. + * + * @{ + */ +#define XUARTPS_SR_TNFUL 0x00004000U /**< TX FIFO Nearly Full Status */ +#define XUARTPS_SR_TTRIG 0x00002000U /**< TX FIFO Trigger Status */ +#define XUARTPS_SR_FLOWDEL 0x00001000U /**< RX FIFO fill over flow delay */ +#define XUARTPS_SR_TACTIVE 0x00000800U /**< TX active */ +#define XUARTPS_SR_RACTIVE 0x00000400U /**< RX active */ +#define XUARTPS_SR_TXFULL 0x00000010U /**< TX FIFO full */ +#define XUARTPS_SR_TXEMPTY 0x00000008U /**< TX FIFO empty */ +#define XUARTPS_SR_RXFULL 0x00000004U /**< RX FIFO full */ +#define XUARTPS_SR_RXEMPTY 0x00000002U /**< RX FIFO empty */ +#define XUARTPS_SR_RXOVR 0x00000001U /**< RX FIFO fill over trigger */ +/* @} */ + +/** @name Flow Delay Register + * + * Operation of the flow delay register (FLOWDEL) is very similar to the + * receive FIFO trigger register. An internal trigger signal activates when the + * FIFO is filled to the level set by this register. This trigger will not + * cause an interrupt, although it can be read through the channel status + * register. In hardware flow control mode, RTS is deactivated when the trigger + * becomes active. RTS only resets when the FIFO level is four less than the + * level of the flow delay trigger and the flow delay trigger is not activated. + * A value less than 4 disables the flow delay. + * @{ + */ +#define XUARTPS_FLOWDEL_MASK XUARTPS_RXWM_MASK /**< Valid bit mask */ +/* @} */ + +/** @name Receiver FIFO Byte Status Register + * + * The Receiver FIFO Status register is used to have a continuous + * monitoring of the raw unmasked byte status information. The register + * contains frame, parity and break status information for the top + * four bytes in the RX FIFO. + * + * Receiver FIFO Byte Status Register Bit Definition + * @{ + */ +#define XUARTPS_RXBS_BYTE3_BRKE 0x00000800U /**< Byte3 Break Error */ +#define XUARTPS_RXBS_BYTE3_FRME 0x00000400U /**< Byte3 Frame Error */ +#define XUARTPS_RXBS_BYTE3_PARE 0x00000200U /**< Byte3 Parity Error */ +#define XUARTPS_RXBS_BYTE2_BRKE 0x00000100U /**< Byte2 Break Error */ +#define XUARTPS_RXBS_BYTE2_FRME 0x00000080U /**< Byte2 Frame Error */ +#define XUARTPS_RXBS_BYTE2_PARE 0x00000040U /**< Byte2 Parity Error */ +#define XUARTPS_RXBS_BYTE1_BRKE 0x00000020U /**< Byte1 Break Error */ +#define XUARTPS_RXBS_BYTE1_FRME 0x00000010U /**< Byte1 Frame Error */ +#define XUARTPS_RXBS_BYTE1_PARE 0x00000008U /**< Byte1 Parity Error */ +#define XUARTPS_RXBS_BYTE0_BRKE 0x00000004U /**< Byte0 Break Error */ +#define XUARTPS_RXBS_BYTE0_FRME 0x00000002U /**< Byte0 Frame Error */ +#define XUARTPS_RXBS_BYTE0_PARE 0x00000001U /**< Byte0 Parity Error */ +#define XUARTPS_RXBS_MASK 0x00000007U /**< 3 bit RX byte status mask */ +/* @} */ + + +/* + * Defines for backwards compatabilty, will be removed + * in the next version of the driver + */ +#define XUARTPS_MEDEMSR_DCDX XUARTPS_MODEMSR_DDCD +#define XUARTPS_MEDEMSR_RIX XUARTPS_MODEMSR_TERI +#define XUARTPS_MEDEMSR_DSRX XUARTPS_MODEMSR_DDSR +#define XUARTPS_MEDEMSR_CTSX XUARTPS_MODEMSR_DCTS + + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + +/****************************************************************************/ +/** +* Read a UART register. +* +* @param BaseAddress contains the base address of the device. +* @param RegOffset contains the offset from the base address of the +* device. +* +* @return The value read from the register. +* +* @note C-Style signature: +* u32 XUartPs_ReadReg(u32 BaseAddress, int RegOffset) +* +******************************************************************************/ +#define XUartPs_ReadReg(BaseAddress, RegOffset) \ + Xil_In32((BaseAddress) + (u32)(RegOffset)) + +/***************************************************************************/ +/** +* Write a UART register. +* +* @param BaseAddress contains the base address of the device. +* @param RegOffset contains the offset from the base address of the +* device. +* @param RegisterValue is the value to be written to the register. +* +* @return None. +* +* @note C-Style signature: +* void XUartPs_WriteReg(u32 BaseAddress, int RegOffset, +* u16 RegisterValue) +* +******************************************************************************/ +#define XUartPs_WriteReg(BaseAddress, RegOffset, RegisterValue) \ + Xil_Out32((BaseAddress) + (u32)(RegOffset), (u32)(RegisterValue)) + +/****************************************************************************/ +/** +* Determine if there is receive data in the receiver and/or FIFO. +* +* @param BaseAddress contains the base address of the device. +* +* @return TRUE if there is receive data, FALSE otherwise. +* +* @note C-Style signature: +* u32 XUartPs_IsReceiveData(u32 BaseAddress) +* +******************************************************************************/ +#define XUartPs_IsReceiveData(BaseAddress) \ + !((Xil_In32((BaseAddress) + XUARTPS_SR_OFFSET) & \ + (u32)XUARTPS_SR_RXEMPTY) == (u32)XUARTPS_SR_RXEMPTY) + +/****************************************************************************/ +/** +* Determine if a byte of data can be sent with the transmitter. +* +* @param BaseAddress contains the base address of the device. +* +* @return TRUE if the TX FIFO is full, FALSE if a byte can be put in the +* FIFO. +* +* @note C-Style signature: +* u32 XUartPs_IsTransmitFull(u32 BaseAddress) +* +******************************************************************************/ +#define XUartPs_IsTransmitFull(BaseAddress) \ + ((Xil_In32((BaseAddress) + XUARTPS_SR_OFFSET) & \ + (u32)XUARTPS_SR_TXFULL) == (u32)XUARTPS_SR_TXFULL) + +/************************** Function Prototypes ******************************/ + +void XUartPs_SendByte(u32 BaseAddress, u8 Data); + +u8 XUartPs_RecvByte(u32 BaseAddress); + +void XUartPs_ResetHw(u32 BaseAddress); + +/************************** Variable Definitions *****************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/uartps_v3_7/src/xuartps_intr.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/uartps_v3_7/src/xuartps_intr.c new file mode 100644 index 0000000..88eed1e --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/uartps_v3_7/src/xuartps_intr.c @@ -0,0 +1,447 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xuartps_intr.c +* @addtogroup uartps_v3_5 +* @{ +* +* This file contains the functions for interrupt handling +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date	Changes
+* ----- ------ -------- -----------------------------------------------
+* 1.00  drg/jz 01/13/10 First Release
+* 3.00  kvn    02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.1	kvn    04/10/15 Modified code for latest RTL changes.
+* 3.7   aru    08/17/18 Resolved MISRA-C mandatory violations.(CR#1007755)
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ + +#include "xuartps.h" + +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Function Prototypes *****************************/ + +static void ReceiveDataHandler(XUartPs *InstancePtr); +static void SendDataHandler(XUartPs *InstancePtr, u32 IsrStatus); +static void ReceiveErrorHandler(XUartPs *InstancePtr, u32 IsrStatus); +static void ReceiveTimeoutHandler(XUartPs *InstancePtr); +static void ModemHandler(XUartPs *InstancePtr); + + +/* Internal function prototypes implemented in xuartps.c */ +extern u32 XUartPs_ReceiveBuffer(XUartPs *InstancePtr); +extern u32 XUartPs_SendBuffer(XUartPs *InstancePtr); + +/************************** Variable Definitions ****************************/ + +typedef void (*Handler)(XUartPs *InstancePtr); + +/****************************************************************************/ +/** +* +* This function gets the interrupt mask +* +* @param InstancePtr is a pointer to the XUartPs instance. +* +* @return +* The current interrupt mask. The mask indicates which interupts +* are enabled. +* +* @note None. +* +*****************************************************************************/ +u32 XUartPs_GetInterruptMask(XUartPs *InstancePtr) +{ + /* Assert validates the input argument */ + Xil_AssertNonvoid(InstancePtr != NULL); + + /* Read the Interrupt Mask register */ + return (XUartPs_ReadReg(InstancePtr->Config.BaseAddress, + XUARTPS_IMR_OFFSET)); +} + +/****************************************************************************/ +/** +* +* This function sets the interrupt mask. +* +* @param InstancePtr is a pointer to the XUartPs instance +* @param Mask contains the interrupts to be enabled or disabled. +* A '1' enables an interupt, and a '0' disables. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XUartPs_SetInterruptMask(XUartPs *InstancePtr, u32 Mask) +{ + u32 TempMask = Mask; + /* Assert validates the input arguments */ + Xil_AssertVoid(InstancePtr != NULL); + + TempMask &= (u32)XUARTPS_IXR_MASK; + + /* Write the mask to the IER Register */ + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, + XUARTPS_IER_OFFSET, TempMask); + + /* Write the inverse of the Mask to the IDR register */ + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, + XUARTPS_IDR_OFFSET, (~TempMask)); + +} + +/****************************************************************************/ +/** +* +* This function sets the handler that will be called when an event (interrupt) +* occurs that needs application's attention. +* +* @param InstancePtr is a pointer to the XUartPs instance +* @param FuncPtr is the pointer to the callback function. +* @param CallBackRef is the upper layer callback reference passed back +* when the callback function is invoked. +* +* @return None. +* +* @note +* +* There is no assert on the CallBackRef since the driver doesn't know what it +* is (nor should it) +* +*****************************************************************************/ +void XUartPs_SetHandler(XUartPs *InstancePtr, XUartPs_Handler FuncPtr, + void *CallBackRef) +{ + /* + * Asserts validate the input arguments + * CallBackRef not checked, no way to know what is valid + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(FuncPtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + InstancePtr->Handler = (XUartPs_Handler)FuncPtr; + InstancePtr->CallBackRef = CallBackRef; +} + +/****************************************************************************/ +/** +* +* This function is the interrupt handler for the driver. +* It must be connected to an interrupt system by the application such that it +* can be called when an interrupt occurs. +* +* @param InstancePtr contains a pointer to the driver instance +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XUartPs_InterruptHandler(XUartPs *InstancePtr) +{ + u32 IsrStatus; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the interrupt ID register to determine which + * interrupt is active + */ + IsrStatus = XUartPs_ReadReg(InstancePtr->Config.BaseAddress, + XUARTPS_IMR_OFFSET); + + IsrStatus &= XUartPs_ReadReg(InstancePtr->Config.BaseAddress, + XUARTPS_ISR_OFFSET); + + /* Dispatch an appropriate handler. */ + if((IsrStatus & ((u32)XUARTPS_IXR_RXOVR | (u32)XUARTPS_IXR_RXEMPTY | + (u32)XUARTPS_IXR_RXFULL)) != (u32)0) { + /* Received data interrupt */ + ReceiveDataHandler(InstancePtr); + } + + if((IsrStatus & ((u32)XUARTPS_IXR_TXEMPTY | (u32)XUARTPS_IXR_TXFULL)) + != (u32)0) { + /* Transmit data interrupt */ + SendDataHandler(InstancePtr, IsrStatus); + } + + /* XUARTPS_IXR_RBRK is applicable only for Zynq Ultrascale+ MP */ + if ((IsrStatus & ((u32)XUARTPS_IXR_OVER | (u32)XUARTPS_IXR_FRAMING | + (u32)XUARTPS_IXR_PARITY | (u32)XUARTPS_IXR_RBRK)) != (u32)0) { + /* Received Error Status interrupt */ + ReceiveErrorHandler(InstancePtr, IsrStatus); + } + + if((IsrStatus & ((u32)XUARTPS_IXR_TOUT)) != (u32)0) { + /* Received Timeout interrupt */ + ReceiveTimeoutHandler(InstancePtr); + } + + if((IsrStatus & ((u32)XUARTPS_IXR_DMS)) != (u32)0) { + /* Modem status interrupt */ + ModemHandler(InstancePtr); + } + + /* Clear the interrupt status. */ + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_ISR_OFFSET, + IsrStatus); + +} + +/****************************************************************************/ +/* +* +* This function handles interrupts for receive errors which include +* overrun errors, framing errors, parity errors, and the break interrupt. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +static void ReceiveErrorHandler(XUartPs *InstancePtr, u32 IsrStatus) +{ + u32 EventData; + u32 Event; + + InstancePtr->is_rxbs_error = 0; + + if ((InstancePtr->Platform == XPLAT_ZYNQ_ULTRA_MP) && + (IsrStatus & ((u32)XUARTPS_IXR_PARITY | (u32)XUARTPS_IXR_RBRK + | (u32)XUARTPS_IXR_FRAMING))) { + InstancePtr->is_rxbs_error = 1; + } + /* + * If there are bytes still to be received in the specified buffer + * go ahead and receive them. Removing bytes from the RX FIFO will + * clear the interrupt. + */ + + (void)XUartPs_ReceiveBuffer(InstancePtr); + + if (!(InstancePtr->is_rxbs_error)) { + Event = XUARTPS_EVENT_RECV_ERROR; + EventData = InstancePtr->ReceiveBuffer.RequestedBytes - + InstancePtr->ReceiveBuffer.RemainingBytes; + + /* + * Call the application handler to indicate that there is a receive + * error or a break interrupt, if the application cares about the + * error it call a function to get the last errors. + */ + InstancePtr->Handler(InstancePtr->CallBackRef, + Event, + EventData); + } +} + +/****************************************************************************/ +/** +* +* This function handles the receive timeout interrupt. This interrupt occurs +* whenever a number of bytes have been present in the RX FIFO and the receive +* data line has been idle for at lease 4 or more character times, (the timeout +* is set using XUartPs_SetrecvTimeout() function). +* +* @param InstancePtr is a pointer to the XUartPs instance +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +static void ReceiveTimeoutHandler(XUartPs *InstancePtr) +{ + u32 Event; + + /* + * If there are bytes still to be received in the specified buffer + * go ahead and receive them. Removing bytes from the RX FIFO will + * clear the interrupt. + */ + if (InstancePtr->ReceiveBuffer.RemainingBytes != (u32)0) { + (void)XUartPs_ReceiveBuffer(InstancePtr); + } + + /* + * If there are no more bytes to receive then indicate that this is + * not a receive timeout but the end of the buffer reached, a timeout + * normally occurs if # of bytes is not divisible by FIFO threshold, + * don't rely on previous test of remaining bytes since receive + * function updates it + */ + if (InstancePtr->ReceiveBuffer.RemainingBytes != (u32)0) { + Event = XUARTPS_EVENT_RECV_TOUT; + } else { + Event = XUARTPS_EVENT_RECV_DATA; + } + + /* + * Call the application handler to indicate that there is a receive + * timeout or data event + */ + InstancePtr->Handler(InstancePtr->CallBackRef, Event, + InstancePtr->ReceiveBuffer.RequestedBytes - + InstancePtr->ReceiveBuffer.RemainingBytes); + +} +/****************************************************************************/ +/** +* +* This function handles the interrupt when data is in RX FIFO. +* +* @param InstancePtr is a pointer to the XUartPs instance +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +static void ReceiveDataHandler(XUartPs *InstancePtr) +{ + /* + * If there are bytes still to be received in the specified buffer + * go ahead and receive them. Removing bytes from the RX FIFO will + * clear the interrupt. + */ + if (InstancePtr->ReceiveBuffer.RemainingBytes != (u32)0) { + (void)XUartPs_ReceiveBuffer(InstancePtr); + } + + /* If the last byte of a message was received then call the application + * handler, this code should not use an else from the previous check of + * the number of bytes to receive because the call to receive the buffer + * updates the bytes ramained + */ + if (InstancePtr->ReceiveBuffer.RemainingBytes == (u32)0) { + InstancePtr->Handler(InstancePtr->CallBackRef, + XUARTPS_EVENT_RECV_DATA, + (InstancePtr->ReceiveBuffer.RequestedBytes - + InstancePtr->ReceiveBuffer.RemainingBytes)); + } + +} + +/****************************************************************************/ +/** +* +* This function handles the interrupt when data has been sent, the transmit +* FIFO is empty (transmitter holding register). +* +* @param InstancePtr is a pointer to the XUartPs instance +* @param IsrStatus is the register value for channel status register +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +static void SendDataHandler(XUartPs *InstancePtr, u32 IsrStatus) +{ + + /* + * If there are not bytes to be sent from the specified buffer then disable + * the transmit interrupt so it will stop interrupting as it interrupts + * any time the FIFO is empty + */ + if (InstancePtr->SendBuffer.RemainingBytes == (u32)0) { + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, + XUARTPS_IDR_OFFSET, + ((u32)XUARTPS_IXR_TXEMPTY | (u32)XUARTPS_IXR_TXFULL)); + + /* Call the application handler to indicate the sending is done */ + InstancePtr->Handler(InstancePtr->CallBackRef, + XUARTPS_EVENT_SENT_DATA, + InstancePtr->SendBuffer.RequestedBytes - + InstancePtr->SendBuffer.RemainingBytes); + } + + /* If TX FIFO is empty, send more. */ + else if((IsrStatus & ((u32)XUARTPS_IXR_TXEMPTY)) != (u32)0) { + (void)XUartPs_SendBuffer(InstancePtr); + } + else { + /* Else with dummy entry for MISRA-C Compliance.*/ + ; + } +} + +/****************************************************************************/ +/** +* +* This function handles modem interrupts. It does not do any processing +* except to call the application handler to indicate a modem event. +* +* @param InstancePtr is a pointer to the XUartPs instance +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +static void ModemHandler(XUartPs *InstancePtr) +{ + u32 MsrRegister; + + /* + * Read the modem status register so that the interrupt is acknowledged + * and it can be passed to the callback handler with the event + */ + MsrRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress, + XUARTPS_MODEMSR_OFFSET); + + /* + * Call the application handler to indicate the modem status changed, + * passing the modem status and the event data in the call + */ + InstancePtr->Handler(InstancePtr->CallBackRef, + XUARTPS_EVENT_MODEM, + MsrRegister); + +} +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/uartps_v3_7/src/xuartps_options.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/uartps_v3_7/src/xuartps_options.c new file mode 100644 index 0000000..ee0db5f --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/uartps_v3_7/src/xuartps_options.c @@ -0,0 +1,760 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xuartps_options.c +* @addtogroup uartps_v3_5 +* @{ +* +* The implementation of the options functions for the XUartPs driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date	Changes
+* ----- ------ -------- -----------------------------------------------
+* 1.00  drg/jz 01/13/10 First Release
+* 1.00  sdm    09/27/11 Fixed a bug in XUartPs_SetFlowDelay where the input
+*			value was not being written to the register.
+* 3.00  kvn    02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.2   rk     07/20/16 Modified the logic for transmission break bit set
+*
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ + +#include "xuartps.h" + +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Variable Definitions ****************************/ +/* + * The following data type is a map from an option to the offset in the + * register to which it belongs as well as its bit mask in that register. + */ +typedef struct { + u16 Option; + u16 RegisterOffset; + u32 Mask; +} Mapping; + +/* + * Create the table which contains options which are to be processed to get/set + * the options. These options are table driven to allow easy maintenance and + * expansion of the options. + */ + +static Mapping OptionsTable[] = { + {XUARTPS_OPTION_SET_BREAK, XUARTPS_CR_OFFSET, XUARTPS_CR_STARTBRK}, + {XUARTPS_OPTION_STOP_BREAK, XUARTPS_CR_OFFSET, XUARTPS_CR_STOPBRK}, + {XUARTPS_OPTION_RESET_TMOUT, XUARTPS_CR_OFFSET, XUARTPS_CR_TORST}, + {XUARTPS_OPTION_RESET_TX, XUARTPS_CR_OFFSET, XUARTPS_CR_TXRST}, + {XUARTPS_OPTION_RESET_RX, XUARTPS_CR_OFFSET, XUARTPS_CR_RXRST}, + {XUARTPS_OPTION_ASSERT_RTS, XUARTPS_MODEMCR_OFFSET, + XUARTPS_MODEMCR_RTS}, + {XUARTPS_OPTION_ASSERT_DTR, XUARTPS_MODEMCR_OFFSET, + XUARTPS_MODEMCR_DTR}, + {XUARTPS_OPTION_SET_FCM, XUARTPS_MODEMCR_OFFSET, XUARTPS_MODEMCR_FCM} +}; + +/* Create a constant for the number of entries in the table */ + +#define XUARTPS_NUM_OPTIONS (sizeof(OptionsTable) / sizeof(Mapping)) + +/************************** Function Prototypes *****************************/ + +/****************************************************************************/ +/** +* +* Gets the options for the specified driver instance. The options are +* implemented as bit masks such that multiple options may be enabled or +* disabled simulataneously. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* +* @return +* +* The current options for the UART. The optionss are bit masks that are +* contained in the file xuartps.h and named XUARTPS_OPTION_*. +* +* @note None. +* +*****************************************************************************/ +u16 XUartPs_GetOptions(XUartPs *InstancePtr) +{ + u16 Options = 0U; + u32 Register; + u32 Index; + + /* Assert validates the input arguments */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Loop thru the options table to map the physical options in the + * registers of the UART to the logical options to be returned + */ + for (Index = 0U; Index < XUARTPS_NUM_OPTIONS; Index++) { + Register = XUartPs_ReadReg(InstancePtr->Config.BaseAddress, + OptionsTable[Index]. + RegisterOffset); + + /* + * If the bit in the register which correlates to the option + * is set, then set the corresponding bit in the options, + * ignoring any bits which are zero since the options variable + * is initialized to zero + */ + if ((Register & OptionsTable[Index].Mask) != (u32)0) { + Options |= OptionsTable[Index].Option; + } + } + + return Options; +} + +/****************************************************************************/ +/** +* +* Sets the options for the specified driver instance. The options are +* implemented as bit masks such that multiple options may be enabled or +* disabled simultaneously. +* +* The GetOptions function may be called to retrieve the currently enabled +* options. The result is ORed in the desired new settings to be enabled and +* ANDed with the inverse to clear the settings to be disabled. The resulting +* value is then used as the options for the SetOption function call. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* @param Options contains the options to be set which are bit masks +* contained in the file xuartps.h and named XUARTPS_OPTION_*. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XUartPs_SetOptions(XUartPs *InstancePtr, u16 Options) +{ + u32 Index; + u32 Register; + + /* Assert validates the input arguments */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Loop thru the options table to map the logical options to the + * physical options in the registers of the UART. + */ + for (Index = 0U; Index < XUARTPS_NUM_OPTIONS; Index++) { + + /* + * Read the register which contains option so that the register + * can be changed without destoying any other bits of the + * register. + */ + Register = XUartPs_ReadReg(InstancePtr->Config.BaseAddress, + OptionsTable[Index]. + RegisterOffset); + + /* + * If the option is set in the input, then set the corresponding + * bit in the specified register, otherwise clear the bit in + * the register. + */ + if ((Options & OptionsTable[Index].Option) != (u16)0) { + if(OptionsTable[Index].Option == XUARTPS_OPTION_SET_BREAK) + Register &= ~XUARTPS_CR_STOPBRK; + Register |= OptionsTable[Index].Mask; + } + else { + Register &= ~OptionsTable[Index].Mask; + } + + /* Write the new value to the register to set the option */ + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, + OptionsTable[Index].RegisterOffset, + Register); + } + +} + +/****************************************************************************/ +/** +* +* This function gets the receive FIFO trigger level. The receive trigger +* level indicates the number of bytes in the receive FIFO that cause a receive +* data event (interrupt) to be generated. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* +* @return The current receive FIFO trigger level. This is a value +* from 0-31. +* +* @note None. +* +*****************************************************************************/ +u8 XUartPs_GetFifoThreshold(XUartPs *InstancePtr) +{ + u8 RtrigRegister; + + /* Assert validates the input arguments */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the value of the FIFO control register so that the threshold + * can be retrieved, this read takes special register processing + */ + RtrigRegister = (u8) XUartPs_ReadReg(InstancePtr->Config.BaseAddress, + XUARTPS_RXWM_OFFSET); + + /* Return only the trigger level from the register value */ + + RtrigRegister &= (u8)XUARTPS_RXWM_MASK; + return RtrigRegister; +} + +/****************************************************************************/ +/** +* +* This functions sets the receive FIFO trigger level. The receive trigger +* level specifies the number of bytes in the receive FIFO that cause a receive +* data event (interrupt) to be generated. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* @param TriggerLevel contains the trigger level to set. +* +* @return None +* +* @note None. +* +*****************************************************************************/ +void XUartPs_SetFifoThreshold(XUartPs *InstancePtr, u8 TriggerLevel) +{ + u32 RtrigRegister; + + /* Assert validates the input arguments */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(TriggerLevel <= (u8)XUARTPS_RXWM_MASK); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + RtrigRegister = ((u32)TriggerLevel) & (u32)XUARTPS_RXWM_MASK; + + /* + * Write the new value for the FIFO control register to it such that the + * threshold is changed + */ + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, + XUARTPS_RXWM_OFFSET, RtrigRegister); + +} + +/****************************************************************************/ +/** +* +* This function gets the modem status from the specified UART. The modem +* status indicates any changes of the modem signals. This function allows +* the modem status to be read in a polled mode. The modem status is updated +* whenever it is read such that reading it twice may not yield the same +* results. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* +* @return +* +* The modem status which are bit masks that are contained in the file +* xuartps.h and named XUARTPS_MODEM_*. +* +* @note +* +* The bit masks used for the modem status are the exact bits of the modem +* status register with no abstraction. +* +*****************************************************************************/ +u16 XUartPs_GetModemStatus(XUartPs *InstancePtr) +{ + u32 ModemStatusRegister; + u16 TmpRegister; + /* Assert validates the input arguments */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* Read the modem status register to return + */ + ModemStatusRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress, + XUARTPS_MODEMSR_OFFSET); + TmpRegister = (u16)ModemStatusRegister; + return TmpRegister; +} + +/****************************************************************************/ +/** +* +* This function determines if the specified UART is sending data. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* +* @return +* - TRUE if the UART is sending data +* - FALSE if UART is not sending data +* +* @note None. +* +*****************************************************************************/ +u32 XUartPs_IsSending(XUartPs *InstancePtr) +{ + u32 ChanStatRegister; + u32 ChanTmpSRegister; + u32 ActiveResult; + u32 EmptyResult; + + /* Assert validates the input arguments */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the channel status register to determine if the transmitter is + * active + */ + ChanStatRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress, + XUARTPS_SR_OFFSET); + + /* + * If the transmitter is active, or the TX FIFO is not empty, then indicate + * that the UART is still sending some data + */ + ActiveResult = ChanStatRegister & ((u32)XUARTPS_SR_TACTIVE); + EmptyResult = ChanStatRegister & ((u32)XUARTPS_SR_TXEMPTY); + ChanTmpSRegister = (((u32)XUARTPS_SR_TACTIVE) == ActiveResult) || + (((u32)XUARTPS_SR_TXEMPTY) != EmptyResult); + + return ChanTmpSRegister; +} + +/****************************************************************************/ +/** +* +* This function gets the operational mode of the UART. The UART can operate +* in one of four modes: Normal, Local Loopback, Remote Loopback, or automatic +* echo. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* +* @return +* +* The operational mode is specified by constants defined in xuartps.h. The +* constants are named XUARTPS_OPER_MODE_* +* +* @note None. +* +*****************************************************************************/ +u8 XUartPs_GetOperMode(XUartPs *InstancePtr) +{ + u32 ModeRegister; + u8 OperMode; + + /* Assert validates the input arguments */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* Read the Mode register. */ + ModeRegister = + XUartPs_ReadReg(InstancePtr->Config.BaseAddress, + XUARTPS_MR_OFFSET); + + ModeRegister &= (u32)XUARTPS_MR_CHMODE_MASK; + /* Return the constant */ + switch (ModeRegister) { + case XUARTPS_MR_CHMODE_NORM: + OperMode = XUARTPS_OPER_MODE_NORMAL; + break; + case XUARTPS_MR_CHMODE_ECHO: + OperMode = XUARTPS_OPER_MODE_AUTO_ECHO; + break; + case XUARTPS_MR_CHMODE_L_LOOP: + OperMode = XUARTPS_OPER_MODE_LOCAL_LOOP; + break; + case XUARTPS_MR_CHMODE_R_LOOP: + OperMode = XUARTPS_OPER_MODE_REMOTE_LOOP; + break; + default: + OperMode = (u8) ((ModeRegister & (u32)XUARTPS_MR_CHMODE_MASK) >> + XUARTPS_MR_CHMODE_SHIFT); + break; + } + + return OperMode; +} + +/****************************************************************************/ +/** +* +* This function sets the operational mode of the UART. The UART can operate +* in one of four modes: Normal, Local Loopback, Remote Loopback, or automatic +* echo. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* @param OperationMode is the mode of the UART. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XUartPs_SetOperMode(XUartPs *InstancePtr, u8 OperationMode) +{ + u32 ModeRegister; + + /* Assert validates the input arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(OperationMode <= XUARTPS_OPER_MODE_REMOTE_LOOP); + + /* Read the Mode register. */ + ModeRegister = + XUartPs_ReadReg(InstancePtr->Config.BaseAddress, + XUARTPS_MR_OFFSET); + + /* Set the correct value by masking the bits, then ORing the const. */ + ModeRegister &= (u32)(~XUARTPS_MR_CHMODE_MASK); + + switch (OperationMode) { + case XUARTPS_OPER_MODE_NORMAL: + ModeRegister |= (u32)XUARTPS_MR_CHMODE_NORM; + break; + case XUARTPS_OPER_MODE_AUTO_ECHO: + ModeRegister |= (u32)XUARTPS_MR_CHMODE_ECHO; + break; + case XUARTPS_OPER_MODE_LOCAL_LOOP: + ModeRegister |= (u32)XUARTPS_MR_CHMODE_L_LOOP; + break; + case XUARTPS_OPER_MODE_REMOTE_LOOP: + ModeRegister |= (u32)XUARTPS_MR_CHMODE_R_LOOP; + break; + default: + /* Default case made for MISRA-C Compliance. */ + break; + } + + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_MR_OFFSET, + ModeRegister); + +} + +/****************************************************************************/ +/** +* +* This function sets the Flow Delay. +* 0 - 3: Flow delay inactive +* 4 - 32: If Flow Control mode is enabled, UART_rtsN is deactivated when the +* receive FIFO fills to this level. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* +* @return +* +* The Flow Delay is specified by constants defined in xuartps_hw.h. The +* constants are named XUARTPS_FLOWDEL* +* +* @note None. +* +*****************************************************************************/ +u8 XUartPs_GetFlowDelay(XUartPs *InstancePtr) +{ + u32 FdelTmpRegister; + + /* Assert validates the input arguments */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* Read the Mode register. */ + FdelTmpRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress, + XUARTPS_FLOWDEL_OFFSET); + + /* Return the contents of the flow delay register */ + FdelTmpRegister = (u8)(FdelTmpRegister & (u32)XUARTPS_FLOWDEL_MASK); + return FdelTmpRegister; +} + +/****************************************************************************/ +/** +* +* This function sets the Flow Delay. +* 0 - 3: Flow delay inactive +* 4 - 63: If Flow Control mode is enabled, UART_rtsN is deactivated when the +* receive FIFO fills to this level. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* @param FlowDelayValue is the Setting for the flow delay. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XUartPs_SetFlowDelay(XUartPs *InstancePtr, u8 FlowDelayValue) +{ + u32 FdelRegister; + + /* Assert validates the input arguments */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(FlowDelayValue > (u8)XUARTPS_FLOWDEL_MASK); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Set the correct value by shifting the input constant, then masking + * the bits + */ + FdelRegister = ((u32)FlowDelayValue) & (u32)XUARTPS_FLOWDEL_MASK; + + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, + XUARTPS_FLOWDEL_OFFSET, FdelRegister); + +} + +/****************************************************************************/ +/** +* +* This function gets the Receive Timeout of the UART. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* +* @return The current setting for receive time out. +* +* @note None. +* +*****************************************************************************/ +u8 XUartPs_GetRecvTimeout(XUartPs *InstancePtr) +{ + u32 RtoRegister; + u8 RtoRTmpRegister; + + /* Assert validates the input arguments */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* Read the Receive Timeout register. */ + RtoRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress, + XUARTPS_RXTOUT_OFFSET); + + /* Return the contents of the mode register shifted appropriately */ + RtoRTmpRegister = (u8)(RtoRegister & (u32)XUARTPS_RXTOUT_MASK); + return RtoRTmpRegister; +} + +/****************************************************************************/ +/** +* +* This function sets the Receive Timeout of the UART. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* @param RecvTimeout setting allows the UART to detect an idle connection +* on the reciever data line. +* Timeout duration = RecvTimeout x 4 x Bit Period. 0 disables the +* timeout function. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XUartPs_SetRecvTimeout(XUartPs *InstancePtr, u8 RecvTimeout) +{ + u32 RtoRegister; + + /* Assert validates the input arguments */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* Set the correct value by masking the bits */ + RtoRegister = ((u32)RecvTimeout & (u32)XUARTPS_RXTOUT_MASK); + + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, + XUARTPS_RXTOUT_OFFSET, RtoRegister); + + /* Configure CR to restart the receiver timeout counter */ + RtoRegister = + XUartPs_ReadReg(InstancePtr->Config.BaseAddress, + XUARTPS_CR_OFFSET); + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_CR_OFFSET, + (RtoRegister | XUARTPS_CR_TORST)); + +} +/****************************************************************************/ +/** +* +* Sets the data format for the device. The data format includes the +* baud rate, number of data bits, number of stop bits, and parity. It is the +* caller's responsibility to ensure that the UART is not sending or receiving +* data when this function is called. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* @param FormatPtr is a pointer to a format structure containing the data +* format to be set. +* +* @return +* - XST_SUCCESS if the data format was successfully set. +* - XST_UART_BAUD_ERROR indicates the baud rate could not be +* set because of the amount of error with the baud rate and +* the input clock frequency. +* - XST_INVALID_PARAM if one of the parameters was not valid. +* +* @note +* +* The data types in the format type, data bits and parity, are 32 bit fields +* to prevent a compiler warning. +* The asserts in this function will cause a warning if these fields are +* bytes. +*

+* +*****************************************************************************/ +s32 XUartPs_SetDataFormat(XUartPs *InstancePtr, + XUartPsFormat * FormatPtr) +{ + s32 Status; + u32 ModeRegister; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(FormatPtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* Verify the inputs specified are valid */ + if ((FormatPtr->DataBits > ((u32)XUARTPS_FORMAT_6_BITS)) || + (FormatPtr->StopBits > ((u8)XUARTPS_FORMAT_2_STOP_BIT)) || + (FormatPtr->Parity > ((u32)XUARTPS_FORMAT_NO_PARITY))) { + Status = XST_INVALID_PARAM; + } else { + + /* + * Try to set the baud rate and if it's not successful then don't + * continue altering the data format, this is done first to avoid the + * format from being altered when an error occurs + */ + Status = XUartPs_SetBaudRate(InstancePtr, FormatPtr->BaudRate); + if (Status != (s32)XST_SUCCESS) { + ; + } else { + + ModeRegister = + XUartPs_ReadReg(InstancePtr->Config.BaseAddress, + XUARTPS_MR_OFFSET); + + /* + * Set the length of data (8,7,6) by first clearing out the bits + * that control it in the register, then set the length in the register + */ + ModeRegister &= (u32)(~XUARTPS_MR_CHARLEN_MASK); + ModeRegister |= (FormatPtr->DataBits << XUARTPS_MR_CHARLEN_SHIFT); + + /* + * Set the number of stop bits in the mode register by first clearing + * out the bits that control it in the register, then set the number + * of stop bits in the register. + */ + ModeRegister &= (u32)(~XUARTPS_MR_STOPMODE_MASK); + ModeRegister |= (((u32)FormatPtr->StopBits) << XUARTPS_MR_STOPMODE_SHIFT); + + /* + * Set the parity by first clearing out the bits that control it in the + * register, then set the bits in the register, the default is no parity + * after clearing the register bits + */ + ModeRegister &= (u32)(~XUARTPS_MR_PARITY_MASK); + ModeRegister |= (FormatPtr->Parity << XUARTPS_MR_PARITY_SHIFT); + + /* Update the mode register */ + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_MR_OFFSET, + ModeRegister); + + Status = XST_SUCCESS; + } + } + return Status; +} + +/****************************************************************************/ +/** +* +* Gets the data format for the specified UART. The data format includes the +* baud rate, number of data bits, number of stop bits, and parity. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* @param FormatPtr is a pointer to a format structure that will contain +* the data format after this call completes. +* +* @return None. +* +* @note None. +* +* +*****************************************************************************/ +void XUartPs_GetDataFormat(XUartPs *InstancePtr, XUartPsFormat * FormatPtr) +{ + u32 ModeRegister; + + + /* Assert validates the input arguments */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(FormatPtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Get the baud rate from the instance, this is not retrieved from the + * hardware because it is only kept as a divisor such that it is more + * difficult to get back to the baud rate + */ + FormatPtr->BaudRate = InstancePtr->BaudRate; + + ModeRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress, + XUARTPS_MR_OFFSET); + + /* Get the length of data (8,7,6,5) */ + FormatPtr->DataBits = + ((ModeRegister & (u32)XUARTPS_MR_CHARLEN_MASK) >> + XUARTPS_MR_CHARLEN_SHIFT); + + /* Get the number of stop bits */ + FormatPtr->StopBits = + (u8)((ModeRegister & (u32)XUARTPS_MR_STOPMODE_MASK) >> + XUARTPS_MR_STOPMODE_SHIFT); + + /* Determine what parity is */ + FormatPtr->Parity = + (u32)((ModeRegister & (u32)XUARTPS_MR_PARITY_MASK) >> + XUARTPS_MR_PARITY_SHIFT); +} +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/uartps_v3_7/src/xuartps_selftest.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/uartps_v3_7/src/xuartps_selftest.c new file mode 100644 index 0000000..f26176a --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/uartps_v3_7/src/xuartps_selftest.c @@ -0,0 +1,162 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xuartps_selftest.c +* @addtogroup uartps_v3_5 +* @{ +* +* This file contains the self-test functions for the XUartPs driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date	Changes
+* ----- ------ -------- -----------------------------------------------
+* 1.00	drg/jz 01/13/10 First Release
+* 3.00  kvn    02/13/15 Modified code for MISRA-C:2012 compliance.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xstatus.h" +#include "xuartps.h" + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + +#define XUARTPS_TOTAL_BYTES (u8)32 + +/************************** Variable Definitions *****************************/ + +static u8 TestString[XUARTPS_TOTAL_BYTES]="abcdefghABCDEFGH012345677654321"; +static u8 ReturnString[XUARTPS_TOTAL_BYTES]; + +/************************** Function Prototypes ******************************/ + + +/****************************************************************************/ +/** +* +* This function runs a self-test on the driver and hardware device. This self +* test performs a local loopback and verifies data can be sent and received. +* +* The time for this test is proportional to the baud rate that has been set +* prior to calling this function. +* +* The mode and control registers are restored before return. +* +* @param InstancePtr is a pointer to the XUartPs instance +* +* @return +* - XST_SUCCESS if the test was successful +* - XST_UART_TEST_FAIL if the test failed looping back the data +* +* @note +* +* This function can hang if the hardware is not functioning properly. +* +******************************************************************************/ +s32 XUartPs_SelfTest(XUartPs *InstancePtr) +{ + s32 Status = XST_SUCCESS; + u32 IntrRegister; + u32 ModeRegister; + u8 Index; + u32 ReceiveDataResult; + + /* Assert validates the input arguments */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* Disable all interrupts in the interrupt disable register */ + IntrRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress, + XUARTPS_IMR_OFFSET); + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_IDR_OFFSET, + XUARTPS_IXR_MASK); + + /* Setup for local loopback */ + ModeRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress, + XUARTPS_MR_OFFSET); + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_MR_OFFSET, + ((ModeRegister & (u32)(~XUARTPS_MR_CHMODE_MASK)) | + (u32)XUARTPS_MR_CHMODE_L_LOOP)); + + /* Send a number of bytes and receive them, one at a time. */ + for (Index = 0U; Index < XUARTPS_TOTAL_BYTES; Index++) { + /* + * Send out the byte and if it was not sent then the failure + * will be caught in the comparison at the end + */ + (void)XUartPs_Send(InstancePtr, &TestString[Index], 1U); + + /* + * Wait until the byte is received. This can hang if the HW + * is broken. Watch for the FIFO empty flag to be false. + */ + ReceiveDataResult = Xil_In32((InstancePtr->Config.BaseAddress) + XUARTPS_SR_OFFSET) & + XUARTPS_SR_RXEMPTY; + while (ReceiveDataResult == XUARTPS_SR_RXEMPTY ) { + ReceiveDataResult = Xil_In32((InstancePtr->Config.BaseAddress) + XUARTPS_SR_OFFSET) & + XUARTPS_SR_RXEMPTY; + } + + /* Receive the byte */ + (void)XUartPs_Recv(InstancePtr, &ReturnString[Index], 1U); + } + + /* + * Compare the bytes received to the bytes sent to verify the exact data + * was received + */ + for (Index = 0U; Index < XUARTPS_TOTAL_BYTES; Index++) { + if (TestString[Index] != ReturnString[Index]) { + Status = XST_UART_TEST_FAIL; + } + } + + /* + * Restore the registers which were altered to put into polling and + * loopback modes so that this test is not destructive + */ + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_IER_OFFSET, + IntrRegister); + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_MR_OFFSET, + ModeRegister); + + return Status; +} +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/uartps_v3_7/src/xuartps_sinit.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/uartps_v3_7/src/xuartps_sinit.c new file mode 100644 index 0000000..c3e809b --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/uartps_v3_7/src/xuartps_sinit.c @@ -0,0 +1,95 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xuartps_sinit.c +* @addtogroup uartps_v3_5 +* @{ +* +* The implementation of the XUartPs driver's static initialzation +* functionality. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date	Changes
+* ----- ------ -------- -----------------------------------------------
+* 1.00  drg/jz 01/13/10 First Release
+* 3.00  kvn    02/13/15 Modified code for MISRA-C:2012 compliance.
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ + +#include "xstatus.h" +#include "xparameters.h" +#include "xuartps.h" + +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Variable Definitions ****************************/ +extern XUartPs_Config XUartPs_ConfigTable[XPAR_XUARTPS_NUM_INSTANCES]; + +/************************** Function Prototypes *****************************/ + +/****************************************************************************/ +/** +* +* Looks up the device configuration based on the unique device ID. The table +* contains the configuration info for each device in the system. +* +* @param DeviceId contains the ID of the device +* +* @return A pointer to the configuration structure or NULL if the +* specified device is not in the system. +* +* @note None. +* +******************************************************************************/ +XUartPs_Config *XUartPs_LookupConfig(u16 DeviceId) +{ + XUartPs_Config *CfgPtr = NULL; + + u32 Index; + + for (Index = 0U; Index < (u32)XPAR_XUARTPS_NUM_INSTANCES; Index++) { + if (XUartPs_ConfigTable[Index].DeviceId == DeviceId) { + CfgPtr = &XUartPs_ConfigTable[Index]; + break; + } + } + + return (XUartPs_Config *)CfgPtr; +} +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/xadcps_v2_3/src/Makefile b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/xadcps_v2_3/src/Makefile new file mode 100644 index 0000000..837ca13 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/xadcps_v2_3/src/Makefile @@ -0,0 +1,40 @@ +COMPILER= +ARCHIVER= +CP=cp +COMPILER_FLAGS= +EXTRA_COMPILER_FLAGS= +LIB=libxil.a + +CC_FLAGS = $(COMPILER_FLAGS) +ECC_FLAGS = $(EXTRA_COMPILER_FLAGS) + +RELEASEDIR=../../../lib +INCLUDEDIR=../../../include +INCLUDES=-I./. -I${INCLUDEDIR} + +OUTS = *.o + +LIBSOURCES:=*.c +INCLUDEFILES:=*.h + +OBJECTS = $(addsuffix .o, $(basename $(wildcard *.c))) + +libs: banner xadcps_libs clean + +%.o: %.c + ${COMPILER} $(CC_FLAGS) $(ECC_FLAGS) $(INCLUDES) -o $@ $< + +banner: + echo "Compiling xadcps" + +xadcps_libs: ${OBJECTS} + $(ARCHIVER) -r ${RELEASEDIR}/${LIB} ${OBJECTS} + +.PHONY: include +include: xadcps_includes + +xadcps_includes: + ${CP} ${INCLUDEFILES} ${INCLUDEDIR} + +clean: + rm -rf ${OBJECTS} diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/xadcps_v2_3/src/xadcps.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/xadcps_v2_3/src/xadcps.c new file mode 100644 index 0000000..5ec5a93 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/xadcps_v2_3/src/xadcps.c @@ -0,0 +1,1830 @@ +/****************************************************************************** +* +* Copyright (C) 2011 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xadcps.c +* @addtogroup xadcps_v2_3 +* @{ +* +* This file contains the driver API functions that can be used to access +* the XADC device. +* +* Refer to the xadcps.h header file for more information about this driver. +* +* @note None. +* +*
+*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- -----  -------- -----------------------------------------------------
+* 1.00a ssb    12/22/11 First release based on the XPS/AXI xadc driver
+* 1.01a bss    02/18/13	Modified XAdcPs_SetSeqChEnables,XAdcPs_SetSeqAvgEnables
+*			XAdcPs_SetSeqInputMode and XAdcPs_SetSeqAcqTime APIs
+*			to fix CR #693371
+* 2.1   bss    08/05/14	Modified Assert for XAdcPs_SetSingleChParams to fix
+*			CR #807563.
+* 2.2	bss	   04/27/14 Modified to use correct Device Config base address
+*						(CR#854437).
+* 2.3   mn     07/09/18 Fix Doxygen warning
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ + +#include "xadcps.h" + +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Function Prototypes *****************************/ + +void XAdcPs_WriteInternalReg(XAdcPs *InstancePtr, u32 RegOffset, u32 Data); +u32 XAdcPs_ReadInternalReg(XAdcPs *InstancePtr, u32 RegOffset); + + +/************************** Variable Definitions ****************************/ + + +/*****************************************************************************/ +/** +* +* This function initializes a specific XAdcPs device/instance. This function +* must be called prior to using the XADC device. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param ConfigPtr points to the XAdcPs device configuration structure. +* @param EffectiveAddr is the device base address in the virtual memory +* address space. If the address translation is not used then the +* physical address is passed. +* Unexpected errors may occur if the address mapping is changed +* after this function is invoked. +* +* @return +* - XST_SUCCESS if successful. +* +* @note The user needs to first call the XAdcPs_LookupConfig() API +* which returns the Configuration structure pointer which is +* passed as a parameter to the XAdcPs_CfgInitialize() API. +* +******************************************************************************/ +int XAdcPs_CfgInitialize(XAdcPs *InstancePtr, XAdcPs_Config *ConfigPtr, + u32 EffectiveAddr) +{ + + u32 RegValue; + /* + * Assert the input arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(ConfigPtr != NULL); + + + /* + * Set the values read from the device config and the base address. + */ + InstancePtr->Config.DeviceId = ConfigPtr->DeviceId; + InstancePtr->Config.BaseAddress = EffectiveAddr; + + /* Write Unlock value to Device Config Unlock register */ + XAdcPs_WriteReg(XPAR_XDCFG_0_BASEADDR, + XADCPS_UNLK_OFFSET, XADCPS_UNLK_VALUE); + + /* Enable the PS access of xadc and set FIFO thresholds */ + + RegValue = XAdcPs_ReadReg((InstancePtr)->Config.BaseAddress, + XADCPS_CFG_OFFSET); + + RegValue = RegValue | XADCPS_CFG_ENABLE_MASK | + XADCPS_CFG_CFIFOTH_MASK | XADCPS_CFG_DFIFOTH_MASK; + + XAdcPs_WriteReg((InstancePtr)->Config.BaseAddress, + XADCPS_CFG_OFFSET, RegValue); + + /* Release xadc from reset */ + + XAdcPs_WriteReg((InstancePtr)->Config.BaseAddress, + XADCPS_MCTL_OFFSET, 0x00); + + /* + * Indicate the instance is now ready to use and + * initialized without error. + */ + InstancePtr->IsReady = XIL_COMPONENT_IS_READY; + + return XST_SUCCESS; +} + + +/****************************************************************************/ +/** +* +* The functions sets the contents of the Config Register. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param Data is the 32 bit data to be written to the Register. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XAdcPs_SetConfigRegister(XAdcPs *InstancePtr, u32 Data) +{ + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + XAdcPs_WriteReg((InstancePtr)->Config.BaseAddress, + XADCPS_CFG_OFFSET, Data); + +} + + +/****************************************************************************/ +/** +* +* The functions reads the contents of the Config Register. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @return A 32-bit value representing the contents of the Config Register. +* Use the XADCPS_SR_*_MASK constants defined in xadcps_hw.h to +* interpret the returned value. +* +* @note None. +* +*****************************************************************************/ +u32 XAdcPs_GetConfigRegister(XAdcPs *InstancePtr) +{ + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the Config Register and return the value. + */ + return XAdcPs_ReadReg((InstancePtr)->Config.BaseAddress, + XADCPS_CFG_OFFSET); +} + + +/****************************************************************************/ +/** +* +* The functions reads the contents of the Miscellaneous Status Register. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @return A 32-bit value representing the contents of the Miscellaneous +* Status Register. Use the XADCPS_MSTS_*_MASK constants defined +* in xadcps_hw.h to interpret the returned value. +* +* @note None. +* +*****************************************************************************/ +u32 XAdcPs_GetMiscStatus(XAdcPs *InstancePtr) +{ + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the Miscellaneous Status Register and return the value. + */ + return XAdcPs_ReadReg((InstancePtr)->Config.BaseAddress, + XADCPS_MSTS_OFFSET); +} + + +/****************************************************************************/ +/** +* +* The functions sets the contents of the Miscellaneous Control register. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param Data is the 32 bit data to be written to the Register. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XAdcPs_SetMiscCtrlRegister(XAdcPs *InstancePtr, u32 Data) +{ + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Write to the Miscellaneous control register Register. + */ + XAdcPs_WriteReg((InstancePtr)->Config.BaseAddress, + XADCPS_MCTL_OFFSET, Data); +} + + +/****************************************************************************/ +/** +* +* The functions reads the contents of the Miscellaneous control register. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @return A 32-bit value representing the contents of the Config Register. +* Use the XADCPS_SR_*_MASK constants defined in xadcps_hw.h to +* interpret the returned value. +* +* @note None. +* +*****************************************************************************/ +u32 XAdcPs_GetMiscCtrlRegister(XAdcPs *InstancePtr) +{ + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the Miscellaneous control register and return the value. + */ + return XAdcPs_ReadReg((InstancePtr)->Config.BaseAddress, + XADCPS_MCTL_OFFSET); +} + + +/*****************************************************************************/ +/** +* +* This function resets the XADC Hard Macro in the device. +* +* @param InstancePtr is a pointer to the Xxadc instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XAdcPs_Reset(XAdcPs *InstancePtr) +{ + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Generate the reset by Control + * register and release from reset + */ + XAdcPs_WriteReg((InstancePtr)->Config.BaseAddress, + XADCPS_MCTL_OFFSET, 0x10); + XAdcPs_WriteReg((InstancePtr)->Config.BaseAddress, + XADCPS_MCTL_OFFSET, 0x00); +} + + +/****************************************************************************/ +/** +* +* Get the ADC converted data for the specified channel. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param Channel is the channel number. Use the XADCPS_CH_* defined in +* the file xadcps.h. +* The valid channels are +* - 0 to 6 +* - 13 to 31 +* +* @return A 16-bit value representing the ADC converted data for the +* specified channel. The XADC Monitor/ADC device guarantees +* a 10 bit resolution for the ADC converted data and data is the +* 10 MSB bits of the 16 data read from the device. +* +* @note The channels 7,8,9 are used for calibration of the device and +* hence there is no associated data with this channel. +* +*****************************************************************************/ +u16 XAdcPs_GetAdcData(XAdcPs *InstancePtr, u8 Channel) +{ + + u32 RegData; + + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid((Channel <= XADCPS_CH_VBRAM) || + ((Channel >= XADCPS_CH_VCCPINT) && + (Channel <= XADCPS_CH_AUX_MAX))); + + RegData = XAdcPs_ReadInternalReg(InstancePtr, + (XADCPS_TEMP_OFFSET + + Channel)); + return (u16) RegData; +} + +/****************************************************************************/ +/** +* +* This function gets the calibration coefficient data for the specified +* parameter. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param CoeffType specifies the calibration coefficient +* to be read. Use XADCPS_CALIB_* constants defined in xadcps.h to +* specify the calibration coefficient to be read. +* +* @return A 16-bit value representing the calibration coefficient. +* The XADC device guarantees a 10 bit resolution for +* the ADC converted data and data is the 10 MSB bits of the 16 +* data read from the device. +* +* @note None. +* +*****************************************************************************/ +u16 XAdcPs_GetCalibCoefficient(XAdcPs *InstancePtr, u8 CoeffType) +{ + u32 RegData; + + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(CoeffType <= XADCPS_CALIB_GAIN_ERROR_COEFF); + + /* + * Read the selected calibration coefficient. + */ + RegData = XAdcPs_ReadInternalReg(InstancePtr, + (XADCPS_ADC_A_SUPPLY_CALIB_OFFSET + + CoeffType)); + return (u16) RegData; +} + +/****************************************************************************/ +/** +* +* This function reads the Minimum/Maximum measurement for one of the +* specified parameters. Use XADCPS_MAX_* and XADCPS_MIN_* constants defined in +* xadcps.h to specify the parameters (Temperature, VccInt, VccAux, VBram, +* VccPInt, VccPAux and VccPDro). +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param MeasurementType specifies the parameter for which the +* Minimum/Maximum measurement has to be read. +* Use XADCPS_MAX_* and XADCPS_MIN_* constants defined in xadcps.h to +* specify the data to be read. +* +* @return A 16-bit value representing the maximum/minimum measurement for +* specified parameter. +* The XADC device guarantees a 10 bit resolution for +* the ADC converted data and data is the 10 MSB bits of the 16 +* data read from the device. +* +* @note None. +* +*****************************************************************************/ +u16 XAdcPs_GetMinMaxMeasurement(XAdcPs *InstancePtr, u8 MeasurementType) +{ + u32 RegData; + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid((MeasurementType <= XADCPS_MAX_VCCPDRO) || + ((MeasurementType >= XADCPS_MIN_VCCPINT) && + (MeasurementType <= XADCPS_MIN_VCCPDRO))) + + /* + * Read and return the specified Minimum/Maximum measurement. + */ + RegData = XAdcPs_ReadInternalReg(InstancePtr, + (XADCPS_MAX_TEMP_OFFSET + + MeasurementType)); + return (u16) RegData; +} + +/****************************************************************************/ +/** +* +* This function sets the number of samples of averaging that is to be done for +* all the channels in both the single channel mode and sequence mode of +* operations. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param Average is the number of samples of averaging programmed to the +* Configuration Register 0. Use the XADCPS_AVG_* definitions defined +* in xadcps.h file : +* - XADCPS_AVG_0_SAMPLES for no averaging +* - XADCPS_AVG_16_SAMPLES for 16 samples of averaging +* - XADCPS_AVG_64_SAMPLES for 64 samples of averaging +* - XADCPS_AVG_256_SAMPLES for 256 samples of averaging +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XAdcPs_SetAvg(XAdcPs *InstancePtr, u8 Average) +{ + u32 RegData; + + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Average <= XADCPS_AVG_256_SAMPLES); + + /* + * Write the averaging value into the Configuration Register 0. + */ + RegData = XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_CFR0_OFFSET) & + (~XADCPS_CFR0_AVG_VALID_MASK); + + RegData |= (((u32) Average << XADCPS_CFR0_AVG_SHIFT)); + XAdcPs_WriteInternalReg(InstancePtr, XADCPS_CFR0_OFFSET, + RegData); + +} + +/****************************************************************************/ +/** +* +* This function returns the number of samples of averaging configured for all +* the channels in the Configuration Register 0. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @return The averaging read from the Configuration Register 0 is +* returned. Use the XADCPS_AVG_* bit definitions defined in +* xadcps.h file to interpret the returned value : +* - XADCPS_AVG_0_SAMPLES means no averaging +* - XADCPS_AVG_16_SAMPLES means 16 samples of averaging +* - XADCPS_AVG_64_SAMPLES means 64 samples of averaging +* - XADCPS_AVG_256_SAMPLES means 256 samples of averaging +* +* @note None. +* +*****************************************************************************/ +u8 XAdcPs_GetAvg(XAdcPs *InstancePtr) +{ + u32 Average; + + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the averaging value from the Configuration Register 0. + */ + Average = XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_CFR0_OFFSET) & XADCPS_CFR0_AVG_VALID_MASK; + + + return ((u8) (Average >> XADCPS_CFR0_AVG_SHIFT)); +} + +/****************************************************************************/ +/** +* +* The function sets the given parameters in the Configuration Register 0 in +* the single channel mode. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param Channel is the channel number for the singel channel mode. +* The valid channels are 0 to 6, 8, and 13 to 31. +* If the external Mux is used then this specifies the channel +* oonnected to the external Mux. Please read the Device Spec +* to know which channels are valid. +* @param IncreaseAcqCycles is a boolean parameter which specifies whether +* the Acquisition time for the external channels has to be +* increased to 10 ADCCLK cycles (specify TRUE) or remain at the +* default 4 ADCCLK cycles (specify FALSE). This parameter is +* only valid for the external channels. +* @param IsEventMode specifies whether the operation of the ADC is Event +* driven or Continuous mode. +* @param IsDifferentialMode is a boolean parameter which specifies +* unipolar(specify FALSE) or differential mode (specify TRUE) for +* the analog inputs. The input mode is only valid for the +* external channels. +* +* @return +* - XST_SUCCESS if the given values were written successfully to +* the Configuration Register 0. +* - XST_FAILURE if the channel sequencer is enabled or the input +* parameters are not valid for the selected channel. +* +* @note +* - The number of samples for the averaging for all the channels +* is set by using the function XAdcPs_SetAvg. +* - The calibration of the device is done by doing a ADC +* conversion on the calibration channel(channel 8). The input +* parameters IncreaseAcqCycles, IsDifferentialMode and +* IsEventMode are not valid for this channel +* +* +*****************************************************************************/ +int XAdcPs_SetSingleChParams(XAdcPs *InstancePtr, + u8 Channel, + int IncreaseAcqCycles, + int IsEventMode, + int IsDifferentialMode) +{ + u32 RegValue; + + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid((Channel <= XADCPS_CH_VBRAM) || + (Channel == XADCPS_CH_ADC_CALIB) || + ((Channel >= XADCPS_CH_VCCPINT) && + (Channel <= XADCPS_CH_AUX_MAX))); + Xil_AssertNonvoid((IncreaseAcqCycles == TRUE) || + (IncreaseAcqCycles == FALSE)); + Xil_AssertNonvoid((IsEventMode == TRUE) || (IsEventMode == FALSE)); + Xil_AssertNonvoid((IsDifferentialMode == TRUE) || + (IsDifferentialMode == FALSE)); + + /* + * Check if the device is in single channel mode else return failure + */ + if ((XAdcPs_GetSequencerMode(InstancePtr) != + XADCPS_SEQ_MODE_SINGCHAN)) { + return XST_FAILURE; + } + + /* + * Read the Configuration Register 0. + */ + RegValue = XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_CFR0_OFFSET) & + XADCPS_CFR0_AVG_VALID_MASK; + + /* + * Select the number of acquisition cycles. The acquisition cycles is + * only valid for the external channels. + */ + if (IncreaseAcqCycles == TRUE) { + if (((Channel >= XADCPS_CH_AUX_MIN) && + (Channel <= XADCPS_CH_AUX_MAX)) || + (Channel == XADCPS_CH_VPVN)){ + RegValue |= XADCPS_CFR0_ACQ_MASK; + } else { + return XST_FAILURE; + } + + } + + /* + * Select the input mode. The input mode is only valid for the + * external channels. + */ + if (IsDifferentialMode == TRUE) { + + if (((Channel >= XADCPS_CH_AUX_MIN) && + (Channel <= XADCPS_CH_AUX_MAX)) || + (Channel == XADCPS_CH_VPVN)){ + RegValue |= XADCPS_CFR0_DU_MASK; + } else { + return XST_FAILURE; + } + } + + /* + * Select the ADC mode. + */ + if (IsEventMode == TRUE) { + RegValue |= XADCPS_CFR0_EC_MASK; + } + + /* + * Write the given values into the Configuration Register 0. + */ + RegValue |= (Channel & XADCPS_CFR0_CHANNEL_MASK); + XAdcPs_WriteInternalReg(InstancePtr, XADCPS_CFR0_OFFSET, + RegValue); + + return XST_SUCCESS; +} + +/****************************************************************************/ +/** +* +* This function enables the alarm outputs for the specified alarms in the +* Configuration Register 1. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param AlmEnableMask is the bit-mask of the alarm outputs to be enabled +* in the Configuration Register 1. +* Bit positions of 1 will be enabled. Bit positions of 0 will be +* disabled. This mask is formed by OR'ing XADCPS_CFR1_ALM_*_MASK and +* XADCPS_CFR1_OT_MASK masks defined in xadcps_hw.h. +* +* @return None. +* +* @note The implementation of the alarm enables in the Configuration +* register 1 is such that the alarms for bit positions of 1 will +* be disabled and alarms for bit positions of 0 will be enabled. +* The alarm outputs specified by the AlmEnableMask are negated +* before writing to the Configuration Register 1. +* +* +*****************************************************************************/ +void XAdcPs_SetAlarmEnables(XAdcPs *InstancePtr, u16 AlmEnableMask) +{ + u32 RegValue; + + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + + RegValue = XAdcPs_ReadInternalReg(InstancePtr, XADCPS_CFR1_OFFSET); + + RegValue &= (u32)~XADCPS_CFR1_ALM_ALL_MASK; + RegValue |= (~AlmEnableMask & XADCPS_CFR1_ALM_ALL_MASK); + + /* + * Enable/disables the alarm enables for the specified alarm bits in the + * Configuration Register 1. + */ + XAdcPs_WriteInternalReg(InstancePtr, XADCPS_CFR1_OFFSET, + RegValue); +} + +/****************************************************************************/ +/** +* +* This function gets the status of the alarm output enables in the +* Configuration Register 1. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @return This is the bit-mask of the enabled alarm outputs in the +* Configuration Register 1. Use the masks XADCPS_CFR1_ALM*_* and +* XADCPS_CFR1_OT_MASK defined in xadcps_hw.h to interpret the +* returned value. +* Bit positions of 1 indicate that the alarm output is enabled. +* Bit positions of 0 indicate that the alarm output is disabled. +* +* +* @note The implementation of the alarm enables in the Configuration +* register 1 is such that alarms for the bit positions of 1 will +* be disabled and alarms for bit positions of 0 will be enabled. +* The enabled alarm outputs returned by this function is the +* negated value of the the data read from the Configuration +* Register 1. +* +*****************************************************************************/ +u16 XAdcPs_GetAlarmEnables(XAdcPs *InstancePtr) +{ + u32 RegValue; + + /* + * Assert the arguments + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the status of alarm output enables from the Configuration + * Register 1. + */ + RegValue = XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_CFR1_OFFSET) & XADCPS_CFR1_ALM_ALL_MASK; + return (u16) (~RegValue & XADCPS_CFR1_ALM_ALL_MASK); +} + +/****************************************************************************/ +/** +* +* This function enables the specified calibration in the Configuration +* Register 1 : +* +* - XADCPS_CFR1_CAL_ADC_OFFSET_MASK : Calibration 0 -ADC offset correction +* - XADCPS_CFR1_CAL_ADC_GAIN_OFFSET_MASK : Calibration 1 -ADC gain and offset +* correction +* - XADCPS_CFR1_CAL_PS_OFFSET_MASK : Calibration 2 -Power Supply sensor +* offset correction +* - XADCPS_CFR1_CAL_PS_GAIN_OFFSET_MASK : Calibration 3 -Power Supply sensor +* gain and offset correction +* - XADCPS_CFR1_CAL_DISABLE_MASK : No Calibration +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param Calibration is the Calibration to be applied. +* Use XADCPS_CFR1_CAL*_* bits defined in xadcps_hw.h. +* Multiple calibrations can be enabled at a time by oring the +* XADCPS_CFR1_CAL_ADC_* and XADCPS_CFR1_CAL_PS_* bits. +* Calibration can be disabled by specifying + XADCPS_CFR1_CAL_DISABLE_MASK; +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XAdcPs_SetCalibEnables(XAdcPs *InstancePtr, u16 Calibration) +{ + u32 RegValue; + + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(((Calibration >= XADCPS_CFR1_CAL_ADC_OFFSET_MASK) && + (Calibration <= XADCPS_CFR1_CAL_VALID_MASK)) || + (Calibration == XADCPS_CFR1_CAL_DISABLE_MASK)); + + /* + * Set the specified calibration in the Configuration Register 1. + */ + RegValue = XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_CFR1_OFFSET); + + RegValue &= (~ XADCPS_CFR1_CAL_VALID_MASK); + RegValue |= (Calibration & XADCPS_CFR1_CAL_VALID_MASK); + XAdcPs_WriteInternalReg(InstancePtr, XADCPS_CFR1_OFFSET, + RegValue); + +} + +/****************************************************************************/ +/** +* +* This function reads the value of the calibration enables from the +* Configuration Register 1. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @return The value of the calibration enables in the Configuration +* Register 1 : +* - XADCPS_CFR1_CAL_ADC_OFFSET_MASK : ADC offset correction +* - XADCPS_CFR1_CAL_ADC_GAIN_OFFSET_MASK : ADC gain and offset +* correction +* - XADCPS_CFR1_CAL_PS_OFFSET_MASK : Power Supply sensor offset +* correction +* - XADCPS_CFR1_CAL_PS_GAIN_OFFSET_MASK : Power Supply sensor +* gain and offset correction +* - XADCPS_CFR1_CAL_DISABLE_MASK : No Calibration +* +* @note None. +* +*****************************************************************************/ +u16 XAdcPs_GetCalibEnables(XAdcPs *InstancePtr) +{ + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the calibration enables from the Configuration Register 1. + */ + return (u16) XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_CFR1_OFFSET) & XADCPS_CFR1_CAL_VALID_MASK; + +} + +/****************************************************************************/ +/** +* +* This function sets the specified Channel Sequencer Mode in the Configuration +* Register 1 : +* - Default safe mode (XADCPS_SEQ_MODE_SAFE) +* - One pass through sequence (XADCPS_SEQ_MODE_ONEPASS) +* - Continuous channel sequencing (XADCPS_SEQ_MODE_CONTINPASS) +* - Single Channel/Sequencer off (XADCPS_SEQ_MODE_SINGCHAN) +* - Simulataneous sampling mode (XADCPS_SEQ_MODE_SIMUL_SAMPLING) +* - Independent mode (XADCPS_SEQ_MODE_INDEPENDENT) +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param SequencerMode is the sequencer mode to be set. +* Use XADCPS_SEQ_MODE_* bits defined in xadcps.h. +* @return None. +* +* @note Only one of the modes can be enabled at a time. Please +* read the Spec of the XADC for further information about the +* sequencer modes. +* +* +*****************************************************************************/ +void XAdcPs_SetSequencerMode(XAdcPs *InstancePtr, u8 SequencerMode) +{ + u32 RegValue; + + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid((SequencerMode <= XADCPS_SEQ_MODE_SIMUL_SAMPLING) || + (SequencerMode == XADCPS_SEQ_MODE_INDEPENDENT)); + + /* + * Set the specified sequencer mode in the Configuration Register 1. + */ + RegValue = XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_CFR1_OFFSET); + RegValue &= (~ XADCPS_CFR1_SEQ_VALID_MASK); + RegValue |= ((SequencerMode << XADCPS_CFR1_SEQ_SHIFT) & + XADCPS_CFR1_SEQ_VALID_MASK); + XAdcPs_WriteInternalReg(InstancePtr, XADCPS_CFR1_OFFSET, + RegValue); + +} + +/****************************************************************************/ +/** +* +* This function gets the channel sequencer mode from the Configuration +* Register 1. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @return The channel sequencer mode : +* - XADCPS_SEQ_MODE_SAFE : Default safe mode +* - XADCPS_SEQ_MODE_ONEPASS : One pass through sequence +* - XADCPS_SEQ_MODE_CONTINPASS : Continuous channel sequencing +* - XADCPS_SEQ_MODE_SINGCHAN : Single channel/Sequencer off +* - XADCPS_SEQ_MODE_SIMUL_SAMPLING : Simulataneous sampling mode +* - XADCPS_SEQ_MODE_INDEPENDENT : Independent mode +* +* +* @note None. +* +*****************************************************************************/ +u8 XAdcPs_GetSequencerMode(XAdcPs *InstancePtr) +{ + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the channel sequencer mode from the Configuration Register 1. + */ + return ((u8) ((XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_CFR1_OFFSET) & XADCPS_CFR1_SEQ_VALID_MASK) >> + XADCPS_CFR1_SEQ_SHIFT)); + +} + +/****************************************************************************/ +/** +* +* The function sets the frequency of the ADCCLK by configuring the DCLK to +* ADCCLK ratio in the Configuration Register #2 +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param Divisor is clock divisor used to derive ADCCLK from DCLK. +* Valid values of the divisor are +* - 0 to 255. Values 0, 1, 2 are all mapped to 2. +* Refer to the device specification for more details +* +* @return None. +* +* @note - The ADCCLK is an internal clock used by the ADC and is +* synchronized to the DCLK clock. The ADCCLK is equal to DCLK +* divided by the user selection in the Configuration Register 2. +* - There is no Assert on the minimum value of the Divisor. +* +*****************************************************************************/ +void XAdcPs_SetAdcClkDivisor(XAdcPs *InstancePtr, u8 Divisor) +{ + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Write the divisor value into the Configuration Register #2. + */ + XAdcPs_WriteInternalReg(InstancePtr, XADCPS_CFR2_OFFSET, + Divisor << XADCPS_CFR2_CD_SHIFT); + +} + +/****************************************************************************/ +/** +* +* The function gets the ADCCLK divisor from the Configuration Register 2. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @return The divisor read from the Configuration Register 2. +* +* @note The ADCCLK is an internal clock used by the ADC and is +* synchronized to the DCLK clock. The ADCCLK is equal to DCLK +* divided by the user selection in the Configuration Register 2. +* +*****************************************************************************/ +u8 XAdcPs_GetAdcClkDivisor(XAdcPs *InstancePtr) +{ + u16 Divisor; + + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the divisor value from the Configuration Register 2. + */ + Divisor = (u16) XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_CFR2_OFFSET); + + return (u8) (Divisor >> XADCPS_CFR2_CD_SHIFT); +} + +/****************************************************************************/ +/** +* +* This function enables the specified channels in the ADC Channel Selection +* Sequencer Registers. The sequencer must be disabled before writing to these +* regsiters. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param ChEnableMask is the bit mask of all the channels to be enabled. +* Use XADCPS_SEQ_CH__* defined in xadcps_hw.h to specify the Channel +* numbers. Bit masks of 1 will be enabled and bit mask of 0 will +* be disabled. +* The ChEnableMask is a 32 bit mask that is written to the two +* 16 bit ADC Channel Selection Sequencer Registers. +* +* @return +* - XST_SUCCESS if the given values were written successfully to +* the ADC Channel Selection Sequencer Registers. +* - XST_FAILURE if the channel sequencer is enabled. +* +* @note None +* +*****************************************************************************/ +int XAdcPs_SetSeqChEnables(XAdcPs *InstancePtr, u32 ChEnableMask) +{ + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * The sequencer must be disabled for writing any of these registers + * Return XST_FAILURE if the channel sequencer is enabled. + */ + if ((XAdcPs_GetSequencerMode(InstancePtr) != XADCPS_SEQ_MODE_SAFE)) { + return XST_FAILURE; + } + + /* + * Enable the specified channels in the ADC Channel Selection Sequencer + * Registers. + */ + XAdcPs_WriteInternalReg(InstancePtr, + XADCPS_SEQ00_OFFSET, + (ChEnableMask & XADCPS_SEQ00_CH_VALID_MASK)); + + XAdcPs_WriteInternalReg(InstancePtr, + XADCPS_SEQ01_OFFSET, + (ChEnableMask >> XADCPS_SEQ_CH_AUX_SHIFT) & + XADCPS_SEQ01_CH_VALID_MASK); + + return XST_SUCCESS; +} + +/****************************************************************************/ +/** +* +* This function gets the channel enable bits status from the ADC Channel +* Selection Sequencer Registers. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @return Gets the channel enable bits. Use XADCPS_SEQ_CH__* defined in +* xadcps_hw.h to interpret the Channel numbers. Bit masks of 1 +* are the channels that are enabled and bit mask of 0 are +* the channels that are disabled. +* +* @return None +* +* @note None +* +*****************************************************************************/ +u32 XAdcPs_GetSeqChEnables(XAdcPs *InstancePtr) +{ + u32 RegValEnable; + + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the channel enable bits for all the channels from the ADC + * Channel Selection Register. + */ + RegValEnable = XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_SEQ00_OFFSET) & + XADCPS_SEQ00_CH_VALID_MASK; + RegValEnable |= (XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_SEQ01_OFFSET) & + XADCPS_SEQ01_CH_VALID_MASK) << + XADCPS_SEQ_CH_AUX_SHIFT; + + + return RegValEnable; +} + +/****************************************************************************/ +/** +* +* This function enables the averaging for the specified channels in the ADC +* Channel Averaging Enable Sequencer Registers. The sequencer must be disabled +* before writing to these regsiters. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param AvgEnableChMask is the bit mask of all the channels for which +* averaging is to be enabled. Use XADCPS_SEQ_CH__* defined in +* xadcps_hw.h to specify the Channel numbers. Averaging will be +* enabled for bit masks of 1 and disabled for bit mask of 0. +* The AvgEnableChMask is a 32 bit mask that is written to the two +* 16 bit ADC Channel Averaging Enable Sequencer Registers. +* +* @return +* - XST_SUCCESS if the given values were written successfully to +* the ADC Channel Averaging Enables Sequencer Registers. +* - XST_FAILURE if the channel sequencer is enabled. +* +* @note None +* +*****************************************************************************/ +int XAdcPs_SetSeqAvgEnables(XAdcPs *InstancePtr, u32 AvgEnableChMask) +{ + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * The sequencer must be disabled for writing any of these registers + * Return XST_FAILURE if the channel sequencer is enabled. + */ + if ((XAdcPs_GetSequencerMode(InstancePtr) != XADCPS_SEQ_MODE_SAFE)) { + return XST_FAILURE; + } + + /* + * Enable/disable the averaging for the specified channels in the + * ADC Channel Averaging Enables Sequencer Registers. + */ + XAdcPs_WriteInternalReg(InstancePtr, + XADCPS_SEQ02_OFFSET, + (AvgEnableChMask & XADCPS_SEQ02_CH_VALID_MASK)); + + XAdcPs_WriteInternalReg(InstancePtr, + XADCPS_SEQ03_OFFSET, + (AvgEnableChMask >> XADCPS_SEQ_CH_AUX_SHIFT) & + XADCPS_SEQ03_CH_VALID_MASK); + + return XST_SUCCESS; +} + +/****************************************************************************/ +/** +* +* This function returns the channels for which the averaging has been enabled +* in the ADC Channel Averaging Enables Sequencer Registers. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @returns The status of averaging (enabled/disabled) for all the channels. +* Use XADCPS_SEQ_CH__* defined in xadcps_hw.h to interpret the +* Channel numbers. Bit masks of 1 are the channels for which +* averaging is enabled and bit mask of 0 are the channels for +* averaging is disabled +* +* @note None +* +*****************************************************************************/ +u32 XAdcPs_GetSeqAvgEnables(XAdcPs *InstancePtr) +{ + u32 RegValAvg; + + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the averaging enable status for all the channels from the + * ADC Channel Averaging Enables Sequencer Registers. + */ + RegValAvg = XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_SEQ02_OFFSET) & XADCPS_SEQ02_CH_VALID_MASK; + RegValAvg |= (XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_SEQ03_OFFSET) & XADCPS_SEQ03_CH_VALID_MASK) << + XADCPS_SEQ_CH_AUX_SHIFT; + + return RegValAvg; +} + +/****************************************************************************/ +/** +* +* This function sets the Analog input mode for the specified channels in the ADC +* Channel Analog-Input Mode Sequencer Registers. The sequencer must be disabled +* before writing to these regsiters. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param InputModeChMask is the bit mask of all the channels for which +* the input mode is differential mode. Use XADCPS_SEQ_CH__* defined +* in xadcps_hw.h to specify the channel numbers. Differential +* input mode will be set for bit masks of 1 and unipolar input +* mode for bit masks of 0. +* The InputModeChMask is a 32 bit mask that is written to the two +* 16 bit ADC Channel Analog-Input Mode Sequencer Registers. +* +* @return +* - XST_SUCCESS if the given values were written successfully to +* the ADC Channel Analog-Input Mode Sequencer Registers. +* - XST_FAILURE if the channel sequencer is enabled. +* +* @note None +* +*****************************************************************************/ +int XAdcPs_SetSeqInputMode(XAdcPs *InstancePtr, u32 InputModeChMask) +{ + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * The sequencer must be disabled for writing any of these registers + * Return XST_FAILURE if the channel sequencer is enabled. + */ + if ((XAdcPs_GetSequencerMode(InstancePtr) != XADCPS_SEQ_MODE_SAFE)) { + return XST_FAILURE; + } + + /* + * Set the input mode for the specified channels in the ADC Channel + * Analog-Input Mode Sequencer Registers. + */ + XAdcPs_WriteInternalReg(InstancePtr, + XADCPS_SEQ04_OFFSET, + (InputModeChMask & XADCPS_SEQ04_CH_VALID_MASK)); + + XAdcPs_WriteInternalReg(InstancePtr, + XADCPS_SEQ05_OFFSET, + (InputModeChMask >> XADCPS_SEQ_CH_AUX_SHIFT) & + XADCPS_SEQ05_CH_VALID_MASK); + + return XST_SUCCESS; +} + +/****************************************************************************/ +/** +* +* This function gets the Analog input mode for all the channels from +* the ADC Channel Analog-Input Mode Sequencer Registers. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @returns The input mode for all the channels. +* Use XADCPS_SEQ_CH_* defined in xadcps_hw.h to interpret the +* Channel numbers. Bit masks of 1 are the channels for which +* input mode is differential and bit mask of 0 are the channels +* for which input mode is unipolar. +* +* @note None. +* +*****************************************************************************/ +u32 XAdcPs_GetSeqInputMode(XAdcPs *InstancePtr) +{ + u32 InputMode; + + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Get the input mode for all the channels from the ADC Channel + * Analog-Input Mode Sequencer Registers. + */ + InputMode = XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_SEQ04_OFFSET) & + XADCPS_SEQ04_CH_VALID_MASK; + InputMode |= (XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_SEQ05_OFFSET) & + XADCPS_SEQ05_CH_VALID_MASK) << + XADCPS_SEQ_CH_AUX_SHIFT; + + return InputMode; +} + +/****************************************************************************/ +/** +* +* This function sets the number of Acquisition cycles in the ADC Channel +* Acquisition Time Sequencer Registers. The sequencer must be disabled +* before writing to these regsiters. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param AcqCyclesChMask is the bit mask of all the channels for which +* the number of acquisition cycles is to be extended. +* Use XADCPS_SEQ_CH__* defined in xadcps_hw.h to specify the Channel +* numbers. Acquisition cycles will be extended to 10 ADCCLK cycles +* for bit masks of 1 and will be the default 4 ADCCLK cycles for +* bit masks of 0. +* The AcqCyclesChMask is a 32 bit mask that is written to the two +* 16 bit ADC Channel Acquisition Time Sequencer Registers. +* +* @return +* - XST_SUCCESS if the given values were written successfully to +* the Channel Sequencer Registers. +* - XST_FAILURE if the channel sequencer is enabled. +* +* @note None. +* +*****************************************************************************/ +int XAdcPs_SetSeqAcqTime(XAdcPs *InstancePtr, u32 AcqCyclesChMask) +{ + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * The sequencer must be disabled for writing any of these registers + * Return XST_FAILURE if the channel sequencer is enabled. + */ + if ((XAdcPs_GetSequencerMode(InstancePtr) != + XADCPS_SEQ_MODE_SAFE)) { + return XST_FAILURE; + } + + /* + * Set the Acquisition time for the specified channels in the + * ADC Channel Acquisition Time Sequencer Registers. + */ + XAdcPs_WriteInternalReg(InstancePtr, + XADCPS_SEQ06_OFFSET, + (AcqCyclesChMask & XADCPS_SEQ06_CH_VALID_MASK)); + + XAdcPs_WriteInternalReg(InstancePtr, + XADCPS_SEQ07_OFFSET, + (AcqCyclesChMask >> XADCPS_SEQ_CH_AUX_SHIFT) & + XADCPS_SEQ07_CH_VALID_MASK); + + return XST_SUCCESS; +} + +/****************************************************************************/ +/** +* +* This function gets the status of acquisition from the ADC Channel Acquisition +* Time Sequencer Registers. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @returns The acquisition time for all the channels. +* Use XADCPS_SEQ_CH__* defined in xadcps_hw.h to interpret the +* Channel numbers. Bit masks of 1 are the channels for which +* acquisition cycles are extended and bit mask of 0 are the +* channels for which acquisition cycles are not extended. +* +* @note None +* +*****************************************************************************/ +u32 XAdcPs_GetSeqAcqTime(XAdcPs *InstancePtr) +{ + u32 RegValAcq; + + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Get the Acquisition cycles for the specified channels from the ADC + * Channel Acquisition Time Sequencer Registers. + */ + RegValAcq = XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_SEQ06_OFFSET) & + XADCPS_SEQ06_CH_VALID_MASK; + RegValAcq |= (XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_SEQ07_OFFSET) & + XADCPS_SEQ07_CH_VALID_MASK) << + XADCPS_SEQ_CH_AUX_SHIFT; + + return RegValAcq; +} + +/****************************************************************************/ +/** +* +* This functions sets the contents of the given Alarm Threshold Register. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param AlarmThrReg is the index of an Alarm Threshold Register to +* be set. Use XADCPS_ATR_* constants defined in xadcps.h to +* specify the index. +* @param Value is the 16-bit threshold value to write into the register. +* +* @return None. +* +* @note Use XAdcPs_SetOverTemp() to set the Over Temperature upper +* threshold value. +* +*****************************************************************************/ +void XAdcPs_SetAlarmThreshold(XAdcPs *InstancePtr, u8 AlarmThrReg, u16 Value) +{ + + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(AlarmThrReg <= XADCPS_ATR_VCCPDRO_LOWER); + + /* + * Write the value into the specified Alarm Threshold Register. + */ + XAdcPs_WriteInternalReg(InstancePtr, XADCPS_ATR_TEMP_UPPER_OFFSET + + AlarmThrReg,Value); + +} + +/****************************************************************************/ +/** +* +* This function returns the contents of the specified Alarm Threshold Register. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param AlarmThrReg is the index of an Alarm Threshold Register +* to be read. Use XADCPS_ATR_* constants defined in xadcps_hw.h +* to specify the index. +* +* @return A 16-bit value representing the contents of the selected Alarm +* Threshold Register. +* +* @note None. +* +*****************************************************************************/ +u16 XAdcPs_GetAlarmThreshold(XAdcPs *InstancePtr, u8 AlarmThrReg) +{ + u32 RegData; + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(AlarmThrReg <= XADCPS_ATR_VCCPDRO_LOWER); + + /* + * Read the specified Alarm Threshold Register and return + * the value + */ + RegData = XAdcPs_ReadInternalReg(InstancePtr, + (XADCPS_ATR_TEMP_UPPER_OFFSET + AlarmThrReg)); + + return (u16) RegData; +} + + +/****************************************************************************/ +/** +* +* This function enables programming of the powerdown temperature for the +* OverTemp signal in the OT Powerdown register. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XAdcPs_EnableUserOverTemp(XAdcPs *InstancePtr) +{ + u16 OtUpper; + + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the OT upper Alarm Threshold Register. + */ + OtUpper = XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_ATR_OT_UPPER_OFFSET); + OtUpper &= ~(XADCPS_ATR_OT_UPPER_ENB_MASK); + + /* + * Preserve the powerdown value and write OT enable value the into the + * OT Upper Alarm Threshold Register. + */ + OtUpper |= XADCPS_ATR_OT_UPPER_ENB_VAL; + XAdcPs_WriteInternalReg(InstancePtr, + XADCPS_ATR_OT_UPPER_OFFSET, OtUpper); +} + +/****************************************************************************/ +/** +* +* This function disables programming of the powerdown temperature for the +* OverTemp signal in the OT Powerdown register. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @return None. +* +* @note None. +* +* +*****************************************************************************/ +void XAdcPs_DisableUserOverTemp(XAdcPs *InstancePtr) +{ + u16 OtUpper; + + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the OT Upper Alarm Threshold Register. + */ + OtUpper = XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_ATR_OT_UPPER_OFFSET); + OtUpper &= ~(XADCPS_ATR_OT_UPPER_ENB_MASK); + + XAdcPs_WriteInternalReg(InstancePtr, + XADCPS_ATR_OT_UPPER_OFFSET, OtUpper); +} + + +/****************************************************************************/ +/** +* +* The function enables the Event mode or Continuous mode in the sequencer mode. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param IsEventMode is a boolean parameter that specifies continuous +* sampling (specify FALSE) or event driven sampling mode (specify +* TRUE) for the given channel. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XAdcPs_SetSequencerEvent(XAdcPs *InstancePtr, int IsEventMode) +{ + u32 RegValue; + + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid((IsEventMode == TRUE) || (IsEventMode == FALSE)); + + /* + * Read the Configuration Register 0. + */ + RegValue = XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_CFR0_OFFSET) & + (~XADCPS_CFR0_EC_MASK); + + /* + * Set the ADC mode. + */ + if (IsEventMode == TRUE) { + RegValue |= XADCPS_CFR0_EC_MASK; + } else { + RegValue &= ~XADCPS_CFR0_EC_MASK; + } + + XAdcPs_WriteInternalReg(InstancePtr, XADCPS_CFR0_OFFSET, + RegValue); +} + + +/****************************************************************************/ +/** +* +* This function returns the sampling mode. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @return The sampling mode +* - 0 specifies continuous sampling +* - 1 specifies event driven sampling mode +* +* @note None. +* +*****************************************************************************/ +int XAdcPs_GetSamplingMode(XAdcPs *InstancePtr) +{ + u32 Mode; + + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the sampling mode from the Configuration Register 0. + */ + Mode = XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_CFR0_OFFSET) & + XADCPS_CFR0_EC_MASK; + if (Mode) { + + return 1; + } + + return (0); +} + + +/****************************************************************************/ +/** +* +* This function sets the External Mux mode. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param MuxMode specifies whether External Mux is used +* - FALSE specifies NO external MUX +* - TRUE specifies External Mux is used +* @param Channel specifies the channel to be used for the +* external Mux. Please read the Device Spec for which +* channels are valid for which mode. +* +* @return None. +* +* @note There is no Assert in this function for checking the channel +* number if the external Mux is used. The user should provide a +* valid channel number. +* +*****************************************************************************/ +void XAdcPs_SetMuxMode(XAdcPs *InstancePtr, int MuxMode, u8 Channel) +{ + u32 RegValue; + + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid((MuxMode == TRUE) || (MuxMode == FALSE)); + + /* + * Read the Configuration Register 0. + */ + RegValue = XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_CFR0_OFFSET) & + (~XADCPS_CFR0_MUX_MASK); + /* + * Select the Mux mode and the channel to be used. + */ + if (MuxMode == TRUE) { + RegValue |= XADCPS_CFR0_MUX_MASK; + RegValue |= (Channel & XADCPS_CFR0_CHANNEL_MASK); + + } + + /* + * Write the mux mode into the Configuration Register 0. + */ + XAdcPs_WriteInternalReg(InstancePtr, XADCPS_CFR0_OFFSET, + RegValue); +} + + +/****************************************************************************/ +/** +* +* This function sets the Power Down mode. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param Mode specifies the Power Down Mode +* - XADCPS_PD_MODE_NONE specifies NO Power Down (Both ADC A and +* ADC B are enabled) +* - XADCPS_PD_MODE_ADCB specfies the Power Down of ADC B +* - XADCPS_PD_MODE_XADC specifies the Power Down of +* both ADC A and ADC B. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XAdcPs_SetPowerdownMode(XAdcPs *InstancePtr, u32 Mode) +{ + u32 RegValue; + + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Mode < XADCPS_PD_MODE_XADC); + + + /* + * Read the Configuration Register 2. + */ + RegValue = XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_CFR2_OFFSET) & + (~XADCPS_CFR2_PD_MASK); + /* + * Select the Power Down mode. + */ + RegValue |= (Mode << XADCPS_CFR2_PD_SHIFT); + + XAdcPs_WriteInternalReg(InstancePtr, XADCPS_CFR2_OFFSET, + RegValue); +} + +/****************************************************************************/ +/** +* +* This function gets the Power Down mode. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @return Mode specifies the Power Down Mode +* - XADCPS_PD_MODE_NONE specifies NO Power Down (Both ADC A and +* ADC B are enabled) +* - XADCPS_PD_MODE_ADCB specfies the Power Down of ADC B +* - XADCPS_PD_MODE_XADC specifies the Power Down of +* both ADC A and ADC B. +* +* @note None. +* +*****************************************************************************/ +u32 XAdcPs_GetPowerdownMode(XAdcPs *InstancePtr) +{ + u32 RegValue; + + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the Power Down Mode. + */ + RegValue = XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_CFR2_OFFSET) & + (~XADCPS_CFR2_PD_MASK); + /* + * Return the Power Down mode. + */ + return (RegValue >> XADCPS_CFR2_PD_SHIFT); + +} + +/****************************************************************************/ +/** +* +* This function is used for writing to XADC Registers using the command FIFO. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param RegOffset is the offset of the XADC register to be written. +* @param Data is the data to be written. +* +* @return None. +* +* @note None. +* +* +*****************************************************************************/ +void XAdcPs_WriteInternalReg(XAdcPs *InstancePtr, u32 RegOffset, u32 Data) +{ + u32 RegData; + + /* + * Write the Data into the FIFO Register. + */ + RegData = XAdcPs_FormatWriteData(RegOffset, Data, TRUE); + + XAdcPs_WriteFifo(InstancePtr, RegData); + + /* Read the Read FIFO after any write since for each write + * one location of Read FIFO gets updated + */ + XAdcPs_ReadFifo(InstancePtr); + +} + + +/****************************************************************************/ +/** +* +* This function is used for reading from the XADC Registers using the Data FIFO. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param RegOffset is the offset of the XADC register to be read. +* +* @return Data read from the FIFO +* +* @note None. +* +* +*****************************************************************************/ +u32 XAdcPs_ReadInternalReg(XAdcPs *InstancePtr, u32 RegOffset) +{ + + u32 RegData; + + RegData = XAdcPs_FormatWriteData(RegOffset, 0x0, FALSE); + + /* Read cmd to FIFO*/ + XAdcPs_WriteFifo(InstancePtr, RegData); + + /* Do a Dummy read */ + RegData = XAdcPs_ReadFifo(InstancePtr); + + /* Do a Dummy write to get the actual read */ + XAdcPs_WriteFifo(InstancePtr, RegData); + + /* Do the Actual read */ + RegData = XAdcPs_ReadFifo(InstancePtr); + + return RegData; + +} +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/xadcps_v2_3/src/xadcps.h b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/xadcps_v2_3/src/xadcps.h new file mode 100644 index 0000000..900edf0 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/xadcps_v2_3/src/xadcps.h @@ -0,0 +1,589 @@ +/****************************************************************************** +* +* Copyright (C) 2011 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xadcps.h +* @addtogroup xadcps_v2_3 +* @{ +* @details +* +* The XAdcPs driver supports the Xilinx XADC/ADC device. +* +* The XADC/ADC device has the following features: +* - 10-bit, 200-KSPS (kilo samples per second) +* Analog-to-Digital Converter (ADC) +* - Monitoring of on-chip supply voltages and temperature +* - 1 dedicated differential analog-input pair and +* 16 auxiliary differential analog-input pairs +* - Automatic alarms based on user defined limits for the on-chip +* supply voltages and temperature +* - Automatic Channel Sequencer, programmable averaging, programmable +* acquisition time for the external inputs, unipolar or differential +* input selection for the external inputs +* - Inbuilt Calibration +* - Optional interrupt request generation +* +* +* The user should refer to the hardware device specification for detailed +* information about the device. +* +* This header file contains the prototypes of driver functions that can +* be used to access the XADC/ADC device. +* +* +* XADC Channel Sequencer Modes +* +* The XADC Channel Sequencer supports the following operating modes: +* +* - Default : This is the default mode after power up. +* In this mode of operation the XADC operates in +* a sequence mode, monitoring the on chip sensors: +* Temperature, VCCINT, and VCCAUX. +* - One pass through sequence : In this mode the XADC +* converts the channels enabled in the Sequencer Channel Enable +* registers for a single pass and then stops. +* - Continuous cycling of sequence : In this mode the XADC +* converts the channels enabled in the Sequencer Channel Enable +* registers continuously. +* - Single channel mode: In this mode the XADC Channel +* Sequencer is disabled and the XADC operates in a +* Single Channel Mode. +* The XADC can operate either in a Continuous or Event +* driven sampling mode in the single channel mode. +* - Simultaneous Sampling Mode: In this mode the XADC Channel +* Sequencer will automatically sequence through eight fixed pairs +* of auxiliary analog input channels for simulataneous conversion. +* - Independent ADC mode: In this mode the first ADC (A) is used to +* is used to implement a fixed monitoring mode similar to the +* default mode but the alarm fucntions ar eenabled. +* The second ADC (B) is available to be used with external analog +* input channels only. +* +* Read the XADC spec for more information about the sequencer modes. +* +* Initialization and Configuration +* +* The device driver enables higher layer software (e.g., an application) to +* communicate to the XADC/ADC device. +* +* XAdcPs_CfgInitialize() API is used to initialize the XADC/ADC +* device. The user needs to first call the XAdcPs_LookupConfig() API which +* returns the Configuration structure pointer which is passed as a parameter to +* the XAdcPs_CfgInitialize() API. +* +* +* Interrupts +* +* The XADC/ADC device supports interrupt driven mode and the default +* operation mode is polling mode. +* +* The interrupt mode is available only if hardware is configured to support +* interrupts. +* +* This driver does not provide a Interrupt Service Routine (ISR) for the device. +* It is the responsibility of the application to provide one if needed. Refer to +* the interrupt example provided with this driver for details on using the +* device in interrupt mode. +* +* +* Virtual Memory +* +* This driver supports Virtual Memory. The RTOS is responsible for calculating +* the correct device base address in Virtual Memory space. +* +* +* Threads +* +* This driver is not thread safe. Any needs for threads or thread mutual +* exclusion must be satisfied by the layer above this driver. +* +* +* Asserts +* +* Asserts are used within all Xilinx drivers to enforce constraints on argument +* values. Asserts can be turned off on a system-wide basis by defining, at +* compile time, the NDEBUG identifier. By default, asserts are turned on and it +* is recommended that users leave asserts on during development. +* +* +* Building the driver +* +* The XAdcPs driver is composed of several source files. This allows the user +* to build and link only those parts of the driver that are necessary. +* +* Limitations of the driver +* +* XADC/ADC device can be accessed through the JTAG port and the PLB +* interface. The driver implementation does not support the simultaneous access +* of the device by both these interfaces. The user has to care of this situation +* in the user application code. +* +*

+* +*
+*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- -----  -------- -----------------------------------------------------
+* 1.00a ssb    12/22/11 First release based on the XPS/AXI xadc driver
+* 1.01a bss    02/18/13	Modified XAdcPs_SetSeqChEnables,XAdcPs_SetSeqAvgEnables
+*			XAdcPs_SetSeqInputMode and XAdcPs_SetSeqAcqTime APIs
+*			in xadcps.c to fix CR #693371
+* 1.03a bss    11/01/13 Modified xadcps_hw.h to use correct Register offsets
+*			CR#749687
+* 2.1   bss    08/05/14 Added declarations for XAdcPs_SetSequencerEvent,
+*			XAdcPs_GetSamplingMode, XAdcPs_SetMuxMode,
+*			XAdcPs_SetPowerdownMode and XAdcPs_GetPowerdownMode
+*			functions.
+*			Modified Assert for XAdcPs_SetSingleChParams in
+*			xadcps.c to fix CR #807563.
+* 2.2   bss    04/27/14 Modified to use correct Device Config base address in
+*						xadcps.c (CR#854437).
+*       ms     01/23/17 Added xil_printf statement in main function for all
+*                       examples to ensure that "Successfully ran" and "Failed"
+*                       strings are available in all examples. This is a fix
+*                       for CR-965028.
+*       ms     03/17/17 Added readme.txt file in examples folder for doxygen
+*                       generation.
+*       ms     04/05/17 Modified Comment lines in functions of xadcps
+*                       examples to recognize it as documentation block
+*                       for doxygen generation.
+* 2.3   mn     07/09/18 Fix Doxygen warning
+*
+* 
+* +*****************************************************************************/ +#ifndef XADCPS_H /* Prevent circular inclusions */ +#define XADCPS_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files ********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xstatus.h" +#include "xadcps_hw.h" + +/************************** Constant Definitions ****************************/ + + +/** + * @name Indexes for the different channels. + * @{ + */ +#define XADCPS_CH_TEMP 0x0 /**< On Chip Temperature */ +#define XADCPS_CH_VCCINT 0x1 /**< VCCINT */ +#define XADCPS_CH_VCCAUX 0x2 /**< VCCAUX */ +#define XADCPS_CH_VPVN 0x3 /**< VP/VN Dedicated analog inputs */ +#define XADCPS_CH_VREFP 0x4 /**< VREFP */ +#define XADCPS_CH_VREFN 0x5 /**< VREFN */ +#define XADCPS_CH_VBRAM 0x6 /**< On-chip VBRAM Data Reg, 7 series */ +#define XADCPS_CH_SUPPLY_CALIB 0x07 /**< Supply Calib Data Reg */ +#define XADCPS_CH_ADC_CALIB 0x08 /**< ADC Offset Channel Reg */ +#define XADCPS_CH_GAINERR_CALIB 0x09 /**< Gain Error Channel Reg */ +#define XADCPS_CH_VCCPINT 0x0D /**< On-chip PS VCCPINT Channel , Zynq */ +#define XADCPS_CH_VCCPAUX 0x0E /**< On-chip PS VCCPAUX Channel , Zynq */ +#define XADCPS_CH_VCCPDRO 0x0F /**< On-chip PS VCCPDRO Channel , Zynq */ +#define XADCPS_CH_AUX_MIN 16 /**< Channel number for 1st Aux Channel */ +#define XADCPS_CH_AUX_MAX 31 /**< Channel number for Last Aux channel */ + +/*@}*/ + + +/** + * @name Indexes for reading the Calibration Coefficient Data. + * @{ + */ +#define XADCPS_CALIB_SUPPLY_COEFF 0 /**< Supply Offset Calib Coefficient */ +#define XADCPS_CALIB_ADC_COEFF 1 /**< ADC Offset Calib Coefficient */ +#define XADCPS_CALIB_GAIN_ERROR_COEFF 2 /**< Gain Error Calib Coefficient*/ +/*@}*/ + + +/** + * @name Indexes for reading the Minimum/Maximum Measurement Data. + * @{ + */ +#define XADCPS_MAX_TEMP 0 /**< Maximum Temperature Data */ +#define XADCPS_MAX_VCCINT 1 /**< Maximum VCCINT Data */ +#define XADCPS_MAX_VCCAUX 2 /**< Maximum VCCAUX Data */ +#define XADCPS_MAX_VBRAM 3 /**< Maximum VBRAM Data */ +#define XADCPS_MIN_TEMP 4 /**< Minimum Temperature Data */ +#define XADCPS_MIN_VCCINT 5 /**< Minimum VCCINT Data */ +#define XADCPS_MIN_VCCAUX 6 /**< Minimum VCCAUX Data */ +#define XADCPS_MIN_VBRAM 7 /**< Minimum VBRAM Data */ +#define XADCPS_MAX_VCCPINT 8 /**< Maximum VCCPINT Register , Zynq */ +#define XADCPS_MAX_VCCPAUX 9 /**< Maximum VCCPAUX Register , Zynq */ +#define XADCPS_MAX_VCCPDRO 0xA /**< Maximum VCCPDRO Register , Zynq */ +#define XADCPS_MIN_VCCPINT 0xC /**< Minimum VCCPINT Register , Zynq */ +#define XADCPS_MIN_VCCPAUX 0xD /**< Minimum VCCPAUX Register , Zynq */ +#define XADCPS_MIN_VCCPDRO 0xE /**< Minimum VCCPDRO Register , Zynq */ + +/*@}*/ + + +/** + * @name Alarm Threshold(Limit) Register (ATR) indexes. + * @{ + */ +#define XADCPS_ATR_TEMP_UPPER 0 /**< High user Temperature */ +#define XADCPS_ATR_VCCINT_UPPER 1 /**< VCCINT high voltage limit register */ +#define XADCPS_ATR_VCCAUX_UPPER 2 /**< VCCAUX high voltage limit register */ +#define XADCPS_ATR_OT_UPPER 3 /**< VCCAUX high voltage limit register */ +#define XADCPS_ATR_TEMP_LOWER 4 /**< Upper Over Temperature limit Reg */ +#define XADCPS_ATR_VCCINT_LOWER 5 /**< VCCINT high voltage limit register */ +#define XADCPS_ATR_VCCAUX_LOWER 6 /**< VCCAUX low voltage limit register */ +#define XADCPS_ATR_OT_LOWER 7 /**< Lower Over Temperature limit */ +#define XADCPS_ATR_VBRAM_UPPER_ 8 /**< VRBAM Upper Alarm Reg, 7 Series */ +#define XADCPS_ATR_VCCPINT_UPPER 9 /**< VCCPINT Upper Alarm Reg, Zynq */ +#define XADCPS_ATR_VCCPAUX_UPPER 0xA /**< VCCPAUX Upper Alarm Reg, Zynq */ +#define XADCPS_ATR_VCCPDRO_UPPER 0xB /**< VCCPDRO Upper Alarm Reg, Zynq */ +#define XADCPS_ATR_VBRAM_LOWER 0xC /**< VRBAM Lower Alarm Reg, 7 Series */ +#define XADCPS_ATR_VCCPINT_LOWER 0xD /**< VCCPINT Lower Alarm Reg , Zynq */ +#define XADCPS_ATR_VCCPAUX_LOWER 0xE /**< VCCPAUX Lower Alarm Reg , Zynq */ +#define XADCPS_ATR_VCCPDRO_LOWER 0xF /**< VCCPDRO Lower Alarm Reg , Zynq */ + +/*@}*/ + + +/** + * @name Averaging to be done for the channels. + * @{ + */ +#define XADCPS_AVG_0_SAMPLES 0 /**< No Averaging */ +#define XADCPS_AVG_16_SAMPLES 1 /**< Average 16 samples */ +#define XADCPS_AVG_64_SAMPLES 2 /**< Average 64 samples */ +#define XADCPS_AVG_256_SAMPLES 3 /**< Average 256 samples */ + +/*@}*/ + + +/** + * @name Channel Sequencer Modes of operation + * @{ + */ +#define XADCPS_SEQ_MODE_SAFE 0 /**< Default Safe Mode */ +#define XADCPS_SEQ_MODE_ONEPASS 1 /**< Onepass through Sequencer */ +#define XADCPS_SEQ_MODE_CONTINPASS 2 /**< Continuous Cycling Sequencer */ +#define XADCPS_SEQ_MODE_SINGCHAN 3 /**< Single channel -No Sequencing */ +#define XADCPS_SEQ_MODE_SIMUL_SAMPLING 4 /**< Simultaneous sampling */ +#define XADCPS_SEQ_MODE_INDEPENDENT 8 /**< Independent mode */ + +/*@}*/ + + + +/** + * @name Power Down Modes + * @{ + */ +#define XADCPS_PD_MODE_NONE 0 /**< No Power Down */ +#define XADCPS_PD_MODE_ADCB 1 /**< Power Down ADC B */ +#define XADCPS_PD_MODE_XADC 2 /**< Power Down ADC A and ADC B */ +/*@}*/ + +/**************************** Type Definitions ******************************/ + +/** + * This typedef contains configuration information for the XADC/ADC + * device. + */ +typedef struct { + u16 DeviceId; /**< Unique ID of device */ + u32 BaseAddress; /**< Device base address */ +} XAdcPs_Config; + + +/** + * The driver's instance data. The user is required to allocate a variable + * of this type for every XADC/ADC device in the system. A pointer to + * a variable of this type is then passed to the driver API functions. + */ +typedef struct { + XAdcPs_Config Config; /**< XAdcPs_Config of current device */ + u32 IsReady; /**< Device is initialized and ready */ + +} XAdcPs; + +/***************** Macros (Inline Functions) Definitions ********************/ + +/****************************************************************************/ +/** +* +* This macro checks if the XADC device is in Event Sampling mode. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @return +* - TRUE if the device is in Event Sampling Mode. +* - FALSE if the device is in Continuous Sampling Mode. +* +* @note C-Style signature: +* int XAdcPs_IsEventSamplingMode(XAdcPs *InstancePtr); +* +*****************************************************************************/ +#define XAdcPs_IsEventSamplingModeSet(InstancePtr) \ + (((XAdcPs_ReadInternalReg(InstancePtr, \ + XADCPS_CFR0_OFFSET) & XADCPS_CFR0_EC_MASK) ? \ + TRUE : FALSE)) + + +/****************************************************************************/ +/** +* +* This macro checks if the XADC device is in External Mux mode. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @return +* - TRUE if the device is in External Mux Mode. +* - FALSE if the device is NOT in External Mux Mode. +* +* @note C-Style signature: +* int XAdcPs_IsExternalMuxMode(XAdcPs *InstancePtr); +* +*****************************************************************************/ +#define XAdcPs_IsExternalMuxModeSet(InstancePtr) \ + (((XAdcPs_ReadInternalReg(InstancePtr, \ + XADCPS_CFR0_OFFSET) & XADCPS_CFR0_MUX_MASK) ? \ + TRUE : FALSE)) + +/****************************************************************************/ +/** +* +* This macro converts XADC Raw Data to Temperature(centigrades). +* +* @param AdcData is the Raw ADC Data from XADC. +* +* @return The Temperature in centigrades. +* +* @note C-Style signature: +* float XAdcPs_RawToTemperature(u32 AdcData); +* +*****************************************************************************/ +#define XAdcPs_RawToTemperature(AdcData) \ + ((((float)(AdcData)/65536.0f)/0.00198421639f ) - 273.15f) + +/****************************************************************************/ +/** +* +* This macro converts XADC/ADC Raw Data to Voltage(volts). +* +* @param AdcData is the XADC/ADC Raw Data. +* +* @return The Voltage in volts. +* +* @note C-Style signature: +* float XAdcPs_RawToVoltage(u32 AdcData); +* +*****************************************************************************/ +#define XAdcPs_RawToVoltage(AdcData) \ + ((((float)(AdcData))* (3.0f))/65536.0f) + +/****************************************************************************/ +/** +* +* This macro converts Temperature in centigrades to XADC/ADC Raw Data. +* +* @param Temperature is the Temperature in centigrades to be +* converted to XADC/ADC Raw Data. +* +* @return The XADC/ADC Raw Data. +* +* @note C-Style signature: +* int XAdcPs_TemperatureToRaw(float Temperature); +* +*****************************************************************************/ +#define XAdcPs_TemperatureToRaw(Temperature) \ + ((int)(((Temperature) + 273.15f)*65536.0f*0.00198421639f)) + +/****************************************************************************/ +/** +* +* This macro converts Voltage in Volts to XADC/ADC Raw Data. +* +* @param Voltage is the Voltage in volts to be converted to +* XADC/ADC Raw Data. +* +* @return The XADC/ADC Raw Data. +* +* @note C-Style signature: +* int XAdcPs_VoltageToRaw(float Voltage); +* +*****************************************************************************/ +#define XAdcPs_VoltageToRaw(Voltage) \ + ((int)((Voltage)*65536.0f/3.0f)) + + +/****************************************************************************/ +/** +* +* This macro is used for writing to the XADC Registers using the +* command FIFO. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param Data is the value to be written to XADC register. +* +* @return None. +* +* @note C-Style signature: +* void XAdcPs_WriteFifo(XAdcPs *InstancePtr, u32 Data); +* +*****************************************************************************/ +#define XAdcPs_WriteFifo(InstancePtr, Data) \ + XAdcPs_WriteReg((InstancePtr)->Config.BaseAddress, \ + XADCPS_CMDFIFO_OFFSET, Data); + + +/****************************************************************************/ +/** +* +* This macro is used for reading from the XADC Registers using the +* data FIFO. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @return Data read from the FIFO +* +* @note C-Style signature: +* u32 XAdcPs_ReadFifo(XAdcPs *InstancePtr); +* +*****************************************************************************/ +#define XAdcPs_ReadFifo(InstancePtr) \ + XAdcPs_ReadReg((InstancePtr)->Config.BaseAddress, \ + XADCPS_RDFIFO_OFFSET); + + +/************************** Function Prototypes *****************************/ + + + +/** + * Functions in xadcps_sinit.c + */ +XAdcPs_Config *XAdcPs_LookupConfig(u16 DeviceId); + +/** + * Functions in xadcps.c + */ +int XAdcPs_CfgInitialize(XAdcPs *InstancePtr, + XAdcPs_Config *ConfigPtr, + u32 EffectiveAddr); + + +u32 XAdcPs_GetStatus(XAdcPs *InstancePtr); + +u32 XAdcPs_GetAlarmOutputStatus(XAdcPs *InstancePtr); + +void XAdcPs_StartAdcConversion(XAdcPs *InstancePtr); + +void XAdcPs_Reset(XAdcPs *InstancePtr); + +u16 XAdcPs_GetAdcData(XAdcPs *InstancePtr, u8 Channel); + +u16 XAdcPs_GetCalibCoefficient(XAdcPs *InstancePtr, u8 CoeffType); + +u16 XAdcPs_GetMinMaxMeasurement(XAdcPs *InstancePtr, u8 MeasurementType); + +void XAdcPs_SetAvg(XAdcPs *InstancePtr, u8 Average); +u8 XAdcPs_GetAvg(XAdcPs *InstancePtr); + +int XAdcPs_SetSingleChParams(XAdcPs *InstancePtr, + u8 Channel, + int IncreaseAcqCycles, + int IsEventMode, + int IsDifferentialMode); + + +void XAdcPs_SetAlarmEnables(XAdcPs *InstancePtr, u16 AlmEnableMask); +u16 XAdcPs_GetAlarmEnables(XAdcPs *InstancePtr); + +void XAdcPs_SetCalibEnables(XAdcPs *InstancePtr, u16 Calibration); +u16 XAdcPs_GetCalibEnables(XAdcPs *InstancePtr); + +void XAdcPs_SetSequencerMode(XAdcPs *InstancePtr, u8 SequencerMode); +u8 XAdcPs_GetSequencerMode(XAdcPs *InstancePtr); + +void XAdcPs_SetAdcClkDivisor(XAdcPs *InstancePtr, u8 Divisor); +u8 XAdcPs_GetAdcClkDivisor(XAdcPs *InstancePtr); + +int XAdcPs_SetSeqChEnables(XAdcPs *InstancePtr, u32 ChEnableMask); +u32 XAdcPs_GetSeqChEnables(XAdcPs *InstancePtr); + +int XAdcPs_SetSeqAvgEnables(XAdcPs *InstancePtr, u32 AvgEnableChMask); +u32 XAdcPs_GetSeqAvgEnables(XAdcPs *InstancePtr); + +int XAdcPs_SetSeqInputMode(XAdcPs *InstancePtr, u32 InputModeChMask); +u32 XAdcPs_GetSeqInputMode(XAdcPs *InstancePtr); + +int XAdcPs_SetSeqAcqTime(XAdcPs *InstancePtr, u32 AcqCyclesChMask); +u32 XAdcPs_GetSeqAcqTime(XAdcPs *InstancePtr); + +void XAdcPs_SetAlarmThreshold(XAdcPs *InstancePtr, u8 AlarmThrReg, u16 Value); +u16 XAdcPs_GetAlarmThreshold(XAdcPs *InstancePtr, u8 AlarmThrReg); + +void XAdcPs_EnableUserOverTemp(XAdcPs *InstancePtr); +void XAdcPs_DisableUserOverTemp(XAdcPs *InstancePtr); + +void XAdcPs_SetSequencerEvent(XAdcPs *InstancePtr, int IsEventMode); + +int XAdcPs_GetSamplingMode(XAdcPs *InstancePtr); + +void XAdcPs_SetMuxMode(XAdcPs *InstancePtr, int MuxMode, u8 Channel); + +void XAdcPs_SetPowerdownMode(XAdcPs *InstancePtr, u32 Mode); + +u32 XAdcPs_GetPowerdownMode(XAdcPs *InstancePtr); + +/** + * Functions in xadcps_selftest.c + */ +int XAdcPs_SelfTest(XAdcPs *InstancePtr); + +/** + * Functions in xadcps_intr.c + */ +void XAdcPs_IntrEnable(XAdcPs *InstancePtr, u32 Mask); +void XAdcPs_IntrDisable(XAdcPs *InstancePtr, u32 Mask); +u32 XAdcPs_IntrGetEnabled(XAdcPs *InstancePtr); + +u32 XAdcPs_IntrGetStatus(XAdcPs *InstancePtr); +void XAdcPs_IntrClear(XAdcPs *InstancePtr, u32 Mask); + + +#ifdef __cplusplus +} +#endif + +#endif /* End of protection macro. */ +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/xadcps_v2_3/src/xadcps_g.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/xadcps_v2_3/src/xadcps_g.c new file mode 100644 index 0000000..b2d7d60 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/xadcps_v2_3/src/xadcps_g.c @@ -0,0 +1,51 @@ + +/******************************************************************* +* +* CAUTION: This file is automatically generated by HSI. +* Version: 2019.1.3 +* DO NOT EDIT. +* +* Copyright (C) 2010-2023 Xilinx, Inc. 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 +*XILINX 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. +* +*Except as contained in this notice, the name of the Xilinx shall not be used +*in advertising or otherwise to promote the sale, use or other dealings in +*this Software without prior written authorization from Xilinx. +* + +* +* Description: Driver configuration +* +*******************************************************************/ + +#include "xparameters.h" +#include "xadcps.h" + +/* +* The configuration table for devices +*/ + +XAdcPs_Config XAdcPs_ConfigTable[XPAR_XADCPS_NUM_INSTANCES] = +{ + { + XPAR_PS7_XADC_0_DEVICE_ID, + XPAR_PS7_XADC_0_BASEADDR + } +}; + + diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/xadcps_v2_3/src/xadcps_hw.h b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/xadcps_v2_3/src/xadcps_hw.h new file mode 100644 index 0000000..dd51473 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/xadcps_v2_3/src/xadcps_hw.h @@ -0,0 +1,498 @@ +/****************************************************************************** +* +* Copyright (C) 2011 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xadcps_hw.h +* @addtogroup xadcps_v2_3 +* @{ +* +* This header file contains identifiers and basic driver functions (or +* macros) that can be used to access the XADC device through the Device +* Config Interface of the Zynq. +* +* +* Refer to the device specification for more information about this driver. +* +* @note None. +* +* +*
+*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- -----  -------- -----------------------------------------------------
+* 1.00a bss    12/22/11 First release based on the XPS/AXI xadc driver
+* 1.03a bss    11/01/13 Modified macros to use correct Register offsets
+*			CR#749687
+*
+* 
+* +*****************************************************************************/ +#ifndef XADCPS_HW_H /* Prevent circular inclusions */ +#define XADCPS_HW_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files ********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_io.h" + +/************************** Constant Definitions ****************************/ + + +/**@name Register offsets of XADC in the Device Config + * + * The following constants provide access to each of the registers of the + * XADC device. + * @{ + */ + +#define XADCPS_CFG_OFFSET 0x00 /**< Configuration Register */ +#define XADCPS_INT_STS_OFFSET 0x04 /**< Interrupt Status Register */ +#define XADCPS_INT_MASK_OFFSET 0x08 /**< Interrupt Mask Register */ +#define XADCPS_MSTS_OFFSET 0x0C /**< Misc status register */ +#define XADCPS_CMDFIFO_OFFSET 0x10 /**< Command FIFO Register */ +#define XADCPS_RDFIFO_OFFSET 0x14 /**< Read FIFO Register */ +#define XADCPS_MCTL_OFFSET 0x18 /**< Misc control register */ + +/* @} */ + + + + + +/** @name XADC Config Register Bit definitions + * @{ + */ +#define XADCPS_CFG_ENABLE_MASK 0x80000000 /**< Enable access from PS mask */ +#define XADCPS_CFG_CFIFOTH_MASK 0x00F00000 /**< Command FIFO Threshold mask */ +#define XADCPS_CFG_DFIFOTH_MASK 0x000F0000 /**< Data FIFO Threshold mask */ +#define XADCPS_CFG_WEDGE_MASK 0x00002000 /**< Write Edge Mask */ +#define XADCPS_CFG_REDGE_MASK 0x00001000 /**< Read Edge Mask */ +#define XADCPS_CFG_TCKRATE_MASK 0x00000300 /**< Clock freq control */ +#define XADCPS_CFG_IGAP_MASK 0x0000001F /**< Idle Gap between + * successive commands */ +/* @} */ + + +/** @name XADC Interrupt Status/Mask Register Bit definitions + * + * The definitions are same for the Interrupt Status Register and + * Interrupt Mask Register. They are defined only once. + * @{ + */ +#define XADCPS_INTX_ALL_MASK 0x000003FF /**< Alarm Signals Mask */ +#define XADCPS_INTX_CFIFO_LTH_MASK 0x00000200 /**< CMD FIFO less than threshold */ +#define XADCPS_INTX_DFIFO_GTH_MASK 0x00000100 /**< Data FIFO greater than threshold */ +#define XADCPS_INTX_OT_MASK 0x00000080 /**< Over temperature Alarm Status */ +#define XADCPS_INTX_ALM_ALL_MASK 0x0000007F /**< Alarm Signals Mask */ +#define XADCPS_INTX_ALM6_MASK 0x00000040 /**< Alarm 6 Mask */ +#define XADCPS_INTX_ALM5_MASK 0x00000020 /**< Alarm 5 Mask */ +#define XADCPS_INTX_ALM4_MASK 0x00000010 /**< Alarm 4 Mask */ +#define XADCPS_INTX_ALM3_MASK 0x00000008 /**< Alarm 3 Mask */ +#define XADCPS_INTX_ALM2_MASK 0x00000004 /**< Alarm 2 Mask */ +#define XADCPS_INTX_ALM1_MASK 0x00000002 /**< Alarm 1 Mask */ +#define XADCPS_INTX_ALM0_MASK 0x00000001 /**< Alarm 0 Mask */ + +/* @} */ + + +/** @name XADC Miscellaneous Register Bit definitions + * @{ + */ +#define XADCPS_MSTS_CFIFO_LVL_MASK 0x000F0000 /**< Command FIFO Level mask */ +#define XADCPS_MSTS_DFIFO_LVL_MASK 0x0000F000 /**< Data FIFO Level Mask */ +#define XADCPS_MSTS_CFIFOF_MASK 0x00000800 /**< Command FIFO Full Mask */ +#define XADCPS_MSTS_CFIFOE_MASK 0x00000400 /**< Command FIFO Empty Mask */ +#define XADCPS_MSTS_DFIFOF_MASK 0x00000200 /**< Data FIFO Full Mask */ +#define XADCPS_MSTS_DFIFOE_MASK 0x00000100 /**< Data FIFO Empty Mask */ +#define XADCPS_MSTS_OT_MASK 0x00000080 /**< Over Temperature Mask */ +#define XADCPS_MSTS_ALM_MASK 0x0000007F /**< Alarms Mask */ +/* @} */ + + +/** @name XADC Miscellaneous Control Register Bit definitions + * @{ + */ +#define XADCPS_MCTL_RESET_MASK 0x00000010 /**< Reset XADC */ +#define XADCPS_MCTL_FLUSH_MASK 0x00000001 /**< Flush the FIFOs */ +/* @} */ + + +/**@name Internal Register offsets of the XADC + * + * The following constants provide access to each of the internal registers of + * the XADC device. + * @{ + */ + +/* + * XADC Internal Channel Registers + */ +#define XADCPS_TEMP_OFFSET 0x00 /**< On-chip Temperature Reg */ +#define XADCPS_VCCINT_OFFSET 0x01 /**< On-chip VCCINT Data Reg */ +#define XADCPS_VCCAUX_OFFSET 0x02 /**< On-chip VCCAUX Data Reg */ +#define XADCPS_VPVN_OFFSET 0x03 /**< ADC out of VP/VN */ +#define XADCPS_VREFP_OFFSET 0x04 /**< On-chip VREFP Data Reg */ +#define XADCPS_VREFN_OFFSET 0x05 /**< On-chip VREFN Data Reg */ +#define XADCPS_VBRAM_OFFSET 0x06 /**< On-chip VBRAM , 7 Series */ +#define XADCPS_ADC_A_SUPPLY_CALIB_OFFSET 0x08 /**< ADC A Supply Offset Reg */ +#define XADCPS_ADC_A_OFFSET_CALIB_OFFSET 0x09 /**< ADC A Offset Data Reg */ +#define XADCPS_ADC_A_GAINERR_CALIB_OFFSET 0x0A /**< ADC A Gain Error Reg */ +#define XADCPS_VCCPINT_OFFSET 0x0D /**< On-chip VCCPINT Reg, Zynq */ +#define XADCPS_VCCPAUX_OFFSET 0x0E /**< On-chip VCCPAUX Reg, Zynq */ +#define XADCPS_VCCPDRO_OFFSET 0x0F /**< On-chip VCCPDRO Reg, Zynq */ + +/* + * XADC External Channel Registers + */ +#define XADCPS_AUX00_OFFSET 0x10 /**< ADC out of VAUXP0/VAUXN0 */ +#define XADCPS_AUX01_OFFSET 0x11 /**< ADC out of VAUXP1/VAUXN1 */ +#define XADCPS_AUX02_OFFSET 0x12 /**< ADC out of VAUXP2/VAUXN2 */ +#define XADCPS_AUX03_OFFSET 0x13 /**< ADC out of VAUXP3/VAUXN3 */ +#define XADCPS_AUX04_OFFSET 0x14 /**< ADC out of VAUXP4/VAUXN4 */ +#define XADCPS_AUX05_OFFSET 0x15 /**< ADC out of VAUXP5/VAUXN5 */ +#define XADCPS_AUX06_OFFSET 0x16 /**< ADC out of VAUXP6/VAUXN6 */ +#define XADCPS_AUX07_OFFSET 0x17 /**< ADC out of VAUXP7/VAUXN7 */ +#define XADCPS_AUX08_OFFSET 0x18 /**< ADC out of VAUXP8/VAUXN8 */ +#define XADCPS_AUX09_OFFSET 0x19 /**< ADC out of VAUXP9/VAUXN9 */ +#define XADCPS_AUX10_OFFSET 0x1A /**< ADC out of VAUXP10/VAUXN10 */ +#define XADCPS_AUX11_OFFSET 0x1B /**< ADC out of VAUXP11/VAUXN11 */ +#define XADCPS_AUX12_OFFSET 0x1C /**< ADC out of VAUXP12/VAUXN12 */ +#define XADCPS_AUX13_OFFSET 0x1D /**< ADC out of VAUXP13/VAUXN13 */ +#define XADCPS_AUX14_OFFSET 0x1E /**< ADC out of VAUXP14/VAUXN14 */ +#define XADCPS_AUX15_OFFSET 0x1F /**< ADC out of VAUXP15/VAUXN15 */ + +/* + * XADC Registers for Maximum/Minimum data captured for the + * on chip Temperature/VCCINT/VCCAUX data. + */ +#define XADCPS_MAX_TEMP_OFFSET 0x20 /**< Max Temperature Reg */ +#define XADCPS_MAX_VCCINT_OFFSET 0x21 /**< Max VCCINT Register */ +#define XADCPS_MAX_VCCAUX_OFFSET 0x22 /**< Max VCCAUX Register */ +#define XADCPS_MAX_VCCBRAM_OFFSET 0x23 /**< Max BRAM Register, 7 series */ +#define XADCPS_MIN_TEMP_OFFSET 0x24 /**< Min Temperature Reg */ +#define XADCPS_MIN_VCCINT_OFFSET 0x25 /**< Min VCCINT Register */ +#define XADCPS_MIN_VCCAUX_OFFSET 0x26 /**< Min VCCAUX Register */ +#define XADCPS_MIN_VCCBRAM_OFFSET 0x27 /**< Min BRAM Register, 7 series */ +#define XADCPS_MAX_VCCPINT_OFFSET 0x28 /**< Max VCCPINT Register, Zynq */ +#define XADCPS_MAX_VCCPAUX_OFFSET 0x29 /**< Max VCCPAUX Register, Zynq */ +#define XADCPS_MAX_VCCPDRO_OFFSET 0x2A /**< Max VCCPDRO Register, Zynq */ +#define XADCPS_MIN_VCCPINT_OFFSET 0x2C /**< Min VCCPINT Register, Zynq */ +#define XADCPS_MIN_VCCPAUX_OFFSET 0x2D /**< Min VCCPAUX Register, Zynq */ +#define XADCPS_MIN_VCCPDRO_OFFSET 0x2E /**< Min VCCPDRO Register,Zynq */ + /* Undefined 0x2F to 0x3E */ +#define XADCPS_FLAG_OFFSET 0x3F /**< Flag Register */ + +/* + * XADC Configuration Registers + */ +#define XADCPS_CFR0_OFFSET 0x40 /**< Configuration Register 0 */ +#define XADCPS_CFR1_OFFSET 0x41 /**< Configuration Register 1 */ +#define XADCPS_CFR2_OFFSET 0x42 /**< Configuration Register 2 */ + +/* Test Registers 0x43 to 0x47 */ + +/* + * XADC Sequence Registers + */ +#define XADCPS_SEQ00_OFFSET 0x48 /**< Seq Reg 00 Adc Channel Selection */ +#define XADCPS_SEQ01_OFFSET 0x49 /**< Seq Reg 01 Adc Channel Selection */ +#define XADCPS_SEQ02_OFFSET 0x4A /**< Seq Reg 02 Adc Average Enable */ +#define XADCPS_SEQ03_OFFSET 0x4B /**< Seq Reg 03 Adc Average Enable */ +#define XADCPS_SEQ04_OFFSET 0x4C /**< Seq Reg 04 Adc Input Mode Select */ +#define XADCPS_SEQ05_OFFSET 0x4D /**< Seq Reg 05 Adc Input Mode Select */ +#define XADCPS_SEQ06_OFFSET 0x4E /**< Seq Reg 06 Adc Acquisition Select */ +#define XADCPS_SEQ07_OFFSET 0x4F /**< Seq Reg 07 Adc Acquisition Select */ + +/* + * XADC Alarm Threshold/Limit Registers (ATR) + */ +#define XADCPS_ATR_TEMP_UPPER_OFFSET 0x50 /**< Temp Upper Alarm Register */ +#define XADCPS_ATR_VCCINT_UPPER_OFFSET 0x51 /**< VCCINT Upper Alarm Reg */ +#define XADCPS_ATR_VCCAUX_UPPER_OFFSET 0x52 /**< VCCAUX Upper Alarm Reg */ +#define XADCPS_ATR_OT_UPPER_OFFSET 0x53 /**< Over Temp Upper Alarm Reg */ +#define XADCPS_ATR_TEMP_LOWER_OFFSET 0x54 /**< Temp Lower Alarm Register */ +#define XADCPS_ATR_VCCINT_LOWER_OFFSET 0x55 /**< VCCINT Lower Alarm Reg */ +#define XADCPS_ATR_VCCAUX_LOWER_OFFSET 0x56 /**< VCCAUX Lower Alarm Reg */ +#define XADCPS_ATR_OT_LOWER_OFFSET 0x57 /**< Over Temp Lower Alarm Reg */ +#define XADCPS_ATR_VBRAM_UPPER_OFFSET 0x58 /**< VBRAM Upper Alarm, 7 series */ +#define XADCPS_ATR_VCCPINT_UPPER_OFFSET 0x59 /**< VCCPINT Upper Alarm, Zynq */ +#define XADCPS_ATR_VCCPAUX_UPPER_OFFSET 0x5A /**< VCCPAUX Upper Alarm, Zynq */ +#define XADCPS_ATR_VCCPDRO_UPPER_OFFSET 0x5B /**< VCCPDRO Upper Alarm, Zynq */ +#define XADCPS_ATR_VBRAM_LOWER_OFFSET 0x5C /**< VRBAM Lower Alarm, 7 Series */ +#define XADCPS_ATR_VCCPINT_LOWER_OFFSET 0x5D /**< VCCPINT Lower Alarm, Zynq */ +#define XADCPS_ATR_VCCPAUX_LOWER_OFFSET 0x5E /**< VCCPAUX Lower Alarm, Zynq */ +#define XADCPS_ATR_VCCPDRO_LOWER_OFFSET 0x5F /**< VCCPDRO Lower Alarm, Zynq */ + +/* Undefined 0x60 to 0x7F */ + +/*@}*/ + + + +/** + * @name Configuration Register 0 (CFR0) mask(s) + * @{ + */ +#define XADCPS_CFR0_CAL_AVG_MASK 0x8000 /**< Averaging enable Mask */ +#define XADCPS_CFR0_AVG_VALID_MASK 0x3000 /**< Averaging bit Mask */ +#define XADCPS_CFR0_AVG1_MASK 0x0000 /**< No Averaging */ +#define XADCPS_CFR0_AVG16_MASK 0x1000 /**< Average 16 samples */ +#define XADCPS_CFR0_AVG64_MASK 0x2000 /**< Average 64 samples */ +#define XADCPS_CFR0_AVG256_MASK 0x3000 /**< Average 256 samples */ +#define XADCPS_CFR0_AVG_SHIFT 12 /**< Averaging bits shift */ +#define XADCPS_CFR0_MUX_MASK 0x0800 /**< External Mask Enable */ +#define XADCPS_CFR0_DU_MASK 0x0400 /**< Bipolar/Unipolar mode */ +#define XADCPS_CFR0_EC_MASK 0x0200 /**< Event driven/ + * Continuous mode selection + */ +#define XADCPS_CFR0_ACQ_MASK 0x0100 /**< Add acquisition by 6 ADCCLK */ +#define XADCPS_CFR0_CHANNEL_MASK 0x001F /**< Channel number bit Mask */ + +/*@}*/ + +/** + * @name Configuration Register 1 (CFR1) mask(s) + * @{ + */ +#define XADCPS_CFR1_SEQ_VALID_MASK 0xF000 /**< Sequence bit Mask */ +#define XADCPS_CFR1_SEQ_SAFEMODE_MASK 0x0000 /**< Default Safe Mode */ +#define XADCPS_CFR1_SEQ_ONEPASS_MASK 0x1000 /**< Onepass through Seq */ +#define XADCPS_CFR1_SEQ_CONTINPASS_MASK 0x2000 /**< Continuous Cycling Seq */ +#define XADCPS_CFR1_SEQ_SINGCHAN_MASK 0x3000 /**< Single channel - No Seq */ +#define XADCPS_CFR1_SEQ_SIMUL_SAMPLING_MASK 0x4000 /**< Simulataneous Sampling Mask */ +#define XADCPS_CFR1_SEQ_INDEPENDENT_MASK 0x8000 /**< Independent Mode */ +#define XADCPS_CFR1_SEQ_SHIFT 12 /**< Sequence bit shift */ +#define XADCPS_CFR1_ALM_VCCPDRO_MASK 0x0800 /**< Alm 6 - VCCPDRO, Zynq */ +#define XADCPS_CFR1_ALM_VCCPAUX_MASK 0x0400 /**< Alm 5 - VCCPAUX, Zynq */ +#define XADCPS_CFR1_ALM_VCCPINT_MASK 0x0200 /**< Alm 4 - VCCPINT, Zynq */ +#define XADCPS_CFR1_ALM_VBRAM_MASK 0x0100 /**< Alm 3 - VBRAM, 7 series */ +#define XADCPS_CFR1_CAL_VALID_MASK 0x00F0 /**< Valid Calibration Mask */ +#define XADCPS_CFR1_CAL_PS_GAIN_OFFSET_MASK 0x0080 /**< Calibration 3 -Power + Supply Gain/Offset + Enable */ +#define XADCPS_CFR1_CAL_PS_OFFSET_MASK 0x0040 /**< Calibration 2 -Power + Supply Offset Enable */ +#define XADCPS_CFR1_CAL_ADC_GAIN_OFFSET_MASK 0x0020 /**< Calibration 1 -ADC Gain + Offset Enable */ +#define XADCPS_CFR1_CAL_ADC_OFFSET_MASK 0x0010 /**< Calibration 0 -ADC Offset + Enable */ +#define XADCPS_CFR1_CAL_DISABLE_MASK 0x0000 /**< No Calibration */ +#define XADCPS_CFR1_ALM_ALL_MASK 0x0F0F /**< Mask for all alarms */ +#define XADCPS_CFR1_ALM_VCCAUX_MASK 0x0008 /**< Alarm 2 - VCCAUX Enable */ +#define XADCPS_CFR1_ALM_VCCINT_MASK 0x0004 /**< Alarm 1 - VCCINT Enable */ +#define XADCPS_CFR1_ALM_TEMP_MASK 0x0002 /**< Alarm 0 - Temperature */ +#define XADCPS_CFR1_OT_MASK 0x0001 /**< Over Temperature Enable */ + +/*@}*/ + +/** + * @name Configuration Register 2 (CFR2) mask(s) + * @{ + */ +#define XADCPS_CFR2_CD_VALID_MASK 0xFF00 /** +* +* MODIFICATION HISTORY: +* +* Ver Who Date Changes +* ----- ----- -------- ----------------------------------------------------- +* 1.00a ssb 12/22/11 First release based on the XPS/AXI xadc driver +* +* +* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xadcps.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + + +/****************************************************************************/ +/** +* +* This function enables the specified interrupts in the device. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param Mask is the bit-mask of the interrupts to be enabled. +* Bit positions of 1 will be enabled. Bit positions of 0 will +* keep the previous setting. This mask is formed by OR'ing +* XADCPS_INTX_* bits defined in xadcps_hw.h. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XAdcPs_IntrEnable(XAdcPs *InstancePtr, u32 Mask) +{ + u32 RegValue; + + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Disable the specified interrupts in the IPIER. + */ + RegValue = XAdcPs_ReadReg(InstancePtr->Config.BaseAddress, + XADCPS_INT_MASK_OFFSET); + RegValue &= ~(Mask & XADCPS_INTX_ALL_MASK); + XAdcPs_WriteReg(InstancePtr->Config.BaseAddress, + XADCPS_INT_MASK_OFFSET, + RegValue); +} + + +/****************************************************************************/ +/** +* +* This function disables the specified interrupts in the device. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param Mask is the bit-mask of the interrupts to be disabled. +* Bit positions of 1 will be disabled. Bit positions of 0 will +* keep the previous setting. This mask is formed by OR'ing +* XADCPS_INTX_* bits defined in xadcps_hw.h. +* +* @return None. +* +* @note None +* +*****************************************************************************/ +void XAdcPs_IntrDisable(XAdcPs *InstancePtr, u32 Mask) +{ + u32 RegValue; + + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Enable the specified interrupts in the IPIER. + */ + RegValue = XAdcPs_ReadReg(InstancePtr->Config.BaseAddress, + XADCPS_INT_MASK_OFFSET); + RegValue |= (Mask & XADCPS_INTX_ALL_MASK); + XAdcPs_WriteReg(InstancePtr->Config.BaseAddress, + XADCPS_INT_MASK_OFFSET, + RegValue); +} +/****************************************************************************/ +/** +* +* This function returns the enabled interrupts read from the Interrupt Mask +* Register (IPIER). Use the XADCPS_IPIXR_* constants defined in xadcps_hw.h to +* interpret the returned value. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @return A 32-bit value representing the contents of the I. +* +* @note None. +* +*****************************************************************************/ +u32 XAdcPs_IntrGetEnabled(XAdcPs *InstancePtr) +{ + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Return the value read from the Interrupt Enable Register. + */ + return (~ XAdcPs_ReadReg(InstancePtr->Config.BaseAddress, + XADCPS_INT_MASK_OFFSET) & XADCPS_INTX_ALL_MASK); +} + +/****************************************************************************/ +/** +* +* This function returns the interrupt status read from Interrupt Status +* Register(IPISR). Use the XADCPS_IPIXR_* constants defined in xadcps_hw.h +* to interpret the returned value. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @return A 32-bit value representing the contents of the IPISR. +* +* @note The device must be configured at hardware build time to include +* interrupt component for this function to work. +* +*****************************************************************************/ +u32 XAdcPs_IntrGetStatus(XAdcPs *InstancePtr) +{ + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Return the value read from the Interrupt Status register. + */ + return XAdcPs_ReadReg(InstancePtr->Config.BaseAddress, + XADCPS_INT_STS_OFFSET) & XADCPS_INTX_ALL_MASK; +} + +/****************************************************************************/ +/** +* +* This function clears the specified interrupts in the Interrupt Status +* Register (IPISR). +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param Mask is the bit-mask of the interrupts to be cleared. +* Bit positions of 1 will be cleared. Bit positions of 0 will not +* change the previous interrupt status. This mask is formed by +* OR'ing XADCPS_IPIXR_* bits which are defined in xadcps_hw.h. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XAdcPs_IntrClear(XAdcPs *InstancePtr, u32 Mask) +{ + u32 RegValue; + + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Clear the specified interrupts in the Interrupt Status register. + */ + RegValue = XAdcPs_ReadReg(InstancePtr->Config.BaseAddress, + XADCPS_INT_STS_OFFSET); + RegValue &= (Mask & XADCPS_INTX_ALL_MASK); + XAdcPs_WriteReg(InstancePtr->Config.BaseAddress, XADCPS_INT_STS_OFFSET, + RegValue); + +} +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/xadcps_v2_3/src/xadcps_selftest.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/xadcps_v2_3/src/xadcps_selftest.c new file mode 100644 index 0000000..2d2a7f2 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/xadcps_v2_3/src/xadcps_selftest.c @@ -0,0 +1,137 @@ +/****************************************************************************** +* +* Copyright (C) 2011 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xadcps_selftest.c +* @addtogroup xadcps_v2_3 +* @{ +* +* This file contains a diagnostic self test function for the XAdcPs driver. +* The self test function does a simple read/write test of the Alarm Threshold +* Register. +* +* See xadcps.h for more information. +* +* @note None. +* +*
+*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- -----  -------- -----------------------------------------------------
+* 1.00a ssb    12/22/11 First release based on the XPS/AXI xadc driver
+*
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ + +#include "xadcps.h" + +/************************** Constant Definitions ****************************/ + +/* + * The following constant defines the test value to be written + * to the Alarm Threshold Register + */ +#define XADCPS_ATR_TEST_VALUE 0x55 + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Variable Definitions ****************************/ + +/************************** Function Prototypes *****************************/ + +/*****************************************************************************/ +/** +* +* Run a self-test on the driver/device. The test +* - Resets the device, +* - Writes a value into the Alarm Threshold register and reads it back +* for comparison. +* - Resets the device again. +* +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @return +* - XST_SUCCESS if the value read from the Alarm Threshold +* register is the same as the value written. +* - XST_FAILURE Otherwise +* +* @note This is a destructive test in that resets of the device are +* performed. Refer to the device specification for the +* device status after the reset operation. +* +******************************************************************************/ +int XAdcPs_SelfTest(XAdcPs *InstancePtr) +{ + int Status; + u32 RegValue; + + /* + * Assert the argument + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + + /* + * Reset the device to get it back to its default state + */ + XAdcPs_Reset(InstancePtr); + + /* + * Write a value into the Alarm Threshold registers, read it back, and + * do the comparison + */ + XAdcPs_SetAlarmThreshold(InstancePtr, XADCPS_ATR_VCCINT_UPPER, + XADCPS_ATR_TEST_VALUE); + RegValue = XAdcPs_GetAlarmThreshold(InstancePtr, XADCPS_ATR_VCCINT_UPPER); + + if (RegValue == XADCPS_ATR_TEST_VALUE) { + Status = XST_SUCCESS; + } else { + Status = XST_FAILURE; + } + + /* + * Reset the device again to its default state. + */ + XAdcPs_Reset(InstancePtr); + /* + * Return the test result. + */ + return Status; +} +/** @} */ diff --git a/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/xadcps_v2_3/src/xadcps_sinit.c b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/xadcps_v2_3/src/xadcps_sinit.c new file mode 100644 index 0000000..5572976 --- /dev/null +++ b/datalink814_ge/bsp/ps7_cortexa9_0/libsrc/xadcps_v2_3/src/xadcps_sinit.c @@ -0,0 +1,99 @@ +/****************************************************************************** +* +* Copyright (C) 2011 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xadcps_sinit.c +* @addtogroup xadcps_v2_3 +* @{ +* +* This file contains the implementation of the XAdcPs driver's static +* initialization functionality. +* +* @note None. +* +*
+*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- -----  -------- -----------------------------------------------------
+* 1.00a ssb    12/22/11 First release based on the XPS/AXI XADC driver
+*
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xparameters.h" +#include "xadcps.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ +extern XAdcPs_Config XAdcPs_ConfigTable[]; + +/*****************************************************************************/ +/** +* +* This function looks up the device configuration based on the unique device ID. +* The table XAdcPs_ConfigTable contains the configuration info for each device +* in the system. +* +* @param DeviceId contains the ID of the device for which the +* device configuration pointer is to be returned. +* +* @return +* - A pointer to the configuration found. +* - NULL if the specified device ID was not found. +* +* @note None. +* +******************************************************************************/ +XAdcPs_Config *XAdcPs_LookupConfig(u16 DeviceId) +{ + XAdcPs_Config *CfgPtr = NULL; + u32 Index; + + for (Index=0; Index < 1; Index++) { + if (XAdcPs_ConfigTable[Index].DeviceId == DeviceId) { + CfgPtr = &XAdcPs_ConfigTable[Index]; + break; + } + } + + return CfgPtr; +} +/** @} */ diff --git a/datalink814_ge/bsp/system.mss b/datalink814_ge/bsp/system.mss new file mode 100644 index 0000000..88489da --- /dev/null +++ b/datalink814_ge/bsp/system.mss @@ -0,0 +1,261 @@ + + PARAMETER VERSION = 2.2.0 + + +BEGIN OS + PARAMETER OS_NAME = standalone + PARAMETER OS_VER = 7.0 + PARAMETER PROC_INSTANCE = ps7_cortexa9_0 + PARAMETER stdin = ps7_uart_1 + PARAMETER stdout = ps7_uart_1 +END + + +BEGIN PROCESSOR + PARAMETER DRIVER_NAME = cpu_cortexa9 + PARAMETER DRIVER_VER = 2.7 + PARAMETER HW_INSTANCE = ps7_cortexa9_0 +END + + +BEGIN DRIVER + PARAMETER DRIVER_NAME = frame_uart + PARAMETER DRIVER_VER = 1.0 + PARAMETER HW_INSTANCE = Frame_Uart_0 +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = gpio + PARAMETER DRIVER_VER = 4.4 + PARAMETER HW_INSTANCE = config_gpio +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = generic + PARAMETER DRIVER_VER = 2.0 + PARAMETER HW_INSTANCE = jesd_jesd204_phy +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = generic + PARAMETER DRIVER_VER = 2.0 + PARAMETER HW_INSTANCE = jesd_jesd204_rx +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = generic + PARAMETER DRIVER_VER = 2.0 + PARAMETER HW_INSTANCE = jesd_jesd204_tx +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = bram + PARAMETER DRIVER_VER = 4.3 + PARAMETER HW_INSTANCE = mpc_bram_interface_mpc_bram_ctrl +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = bram + PARAMETER DRIVER_VER = 4.3 + PARAMETER HW_INSTANCE = phy_data_interface_ant_info_bram_ctrl +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = bram + PARAMETER DRIVER_VER = 4.3 + PARAMETER HW_INSTANCE = phy_data_interface_rx_frame_bram_ctrl +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = bram + PARAMETER DRIVER_VER = 4.3 + PARAMETER HW_INSTANCE = phy_data_interface_tx_frame_bram_ctrl +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = generic + PARAMETER DRIVER_VER = 2.0 + PARAMETER HW_INSTANCE = ps7_afi_0 +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = generic + PARAMETER DRIVER_VER = 2.0 + PARAMETER HW_INSTANCE = ps7_afi_1 +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = generic + PARAMETER DRIVER_VER = 2.0 + PARAMETER HW_INSTANCE = ps7_afi_2 +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = generic + PARAMETER DRIVER_VER = 2.0 + PARAMETER HW_INSTANCE = ps7_afi_3 +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = coresightps_dcc + PARAMETER DRIVER_VER = 1.5 + PARAMETER HW_INSTANCE = ps7_coresight_comp_0 +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = ddrps + PARAMETER DRIVER_VER = 1.0 + PARAMETER HW_INSTANCE = ps7_ddr_0 +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = generic + PARAMETER DRIVER_VER = 2.0 + PARAMETER HW_INSTANCE = ps7_ddrc_0 +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = devcfg + PARAMETER DRIVER_VER = 3.5 + PARAMETER HW_INSTANCE = ps7_dev_cfg_0 +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = dmaps + PARAMETER DRIVER_VER = 2.4 + PARAMETER HW_INSTANCE = ps7_dma_ns +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = dmaps + PARAMETER DRIVER_VER = 2.4 + PARAMETER HW_INSTANCE = ps7_dma_s +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = generic + PARAMETER DRIVER_VER = 2.0 + PARAMETER HW_INSTANCE = ps7_globaltimer_0 +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = gpiops + PARAMETER DRIVER_VER = 3.5 + PARAMETER HW_INSTANCE = ps7_gpio_0 +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = generic + PARAMETER DRIVER_VER = 2.0 + PARAMETER HW_INSTANCE = ps7_gpv_0 +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = generic + PARAMETER DRIVER_VER = 2.0 + PARAMETER HW_INSTANCE = ps7_intc_dist_0 +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = generic + PARAMETER DRIVER_VER = 2.0 + PARAMETER HW_INSTANCE = ps7_iop_bus_config_0 +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = generic + PARAMETER DRIVER_VER = 2.0 + PARAMETER HW_INSTANCE = ps7_l2cachec_0 +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = generic + PARAMETER DRIVER_VER = 2.0 + PARAMETER HW_INSTANCE = ps7_ocmc_0 +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = generic + PARAMETER DRIVER_VER = 2.0 + PARAMETER HW_INSTANCE = ps7_pl310_0 +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = generic + PARAMETER DRIVER_VER = 2.0 + PARAMETER HW_INSTANCE = ps7_pmu_0 +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = qspips + PARAMETER DRIVER_VER = 3.6 + PARAMETER HW_INSTANCE = ps7_qspi_0 +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = generic + PARAMETER DRIVER_VER = 2.0 + PARAMETER HW_INSTANCE = ps7_qspi_linear_0 +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = generic + PARAMETER DRIVER_VER = 2.0 + PARAMETER HW_INSTANCE = ps7_ram_0 +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = generic + PARAMETER DRIVER_VER = 2.0 + PARAMETER HW_INSTANCE = ps7_ram_1 +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = generic + PARAMETER DRIVER_VER = 2.0 + PARAMETER HW_INSTANCE = ps7_scuc_0 +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = scugic + PARAMETER DRIVER_VER = 4.0 + PARAMETER HW_INSTANCE = ps7_scugic_0 +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = scutimer + PARAMETER DRIVER_VER = 2.1 + PARAMETER HW_INSTANCE = ps7_scutimer_0 +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = scuwdt + PARAMETER DRIVER_VER = 2.1 + PARAMETER HW_INSTANCE = ps7_scuwdt_0 +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = generic + PARAMETER DRIVER_VER = 2.0 + PARAMETER HW_INSTANCE = ps7_slcr_0 +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = spips + PARAMETER DRIVER_VER = 3.2 + PARAMETER HW_INSTANCE = ps7_spi_0 +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = uartps + PARAMETER DRIVER_VER = 3.7 + PARAMETER HW_INSTANCE = ps7_uart_1 +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = xadcps + PARAMETER DRIVER_VER = 2.3 + PARAMETER HW_INSTANCE = ps7_xadc_0 +END + + diff --git a/datalink814_ge/build/Xilinx.spec b/datalink814_ge/build/Xilinx.spec new file mode 100644 index 0000000..8eea377 --- /dev/null +++ b/datalink814_ge/build/Xilinx.spec @@ -0,0 +1,2 @@ +*startfile: +crti%O%s crtbegin%O%s diff --git a/datalink814_ge/build/makefile b/datalink814_ge/build/makefile new file mode 100644 index 0000000..c199bfe --- /dev/null +++ b/datalink814_ge/build/makefile @@ -0,0 +1,77 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +-include ../makefile.init + +CC := /tools/Xilinx/SDK/2019.1/gnu/aarch32/lin/gcc-arm-none-eabi/bin/arm-none-eabi-gcc +XILIN_A9_PRE := /tools/Xilinx/SDK/2019.1/bin/a9-linaro-pre-build-step +RM := rm -rf + +# All of the sources participating in the build are defined here +-include sources.mk +-include src/util/subdir.mk +-include src/time_ctrl/subdir.mk +-include src/phy_ctrl/subdir.mk +-include src/mpc/subdir.mk +-include src/linklayer/geometry/subdir.mk +-include src/linklayer/subdir.mk +-include src/hardware/mykonos/subdir.mk +-include src/hardware/subdir.mk +-include src/config/subdir.mk +-include src/bit_array/subdir.mk +-include src/subdir.mk +-include subdir.mk +-include objects.mk + +ifneq ($(MAKECMDGOALS),clean) +ifneq ($(strip $(S_UPPER_DEPS)),) +-include $(S_UPPER_DEPS) +endif +ifneq ($(strip $(C_DEPS)),) +-include $(C_DEPS) +endif +endif + +-include ../makefile.defs + +# Add inputs and outputs from these tool invocations to the build variables +ELFSIZE += \ +datalink814_ge.elf.size \ + + +# All Target +all: pre-build main-build + +# Main-build Target +main-build: datalink814_ge.elf secondary-outputs + +# Tool invocations +datalink814_ge.elf: $(OBJS) ../src/lscript.ld $(USER_OBJS) + @echo 'Building target: $@' + @echo 'Invoking: ARM v7 gcc linker' + $(CC) -mcpu=cortex-a9 -mfpu=vfpv3 -mfloat-abi=hard -Wl,-build-id=none -specs=Xilinx.spec -Wl,-T -Wl,../src/lscript.ld -L../bsp/ps7_cortexa9_0/lib -o "datalink814_ge.elf" $(OBJS) $(USER_OBJS) $(LIBS) + @echo 'Finished building target: $@' + @echo ' ' + +datalink814_ge.elf.size: datalink814_ge.elf + @echo 'Invoking: ARM v7 Print Size' + arm-none-eabi-size datalink814_ge.elf |tee "datalink814_ge.elf.size" + @echo 'Finished building: $@' + @echo ' ' + +# Other Targets +clean: + -$(RM) $(EXECUTABLES)$(OBJS)$(S_UPPER_DEPS)$(C_DEPS)$(ELFSIZE) datalink814_ge.elf + -@echo ' ' + +pre-build: + -$(XILIN_A9_PRE) + -@echo ' ' + +secondary-outputs: $(ELFSIZE) + +.PHONY: all clean dependents +.SECONDARY: main-build pre-build + +-include ../makefile.targets diff --git a/datalink814_ge/build/objects.mk b/datalink814_ge/build/objects.mk new file mode 100644 index 0000000..5d23511 --- /dev/null +++ b/datalink814_ge/build/objects.mk @@ -0,0 +1,8 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +USER_OBJS := + +LIBS := -lm -Wl,--start-group,-lxil,-lgcc,-lc,--end-group + diff --git a/datalink814_ge/build/sources.mk b/datalink814_ge/build/sources.mk new file mode 100644 index 0000000..1efb5fe --- /dev/null +++ b/datalink814_ge/build/sources.mk @@ -0,0 +1,30 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +LD_SRCS := +OBJ_SRCS := +S_SRCS := +C_SRCS := +S_UPPER_SRCS := +O_SRCS := +EXECUTABLES := +OBJS := +S_UPPER_DEPS := +C_DEPS := +ELFSIZE := + +# Every subdirectory with source files must be described here +SUBDIRS := \ +src/bit_array \ +src \ +src/config \ +src/hardware \ +src/hardware/mykonos \ +src/linklayer \ +src/linklayer/geometry \ +src/mpc \ +src/phy_ctrl \ +src/time_ctrl \ +src/util \ + diff --git a/datalink814_ge/build/src/bit_array/subdir.mk b/datalink814_ge/build/src/bit_array/subdir.mk new file mode 100644 index 0000000..d3fcac6 --- /dev/null +++ b/datalink814_ge/build/src/bit_array/subdir.mk @@ -0,0 +1,24 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +# Add inputs and outputs from these tool invocations to the build variables +C_SRCS += \ +../src/bit_array/bit_array.c + +OBJS += \ +./src/bit_array/bit_array.o + +C_DEPS += \ +./src/bit_array/bit_array.d + + +# Each subdirectory must supply rules for building sources it contributes +src/bit_array/%.o: ../src/bit_array/%.c + @echo 'Building file: $<' + @echo 'Invoking: ARM v7 gcc compiler' + $(CC) -Wall -O0 -g3 -c -fmessage-length=0 -MT"$@" -mcpu=cortex-a9 -mfpu=vfpv3 -mfloat-abi=hard -I../bsp/ps7_cortexa9_0/include -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + + diff --git a/datalink814_ge/build/src/config/subdir.mk b/datalink814_ge/build/src/config/subdir.mk new file mode 100644 index 0000000..9b6b485 --- /dev/null +++ b/datalink814_ge/build/src/config/subdir.mk @@ -0,0 +1,24 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +# Add inputs and outputs from these tool invocations to the build variables +C_SRCS += \ +../src/config/platform.c + +OBJS += \ +./src/config/platform.o + +C_DEPS += \ +./src/config/platform.d + + +# Each subdirectory must supply rules for building sources it contributes +src/config/%.o: ../src/config/%.c + @echo 'Building file: $<' + @echo 'Invoking: ARM v7 gcc compiler' + $(CC) -Wall -O0 -g3 -c -fmessage-length=0 -MT"$@" -mcpu=cortex-a9 -mfpu=vfpv3 -mfloat-abi=hard -I../bsp/ps7_cortexa9_0/include -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + + diff --git a/datalink814_ge/build/src/hardware/mykonos/subdir.mk b/datalink814_ge/build/src/hardware/mykonos/subdir.mk new file mode 100644 index 0000000..0ce09bc --- /dev/null +++ b/datalink814_ge/build/src/hardware/mykonos/subdir.mk @@ -0,0 +1,39 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +# Add inputs and outputs from these tool invocations to the build variables +C_SRCS += \ +../src/hardware/mykonos/Mykonos_M3.c \ +../src/hardware/mykonos/ad9528.c \ +../src/hardware/mykonos/mykonos.c \ +../src/hardware/mykonos/mykonosMmap.c \ +../src/hardware/mykonos/mykonos_gpio.c \ +../src/hardware/mykonos/mykonos_user.c + +OBJS += \ +./src/hardware/mykonos/Mykonos_M3.o \ +./src/hardware/mykonos/ad9528.o \ +./src/hardware/mykonos/mykonos.o \ +./src/hardware/mykonos/mykonosMmap.o \ +./src/hardware/mykonos/mykonos_gpio.o \ +./src/hardware/mykonos/mykonos_user.o + +C_DEPS += \ +./src/hardware/mykonos/Mykonos_M3.d \ +./src/hardware/mykonos/ad9528.d \ +./src/hardware/mykonos/mykonos.d \ +./src/hardware/mykonos/mykonosMmap.d \ +./src/hardware/mykonos/mykonos_gpio.d \ +./src/hardware/mykonos/mykonos_user.d + + +# Each subdirectory must supply rules for building sources it contributes +src/hardware/mykonos/%.o: ../src/hardware/mykonos/%.c + @echo 'Building file: $<' + @echo 'Invoking: ARM v7 gcc compiler' + $(CC) -Wall -O0 -g3 -c -fmessage-length=0 -MT"$@" -mcpu=cortex-a9 -mfpu=vfpv3 -mfloat-abi=hard -I../bsp/ps7_cortexa9_0/include -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + + diff --git a/datalink814_ge/build/src/hardware/subdir.mk b/datalink814_ge/build/src/hardware/subdir.mk new file mode 100644 index 0000000..4b1b578 --- /dev/null +++ b/datalink814_ge/build/src/hardware/subdir.mk @@ -0,0 +1,36 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +# Add inputs and outputs from these tool invocations to the build variables +C_SRCS += \ +../src/hardware/common.c \ +../src/hardware/headless.c \ +../src/hardware/myk_ad9528init.c \ +../src/hardware/myk_init.c \ +../src/hardware/platform_drivers.c + +OBJS += \ +./src/hardware/common.o \ +./src/hardware/headless.o \ +./src/hardware/myk_ad9528init.o \ +./src/hardware/myk_init.o \ +./src/hardware/platform_drivers.o + +C_DEPS += \ +./src/hardware/common.d \ +./src/hardware/headless.d \ +./src/hardware/myk_ad9528init.d \ +./src/hardware/myk_init.d \ +./src/hardware/platform_drivers.d + + +# Each subdirectory must supply rules for building sources it contributes +src/hardware/%.o: ../src/hardware/%.c + @echo 'Building file: $<' + @echo 'Invoking: ARM v7 gcc compiler' + $(CC) -Wall -O0 -g3 -c -fmessage-length=0 -MT"$@" -mcpu=cortex-a9 -mfpu=vfpv3 -mfloat-abi=hard -I../bsp/ps7_cortexa9_0/include -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + + diff --git a/datalink814_ge/build/src/linklayer/geometry/subdir.mk b/datalink814_ge/build/src/linklayer/geometry/subdir.mk new file mode 100644 index 0000000..f710555 --- /dev/null +++ b/datalink814_ge/build/src/linklayer/geometry/subdir.mk @@ -0,0 +1,30 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +# Add inputs and outputs from these tool invocations to the build variables +C_SRCS += \ +../src/linklayer/geometry/coord.c \ +../src/linklayer/geometry/eulerangles.c \ +../src/linklayer/geometry/quaternion.c + +OBJS += \ +./src/linklayer/geometry/coord.o \ +./src/linklayer/geometry/eulerangles.o \ +./src/linklayer/geometry/quaternion.o + +C_DEPS += \ +./src/linklayer/geometry/coord.d \ +./src/linklayer/geometry/eulerangles.d \ +./src/linklayer/geometry/quaternion.d + + +# Each subdirectory must supply rules for building sources it contributes +src/linklayer/geometry/%.o: ../src/linklayer/geometry/%.c + @echo 'Building file: $<' + @echo 'Invoking: ARM v7 gcc compiler' + $(CC) -Wall -O0 -g3 -c -fmessage-length=0 -MT"$@" -mcpu=cortex-a9 -mfpu=vfpv3 -mfloat-abi=hard -I../bsp/ps7_cortexa9_0/include -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + + diff --git a/datalink814_ge/build/src/linklayer/subdir.mk b/datalink814_ge/build/src/linklayer/subdir.mk new file mode 100644 index 0000000..c367bc5 --- /dev/null +++ b/datalink814_ge/build/src/linklayer/subdir.mk @@ -0,0 +1,45 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +# Add inputs and outputs from these tool invocations to the build variables +C_SRCS += \ +../src/linklayer/framing.c \ +../src/linklayer/linklayer814.c \ +../src/linklayer/linklayer_routine.c \ +../src/linklayer/net_mgmt.c \ +../src/linklayer/net_scan.c \ +../src/linklayer/net_service.c \ +../src/linklayer/node_list.c \ +../src/linklayer/time_sync.c + +OBJS += \ +./src/linklayer/framing.o \ +./src/linklayer/linklayer814.o \ +./src/linklayer/linklayer_routine.o \ +./src/linklayer/net_mgmt.o \ +./src/linklayer/net_scan.o \ +./src/linklayer/net_service.o \ +./src/linklayer/node_list.o \ +./src/linklayer/time_sync.o + +C_DEPS += \ +./src/linklayer/framing.d \ +./src/linklayer/linklayer814.d \ +./src/linklayer/linklayer_routine.d \ +./src/linklayer/net_mgmt.d \ +./src/linklayer/net_scan.d \ +./src/linklayer/net_service.d \ +./src/linklayer/node_list.d \ +./src/linklayer/time_sync.d + + +# Each subdirectory must supply rules for building sources it contributes +src/linklayer/%.o: ../src/linklayer/%.c + @echo 'Building file: $<' + @echo 'Invoking: ARM v7 gcc compiler' + $(CC) -Wall -O0 -g3 -c -fmessage-length=0 -MT"$@" -mcpu=cortex-a9 -mfpu=vfpv3 -mfloat-abi=hard -I../bsp/ps7_cortexa9_0/include -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + + diff --git a/datalink814_ge/build/src/mpc/subdir.mk b/datalink814_ge/build/src/mpc/subdir.mk new file mode 100644 index 0000000..1c9cfb1 --- /dev/null +++ b/datalink814_ge/build/src/mpc/subdir.mk @@ -0,0 +1,24 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +# Add inputs and outputs from these tool invocations to the build variables +C_SRCS += \ +../src/mpc/mpc_ctrl.c + +OBJS += \ +./src/mpc/mpc_ctrl.o + +C_DEPS += \ +./src/mpc/mpc_ctrl.d + + +# Each subdirectory must supply rules for building sources it contributes +src/mpc/%.o: ../src/mpc/%.c + @echo 'Building file: $<' + @echo 'Invoking: ARM v7 gcc compiler' + $(CC) -Wall -O0 -g3 -c -fmessage-length=0 -MT"$@" -mcpu=cortex-a9 -mfpu=vfpv3 -mfloat-abi=hard -I../bsp/ps7_cortexa9_0/include -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + + diff --git a/datalink814_ge/build/src/phy_ctrl/subdir.mk b/datalink814_ge/build/src/phy_ctrl/subdir.mk new file mode 100644 index 0000000..de854ec --- /dev/null +++ b/datalink814_ge/build/src/phy_ctrl/subdir.mk @@ -0,0 +1,27 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +# Add inputs and outputs from these tool invocations to the build variables +C_SRCS += \ +../src/phy_ctrl/antenna.c \ +../src/phy_ctrl/phy_ctrl.c + +OBJS += \ +./src/phy_ctrl/antenna.o \ +./src/phy_ctrl/phy_ctrl.o + +C_DEPS += \ +./src/phy_ctrl/antenna.d \ +./src/phy_ctrl/phy_ctrl.d + + +# Each subdirectory must supply rules for building sources it contributes +src/phy_ctrl/%.o: ../src/phy_ctrl/%.c + @echo 'Building file: $<' + @echo 'Invoking: ARM v7 gcc compiler' + $(CC) -Wall -O0 -g3 -c -fmessage-length=0 -MT"$@" -mcpu=cortex-a9 -mfpu=vfpv3 -mfloat-abi=hard -I../bsp/ps7_cortexa9_0/include -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + + diff --git a/datalink814_ge/build/src/subdir.mk b/datalink814_ge/build/src/subdir.mk new file mode 100644 index 0000000..925a07c --- /dev/null +++ b/datalink814_ge/build/src/subdir.mk @@ -0,0 +1,30 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +# Add inputs and outputs from these tool invocations to the build variables +LD_SRCS += \ +../src/lscript.ld + +C_SRCS += \ +../src/common.c \ +../src/main.c + +OBJS += \ +./src/common.o \ +./src/main.o + +C_DEPS += \ +./src/common.d \ +./src/main.d + + +# Each subdirectory must supply rules for building sources it contributes +src/%.o: ../src/%.c + @echo 'Building file: $<' + @echo 'Invoking: ARM v7 gcc compiler' + $(CC) -Wall -O0 -g3 -c -fmessage-length=0 -MT"$@" -mcpu=cortex-a9 -mfpu=vfpv3 -mfloat-abi=hard -I../bsp/ps7_cortexa9_0/include -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + + diff --git a/datalink814_ge/build/src/time_ctrl/subdir.mk b/datalink814_ge/build/src/time_ctrl/subdir.mk new file mode 100644 index 0000000..498c8b0 --- /dev/null +++ b/datalink814_ge/build/src/time_ctrl/subdir.mk @@ -0,0 +1,24 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +# Add inputs and outputs from these tool invocations to the build variables +C_SRCS += \ +../src/time_ctrl/time_ctrl.c + +OBJS += \ +./src/time_ctrl/time_ctrl.o + +C_DEPS += \ +./src/time_ctrl/time_ctrl.d + + +# Each subdirectory must supply rules for building sources it contributes +src/time_ctrl/%.o: ../src/time_ctrl/%.c + @echo 'Building file: $<' + @echo 'Invoking: ARM v7 gcc compiler' + $(CC) -Wall -O0 -g3 -c -fmessage-length=0 -MT"$@" -mcpu=cortex-a9 -mfpu=vfpv3 -mfloat-abi=hard -I../bsp/ps7_cortexa9_0/include -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + + diff --git a/datalink814_ge/build/src/util/subdir.mk b/datalink814_ge/build/src/util/subdir.mk new file mode 100644 index 0000000..8c9529a --- /dev/null +++ b/datalink814_ge/build/src/util/subdir.mk @@ -0,0 +1,27 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +# Add inputs and outputs from these tool invocations to the build variables +C_SRCS += \ +../src/util/crc.c \ +../src/util/util.c + +OBJS += \ +./src/util/crc.o \ +./src/util/util.o + +C_DEPS += \ +./src/util/crc.d \ +./src/util/util.d + + +# Each subdirectory must supply rules for building sources it contributes +src/util/%.o: ../src/util/%.c + @echo 'Building file: $<' + @echo 'Invoking: ARM v7 gcc compiler' + $(CC) -Wall -O0 -g3 -c -fmessage-length=0 -MT"$@" -mcpu=cortex-a9 -mfpu=vfpv3 -mfloat-abi=hard -I../bsp/ps7_cortexa9_0/include -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + + diff --git a/datalink814_ge/src/Xilinx.spec b/datalink814_ge/src/Xilinx.spec new file mode 100644 index 0000000..9c27dca --- /dev/null +++ b/datalink814_ge/src/Xilinx.spec @@ -0,0 +1,2 @@ +*startfile: +crti%O%s crtbegin%O%s diff --git a/datalink814_ge/src/bit_array/bar.h b/datalink814_ge/src/bit_array/bar.h new file mode 100644 index 0000000..2dc3b1c --- /dev/null +++ b/datalink814_ge/src/bit_array/bar.h @@ -0,0 +1,148 @@ +/* + bar.h + project: bit array C library + url: https://github.com/noporpoise/BitArray/ + maintainer: Isaac Turner + license: Public Domain, no warranty + date: Sept 2014 +*/ + +// shorten the names of some of the bit_array functions to be more +// like the str* function names. The prefix "bar" is used to represent +// bit_array and is analogous to "str". + +#ifndef BAR_HEADER_SEEN +#define BAR_HEADER_SEEN + +#include "bit_array.h" + +#define bar BIT_ARRAY + +#define barcreate bit_array_create +#define bardestroy bit_array_free +#define baralloc bit_array_alloc +#define barfree bit_array_dealloc +#define barlen bit_array_length + +#define barsize bit_array_resize +#define barcap bit_array_ensure_size + +// These five are MACROs +#define barget bit_array_get +#define barset bit_array_set +#define barclr bit_array_clear +#define barflip bit_array_toggle +#define barmake bit_array_assign + +/* Functions instead of macros bars* => s for safe */ +#define barsget bit_array_get_bit +#define barsset bit_array_set_bit +#define barsclr bit_array_clear_bit +#define barsflip bit_array_toggle_bit +#define barsmake bit_array_assign_bit + +/* "resize" functions barr*: automatically enlarge array if needed */ +#define barrget bit_array_rget +#define barrset bit_array_rset +#define barrclr bit_array_rclear +#define barrflip bit_array_rtoggle +#define barrmake bit_array_rassign + +#define barsetn bit_array_set_bits +#define barclrn bit_array_clear_bits +#define barflipn bit_array_toggle_bits + +#define barsetr bit_array_set_region +#define barclrr bit_array_clear_region +#define barflipr bit_array_toggle_region + +#define barfill bit_array_set_all +#define barzero bit_array_clear_all +#define bartogl bit_array_toggle_all + +/* gw "get word" */ +#define bargw64 bit_array_get_word64 +#define bargw32 bit_array_get_word32 +#define bargw16 bit_array_get_word16 +#define bargw8 bit_array_get_word8 +#define bargwn bit_array_get_wordn + +/* sw "set word" */ +#define barsw64 bit_array_set_word64 +#define barsw32 bit_array_set_word32 +#define barsw16 bit_array_set_word16 +#define barswn bit_array_set_wordn + +#define barncpy bit_array_copy +#define barcpy bit_array_copy_all +#define bardup bit_array_clone + +#define barpopc bit_array_num_bits_set +#define barzeros bit_array_num_bits_cleared +#define bardist bit_array_hamming_distance +#define barparity bit_array_parity + +#define barfns bit_array_find_next_set_bit +#define barfps bit_array_find_prev_set_bit +#define barffs bit_array_find_first_set_bit +#define barfls bit_array_find_last_set_bit + +#define barfnz bit_array_find_next_clear_bit +#define barfpz bit_array_find_prev_clear_bit +#define barffz bit_array_find_first_clear_bit +#define barflz bit_array_find_last_clear_bit + +#define barsort bit_array_sort_bits +#define barsortr bit_array_sort_bits_rev + +#define barand bit_array_and +#define baror bit_array_or +#define barxor bit_array_xor +#define barnot bit_array_not + +#define barcmp bit_array_cmp +#define barcmpbe bit_array_cmp_big_endian +#define barcmpw bit_array_cmp_words +#define barcmp64 bit_array_cmp_uint64 + +#define barshr bit_array_shift_right +#define barshl bit_array_shift_left +#define bareshl bit_array_shift_left_extend + +#define barcycr bit_array_cycle_right +#define barcycl bit_array_cycle_left + +#define barmix bit_array_interleave + +#define barrev bit_array_reverse +#define barrevr bit_array_reverse_region + +#define bar2num bit_array_as_num + +/* Add/sub/mult/div a bit array with: */ +/* _i unsigned integer, _si shifted integer, _sb shifted bitarray */ +#define baraddi bit_array_add_uint64 +#define baraddsi bit_array_add_word +#define baraddsb bit_array_add_words +#define barsubi bit_array_sub_uint64 +#define barsubsi bit_array_sub_word +#define barsubsb bit_array_sub_words +#define barmuli bit_array_mul_uint64 +#define bardivi bit_array_div_uint64 + +/* arguments are both bit arrays */ +#define baradd bit_array_add +#define barsub bit_array_subtract +#define barmul bit_array_multiply +#define bardiv bit_array_divide + +#define barsave bit_array_save +#define barload bit_array_load + +#define barhash bit_array_hash + +#define barrand bit_array_random +#define barshfl bit_array_shuffle +#define barperm bit_array_next_permutation + +#endif /* BAR_HEADER_SEEN */ diff --git a/datalink814_ge/src/bit_array/bit_array.c b/datalink814_ge/src/bit_array/bit_array.c new file mode 100644 index 0000000..835781d --- /dev/null +++ b/datalink814_ge/src/bit_array/bit_array.c @@ -0,0 +1,3045 @@ +/* + bit_array.c + project: bit array C library + url: https://github.com/noporpoise/BitArray/ + maintainer: Isaac Turner + license: Public Domain, no warranty + date: Aug 2014 +*/ + +// 64 bit words +// Array length can be zero +// Unused top bits must be zero + +#include +#include +#include +#include // ULONG_MAX +#include // memset() +#include +#include + +#include "bit_array.h" +#include "bit_macros.h" + +// +// Tables of constants +// + +// byte reverse look up table +static const word_t reverse_table[256] = +{ + 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, + 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0, + 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, + 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, + 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, + 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4, + 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, + 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC, + 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, + 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2, + 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, + 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA, + 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, + 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6, + 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, + 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE, + 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, + 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1, + 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, + 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9, + 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, + 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5, + 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, + 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD, + 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, + 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3, + 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, + 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB, + 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, + 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7, + 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, + 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF, +}; + +// Morton table for interleaving bytes +static const word_t morton_table0[256] = +{ + 0x0000, 0x0001, 0x0004, 0x0005, 0x0010, 0x0011, 0x0014, 0x0015, + 0x0040, 0x0041, 0x0044, 0x0045, 0x0050, 0x0051, 0x0054, 0x0055, + 0x0100, 0x0101, 0x0104, 0x0105, 0x0110, 0x0111, 0x0114, 0x0115, + 0x0140, 0x0141, 0x0144, 0x0145, 0x0150, 0x0151, 0x0154, 0x0155, + 0x0400, 0x0401, 0x0404, 0x0405, 0x0410, 0x0411, 0x0414, 0x0415, + 0x0440, 0x0441, 0x0444, 0x0445, 0x0450, 0x0451, 0x0454, 0x0455, + 0x0500, 0x0501, 0x0504, 0x0505, 0x0510, 0x0511, 0x0514, 0x0515, + 0x0540, 0x0541, 0x0544, 0x0545, 0x0550, 0x0551, 0x0554, 0x0555, + 0x1000, 0x1001, 0x1004, 0x1005, 0x1010, 0x1011, 0x1014, 0x1015, + 0x1040, 0x1041, 0x1044, 0x1045, 0x1050, 0x1051, 0x1054, 0x1055, + 0x1100, 0x1101, 0x1104, 0x1105, 0x1110, 0x1111, 0x1114, 0x1115, + 0x1140, 0x1141, 0x1144, 0x1145, 0x1150, 0x1151, 0x1154, 0x1155, + 0x1400, 0x1401, 0x1404, 0x1405, 0x1410, 0x1411, 0x1414, 0x1415, + 0x1440, 0x1441, 0x1444, 0x1445, 0x1450, 0x1451, 0x1454, 0x1455, + 0x1500, 0x1501, 0x1504, 0x1505, 0x1510, 0x1511, 0x1514, 0x1515, + 0x1540, 0x1541, 0x1544, 0x1545, 0x1550, 0x1551, 0x1554, 0x1555, + 0x4000, 0x4001, 0x4004, 0x4005, 0x4010, 0x4011, 0x4014, 0x4015, + 0x4040, 0x4041, 0x4044, 0x4045, 0x4050, 0x4051, 0x4054, 0x4055, + 0x4100, 0x4101, 0x4104, 0x4105, 0x4110, 0x4111, 0x4114, 0x4115, + 0x4140, 0x4141, 0x4144, 0x4145, 0x4150, 0x4151, 0x4154, 0x4155, + 0x4400, 0x4401, 0x4404, 0x4405, 0x4410, 0x4411, 0x4414, 0x4415, + 0x4440, 0x4441, 0x4444, 0x4445, 0x4450, 0x4451, 0x4454, 0x4455, + 0x4500, 0x4501, 0x4504, 0x4505, 0x4510, 0x4511, 0x4514, 0x4515, + 0x4540, 0x4541, 0x4544, 0x4545, 0x4550, 0x4551, 0x4554, 0x4555, + 0x5000, 0x5001, 0x5004, 0x5005, 0x5010, 0x5011, 0x5014, 0x5015, + 0x5040, 0x5041, 0x5044, 0x5045, 0x5050, 0x5051, 0x5054, 0x5055, + 0x5100, 0x5101, 0x5104, 0x5105, 0x5110, 0x5111, 0x5114, 0x5115, + 0x5140, 0x5141, 0x5144, 0x5145, 0x5150, 0x5151, 0x5154, 0x5155, + 0x5400, 0x5401, 0x5404, 0x5405, 0x5410, 0x5411, 0x5414, 0x5415, + 0x5440, 0x5441, 0x5444, 0x5445, 0x5450, 0x5451, 0x5454, 0x5455, + 0x5500, 0x5501, 0x5504, 0x5505, 0x5510, 0x5511, 0x5514, 0x5515, + 0x5540, 0x5541, 0x5544, 0x5545, 0x5550, 0x5551, 0x5554, 0x5555, +}; + +// Morton table for interleaving bytes, shifted left 1 bit +static const word_t morton_table1[256] = +{ + 0x0000, 0x0002, 0x0008, 0x000A, 0x0020, 0x0022, 0x0028, 0x002A, + 0x0080, 0x0082, 0x0088, 0x008A, 0x00A0, 0x00A2, 0x00A8, 0x00AA, + 0x0200, 0x0202, 0x0208, 0x020A, 0x0220, 0x0222, 0x0228, 0x022A, + 0x0280, 0x0282, 0x0288, 0x028A, 0x02A0, 0x02A2, 0x02A8, 0x02AA, + 0x0800, 0x0802, 0x0808, 0x080A, 0x0820, 0x0822, 0x0828, 0x082A, + 0x0880, 0x0882, 0x0888, 0x088A, 0x08A0, 0x08A2, 0x08A8, 0x08AA, + 0x0A00, 0x0A02, 0x0A08, 0x0A0A, 0x0A20, 0x0A22, 0x0A28, 0x0A2A, + 0x0A80, 0x0A82, 0x0A88, 0x0A8A, 0x0AA0, 0x0AA2, 0x0AA8, 0x0AAA, + 0x2000, 0x2002, 0x2008, 0x200A, 0x2020, 0x2022, 0x2028, 0x202A, + 0x2080, 0x2082, 0x2088, 0x208A, 0x20A0, 0x20A2, 0x20A8, 0x20AA, + 0x2200, 0x2202, 0x2208, 0x220A, 0x2220, 0x2222, 0x2228, 0x222A, + 0x2280, 0x2282, 0x2288, 0x228A, 0x22A0, 0x22A2, 0x22A8, 0x22AA, + 0x2800, 0x2802, 0x2808, 0x280A, 0x2820, 0x2822, 0x2828, 0x282A, + 0x2880, 0x2882, 0x2888, 0x288A, 0x28A0, 0x28A2, 0x28A8, 0x28AA, + 0x2A00, 0x2A02, 0x2A08, 0x2A0A, 0x2A20, 0x2A22, 0x2A28, 0x2A2A, + 0x2A80, 0x2A82, 0x2A88, 0x2A8A, 0x2AA0, 0x2AA2, 0x2AA8, 0x2AAA, + 0x8000, 0x8002, 0x8008, 0x800A, 0x8020, 0x8022, 0x8028, 0x802A, + 0x8080, 0x8082, 0x8088, 0x808A, 0x80A0, 0x80A2, 0x80A8, 0x80AA, + 0x8200, 0x8202, 0x8208, 0x820A, 0x8220, 0x8222, 0x8228, 0x822A, + 0x8280, 0x8282, 0x8288, 0x828A, 0x82A0, 0x82A2, 0x82A8, 0x82AA, + 0x8800, 0x8802, 0x8808, 0x880A, 0x8820, 0x8822, 0x8828, 0x882A, + 0x8880, 0x8882, 0x8888, 0x888A, 0x88A0, 0x88A2, 0x88A8, 0x88AA, + 0x8A00, 0x8A02, 0x8A08, 0x8A0A, 0x8A20, 0x8A22, 0x8A28, 0x8A2A, + 0x8A80, 0x8A82, 0x8A88, 0x8A8A, 0x8AA0, 0x8AA2, 0x8AA8, 0x8AAA, + 0xA000, 0xA002, 0xA008, 0xA00A, 0xA020, 0xA022, 0xA028, 0xA02A, + 0xA080, 0xA082, 0xA088, 0xA08A, 0xA0A0, 0xA0A2, 0xA0A8, 0xA0AA, + 0xA200, 0xA202, 0xA208, 0xA20A, 0xA220, 0xA222, 0xA228, 0xA22A, + 0xA280, 0xA282, 0xA288, 0xA28A, 0xA2A0, 0xA2A2, 0xA2A8, 0xA2AA, + 0xA800, 0xA802, 0xA808, 0xA80A, 0xA820, 0xA822, 0xA828, 0xA82A, + 0xA880, 0xA882, 0xA888, 0xA88A, 0xA8A0, 0xA8A2, 0xA8A8, 0xA8AA, + 0xAA00, 0xAA02, 0xAA08, 0xAA0A, 0xAA20, 0xAA22, 0xAA28, 0xAA2A, + 0xAA80, 0xAA82, 0xAA88, 0xAA8A, 0xAAA0, 0xAAA2, 0xAAA8, 0xAAAA, +}; + +// +// Macros +// + +// WORD_SIZE is the number of bits per word +// sizeof gives size in bytes (8 bits per byte) +#define WORD_SIZE 64 +// #define WORD_SIZE (sizeof(word_t) * 8) + +// POPCOUNT is number of bits set + +#if defined(_WIN32) + +// See http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel +static word_t __inline windows_popcount(word_t w) +{ + w = w - ((w >> 1) & (word_t)~(word_t)0/3); + w = (w & (word_t)~(word_t)0/15*3) + ((w >> 2) & (word_t)~(word_t)0/15*3); + w = (w + (w >> 4)) & (word_t)~(word_t)0/255*15; + c = (word_t)(w * ((word_t)~(word_t)0/255)) >> (sizeof(word_t) - 1) * 8; +} + +static word_t __inline windows_parity(word_t w) +{ + w ^= w >> 1; + w ^= w >> 2; + w = (w & 0x1111111111111111UL) * 0x1111111111111111UL; + return (w >> 60) & 1; +} + +#define POPCOUNT(x) windows_popcountl(x) +#define PARITY(x) windows_parity(x) +#else +#define POPCOUNT(x) (unsigned)__builtin_popcountll(x) +#define PARITY(x) (unsigned)__builtin_parityll(x) +#endif + +#define MIN(a, b) (((a) <= (b)) ? (a) : (b)) +#define MAX(a, b) (((a) >= (b)) ? (a) : (b)) + +// Make this a power of two +#define INIT_CAPACITY_WORDS 2 + +// word of all 1s +#define WORD_MAX (~(word_t)0) + +#define SET_REGION(arr,start,len) _set_region((arr),(start),(len),FILL_REGION) +#define CLEAR_REGION(arr,start,len) _set_region((arr),(start),(len),ZERO_REGION) +#define TOGGLE_REGION(arr,start,len) _set_region((arr),(start),(len),SWAP_REGION) + +// +// Common internal functions +// + +#define bits_in_top_word(nbits) ((nbits) ? bitset64_idx((nbits) - 1) + 1 : 0) + +// Mostly used for debugging +static inline void _print_word(word_t word, FILE* out) +{ + word_offset_t i; + for(i = 0; i < WORD_SIZE; i++) + { + fprintf(out, "%c", ((word >> i) & (word_t)0x1) == 0 ? '0' : '1'); + } +} + +// prints right to left +static inline char* _word_to_str(word_t word, char str[WORD_SIZE+1]) + __attribute__((unused)); + +static inline char* _word_to_str(word_t word, char str[WORD_SIZE+1]) +{ + word_offset_t i; + for(i = 0; i < WORD_SIZE; i++) + { + str[WORD_SIZE-i-1] = ((word >> i) & (word_t)0x1) == 0 ? '0' : '1'; + } + str[WORD_SIZE] = '\0'; + return str; +} + +// Used in debugging +#ifdef DEBUG + #define DEBUG_PRINT(...) {printf("[%s:%i] ", __FILE__, __LINE__); printf(__VA_ARGS__);} + #define DEBUG_VALIDATE(a) validate_bitarr((a), __FILE__, __LINE__) +#else + #define DEBUG_PRINT(...) + #define DEBUG_VALIDATE(a) +#endif + +void validate_bitarr(BIT_ARRAY *arr, const char *file, int lineno) +{ + // Check top word is masked + word_addr_t tw = arr->num_of_words == 0 ? 0 : arr->num_of_words - 1; + bit_index_t top_bits = bits_in_top_word(arr->num_of_bits); + int err = 0; + + if(arr->words[tw] > bitmask64(top_bits)) + { + _print_word(arr->words[tw], stderr); + fprintf(stderr, "\n[%s:%i] Expected %i bits in top word[%i]\n", + file, lineno, (int)top_bits, (int)tw); + err = 1; + } + + // Check num of words is correct + word_addr_t num_words = roundup_bits2words64(arr->num_of_bits); + if(num_words != arr->num_of_words) + { + fprintf(stderr, "\n[%s:%i] num of words wrong " + "[bits: %i, word: %i, actual words: %i]\n", file, lineno, + (int)arr->num_of_bits, (int)num_words, (int)arr->num_of_words); + err = 1; + } + + if(err) abort(); +} + +// Reverse a word +static inline word_t _reverse_word(word_t word) +{ + word_t reverse = (reverse_table[(word) & 0xff] << 56) | + (reverse_table[(word >> 8) & 0xff] << 48) | + (reverse_table[(word >> 16) & 0xff] << 40) | + (reverse_table[(word >> 24) & 0xff] << 32) | + (reverse_table[(word >> 32) & 0xff] << 24) | + (reverse_table[(word >> 40) & 0xff] << 16) | + (reverse_table[(word >> 48) & 0xff] << 8) | + (reverse_table[(word >> 56) & 0xff]); + + return reverse; +} + +static inline void _mask_top_word(BIT_ARRAY* bitarr) +{ + // Mask top word + word_addr_t num_of_words = MAX(1, bitarr->num_of_words); + word_offset_t bits_active = bits_in_top_word(bitarr->num_of_bits); + bitarr->words[num_of_words-1] &= bitmask64(bits_active); +} + +// +// Get and set words (internal use only -- no bounds checking) +// + +static inline word_t _get_word(const BIT_ARRAY* bitarr, bit_index_t start) +{ + word_addr_t word_index = bitset64_wrd(start); + word_offset_t word_offset = bitset64_idx(start); + + word_t result = bitarr->words[word_index] >> word_offset; + + word_offset_t bits_taken = WORD_SIZE - word_offset; + + // word_offset is now the number of bits we need from the next word + // Check the next word has at least some bits + if(word_offset > 0 && start + bits_taken < bitarr->num_of_bits) + { + result |= bitarr->words[word_index+1] << (WORD_SIZE - word_offset); + } + + return result; +} + +// Set 64 bits from a particular start position +// Doesn't extend bit array +static inline void _set_word(BIT_ARRAY* bitarr, bit_index_t start, word_t word) +{ + word_addr_t word_index = bitset64_wrd(start); + word_offset_t word_offset = bitset64_idx(start); + + if(word_offset == 0) + { + bitarr->words[word_index] = word; + } + else + { + bitarr->words[word_index] + = (word << word_offset) | + (bitarr->words[word_index] & bitmask64(word_offset)); + + if(word_index+1 < bitarr->num_of_words) + { + bitarr->words[word_index+1] + = (word >> (WORD_SIZE - word_offset)) | + (bitarr->words[word_index+1] & (WORD_MAX << word_offset)); + } + } + + // Mask top word + _mask_top_word(bitarr); + DEBUG_VALIDATE(bitarr); +} + +static inline void _set_byte(BIT_ARRAY *bitarr, bit_index_t start, uint8_t byte) +{ + word_t w = _get_word(bitarr, start); + _set_word(bitarr, start, (w & ~(word_t)0xff) | byte); +} + +// 4 bits +static inline void _set_nibble(BIT_ARRAY *bitarr, bit_index_t start, + uint8_t nibble) +{ + word_t w = _get_word(bitarr, start); + _set_word(bitarr, start, (w & ~(word_t)0xf) | nibble); +} + +// Wrap around +static inline word_t _get_word_cyclic(const BIT_ARRAY* bitarr, bit_index_t start) +{ + word_t word = _get_word(bitarr, start); + + bit_index_t bits_taken = bitarr->num_of_bits - start; + + if(bits_taken < WORD_SIZE) + { + word |= (bitarr->words[0] << bits_taken); + + if(bitarr->num_of_bits < (bit_index_t)WORD_SIZE) + { + // Mask word to prevent repetition of the same bits + word = word & bitmask64(bitarr->num_of_bits); + } + } + + return word; +} + +// Wrap around +static inline void _set_word_cyclic(BIT_ARRAY* bitarr, + bit_index_t start, word_t word) +{ + _set_word(bitarr, start, word); + + bit_index_t bits_set = bitarr->num_of_bits - start; + + if(bits_set < WORD_SIZE && start > 0) + { + word >>= bits_set; + + // Prevent overwriting the bits we've just set + // by setting 'start' as the upper bound for the number of bits to write + word_offset_t bits_remaining = MIN(WORD_SIZE - bits_set, start); + word_t mask = bitmask64(bits_remaining); + + bitarr->words[0] = bitmask_merge(word, bitarr->words[0], mask); + } +} + +// +// Fill a region (internal use only) +// + +// FillAction is fill with 0 or 1 or toggle +typedef enum {ZERO_REGION, FILL_REGION, SWAP_REGION} FillAction; + +static inline void _set_region(BIT_ARRAY* bitarr, bit_index_t start, + bit_index_t length, FillAction action) +{ + if(length == 0) return; + + word_addr_t first_word = bitset64_wrd(start); + word_addr_t last_word = bitset64_wrd(start+length-1); + word_offset_t foffset = bitset64_idx(start); + word_offset_t loffset = bitset64_idx(start+length-1); + + if(first_word == last_word) + { + word_t mask = bitmask64(length) << foffset; + + switch(action) + { + case ZERO_REGION: bitarr->words[first_word] &= ~mask; break; + case FILL_REGION: bitarr->words[first_word] |= mask; break; + case SWAP_REGION: bitarr->words[first_word] ^= mask; break; + } + } + else + { + // Set first word + switch(action) + { + case ZERO_REGION: bitarr->words[first_word] &= bitmask64(foffset); break; + case FILL_REGION: bitarr->words[first_word] |= ~bitmask64(foffset); break; + case SWAP_REGION: bitarr->words[first_word] ^= ~bitmask64(foffset); break; + } + + word_addr_t i; + + // Set whole words + switch(action) + { + case ZERO_REGION: + for(i = first_word + 1; i < last_word; i++) + bitarr->words[i] = (word_t)0; + break; + case FILL_REGION: + for(i = first_word + 1; i < last_word; i++) + bitarr->words[i] = WORD_MAX; + break; + case SWAP_REGION: + for(i = first_word + 1; i < last_word; i++) + bitarr->words[i] ^= WORD_MAX; + break; + } + + // Set last word + switch(action) + { + case ZERO_REGION: bitarr->words[last_word] &= ~bitmask64(loffset+1); break; + case FILL_REGION: bitarr->words[last_word] |= bitmask64(loffset+1); break; + case SWAP_REGION: bitarr->words[last_word] ^= bitmask64(loffset+1); break; + } + } +} + + + +// +// Constructor +// + +// If cannot allocate memory, set errno to ENOMEM, return NULL +BIT_ARRAY* bit_array_alloc(BIT_ARRAY* bitarr, bit_index_t nbits) +{ + bitarr->num_of_bits = nbits; + bitarr->num_of_words = roundup_bits2words64(nbits); + bitarr->capacity_in_words = MAX(8, roundup2pow(bitarr->num_of_words)); + bitarr->words = (word_t*)calloc(bitarr->capacity_in_words, sizeof(word_t)); + if(bitarr->words == NULL) { + return NULL; + } + return bitarr; +} + +void bit_array_dealloc(BIT_ARRAY* bitarr) +{ + free(bitarr->words); + memset(bitarr, 0, sizeof(BIT_ARRAY)); +} + +// If cannot allocate memory, set errno to ENOMEM, return NULL +BIT_ARRAY* bit_array_create(bit_index_t nbits) +{ + BIT_ARRAY* bitarr = (BIT_ARRAY*)malloc(sizeof(BIT_ARRAY)); + + // error if could not allocate enough memory + if(bitarr == NULL || bit_array_alloc(bitarr, nbits) == NULL) + { + if(bitarr != NULL) free(bitarr); + return NULL; + } + + DEBUG_PRINT("Creating BIT_ARRAY (bits: %lu; allocated words: %lu; " + "using words: %lu; WORD_SIZE: %i)\n", + (unsigned long)nbits, (unsigned long)bitarr->capacity_in_words, + (unsigned long)roundup_bits2words64(nbits), (int)WORD_SIZE); + + DEBUG_VALIDATE(bitarr); + + return bitarr; +} + +// +// Destructor +// +void bit_array_free(BIT_ARRAY* bitarr) +{ + if(bitarr->words != NULL) + free(bitarr->words); + + free(bitarr); +} + +bit_index_t bit_array_length(const BIT_ARRAY* bit_arr) +{ + return bit_arr->num_of_bits; +} + +// Change the size of a bit array. Enlarging an array will add zeros +// to the end of it. Returns 1 on success, 0 on failure (e.g. not enough memory) +char bit_array_resize(BIT_ARRAY* bitarr, bit_index_t new_num_of_bits) +{ + word_addr_t old_num_of_words = bitarr->num_of_words; + word_addr_t new_num_of_words = roundup_bits2words64(new_num_of_bits); + + bitarr->num_of_bits = new_num_of_bits; + bitarr->num_of_words = new_num_of_words; + + DEBUG_PRINT("Resize: old_num_of_words: %i; new_num_of_words: %i capacity: %i\n", + (int)old_num_of_words, (int)new_num_of_words, + (int)bitarr->capacity_in_words); + + if(new_num_of_words > bitarr->capacity_in_words) + { + // Need to change the amount of memory used + word_addr_t old_capacity_in_words = bitarr->capacity_in_words; + size_t old_capacity_in_bytes = old_capacity_in_words * sizeof(word_t); + + bitarr->capacity_in_words = roundup2pow(new_num_of_words); + bitarr->capacity_in_words = MAX(8, bitarr->capacity_in_words); + + size_t new_capacity_in_bytes = bitarr->capacity_in_words * sizeof(word_t); + bitarr->words = (word_t*)realloc(bitarr->words, new_capacity_in_bytes); + + if(bitarr->words == NULL) + { + // error - could not allocate enough memory + perror("resize realloc"); + return 0; + } + + // Need to zero new memory + size_t num_bytes_to_zero = new_capacity_in_bytes - old_capacity_in_bytes; + memset(bitarr->words + old_capacity_in_words, 0, num_bytes_to_zero); + + DEBUG_PRINT("zeroing from word %i for %i bytes\n", (int)old_capacity_in_words, + (int)num_bytes_to_zero); + } + else if(new_num_of_words < old_num_of_words) + { + // Shrunk -- need to zero old memory + size_t num_bytes_to_zero = (old_num_of_words - new_num_of_words)*sizeof(word_t); + + memset(bitarr->words + new_num_of_words, 0, num_bytes_to_zero); + } + + // Mask top word + _mask_top_word(bitarr); + DEBUG_VALIDATE(bitarr); + return 1; +} + +void bit_array_resize_critical(BIT_ARRAY* bitarr, bit_index_t num_of_bits) +{ + bit_index_t old_num_of_bits = bitarr->num_of_bits; + + if(!bit_array_resize(bitarr, num_of_bits)) + { + fprintf(stderr, "Ran out of memory resizing [%lu -> %lu]", + (unsigned long)old_num_of_bits, (unsigned long)num_of_bits); + abort(); + } +} + +// If bitarr length < num_bits, resizes to num_bits +char bit_array_ensure_size(BIT_ARRAY* bitarr, bit_index_t ensure_num_of_bits) +{ + if(bitarr->num_of_bits < ensure_num_of_bits) + { + return bit_array_resize(bitarr, ensure_num_of_bits); + } + + return 1; +} + +void bit_array_ensure_size_critical(BIT_ARRAY* bitarr, bit_index_t num_of_bits) +{ + if(num_of_bits > bitarr->num_of_bits) + { + bit_array_resize_critical(bitarr, num_of_bits); + } +} + +static inline +void _bit_array_ensure_nwords(BIT_ARRAY* bitarr, word_addr_t nwords, + const char *file, int lineno, const char *func) +{ + size_t newmem, oldmem; + if(bitarr->capacity_in_words < nwords) { + oldmem = bitarr->capacity_in_words * sizeof(word_t); + bitarr->capacity_in_words = roundup2pow(nwords); + newmem = bitarr->capacity_in_words * sizeof(word_t); + bitarr->words = (word_t*)realloc(bitarr->words, newmem); + + if(bitarr->words == NULL) { + fprintf(stderr, "[%s:%i:%s()] Ran out of memory resizing [%zu -> %zu]", + file, lineno, func, oldmem, newmem); + abort(); + } + + DEBUG_PRINT("Ensure nwords realloc %zu -> %zu\n", oldmem, newmem); + } +} + + +// +// Get, set, clear, assign and toggle individual bits +// + +// Get the value of a bit (returns 0 or 1) +char bit_array_get_bit(const BIT_ARRAY* bitarr, bit_index_t b) +{ + assert(b < bitarr->num_of_bits); + return bit_array_get(bitarr, b); +} + +// set a bit (to 1) at position b +void bit_array_set_bit(BIT_ARRAY* bitarr, bit_index_t b) +{ + assert(b < bitarr->num_of_bits); + bit_array_set(bitarr,b); + DEBUG_VALIDATE(bitarr); +} + +// clear a bit (to 0) at position b +void bit_array_clear_bit(BIT_ARRAY* bitarr, bit_index_t b) +{ + assert(b < bitarr->num_of_bits); + bit_array_clear(bitarr, b); + DEBUG_VALIDATE(bitarr); +} + +// If bit is 0 -> 1, if bit is 1 -> 0. AKA 'flip' +void bit_array_toggle_bit(BIT_ARRAY* bitarr, bit_index_t b) +{ + assert(b < bitarr->num_of_bits); + bit_array_toggle(bitarr, b); + DEBUG_VALIDATE(bitarr); +} + +// If char c != 0, set bit; otherwise clear bit +void bit_array_assign_bit(BIT_ARRAY* bitarr, bit_index_t b, char c) +{ + assert(b < bitarr->num_of_bits); + bit_array_assign(bitarr, b, c ? 1 : 0); + DEBUG_VALIDATE(bitarr); +} + +// +// Get, set etc with resize +// + +// Get the value of a bit (returns 0 or 1) +char bit_array_rget(BIT_ARRAY* bitarr, bit_index_t b) +{ + bit_array_ensure_size_critical(bitarr, b+1); + return bit_array_get(bitarr, b); +} + +// set a bit (to 1) at position b +void bit_array_rset(BIT_ARRAY* bitarr, bit_index_t b) +{ + bit_array_ensure_size_critical(bitarr, b+1); + bit_array_set(bitarr,b); + DEBUG_VALIDATE(bitarr); +} + +// clear a bit (to 0) at position b +void bit_array_rclear(BIT_ARRAY* bitarr, bit_index_t b) +{ + bit_array_ensure_size_critical(bitarr, b+1); + bit_array_clear(bitarr, b); + DEBUG_VALIDATE(bitarr); +} + +// If bit is 0 -> 1, if bit is 1 -> 0. AKA 'flip' +void bit_array_rtoggle(BIT_ARRAY* bitarr, bit_index_t b) +{ + bit_array_ensure_size_critical(bitarr, b+1); + bit_array_toggle(bitarr, b); + DEBUG_VALIDATE(bitarr); +} + +// If char c != 0, set bit; otherwise clear bit +void bit_array_rassign(BIT_ARRAY* bitarr, bit_index_t b, char c) +{ + bit_array_ensure_size_critical(bitarr, b+1); + bit_array_assign(bitarr, b, c ? 1 : 0); + DEBUG_VALIDATE(bitarr); +} + +// +// Set, clear and toggle several bits at once +// + +// Set multiple bits at once. +// e.g. set bits 1, 20 & 31: bit_array_set_bits(bitarr, 3, 1,20,31); +void bit_array_set_bits(BIT_ARRAY* bitarr, size_t n, ...) +{ + size_t i; + va_list argptr; + va_start(argptr, n); + + for(i = 0; i < n; i++) + { + unsigned int bit_index = va_arg(argptr, unsigned int); + bit_array_set_bit(bitarr, bit_index); + } + + va_end(argptr); + DEBUG_VALIDATE(bitarr); +} + +// Clear multiple bits at once. +// e.g. clear bits 1, 20 & 31: bit_array_clear_bits(bitarr, 3, 1,20,31); +void bit_array_clear_bits(BIT_ARRAY* bitarr, size_t n, ...) +{ + size_t i; + va_list argptr; + va_start(argptr, n); + + for(i = 0; i < n; i++) + { + unsigned int bit_index = va_arg(argptr, unsigned int); + bit_array_clear_bit(bitarr, bit_index); + } + + va_end(argptr); + DEBUG_VALIDATE(bitarr); +} + +// Toggle multiple bits at once +// e.g. toggle bits 1, 20 & 31: bit_array_toggle_bits(bitarr, 3, 1,20,31); +void bit_array_toggle_bits(BIT_ARRAY* bitarr, size_t n, ...) +{ + size_t i; + va_list argptr; + va_start(argptr, n); + + for(i = 0; i < n; i++) + { + unsigned int bit_index = va_arg(argptr, unsigned int); + bit_array_toggle_bit(bitarr, bit_index); + } + + va_end(argptr); + DEBUG_VALIDATE(bitarr); +} + + +// +// Set, clear and toggle all bits in a region +// + +// Set all the bits in a region +void bit_array_set_region(BIT_ARRAY* bitarr, bit_index_t start, bit_index_t len) +{ + assert(start + len <= bitarr->num_of_bits); + SET_REGION(bitarr, start, len); + DEBUG_VALIDATE(bitarr); +} + + +// Clear all the bits in a region +void bit_array_clear_region(BIT_ARRAY* bitarr, bit_index_t start, bit_index_t len) +{ + assert(start + len <= bitarr->num_of_bits); + CLEAR_REGION(bitarr, start, len); + DEBUG_VALIDATE(bitarr); +} + +// Toggle all the bits in a region +void bit_array_toggle_region(BIT_ARRAY* bitarr, bit_index_t start, bit_index_t len) +{ + assert(start + len <= bitarr->num_of_bits); + TOGGLE_REGION(bitarr, start, len); + DEBUG_VALIDATE(bitarr); +} + + +// +// Set, clear and toggle all bits at once +// + +// set all elements of data to one +void bit_array_set_all(BIT_ARRAY* bitarr) +{ + bit_index_t num_of_bytes = bitarr->num_of_words * sizeof(word_t); + memset(bitarr->words, 0xFF, num_of_bytes); + _mask_top_word(bitarr); + DEBUG_VALIDATE(bitarr); +} + +// set all elements of data to zero +void bit_array_clear_all(BIT_ARRAY* bitarr) +{ + memset(bitarr->words, 0, bitarr->num_of_words * sizeof(word_t)); + DEBUG_VALIDATE(bitarr); +} + +// Set all 1 bits to 0, and all 0 bits to 1. AKA flip +void bit_array_toggle_all(BIT_ARRAY* bitarr) +{ + word_addr_t i; + for(i = 0; i < bitarr->num_of_words; i++) + { + bitarr->words[i] ^= WORD_MAX; + } + + _mask_top_word(bitarr); + DEBUG_VALIDATE(bitarr); +} + +// +// Get a word at a time +// + +uint64_t bit_array_get_word64(const BIT_ARRAY* bitarr, bit_index_t start) +{ + assert(start < bitarr->num_of_bits); + return (uint64_t)_get_word(bitarr, start); +} + +uint32_t bit_array_get_word32(const BIT_ARRAY* bitarr, bit_index_t start) +{ + assert(start < bitarr->num_of_bits); + return (uint32_t)_get_word(bitarr, start); +} + +uint16_t bit_array_get_word16(const BIT_ARRAY* bitarr, bit_index_t start) +{ + assert(start < bitarr->num_of_bits); + return (uint16_t)_get_word(bitarr, start); +} + +uint8_t bit_array_get_word8(const BIT_ARRAY* bitarr, bit_index_t start) +{ + assert(start < bitarr->num_of_bits); + return (uint8_t)_get_word(bitarr, start); +} + +uint64_t bit_array_get_wordn(const BIT_ARRAY* bitarr, bit_index_t start, int n) +{ + assert(start < bitarr->num_of_bits); + assert(n <= 64); + return (uint64_t)(_get_word(bitarr, start) & bitmask64(n)); +} + +// +// Set a word at a time +// +// Doesn't extend bit array. However it is safe to TRY to set bits beyond the +// end of the array, as long as: `start` is < `bit_array_length(arr)` +// + +void bit_array_set_word64(BIT_ARRAY* bitarr, bit_index_t start, uint64_t word) +{ + assert(start < bitarr->num_of_bits); + _set_word(bitarr, start, (word_t)word); +} + +void bit_array_set_word32(BIT_ARRAY* bitarr, bit_index_t start, uint32_t word) +{ + assert(start < bitarr->num_of_bits); + word_t w = _get_word(bitarr, start); + _set_word(bitarr, start, bitmask_merge(w, word, 0xffffffff00000000UL)); +} + +void bit_array_set_word16(BIT_ARRAY* bitarr, bit_index_t start, uint16_t word) +{ + assert(start < bitarr->num_of_bits); + word_t w = _get_word(bitarr, start); + _set_word(bitarr, start, bitmask_merge(w, word, 0xffffffffffff0000UL)); +} + +void bit_array_set_word8(BIT_ARRAY* bitarr, bit_index_t start, uint8_t byte) +{ + assert(start < bitarr->num_of_bits); + _set_byte(bitarr, start, byte); +} + +void bit_array_set_wordn(BIT_ARRAY* bitarr, bit_index_t start, uint64_t word, int n) +{ + assert(start < bitarr->num_of_bits); + assert(n <= 64); + word_t w = _get_word(bitarr, start), m = bitmask64(n); + _set_word(bitarr, start, bitmask_merge(word,w,m)); +} + +// +// Number of bits set +// + +// Get the number of bits set (hamming weight) +bit_index_t bit_array_num_bits_set(const BIT_ARRAY* bitarr) +{ + word_addr_t i; + + bit_index_t num_of_bits_set = 0; + + for(i = 0; i < bitarr->num_of_words; i++) + { + if(bitarr->words[i] > 0) + { + num_of_bits_set += POPCOUNT(bitarr->words[i]); + } + } + + return num_of_bits_set; +} + +// Get the number of bits not set (1 - hamming weight) +bit_index_t bit_array_num_bits_cleared(const BIT_ARRAY* bitarr) +{ + return bitarr->num_of_bits - bit_array_num_bits_set(bitarr); +} + + +// Get the number of bits set in on array and not the other. This is equivalent +// to hamming weight of the XOR when the two arrays are the same length. +// e.g. 10101 vs 00111 => hamming distance 2 (XOR is 10010) +bit_index_t bit_array_hamming_distance(const BIT_ARRAY* arr1, + const BIT_ARRAY* arr2) +{ + word_addr_t min_words = MIN(arr1->num_of_words, arr2->num_of_words); + word_addr_t max_words = MAX(arr1->num_of_words, arr2->num_of_words); + + bit_index_t hamming_distance = 0; + word_addr_t i; + + for(i = 0; i < min_words; i++) + { + hamming_distance += POPCOUNT(arr1->words[i] ^ arr2->words[i]); + } + + if(min_words != max_words) + { + const BIT_ARRAY* long_arr + = (arr1->num_of_words > arr2->num_of_words ? arr1 : arr2); + + for(i = min_words; i < max_words; i++) + { + hamming_distance += POPCOUNT(long_arr->words[i]); + } + } + + return hamming_distance; +} + +// Parity - returns 1 if odd number of bits set, 0 if even +char bit_array_parity(const BIT_ARRAY* bitarr) +{ + word_addr_t w; + unsigned int parity = 0; + + for(w = 0; w < bitarr->num_of_words; w++) + { + parity ^= PARITY(bitarr->words[w]); + } + + return (char)parity; +} + +// +// Find indices of set/clear bits +// + +// Find the index of the next bit that is set/clear, at or after `offset` +// Returns 1 if such a bit is found, otherwise 0 +// Index is stored in the integer pointed to by `result` +// If no such bit is found, value at `result` is not changed +#define _next_bit_func_def(FUNC,GET) \ +char FUNC(const BIT_ARRAY* bitarr, bit_index_t offset, bit_index_t* result) \ +{ \ + assert(offset < bitarr->num_of_bits); \ + if(bitarr->num_of_bits == 0 || offset >= bitarr->num_of_bits) { return 0; } \ + \ + /* Find first word that is greater than zero */ \ + word_addr_t i = bitset64_wrd(offset); \ + word_t w = GET(bitarr->words[i]) & ~bitmask64(bitset64_idx(offset)); \ + \ + while(1) { \ + if(w > 0) { \ + bit_index_t pos = i * WORD_SIZE + trailing_zeros(w); \ + if(pos < bitarr->num_of_bits) { *result = pos; return 1; } \ + else { return 0; } \ + } \ + i++; \ + if(i >= bitarr->num_of_words) break; \ + w = GET(bitarr->words[i]); \ + } \ + \ + return 0; \ +} + +// Find the index of the previous bit that is set/clear, before `offset`. +// Returns 1 if such a bit is found, otherwise 0 +// Index is stored in the integer pointed to by `result` +// If no such bit is found, value at `result` is not changed +#define _prev_bit_func_def(FUNC,GET) \ +char FUNC(const BIT_ARRAY* bitarr, bit_index_t offset, bit_index_t* result) \ +{ \ + assert(offset <= bitarr->num_of_bits); \ + if(bitarr->num_of_bits == 0 || offset == 0) { return 0; } \ + \ + /* Find prev word that is greater than zero */ \ + word_addr_t i = bitset64_wrd(offset-1); \ + word_t w = GET(bitarr->words[i]) & bitmask64(bitset64_idx(offset-1)+1); \ + \ + if(w > 0) { *result = (i+1) * WORD_SIZE - leading_zeros(w) - 1; return 1; } \ + \ + /* i is unsigned so have to use break when i == 0 */ \ + for(--i; i != BIT_INDEX_MAX; i--) { \ + w = GET(bitarr->words[i]); \ + if(w > 0) { \ + *result = (i+1) * WORD_SIZE - leading_zeros(w) - 1; \ + return 1; \ + } \ + } \ + \ + return 0; \ +} + +#define GET_WORD(x) (x) +#define NEG_WORD(x) (~(x)) +_next_bit_func_def(bit_array_find_next_set_bit, GET_WORD) +_next_bit_func_def(bit_array_find_next_clear_bit,NEG_WORD) +_prev_bit_func_def(bit_array_find_prev_set_bit, GET_WORD) +_prev_bit_func_def(bit_array_find_prev_clear_bit,NEG_WORD) + +// Find the index of the first bit that is set. +// Returns 1 if a bit is set, otherwise 0 +// Index of first set bit is stored in the integer pointed to by result +// If no bits are set, value at `result` is not changed +char bit_array_find_first_set_bit(const BIT_ARRAY* bitarr, bit_index_t* result) +{ + return bit_array_find_next_set_bit(bitarr, 0, result); +} + +// same same +char bit_array_find_first_clear_bit(const BIT_ARRAY* bitarr, bit_index_t* result) +{ + return bit_array_find_next_clear_bit(bitarr, 0, result); +} + +// Find the index of the last bit that is set. +// Returns 1 if a bit is set, otherwise 0 +// Index of last set bit is stored in the integer pointed to by `result` +// If no bits are set, value at `result` is not changed +char bit_array_find_last_set_bit(const BIT_ARRAY* bitarr, bit_index_t* result) +{ + return bit_array_find_prev_set_bit(bitarr, bitarr->num_of_bits, result); +} + +// same same +char bit_array_find_last_clear_bit(const BIT_ARRAY* bitarr, bit_index_t* result) +{ + return bit_array_find_prev_clear_bit(bitarr, bitarr->num_of_bits, result); +} + +// +// "Sorting" bits +// + +// Put all the 0s before all the 1s +void bit_array_sort_bits(BIT_ARRAY* bitarr) +{ + bit_index_t num_of_bits_set = bit_array_num_bits_set(bitarr); + bit_index_t num_of_bits_cleared = bitarr->num_of_bits - num_of_bits_set; + bit_array_set_all(bitarr); + CLEAR_REGION(bitarr, 0, num_of_bits_cleared); + DEBUG_VALIDATE(bitarr); +} + +// Put all the 1s before all the 0s +void bit_array_sort_bits_rev(BIT_ARRAY* bitarr) +{ + bit_index_t num_of_bits_set = bit_array_num_bits_set(bitarr); + bit_array_clear_all(bitarr); + SET_REGION(bitarr, 0, num_of_bits_set); + DEBUG_VALIDATE(bitarr); +} + + +// +// Strings and printing +// + +// Construct a BIT_ARRAY from a substring with given on and off characters. +void bit_array_from_substr(BIT_ARRAY* bitarr, bit_index_t offset, + const char *str, size_t len, + const char *on, const char *off, + char left_to_right) +{ + bit_array_ensure_size(bitarr, offset + len); + bit_array_clear_region(bitarr, offset, len); + + // BitArray region is now all 0s -- just set the 1s + size_t i; + bit_index_t j; + + for(i = 0; i < len; i++) + { + if(strchr(on, str[i]) != NULL) + { + j = offset + (left_to_right ? i : len - i - 1); + bit_array_set(bitarr, j); + } + else { assert(strchr(off, str[i]) != NULL); } + } + + DEBUG_VALIDATE(bitarr); +} + +// From string method +void bit_array_from_str(BIT_ARRAY* bitarr, const char* str) +{ + bit_array_from_substr(bitarr, 0, str, strlen(str), "1", "0", 1); +} + +// Takes a char array to write to. `str` must be bitarr->num_of_bits+1 in length +// Terminates string with '\0' +char* bit_array_to_str(const BIT_ARRAY* bitarr, char* str) +{ + bit_index_t i; + + for(i = 0; i < bitarr->num_of_bits; i++) + { + str[i] = bit_array_get(bitarr, i) ? '1' : '0'; + } + + str[bitarr->num_of_bits] = '\0'; + + return str; +} + +char* bit_array_to_str_rev(const BIT_ARRAY* bitarr, char* str) +{ + bit_index_t i; + + for(i = 0; i < bitarr->num_of_bits; i++) + { + str[i] = bit_array_get(bitarr, bitarr->num_of_bits-i-1) ? '1' : '0'; + } + + str[bitarr->num_of_bits] = '\0'; + + return str; +} + + +// Get a string representations for a given region, using given on/off characters. +// Note: does not null-terminate +void bit_array_to_substr(const BIT_ARRAY* bitarr, + bit_index_t start, bit_index_t length, + char* str, char on, char off, + char left_to_right) +{ + assert(start + length <= bitarr->num_of_bits); + + bit_index_t i, j; + bit_index_t end = start + length - 1; + + for(i = 0; i < length; i++) + { + j = (left_to_right ? start + i : end - i); + str[i] = bit_array_get(bitarr, j) ? on : off; + } + +// str[length] = '\0'; +} + +// Print this array to a file stream. Prints '0's and '1'. Doesn't print newline. +void bit_array_print(const BIT_ARRAY* bitarr, FILE* fout) +{ + bit_index_t i; + + for(i = 0; i < bitarr->num_of_bits; i++) + { + fprintf(fout, "%c", bit_array_get(bitarr, i) ? '1' : '0'); + } +} + +// Print a string representations for a given region, using given on/off characters. +void bit_array_print_substr(const BIT_ARRAY* bitarr, + bit_index_t start, bit_index_t length, + FILE* fout, char on, char off, + char left_to_right) +{ + assert(start + length <= bitarr->num_of_bits); + + bit_index_t i, j; + bit_index_t end = start + length - 1; + + for(i = 0; i < length; i++) + { + j = (left_to_right ? start + i : end - i); + fprintf(fout, "%c", bit_array_get(bitarr, j) ? on : off); + } +} + +// +// Decimal +// + +// Get bit array as decimal str (e.g. 0b1101 -> "13") +// len is the length of str char array -- will write at most len-1 chars +// returns the number of characters needed +// return is the same as strlen(str) +size_t bit_array_to_decimal(const BIT_ARRAY *bitarr, char *str, size_t len) +{ + size_t i = 0; + + if(bit_array_cmp_uint64(bitarr, 0) == 0) + { + if(len >= 2) + { + *str = '0'; + *(str+1) = '\0'; + } + + return 1; + } + + BIT_ARRAY *tmp = bit_array_clone(bitarr); + uint64_t rem; + + str[len-1] = '\0'; + + while(bit_array_cmp_uint64(tmp, 0) != 0) + { + bit_array_div_uint64(tmp, 10, &rem); + + if(i < len-1) + { + str[len-2-i] = '0' + rem; + } + + i++; + } + + if(i < len-1) + { + // Moves null-terminator as well + memmove(str, str+len-i-1, i+1); + } + + bit_array_free(tmp); + + return i; +} + +// Get bit array from decimal str (e.g. "13" -> 0b1101) +// Returns number of characters used +size_t bit_array_from_decimal(BIT_ARRAY *bitarr, const char* decimal) +{ + bit_array_clear_all(bitarr); + size_t i = 0; + + if(decimal[0] == '\0' || decimal[0] < '0' || decimal[0] > '9') + { + return 0; + } + + bit_array_add_uint64(bitarr, decimal[i] - '0'); + i++; + + while(decimal[i] != '\0' && decimal[i] >= '0' && decimal[i] <= '9') + { + bit_array_mul_uint64(bitarr, 10); + bit_array_add_uint64(bitarr, decimal[i] - '0'); + i++; + } + + return i; +} + +// +// Hexidecimal +// + +char bit_array_hex_to_nibble(char c, uint8_t *b) +{ + c = tolower(c); + + if(c >= '0' && c <= '9') + { + *b = c - '0'; + return 1; + } + else if(c >= 'a' && c <= 'f') + { + *b = 0xa + (c - 'a'); + return 1; + } + else + { + return 0; + } +} + +char bit_array_nibble_to_hex(uint8_t b, char uppercase) +{ + if(b <= 9) + { + return '0' + b; + } + else + { + return (uppercase ? 'A' : 'a') + (b - 0xa); + } +} + +// Loads array from hex string +// Returns the number of bits loaded (will be chars rounded up to multiple of 4) +// (0 on failure) +bit_index_t bit_array_from_hex(BIT_ARRAY* bitarr, bit_index_t offset, + const char* str, size_t len) +{ + if(str[0] == '0' && tolower(str[1]) == 'x') + { + str += 2; + len -= 2; + } + + size_t i; + for(i = 0; i < len; i++, offset += 4) + { + uint8_t b; + if(bit_array_hex_to_nibble(str[i], &b)) + { + bit_array_ensure_size(bitarr, offset + 4); + _set_nibble(bitarr, offset, b); + } + else + { + break; + } + } + + return 4 * i; +} + +// Returns number of characters written +size_t bit_array_to_hex(const BIT_ARRAY* bitarr, + bit_index_t start, bit_index_t length, + char* str, char uppercase) +{ + assert(start + length <= bitarr->num_of_bits); + + size_t k = 0; + bit_index_t offset, end = start + length; + + for(offset = start; offset + WORD_SIZE <= end; offset += WORD_SIZE) + { + word_t w = _get_word(bitarr, offset); + + word_offset_t j; + for(j = 0; j < 64; j += 4) + { + str[k++] = bit_array_nibble_to_hex((w>>j) & 0xf, uppercase); + } + } + + if(offset < end) + { + // Remaining full nibbles (4 bits) + word_t w = _get_word(bitarr, offset); + + for(; offset + 4 <= end; offset += 4) + { + str[k++] = bit_array_nibble_to_hex(w & 0xf, uppercase); + w >>= 4; + } + + if(offset < end) + { + // Remaining bits + str[k++] = bit_array_nibble_to_hex(w & bitmask64(end - offset), uppercase); + } + } + + str[k] = '\0'; + + // Return number of characters written + return k; +} + +// Print bit array as hex +size_t bit_array_print_hex(const BIT_ARRAY* bitarr, + bit_index_t start, bit_index_t length, + FILE* fout, char uppercase) +{ + assert(start + length <= bitarr->num_of_bits); + + size_t k = 0; + bit_index_t offset, end = start + length; + + for(offset = start; offset + WORD_SIZE <= end; offset += WORD_SIZE) + { + word_t w = _get_word(bitarr, offset); + + word_offset_t j; + for(j = 0; j < 64; j += 4) + { + fprintf(fout, "%c", bit_array_nibble_to_hex((w>>j) & 0xf, uppercase)); + k++; + } + } + + if(offset < end) + { + // Remaining full nibbles (4 bits) + word_t w = _get_word(bitarr, offset); + + for(; offset + 4 <= end; offset += 4) + { + fprintf(fout, "%c", bit_array_nibble_to_hex(w & 0xf, uppercase)); + w >>= 4; + k++; + } + + if(offset < end) + { + // Remaining bits + char hex = bit_array_nibble_to_hex(w & bitmask64(end - offset), uppercase); + fprintf(fout, "%c", hex); + k++; + } + } + + return k; +} + +// +// Clone and copy +// + +// Returns NULL if cannot malloc +BIT_ARRAY* bit_array_clone(const BIT_ARRAY* bitarr) +{ + BIT_ARRAY* cpy = bit_array_create(bitarr->num_of_bits); + + if(cpy == NULL) + { + return NULL; + } + + // Copy across bits + memcpy(cpy->words, bitarr->words, bitarr->num_of_words * sizeof(word_t)); + + DEBUG_VALIDATE(cpy); + return cpy; +} + +// destination and source may be the same bit_array +// and src/dst regions may overlap +static void _array_copy(BIT_ARRAY* dst, bit_index_t dstindx, + const BIT_ARRAY* src, bit_index_t srcindx, + bit_index_t length) +{ + DEBUG_PRINT("bit_array_copy(dst: %zu, src: %zu, length: %zu)\n", + (size_t)dstindx, (size_t)srcindx, (size_t)length); + + // Num of full words to copy + word_addr_t num_of_full_words = length / WORD_SIZE; + word_addr_t i; + + word_offset_t bits_in_last_word = bits_in_top_word(length); + + if(dst == src && srcindx > dstindx) + { + // Work left to right + DEBUG_PRINT("work left to right\n"); + + for(i = 0; i < num_of_full_words; i++) + { + word_t word = _get_word(src, srcindx+i*WORD_SIZE); + _set_word(dst, dstindx+i*WORD_SIZE, word); + } + + if(bits_in_last_word > 0) + { + word_t src_word = _get_word(src, srcindx+i*WORD_SIZE); + word_t dst_word = _get_word(dst, dstindx+i*WORD_SIZE); + + word_t mask = bitmask64(bits_in_last_word); + word_t word = bitmask_merge(src_word, dst_word, mask); + + _set_word(dst, dstindx+num_of_full_words*WORD_SIZE, word); + } + } + else + { + // Work right to left + DEBUG_PRINT("work right to left\n"); + + for(i = 0; i < num_of_full_words; i++) + { + word_t word = _get_word(src, srcindx+length-(i+1)*WORD_SIZE); + _set_word(dst, dstindx+length-(i+1)*WORD_SIZE, word); + } + + DEBUG_PRINT("Copy %i,%i to %i\n", (int)srcindx, (int)bits_in_last_word, + (int)dstindx); + + if(bits_in_last_word > 0) + { + word_t src_word = _get_word(src, srcindx); + word_t dst_word = _get_word(dst, dstindx); + + word_t mask = bitmask64(bits_in_last_word); + word_t word = bitmask_merge(src_word, dst_word, mask); + _set_word(dst, dstindx, word); + } + } + + _mask_top_word(dst); +} + +// destination and source may be the same bit_array +// and src/dst regions may overlap +void bit_array_copy(BIT_ARRAY* dst, bit_index_t dstindx, + const BIT_ARRAY* src, bit_index_t srcindx, + bit_index_t length) +{ + assert(srcindx + length <= src->num_of_bits); + assert(dstindx <= dst->num_of_bits); + _array_copy(dst, dstindx, src, srcindx, length); + DEBUG_VALIDATE(dst); +} + +// Clone `src` into `dst`. Resizes `dst`. +void bit_array_copy_all(BIT_ARRAY* dst, const BIT_ARRAY* src) +{ + bit_array_resize_critical(dst, src->num_of_bits); + memmove(dst->words, src->words, src->num_of_words * sizeof(word_t)); + DEBUG_VALIDATE(dst); +} + + +// +// Logic operators +// + +// Destination can be the same as one or both of the sources +void bit_array_and(BIT_ARRAY* dst, const BIT_ARRAY* src1, const BIT_ARRAY* src2) +{ + // Ensure dst array is big enough + word_addr_t max_bits = MAX(src1->num_of_bits, src2->num_of_bits); + bit_array_ensure_size_critical(dst, max_bits); + + word_addr_t min_words = MIN(src1->num_of_words, src2->num_of_words); + + word_addr_t i; + + for(i = 0; i < min_words; i++) + { + dst->words[i] = src1->words[i] & src2->words[i]; + } + + // Set remaining bits to zero + for(i = min_words; i < dst->num_of_words; i++) + { + dst->words[i] = (word_t)0; + } + + DEBUG_VALIDATE(dst); +} + +// Destination can be the same as one or both of the sources +static void _logical_or_xor(BIT_ARRAY* dst, + const BIT_ARRAY* src1, + const BIT_ARRAY* src2, + char use_xor) +{ + // Ensure dst array is big enough + bit_array_ensure_size_critical(dst, MAX(src1->num_of_bits, src2->num_of_bits)); + + word_addr_t min_words = MIN(src1->num_of_words, src2->num_of_words); + word_addr_t max_words = MAX(src1->num_of_words, src2->num_of_words); + + word_addr_t i; + + if(use_xor) + { + for(i = 0; i < min_words; i++) + dst->words[i] = src1->words[i] ^ src2->words[i]; + } + else + { + for(i = 0; i < min_words; i++) + dst->words[i] = src1->words[i] | src2->words[i]; + } + + // Copy remaining bits from longer src array + if(min_words != max_words) + { + const BIT_ARRAY* longer = src1->num_of_words > src2->num_of_words ? src1 : src2; + + for(i = min_words; i < max_words; i++) + { + dst->words[i] = longer->words[i]; + } + } + + // Set remaining bits to zero + size_t size = (dst->num_of_words - max_words) * sizeof(word_t); + memset(dst->words + max_words, 0, size); + + DEBUG_VALIDATE(dst); +} + +void bit_array_or(BIT_ARRAY* dst, const BIT_ARRAY* src1, const BIT_ARRAY* src2) +{ + _logical_or_xor(dst, src1, src2, 0); +} + +// Destination can be the same as one or both of the sources +void bit_array_xor(BIT_ARRAY* dst, const BIT_ARRAY* src1, const BIT_ARRAY* src2) +{ + _logical_or_xor(dst, src1, src2, 1); +} + +// If dst is longer than src, top bits are set to 1 +void bit_array_not(BIT_ARRAY* dst, const BIT_ARRAY* src) +{ + bit_array_ensure_size_critical(dst, src->num_of_bits); + + word_addr_t i; + + for(i = 0; i < src->num_of_words; i++) + { + dst->words[i] = ~(src->words[i]); + } + + // Set remaining words to 1s + for(i = src->num_of_words; i < dst->num_of_words; i++) + { + dst->words[i] = WORD_MAX; + } + + _mask_top_word(dst); + + DEBUG_VALIDATE(dst); +} + +// +// Comparisons +// + +// Compare two bit arrays by value stored, with index 0 being the Least +// Significant Bit (LSB). Arrays do not have to be the same length. +// Example: ..0101 (5) > ...0011 (3) [index 0 is LSB at right hand side] +// Sorts on length if all zeros: (0,0) < (0,0,0) +// returns: +// >0 iff bitarr1 > bitarr2 +// 0 iff bitarr1 == bitarr2 +// <0 iff bitarr1 < bitarr2 +int bit_array_cmp(const BIT_ARRAY* bitarr1, const BIT_ARRAY* bitarr2) +{ + word_addr_t i; + word_t word1, word2; + word_addr_t min_words = bitarr1->num_of_words; + + // i is unsigned so break when i == 0 + if(bitarr1->num_of_words > bitarr2->num_of_words) { + min_words = bitarr2->num_of_words; + for(i = bitarr1->num_of_words-1; ; i--) { + if(bitarr1->words[i]) return 1; + if(i == bitarr2->num_of_words) break; + } + } + else if(bitarr1->num_of_words < bitarr2->num_of_words) { + for(i = bitarr2->num_of_words-1; ; i--) { + if(bitarr2->words[i]) return 1; + if(i == bitarr1->num_of_words) break; + } + } + + if(min_words == 0) return 0; + + for(i = min_words-1; ; i--) + { + word1 = bitarr1->words[i]; + word2 = bitarr2->words[i]; + if(word1 != word2) return (word1 > word2 ? 1 : -1); + if(i == 0) break; + } + + if(bitarr1->num_of_bits == bitarr2->num_of_bits) return 0; + return bitarr1->num_of_bits > bitarr2->num_of_bits ? 1 : -1; +} + +// Compare two bit arrays by value stored, with index 0 being the Most +// Significant Bit (MSB). Arrays do not have to be the same length. +// Example: 10.. > 01.. [index 0 is MSB at left hand side] +// Sorts on length if all zeros: (0,0) < (0,0,0) +// returns: +// >0 iff bitarr1 > bitarr2 +// 0 iff bitarr1 == bitarr2 +// <0 iff bitarr1 < bitarr2 +int bit_array_cmp_big_endian(const BIT_ARRAY* bitarr1, const BIT_ARRAY* bitarr2) +{ + word_addr_t min_words = MAX(bitarr1->num_of_words, bitarr2->num_of_words); + + word_addr_t i; + word_t word1, word2; + + for(i = 0; i < min_words; i++) { + word1 = _reverse_word(bitarr1->words[i]); + word2 = _reverse_word(bitarr2->words[i]); + if(word1 != word2) return (word1 > word2 ? 1 : -1); + } + + // Check remaining words. Only one of these loops will execute + for(; i < bitarr1->num_of_words; i++) + if(bitarr1->words[i]) return 1; + for(; i < bitarr2->num_of_words; i++) + if(bitarr2->words[i]) return -1; + + if(bitarr1->num_of_bits == bitarr2->num_of_bits) return 0; + return bitarr1->num_of_bits > bitarr2->num_of_bits ? 1 : -1; +} + +// compare bitarr with (bitarr2 << pos) +// bit_array_cmp(bitarr1, bitarr2<0 iff bitarr1 > bitarr2 +// 0 iff bitarr1 == bitarr2 +// <0 iff bitarr1 < bitarr2 +int bit_array_cmp_words(const BIT_ARRAY *arr1, + bit_index_t pos, const BIT_ARRAY *arr2) +{ + if(arr1->num_of_bits == 0 && arr2->num_of_bits == 0) + { + return 0; + } + + bit_index_t top_bit1 = 0, top_bit2 = 0; + + char arr1_zero = !bit_array_find_last_set_bit(arr1, &top_bit1); + char arr2_zero = !bit_array_find_last_set_bit(arr2, &top_bit2); + + if(arr1_zero && arr2_zero) return 0; + if(arr1_zero) return -1; + if(arr2_zero) return 1; + + bit_index_t top_bit2_offset = top_bit2 + pos; + + if(top_bit1 != top_bit2_offset) { + return top_bit1 > top_bit2_offset ? 1 : -1; + } + + word_addr_t i; + word_t word1, word2; + + for(i = top_bit2 / WORD_SIZE; i > 0; i--) + { + word1 = _get_word(arr1, pos + i * WORD_SIZE); + word2 = arr2->words[i]; + + if(word1 > word2) return 1; + if(word1 < word2) return -1; + } + + word1 = _get_word(arr1, pos); + word2 = arr2->words[0]; + + if(word1 > word2) return 1; + if(word1 < word2) return -1; + + // return 1 if arr1[0..pos] != 0, 0 otherwise + + // Whole words + word_addr_t num_words = pos / WORD_SIZE; + + for(i = 0; i < num_words; i++) + { + if(arr1->words[i] > 0) + { + return 1; + } + } + + word_offset_t bits_remaining = pos - num_words * WORD_SIZE; + + if(arr1->words[num_words] & bitmask64(bits_remaining)) + { + return 1; + } + + return 0; +} + + +// +// Reverse -- coords may wrap around +// + +// No bounds checking +// length cannot be zero +static void _reverse_region(BIT_ARRAY* bitarr, + bit_index_t start, + bit_index_t length) +{ + bit_index_t left = start; + bit_index_t right = (start + length - WORD_SIZE) % bitarr->num_of_bits; + + while(length >= 2 * WORD_SIZE) + { + // Swap entire words + word_t left_word = _get_word_cyclic(bitarr, left); + word_t right_word = _get_word_cyclic(bitarr, right); + + // reverse words individually + left_word = _reverse_word(left_word); + right_word = _reverse_word(right_word); + + // Swap + _set_word_cyclic(bitarr, left, right_word); + _set_word_cyclic(bitarr, right, left_word); + + // Update + left = (left + WORD_SIZE) % bitarr->num_of_bits; + right = (right < WORD_SIZE ? right + bitarr->num_of_bits : right) - WORD_SIZE; + length -= 2 * WORD_SIZE; + } + + word_t word, rev; + + if(length == 0) + { + return; + } + else if(length > WORD_SIZE) + { + // Words overlap + word_t left_word = _get_word_cyclic(bitarr, left); + word_t right_word = _get_word_cyclic(bitarr, right); + + rev = _reverse_word(left_word); + right_word = _reverse_word(right_word); + + // fill left 64 bits with right word rev + _set_word_cyclic(bitarr, left, right_word); + + // Now do remaining bits (length is between 1 and 64 bits) + left += WORD_SIZE; + length -= WORD_SIZE; + + word = _get_word_cyclic(bitarr, left); + } + else + { + word = _get_word_cyclic(bitarr, left); + rev = _reverse_word(word); + } + + rev >>= WORD_SIZE - length; + word_t mask = bitmask64(length); + + word = bitmask_merge(rev, word, mask); + + _set_word_cyclic(bitarr, left, word); +} + +void bit_array_reverse_region(BIT_ARRAY* bitarr, bit_index_t start, bit_index_t len) +{ + assert(start + len <= bitarr->num_of_bits); + if(len > 0) _reverse_region(bitarr, start, len); + DEBUG_VALIDATE(bitarr); +} + +void bit_array_reverse(BIT_ARRAY* bitarr) +{ + if(bitarr->num_of_bits > 0) _reverse_region(bitarr, 0, bitarr->num_of_bits); + DEBUG_VALIDATE(bitarr); +} + +// +// Shift left / right +// + +// Shift towards MSB / higher index +void bit_array_shift_left(BIT_ARRAY* bitarr, bit_index_t shift_dist, char fill) +{ + if(shift_dist >= bitarr->num_of_bits) + { + fill ? bit_array_set_all(bitarr) : bit_array_clear_all(bitarr); + return; + } + else if(shift_dist == 0) + { + return; + } + + FillAction action = fill ? FILL_REGION : ZERO_REGION; + + bit_index_t cpy_length = bitarr->num_of_bits - shift_dist; + _array_copy(bitarr, shift_dist, bitarr, 0, cpy_length); + _set_region(bitarr, 0, shift_dist, action); +} + +// shift left extend - don't truncate bits when shifting UP, instead +// make room for them. +void bit_array_shift_left_extend(BIT_ARRAY* bitarr, bit_index_t shift_dist, + char fill) +{ + bit_index_t newlen = bitarr->num_of_bits + shift_dist; + bit_index_t cpy_length = bitarr->num_of_bits; + + if(shift_dist == 0) + { + return; + } + + bit_array_resize_critical(bitarr, newlen); + + FillAction action = fill ? FILL_REGION : ZERO_REGION; + _array_copy(bitarr, shift_dist, bitarr, 0, cpy_length); + _set_region(bitarr, 0, shift_dist, action); +} + +// Shift towards LSB / lower index +void bit_array_shift_right(BIT_ARRAY* bitarr, bit_index_t shift_dist, char fill) +{ + if(shift_dist >= bitarr->num_of_bits) + { + fill ? bit_array_set_all(bitarr) : bit_array_clear_all(bitarr); + return; + } + else if(shift_dist == 0) + { + return; + } + + FillAction action = fill ? FILL_REGION : ZERO_REGION; + + bit_index_t cpy_length = bitarr->num_of_bits - shift_dist; + bit_array_copy(bitarr, 0, bitarr, shift_dist, cpy_length); + + _set_region(bitarr, cpy_length, shift_dist, action); +} + +// +// Cycle +// + +// Cycle towards index 0 +void bit_array_cycle_right(BIT_ARRAY* bitarr, bit_index_t cycle_dist) +{ + if(bitarr->num_of_bits == 0) + { + return; + } + + cycle_dist = cycle_dist % bitarr->num_of_bits; + + if(cycle_dist == 0) + { + return; + } + + bit_index_t len1 = cycle_dist; + bit_index_t len2 = bitarr->num_of_bits - cycle_dist; + + _reverse_region(bitarr, 0, len1); + _reverse_region(bitarr, len1, len2); + bit_array_reverse(bitarr); +} + +// Cycle away from index 0 +void bit_array_cycle_left(BIT_ARRAY* bitarr, bit_index_t cycle_dist) +{ + if(bitarr->num_of_bits == 0) + { + return; + } + + cycle_dist = cycle_dist % bitarr->num_of_bits; + + if(cycle_dist == 0) + { + return; + } + + bit_index_t len1 = bitarr->num_of_bits - cycle_dist; + bit_index_t len2 = cycle_dist; + + _reverse_region(bitarr, 0, len1); + _reverse_region(bitarr, len1, len2); + bit_array_reverse(bitarr); +} + +// +// Next permutation +// + +static word_t _next_permutation(word_t v) +{ + assert(v); + // From http://graphics.stanford.edu/~seander/bithacks.html#NextBitPermutation + word_t t = v | (v - 1); // t gets v's least significant 0 bits set to 1 + // Next set to 1 the most significant bit to change, + // set to 0 the least significant ones, and add the necessary 1 bits. + return (t+1) | (((~t & (t+1)) - 1) >> (trailing_zeros(v) + 1)); +} + +// Get the next permutation of an array with a fixed size and given number of +// bits set. Also known as next lexicographic permutation. +// Given a bit array find the next lexicographic orginisation of the bits +// Number of possible combinations given by (size choose bits_set) i.e. nCk +// 00011 -> 00101 -> 00110 -> 01001 -> 01010 -> +// 01100 -> 10001 -> 10010 -> 10100 -> 11000 -> 00011 (back to start) +void bit_array_next_permutation(BIT_ARRAY* bitarr) +{ + if(bitarr->num_of_bits == 0) + { + return; + } + + word_addr_t w; + + char carry = 0; + word_offset_t top_bits = bitset64_idx(bitarr->num_of_bits); + + for(w = 0; w < bitarr->num_of_words; w++) + { + word_t mask + = (w < bitarr->num_of_words - 1 || top_bits == 0) ? WORD_MAX + : bitmask64(top_bits); + + if(bitarr->words[w] > 0 && + (bitarr->words[w] | (bitarr->words[w]-1)) == mask) + { + // Bits in this word cannot be moved forward + carry = 1; + } + else if(carry) + { + // 0111 -> 1000, 1000 -> 1001 + word_t tmp = bitarr->words[w] + 1; + + // Count bits previously set + bit_index_t bits_previously_set = POPCOUNT(bitarr->words[w]); + + // set new word + bitarr->words[w] = tmp; + + // note: w is unsigned + // Zero words while counting bits set + while(w > 0) + { + bits_previously_set += POPCOUNT(bitarr->words[w-1]); + bitarr->words[w-1] = 0; + w--; + } + + // Set bits at the beginning + SET_REGION(bitarr, 0, bits_previously_set - POPCOUNT(tmp)); + + carry = 0; + break; + } + else if(bitarr->words[w] > 0) + { + bitarr->words[w] = _next_permutation(bitarr->words[w]); + break; + } + } + + if(carry) + { + // Loop around + bit_index_t num_bits_set = bit_array_num_bits_set(bitarr); + bit_array_clear_all(bitarr); + SET_REGION(bitarr, 0, num_bits_set); + } + + DEBUG_VALIDATE(bitarr); +} + + +// +// Interleave +// + +// dst cannot point to the same bit array as src1 or src2 +// src1, src2 may point to the same bit array +// abcd 1234 -> a1b2c3d4 +// 0011 0000 -> 00001010 +// 1111 0000 -> 10101010 +// 0101 1010 -> 01100110 +void bit_array_interleave(BIT_ARRAY* dst, + const BIT_ARRAY* src1, + const BIT_ARRAY* src2) +{ + // dst cannot be either src1 or src2 + assert(dst != src1 && dst != src2); + // Behaviour undefined when src1 length != src2 length", + assert(src1->num_of_bits == src2->num_of_bits); + + // Need at least src1->num_of_words + src2->num_of_words + size_t nwords = MIN(src1->num_of_words + src2->num_of_words, 2); + _bit_array_ensure_nwords(dst, nwords, __FILE__, __LINE__, __func__); + dst->num_of_bits = src1->num_of_bits + src2->num_of_bits; + dst->num_of_words = roundup_bits2words64(dst->num_of_bits); + + word_addr_t i, j; + + for(i = 0, j = 0; i < src1->num_of_words; i++) + { + word_t a = src1->words[i]; + word_t b = src2->words[i]; + + dst->words[j++] = morton_table0[(a ) & 0xff] | + morton_table1[(b ) & 0xff] | + (morton_table0[(a >> 8) & 0xff] << 16) | + (morton_table1[(b >> 8) & 0xff] << 16) | + (morton_table0[(a >> 16) & 0xff] << 32) | + (morton_table1[(b >> 16) & 0xff] << 32) | + (morton_table0[(a >> 24) & 0xff] << 48) | + (morton_table1[(b >> 24) & 0xff] << 48); + + dst->words[j++] = morton_table0[(a >> 32) & 0xff] | + morton_table1[(b >> 32) & 0xff] | + (morton_table0[(a >> 40) & 0xff] << 16) | + (morton_table1[(b >> 40) & 0xff] << 16) | + (morton_table0[(a >> 48) & 0xff] << 32) | + (morton_table1[(b >> 48) & 0xff] << 32) | + (morton_table0[(a >> 56) ] << 48) | + (morton_table1[(b >> 56) ] << 48); + } + + DEBUG_VALIDATE(dst); +} + +// +// Arithmetic +// + +// Returns 1 on sucess, 0 if value in array is too big +char bit_array_as_num(const BIT_ARRAY* bitarr, uint64_t* result) +{ + if(bitarr->num_of_bits == 0) + { + *result = 0; + return 1; + } + + word_addr_t w; + + for(w = bitarr->num_of_words-1; w > 0; w--) + { + if(bitarr->words[w] > 0) + { + return 0; + } + } + + *result = bitarr->words[0]; + return 1; +} + + +// 1 iff bitarr > value +// 0 iff bitarr == value +// -1 iff bitarr < value +int bit_array_cmp_uint64(const BIT_ARRAY* bitarr, uint64_t value) +{ + uint64_t arr_num = 0; + + // If cannot put bitarr in uint64, it is > value + if(!bit_array_as_num(bitarr, &arr_num)) return 1; + + if(arr_num > value) return 1; + else if(arr_num < value) return -1; + else return 0; +} + +// If value is zero, no change is made +void bit_array_add_uint64(BIT_ARRAY* bitarr, uint64_t value) +{ + if(value == 0) + { + return; + } + else if(bitarr->num_of_bits == 0) + { + bit_array_resize_critical(bitarr, WORD_SIZE - leading_zeros(value)); + bitarr->words[0] = (word_t)value; + return; + } + + char carry = 0; + word_addr_t i; + + for(i = 0; i < bitarr->num_of_words; i++) + { + if(WORD_MAX - bitarr->words[i] < value) + { + carry = 1; + bitarr->words[i] += value; + } + else + { + // Carry is absorbed + bitarr->words[i] += value; + carry = 0; + break; + } + } + + if(carry) + { + // Bit array full, need another bit after all words filled + bit_array_resize_critical(bitarr, bitarr->num_of_words * WORD_SIZE + 1); + + // Set top word to 1 + bitarr->words[bitarr->num_of_words-1] = 1; + } + else + { + word_t final_word = bitarr->words[bitarr->num_of_words-1]; + word_offset_t expected_bits = bits_in_top_word(bitarr->num_of_bits); + word_offset_t actual_bits = WORD_SIZE - leading_zeros(final_word); + + if(actual_bits > expected_bits) + { + // num_of_bits has increased -- num_of_words has not + bitarr->num_of_bits += (actual_bits - expected_bits); + } + } +} + +// If value is greater than bitarr, bitarr is not changed and 0 is returned +// Returns 1 on success, 0 if value > bitarr +char bit_array_sub_uint64(BIT_ARRAY* bitarr, uint64_t value) +{ + if(value == 0) + { + return 1; + } + else if(bitarr->words[0] >= value) + { + bitarr->words[0] -= value; + return 1; + } + + value -= bitarr->words[0]; + + word_addr_t i; + + for(i = 1; i < bitarr->num_of_words; i++) + { + if(bitarr->words[i] > 0) + { + // deduct one + bitarr->words[i]--; + + for(; i > 0; i--) + { + bitarr->words[i] = WORD_MAX; + } + + // -1 since we've already deducted 1 + bitarr->words[0] = WORD_MAX - value - 1; + + return 1; + } + } + + // subtract value is greater than array + return 0; +} + +// +// Arithmetic between bit arrays +// + +// src1, src2 and dst can all be the same BIT_ARRAY +static void _arithmetic(BIT_ARRAY* dst, + const BIT_ARRAY* src1, + const BIT_ARRAY* src2, + char subtract) +{ + word_addr_t max_words = MAX(src1->num_of_words, src2->num_of_words); + + // Adding: dst_words >= max(src1 words, src2 words) + // Subtracting: dst_words is >= src1->num_of_words + + char carry = subtract ? 1 : 0; + + word_addr_t i; + word_t word1, word2; + + for(i = 0; i < max_words; i++) + { + word1 = (i < src1->num_of_words ? src1->words[i] : 0); + word2 = (i < src2->num_of_words ? src2->words[i] : 0); + + if(subtract) + word2 = ~word2; + + dst->words[i] = word1 + word2 + carry; + // Update carry + carry = WORD_MAX - word1 < word2 || WORD_MAX - word1 - word2 < (word_t)carry; + } + + if(subtract) + { + carry = 0; + } + else + { + // Check last word + word_offset_t bits_on_last_word = bits_in_top_word(dst->num_of_bits); + + if(bits_on_last_word < WORD_SIZE) + { + word_t mask = bitmask64(bits_on_last_word); + + if(dst->words[max_words-1] > mask) + { + // Array has overflowed, increase size + dst->num_of_bits++; + } + } + else if(carry) + { + // Carry onto a new word + if(dst->num_of_words == max_words) + { + // Need to resize for the carry bit + bit_array_resize_critical(dst, dst->num_of_bits+1); + } + + dst->words[max_words] = (word_t)1; + } + } + + // Zero the rest of dst array + for(i = max_words+carry; i < dst->num_of_words; i++) + { + dst->words[i] = (word_t)0; + } + + DEBUG_VALIDATE(dst); +} + +// src1, src2 and dst can all be the same BIT_ARRAY +// If dst is shorter than either of src1, src2, it is enlarged +void bit_array_add(BIT_ARRAY* dst, const BIT_ARRAY* src1, const BIT_ARRAY* src2) +{ + bit_array_ensure_size_critical(dst, MAX(src1->num_of_bits, src2->num_of_bits)); + _arithmetic(dst, src1, src2, 0); +} + +// dst = src1 - src2 +// src1, src2 and dst can all be the same BIT_ARRAY +// If dst is shorter than src1, it will be extended to be as long as src1 +// src1 must be greater than or equal to src2 (src1 >= src2) +void bit_array_subtract(BIT_ARRAY* dst, + const BIT_ARRAY* src1, const BIT_ARRAY* src2) +{ + // subtraction by method of complements: + // a - b = a + ~b + 1 = src1 + ~src2 +1 + + assert(bit_array_cmp(src1, src2) >= 0); // Require src1 >= src2 + + bit_array_ensure_size_critical(dst, src1->num_of_bits); + _arithmetic(dst, src1, src2, 1); +} + + +// Add `add` to `bitarr` at `pos` +// Bounds checking not needed as out of bounds is valid +void bit_array_add_word(BIT_ARRAY *bitarr, bit_index_t pos, uint64_t add) +{ + DEBUG_VALIDATE(bitarr); + + if(add == 0) + { + return; + } + else if(pos >= bitarr->num_of_bits) + { + // Resize and add! + bit_index_t num_bits_required = pos + (WORD_SIZE - leading_zeros(add)); + bit_array_resize_critical(bitarr, num_bits_required); + _set_word(bitarr, pos, (word_t)add); + return; + } + + /* + char str[1000]; + printf(" add_word: %s\n", bit_array_to_str_rev(bitarr, str)); + printf(" word: %s [pos: %i]\n", _word_to_str(add, str), (int)pos); + */ + + word_t w = _get_word(bitarr, pos); + word_t sum = w + add; + char carry = WORD_MAX - w < add; + + // Ensure array is big enough + bit_index_t num_bits_required = pos + (carry ? WORD_SIZE + 1 + : (WORD_SIZE - leading_zeros(sum))); + + bit_array_ensure_size(bitarr, num_bits_required); + + _set_word(bitarr, pos, sum); + pos += WORD_SIZE; + + if(carry) + { + word_offset_t offset = pos % WORD_SIZE; + word_addr_t addr = bitset64_wrd(pos); + + add = (word_t)0x1 << offset; + carry = (WORD_MAX - bitarr->words[addr] < add); + sum = bitarr->words[addr] + add; + + num_bits_required = addr * WORD_SIZE + + (carry ? WORD_SIZE + 1 : (WORD_SIZE - leading_zeros(sum))); + + bit_array_ensure_size(bitarr, num_bits_required); + + bitarr->words[addr++] = sum; + + if(carry) + { + while(addr < bitarr->num_of_words && bitarr->words[addr] == WORD_MAX) + { + bitarr->words[addr++] = 0; + } + + if(addr == bitarr->num_of_words) + { + bit_array_resize_critical(bitarr, addr * WORD_SIZE + 1); + } + else if(addr == bitarr->num_of_words-1 && + bitarr->words[addr] == bitmask64(bits_in_top_word(bitarr->num_of_bits))) + { + bit_array_resize_critical(bitarr, bitarr->num_of_bits + 1); + } + + bitarr->words[addr]++; + } + } + + DEBUG_VALIDATE(bitarr); +} + +// Add `add` to `bitarr` at `pos` +// Bounds checking not needed as out of bounds is valid +void bit_array_add_words(BIT_ARRAY *bitarr, bit_index_t pos, const BIT_ARRAY *add) +{ + assert(bitarr != add); // bitarr and add cannot point to the same bit array + + bit_index_t add_top_bit_set; + + if(!bit_array_find_last_set_bit(add, &add_top_bit_set)) + { + // No bits set in add + return; + } + else if(pos >= bitarr->num_of_bits) + { + // Just resize and copy! + bit_index_t num_bits_required = pos + add_top_bit_set + 1; + bit_array_resize_critical(bitarr, num_bits_required); + _array_copy(bitarr, pos, add, 0, add->num_of_bits); + return; + } + else if(pos == 0) + { + bit_array_add(bitarr, bitarr, add); + return; + } + + /* + char str[1000]; + printf(" add_words1: %s\n", bit_array_to_str_rev(bitarr, str)); + printf(" add_words2: %s\n", bit_array_to_str_rev(add, str)); + printf(" [pos: %i]\n", (int)pos); + */ + + bit_index_t num_bits_required = pos + add_top_bit_set + 1; + bit_array_ensure_size(bitarr, num_bits_required); + + word_addr_t first_word = bitset64_wrd(pos); + word_offset_t first_offset = bitset64_idx(pos); + + word_t w = add->words[0] << first_offset; + unsigned char carry = (WORD_MAX - bitarr->words[first_word] < w); + + bitarr->words[first_word] += w; + + word_addr_t i = first_word + 1; + bit_index_t offset = WORD_SIZE - first_offset; + + for(; carry || offset <= add_top_bit_set; i++, offset += WORD_SIZE) + { + w = offset < add->num_of_bits ? _get_word(add, offset) : (word_t)0; + + if(i >= bitarr->num_of_words) + { + // Extend by a word + bit_array_resize_critical(bitarr, (bit_index_t)(i+1)*WORD_SIZE+1); + } + + word_t prev = bitarr->words[i]; + + bitarr->words[i] += w + carry; + + carry = (WORD_MAX - prev < w || (carry && prev + w == WORD_MAX)) ? 1 : 0; + } + + word_offset_t top_bits + = WORD_SIZE - leading_zeros(bitarr->words[bitarr->num_of_words-1]); + + bit_index_t min_bits = (bitarr->num_of_words-1)*WORD_SIZE + top_bits; + + if(bitarr->num_of_bits < min_bits) + { + // Extend within the last word + bitarr->num_of_bits = min_bits; + } + + DEBUG_VALIDATE(bitarr); +} + +char bit_array_sub_word(BIT_ARRAY* bitarr, bit_index_t pos, word_t minus) +{ + DEBUG_VALIDATE(bitarr); + + if(minus == 0) + { + return 1; + } + + word_t w = _get_word(bitarr, pos); + + if(w >= minus) + { + _set_word(bitarr, pos, w - minus); + DEBUG_VALIDATE(bitarr); + return 1; + } + + minus -= w; + + bit_index_t offset; + for(offset = pos + WORD_SIZE; offset < bitarr->num_of_bits; offset += WORD_SIZE) + { + w = _get_word(bitarr, offset); + + if(w > 0) + { + // deduct one + _set_word(bitarr, offset, w - 1); + + SET_REGION(bitarr, pos, offset-pos); + + // -1 since we've already deducted 1 + minus--; + + _set_word(bitarr, pos, WORD_MAX - minus); + + DEBUG_VALIDATE(bitarr); + return 1; + } + } + + DEBUG_VALIDATE(bitarr); + + return 0; +} + +char bit_array_sub_words(BIT_ARRAY* bitarr, bit_index_t pos, BIT_ARRAY* minus) +{ + assert(bitarr != minus); // bitarr and minus cannot point to the same bit array + + int cmp = bit_array_cmp_words(bitarr, pos, minus); + + if(cmp == 0) + { + bit_array_clear_all(bitarr); + return 1; + } + else if(cmp < 0) + { + return 0; + } + + bit_index_t bitarr_length = bitarr->num_of_bits; + + bit_index_t bitarr_top_bit_set; + bit_array_find_last_set_bit(bitarr, &bitarr_top_bit_set); + + // subtraction by method of complements: + // a - b = a + ~b + 1 = src1 + ~src2 +1 + + bit_array_not(minus, minus); + + bit_array_add_words(bitarr, pos, minus); + bit_array_add_word(bitarr, pos, (word_t)1); + + bit_array_sub_word(bitarr, pos+minus->num_of_bits, 1); + bit_array_resize(bitarr, bitarr_length); + + bit_array_not(minus, minus); + + DEBUG_VALIDATE(bitarr); + + return 1; +} + +void bit_array_mul_uint64(BIT_ARRAY *bitarr, uint64_t multiplier) +{ + if(bitarr->num_of_bits == 0 || multiplier == 1) + { + return; + } + else if(multiplier == 0) + { + bit_array_clear_all(bitarr); + return; + } + + bit_index_t i; + + for(i = bitarr->num_of_bits; i > 0; i--) + { + if(bit_array_get(bitarr, i-1)) + { + bit_array_clear(bitarr, i-1); + bit_array_add_word(bitarr, i-1, multiplier); + } + } + + DEBUG_VALIDATE(bitarr); +} + +void bit_array_multiply(BIT_ARRAY *dst, BIT_ARRAY *src1, BIT_ARRAY *src2) +{ + if(src1->num_of_bits == 0 || src2->num_of_bits == 0) + { + bit_array_clear_all(dst); + return; + } + + // Cannot pass the same array as dst, src1 AND src2 + assert(dst != src1 || dst != src2); + + // Dev: multiplier == 1? + + BIT_ARRAY *read_arr, *add_arr; + + if(src1 == dst) + { + read_arr = src1; + add_arr = src2; + } + else + { + read_arr = src2; + add_arr = src1; + } + + if(dst != src1 && dst != src2) + { + bit_array_clear_all(dst); + } + + bit_index_t i; + + for(i = read_arr->num_of_bits; i > 0; i--) + { + if(bit_array_get(read_arr, i-1)) + { + bit_array_clear(dst, i-1); + bit_array_add_words(dst, i-1, add_arr); + } + } + + DEBUG_VALIDATE(dst); +} + +// bitarr = round_down(bitarr / divisor) +// rem = bitarr % divisor +void bit_array_div_uint64(BIT_ARRAY *bitarr, uint64_t divisor, uint64_t *rem) +{ + assert(divisor != 0); // cannot divide by zero + + bit_index_t div_top_bit = 63 - leading_zeros(divisor); + bit_index_t bitarr_top_bit; + + if(!bit_array_find_last_set_bit(bitarr, &bitarr_top_bit)) + { + *rem = 0; + return; + } + + if(bitarr_top_bit < div_top_bit) + { + *rem = bitarr->words[0]; + bit_array_clear_all(bitarr); + return; + } + + // When div is shifted by offset, their top set bits are aligned + bit_index_t offset = bitarr_top_bit - div_top_bit; + + uint64_t tmp = _get_word(bitarr, offset); + _set_word(bitarr, offset, (word_t)0); + + // Carry if 1 if the top bit was set before left shift + char carry = 0; + + // offset unsigned so break when offset == 0 + while(1) + { + if(carry) + { + // (carry:tmp) - divisor = (WORD_MAX+1+tmp)-divisor + tmp = WORD_MAX - divisor + tmp + 1; + bit_array_set(bitarr, offset); + } + else if(tmp >= divisor) + { + tmp -= divisor; + bit_array_set(bitarr, offset); + } + else + { + bit_array_clear(bitarr, offset); + } + + if(offset == 0) + break; + + offset--; + + // Is the top bit set (that we're about to shift off)? + carry = tmp & 0x8000000000000000; + + tmp <<= 1; + tmp |= bit_array_get(bitarr, offset); + } + + *rem = tmp; +} + +// Results in: +// quotient = dividend / divisor +// dividend = dividend % divisor +// (dividend is used to return the remainder) +void bit_array_divide(BIT_ARRAY *dividend, BIT_ARRAY *quotient, BIT_ARRAY *divisor) +{ + assert(bit_array_cmp_uint64(divisor, 0) != 0); // Cannot divide by zero + + bit_array_clear_all(quotient); + + int cmp = bit_array_cmp(dividend, divisor); + + if(cmp == 0) + { + bit_array_ensure_size(quotient, 1); + bit_array_set(quotient, 0); + bit_array_clear_all(dividend); + return; + } + else if(cmp < 0) + { + // dividend is < divisor, quotient is zero -- done + return; + } + + // now we know: dividend > divisor, quotient is zero'd, + // dividend != 0, divisor != 0 + bit_index_t dividend_top_bit = 0, div_top_bit = 0; + + bit_array_find_last_set_bit(dividend, ÷nd_top_bit); + bit_array_find_last_set_bit(divisor, &div_top_bit); + + // When divisor is shifted by offset, their top set bits are aligned + bit_index_t offset = dividend_top_bit - div_top_bit; + + // offset unsigned so break when offset == 0 + for(; ; offset--) + { + if(bit_array_cmp_words(dividend, offset, divisor) >= 0) + { + bit_array_sub_words(dividend, offset, divisor); + bit_array_ensure_size(quotient, offset+1); + bit_array_set(quotient, offset); + } + + if(offset == 0) + break; + } +} + +// +// Read/Write from files +// +// file format is [8 bytes: for number of elements in array][data] +// data is written in little endian order (least sig byte first) +// + +// Saves bit array to a file. Returns the number of bytes written +// number of bytes returned should be 8+(bitarr->num_of_bits+7)/8 +bit_index_t bit_array_save(const BIT_ARRAY* bitarr, FILE* f) +{ + bit_index_t num_of_bytes = roundup_bits2bytes(bitarr->num_of_bits); + bit_index_t bytes_written = 0; + + const int endian = 1; + if(*(uint8_t*)&endian == 1) + { + // Little endian machine + // Write 8 bytes to store the number of bits in the array + bytes_written += fwrite(&bitarr->num_of_bits, 1, 8, f); + + // Write the array + bytes_written += fwrite(bitarr->words, 1, num_of_bytes, f); + } + else + { + // Big endian machine + uint64_t i, w, whole_words = num_of_bytes/sizeof(word_t); + uint64_t rem_bytes = num_of_bytes - whole_words*sizeof(word_t); + uint64_t n_bits = byteswap64(bitarr->num_of_bits); + + // Write 8 bytes to store the number of bits in the array + bytes_written += fwrite(&n_bits, 1, 8, f); + + // Write the array + for(i = 0; i < whole_words; i++) { + w = byteswap64(bitarr->words[i]); + bytes_written += fwrite(&w, 1, 8, f); + } + + if(rem_bytes > 0) { + w = byteswap64(bitarr->words[whole_words]); + bytes_written += fwrite(&w, 1, rem_bytes, f); + } + } + + return bytes_written; +} + +// Load a uint64 from little endian format. +// Works for both big and little endian architectures +static inline uint64_t le64_to_cpu(const uint8_t *x) +{ + return (((uint64_t)(x[0])) | ((uint64_t)(x[1]) << 8) | + ((uint64_t)(x[2]) << 16) | ((uint64_t)(x[3]) << 24) | + ((uint64_t)(x[4]) << 32) | ((uint64_t)(x[5]) << 40) | + ((uint64_t)(x[6]) << 48) | ((uint64_t)(x[7]) << 56)); +} + +// Reads bit array from a file. bitarr is resized and filled. +// Returns 1 on success, 0 on failure +char bit_array_load(BIT_ARRAY* bitarr, FILE* f) +{ + // Read in number of bits, return 0 if we can't read in + bit_index_t num_bits; + if(fread(&num_bits, 1, 8, f) != 8) return 0; + num_bits = le64_to_cpu((uint8_t*)&num_bits); + + // Resize + bit_array_resize_critical(bitarr, num_bits); + + // Have to calculate how many bytes are needed for the file + // (Note: this may be different from num_of_words * sizeof(word_t)) + bit_index_t num_of_bytes = roundup_bits2bytes(bitarr->num_of_bits); + if(fread(bitarr->words, 1, num_of_bytes, f) != num_of_bytes) return 0; + + // Fix endianness + word_addr_t i; + for(i = 0; i < bitarr->num_of_words; i++) + bitarr->words[i] = le64_to_cpu((uint8_t*)&bitarr->words[i]); + + // Mask top word + _mask_top_word(bitarr); + DEBUG_VALIDATE(bitarr); + return 1; +} + +// +// Hash function +// + +/* From: lookup3.c, by Bob Jenkins, May 2006, Public Domain. */ +#define hashsize(n) ((uint32_t)1<<(n)) +#define hashmask(n) (hashsize(n)-1) +#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k)))) + +/* From: lookup3.c, by Bob Jenkins, May 2006, Public Domain. */ +#define mix(a,b,c) \ +{ \ + a -= c; a ^= rot(c, 4); c += b; \ + b -= a; b ^= rot(a, 6); a += c; \ + c -= b; c ^= rot(b, 8); b += a; \ + a -= c; a ^= rot(c,16); c += b; \ + b -= a; b ^= rot(a,19); a += c; \ + c -= b; c ^= rot(b, 4); b += a; \ +} + +/* From: lookup3.c, by Bob Jenkins, May 2006, Public Domain. */ +#define final(a,b,c) \ +{ \ + c ^= b; c -= rot(b,14); \ + a ^= c; a -= rot(c,11); \ + b ^= a; b -= rot(a,25); \ + c ^= b; c -= rot(b,16); \ + a ^= c; a -= rot(c,4); \ + b ^= a; b -= rot(a,14); \ + c ^= b; c -= rot(b,24); \ +} + +/* +From: lookup3.c, by Bob Jenkins, May 2006, Public Domain. +-------------------------------------------------------------------- +hashword2() -- same as hashword(), but take two seeds and return two +32-bit values. pc and pb must both be nonnull, and *pc and *pb must +both be initialized with seeds. If you pass in (*pb)==0, the output +(*pc) will be the same as the return value from hashword(). +-------------------------------------------------------------------- +*/ +static void hashword2 ( +const uint32_t *k, /* the key, an array of uint32_t values */ +size_t length, /* the length of the key, in uint32_ts */ +uint32_t *pc, /* IN: seed OUT: primary hash value */ +uint32_t *pb) /* IN: more seed OUT: secondary hash value */ +{ + uint32_t a,b,c; + + /* Set up the internal state */ + a = b = c = 0xdeadbeef + ((uint32_t)(length<<2)) + *pc; + c += *pb; + + /*------------------------------------------------- handle most of the key */ + while (length > 3) + { + a += k[0]; + b += k[1]; + c += k[2]; + mix(a,b,c); + length -= 3; + k += 3; + } + + /*------------------------------------------- handle the last 3 uint32_t's */ + switch(length) /* all the case statements fall through */ + { + case 3 : c+=k[2]; + case 2 : b+=k[1]; + case 1 : a+=k[0]; + final(a,b,c); + case 0: /* case 0: nothing left to add */ + break; + } + /*------------------------------------------------------ report the result */ + *pc=c; *pb=b; +} + +// Pass seed as 0 on first call, pass previous hash value if rehashing due +// to a collision +// Using bob jenkins hash lookup3 +uint64_t bit_array_hash(const BIT_ARRAY* bitarr, uint64_t seed) +{ + uint32_t seed32[2]; + memcpy(seed32, &seed, sizeof(uint32_t)*2); + + // Round up length to number 32bit words + hashword2((uint32_t*)bitarr->words, (bitarr->num_of_bits + 31) / 32, + &seed32[0], &seed32[1]); + + // XOR with array length. This ensures arrays with different length but same + // contents have different hash values + seed ^= bitarr->num_of_bits; + + return seed; +} + + +// +// Generally useful functions +// + +// Generalised 'binary to string' function +// Adds bits to the string in order of lsb to msb +// e.g. 0b11010 (26 in decimal) would come out as "01011" +char* bit_array_word2str(const void *ptr, size_t num_of_bits, char *str) +{ + const uint8_t* d = (const uint8_t*)ptr; + + size_t i; + for(i = 0; i < num_of_bits; i++) + { + uint8_t bit = (d[i/8] >> (i % 8)) & 0x1; + str[i] = bit ? '1' : '0'; + } + str[num_of_bits] = '\0'; + return str; +} + +char* bit_array_word2str_rev(const void *ptr, size_t num_of_bits, char *str) +{ + const uint8_t* d = (const uint8_t*)ptr; + + size_t i; + for(i = 0; i < num_of_bits; i++) + { + uint8_t bit = (d[i/8] >> (i % 8)) & 0x1; + str[num_of_bits-1-i] = bit ? '1' : '0'; + } + str[num_of_bits] = '\0'; + return str; +} diff --git a/datalink814_ge/src/bit_array/bit_array.h b/datalink814_ge/src/bit_array/bit_array.h new file mode 100644 index 0000000..6d63f1a --- /dev/null +++ b/datalink814_ge/src/bit_array/bit_array.h @@ -0,0 +1,548 @@ +/* + bit_array.h + project: bit array C library + url: https://github.com/noporpoise/BitArray/ + maintainer: Isaac Turner + license: Public Domain, no warranty + date: Sep 2014 +*/ + +#ifndef BIT_ARRAY_HEADER_SEEN +#define BIT_ARRAY_HEADER_SEEN + +#include +#include + +#include "bit_macros.h" + +typedef struct BIT_ARRAY BIT_ARRAY; + +// 64 bit words +typedef uint64_t word_t, word_addr_t, bit_index_t; +typedef uint8_t word_offset_t; // Offset within a 64 bit word + +#define BIT_INDEX_MIN 0 +#define BIT_INDEX_MAX (~(bit_index_t)0) + +#ifdef __cplusplus +extern "C" { +#endif + +// +// Structs +// + +struct BIT_ARRAY +{ + word_t* words; + bit_index_t num_of_bits; + // Number of words used -- this is just round_up(num_of_bits / 64) + // if num_of_bits == 0, this is 0 + word_addr_t num_of_words; + // For more efficient allocation we use realloc only to double size -- + // not for adding every word. Initial size is INIT_CAPACITY_WORDS. + word_addr_t capacity_in_words; +}; + +// +// Basics: Constructor, destructor, get length, resize +// + +// Constructor - create a new bit array of length nbits +BIT_ARRAY* bit_array_create(bit_index_t nbits); + +// Destructor - free the memory used for a bit array +void bit_array_free(BIT_ARRAY* bitarray); + +// Allocate using existing struct +BIT_ARRAY* bit_array_alloc(BIT_ARRAY* bitarr, bit_index_t nbits); +void bit_array_dealloc(BIT_ARRAY* bitarr); + +// Get length of bit array +bit_index_t bit_array_length(const BIT_ARRAY* bit_arr); + +// Change the size of a bit array. Enlarging an array will add zeros +// to the end of it. Returns 1 on success, 0 on failure (e.g. not enough memory) +char bit_array_resize(BIT_ARRAY* bitarr, bit_index_t new_num_of_bits); + +// If bitarr length < num_bits, resizes to num_bits +char bit_array_ensure_size(BIT_ARRAY* bitarr, bit_index_t ensure_num_of_bits); + +// Same as above but exit with an error message if out of memory +void bit_array_resize_critical(BIT_ARRAY* bitarr, bit_index_t num_of_bits); +void bit_array_ensure_size_critical(BIT_ARRAY* bitarr, bit_index_t num_of_bits); + + +// +// Macros +// + +// +// Get, set, clear, assign and toggle individual bits +// Macros for fast access -- beware: no bounds checking +// + +#define bit_array_get(arr,i) bitset_get((arr)->words, i) +#define bit_array_set(arr,i) bitset_set((arr)->words, i) +#define bit_array_clear(arr,i) bitset_del((arr)->words, i) +#define bit_array_toggle(arr,i) bitset_tgl((arr)->words, i) +// c must be 0 or 1 +#define bit_array_assign(arr,i,c) bitset_cpy((arr)->words,i,c) + +// +// Get, set, clear, assign and toggle individual bits +// "Safe": use assert() to check bounds +// + +// Get the value of a bit (returns 0 or 1) +char bit_array_get_bit(const BIT_ARRAY* bitarr, bit_index_t b); +void bit_array_set_bit(BIT_ARRAY* bitarr, bit_index_t b); +void bit_array_clear_bit(BIT_ARRAY* bitarr, bit_index_t b); +void bit_array_toggle_bit(BIT_ARRAY* bitarr, bit_index_t b); +// If char c != 0, set bit; otherwise clear bit +void bit_array_assign_bit(BIT_ARRAY* bitarr, bit_index_t b, char c); + +// +// "Resizing": enlarge array if needed +// + +char bit_array_rget(BIT_ARRAY* bitarr, bit_index_t b); +void bit_array_rset(BIT_ARRAY* bitarr, bit_index_t b); +void bit_array_rclear(BIT_ARRAY* bitarr, bit_index_t b); +void bit_array_rtoggle(BIT_ARRAY* bitarr, bit_index_t b); +void bit_array_rassign(BIT_ARRAY* bitarr, bit_index_t b, char c); + +// +// Set, clear and toggle several bits at once +// + +// Set multiple bits at once. +// e.g. set bits 1, 20 & 31: bit_array_set_bits(bitarr, 3, 1,20,31); +// Note: variable args are of type unsigned int +void bit_array_set_bits(BIT_ARRAY* bitarr, size_t n, ...); + +// Clear multiple bits at once. +// e.g. clear bits 1, 20 & 31: bit_array_clear_bits(bitarr, 3, 1,20,31); +// Note: variable args are of type unsigned int +void bit_array_clear_bits(BIT_ARRAY* bitarr, size_t n, ...); + +// Toggle multiple bits at once +// e.g. toggle bits 1, 20 & 31: bit_array_toggle_bits(bitarr, 3, 1,20,31); +// Note: variable args are of type unsigned int +void bit_array_toggle_bits(BIT_ARRAY* bitarr, size_t n, ...); + +// +// Set, clear and toggle all bits in a region +// + +// Set all the bits in a region +void bit_array_set_region(BIT_ARRAY* bitarr, bit_index_t start, bit_index_t len); + +// Clear all the bits in a region +void bit_array_clear_region(BIT_ARRAY* bitarr, bit_index_t start, bit_index_t len); + +// Toggle all the bits in a region +void bit_array_toggle_region(BIT_ARRAY* bitarr, bit_index_t start, bit_index_t len); + +// +// Set, clear and toggle all bits at once +// + +// Set all bits in this array to 1 +void bit_array_set_all(BIT_ARRAY* bitarr); + +// Set all bits in this array to 0 +void bit_array_clear_all(BIT_ARRAY* bitarr); + +// Set all 1 bits to 0, and all 0 bits to 1 +void bit_array_toggle_all(BIT_ARRAY* bitarr); + +// +// Get / set a word of a given size +// + +// First bit is in the least significant bit position +// start index must be within the range of the bit array (0 <= x < length) +uint64_t bit_array_get_word64(const BIT_ARRAY* bitarr, bit_index_t start); +uint32_t bit_array_get_word32(const BIT_ARRAY* bitarr, bit_index_t start); +uint16_t bit_array_get_word16(const BIT_ARRAY* bitarr, bit_index_t start); +uint8_t bit_array_get_word8(const BIT_ARRAY* bitarr, bit_index_t start); +uint64_t bit_array_get_wordn(const BIT_ARRAY* bitarr, bit_index_t start, int n); + +// Set 64 bits at once from a particular start position +// Doesn't extend bit array. However it is safe to TRY to set bits beyond the +// end of the array, as long as: `start` is < `bit_array_length(arr)` +void bit_array_set_word64(BIT_ARRAY* bitarr, bit_index_t start, uint64_t word); +void bit_array_set_word32(BIT_ARRAY* bitarr, bit_index_t start, uint32_t word); +void bit_array_set_word16(BIT_ARRAY* bitarr, bit_index_t start, uint16_t word); +void bit_array_set_word8(BIT_ARRAY* bitarr, bit_index_t start, uint8_t byte); +void bit_array_set_wordn(BIT_ARRAY* bitarr, bit_index_t start, uint64_t word, int n); + +// +// Number of bits set +// + +// Get the number of bits set (hamming weight) +bit_index_t bit_array_num_bits_set(const BIT_ARRAY* bitarr); + +// Get the number of bits not set (length - hamming weight) +bit_index_t bit_array_num_bits_cleared(const BIT_ARRAY* bitarr); + +// Get the number of bits set in on array and not the other. This is equivalent +// to hamming weight of the XOR when the two arrays are the same length. +// e.g. 10101 vs 00111 => hamming distance 2 (XOR is 10010) +bit_index_t bit_array_hamming_distance(const BIT_ARRAY* arr1, + const BIT_ARRAY* arr2); + +// Parity - returns 1 if odd number of bits set, 0 if even +char bit_array_parity(const BIT_ARRAY* bitarr); + +// +// Find indices of set/clear bits +// + +// Find the index of the next bit that is set, at or after `offset` +// Returns 1 if a bit is set, otherwise 0 +// Index of next set bit is stored in the integer pointed to by result +// If no next bit is set result is not changed +char bit_array_find_next_set_bit(const BIT_ARRAY* bitarr, bit_index_t offset, + bit_index_t* result); + +// Find the index of the next bit that is NOT set, at or after `offset` +// Returns 1 if a bit is NOT set, otherwise 0 +// Index of next zero bit is stored in the integer pointed to by `result` +// If no next bit is zero, value at `result` is not changed +char bit_array_find_next_clear_bit(const BIT_ARRAY* bitarr, bit_index_t offset, + bit_index_t* result); + +// Find the index of the previous bit that is set, before offset. +// Returns 1 if a bit is set, otherwise 0 +// Index of previous set bit is stored in the integer pointed to by `result` +// If no previous bit is set result is not changed +char bit_array_find_prev_set_bit(const BIT_ARRAY* bitarr, bit_index_t offset, + bit_index_t* result); + +// Find the index of the previous bit that is NOT set, before offset. +// Returns 1 if a bit is clear, otherwise 0 +// Index of previous zero bit is stored in the integer pointed to by `result` +// If no previous bit is zero result is not changed +char bit_array_find_prev_clear_bit(const BIT_ARRAY* bitarr, bit_index_t offset, + bit_index_t* result); + +// Find the index of the first bit that is set. +// Returns 1 if a bit is set, otherwise 0 +// Index of first set bit is stored in the integer pointed to by `result` +// If no bit is set result is not changed +char bit_array_find_first_set_bit(const BIT_ARRAY* bitarr, bit_index_t* result); + +// Find the index of the first bit that is NOT set. +// Returns 1 if a bit is clear, otherwise 0 +// Index of first zero bit is stored in the integer pointed to by `result` +// If no bit is zero result is not changed +char bit_array_find_first_clear_bit(const BIT_ARRAY* bitarr, bit_index_t* result); + +// Find the index of the last bit that is set. +// Returns 1 if a bit is set, otherwise 0 +// Index of last set bit is stored in the integer pointed to by `result` +// If no bit is set result is not changed +char bit_array_find_last_set_bit(const BIT_ARRAY* bitarr, bit_index_t* result); + +// Find the index of the last bit that is NOT set. +// Returns 1 if a bit is clear, otherwise 0 +// Index of last zero bit is stored in the integer pointed to by `result` +// If no bit is zero result is not changed +char bit_array_find_last_clear_bit(const BIT_ARRAY* bitarr, bit_index_t* result); + + +// +// Sorting +// + +// Put all the 0s before all the 1s +void bit_array_sort_bits(BIT_ARRAY* bitarr); + +// Put all the 1s before all the 0s +void bit_array_sort_bits_rev(BIT_ARRAY* bitarr); + + +// +// String and printing methods +// + +// Construct a BIT_ARRAY from a string. +void bit_array_from_str(BIT_ARRAY* bitarr, const char* bitstr); + +// Construct a BIT_ARRAY from a substring with given on and off characters. +void bit_array_from_substr(BIT_ARRAY* bitarr, bit_index_t offset, + const char* str, size_t len, + const char *on, const char *off, char left_to_right); + +// Takes a char array to write to. `str` must be bitarr->num_of_bits+1 in +// length. Terminates string with '\0' +char* bit_array_to_str(const BIT_ARRAY* bitarr, char* str); +char* bit_array_to_str_rev(const BIT_ARRAY* bitarr, char* str); + +// Get a string representations for a given region, using given on/off +// characters. +// Note: does not null-terminate +void bit_array_to_substr(const BIT_ARRAY* bitarr, + bit_index_t start, bit_index_t length, + char* str, char on, char off, char left_to_right); + +// Print this array to a file stream. Prints '0's and '1'. Doesn't print +// newline. +void bit_array_print(const BIT_ARRAY* bitarr, FILE* fout); + +// Print a string representations for a given region, using given on/off +// characters. Reverse prints from highest to lowest -- this is useful for +// printing binary numbers +void bit_array_print_substr(const BIT_ARRAY* bitarr, + bit_index_t start, bit_index_t length, + FILE* fout, char on, char off, char left_to_right); + +// +// Decimal +// + +// Get bit array as decimal str (e.g. 0b1101 -> "13") +size_t bit_array_to_decimal(const BIT_ARRAY *bitarr, char *str, size_t len); + +// Return number of characters used +size_t bit_array_from_decimal(BIT_ARRAY *bitarr, const char* decimal); + +// +// Hexidecimal +// + +// Loads array from hex string +// Returns the number of bits loaded (will be chars rounded up to multiple of 8) +// (0 on failure) +bit_index_t bit_array_from_hex(BIT_ARRAY* bitarr, bit_index_t offset, + const char* str, size_t len); + +// Returns number of characters written +size_t bit_array_to_hex(const BIT_ARRAY* bitarr, + bit_index_t start, bit_index_t length, + char* str, char uppercase); + +// Print bit array as hex +size_t bit_array_print_hex(const BIT_ARRAY* bitarr, + bit_index_t start, bit_index_t length, + FILE* fout, char uppercase); + +// +// Clone and copy +// + +// Copy a BIT_ARRAY struct and the data it holds - returns pointer to new object +#define bit_array_dup bit_array_clone +BIT_ARRAY* bit_array_clone(const BIT_ARRAY* bitarr); + +// Copy bits from one array to another +// Note: use MACRO bit_array_copy +// Destination and source can be the same bit_array and +// src/dst regions can overlap +void bit_array_copy(BIT_ARRAY* dst, bit_index_t dstindx, + const BIT_ARRAY* src, bit_index_t srcindx, + bit_index_t length); + +// copy all of src to dst. dst is resized to match src. +void bit_array_copy_all(BIT_ARRAY* dst, const BIT_ARRAY* src); + +// +// Logic operators +// + +// BIT_ARRAYs can all be different or the same object +// dest array will be resized if it is too short +// +void bit_array_and(BIT_ARRAY* dest, const BIT_ARRAY* src1, const BIT_ARRAY* src2); +void bit_array_or (BIT_ARRAY* dest, const BIT_ARRAY* src1, const BIT_ARRAY* src2); +void bit_array_xor(BIT_ARRAY* dest, const BIT_ARRAY* src1, const BIT_ARRAY* src2); +void bit_array_not(BIT_ARRAY* dest, const BIT_ARRAY* src); + +// +// Comparisons +// + +// Note: (bit_array_cmp(a,b) == 0) <=> (bit_array_cmp_big_endian(a,b) == 0) + +// comparison functions return: +// 1 iff bitarr1 > bitarr2 +// 0 iff bitarr1 == bitarr2 +// -1 iff bitarr1 < bitarr2 + +// Compare two bit arrays by value stored, with index 0 being the Least +// Significant Bit (LSB). Arrays do not have to be the same length. +// Example: ..0101 (5) > ...0011 (3) [index 0 is LSB at right hand side] +int bit_array_cmp(const BIT_ARRAY* bitarr1, const BIT_ARRAY* bitarr2); + +// Compare two bit arrays by value stored, with index 0 being the Most +// Significant Bit (MSB). Arrays do not have to be the same length. +// Example: 10.. > 01.. [index 0 is MSB at left hand side] +int bit_array_cmp_big_endian(const BIT_ARRAY* bitarr1, const BIT_ARRAY* bitarr2); + +// compare bitarr with (bitarr2 << pos) +int bit_array_cmp_words(const BIT_ARRAY *bitarr, + bit_index_t pos, const BIT_ARRAY *bitarr2); + +// +// Shift, interleave, reverse +// + +// Shift array left/right. If fill is zero, filled with 0, otherwise 1 +void bit_array_shift_right(BIT_ARRAY* bitarr, bit_index_t shift_dist, char fill); +void bit_array_shift_left (BIT_ARRAY* bitarr, bit_index_t shift_dist, char fill); + +// shift left without losing any bits. Resizes bitarr. +void bit_array_shift_left_extend(BIT_ARRAY* bitarr, bit_index_t shift_dist, + char fill); + +// Cyclic shift +void bit_array_cycle_right(BIT_ARRAY* bitarr, bit_index_t dist); +void bit_array_cycle_left (BIT_ARRAY* bitarr, bit_index_t dist); + +// Interleave +// dst cannot point to the same bit array as src1 or src2 +// src1, src2 may point to the same bit array +// abcd 1234 -> a1b2c3d4 +// 0011 0000 -> 00001010 +// 1111 0000 -> 10101010 +// 0101 1010 -> 01100110 +// Extends dst if it is too short, but does not shrink it if it is too long +// if dst is longer than length(src1)+length(src2), the end bits are not altered +void bit_array_interleave(BIT_ARRAY* dst, + const BIT_ARRAY* src1, + const BIT_ARRAY* src2); + +// Reverse the whole array or part of it +void bit_array_reverse(BIT_ARRAY* bitarr); +void bit_array_reverse_region(BIT_ARRAY* bitarr, bit_index_t start, bit_index_t len); + +// +// Numeric +// + +// Returns 1 on sucess, 0 if value in array is too big +char bit_array_as_num(const BIT_ARRAY* bitarr, uint64_t* result); + +// 1 iff bitarr > value +// 0 iff bitarr == value +// -1 iff bitarr < value +int bit_array_cmp_uint64(const BIT_ARRAY* bitarr, uint64_t value); + +// +// Arithmetic +// + +// bitarr will be extended if needed +void bit_array_add_uint64(BIT_ARRAY* bitarr, uint64_t value); + +// Add `add` to `bitarr` at `pos` -- same as: +// bitarr + (add << pos) +// where pos can be bigger than the length of the array (bitarr will be resized) +void bit_array_add_word(BIT_ARRAY *bitarr, bit_index_t pos, uint64_t add); + +// Add `add` to `bitarr` at `pos` +void bit_array_add_words(BIT_ARRAY *bitarr, bit_index_t pos, const BIT_ARRAY *add); + +// If value is greater than bitarr, bitarr is not changed and 0 is returned +// Returns 1 on success, 0 if value > bitarr +char bit_array_sub_uint64(BIT_ARRAY* bitarr, uint64_t value); + +// minus `minus` from `bitarr` at `pos` -- same as: +// bitarr + (minus << pos) +// Returns 1 on success, 0 if value > bitarr +char bit_array_sub_word(BIT_ARRAY *bitarr, bit_index_t pos, word_t minus); + +// minus `minus` from `bitarr` at `pos` +// Returns 1 on success, 0 if value > bitarr +char bit_array_sub_words(BIT_ARRAY* bitarr, bit_index_t pos, BIT_ARRAY* minus); + +// Multiply by some value +void bit_array_mul_uint64(BIT_ARRAY *bitarr, uint64_t multiplier); + +// bitarr = round_down(bitarr / divisor) +// rem = bitarr % divisor +void bit_array_div_uint64(BIT_ARRAY *bitarr, uint64_t divisor, uint64_t *rem); + +// +// Arithmetic between arrays +// + +// dst = src1 + src2 +// src1, src2 and dst can all be the same BIT_ARRAY +// If dst is shorter than either of src1, src2, it is enlarged +void bit_array_add(BIT_ARRAY* dst, const BIT_ARRAY* src1, const BIT_ARRAY* src2); + +// dst = src1 - src2 +// src1, src2 and dst can all be the same BIT_ARRAY +// If dst is shorter than src1, it will be extended to be as long as src1 +// src1 must be greater than or equal to src2 (src1 >= src2) +void bit_array_subtract(BIT_ARRAY* dst, + const BIT_ARRAY* src1, const BIT_ARRAY* src2); + +// dst = src1 * src2 +// Pointers cannot all point to the same BIT_ARRAY +void bit_array_multiply(BIT_ARRAY *dst, BIT_ARRAY *src1, BIT_ARRAY *src2); + +// Results in: +// quotient = dividend / divisor +// dividend = dividend % divisor +// (dividend is used to return the remainder) +void bit_array_divide(BIT_ARRAY *dividend, BIT_ARRAY *quotient, BIT_ARRAY *divisor); + +// +// Read/Write bit_array to a file +// +// File format is [8 bytes: for number of elements in array][data] +// Number of bytes of data is: (int)((num_of_bits + 7) / 8) +// + +// Saves bit array to a file +// returns the number of bytes written +bit_index_t bit_array_save(const BIT_ARRAY* bitarr, FILE* f); + +// Reads bit array from a file. bitarr is resized and filled. +// Returns 1 on success, 0 on failure +char bit_array_load(BIT_ARRAY* bitarr, FILE* f); + + +// +// Hash function +// + +// Pass seed as 0 on first call, pass previous hash value if rehashing due +// to a collision +// Using bob jenkins hash lookup3 +uint64_t bit_array_hash(const BIT_ARRAY* bitarr, uint64_t seed); + +// +// Randomness +// + +// Get the next permutation of an array with a fixed size and given number of +// bits set. Also known as next lexicographic permutation. +// Given a bit array find the next lexicographic orginisation of the bits +// Number of possible combinations given by (size choose bits_set) i.e. nCk +// 00011 -> 00101 -> 00110 -> 01001 -> 01010 -> +// 01100 -> 10001 -> 10010 -> 10100 -> 11000 -> 00011 (back to start) +void bit_array_next_permutation(BIT_ARRAY* bitarr); + +// +// Generally useful functions +// + +// Generalised 'binary to string' function +// Adds bits to the string in order of lsb to msb +// e.g. 0b11010 (26 in decimal) would come out as "01011" +char* bit_array_word2str(const void *ptr, size_t num_of_bits, char *str); + +// Same as above but in reverse +char* bit_array_word2str_rev(const void *ptr, size_t num_of_bits, char *str); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/datalink814_ge/src/bit_array/bit_macros.h b/datalink814_ge/src/bit_array/bit_macros.h new file mode 100644 index 0000000..6cd937d --- /dev/null +++ b/datalink814_ge/src/bit_array/bit_macros.h @@ -0,0 +1,205 @@ +/* + bit_macros.h + project: bit array C library + url: https://github.com/noporpoise/BitArray/ + author: Isaac Turner + license: Public Domain, no warranty + date: Dec 2013 +*/ + +#ifndef BITSET_H_ +#define BITSET_H_ + +#include +#include + +// trailing_zeros is number of least significant zeros +// leading_zeros is number of most significant zeros +#if defined(_WIN32) + #define trailing_zeros(x) ({ __typeof(x) _r; _BitScanReverse64(&_r, x); _r; }) + #define leading_zeros(x) ({ __typeof(x) _r; _BitScanForward64(&_r, x); _r; }) +#else + #define trailing_zeros(x) ((x) ? (__typeof(x))__builtin_ctzll(x) : (__typeof(x))sizeof(x)*8) + #define leading_zeros(x) ((x) ? (__typeof(x))__builtin_clzll(x) : (__typeof(x))sizeof(x)*8) +#endif + +// Get index of top set bit. If x is 0 return nbits +#define top_set_bit(x) ((x) ? sizeof(x)*8-leading_zeros(x)-1 : sizeof(x)*8) + +#define roundup_bits2bytes(bits) (((bits)+7)/8) +#define roundup_bits2words32(bits) (((bits)+31)/32) +#define roundup_bits2words64(bits) (((bits)+63)/64) + +// Round a number up to the nearest number that is a power of two +#define roundup2pow(x) (1UL << (64 - leading_zeros(x))) + +#define rot32(x,r) (((x)<<(r)) | ((x)>>(32-(r)))) +#define rot64(x,r) (((x)<<(r)) | ((x)>>(64-(r)))) + +// need to check for length == 0, undefined behaviour if uint64_t >> 64 etc +#define bitmask(nbits,type) ((nbits) ? ~(type)0 >> (sizeof(type)*8-(nbits)): (type)0) +#define bitmask32(nbits) bitmask(nbits,uint32_t) +#define bitmask64(nbits) bitmask(nbits,uint64_t) + +// A possibly faster way to combine two words with a mask +//#define bitmask_merge(a,b,abits) ((a & abits) | (b & ~abits)) +#define bitmask_merge(a,b,abits) (b ^ ((a ^ b) & abits)) + +// Swap lowest four bits. A nibble is 4 bits (i.e. half a byte) +#define rev_nibble(x) ((((x)&1)<<3)|(((x)&2)<<1)|(((x)&4)>>1)|(((x)&8)>>3)) + +// +// Bit array (bitset) +// +// bitsetX_wrd(): get word for a given position +// bitsetX_idx(): get index within word for a given position +#define _VOLPTR(x) ((volatile __typeof(x) *)(&(x))) +#define _VOLVALUE(x) (*_VOLPTR(x)) + +#define _TYPESHIFT(arr,word,shift) \ + ((__typeof(*(arr)))((__typeof(*(arr)))(word) << (shift))) + +#define bitsetX_wrd(wrdbits,pos) ((pos) / (wrdbits)) +#define bitsetX_idx(wrdbits,pos) ((pos) % (wrdbits)) + +#define bitset32_wrd(pos) ((pos) >> 5) +#define bitset32_idx(pos) ((pos) & 31) + +#define bitset64_wrd(pos) ((pos) >> 6) +#define bitset64_idx(pos) ((pos) & 63) + +// +// Bit functions on arrays +// +#define bitset2_get(arr,wrd,idx) (((arr)[wrd] >> (idx)) & 0x1) +#define bitset2_set(arr,wrd,idx) ((arr)[wrd] |= _TYPESHIFT(arr,1,idx)) +#define bitset2_del(arr,wrd,idx) ((arr)[wrd] &=~ _TYPESHIFT(arr,1,idx)) +#define bitset2_tgl(arr,wrd,idx) ((arr)[wrd] ^= _TYPESHIFT(arr,1,idx)) +#define bitset2_or(arr,wrd,idx,bit) ((arr)[wrd] |= _TYPESHIFT(arr,bit,idx)) +#define bitset2_xor(arr,wrd,idx,bit) ((arr)[wrd] = ~((arr)[wrd] ^ (~_TYPESHIFT(arr,bit,idx)))) +#define bitset2_and(arr,wrd,idx,bit) ((arr)[wrd] &= (_TYPESHIFT(arr,bit,idx) | ~_TYPESHIFT(arr,1,idx))) +#define bitset2_cpy(arr,wrd,idx,bit) ((arr)[wrd] = ((arr)[wrd] &~ _TYPESHIFT(arr,1,idx)) | _TYPESHIFT(arr,bit,idx)) + +// +// Thread safe versions +// +// They return the value of the bit (0 or 1) before it was updated +#define bitset2_get_mt(arr,wrd,idx) bitset2_get(_VOLPTR(*(arr)),wrd,idx) +#define bitset2_set_mt(arr,wrd,idx) ((__sync_fetch_and_or (_VOLPTR((arr)[wrd]), _TYPESHIFT(arr,1,idx)) >> (idx))&1) +#define bitset2_del_mt(arr,wrd,idx) ((__sync_fetch_and_and(_VOLPTR((arr)[wrd]), ~_TYPESHIFT(arr,1,idx)) >> (idx))&1) +#define bitset2_tgl_mt(arr,wrd,idx) ((__sync_fetch_and_xor(_VOLPTR((arr)[wrd]), _TYPESHIFT(arr,1,idx)) >> (idx))&1) +#define bitset2_or_mt(arr,wrd,idx,bit) ((__sync_fetch_and_or (_VOLPTR((arr)[wrd]), _TYPESHIFT(arr,bit,idx)) >> (idx))&1) +#define bitset2_xor_mt(arr,wrd,idx,bit) ((__sync_fetch_and_xor(_VOLPTR((arr)[wrd]), _TYPESHIFT(arr,bit,idx)) >> (idx))&1) +#define bitset2_and_mt(arr,wrd,idx,bit) ((__sync_fetch_and_and(_VOLPTR((arr)[wrd]), (_TYPESHIFT(arr,bit,idx) | ~_TYPESHIFT(arr,1,idx))) >> (idx))&1) +#define bitset2_cpy_mt(arr,wrd,idx,bit) ((bit) ? bitset2_set_mt(arr,wrd,idx) : bitset2_del_mt(arr,wrd,idx)) + +// +// Auto detect size of type from pointer +// +#define bitset_wrd(arr,pos) bitsetX_wrd(sizeof(*(arr))*8,pos) +#define bitset_idx(arr,pos) bitsetX_idx(sizeof(*(arr))*8,pos) +#define bitset_op(func,arr,pos) func(arr, bitset_wrd(arr,pos), bitset_idx(arr,pos)) +#define bitset_op2(func,arr,pos,bit) func(arr, bitset_wrd(arr,pos), bitset_idx(arr,pos), bit) + +// Auto-detect type size: bit functions +#define bitset_get(arr,pos) bitset_op(bitset2_get, arr, pos) +#define bitset_set(arr,pos) bitset_op(bitset2_set, arr, pos) +#define bitset_del(arr,pos) bitset_op(bitset2_del, arr, pos) +#define bitset_tgl(arr,pos) bitset_op(bitset2_tgl, arr, pos) +#define bitset_or(arr,pos,bit) bitset_op2(bitset2_or, arr, pos, bit) +#define bitset_xor(arr,pos,bit) bitset_op2(bitset2_xor, arr, pos, bit) +#define bitset_and(arr,pos,bit) bitset_op2(bitset2_and, arr, pos, bit) +#define bitset_cpy(arr,pos,bit) bitset_op2(bitset2_cpy, arr, pos, bit) + +// Auto-detect type size: thread safe bit functions +// They return the value of the bit (0 or 1) before it was updated +#define bitset_get_mt(arr,pos) bitset_op(bitset2_get_mt, arr, pos) +#define bitset_set_mt(arr,pos) bitset_op(bitset2_set_mt, arr, pos) +#define bitset_del_mt(arr,pos) bitset_op(bitset2_del_mt, arr, pos) +#define bitset_tgl_mt(arr,pos) bitset_op(bitset2_tgl_mt, arr, pos) +#define bitset_or_mt(arr,pos,bit) bitset_op2(bitset2_or_mt, arr, pos, bit) +#define bitset_xor_mt(arr,pos,bit) bitset_op2(bitset2_xor_mt, arr, pos, bit) +#define bitset_and_mt(arr,pos,bit) bitset_op2(bitset2_and_mt, arr, pos, bit) +#define bitset_cpy_mt(arr,pos,bit) bitset_op2(bitset2_cpy_mt, arr, pos, bit) + +// Clearing a word does not return a meaningful value +#define bitset_clear_word(arr,pos) ((arr)[bitset_wrd(arr,pos)] = 0) +#define bitset_clear_word_mt(arr,pos) (_VOLVALUE((arr)[bitset_wrd(arr,pos)]) = 0) + +// +// Compact bit array of spin locks +// These are most effecient when arr is of type: volatile char* +// +// Acquire a lock +#define bitlock_acquire_block(arr,pos,wait,abandon) do { \ + size_t _w = bitset_wrd(arr,pos); \ + __typeof(*(arr)) _o, _n, _b = _TYPESHIFT(arr, 1, bitset_idx(arr,pos)); \ + do { \ + while((_o = _VOLVALUE((arr)[_w])) & _b) { wait } \ + abandon \ + _n = _o | _b; \ + } while(!__sync_bool_compare_and_swap(_VOLPTR((arr)[_w]), _o, _n)); \ + __sync_synchronize(); /* Must not move commands to before acquiring lock */ \ +} while(0) + +// Undefined behaviour if you do not already hold the lock +#define bitlock_release(arr,pos) do { \ + size_t _w = bitset_wrd(arr,pos); \ + __typeof(*(arr)) _mask = ~_TYPESHIFT(arr, 1, bitset_idx(arr,pos)); \ + __sync_synchronize(); /* Must get the lock before releasing it */ \ + __sync_and_and_fetch(_VOLPTR((arr)[_w]), _mask); \ +} while(0) + +#define bitlock_acquire(arr,pos) bitlock_acquire_block(arr,pos,{},{}) + +// calls yield if cannot acquire the lock +#define bitlock_yield_acquire(arr,pos) bitlock_acquire_block(arr,pos,sched_yield();,{}) + +// Block until we get the lock or someone else does +// sets the memory pointed to by retptr to 1 if we got the lock, 0 otherwise +#define bitlock_try_acquire(arr,pos,retptr) do { \ + *(retptr) = 1; /* default to success, set to zero if locked */ \ + bitlock_acquire_block(arr,pos,{*(retptr)=0;break;},if(!*(retptr)){break;}); \ +} while(0) + +/* + * Byteswapping + */ + +/* clang uses these to check for features */ +#ifndef __has_feature +#define __has_feature(x) 0 +#endif + +#ifndef __has_builtin +#define __has_builtin(x) 0 +#endif + +/* GCC versions < 4.3 do not have __builtin_bswapX() */ +#if ( defined(__clang__) && !__has_builtin(__builtin_bswap64) ) || \ + ( !defined(__clang__) && defined(__GNUC__) && defined(__GNUC_MINOR__) && \ + ( (__GNUC__ < 4) || (__GNUC__ == 4 && __GNUC_MINOR__ < 3)) ) + #define byteswap64(x) ( (((uint64_t)(x) << 56)) | \ + (((uint64_t)(x) << 40) & 0xff000000000000ULL) | \ + (((uint64_t)(x) << 24) & 0xff0000000000ULL) | \ + (((uint64_t)(x) << 8) & 0xff00000000ULL) | \ + (((uint64_t)(x) >> 8) & 0xff000000ULL) | \ + (((uint64_t)(x) >> 24) & 0xff0000ULL) | \ + (((uint64_t)(x) >> 40) & 0xff00ULL) | \ + (((uint64_t)(x) >> 56)) ) + + #define byteswap32(x) ( (((uint32_t)(x) << 24)) | \ + (((uint32_t)(x) << 8) & 0xff0000U) | \ + (((uint32_t)(x) >> 8) & 0xff00U) | \ + (((uint32_t)(x) >> 24)) ) + + /* uint16_t type might be bigger than 2 bytes, so need to mask */ + #define byteswap16(x) ( (((uint16_t)(x) & 0xff) << 8) | \ + (((uint16_t)(x) >> 8) & 0xff) ) +#else + #define byteswap64(x) __builtin_bswap64(x) + #define byteswap32(x) __builtin_bswap64(x) + #define byteswap16(x) __builtin_bswap64(x) +#endif + +#endif /* BITLOCK_H_ */ diff --git a/datalink814_ge/src/common.c b/datalink814_ge/src/common.c new file mode 100644 index 0000000..67ce4eb --- /dev/null +++ b/datalink814_ge/src/common.c @@ -0,0 +1,44 @@ +/*****************************************************************************/ +/** + * Description: Common functions + * + * Date: 2021-11-16 00:08 + * LastEditors: Fan Hao + * LastEditTime: 2022-07-16 17:13 + * Revisions: Rev 0.1 + * History: + * [2022-07-16]: New branch for Dijian. + * [2021-11-16]: Initial version. + * + * Copyright(c) 2021 Beijing Institute of Technology. + * Lab of Communication and Networking + * + ******************************************************************************/ + +/***************************** Include Files *********************************/ +#include "common.h" +#include "error.h" +#include "util/util.h" +#include "util/util.h" + +/************************** Constant Definitions *****************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/**************************** Type Definitions *******************************/ + +/************************** Variable Definitions *****************************/ + +/*****************************************************************************/ +/** + * @brief + * + * @param + * + * @return + * + ******************************************************************************/ +void AppAssert(const char * file, int line){ + DBG_PRINT("in %s #%4d [assert] ",file, line); + while(1); +} diff --git a/datalink814_ge/src/common.h b/datalink814_ge/src/common.h new file mode 100644 index 0000000..ab7b523 --- /dev/null +++ b/datalink814_ge/src/common.h @@ -0,0 +1,81 @@ +/*****************************************************************************/ +/** + * Description: Common definitions + * + * Date: 2021-12-04 16:32 + * LastEditors: Fan Hao + * LastEditTime: 2022-07-16 17:13 + * Revisions: Rev 0.1 + * History: + * [2022-07-16]: New branch for Dijian. + * [2021-11-16]: Initial version. + * + * Copyright(c) 2021 Beijing Institute of Technology. + * Lab of Communication and Networking + * + ******************************************************************************/ +/***************************** Include Files *********************************/ +#ifndef DATAKINK_COMMON_H_ +#define DATAKINK_COMMON_H_ +#include +#include +#include +#include +#include "util/util.h" +#include "error.h" + +/************************** Constant Definitions *****************************/ +/***************** Macros (Inline Functions) Definitions *********************/ +#define __PRINT_BLOCK(block) do {\ + block\ +} while(0) + +#define ASSERT(exp) ((exp) ? (void)0 : AppAssert(__FILE__, __LINE__)) +#define _nop_() __asm__("nop") + +/* Stringify */ +#define STR(x) #x + +//#define _814_DEBUG_LEVEL 3 + +#if _814_DEBUG_LEVEL > 0 +#define DBG_PRINT(...) printf(__VA_ARGS__) +#endif +#if _814_DEBUG_LEVEL >= 1 +#define DBG_ERROR(...) __PRINT_BLOCK( \ + printf("in"__FILE__" #%4d [error]\t",__LINE__); \ + printf(__VA_ARGS__); \ +) +#endif +#if _814_DEBUG_LEVEL >= 2 +#define DBG_WARNING(...) __PRINT_BLOCK( \ + printf("[warning]\t"); \ + printf(__VA_ARGS__); \ +) +#endif +#if _814_DEBUG_LEVEL >= 3 +#define DBG_INFO(...) __PRINT_BLOCK( \ + printf("[Info]\t"); \ + printf(__VA_ARGS__); \ +) +#endif + +#ifndef DBG_ERROR +#define DBG_ERROR(...) {} +#endif +#ifndef DBG_WARNING +#define DBG_WARNING(...) {} +#endif +#ifndef DBG_INFO +#define DBG_INFO(...) {} +#endif +#ifndef DBG_PRINT +#define DBG_PRINT(...) {} +#endif +/**************************** Type Definitions *******************************/ + +/************************** Variable Definitions *****************************/ + +/************************** Function Prototypes ******************************/ +void AppAssert(const char * file, int line); +#endif /* COMMON_H_ */ diff --git a/datalink814_ge/src/config/app_config.h b/datalink814_ge/src/config/app_config.h new file mode 100644 index 0000000..48f3768 --- /dev/null +++ b/datalink814_ge/src/config/app_config.h @@ -0,0 +1,77 @@ +/*****************************************************************************/ +/** + * Description: Global configurations. + * + * Date: 2021-04-28 13:19 + * Last Editors: Fan Hao + * Last Edit Time: [2022-05-23 20:32] + * + * Revisions: Rev 0.0 + * History: + * [2021-04-28]: Initial edition. + * + * Copyright(c) 2021 Beijing Institute of Technology. + * Lab of Communication and Networking + * + ******************************************************************************/ + +#ifndef CONFIG_H_ +#define CONFIG_H_ + +#define XILINX_PLATFORM + +#include "xparameters.h" + +/******** MPC Status Configuration ********/ +#define _MPC_CTRL +#define _MPC_PCIE + +/******** Software Version Switch ********/ +#define _EX_VER + +/*********** Debug Info Level ************/ + #define _814_DEBUG_LEVEL -1 +// 3 - print all debug info +// 2 - print warnings and errors +// 1 - print only errors +// other - print nothing +#define FRAME_MSB_FIRST_ +/*********** Indoor Test Mode ************/ +#define PHY_BEAM_SET_PRESET +#define PHY_BEAM_FORMING_ENABLE + +// Physical layer instance coindig +#define PHY_CTRL_BASEADDR XPAR_PHYC_BASEADDR +#define ANTCONFIG_BRAM_ID XPAR_PHY_DATA_INTERFACE_ANT_INFO_BRAM_CTRL_DEVICE_ID +#define TXBUFF_BRAM_ID XPAR_PHY_DATA_INTERFACE_TX_FRAME_BRAM_CTRL_DEVICE_ID +#define RXBUFF_BRAM_ID XPAR_PHY_DATA_INTERFACE_RX_FRAME_BRAM_CTRL_DEVICE_ID +#define MPC_PCIE_BRAM_ID XPAR_MPC_BRAM_INTERFACE_MPC_BRAM_CTRL_DEVICE_ID + +// Time controller config +#define TIME_CONTROLLER_BASEADDR XPAR_TMC_BASEADDR +/************ Hardware Configs ************/ +#define CPU_CLK_HZ XPAR_CPU_CORTEXA9_CORE_CLOCK_FREQ_HZ +#define FCLK_CLK0_HZ 125000000 + +/********* Zynq Platform Configs **********/ +// Device ID Configs +#define SCUGIC_DEVICE_ID XPAR_SCUGIC_0_DEVICE_ID +#define PHY_DEVICE_ID 0 + +// Interrupt Configs +#define PERIODIC_5MS_INTR_ID XPAR_FABRIC_PHY_5MS_DELAY_2MS_INTR +#define MPC_RX_DONE_INTR_ID XPAR_FABRIC_MPC_IRQ_INTR +#define MPC_BUFFER_LENGTH (XPAR_MPC_BRAM_INTERFACE_MPC_BRAM_CTRL_S_AXI_HIGHADDR \ + - XPAR_MPC_BRAM_INTERFACE_MPC_BRAM_CTRL_S_AXI_BASEADDR) + +// Test Mode Configs +//#define DATA_ERROR_TEST // fill 1.2M frames with 0xCC +#define TEST_200KBPS // set all mgmt svc tsync frame as 200KBPS + +// Configuration Check +#if defined(PHY_BEAM_SET_PRESET) && !defined(PHY_BEAM_FORMING_ENABLE) +#define L2_BEAM_FORMING_ENABLE +#warning To impliment beam scan must enable beam forming... +#endif + +#endif diff --git a/datalink814_ge/src/config/platform.c b/datalink814_ge/src/config/platform.c new file mode 100644 index 0000000..364f8ce --- /dev/null +++ b/datalink814_ge/src/config/platform.c @@ -0,0 +1,110 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2015 Xilinx, Inc. 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. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +#include "xparameters.h" +#include "xil_cache.h" +#include "platform_config.h" + +/* + * Uncomment one of the following two lines, depending on the target, + * if ps7/psu init source files are added in the source directory for + * compiling example outside of SDK. + */ +/*#include "ps7_init.h"*/ +/*#include "psu_init.h"*/ + +#ifdef STDOUT_IS_16550 + #include "xuartns550_l.h" + + #define UART_BAUD 9600 +#endif + +void +enable_caches() +{ +#ifdef __PPC__ + Xil_ICacheEnableRegion(CACHEABLE_REGION_MASK); + Xil_DCacheEnableRegion(CACHEABLE_REGION_MASK); +#elif __MICROBLAZE__ +#ifdef XPAR_MICROBLAZE_USE_ICACHE + Xil_ICacheEnable(); +#endif +#ifdef XPAR_MICROBLAZE_USE_DCACHE + Xil_DCacheEnable(); +#endif +#endif +} + +void +disable_caches() +{ +#ifdef __MICROBLAZE__ +#ifdef XPAR_MICROBLAZE_USE_DCACHE + Xil_DCacheDisable(); +#endif +#ifdef XPAR_MICROBLAZE_USE_ICACHE + Xil_ICacheDisable(); +#endif +#endif +} + +void +init_uart() +{ +#ifdef STDOUT_IS_16550 + XUartNs550_SetBaud(STDOUT_BASEADDR, XPAR_XUARTNS550_CLOCK_HZ, UART_BAUD); + XUartNs550_SetLineControlReg(STDOUT_BASEADDR, XUN_LCR_8_DATA_BITS); +#endif + /* Bootrom/BSP configures PS7/PSU UART to 115200 bps */ +} + +void +init_platform() +{ + /* + * If you want to run this example outside of SDK, + * uncomment one of the following two lines and also #include "ps7_init.h" + * or #include "ps7_init.h" at the top, depending on the target. + * Make sure that the ps7/psu_init.c and ps7/psu_init.h files are included + * along with this example source files for compilation. + */ + /* ps7_init();*/ + /* psu_init();*/ + enable_caches(); + init_uart(); +} + +void +cleanup_platform() +{ + disable_caches(); +} diff --git a/datalink814_ge/src/config/platform.h b/datalink814_ge/src/config/platform.h new file mode 100644 index 0000000..e273e37 --- /dev/null +++ b/datalink814_ge/src/config/platform.h @@ -0,0 +1,41 @@ +/****************************************************************************** +* +* Copyright (C) 2008 - 2014 Xilinx, Inc. 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. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +#ifndef __PLATFORM_H_ +#define __PLATFORM_H_ + +#include "platform_config.h" + +void init_platform(); +void cleanup_platform(); + +#endif diff --git a/datalink814_ge/src/config/platform_config.h b/datalink814_ge/src/config/platform_config.h new file mode 100644 index 0000000..e2fd813 --- /dev/null +++ b/datalink814_ge/src/config/platform_config.h @@ -0,0 +1,7 @@ +#ifndef __PLATFORM_CONFIG_H_ +#define __PLATFORM_CONFIG_H_ + +#define STDOUT_IS_PS7_UART +#define UART_DEVICE_ID 0 + +#endif diff --git a/datalink814_ge/src/error.h b/datalink814_ge/src/error.h new file mode 100644 index 0000000..d6edeeb --- /dev/null +++ b/datalink814_ge/src/error.h @@ -0,0 +1,31 @@ +#ifndef DATAKINK_ERROR_H_ +#define DATAKINK_ERROR_H_ + +#include + +/******************************************************************************/ +/********************** Macros and Constants Definitions **********************/ +/******************************************************************************/ + +#ifdef SUCCESS +#undef SUCCESS +#endif +#define SUCCESS 0 +#ifdef FAILURE +#undef FAILURE +#endif +#define FAILURE -1 + +#define EPARAM -2 /*!< Data crc check failed */ +#define ECRC -3 /*!< Data crc check failed */ +#define EDINVAL -4 /*!< Device is invalid (sleep or power off) */ +#define EDCONF -5 /*!< Device confugure error */ +#define ETIMEOUT -6 /*!< Timeout error */ +#define EIGNORE -7 /*!< Received an unsupported command, and ignore it */ +#define EQUEUE -8 /*!< Queue overflow */ +#define EALLOC -9 /*!< Failed to allocate memory */ +#define EUNEXP -10 /*!< Encounter an unexpected error */ + +// #define IS_ERR_VALUE(x) ((x) != SUCCESS) + +#endif // ERROR_H_ diff --git a/datalink814_ge/src/hardware/common.c b/datalink814_ge/src/hardware/common.c new file mode 100644 index 0000000..c4323b2 --- /dev/null +++ b/datalink814_ge/src/hardware/common.c @@ -0,0 +1,275 @@ +/** + * \file common.c + * \brief Contains Mykonos API common wrapper functions for user hardware platform drivers + */ + +/** +* \page Disclaimer Legal Disclaimer +* Copyright 2015-2017 Analog Devices Inc. +* Released under the AD9371 API license, for more information see the "LICENSE.txt" file in this zip file. +* +*/ + +#include +#include +#include +#include +#include +#include "common.h" +#include "platform_drivers.h" +#include "parameters.h" + +ADI_LOGLEVEL CMB_LOGLEVEL = ADIHAL_LOG_NONE; + +static uint32_t _desired_time_to_elapse_us = 0; +struct spi_desc *spi_ad_desc; +struct gpio_desc *gpio_ad9371_resetb; +struct gpio_desc *gpio_ad9528_resetb; +struct gpio_desc *gpio_ad9528_sysref_req; + +commonErr_t CMB_initPlatform(void) +{ + struct spi_init_param spi_param; + int32_t status = COMMONERR_OK; + + status |= gpio_get(&gpio_ad9371_resetb, AD9371_RESET_B); + status |= gpio_get(&gpio_ad9528_resetb, AD9528_RESET_B); + status |= gpio_get(&gpio_ad9528_sysref_req, AD9528_SYSREF_REQ); + + spi_param.id = 0; + spi_param.mode = SPI_MODE_0; + spi_param.chip_select = AD9371_CS; + spi_param.max_speed_hz = 25000000u; + + status |= spi_init(&spi_ad_desc, &spi_param); + + if (status != SUCCESS) { + return COMMONERR_FAILED; + } + + return COMMONERR_OK; +} + +commonErr_t CMB_closeHardware(void) +{ + return(COMMONERR_OK); +} + +commonErr_t CMB_setGPIO(uint32_t GPIO) +{ + return(COMMONERR_OK); +} + +commonErr_t CMB_hardReset(uint8_t spiChipSelectIndex) +{ + struct gpio_desc *reset_gpio; + + switch (spiChipSelectIndex) { + case AD9371_CS: + reset_gpio = gpio_ad9371_resetb; + break; + case AD9528_CS: + reset_gpio = gpio_ad9528_resetb; + break; + default: + return(COMMONERR_FAILED); + } + + gpio_direction_output(reset_gpio, 1); + CMB_wait_ms(1); + gpio_direction_output(reset_gpio, 0); + CMB_wait_ms(1); + gpio_direction_output(reset_gpio, 1); + CMB_wait_ms(1); + + return(COMMONERR_OK); +} + +commonErr_t CMB_setSPIOptions(spiSettings_t *spiSettings) +{ + return(COMMONERR_OK); +} + +commonErr_t CMB_setSPIChannel(uint16_t chipSelectIndex ) +{ + return(COMMONERR_OK); +} + +commonErr_t CMB_SPIWriteByte(spiSettings_t *spiSettings, uint16_t addr, + uint8_t data) +{ + uint8_t buf[3]; + + spi_ad_desc->chip_select = spiSettings->chipSelectIndex - 1; + + buf[0] = (uint8_t) ((addr >> 8) & 0x7f); + buf[1] = (uint8_t) (addr & 0xff); + buf[2] = (uint8_t) data; + + spi_write_and_read(spi_ad_desc, buf, 3); + + return(COMMONERR_OK); +} + +commonErr_t CMB_SPIWriteBytes(spiSettings_t *spiSettings, uint16_t *addr, + uint8_t *data, uint32_t count) +{ + uint32_t index; + + for (index = 0; index < count; index++) + if (CMB_SPIWriteByte(spiSettings, *(addr + index), + *(data + index)) != COMMONERR_OK) + return(COMMONERR_FAILED); + + return(COMMONERR_OK); +} + +commonErr_t CMB_SPIReadByte(spiSettings_t *spiSettings, uint16_t addr, + uint8_t *readdata) +{ + uint8_t buf[3]; + + spi_ad_desc->chip_select = spiSettings->chipSelectIndex - 1; + + buf[0] = (uint8_t) ((addr >> 8) | 0x80); + buf[1] = (uint8_t) (addr & 0xff); + buf[2] = (uint8_t) 0x00; + + spi_write_and_read(spi_ad_desc, buf, 3); + *readdata = buf[2]; + + return(COMMONERR_OK); +} + +commonErr_t CMB_SPIWriteField(spiSettings_t *spiSettings, uint16_t addr, + uint8_t field_val, uint8_t mask, uint8_t start_bit) +{ + uint8_t data; + + if (CMB_SPIReadByte(spiSettings, addr, &data) != COMMONERR_OK) + return(COMMONERR_FAILED); + + data = (data & ~mask) | ((field_val << start_bit) & mask); + + if (CMB_SPIWriteByte(spiSettings, addr, data) != COMMONERR_OK) + return(COMMONERR_FAILED); + + return(COMMONERR_OK); +} + +/* read a field in a single register space (not multibyte fields) */ +commonErr_t CMB_SPIReadField(spiSettings_t *spiSettings, uint16_t addr, + uint8_t *field_val, uint8_t mask, uint8_t start_bit) +{ + uint8_t data; + + if (CMB_SPIReadByte(spiSettings, addr, &data) != COMMONERR_OK) + return(COMMONERR_FAILED); + + data = (data & mask) >> start_bit; + *field_val = data; + + return(COMMONERR_OK); +} + + +commonErr_t CMB_writeToLog(ADI_LOGLEVEL level, uint8_t deviceIndex, + uint32_t errorCode, const char *comment) +{ + + if((CMB_LOGLEVEL & ADIHAL_LOG_ERROR) && (level == ADIHAL_LOG_ERROR)) { + printf("ERROR: %d: %s", (int)errorCode, comment); + } else if((CMB_LOGLEVEL & ADIHAL_LOG_WARNING) + && (level == ADIHAL_LOG_WARNING)) { + printf("WARNING: %d: %s",(int)errorCode, comment); + } else if((CMB_LOGLEVEL & ADIHAL_LOG_MESSAGE) + && (level == ADIHAL_LOG_MESSAGE)) { + printf("MESSAGE: %d: %s",(int)errorCode, comment); + } else if(CMB_LOGLEVEL == ADIHAL_LOG_NONE ) { + //printf("MESSAGE: %d: %s",(int)errorCode, comment); + } else { + printf("Undefined Log Level: 0x%X", level); + } + + return(COMMONERR_OK); +} + +/* if filename null, a default path will be used in logging.c */ +commonErr_t CMB_openLog(const char *filename) +{ + return(COMMONERR_OK); +} + +commonErr_t CMB_closeLog(void) +{ + return(COMMONERR_OK); +} + +commonErr_t CMB_flushLog(void) +{ + return(COMMONERR_OK); +} + +commonErr_t CMB_wait_ms(uint32_t time_ms) +{ + mdelay(time_ms); + + return(COMMONERR_OK); +} + +commonErr_t CMB_wait_us(uint32_t time_us) +{ + udelay(time_us); + + return(COMMONERR_OK); +} + +commonErr_t CMB_setTimeout_ms(uint32_t timeOut_ms) +{ +#ifdef _XPARAMETERS_PS_H_ + _desired_time_to_elapse_us = timeOut_ms * 1000; +#else + _desired_time_to_elapse_us = timeOut_ms * 50; // FIXME +#endif + + return(COMMONERR_OK); +} + +commonErr_t CMB_setTimeout_us(uint32_t timeOut_us) +{ + _desired_time_to_elapse_us = timeOut_us; + + return(COMMONERR_OK); +} + + +commonErr_t CMB_hasTimeoutExpired() +{ + udelay(1); + + _desired_time_to_elapse_us--; + if (_desired_time_to_elapse_us > 0) + return(COMMONERR_OK); + + return(COMMONERR_FAILED); +} + +commonErr_t CMB_regRead(uint32_t offset, uint32_t *data) +{ + return(COMMONERR_OK); +} + +commonErr_t CMB_regWrite(uint32_t offset, uint32_t data) +{ + return(COMMONERR_OK); +} + +commonErr_t CMB_memRead(uint32_t offset, uint32_t *data, uint32_t len) +{ + return(COMMONERR_OK); +} + +commonErr_t CMB_memWrite(uint32_t offset, uint32_t *data, uint32_t len) +{ + return(COMMONERR_OK); +} diff --git a/datalink814_ge/src/hardware/common.h b/datalink814_ge/src/hardware/common.h new file mode 100644 index 0000000..785217d --- /dev/null +++ b/datalink814_ge/src/hardware/common.h @@ -0,0 +1,131 @@ +/** + * \file common.h + * \brief Contains type definitions and prototype declarations for common.c + */ + +/** +* \page Disclaimer Legal Disclaimer +* Copyright 2015-2017 Analog Devices Inc. +* Released under the AD9371 API license, for more information see the "LICENSE.txt" file in this zip file. +* +*/ + +#ifndef _COMMON_H_ +#define _COMMON_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* build project settings include the path to the desired platform folder for correct includes */ +#include "stdint.h" + +#define THROW_ERROR() + +#define SPIARRAYSIZE 1024 + +/* assuming 3 byte SPI message - integer math enforces floor() */ +#define SPIARRAYTRIPSIZE ((SPIARRAYSIZE / 3) * 3) + +/*======================================== + * Enums and structures + *=======================================*/ +/* proposed to increase number of error return values to make unique for each return */ +typedef enum +{ + ADIERR_OK=0, + ADIERR_INV_PARM, + ADIERR_FAILED +} ADI_ERR; + +/*!< \brief COMMON layer error reporting enumerated types */ +typedef enum +{ + COMMONERR_OK=0, + COMMONERR_FAILED +} commonErr_t; + +/* bit 0 is MESSAGE, bit 1 is WARNING, bit 2 is ERROR */ +typedef enum +{ + ADIHAL_LOG_NONE = 0x0, + ADIHAL_LOG_MESSAGE = 0x1, + ADIHAL_LOG_WARNING = 0x2, + ADIHAL_LOG_ERROR = 0x4, + ADIHAL_LOG_SPI = 0x8, + ADIHAL_LOG_AXI_REG = 0x10, + ADIHAL_LOG_AXI_MEM = 0x20, + ADIHAL_LOG_ALL = 0x3F +} ADI_LOGLEVEL; + +/** + * \brief Data structure to hold SPI settings for all system device types + */ +typedef struct +{ + uint8_t chipSelectIndex; ///< valid 1~8 + uint8_t writeBitPolarity; ///< the level of the write bit of a SPI write instruction word, value is inverted for SPI read operation + uint8_t longInstructionWord; ///< 1 = 16bit instruction word, 0 = 8bit instruction word + uint8_t MSBFirst; ///< 1 = MSBFirst, 0 = LSBFirst + uint8_t CPHA; ///< clock phase, sets which clock edge the data updates (valid 0 or 1) + uint8_t CPOL; ///< clock polarity 0 = clock starts low, 1 = clock starts high + uint8_t enSpiStreaming; ///< Not implemented. SW feature to improve SPI throughput. + uint8_t autoIncAddrUp; ///< Not implemented. For SPI Streaming, set address increment direction. 1= next addr = addr+1, 0:addr = addr-1 + uint8_t fourWireMode; ///< 1: Use 4-wire SPI, 0: 3-wire SPI (SDIO pin is bidirectional). NOTE: ADI's FPGA platform always uses 4-wire mode. + uint32_t spiClkFreq_Hz; ///< SPI Clk frequency in Hz (default 25000000), platform will use next lowest frequency that it's baud rate generator can create */ + +} spiSettings_t; + +/* global variable so application layer can set the log level */ +extern ADI_LOGLEVEL CMB_LOGLEVEL; +extern struct spi_desc *spi_ad_desc; +extern struct gpio_desc *gpio_ad9371_resetb; +extern struct gpio_desc *gpio_ad9528_resetb; +extern struct gpio_desc *gpio_ad9528_sysref_req; + +/* initialize hardware platform */ +commonErr_t CMB_initPlatform(void); + +/* close hardware pointers */ +commonErr_t CMB_closeHardware(void); + +/* GPIO function */ +commonErr_t CMB_setGPIO(uint32_t GPIO); + +/* hardware reset function */ +commonErr_t CMB_hardReset(uint8_t spiChipSelectIndex); + +/* SPI read/write functions */ +commonErr_t CMB_setSPIOptions(spiSettings_t *spiSettings); /* allows the platform HAL to work with devices with various SPI settings */ +commonErr_t CMB_setSPIChannel(uint16_t chipSelectIndex ); /* value of 0 deasserts all chip selects */ +commonErr_t CMB_SPIWriteByte(spiSettings_t *spiSettings, uint16_t addr, uint8_t data); /* single SPI byte write function */ +commonErr_t CMB_SPIWriteBytes(spiSettings_t *spiSettings, uint16_t *addr, uint8_t *data, uint32_t count); +commonErr_t CMB_SPIReadByte (spiSettings_t *spiSettings, uint16_t addr, uint8_t *readdata); /* single SPI byte read function */ +commonErr_t CMB_SPIWriteField(spiSettings_t *spiSettings, uint16_t addr, uint8_t field_val, uint8_t mask, uint8_t start_bit); /* write a field in a single register */ +commonErr_t CMB_SPIReadField (spiSettings_t *spiSettings, uint16_t addr, uint8_t *field_val, uint8_t mask, uint8_t start_bit); /* read a field in a single register */ + +/* platform timer functions */ +commonErr_t CMB_wait_ms(uint32_t time_ms); +commonErr_t CMB_wait_us(uint32_t time_us); +commonErr_t CMB_setTimeout_ms(uint32_t timeOut_ms); +commonErr_t CMB_setTimeout_us(uint32_t timeOut_us); +commonErr_t CMB_hasTimeoutExpired(); + +/* platform logging functions */ +commonErr_t CMB_openLog(const char *filename); +commonErr_t CMB_closeLog(void); +commonErr_t CMB_writeToLog(ADI_LOGLEVEL level, uint8_t deviceIndex, uint32_t errorCode, const char *comment); +commonErr_t CMB_flushLog(void); + +/* platform FPGA AXI register read/write functions */ +commonErr_t CMB_regRead(uint32_t offset, uint32_t *data); +commonErr_t CMB_regWrite(uint32_t offset, uint32_t data); + +/* platform DDR3 memory read/write functions */ +commonErr_t CMB_memRead(uint32_t offset, uint32_t *data, uint32_t len); +commonErr_t CMB_memWrite(uint32_t offset, uint32_t *data, uint32_t len); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/datalink814_ge/src/hardware/headless.c b/datalink814_ge/src/hardware/headless.c new file mode 100644 index 0000000..c521ff2 --- /dev/null +++ b/datalink814_ge/src/hardware/headless.c @@ -0,0 +1,1140 @@ +/***************************************************************************//** + * @file ad9371/src/app/headless.c + * @brief Implementation of Main Function. +******************************************************************************** + * Copyright 2017(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +/***************************** Include Files ********************************/ +#include "headless.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Variable Definitions *****************************/ + +//XGpio GpioFreqCtrl; +//XGpio GpioGainCtrl; +//XGpio GpioAttnCtrl; +XScuGic Intc; + +/************************** Function Prototypes ******************************/ + +int HARDWARE_initialize() +{ + int Status; + + // use configuration + mykDevice.rx->rxPllLoFrequency_Hz = 2500000000u; + mykDevice.tx->txPllLoFrequency_Hz = 2500000000u; + mykDevice.tx->tx1Atten_mdB = 20000; + mykDevice.tx->tx2Atten_mdB = 20000; + + Status = HARDWARE_ad9371Config(); + + if (Status != ADIERR_OK){ + return ADIERR_FAILED; + } + +// /**********************************************************/ +// /************ AD9371 Dynamical Reconfiguration ************/ +// /**********************************************************/ +// Status = HW_ad9371DynamicCfgInit(); +// if (Status != ADIERR_OK){ +// xil_printf("HW:: AD9371 dynamic configuration initialization failed!\n"); +// return ADIERR_FAILED; +// } +// +// xil_printf("HW:: AD9371 ready to be reconfigured!\n"); +// +// // main loop +// while(1); + + // never reach + return ADIERR_OK; +} + +// this function is NOT safe +int HARDWARE_ad9371Config(void) +{ + int Status; + uint8_t reg508; + uint8_t framerStatus; + uint8_t obsFramerStatus; + uint8_t deframerStatus; + + xil_printf("main: Hello\n"); + + /**********************************************************/ + /*********** Initialize Configuration Interface ***********/ + /**********************************************************/ + Status = CMB_initPlatform(); + if (Status != ADIERR_OK){ + return ADIERR_FAILED; + } + + Status = HW_adiCfgProfileInit(); + if (Status != ADIERR_OK){ + return ADIERR_FAILED; + } + + xil_printf("HW:: Initialize configuration interface done!\n"); + + /**********************************************************/ + /****************** AD9528 Configuration ******************/ + /**********************************************************/ + Status = HW_9528Config(ad9528Init); + if (Status != ADIERR_OK){ + return ADIERR_FAILED; + } + + xil_printf("HW:: AD9528 configuration done!\n"); + + Status = HW_9528GetLockStatus(ad9528Init, ®508); + if (Status != ADIERR_OK){ + return ADIERR_FAILED; + } + + xil_printf("HW:: AD9528 REG508: 0x%02x \n",reg508); + + /**********************************************************/ + /****************** AD9371 Configuration ******************/ + /**********************************************************/ + Status = HW_9371Config(ad9528Init, &mykDevice); + if (Status != ADIERR_OK){ + return ADIERR_FAILED; + } + + Status = HW_9371CheckJesdStatus(&mykDevice, &framerStatus, + &obsFramerStatus, &deframerStatus); + if (Status != ADIERR_OK){ + return ADIERR_FAILED; + } + else { + // typical value: 0x3E + printf("HW:: RxFramerStatus = 0x%x\n", framerStatus); + // typical value: 0x3E + printf("HW:: OrxFramerStatus = 0x%x\n", obsFramerStatus); + // typical value: 0x28 + printf("HW:: DeframerStatus = 0x%x\n", deframerStatus); + } + + xil_printf("HW:: All configuration done!\n"); + + return ADIERR_OK; +} + +// this function is NOT safe +//int HW_ad9371DynamicCfgInit(void) +//{ +// int Status; +// +// Status = HW_setupIntrSystem(INTC_DEVICE_ID, &Intc); +// if (Status != XST_SUCCESS) { +// printf("HW: HW_setupIntrSystem() failed!\n"); +// return XST_FAILURE; +// } +// +// Status = XGpio_Initialize(&GpioFreqCtrl, FREQ_CTRL_DEVICE_ID); +// Status |= XGpio_Initialize(&GpioGainCtrl, GAIN_CTRL_DEVICE_ID); +// Status |= XGpio_Initialize(&GpioAttnCtrl, ATTN_CTRL_DEVICE_ID); +// if (Status != XST_SUCCESS) { +// printf("HW: GPIO init failed!\n"); +// return XST_FAILURE; +// } +// +// /* Set the direction for all signals as inputs. */ +// XGpio_SetDataDirection(&GpioFreqCtrl, AXI_GPIO_BANK_1, 0xFFFFFFFF); +// XGpio_SetDataDirection(&GpioFreqCtrl, AXI_GPIO_BANK_2, 0xFFFFFFFF); +// +// XGpio_SetDataDirection(&GpioGainCtrl, AXI_GPIO_BANK_1, 0xFFFFFFFF); +// XGpio_SetDataDirection(&GpioGainCtrl, AXI_GPIO_BANK_2, 0xFFFFFFFF); +// +// XGpio_SetDataDirection(&GpioAttnCtrl, AXI_GPIO_BANK_1, 0xFFFFFFFF); +// XGpio_SetDataDirection(&GpioAttnCtrl, AXI_GPIO_BANK_2, 0xFFFFFFFF); +// +// Status = HW_connectIntr(&Intc, FREQ_CTRL_INTR_ID, +// (Xil_InterruptHandler)FreqIntrHandler, &GpioFreqCtrl, 0xA0, 0x3); +// Status |= HW_connectIntr(&Intc, GAIN_CTRL_INTR_ID, +// (Xil_InterruptHandler)GainIntrHandler, &GpioGainCtrl, 0xA0, 0x3); +// Status |= HW_connectIntr(&Intc, ATTN_CTRL_INTR_ID, +// (Xil_InterruptHandler)AttnIntrHandler, &GpioAttnCtrl, 0xA0, 0x3); +// +// XGpio_InterruptEnable(&GpioFreqCtrl, XGPIO_IR_MASK); +// XGpio_InterruptGlobalEnable(&GpioFreqCtrl); +// +// XGpio_InterruptEnable(&GpioGainCtrl, XGPIO_IR_MASK); +// XGpio_InterruptGlobalEnable(&GpioGainCtrl); +// +// XGpio_InterruptEnable(&GpioAttnCtrl, XGPIO_IR_MASK); +// XGpio_InterruptGlobalEnable(&GpioAttnCtrl); +// +// return XST_SUCCESS; +//} + +/*****************************************************************************/ +/* +* +* This function setups the interrupt system. +* +* @param DeviceId is the unique identifier for a GIC device. +* @param GicPtr is a pointer to the instance of the INTC. +* +* @return +* - XST_SUCCESS if successful, +* - XST_FAILURE.if not succesful +* +* @note None. +* +******************************************************************************/ +int HW_setupIntrSystem(u16 DeviceId, XScuGic * GicPtr) +{ + int Status; + XScuGic_Config *CfgPtr; + + /* + * Initialize the interrupt controller driver so that it is ready to + * use. + */ + CfgPtr = XScuGic_LookupConfig(DeviceId); + if (!CfgPtr) { + xil_printf("No interrupt config found for %d\n", DeviceId); + return XST_FAILURE; + } + + Status = XScuGic_CfgInitialize(GicPtr, CfgPtr, CfgPtr->CpuBaseAddress); + if (Status != XST_SUCCESS) { + xil_printf("No interrupt config found for %d\n", DeviceId); + return XST_FAILURE; + } + + Xil_ExceptionInit(); + Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, + (Xil_ExceptionHandler)XScuGic_InterruptHandler, + (void *)GicPtr); + Xil_ExceptionEnable(); + + return XST_SUCCESS; +} + + +int HW_connectIntr(XScuGic *GicPtr,u32 IntrId,Xil_InterruptHandler Handler, + void *CallBackRef, u8 Priority, u8 Trigger) +{ + int Status; + // Register interrupt handler + Status = XScuGic_Connect(GicPtr, IntrId, (Xil_InterruptHandler)Handler, + CallBackRef); + if(Status != XST_SUCCESS) + { + return XST_FAILURE; + } + XScuGic_SetPriorityTriggerType(GicPtr, IntrId, Priority, Trigger); + + XScuGic_Enable(GicPtr, IntrId); + + return XST_SUCCESS; +} + + +int HW_adiCfgProfileInit(void) +{ + if (!ad9528Init) { + printf("Cannot find ad9528 configuration profile with name 'ad9528Init'!"); + return ADIERR_FAILED; + } + + if (!&mykDevice) { + printf("Cannot find ad9371 configuration profile with name 'mykDevice'!"); + return ADIERR_FAILED; + } + + ad9528Init->spiSettings->chipSelectIndex = AD9528_CS; + mykDevice.spiSettings->chipSelectIndex = AD9371_CS; + + mykDevice.rx->framer->serializerLanesEnabled = 0x03; + mykDevice.rx->framer->serializerLaneCrossbar = 0xE4; + mykDevice.obsRx->framer->serializerLanesEnabled = 0x04; + mykDevice.tx->deframer->deserializerLanesEnabled = 0x03; + mykDevice.tx->deframer->deserializerLaneCrossbar = 0xE4; + + return ADIERR_OK; +} + + +int HW_9528Config(ad9528Device_t *clockAD9528_device) +{ + ADI_ERR error; + /**************************************************************************/ + /***** System Clocks Initialization Initialization Sequence *****/ + /**************************************************************************/ + + /* Perform a hard reset on the AD9528 DUT */ + error = AD9528_resetDevice(clockAD9528_device); + if (error != ADIERR_OK) { + printf("AD9528_resetDevice() failed\n"); + return ADIERR_FAILED; + } + + error = AD9528_initDeviceDataStruct(clockAD9528_device, + clockAD9528_device->pll1Settings->vcxo_Frequency_Hz, + clockAD9528_device->pll1Settings->refA_Frequency_Hz, + clockAD9528_device->outputSettings->outFrequency_Hz[1]); + if (error != ADIERR_OK) { + printf("AD9528_initDeviceDataStruct() failed\n"); + return ADIERR_FAILED; + } + + /* Initialize the AD9528 by writing all SPI registers */ + error = AD9528_initialize(clockAD9528_device); + if (error != ADIERR_OK) { + printf("WARNING: AD9528_initialize() issues.\n"); + } + + return ADIERR_OK; +} + + +int HW_9528GetLockStatus(ad9528Device_t *device, uint8_t *reg508) +{ + ADI_ERR error; + + error = CMB_SPIReadByte(device->spiSettings, AD9528_ADDR_STATUS_READBACK0, reg508); + if (error != ADIERR_OK) { + printf("HW_9528GetLockStatus failed.\n"); + return ADIERR_FAILED; + } + + return ADIERR_OK; +} + + +int HW_9371Config(ad9528Device_t *clockAD9528_device, mykonosDevice_t *mykDevice) +{ + ADI_ERR error; + mykonosErr_t mykError; + const char *errorString; + uint8_t pllLockStatus; + uint8_t mcsStatus; + uint8_t arm_major; + uint8_t arm_minor; + uint8_t arm_release; + uint32_t initCalMask = TX_BB_FILTER | ADC_TUNER | TIA_3DB_CORNER | DC_OFFSET | + TX_ATTENUATION_DELAY | RX_GAIN_DELAY | FLASH_CAL | + PATH_DELAY | TX_LO_LEAKAGE_INTERNAL | TX_QEC_INIT | + LOOPBACK_RX_LO_DELAY | LOOPBACK_RX_RX_QEC_INIT | + RX_LO_DELAY | RX_QEC_INIT ; + uint8_t errorFlag = 0; + uint8_t errorCode = 0; + uint32_t initCalsCompleted; + uint32_t trackingCalMask = TRACK_ORX1_QEC | TRACK_ORX2_QEC | TRACK_RX1_QEC | + TRACK_RX2_QEC | TRACK_TX1_QEC | TRACK_TX2_QEC; + + /* Allocating memory for the errorString */ + errorString = NULL; + + + + /*************************************************************************/ + /***** Mykonos Initialization Sequence *****/ + /*************************************************************************/ + + /* Perform a hard reset on the MYKONOS DUT (Toggle RESETB pin on device) */ + if ((mykError = MYKONOS_resetDevice(mykDevice)) != MYKONOS_ERR_OK) { + errorString = getMykonosErrorMessage(mykError); + goto error_11; + } + + if ((mykError = MYKONOS_initialize(mykDevice)) != MYKONOS_ERR_OK) { + errorString = getMykonosErrorMessage(mykError); + goto error_11; + } + + /*************************************************************************/ + /***** Mykonos CLKPLL Status Check *****/ + /*************************************************************************/ + + if ((mykError = MYKONOS_checkPllsLockStatus(mykDevice, + &pllLockStatus)) != MYKONOS_ERR_OK) { + errorString = getMykonosErrorMessage(mykError); + goto error_11; + } + + /*************************************************************************/ + /***** Mykonos Perform MultiChip Sync *****/ + /*************************************************************************/ + + if ((mykError = MYKONOS_enableMultichipSync(mykDevice, 1, + &mcsStatus)) != MYKONOS_ERR_OK) { + errorString = getMykonosErrorMessage(mykError); + goto error_11; + } + + /* Minimum 3 SYSREF pulses from Clock Device has to be produced for MulticChip Sync */ + + AD9528_requestSysref(clockAD9528_device, 1); + mdelay(1); + AD9528_requestSysref(clockAD9528_device, 1); + mdelay(1); + AD9528_requestSysref(clockAD9528_device, 1); + mdelay(1); + AD9528_requestSysref(clockAD9528_device, 1); + mdelay(1); + + /*************************************************************************/ + /***** Mykonos Verify MultiChip Sync *****/ + /*************************************************************************/ + + if ((mykError = MYKONOS_enableMultichipSync(mykDevice, 0, + &mcsStatus)) != MYKONOS_ERR_OK) { + errorString = getMykonosErrorMessage(mykError); + goto error_11; + } + + if ((mcsStatus & 0x0B) == 0x0B) + printf("MCS successful\n"); + else + printf("MCS failed\n"); + + /*************************************************************************/ + /***** Mykonos Load ARM file *****/ + /*************************************************************************/ + + if (pllLockStatus & 0x01) { + printf("CLKPLL locked\n"); + if ((mykError = MYKONOS_initArm(mykDevice)) != MYKONOS_ERR_OK) { + errorString = getMykonosErrorMessage(mykError); + goto error_11; + } + + if ((mykError = MYKONOS_loadArmFromBinary(mykDevice, + &firmware_Mykonos_M3_bin[0], firmware_Mykonos_M3_bin_len)) != MYKONOS_ERR_OK) { + errorString = getMykonosErrorMessage(mykError); + goto error_11; + } + } else { + printf("CLKPLL not locked (0x%x)\n", pllLockStatus); + error = ADIERR_FAILED; + goto error_2; + } + + /* Read back the version of the ARM binary loaded into the Mykonos ARM memory */ + if ((mykError = MYKONOS_getArmVersion(mykDevice, &arm_major, &arm_minor, + &arm_release, NULL)) == MYKONOS_ERR_OK) + printf("AD9371 ARM version %d.%d.%d\n", arm_major, arm_minor, arm_release); + + /*************************************************************************/ + /***** Mykonos Set RF PLL Frequencies *****/ + /*************************************************************************/ + + if ((mykError = MYKONOS_setRfPllFrequency(mykDevice, RX_PLL, + mykDevice->rx->rxPllLoFrequency_Hz)) != MYKONOS_ERR_OK) { + errorString = getMykonosErrorMessage(mykError); + goto error_11; + } + + if ((mykError = MYKONOS_setRfPllFrequency(mykDevice, TX_PLL, + mykDevice->tx->txPllLoFrequency_Hz)) != MYKONOS_ERR_OK) { + errorString = getMykonosErrorMessage(mykError); + goto error_11; + } + + if ((mykError = MYKONOS_setRfPllFrequency(mykDevice, SNIFFER_PLL, + mykDevice->obsRx->snifferPllLoFrequency_Hz)) != MYKONOS_ERR_OK) { + errorString = getMykonosErrorMessage(mykError); + goto error_11; + } + + /* Wait 200ms for PLLs to lock */ + mdelay(200); + + if ((mykError = MYKONOS_checkPllsLockStatus(mykDevice, + &pllLockStatus)) != MYKONOS_ERR_OK) { + errorString = getMykonosErrorMessage(mykError); + goto error_11; + } + + if ((pllLockStatus & 0x0F) == 0x0F) + printf("PLLs locked\n"); + else { + printf("PLLs not locked (0x%x)\n", pllLockStatus); + error = ADIERR_FAILED; + goto error_2; + } + +// /*************************************************************************/ +// /***** Mykonos Set GPIOs *****/ +// /*************************************************************************/ +// +// if ((mykGpioErr = MYKONOS_setRx1GainCtrlPin(mykDevice, 0, 0, 0, 0, +// 0)) != MYKONOS_ERR_GPIO_OK) { +// errorString = getGpioMykonosErrorMessage(mykGpioErr); +// goto error_11; +// } +// +// if ((mykGpioErr = MYKONOS_setRx2GainCtrlPin(mykDevice, 0, 0, 0, 0, +// 0)) != MYKONOS_ERR_GPIO_OK) { +// errorString = getGpioMykonosErrorMessage(mykGpioErr); +// goto error_11; +// } +// +// if ((mykGpioErr = MYKONOS_setTx1AttenCtrlPin(mykDevice, 0, 0, 0, 0, +// 0)) != MYKONOS_ERR_GPIO_OK) { +// errorString = getGpioMykonosErrorMessage(mykGpioErr); +// goto error_11; +// } +// +// if ((mykGpioErr = MYKONOS_setTx2AttenCtrlPin(mykDevice, 0, 0, 0, +// 0)) != MYKONOS_ERR_GPIO_OK) { +// errorString = getGpioMykonosErrorMessage(mykGpioErr); +// goto error_11; +// } +// +// if ((mykGpioErr = MYKONOS_setupGpio(mykDevice)) != MYKONOS_ERR_GPIO_OK) { +// errorString = getGpioMykonosErrorMessage(mykGpioErr); +// goto error_11; +// } +// +// /*************************************************************************/ +// /***** Mykonos Set manual gains values *****/ +// /*************************************************************************/ +// +// if ((mykError = MYKONOS_setRx1ManualGain(mykDevice, 255)) != MYKONOS_ERR_OK) { +// errorString = getMykonosErrorMessage(mykError); +// goto error_11; +// } +// +// if ((mykError = MYKONOS_setRx2ManualGain(mykDevice, 255)) != MYKONOS_ERR_OK) { +// errorString = getMykonosErrorMessage(mykError); +// goto error_11; +// } +// +// if ((mykError = MYKONOS_setObsRxManualGain(mykDevice, OBS_RX1_TXLO, +// 255)) != MYKONOS_ERR_OK) { +// errorString = getMykonosErrorMessage(mykError); +// goto error_11; +// } +// +// if ((mykError = MYKONOS_setObsRxManualGain(mykDevice, OBS_RX2_TXLO, +// 255)) != MYKONOS_ERR_OK) { +// errorString = getMykonosErrorMessage(mykError); +// goto error_11; +// } +// +// if ((mykError = MYKONOS_setObsRxManualGain(mykDevice, OBS_SNIFFER_A, +// 255)) != MYKONOS_ERR_OK) { +// errorString = getMykonosErrorMessage(mykError); +// goto error_11; +// } +// +// if ((mykError = MYKONOS_setObsRxManualGain(mykDevice, OBS_SNIFFER_B, +// 255)) != MYKONOS_ERR_OK) { +// errorString = getMykonosErrorMessage(mykError); +// goto error_11; +// } +// +// if ((mykError = MYKONOS_setObsRxManualGain(mykDevice, OBS_SNIFFER_C, +// 255)) != MYKONOS_ERR_OK) { +// errorString = getMykonosErrorMessage(mykError); +// goto error_11; +// } +// +// /*************************************************************************/ +// /***** Mykonos Initialize attenuations *****/ +// /*************************************************************************/ +// +// mykError = MYKONOS_setTx1Attenuation(mykDevice, 10000); +// if (mykError != MYKONOS_ERR_OK) { +// errorString = getMykonosErrorMessage(mykError); +// goto error_11; +// } +// +// mykError = MYKONOS_setTx2Attenuation(mykDevice, 10000); +// if (mykError != MYKONOS_ERR_OK) { +// errorString = getMykonosErrorMessage(mykError); +// goto error_11; +// } + + /*************************************************************************/ + /***** Mykonos ARM Initialization Calibrations *****/ + /*************************************************************************/ + + if ((mykError = MYKONOS_runInitCals(mykDevice, + (initCalMask & ~TX_LO_LEAKAGE_EXTERNAL))) != MYKONOS_ERR_OK) { + errorString = getMykonosErrorMessage(mykError); + goto error_11; + } + + if ((mykError = MYKONOS_waitInitCals(mykDevice, 60000, &errorFlag, + &errorCode)) != MYKONOS_ERR_OK) { + errorString = getMykonosErrorMessage(mykError); + goto error_11; + } + + if ((errorFlag != 0) || (errorCode != 0)) { + /*** < Info: abort init cals > ***/ + if ((mykError = MYKONOS_abortInitCals(mykDevice, + &initCalsCompleted)) != MYKONOS_ERR_OK) { + errorString = getMykonosErrorMessage(mykError); + goto error_11; + } + if (initCalsCompleted) + printf("Completed calibrations: %x\n", (unsigned int)initCalsCompleted); + } else + printf("Calibrations completed successfully\n"); + + /*************************************************************************/ + /***** Mykonos ARM Initialization External LOL Calibrations with PA *****/ + /*************************************************************************/ + + /* Please ensure PA is enabled operational at this time */ + if (initCalMask & TX_LO_LEAKAGE_EXTERNAL) { + if ((mykError = MYKONOS_runInitCals(mykDevice, + TX_LO_LEAKAGE_EXTERNAL)) != MYKONOS_ERR_OK) { + errorString = getMykonosErrorMessage(mykError); + goto error_11; + } + + if ((mykError = MYKONOS_waitInitCals(mykDevice, 60000, &errorFlag, + &errorCode)) != MYKONOS_ERR_OK) { + errorString = getMykonosErrorMessage(mykError); + goto error_11; + } + + if ((errorFlag != 0) || (errorCode != 0)) { + /*** < Info: abort init cals > ***/ + if ((mykError = MYKONOS_abortInitCals(mykDevice, + &initCalsCompleted)) != MYKONOS_ERR_OK) { + errorString = getMykonosErrorMessage(mykError); + goto error_11; + } + } else + printf("External LOL Calibrations completed successfully\n"); + } + + /*************************************************************************/ + /***** SYSTEM JESD bring up procedure *****/ + /*************************************************************************/ + + if ((mykError = MYKONOS_enableSysrefToRxFramer(mykDevice, + 1)) != MYKONOS_ERR_OK) { + errorString = getMykonosErrorMessage(mykError); + goto error_11; + } + /*** < Info: Mykonos is waiting for sysref in order to start + * transmitting CGS from the RxFramer> ***/ + + if ((mykError = MYKONOS_enableSysrefToObsRxFramer(mykDevice, + 1)) != MYKONOS_ERR_OK) { + errorString = getMykonosErrorMessage(mykError); + goto error_11; + } + /*** < Info: Mykonos is waiting for sysref in order to start + * transmitting CGS from the ObsRxFramer> ***/ + + if ((mykError = MYKONOS_enableSysrefToDeframer(mykDevice, + 0)) != MYKONOS_ERR_OK) { + errorString = getMykonosErrorMessage(mykError); + goto error_11; + } + + if ((mykError = MYKONOS_resetDeframer(mykDevice)) != MYKONOS_ERR_OK) { + errorString = getMykonosErrorMessage(mykError); + goto error_11; + } + + if ((mykError = MYKONOS_enableSysrefToDeframer(mykDevice, + 1)) != MYKONOS_ERR_OK) { + errorString = getMykonosErrorMessage(mykError); + goto error_11; + } + + /*************************************************************************/ + /***** Enable SYSREF to Mykonos and BBIC *****/ + /*************************************************************************/ + + /* Request a SYSREF from the AD9528 */ + AD9528_requestSysref(clockAD9528_device, 1); + mdelay(1); + + /*** < Info: Mykonos is actively transmitting CGS from the RxFramer> ***/ + + /*** < Info: Mykonos is actively transmitting CGS from the ObsRxFramer> ***/ + + /* Request two SYSREFs from the AD9528 */ + AD9528_requestSysref(clockAD9528_device, 1); + mdelay(1); + AD9528_requestSysref(clockAD9528_device, 1); + mdelay(5); + + /*************************************************************************/ + /***** Mykonos enable tracking calibrations *****/ + /*************************************************************************/ + + if ((mykError = MYKONOS_enableTrackingCals(mykDevice, + trackingCalMask)) != MYKONOS_ERR_OK) { + errorString = getMykonosErrorMessage(mykError); + goto error_11; + } + + /*** < Info: Allow Rx1/2 QEC tracking and Tx1/2 QEC tracking to run when in the radioOn state + * Tx calibrations will only run if radioOn and the obsRx path is set to OBS_INTERNAL_CALS > ***/ + + /*** < Info: Function to turn radio on, Enables transmitters and receivers + * that were setup during MYKONOS_initialize() > ***/ + if ((mykError = MYKONOS_radioOn(mykDevice)) != MYKONOS_ERR_OK) { + errorString = getMykonosErrorMessage(mykError); + goto error_11; + } + + /*** < Info: Allow TxQEC to run when User: is not actively using ORx receive path > ***/ + if ((mykError = MYKONOS_setObsRxPathSource(mykDevice, + OBS_RXOFF)) != MYKONOS_ERR_OK) { + errorString = getMykonosErrorMessage(mykError); + goto error_11; + } + if ((mykError = MYKONOS_setObsRxPathSource(mykDevice, + OBS_INTERNALCALS)) != MYKONOS_ERR_OK) { + errorString = getMykonosErrorMessage(mykError); + goto error_11; + } + + mdelay(1000); + + if ((mykError = MYKONOS_setObsRxPathSource(mykDevice, + OBS_RX1_SNIFFERLO)) != MYKONOS_ERR_OK) { + errorString = getMykonosErrorMessage(mykError); + goto error_11; + } + + Xil_DCacheInvalidateRange(DDR_MEM_BASEADDR + 0x800000, 16384 * 8); + + printf("Done\n"); + + return 0; + +error_11: + printf("%s", errorString); + +error_2: +// axi_clkgen_remove(rx_clkgen); + return FAILURE; +} + + +int HW_9371CheckJesdStatus(mykonosDevice_t *mykDevice, uint8_t *framerStatus, + uint8_t *obsFramerStatus, uint8_t *deframerStatus) +{ + mykonosErr_t mykError; + const char *errorString; + /* Allocating memory for the errorString */ + errorString = NULL; + + /*************************************************************************/ + /***** Check Mykonos Framer Status *****/ + /*************************************************************************/ + + if ((mykError = MYKONOS_readRxFramerStatus(mykDevice, + framerStatus)) != MYKONOS_ERR_OK) { + errorString = getMykonosErrorMessage(mykError); + return ADIERR_FAILED; + } + else { + // typical value: 0x3E + } + + if ((mykError = MYKONOS_readOrxFramerStatus(mykDevice, + obsFramerStatus)) != MYKONOS_ERR_OK) { + errorString = getMykonosErrorMessage(mykError); + return ADIERR_FAILED; + } else { + // typical value: 0x3E + } + + /*************************************************************************/ + /***** Check Mykonos Deframer Status *****/ + /*************************************************************************/ + + if ((mykError = MYKONOS_readDeframerStatus(mykDevice, + deframerStatus)) != MYKONOS_ERR_OK) { + errorString = getMykonosErrorMessage(mykError); + return ADIERR_FAILED; + } else { + // typical value: 0x28 + } + + return ADIERR_OK; +} + + +int HW_9371SmallFrequencyChange(mykonosDevice_t *mykDevice, uint64_t freq_Hz) +{ + mykonosErr_t mykError = MYKONOS_ERR_OK; + uint8_t pllLockStatus = 0; + /* + * Move the device into the radio off state. + */ + if((mykError = MYKONOS_radioOff(mykDevice)) != MYKONOS_ERR_OK) + { + xil_printf("Turn radio off failed!\n\r"); + return ADIERR_FAILED; + } + + /* + * Program the new local oscillator (LO) frequency. Check if PLL is locked. + */ + if((mykError = MYKONOS_setRfPllFrequency(mykDevice, TX_PLL, + freq_Hz)) != MYKONOS_ERR_OK) + { + xil_printf("Set TX PLL failed!\n\r"); + return ADIERR_FAILED; + } + mykError = MYKONOS_checkPllsLockStatus(mykDevice, &pllLockStatus); + if ((pllLockStatus & 0x07) != 0x07) + { + /*** < Info: Clock, Rx and Tx PLLs not locked > ***/ + xil_printf("Not all PLLs locked, lock status: 0x%02x\n", pllLockStatus); + } + + /* + * Reset the external channel. + */ +// If((mykError = MYKONOS_resetExtTxLolChannel(mykDevice, TX1_TX2)) +// != MYKONOS_ERR_OK) ; //where TX1_TX2 is part of the enum mykonosTxChannels_t +// { +// xil_printf("Reset external channel FAILED!"); +// } + + /* + * Move the device back into the radio on state. + */ + if ((mykError = MYKONOS_radioOn(mykDevice)) != MYKONOS_ERR_OK) + { + xil_printf("Turn radio on failed!\n\r"); + return ADIERR_FAILED; + } + + /* + * Reenable tracking calibrations. + */ +// If((mykError = MYKONOS_MYKONOS_setObsRxPathSource(mykDevice, OBS_INTERNALCALS)) +// != MYKONOS_ERR_OK) ; //where TX1_TX2 is part of the enum mykonosTxChannels_t +// { +// xil_printf("Reenable tracking calibrations FAILED!"); +// } + return ADIERR_OK; +} + + +int HW_9371LargeFrequencyChange(mykonosDevice_t *mykDevice, uint64_t freq_Hz) +{ + mykonosErr_t mykError = MYKONOS_ERR_OK; + uint8_t pllLockStatus = 0; + uint8_t errorFlag = 0; + uint8_t errorCode = 0; + uint32_t initCalsCompleted = 0; + uint16_t errorWord = 0; + uint16_t statusWord = 0; + uint8_t status = 0; + mykonosInitCalStatus_t initCalStatus = {0}; + + /* + * Move the device into the radio off state. + */ + if((mykError = MYKONOS_radioOff(mykDevice)) != MYKONOS_ERR_OK) + { + xil_printf("Turn radio off failed!\n\r"); + return ADIERR_FAILED; + } + + /* + * Program the new local oscillator (LO) frequency. Check if PLL is locked. + */ + if((mykError = MYKONOS_setRfPllFrequency(mykDevice, TX_PLL, + freq_Hz)) != MYKONOS_ERR_OK) + { + printf("Set TX PLL failed!\n\r"); + return ADIERR_FAILED; + } + mykError = MYKONOS_checkPllsLockStatus(mykDevice, &pllLockStatus); + if ((pllLockStatus & 0x07) != 0x07) + { + /*** < Info: Clock, Rx and Tx PLLs not locked > ***/ + xil_printf("Not all PLLs locked, lock status: 0x%02x\n", pllLockStatus); + } + + /* + * Rerun the initialization calibrations. + */ + uint32_t initCalMask = TX_QEC_INIT | LOOPBACK_RX_LO_DELAY | + LOOPBACK_RX_RX_QEC_INIT | RX_LO_DELAY | RX_QEC_INIT; + if ((mykError = MYKONOS_runInitCals(mykDevice, initCalMask)) + != MYKONOS_ERR_OK) + { + printf("Rerun the initialization calibrations FAILED!"); + return ADIERR_FAILED; + } + if ((mykError = MYKONOS_waitInitCals(mykDevice, 60000, &errorFlag, + &errorCode)) != MYKONOS_ERR_OK) + { + printf("Initialize calibration TIME OUT!"); + return ADIERR_FAILED; + } + if ((errorFlag != 0) || (errorCode != 0)) + { + printf("initial cals error!\n\r"); + + if((mykError = MYKONOS_getInitCalStatus(mykDevice, &initCalStatus)) + != MYKONOS_ERR_OK) + { + /*** < User log error return value to debug why init failed > ***/ + } + + //abort init calibrations + if((mykError = MYKONOS_abortInitCals(mykDevice, &initCalsCompleted)) + != MYKONOS_ERR_OK) + { + /*** < User log error return value to debug why init failed > ***/ + + } + if(initCalsCompleted) + { + /*** < which calls had completed, per the mask > ***/ + } + if((mykError = MYKONOS_readArmCmdStatus(mykDevice, &errorWord, + &statusWord)) != MYKONOS_ERR_OK) + { + /*** < User log error return value to debug why init failed > ***/ + } + if((mykError = MYKONOS_readArmCmdStatusByte(mykDevice, 2, &status)) + != MYKONOS_ERR_OK) + { + + } + if(status!=0) + { + /*** < Arm Mailbox Status Error errorWord > ***/ + /*** < Pending Flag per opcode statusWord, this follows the mask > ***/ + } + } + + /* + * Move the device back into the radio on state. + */ + if ((mykError = MYKONOS_radioOn(mykDevice)) != MYKONOS_ERR_OK) + { + xil_printf("Turn radio on failed!\n\r"); + return ADIERR_FAILED; + } + + return ADIERR_OK; +} + + +//void FreqIntrHandler(void *CallbackRef) +//{ +// XGpio *GpioPtr = (XGpio *)CallbackRef; +// uint8_t IntrStatus; +// uint32_t NewFreqHz; +// IntrStatus = XGpio_InterruptGetStatus(GpioPtr); +// +// if (IntrStatus & XGPIO_IR_CH1_MASK) +// { +// /* Clear the Interrupt */ +// XGpio_InterruptClear(GpioPtr, XGPIO_IR_CH1_MASK); +// +// NewFreqHz = XGpio_DiscreteRead(GpioPtr, AXI_GPIO_BANK_1); +// if (NewFreqHz != mykDevice.tx->txPllLoFrequency_Hz) +// { +// if (NewFreqHz > 300000000 && NewFreqHz < 6000000000) +// { +// if (abs(NewFreqHz - mykDevice.tx->txPllLoFrequency_Hz) <= 100000000) +// { +// HW_9371SmallFrequencyChange(&mykDevice, NewFreqHz); +// } +// else +// { +// HW_9371LargeFrequencyChange(&mykDevice, NewFreqHz); +// } +// mykDevice.tx->txPllLoFrequency_Hz = NewFreqHz; +// printf("New Tx frequency set to %ld Hz!\n",NewFreqHz); +// } +// else +// { +// printf("The desired Tx Frequency is out of range(300 ~ 6000 MHz)!\n"); +// } +// } +// } +// +// if (IntrStatus & XGPIO_IR_CH2_MASK) +// { +// /* Clear the Interrupt */ +// XGpio_InterruptClear(GpioPtr, XGPIO_IR_CH2_MASK); +// +// NewFreqHz = XGpio_DiscreteRead(GpioPtr, AXI_GPIO_BANK_2); +// if (NewFreqHz != mykDevice.rx->rxPllLoFrequency_Hz) +// { +// if (NewFreqHz > 300000000 && NewFreqHz < 6000000000) +// { +// if (abs(NewFreqHz - mykDevice.rx->rxPllLoFrequency_Hz) <= 100000000) +// { +// HW_9371SmallFrequencyChange(&mykDevice, NewFreqHz); +// } +// else +// { +// HW_9371LargeFrequencyChange(&mykDevice, NewFreqHz); +// } +// mykDevice.rx->rxPllLoFrequency_Hz = NewFreqHz; +// printf("New Rx frequency set to %ld Hz!\n",NewFreqHz); +// } +// else +// { +// printf("The desired Rx Frequency is out of range(300 ~ 6000 MHz)!\n"); +// } +// } +// } +//} +// +// +//void GainIntrHandler(void *CallbackRef) +//{ +// XGpio *GpioPtr = (XGpio *)CallbackRef; +// uint8_t IntrStatus; +// uint32_t NewRxGain; +// IntrStatus = XGpio_InterruptGetStatus(GpioPtr); +// +// if (IntrStatus & XGPIO_IR_CH1_MASK) +// { +// /* Clear the Interrupt */ +// XGpio_InterruptClear(GpioPtr, XGPIO_IR_CH1_MASK); +// +// NewRxGain = XGpio_DiscreteRead(GpioPtr, AXI_GPIO_BANK_1); +// if (NewRxGain != mykDevice.rx->rxGainCtrl->rx1GainIndex) +// { +// if ((NewRxGain >= 195) && (NewRxGain <= 255)) +// { +// MYKONOS_setRx1ManualGain(&mykDevice, NewRxGain); +// mykDevice.rx->rxGainCtrl->rx1GainIndex = NewRxGain; +// char buf[BUFSIZ]; +// sprintf(buf, "%u", NewRxGain); +// printf("New Rx1 gain index set to %s!\n",buf); +// } +// else +// { +// printf("The desired Rx1 gain index is out of range(195 ~ 255), 0.5dB per stage!\n"); +// } +// } +// } +// +// if (IntrStatus & XGPIO_IR_CH2_MASK) +// { +// /* Clear the Interrupt */ +// XGpio_InterruptClear(GpioPtr, XGPIO_IR_CH2_MASK); +// +// NewRxGain = XGpio_DiscreteRead(GpioPtr, AXI_GPIO_BANK_2); +// if (NewRxGain != mykDevice.rx->rxGainCtrl->rx2GainIndex) +// { +// if ((NewRxGain >= 195) && (NewRxGain <= 255)) +// { +// MYKONOS_setRx2ManualGain(&mykDevice, NewRxGain); +// mykDevice.rx->rxGainCtrl->rx2GainIndex = NewRxGain; +// char buf[BUFSIZ]; +// sprintf(buf, "%u", NewRxGain); +// printf("New Rx2 gain index set to %s!\n",buf); +// } +// else +// { +// printf("The desired Rx2 gain index is out of range(195 ~ 255), 0.5dB per stage!\n"); +// } +// } +// } +//} +// +// +//void AttnIntrHandler(void *CallbackRef) +//{ +// XGpio *GpioPtr = (XGpio *)CallbackRef; +// uint8_t IntrStatus; +// uint32_t NewTxAttn; +// IntrStatus = XGpio_InterruptGetStatus(GpioPtr); +// +// if (IntrStatus & XGPIO_IR_CH1_MASK) +// { +// /* Clear the Interrupt */ +// XGpio_InterruptClear(GpioPtr, XGPIO_IR_CH1_MASK); +// +// NewTxAttn = XGpio_DiscreteRead(GpioPtr, AXI_GPIO_BANK_1); +// if (NewTxAttn != mykDevice.tx->tx1Atten_mdB) +// { +// if ((NewTxAttn >= 0) && (NewTxAttn <= 41950)) +// { +// MYKONOS_setTx1Attenuation(&mykDevice, NewTxAttn); +// mykDevice.tx->tx1Atten_mdB = NewTxAttn; +// char buf[BUFSIZ]; +// sprintf(buf, "%u", NewTxAttn); +// printf("New Tx1 attenuation set to %s dBm!\n",buf); +// } +// else +// { +// printf("The desired Tx1 attenuation is out of range(0 ~ 41950 dBm), 50 dBm step!\n"); +// } +// } +// } +// +// if (IntrStatus & XGPIO_IR_CH2_MASK) +// { +// /* Clear the Interrupt */ +// XGpio_InterruptClear(GpioPtr, XGPIO_IR_CH2_MASK); +// +// NewTxAttn = XGpio_DiscreteRead(GpioPtr, AXI_GPIO_BANK_2); +// if (NewTxAttn != mykDevice.tx->tx2Atten_mdB) +// { +// if ((NewTxAttn >= 0) && (NewTxAttn <= 41950)) +// { +// MYKONOS_setTx2Attenuation(&mykDevice, NewTxAttn); +// mykDevice.tx->tx2Atten_mdB = NewTxAttn; +// char buf[BUFSIZ]; +// sprintf(buf, "%u", NewTxAttn); +// printf("New Tx2 attenuation set to %s dBm!\n",buf); +// } +// else +// { +// printf("The desired Tx2 attenuation is out of range(0 ~ 41950 dBm), 50 dBm step!\n"); +// } +// } +// } +//} diff --git a/datalink814_ge/src/hardware/headless.h b/datalink814_ge/src/hardware/headless.h new file mode 100644 index 0000000..41efed4 --- /dev/null +++ b/datalink814_ge/src/hardware/headless.h @@ -0,0 +1,348 @@ +/* + * headless.h + * + * Created on: 2021Äê6ÔÂ8ÈÕ + * Author: Josh + */ + +#ifndef SRC_HEADLESS_H_ +#define SRC_HEADLESS_H_ + +/***************************** Include Files ********************************/ +#include +#include +#include "xil_cache.h" +#include "xscugic.h" +//#include "xgpio.h" + +#include "common.h" +#include "./mykonos/ad9528.h" +#include "./mykonos/mykonos.h" +#include "./mykonos/Mykonos_M3.h" +#include "./mykonos/mykonos_gpio.h" +#include "myk_ad9528init.h" +#include "myk_init.h" + +#include "parameters.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Variable Definitions *****************************/ + +/************************** Function Prototypes ******************************/ + +/*****************************************************************************/ +/* +* +* This function setups ad9528 and ad9371 via spi. +* +* @param None. +* +* @return +* - ADIERR_FAILED if successful, +* - ADIERR_OK if not succesful +* +* @note None. +* +******************************************************************************/ +int HARDWARE_initialize(); + +int HARDWARE_ad9371Config(void); + +/*****************************************************************************/ +/* +* +* Setup up Axi Gpio, through which ad9371 can be reconfigured. Axi Gpio +* instance and interrupt system initialization are included. +* +* @param None. +* +* @return +* - ADIERR_FAILED if successful, +* - ADIERR_OK if not succesful +* +* @note None. +* +******************************************************************************/ +int HW_ad9371DynamicCfgInit(void); + +/*****************************************************************************/ +/* +* +* Setup up interrupt system, initialize exception handlers. +* +* @param DeviceId is the unique identifier for a device. +* @param GicPtr is a pointer to the XScuGic instance. +* +* @return +* - XST_SUCCESS if successful, +* - XST_FAILURE if not succesful +* +* @note None. +* +******************************************************************************/ +int HW_setupIntrSystem(u16 DeviceId, XScuGic * GicPtr); + +/*****************************************************************************/ +/* +* +* Make the connection between the Int_Id of the interrupt source and the +* associated handler. Set the interrupt priority and trigger type for the +* specified IRQ source.. +* +* @param GicPtr is a pointer to the XScuGic instance. +* @param Int_Id contains the ID of the interrupt source and should be +* in the range of 0 to XSCUGIC_MAX_NUM_INTR_INPUTS - 1 +* @param Handler to the handler for that interrupt. +* @param CallBackRef is the callback reference, usually the instance +* pointer of the connecting driver. +* @param Priority is the new priority for the IRQ source. 0 is highest +* priority, 0xF8(248) is lowest. There are 32 priority levels +* supported with a step of 8. Hence the supported priorities are +* 0, 8, 16, 32, 40 ..., 248. +* @param Trigger is the new trigger type for the IRQ source. +* Each bit pair describes the configuration for an INT_ID. +* SFI Read Only b10 always +* PPI Read Only depending on how the PPIs are configured. +* b01 Active HIGH level sensitive +* b11 Rising edge sensitive +* SPI LSB is read only. +* b01 Active HIGH level sensitive +* b11 Rising edge sensitive/ +* +* @return +* - XST_SUCCESS if successful, +* - XST_FAILURE if not succesful +* +* @note None. +* +******************************************************************************/ +int HW_connectIntr(XScuGic *GicPtr,u32 IntrId,Xil_InterruptHandler Handler, + void *CallBackRef, u8 Priority, u8 Trigger); + +/*****************************************************************************/ +/* +* +* Initialize Analog Device related configuration profile. This is a HARDWARE- +* ASSOTIATED function, which may differ between different board. +* +* @param None. +* +* @return +* - ADIERR_OK if configuration profile exists, +* - ADIERR_FAILED if onfiguration profile does not exist +* +* @note None. +* +******************************************************************************/ +int HW_adiCfgProfileInit(void); + +/******************************************************************************/ +/** +* +* This function conducts AD9528 device configuration initializing procedure. +* +* @param clockAD9528_device is a pointer to the data structure holding +* AD9528 settings, which contains basic AD9528 settings such as +* spi and gpio. +* +* @return +* - ADIERR_OK if successful. +* - ADIERR_FAILED if not successful. +* +* @note None. +* +*******************************************************************************/ +int HW_9528Config(ad9528Device_t *clockAD9528_device); + +/******************************************************************************/ +/** +* +* This function read AD9528 reg508 status, to check whether ad9528 is locked or +* not. +* +* @param clockAD9528_device is a pointer to the data structure holding +* AD9528 settings, which contains basic AD9528 settings. +* +* @return +* - ADIERR_OK if successful. +* - ADIERR_FAILED if not successful. +* +* @note None. +* +*******************************************************************************/ +int HW_9528GetLockStatus(ad9528Device_t *device, uint8_t *reg508); + +/******************************************************************************/ +/** +* +* Conduct AD9371 device configuration initializing procedure. +* +* @param clockAD9528_device is a pointer to the data structure holding +* AD9528 settings, which contains basic AD9528 settings. +* @param mykDevice is ADI hardware layer settings pointer specific to +* a Mykonos instance which contains basic settings such as spi, +* gpio, tx/rx and jesd configurations. +* +* @return +* - ADIERR_OK if successful. +* - ADIERR_FAILED if not successful. +* +* @note None. +* +*******************************************************************************/ +int HW_9371Config(ad9528Device_t *clockAD9528_device, mykonosDevice_t *mykDevice); + +/******************************************************************************/ +/** +* +* Read AD9371's RX framer, ORX framer and TX deframer status, to check jesd204b +* sync status. +* +* @param mykDevice is ADI hardware layer settings pointer specific to +* a Mykonos instance which contains basic settings such as spi, +* gpio, tx/rx and jesd configurations. +* @param framerStatus is the RX framer status byte read +* framerStatus | Description +* -------------|----------------------------------------------------------------------------- +* [7] | SYSREF phase error ? a new SYSREF had different timing than the first that set the LMFC timing. +* [6] | Framer lane FIFO read/write pointer delta has changed. Can help debug issues with deterministic latency. +* [5] | Framer has received the SYSREF and has retimed its LMFC +* [4:2] | Framer ILAS state: 0=CGS, 1= 1st Multframe, 2= 2nd Multiframe, 3= 3rd Multiframe, 4= 4th multiframe, 5= Last multiframe, 6=invalid, 7= ILAS complete +* [1:0] | Framer Tx state: 0=CGS, 1= ILAS, 2 = ADC Data +* @param obsFramerStatus is the ORX framer status byte read +* obsFramerStatus | Description +* ----------------|----------------------------------------------------------------------------- +* [7] | SYSREF phase error ? a new SYSREF had different timing than the first that set the LMFC timing. +* [6] | Framer lane FIFO read/write pointer delta has changed. Can help debug issues with deterministic latency. +* [5] | Framer has received the SYSREF and has retimed its LMFC +* [4:2] | Framer ILAS state: 0=CGS, 1= 1st Multframe, 2= 2nd Multiframe, 3= 3rd Multiframe, 4= 4th multiframe, 5= Last multiframe, 6=invalid, 7= ILAS complete +* [1:0] | Framer Tx state: 0=CGS, 1= ILAS, 2 = ADC Data +* @param deframerStatus is the TX deframer status byte read +* deframerStatus | Bit Name | Description +* ----------------|--------------------------|--------------------------------------------- +* [7] | Unused | Unused +* [6] | Deframer IRQ | This bit indicates that the IRQ interrupt was asserted. +* [5] | Deframer SYSREF Received | When this bit is set, it indicates that the SYSREF pulse was received by the deframer IP +* [4] | Deframer Receiver Error | This bit is set when PRBS has received an error. +* [3] | Valid Checksum | This bit is set when the received ILAS checksum is valid. +* [2] | EOF Event | This bit captures the internal status of the framer End of Frame event. Value =1 if framing error during ILAS +* [1] | EOMF Event | This bit captures the internal status of the framer End of Multi-Frame event. Value =1 if framing error during ILAS +* [0] | FS Lost | This bit captures the internal status of the framer Frame Symbol event. Value =1 if framing error during ILAS or user data (invalid replacement characters) +* +* @return +* - ADIERR_OK if successful. +* - ADIERR_FAILED if not successful. +* +* @note None. +* +*******************************************************************************/ +int HW_9371CheckJesdStatus(mykonosDevice_t *mykDevice, uint8_t *framerStatus, + uint8_t *obsFramerStatus, uint8_t *deframerStatus); + +/******************************************************************************/ +/** +* +* This function conducts AD9371/9375 samll RF PLL frequcny change procedure. The +* procedure is performed as follows: +* 1. Move the device into the radio off state. +* 2. Program the new local oscillator (LO) frequency. +* 3. Reset the external channel.(ignored) +* 4. Move the device back into the radio on state. +* 5. Reenable tracking calibrations.(ignored) +* +* @param mykDevice is ADI hardware layer settings pointer specific to +* a Mykonos instance which contains basic settings such as spi, +* gpio, tx/rx and jesd configurations. +* @param freq_Hz is the target frequancy in Hz. +* +* @return None. +* +* @note The procedure is used when a radio frequency (RF) phased-lock loop +* (PLL) change is required with the following conditions: +* - A desire to change the Rx, Tx, and ORx frequencies. +* - The frequency step change is less than 100 MHz. +* - The frequency step does not cross the divide by 2 boundaries outlined +* in AD9371/9375-UG-992-Rev.B-Table 96. +* +*******************************************************************************/ +int HW_9371SmallFrequencyChange(mykonosDevice_t *mykDevice, uint64_t freq_Hz); + +/******************************************************************************/ +/** +* +* This function conducts AD9371/9375 large RF PLL frequcny change procedure. The +* procedure is performed as follows: +* 1. Move the device into the radio off state. +* 2. Program the new local oscillator (LO) frequency. +* 3. Rerun the initialization calibrations. +* 4. Move the device back into the radio on state. +* 5. Reenable tracking calibrations.(ignored) +* +* @param mykDevice is ADI hardware layer settings pointer specific to +* a Mykonos instance which contains basic settings such as spi, +* gpio, tx/rx and jesd configurations. +* @param freq_Hz is the target frequancy in Hz. +* +* @return None. +* +* @note The procedure is used when a radio frequency (RF) phased-lock loop +* (PLL) change is required with the following conditions: +* - A desire to change the Rx, Tx, and ORx frequencies. +* - The frequency step change is more than 100 MHz. +* - The frequency step does cross the divide by 2 boundaries outlined +* in AD9371/9375-UG-992-Rev.B-Table 96. +* +*******************************************************************************/ +int HW_9371LargeFrequencyChange(mykonosDevice_t *mykDevice, uint64_t freq_Hz); + +/******************************************************************************/ +/** +* +* Handles AD9371 TX & RX frequency change axi gpio interruput. +* +* @param CallBackRef is the callback reference, usually the instance +* pointer of the connecting driver. +* +* @return None. +* +* @note None. +* +*******************************************************************************/ +void FreqIntrHandler(void *CallbackRef); + +/******************************************************************************/ +/** +* +* Handles AD9371 Rx gain index change axi gpio interruput. +* +* @param CallBackRef is the callback reference, usually the instance +* pointer of the connecting driver. +* +* @return None. +* +* @note None. +* +*******************************************************************************/ +void GainIntrHandler(void *CallbackRef); + +/******************************************************************************/ +/** +* +* Handles AD9371 Tx attenuation change axi gpio interruput. +* +* @param CallBackRef is the callback reference, usually the instance +* pointer of the connecting driver. +* +* @return None. +* +* @note None. +* +*******************************************************************************/ +void AttnIntrHandler(void *CallbackRef); + +#endif /* SRC_HEADLESS_H_ */ diff --git a/datalink814_ge/src/hardware/myk_ad9528init.c b/datalink814_ge/src/hardware/myk_ad9528init.c new file mode 100644 index 0000000..0cb935d --- /dev/null +++ b/datalink814_ge/src/hardware/myk_ad9528init.c @@ -0,0 +1,189 @@ +///* +// * myk_clock_init.c +// * +// */ +// +///** +//* \page Disclaimer Legal Disclaimer +//* Copyright 2015-2017 Analog Devices Inc. +//* Released under the AD9371 API license, for more information see the "LICENSE.txt" file in this zip file. +//* +//*/ +// +//#ifndef MYK_CLOCK_INIT_C_ +//#define MYK_CLOCK_INIT_C_ +//#include +//#include +//#include +//#include "common.h" +// +//#include "ad9528.h" +//#include "t_ad9528.h" +//#include "myk_ad9528init.h" +//#include "parameters.h" +// +//static ad9528pll1Settings_t clockPll1Settings = +//{ +// .refA_Frequency_Hz = 30720000, +// .refA_Divider = 1, +// .refA_bufferCtrl = DISABLED, +// .refB_Frequency_Hz = 0, +// .refB_Divider = 1, +// .refB_bufferCtrl = DISABLED, +// .vcxo_Frequency_Hz = 122880000, +// .vcxoBufferCtrl = NEG_SINGLE_ENDED, +// .nDivider = 4, +// .bypassPll1 = 0 +//}; +// +//static ad9528pll2Settings_t clockPll2Settings = +//{ +// .rfDivider = 4, +// .n2Divider = 10, +// .totalNdiv = 30 +//}; +// +//static ad9528outputSettings_t clockOutputSettings = +//{ +// .outPowerDown = 53237, // 0xCFF5 +// .outSource = { +// CHANNEL_DIV, CHANNEL_DIV, CHANNEL_DIV, SYSREF, +// CHANNEL_DIV, CHANNEL_DIV, CHANNEL_DIV, CHANNEL_DIV, +// CHANNEL_DIV, CHANNEL_DIV, CHANNEL_DIV, CHANNEL_DIV, +// SYSREF, CHANNEL_DIV}, +// .outBufferCtrl = {0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +// .outAnalogDelay = {0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +// .outDigitalDelay = {0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +// .outChannelDiv = {10,10,10,10,10,10,10,10,10,10,10,10,10,10}, +// .outFrequency_Hz = {122880000, 122880000, 122880000, 122880000, 122880000, 122880000, 122880000, 122880000, 122880000, 122880000, 122880000, 122880000, 122880000, 122880000} +//}; +// +//static ad9528sysrefSettings_t clockSysrefSettings = +//{ +// .sysrefRequestMethod = PIN, +// .sysrefSource = INTERNAL, +// .sysrefPinEdgeMode = LEVEL_ACTIVE_HIGH, +// .sysrefPinBufferMode = DISABLED, +// .sysrefPatternMode = NSHOT, +// .sysrefNshotMode = ONE_PULSE, +// .sysrefDivide = 512 +//}; +// +//static spiSettings_t clockSpiSettings = +//{ +// .chipSelectIndex = AD9528_CS, //chip select Index +// .writeBitPolarity = 0, //Write bit polarity +// .longInstructionWord = 1, //16bit instruction word +// .MSBFirst = 1, //MSB first +// .CPHA = 0, //Clock phase +// .CPOL = 0, //Clock polarity +// .enSpiStreaming = 0, //uint8_t enSpiStreaming; +// .autoIncAddrUp = 1, //uint8_t autoIncAddrUp; +// .fourWireMode = 1 //uint8_t fourWireMode; +//}; +// +//ad9528Device_t clockAD9528_ = +//{ +// &clockSpiSettings, +// &clockPll1Settings, +// &clockPll2Settings, +// &clockOutputSettings, +// &clockSysrefSettings +//}; +// +//ad9528Device_t *ad9528Init = &clockAD9528_; +// +//#endif /* MYK_CLOCK_INIT_C_ */ + + +/* AD9528 data structure initialization file */ +#include +#include +#include +#include "common.h" + +#include "./mykonos/ad9528.h" +#include "./mykonos/t_ad9528.h" +#include "myk_ad9528init.h" +#include "parameters.h" + +static ad9528pll1Settings_t clockPll1Settings = { + .refA_Frequency_Hz = 122880000, + .refA_Divider = 1, + .refA_bufferCtrl = SINGLE_ENDED, + .refB_Frequency_Hz = 0, + .refB_Divider = 1, + .refB_bufferCtrl = DISABLED, + .vcxo_Frequency_Hz = 122880000, + .vcxoBufferCtrl = DIFFERENTIAL, + .nDivider = 1, + .bypassPll1 = 0 +}; + +static ad9528pll2Settings_t clockPll2Settings = { + .rfDivider = 3, + .n2Divider = 10, + .totalNdiv = 30 +}; + +/******************************************************************* + * Output Distribution Settings + * 9369CE02A uses the following clock outputs + * OUT 1: FPGA_REF_CLK + * OUT 2: FPGA_AUX_CLK + * OUT 3: FPGA_SYSREF + * OUT 12: SYSREF_IN + * OUT 13: DEV_CLK_IN + ******************************************************************* + */ +static ad9528outputSettings_t clockOutputSettings = { + .outPowerDown = 0x0, + .outSource = { + SYSREF, SYSREF, CHANNEL_DIV, SYSREF, + CHANNEL_DIV, CHANNEL_DIV, SYSREF, SYSREF, + CHANNEL_DIV, CHANNEL_DIV, CHANNEL_DIV, CHANNEL_DIV, + SYSREF , CHANNEL_DIV + }, + .outBufferCtrl = {0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + .outAnalogDelay = {0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + .outDigitalDelay = {0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + .outChannelDiv = {10,10,10,10,10,10,10,10,10,10,10,10,10,10}, + .outFrequency_Hz = { + 122880000, 122880000, 122880000, 122880000, + 122880000, 122880000, 122880000, 122880000, + 122880000, 122880000, 122880000, 122880000, + 122880000, 122880000 + } +}; + +static ad9528sysrefSettings_t clockSysrefSettings = { + .sysrefRequestMethod = SPI, + .sysrefSource = INTERNAL, + .sysrefPinEdgeMode = LEVEL_ACTIVE_HIGH, + .sysrefPinBufferMode = DISABLED, + .sysrefPatternMode = CONTINUOUS, + .sysrefNshotMode = FOUR_PULSES, + .sysrefDivide = 512 +}; + +static spiSettings_t clockSpiSettings = { + .chipSelectIndex = 2, //chip select Index + .writeBitPolarity = 0, //Write bit polarity + .longInstructionWord = 1, //16bit instruction word + .MSBFirst = 1, //MSB first + .CPHA = 0, //Clock phase + .CPOL = 0, //Clock polarity + .enSpiStreaming = 0, //uint8_t enSpiStreaming; + .autoIncAddrUp = 1, //uint8_t autoIncAddrUp; + .fourWireMode = 1 //uint8_t fourWireMode; +}; + +ad9528Device_t clockAD9528_ = { + &clockSpiSettings, + &clockPll1Settings, + &clockPll2Settings, + &clockOutputSettings, + &clockSysrefSettings +}; + +ad9528Device_t *ad9528Init = &clockAD9528_; diff --git a/datalink814_ge/src/hardware/myk_ad9528init.h b/datalink814_ge/src/hardware/myk_ad9528init.h new file mode 100644 index 0000000..53e8be6 --- /dev/null +++ b/datalink814_ge/src/hardware/myk_ad9528init.h @@ -0,0 +1,20 @@ +/* + * myk_clock_init.h + * + */ + +/** +* \page Disclaimer Legal Disclaimer +* Copyright 2015-2017 Analog Devices Inc. +* Released under the AD9371 API license, for more information see the "LICENSE.txt" file in this zip file. +* +*/ + +#ifndef MYK_CLOCK_INIT_H_ +#define MYK_CLOCK_INIT_H_ + +#include "./mykonos/ad9528.h" + +extern ad9528Device_t *ad9528Init; + +#endif /* MYK_CLOCK_INIT_H_ */ diff --git a/datalink814_ge/src/hardware/myk_init.c b/datalink814_ge/src/hardware/myk_init.c new file mode 100644 index 0000000..d585d1a --- /dev/null +++ b/datalink814_ge/src/hardware/myk_init.c @@ -0,0 +1,558 @@ +/** + * \file myk_init.c + * + * \brief Contains init setting structure declarations for the _instance API + * + * The top level structure mykonosDevice_t mykDevice uses keyword + * extern to allow the application layer main() to have visibility + * to these settings. + * + * All data structures required for operation have been initialized with values which reflect + * these settings: + * + * Device Clock = $122.88$ Mhz + * Rx enabled channels = $2$ + * Tx enabled channels = $2$ + * + * Mykonos Framer: + * Lane Rate = $4915.2$ Mbs + * L = $2$ + * K = $32$ + * M = $4$ + * F = $4$ + * + * Mykonos Deframer: + * Lane Rate = $4915.2$ Mbs + * L = $2$ + * K = $32$ + * M = $4$ + * F = $4$ + * + * Mykonos Observation framer: + * Lane Rate = $4915.2$ Mbs + * L = $2$ + * K = $32$ + * M = $4$ + * F = $4$ + * + * Using these profiles: + * $Rx 100Mhz, IQrate 122.88Mhz, Dec5$ + * $Tx 100/100Mhz, IQrate 122.88Mhz, Dec5$ + * $ORX 100Mhz, IQrate 122.88Mhz, Dec5$ + * $SRx 20Mhz, IQrate 30.72Mhz, Dec5$ + * + */ + +/** +* \page Disclaimer Legal Disclaimer +* Copyright 2015-2017 Analog Devices Inc. +* Released under the AD9371 API license, for more information see the "LICENSE.txt" file in this zip file. +* +*/ + +#include +#include "./mykonos/t_mykonos.h" +#include "myk_init.h" +#include "parameters.h" +#include "./mykonos/mykonos_gpio.h" + +static int16_t txFirCoefs[] = {-94,-26,282,177,-438,-368,756,732,-1170,-1337,1758,2479,-2648,-5088,4064,16760,16759,4110,-4881,-2247,2888,1917,-1440,-1296,745,828,-358,-474,164,298,-16,-94}; + +static mykonosFir_t txFir = +{ + 6, /* Filter gain in dB*/ + 32, /* Number of coefficients in the FIR filter*/ + &txFirCoefs[0] /* A pointer to an array of filter coefficients*/ +}; + +static int16_t rxFirCoefs[] = {-20,6,66,22,-128,-54,240,126,-402,-248,634,444,-956,-756,1400,1244,-2028,-2050,2978,3538,-4646,-7046,9536,30880,30880,9536,-7046,-4646,3538,2978,-2050,-2028,1244,1400,-756,-956,444,634,-248,-402,126,240,-54,-128,22,66,6,-20}; + +static mykonosFir_t rxFir = +{ + -6, /* Filter gain in dB*/ + 48, /* Number of coefficients in the FIR filter*/ + &rxFirCoefs[0] /* A pointer to an array of filter coefficients*/ +}; + +static int16_t obsrxFirCoefs[] = {-14,-19,44,41,-89,-95,175,178,-303,-317,499,527,-779,-843,1184,1317,-1781,-2059,2760,3350,-4962,-7433,9822,32154,32154,9822,-7433,-4962,3350,2760,-2059,-1781,1317,1184,-843,-779,527,499,-317,-303,178,175,-95,-89,41,44,-19,-14}; +static mykonosFir_t obsrxFir = +{ + -6, /* Filter gain in dB*/ + 48, /* Number of coefficients in the FIR filter*/ + &obsrxFirCoefs[0]/* A pointer to an array of filter coefficients*/ +}; + +static int16_t snifferFirCoefs[] = {-1,-5,-14,-23,-16,24,92,137,80,-120,-378,-471,-174,507,1174,1183,98,-1771,-3216,-2641,942,7027,13533,17738,17738,13533,7027,942,-2641,-3216,-1771,98,1183,1174,507,-174,-471,-378,-120,80,137,92,24,-16,-23,-14,-5,-1}; +static mykonosFir_t snifferRxFir= +{ + -6, /* Filter gain in dB*/ + 48, /* Number of coefficients in the FIR filter*/ + &snifferFirCoefs[0]/* A pointer to an array of filter coefficients*/ +}; + +static mykonosJesd204bFramerConfig_t rxFramer = +{ + 0, /* JESD204B Configuration Bank ID -extension to Device ID (Valid 0..15)*/ + 0, /* JESD204B Configuration Device ID - link identification number. (Valid 0..255)*/ + 0, /* JESD204B Configuration starting Lane ID. If more than one lane used, each lane will increment from the Lane0 ID. (Valid 0..31)*/ + 4, /* number of ADCs (0, 2, or 4) - 2 ADCs per receive chain*/ + 32, /* number of frames in a multiframe (default=32), F*K must be a multiple of 4. (F=2*M/numberOfLanes)*/ + 0, /* scrambling off if framerScramble= 0, if framerScramble>0 scramble is enabled.*/ + 1, /* 0=use internal SYSREF, 1= use external SYSREF*/ + 0x03, /* serializerLanesEnabled - bit per lane, [0] = Lane0 enabled, [1] = Lane1 enabled*/ + 0xE4, /* serializerLaneCrossbar*/ + 22, /* serializerAmplitude - default 22 (valid (0-31)*/ + 4, /* preEmphasis - < default 4 (valid 0 - 7)*/ + 0, /* invertLanePolarity - default 0 ([0] will invert lane [0], bit1 will invert lane1)*/ + 0, /* lmfcOffset - LMFC_Offset offset value for deterministic latency setting*/ + 0, /* Flag for determining if SYSREF on relink should be set. Where, if > 0 = set, 0 = not set*/ + 0, /* Flag for determining if auto channel select for the xbar should be set. Where, if > 0 = set, '0' = not set*/ + 0, /* Selects SYNCb input source. Where, 0 = use RXSYNCB for this framer, 1 = use OBSRX_SYNCB for this framer*/ + 0, /* Flag for determining if CMOS mode for RX Sync signal is used. Where, if > 0 = CMOS, '0' = LVDS*/ + 0, /* Selects framer bit repeat or oversampling mode for lane rate matching. Where, 0 = bitRepeat mode (changes effective lanerate), 1 = overSample (maintains same lane rate between ObsRx framer and Rx framer and oversamples the ADC samples)*/ + 0 /* Flag for determining if API will calculate the appropriate settings for framer lane outputs to physical lanes. Where, if '0' = API will set automatic lane crossbar, '1' = set to manual mode and the value in serializerLaneCrossbar will be used*/ +}; + +static mykonosJesd204bFramerConfig_t obsRxFramer = +{ + 0, /* JESD204B Configuration Bank ID -extension to Device ID (Valid 0..15)*/ + 0, /* JESD204B Configuration Device ID - link identification number. (Valid 0..255)*/ + 0, /* JESD204B Configuration starting Lane ID. If more than one lane used, each lane will increment from the Lane0 ID. (Valid 0..31)*/ + 2, /* number of ADCs (0, 2, or 4) - 2 ADCs per receive chain*/ + 32, /* number of frames in a multiframe (default=32), F*K must be a multiple of 4. (F=2*M/numberOfLanes)*/ + 0, /* scrambling off if framerScramble= 0, if framerScramble>0 scramble is enabled.*/ + 1, /* 0=use internal SYSREF, 1= use external SYSREF*/ + 0x04, /* serializerLanesEnabled - bit per lane, [0] = Lane0 enabled, [1] = Lane1 enabled*/ + 0xE4, /* Lane crossbar to map framer lane outputs to physical lanes*/ + 22, /* serializerAmplitude - default 22 (valid (0-31)*/ + 4, /* preEmphasis - < default 4 (valid 0 - 7)*/ + 0, /* invertLanePolarity - default 0 ([0] will invert lane [0], bit1 will invert lane1)*/ + 0, /* lmfcOffset - LMFC_Offset offset value for deterministic latency setting*/ + 0, /* Flag for determining if SYSREF on relink should be set. Where, if > 0 = set, 0 = not set*/ + 0, /* Flag for determining if auto channel select for the xbar should be set. Where, if > 0 = set, '0' = not set*/ + 1, /* Selects SYNCb input source. Where, 0 = use RXSYNCB for this framer, 1 = use OBSRX_SYNCB for this framer*/ + 0, /* Flag for determining if CMOS mode for RX Sync signal is used. Where, if > 0 = CMOS, '0' = LVDS*/ + 0, /* Selects framer bit repeat or oversampling mode for lane rate matching. Where, 0 = bitRepeat mode (changes effective lanerate), 1 = overSample (maintains same lane rate between ObsRx framer and Rx framer and oversamples the ADC samples)*/ + 0 /* Flag for determining if API will calculate the appropriate settings for framer lane outputs to physical lanes. Where, if '0' = API will set automatic lane crossbar, '1' = set to manual mode and the value in serializerLaneCrossbar will be used*/ +}; + +static mykonosJesd204bDeframerConfig_t deframer = +{ + 0, /* bankId extension to Device ID (Valid 0..15)*/ + 0, /* deviceId link identification number. (Valid 0..255)*/ + 0, /* lane0Id Lane0 ID. (Valid 0..31)*/ + 4, /* M number of DACss (0, 2, or 4) - 2 DACs per transmit chain */ + 32, /* K #frames in a multiframe (default=32), F*K=multiple of 4. (F=2*M/numberOfLanes)*/ + 0, /* scramble scrambling off if scramble= 0.*/ + 1, /* External SYSREF select. 0 = use internal SYSREF, 1 = external SYSREF*/ + 0x03, /* Deserializer lane select bit field. Where, [0] = Lane0 enabled, [1] = Lane1 enabled, etc */ + 0xE4, /* Lane crossbar to map physical lanes to deframer lane inputs [1:0] = Deframer Input 0 Lane section, [3:2] = Deframer Input 1 lane select, etc */ + 1, /* Equalizer setting. Applied to all deserializer lanes. Range is 0..4*/ + 0, /* PN inversion per each lane. bit[0] = 1 Invert PN of Lane 0, bit[1] = Invert PN of Lane 1, etc).*/ + 0, /* LMFC_Offset offset value to adjust deterministic latency. Range is 0..31*/ + 0, /* Flag for determining if SYSREF on relink should be set. Where, if > 0 = set, '0' = not set*/ + 0, /* Flag for determining if auto channel select for the xbar should be set. Where, if > 0 = set, '0' = not set*/ + 0, /* Flag for determining if CMOS mode for TX Sync signal is used. Where, if > 0 = CMOS, '0' = LVDS*/ + 0 /* Flag for determining if API will calculate the appropriate settings for deframer lane in to physical lanes. Where, if '0' = API will set automatic lane crossbar, '1' = set to manual mode and the value in deserializerLaneCrossbar will be used*/ +}; + +static mykonosRxGainControl_t rxGainControl = +{ + MGC, /* Current Rx gain control mode setting*/ + 255, /* Rx1 Gain Index, can be used in different ways for manual and AGC gain control*/ + 255, /* Rx2 Gain Index, can be used in different ways for manual and AGC gain control*/ + 255, /* Max gain index for the currently loaded Rx1 Gain table*/ + 195, /* Min gain index for the currently loaded Rx1 Gain table*/ + 255, /* Max gain index for the currently loaded Rx2 Gain table*/ + 195, /* Min gain index for the currently loaded Rx2 Gain table*/ + 0, /* Stores Rx1 RSSI value read back from the Mykonos*/ + 0 /* Stores Rx2 RSSI value read back from the Mykonos*/ +}; + + +static mykonosORxGainControl_t orxGainControl = +{ + MGC, /* Current ORx gain control mode setting*/ + 255, /* ORx1 Gain Index, can be used in different ways for manual and AGC gain control*/ + 255, /* ORx2 Gain Index, can be used in different ways for manual and AGC gain control*/ + 255, /* Max gain index for the currently loaded ORx Gain table*/ + 237 /* Min gain index for the currently loaded ORx Gain table*/ +}; + +static mykonosSnifferGainControl_t snifferGainControl = +{ + MGC, /* Current Sniffer gain control mode setting*/ + 255, /* Current Sniffer gain index. Can be used differently for MANUAL Gain control/AGC*/ + 255, /* Max gain index for the currently loaded Sniffer Gain table*/ + 203 /* Min gain index for the currently loaded Sniffer Gain table*/ +}; + +static mykonosPeakDetAgcCfg_t rxPeakAgc = +{ + 0x0C, /* apdHighThresh: */ + 0x08, /* apdLowThresh */ + 0xB5, /* hb2HighThresh */ + 0x80, /* hb2LowThresh */ + 0x40, /* hb2VeryLowThresh */ + 0x06, /* apdHighThreshExceededCnt */ + 0x04, /* apdLowThreshExceededCnt */ + 0x06, /* hb2HighThreshExceededCnt */ + 0x04, /* hb2LowThreshExceededCnt */ + 0x04, /* hb2VeryLowThreshExceededCnt */ + 0x4, /* apdHighGainStepAttack */ + 0x2, /* apdLowGainStepRecovery */ + 0x4, /* hb2HighGainStepAttack */ + 0x2, /* hb2LowGainStepRecovery */ + 0x4, /* hb2VeryLowGainStepRecovery */ + 0x1, /* apdFastAttack */ + 0x1, /* hb2FastAttack */ + 0x1, /* hb2OverloadDetectEnable */ + 0x1, /* hb2OverloadDurationCnt */ + 0x1 /* hb2OverloadThreshCnt */ +}; + +static mykonosPowerMeasAgcCfg_t rxPwrAgc = +{ + 0x01, /* pmdUpperHighThresh */ + 0x03, /* pmdUpperLowThresh */ + 0x0C, /* pmdLowerHighThresh */ + 0x00, /* pmdLowerLowThresh */ + 0x4, /* pmdUpperHighGainStepAttack */ + 0x2, /* pmdUpperLowGainStepAttack */ + 0x2, /* pmdLowerHighGainStepRecovery */ + 0x4, /* pmdLowerLowGainStepRecovery */ + 0x08, /* pmdMeasDuration */ + 0x02 /* pmdMeasConfig */ +}; + +static mykonosAgcCfg_t rxAgcConfig = +{ + 255, /* agcRx1MaxGainIndex */ + 195, /* agcRx1MinGainIndex */ + 255, /* agcRx2MaxGainIndex */ + 195, /* agcRx2MinGainIndex: */ + 255, /* agcObsRxMaxGainIndex */ + 203, /* agcObsRxMinGainIndex */ + 1, /* agcObsRxSelect */ + 1, /* agcPeakThresholdMode */ + 1, /* agcLowThsPreventGainIncrease */ + 30720, /* agcGainUpdateCounter */ + 3, /* agcSlowLoopSettlingDelay */ + 2, /* agcPeakWaitTime */ + 1, /* agcResetOnRxEnable */ + 0, /* agcEnableSyncPulseForGainCounter */ + &rxPeakAgc, + &rxPwrAgc +}; + +static mykonosPeakDetAgcCfg_t obsRxPeakAgc = +{ + 0x1F, /* apdHighThresh: */ + 0x16, /* apdLowThresh */ + 0xB5, /* hb2HighThresh */ + 0x80, /* hb2LowThresh */ + 0x40, /* hb2VeryLowThresh */ + 0x06, /* apdHighThreshExceededCnt */ + 0x04, /* apdLowThreshExceededCnt */ + 0x06, /* hb2HighThreshExceededCnt */ + 0x04, /* hb2LowThreshExceededCnt */ + 0x04, /* hb2VeryLowThreshExceededCnt */ + 0x4, /* apdHighGainStepAttack */ + 0x2, /* apdLowGainStepRecovery */ + 0x4, /* hb2HighGainStepAttack */ + 0x2, /* hb2LowGainStepRecovery */ + 0x4, /* hb2VeryLowGainStepRecovery */ + 0x1, /* apdFastAttack */ + 0x1, /* hb2FastAttack */ + 0x1, /* hb2OverloadDetectEnable */ + 0x1, /* hb2OverloadDurationCnt */ + 0x1 /* hb2OverloadThreshCnt */ +}; + +static mykonosPowerMeasAgcCfg_t obsRxPwrAgc = +{ + 0x01, /* pmdUpperHighThresh */ + 0x03, /* pmdUpperLowThresh */ + 0x0C, /* pmdLowerHighThresh */ + 0x00, /* pmdLowerLowThresh */ + 0x4, /* pmdUpperHighGainStepAttack */ + 0x2, /* pmdUpperLowGainStepAttack */ + 0x2, /* pmdLowerHighGainStepRecovery */ + 0x4, /* pmdLowerLowGainStepRecovery */ + 0x08, /* pmdMeasDuration */ + 0x02 /* pmdMeasConfig */ +}; + +static mykonosAgcCfg_t obsRxAgcConfig = +{ + 255, /* agcRx1MaxGainIndex */ + 195, /* agcRx1MinGainIndex */ + 255, /* agcRx2MaxGainIndex */ + 195, /* agcRx2MinGainIndex: */ + 255, /* agcObsRxMaxGainIndex */ + 203, /* agcObsRxMinGainIndex */ + 1, /* agcObsRxSelect */ + 1, /* agcPeakThresholdMode */ + 1, /* agcLowThsPreventGainIncrease */ + 30720, /* agcGainUpdateCounter */ + 3, /* agcSlowLoopSettlingDelay */ + 2, /* agcPeakWaitTime */ + 1, /* agcResetOnRxEnable */ + 0, /* agcEnableSyncPulseForGainCounter */ + &obsRxPeakAgc, + &obsRxPwrAgc +}; + + +static mykonosRxProfile_t rxProfile = +{/* Rx 100MHz, IQrate 122.88MSPS, Dec5 */ + 1, /* The divider used to generate the ADC clock*/ + &rxFir, /* Pointer to Rx FIR filter structure*/ + 2, /* Rx FIR decimation (1,2,4)*/ + 5, /* Decimation of Dec5 or Dec4 filter (5,4)*/ + 1, /* If set, and DEC5 filter used, will use a higher rejection DEC5 FIR filter (1=Enabled, 0=Disabled)*/ + 1, /* RX Half band 1 decimation (1 or 2)*/ + 122880, /* Rx IQ data rate in kHz*/ + 100000000, /* The Rx RF passband bandwidth for the profile*/ + 100000, /* Rx BBF 3dB corner in kHz*/ + NULL /* pointer to custom ADC profile*/ +}; + +static mykonosRxProfile_t orxProfile = +{/* ORX 100MHz, IQrate 122.88MSPS, Dec5 */ + 1, /* The divider used to generate the ADC clock*/ + &obsrxFir, /* Pointer to Rx FIR filter structure or NULL*/ + 2, /* Rx FIR decimation (1,2,4)*/ + 5, /* Decimation of Dec5 or Dec4 filter (5,4)*/ + 0, /* If set, and DEC5 filter used, will use a higher rejection DEC5 FIR filter (1=Enabled, 0=Disabled)*/ + 1, /* RX Half band 1 decimation (1 or 2)*/ + 122880, /* Rx IQ data rate in kHz*/ + 100000000, /* The Rx RF passband bandwidth for the profile*/ + 100000, /* Rx BBF 3dB corner in kHz*/ + NULL /* pointer to custom ADC profile*/ +}; + + +static mykonosRxProfile_t snifferProfile = +{ /* SRx 20MHz, IQrate 30.72MSPS, Dec5 */ + 1, /* The divider used to generate the ADC clock*/ + &snifferRxFir, /* Pointer to Rx FIR filter structure or NULL*/ + 4, /* Rx FIR decimation (1,2,4)*/ + 5, /* Decimation of Dec5 or Dec4 filter (5,4)*/ + 0, /* If set, and DEC5 filter used, will use a higher rejection DEC5 FIR filter (1=Enabled, 0=Disabled)*/ + 2, /* RX Half band 1 decimation (1 or 2)*/ + 30720, /* Rx IQ data rate in kHz*/ + 10000000, /* The Rx RF passband bandwidth for the profile*/ + 100000, /* Rx BBF 3dB corner in kHz*/ + NULL /* pointer to custom ADC profile*/ +}; + + + +static mykonosTxProfile_t txProfile = +{ /* Tx 20/100MHz, IQrate 122.88MSPS, Dec5 */ + DACDIV_2p5, /* The divider used to generate the DAC clock*/ + &txFir, /* Pointer to Tx FIR filter structure*/ + 2, /* The Tx digital FIR filter interpolation (1,2,4)*/ + 2, /* Tx Halfband1 filter interpolation (1,2)*/ + 1, /* Tx Halfband2 filter interpolation (1,2)*/ + 1, /* TxInputHbInterpolation (1,2)*/ + 122880, /* Tx IQ data rate in kHz*/ + 100000000, /* Primary Signal BW*/ + 100000000, /* The Tx RF passband bandwidth for the profile*/ + 710539, /* The DAC filter 3dB corner in kHz*/ + 50000, /* Tx BBF 3dB corner in kHz*/ + 0 /* Enable DPD, only valid for AD9373*/ +}; + +static mykonosDigClocks_t mykonosClocks = +{ + 122880, /* CLKPLL and device reference clock frequency in kHz*/ + 9830400, /* CLKPLL VCO frequency in kHz*/ + VCODIV_2, /* CLKPLL VCO divider*/ + 4 /* CLKPLL high speed clock divider*/ +}; + +static mykonosRxSettings_t rxSettings = +{ + &rxProfile, /* Rx datapath profile, 3dB corner frequencies, and digital filter enables*/ + &rxFramer, /* Rx JESD204b framer configuration structure*/ + &rxGainControl, /* Rx Gain control settings structure*/ + &rxAgcConfig, /* Rx AGC control settings structure*/ + RX1_RX2, /* The desired Rx Channels to enable during initialization*/ + 0, /* Internal LO = 0, external LO*2 = 1*/ + 2550000000U, /* Rx PLL LO Frequency (internal or external LO)*/ + 0 /* Flag to choose if complex baseband or real IF data are selected for Rx and ObsRx paths. Where, if > 0 = real IF data, '0' = zero IF (IQ) data*/ +}; + +static mykonosDpdConfig_t dpdConfig = +{ + 5, /* 1/2^(damping + 8) fraction of power `forgotten' per sample (default: `1/8192' = 5, valid 0 to 15), 0 = infinite damping*/ + 1, /* number of weights to use for int8_cpx weights weights member of this structure (default = 1)*/ + 2, /* DPD model version: one of four different generalized polynomial models: 0 = same as R0 silicon, 1-3 are new and the best one depends on the PA (default: 2)*/ + 1, /* 1 = Update saved model whenever peak Tx digital RMS is within 1dB of historical peak Tx RMS*/ + 20, /* Determines how much weight the loaded prior model has on DPD modeling (Valid 0 - 32, default 20)*/ + 0, /* Default off = 0, 1=enables automatic outlier removal during DPD modeling */ + 512, /* Number of samples to capture (default: 512, valid 64-32768)*/ + 4096, /* threshold for sample in AM-AM plot outside of 1:1 line to be thrown out. (default: 50% = 8192/2, valid 8192 to 1)*/ + 0, /* 16th of an ORx sample (16=1sample), (default 0, valid -64 to 64)*/ + 255, /* Default 255 (-30dBFs=(20Log10(value/8192)), (valid range 1 to 8191)*/ + {{64,0},{0,0},{0,0}}/* DPD model error weighting (real/imag valid from -128 to 127)*/ +}; + +static mykonosClgcConfig_t clgcConfig = +{ + -2000, /* (value = 100 * dB (valid range -32768 to 32767) - total gain and attenuation from Mykonos Tx1 output to ORx1 input in (dB * 100)*/ + -2000, /* (value = 100 * dB (valid range -32768 to 32767) - total gain and attenuation from Mykonos Tx2 output to ORx2 input in (dB * 100)*/ + 0, /* (valid range 0 - 40dB), no default, depends on PA, Protects PA by making sure Tx1Atten is not reduced below the limit*/ + 0, /* (valid range 0 - 40dB), no default, depends on PA, Protects PA by making sure Tx2Atten is not reduced below the limit*/ + 75, /* valid range 1-100, default 75*/ + 75, /* valid range 1-100, default 45*/ + 0, /* 0= allow CLGC to run, but Tx1Atten will not be updated. User can still read back power measurements. 1=CLGC runs, and Tx1Atten automatically updated*/ + 0, /* 0= allow CLGC to run, but Tx2Atten will not be updated. User can still read back power measurements. 1=CLGC runs, and Tx2Atten automatically updated*/ + 0, /* 16th of an ORx sample (16=1sample), (default 0, valid -64 to 64)*/ + 255, /* Default 255 (-30dBFs=(20Log10(value/8192)), (valid range 1 to 8191)*/ + 600, /* Threshold for Tx1 in order to stop tracking, value = 100 * dB, default 6db then value = 600*/ + 600, /* Threshold for Tx2 in order to stop tracking, value = 100 * dB, default 6db then value = 600*/ + 0, /* Threshold feature enable for Tx1, 0 = disable, 1 = enable, default = 0*/ + 0 /* Threshold feature enable for Tx1, 0 = disable, 1 = enable, default = 0*/ +}; + +static mykonosVswrConfig_t vswrConfig = +{ + 0, /* 16th of an ORx sample (16=1sample), (default 0, valid -64 to 64)*/ + 255, /* Default 255 (-30dBFs=(20Log10(value/8192)), (valid range 1 to 8191)*/ + 0, /* 3p3V GPIO pin to use to control VSWR switch for Tx1 (valid 0-11) (output from Mykonos)*/ + 1, /* 3p3V GPIO pin to use to control VSWR switch for Tx2 (valid 0-11) (output from Mykonos)*/ + 0, /* 3p3v GPIO pin polarity for forward path of Tx1, opposite used for reflection path (1 = high level, 0 = low level)*/ + 0, /* 3p3v GPIO pin polarity for forward path of Tx2, opposite used for reflection path (1 = high level, 0 = low level)*/ + 50, /* Delay for Tx1 after flipping the VSWR switch until measurement is made. In us resolution*/ + 50 /* Delay for Tx2 after flipping the VSWR switch until measurement is made. In us resolution*/ +}; + +static mykonosTxSettings_t txSettings = +{ + &txProfile, /* Tx datapath profile, 3dB corner frequencies, and digital filter enables*/ + &deframer, /* Mykonos JESD204b deframer config for the Tx data path*/ + TX1_TX2, /* The desired Tx channels to enable during initialization*/ + 0, /* Internal LO=0, external LO*2 if =1*/ + 2500000000U, /* Tx PLL LO frequency (internal or external LO)*/ + TXATTEN_0P05_DB,/* Initial and current Tx1 Attenuation*/ + 10000, /* Initial and current Tx1 Attenuation mdB*/ + 10000, /* Initial and current Tx2 Attenuation mdB*/ + NULL, /* DPD,CLGC,VSWR settings. Only valid for AD9373 device, set pointer to NULL otherwise*/ + NULL, /* CLGC Config Structure. Only valid for AD9373 device, set pointer to NULL otherwise*/ + NULL /* VSWR Config Structure. Only valid for AD9373 device, set pointer to NULL otherwise*/ +}; + + +static mykonosObsRxSettings_t obsRxSettings = +{ + &orxProfile, /* ORx datapath profile, 3dB corner frequencies, and digital filter enables*/ + &orxGainControl,/* ObsRx gain control settings structure*/ + &obsRxAgcConfig,/* ORx AGC control settings structure*/ + &snifferProfile,/* Sniffer datapath profile, 3dB corner frequencies, and digital filter enables*/ + &snifferGainControl,/* SnRx gain control settings structure*/ + &obsRxFramer, /* ObsRx JESD204b framer configuration structure */ + (MYK_ORX1_ORX2 | MYK_SNRXA_B_C),/* obsRxChannel */ + OBSLO_TX_PLL, /* (obsRxLoSource) The Obs Rx mixer can use the Tx Synth(TX_PLL) or Sniffer Synth (SNIFFER_PLL) */ + 2600000000U, /* SnRx PLL LO frequency in Hz */ + 0, /* Flag to choose if complex baseband or real IF data are selected for Rx and ObsRx paths. Where if > 0 = real IF data, '0' = complex data*/ + NULL, /* Custom Loopback ADC profile to set the bandwidth of the ADC response */ + OBS_RXOFF /* Default ObsRx channel to enter when radioOn called */ +}; + +static mykonosArmGpioConfig_t armGpio = +{ + 1, // useRx2EnablePin; /*!< 0= RX1_ENABLE controls RX1 and RX2, 1 = separate RX1_ENABLE/RX2_ENABLE pins */ + 1, // useTx2EnablePin; /*!< 0= TX1_ENABLE controls TX1 and TX2, 1 = separate TX1_ENABLE/TX2_ENABLE pins */ + 1, // txRxPinMode; /*!< 0= ARM command mode, 1 = Pin mode to power up Tx/Rx chains */ + 0, // orxPinMode; /*!< 0= ARM command mode, 1 = Pin mode to power up ObsRx receiver*/ + + /*Mykonos ARM input GPIO pins -- Only valid if orxPinMode = 1 */ + 0, // orxTriggerPin; /*!< Select desired GPIO pin (valid 4-15) */ + 0, // orxMode2Pin; /*!< Select desired GPIO pin (valid 0-18) */ + 0, // orxMode1Pin; /*!< Select desired GPIO pin (valid 0-18) */ + 0, // orxMode0Pin; /*!< Select desired GPIO pin (valid 0-18) */ + + /* Mykonos ARM output GPIO pins -- always available, even when pin mode not enabled*/ + 0, // rx1EnableAck; /*!< Select desired GPIO pin (0-15), [4] = Output Enable */ + 0, // rx2EnableAck; /*!< Select desired GPIO pin (0-15), [4] = Output Enable */ + 0, // tx1EnableAck; /*!< Select desired GPIO pin (0-15), [4] = Output Enable */ + 0, // tx2EnableAck; /*!< Select desired GPIO pin (0-15), [4] = Output Enable */ + 0, // orx1EnableAck; /*!< Select desired GPIO pin (0-15), [4] = Output Enable */ + 0, // orx2EnableAck; /*!< Select desired GPIO pin (0-15), [4] = Output Enable */ + 0, // srxEnableAck; /*!< Select desired GPIO pin (0-15), [4] = Output Enable */ + 0 // txObsSelect; /*!< Select desired GPIO pin (0-15), [4] = Output Enable */ + /* When 2Tx are used with only 1 ORx input, this GPIO tells the BBIC which Tx channel is */ + /* active for calibrations, so BBIC can route correct RF Tx path into the single ORx input*/ +}; + +static mykonosGpio3v3_t gpio3v3 = +{ + 0, /*!< Oe per pin, 1=output, 0 = input */ + GPIO3V3_BITBANG_MODE, /*!< Mode for GPIO3V3[3:0] */ + GPIO3V3_BITBANG_MODE, /*!< Mode for GPIO3V3[7:4] */ + GPIO3V3_BITBANG_MODE, /*!< Mode for GPIO3V3[11:8] */ +}; + +static mykonosGpioLowVoltage_t gpio = +{ + 0,/* Oe per pin, 1=output, 0 = input */ + GPIO_MONITOR_MODE,/* Mode for GPIO[3:0] */ + GPIO_MONITOR_MODE,/* Mode for GPIO[7:4] */ + GPIO_MONITOR_MODE,/* Mode for GPIO[11:8] */ + GPIO_MONITOR_MODE,/* Mode for GPIO[15:12] */ + GPIO_MONITOR_MODE,/* Mode for GPIO[18:16] */ +}; + +static mykonosAuxIo_t mykonosAuxIo = +{ + 0, //auxDacEnableMask uint16_t + {0,0,0,0,0,0,0,0,0,0}, //AuxDacValue uint16[10] + {0,0,0,0,0,0,0,0,0,0}, //AuxDacSlope uint8[10] + {0,0,0,0,0,0,0,0,0,0}, //AuxDacVref uint8[10] + &gpio3v3, //pointer to gpio3v3 struct + &gpio, //pointer to gpio1v8 struct + &armGpio +}; + +static spiSettings_t mykSpiSettings = +{ + 1, /* chip select index - valid 1~8 */ + 0, /* the level of the write bit of a SPI write instruction word, value is inverted for SPI read operation */ + 1, /* 1 = 16-bit instruction word, 0 = 8-bit instruction word */ + 1, /* 1 = MSBFirst, 0 = LSBFirst */ + 0, /* clock phase, sets which clock edge the data updates (valid 0 or 1) */ + 0, /* clock polarity 0 = clock starts low, 1 = clock starts high */ + 0, /* Not implemented in ADIs platform layer. SW feature to improve SPI throughput */ + 1, /* Not implemented in ADIs platform layer. For SPI Streaming, set address increment direction. 1= next addr = addr+1, 0:addr=addr-1 */ + 1 /* 1: Use 4-wire SPI, 0: 3-wire SPI (SDIO pin is bidirectional). NOTE: ADI's FPGA platform always uses 4-wire mode */ +}; + +static mykonosTempSensorConfig_t tempSensor = +{ + 7, /* 3-bit value that controls the AuxADC decimation factor when used for temp sensor calculations; AuxADC_decimation = 256 * 2^tempDecimation*/ + 67, /* 8-bit offset that gets added to temp sensor code internally*/ + 1, /* this bit overrides the factory-calibrated fuse offset and uses the value stored in the offset member*/ + 15, /* 4-bit code with a resolution of 1°C/LSB, each time a temperature measurement is performed, the device compares the current temperature against the previous value.*/ +}; + +static mykonosTempSensorStatus_t tempStatus = +{ + 0, /* 16-bit signed temperature value (in deg C) that is read back*/ + 0, /* If the absolute value of the difference is greater than the value in temperature configuration tempWindow, the windowExceeded flag is set.*/ + 0, /* when windowExceeded member gets set, this bit is set to 1 if current value is greater than previous value, else reset*/ + 0, /* when the reading is complete and a valid temperature value stored in tempCode.*/ +}; + +mykonosDevice_t mykDevice = +{ + &mykSpiSettings, /* SPI settings data structure pointer */ + &rxSettings, /* Rx settings data structure pointer */ + &txSettings, /* Tx settings data structure pointer */ + &obsRxSettings, /* ObsRx settings data structure pointer */ + &mykonosAuxIo, /* Auxiliary IO settings data structure pointer */ + &mykonosClocks, /* Holds settings for CLKPLL and reference clock */ + 0 /* Mykonos initialize function uses this as an output to remember which profile data structure pointers are valid */ +}; diff --git a/datalink814_ge/src/hardware/myk_init.h b/datalink814_ge/src/hardware/myk_init.h new file mode 100644 index 0000000..ef11bad --- /dev/null +++ b/datalink814_ge/src/hardware/myk_init.h @@ -0,0 +1,24 @@ +/** + * \file myk_init.h + * + * \brief Contains structure definitions for myk_init.c + * + * The top level structure mykonosDevice_t mykDevice uses keyword + * extern to allow the application layer main() to have visibility + * to these settings. + */ + +/** +* \page Disclaimer Legal Disclaimer +* Copyright 2015-2017 Analog Devices Inc. +* Released under the AD9371 API license, for more information see the "LICENSE.txt" file in this zip file. +* +*/ + +#ifndef MYK_INIT_H_ +#define MYK_INIT_H_ + + +extern mykonosDevice_t mykDevice; + +#endif diff --git a/datalink814_ge/src/hardware/mykonos/Mykonos_M3.c b/datalink814_ge/src/hardware/mykonos/Mykonos_M3.c new file mode 100644 index 0000000..369ad92 --- /dev/null +++ b/datalink814_ge/src/hardware/mykonos/Mykonos_M3.c @@ -0,0 +1,8518 @@ +/** + +SOFTWARE LICENSE AGREEMENT +20180301-AD937X-CTSLA + +This Software License Agreement (the 鈥淎greement鈥�) is a legal agreement +between Analog Devices, Inc., a Massachusetts corporation, with its principal +office at One Technology Way, Norwood, Massachusetts, USA 02062 (鈥淎nalog +Devices鈥�) and you (personally or on behalf of your employer, as applicable) +(鈥淟icensee鈥�) for the software and related documentation that accompanies +this Agreement (the 鈥淟icensed Software鈥�). YOU AGREE THAT YOU ARE BOUND BY +THE TERMS AND CONDITIONS OF THIS AGREEMENT BY DOWNLOADING, INSTALLING, COPYING +OR USING THE SOFTWARE. IF YOU DO NOT AGREE, DO NOT DOWNLOAD, INSTALL, COPY OR +USE THE SOFTWARE. + +1. Development License. Subject to terms of this Agreement, Analog Devices +grants to Licensee a non-exclusive, non-transferable, non-sublicensable +license, without charge, to incorporate Licensed Software in object code form +into Licensee products solely for use within Analog Devices products that are +incorporated into such Licensee products. The licenses granted under Sections +1 and 2 of this Agreement are limited to the specific Analog Devices products +identified in Appendix A to this Agreement. + +2. Distribution License. Subject to the terms of this Agreement, Analog +Devices grants to Licensee a non-exclusive, non-transferrable, +non-sublicensable license, to copy and distribute Licensed Software in object +code form solely for use within Analog Devices products that are incorporated +into Licensee products. Distribution is limited to Licensed Software in object +code form that is incorporated into Licensee products. + +3. License to Analog Devices. During the term of this Agreement Licensee +grants to Analog Devices (and its affiliates) under any and all Licensee (and +its affiliates) patents a non-exclusive, worldwide, fully paid-up, royalty-free +license to make, use, sell, import, export, copy, distribute and otherwise +exploit Licensed Software in-whole or in-part (including updated versions of +Licensed Software), and to directly or indirectly sub-license others to do the +same. + +4. Restrictions. Licensee shall not modify, reverse engineer, decompile, +disassemble or create derivative works of Licensed Software. Licensee may only +copy the Licensed Software as expressly authorized in Sections 1 and 2 above. +In no event shall Licensee deliver or disclose the Licensed Software apart from +Licensee products to any third party without entering into a written license +agreement with Analog Devices expressly permitting such distribution. The +Licensed Software may not be used with any products other than Analog +Devices鈥� products or for any other purpose. + +Licensee shall not use or distribute the Licensed Software in any manner that +would cause Licensed Software, in whole or in part to become subject to any +terms of an Excluded License. An 鈥淓xcluded License鈥� means any license, +including licenses for 鈥渙pen source鈥� code (as defined by the Free Software +Foundation), that requires as a condition of use, modification, and/or +distribution of software subject to the Excluded License, that such software or +other software combined and/or distributed with such software be (i) disclosed +or distributed in source code form; (ii) licensed for the purpose of making +derivative works; or (iii) redistributable at no charge. The restrictions of +this section apply regardless of whether the Licensed Software is intended or +designed to run in an environment that includes software under an Excluded +License. Any license, agreement or other document issued, entered into or +granted by Licensee that purports to apply any Excluded License to any portion +of Licensed Software shall be null and void with regard to Licensed Software. +Under no circumstances will Licensee offer, provide, distribute, or license any +Licensed Software (whether in source code form or object code form) under any +form of Excluded License. + +All rights not expressly granted in this Agreement are reserved to Analog +Devices and its licensors. Analog Devices and its licensors retain all right, +title and interest in the Licensed Software and modifications thereof, +including all related patent, copyright and other intellectual property rights, +and Licensee shall not take any action inconsistent with such ownership. Any +use of the Licensed Software for any purpose other than as expressly licensed +hereunder is outside the scope of this Agreement. It is agreed that because of +the proprietary nature of the Licensed Software, Analog Devices鈥� remedies at +law for a breach by the Licensee of its obligations under this License or for +use of the Licensed Software beyond the scope of the license granted herein +will be inadequate and that Analog Devices will, in the event of such breach, +be entitled to equitable relief, including injunctive relief, without the +posting of any bond, in addition to all other remedies provided under this +License or available at law. + +If Analog Devices elects to make any update, upgrade or new version of the +Licensed Software (鈥淯pdates鈥�) available to Licensee, such Updates shall be +deemed to be Licensed Software under this Agreement. If requested by Analog +Devices, Licensee shall only use the latest version of the Licensed Software +(including Updates). Analog Devices shall have no obligation to provide +support or Updates. + +5. Publicity. Notwithstanding anything in this Agreement, Licensee may not use +any trademark or trade name of Analog Devices or make any public announcement +regarding the existence of this Agreement without Analog Devices鈥� prior +written consent. Licensee may not publish or provide the results of any +benchmark or comparison tests run on the Licensed Software to any third party +without the prior written consent of Analog Devices. + +6. Feedback. Licensee may from time to time provide suggestions, ideas, +comments or other feedback (鈥淔eedback鈥�) to Analog Devices with respect to +the Licensed Software. Licensee agrees that all Feedback is and shall be given +entirely voluntarily. To the extent Licensee provides such Feedback, however, +Licensee hereby grants to Analog Devices a non-exclusive, irrevocable, +perpetual, worldwide, royalty-free, transferable license, with the right to +sublicense, under Licensee鈥檚 intellectual property, to use and disclose +Feedback in any manner Analog Devices chooses and to display, perform, copy, +make, have made, use, sell, and otherwise dispose of Analog Devices鈥� and its +licensee鈥檚 products embodying such Feedback in any manner and via any media +Analog Devices chooses, without reference to its source or other obligation to +Analog Devices, even if the Feedback is designated as confidential. + +7. Confidentiality. Licensed Software in source code form and accompanying +documentation shall be regarded as 鈥æ·�onfidential Information鈥� of Analog +Devices and Licensee agrees to protect the confidentiality of Analog Devices鈥� +Confidential Information with at least the same degree of care that it utilizes +with respect to its own similar proprietary information (but in no event less +than a reasonable degree of care), including without limitation agreeing (i) +not to disclose or otherwise permit any other person or entity access to +Confidential Information or to use Confidential Information or any part thereof +in any form whatsoever, except that such disclosure or access shall be +permitted to an employee or consultant of Licensee requiring access to +Confidential Information in connection with this Agreement who has signed an +agreement obligating the employee/consultant to maintain the confidentiality of +confidential information in Licensee鈥檚 possession, (ii) to notify Analog +Devices promptly and in writing of the circumstances surrounding any suspected +possessions, use, or knowledge of Confidential Information other than those +authorized by this Agreement, and (iii) not to use Confidential Information for +any purpose other than as explicitly set forth herein. Nothing shall restrict +Licensee with respect to information or data that is independently developed or +is available to the general public otherwise than through any act or default of +Licensee. + +8. Copyright Notice. In no event shall Licensee remove any copyright or other +intellectual property notice or other legend contained on or in copies of +Licensed Software or displayed by any Licensed Software. + +9. Third Party Software. The Licensed Software may be accompanied by or +include software made available by one or more third parties (鈥淭hird Party +Software鈥�). Each portion of Third Party Software is subject to its own +separate software license terms and conditions (鈥淭hird Party Licenses鈥�). +The Third Party Licenses for Third Party Software delivered with the Licensed +Software may be set forth or identified (by URL or otherwise) in (i) Appendix A +to this license (if any), (ii) the applicable software header or footer text, +(iii) a text file located in the directory of the applicable Third Party +Software component and/or (iv) such other location customarily used for +licensing terms. The use of each portion of Third Party Software is subject to +the Third Party Licenses, and you agree that your use of any Third Party +Software is bound by the applicable Third Party License. You agree to review +and comply with all applicable Third Party Licenses prior to any use or +distribution of any Third Party Software. Third Party Software is provided on +an 鈥æ¸�s is鈥� basis without any representation, warranty or liability of any +kind. Analog Devices (including its licensors) shall have no liability or +responsibility for the operation or performance of the Third Party Software and +shall not be liable for any damages, costs, or expenses, direct or indirect, +arising out of the performance or failure to perform of the Third Party +Software. Analog Devices (including its licensors) shall be entitled to the +benefit of any and all limitations of liability and disclaimers of warranties +contained in the Third Party Licenses. + +In the event that Third Party Software has only been provided to you in object +code form under this Agreement, and the Third Party License requires +distribution of the corresponding source code, you may contact +software.licensing@analog.com regarding receiving a copy of such source code. + +10. Licensee Requirements. Licensee acknowledges that use or distribution of +the Licensed Software may require Licensee to obtain licenses to intellectual +property or other consents from one or more third parties. Licensee is +responsible for obtaining any and all such required licenses, or permissions +regarding the Licensed Software and for the performance of any and all required +tests or analysis necessary or appropriate for the determination of the +suitability of the Licensed Software for its or its customers鈥� purposes. +Licensee shall defend, indemnify and hold Analog Devices, its licensors, and +their respective officers, directors, employees and agents (each an +鈥淚ndemnified Party鈥�) harmless from and against any damages, fines, +penalties, assessments, liabilities, costs and expenses (including reasonable +attorneys鈥� fees and court costs) in the event that any claim is brought +against an Indemnified Party (i) arising or alleged to arise from Licensee鈥檚 +use or distribution of Licensed Software or Third Party Software, or (ii) on +account of Licensee鈥檚 failure to obtain any required license or consent to +use or distribute Licensed Software or Third Party Software. Licensee shall +bear any and all expenses and pay any and all taxes that may be payable in +relation to this Agreement. + +11. Audit. Analog Devices shall have the right upon ten (10) days prior +written notice to audit Licensee鈥檚 compliance with the terms of this +Agreement during normal business hours. In connection with such audit Analog +Devices shall have access to all reasonably requested documents, equipment, +information and personnel. Licensee shall maintain complete and accurate +records of its use of the Licensed Software for a period of at least three +years from the applicable use of the Licensed Software. + +12. License Term; Term of Agreement. This Agreement is effective upon receipt +of the Licensed Software and shall continue for three (3) years, unless earlier +terminated as permitted in this Agreement. This Agreement will automatically +renew for additional one (1) year terms unless indicated otherwise in writing +by either of the parties thirty (30) days prior to any renewal date. Licensee +may terminate this Agreement at any time by giving written notice to Analog +Devices. Analog Devices may terminate this Agreement at any time in the event +of any failure by Licensee to comply with any term or condition of the +Agreement. In the event of termination, Licensee must permanently delete all +copies of Licensed Software and all of its component parts, including any +backup or archival copies. Licenses granted to end users prior to termination +shall survive. The provisions of Sections 3-22 shall survive any termination +or expiration of this Agreement according to their terms. + +13. DISCLAIMER AND LIMITATION OF WARRANTIES. LICENSED SOFTWARE AND THIRD PARTY +SOFTWARE ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, AND ANALOG DEVICES, +FOR ITSELF AND ITS LICENSORS, HEREBY DISCLAIMS ALL WARRANTIES, WHETHER EXPRESS +OR IMPLIED, ORAL OR WRITTEN, WITH RESPECT TO THE LICENSED SOFTWARE AND THIRD +PARTY SOFTWARE, INCLUDING, BUT NOT LIMITED TO, ANY EXPRESS AND IMPLIED +WARRANTIES OF MERCHANTABILITY; FITNESS FOR PARTICULAR PURPOSE AND SYSTEM +INTEGRATION; CONDITIONS OF QUALITY AND ACCURACY OF INFORMATIONAL CONTENT; +NON-INFRINGEMENT; QUIET ENJOYMENT; AND TITLE. LICENSEE AGREES THAT ANY EFFORTS +BY ANALOG DEVICES TO MODIFY OR UPDATE LICENSED SOFTWARE OR THIRD PARTY SOFTWARE +SHALL NOT BE DEEMED A WAIVER OF THESE LIMITATIONS, AND THAT ANY ANALOG DEVICES +WARRANTIES SHALL NOT BE DEEMED TO HAVE FAILED OF THEIR ESSENTIAL PURPOSE. + +14. Limitation of Liability. TO THE MAXIMUM EXTENT PERMITTED BY LAW ANALOG +DEVICES (INCLUDING ITS LICENSORS) SHALL NOT BE LIABLE FOR ANY DAMAGES ARISING +FROM OR RELATED TO THE LICENSED SOFTWARE, THIRD PARTY SOFTWARE, THEIR USE OR +ANY RELATED INFORMATION AND/OR SERVICES, INCLUDING BUT NOT LIMITED TO ANY +INDIRECT, INCIDENTAL, SPECIAL, PUNITIVE, EXEMPLARY, CONSEQUENTIAL OR ANALOGOUS +DAMAGES (INCLUDING WITHOUT LIMITATION ANY DAMAGES RESULTING FROM LOSS OF USE, +DATA, REVENUE, PROFITS, OR SAVINGS, COMPUTER DAMAGE OR ANY OTHER CAUSE), UNDER +ANY LEGAL THEORY (INCLUDING WITHOUT LIMITATION CONTRACT, WARRANTY, TORT, +NEGLIGENCE, STRICT OR PRODUCT LIABILITY), EVEN IF IT HAS BEEN INFORMED OF THE +POSSIBILITY OF SUCH DAMAGES. + +IN NO EVENT SHALL ANALOG DEVICES鈥� OR ITS LICENSORS鈥� CUMULATIVE LIABILITY +FOR DAMAGES TO LICENSEE FOR ANY AND ALL CAUSES WHATSOEVER, REGARDLESS OF THE +FORM OF ANY CLAIMS OR ACTIONS, EXCEED THE GREATER OF (1) ONE HUNDRED U.S. +DOLLARS ($100.00 U.S.) OR (2) THE AMOUNT PAID TO ANALOG DEVICES HEREUNDER FOR +THE LICENSED SOFTWARE. + +Some jurisdictions do not permit the exclusion or limitation of liability for +consequential or incidental damages, and, as such, some portion of the above +limitation may not apply to Licensee. In such jurisdictions, Analog Devices' +liability is limited to the greatest extent permitted by law. + +15. HIGH RISK APPLICATIONS. THE LICENSED SOFTWARE IS NOT DESIGNED OR INTENDED +FOR USE IN HAZARDOUS ENVIRONMENTS REQUIRING FAIL-SAFE PERFORMANCE, INCLUDING, +WITHOUT LIMITATION, IN THE OPERATION OF NUCLEAR FACILITIES, AIRCRAFT NAVIGATION +OR CONTROL SYSTEMS, AIR TRAFFIC CONTROL, LIFE SUPPORT MACHINES, WEAPONS +SYSTEMS, OR ANY OTHER APPLICATION IN WHICH THE FAILURE OF THE LICENSED SOFTWARE +COULD LEAD TO DEATH, PERSONAL INJURY OR SEVERE PHYSICAL OR ENVIRONMENTAL +DAMAGES (鈥淗IGH RISK ACTIVITIES鈥�). LICENSED SOFTWARE IS NOT DESIGNED, +AUTHORIZED, OR WARRANTED TO BE SUITABLE FOR USE IN CONNECTION WITH HIGH RISK +ACTIVITIES. USE OF LICENSED SOFTWARE IN CONNECTION WITH HIGH RISK ACTIVITIES +IS UNDERSTOOD TO BE FULLY AT LICENSEE鈥橲 RISK. + +16. Choice of Law. This Agreement and any dispute related to the Licensed +Software shall be governed by the laws of the Commonwealth of Massachusetts, +United States of America, without reference to its principles of conflicts of +laws, and, as to matters affecting copyrights, trademarks and patents, in +addition, by applicable United States federal law. The parties agree that the +jurisdiction and venue of any action with respect to this Agreement shall be in +a court of competent subject matter jurisdiction located in the Commonwealth of +Massachusetts, and each of the parties hereby agrees to submit itself to the +exclusive jurisdiction and venue of such courts for the purpose of any such +action, except that Analog Devices may seek injunctive relief in any venue of +its choosing. Licensee hereby submits to personal jurisdiction in such courts. +The parties hereto specifically exclude the United Nations Convention on +Contracts for the International Sale of Goods and the Uniform Computer +Information Transactions Act from this Agreement and any transaction between +them that may be implemented in connection with this Agreement. The original of +this Agreement has been written in English. The parties hereto waive any +statute, law, or regulation that might provide an alternative law or forum or +to have this Agreement written in any language other than English. + +17. U.S. Government Restricted Rights. Licensed Software is provided with +RESTRICTED RIGHTS. Use, duplication, or disclosure by the Government is +subject to restrictions as set forth in subparagraphs (a) through (d) of the +Commercial Computer Software - Restricted Rights clause at FAR 52.227-19, +(c)(1)(ii) of The Rights in Technical Data and Computer Software clause at +DFARS 252.227-7013, and in similar clauses in the NASA FAR Supplement, as +applicable. The contractor/manufacturer of this Licensed Software is Analog +Devices, Inc., One Technology Way, Norwood, Massachusetts 02062 USA, or its +authorized licensors. + +18. Export. Licensee shall not export, directly or indirectly, Licensed +Software, or other information or materials provided by Analog Devices or its +suppliers hereunder, to any country for which the United States or any other +relevant jurisdiction requires any export license or other governmental +approval at the time of export without first obtaining such license or +approval. Licensee shall defend indemnify and hold harmless Analog Devices +from and against any damages, fines, penalties, assessments, liabilities, costs +and expenses (including reasonable attorneys鈥� fees and court costs) arising +out of any failure by Licensee to comply with this Section. + +19. Compliance with Laws of Other Jurisdictions. Licensee shall comply with +all laws, legislation, rules, regulations, governmental requirements and +industry standards with respect to Licensed Software, and the performance by +Licensee of its obligations hereunder, existing in any applicable jurisdiction. + +20. Assignment. This Agreement is personal to Licensee and Licensee may not +transfer, sublicense, lease, rent, or assign its rights under this License, and +any such attempt shall be null and void. Analog Devices may assign, transfer, +or sublicense this Agreement or any rights or obligations hereunder at any time +in its sole discretion. + +21. Waiver; Modification; Severability. No waiver, consent, modification or +change of terms of this Agreement shall bind either party unless in writing +signed by both parties, and then such waiver, consent, modification or change +shall be effective only in the specific instance and for the specific purpose +given. If any provision of this Agreement is unenforceable, such provision +shall be enforced to the extent possible under applicable law, and the +remaining provisions will remain in effect. + +22. Entire Agreement. This Agreement supersedes any and all other agreements, +either oral or in writing, between the parties with respect to the matters +stated herein. If, for any reason, any provision of this Agreement is held +invalid, such invalidity shall not affect the remainder of this Agreement, and +this Agreement shall continue in force and effect to the full extent allowed by +law. For the avoidance of doubt, all Licensed Software under this Agreement is +subject to the terms and conditions of this Agreement and not any agreement or +terms for purchase of Analog Devices products, even if the Licensed Software is +delivered with such products. + + +Appendix A + +License limited to Analog Devices transceiver / receiver / transmitter products. + +*/ +#include "Mykonos_M3.h" +// Version 5.2.2 + +unsigned char firmware_Mykonos_M3_bin[] = { + 0x90, 0xbc, 0x00, 0x20, 0x35, 0x6b, 0x01, 0x01, 0xf1, 0x66, 0x01, 0x01, + 0xf1, 0x66, 0x01, 0x01, 0xf1, 0x66, 0x01, 0x01, 0xf1, 0x66, 0x01, 0x01, + 0xf1, 0x66, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf5, 0x6a, 0x01, 0x01, + 0xf7, 0x6a, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x97, 0x7a, 0x00, 0x01, + 0x2d, 0x7a, 0x00, 0x01, 0xf9, 0x6a, 0x01, 0x01, 0xd7, 0x8b, 0x00, 0x01, + 0xe7, 0xeb, 0x00, 0x01, 0x71, 0x52, 0x00, 0x01, 0xfb, 0x6a, 0x01, 0x01, + 0x8d, 0x69, 0x00, 0x01, 0x9d, 0x69, 0x00, 0x01, 0xad, 0x69, 0x00, 0x01, + 0xd9, 0x69, 0x00, 0x01, 0x3f, 0xfd, 0x00, 0x01, 0x07, 0x8d, 0x00, 0x01, + 0x43, 0x8e, 0x00, 0x01, 0xc3, 0x8d, 0x00, 0x01, 0xeb, 0x8e, 0x00, 0x01, + 0xff, 0x32, 0x00, 0x01, 0x31, 0xf1, 0x00, 0x01, 0xd3, 0x8c, 0x00, 0x01, + 0x7b, 0xf2, 0x00, 0x01, 0xfd, 0x6a, 0x01, 0x01, 0x6b, 0x5f, 0x00, 0x01, + 0xff, 0x6a, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x01, 0x03, 0x6b, 0x01, 0x01, + 0x05, 0x6b, 0x01, 0x01, 0x07, 0x6b, 0x01, 0x01, 0x51, 0xf4, 0x00, 0x01, + 0x09, 0x6b, 0x01, 0x01, 0x0b, 0x6b, 0x01, 0x01, 0x93, 0xfd, 0x00, 0x01, + 0x53, 0x8d, 0x00, 0x01, 0x7f, 0x8e, 0x00, 0x01, 0x65, 0x8f, 0x00, 0x01, + 0xbd, 0x9d, 0x00, 0x01, 0x11, 0xf3, 0x00, 0x01, 0x2d, 0xf2, 0x00, 0x01, + 0x5f, 0xf2, 0x00, 0x01, 0x0d, 0x6b, 0x01, 0x01, 0x0f, 0x6b, 0x01, 0x01, + 0x11, 0x6b, 0x01, 0x01, 0x13, 0x6b, 0x01, 0x01, 0x15, 0x6b, 0x01, 0x01, + 0x17, 0x6b, 0x01, 0x01, 0x19, 0x6b, 0x01, 0x01, 0x1b, 0x6b, 0x01, 0x01, + 0x1d, 0x6b, 0x01, 0x01, 0x1f, 0x6b, 0x01, 0x01, 0x21, 0x6b, 0x01, 0x01, + 0xf7, 0x82, 0x00, 0x01, 0x23, 0x6b, 0x01, 0x01, 0xdb, 0x82, 0x00, 0x01, + 0x25, 0x6b, 0x01, 0x01, 0x27, 0x6b, 0x01, 0x01, 0x29, 0x6b, 0x01, 0x01, + 0x2b, 0x6b, 0x01, 0x01, 0x2d, 0x6b, 0x01, 0x01, 0x2f, 0x6b, 0x01, 0x01, + 0x31, 0x6b, 0x01, 0x01, 0x33, 0x6b, 0x01, 0x01, 0x1a, 0xc4, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x1f, 0x15, 0x00, 0x00, 0x74, 0x72, 0x75, 0x6e, + 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xf0, 0xb7, 0x00, 0x20, 0xb8, 0x82, 0x00, 0x20, 0x00, 0xf2, 0x00, 0x20, + 0x10, 0xf1, 0x00, 0x20, 0x78, 0x29, 0x00, 0x20, 0xa4, 0x2b, 0x00, 0x20, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x8c, 0x09, 0x00, 0x20, 0xf0, 0xb2, 0x00, 0x20, 0x98, 0xb4, 0x00, 0x20, + 0x00, 0x00, 0x70, 0x47, 0x4c, 0xbd, 0x00, 0x20, 0x38, 0xb2, 0x00, 0x20, + 0xe0, 0xb3, 0x00, 0x20, 0xb8, 0x00, 0xff, 0xff, 0xef, 0xf3, 0x11, 0x80, + 0x60, 0x21, 0x81, 0xf3, 0x11, 0x88, 0x70, 0x47, 0x38, 0xb5, 0x14, 0x46, + 0x00, 0x22, 0x82, 0x70, 0x00, 0xf1, 0x4c, 0x05, 0xdf, 0xf8, 0x14, 0x29, + 0x82, 0x61, 0x00, 0x22, 0xc2, 0x61, 0x02, 0x62, 0x02, 0x80, 0x82, 0x81, + 0x01, 0x22, 0xc2, 0x81, 0x02, 0x82, 0x42, 0x82, 0x00, 0x22, 0xa0, 0xf8, + 0x18, 0x22, 0x40, 0x22, 0xea, 0x83, 0x2a, 0x84, 0x00, 0x22, 0x6a, 0x85, + 0x2a, 0x80, 0xaa, 0x61, 0x41, 0xb1, 0x4f, 0xf0, 0x00, 0x41, 0x41, 0x61, + 0x4f, 0xf0, 0xff, 0x31, 0x01, 0x81, 0x41, 0x81, 0x81, 0x80, 0xc1, 0x80, + 0x01, 0xf0, 0x82, 0xf8, 0xdf, 0xf8, 0xd4, 0x08, 0x34, 0xb9, 0x41, 0x78, + 0x02, 0x78, 0x42, 0xea, 0x01, 0x21, 0xc2, 0x78, 0x80, 0x78, 0x05, 0xe0, + 0x41, 0x79, 0x02, 0x79, 0x42, 0xea, 0x01, 0x21, 0xc2, 0x79, 0x80, 0x79, + 0x09, 0xb2, 0x40, 0xea, 0x02, 0x20, 0xb1, 0xf5, 0x00, 0x5f, 0xa8, 0xbf, + 0xa1, 0xf5, 0x80, 0x41, 0x00, 0xb2, 0xb0, 0xf5, 0x00, 0x5f, 0xa8, 0xbf, + 0xa0, 0xf5, 0x80, 0x40, 0x69, 0x84, 0xa8, 0x84, 0x01, 0xf0, 0x96, 0xfd, + 0xdf, 0xf8, 0x94, 0x08, 0x34, 0x21, 0x01, 0xfb, 0x04, 0x04, 0x20, 0x46, + 0x02, 0xf0, 0xb0, 0xfe, 0x64, 0x20, 0x60, 0x60, 0xbd, 0xe8, 0x31, 0x40, + 0x01, 0xf0, 0x9d, 0xbd, 0x2d, 0xe9, 0xf0, 0x41, 0x04, 0x46, 0x0e, 0x46, + 0x15, 0x46, 0xff, 0xf7, 0x9b, 0xff, 0x00, 0x27, 0x80, 0x46, 0xe1, 0x5f, + 0x70, 0x1e, 0x81, 0x42, 0xbc, 0xbf, 0x72, 0x42, 0x8a, 0x42, 0x05, 0xda, + 0xb4, 0xf9, 0x02, 0x10, 0x81, 0x42, 0xb8, 0xbf, 0x8a, 0x42, 0x02, 0xdb, + 0x27, 0x80, 0x67, 0x80, 0x01, 0x27, 0xb4, 0xf9, 0x00, 0x00, 0x00, 0x12, + 0x00, 0xf0, 0x3f, 0x01, 0xa5, 0xb9, 0x40, 0xf6, 0x15, 0x20, 0x02, 0xf0, + 0xc5, 0xfe, 0x20, 0x88, 0xc1, 0xb2, 0x40, 0xf6, 0x14, 0x20, 0x02, 0xf0, + 0xbf, 0xfe, 0x00, 0xf0, 0x2b, 0xf8, 0x40, 0xf6, 0x17, 0x20, 0x02, 0xf0, + 0xb9, 0xfe, 0x60, 0x88, 0xc1, 0xb2, 0x40, 0xf6, 0x16, 0x20, 0x13, 0xe0, + 0x40, 0xf6, 0x19, 0x20, 0x02, 0xf0, 0xb0, 0xfe, 0x20, 0x88, 0xc1, 0xb2, + 0x40, 0xf6, 0x18, 0x20, 0x02, 0xf0, 0xaa, 0xfe, 0x00, 0xf0, 0x16, 0xf8, + 0x40, 0xf6, 0x1b, 0x20, 0x02, 0xf0, 0xa4, 0xfe, 0x60, 0x88, 0xc1, 0xb2, + 0x40, 0xf6, 0x1a, 0x20, 0x02, 0xf0, 0x9e, 0xfe, 0x01, 0x20, 0xa8, 0x40, + 0xc1, 0xb2, 0x40, 0xf6, 0x1c, 0x20, 0x02, 0xf0, 0x97, 0xfe, 0x88, 0xf3, + 0x11, 0x88, 0x38, 0x46, 0xbd, 0xe8, 0xf0, 0x81, 0xb4, 0xf9, 0x02, 0x00, + 0x00, 0x12, 0x00, 0xf0, 0x3f, 0x01, 0x70, 0x47, 0x2d, 0xe9, 0xf8, 0x4f, + 0x80, 0x46, 0xdf, 0xf8, 0x0c, 0x0e, 0x4f, 0xf4, 0x08, 0x71, 0x01, 0xfb, + 0x08, 0x0a, 0xff, 0xf7, 0x3b, 0xff, 0x83, 0x46, 0x40, 0x46, 0x0a, 0xf1, + 0x6a, 0x05, 0x02, 0xf0, 0xe3, 0xff, 0x2a, 0x88, 0xdf, 0xf8, 0xf0, 0x1d, + 0x40, 0x56, 0x56, 0x56, 0x00, 0x24, 0x81, 0x1b, 0x04, 0xd4, 0xb1, 0x46, + 0x06, 0x46, 0x04, 0xd0, 0x01, 0x21, 0x02, 0xe0, 0x81, 0x46, 0x4f, 0xf0, + 0xff, 0x31, 0x40, 0x2a, 0x1f, 0xd0, 0x01, 0x24, 0x00, 0x29, 0x4c, 0xbf, + 0x1f, 0xfa, 0x89, 0xf7, 0xb7, 0xb2, 0xda, 0xe9, 0x82, 0x01, 0x3a, 0x46, + 0x03, 0xf0, 0x64, 0xf8, 0xc0, 0x07, 0x18, 0xd5, 0x0a, 0xeb, 0xc7, 0x00, + 0xb1, 0x45, 0xc1, 0x6f, 0x04, 0xd0, 0x80, 0x6f, 0x40, 0x11, 0xa8, 0x80, + 0x48, 0x11, 0xe8, 0x80, 0x42, 0x46, 0xdf, 0xf8, 0xd8, 0x0d, 0xb0, 0xf9, + 0x24, 0x10, 0x0a, 0xf1, 0x6e, 0x00, 0xff, 0xf7, 0x61, 0xff, 0xac, 0x81, + 0x8b, 0xf3, 0x11, 0x88, 0x00, 0x20, 0xbd, 0xe8, 0xf2, 0x8f, 0x00, 0x24, + 0xf7, 0xe7, 0xf8, 0xb5, 0x04, 0x46, 0x0d, 0x46, 0x26, 0x68, 0x60, 0x68, + 0xb6, 0xf9, 0x34, 0xc0, 0x03, 0xeb, 0x02, 0x17, 0x81, 0x1c, 0x67, 0x44, + 0x3f, 0x11, 0xcf, 0x80, 0xb7, 0x8e, 0x4a, 0x80, 0xff, 0x18, 0xb1, 0xf9, + 0x0a, 0x20, 0x8b, 0x80, 0x07, 0xf0, 0x0f, 0x07, 0x0f, 0x81, 0x00, 0x2a, + 0x14, 0xbf, 0x02, 0x22, 0x01, 0x22, 0xb1, 0xf9, 0x0c, 0x70, 0x13, 0x46, + 0x1f, 0xb1, 0x37, 0x69, 0xe7, 0x61, 0x01, 0x27, 0x08, 0xe0, 0x02, 0x2b, + 0x03, 0xd1, 0x77, 0x69, 0xe7, 0x61, 0x37, 0x8c, 0x02, 0xe0, 0xb7, 0x69, + 0xe7, 0x61, 0x77, 0x8c, 0x27, 0x84, 0xb1, 0xf9, 0x0e, 0x70, 0x00, 0x2f, + 0x01, 0xbf, 0xb1, 0xf9, 0x10, 0x70, 0x00, 0x2f, 0x0f, 0x78, 0xba, 0x42, + 0x24, 0xd0, 0x00, 0xf1, 0x18, 0x07, 0xdf, 0xf8, 0xb4, 0xc6, 0xc7, 0xf8, + 0x00, 0xc0, 0x4f, 0xf0, 0x00, 0x0c, 0xc7, 0xf8, 0x04, 0xc0, 0xc7, 0xf8, + 0x08, 0xc0, 0xb4, 0xf8, 0x12, 0xc0, 0xa4, 0xf8, 0x16, 0xc0, 0x4f, 0xf0, + 0x00, 0x0c, 0xa0, 0xf8, 0x00, 0xc0, 0xa1, 0xf8, 0x0e, 0xc0, 0x0a, 0x70, + 0xc7, 0xf8, 0x4c, 0xc0, 0x32, 0x69, 0xe2, 0x61, 0x01, 0x22, 0x22, 0x84, + 0xb1, 0xf9, 0x0c, 0x20, 0x00, 0x2a, 0x1a, 0xbf, 0x01, 0x2b, 0x08, 0x22, + 0x20, 0x22, 0xba, 0x86, 0xb1, 0xf9, 0x10, 0x10, 0x21, 0xb1, 0x00, 0xf0, + 0x4b, 0xff, 0x61, 0x68, 0x00, 0x20, 0x48, 0x82, 0x25, 0x81, 0xf1, 0xbd, + 0x2d, 0xe9, 0xf9, 0x4f, 0x97, 0xb0, 0x00, 0x20, 0x0c, 0x46, 0x01, 0x90, + 0xe0, 0x8a, 0x17, 0x99, 0x40, 0x08, 0x02, 0x90, 0x01, 0x20, 0x88, 0x40, + 0x11, 0x90, 0x00, 0x21, 0x00, 0x20, 0x03, 0xf0, 0x20, 0xf8, 0x11, 0x98, + 0x02, 0xf0, 0x32, 0xfe, 0x00, 0x25, 0x30, 0xb9, 0x04, 0xf0, 0x99, 0xf8, + 0x18, 0xb9, 0x03, 0xf0, 0x73, 0xf8, 0x02, 0x20, 0x0c, 0xe3, 0x00, 0xf0, + 0x26, 0xfb, 0x02, 0xf0, 0xec, 0xfd, 0xdf, 0xf8, 0x34, 0x0e, 0x00, 0x68, + 0x60, 0x62, 0x04, 0xf1, 0x28, 0x00, 0x04, 0xf0, 0xb6, 0xfe, 0x00, 0xf0, + 0x81, 0xff, 0x00, 0x28, 0x04, 0xf1, 0x2c, 0x00, 0x02, 0xd0, 0x04, 0xf0, + 0xe6, 0xff, 0x01, 0xe0, 0x05, 0xf0, 0x55, 0xfa, 0x17, 0x99, 0x20, 0x46, + 0x00, 0xf0, 0x16, 0xff, 0x06, 0x46, 0x60, 0x68, 0xb0, 0xf9, 0x0c, 0x10, + 0x00, 0x29, 0x17, 0x99, 0x14, 0xbf, 0xb0, 0xf9, 0x08, 0x00, 0xb0, 0xf9, + 0x04, 0x00, 0x00, 0x29, 0x14, 0xbf, 0xdf, 0xf8, 0xf0, 0x1d, 0xdf, 0xf8, + 0xf0, 0x1d, 0x09, 0x68, 0xc9, 0x07, 0x05, 0xd5, 0x01, 0x21, 0xc0, 0x1d, + 0x80, 0x28, 0x02, 0xd3, 0x7f, 0x20, 0x00, 0xe0, 0x00, 0x21, 0x17, 0x9a, + 0xdf, 0xf8, 0xd8, 0x3d, 0x00, 0x04, 0x00, 0xf4, 0xfe, 0x00, 0x40, 0xea, + 0x82, 0x70, 0x40, 0xea, 0xc1, 0x32, 0x1a, 0x43, 0x16, 0x92, 0x00, 0x27, + 0x22, 0x8b, 0xd2, 0x05, 0x02, 0xf0, 0x7e, 0x52, 0x10, 0x43, 0x40, 0xea, + 0xc1, 0x30, 0xdf, 0xf8, 0xb8, 0x1d, 0x08, 0x43, 0x10, 0x90, 0x10, 0x98, + 0x05, 0xf0, 0x3b, 0xfb, 0x20, 0x68, 0xc0, 0x8e, 0x41, 0x42, 0x09, 0xb2, + 0x00, 0xb2, 0x05, 0xf0, 0xa3, 0xfd, 0x60, 0x68, 0xb0, 0xf9, 0x0e, 0x10, + 0x39, 0xb1, 0xdf, 0xf8, 0x84, 0x2d, 0x4f, 0xf4, 0x88, 0x71, 0xd1, 0x61, + 0x11, 0x62, 0x4f, 0xf4, 0x84, 0x77, 0x61, 0x6a, 0xdf, 0xf8, 0x70, 0x2d, + 0x39, 0x43, 0x41, 0xf0, 0x02, 0x01, 0x11, 0x60, 0xd0, 0xf8, 0x6e, 0x00, + 0x03, 0x90, 0x17, 0x98, 0x06, 0xf0, 0x60, 0xf8, 0x04, 0xe0, 0x1f, 0xfa, + 0x89, 0xf8, 0x01, 0x98, 0x40, 0x1c, 0x01, 0x90, 0x02, 0x98, 0x01, 0x99, + 0x88, 0x42, 0xc0, 0xf2, 0x66, 0x82, 0x00, 0x2d, 0x08, 0xbf, 0x00, 0x2e, + 0x40, 0xf0, 0x61, 0x82, 0x08, 0x46, 0x02, 0x99, 0x88, 0x42, 0x08, 0xbf, + 0x4f, 0xf0, 0x01, 0x0a, 0x1c, 0xd0, 0x00, 0xf0, 0x05, 0xff, 0x4f, 0xf0, + 0x00, 0x0a, 0x20, 0xb9, 0x17, 0x98, 0x01, 0x21, 0xc0, 0xb2, 0x05, 0xf0, + 0xfa, 0xf9, 0x20, 0x68, 0x80, 0x8f, 0x06, 0xf0, 0x6d, 0xf9, 0x05, 0xf0, + 0x9c, 0xfa, 0x01, 0x98, 0x17, 0x9a, 0x64, 0x21, 0x48, 0x43, 0x02, 0x99, + 0x90, 0xfb, 0xf1, 0xf0, 0xdf, 0xf8, 0xe8, 0x14, 0x34, 0x23, 0x03, 0xfb, + 0x02, 0x11, 0x48, 0x60, 0x01, 0x98, 0x01, 0x28, 0x2d, 0xdb, 0xdd, 0xe9, + 0x08, 0x01, 0x06, 0xf0, 0xf7, 0xf9, 0x0f, 0x90, 0xdd, 0xe9, 0x06, 0x01, + 0x06, 0xf0, 0xf2, 0xf9, 0xb8, 0xf1, 0x00, 0x0f, 0x0e, 0x90, 0x20, 0xd1, + 0x60, 0x68, 0xdd, 0xe9, 0x14, 0x23, 0xd0, 0xe9, 0x0a, 0x71, 0xba, 0x18, + 0x4b, 0x41, 0xc0, 0xe9, 0x0a, 0x23, 0xd0, 0xe9, 0x0c, 0x71, 0xdd, 0xe9, + 0x12, 0x23, 0xba, 0x18, 0x4b, 0x41, 0xc0, 0xe9, 0x0c, 0x23, 0xd0, 0xe9, + 0x0e, 0x71, 0xdd, 0xe9, 0x08, 0x23, 0xba, 0x18, 0x4b, 0x41, 0xc0, 0xe9, + 0x0e, 0x23, 0xd0, 0xe9, 0x10, 0x71, 0xdd, 0xe9, 0x06, 0x23, 0xba, 0x18, + 0x4b, 0x41, 0xc0, 0xe9, 0x10, 0x23, 0x17, 0x98, 0x02, 0xf0, 0x4e, 0xfe, + 0xdf, 0xf8, 0xc8, 0x2a, 0xdf, 0xf8, 0x48, 0x1d, 0x80, 0x56, 0x31, 0xf8, + 0x10, 0x00, 0x06, 0xf0, 0xfd, 0xf9, 0xdf, 0xf8, 0x40, 0x1d, 0x06, 0xf0, + 0x09, 0xfa, 0x00, 0xf0, 0x6d, 0xfd, 0xba, 0xf1, 0x00, 0x0f, 0x0d, 0x90, + 0x39, 0xd1, 0x05, 0xf0, 0x62, 0xfa, 0x02, 0x28, 0x0c, 0xbf, 0x06, 0x26, + 0x01, 0x28, 0x00, 0xd1, 0x01, 0x25, 0xdf, 0xf8, 0x20, 0x2d, 0xd2, 0xe9, + 0x00, 0x01, 0xcd, 0xe9, 0x14, 0x01, 0xd2, 0xe9, 0x02, 0x01, 0xcd, 0xe9, + 0x12, 0x01, 0xd2, 0xe9, 0x04, 0x01, 0xcd, 0xe9, 0x08, 0x01, 0xd2, 0xe9, + 0x06, 0x01, 0xcd, 0xe9, 0x06, 0x01, 0x60, 0x68, 0xb0, 0xf9, 0x0c, 0x00, + 0xb0, 0xb9, 0x17, 0x98, 0x00, 0x21, 0xc0, 0xb2, 0x05, 0xf0, 0x7d, 0xf9, + 0xdd, 0xe9, 0x08, 0x01, 0x40, 0x42, 0x61, 0xeb, 0x41, 0x01, 0xcd, 0xe9, + 0x08, 0x01, 0xdd, 0xe9, 0x06, 0x01, 0x40, 0x42, 0x61, 0xeb, 0x41, 0x01, + 0xcd, 0xe9, 0x06, 0x01, 0x20, 0x68, 0x80, 0x8f, 0x06, 0xf0, 0xe2, 0xf8, + 0x00, 0x2d, 0x04, 0xbf, 0x00, 0x2e, 0x05, 0xf0, 0x0e, 0xfa, 0x01, 0x98, + 0x02, 0x28, 0xc0, 0xf2, 0xcc, 0x80, 0x0f, 0x98, 0x00, 0x99, 0x06, 0xf0, + 0x3f, 0xfa, 0x0c, 0x90, 0x59, 0x46, 0x0e, 0x98, 0x06, 0xf0, 0x3a, 0xfa, + 0x0b, 0x90, 0xbd, 0xf9, 0x14, 0x10, 0xbd, 0xf9, 0x10, 0x00, 0x40, 0x1a, + 0x06, 0xf0, 0x9a, 0xf9, 0x07, 0x46, 0xbd, 0xf9, 0x12, 0x00, 0xbd, 0xf9, + 0x16, 0x10, 0x40, 0x1a, 0x06, 0xf0, 0x92, 0xf9, 0x00, 0xf0, 0x1c, 0xfd, + 0x83, 0x46, 0x48, 0x46, 0x00, 0xf0, 0xfc, 0xfc, 0x59, 0x46, 0x06, 0xf0, + 0x95, 0xfa, 0x06, 0xf0, 0xd5, 0xfa, 0x00, 0x21, 0x06, 0xf0, 0x0c, 0xfb, + 0x83, 0x46, 0x1d, 0xd0, 0x20, 0x68, 0x30, 0xf8, 0x42, 0x1f, 0x81, 0xb1, + 0x61, 0x68, 0x4c, 0x31, 0x00, 0x91, 0x40, 0x88, 0x06, 0xf0, 0x82, 0xf9, + 0x01, 0x46, 0x00, 0x98, 0x80, 0x69, 0x06, 0xf0, 0x09, 0xfb, 0x04, 0xd3, + 0x00, 0x98, 0x00, 0x88, 0x08, 0x28, 0xc0, 0xf2, 0x90, 0x80, 0x11, 0x98, + 0x02, 0xf0, 0xbe, 0xfc, 0x00, 0x28, 0x03, 0xd0, 0x04, 0x20, 0x02, 0xf0, + 0xab, 0xfc, 0x00, 0x28, 0x00, 0xf0, 0x85, 0x80, 0x0c, 0x98, 0x00, 0xf0, + 0xd6, 0xfc, 0x00, 0x90, 0x49, 0x46, 0x0b, 0x98, 0x06, 0xf0, 0x02, 0xfb, + 0x00, 0x99, 0x06, 0xf0, 0x63, 0xfa, 0x59, 0x46, 0x06, 0xf0, 0x6e, 0xf9, + 0x00, 0x90, 0x39, 0x46, 0x0b, 0x98, 0x06, 0xf0, 0xf7, 0xfa, 0x07, 0x46, + 0x0c, 0x98, 0x00, 0xf0, 0xbb, 0xfc, 0x01, 0x46, 0x38, 0x46, 0x06, 0xf0, + 0xdf, 0xf9, 0x59, 0x46, 0x06, 0xf0, 0x5e, 0xf9, 0x0a, 0x90, 0x4f, 0xf0, + 0x7e, 0x50, 0x18, 0x99, 0x06, 0xf0, 0xd6, 0xf9, 0xb8, 0xf1, 0x00, 0x0f, + 0x81, 0x46, 0x5c, 0xd1, 0x67, 0x68, 0x00, 0xf0, 0xa6, 0xfc, 0x0d, 0x99, + 0x06, 0xf0, 0xdc, 0xfa, 0xb9, 0x69, 0x06, 0xf0, 0x3d, 0xfa, 0xb8, 0x61, + 0x49, 0x46, 0x00, 0x98, 0x06, 0xf0, 0xd4, 0xfa, 0xf9, 0x69, 0x06, 0xf0, + 0x35, 0xfa, 0xf8, 0x61, 0x49, 0x46, 0x0a, 0x98, 0x06, 0xf0, 0xcc, 0xfa, + 0x39, 0x6a, 0x06, 0xf0, 0x2d, 0xfa, 0x38, 0x62, 0x4f, 0xf0, 0x7e, 0x51, + 0x38, 0x6d, 0x06, 0xf0, 0x27, 0xfa, 0x38, 0x65, 0x59, 0x46, 0x0d, 0x98, + 0x06, 0xf0, 0xbe, 0xfa, 0x81, 0x46, 0x00, 0x98, 0x49, 0x46, 0x06, 0xf0, + 0x2b, 0xf9, 0x79, 0x6d, 0x83, 0x46, 0x06, 0xf0, 0xa5, 0xf9, 0x00, 0x90, + 0x39, 0x6d, 0x06, 0xf0, 0x23, 0xf9, 0x79, 0x6d, 0x06, 0xf0, 0x12, 0xfa, + 0x01, 0x46, 0x79, 0x65, 0x00, 0xf0, 0x76, 0xfc, 0x00, 0x99, 0x06, 0xf0, + 0xa7, 0xfa, 0xf9, 0x6d, 0x06, 0xf0, 0x08, 0xfa, 0xf8, 0x65, 0x49, 0x46, + 0x0a, 0x98, 0x06, 0xf0, 0x11, 0xf9, 0xb9, 0x6d, 0x81, 0x46, 0x06, 0xf0, + 0x8b, 0xf9, 0x39, 0x6d, 0x83, 0x46, 0x06, 0xf0, 0x09, 0xf9, 0xb9, 0x6d, + 0x06, 0xf0, 0xf8, 0xf9, 0x01, 0x46, 0xb9, 0x65, 0x48, 0x46, 0x06, 0xf0, + 0x7f, 0xf9, 0x59, 0x46, 0x06, 0xf0, 0x8c, 0xfa, 0x39, 0x6e, 0x06, 0xf0, + 0xed, 0xf9, 0x38, 0x66, 0x01, 0xe0, 0x01, 0x28, 0x03, 0xdb, 0x0f, 0x98, + 0xdd, 0xf8, 0x38, 0xb0, 0x00, 0x90, 0xba, 0xf1, 0x00, 0x0f, 0x04, 0x98, + 0x05, 0x90, 0x03, 0x98, 0x04, 0x90, 0x7f, 0xf4, 0x70, 0xae, 0x60, 0x68, + 0xdf, 0xf8, 0x74, 0x2d, 0x50, 0xf8, 0x14, 0x7f, 0xdf, 0xf8, 0x6c, 0x3d, + 0x07, 0xf0, 0x01, 0x01, 0x51, 0x43, 0x81, 0xea, 0x57, 0x01, 0x00, 0xf0, + 0x05, 0xf9, 0x00, 0xf0, 0x03, 0xf9, 0x01, 0x60, 0x07, 0xf0, 0x01, 0x02, + 0x07, 0xf0, 0x02, 0x01, 0x49, 0x1e, 0x7b, 0x07, 0x05, 0xd5, 0xfb, 0x43, + 0x03, 0xf0, 0x01, 0x03, 0x4b, 0x43, 0x51, 0x43, 0x01, 0xe0, 0x52, 0x00, + 0x53, 0x1e, 0x07, 0x8f, 0x79, 0x43, 0x07, 0xfb, 0x03, 0xf2, 0xb0, 0xf9, + 0x5a, 0x70, 0x13, 0xb2, 0x3b, 0x44, 0xbd, 0xf9, 0x10, 0x70, 0xbb, 0x42, + 0x07, 0xd1, 0xb0, 0xf9, 0x5c, 0x70, 0x0b, 0xb2, 0x3b, 0x44, 0xbd, 0xf9, + 0x12, 0x70, 0xbb, 0x42, 0x04, 0xd0, 0x02, 0x9f, 0x01, 0x9b, 0x7f, 0x1e, + 0xbb, 0x42, 0x01, 0xdb, 0x00, 0x22, 0x00, 0x21, 0x83, 0x8e, 0xd3, 0x18, + 0x83, 0x86, 0xc3, 0x8e, 0xcb, 0x18, 0xc3, 0x86, 0xb0, 0xf8, 0x5a, 0x30, + 0xd2, 0x18, 0xad, 0xf8, 0x0c, 0x20, 0xb0, 0xf8, 0x5c, 0x00, 0x08, 0x18, + 0xad, 0xf8, 0x0e, 0x00, 0x00, 0x2d, 0x08, 0xbf, 0x00, 0x2e, 0x07, 0xd1, + 0x05, 0xf0, 0xfb, 0xf8, 0x02, 0x28, 0x0c, 0xbf, 0x06, 0x26, 0x01, 0x28, + 0x00, 0xd1, 0x01, 0x25, 0xdf, 0xf8, 0x50, 0xca, 0xdd, 0xe9, 0x14, 0x23, + 0xdc, 0xe9, 0x00, 0x01, 0x10, 0x18, 0x59, 0x41, 0xcd, 0xe9, 0x14, 0x01, + 0xdd, 0xe9, 0x12, 0x23, 0xdc, 0xe9, 0x02, 0x01, 0x10, 0x18, 0x59, 0x41, + 0xcd, 0xe9, 0x12, 0x01, 0xdd, 0xe9, 0x08, 0x23, 0xdc, 0xe9, 0x04, 0x01, + 0x10, 0x18, 0x59, 0x41, 0xcd, 0xe9, 0x08, 0x01, 0xdd, 0xe9, 0x06, 0x23, + 0xdc, 0xe9, 0x06, 0x01, 0x10, 0x18, 0x59, 0x41, 0xcd, 0xe9, 0x06, 0x01, + 0x4f, 0xea, 0x68, 0x09, 0x20, 0x68, 0x24, 0x30, 0xc1, 0x8b, 0x00, 0x29, + 0x47, 0xd0, 0x16, 0x98, 0x4f, 0xf0, 0x8a, 0x41, 0x00, 0x2d, 0x08, 0x60, + 0x48, 0xd1, 0x00, 0x2e, 0x7f, 0xf4, 0xe5, 0xad, 0x05, 0xf0, 0xa5, 0xf8, + 0x20, 0x68, 0xb0, 0xf9, 0x24, 0x10, 0x17, 0x9a, 0x03, 0xa8, 0xff, 0xf7, + 0x41, 0xfc, 0x00, 0xf0, 0x96, 0xf8, 0x05, 0xf0, 0xb6, 0xf8, 0x02, 0x28, + 0x0c, 0xbf, 0x06, 0x26, 0x01, 0x28, 0x00, 0xd1, 0x01, 0x25, 0x10, 0x98, + 0x4f, 0xf0, 0x8a, 0x41, 0x08, 0x60, 0x67, 0x68, 0xdf, 0xf8, 0xec, 0x1d, + 0x78, 0x6e, 0x06, 0xf0, 0xd3, 0xf9, 0xdf, 0xf8, 0x90, 0x1d, 0x84, 0x46, + 0xdf, 0xf8, 0xac, 0x09, 0xc7, 0xf8, 0x64, 0xc0, 0xd1, 0xe9, 0x00, 0x23, + 0x00, 0x68, 0x00, 0xf0, 0x68, 0xf8, 0x08, 0xbf, 0x00, 0x28, 0x0b, 0xd0, + 0xdf, 0xf8, 0x70, 0x1d, 0xdf, 0xf8, 0x90, 0x09, 0x80, 0x68, 0xd1, 0xe9, + 0x12, 0x23, 0x00, 0xf0, 0x5c, 0xf8, 0x08, 0xbf, 0x00, 0x28, 0x0d, 0xd1, + 0x4f, 0xf0, 0x7e, 0x51, 0x60, 0x46, 0x06, 0xf0, 0x17, 0xf9, 0x78, 0x66, + 0x06, 0xe0, 0x41, 0x5e, 0x17, 0x9a, 0x03, 0xa8, 0xff, 0xf7, 0x06, 0xfc, + 0x00, 0xf0, 0x5b, 0xf8, 0x00, 0x2d, 0x3f, 0xf4, 0x9c, 0xad, 0x02, 0x98, + 0x80, 0x1c, 0x08, 0xf0, 0x01, 0x01, 0x40, 0x1a, 0x09, 0xf0, 0x01, 0x01, + 0x40, 0x1a, 0x02, 0x90, 0x4f, 0xf0, 0x03, 0x08, 0x91, 0xe5, 0x20, 0x68, + 0xb0, 0xf9, 0x24, 0x10, 0x60, 0x68, 0x17, 0x9a, 0x6e, 0x30, 0xff, 0xf7, + 0xed, 0xfb, 0x00, 0xf0, 0x42, 0xf8, 0x00, 0xf0, 0x3a, 0xf8, 0x02, 0xf0, + 0xed, 0xfa, 0x60, 0x6a, 0xdf, 0xf8, 0x58, 0x18, 0x08, 0x60, 0x00, 0xf0, + 0x99, 0xfc, 0x28, 0xb1, 0x00, 0x21, 0x04, 0xf1, 0x2c, 0x00, 0x04, 0xf0, + 0x10, 0xfd, 0x03, 0xe0, 0x04, 0xf1, 0x2c, 0x00, 0x04, 0xf0, 0x78, 0xff, + 0x04, 0xf1, 0x28, 0x00, 0x04, 0xf0, 0xc4, 0xfb, 0x00, 0x20, 0x02, 0xf0, + 0x69, 0xfd, 0x15, 0xb1, 0x00, 0x2e, 0x3f, 0xf4, 0xe4, 0xac, 0x30, 0x46, + 0x19, 0xb0, 0xbd, 0xe8, 0xf0, 0x8f, 0x00, 0x00, 0xff, 0xe6, 0xdb, 0x2e, + 0x14, 0x0a, 0x00, 0x46, 0x98, 0xf1, 0x00, 0x20, 0x01, 0x60, 0x01, 0xf0, + 0x01, 0x02, 0x5a, 0x43, 0x82, 0xea, 0x51, 0x01, 0x70, 0x47, 0xdb, 0x01, + 0x43, 0xea, 0x52, 0x63, 0x40, 0x43, 0xd2, 0x01, 0xc1, 0x17, 0x10, 0x1a, + 0x73, 0xeb, 0x01, 0x01, 0x70, 0x47, 0x02, 0x22, 0x04, 0xf1, 0x22, 0x01, + 0x0f, 0xf6, 0x68, 0x50, 0x70, 0x47, 0x22, 0x99, 0x09, 0x68, 0x08, 0x43, + 0x22, 0x99, 0x08, 0x60, 0x70, 0x47, 0x2d, 0xe9, 0xf0, 0x4f, 0x8d, 0xb0, + 0x53, 0x78, 0x12, 0x78, 0x04, 0x46, 0x88, 0x46, 0xff, 0xf7, 0x41, 0xfc, + 0x20, 0x8b, 0xc0, 0xb2, 0x05, 0xf0, 0x56, 0xf8, 0x4f, 0xea, 0x40, 0x0b, + 0xe0, 0x69, 0x05, 0xf0, 0x99, 0xff, 0xdf, 0xf8, 0xc8, 0x1c, 0x05, 0xf0, + 0xa5, 0xff, 0x05, 0x90, 0x26, 0x68, 0xf0, 0x8d, 0x05, 0xf0, 0x90, 0xff, + 0xdf, 0xf8, 0xb8, 0x1c, 0x05, 0xf0, 0x9c, 0xff, 0x01, 0x46, 0x06, 0xf0, + 0x27, 0xf9, 0x07, 0x46, 0xe0, 0x8a, 0x05, 0xf0, 0x85, 0xff, 0x00, 0xf0, + 0xf0, 0xfa, 0x07, 0x46, 0x05, 0x99, 0x4f, 0xf0, 0x7e, 0x50, 0x06, 0xf0, + 0x0b, 0xf8, 0x4f, 0xf0, 0x80, 0x41, 0x06, 0xf0, 0x17, 0xf9, 0x01, 0x46, + 0x38, 0x46, 0x05, 0xf0, 0x85, 0xff, 0x82, 0x46, 0x4f, 0xf0, 0x7a, 0x50, + 0x51, 0x46, 0x06, 0xf0, 0x0d, 0xf9, 0x07, 0x90, 0x00, 0x20, 0x63, 0x68, + 0x03, 0xf1, 0x28, 0x02, 0xc2, 0xe9, 0x00, 0x00, 0xc2, 0xe9, 0x02, 0x00, + 0xc2, 0xe9, 0x04, 0x00, 0xc2, 0xe9, 0x06, 0x00, 0x10, 0x84, 0x50, 0x84, + 0x90, 0x62, 0x50, 0x63, 0xd0, 0x62, 0x90, 0x63, 0x10, 0x63, 0xa3, 0xf8, + 0x68, 0x00, 0x04, 0x90, 0x71, 0x8d, 0x90, 0x8c, 0x88, 0x42, 0x26, 0xbf, + 0xb1, 0x8d, 0x81, 0x42, 0x91, 0x84, 0x04, 0xa8, 0x00, 0x90, 0x5a, 0x46, + 0x05, 0x9b, 0x21, 0x46, 0x40, 0x46, 0xff, 0xf7, 0x4d, 0xfc, 0x00, 0x28, + 0x40, 0xf0, 0xa0, 0x82, 0x40, 0x46, 0x02, 0xf0, 0x82, 0xfb, 0x06, 0x46, + 0x40, 0x46, 0x02, 0xf0, 0x87, 0xfb, 0x07, 0x46, 0x40, 0xf2, 0x47, 0x30, + 0x86, 0x42, 0x0d, 0xda, 0x0f, 0xf6, 0xdc, 0x40, 0x30, 0x5c, 0x00, 0xf2, + 0x01, 0x10, 0x80, 0xb2, 0x05, 0xf0, 0x32, 0xff, 0x4f, 0xf0, 0x72, 0x51, + 0x06, 0xf0, 0xcc, 0xf8, 0x06, 0x46, 0x01, 0xe0, 0x4f, 0xf0, 0x82, 0x46, + 0xdf, 0xf8, 0x10, 0x15, 0x0f, 0xf6, 0x54, 0x40, 0x79, 0x56, 0x30, 0xf8, + 0x11, 0x00, 0x05, 0xf0, 0x21, 0xff, 0xdf, 0xf8, 0x88, 0x17, 0x05, 0xf0, + 0x2d, 0xff, 0x00, 0xf0, 0x91, 0xfa, 0x0b, 0x90, 0xe0, 0x8a, 0x40, 0x08, + 0x05, 0xf0, 0x16, 0xff, 0x07, 0x46, 0x60, 0x68, 0x0a, 0x90, 0x00, 0xf1, + 0x18, 0x05, 0xd5, 0xe9, 0x04, 0x01, 0x05, 0xf0, 0xd1, 0xfe, 0x00, 0xf0, + 0x7e, 0xfa, 0x81, 0x46, 0xd5, 0xe9, 0x06, 0x01, 0x05, 0xf0, 0xca, 0xfe, + 0x00, 0xf0, 0x77, 0xfa, 0x06, 0x90, 0xd5, 0xe9, 0x08, 0x01, 0x05, 0xf0, + 0xc3, 0xfe, 0x00, 0xf0, 0x70, 0xfa, 0x09, 0x90, 0xd5, 0xe9, 0x0a, 0x01, + 0x05, 0xf0, 0xbc, 0xfe, 0x00, 0xf0, 0x69, 0xfa, 0x08, 0x90, 0x2f, 0x68, + 0x69, 0x6c, 0xa8, 0x6c, 0x05, 0xf0, 0xf2, 0xff, 0x01, 0x90, 0x00, 0xf0, + 0x6b, 0xfa, 0x00, 0x90, 0xa9, 0x68, 0x00, 0xf0, 0x68, 0xfa, 0x00, 0x99, + 0x05, 0xf0, 0xe8, 0xff, 0x00, 0x90, 0x39, 0x46, 0x38, 0x46, 0x06, 0xf0, + 0x7f, 0xf8, 0x01, 0x46, 0x00, 0x98, 0x05, 0xf0, 0xed, 0xfe, 0x07, 0x46, + 0xa9, 0x6b, 0xdf, 0xf8, 0x54, 0x0b, 0x05, 0xf0, 0xd9, 0xff, 0x00, 0xf0, + 0x42, 0xfa, 0x01, 0x46, 0x01, 0x98, 0x05, 0xf0, 0xe1, 0xfe, 0x01, 0x46, + 0x50, 0x46, 0x06, 0xf0, 0x59, 0xf8, 0x02, 0xd2, 0xa8, 0x8e, 0x40, 0x1c, + 0xa8, 0x86, 0x08, 0x46, 0x07, 0x99, 0x06, 0xf0, 0x51, 0xf8, 0x04, 0xd2, + 0xa9, 0x8e, 0xa1, 0xeb, 0x11, 0x10, 0x40, 0x1e, 0xa8, 0x86, 0x20, 0x68, + 0x00, 0xf1, 0x26, 0x07, 0xb8, 0x8b, 0x02, 0x28, 0x0b, 0xd1, 0xf8, 0x8b, + 0x05, 0xf0, 0xb6, 0xfe, 0xe9, 0x6c, 0x06, 0xf0, 0x3f, 0xf8, 0x04, 0xd2, + 0xa8, 0x8e, 0x08, 0x28, 0xbc, 0xbf, 0x08, 0x20, 0xa8, 0x86, 0x48, 0x46, + 0x00, 0x21, 0x06, 0xf0, 0x35, 0xf8, 0xca, 0x46, 0x38, 0xbf, 0x8a, 0xf0, + 0x00, 0x4a, 0x06, 0x98, 0x06, 0xf0, 0x2e, 0xf8, 0x38, 0xbf, 0x80, 0xf0, + 0x00, 0x40, 0x00, 0x90, 0x58, 0x46, 0x05, 0xf0, 0x91, 0xfe, 0x07, 0x90, + 0x51, 0x46, 0x00, 0x98, 0x05, 0xf0, 0x98, 0xff, 0x82, 0x46, 0xdf, 0xf8, + 0xcc, 0x0a, 0x00, 0xf0, 0xf3, 0xf9, 0x07, 0x99, 0x05, 0xf0, 0x9e, 0xfe, + 0x51, 0x46, 0x06, 0xf0, 0x29, 0xf8, 0xdf, 0xf8, 0xbc, 0x1a, 0x06, 0xf0, + 0x25, 0xf8, 0x06, 0xf0, 0x8f, 0xf8, 0xad, 0xf8, 0x04, 0x00, 0xbd, 0xf8, + 0x04, 0x10, 0xa8, 0x8e, 0x88, 0x42, 0x38, 0xbf, 0x08, 0x46, 0xa8, 0x86, + 0xf9, 0x88, 0xa8, 0x8e, 0x81, 0x42, 0x26, 0xbf, 0xb9, 0x88, 0x88, 0x42, + 0xa9, 0x86, 0x00, 0xf0, 0xf1, 0xf9, 0xa9, 0x68, 0x82, 0x46, 0x00, 0xf0, + 0xee, 0xf9, 0x51, 0x46, 0x05, 0xf0, 0x6e, 0xff, 0x0b, 0x99, 0x06, 0xf0, + 0x07, 0xf8, 0x29, 0x68, 0x05, 0xf0, 0x76, 0xfe, 0x4f, 0xf0, 0x7e, 0x51, + 0x05, 0xf0, 0xee, 0xff, 0x82, 0x46, 0x38, 0xbf, 0x8a, 0x46, 0x09, 0x99, + 0x68, 0x68, 0x05, 0xf0, 0xf9, 0xff, 0x83, 0x46, 0x08, 0x99, 0xa8, 0x68, + 0x05, 0xf0, 0xf4, 0xff, 0x59, 0x46, 0x05, 0xf0, 0x55, 0xff, 0x00, 0xf0, + 0xc1, 0xf9, 0x83, 0x46, 0x08, 0x99, 0x68, 0x68, 0x05, 0xf0, 0xea, 0xff, + 0x00, 0x90, 0x09, 0x99, 0xa8, 0x68, 0x05, 0xf0, 0xe5, 0xff, 0x01, 0x46, + 0x00, 0x98, 0x05, 0xf0, 0xd1, 0xfe, 0x00, 0xf0, 0xb1, 0xf9, 0x00, 0x90, + 0xe0, 0x8a, 0x40, 0x08, 0x05, 0xf0, 0x3c, 0xfe, 0x82, 0x46, 0xb5, 0xf9, + 0x30, 0x00, 0x05, 0xf0, 0x2d, 0xfe, 0x00, 0xf0, 0xa5, 0xf9, 0x00, 0xf0, + 0x9c, 0xf9, 0x83, 0x46, 0xb5, 0xf9, 0x32, 0x00, 0x05, 0xf0, 0x24, 0xfe, + 0x00, 0xf0, 0x9c, 0xf9, 0x01, 0x46, 0x00, 0x98, 0x05, 0xf0, 0xb6, 0xfe, + 0x05, 0x46, 0xb8, 0x89, 0x90, 0xb1, 0x07, 0x99, 0x30, 0x46, 0x05, 0xf0, + 0x31, 0xfe, 0x06, 0x46, 0x48, 0x46, 0x00, 0xf0, 0x7f, 0xf9, 0x00, 0xf0, + 0x84, 0xf9, 0x83, 0x46, 0x06, 0x98, 0x00, 0xf0, 0x79, 0xf9, 0x01, 0x46, + 0x28, 0x46, 0x05, 0xf0, 0xa1, 0xfe, 0x05, 0x46, 0x58, 0x46, 0x06, 0xf0, + 0x3b, 0xf8, 0x06, 0xf0, 0x17, 0xf8, 0xad, 0xf8, 0x0c, 0x00, 0x28, 0x46, + 0x06, 0xf0, 0x34, 0xf8, 0x06, 0xf0, 0x10, 0xf8, 0xad, 0xf8, 0x0e, 0x00, + 0x78, 0x88, 0x05, 0xf0, 0x01, 0xfe, 0x06, 0x46, 0xbd, 0xf8, 0x04, 0x00, + 0x05, 0xf0, 0xfc, 0xfd, 0x01, 0x46, 0xdf, 0xf8, 0x9c, 0x09, 0x05, 0xf0, + 0x85, 0xfe, 0x00, 0xf0, 0x57, 0xf9, 0xdf, 0xf8, 0x94, 0x19, 0x05, 0xf0, + 0x01, 0xfe, 0xdf, 0xf8, 0x90, 0x19, 0x05, 0xf0, 0x79, 0xff, 0x81, 0x46, + 0x38, 0xbf, 0x89, 0x46, 0x00, 0xf0, 0x4d, 0xf9, 0x06, 0xf0, 0x12, 0xf8, + 0x05, 0xf0, 0xee, 0xff, 0xad, 0xf8, 0x08, 0x00, 0x49, 0x46, 0x28, 0x46, + 0x05, 0xf0, 0x7c, 0xff, 0x06, 0xf0, 0x08, 0xf8, 0x05, 0xf0, 0xe4, 0xff, + 0xad, 0xf8, 0x0a, 0x00, 0x0a, 0x98, 0xb0, 0xf8, 0x76, 0x00, 0x28, 0xb3, + 0xbd, 0xf9, 0x0a, 0x00, 0xbd, 0xf9, 0x08, 0x10, 0x23, 0x8c, 0x00, 0xfb, + 0x00, 0xf2, 0x01, 0xfb, 0x01, 0x22, 0x9a, 0x42, 0x1a, 0xda, 0x3a, 0x88, + 0x8a, 0x42, 0xbc, 0xbf, 0x12, 0xb2, 0xad, 0xf8, 0x08, 0x20, 0x39, 0x88, + 0x81, 0x42, 0xb8, 0xbf, 0xad, 0xf8, 0x0a, 0x10, 0x38, 0x88, 0xbd, 0xf9, + 0x08, 0x10, 0x40, 0x42, 0x81, 0x42, 0xb8, 0xbf, 0xad, 0xf8, 0x08, 0x00, + 0x38, 0x88, 0xbd, 0xf9, 0x0a, 0x10, 0x40, 0x42, 0x81, 0x42, 0xb8, 0xbf, + 0xad, 0xf8, 0x0a, 0x00, 0xff, 0xf7, 0x46, 0xf9, 0x06, 0x46, 0x60, 0x68, + 0xbd, 0xf8, 0x0c, 0x20, 0xb0, 0xf9, 0x6e, 0x10, 0xbd, 0xf8, 0x0e, 0x30, + 0x8a, 0x1a, 0xad, 0xf8, 0x0c, 0x20, 0xb0, 0xf8, 0x70, 0x20, 0xd2, 0x1a, + 0xad, 0xf8, 0x0e, 0x20, 0xbd, 0xf8, 0x08, 0x20, 0x89, 0x1a, 0xad, 0xf8, + 0x08, 0x10, 0x42, 0x46, 0xb0, 0xf8, 0x70, 0x00, 0xbd, 0xf8, 0x0a, 0x10, + 0x40, 0x1a, 0xad, 0xf8, 0x0a, 0x00, 0x20, 0x68, 0xb0, 0xf9, 0x24, 0x10, + 0x02, 0xa8, 0xff, 0xf7, 0x81, 0xf9, 0x04, 0x99, 0x08, 0x43, 0x04, 0x90, + 0x61, 0x68, 0x02, 0x98, 0xc1, 0xf8, 0x6e, 0x00, 0x86, 0xf3, 0x11, 0x88, + 0x34, 0x21, 0xdf, 0xf8, 0x4c, 0x04, 0x01, 0xfb, 0x08, 0x06, 0x23, 0x46, + 0x30, 0x69, 0x40, 0x1c, 0x30, 0x61, 0xf0, 0x68, 0x40, 0x1c, 0xf0, 0x60, + 0x04, 0x9a, 0x02, 0x99, 0x03, 0x98, 0xcd, 0xf8, 0x00, 0x80, 0x00, 0xf0, + 0xf4, 0xf8, 0x20, 0x68, 0x30, 0xf8, 0x42, 0x1f, 0x69, 0xb1, 0x61, 0x68, + 0x40, 0x88, 0x01, 0xf1, 0x4c, 0x07, 0x05, 0xf0, 0x63, 0xfd, 0x01, 0x46, + 0xb8, 0x69, 0x05, 0xf0, 0xeb, 0xfe, 0x02, 0xd3, 0x38, 0x88, 0x08, 0x28, + 0x14, 0xdb, 0xff, 0xf7, 0xf3, 0xf8, 0x67, 0x68, 0xb9, 0x69, 0x80, 0x46, + 0x05, 0x98, 0x05, 0xf0, 0xf1, 0xfe, 0xb8, 0x61, 0xf9, 0x69, 0x05, 0x98, + 0x05, 0xf0, 0xec, 0xfe, 0xf8, 0x61, 0x39, 0x6a, 0x05, 0x98, 0x05, 0xf0, + 0xe7, 0xfe, 0x38, 0x62, 0x88, 0xf3, 0x11, 0x88, 0x00, 0xf0, 0xc4, 0xfe, + 0x64, 0x68, 0x04, 0xf1, 0x18, 0x08, 0xd8, 0xf8, 0x04, 0x10, 0xd8, 0xf8, + 0x08, 0x70, 0x00, 0xf0, 0xba, 0xf8, 0x00, 0xf0, 0xbb, 0xf8, 0x49, 0x46, + 0x05, 0xf0, 0x38, 0xfe, 0x05, 0xf0, 0x78, 0xfe, 0x01, 0x46, 0x0b, 0x98, + 0x05, 0xf0, 0xce, 0xfe, 0xd8, 0xf8, 0x00, 0x10, 0x05, 0xf0, 0x3c, 0xfd, + 0xb0, 0x61, 0xd8, 0xf8, 0x08, 0x00, 0xd8, 0xf8, 0x04, 0x10, 0x80, 0xf0, + 0x00, 0x40, 0x05, 0xf0, 0x63, 0xff, 0xf0, 0x61, 0xb8, 0xf8, 0x34, 0x00, + 0x30, 0x86, 0x34, 0xf9, 0x0e, 0x0f, 0x00, 0x28, 0x6a, 0xd1, 0x58, 0x46, + 0x59, 0x46, 0x05, 0xf0, 0xb5, 0xfe, 0x07, 0x46, 0x28, 0x46, 0x29, 0x46, + 0x05, 0xf0, 0xb0, 0xfe, 0x39, 0x46, 0x05, 0xf0, 0x11, 0xfe, 0x05, 0xf0, + 0x51, 0xfe, 0x05, 0x46, 0xb1, 0x6a, 0x4f, 0xf0, 0x7e, 0x50, 0x05, 0xf0, + 0x09, 0xfe, 0xb0, 0x62, 0x28, 0x46, 0x31, 0x6a, 0x05, 0xf0, 0x90, 0xfd, + 0xb1, 0x6a, 0x07, 0x46, 0x05, 0xf0, 0x0e, 0xfd, 0x31, 0x6a, 0x05, 0xf0, + 0xfd, 0xfd, 0x01, 0x46, 0x31, 0x62, 0x28, 0x46, 0x05, 0xf0, 0x84, 0xfd, + 0x00, 0xf0, 0x61, 0xf8, 0x71, 0x6a, 0x05, 0xf0, 0xf3, 0xfd, 0x70, 0x62, + 0xdf, 0xf8, 0x90, 0x17, 0xb0, 0x6a, 0x05, 0xf0, 0x91, 0xff, 0x39, 0xd8, + 0x01, 0x46, 0xdf, 0xf8, 0x70, 0x07, 0xdf, 0xf8, 0x48, 0x57, 0x05, 0xf0, + 0xe5, 0xfd, 0x01, 0x46, 0x70, 0x6a, 0x05, 0xf0, 0xef, 0xfc, 0x01, 0x46, + 0xf1, 0x62, 0xdf, 0xf8, 0x70, 0x07, 0x05, 0xf0, 0xdb, 0xfd, 0x01, 0x46, + 0xdf, 0xf8, 0x68, 0x07, 0x05, 0xf0, 0xe4, 0xfc, 0x05, 0xf0, 0xfe, 0xfe, + 0x05, 0xf0, 0xda, 0xfe, 0xb0, 0x60, 0x65, 0x28, 0x24, 0xbf, 0x64, 0x20, + 0xb0, 0x60, 0xb0, 0x6a, 0x29, 0x46, 0x05, 0xf0, 0x65, 0xfe, 0xdf, 0xf8, + 0x2c, 0x17, 0x05, 0xf0, 0xc5, 0xfd, 0x71, 0x6a, 0x05, 0xf0, 0x5e, 0xfe, + 0x07, 0x46, 0xb1, 0x6a, 0xdf, 0xf8, 0x18, 0x07, 0x05, 0xf0, 0xbc, 0xfd, + 0x01, 0x46, 0x38, 0x46, 0x05, 0xf0, 0xc6, 0xfc, 0x70, 0x62, 0x29, 0x46, + 0xb0, 0x6a, 0x05, 0xf0, 0x4f, 0xfe, 0xb0, 0x62, 0x04, 0x98, 0x20, 0xb1, + 0x01, 0x20, 0x60, 0x80, 0x70, 0x69, 0x40, 0x1c, 0x70, 0x61, 0x00, 0xf0, + 0x3c, 0xfe, 0x00, 0x20, 0x0d, 0xb0, 0xbd, 0xe8, 0xf0, 0x8f, 0x00, 0x00, + 0x48, 0xad, 0x00, 0x20, 0x24, 0x2b, 0x00, 0x20, 0x31, 0x46, 0x05, 0xf0, + 0x39, 0xbe, 0x58, 0x46, 0x49, 0x46, 0x05, 0xf0, 0x35, 0xbe, 0x01, 0x46, + 0x58, 0x46, 0x05, 0xf0, 0x21, 0xbd, 0x39, 0x46, 0x05, 0xf0, 0x2e, 0xbe, + 0x51, 0x46, 0x05, 0xf0, 0x9d, 0xbc, 0x39, 0x46, 0x05, 0xf0, 0x9a, 0xbc, + 0x01, 0x46, 0xdf, 0xf8, 0xd0, 0x06, 0x06, 0xf0, 0x9a, 0xb8, 0x00, 0x00, + 0xdc, 0x2a, 0x00, 0x20, 0x69, 0x68, 0x08, 0x46, 0x05, 0xf0, 0x1c, 0xbe, + 0x81, 0x46, 0x38, 0x46, 0x39, 0x46, 0x05, 0xf0, 0x17, 0xbe, 0x2d, 0xe9, + 0xfa, 0x4f, 0x83, 0xb0, 0x1e, 0x68, 0xd3, 0xf8, 0x04, 0x80, 0x22, 0xb1, + 0x40, 0x46, 0x05, 0xb0, 0xbd, 0xe8, 0xf0, 0x4f, 0xb6, 0xe0, 0x0e, 0x98, + 0x02, 0xf0, 0xb2, 0xf8, 0x08, 0xf1, 0x68, 0x05, 0x83, 0x46, 0xa9, 0x88, + 0xdf, 0xf8, 0x8c, 0x06, 0x09, 0x56, 0x02, 0x91, 0x1b, 0xf9, 0x00, 0x00, + 0x40, 0x1a, 0x7d, 0xd0, 0x28, 0x88, 0x00, 0x28, 0x7a, 0xd1, 0xb8, 0xf9, + 0x0c, 0x00, 0xe8, 0xb1, 0x04, 0x98, 0x40, 0x68, 0x02, 0x9a, 0x00, 0xf5, + 0x02, 0x74, 0xd4, 0xe9, 0x02, 0x01, 0x02, 0xf0, 0x35, 0xf9, 0xc0, 0x07, + 0x12, 0xd4, 0xd4, 0xe9, 0x02, 0x01, 0xcd, 0xe9, 0x00, 0x01, 0x02, 0x9a, + 0x01, 0x20, 0x00, 0x21, 0x06, 0xf0, 0x5c, 0xf8, 0xdd, 0xe9, 0x00, 0x23, + 0x10, 0x43, 0x19, 0x43, 0xc4, 0xe9, 0x02, 0x01, 0x00, 0x26, 0x4f, 0xf0, + 0x7e, 0x5a, 0x0d, 0xe0, 0xf0, 0x69, 0x05, 0xf0, 0x37, 0xfc, 0xdf, 0xf8, + 0x04, 0x16, 0x05, 0xf0, 0x43, 0xfc, 0x06, 0x46, 0x4f, 0xf0, 0x7e, 0x50, + 0x31, 0x46, 0x05, 0xf0, 0xbb, 0xfc, 0x82, 0x46, 0xb5, 0xf9, 0x0a, 0x00, + 0x44, 0x01, 0xb5, 0xf9, 0x0c, 0x00, 0x4f, 0xea, 0x40, 0x19, 0x02, 0x98, + 0x08, 0xeb, 0xc0, 0x07, 0x04, 0x98, 0x42, 0x68, 0xd2, 0xe9, 0x82, 0x01, + 0x02, 0x9a, 0x02, 0xf0, 0x01, 0xf9, 0xc0, 0x07, 0x2b, 0xd5, 0x20, 0x46, + 0x05, 0xf0, 0x0c, 0xfc, 0x01, 0x46, 0x50, 0x46, 0x05, 0xf0, 0xb0, 0xfd, + 0x04, 0x46, 0xb8, 0x6f, 0x05, 0xf0, 0x04, 0xfc, 0x01, 0x46, 0x30, 0x46, + 0x05, 0xf0, 0xa8, 0xfd, 0x01, 0x46, 0x20, 0x46, 0x05, 0xf0, 0x08, 0xfd, + 0x05, 0xf0, 0x0e, 0xfe, 0x04, 0x46, 0x48, 0x46, 0x05, 0xf0, 0xf6, 0xfb, + 0x01, 0x46, 0x50, 0x46, 0x05, 0xf0, 0x9a, 0xfd, 0x82, 0x46, 0xf8, 0x6f, + 0x05, 0xf0, 0xee, 0xfb, 0x01, 0x46, 0x30, 0x46, 0x05, 0xf0, 0x92, 0xfd, + 0x01, 0x46, 0x50, 0x46, 0x05, 0xf0, 0xf2, 0xfc, 0x05, 0xf0, 0xf8, 0xfd, + 0x81, 0x46, 0xfe, 0xf7, 0x85, 0xff, 0xbc, 0x67, 0x06, 0x46, 0xc7, 0xf8, + 0x7c, 0x90, 0x02, 0x98, 0x81, 0xb2, 0x04, 0x98, 0x00, 0xf0, 0xd6, 0xfa, + 0x86, 0xf3, 0x11, 0x88, 0x28, 0x88, 0x48, 0xb9, 0xfe, 0xf7, 0x76, 0xff, + 0x06, 0x46, 0x03, 0x98, 0xc8, 0xf8, 0x72, 0x00, 0xa5, 0xf8, 0x04, 0xb0, + 0x86, 0xf3, 0x11, 0x88, 0x01, 0x20, 0xe8, 0x81, 0x58, 0xe1, 0x38, 0xb5, + 0x14, 0x46, 0xdf, 0xf8, 0x64, 0x15, 0x4f, 0xf4, 0x08, 0x72, 0x02, 0xfb, + 0x00, 0x15, 0xff, 0xf7, 0x1b, 0xf8, 0x05, 0xf1, 0x68, 0x00, 0x01, 0x21, + 0x44, 0x80, 0x01, 0x80, 0x31, 0xbd, 0x00, 0x00, 0x04, 0x00, 0x00, 0x51, + 0x00, 0x00, 0x50, 0x59, 0x00, 0x00, 0x40, 0x59, 0x06, 0x40, 0x80, 0x83, + 0x07, 0x40, 0x00, 0x80, 0x00, 0xf5, 0x02, 0x70, 0x00, 0x22, 0xc0, 0xe9, + 0x00, 0x22, 0xc0, 0xe9, 0x02, 0x22, 0x70, 0x47, 0x70, 0xb5, 0x04, 0x46, + 0x0d, 0x46, 0x00, 0xf0, 0x59, 0xf8, 0x40, 0xf2, 0x42, 0x66, 0x88, 0xb3, + 0xdf, 0xf8, 0x14, 0x05, 0xb0, 0xf8, 0x54, 0x10, 0x28, 0x46, 0x03, 0xf0, + 0xa6, 0xfb, 0x08, 0xb1, 0x07, 0x20, 0x70, 0xbd, 0xdf, 0xf8, 0x04, 0x05, + 0x01, 0x78, 0x03, 0x22, 0x11, 0x42, 0x06, 0xd0, 0x00, 0x7e, 0x00, 0xf0, + 0x03, 0x00, 0x02, 0x28, 0x01, 0xd1, 0x06, 0x20, 0x70, 0xbd, 0xe8, 0xb2, + 0x02, 0xf0, 0xea, 0xfb, 0x00, 0x28, 0xe0, 0x60, 0x01, 0xd5, 0x08, 0x20, + 0x70, 0xbd, 0x00, 0x22, 0x10, 0x21, 0x30, 0x46, 0x01, 0xf0, 0x6c, 0xfe, + 0x08, 0x20, 0x04, 0xf0, 0x03, 0xf9, 0x08, 0xb1, 0x09, 0x20, 0x70, 0xbd, + 0xe0, 0x68, 0x04, 0xf0, 0xbc, 0xf8, 0x04, 0xf0, 0xdb, 0xf8, 0x00, 0xf0, + 0x1f, 0xf8, 0x13, 0xe0, 0xe5, 0x60, 0x01, 0x21, 0xe8, 0xb2, 0x04, 0xf0, + 0xfd, 0xf9, 0x04, 0xf0, 0x38, 0xfa, 0x00, 0xf0, 0x15, 0xf8, 0x00, 0x22, + 0x18, 0x21, 0x40, 0xf2, 0x7a, 0x60, 0x01, 0xf0, 0x4f, 0xfe, 0x00, 0x22, + 0x20, 0x21, 0x30, 0x46, 0x01, 0xf0, 0x4a, 0xfe, 0x00, 0x20, 0x70, 0xbd, + 0x68, 0x18, 0x00, 0x01, 0x00, 0x00, 0xc8, 0xc3, 0xc0, 0x01, 0x00, 0x45, + 0x98, 0xf1, 0x00, 0x20, 0xe0, 0x68, 0x80, 0x1c, 0x28, 0x21, 0x80, 0xb2, + 0x03, 0xf0, 0x46, 0xbf, 0x60, 0x68, 0xb0, 0xf9, 0x0c, 0x00, 0x70, 0x47, + 0x2d, 0xe9, 0xf0, 0x4f, 0xdf, 0xf8, 0x64, 0x04, 0x85, 0xb0, 0x80, 0x7a, + 0x00, 0xf0, 0x03, 0x00, 0x04, 0x90, 0x0c, 0x46, 0xdf, 0xf8, 0x58, 0x04, + 0x20, 0x60, 0x20, 0x46, 0x00, 0xf0, 0x8c, 0xf9, 0x05, 0x00, 0x40, 0xf0, + 0xc0, 0x80, 0x00, 0x26, 0x0f, 0xf2, 0x74, 0x4a, 0x04, 0x98, 0xf0, 0x40, + 0xc0, 0x07, 0x40, 0xf1, 0xb4, 0x80, 0x34, 0x20, 0x00, 0xfb, 0x06, 0xfb, + 0xdf, 0xf8, 0x34, 0x04, 0xdf, 0xf8, 0x30, 0x14, 0x0b, 0xeb, 0x00, 0x09, + 0x00, 0x20, 0x4b, 0xf8, 0x01, 0x00, 0xc9, 0xf8, 0x04, 0x00, 0x4f, 0xf4, + 0x08, 0x71, 0xdf, 0xf8, 0x08, 0x04, 0x01, 0xfb, 0x06, 0x00, 0x60, 0x60, + 0x00, 0x21, 0x81, 0x81, 0x01, 0x21, 0xc1, 0x81, 0x01, 0x82, 0x41, 0x82, + 0xff, 0xf7, 0x5e, 0xff, 0x60, 0x68, 0x00, 0x21, 0x20, 0xf8, 0x6e, 0x1f, + 0x41, 0x80, 0x32, 0x46, 0x21, 0x68, 0xb1, 0xf9, 0x24, 0x10, 0xfe, 0xf7, + 0x01, 0xff, 0x30, 0x46, 0x01, 0xf0, 0x4e, 0xff, 0x80, 0x46, 0x60, 0x68, + 0xa0, 0xf8, 0x6a, 0x80, 0x69, 0x46, 0x30, 0x46, 0x05, 0xf0, 0x28, 0xff, + 0xdd, 0xe9, 0x00, 0x01, 0xcd, 0xe9, 0x02, 0x01, 0x02, 0xaa, 0x00, 0x20, + 0x8d, 0xf8, 0x0a, 0x00, 0x01, 0x21, 0x30, 0x46, 0x05, 0xf0, 0x53, 0xff, + 0x20, 0x68, 0x90, 0xf8, 0x3a, 0x00, 0x3a, 0xf8, 0x10, 0x10, 0x00, 0xf0, + 0x79, 0xf8, 0x60, 0x8a, 0xe0, 0x82, 0x31, 0x46, 0x01, 0x20, 0x20, 0x82, + 0x00, 0xf0, 0xca, 0xf8, 0x05, 0x46, 0x02, 0x20, 0x20, 0x82, 0x31, 0x46, + 0x60, 0x8a, 0x00, 0x09, 0xe0, 0x82, 0x00, 0xf0, 0xc1, 0xf8, 0x05, 0xb9, + 0x05, 0x46, 0x20, 0x68, 0x90, 0xf8, 0x3a, 0x00, 0x47, 0x1c, 0x09, 0xe0, + 0x3a, 0xf8, 0x17, 0x10, 0x00, 0xf0, 0x5e, 0xf8, 0x01, 0x20, 0x00, 0xf0, + 0xb1, 0xf8, 0x05, 0xb9, 0x05, 0x46, 0x7f, 0x1c, 0x20, 0x68, 0x90, 0xf8, + 0x3b, 0x00, 0xbf, 0xb2, 0xb8, 0x42, 0xef, 0xd2, 0x07, 0x46, 0x12, 0xe0, + 0x20, 0x68, 0x90, 0xf8, 0x3b, 0x00, 0x02, 0xeb, 0xc0, 0x00, 0x00, 0xf1, + 0x70, 0x0c, 0x02, 0xeb, 0xc7, 0x02, 0xdc, 0xe9, 0x00, 0x01, 0x78, 0x32, + 0xc2, 0xe9, 0x00, 0x01, 0x39, 0x46, 0x20, 0x46, 0x00, 0xf0, 0xa4, 0xf9, + 0x7f, 0x1c, 0xbf, 0xb2, 0x62, 0x68, 0x32, 0x2f, 0xe8, 0xdb, 0xa2, 0xf8, + 0x6c, 0x80, 0x69, 0x46, 0x30, 0x46, 0x05, 0xf0, 0xef, 0xfe, 0x00, 0xf0, + 0x2e, 0xf8, 0x03, 0x20, 0x00, 0xf0, 0x84, 0xf8, 0x05, 0xb9, 0x05, 0x46, + 0x1d, 0xb9, 0x61, 0x68, 0x01, 0x20, 0xa1, 0xf8, 0x18, 0x02, 0x00, 0xf0, + 0x28, 0xf8, 0x30, 0xf8, 0x02, 0x1c, 0x00, 0xf0, 0x21, 0xf8, 0x00, 0xf0, + 0x1c, 0xf8, 0x00, 0xf0, 0x20, 0xf8, 0x30, 0xf8, 0x04, 0x1c, 0x00, 0xf0, + 0x19, 0xf8, 0x00, 0xf0, 0x14, 0xf8, 0x69, 0x46, 0x30, 0x46, 0x05, 0xf0, + 0xcf, 0xfe, 0x00, 0xf0, 0x0e, 0xf8, 0x64, 0x20, 0xc9, 0xf8, 0x04, 0x00, + 0xb6, 0x48, 0x4b, 0xf8, 0x00, 0x50, 0x76, 0x1c, 0x02, 0x2e, 0xff, 0xf4, + 0x43, 0xaf, 0x28, 0x46, 0x05, 0xb0, 0xbd, 0xe8, 0xf0, 0x8f, 0x30, 0x46, + 0xfe, 0xf7, 0xc6, 0xbe, 0x30, 0x46, 0x05, 0xf0, 0x1d, 0xbf, 0x20, 0x68, + 0x90, 0xf8, 0x3b, 0x00, 0x0a, 0xeb, 0x40, 0x00, 0x70, 0x47, 0x2d, 0xe9, + 0xf0, 0x47, 0x0c, 0x46, 0xa8, 0x48, 0xa7, 0x49, 0x20, 0x60, 0x49, 0x89, + 0xc0, 0x8f, 0x08, 0x40, 0x00, 0xf0, 0x03, 0x08, 0x20, 0x46, 0x00, 0xf0, + 0xab, 0xf8, 0x05, 0x00, 0x37, 0xd1, 0x00, 0x26, 0xdf, 0xf8, 0x88, 0xa2, + 0x28, 0xfa, 0x06, 0xf0, 0xc0, 0x07, 0x2d, 0xd5, 0x00, 0xf0, 0xd0, 0xfb, + 0x34, 0x20, 0x00, 0xfb, 0x06, 0xf9, 0x09, 0xeb, 0x0a, 0x07, 0x00, 0x20, + 0x78, 0x60, 0x49, 0xf8, 0x0a, 0x00, 0x00, 0xf0, 0xda, 0xfb, 0x94, 0x48, + 0x4f, 0xf4, 0x08, 0x71, 0x01, 0xfb, 0x06, 0x00, 0x60, 0x60, 0x01, 0x21, + 0x81, 0x81, 0xc1, 0x81, 0x21, 0x82, 0x31, 0x46, 0x60, 0x8a, 0xe0, 0x82, + 0x00, 0xf0, 0x1c, 0xf8, 0x05, 0x46, 0xa0, 0x8a, 0xe0, 0x82, 0x31, 0x46, + 0x02, 0x20, 0x20, 0x82, 0x00, 0xf0, 0x14, 0xf8, 0x05, 0xb9, 0x05, 0x46, + 0x00, 0xf0, 0xaa, 0xfb, 0x64, 0x20, 0x78, 0x60, 0x49, 0xf8, 0x0a, 0x50, + 0x00, 0xf0, 0xb9, 0xfb, 0x76, 0x1c, 0x02, 0x2e, 0xca, 0xd3, 0x28, 0x46, + 0xbd, 0xe8, 0xf0, 0x87, 0x49, 0x03, 0x00, 0x80, 0x20, 0x82, 0x31, 0x46, + 0x20, 0x46, 0xad, 0xe0, 0x2d, 0xe9, 0xf8, 0x43, 0x80, 0x46, 0x0d, 0x46, + 0x7f, 0x48, 0x80, 0x4f, 0x28, 0x60, 0x4f, 0xf4, 0x08, 0x71, 0x79, 0x48, + 0x01, 0xfb, 0x08, 0x00, 0x68, 0x60, 0x00, 0xf0, 0x89, 0xfb, 0x34, 0x20, + 0x00, 0xfb, 0x08, 0xf6, 0xf4, 0x19, 0x00, 0x20, 0x60, 0x60, 0xf0, 0x51, + 0x00, 0xf0, 0x95, 0xfb, 0x28, 0x46, 0x00, 0xf0, 0x4d, 0xf8, 0x5f, 0xea, + 0x00, 0x09, 0x2b, 0xd1, 0x68, 0x68, 0xb0, 0xf8, 0x18, 0x12, 0x11, 0xb9, + 0x4f, 0xf0, 0x04, 0x09, 0x24, 0xe0, 0x30, 0xf9, 0x0c, 0x1f, 0x00, 0x29, + 0x02, 0xbf, 0x29, 0x68, 0xb1, 0xf8, 0x40, 0x10, 0x00, 0x29, 0x10, 0xd1, + 0x01, 0x21, 0x01, 0x80, 0x03, 0x21, 0x29, 0x82, 0x00, 0x21, 0x41, 0x80, + 0x01, 0x20, 0x00, 0xf0, 0x1e, 0xf8, 0x81, 0x46, 0x02, 0x20, 0x00, 0xf0, + 0x1a, 0xf8, 0xb9, 0xf1, 0x00, 0x0f, 0x0b, 0xd1, 0x09, 0xe0, 0x01, 0x21, + 0x29, 0x82, 0x00, 0x21, 0x41, 0x80, 0x41, 0x46, 0xa8, 0x8a, 0xe8, 0x82, + 0x28, 0x46, 0x00, 0xf0, 0x65, 0xf8, 0x81, 0x46, 0x00, 0xf0, 0x4c, 0xfb, + 0x64, 0x20, 0x60, 0x60, 0x46, 0xf8, 0x07, 0x90, 0x00, 0xf0, 0x5b, 0xfb, + 0x48, 0x46, 0xbd, 0xe8, 0xf2, 0x83, 0x28, 0x82, 0x41, 0x46, 0x28, 0x46, + 0x54, 0xe0, 0x80, 0xb5, 0x53, 0x49, 0x56, 0x4a, 0x09, 0x6c, 0xa0, 0xfb, + 0x01, 0x01, 0x00, 0x23, 0x05, 0xf0, 0xc4, 0xfe, 0x04, 0xf0, 0x76, 0xfa, + 0xbd, 0xe8, 0x02, 0x40, 0x04, 0xf0, 0x68, 0xba, 0x70, 0xb5, 0x04, 0x46, + 0x00, 0x20, 0x02, 0xf0, 0x7b, 0xfd, 0x06, 0x46, 0x20, 0x68, 0x01, 0x88, + 0x0a, 0x25, 0x8e, 0x42, 0xb8, 0xbf, 0x0e, 0x46, 0x03, 0xdb, 0x40, 0x88, + 0xb0, 0x42, 0xb8, 0xbf, 0x06, 0x46, 0x10, 0x2e, 0x18, 0xdb, 0x40, 0xf2, + 0xee, 0x20, 0xff, 0xf7, 0xda, 0xff, 0x05, 0x46, 0xa6, 0xf1, 0x0f, 0x00, + 0xff, 0xf7, 0xd5, 0xff, 0x06, 0x46, 0x04, 0xf0, 0x53, 0xfa, 0x20, 0x83, + 0x20, 0x68, 0x41, 0x68, 0x69, 0x43, 0xb1, 0xfb, 0xf6, 0xf1, 0x61, 0x82, + 0x80, 0x68, 0x68, 0x43, 0xb0, 0xfb, 0xf6, 0xf0, 0xa0, 0x82, 0x00, 0x25, + 0x28, 0x46, 0x70, 0xbd, 0x70, 0xb5, 0x00, 0x24, 0x38, 0x4d, 0x31, 0x4e, + 0x4f, 0xf4, 0x08, 0x70, 0x22, 0x46, 0x01, 0x21, 0x00, 0xfb, 0x04, 0x60, + 0xfe, 0xf7, 0x16, 0xfd, 0x2b, 0x46, 0x00, 0x22, 0xe1, 0xb2, 0x00, 0x20, + 0x01, 0xf0, 0x7c, 0xfd, 0x64, 0x1c, 0x02, 0x2c, 0xee, 0xd3, 0x70, 0xbd, + 0x00, 0x01, 0x00, 0x45, 0x70, 0xb5, 0x04, 0x46, 0x0d, 0x46, 0x00, 0x20, + 0x05, 0xf0, 0x5b, 0xff, 0x90, 0xb1, 0x29, 0x46, 0x00, 0x20, 0x05, 0xf0, + 0x5b, 0xff, 0x06, 0x46, 0x32, 0x46, 0x29, 0x46, 0x20, 0x46, 0xff, 0xf7, + 0xae, 0xf9, 0x21, 0x8a, 0x49, 0x1e, 0x21, 0x82, 0x09, 0xb2, 0x01, 0x29, + 0x03, 0xdb, 0x00, 0x28, 0xf2, 0xd0, 0x70, 0xbd, 0x03, 0x20, 0x70, 0xbd, + 0x18, 0x49, 0xc2, 0x07, 0x44, 0xbf, 0x01, 0x22, 0x0a, 0x82, 0x80, 0x07, + 0x44, 0xbf, 0x01, 0x20, 0xa1, 0xf8, 0x30, 0x02, 0x70, 0x47, 0x00, 0x00, + 0xa4, 0x70, 0x7d, 0x3f, 0x11, 0x49, 0xc2, 0x07, 0x44, 0xbf, 0x01, 0x22, + 0x4a, 0x82, 0x80, 0x07, 0x44, 0xbf, 0x01, 0x20, 0xa1, 0xf8, 0x32, 0x02, + 0x70, 0x47, 0x00, 0x00, 0x00, 0x24, 0x74, 0x49, 0x00, 0x00, 0x7a, 0x44, + 0x00, 0x00, 0x80, 0xbf, 0x02, 0x56, 0xfd, 0x37, 0x00, 0x00, 0x34, 0x44, + 0x00, 0xa0, 0x8c, 0x47, 0xcd, 0xcc, 0x4c, 0x3d, 0x01, 0x00, 0x80, 0x3f, + 0xff, 0xe6, 0xdb, 0x2e, 0x00, 0x00, 0xc8, 0x42, 0x00, 0x00, 0x20, 0x41, + 0x24, 0x2b, 0x00, 0x20, 0x48, 0xad, 0x00, 0x20, 0x4c, 0x1f, 0x00, 0x20, + 0x48, 0x04, 0x00, 0x46, 0x78, 0x29, 0x00, 0x20, 0xdc, 0x2a, 0x00, 0x20, + 0x98, 0xf1, 0x00, 0x20, 0x80, 0x8d, 0x5b, 0x00, 0xbf, 0x12, 0x00, 0x01, + 0xd0, 0xb5, 0x44, 0x68, 0x0a, 0x46, 0xd4, 0xe9, 0x82, 0x67, 0x01, 0x20, + 0x00, 0x21, 0x05, 0xf0, 0x1b, 0xfd, 0x30, 0x43, 0x39, 0x43, 0xc4, 0xe9, + 0x82, 0x01, 0xd0, 0xbd, 0x42, 0x06, 0x7a, 0x06, 0x00, 0x00, 0x06, 0x00, + 0x0c, 0x00, 0x0f, 0x00, 0x15, 0x00, 0x1b, 0x00, 0x1e, 0x00, 0x24, 0x00, + 0x28, 0x00, 0x2f, 0x00, 0x32, 0x00, 0x37, 0x00, 0x3e, 0x00, 0x41, 0x00, + 0x46, 0x00, 0x4b, 0x00, 0x52, 0x00, 0x56, 0x00, 0x5b, 0x00, 0x60, 0x00, + 0x65, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x79, 0x00, 0x7e, 0x00, + 0x84, 0x00, 0x91, 0x00, 0x96, 0x00, 0x9d, 0x00, 0xab, 0x00, 0xba, 0x00, + 0xc3, 0x00, 0xd3, 0x00, 0xdd, 0x00, 0xe7, 0x00, 0xf1, 0x00, 0x09, 0x01, + 0x15, 0x01, 0x23, 0x01, 0x32, 0x01, 0x55, 0x01, 0x6b, 0x01, 0x83, 0x01, + 0x9d, 0x01, 0xbe, 0x01, 0xe2, 0x01, 0x14, 0x02, 0x5a, 0x02, 0xd3, 0x02, + 0xff, 0xfc, 0xf9, 0xf6, 0xf4, 0xf1, 0xfe, 0xfb, 0xf8, 0xf5, 0xf2, 0xef, + 0xfd, 0xfa, 0xf7, 0xfd, 0xfa, 0xf7, 0xf4, 0xf1, 0xee, 0xfd, 0xfa, 0xf7, + 0xf4, 0xf1, 0xee, 0xfd, 0xfa, 0xf7, 0xfe, 0xfb, 0xf8, 0xf5, 0xf2, 0xef, + 0xff, 0xfd, 0xfa, 0xf7, 0xfe, 0xfb, 0xf8, 0xf5, 0xf2, 0xef, 0xec, 0xfd, + 0xfb, 0xf8, 0xff, 0xfc, 0xf9, 0xf6, 0xf4, 0xfb, 0xf8, 0xf5, 0xf3, 0xf0, + 0xed, 0xea, 0xfd, 0xfa, 0xf7, 0xff, 0xfd, 0xfa, 0xf7, 0xf4, 0xfd, 0xfa, + 0xf7, 0xf4, 0xf1, 0xfa, 0xf7, 0xf4, 0xf1, 0xee, 0xec, 0xe9, 0xfe, 0xfb, + 0xf8, 0xf5, 0xff, 0xfc, 0xfa, 0xf7, 0xf4, 0xfe, 0xfb, 0xf8, 0xf5, 0xf2, + 0xfd, 0xfa, 0xf7, 0xf4, 0xf1, 0xfc, 0xf9, 0xf6, 0xf3, 0xff, 0xfc, 0xf9, + 0xf6, 0xf3, 0xff, 0xfc, 0xf9, 0xf6, 0xf3, 0xff, 0xfd, 0xfa, 0xf7, 0xf4, + 0xf1, 0xfe, 0xfb, 0xf8, 0xf5, 0xf2, 0xff, 0xfc, 0xf9, 0xf6, 0xf3, 0xf1, + 0xfe, 0xfb, 0xf8, 0xf5, 0xf3, 0xf0, 0xed, 0xea, 0xe7, 0xe4, 0xe2, 0xdf, + 0xdc, 0xfb, 0xf8, 0xf5, 0xf2, 0xf0, 0xff, 0xfc, 0xf9, 0xf6, 0xf3, 0xf1, + 0xee, 0xfe, 0xfb, 0xf8, 0xf5, 0xf2, 0xef, 0xec, 0xea, 0xe7, 0xe4, 0xe1, + 0xde, 0xdc, 0xd9, 0xfd, 0xfb, 0xf8, 0xf5, 0xf2, 0xef, 0xec, 0xe9, 0xe6, + 0xe4, 0xe1, 0xde, 0xdb, 0xd9, 0xd6, 0xfe, 0xfb, 0xf8, 0xf5, 0xf2, 0xef, + 0xec, 0xea, 0xe7, 0xfb, 0xf8, 0xf5, 0xf2, 0xf0, 0xed, 0xea, 0xe7, 0xe4, + 0xe1, 0xdf, 0xdc, 0xd9, 0xd6, 0xd4, 0xd1, 0xff, 0xfc, 0xf9, 0xf6, 0xf4, + 0xf1, 0xee, 0xeb, 0xe8, 0xe5, 0xfd, 0xfa, 0xf8, 0xf5, 0xf2, 0xef, 0xec, + 0xe9, 0xe6, 0xe4, 0xfd, 0xfa, 0xf7, 0xf4, 0xf2, 0xef, 0xec, 0xe9, 0xe6, + 0xe3, 0xff, 0xfc, 0xf9, 0xf6, 0xf3, 0xf0, 0xed, 0xeb, 0xe8, 0xe5, 0xe2, + 0xdf, 0xdd, 0xda, 0xd7, 0xd4, 0xd2, 0xcf, 0xcc, 0xca, 0xc7, 0xc4, 0xc2, + 0xbf, 0xfc, 0xf9, 0xf7, 0xf4, 0xf1, 0xee, 0xeb, 0xe8, 0xe5, 0xe3, 0xe0, + 0xdd, 0xff, 0xfc, 0xf9, 0xf6, 0xf3, 0xf0, 0xee, 0xeb, 0xe8, 0xe5, 0xe2, + 0xe0, 0xdd, 0xda, 0xff, 0xfc, 0xf9, 0xf6, 0xf3, 0xf0, 0xed, 0xea, 0xe8, + 0xe5, 0xe2, 0xdf, 0xdd, 0xda, 0xd7, 0xff, 0xfc, 0xf9, 0xf6, 0xf3, 0xf0, + 0xee, 0xeb, 0xe8, 0xe5, 0xe2, 0xe0, 0xdd, 0xda, 0xd7, 0xd5, 0xd2, 0xcf, + 0xcd, 0xca, 0xc7, 0xc5, 0xc2, 0xc0, 0xbd, 0xba, 0xb8, 0xb5, 0xb3, 0xb0, + 0xae, 0xab, 0xa9, 0xa6, 0xa4, 0xff, 0xfc, 0xf9, 0xf6, 0xf3, 0xf0, 0xed, + 0xea, 0xe8, 0xe5, 0xe2, 0xdf, 0xdc, 0xda, 0xd7, 0xd4, 0xd2, 0xcf, 0xcc, + 0xca, 0xc7, 0xc4, 0xfa, 0xf7, 0xf4, 0xf1, 0xef, 0xec, 0xe9, 0xe6, 0xe3, + 0xe0, 0xde, 0xdb, 0xd8, 0xd6, 0xd3, 0xd0, 0xcd, 0xcb, 0xc8, 0xc6, 0xc3, + 0xc0, 0xbe, 0xbb, 0xf8, 0xf5, 0xf2, 0xef, 0xec, 0xe9, 0xe7, 0xe4, 0xe1, + 0xde, 0xdc, 0xd9, 0xd6, 0xd3, 0xd1, 0xce, 0xcb, 0xc9, 0xc6, 0xc3, 0xc1, + 0xbe, 0xbc, 0xb9, 0xb7, 0xb4, 0xfa, 0xf7, 0xf4, 0xf1, 0xee, 0xec, 0xe9, + 0xe6, 0xe3, 0xe0, 0xde, 0xdb, 0xd8, 0xd5, 0xd3, 0xd0, 0xcd, 0xcb, 0xc8, + 0xc6, 0xc3, 0xc0, 0xbe, 0xbb, 0xb9, 0xb6, 0xb4, 0xb1, 0xaf, 0xac, 0xaa, + 0xa7, 0xa5, 0xf6, 0xf3, 0xf0, 0xee, 0xeb, 0xe8, 0xe5, 0xe2, 0xe0, 0xdd, + 0xda, 0xd7, 0xd5, 0xd2, 0xcf, 0xcd, 0xca, 0xc7, 0xc5, 0xc2, 0xbf, 0xbd, + 0xba, 0xb8, 0xb5, 0xb3, 0xb0, 0xae, 0xab, 0xa9, 0xa6, 0xa4, 0xa2, 0x9f, + 0x9d, 0x9a, 0xfe, 0xfb, 0xf8, 0xf5, 0xf3, 0xf0, 0xed, 0xea, 0xe7, 0xe4, + 0xe2, 0xdf, 0xdc, 0xd9, 0xd7, 0xd4, 0xd1, 0xcf, 0xcc, 0xc9, 0xc7, 0xc4, + 0xc1, 0xbf, 0xbc, 0xba, 0xb7, 0xb5, 0xb2, 0xb0, 0xad, 0xab, 0xa8, 0xa6, + 0xa3, 0xa1, 0x9f, 0x9c, 0x9a, 0x97, 0x95, 0x93, 0x90, 0x8e, 0x8c, 0x8a, + 0x87, 0x85, 0x83, 0x81, 0xfe, 0xfb, 0xf8, 0xf5, 0xf3, 0xf0, 0xed, 0xea, + 0xe7, 0xe4, 0xe2, 0xdf, 0xdc, 0xd9, 0xd7, 0xd4, 0xd1, 0xcf, 0xcc, 0xc9, + 0xc7, 0xc4, 0xc1, 0xbf, 0xbc, 0xba, 0xb7, 0xb5, 0xb2, 0xb0, 0xad, 0xab, + 0xa8, 0xa6, 0xa3, 0xa1, 0x9f, 0x9c, 0x9a, 0x97, 0x95, 0x93, 0x90, 0x8e, + 0x8c, 0x8a, 0x87, 0x85, 0x83, 0x81, 0x7e, 0x7c, 0x7a, 0x78, 0x76, 0x73, + 0x71, 0x6f, 0x6d, 0x6b, 0x69, 0x67, 0x65, 0x63, 0x61, 0x5f, 0x5d, 0x5b, + 0x59, 0x57, 0xff, 0xfc, 0xfa, 0xf7, 0xf4, 0xf1, 0xee, 0xeb, 0xe8, 0xe6, + 0xe3, 0xe0, 0xdd, 0xda, 0xd8, 0xd5, 0xd2, 0xd0, 0xcd, 0xca, 0xc8, 0xc5, + 0xc3, 0xc0, 0xbd, 0xbb, 0xb8, 0xb6, 0xb3, 0xb1, 0xae, 0xac, 0xa9, 0xa7, + 0xa4, 0xa2, 0xa0, 0x9d, 0x9b, 0x98, 0x96, 0x94, 0x91, 0x8f, 0x8d, 0x8b, + 0x88, 0x86, 0x84, 0x82, 0x7f, 0x7d, 0x7b, 0x79, 0x77, 0x74, 0x72, 0x70, + 0x6e, 0x6c, 0x6a, 0x68, 0x66, 0x64, 0x62, 0x60, 0x5e, 0x5c, 0x5a, 0x58, + 0x56, 0x54, 0x52, 0x50, 0x4e, 0x4c, 0x4a, 0x48, 0x46, 0x44, 0x42, 0x41, + 0x3f, 0x3d, 0x3b, 0x39, 0x37, 0x36, 0x34, 0x32, 0x30, 0x2f, 0x2d, 0x2b, + 0x29, 0x28, 0x26, 0x24, 0x23, 0x21, 0x1f, 0x1e, 0x1c, 0x1a, 0x19, 0x17, + 0x15, 0x14, 0x12, 0x11, 0x0f, 0x0e, 0x0c, 0x0b, 0x09, 0x07, 0x06, 0x04, + 0x03, 0x01, 0x00, 0xfe, 0xfb, 0xf8, 0xf5, 0xf2, 0xef, 0xec, 0xea, 0xe7, + 0xe4, 0xe1, 0xde, 0xdc, 0xd9, 0xd6, 0xd3, 0xd1, 0xce, 0xcb, 0xc9, 0xc6, + 0xc4, 0xc1, 0xbe, 0xbc, 0xb9, 0xb7, 0xb4, 0xb2, 0xaf, 0xad, 0xaa, 0xa8, + 0xa5, 0xa3, 0xa1, 0x9e, 0x9c, 0x99, 0x97, 0x95, 0x92, 0x90, 0x8e, 0x8b, + 0x89, 0x87, 0x85, 0x82, 0x80, 0x7e, 0x7c, 0x7a, 0x77, 0x75, 0x73, 0x71, + 0x6f, 0x6d, 0x6b, 0x69, 0x67, 0x64, 0x62, 0x60, 0x5e, 0x5c, 0x5a, 0x58, + 0x56, 0x54, 0x52, 0x50, 0x4f, 0x4d, 0x4b, 0x49, 0x47, 0x45, 0x43, 0x41, + 0x3f, 0x3e, 0x3c, 0x3a, 0x38, 0x36, 0x35, 0x33, 0x31, 0x2f, 0x2e, 0x2c, + 0x2a, 0x28, 0x27, 0x25, 0x23, 0x22, 0x20, 0x1e, 0x1d, 0x1b, 0x19, 0x18, + 0x16, 0x15, 0x13, 0x11, 0x10, 0x0e, 0x0d, 0x0b, 0x0a, 0x08, 0x07, 0x00, + 0x70, 0xb5, 0x86, 0xb0, 0x05, 0xf0, 0xac, 0xfe, 0xdf, 0xf8, 0x14, 0x19, + 0xdf, 0xf8, 0x14, 0x49, 0x00, 0x20, 0x08, 0x60, 0x20, 0x70, 0x60, 0x70, + 0xa0, 0x71, 0x60, 0x71, 0x20, 0x61, 0xe0, 0x61, 0x20, 0x72, 0x20, 0x71, + 0x00, 0x21, 0x04, 0xf1, 0x0c, 0x00, 0xa1, 0x70, 0x01, 0x60, 0xe1, 0x70, + 0xa1, 0x62, 0x21, 0x62, 0x04, 0xf5, 0x45, 0x75, 0x4f, 0xf4, 0xfc, 0x61, + 0x28, 0x46, 0x00, 0xf0, 0x78, 0xf9, 0x64, 0x21, 0x04, 0xf1, 0x30, 0x00, + 0x00, 0xf0, 0x73, 0xf9, 0x00, 0x20, 0xad, 0xa1, 0x54, 0x22, 0x02, 0xfb, + 0x00, 0x43, 0x03, 0xf5, 0x45, 0x76, 0x40, 0x1c, 0x03, 0xf5, 0x5a, 0x73, + 0x17, 0x28, 0x73, 0x61, 0xf1, 0x64, 0xf4, 0xd3, 0x02, 0xfb, 0x00, 0x40, + 0x00, 0xf5, 0x45, 0x70, 0x00, 0x22, 0x42, 0x61, 0xc1, 0x64, 0x65, 0x62, + 0xe2, 0x62, 0x04, 0xf1, 0x94, 0x05, 0x4f, 0xf4, 0xa0, 0x71, 0x28, 0x46, + 0x00, 0xf0, 0x55, 0xf9, 0x00, 0x20, 0x00, 0x23, 0x04, 0xeb, 0x00, 0x11, + 0x01, 0xf1, 0x94, 0x02, 0x40, 0x1c, 0xa4, 0x31, 0x13, 0x28, 0x13, 0x70, + 0x51, 0x60, 0xf5, 0xd3, 0x04, 0xeb, 0x00, 0x10, 0x00, 0xf8, 0x94, 0x3f, + 0x43, 0x60, 0x65, 0x61, 0x00, 0xf0, 0xea, 0xfb, 0x00, 0xf0, 0x5c, 0xfd, + 0x03, 0x21, 0x04, 0x91, 0x00, 0x21, 0x03, 0x91, 0x80, 0x21, 0x02, 0x91, + 0x4f, 0xf6, 0xff, 0x71, 0xdf, 0xf8, 0x64, 0x08, 0x01, 0x90, 0x00, 0x91, + 0x00, 0xf5, 0xfe, 0x72, 0x18, 0x23, 0x00, 0x21, 0x0f, 0xf2, 0xc1, 0x30, + 0x00, 0xf0, 0x0d, 0xfe, 0x05, 0xaa, 0x0f, 0xf2, 0x14, 0x01, 0x18, 0x20, + 0x00, 0xf0, 0xbe, 0xfe, 0x01, 0xf0, 0x74, 0xf8, 0xc0, 0x46, 0xc0, 0x46, + 0x06, 0xb0, 0x70, 0xbd, 0x75, 0x43, 0x2f, 0x4f, 0x53, 0x2d, 0x49, 0x49, + 0x20, 0x49, 0x64, 0x6c, 0x65, 0x00, 0x00, 0x00, 0x38, 0xb5, 0x00, 0xf0, + 0x31, 0xf8, 0x1e, 0xd1, 0x05, 0xf0, 0x9a, 0xfe, 0x05, 0x46, 0x20, 0x78, + 0x08, 0xb1, 0x40, 0x1e, 0x20, 0x70, 0x20, 0x78, 0x61, 0x78, 0x08, 0x43, + 0x11, 0xd1, 0x00, 0xf0, 0x2c, 0xf9, 0xe0, 0x78, 0xa2, 0x78, 0x04, 0xeb, + 0x80, 0x01, 0x90, 0x42, 0x09, 0x6b, 0xa1, 0x62, 0x07, 0xd0, 0x88, 0x6b, + 0x40, 0x1c, 0x88, 0x63, 0x20, 0x69, 0x40, 0x1c, 0x20, 0x61, 0x05, 0xf0, + 0x9a, 0xfe, 0x28, 0x46, 0x15, 0xe1, 0x31, 0xbd, 0x10, 0xb5, 0x00, 0xf0, + 0x0d, 0xf8, 0x0a, 0xd1, 0x05, 0xf0, 0x76, 0xfe, 0x21, 0x78, 0x21, 0xb9, + 0x61, 0x78, 0xff, 0x29, 0x1c, 0xbf, 0x49, 0x1c, 0x61, 0x70, 0x00, 0xf0, + 0xe3, 0xbe, 0x10, 0xbd, 0xdf, 0xf8, 0xb4, 0x47, 0x60, 0x79, 0x01, 0x28, + 0x70, 0x47, 0x10, 0xb5, 0xff, 0xf7, 0xf8, 0xff, 0x10, 0xd1, 0x05, 0xf0, + 0x61, 0xfe, 0x21, 0x78, 0x51, 0xb9, 0x61, 0x78, 0x41, 0xb1, 0x49, 0x1e, + 0x61, 0x70, 0xc9, 0xb2, 0x21, 0xb9, 0x80, 0xf3, 0x11, 0x88, 0xbd, 0xe8, + 0x10, 0x40, 0xcf, 0xe0, 0x00, 0xf0, 0xc8, 0xbe, 0x10, 0xbd, 0x10, 0xb5, + 0xdf, 0xf8, 0x7c, 0x47, 0x60, 0x79, 0x60, 0xb9, 0x00, 0xf0, 0xe7, 0xf8, + 0xe0, 0x78, 0xa0, 0x70, 0x04, 0xeb, 0x80, 0x00, 0x00, 0x6b, 0xa0, 0x62, + 0x20, 0x62, 0xbd, 0xe8, 0x10, 0x40, 0x05, 0xf0, 0x48, 0xbe, 0x10, 0xbd, + 0x70, 0xb5, 0x05, 0xf0, 0x14, 0xfe, 0x05, 0xf0, 0x39, 0xfe, 0xdf, 0xf8, + 0x4c, 0x17, 0xdf, 0xf8, 0x4c, 0x47, 0x0a, 0x68, 0x52, 0x1c, 0x0a, 0x60, + 0x80, 0xf3, 0x11, 0x88, 0x60, 0x79, 0x01, 0x28, 0x35, 0xd1, 0xe0, 0x79, + 0x38, 0xb1, 0x02, 0x28, 0x01, 0xd0, 0x30, 0xd3, 0x01, 0xe0, 0x01, 0x20, + 0x00, 0xe0, 0x00, 0x20, 0xe0, 0x71, 0xe6, 0x6a, 0x12, 0xe0, 0x69, 0x77, + 0x29, 0x7f, 0x09, 0x07, 0x0b, 0xd4, 0x06, 0xf1, 0x34, 0x01, 0x22, 0x79, + 0x8b, 0x78, 0x1a, 0x43, 0x22, 0x71, 0x0a, 0x78, 0x49, 0x78, 0x12, 0x19, + 0x13, 0x7b, 0x19, 0x43, 0x11, 0x73, 0x2e, 0x68, 0x80, 0xf3, 0x11, 0x88, + 0x06, 0xf1, 0x14, 0x05, 0xa8, 0x7f, 0x18, 0x28, 0x11, 0xd0, 0x05, 0xf0, + 0x07, 0xfe, 0xa9, 0x69, 0x00, 0x29, 0xf2, 0xd0, 0x49, 0x1e, 0xa9, 0x61, + 0xef, 0xd1, 0x29, 0x7f, 0x37, 0x22, 0x11, 0x42, 0x1d, 0xbf, 0x01, 0xf0, + 0xc8, 0x01, 0x29, 0x77, 0x01, 0x21, 0x00, 0x21, 0xd5, 0xe7, 0x70, 0xbd, + 0xf8, 0xb5, 0x85, 0x7a, 0x0f, 0xf2, 0x38, 0x14, 0xdf, 0xf8, 0xc0, 0x76, + 0x2e, 0x5d, 0x35, 0x18, 0x4f, 0xf0, 0x00, 0x0e, 0xed, 0x7a, 0x2c, 0x5d, + 0x04, 0xeb, 0xc6, 0x05, 0xed, 0xb2, 0x07, 0xeb, 0x85, 0x04, 0x24, 0x6b, + 0x04, 0xf1, 0x20, 0x0c, 0xcc, 0xf8, 0x00, 0x10, 0xcc, 0xf8, 0x0c, 0xe0, + 0x8c, 0xf8, 0x11, 0x30, 0x9c, 0xf8, 0x10, 0x10, 0x91, 0x43, 0x8c, 0xf8, + 0x10, 0x10, 0x9c, 0xf8, 0x10, 0x10, 0x09, 0x07, 0x0a, 0xd4, 0x39, 0x79, + 0x9c, 0xf8, 0x16, 0x20, 0x11, 0x43, 0x39, 0x71, 0xf1, 0x19, 0x9c, 0xf8, + 0x15, 0x30, 0x0a, 0x7b, 0x1a, 0x43, 0x0a, 0x73, 0x01, 0x46, 0x20, 0x46, + 0x00, 0xf0, 0x26, 0xf8, 0x28, 0x46, 0xf2, 0xbd, 0x10, 0xb5, 0xdf, 0xf8, + 0x60, 0x16, 0x0a, 0x6a, 0x42, 0xf8, 0x1c, 0x0f, 0x13, 0x7e, 0x52, 0x7e, + 0x1b, 0x18, 0xdc, 0x7a, 0x22, 0x43, 0xda, 0x72, 0x0b, 0x6a, 0x82, 0x7a, + 0x93, 0xf8, 0x36, 0x30, 0x1a, 0x43, 0x82, 0x72, 0x08, 0x6a, 0x10, 0xf8, + 0x34, 0x2f, 0x44, 0x78, 0x52, 0x18, 0x13, 0x7b, 0xa3, 0x43, 0x13, 0x73, + 0x04, 0xd1, 0x0a, 0x79, 0x80, 0x78, 0x22, 0xea, 0x00, 0x00, 0x08, 0x71, + 0x10, 0xbd, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x10, 0xb5, 0x10, 0xf8, + 0x34, 0x2f, 0x44, 0x78, 0x52, 0x18, 0xd3, 0x7a, 0xa3, 0x43, 0xd3, 0x72, + 0x04, 0xd1, 0x8a, 0x7a, 0x80, 0x78, 0x22, 0xea, 0x00, 0x00, 0x88, 0x72, + 0x10, 0xbd, 0x00, 0x21, 0x81, 0x72, 0x0b, 0x30, 0x04, 0x21, 0x01, 0xf0, + 0x2f, 0xb8, 0x00, 0x29, 0x18, 0xbf, 0x01, 0xf0, 0x2b, 0xb8, 0x70, 0x47, + 0x38, 0xb5, 0x05, 0xf0, 0x81, 0xfd, 0xdf, 0xf8, 0xe0, 0x55, 0x69, 0x78, + 0x04, 0x46, 0x28, 0x78, 0x08, 0x43, 0x11, 0xd1, 0x00, 0xf0, 0x15, 0xf8, + 0xe8, 0x78, 0xaa, 0x78, 0x05, 0xeb, 0x80, 0x01, 0x90, 0x42, 0x09, 0x6b, + 0xa9, 0x62, 0x07, 0xd0, 0x88, 0x6b, 0x40, 0x1c, 0x88, 0x63, 0x28, 0x69, + 0x40, 0x1c, 0x28, 0x61, 0x05, 0xf0, 0x7f, 0xfd, 0x20, 0x46, 0xbd, 0xe8, + 0x32, 0x40, 0x05, 0xf0, 0x69, 0xbd, 0xdf, 0xf8, 0xa4, 0x05, 0x0f, 0xf2, + 0x14, 0x01, 0x02, 0x79, 0x52, 0x5c, 0x13, 0x18, 0x1b, 0x7b, 0x59, 0x5c, + 0x01, 0xeb, 0xc2, 0x01, 0xc1, 0x70, 0x70, 0x47, 0x00, 0x00, 0x01, 0x00, + 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, + 0x04, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, + 0x02, 0x00, 0x01, 0x00, 0x05, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, + 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x04, 0x00, 0x01, 0x00, + 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, + 0x06, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, + 0x02, 0x00, 0x01, 0x00, 0x04, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, + 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x05, 0x00, 0x01, 0x00, + 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, + 0x04, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, + 0x02, 0x00, 0x01, 0x00, 0x07, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, + 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x04, 0x00, 0x01, 0x00, + 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, + 0x05, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, + 0x02, 0x00, 0x01, 0x00, 0x04, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, + 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x06, 0x00, 0x01, 0x00, + 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, + 0x04, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, + 0x02, 0x00, 0x01, 0x00, 0x05, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, + 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x04, 0x00, 0x01, 0x00, + 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, + 0x80, 0xb5, 0x05, 0xf0, 0xd3, 0xfc, 0xdf, 0xf8, 0x84, 0x14, 0xca, 0x69, + 0x52, 0x1c, 0xca, 0x61, 0x80, 0xf3, 0x11, 0x88, 0x05, 0xf0, 0x60, 0xfc, + 0xf3, 0xe7, 0x2d, 0xe9, 0xf8, 0x43, 0x04, 0x46, 0x0f, 0x46, 0x91, 0x46, + 0x98, 0x46, 0x05, 0xf0, 0xc1, 0xfc, 0xdf, 0xf8, 0x60, 0x54, 0x6e, 0x6a, + 0x00, 0x2e, 0x58, 0xd0, 0x71, 0x69, 0x69, 0x62, 0x80, 0xf3, 0x11, 0x88, + 0x37, 0x60, 0x00, 0x20, 0x06, 0xf1, 0x30, 0x07, 0xbc, 0x70, 0x38, 0x70, + 0x78, 0x70, 0xf0, 0x62, 0x01, 0x22, 0x09, 0x98, 0x70, 0x60, 0x04, 0xf0, + 0x07, 0x01, 0x08, 0x98, 0xf0, 0x60, 0xc6, 0xf8, 0x08, 0x90, 0x0a, 0x98, + 0x30, 0x82, 0xa6, 0xf8, 0x12, 0x80, 0x00, 0x20, 0xf8, 0x71, 0xf9, 0x70, + 0xe0, 0x08, 0x38, 0x71, 0x02, 0xfa, 0x00, 0xf0, 0xb8, 0x71, 0x02, 0xfa, + 0x01, 0xf0, 0x78, 0x71, 0x00, 0x20, 0xf0, 0x61, 0x70, 0x62, 0x30, 0x62, + 0xb8, 0x60, 0x38, 0x61, 0xf8, 0x60, 0x78, 0x61, 0xb8, 0x61, 0x4d, 0xa0, + 0xf8, 0x61, 0x00, 0x20, 0x38, 0x62, 0x30, 0x46, 0x05, 0xf0, 0x5f, 0xfc, + 0x05, 0xf0, 0x86, 0xfc, 0x05, 0xeb, 0x84, 0x01, 0x0e, 0x63, 0x80, 0xf3, + 0x11, 0x88, 0x30, 0x46, 0x05, 0xf0, 0x10, 0xfc, 0x05, 0xf0, 0x7c, 0xfc, + 0xe9, 0x6a, 0x71, 0x61, 0x00, 0x21, 0xb1, 0x61, 0xe9, 0x6a, 0x01, 0xb1, + 0x8e, 0x61, 0xee, 0x62, 0x29, 0x79, 0xba, 0x79, 0x11, 0x43, 0x29, 0x71, + 0x39, 0x79, 0x7b, 0x79, 0x49, 0x19, 0x0a, 0x7b, 0x1a, 0x43, 0x0a, 0x73, + 0xa9, 0x79, 0x49, 0x1c, 0xa9, 0x71, 0x80, 0xf3, 0x11, 0x88, 0x00, 0x20, + 0x02, 0xe0, 0x80, 0xf3, 0x11, 0x88, 0x42, 0x20, 0xbd, 0xe8, 0xf2, 0x83, + 0x00, 0x00, 0x00, 0x00, 0x2d, 0xe9, 0xf0, 0x41, 0x05, 0x46, 0x88, 0x46, + 0x28, 0x78, 0x05, 0x28, 0x17, 0x46, 0x1c, 0x46, 0x02, 0xd0, 0x00, 0xf0, + 0x7c, 0xfa, 0x36, 0xe0, 0x38, 0x06, 0x46, 0xbf, 0x07, 0xf0, 0x7f, 0x07, + 0x01, 0x26, 0x00, 0x26, 0x00, 0x20, 0x20, 0x70, 0x05, 0xf0, 0x46, 0xfc, + 0x03, 0x2f, 0x24, 0xd8, 0xdf, 0xe8, 0x07, 0xf0, 0x15, 0x1b, 0x02, 0x0c, + 0x29, 0x89, 0x08, 0xea, 0x01, 0x07, 0x47, 0x45, 0x08, 0xd0, 0x70, 0x21, + 0x21, 0x70, 0x80, 0xf3, 0x11, 0x88, 0x1b, 0xe0, 0x29, 0x89, 0x18, 0xea, + 0x01, 0x07, 0xf6, 0xd0, 0x00, 0x2e, 0xf6, 0xd0, 0xb9, 0x43, 0x29, 0x81, + 0xf3, 0xe7, 0x29, 0x89, 0x28, 0xea, 0x01, 0x07, 0x47, 0x45, 0xec, 0xd1, + 0x03, 0xe0, 0x29, 0x89, 0x38, 0xea, 0x01, 0x07, 0xe7, 0xd0, 0x00, 0x2e, + 0xe7, 0xd0, 0x39, 0x43, 0xef, 0xe7, 0x80, 0xf3, 0x11, 0x88, 0x6f, 0x20, + 0x00, 0x27, 0x20, 0x70, 0x38, 0x46, 0xbd, 0xe8, 0xf0, 0x81, 0xf8, 0xb5, + 0xdf, 0xf8, 0x08, 0x73, 0x06, 0x46, 0x38, 0x78, 0x0c, 0x46, 0x10, 0xb1, + 0x10, 0x20, 0x00, 0xf0, 0xb2, 0xbd, 0x05, 0xf0, 0x0b, 0xfc, 0xb9, 0x69, + 0x0d, 0x00, 0x0c, 0xd0, 0x49, 0x68, 0xb9, 0x61, 0x05, 0x21, 0x29, 0x70, + 0x2e, 0x81, 0x00, 0x21, 0x69, 0x60, 0x06, 0xa1, 0xe9, 0x60, 0x80, 0xf3, + 0x11, 0x88, 0x00, 0x20, 0x02, 0xe0, 0x80, 0xf3, 0x11, 0x88, 0x72, 0x20, + 0xff, 0xe7, 0x20, 0x70, 0x28, 0x46, 0xf2, 0xbd, 0x3f, 0x00, 0x00, 0x00, + 0x2d, 0xe9, 0xf8, 0x4f, 0x86, 0xb0, 0xdf, 0xf8, 0x3c, 0x65, 0x10, 0x9d, + 0x04, 0x46, 0x30, 0x78, 0x8a, 0x46, 0x93, 0x46, 0x08, 0xb1, 0x02, 0x20, + 0x7a, 0xe0, 0x70, 0x78, 0x08, 0xb1, 0x0d, 0x20, 0x76, 0xe0, 0x20, 0x78, + 0x05, 0x28, 0x18, 0xbf, 0x01, 0x20, 0x71, 0xd1, 0x5f, 0xea, 0x0b, 0x60, + 0x46, 0xbf, 0x0b, 0xf0, 0x7f, 0x0b, 0x4f, 0xf0, 0x01, 0x08, 0x4f, 0xf0, + 0x00, 0x08, 0x05, 0xf0, 0xd1, 0xfb, 0xbb, 0xf1, 0x03, 0x0f, 0x81, 0x46, + 0x5f, 0xd8, 0xdf, 0xe8, 0x0b, 0xf0, 0x33, 0x39, 0x02, 0x2a, 0x20, 0x89, + 0x0a, 0xea, 0x00, 0x07, 0x57, 0x45, 0x26, 0xd0, 0x06, 0x98, 0x00, 0x90, + 0x5b, 0x46, 0x52, 0x46, 0x01, 0xa9, 0x20, 0x46, 0x00, 0xf0, 0xae, 0xf8, + 0x00, 0xf0, 0x30, 0xf9, 0xff, 0xf7, 0x34, 0xfe, 0x05, 0xf0, 0xb6, 0xfb, + 0x81, 0x46, 0x30, 0x6a, 0x28, 0x30, 0x47, 0x7a, 0x57, 0xb3, 0x00, 0x21, + 0x41, 0x72, 0x01, 0xa8, 0x00, 0xf0, 0x0b, 0xf9, 0x31, 0x6a, 0x00, 0x20, + 0x81, 0xf8, 0x30, 0x00, 0x00, 0xf0, 0x1c, 0xf9, 0x02, 0x2f, 0x14, 0xbf, + 0x0a, 0x20, 0x0e, 0x20, 0x36, 0xe0, 0x20, 0x89, 0x1a, 0xea, 0x00, 0x07, + 0xd8, 0xd0, 0xb8, 0xf1, 0x00, 0x0f, 0x10, 0xd0, 0xb8, 0x43, 0x0d, 0xe0, + 0x20, 0x89, 0x2a, 0xea, 0x00, 0x07, 0x57, 0x45, 0xce, 0xd1, 0x03, 0xe0, + 0x20, 0x89, 0x3a, 0xea, 0x00, 0x07, 0xc9, 0xd0, 0xb8, 0xf1, 0x00, 0x0f, + 0x01, 0xd0, 0x38, 0x43, 0x20, 0x81, 0x30, 0x6a, 0x07, 0x85, 0x0d, 0xe0, + 0x07, 0x88, 0xb8, 0xf1, 0x00, 0x0f, 0x09, 0xd0, 0xbb, 0xf1, 0x01, 0x0f, + 0x0e, 0xd9, 0xab, 0xf1, 0x02, 0x00, 0x01, 0x28, 0x0d, 0xd8, 0x20, 0x89, + 0xb8, 0x43, 0x20, 0x81, 0x00, 0xf0, 0xec, 0xf8, 0x00, 0x20, 0x28, 0x70, + 0x38, 0x46, 0x07, 0xb0, 0xbd, 0xe8, 0xf0, 0x8f, 0x20, 0x89, 0x38, 0x43, + 0xf3, 0xe7, 0x00, 0xf0, 0xe1, 0xf8, 0x6f, 0x20, 0x28, 0x70, 0x00, 0x20, + 0xf3, 0xe7, 0x00, 0x00, 0x2d, 0xe9, 0xf0, 0x41, 0x04, 0x46, 0x0f, 0x46, + 0x20, 0x78, 0x05, 0x28, 0x16, 0x46, 0x1d, 0x46, 0x18, 0xbf, 0x01, 0x20, + 0x3a, 0xd1, 0x05, 0xf0, 0x59, 0xfb, 0x80, 0x46, 0x16, 0xb1, 0x01, 0x2e, + 0x06, 0xd0, 0x08, 0xe0, 0x20, 0x89, 0xb8, 0x43, 0x20, 0x81, 0x00, 0x27, + 0x66, 0x68, 0x13, 0xe0, 0x20, 0x89, 0x38, 0x43, 0xf8, 0xe7, 0x80, 0xf3, + 0x11, 0x88, 0x71, 0x20, 0x26, 0xe0, 0x30, 0x8a, 0x21, 0x89, 0x01, 0x40, + 0x81, 0x42, 0x06, 0xd1, 0x00, 0x22, 0x30, 0x46, 0x00, 0xf0, 0x7f, 0xf8, + 0x01, 0x28, 0x08, 0xbf, 0x01, 0x27, 0x36, 0x68, 0xde, 0xb1, 0xb0, 0x7c, + 0x03, 0x28, 0x12, 0xd8, 0xdf, 0xe8, 0x00, 0xf0, 0x08, 0x0d, 0x02, 0x03, + 0xe9, 0xe7, 0x20, 0x89, 0x31, 0x8a, 0x01, 0x40, 0xf1, 0xd0, 0xe9, 0xe7, + 0x30, 0x8a, 0x21, 0x89, 0x20, 0xea, 0x01, 0x01, 0xe2, 0xe7, 0x20, 0x89, + 0x31, 0x8a, 0x81, 0x43, 0xf4, 0xe7, 0x00, 0xf0, 0x4e, 0xfa, 0x6f, 0x20, + 0x28, 0x70, 0x00, 0x20, 0x0c, 0xe0, 0x00, 0xf0, 0x48, 0xfa, 0x0f, 0xb1, + 0xff, 0xf7, 0x94, 0xfd, 0x05, 0xf0, 0x16, 0xfb, 0x24, 0x89, 0x80, 0xf3, + 0x11, 0x88, 0x00, 0x20, 0x28, 0x70, 0x20, 0x46, 0xbd, 0xe8, 0xf0, 0x81, + 0x70, 0xb5, 0xdf, 0xf8, 0x78, 0x43, 0x25, 0x6a, 0x95, 0xf8, 0x30, 0x60, + 0x46, 0xf0, 0x20, 0x06, 0x85, 0xf8, 0x30, 0x60, 0x00, 0x25, 0x26, 0x6a, + 0x86, 0xf8, 0x31, 0x50, 0x25, 0x6a, 0x04, 0x9e, 0xee, 0x62, 0x69, 0x62, + 0x0a, 0x82, 0x8b, 0x74, 0x22, 0x6a, 0x8a, 0x60, 0x43, 0x68, 0x0b, 0x60, + 0xc8, 0x60, 0x00, 0x23, 0x4b, 0x60, 0x43, 0x68, 0x03, 0xb1, 0x59, 0x60, + 0x41, 0x60, 0x02, 0xf1, 0x34, 0x00, 0x01, 0x78, 0x43, 0x78, 0x09, 0x19, + 0x0a, 0x7b, 0x9a, 0x43, 0x0a, 0x73, 0x04, 0xd1, 0x21, 0x79, 0x80, 0x78, + 0x21, 0xea, 0x00, 0x00, 0x20, 0x71, 0x70, 0xbd, 0x70, 0xb5, 0x27, 0x4c, + 0x04, 0xf5, 0xea, 0x75, 0x4f, 0xf4, 0xa0, 0x71, 0x28, 0x46, 0xff, 0xf7, + 0x4e, 0xfd, 0x00, 0x20, 0x23, 0xa1, 0x00, 0x26, 0x04, 0xeb, 0x00, 0x12, + 0x02, 0xf5, 0xea, 0x73, 0x40, 0x1c, 0x02, 0xf5, 0xf2, 0x72, 0x13, 0x28, + 0x1e, 0x70, 0x5a, 0x60, 0xd9, 0x60, 0xf3, 0xd3, 0x04, 0xeb, 0x00, 0x10, + 0x00, 0xf5, 0xea, 0x70, 0x06, 0x70, 0x46, 0x60, 0xc1, 0x60, 0xa5, 0x61, + 0x70, 0xbd, 0x10, 0xb5, 0x83, 0x68, 0x28, 0x33, 0x00, 0x24, 0x19, 0x80, + 0x5c, 0x60, 0x5a, 0x72, 0x19, 0x7a, 0x01, 0xf0, 0xdf, 0x01, 0x19, 0x72, + 0x19, 0x7a, 0x61, 0xb9, 0xdf, 0xf8, 0xc0, 0x12, 0x9c, 0x7b, 0x0a, 0x79, + 0x22, 0x43, 0x0a, 0x71, 0x01, 0x24, 0x1a, 0x7b, 0x5b, 0x7b, 0x51, 0x18, + 0x0a, 0x7b, 0x1a, 0x43, 0x0a, 0x73, 0x00, 0xf0, 0x02, 0xf8, 0x20, 0x46, + 0x10, 0xbd, 0x41, 0x68, 0x02, 0x68, 0x21, 0xb9, 0xc1, 0x68, 0x4a, 0x60, + 0x22, 0xb1, 0x00, 0x21, 0x01, 0xe0, 0x0a, 0x60, 0x02, 0xb1, 0x51, 0x60, + 0x80, 0x68, 0x00, 0x21, 0x41, 0x62, 0x70, 0x47, 0x90, 0xf3, 0x00, 0x20, + 0x20, 0xbd, 0x00, 0x20, 0x3f, 0x00, 0x00, 0x00, 0x68, 0x7a, 0x00, 0x20, + 0x48, 0x46, 0x05, 0xf0, 0x8d, 0xba, 0x2d, 0xe9, 0xf0, 0x41, 0xdf, 0xf8, + 0x68, 0x62, 0x04, 0x46, 0x30, 0x78, 0x88, 0x46, 0x08, 0xb1, 0x00, 0x20, + 0x2e, 0xe0, 0x05, 0xf0, 0x7b, 0xfa, 0x71, 0x69, 0x0f, 0x00, 0x1c, 0xbf, + 0x49, 0x68, 0x71, 0x61, 0x05, 0xf0, 0x7a, 0xfa, 0x1f, 0xb3, 0x05, 0xf0, + 0x71, 0xfa, 0xdf, 0xf8, 0xb4, 0x15, 0x0a, 0x68, 0x15, 0x00, 0x16, 0xd0, + 0x12, 0x68, 0x0a, 0x60, 0x80, 0xf3, 0x11, 0x88, 0x6c, 0x60, 0x04, 0xeb, + 0x88, 0x00, 0xa8, 0x60, 0xec, 0x60, 0x2c, 0x61, 0xa5, 0xf8, 0x14, 0x80, + 0x00, 0x20, 0xe8, 0x82, 0x02, 0x20, 0x38, 0x70, 0x00, 0x20, 0x38, 0x81, + 0x7d, 0x60, 0x38, 0x46, 0xff, 0xf7, 0xc7, 0xfc, 0x05, 0xe0, 0x71, 0x69, + 0x79, 0x60, 0x77, 0x61, 0x80, 0xf3, 0x11, 0x88, 0x00, 0x27, 0x38, 0x46, + 0xbd, 0xe8, 0xf0, 0x81, 0x10, 0xb5, 0x04, 0x46, 0x05, 0xf0, 0x48, 0xfa, + 0x61, 0x68, 0x4a, 0x68, 0xca, 0x60, 0x4a, 0x68, 0x0a, 0x61, 0x00, 0x22, + 0xca, 0x82, 0x80, 0xf3, 0x11, 0x88, 0x00, 0x20, 0x10, 0xbd, 0x2d, 0xe9, + 0xf0, 0x41, 0x07, 0x46, 0x0e, 0x46, 0x38, 0x78, 0x02, 0x28, 0x14, 0x46, + 0x18, 0xbf, 0x01, 0x20, 0x07, 0xd1, 0x71, 0x4d, 0x28, 0x78, 0x08, 0xb1, + 0x02, 0x20, 0x02, 0xe0, 0x68, 0x78, 0x18, 0xb1, 0x0d, 0x20, 0x20, 0x70, + 0x00, 0x20, 0x50, 0xe0, 0x05, 0xf0, 0x26, 0xfa, 0x80, 0x46, 0x78, 0x68, + 0xc1, 0x8a, 0x89, 0xb1, 0x02, 0x69, 0x12, 0x1d, 0x02, 0x61, 0x49, 0x1e, + 0x52, 0xf8, 0x04, 0x7d, 0x82, 0x68, 0xc1, 0x82, 0x01, 0x69, 0x91, 0x42, + 0x04, 0xbf, 0x41, 0x68, 0x01, 0x61, 0x00, 0xf0, 0x40, 0xf9, 0x00, 0x20, + 0x20, 0x70, 0x37, 0xe0, 0x28, 0x6a, 0x90, 0xf8, 0x30, 0x10, 0x41, 0xf0, + 0x04, 0x01, 0x80, 0xf8, 0x30, 0x10, 0x00, 0x20, 0x29, 0x6a, 0x81, 0xf8, + 0x31, 0x00, 0x28, 0x6a, 0xc6, 0x62, 0x38, 0x46, 0xff, 0xf7, 0x3e, 0xfc, + 0x00, 0xf0, 0x2b, 0xf9, 0xff, 0xf7, 0x78, 0xfc, 0x05, 0xf0, 0xfa, 0xf9, + 0x06, 0x46, 0x28, 0x6a, 0x00, 0xf1, 0x20, 0x01, 0x4a, 0x7c, 0x12, 0xb1, + 0x02, 0x2a, 0x03, 0xd0, 0x05, 0xe0, 0x0f, 0x68, 0x00, 0x20, 0x07, 0xe0, + 0x00, 0x27, 0x0e, 0x20, 0x04, 0xe0, 0x39, 0x46, 0xff, 0xf7, 0x4a, 0xfc, + 0x00, 0x27, 0x0a, 0x20, 0x20, 0x70, 0x00, 0x20, 0x29, 0x6a, 0x81, 0xf8, + 0x30, 0x00, 0x29, 0x6a, 0x81, 0xf8, 0x31, 0x00, 0x00, 0x21, 0x28, 0x6a, + 0xc1, 0x61, 0x01, 0x62, 0x00, 0xf0, 0x69, 0xf8, 0x38, 0x46, 0xbd, 0xe8, + 0xf0, 0x81, 0x01, 0x20, 0x20, 0x70, 0x00, 0x20, 0x70, 0x47, 0x70, 0xb5, + 0x06, 0x46, 0x0c, 0x46, 0x30, 0x78, 0x02, 0x28, 0x01, 0xd0, 0x01, 0x20, + 0x70, 0xbd, 0x05, 0xf0, 0xc7, 0xf9, 0x05, 0x46, 0xb0, 0x7a, 0x30, 0xb1, + 0x00, 0xf0, 0x46, 0xf8, 0x00, 0xf0, 0x4e, 0xf8, 0xff, 0xf7, 0x3a, 0xfc, + 0x14, 0xe0, 0x70, 0x68, 0xc1, 0x8a, 0x82, 0x8a, 0x91, 0x42, 0x00, 0xd3, + 0x40, 0xe0, 0xc2, 0x68, 0x12, 0x1d, 0xc2, 0x60, 0x49, 0x1c, 0x42, 0xf8, + 0x04, 0x4d, 0xc1, 0x82, 0x82, 0x68, 0xc1, 0x68, 0x91, 0x42, 0x04, 0xbf, + 0x41, 0x68, 0xc1, 0x60, 0x00, 0xf0, 0x36, 0xf8, 0x00, 0x20, 0x70, 0xbd, + 0x70, 0xb5, 0x06, 0x46, 0x0c, 0x46, 0x30, 0x78, 0x02, 0x28, 0x01, 0xd0, + 0x01, 0x20, 0x70, 0xbd, 0x05, 0xf0, 0x9c, 0xf9, 0x05, 0x46, 0xb0, 0x7a, + 0x30, 0xb1, 0x00, 0xf0, 0x1b, 0xf8, 0x00, 0xf0, 0x23, 0xf8, 0xff, 0xf7, + 0x0f, 0xfc, 0x13, 0xe0, 0x70, 0x68, 0xc1, 0x8a, 0x82, 0x8a, 0x91, 0x42, + 0x00, 0xd3, 0x15, 0xe0, 0x02, 0x69, 0x43, 0x68, 0x9a, 0x42, 0x04, 0xbf, + 0x82, 0x68, 0x02, 0x61, 0x02, 0x69, 0x12, 0x1f, 0x02, 0x61, 0x14, 0x60, + 0x49, 0x1c, 0xc1, 0x82, 0x00, 0xf0, 0x0c, 0xf8, 0x00, 0x20, 0x70, 0xbd, + 0x00, 0x23, 0x04, 0x22, 0x21, 0x46, 0x30, 0x46, 0xff, 0xf7, 0x80, 0xbb, + 0x00, 0xf0, 0x02, 0xf8, 0x1e, 0x20, 0x70, 0xbd, 0x28, 0x46, 0x05, 0xf0, + 0x75, 0xb9, 0x30, 0x46, 0x05, 0xf0, 0x72, 0xb9, 0x10, 0xb5, 0xdf, 0xf8, + 0x60, 0x46, 0x4f, 0xf4, 0x90, 0x71, 0x20, 0x46, 0xff, 0xf7, 0xdb, 0xfb, + 0x00, 0x20, 0x18, 0x21, 0x01, 0xfb, 0x00, 0xf2, 0x13, 0x19, 0x18, 0x33, + 0x40, 0x1c, 0x13, 0x51, 0x0b, 0x28, 0xf7, 0xd3, 0x01, 0xfb, 0x00, 0x40, + 0x00, 0x22, 0x02, 0x60, 0xdf, 0xf8, 0x7c, 0x03, 0x04, 0x60, 0x10, 0xbd, + 0x00, 0x00, 0x00, 0x00, 0x20, 0xbd, 0x00, 0x20, 0x70, 0xb5, 0x00, 0xf0, + 0x17, 0xf8, 0x08, 0xb1, 0x00, 0x20, 0x70, 0xbd, 0x05, 0xf0, 0x46, 0xf9, + 0x69, 0x69, 0x0e, 0x00, 0x1c, 0xbf, 0x49, 0x68, 0x69, 0x61, 0x05, 0xf0, + 0x45, 0xf9, 0x3e, 0xb1, 0x03, 0x20, 0x30, 0x70, 0x34, 0x81, 0x00, 0x20, + 0x70, 0x60, 0x30, 0x46, 0xff, 0xf7, 0xa7, 0xfb, 0x30, 0x46, 0x70, 0xbd, + 0xdf, 0xf8, 0x20, 0x57, 0x04, 0x46, 0x28, 0x78, 0x70, 0x47, 0xdf, 0xf8, + 0x84, 0x77, 0x38, 0x78, 0x70, 0x47, 0x01, 0x22, 0x00, 0x21, 0x20, 0x46, + 0xff, 0xf7, 0x30, 0xbb, 0x2d, 0xe9, 0xf0, 0x41, 0x00, 0xf0, 0x52, 0xf8, + 0x18, 0xbf, 0x01, 0x20, 0x12, 0xd1, 0xff, 0xf7, 0xee, 0xff, 0x08, 0xb1, + 0x02, 0x20, 0x0d, 0xe0, 0x78, 0x78, 0x08, 0xb1, 0x0d, 0x20, 0x09, 0xe0, + 0x05, 0xf0, 0x14, 0xf9, 0x80, 0x46, 0x28, 0x89, 0x30, 0xb1, 0x40, 0x1e, + 0x28, 0x81, 0x00, 0xf0, 0x3a, 0xf8, 0x00, 0x20, 0x20, 0x70, 0x34, 0xe0, + 0x38, 0x6a, 0x90, 0xf8, 0x30, 0x10, 0x41, 0xf0, 0x01, 0x01, 0x80, 0xf8, + 0x30, 0x10, 0x00, 0x20, 0x39, 0x6a, 0x81, 0xf8, 0x31, 0x00, 0x38, 0x6a, + 0xc6, 0x62, 0x28, 0x46, 0xff, 0xf7, 0x38, 0xfb, 0x00, 0xf0, 0x25, 0xf8, + 0xff, 0xf7, 0x72, 0xfb, 0x05, 0xf0, 0xf4, 0xf8, 0x06, 0x46, 0x38, 0x6a, + 0x90, 0xf8, 0x31, 0x10, 0x11, 0xb1, 0x02, 0x29, 0x02, 0xd0, 0x03, 0xe0, + 0x00, 0x20, 0x05, 0xe0, 0x0e, 0x20, 0x03, 0xe0, 0x29, 0x46, 0xff, 0xf7, + 0x47, 0xfb, 0x0a, 0x20, 0x20, 0x70, 0x00, 0x20, 0x39, 0x6a, 0x81, 0xf8, + 0x30, 0x00, 0x39, 0x6a, 0x81, 0xf8, 0x31, 0x00, 0x39, 0x6a, 0xc8, 0x61, + 0x30, 0x46, 0xbd, 0xe8, 0xf0, 0x41, 0x05, 0xf0, 0xdb, 0xb8, 0xbd, 0xe8, + 0xf0, 0x81, 0x40, 0x46, 0x05, 0xf0, 0xd6, 0xb8, 0x05, 0x46, 0x0e, 0x46, + 0x28, 0x78, 0x03, 0x28, 0x14, 0x46, 0x70, 0x47, 0x38, 0xb5, 0x04, 0x46, + 0x20, 0x78, 0x03, 0x28, 0x01, 0xd0, 0x01, 0x20, 0x32, 0xbd, 0x05, 0xf0, + 0xc1, 0xf8, 0x05, 0x46, 0xa0, 0x7a, 0x38, 0xb1, 0x00, 0x23, 0xff, 0xf7, + 0x90, 0xff, 0xff, 0xf7, 0x47, 0xff, 0xff, 0xf7, 0x33, 0xfb, 0x08, 0xe0, + 0x20, 0x89, 0x4f, 0xf6, 0xff, 0x71, 0x88, 0x42, 0x05, 0xd0, 0x40, 0x1c, + 0x20, 0x81, 0xff, 0xf7, 0x3b, 0xff, 0x00, 0x20, 0x32, 0xbd, 0xff, 0xf7, + 0x37, 0xff, 0x33, 0x20, 0x32, 0xbd, 0x2d, 0xe9, 0xf1, 0x4f, 0x84, 0xb0, + 0x8b, 0x46, 0x90, 0x46, 0x99, 0x46, 0x05, 0xf0, 0x9f, 0xf8, 0xdf, 0xf8, + 0x64, 0x56, 0x29, 0x78, 0x19, 0xb1, 0x80, 0xf3, 0x11, 0x88, 0x3c, 0x20, + 0x33, 0xe0, 0x05, 0xeb, 0x89, 0x06, 0x31, 0x6b, 0x61, 0xbb, 0x01, 0x21, + 0x31, 0x63, 0x80, 0xf3, 0x11, 0x88, 0xdd, 0xf8, 0x3c, 0xa0, 0x10, 0x9f, + 0x12, 0x9c, 0x22, 0x46, 0x39, 0x46, 0x50, 0x46, 0x00, 0xf0, 0xc6, 0xf8, + 0x04, 0x98, 0x23, 0x46, 0x42, 0x46, 0x59, 0x46, 0x05, 0xf0, 0x1a, 0xf8, + 0x01, 0x46, 0x11, 0x98, 0x02, 0x94, 0x01, 0x90, 0x00, 0x97, 0x52, 0x46, + 0x0e, 0x9b, 0x48, 0x46, 0xff, 0xf7, 0xad, 0xfb, 0x04, 0x00, 0x05, 0xd1, + 0x68, 0x79, 0x01, 0x28, 0x08, 0xd1, 0xff, 0xf7, 0xeb, 0xfa, 0x05, 0xe0, + 0x05, 0xf0, 0x6c, 0xf8, 0x00, 0x21, 0x31, 0x63, 0x80, 0xf3, 0x11, 0x88, + 0x20, 0x46, 0x02, 0xe0, 0x80, 0xf3, 0x11, 0x88, 0x28, 0x20, 0x05, 0xb0, + 0xbd, 0xe8, 0xf0, 0x8f, 0x2d, 0xe9, 0xf0, 0x41, 0xdf, 0xf8, 0x74, 0x45, + 0x06, 0x46, 0x20, 0x78, 0x08, 0xb1, 0x40, 0x20, 0x64, 0xe0, 0x18, 0x2e, + 0x08, 0xbf, 0x3e, 0x20, 0x60, 0xd0, 0x05, 0xf0, 0x51, 0xf8, 0x80, 0x46, + 0xff, 0x2e, 0x04, 0xbf, 0x20, 0x6a, 0x90, 0xf8, 0x32, 0x60, 0x04, 0xeb, + 0x86, 0x05, 0x2e, 0x6b, 0x1e, 0xb9, 0xff, 0xf7, 0x72, 0xff, 0x43, 0x20, + 0x50, 0xe0, 0x01, 0x2e, 0x03, 0xd1, 0xff, 0xf7, 0x6c, 0xff, 0x3d, 0x20, + 0x4a, 0xe0, 0x06, 0xf1, 0x30, 0x07, 0x38, 0x79, 0x7a, 0x79, 0x00, 0x19, + 0x01, 0x7b, 0x91, 0x43, 0x01, 0x73, 0x38, 0x79, 0x00, 0x19, 0x00, 0x7b, + 0x18, 0xb9, 0x20, 0x79, 0xb9, 0x79, 0x88, 0x43, 0x20, 0x71, 0xf1, 0x69, + 0x11, 0xb1, 0x30, 0x46, 0xff, 0xf7, 0x8a, 0xfa, 0x70, 0x6a, 0x08, 0xb1, + 0xff, 0xf7, 0x83, 0xfd, 0x00, 0x20, 0xf0, 0x62, 0x38, 0x70, 0x78, 0x70, + 0x60, 0x78, 0xff, 0x28, 0x1c, 0xbf, 0x40, 0x1c, 0x60, 0x70, 0xff, 0xf7, + 0x46, 0xff, 0x05, 0xf0, 0x17, 0xf8, 0x80, 0x46, 0x60, 0x78, 0x08, 0xb1, + 0x40, 0x1e, 0x60, 0x70, 0x30, 0x46, 0x04, 0xf0, 0xa3, 0xff, 0xa0, 0x79, + 0x40, 0x1e, 0xa0, 0x71, 0x00, 0x20, 0x28, 0x63, 0xb1, 0x69, 0x70, 0x69, + 0x19, 0xb9, 0x81, 0x61, 0x70, 0x69, 0xe0, 0x62, 0x03, 0xe0, 0x48, 0x61, + 0x71, 0x69, 0xb0, 0x69, 0x88, 0x61, 0x60, 0x6a, 0x70, 0x61, 0x66, 0x62, + 0x1c, 0xa0, 0xf8, 0x61, 0xff, 0xf7, 0x25, 0xff, 0x60, 0x79, 0x01, 0x28, + 0x08, 0xbf, 0xff, 0xf7, 0x6f, 0xfa, 0x00, 0x20, 0xbd, 0xe8, 0xf0, 0x81, + 0xf8, 0xb5, 0xdf, 0xf8, 0x04, 0x75, 0x05, 0x46, 0x38, 0x78, 0x0e, 0x46, + 0x14, 0x46, 0x08, 0xb1, 0x12, 0x20, 0x15, 0xe0, 0x04, 0xf0, 0xe4, 0xff, + 0xff, 0x2d, 0x04, 0xbf, 0x39, 0x6a, 0x91, 0xf8, 0x32, 0x50, 0x07, 0xeb, + 0x85, 0x01, 0x09, 0x6b, 0x00, 0x29, 0x18, 0xbf, 0x01, 0x29, 0x03, 0xd1, + 0x04, 0xf0, 0xdc, 0xff, 0x43, 0x20, 0x03, 0xe0, 0xce, 0x64, 0x80, 0xf3, + 0x11, 0x88, 0x00, 0x20, 0x20, 0x70, 0xf1, 0xbd, 0x80, 0xb5, 0xdf, 0xf8, + 0xc0, 0x04, 0x00, 0x6a, 0x04, 0xf0, 0x60, 0xff, 0xbd, 0xe8, 0x02, 0x40, + 0xff, 0x20, 0x63, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, + 0x02, 0xf0, 0x03, 0x02, 0x03, 0x2a, 0x04, 0xd1, 0x00, 0x29, 0x1c, 0xbf, + 0x89, 0x00, 0x05, 0xf0, 0x09, 0xb8, 0x70, 0x47, 0x70, 0xb5, 0xff, 0xf7, + 0x7f, 0xfe, 0x00, 0x28, 0x04, 0xbf, 0x68, 0x78, 0x00, 0x28, 0x16, 0xd1, + 0xac, 0xb1, 0x04, 0xf0, 0xab, 0xff, 0x29, 0x6a, 0x2c, 0x31, 0x0a, 0x7a, + 0x4e, 0x7a, 0x52, 0x19, 0x13, 0x7b, 0xb3, 0x43, 0x13, 0x73, 0x03, 0xd1, + 0x2a, 0x79, 0x8b, 0x7a, 0x9a, 0x43, 0x2a, 0x71, 0x0c, 0x60, 0x80, 0xf3, + 0x11, 0x88, 0xbd, 0xe8, 0x70, 0x40, 0xff, 0xf7, 0x13, 0xba, 0x70, 0xbd, + 0x8c, 0xf3, 0x00, 0x20, 0x10, 0xb5, 0x04, 0xf0, 0x91, 0xff, 0xdf, 0xf8, + 0x50, 0x14, 0x0c, 0x68, 0x80, 0xf3, 0x11, 0x88, 0x20, 0x46, 0x10, 0xbd, + 0xbd, 0xe8, 0x10, 0x40, 0x04, 0xf0, 0x8c, 0xbf, 0x2d, 0xe9, 0xf8, 0x43, + 0x06, 0x46, 0xdf, 0xf8, 0xc0, 0x03, 0x0a, 0x9c, 0x00, 0x78, 0x0f, 0x46, + 0x90, 0x46, 0x99, 0x46, 0x08, 0xb1, 0x8b, 0x20, 0x08, 0xe0, 0xff, 0xf7, + 0xfb, 0xf8, 0xdf, 0xf8, 0x20, 0x04, 0x05, 0x69, 0x2d, 0xb9, 0xff, 0xf7, + 0x0a, 0xf9, 0x86, 0x20, 0x20, 0x70, 0x00, 0x20, 0x20, 0xe0, 0xe9, 0x68, + 0x01, 0x61, 0x00, 0x21, 0xe9, 0x60, 0x29, 0x61, 0x41, 0x88, 0x49, 0x1c, + 0x41, 0x80, 0x01, 0x88, 0x49, 0x1e, 0x01, 0x80, 0x05, 0xf1, 0x24, 0x00, + 0x01, 0x21, 0x41, 0x70, 0x29, 0x1d, 0x4e, 0x61, 0x8f, 0x61, 0x80, 0xf8, + 0x00, 0x80, 0xc1, 0xf8, 0x00, 0x90, 0x08, 0x98, 0x48, 0x60, 0x09, 0x98, + 0x00, 0xb9, 0x8b, 0xa0, 0xc8, 0x61, 0xff, 0xf7, 0xe8, 0xf8, 0x00, 0x20, + 0x20, 0x70, 0x28, 0x46, 0xbd, 0xe8, 0xf2, 0x83, 0x00, 0x00, 0x00, 0x00, + 0x38, 0xb5, 0x00, 0xf0, 0x74, 0xf8, 0x18, 0xbf, 0x89, 0x20, 0x1c, 0xd1, + 0x00, 0xf0, 0x6c, 0xf8, 0x08, 0xb1, 0x8b, 0x20, 0x17, 0xe0, 0xff, 0xf7, + 0xbf, 0xf8, 0x95, 0xf8, 0x25, 0x00, 0x03, 0x28, 0x0e, 0xd8, 0xdf, 0xe8, + 0x00, 0xf0, 0x09, 0x05, 0x05, 0x02, 0x28, 0x46, 0x00, 0xf0, 0x6c, 0xf9, + 0x28, 0x46, 0x00, 0xf0, 0xd9, 0xf8, 0x84, 0xe0, 0xff, 0xf7, 0xc3, 0xf8, + 0x87, 0x20, 0x02, 0xe0, 0xff, 0xf7, 0xbf, 0xf8, 0x8d, 0x20, 0x20, 0x70, + 0x00, 0x20, 0x32, 0xbd, 0x70, 0xb5, 0x00, 0xf0, 0x4e, 0xf8, 0x18, 0xbf, + 0x89, 0x20, 0x2c, 0xd1, 0x00, 0xf0, 0x46, 0xf8, 0x08, 0xb1, 0x8b, 0x20, + 0x27, 0xe0, 0xff, 0xf7, 0x99, 0xf8, 0x05, 0xf1, 0x24, 0x00, 0x41, 0x78, + 0x03, 0x29, 0x1d, 0xd8, 0xdf, 0xe8, 0x01, 0xf0, 0x18, 0x07, 0x13, 0x02, + 0xd2, 0x49, 0x68, 0x69, 0x49, 0x68, 0x46, 0x1a, 0x05, 0xe0, 0x00, 0x78, + 0xae, 0x69, 0x02, 0x28, 0x04, 0xbf, 0x00, 0x2e, 0xee, 0x69, 0xff, 0xf7, + 0x98, 0xf8, 0x00, 0x20, 0x20, 0x70, 0x30, 0x46, 0x70, 0xbd, 0xff, 0xf7, + 0x92, 0xf8, 0x00, 0x20, 0x20, 0x70, 0x70, 0xbd, 0xff, 0xf7, 0x8d, 0xf8, + 0x87, 0x20, 0x02, 0xe0, 0xff, 0xf7, 0x89, 0xf8, 0x8d, 0x20, 0x20, 0x70, + 0x00, 0x20, 0x70, 0xbd, 0x38, 0xb5, 0x00, 0xf0, 0x18, 0xf8, 0x18, 0xbf, + 0x89, 0x20, 0x03, 0xd1, 0x00, 0xf0, 0x10, 0xf8, 0x08, 0xb1, 0x8b, 0x20, + 0xbb, 0xe7, 0xff, 0xf7, 0x63, 0xf8, 0x95, 0xf8, 0x25, 0x50, 0x03, 0x2d, + 0x94, 0xbf, 0x00, 0x20, 0x8d, 0x20, 0x20, 0x70, 0xff, 0xf7, 0x6f, 0xf8, + 0x28, 0x46, 0x32, 0xbd, 0xb3, 0x48, 0x00, 0x78, 0x70, 0x47, 0x05, 0x46, + 0x0c, 0x46, 0x28, 0x78, 0x64, 0x28, 0x70, 0x47, 0x38, 0xb5, 0xff, 0xf7, + 0xf8, 0xff, 0x18, 0xbf, 0x89, 0x20, 0x1d, 0xd1, 0xff, 0xf7, 0xf0, 0xff, + 0x08, 0xb1, 0x8b, 0x20, 0x18, 0xe0, 0xff, 0xf7, 0x43, 0xf8, 0x95, 0xf8, + 0x25, 0x00, 0x03, 0x28, 0x0f, 0xd8, 0xdf, 0xe8, 0x00, 0xf0, 0x0a, 0x05, + 0x05, 0x02, 0x28, 0x46, 0x00, 0xf0, 0xf0, 0xf8, 0x00, 0x21, 0x28, 0x46, + 0x00, 0xf0, 0xca, 0xf8, 0x07, 0xe0, 0xff, 0xf7, 0x46, 0xf8, 0x87, 0x20, + 0x02, 0xe0, 0xff, 0xf7, 0x42, 0xf8, 0x8d, 0x20, 0x81, 0xe7, 0xff, 0xf7, + 0x3e, 0xf8, 0x00, 0x20, 0x20, 0x70, 0x01, 0x20, 0x32, 0xbd, 0x00, 0x00, + 0xf8, 0xb5, 0x05, 0x46, 0x0f, 0x46, 0x28, 0x78, 0x64, 0x28, 0x16, 0x46, + 0x1c, 0x46, 0x18, 0xbf, 0x89, 0x20, 0x3a, 0xd1, 0xff, 0xf7, 0xc0, 0xff, + 0x08, 0xb1, 0x8b, 0x20, 0x35, 0xe0, 0xff, 0xf7, 0x13, 0xf8, 0x95, 0xf8, + 0x25, 0x00, 0x03, 0x28, 0x2c, 0xd8, 0xdf, 0xe8, 0x00, 0xf0, 0x27, 0x21, + 0x21, 0x02, 0x28, 0x46, 0x00, 0xf0, 0xc0, 0xf8, 0x00, 0x20, 0x20, 0x70, + 0xaf, 0xb1, 0x03, 0x2f, 0x02, 0xd0, 0x04, 0x2f, 0x06, 0xd0, 0x0e, 0xe0, + 0x6a, 0x68, 0x10, 0x00, 0x18, 0xbf, 0xa9, 0x68, 0x04, 0xd1, 0x06, 0xe0, + 0x6a, 0x68, 0x10, 0x00, 0x03, 0xd0, 0x31, 0x46, 0x28, 0x46, 0x90, 0x47, + 0x03, 0xe0, 0x8f, 0x20, 0x00, 0xe0, 0x84, 0x20, 0x20, 0x70, 0xff, 0xf7, + 0x02, 0xf8, 0x03, 0xe0, 0xfe, 0xf7, 0xff, 0xff, 0x8e, 0x20, 0x20, 0x70, + 0x01, 0x20, 0xf2, 0xbd, 0xfe, 0xf7, 0xf9, 0xff, 0x87, 0x20, 0x02, 0xe0, + 0xfe, 0xf7, 0xf5, 0xff, 0x8d, 0x20, 0x20, 0x70, 0x00, 0x20, 0xf2, 0xbd, + 0x78, 0x48, 0xc0, 0x68, 0xff, 0xf7, 0x8a, 0xbd, 0x00, 0xf1, 0x24, 0x01, + 0x00, 0x22, 0x4a, 0x70, 0x0a, 0x70, 0x09, 0xa1, 0x01, 0x62, 0xc2, 0x61, + 0x42, 0x61, 0x42, 0x60, 0x82, 0x60, 0x02, 0x61, 0x70, 0x49, 0x0a, 0x69, + 0xc2, 0x60, 0x08, 0x61, 0x48, 0x88, 0x40, 0x1e, 0x48, 0x80, 0x08, 0x88, + 0x40, 0x1c, 0x08, 0x80, 0x70, 0x47, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, + 0x74, 0xec, 0x00, 0x20, 0x70, 0xb5, 0x68, 0x4c, 0x86, 0xb0, 0x4f, 0xf4, + 0x70, 0x71, 0x04, 0xf1, 0x54, 0x00, 0xff, 0xf7, 0xa6, 0xf8, 0x40, 0x21, + 0x04, 0xf1, 0x14, 0x00, 0xff, 0xf7, 0xa1, 0xf8, 0x00, 0x20, 0x5f, 0xa1, + 0x28, 0x22, 0x02, 0xfb, 0x00, 0x43, 0x03, 0xf1, 0x54, 0x05, 0x64, 0x26, + 0x2e, 0x70, 0x40, 0x1c, 0x00, 0x26, 0x7c, 0x33, 0x17, 0x28, 0x85, 0xf8, + 0x25, 0x60, 0xeb, 0x60, 0x29, 0x62, 0xf0, 0xd3, 0x02, 0xfb, 0x00, 0x40, + 0x64, 0x22, 0x00, 0xf8, 0x54, 0x2f, 0x80, 0xf8, 0x25, 0x60, 0xc6, 0x60, + 0x01, 0x62, 0x18, 0x20, 0x20, 0x80, 0x66, 0x60, 0x04, 0xf1, 0x54, 0x00, + 0x20, 0x61, 0x66, 0x80, 0x01, 0x20, 0xff, 0xf7, 0xb7, 0xfc, 0xa0, 0x60, + 0x00, 0x20, 0xff, 0xf7, 0xb3, 0xfc, 0x03, 0x21, 0x04, 0x91, 0xe0, 0x60, + 0x80, 0x21, 0x02, 0x91, 0x4f, 0xf6, 0xfd, 0x71, 0x4a, 0x48, 0x01, 0x90, + 0x00, 0x91, 0x00, 0xf5, 0xfe, 0x72, 0x03, 0x96, 0x02, 0x23, 0x00, 0x21, + 0x0f, 0xf2, 0xa1, 0x00, 0xff, 0xf7, 0x47, 0xfd, 0x05, 0xaa, 0x0f, 0xf2, + 0x14, 0x11, 0x02, 0x20, 0xff, 0xf7, 0xf8, 0xfd, 0x06, 0xb0, 0x70, 0xbd, + 0x10, 0xb5, 0x03, 0x22, 0x80, 0xf8, 0x25, 0x20, 0x01, 0x29, 0x3d, 0x4a, + 0x53, 0x68, 0x1a, 0xbf, 0x81, 0x69, 0x00, 0x29, 0xc1, 0x69, 0x59, 0x18, + 0x41, 0x61, 0x01, 0x7d, 0x01, 0xf0, 0x07, 0x01, 0x02, 0xeb, 0xc1, 0x01, + 0x14, 0x31, 0x8a, 0x88, 0x0b, 0x68, 0x1b, 0xb9, 0x00, 0x22, 0xc2, 0x60, + 0x01, 0x22, 0x02, 0xe0, 0xc3, 0x60, 0x18, 0x61, 0x52, 0x1c, 0x8a, 0x80, + 0x08, 0x60, 0x00, 0x21, 0x01, 0x61, 0x10, 0xbd, 0x10, 0xb5, 0x00, 0xf1, + 0x0c, 0x01, 0x2d, 0x4a, 0x0b, 0x7a, 0x03, 0xf0, 0x07, 0x03, 0x02, 0xeb, + 0xc3, 0x02, 0x52, 0xf8, 0x14, 0x4f, 0x0b, 0x68, 0x84, 0x42, 0x05, 0xd1, + 0x18, 0x00, 0x10, 0x60, 0x06, 0xd0, 0x00, 0x23, 0x03, 0x61, 0x03, 0xe0, + 0x48, 0x68, 0xc3, 0x60, 0x03, 0xb1, 0x18, 0x61, 0x01, 0x20, 0x48, 0x76, + 0x00, 0x20, 0x08, 0x60, 0x48, 0x60, 0x90, 0x88, 0x40, 0x1e, 0x90, 0x80, + 0x10, 0xbd, 0x00, 0x00, 0x20, 0xbd, 0x00, 0x20, 0xf8, 0xb5, 0x1c, 0x4c, + 0x01, 0xe0, 0xfe, 0xf7, 0x34, 0xff, 0xe0, 0x68, 0x6a, 0x46, 0x00, 0x21, + 0xff, 0xf7, 0x70, 0xfc, 0xfe, 0xf7, 0x18, 0xff, 0x60, 0x68, 0x40, 0x1c, + 0x60, 0x60, 0x00, 0xf0, 0x07, 0x00, 0x04, 0xeb, 0xc0, 0x00, 0x45, 0x69, + 0x00, 0x2d, 0x08, 0xe0, 0x02, 0x21, 0x41, 0x70, 0x32, 0x68, 0x10, 0x00, + 0x02, 0xd0, 0x71, 0x68, 0x28, 0x46, 0x90, 0x47, 0x3d, 0x00, 0xe2, 0xd0, + 0x2e, 0x1d, 0x60, 0x68, 0x31, 0x69, 0xb7, 0x68, 0x88, 0x42, 0xf7, 0xd1, + 0x28, 0x46, 0xff, 0xf7, 0xb3, 0xff, 0x05, 0xf1, 0x24, 0x00, 0x01, 0x78, + 0x02, 0x29, 0xe7, 0xd1, 0x01, 0x21, 0x28, 0x46, 0xff, 0xf7, 0x88, 0xff, + 0xe4, 0xe7, 0x00, 0x00, 0x20, 0xbd, 0x00, 0x20, 0x3f, 0x00, 0x00, 0x00, + 0x90, 0xf3, 0x00, 0x20, 0x68, 0xdb, 0x00, 0x20, 0x68, 0x78, 0x00, 0x20, + 0x75, 0x43, 0x2f, 0x4f, 0x53, 0x2d, 0x49, 0x49, 0x20, 0x54, 0x6d, 0x72, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x04, 0xf0, 0xb1, 0xbd, 0xf0, 0xb4, + 0x01, 0x68, 0x44, 0x68, 0x83, 0x68, 0x09, 0x18, 0x01, 0xeb, 0x54, 0x02, + 0xe4, 0x07, 0x48, 0xbf, 0x4b, 0x44, 0x0c, 0x30, 0x91, 0x42, 0x2b, 0xd0, + 0x11, 0xf8, 0x01, 0x4b, 0x14, 0xf0, 0x03, 0x05, 0x04, 0xbf, 0x11, 0xf8, + 0x01, 0x5b, 0xed, 0x1c, 0x26, 0x09, 0x0f, 0x2e, 0x07, 0xd1, 0x11, 0xf8, + 0x01, 0x6b, 0x0f, 0x36, 0x03, 0xe0, 0x11, 0xf8, 0x01, 0x7b, 0x03, 0xf8, + 0x01, 0x7b, 0x6d, 0x1e, 0xf9, 0xd1, 0x00, 0x2e, 0xe6, 0xd0, 0xa4, 0x08, + 0x11, 0xf8, 0x01, 0x5b, 0x04, 0xf0, 0x03, 0x04, 0x03, 0x2c, 0x08, 0xbf, + 0x11, 0xf8, 0x01, 0x4b, 0x05, 0xeb, 0x04, 0x24, 0x1c, 0x1b, 0xb5, 0x1c, + 0xd8, 0xd0, 0x14, 0xf8, 0x01, 0x6b, 0x03, 0xf8, 0x01, 0x6b, 0x6d, 0x1e, + 0xf9, 0xd1, 0xd1, 0xe7, 0xf0, 0xbc, 0x70, 0x47, 0x10, 0xb5, 0xef, 0xf3, + 0x10, 0x82, 0x72, 0xb6, 0x66, 0x4b, 0x4f, 0xf6, 0xfe, 0x64, 0x00, 0xf1, + 0x8c, 0x40, 0x44, 0xe0, 0x30, 0xb5, 0x00, 0xf1, 0x8c, 0x40, 0xef, 0xf3, + 0x10, 0x83, 0x72, 0xb6, 0x60, 0x4c, 0x4f, 0xf6, 0xfe, 0x65, 0x25, 0x60, + 0x05, 0x78, 0x8d, 0x43, 0x11, 0x40, 0x29, 0x43, 0x01, 0x70, 0x00, 0x20, + 0x20, 0x60, 0x83, 0xf3, 0x10, 0x88, 0x30, 0xbd, 0xf0, 0xb5, 0x00, 0xf0, + 0x23, 0xf8, 0x0b, 0xe0, 0x72, 0xb6, 0x4f, 0xf6, 0xfe, 0x66, 0x2e, 0x60, + 0x30, 0xf8, 0x14, 0x70, 0x66, 0x5c, 0x07, 0xf1, 0x8c, 0x47, 0x3e, 0x70, + 0x00, 0xf0, 0x10, 0xf8, 0x94, 0x42, 0xf1, 0xd3, 0xf0, 0xbd, 0x10, 0xb5, + 0x00, 0x23, 0x06, 0xe0, 0x30, 0xf8, 0x13, 0x40, 0x04, 0xf1, 0x8c, 0x44, + 0x24, 0x78, 0x5c, 0x54, 0x5b, 0x1c, 0x93, 0x42, 0xf6, 0xd3, 0x10, 0xbd, + 0x00, 0x26, 0x2e, 0x60, 0x83, 0xf3, 0x10, 0x88, 0x64, 0x1c, 0x70, 0x47, + 0xef, 0xf3, 0x10, 0x83, 0x00, 0x24, 0x45, 0x4d, 0x70, 0x47, 0x10, 0xb5, + 0x00, 0xf0, 0x0a, 0xf8, 0x1c, 0x60, 0x01, 0x60, 0x01, 0xe0, 0x1c, 0x60, + 0x01, 0x70, 0x00, 0x20, 0x18, 0x60, 0x82, 0xf3, 0x10, 0x88, 0x10, 0xbd, + 0xef, 0xf3, 0x10, 0x82, 0x72, 0xb6, 0x3c, 0x4b, 0x3c, 0x4c, 0x70, 0x47, + 0x3c, 0x49, 0x09, 0x78, 0x01, 0xf0, 0x07, 0x02, 0x06, 0x2a, 0x02, 0xbf, + 0xc1, 0xf3, 0xc2, 0x01, 0x01, 0x40, 0x81, 0x42, 0x0c, 0xbf, 0x01, 0x20, + 0x00, 0x20, 0x70, 0x47, 0x35, 0x49, 0x09, 0x78, 0x01, 0xf0, 0x07, 0x02, + 0x06, 0x2a, 0x03, 0xbf, 0x00, 0xea, 0x91, 0x11, 0x81, 0x42, 0x01, 0x20, + 0x00, 0x20, 0x70, 0x47, 0x1c, 0xb5, 0x0f, 0xf2, 0xcc, 0x02, 0x18, 0xca, + 0x69, 0x46, 0x03, 0x28, 0x18, 0xc1, 0x01, 0xd3, 0x00, 0x20, 0x16, 0xbd, + 0x00, 0xf0, 0x03, 0x00, 0x3d, 0xf8, 0x10, 0x00, 0x00, 0xf1, 0x8c, 0x41, + 0x00, 0x22, 0x08, 0x78, 0x01, 0xe0, 0x00, 0x22, 0x18, 0x46, 0x0b, 0x78, + 0x83, 0x42, 0xfa, 0xd1, 0x52, 0x1c, 0x05, 0x2a, 0xf9, 0xd3, 0x16, 0xbd, + 0x38, 0xb5, 0x04, 0x46, 0x00, 0x22, 0x04, 0x21, 0x40, 0xf2, 0x16, 0x50, + 0xff, 0xf7, 0x70, 0xff, 0x1e, 0x4d, 0x0c, 0xb9, 0x28, 0x78, 0x32, 0xbd, + 0x01, 0x2c, 0x01, 0xd1, 0x28, 0x79, 0x32, 0xbd, 0xa0, 0x1e, 0xc2, 0x00, + 0xd2, 0xb2, 0x18, 0x21, 0x40, 0xf2, 0x17, 0x50, 0xff, 0xf7, 0x60, 0xff, + 0x28, 0x7a, 0x32, 0xbd, 0x80, 0xb5, 0xff, 0xf7, 0xe3, 0xff, 0x0f, 0xf2, + 0x64, 0x01, 0x40, 0x56, 0x02, 0xbd, 0x38, 0xb5, 0x02, 0x00, 0x0c, 0x46, + 0x10, 0x4d, 0x40, 0xf2, 0x16, 0x50, 0x07, 0xd1, 0x0c, 0x22, 0x1c, 0x21, + 0xff, 0xf7, 0x4c, 0xff, 0x00, 0xf0, 0x1a, 0xf8, 0x28, 0x78, 0x0a, 0xe0, + 0x01, 0x2a, 0x07, 0xd1, 0x14, 0x22, 0x1c, 0x21, 0xff, 0xf7, 0x42, 0xff, + 0x00, 0xf0, 0x10, 0xf8, 0x28, 0x79, 0x00, 0xe0, 0x00, 0x20, 0x0f, 0xf2, + 0x28, 0x01, 0x40, 0x56, 0x32, 0xbd, 0x00, 0x00, 0x48, 0x00, 0x00, 0x50, + 0x00, 0x00, 0xab, 0xab, 0xb3, 0x01, 0x00, 0x46, 0x0b, 0x05, 0x00, 0x46, + 0x21, 0x46, 0x4f, 0xf4, 0xa0, 0x60, 0x21, 0xe7, 0xb0, 0x04, 0xb3, 0x04, + 0xb6, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfd, 0xfd, 0xfd, + 0xfd, 0xfd, 0xfc, 0xfc, 0xfc, 0xfc, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfa, + 0xfa, 0xfa, 0xf9, 0xf9, 0xf9, 0xf9, 0xf8, 0xf8, 0xf7, 0xf7, 0xf7, 0xf6, + 0xf6, 0xf5, 0xf5, 0xf4, 0xf4, 0xf3, 0xf3, 0xf2, 0xf1, 0xf1, 0xf0, 0xef, + 0xee, 0xed, 0xeb, 0xea, 0xe8, 0xe5, 0xe2, 0xdc, 0x10, 0xb5, 0x01, 0x20, + 0x04, 0xf0, 0x13, 0xfe, 0x79, 0x4c, 0x18, 0x21, 0x04, 0xf1, 0x14, 0x00, + 0xff, 0xf7, 0xb6, 0xfe, 0x01, 0x22, 0x02, 0x21, 0x20, 0x1d, 0x04, 0xf0, + 0x61, 0xfc, 0xa0, 0x1c, 0x00, 0x21, 0x01, 0x80, 0x0e, 0x20, 0x04, 0xf0, + 0x56, 0xfe, 0x00, 0x22, 0x80, 0x21, 0x40, 0xf6, 0x6e, 0x10, 0xff, 0xf7, + 0xed, 0xfe, 0x6f, 0x48, 0x4f, 0xf0, 0x40, 0x71, 0xc1, 0x62, 0x01, 0x60, + 0x0e, 0x20, 0x06, 0x21, 0x04, 0xf0, 0x53, 0xfe, 0x0e, 0x20, 0x04, 0xf0, + 0x35, 0xfe, 0xbd, 0xe8, 0x10, 0x40, 0x19, 0xe0, 0x03, 0x28, 0x00, 0xdb, + 0x70, 0x47, 0x30, 0xb5, 0x02, 0x29, 0x0b, 0xda, 0x63, 0x4c, 0x01, 0xeb, + 0x41, 0x05, 0x2d, 0x19, 0x45, 0x19, 0x2a, 0x72, 0x0c, 0x22, 0x02, 0xfb, + 0x01, 0x41, 0x01, 0xeb, 0x80, 0x00, 0x43, 0x61, 0x30, 0xbd, 0x00, 0x23, + 0x00, 0x22, 0xe9, 0xe7, 0x0e, 0x20, 0x04, 0xf0, 0x28, 0xbe, 0x00, 0xbf, + 0x0e, 0x20, 0x04, 0xf0, 0x1b, 0xbe, 0x70, 0xb5, 0x04, 0x46, 0x57, 0x4d, + 0x66, 0x19, 0xb0, 0x78, 0x70, 0xb9, 0x01, 0x20, 0xa0, 0x40, 0xff, 0xf7, + 0x17, 0xff, 0x48, 0xb1, 0x05, 0xeb, 0x44, 0x00, 0x00, 0xf1, 0x10, 0x01, + 0x32, 0x46, 0x20, 0x46, 0x04, 0xf0, 0x84, 0xf8, 0x01, 0x20, 0xb0, 0x70, + 0x70, 0xbd, 0x10, 0xb5, 0x04, 0x46, 0xff, 0xf7, 0xe6, 0xff, 0x4b, 0x48, + 0x00, 0xeb, 0x44, 0x00, 0x00, 0x8a, 0x10, 0xbd, 0x10, 0xb5, 0x04, 0x46, + 0xff, 0xf7, 0xdd, 0xff, 0x46, 0x48, 0x20, 0x5c, 0x10, 0xbd, 0x2d, 0xe9, + 0xf8, 0x4f, 0x00, 0x20, 0x00, 0x90, 0x00, 0x27, 0x42, 0x4c, 0xe8, 0x46, + 0x0d, 0xf1, 0x02, 0x06, 0x00, 0xe0, 0x0f, 0xb9, 0x1b, 0x20, 0x00, 0xe0, + 0x1c, 0x20, 0x04, 0xf0, 0x5e, 0xfe, 0x0f, 0xf2, 0x04, 0x10, 0x3e, 0x49, + 0x50, 0xf8, 0x27, 0x00, 0x08, 0x60, 0x01, 0x20, 0xb8, 0x40, 0xff, 0xf7, + 0xe1, 0xfe, 0x10, 0xb3, 0x04, 0xeb, 0x47, 0x0a, 0x17, 0xf8, 0x04, 0x90, + 0xba, 0xf8, 0x10, 0xb0, 0x3d, 0x19, 0x2a, 0x46, 0x0a, 0xf1, 0x10, 0x01, + 0x38, 0x46, 0x04, 0xf0, 0x49, 0xf8, 0xa8, 0x78, 0x10, 0xb9, 0x01, 0x20, + 0xb8, 0x55, 0x09, 0xe0, 0xba, 0xf8, 0x10, 0x00, 0x58, 0x45, 0x14, 0xbf, + 0x01, 0x20, 0x00, 0x20, 0xb8, 0x55, 0x38, 0x5d, 0x48, 0x45, 0x01, 0xd0, + 0x01, 0x20, 0x00, 0xe0, 0x00, 0x20, 0x07, 0xf8, 0x08, 0x00, 0x01, 0x20, + 0xa8, 0x70, 0x7f, 0x1c, 0x02, 0x2f, 0xc8, 0xd3, 0x00, 0x27, 0x38, 0x19, + 0x00, 0x79, 0x00, 0xb3, 0x00, 0x25, 0x17, 0xf8, 0x08, 0x00, 0x48, 0xb9, + 0xb8, 0x5d, 0xb8, 0xb1, 0x04, 0xf1, 0x08, 0x00, 0x07, 0xeb, 0x47, 0x01, + 0x08, 0x18, 0x28, 0x5c, 0x01, 0x28, 0x0f, 0xd1, 0x04, 0xf1, 0x14, 0x00, + 0x0c, 0x21, 0x01, 0xfb, 0x07, 0x00, 0x50, 0xf8, 0x25, 0x30, 0x18, 0x00, + 0x06, 0xd0, 0x04, 0xf1, 0x10, 0x00, 0x30, 0xf8, 0x17, 0x10, 0x3a, 0x5d, + 0xf8, 0xb2, 0x98, 0x47, 0x6d, 0x1c, 0x03, 0x2d, 0xdf, 0xd3, 0x7f, 0x1c, + 0x02, 0x2f, 0xd8, 0xd3, 0xbd, 0xe8, 0xf1, 0x8f, 0x12, 0x48, 0x4f, 0xf4, + 0x40, 0x51, 0x01, 0x60, 0xc1, 0x68, 0x41, 0xf4, 0x40, 0x51, 0xc1, 0x60, + 0x70, 0x47, 0x00, 0x28, 0x0c, 0xbf, 0x4f, 0xf4, 0x00, 0x50, 0x4f, 0xf4, + 0x80, 0x50, 0x0b, 0x4a, 0x01, 0x29, 0x0c, 0xbf, 0x11, 0x68, 0x51, 0x68, + 0x08, 0x40, 0x70, 0x47, 0x00, 0x28, 0x07, 0x49, 0x0c, 0xbf, 0x4f, 0xf4, + 0x00, 0x50, 0x4f, 0xf4, 0x80, 0x50, 0x08, 0x60, 0x70, 0x47, 0x00, 0x00, + 0x3c, 0xee, 0x00, 0x20, 0x14, 0x00, 0x00, 0x50, 0x40, 0x00, 0x00, 0x50, + 0x40, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, + 0xd2, 0xb2, 0x20, 0x3a, 0x22, 0xbf, 0x21, 0xfa, 0x02, 0xf0, 0x00, 0x21, + 0x70, 0x47, 0x20, 0x32, 0xd1, 0x41, 0xd0, 0x40, 0x48, 0x40, 0x91, 0x40, + 0xd1, 0x40, 0x48, 0x40, 0x70, 0x47, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, + 0x10, 0xb5, 0x04, 0x46, 0x18, 0x22, 0x63, 0x00, 0x01, 0x20, 0x00, 0x21, + 0x9a, 0x40, 0x03, 0xf0, 0x17, 0xff, 0x02, 0x46, 0x04, 0xf1, 0x18, 0x00, + 0x0b, 0x46, 0x40, 0x00, 0x04, 0xf0, 0x52, 0xfe, 0xc0, 0xb2, 0x10, 0xbd, + 0x38, 0xb5, 0xdf, 0xf8, 0x00, 0x4d, 0x25, 0x68, 0x00, 0xf0, 0x6b, 0xfb, + 0x05, 0x28, 0x04, 0xbf, 0x28, 0x0c, 0x60, 0xf3, 0x82, 0x05, 0x00, 0xf0, + 0x78, 0xfb, 0x06, 0x28, 0x04, 0xbf, 0x68, 0x0c, 0x60, 0xf3, 0xc3, 0x05, + 0x65, 0x60, 0x31, 0xbd, 0x38, 0xb5, 0x04, 0x46, 0x0d, 0x00, 0x14, 0xbf, + 0x01, 0x20, 0x00, 0x20, 0x04, 0xf0, 0xd3, 0xfc, 0x68, 0x68, 0x00, 0xf0, + 0xc5, 0xfa, 0xdf, 0xf8, 0x30, 0x0d, 0x00, 0xeb, 0x84, 0x00, 0x45, 0x60, + 0xfe, 0xf7, 0x50, 0xfc, 0x01, 0x21, 0x28, 0x46, 0x00, 0xf0, 0x38, 0xfe, + 0x88, 0xe1, 0xf0, 0xb5, 0x83, 0xb0, 0x0c, 0x46, 0xef, 0xf3, 0x05, 0x80, + 0x08, 0xb1, 0x00, 0xf0, 0xbb, 0xfe, 0x00, 0xf0, 0xaf, 0xfe, 0x06, 0x46, + 0x00, 0xf0, 0x64, 0xfa, 0x05, 0x00, 0x14, 0xbf, 0x01, 0x20, 0x00, 0x20, + 0x04, 0xf0, 0xb1, 0xfc, 0x05, 0xf1, 0x1c, 0x07, 0x30, 0x02, 0x40, 0xf0, + 0x02, 0x00, 0x38, 0x60, 0x07, 0x20, 0x04, 0xf0, 0x6c, 0xfd, 0x68, 0x68, + 0xdf, 0xf8, 0xdc, 0x6c, 0x01, 0xab, 0x00, 0x22, 0x17, 0x21, 0xfe, 0xf7, + 0x3d, 0xff, 0x30, 0x68, 0x39, 0x46, 0xff, 0xf7, 0xce, 0xf8, 0x8d, 0xf8, + 0x04, 0x00, 0x40, 0x1e, 0x00, 0xf0, 0x45, 0xfc, 0x0d, 0xf1, 0x05, 0x00, + 0x00, 0x90, 0x23, 0x46, 0x68, 0x68, 0x82, 0x22, 0x02, 0x21, 0xfe, 0xf7, + 0x9f, 0xfe, 0x9d, 0xf8, 0x05, 0x10, 0x00, 0xf0, 0x37, 0xfc, 0x02, 0x20, + 0x04, 0xf0, 0x54, 0xfe, 0xef, 0xf3, 0x11, 0x84, 0x60, 0x20, 0x80, 0xf3, + 0x11, 0x88, 0xdf, 0xf8, 0xa8, 0x7c, 0xdf, 0xf8, 0xa8, 0x1c, 0x3d, 0x68, + 0x4f, 0xf0, 0x00, 0x40, 0x08, 0x60, 0x04, 0xf0, 0xd9, 0xfe, 0x03, 0x28, + 0x04, 0xbf, 0x96, 0xf8, 0x54, 0x03, 0x03, 0x28, 0x03, 0xd1, 0xdf, 0xf8, + 0xbc, 0x1c, 0x01, 0x20, 0x08, 0x70, 0x05, 0xf0, 0x00, 0x40, 0x38, 0x60, + 0x84, 0xf3, 0x11, 0x88, 0x00, 0x20, 0xfe, 0xbd, 0x38, 0xb5, 0xef, 0xf3, + 0x05, 0x80, 0x08, 0xb1, 0x00, 0xf0, 0x60, 0xfe, 0x00, 0xf0, 0x54, 0xfe, + 0x00, 0xf0, 0x09, 0xfa, 0x05, 0x00, 0x14, 0xbf, 0x01, 0x20, 0x00, 0x20, + 0x04, 0xf0, 0x57, 0xfc, 0x20, 0x02, 0x40, 0xf0, 0x03, 0x00, 0x45, 0xf8, + 0x1c, 0x0f, 0x00, 0x21, 0x08, 0x20, 0x04, 0xf0, 0x22, 0xfd, 0xdf, 0xf8, + 0x2c, 0x0c, 0x00, 0x68, 0x29, 0x46, 0xff, 0xf7, 0x7a, 0xf8, 0x40, 0x1e, + 0x00, 0xf0, 0xf3, 0xfb, 0x00, 0x20, 0x32, 0xbd, 0x70, 0xb5, 0x0c, 0x46, + 0xef, 0xf3, 0x05, 0x80, 0x08, 0xb1, 0x00, 0xf0, 0x3b, 0xfe, 0x00, 0xf0, + 0x2f, 0xfe, 0x05, 0x46, 0x00, 0xf0, 0xe4, 0xf9, 0x06, 0x00, 0x14, 0xbf, + 0x01, 0x20, 0x00, 0x20, 0x04, 0xf0, 0x31, 0xfc, 0x06, 0xf1, 0x1c, 0x01, + 0x44, 0xea, 0x05, 0x20, 0x08, 0x60, 0xdf, 0xf8, 0xe8, 0x0b, 0x00, 0x68, + 0xff, 0xf7, 0x59, 0xf8, 0x40, 0x1e, 0x00, 0xf0, 0xd2, 0xfb, 0x00, 0x20, + 0x70, 0xbd, 0x10, 0xb5, 0x04, 0x46, 0x03, 0x20, 0x04, 0xf0, 0xe1, 0xfc, + 0x20, 0x46, 0xbd, 0xe8, 0x10, 0x40, 0x04, 0x21, 0xd4, 0xe7, 0x10, 0xb5, + 0x04, 0x46, 0x20, 0x68, 0xc0, 0xb2, 0x81, 0x42, 0x0c, 0xbf, 0x01, 0x20, + 0x00, 0x20, 0x04, 0xf0, 0x0e, 0xfc, 0xdf, 0xf8, 0xac, 0x0b, 0x00, 0x68, + 0x21, 0x46, 0xff, 0xf7, 0x65, 0xf8, 0x40, 0x1e, 0x00, 0xf0, 0xb3, 0xfb, + 0x00, 0x20, 0x10, 0xbd, 0xdf, 0xf8, 0x94, 0x1b, 0x91, 0xf8, 0x60, 0x23, + 0x0a, 0xb1, 0x00, 0x20, 0x70, 0x47, 0x01, 0x22, 0x81, 0xf8, 0x60, 0x23, + 0x00, 0x21, 0xde, 0xe7, 0x01, 0x21, 0xdc, 0xe7, 0x10, 0xb5, 0x04, 0x46, + 0x17, 0x20, 0x04, 0xf0, 0xb4, 0xfc, 0x20, 0x46, 0xbd, 0xe8, 0x10, 0x40, + 0x08, 0x21, 0xd2, 0xe7, 0x70, 0xb5, 0x04, 0x46, 0x0d, 0x46, 0x82, 0xb0, + 0x21, 0x46, 0x09, 0x20, 0x04, 0xf0, 0xc6, 0xfc, 0x01, 0x21, 0x08, 0x20, + 0x04, 0xf0, 0xb3, 0xfc, 0xe0, 0xb2, 0x00, 0xf0, 0xcb, 0xfd, 0x06, 0x46, + 0x03, 0x20, 0x30, 0x76, 0x0c, 0xb1, 0xc5, 0xf3, 0x02, 0x10, 0xdf, 0xf8, + 0x3c, 0x5b, 0x85, 0xf8, 0x54, 0x03, 0x02, 0x20, 0x04, 0xf0, 0x7e, 0xfd, + 0x70, 0x68, 0x6b, 0x46, 0x01, 0x22, 0x02, 0x21, 0xfe, 0xf7, 0x66, 0xfe, + 0x05, 0xf1, 0x4c, 0x00, 0x01, 0x21, 0x81, 0x72, 0x04, 0x80, 0x00, 0x21, + 0xc1, 0x72, 0x00, 0xf0, 0x6b, 0xfb, 0x00, 0x20, 0x76, 0xbd, 0x70, 0xb5, + 0x04, 0x46, 0xdf, 0xf8, 0x08, 0x5b, 0x60, 0x88, 0x1c, 0x21, 0x01, 0xfb, + 0x00, 0x50, 0x00, 0x2c, 0x90, 0xf8, 0x40, 0x61, 0x14, 0xbf, 0x01, 0x20, + 0x00, 0x20, 0x04, 0xf0, 0xae, 0xfb, 0x00, 0x20, 0x20, 0x63, 0x00, 0x2e, + 0x0c, 0xbf, 0x05, 0xf5, 0x4b, 0x70, 0x05, 0xf5, 0x4c, 0x70, 0x01, 0x68, + 0x11, 0xb9, 0x04, 0x60, 0x70, 0xbd, 0x01, 0x46, 0x08, 0x6b, 0x00, 0x28, + 0xfb, 0xd1, 0x0c, 0x63, 0x70, 0xbd, 0x10, 0xb5, 0x04, 0x46, 0xfe, 0xf7, + 0x1f, 0xfb, 0xdf, 0xf8, 0xc0, 0x0a, 0x00, 0xf5, 0x4b, 0x71, 0x00, 0x2c, + 0x0c, 0xbf, 0x09, 0x68, 0x49, 0x68, 0x71, 0xb1, 0x89, 0x78, 0x1c, 0x22, + 0x02, 0xfb, 0x01, 0x04, 0x94, 0xf8, 0x30, 0x01, 0x03, 0x28, 0x06, 0xd1, + 0x84, 0xf8, 0x30, 0x01, 0xfe, 0xf7, 0x1f, 0xfb, 0x04, 0xf5, 0x98, 0x70, + 0x10, 0xbd, 0xc9, 0xe0, 0x70, 0xb5, 0x04, 0x00, 0x14, 0xbf, 0x01, 0x26, + 0x00, 0x26, 0x30, 0x46, 0x04, 0xf0, 0x77, 0xfb, 0x30, 0x46, 0x04, 0xf0, + 0x74, 0xfb, 0x61, 0x88, 0xdf, 0xf8, 0x74, 0x0a, 0x1c, 0x22, 0x02, 0xfb, + 0x01, 0x01, 0x91, 0xf8, 0x40, 0x11, 0x00, 0x29, 0x0c, 0xbf, 0x00, 0xf5, + 0x4b, 0x70, 0x00, 0xf5, 0x4c, 0x70, 0x01, 0x68, 0xa1, 0x42, 0x06, 0xd1, + 0x09, 0x6b, 0x01, 0x60, 0x00, 0x20, 0x20, 0x63, 0x70, 0xbd, 0x0d, 0x46, + 0x09, 0x6b, 0x00, 0x29, 0x18, 0xbf, 0xa1, 0x42, 0xf9, 0xd1, 0xa1, 0x42, + 0x03, 0xd1, 0x08, 0x6b, 0x28, 0x63, 0x00, 0x20, 0x08, 0x63, 0x70, 0xbd, + 0x38, 0xb5, 0xdf, 0xf8, 0x30, 0x1a, 0x1c, 0x22, 0x02, 0xfb, 0x00, 0x11, + 0x01, 0xf5, 0x98, 0x74, 0x00, 0xf0, 0xf4, 0xf8, 0x05, 0x46, 0xfe, 0xf7, + 0xcb, 0xfa, 0x20, 0x78, 0x01, 0x28, 0x1c, 0xbf, 0x03, 0x28, 0x02, 0x28, + 0x02, 0xd1, 0x28, 0x46, 0xff, 0xf7, 0xbc, 0xff, 0xbd, 0xe8, 0x31, 0x40, + 0xfe, 0xf7, 0xd3, 0xba, 0x10, 0xb5, 0x82, 0xb0, 0x04, 0x46, 0xfe, 0xf7, + 0xb9, 0xfa, 0x00, 0xf0, 0xa4, 0xf8, 0x0c, 0xbf, 0x4c, 0x68, 0x8c, 0x68, + 0xac, 0xb1, 0xa2, 0x78, 0x1c, 0x23, 0x03, 0xfb, 0x02, 0x00, 0x90, 0xf8, + 0x30, 0x21, 0x03, 0x2a, 0x00, 0xd0, 0x8c, 0xe0, 0x4f, 0xf0, 0xff, 0x32, + 0x0a, 0x60, 0x04, 0x21, 0x80, 0xf8, 0x30, 0x11, 0x20, 0x46, 0xff, 0xf7, + 0x9b, 0xff, 0x00, 0xf0, 0x86, 0xf8, 0x00, 0xf0, 0xc1, 0xfa, 0xfe, 0xf7, + 0xb0, 0xfa, 0x00, 0x20, 0x16, 0xbd, 0x2d, 0xe9, 0xf0, 0x43, 0x83, 0xb0, + 0x88, 0x46, 0x14, 0x46, 0xef, 0xf3, 0x05, 0x80, 0x08, 0xb1, 0x00, 0xf0, + 0x07, 0xfd, 0xfe, 0xf7, 0x8d, 0xfa, 0x00, 0xf0, 0xf9, 0xfc, 0xc7, 0xb2, + 0x38, 0x46, 0x00, 0xf0, 0xef, 0xfc, 0x05, 0x46, 0xdf, 0xf8, 0x8c, 0x99, + 0x1c, 0x20, 0x00, 0xfb, 0x07, 0x90, 0x00, 0xf5, 0x98, 0x76, 0x01, 0x20, + 0x30, 0x70, 0x39, 0x46, 0x0a, 0x20, 0x04, 0xf0, 0xd5, 0xfb, 0x28, 0x46, + 0xff, 0xf7, 0x31, 0xff, 0x38, 0x02, 0x40, 0xf0, 0x07, 0x00, 0x70, 0x61, + 0x06, 0xf1, 0x14, 0x01, 0xdf, 0xf8, 0x98, 0x0c, 0x00, 0x68, 0xfe, 0xf7, + 0x16, 0xff, 0x40, 0x1e, 0x00, 0xf0, 0x8f, 0xfa, 0xfe, 0xf7, 0x7b, 0xfa, + 0x01, 0xa8, 0x00, 0x90, 0x43, 0x46, 0x68, 0x68, 0x83, 0x22, 0x10, 0x21, + 0xfe, 0xf7, 0xe8, 0xfc, 0x9d, 0xf8, 0x04, 0x10, 0x00, 0xf0, 0x80, 0xfa, + 0x03, 0x20, 0x04, 0xf0, 0x9d, 0xfc, 0x09, 0xf6, 0x6c, 0x40, 0x20, 0x60, + 0x00, 0x20, 0xbd, 0xe8, 0xfe, 0x83, 0x10, 0xb5, 0xef, 0xf3, 0x05, 0x80, + 0x08, 0xb1, 0x00, 0xf0, 0xc3, 0xfc, 0xfe, 0xf7, 0x49, 0xfa, 0x00, 0xf0, + 0xb5, 0xfc, 0x00, 0xf0, 0x6a, 0xf8, 0xdf, 0xf8, 0x0c, 0x19, 0xe4, 0xb2, + 0x1c, 0x22, 0x02, 0xfb, 0x04, 0x11, 0x00, 0x20, 0x81, 0xf8, 0x30, 0x01, + 0xfe, 0xf7, 0x4f, 0xfa, 0x00, 0x20, 0x10, 0xbd, 0x10, 0xb5, 0x82, 0xb0, + 0x04, 0x46, 0xfe, 0xf7, 0x33, 0xfa, 0x00, 0xf0, 0x1e, 0xf8, 0x0c, 0xbf, + 0x4c, 0x68, 0x8c, 0x68, 0x7c, 0xb1, 0xa2, 0x78, 0x0a, 0x60, 0x1c, 0x23, + 0x03, 0xfb, 0x02, 0x00, 0x02, 0x21, 0x80, 0xf8, 0x30, 0x11, 0x03, 0x20, + 0x04, 0xf0, 0x4a, 0xfc, 0x00, 0xf0, 0x07, 0xf8, 0x00, 0xf0, 0x42, 0xfa, + 0x7f, 0xe7, 0xfe, 0xf7, 0x30, 0xfa, 0x01, 0x20, 0x16, 0xbd, 0x60, 0x68, + 0x6b, 0x46, 0x01, 0x22, 0x10, 0x21, 0xfe, 0xf7, 0x29, 0xbd, 0xdf, 0xf8, + 0xa8, 0x08, 0x00, 0xf5, 0x4a, 0x71, 0x00, 0x2c, 0x70, 0x47, 0x2d, 0xe9, + 0xfc, 0x41, 0x04, 0x46, 0x88, 0x46, 0x16, 0x46, 0xef, 0xf3, 0x05, 0x80, + 0x08, 0xb1, 0x00, 0xf0, 0x7b, 0xfc, 0xfe, 0xf7, 0x01, 0xfa, 0x00, 0xf0, + 0x6d, 0xfc, 0x05, 0x46, 0x00, 0xf0, 0x22, 0xf8, 0x07, 0x46, 0xdf, 0xf8, + 0x78, 0x08, 0xed, 0xb2, 0x1c, 0x21, 0x01, 0xfb, 0x05, 0x01, 0x01, 0xf5, + 0x98, 0x71, 0x03, 0x22, 0x00, 0xf6, 0x6c, 0x40, 0x0a, 0x70, 0x48, 0x60, + 0xce, 0x60, 0x0c, 0x74, 0xfe, 0xf7, 0xff, 0xf9, 0x01, 0xa8, 0x00, 0x90, + 0x43, 0x46, 0x78, 0x68, 0x83, 0x22, 0x10, 0x21, 0xfe, 0xf7, 0x6c, 0xfc, + 0x9d, 0xf8, 0x04, 0x10, 0x00, 0xf0, 0x04, 0xfa, 0x00, 0x20, 0xbd, 0xe8, + 0xf6, 0x81, 0x04, 0x46, 0xc0, 0xb2, 0x00, 0xf0, 0x3f, 0xbc, 0x30, 0xb5, + 0xdf, 0xf8, 0x2c, 0x48, 0x87, 0xb0, 0x14, 0x21, 0x04, 0xf2, 0x84, 0x40, + 0xfe, 0xf7, 0xc3, 0xfd, 0x20, 0x60, 0x00, 0xf0, 0x39, 0xf8, 0x03, 0x21, + 0x04, 0x91, 0x00, 0x21, 0x03, 0x91, 0x80, 0x21, 0x02, 0x91, 0x03, 0x21, + 0xdf, 0xf8, 0x68, 0x0c, 0x01, 0x90, 0x00, 0x91, 0x00, 0xf5, 0xfe, 0x72, + 0x03, 0x23, 0x00, 0x21, 0x0f, 0xf6, 0xa9, 0x10, 0xfe, 0xf7, 0x8d, 0xff, + 0x40, 0x1e, 0x00, 0xf0, 0xdc, 0xf9, 0x05, 0xaa, 0x0f, 0xf2, 0x38, 0x01, + 0x03, 0x20, 0xff, 0xf7, 0x3b, 0xf8, 0x04, 0xf1, 0x4c, 0x00, 0x00, 0x21, + 0x01, 0x81, 0x04, 0xf5, 0x51, 0x75, 0x4f, 0xf6, 0xff, 0x71, 0x01, 0x80, + 0x4f, 0xf0, 0xff, 0x31, 0x29, 0x60, 0x69, 0x60, 0x00, 0x21, 0x81, 0x72, + 0x04, 0xf5, 0x59, 0x70, 0xe8, 0x60, 0x00, 0xf0, 0x44, 0xf8, 0x00, 0x20, + 0x28, 0x72, 0x28, 0x77, 0x07, 0xb0, 0x30, 0xbd, 0x43, 0x74, 0x72, 0x6c, + 0x54, 0x73, 0x6b, 0x00, 0x00, 0xb1, 0x01, 0x20, 0x04, 0xf0, 0x07, 0xba, + 0xf8, 0xb5, 0x00, 0x25, 0x00, 0x21, 0xdf, 0xf8, 0x98, 0x67, 0x20, 0xfa, + 0x01, 0xf2, 0xd2, 0x07, 0x03, 0xd5, 0x06, 0xeb, 0x81, 0x02, 0xd4, 0x6f, + 0x34, 0xb9, 0x49, 0x1c, 0x07, 0x29, 0xf4, 0xd3, 0x28, 0x46, 0xf2, 0xbd, + 0x00, 0x25, 0x14, 0x46, 0xe2, 0x6a, 0x00, 0x2a, 0xf5, 0xd0, 0x63, 0x7b, + 0xa5, 0x7b, 0x2b, 0x42, 0xf6, 0xd0, 0x01, 0x21, 0x20, 0x46, 0x00, 0xf0, + 0x7d, 0xfb, 0x20, 0x7b, 0x01, 0x25, 0x07, 0x46, 0x07, 0x28, 0xb4, 0xbf, + 0x01, 0x20, 0x00, 0x20, 0x04, 0xf0, 0xdf, 0xf9, 0x00, 0x20, 0xe0, 0x62, + 0x06, 0xeb, 0x87, 0x00, 0xc1, 0x6f, 0xc4, 0x67, 0x00, 0x29, 0xdf, 0xd0, + 0xe1, 0x62, 0xdd, 0xe7, 0xdf, 0xf8, 0x38, 0x07, 0x90, 0xf8, 0x54, 0x03, + 0x70, 0x47, 0xdf, 0xf8, 0xfc, 0x0b, 0x40, 0x89, 0x00, 0xf0, 0x03, 0x01, + 0xc0, 0xf3, 0x01, 0x10, 0x03, 0x28, 0x04, 0xd1, 0x03, 0x29, 0x0c, 0xd1, + 0x01, 0x20, 0x02, 0x21, 0x1f, 0xe0, 0x01, 0x28, 0x18, 0xbf, 0x02, 0x28, + 0x0d, 0xd1, 0x03, 0x29, 0x09, 0xd1, 0x01, 0x28, 0x13, 0xd1, 0x03, 0x20, + 0x14, 0xe0, 0x01, 0x29, 0x18, 0xbf, 0x02, 0x29, 0x0f, 0xd1, 0x08, 0x46, + 0x0f, 0xe0, 0x01, 0x28, 0x01, 0xd0, 0x02, 0x28, 0x09, 0xd1, 0x01, 0x29, + 0x18, 0xbf, 0x02, 0x29, 0x05, 0xd1, 0x01, 0x28, 0x01, 0xd1, 0x08, 0x46, + 0x02, 0xe0, 0x00, 0x20, 0x01, 0xe0, 0x00, 0x20, 0x00, 0x21, 0x40, 0xea, + 0x81, 0x00, 0xdf, 0xf8, 0xd0, 0x16, 0x81, 0xf8, 0xb8, 0x03, 0x70, 0x47, + 0xdf, 0xf8, 0xc4, 0x26, 0x92, 0xf8, 0xb8, 0x23, 0x01, 0x23, 0x03, 0xfa, + 0x00, 0xf0, 0x00, 0x21, 0x00, 0xea, 0x02, 0x03, 0x13, 0xf0, 0x03, 0x0f, + 0x18, 0xbf, 0x01, 0x21, 0x05, 0xd1, 0x00, 0xea, 0x92, 0x00, 0x10, 0xf0, + 0x03, 0x0f, 0x18, 0xbf, 0x02, 0x21, 0xdf, 0xf8, 0x68, 0x0b, 0x40, 0x89, + 0x01, 0xea, 0x10, 0x10, 0x40, 0x1e, 0x40, 0xb2, 0x70, 0x47, 0xdf, 0xf8, + 0x8c, 0x06, 0xd0, 0xf8, 0x64, 0x13, 0xca, 0x03, 0x05, 0xd5, 0x90, 0xf8, + 0xba, 0x23, 0x05, 0x2a, 0x01, 0xd1, 0x05, 0x20, 0x70, 0x47, 0x49, 0x07, + 0x03, 0xd5, 0x90, 0xf8, 0xba, 0x03, 0x01, 0x28, 0x00, 0xd0, 0xff, 0x20, + 0x70, 0x47, 0xdf, 0xf8, 0x64, 0x06, 0xd0, 0xf8, 0x64, 0x13, 0x8a, 0x03, + 0x05, 0xd5, 0x90, 0xf8, 0xbb, 0x23, 0x06, 0x2a, 0x01, 0xd1, 0x06, 0x20, + 0x70, 0x47, 0x09, 0x07, 0x03, 0xd5, 0x90, 0xf8, 0xbb, 0x03, 0x02, 0x28, + 0x00, 0xd0, 0xff, 0x20, 0x70, 0x47, 0x10, 0xb5, 0x04, 0x46, 0x00, 0xf0, + 0x47, 0xfb, 0x84, 0x42, 0x0c, 0xbf, 0x01, 0x20, 0x00, 0x20, 0x10, 0xbd, + 0x2d, 0xe9, 0xf1, 0x4f, 0x0c, 0x46, 0xdf, 0xf8, 0x24, 0x86, 0xdf, 0xf8, + 0xf0, 0xaa, 0x15, 0x46, 0x01, 0x26, 0x04, 0xf0, 0x04, 0x0b, 0x08, 0xf2, + 0xb9, 0x39, 0x00, 0x98, 0xf0, 0x40, 0xc0, 0x07, 0x6d, 0xd5, 0x08, 0xeb, + 0x86, 0x00, 0xc7, 0x6f, 0x23, 0xe0, 0x38, 0x78, 0x05, 0x28, 0x09, 0xd1, + 0xff, 0xf7, 0xb5, 0xff, 0x85, 0x42, 0x66, 0xd0, 0x03, 0x2d, 0x03, 0xd1, + 0x99, 0xf8, 0x03, 0x00, 0x00, 0x28, 0x60, 0xd1, 0x38, 0x78, 0x06, 0x28, + 0x09, 0xd1, 0xff, 0xf7, 0xbc, 0xff, 0x85, 0x42, 0x59, 0xd0, 0x03, 0x2d, + 0x03, 0xd1, 0x99, 0xf8, 0x03, 0x00, 0x00, 0x28, 0x53, 0xd1, 0x38, 0x78, + 0x01, 0x28, 0x01, 0xd1, 0xe1, 0x07, 0x4e, 0xd4, 0x02, 0x28, 0x01, 0xd1, + 0xa0, 0x07, 0x4a, 0xd4, 0xff, 0x6a, 0x00, 0x2f, 0x43, 0xd0, 0x78, 0x7b, + 0x00, 0x28, 0xf9, 0xd0, 0x79, 0x88, 0xd8, 0xf8, 0x48, 0x03, 0x11, 0xf8, + 0x0a, 0x10, 0xc8, 0x40, 0xc0, 0x07, 0xf1, 0xd5, 0x38, 0x7b, 0x01, 0x28, + 0x18, 0xbf, 0x04, 0x28, 0x25, 0xd0, 0x05, 0x28, 0xc7, 0xd0, 0x02, 0x28, + 0x1f, 0xd1, 0x39, 0x78, 0x99, 0xf8, 0x00, 0x00, 0x03, 0x29, 0x0c, 0xd1, + 0xbb, 0xf1, 0x00, 0x0f, 0xe0, 0xd0, 0x03, 0x2d, 0x29, 0xd0, 0x01, 0x2d, + 0x02, 0xd1, 0xc0, 0x07, 0xda, 0xd5, 0x24, 0xe0, 0x02, 0x2d, 0xd7, 0xd1, + 0x0b, 0xe0, 0x04, 0x29, 0xd4, 0xd1, 0x21, 0x07, 0xd2, 0xd5, 0x03, 0x2d, + 0x1b, 0xd0, 0x02, 0x2d, 0x01, 0xd1, 0x00, 0x07, 0xf0, 0xe7, 0x01, 0x2d, + 0xca, 0xd1, 0x80, 0x07, 0xec, 0xe7, 0x03, 0x28, 0xc6, 0xd1, 0x39, 0x78, + 0x03, 0x29, 0x03, 0xd1, 0xbb, 0xf1, 0x00, 0x0f, 0x04, 0xd1, 0xbf, 0xe7, + 0x04, 0x29, 0xbd, 0xd1, 0x20, 0x07, 0xbb, 0xd5, 0x03, 0x2d, 0xb9, 0xd1, + 0x03, 0xe0, 0x76, 0x1c, 0x07, 0x2e, 0x8a, 0xdb, 0x00, 0x27, 0x38, 0x46, + 0xbd, 0xe8, 0xf2, 0x8f, 0x2d, 0xe9, 0xf0, 0x41, 0xdf, 0xf8, 0xec, 0x59, + 0x80, 0x46, 0x95, 0xf8, 0x4c, 0x00, 0xc0, 0x07, 0x0e, 0x46, 0x04, 0xd5, + 0x28, 0x7a, 0x01, 0x28, 0x08, 0xbf, 0x00, 0x20, 0x2d, 0xd0, 0x2c, 0x6d, + 0xc6, 0xf3, 0x02, 0x17, 0x4c, 0xb1, 0x20, 0x46, 0xff, 0xf7, 0xaa, 0xfe, + 0x28, 0xb1, 0x3a, 0x46, 0x31, 0x46, 0x20, 0x46, 0xff, 0xf7, 0x5e, 0xff, + 0x20, 0xb9, 0x3a, 0x46, 0x31, 0x46, 0x7f, 0x20, 0xff, 0xf7, 0x58, 0xff, + 0x00, 0x28, 0xa9, 0x7a, 0x14, 0xbf, 0x07, 0x7b, 0x00, 0x27, 0x79, 0xb1, + 0x2e, 0x88, 0xf0, 0xb2, 0x00, 0xf0, 0x8a, 0xfa, 0xb8, 0xf1, 0x00, 0x0f, + 0x04, 0xbf, 0x00, 0x7b, 0xb8, 0x42, 0x0c, 0xd0, 0xe8, 0x7a, 0x50, 0xb9, + 0xf0, 0xb2, 0x00, 0xf0, 0x07, 0xf9, 0x06, 0xe0, 0x00, 0x2e, 0x04, 0xd4, + 0x18, 0xb1, 0x40, 0x88, 0x31, 0x46, 0xff, 0xf7, 0x9d, 0xfc, 0x00, 0x20, + 0xbd, 0xe8, 0xf0, 0x81, 0x70, 0xb5, 0x04, 0x00, 0x14, 0xbf, 0x01, 0x20, + 0x00, 0x20, 0x04, 0xf0, 0x7e, 0xf8, 0x20, 0x68, 0x0f, 0x28, 0x00, 0xf0, + 0x28, 0xf8, 0x25, 0x68, 0xdf, 0xf8, 0x80, 0x24, 0xd2, 0xf8, 0xbc, 0x60, + 0x28, 0x46, 0x41, 0x08, 0x02, 0xeb, 0xc1, 0x01, 0x01, 0xf1, 0xc0, 0x03, + 0xf8, 0x31, 0xc6, 0x40, 0xf6, 0x07, 0x04, 0xd5, 0xbd, 0xe8, 0x70, 0x40, + 0x01, 0x21, 0x04, 0xf0, 0xa7, 0xb9, 0x1d, 0x60, 0x01, 0x25, 0x64, 0x68, + 0x5c, 0x60, 0x05, 0xfa, 0x00, 0xf0, 0xd2, 0xf8, 0xbc, 0x40, 0x20, 0x43, + 0xc2, 0xf8, 0xbc, 0x00, 0x0d, 0x60, 0x4b, 0x60, 0x08, 0x46, 0xbd, 0xe8, + 0x70, 0x40, 0x5d, 0xe4, 0x9d, 0xf8, 0x00, 0x10, 0x48, 0x1e, 0x80, 0x41, + 0xc0, 0x0f, 0x04, 0xf0, 0x4e, 0xb8, 0xf8, 0xb5, 0x06, 0x46, 0x37, 0x68, + 0x0e, 0x2f, 0x20, 0xd2, 0x00, 0x21, 0x38, 0x46, 0xdf, 0xf8, 0x1c, 0x44, + 0x04, 0xf0, 0x6e, 0xf9, 0x04, 0xf1, 0x54, 0x05, 0xf8, 0xb2, 0x29, 0x78, + 0x05, 0xf0, 0x56, 0xfb, 0x00, 0x28, 0x40, 0xf0, 0xa6, 0x80, 0x6f, 0xb1, + 0x02, 0x2f, 0x10, 0xd0, 0x04, 0x2f, 0x19, 0xd0, 0x06, 0x2f, 0x5f, 0xd0, + 0x08, 0x2f, 0x4f, 0xd0, 0x0a, 0x2f, 0x69, 0xd0, 0x0c, 0x2f, 0x00, 0xf0, + 0x80, 0x80, 0x93, 0xe0, 0x70, 0x68, 0x00, 0xf0, 0x8f, 0xfb, 0x00, 0x20, + 0xf2, 0xbd, 0x74, 0x68, 0x0e, 0x20, 0x04, 0xf0, 0xe6, 0xf8, 0x01, 0x20, + 0x28, 0x70, 0x00, 0x21, 0x20, 0x46, 0x05, 0xf0, 0xbd, 0xfb, 0xf2, 0xe7, + 0x10, 0x20, 0x04, 0xf0, 0xdc, 0xf8, 0x04, 0xf0, 0x0c, 0xfe, 0x01, 0x00, + 0x06, 0xd0, 0x04, 0x20, 0x04, 0xf0, 0x52, 0xf9, 0x04, 0x20, 0x00, 0xf0, + 0x62, 0xfb, 0xe4, 0xe7, 0x04, 0x20, 0x28, 0x70, 0x1c, 0x21, 0x00, 0x20, + 0xa8, 0x64, 0x04, 0xf1, 0xa0, 0x00, 0x03, 0xf0, 0x59, 0xfe, 0x00, 0xf0, + 0xfd, 0xfb, 0x48, 0xb1, 0x4f, 0xf0, 0x7f, 0x42, 0x40, 0xf6, 0xff, 0x73, + 0x00, 0x20, 0x00, 0xf0, 0x0d, 0xf9, 0x68, 0x46, 0x05, 0xf0, 0x7d, 0xfb, + 0xff, 0xf7, 0x06, 0xfb, 0x07, 0x22, 0x00, 0x23, 0x03, 0x20, 0x00, 0xf0, + 0x03, 0xf9, 0x04, 0x20, 0x00, 0xf0, 0x41, 0xfb, 0x00, 0x25, 0x6c, 0x20, + 0x00, 0xfb, 0x05, 0x40, 0x00, 0xf2, 0x14, 0x50, 0x05, 0xf0, 0x32, 0xfc, + 0x6d, 0x1c, 0x12, 0x2d, 0xf5, 0xd3, 0xb8, 0xe7, 0x74, 0x68, 0x12, 0x20, + 0x04, 0xf0, 0xa1, 0xf8, 0x21, 0x46, 0x00, 0x20, 0x05, 0xf0, 0x2a, 0xfc, + 0x01, 0x46, 0x08, 0x20, 0x04, 0xf0, 0x16, 0xf9, 0x08, 0x20, 0xc2, 0xe7, + 0x74, 0x68, 0x11, 0x20, 0x04, 0xf0, 0x93, 0xf8, 0x21, 0x46, 0x01, 0x20, + 0x05, 0xf0, 0x1c, 0xfc, 0x01, 0x46, 0x06, 0x20, 0x04, 0xf0, 0x08, 0xf9, + 0x06, 0x20, 0xb4, 0xe7, 0x74, 0x68, 0x14, 0x20, 0x04, 0xf0, 0x85, 0xf8, + 0x29, 0x78, 0xe0, 0xb2, 0x05, 0xf0, 0xc6, 0xfa, 0x48, 0xb9, 0xc4, 0xf3, + 0x42, 0x10, 0x03, 0x28, 0x04, 0xd1, 0x01, 0x21, 0x20, 0x46, 0x00, 0xf0, + 0xf9, 0xfb, 0x00, 0xe0, 0x04, 0x20, 0x01, 0x46, 0x0a, 0x20, 0x04, 0xf0, + 0xef, 0xf8, 0x0a, 0x20, 0x9b, 0xe7, 0x74, 0x68, 0x20, 0x06, 0x45, 0x0f, + 0x13, 0x20, 0x04, 0xf0, 0x6a, 0xf8, 0x03, 0x2d, 0x18, 0xbf, 0x02, 0x2d, + 0x11, 0xbf, 0x04, 0x20, 0x00, 0x21, 0x20, 0x46, 0x00, 0xf0, 0xe2, 0xfb, + 0x01, 0x46, 0x0c, 0x20, 0x04, 0xf0, 0xda, 0xf8, 0x0c, 0x20, 0x86, 0xe7, + 0x03, 0xf0, 0x95, 0xff, 0x6b, 0xe7, 0x80, 0x28, 0x03, 0xd1, 0x38, 0x46, + 0x00, 0xf0, 0xe3, 0xfa, 0x65, 0xe7, 0x01, 0x46, 0x38, 0x46, 0x04, 0xf0, + 0xcb, 0xf8, 0xf6, 0xe7, 0x10, 0xb5, 0x82, 0xb0, 0x00, 0xf0, 0x74, 0xf9, + 0x04, 0x46, 0x20, 0x7e, 0x05, 0x28, 0x1c, 0xbf, 0x04, 0x20, 0x20, 0x76, + 0x02, 0x20, 0x04, 0xf0, 0x2b, 0xf9, 0x60, 0x68, 0x6b, 0x46, 0x01, 0x22, + 0x01, 0x21, 0xfe, 0xf7, 0x13, 0xfa, 0xff, 0xf7, 0x1f, 0xff, 0xdf, 0xf8, + 0x70, 0x1b, 0x01, 0x20, 0x81, 0xf8, 0x57, 0x00, 0x06, 0x20, 0x04, 0xf0, + 0x30, 0xf8, 0x00, 0x20, 0x16, 0xbd, 0x70, 0xb5, 0x04, 0x46, 0x0d, 0x46, + 0xff, 0xf7, 0x12, 0xfd, 0x06, 0x46, 0xb0, 0x7b, 0x28, 0xb1, 0xe0, 0xb2, + 0x00, 0xf0, 0xb2, 0xf8, 0x05, 0x20, 0x04, 0xf0, 0x20, 0xf8, 0x00, 0x20, + 0x70, 0x73, 0xb0, 0x73, 0x01, 0x21, 0x30, 0x46, 0x00, 0xf0, 0xea, 0xf8, + 0xe0, 0xb2, 0x05, 0xf0, 0x57, 0xfb, 0xdf, 0xf8, 0x2c, 0x1b, 0x01, 0xeb, + 0x84, 0x01, 0x00, 0x20, 0x48, 0x60, 0x30, 0x69, 0xff, 0xf7, 0x3e, 0xfd, + 0x70, 0x6a, 0x33, 0x69, 0x00, 0x22, 0x29, 0x46, 0x98, 0x47, 0x00, 0x20, + 0x70, 0xbd, 0xf0, 0xb5, 0x83, 0xb0, 0x07, 0x46, 0x00, 0xf0, 0x2c, 0xf9, + 0x04, 0x46, 0x02, 0x20, 0x04, 0xf0, 0x06, 0xf9, 0x20, 0x7e, 0xdf, 0xf8, + 0xf8, 0x5a, 0x05, 0x28, 0x05, 0xf1, 0x4c, 0x06, 0x11, 0xd1, 0x01, 0x21, + 0x38, 0x46, 0xff, 0xf7, 0xc4, 0xff, 0x30, 0x7a, 0x05, 0x28, 0x0a, 0xd1, + 0x03, 0x20, 0x30, 0x72, 0x04, 0xf0, 0x13, 0xfc, 0x00, 0xf0, 0x35, 0xf8, + 0x04, 0xf0, 0x1e, 0xf9, 0x00, 0x20, 0x00, 0xf0, 0x74, 0xfa, 0x00, 0x20, + 0x60, 0x73, 0x02, 0x20, 0x20, 0x76, 0x4f, 0xf6, 0xff, 0x70, 0x30, 0x80, + 0x00, 0x20, 0x70, 0x81, 0x00, 0x2f, 0x04, 0xbf, 0x30, 0x7a, 0x05, 0x28, + 0x0a, 0xd1, 0x08, 0x20, 0x00, 0x90, 0x4f, 0xf0, 0xff, 0x30, 0x01, 0x90, + 0x68, 0x46, 0x00, 0xf0, 0x20, 0xf8, 0x00, 0x20, 0x00, 0xf0, 0x5b, 0xfa, + 0x20, 0x7b, 0x05, 0xeb, 0x80, 0x01, 0x01, 0x22, 0xc9, 0x6f, 0x04, 0xe0, + 0x4b, 0x7b, 0x01, 0x2b, 0x08, 0xbf, 0x00, 0x22, 0xc9, 0x6a, 0x00, 0x29, + 0xf8, 0xd1, 0x32, 0xb1, 0xf1, 0x6c, 0x01, 0x22, 0x02, 0xfa, 0x00, 0xf0, + 0x21, 0xea, 0x00, 0x00, 0xf0, 0x64, 0x00, 0x20, 0xfe, 0xbd, 0x07, 0x22, + 0x00, 0x23, 0x02, 0x20, 0x00, 0x21, 0x04, 0xf0, 0x39, 0xb8, 0xf8, 0xb5, + 0x06, 0x46, 0x00, 0x20, 0x00, 0xf0, 0xd4, 0xf8, 0xdf, 0xf8, 0x50, 0x5a, + 0xd5, 0xf8, 0xc8, 0x70, 0x05, 0xf1, 0x54, 0x04, 0xa0, 0x6e, 0x80, 0x08, + 0x00, 0xf0, 0x01, 0x00, 0x03, 0xf0, 0xd9, 0xfe, 0x02, 0x2f, 0x0c, 0xbf, + 0x01, 0x20, 0x00, 0x20, 0x03, 0xf0, 0xd3, 0xfe, 0x71, 0x68, 0xc9, 0xb2, + 0x38, 0x46, 0x04, 0xf0, 0x0f, 0xf8, 0x38, 0x46, 0x00, 0xf0, 0x1f, 0xfa, + 0x70, 0x68, 0x70, 0xb9, 0x05, 0xf0, 0x93, 0xfc, 0x48, 0xb1, 0x03, 0x20, + 0x20, 0x70, 0x01, 0x20, 0x85, 0xf8, 0x4c, 0x03, 0x04, 0xf0, 0xab, 0xfb, + 0xff, 0xf7, 0xcd, 0xff, 0x08, 0xe0, 0x02, 0x20, 0x05, 0xe0, 0x95, 0xf8, + 0x4c, 0x03, 0x00, 0x28, 0x14, 0xbf, 0x03, 0x20, 0x02, 0x20, 0x20, 0x70, + 0x01, 0x21, 0x00, 0x20, 0xff, 0xf7, 0x45, 0xff, 0x00, 0x20, 0xf2, 0xbd, + 0x80, 0xb5, 0x00, 0xf0, 0x99, 0xf8, 0x00, 0x21, 0x81, 0x73, 0x02, 0x7b, + 0xdf, 0xf8, 0xd4, 0x19, 0x01, 0xeb, 0x82, 0x02, 0xd2, 0xf8, 0xa0, 0x30, + 0x5b, 0x1e, 0xc2, 0xf8, 0xa0, 0x30, 0x00, 0x7b, 0x01, 0xeb, 0x80, 0x02, + 0xd2, 0xf8, 0xa0, 0x20, 0x42, 0xb9, 0xd1, 0xf8, 0x9c, 0x20, 0x01, 0x23, + 0x03, 0xfa, 0x00, 0xf0, 0x22, 0xea, 0x00, 0x00, 0xc1, 0xf8, 0x9c, 0x00, + 0x00, 0x20, 0x02, 0xbd, 0x70, 0xb5, 0x04, 0x46, 0x0d, 0x46, 0x20, 0x7b, + 0x06, 0x46, 0x07, 0x28, 0xb4, 0xbf, 0x01, 0x20, 0x00, 0x20, 0x03, 0xf0, + 0x82, 0xfe, 0x00, 0x20, 0xe0, 0x62, 0x00, 0x2d, 0x23, 0x48, 0x0c, 0xbf, + 0x60, 0x30, 0x7c, 0x30, 0x50, 0xf8, 0x26, 0x10, 0x19, 0xb9, 0x40, 0xf8, + 0x26, 0x40, 0x04, 0xe0, 0x01, 0x46, 0xc8, 0x6a, 0x00, 0x28, 0xfb, 0xd1, + 0xcc, 0x62, 0x00, 0x20, 0x70, 0xbd, 0x00, 0x00, 0xfc, 0x07, 0x00, 0x20, + 0xf8, 0xb5, 0x06, 0x46, 0x0f, 0x46, 0x30, 0x7b, 0x04, 0x46, 0x07, 0x28, + 0xb4, 0xbf, 0x01, 0x20, 0x00, 0x20, 0x03, 0xf0, 0x60, 0xfe, 0xdf, 0xf8, + 0x48, 0x19, 0x00, 0x2f, 0x0c, 0xbf, 0x01, 0xf1, 0x60, 0x02, 0x01, 0xf1, + 0x7c, 0x02, 0x52, 0xf8, 0x24, 0x00, 0xb0, 0x42, 0x11, 0xd1, 0xc3, 0x6a, + 0x42, 0xf8, 0x24, 0x30, 0x3b, 0xb9, 0x04, 0x7b, 0xd1, 0xf8, 0x98, 0x20, + 0x01, 0x23, 0xa3, 0x40, 0x9a, 0x43, 0xc1, 0xf8, 0x98, 0x20, 0x00, 0x21, + 0xc1, 0x62, 0x00, 0x20, 0xf2, 0xbd, 0x05, 0x46, 0xc0, 0x6a, 0x00, 0x28, + 0x18, 0xbf, 0xb0, 0x42, 0xf9, 0xd1, 0xb0, 0x42, 0x02, 0xd1, 0xc1, 0x6a, + 0xe9, 0x62, 0xf0, 0xe7, 0x01, 0x20, 0xf2, 0xbd, 0xb8, 0x04, 0x00, 0x20, + 0xdf, 0xf8, 0xf0, 0x18, 0xdf, 0xf8, 0xc4, 0x24, 0xd1, 0xf8, 0x50, 0x13, + 0x80, 0x5c, 0x1d, 0xe0, 0x00, 0xe1, 0x00, 0xe0, 0x80, 0xe1, 0x00, 0xe0, + 0x10, 0xb5, 0x04, 0x46, 0x04, 0x2c, 0xb4, 0xbf, 0x01, 0x20, 0x00, 0x20, + 0x03, 0xf0, 0x21, 0xfe, 0xdf, 0xf8, 0xc8, 0x08, 0x00, 0xeb, 0x84, 0x00, + 0xd0, 0xf8, 0xa8, 0x43, 0x04, 0xf0, 0x4a, 0xf8, 0xa0, 0x42, 0x34, 0xbf, + 0x20, 0x1a, 0x00, 0x20, 0x10, 0xbd, 0x00, 0x00, 0x65, 0x2c, 0x00, 0x20, + 0xdf, 0xf8, 0xa8, 0x18, 0x01, 0xeb, 0x80, 0x00, 0x40, 0x68, 0x70, 0x47, + 0x80, 0xb5, 0xef, 0xf3, 0x05, 0x80, 0x08, 0xb1, 0x00, 0xf0, 0x04, 0xf8, + 0xdf, 0xf8, 0x94, 0x08, 0x00, 0x68, 0x02, 0xbd, 0x00, 0x20, 0x03, 0xf0, + 0xfe, 0xbd, 0x80, 0xb5, 0xff, 0xf7, 0xf0, 0xff, 0xdf, 0xf8, 0x54, 0x14, + 0x40, 0x5c, 0x02, 0xbd, 0x10, 0xb5, 0xdf, 0xf8, 0x78, 0x48, 0x20, 0x68, + 0x10, 0xf1, 0x01, 0x0f, 0x14, 0xbf, 0x01, 0x20, 0x00, 0x20, 0x03, 0xf0, + 0xec, 0xfd, 0xef, 0xf3, 0x05, 0x80, 0x08, 0xb1, 0xff, 0xf7, 0xe6, 0xff, + 0x20, 0x68, 0xc0, 0xb2, 0xff, 0xf7, 0xd2, 0xff, 0x04, 0x00, 0x14, 0xbf, + 0x01, 0x20, 0x00, 0x20, 0x03, 0xf0, 0xdd, 0xfd, 0x60, 0x68, 0x10, 0xbd, + 0xf8, 0xb5, 0x00, 0xf0, 0x56, 0xf8, 0x0e, 0x46, 0x14, 0xbf, 0x01, 0x20, + 0x00, 0x20, 0x03, 0xf0, 0xd2, 0xfd, 0xef, 0xf3, 0x05, 0x80, 0x08, 0xb1, + 0xff, 0xf7, 0xcc, 0xff, 0x67, 0x00, 0x01, 0x20, 0x00, 0x21, 0x07, 0xf1, + 0x18, 0x02, 0x02, 0xf0, 0xe5, 0xff, 0x04, 0x46, 0x0d, 0x46, 0x01, 0x20, + 0x00, 0x21, 0x07, 0xf1, 0x19, 0x02, 0x02, 0xf0, 0xdd, 0xff, 0x03, 0x2e, + 0x14, 0xd8, 0xdf, 0xe8, 0x06, 0xf0, 0x02, 0x07, 0x0a, 0x0d, 0x22, 0x46, + 0x2b, 0x46, 0x20, 0x46, 0x29, 0x46, 0x09, 0xe0, 0x22, 0x46, 0x2b, 0x46, + 0x04, 0xe0, 0x02, 0x46, 0x0b, 0x46, 0x03, 0xe0, 0x02, 0x46, 0x0b, 0x46, + 0x00, 0x20, 0x00, 0x21, 0x03, 0xf0, 0xf6, 0xfe, 0x00, 0x20, 0xf2, 0xbd, + 0x10, 0xb5, 0x82, 0xb0, 0xff, 0xf7, 0x96, 0xff, 0xc0, 0xb2, 0xff, 0xf7, + 0x8d, 0xff, 0x00, 0xf0, 0x1a, 0xf8, 0x14, 0xbf, 0x01, 0x20, 0x00, 0x20, + 0x03, 0xf0, 0x97, 0xfd, 0xef, 0xf3, 0x05, 0x80, 0x08, 0xb1, 0xff, 0xf7, + 0x91, 0xff, 0x60, 0x68, 0x6b, 0x46, 0x00, 0x22, 0x08, 0x21, 0xfe, 0xf7, + 0x29, 0xf8, 0xff, 0xf7, 0x35, 0xfd, 0xa0, 0x6a, 0x69, 0x46, 0xfe, 0xf7, + 0xbd, 0xfc, 0xff, 0xf7, 0x2f, 0xfd, 0x00, 0x20, 0x16, 0xbd, 0x04, 0x46, + 0xdf, 0xf8, 0x8c, 0x07, 0x00, 0x68, 0x10, 0xf1, 0x01, 0x0f, 0x70, 0x47, + 0x00, 0xb5, 0xdf, 0xf8, 0x80, 0x07, 0x83, 0xb0, 0x00, 0x68, 0x10, 0xf1, + 0x01, 0x0f, 0x14, 0xbf, 0x01, 0x20, 0x00, 0x20, 0x03, 0xf0, 0x6f, 0xfd, + 0xef, 0xf3, 0x05, 0x80, 0x08, 0xb1, 0xff, 0xf7, 0x69, 0xff, 0xff, 0xf7, + 0x71, 0xff, 0x01, 0xa9, 0x00, 0x91, 0x00, 0x23, 0x82, 0x22, 0x08, 0x21, + 0xfd, 0xf7, 0x72, 0xff, 0x00, 0x20, 0x0e, 0xbd, 0x2d, 0xe9, 0xf0, 0x47, + 0x82, 0xb0, 0x04, 0xf0, 0xa8, 0xf8, 0xdf, 0xf8, 0x44, 0x07, 0xdf, 0xf8, + 0x38, 0x47, 0x03, 0xf0, 0x5b, 0xfe, 0x04, 0xf1, 0x54, 0x05, 0x02, 0x20, + 0x28, 0x70, 0x01, 0x26, 0x00, 0x20, 0xc0, 0x46, 0x07, 0x22, 0x00, 0x23, + 0x01, 0x20, 0xff, 0xf7, 0x5b, 0xfe, 0x03, 0xf0, 0x9d, 0xff, 0x20, 0x65, + 0x09, 0xe0, 0x40, 0x46, 0xff, 0xf7, 0x57, 0xfe, 0x21, 0x6d, 0x48, 0x46, + 0xff, 0xf7, 0x76, 0xfc, 0x01, 0x20, 0x03, 0xf0, 0x07, 0xff, 0x20, 0x68, + 0x6a, 0x46, 0x00, 0x21, 0xfe, 0xf7, 0xfb, 0xf8, 0x80, 0x46, 0x01, 0x20, + 0xd8, 0xf8, 0x00, 0xa0, 0x03, 0xf0, 0xde, 0xfe, 0x5f, 0xfa, 0x8a, 0xf0, + 0x0a, 0x28, 0x4f, 0xea, 0x1a, 0x27, 0x4f, 0xf0, 0x00, 0x09, 0xe5, 0xd8, + 0xdf, 0xe8, 0x00, 0xf0, 0x08, 0x13, 0x37, 0x46, 0x4a, 0x06, 0x06, 0x06, + 0x07, 0x56, 0x69, 0x00, 0xdc, 0xe7, 0xd8, 0xe7, 0x84, 0xf8, 0x60, 0x93, + 0x03, 0xf0, 0x70, 0xff, 0x01, 0x46, 0x21, 0x65, 0x02, 0x20, 0x03, 0xf0, + 0xf7, 0xfd, 0xb1, 0x46, 0xd0, 0xe7, 0xb4, 0xf8, 0xc0, 0x03, 0xd8, 0xf8, + 0x04, 0x30, 0x04, 0xeb, 0xc0, 0x00, 0x00, 0xf5, 0x71, 0x72, 0xd3, 0xe9, + 0x00, 0x01, 0xc2, 0xe9, 0x00, 0x01, 0xd8, 0xf8, 0x04, 0x00, 0xff, 0xf7, + 0xb4, 0xfc, 0xb4, 0xf8, 0xc0, 0x03, 0xdf, 0xf8, 0x94, 0x16, 0x09, 0x68, + 0x04, 0xeb, 0x80, 0x00, 0xc0, 0xf8, 0x44, 0x14, 0xb4, 0xf8, 0xc0, 0x03, + 0x40, 0x1c, 0xa4, 0xf8, 0xc0, 0x03, 0x80, 0xb2, 0x10, 0x28, 0xaf, 0xdb, + 0xa4, 0xf8, 0xc0, 0x93, 0xac, 0xe7, 0x28, 0x78, 0x05, 0x28, 0xa9, 0xd0, + 0xf8, 0xb2, 0xff, 0xf7, 0xd7, 0xfe, 0x02, 0x7b, 0x69, 0x6c, 0x06, 0xfa, + 0x02, 0xf2, 0x11, 0x43, 0x69, 0x64, 0x06, 0x76, 0x46, 0x73, 0x9d, 0xe7, + 0xf8, 0xb2, 0xff, 0xf7, 0x9a, 0xfd, 0x99, 0xe7, 0xf8, 0xb2, 0xff, 0xf7, + 0xc7, 0xfe, 0x07, 0x46, 0x01, 0x21, 0xff, 0xf7, 0x69, 0xfe, 0x01, 0x21, + 0x38, 0x46, 0xff, 0xf7, 0x43, 0xfe, 0x8d, 0xe7, 0xf8, 0xb2, 0xff, 0xf7, + 0xbb, 0xfe, 0x02, 0x7b, 0xa9, 0x6c, 0x06, 0xfa, 0x02, 0xf2, 0x11, 0x43, + 0xa9, 0x64, 0x01, 0x7b, 0x04, 0xeb, 0x81, 0x01, 0xd1, 0xf8, 0xa0, 0x20, + 0x52, 0x1c, 0xc1, 0xf8, 0xa0, 0x20, 0x86, 0x73, 0x7a, 0xe7, 0xf8, 0xb2, + 0xff, 0xf7, 0x0c, 0xfe, 0x76, 0xe7, 0xdf, 0xf8, 0x08, 0x06, 0xdf, 0xf8, + 0xf8, 0x25, 0x00, 0x68, 0x41, 0x68, 0x11, 0x60, 0x90, 0xf8, 0x32, 0x10, + 0x01, 0x20, 0x03, 0xf0, 0x8f, 0xbd, 0x10, 0xb5, 0x04, 0x46, 0x72, 0xb6, + 0x03, 0xf0, 0xc1, 0xfd, 0xdf, 0xf8, 0xd4, 0x05, 0xd0, 0xf8, 0xbc, 0x10, + 0x01, 0x22, 0xa2, 0x40, 0x91, 0x43, 0xc0, 0xf8, 0xbc, 0x10, 0x62, 0xb6, + 0x10, 0xbd, 0x00, 0x00, 0x88, 0xf2, 0x00, 0x20, 0xfe, 0xb5, 0x0f, 0x20, + 0xdf, 0xf8, 0xb4, 0x55, 0x03, 0xf0, 0x57, 0xfd, 0x05, 0xf1, 0x4c, 0x04, + 0x20, 0x7a, 0x01, 0x28, 0x10, 0xd1, 0xa0, 0x7a, 0x28, 0xb1, 0x05, 0x20, + 0x20, 0x72, 0x00, 0x20, 0xff, 0xf7, 0xfe, 0xfc, 0x3f, 0xe0, 0x08, 0x20, + 0x01, 0x90, 0x4f, 0xf0, 0xff, 0x30, 0x02, 0x90, 0x01, 0xa8, 0xff, 0xf7, + 0x94, 0xfd, 0x33, 0xe0, 0x68, 0x46, 0x05, 0xf0, 0x25, 0xfb, 0x68, 0x46, + 0x05, 0xf0, 0xf5, 0xfa, 0x05, 0x20, 0x20, 0x72, 0x01, 0x26, 0x04, 0xf0, + 0x54, 0xf9, 0x05, 0xeb, 0x86, 0x00, 0x47, 0x68, 0x8f, 0xb1, 0x78, 0x88, + 0x22, 0x88, 0xc1, 0xb2, 0x91, 0x42, 0x08, 0xd1, 0x39, 0x7e, 0x05, 0x29, + 0x05, 0xd0, 0xc0, 0xb2, 0xff, 0xf7, 0xda, 0xfc, 0x05, 0x20, 0x38, 0x76, + 0x03, 0xe0, 0x01, 0x21, 0xc0, 0xb2, 0xff, 0xf7, 0xf2, 0xfc, 0x76, 0x1c, + 0x12, 0x2e, 0xe6, 0xdb, 0x20, 0x88, 0x4f, 0xf6, 0xff, 0x71, 0x88, 0x42, + 0x0d, 0xd1, 0x05, 0xf0, 0x1e, 0xfa, 0x50, 0xb1, 0x03, 0x20, 0x20, 0x72, + 0x04, 0xf0, 0x39, 0xf9, 0xff, 0xf7, 0x5b, 0xfd, 0x03, 0xf0, 0x44, 0xfe, + 0x00, 0x20, 0xff, 0xf7, 0x9a, 0xff, 0x00, 0x20, 0xfe, 0xbd, 0x10, 0xb5, + 0x82, 0xb0, 0xef, 0xf3, 0x05, 0x80, 0x08, 0xb1, 0xff, 0xf7, 0x3c, 0xfe, + 0xff, 0xf7, 0x30, 0xfe, 0xff, 0xf7, 0x42, 0xfe, 0x04, 0x00, 0x14, 0xbf, + 0x01, 0x20, 0x00, 0x20, 0x03, 0xf0, 0x33, 0xfc, 0x6b, 0x46, 0x02, 0x22, + 0x01, 0x21, 0x20, 0x46, 0xfd, 0xf7, 0xd4, 0xfd, 0x00, 0xf0, 0x01, 0x00, + 0x16, 0xbd, 0x10, 0xb5, 0x00, 0x24, 0xc0, 0xf3, 0x47, 0x12, 0x00, 0x2a, + 0x18, 0xbf, 0x01, 0x2a, 0x00, 0xf0, 0x1f, 0x00, 0x14, 0xd1, 0x02, 0x29, + 0x10, 0xd2, 0x0c, 0x23, 0x58, 0x43, 0x00, 0x2a, 0x0c, 0xbf, 0xdf, 0xf8, + 0xd0, 0x24, 0xdf, 0xf8, 0xd0, 0x24, 0x80, 0x18, 0x82, 0x68, 0x50, 0xf8, + 0x21, 0x10, 0xdf, 0xf8, 0xc8, 0x04, 0x05, 0xf0, 0x1d, 0xfb, 0x02, 0xe0, + 0x05, 0x24, 0x00, 0xe0, 0x04, 0x24, 0x20, 0x46, 0x10, 0xbd, 0x00, 0x00, + 0x68, 0x76, 0x00, 0x20, 0xf8, 0xb5, 0xdf, 0xf8, 0x90, 0x04, 0xd0, 0xf8, + 0x50, 0x03, 0x05, 0x68, 0x16, 0x48, 0x44, 0x89, 0x04, 0xf0, 0x03, 0x00, + 0xc4, 0xf3, 0x83, 0x01, 0x41, 0xea, 0x00, 0x11, 0x41, 0xea, 0x80, 0x11, + 0x41, 0xea, 0x00, 0x21, 0x41, 0xea, 0x80, 0x21, 0x41, 0xea, 0x00, 0x30, + 0x00, 0xea, 0x05, 0x06, 0xff, 0xf7, 0x6d, 0xfa, 0x05, 0x28, 0x0c, 0xbf, + 0x01, 0x27, 0x00, 0x27, 0xff, 0xf7, 0x7b, 0xfa, 0x06, 0x28, 0x0c, 0xbf, + 0x01, 0x20, 0x00, 0x20, 0x47, 0xea, 0x40, 0x00, 0x15, 0xea, 0x00, 0x40, + 0x07, 0xd0, 0x00, 0x90, 0x00, 0x98, 0x80, 0x0b, 0x00, 0xea, 0x94, 0x00, + 0x00, 0xf0, 0x0c, 0x00, 0x06, 0x43, 0x30, 0x46, 0xf2, 0xbd, 0x00, 0x00, + 0x78, 0x29, 0x00, 0x20, 0xf4, 0x1e, 0x00, 0x20, 0x04, 0x05, 0x00, 0x20, + 0xdf, 0xf8, 0x1c, 0x14, 0xd1, 0xf8, 0x64, 0x13, 0xc1, 0x40, 0x01, 0xf0, + 0x01, 0x00, 0x70, 0x47, 0x10, 0xb5, 0x04, 0x46, 0xff, 0xf7, 0xba, 0xff, + 0xe0, 0x40, 0x00, 0xf0, 0x01, 0x00, 0x10, 0xbd, 0x2d, 0xe9, 0xf0, 0x43, + 0x00, 0x24, 0x85, 0xb0, 0x03, 0x46, 0xde, 0xb2, 0x0f, 0x46, 0x18, 0x0a, + 0x40, 0x2e, 0x4f, 0xea, 0x13, 0x4c, 0x00, 0xf0, 0x0f, 0x01, 0xdf, 0xf8, + 0xe4, 0x83, 0xdf, 0xf8, 0xfc, 0x53, 0x18, 0xbf, 0x41, 0x2e, 0x0c, 0xf0, + 0x01, 0x0e, 0x00, 0xf0, 0x03, 0x00, 0xc3, 0xf3, 0x07, 0x22, 0x08, 0xf5, + 0x51, 0x79, 0x2b, 0xd0, 0x42, 0x2e, 0x2e, 0xd0, 0x43, 0x2e, 0x32, 0xd0, + 0x44, 0x2e, 0x25, 0xd0, 0x60, 0x2e, 0x35, 0xd0, 0x61, 0x2e, 0x00, 0xf0, + 0x73, 0x81, 0x62, 0x2e, 0x68, 0xd0, 0x63, 0x2e, 0x00, 0xf0, 0x4d, 0x81, + 0x64, 0x2e, 0x00, 0xf0, 0x7b, 0x81, 0x65, 0x2e, 0x00, 0xf0, 0x80, 0x80, + 0x66, 0x2e, 0x00, 0xf0, 0x9c, 0x80, 0x67, 0x2e, 0x00, 0xf0, 0x1f, 0x81, + 0x69, 0x2e, 0x00, 0xf0, 0x39, 0x81, 0x6a, 0x2e, 0x00, 0xf0, 0x7a, 0x81, + 0x6b, 0x2e, 0x00, 0xf0, 0x7f, 0x81, 0x6c, 0x2e, 0x03, 0xd0, 0x6d, 0x2e, + 0x00, 0xf0, 0x3e, 0x81, 0x7d, 0xe1, 0x00, 0x2f, 0x00, 0xf0, 0x7a, 0x81, + 0x05, 0xf0, 0x17, 0xfb, 0x77, 0xe1, 0xc3, 0xf3, 0x07, 0x41, 0x10, 0x46, + 0xff, 0xf7, 0x3f, 0xff, 0x3f, 0xe1, 0x14, 0x22, 0xdf, 0xf8, 0x74, 0x13, + 0x28, 0x46, 0x05, 0xf0, 0x71, 0xfa, 0x6a, 0xe1, 0x16, 0x46, 0xe0, 0x46, + 0x30, 0x46, 0x05, 0xf0, 0x15, 0xfb, 0x00, 0x28, 0x00, 0xf0, 0xfb, 0x80, + 0x00, 0x2f, 0x30, 0x46, 0x11, 0xd0, 0x05, 0xf0, 0x6b, 0xfb, 0x18, 0xb9, + 0x08, 0xf0, 0x1f, 0x01, 0x00, 0x22, 0x06, 0xe0, 0x4f, 0xea, 0x08, 0x62, + 0x10, 0x0f, 0x08, 0xf0, 0x0f, 0x01, 0x00, 0xf0, 0x01, 0x02, 0x30, 0x46, + 0x05, 0xf0, 0x37, 0xfb, 0x4d, 0xe1, 0x05, 0xf0, 0x20, 0xfb, 0x07, 0x46, + 0x30, 0x46, 0x05, 0xf0, 0x4b, 0xfb, 0x80, 0x46, 0x30, 0x46, 0x05, 0xf0, + 0x51, 0xfb, 0x3f, 0x02, 0x18, 0xb9, 0x08, 0xf0, 0x1f, 0x00, 0x38, 0x43, + 0x36, 0xe1, 0xb8, 0xf1, 0x13, 0x0f, 0x08, 0xbf, 0x2f, 0x60, 0xe9, 0xd0, + 0x08, 0xf0, 0x0f, 0x00, 0x38, 0x43, 0x40, 0xf0, 0x10, 0x00, 0x2b, 0xe1, + 0x00, 0x2f, 0x40, 0xf0, 0x2f, 0x81, 0x00, 0x20, 0xfe, 0xf7, 0x69, 0xfd, + 0x06, 0x46, 0x00, 0x20, 0xfe, 0xf7, 0x6e, 0xfd, 0x46, 0xea, 0x00, 0x40, + 0x04, 0x90, 0x01, 0x20, 0xfe, 0xf7, 0x5f, 0xfd, 0x06, 0x46, 0x01, 0x20, + 0xfe, 0xf7, 0x64, 0xfd, 0x46, 0xea, 0x00, 0x40, 0x03, 0x90, 0x04, 0x22, + 0x04, 0xa9, 0x28, 0x46, 0x05, 0xf0, 0x1c, 0xfa, 0x04, 0x22, 0x03, 0xa9, + 0x28, 0x1d, 0x02, 0xe1, 0xd9, 0xf8, 0x00, 0x00, 0x00, 0x2f, 0xda, 0xd0, + 0x0f, 0x29, 0x03, 0xd1, 0x28, 0x68, 0xc9, 0xf8, 0x00, 0x00, 0x11, 0xe0, + 0xc3, 0xf3, 0x00, 0x32, 0x02, 0xeb, 0x41, 0x01, 0x14, 0x29, 0x28, 0xbf, + 0x04, 0x24, 0x01, 0x22, 0x02, 0xfa, 0x01, 0xf1, 0x9a, 0x04, 0x4c, 0xbf, + 0x08, 0x43, 0x88, 0x43, 0x00, 0x2c, 0xc9, 0xf8, 0x00, 0x00, 0x01, 0xd1, + 0xfe, 0xf7, 0xfc, 0xfd, 0xf3, 0xe0, 0x56, 0x1e, 0x07, 0x2e, 0xc3, 0xf3, + 0x01, 0x41, 0xbc, 0xd8, 0xdf, 0xe8, 0x06, 0xf0, 0x04, 0x20, 0x57, 0x62, + 0x4c, 0x4c, 0x6c, 0x12, 0x00, 0x2f, 0x67, 0xd0, 0x5f, 0xfa, 0x8c, 0xf1, + 0x01, 0xf0, 0x03, 0x00, 0x49, 0x07, 0x02, 0xd5, 0xfc, 0xf7, 0x9c, 0xff, + 0xdd, 0xe0, 0xfc, 0xf7, 0x8b, 0xff, 0xda, 0xe0, 0x00, 0x2f, 0x76, 0x46, + 0x58, 0xd0, 0x29, 0x46, 0x30, 0x46, 0x03, 0xf0, 0x34, 0xf8, 0x00, 0x28, + 0x52, 0xd0, 0x29, 0x46, 0x30, 0x46, 0x02, 0xf0, 0xe4, 0xff, 0xcc, 0xe0, + 0xc3, 0xf3, 0x83, 0x46, 0x00, 0x2f, 0x18, 0xbf, 0x00, 0x2e, 0x0d, 0x46, + 0x46, 0xd0, 0x00, 0x27, 0x25, 0xfa, 0x07, 0xf0, 0xc0, 0x07, 0x1b, 0xd5, + 0x00, 0x2f, 0x14, 0xbf, 0x09, 0x20, 0x08, 0x20, 0x98, 0xf8, 0x54, 0x10, + 0x03, 0x29, 0x04, 0xd0, 0xd9, 0xf8, 0x20, 0x10, 0xc1, 0x40, 0xc8, 0x07, + 0x04, 0xd4, 0x31, 0x46, 0x38, 0x46, 0x05, 0xf0, 0xe5, 0xfd, 0x09, 0xe0, + 0x38, 0x46, 0x05, 0xf0, 0xc4, 0xfd, 0x08, 0xb1, 0x01, 0x24, 0xa8, 0xe0, + 0x31, 0x46, 0x38, 0x46, 0x05, 0xf0, 0xc7, 0xfd, 0x7f, 0x1c, 0x02, 0x2f, + 0xdc, 0xd3, 0xa0, 0xe0, 0x00, 0x2f, 0x1f, 0xd0, 0x05, 0x2a, 0x0c, 0xbf, + 0x00, 0x20, 0x01, 0x20, 0x0f, 0xfa, 0x8c, 0xf1, 0x06, 0xf0, 0x6e, 0xfb, + 0x95, 0xe0, 0x00, 0x2f, 0x14, 0xd0, 0x0d, 0x46, 0x28, 0x46, 0x07, 0xf0, + 0x6f, 0xff, 0x29, 0x46, 0x00, 0x20, 0x05, 0xf0, 0x56, 0xfd, 0x8a, 0xe0, + 0x00, 0x2f, 0x09, 0xd0, 0x0d, 0x46, 0x01, 0x20, 0x05, 0xf0, 0x4f, 0xfd, + 0x28, 0x46, 0x07, 0xf0, 0x73, 0xff, 0x80, 0xe0, 0x00, 0x2f, 0x0c, 0x46, + 0x7c, 0xd0, 0x98, 0xf8, 0x54, 0x00, 0x03, 0x28, 0x78, 0xd1, 0x00, 0x25, + 0x24, 0xfa, 0x05, 0xf0, 0xc0, 0x07, 0x44, 0xbf, 0x28, 0x46, 0x05, 0xf0, + 0x9c, 0xfd, 0x6d, 0x1c, 0x02, 0x2d, 0xf5, 0xd3, 0x6c, 0xe0, 0x0e, 0xeb, + 0x41, 0x00, 0xc0, 0xb2, 0x06, 0x46, 0x13, 0x2e, 0x01, 0xdb, 0x05, 0x24, + 0x65, 0xe0, 0x7f, 0xb1, 0xfe, 0xf7, 0x58, 0xfd, 0x00, 0x28, 0x60, 0xd1, + 0x56, 0x48, 0x30, 0x5c, 0x08, 0xeb, 0x80, 0x00, 0x02, 0xab, 0x40, 0x68, + 0x40, 0x68, 0x01, 0x22, 0x28, 0x21, 0xfd, 0xf7, 0xe9, 0xfc, 0x54, 0xe0, + 0xfe, 0xf7, 0x48, 0xfd, 0x28, 0x70, 0x50, 0xe0, 0x00, 0x2f, 0x4d, 0xd0, + 0xff, 0xf7, 0x42, 0xfc, 0x4b, 0xe0, 0x27, 0xb1, 0xd5, 0xe9, 0x00, 0x23, + 0x04, 0xf0, 0xa2, 0xfc, 0x13, 0xe0, 0x07, 0xf0, 0xcd, 0xff, 0xc5, 0xe9, + 0x00, 0x01, 0x40, 0xe0, 0x4f, 0xea, 0x8c, 0x56, 0x18, 0x0b, 0xb6, 0x0d, + 0x00, 0xf0, 0x03, 0x00, 0x4f, 0xb1, 0x02, 0x28, 0xa8, 0xbf, 0x07, 0x24, + 0x35, 0xda, 0x0a, 0x46, 0x31, 0x46, 0x08, 0xf0, 0x58, 0xfc, 0x04, 0x46, + 0x2f, 0xe0, 0xea, 0x1c, 0x29, 0x46, 0x08, 0xf0, 0x7a, 0xfc, 0x2a, 0xe0, + 0x7f, 0xb9, 0x03, 0xf0, 0x7f, 0xfc, 0x06, 0x46, 0x04, 0x2e, 0x05, 0xd1, + 0x04, 0xf0, 0x3d, 0xfc, 0x46, 0xea, 0x00, 0x10, 0x00, 0x90, 0x00, 0xe0, + 0x00, 0x96, 0x04, 0x22, 0x69, 0x46, 0x09, 0xe0, 0x0f, 0xb1, 0x02, 0x24, + 0x17, 0xe0, 0x03, 0xf0, 0x63, 0xfc, 0x00, 0xf0, 0x0f, 0x00, 0x01, 0x90, + 0x04, 0x22, 0x01, 0xa9, 0x28, 0x46, 0x05, 0xf0, 0x13, 0xf9, 0x0c, 0xe0, + 0x17, 0xb1, 0x04, 0xf0, 0x20, 0xfc, 0x08, 0xe0, 0x04, 0xf0, 0x21, 0xfc, + 0x28, 0x60, 0x04, 0xe0, 0x17, 0xb1, 0x08, 0xf0, 0x3f, 0xff, 0x00, 0xe0, + 0x03, 0x24, 0xe0, 0xb2, 0x05, 0xb0, 0xbd, 0xe8, 0xf0, 0x83, 0x38, 0xb5, + 0x04, 0x46, 0x1a, 0x48, 0x90, 0xf8, 0xb8, 0x03, 0x0d, 0x46, 0x00, 0xf0, + 0x03, 0x01, 0x03, 0x29, 0xc0, 0xf3, 0x81, 0x00, 0x01, 0xd1, 0xb0, 0xb9, + 0x03, 0xe0, 0x00, 0x29, 0x08, 0xbf, 0x03, 0x28, 0x11, 0xd1, 0x0b, 0x20, + 0x05, 0xf0, 0xea, 0xf9, 0x13, 0x28, 0x01, 0xd1, 0x01, 0x20, 0x32, 0xbd, + 0x1c, 0xb9, 0x0b, 0x20, 0x05, 0xf0, 0x9c, 0xf9, 0x02, 0xe0, 0x0b, 0x20, + 0x05, 0xf0, 0x8f, 0xf9, 0x28, 0x46, 0x01, 0xf0, 0xf9, 0xfe, 0x00, 0x20, + 0x32, 0xbd, 0x08, 0x48, 0xd0, 0xf8, 0xa8, 0x03, 0x70, 0x47, 0x06, 0x48, + 0xd0, 0xf8, 0xb4, 0x03, 0x70, 0x47, 0x04, 0x48, 0xd0, 0xf8, 0xac, 0x03, + 0x70, 0x47, 0x02, 0x48, 0x90, 0xf8, 0x54, 0x00, 0x70, 0x47, 0x00, 0x00, + 0xb8, 0x04, 0x00, 0x20, 0x60, 0xf3, 0x00, 0x20, 0x49, 0x3d, 0x00, 0x01, + 0x08, 0x00, 0x00, 0x49, 0x48, 0xbd, 0x00, 0x20, 0x98, 0x68, 0x01, 0x01, + 0xa8, 0x6f, 0x01, 0x01, 0x00, 0x00, 0x00, 0x20, 0xe8, 0xf2, 0x00, 0x20, + 0xc8, 0x20, 0x00, 0x20, 0xdf, 0xf8, 0x84, 0x07, 0x00, 0x68, 0x70, 0x47, + 0x28, 0x21, 0x42, 0xf6, 0x2c, 0x40, 0xf8, 0xb5, 0x04, 0x46, 0x0d, 0x46, + 0x00, 0x22, 0x00, 0xf0, 0x44, 0xf8, 0x40, 0xf2, 0xc9, 0x66, 0x80, 0x21, + 0x30, 0x46, 0xfe, 0xf7, 0x7b, 0xfa, 0x00, 0x21, 0x30, 0x46, 0xfe, 0xf7, + 0x77, 0xfa, 0xdf, 0xf8, 0x5c, 0x07, 0xdf, 0xf8, 0x5c, 0x17, 0x40, 0x6b, + 0x46, 0x00, 0x30, 0x46, 0x00, 0x27, 0x01, 0xe0, 0x40, 0x08, 0x7f, 0x1c, + 0x88, 0x42, 0xfb, 0xd2, 0x06, 0x2f, 0xb4, 0xbf, 0x01, 0x20, 0x00, 0x20, + 0x03, 0xf0, 0x7d, 0xf9, 0x7a, 0x01, 0xd2, 0xb2, 0xe0, 0x21, 0x00, 0xf0, + 0x23, 0xf8, 0xdf, 0xf8, 0x28, 0x07, 0xfe, 0x40, 0x06, 0x60, 0x04, 0x22, + 0x00, 0xf0, 0x1b, 0xf8, 0xdf, 0xf8, 0x24, 0x07, 0xdf, 0xf8, 0x24, 0x17, + 0xdf, 0xf8, 0x24, 0x27, 0x04, 0x80, 0x45, 0x80, 0x30, 0x20, 0x08, 0x80, + 0xdf, 0xf8, 0x1c, 0x17, 0x08, 0x80, 0x0f, 0x21, 0xdf, 0xf8, 0x18, 0x07, + 0x01, 0x80, 0x30, 0x21, 0x11, 0x80, 0x01, 0x80, 0x70, 0x21, 0x01, 0x80, + 0xb0, 0x21, 0x01, 0x80, 0xf0, 0x21, 0x01, 0x80, 0xf1, 0xbd, 0x04, 0x21, + 0x4f, 0xf4, 0x8c, 0x70, 0xfe, 0xf7, 0x42, 0xba, 0x2d, 0xe9, 0xf8, 0x4f, + 0xdf, 0xf8, 0xf4, 0x66, 0xdf, 0xf8, 0xf4, 0x16, 0xdf, 0xf8, 0xd0, 0x26, + 0x18, 0xb9, 0xd2, 0xe9, 0x06, 0x5b, 0xc8, 0x6a, 0x03, 0xe0, 0xd2, 0xe9, + 0x08, 0x5b, 0x08, 0x6c, 0x50, 0x36, 0x30, 0x21, 0xb0, 0xfb, 0xf1, 0xf9, + 0x50, 0x21, 0x30, 0x46, 0x02, 0xf0, 0x8e, 0xff, 0x01, 0x27, 0x09, 0xfb, + 0x07, 0xf0, 0x00, 0x21, 0x15, 0xeb, 0x00, 0x08, 0x4b, 0xeb, 0x01, 0x0a, + 0x28, 0x1a, 0x6b, 0xeb, 0x01, 0x01, 0x08, 0xf0, 0x83, 0xff, 0x01, 0x21, + 0x00, 0x28, 0x01, 0xfa, 0x07, 0xf4, 0x03, 0xd5, 0xb0, 0x6c, 0x20, 0x43, + 0xb0, 0x64, 0x04, 0xe0, 0x06, 0xeb, 0x80, 0x00, 0x41, 0x6a, 0x21, 0x43, + 0x41, 0x62, 0x40, 0x46, 0x51, 0x46, 0x08, 0xf0, 0x71, 0xff, 0x00, 0x28, + 0x03, 0xd5, 0xf0, 0x6c, 0x20, 0x43, 0xf0, 0x64, 0x04, 0xe0, 0x56, 0xf8, + 0x20, 0x10, 0x21, 0x43, 0x46, 0xf8, 0x20, 0x10, 0x7f, 0x1c, 0x18, 0x2f, + 0xd3, 0xd3, 0xbd, 0xe8, 0xf1, 0x8f, 0x2d, 0xe9, 0xf8, 0x4f, 0x89, 0x46, + 0x17, 0x46, 0xdf, 0xf8, 0x48, 0x16, 0xdf, 0xf8, 0x64, 0x26, 0x15, 0x68, + 0x00, 0x28, 0x07, 0xbf, 0xd0, 0x6a, 0xd1, 0xe9, 0x00, 0x48, 0x10, 0x6c, + 0xd1, 0xe9, 0x02, 0x48, 0x01, 0x09, 0x00, 0x07, 0x2a, 0x46, 0x00, 0x23, + 0x02, 0xf0, 0x08, 0xfc, 0x30, 0x22, 0x00, 0x23, 0x02, 0xf0, 0x04, 0xfc, + 0x06, 0x46, 0x8a, 0x46, 0xdf, 0xb1, 0x07, 0xf1, 0x18, 0x00, 0x31, 0x28, + 0x17, 0xd2, 0xfa, 0x17, 0xa6, 0xfb, 0x07, 0x01, 0x06, 0xfb, 0x02, 0x11, + 0x0a, 0xfb, 0x07, 0x11, 0x27, 0x1a, 0x28, 0x46, 0x68, 0xeb, 0x01, 0x0b, + 0xa0, 0xfb, 0x07, 0x23, 0x00, 0xfb, 0x0b, 0x33, 0x12, 0x0f, 0x42, 0xea, + 0x03, 0x10, 0x19, 0x0f, 0x08, 0xf0, 0x2a, 0xff, 0x05, 0x46, 0x00, 0x2d, + 0x01, 0xd5, 0x00, 0x20, 0x20, 0xe0, 0x3a, 0x46, 0x5b, 0x46, 0x48, 0x46, + 0x08, 0xf0, 0x78, 0xfe, 0x2a, 0x46, 0x20, 0x46, 0x41, 0x46, 0x08, 0xf0, + 0x38, 0xfe, 0x04, 0x46, 0x0f, 0x46, 0x2a, 0x46, 0x30, 0x46, 0x51, 0x46, + 0x08, 0xf0, 0x31, 0xfe, 0x06, 0x46, 0xdf, 0xf8, 0xd8, 0x25, 0x24, 0x09, + 0x00, 0x0f, 0x44, 0xea, 0x07, 0x74, 0x40, 0xea, 0x01, 0x10, 0x14, 0x60, + 0x40, 0xf4, 0x00, 0x40, 0x10, 0x81, 0x30, 0x01, 0x50, 0x60, 0x01, 0x20, + 0xbd, 0xe8, 0xf2, 0x8f, 0xdf, 0xf8, 0xb8, 0x15, 0x08, 0x80, 0x70, 0x47, + 0x4f, 0xf0, 0x82, 0x41, 0x02, 0x68, 0x0a, 0x60, 0x42, 0x68, 0x4a, 0x60, + 0x02, 0x89, 0x0a, 0x81, 0x42, 0x89, 0x4a, 0x81, 0x82, 0x89, 0x8a, 0x81, + 0xc2, 0x89, 0xca, 0x87, 0xdf, 0xf8, 0x98, 0x15, 0x02, 0x8a, 0x0a, 0x80, + 0x40, 0x8a, 0x48, 0x80, 0x00, 0x21, 0xdf, 0xf8, 0x90, 0x05, 0x41, 0x80, + 0x81, 0x82, 0xc1, 0x82, 0x1f, 0x21, 0x01, 0x80, 0x00, 0x21, 0x81, 0x80, + 0xc1, 0x80, 0x70, 0x47, 0x38, 0xb5, 0x0c, 0x46, 0x01, 0xf0, 0x8a, 0xfe, + 0xdf, 0xf8, 0x74, 0x15, 0x02, 0xf0, 0x24, 0xf8, 0x05, 0x46, 0x20, 0x46, + 0x01, 0xf0, 0x82, 0xfe, 0x29, 0x46, 0x02, 0xf0, 0x1d, 0xf8, 0xdf, 0xf8, + 0x64, 0x15, 0x01, 0xf0, 0x8b, 0xfe, 0x08, 0xf0, 0x17, 0xff, 0x04, 0x46, + 0x03, 0xf0, 0xab, 0xf8, 0x20, 0x28, 0x28, 0xbf, 0x1f, 0x20, 0x01, 0x21, + 0x01, 0xfa, 0x00, 0xf2, 0x43, 0x1e, 0xa2, 0x1a, 0x99, 0x40, 0x8a, 0x42, + 0x28, 0xbf, 0x40, 0xf0, 0x20, 0x00, 0x80, 0xb2, 0x32, 0xbd, 0x00, 0xf0, + 0x1f, 0x01, 0x01, 0x22, 0x8a, 0x40, 0xc0, 0xf3, 0x40, 0x10, 0x49, 0x1e, + 0x88, 0x40, 0x80, 0x18, 0x70, 0x47, 0xdf, 0xf8, 0x24, 0x25, 0x4f, 0xf6, + 0xff, 0x73, 0x13, 0x81, 0x01, 0xb1, 0x04, 0x21, 0x00, 0xf0, 0x03, 0x00, + 0x08, 0x18, 0x00, 0x02, 0x40, 0xf4, 0x10, 0x40, 0x10, 0x80, 0x70, 0x47, + 0xdf, 0xf8, 0x04, 0x05, 0x01, 0x88, 0x01, 0xf4, 0x73, 0x61, 0x41, 0xf0, + 0x80, 0x01, 0x01, 0x80, 0x70, 0x47, 0xf0, 0xb5, 0x04, 0x46, 0x0d, 0x46, + 0x83, 0xb0, 0x00, 0xf0, 0x0c, 0xf9, 0xdf, 0xf8, 0xec, 0x64, 0xdf, 0xf8, + 0xec, 0x74, 0xff, 0xf7, 0x3b, 0xfa, 0x30, 0x60, 0x06, 0x21, 0x03, 0x20, + 0x03, 0xf0, 0x8d, 0xf8, 0x4f, 0xf6, 0xff, 0x70, 0xb8, 0x80, 0x4f, 0xf6, + 0xf5, 0x30, 0xb8, 0x81, 0x03, 0x20, 0x03, 0xf0, 0x69, 0xf8, 0x03, 0x20, + 0x03, 0xf0, 0x6c, 0xf8, 0x30, 0x68, 0x00, 0xf0, 0xed, 0xf8, 0x29, 0x46, + 0xe0, 0xb2, 0xff, 0xf7, 0xc4, 0xff, 0x01, 0xa8, 0x00, 0x90, 0x41, 0xf2, + 0x88, 0x33, 0x30, 0x68, 0x03, 0x22, 0x05, 0x21, 0xfd, 0xf7, 0x22, 0xfa, + 0x39, 0x88, 0xc0, 0x07, 0x04, 0xd5, 0x2f, 0x20, 0x03, 0xf0, 0xcf, 0xf8, + 0x01, 0x24, 0x0d, 0xe0, 0x40, 0xf2, 0x0a, 0x40, 0x08, 0x40, 0x02, 0x28, + 0x04, 0xd1, 0x30, 0x20, 0x03, 0xf0, 0xc5, 0xf8, 0x00, 0x24, 0x03, 0xe0, + 0x31, 0x20, 0x03, 0xf0, 0xc0, 0xf8, 0x03, 0x24, 0x00, 0xf0, 0x68, 0xf8, + 0x03, 0x20, 0x03, 0xf0, 0x4a, 0xf8, 0x00, 0x21, 0x00, 0xf0, 0xc8, 0xf8, + 0x20, 0x46, 0xfe, 0xbd, 0x00, 0x28, 0x08, 0xd5, 0xdf, 0xf8, 0x60, 0x34, + 0x40, 0x42, 0x53, 0xf8, 0x20, 0x30, 0x13, 0x60, 0xdf, 0xf8, 0x58, 0x24, + 0x06, 0xe0, 0xdf, 0xf8, 0x58, 0x34, 0x53, 0xf8, 0x20, 0x30, 0x13, 0x60, + 0xdf, 0xf8, 0x50, 0x24, 0x52, 0xf8, 0x20, 0x00, 0x08, 0x60, 0x70, 0x47, + 0xdf, 0xf8, 0x48, 0x14, 0xdf, 0xf8, 0x48, 0x34, 0x08, 0x22, 0x0a, 0x80, + 0x00, 0x22, 0x4a, 0x83, 0x8a, 0x83, 0x00, 0x21, 0xdf, 0xf8, 0x3c, 0x24, + 0x11, 0x80, 0x30, 0xf8, 0x11, 0x20, 0x23, 0xf8, 0x11, 0x20, 0x49, 0x1c, + 0x18, 0x29, 0xf8, 0xd3, 0xdf, 0xf8, 0x2c, 0x14, 0x42, 0x8e, 0x0a, 0x80, + 0xc2, 0x8e, 0x4a, 0x82, 0x02, 0x8f, 0x8a, 0x82, 0x42, 0x8f, 0xca, 0x82, + 0x82, 0x8f, 0x0a, 0x83, 0xc2, 0x8f, 0x4a, 0x83, 0xb0, 0xf8, 0x40, 0x00, + 0x88, 0x83, 0x00, 0x20, 0x48, 0x80, 0x88, 0x80, 0x70, 0x47, 0x10, 0xb5, + 0x01, 0xb1, 0x04, 0x21, 0x00, 0xf0, 0x03, 0x00, 0x08, 0x18, 0xdf, 0xf8, + 0xd0, 0x13, 0xdf, 0xf8, 0xc0, 0x33, 0x00, 0x02, 0x08, 0x80, 0x40, 0xf4, + 0x30, 0x40, 0x94, 0x8e, 0x5c, 0x82, 0x40, 0xf0, 0x40, 0x00, 0x4f, 0xf6, + 0xff, 0x74, 0x0c, 0x81, 0x9c, 0x8a, 0x44, 0xf4, 0x7f, 0x44, 0x9c, 0x82, + 0x1c, 0x8b, 0x44, 0xf4, 0x00, 0x44, 0x1c, 0x83, 0x12, 0x8e, 0x1a, 0x80, + 0x08, 0x80, 0x10, 0xbd, 0xdf, 0xf8, 0x98, 0x03, 0x01, 0x88, 0x01, 0xf4, + 0x73, 0x61, 0x41, 0xf4, 0x03, 0x51, 0x01, 0x80, 0x70, 0x47, 0x2d, 0xe9, + 0xfc, 0x41, 0x06, 0x46, 0x0f, 0x46, 0x90, 0x46, 0x00, 0xf0, 0x55, 0xf8, + 0xdf, 0xf8, 0x7c, 0x43, 0xdf, 0xf8, 0x7c, 0x53, 0xff, 0xf7, 0x84, 0xf9, + 0x20, 0x60, 0x06, 0x21, 0x03, 0x20, 0x02, 0xf0, 0xd6, 0xff, 0x4f, 0xf6, + 0xff, 0x70, 0xa8, 0x80, 0x4f, 0xf6, 0x35, 0x30, 0xa8, 0x81, 0x03, 0x20, + 0x02, 0xf0, 0xb2, 0xff, 0x03, 0x20, 0x02, 0xf0, 0xb5, 0xff, 0x42, 0x46, + 0x39, 0x46, 0x30, 0x46, 0xff, 0xf7, 0xb3, 0xff, 0x01, 0xa8, 0x00, 0x90, + 0x41, 0xf2, 0x88, 0x33, 0x20, 0x68, 0x03, 0x22, 0x05, 0x21, 0xfd, 0xf7, + 0x6d, 0xf9, 0x02, 0x46, 0x28, 0x88, 0xd2, 0x07, 0x04, 0xd5, 0x2f, 0x20, + 0x03, 0xf0, 0x19, 0xf8, 0x01, 0x25, 0x13, 0xe0, 0x4f, 0xf4, 0x99, 0x62, + 0x10, 0x42, 0x04, 0xd0, 0x31, 0x20, 0x03, 0xf0, 0x10, 0xf8, 0x02, 0x25, + 0x0a, 0xe0, 0x80, 0x07, 0x04, 0xd5, 0x30, 0x20, 0x03, 0xf0, 0x09, 0xf8, + 0x00, 0x25, 0x03, 0xe0, 0x31, 0x20, 0x03, 0xf0, 0x04, 0xf8, 0x03, 0x25, + 0xff, 0xf7, 0xac, 0xff, 0x03, 0x20, 0x02, 0xf0, 0x8e, 0xff, 0x20, 0x68, + 0x00, 0xf0, 0x06, 0xf8, 0x00, 0x21, 0x00, 0xf0, 0x09, 0xf8, 0x28, 0x46, + 0xbd, 0xe8, 0xf6, 0x81, 0x01, 0xab, 0x00, 0x22, 0x04, 0x21, 0xfd, 0xf7, + 0xc9, 0xb9, 0x01, 0x21, 0x2d, 0x20, 0x02, 0xf0, 0xfc, 0xbf, 0x00, 0xf5, + 0x4a, 0x70, 0x00, 0x23, 0x03, 0x60, 0x01, 0x71, 0x42, 0x71, 0x70, 0x47, + 0x30, 0xb5, 0x00, 0x24, 0x00, 0x23, 0x50, 0xf8, 0x24, 0x20, 0x01, 0xeb, + 0xc4, 0x05, 0x64, 0x1c, 0xc5, 0xe9, 0x00, 0x23, 0x18, 0x2c, 0xf6, 0xd3, + 0x30, 0xbd, 0x30, 0xb5, 0x00, 0x24, 0x50, 0xf8, 0x24, 0x20, 0x01, 0xeb, + 0xc4, 0x05, 0xd3, 0x17, 0xc5, 0xe9, 0x00, 0x23, 0x64, 0x1c, 0x18, 0x2c, + 0xf5, 0xd3, 0x30, 0xbd, 0x70, 0xb5, 0x02, 0x46, 0x0b, 0x46, 0x00, 0x26, + 0x03, 0xeb, 0xc6, 0x00, 0x00, 0x21, 0xd0, 0xe9, 0x00, 0x45, 0x52, 0xf8, + 0x26, 0x00, 0x00, 0xf0, 0x11, 0xf8, 0xf5, 0xd3, 0x70, 0xbd, 0x70, 0xb5, + 0x02, 0x46, 0x0b, 0x46, 0x00, 0x26, 0x03, 0xeb, 0xc6, 0x00, 0xd0, 0xe9, + 0x00, 0x45, 0x52, 0xf8, 0x26, 0x00, 0xc1, 0x17, 0x00, 0xf0, 0x02, 0xf8, + 0xf5, 0xd3, 0x70, 0xbd, 0x20, 0x18, 0x03, 0xeb, 0xc6, 0x04, 0x69, 0x41, + 0xc4, 0xe9, 0x00, 0x01, 0x76, 0x1c, 0x18, 0x2e, 0x70, 0x47, 0x2d, 0xe9, + 0xf0, 0x47, 0x04, 0x46, 0x04, 0xf5, 0x16, 0x75, 0xd4, 0xf8, 0x28, 0x13, + 0xdf, 0xf8, 0x3c, 0x82, 0xdf, 0xf8, 0x3c, 0x92, 0xdf, 0xf8, 0x2c, 0xa2, + 0xdf, 0xf8, 0x2c, 0x02, 0x00, 0x29, 0x04, 0xf5, 0xc8, 0x76, 0x04, 0xf1, + 0xc8, 0x07, 0x21, 0x46, 0x11, 0xd0, 0xff, 0xf7, 0xc1, 0xff, 0x39, 0x46, + 0x50, 0x46, 0xff, 0xf7, 0xbd, 0xff, 0x31, 0x46, 0x48, 0x46, 0xff, 0xf7, + 0xc8, 0xff, 0x29, 0x46, 0x40, 0x46, 0xff, 0xf7, 0xc4, 0xff, 0xd4, 0xf8, + 0x28, 0x03, 0x40, 0x1c, 0x0e, 0xe0, 0xff, 0xf7, 0x95, 0xff, 0x39, 0x46, + 0x50, 0x46, 0xff, 0xf7, 0x91, 0xff, 0x31, 0x46, 0x48, 0x46, 0xff, 0xf7, + 0x9a, 0xff, 0x29, 0x46, 0x40, 0x46, 0xff, 0xf7, 0x96, 0xff, 0x01, 0x20, + 0xc4, 0xf8, 0x28, 0x03, 0xbd, 0xe8, 0xf0, 0x87, 0xc1, 0xb2, 0x01, 0xeb, + 0x10, 0x20, 0x70, 0x47, 0xf0, 0xb5, 0x4b, 0x6e, 0x03, 0x66, 0x01, 0x22, + 0x00, 0x24, 0x00, 0x25, 0x00, 0x23, 0x17, 0x26, 0x02, 0x27, 0x0a, 0xe0, + 0x01, 0xeb, 0x83, 0x0c, 0xdc, 0xf8, 0x04, 0xc0, 0xa4, 0x45, 0xd8, 0xbf, + 0x64, 0x46, 0x65, 0x45, 0xb8, 0xbf, 0x65, 0x46, 0x5b, 0x1c, 0x9e, 0x42, + 0xf2, 0xd2, 0x19, 0x23, 0x2f, 0x26, 0x7f, 0x1e, 0xf9, 0xd1, 0x23, 0x46, + 0x2c, 0x46, 0x6f, 0xf3, 0x0b, 0x04, 0xb4, 0xf1, 0x00, 0x6f, 0x6f, 0xf3, + 0x0b, 0x03, 0x04, 0xdc, 0x13, 0xf1, 0x00, 0x6f, 0x04, 0xdb, 0x00, 0x24, + 0x17, 0xe0, 0xb4, 0xf1, 0x80, 0x5f, 0x05, 0xda, 0x13, 0xf1, 0x80, 0x5f, + 0x05, 0xdb, 0x01, 0x24, 0x01, 0x25, 0x13, 0xe0, 0xb4, 0xf1, 0x00, 0x5f, + 0x04, 0xda, 0x13, 0xf1, 0x00, 0x5f, 0x04, 0xdb, 0x02, 0x24, 0x06, 0xe0, + 0xb4, 0xf1, 0x80, 0x4f, 0x05, 0xda, 0x13, 0xf1, 0x80, 0x4f, 0x02, 0xdb, + 0x03, 0x24, 0x25, 0x46, 0x02, 0xe0, 0x03, 0x24, 0x03, 0x25, 0x00, 0x22, + 0x00, 0x23, 0x17, 0x26, 0x02, 0x27, 0x08, 0xe0, 0x01, 0xeb, 0x83, 0x0c, + 0xdc, 0xf8, 0x04, 0xc0, 0x4c, 0xfa, 0x05, 0xfc, 0x40, 0xf8, 0x23, 0xc0, + 0x5b, 0x1c, 0x9e, 0x42, 0xf4, 0xd2, 0x19, 0x23, 0x2f, 0x26, 0x7f, 0x1e, + 0xf9, 0xd1, 0x44, 0xf0, 0x30, 0x03, 0x20, 0xf8, 0xc0, 0x3f, 0x09, 0x68, + 0x41, 0x60, 0x10, 0x46, 0xf0, 0xbd, 0x3e, 0xb5, 0x0f, 0xf2, 0x34, 0x12, + 0x38, 0xca, 0x69, 0x46, 0x03, 0x28, 0x38, 0xc1, 0x34, 0xbf, 0x5d, 0xf8, + 0x20, 0x00, 0x00, 0x20, 0x3e, 0xbd, 0x70, 0xb5, 0x0f, 0xf2, 0x10, 0x13, + 0x84, 0xb0, 0x70, 0xcb, 0x6a, 0x46, 0x03, 0x28, 0x70, 0xc2, 0x11, 0xd2, + 0x5d, 0xf8, 0x20, 0x00, 0x01, 0xfa, 0x00, 0xf2, 0x03, 0x23, 0x03, 0xfa, + 0x00, 0xf0, 0x19, 0x42, 0x40, 0xf0, 0xc0, 0x00, 0x06, 0xd0, 0x81, 0xb2, + 0x92, 0xb2, 0x24, 0x48, 0x00, 0xf0, 0xaf, 0xf8, 0x01, 0x20, 0x00, 0xe0, + 0x00, 0x20, 0x04, 0xb0, 0x70, 0xbd, 0x20, 0x49, 0x09, 0x88, 0x01, 0x80, + 0x32, 0x49, 0x09, 0x88, 0x41, 0x80, 0x70, 0x47, 0x10, 0xb5, 0x04, 0x46, + 0x1b, 0x48, 0x21, 0x88, 0x00, 0xf0, 0xfa, 0xf8, 0x61, 0x88, 0x2d, 0x48, + 0xbd, 0xe8, 0x10, 0x40, 0x00, 0xf0, 0xf4, 0xb8, 0x10, 0xb5, 0x00, 0x03, + 0x0c, 0x46, 0x00, 0xf4, 0x40, 0x52, 0x4f, 0xf4, 0x40, 0x51, 0x13, 0x48, + 0x00, 0xf0, 0xfa, 0xf8, 0x04, 0xf0, 0x3c, 0x01, 0xbd, 0xe8, 0x10, 0x40, + 0xff, 0xe7, 0x23, 0x48, 0x00, 0xf0, 0xe2, 0xb8, 0x80, 0xb5, 0x22, 0x49, + 0x4f, 0xf6, 0xff, 0x70, 0x08, 0x80, 0x6b, 0x46, 0x14, 0x48, 0x00, 0x68, + 0x01, 0x22, 0x04, 0x21, 0xfd, 0xf7, 0x82, 0xf8, 0x01, 0xbd, 0x00, 0x00, + 0x80, 0xf3, 0x00, 0x20, 0x00, 0xf2, 0x00, 0x20, 0x01, 0xd0, 0x12, 0x13, + 0xfc, 0x01, 0x00, 0x41, 0xc0, 0x02, 0x00, 0x41, 0xc0, 0x06, 0x00, 0x41, + 0xc0, 0x04, 0x00, 0x41, 0x02, 0x08, 0x00, 0x41, 0x08, 0xef, 0x00, 0x20, + 0x78, 0x29, 0x00, 0x20, 0x40, 0x00, 0x00, 0x41, 0x0c, 0x00, 0x00, 0x41, + 0x58, 0x00, 0x00, 0x41, 0xb0, 0x00, 0x00, 0x41, 0xbd, 0x37, 0x86, 0x35, + 0x00, 0x00, 0x40, 0x42, 0x00, 0x08, 0x00, 0x41, 0x7c, 0xf3, 0x00, 0x20, + 0x08, 0x08, 0x00, 0x41, 0x00, 0x16, 0x00, 0x41, 0x80, 0x16, 0x00, 0x41, + 0x00, 0x17, 0x00, 0x41, 0x80, 0x17, 0x00, 0x41, 0x3e, 0x00, 0x00, 0x41, + 0x80, 0x00, 0x00, 0x41, 0x04, 0x08, 0x00, 0x41, 0xb2, 0x00, 0x00, 0x41, + 0xfe, 0x01, 0x00, 0x41, 0x14, 0x08, 0x00, 0x41, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x41, + 0x00, 0x04, 0x00, 0x41, 0x00, 0x06, 0x00, 0x41, 0xdf, 0xf8, 0x10, 0x14, + 0x28, 0x22, 0x02, 0xfb, 0x00, 0x10, 0x81, 0x7f, 0xc2, 0x7f, 0x90, 0xf8, + 0x20, 0x00, 0x41, 0xea, 0x02, 0x21, 0x41, 0xea, 0x00, 0x40, 0x70, 0x47, + 0xdf, 0xf8, 0xf4, 0x13, 0x28, 0x22, 0x02, 0xfb, 0x00, 0x10, 0x10, 0xf8, + 0x21, 0x1f, 0x40, 0x78, 0x00, 0xf0, 0x07, 0x00, 0x41, 0xea, 0x00, 0x20, + 0x70, 0x47, 0xef, 0xf3, 0x11, 0x80, 0x60, 0x21, 0x81, 0xf3, 0x11, 0x88, + 0xdf, 0xf8, 0xd4, 0x13, 0xdf, 0xf8, 0xd4, 0x33, 0x09, 0x68, 0x4f, 0xf0, + 0x00, 0x42, 0x1a, 0x60, 0x70, 0x47, 0xdf, 0xf8, 0xc4, 0x33, 0x01, 0xf0, + 0x00, 0x42, 0x1a, 0x60, 0x80, 0xf3, 0x11, 0x88, 0x70, 0x47, 0x70, 0xb5, + 0x00, 0xf0, 0x56, 0xf8, 0x00, 0xf0, 0x79, 0xf8, 0xbd, 0xe8, 0x70, 0x40, + 0xef, 0xe7, 0x2d, 0xe9, 0xf0, 0x41, 0x06, 0x46, 0x88, 0x46, 0xff, 0xf7, + 0xdc, 0xff, 0x00, 0xf0, 0x36, 0xf8, 0x20, 0xb1, 0x41, 0x46, 0x30, 0x46, + 0xfd, 0xf7, 0x3e, 0xfe, 0x01, 0x27, 0x20, 0x46, 0x29, 0x46, 0xff, 0xf7, + 0xde, 0xff, 0x38, 0x46, 0xbd, 0xe8, 0xf0, 0x81, 0xf8, 0xb5, 0x04, 0x46, + 0x0d, 0x46, 0x16, 0x46, 0x01, 0x20, 0x00, 0x27, 0x00, 0xe0, 0x7f, 0x1c, + 0xb7, 0x42, 0x06, 0xd2, 0x79, 0x5d, 0x34, 0xf8, 0x17, 0x00, 0xff, 0xf7, + 0xdc, 0xff, 0x00, 0x28, 0xf5, 0xd1, 0xf2, 0xbd, 0x2d, 0xe9, 0xf8, 0x43, + 0x06, 0x46, 0x89, 0x46, 0x90, 0x46, 0xff, 0xf7, 0xb4, 0xff, 0x00, 0xf0, + 0x0e, 0xf8, 0x28, 0xb1, 0x42, 0x46, 0x49, 0x46, 0x30, 0x46, 0xfd, 0xf7, + 0x1f, 0xfe, 0x01, 0x27, 0x20, 0x46, 0x29, 0x46, 0xff, 0xf7, 0xb5, 0xff, + 0x38, 0x46, 0xbd, 0xe8, 0xf2, 0x83, 0x04, 0x46, 0xdf, 0xf8, 0x2c, 0x03, + 0x00, 0x78, 0x00, 0x27, 0x0d, 0x46, 0x70, 0x47, 0x70, 0xb5, 0x00, 0xf0, + 0x06, 0xf8, 0x00, 0xf0, 0x17, 0xf8, 0x0a, 0xb1, 0x25, 0x70, 0x01, 0x26, + 0x0e, 0xe0, 0x04, 0x46, 0x0d, 0x46, 0x90, 0xe7, 0x04, 0x46, 0x0d, 0x46, + 0x16, 0x46, 0x8c, 0xe7, 0x70, 0xb5, 0xff, 0xf7, 0xf6, 0xff, 0x00, 0xf0, + 0x07, 0xf8, 0x0a, 0xb1, 0x25, 0x80, 0x01, 0x26, 0xff, 0xf7, 0x91, 0xff, + 0x30, 0x46, 0x70, 0xbd, 0xba, 0x4a, 0x12, 0x78, 0x00, 0x26, 0x70, 0x47, + 0xf8, 0xb5, 0xff, 0xf7, 0xe9, 0xff, 0x00, 0xf0, 0x08, 0xf8, 0x12, 0xb1, + 0x00, 0xf0, 0x09, 0xf8, 0x01, 0x27, 0xff, 0xf7, 0x80, 0xff, 0x38, 0x46, + 0xf2, 0xbd, 0xb2, 0x4a, 0x12, 0x78, 0x00, 0x27, 0x70, 0x47, 0x22, 0x88, + 0xaa, 0x43, 0x05, 0xea, 0x06, 0x03, 0x1a, 0x43, 0x22, 0x80, 0x70, 0x47, + 0x70, 0xb5, 0xff, 0xf7, 0xce, 0xff, 0xff, 0xf7, 0xdf, 0xff, 0x0a, 0xb1, + 0x25, 0x60, 0x01, 0x26, 0xd6, 0xe7, 0x10, 0xb5, 0x04, 0x46, 0x04, 0x22, + 0x21, 0x46, 0x0f, 0xf2, 0xb4, 0x20, 0xfd, 0xf7, 0xee, 0xfd, 0x01, 0x22, + 0x21, 0x1d, 0x0f, 0xf2, 0xb0, 0x20, 0xfd, 0xf7, 0xe8, 0xfd, 0xa2, 0x48, + 0x00, 0x68, 0xa0, 0x60, 0x10, 0xbd, 0x38, 0xb5, 0x04, 0x46, 0x0d, 0x46, + 0x04, 0x22, 0x21, 0x46, 0x0f, 0xf2, 0x8c, 0x20, 0xff, 0xf7, 0x74, 0xff, + 0x55, 0xb9, 0xa0, 0x68, 0x9a, 0x49, 0x08, 0x60, 0x21, 0x1d, 0xbd, 0xe8, + 0x38, 0x40, 0x01, 0x22, 0x0f, 0xf2, 0x7c, 0x20, 0xfd, 0xf7, 0xbc, 0xbd, + 0x31, 0xbd, 0x38, 0xb5, 0x20, 0xb9, 0x01, 0x24, 0x40, 0xf6, 0x12, 0x05, + 0x80, 0x21, 0x03, 0xe0, 0x02, 0x24, 0x40, 0xf6, 0x13, 0x05, 0x40, 0x21, + 0x00, 0x22, 0x40, 0xf6, 0x14, 0x00, 0xff, 0xf7, 0x69, 0xff, 0x00, 0x22, + 0xc0, 0x21, 0x28, 0x46, 0xff, 0xf7, 0x64, 0xff, 0x21, 0x46, 0x4f, 0xf4, + 0x82, 0x70, 0xff, 0xf7, 0x38, 0xff, 0xbd, 0xe8, 0x38, 0x40, 0x00, 0x22, + 0x33, 0x21, 0x4f, 0xf4, 0xa9, 0x60, 0x57, 0xe7, 0x80, 0xb5, 0x85, 0x48, + 0x01, 0x6d, 0x03, 0x20, 0x01, 0xf0, 0x0e, 0xfa, 0x03, 0x20, 0x01, 0xf0, + 0x23, 0xfa, 0x18, 0xb9, 0xff, 0xf7, 0x45, 0xf8, 0x00, 0x28, 0xf7, 0xd0, + 0xbd, 0xe8, 0x02, 0x40, 0x03, 0x20, 0x01, 0xf0, 0x91, 0xb9, 0x77, 0x48, + 0x90, 0xf8, 0x43, 0x20, 0x04, 0xe0, 0x75, 0x48, 0x90, 0xf8, 0x6b, 0x00, + 0x40, 0xf0, 0x20, 0x02, 0x3f, 0x21, 0x40, 0xf6, 0x15, 0x00, 0x37, 0xe7, + 0x2d, 0xe9, 0xf1, 0x4f, 0x84, 0xb0, 0x07, 0xf0, 0x0c, 0xfd, 0x01, 0x20, + 0xff, 0xf7, 0xde, 0xfe, 0x04, 0x46, 0x01, 0x20, 0xff, 0xf7, 0xcc, 0xfe, + 0x82, 0x46, 0x03, 0x20, 0xff, 0xf7, 0xd6, 0xfe, 0x05, 0x46, 0x03, 0x20, + 0xff, 0xf7, 0xc4, 0xfe, 0x06, 0x46, 0x6c, 0x48, 0x6c, 0x4a, 0x41, 0x78, + 0x00, 0x78, 0x13, 0x78, 0x40, 0xea, 0x01, 0x20, 0x40, 0x05, 0x40, 0x0d, + 0x01, 0x21, 0x03, 0xf0, 0x03, 0x07, 0x02, 0x2f, 0x4f, 0xf0, 0x00, 0x0b, + 0x08, 0xbf, 0x02, 0x21, 0x02, 0xd0, 0x03, 0x2f, 0x08, 0xbf, 0x04, 0x21, + 0xdf, 0x06, 0x48, 0xbf, 0x49, 0x00, 0x9b, 0x06, 0x48, 0xbf, 0x49, 0x00, + 0x52, 0x78, 0x52, 0x07, 0x4c, 0xbf, 0x01, 0xeb, 0x81, 0x01, 0x89, 0x00, + 0x00, 0x91, 0x02, 0x27, 0x54, 0x49, 0x91, 0xf8, 0x89, 0x20, 0x91, 0xf8, + 0x39, 0x10, 0x8b, 0x1a, 0x01, 0x2b, 0x03, 0xdb, 0x07, 0xfa, 0x01, 0xf1, + 0x01, 0x27, 0x08, 0xe0, 0x00, 0x2b, 0x03, 0xd5, 0x59, 0x42, 0x8c, 0x40, + 0x0a, 0xfa, 0x01, 0xfa, 0x07, 0xfa, 0x02, 0xf1, 0x00, 0x27, 0x05, 0xfa, + 0x07, 0xf2, 0xa2, 0x1a, 0x50, 0x4b, 0x03, 0xfb, 0x02, 0xa2, 0x01, 0x92, + 0x48, 0x43, 0x01, 0x9b, 0x00, 0x9a, 0xc1, 0x17, 0x06, 0xfa, 0x07, 0xf4, + 0xcd, 0xe9, 0x02, 0x01, 0x1b, 0x1b, 0x83, 0xfb, 0x02, 0x89, 0x00, 0x25, + 0x07, 0xe0, 0xae, 0x19, 0x01, 0x99, 0x00, 0x98, 0x06, 0xfa, 0x07, 0xf2, + 0x89, 0x1a, 0x81, 0xfb, 0x00, 0x89, 0xdd, 0xe9, 0x02, 0x23, 0x40, 0x46, + 0x49, 0x46, 0x01, 0xf0, 0xf9, 0xfe, 0xdd, 0xe9, 0x02, 0x23, 0x04, 0x46, + 0x8a, 0x46, 0xa2, 0xfb, 0x04, 0x01, 0x02, 0xfb, 0x0a, 0x11, 0x03, 0xfb, + 0x04, 0x11, 0xb8, 0xeb, 0x00, 0x00, 0x79, 0xeb, 0x01, 0x01, 0x08, 0xbf, + 0x00, 0x28, 0x08, 0xd0, 0x00, 0x2d, 0xde, 0xd1, 0x38, 0x48, 0x86, 0x42, + 0xac, 0xbf, 0x4f, 0xf0, 0xff, 0x35, 0x01, 0x25, 0xd7, 0xe7, 0xb5, 0xb1, + 0x30, 0x02, 0x01, 0x0e, 0x40, 0xf2, 0x45, 0x30, 0xff, 0xf7, 0x81, 0xfe, + 0x30, 0x04, 0x01, 0x0e, 0x4f, 0xf4, 0x51, 0x70, 0xff, 0xf7, 0x7b, 0xfe, + 0xf1, 0xb2, 0x40, 0xf2, 0x43, 0x30, 0xff, 0xf7, 0x76, 0xfe, 0x00, 0x22, + 0x00, 0x21, 0x40, 0xf2, 0x41, 0x30, 0xff, 0xf7, 0x97, 0xfe, 0x60, 0x42, + 0x00, 0x02, 0x23, 0x4e, 0x00, 0x0a, 0x40, 0xf0, 0x40, 0x70, 0x30, 0x60, + 0x20, 0x22, 0x4f, 0xf4, 0x80, 0x50, 0x70, 0x60, 0x20, 0x21, 0x40, 0xf6, + 0x15, 0x00, 0xff, 0xf7, 0x87, 0xfe, 0x00, 0x22, 0x01, 0x21, 0x4f, 0xf4, + 0x60, 0x70, 0xfd, 0xf7, 0xaf, 0xfc, 0x04, 0x98, 0x01, 0x28, 0x23, 0xdb, + 0x30, 0x68, 0x04, 0x99, 0x20, 0xf0, 0xf0, 0x40, 0x40, 0xea, 0xc1, 0x60, + 0x40, 0xf0, 0x80, 0x60, 0x30, 0x60, 0x4f, 0xf4, 0x7a, 0x71, 0x03, 0x20, + 0x01, 0xf0, 0x2c, 0xf9, 0x30, 0x68, 0x40, 0x01, 0x07, 0xd5, 0x03, 0x20, + 0x01, 0xf0, 0x3e, 0xf9, 0x18, 0xb9, 0xfe, 0xf7, 0x60, 0xff, 0x00, 0x28, + 0xf4, 0xd0, 0x30, 0x68, 0x40, 0x01, 0x04, 0xd5, 0xfe, 0xf7, 0x59, 0xff, + 0x08, 0xb9, 0x4f, 0xf0, 0x01, 0x0b, 0x03, 0x20, 0x01, 0xf0, 0xa6, 0xf8, + 0x58, 0x46, 0x05, 0xb0, 0xbd, 0xe8, 0xf0, 0x8f, 0x68, 0xee, 0x00, 0x20, + 0x00, 0xe1, 0x00, 0xe0, 0x80, 0xe1, 0x00, 0xe0, 0x65, 0x2c, 0x00, 0x20, + 0x10, 0x00, 0x00, 0x45, 0x4c, 0x1f, 0x00, 0x20, 0x41, 0x01, 0x00, 0x46, + 0x01, 0x01, 0x00, 0x46, 0x00, 0xf8, 0x7f, 0x00, 0x01, 0xfc, 0x3f, 0x00, + 0x48, 0x05, 0x12, 0x08, 0x13, 0x08, 0x14, 0x08, 0x80, 0x03, 0x00, 0x00, + 0x10, 0xb5, 0x00, 0x24, 0x00, 0x21, 0xe0, 0xb2, 0x00, 0xf0, 0xad, 0xf8, + 0x01, 0x21, 0xe0, 0xb2, 0x00, 0xf0, 0xe1, 0xf8, 0x64, 0x1c, 0x02, 0x2c, + 0xf4, 0xd3, 0x10, 0xbd, 0x70, 0xb5, 0x04, 0x46, 0x0d, 0x46, 0xff, 0xf7, + 0xe4, 0xfe, 0x00, 0x2c, 0x0c, 0xbf, 0x01, 0x21, 0x10, 0x21, 0x40, 0xf2, + 0x49, 0x50, 0xfd, 0xf7, 0x45, 0xfc, 0x2e, 0x00, 0x18, 0xbf, 0x01, 0x2d, + 0x04, 0xd1, 0x7e, 0x21, 0x40, 0xf2, 0x0b, 0x20, 0xfd, 0xf7, 0x3c, 0xfc, + 0x00, 0x2c, 0x0c, 0xbf, 0x00, 0x20, 0x04, 0x20, 0x05, 0xf0, 0x03, 0x01, + 0x01, 0xfa, 0x00, 0xf2, 0x03, 0x21, 0x81, 0x40, 0xd2, 0xb2, 0xc9, 0xb2, + 0x4f, 0xf4, 0xa9, 0x60, 0xff, 0xf7, 0x08, 0xfe, 0x01, 0x2d, 0x18, 0xbf, + 0x02, 0x2d, 0x10, 0xd1, 0x00, 0x2c, 0x07, 0xbf, 0x08, 0x24, 0x40, 0xf2, + 0x42, 0x50, 0x10, 0x24, 0x40, 0xf2, 0x43, 0x50, 0x00, 0x22, 0xc0, 0x21, + 0xff, 0xf7, 0xf8, 0xfd, 0x21, 0x46, 0x4f, 0xf4, 0x82, 0x70, 0xff, 0xf7, + 0xcc, 0xfd, 0x01, 0x20, 0x70, 0xbd, 0xff, 0xf7, 0x97, 0xbe, 0x00, 0xb1, + 0x04, 0x20, 0x41, 0x49, 0x09, 0x78, 0xc1, 0x40, 0x01, 0xf0, 0x03, 0x00, + 0x70, 0x47, 0x10, 0xb5, 0x02, 0x46, 0x00, 0x21, 0x53, 0x68, 0x18, 0x46, + 0x01, 0xf0, 0xca, 0xfb, 0x08, 0xd2, 0x10, 0x68, 0x3a, 0x4c, 0x19, 0x46, + 0x01, 0xf0, 0x2e, 0xf9, 0x20, 0x60, 0x00, 0x20, 0xc4, 0xe9, 0x02, 0x00, + 0x10, 0xbd, 0x38, 0xb5, 0x36, 0x4a, 0x35, 0x4d, 0xd2, 0xe9, 0x08, 0x01, + 0xd5, 0xe9, 0x02, 0x23, 0x99, 0x42, 0x08, 0xbf, 0x90, 0x42, 0x3f, 0xd0, + 0xc5, 0xe9, 0x02, 0x01, 0x31, 0x4a, 0x00, 0x23, 0x01, 0xf0, 0x16, 0xfe, + 0x00, 0x24, 0x80, 0xb2, 0xb0, 0xf5, 0x95, 0x7f, 0xb8, 0xbf, 0xff, 0x24, + 0x1a, 0xdb, 0xb0, 0xf5, 0xd5, 0x6f, 0x17, 0xdc, 0x40, 0xf2, 0x29, 0x11, + 0x40, 0x1a, 0x00, 0xb2, 0x41, 0x11, 0x00, 0xeb, 0x91, 0x61, 0x89, 0x02, + 0x09, 0x0c, 0x0f, 0xf2, 0x74, 0x12, 0x8b, 0x5c, 0xa0, 0xeb, 0x81, 0x10, + 0x89, 0x18, 0x00, 0xb2, 0x49, 0x78, 0x59, 0x1a, 0x48, 0x43, 0x41, 0x11, + 0x00, 0xeb, 0x91, 0x60, 0xa3, 0xeb, 0xa0, 0x14, 0xe0, 0xb2, 0x01, 0xf0, + 0xe3, 0xf8, 0x29, 0x68, 0x01, 0xf0, 0x7e, 0xfa, 0x01, 0xf0, 0xe8, 0xfa, + 0x84, 0xb2, 0xff, 0x2c, 0xc8, 0xbf, 0xff, 0x24, 0xe1, 0xb2, 0x40, 0xf2, + 0x44, 0x50, 0xfd, 0xf7, 0xb5, 0xfb, 0xe1, 0xb2, 0xbd, 0xe8, 0x34, 0x40, + 0x40, 0xf2, 0x45, 0x50, 0xfd, 0xf7, 0xae, 0xbb, 0x31, 0xbd, 0x00, 0x28, + 0x0c, 0xbf, 0x40, 0xf2, 0x46, 0x50, 0x40, 0xf2, 0x47, 0x50, 0x01, 0xf0, + 0x03, 0x02, 0x03, 0x21, 0xfd, 0xf7, 0xac, 0xbb, 0x70, 0xb5, 0x04, 0x46, + 0x0d, 0x46, 0x08, 0xf0, 0x6d, 0xf9, 0x2f, 0x26, 0x03, 0x28, 0x08, 0xd1, + 0x00, 0x21, 0x8d, 0x42, 0x08, 0x48, 0x03, 0xd8, 0x84, 0x42, 0x38, 0xbf, + 0x2d, 0x26, 0x00, 0xd3, 0x2e, 0x26, 0x30, 0x46, 0x70, 0xbd, 0x00, 0x00, + 0x48, 0x05, 0x00, 0x46, 0x08, 0xf3, 0x00, 0x20, 0x00, 0xf2, 0x00, 0x20, + 0x40, 0x42, 0x0f, 0x00, 0x00, 0x28, 0x6b, 0xee, 0x00, 0x28, 0x0c, 0xbf, + 0x40, 0xf2, 0x5e, 0x40, 0x40, 0xf2, 0x5f, 0x40, 0xfd, 0xf7, 0x7c, 0xbb, + 0x00, 0xf0, 0x0f, 0x02, 0x0f, 0x21, 0x4f, 0xf4, 0xc1, 0x70, 0xfd, 0xf7, + 0x7f, 0xbb, 0x00, 0x28, 0x0c, 0xbf, 0x40, 0xf2, 0x46, 0x50, 0x40, 0xf2, + 0x47, 0x50, 0x89, 0x00, 0x01, 0xf0, 0x0c, 0x02, 0x0c, 0x21, 0xfd, 0xf7, + 0x73, 0xbb, 0x00, 0x28, 0x0c, 0xbf, 0x4f, 0xf4, 0xa8, 0x60, 0x40, 0xf2, + 0x41, 0x50, 0x8a, 0x01, 0xd2, 0xb2, 0xc0, 0x21, 0xfd, 0xf7, 0x68, 0xbb, + 0x00, 0x28, 0x0c, 0xbf, 0x4f, 0xf4, 0xa8, 0x60, 0x40, 0xf2, 0x41, 0x50, + 0x01, 0xf0, 0x3f, 0x02, 0x3f, 0x21, 0xfd, 0xf7, 0x5d, 0xbb, 0x10, 0xb5, + 0x00, 0xf0, 0x17, 0xf8, 0xfd, 0xf7, 0x7f, 0xfb, 0x21, 0x46, 0xbd, 0xe8, + 0x10, 0x40, 0x05, 0x22, 0x0f, 0xf2, 0x48, 0x00, 0xfd, 0xf7, 0x77, 0xbb, + 0x10, 0xb5, 0x00, 0xf0, 0x0a, 0xf8, 0xff, 0xf7, 0x0b, 0xfd, 0x21, 0x46, + 0xbd, 0xe8, 0x10, 0x40, 0x05, 0x22, 0x0f, 0xf2, 0x30, 0x00, 0xfd, 0xf7, + 0x57, 0xbb, 0x04, 0x46, 0x03, 0x22, 0x61, 0x1d, 0x0f, 0xf2, 0x2c, 0x00, + 0x70, 0x47, 0x00, 0xb1, 0x04, 0x20, 0x01, 0xf0, 0x01, 0x01, 0x01, 0xfa, + 0x00, 0xf2, 0x01, 0x21, 0x81, 0x40, 0xd2, 0xb2, 0xc9, 0xb2, 0x4f, 0xf4, + 0xaa, 0x60, 0xfd, 0xf7, 0x2f, 0xbb, 0x00, 0x00, 0x40, 0x05, 0x41, 0x05, + 0x50, 0x05, 0x49, 0x05, 0x0b, 0x02, 0x00, 0x00, 0x48, 0x05, 0x42, 0x05, + 0x43, 0x05, 0x00, 0x00, 0xff, 0xc1, 0x97, 0x7a, 0x65, 0x57, 0x4b, 0x42, + 0x3a, 0x33, 0x2d, 0x27, 0x22, 0x1d, 0x1a, 0x16, 0x13, 0x10, 0x0d, 0x0a, + 0x06, 0x03, 0x00, 0x00, 0x70, 0xb5, 0x04, 0x46, 0x00, 0x25, 0x0f, 0xf2, + 0x60, 0x66, 0x36, 0xf9, 0x15, 0x20, 0xe9, 0xb2, 0x20, 0x46, 0x00, 0xf0, + 0x29, 0xf8, 0x6d, 0x1c, 0x04, 0x2d, 0xf6, 0xd3, 0x70, 0xbd, 0x10, 0xb5, + 0x08, 0x22, 0x08, 0x21, 0x4f, 0xf4, 0x8c, 0x70, 0xfd, 0xf7, 0x02, 0xfb, + 0x00, 0x24, 0x20, 0x46, 0xff, 0xf7, 0xe6, 0xff, 0x64, 0x1c, 0x02, 0x2c, + 0xf9, 0xd3, 0xdf, 0xf8, 0xac, 0x05, 0x4f, 0xf4, 0x80, 0x71, 0x81, 0x61, + 0x42, 0x6a, 0x42, 0xf4, 0x80, 0x72, 0x42, 0x62, 0x01, 0x60, 0x13, 0x20, + 0x06, 0x21, 0x02, 0xf0, 0x5c, 0xfa, 0x13, 0x20, 0x02, 0xf0, 0x3e, 0xfa, + 0xbd, 0xe8, 0x10, 0x40, 0x13, 0x20, 0x02, 0xf0, 0x3f, 0xba, 0x00, 0x00, + 0x2d, 0xe9, 0xf8, 0x43, 0x14, 0x46, 0x05, 0x46, 0x27, 0x12, 0x01, 0x20, + 0x03, 0x29, 0x00, 0xfa, 0x05, 0xf6, 0x40, 0xf6, 0x1c, 0x28, 0x3b, 0xd8, + 0xdf, 0xe8, 0x01, 0xf0, 0x02, 0x1a, 0x21, 0x27, 0x0f, 0xf2, 0xcc, 0x56, + 0xa0, 0x05, 0x01, 0x0e, 0x36, 0xf8, 0x25, 0x00, 0xfd, 0xf7, 0xc2, 0xfa, + 0x06, 0xeb, 0x85, 0x00, 0x04, 0xf0, 0x03, 0x04, 0x45, 0x88, 0x44, 0xf0, + 0x80, 0x01, 0x28, 0x46, 0xfd, 0xf7, 0xb8, 0xfa, 0x00, 0xbf, 0x00, 0xbf, + 0x00, 0xbf, 0x21, 0x46, 0x28, 0x46, 0x1b, 0xe0, 0x0f, 0xf2, 0xa4, 0x59, + 0x00, 0xf0, 0x1e, 0xf8, 0x07, 0xf0, 0x3f, 0x01, 0x0a, 0xe0, 0x0f, 0xf2, + 0xa8, 0x50, 0x30, 0xf8, 0x15, 0x00, 0xe1, 0xb2, 0x0e, 0xe0, 0x0f, 0xf2, + 0xa0, 0x59, 0x00, 0xf0, 0x11, 0xf8, 0xf9, 0xb2, 0x09, 0xeb, 0x85, 0x00, + 0x40, 0x88, 0xfd, 0xf7, 0x9b, 0xfa, 0x00, 0xbf, 0x00, 0xbf, 0x00, 0xbf, + 0xf1, 0xb2, 0x40, 0x46, 0xbd, 0xe8, 0xf4, 0x43, 0xfd, 0xf7, 0x92, 0xba, + 0xbd, 0xe8, 0xf1, 0x83, 0x39, 0xf8, 0x25, 0x00, 0xe1, 0xb2, 0xfd, 0xf7, + 0x8b, 0xba, 0x10, 0xb5, 0x82, 0xb0, 0xdf, 0xf8, 0xe0, 0x44, 0xfe, 0xf7, + 0xa7, 0xfb, 0x20, 0x60, 0x01, 0x21, 0x2e, 0x20, 0x02, 0xf0, 0x6d, 0xfa, + 0x20, 0x68, 0x6b, 0x46, 0x00, 0x22, 0x04, 0x21, 0xfc, 0xf7, 0x30, 0xfc, + 0x4f, 0xf0, 0x8a, 0x40, 0x01, 0x68, 0x61, 0x60, 0x41, 0x68, 0x01, 0xf4, + 0xa0, 0x71, 0x41, 0xf0, 0x11, 0x01, 0x41, 0x60, 0x13, 0xbd, 0x30, 0xb5, + 0x83, 0xb0, 0xfe, 0xf7, 0x8d, 0xfb, 0xdf, 0xf8, 0xa4, 0x14, 0x08, 0x60, + 0x01, 0xa9, 0x00, 0x91, 0x41, 0xf2, 0x88, 0x33, 0x03, 0x22, 0x05, 0x21, + 0xfc, 0xf7, 0x8a, 0xfb, 0xc0, 0x07, 0x4f, 0xf0, 0x8a, 0x44, 0x04, 0xd5, + 0x2f, 0x20, 0x02, 0xf0, 0x36, 0xfa, 0x01, 0x25, 0x0b, 0xe0, 0xa0, 0x68, + 0xc0, 0x07, 0x04, 0xd5, 0x30, 0x20, 0x02, 0xf0, 0x2e, 0xfa, 0x00, 0x25, + 0x03, 0xe0, 0x31, 0x20, 0x02, 0xf0, 0x29, 0xfa, 0x02, 0x25, 0xa0, 0x68, + 0xc0, 0x07, 0x07, 0xd4, 0x20, 0x68, 0x20, 0xf0, 0x7e, 0x50, 0x20, 0x60, + 0x60, 0x68, 0x40, 0xf0, 0x01, 0x00, 0x60, 0x60, 0x00, 0x21, 0x2e, 0x20, + 0x02, 0xf0, 0x29, 0xfa, 0x28, 0x46, 0x3e, 0xbd, 0xdf, 0xf8, 0x44, 0x04, + 0x01, 0x68, 0x41, 0xf0, 0x02, 0x01, 0x01, 0x60, 0x70, 0x47, 0x4f, 0xf0, + 0x8a, 0x41, 0x08, 0x60, 0x70, 0x47, 0x02, 0x68, 0x22, 0xf0, 0x7e, 0x52, + 0x42, 0xea, 0xc1, 0x51, 0x01, 0x60, 0x70, 0x47, 0x01, 0x21, 0x00, 0xf0, + 0x1f, 0x02, 0x91, 0x40, 0xc0, 0xf3, 0x41, 0x10, 0x48, 0x43, 0x01, 0xeb, + 0x90, 0x00, 0x70, 0x47, 0x10, 0xb5, 0x04, 0x46, 0x02, 0xf0, 0x6f, 0xf9, + 0x01, 0x21, 0x81, 0x40, 0x62, 0x1a, 0x89, 0x08, 0xb2, 0xfb, 0xf1, 0xf1, + 0x40, 0xea, 0x41, 0x10, 0xc0, 0xb2, 0x10, 0xbd, 0xdf, 0xf8, 0xf4, 0x13, + 0x0a, 0x68, 0x22, 0xf0, 0xf2, 0x02, 0x00, 0xf0, 0x0f, 0x00, 0x42, 0xea, + 0x00, 0x10, 0x40, 0xf0, 0x04, 0x00, 0x08, 0x60, 0x70, 0x47, 0xdf, 0xf8, + 0xdc, 0x03, 0x01, 0x68, 0x21, 0xf0, 0x04, 0x01, 0xc5, 0xe7, 0x10, 0xb5, + 0xd3, 0x07, 0x12, 0xd5, 0x0f, 0xf2, 0x2c, 0x43, 0x33, 0xf8, 0x20, 0x40, + 0x04, 0xf1, 0x8c, 0x44, 0x03, 0xeb, 0x80, 0x03, 0x24, 0x78, 0xa4, 0x00, + 0x0c, 0x80, 0x5b, 0x88, 0x03, 0xf1, 0x8c, 0x43, 0x1b, 0x78, 0x03, 0xf0, + 0x03, 0x03, 0x23, 0x43, 0x0b, 0x80, 0x92, 0x07, 0x17, 0xd5, 0x0f, 0xf2, + 0x0c, 0x42, 0x32, 0xf8, 0x20, 0x30, 0x03, 0xf1, 0x8c, 0x43, 0x02, 0xeb, + 0x80, 0x00, 0x1b, 0x78, 0x4b, 0x80, 0x40, 0x88, 0x00, 0xf1, 0x8c, 0x40, + 0x00, 0x78, 0x00, 0xf0, 0x3f, 0x00, 0x43, 0xea, 0x00, 0x20, 0x82, 0x04, + 0x48, 0x80, 0x02, 0xd5, 0xde, 0x4a, 0x10, 0x43, 0x48, 0x80, 0x10, 0xbd, + 0x00, 0x21, 0xdd, 0x4a, 0x52, 0xf8, 0x21, 0x20, 0x40, 0xf8, 0x21, 0x20, + 0x49, 0x1c, 0x38, 0x29, 0xf7, 0xd3, 0x70, 0x47, 0x2d, 0xe9, 0xf0, 0x47, + 0x0d, 0x46, 0xd8, 0x49, 0x49, 0x69, 0x92, 0x46, 0xd7, 0x4a, 0x12, 0x78, + 0x04, 0x46, 0x01, 0x20, 0x13, 0x07, 0x48, 0xbf, 0x04, 0x20, 0x02, 0xd4, + 0x52, 0x07, 0x48, 0xbf, 0x02, 0x20, 0x48, 0x43, 0xd2, 0x49, 0x88, 0x42, + 0x2c, 0xbf, 0x0f, 0xf2, 0xc4, 0x38, 0x0f, 0xf2, 0xb4, 0x38, 0x00, 0x27, + 0x05, 0xeb, 0xc7, 0x00, 0x00, 0xf1, 0x60, 0x06, 0xd6, 0xe9, 0x00, 0x01, + 0x00, 0xf0, 0x84, 0xfe, 0x00, 0xf0, 0xdf, 0xf8, 0xe1, 0x68, 0x00, 0xf0, + 0xbd, 0xff, 0xe0, 0x60, 0xd6, 0xe9, 0x06, 0x01, 0x00, 0xf0, 0x7a, 0xfe, + 0x00, 0xf0, 0xd5, 0xf8, 0x21, 0x69, 0x00, 0xf0, 0xb3, 0xff, 0x20, 0x61, + 0xd6, 0xe9, 0x0c, 0x01, 0x00, 0xf0, 0x70, 0xfe, 0x00, 0xf0, 0xcb, 0xf8, + 0x61, 0x69, 0x00, 0xf0, 0xa9, 0xff, 0x60, 0x61, 0xd6, 0xe9, 0x12, 0x01, + 0x00, 0xf0, 0x66, 0xfe, 0x00, 0xf0, 0xc1, 0xf8, 0xa1, 0x69, 0x00, 0xf0, + 0x9f, 0xff, 0x7f, 0x1c, 0x03, 0x2f, 0xa0, 0x61, 0xd0, 0xd3, 0x00, 0x27, + 0x00, 0xf0, 0xbb, 0xf8, 0x00, 0xf0, 0xb2, 0xf8, 0x21, 0x68, 0x00, 0xf0, + 0x93, 0xff, 0x00, 0xf0, 0xbd, 0xf8, 0x00, 0xf0, 0xab, 0xf8, 0x61, 0x68, + 0x00, 0xf0, 0x8c, 0xff, 0x60, 0x60, 0xd9, 0xe9, 0x06, 0x01, 0x00, 0xf0, + 0x49, 0xfe, 0x00, 0xf0, 0xa1, 0xf8, 0xa1, 0x68, 0x00, 0xf0, 0x82, 0xff, + 0x02, 0x2f, 0xa0, 0x60, 0xe4, 0xd3, 0x01, 0x27, 0x00, 0xf0, 0x9f, 0xf8, + 0x00, 0xf0, 0x96, 0xf8, 0x21, 0x68, 0x00, 0xf0, 0x77, 0xff, 0x00, 0xf0, + 0xa1, 0xf8, 0x00, 0xf0, 0x8f, 0xf8, 0x61, 0x68, 0x00, 0xf0, 0x70, 0xff, + 0x60, 0x60, 0xd9, 0xe9, 0x0c, 0x01, 0x00, 0xf0, 0x2d, 0xfe, 0x00, 0xf0, + 0x85, 0xf8, 0xa1, 0x68, 0x00, 0xf0, 0x66, 0xff, 0x02, 0x2f, 0xa0, 0x60, + 0xe4, 0xd3, 0xc0, 0x35, 0xd5, 0xe9, 0x00, 0x01, 0x00, 0xf0, 0x20, 0xfe, + 0xe1, 0x69, 0x00, 0xf0, 0x5b, 0xff, 0xe0, 0x61, 0xd5, 0xe9, 0x02, 0x01, + 0x00, 0xf0, 0x18, 0xfe, 0x21, 0x6a, 0x00, 0xf0, 0x53, 0xff, 0x20, 0x62, + 0xd5, 0xe9, 0x04, 0x01, 0x00, 0xf0, 0x10, 0xfe, 0x61, 0x6a, 0x00, 0xf0, + 0x4b, 0xff, 0x60, 0x62, 0xd5, 0xe9, 0x06, 0x01, 0x00, 0xf0, 0x08, 0xfe, + 0xa1, 0x6a, 0x00, 0xf0, 0x43, 0xff, 0xa0, 0x62, 0x50, 0x46, 0x00, 0xf0, + 0x3d, 0xfe, 0xe1, 0x6a, 0x00, 0xf0, 0x3c, 0xff, 0xe1, 0x69, 0x05, 0x46, + 0xe5, 0x62, 0x08, 0x46, 0x00, 0xf0, 0xd2, 0xff, 0x29, 0x46, 0x00, 0xf0, + 0x41, 0xfe, 0x01, 0x46, 0x20, 0x68, 0x00, 0xf0, 0xbb, 0xfe, 0x60, 0x63, + 0x25, 0x6a, 0x28, 0x46, 0x29, 0x46, 0x00, 0xf0, 0xc5, 0xff, 0x00, 0xf0, + 0x3c, 0xf8, 0x01, 0x46, 0x60, 0x68, 0x00, 0xf0, 0xaf, 0xfe, 0xa0, 0x63, + 0x29, 0x46, 0xe0, 0x69, 0x00, 0xf0, 0xba, 0xff, 0x00, 0xf0, 0x31, 0xf8, + 0x01, 0x46, 0xa0, 0x68, 0x00, 0xf0, 0xa4, 0xfe, 0xe0, 0x63, 0x66, 0x6a, + 0x00, 0xf0, 0x2c, 0xf8, 0x00, 0xf0, 0x27, 0xf8, 0x01, 0x46, 0xe0, 0x68, + 0x00, 0xf0, 0x9a, 0xfe, 0x20, 0x64, 0x29, 0x46, 0x30, 0x46, 0x00, 0xf0, + 0xa5, 0xff, 0x00, 0xf0, 0x1c, 0xf8, 0x01, 0x46, 0x60, 0x69, 0x00, 0xf0, + 0x8f, 0xfe, 0xa0, 0x64, 0xa6, 0x6a, 0x00, 0xf0, 0x17, 0xf8, 0x00, 0xf0, + 0x12, 0xf8, 0x01, 0x46, 0x20, 0x69, 0x00, 0xf0, 0x85, 0xfe, 0x60, 0x64, + 0x29, 0x46, 0x30, 0x46, 0x00, 0xf0, 0x90, 0xff, 0x00, 0xf0, 0x07, 0xf8, + 0x01, 0x46, 0xa0, 0x69, 0x00, 0xf0, 0x7a, 0xfe, 0xe0, 0x64, 0xbd, 0xe8, + 0xf0, 0x87, 0xe1, 0x6a, 0x00, 0xf0, 0xf6, 0xbd, 0xe0, 0x69, 0x31, 0x46, + 0x00, 0xf0, 0x80, 0xbf, 0x71, 0x68, 0x00, 0xf0, 0x7d, 0xbf, 0x58, 0xf8, + 0x27, 0x10, 0x00, 0xf0, 0x79, 0xbf, 0x78, 0x42, 0x05, 0xeb, 0xc7, 0x09, + 0x08, 0xeb, 0x80, 0x06, 0xd9, 0xe9, 0x00, 0x01, 0x00, 0xf0, 0x96, 0xbd, + 0x20, 0x60, 0x7f, 0x1c, 0xd9, 0xe9, 0x12, 0x01, 0x00, 0xf0, 0x90, 0xbd, + 0x30, 0xb5, 0xb9, 0xb0, 0x04, 0x46, 0x0d, 0x46, 0x68, 0x46, 0xff, 0xf7, + 0xd9, 0xfe, 0x2a, 0x46, 0x69, 0x46, 0x20, 0x46, 0xff, 0xf7, 0xde, 0xfe, + 0x39, 0xb0, 0x30, 0xbd, 0x2d, 0xe9, 0xf8, 0x43, 0x04, 0x46, 0x04, 0xf1, + 0xc0, 0x07, 0x0d, 0x46, 0xd7, 0xe9, 0x02, 0x01, 0x90, 0x46, 0x00, 0xf0, + 0x77, 0xfd, 0x06, 0x46, 0xd7, 0xe9, 0x00, 0x01, 0x00, 0xf0, 0x72, 0xfd, + 0x07, 0x46, 0x40, 0x46, 0x00, 0xf0, 0xaa, 0xfd, 0x80, 0x46, 0xd4, 0xe9, + 0x00, 0x01, 0x00, 0xf0, 0x69, 0xfd, 0x81, 0x46, 0x38, 0x46, 0x39, 0x46, + 0x00, 0xf0, 0x3e, 0xff, 0x41, 0x46, 0x00, 0xf0, 0xad, 0xfd, 0x01, 0x46, + 0x48, 0x46, 0x00, 0xf0, 0x27, 0xfe, 0x07, 0x46, 0xd4, 0xe9, 0x12, 0x01, + 0x00, 0xf0, 0x58, 0xfd, 0x04, 0x46, 0x30, 0x46, 0xff, 0xf7, 0xab, 0xff, + 0x41, 0x46, 0x00, 0xf0, 0x9d, 0xfd, 0x01, 0x46, 0x20, 0x46, 0x00, 0xf0, + 0x17, 0xfe, 0x39, 0x46, 0x00, 0xf0, 0x88, 0xfe, 0x41, 0x46, 0x00, 0xf0, + 0x93, 0xfd, 0x29, 0x46, 0x01, 0xf0, 0x26, 0xf8, 0x94, 0xbf, 0x01, 0x20, + 0x00, 0x20, 0xbd, 0xe8, 0xf2, 0x83, 0x10, 0xb5, 0x28, 0x49, 0x20, 0x4c, + 0x82, 0xb0, 0x4f, 0xf4, 0x80, 0x70, 0x08, 0x60, 0x6b, 0x46, 0x20, 0x68, + 0x01, 0x22, 0x04, 0x21, 0xfc, 0xf7, 0x04, 0xfa, 0x60, 0x68, 0x4f, 0xf0, + 0x8a, 0x41, 0x08, 0x60, 0x13, 0xbd, 0x38, 0xb5, 0x04, 0x46, 0x0d, 0x46, + 0x28, 0x46, 0xff, 0xf7, 0xf0, 0xfc, 0x05, 0xf1, 0x08, 0x00, 0xff, 0xf7, + 0x42, 0xf9, 0x01, 0x21, 0xe0, 0xb2, 0xff, 0xf7, 0xe9, 0xfb, 0x1a, 0x4a, + 0xd2, 0xe9, 0x08, 0x01, 0xff, 0xf7, 0x94, 0xfc, 0x01, 0x46, 0xe0, 0xb2, + 0xff, 0xf7, 0xae, 0xfc, 0x00, 0x20, 0xff, 0xf7, 0xb3, 0xfc, 0x03, 0x21, + 0xe0, 0xb2, 0xff, 0xf7, 0xc2, 0xfc, 0x3f, 0x21, 0xe0, 0xb2, 0xff, 0xf7, + 0xc9, 0xfc, 0xff, 0xf7, 0x2c, 0xfc, 0xff, 0xf7, 0x0e, 0xfc, 0x00, 0x2c, + 0x0c, 0xbf, 0x02, 0x20, 0x03, 0x20, 0xbd, 0xe8, 0x34, 0x40, 0x28, 0x21, + 0xff, 0xf7, 0x30, 0xb9, 0x28, 0x00, 0x00, 0x50, 0x58, 0xf3, 0x00, 0x20, + 0x04, 0x00, 0x00, 0x45, 0x04, 0x00, 0x00, 0x51, 0x00, 0xc0, 0xff, 0xff, + 0x00, 0x01, 0x00, 0x45, 0x78, 0x29, 0x00, 0x20, 0x10, 0x09, 0x00, 0x46, + 0x01, 0x1c, 0x4e, 0x0e, 0x40, 0x00, 0x00, 0x50, 0x00, 0xf2, 0x00, 0x20, + 0x38, 0xb5, 0x04, 0x46, 0x0d, 0x46, 0x07, 0xf0, 0x53, 0xfe, 0x28, 0x60, + 0x29, 0x1d, 0x20, 0x46, 0xbd, 0xe8, 0x34, 0x40, 0xaf, 0xe7, 0x10, 0xb5, + 0x04, 0x46, 0x04, 0xf1, 0x08, 0x00, 0xff, 0xf7, 0xfd, 0xf8, 0x20, 0x46, + 0xbd, 0xe8, 0x10, 0x40, 0xff, 0xf7, 0xa8, 0xbc, 0x38, 0xb5, 0x04, 0x46, + 0x0d, 0x46, 0x28, 0x1d, 0xff, 0xf7, 0xef, 0xff, 0x29, 0x68, 0x20, 0x46, + 0xbd, 0xe8, 0x34, 0x40, 0x07, 0xf0, 0x3e, 0xbe, 0x00, 0x07, 0x01, 0x07, + 0x02, 0x07, 0x03, 0x07, 0x12, 0x0a, 0x13, 0x0a, 0x1f, 0x0a, 0x20, 0x0a, + 0xee, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0x09, 0xab, 0x09, + 0x10, 0x0a, 0x11, 0x0a, 0x1d, 0x0a, 0x1e, 0x0a, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xb3, 0x7b, 0x72, 0x3e, + 0x99, 0xbb, 0x06, 0x3f, 0xb3, 0x7b, 0x72, 0x3e, 0x0f, 0x4a, 0x80, 0x04, + 0x80, 0x0c, 0x10, 0x60, 0x88, 0x04, 0x80, 0x0c, 0x50, 0x60, 0x70, 0x47, + 0x0c, 0x4a, 0x10, 0x60, 0x51, 0x60, 0x70, 0x47, 0x4f, 0xf0, 0xa2, 0x41, + 0x0a, 0x68, 0x22, 0xf0, 0x80, 0x42, 0x42, 0xea, 0x80, 0x70, 0x08, 0x60, + 0x48, 0x68, 0x40, 0xf0, 0x08, 0x00, 0x48, 0x60, 0x70, 0x47, 0x05, 0x48, + 0x01, 0x68, 0x21, 0xf0, 0x08, 0x01, 0x01, 0x60, 0x70, 0x47, 0x00, 0x00, + 0x0c, 0x00, 0x00, 0x51, 0x20, 0x00, 0x00, 0x51, 0x04, 0x00, 0x00, 0x51, + 0x38, 0xb5, 0xdf, 0xf8, 0x90, 0x46, 0xa8, 0x21, 0x20, 0x46, 0x01, 0xf0, + 0x05, 0xfd, 0x00, 0x25, 0xfc, 0xf7, 0x1c, 0xfd, 0x54, 0x21, 0x01, 0xfb, + 0x05, 0x41, 0x6d, 0x1c, 0x02, 0x2d, 0x08, 0x64, 0xf6, 0xd3, 0x0f, 0xf2, + 0xd8, 0x61, 0xdf, 0xf8, 0x70, 0x06, 0x1c, 0xc9, 0x1c, 0xc0, 0x31, 0xbd, + 0x2d, 0xe9, 0xf0, 0x47, 0xdf, 0xf8, 0x64, 0x06, 0x84, 0xb0, 0x80, 0x7a, + 0x0c, 0x46, 0x00, 0xf0, 0x03, 0x09, 0xff, 0xf7, 0xdd, 0xff, 0x00, 0x27, + 0x00, 0x26, 0x0d, 0xf1, 0x04, 0x0a, 0x29, 0xfa, 0x06, 0xf0, 0xc0, 0x07, + 0x4f, 0xd5, 0xdf, 0xf8, 0x40, 0x06, 0x26, 0x60, 0x00, 0xf1, 0x40, 0x01, + 0x61, 0x60, 0x54, 0x22, 0x00, 0xf1, 0x0c, 0x01, 0xa1, 0x60, 0x01, 0x25, + 0xdf, 0xf8, 0x24, 0x16, 0x02, 0xfb, 0x06, 0x18, 0x06, 0x21, 0x01, 0xfb, + 0x06, 0x00, 0x6c, 0x30, 0xe0, 0x61, 0xc4, 0xf8, 0x0c, 0x80, 0x20, 0x46, + 0x00, 0xf0, 0x18, 0xfb, 0x29, 0x46, 0x20, 0x46, 0x00, 0xf0, 0x8c, 0xfa, + 0x07, 0x00, 0x19, 0xd1, 0xe1, 0x69, 0x60, 0x68, 0x01, 0xeb, 0x45, 0x01, + 0x00, 0x91, 0x14, 0x21, 0x01, 0xfb, 0x05, 0x01, 0x0b, 0x1d, 0xb0, 0xf9, + 0x02, 0x20, 0x01, 0x88, 0x20, 0x68, 0x01, 0xf0, 0x5a, 0xfb, 0x00, 0xb1, + 0x05, 0x20, 0x4a, 0xf8, 0x25, 0x00, 0x20, 0xb9, 0xe0, 0x69, 0x10, 0xf8, + 0x15, 0x00, 0x5a, 0x28, 0x00, 0xda, 0x05, 0x27, 0x29, 0x46, 0x20, 0x46, + 0x00, 0xf0, 0xa6, 0xfa, 0xc7, 0xb9, 0xe1, 0x69, 0x11, 0xf8, 0x15, 0x20, + 0x08, 0xeb, 0x85, 0x00, 0x48, 0x30, 0x01, 0xeb, 0x45, 0x01, 0x42, 0x80, + 0x6d, 0x1e, 0x49, 0x78, 0x01, 0x80, 0xcd, 0xd5, 0xe0, 0x68, 0x50, 0x30, + 0x01, 0x21, 0x41, 0x80, 0x01, 0x80, 0x76, 0x1c, 0x02, 0x2e, 0xa8, 0xd3, + 0x38, 0x46, 0x04, 0xb0, 0xbd, 0xe8, 0xf0, 0x87, 0xe0, 0x68, 0x50, 0x30, + 0x00, 0x21, 0x41, 0x80, 0x01, 0x80, 0xf5, 0xe7, 0x70, 0x47, 0x2d, 0xe9, + 0xf0, 0x4f, 0x0c, 0x46, 0x8b, 0xb0, 0xdf, 0xf8, 0x7c, 0x15, 0x20, 0x60, + 0x01, 0xf1, 0x40, 0x02, 0x62, 0x60, 0x54, 0x23, 0x01, 0xf1, 0x0c, 0x02, + 0xa2, 0x60, 0x4f, 0xf4, 0x84, 0x5a, 0xdf, 0xf8, 0x60, 0x25, 0x03, 0xfb, + 0x00, 0x22, 0xe2, 0x60, 0x06, 0x22, 0x02, 0xfb, 0x00, 0x10, 0x6c, 0x30, + 0xe0, 0x61, 0xfb, 0xf7, 0x99, 0xfd, 0xe0, 0x68, 0x01, 0x6c, 0x41, 0x64, + 0xfc, 0xf7, 0x7c, 0xfc, 0x01, 0x46, 0xe0, 0x68, 0x01, 0x64, 0x52, 0x46, + 0xc1, 0x6b, 0x49, 0x1c, 0xc1, 0x63, 0x08, 0x21, 0x07, 0xf0, 0x72, 0xfe, + 0xe0, 0x68, 0xe1, 0x69, 0xb0, 0xf8, 0x4a, 0x00, 0x08, 0x70, 0xe0, 0x68, + 0xe1, 0x69, 0xb0, 0xf8, 0x48, 0x00, 0x48, 0x70, 0xe0, 0x68, 0xe1, 0x69, + 0xb0, 0xf8, 0x4e, 0x00, 0x88, 0x70, 0xe0, 0x68, 0xe1, 0x69, 0xb0, 0xf8, + 0x4c, 0x00, 0xc8, 0x70, 0xfb, 0xf7, 0x89, 0xfd, 0x20, 0x46, 0x00, 0xf0, + 0x8f, 0xfa, 0xe0, 0x68, 0xb0, 0xf8, 0x50, 0x00, 0x10, 0xb9, 0x4f, 0xf0, + 0x05, 0x09, 0x65, 0xe0, 0x01, 0x26, 0x49, 0xf2, 0xb2, 0x27, 0x32, 0x46, + 0x69, 0x46, 0x20, 0x46, 0x00, 0xf0, 0x67, 0xf8, 0x5f, 0xea, 0x00, 0x09, + 0x5a, 0xd1, 0x01, 0x2e, 0x05, 0xd1, 0xe0, 0x68, 0x3a, 0x46, 0x00, 0x21, + 0x07, 0xf0, 0x40, 0xfe, 0xba, 0x46, 0x76, 0x1e, 0xed, 0xd5, 0xfb, 0xf7, + 0x53, 0xfd, 0x00, 0x26, 0xdf, 0xf8, 0xc4, 0xa4, 0xdf, 0xf8, 0xc4, 0x84, + 0x68, 0x46, 0x14, 0x21, 0x01, 0xfb, 0x06, 0x05, 0x01, 0x21, 0x28, 0x68, + 0x07, 0xf0, 0x6e, 0xfe, 0xe7, 0x68, 0x0c, 0x21, 0x01, 0xfb, 0x06, 0x7b, + 0x41, 0x46, 0x00, 0xf0, 0x5d, 0xfd, 0x51, 0x46, 0x00, 0xf0, 0x5a, 0xfd, + 0x00, 0xf0, 0xc4, 0xfd, 0xcb, 0xf8, 0x14, 0x00, 0x51, 0x46, 0x68, 0x68, + 0x00, 0xf0, 0x52, 0xfd, 0x00, 0xf0, 0xbc, 0xfd, 0xcb, 0xf8, 0x18, 0x00, + 0x51, 0x46, 0xa8, 0x68, 0x00, 0xf0, 0x4a, 0xfd, 0x00, 0xf0, 0xb4, 0xfd, + 0xcb, 0xf8, 0x1c, 0x00, 0x01, 0x21, 0xe8, 0x68, 0x07, 0xf0, 0x4c, 0xfe, + 0x01, 0x46, 0x40, 0x46, 0x00, 0xf0, 0x3e, 0xfd, 0x51, 0x46, 0x00, 0xf0, + 0x3b, 0xfd, 0x07, 0xeb, 0xc6, 0x07, 0x00, 0xf0, 0xa3, 0xfd, 0xf8, 0x62, + 0x01, 0x21, 0x28, 0x69, 0x07, 0xf0, 0x3c, 0xfe, 0x41, 0x46, 0x00, 0xf0, + 0x2f, 0xfd, 0x51, 0x46, 0x00, 0xf0, 0x2c, 0xfd, 0x00, 0xf0, 0x96, 0xfd, + 0x76, 0x1c, 0x02, 0x2e, 0x38, 0x63, 0xb9, 0xdb, 0xfb, 0xf7, 0x1b, 0xfd, + 0x49, 0xf6, 0xe4, 0x2a, 0xe0, 0x68, 0x52, 0x46, 0x49, 0x46, 0x07, 0xf0, + 0xe7, 0xfd, 0x48, 0x46, 0x0b, 0xb0, 0xbd, 0xe8, 0xf0, 0x8f, 0x2d, 0xe9, + 0xf7, 0x4f, 0x92, 0xb0, 0x00, 0x24, 0x12, 0x98, 0x03, 0x94, 0x02, 0x94, + 0xa0, 0x46, 0x00, 0x68, 0x14, 0x99, 0x01, 0x90, 0x12, 0x98, 0x00, 0xf0, + 0x83, 0xf9, 0x00, 0x90, 0x10, 0xb1, 0x00, 0xf0, 0xe7, 0xf8, 0xd7, 0xe0, + 0x12, 0x98, 0xc0, 0x69, 0x14, 0x99, 0x10, 0xf8, 0x11, 0x10, 0x01, 0x98, + 0x03, 0xf0, 0x91, 0xfe, 0xa3, 0x46, 0x77, 0xe0, 0x00, 0x26, 0x04, 0xaa, + 0x04, 0xa8, 0x32, 0xf9, 0x26, 0x20, 0x00, 0xeb, 0x86, 0x0a, 0xd3, 0x17, + 0xa2, 0xfb, 0x02, 0x57, 0xba, 0xf9, 0x02, 0x00, 0x02, 0xfb, 0x03, 0x77, + 0x03, 0xfb, 0x02, 0x77, 0xc1, 0x17, 0xa0, 0xfb, 0x00, 0x23, 0x00, 0xfb, + 0x01, 0x33, 0x01, 0xfb, 0x00, 0x33, 0x39, 0x46, 0xa8, 0x18, 0x59, 0x41, + 0x00, 0xf0, 0x06, 0xfb, 0x03, 0x99, 0x00, 0xf0, 0x41, 0xfc, 0x03, 0x90, + 0x0b, 0xa8, 0x00, 0xeb, 0x86, 0x09, 0x30, 0xf9, 0x26, 0x00, 0xc1, 0x17, + 0xa0, 0xfb, 0x00, 0x23, 0xb9, 0xf9, 0x02, 0x50, 0x00, 0xfb, 0x01, 0x33, + 0x01, 0xfb, 0x00, 0x33, 0xef, 0x17, 0xa5, 0xfb, 0x05, 0x01, 0x05, 0xfb, + 0x07, 0x11, 0x07, 0xfb, 0x05, 0x11, 0x10, 0x18, 0x59, 0x41, 0x00, 0xf0, + 0xe9, 0xfa, 0x21, 0x46, 0x00, 0xf0, 0x24, 0xfc, 0x04, 0x46, 0x0b, 0xa8, + 0xb9, 0xf9, 0x02, 0x50, 0x30, 0xf9, 0x26, 0x90, 0xba, 0xf9, 0x02, 0x20, + 0x04, 0xa8, 0xef, 0x17, 0x30, 0xf9, 0x26, 0xc0, 0xa2, 0xfb, 0x05, 0x01, + 0xd3, 0x17, 0x02, 0xfb, 0x07, 0x11, 0x03, 0xfb, 0x05, 0x11, 0xcc, 0xfb, + 0x09, 0x01, 0x00, 0xf0, 0xcf, 0xfa, 0x02, 0x99, 0x00, 0xf0, 0x0a, 0xfc, + 0x02, 0x90, 0x2a, 0x46, 0x04, 0xa8, 0x3b, 0x46, 0x30, 0xf9, 0x26, 0x00, + 0xa0, 0xfb, 0x02, 0x57, 0xc1, 0x17, 0x00, 0xfb, 0x03, 0x77, 0x0b, 0xa8, + 0x01, 0xfb, 0x02, 0x77, 0x30, 0xf9, 0x26, 0x00, 0xba, 0xf9, 0x02, 0x10, + 0x81, 0xfb, 0x00, 0x01, 0x28, 0x1a, 0x67, 0xeb, 0x01, 0x01, 0x00, 0xf0, + 0xb3, 0xfa, 0x41, 0x46, 0x00, 0xf0, 0xee, 0xfb, 0x76, 0x1c, 0x07, 0x2e, + 0x80, 0x46, 0x8a, 0xd3, 0x0b, 0xf1, 0x01, 0x0b, 0x00, 0xf0, 0x5b, 0xf8, + 0x83, 0x45, 0x19, 0xd2, 0x01, 0x98, 0x07, 0x23, 0x04, 0xaa, 0x0b, 0xa9, + 0x03, 0xf0, 0x4e, 0xfe, 0xfe, 0xf7, 0x8f, 0xf8, 0x00, 0x28, 0x3f, 0xf4, + 0x79, 0xaf, 0x12, 0x99, 0xc9, 0x68, 0x06, 0x20, 0x08, 0x60, 0xab, 0xf1, + 0x01, 0x0b, 0x00, 0xf0, 0x4d, 0xf8, 0x14, 0x99, 0x12, 0x98, 0x00, 0xf0, + 0xe1, 0xf8, 0x00, 0x28, 0x00, 0x90, 0xdf, 0xd0, 0x00, 0xf0, 0x44, 0xf8, + 0x00, 0x98, 0x00, 0x28, 0x32, 0xd1, 0x13, 0x98, 0x14, 0x99, 0x14, 0x22, + 0x02, 0xfb, 0x01, 0x06, 0x00, 0xf0, 0x33, 0xf8, 0xc0, 0xeb, 0xc0, 0x00, + 0x00, 0xf0, 0xae, 0xfa, 0x05, 0x46, 0x20, 0x46, 0x29, 0x46, 0x00, 0xf0, + 0xc3, 0xfa, 0x00, 0xf0, 0xf5, 0xfb, 0x00, 0xf0, 0x23, 0xf8, 0xf0, 0x60, + 0x29, 0x46, 0x03, 0x98, 0x00, 0xf0, 0xba, 0xfa, 0x00, 0xf0, 0xec, 0xfb, + 0x00, 0xf0, 0x1a, 0xf8, 0x30, 0x61, 0xf1, 0x68, 0x00, 0xf0, 0xb2, 0xfa, + 0x30, 0x60, 0x21, 0x46, 0x9a, 0x48, 0x00, 0xf0, 0x3b, 0xfc, 0x00, 0xf0, + 0x0f, 0xf8, 0x04, 0x46, 0x02, 0x98, 0x21, 0x46, 0x00, 0xf0, 0xa6, 0xfa, + 0x70, 0x60, 0x21, 0x46, 0x40, 0x46, 0x00, 0xf0, 0xa1, 0xfa, 0xb0, 0x60, + 0x00, 0x98, 0x15, 0xb0, 0xbd, 0xe8, 0xf0, 0x8f, 0x90, 0x49, 0x00, 0xf0, + 0x99, 0xba, 0x12, 0x98, 0x01, 0x99, 0x80, 0x68, 0x00, 0xeb, 0x41, 0x00, + 0x80, 0x8a, 0x70, 0x47, 0x14, 0x99, 0x12, 0x98, 0xce, 0xe0, 0x10, 0xb5, + 0x04, 0x46, 0x21, 0x46, 0x08, 0x29, 0xb1, 0xbf, 0x4f, 0xf4, 0x30, 0x60, + 0x40, 0xf6, 0x01, 0x30, 0x08, 0x39, 0x89, 0xb2, 0x00, 0xf1, 0x8c, 0x42, + 0x01, 0x23, 0x12, 0x78, 0x03, 0xfa, 0x01, 0xf1, 0x8a, 0x43, 0x11, 0x43, + 0xc9, 0xb2, 0xfc, 0xf7, 0x49, 0xfd, 0x04, 0x2c, 0x40, 0xf6, 0x06, 0x30, + 0x7e, 0x49, 0x05, 0xda, 0x09, 0x78, 0x01, 0xf0, 0xf0, 0x01, 0x41, 0xf0, + 0x03, 0x01, 0x0e, 0xe0, 0x08, 0x2c, 0x05, 0xda, 0x09, 0x78, 0x01, 0xf0, + 0x0f, 0x01, 0x41, 0xf0, 0x30, 0x01, 0x06, 0xe0, 0x48, 0x78, 0x00, 0xf0, + 0xf0, 0x00, 0x40, 0xf0, 0x03, 0x01, 0x40, 0xf6, 0x07, 0x30, 0xbd, 0xe8, + 0x10, 0x40, 0xfc, 0xf7, 0x2b, 0xbd, 0x10, 0xb5, 0x08, 0x28, 0xb2, 0xbf, + 0x40, 0xf6, 0x02, 0x32, 0x40, 0xf6, 0x03, 0x32, 0x08, 0x38, 0x02, 0xf1, + 0x8c, 0x43, 0x01, 0x24, 0x1b, 0x78, 0x84, 0x40, 0x23, 0xea, 0x04, 0x00, + 0x01, 0xb1, 0x20, 0x43, 0xbd, 0xe8, 0x10, 0x40, 0xc1, 0xb2, 0x10, 0x46, + 0xfc, 0xf7, 0x14, 0xbd, 0x38, 0xb5, 0x04, 0x46, 0xa0, 0x68, 0x22, 0x68, + 0x00, 0xeb, 0x42, 0x00, 0x01, 0x29, 0x02, 0x89, 0x80, 0x88, 0x02, 0xd1, + 0x52, 0x1e, 0x92, 0x41, 0xd2, 0x0f, 0x11, 0x46, 0xff, 0xf7, 0xd9, 0xff, + 0x5e, 0x48, 0x58, 0x4d, 0x00, 0x68, 0x21, 0x68, 0x05, 0xeb, 0x81, 0x01, + 0x08, 0x63, 0xfc, 0xf7, 0x83, 0xfa, 0x21, 0x68, 0x05, 0xeb, 0x81, 0x01, + 0x88, 0x63, 0x00, 0x21, 0x20, 0x68, 0x05, 0xeb, 0x80, 0x00, 0xbd, 0xe8, + 0x34, 0x40, 0x00, 0x1d, 0xfe, 0xf7, 0x20, 0xbf, 0xf8, 0xb5, 0x04, 0x46, + 0x53, 0x4d, 0x4c, 0x4e, 0x51, 0x48, 0x07, 0x68, 0xfc, 0xf7, 0x6e, 0xfa, + 0x06, 0xf1, 0x38, 0x02, 0x06, 0xf1, 0x30, 0x01, 0x52, 0xf8, 0x24, 0x20, + 0x51, 0xf8, 0x24, 0x10, 0x80, 0x1a, 0x2a, 0x6c, 0xc9, 0x1b, 0x02, 0xfb, + 0x00, 0x10, 0x06, 0xeb, 0x84, 0x01, 0x49, 0x68, 0x49, 0xb9, 0x06, 0xf1, + 0x28, 0x01, 0x51, 0xf8, 0x24, 0x10, 0x88, 0x42, 0x03, 0xd2, 0xfd, 0xf7, + 0xa2, 0xff, 0x00, 0x28, 0xe0, 0xd0, 0xf1, 0xbd, 0x70, 0xb5, 0x04, 0x46, + 0x0d, 0x46, 0x00, 0x21, 0x00, 0x20, 0xfc, 0xf7, 0x18, 0xff, 0x01, 0x2d, + 0x03, 0xd1, 0x01, 0x21, 0x20, 0x46, 0xff, 0xf7, 0xa9, 0xff, 0x20, 0x68, + 0x04, 0xf1, 0x10, 0x01, 0x03, 0xf0, 0xf5, 0xfd, 0x06, 0x00, 0x09, 0xd1, + 0xe0, 0x69, 0x00, 0xeb, 0x45, 0x01, 0x20, 0x68, 0x03, 0xf0, 0x48, 0xfe, + 0x20, 0x68, 0x03, 0xf0, 0x2a, 0xfe, 0x06, 0x46, 0x01, 0x2e, 0x0b, 0xd0, + 0x02, 0x2e, 0x0b, 0xd0, 0x0c, 0x2e, 0x0b, 0xd0, 0x11, 0x2e, 0x0b, 0xd0, + 0x13, 0x2e, 0x0b, 0xd0, 0x14, 0x2e, 0x08, 0xbf, 0x0a, 0x26, 0x08, 0xe0, + 0x02, 0x26, 0x06, 0xe0, 0x01, 0x26, 0x04, 0xe0, 0x0b, 0x26, 0x02, 0xe0, + 0x03, 0x26, 0x00, 0xe0, 0x09, 0x26, 0x20, 0x68, 0xff, 0xf7, 0xa4, 0xff, + 0x30, 0x46, 0x70, 0xbd, 0x38, 0xb5, 0x04, 0x46, 0x0d, 0x46, 0xfd, 0xf7, + 0xcf, 0xf9, 0x03, 0x28, 0x06, 0xd1, 0x07, 0xf0, 0xd5, 0xfe, 0x00, 0x21, + 0x04, 0xf1, 0x10, 0x00, 0xfe, 0xf7, 0xcf, 0xfe, 0x01, 0x2d, 0x03, 0xd1, + 0x00, 0x21, 0x20, 0x46, 0xff, 0xf7, 0x68, 0xff, 0xbd, 0xe8, 0x32, 0x40, + 0x00, 0x20, 0xfc, 0xf7, 0x29, 0xbf, 0x70, 0xb5, 0x11, 0x4b, 0x03, 0xeb, + 0x40, 0x01, 0x00, 0x22, 0x0d, 0x7c, 0x8c, 0x8a, 0x08, 0x2d, 0x02, 0xdb, + 0x08, 0x3d, 0xed, 0xb2, 0x01, 0x22, 0x01, 0x26, 0x06, 0xfa, 0x05, 0xf5, + 0xd6, 0x5c, 0xae, 0x43, 0xd6, 0x54, 0x04, 0xb9, 0x00, 0x25, 0xd2, 0x18, + 0x03, 0xeb, 0x80, 0x00, 0x94, 0x78, 0x2c, 0x43, 0x94, 0x70, 0x01, 0x22, + 0x42, 0x60, 0x0b, 0x4a, 0x09, 0x8b, 0xd2, 0x6b, 0x51, 0x43, 0x81, 0x62, + 0x70, 0xbd, 0x00, 0x00, 0x94, 0xed, 0x00, 0x20, 0xec, 0x2b, 0x00, 0x20, + 0x78, 0x29, 0x00, 0x20, 0x00, 0x00, 0xc8, 0x42, 0x00, 0x00, 0xa0, 0x41, + 0xf4, 0xfd, 0xb4, 0x47, 0x06, 0x0b, 0x00, 0x46, 0x18, 0xe0, 0x00, 0xe0, + 0x00, 0xf2, 0x00, 0x20, 0x10, 0xb5, 0x04, 0x46, 0xe0, 0x69, 0x80, 0x88, + 0xd0, 0xb9, 0xa0, 0x68, 0x21, 0x68, 0x00, 0xeb, 0x41, 0x00, 0x00, 0x8a, + 0x20, 0x28, 0x09, 0xda, 0xff, 0xf7, 0xd5, 0xfe, 0xa0, 0x68, 0x22, 0x68, + 0x00, 0xeb, 0x42, 0x00, 0x01, 0x21, 0x00, 0x8a, 0xff, 0xf7, 0x01, 0xff, + 0xa0, 0x68, 0x21, 0x68, 0x00, 0xeb, 0x41, 0x00, 0x80, 0x88, 0xff, 0xf7, + 0xc6, 0xfe, 0xe1, 0x69, 0x01, 0x20, 0x88, 0x80, 0x10, 0xbd, 0x00, 0x00, + 0xff, 0xff, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x38, 0xb5, 0x75, 0x4d, 0x04, 0x46, 0x15, 0xf8, 0x34, 0x10, 0x48, 0x1e, + 0x80, 0x41, 0xc0, 0x0f, 0x01, 0xf0, 0x29, 0xfb, 0x01, 0x20, 0x3f, 0xe0, + 0xf8, 0xb5, 0x06, 0x46, 0x6e, 0x4d, 0x34, 0x46, 0x15, 0xf8, 0x34, 0x00, + 0x01, 0x28, 0x0f, 0x46, 0x18, 0xbf, 0x00, 0x20, 0x01, 0xf0, 0x1b, 0xfb, + 0x6a, 0x48, 0x87, 0x42, 0x28, 0xbf, 0x6a, 0x4f, 0x28, 0x6b, 0x47, 0x43, + 0x30, 0x46, 0x00, 0xf0, 0x4f, 0xf8, 0x30, 0x46, 0x00, 0xf0, 0x53, 0xf8, + 0x05, 0xeb, 0xc4, 0x00, 0x02, 0x21, 0x40, 0x68, 0x07, 0x60, 0xc1, 0x60, + 0x00, 0x21, 0x81, 0x60, 0xf0, 0x21, 0x81, 0x60, 0x02, 0x20, 0x05, 0xf8, + 0x34, 0x00, 0xf1, 0xbd, 0x10, 0xb5, 0x5c, 0x4a, 0x02, 0xeb, 0xc0, 0x01, + 0x4b, 0x68, 0x59, 0x68, 0x14, 0x6b, 0xb1, 0xfb, 0xf4, 0xf1, 0x00, 0x24, + 0x9c, 0x60, 0x01, 0x23, 0x02, 0xf8, 0x30, 0x30, 0x08, 0x46, 0x10, 0xbd, + 0x38, 0xb5, 0x54, 0x4d, 0x04, 0x46, 0x15, 0xf8, 0x34, 0x10, 0x01, 0x29, + 0x18, 0xbf, 0xff, 0xf7, 0xe7, 0xff, 0x00, 0x20, 0x05, 0xf8, 0x34, 0x00, + 0x31, 0xbd, 0x51, 0x49, 0x0a, 0x68, 0x90, 0x42, 0x09, 0xd3, 0x49, 0x68, + 0x80, 0x1a, 0xb0, 0xfb, 0xf1, 0xf0, 0x00, 0x21, 0x01, 0xe0, 0x00, 0xbf, + 0x49, 0x1c, 0x81, 0x42, 0xfb, 0xd3, 0x70, 0x47, 0x10, 0xb4, 0x46, 0x4b, + 0x1b, 0x6b, 0x03, 0xfb, 0x00, 0xf3, 0x06, 0x24, 0xb3, 0xfb, 0xf4, 0xf3, + 0x19, 0x00, 0x00, 0x23, 0x1a, 0x00, 0x8a, 0x42, 0x02, 0xd2, 0x00, 0xbf, + 0x52, 0x1c, 0xfa, 0xe7, 0x10, 0xbc, 0x70, 0x47, 0x3d, 0x49, 0x01, 0xeb, + 0xc0, 0x00, 0x90, 0xf9, 0x01, 0x00, 0x01, 0xf0, 0x01, 0xbb, 0x10, 0xb5, + 0x39, 0x49, 0x01, 0xeb, 0xc0, 0x00, 0x90, 0xf9, 0x01, 0x40, 0x20, 0x46, + 0x01, 0xf0, 0xf8, 0xfa, 0x20, 0x46, 0xbd, 0xe8, 0x10, 0x40, 0x01, 0xf0, + 0xf9, 0xba, 0x33, 0x49, 0x01, 0xeb, 0xc0, 0x00, 0x90, 0xf9, 0x01, 0x00, + 0x01, 0xf0, 0xfb, 0xba, 0x80, 0xb5, 0x06, 0x21, 0x05, 0x20, 0x01, 0xf0, + 0x02, 0xfb, 0x06, 0x21, 0x06, 0x20, 0x01, 0xf0, 0xfe, 0xfa, 0x06, 0x21, + 0x07, 0x20, 0x01, 0xf0, 0xfa, 0xfa, 0x06, 0x21, 0x08, 0x20, 0x01, 0xf0, + 0xf6, 0xfa, 0x06, 0x21, 0x2f, 0x20, 0x01, 0xf0, 0xf2, 0xfa, 0x06, 0x21, + 0x30, 0x20, 0x01, 0xf0, 0xee, 0xfa, 0x06, 0x21, 0x31, 0x20, 0x01, 0xf0, + 0xea, 0xfa, 0x06, 0x21, 0x32, 0x20, 0x01, 0xf0, 0xe6, 0xfa, 0x23, 0x48, + 0x1e, 0x49, 0xc0, 0x6b, 0x08, 0x63, 0x01, 0xbd, 0x38, 0xb5, 0x04, 0x46, + 0x0d, 0x46, 0xff, 0xf7, 0x49, 0xff, 0x1b, 0x48, 0x85, 0x42, 0x19, 0x48, + 0x28, 0xbf, 0x1a, 0x4d, 0x01, 0x6b, 0x00, 0xeb, 0xc4, 0x00, 0x69, 0x43, + 0x40, 0x68, 0x01, 0x60, 0x02, 0x21, 0xc1, 0x60, 0x00, 0x21, 0xc1, 0x60, + 0x81, 0x60, 0xf0, 0x21, 0x81, 0x60, 0x31, 0xbd, 0x10, 0x49, 0x01, 0xeb, + 0xc0, 0x00, 0x40, 0x68, 0x40, 0x69, 0x70, 0x47, 0x80, 0xb5, 0x00, 0x20, + 0xff, 0xf7, 0xb1, 0xff, 0x00, 0xf0, 0x12, 0xf8, 0x08, 0x70, 0x01, 0xbd, + 0x80, 0xb5, 0x01, 0x20, 0xff, 0xf7, 0xa9, 0xff, 0x00, 0xf0, 0x0a, 0xf8, + 0x08, 0x72, 0x01, 0xbd, 0x80, 0xb5, 0x02, 0x20, 0xff, 0xf7, 0xa1, 0xff, + 0x00, 0xf0, 0x02, 0xf8, 0x08, 0x74, 0x01, 0xbd, 0x01, 0x49, 0x01, 0x20, + 0x70, 0x47, 0x00, 0x00, 0x78, 0x2a, 0x00, 0x20, 0xc1, 0xe1, 0xe4, 0x00, + 0xc0, 0xe1, 0xe4, 0x00, 0xac, 0x2a, 0x00, 0x20, 0x00, 0xf2, 0x00, 0x20, + 0x80, 0xb5, 0x03, 0x20, 0xff, 0xf7, 0x8b, 0xff, 0xff, 0xf7, 0xec, 0xff, + 0x08, 0x76, 0x01, 0xbd, 0x00, 0x29, 0x40, 0xf1, 0x0b, 0x80, 0xf4, 0x46, + 0x49, 0x42, 0x40, 0x42, 0x71, 0xf1, 0x00, 0x01, 0x00, 0xf0, 0x0a, 0xf8, + 0x50, 0xf0, 0x00, 0x40, 0x60, 0x47, 0x00, 0x00, 0x50, 0xea, 0x01, 0x02, + 0x00, 0xf0, 0x0e, 0x80, 0x09, 0x42, 0x00, 0xbf, 0x0b, 0xd1, 0xb0, 0xfa, + 0x80, 0xf1, 0x88, 0x40, 0xc1, 0xf1, 0x9d, 0x01, 0xc9, 0x05, 0x02, 0x06, + 0x72, 0xf1, 0x00, 0x42, 0x41, 0xeb, 0x10, 0x20, 0x70, 0x47, 0xb1, 0xfa, + 0x81, 0xf2, 0x41, 0x40, 0x90, 0x40, 0xc2, 0xf1, 0x20, 0x02, 0x61, 0xfa, + 0x02, 0xf1, 0x81, 0xea, 0x00, 0x00, 0x18, 0xbf, 0x40, 0xf0, 0x01, 0x00, + 0x02, 0xf1, 0x9d, 0x01, 0xe8, 0xe7, 0x00, 0x00, 0x00, 0x28, 0x40, 0xf1, + 0x09, 0x80, 0xf4, 0x46, 0x40, 0x42, 0x00, 0xf0, 0x05, 0xf8, 0x50, 0xf0, + 0x00, 0x40, 0x60, 0x47, 0x00, 0x28, 0x00, 0xbf, 0x0a, 0xd0, 0xb0, 0xfa, + 0x80, 0xf1, 0x88, 0x40, 0xd1, 0xf1, 0x9d, 0x01, 0xc9, 0x05, 0x02, 0x06, + 0x72, 0xf1, 0x00, 0x42, 0x41, 0xeb, 0x10, 0x20, 0x70, 0x47, 0x00, 0x00, + 0x10, 0xb5, 0xff, 0x23, 0x13, 0xea, 0xd0, 0x54, 0x1d, 0xbf, 0x13, 0xea, + 0xd1, 0x52, 0x9c, 0x42, 0x9a, 0x42, 0x39, 0xe0, 0xa4, 0x1a, 0xda, 0x07, + 0x80, 0xea, 0x01, 0x03, 0x13, 0x40, 0x42, 0xea, 0x01, 0x21, 0x42, 0xea, + 0x00, 0x20, 0x42, 0x1a, 0x3c, 0xbf, 0x64, 0x1e, 0x01, 0xeb, 0x42, 0x02, + 0x09, 0x0a, 0xb2, 0xfb, 0xf1, 0xfe, 0x01, 0xfb, 0x1e, 0x22, 0x12, 0x02, + 0xb2, 0xfb, 0xf1, 0xf0, 0x01, 0xfb, 0x10, 0x22, 0x6e, 0xf3, 0x0f, 0x20, + 0x12, 0x02, 0xb2, 0xfb, 0xf1, 0xfe, 0x4e, 0xea, 0x00, 0x20, 0x7f, 0x34, + 0x06, 0xdd, 0xfe, 0x2c, 0x24, 0xda, 0x53, 0xea, 0x50, 0x00, 0x50, 0xeb, + 0xc4, 0x50, 0x10, 0xbd, 0xd4, 0xf1, 0x02, 0x04, 0x01, 0xfb, 0x1e, 0x22, + 0x40, 0xf0, 0x80, 0x71, 0x19, 0x2c, 0x1d, 0xdc, 0x21, 0xfa, 0x04, 0xf0, + 0xc4, 0xf1, 0x20, 0x04, 0xa1, 0x40, 0x11, 0x43, 0x71, 0xf1, 0x00, 0x42, + 0x58, 0x41, 0x10, 0xbd, 0x9c, 0x42, 0x1a, 0xbf, 0x03, 0xea, 0xd1, 0x52, + 0x9a, 0x42, 0x0f, 0xe0, 0x80, 0xea, 0x01, 0x0e, 0x0e, 0xf0, 0x00, 0x43, + 0x40, 0x00, 0x04, 0xd0, 0x49, 0x00, 0x16, 0xd1, 0x43, 0xf0, 0xff, 0x40, + 0x10, 0xbd, 0x49, 0x00, 0x08, 0xbf, 0xd3, 0x43, 0x18, 0x00, 0x10, 0xbd, + 0x9c, 0x42, 0x05, 0xd1, 0xd2, 0x1a, 0xf7, 0xd0, 0x01, 0xf0, 0x00, 0x41, + 0x48, 0x40, 0x10, 0xbd, 0x4a, 0x02, 0x12, 0xbf, 0x08, 0x46, 0x48, 0x40, + 0x00, 0xf0, 0x00, 0x40, 0x10, 0xbd, 0x4a, 0xb9, 0x09, 0x02, 0xb1, 0xfa, + 0x81, 0xf2, 0x91, 0x40, 0x44, 0xb1, 0xa4, 0x18, 0xc0, 0x01, 0x40, 0xf0, + 0x00, 0x40, 0x9e, 0xe7, 0xc9, 0x01, 0x41, 0xf0, 0x00, 0x41, 0x52, 0x42, + 0x00, 0x02, 0xb0, 0xfa, 0x80, 0xf4, 0xa0, 0x40, 0x14, 0x1b, 0x94, 0xe7, + 0x90, 0xea, 0x01, 0x0f, 0x44, 0xbf, 0x81, 0xf0, 0x00, 0x41, 0x00, 0xf0, + 0x75, 0xb8, 0x00, 0xbf, 0x43, 0x1a, 0x4f, 0xf0, 0x00, 0x42, 0x3e, 0xbf, + 0x53, 0x40, 0xc0, 0x1a, 0xc9, 0x18, 0x00, 0xbf, 0xd3, 0x09, 0x5f, 0xea, + 0xd0, 0x5c, 0x13, 0xeb, 0x40, 0x0f, 0x34, 0xbf, 0xb3, 0xeb, 0x41, 0x0f, + 0x40, 0xe0, 0x7c, 0xeb, 0xd1, 0x53, 0x0c, 0xd3, 0x42, 0xea, 0x01, 0x21, + 0x22, 0xd8, 0xd1, 0xeb, 0x40, 0x20, 0x09, 0xd3, 0x40, 0x0a, 0x28, 0xbf, + 0x5f, 0xea, 0x50, 0x01, 0x40, 0xeb, 0xcc, 0x50, 0x70, 0x47, 0x40, 0x1a, + 0x15, 0xd0, 0x40, 0x02, 0xb0, 0xfa, 0x80, 0xf2, 0x52, 0x1c, 0x90, 0x40, + 0x40, 0x0a, 0x4f, 0xea, 0x3c, 0x23, 0xb3, 0xeb, 0x02, 0x63, 0x84, 0xbf, + 0x00, 0xeb, 0x73, 0x00, 0x07, 0xe0, 0x40, 0xf4, 0x00, 0x00, 0x1a, 0x16, + 0xdb, 0x07, 0xc2, 0xf1, 0x01, 0x02, 0xd0, 0x40, 0x18, 0x43, 0x70, 0x47, + 0x18, 0x2b, 0xfc, 0xdc, 0x31, 0xfa, 0x03, 0xf2, 0x02, 0xfa, 0x03, 0xf3, + 0x59, 0x1a, 0x38, 0xbf, 0x42, 0xf0, 0x01, 0x02, 0xd2, 0xeb, 0x40, 0x20, + 0x3c, 0xbf, 0x40, 0x00, 0xac, 0xf1, 0x01, 0x0c, 0x5f, 0xea, 0xcc, 0x5c, + 0xc2, 0x05, 0x72, 0xf1, 0x00, 0x41, 0x4c, 0xeb, 0x50, 0x20, 0x70, 0x47, + 0x13, 0xeb, 0x40, 0x0f, 0x0f, 0xd2, 0x4b, 0x00, 0x09, 0xd0, 0xac, 0xeb, + 0xd1, 0x53, 0x02, 0x2b, 0x03, 0xdb, 0x49, 0x02, 0x17, 0x2b, 0xdd, 0xdd, + 0x70, 0x47, 0x91, 0x43, 0x40, 0x1a, 0x43, 0x00, 0xd5, 0xd1, 0x00, 0x20, + 0x70, 0x47, 0x13, 0xeb, 0x41, 0x0f, 0xd0, 0xd3, 0x6f, 0xf0, 0x00, 0x00, + 0x70, 0x47, 0x00, 0x00, 0x90, 0xea, 0x01, 0x0f, 0x44, 0xbf, 0x81, 0xf0, + 0x00, 0x41, 0xff, 0xf7, 0x8d, 0xbf, 0x00, 0xbf, 0x42, 0x1a, 0x3c, 0xbf, + 0x80, 0x1a, 0x89, 0x18, 0x4f, 0xf0, 0x00, 0x4c, 0xc0, 0xf3, 0xc7, 0x52, + 0xff, 0x2a, 0x24, 0xd0, 0xc1, 0xf3, 0xc7, 0x53, 0x13, 0xb3, 0xd2, 0x1a, + 0xd2, 0xf1, 0x19, 0x03, 0x27, 0xdd, 0x4c, 0xea, 0x01, 0x21, 0x4c, 0xfa, + 0x03, 0xf3, 0x21, 0xea, 0x03, 0x03, 0xd1, 0x40, 0xc2, 0x0d, 0x4c, 0xea, + 0x00, 0x20, 0x40, 0x18, 0x34, 0xbf, 0x20, 0xea, 0x0c, 0x00, 0x4c, 0xea, + 0x50, 0x00, 0xd2, 0x05, 0x53, 0xea, 0x00, 0x63, 0x73, 0xeb, 0x0c, 0x0c, + 0x52, 0xeb, 0x10, 0x20, 0x42, 0x00, 0x12, 0xf1, 0x80, 0x7f, 0x38, 0xbf, + 0x70, 0x47, 0xc0, 0x0d, 0xc0, 0x05, 0x70, 0x47, 0x49, 0x02, 0x12, 0xbf, + 0x9a, 0x42, 0x00, 0xeb, 0x51, 0x20, 0xf8, 0xe7, 0xd2, 0xf1, 0x17, 0x03, + 0xd9, 0xd5, 0x70, 0x47, 0x4f, 0xf4, 0x00, 0x02, 0xc1, 0x0d, 0x23, 0xd0, + 0xff, 0x29, 0x29, 0xd2, 0x30, 0xea, 0xc1, 0x50, 0x10, 0x43, 0x7d, 0x31, + 0x49, 0x08, 0x28, 0xbf, 0x00, 0x18, 0x80, 0x00, 0x4f, 0xf0, 0xc0, 0x73, + 0xb0, 0xf1, 0x90, 0x60, 0x06, 0xd4, 0x52, 0x08, 0x0e, 0xd2, 0xc0, 0x1a, + 0x9b, 0x18, 0xd2, 0xeb, 0x40, 0x00, 0xf8, 0xd5, 0x52, 0x08, 0x06, 0xd2, + 0xc0, 0x18, 0x9b, 0x1a, 0xd2, 0xeb, 0x40, 0x00, 0xf1, 0xd5, 0x52, 0x08, + 0xf8, 0xd3, 0x5b, 0x1e, 0x58, 0x08, 0x50, 0xeb, 0xc1, 0x50, 0x70, 0x47, + 0xb0, 0xfa, 0x80, 0xf1, 0x08, 0x39, 0x88, 0x40, 0xf9, 0xd0, 0xd1, 0xf1, + 0x01, 0x01, 0xd8, 0xe7, 0xff, 0x29, 0xf4, 0xd0, 0xd0, 0x42, 0xf2, 0xd8, + 0x40, 0x00, 0xf0, 0xd0, 0xc8, 0x43, 0x07, 0xf0, 0xd1, 0xbf, 0x00, 0x00, + 0x40, 0xea, 0x01, 0x0c, 0x5f, 0xea, 0x4c, 0x0c, 0x07, 0xd0, 0x88, 0x42, + 0x05, 0xd1, 0x4f, 0xea, 0x40, 0x0c, 0x1c, 0xf1, 0x80, 0x7f, 0x98, 0xbf, + 0x80, 0x42, 0x70, 0x47, 0x4f, 0xf0, 0x80, 0x7c, 0x1c, 0xeb, 0x40, 0x0f, + 0x94, 0xbf, 0x1c, 0xeb, 0x41, 0x0f, 0x05, 0xe0, 0x40, 0xea, 0x01, 0x0c, + 0x5f, 0xea, 0x4c, 0x0c, 0x01, 0xd2, 0x88, 0x42, 0x70, 0x47, 0x18, 0xbf, + 0x81, 0x42, 0x70, 0x47, 0xff, 0x22, 0x12, 0xea, 0xd0, 0x5c, 0x1d, 0xbf, + 0x12, 0xea, 0xd1, 0x53, 0x94, 0x45, 0x93, 0x42, 0x2b, 0xe0, 0x9c, 0x44, + 0xd3, 0x07, 0x80, 0xea, 0x01, 0x02, 0x1a, 0x40, 0x43, 0xea, 0x00, 0x20, + 0x43, 0xea, 0x01, 0x21, 0xa1, 0xfb, 0x00, 0x30, 0x41, 0x00, 0x38, 0xbf, + 0x40, 0x00, 0x7c, 0xf1, 0x7f, 0x01, 0x0b, 0xdb, 0xfe, 0x29, 0x4a, 0xda, + 0x5b, 0x08, 0x42, 0xea, 0xc1, 0x51, 0x53, 0xea, 0x00, 0x63, 0x73, 0xf1, + 0x00, 0x4c, 0x51, 0xeb, 0x10, 0x20, 0x70, 0x47, 0xd1, 0xf1, 0x08, 0x0c, + 0xdc, 0xf1, 0x20, 0x01, 0x2f, 0xdb, 0x5b, 0x08, 0x10, 0xfa, 0x01, 0xf1, + 0x0b, 0x43, 0x73, 0xf1, 0x00, 0x41, 0x20, 0xfa, 0x0c, 0xf0, 0x50, 0x41, + 0x70, 0x47, 0x94, 0x45, 0x1c, 0xbf, 0x02, 0xea, 0xd1, 0x53, 0x93, 0x42, + 0x80, 0xea, 0x01, 0x02, 0x02, 0xf0, 0x00, 0x42, 0x1d, 0xd0, 0x40, 0x00, + 0x19, 0xd0, 0x49, 0x00, 0x17, 0xd0, 0x5b, 0xb9, 0x63, 0x45, 0x14, 0xd0, + 0x09, 0x02, 0xb1, 0xfa, 0x81, 0xf3, 0x99, 0x40, 0xbc, 0xeb, 0x03, 0x0c, + 0xc0, 0x01, 0x40, 0xf0, 0x00, 0x40, 0xc1, 0xe7, 0x00, 0x02, 0xb0, 0xfa, + 0x80, 0xfc, 0x10, 0xfa, 0x0c, 0xf0, 0xb3, 0xeb, 0x0c, 0x0c, 0xc9, 0x01, + 0x41, 0xf0, 0x00, 0x41, 0xb6, 0xe7, 0x10, 0x00, 0x70, 0x47, 0x40, 0x00, + 0x0a, 0xd0, 0x49, 0x00, 0x08, 0xd0, 0x10, 0xf1, 0x80, 0x7f, 0x94, 0xbf, + 0x11, 0xf1, 0x80, 0x7f, 0x02, 0xe0, 0x42, 0xf0, 0xff, 0x40, 0x70, 0x47, + 0xd0, 0x43, 0x70, 0x47, 0x41, 0x00, 0x09, 0x0e, 0x7f, 0x39, 0x15, 0xd4, + 0xd1, 0xf1, 0x1f, 0x01, 0x14, 0xd4, 0x40, 0x00, 0x07, 0xd2, 0xc0, 0x01, + 0x40, 0xf0, 0x00, 0x40, 0xc8, 0x40, 0x48, 0xbf, 0x6f, 0xf0, 0x00, 0x40, + 0x70, 0x47, 0xc0, 0x01, 0x40, 0xf0, 0x00, 0x40, 0xc8, 0x40, 0x4c, 0xbf, + 0x4f, 0xf0, 0x00, 0x40, 0x40, 0x42, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, + 0x00, 0x42, 0x4f, 0xf0, 0x00, 0x40, 0x58, 0xbf, 0xc0, 0x43, 0x70, 0x47, + 0xc0, 0xf3, 0xc7, 0x52, 0x7e, 0x3a, 0x09, 0xdd, 0x18, 0x2a, 0x0c, 0xda, + 0x6f, 0xf0, 0x7f, 0x41, 0xd1, 0x40, 0x20, 0xea, 0x51, 0x00, 0x40, 0x18, + 0x88, 0x43, 0x70, 0x47, 0x00, 0xf0, 0x00, 0x40, 0x08, 0xbf, 0x40, 0xf0, + 0x7e, 0x50, 0x70, 0x47, 0x38, 0xb5, 0x0b, 0x46, 0xc3, 0xf3, 0xc7, 0x51, + 0xff, 0x29, 0x02, 0x46, 0x09, 0xd0, 0x11, 0xb1, 0x4f, 0xf0, 0xff, 0x34, + 0x09, 0xe0, 0x58, 0x02, 0x0c, 0xbf, 0x00, 0x24, 0x6f, 0xf0, 0x01, 0x04, + 0x03, 0xe0, 0x58, 0x02, 0x14, 0xbf, 0x02, 0x24, 0x01, 0x24, 0xc2, 0xf3, + 0xc7, 0x51, 0xff, 0x29, 0x08, 0xd0, 0x11, 0xb1, 0x4f, 0xf0, 0xff, 0x31, + 0x08, 0xe0, 0x50, 0x02, 0x06, 0xd0, 0x6f, 0xf0, 0x01, 0x01, 0x03, 0xe0, + 0x50, 0x02, 0x14, 0xbf, 0x02, 0x21, 0x01, 0x21, 0x01, 0x2c, 0xb8, 0xbf, + 0x01, 0x29, 0x1c, 0xda, 0x00, 0x2a, 0x46, 0xbf, 0x82, 0xf0, 0x00, 0x42, + 0x08, 0x25, 0x00, 0x25, 0x00, 0x2b, 0x44, 0xbf, 0x83, 0xf0, 0x00, 0x43, + 0x85, 0xf0, 0x06, 0x05, 0x18, 0x46, 0x11, 0x46, 0xff, 0xf7, 0x12, 0xff, + 0x02, 0xd2, 0xff, 0xf7, 0x93, 0xfd, 0x1f, 0xe0, 0x00, 0x2c, 0x04, 0xd5, + 0x10, 0x46, 0x19, 0x46, 0xff, 0xf7, 0x8c, 0xfd, 0x1a, 0xe0, 0x00, 0x20, + 0x18, 0xe0, 0x02, 0x29, 0x01, 0xd1, 0x10, 0x46, 0x32, 0xbd, 0x02, 0x2c, + 0x01, 0xd1, 0x18, 0x46, 0x32, 0xbd, 0x8c, 0x42, 0x0c, 0xbf, 0x4f, 0xf0, + 0x7e, 0x50, 0x00, 0x20, 0x00, 0x2a, 0x4c, 0xbf, 0x08, 0x25, 0x00, 0x25, + 0x00, 0x2b, 0x48, 0xbf, 0x85, 0xf0, 0x06, 0x05, 0x01, 0x29, 0x01, 0xd1, + 0x85, 0xf0, 0x02, 0x05, 0x29, 0x46, 0xbd, 0xe8, 0x34, 0x40, 0x07, 0xf0, + 0xaf, 0xbe, 0x00, 0x00, 0x4f, 0xf0, 0x80, 0x7c, 0x1c, 0xeb, 0x40, 0x0f, + 0x94, 0xbf, 0x1c, 0xeb, 0x41, 0x0f, 0x05, 0xe0, 0x40, 0xea, 0x01, 0x0c, + 0x5f, 0xea, 0x4c, 0x0c, 0x01, 0xd2, 0x81, 0x42, 0x70, 0x47, 0x18, 0xbf, + 0x88, 0x42, 0x70, 0x47, 0x2d, 0xe9, 0xf1, 0x4d, 0x83, 0xb0, 0x0c, 0x46, + 0x03, 0x98, 0x01, 0x94, 0xc0, 0xf3, 0xc7, 0x50, 0xff, 0x28, 0x15, 0x46, + 0x08, 0xd1, 0x03, 0x98, 0x00, 0x27, 0x40, 0x02, 0x0c, 0xbf, 0x4f, 0xf0, + 0x01, 0x08, 0x4f, 0xf0, 0x02, 0x08, 0x13, 0xe0, 0x01, 0x28, 0x07, 0xda, + 0x03, 0xa8, 0x07, 0xf0, 0xfd, 0xfe, 0x01, 0x28, 0x02, 0xdb, 0x00, 0x27, + 0xb8, 0x46, 0x09, 0xe0, 0x03, 0x99, 0x21, 0xf0, 0xff, 0x41, 0x41, 0xf0, + 0x7c, 0x51, 0x03, 0x91, 0xa0, 0xf1, 0x7e, 0x07, 0x4f, 0xf0, 0xff, 0x38, + 0x00, 0x21, 0x01, 0xa8, 0x07, 0xf0, 0xfd, 0xfe, 0x06, 0x46, 0x0d, 0xb1, + 0x00, 0x20, 0x28, 0x80, 0x26, 0xb9, 0x20, 0x46, 0x00, 0x21, 0xff, 0xf7, + 0x91, 0xfe, 0x12, 0xd0, 0xb8, 0xf1, 0x00, 0x0f, 0x12, 0xd5, 0x3f, 0xb2, + 0x01, 0x2f, 0x14, 0xd1, 0x03, 0x98, 0x4f, 0xf0, 0x7c, 0x51, 0xff, 0xf7, + 0x85, 0xfe, 0x06, 0xd0, 0x01, 0x2e, 0x0c, 0xd1, 0x4f, 0xf0, 0x3f, 0x41, + 0xff, 0xf7, 0x7e, 0xfe, 0x2e, 0xd1, 0x4f, 0xf0, 0x7e, 0x50, 0x0d, 0xe1, + 0xb8, 0xf1, 0x02, 0x0f, 0x03, 0xd1, 0x03, 0x98, 0x08, 0xe1, 0x01, 0x2e, + 0x53, 0xdb, 0x02, 0x2e, 0x08, 0xbf, 0x20, 0x46, 0x00, 0xf0, 0x02, 0x81, + 0xb8, 0xf1, 0x01, 0x0f, 0x1a, 0xd1, 0x03, 0x98, 0x00, 0x28, 0x02, 0xd4, + 0x00, 0x2c, 0x43, 0xd5, 0x2f, 0xe0, 0x00, 0x2c, 0x09, 0xd4, 0x00, 0x2e, + 0x3e, 0xd1, 0x4f, 0xf0, 0xff, 0x31, 0x01, 0xa8, 0x07, 0xf0, 0xbf, 0xfe, + 0x00, 0x28, 0x37, 0xd5, 0x34, 0xe0, 0x16, 0xbb, 0x4f, 0xf0, 0xff, 0x31, + 0x01, 0xa8, 0x07, 0xf0, 0xb6, 0xfe, 0x00, 0x28, 0x1b, 0xd5, 0x17, 0xe0, + 0x01, 0x2e, 0x08, 0xd1, 0x00, 0x2c, 0x3f, 0xb2, 0x02, 0xd4, 0x01, 0x2f, + 0x26, 0xda, 0x12, 0xe0, 0x01, 0x2f, 0x10, 0xda, 0x22, 0xe0, 0x00, 0x2c, + 0x0f, 0xd4, 0x66, 0xb9, 0x4f, 0xf0, 0xff, 0x31, 0x01, 0xa8, 0x07, 0xf0, + 0xa0, 0xfe, 0x00, 0x28, 0x44, 0xbf, 0x03, 0x98, 0x00, 0x28, 0x02, 0xd5, + 0x4f, 0xf0, 0x00, 0x40, 0xc8, 0xe0, 0x00, 0x20, 0xc6, 0xe0, 0x07, 0xf0, + 0xbb, 0xfe, 0x22, 0x21, 0x01, 0x60, 0x5e, 0xb9, 0x4f, 0xf0, 0xff, 0x31, + 0x01, 0xa8, 0x07, 0xf0, 0x8c, 0xfe, 0x00, 0x28, 0x44, 0xbf, 0x03, 0x98, + 0x00, 0x28, 0x01, 0xd5, 0x4f, 0x48, 0xb5, 0xe0, 0x4f, 0xf0, 0xff, 0x40, + 0xb2, 0xe0, 0x03, 0x98, 0x00, 0x28, 0x48, 0xbf, 0x00, 0x2e, 0x06, 0xd5, + 0x07, 0xf0, 0xa2, 0xfe, 0x21, 0x21, 0x01, 0x60, 0x6f, 0xf0, 0x00, 0x40, + 0xa6, 0xe0, 0x00, 0x21, 0xff, 0xf7, 0x38, 0xff, 0x38, 0xbf, 0x00, 0x26, + 0x08, 0xd3, 0x80, 0xf0, 0x00, 0x40, 0x03, 0x90, 0x4f, 0xf0, 0xff, 0x31, + 0x01, 0xa8, 0x07, 0xf0, 0x68, 0xfe, 0x06, 0x46, 0x03, 0x98, 0x40, 0x49, + 0xff, 0xf7, 0x0e, 0xfe, 0x06, 0xd2, 0x01, 0x46, 0x4f, 0xf0, 0x80, 0x40, + 0xff, 0xf7, 0x1a, 0xfe, 0x03, 0x90, 0x7f, 0x1e, 0x03, 0x99, 0x3b, 0x48, + 0xff, 0xf7, 0x78, 0xfd, 0x83, 0x46, 0x03, 0x99, 0x4f, 0xf0, 0x7e, 0x50, + 0xff, 0xf7, 0x72, 0xfd, 0x01, 0x46, 0x58, 0x46, 0xff, 0xf7, 0x7c, 0xfc, + 0x80, 0x46, 0x41, 0x46, 0xff, 0xf7, 0x06, 0xfe, 0x82, 0x46, 0xcd, 0xf8, + 0x0c, 0xb0, 0x06, 0xf0, 0xcb, 0xff, 0x51, 0x46, 0xff, 0xf7, 0xfe, 0xfd, + 0x03, 0x99, 0xff, 0xf7, 0xeb, 0xfc, 0x41, 0x46, 0xff, 0xf7, 0xf8, 0xfd, + 0x01, 0x46, 0x03, 0x98, 0xff, 0xf7, 0x58, 0xfd, 0x80, 0x46, 0x38, 0xb2, + 0xff, 0xf7, 0x48, 0xfc, 0x07, 0x46, 0x40, 0x46, 0x27, 0x49, 0xff, 0xf7, + 0x5d, 0xfc, 0x39, 0x46, 0xff, 0xf7, 0x4c, 0xfd, 0x01, 0x90, 0x21, 0x46, + 0xff, 0xf7, 0xe4, 0xfd, 0x00, 0x90, 0x4f, 0xf0, 0x47, 0x41, 0xff, 0xf7, + 0xcd, 0xfd, 0x43, 0xd3, 0x20, 0x49, 0xff, 0xf7, 0xe3, 0xfe, 0x41, 0xd9, + 0x00, 0x21, 0xff, 0xf7, 0xc5, 0xfd, 0x01, 0x46, 0x34, 0xbf, 0x4f, 0xf0, + 0x3f, 0x40, 0x4f, 0xf0, 0x7c, 0x50, 0xff, 0xf7, 0x33, 0xfd, 0xff, 0xf7, + 0x39, 0xfe, 0x82, 0x46, 0x38, 0x46, 0x21, 0x46, 0xff, 0xf7, 0xc8, 0xfd, + 0x07, 0x46, 0x50, 0x46, 0xff, 0xf7, 0x1c, 0xfc, 0x01, 0x46, 0x38, 0x46, + 0xff, 0xf7, 0xb0, 0xfc, 0x10, 0x49, 0xff, 0xf7, 0xbd, 0xfd, 0x07, 0x46, + 0x40, 0x46, 0x21, 0x46, 0xff, 0xf7, 0xb8, 0xfd, 0x39, 0x46, 0xff, 0xf7, + 0x19, 0xfd, 0x00, 0x90, 0x1d, 0xb1, 0xa5, 0xf8, 0x00, 0xa0, 0x4f, 0xf0, + 0x00, 0x0a, 0x52, 0x46, 0x4f, 0xf0, 0x7e, 0x51, 0x68, 0x46, 0x07, 0xf0, + 0x19, 0xfe, 0x68, 0xb1, 0x01, 0x28, 0x0d, 0xd0, 0x13, 0xe0, 0x00, 0xbf, + 0x00, 0x00, 0x80, 0xff, 0xf3, 0x04, 0x35, 0x3f, 0x00, 0x00, 0x80, 0xbf, + 0x18, 0x72, 0x31, 0x3f, 0x01, 0x00, 0x00, 0x47, 0x00, 0x20, 0x01, 0xe0, + 0x4f, 0xf0, 0xff, 0x40, 0x00, 0x90, 0x07, 0xf0, 0xfd, 0xfd, 0x22, 0x21, + 0x01, 0x60, 0x00, 0x2e, 0x00, 0x98, 0x18, 0xbf, 0x80, 0xf0, 0x00, 0x40, + 0x04, 0xb0, 0xbd, 0xe8, 0xf0, 0x8d, 0x00, 0x22, 0xa0, 0xe6, 0x00, 0x00, + 0xd2, 0xb2, 0x20, 0x3a, 0x22, 0xbf, 0x00, 0xfa, 0x02, 0xf1, 0x00, 0x20, + 0x70, 0x47, 0x52, 0x42, 0xd0, 0x41, 0xd2, 0xf1, 0x20, 0x02, 0x91, 0x40, + 0x41, 0x40, 0xd0, 0x40, 0x90, 0x40, 0x41, 0x40, 0x70, 0x47, 0x00, 0x00, + 0x38, 0xb5, 0x05, 0x46, 0x0d, 0x48, 0x0c, 0x46, 0x41, 0x78, 0x21, 0x70, + 0x6a, 0x46, 0x00, 0x78, 0x60, 0x70, 0xa1, 0x1d, 0x28, 0x46, 0x00, 0xf0, + 0x89, 0xf8, 0x0f, 0xf2, 0x50, 0x10, 0x30, 0xf8, 0x25, 0x10, 0x01, 0xf1, + 0x8c, 0x41, 0x00, 0xeb, 0x85, 0x00, 0x09, 0x78, 0xe1, 0x70, 0x40, 0x88, + 0x00, 0xf1, 0x8c, 0x40, 0x00, 0x78, 0x20, 0x71, 0x31, 0xbd, 0x00, 0x00, + 0x6d, 0x09, 0x00, 0x46, 0x38, 0xb5, 0x0d, 0x46, 0x2a, 0x79, 0xe9, 0x78, + 0x04, 0x46, 0x00, 0xf0, 0x47, 0xf8, 0xe9, 0x88, 0x20, 0x46, 0x00, 0xf0, + 0x59, 0xf8, 0x29, 0x78, 0x40, 0xf6, 0x6e, 0x10, 0xfb, 0xf7, 0x86, 0xfe, + 0x69, 0x78, 0xbd, 0xe8, 0x34, 0x40, 0x40, 0xf6, 0x6d, 0x10, 0xfb, 0xf7, + 0x7f, 0xbe, 0x70, 0xb5, 0x55, 0x1c, 0x0e, 0x46, 0x03, 0x2e, 0x04, 0x46, + 0x1d, 0xd0, 0x10, 0x78, 0x00, 0xf0, 0x9f, 0x00, 0x10, 0x70, 0x02, 0x2e, + 0x28, 0x78, 0x00, 0xf0, 0xe0, 0x00, 0x28, 0x70, 0x08, 0xd1, 0x90, 0x78, + 0x13, 0x78, 0x43, 0xea, 0x40, 0x13, 0x13, 0x70, 0x2b, 0x78, 0x43, 0xea, + 0x40, 0x10, 0x28, 0x70, 0x00, 0x2c, 0x10, 0x78, 0x07, 0xbf, 0x00, 0xf0, + 0xfc, 0x00, 0x08, 0x43, 0x00, 0xf0, 0xf3, 0x00, 0x40, 0xea, 0x81, 0x00, + 0x10, 0x70, 0x40, 0xf6, 0x6e, 0x10, 0x11, 0x78, 0xfb, 0xf7, 0x56, 0xfe, + 0x29, 0x78, 0x40, 0xf6, 0x6d, 0x10, 0xfb, 0xf7, 0x51, 0xfe, 0x02, 0x2e, + 0x05, 0xd1, 0x20, 0x46, 0xbd, 0xe8, 0x70, 0x40, 0x00, 0x22, 0x00, 0x21, + 0x00, 0xe0, 0x70, 0xbd, 0x70, 0xb5, 0x39, 0x2a, 0x0f, 0xf2, 0x88, 0x06, + 0x04, 0x46, 0xac, 0xbf, 0x42, 0xf0, 0x40, 0x05, 0x02, 0xf0, 0xbf, 0x05, + 0x36, 0xf8, 0x24, 0x00, 0xfb, 0xf7, 0x3a, 0xfe, 0x29, 0x46, 0x06, 0xeb, + 0x84, 0x00, 0xbd, 0xe8, 0x70, 0x40, 0x40, 0x88, 0xfb, 0xf7, 0x32, 0xbe, + 0x70, 0xb5, 0x04, 0x46, 0x0f, 0xf2, 0x64, 0x06, 0x06, 0xeb, 0x84, 0x00, + 0x0d, 0x46, 0x40, 0x88, 0x29, 0x0a, 0xfb, 0xf7, 0x27, 0xfe, 0x36, 0xf8, + 0x24, 0x00, 0xe9, 0xb2, 0xbd, 0xe8, 0x70, 0x40, 0xfb, 0xf7, 0x20, 0xbe, + 0x2d, 0xe9, 0xf0, 0x41, 0x06, 0x46, 0x0f, 0xf2, 0x48, 0x08, 0x08, 0xeb, + 0x86, 0x00, 0x0c, 0x46, 0x47, 0x88, 0x15, 0x46, 0x00, 0x21, 0x38, 0x46, + 0xfb, 0xf7, 0x12, 0xfe, 0x07, 0xf1, 0x8c, 0x40, 0x00, 0x78, 0x38, 0xf8, + 0x26, 0x10, 0x01, 0xf1, 0x8c, 0x41, 0x09, 0x78, 0x41, 0xea, 0x00, 0x20, + 0x81, 0x0a, 0x80, 0x05, 0x29, 0x70, 0x80, 0x0d, 0x20, 0x80, 0xbd, 0xe8, + 0xf0, 0x81, 0x00, 0x00, 0x67, 0x09, 0x68, 0x09, 0x6a, 0x09, 0x6b, 0x09, + 0x60, 0x09, 0x61, 0x09, 0x62, 0x09, 0x63, 0x09, 0x40, 0x09, 0x41, 0x09, + 0x42, 0x09, 0x43, 0x09, 0x13, 0xf0, 0x00, 0x4c, 0x03, 0xd5, 0x5b, 0x42, + 0x52, 0x42, 0x63, 0xf1, 0x00, 0x03, 0x9c, 0xea, 0x21, 0x0c, 0x00, 0xf0, + 0x17, 0x80, 0x10, 0xb5, 0x64, 0x46, 0x03, 0xd3, 0x49, 0x42, 0x40, 0x42, + 0x61, 0xf1, 0x00, 0x01, 0x00, 0xf0, 0x0e, 0xf8, 0x64, 0x00, 0x04, 0xd3, + 0x49, 0x42, 0x40, 0x42, 0x61, 0xf1, 0x00, 0x01, 0x24, 0x42, 0x03, 0xd5, + 0x5b, 0x42, 0x52, 0x42, 0x63, 0xf1, 0x00, 0x03, 0x10, 0xbd, 0x00, 0x00, + 0x1b, 0x42, 0x13, 0xd1, 0x09, 0x42, 0x36, 0xd1, 0x2a, 0xb1, 0x84, 0x46, + 0xb0, 0xfb, 0xf2, 0xf0, 0x02, 0xfb, 0x10, 0xc2, 0x70, 0x47, 0x07, 0xf0, + 0xff, 0xbd, 0xfc, 0xd3, 0x00, 0x22, 0x00, 0x23, 0x70, 0x47, 0x0b, 0x00, + 0x02, 0x00, 0x00, 0x21, 0x00, 0x20, 0x70, 0x47, 0x90, 0x42, 0x71, 0xeb, + 0x03, 0x0c, 0xf6, 0xd3, 0x70, 0xb5, 0xb1, 0xfa, 0x81, 0xf4, 0xb3, 0xfa, + 0x83, 0xf5, 0x2c, 0x1b, 0xa3, 0x40, 0xc4, 0xf1, 0x20, 0x05, 0x32, 0xfa, + 0x05, 0xf6, 0x33, 0x43, 0xa2, 0x40, 0x5f, 0xf0, 0x00, 0x46, 0xe6, 0x40, + 0x02, 0xe0, 0x5b, 0x08, 0x5f, 0xea, 0x32, 0x02, 0x84, 0x1a, 0x71, 0xeb, + 0x03, 0x05, 0x24, 0xbf, 0x20, 0x46, 0x29, 0x46, 0x76, 0x41, 0xf4, 0xd3, + 0x02, 0x00, 0x0b, 0x00, 0x30, 0x00, 0x00, 0x21, 0x70, 0xbd, 0x01, 0x2a, + 0xcf, 0xd9, 0x70, 0xb5, 0x14, 0x0c, 0x20, 0xd0, 0xb1, 0xfa, 0x81, 0xf4, + 0xb2, 0xfa, 0x82, 0xf5, 0xc4, 0xf1, 0x20, 0x04, 0x64, 0x19, 0xb4, 0xf1, + 0x20, 0x06, 0xd6, 0xd3, 0xb2, 0x40, 0x5f, 0xf0, 0x00, 0x44, 0xf4, 0x40, + 0x00, 0x25, 0x02, 0xe0, 0x52, 0x08, 0x5f, 0xea, 0x33, 0x03, 0xc6, 0x1a, + 0x71, 0xeb, 0x02, 0x0e, 0x24, 0xbf, 0x30, 0x46, 0x71, 0x46, 0x64, 0x41, + 0x6d, 0x41, 0xf3, 0xd3, 0x02, 0x00, 0x0b, 0x00, 0x20, 0x00, 0x29, 0x00, + 0x70, 0xbd, 0x0c, 0x46, 0xb1, 0xfb, 0xf2, 0xf1, 0x02, 0xfb, 0x11, 0x45, + 0x2d, 0x04, 0x45, 0xea, 0x10, 0x45, 0xb5, 0xfb, 0xf2, 0xf4, 0x02, 0xfb, + 0x14, 0x55, 0x80, 0xb2, 0x40, 0xea, 0x05, 0x45, 0xb5, 0xfb, 0xf2, 0xf0, + 0x02, 0xfb, 0x10, 0x52, 0x40, 0xea, 0x04, 0x40, 0x70, 0xbd, 0x00, 0x00, + 0x10, 0xb5, 0xda, 0x48, 0x01, 0x1d, 0x00, 0x22, 0x00, 0x23, 0x0c, 0xc1, + 0x00, 0x21, 0x00, 0x24, 0x1e, 0xc0, 0x10, 0xbd, 0x2d, 0xe9, 0xf0, 0x43, + 0xd5, 0x48, 0x87, 0xb0, 0x80, 0x7a, 0x00, 0xf0, 0x03, 0x08, 0x40, 0x46, + 0xfb, 0xf7, 0xb0, 0xfd, 0x00, 0x24, 0x08, 0xb9, 0x02, 0x20, 0x55, 0xe0, + 0x00, 0x26, 0xdf, 0xf8, 0x38, 0x93, 0xcf, 0x4d, 0x28, 0xfa, 0x06, 0xf0, + 0xc0, 0x07, 0x49, 0xd5, 0x00, 0x27, 0x28, 0x78, 0x01, 0x21, 0xb9, 0x40, + 0x08, 0x42, 0x3f, 0xd0, 0x00, 0x21, 0x00, 0x20, 0xfb, 0xf7, 0x85, 0xff, + 0x01, 0x2f, 0x06, 0xd1, 0x03, 0xa9, 0x30, 0x46, 0xfe, 0xf7, 0x26, 0xfd, + 0x05, 0xf1, 0x18, 0x01, 0x11, 0xe0, 0x68, 0x46, 0xfd, 0xf7, 0x27, 0xfe, + 0x01, 0xa8, 0xfe, 0xf7, 0xce, 0xf9, 0x01, 0x21, 0xf0, 0xb2, 0xfe, 0xf7, + 0xcb, 0xf8, 0xfe, 0xf7, 0x06, 0xf9, 0xb0, 0x1c, 0x28, 0x21, 0x80, 0xb2, + 0xfd, 0xf7, 0x2c, 0xfe, 0x29, 0x1d, 0x09, 0xf1, 0x04, 0x00, 0x00, 0xeb, + 0x86, 0x00, 0x00, 0xeb, 0x47, 0x02, 0x30, 0x46, 0x00, 0xf0, 0x6e, 0xf8, + 0x04, 0x46, 0x40, 0x1e, 0x80, 0x41, 0x09, 0xeb, 0x46, 0x01, 0xc0, 0x0f, + 0x78, 0x54, 0x01, 0x2f, 0x04, 0xd1, 0x03, 0xa9, 0x30, 0x46, 0xfe, 0xf7, + 0x11, 0xfd, 0x05, 0xe0, 0x68, 0x46, 0xfd, 0xf7, 0x05, 0xfe, 0x01, 0xa8, + 0xfe, 0xf7, 0xb2, 0xf9, 0x00, 0x20, 0xfb, 0xf7, 0xa7, 0xff, 0x14, 0xb9, + 0x7f, 0x1c, 0x02, 0x2f, 0xb7, 0xd3, 0x14, 0xb9, 0x76, 0x1c, 0x02, 0x2e, + 0xae, 0xd3, 0x20, 0x46, 0x07, 0xb0, 0xbd, 0xe8, 0xf0, 0x83, 0xa2, 0x4a, + 0x02, 0xeb, 0x41, 0x01, 0x40, 0x5c, 0x70, 0x47, 0x9f, 0x4a, 0x02, 0xeb, + 0x81, 0x01, 0x01, 0xeb, 0x40, 0x00, 0x00, 0x1d, 0x70, 0x47, 0x80, 0xb5, + 0xfe, 0xf7, 0x4f, 0xfa, 0xfe, 0xf7, 0x69, 0xfa, 0x02, 0x28, 0x01, 0xd1, + 0x03, 0x20, 0x02, 0xbd, 0x01, 0x28, 0x0c, 0xbf, 0x04, 0x20, 0x00, 0x20, + 0x02, 0xbd, 0xf0, 0xb5, 0x05, 0x46, 0x0c, 0x46, 0x96, 0x48, 0x00, 0xeb, + 0xc4, 0x02, 0xd2, 0xe9, 0x00, 0x01, 0x95, 0x4a, 0x02, 0xeb, 0xc4, 0x06, + 0xd6, 0xe9, 0x00, 0x23, 0x80, 0x18, 0x59, 0x41, 0x2a, 0x46, 0x07, 0xf0, + 0xf9, 0xfc, 0xa0, 0xfb, 0x00, 0x67, 0x00, 0xfb, 0x01, 0x77, 0x01, 0xfb, + 0x00, 0x77, 0x8e, 0x48, 0x00, 0xeb, 0xc4, 0x02, 0xd2, 0xe9, 0x00, 0x01, + 0x8c, 0x4a, 0x02, 0xeb, 0xc4, 0x04, 0xd4, 0xe9, 0x00, 0x23, 0x80, 0x1a, + 0x99, 0x41, 0x2a, 0x46, 0x07, 0xf0, 0xe4, 0xfc, 0xa0, 0xfb, 0x00, 0x23, + 0x00, 0xfb, 0x01, 0x33, 0x01, 0xfb, 0x00, 0x33, 0xb0, 0x18, 0x47, 0xeb, + 0x03, 0x01, 0xf0, 0xbd, 0x2d, 0xe9, 0xf5, 0x4f, 0x0e, 0x46, 0x81, 0xb0, + 0xb6, 0xf9, 0x08, 0x10, 0xb6, 0xf9, 0x06, 0x00, 0xfe, 0xf7, 0xd0, 0xfc, + 0x31, 0x69, 0xf0, 0x68, 0xfe, 0xf7, 0xd4, 0xfc, 0x01, 0x98, 0xfe, 0xf7, + 0xd5, 0xfc, 0x4f, 0xf0, 0x00, 0x0a, 0xd0, 0x46, 0xf0, 0x78, 0x00, 0x27, + 0xc1, 0x46, 0x18, 0xb1, 0xfe, 0xf7, 0x81, 0xfa, 0xc3, 0x46, 0x04, 0xe0, + 0x08, 0x20, 0xfe, 0xf7, 0x6f, 0xfa, 0x4f, 0xf0, 0x08, 0x0b, 0xb6, 0xf9, + 0x06, 0x00, 0x00, 0x28, 0x48, 0xbf, 0x40, 0x42, 0xb6, 0xf9, 0x08, 0x40, + 0x00, 0x2c, 0x48, 0xbf, 0x64, 0x42, 0x84, 0x42, 0x38, 0xbf, 0x04, 0x46, + 0x20, 0x46, 0x00, 0xf0, 0xb7, 0xfb, 0x11, 0x28, 0x04, 0xd2, 0x20, 0x46, + 0x00, 0xf0, 0xb2, 0xfb, 0x11, 0x30, 0x00, 0xe0, 0x22, 0x20, 0xb1, 0x78, + 0x08, 0x18, 0x1d, 0x28, 0x26, 0xbf, 0x1c, 0x38, 0x00, 0x90, 0xcd, 0xf8, + 0x00, 0x80, 0x34, 0x78, 0x10, 0xe0, 0x00, 0x25, 0x00, 0x98, 0x29, 0x46, + 0xff, 0xf7, 0x87, 0xff, 0x89, 0x45, 0x05, 0xdc, 0x01, 0xdb, 0x80, 0x45, + 0x02, 0xd2, 0x2f, 0x19, 0x80, 0x46, 0x89, 0x46, 0x6d, 0x1c, 0x03, 0x2d, + 0xf0, 0xd3, 0xe4, 0x1c, 0x70, 0x78, 0x80, 0x1e, 0xa0, 0x42, 0x08, 0xd3, + 0x01, 0x98, 0x21, 0x04, 0x00, 0xf0, 0x43, 0xf8, 0xff, 0xf7, 0x63, 0xff, + 0x5f, 0xea, 0x00, 0x0a, 0xe1, 0xd0, 0x00, 0xf0, 0x36, 0xf8, 0xf0, 0x78, + 0x00, 0x28, 0x2b, 0xd1, 0x02, 0x99, 0x09, 0x78, 0x01, 0x98, 0x49, 0x1e, + 0x09, 0x04, 0x00, 0xf0, 0x32, 0xf8, 0x00, 0x24, 0x01, 0xe0, 0x08, 0x2c, + 0x1b, 0xd0, 0x20, 0x46, 0xfe, 0xf7, 0x1a, 0xfa, 0xff, 0xf7, 0x4b, 0xff, + 0x5f, 0xea, 0x00, 0x0a, 0x16, 0xd1, 0x00, 0x25, 0x00, 0x98, 0x29, 0x46, + 0xff, 0xf7, 0x51, 0xff, 0x89, 0x45, 0x09, 0xdc, 0x01, 0xdb, 0x80, 0x45, + 0x06, 0xd2, 0x02, 0x9a, 0x12, 0x78, 0xaa, 0x18, 0x57, 0x1e, 0xa3, 0x46, + 0x80, 0x46, 0x89, 0x46, 0x6d, 0x1c, 0x03, 0x2d, 0xec, 0xd3, 0x64, 0x1c, + 0x10, 0x2c, 0xde, 0xd3, 0x00, 0xf0, 0x07, 0xf8, 0xfe, 0xf7, 0x5f, 0xfc, + 0xfe, 0xf7, 0x05, 0xfa, 0x50, 0x46, 0xbd, 0xe8, 0xfe, 0x8f, 0x02, 0x98, + 0x07, 0x70, 0x02, 0x98, 0x80, 0xf8, 0x01, 0xb0, 0x70, 0x47, 0x01, 0xf4, + 0xfe, 0x01, 0x41, 0xea, 0x80, 0x70, 0xb1, 0x78, 0xc9, 0x05, 0x01, 0xf0, + 0x7e, 0x51, 0x08, 0x43, 0x31, 0x79, 0xc9, 0x03, 0x01, 0xf4, 0x00, 0x41, + 0x08, 0x43, 0x40, 0xf0, 0x00, 0x40, 0x40, 0xf4, 0x80, 0x40, 0xfe, 0xf7, + 0xb8, 0xb9, 0x70, 0xb5, 0x04, 0x9c, 0x0e, 0x46, 0x15, 0x46, 0x19, 0x46, + 0x22, 0x46, 0xff, 0xf7, 0x45, 0xff, 0xc8, 0xb9, 0x21, 0x78, 0x71, 0x18, + 0x21, 0x70, 0xad, 0xb1, 0xea, 0x10, 0x05, 0xeb, 0x12, 0x72, 0x12, 0x11, + 0xc9, 0xb2, 0x51, 0x18, 0x63, 0x78, 0xa5, 0xeb, 0x02, 0x12, 0xd2, 0x18, + 0x12, 0xb2, 0x00, 0x2a, 0x02, 0xd5, 0x49, 0x1e, 0x10, 0x32, 0x03, 0xe0, + 0x10, 0x2a, 0xa4, 0xbf, 0x49, 0x1c, 0x10, 0x3a, 0x21, 0x70, 0x62, 0x70, + 0x70, 0xbd, 0x10, 0xb5, 0x00, 0x22, 0x17, 0x4b, 0x44, 0x24, 0x00, 0xf0, + 0x31, 0xf8, 0xdc, 0x63, 0x01, 0x24, 0xa3, 0xf8, 0x40, 0x40, 0x94, 0x24, + 0x13, 0x4b, 0x00, 0xf0, 0x29, 0xf8, 0x9c, 0x61, 0x01, 0x24, 0x9c, 0x83, + 0x58, 0xb1, 0x11, 0x4b, 0x54, 0x24, 0x00, 0xf0, 0x21, 0xf8, 0x9c, 0x64, + 0x01, 0xeb, 0x82, 0x04, 0xa4, 0x68, 0xdc, 0x64, 0x01, 0x24, 0xa3, 0xf8, + 0x50, 0x40, 0x52, 0x1c, 0x02, 0x2a, 0xe0, 0xd3, 0x10, 0xbd, 0x00, 0x00, + 0x78, 0xb8, 0x00, 0x20, 0x78, 0x29, 0x00, 0x20, 0x20, 0x29, 0x00, 0x20, + 0x60, 0x01, 0x00, 0x45, 0xa8, 0x01, 0x00, 0x45, 0x90, 0x01, 0x00, 0x45, + 0x78, 0x01, 0x00, 0x45, 0xa8, 0xef, 0x00, 0x20, 0x74, 0x27, 0x00, 0x20, + 0x94, 0xed, 0x00, 0x20, 0x04, 0xfb, 0x02, 0x33, 0x51, 0xf8, 0x22, 0x40, + 0x70, 0x47, 0x01, 0xb4, 0xbd, 0xf8, 0x02, 0x00, 0x5a, 0x28, 0x03, 0xdb, + 0xbd, 0xf8, 0x00, 0x00, 0x10, 0x28, 0x01, 0xdb, 0x00, 0x20, 0x00, 0xe0, + 0x01, 0x20, 0x01, 0xb0, 0x70, 0x47, 0xfe, 0xb5, 0x04, 0x46, 0x0d, 0x46, + 0x00, 0x26, 0x55, 0xf8, 0x26, 0x00, 0x00, 0x90, 0xff, 0xf7, 0xe9, 0xff, + 0x07, 0x46, 0x34, 0xb1, 0x05, 0xeb, 0x86, 0x00, 0x80, 0x68, 0x00, 0x90, + 0xff, 0xf7, 0xe1, 0xff, 0x00, 0xe0, 0x01, 0x20, 0x17, 0xb1, 0x10, 0xb1, + 0x01, 0x20, 0x00, 0xe0, 0x00, 0x20, 0x01, 0xa9, 0xc0, 0xb2, 0x41, 0xf8, + 0x26, 0x00, 0x76, 0x1c, 0x02, 0x2e, 0xe4, 0xd3, 0x01, 0x98, 0x00, 0x28, + 0x1e, 0xbf, 0x02, 0x98, 0x00, 0x28, 0x01, 0x20, 0xc0, 0xb2, 0xfe, 0xbd, + 0x35, 0x49, 0x00, 0x20, 0x08, 0x80, 0x70, 0x47, 0x07, 0xf0, 0x9d, 0xbb, + 0x07, 0xf0, 0x9c, 0xbb, 0x07, 0xf0, 0x9b, 0xbb, 0x07, 0xf0, 0x9b, 0xbb, + 0x4f, 0xf0, 0x80, 0x73, 0x42, 0xf8, 0x04, 0x39, 0x10, 0x60, 0x10, 0x1f, + 0x2d, 0x4a, 0x40, 0xf8, 0x04, 0x29, 0x4f, 0xf0, 0x12, 0x32, 0x40, 0xf8, + 0x04, 0x29, 0x4f, 0xf0, 0x03, 0x32, 0x40, 0xf8, 0x04, 0x29, 0x4f, 0xf0, + 0x02, 0x32, 0x40, 0xf8, 0x04, 0x29, 0x4f, 0xf0, 0x01, 0x32, 0x40, 0xf8, + 0x04, 0x29, 0x40, 0xf8, 0x04, 0x19, 0x4f, 0xf0, 0x11, 0x31, 0x40, 0xf8, + 0x04, 0x19, 0x4f, 0xf0, 0x10, 0x31, 0x40, 0xf8, 0x04, 0x19, 0x4f, 0xf0, + 0x09, 0x31, 0x40, 0xf8, 0x04, 0x19, 0x4f, 0xf0, 0x08, 0x31, 0x40, 0xf8, + 0x04, 0x19, 0x4f, 0xf0, 0x07, 0x31, 0x40, 0xf8, 0x04, 0x19, 0x4f, 0xf0, + 0x06, 0x31, 0x40, 0xf8, 0x04, 0x19, 0x4f, 0xf0, 0x05, 0x31, 0x40, 0xf8, + 0x04, 0x19, 0x4f, 0xf0, 0x04, 0x31, 0x01, 0x60, 0x70, 0x47, 0x07, 0xf0, + 0x5f, 0xbb, 0x07, 0xf0, 0x64, 0xbb, 0x80, 0xb5, 0x07, 0xf0, 0x62, 0xfb, + 0x0e, 0x48, 0x01, 0x88, 0x49, 0x1c, 0x01, 0x80, 0x89, 0xb2, 0x05, 0x29, + 0x05, 0xd3, 0x00, 0x21, 0x01, 0x80, 0xbd, 0xe8, 0x01, 0x40, 0xfb, 0xf7, + 0xbf, 0xb9, 0x01, 0xbd, 0x80, 0xb5, 0x00, 0xf0, 0x13, 0xf8, 0x08, 0x49, + 0x0a, 0x78, 0x52, 0x1c, 0x0a, 0x70, 0x80, 0xf3, 0x11, 0x88, 0xfa, 0xf7, + 0xcd, 0xf9, 0xbd, 0xe8, 0x01, 0x40, 0xfa, 0xf7, 0x67, 0xb9, 0x00, 0x00, + 0x9c, 0xf3, 0x00, 0x20, 0xbd, 0x2a, 0x00, 0x01, 0x20, 0xbd, 0x00, 0x20, + 0xef, 0xf3, 0x11, 0x80, 0x60, 0x21, 0x81, 0xf3, 0x11, 0x88, 0x70, 0x47, + 0x80, 0xf3, 0x11, 0x88, 0x70, 0x47, 0x1b, 0x48, 0xff, 0x21, 0x01, 0x70, + 0x00, 0x20, 0x80, 0xf3, 0x09, 0x88, 0x19, 0x48, 0x01, 0x21, 0x01, 0x70, + 0x18, 0x48, 0x19, 0x49, 0x01, 0x60, 0x62, 0xb6, 0xfe, 0xe7, 0x16, 0x48, + 0x16, 0x49, 0x01, 0x60, 0x70, 0x47, 0x14, 0x48, 0x14, 0x49, 0x01, 0x60, + 0x70, 0x47, 0x72, 0xb6, 0xef, 0xf3, 0x09, 0x80, 0x28, 0xb1, 0x20, 0x38, + 0x80, 0xe8, 0xf0, 0x0f, 0x10, 0x49, 0x09, 0x68, 0x08, 0x60, 0x00, 0xb5, + 0x0f, 0x48, 0x80, 0x47, 0x5d, 0xf8, 0x04, 0xeb, 0x0e, 0x48, 0x0f, 0x49, + 0x0a, 0x78, 0x02, 0x70, 0x0a, 0x48, 0x0e, 0x49, 0x0a, 0x68, 0x02, 0x60, + 0x10, 0x68, 0x90, 0xe8, 0xf0, 0x0f, 0x20, 0x30, 0x80, 0xf3, 0x09, 0x88, + 0x4e, 0xf0, 0x04, 0x0e, 0x62, 0xb6, 0x70, 0x47, 0x22, 0xed, 0x00, 0xe0, + 0x25, 0xbd, 0x00, 0x20, 0x04, 0xed, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x10, + 0x40, 0xbd, 0x00, 0x20, 0x03, 0x7a, 0x00, 0x01, 0x22, 0xbd, 0x00, 0x20, + 0x23, 0xbd, 0x00, 0x20, 0x48, 0xbd, 0x00, 0x20, 0x00, 0x22, 0x07, 0xf0, + 0xeb, 0xba, 0x00, 0x00, 0x62, 0xf3, 0x0f, 0x22, 0x62, 0xf3, 0x1f, 0x42, + 0x40, 0x18, 0x10, 0xf0, 0x03, 0x03, 0x08, 0xd0, 0xc9, 0x1a, 0x1f, 0xd3, + 0xdb, 0x07, 0x48, 0xbf, 0x00, 0xf8, 0x01, 0x2d, 0x28, 0xbf, 0x20, 0xf8, + 0x02, 0x2d, 0x13, 0x00, 0x30, 0xb4, 0x14, 0x46, 0x15, 0x46, 0x10, 0x39, + 0x28, 0xbf, 0x20, 0xe9, 0x3c, 0x00, 0xfa, 0xd8, 0x49, 0x07, 0x28, 0xbf, + 0x20, 0xe9, 0x0c, 0x00, 0x48, 0xbf, 0x40, 0xf8, 0x04, 0x2d, 0x89, 0x00, + 0x28, 0xbf, 0x20, 0xf8, 0x02, 0x2d, 0x48, 0xbf, 0x00, 0xf8, 0x01, 0x2d, + 0x30, 0xbc, 0x70, 0x47, 0xc9, 0x18, 0x18, 0xbf, 0x00, 0xf8, 0x01, 0x2d, + 0xcb, 0x07, 0x28, 0xbf, 0x00, 0xf8, 0x01, 0x2d, 0x70, 0x47, 0x00, 0x00, + 0x58, 0xb5, 0x04, 0x46, 0x03, 0x2c, 0x16, 0xda, 0x04, 0xf0, 0x00, 0xff, + 0xbb, 0x4a, 0xbc, 0x4e, 0x12, 0x68, 0x09, 0x07, 0x41, 0xea, 0x10, 0x11, + 0x00, 0x07, 0x00, 0x23, 0xff, 0xf7, 0x78, 0xfc, 0x06, 0xeb, 0xc4, 0x02, + 0xc2, 0xe9, 0x00, 0x01, 0x20, 0x46, 0x04, 0xf0, 0xef, 0xfe, 0x06, 0xeb, + 0xc4, 0x02, 0xc2, 0xe9, 0x06, 0x01, 0x51, 0xbd, 0x7c, 0xb5, 0xb2, 0x49, + 0x0f, 0xf2, 0x28, 0x34, 0x09, 0x78, 0x01, 0xf0, 0x03, 0x02, 0x89, 0x08, + 0x01, 0xf0, 0x01, 0x03, 0x60, 0xcc, 0x69, 0x46, 0x01, 0x2a, 0x60, 0xc1, + 0x4f, 0xf4, 0x7a, 0x71, 0xa1, 0xfb, 0x00, 0x01, 0x04, 0xd1, 0x1b, 0xb1, + 0x49, 0x00, 0x41, 0xea, 0xd0, 0x71, 0x40, 0x00, 0x6c, 0x46, 0x04, 0xeb, + 0x83, 0x03, 0xd2, 0x5c, 0x02, 0xb0, 0xbd, 0xe8, 0x70, 0x40, 0x00, 0x23, + 0xff, 0xf7, 0x4a, 0xbc, 0xa2, 0x49, 0x09, 0x78, 0x49, 0x07, 0x46, 0xbf, + 0x05, 0x21, 0xb0, 0xfb, 0xf1, 0xf0, 0x80, 0x08, 0x70, 0x47, 0x9f, 0x49, + 0x09, 0x78, 0xc9, 0x07, 0x9e, 0x49, 0x48, 0xbf, 0x40, 0x08, 0x09, 0x78, + 0xc1, 0xf3, 0x41, 0x01, 0xc8, 0x40, 0x70, 0x47, 0x10, 0xb5, 0x95, 0x48, + 0x95, 0x4c, 0x40, 0x68, 0xff, 0xf7, 0xc4, 0xff, 0x20, 0x63, 0xff, 0xf7, + 0xe3, 0xff, 0x60, 0x63, 0xff, 0xf7, 0xe9, 0xff, 0xa0, 0x63, 0x95, 0x49, + 0xb0, 0xfb, 0xf1, 0xf0, 0x40, 0x1c, 0xe0, 0x63, 0x4f, 0xf4, 0x7a, 0x71, + 0xa0, 0x6b, 0xb0, 0xfb, 0xf1, 0xf0, 0x20, 0x64, 0x10, 0xbd, 0x4b, 0x01, + 0x19, 0x18, 0x8f, 0x48, 0x20, 0x22, 0x18, 0x18, 0x02, 0xf0, 0x10, 0xb8, + 0xf8, 0xb5, 0x8d, 0x4d, 0x8d, 0x4a, 0x29, 0x68, 0x51, 0x18, 0x00, 0x20, + 0x8c, 0x4a, 0x91, 0x42, 0x0c, 0xd2, 0x69, 0x68, 0x8b, 0x4a, 0x51, 0x18, + 0x8b, 0x4a, 0x91, 0x42, 0x06, 0xd2, 0x29, 0x7a, 0x04, 0x29, 0x03, 0xda, + 0x69, 0x89, 0xb1, 0xf5, 0x00, 0x7f, 0x00, 0xd3, 0x01, 0x20, 0xae, 0x7a, + 0x86, 0x49, 0x87, 0x4a, 0x87, 0x4b, 0x88, 0x4c, 0x03, 0x27, 0x3e, 0x42, + 0x0c, 0xd0, 0x2e, 0x7c, 0x03, 0x2e, 0x07, 0xda, 0x6e, 0x69, 0xa6, 0x19, + 0x9e, 0x42, 0x03, 0xd2, 0x6e, 0x6a, 0x00, 0xf0, 0x69, 0xf8, 0x02, 0xe0, + 0x01, 0x26, 0x00, 0xe0, 0x00, 0x26, 0x30, 0x43, 0xae, 0x7a, 0x0c, 0x27, + 0x3e, 0x42, 0x09, 0xd0, 0xee, 0x6a, 0xa6, 0x19, 0x9e, 0x42, 0x03, 0xd2, + 0xae, 0x6b, 0x00, 0xf0, 0x59, 0xf8, 0x02, 0xe0, 0x01, 0x26, 0x00, 0xe0, + 0x00, 0x26, 0x30, 0x43, 0xae, 0x7a, 0x30, 0x27, 0x3e, 0x42, 0x0b, 0xd0, + 0x2e, 0x6c, 0xa6, 0x19, 0x9e, 0x42, 0x05, 0xd2, 0xee, 0x6c, 0x73, 0x4f, + 0xbe, 0x42, 0xb6, 0x41, 0xf6, 0x0f, 0x02, 0xe0, 0x01, 0x26, 0x00, 0xe0, + 0x00, 0x26, 0x30, 0x43, 0x6e, 0x89, 0x4f, 0xf4, 0xe0, 0x77, 0x3e, 0x42, + 0x0c, 0xd0, 0x6e, 0x6d, 0xa4, 0x19, 0x9c, 0x42, 0x06, 0xd2, 0x2b, 0x6e, + 0xd2, 0x18, 0x8a, 0x42, 0x89, 0x41, 0xc9, 0x43, 0xc9, 0x0f, 0x02, 0xe0, + 0x01, 0x21, 0x00, 0xe0, 0x00, 0x21, 0x51, 0xea, 0x00, 0x04, 0x06, 0xd0, + 0x04, 0x22, 0x00, 0x23, 0x00, 0x21, 0x04, 0x20, 0x00, 0xf0, 0xe4, 0xf9, + 0x22, 0xe0, 0x4f, 0x4e, 0x64, 0x22, 0x29, 0x46, 0x30, 0x46, 0x01, 0xf0, + 0x9d, 0xff, 0x70, 0x89, 0xc0, 0xf3, 0x81, 0x00, 0x10, 0xb1, 0x00, 0x21, + 0x00, 0xf0, 0x1e, 0xf8, 0x70, 0x89, 0xc0, 0xf3, 0x01, 0x10, 0x10, 0xb1, + 0x01, 0x21, 0x00, 0xf0, 0x17, 0xf8, 0x70, 0x89, 0xc0, 0xf3, 0x82, 0x10, + 0x10, 0xb1, 0x02, 0x21, 0x00, 0xf0, 0x10, 0xf8, 0xb0, 0x7a, 0x03, 0x21, + 0x08, 0x42, 0x1c, 0xbf, 0x05, 0xf1, 0x64, 0x00, 0xff, 0xf7, 0x69, 0xff, + 0x20, 0x46, 0xf2, 0xbd, 0x96, 0x19, 0x8e, 0x42, 0xb6, 0x41, 0xf6, 0x43, + 0xf6, 0x0f, 0x70, 0x47, 0x05, 0xf1, 0x64, 0x00, 0x5d, 0xe7, 0x80, 0xb5, + 0x00, 0xf0, 0x43, 0xf8, 0x0e, 0xd0, 0x00, 0xf0, 0x35, 0xf8, 0x00, 0x21, + 0x40, 0xf2, 0x09, 0x20, 0xfb, 0xf7, 0x42, 0xf9, 0x00, 0xf0, 0x33, 0xf8, + 0x00, 0x22, 0x03, 0x21, 0x40, 0xf2, 0x0a, 0x20, 0xfb, 0xf7, 0x44, 0xf9, + 0xf8, 0x20, 0x00, 0xf0, 0x35, 0xf8, 0xbd, 0xe8, 0x02, 0x40, 0x0e, 0x20, + 0x00, 0xf0, 0xa5, 0xb8, 0x80, 0xb5, 0x05, 0x21, 0x4f, 0xf4, 0xd8, 0x70, + 0xfb, 0xf7, 0x2c, 0xf9, 0x00, 0x21, 0x4f, 0xf4, 0x82, 0x70, 0xfb, 0xf7, + 0x27, 0xf9, 0x00, 0xf0, 0x1e, 0xf8, 0x10, 0xd0, 0xff, 0x21, 0x40, 0xf2, + 0x09, 0x20, 0xfb, 0xf7, 0x1f, 0xf9, 0x00, 0xf0, 0x0b, 0xf8, 0x00, 0xf0, + 0x0e, 0xf8, 0xbd, 0xe8, 0x08, 0x40, 0x03, 0x22, 0x03, 0x21, 0x40, 0xf2, + 0x0a, 0x20, 0xfb, 0xf7, 0x1d, 0xb9, 0x01, 0xbd, 0xff, 0x21, 0x40, 0xf6, + 0x89, 0x50, 0xfb, 0xf7, 0x0d, 0xb9, 0x03, 0x22, 0x03, 0x21, 0x40, 0xf6, + 0x8a, 0x50, 0xfb, 0xf7, 0x11, 0xb9, 0x15, 0x48, 0x80, 0x7a, 0x03, 0x21, + 0x08, 0x42, 0x70, 0x47, 0x01, 0x07, 0x0a, 0xd5, 0x11, 0x49, 0x49, 0x89, + 0x01, 0xf0, 0x03, 0x02, 0x89, 0x08, 0x89, 0x01, 0x41, 0xea, 0x02, 0x11, + 0x41, 0xf0, 0x0f, 0x01, 0x08, 0x40, 0x01, 0x46, 0x4f, 0xf4, 0xd8, 0x70, + 0xfb, 0xf7, 0xf0, 0xb8, 0x00, 0x28, 0x14, 0xbf, 0x02, 0x22, 0x00, 0x22, + 0x02, 0x21, 0x4f, 0xf4, 0xd8, 0x70, 0xfb, 0xf7, 0xf1, 0xb8, 0x38, 0xb9, + 0x16, 0x49, 0x4f, 0xf0, 0x00, 0x40, 0x08, 0x60, 0x00, 0xbf, 0x00, 0xbf, + 0x00, 0xbf, 0x00, 0xbf, 0x70, 0x47, 0x00, 0x00, 0x78, 0x29, 0x00, 0x20, + 0x00, 0xf2, 0x00, 0x20, 0x19, 0x01, 0x00, 0x46, 0x02, 0x01, 0x00, 0x46, + 0x18, 0x01, 0x00, 0x46, 0x08, 0x0d, 0x00, 0x46, 0x40, 0x42, 0x0f, 0x00, + 0x00, 0x02, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0xc0, 0x87, 0x82, 0xfe, + 0xc1, 0x57, 0x95, 0x11, 0x20, 0xf9, 0xa5, 0xff, 0x21, 0x79, 0x61, 0x00, + 0x81, 0x77, 0x8e, 0x06, 0x00, 0xd3, 0xce, 0xfe, 0x01, 0x70, 0x28, 0x12, + 0x00, 0xa0, 0x15, 0xff, 0x00, 0x2d, 0x31, 0x01, 0x04, 0xed, 0x00, 0xe0, + 0x10, 0xb5, 0x04, 0x46, 0x00, 0xf0, 0x07, 0xf8, 0x01, 0x21, 0x81, 0x40, + 0x49, 0x1e, 0x21, 0x42, 0x18, 0xbf, 0x40, 0x1c, 0x10, 0xbd, 0xb0, 0xfa, + 0x80, 0xf0, 0xc0, 0xf1, 0x1f, 0x00, 0x70, 0x47, 0x04, 0x06, 0x08, 0x0c, + 0x05, 0x0f, 0x0a, 0x0f, 0x01, 0x21, 0x00, 0xf0, 0x1f, 0x02, 0x91, 0x40, + 0x11, 0x4a, 0x04, 0xe0, 0x01, 0x21, 0x00, 0xf0, 0x1f, 0x02, 0x91, 0x40, + 0x0f, 0x4a, 0x40, 0x09, 0x42, 0xf8, 0x20, 0x10, 0x70, 0x47, 0x01, 0x21, + 0x00, 0xf0, 0x1f, 0x02, 0x91, 0x40, 0x0c, 0x4a, 0xf5, 0xe7, 0x01, 0x21, + 0x00, 0xf0, 0x1f, 0x02, 0x91, 0x40, 0x0a, 0x4a, 0xef, 0xe7, 0x09, 0x01, + 0x00, 0x28, 0x06, 0xd5, 0x08, 0x4a, 0x00, 0xf0, 0x0f, 0x00, 0x80, 0x18, + 0x00, 0xf8, 0x04, 0x1c, 0x70, 0x47, 0x06, 0x4a, 0x81, 0x54, 0x70, 0x47, + 0x80, 0xe2, 0x00, 0xe0, 0x00, 0xe1, 0x00, 0xe0, 0x80, 0xe1, 0x00, 0xe0, + 0x00, 0xe2, 0x00, 0xe0, 0x18, 0xed, 0x00, 0xe0, 0x00, 0xe4, 0x00, 0xe0, + 0x42, 0x48, 0x00, 0xf1, 0x08, 0x01, 0x01, 0x60, 0x00, 0x21, 0xc1, 0x80, + 0x04, 0x21, 0x81, 0x80, 0x00, 0x21, 0x3f, 0x48, 0x81, 0x60, 0x6f, 0xf0, + 0x7f, 0x41, 0x01, 0x60, 0x15, 0x21, 0x81, 0x60, 0x70, 0x47, 0xef, 0xf3, + 0x11, 0x80, 0x60, 0x21, 0x81, 0xf3, 0x11, 0x88, 0x70, 0x47, 0x37, 0x49, + 0x0a, 0x68, 0x10, 0x60, 0x01, 0xf5, 0x80, 0x50, 0x00, 0x1d, 0x82, 0x42, + 0x2c, 0xbf, 0x01, 0xf1, 0x08, 0x00, 0x10, 0x1d, 0x08, 0x60, 0xc8, 0x88, + 0xb0, 0xf5, 0x80, 0x6f, 0xbc, 0xbf, 0x40, 0x1c, 0xc8, 0x80, 0x70, 0x47, + 0x38, 0xb5, 0x04, 0x46, 0xff, 0xf7, 0xe3, 0xff, 0x05, 0x46, 0x00, 0xf0, + 0x11, 0xf8, 0x85, 0xf3, 0x11, 0x88, 0x31, 0xbd, 0x70, 0xb5, 0x04, 0x46, + 0x0d, 0x46, 0xff, 0xf7, 0xd8, 0xff, 0x06, 0x46, 0x00, 0xf0, 0x06, 0xf8, + 0x28, 0x46, 0xff, 0xf7, 0xd8, 0xff, 0x86, 0xf3, 0x11, 0x88, 0x70, 0xbd, + 0x23, 0x48, 0x01, 0x68, 0x00, 0x22, 0x42, 0x60, 0x15, 0x22, 0x42, 0x60, + 0x44, 0xea, 0xc1, 0x10, 0xcb, 0xe7, 0x10, 0xb5, 0x1f, 0x4a, 0x04, 0x46, + 0xd2, 0xe9, 0x02, 0x01, 0x22, 0x46, 0xfb, 0xf7, 0x21, 0xfa, 0xc0, 0x07, + 0x04, 0xd5, 0x44, 0xf0, 0x00, 0x40, 0xbd, 0xe8, 0x10, 0x40, 0xcf, 0xe7, + 0x10, 0xbd, 0x38, 0xb5, 0x00, 0xf0, 0x1f, 0xf8, 0xc0, 0x07, 0x08, 0xd5, + 0x05, 0xf0, 0x01, 0x00, 0x44, 0xea, 0x80, 0x10, 0xbd, 0xe8, 0x32, 0x40, + 0x40, 0xf0, 0x00, 0x40, 0xc0, 0xe7, 0x31, 0xbd, 0x38, 0xb5, 0x00, 0xf0, + 0x10, 0xf8, 0xc0, 0x07, 0x0c, 0xd5, 0x68, 0x0e, 0x00, 0xf0, 0x40, 0x00, + 0x04, 0xf0, 0x3f, 0x02, 0x69, 0x00, 0x10, 0x43, 0xbd, 0xe8, 0x34, 0x40, + 0x49, 0x08, 0x40, 0xf0, 0x00, 0x40, 0xb7, 0xe7, 0x31, 0xbd, 0x07, 0x4a, + 0x04, 0x46, 0x0d, 0x46, 0xd2, 0xe9, 0x02, 0x01, 0x22, 0x46, 0xfb, 0xf7, + 0xef, 0xb9, 0x00, 0x00, 0xb8, 0x82, 0x00, 0x20, 0x00, 0x00, 0x30, 0x59, + 0x04, 0x00, 0x30, 0x59, 0x88, 0x02, 0x00, 0x20, 0x10, 0xb5, 0x04, 0x46, + 0x00, 0xf0, 0x07, 0xf8, 0x20, 0x46, 0x07, 0xf0, 0x5b, 0xf8, 0xbd, 0xe8, + 0x10, 0x40, 0x07, 0xf0, 0x4b, 0xb8, 0x10, 0xb5, 0x30, 0x48, 0x00, 0x21, + 0x00, 0x22, 0x00, 0x23, 0x00, 0x24, 0x1e, 0xc0, 0x10, 0xbd, 0x10, 0xb5, + 0x00, 0xf0, 0x05, 0xf8, 0x23, 0xea, 0x00, 0x00, 0x42, 0xf8, 0x21, 0x00, + 0x10, 0xbd, 0x29, 0x4a, 0x01, 0x09, 0x52, 0xf8, 0x21, 0x30, 0x01, 0x24, + 0x40, 0x00, 0x04, 0xfa, 0x00, 0xf0, 0x70, 0x47, 0x30, 0xb5, 0x02, 0x09, + 0x23, 0x4b, 0x53, 0xf8, 0x22, 0x40, 0x40, 0x00, 0x40, 0x1c, 0x07, 0x25, + 0x85, 0x40, 0xac, 0x43, 0x43, 0xf8, 0x22, 0x40, 0x01, 0xf0, 0x07, 0x01, + 0x53, 0xf8, 0x22, 0x40, 0x01, 0xfa, 0x00, 0xf0, 0x20, 0x43, 0x43, 0xf8, + 0x22, 0x00, 0x30, 0xbd, 0x19, 0x4a, 0x03, 0x09, 0x52, 0xf8, 0x23, 0x20, + 0x43, 0x00, 0x5b, 0x1c, 0xda, 0x40, 0x02, 0xf0, 0x07, 0x02, 0x8a, 0x42, + 0x38, 0xbf, 0xff, 0xf7, 0xdd, 0xbf, 0x70, 0x47, 0xf0, 0xb5, 0xef, 0xf3, + 0x10, 0x84, 0x72, 0xb6, 0x11, 0x4d, 0xd5, 0xe9, 0x00, 0x67, 0x26, 0xea, + 0x02, 0x02, 0x27, 0xea, 0x03, 0x03, 0x10, 0x43, 0x19, 0x43, 0xc5, 0xe9, + 0x00, 0x01, 0x84, 0xf3, 0x10, 0x88, 0xf0, 0xbd, 0xd0, 0xb5, 0x04, 0x46, + 0xef, 0xf3, 0x10, 0x80, 0x72, 0xb6, 0x08, 0x49, 0xd1, 0xe9, 0x00, 0x67, + 0x80, 0xf3, 0x10, 0x88, 0x26, 0xea, 0x02, 0x00, 0x27, 0xea, 0x03, 0x01, + 0x22, 0x46, 0xbd, 0xe8, 0xd0, 0x40, 0xfb, 0xf7, 0x79, 0xb9, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x49, 0x10, 0x00, 0x00, 0x49, 0x3c, 0x48, 0x01, 0x74, + 0xc9, 0xb2, 0x03, 0x29, 0x9c, 0xbf, 0x00, 0x20, 0xff, 0xf7, 0x7f, 0xbe, + 0x70, 0x47, 0x30, 0xb5, 0x37, 0x4d, 0x85, 0xb0, 0x04, 0x46, 0x55, 0xf8, + 0x24, 0x10, 0xa1, 0xb9, 0x03, 0xa9, 0x02, 0x91, 0x00, 0x90, 0x00, 0x21, + 0x33, 0x48, 0x34, 0x4b, 0x01, 0x91, 0x01, 0x22, 0x50, 0xf8, 0x24, 0x00, + 0xfa, 0xf7, 0xe8, 0xfc, 0x45, 0xf8, 0x24, 0x00, 0x9d, 0xf8, 0x0c, 0x10, + 0x48, 0x1e, 0x80, 0x41, 0xc0, 0x0f, 0xff, 0xf7, 0x62, 0xfe, 0x05, 0xb0, + 0x30, 0xbd, 0x38, 0xb5, 0x28, 0x4d, 0x04, 0x46, 0x55, 0xf8, 0x24, 0x00, + 0x20, 0xb1, 0x69, 0x46, 0xfa, 0xf7, 0x12, 0xfd, 0x00, 0xf0, 0x1b, 0xf8, + 0x00, 0x20, 0x45, 0xf8, 0x24, 0x00, 0x31, 0xbd, 0x38, 0xb5, 0x00, 0xf0, + 0x3b, 0xf8, 0x11, 0xd1, 0x1f, 0x4d, 0x55, 0xf8, 0x24, 0x00, 0x68, 0xb1, + 0x69, 0x46, 0xfa, 0xf7, 0x5d, 0xfd, 0x01, 0x28, 0x08, 0xd1, 0x00, 0xf0, + 0x08, 0xf8, 0x55, 0xf8, 0x24, 0x00, 0x69, 0x46, 0xfa, 0xf7, 0x74, 0xfd, + 0x00, 0xf0, 0x01, 0xf8, 0x31, 0xbd, 0x9d, 0xf8, 0x00, 0x10, 0x48, 0x1e, + 0x80, 0x41, 0xc0, 0x0f, 0xff, 0xf7, 0x33, 0xbe, 0x38, 0xb5, 0x00, 0xf0, + 0x1d, 0xf8, 0x1a, 0xd1, 0x10, 0x4d, 0x55, 0xf8, 0x24, 0x00, 0xb0, 0xb1, + 0x69, 0x46, 0xfa, 0xf7, 0x3f, 0xfd, 0x03, 0x28, 0x11, 0xd1, 0xff, 0xf7, + 0xea, 0xff, 0x55, 0xf8, 0x24, 0x00, 0x69, 0x46, 0xfa, 0xf7, 0x00, 0xfd, + 0xff, 0xf7, 0xe3, 0xff, 0x55, 0xf8, 0x24, 0x00, 0x6b, 0x46, 0x00, 0x22, + 0x00, 0x21, 0xfa, 0xf7, 0x79, 0xfd, 0xff, 0xf7, 0xda, 0xff, 0x31, 0xbd, + 0x04, 0x46, 0x03, 0x48, 0x00, 0x7c, 0x01, 0x28, 0x70, 0x47, 0x00, 0x00, + 0x08, 0x1f, 0x00, 0x20, 0x1c, 0x1f, 0x00, 0x20, 0x45, 0x81, 0x00, 0x01, + 0x00, 0x20, 0x00, 0xe0, 0x01, 0x20, 0x38, 0xb5, 0xff, 0xf7, 0xee, 0xff, + 0x0b, 0xd1, 0x00, 0x25, 0x00, 0x2c, 0xe8, 0xb2, 0x02, 0xd1, 0xff, 0xf7, + 0x7c, 0xff, 0x01, 0xe0, 0xff, 0xf7, 0x97, 0xff, 0x6d, 0x1c, 0x04, 0x2d, + 0xf4, 0xd3, 0x31, 0xbd, 0xef, 0xf3, 0x11, 0x80, 0x60, 0x21, 0x81, 0xf3, + 0x11, 0x88, 0x70, 0x47, 0x30, 0xb5, 0x00, 0xf0, 0x11, 0xf8, 0x23, 0x43, + 0x13, 0x60, 0x01, 0xeb, 0x40, 0x00, 0x01, 0x22, 0x42, 0x70, 0x30, 0xbd, + 0x30, 0xb5, 0x00, 0xf0, 0x07, 0xf8, 0xa3, 0x43, 0x13, 0x60, 0x01, 0xeb, + 0x40, 0x00, 0x00, 0x22, 0x42, 0x70, 0x30, 0xbd, 0xdf, 0xf8, 0xb0, 0x2c, + 0xdf, 0xf8, 0xd4, 0x1d, 0x13, 0x68, 0x11, 0xf9, 0x10, 0x50, 0x01, 0x24, + 0xac, 0x40, 0x70, 0x47, 0xdf, 0xf8, 0xa0, 0x0c, 0xc0, 0x6c, 0x70, 0x47, + 0xdf, 0xf8, 0x9c, 0x1c, 0xdf, 0xf8, 0x94, 0x0c, 0x89, 0x6b, 0xc0, 0x6c, + 0xdf, 0xf8, 0x94, 0x2c, 0xb1, 0xfb, 0xf2, 0xf1, 0x48, 0x43, 0xdf, 0xf8, + 0x68, 0x1d, 0x48, 0x60, 0x70, 0x47, 0x80, 0xb5, 0xdf, 0xf8, 0x3c, 0x0d, + 0x00, 0x21, 0x41, 0x71, 0x84, 0x30, 0xfb, 0xf7, 0xb1, 0xf9, 0x06, 0xf0, + 0xea, 0xf9, 0xbd, 0xe8, 0x01, 0x40, 0x06, 0xf0, 0x1a, 0xb9, 0xdf, 0xf8, + 0xc8, 0x1d, 0x02, 0x20, 0x08, 0x60, 0x70, 0x47, 0xdf, 0xf8, 0x18, 0x0d, + 0x41, 0x79, 0xd0, 0xf8, 0x80, 0x00, 0x00, 0x29, 0x18, 0xbf, 0x40, 0xf0, + 0x00, 0x40, 0x70, 0x47, 0xdf, 0xf8, 0x04, 0x0d, 0x01, 0x79, 0x00, 0x29, + 0x0e, 0xbf, 0x00, 0x20, 0xd0, 0xf8, 0x80, 0x00, 0xc0, 0xf3, 0x02, 0x10, + 0x70, 0x47, 0x10, 0xb5, 0xdf, 0xf8, 0x28, 0x4c, 0xa1, 0x7c, 0x4f, 0xf4, + 0x17, 0x60, 0xfa, 0xf7, 0x73, 0xfe, 0xe1, 0x7c, 0xbd, 0xe8, 0x10, 0x40, + 0x40, 0xf6, 0x71, 0x10, 0xfa, 0xf7, 0x6c, 0xbe, 0x2d, 0xe9, 0xf0, 0x47, + 0x06, 0x21, 0x31, 0x20, 0xff, 0xf7, 0xdf, 0xfd, 0x31, 0x20, 0xff, 0xf7, + 0xc1, 0xfd, 0x31, 0x20, 0xff, 0xf7, 0xc4, 0xfd, 0xff, 0xf7, 0xac, 0xff, + 0xdf, 0xf8, 0xb4, 0x4c, 0xdf, 0xf8, 0xd0, 0x5c, 0xdf, 0xf8, 0xd0, 0x1c, + 0xdf, 0xf8, 0xe4, 0x9b, 0x00, 0x20, 0x60, 0x71, 0x68, 0x68, 0x08, 0x60, + 0x06, 0x21, 0x10, 0x20, 0xff, 0xf7, 0xc7, 0xfd, 0x02, 0x21, 0x0c, 0x20, + 0xff, 0xf7, 0xc3, 0xfd, 0x02, 0x21, 0x0a, 0x20, 0xff, 0xf7, 0xbf, 0xfd, + 0x02, 0x21, 0x1d, 0x20, 0xff, 0xf7, 0xbb, 0xfd, 0x02, 0x21, 0x0d, 0x20, + 0xff, 0xf7, 0xb7, 0xfd, 0x02, 0x21, 0x0b, 0x20, 0xff, 0xf7, 0xb3, 0xfd, + 0x02, 0x21, 0x1e, 0x20, 0xff, 0xf7, 0xaf, 0xfd, 0x02, 0x21, 0x1f, 0x20, + 0xff, 0xf7, 0xab, 0xfd, 0xdf, 0xf8, 0xc4, 0x0d, 0x40, 0x89, 0xc0, 0xf3, + 0x81, 0x01, 0x89, 0xf8, 0x04, 0x10, 0x01, 0x23, 0x00, 0xf0, 0x03, 0x01, + 0x89, 0xf8, 0x05, 0x10, 0x00, 0x21, 0x03, 0xfa, 0x01, 0xf8, 0x08, 0xea, + 0x00, 0x06, 0x0f, 0x1d, 0x8a, 0x1c, 0x16, 0xf0, 0x03, 0x0f, 0x03, 0xfa, + 0x07, 0xf7, 0x03, 0xfa, 0x02, 0xf2, 0x03, 0xfa, 0x01, 0xfe, 0x0d, 0xd1, + 0x2e, 0x78, 0x42, 0xea, 0x0e, 0x0a, 0x47, 0xea, 0x0a, 0x0a, 0x4a, 0xea, + 0x06, 0x06, 0x2e, 0x70, 0x4e, 0xf0, 0x04, 0x0a, 0x6e, 0x78, 0x4a, 0xea, + 0x06, 0x06, 0x6e, 0x70, 0x08, 0xea, 0x90, 0x0a, 0x8e, 0x1d, 0x1a, 0xf0, + 0x03, 0x0f, 0x03, 0xfa, 0x06, 0xf6, 0x0b, 0xd1, 0x42, 0xea, 0x0e, 0x02, + 0x94, 0xf8, 0x06, 0xa0, 0x17, 0x43, 0x37, 0x43, 0x47, 0xea, 0x0a, 0x07, + 0xa7, 0x71, 0x4a, 0x19, 0x7f, 0x27, 0x97, 0x70, 0x08, 0xea, 0x10, 0x17, + 0x17, 0xf0, 0x03, 0x0f, 0x02, 0xd1, 0xe7, 0x79, 0x37, 0x43, 0xe7, 0x71, + 0x49, 0x1c, 0x02, 0x29, 0xc3, 0xdb, 0xc0, 0xf3, 0x82, 0x10, 0x20, 0xb9, + 0xe0, 0x79, 0x40, 0xf0, 0x30, 0x00, 0xe0, 0x71, 0x15, 0xe0, 0x80, 0x22, + 0x80, 0x21, 0x4f, 0xf4, 0x02, 0x60, 0xfa, 0xf7, 0xe5, 0xfd, 0xc0, 0x22, + 0xc0, 0x21, 0x40, 0xf6, 0x1f, 0x00, 0xfa, 0xf7, 0xdf, 0xfd, 0x3f, 0x21, + 0x40, 0xf6, 0x8c, 0x50, 0xfa, 0xf7, 0xd0, 0xfd, 0x03, 0x21, 0x4f, 0xf4, + 0x03, 0x70, 0xfa, 0xf7, 0xcb, 0xfd, 0xc0, 0x22, 0xc0, 0x21, 0x40, 0xf6, + 0x14, 0x00, 0xfa, 0xf7, 0xcf, 0xfd, 0xc0, 0x22, 0xc0, 0x21, 0x40, 0xf6, + 0x12, 0x00, 0xfa, 0xf7, 0xc9, 0xfd, 0xc0, 0x22, 0xc0, 0x21, 0x40, 0xf6, + 0x13, 0x00, 0xfa, 0xf7, 0xc3, 0xfd, 0xc0, 0x22, 0xc0, 0x21, 0x40, 0xf2, + 0x42, 0x50, 0xfa, 0xf7, 0xbd, 0xfd, 0xc0, 0x22, 0xc0, 0x21, 0x40, 0xf2, + 0x43, 0x50, 0xfa, 0xf7, 0xb7, 0xfd, 0x00, 0x22, 0xc0, 0x21, 0x40, 0xf2, + 0xe4, 0x60, 0xfa, 0xf7, 0xb1, 0xfd, 0x99, 0xf8, 0x04, 0x00, 0x99, 0xf8, + 0x05, 0x10, 0x40, 0xea, 0x81, 0x00, 0xc4, 0xf8, 0x80, 0x00, 0x06, 0xf0, + 0x2b, 0xf8, 0xbd, 0xe8, 0xf0, 0x47, 0x05, 0xf0, 0x6b, 0xbe, 0x80, 0xb5, + 0x4f, 0xf0, 0x92, 0x41, 0x00, 0x20, 0x08, 0x60, 0x04, 0x21, 0x01, 0x20, + 0xff, 0xf7, 0x09, 0xfd, 0x01, 0x20, 0xff, 0xf7, 0xf1, 0xfc, 0x00, 0x20, + 0x02, 0xbd, 0xf8, 0xb5, 0x0a, 0x20, 0xff, 0xf7, 0xe5, 0xfc, 0x1d, 0x20, + 0xff, 0xf7, 0xe2, 0xfc, 0x0c, 0x20, 0xff, 0xf7, 0xdf, 0xfc, 0xdf, 0xf8, + 0x78, 0x3c, 0xdf, 0xf8, 0x78, 0x5c, 0xdf, 0xf8, 0x30, 0x2a, 0xdf, 0xf8, + 0xf0, 0x4a, 0x00, 0x20, 0x98, 0x60, 0x18, 0x60, 0x28, 0x60, 0x4f, 0xf4, + 0x00, 0x21, 0x90, 0x78, 0x70, 0xb9, 0x00, 0xf0, 0xfd, 0xf9, 0x10, 0x79, + 0xc2, 0x07, 0x4c, 0xbf, 0x80, 0x22, 0x00, 0x22, 0xa2, 0x65, 0x80, 0x07, + 0x58, 0xbf, 0x00, 0x21, 0x21, 0x66, 0x03, 0x20, 0x20, 0x72, 0x45, 0xe0, + 0x03, 0xf1, 0x40, 0x00, 0x60, 0x62, 0x03, 0xf1, 0x3c, 0x00, 0xa0, 0x62, + 0x05, 0xf1, 0x40, 0x00, 0x20, 0x63, 0x05, 0xf1, 0x3c, 0x00, 0x60, 0x63, + 0x80, 0x20, 0xd8, 0x63, 0xe9, 0x63, 0x98, 0x6c, 0x40, 0xf0, 0x80, 0x00, + 0x98, 0x64, 0xd8, 0x6c, 0x40, 0xf0, 0x80, 0x00, 0xd8, 0x64, 0xa8, 0x6c, + 0x40, 0xf4, 0x00, 0x20, 0xa8, 0x64, 0xe8, 0x6c, 0x40, 0xf4, 0x00, 0x20, + 0xe8, 0x64, 0xdf, 0xf8, 0xe8, 0x0b, 0x46, 0x89, 0xc6, 0xf3, 0x81, 0x07, + 0x03, 0x2f, 0x04, 0xbf, 0x12, 0x78, 0x00, 0x2a, 0x40, 0xf2, 0x05, 0x10, + 0x05, 0xd1, 0x80, 0x21, 0x99, 0x60, 0x08, 0x22, 0x04, 0x21, 0x21, 0x72, + 0x11, 0xe0, 0x00, 0x22, 0x22, 0x72, 0xc6, 0xf3, 0x80, 0x02, 0x1a, 0xb1, + 0x80, 0x22, 0x1a, 0x60, 0x01, 0x22, 0x22, 0x72, 0xb2, 0x08, 0x92, 0x07, + 0x04, 0xd5, 0x29, 0x60, 0x21, 0x7a, 0x41, 0xf0, 0x02, 0x01, 0x21, 0x72, + 0x00, 0x22, 0x08, 0x21, 0xfa, 0xf7, 0x26, 0xfd, 0x00, 0xf0, 0xc3, 0xf9, + 0x05, 0xf0, 0xeb, 0xff, 0xd4, 0xf8, 0x80, 0x00, 0x80, 0x08, 0x80, 0x00, + 0xc4, 0xf8, 0x80, 0x00, 0x0a, 0x20, 0xff, 0xf7, 0x82, 0xfc, 0x1d, 0x20, + 0xff, 0xf7, 0x7f, 0xfc, 0xbd, 0xe8, 0xf2, 0x40, 0x0c, 0x20, 0xff, 0xf7, + 0x7a, 0xbc, 0xf8, 0xb5, 0x0d, 0x20, 0xff, 0xf7, 0x61, 0xfc, 0x0b, 0x20, + 0xff, 0xf7, 0x5e, 0xfc, 0x1e, 0x20, 0xff, 0xf7, 0x5b, 0xfc, 0xdf, 0xf8, + 0xf8, 0x5b, 0xdf, 0xf8, 0xf8, 0x6b, 0xdf, 0xf8, 0x28, 0x39, 0xdf, 0xf8, + 0xdc, 0x1c, 0xdf, 0xf8, 0xe4, 0x49, 0x00, 0x20, 0xa8, 0x60, 0x28, 0x60, + 0x30, 0x60, 0x4f, 0xf4, 0x80, 0x12, 0x98, 0x78, 0x70, 0xb9, 0x00, 0xf0, + 0x6a, 0xf9, 0x58, 0x79, 0xc3, 0x07, 0x4c, 0xbf, 0x40, 0x23, 0x00, 0x23, + 0xa3, 0x64, 0x80, 0x07, 0x58, 0xbf, 0x00, 0x22, 0x22, 0x65, 0x03, 0x20, + 0x08, 0x70, 0x43, 0xe0, 0x05, 0xf1, 0x3c, 0x00, 0xe0, 0x60, 0x05, 0xf1, + 0x38, 0x00, 0x20, 0x61, 0x06, 0xf1, 0x3c, 0x00, 0xa0, 0x61, 0x06, 0xf1, + 0x38, 0x00, 0xe0, 0x61, 0x40, 0x20, 0xa8, 0x63, 0xb2, 0x63, 0x68, 0x6c, + 0x40, 0xf0, 0x40, 0x00, 0x68, 0x64, 0xa8, 0x6c, 0x40, 0xf0, 0x40, 0x00, + 0xa8, 0x64, 0x70, 0x6c, 0x40, 0xf4, 0x80, 0x10, 0x70, 0x64, 0xb0, 0x6c, + 0x40, 0xf4, 0x80, 0x10, 0xb0, 0x64, 0xdf, 0xf8, 0xdc, 0x0a, 0x47, 0x89, + 0x07, 0xf0, 0x03, 0x0c, 0xbc, 0xf1, 0x03, 0x0f, 0x04, 0xbf, 0x5b, 0x78, + 0x00, 0x2b, 0x40, 0xf2, 0x05, 0x10, 0x04, 0xd1, 0x40, 0x22, 0xaa, 0x60, + 0x04, 0x22, 0x0a, 0x70, 0x0f, 0xe0, 0x00, 0x23, 0x0b, 0x70, 0xfb, 0x07, + 0x03, 0xd5, 0x40, 0x23, 0x2b, 0x60, 0x01, 0x23, 0x0b, 0x70, 0xbb, 0x07, + 0x04, 0xd5, 0x32, 0x60, 0x0a, 0x78, 0x42, 0xf0, 0x02, 0x02, 0x0a, 0x70, + 0x00, 0x22, 0x04, 0x21, 0xfa, 0xf7, 0xa2, 0xfc, 0x00, 0xf0, 0x6f, 0xf9, + 0xff, 0xf7, 0x19, 0xfe, 0xd4, 0xf8, 0x80, 0x00, 0x20, 0xf0, 0x0c, 0x00, + 0xc4, 0xf8, 0x80, 0x00, 0x0b, 0x20, 0xff, 0xf7, 0xfe, 0xfb, 0x1e, 0x20, + 0xff, 0xf7, 0xfb, 0xfb, 0xbd, 0xe8, 0xf2, 0x40, 0x0d, 0x20, 0xff, 0xf7, + 0xf6, 0xbb, 0x2d, 0xe9, 0xf8, 0x43, 0xdf, 0xf8, 0x38, 0x58, 0xdf, 0xf8, + 0xf0, 0x6b, 0xe8, 0x78, 0xdf, 0xf8, 0xf0, 0x48, 0x98, 0xb9, 0x00, 0xf0, + 0x12, 0xf9, 0x30, 0x60, 0x10, 0x20, 0x60, 0x64, 0xa9, 0x79, 0x48, 0x08, + 0x40, 0x00, 0x01, 0xf0, 0x01, 0x02, 0x89, 0x08, 0x00, 0xf0, 0x02, 0x00, + 0x89, 0x00, 0x10, 0x43, 0x01, 0xf0, 0x04, 0x01, 0x08, 0x43, 0xa0, 0x66, + 0x37, 0xe0, 0x00, 0x20, 0x01, 0xf0, 0x88, 0xfb, 0x80, 0x46, 0x01, 0x20, + 0x01, 0xf0, 0x84, 0xfb, 0x07, 0x46, 0x02, 0x20, 0x01, 0xf0, 0x80, 0xfb, + 0x81, 0x46, 0x03, 0x20, 0x01, 0xf0, 0x7c, 0xfb, 0xa8, 0xf1, 0x04, 0x01, + 0x04, 0x2f, 0x21, 0x67, 0x0a, 0xd2, 0x07, 0xf1, 0x0a, 0x02, 0x62, 0x67, + 0x0a, 0x30, 0xe0, 0x67, 0x09, 0xf1, 0x0a, 0x02, 0xa2, 0x67, 0xdf, 0xf8, + 0x88, 0x0b, 0x0c, 0xe0, 0x10, 0x2f, 0x09, 0xd2, 0x3a, 0x1f, 0x62, 0x67, + 0x00, 0x1f, 0xe0, 0x67, 0xa9, 0xf1, 0x04, 0x02, 0xa2, 0x67, 0x06, 0xf1, + 0x38, 0x00, 0x00, 0xe0, 0x00, 0x20, 0xe0, 0x63, 0x01, 0x20, 0x88, 0x40, + 0x06, 0xf1, 0x34, 0x01, 0x21, 0x64, 0x60, 0x64, 0x70, 0x63, 0x30, 0x60, + 0x31, 0x6c, 0x08, 0x43, 0x30, 0x64, 0x00, 0x22, 0x03, 0x21, 0x40, 0xf2, + 0x05, 0x10, 0xfa, 0xf7, 0x31, 0xfc, 0x00, 0x21, 0x4f, 0xf4, 0x82, 0x70, + 0xfa, 0xf7, 0x22, 0xfc, 0xdf, 0xf8, 0xb4, 0x0b, 0x00, 0x78, 0x60, 0x70, + 0x29, 0x7e, 0xc9, 0x07, 0x48, 0xbf, 0x40, 0xf0, 0xc0, 0x00, 0x20, 0x70, + 0x00, 0xf0, 0x10, 0xf9, 0x05, 0xf0, 0x58, 0xfd, 0xd4, 0xf8, 0x80, 0x00, + 0xdf, 0xf8, 0x98, 0x1b, 0x20, 0xf0, 0x70, 0x00, 0xc4, 0xf8, 0x80, 0x00, + 0x00, 0x20, 0x08, 0x70, 0x1f, 0x20, 0xbd, 0xe8, 0xf2, 0x43, 0xff, 0xf7, + 0x78, 0xbb, 0xdf, 0xf8, 0x84, 0x0b, 0x01, 0x79, 0x01, 0x29, 0x0c, 0xbf, + 0x02, 0x21, 0x00, 0x21, 0x01, 0x71, 0x00, 0x20, 0x70, 0x47, 0x10, 0xb5, + 0xdf, 0xf8, 0xec, 0x47, 0x20, 0x79, 0x02, 0x28, 0x6d, 0xd1, 0xdf, 0xf8, + 0x68, 0x0b, 0x01, 0x68, 0x21, 0xf0, 0xc0, 0x01, 0x01, 0x60, 0x41, 0x68, + 0x21, 0xf0, 0xc0, 0x01, 0x41, 0x60, 0xdf, 0xf8, 0x58, 0x0b, 0x01, 0x68, + 0x21, 0xf4, 0xc0, 0x11, 0x01, 0x60, 0x41, 0x68, 0x21, 0xf4, 0xc0, 0x11, + 0x41, 0x60, 0xdf, 0xf8, 0xf8, 0x16, 0xc9, 0x78, 0x01, 0x29, 0x05, 0xd1, + 0x01, 0x68, 0x23, 0x6f, 0x01, 0x22, 0x9a, 0x40, 0x91, 0x43, 0x01, 0x60, + 0x05, 0xf0, 0x07, 0xff, 0x00, 0xf0, 0x60, 0xf8, 0x00, 0x20, 0xa0, 0x65, + 0x20, 0x66, 0x0c, 0x20, 0xff, 0xf7, 0x3f, 0xfb, 0x0a, 0x20, 0xff, 0xf7, + 0x3c, 0xfb, 0x1d, 0x20, 0xff, 0xf7, 0x39, 0xfb, 0x00, 0xf0, 0x45, 0xf8, + 0x00, 0x20, 0xa0, 0x64, 0x20, 0x65, 0x0d, 0x20, 0xff, 0xf7, 0x31, 0xfb, + 0x0b, 0x20, 0xff, 0xf7, 0x2e, 0xfb, 0x1e, 0x20, 0xff, 0xf7, 0x2b, 0xfb, + 0x00, 0xf0, 0x51, 0xf8, 0xa0, 0x66, 0x1f, 0x20, 0xff, 0xf7, 0x25, 0xfb, + 0xdf, 0xf8, 0xd8, 0x1a, 0x01, 0x20, 0x08, 0x70, 0x10, 0x20, 0xff, 0xf7, + 0x18, 0xfb, 0x0a, 0x20, 0xff, 0xf7, 0x15, 0xfb, 0x1d, 0x20, 0xff, 0xf7, + 0x12, 0xfb, 0x0c, 0x20, 0xff, 0xf7, 0x0f, 0xfb, 0x0b, 0x20, 0xff, 0xf7, + 0x0c, 0xfb, 0x1e, 0x20, 0xff, 0xf7, 0x09, 0xfb, 0x0d, 0x20, 0xff, 0xf7, + 0x06, 0xfb, 0x1f, 0x20, 0xff, 0xf7, 0x03, 0xfb, 0x06, 0xf0, 0x7b, 0xfc, + 0x00, 0x20, 0xff, 0xf7, 0xa1, 0xfa, 0xff, 0xf7, 0x5d, 0xfa, 0x07, 0x22, + 0x04, 0xf1, 0x8c, 0x01, 0x0f, 0xf6, 0xfc, 0x20, 0xfa, 0xf7, 0xa6, 0xfb, + 0x04, 0xe0, 0x00, 0x20, 0xff, 0xf7, 0x94, 0xfa, 0xff, 0xf7, 0x50, 0xfa, + 0x00, 0x20, 0x20, 0x71, 0x10, 0xbd, 0x04, 0xf1, 0x48, 0x00, 0xe0, 0x60, + 0x04, 0xf1, 0x4c, 0x00, 0x20, 0x61, 0x04, 0xf1, 0x50, 0x00, 0xa0, 0x61, + 0x04, 0xf1, 0x54, 0x00, 0xe0, 0x61, 0x70, 0x47, 0x04, 0xf1, 0x58, 0x00, + 0x60, 0x62, 0x04, 0xf1, 0x5c, 0x00, 0xa0, 0x62, 0x04, 0xf1, 0x60, 0x00, + 0x20, 0x63, 0x04, 0xf1, 0x64, 0x00, 0x60, 0x63, 0x70, 0x47, 0x04, 0xf1, + 0x68, 0x00, 0xe0, 0x63, 0x04, 0xf1, 0x6c, 0x00, 0x20, 0x64, 0x00, 0x20, + 0x60, 0x67, 0x01, 0x20, 0xa0, 0x67, 0x02, 0x20, 0xe0, 0x67, 0x00, 0x20, + 0x70, 0x47, 0x38, 0xb5, 0xdf, 0xf8, 0xe0, 0x45, 0xdf, 0xf8, 0xa0, 0x16, + 0x20, 0x7b, 0x89, 0x79, 0xdf, 0xf8, 0xb8, 0x56, 0x20, 0xea, 0x01, 0x01, + 0x40, 0xf6, 0x84, 0x50, 0xfa, 0xf7, 0x48, 0xfb, 0x60, 0x7b, 0xa9, 0x78, + 0x20, 0xea, 0x01, 0x01, 0x40, 0xf6, 0x85, 0x50, 0xfa, 0xf7, 0x40, 0xfb, + 0xa0, 0x7b, 0xe9, 0x78, 0x20, 0xea, 0x01, 0x01, 0x40, 0xf6, 0x86, 0x50, + 0xfa, 0xf7, 0x38, 0xfb, 0x00, 0x21, 0x4f, 0xf4, 0x01, 0x70, 0xfa, 0xf7, + 0x33, 0xfb, 0x00, 0x21, 0x40, 0xf2, 0x05, 0x20, 0xfa, 0xf7, 0x2e, 0xfb, + 0xbd, 0xe8, 0x34, 0x40, 0x00, 0x21, 0x40, 0xf2, 0x06, 0x20, 0xfa, 0xf7, + 0x27, 0xbb, 0x38, 0xb5, 0xdf, 0xf8, 0x64, 0x46, 0xdf, 0xf8, 0xcc, 0x59, + 0x21, 0x78, 0x28, 0x7c, 0x20, 0xea, 0x01, 0x01, 0x40, 0xf6, 0x89, 0x50, + 0xfa, 0xf7, 0x1a, 0xfb, 0x68, 0x7c, 0x61, 0x78, 0x20, 0xea, 0x01, 0x01, + 0x40, 0xf6, 0x8a, 0x50, 0xfa, 0xf7, 0x12, 0xfb, 0x00, 0x21, 0x40, 0xf2, + 0x09, 0x20, 0xfa, 0xf7, 0x0d, 0xfb, 0xbd, 0xe8, 0x34, 0x40, 0x00, 0x21, + 0x40, 0xf2, 0x0a, 0x20, 0xfa, 0xf7, 0x06, 0xbb, 0x80, 0xb5, 0xdf, 0xf8, + 0x04, 0x16, 0xdf, 0xf8, 0x3c, 0x05, 0xc9, 0x79, 0x40, 0x69, 0xc9, 0x43, + 0x01, 0x40, 0xc9, 0xb2, 0x40, 0xf6, 0x87, 0x50, 0xfa, 0xf7, 0xf8, 0xfa, + 0xbd, 0xe8, 0x04, 0x40, 0x00, 0x21, 0x40, 0xf2, 0x07, 0x20, 0xfa, 0xf7, + 0xf1, 0xba, 0xf8, 0xb5, 0x00, 0x24, 0x0f, 0xf6, 0x18, 0x25, 0x0f, 0xf6, + 0x10, 0x26, 0xa0, 0x5d, 0xfb, 0xf7, 0x36, 0xfe, 0x30, 0xb1, 0x20, 0x46, + 0x01, 0xf0, 0x6d, 0xfd, 0x10, 0xb9, 0x20, 0x46, 0x05, 0xf0, 0xb3, 0xf9, + 0x60, 0x5d, 0xfb, 0xf7, 0x2b, 0xfe, 0x10, 0xb1, 0x20, 0x46, 0xfd, 0xf7, + 0x62, 0xfe, 0x64, 0x1c, 0x02, 0x2c, 0xea, 0xd3, 0x04, 0xf0, 0xa1, 0xfa, + 0x08, 0xb1, 0x04, 0xf0, 0xa2, 0xfa, 0xdf, 0xf8, 0xd8, 0x44, 0xe0, 0x78, + 0x01, 0x28, 0x43, 0xd1, 0x00, 0x20, 0x01, 0xf0, 0xef, 0xf9, 0x00, 0x1f, + 0x0c, 0x28, 0x3b, 0xd2, 0x01, 0x20, 0x01, 0xf0, 0xe9, 0xf9, 0x05, 0x46, + 0x02, 0x20, 0x01, 0xf0, 0xe5, 0xf9, 0x06, 0x46, 0x03, 0x20, 0x01, 0xf0, + 0xe1, 0xf9, 0x04, 0x2d, 0xb8, 0xbf, 0x00, 0x21, 0x07, 0xdb, 0x10, 0x2d, + 0xb8, 0xbf, 0x01, 0x21, 0x03, 0xdb, 0x13, 0x2d, 0xb4, 0xbf, 0x02, 0x21, + 0x03, 0x21, 0x04, 0x2e, 0xb8, 0xbf, 0x00, 0x22, 0x07, 0xdb, 0x10, 0x2e, + 0xb8, 0xbf, 0x01, 0x22, 0x03, 0xdb, 0x13, 0x2e, 0xb4, 0xbf, 0x02, 0x22, + 0x03, 0x22, 0x04, 0x28, 0xb8, 0xbf, 0x00, 0x23, 0x07, 0xdb, 0x10, 0x28, + 0xb8, 0xbf, 0x01, 0x23, 0x03, 0xdb, 0x13, 0x28, 0xb4, 0xbf, 0x02, 0x23, + 0x03, 0x23, 0x03, 0x29, 0x0a, 0xd2, 0x91, 0x42, 0x08, 0xbf, 0x99, 0x42, + 0x06, 0xd1, 0x02, 0x29, 0x06, 0xd1, 0x10, 0x2d, 0x04, 0xbf, 0x11, 0x2e, + 0x12, 0x28, 0x01, 0xd0, 0x04, 0x20, 0xf2, 0xbd, 0xef, 0xf3, 0x10, 0x86, + 0x72, 0xb6, 0xdf, 0xf8, 0x04, 0x55, 0x0f, 0xf6, 0xec, 0x00, 0x07, 0x22, + 0x05, 0xf1, 0x8c, 0x01, 0xfa, 0xf7, 0xad, 0xfa, 0xff, 0xf7, 0xef, 0xfc, + 0xff, 0xf7, 0x71, 0xfd, 0xff, 0xf7, 0xf3, 0xfd, 0x21, 0x7a, 0x4f, 0xf4, + 0xdb, 0x70, 0xfa, 0xf7, 0x71, 0xfa, 0x61, 0x7a, 0x40, 0xf2, 0xb7, 0x10, + 0xfa, 0xf7, 0x6c, 0xfa, 0x08, 0x20, 0xff, 0xf7, 0x67, 0xf9, 0x40, 0xf2, + 0x2f, 0x47, 0x80, 0x22, 0x80, 0x21, 0x38, 0x46, 0xfa, 0xf7, 0x6c, 0xfa, + 0x00, 0x22, 0x80, 0x21, 0x38, 0x46, 0xfa, 0xf7, 0x67, 0xfa, 0xa0, 0x78, + 0x01, 0x28, 0x18, 0xbf, 0x00, 0x20, 0xff, 0xf7, 0x67, 0xf9, 0xff, 0xf7, + 0xa3, 0xfb, 0x01, 0x20, 0x28, 0x71, 0x86, 0xf3, 0x10, 0x88, 0x10, 0x20, + 0xff, 0xf7, 0xb2, 0xf9, 0x28, 0x7a, 0x41, 0x07, 0x48, 0xbf, 0x0c, 0x20, + 0x08, 0xd4, 0xc0, 0x07, 0x44, 0xbf, 0x0a, 0x20, 0xff, 0xf7, 0xa8, 0xf9, + 0x28, 0x7a, 0x80, 0x07, 0x02, 0xd5, 0x1d, 0x20, 0xff, 0xf7, 0xa2, 0xf9, + 0xdf, 0xf8, 0x68, 0x47, 0x20, 0x78, 0x41, 0x07, 0x48, 0xbf, 0x0d, 0x20, + 0x08, 0xd4, 0xc0, 0x07, 0x44, 0xbf, 0x0b, 0x20, 0xff, 0xf7, 0x96, 0xf9, + 0x20, 0x78, 0x80, 0x07, 0x02, 0xd5, 0x1e, 0x20, 0xff, 0xf7, 0x90, 0xf9, + 0x1f, 0x20, 0xff, 0xf7, 0x8d, 0xf9, 0x06, 0xf0, 0xc5, 0xfa, 0x00, 0x20, + 0xf2, 0xbd, 0x2d, 0xe9, 0xf0, 0x41, 0x4f, 0xf0, 0x92, 0x45, 0xdf, 0xf8, + 0x3c, 0x64, 0x28, 0x68, 0x69, 0x68, 0x6f, 0x68, 0x4f, 0xea, 0x11, 0x28, + 0x31, 0x79, 0x00, 0x24, 0x01, 0x29, 0x04, 0xbf, 0x00, 0xf0, 0x3f, 0x00, + 0x0a, 0x28, 0x63, 0xd1, 0x00, 0x21, 0xff, 0xf7, 0x53, 0xfa, 0xff, 0xb2, + 0x61, 0x2f, 0xdf, 0xf8, 0xa0, 0x07, 0x40, 0xd0, 0x64, 0x2f, 0x04, 0xbf, + 0x80, 0x78, 0x00, 0x28, 0x56, 0xd1, 0xd6, 0xf8, 0x80, 0x00, 0x08, 0xf0, + 0x0f, 0x08, 0x88, 0xea, 0x00, 0x07, 0xf8, 0x07, 0x0b, 0xd5, 0x71, 0x6a, + 0x08, 0xf0, 0x01, 0x00, 0xc0, 0x01, 0x08, 0x60, 0x01, 0x24, 0xb1, 0x6a, + 0xf0, 0x6a, 0x08, 0x60, 0x0a, 0x20, 0xff, 0xf7, 0x64, 0xf9, 0xb8, 0x07, + 0x0b, 0xd5, 0x31, 0x6b, 0x08, 0xf0, 0x02, 0x00, 0x80, 0x04, 0x08, 0x60, + 0x01, 0x24, 0x71, 0x6b, 0xb0, 0x6b, 0x08, 0x60, 0x1d, 0x20, 0xff, 0xf7, + 0x56, 0xf9, 0x78, 0x07, 0x0b, 0xd5, 0xf1, 0x68, 0x08, 0xf0, 0x04, 0x00, + 0x00, 0x01, 0x08, 0x60, 0x01, 0x24, 0x31, 0x69, 0x70, 0x69, 0x08, 0x60, + 0x0b, 0x20, 0xff, 0xf7, 0x48, 0xf9, 0x38, 0x07, 0x1c, 0xd5, 0xb1, 0x69, + 0x08, 0xf0, 0x08, 0x00, 0x40, 0x04, 0x08, 0x60, 0xf1, 0x69, 0x30, 0x6a, + 0x08, 0x60, 0x1e, 0x20, 0x0f, 0xe0, 0xc0, 0x78, 0xc0, 0xb9, 0xf1, 0x6b, + 0x08, 0xf0, 0x07, 0x00, 0x08, 0x60, 0x04, 0x28, 0x32, 0x6c, 0x71, 0x6c, + 0x11, 0x60, 0x04, 0xbf, 0xc8, 0xf3, 0x01, 0x10, 0x00, 0xf0, 0xf3, 0xfa, + 0x1f, 0x20, 0xff, 0xf7, 0x2a, 0xf9, 0x00, 0xe0, 0x5c, 0xb1, 0x00, 0x20, + 0x28, 0x60, 0x0a, 0x20, 0xbd, 0xe8, 0xf0, 0x41, 0xfb, 0xf7, 0x1b, 0xbc, + 0xbd, 0xe8, 0xf0, 0x41, 0x0f, 0x20, 0xff, 0xf7, 0x1c, 0xb9, 0xbd, 0xe8, + 0xf0, 0x81, 0x10, 0xb5, 0x05, 0xf0, 0xe8, 0xfc, 0x05, 0xf0, 0x1c, 0xfc, + 0xd8, 0x4c, 0x00, 0x20, 0xa0, 0x60, 0x02, 0x20, 0xe0, 0x60, 0x31, 0x20, + 0xff, 0xf7, 0xf8, 0xf8, 0xcb, 0x48, 0x01, 0x21, 0x41, 0x71, 0x84, 0x30, + 0xd1, 0x49, 0x49, 0x68, 0x21, 0x60, 0x70, 0x21, 0xa1, 0x60, 0xbd, 0xe8, + 0x10, 0x40, 0xfa, 0xf7, 0xa3, 0xbc, 0x70, 0xb5, 0x00, 0xf0, 0x8c, 0xf8, + 0x10, 0xd5, 0x30, 0x78, 0x40, 0xf0, 0x40, 0x00, 0x30, 0x70, 0x04, 0x20, + 0xff, 0xf7, 0xae, 0xfa, 0xd5, 0xf8, 0x80, 0x00, 0x40, 0xf0, 0x01, 0x00, + 0xc5, 0xf8, 0x80, 0x00, 0x00, 0x20, 0xc0, 0x46, 0xc0, 0x46, 0x0f, 0xe0, + 0x00, 0x20, 0xc0, 0x46, 0xc0, 0x46, 0x30, 0x78, 0x00, 0xf0, 0xbf, 0x00, + 0x30, 0x70, 0x04, 0x20, 0xff, 0xf7, 0xa4, 0xfa, 0xd5, 0xf8, 0x80, 0x00, + 0x40, 0x08, 0x40, 0x00, 0xc5, 0xf8, 0x80, 0x00, 0x62, 0xe0, 0x70, 0xb5, + 0xb1, 0x4c, 0xdf, 0xf8, 0x54, 0x56, 0x61, 0x6b, 0xdf, 0xf8, 0x50, 0x66, + 0x4f, 0xf4, 0x00, 0x20, 0x08, 0x60, 0x4f, 0xf6, 0xfe, 0x60, 0x28, 0x60, + 0x20, 0x6b, 0x00, 0x68, 0x00, 0x03, 0x10, 0xd5, 0x30, 0x78, 0x40, 0xf0, + 0x80, 0x00, 0x30, 0x70, 0x05, 0x20, 0xff, 0xf7, 0x7b, 0xfa, 0xd4, 0xf8, + 0x80, 0x00, 0x40, 0xf0, 0x02, 0x00, 0xc4, 0xf8, 0x80, 0x00, 0x01, 0x20, + 0xc0, 0x46, 0xc0, 0x46, 0x0f, 0xe0, 0x01, 0x20, 0xc0, 0x46, 0xc0, 0x46, + 0x30, 0x78, 0x00, 0xf0, 0x7f, 0x00, 0x30, 0x70, 0x05, 0x20, 0xff, 0xf7, + 0x71, 0xfa, 0xd4, 0xf8, 0x80, 0x00, 0x20, 0xf0, 0x02, 0x00, 0xc4, 0xf8, + 0x80, 0x00, 0x10, 0x20, 0xff, 0xf7, 0xa5, 0xf8, 0x00, 0x20, 0x28, 0x60, + 0x70, 0xbd, 0x70, 0xb5, 0x00, 0xf0, 0x2e, 0xf8, 0x13, 0xd5, 0x30, 0x78, + 0x40, 0xf0, 0xc0, 0x00, 0x30, 0x70, 0x04, 0x20, 0xff, 0xf7, 0x50, 0xfa, + 0x05, 0x20, 0xff, 0xf7, 0x4d, 0xfa, 0xd5, 0xf8, 0x80, 0x00, 0x40, 0xf0, + 0x03, 0x00, 0xc5, 0xf8, 0x80, 0x00, 0x02, 0x20, 0xc0, 0x46, 0xc0, 0x46, + 0x12, 0xe0, 0x02, 0x20, 0xc0, 0x46, 0xc0, 0x46, 0x30, 0x78, 0x00, 0xf0, + 0x3f, 0x00, 0x30, 0x70, 0x04, 0x20, 0xff, 0xf7, 0x43, 0xfa, 0x05, 0x20, + 0xff, 0xf7, 0x40, 0xfa, 0xd5, 0xf8, 0x80, 0x00, 0x80, 0x08, 0x80, 0x00, + 0xc5, 0xf8, 0x80, 0x00, 0x10, 0x20, 0xff, 0xf7, 0x74, 0xf8, 0x00, 0x20, + 0x20, 0x60, 0x70, 0xbd, 0xdf, 0xf8, 0x84, 0x45, 0x7c, 0x4d, 0xdf, 0xf8, + 0x84, 0x65, 0x4f, 0xf6, 0xfe, 0x60, 0x20, 0x60, 0x80, 0x20, 0xa9, 0x6a, + 0x08, 0x60, 0x68, 0x6a, 0x00, 0x68, 0x00, 0x06, 0x70, 0x47, 0x38, 0xb5, + 0x00, 0xf0, 0x75, 0xf8, 0x0c, 0xd5, 0x41, 0xf0, 0x10, 0x01, 0x01, 0x70, + 0x06, 0x20, 0xff, 0xf7, 0x11, 0xfa, 0xd5, 0xf8, 0x80, 0x00, 0x40, 0xf0, + 0x04, 0x00, 0x00, 0xf0, 0x3f, 0xf8, 0x0b, 0xe0, 0x01, 0xf0, 0xef, 0x01, + 0x01, 0x70, 0x06, 0x20, 0xff, 0xf7, 0x0e, 0xfa, 0xd5, 0xf8, 0x80, 0x00, + 0x20, 0xf0, 0x04, 0x00, 0xc5, 0xf8, 0x80, 0x00, 0x2a, 0xe0, 0x38, 0xb5, + 0xdf, 0xf8, 0x28, 0x45, 0x65, 0x4d, 0x4f, 0xf6, 0xfe, 0x60, 0x20, 0x60, + 0x4f, 0xf4, 0x80, 0x10, 0xe9, 0x69, 0x08, 0x60, 0xa9, 0x69, 0xdf, 0xf8, + 0x18, 0x05, 0x09, 0x68, 0xc9, 0x02, 0x01, 0x78, 0x0c, 0xd5, 0x41, 0xf0, + 0x20, 0x01, 0x01, 0x70, 0x07, 0x20, 0xff, 0xf7, 0xe5, 0xf9, 0xd5, 0xf8, + 0x80, 0x00, 0x40, 0xf0, 0x08, 0x00, 0x00, 0xf0, 0x13, 0xf8, 0x0b, 0xe0, + 0x01, 0xf0, 0xdf, 0x01, 0x01, 0x70, 0x07, 0x20, 0xff, 0xf7, 0xe2, 0xf9, + 0xd5, 0xf8, 0x80, 0x00, 0x20, 0xf0, 0x08, 0x00, 0xc5, 0xf8, 0x80, 0x00, + 0x10, 0x20, 0xff, 0xf7, 0x16, 0xf8, 0x00, 0x20, 0x20, 0x60, 0x31, 0xbd, + 0xc5, 0xf8, 0x80, 0x00, 0x0e, 0x20, 0xff, 0xf7, 0x0e, 0xb8, 0x38, 0xb5, + 0x00, 0xf0, 0x21, 0xf8, 0x0f, 0xd5, 0x41, 0xf0, 0x30, 0x01, 0x01, 0x70, + 0x06, 0x20, 0xff, 0xf7, 0xbd, 0xf9, 0x07, 0x20, 0xff, 0xf7, 0xba, 0xf9, + 0xd5, 0xf8, 0x80, 0x00, 0x40, 0xf0, 0x0c, 0x00, 0xff, 0xf7, 0xe8, 0xff, + 0x0e, 0xe0, 0x01, 0xf0, 0xcf, 0x01, 0x01, 0x70, 0x06, 0x20, 0xff, 0xf7, + 0xb7, 0xf9, 0x07, 0x20, 0xff, 0xf7, 0xb4, 0xf9, 0xd5, 0xf8, 0x80, 0x00, + 0x20, 0xf0, 0x0c, 0x00, 0xc5, 0xf8, 0x80, 0x00, 0xd0, 0xe7, 0xdf, 0xf8, + 0x78, 0x44, 0x39, 0x4d, 0x4f, 0xf6, 0xfe, 0x60, 0x20, 0x60, 0x40, 0x20, + 0x29, 0x69, 0x08, 0x60, 0xe9, 0x68, 0xdf, 0xf8, 0x68, 0x04, 0x09, 0x68, + 0x49, 0x06, 0x01, 0x78, 0x70, 0x47, 0x00, 0x00, 0x18, 0x00, 0x00, 0x49, + 0x4c, 0x1f, 0x00, 0x20, 0x00, 0xf2, 0x00, 0x20, 0x40, 0x42, 0x0f, 0x00, + 0xf8, 0xb5, 0x2d, 0x48, 0x02, 0x6c, 0x41, 0x6c, 0x11, 0x60, 0xd0, 0xf8, + 0x80, 0x10, 0xc1, 0xf3, 0x02, 0x14, 0xc1, 0x6b, 0x91, 0xb1, 0x09, 0x68, + 0x42, 0x6f, 0x21, 0xfa, 0x02, 0xf3, 0x82, 0x6f, 0x21, 0xfa, 0x02, 0xf5, + 0x05, 0xf0, 0x01, 0x02, 0x5b, 0x08, 0xc3, 0x6f, 0x52, 0x41, 0xd9, 0x40, + 0x01, 0xf0, 0x01, 0x01, 0x42, 0xea, 0x81, 0x05, 0xed, 0xb2, 0x04, 0xe0, + 0xdf, 0xf8, 0x10, 0x14, 0x09, 0x78, 0x01, 0xf0, 0x07, 0x05, 0xac, 0x42, + 0x35, 0xd0, 0xd0, 0xf8, 0x80, 0x10, 0xdf, 0xf8, 0xf8, 0x63, 0x21, 0xf0, + 0x70, 0x01, 0x41, 0xea, 0x05, 0x11, 0xc0, 0xf8, 0x80, 0x10, 0x10, 0x20, + 0xfe, 0xf7, 0x9f, 0xff, 0x4f, 0xf6, 0xfe, 0x60, 0x30, 0x60, 0xdf, 0xf8, + 0xd8, 0x03, 0x00, 0x7e, 0xc0, 0x07, 0x03, 0xd5, 0xdf, 0xf8, 0xb8, 0x03, + 0x00, 0xf0, 0x83, 0xf8, 0xdf, 0xf8, 0xd4, 0x73, 0x0f, 0xf2, 0x50, 0x41, + 0x38, 0x78, 0x00, 0xf0, 0xef, 0x00, 0x38, 0x70, 0x20, 0x46, 0x51, 0xf8, + 0x24, 0x10, 0x88, 0x47, 0x0f, 0xf2, 0x1c, 0x41, 0x51, 0xf8, 0x25, 0x10, + 0x28, 0x46, 0x88, 0x47, 0x38, 0x78, 0x40, 0xf0, 0x10, 0x00, 0x38, 0x70, + 0x00, 0x20, 0x30, 0x60, 0x1c, 0x20, 0xbd, 0xe8, 0xf2, 0x40, 0xfe, 0xf7, + 0x76, 0xbf, 0xf1, 0xbd, 0xd0, 0x1f, 0x00, 0x20, 0xdf, 0xf8, 0x98, 0x03, + 0xdf, 0xf8, 0x98, 0x23, 0x01, 0x78, 0x92, 0xf8, 0x6b, 0x20, 0x01, 0xf0, + 0xe0, 0x01, 0x11, 0x43, 0x41, 0xf0, 0x20, 0x01, 0x01, 0x70, 0x70, 0x47, + 0x30, 0xf3, 0x00, 0x20, 0x00, 0x00, 0x20, 0x59, 0xdf, 0xf8, 0x7c, 0x13, + 0x00, 0x20, 0x08, 0x70, 0xdf, 0xf8, 0x78, 0x13, 0x08, 0x80, 0x70, 0x47, + 0x70, 0x47, 0x10, 0xb5, 0x00, 0xf0, 0x2b, 0xf8, 0x00, 0xf0, 0x65, 0xf8, + 0xa4, 0x7c, 0x00, 0xf0, 0x69, 0xf8, 0x49, 0x7d, 0x81, 0x70, 0x01, 0x21, + 0x11, 0x70, 0xd4, 0x4a, 0x41, 0x79, 0x00, 0xf0, 0x54, 0xf8, 0x41, 0x71, + 0x01, 0x20, 0x11, 0xe0, 0xb4, 0x28, 0x00, 0x20, 0x10, 0xb5, 0x00, 0xf0, + 0x16, 0xf8, 0x00, 0xf0, 0x75, 0xf8, 0xa4, 0x7c, 0x23, 0x43, 0x03, 0x70, + 0x09, 0x78, 0x89, 0x18, 0x49, 0x7d, 0x81, 0x70, 0x01, 0x20, 0x00, 0xf0, + 0x68, 0xf8, 0x05, 0x20, 0x05, 0xf0, 0x67, 0xf9, 0x00, 0xf0, 0x1d, 0xf9, + 0x08, 0x20, 0xbd, 0xe8, 0x10, 0x40, 0xff, 0xf7, 0xe3, 0xb8, 0xc6, 0x48, + 0xc6, 0x4a, 0x01, 0x79, 0x01, 0xf0, 0x7f, 0x01, 0x01, 0x71, 0x70, 0x47, + 0x0c, 0x00, 0x00, 0x59, 0x80, 0xb5, 0x00, 0xe0, 0x80, 0xb5, 0x05, 0xf0, + 0x85, 0xf9, 0xc1, 0x48, 0x81, 0x78, 0x41, 0xf0, 0x80, 0x01, 0x81, 0x70, + 0x00, 0xf0, 0x05, 0xf8, 0x08, 0x20, 0xbd, 0xe8, 0x02, 0x40, 0xff, 0xf7, + 0xd3, 0xb8, 0x01, 0x78, 0x41, 0xf0, 0xc0, 0x01, 0x01, 0x70, 0x70, 0x47, + 0x10, 0xb5, 0x00, 0xf0, 0x49, 0xf8, 0x00, 0xf0, 0x18, 0xf8, 0x24, 0x7e, + 0x00, 0xf0, 0x1c, 0xf8, 0xc9, 0x7e, 0x81, 0x70, 0x02, 0x21, 0x11, 0x70, + 0xad, 0x4a, 0x01, 0x79, 0x00, 0xf0, 0x07, 0xf8, 0x01, 0x71, 0x02, 0x20, + 0x05, 0xf0, 0x2d, 0xf9, 0x00, 0xf0, 0x42, 0xf8, 0xc5, 0xe7, 0x92, 0xf8, + 0x43, 0x20, 0x01, 0xf0, 0xc0, 0x01, 0x11, 0x43, 0x70, 0x47, 0xab, 0x49, + 0x03, 0x78, 0x0c, 0x78, 0xa4, 0x18, 0x03, 0xf0, 0xc0, 0x03, 0x70, 0x47, + 0x23, 0x43, 0x03, 0x70, 0x09, 0x78, 0x89, 0x18, 0xa0, 0x4a, 0x70, 0x47, + 0x10, 0xb5, 0x00, 0xf0, 0x1f, 0xf8, 0x00, 0xf0, 0x13, 0xf8, 0x24, 0x7e, + 0x23, 0x43, 0x03, 0x70, 0x09, 0x78, 0x89, 0x18, 0xc9, 0x7e, 0x81, 0x70, + 0x02, 0x20, 0x00, 0xf0, 0x06, 0xf8, 0x06, 0x20, 0x05, 0xf0, 0x05, 0xf9, + 0x00, 0xf0, 0x1a, 0xf8, 0x9d, 0xe7, 0x95, 0x49, 0x08, 0x70, 0x55, 0xe7, + 0x99, 0x49, 0x03, 0x78, 0x0c, 0x78, 0xa4, 0x18, 0x03, 0xf0, 0xc0, 0x03, + 0x70, 0x47, 0x00, 0x00, 0x78, 0x29, 0x00, 0x20, 0x95, 0x48, 0x91, 0x4a, + 0xc1, 0x78, 0x01, 0xf0, 0xbf, 0x01, 0xc1, 0x70, 0x70, 0x47, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x50, 0x04, 0x00, 0x00, 0x58, 0x7c, 0x48, 0x01, 0x78, + 0x01, 0xf0, 0x3f, 0x01, 0x01, 0x70, 0x09, 0x20, 0x70, 0x47, 0x80, 0xb5, + 0x05, 0xf0, 0x12, 0xf9, 0x00, 0xf0, 0x07, 0xf8, 0x91, 0xe7, 0x80, 0xb5, + 0x05, 0xf0, 0x0c, 0xf9, 0x00, 0xf0, 0x01, 0xf8, 0x8b, 0xe7, 0x87, 0x48, + 0x41, 0x78, 0x41, 0xf0, 0x40, 0x01, 0x41, 0x70, 0x01, 0x78, 0x41, 0xf0, + 0xc0, 0x01, 0x01, 0x70, 0x09, 0x20, 0x70, 0x47, 0x10, 0xb5, 0x79, 0x49, + 0x7a, 0x4a, 0x00, 0x20, 0x08, 0x70, 0x7a, 0x49, 0x7b, 0x48, 0x13, 0x78, + 0x00, 0xf0, 0x1c, 0xf8, 0xa4, 0x7c, 0x23, 0x43, 0x13, 0x70, 0x93, 0x78, + 0x00, 0xf0, 0x16, 0xf8, 0x64, 0x7d, 0x23, 0x43, 0x93, 0x70, 0x53, 0x78, + 0x00, 0xf0, 0x10, 0xf8, 0x24, 0x7e, 0x23, 0x43, 0x53, 0x70, 0xd3, 0x78, + 0x00, 0x78, 0x40, 0x18, 0x03, 0xf0, 0xc0, 0x03, 0xc0, 0x7e, 0x18, 0x43, + 0xd0, 0x70, 0x10, 0xbd, 0x08, 0x00, 0x00, 0x50, 0x08, 0x00, 0x00, 0x58, + 0x04, 0x78, 0x64, 0x18, 0x03, 0xf0, 0xc0, 0x03, 0x70, 0x47, 0x80, 0xb5, + 0x05, 0xf0, 0xd0, 0xf8, 0x6b, 0x48, 0xff, 0xf7, 0x54, 0xff, 0x41, 0x78, + 0x41, 0xf0, 0xc0, 0x01, 0x41, 0x70, 0x63, 0x49, 0x8a, 0x78, 0x42, 0xf0, + 0xc0, 0x02, 0x8a, 0x70, 0x0a, 0x78, 0x42, 0xf0, 0xc0, 0x02, 0x0a, 0x70, + 0x4a, 0x78, 0x42, 0xf0, 0xc0, 0x02, 0x4a, 0x70, 0x81, 0x79, 0x01, 0xf0, + 0xcc, 0x01, 0x81, 0x71, 0x60, 0x48, 0x61, 0x49, 0x0a, 0x78, 0x03, 0x78, + 0x1a, 0x40, 0x83, 0x78, 0x1a, 0x43, 0x0a, 0x70, 0x4a, 0x78, 0x43, 0x78, + 0x1a, 0x40, 0xc3, 0x78, 0x1a, 0x43, 0x4a, 0x70, 0x01, 0x21, 0x41, 0x60, + 0x81, 0x60, 0x00, 0x20, 0x42, 0x49, 0x08, 0x70, 0x01, 0xbd, 0x08, 0xb1, + 0x57, 0x49, 0x08, 0x70, 0x70, 0x47, 0x56, 0x48, 0x00, 0x78, 0x70, 0x47, + 0x80, 0xb5, 0x55, 0x48, 0x53, 0x4a, 0x81, 0x79, 0x46, 0x4b, 0x01, 0xf0, + 0x7f, 0x01, 0x81, 0x71, 0x41, 0x79, 0x01, 0xf0, 0x3f, 0x01, 0x41, 0x71, + 0x12, 0x78, 0x0f, 0xf2, 0xa4, 0x11, 0x51, 0x5c, 0x4e, 0x4a, 0x11, 0x70, + 0x04, 0x22, 0x1a, 0x70, 0x01, 0x70, 0xff, 0xf7, 0xa9, 0xfe, 0x04, 0x20, + 0x05, 0xf0, 0x4f, 0xf8, 0x00, 0xf0, 0x05, 0xf8, 0x0a, 0x20, 0xbd, 0xe8, + 0x02, 0x40, 0xfe, 0xf7, 0xcb, 0xbf, 0x2c, 0x48, 0x01, 0x78, 0x01, 0xf0, + 0x3f, 0x01, 0x01, 0x70, 0x70, 0x47, 0x80, 0xb5, 0x05, 0xf0, 0x72, 0xf8, + 0x40, 0x48, 0x00, 0x21, 0x01, 0x70, 0x81, 0x79, 0x41, 0xf0, 0x80, 0x01, + 0x81, 0x71, 0x41, 0x79, 0x41, 0xf0, 0xc0, 0x01, 0x41, 0x71, 0x0a, 0x20, + 0xe7, 0xe6, 0x00, 0x00, 0x64, 0xf3, 0x00, 0x20, 0x0c, 0x00, 0x00, 0x58, + 0x44, 0x00, 0x00, 0x50, 0x2d, 0xe9, 0xf0, 0x47, 0x04, 0x46, 0x91, 0x46, + 0x9a, 0x46, 0xfe, 0xf7, 0xa1, 0xff, 0x1c, 0x4f, 0x80, 0x46, 0x38, 0x79, + 0x01, 0x28, 0x25, 0xd1, 0x02, 0x2c, 0x21, 0xd1, 0xfe, 0xf7, 0x98, 0xff, + 0x30, 0x4e, 0x31, 0x49, 0x35, 0x68, 0x04, 0x46, 0x4f, 0xf0, 0x00, 0x40, + 0x08, 0x60, 0xd7, 0xf8, 0x80, 0x00, 0xc0, 0xf3, 0x02, 0x10, 0x03, 0x28, + 0x18, 0xbf, 0x04, 0x28, 0x09, 0xd0, 0x05, 0x28, 0x18, 0xbf, 0x06, 0x28, + 0x05, 0xd0, 0x02, 0x22, 0x48, 0x46, 0x51, 0x46, 0x03, 0xf0, 0xc4, 0xfc, + 0x00, 0xe0, 0x05, 0x20, 0x05, 0xf0, 0x00, 0x41, 0x31, 0x60, 0x84, 0xf3, + 0x11, 0x88, 0x06, 0xe0, 0x05, 0x20, 0x04, 0xe0, 0x22, 0x46, 0x48, 0x46, + 0x51, 0x46, 0x03, 0xf0, 0xb5, 0xfc, 0x88, 0xf3, 0x11, 0x88, 0xc0, 0xb2, + 0xbd, 0xe8, 0xf0, 0x87, 0x41, 0x0c, 0x00, 0x46, 0x65, 0x2c, 0x00, 0x20, + 0xd0, 0x1f, 0x00, 0x20, 0x4c, 0x00, 0x00, 0x50, 0x4c, 0x00, 0x00, 0x58, + 0x4c, 0x1f, 0x00, 0x20, 0x48, 0x00, 0x00, 0x50, 0xb0, 0x01, 0x00, 0x46, + 0x28, 0x0b, 0x00, 0x46, 0x42, 0x06, 0x00, 0x46, 0x15, 0x08, 0x00, 0x46, + 0x68, 0xee, 0x00, 0x20, 0x04, 0x01, 0x00, 0x46, 0xfe, 0x01, 0x00, 0x41, + 0x10, 0x08, 0x00, 0x46, 0x4c, 0x29, 0x00, 0x20, 0x12, 0x08, 0x00, 0x46, + 0x6c, 0x29, 0x00, 0x20, 0x6d, 0x29, 0x00, 0x20, 0x11, 0x08, 0x00, 0x46, + 0x13, 0x08, 0x00, 0x46, 0x42, 0x05, 0x00, 0x46, 0xec, 0x2b, 0x00, 0x20, + 0x02, 0x0b, 0x00, 0x46, 0x64, 0x2c, 0x00, 0x20, 0x1a, 0x08, 0x00, 0x46, + 0x0c, 0x02, 0x00, 0x46, 0x00, 0xe1, 0x00, 0xe0, 0x80, 0xe1, 0x00, 0xe0, + 0x04, 0x02, 0x84, 0x0d, 0x05, 0x02, 0x85, 0x0d, 0x06, 0x02, 0x86, 0x0d, + 0x41, 0x0c, 0x00, 0x00, 0x45, 0x90, 0x00, 0x01, 0x57, 0x90, 0x00, 0x01, + 0xf1, 0x90, 0x00, 0x01, 0xdd, 0x91, 0x00, 0x01, 0xa1, 0x92, 0x00, 0x01, + 0x81, 0x90, 0x00, 0x01, 0x45, 0x91, 0x00, 0x01, 0x45, 0x90, 0x00, 0x01, + 0x55, 0x90, 0x00, 0x01, 0xc5, 0x90, 0x00, 0x01, 0xaf, 0x91, 0x00, 0x01, + 0x33, 0x92, 0x00, 0x01, 0xef, 0x92, 0x00, 0x01, 0xc9, 0x90, 0x00, 0x01, + 0xbb, 0x91, 0x00, 0x01, 0x55, 0x90, 0x00, 0x01, 0x08, 0x09, 0x00, 0x00, + 0x0c, 0x0d, 0x00, 0x00, 0x00, 0x03, 0x0c, 0x30, 0x0f, 0xf2, 0x2c, 0x02, + 0x00, 0xf0, 0x1f, 0x00, 0x80, 0x5c, 0x08, 0xb9, 0x03, 0x20, 0x70, 0x47, + 0x01, 0x22, 0x02, 0xfa, 0x01, 0xf1, 0x08, 0x42, 0x14, 0xbf, 0x00, 0x20, + 0x02, 0x20, 0x70, 0x47, 0x0f, 0xf2, 0x1c, 0x02, 0x06, 0x23, 0x03, 0xfb, + 0x00, 0x20, 0x08, 0x5c, 0x70, 0x47, 0x00, 0x00, 0x0c, 0x18, 0x1c, 0x1c, + 0x18, 0x3e, 0x3e, 0x18, 0x00, 0x3e, 0x1c, 0x3e, 0x3e, 0x0c, 0x00, 0x00, + 0x02, 0x00, 0x80, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x80, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x02, 0x02, 0x00, 0x80, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x80, 0xb5, 0x08, 0x46, + 0x6b, 0x46, 0x40, 0x68, 0x01, 0x22, 0x08, 0x21, 0xf8, 0xf7, 0x44, 0xff, + 0x00, 0xf0, 0x01, 0xf8, 0x01, 0xbd, 0x9d, 0xf8, 0x00, 0x10, 0x48, 0x1e, + 0x80, 0x41, 0xc0, 0x0f, 0xfe, 0xf7, 0x9d, 0xbc, 0x70, 0xb5, 0x82, 0xb0, + 0x0d, 0xf1, 0x01, 0x00, 0xfa, 0xf7, 0x47, 0xfa, 0x01, 0x24, 0x67, 0x4d, + 0x58, 0x20, 0x00, 0xfb, 0x04, 0x56, 0x33, 0x69, 0x18, 0x00, 0x03, 0xd0, + 0x70, 0x6a, 0x00, 0x22, 0x00, 0x21, 0x98, 0x47, 0x69, 0x46, 0x00, 0x20, + 0xf8, 0xf7, 0x73, 0xfe, 0x70, 0x60, 0xff, 0xf7, 0xe0, 0xff, 0x64, 0x1c, + 0x11, 0x2c, 0xeb, 0xd3, 0x05, 0xf0, 0x46, 0xff, 0x0d, 0xf1, 0x01, 0x00, + 0x00, 0xf0, 0xe0, 0xfa, 0x73, 0xbd, 0xf8, 0xb5, 0xfe, 0xf7, 0x70, 0xfe, + 0x00, 0x24, 0x57, 0x4d, 0x57, 0x4e, 0xe0, 0xb2, 0xfb, 0xf7, 0xae, 0xf8, + 0x60, 0xb1, 0xa0, 0x5d, 0x58, 0x21, 0x01, 0xfb, 0x00, 0x57, 0x00, 0xf0, + 0x25, 0xf8, 0x3b, 0x69, 0x18, 0x00, 0x03, 0xd0, 0x78, 0x6a, 0x00, 0x22, + 0x02, 0x21, 0x98, 0x47, 0x64, 0x1c, 0x10, 0x2c, 0xeb, 0xd3, 0xf1, 0xbd, + 0x10, 0xb5, 0x4b, 0x4c, 0x82, 0xb0, 0x60, 0x62, 0x60, 0x68, 0x20, 0xb9, + 0x69, 0x46, 0xf8, 0xf7, 0x42, 0xfe, 0x60, 0x60, 0x03, 0xe0, 0x00, 0xf0, + 0x98, 0xf8, 0xff, 0xf7, 0xac, 0xff, 0x00, 0x20, 0x00, 0xf0, 0x08, 0xf8, + 0x23, 0x69, 0x18, 0x00, 0x03, 0xd0, 0x60, 0x6a, 0x00, 0x22, 0x02, 0x21, + 0x98, 0x47, 0x13, 0xbd, 0x30, 0xb5, 0x04, 0x46, 0x3d, 0x48, 0x58, 0x21, + 0x87, 0xb0, 0x01, 0xfb, 0x04, 0x05, 0xfb, 0xf7, 0x37, 0xf8, 0xc4, 0xb1, + 0x3b, 0x48, 0x20, 0x5c, 0xfb, 0xf7, 0x74, 0xf8, 0x00, 0x28, 0x36, 0xd0, + 0x20, 0x46, 0xfa, 0xf7, 0xfd, 0xfd, 0x05, 0xa9, 0x02, 0x91, 0x00, 0x95, + 0x00, 0x21, 0x01, 0x91, 0x01, 0x46, 0x35, 0x4b, 0x01, 0x22, 0x00, 0x20, + 0xf9, 0xf7, 0xa4, 0xfa, 0xa8, 0x62, 0x9d, 0xf8, 0x14, 0x10, 0xff, 0xf7, + 0x80, 0xff, 0xeb, 0x6b, 0xa8, 0x6c, 0xe9, 0x6c, 0x01, 0x90, 0x03, 0x22, + 0x04, 0x92, 0x02, 0x91, 0x9a, 0xb2, 0x00, 0x92, 0x00, 0xeb, 0x81, 0x00, + 0x03, 0x94, 0x02, 0x1f, 0x69, 0x6a, 0x68, 0x6c, 0xdb, 0xb2, 0xf9, 0xf7, + 0x6c, 0xf9, 0x8d, 0xf8, 0x14, 0x00, 0x00, 0xf0, 0x4d, 0xf8, 0xe8, 0x6b, + 0x29, 0x6c, 0x05, 0xaa, 0xc0, 0xb2, 0xf9, 0xf7, 0x19, 0xfa, 0x9d, 0xf8, + 0x14, 0x10, 0xff, 0xf7, 0x60, 0xff, 0x29, 0x46, 0x20, 0x46, 0xf9, 0xf7, + 0x23, 0xff, 0x00, 0x20, 0x07, 0xb0, 0x30, 0xbd, 0x38, 0xb5, 0x05, 0x46, + 0x18, 0x48, 0x58, 0x21, 0x01, 0xfb, 0x05, 0x04, 0xfa, 0xf7, 0xee, 0xff, + 0x25, 0xb1, 0x17, 0x48, 0x28, 0x5c, 0xfb, 0xf7, 0x2b, 0xf8, 0xf8, 0xb1, + 0x28, 0x46, 0xfa, 0xf7, 0x99, 0xf8, 0xa0, 0x6a, 0x68, 0xb1, 0x6b, 0x46, + 0x00, 0x22, 0x00, 0x21, 0xf9, 0xf7, 0x46, 0xfb, 0xa0, 0x6a, 0x0d, 0xf1, + 0x01, 0x01, 0xf9, 0xf7, 0x99, 0xfa, 0x9d, 0xf8, 0x01, 0x10, 0xff, 0xf7, + 0x38, 0xff, 0x60, 0x68, 0x00, 0xf0, 0x1d, 0xf8, 0xff, 0xf7, 0x31, 0xff, + 0xe0, 0x6b, 0xc0, 0xb2, 0xf9, 0xf7, 0x74, 0xf9, 0x8d, 0xf8, 0x00, 0x00, + 0x00, 0xf0, 0x0e, 0xf8, 0x9d, 0xf8, 0x00, 0x00, 0x00, 0xb1, 0x02, 0x20, + 0x32, 0xbd, 0x00, 0x00, 0xd8, 0x20, 0x00, 0x20, 0xc8, 0x20, 0x00, 0x20, + 0xf4, 0x1e, 0x00, 0x20, 0xf5, 0x94, 0x00, 0x01, 0x40, 0x1e, 0x80, 0x41, + 0xc0, 0x0f, 0xfe, 0xf7, 0xba, 0xbb, 0x6b, 0x46, 0x00, 0x22, 0x4f, 0xf6, + 0xff, 0x71, 0xf8, 0xf7, 0x51, 0xbe, 0x00, 0x00, 0x2c, 0x21, 0xfe, 0xf7, + 0x05, 0xba, 0x00, 0x00, 0x2d, 0xe9, 0xf0, 0x41, 0x88, 0x46, 0x04, 0x46, + 0x00, 0x25, 0xc9, 0xb2, 0x48, 0x09, 0x05, 0x28, 0x01, 0xf0, 0x1f, 0x01, + 0x49, 0xda, 0x0f, 0xf2, 0xac, 0x03, 0x03, 0xeb, 0xc0, 0x02, 0x57, 0x68, + 0x00, 0x2f, 0x42, 0xd0, 0x13, 0xf8, 0x30, 0x30, 0x99, 0x42, 0x3e, 0xda, + 0x23, 0x4b, 0x53, 0xf8, 0x20, 0x60, 0x01, 0x27, 0x07, 0xfa, 0x01, 0xfe, + 0x0e, 0xea, 0x06, 0x06, 0xd3, 0xf8, 0x14, 0xe0, 0x9b, 0x69, 0x07, 0xfa, + 0x00, 0xf0, 0x00, 0xea, 0x0e, 0x00, 0x30, 0x43, 0x43, 0xea, 0x00, 0x07, + 0x50, 0x68, 0x00, 0xeb, 0xc1, 0x06, 0xfb, 0xf7, 0xc2, 0xf9, 0x04, 0x28, + 0x03, 0xd1, 0xf0, 0x88, 0x80, 0xf0, 0x01, 0x00, 0x07, 0x43, 0x00, 0x2c, + 0x1c, 0xbf, 0x00, 0x2f, 0x06, 0x25, 0x1d, 0xd1, 0x30, 0x68, 0xb1, 0x88, + 0x00, 0x28, 0x18, 0xbf, 0x00, 0x29, 0x14, 0xd0, 0x4f, 0xea, 0x08, 0x23, + 0x4f, 0xea, 0x18, 0x62, 0x02, 0xeb, 0x13, 0x46, 0xb1, 0x42, 0x0a, 0xdb, + 0x00, 0xeb, 0x13, 0x40, 0x0b, 0x4b, 0x00, 0x2c, 0x12, 0xbf, 0x19, 0x46, + 0x01, 0x46, 0x18, 0x46, 0x00, 0xf0, 0x6e, 0xfa, 0x04, 0xe0, 0x07, 0x25, + 0x02, 0xe0, 0x05, 0x25, 0x00, 0xe0, 0x04, 0x25, 0x28, 0x46, 0xbd, 0xe8, + 0xf0, 0x81, 0x02, 0x49, 0x00, 0xf0, 0x01, 0x00, 0x88, 0x61, 0x70, 0x47, + 0x14, 0x27, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x13, 0x00, 0x00, 0x00, + 0x00, 0x68, 0x01, 0x01, 0x08, 0x00, 0x00, 0x00, 0x68, 0x6f, 0x01, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x38, 0x76, 0x01, 0x01, + 0x10, 0xb5, 0x01, 0x21, 0x15, 0x20, 0xfe, 0xf7, 0x08, 0xfc, 0x00, 0xf0, + 0x4d, 0xf8, 0x84, 0x4c, 0xf9, 0xf7, 0x47, 0xfc, 0x21, 0x7a, 0x4f, 0xf4, + 0xdb, 0x70, 0xf9, 0xf7, 0x11, 0xfc, 0x61, 0x7a, 0x80, 0x4c, 0x40, 0xf2, + 0xb7, 0x10, 0xf9, 0xf7, 0x0b, 0xfc, 0xfe, 0xf7, 0xbc, 0xfa, 0x00, 0x22, + 0x03, 0x21, 0x40, 0xf2, 0x33, 0x40, 0xf9, 0xf7, 0x0d, 0xfc, 0x00, 0x22, + 0x01, 0x21, 0x40, 0xf2, 0x4c, 0x40, 0xf9, 0xf7, 0x07, 0xfc, 0x00, 0x22, + 0x0f, 0x21, 0x40, 0xf2, 0x2e, 0x40, 0xf9, 0xf7, 0x01, 0xfc, 0x00, 0x22, + 0x03, 0x21, 0x4f, 0xf4, 0x89, 0x60, 0xf9, 0xf7, 0xfb, 0xfb, 0x21, 0x78, + 0x40, 0xf2, 0x35, 0x40, 0xf9, 0xf7, 0xec, 0xfb, 0x61, 0x7d, 0x40, 0xf2, + 0x36, 0x40, 0xf9, 0xf7, 0xe7, 0xfb, 0xff, 0xf7, 0x8e, 0xf8, 0xff, 0xf7, + 0xbc, 0xf8, 0xff, 0xf7, 0xdb, 0xf8, 0xbd, 0xe8, 0x10, 0x40, 0x04, 0x20, + 0xfc, 0xf7, 0xc2, 0xbf, 0x80, 0xb5, 0x04, 0x20, 0xfd, 0xf7, 0x00, 0xf8, + 0x00, 0xf0, 0x0a, 0xf8, 0xf9, 0xf7, 0xf2, 0xfb, 0xfe, 0xf7, 0xa0, 0xfa, + 0xbd, 0xe8, 0x04, 0x40, 0x00, 0x21, 0x15, 0x20, 0xfe, 0xf7, 0xb9, 0xbb, + 0x09, 0x22, 0x5f, 0x49, 0x0f, 0xf2, 0x78, 0x20, 0x70, 0x47, 0x2d, 0xe9, + 0xf1, 0x4f, 0xdf, 0xf8, 0x74, 0xa1, 0x5d, 0x4e, 0x5d, 0x4f, 0x82, 0xb0, + 0x9a, 0xf8, 0x00, 0x00, 0x00, 0x90, 0x00, 0x24, 0x74, 0x60, 0xb4, 0x81, + 0x03, 0x21, 0xb8, 0x7a, 0x08, 0x42, 0x06, 0xd0, 0x01, 0x20, 0x03, 0xf0, + 0x5f, 0xf8, 0x00, 0x29, 0x08, 0xbf, 0x00, 0x28, 0x15, 0xd0, 0x78, 0x89, + 0xc0, 0xf3, 0x81, 0x00, 0x30, 0xb1, 0x00, 0x20, 0x03, 0xf0, 0x54, 0xf8, + 0x00, 0x29, 0x08, 0xbf, 0x00, 0x28, 0x0a, 0xd0, 0x78, 0x89, 0xc0, 0xf3, + 0x82, 0x10, 0x40, 0xb1, 0x02, 0x20, 0x03, 0xf0, 0x49, 0xf8, 0x00, 0x29, + 0x08, 0xbf, 0x00, 0x28, 0x01, 0xd1, 0x05, 0x24, 0x53, 0xe0, 0x00, 0x98, + 0x20, 0x28, 0x4f, 0xd2, 0x01, 0x20, 0xff, 0xf7, 0x54, 0xff, 0x34, 0x61, + 0x00, 0x27, 0xdf, 0xf8, 0x14, 0x81, 0xdf, 0xf8, 0x14, 0x91, 0x00, 0xe0, + 0x7f, 0x1c, 0x00, 0x98, 0x87, 0x42, 0x3d, 0xd2, 0x07, 0xeb, 0x0a, 0x00, + 0x0c, 0x21, 0x40, 0x78, 0x00, 0xf0, 0x1f, 0x05, 0x0f, 0xf2, 0x00, 0x10, + 0x01, 0xfb, 0x05, 0x0b, 0xdb, 0xf8, 0x04, 0x00, 0x00, 0x28, 0xed, 0xd0, + 0x02, 0x98, 0xe8, 0x40, 0xc0, 0x07, 0xe9, 0xd5, 0x29, 0x46, 0x16, 0x20, + 0xfe, 0xf7, 0x6c, 0xfb, 0x49, 0x46, 0x04, 0x20, 0xfc, 0xf7, 0x5e, 0xff, + 0x9b, 0xf8, 0x08, 0x00, 0xfe, 0xf7, 0x66, 0xfa, 0xdb, 0xf8, 0x04, 0x20, + 0x41, 0x46, 0x00, 0x20, 0x90, 0x47, 0x04, 0x46, 0x04, 0x20, 0xfc, 0xf7, + 0x77, 0xff, 0xe4, 0xb2, 0x1c, 0xb1, 0x35, 0x73, 0x74, 0x73, 0x07, 0x24, + 0x10, 0xe0, 0x01, 0x21, 0x72, 0x68, 0xa9, 0x40, 0x0a, 0x43, 0x72, 0x60, + 0x32, 0x68, 0x11, 0x43, 0x31, 0x60, 0x31, 0x69, 0x49, 0x44, 0x08, 0x1a, + 0x30, 0x61, 0xfa, 0xf7, 0x20, 0xfe, 0x00, 0x28, 0xbe, 0xd0, 0x06, 0x24, + 0x00, 0x20, 0xff, 0xf7, 0x08, 0xff, 0x00, 0xe0, 0x04, 0x24, 0x20, 0x46, + 0xbd, 0xe8, 0xfe, 0x8f, 0x1f, 0x49, 0x01, 0x20, 0x08, 0x70, 0x70, 0x47, + 0xf8, 0xb5, 0x04, 0x46, 0x0d, 0x46, 0x16, 0x46, 0x19, 0x46, 0x00, 0x20, + 0xfc, 0xf7, 0xcc, 0xff, 0x00, 0x27, 0xfa, 0xf7, 0x06, 0xfe, 0x08, 0xb1, + 0x02, 0x27, 0x0d, 0xe0, 0x04, 0xf1, 0x8c, 0x40, 0x05, 0xea, 0x06, 0x01, + 0x00, 0x78, 0x28, 0x40, 0x88, 0x42, 0x05, 0xd0, 0x00, 0x20, 0xfc, 0xf7, + 0xd3, 0xff, 0x00, 0x28, 0xed, 0xd0, 0x01, 0x27, 0x00, 0x20, 0xfc, 0xf7, + 0x45, 0xff, 0x38, 0x46, 0xf2, 0xbd, 0x09, 0x48, 0x81, 0x68, 0x00, 0x68, + 0x08, 0x40, 0x88, 0x42, 0x0c, 0xbf, 0x01, 0x20, 0x00, 0x20, 0x70, 0x47, + 0x00, 0x00, 0x00, 0x00, 0x4c, 0x1f, 0x00, 0x20, 0x31, 0x04, 0x00, 0x46, + 0xfc, 0xf2, 0x00, 0x20, 0xd4, 0x28, 0x00, 0x20, 0xe8, 0xf2, 0x00, 0x20, + 0x78, 0x29, 0x00, 0x20, 0x60, 0xb5, 0x00, 0x20, 0xc0, 0xe1, 0xe4, 0x00, + 0x9e, 0xf3, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0xed, 0x52, 0x01, 0x01, + 0x05, 0x00, 0x00, 0x00, 0x91, 0x55, 0x01, 0x01, 0x93, 0x55, 0x01, 0x01, + 0x05, 0x00, 0x00, 0x00, 0x7d, 0x69, 0x01, 0x01, 0x7f, 0x69, 0x01, 0x01, + 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x38, 0x01, 0x01, + 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x64, 0x01, 0x01, + 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf5, 0x76, 0x01, 0x01, + 0x38, 0x00, 0x00, 0x00, 0x11, 0x31, 0x01, 0x01, 0x13, 0x31, 0x01, 0x01, + 0xc8, 0x00, 0x00, 0x00, 0x6d, 0x75, 0x00, 0x01, 0x81, 0x75, 0x00, 0x01, + 0x38, 0x00, 0x00, 0x00, 0x5d, 0x17, 0x00, 0x01, 0xc9, 0x13, 0x00, 0x01, + 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x15, 0x00, 0x01, + 0x38, 0x00, 0x00, 0x00, 0xb7, 0x58, 0x01, 0x01, 0xf7, 0x58, 0x01, 0x01, + 0x38, 0x00, 0x00, 0x00, 0x95, 0x5b, 0x01, 0x01, 0x8b, 0x5c, 0x01, 0x01, + 0x38, 0x00, 0x00, 0x00, 0x91, 0x5d, 0x01, 0x01, 0xd5, 0x5d, 0x01, 0x01, + 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xf9, 0x5c, 0x01, 0x01, 0xa5, 0x5d, 0x01, 0x01, + 0xc8, 0x00, 0x00, 0x00, 0xd9, 0xdb, 0x00, 0x01, 0x31, 0xdc, 0x00, 0x01, + 0xf8, 0x00, 0x00, 0x00, 0xbd, 0xa5, 0x00, 0x01, 0x1d, 0xa6, 0x00, 0x01, + 0x38, 0x00, 0x00, 0x00, 0xe5, 0x60, 0x00, 0x01, 0x15, 0x61, 0x00, 0x01, + 0x38, 0x00, 0x00, 0x00, 0x4b, 0x34, 0x00, 0x01, 0x4d, 0x34, 0x00, 0x01, + 0x38, 0x00, 0x00, 0x00, 0x2e, 0x04, 0x33, 0x04, 0x35, 0x04, 0x36, 0x04, + 0x48, 0x04, 0x4c, 0x04, 0x5b, 0x04, 0x5c, 0x04, 0x5d, 0x04, 0x00, 0x00, + 0x30, 0xb5, 0x04, 0x46, 0x4a, 0x4d, 0x87, 0xb0, 0x08, 0x21, 0x28, 0x1d, + 0xf8, 0xf7, 0x0f, 0xfd, 0x28, 0x60, 0x00, 0xb1, 0x01, 0x20, 0xfe, 0xf7, + 0x8e, 0xf9, 0x03, 0x21, 0x04, 0x91, 0x00, 0xf0, 0x24, 0xf8, 0x05, 0xaa, + 0x0f, 0xf2, 0x10, 0x11, 0x16, 0x20, 0xf8, 0xf7, 0x97, 0xff, 0x00, 0x20, + 0x12, 0xe0, 0x30, 0xb5, 0x87, 0xb0, 0x03, 0x21, 0x04, 0x91, 0x04, 0x46, + 0x00, 0xf0, 0x15, 0xf8, 0x00, 0xf0, 0x0d, 0xf8, 0x05, 0xaa, 0x0f, 0xf2, + 0x00, 0x11, 0x16, 0x20, 0xf8, 0xf7, 0x86, 0xff, 0x00, 0x2d, 0x0c, 0xbf, + 0x00, 0x20, 0x02, 0x20, 0x20, 0x70, 0x07, 0xb0, 0x30, 0xbd, 0x05, 0x46, + 0x40, 0x1e, 0x80, 0x41, 0xc0, 0x0f, 0xfe, 0xf7, 0x66, 0xb9, 0x00, 0x21, + 0x03, 0x91, 0x4f, 0xf4, 0x20, 0x71, 0x02, 0x91, 0x16, 0x21, 0x2f, 0x48, + 0x01, 0x90, 0x00, 0x91, 0x00, 0xf6, 0xfc, 0x12, 0x16, 0x23, 0x00, 0x21, + 0x0f, 0xf2, 0x39, 0x00, 0xf8, 0xf7, 0xb1, 0xbe, 0x38, 0xb5, 0x04, 0x46, + 0x00, 0x20, 0xfe, 0xf7, 0x1d, 0xfb, 0x03, 0x20, 0xfe, 0xf7, 0x1a, 0xfb, + 0x24, 0x48, 0x00, 0x68, 0xf8, 0xf7, 0x00, 0xfd, 0xff, 0xf7, 0xdc, 0xff, + 0x16, 0x20, 0xf8, 0xf7, 0xe7, 0xfe, 0xff, 0xf7, 0xd6, 0xff, 0x00, 0x2d, + 0x0c, 0xbf, 0x00, 0x20, 0x02, 0x20, 0x20, 0x70, 0x31, 0xbd, 0x00, 0x00, + 0x38, 0xb5, 0x1b, 0x4c, 0x23, 0xe0, 0xfe, 0xf7, 0x36, 0xf9, 0x00, 0x20, + 0xfe, 0xf7, 0xe2, 0xfa, 0x00, 0x20, 0xf9, 0xf7, 0x7f, 0xfe, 0x01, 0x28, + 0x19, 0xd0, 0x29, 0x0e, 0x0c, 0x20, 0xfe, 0xf7, 0x0d, 0xfa, 0x01, 0x21, + 0x0b, 0x20, 0xfe, 0xf7, 0xfa, 0xf9, 0x00, 0x20, 0xf9, 0xf7, 0x87, 0xfd, + 0x01, 0x00, 0x0c, 0xd0, 0x48, 0x68, 0xc9, 0x68, 0x88, 0x47, 0x00, 0x21, + 0x0b, 0x20, 0xfe, 0xf7, 0xee, 0xf9, 0x00, 0x20, 0xf9, 0xf7, 0xe0, 0xfd, + 0x00, 0x20, 0xfe, 0xf7, 0xe1, 0xfa, 0x00, 0x20, 0xfe, 0xf7, 0xde, 0xfa, + 0x20, 0x68, 0x6a, 0x46, 0x00, 0x21, 0xf8, 0xf7, 0xd2, 0xfc, 0x00, 0x68, + 0x05, 0x04, 0xc0, 0xb2, 0x07, 0x28, 0x0c, 0xbf, 0x01, 0x20, 0x00, 0x20, + 0xcb, 0xe7, 0x00, 0x00, 0x88, 0xf2, 0x00, 0x20, 0x68, 0x2c, 0x00, 0x20, + 0x41, 0x6e, 0x61, 0x6c, 0x79, 0x73, 0x69, 0x73, 0x54, 0x61, 0x73, 0x6b, + 0x00, 0x00, 0x00, 0x00, 0x41, 0x6e, 0x61, 0x6c, 0x79, 0x73, 0x69, 0x73, + 0x54, 0x73, 0x6b, 0x00, 0x62, 0xb3, 0x8b, 0x07, 0x08, 0xd0, 0x52, 0x1e, + 0x11, 0xf8, 0x01, 0x3b, 0x00, 0xf8, 0x01, 0x3b, 0x00, 0xf0, 0x24, 0x80, + 0x8b, 0x07, 0xf6, 0xd1, 0x83, 0x07, 0x40, 0xf0, 0x20, 0x80, 0x00, 0xbf, + 0x10, 0x3a, 0x07, 0xd3, 0x30, 0xb4, 0xb1, 0xe8, 0x38, 0x10, 0x10, 0x3a, + 0xa0, 0xe8, 0x38, 0x10, 0xf9, 0xd2, 0x30, 0xbc, 0x53, 0x07, 0x24, 0xbf, + 0xb1, 0xe8, 0x08, 0x10, 0xa0, 0xe8, 0x08, 0x10, 0x44, 0xbf, 0x51, 0xf8, + 0x04, 0x3b, 0x40, 0xf8, 0x04, 0x3b, 0xd2, 0x07, 0x24, 0xbf, 0x31, 0xf8, + 0x02, 0x2b, 0x20, 0xf8, 0x02, 0x2b, 0x44, 0xbf, 0x0b, 0x78, 0x03, 0x70, + 0x70, 0x47, 0x08, 0x3a, 0x07, 0xd3, 0xb1, 0xe8, 0x08, 0x10, 0x08, 0x3a, + 0x40, 0xf8, 0x04, 0x3b, 0x40, 0xf8, 0x04, 0xcb, 0xf7, 0xd2, 0x53, 0x07, + 0xe4, 0xe7, 0x00, 0x00, 0x80, 0xb5, 0x30, 0x48, 0x4f, 0xf0, 0x80, 0x71, + 0x01, 0x63, 0xc2, 0x6b, 0x42, 0xf0, 0x80, 0x72, 0xc2, 0x63, 0x01, 0x60, + 0x20, 0x20, 0x01, 0x21, 0xfe, 0xf7, 0x07, 0xf9, 0x20, 0x20, 0xfe, 0xf7, + 0xe9, 0xf8, 0xbd, 0xe8, 0x02, 0x40, 0x20, 0x20, 0xfe, 0xf7, 0xea, 0xb8, + 0x2d, 0xe9, 0xf0, 0x41, 0x82, 0xb0, 0x00, 0x24, 0x00, 0x25, 0x24, 0x4e, + 0x06, 0xeb, 0xc5, 0x07, 0xd7, 0xf8, 0x08, 0x80, 0x0e, 0xe0, 0x30, 0x68, + 0x64, 0x1c, 0x84, 0x42, 0x05, 0xd3, 0x71, 0x68, 0xb0, 0x69, 0x6a, 0x46, + 0xf8, 0xf7, 0x68, 0xfd, 0x00, 0x24, 0x40, 0x46, 0x00, 0xf0, 0x0a, 0xf8, + 0x08, 0xf1, 0x04, 0x08, 0xf8, 0x68, 0x80, 0x45, 0xed, 0xd3, 0x6d, 0x1c, + 0x02, 0x2d, 0xe5, 0xd3, 0xbd, 0xe8, 0xf3, 0x81, 0x80, 0xb5, 0x72, 0xb6, + 0x15, 0x48, 0x16, 0x49, 0x01, 0x60, 0x00, 0x21, 0x01, 0x60, 0x62, 0xb6, + 0x00, 0x22, 0xf0, 0x21, 0x40, 0xf6, 0x59, 0x40, 0xf9, 0xf7, 0x60, 0xf9, + 0xbd, 0xe8, 0x08, 0x40, 0x00, 0x22, 0xf0, 0x21, 0x40, 0xf6, 0x51, 0x40, + 0xf9, 0xf7, 0x58, 0xb9, 0x80, 0xb5, 0xff, 0xf7, 0xaf, 0xff, 0x00, 0x22, + 0x02, 0x21, 0x4f, 0xf4, 0x45, 0x60, 0xf9, 0xf7, 0x4f, 0xf9, 0x00, 0x20, + 0xf8, 0xf7, 0x10, 0xfd, 0x04, 0x49, 0x88, 0x61, 0x01, 0xbd, 0x03, 0x48, + 0x80, 0x69, 0xf8, 0xf7, 0x8d, 0xbd, 0x00, 0x00, 0x10, 0x00, 0x00, 0x58, + 0x30, 0x1f, 0x00, 0x20, 0x48, 0x00, 0x00, 0x50, 0x00, 0x00, 0xab, 0xab, + 0x00, 0x20, 0xfe, 0xf7, 0x48, 0xb8, 0x00, 0x00, 0x0f, 0x28, 0xb4, 0xbf, + 0x01, 0x20, 0x00, 0x20, 0x70, 0x47, 0x70, 0xb5, 0x00, 0xf0, 0x12, 0xf8, + 0x2c, 0x43, 0x1c, 0x60, 0x02, 0xeb, 0x40, 0x00, 0x01, 0x23, 0x07, 0xe0, + 0x70, 0xb5, 0x00, 0xf0, 0x09, 0xf8, 0xac, 0x43, 0x1c, 0x60, 0x02, 0xeb, + 0x40, 0x00, 0x00, 0x23, 0x43, 0x70, 0x81, 0xf3, 0x10, 0x88, 0x70, 0xbd, + 0xef, 0xf3, 0x10, 0x81, 0x72, 0xb6, 0x1d, 0x4b, 0x1d, 0x4a, 0x1c, 0x68, + 0x12, 0xf9, 0x10, 0x60, 0x01, 0x25, 0xb5, 0x40, 0x70, 0x47, 0x0f, 0xf2, + 0x78, 0x02, 0x19, 0x49, 0x82, 0x5c, 0x52, 0xb9, 0x11, 0xf8, 0x10, 0x00, + 0x17, 0x49, 0xc2, 0x08, 0x00, 0xf0, 0x07, 0x00, 0x51, 0x5c, 0xc1, 0x40, + 0x01, 0xf0, 0x01, 0x00, 0x70, 0x47, 0x01, 0xeb, 0x40, 0x00, 0x40, 0x78, + 0x70, 0x47, 0x38, 0xb5, 0x0f, 0x4b, 0x03, 0xeb, 0x40, 0x03, 0xef, 0xf3, + 0x10, 0x84, 0x72, 0xb6, 0x0f, 0xf2, 0x40, 0x05, 0x45, 0x5d, 0x01, 0x2d, + 0x0a, 0xd1, 0x02, 0xb9, 0x13, 0x21, 0x19, 0x70, 0x59, 0x78, 0x11, 0xb1, + 0xff, 0xf7, 0xb9, 0xff, 0x03, 0xe0, 0xff, 0xf7, 0xbf, 0xff, 0x00, 0xe0, + 0x19, 0x70, 0x84, 0xf3, 0x10, 0x88, 0x31, 0xbd, 0x02, 0x49, 0x11, 0xf8, + 0x10, 0x00, 0x70, 0x47, 0x18, 0x00, 0x00, 0x49, 0xb4, 0x28, 0x00, 0x20, + 0x26, 0x0b, 0x00, 0x46, 0x0f, 0xf2, 0x04, 0x01, 0x40, 0x5c, 0x70, 0x47, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x00, 0xef, 0xf3, 0x11, 0x80, 0x60, 0x21, 0x81, 0xf3, + 0x11, 0x88, 0x70, 0x47, 0xdf, 0xf8, 0x9c, 0x06, 0x00, 0x78, 0x00, 0xf0, + 0x02, 0x00, 0x70, 0x47, 0x38, 0xb5, 0x04, 0x46, 0x0d, 0x46, 0xff, 0xf7, + 0xef, 0xff, 0x00, 0x22, 0x00, 0x23, 0xc5, 0xe9, 0x02, 0x23, 0xc5, 0xe9, + 0x04, 0x23, 0xc5, 0xe9, 0x06, 0x23, 0x00, 0x21, 0xca, 0x00, 0xdf, 0xf8, + 0x78, 0x56, 0xab, 0x50, 0x49, 0x1c, 0xdf, 0xf8, 0x74, 0x56, 0xab, 0x50, + 0x16, 0x29, 0xf5, 0xd3, 0xa1, 0x00, 0xdf, 0xf8, 0x6c, 0x26, 0x41, 0xf0, + 0x01, 0x01, 0x11, 0x60, 0x16, 0xe0, 0x38, 0xb5, 0x04, 0x46, 0x0d, 0x46, + 0xff, 0xf7, 0xd0, 0xff, 0xdf, 0xf8, 0x58, 0x26, 0x24, 0xb9, 0xdf, 0xf8, + 0x58, 0x36, 0x1c, 0x68, 0x12, 0x78, 0x03, 0xe0, 0xdf, 0xf8, 0x50, 0x36, + 0x1c, 0x68, 0x52, 0x78, 0x24, 0xf0, 0x02, 0x04, 0x44, 0xea, 0x45, 0x01, + 0x11, 0x43, 0x19, 0x60, 0x80, 0xf3, 0x11, 0x88, 0x31, 0xbd, 0x7f, 0xb5, + 0x0a, 0xb1, 0x00, 0xf5, 0x80, 0x70, 0x40, 0xf2, 0xfc, 0x72, 0x02, 0xea, + 0x80, 0x00, 0x40, 0xf0, 0x02, 0x00, 0x00, 0x22, 0x03, 0xeb, 0x82, 0x05, + 0x33, 0xf8, 0x22, 0x60, 0xb5, 0xf9, 0x02, 0x50, 0x46, 0xea, 0x05, 0x45, + 0x4d, 0xf8, 0x22, 0x50, 0x52, 0x1c, 0x04, 0x2a, 0xf2, 0xdb, 0x03, 0x9a, + 0x02, 0x9b, 0x01, 0x9c, 0x00, 0x29, 0x0c, 0xbf, 0xdf, 0xf8, 0x00, 0x16, + 0xdf, 0xf8, 0x00, 0x16, 0x00, 0x9d, 0x4d, 0x60, 0x8c, 0x60, 0xcb, 0x60, + 0x0a, 0x61, 0x08, 0x60, 0x7f, 0xbd, 0x7f, 0xb5, 0x04, 0x46, 0x68, 0x46, + 0x10, 0x21, 0xfd, 0xf7, 0xbf, 0xfd, 0x4f, 0xf4, 0x00, 0x50, 0xad, 0xf8, + 0x00, 0x00, 0x00, 0x25, 0x00, 0x26, 0x86, 0xf0, 0x01, 0x01, 0xc9, 0xb2, + 0xe0, 0xb2, 0xff, 0xf7, 0xac, 0xff, 0x6b, 0x46, 0x32, 0x46, 0x21, 0x46, + 0x28, 0x46, 0xff, 0xf7, 0xc0, 0xff, 0x76, 0x1c, 0x02, 0x2e, 0xf0, 0xd3, + 0x6d, 0x1c, 0xff, 0x2d, 0xec, 0xd9, 0x7f, 0xbd, 0xc0, 0x0b, 0x00, 0x21, + 0x00, 0xfa, 0x01, 0xf2, 0x12, 0x05, 0x03, 0xd4, 0x49, 0x1c, 0xc9, 0xb2, + 0x07, 0x29, 0xf7, 0xdb, 0xc1, 0xf1, 0x07, 0x01, 0xc9, 0xb2, 0x00, 0x29, + 0x14, 0xbf, 0x4a, 0x1e, 0x00, 0x22, 0xd0, 0x40, 0x00, 0xf0, 0x1f, 0x00, + 0x40, 0xea, 0x41, 0x10, 0x70, 0x47, 0x41, 0x09, 0x05, 0xd0, 0x00, 0xf0, + 0x1f, 0x00, 0x40, 0xf0, 0x20, 0x00, 0x4a, 0x1e, 0x90, 0x40, 0x02, 0x29, + 0x04, 0xdb, 0x01, 0x22, 0x89, 0x1e, 0x02, 0xfa, 0x01, 0xf1, 0x08, 0x43, + 0x70, 0x47, 0x10, 0xb5, 0x02, 0x46, 0x0b, 0x46, 0x14, 0x68, 0x18, 0x46, + 0x21, 0x46, 0xfc, 0xf7, 0xb5, 0xfe, 0x38, 0xbf, 0x1c, 0x46, 0x83, 0xf0, + 0x00, 0x43, 0x20, 0x46, 0x19, 0x46, 0xfc, 0xf7, 0xad, 0xfe, 0x38, 0xbf, + 0x1c, 0x46, 0x14, 0x60, 0x10, 0xbd, 0x2d, 0xe9, 0xf7, 0x4f, 0x8e, 0xb0, + 0x9a, 0x46, 0x1a, 0x9c, 0xdf, 0xf8, 0x34, 0xb5, 0x00, 0x26, 0x4f, 0xf0, + 0x8c, 0x48, 0x0d, 0xf1, 0x14, 0x09, 0xf0, 0xb2, 0xff, 0xf7, 0xcd, 0xff, + 0x80, 0x03, 0x01, 0xf0, 0x2d, 0xf8, 0x01, 0x46, 0x0e, 0x9a, 0x00, 0x94, + 0x53, 0x46, 0x05, 0xa8, 0x01, 0xf0, 0x92, 0xfb, 0x00, 0x25, 0x59, 0xf8, + 0x35, 0x00, 0x41, 0x46, 0xfc, 0xf7, 0x9c, 0xfe, 0x49, 0xf8, 0x35, 0x00, + 0x41, 0x46, 0x05, 0xa8, 0x00, 0xeb, 0xc5, 0x07, 0x78, 0x68, 0xfc, 0xf7, + 0x93, 0xfe, 0x78, 0x60, 0x59, 0x46, 0x38, 0x46, 0xff, 0xf7, 0xbf, 0xff, + 0x59, 0x46, 0x38, 0x1d, 0xff, 0xf7, 0xbb, 0xff, 0x59, 0xf8, 0x35, 0x00, + 0xfc, 0xf7, 0xf2, 0xfe, 0x01, 0xa9, 0x21, 0xf8, 0x25, 0x00, 0x78, 0x68, + 0xfc, 0xf7, 0xec, 0xfe, 0x01, 0xa9, 0x01, 0xeb, 0x85, 0x01, 0x6d, 0x1c, + 0x04, 0x2d, 0x48, 0x80, 0xd7, 0xd3, 0x10, 0x9a, 0x0f, 0x99, 0x01, 0xab, + 0x30, 0x46, 0xff, 0xf7, 0x36, 0xff, 0x76, 0x1c, 0xff, 0x2e, 0xc0, 0xd9, + 0x11, 0xb0, 0xbd, 0xe8, 0xf0, 0x8f, 0x10, 0xb5, 0x04, 0x00, 0x0c, 0xbf, + 0xdf, 0xf8, 0xa0, 0x24, 0xdf, 0xf8, 0xa0, 0x24, 0xc8, 0xb2, 0x10, 0x60, + 0x08, 0x1d, 0xdf, 0xf8, 0x9c, 0x14, 0xdf, 0xf8, 0x9c, 0x24, 0x89, 0x6b, + 0x52, 0x69, 0xa1, 0xfb, 0x00, 0x01, 0x00, 0x23, 0xfd, 0xf7, 0xc8, 0xf9, + 0xdf, 0xf8, 0x8c, 0x14, 0x40, 0x1c, 0x41, 0xf8, 0x24, 0x00, 0x10, 0xbd, + 0xf8, 0xb5, 0x00, 0x88, 0x00, 0x0a, 0x0c, 0x46, 0x80, 0xf0, 0x02, 0x00, + 0x59, 0x00, 0xc0, 0x00, 0x01, 0xf0, 0x02, 0x01, 0x00, 0xf0, 0x18, 0x00, + 0x08, 0x43, 0x15, 0x46, 0x40, 0xf0, 0x01, 0x07, 0xff, 0xf7, 0xbe, 0xfe, + 0x06, 0x46, 0x29, 0x46, 0x20, 0x46, 0xff, 0xf7, 0xce, 0xff, 0xdf, 0xf8, + 0x2c, 0x04, 0x1c, 0xb9, 0x00, 0x78, 0xdf, 0xf8, 0x28, 0x14, 0x02, 0xe0, + 0x40, 0x78, 0xdf, 0xf8, 0x24, 0x14, 0x38, 0x43, 0x08, 0x60, 0x86, 0xf3, + 0x11, 0x88, 0xf1, 0xbd, 0xf8, 0xb5, 0x07, 0x00, 0x0c, 0x46, 0x1a, 0xbf, + 0x00, 0x20, 0xdf, 0xf8, 0x30, 0x14, 0xdf, 0xf8, 0x30, 0x14, 0x15, 0x46, + 0x08, 0x60, 0x1e, 0x46, 0xdf, 0xf8, 0x1c, 0x04, 0x50, 0xf8, 0x27, 0x00, + 0xfc, 0xf7, 0x91, 0xfb, 0xc7, 0xb1, 0x00, 0x20, 0xb0, 0x42, 0x2e, 0xda, + 0x41, 0x42, 0xc9, 0x00, 0xdf, 0xf8, 0x10, 0x24, 0x00, 0xf0, 0x31, 0xf8, + 0xdf, 0xf8, 0x0c, 0x24, 0x52, 0x58, 0xd2, 0x08, 0x5a, 0x80, 0xdf, 0xf8, + 0x08, 0x24, 0x52, 0x58, 0xd2, 0x08, 0x25, 0xf8, 0x20, 0x20, 0xdf, 0xf8, + 0x00, 0x24, 0x00, 0xf0, 0x1b, 0xf8, 0xe7, 0xe7, 0x00, 0x20, 0x14, 0xe0, + 0x41, 0x42, 0xc9, 0x00, 0xdf, 0xf8, 0xf0, 0x23, 0x00, 0xf0, 0x19, 0xf8, + 0xdf, 0xf8, 0xec, 0x23, 0x52, 0x58, 0xd2, 0x08, 0x5a, 0x80, 0xdf, 0xf8, + 0xe8, 0x23, 0x52, 0x58, 0xd2, 0x08, 0x25, 0xf8, 0x20, 0x20, 0xdf, 0xf8, + 0xe0, 0x23, 0x00, 0xf0, 0x03, 0xf8, 0xb0, 0x42, 0xe8, 0xdb, 0xf1, 0xbd, + 0x51, 0x58, 0x05, 0xeb, 0x80, 0x02, 0xc9, 0x08, 0x51, 0x80, 0x40, 0x1c, + 0x70, 0x47, 0x52, 0x58, 0xd2, 0x08, 0x24, 0xf8, 0x20, 0x20, 0x04, 0xeb, + 0x80, 0x03, 0x70, 0x47, 0xf8, 0xb5, 0x06, 0x46, 0x0c, 0x46, 0x15, 0x46, + 0x1f, 0x46, 0xff, 0xf7, 0x4f, 0xfe, 0x00, 0x21, 0xca, 0x00, 0x56, 0xf8, + 0x31, 0x30, 0xdf, 0xf8, 0x44, 0xc3, 0x4c, 0xf8, 0x02, 0x30, 0x06, 0xeb, + 0xc1, 0x03, 0xdf, 0xf8, 0x3c, 0xc3, 0x5b, 0x68, 0x4c, 0xf8, 0x02, 0x30, + 0x49, 0x1c, 0x15, 0x29, 0xee, 0xd3, 0xdf, 0xf8, 0x88, 0x13, 0x0c, 0x60, + 0x4d, 0x60, 0x3f, 0x06, 0x06, 0x99, 0x3a, 0x0d, 0x02, 0xf0, 0xf0, 0x02, + 0x42, 0xea, 0x81, 0x01, 0xc6, 0x4a, 0x41, 0xf0, 0x03, 0x01, 0x11, 0x60, + 0x80, 0xf3, 0x11, 0x88, 0xf1, 0xbd, 0x38, 0xb5, 0x04, 0x46, 0x00, 0x21, + 0x00, 0x20, 0xf9, 0xf7, 0x3e, 0xf9, 0x20, 0x69, 0x04, 0xf1, 0xbc, 0x01, + 0x00, 0xf0, 0x21, 0xf8, 0x05, 0x00, 0x07, 0xd1, 0x21, 0x68, 0x20, 0x69, + 0x00, 0xf0, 0x76, 0xf8, 0x20, 0x69, 0x00, 0xf0, 0x58, 0xf8, 0x05, 0x46, + 0x20, 0x69, 0xfc, 0xf7, 0xe9, 0xf9, 0x28, 0x46, 0x32, 0xbd, 0x10, 0xb5, + 0x04, 0x46, 0xf9, 0xf7, 0x15, 0xfc, 0x03, 0x28, 0x06, 0xd1, 0x04, 0xf0, + 0x1b, 0xf9, 0x00, 0x21, 0x04, 0xf1, 0xbc, 0x00, 0xfb, 0xf7, 0x15, 0xf9, + 0xbd, 0xe8, 0x10, 0x40, 0x00, 0x20, 0xf9, 0xf7, 0x75, 0xb9, 0x2d, 0xe9, + 0xf0, 0x41, 0x04, 0x46, 0x88, 0x46, 0xf9, 0xf7, 0x01, 0xfc, 0x00, 0x26, + 0x03, 0x28, 0x25, 0xd1, 0xe0, 0xb2, 0xf9, 0xf7, 0x35, 0xfc, 0x05, 0x46, + 0x40, 0x46, 0xfb, 0xf7, 0xee, 0xf8, 0x00, 0x2d, 0x48, 0xbf, 0x14, 0x26, + 0x20, 0xd4, 0x28, 0x46, 0xfb, 0xf7, 0x0f, 0xf9, 0xfb, 0xf7, 0x41, 0xf9, + 0xfb, 0xf7, 0x2c, 0xf9, 0x01, 0x2d, 0x0c, 0xd1, 0x03, 0x27, 0x02, 0x20, + 0x04, 0xf0, 0x98, 0xf8, 0xb3, 0x48, 0xb0, 0xf8, 0x54, 0x10, 0x20, 0x46, + 0xfa, 0xf7, 0xc3, 0xfb, 0x60, 0xb1, 0x13, 0x26, 0x0a, 0xe0, 0x02, 0x27, + 0x00, 0x2d, 0xf0, 0xd1, 0x01, 0x20, 0xef, 0xe7, 0xf9, 0xf7, 0xd6, 0xfb, + 0x02, 0x28, 0x0c, 0xbf, 0x03, 0x27, 0x02, 0x27, 0xf8, 0xb2, 0xfa, 0xf7, + 0xd9, 0xf9, 0x18, 0xb9, 0xf9, 0xf7, 0x4b, 0xfc, 0x00, 0xb9, 0x0c, 0x26, + 0x30, 0x46, 0xbd, 0xe8, 0xf0, 0x81, 0x38, 0xb5, 0x04, 0x46, 0x01, 0x20, + 0xa0, 0x40, 0xf8, 0xf7, 0xe7, 0xfe, 0x00, 0x25, 0x08, 0xb9, 0x02, 0x25, + 0x0a, 0xe0, 0x04, 0x20, 0xf8, 0xf7, 0xd2, 0xfe, 0x08, 0xb9, 0x01, 0x25, + 0x04, 0xe0, 0xe0, 0xb2, 0xfb, 0xf7, 0x5d, 0xfa, 0x00, 0xb1, 0x11, 0x25, + 0xfa, 0xf7, 0x41, 0xf9, 0x00, 0xb1, 0x00, 0x25, 0x28, 0x46, 0x32, 0xbd, + 0x10, 0xb5, 0x0c, 0x46, 0x21, 0x78, 0x09, 0x04, 0x01, 0xf4, 0xfe, 0x01, + 0x41, 0xea, 0x80, 0x70, 0x40, 0xf0, 0x00, 0x40, 0x40, 0xf4, 0x80, 0x40, + 0xfb, 0xf7, 0x27, 0xfc, 0x60, 0x78, 0xbd, 0xe8, 0x10, 0x40, 0xfb, 0xf7, + 0x45, 0xbc, 0x38, 0xb5, 0x04, 0x46, 0xf7, 0xf7, 0xf1, 0xfc, 0x20, 0x68, + 0xc0, 0x78, 0x80, 0xf0, 0x01, 0x05, 0xa0, 0x68, 0x20, 0x30, 0x2a, 0x46, + 0x01, 0x79, 0x00, 0x91, 0x03, 0x68, 0x21, 0x69, 0x04, 0xf1, 0x14, 0x00, + 0xff, 0xf7, 0x45, 0xfe, 0x20, 0x68, 0x02, 0x78, 0x21, 0x69, 0xa0, 0x68, + 0x2b, 0x46, 0xff, 0xf7, 0xa7, 0xfe, 0x20, 0x68, 0xc5, 0x70, 0xbd, 0xe8, + 0x31, 0x40, 0xf7, 0xf7, 0xea, 0xbc, 0x2d, 0xe9, 0xf8, 0x43, 0x80, 0x46, + 0x4f, 0xf4, 0xd4, 0x70, 0x00, 0xfb, 0x08, 0xf5, 0x7a, 0x4e, 0xdf, 0xf8, + 0xec, 0x91, 0xaf, 0x19, 0xf8, 0x78, 0x80, 0xf0, 0x01, 0x04, 0x09, 0xf1, + 0x20, 0x00, 0x22, 0x46, 0x01, 0x79, 0x03, 0x68, 0x00, 0x91, 0x07, 0xf1, + 0x28, 0x00, 0x41, 0x46, 0xff, 0xf7, 0x1f, 0xfe, 0xaa, 0x5d, 0x23, 0x46, + 0x41, 0x46, 0x48, 0x46, 0xff, 0xf7, 0x82, 0xfe, 0xfc, 0x70, 0xbd, 0xe8, + 0xf1, 0x83, 0x10, 0xb5, 0xcb, 0x07, 0x55, 0x4a, 0x0d, 0xd5, 0x55, 0x4b, + 0x28, 0xb1, 0x04, 0x24, 0x14, 0x70, 0x1c, 0x68, 0x44, 0xf0, 0x04, 0x04, + 0x04, 0xe0, 0x00, 0x24, 0x14, 0x70, 0x1c, 0x68, 0x24, 0xf0, 0x04, 0x04, + 0x1c, 0x60, 0x89, 0x07, 0x0c, 0xd5, 0x4e, 0x49, 0x28, 0xb1, 0x04, 0x20, + 0x50, 0x70, 0x08, 0x68, 0x40, 0xf0, 0x04, 0x00, 0x03, 0xe0, 0x50, 0x70, + 0x08, 0x68, 0x20, 0xf0, 0x04, 0x00, 0x08, 0x60, 0x10, 0xbd, 0xf8, 0xb5, + 0x04, 0x46, 0x0d, 0x46, 0x16, 0x46, 0x1f, 0x46, 0x21, 0x46, 0x30, 0x46, + 0xff, 0xf7, 0x30, 0xfd, 0x20, 0x88, 0x00, 0x90, 0x4f, 0xf4, 0xd4, 0x71, + 0x20, 0x46, 0xfd, 0xf7, 0x4f, 0xfb, 0xbd, 0xf8, 0x00, 0x00, 0x20, 0x80, + 0x4f, 0xf2, 0xff, 0x71, 0x38, 0x88, 0x08, 0x40, 0xa0, 0x80, 0x04, 0xf5, + 0xce, 0x70, 0x39, 0x6a, 0x01, 0x60, 0x97, 0xf8, 0x24, 0x10, 0x01, 0x71, + 0x30, 0x46, 0xff, 0xf7, 0x78, 0xfd, 0x00, 0x20, 0xe0, 0x70, 0x00, 0x21, + 0xf0, 0xb2, 0xff, 0xf7, 0x30, 0xfd, 0x00, 0x20, 0x28, 0x85, 0x68, 0x85, + 0xf1, 0xbd, 0x46, 0x49, 0x4f, 0xf4, 0xd4, 0x72, 0x02, 0xfb, 0x00, 0x10, + 0x90, 0xf8, 0xa1, 0x01, 0x00, 0xb1, 0x01, 0x20, 0x70, 0x47, 0x41, 0x4a, + 0x4f, 0xf4, 0xd4, 0x73, 0x03, 0xfb, 0x00, 0x20, 0x80, 0xf8, 0xa1, 0x11, + 0x70, 0x47, 0x3d, 0x49, 0x4f, 0xf4, 0xd4, 0x72, 0x02, 0xfb, 0x00, 0x11, + 0x01, 0xf1, 0xe0, 0x00, 0x28, 0x31, 0xb8, 0x22, 0xff, 0xf7, 0xe0, 0xbb, + 0x70, 0xb5, 0x04, 0x46, 0x0d, 0x46, 0x36, 0x48, 0x4f, 0xf4, 0xd4, 0x71, + 0x01, 0xfb, 0x04, 0x06, 0x00, 0x20, 0x86, 0xf8, 0xa1, 0x01, 0x28, 0x07, + 0x03, 0xd5, 0x31, 0x46, 0x20, 0x46, 0xff, 0xf7, 0xdf, 0xfc, 0x68, 0x07, + 0x04, 0xd5, 0xb8, 0x21, 0x06, 0xf1, 0x28, 0x00, 0xf8, 0xf7, 0x52, 0xfd, + 0xe8, 0x07, 0x08, 0xd5, 0x2c, 0x48, 0x2b, 0x4b, 0x94, 0x21, 0x01, 0xfb, + 0x04, 0x01, 0x22, 0x46, 0x30, 0x46, 0xff, 0xf7, 0x94, 0xff, 0xa8, 0x07, + 0x0a, 0xd5, 0x06, 0xf1, 0x28, 0x00, 0x06, 0xf1, 0xe0, 0x01, 0xb8, 0x22, + 0xff, 0xf7, 0xb4, 0xfb, 0x20, 0x46, 0xbd, 0xe8, 0x70, 0x40, 0x42, 0xe7, + 0x70, 0xbd, 0x1f, 0x49, 0x4f, 0xf4, 0xd4, 0x72, 0x02, 0xfb, 0x00, 0x10, + 0x80, 0x78, 0x70, 0x47, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x46, + 0x08, 0x00, 0x60, 0x59, 0x0c, 0x00, 0x60, 0x59, 0x00, 0x00, 0x60, 0x59, + 0x98, 0xf3, 0x00, 0x20, 0x00, 0x00, 0x40, 0x59, 0x00, 0x00, 0x50, 0x59, + 0x04, 0x00, 0x40, 0x59, 0x04, 0x00, 0x50, 0x59, 0x00, 0xfc, 0x7f, 0x46, + 0x18, 0x00, 0x40, 0x59, 0x18, 0x00, 0x50, 0x59, 0x00, 0xf2, 0x00, 0x20, + 0x78, 0x29, 0x00, 0x20, 0x38, 0xf3, 0x00, 0x20, 0x1c, 0x00, 0x50, 0x59, + 0x1c, 0x00, 0x40, 0x59, 0x4c, 0x00, 0x50, 0x59, 0x50, 0x00, 0x50, 0x59, + 0x8c, 0x00, 0x50, 0x59, 0x90, 0x00, 0x50, 0x59, 0x4c, 0x00, 0x40, 0x59, + 0x50, 0x00, 0x40, 0x59, 0x8c, 0x00, 0x40, 0x59, 0x90, 0x00, 0x40, 0x59, + 0xb0, 0x00, 0x60, 0x59, 0x4c, 0x1f, 0x00, 0x20, 0x10, 0xb2, 0x00, 0x20, + 0x30, 0x27, 0x00, 0x20, 0x74, 0x27, 0x00, 0x20, 0x2d, 0xe9, 0xf8, 0x43, + 0xdf, 0xf8, 0x88, 0x8a, 0x88, 0x21, 0x40, 0x46, 0xfd, 0xf7, 0x98, 0xfa, + 0x00, 0x25, 0x0f, 0xf6, 0x4d, 0x29, 0xdf, 0xf8, 0x7c, 0x7a, 0xd4, 0x20, + 0x00, 0xfb, 0x05, 0xf4, 0x44, 0x20, 0xe5, 0x53, 0x00, 0xfb, 0x05, 0x86, + 0x6f, 0xf0, 0xc7, 0x00, 0x70, 0x61, 0xf8, 0xf7, 0xa1, 0xfa, 0x70, 0x63, + 0x00, 0x21, 0xdf, 0xf8, 0x60, 0x0a, 0x28, 0x18, 0x4b, 0x46, 0x81, 0x70, + 0x01, 0x71, 0x01, 0x22, 0xe9, 0xb2, 0x02, 0x20, 0xf8, 0xf7, 0x38, 0xfe, + 0xe0, 0x19, 0x00, 0xf0, 0xb7, 0xfc, 0x6d, 0x1c, 0x02, 0x2d, 0xe0, 0xd3, + 0xbd, 0xe8, 0xf1, 0x43, 0xf8, 0xf7, 0xdc, 0xbe, 0x2d, 0xe9, 0xf0, 0x43, + 0xdf, 0xf8, 0x34, 0x0a, 0xdf, 0xf8, 0x24, 0x9a, 0xdf, 0xf8, 0x30, 0x7a, + 0x89, 0xb0, 0x80, 0x7a, 0x00, 0xf0, 0x03, 0x08, 0xff, 0xf7, 0xc2, 0xff, + 0x00, 0x24, 0x00, 0x25, 0x28, 0xfa, 0x05, 0xf0, 0xc0, 0x07, 0x3d, 0xd5, + 0xdf, 0xf8, 0x08, 0x0a, 0x01, 0x95, 0xd4, 0x21, 0x01, 0xfb, 0x05, 0x00, + 0xdf, 0xf8, 0x0c, 0x1a, 0x02, 0x91, 0x03, 0x97, 0x44, 0x21, 0x01, 0xfb, + 0x05, 0x91, 0x04, 0x91, 0x08, 0x90, 0x00, 0xf1, 0xd0, 0x06, 0x05, 0x80, + 0x00, 0x21, 0x31, 0x70, 0x71, 0x70, 0x00, 0xf0, 0x85, 0xfc, 0x01, 0xa8, + 0x00, 0xf0, 0x89, 0xfc, 0x04, 0x00, 0x09, 0xd1, 0x02, 0x98, 0x00, 0x96, + 0xb0, 0xf9, 0x02, 0x20, 0x01, 0x88, 0x03, 0x1d, 0x01, 0x98, 0xfd, 0xf7, + 0xde, 0xf8, 0x04, 0x46, 0x01, 0xa8, 0x00, 0xf0, 0xad, 0xfc, 0x14, 0xb9, + 0x30, 0x78, 0x5a, 0x28, 0x05, 0xda, 0x04, 0x98, 0x3c, 0x30, 0x00, 0x21, + 0xc1, 0x80, 0x81, 0x80, 0x0d, 0xe0, 0x04, 0x98, 0x3c, 0x30, 0x01, 0x21, + 0xc1, 0x80, 0x81, 0x80, 0x08, 0x99, 0x11, 0xf8, 0xd0, 0x2f, 0x42, 0x80, + 0x49, 0x78, 0x01, 0x80, 0x6d, 0x1c, 0x02, 0x2d, 0xba, 0xd3, 0x20, 0x46, + 0x09, 0xb0, 0xbd, 0xe8, 0xf0, 0x83, 0x00, 0x00, 0x2d, 0xe9, 0xf1, 0x4f, + 0xa0, 0xb0, 0xf8, 0xf7, 0x02, 0xfe, 0x02, 0x90, 0x3a, 0x21, 0x20, 0x98, + 0xdf, 0xf8, 0x70, 0x69, 0xdf, 0xf8, 0x7c, 0x49, 0x04, 0x90, 0x44, 0x22, + 0x06, 0xf1, 0x10, 0x00, 0x05, 0x90, 0x4f, 0xf4, 0x84, 0x58, 0x20, 0x98, + 0x01, 0xfb, 0x00, 0xf5, 0x28, 0x19, 0x06, 0x90, 0x20, 0x99, 0xdf, 0xf8, + 0x48, 0x09, 0x02, 0xfb, 0x01, 0x00, 0x07, 0x90, 0xd4, 0x22, 0x20, 0x99, + 0xdf, 0xf8, 0x3c, 0x09, 0x02, 0xfb, 0x01, 0x00, 0x0b, 0x90, 0x0f, 0x90, + 0xf7, 0xf7, 0x20, 0xfb, 0x28, 0x19, 0xdf, 0xf8, 0x38, 0x19, 0x3a, 0x22, + 0xff, 0xf7, 0xa2, 0xfa, 0x07, 0x98, 0x0b, 0x99, 0xc0, 0x8f, 0x81, 0xf8, + 0xd0, 0x00, 0x07, 0x98, 0x0b, 0x99, 0x80, 0x8f, 0x81, 0xf8, 0xd1, 0x00, + 0xf7, 0xf7, 0x23, 0xfb, 0x06, 0x98, 0x20, 0x99, 0x30, 0xf9, 0x11, 0x00, + 0x03, 0x90, 0x07, 0x98, 0x41, 0x6b, 0x81, 0x63, 0xf8, 0xf7, 0xec, 0xf9, + 0x07, 0x9d, 0x68, 0x63, 0x28, 0x6b, 0x40, 0x1c, 0x28, 0x63, 0x20, 0x98, + 0x06, 0xeb, 0x80, 0x00, 0x11, 0x90, 0x03, 0x98, 0xfc, 0xf7, 0x6e, 0xf9, + 0xdf, 0xf8, 0xf4, 0x18, 0xfc, 0xf7, 0x84, 0xf9, 0xdf, 0xf8, 0xf0, 0x18, + 0xfc, 0xf7, 0x80, 0xf9, 0x00, 0xf0, 0xc9, 0xfa, 0x11, 0x99, 0x88, 0x60, + 0x03, 0x98, 0x68, 0x61, 0x02, 0x98, 0x68, 0x62, 0xb5, 0xf8, 0x40, 0x00, + 0x30, 0xb9, 0x0f, 0x98, 0x00, 0xf0, 0xf0, 0xfb, 0x49, 0xf2, 0x80, 0x28, + 0x06, 0x25, 0xab, 0xe2, 0x00, 0x20, 0x0e, 0x90, 0x00, 0x90, 0x0d, 0x90, + 0x0c, 0x90, 0x10, 0x90, 0x04, 0xa8, 0x00, 0xf0, 0xea, 0xfb, 0x05, 0x00, + 0x1d, 0xd1, 0x0b, 0x98, 0x90, 0xf8, 0xd0, 0x10, 0x04, 0x98, 0xff, 0xf7, + 0x7e, 0xfc, 0xef, 0xf3, 0x11, 0x8b, 0x60, 0x20, 0x80, 0xf3, 0x11, 0x88, + 0x20, 0x98, 0xf8, 0xf7, 0x15, 0xfe, 0x20, 0x98, 0x80, 0x19, 0x01, 0x90, + 0x00, 0x20, 0x01, 0x99, 0x08, 0x71, 0x00, 0xf0, 0x9f, 0xfa, 0x00, 0x8c, + 0x48, 0xb9, 0x01, 0x99, 0x88, 0x70, 0x8b, 0xf3, 0x11, 0x88, 0x00, 0x27, + 0x84, 0xe0, 0x04, 0xa8, 0x00, 0xf0, 0xfa, 0xfb, 0x7e, 0xe2, 0x20, 0x98, + 0x00, 0x21, 0xf8, 0xf7, 0xf0, 0xfd, 0x00, 0x28, 0xef, 0xd0, 0x01, 0x20, + 0xed, 0xe7, 0x00, 0x26, 0x12, 0xaa, 0x12, 0xa8, 0x32, 0xf9, 0x26, 0x20, + 0x00, 0xeb, 0x86, 0x0a, 0xd3, 0x17, 0xa2, 0xfb, 0x02, 0x49, 0xba, 0xf9, + 0x02, 0x00, 0x02, 0xfb, 0x03, 0x99, 0x03, 0xfb, 0x02, 0x99, 0xc1, 0x17, + 0xa0, 0xfb, 0x00, 0x23, 0x00, 0xfb, 0x01, 0x33, 0x01, 0xfb, 0x00, 0x33, + 0x49, 0x46, 0xa0, 0x18, 0x59, 0x41, 0xfc, 0xf7, 0xd1, 0xf8, 0x0e, 0x99, + 0xfc, 0xf7, 0x0c, 0xfa, 0x0e, 0x90, 0x19, 0xa8, 0x00, 0xeb, 0x86, 0x0b, + 0x30, 0xf9, 0x26, 0x00, 0xc1, 0x17, 0xa0, 0xfb, 0x00, 0x23, 0xbb, 0xf9, + 0x02, 0x40, 0x00, 0xfb, 0x01, 0x33, 0x01, 0xfb, 0x00, 0x33, 0x4f, 0xea, + 0xe4, 0x79, 0xa4, 0xfb, 0x04, 0x01, 0x04, 0xfb, 0x09, 0x11, 0x09, 0xfb, + 0x04, 0x11, 0x10, 0x18, 0x59, 0x41, 0xfc, 0xf7, 0xb3, 0xf8, 0x00, 0x99, + 0xfc, 0xf7, 0xee, 0xf9, 0x00, 0x90, 0x19, 0xa8, 0xbb, 0xf9, 0x02, 0x40, + 0x30, 0xf9, 0x26, 0xb0, 0xba, 0xf9, 0x02, 0x20, 0x12, 0xa8, 0x4f, 0xea, + 0xe4, 0x79, 0x30, 0xf9, 0x26, 0xc0, 0xa2, 0xfb, 0x04, 0x01, 0xd3, 0x17, + 0x02, 0xfb, 0x09, 0x11, 0x03, 0xfb, 0x04, 0x11, 0xcc, 0xfb, 0x0b, 0x01, + 0xfc, 0xf7, 0x98, 0xf8, 0x0d, 0x99, 0xfc, 0xf7, 0xd3, 0xf9, 0x0d, 0x90, + 0x22, 0x46, 0x12, 0xa8, 0x4b, 0x46, 0x30, 0xf9, 0x26, 0x00, 0xa0, 0xfb, + 0x02, 0x49, 0xc1, 0x17, 0x00, 0xfb, 0x03, 0x99, 0x19, 0xa8, 0x01, 0xfb, + 0x02, 0x99, 0x30, 0xf9, 0x26, 0x00, 0xba, 0xf9, 0x02, 0x10, 0x81, 0xfb, + 0x00, 0x01, 0x20, 0x1a, 0x69, 0xeb, 0x01, 0x01, 0xfc, 0xf7, 0x7c, 0xf8, + 0x0c, 0x99, 0xfc, 0xf7, 0xb7, 0xf9, 0x76, 0x1c, 0x07, 0x2e, 0x0c, 0x90, + 0x88, 0xd3, 0x7f, 0x1c, 0x00, 0xf0, 0x10, 0xfa, 0x00, 0x8b, 0x87, 0x42, + 0x19, 0xd2, 0x0f, 0x98, 0x00, 0x88, 0x07, 0x23, 0x12, 0xaa, 0x19, 0xa9, + 0xff, 0xf7, 0x16, 0xfc, 0xf9, 0xf7, 0x57, 0xfe, 0x00, 0x28, 0x3f, 0xf4, + 0x76, 0xaf, 0x07, 0x99, 0x04, 0x20, 0x08, 0x60, 0x7f, 0x1e, 0x04, 0xa8, + 0x00, 0xf0, 0x60, 0xfb, 0x04, 0xa8, 0x00, 0xf0, 0x2a, 0xfb, 0x05, 0x00, + 0xe1, 0xd0, 0x01, 0x20, 0x10, 0x90, 0x04, 0xa8, 0x00, 0xf0, 0x56, 0xfb, + 0x10, 0x98, 0x00, 0x28, 0x02, 0xbf, 0x01, 0x98, 0x00, 0x79, 0x00, 0x28, + 0x05, 0xd1, 0x01, 0x98, 0x80, 0x78, 0x18, 0xb1, 0x0f, 0x25, 0x49, 0xf2, + 0x80, 0x28, 0xcd, 0xe1, 0x06, 0x98, 0x20, 0x99, 0xdf, 0xf8, 0x04, 0xb7, + 0x00, 0xeb, 0x41, 0x07, 0x38, 0x8b, 0xc0, 0xeb, 0xc0, 0x00, 0xfc, 0xf7, + 0x6b, 0xf8, 0x04, 0x46, 0x00, 0x98, 0x21, 0x46, 0xfc, 0xf7, 0x80, 0xf8, + 0xfc, 0xf7, 0xb2, 0xf9, 0x00, 0xf0, 0xc3, 0xf9, 0x06, 0x46, 0x0e, 0x98, + 0x21, 0x46, 0xfc, 0xf7, 0x77, 0xf8, 0xfc, 0xf7, 0xa9, 0xf9, 0x00, 0xf0, + 0xba, 0xf9, 0x81, 0x46, 0x07, 0x9c, 0x01, 0x21, 0x30, 0x46, 0x03, 0xf0, + 0x05, 0xfb, 0x00, 0xf0, 0xe3, 0xfa, 0x00, 0xf0, 0xb8, 0xf9, 0xfc, 0xf7, + 0x61, 0xfa, 0xa0, 0x62, 0x01, 0x21, 0x48, 0x46, 0x03, 0xf0, 0xfa, 0xfa, + 0x00, 0xf0, 0xd8, 0xfa, 0x00, 0xf0, 0xad, 0xf9, 0xfc, 0xf7, 0x56, 0xfa, + 0xe0, 0x62, 0x01, 0x98, 0x80, 0x78, 0x10, 0xb1, 0x49, 0xf2, 0x80, 0x28, + 0x29, 0xe0, 0xf8, 0x8e, 0xfc, 0xf7, 0x42, 0xf8, 0x4f, 0xf0, 0x5e, 0x5a, + 0x00, 0xf0, 0xc3, 0xfa, 0x01, 0x46, 0x30, 0x46, 0xfc, 0xf7, 0xc6, 0xf9, + 0x04, 0xd2, 0x02, 0x98, 0x60, 0x62, 0x49, 0xf2, 0xb2, 0x28, 0x12, 0x25, + 0xb8, 0x8b, 0xfc, 0xf7, 0x31, 0xf8, 0x00, 0xf0, 0xb4, 0xfa, 0x01, 0x46, + 0x48, 0x46, 0xfc, 0xf7, 0xb7, 0xf9, 0x10, 0xd2, 0x02, 0x98, 0x60, 0x62, + 0x49, 0xf2, 0xb2, 0x28, 0x13, 0x25, 0x66, 0x6a, 0x48, 0xf4, 0x02, 0x40, + 0x40, 0xf0, 0xe4, 0x08, 0x01, 0x98, 0x80, 0x78, 0x00, 0x28, 0x00, 0xf0, + 0x27, 0x81, 0x0f, 0x25, 0x66, 0xe1, 0x00, 0x2d, 0xf1, 0xd1, 0x01, 0x98, + 0x04, 0x78, 0xb8, 0x8a, 0xfc, 0xf7, 0x12, 0xf8, 0xdf, 0xf8, 0x30, 0x16, + 0xfc, 0xf7, 0x1e, 0xf8, 0x31, 0x46, 0xfc, 0xf7, 0x97, 0xf9, 0x4f, 0xf0, + 0x00, 0x0a, 0x38, 0xbf, 0x00, 0x20, 0x0b, 0xd3, 0x38, 0x8a, 0xfc, 0xf7, + 0x03, 0xf8, 0xdf, 0xf8, 0x14, 0x16, 0xfc, 0xf7, 0x0f, 0xf8, 0x31, 0x46, + 0xfc, 0xf7, 0x88, 0xf9, 0x16, 0xd2, 0x01, 0x20, 0x04, 0x2c, 0x13, 0xd8, + 0xdf, 0xe8, 0x04, 0xf0, 0x03, 0x0c, 0x05, 0x03, 0x03, 0x00, 0x20, 0xb9, + 0x07, 0xe0, 0x10, 0xb9, 0x4f, 0xf0, 0x04, 0x0a, 0x08, 0xe0, 0x4f, 0xf0, + 0x02, 0x0a, 0x05, 0xe0, 0x10, 0xb9, 0x4f, 0xf0, 0x01, 0x0a, 0x01, 0xe0, + 0x4f, 0xf0, 0x03, 0x0a, 0x01, 0x98, 0x80, 0xf8, 0x00, 0xa0, 0xf7, 0xf7, + 0x5f, 0xf9, 0x01, 0x98, 0x04, 0x78, 0x54, 0xb9, 0x07, 0x9c, 0x00, 0x20, + 0xa0, 0x61, 0xe0, 0x61, 0x20, 0x62, 0x48, 0xf4, 0x02, 0x48, 0xf7, 0xf7, + 0x68, 0xf9, 0x0b, 0x25, 0x1e, 0xe1, 0x48, 0x46, 0x31, 0x46, 0xfb, 0xf7, + 0xdd, 0xff, 0x81, 0x46, 0x0d, 0x98, 0x00, 0x99, 0xfb, 0xf7, 0xd8, 0xff, + 0x4f, 0xf0, 0x8c, 0x47, 0x39, 0x46, 0xfc, 0xf7, 0x61, 0xf9, 0x00, 0xf0, + 0x18, 0xf9, 0x82, 0x46, 0x0c, 0x98, 0x00, 0x99, 0xfb, 0xf7, 0xcc, 0xff, + 0x39, 0x46, 0xfc, 0xf7, 0x57, 0xf9, 0x00, 0xf0, 0x0e, 0xf9, 0x07, 0x46, + 0x50, 0x46, 0x00, 0xf0, 0x38, 0xfa, 0x00, 0x90, 0x39, 0x46, 0x38, 0x46, + 0xfc, 0xf7, 0x4c, 0xf9, 0x00, 0x99, 0xfc, 0xf7, 0xad, 0xf8, 0xfc, 0xf7, + 0xed, 0xf8, 0x01, 0x2c, 0x1c, 0xbf, 0x03, 0x2c, 0x81, 0x46, 0x07, 0x9c, + 0x01, 0x21, 0x48, 0x46, 0x03, 0xf0, 0x48, 0xfa, 0x00, 0xf0, 0x26, 0xfa, + 0x00, 0xf0, 0xfb, 0xf8, 0xfc, 0xf7, 0xa4, 0xf9, 0xa0, 0x61, 0x51, 0x46, + 0xdf, 0xf8, 0x34, 0x05, 0xfc, 0xf7, 0x32, 0xf9, 0xfc, 0xf7, 0x9c, 0xf9, + 0xe0, 0x61, 0x39, 0x46, 0xdf, 0xf8, 0x24, 0x05, 0xfc, 0xf7, 0x2a, 0xf9, + 0xfc, 0xf7, 0x94, 0xf9, 0x20, 0x62, 0xf7, 0xf7, 0x1c, 0xf9, 0x00, 0xf0, + 0xe7, 0xf8, 0x81, 0x8c, 0x61, 0xb1, 0x07, 0x99, 0x03, 0x9a, 0x89, 0x69, + 0x00, 0x8d, 0x89, 0x1a, 0x48, 0xbf, 0x49, 0x42, 0x88, 0x42, 0x03, 0xda, + 0x48, 0xf4, 0x02, 0x48, 0x10, 0x25, 0xc3, 0xe0, 0x02, 0xa8, 0x00, 0x88, + 0xfb, 0xf7, 0x72, 0xff, 0x04, 0x46, 0xdf, 0xf8, 0xf4, 0x04, 0x21, 0x46, + 0xfc, 0xf7, 0x0a, 0xf9, 0xdf, 0xf8, 0xec, 0x14, 0xfb, 0xf7, 0x78, 0xff, + 0x00, 0xf0, 0xc1, 0xf8, 0x01, 0x46, 0x0f, 0x98, 0x33, 0x46, 0x4a, 0x46, + 0x00, 0xf0, 0xc7, 0xf8, 0x07, 0x46, 0xfc, 0xf7, 0x67, 0xf9, 0x10, 0xf1, + 0x01, 0x0f, 0x18, 0xbf, 0x10, 0xf1, 0x02, 0x0f, 0x49, 0xf2, 0xcb, 0x21, + 0x05, 0xd0, 0x10, 0xf1, 0x03, 0x0f, 0x18, 0xbf, 0x10, 0xf1, 0x04, 0x0f, + 0x05, 0xd1, 0x07, 0x9a, 0x02, 0x98, 0x50, 0x62, 0x88, 0x46, 0x07, 0x25, + 0x96, 0xe0, 0x06, 0x98, 0x20, 0x9a, 0x00, 0xeb, 0x42, 0x06, 0xb0, 0x88, + 0x28, 0xb9, 0x07, 0x9a, 0x02, 0x98, 0x50, 0x62, 0x88, 0x46, 0x09, 0x25, + 0x8a, 0xe0, 0xb0, 0x89, 0xfb, 0xf7, 0x3a, 0xff, 0xdf, 0xf8, 0x8c, 0x14, + 0xfc, 0xf7, 0xd4, 0xf8, 0x11, 0x99, 0x89, 0x68, 0x81, 0x46, 0x38, 0x46, + 0xfb, 0xf7, 0x40, 0xff, 0x01, 0x21, 0x03, 0xf0, 0xd5, 0xf9, 0x00, 0xf0, + 0xb3, 0xf9, 0x00, 0x90, 0x00, 0xf0, 0xb3, 0xf9, 0x00, 0xf0, 0xae, 0xf9, + 0x21, 0x46, 0xfc, 0xf7, 0x25, 0xf8, 0x82, 0x46, 0x11, 0xe0, 0x4f, 0xf0, + 0x7c, 0x50, 0x00, 0xf0, 0xa8, 0xf9, 0x81, 0x46, 0x00, 0x98, 0x00, 0xf0, + 0xa4, 0xf9, 0x00, 0xf0, 0x9f, 0xf9, 0x21, 0x46, 0xfc, 0xf7, 0x16, 0xf8, + 0x07, 0x99, 0x82, 0x46, 0x08, 0x20, 0x08, 0x60, 0x50, 0x46, 0xfc, 0xf7, + 0x17, 0xf9, 0x07, 0xb2, 0xb7, 0xf5, 0x52, 0x7f, 0xe7, 0xd2, 0x30, 0x89, + 0xfb, 0xf7, 0x06, 0xff, 0x00, 0xf0, 0x8c, 0xf9, 0x06, 0x46, 0x38, 0x46, + 0xfb, 0xf7, 0xf6, 0xfe, 0x01, 0x46, 0x30, 0x46, 0xfc, 0xf7, 0xa2, 0xf9, + 0x9c, 0xbf, 0xb2, 0x46, 0x0a, 0x25, 0x50, 0x46, 0xfc, 0xf7, 0x00, 0xf9, + 0x06, 0x46, 0xcf, 0xe6, 0x06, 0x98, 0x20, 0x99, 0x00, 0xeb, 0x41, 0x02, + 0xd1, 0x8d, 0x53, 0x8e, 0x5a, 0x18, 0xcb, 0x1a, 0xb6, 0xb2, 0xb2, 0x42, + 0xb4, 0xbf, 0x4f, 0xf0, 0x01, 0x0c, 0x4f, 0xf0, 0x00, 0x0c, 0x9e, 0x42, + 0xb4, 0xbf, 0x4f, 0xf0, 0x01, 0x0b, 0x4f, 0xf0, 0x00, 0x0b, 0x5b, 0xea, + 0x0c, 0x04, 0x13, 0xd0, 0x20, 0x9d, 0x28, 0x18, 0x90, 0xf8, 0x2c, 0x00, + 0x10, 0xb1, 0x02, 0x28, 0x02, 0xd0, 0x07, 0xe0, 0x0e, 0x46, 0x07, 0xe0, + 0xbc, 0xf1, 0x00, 0x0f, 0x0c, 0xbf, 0x1e, 0x46, 0x16, 0x46, 0x01, 0xe0, + 0x07, 0x98, 0x46, 0x6a, 0x11, 0x25, 0x01, 0xe0, 0x49, 0xf6, 0xe4, 0x28, + 0x20, 0x98, 0x0f, 0xf2, 0xc4, 0x34, 0x4f, 0xea, 0x40, 0x0b, 0x30, 0x04, + 0x01, 0x0e, 0x34, 0xf8, 0x1b, 0x00, 0xf8, 0xf7, 0x9b, 0xf9, 0x04, 0xeb, + 0x4b, 0x00, 0xf1, 0xb2, 0x40, 0x88, 0xf8, 0xf7, 0x95, 0xf9, 0x07, 0x98, + 0xb6, 0xb2, 0x46, 0x62, 0x42, 0x46, 0x07, 0x98, 0x29, 0x46, 0x03, 0xf0, + 0x15, 0xf9, 0x28, 0x46, 0x21, 0xb0, 0xbd, 0xe8, 0xf0, 0x8f, 0x4f, 0xf0, + 0x64, 0x51, 0xfc, 0xf7, 0x43, 0xb8, 0x01, 0x46, 0xd9, 0x48, 0xfc, 0xf7, + 0xb6, 0xba, 0xd2, 0x49, 0xfc, 0xf7, 0x3c, 0xb8, 0x06, 0x98, 0x20, 0x99, + 0x00, 0xeb, 0x41, 0x00, 0x70, 0x47, 0x2d, 0xe9, 0xf6, 0x4f, 0x04, 0x46, + 0x1d, 0x46, 0x87, 0xb0, 0x28, 0x46, 0x00, 0x21, 0xfc, 0xf7, 0x1c, 0xf8, + 0x04, 0xd2, 0x20, 0x46, 0x00, 0xf0, 0x1a, 0xf9, 0xce, 0x48, 0x07, 0xe1, + 0x60, 0x88, 0x10, 0x28, 0x1d, 0xda, 0x0c, 0x22, 0x07, 0x99, 0x02, 0xfb, + 0x00, 0x40, 0x01, 0x61, 0x60, 0x88, 0x08, 0x99, 0x02, 0xfb, 0x00, 0x40, + 0x41, 0x61, 0x29, 0x46, 0x60, 0x88, 0x02, 0xfb, 0x00, 0x40, 0x85, 0x61, + 0xa0, 0x68, 0xfc, 0xf7, 0x01, 0xf8, 0x38, 0xbf, 0xa5, 0x60, 0x03, 0xd3, + 0x00, 0xf0, 0xf1, 0xf8, 0x38, 0xbf, 0xe5, 0x60, 0x60, 0x88, 0x40, 0x1c, + 0x60, 0x80, 0x08, 0x98, 0xe6, 0xe0, 0x8b, 0x46, 0x00, 0x26, 0x8a, 0x46, + 0x88, 0x46, 0x89, 0x46, 0x02, 0x91, 0x06, 0x91, 0x05, 0x91, 0xad, 0xf8, + 0x10, 0x10, 0x00, 0x27, 0x0c, 0x20, 0x00, 0xfb, 0x07, 0x40, 0x03, 0x90, + 0x59, 0x46, 0x00, 0x69, 0x01, 0x90, 0x7f, 0x1c, 0xfb, 0xf7, 0x56, 0xff, + 0x83, 0x46, 0x03, 0x98, 0x40, 0x69, 0x00, 0x90, 0x31, 0x46, 0xfb, 0xf7, + 0x4f, 0xff, 0x06, 0x46, 0x01, 0x98, 0x00, 0x99, 0xfb, 0xf7, 0xe6, 0xff, + 0x49, 0x46, 0xfb, 0xf7, 0x47, 0xff, 0x81, 0x46, 0x01, 0x98, 0x01, 0x46, + 0xfb, 0xf7, 0xde, 0xff, 0x51, 0x46, 0xfb, 0xf7, 0x3f, 0xff, 0x82, 0x46, + 0x00, 0x98, 0x01, 0x46, 0xfb, 0xf7, 0xd6, 0xff, 0x41, 0x46, 0xfb, 0xf7, + 0x37, 0xff, 0x10, 0x2f, 0x80, 0x46, 0xd3, 0xd3, 0x4f, 0xf0, 0x83, 0x40, + 0x00, 0xf0, 0xb3, 0xf8, 0x07, 0x46, 0x58, 0x46, 0x00, 0xf0, 0xb2, 0xf8, + 0x01, 0x46, 0x38, 0x46, 0xfb, 0xf7, 0xb4, 0xfe, 0x07, 0x46, 0x4f, 0xf0, + 0x83, 0x40, 0x41, 0x46, 0xfb, 0xf7, 0xbe, 0xff, 0x80, 0x46, 0x30, 0x46, + 0x31, 0x46, 0xfb, 0xf7, 0xb9, 0xff, 0x01, 0x46, 0x40, 0x46, 0xfb, 0xf7, + 0xa5, 0xfe, 0x80, 0x46, 0x4f, 0xf0, 0x83, 0x40, 0x00, 0xf0, 0x9d, 0xf8, + 0x81, 0x46, 0x58, 0x46, 0x31, 0x46, 0xfb, 0xf7, 0xab, 0xff, 0x01, 0x46, + 0x48, 0x46, 0xfb, 0xf7, 0x97, 0xfe, 0x81, 0x46, 0x8d, 0x49, 0x38, 0x46, + 0xfc, 0xf7, 0xaa, 0xf8, 0x21, 0xd8, 0x40, 0x46, 0xfc, 0xf7, 0xa6, 0xf8, + 0x1d, 0xd8, 0x01, 0x20, 0xad, 0xf8, 0x10, 0x00, 0x41, 0x46, 0x38, 0x46, + 0xfb, 0xf7, 0x96, 0xff, 0xfb, 0xf7, 0x3a, 0xff, 0x01, 0x46, 0x48, 0x46, + 0xfb, 0xf7, 0x02, 0xfe, 0x05, 0x90, 0x39, 0x46, 0x48, 0x46, 0xfb, 0xf7, + 0xfd, 0xfd, 0x02, 0x90, 0x00, 0xf0, 0x72, 0xf8, 0x01, 0x46, 0x30, 0x46, + 0xfb, 0xf7, 0x74, 0xfe, 0x4f, 0xf0, 0x76, 0x51, 0xfb, 0xf7, 0x80, 0xff, + 0x06, 0x90, 0x29, 0x46, 0xe0, 0x68, 0xfb, 0xf7, 0x69, 0xff, 0x03, 0xd2, + 0xa1, 0x68, 0x00, 0xf0, 0x5b, 0xf8, 0x26, 0xd3, 0xbd, 0xf8, 0x10, 0x00, + 0x20, 0xb1, 0x05, 0x98, 0x74, 0x49, 0xfb, 0xf7, 0x5d, 0xff, 0x01, 0xd2, + 0x73, 0x4a, 0x1d, 0xe0, 0x02, 0x99, 0x07, 0x98, 0xfb, 0xf7, 0x68, 0xff, + 0x06, 0x99, 0xfb, 0xf7, 0xc9, 0xfe, 0x08, 0x99, 0x06, 0x46, 0xfb, 0xf7, + 0x51, 0xfe, 0x00, 0x21, 0xfb, 0xf7, 0x4c, 0xff, 0x03, 0xd2, 0x08, 0x98, + 0x31, 0x46, 0xfb, 0xf7, 0x49, 0xfe, 0x08, 0x99, 0xfb, 0xf7, 0xc8, 0xfd, + 0x68, 0x49, 0xfc, 0xf7, 0x5b, 0xf8, 0x98, 0xbf, 0x4f, 0xf0, 0x40, 0x42, + 0x00, 0xd9, 0x08, 0x9a, 0xa0, 0x88, 0x0c, 0x21, 0x01, 0xfb, 0x00, 0x40, + 0x07, 0x99, 0x01, 0x61, 0x0c, 0x21, 0xa0, 0x88, 0x01, 0xfb, 0x00, 0x40, + 0x08, 0x99, 0x41, 0x61, 0x0c, 0x21, 0xa0, 0x88, 0x01, 0xfb, 0x00, 0x40, + 0x00, 0x23, 0x85, 0x61, 0xa0, 0x88, 0x40, 0x1c, 0xc1, 0x10, 0x00, 0xeb, + 0x11, 0x71, 0x09, 0x11, 0xa0, 0xeb, 0x01, 0x10, 0xa0, 0x80, 0x0c, 0x20, + 0x00, 0xfb, 0x03, 0x40, 0x85, 0x69, 0xa0, 0x68, 0x29, 0x46, 0xfb, 0xf7, + 0x19, 0xff, 0x38, 0xbf, 0xa5, 0x60, 0x03, 0xd3, 0x00, 0xf0, 0x09, 0xf8, + 0x38, 0xbf, 0xe5, 0x60, 0x5b, 0x1c, 0x10, 0x2b, 0xed, 0xd3, 0x10, 0x46, + 0x09, 0xb0, 0xbd, 0xe8, 0xf0, 0x8f, 0xe1, 0x68, 0x28, 0x46, 0xfb, 0xf7, + 0x07, 0xbf, 0x51, 0x46, 0xfb, 0xf7, 0x16, 0xbf, 0x59, 0x46, 0xfb, 0xf7, + 0x13, 0xbf, 0x49, 0x46, 0xfb, 0xf7, 0x10, 0xbf, 0x00, 0x21, 0x41, 0x80, + 0x81, 0x80, 0x81, 0x60, 0x44, 0x49, 0xc1, 0x60, 0x70, 0x47, 0x38, 0xb5, + 0x04, 0x46, 0x00, 0x21, 0x00, 0x20, 0xf8, 0xf7, 0x9a, 0xfa, 0x20, 0x68, + 0x04, 0xf1, 0x10, 0x01, 0xff, 0xf7, 0x7d, 0xf9, 0x05, 0x00, 0x09, 0xd1, + 0xe0, 0x69, 0x00, 0xf1, 0xd0, 0x01, 0x20, 0x68, 0xff, 0xf7, 0xd0, 0xf9, + 0x20, 0x68, 0xff, 0xf7, 0xb2, 0xf9, 0x05, 0x46, 0x01, 0x2d, 0x0b, 0xd0, + 0x02, 0x2d, 0x0b, 0xd0, 0x0c, 0x2d, 0x0b, 0xd0, 0x11, 0x2d, 0x0b, 0xd0, + 0x13, 0x2d, 0x0b, 0xd0, 0x14, 0x2d, 0x08, 0xbf, 0x0d, 0x25, 0x08, 0xe0, + 0x02, 0x25, 0x06, 0xe0, 0x01, 0x25, 0x04, 0xe0, 0x0e, 0x25, 0x02, 0xe0, + 0x03, 0x25, 0x00, 0xe0, 0x0c, 0x25, 0x20, 0x68, 0xfb, 0xf7, 0x2c, 0xfb, + 0x28, 0x46, 0x32, 0xbd, 0x10, 0xb5, 0x04, 0x46, 0xf8, 0xf7, 0x58, 0xfd, + 0x03, 0x28, 0x06, 0xd1, 0x03, 0xf0, 0x5e, 0xfa, 0x00, 0x21, 0x04, 0xf1, + 0x10, 0x00, 0xfa, 0xf7, 0x58, 0xfa, 0xbd, 0xe8, 0x10, 0x40, 0x00, 0x20, + 0xf8, 0xf7, 0xb8, 0xba, 0x11, 0x4a, 0x22, 0xf8, 0x10, 0x10, 0x70, 0x47, + 0x10, 0xb5, 0x04, 0x46, 0x0e, 0x49, 0x01, 0xeb, 0x44, 0x01, 0x09, 0x8c, + 0x29, 0xb1, 0x01, 0x21, 0xf8, 0xf7, 0xdb, 0xf9, 0x10, 0xb1, 0x01, 0x20, + 0x00, 0xe0, 0x00, 0x20, 0x06, 0x49, 0x61, 0x18, 0x88, 0x70, 0x8a, 0x78, + 0x50, 0x1e, 0x80, 0x41, 0xc0, 0x0f, 0x08, 0x71, 0x10, 0xbd, 0x00, 0x00, + 0xa8, 0xef, 0x00, 0x20, 0xcc, 0xe6, 0x00, 0x20, 0xb0, 0x26, 0x00, 0x20, + 0x78, 0x29, 0x00, 0x20, 0xd8, 0x26, 0x00, 0x20, 0xc0, 0x26, 0x00, 0x20, + 0xd4, 0xac, 0x00, 0x20, 0x00, 0x00, 0xc8, 0x42, 0x00, 0x00, 0xa0, 0x41, + 0x00, 0x00, 0x7a, 0x44, 0xcd, 0xcc, 0x4c, 0x3d, 0x00, 0x00, 0xa0, 0xc1, + 0x0a, 0xd7, 0x23, 0x3c, 0x00, 0x00, 0x20, 0x41, 0x00, 0x00, 0x80, 0xc0, + 0x70, 0x12, 0x83, 0x3a, 0xcd, 0xcc, 0xcc, 0x3d, 0x00, 0x00, 0x40, 0xc0, + 0xce, 0xcc, 0x4c, 0x3d, 0xec, 0x78, 0xad, 0x60, 0x61, 0x09, 0x60, 0x09, + 0x63, 0x09, 0x62, 0x09, 0x01, 0x22, 0x41, 0x1c, 0x03, 0xe0, 0x0a, 0x46, + 0xb0, 0xfb, 0xf2, 0xf1, 0x89, 0x18, 0x49, 0x08, 0x8a, 0x1a, 0x48, 0xbf, + 0x52, 0x42, 0x02, 0x2a, 0xf5, 0xda, 0x01, 0xfb, 0x01, 0xf2, 0x90, 0x42, + 0x38, 0xbf, 0x49, 0x1e, 0xf9, 0xd3, 0x08, 0x46, 0x70, 0x47, 0x30, 0xb5, + 0x4f, 0xf4, 0x80, 0x53, 0x03, 0x60, 0x41, 0x60, 0x02, 0x23, 0x00, 0xeb, + 0x83, 0x05, 0x01, 0xfb, 0x02, 0xf4, 0x55, 0xf8, 0x04, 0x5c, 0x6c, 0x43, + 0x64, 0x0b, 0x40, 0xf8, 0x23, 0x40, 0x5b, 0x1c, 0x08, 0x2b, 0xf2, 0xdb, + 0x30, 0xbd, 0x2d, 0xe9, 0xf0, 0x41, 0x06, 0x9e, 0x00, 0x24, 0x00, 0x25, + 0x26, 0xfa, 0x05, 0xfe, 0x5f, 0xea, 0xce, 0x7e, 0x4f, 0xea, 0xd5, 0x0c, + 0x05, 0xf0, 0x07, 0x07, 0x49, 0xd5, 0xbc, 0xf1, 0x03, 0x0f, 0x01, 0xeb, + 0x87, 0x07, 0x11, 0xd0, 0xbc, 0xf1, 0x01, 0x0f, 0x05, 0xd1, 0x3f, 0x6a, + 0xb2, 0xf9, 0x00, 0xc0, 0xb2, 0xf9, 0x02, 0xe0, 0x1f, 0xe0, 0x3f, 0x68, + 0xbc, 0xf1, 0x02, 0x0f, 0xf6, 0xd1, 0xb2, 0xf9, 0x04, 0xc0, 0xb2, 0xf9, + 0x06, 0xe0, 0x16, 0xe0, 0x93, 0xb1, 0x5f, 0xea, 0x83, 0x7c, 0x4c, 0xbf, + 0x3f, 0x6c, 0x3f, 0x6a, 0x5f, 0xea, 0xc3, 0x7c, 0xe8, 0xd5, 0xb2, 0xf8, + 0x00, 0xc0, 0xb2, 0xf8, 0x04, 0xe0, 0xb2, 0xf8, 0x06, 0x80, 0xf4, 0x44, + 0xb2, 0xf8, 0x02, 0xe0, 0xc6, 0x44, 0x02, 0xe0, 0x00, 0x27, 0xbe, 0x46, + 0xbc, 0x46, 0x0f, 0xfa, 0x8c, 0xfc, 0x07, 0xfb, 0x0c, 0xfc, 0x4f, 0xea, + 0x6c, 0x28, 0x0c, 0xeb, 0x98, 0x5c, 0x4f, 0xea, 0xac, 0x2c, 0x40, 0xf8, + 0x34, 0xc0, 0x0f, 0xfa, 0x8e, 0xfe, 0x07, 0xfb, 0x0e, 0xf7, 0x4f, 0xea, + 0x67, 0x2c, 0x07, 0xeb, 0x9c, 0x57, 0x00, 0xeb, 0xc4, 0x0c, 0x64, 0x1c, + 0xbf, 0x12, 0x15, 0x2c, 0xcc, 0xf8, 0x04, 0x70, 0x02, 0xd2, 0x6d, 0x1c, + 0x20, 0x2d, 0xa9, 0xd3, 0xbd, 0xe8, 0xf0, 0x81, 0x2d, 0xe9, 0xf0, 0x43, + 0x00, 0x24, 0x61, 0xe0, 0x00, 0x26, 0x00, 0xeb, 0x44, 0x05, 0xa8, 0x27, + 0x07, 0xfb, 0x04, 0x27, 0x07, 0xeb, 0xc6, 0x07, 0x57, 0xf8, 0xa8, 0xef, + 0x95, 0xf9, 0x01, 0x80, 0xd7, 0xf8, 0x04, 0x90, 0x10, 0xf9, 0x14, 0xc0, + 0x09, 0xfb, 0x08, 0xf8, 0x0e, 0xfb, 0x0c, 0x8c, 0x52, 0xf8, 0x36, 0xe0, + 0x4f, 0xea, 0x6c, 0x18, 0x0c, 0xeb, 0x98, 0x6c, 0x0e, 0xeb, 0xac, 0x1c, + 0x42, 0xf8, 0x36, 0xc0, 0xd7, 0xf8, 0x04, 0xe0, 0x10, 0xf9, 0x14, 0xc0, + 0x3f, 0x68, 0x0e, 0xfb, 0x0c, 0xfc, 0x95, 0xf9, 0x01, 0xe0, 0x07, 0xfb, + 0x1e, 0xc7, 0x02, 0xeb, 0xc6, 0x0c, 0x4f, 0xea, 0x67, 0x18, 0xdc, 0xf8, + 0x04, 0xe0, 0x07, 0xeb, 0x98, 0x67, 0x76, 0x1c, 0x0e, 0xeb, 0xa7, 0x17, + 0x15, 0x2e, 0xcc, 0xf8, 0x04, 0x70, 0xca, 0xd3, 0x03, 0xeb, 0xc4, 0x06, + 0x95, 0xf9, 0x01, 0xe0, 0xd6, 0xf8, 0x0c, 0x80, 0x10, 0xf9, 0x14, 0x70, + 0xd6, 0xf8, 0x08, 0xc0, 0x08, 0xfb, 0x0e, 0xfe, 0x0c, 0xfb, 0x07, 0xe7, + 0xd3, 0xf8, 0x00, 0xc0, 0x4f, 0xea, 0x67, 0x1e, 0x07, 0xeb, 0x9e, 0x67, + 0x0c, 0xeb, 0xa7, 0x17, 0x1f, 0x60, 0xd6, 0xf8, 0x0c, 0xc0, 0x10, 0xf9, + 0x14, 0x70, 0x95, 0xf9, 0x01, 0x50, 0xb6, 0x68, 0x0c, 0xfb, 0x07, 0xf7, + 0x06, 0xfb, 0x15, 0x75, 0x5e, 0x68, 0x6f, 0x11, 0x05, 0xeb, 0x97, 0x65, + 0x06, 0xeb, 0xa5, 0x15, 0x5d, 0x60, 0x64, 0x1c, 0x8c, 0x42, 0x9b, 0xd3, + 0xbd, 0xe8, 0xf0, 0x83, 0x2d, 0xe9, 0xf0, 0x4f, 0x04, 0x46, 0xad, 0xf2, + 0x5c, 0x4d, 0xa0, 0x68, 0x00, 0x88, 0xc0, 0xf3, 0x01, 0x1a, 0x20, 0x68, + 0x0f, 0x46, 0x81, 0x88, 0x08, 0x0a, 0x00, 0xf0, 0x03, 0x00, 0x8d, 0xf8, + 0x04, 0x00, 0x90, 0x46, 0x01, 0xf0, 0x0f, 0x00, 0x8d, 0xf8, 0x05, 0x00, + 0x00, 0x25, 0x08, 0xeb, 0x85, 0x00, 0xb0, 0xf9, 0x02, 0x00, 0x38, 0xf9, + 0x25, 0x10, 0x00, 0xf0, 0x63, 0xfb, 0xa1, 0x68, 0x91, 0xf8, 0x24, 0x20, + 0x01, 0x46, 0xde, 0xa8, 0x00, 0xeb, 0x45, 0x10, 0xff, 0xf7, 0xfd, 0xfe, + 0x6d, 0x1c, 0x07, 0x2d, 0xeb, 0xd3, 0x00, 0x20, 0x02, 0xae, 0x37, 0xf9, + 0x20, 0x10, 0x46, 0xf8, 0x30, 0x10, 0x02, 0xaa, 0x07, 0xeb, 0x80, 0x01, + 0x02, 0xeb, 0xc0, 0x02, 0xb1, 0xf9, 0x02, 0x10, 0x51, 0x60, 0x40, 0x1c, + 0x05, 0x28, 0xf0, 0xd3, 0x00, 0x27, 0xa8, 0x25, 0x02, 0xe0, 0x00, 0xf0, + 0x29, 0xf8, 0x7f, 0x1c, 0x57, 0x45, 0xfa, 0xd3, 0x05, 0x2f, 0x1f, 0xd2, + 0x00, 0xf0, 0x22, 0xf8, 0xa7, 0xeb, 0x0a, 0x0b, 0x0c, 0xa8, 0x05, 0xfb, + 0x0b, 0x09, 0x02, 0xa8, 0x00, 0xeb, 0xcb, 0x03, 0xa0, 0x68, 0x4a, 0x46, + 0x51, 0x46, 0x0e, 0x30, 0xff, 0xf7, 0x40, 0xff, 0x20, 0x69, 0x9d, 0xf8, + 0x05, 0x30, 0xc0, 0xb2, 0x00, 0x90, 0x06, 0xeb, 0xcb, 0x02, 0x7f, 0x1c, + 0xd2, 0xe9, 0x00, 0x01, 0x0a, 0x46, 0x01, 0x46, 0x48, 0x46, 0xfe, 0xf7, + 0x4f, 0xff, 0xdd, 0xe7, 0x0d, 0xf2, 0x5c, 0x4d, 0xbd, 0xe8, 0xf0, 0x8f, + 0xa0, 0x68, 0x00, 0x6a, 0x9d, 0xf8, 0x04, 0x30, 0x00, 0x90, 0x08, 0xeb, + 0x87, 0x02, 0xde, 0xa8, 0x00, 0xeb, 0x47, 0x11, 0x0c, 0xa8, 0x05, 0xfb, + 0x07, 0x00, 0xc0, 0xe6, 0x2d, 0xe9, 0xf6, 0x4f, 0xdf, 0xb0, 0x04, 0x46, + 0x01, 0x20, 0xa2, 0x68, 0xd2, 0x7e, 0x00, 0x21, 0xfb, 0xf7, 0x84, 0xff, + 0x04, 0xf0, 0x74, 0xf8, 0xcd, 0xe9, 0x0e, 0x01, 0x20, 0x69, 0x00, 0x28, + 0x14, 0xbf, 0xdf, 0xf8, 0x6c, 0x0b, 0xdf, 0xf8, 0x6c, 0x0b, 0x04, 0x90, + 0x00, 0x20, 0x02, 0x90, 0x5f, 0x98, 0x02, 0x99, 0xa8, 0x22, 0x02, 0xfb, + 0x01, 0x00, 0x00, 0x27, 0x03, 0x90, 0x04, 0x98, 0x02, 0x99, 0x00, 0xeb, + 0xc1, 0x00, 0x00, 0xeb, 0x07, 0x22, 0x00, 0xf0, 0xc5, 0xf9, 0x04, 0x46, + 0x88, 0x46, 0x5f, 0x98, 0xa8, 0x21, 0x01, 0xfb, 0x07, 0x00, 0x06, 0x90, + 0x5f, 0x98, 0x02, 0x99, 0x00, 0xeb, 0xc7, 0x00, 0x07, 0x90, 0x5f, 0x98, + 0x00, 0xeb, 0xc1, 0x00, 0x05, 0x90, 0x02, 0x98, 0xb8, 0x42, 0x37, 0xd1, + 0x38, 0xb1, 0xdd, 0xe9, 0x0e, 0x01, 0x22, 0x46, 0x43, 0x46, 0x04, 0xf0, + 0x5f, 0xf8, 0x04, 0x46, 0x88, 0x46, 0x00, 0x25, 0x21, 0xe0, 0xa8, 0x20, + 0x00, 0xfb, 0x05, 0xf2, 0x05, 0x98, 0x13, 0x18, 0xd3, 0xe9, 0x00, 0x01, + 0x07, 0x9b, 0xd6, 0x18, 0xd6, 0xe9, 0x00, 0x23, 0x04, 0xf0, 0xc2, 0xf8, + 0x06, 0x46, 0x03, 0x98, 0x00, 0xeb, 0xc5, 0x02, 0x89, 0x46, 0xd2, 0xe9, + 0x00, 0x01, 0x06, 0x9a, 0x02, 0xeb, 0xc5, 0x0c, 0x6d, 0x1c, 0xdc, 0xe9, + 0x00, 0x23, 0x04, 0xf0, 0xb3, 0xf8, 0x00, 0xf0, 0x7f, 0xf9, 0x00, 0xf0, + 0x6c, 0xf9, 0x04, 0x46, 0x88, 0x46, 0xbd, 0x42, 0xdb, 0xdb, 0x20, 0x46, + 0x41, 0x46, 0x04, 0xf0, 0x79, 0xf9, 0x03, 0x9a, 0x02, 0x9b, 0x02, 0xeb, + 0xc3, 0x02, 0x5c, 0xe0, 0x04, 0x98, 0x02, 0x99, 0x00, 0xeb, 0x01, 0x20, + 0x00, 0xeb, 0xc7, 0x02, 0x00, 0x25, 0x00, 0xf0, 0x71, 0xf9, 0x40, 0xe0, + 0x06, 0x98, 0x00, 0xeb, 0xc5, 0x02, 0xd2, 0xe9, 0x00, 0x01, 0xcd, 0xe9, + 0x0c, 0x01, 0x00, 0xf0, 0x46, 0xf9, 0xcd, 0xe9, 0x0a, 0x01, 0xa8, 0x20, + 0x00, 0xfb, 0x05, 0xf2, 0x07, 0x98, 0x13, 0x18, 0x6d, 0x1c, 0xd3, 0xe9, + 0x00, 0x01, 0xcd, 0xe9, 0x08, 0x01, 0x05, 0x98, 0x10, 0x18, 0xd0, 0xe9, + 0x00, 0xab, 0xdd, 0xe9, 0x08, 0x01, 0x00, 0xf0, 0x28, 0xf9, 0xcd, 0xe9, + 0x00, 0x01, 0xdd, 0xe9, 0x0a, 0x23, 0xdd, 0xe9, 0x0c, 0x01, 0x04, 0xf0, + 0x73, 0xf8, 0xdd, 0xe9, 0x00, 0x23, 0x03, 0xf0, 0xfb, 0xff, 0x00, 0xf0, + 0x2a, 0xf9, 0x04, 0x46, 0x88, 0x46, 0xdd, 0xe9, 0x0c, 0x01, 0x00, 0xf0, + 0x14, 0xf9, 0x82, 0x46, 0x8b, 0x46, 0xdd, 0xe9, 0x0a, 0x23, 0xdd, 0xe9, + 0x08, 0x01, 0x04, 0xf0, 0x5f, 0xf8, 0x02, 0x46, 0x0b, 0x46, 0x50, 0x46, + 0x59, 0x46, 0x04, 0xf0, 0xa3, 0xf9, 0x00, 0xf0, 0x25, 0xf9, 0x06, 0x46, + 0x89, 0x46, 0xbd, 0x42, 0xba, 0xdb, 0x06, 0x9a, 0x00, 0xf0, 0x37, 0xf9, + 0x00, 0xf0, 0x20, 0xf9, 0x05, 0x9a, 0xa8, 0x23, 0x03, 0xfb, 0x07, 0x22, + 0x00, 0xf0, 0x0e, 0xf9, 0x03, 0x9a, 0x02, 0xeb, 0xc7, 0x02, 0xc2, 0xe9, + 0x00, 0x01, 0x02, 0x98, 0x7f, 0x1c, 0xb8, 0x42, 0xbf, 0xf6, 0x49, 0xaf, + 0x40, 0x1c, 0x15, 0x28, 0x02, 0x90, 0xff, 0xf6, 0x3d, 0xaf, 0x00, 0x27, + 0x04, 0x98, 0x00, 0xeb, 0x07, 0x22, 0x7d, 0x1e, 0xd2, 0xe9, 0x2a, 0x01, + 0x03, 0xf0, 0x8e, 0xff, 0x04, 0x46, 0x04, 0x98, 0x00, 0xeb, 0xc7, 0x00, + 0x00, 0xf5, 0xa8, 0x52, 0x88, 0x46, 0x00, 0xf0, 0xff, 0xf8, 0x06, 0x46, + 0x89, 0x46, 0x5f, 0x98, 0xa8, 0x21, 0x01, 0xfb, 0x07, 0x00, 0x03, 0x90, + 0x3d, 0xe0, 0x00, 0xf0, 0xd4, 0xf8, 0xcd, 0xe9, 0x06, 0x01, 0x00, 0xf0, + 0xf5, 0xf8, 0x00, 0xeb, 0x05, 0x10, 0x02, 0x90, 0x5b, 0x46, 0x0a, 0xa8, + 0x00, 0xeb, 0x05, 0x12, 0xd2, 0xe9, 0x00, 0x01, 0x52, 0x46, 0x04, 0xf0, + 0x0d, 0xf8, 0xcd, 0xe9, 0x00, 0x01, 0xdd, 0xf8, 0x08, 0xc0, 0xdd, 0xe9, + 0x06, 0x23, 0xdc, 0xe9, 0x02, 0x01, 0x04, 0xf0, 0x03, 0xf8, 0xdd, 0xe9, + 0x00, 0x23, 0x03, 0xf0, 0x8b, 0xff, 0x00, 0xf0, 0xba, 0xf8, 0x04, 0x46, + 0x0a, 0xa8, 0x00, 0xeb, 0x05, 0x1c, 0x88, 0x46, 0xdd, 0xe9, 0x06, 0x23, + 0xdc, 0xe9, 0x00, 0x01, 0x03, 0xf0, 0xf2, 0xff, 0xdd, 0xf8, 0x08, 0xc0, + 0xcd, 0xe9, 0x00, 0x01, 0xdc, 0xe9, 0x02, 0x23, 0x50, 0x46, 0x59, 0x46, + 0x03, 0xf0, 0xe8, 0xff, 0x00, 0xf0, 0x97, 0xf8, 0x00, 0xf0, 0xb2, 0xf8, + 0x06, 0x46, 0x89, 0x46, 0x6d, 0x1e, 0x00, 0x2d, 0xbf, 0xd5, 0x00, 0xf0, + 0xc3, 0xf8, 0x00, 0xf0, 0xad, 0xf8, 0x00, 0xf0, 0x9c, 0xf8, 0x0a, 0xaa, + 0x02, 0xeb, 0x07, 0x12, 0x7f, 0x1c, 0xc2, 0xe9, 0x02, 0x01, 0x15, 0x2f, + 0x98, 0xdb, 0x14, 0x27, 0x0a, 0xa8, 0x00, 0xeb, 0x07, 0x10, 0xa8, 0x21, + 0xd0, 0xe9, 0x00, 0x48, 0x0a, 0xa8, 0x00, 0xeb, 0x07, 0x10, 0x04, 0x90, + 0xd0, 0xe9, 0x02, 0x69, 0x5f, 0x98, 0x01, 0xfb, 0x07, 0x00, 0x7d, 0x1c, + 0x03, 0x90, 0x41, 0xe0, 0x00, 0xf0, 0x73, 0xf8, 0xcd, 0xe9, 0x08, 0x01, + 0x00, 0xf0, 0x94, 0xf8, 0x00, 0xeb, 0x05, 0x13, 0xd3, 0xe9, 0x00, 0x01, + 0xcd, 0xe9, 0x06, 0x01, 0x5b, 0x46, 0x0a, 0xa8, 0x00, 0xeb, 0x05, 0x10, + 0x02, 0x90, 0x02, 0x46, 0x6d, 0x1c, 0xd2, 0xe9, 0x02, 0x01, 0x52, 0x46, + 0x03, 0xf0, 0xa6, 0xff, 0xcd, 0xe9, 0x00, 0x01, 0xdd, 0xe9, 0x08, 0x23, + 0xdd, 0xe9, 0x06, 0x01, 0x03, 0xf0, 0x9e, 0xff, 0x00, 0xf0, 0x4d, 0xf8, + 0x22, 0x46, 0x43, 0x46, 0x03, 0xf0, 0x24, 0xff, 0x04, 0x46, 0x88, 0x46, + 0xdd, 0xe9, 0x06, 0x01, 0x00, 0xf0, 0x3f, 0xf8, 0xdd, 0xf8, 0x08, 0xc0, + 0x82, 0x46, 0x8b, 0x46, 0xdd, 0xe9, 0x08, 0x23, 0xdc, 0xe9, 0x02, 0x01, + 0x03, 0xf0, 0x88, 0xff, 0x52, 0x46, 0x5b, 0x46, 0x03, 0xf0, 0x10, 0xff, + 0x02, 0x46, 0x0b, 0x46, 0x30, 0x46, 0x49, 0x46, 0x04, 0xf0, 0xc8, 0xf8, + 0x06, 0x46, 0x89, 0x46, 0x15, 0x2d, 0xbb, 0xdb, 0x00, 0xf0, 0x5e, 0xf8, + 0x00, 0xf0, 0x48, 0xf8, 0x00, 0xf0, 0x37, 0xf8, 0x04, 0x9a, 0x7f, 0x1e, + 0xc2, 0xe9, 0x02, 0x01, 0x9e, 0xd5, 0x00, 0x24, 0x0a, 0xa8, 0x00, 0xeb, + 0x04, 0x12, 0xd2, 0xe9, 0x00, 0x01, 0x04, 0xf0, 0x71, 0xf9, 0x60, 0x99, + 0x41, 0xf8, 0x34, 0x00, 0x0a, 0xa8, 0x00, 0xeb, 0x04, 0x12, 0xd2, 0xe9, + 0x02, 0x01, 0x04, 0xf0, 0x67, 0xf9, 0x60, 0x99, 0x01, 0xeb, 0xc4, 0x01, + 0x64, 0x1c, 0x15, 0x2c, 0x48, 0x60, 0xe7, 0xdb, 0x61, 0xb0, 0xbd, 0xe8, + 0xf0, 0x8f, 0x52, 0x46, 0x5b, 0x46, 0x03, 0xf0, 0x4f, 0xbf, 0x02, 0x46, + 0x0b, 0x46, 0xdd, 0xe9, 0x00, 0x01, 0x04, 0xf0, 0x93, 0xb8, 0x03, 0x98, + 0x00, 0xeb, 0xc5, 0x02, 0xd2, 0xe9, 0x00, 0x01, 0x70, 0x47, 0x02, 0x46, + 0x0b, 0x46, 0x20, 0x46, 0x41, 0x46, 0x04, 0xf0, 0x87, 0xb8, 0x0a, 0xaa, + 0x02, 0xeb, 0x07, 0x12, 0x4b, 0x46, 0xc2, 0xe9, 0x00, 0x01, 0x32, 0x46, + 0x28, 0x46, 0x59, 0x46, 0x03, 0xf0, 0x32, 0xbf, 0x32, 0x46, 0x4b, 0x46, + 0x03, 0xf0, 0xba, 0xbe, 0x05, 0x46, 0x8b, 0x46, 0x22, 0x46, 0x43, 0x46, + 0x03, 0xf0, 0x28, 0xbf, 0xd2, 0xe9, 0x00, 0x01, 0x03, 0xf0, 0x82, 0xbe, + 0x5f, 0x98, 0x00, 0xeb, 0xc7, 0x00, 0xa8, 0x21, 0x01, 0xfb, 0x05, 0x00, + 0xd0, 0xe9, 0x00, 0xab, 0x0a, 0xa8, 0x70, 0x47, 0x03, 0x9a, 0xdf, 0xf8, + 0xa0, 0x17, 0x02, 0xeb, 0xc7, 0x0c, 0x00, 0x20, 0xdc, 0xe9, 0x00, 0x23, + 0x04, 0xf0, 0x62, 0xb9, 0x2d, 0xe9, 0xf0, 0x4f, 0x89, 0xb0, 0x90, 0x46, + 0x04, 0x46, 0x12, 0x9a, 0x9b, 0x46, 0x68, 0x46, 0xff, 0xf7, 0x9f, 0xfc, + 0x00, 0x20, 0x00, 0x21, 0x44, 0xf8, 0x30, 0x10, 0x04, 0xeb, 0xc0, 0x02, + 0x40, 0x1c, 0x04, 0x28, 0x51, 0x60, 0xf7, 0xd3, 0x00, 0x27, 0x00, 0x25, + 0x4f, 0xf0, 0x6a, 0x59, 0x2b, 0xfa, 0x05, 0xf0, 0xc0, 0x07, 0x27, 0xd5, + 0x05, 0xf0, 0x07, 0x00, 0x5d, 0xf8, 0x20, 0x00, 0xfb, 0xf7, 0x46, 0xf9, + 0x82, 0x46, 0x58, 0xf8, 0x37, 0x00, 0x51, 0x46, 0xfb, 0xf7, 0xe8, 0xfa, + 0x49, 0x46, 0xfb, 0xf7, 0xe5, 0xfa, 0xee, 0x08, 0x54, 0xf8, 0x36, 0x10, + 0xfb, 0xf7, 0x44, 0xfa, 0x51, 0x46, 0x44, 0xf8, 0x36, 0x00, 0x04, 0xeb, + 0xc6, 0x06, 0x08, 0xeb, 0xc7, 0x00, 0x7f, 0x1c, 0x40, 0x68, 0xfb, 0xf7, + 0xd5, 0xfa, 0x49, 0x46, 0xfb, 0xf7, 0xd2, 0xfa, 0x71, 0x68, 0xfb, 0xf7, + 0x33, 0xfa, 0x15, 0x2f, 0x70, 0x60, 0x02, 0xd2, 0x6d, 0x1c, 0x20, 0x2d, + 0xd0, 0xd3, 0x09, 0xb0, 0xbd, 0xe8, 0xf0, 0x8f, 0x2d, 0xe9, 0xf0, 0x4f, + 0x0d, 0x46, 0x9d, 0xb0, 0x82, 0x46, 0xa8, 0x68, 0x00, 0x88, 0x00, 0x0a, + 0x00, 0xf0, 0x03, 0x04, 0x00, 0x26, 0x0a, 0xeb, 0x86, 0x00, 0xb0, 0xf9, + 0x02, 0x00, 0x3a, 0xf9, 0x26, 0x10, 0x00, 0xf0, 0xa9, 0xf8, 0xa9, 0x68, + 0x20, 0x31, 0x0a, 0x79, 0x00, 0x92, 0x05, 0xf1, 0x14, 0x02, 0x0b, 0x68, + 0x01, 0x46, 0x04, 0xa8, 0x00, 0xeb, 0x46, 0x10, 0xff, 0xf7, 0x96, 0xff, + 0x76, 0x1c, 0x03, 0x2e, 0xe7, 0xd3, 0xa0, 0x07, 0x4c, 0xbf, 0x40, 0x27, + 0x20, 0x27, 0xba, 0xf9, 0x06, 0x00, 0xfb, 0xf7, 0xf3, 0xf8, 0x04, 0xae, + 0x05, 0x46, 0x71, 0x68, 0xf0, 0x6a, 0xfb, 0xf7, 0xf9, 0xf9, 0x83, 0x46, + 0xba, 0xf9, 0x02, 0x00, 0xfb, 0xf7, 0xe8, 0xf8, 0x03, 0x90, 0xba, 0xf9, + 0x04, 0x00, 0xfb, 0xf7, 0xe3, 0xf8, 0x80, 0x46, 0x04, 0x99, 0xb0, 0x6a, + 0xfb, 0xf7, 0xea, 0xf9, 0x81, 0x46, 0xba, 0xf9, 0x00, 0x00, 0xfb, 0xf7, + 0xd9, 0xf8, 0x82, 0x46, 0x04, 0xa8, 0x3f, 0x18, 0x49, 0x46, 0xb8, 0x69, + 0xfb, 0xf7, 0xde, 0xf9, 0x51, 0x46, 0xfb, 0xf7, 0x77, 0xfa, 0x00, 0x90, + 0x41, 0x46, 0x30, 0x69, 0xfb, 0xf7, 0x72, 0xfa, 0x00, 0x99, 0xfb, 0xf7, + 0xd3, 0xf9, 0x01, 0x90, 0x59, 0x46, 0xf8, 0x69, 0xfb, 0xf7, 0xce, 0xf9, + 0x03, 0x99, 0xfb, 0xf7, 0x67, 0xfa, 0x00, 0x90, 0x29, 0x46, 0x70, 0x69, + 0xfb, 0xf7, 0x62, 0xfa, 0x00, 0x99, 0xfb, 0xf7, 0xc3, 0xf9, 0x01, 0x46, + 0x01, 0x98, 0xfb, 0xf7, 0x4b, 0xf9, 0xfb, 0xf7, 0xc5, 0xfa, 0xad, 0xf8, + 0x08, 0x00, 0x49, 0x46, 0xb8, 0x69, 0xfb, 0xf7, 0xb7, 0xf9, 0x03, 0x99, + 0xfb, 0xf7, 0x50, 0xfa, 0x81, 0x46, 0x30, 0x69, 0x00, 0xf0, 0x98, 0xf8, + 0x49, 0x46, 0xfb, 0xf7, 0xad, 0xf9, 0x81, 0x46, 0xf8, 0x69, 0x59, 0x46, + 0xfb, 0xf7, 0xa8, 0xf9, 0x51, 0x46, 0xfb, 0xf7, 0x41, 0xfa, 0x83, 0x46, + 0x70, 0x69, 0x00, 0xf0, 0x15, 0xff, 0x59, 0x46, 0xfb, 0xf7, 0x9e, 0xf9, + 0x49, 0x46, 0xfb, 0xf7, 0x9b, 0xf9, 0xfb, 0xf7, 0xa1, 0xfa, 0x06, 0x46, + 0xe0, 0x07, 0xad, 0xf8, 0x0a, 0x60, 0x21, 0xd5, 0xbd, 0xf8, 0x08, 0x40, + 0xb8, 0x69, 0x00, 0xf0, 0x03, 0xff, 0x83, 0x46, 0xf8, 0x69, 0x00, 0xf0, + 0x73, 0xf8, 0x01, 0x46, 0x58, 0x46, 0xfb, 0xf7, 0x13, 0xf9, 0xfb, 0xf7, + 0x8d, 0xfa, 0x00, 0x19, 0xad, 0xf8, 0x08, 0x00, 0x29, 0x46, 0xb8, 0x69, + 0xfb, 0xf7, 0x1a, 0xfa, 0x04, 0x46, 0xf8, 0x69, 0x00, 0xf0, 0xee, 0xfe, + 0x21, 0x46, 0xfb, 0xf7, 0x77, 0xf9, 0xfb, 0xf7, 0x7d, 0xfa, 0x80, 0x19, + 0xad, 0xf8, 0x0a, 0x00, 0x02, 0x98, 0x1d, 0xb0, 0xbd, 0xe8, 0xf0, 0x8f, + 0x40, 0x43, 0x01, 0xfb, 0x01, 0x00, 0x00, 0xeb, 0xd0, 0x70, 0x40, 0x10, + 0xff, 0xf7, 0x86, 0xbb, 0x01, 0xb4, 0xbd, 0xf9, 0x02, 0x00, 0xbd, 0xf9, + 0x00, 0x10, 0x40, 0x43, 0x01, 0xfb, 0x01, 0x00, 0x01, 0xb0, 0x70, 0x47, + 0x49, 0x43, 0x00, 0xfb, 0x00, 0x10, 0x70, 0x47, 0x38, 0xb5, 0x0d, 0x46, + 0x01, 0x46, 0xfb, 0xf7, 0xef, 0xf9, 0x04, 0x46, 0x28, 0x46, 0x00, 0xf0, + 0x37, 0xf8, 0x21, 0x46, 0xbd, 0xe8, 0x34, 0x40, 0xfb, 0xf7, 0x4a, 0xb9, + 0x2d, 0xe9, 0xf9, 0x42, 0x82, 0xb0, 0x0c, 0x46, 0xbd, 0xf9, 0x0a, 0x00, + 0x15, 0x46, 0xfb, 0xf7, 0x35, 0xf8, 0x07, 0x46, 0xbd, 0xf9, 0x08, 0x00, + 0xfb, 0xf7, 0x30, 0xf8, 0x06, 0x46, 0x20, 0x46, 0x31, 0x46, 0xfb, 0xf7, + 0xd3, 0xf9, 0x81, 0x46, 0x38, 0x46, 0x00, 0xf0, 0x1b, 0xf8, 0x01, 0x46, + 0x48, 0x46, 0xfb, 0xf7, 0xbb, 0xf8, 0xfb, 0xf7, 0x35, 0xfa, 0xad, 0xf8, + 0x00, 0x00, 0x39, 0x46, 0x20, 0x46, 0xfb, 0xf7, 0xc3, 0xf9, 0x04, 0x46, + 0x30, 0x46, 0x00, 0xf0, 0x0b, 0xf8, 0x21, 0x46, 0xfb, 0xf7, 0x20, 0xf9, + 0xfb, 0xf7, 0x26, 0xfa, 0xad, 0xf8, 0x02, 0x00, 0x00, 0x98, 0x04, 0xb0, + 0xbd, 0xe8, 0xf0, 0x82, 0x29, 0x46, 0xfb, 0xf7, 0xb1, 0xb9, 0x0e, 0xb4, + 0x2d, 0xe9, 0xf0, 0x4a, 0x84, 0xb0, 0x81, 0x46, 0x0f, 0x98, 0x00, 0x28, + 0x14, 0xbf, 0x4f, 0xf0, 0xff, 0x37, 0x01, 0x27, 0xdd, 0xe9, 0x0d, 0x45, + 0x93, 0x46, 0x20, 0x46, 0xfb, 0xf7, 0xa0, 0xf9, 0x00, 0x90, 0x38, 0x46, + 0xfa, 0xf7, 0xf4, 0xff, 0x59, 0x46, 0xfb, 0xf7, 0x99, 0xf9, 0xff, 0xf7, + 0xe3, 0xff, 0x01, 0x46, 0x00, 0x98, 0xfb, 0xf7, 0x83, 0xf8, 0x06, 0x46, + 0x20, 0x46, 0x59, 0x46, 0xfb, 0xf7, 0x8e, 0xf9, 0x04, 0x46, 0x38, 0x46, + 0xfa, 0xf7, 0xe2, 0xff, 0x0b, 0x99, 0xfb, 0xf7, 0x87, 0xf9, 0xff, 0xf7, + 0xd1, 0xff, 0x21, 0x46, 0xfb, 0xf7, 0xe6, 0xf8, 0xc9, 0xe9, 0x00, 0x60, + 0x04, 0xb0, 0xbd, 0xe8, 0xf0, 0x0a, 0x5d, 0xf8, 0x10, 0xfb, 0xfe, 0xb5, + 0x06, 0x46, 0x10, 0x46, 0x19, 0x46, 0xfa, 0xf7, 0x9b, 0xff, 0x07, 0x46, + 0xdd, 0xe9, 0x08, 0x01, 0xfa, 0xf7, 0x96, 0xff, 0x39, 0x46, 0xfa, 0xf7, + 0xdf, 0xff, 0x05, 0x46, 0xdd, 0xe9, 0x0a, 0x01, 0xfa, 0xf7, 0x8e, 0xff, + 0x39, 0x46, 0xfa, 0xf7, 0xd7, 0xff, 0x07, 0x46, 0x28, 0x46, 0x39, 0x46, + 0xff, 0xf7, 0x6c, 0xff, 0x04, 0x46, 0x29, 0x46, 0xdf, 0xf8, 0x88, 0x0d, + 0xfb, 0xf7, 0x5a, 0xf9, 0x21, 0x46, 0xfa, 0xf7, 0xc9, 0xff, 0x04, 0x46, + 0x28, 0x46, 0x39, 0x46, 0xff, 0xf7, 0x5e, 0xff, 0x05, 0x46, 0xdf, 0xf8, + 0x74, 0x0d, 0x39, 0x46, 0xfb, 0xf7, 0x4c, 0xf9, 0x29, 0x46, 0xfa, 0xf7, + 0xbb, 0xff, 0xc6, 0xe9, 0x00, 0x40, 0xfe, 0xbd, 0x2d, 0xe9, 0xf0, 0x4f, + 0x07, 0x46, 0x8f, 0xb0, 0x38, 0x68, 0x00, 0x22, 0xc0, 0xe9, 0x06, 0x22, + 0xc0, 0xe9, 0x04, 0x22, 0xc0, 0xe9, 0x02, 0x22, 0x00, 0x24, 0x0d, 0xf1, + 0x04, 0x0a, 0x0d, 0xf1, 0x20, 0x09, 0x38, 0x69, 0x07, 0x23, 0x01, 0xaa, + 0x08, 0xa9, 0xfe, 0xf7, 0x03, 0xfb, 0xf8, 0xf7, 0x44, 0xfd, 0x48, 0xb1, + 0x38, 0x46, 0xfe, 0xf7, 0x96, 0xfb, 0x38, 0x46, 0xfe, 0xf7, 0x79, 0xfb, + 0x64, 0x1e, 0x00, 0x28, 0x40, 0xd0, 0x56, 0xe0, 0x00, 0x25, 0x01, 0xa8, + 0x00, 0xeb, 0x85, 0x06, 0xd7, 0xf8, 0x00, 0xc0, 0xb6, 0xf9, 0x02, 0xb0, + 0x08, 0xa8, 0x00, 0xeb, 0x85, 0x08, 0xdc, 0xe9, 0x02, 0x01, 0x02, 0x46, + 0x0b, 0x46, 0xb8, 0xf9, 0x02, 0xe0, 0x39, 0xf9, 0x25, 0x00, 0x3a, 0xf9, + 0x25, 0x10, 0x0b, 0xfb, 0x0e, 0xfe, 0x01, 0xfb, 0x00, 0xe0, 0xc1, 0x17, + 0x10, 0x18, 0x59, 0x41, 0xcc, 0xe9, 0x02, 0x01, 0x39, 0xf9, 0x25, 0x20, + 0xb6, 0xf9, 0x02, 0x30, 0x3a, 0xf9, 0x25, 0x60, 0x5a, 0x43, 0xdc, 0xe9, + 0x04, 0x01, 0xb8, 0xf9, 0x02, 0x30, 0x06, 0xfb, 0x13, 0x22, 0x80, 0x18, + 0x41, 0xeb, 0xe2, 0x71, 0xcc, 0xe9, 0x04, 0x01, 0x59, 0xf8, 0x25, 0x00, + 0x00, 0x90, 0xff, 0xf7, 0xeb, 0xfe, 0x3e, 0x68, 0x00, 0x21, 0xd6, 0xe9, + 0x06, 0x23, 0x10, 0x18, 0x59, 0x41, 0xc6, 0xe9, 0x06, 0x01, 0x6d, 0x1c, + 0x07, 0x2d, 0xc0, 0xdb, 0x64, 0x1c, 0x80, 0x2c, 0xa9, 0xdb, 0x3a, 0x68, + 0xb8, 0x68, 0x80, 0x8b, 0xd2, 0xe9, 0x06, 0x45, 0xa0, 0xfb, 0x00, 0x23, + 0x4f, 0xf4, 0x60, 0x70, 0xa0, 0xfb, 0x02, 0x68, 0x00, 0xfb, 0x03, 0x88, + 0x45, 0x45, 0x03, 0xd8, 0x2c, 0xbf, 0xb4, 0x42, 0x07, 0x20, 0x00, 0xd3, + 0x00, 0x20, 0x0f, 0xb0, 0xbd, 0xe8, 0xf0, 0x8f, 0x2d, 0xe9, 0xf1, 0x4f, + 0xad, 0xf5, 0x06, 0x7d, 0x84, 0x68, 0x00, 0x68, 0x03, 0x90, 0x20, 0x21, + 0x7e, 0xa8, 0xfb, 0xf7, 0x6d, 0xff, 0x66, 0xa8, 0x60, 0x21, 0xfb, 0xf7, + 0x69, 0xff, 0x3c, 0xa8, 0xa8, 0x21, 0xfb, 0xf7, 0x65, 0xff, 0x12, 0xa8, + 0xa8, 0x21, 0xfb, 0xf7, 0x61, 0xff, 0x07, 0xa8, 0x00, 0x21, 0x00, 0x22, + 0x06, 0xc0, 0x03, 0x98, 0xd4, 0x30, 0x02, 0x90, 0x00, 0x68, 0xfb, 0xf7, + 0x87, 0xf8, 0x05, 0xd1, 0x02, 0x98, 0x40, 0x68, 0xfb, 0xf7, 0x82, 0xf8, + 0x00, 0xf0, 0xf2, 0x80, 0x03, 0x9a, 0x0d, 0xf5, 0xfc, 0x7a, 0xd2, 0xe9, + 0x08, 0x01, 0xff, 0xf7, 0xa5, 0xfe, 0x02, 0x9a, 0x09, 0x90, 0xd2, 0xe9, + 0x00, 0x01, 0xff, 0xf7, 0x9f, 0xfe, 0x04, 0x90, 0x01, 0x20, 0x01, 0x90, + 0x02, 0x98, 0xd0, 0xe9, 0x00, 0x9b, 0x03, 0x98, 0xcd, 0xf8, 0x00, 0xb0, + 0x4b, 0x46, 0xd0, 0xe9, 0x08, 0x9b, 0x49, 0x46, 0x5a, 0x46, 0x05, 0xa8, + 0xff, 0xf7, 0xd1, 0xfe, 0x05, 0x98, 0x04, 0x99, 0xfa, 0xf7, 0xf0, 0xfe, + 0x05, 0x90, 0x4f, 0xf0, 0x8c, 0x49, 0x06, 0x98, 0x04, 0x99, 0xfa, 0xf7, + 0xe9, 0xfe, 0x02, 0x99, 0x06, 0x90, 0x09, 0x89, 0x34, 0xf8, 0x0c, 0x2f, + 0x8d, 0x1a, 0x49, 0x46, 0xfb, 0xf7, 0x6e, 0xf8, 0xfb, 0xf7, 0xd8, 0xf8, + 0xad, 0xf8, 0x06, 0x00, 0x49, 0x46, 0x05, 0x98, 0xfb, 0xf7, 0x66, 0xf8, + 0xfb, 0xf7, 0xd0, 0xf8, 0xad, 0xf8, 0x04, 0x00, 0x0d, 0xf1, 0x48, 0x0b, + 0x0b, 0xe0, 0x00, 0xbf, 0x00, 0x98, 0x41, 0x1e, 0x00, 0x28, 0x00, 0x91, + 0xf9, 0xd1, 0x08, 0xf1, 0x01, 0x08, 0xb8, 0xf1, 0x04, 0x0f, 0x6f, 0xd3, + 0x6d, 0x1c, 0x02, 0x99, 0x09, 0x89, 0xe8, 0xb2, 0x88, 0x42, 0x80, 0xf0, + 0x9f, 0x80, 0xfe, 0xf7, 0x6c, 0xf9, 0x80, 0x03, 0xff, 0xf7, 0xcc, 0xf9, + 0x01, 0x46, 0x20, 0x7e, 0x00, 0x90, 0x00, 0x27, 0x03, 0x98, 0x63, 0x69, + 0x00, 0xf1, 0x28, 0x02, 0x0a, 0xa8, 0xff, 0xf7, 0x2d, 0xfd, 0x0a, 0xa8, + 0x49, 0x46, 0x50, 0xf8, 0x37, 0x00, 0xfb, 0xf7, 0x37, 0xf8, 0xfb, 0xf7, + 0xa1, 0xf8, 0x4a, 0xf8, 0x37, 0x00, 0x49, 0x46, 0x0a, 0xa8, 0x00, 0xeb, + 0xc7, 0x00, 0x40, 0x68, 0xfb, 0xf7, 0x2c, 0xf8, 0xfb, 0xf7, 0x96, 0xf8, + 0x7e, 0xa9, 0x01, 0xeb, 0xc7, 0x01, 0x7f, 0x1c, 0x04, 0x2f, 0x48, 0x60, + 0xe5, 0xdb, 0xe8, 0xb2, 0xfe, 0xf7, 0x41, 0xf9, 0xfa, 0xf7, 0x80, 0xfe, + 0x4f, 0xf0, 0x8d, 0x41, 0xfb, 0xf7, 0x1a, 0xf8, 0x09, 0x99, 0xfb, 0xf7, + 0x17, 0xf8, 0x04, 0x99, 0xfa, 0xf7, 0x86, 0xfe, 0x01, 0xf0, 0x12, 0xff, + 0xff, 0xf7, 0x94, 0xf9, 0x07, 0x46, 0xbd, 0xf8, 0x04, 0x00, 0xad, 0xf8, + 0x1c, 0x00, 0x00, 0x26, 0xbd, 0xf8, 0x06, 0x00, 0xad, 0xf8, 0x1e, 0x00, + 0xbd, 0xf8, 0x04, 0x00, 0xad, 0xf8, 0x20, 0x00, 0xbd, 0xf8, 0x06, 0x00, + 0xad, 0xf8, 0x22, 0x00, 0x22, 0x7e, 0x66, 0xa8, 0x39, 0x46, 0x00, 0xeb, + 0x46, 0x10, 0xff, 0xf7, 0x90, 0xf9, 0x76, 0x1c, 0x03, 0x2e, 0xf5, 0xdb, + 0x07, 0xaa, 0x86, 0x98, 0x80, 0x68, 0x00, 0x6a, 0x00, 0x90, 0x66, 0xa9, + 0x03, 0x98, 0x80, 0x88, 0x00, 0x0a, 0x00, 0xf0, 0x03, 0x03, 0x3c, 0xa8, + 0xff, 0xf7, 0x93, 0xf9, 0x00, 0x26, 0xb0, 0x46, 0x00, 0x27, 0x00, 0x20, + 0x4b, 0xf8, 0x37, 0x00, 0x12, 0xa9, 0x01, 0xeb, 0xc7, 0x01, 0x7f, 0x1c, + 0x15, 0x2f, 0x48, 0x60, 0xf6, 0xdb, 0x61, 0x69, 0x00, 0xeb, 0xc8, 0x02, + 0xd1, 0x40, 0xc9, 0x07, 0x0f, 0xd5, 0x3c, 0xa9, 0x12, 0xaa, 0x51, 0xf8, + 0x36, 0x10, 0x4b, 0xf8, 0x36, 0x10, 0x02, 0xeb, 0xc6, 0x02, 0x3c, 0xa9, + 0x01, 0xeb, 0xc6, 0x01, 0x76, 0x1c, 0x49, 0x68, 0x51, 0x60, 0x15, 0x2e, + 0x02, 0xd2, 0x40, 0x1c, 0x08, 0x28, 0xe6, 0xd3, 0x86, 0x98, 0x00, 0x69, + 0xc0, 0xb2, 0x00, 0x90, 0x0a, 0xeb, 0xc8, 0x02, 0x00, 0x23, 0xd2, 0xe9, + 0x00, 0x01, 0x0a, 0x46, 0x01, 0x46, 0x12, 0xa8, 0xfe, 0xf7, 0xda, 0xf9, + 0x4f, 0xf4, 0xc8, 0x70, 0x00, 0x90, 0x4f, 0xe7, 0x0d, 0xf5, 0x07, 0x7d, + 0xbd, 0xe8, 0xf0, 0x8f, 0x70, 0xb5, 0x82, 0xb0, 0x04, 0x46, 0x00, 0x25, + 0x00, 0x26, 0x54, 0xf8, 0x26, 0x00, 0x00, 0x90, 0x76, 0x1c, 0xff, 0xf7, + 0x9d, 0xfd, 0x45, 0x19, 0x07, 0x2e, 0xf6, 0xd3, 0x28, 0x46, 0x76, 0xbd, + 0x70, 0xb5, 0x82, 0xb0, 0x04, 0x46, 0x00, 0x25, 0x00, 0x26, 0x54, 0xf8, + 0x26, 0x00, 0x00, 0x90, 0xff, 0xf7, 0x8e, 0xfd, 0x85, 0x42, 0x38, 0xbf, + 0x05, 0x46, 0x76, 0x1c, 0x07, 0x2e, 0xf4, 0xd3, 0x28, 0x46, 0x76, 0xbd, + 0x38, 0xb5, 0x00, 0x24, 0x02, 0xfb, 0x02, 0xf5, 0x11, 0xb9, 0xff, 0xf7, + 0xe7, 0xff, 0x03, 0xe0, 0xff, 0xf7, 0xd4, 0xff, 0xc5, 0xeb, 0xc5, 0x05, + 0xa8, 0x42, 0x28, 0xbf, 0x01, 0x24, 0x20, 0x46, 0x32, 0xbd, 0xc9, 0xb2, + 0x51, 0xb1, 0x15, 0x29, 0x08, 0xda, 0xc0, 0x68, 0x00, 0xeb, 0x81, 0x01, + 0x0a, 0x6c, 0x52, 0x1c, 0x0a, 0x64, 0x01, 0x6c, 0x49, 0x1c, 0x01, 0x64, + 0x70, 0x47, 0x03, 0x68, 0x00, 0xf1, 0x08, 0x01, 0x03, 0xf1, 0x14, 0x02, + 0x18, 0x46, 0xff, 0xf7, 0x4d, 0xba, 0x10, 0xb5, 0x82, 0xb0, 0x04, 0x46, + 0x6a, 0x46, 0x00, 0x21, 0x00, 0x20, 0xf7, 0xf7, 0xa2, 0xfc, 0x00, 0x98, + 0xdf, 0xf8, 0x84, 0x29, 0x04, 0x60, 0x00, 0x21, 0x00, 0x20, 0xf7, 0xf7, + 0x26, 0xfd, 0x00, 0x20, 0xf7, 0xf7, 0xdf, 0xfc, 0x13, 0xbd, 0x00, 0x00, + 0x00, 0x20, 0x70, 0x59, 0x00, 0x00, 0x70, 0x59, 0x00, 0x00, 0xf0, 0x3f, + 0x2d, 0xe9, 0xf0, 0x4f, 0x04, 0x46, 0xd3, 0xb0, 0xa3, 0x68, 0x08, 0x93, + 0x20, 0x68, 0x08, 0x9a, 0x05, 0x90, 0xe1, 0x68, 0x06, 0x91, 0x00, 0x21, + 0x10, 0x91, 0x0f, 0x91, 0x0e, 0x91, 0x08, 0x99, 0x24, 0x31, 0x04, 0x91, + 0x05, 0x99, 0x01, 0xf5, 0xcc, 0x71, 0x09, 0x91, 0x05, 0x99, 0x12, 0x88, + 0x89, 0x88, 0x22, 0xf4, 0x00, 0x62, 0x91, 0x42, 0x0b, 0xd1, 0x09, 0x99, + 0x08, 0x9a, 0x49, 0x68, 0x12, 0x6a, 0x91, 0x42, 0x05, 0xd1, 0x09, 0x99, + 0x04, 0x9a, 0x09, 0x7a, 0x12, 0x78, 0x91, 0x42, 0x03, 0xd0, 0x22, 0x69, + 0x06, 0x99, 0xfe, 0xf7, 0x6a, 0xfa, 0x05, 0x98, 0x08, 0x30, 0x07, 0x90, + 0xd0, 0xe9, 0x04, 0x23, 0x00, 0x2b, 0x08, 0xbf, 0x00, 0x2a, 0x0b, 0xd0, + 0xd0, 0xe9, 0x00, 0x23, 0x00, 0x2b, 0x08, 0xbf, 0x00, 0x2a, 0x0c, 0xd1, + 0xd0, 0xe9, 0x02, 0x23, 0x00, 0x2b, 0x08, 0xbf, 0x00, 0x2a, 0x06, 0xd1, + 0x20, 0x46, 0xff, 0xf7, 0xbb, 0xfd, 0x5f, 0xea, 0x00, 0x09, 0x40, 0xf0, + 0xbe, 0x82, 0x00, 0x20, 0x0b, 0x90, 0x6a, 0x46, 0x07, 0x98, 0x0a, 0xc8, + 0x0a, 0xc2, 0x0a, 0xc8, 0x0a, 0xc2, 0x07, 0x98, 0x00, 0x25, 0xd0, 0xe9, + 0x04, 0x23, 0x0c, 0xa8, 0xff, 0xf7, 0x73, 0xfd, 0xdd, 0xe9, 0x0c, 0x01, + 0x05, 0x9a, 0xc2, 0xe9, 0x08, 0x01, 0x00, 0x20, 0xcd, 0xe9, 0x18, 0x00, + 0xcd, 0xe9, 0x0c, 0x00, 0x04, 0x9a, 0x08, 0x98, 0x04, 0x99, 0x04, 0x9b, + 0x40, 0x88, 0x92, 0x89, 0x49, 0x8a, 0xdb, 0x89, 0x03, 0x90, 0x12, 0x18, + 0x64, 0x31, 0x9a, 0x18, 0x51, 0x43, 0x64, 0x22, 0xb1, 0xfb, 0xf2, 0xf1, + 0x01, 0x20, 0x14, 0x91, 0x01, 0x90, 0x0d, 0xe0, 0x02, 0x28, 0x03, 0xd1, + 0x04, 0x99, 0x03, 0x98, 0x89, 0x89, 0x04, 0xe0, 0x03, 0x28, 0x05, 0xd1, + 0x04, 0x99, 0x03, 0x98, 0xc9, 0x89, 0x08, 0x18, 0x80, 0xb2, 0x03, 0x90, + 0x01, 0x20, 0xad, 0xf8, 0x00, 0x00, 0x00, 0xf0, 0xa1, 0xfb, 0x0a, 0x90, + 0x00, 0x20, 0x02, 0x90, 0x76, 0xe0, 0xdd, 0xe9, 0x18, 0x01, 0x0b, 0x46, + 0x00, 0x21, 0xc0, 0x19, 0x59, 0x41, 0xcd, 0xe9, 0x18, 0x01, 0xdd, 0xe9, + 0x0c, 0x23, 0x00, 0x21, 0x12, 0xeb, 0x0b, 0x00, 0x59, 0x41, 0xcd, 0xe9, + 0x0c, 0x01, 0x05, 0x98, 0x00, 0x79, 0x00, 0xf0, 0x0f, 0x00, 0x01, 0x21, + 0x08, 0x30, 0x01, 0xfa, 0x00, 0xf0, 0xc1, 0x17, 0xcd, 0xe9, 0x16, 0x01, + 0x07, 0x98, 0xd0, 0xe9, 0x00, 0x79, 0x00, 0xf0, 0x6b, 0xfb, 0x38, 0x1a, + 0x69, 0xeb, 0x01, 0x01, 0x07, 0x9a, 0x10, 0xeb, 0x0a, 0x00, 0x41, 0xeb, + 0xea, 0x71, 0xc2, 0xe9, 0x00, 0x01, 0x07, 0x98, 0xd0, 0xe9, 0x02, 0x79, + 0x00, 0xf0, 0x5c, 0xfb, 0x3a, 0x1a, 0x15, 0x98, 0x69, 0xeb, 0x01, 0x03, + 0xc1, 0x17, 0x10, 0x18, 0x07, 0x9a, 0x59, 0x41, 0xc2, 0xe9, 0x02, 0x01, + 0x07, 0x98, 0xd0, 0xe9, 0x04, 0x79, 0x00, 0xf0, 0x4d, 0xfb, 0x38, 0x1a, + 0x69, 0xeb, 0x01, 0x01, 0x00, 0x23, 0x07, 0x9a, 0x10, 0xeb, 0x0b, 0x00, + 0x59, 0x41, 0xc2, 0xe9, 0x04, 0x01, 0x1a, 0xa8, 0x50, 0xf8, 0x26, 0x00, + 0x15, 0x90, 0x05, 0x98, 0xd0, 0xe9, 0x08, 0x23, 0x11, 0x46, 0x15, 0x98, + 0x1a, 0x46, 0xff, 0xf7, 0x7f, 0xfc, 0x1a, 0xa9, 0x41, 0xf8, 0x26, 0x00, + 0x1a, 0xa8, 0x21, 0xa9, 0x30, 0xf9, 0x26, 0x00, 0x31, 0xf9, 0x26, 0x10, + 0x40, 0x1a, 0x11, 0x90, 0x13, 0x98, 0xb8, 0xf9, 0x02, 0x10, 0xb0, 0xf9, + 0x02, 0x00, 0x00, 0xf0, 0x14, 0xfb, 0x08, 0x99, 0x49, 0x89, 0x49, 0x43, + 0x81, 0x42, 0x02, 0xd2, 0x0e, 0x98, 0x40, 0x1c, 0x0e, 0x90, 0x76, 0x1c, + 0x07, 0x2e, 0x62, 0xd3, 0x1a, 0xaa, 0x21, 0xa9, 0x20, 0x46, 0xff, 0xf7, + 0xb7, 0xf8, 0x6d, 0x1c, 0x03, 0x98, 0x85, 0x42, 0x80, 0xf0, 0x90, 0x80, + 0x00, 0xf0, 0x28, 0xfb, 0x06, 0x99, 0x0a, 0x98, 0x08, 0x62, 0x6e, 0x1e, + 0xf8, 0xf7, 0x4d, 0xfa, 0x88, 0xb1, 0x00, 0xf0, 0x0e, 0xfb, 0x20, 0x46, + 0xfe, 0xf7, 0x83, 0xf8, 0x5f, 0xea, 0x00, 0x09, 0x35, 0x46, 0x07, 0xd1, + 0x08, 0x99, 0x05, 0x98, 0x09, 0x88, 0x80, 0x88, 0x21, 0xf4, 0x00, 0x61, + 0x88, 0x42, 0xe0, 0xd0, 0xe3, 0xe1, 0x01, 0x98, 0x01, 0x28, 0x31, 0xd0, + 0x0a, 0x98, 0xfa, 0xf7, 0x89, 0xfe, 0x00, 0xf0, 0xf9, 0xfa, 0x40, 0xbb, + 0x02, 0x98, 0x45, 0x1c, 0x01, 0x98, 0x03, 0x28, 0x1b, 0xd1, 0x04, 0x99, + 0xbd, 0xf8, 0x00, 0x00, 0x09, 0x8a, 0x88, 0x42, 0x03, 0xd2, 0x40, 0x1c, + 0xad, 0xf8, 0x00, 0x00, 0x12, 0xe0, 0x04, 0x98, 0xc0, 0x88, 0xfa, 0xf7, + 0x69, 0xfc, 0x00, 0xf0, 0xd4, 0xfa, 0x00, 0xf0, 0xcf, 0xfa, 0x00, 0xf0, + 0xf3, 0xfa, 0x01, 0x46, 0x0a, 0x98, 0xfa, 0xf7, 0xfd, 0xfd, 0x0a, 0x90, + 0x01, 0x20, 0xad, 0xf8, 0x00, 0x00, 0x02, 0x95, 0x02, 0x98, 0x14, 0x99, + 0x88, 0x42, 0x80, 0xf0, 0xdc, 0x81, 0x35, 0x46, 0xad, 0xe7, 0x00, 0xf0, + 0xd3, 0xfa, 0x0a, 0x90, 0x21, 0xa8, 0xff, 0xf7, 0x51, 0xfe, 0x0b, 0x99, + 0x81, 0x42, 0x38, 0xbf, 0x01, 0x46, 0x0b, 0x91, 0x00, 0x26, 0x21, 0xa8, + 0x00, 0xf0, 0xa9, 0xfa, 0x83, 0x46, 0x1a, 0xa8, 0x00, 0xf0, 0xa5, 0xfa, + 0x07, 0x46, 0x1a, 0xa8, 0x00, 0xeb, 0x86, 0x01, 0x13, 0x91, 0x1a, 0xaa, + 0xb1, 0xf9, 0x02, 0x00, 0x32, 0xf9, 0x26, 0x20, 0x21, 0xa9, 0x01, 0xeb, + 0x86, 0x08, 0xb8, 0xf9, 0x02, 0x30, 0x31, 0xf9, 0x26, 0x10, 0x43, 0x43, + 0x02, 0xfb, 0x01, 0x3a, 0x21, 0xa9, 0x1a, 0xaa, 0x31, 0xf9, 0x26, 0x10, + 0x32, 0xf9, 0x26, 0x20, 0x48, 0x43, 0xb8, 0xf9, 0x02, 0x10, 0x02, 0xfb, + 0x11, 0x01, 0x08, 0x98, 0x15, 0x91, 0x00, 0x89, 0x40, 0x43, 0x58, 0x45, + 0x03, 0xd2, 0x10, 0x98, 0x40, 0x1c, 0x10, 0x90, 0x69, 0xe7, 0xb8, 0x42, + 0xbf, 0xf4, 0xf9, 0xae, 0x0f, 0x98, 0x40, 0x1c, 0x0f, 0x90, 0x62, 0xe7, + 0x01, 0x98, 0x40, 0x1c, 0xc0, 0xb2, 0x04, 0x28, 0x01, 0x90, 0xff, 0xf6, + 0xd7, 0xae, 0x00, 0xf0, 0x80, 0xfa, 0x03, 0xa8, 0x00, 0x21, 0x00, 0x88, + 0xcd, 0xe9, 0x00, 0x01, 0x07, 0x26, 0x04, 0x98, 0x80, 0x7e, 0x00, 0x28, + 0x60, 0xd0, 0x04, 0x98, 0xc0, 0x8b, 0xfa, 0xf7, 0xf9, 0xfb, 0x00, 0xf0, + 0x64, 0xfa, 0xdf, 0xf8, 0x04, 0x16, 0xfa, 0xf7, 0x03, 0xfc, 0x00, 0xf0, + 0x81, 0xfa, 0x05, 0x46, 0x04, 0x98, 0x82, 0x8b, 0xdd, 0xe9, 0x00, 0x01, + 0xa2, 0xfb, 0x00, 0x79, 0x02, 0xfb, 0x01, 0x99, 0xa2, 0xfb, 0x07, 0x01, + 0x02, 0xfb, 0x09, 0x11, 0xa6, 0xfb, 0x00, 0x79, 0x06, 0xfb, 0x01, 0x99, + 0x38, 0x46, 0x49, 0x46, 0xfa, 0xf7, 0xae, 0xfb, 0xff, 0xf7, 0xc4, 0xfb, + 0x03, 0xf0, 0xf4, 0xfc, 0x02, 0x46, 0x20, 0x69, 0x0b, 0x46, 0x01, 0x28, + 0x0c, 0xbf, 0x02, 0x21, 0x01, 0x21, 0x00, 0x25, 0xef, 0xf3, 0x11, 0x8a, + 0x60, 0x20, 0x80, 0xf3, 0x11, 0x88, 0x09, 0x98, 0xc0, 0x7a, 0x38, 0xbb, + 0x09, 0x98, 0x80, 0x7a, 0x80, 0xb1, 0xdd, 0xe9, 0x0c, 0x70, 0x83, 0x42, + 0x08, 0xd8, 0x28, 0xbf, 0xba, 0x42, 0x05, 0xd2, 0x09, 0x9a, 0x95, 0x72, + 0x01, 0x20, 0xfe, 0xf7, 0x86, 0xf8, 0x17, 0xe0, 0x00, 0x20, 0xfe, 0xf7, + 0x82, 0xf8, 0x12, 0xe0, 0xdd, 0xe9, 0x0c, 0x23, 0x4b, 0x45, 0x0f, 0xd8, + 0x28, 0xbf, 0xba, 0x42, 0x0c, 0xd2, 0x09, 0x9a, 0x01, 0x20, 0x90, 0x72, + 0x00, 0x20, 0xfe, 0xf7, 0x74, 0xf8, 0xa0, 0x68, 0x90, 0xf8, 0x3f, 0x10, + 0x20, 0x69, 0xfe, 0xf7, 0xd9, 0xf8, 0x0f, 0x25, 0x8a, 0xf3, 0x11, 0x88, + 0x00, 0x2d, 0x72, 0xd1, 0x08, 0x98, 0x80, 0x8b, 0xdd, 0xe9, 0x00, 0x23, + 0xa0, 0xfb, 0x02, 0x79, 0x00, 0xfb, 0x03, 0x99, 0xa0, 0xfb, 0x07, 0x23, + 0x00, 0xfb, 0x09, 0x33, 0xa6, 0xfb, 0x02, 0x01, 0x06, 0xfb, 0x03, 0x11, + 0xdd, 0xe9, 0x0c, 0x23, 0x8b, 0x42, 0x07, 0xd8, 0x28, 0xbf, 0x82, 0x42, + 0x04, 0xd2, 0x21, 0x68, 0x00, 0xf0, 0x09, 0xfa, 0x07, 0x20, 0xdb, 0xe1, + 0x10, 0x9a, 0x02, 0x2a, 0x07, 0xd3, 0xa3, 0x68, 0x22, 0x69, 0x06, 0x99, + 0x05, 0x98, 0xfe, 0xf7, 0x66, 0xf8, 0x08, 0x20, 0xd0, 0xe1, 0xdd, 0xe9, + 0x18, 0x23, 0x8b, 0x42, 0x03, 0xd8, 0x2c, 0xbf, 0x82, 0x42, 0x05, 0x20, + 0xf6, 0xd3, 0x0f, 0x98, 0x04, 0x28, 0x03, 0xd3, 0x00, 0xf0, 0xee, 0xf9, + 0x06, 0x20, 0xc1, 0xe1, 0x0e, 0x98, 0x03, 0x28, 0x03, 0xd3, 0x00, 0xf0, + 0xe7, 0xf9, 0x0a, 0x20, 0xba, 0xe1, 0xdd, 0xe9, 0x0c, 0x01, 0xdd, 0xe9, + 0x00, 0x23, 0xfb, 0xf7, 0x67, 0xf8, 0xfa, 0xf7, 0x29, 0xfb, 0xfa, 0xf7, + 0x99, 0xfc, 0x01, 0xf0, 0xf1, 0xfb, 0x07, 0x90, 0x11, 0x25, 0x0f, 0xf2, + 0x80, 0x56, 0x0f, 0xf2, 0xd4, 0x47, 0x28, 0xa8, 0x39, 0x46, 0xa8, 0x22, + 0xfd, 0xf7, 0x60, 0xfc, 0xd6, 0xe9, 0x00, 0x01, 0x28, 0xab, 0x01, 0x22, + 0x43, 0xf8, 0x35, 0x20, 0x00, 0x23, 0x22, 0x69, 0xd2, 0xb2, 0x00, 0x92, + 0x6d, 0x1c, 0x0a, 0x46, 0x01, 0x46, 0x28, 0xa8, 0xfd, 0xf7, 0xfe, 0xfe, + 0x15, 0x2d, 0xe8, 0xd3, 0x20, 0x46, 0xff, 0xf7, 0x09, 0xfc, 0x20, 0x46, + 0xff, 0xf7, 0x6d, 0xfd, 0x20, 0x46, 0xfd, 0xf7, 0x1e, 0xff, 0x05, 0x00, + 0x03, 0xd0, 0x00, 0xf0, 0xa2, 0xf9, 0x28, 0x46, 0x82, 0xe1, 0x00, 0x20, + 0xcd, 0xe9, 0x0c, 0x00, 0x03, 0x90, 0x00, 0x27, 0x00, 0xf0, 0xa2, 0xf9, + 0x80, 0x46, 0x02, 0x97, 0xbb, 0x46, 0xba, 0x46, 0x01, 0x25, 0x00, 0x26, + 0x63, 0xe0, 0x80, 0x88, 0xfa, 0xf7, 0x16, 0xfb, 0x80, 0x46, 0x4f, 0xf0, + 0x00, 0x09, 0x1a, 0xa8, 0x50, 0xf8, 0x29, 0x00, 0x05, 0x9a, 0x00, 0x90, + 0xd2, 0xe9, 0x08, 0x01, 0x0a, 0x46, 0x01, 0x46, 0x00, 0x98, 0xff, 0xf7, + 0xbf, 0xfa, 0x1a, 0xa9, 0x41, 0xf8, 0x29, 0x00, 0x09, 0xf1, 0x01, 0x09, + 0xb9, 0xf1, 0x03, 0x0f, 0xeb, 0xd3, 0x21, 0x46, 0x1a, 0xa8, 0xff, 0xf7, + 0xd3, 0xf9, 0x00, 0x90, 0xbd, 0xf9, 0x00, 0x10, 0xbd, 0xf9, 0x84, 0x00, + 0x40, 0x1a, 0x11, 0x90, 0xbd, 0xf9, 0x02, 0x10, 0xbd, 0xf9, 0x86, 0x00, + 0x00, 0xf0, 0x4d, 0xf9, 0xfa, 0xf7, 0xec, 0xfa, 0x03, 0x99, 0xfa, 0xf7, + 0xeb, 0xfb, 0x03, 0x90, 0x1a, 0x98, 0xff, 0xf7, 0x81, 0xfa, 0xfa, 0xf7, + 0xe3, 0xfa, 0x59, 0x46, 0xfa, 0xf7, 0xe2, 0xfb, 0x83, 0x46, 0x00, 0x98, + 0xff, 0xf7, 0x78, 0xfa, 0xfa, 0xf7, 0xda, 0xfa, 0x51, 0x46, 0xfa, 0xf7, + 0xd9, 0xfb, 0x82, 0x46, 0x21, 0x98, 0xff, 0xf7, 0x6f, 0xfa, 0xfd, 0xf7, + 0x79, 0xfd, 0x5f, 0xfa, 0x80, 0xf9, 0xdd, 0xe9, 0x11, 0x01, 0xff, 0xf7, + 0x71, 0xfa, 0x04, 0x99, 0x49, 0x88, 0x49, 0x43, 0x88, 0x42, 0x3c, 0xbf, + 0x4f, 0x45, 0x4f, 0x46, 0xdd, 0xe9, 0x0c, 0x01, 0xcd, 0xe9, 0x00, 0x01, + 0x21, 0x98, 0xff, 0xf7, 0x59, 0xfa, 0xdd, 0xe9, 0x00, 0x23, 0x00, 0x21, + 0x10, 0x18, 0x59, 0x41, 0xcd, 0xe9, 0x0c, 0x01, 0x76, 0x1c, 0x08, 0x98, + 0xc0, 0x88, 0x86, 0x42, 0x3d, 0xda, 0x00, 0xf0, 0x39, 0xf9, 0xf8, 0xf7, + 0x62, 0xf8, 0xa6, 0xf1, 0x01, 0x09, 0x60, 0xb1, 0x00, 0xf0, 0x21, 0xf9, + 0x20, 0x46, 0xfd, 0xf7, 0x96, 0xfe, 0x4e, 0x46, 0x5f, 0xea, 0x00, 0x09, + 0xea, 0xd0, 0x00, 0xf0, 0x18, 0xf9, 0x48, 0x46, 0xf8, 0xe0, 0x40, 0x46, + 0xfa, 0xf7, 0xa4, 0xfc, 0x00, 0xf0, 0x14, 0xf9, 0x00, 0x28, 0x04, 0x98, + 0x7f, 0xf4, 0x7b, 0xaf, 0x00, 0x8a, 0xad, 0xb2, 0x85, 0x42, 0x38, 0xbf, + 0x6d, 0x1c, 0x10, 0xd3, 0x04, 0x98, 0xc0, 0x88, 0xfa, 0xf7, 0x8a, 0xfa, + 0x00, 0xf0, 0xf5, 0xf8, 0x00, 0xf0, 0xf0, 0xf8, 0x00, 0xf0, 0x14, 0xf9, + 0x00, 0xf0, 0xf8, 0xf8, 0x80, 0x46, 0x02, 0x98, 0x40, 0x1c, 0x01, 0x25, + 0x02, 0x90, 0x02, 0x98, 0x14, 0x99, 0x88, 0x42, 0x03, 0xd3, 0x00, 0xf0, + 0xf0, 0xf8, 0x0d, 0x20, 0xd0, 0xe0, 0x4e, 0x46, 0xbc, 0xe7, 0x00, 0xf0, + 0xea, 0xf8, 0xdd, 0xe9, 0x0c, 0x01, 0x40, 0x1c, 0x41, 0xf1, 0x00, 0x01, + 0xfa, 0xf7, 0x3c, 0xfa, 0x01, 0x46, 0x03, 0x98, 0xfa, 0xf7, 0x76, 0xfa, + 0xfa, 0xf7, 0xa8, 0xfb, 0xb8, 0x49, 0xfa, 0xf7, 0xff, 0xfb, 0x01, 0xf0, + 0xfd, 0xfa, 0x06, 0x99, 0xc8, 0x60, 0x09, 0x98, 0x06, 0x99, 0x00, 0x68, + 0x48, 0x62, 0x06, 0x98, 0xc6, 0x68, 0x08, 0x98, 0x80, 0x88, 0xb0, 0x42, + 0x02, 0xd2, 0x00, 0xf0, 0xd7, 0xf8, 0x33, 0xe0, 0x04, 0x98, 0xb0, 0xf8, + 0x0a, 0x80, 0xb8, 0xf1, 0x00, 0x0f, 0x2f, 0xd0, 0x00, 0x89, 0xfa, 0xf7, + 0x47, 0xfa, 0x00, 0xf0, 0xb2, 0xf8, 0x00, 0xf0, 0xad, 0xf8, 0x00, 0xf0, + 0xd1, 0xf8, 0x05, 0x46, 0x40, 0x46, 0xfa, 0xf7, 0x3d, 0xfa, 0x00, 0xf0, + 0xa8, 0xf8, 0x80, 0x46, 0x30, 0x46, 0xfa, 0xf7, 0x37, 0xfa, 0x06, 0x46, + 0x09, 0x98, 0x00, 0x68, 0xff, 0xf7, 0x1c, 0xfa, 0x81, 0x46, 0x4f, 0xf0, + 0x7e, 0x50, 0x29, 0x46, 0xfa, 0xf7, 0xba, 0xfa, 0x31, 0x46, 0xfa, 0xf7, + 0xc7, 0xfb, 0x49, 0x46, 0xfa, 0xf7, 0x28, 0xfb, 0x01, 0x46, 0x09, 0x98, + 0x01, 0x60, 0x40, 0x46, 0xfa, 0xf7, 0xbe, 0xfb, 0x31, 0x46, 0xfa, 0xf7, + 0xa9, 0xfb, 0x01, 0xd2, 0x09, 0x20, 0x75, 0xe0, 0xa0, 0x68, 0x90, 0xf8, + 0x3a, 0x00, 0xa0, 0xb3, 0x01, 0x21, 0x58, 0x46, 0x01, 0xf0, 0xba, 0xfc, + 0x90, 0x49, 0xfa, 0xf7, 0xad, 0xfb, 0x06, 0x46, 0x01, 0x21, 0x50, 0x46, + 0x01, 0xf0, 0xb2, 0xfc, 0x8c, 0x49, 0xfa, 0xf7, 0xa5, 0xfb, 0x80, 0x46, + 0x30, 0x46, 0x41, 0x46, 0xfa, 0xf7, 0x90, 0xfa, 0x00, 0x21, 0xfa, 0xf7, + 0x8b, 0xfb, 0x05, 0x46, 0x04, 0xd2, 0x40, 0x46, 0x31, 0x46, 0xfa, 0xf7, + 0x87, 0xfa, 0x05, 0x46, 0x84, 0x48, 0xff, 0xf7, 0xdf, 0xf9, 0x05, 0x46, + 0x01, 0xf0, 0x90, 0xfa, 0xe1, 0x68, 0x08, 0x63, 0xa6, 0x68, 0xb0, 0x8f, + 0xfa, 0xf7, 0xec, 0xf9, 0x29, 0x46, 0xfa, 0xf7, 0x75, 0xfb, 0x06, 0xd2, + 0x96, 0xf8, 0x3b, 0x10, 0x20, 0x69, 0xfd, 0xf7, 0x1b, 0xff, 0x0e, 0x20, + 0x3c, 0xe0, 0x20, 0x46, 0xfd, 0xf7, 0x69, 0xfe, 0x0b, 0x98, 0xfe, 0xf7, + 0xfd, 0xfc, 0x06, 0x99, 0x08, 0x85, 0x06, 0x98, 0x06, 0x99, 0x40, 0x8d, + 0x09, 0x8d, 0x88, 0x42, 0x38, 0xbf, 0x08, 0x46, 0x06, 0x99, 0x48, 0x85, + 0xa0, 0x68, 0x00, 0x88, 0x40, 0x05, 0x26, 0xd5, 0x05, 0x98, 0x08, 0x9a, + 0x50, 0xf8, 0xd0, 0x1f, 0x92, 0x7e, 0x51, 0x43, 0x64, 0x22, 0x91, 0xfb, + 0xf2, 0xf1, 0x07, 0x9a, 0x91, 0x42, 0x1a, 0xd2, 0x81, 0x89, 0x02, 0x60, + 0xb9, 0x42, 0x38, 0xbf, 0x87, 0x81, 0x05, 0x98, 0x00, 0x25, 0xd0, 0xe9, + 0x08, 0x23, 0xd4, 0x30, 0xc0, 0xe9, 0x00, 0x23, 0x04, 0xeb, 0xc5, 0x00, + 0x00, 0xf1, 0x14, 0x02, 0xd2, 0xe9, 0x00, 0x01, 0x05, 0x9a, 0x02, 0xeb, + 0xc5, 0x02, 0x28, 0x32, 0x6d, 0x1c, 0xc2, 0xe9, 0x00, 0x01, 0x15, 0x2d, + 0xf0, 0xd3, 0x00, 0x20, 0x53, 0xb0, 0xbd, 0xe8, 0xf0, 0x8f, 0x40, 0x1a, + 0x12, 0x90, 0xdd, 0xe9, 0x11, 0x01, 0xff, 0xf7, 0x41, 0xb9, 0x50, 0xf8, + 0x26, 0x00, 0x13, 0x90, 0xff, 0xf7, 0x32, 0xb9, 0x54, 0x49, 0xfa, 0xf7, + 0xa3, 0xb9, 0x52, 0x49, 0xfa, 0xf7, 0xa0, 0xb9, 0xdd, 0xe9, 0x16, 0x23, + 0x38, 0x46, 0x49, 0x46, 0xfa, 0xf7, 0x76, 0xbe, 0x41, 0x46, 0xfa, 0xf7, + 0x25, 0xbb, 0x20, 0x46, 0xfd, 0xf7, 0x8f, 0xbd, 0x02, 0x46, 0x04, 0x98, + 0x81, 0x8a, 0x21, 0xa8, 0xff, 0xf7, 0x94, 0xbb, 0x04, 0x98, 0x80, 0x88, + 0xfa, 0xf7, 0x7a, 0xb9, 0x05, 0x99, 0x20, 0x69, 0xfd, 0xf7, 0x9e, 0xbb, + 0x20, 0x69, 0x07, 0x23, 0x1a, 0xaa, 0x21, 0xa9, 0xfd, 0xf7, 0xe2, 0xbc, + 0x01, 0x46, 0x3f, 0x48, 0xfa, 0xf7, 0x81, 0xbd, 0x80, 0xb5, 0x41, 0x68, + 0x02, 0x68, 0x00, 0x92, 0x0b, 0x1d, 0xb1, 0xf9, 0x02, 0x20, 0x09, 0x88, + 0x00, 0x69, 0xfb, 0xf7, 0x56, 0xf8, 0x02, 0xbd, 0x2d, 0xe9, 0xf8, 0x43, + 0x04, 0x46, 0x25, 0x69, 0x26, 0x68, 0xd4, 0xf8, 0x0c, 0x90, 0x88, 0x46, + 0xfd, 0xf7, 0x78, 0xfb, 0x00, 0x27, 0x08, 0xb9, 0x0b, 0x27, 0x30, 0xe0, + 0x00, 0x2d, 0x14, 0xbf, 0x32, 0x48, 0x33, 0x48, 0x01, 0x21, 0x01, 0x60, + 0x2a, 0x46, 0xa3, 0x68, 0x49, 0x46, 0x30, 0x46, 0xfd, 0xf7, 0x35, 0xfe, + 0xb8, 0xf1, 0x00, 0x0f, 0x86, 0xf8, 0xa1, 0x71, 0x03, 0xd1, 0xe0, 0x68, + 0xf3, 0x78, 0x42, 0x8b, 0x15, 0xe0, 0x20, 0x46, 0xff, 0xf7, 0xce, 0xff, + 0x07, 0x00, 0x03, 0xd1, 0x20, 0x68, 0x01, 0x78, 0x5a, 0x29, 0x04, 0xda, + 0xe1, 0x68, 0x00, 0x20, 0x88, 0x83, 0x03, 0x27, 0x0d, 0xe0, 0xe2, 0x68, + 0x51, 0x83, 0x40, 0x78, 0x10, 0x83, 0x01, 0x20, 0x90, 0x83, 0xf3, 0x78, + 0x32, 0x78, 0xa0, 0x68, 0x29, 0x46, 0xfd, 0xf7, 0x6f, 0xfc, 0x01, 0x20, + 0xb0, 0x70, 0x38, 0x46, 0xbd, 0xe8, 0xf2, 0x83, 0x10, 0xb5, 0x00, 0x21, + 0x1a, 0x4a, 0x20, 0xfa, 0x01, 0xf3, 0xdb, 0x07, 0x06, 0xd5, 0x4f, 0xf4, + 0xd4, 0x74, 0x04, 0xfb, 0x01, 0x24, 0x01, 0x23, 0x84, 0xf8, 0xa3, 0x31, + 0x49, 0x1c, 0x02, 0x29, 0xf1, 0xd3, 0x10, 0xbd, 0x10, 0xb5, 0x00, 0x21, + 0x11, 0x4a, 0x20, 0xfa, 0x01, 0xf3, 0xdb, 0x07, 0x06, 0xd5, 0x4f, 0xf4, + 0xd4, 0x74, 0x04, 0xfb, 0x01, 0x24, 0x00, 0x23, 0x84, 0xf8, 0xa3, 0x31, + 0x49, 0x1c, 0x02, 0x29, 0xf1, 0xd3, 0x10, 0xbd, 0xae, 0x47, 0x81, 0x3f, + 0xae, 0x47, 0x81, 0xbf, 0xcb, 0xbe, 0x00, 0x01, 0x00, 0x00, 0xa0, 0x41, + 0x00, 0x00, 0x7a, 0x44, 0x00, 0x00, 0x20, 0x41, 0x00, 0x00, 0xc8, 0x42, + 0x00, 0x00, 0xa0, 0xc1, 0x00, 0x00, 0x50, 0x59, 0x00, 0x00, 0x40, 0x59, + 0x10, 0xb2, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0xb4, 0x50, 0xf8, 0x04, 0x1b, 0x79, 0xb1, 0x02, 0x68, 0x43, 0x68, + 0x12, 0x18, 0x08, 0x30, 0xdc, 0x07, 0x44, 0xbf, 0xa9, 0xf1, 0x01, 0x04, + 0xe3, 0x18, 0x52, 0xf8, 0x04, 0x4b, 0x43, 0xf8, 0x04, 0x4b, 0x09, 0x1f, + 0xf9, 0xd1, 0xec, 0xe7, 0x10, 0xbc, 0x70, 0x47, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x28, 0x07, 0xda, 0xdf, 0xf8, 0xa0, 0x1c, 0x28, 0x22, 0x02, 0xfb, + 0x00, 0x12, 0xd2, 0xe9, 0x02, 0x01, 0x70, 0x47, 0x00, 0x20, 0x00, 0x21, + 0x70, 0x47, 0xf0, 0xb5, 0xdf, 0xf8, 0x8c, 0x3c, 0x0f, 0xf2, 0x48, 0x05, + 0x1b, 0x68, 0x4f, 0xf4, 0x7a, 0x74, 0x0a, 0x46, 0xb3, 0xfb, 0xf4, 0xf3, + 0x00, 0x21, 0x00, 0x24, 0x42, 0xf2, 0x10, 0x77, 0x15, 0xf8, 0x14, 0x60, + 0x7e, 0x43, 0x9e, 0x42, 0x0d, 0xd3, 0x05, 0xeb, 0x44, 0x04, 0x94, 0xf9, + 0x01, 0x40, 0x00, 0x2c, 0x0a, 0xd4, 0x14, 0x70, 0x03, 0x2c, 0x07, 0xbf, + 0x5a, 0x00, 0x02, 0x60, 0xe3, 0x40, 0x03, 0x60, 0x03, 0xe0, 0x64, 0x1c, + 0x05, 0x2c, 0xe9, 0xd3, 0x04, 0x21, 0x08, 0x46, 0xf0, 0xbd, 0x00, 0x00, + 0x02, 0xff, 0x04, 0x03, 0x08, 0x00, 0x10, 0x01, 0x20, 0x02, 0x00, 0x00, + 0xf8, 0xb5, 0x00, 0x24, 0x00, 0x27, 0x0f, 0xf2, 0xf4, 0x25, 0xdf, 0xf8, + 0x24, 0x6c, 0x28, 0x20, 0x78, 0x43, 0xf9, 0xb2, 0x81, 0x53, 0x80, 0x19, + 0x35, 0xf8, 0x17, 0x20, 0x42, 0x80, 0x01, 0x21, 0x80, 0xf8, 0x27, 0x10, + 0x02, 0xf1, 0x22, 0x00, 0x0e, 0x21, 0x00, 0xf0, 0x70, 0xfb, 0x7f, 0x1c, + 0x04, 0x2f, 0xec, 0xdb, 0xdf, 0xf8, 0xfc, 0x5b, 0x68, 0x89, 0xc0, 0xf3, + 0x81, 0x00, 0x80, 0xb1, 0x00, 0x22, 0x10, 0x21, 0x4f, 0xf4, 0x10, 0x70, + 0xf6, 0xf7, 0xfc, 0xfa, 0x03, 0x22, 0x32, 0x21, 0x00, 0x20, 0x00, 0xf0, + 0x36, 0xfc, 0x04, 0x46, 0x4f, 0xf4, 0x10, 0x70, 0x00, 0xf0, 0x20, 0xfc, + 0xec, 0xb9, 0xa8, 0x7a, 0x03, 0x21, 0x08, 0x42, 0x1a, 0xd0, 0x00, 0x22, + 0x10, 0x21, 0x4f, 0xf4, 0x2c, 0x70, 0xf6, 0xf7, 0xe7, 0xfa, 0x03, 0x22, + 0x32, 0x21, 0x01, 0x20, 0x00, 0xf0, 0x21, 0xfc, 0x04, 0x46, 0x4f, 0xf4, + 0x2c, 0x70, 0x00, 0xf0, 0x0b, 0xfc, 0xa8, 0x69, 0xdf, 0xf8, 0xa8, 0x2b, + 0x40, 0x08, 0x00, 0xf5, 0x43, 0x40, 0x50, 0x30, 0x00, 0x21, 0xc2, 0xe9, + 0x00, 0x01, 0xec, 0xb9, 0x68, 0x89, 0x4f, 0xf4, 0xf8, 0x71, 0x08, 0x42, + 0x18, 0xd0, 0x00, 0x22, 0x10, 0x21, 0x4f, 0xf4, 0x50, 0x70, 0xf6, 0xf7, + 0xc7, 0xfa, 0x03, 0x22, 0x4f, 0xf4, 0xfa, 0x71, 0x02, 0x20, 0x00, 0xf0, + 0x00, 0xfc, 0x04, 0x46, 0x03, 0x22, 0x4f, 0xf4, 0xfa, 0x71, 0x03, 0x20, + 0x00, 0xf0, 0xf9, 0xfb, 0x04, 0xb9, 0x04, 0x46, 0x4f, 0xf4, 0x50, 0x70, + 0x00, 0xf0, 0xe2, 0xfb, 0x20, 0x46, 0xf2, 0xbd, 0x2d, 0xe9, 0xf0, 0x47, + 0x16, 0x46, 0x86, 0xb0, 0x04, 0x46, 0x8a, 0x46, 0x35, 0x88, 0x06, 0xf1, + 0x10, 0x01, 0x02, 0xa8, 0xff, 0xf7, 0x55, 0xff, 0x00, 0x28, 0x42, 0xd1, + 0x30, 0x7c, 0x0f, 0xf6, 0x44, 0x51, 0x00, 0xf0, 0x03, 0x00, 0x80, 0x00, + 0x40, 0xf0, 0x13, 0x00, 0x30, 0x74, 0x00, 0x27, 0x4f, 0xf4, 0x7a, 0x70, + 0x51, 0xf8, 0x27, 0x20, 0xa0, 0xfb, 0x02, 0x89, 0xca, 0x45, 0x05, 0xd3, + 0x01, 0xd8, 0x44, 0x45, 0x02, 0xd3, 0x7f, 0x1c, 0x08, 0x2f, 0xf3, 0xd3, + 0x00, 0x2f, 0x18, 0xbf, 0x08, 0x2f, 0x25, 0xd0, 0xc7, 0xf1, 0x07, 0x07, + 0x02, 0x22, 0xba, 0x40, 0xd3, 0x17, 0xa4, 0xfb, 0x02, 0x89, 0x04, 0xfb, + 0x03, 0x99, 0x0a, 0xfb, 0x02, 0x99, 0xcd, 0xe9, 0x04, 0x89, 0x77, 0x74, + 0x00, 0x27, 0x0f, 0xf6, 0x64, 0x31, 0xdd, 0xe9, 0x04, 0x23, 0xcd, 0xe9, + 0x00, 0x23, 0x51, 0xf8, 0x27, 0x80, 0xa0, 0xfb, 0x08, 0x23, 0xdd, 0xe9, + 0x00, 0x89, 0x99, 0x45, 0x04, 0xd8, 0x2e, 0xbf, 0x90, 0x45, 0x7f, 0x1c, + 0x34, 0x2f, 0xee, 0xd3, 0x78, 0x1c, 0x01, 0xd0, 0x36, 0x28, 0x01, 0xd3, + 0x04, 0x20, 0x8c, 0xe0, 0x00, 0x27, 0x0f, 0xf6, 0xdc, 0x41, 0x7a, 0x5c, + 0x82, 0x42, 0x3c, 0xbf, 0x7f, 0x1c, 0x07, 0x2f, 0xf9, 0xd3, 0xc7, 0xf1, + 0x0d, 0x01, 0x41, 0xf0, 0x40, 0x01, 0xb1, 0x74, 0xa0, 0xf1, 0x1e, 0x01, + 0x05, 0x29, 0x34, 0xbf, 0xc2, 0x22, 0xc1, 0x22, 0xf2, 0x74, 0x08, 0x28, + 0x38, 0xbf, 0x04, 0x22, 0x06, 0xd3, 0x11, 0x28, 0x38, 0xbf, 0x06, 0x22, + 0x02, 0xd3, 0x07, 0x22, 0x1a, 0x28, 0x05, 0xd0, 0x08, 0x29, 0x03, 0xd3, + 0x28, 0x28, 0x01, 0xd0, 0x2c, 0x28, 0x01, 0xd3, 0x03, 0x21, 0x00, 0xe0, + 0x02, 0x21, 0x42, 0xea, 0xc1, 0x01, 0x31, 0x75, 0x0f, 0xf6, 0xa0, 0x21, + 0x41, 0x18, 0x11, 0xf8, 0x01, 0x1c, 0x01, 0xf0, 0x0f, 0x01, 0xc9, 0x00, + 0x71, 0x75, 0x1e, 0x28, 0x38, 0xbf, 0x0c, 0x21, 0x03, 0xd3, 0x23, 0x28, + 0x34, 0xbf, 0x0d, 0x21, 0x0e, 0x21, 0xb1, 0x75, 0xd4, 0x22, 0xdf, 0xf8, + 0x38, 0x1a, 0xdf, 0xf8, 0x38, 0x7a, 0x02, 0xfb, 0x05, 0x11, 0x01, 0xeb, + 0x80, 0x00, 0x00, 0x21, 0x50, 0xf8, 0x04, 0x0c, 0x0f, 0xf6, 0x20, 0x42, + 0xc6, 0xf8, 0x17, 0x00, 0x00, 0x20, 0x12, 0xf8, 0x11, 0x30, 0xa7, 0xfb, + 0x03, 0x89, 0xd1, 0x45, 0x06, 0xd8, 0x28, 0xbf, 0xa0, 0x45, 0x03, 0xd2, + 0x49, 0x1c, 0x04, 0x29, 0xf3, 0xd3, 0x02, 0xe0, 0x02, 0xeb, 0x41, 0x00, + 0x40, 0x78, 0xf0, 0x76, 0x4f, 0xf4, 0x7a, 0x71, 0x02, 0x98, 0x01, 0xfb, + 0x00, 0xf4, 0xdd, 0xe9, 0x04, 0x01, 0x00, 0xf0, 0xe9, 0xfc, 0xdd, 0xe9, + 0x04, 0x23, 0x07, 0x46, 0x04, 0xfb, 0x10, 0x20, 0xdf, 0xf8, 0xe0, 0x19, + 0xa1, 0xfb, 0x00, 0x01, 0x00, 0xf0, 0xde, 0xfc, 0x40, 0x1c, 0x40, 0x08, + 0xdf, 0xf8, 0xd4, 0x19, 0x88, 0x42, 0x06, 0xf1, 0x21, 0x01, 0x04, 0xbf, + 0x00, 0x20, 0x7f, 0x1c, 0x0f, 0x70, 0x3f, 0x04, 0x3a, 0x0e, 0x02, 0xf0, + 0x03, 0x02, 0x4a, 0x70, 0xb0, 0x77, 0x01, 0x0a, 0x00, 0x0c, 0x00, 0xf0, + 0x7f, 0x00, 0x86, 0xf8, 0x20, 0x00, 0xf1, 0x77, 0x00, 0x20, 0x06, 0xb0, + 0xbd, 0xe8, 0xf0, 0x87, 0x70, 0xb5, 0x04, 0x46, 0x0f, 0xf2, 0x50, 0x00, + 0x30, 0xf8, 0x14, 0x60, 0x4f, 0xf4, 0x96, 0x71, 0x02, 0x20, 0xf9, 0xf7, + 0x53, 0xfe, 0x00, 0x25, 0x06, 0xf1, 0x8c, 0x46, 0x30, 0x78, 0xc0, 0x07, + 0x04, 0xd5, 0x02, 0x20, 0xf9, 0xf7, 0x62, 0xfe, 0x00, 0x28, 0xf7, 0xd0, + 0x30, 0x78, 0xc0, 0x07, 0x0d, 0xd4, 0x20, 0x46, 0x00, 0xf0, 0x92, 0xf9, + 0x20, 0xb9, 0x02, 0x20, 0xf9, 0xf7, 0x56, 0xfe, 0x00, 0x28, 0xf6, 0xd0, + 0x20, 0x46, 0x00, 0xf0, 0x89, 0xf9, 0x00, 0xb1, 0x01, 0x25, 0x02, 0x20, + 0xf9, 0xf7, 0xc4, 0xfd, 0x28, 0x46, 0x70, 0xbd, 0x40, 0x02, 0xb0, 0x02, + 0x40, 0x03, 0x40, 0x03, 0x2d, 0xe9, 0xf0, 0x4d, 0x80, 0x46, 0x8a, 0x46, + 0x15, 0x46, 0xdf, 0xf8, 0x20, 0x09, 0xdf, 0xf8, 0x38, 0x29, 0x28, 0x21, + 0x01, 0xfb, 0x05, 0x06, 0x00, 0x20, 0x01, 0x23, 0x9a, 0x45, 0x04, 0xd3, + 0x01, 0xd8, 0x90, 0x45, 0x01, 0xd3, 0x02, 0x20, 0x06, 0xe0, 0x82, 0x45, + 0xdf, 0xf8, 0x1c, 0x29, 0x01, 0xd8, 0x90, 0x45, 0x00, 0xd3, 0x01, 0x20, + 0xdf, 0xf8, 0x14, 0x19, 0xdf, 0xf8, 0xf0, 0x28, 0x47, 0x18, 0x20, 0x31, + 0x05, 0xb3, 0x02, 0x2d, 0x3b, 0xd0, 0x62, 0xd2, 0x93, 0x7a, 0x12, 0x7b, + 0x08, 0x70, 0x02, 0xf0, 0x01, 0x0b, 0x3a, 0x78, 0x03, 0xf0, 0x03, 0x04, + 0x3f, 0x21, 0x4f, 0xf4, 0x01, 0x60, 0xf6, 0xf7, 0x6d, 0xf9, 0xba, 0x79, + 0x3f, 0x21, 0x40, 0xf6, 0x11, 0x00, 0xf6, 0xf7, 0x67, 0xf9, 0xfa, 0x78, + 0x3f, 0x21, 0x40, 0xf6, 0x12, 0x00, 0xf6, 0xf7, 0x61, 0xf9, 0x7a, 0x7a, + 0x3f, 0x21, 0x40, 0xf6, 0x13, 0x00, 0x2f, 0xe0, 0x50, 0x89, 0xc0, 0xf3, + 0x81, 0x04, 0x10, 0x7b, 0x3a, 0x78, 0x00, 0xf0, 0x02, 0x0b, 0x3f, 0x21, + 0x4f, 0xf4, 0xa4, 0x60, 0xf6, 0xf7, 0x50, 0xf9, 0xba, 0x79, 0x3f, 0x21, + 0x40, 0xf2, 0x21, 0x50, 0xf6, 0xf7, 0x4a, 0xf9, 0xfa, 0x78, 0x3f, 0x21, + 0x40, 0xf2, 0x22, 0x50, 0xf6, 0xf7, 0x44, 0xf9, 0x7a, 0x7a, 0x3f, 0x21, + 0x40, 0xf2, 0x23, 0x50, 0x12, 0xe0, 0x52, 0x89, 0x12, 0xf4, 0xf8, 0x72, + 0x14, 0x46, 0x18, 0xbf, 0x01, 0x24, 0x48, 0x70, 0x3f, 0x21, 0x3a, 0x7b, + 0x40, 0xf6, 0x1e, 0x00, 0xf6, 0xf7, 0x32, 0xf9, 0xfa, 0x7b, 0x4f, 0xf0, + 0x00, 0x0b, 0x3f, 0x21, 0x40, 0xf6, 0x1f, 0x00, 0xf6, 0xf7, 0x2a, 0xf9, + 0x00, 0x20, 0xc6, 0xe9, 0x02, 0x00, 0x4f, 0xf0, 0xff, 0x31, 0xdf, 0xf8, + 0x5c, 0x08, 0x18, 0xeb, 0x00, 0x02, 0x4a, 0xeb, 0x01, 0x03, 0x01, 0x21, + 0x8b, 0x42, 0xdf, 0xf8, 0x50, 0x08, 0x04, 0xd3, 0x01, 0xd8, 0x82, 0x42, + 0x01, 0xd3, 0x05, 0x20, 0x4b, 0xe0, 0x0c, 0xb9, 0x05, 0x27, 0x47, 0xe0, + 0x32, 0x46, 0x40, 0x46, 0x51, 0x46, 0xff, 0xf7, 0x5b, 0xfe, 0x07, 0x00, + 0x6e, 0xd1, 0x74, 0x88, 0xbb, 0xf1, 0x00, 0x0f, 0x3f, 0xd0, 0x01, 0x2d, + 0x1a, 0xd1, 0x80, 0x21, 0x40, 0xf2, 0x02, 0x20, 0xf6, 0xf7, 0xf6, 0xf8, + 0x01, 0x21, 0x4f, 0xf4, 0x40, 0x70, 0xf6, 0xf7, 0xf1, 0xf8, 0x10, 0x21, + 0x40, 0xf2, 0xca, 0x20, 0xf6, 0xf7, 0xec, 0xf8, 0xf2, 0x7e, 0x1f, 0x21, + 0x40, 0xf6, 0x15, 0x00, 0xf6, 0xf7, 0xf0, 0xf8, 0x40, 0x46, 0x51, 0x46, + 0x00, 0xf0, 0x52, 0xf8, 0x07, 0x46, 0x14, 0xe0, 0x80, 0x21, 0x4f, 0xf4, + 0x00, 0x70, 0xf6, 0xf7, 0xdb, 0xf8, 0x01, 0x21, 0x4f, 0xf4, 0x24, 0x70, + 0xf6, 0xf7, 0xd6, 0xf8, 0x10, 0x21, 0x40, 0xf2, 0x5a, 0x20, 0xf6, 0xf7, + 0xd1, 0xf8, 0xf2, 0x7e, 0x1f, 0x21, 0x40, 0xf2, 0x25, 0x50, 0xf6, 0xf7, + 0xd5, 0xf8, 0x04, 0xf1, 0x42, 0x00, 0x07, 0x21, 0x00, 0xf0, 0x35, 0xf9, + 0x27, 0xb9, 0xc6, 0xe9, 0x02, 0x8a, 0x28, 0x46, 0xfa, 0xf7, 0x66, 0xfe, + 0x38, 0x46, 0xbd, 0xe8, 0xf0, 0x8d, 0x00, 0x21, 0x30, 0x46, 0x00, 0xf0, + 0xaf, 0xf8, 0x28, 0x46, 0xff, 0xf7, 0xf0, 0xfe, 0x08, 0xb9, 0x07, 0x27, + 0xf2, 0xe7, 0x04, 0xf1, 0x08, 0x00, 0x80, 0xb2, 0x00, 0xf1, 0x8c, 0x40, + 0x00, 0x78, 0x00, 0xf0, 0xfd, 0x00, 0x70, 0x75, 0xe0, 0x1d, 0x80, 0xb2, + 0x00, 0xf1, 0x8c, 0x40, 0x00, 0x78, 0x30, 0x77, 0xa0, 0x1d, 0x80, 0xb2, + 0x00, 0xf1, 0x8c, 0x40, 0x01, 0x2d, 0x00, 0x78, 0x00, 0xf0, 0x7f, 0x00, + 0x70, 0x77, 0xd4, 0xd1, 0x40, 0x46, 0x51, 0x46, 0x00, 0xf0, 0x06, 0xf8, + 0x07, 0x46, 0x00, 0xf0, 0x64, 0xf8, 0xcb, 0xe7, 0x06, 0x27, 0xcf, 0xe7, + 0x2d, 0xe9, 0xf0, 0x42, 0xdf, 0xf8, 0x20, 0x47, 0xdf, 0xf8, 0x44, 0x77, + 0xd4, 0xe9, 0x00, 0x23, 0x00, 0x26, 0x84, 0x18, 0x41, 0xeb, 0x03, 0x09, + 0x01, 0x25, 0xa9, 0x45, 0x05, 0xd3, 0x01, 0xd8, 0xbc, 0x42, 0x02, 0xd3, + 0x84, 0x1a, 0x61, 0xeb, 0x03, 0x09, 0xdf, 0xf8, 0xf4, 0x56, 0x05, 0xf1, + 0x80, 0x07, 0xd7, 0xe9, 0x00, 0x01, 0x89, 0x45, 0x08, 0xbf, 0x84, 0x42, + 0x22, 0xd0, 0xc7, 0xe9, 0x00, 0x66, 0x05, 0xf1, 0x78, 0x02, 0x20, 0x46, + 0x49, 0x46, 0xff, 0xf7, 0xc1, 0xfd, 0x06, 0x00, 0x18, 0xd1, 0x00, 0x21, + 0x05, 0xf1, 0x78, 0x00, 0x00, 0xf0, 0x58, 0xf8, 0x02, 0x20, 0xff, 0xf7, + 0x99, 0xfe, 0x70, 0xb1, 0xdf, 0xf8, 0xec, 0x06, 0x81, 0x78, 0x01, 0xf0, + 0xfd, 0x01, 0x79, 0x73, 0x41, 0x78, 0x39, 0x75, 0x00, 0x78, 0xc7, 0xe9, + 0x00, 0x49, 0x00, 0xf0, 0x7f, 0x00, 0x78, 0x75, 0x00, 0xe0, 0x04, 0x26, + 0x30, 0x46, 0xbd, 0xe8, 0xf0, 0x82, 0xdf, 0xf8, 0x94, 0x06, 0x10, 0xb5, + 0xd0, 0xe9, 0x20, 0x23, 0x00, 0x24, 0x00, 0x2b, 0x08, 0xbf, 0x00, 0x2a, + 0x0b, 0xd0, 0x01, 0x21, 0x78, 0x30, 0x00, 0xf0, 0xaf, 0xf8, 0x04, 0x46, + 0x32, 0x20, 0xf9, 0xf7, 0x7d, 0xfc, 0xdf, 0xf8, 0xa8, 0x16, 0x01, 0x20, + 0x08, 0x60, 0x20, 0x46, 0x10, 0xbd, 0xdf, 0xf8, 0x9c, 0x06, 0x00, 0x68, + 0x70, 0x47, 0x38, 0xb5, 0xdf, 0xf8, 0x58, 0x26, 0x04, 0x20, 0xd2, 0xe9, + 0x16, 0x45, 0x00, 0x2d, 0x08, 0xbf, 0x00, 0x2c, 0x0b, 0xd0, 0x01, 0x21, + 0x02, 0xf1, 0x50, 0x00, 0x00, 0xf0, 0x16, 0xf8, 0x32, 0x20, 0xf9, 0xf7, + 0x61, 0xfc, 0xdf, 0xf8, 0x70, 0x16, 0x00, 0x20, 0x08, 0x60, 0x32, 0xbd, + 0x30, 0xb1, 0x01, 0x28, 0x0c, 0xbf, 0xdf, 0xf8, 0x64, 0x06, 0xdf, 0xf8, + 0x64, 0x06, 0x01, 0xe0, 0xdf, 0xf8, 0x60, 0x06, 0x00, 0x78, 0x00, 0xf0, + 0x01, 0x00, 0x70, 0x47, 0x2d, 0xe9, 0xf0, 0x41, 0x07, 0x46, 0xbc, 0x1c, + 0x88, 0x46, 0x25, 0x88, 0xb5, 0xf5, 0x10, 0x7f, 0x0c, 0xd0, 0xb5, 0xf5, + 0x2c, 0x7f, 0xa1, 0x7b, 0x14, 0xd1, 0x40, 0xf2, 0x32, 0x20, 0xf5, 0xf7, + 0xf9, 0xff, 0x62, 0x7e, 0x1f, 0x21, 0x40, 0xf6, 0x15, 0x00, 0x08, 0xe0, + 0xa1, 0x7b, 0x4f, 0xf4, 0x0c, 0x70, 0xf5, 0xf7, 0xef, 0xff, 0x62, 0x7e, + 0x1f, 0x21, 0x40, 0xf2, 0x25, 0x50, 0xf5, 0xf7, 0xf3, 0xff, 0x03, 0xe0, + 0x40, 0xf2, 0x33, 0x20, 0xf5, 0xf7, 0xe4, 0xff, 0x39, 0x46, 0x00, 0x20, + 0x00, 0xf0, 0xd3, 0xf8, 0x17, 0xf8, 0x22, 0x2f, 0xa8, 0x1c, 0x07, 0x21, + 0x80, 0xb2, 0xf5, 0xf7, 0xe3, 0xff, 0xe1, 0x7f, 0x68, 0x1c, 0x00, 0xf0, + 0x44, 0xf8, 0xe1, 0x7b, 0x05, 0xf1, 0x42, 0x00, 0x00, 0xf0, 0x3f, 0xf8, + 0x78, 0x79, 0x28, 0xb1, 0x4f, 0xf4, 0xfa, 0x60, 0xf9, 0xf7, 0x0e, 0xfc, + 0x00, 0x20, 0x78, 0x71, 0xae, 0x1d, 0xb8, 0xf1, 0x00, 0x0f, 0x05, 0xf1, + 0x08, 0x07, 0x12, 0xd1, 0x80, 0x22, 0x80, 0x21, 0xb0, 0xb2, 0xf5, 0xf7, + 0xc7, 0xff, 0x00, 0x22, 0x80, 0x21, 0xb0, 0xb2, 0xf5, 0xf7, 0xc2, 0xff, + 0x00, 0x22, 0x02, 0x21, 0xb8, 0xb2, 0xf5, 0xf7, 0xbd, 0xff, 0x01, 0x22, + 0x01, 0x21, 0x28, 0x46, 0x18, 0xe0, 0x00, 0xf0, 0x99, 0xf8, 0xf5, 0xf7, + 0xb5, 0xff, 0xe0, 0x7e, 0x40, 0xf0, 0x80, 0x01, 0xb0, 0xb2, 0xf5, 0xf7, + 0xa5, 0xff, 0xa1, 0x7e, 0xe8, 0x1d, 0x00, 0xf0, 0x10, 0xf8, 0x00, 0xf0, + 0x84, 0xf8, 0xb8, 0xb2, 0xf5, 0xf7, 0xa6, 0xff, 0x01, 0x20, 0xf9, 0xf7, + 0xdd, 0xfb, 0x00, 0x22, 0x00, 0xf0, 0x85, 0xf8, 0xf5, 0xf7, 0x9e, 0xff, + 0x00, 0x20, 0xbd, 0xe8, 0xf0, 0x81, 0x80, 0xb2, 0xf5, 0xf7, 0x8e, 0xbf, + 0x2d, 0xe9, 0xf0, 0x41, 0x06, 0x46, 0xb4, 0x1c, 0x88, 0x46, 0x25, 0x88, + 0xb5, 0xf5, 0x10, 0x7f, 0x40, 0xf6, 0x15, 0x07, 0x08, 0xd0, 0xa1, 0x7b, + 0xb5, 0xf5, 0x2c, 0x7f, 0x0c, 0xbf, 0x40, 0xf2, 0x32, 0x20, 0x40, 0xf2, + 0x33, 0x20, 0x09, 0xe0, 0xa1, 0x7b, 0x4f, 0xf4, 0x0c, 0x70, 0xf8, 0xf7, + 0x2a, 0xf9, 0x62, 0x7e, 0x1f, 0x21, 0x40, 0xf2, 0x25, 0x50, 0x04, 0xe0, + 0xf8, 0xf7, 0x23, 0xf9, 0x62, 0x7e, 0x1f, 0x21, 0x38, 0x46, 0xf8, 0xf7, + 0x45, 0xf9, 0x31, 0x46, 0x01, 0x20, 0x00, 0xf0, 0x58, 0xf8, 0x96, 0xf8, + 0x22, 0x20, 0xa8, 0x1c, 0x07, 0x21, 0x80, 0xb2, 0xf8, 0xf7, 0x3a, 0xf9, + 0xe1, 0x7f, 0x68, 0x1c, 0x80, 0xb2, 0xf8, 0xf7, 0x0e, 0xf9, 0xe1, 0x7b, + 0x05, 0xf1, 0x42, 0x00, 0x80, 0xb2, 0xf8, 0xf7, 0x08, 0xf9, 0xaf, 0x1d, + 0xb8, 0xf1, 0x00, 0x0f, 0x05, 0xf1, 0x08, 0x06, 0x12, 0xd1, 0x80, 0x22, + 0x80, 0x21, 0xb8, 0xb2, 0xf8, 0xf7, 0x24, 0xf9, 0x00, 0x22, 0x80, 0x21, + 0xb8, 0xb2, 0xf8, 0xf7, 0x1f, 0xf9, 0x00, 0x22, 0x02, 0x21, 0xb0, 0xb2, + 0xf8, 0xf7, 0x1a, 0xf9, 0x01, 0x22, 0x01, 0x21, 0x28, 0x46, 0x19, 0xe0, + 0x00, 0xf0, 0x24, 0xf8, 0xf8, 0xf7, 0x12, 0xf9, 0xe0, 0x7e, 0x40, 0xf0, + 0x80, 0x01, 0xb8, 0xb2, 0xf8, 0xf7, 0xe5, 0xf8, 0xa1, 0x7e, 0xe8, 0x1d, + 0x80, 0xb2, 0xf8, 0xf7, 0xe0, 0xf8, 0x00, 0xf0, 0x0e, 0xf8, 0xb0, 0xb2, + 0xf8, 0xf7, 0x02, 0xf9, 0x01, 0x20, 0xf9, 0xf7, 0x67, 0xfb, 0x00, 0x22, + 0x00, 0xf0, 0x0f, 0xf8, 0xf8, 0xf7, 0xfa, 0xf8, 0x04, 0x20, 0xbd, 0xe8, + 0xf0, 0x81, 0xe0, 0x7c, 0x00, 0xf0, 0x01, 0x00, 0x40, 0xf0, 0x02, 0x02, + 0x03, 0x21, 0x70, 0x47, 0x05, 0xf1, 0x13, 0x08, 0x80, 0x22, 0x80, 0x21, + 0x1f, 0xfa, 0x88, 0xf0, 0x70, 0x47, 0xb0, 0xb5, 0x88, 0xb0, 0x04, 0x46, + 0x0d, 0x46, 0x68, 0x46, 0x0f, 0xf2, 0x48, 0x61, 0x20, 0x22, 0xfc, 0xf7, + 0x3b, 0xfd, 0xa8, 0x7c, 0x8d, 0xf8, 0x01, 0x00, 0x00, 0x27, 0xe8, 0x7c, + 0x8d, 0xf8, 0x03, 0x00, 0x28, 0x7d, 0x8d, 0xf8, 0x05, 0x00, 0x68, 0x7d, + 0x8d, 0xf8, 0x07, 0x00, 0xa8, 0x7d, 0x8d, 0xf8, 0x0b, 0x00, 0xe8, 0x7d, + 0x8d, 0xf8, 0x0f, 0x00, 0x28, 0x7e, 0x8d, 0xf8, 0x11, 0x00, 0x68, 0x7e, + 0x8d, 0xf8, 0x13, 0x00, 0xa8, 0x7e, 0x8d, 0xf8, 0x15, 0x00, 0xa8, 0x7f, + 0x8d, 0xf8, 0x19, 0x00, 0xe8, 0x7f, 0x8d, 0xf8, 0x1b, 0x00, 0x95, 0xf8, + 0x20, 0x00, 0x8d, 0xf8, 0x1d, 0x00, 0x68, 0x88, 0x1d, 0xf8, 0x17, 0x10, + 0x08, 0x18, 0x69, 0x46, 0x01, 0xeb, 0x47, 0x01, 0x01, 0x2c, 0x49, 0x78, + 0x80, 0xb2, 0x02, 0xd1, 0xf8, 0xf7, 0x85, 0xf8, 0x01, 0xe0, 0xf5, 0xf7, + 0xcd, 0xfe, 0x7f, 0x1c, 0x0f, 0x2f, 0xec, 0xd3, 0x08, 0xb0, 0xb0, 0xbd, + 0x70, 0xb5, 0x04, 0x46, 0x00, 0x25, 0x0f, 0xf2, 0xe4, 0x56, 0x06, 0xeb, + 0x45, 0x00, 0x41, 0x78, 0x16, 0xf8, 0x15, 0x00, 0x00, 0x19, 0xff, 0xf7, + 0x2a, 0xff, 0x6d, 0x1c, 0x14, 0x2d, 0xf4, 0xd3, 0x70, 0xbd, 0x03, 0x46, + 0x06, 0x20, 0x04, 0x2b, 0x00, 0xdb, 0x70, 0x47, 0x10, 0xb5, 0x0f, 0xf2, + 0xe4, 0x54, 0x34, 0xf8, 0x13, 0x40, 0xa1, 0x42, 0x22, 0xbf, 0x0f, 0xf2, + 0xe0, 0x54, 0x34, 0xf8, 0x13, 0x40, 0x8c, 0x42, 0x14, 0xd3, 0x0f, 0xf2, + 0xdc, 0x54, 0x1c, 0x5d, 0xa2, 0x42, 0x22, 0xbf, 0x0f, 0xf2, 0xd4, 0x54, + 0x1c, 0x5d, 0x94, 0x42, 0x0a, 0xd3, 0xcd, 0x48, 0x28, 0x24, 0x04, 0xfb, + 0x03, 0x00, 0x00, 0xf1, 0x24, 0x03, 0x19, 0x80, 0x9a, 0x70, 0xbd, 0xe8, + 0x10, 0x40, 0x0b, 0xe0, 0x10, 0xbd, 0x10, 0xb5, 0xc6, 0x4b, 0x28, 0x24, + 0x04, 0xfb, 0x00, 0x30, 0x30, 0xf8, 0x24, 0x3f, 0x0b, 0x80, 0x80, 0x78, + 0x10, 0x70, 0x10, 0xbd, 0x2d, 0xe9, 0xf0, 0x4f, 0x04, 0x46, 0x89, 0xb0, + 0x20, 0x78, 0x0f, 0xf2, 0x98, 0x58, 0x0f, 0xf2, 0x80, 0x39, 0x07, 0x90, + 0x04, 0xf1, 0x10, 0x01, 0x06, 0xa8, 0xff, 0xf7, 0x2e, 0xfb, 0xc0, 0xb2, + 0x00, 0x25, 0x00, 0x28, 0x55, 0xd1, 0x59, 0xf8, 0x25, 0x00, 0x06, 0x99, + 0xb0, 0xfb, 0xf1, 0xfb, 0x0f, 0xf2, 0x74, 0x40, 0x30, 0xf8, 0x15, 0xa0, + 0x0f, 0xf2, 0x18, 0x30, 0x00, 0x68, 0x03, 0x90, 0x00, 0x27, 0x03, 0xa8, + 0x02, 0x90, 0x08, 0xeb, 0x87, 0x06, 0x04, 0xa8, 0x01, 0x90, 0xcd, 0xf8, + 0x00, 0xa0, 0x72, 0x78, 0x31, 0x78, 0x5b, 0x46, 0x20, 0x46, 0x00, 0xf0, + 0x3d, 0xf8, 0xf1, 0x78, 0x01, 0x29, 0x05, 0xd1, 0xbd, 0xf8, 0x0c, 0x10, + 0xb2, 0x78, 0x91, 0x42, 0x07, 0xd1, 0x09, 0xe0, 0x02, 0x29, 0x02, 0xbf, + 0xbd, 0xf8, 0x0e, 0x10, 0xb2, 0x78, 0x91, 0x42, 0x02, 0xd0, 0x7f, 0x1c, + 0x04, 0x2f, 0xde, 0xd3, 0x10, 0xbb, 0x07, 0x9a, 0xa2, 0x49, 0xd4, 0x23, + 0x03, 0xfb, 0x02, 0x11, 0x9d, 0xf8, 0x15, 0x20, 0x01, 0xeb, 0x85, 0x01, + 0x02, 0xf0, 0x3f, 0x02, 0x0a, 0x70, 0x9d, 0xf8, 0x10, 0x30, 0x9d, 0xf8, + 0x11, 0x20, 0x03, 0xf0, 0x0f, 0x03, 0x43, 0xea, 0x02, 0x12, 0x4a, 0x70, + 0x9d, 0xf8, 0x12, 0x30, 0x9d, 0xf8, 0x13, 0x20, 0x03, 0xf0, 0x0f, 0x03, + 0x43, 0xea, 0x02, 0x12, 0x8a, 0x70, 0x9d, 0xf8, 0x14, 0x20, 0x02, 0xf0, + 0x0f, 0x02, 0xca, 0x70, 0x6d, 0x1c, 0x35, 0x2d, 0xa7, 0xd3, 0x09, 0xb0, + 0xbd, 0xe8, 0xf0, 0x8f, 0x2d, 0xe9, 0xfe, 0x4f, 0x9c, 0xb0, 0x04, 0x46, + 0x04, 0xa8, 0x28, 0x21, 0xfa, 0xf7, 0x7e, 0xfb, 0x12, 0xa8, 0x28, 0x21, + 0xfa, 0xf7, 0x7a, 0xfb, 0x04, 0xf1, 0x24, 0x00, 0x4f, 0xf4, 0x7a, 0x72, + 0x01, 0x88, 0x0f, 0xf2, 0x6c, 0x3b, 0x51, 0x43, 0x93, 0x4a, 0xa2, 0xfb, + 0x01, 0x23, 0x12, 0x0c, 0x42, 0xea, 0x03, 0x42, 0x1b, 0x0c, 0xcd, 0xe9, + 0x00, 0x23, 0x84, 0x78, 0xdd, 0xe9, 0x00, 0x01, 0x00, 0x23, 0x22, 0x46, + 0xfa, 0xf7, 0x22, 0xf8, 0xcd, 0xe9, 0x10, 0x01, 0x4f, 0xf0, 0x00, 0x09, + 0xdd, 0xe9, 0x00, 0x01, 0xa4, 0xfb, 0x00, 0x23, 0x04, 0xfb, 0x01, 0x33, + 0xcd, 0xe9, 0x02, 0x23, 0xdd, 0xe9, 0x02, 0x01, 0x89, 0x00, 0x41, 0xea, + 0x90, 0x71, 0x80, 0x00, 0xcd, 0xe9, 0x0e, 0x01, 0xca, 0x46, 0x3f, 0x27, + 0x0c, 0x97, 0xdd, 0xe9, 0x00, 0x45, 0x1e, 0x9a, 0x28, 0x9b, 0xa2, 0xfb, + 0x04, 0x01, 0x02, 0xfb, 0x05, 0x11, 0x3a, 0x46, 0x5a, 0x43, 0x00, 0xf0, + 0xce, 0xf8, 0xdd, 0xe9, 0x10, 0x45, 0x0a, 0x90, 0x02, 0x46, 0xa2, 0xfb, + 0x04, 0x68, 0x02, 0xfb, 0x05, 0x88, 0xcd, 0xe9, 0x04, 0x68, 0x14, 0x46, + 0x50, 0x08, 0xdd, 0xe9, 0x02, 0x23, 0xa2, 0xfb, 0x04, 0x68, 0x03, 0xfb, + 0x04, 0x88, 0xdd, 0xe9, 0x04, 0x23, 0xb2, 0x1a, 0x68, 0xeb, 0x03, 0x03, + 0xcd, 0xe9, 0x06, 0x23, 0x0b, 0x90, 0xdd, 0xe9, 0x0e, 0x23, 0xa0, 0xfb, + 0x02, 0x45, 0x00, 0xfb, 0x03, 0x55, 0xcd, 0xe9, 0x08, 0x45, 0x00, 0x22, + 0x04, 0xab, 0x0a, 0xac, 0x00, 0x25, 0x0b, 0xeb, 0x05, 0x1e, 0xd3, 0xe9, + 0x00, 0x01, 0xde, 0xe9, 0x02, 0x68, 0x41, 0x45, 0x0c, 0xd3, 0x01, 0xd8, + 0xb0, 0x42, 0x09, 0xd3, 0x0b, 0xeb, 0x05, 0x1c, 0xdc, 0xe9, 0x00, 0x68, + 0x88, 0x45, 0x03, 0xd3, 0x01, 0xd8, 0x86, 0x42, 0x00, 0xd3, 0x52, 0x1c, + 0x08, 0x33, 0x6d, 0x1c, 0x03, 0x2d, 0xe6, 0xd3, 0x00, 0x20, 0x0f, 0xf2, + 0xb0, 0x23, 0x21, 0x68, 0x53, 0xf8, 0x30, 0x30, 0x99, 0x42, 0x21, 0xbf, + 0x0f, 0xf2, 0xa0, 0x23, 0x03, 0xeb, 0xc0, 0x03, 0x5b, 0x68, 0x8b, 0x42, + 0x28, 0xbf, 0x52, 0x1c, 0x24, 0x1d, 0x40, 0x1c, 0x02, 0x28, 0xec, 0xd3, + 0xad, 0xf8, 0x34, 0x20, 0x92, 0xb2, 0xbd, 0xf9, 0x70, 0x10, 0x8a, 0x42, + 0x18, 0xda, 0xbd, 0xf9, 0x74, 0x10, 0x8a, 0x42, 0x07, 0xdb, 0x91, 0x46, + 0x12, 0xa8, 0x04, 0xa9, 0x28, 0x22, 0xfc, 0xf7, 0xa5, 0xfb, 0xad, 0xf8, + 0x6e, 0x90, 0x7f, 0x1e, 0x01, 0x2f, 0x89, 0xda, 0xbd, 0xf9, 0x74, 0x00, + 0x81, 0x45, 0x0d, 0xdb, 0x29, 0x99, 0x12, 0xa8, 0x00, 0xf0, 0x10, 0xf8, + 0x1b, 0x98, 0x04, 0xe0, 0x29, 0x99, 0x04, 0xa8, 0x00, 0xf0, 0x0a, 0xf8, + 0x0d, 0x98, 0x2a, 0x99, 0x08, 0x60, 0x01, 0xe0, 0x4f, 0xf0, 0x05, 0x0a, + 0x50, 0x46, 0x1f, 0xb0, 0xbd, 0xe8, 0xf0, 0x8f, 0x2d, 0xe9, 0xf0, 0x43, + 0x00, 0xf1, 0x18, 0x04, 0x05, 0x46, 0x00, 0x6a, 0x0f, 0xf2, 0x20, 0x29, + 0x48, 0x71, 0xce, 0x1c, 0x88, 0x46, 0x00, 0x27, 0x09, 0xeb, 0xc7, 0x00, + 0x22, 0x68, 0x41, 0x68, 0x91, 0x42, 0x38, 0xbf, 0x0f, 0x20, 0x0d, 0xd3, + 0x59, 0xf8, 0x37, 0x10, 0x91, 0x42, 0x28, 0xbf, 0x00, 0x20, 0x07, 0xd2, + 0x40, 0x68, 0x41, 0x0c, 0xc0, 0x03, 0x00, 0xf0, 0x2e, 0xf8, 0xc0, 0xf5, + 0x04, 0x20, 0xc0, 0x0b, 0x24, 0x1d, 0x7f, 0x1c, 0x02, 0x2f, 0x06, 0xf8, + 0x01, 0x0b, 0xe3, 0xd3, 0x00, 0x24, 0x0f, 0xf2, 0xac, 0x16, 0x06, 0xeb, + 0x04, 0x1e, 0xd5, 0xe9, 0x00, 0x23, 0xde, 0xe9, 0x02, 0x01, 0x8b, 0x42, + 0x03, 0xd8, 0x2c, 0xbf, 0x82, 0x42, 0x0f, 0x20, 0x0c, 0xd3, 0x06, 0xeb, + 0x04, 0x1c, 0xdc, 0xe9, 0x00, 0x01, 0x8b, 0x42, 0x04, 0xd3, 0x01, 0xd8, + 0x82, 0x42, 0x01, 0xd3, 0x00, 0x20, 0x01, 0xe0, 0xf9, 0xf7, 0x3a, 0xff, + 0x08, 0x35, 0x64, 0x1c, 0x03, 0x2c, 0x08, 0xf8, 0x01, 0x0b, 0xe0, 0xd3, + 0xbd, 0xe8, 0xf0, 0x83, 0x22, 0x46, 0x00, 0x23, 0xf9, 0xf7, 0x2e, 0xbf, + 0x68, 0xee, 0x00, 0x20, 0x78, 0x29, 0x00, 0x20, 0x48, 0xf3, 0x00, 0x20, + 0x7c, 0xdf, 0x00, 0x20, 0x80, 0x96, 0x98, 0x00, 0x00, 0xf0, 0xff, 0x00, + 0x00, 0xf8, 0x7f, 0x00, 0x00, 0xf2, 0x05, 0x2a, 0x00, 0x5e, 0xd0, 0xb2, + 0x4c, 0x29, 0x00, 0x20, 0x80, 0x18, 0x42, 0xfd, 0x81, 0xb5, 0xd8, 0x68, + 0x01, 0x9d, 0x96, 0x6b, 0x46, 0x03, 0x00, 0x46, 0x78, 0xf3, 0x00, 0x20, + 0xc7, 0x02, 0x00, 0x46, 0x57, 0x03, 0x00, 0x46, 0x57, 0x02, 0x00, 0x46, + 0x7e, 0x48, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0e, 0x0d, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0d, 0x0c, 0x0c, 0x0d, 0x0c, 0x0c, + 0x0c, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0c, 0x0c, 0x0c, 0x0b, 0x0b, 0x0c, + 0x0b, 0x0b, 0x0b, 0x0c, 0x0d, 0x0f, 0x0f, 0x0f, 0x0e, 0x0e, 0x0e, 0x0e, + 0x0e, 0x00, 0x00, 0x00, 0x48, 0x56, 0xc0, 0x00, 0x08, 0xd8, 0xba, 0x00, + 0xd0, 0xab, 0xb5, 0x00, 0xa0, 0xd1, 0xb0, 0x00, 0xc0, 0x3d, 0xac, 0x00, + 0x18, 0xf4, 0xa7, 0x00, 0xf0, 0xe8, 0xa3, 0x00, 0x60, 0x18, 0xa0, 0x00, + 0x50, 0x86, 0x9c, 0x00, 0x20, 0x23, 0x99, 0x00, 0xd8, 0xf5, 0x95, 0x00, + 0x7c, 0xf5, 0x92, 0x00, 0xb4, 0x1f, 0x90, 0x00, 0x28, 0x72, 0x8d, 0x00, + 0xf0, 0xe8, 0x8a, 0x00, 0x7c, 0x82, 0x88, 0x00, 0x48, 0x3b, 0x86, 0x00, + 0xc4, 0x11, 0x84, 0x00, 0x98, 0x03, 0x82, 0x00, 0x6c, 0x0e, 0x80, 0x00, + 0x4c, 0x30, 0x7e, 0x00, 0x0c, 0x68, 0x7c, 0x00, 0xb8, 0xb3, 0x7a, 0x00, + 0xc0, 0x11, 0x79, 0x00, 0xf8, 0x80, 0x77, 0x00, 0xd0, 0xff, 0x75, 0x00, + 0x80, 0x8d, 0x74, 0x00, 0xdc, 0x28, 0x73, 0x00, 0xb8, 0xd0, 0x71, 0x00, + 0xb0, 0x84, 0x70, 0x00, 0xfc, 0x43, 0x6f, 0x00, 0x70, 0x0d, 0x6e, 0x00, + 0x0c, 0xe1, 0x6c, 0x00, 0x08, 0xbe, 0x6b, 0x00, 0x9c, 0xa3, 0x6a, 0x00, + 0xc8, 0x91, 0x69, 0x00, 0x28, 0x88, 0x68, 0x00, 0x58, 0x86, 0x67, 0x00, + 0xf4, 0x8b, 0x66, 0x00, 0x98, 0x98, 0x65, 0x00, 0xa8, 0xac, 0x64, 0x00, + 0xc0, 0xc7, 0x63, 0x00, 0x7c, 0xe9, 0x62, 0x00, 0x78, 0x11, 0x62, 0x00, + 0x18, 0x40, 0x61, 0x00, 0xf8, 0x74, 0x60, 0x00, 0xb4, 0xaf, 0x5f, 0x00, + 0xb0, 0xf0, 0x5e, 0x00, 0x24, 0x37, 0x5e, 0x00, 0x10, 0x83, 0x5d, 0x00, + 0x10, 0xd4, 0x5c, 0x00, 0x24, 0x2a, 0x5c, 0x00, 0x84, 0x84, 0x5b, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x05, 0x09, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x95, 0x8d, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xaf, 0x2b, + 0x78, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xba, 0x82, 0x07, 0x00, 0x00, 0x00, + 0x00, 0x80, 0xf1, 0x42, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x18, 0x2f, 0xf4, + 0x04, 0x00, 0x00, 0x00, 0x1c, 0x02, 0x00, 0x00, 0xdb, 0x21, 0x00, 0x00, + 0xae, 0x00, 0x00, 0x00, 0xe2, 0x0a, 0x00, 0x00, 0x6e, 0x46, 0xb6, 0x3f, + 0xee, 0x39, 0xf8, 0x34, 0xac, 0x30, 0xe2, 0x2c, 0x90, 0x29, 0x9d, 0x26, + 0xff, 0x23, 0xa8, 0x21, 0x8e, 0x1f, 0xa9, 0x1d, 0xf3, 0x1b, 0x65, 0x1a, + 0xfb, 0x18, 0xb0, 0x17, 0xa8, 0x17, 0x83, 0x16, 0x75, 0x15, 0x7c, 0x14, + 0x95, 0x13, 0xbf, 0x12, 0xf8, 0x11, 0x2d, 0x12, 0x77, 0x11, 0xc2, 0x11, + 0x18, 0x11, 0x79, 0x10, 0xe4, 0x0f, 0xa7, 0x13, 0xfd, 0x12, 0x5c, 0x12, + 0xc3, 0x11, 0x33, 0x11, 0x02, 0x0d, 0x60, 0x0d, 0xfa, 0x0c, 0x99, 0x0c, + 0x3c, 0x0c, 0x38, 0x10, 0xc6, 0x0f, 0x58, 0x0f, 0xf0, 0x0e, 0x8d, 0x0f, + 0x27, 0x0f, 0xc6, 0x0e, 0x69, 0x0e, 0x0f, 0x0e, 0xbe, 0x0e, 0x66, 0x0e, + 0x11, 0x0e, 0xc0, 0x0d, 0x72, 0x0d, 0x00, 0x00, 0x1e, 0x0b, 0x50, 0x0a, + 0x78, 0x0a, 0xa0, 0x05, 0xb0, 0xb3, 0x00, 0x00, 0x36, 0x6e, 0x01, 0x00, + 0x6c, 0xdc, 0x02, 0x00, 0xd8, 0xb8, 0x05, 0x00, 0xb0, 0x71, 0x0b, 0x00, + 0x60, 0xe3, 0x16, 0x00, 0xc0, 0xc6, 0x2d, 0x00, 0x20, 0x14, 0x5d, 0x00, + 0x10, 0x17, 0x19, 0x23, 0x27, 0x2b, 0x30, 0x00, 0x0a, 0x00, 0x09, 0x00, + 0x12, 0x00, 0x08, 0x00, 0x15, 0x00, 0x21, 0x00, 0x20, 0x70, 0x0b, 0x00, + 0x0e, 0x00, 0x0f, 0x00, 0x10, 0x00, 0x0d, 0x84, 0x03, 0x00, 0x04, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x1d, 0x2b, 0x1c, 0x0f, 0x1d, 0x6b, + 0x1d, 0x2a, 0x1c, 0x0f, 0x1d, 0x6a, 0x1d, 0x29, 0x1c, 0x0f, 0x1d, 0x69, + 0x1d, 0x28, 0x1c, 0x00, 0x1d, 0x68, 0x1d, 0x27, 0x1c, 0x00, 0x1d, 0x67, + 0x1d, 0x26, 0x1c, 0x00, 0x1d, 0x66, 0x1d, 0x20, 0x32, 0x00, 0x32, 0x00, + 0xf4, 0x01, 0xf4, 0x01, 0xee, 0x02, 0xee, 0x02, 0xee, 0x02, 0xee, 0x02, + 0x03, 0x03, 0x03, 0x03, 0x0f, 0x0f, 0x0f, 0x0f, 0x05, 0x02, 0x05, 0x01, + 0x04, 0x04, 0x04, 0x01, 0x04, 0x03, 0x03, 0x02, 0x03, 0x02, 0x00, 0x00, + 0x03, 0x49, 0x09, 0x68, 0xc1, 0x40, 0xc8, 0x07, 0x01, 0xd4, 0x01, 0x21, + 0x03, 0xe0, 0x70, 0x47, 0x84, 0xf3, 0x00, 0x20, 0x00, 0x21, 0x40, 0xf6, + 0x01, 0x50, 0xf5, 0xf7, 0x9b, 0xbb, 0x00, 0x00, 0x70, 0xb5, 0x00, 0x20, + 0x0f, 0xf2, 0x74, 0x21, 0x11, 0xf8, 0x10, 0x30, 0x7b, 0x4c, 0x63, 0x43, + 0x7b, 0x4c, 0x24, 0x68, 0xa3, 0x42, 0x24, 0xbf, 0x01, 0xeb, 0x40, 0x02, + 0x52, 0x78, 0x40, 0x1c, 0x04, 0x28, 0xf1, 0xd3, 0xd2, 0xb2, 0x03, 0x21, + 0x4f, 0xf4, 0xbb, 0x70, 0xf5, 0xf7, 0x8c, 0xfb, 0x00, 0x24, 0x0f, 0xf2, + 0x50, 0x25, 0x0f, 0xf2, 0x60, 0x26, 0xa1, 0x5d, 0x35, 0xf8, 0x14, 0x00, + 0xf5, 0xf7, 0x78, 0xfb, 0x64, 0x1c, 0x09, 0x2c, 0xf7, 0xd3, 0x01, 0x20, + 0x70, 0xbd, 0x30, 0xb5, 0x14, 0x46, 0x6c, 0x4a, 0x0f, 0xf2, 0x18, 0x23, + 0x12, 0x78, 0x0f, 0xf2, 0x48, 0x25, 0xe3, 0x5c, 0x02, 0xf0, 0x03, 0x02, + 0x52, 0x5d, 0xd2, 0x18, 0x52, 0xb2, 0x00, 0x2a, 0x02, 0xd4, 0xf9, 0xf7, + 0x99, 0xfc, 0x02, 0xe0, 0x52, 0x42, 0xf5, 0xf7, 0x63, 0xfd, 0x07, 0x2c, + 0x08, 0xbf, 0x03, 0x22, 0x02, 0xd0, 0x08, 0x2c, 0x05, 0xd1, 0x05, 0x22, + 0xbd, 0xe8, 0x30, 0x40, 0x00, 0x23, 0xf9, 0xf7, 0x7f, 0xbd, 0x30, 0xbd, + 0x23, 0x29, 0x05, 0xd3, 0x02, 0xd8, 0xb0, 0xf1, 0xf1, 0x4f, 0x01, 0xd3, + 0x3f, 0x20, 0x0d, 0xe0, 0x40, 0x0b, 0x40, 0xea, 0xc1, 0x40, 0x50, 0x21, + 0x48, 0x43, 0x40, 0xf2, 0xcb, 0x21, 0xb0, 0xfb, 0xf1, 0xf0, 0x00, 0xf5, + 0x80, 0x40, 0xc0, 0x0b, 0x18, 0xbf, 0x40, 0x1e, 0xc0, 0xb2, 0x70, 0x47, + 0xf8, 0xb5, 0x06, 0x46, 0x4d, 0x48, 0x14, 0x46, 0x02, 0x68, 0x1d, 0x46, + 0xa2, 0xfb, 0x04, 0x01, 0x02, 0xfb, 0x05, 0x11, 0x00, 0x0f, 0x40, 0xea, + 0x01, 0x10, 0x09, 0x0f, 0x00, 0xf0, 0x98, 0xf8, 0x07, 0x00, 0x01, 0xd5, + 0x00, 0x20, 0xf2, 0xbd, 0x3a, 0x46, 0x20, 0x46, 0x29, 0x46, 0xff, 0xf7, + 0xac, 0xff, 0x05, 0x2e, 0x04, 0x46, 0x0d, 0x46, 0x03, 0xda, 0x0f, 0xf2, + 0xa8, 0x10, 0x31, 0x5c, 0x09, 0xb9, 0x40, 0x48, 0x01, 0x78, 0x40, 0xf2, + 0x0b, 0x20, 0xf5, 0xf7, 0x11, 0xfb, 0x0f, 0xf2, 0x50, 0x10, 0x39, 0x5c, + 0x40, 0xf2, 0x81, 0x10, 0xf5, 0xf7, 0x0a, 0xfb, 0x20, 0x46, 0x29, 0x46, + 0xff, 0xf7, 0xb6, 0xff, 0x02, 0x46, 0x3f, 0x21, 0x40, 0xf2, 0x77, 0x10, + 0xf5, 0xf7, 0x0a, 0xfb, 0x22, 0x0f, 0x42, 0xea, 0x05, 0x12, 0xd1, 0xb2, + 0x40, 0xf2, 0x75, 0x10, 0xf5, 0xf7, 0xf8, 0xfa, 0x6f, 0xf0, 0x70, 0x40, + 0x20, 0x40, 0x4f, 0xf4, 0xff, 0x12, 0xa2, 0xfb, 0x00, 0x45, 0x24, 0x0f, + 0x44, 0xea, 0x05, 0x14, 0xe1, 0xb2, 0x4f, 0xf4, 0xba, 0x70, 0x2d, 0x0f, + 0xf5, 0xf7, 0xe8, 0xfa, 0x24, 0x0a, 0x44, 0xea, 0x05, 0x64, 0xe1, 0xb2, + 0x40, 0xf2, 0x73, 0x10, 0xf5, 0xf7, 0xe0, 0xfa, 0x21, 0x0a, 0x4f, 0xf4, + 0xb9, 0x70, 0xf5, 0xf7, 0xdb, 0xfa, 0x01, 0x21, 0x40, 0xf2, 0x7f, 0x10, + 0xf5, 0xf7, 0xd6, 0xfa, 0x01, 0x20, 0xf2, 0xbd, 0x10, 0xb5, 0x05, 0x21, + 0x4f, 0xf4, 0xb8, 0x70, 0xf5, 0xf7, 0xce, 0xfa, 0x01, 0x21, 0x4f, 0xf4, + 0xb8, 0x70, 0xf5, 0xf7, 0xc9, 0xfa, 0x1a, 0x49, 0x01, 0x20, 0xf8, 0xf7, + 0x5d, 0xff, 0xf6, 0xf7, 0x98, 0xfd, 0x50, 0xb9, 0x17, 0x48, 0x00, 0x78, + 0x00, 0x06, 0x01, 0xd5, 0x01, 0x24, 0x05, 0xe0, 0x01, 0x20, 0xf8, 0xf7, + 0x69, 0xff, 0x00, 0x28, 0xf1, 0xd0, 0x00, 0x24, 0x01, 0x20, 0xf8, 0xf7, + 0xdb, 0xfe, 0x20, 0x46, 0x10, 0xbd, 0x10, 0xb5, 0x04, 0x46, 0x00, 0x20, + 0x10, 0x2b, 0x0e, 0xd2, 0x1b, 0x07, 0x43, 0xea, 0x12, 0x11, 0x10, 0x07, + 0x06, 0x4a, 0x12, 0x68, 0x00, 0x23, 0xf9, 0xf7, 0xd1, 0xfc, 0x02, 0x46, + 0x20, 0x46, 0xbd, 0xe8, 0x10, 0x40, 0x0b, 0x46, 0x64, 0xe7, 0x10, 0xbd, + 0x80, 0x96, 0x98, 0x00, 0x78, 0x29, 0x00, 0x20, 0x76, 0x01, 0x00, 0x46, + 0x0b, 0x02, 0x00, 0x46, 0x40, 0x42, 0x0f, 0x00, 0x7f, 0x01, 0x00, 0x46, + 0x10, 0xb5, 0x4f, 0xf4, 0x7a, 0x72, 0x00, 0x23, 0xf9, 0xf7, 0xb8, 0xfc, + 0x4f, 0xf0, 0xff, 0x34, 0x00, 0x21, 0x0f, 0xf2, 0x18, 0x02, 0x52, 0xf8, + 0x21, 0x30, 0x83, 0x42, 0x01, 0xd3, 0x0c, 0x46, 0x02, 0xe0, 0x49, 0x1c, + 0x09, 0x29, 0xf6, 0xd3, 0x20, 0x46, 0x10, 0xbd, 0xf4, 0xef, 0x02, 0x00, + 0xe8, 0xdf, 0x05, 0x00, 0xd0, 0xbf, 0x0b, 0x00, 0xa0, 0x7f, 0x17, 0x00, + 0x98, 0x9e, 0x19, 0x00, 0x38, 0x07, 0x20, 0x00, 0x80, 0xb9, 0x2a, 0x00, + 0xe0, 0x7e, 0x46, 0x00, 0x60, 0x56, 0x6c, 0x00, 0x00, 0x01, 0x02, 0x03, + 0x04, 0x14, 0x24, 0x05, 0x05, 0x00, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00, + 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x08, 0x00, + 0x10, 0x01, 0x64, 0x02, 0x7d, 0x01, 0x7e, 0x01, 0x7e, 0x01, 0x7e, 0x01, + 0x79, 0x01, 0x7a, 0x01, 0x7b, 0x01, 0x7c, 0x01, 0x7f, 0x01, 0x00, 0x00, + 0x86, 0x08, 0x01, 0x05, 0xe5, 0x5b, 0x35, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x02, 0xff, 0x00, 0x54, 0x2c, 0x04, 0xf8, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x0d, 0xd2, 0x01, 0x0e, 0x7f, 0x39, 0x0a, 0xd4, 0xd1, 0xf1, + 0x1f, 0x01, 0x04, 0xd4, 0xc0, 0x01, 0x40, 0xf0, 0x00, 0x40, 0xc8, 0x40, + 0x70, 0x47, 0x7f, 0xf0, 0x00, 0x00, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, + 0x03, 0x48, 0x00, 0x78, 0x18, 0xb9, 0x03, 0x48, 0x00, 0x78, 0x00, 0xf0, + 0x07, 0x00, 0x70, 0x47, 0x88, 0x02, 0x00, 0x20, 0x04, 0x00, 0x00, 0x46, + 0x2d, 0xe9, 0xf8, 0x43, 0x88, 0x4c, 0x4f, 0xf4, 0x94, 0x71, 0x04, 0xf1, + 0x44, 0x00, 0xf9, 0xf7, 0x89, 0xff, 0x00, 0x25, 0x85, 0x4e, 0x0f, 0xf2, + 0x2c, 0x28, 0x85, 0x4f, 0x4f, 0xf4, 0xd4, 0x79, 0x84, 0x48, 0x09, 0xfb, + 0x05, 0x00, 0x49, 0x46, 0x88, 0x30, 0xf5, 0xf7, 0xcf, 0xf9, 0x94, 0x20, + 0x00, 0xfb, 0x05, 0x40, 0x4f, 0xf4, 0x7a, 0x71, 0x01, 0x65, 0x79, 0x69, + 0x41, 0x65, 0x39, 0x6c, 0x81, 0x65, 0x00, 0x20, 0x58, 0xf8, 0x25, 0x10, + 0x08, 0x60, 0x04, 0x20, 0xa8, 0x55, 0x6d, 0x1c, 0x02, 0x2d, 0xe5, 0xd3, + 0xbd, 0xe8, 0xf1, 0x83, 0x2d, 0xe9, 0xf8, 0x43, 0x74, 0x48, 0xdf, 0xf8, + 0xc8, 0x81, 0x80, 0x7a, 0x0c, 0x46, 0x00, 0x25, 0x00, 0xf0, 0x03, 0x09, + 0x00, 0x27, 0x29, 0xfa, 0x07, 0xf0, 0xc0, 0x07, 0x35, 0xd5, 0x08, 0xf5, + 0xb6, 0x70, 0x60, 0x60, 0x4f, 0xf4, 0xd4, 0x71, 0x6c, 0x48, 0x27, 0x61, + 0x01, 0xfb, 0x07, 0x00, 0xc4, 0xf8, 0x08, 0x80, 0x88, 0x30, 0x20, 0x60, + 0x94, 0x21, 0x08, 0xf1, 0x44, 0x00, 0x01, 0xfb, 0x07, 0x00, 0xe0, 0x60, + 0xf4, 0xf7, 0x74, 0xf8, 0xe0, 0x68, 0x00, 0x21, 0x41, 0x60, 0x01, 0x60, + 0x81, 0x60, 0xc1, 0x62, 0x4f, 0xf4, 0x7a, 0x71, 0xc1, 0x60, 0xf4, 0xf7, + 0x7e, 0xf8, 0x20, 0x46, 0xfc, 0xf7, 0xd7, 0xfa, 0x06, 0x00, 0x04, 0xd1, + 0x01, 0x21, 0x20, 0x46, 0xfe, 0xf7, 0x80, 0xfd, 0x06, 0x46, 0x20, 0x46, + 0xfc, 0xf7, 0xe7, 0xfa, 0xe0, 0x68, 0x16, 0xb9, 0x01, 0x21, 0xc1, 0x83, + 0x03, 0xe0, 0x00, 0x21, 0xc1, 0x83, 0x06, 0x60, 0x35, 0x46, 0x7f, 0x1c, + 0x02, 0x2f, 0xc2, 0xd3, 0x28, 0x46, 0xbd, 0xe8, 0xf2, 0x83, 0x70, 0x47, + 0x00, 0x28, 0x0c, 0xbf, 0x50, 0x49, 0x51, 0x49, 0x00, 0x22, 0x08, 0x68, + 0x0a, 0x60, 0x70, 0x47, 0x00, 0x28, 0x0c, 0xbf, 0x4c, 0x48, 0x4d, 0x48, + 0x01, 0x60, 0x70, 0x47, 0x2d, 0xe9, 0xf0, 0x47, 0x48, 0x4e, 0xdf, 0xf8, + 0x14, 0xa1, 0x0c, 0x46, 0x80, 0x46, 0x44, 0x20, 0x00, 0xfb, 0x08, 0xf5, + 0xa8, 0x19, 0xa0, 0x60, 0xc4, 0xf8, 0x10, 0x80, 0x4f, 0xf4, 0xd4, 0x70, + 0x00, 0xfb, 0x08, 0x60, 0x88, 0x30, 0x20, 0x60, 0x91, 0x46, 0x94, 0x20, + 0x00, 0xfb, 0x08, 0xa0, 0x44, 0x30, 0xe0, 0x60, 0x01, 0x27, 0xf4, 0xf7, + 0x21, 0xf8, 0xa8, 0x19, 0x51, 0x46, 0x44, 0x22, 0xfb, 0xf7, 0xb4, 0xff, + 0x20, 0x68, 0x90, 0xf8, 0xa1, 0x11, 0x40, 0x46, 0xfc, 0xf7, 0xce, 0xfb, + 0xe0, 0x68, 0x21, 0x68, 0x40, 0x8b, 0x08, 0x70, 0xe0, 0x68, 0x21, 0x68, + 0x00, 0x8b, 0x48, 0x70, 0xf4, 0xf7, 0x21, 0xf8, 0xfc, 0xf7, 0xac, 0xf8, + 0x48, 0xb9, 0x0b, 0x25, 0x29, 0x46, 0x20, 0x46, 0xfe, 0xf7, 0xab, 0xf8, + 0xe0, 0x68, 0x05, 0x60, 0x28, 0x46, 0xbd, 0xe8, 0xf0, 0x87, 0xe0, 0x68, + 0x80, 0x8b, 0x10, 0xb9, 0x03, 0x25, 0xf1, 0xe7, 0x7f, 0x1c, 0x20, 0x46, + 0xfc, 0xf7, 0x67, 0xfa, 0x05, 0x00, 0x06, 0xd0, 0x20, 0x46, 0xfc, 0xf7, + 0x7c, 0xfa, 0x15, 0x2d, 0xe6, 0xd3, 0x00, 0x25, 0xe8, 0xe7, 0x20, 0x68, + 0x01, 0x78, 0x40, 0x46, 0xfc, 0xf7, 0x99, 0xf9, 0x20, 0x46, 0xfe, 0xf7, + 0xbd, 0xf8, 0x05, 0x46, 0xe0, 0x68, 0xc1, 0x6a, 0x49, 0x1c, 0x00, 0x2d, + 0xc1, 0x62, 0xec, 0xd1, 0x81, 0x68, 0x49, 0x1c, 0xb9, 0xf1, 0x00, 0x0f, + 0x81, 0x60, 0xcf, 0xd0, 0xa1, 0x68, 0x09, 0x8b, 0x8f, 0x42, 0xd9, 0xd3, + 0xc0, 0x68, 0xf8, 0xf7, 0x51, 0xfe, 0x21, 0x68, 0xc1, 0xf8, 0x98, 0x01, + 0xc4, 0xe7, 0x10, 0xb5, 0x4f, 0xf4, 0xd4, 0x74, 0x12, 0x49, 0xc8, 0x22, + 0x02, 0xfb, 0x00, 0x12, 0x0a, 0x49, 0x10, 0x61, 0x01, 0xf5, 0xb6, 0x73, + 0x53, 0x60, 0x91, 0x60, 0x0a, 0x4b, 0x04, 0xfb, 0x00, 0x33, 0x88, 0x33, + 0x13, 0x60, 0x94, 0x23, 0x03, 0xfb, 0x00, 0x10, 0x44, 0x30, 0xd0, 0x60, + 0x00, 0x21, 0xbd, 0xe8, 0x10, 0x40, 0x10, 0x46, 0xfe, 0xf7, 0xd0, 0xbc, + 0x30, 0x27, 0x00, 0x20, 0x98, 0xf3, 0x00, 0x20, 0x78, 0x29, 0x00, 0x20, + 0x88, 0xb1, 0x00, 0x20, 0x00, 0x00, 0x40, 0x59, 0x00, 0x00, 0x50, 0x59, + 0x74, 0xe8, 0x00, 0x20, 0x00, 0x00, 0x40, 0x59, 0x00, 0x00, 0x50, 0x59, + 0x2d, 0xe9, 0xf0, 0x41, 0xf9, 0xf7, 0xf2, 0xfe, 0xf8, 0xf7, 0x6a, 0xfd, + 0xf5, 0xf7, 0xf8, 0xf9, 0x01, 0xf0, 0x54, 0xff, 0xf6, 0xf7, 0x68, 0xfe, + 0xf7, 0xf7, 0xf1, 0xfd, 0xff, 0xf7, 0x54, 0xfd, 0xfe, 0xf7, 0xd4, 0xfd, + 0xfa, 0xf7, 0x7e, 0xfa, 0xfa, 0xf7, 0x6d, 0xfa, 0x00, 0x24, 0x0f, 0xf2, + 0x54, 0x15, 0x0f, 0xf2, 0x48, 0x16, 0x36, 0xf8, 0x24, 0x00, 0x93, 0x21, + 0xf5, 0xf7, 0xde, 0xf8, 0x06, 0xeb, 0x84, 0x00, 0x82, 0x21, 0x00, 0xf0, + 0x5d, 0xf8, 0x00, 0xbf, 0x00, 0xbf, 0x00, 0xbf, 0x02, 0x21, 0x00, 0xf0, + 0x58, 0xf8, 0x35, 0xf8, 0x24, 0x00, 0x8c, 0x21, 0xf5, 0xf7, 0xce, 0xf8, + 0x05, 0xeb, 0x84, 0x00, 0x80, 0x21, 0x00, 0xf0, 0x4d, 0xf8, 0x00, 0xbf, + 0x00, 0xbf, 0x00, 0xbf, 0x00, 0x21, 0x00, 0xf0, 0x48, 0xf8, 0x64, 0x1c, + 0x02, 0x2c, 0xdc, 0xd3, 0x0f, 0xf2, 0xe4, 0x06, 0xf7, 0xf7, 0x5c, 0xfc, + 0x00, 0x24, 0x4f, 0xf0, 0x0c, 0x08, 0x00, 0x27, 0x08, 0xfb, 0x04, 0xf5, + 0x09, 0xe0, 0xa8, 0x19, 0x40, 0x68, 0x08, 0xfb, 0x07, 0x00, 0x18, 0xb1, + 0x00, 0x68, 0x01, 0x00, 0x18, 0xbf, 0x80, 0x47, 0x7f, 0x1c, 0xa8, 0x5d, + 0x87, 0x42, 0xf2, 0xd3, 0x64, 0x1c, 0x02, 0x2c, 0xeb, 0xd3, 0x12, 0x48, + 0x12, 0x4a, 0x40, 0x89, 0x10, 0xf0, 0x03, 0x01, 0x18, 0xbf, 0x01, 0x21, + 0x91, 0x60, 0xc0, 0xf3, 0x81, 0x01, 0x01, 0xb1, 0x4e, 0x21, 0x93, 0x68, + 0x19, 0x43, 0x91, 0x60, 0xc0, 0xf3, 0x01, 0x13, 0x03, 0xb1, 0x4e, 0x23, + 0x19, 0x43, 0x91, 0x60, 0xc0, 0xf3, 0x82, 0x10, 0x00, 0xb1, 0x08, 0x20, + 0x08, 0x43, 0x90, 0x60, 0x00, 0x22, 0x70, 0x21, 0x40, 0xf6, 0x8a, 0x50, + 0xf5, 0xf7, 0x8e, 0xf8, 0xbd, 0xe8, 0xf0, 0x41, 0xfb, 0xf7, 0x40, 0xbd, + 0x78, 0x29, 0x00, 0x20, 0xe8, 0xf2, 0x00, 0x20, 0x47, 0x88, 0x38, 0x46, + 0xf5, 0xf7, 0x78, 0xb8, 0x70, 0xb5, 0x04, 0x46, 0x15, 0x46, 0x0e, 0x46, + 0x28, 0x04, 0x48, 0xbf, 0xf3, 0xf7, 0x10, 0xff, 0x26, 0x60, 0x28, 0x06, + 0x44, 0xbf, 0x05, 0xf0, 0x7f, 0x00, 0x60, 0x60, 0xe8, 0x05, 0x48, 0xbf, + 0x00, 0x20, 0x03, 0xd4, 0xa8, 0x05, 0x02, 0xd5, 0xe0, 0x68, 0x40, 0x1c, + 0xe0, 0x60, 0x68, 0x05, 0x48, 0xbf, 0x00, 0x20, 0x03, 0xd4, 0x28, 0x05, + 0x02, 0xd5, 0x20, 0x69, 0x40, 0x1c, 0x20, 0x61, 0xe8, 0x04, 0x44, 0xbf, + 0x00, 0x20, 0xa0, 0x60, 0x28, 0x04, 0x44, 0xbf, 0xbd, 0xe8, 0x70, 0x40, + 0xf3, 0xf7, 0x03, 0xbf, 0x70, 0xbd, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x24, 0x9a, 0x00, 0x01, 0x60, 0xb5, 0x00, 0x20, 0x08, 0x00, 0x00, 0x00, + 0x08, 0x6f, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0xe6, 0x06, 0xe7, 0x06, + 0xe8, 0x06, 0xe9, 0x06, 0xe0, 0x08, 0xe1, 0x08, 0xe2, 0x08, 0xe3, 0x08, + 0x2d, 0xe9, 0xf1, 0x41, 0xc0, 0xf3, 0xc7, 0x50, 0xff, 0x28, 0x81, 0xb0, + 0x0c, 0x46, 0x09, 0xd1, 0x01, 0x98, 0x00, 0x26, 0x40, 0x02, 0x02, 0xd1, + 0x01, 0x98, 0x00, 0x28, 0x18, 0xd4, 0x01, 0x98, 0xbd, 0xe8, 0xf6, 0x81, + 0x01, 0x28, 0x0b, 0xda, 0x01, 0xa8, 0x00, 0xf0, 0x0f, 0xff, 0x01, 0x28, + 0x06, 0xdb, 0x00, 0xf0, 0x45, 0xff, 0x22, 0x21, 0x01, 0x60, 0x5a, 0x48, + 0xbd, 0xe8, 0xf6, 0x81, 0x01, 0x99, 0x21, 0xf0, 0xff, 0x41, 0x41, 0xf0, + 0x7c, 0x51, 0x01, 0x91, 0xa0, 0xf1, 0x7e, 0x06, 0x01, 0x98, 0x00, 0x28, + 0x07, 0xd5, 0x00, 0xf0, 0x33, 0xff, 0x21, 0x21, 0x01, 0x60, 0x6f, 0xf0, + 0x00, 0x40, 0xbd, 0xe8, 0xf6, 0x81, 0x50, 0x49, 0xf8, 0xf7, 0xae, 0xfe, + 0x06, 0xd2, 0x01, 0x46, 0x4f, 0xf0, 0x80, 0x40, 0xf8, 0xf7, 0xba, 0xfe, + 0x01, 0x90, 0x76, 0x1e, 0x01, 0x99, 0x4b, 0x48, 0xf8, 0xf7, 0x18, 0xfe, + 0x05, 0x46, 0x01, 0x99, 0x4f, 0xf0, 0x7e, 0x50, 0xf8, 0xf7, 0x12, 0xfe, + 0x01, 0x46, 0x28, 0x46, 0xf8, 0xf7, 0x1c, 0xfd, 0x07, 0x46, 0x39, 0x46, + 0xf8, 0xf7, 0xa6, 0xfe, 0x80, 0x46, 0x43, 0x48, 0x41, 0x46, 0xf8, 0xf7, + 0xa1, 0xfe, 0x42, 0x49, 0xf8, 0xf7, 0x02, 0xfe, 0x41, 0x46, 0xf8, 0xf7, + 0x9b, 0xfe, 0x40, 0x49, 0xf8, 0xf7, 0xfc, 0xfd, 0x41, 0x46, 0xf8, 0xf7, + 0x95, 0xfe, 0x01, 0x46, 0x28, 0x46, 0xf8, 0xf7, 0x81, 0xfd, 0x39, 0x46, + 0xf8, 0xf7, 0x8e, 0xfe, 0x07, 0x46, 0x30, 0xb2, 0xf8, 0xf7, 0xe2, 0xfc, + 0x06, 0x46, 0x84, 0xb9, 0x37, 0x48, 0x31, 0x46, 0xf8, 0xf7, 0x84, 0xfe, + 0x39, 0x46, 0xf8, 0xf7, 0x71, 0xfd, 0x29, 0x46, 0xf8, 0xf7, 0xe2, 0xfd, + 0x04, 0x46, 0x33, 0x48, 0x31, 0x46, 0xf8, 0xf7, 0x79, 0xfe, 0x21, 0x46, + 0x3c, 0xe0, 0x01, 0x2c, 0x23, 0xdb, 0x30, 0x48, 0x29, 0x46, 0xf8, 0xf7, + 0x71, 0xfe, 0x04, 0x46, 0x2e, 0x48, 0x29, 0x46, 0xf8, 0xf7, 0x6c, 0xfe, + 0x05, 0x46, 0x2d, 0x48, 0x31, 0x46, 0xf8, 0xf7, 0x67, 0xfe, 0x80, 0x46, + 0x2b, 0x48, 0x39, 0x46, 0xf8, 0xf7, 0x62, 0xfe, 0x01, 0x46, 0x40, 0x46, + 0xf8, 0xf7, 0x4e, 0xfd, 0x29, 0x46, 0xf8, 0xf7, 0xbf, 0xfd, 0x21, 0x46, + 0xf8, 0xf7, 0xbc, 0xfd, 0x04, 0x46, 0x25, 0x48, 0x31, 0x46, 0xf8, 0xf7, + 0x53, 0xfe, 0x21, 0x46, 0x16, 0xe0, 0x23, 0x4c, 0x28, 0x46, 0x21, 0x46, + 0xf8, 0xf7, 0x4c, 0xfe, 0x80, 0x46, 0x21, 0x48, 0x29, 0x46, 0xf8, 0xf7, + 0x47, 0xfe, 0x05, 0x46, 0x38, 0x46, 0x21, 0x46, 0xf8, 0xf7, 0x42, 0xfe, + 0x01, 0x46, 0x28, 0x46, 0xf8, 0xf7, 0x2e, 0xfd, 0x41, 0x46, 0xf8, 0xf7, + 0x9f, 0xfd, 0x31, 0x46, 0xf8, 0xf7, 0x9c, 0xfd, 0xbd, 0xe8, 0xf6, 0x81, + 0x10, 0xb5, 0x04, 0x46, 0x0a, 0x48, 0x21, 0x46, 0xf8, 0xf7, 0x30, 0xfe, + 0x09, 0x49, 0xf8, 0xf7, 0x91, 0xfd, 0x21, 0x46, 0xf8, 0xf7, 0x2a, 0xfe, + 0xbd, 0xe8, 0x10, 0x40, 0x06, 0x49, 0xf8, 0xf7, 0x89, 0xbd, 0x00, 0x00, + 0x00, 0x00, 0x80, 0xff, 0xf3, 0x04, 0x35, 0x3f, 0x00, 0x00, 0x80, 0xbf, + 0x15, 0x02, 0x99, 0x3e, 0x11, 0xae, 0xcc, 0x3e, 0xc0, 0xaa, 0x2a, 0x3f, + 0xe8, 0xe8, 0xfb, 0x33, 0x16, 0x72, 0x31, 0x3f, 0xd8, 0x5b, 0xde, 0x3e, + 0x28, 0x37, 0xa9, 0x32, 0xf4, 0x3e, 0xa1, 0x33, 0xd9, 0x5b, 0xde, 0x3e, + 0x98, 0x20, 0x9a, 0x3e, 0x3b, 0xaa, 0xb8, 0x3f, 0x60, 0x70, 0xa5, 0x32, + 0xef, 0xf3, 0x11, 0x80, 0x60, 0x21, 0x81, 0xf3, 0x11, 0x88, 0x70, 0x47, + 0x80, 0xb5, 0xff, 0xf7, 0xf7, 0xff, 0xdf, 0xf8, 0x9c, 0x1a, 0xdf, 0xf8, + 0x9c, 0x3a, 0x09, 0x68, 0x4f, 0xf0, 0x00, 0x42, 0x1a, 0x60, 0x04, 0xbd, + 0xdf, 0xf8, 0x88, 0x3a, 0x01, 0xf0, 0x00, 0x42, 0x1a, 0x60, 0x80, 0xf3, + 0x11, 0x88, 0x70, 0x47, 0x2d, 0xe9, 0xf0, 0x41, 0xdf, 0xf8, 0x7c, 0x6a, + 0xdf, 0xf8, 0x7c, 0x4a, 0xdf, 0xf8, 0x7c, 0x5a, 0x82, 0xb0, 0x70, 0x89, + 0xc0, 0xf3, 0x01, 0x10, 0x00, 0x28, 0x41, 0xd0, 0x07, 0x21, 0x05, 0xf1, + 0x32, 0x00, 0x00, 0xf0, 0xa3, 0xfc, 0x00, 0x21, 0x05, 0xf1, 0x34, 0x00, + 0x00, 0xf0, 0xa3, 0xfc, 0x30, 0x6c, 0xdf, 0xf8, 0x5c, 0x8a, 0x00, 0x90, + 0x23, 0x46, 0x13, 0x22, 0x05, 0xf1, 0x36, 0x01, 0x05, 0xf1, 0x38, 0x00, + 0x00, 0xf0, 0x1b, 0xfc, 0x00, 0x20, 0x00, 0x90, 0x4f, 0xf4, 0x00, 0x63, + 0x32, 0x6c, 0x05, 0xf1, 0x36, 0x01, 0x05, 0xf1, 0x38, 0x00, 0x00, 0xf0, + 0x45, 0xfc, 0x33, 0x6c, 0x22, 0x46, 0x0a, 0x21, 0x05, 0xf1, 0x3a, 0x00, + 0x00, 0xf0, 0x21, 0xfc, 0x02, 0x27, 0x0c, 0x20, 0xc0, 0x21, 0x00, 0xfb, + 0x07, 0x80, 0x01, 0xfb, 0x07, 0x81, 0x01, 0xf5, 0x2c, 0x71, 0x01, 0x60, + 0x07, 0xeb, 0x47, 0x01, 0x41, 0x44, 0x01, 0xf2, 0xba, 0x51, 0x41, 0x60, + 0x7f, 0x1c, 0x18, 0x21, 0x01, 0x72, 0x2f, 0x21, 0x41, 0x72, 0x18, 0x21, + 0x00, 0xf0, 0x73, 0xfc, 0x04, 0x2f, 0xe6, 0xd3, 0x70, 0x89, 0xc0, 0xf3, + 0x82, 0x10, 0xd0, 0xb1, 0x07, 0x21, 0x05, 0xf1, 0x40, 0x00, 0x00, 0xf0, + 0x5d, 0xfc, 0x00, 0x21, 0x05, 0xf1, 0x42, 0x00, 0x00, 0xf0, 0x5d, 0xfc, + 0x70, 0x6d, 0x00, 0x90, 0x23, 0x46, 0x13, 0x22, 0x05, 0xf1, 0x44, 0x01, + 0x05, 0xf1, 0x46, 0x00, 0x00, 0xf0, 0xd7, 0xfb, 0x73, 0x6d, 0x22, 0x46, + 0x0a, 0x21, 0x05, 0xf1, 0x48, 0x00, 0x00, 0xf0, 0xe8, 0xfb, 0xbd, 0xe8, + 0xf3, 0x41, 0x00, 0xe0, 0x00, 0xbf, 0xf8, 0xb5, 0xdf, 0xf8, 0xa8, 0x49, + 0xdf, 0xf8, 0x9c, 0x59, 0x0e, 0x22, 0x05, 0xf1, 0x2e, 0x01, 0x20, 0x46, + 0xfb, 0xf7, 0xd8, 0xfc, 0x0e, 0x22, 0x05, 0xf1, 0x3c, 0x01, 0x04, 0xf1, + 0x10, 0x00, 0xfb, 0xf7, 0xe1, 0xfc, 0xa5, 0x88, 0x4f, 0xf6, 0xfe, 0x70, + 0x00, 0xea, 0x05, 0x06, 0x20, 0x78, 0x01, 0x06, 0x45, 0xf0, 0x01, 0x07, + 0x07, 0xd5, 0x00, 0xf0, 0x7f, 0x00, 0x65, 0x84, 0xa5, 0x84, 0x65, 0x85, + 0xa5, 0x85, 0x20, 0x70, 0x1b, 0xe0, 0x02, 0x20, 0xf6, 0xf7, 0xe2, 0xf9, + 0x00, 0x28, 0x14, 0xbf, 0x67, 0x84, 0x66, 0x84, 0x03, 0x20, 0xf6, 0xf7, + 0xdb, 0xf9, 0x00, 0x28, 0x14, 0xbf, 0xa7, 0x84, 0xa6, 0x84, 0x10, 0x20, + 0xf6, 0xf7, 0xd4, 0xf9, 0x00, 0x28, 0x14, 0xbf, 0x67, 0x85, 0x66, 0x85, + 0x11, 0x20, 0xf6, 0xf7, 0xcd, 0xf9, 0x00, 0x28, 0x14, 0xbf, 0xa7, 0x85, + 0xa6, 0x85, 0x20, 0x7c, 0x01, 0x06, 0x04, 0xd5, 0x00, 0xf0, 0x7f, 0x00, + 0x25, 0x85, 0x20, 0x74, 0x06, 0xe0, 0x12, 0x20, 0xf6, 0xf7, 0xbe, 0xf9, + 0x00, 0x28, 0x14, 0xbf, 0x27, 0x85, 0x26, 0x85, 0x21, 0x78, 0x60, 0x88, + 0x00, 0x29, 0x0e, 0xbf, 0x40, 0xf0, 0x10, 0x00, 0x4f, 0xf6, 0xef, 0x71, + 0x08, 0x40, 0x60, 0x80, 0x21, 0x7c, 0x60, 0x8a, 0x00, 0x29, 0x0e, 0xbf, + 0x40, 0xf0, 0x10, 0x00, 0x4f, 0xf6, 0xef, 0x71, 0x08, 0x40, 0x60, 0x82, + 0xf1, 0xbd, 0x30, 0xb5, 0x0f, 0xf6, 0x50, 0x11, 0x0f, 0xf6, 0x2c, 0x12, + 0x51, 0xf8, 0x20, 0x30, 0xdf, 0xf8, 0xd4, 0x18, 0x0f, 0xf6, 0x60, 0x14, + 0xdf, 0xf8, 0xd0, 0x58, 0x0b, 0x63, 0x52, 0xf8, 0x20, 0x20, 0x34, 0xf8, + 0x10, 0x40, 0x2c, 0x80, 0x01, 0xeb, 0x40, 0x00, 0x00, 0x24, 0x1c, 0x70, + 0xdf, 0xf8, 0xbc, 0x38, 0xd4, 0x88, 0x5c, 0x80, 0x14, 0x89, 0x9c, 0x80, + 0x54, 0x89, 0xdc, 0x80, 0x94, 0x89, 0x1c, 0x81, 0x0c, 0x6b, 0xdf, 0xf8, + 0xac, 0x18, 0xa5, 0x89, 0x1d, 0x82, 0xe5, 0x89, 0x5d, 0x82, 0x25, 0x8a, + 0x9d, 0x82, 0x64, 0x8a, 0xdc, 0x82, 0x00, 0x24, 0x1c, 0x80, 0x00, 0x8c, + 0x18, 0x80, 0x50, 0x88, 0x08, 0x80, 0x30, 0xbd, 0xdf, 0xf8, 0x84, 0x08, + 0x4f, 0xf4, 0xc0, 0x41, 0x01, 0x80, 0xdf, 0xf8, 0x74, 0x18, 0x0a, 0x6b, + 0x7a, 0xb1, 0xb0, 0xf9, 0x10, 0x30, 0x93, 0x81, 0xb0, 0xf9, 0x12, 0x30, + 0xd3, 0x81, 0xb0, 0xf9, 0x14, 0x30, 0x13, 0x82, 0xb0, 0xf9, 0x16, 0x00, + 0x50, 0x82, 0x01, 0x20, 0x10, 0x70, 0x00, 0x20, 0x08, 0x63, 0x70, 0x47, + 0xf8, 0xb5, 0x04, 0x46, 0x0f, 0xf6, 0xb4, 0x00, 0xdf, 0xf8, 0x40, 0x78, + 0x50, 0xf8, 0x24, 0x50, 0x0f, 0xf6, 0x88, 0x00, 0x50, 0xf8, 0x24, 0x60, + 0x0f, 0xf6, 0xc0, 0x00, 0x30, 0xf8, 0x14, 0x10, 0xdf, 0xf8, 0x2c, 0x08, + 0xf7, 0xf7, 0x00, 0xf8, 0xf1, 0x88, 0xdf, 0xf8, 0x30, 0x08, 0xf6, 0xf7, + 0xfb, 0xff, 0x31, 0x89, 0xdf, 0xf8, 0x28, 0x08, 0xf6, 0xf7, 0xf6, 0xff, + 0x71, 0x89, 0xdf, 0xf8, 0x24, 0x08, 0xf6, 0xf7, 0xf1, 0xff, 0xb1, 0x89, + 0xdf, 0xf8, 0x1c, 0x08, 0xf6, 0xf7, 0xec, 0xff, 0xa9, 0x89, 0xdf, 0xf8, + 0x18, 0x08, 0xf6, 0xf7, 0xe7, 0xff, 0xe9, 0x89, 0xdf, 0xf8, 0x10, 0x08, + 0xf6, 0xf7, 0xe2, 0xff, 0x29, 0x8a, 0xdf, 0xf8, 0x0c, 0x08, 0xf6, 0xf7, + 0xdd, 0xff, 0x69, 0x8a, 0xdf, 0xf8, 0x04, 0x08, 0xf6, 0xf7, 0xd8, 0xff, + 0x29, 0x46, 0x07, 0xf1, 0x30, 0x00, 0xf6, 0xf7, 0xfb, 0xff, 0x00, 0x21, + 0x28, 0x46, 0xf6, 0xf7, 0xbf, 0xff, 0xdf, 0xf8, 0xc8, 0x57, 0x00, 0x21, + 0x28, 0x46, 0xf6, 0xf7, 0xc9, 0xff, 0x07, 0xeb, 0x44, 0x00, 0x01, 0x8c, + 0x28, 0x46, 0xf6, 0xf7, 0xc3, 0xff, 0x71, 0x88, 0xdf, 0xf8, 0xb0, 0x07, + 0xbd, 0xe8, 0xf4, 0x40, 0xf6, 0xf7, 0xbc, 0xbf, 0x70, 0xb5, 0xdf, 0xf8, + 0xa0, 0x47, 0x4f, 0xf4, 0xc0, 0x41, 0x20, 0x46, 0xf6, 0xf7, 0xb4, 0xff, + 0xdf, 0xf8, 0x88, 0x57, 0x2e, 0x6b, 0xf6, 0xb1, 0x21, 0x8a, 0x06, 0xf1, + 0x0c, 0x00, 0xf6, 0xf7, 0xab, 0xff, 0x61, 0x8a, 0x06, 0xf1, 0x0e, 0x00, + 0xf6, 0xf7, 0xa6, 0xff, 0xa1, 0x8a, 0x06, 0xf1, 0x10, 0x00, 0xf6, 0xf7, + 0xa1, 0xff, 0xe1, 0x8a, 0x06, 0xf1, 0x12, 0x00, 0xf6, 0xf7, 0x9c, 0xff, + 0x01, 0x21, 0x30, 0x46, 0xf6, 0xf7, 0x88, 0xff, 0x05, 0xf1, 0x30, 0x00, + 0xbd, 0xe8, 0x70, 0x40, 0x00, 0x21, 0xf6, 0xf7, 0xb9, 0xbf, 0x70, 0xbd, + 0xdf, 0xf8, 0x38, 0x17, 0xdf, 0xf8, 0x50, 0x07, 0xca, 0x8e, 0x4f, 0xf6, + 0xe0, 0x73, 0x1a, 0x40, 0x02, 0x80, 0x09, 0x8f, 0xc8, 0xe0, 0xdf, 0xf8, + 0x24, 0x17, 0xdf, 0xf8, 0x3c, 0x07, 0xca, 0x8e, 0x02, 0x80, 0x09, 0x8f, + 0x41, 0x80, 0x70, 0x47, 0x70, 0xb5, 0xdf, 0xf8, 0x48, 0x17, 0x82, 0xb0, + 0x00, 0x20, 0x88, 0x61, 0xdf, 0xf8, 0xfc, 0x46, 0x60, 0x89, 0xc0, 0xf3, + 0x81, 0x00, 0xb8, 0xb3, 0xdf, 0xf8, 0xf8, 0x56, 0x07, 0x21, 0x05, 0xf1, + 0x24, 0x00, 0x00, 0xf0, 0xe7, 0xfa, 0x0c, 0x21, 0x05, 0xf1, 0x26, 0x00, + 0x00, 0xf0, 0xe7, 0xfa, 0xe0, 0x6a, 0xdf, 0xf8, 0xdc, 0x66, 0x00, 0x90, + 0x33, 0x46, 0x13, 0x22, 0x05, 0xf1, 0x28, 0x01, 0x05, 0xf1, 0x2a, 0x00, + 0x00, 0xf0, 0x5f, 0xfa, 0xe3, 0x6a, 0x32, 0x46, 0x0a, 0x21, 0x05, 0xf1, + 0x2c, 0x00, 0x00, 0xf0, 0x70, 0xfa, 0x00, 0x24, 0xdf, 0xf8, 0xbc, 0x56, + 0x0c, 0x20, 0x00, 0xfb, 0x04, 0x50, 0x05, 0xeb, 0x44, 0x21, 0x30, 0x31, + 0x01, 0x60, 0x05, 0xeb, 0xc4, 0x01, 0x01, 0xf5, 0xb6, 0x61, 0x41, 0x60, + 0x64, 0x1c, 0xc0, 0x21, 0x01, 0x72, 0xff, 0x21, 0x41, 0x72, 0x40, 0x21, + 0x00, 0xf0, 0xc3, 0xfa, 0x02, 0x2c, 0xe9, 0xd3, 0x73, 0xbd, 0x10, 0xb5, + 0xdf, 0xf8, 0xbc, 0x46, 0xdf, 0xf8, 0xbc, 0x16, 0x0e, 0x22, 0x20, 0x46, + 0xfb, 0xf7, 0x5c, 0xfb, 0x20, 0x78, 0x01, 0x06, 0x03, 0xd5, 0x00, 0xf0, + 0x7f, 0x00, 0x20, 0x70, 0x17, 0xe0, 0x00, 0x20, 0xf6, 0xf7, 0x68, 0xf8, + 0xa1, 0x88, 0x00, 0x28, 0x12, 0xbf, 0x41, 0xf0, 0x01, 0x00, 0x4f, 0xf6, + 0xfe, 0x70, 0x08, 0x40, 0xa0, 0x80, 0x01, 0x20, 0xf6, 0xf7, 0x5c, 0xf8, + 0x00, 0x28, 0xa0, 0x88, 0x12, 0xbf, 0x40, 0xf0, 0x02, 0x00, 0x4f, 0xf6, + 0xfd, 0x71, 0x08, 0x40, 0xa0, 0x80, 0x00, 0x20, 0x20, 0x61, 0x06, 0x21, + 0x4f, 0xf0, 0xff, 0x30, 0xa0, 0x82, 0x02, 0x20, 0xf9, 0xf7, 0x75, 0xfc, + 0xdf, 0xf8, 0x64, 0x06, 0x4f, 0xf6, 0xff, 0x71, 0x01, 0x80, 0x4f, 0xf6, + 0xff, 0x61, 0x41, 0x80, 0x02, 0x20, 0xf9, 0xf7, 0x4f, 0xfc, 0x02, 0x20, + 0xf9, 0xf7, 0x52, 0xfc, 0x61, 0x88, 0x23, 0x78, 0xdf, 0xf8, 0x48, 0x06, + 0xdf, 0xf8, 0x48, 0x26, 0x33, 0xb9, 0x00, 0xf0, 0x11, 0xf8, 0x01, 0x20, + 0xa0, 0x61, 0xbd, 0xe8, 0x10, 0x40, 0x39, 0xe0, 0x4e, 0xf6, 0xef, 0x73, + 0x19, 0x40, 0x00, 0xf0, 0x07, 0xf8, 0x00, 0x21, 0x01, 0x82, 0x41, 0x82, + 0x01, 0x83, 0x41, 0x83, 0xa1, 0x61, 0x10, 0xbd, 0x11, 0x80, 0x4f, 0xf6, + 0xfc, 0x72, 0xa1, 0x88, 0x11, 0x40, 0x01, 0x80, 0x70, 0x47, 0xdf, 0xf8, + 0x00, 0x06, 0x00, 0x21, 0x81, 0x61, 0x4f, 0xf6, 0xfc, 0x72, 0x4f, 0xf0, + 0xff, 0x31, 0x81, 0x82, 0xdf, 0xf8, 0xf8, 0x05, 0x01, 0x88, 0x11, 0x40, + 0x01, 0x80, 0x02, 0x20, 0xf9, 0xf7, 0x29, 0xbc, 0xdf, 0xf8, 0xdc, 0x15, + 0xdf, 0xf8, 0xec, 0x05, 0x0a, 0x89, 0x4f, 0xf6, 0xe0, 0x73, 0x1a, 0x40, + 0x02, 0x80, 0x49, 0x89, 0x19, 0x40, 0x41, 0x80, 0x70, 0x47, 0xdf, 0xf8, + 0xc4, 0x15, 0xdf, 0xf8, 0xd4, 0x05, 0x0a, 0x89, 0x02, 0x80, 0x49, 0x89, + 0x41, 0x80, 0x70, 0x47, 0xf8, 0xb5, 0xdf, 0xf8, 0xb0, 0x45, 0xa0, 0x69, + 0x00, 0x28, 0x5d, 0xd0, 0xdf, 0xf8, 0xb0, 0x55, 0x28, 0x88, 0x4f, 0xf6, + 0xfc, 0x71, 0x08, 0x40, 0x28, 0x80, 0x00, 0xf0, 0x9f, 0xfa, 0x20, 0x79, + 0x00, 0x27, 0xc0, 0x07, 0x4f, 0xf0, 0xff, 0x36, 0x05, 0xd5, 0x00, 0x20, + 0x00, 0xf0, 0x84, 0xfd, 0x08, 0xb9, 0x26, 0x8a, 0x01, 0x27, 0x20, 0x79, + 0x80, 0x07, 0x09, 0xd5, 0x01, 0x20, 0x00, 0xf0, 0x7b, 0xfd, 0x28, 0xb9, + 0x60, 0x8a, 0x86, 0x42, 0x47, 0xf0, 0x02, 0x07, 0x28, 0xbf, 0x06, 0x46, + 0x22, 0x8a, 0xdf, 0xf8, 0x28, 0x05, 0x0a, 0x21, 0x96, 0x42, 0x01, 0xfb, + 0x06, 0x01, 0x06, 0xd2, 0x91, 0xf8, 0x5a, 0x20, 0xd2, 0x07, 0x5c, 0xbf, + 0x4f, 0xf6, 0xfe, 0x72, 0x17, 0x40, 0x62, 0x8a, 0x96, 0x42, 0x06, 0xd2, + 0x91, 0xf8, 0x5a, 0x20, 0x92, 0x07, 0x5c, 0xbf, 0x4f, 0xf6, 0xfd, 0x72, + 0x17, 0x40, 0xbf, 0xb1, 0xb0, 0xf8, 0x58, 0x00, 0x86, 0x42, 0x32, 0xbf, + 0x01, 0xf1, 0x5a, 0x00, 0x06, 0x46, 0x20, 0x1d, 0x41, 0x88, 0x69, 0x80, + 0x81, 0x88, 0xa9, 0x80, 0xc1, 0x88, 0xe9, 0x80, 0x01, 0x89, 0x29, 0x81, + 0x4f, 0xf6, 0xfc, 0x71, 0x00, 0x88, 0x08, 0x40, 0x38, 0x43, 0x28, 0x80, + 0x30, 0x46, 0x01, 0xe0, 0x4f, 0xf0, 0xff, 0x30, 0x47, 0xea, 0x06, 0x11, + 0xa0, 0x82, 0x3d, 0x20, 0xbd, 0xe8, 0xf4, 0x40, 0xf9, 0xf7, 0x3e, 0xbc, + 0xf1, 0xbd, 0x38, 0xb5, 0x04, 0x46, 0xff, 0xf7, 0xf5, 0xfc, 0xdf, 0xf8, + 0xe0, 0x14, 0x05, 0x46, 0x01, 0xeb, 0x44, 0x01, 0x00, 0x20, 0x08, 0x82, + 0x00, 0x22, 0x00, 0x21, 0x20, 0x46, 0x00, 0xf0, 0x03, 0xf8, 0x85, 0xf3, + 0x11, 0x88, 0x31, 0xbd, 0xf8, 0xb5, 0x04, 0x46, 0x0d, 0x46, 0x16, 0x46, + 0xff, 0xf7, 0xe0, 0xfc, 0x07, 0x46, 0xdf, 0xf8, 0xc0, 0x04, 0x01, 0x88, + 0x4f, 0xf6, 0xfc, 0x72, 0x11, 0x40, 0x01, 0x80, 0x14, 0xb9, 0x05, 0x82, + 0x46, 0x82, 0x03, 0xe0, 0x01, 0x2c, 0x04, 0xbf, 0x05, 0x83, 0x46, 0x83, + 0xff, 0xf7, 0x70, 0xff, 0x87, 0xf3, 0x11, 0x88, 0xf1, 0xbd, 0x2d, 0xe9, + 0xf8, 0x43, 0x80, 0x46, 0x0f, 0xf2, 0xc4, 0x40, 0x50, 0xf8, 0x28, 0x50, + 0x0e, 0x46, 0x17, 0x46, 0xff, 0xf7, 0xc6, 0xfc, 0x04, 0x46, 0x89, 0x46, + 0xf9, 0xf7, 0x7e, 0xfd, 0x40, 0x45, 0x0a, 0xd1, 0xdf, 0xf8, 0x40, 0x04, + 0x01, 0x88, 0x4f, 0xf6, 0xfe, 0x72, 0x0a, 0x40, 0x02, 0x80, 0x06, 0x82, + 0x47, 0x82, 0x01, 0x80, 0x03, 0xe0, 0xae, 0x81, 0xef, 0x81, 0x01, 0x20, + 0x28, 0x70, 0x20, 0x46, 0x49, 0x46, 0xbd, 0xe8, 0xf4, 0x43, 0xb7, 0xe4, + 0x00, 0x28, 0xdf, 0xf8, 0x40, 0x14, 0x0c, 0xbf, 0x01, 0x20, 0x02, 0x20, + 0x89, 0x88, 0x08, 0x40, 0x70, 0x47, 0xdf, 0xf8, 0x00, 0x14, 0x01, 0xeb, + 0x40, 0x00, 0x90, 0xf8, 0x20, 0x00, 0x00, 0xf0, 0x01, 0x00, 0x70, 0x47, + 0xdf, 0xf8, 0x1c, 0x24, 0x02, 0xeb, 0x40, 0x00, 0x00, 0x21, 0x01, 0x82, + 0x2e, 0xe7, 0x2d, 0xe9, 0xfc, 0x47, 0x06, 0x46, 0xdf, 0xf8, 0xd4, 0x93, + 0x0c, 0x20, 0x88, 0x46, 0x17, 0x46, 0x00, 0xfb, 0x06, 0x9a, 0x39, 0x46, + 0x50, 0x46, 0x00, 0xf0, 0x6a, 0xf9, 0x00, 0x25, 0x20, 0xb1, 0x39, 0x46, + 0x50, 0x46, 0x00, 0xf0, 0x58, 0xf9, 0x05, 0x46, 0xdf, 0xf8, 0xf0, 0x73, + 0xdf, 0xf8, 0xe0, 0x43, 0x38, 0x88, 0x4f, 0xf6, 0xfc, 0x71, 0x08, 0x40, + 0x38, 0x80, 0x06, 0xbb, 0xb7, 0xf9, 0x10, 0x00, 0xad, 0xf8, 0x00, 0x00, + 0x6a, 0x46, 0xb7, 0xf9, 0x12, 0x00, 0xad, 0xf8, 0x02, 0x00, 0x41, 0x46, + 0xb7, 0xf9, 0x14, 0x00, 0xad, 0xf8, 0x04, 0x00, 0xb7, 0xf9, 0x16, 0x00, + 0xad, 0xf8, 0x06, 0x00, 0x48, 0x46, 0x00, 0xf0, 0x59, 0xf9, 0x3d, 0xb1, + 0x28, 0x88, 0x38, 0x82, 0x68, 0x88, 0x78, 0x82, 0xa8, 0x88, 0xb8, 0x82, + 0xe8, 0x88, 0xf8, 0x82, 0x00, 0x20, 0x20, 0x82, 0x21, 0xe0, 0x01, 0x2e, + 0x1f, 0xd1, 0xb7, 0xf9, 0x18, 0x00, 0xad, 0xf8, 0x00, 0x00, 0x6a, 0x46, + 0xb7, 0xf9, 0x1a, 0x00, 0xad, 0xf8, 0x02, 0x00, 0x41, 0x46, 0xb7, 0xf9, + 0x1c, 0x00, 0xad, 0xf8, 0x04, 0x00, 0xb7, 0xf9, 0x1e, 0x00, 0xad, 0xf8, + 0x06, 0x00, 0x50, 0x46, 0x00, 0xf0, 0x36, 0xf9, 0x3d, 0xb1, 0x28, 0x88, + 0x38, 0x83, 0x68, 0x88, 0x78, 0x83, 0xa8, 0x88, 0xb8, 0x83, 0xe8, 0x88, + 0xf8, 0x83, 0x00, 0x20, 0x60, 0x82, 0xff, 0xf7, 0xcb, 0xfe, 0xbd, 0xe8, + 0xf3, 0x87, 0x2d, 0xe9, 0xfc, 0x47, 0x06, 0x46, 0x04, 0x2e, 0x8a, 0x46, + 0x14, 0x46, 0x57, 0xda, 0xc0, 0x48, 0x0c, 0x21, 0x01, 0xfb, 0x06, 0x08, + 0x21, 0x46, 0x40, 0x46, 0x00, 0xf0, 0x03, 0xf9, 0x00, 0x25, 0x20, 0xb1, + 0x21, 0x46, 0x40, 0x46, 0x00, 0xf0, 0xf1, 0xf8, 0x05, 0x46, 0xff, 0xf7, + 0x15, 0xfc, 0x02, 0x2e, 0x04, 0x46, 0x89, 0x46, 0x02, 0xd1, 0xf5, 0xf7, + 0xec, 0xf8, 0x01, 0xe0, 0xf5, 0xf7, 0xfd, 0xf8, 0x06, 0x46, 0xf9, 0xf7, + 0xc5, 0xfc, 0xb0, 0x42, 0x25, 0xd1, 0xb4, 0x4e, 0x37, 0x88, 0x4f, 0xf6, + 0xfe, 0x70, 0x38, 0x40, 0x30, 0x80, 0x6a, 0x46, 0xb6, 0xf9, 0x10, 0x00, + 0xad, 0xf8, 0x00, 0x00, 0x51, 0x46, 0xb6, 0xf9, 0x12, 0x00, 0xad, 0xf8, + 0x02, 0x00, 0xb6, 0xf9, 0x14, 0x00, 0xad, 0xf8, 0x04, 0x00, 0xb6, 0xf9, + 0x16, 0x00, 0xad, 0xf8, 0x06, 0x00, 0x40, 0x46, 0x00, 0xf0, 0xe6, 0xf8, + 0x3d, 0xb1, 0x28, 0x88, 0x30, 0x82, 0x68, 0x88, 0x70, 0x82, 0xa8, 0x88, + 0xb0, 0x82, 0xe8, 0x88, 0xf0, 0x82, 0x37, 0x80, 0x0e, 0xe0, 0x6d, 0xb1, + 0x0f, 0xf2, 0xe8, 0x20, 0x50, 0xf8, 0x26, 0x00, 0x29, 0x88, 0x81, 0x81, + 0x69, 0x88, 0xc1, 0x81, 0xa9, 0x88, 0x01, 0x82, 0xe9, 0x88, 0x41, 0x82, + 0x01, 0x21, 0x01, 0x70, 0x20, 0x46, 0x49, 0x46, 0xff, 0xf7, 0xda, 0xfb, + 0xbd, 0xe8, 0xf3, 0x87, 0x10, 0xf1, 0x14, 0x0f, 0xb8, 0xbf, 0x1f, 0x20, + 0x04, 0xdb, 0x0a, 0x28, 0xac, 0xbf, 0x00, 0x20, 0xc0, 0xf1, 0x0a, 0x00, + 0x80, 0xb2, 0x70, 0x47, 0x10, 0xb5, 0x91, 0x42, 0x04, 0x46, 0x05, 0xd2, + 0xb2, 0xfb, 0xf1, 0xf0, 0xf9, 0xf7, 0x4f, 0xfa, 0x24, 0x1a, 0x06, 0xe0, + 0x8a, 0x42, 0x04, 0xd2, 0xb1, 0xfb, 0xf2, 0xf0, 0xf9, 0xf7, 0x47, 0xfa, + 0x04, 0x19, 0x20, 0x46, 0x10, 0xbd, 0x38, 0xb5, 0x04, 0x46, 0x1f, 0x2a, + 0xac, 0xbf, 0x6f, 0xf0, 0x14, 0x00, 0xc2, 0xf1, 0x0a, 0x00, 0x0d, 0x46, + 0x04, 0x9a, 0x19, 0x46, 0xff, 0xf7, 0xe0, 0xff, 0xff, 0xf7, 0xd2, 0xff, + 0x21, 0x88, 0x4e, 0xf2, 0xff, 0x02, 0x11, 0x40, 0x41, 0xea, 0x00, 0x21, + 0x21, 0x80, 0x29, 0x88, 0x17, 0xe0, 0x38, 0xb5, 0x05, 0x46, 0x0f, 0x29, + 0x14, 0x46, 0xac, 0xbf, 0x6f, 0xf0, 0x0e, 0x00, 0x48, 0x42, 0x1a, 0x46, + 0x21, 0x46, 0xff, 0xf7, 0xc9, 0xff, 0x00, 0x28, 0x58, 0xbf, 0x00, 0x20, + 0x04, 0xd5, 0x10, 0xf1, 0x0e, 0x0f, 0xb4, 0xbf, 0x0f, 0x20, 0x40, 0x42, + 0x29, 0x88, 0x4f, 0xf2, 0xff, 0x02, 0x11, 0x40, 0x41, 0xea, 0x00, 0x20, + 0x28, 0x80, 0x31, 0xbd, 0xf8, 0xb5, 0x05, 0x46, 0x0c, 0x46, 0x10, 0x46, + 0x1e, 0x46, 0xf7, 0xf7, 0xd3, 0xff, 0x79, 0x49, 0xf8, 0xf7, 0x6e, 0xf9, + 0x07, 0x46, 0x30, 0x46, 0xf7, 0xf7, 0xcc, 0xff, 0x01, 0x46, 0x38, 0x46, + 0xf7, 0xf7, 0xd8, 0xff, 0xff, 0xf7, 0x64, 0xf8, 0x06, 0x99, 0x46, 0x1a, + 0x30, 0x00, 0x18, 0xbf, 0x01, 0x20, 0xc0, 0xb2, 0xf9, 0xf7, 0xb7, 0xf9, + 0x30, 0x46, 0xf7, 0xf7, 0xbb, 0xff, 0x4f, 0xf0, 0xff, 0x37, 0x39, 0x46, + 0xff, 0xf7, 0x5e, 0xfa, 0x01, 0x46, 0x6b, 0x48, 0xf8, 0xf7, 0x40, 0xf8, + 0xf8, 0xf7, 0xba, 0xf9, 0xff, 0xf7, 0x80, 0xff, 0x2a, 0x88, 0x01, 0x02, + 0xc2, 0xf3, 0x04, 0x23, 0x98, 0x42, 0x04, 0xd2, 0x4e, 0xf2, 0xff, 0x03, + 0x1a, 0x40, 0x0a, 0x43, 0x2a, 0x80, 0x22, 0x88, 0xc2, 0xf3, 0x04, 0x23, + 0x98, 0x42, 0x04, 0xd2, 0x4e, 0xf2, 0xff, 0x00, 0x10, 0x40, 0x08, 0x43, + 0x20, 0x80, 0xf1, 0xbd, 0x02, 0x88, 0x61, 0xf3, 0x0a, 0x22, 0x02, 0x80, + 0x70, 0x47, 0x02, 0x88, 0x02, 0xf4, 0x7f, 0x42, 0x11, 0x43, 0x01, 0x80, + 0x70, 0x47, 0x40, 0x68, 0xc9, 0x08, 0xf4, 0xf7, 0x2b, 0xba, 0x38, 0xb5, + 0x04, 0x46, 0x00, 0xf0, 0x3e, 0xf8, 0x00, 0x25, 0x00, 0x28, 0x5c, 0xbf, + 0x21, 0x68, 0x01, 0xeb, 0xc0, 0x05, 0x28, 0x46, 0x32, 0xbd, 0x38, 0xb5, + 0x05, 0x46, 0x00, 0xf0, 0x32, 0xf8, 0x00, 0x24, 0x00, 0x28, 0x0b, 0xd4, + 0x69, 0x68, 0xc2, 0x10, 0x00, 0xf0, 0x07, 0x00, 0x51, 0x5c, 0x01, 0x22, + 0x02, 0xfa, 0x00, 0xf0, 0x08, 0x40, 0x01, 0x28, 0xa8, 0xbf, 0x01, 0x24, + 0x20, 0x46, 0x32, 0xbd, 0x70, 0xb5, 0x04, 0x46, 0x15, 0x46, 0x00, 0xf0, + 0x1c, 0xf8, 0x00, 0x28, 0x18, 0xd4, 0x00, 0xf0, 0x07, 0x02, 0x01, 0x23, + 0x03, 0xfa, 0x02, 0xf2, 0x63, 0x68, 0xc1, 0x10, 0xce, 0x5c, 0x96, 0x43, + 0xce, 0x54, 0x23, 0x68, 0x03, 0xeb, 0xc0, 0x00, 0x2b, 0x88, 0x03, 0x80, + 0x6b, 0x88, 0x43, 0x80, 0xab, 0x88, 0x83, 0x80, 0xeb, 0x88, 0xc3, 0x80, + 0x60, 0x68, 0x0b, 0x5c, 0x1a, 0x43, 0x0a, 0x54, 0x70, 0xbd, 0x03, 0x7a, + 0x4f, 0xf0, 0xff, 0x32, 0x99, 0x42, 0x22, 0xbf, 0x40, 0x7a, 0x88, 0x42, + 0xca, 0x1a, 0x10, 0x46, 0x70, 0x47, 0x70, 0xb5, 0x3c, 0x20, 0xf9, 0xf7, + 0xf6, 0xf9, 0x29, 0x48, 0x04, 0x88, 0x4f, 0xf6, 0xfc, 0x71, 0x21, 0x40, + 0x01, 0x80, 0x00, 0xf0, 0x19, 0xf8, 0x22, 0x48, 0xb0, 0xf9, 0x14, 0x10, + 0x00, 0x29, 0x10, 0xd4, 0x00, 0x22, 0x0f, 0xf2, 0xec, 0x03, 0x33, 0xf8, + 0x12, 0x50, 0x2c, 0x42, 0x06, 0xd0, 0x00, 0xeb, 0x42, 0x05, 0x2e, 0x8a, + 0xb1, 0x42, 0xa4, 0xbf, 0x76, 0x1c, 0x2e, 0x82, 0x52, 0x1c, 0x02, 0x2a, + 0xf1, 0xd3, 0xbd, 0xe8, 0x70, 0x40, 0x51, 0xe5, 0x4f, 0xf4, 0x80, 0x70, + 0x16, 0x49, 0x08, 0x80, 0x02, 0x20, 0xf9, 0xf7, 0x4f, 0xb9, 0x00, 0x00, + 0x00, 0xe1, 0x00, 0xe0, 0x80, 0xe1, 0x00, 0xe0, 0x78, 0x29, 0x00, 0x20, + 0x00, 0x00, 0xa6, 0x0e, 0x4c, 0x1f, 0x00, 0x20, 0x80, 0xa2, 0x00, 0x20, + 0x14, 0xc8, 0x00, 0x20, 0x02, 0x08, 0x00, 0x41, 0x20, 0x01, 0x00, 0x41, + 0xfe, 0x01, 0x00, 0x41, 0x22, 0x01, 0x00, 0x41, 0x24, 0x01, 0x00, 0x41, + 0x26, 0x01, 0x00, 0x41, 0x28, 0x01, 0x00, 0x41, 0x30, 0x01, 0x00, 0x41, + 0x32, 0x01, 0x00, 0x41, 0x34, 0x01, 0x00, 0x41, 0x36, 0x01, 0x00, 0x41, + 0xcc, 0xf2, 0x00, 0x20, 0x6c, 0x1f, 0x00, 0x20, 0x08, 0x08, 0x00, 0x41, + 0x00, 0x01, 0x00, 0x41, 0xfc, 0x01, 0x00, 0x41, 0x04, 0x01, 0x00, 0x41, + 0x34, 0x80, 0x37, 0x3a, 0x48, 0xe1, 0x9a, 0xbf, 0x00, 0x00, 0x00, 0x00, + 0x14, 0xc8, 0x00, 0x20, 0x14, 0xc8, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, + 0x24, 0xc8, 0x00, 0x20, 0x14, 0xc8, 0x00, 0x20, 0x14, 0xc8, 0x00, 0x20, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x20, 0x00, 0x20, + 0x78, 0x20, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x8c, 0x20, 0x00, 0x20, + 0xa0, 0x20, 0x00, 0x20, 0xb4, 0x20, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x1f, 0xb5, 0x00, 0xf0, + 0xb7, 0xf8, 0x21, 0x21, 0x01, 0x60, 0x1f, 0xbd, 0xf8, 0xb5, 0x0c, 0x46, + 0x2b, 0x49, 0xf8, 0xf7, 0x4d, 0xf9, 0x05, 0x46, 0x12, 0xd8, 0x2a, 0x4e, + 0x31, 0x46, 0xf8, 0xf7, 0x3f, 0xf8, 0x29, 0x49, 0xf7, 0xf7, 0xa0, 0xff, + 0x07, 0x46, 0x28, 0x46, 0x31, 0x46, 0xf7, 0xf7, 0x9b, 0xff, 0x01, 0x46, + 0x38, 0x46, 0xf7, 0xf7, 0xa5, 0xfe, 0x05, 0x46, 0x44, 0xf0, 0x01, 0x04, + 0x28, 0x46, 0x22, 0x49, 0xf8, 0xf7, 0x1a, 0xf8, 0x03, 0xd3, 0x21, 0x49, + 0xf8, 0xf7, 0x30, 0xf9, 0x21, 0xd8, 0x29, 0x46, 0xf8, 0xf7, 0x24, 0xf8, + 0x06, 0x46, 0x28, 0x46, 0x31, 0x46, 0xf8, 0xf7, 0x1f, 0xf8, 0x1c, 0x49, + 0xf8, 0xf7, 0x1c, 0xf8, 0x29, 0x46, 0xf7, 0xf7, 0x7d, 0xff, 0x05, 0x46, + 0x19, 0x48, 0x31, 0x46, 0xf8, 0xf7, 0x14, 0xf8, 0x18, 0x49, 0xf7, 0xf7, + 0x75, 0xff, 0x31, 0x46, 0xf8, 0xf7, 0x0e, 0xf8, 0x4f, 0xf0, 0x7e, 0x51, + 0xf7, 0xf7, 0x6e, 0xff, 0x01, 0x46, 0x28, 0x46, 0xf7, 0xf7, 0x78, 0xfe, + 0x05, 0x46, 0xa0, 0x07, 0x48, 0xbf, 0x85, 0xf0, 0x00, 0x45, 0x14, 0xf0, + 0x07, 0x00, 0x07, 0xd0, 0x0f, 0xf2, 0x38, 0x01, 0x51, 0xf8, 0x20, 0x00, + 0x29, 0x46, 0xf7, 0xf7, 0x5b, 0xff, 0x05, 0x46, 0x20, 0x07, 0x48, 0xbf, + 0x85, 0xf0, 0x00, 0x45, 0x28, 0x46, 0xf2, 0xbd, 0xa4, 0x30, 0x89, 0x3e, + 0xd7, 0xb3, 0xdd, 0x3f, 0x00, 0x00, 0x80, 0xbf, 0x00, 0x00, 0x80, 0xb9, + 0x01, 0x00, 0x80, 0x39, 0x6a, 0xd5, 0x03, 0x3f, 0x2b, 0x94, 0xa9, 0x3d, + 0xb8, 0x2a, 0x59, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x92, 0x0a, 0x06, 0x3f, + 0xdb, 0x0f, 0xc9, 0x3f, 0x92, 0x0a, 0x86, 0x3f, 0xdb, 0x0f, 0xc9, 0x3f, + 0x92, 0x0a, 0x06, 0x40, 0xdb, 0x0f, 0x49, 0x40, 0x36, 0x8d, 0x27, 0x40, + 0x02, 0x68, 0x02, 0xf0, 0x00, 0x43, 0x01, 0x21, 0x52, 0x02, 0x52, 0x0a, + 0x02, 0xd1, 0x06, 0xe0, 0x52, 0x00, 0x49, 0x1e, 0x5f, 0xea, 0x02, 0x2c, + 0xfa, 0xd5, 0x52, 0x02, 0x52, 0x0a, 0x1a, 0x43, 0x02, 0x60, 0x08, 0x46, + 0x70, 0x47, 0x02, 0x68, 0xc2, 0xf3, 0xc7, 0x52, 0xff, 0x2a, 0x05, 0xd1, + 0x00, 0x68, 0x40, 0x02, 0x0c, 0xbf, 0x01, 0x20, 0x02, 0x20, 0x70, 0x47, + 0x03, 0x68, 0x5b, 0x00, 0x16, 0xd0, 0xc2, 0xf1, 0x96, 0x02, 0x52, 0x1a, + 0x01, 0x2a, 0x11, 0xdb, 0x18, 0x2a, 0x04, 0xdb, 0x01, 0x68, 0x01, 0xf0, + 0x00, 0x41, 0x01, 0x60, 0x07, 0xe0, 0x01, 0x21, 0x91, 0x40, 0x02, 0x68, + 0x49, 0x1e, 0x11, 0x40, 0x4a, 0x40, 0x02, 0x60, 0x11, 0xb1, 0x4f, 0xf0, + 0xff, 0x30, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x01, 0x48, 0xf1, 0xf7, + 0x86, 0xb9, 0x00, 0x00, 0x1c, 0xbd, 0x00, 0x20, 0x2d, 0xe9, 0xf0, 0x4d, + 0x04, 0x46, 0x0d, 0x46, 0x27, 0x68, 0xc7, 0xf3, 0xc7, 0x51, 0xff, 0x29, + 0x16, 0x46, 0x09, 0xd0, 0x11, 0xb1, 0x4f, 0xf0, 0xff, 0x30, 0x09, 0xe0, + 0x78, 0x02, 0x0c, 0xbf, 0x00, 0x20, 0x6f, 0xf0, 0x01, 0x00, 0x03, 0xe0, + 0x78, 0x02, 0x14, 0xbf, 0x02, 0x20, 0x01, 0x20, 0xc5, 0xf3, 0xc7, 0x52, + 0xff, 0x2a, 0x09, 0xd0, 0x12, 0xb1, 0x4f, 0xf0, 0xff, 0x31, 0x09, 0xe0, + 0x69, 0x02, 0x0c, 0xbf, 0x00, 0x21, 0x6f, 0xf0, 0x01, 0x01, 0x03, 0xe0, + 0x69, 0x02, 0x14, 0xbf, 0x02, 0x21, 0x01, 0x21, 0x02, 0x00, 0x48, 0xbf, + 0x00, 0x29, 0x3e, 0xd4, 0x02, 0x28, 0x00, 0xf0, 0xc6, 0x80, 0x02, 0x29, + 0x08, 0xbf, 0x25, 0x60, 0x18, 0xd0, 0x39, 0xb9, 0x38, 0x46, 0x4f, 0xf0, + 0xff, 0x41, 0xf7, 0xf7, 0x35, 0xff, 0x0a, 0xd0, 0x25, 0x60, 0x38, 0xe0, + 0x01, 0x29, 0x10, 0xd1, 0x38, 0x46, 0x5c, 0x49, 0xf7, 0xf7, 0x2c, 0xff, + 0x18, 0xbf, 0x25, 0x60, 0x40, 0xd1, 0xff, 0xf7, 0xb1, 0xff, 0x21, 0x21, + 0x01, 0x60, 0x6f, 0xf0, 0x00, 0x40, 0x20, 0x60, 0x02, 0x20, 0xbd, 0xe8, + 0xf0, 0x8d, 0x70, 0xb9, 0x25, 0x60, 0x31, 0x46, 0x20, 0x46, 0x00, 0xf0, + 0x61, 0xff, 0x04, 0x00, 0x18, 0xbf, 0x01, 0x2c, 0x40, 0xf0, 0x9a, 0x80, + 0xff, 0xf7, 0x9c, 0xff, 0x22, 0x21, 0x01, 0x60, 0x94, 0xe0, 0x38, 0x46, + 0x4f, 0xf0, 0xff, 0x41, 0xf7, 0xf7, 0x0a, 0xff, 0x0a, 0xd1, 0x08, 0x46, + 0x29, 0x46, 0xf7, 0xf7, 0x25, 0xff, 0x20, 0x60, 0x1a, 0xe0, 0x38, 0x46, + 0x46, 0x49, 0xf7, 0xf7, 0x0d, 0xff, 0x07, 0xd2, 0x00, 0x20, 0x29, 0x46, + 0xf7, 0xf7, 0x1a, 0xff, 0x20, 0x60, 0x00, 0x20, 0xbd, 0xe8, 0xf0, 0x8d, + 0x41, 0x49, 0xf8, 0xf7, 0x1b, 0xf8, 0x0c, 0xd8, 0x4f, 0xf0, 0xff, 0x40, + 0x29, 0x46, 0xf7, 0xf7, 0x0d, 0xff, 0x20, 0x60, 0xff, 0xf7, 0x74, 0xff, + 0x22, 0x21, 0x01, 0x60, 0x01, 0x20, 0xbd, 0xe8, 0xf0, 0x8d, 0x3a, 0x48, + 0x39, 0x46, 0xf7, 0xf7, 0x01, 0xff, 0x00, 0x21, 0xf7, 0xf7, 0xec, 0xfe, + 0x34, 0xbf, 0x4f, 0xf0, 0x3f, 0x41, 0x4f, 0xf0, 0x7c, 0x51, 0xf7, 0xf7, + 0x5b, 0xfe, 0xf7, 0xf7, 0x61, 0xff, 0x80, 0x46, 0xf7, 0xf7, 0x4a, 0xfd, + 0x82, 0x46, 0x31, 0x48, 0x51, 0x46, 0xf7, 0xf7, 0xed, 0xfe, 0x01, 0x46, + 0x38, 0x46, 0xf7, 0xf7, 0xd9, 0xfd, 0x07, 0x46, 0x2d, 0x48, 0x51, 0x46, + 0xf7, 0xf7, 0xe4, 0xfe, 0x01, 0x46, 0x38, 0x46, 0xf7, 0xf7, 0xd0, 0xfd, + 0x4f, 0xf0, 0x33, 0x41, 0xf7, 0xf7, 0xe4, 0xff, 0x82, 0x46, 0x03, 0xd8, + 0x27, 0x49, 0xf7, 0xf7, 0xc5, 0xfe, 0x2d, 0xd3, 0x51, 0x46, 0xf7, 0xf7, + 0xd3, 0xfe, 0x83, 0x46, 0x24, 0x48, 0x59, 0x46, 0xf7, 0xf7, 0xce, 0xfe, + 0x07, 0x46, 0x23, 0x48, 0x59, 0x46, 0xf7, 0xf7, 0xc9, 0xfe, 0x4f, 0xf0, + 0x7c, 0x51, 0xf7, 0xf7, 0x29, 0xfe, 0x51, 0x46, 0xf7, 0xf7, 0xc2, 0xfe, + 0x82, 0x46, 0x38, 0x46, 0x51, 0x46, 0xf7, 0xf7, 0x21, 0xfe, 0x4f, 0xf0, + 0x7e, 0x51, 0xf7, 0xf7, 0x1d, 0xfe, 0x83, 0x46, 0x38, 0x46, 0x51, 0x46, + 0xf7, 0xf7, 0xa4, 0xfd, 0x4f, 0xf0, 0x7e, 0x51, 0xf7, 0xf7, 0x14, 0xfe, + 0x01, 0x46, 0x58, 0x46, 0xf7, 0xf7, 0x1e, 0xfd, 0x29, 0x46, 0xf7, 0xf7, + 0xa9, 0xfe, 0x05, 0x46, 0x25, 0x60, 0x06, 0xeb, 0x08, 0x01, 0x20, 0x46, + 0x00, 0xf0, 0xca, 0xfe, 0x04, 0x00, 0x18, 0xbf, 0x01, 0x2c, 0x03, 0xd1, + 0xff, 0xf7, 0x06, 0xff, 0x22, 0x21, 0x01, 0x60, 0x20, 0x46, 0xbd, 0xe8, + 0xf0, 0x8d, 0x00, 0xbf, 0x00, 0x00, 0x80, 0xff, 0x00, 0x00, 0x65, 0xc3, + 0x01, 0x00, 0x65, 0x43, 0x3b, 0xaa, 0xb8, 0x3f, 0x00, 0x60, 0x31, 0x3f, + 0xbf, 0xbf, 0x90, 0x39, 0x01, 0x00, 0x00, 0x33, 0x9e, 0xbf, 0xcc, 0x3d, + 0x13, 0x54, 0x08, 0x3c, 0x70, 0x47, 0x00, 0x00, 0xd2, 0xb2, 0x20, 0x3a, + 0x22, 0xbf, 0x41, 0xfa, 0x02, 0xf0, 0xc9, 0x17, 0x70, 0x47, 0x20, 0x32, + 0xd1, 0x41, 0xd0, 0x40, 0x48, 0x40, 0x91, 0x40, 0xd1, 0x40, 0x48, 0x40, + 0x91, 0x40, 0x11, 0x41, 0x70, 0x47, 0x70, 0x47, 0x70, 0x47, 0x00, 0xf0, + 0xad, 0xb9, 0x70, 0x47, 0x80, 0xb5, 0xf5, 0xf7, 0x0c, 0xfa, 0xbd, 0xe8, + 0x01, 0x40, 0x00, 0xf0, 0xa5, 0xb9, 0x70, 0x47, 0x00, 0xf0, 0xa1, 0xb8, + 0x00, 0xb5, 0x00, 0xbf, 0x13, 0x00, 0x96, 0x46, 0x94, 0x46, 0x10, 0x39, + 0x28, 0xbf, 0xa0, 0xe8, 0x0c, 0x50, 0xfa, 0xd8, 0x5f, 0xea, 0x41, 0x7c, + 0x28, 0xbf, 0x0c, 0xc0, 0x48, 0xbf, 0x40, 0xf8, 0x04, 0x2b, 0xc9, 0x07, + 0x28, 0xbf, 0x20, 0xf8, 0x02, 0x2b, 0x48, 0xbf, 0x00, 0xf8, 0x01, 0x2b, + 0x00, 0xbd, 0x00, 0x00, 0x80, 0xb5, 0x4f, 0xf0, 0x92, 0x41, 0x00, 0x20, + 0x08, 0x60, 0x06, 0x21, 0x0f, 0x20, 0xf8, 0xf7, 0xfa, 0xfe, 0xbd, 0xe8, + 0x02, 0x40, 0x02, 0xe0, 0x0c, 0x49, 0x08, 0x60, 0x70, 0x47, 0x0f, 0x20, + 0xf8, 0xf7, 0xdc, 0xbe, 0x1c, 0xb5, 0x4f, 0xf0, 0x92, 0x44, 0x08, 0x49, + 0x20, 0x68, 0x00, 0x90, 0x60, 0x68, 0x09, 0x68, 0x01, 0x90, 0x00, 0x98, + 0x00, 0xf0, 0x3f, 0x00, 0x00, 0x90, 0x68, 0x46, 0x88, 0x47, 0x00, 0x20, + 0x20, 0x60, 0x13, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x6c, 0xf3, 0x00, 0x20, + 0x10, 0xb5, 0x93, 0x48, 0x93, 0x4c, 0x4f, 0xf4, 0xf0, 0x01, 0x01, 0x62, + 0xc2, 0x6a, 0x42, 0xf4, 0xf0, 0x02, 0xc2, 0x62, 0x02, 0x6b, 0x42, 0xf4, + 0xf0, 0x02, 0x02, 0x63, 0x01, 0x60, 0x11, 0x20, 0xf8, 0xf7, 0xc3, 0xfe, + 0x06, 0x21, 0x11, 0x20, 0xf8, 0xf7, 0xc5, 0xfe, 0x11, 0x20, 0xf8, 0xf7, + 0xad, 0xfe, 0x4f, 0xf4, 0x40, 0x30, 0xe0, 0x62, 0xa1, 0x6b, 0x41, 0xf4, + 0x40, 0x31, 0xa1, 0x63, 0xe1, 0x6b, 0x41, 0xf4, 0x40, 0x31, 0xe1, 0x63, + 0x20, 0x60, 0x21, 0x20, 0xf8, 0xf7, 0xad, 0xfe, 0x06, 0x21, 0x21, 0x20, + 0xf8, 0xf7, 0xaf, 0xfe, 0x21, 0x20, 0xf8, 0xf7, 0x97, 0xfe, 0x00, 0x20, + 0x60, 0x60, 0x22, 0x20, 0xf8, 0xf7, 0xa1, 0xfe, 0x06, 0x21, 0x22, 0x20, + 0xf8, 0xf7, 0xa3, 0xfe, 0x22, 0x20, 0xf8, 0xf7, 0x8b, 0xfe, 0x00, 0x20, + 0xa0, 0x60, 0x23, 0x20, 0xf8, 0xf7, 0x95, 0xfe, 0x06, 0x21, 0x23, 0x20, + 0xf8, 0xf7, 0x97, 0xfe, 0xbd, 0xe8, 0x10, 0x40, 0x23, 0x20, 0xf8, 0xf7, + 0x7d, 0xbe, 0x80, 0xb5, 0x11, 0x20, 0xf8, 0xf7, 0x82, 0xfe, 0x21, 0x20, + 0xf8, 0xf7, 0x7f, 0xfe, 0x22, 0x20, 0xf8, 0xf7, 0x7c, 0xfe, 0xbd, 0xe8, + 0x02, 0x40, 0x23, 0x20, 0xf8, 0xf7, 0x77, 0xbe, 0x69, 0x49, 0x51, 0xf8, + 0x20, 0x00, 0x00, 0xb1, 0x01, 0x20, 0xc0, 0xb2, 0x70, 0x47, 0x80, 0xb5, + 0x22, 0x20, 0xf8, 0xf7, 0x72, 0xfe, 0xbd, 0xe8, 0x02, 0x40, 0x23, 0x20, + 0xf8, 0xf7, 0x6d, 0xbe, 0xf8, 0xb5, 0x00, 0x24, 0x0f, 0xf2, 0x88, 0x15, + 0x5d, 0x4e, 0x5f, 0x4f, 0x57, 0xf8, 0x24, 0x00, 0x38, 0xb1, 0x30, 0x68, + 0x55, 0xf8, 0x24, 0x10, 0x08, 0x43, 0x30, 0x60, 0x11, 0x20, 0xf8, 0xf7, + 0x5c, 0xfe, 0x07, 0xeb, 0x84, 0x01, 0x64, 0x1c, 0x00, 0x20, 0x02, 0x2c, + 0xc8, 0x60, 0xed, 0xd3, 0xf1, 0xbd, 0x10, 0xb5, 0x54, 0x4c, 0xa0, 0x68, + 0x30, 0xb1, 0x52, 0x49, 0x4f, 0xf4, 0x40, 0x30, 0x08, 0x60, 0x21, 0x20, + 0xf8, 0xf7, 0x49, 0xfe, 0x00, 0x20, 0x60, 0x61, 0x10, 0xbd, 0x2d, 0xe9, + 0xf8, 0x4f, 0x01, 0x21, 0x36, 0x20, 0xf8, 0xf7, 0xba, 0xfe, 0x00, 0x24, + 0x48, 0x4d, 0xdf, 0xf8, 0x2c, 0x81, 0x0f, 0xf2, 0x44, 0x1b, 0x48, 0x4e, + 0x0f, 0xf2, 0x24, 0x19, 0x0f, 0xf2, 0x2c, 0x1a, 0x5a, 0xf8, 0x24, 0x00, + 0x59, 0xf8, 0x24, 0x70, 0x01, 0x68, 0x39, 0x40, 0x29, 0xd0, 0x01, 0x60, + 0xf0, 0x69, 0xa0, 0x42, 0x05, 0xd1, 0x01, 0x20, 0xb0, 0x61, 0x01, 0x21, + 0x3b, 0x20, 0xf8, 0xf7, 0x9e, 0xfe, 0x5b, 0xf8, 0x24, 0x00, 0x00, 0x68, + 0x06, 0xeb, 0x84, 0x01, 0x38, 0x40, 0xca, 0x68, 0x46, 0xf8, 0x24, 0x00, + 0x52, 0x1c, 0xca, 0x60, 0x30, 0xb1, 0xb8, 0xf8, 0x56, 0x00, 0x90, 0x42, + 0x02, 0xd2, 0x28, 0x68, 0xb8, 0x43, 0x28, 0x60, 0x20, 0x46, 0xff, 0xf7, + 0xbf, 0xfa, 0x56, 0xf8, 0x24, 0x10, 0x01, 0xb1, 0x01, 0x21, 0x04, 0xf1, + 0x38, 0x00, 0xc9, 0xb2, 0xc0, 0xb2, 0xf8, 0xf7, 0x7e, 0xfe, 0x64, 0x1c, + 0x02, 0x2c, 0xcb, 0xd3, 0xbd, 0xe8, 0xf4, 0x4f, 0x00, 0x21, 0x36, 0x20, + 0xf8, 0xf7, 0x75, 0xbe, 0x38, 0xb5, 0x01, 0x21, 0x37, 0x20, 0xf8, 0xf7, + 0x70, 0xfe, 0x25, 0x4c, 0x25, 0x4d, 0xe0, 0x6a, 0x00, 0xf4, 0x40, 0x30, + 0xe0, 0x62, 0xe9, 0x69, 0x02, 0x29, 0x06, 0xd1, 0x28, 0xb1, 0x01, 0x20, + 0xa8, 0x61, 0x01, 0x21, 0x3b, 0x20, 0xf8, 0xf7, 0x60, 0xfe, 0x20, 0x6b, + 0x69, 0x69, 0x00, 0xf4, 0x40, 0x30, 0x49, 0x1c, 0xa8, 0x60, 0x69, 0x61, + 0x50, 0xb1, 0x1b, 0x48, 0xb0, 0xf8, 0x56, 0x00, 0x88, 0x42, 0x3c, 0xbf, + 0x00, 0x20, 0x20, 0x60, 0xa9, 0x68, 0x11, 0xb1, 0x01, 0x21, 0x00, 0xe0, + 0x00, 0x21, 0xc9, 0xb2, 0x3a, 0x20, 0xf8, 0xf7, 0x48, 0xfe, 0xbd, 0xe8, + 0x34, 0x40, 0x00, 0x21, 0x37, 0x20, 0xf8, 0xf7, 0x42, 0xbe, 0x0f, 0x49, + 0x0f, 0xf2, 0x58, 0x02, 0x0f, 0xf2, 0x3c, 0x03, 0xc8, 0x61, 0x52, 0xf8, + 0x20, 0x20, 0x12, 0x68, 0x53, 0xf8, 0x20, 0x00, 0x10, 0x40, 0x88, 0x61, + 0x01, 0x00, 0x18, 0xbf, 0x01, 0x21, 0xc9, 0xb2, 0x3b, 0x20, 0xf8, 0xf7, + 0x2e, 0xbe, 0x05, 0x49, 0x89, 0x69, 0x00, 0x20, 0x01, 0xb1, 0x01, 0x20, + 0x70, 0x47, 0x00, 0x00, 0x20, 0x00, 0x00, 0x50, 0x14, 0x00, 0x00, 0x58, + 0xac, 0xf2, 0x00, 0x20, 0x4c, 0x1f, 0x00, 0x20, 0x00, 0x00, 0x50, 0x00, + 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x03, 0x00, 0x40, 0x00, 0x00, 0x50, + 0x40, 0x00, 0x00, 0x50, 0x40, 0x00, 0x00, 0x58, 0x44, 0x00, 0x00, 0x50, + 0x44, 0x00, 0x00, 0x50, 0x44, 0x00, 0x00, 0x58, 0x80, 0xb5, 0x00, 0xf0, + 0x13, 0xf8, 0x19, 0x20, 0xf8, 0xf7, 0x78, 0xfd, 0x4f, 0xf0, 0xa4, 0x41, + 0x15, 0x48, 0x08, 0x60, 0x00, 0x21, 0x19, 0x20, 0xf8, 0xf7, 0x8b, 0xfd, + 0xbd, 0xe8, 0x01, 0x40, 0x12, 0x49, 0x01, 0x20, 0x08, 0x60, 0x19, 0x20, + 0xf8, 0xf7, 0x6e, 0xbd, 0x80, 0xb5, 0x19, 0x20, 0xf8, 0xf7, 0x73, 0xfd, + 0x0d, 0x49, 0x00, 0x20, 0x08, 0x60, 0x01, 0xbd, 0xef, 0xf3, 0x11, 0x80, + 0x60, 0x21, 0x81, 0xf3, 0x11, 0x88, 0x09, 0x49, 0x0a, 0x68, 0x42, 0xf0, + 0x02, 0x03, 0x0b, 0x60, 0x22, 0xf0, 0x02, 0x02, 0x0a, 0x60, 0x80, 0xf3, + 0x11, 0x88, 0x70, 0x47, 0x03, 0x48, 0x00, 0x68, 0x00, 0xf0, 0x01, 0x00, + 0x70, 0x47, 0x00, 0x00, 0x00, 0x70, 0x17, 0x00, 0x04, 0x00, 0x00, 0x52, + 0x00, 0x20, 0xf8, 0xf7, 0xfe, 0xbc, 0x00, 0x00, 0x09, 0x42, 0x40, 0xf1, + 0x0d, 0x80, 0xf4, 0x46, 0x49, 0x42, 0x40, 0x42, 0x71, 0xf1, 0x00, 0x01, + 0x00, 0xf0, 0x06, 0xf8, 0x51, 0xf0, 0x00, 0x41, 0x60, 0x47, 0x00, 0x00, + 0x09, 0x42, 0x00, 0xbf, 0x08, 0xbf, 0x00, 0xf0, 0x15, 0xbd, 0x02, 0x46, + 0x08, 0x46, 0xb0, 0xfa, 0x80, 0xf1, 0x50, 0x40, 0x8a, 0x40, 0xc1, 0xf1, + 0x20, 0x01, 0xc8, 0x41, 0x50, 0x40, 0xc9, 0x1e, 0x01, 0xf5, 0x84, 0x61, + 0x09, 0x05, 0x01, 0xeb, 0xd0, 0x21, 0x40, 0x05, 0x40, 0xea, 0xd2, 0x20, + 0x52, 0x05, 0x72, 0xf1, 0x00, 0x42, 0x50, 0xf1, 0x00, 0x00, 0x41, 0xf1, + 0x00, 0x01, 0x70, 0x47, 0xf0, 0xb4, 0x4f, 0xf0, 0x00, 0x45, 0x91, 0xea, + 0x03, 0x0c, 0x44, 0xbf, 0x6b, 0x40, 0x00, 0xf0, 0xbf, 0xb9, 0x00, 0xbf, + 0x84, 0x1a, 0x71, 0xeb, 0x03, 0x06, 0x03, 0xd2, 0x00, 0x1b, 0xb1, 0x41, + 0x12, 0x19, 0x73, 0x41, 0x4f, 0xf4, 0x00, 0x1c, 0x1c, 0xeb, 0x41, 0x0f, + 0x34, 0xbf, 0x7c, 0xeb, 0x43, 0x04, 0x43, 0xe0, 0x0c, 0x0d, 0xa4, 0xeb, + 0x13, 0x56, 0x35, 0x2e, 0x50, 0xdc, 0x45, 0xea, 0xc3, 0x23, 0xdb, 0x0a, + 0x45, 0xea, 0xc1, 0x21, 0xc9, 0x12, 0xb6, 0xf1, 0x20, 0x05, 0x0d, 0xdd, + 0x63, 0xfa, 0x05, 0xf6, 0xeb, 0x40, 0x86, 0xea, 0x03, 0x05, 0x12, 0x42, + 0x18, 0xbf, 0x45, 0xf0, 0x01, 0x05, 0xc0, 0x18, 0x51, 0xf1, 0x00, 0x01, + 0x0c, 0xd2, 0x13, 0xe0, 0x62, 0xfa, 0x06, 0xf5, 0xf2, 0x40, 0x55, 0x40, + 0xf3, 0x41, 0x5a, 0x40, 0xb3, 0x40, 0xf3, 0x40, 0x5a, 0x40, 0x80, 0x18, + 0x59, 0x41, 0x07, 0xd3, 0x49, 0x08, 0x5f, 0xea, 0x30, 0x00, 0x5f, 0xea, + 0x35, 0x05, 0x28, 0xbf, 0x45, 0xf0, 0x01, 0x05, 0x01, 0xf5, 0x80, 0x11, + 0x42, 0x08, 0x75, 0xf1, 0x00, 0x42, 0x50, 0xf1, 0x00, 0x00, 0x41, 0xeb, + 0x04, 0x51, 0xf0, 0xbc, 0x4f, 0xf4, 0x00, 0x1c, 0x1c, 0xeb, 0x41, 0x0f, + 0x38, 0xbf, 0x70, 0x47, 0x00, 0x20, 0x09, 0x0d, 0x09, 0x05, 0x70, 0x47, + 0x1c, 0xeb, 0x41, 0x0f, 0x10, 0xd2, 0x52, 0xea, 0x43, 0x06, 0x0b, 0xd0, + 0xbc, 0xeb, 0x41, 0x0f, 0x05, 0xd8, 0x0c, 0x0d, 0xab, 0x43, 0x66, 0x1e, + 0x34, 0x2e, 0xb5, 0xdd, 0x02, 0xe0, 0xab, 0x43, 0x80, 0x18, 0x59, 0x41, + 0xf0, 0xbc, 0x70, 0x47, 0xf0, 0xbc, 0x70, 0x47, 0xb0, 0xb5, 0x81, 0xea, + 0x03, 0x0c, 0x0c, 0xf0, 0x00, 0x4c, 0x40, 0xf2, 0xff, 0x75, 0x15, 0xea, + 0x11, 0x54, 0x1d, 0xbf, 0x15, 0xea, 0x13, 0x57, 0xac, 0x42, 0xaf, 0x42, + 0x39, 0xe0, 0xe4, 0x19, 0x23, 0xea, 0x45, 0x53, 0x43, 0xf4, 0x80, 0x13, + 0xc9, 0x02, 0x41, 0xf0, 0x00, 0x41, 0x41, 0xea, 0x50, 0x5e, 0xc7, 0x02, + 0x11, 0x00, 0xa7, 0xfb, 0x02, 0x02, 0x00, 0x28, 0x4f, 0xf0, 0x00, 0x00, + 0xee, 0xfb, 0x01, 0x20, 0x4f, 0xf0, 0x00, 0x01, 0xe3, 0xfb, 0x07, 0x21, + 0x18, 0xbf, 0x42, 0xf0, 0x01, 0x02, 0x40, 0x18, 0x00, 0x21, 0x49, 0x41, + 0xe3, 0xfb, 0x0e, 0x01, 0xa4, 0xf5, 0x80, 0x64, 0x0f, 0x03, 0x02, 0xd2, + 0x52, 0x00, 0x40, 0x41, 0x49, 0x41, 0x54, 0xf1, 0x01, 0x04, 0x6c, 0xdd, + 0x47, 0x08, 0x72, 0xf1, 0x00, 0x42, 0x50, 0xf1, 0x00, 0x00, 0x51, 0xeb, + 0x04, 0x51, 0xa1, 0xf5, 0x80, 0x11, 0x5c, 0xbf, 0x41, 0xea, 0x0c, 0x01, + 0xb0, 0xbd, 0x4c, 0xea, 0x05, 0x51, 0x00, 0x20, 0xb0, 0xbd, 0x05, 0xea, + 0x13, 0x57, 0xac, 0x42, 0x14, 0xbf, 0xaf, 0x42, 0x41, 0xe0, 0x50, 0xea, + 0x41, 0x0e, 0x1c, 0xbf, 0x52, 0xea, 0x43, 0x0e, 0x02, 0xe0, 0x61, 0x46, + 0x00, 0x20, 0xb0, 0xbd, 0x24, 0x42, 0x3c, 0x44, 0x1b, 0xd1, 0x5f, 0xea, + 0x07, 0x0e, 0xf6, 0xd0, 0x09, 0x03, 0x02, 0xbf, 0x01, 0x46, 0x00, 0x20, + 0xae, 0xf1, 0x14, 0x0e, 0xb1, 0xfa, 0x81, 0xf7, 0xae, 0xeb, 0x07, 0x04, + 0x01, 0xfa, 0x07, 0xfe, 0x0c, 0x37, 0xc7, 0xf1, 0x20, 0x01, 0x00, 0xfa, + 0x07, 0xf7, 0xc8, 0x40, 0x4e, 0xea, 0x00, 0x0e, 0x23, 0xea, 0x45, 0x53, + 0x43, 0xf4, 0x80, 0x13, 0xa2, 0xe7, 0x33, 0xf0, 0x00, 0x43, 0xb3, 0xfa, + 0x83, 0xf7, 0x04, 0xbf, 0xb2, 0xfa, 0x82, 0xfe, 0x77, 0x44, 0x0b, 0x3f, + 0xe4, 0x1b, 0xb7, 0xf1, 0x20, 0x0e, 0x2f, 0xbf, 0x02, 0xfa, 0x0e, 0xf3, + 0xbb, 0x40, 0xc7, 0xf1, 0x20, 0x0e, 0x22, 0xfa, 0x0e, 0xfe, 0x38, 0xbf, + 0x43, 0xea, 0x0e, 0x03, 0xba, 0x40, 0x64, 0x1c, 0x82, 0xe7, 0x50, 0xea, + 0x41, 0x0e, 0x14, 0xbf, 0x52, 0xea, 0x43, 0x0e, 0x6f, 0xf0, 0x00, 0x01, + 0x4f, 0xf4, 0x00, 0x17, 0x17, 0xeb, 0x43, 0x0f, 0x8a, 0xbf, 0x19, 0x46, + 0x17, 0xeb, 0x41, 0x0f, 0xb5, 0xe7, 0x4c, 0xea, 0x05, 0x51, 0x00, 0x20, + 0xb0, 0xbd, 0xd4, 0xf1, 0x01, 0x04, 0xb4, 0xf1, 0x20, 0x07, 0x0f, 0xda, + 0xc4, 0xf1, 0x20, 0x07, 0x52, 0x08, 0x28, 0xbf, 0x42, 0xf0, 0x01, 0x02, + 0x10, 0xfa, 0x07, 0xf5, 0x01, 0xfa, 0x07, 0xf7, 0xe1, 0xbf, 0x2a, 0x43, + 0xe0, 0x40, 0x38, 0x43, 0xe1, 0x40, 0x0f, 0xe0, 0x35, 0x2c, 0x98, 0xdc, + 0xc7, 0xf1, 0x20, 0x04, 0x52, 0xea, 0x40, 0x02, 0x20, 0xfa, 0x07, 0xf2, + 0x18, 0xbf, 0x42, 0xf0, 0x01, 0x02, 0x31, 0xfa, 0x07, 0xf0, 0xa1, 0x40, + 0x0a, 0x43, 0x00, 0x21, 0x72, 0xf1, 0x00, 0x42, 0x50, 0xf1, 0x00, 0x00, + 0x51, 0xeb, 0x0c, 0x01, 0xb0, 0xbd, 0x00, 0x00, 0x40, 0xf2, 0xff, 0x7c, + 0x0b, 0x0d, 0x4d, 0xd0, 0x63, 0x45, 0x66, 0xd2, 0x30, 0xb4, 0x21, 0xea, + 0x03, 0x51, 0x41, 0xf4, 0x80, 0x11, 0x03, 0xf2, 0xfd, 0x3c, 0x5f, 0xea, + 0x5c, 0x0c, 0x01, 0xd3, 0x00, 0x18, 0x49, 0x41, 0x89, 0x00, 0x41, 0xea, + 0x90, 0x71, 0x80, 0x00, 0x4f, 0xf4, 0x40, 0x14, 0x00, 0x23, 0xe2, 0x02, + 0xd5, 0x0a, 0xb1, 0xf5, 0x10, 0x01, 0x07, 0xd4, 0x6d, 0x08, 0x1d, 0xd2, + 0x09, 0x1b, 0x64, 0x19, 0x00, 0x18, 0x49, 0x41, 0x49, 0x1b, 0xf7, 0xd5, + 0x6d, 0x08, 0x0a, 0xd2, 0x09, 0x19, 0x64, 0x1b, 0x00, 0x18, 0x49, 0x41, + 0x49, 0x1b, 0xef, 0xd5, 0x6d, 0x08, 0xf7, 0xd3, 0x01, 0xe0, 0x52, 0x08, + 0x17, 0xd0, 0xc0, 0x18, 0x61, 0x41, 0x9b, 0x1a, 0xac, 0x41, 0x00, 0x18, + 0x49, 0x41, 0x80, 0x1a, 0xa9, 0x41, 0xf4, 0xd4, 0x52, 0x08, 0x0a, 0xd0, + 0xc0, 0x1a, 0xa1, 0x41, 0x9b, 0x18, 0x6c, 0x41, 0x00, 0x18, 0x49, 0x41, + 0x80, 0x1a, 0xa9, 0x41, 0xe9, 0xd4, 0x52, 0x08, 0xf4, 0xd1, 0x5b, 0x1c, + 0x6c, 0x41, 0x61, 0x08, 0x4f, 0xea, 0x33, 0x00, 0x01, 0xeb, 0x0c, 0x51, + 0x30, 0xbc, 0x70, 0x47, 0x50, 0xea, 0x01, 0x03, 0xfb, 0xd0, 0x30, 0xb4, + 0xb1, 0xfa, 0x81, 0xf3, 0x11, 0xb9, 0xb0, 0xfa, 0x80, 0xf4, 0x1b, 0x19, + 0x0b, 0x3b, 0xb3, 0xf1, 0x20, 0x04, 0x2f, 0xbf, 0x00, 0xfa, 0x04, 0xf1, + 0x99, 0x40, 0xc3, 0xf1, 0x20, 0x04, 0x20, 0xfa, 0x04, 0xf4, 0x38, 0xbf, + 0x21, 0x43, 0x98, 0x40, 0xd3, 0xf1, 0x01, 0x03, 0x9d, 0xe7, 0x63, 0x45, + 0xe1, 0xd0, 0x11, 0xf5, 0x80, 0x1f, 0xde, 0xd8, 0x50, 0xea, 0x41, 0x01, + 0xdb, 0xd0, 0xd9, 0x43, 0xff, 0xf7, 0x66, 0xba, 0xf0, 0xb4, 0x4f, 0xf0, + 0x00, 0x45, 0x91, 0xea, 0x03, 0x0f, 0x44, 0xbf, 0x6b, 0x40, 0xff, 0xf7, + 0x43, 0xbe, 0x00, 0xbf, 0x84, 0x1a, 0x71, 0xeb, 0x03, 0x06, 0x04, 0xd2, + 0x6e, 0x40, 0x00, 0x1b, 0xb1, 0x41, 0x12, 0x19, 0x73, 0x41, 0x4f, 0xf4, + 0x00, 0x1c, 0x1c, 0xeb, 0x41, 0x0f, 0x34, 0xbf, 0x7c, 0xeb, 0x43, 0x06, + 0x84, 0xe0, 0x0c, 0x0d, 0xa4, 0xeb, 0x13, 0x56, 0x36, 0x2e, 0x7d, 0xdc, + 0x01, 0x2e, 0x43, 0xdc, 0x45, 0xea, 0xc3, 0x23, 0x43, 0xea, 0x52, 0x53, + 0x12, 0xbf, 0xd2, 0x02, 0x92, 0x02, 0x5b, 0x08, 0x24, 0x05, 0x45, 0xea, + 0xc1, 0x21, 0x41, 0xea, 0x50, 0x51, 0xd2, 0xeb, 0xc0, 0x20, 0x99, 0x41, + 0x25, 0xd4, 0x07, 0xd1, 0xb0, 0xfa, 0x80, 0xf6, 0x10, 0xfa, 0x06, 0xf1, + 0x64, 0xd0, 0x00, 0x20, 0x20, 0x36, 0x08, 0xe0, 0xb1, 0xfa, 0x81, 0xf6, + 0xb1, 0x40, 0xc6, 0xf1, 0x20, 0x02, 0x20, 0xfa, 0x02, 0xf2, 0x11, 0x43, + 0xb0, 0x40, 0x4f, 0xea, 0xf4, 0x74, 0xb4, 0xeb, 0x46, 0x54, 0x34, 0xf0, + 0x01, 0x06, 0x4f, 0xea, 0x74, 0x04, 0x0a, 0xd8, 0xd6, 0xf5, 0x00, 0x16, + 0x76, 0x0d, 0x04, 0xf0, 0x00, 0x44, 0xf0, 0x40, 0x61, 0xfa, 0x06, 0xf2, + 0x50, 0x40, 0xf1, 0x40, 0x48, 0x40, 0xc0, 0x0a, 0x40, 0xea, 0x41, 0x50, + 0x21, 0xf0, 0x00, 0x41, 0x28, 0xbf, 0x5f, 0xea, 0x50, 0x05, 0x50, 0xf1, + 0x00, 0x00, 0x44, 0xeb, 0xd1, 0x21, 0x37, 0xe0, 0x45, 0xea, 0xc3, 0x23, + 0xdb, 0x0a, 0x45, 0xea, 0xc1, 0x21, 0xc9, 0x0a, 0xb6, 0xf1, 0x20, 0x05, + 0x0e, 0xdd, 0x42, 0xea, 0x02, 0x42, 0x12, 0x0c, 0xc5, 0xf1, 0x20, 0x06, + 0x03, 0xfa, 0x06, 0xf6, 0xeb, 0x40, 0x42, 0xea, 0x06, 0x05, 0x6d, 0x42, + 0x98, 0x41, 0x61, 0xf1, 0x00, 0x01, 0x0d, 0xe0, 0x62, 0xfa, 0x06, 0xf5, + 0xf2, 0x40, 0x55, 0x40, 0x63, 0xfa, 0x06, 0xfc, 0x82, 0xea, 0x0c, 0x02, + 0xf3, 0x40, 0x5a, 0x40, 0x6d, 0x42, 0x90, 0x41, 0x61, 0xeb, 0x03, 0x01, + 0x11, 0xf4, 0x80, 0x1f, 0x05, 0xd1, 0x64, 0x1e, 0x62, 0x05, 0x02, 0xd0, + 0x6d, 0x00, 0x40, 0x41, 0x49, 0x41, 0x21, 0xf4, 0x80, 0x11, 0x43, 0x08, + 0x75, 0xf1, 0x00, 0x43, 0x50, 0xf1, 0x00, 0x00, 0x41, 0xeb, 0x04, 0x51, + 0xf0, 0xbc, 0x70, 0x47, 0x1c, 0xeb, 0x41, 0x0f, 0x15, 0xd2, 0x23, 0xf0, + 0x00, 0x43, 0x52, 0xea, 0x43, 0x06, 0x0b, 0xd0, 0x4f, 0xea, 0x4c, 0x0c, + 0xbc, 0xeb, 0x41, 0x0f, 0x04, 0xd8, 0x0c, 0x0d, 0x66, 0x1e, 0x34, 0x2e, + 0xb7, 0xdd, 0xeb, 0xe7, 0x80, 0x1a, 0x99, 0x41, 0x50, 0xea, 0x41, 0x06, + 0x08, 0xbf, 0x00, 0x21, 0xe4, 0xe7, 0x08, 0xbf, 0x1c, 0xeb, 0x43, 0x0f, + 0x28, 0xbf, 0x6f, 0xf0, 0x00, 0x01, 0xdd, 0xe7, 0x4f, 0xea, 0xf1, 0x7c, + 0xbc, 0xf1, 0xe0, 0x4c, 0x2c, 0xbf, 0xbc, 0xf5, 0x00, 0x1f, 0x11, 0xe0, + 0x5f, 0xea, 0x4c, 0x0c, 0x34, 0xbf, 0xbc, 0xf1, 0x7f, 0x5f, 0x2e, 0xe0, + 0x5f, 0xea, 0x9c, 0x0c, 0x4f, 0xea, 0x0c, 0x1c, 0x4f, 0xea, 0x3c, 0x0c, + 0xc1, 0x00, 0x71, 0xf1, 0x00, 0x41, 0x4c, 0xeb, 0x50, 0x70, 0x70, 0x47, + 0xc9, 0x02, 0x41, 0xea, 0x50, 0x51, 0xc0, 0x02, 0x18, 0xbf, 0x41, 0xf0, + 0x01, 0x01, 0x41, 0xf0, 0x00, 0x41, 0x4f, 0xea, 0x6c, 0x50, 0xc0, 0xf1, + 0x09, 0x00, 0x21, 0x28, 0x10, 0xd2, 0x40, 0xea, 0xcc, 0x7c, 0xcc, 0xf1, + 0x20, 0x0c, 0x11, 0xfa, 0x0c, 0xf0, 0x70, 0xf1, 0x00, 0x40, 0xcc, 0xf1, + 0x20, 0x0c, 0x21, 0xfa, 0x0c, 0xf0, 0x0c, 0xf0, 0x00, 0x4c, 0x40, 0xeb, + 0x0c, 0x00, 0x70, 0x47, 0x4f, 0xea, 0xcc, 0x70, 0x70, 0x47, 0x49, 0x00, + 0x11, 0xf5, 0x00, 0x1f, 0x04, 0xd8, 0x4f, 0xea, 0xcc, 0x10, 0xff, 0x30, + 0xc0, 0x05, 0x70, 0x47, 0xc8, 0x17, 0x70, 0x47, 0x2d, 0xe9, 0xf0, 0x41, + 0x40, 0xf2, 0xff, 0x75, 0x81, 0xea, 0x03, 0x0c, 0x0c, 0xf0, 0x00, 0x4c, + 0x15, 0xea, 0x11, 0x54, 0x1d, 0xbf, 0x15, 0xea, 0x13, 0x57, 0xac, 0x42, + 0xaf, 0x42, 0xe9, 0xe0, 0xbc, 0x41, 0xc1, 0xf3, 0x13, 0x01, 0xc3, 0xf3, + 0x13, 0x03, 0x80, 0x1a, 0x99, 0x41, 0x43, 0xf4, 0x80, 0x13, 0x04, 0xd2, + 0x64, 0x1e, 0x40, 0x00, 0x49, 0x41, 0x80, 0x18, 0x59, 0x41, 0xc9, 0x02, + 0x41, 0xea, 0x50, 0x51, 0xb1, 0xfb, 0xf3, 0xf6, 0x03, 0xfb, 0x16, 0x11, + 0xa2, 0xfb, 0x06, 0x75, 0xd7, 0xeb, 0xc0, 0x20, 0xa9, 0x41, 0x02, 0xd2, + 0x76, 0x1e, 0x80, 0x18, 0x59, 0x41, 0xc9, 0x02, 0x41, 0xea, 0x50, 0x51, + 0xb1, 0xfb, 0xf3, 0xfe, 0x03, 0xfb, 0x1e, 0x11, 0xa2, 0xfb, 0x0e, 0x75, + 0xd7, 0xeb, 0xc0, 0x20, 0xa9, 0x41, 0x03, 0xd2, 0xae, 0xf1, 0x01, 0x0e, + 0x80, 0x18, 0x59, 0x41, 0x89, 0x02, 0x41, 0xea, 0x90, 0x51, 0x76, 0x05, + 0x46, 0xea, 0x8e, 0x2e, 0xb1, 0xfb, 0xf3, 0xf6, 0x03, 0xfb, 0x16, 0x11, + 0xa2, 0xfb, 0x06, 0x75, 0xd7, 0xeb, 0x80, 0x20, 0xa9, 0x41, 0x02, 0xd2, + 0x76, 0x1e, 0x80, 0x18, 0x59, 0x41, 0xc9, 0x02, 0x41, 0xea, 0x50, 0x51, + 0x4e, 0xea, 0x06, 0x0e, 0xb1, 0xfb, 0xf3, 0xf6, 0x03, 0xfb, 0x16, 0x11, + 0xa2, 0xfb, 0x06, 0x75, 0xd7, 0xeb, 0xc0, 0x20, 0xa9, 0x41, 0x02, 0xd2, + 0x76, 0x1e, 0x80, 0x18, 0x59, 0x41, 0xc9, 0x02, 0x41, 0xea, 0x50, 0x51, + 0xb1, 0xfb, 0xf3, 0xf7, 0x03, 0xfb, 0x17, 0x11, 0xa2, 0xfb, 0x07, 0x35, + 0xd3, 0xeb, 0xc0, 0x20, 0xa9, 0x41, 0x67, 0xf1, 0x00, 0x07, 0x0c, 0xbf, + 0x00, 0x42, 0x47, 0xf0, 0x01, 0x07, 0x66, 0xf3, 0xd5, 0x27, 0x4f, 0xea, + 0x1e, 0x31, 0xb8, 0x08, 0x14, 0xf5, 0x80, 0x64, 0x14, 0xdd, 0xbd, 0x07, + 0x75, 0xf1, 0x00, 0x42, 0x50, 0xeb, 0x0e, 0x50, 0x51, 0xeb, 0x04, 0x51, + 0x11, 0xf5, 0x80, 0x1f, 0x5c, 0xbf, 0x41, 0xea, 0x0c, 0x01, 0xbd, 0xe8, + 0xf0, 0x81, 0x4c, 0xf0, 0x7f, 0x61, 0x41, 0xf0, 0xe0, 0x41, 0x00, 0x20, + 0xbd, 0xe8, 0xf0, 0x81, 0xbd, 0x07, 0x6d, 0x08, 0x40, 0xea, 0x0e, 0x50, + 0x41, 0xf4, 0x80, 0x11, 0xd4, 0xf1, 0x01, 0x04, 0xb4, 0xf1, 0x20, 0x06, + 0x0a, 0xda, 0xc4, 0xf1, 0x20, 0x06, 0x02, 0x00, 0xe0, 0x40, 0x01, 0xfa, + 0x06, 0xf3, 0xe1, 0x40, 0x18, 0x43, 0xb2, 0x40, 0x15, 0x43, 0x0e, 0xe0, + 0x34, 0x2c, 0x14, 0xdc, 0xc6, 0xf1, 0x20, 0x04, 0x45, 0xea, 0x40, 0x05, + 0x6d, 0x08, 0x20, 0xfa, 0x06, 0xf2, 0x15, 0x43, 0x21, 0xfa, 0x06, 0xf0, + 0xa1, 0x40, 0x0d, 0x43, 0x00, 0x21, 0x75, 0xf1, 0x00, 0x42, 0x50, 0xf1, + 0x00, 0x00, 0x51, 0xeb, 0x0c, 0x01, 0xbd, 0xe8, 0xf0, 0x81, 0x00, 0x20, + 0x5f, 0xea, 0x0c, 0x01, 0xbd, 0xe8, 0xf0, 0x81, 0xcf, 0xb9, 0x92, 0x18, + 0x5b, 0x41, 0xb3, 0xfa, 0x83, 0xf7, 0x04, 0xbf, 0xb2, 0xfa, 0x82, 0xf6, + 0xbf, 0x19, 0x0b, 0x3f, 0xb7, 0xf1, 0x20, 0x06, 0x2f, 0xbf, 0x02, 0xfa, + 0x06, 0xf3, 0xbb, 0x40, 0xc7, 0xf1, 0x20, 0x06, 0x22, 0xfa, 0x06, 0xf6, + 0x38, 0xbf, 0x33, 0x43, 0xba, 0x40, 0x1c, 0xb1, 0xe4, 0x19, 0x64, 0x1e, + 0x2f, 0xe7, 0x7f, 0x42, 0x31, 0xf0, 0x00, 0x41, 0xb1, 0xfa, 0x81, 0xf4, + 0x04, 0xbf, 0xb0, 0xfa, 0x80, 0xf6, 0xa4, 0x19, 0x0b, 0x3c, 0xb4, 0xf1, + 0x20, 0x06, 0x2f, 0xbf, 0x00, 0xfa, 0x06, 0xf1, 0xa1, 0x40, 0xc4, 0xf1, + 0x20, 0x06, 0x20, 0xfa, 0x06, 0xf6, 0x38, 0xbf, 0x31, 0x43, 0xa0, 0x40, + 0x3c, 0x1b, 0x16, 0xe7, 0xac, 0x42, 0x1a, 0xbf, 0x05, 0xea, 0x13, 0x57, + 0xaf, 0x42, 0x14, 0xe0, 0x50, 0xea, 0x41, 0x06, 0x1c, 0xbf, 0x52, 0xea, + 0x43, 0x06, 0xbf, 0xe7, 0x50, 0xea, 0x41, 0x07, 0x30, 0x46, 0x61, 0x46, + 0x1c, 0xbf, 0x41, 0xea, 0x05, 0x51, 0xbd, 0xe8, 0xf0, 0x81, 0x52, 0xea, + 0x43, 0x0c, 0x08, 0xbf, 0xc1, 0x43, 0xbd, 0xe8, 0xf0, 0x81, 0x00, 0x20, + 0x4f, 0xf4, 0x00, 0x16, 0x16, 0xeb, 0x41, 0x0f, 0x98, 0xbf, 0x16, 0xeb, + 0x43, 0x0f, 0x08, 0xbf, 0x16, 0xeb, 0x41, 0x0f, 0x24, 0xbf, 0xc1, 0x43, + 0x05, 0xe0, 0x16, 0xeb, 0x43, 0x0f, 0x0c, 0xbf, 0x61, 0x46, 0x4c, 0xea, + 0x05, 0x51, 0xbd, 0xe8, 0xf0, 0x81, 0x00, 0x00, 0x41, 0x00, 0x1d, 0xd2, + 0x09, 0x0e, 0x7f, 0x39, 0x1a, 0xd4, 0x20, 0x29, 0x08, 0xda, 0xc1, 0xf1, + 0x1f, 0x0c, 0x01, 0x02, 0x41, 0xf0, 0x00, 0x41, 0x21, 0xfa, 0x0c, 0xf0, + 0x00, 0x21, 0x70, 0x47, 0xd1, 0xf1, 0x3f, 0x0c, 0x08, 0xd4, 0x01, 0x02, + 0x41, 0xf0, 0x00, 0x41, 0x61, 0xfa, 0x0c, 0xf0, 0x21, 0xfa, 0x0c, 0xf1, + 0x48, 0x40, 0x70, 0x47, 0x6f, 0xf0, 0x00, 0x00, 0x01, 0x00, 0x70, 0x47, + 0x00, 0x20, 0x00, 0x21, 0x70, 0x47, 0x00, 0x00, 0x80, 0xb5, 0x01, 0x20, + 0xf8, 0xf7, 0xb5, 0xf8, 0x01, 0x20, 0xf8, 0xf7, 0xb2, 0xf8, 0x4f, 0xf0, + 0xa0, 0x40, 0x03, 0x21, 0x01, 0x64, 0x01, 0x60, 0x09, 0x20, 0x06, 0x21, + 0xf8, 0xf7, 0x09, 0xf9, 0x09, 0x20, 0xf8, 0xf7, 0x00, 0xf9, 0x09, 0x20, + 0xf8, 0xf7, 0xee, 0xf8, 0x4f, 0xf0, 0xb0, 0x40, 0x4f, 0xf0, 0x00, 0x71, + 0x01, 0x64, 0x01, 0x60, 0x1c, 0x20, 0x06, 0x21, 0xf8, 0xf7, 0xf9, 0xf8, + 0x1c, 0x20, 0xf8, 0xf7, 0xf0, 0xf8, 0xff, 0xe7, 0xbd, 0xe8, 0x02, 0x40, + 0x1c, 0x20, 0xf8, 0xf7, 0xdb, 0xb8, 0x05, 0x28, 0xba, 0xbf, 0x27, 0x49, + 0x40, 0x5c, 0x00, 0x20, 0x70, 0x47, 0x38, 0xb5, 0x25, 0x49, 0x24, 0x4d, + 0x03, 0x20, 0x08, 0x60, 0x00, 0x20, 0xf3, 0xf7, 0xdf, 0xf9, 0x29, 0x78, + 0x04, 0x46, 0x8c, 0x42, 0x0a, 0xd0, 0x22, 0x46, 0x00, 0x20, 0xfe, 0xf7, + 0x8c, 0xfd, 0x00, 0x20, 0x00, 0xf0, 0x77, 0xf9, 0x18, 0x20, 0xf8, 0xf7, + 0x38, 0xf9, 0x2c, 0x70, 0x01, 0x20, 0xf3, 0xf7, 0xcd, 0xf9, 0x69, 0x78, + 0x04, 0x46, 0x8c, 0x42, 0x0a, 0xd0, 0x22, 0x46, 0x01, 0x20, 0xfe, 0xf7, + 0x7a, 0xfd, 0x01, 0x20, 0x00, 0xf0, 0x65, 0xf9, 0x19, 0x20, 0xf8, 0xf7, + 0x26, 0xf9, 0x6c, 0x70, 0x31, 0xbd, 0xf8, 0xb5, 0x11, 0x49, 0x0f, 0x4d, + 0x0f, 0xf2, 0x44, 0x06, 0x4f, 0xf0, 0x00, 0x70, 0x08, 0x60, 0x02, 0x24, + 0x36, 0xf8, 0x14, 0x00, 0x00, 0xf1, 0x8c, 0x40, 0x07, 0x78, 0x61, 0x5d, + 0x8f, 0x42, 0x0a, 0xd0, 0x3a, 0x46, 0xe0, 0xb2, 0xfe, 0xf7, 0xc3, 0xfd, + 0xe0, 0xb2, 0x00, 0xf0, 0x48, 0xf9, 0x1a, 0x20, 0xf8, 0xf7, 0x09, 0xf9, + 0x67, 0x55, 0x64, 0x1c, 0x05, 0x2c, 0xe9, 0xd3, 0xf1, 0xbd, 0x00, 0x00, + 0x50, 0xf3, 0x00, 0x20, 0x40, 0x00, 0x00, 0x50, 0x40, 0x00, 0x00, 0x58, + 0xb0, 0x04, 0xb3, 0x04, 0x5b, 0x04, 0x5c, 0x04, 0x5d, 0x04, 0x00, 0x00, + 0x38, 0xb5, 0x04, 0x46, 0x0d, 0x46, 0x20, 0x68, 0x40, 0x00, 0x00, 0x0e, + 0xff, 0x28, 0x04, 0xd1, 0x20, 0x68, 0x40, 0x02, 0x14, 0xd0, 0x02, 0x20, + 0x32, 0xbd, 0x20, 0xb9, 0x20, 0x46, 0xfe, 0xf7, 0xf7, 0xff, 0x01, 0x28, + 0x46, 0xda, 0x01, 0x2d, 0x0c, 0xdb, 0xc0, 0xf1, 0xff, 0x01, 0x8d, 0x42, + 0x08, 0xd3, 0x20, 0x68, 0x00, 0x28, 0x4c, 0xbf, 0x1f, 0x48, 0x4f, 0xf0, + 0xff, 0x40, 0x20, 0x60, 0x01, 0x20, 0x32, 0xbd, 0x41, 0x42, 0xa9, 0x42, + 0x21, 0x68, 0x06, 0xda, 0x21, 0xf0, 0xff, 0x41, 0x40, 0x19, 0x41, 0xea, + 0xc0, 0x50, 0x20, 0x60, 0x26, 0xe0, 0x22, 0x68, 0x52, 0x02, 0x40, 0x1e, + 0x52, 0x0a, 0x45, 0x19, 0x42, 0xf4, 0x00, 0x02, 0x05, 0xf1, 0x18, 0x00, + 0x01, 0xf0, 0x00, 0x41, 0x22, 0x60, 0x18, 0x28, 0x28, 0xbf, 0x21, 0x60, + 0x1c, 0xd2, 0x00, 0x20, 0x6a, 0x42, 0x06, 0xd0, 0x20, 0x68, 0xc2, 0xf1, + 0x20, 0x03, 0x98, 0x40, 0x23, 0x68, 0xd3, 0x40, 0x23, 0x60, 0x22, 0x68, + 0x0a, 0x43, 0xb0, 0xf1, 0x00, 0x4f, 0x22, 0x60, 0x03, 0xd8, 0x08, 0xd1, + 0x20, 0x78, 0xc0, 0x07, 0x05, 0xd5, 0x20, 0x68, 0x40, 0x1c, 0x20, 0x60, + 0x4f, 0xf0, 0xff, 0x30, 0x32, 0xbd, 0x20, 0x68, 0x88, 0x42, 0xf9, 0xd1, + 0x00, 0x20, 0x32, 0xbd, 0x00, 0x00, 0x80, 0xff, 0x01, 0x00, 0x00, 0xbf, + 0x09, 0xd0, 0xb0, 0xfa, 0x80, 0xf1, 0x88, 0x40, 0xc9, 0x1c, 0xc1, 0xf5, + 0x84, 0x61, 0x09, 0x05, 0x01, 0xeb, 0xd0, 0x21, 0x40, 0x05, 0x70, 0x47, + 0x70, 0xb5, 0x00, 0x24, 0x67, 0x4d, 0x0f, 0xf2, 0xbc, 0x16, 0x56, 0xf8, + 0x24, 0x10, 0x4f, 0xf4, 0x7c, 0x70, 0x00, 0xfb, 0x04, 0x50, 0x00, 0xf0, + 0xf2, 0xf8, 0x64, 0x1c, 0x04, 0x2c, 0xf4, 0xd3, 0x61, 0x4e, 0x62, 0x4d, + 0xf4, 0xf7, 0x0c, 0xfe, 0xf1, 0x6a, 0x04, 0x46, 0x00, 0xf0, 0x43, 0xf8, + 0xa5, 0xf8, 0x4a, 0x00, 0x20, 0x46, 0x31, 0x6c, 0x00, 0xf0, 0x3d, 0xf8, + 0xa5, 0xf8, 0x5a, 0x01, 0x70, 0xbd, 0x0f, 0xf2, 0x80, 0x11, 0x51, 0xf8, + 0x20, 0x00, 0x00, 0xf0, 0x6a, 0xb9, 0x00, 0xe0, 0x00, 0xbf, 0xf0, 0xb5, + 0x14, 0x46, 0x83, 0xb0, 0x20, 0x70, 0x61, 0x70, 0x05, 0x00, 0x0f, 0xf2, + 0x54, 0x11, 0x51, 0xf8, 0x25, 0x60, 0x4f, 0x49, 0x66, 0x60, 0x4f, 0xf4, + 0x7c, 0x72, 0x02, 0xfb, 0x05, 0x11, 0xa1, 0x60, 0x18, 0xbf, 0x01, 0x2d, + 0x4b, 0x49, 0x07, 0xbf, 0xcf, 0x6a, 0x01, 0x20, 0x0f, 0x6c, 0x03, 0x20, + 0xf4, 0xf7, 0x5a, 0xf9, 0x04, 0xf1, 0x10, 0x01, 0x01, 0x91, 0x06, 0xf1, + 0x48, 0x03, 0x04, 0xf1, 0x0c, 0x01, 0x00, 0x91, 0x3a, 0x46, 0x01, 0x46, + 0x30, 0x46, 0x00, 0xf0, 0x27, 0xf8, 0x0f, 0xf2, 0x20, 0x10, 0x50, 0xf8, + 0x25, 0x10, 0x20, 0x46, 0x03, 0xb0, 0xbd, 0xe8, 0xf0, 0x40, 0x00, 0xf0, + 0x4a, 0xb9, 0x38, 0xb5, 0x0d, 0x46, 0x04, 0x46, 0xb5, 0xf1, 0x00, 0x5f, + 0x80, 0x41, 0xc0, 0x0f, 0xf7, 0xf7, 0x63, 0xff, 0xb4, 0xeb, 0x45, 0x0f, + 0x01, 0xd3, 0x00, 0x20, 0x32, 0xbd, 0x28, 0x09, 0x60, 0x21, 0x48, 0x43, + 0x21, 0x09, 0xb0, 0xfb, 0xf1, 0xf0, 0x30, 0x28, 0x01, 0xd2, 0x01, 0x20, + 0x32, 0xbd, 0x2f, 0x38, 0xff, 0x28, 0x88, 0xbf, 0xff, 0x20, 0x32, 0xbd, + 0x2d, 0xe9, 0xf8, 0x43, 0x80, 0x46, 0x08, 0xf1, 0x48, 0x06, 0x0c, 0x46, + 0x70, 0x88, 0x91, 0x46, 0x1d, 0x46, 0xf5, 0xf7, 0x9f, 0xf8, 0x07, 0x46, + 0x15, 0x2c, 0x2c, 0xbf, 0x14, 0x3c, 0x00, 0x24, 0x48, 0x46, 0xf6, 0xf7, + 0x43, 0xfd, 0x81, 0x46, 0x20, 0x46, 0xf6, 0xf7, 0x3f, 0xfd, 0x49, 0x46, + 0xf6, 0xf7, 0xda, 0xfe, 0x04, 0x46, 0x07, 0xf1, 0x30, 0x00, 0x21, 0x49, + 0x48, 0x43, 0xf6, 0xf7, 0x35, 0xfd, 0x01, 0x46, 0x20, 0x46, 0xf6, 0xf7, + 0x41, 0xfd, 0xfd, 0xf7, 0xcd, 0xfd, 0x08, 0x9f, 0x09, 0x9c, 0xd0, 0xb1, + 0xf7, 0xf7, 0x5f, 0xff, 0x0c, 0x28, 0x28, 0xbf, 0x0c, 0x20, 0x31, 0x88, + 0x4f, 0xf2, 0xff, 0x02, 0x11, 0x40, 0x41, 0xea, 0x00, 0x21, 0x29, 0x80, + 0xc0, 0xf1, 0x0c, 0x00, 0x01, 0x21, 0x01, 0xfa, 0x00, 0xf0, 0x08, 0xf5, + 0x84, 0x71, 0x0a, 0x88, 0x02, 0xb9, 0x02, 0x46, 0x3a, 0x60, 0x49, 0x88, + 0x41, 0xb1, 0x21, 0x60, 0x07, 0xe0, 0x30, 0x88, 0x4f, 0xf2, 0xff, 0x01, + 0x08, 0x40, 0x28, 0x80, 0x00, 0x20, 0x38, 0x60, 0x20, 0x60, 0xbd, 0xe8, + 0xf1, 0x83, 0x04, 0x28, 0x06, 0xda, 0x04, 0x49, 0x4f, 0xf4, 0x7c, 0x72, + 0x02, 0xfb, 0x00, 0x10, 0x00, 0xf0, 0xe3, 0xbc, 0x70, 0x47, 0x00, 0x00, + 0xc0, 0x92, 0x00, 0x20, 0x78, 0x29, 0x00, 0x20, 0x98, 0x02, 0x00, 0x20, + 0x40, 0x42, 0x0f, 0x00, 0x98, 0x02, 0x00, 0x20, 0x98, 0x02, 0x00, 0x20, + 0xa8, 0x03, 0x00, 0x20, 0xa8, 0x03, 0x00, 0x20, 0x04, 0xea, 0x00, 0x20, + 0xa0, 0xea, 0x00, 0x20, 0x3c, 0xeb, 0x00, 0x20, 0xd8, 0xeb, 0x00, 0x20, + 0xef, 0xf3, 0x11, 0x80, 0x60, 0x21, 0x81, 0xf3, 0x11, 0x88, 0x70, 0x47, + 0x01, 0x68, 0x11, 0xf1, 0x01, 0x0f, 0x1c, 0xbf, 0x49, 0x1c, 0x01, 0x60, + 0x70, 0x47, 0x01, 0x88, 0x4f, 0xf6, 0xff, 0x72, 0x91, 0x42, 0x1c, 0xbf, + 0x49, 0x1c, 0x01, 0x80, 0x70, 0x47, 0x38, 0xb5, 0x04, 0x46, 0x00, 0x20, + 0x20, 0x80, 0x60, 0x80, 0x60, 0x60, 0x0d, 0x46, 0xc0, 0x21, 0x04, 0xf1, + 0x08, 0x00, 0xf7, 0xf7, 0x11, 0xfd, 0x4f, 0xf0, 0x80, 0x40, 0xa0, 0x66, + 0x00, 0x21, 0x04, 0xf1, 0xd0, 0x00, 0x01, 0x70, 0x4f, 0xf0, 0x7e, 0x51, + 0x41, 0x60, 0x00, 0x21, 0x81, 0x60, 0x01, 0x73, 0x04, 0xf1, 0xe0, 0x00, + 0x01, 0xf0, 0xea, 0xfe, 0x28, 0x46, 0xbd, 0xe8, 0x32, 0x40, 0x58, 0xe0, + 0x38, 0xb5, 0x00, 0x25, 0x05, 0x80, 0x00, 0xf1, 0xe0, 0x04, 0x45, 0x80, + 0xd0, 0x30, 0x65, 0x68, 0x45, 0x60, 0x25, 0x68, 0x85, 0x60, 0x01, 0x25, + 0x05, 0x73, 0x00, 0x25, 0x45, 0x73, 0x05, 0x70, 0x20, 0x46, 0x01, 0xb0, + 0xbd, 0xe8, 0x30, 0x40, 0x01, 0xf0, 0x53, 0xbe, 0x70, 0xb5, 0x0c, 0x46, + 0xc0, 0x21, 0x06, 0x46, 0x00, 0x20, 0x30, 0x80, 0x70, 0x80, 0x70, 0x60, + 0x06, 0xf1, 0xe0, 0x05, 0x06, 0xf1, 0x08, 0x00, 0xf7, 0xf7, 0xd8, 0xfc, + 0x4f, 0xf0, 0x80, 0x40, 0xb0, 0x66, 0x06, 0xf1, 0xd0, 0x01, 0x05, 0xf5, + 0x0a, 0x70, 0x42, 0x68, 0x4a, 0x60, 0x00, 0x68, 0x88, 0x60, 0x01, 0x20, + 0x08, 0x73, 0x00, 0x20, 0x48, 0x73, 0x95, 0xf8, 0xf4, 0x02, 0x08, 0x70, + 0x21, 0x46, 0x28, 0x46, 0xbd, 0xe8, 0x70, 0x40, 0x01, 0xf0, 0xf6, 0xbe, + 0x00, 0x21, 0x01, 0x60, 0x41, 0x60, 0x81, 0x60, 0xc1, 0x60, 0x4f, 0xf0, + 0xff, 0x31, 0x01, 0x61, 0x00, 0x21, 0x41, 0x61, 0x70, 0x47, 0x42, 0x68, + 0x11, 0x43, 0x41, 0x60, 0x08, 0x30, 0x83, 0xe7, 0x02, 0x69, 0x8a, 0x42, + 0x88, 0xbf, 0x0a, 0x46, 0x02, 0x61, 0x42, 0x69, 0x91, 0x42, 0x38, 0xbf, + 0x11, 0x46, 0x41, 0x61, 0x70, 0x47, 0x0c, 0x30, 0x76, 0xe7, 0x10, 0xb5, + 0x04, 0x46, 0x00, 0x20, 0x20, 0x60, 0x28, 0x21, 0x64, 0x20, 0x60, 0x60, + 0x4f, 0xf0, 0xff, 0x30, 0xa0, 0x60, 0x00, 0x20, 0xe0, 0x60, 0x20, 0x61, + 0x04, 0xf1, 0x74, 0x00, 0xf7, 0xf7, 0x92, 0xfc, 0x04, 0xf1, 0x5c, 0x00, + 0xff, 0xf7, 0xce, 0xff, 0x20, 0x46, 0xbd, 0xe8, 0x10, 0x40, 0x10, 0xb5, + 0x04, 0x46, 0x04, 0xf1, 0x44, 0x00, 0xff, 0xf7, 0xc5, 0xff, 0x20, 0x46, + 0xbd, 0xe8, 0x10, 0x40, 0x10, 0xb5, 0x04, 0x46, 0x04, 0xf1, 0x2c, 0x00, + 0xff, 0xf7, 0xbc, 0xff, 0x20, 0x46, 0xbd, 0xe8, 0x10, 0x40, 0x14, 0x30, + 0xb6, 0xe7, 0x2d, 0xe9, 0xf0, 0x41, 0x04, 0x46, 0x0d, 0x46, 0xad, 0xf5, + 0x7c, 0x7d, 0x05, 0xf1, 0x74, 0x00, 0xc4, 0xf8, 0x60, 0x03, 0x00, 0x22, + 0x00, 0x21, 0x04, 0xf1, 0x30, 0x00, 0xf4, 0xf7, 0xea, 0xfe, 0xff, 0xf7, + 0x33, 0xff, 0x06, 0x46, 0x00, 0x20, 0x28, 0x60, 0x68, 0x60, 0x28, 0x46, + 0xff, 0xf7, 0xdc, 0xff, 0x86, 0xf3, 0x11, 0x88, 0x4f, 0xf4, 0x7c, 0x78, + 0xa1, 0x68, 0x42, 0x46, 0x68, 0x46, 0xf9, 0xf7, 0x1f, 0xfd, 0x00, 0x27, + 0x28, 0x46, 0xff, 0xf7, 0xd8, 0xff, 0x69, 0x46, 0x20, 0x46, 0x00, 0xf0, + 0x98, 0xf8, 0xff, 0xf7, 0x19, 0xff, 0x06, 0x46, 0xa0, 0x68, 0x42, 0x46, + 0x69, 0x46, 0xf9, 0xf7, 0x0f, 0xfd, 0xe8, 0x68, 0x40, 0x1c, 0xe8, 0x60, + 0x60, 0x7f, 0x10, 0xb1, 0x28, 0x69, 0x40, 0x1c, 0x28, 0x61, 0xa0, 0x68, + 0x61, 0x68, 0x40, 0x88, 0x89, 0x8a, 0x90, 0xfb, 0xf1, 0xf0, 0x64, 0x28, + 0x28, 0xbf, 0x63, 0x20, 0x68, 0x60, 0x61, 0x69, 0x09, 0xb3, 0x05, 0xf1, + 0x5c, 0x00, 0xff, 0xf7, 0x78, 0xff, 0x61, 0x69, 0x05, 0xf1, 0x44, 0x00, + 0xff, 0xf7, 0x73, 0xff, 0x61, 0x69, 0x05, 0xf1, 0x2c, 0x00, 0xff, 0xf7, + 0x6e, 0xff, 0x61, 0x69, 0x05, 0xf1, 0x14, 0x00, 0xff, 0xf7, 0x69, 0xff, + 0x60, 0x69, 0xc1, 0x06, 0x01, 0xd5, 0x03, 0x20, 0x07, 0xe0, 0x81, 0x07, + 0x02, 0xd5, 0x01, 0x20, 0x28, 0x60, 0x3c, 0xe0, 0xc0, 0x07, 0x3b, 0xd5, + 0x02, 0x20, 0x28, 0x60, 0x37, 0xe0, 0x20, 0x69, 0xa8, 0xb3, 0xa0, 0x7f, + 0x00, 0x28, 0x1c, 0xbf, 0xe0, 0x7f, 0x00, 0x28, 0x30, 0xd0, 0x20, 0x6a, + 0xa8, 0x60, 0x05, 0xf1, 0x14, 0x00, 0x21, 0x6a, 0xff, 0xf7, 0x50, 0xff, + 0x21, 0x6a, 0x05, 0xf1, 0x2c, 0x00, 0xff, 0xf7, 0x4b, 0xff, 0x21, 0x6a, + 0x05, 0xf1, 0x44, 0x00, 0xff, 0xf7, 0x46, 0xff, 0x21, 0x6a, 0x05, 0xf1, + 0x5c, 0x00, 0xff, 0xf7, 0x41, 0xff, 0x20, 0x78, 0xa9, 0x68, 0x32, 0x30, + 0xc0, 0xb2, 0xf7, 0xf7, 0x79, 0xfe, 0xe0, 0x7f, 0x02, 0x28, 0x10, 0xd1, + 0x05, 0xf1, 0x14, 0x00, 0xff, 0xf7, 0x3f, 0xff, 0x05, 0xf1, 0x2c, 0x00, + 0xff, 0xf7, 0x3b, 0xff, 0x05, 0xf1, 0x44, 0x00, 0xff, 0xf7, 0x37, 0xff, + 0x05, 0xf1, 0x5c, 0x00, 0xff, 0xf7, 0x33, 0xff, 0x00, 0xe0, 0x01, 0x27, + 0x05, 0xf1, 0x14, 0x00, 0xff, 0xf7, 0xa6, 0xfe, 0x05, 0xf1, 0x2c, 0x00, + 0xff, 0xf7, 0xa2, 0xfe, 0x05, 0xf1, 0x44, 0x00, 0xff, 0xf7, 0x9e, 0xfe, + 0x05, 0xf1, 0x5c, 0x00, 0xff, 0xf7, 0x9a, 0xfe, 0x60, 0x78, 0x08, 0xb9, + 0x01, 0x27, 0x00, 0xe0, 0x0f, 0xb1, 0x64, 0x20, 0x68, 0x60, 0x86, 0xf3, + 0x11, 0x88, 0x00, 0x2f, 0x3f, 0xf4, 0x66, 0xaf, 0x28, 0x68, 0x0d, 0xf5, + 0x7c, 0x7d, 0xbd, 0xe8, 0xf0, 0x81, 0xf8, 0xb5, 0x04, 0x46, 0x00, 0x20, + 0x60, 0x61, 0x20, 0x76, 0x60, 0x76, 0xa0, 0x76, 0xe0, 0x76, 0x20, 0x77, + 0x60, 0x77, 0x0d, 0x46, 0x04, 0xf1, 0x24, 0x00, 0x00, 0x21, 0x04, 0xf5, + 0x56, 0x76, 0x01, 0x70, 0x41, 0x60, 0x41, 0x70, 0xb1, 0x61, 0xf1, 0x61, + 0x20, 0x69, 0x88, 0xb1, 0x31, 0x68, 0x00, 0x29, 0x1c, 0xbf, 0x71, 0x79, + 0x01, 0x29, 0x0b, 0xd1, 0x61, 0x68, 0x2a, 0x88, 0x4b, 0x8a, 0x9a, 0x42, + 0x06, 0xd3, 0x6a, 0x88, 0x8b, 0x8a, 0x9a, 0x42, 0x89, 0x41, 0xc9, 0x43, + 0xc9, 0x0f, 0x00, 0xe0, 0x00, 0x21, 0xa1, 0x77, 0xa1, 0x7f, 0x01, 0xb9, + 0xe0, 0x68, 0x30, 0x84, 0x01, 0xf0, 0xfc, 0xfe, 0x30, 0x8c, 0x88, 0xb9, + 0x60, 0x69, 0x40, 0xf0, 0x10, 0x00, 0x60, 0x61, 0x0c, 0xe0, 0x20, 0x7e, + 0x03, 0x28, 0x56, 0xd0, 0x02, 0x28, 0x1c, 0xbf, 0x60, 0x7e, 0x01, 0x28, + 0x04, 0xd1, 0x60, 0x68, 0x80, 0x78, 0x08, 0xb1, 0xf2, 0xf7, 0x68, 0xfb, + 0x60, 0x69, 0x00, 0x28, 0x38, 0xd1, 0xdf, 0xf8, 0x74, 0x75, 0x20, 0x78, + 0x47, 0xf8, 0x20, 0x40, 0x00, 0x20, 0xf0, 0x61, 0x20, 0x76, 0x60, 0x76, + 0xa0, 0x76, 0x00, 0x21, 0xf3, 0xf7, 0x47, 0xf8, 0x20, 0x46, 0x00, 0xf0, + 0x4a, 0xf8, 0x20, 0x46, 0x00, 0xf0, 0xed, 0xf8, 0xf0, 0x69, 0x98, 0xb9, + 0x20, 0x46, 0x00, 0xf0, 0x8d, 0xf8, 0x20, 0x7e, 0x70, 0xb9, 0x20, 0x46, + 0x00, 0xf0, 0xaa, 0xf8, 0x28, 0xb3, 0x00, 0x20, 0x60, 0x76, 0x20, 0x46, + 0x00, 0xf0, 0x05, 0xf9, 0x30, 0x68, 0x31, 0x8c, 0x88, 0x42, 0xeb, 0xd3, + 0x01, 0x20, 0xa0, 0x76, 0x00, 0x20, 0x21, 0x78, 0x47, 0xf8, 0x21, 0x00, + 0x20, 0x46, 0x00, 0xf0, 0x5e, 0xf8, 0x00, 0x20, 0xf3, 0xf7, 0x7e, 0xf8, + 0xb0, 0x69, 0x00, 0x28, 0x04, 0xbf, 0xa0, 0x7e, 0x00, 0x28, 0xb6, 0xd0, + 0xa0, 0x7e, 0x70, 0xb1, 0x29, 0x46, 0x20, 0x46, 0x00, 0xf0, 0x05, 0xfa, + 0xe0, 0x7e, 0x28, 0xb9, 0x01, 0x20, 0x20, 0x77, 0x07, 0xe0, 0x01, 0x20, + 0x60, 0x76, 0xe1, 0xe7, 0x00, 0x20, 0x20, 0x77, 0xf1, 0xbd, 0x20, 0x7f, + 0x60, 0xb1, 0x29, 0x46, 0x20, 0x46, 0x00, 0xf0, 0x79, 0xfa, 0x08, 0xb1, + 0x01, 0x20, 0x04, 0xe0, 0x60, 0x69, 0x40, 0xf0, 0x04, 0x00, 0x60, 0x61, + 0x00, 0x20, 0x60, 0x77, 0xf1, 0xbd, 0x38, 0xb5, 0x04, 0x46, 0x60, 0x68, + 0x18, 0x30, 0xf4, 0xf7, 0xdd, 0xfc, 0x20, 0x78, 0x02, 0x28, 0x18, 0xbf, + 0x03, 0x28, 0x27, 0xd1, 0xf3, 0xf7, 0xdc, 0xfa, 0x03, 0x28, 0x23, 0xd1, + 0x20, 0x78, 0x02, 0x28, 0x02, 0xd1, 0xf3, 0xf7, 0x2c, 0xfb, 0x01, 0xe0, + 0xf3, 0xf7, 0x3d, 0xfb, 0x05, 0x46, 0x04, 0xf5, 0x59, 0x70, 0xf4, 0xf7, + 0xc4, 0xff, 0x20, 0x78, 0x03, 0x28, 0x0c, 0xbf, 0x01, 0x20, 0x00, 0x20, + 0xf4, 0xf7, 0xe5, 0xff, 0x05, 0x2d, 0x18, 0xbf, 0x06, 0x2d, 0x02, 0xd1, + 0xf5, 0xf7, 0x17, 0xf8, 0x01, 0xe0, 0xf5, 0xf7, 0x10, 0xf8, 0xf4, 0xf7, + 0xfb, 0xff, 0x28, 0x46, 0xbd, 0xe8, 0x32, 0x40, 0xfd, 0xf7, 0x68, 0xbf, + 0x31, 0xbd, 0x10, 0xb5, 0x04, 0x46, 0xf4, 0xf7, 0xf5, 0xfc, 0x20, 0x78, + 0x02, 0x28, 0x18, 0xbf, 0x03, 0x28, 0x0c, 0xd1, 0xf3, 0xf7, 0xaa, 0xfa, + 0x03, 0x28, 0x08, 0xd1, 0xfd, 0xf7, 0xb0, 0xff, 0x04, 0xf5, 0x59, 0x70, + 0xbd, 0xe8, 0x10, 0x40, 0x00, 0x21, 0xf4, 0xf7, 0xa8, 0xbf, 0x10, 0xbd, + 0x10, 0xb5, 0x00, 0xf0, 0x52, 0xf8, 0xfe, 0xf7, 0x00, 0xff, 0x60, 0x68, + 0x23, 0x78, 0xa1, 0x7f, 0x00, 0xf1, 0x18, 0x02, 0x0f, 0xf2, 0xb4, 0x40, + 0x18, 0x5c, 0xf4, 0xf7, 0xdc, 0xfc, 0x01, 0x28, 0x03, 0xd0, 0xa1, 0x68, + 0xd1, 0xf8, 0xec, 0x13, 0x09, 0xb1, 0x01, 0x20, 0x08, 0xe0, 0x02, 0x28, + 0x18, 0xbf, 0x00, 0x28, 0x04, 0xd0, 0x61, 0x69, 0x41, 0xf0, 0x01, 0x01, + 0x03, 0x20, 0x61, 0x61, 0x20, 0x76, 0x10, 0xbd, 0xd0, 0xb5, 0x00, 0xf0, + 0x30, 0xf8, 0xfe, 0xf7, 0xf2, 0xfe, 0x01, 0x28, 0x20, 0xd0, 0x00, 0x26, + 0x00, 0x27, 0x01, 0x22, 0xdf, 0xf8, 0xd4, 0x03, 0x00, 0xf0, 0x1e, 0xf8, + 0xdf, 0xf8, 0xd0, 0x03, 0x00, 0xf0, 0x1a, 0xf8, 0xdf, 0xf8, 0xcc, 0x03, + 0x50, 0xf8, 0x22, 0x00, 0xc1, 0x17, 0x49, 0x00, 0x41, 0xea, 0xd0, 0x71, + 0x16, 0xeb, 0x40, 0x06, 0x4f, 0x41, 0x52, 0x1c, 0x18, 0x2a, 0xe9, 0xd3, + 0x60, 0x68, 0xd0, 0xe9, 0x02, 0x23, 0x9f, 0x42, 0x04, 0xdc, 0x01, 0xdb, + 0x96, 0x42, 0x01, 0xd2, 0x00, 0x20, 0xd0, 0xbd, 0x01, 0x20, 0xd0, 0xbd, + 0x50, 0xf8, 0x22, 0x00, 0x16, 0xeb, 0x00, 0x16, 0x57, 0xeb, 0x10, 0x77, + 0x70, 0x47, 0x04, 0x46, 0x0f, 0xf2, 0x20, 0x40, 0x21, 0x78, 0x08, 0x5c, + 0x70, 0x47, 0x70, 0xb5, 0x04, 0x46, 0xa5, 0x7f, 0x05, 0xb1, 0x01, 0x25, + 0x21, 0x78, 0x0f, 0xf2, 0x10, 0x40, 0x08, 0x5c, 0xff, 0xf7, 0x7d, 0xfb, + 0x04, 0xf5, 0x54, 0x76, 0xb1, 0x68, 0x29, 0xb1, 0x31, 0x7b, 0x81, 0x42, + 0x04, 0xbf, 0x71, 0x7b, 0xa9, 0x42, 0x08, 0xd0, 0x01, 0x46, 0x2a, 0x46, + 0x04, 0xf1, 0x30, 0x00, 0xf4, 0xf7, 0xd5, 0xfc, 0x00, 0x20, 0xc6, 0xe9, + 0x00, 0x00, 0xa1, 0x68, 0x00, 0x20, 0xc1, 0xf8, 0xec, 0x03, 0x70, 0xbd, + 0x00, 0x22, 0x00, 0x21, 0x30, 0x30, 0xf4, 0xf7, 0xc8, 0xbc, 0x10, 0xb5, + 0x04, 0x46, 0x04, 0xf1, 0x30, 0x00, 0xf4, 0xf7, 0x0a, 0xfd, 0xd4, 0xe9, + 0x0c, 0x01, 0xc4, 0xe9, 0x3e, 0x01, 0x10, 0xbd, 0x2d, 0xe9, 0xf0, 0x4f, + 0x04, 0x46, 0xad, 0xf2, 0xfc, 0x5d, 0xe0, 0x68, 0x00, 0xf5, 0x4b, 0x71, + 0x91, 0xf8, 0x00, 0x80, 0x4f, 0x78, 0x01, 0x21, 0x21, 0x77, 0x04, 0xf1, + 0x24, 0x06, 0x00, 0x21, 0x61, 0x77, 0x71, 0x70, 0xa1, 0x68, 0x67, 0x90, + 0x5c, 0x31, 0x66, 0x91, 0x20, 0x68, 0xe0, 0x30, 0x68, 0x90, 0x60, 0x68, + 0x69, 0x90, 0x61, 0x69, 0x20, 0x69, 0x01, 0xf0, 0xf7, 0xfd, 0x6a, 0x90, + 0x20, 0x68, 0x90, 0xf8, 0xd0, 0x10, 0x88, 0x45, 0x03, 0xd1, 0xd0, 0xf8, + 0xf8, 0x12, 0x01, 0x29, 0x06, 0xd1, 0x68, 0x9a, 0x01, 0x21, 0xc2, 0xf8, + 0x10, 0x12, 0x00, 0x21, 0xc0, 0xf8, 0xf8, 0x12, 0x01, 0x2f, 0x1b, 0xd1, + 0x69, 0x46, 0x66, 0xa8, 0x01, 0xf0, 0x8e, 0xfc, 0x60, 0x77, 0x00, 0x20, + 0x27, 0x68, 0x78, 0x80, 0x65, 0x7f, 0x1d, 0xb9, 0x4f, 0xf0, 0xff, 0x30, + 0x20, 0x62, 0x09, 0xe0, 0x00, 0x98, 0xfd, 0xf7, 0x47, 0xfa, 0x02, 0x2d, + 0x20, 0x62, 0x03, 0xd1, 0x41, 0x46, 0x38, 0x46, 0xff, 0xf7, 0x0a, 0xfd, + 0x01, 0x20, 0x70, 0x70, 0x02, 0x20, 0xbd, 0xe0, 0x00, 0x20, 0x00, 0x90, + 0x68, 0x98, 0x00, 0xf5, 0x04, 0x70, 0x01, 0x68, 0x91, 0xb1, 0x69, 0x46, + 0x66, 0xa8, 0x00, 0xf0, 0xdc, 0xf9, 0x68, 0x99, 0x01, 0xf5, 0x04, 0x71, + 0x48, 0x60, 0x48, 0x68, 0x03, 0x28, 0x14, 0xd0, 0x48, 0x68, 0x01, 0x28, + 0x02, 0xd0, 0x00, 0x20, 0x08, 0x60, 0x0e, 0xe0, 0x00, 0x20, 0x0d, 0xe0, + 0x40, 0x68, 0x02, 0x28, 0x69, 0x46, 0x66, 0xa8, 0x02, 0xd1, 0x00, 0xf0, + 0xc6, 0xf9, 0x01, 0xe0, 0x00, 0xf0, 0x6e, 0xf9, 0x68, 0x99, 0xc1, 0xf8, + 0x14, 0x02, 0x01, 0x20, 0x70, 0x70, 0x00, 0x2f, 0x68, 0x98, 0xd0, 0xf8, + 0x14, 0x02, 0x69, 0x99, 0x48, 0x62, 0x40, 0xf0, 0x8e, 0x80, 0x00, 0x20, + 0x00, 0x90, 0x4f, 0xf0, 0x00, 0x09, 0x27, 0x68, 0x07, 0xf1, 0xe0, 0x05, + 0x05, 0xf1, 0xcc, 0x00, 0x29, 0x68, 0x40, 0x68, 0xf6, 0xf7, 0x62, 0xfa, + 0x33, 0x90, 0x33, 0xa8, 0x05, 0xeb, 0x89, 0x0b, 0x00, 0xeb, 0x89, 0x0a, + 0xdb, 0xf8, 0x04, 0x00, 0xd5, 0xf8, 0xcc, 0x10, 0xf6, 0xf7, 0xf2, 0xfa, + 0xca, 0xf8, 0x04, 0x00, 0x09, 0xf1, 0x01, 0x09, 0xdb, 0xf8, 0x68, 0x00, + 0xca, 0xf8, 0x68, 0x00, 0xb9, 0xf1, 0x19, 0x0f, 0xe9, 0xd3, 0x00, 0x25, + 0x33, 0xa8, 0x00, 0xeb, 0x85, 0x09, 0x74, 0x49, 0xd9, 0xf8, 0x04, 0x00, + 0xf6, 0xf7, 0x42, 0xfa, 0x82, 0x46, 0x33, 0x98, 0xd9, 0xf8, 0x68, 0x10, + 0xf6, 0xf7, 0x3c, 0xfa, 0x81, 0x46, 0x50, 0x46, 0x51, 0x46, 0xf6, 0xf7, + 0xd3, 0xfa, 0x82, 0x46, 0x48, 0x46, 0x49, 0x46, 0xf6, 0xf7, 0xce, 0xfa, + 0x51, 0x46, 0xf6, 0xf7, 0x2f, 0xfa, 0x4f, 0xf0, 0x7a, 0x51, 0xf6, 0xf7, + 0xc7, 0xfa, 0x01, 0x46, 0xa0, 0x68, 0xd0, 0xf8, 0x00, 0x01, 0xf6, 0xf7, + 0xaf, 0xfa, 0x08, 0xd2, 0x01, 0x20, 0x30, 0x70, 0x41, 0x46, 0x20, 0x68, + 0xff, 0xf7, 0x84, 0xfc, 0x01, 0x20, 0x70, 0x70, 0x38, 0xe0, 0x6d, 0x1c, + 0x19, 0x2d, 0xcd, 0xd3, 0x07, 0xf1, 0xd4, 0x00, 0x01, 0x7a, 0x49, 0xb9, + 0x34, 0x99, 0x01, 0x60, 0x33, 0x99, 0x41, 0x60, 0x01, 0x21, 0x01, 0x72, + 0x01, 0x20, 0x21, 0x68, 0x81, 0xf8, 0xdd, 0x00, 0x20, 0x68, 0x80, 0xf8, + 0xd0, 0x80, 0x20, 0x68, 0xff, 0xf7, 0x2b, 0xfc, 0x20, 0x68, 0x80, 0x1c, + 0xff, 0xf7, 0x27, 0xfc, 0xa0, 0x69, 0x98, 0xb9, 0x20, 0x68, 0xd4, 0x30, + 0x18, 0x26, 0x41, 0x68, 0x33, 0x91, 0x00, 0x68, 0x34, 0x99, 0xf6, 0xf7, + 0x03, 0xf9, 0x05, 0x46, 0x33, 0xa8, 0x00, 0xeb, 0x86, 0x07, 0x29, 0x46, + 0x78, 0x68, 0xf6, 0xf7, 0x89, 0xfa, 0x76, 0x1e, 0x78, 0x60, 0xf5, 0xd5, + 0x20, 0x68, 0x01, 0x1d, 0x6b, 0x46, 0x01, 0xaa, 0x33, 0xa8, 0x01, 0xf0, + 0x22, 0xfd, 0x00, 0x20, 0x20, 0x77, 0x0d, 0xf2, 0xfc, 0x5d, 0xbd, 0xe8, + 0xf0, 0x8f, 0x70, 0xb5, 0x82, 0xb0, 0x04, 0x46, 0x0e, 0x46, 0x6a, 0x46, + 0x00, 0x21, 0x00, 0x20, 0xf2, 0xf7, 0xb9, 0xff, 0x00, 0x98, 0x30, 0xb9, + 0x01, 0x20, 0xe0, 0x76, 0x60, 0x69, 0x40, 0xf0, 0x08, 0x00, 0x60, 0x61, + 0x73, 0xbd, 0x20, 0x78, 0x01, 0x46, 0x02, 0x29, 0x04, 0xf1, 0x24, 0x05, + 0x08, 0xd0, 0x03, 0x29, 0x09, 0xd1, 0xf3, 0xf7, 0x4e, 0xf9, 0x68, 0x70, + 0x68, 0x78, 0xfd, 0xf7, 0xb6, 0xff, 0x0b, 0xe0, 0xf3, 0xf7, 0x33, 0xf9, + 0xf7, 0xe7, 0x00, 0x28, 0x18, 0xbf, 0x01, 0x29, 0x08, 0xd1, 0x0f, 0xf2, + 0x3c, 0x10, 0x08, 0x5c, 0xfd, 0xf7, 0xa0, 0xff, 0x40, 0x1e, 0x80, 0x41, + 0xc0, 0x0f, 0x68, 0x60, 0x00, 0x98, 0x06, 0x60, 0x00, 0x99, 0xd4, 0xf8, + 0x60, 0x03, 0x48, 0x60, 0x00, 0x99, 0x60, 0x68, 0x88, 0x60, 0x04, 0xf1, + 0x30, 0x00, 0x00, 0x99, 0xc8, 0x60, 0x00, 0x99, 0x68, 0x68, 0x88, 0x61, + 0x21, 0x78, 0x1f, 0x48, 0x01, 0x29, 0x03, 0xd9, 0x89, 0x1e, 0x01, 0x29, + 0x05, 0xd9, 0x09, 0xe0, 0x00, 0x9a, 0x41, 0x6b, 0x11, 0x61, 0xc0, 0x6a, + 0x08, 0xe0, 0x00, 0x9a, 0x81, 0x6c, 0x11, 0x61, 0x00, 0x6c, 0x03, 0xe0, + 0x00, 0x9a, 0xc1, 0x6d, 0x11, 0x61, 0x40, 0x6d, 0x00, 0x99, 0x15, 0x4a, + 0x48, 0x61, 0x00, 0x21, 0x00, 0x20, 0xf2, 0xf7, 0xf0, 0xff, 0x00, 0x98, + 0x90, 0xf8, 0x25, 0x00, 0x10, 0xb1, 0x20, 0x46, 0xff, 0xf7, 0x7a, 0xfe, + 0x00, 0x98, 0x40, 0x7f, 0xe0, 0x77, 0x00, 0x98, 0x50, 0xf8, 0x20, 0x1f, + 0x21, 0x62, 0x00, 0x79, 0x28, 0x70, 0x00, 0x98, 0x00, 0x7f, 0xe0, 0x76, + 0x00, 0x20, 0xf2, 0xf7, 0x96, 0xff, 0x73, 0xbd, 0x00, 0x00, 0x00, 0x00, + 0x18, 0xf3, 0x00, 0x20, 0x80, 0x16, 0x00, 0x41, 0x00, 0x16, 0x00, 0x41, + 0x80, 0x17, 0x00, 0x41, 0x00, 0x00, 0x80, 0xbf, 0x78, 0x29, 0x00, 0x20, + 0x89, 0x06, 0x01, 0x01, 0x2d, 0xe9, 0xf8, 0x43, 0x0d, 0x46, 0x04, 0x46, + 0x0f, 0xf2, 0x78, 0x00, 0x21, 0x78, 0x0f, 0x5c, 0x38, 0x46, 0xf4, 0xf7, + 0x04, 0xfc, 0x80, 0x46, 0xf1, 0xf7, 0xc8, 0xf9, 0x21, 0x78, 0x0f, 0xf2, + 0x70, 0x00, 0x08, 0x5c, 0x40, 0xf0, 0x02, 0x09, 0x29, 0x1d, 0x40, 0x46, + 0xf4, 0xf7, 0x96, 0xfb, 0x00, 0x26, 0x28, 0xb1, 0x49, 0x46, 0x38, 0x46, + 0xf4, 0xf7, 0xfd, 0xfb, 0x00, 0xb1, 0x01, 0x26, 0x95, 0xf8, 0xdd, 0x00, + 0x00, 0x28, 0x04, 0xbf, 0xa0, 0x6a, 0x00, 0x28, 0x0e, 0xd0, 0x02, 0x2f, + 0x06, 0xd3, 0x94, 0xf8, 0x25, 0x00, 0x00, 0x22, 0x00, 0x21, 0xfd, 0xf7, + 0xf4, 0xfe, 0x02, 0xe0, 0x20, 0x78, 0xfd, 0xf7, 0xc2, 0xfe, 0x00, 0x20, + 0x85, 0xf8, 0xdd, 0x00, 0xf1, 0xf7, 0xb3, 0xf9, 0x30, 0x46, 0xbd, 0xe8, + 0xf2, 0x83, 0x00, 0x21, 0x01, 0x80, 0x01, 0x21, 0xc0, 0xf8, 0xec, 0x13, + 0x70, 0x47, 0x00, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, + 0x00, 0x01, 0x02, 0x03, 0x00, 0x00, 0x00, 0x04, 0xf8, 0xb5, 0x04, 0x46, + 0x04, 0xf1, 0x14, 0x06, 0x06, 0xf5, 0xd0, 0x77, 0x0d, 0x46, 0x01, 0x20, + 0xb8, 0x62, 0x05, 0x20, 0xe1, 0x68, 0x08, 0x60, 0xa0, 0x68, 0x00, 0xf0, + 0x89, 0xf9, 0x00, 0x22, 0x31, 0x46, 0x20, 0x46, 0x00, 0xf0, 0xcc, 0xf9, + 0x28, 0x68, 0x20, 0xbb, 0x38, 0x68, 0x10, 0xb3, 0x31, 0x46, 0x20, 0x46, + 0x00, 0xf0, 0x1c, 0xf9, 0xe1, 0x68, 0x00, 0x20, 0x08, 0x62, 0x01, 0x22, + 0x20, 0x68, 0x00, 0x78, 0x00, 0xf0, 0x0f, 0x00, 0x00, 0xf0, 0x20, 0xf8, + 0x29, 0x68, 0x00, 0x29, 0x08, 0xbf, 0x00, 0x28, 0x0f, 0xd1, 0xa0, 0x68, + 0x00, 0x68, 0xc6, 0xf8, 0x34, 0x02, 0x02, 0x22, 0x20, 0x68, 0x00, 0x88, + 0xc0, 0xf3, 0x03, 0x20, 0x00, 0xf0, 0x10, 0xf8, 0x29, 0x68, 0x00, 0x29, + 0x08, 0xbf, 0x00, 0x28, 0x01, 0xd0, 0x00, 0x20, 0xf2, 0xbd, 0x20, 0x68, + 0x00, 0x88, 0xc0, 0xf3, 0x03, 0x20, 0xf8, 0x62, 0x03, 0x22, 0x00, 0xf0, + 0x03, 0xf8, 0xf4, 0xe7, 0x40, 0x1c, 0xf8, 0x62, 0x31, 0x46, 0x20, 0x46, + 0x00, 0xf0, 0x26, 0xbc, 0x51, 0x46, 0x70, 0x68, 0xf6, 0xf7, 0x5a, 0xb9, + 0x4f, 0xf0, 0x7e, 0x50, 0x29, 0x46, 0xf6, 0xf7, 0x45, 0xb8, 0x2d, 0xe9, + 0xf0, 0x47, 0x04, 0x46, 0x04, 0xf1, 0x14, 0x05, 0x05, 0xf5, 0xd0, 0x76, + 0x84, 0xb0, 0x01, 0x20, 0xb0, 0x62, 0x0f, 0x46, 0xe0, 0x68, 0x02, 0x21, + 0x01, 0x62, 0x02, 0x22, 0x05, 0x21, 0x01, 0x60, 0x20, 0x46, 0x29, 0x46, + 0x00, 0xf0, 0x76, 0xf9, 0x38, 0x68, 0x08, 0xb9, 0x30, 0x68, 0x38, 0xb9, + 0xa0, 0x68, 0xd0, 0xf8, 0x10, 0x02, 0x00, 0x28, 0x0c, 0xbf, 0x02, 0x20, + 0x03, 0x20, 0x3e, 0xe0, 0xa0, 0x68, 0xd0, 0xf8, 0x10, 0x02, 0x30, 0xb1, + 0x60, 0x68, 0xd0, 0xf8, 0x28, 0x03, 0x40, 0x28, 0xb6, 0x41, 0xf6, 0x0f, + 0x00, 0xe0, 0x00, 0x26, 0x01, 0x20, 0x00, 0x90, 0x02, 0xab, 0x01, 0xaa, + 0x29, 0x46, 0x20, 0x46, 0x00, 0xf0, 0x2e, 0xf8, 0xa7, 0x68, 0x02, 0x98, + 0x39, 0x68, 0xf6, 0xf7, 0x0b, 0xf8, 0x04, 0x46, 0x07, 0xf1, 0xcc, 0x05, + 0x1e, 0xb1, 0x01, 0x98, 0x28, 0x60, 0x6c, 0x60, 0x1c, 0xe0, 0xdf, 0xf8, + 0xdc, 0x9d, 0x28, 0x68, 0xdf, 0xf8, 0xd8, 0x8d, 0x01, 0xf0, 0x02, 0xf8, + 0x82, 0x46, 0x01, 0x98, 0x01, 0xf0, 0x03, 0xf8, 0x51, 0x46, 0xf6, 0xf7, + 0x69, 0xf8, 0x28, 0x60, 0x49, 0x46, 0x68, 0x68, 0xf6, 0xf7, 0x00, 0xf9, + 0x81, 0x46, 0x20, 0x46, 0x00, 0xf0, 0xf7, 0xff, 0x00, 0xf0, 0xbc, 0xfb, + 0x68, 0x60, 0x38, 0x46, 0x00, 0xf0, 0xe4, 0xf8, 0x30, 0x46, 0x04, 0xb0, + 0xbd, 0xe8, 0xf0, 0x87, 0x2d, 0xe9, 0xf1, 0x4f, 0x84, 0xb0, 0x4f, 0xf0, + 0x7e, 0x50, 0x03, 0x90, 0x88, 0x46, 0x0e, 0x9f, 0x00, 0x20, 0x02, 0x90, + 0x00, 0x2f, 0x08, 0xf5, 0x13, 0x75, 0x14, 0xbf, 0x6c, 0x46, 0x03, 0xac, + 0x68, 0x60, 0x91, 0x46, 0x9a, 0x46, 0x28, 0x60, 0x01, 0x26, 0x04, 0x98, + 0x80, 0x68, 0x01, 0x90, 0x00, 0xeb, 0x86, 0x00, 0x40, 0x68, 0x00, 0x90, + 0xd8, 0xf8, 0x90, 0x01, 0xf0, 0x40, 0xc0, 0x07, 0x1a, 0xd5, 0x58, 0xf8, + 0x26, 0x10, 0x20, 0x68, 0x08, 0xeb, 0x86, 0x0b, 0xf6, 0xf7, 0xca, 0xf8, + 0xdb, 0xf8, 0xc8, 0x10, 0xf6, 0xf7, 0xc6, 0xf8, 0x69, 0x68, 0xf6, 0xf7, + 0x27, 0xf8, 0x68, 0x60, 0x21, 0x68, 0x08, 0x46, 0xf6, 0xf7, 0xbe, 0xf8, + 0xdb, 0xf8, 0xc8, 0x10, 0xf6, 0xf7, 0xba, 0xf8, 0x29, 0x68, 0xf6, 0xf7, + 0x1b, 0xf8, 0x28, 0x60, 0x76, 0x1c, 0x18, 0x2e, 0xd5, 0xdb, 0x68, 0x68, + 0x29, 0x68, 0xf5, 0xf7, 0x21, 0xff, 0xc9, 0xf8, 0x00, 0x00, 0x00, 0x2f, + 0x14, 0xbf, 0xe9, 0x46, 0x0d, 0xf1, 0x08, 0x09, 0x00, 0x20, 0x68, 0x60, + 0x28, 0x60, 0x01, 0x27, 0x01, 0x98, 0x00, 0xeb, 0x87, 0x00, 0x80, 0x6e, + 0x00, 0x90, 0xd8, 0xf8, 0x90, 0x01, 0xf8, 0x40, 0xc0, 0x07, 0x1b, 0xd5, + 0x08, 0xeb, 0x87, 0x04, 0x04, 0xf1, 0x64, 0x06, 0xd9, 0xf8, 0x00, 0x10, + 0x00, 0xf0, 0xc5, 0xf8, 0x01, 0x46, 0xd4, 0xf8, 0x2c, 0x01, 0xf5, 0xf7, + 0x7d, 0xff, 0x71, 0x6e, 0xf6, 0xf7, 0x8a, 0xf8, 0x69, 0x68, 0xf5, 0xf7, + 0xeb, 0xff, 0x68, 0x60, 0x70, 0x6e, 0x01, 0x46, 0xf6, 0xf7, 0x82, 0xf8, + 0x29, 0x68, 0xf5, 0xf7, 0xe3, 0xff, 0x28, 0x60, 0x7f, 0x1c, 0x18, 0x2f, + 0xd6, 0xdb, 0x68, 0x68, 0x29, 0x68, 0xf5, 0xf7, 0xe9, 0xfe, 0xca, 0xf8, + 0x00, 0x00, 0x05, 0xb0, 0xbd, 0xe8, 0xf0, 0x8f, 0x2d, 0xe9, 0xf8, 0x4f, + 0x04, 0x46, 0x00, 0x26, 0x20, 0x69, 0x00, 0x90, 0x0d, 0x46, 0xb3, 0x46, + 0xb0, 0x46, 0xb1, 0x46, 0xb2, 0x46, 0x01, 0x27, 0x01, 0xe0, 0x03, 0x2f, + 0x0b, 0xda, 0x04, 0xeb, 0x87, 0x00, 0x00, 0xf5, 0x34, 0x70, 0x01, 0x68, + 0x40, 0x6e, 0xf5, 0xf7, 0xbf, 0xff, 0x00, 0xf0, 0x1e, 0xfb, 0x06, 0x46, + 0x0e, 0xe0, 0x00, 0xf0, 0x5b, 0xfe, 0x01, 0x46, 0x00, 0x98, 0xb8, 0x42, + 0x04, 0xda, 0x40, 0x46, 0xf5, 0xf7, 0xb2, 0xff, 0x80, 0x46, 0x03, 0xe0, + 0x58, 0x46, 0xf5, 0xf7, 0xad, 0xff, 0x83, 0x46, 0x00, 0xf0, 0x4c, 0xfe, + 0xd5, 0xf8, 0x9c, 0x11, 0xf9, 0x40, 0xc9, 0x07, 0x03, 0xd5, 0x00, 0xf0, + 0x01, 0xfb, 0x81, 0x46, 0x03, 0xe0, 0x51, 0x46, 0xf5, 0xf7, 0x9e, 0xff, + 0x82, 0x46, 0x7f, 0x1c, 0x18, 0x2f, 0xd0, 0xdb, 0x58, 0x46, 0x41, 0x46, + 0xf5, 0xf7, 0x96, 0xff, 0x02, 0x46, 0x50, 0x46, 0x49, 0x46, 0xf6, 0xf7, + 0x1b, 0xf8, 0x10, 0x46, 0x31, 0x46, 0x05, 0xd2, 0xf6, 0xf7, 0x16, 0xf8, + 0x2c, 0xbf, 0x01, 0x20, 0x04, 0x20, 0x0d, 0xe0, 0xf6, 0xf7, 0x10, 0xf8, + 0x38, 0xbf, 0x02, 0x20, 0x08, 0xd3, 0x58, 0x46, 0xf5, 0xf7, 0x80, 0xff, + 0x41, 0x46, 0xf6, 0xf7, 0x07, 0xf8, 0x34, 0xbf, 0x03, 0x20, 0x00, 0x20, + 0xe1, 0x68, 0x08, 0x60, 0xbd, 0xe8, 0xf2, 0x8f, 0x2d, 0xe9, 0xf0, 0x41, + 0x80, 0x46, 0x00, 0x27, 0x08, 0xf5, 0x01, 0x75, 0x08, 0xf1, 0xcc, 0x06, + 0x08, 0xeb, 0x87, 0x04, 0x30, 0x68, 0x61, 0x68, 0xf6, 0xf7, 0x04, 0xf8, + 0x60, 0x60, 0x28, 0x68, 0xf8, 0x40, 0xc0, 0x07, 0x05, 0xd5, 0xd4, 0xf8, + 0xd4, 0x10, 0x00, 0xf0, 0x2e, 0xf8, 0xc4, 0xf8, 0xd4, 0x00, 0x7f, 0x1c, + 0x18, 0x2f, 0xeb, 0xdb, 0x4f, 0xf0, 0x7e, 0x50, 0x30, 0x60, 0x00, 0x27, + 0xd8, 0xf8, 0x00, 0x10, 0x70, 0x68, 0xf5, 0xf7, 0x51, 0xff, 0xc8, 0xf8, + 0x00, 0x00, 0x08, 0xeb, 0x87, 0x00, 0x00, 0xf5, 0x9c, 0x74, 0x68, 0x68, + 0xf8, 0x40, 0xc0, 0x07, 0x04, 0xd5, 0x20, 0x68, 0x71, 0x68, 0xf5, 0xf7, + 0xcf, 0xfe, 0x20, 0x60, 0xa8, 0x68, 0xf8, 0x40, 0xc0, 0x07, 0x04, 0xd5, + 0x60, 0x6e, 0x71, 0x68, 0xf5, 0xf7, 0xc6, 0xfe, 0x60, 0x66, 0x7f, 0x1c, + 0x18, 0x2f, 0xe6, 0xdb, 0x00, 0x20, 0x70, 0x60, 0xbd, 0xe8, 0xf0, 0x81, + 0xf1, 0x68, 0x30, 0x68, 0xf5, 0xf7, 0xca, 0xbf, 0x2d, 0xe9, 0xf6, 0x4f, + 0x04, 0x46, 0x85, 0xb0, 0x60, 0x68, 0xd0, 0xf8, 0x28, 0x03, 0xf5, 0xf7, + 0x23, 0xfe, 0x05, 0x46, 0x4f, 0xf0, 0x8a, 0x40, 0x00, 0xf0, 0xd1, 0xff, + 0x83, 0x46, 0x82, 0x46, 0x4f, 0xf0, 0x8e, 0x40, 0x00, 0xf0, 0xcb, 0xff, + 0x05, 0x46, 0x06, 0x46, 0x4f, 0xf0, 0x00, 0x08, 0x00, 0xf0, 0x6e, 0xfa, + 0x04, 0xeb, 0x88, 0x07, 0xd2, 0xe9, 0x00, 0x01, 0xf5, 0xf7, 0xde, 0xfd, + 0x59, 0x46, 0x07, 0xf5, 0x34, 0x79, 0xf5, 0xf7, 0x17, 0xfe, 0xc9, 0xf8, + 0x00, 0x00, 0x07, 0xf5, 0x66, 0x77, 0x00, 0xf0, 0x5d, 0xfa, 0xd2, 0xe9, + 0x32, 0x01, 0xf5, 0xf7, 0xcf, 0xfd, 0x51, 0x46, 0xf5, 0xf7, 0x0a, 0xfe, + 0xc9, 0xf8, 0x64, 0x00, 0x00, 0xf0, 0x52, 0xfa, 0xd2, 0xe9, 0x64, 0x01, + 0xf5, 0xf7, 0xb6, 0xfd, 0x29, 0x46, 0xf5, 0xf7, 0xff, 0xfd, 0x38, 0x60, + 0x00, 0xf0, 0x48, 0xfa, 0x08, 0xf1, 0x01, 0x08, 0xd2, 0xe9, 0x96, 0x01, + 0xf5, 0xf7, 0xaa, 0xfd, 0x31, 0x46, 0xf5, 0xf7, 0xf3, 0xfd, 0xb8, 0xf1, + 0x19, 0x0f, 0x78, 0x66, 0xca, 0xd3, 0x62, 0x68, 0x01, 0x25, 0xd2, 0xe9, + 0xc8, 0x01, 0xf5, 0xf7, 0xab, 0xfd, 0x4f, 0xf0, 0x3a, 0x51, 0xf5, 0xf7, + 0x73, 0xff, 0xc4, 0xf8, 0x60, 0x04, 0xd4, 0xf8, 0xd0, 0x02, 0x01, 0x90, + 0x04, 0xeb, 0x85, 0x06, 0x06, 0xf5, 0x34, 0x71, 0x00, 0xf0, 0x72, 0xfd, + 0x07, 0x46, 0xd6, 0xf8, 0x98, 0x03, 0x4f, 0xf0, 0x80, 0x41, 0xf5, 0xf7, + 0x61, 0xff, 0x00, 0xf0, 0x9b, 0xfd, 0x07, 0x46, 0x01, 0x98, 0x39, 0x46, + 0xf5, 0xf7, 0x48, 0xff, 0x38, 0xbf, 0x01, 0x97, 0x6d, 0x1c, 0x15, 0x2d, + 0xe6, 0xd3, 0x01, 0x26, 0x05, 0x98, 0x00, 0xf5, 0xc8, 0x75, 0x00, 0x20, + 0x28, 0x60, 0x68, 0x60, 0xa8, 0x60, 0xe8, 0x60, 0x28, 0x61, 0xa8, 0x61, + 0x68, 0x61, 0xe8, 0x61, 0xe8, 0x62, 0x28, 0x63, 0x28, 0x62, 0x68, 0x62, + 0xa8, 0x62, 0xd4, 0xf8, 0x60, 0x14, 0xdf, 0xf8, 0x40, 0x0a, 0xf5, 0xf7, + 0x3d, 0xff, 0x03, 0x90, 0x04, 0xeb, 0x86, 0x00, 0x00, 0xf5, 0x34, 0x71, + 0x00, 0xf5, 0x66, 0x77, 0xd1, 0xf8, 0x00, 0xa0, 0x49, 0x6e, 0x00, 0x91, + 0x4f, 0xf0, 0x80, 0x41, 0x38, 0x68, 0xf5, 0xf7, 0x2d, 0xff, 0x81, 0x46, + 0x05, 0x98, 0x00, 0xeb, 0x86, 0x08, 0x78, 0x6e, 0xc8, 0xf8, 0x2c, 0x01, + 0x51, 0x46, 0x00, 0x98, 0xf5, 0xf7, 0x86, 0xfe, 0x83, 0x46, 0x00, 0xf0, + 0xe1, 0xf9, 0x02, 0x90, 0x00, 0x21, 0xf5, 0xf7, 0xfb, 0xfe, 0x07, 0x46, + 0x36, 0xd0, 0x58, 0x46, 0x49, 0x46, 0xf5, 0xf7, 0x05, 0xfe, 0x39, 0x46, + 0xf5, 0xf7, 0x84, 0xfd, 0x00, 0x21, 0xf6, 0xf7, 0x17, 0xf8, 0x81, 0x46, + 0x04, 0xd9, 0xdf, 0xf8, 0xdc, 0x09, 0x00, 0xf0, 0xff, 0xfd, 0x81, 0x46, + 0x48, 0x46, 0xf5, 0xf7, 0xab, 0xfe, 0x05, 0x99, 0x41, 0xf8, 0x26, 0x00, + 0x50, 0x46, 0x00, 0x99, 0xf5, 0xf7, 0xee, 0xfd, 0x81, 0x46, 0x4f, 0xf0, + 0x7c, 0x50, 0x49, 0x46, 0x08, 0xf1, 0x64, 0x0a, 0xf5, 0xf7, 0xf6, 0xfe, + 0xca, 0xf8, 0x00, 0x00, 0x39, 0x46, 0x4f, 0xf0, 0x3f, 0x40, 0xf5, 0xf7, + 0xef, 0xfe, 0xca, 0xf8, 0x64, 0x00, 0x00, 0x21, 0xda, 0xf8, 0x00, 0x00, + 0xf5, 0xf7, 0xf0, 0xff, 0x24, 0xbf, 0xdf, 0xf8, 0x90, 0x19, 0xf5, 0xf7, + 0xe3, 0xfe, 0x02, 0xe0, 0x4f, 0xf0, 0x7e, 0x59, 0xd6, 0xe7, 0x29, 0x6b, + 0xf5, 0xf7, 0xca, 0xfe, 0x38, 0xbf, 0x08, 0x46, 0x28, 0x63, 0xda, 0xf8, + 0x64, 0x10, 0xe8, 0x6a, 0xf5, 0xf7, 0xc2, 0xfe, 0x38, 0xbf, 0x01, 0x46, + 0xe9, 0x62, 0x38, 0x46, 0x01, 0x99, 0xd4, 0xf8, 0x00, 0xa0, 0xf5, 0xf7, + 0x3d, 0xfd, 0x0a, 0xf1, 0x08, 0x0b, 0x01, 0x46, 0xdb, 0xf8, 0x04, 0x00, + 0xf5, 0xf7, 0xb2, 0xfe, 0x08, 0xd2, 0xdb, 0xf8, 0x00, 0x00, 0x39, 0x46, + 0xf5, 0xf7, 0xac, 0xfe, 0x38, 0xbf, 0x4f, 0xf0, 0x01, 0x0b, 0x01, 0xd3, + 0x4f, 0xf0, 0x00, 0x0b, 0xa0, 0x68, 0xd0, 0xf8, 0x10, 0x02, 0x10, 0xb9, + 0x06, 0x98, 0x02, 0x28, 0x02, 0xd1, 0xda, 0xf8, 0x8c, 0x00, 0x78, 0xb1, + 0x0a, 0xeb, 0x86, 0x01, 0x03, 0x98, 0x89, 0x6a, 0xf5, 0xf7, 0xa8, 0xfe, + 0x00, 0x90, 0x39, 0x46, 0xdf, 0xf8, 0x10, 0x09, 0xf5, 0xf7, 0xa2, 0xfe, + 0x00, 0x99, 0xf5, 0xf7, 0x8d, 0xfe, 0x29, 0xd3, 0xbb, 0xf1, 0x00, 0x0f, + 0x1c, 0xbf, 0x06, 0x98, 0x01, 0x28, 0x25, 0xd0, 0x05, 0x98, 0xdf, 0xf8, + 0xf0, 0x18, 0x50, 0xf8, 0x26, 0x00, 0xf5, 0xf7, 0xf5, 0xfd, 0x83, 0x46, + 0xd8, 0xf8, 0x2c, 0x01, 0x39, 0x46, 0xf5, 0xf7, 0xfd, 0xfc, 0x80, 0x46, + 0x58, 0x46, 0x00, 0xf0, 0xb1, 0xfc, 0x07, 0x46, 0x40, 0x46, 0x00, 0xf0, + 0x7e, 0xfd, 0x00, 0xf0, 0xbd, 0xfc, 0x4f, 0xf0, 0x7a, 0x51, 0xf5, 0xf7, + 0x7d, 0xfe, 0x0a, 0xf1, 0x8c, 0x01, 0x49, 0x69, 0xf5, 0xf7, 0x66, 0xfe, + 0x38, 0xbf, 0x4f, 0xf0, 0x01, 0x0b, 0x01, 0xd3, 0x4f, 0xf0, 0x00, 0x0b, + 0x28, 0x69, 0x58, 0x44, 0x28, 0x61, 0x0b, 0xfa, 0x06, 0xf1, 0x28, 0x68, + 0x08, 0x43, 0x28, 0x60, 0x48, 0x46, 0x02, 0x99, 0xf5, 0xf7, 0xd8, 0xfc, + 0x01, 0x46, 0x20, 0x68, 0x07, 0x69, 0x38, 0x46, 0xf5, 0xf7, 0x4e, 0xfe, + 0x05, 0xd2, 0x01, 0x20, 0x5f, 0xea, 0x0b, 0x01, 0x0e, 0xd0, 0x01, 0x21, + 0x0c, 0xe0, 0xdf, 0xf8, 0x74, 0x08, 0xf5, 0xf7, 0x55, 0xfe, 0x01, 0x46, + 0x38, 0x46, 0xf5, 0xf7, 0x3f, 0xfe, 0x34, 0xbf, 0x4f, 0xf0, 0xff, 0x30, + 0x00, 0x20, 0x00, 0x21, 0xaa, 0x69, 0x8a, 0x18, 0xaa, 0x61, 0xb1, 0x40, + 0x6a, 0x68, 0x11, 0x43, 0xbb, 0xf1, 0x00, 0x0f, 0x69, 0x60, 0x04, 0xd0, + 0x10, 0xf1, 0x01, 0x0f, 0x08, 0xbf, 0x01, 0x21, 0x00, 0xd0, 0x00, 0x21, + 0x6a, 0x69, 0x8a, 0x18, 0x6a, 0x61, 0xb1, 0x40, 0xaa, 0x68, 0x11, 0x43, + 0xa9, 0x60, 0x40, 0x1e, 0x80, 0x41, 0xe9, 0x69, 0xc0, 0x0f, 0x41, 0x18, + 0xe9, 0x61, 0xb0, 0x40, 0xe9, 0x68, 0x76, 0x1c, 0x08, 0x43, 0x15, 0x2e, + 0xe8, 0x60, 0xff, 0xf4, 0xeb, 0xae, 0x4f, 0xf0, 0x7e, 0x50, 0x05, 0x99, + 0x08, 0x60, 0x00, 0x21, 0x05, 0x98, 0xc8, 0x30, 0x41, 0x66, 0x01, 0x60, + 0x00, 0x20, 0x05, 0x99, 0x48, 0x66, 0x15, 0x26, 0x05, 0x99, 0x4f, 0xf0, + 0x7e, 0x50, 0x41, 0xf8, 0x26, 0x00, 0x00, 0x21, 0x05, 0x98, 0x00, 0xeb, + 0x86, 0x00, 0x76, 0x1c, 0xc0, 0xf8, 0x2c, 0x11, 0x64, 0x30, 0x19, 0x2e, + 0x41, 0x66, 0x01, 0x60, 0xee, 0xd3, 0x06, 0x98, 0x01, 0x28, 0x25, 0xd1, + 0xe9, 0x6a, 0x4f, 0xf0, 0x40, 0x40, 0xf5, 0xf7, 0x01, 0xfe, 0x80, 0x46, + 0x01, 0x26, 0x04, 0xeb, 0x86, 0x07, 0x07, 0xf5, 0x34, 0x71, 0x00, 0xf0, + 0x03, 0xfc, 0x81, 0x46, 0xd7, 0xf8, 0x98, 0x03, 0x4f, 0xf0, 0x80, 0x41, + 0xf5, 0xf7, 0xf2, 0xfd, 0x00, 0xf0, 0xb2, 0xf8, 0x41, 0x46, 0xf5, 0xf7, + 0x5f, 0xfc, 0xdf, 0xf8, 0xa4, 0x17, 0xf5, 0xf7, 0xd7, 0xfd, 0x04, 0xd2, + 0x28, 0x68, 0x01, 0x21, 0xb1, 0x40, 0x88, 0x43, 0x28, 0x60, 0x76, 0x1c, + 0x18, 0x2e, 0xe0, 0xd3, 0x27, 0x68, 0xe9, 0x6a, 0x38, 0x6a, 0xf5, 0xf7, + 0xdb, 0xfd, 0x06, 0x46, 0x29, 0x6b, 0x78, 0x6a, 0xf5, 0xf7, 0xd6, 0xfd, + 0x80, 0x46, 0x01, 0x27, 0x05, 0x98, 0x00, 0xeb, 0x87, 0x00, 0x00, 0xf1, + 0x64, 0x09, 0x28, 0x68, 0xf8, 0x40, 0xc0, 0x07, 0x07, 0xd5, 0xd9, 0xf8, + 0x64, 0x00, 0x31, 0x46, 0xf5, 0xf7, 0xb4, 0xfd, 0x38, 0xbf, 0x01, 0x20, + 0x00, 0xd3, 0x00, 0x20, 0x29, 0x6a, 0xb8, 0x40, 0x08, 0x43, 0x28, 0x62, + 0x68, 0x68, 0xf8, 0x40, 0xc0, 0x07, 0x07, 0xd5, 0xd9, 0xf8, 0x00, 0x10, + 0x40, 0x46, 0xf5, 0xf7, 0xa3, 0xfd, 0x38, 0xbf, 0x01, 0x20, 0x00, 0xd3, + 0x00, 0x20, 0x69, 0x6a, 0xb8, 0x40, 0x08, 0x43, 0x68, 0x62, 0xa8, 0x68, + 0xf8, 0x40, 0xc0, 0x07, 0x0b, 0xd5, 0xdf, 0xf8, 0x14, 0x07, 0x00, 0xf0, + 0xa0, 0xfc, 0x01, 0x46, 0xd9, 0xf8, 0x00, 0x00, 0xf5, 0xf7, 0x8e, 0xfd, + 0x38, 0xbf, 0x01, 0x20, 0x00, 0xd3, 0x00, 0x20, 0xa9, 0x6a, 0xb8, 0x40, + 0x7f, 0x1c, 0x08, 0x43, 0x18, 0x2f, 0xa8, 0x62, 0xc0, 0xd3, 0x04, 0xf5, + 0x34, 0x70, 0xd4, 0xf8, 0x9c, 0x63, 0xd4, 0xf8, 0xd0, 0x12, 0x40, 0x68, + 0xf5, 0xf7, 0xf0, 0xfc, 0x04, 0xf5, 0x34, 0x71, 0x4f, 0xf0, 0x02, 0x08, + 0x89, 0x6e, 0xf5, 0xf7, 0xe9, 0xfc, 0x00, 0xf0, 0x48, 0xf8, 0x00, 0xf0, + 0x46, 0xf8, 0x06, 0x46, 0x00, 0x20, 0x04, 0xeb, 0x88, 0x01, 0x01, 0xf5, + 0x34, 0x79, 0xd1, 0xf8, 0x98, 0x73, 0xd9, 0xf8, 0x00, 0x10, 0xf5, 0xf7, + 0xd9, 0xfc, 0xd9, 0xf8, 0x64, 0x10, 0xf5, 0xf7, 0xd5, 0xfc, 0x00, 0xf0, + 0xab, 0xfb, 0x00, 0xf0, 0xa9, 0xfb, 0x08, 0xf1, 0x01, 0x08, 0xb8, 0xf1, + 0x18, 0x0f, 0xe8, 0xd3, 0xa7, 0x68, 0xdf, 0xf8, 0x3c, 0x1d, 0xf5, 0xf7, + 0x63, 0xfd, 0x01, 0x46, 0x30, 0x46, 0xf5, 0xf7, 0x4d, 0xfd, 0x34, 0xbf, + 0x01, 0x20, 0x00, 0x20, 0x87, 0xf8, 0x08, 0x03, 0xe1, 0x68, 0x28, 0x68, + 0x48, 0x60, 0xe1, 0x68, 0x68, 0x68, 0x88, 0x60, 0xe1, 0x68, 0xa8, 0x68, + 0xc8, 0x60, 0xe1, 0x68, 0xe8, 0x68, 0x08, 0x61, 0xe1, 0x68, 0x28, 0x6a, + 0x48, 0x61, 0xe1, 0x68, 0x68, 0x6a, 0x88, 0x61, 0xe1, 0x68, 0xa8, 0x6a, + 0xc8, 0x61, 0x07, 0xb0, 0xbd, 0xe8, 0xf0, 0x8f, 0x60, 0x68, 0x00, 0xeb, + 0xc8, 0x02, 0x70, 0x47, 0x49, 0x46, 0xf5, 0xf7, 0x9f, 0xbc, 0x31, 0x46, + 0xf5, 0xf7, 0x9c, 0xbc, 0x2d, 0xe9, 0xf7, 0x4f, 0x86, 0xb0, 0x80, 0x68, + 0xd0, 0xf8, 0x00, 0x02, 0x40, 0x08, 0x00, 0xf0, 0x01, 0x00, 0x03, 0x90, + 0x07, 0x98, 0x00, 0xf5, 0xc8, 0x74, 0x20, 0x69, 0x00, 0x28, 0x00, 0xf0, + 0xae, 0x81, 0x07, 0x98, 0xdf, 0xf8, 0x0c, 0xb6, 0x00, 0xf5, 0xe8, 0x70, + 0x04, 0x90, 0x64, 0x21, 0xf6, 0xf7, 0xce, 0xfb, 0x07, 0x98, 0x00, 0xf5, + 0x0d, 0x76, 0x14, 0x21, 0x30, 0x46, 0xf6, 0xf7, 0xc7, 0xfb, 0x07, 0x98, + 0x00, 0xf5, 0xe2, 0x70, 0x00, 0x90, 0x4f, 0xf0, 0x7e, 0x58, 0x08, 0x98, + 0x01, 0x28, 0x46, 0xd1, 0x00, 0xf0, 0xdd, 0xfa, 0x0a, 0xe0, 0xf5, 0xf7, + 0x09, 0xfd, 0x03, 0x2d, 0x30, 0x62, 0x02, 0xd2, 0x00, 0xf0, 0xda, 0xfa, + 0x30, 0x62, 0x6d, 0x1c, 0x00, 0xf0, 0xe9, 0xfa, 0x18, 0x2d, 0x47, 0xd2, + 0x20, 0x68, 0x22, 0x6a, 0x65, 0x63, 0xe8, 0x40, 0x00, 0xf0, 0x01, 0x09, + 0x06, 0x98, 0x81, 0x68, 0xd1, 0xf8, 0x04, 0x02, 0xc6, 0xf8, 0x14, 0x80, + 0xe8, 0x40, 0xea, 0x40, 0xc6, 0xf8, 0x18, 0x80, 0x01, 0x23, 0x00, 0xf0, + 0x01, 0x00, 0x02, 0xf0, 0x01, 0x02, 0xa3, 0x63, 0x4a, 0xb9, 0x28, 0xb1, + 0x00, 0xf0, 0x11, 0xfb, 0x06, 0x99, 0x09, 0x68, 0x49, 0x69, 0xd4, 0xe7, + 0xb9, 0xf1, 0x00, 0x0f, 0x0a, 0xd0, 0x07, 0x98, 0x50, 0xf8, 0x25, 0x00, + 0xf0, 0x61, 0x59, 0x46, 0x07, 0x98, 0x00, 0xeb, 0x85, 0x00, 0xd0, 0xf8, + 0xc8, 0x00, 0xc6, 0xe7, 0x00, 0xf0, 0xfd, 0xfa, 0x01, 0x46, 0x06, 0x98, + 0x03, 0x9a, 0x00, 0x68, 0x00, 0x2a, 0x14, 0xbf, 0x80, 0x69, 0xc0, 0x69, + 0xbb, 0xe7, 0x02, 0x28, 0x72, 0xd1, 0x00, 0xf0, 0x94, 0xfa, 0x0a, 0xe0, + 0xf5, 0xf7, 0xc0, 0xfc, 0x03, 0x2d, 0x30, 0x62, 0x02, 0xd2, 0x00, 0xf0, + 0x91, 0xfa, 0x30, 0x62, 0x00, 0xf0, 0xa1, 0xfa, 0x6d, 0x1c, 0x18, 0x2d, + 0x80, 0xf0, 0xf4, 0x80, 0x60, 0x68, 0x65, 0x63, 0xe8, 0x40, 0xc0, 0x07, + 0x5d, 0xbf, 0xa0, 0x68, 0xe8, 0x40, 0x00, 0xf0, 0x01, 0x09, 0x4f, 0xf0, + 0x01, 0x09, 0x00, 0xf0, 0x99, 0xfa, 0x29, 0xd4, 0xa1, 0x6a, 0xe9, 0x40, + 0xc9, 0x07, 0x25, 0xd4, 0x6f, 0xb1, 0x00, 0xeb, 0x85, 0x00, 0xc6, 0xf8, + 0x14, 0x80, 0xc6, 0xf8, 0x18, 0xb0, 0xd0, 0xf8, 0x38, 0x01, 0x00, 0xf0, + 0xdd, 0xfa, 0x00, 0xf0, 0xb8, 0xfa, 0x00, 0xf0, 0x7b, 0xfa, 0x01, 0x98, + 0x60, 0xb1, 0x00, 0xf0, 0x52, 0xfa, 0x80, 0x68, 0x00, 0xeb, 0x85, 0x00, + 0xd0, 0xf8, 0x9c, 0x01, 0x00, 0xf0, 0xce, 0xfa, 0x00, 0xf0, 0xa9, 0xfa, + 0x00, 0xf0, 0x6c, 0xfa, 0x01, 0x98, 0x38, 0x43, 0xc0, 0xb2, 0x00, 0x28, + 0xc6, 0xd1, 0xb9, 0xf1, 0x00, 0x0f, 0x12, 0xd0, 0x00, 0xf0, 0x43, 0xfa, + 0x06, 0x98, 0x80, 0x68, 0x49, 0x6e, 0x00, 0xeb, 0x85, 0x00, 0x40, 0x68, + 0xf5, 0xf7, 0x72, 0xfc, 0xb0, 0x61, 0xd9, 0xf8, 0x2c, 0x01, 0xf0, 0x61, + 0x01, 0x20, 0xa0, 0x63, 0xc6, 0xf8, 0x20, 0x80, 0xae, 0xe7, 0x70, 0x61, + 0xc6, 0xf8, 0x18, 0xb0, 0x00, 0xf0, 0x4f, 0xfa, 0x00, 0xf0, 0x6c, 0xfa, + 0x4f, 0xf0, 0x7c, 0x51, 0xf5, 0xf7, 0x5e, 0xfc, 0x00, 0xf0, 0xa2, 0xfa, + 0x01, 0x46, 0x31, 0x62, 0x06, 0x98, 0x03, 0x9a, 0x00, 0x68, 0x00, 0x2a, + 0x14, 0xbf, 0x80, 0x69, 0xc0, 0x69, 0x8f, 0xe7, 0x60, 0x6a, 0x00, 0x28, + 0x04, 0xbf, 0xa0, 0x6a, 0x00, 0x28, 0x05, 0xd0, 0x21, 0x6b, 0x08, 0x46, + 0xf5, 0xf7, 0x48, 0xfc, 0x02, 0x90, 0x01, 0xe0, 0xcd, 0xf8, 0x08, 0x80, + 0x00, 0xf0, 0x13, 0xfa, 0x0c, 0xe0, 0x02, 0x98, 0x51, 0x46, 0xf5, 0xf7, + 0x3d, 0xfc, 0x03, 0x2d, 0x30, 0x62, 0x02, 0xd2, 0x00, 0xf0, 0x0f, 0xfa, + 0x30, 0x62, 0x00, 0xf0, 0x1e, 0xfa, 0x6d, 0x1c, 0x18, 0x2d, 0x71, 0xd2, + 0x60, 0x68, 0x65, 0x63, 0xe8, 0x40, 0xc0, 0x07, 0x5d, 0xbf, 0xa0, 0x68, + 0xe8, 0x40, 0x00, 0xf0, 0x01, 0x09, 0x4f, 0xf0, 0x01, 0x09, 0x00, 0xf0, + 0x17, 0xfa, 0x2f, 0xd4, 0xa1, 0x6a, 0xe9, 0x40, 0xc9, 0x07, 0x2b, 0xd4, + 0x06, 0x99, 0x09, 0x68, 0xd1, 0xf8, 0x14, 0xa0, 0x77, 0xb1, 0x00, 0xeb, + 0x85, 0x01, 0xc6, 0xf8, 0x14, 0x80, 0xc6, 0xf8, 0x18, 0x80, 0xd1, 0xf8, + 0x38, 0x11, 0x00, 0x68, 0xf5, 0xf7, 0x74, 0xfb, 0x00, 0xf0, 0x2b, 0xfa, + 0x00, 0xf0, 0xf4, 0xf9, 0x01, 0x98, 0x68, 0xb1, 0x00, 0xf0, 0xcb, 0xf9, + 0x81, 0x68, 0x01, 0xeb, 0x85, 0x00, 0x09, 0x68, 0xd0, 0xf8, 0x9c, 0x01, + 0xf5, 0xf7, 0x64, 0xfb, 0x00, 0xf0, 0x1b, 0xfa, 0x00, 0xf0, 0xe4, 0xf9, + 0x01, 0x98, 0x38, 0x43, 0xc0, 0xb2, 0x00, 0x28, 0xc1, 0xd1, 0xb9, 0xf1, + 0x00, 0x0f, 0x19, 0xd0, 0x00, 0xf0, 0xbb, 0xf9, 0xb0, 0x61, 0x06, 0x98, + 0xd0, 0xf8, 0x08, 0xa0, 0x49, 0x6e, 0x0a, 0xeb, 0x85, 0x00, 0x40, 0x68, + 0xf5, 0xf7, 0xe8, 0xfb, 0xda, 0xf8, 0x00, 0x10, 0xf5, 0xf7, 0xe4, 0xfb, + 0x01, 0x46, 0xd9, 0xf8, 0x2c, 0x01, 0xf5, 0xf7, 0xcf, 0xfa, 0xf0, 0x61, + 0xa5, 0x63, 0xc6, 0xf8, 0x20, 0x80, 0xa2, 0xe7, 0xc6, 0xf8, 0x14, 0x80, + 0xc6, 0xf8, 0x18, 0x80, 0x00, 0xf0, 0xbf, 0xf9, 0x08, 0x68, 0x49, 0x6e, + 0xf5, 0xf7, 0xc0, 0xfa, 0x4f, 0xf0, 0x7c, 0x51, 0xf5, 0xf7, 0xcc, 0xfb, + 0xf0, 0x61, 0xa5, 0x63, 0x06, 0x98, 0x03, 0x99, 0x00, 0x68, 0x00, 0x29, + 0x14, 0xbf, 0xd0, 0xf8, 0x18, 0xa0, 0xd0, 0xf8, 0x1c, 0xa0, 0x7e, 0xe7, + 0xe0, 0x6b, 0x01, 0x28, 0x05, 0xd1, 0x30, 0x68, 0x21, 0x6c, 0xf5, 0xf7, + 0x2b, 0xfa, 0x30, 0x60, 0x04, 0xe0, 0x02, 0x46, 0x04, 0x98, 0x31, 0x46, + 0x00, 0xf0, 0x14, 0xfb, 0x08, 0x98, 0x02, 0x28, 0x26, 0xd1, 0x34, 0x68, + 0x20, 0x46, 0x21, 0x46, 0xf5, 0xf7, 0x8a, 0xfb, 0x2f, 0xd1, 0x06, 0x98, + 0x85, 0x68, 0x95, 0xf8, 0x00, 0x02, 0xc0, 0x07, 0x12, 0xd5, 0x06, 0x98, + 0x00, 0x68, 0x46, 0x68, 0x40, 0x46, 0x31, 0x46, 0xf5, 0xf7, 0x8c, 0xfa, + 0x29, 0x68, 0xf5, 0xf7, 0x99, 0xfb, 0x07, 0x46, 0x20, 0x46, 0x31, 0x46, + 0xf5, 0xf7, 0x94, 0xfb, 0x00, 0xf0, 0xce, 0xf9, 0x28, 0x60, 0x00, 0xe0, + 0x2c, 0x60, 0xd5, 0xf8, 0x00, 0x02, 0x40, 0xf0, 0x01, 0x00, 0xc5, 0xf8, + 0x00, 0x02, 0x46, 0xe1, 0x00, 0x25, 0x00, 0xe0, 0x6d, 0x1c, 0xe0, 0x6b, + 0x85, 0x42, 0x0a, 0xd2, 0x07, 0x98, 0x00, 0xeb, 0x85, 0x00, 0xd0, 0xf8, + 0x34, 0x02, 0x01, 0x46, 0xf5, 0xf7, 0x5a, 0xfb, 0xf2, 0xd0, 0x01, 0x20, + 0x36, 0xe1, 0x08, 0x98, 0x01, 0x28, 0x0c, 0xbf, 0x02, 0x20, 0x01, 0x20, + 0x00, 0x90, 0x31, 0x46, 0x06, 0x98, 0x03, 0x69, 0x07, 0x98, 0xe2, 0x6b, + 0x00, 0xf5, 0x16, 0x70, 0x00, 0xf0, 0x84, 0xfa, 0x08, 0x98, 0x01, 0x28, + 0x10, 0xd1, 0x00, 0x25, 0x09, 0xe0, 0x07, 0x99, 0x01, 0xeb, 0x80, 0x00, + 0x01, 0xeb, 0x85, 0x01, 0xd0, 0xf8, 0x5c, 0x02, 0xc1, 0xf8, 0x58, 0x02, + 0x6d, 0x1c, 0x06, 0x98, 0x07, 0x68, 0x78, 0x88, 0xa8, 0x42, 0xf0, 0xd2, + 0x00, 0x25, 0x07, 0x98, 0x00, 0xeb, 0x85, 0x0b, 0x08, 0x98, 0x01, 0x28, + 0x1f, 0xd1, 0x06, 0x98, 0x81, 0x68, 0xdb, 0xf8, 0x58, 0x62, 0xd1, 0xf8, + 0x04, 0x02, 0x01, 0xeb, 0x85, 0x08, 0x98, 0xb1, 0x06, 0x98, 0x07, 0x68, + 0x7f, 0x68, 0x00, 0xf0, 0x57, 0xfb, 0x01, 0x46, 0xd8, 0xf8, 0x04, 0x00, + 0xf5, 0xf7, 0x3a, 0xfb, 0x83, 0x46, 0x30, 0x46, 0x39, 0x46, 0xf5, 0xf7, + 0x35, 0xfb, 0x00, 0xf0, 0x36, 0xf9, 0xc8, 0xf8, 0x04, 0x00, 0x2a, 0xe0, + 0xc8, 0xf8, 0x04, 0x60, 0x27, 0xe0, 0x03, 0x28, 0x25, 0xd1, 0x06, 0x98, + 0x82, 0x68, 0x02, 0xf5, 0x01, 0x76, 0x70, 0x68, 0x00, 0x28, 0x04, 0xbf, + 0xb0, 0x68, 0x00, 0x28, 0x16, 0xd0, 0x06, 0x98, 0x07, 0x68, 0x7f, 0x68, + 0x02, 0xeb, 0x85, 0x08, 0x00, 0xf0, 0x32, 0xfb, 0x01, 0x46, 0xd8, 0xf8, + 0x68, 0x00, 0xf5, 0xf7, 0x15, 0xfb, 0x06, 0x46, 0xdb, 0xf8, 0x58, 0x02, + 0x39, 0x46, 0xf5, 0xf7, 0x0f, 0xfb, 0xff, 0xf7, 0xd2, 0xfd, 0xc8, 0xf8, + 0x68, 0x00, 0x04, 0xe0, 0xdb, 0xf8, 0x58, 0x02, 0x02, 0xeb, 0x85, 0x01, + 0x88, 0x66, 0x6d, 0x1c, 0x19, 0x2d, 0xae, 0xd3, 0x00, 0x25, 0x01, 0x20, + 0xa8, 0x40, 0x00, 0x90, 0x07, 0x98, 0x00, 0xeb, 0x85, 0x08, 0x08, 0x98, + 0x01, 0x28, 0x38, 0xd1, 0x06, 0x98, 0x82, 0x68, 0x21, 0x6a, 0x02, 0xf5, + 0x01, 0x76, 0xe9, 0x40, 0x30, 0x68, 0xe8, 0x40, 0xc9, 0x07, 0x00, 0xf0, + 0x01, 0x00, 0x18, 0xd5, 0xd8, 0xf8, 0x58, 0x82, 0x02, 0xeb, 0x85, 0x01, + 0x01, 0xf1, 0xd4, 0x0b, 0x50, 0xb1, 0x00, 0xf0, 0x22, 0xf9, 0x00, 0xf0, + 0xf9, 0xf8, 0x00, 0xf0, 0xd8, 0xf9, 0xff, 0xf7, 0x9f, 0xfd, 0xcb, 0xf8, + 0x00, 0x00, 0x01, 0xe0, 0xcb, 0xf8, 0x00, 0x80, 0x30, 0x68, 0x00, 0x99, + 0x08, 0x43, 0x30, 0x60, 0x8d, 0xe0, 0x00, 0x28, 0xfc, 0xd1, 0x02, 0xeb, + 0x85, 0x00, 0x00, 0xf1, 0xd4, 0x0b, 0x00, 0xf0, 0x0a, 0xf9, 0x00, 0xf0, + 0xe1, 0xf8, 0x06, 0x46, 0xd8, 0xf8, 0x58, 0x02, 0x00, 0xf0, 0xe8, 0xfc, + 0xff, 0xf7, 0x87, 0xfd, 0xcb, 0xf8, 0x00, 0x00, 0x79, 0xe0, 0x08, 0x98, + 0x03, 0x28, 0x76, 0xd1, 0x06, 0x98, 0xd0, 0xf8, 0x08, 0xa0, 0x0a, 0xf5, + 0x01, 0x76, 0x70, 0x68, 0xe8, 0x40, 0x00, 0xf0, 0x01, 0x07, 0xb0, 0x68, + 0xe8, 0x40, 0x00, 0xf0, 0x01, 0x00, 0x01, 0x90, 0x60, 0x6a, 0xe8, 0x40, + 0xc0, 0x07, 0x19, 0xd5, 0x00, 0xf0, 0xde, 0xf8, 0x80, 0x46, 0x0a, 0xeb, + 0x85, 0x00, 0x00, 0xf1, 0xd4, 0x0b, 0x57, 0xb1, 0x00, 0xf0, 0xdf, 0xf8, + 0x00, 0xf0, 0xb1, 0xf8, 0x00, 0xf0, 0x95, 0xf9, 0xff, 0xf7, 0x5c, 0xfd, + 0xcb, 0xf8, 0x64, 0x00, 0x01, 0xe0, 0xcb, 0xf8, 0x64, 0x80, 0x70, 0x68, + 0x00, 0x99, 0x08, 0x43, 0x70, 0x60, 0x4a, 0xe0, 0xa0, 0x6a, 0xe8, 0x40, + 0xc0, 0x07, 0x1b, 0xd5, 0x00, 0xf0, 0xb0, 0xfb, 0x83, 0x46, 0x01, 0x98, + 0x0a, 0xeb, 0x85, 0x09, 0x68, 0xb1, 0x00, 0xf0, 0xc2, 0xf8, 0x00, 0xf0, + 0x8f, 0xf8, 0x80, 0x46, 0x78, 0x68, 0x00, 0xf0, 0xa7, 0xf8, 0x41, 0x46, + 0xf5, 0xf7, 0xde, 0xf9, 0xc9, 0xf8, 0x9c, 0x01, 0x01, 0xe0, 0xc9, 0xf8, + 0x9c, 0xb1, 0xb0, 0x68, 0x00, 0x99, 0x08, 0x43, 0xb0, 0x60, 0x2a, 0xe0, + 0x01, 0x98, 0x38, 0x43, 0x27, 0xd1, 0x06, 0x98, 0x07, 0x68, 0x79, 0x68, + 0x4f, 0xf0, 0x7e, 0x50, 0x0a, 0xeb, 0x85, 0x09, 0xf5, 0xf7, 0x54, 0xf9, + 0x09, 0xf1, 0xd4, 0x0b, 0x00, 0xf0, 0x73, 0xf8, 0x06, 0x46, 0x00, 0xf0, + 0x93, 0xf8, 0x00, 0xf0, 0x7f, 0xfc, 0xff, 0xf7, 0x1e, 0xfd, 0xcb, 0xf8, + 0x64, 0x00, 0x4f, 0xf0, 0x7e, 0x50, 0x7e, 0x68, 0x31, 0x46, 0xf5, 0xf7, + 0x41, 0xf9, 0x00, 0xf0, 0x5d, 0xf8, 0x07, 0x46, 0x00, 0xf0, 0x72, 0xfb, + 0x31, 0x46, 0xf5, 0xf7, 0x49, 0xfa, 0x00, 0xf0, 0x83, 0xf8, 0xc9, 0xf8, + 0x9c, 0x01, 0x6d, 0x1c, 0x19, 0x2d, 0xff, 0xf4, 0x40, 0xaf, 0x00, 0x20, + 0x09, 0xb0, 0xbd, 0xe8, 0xf0, 0x8f, 0xc6, 0xf8, 0x14, 0xb0, 0xc6, 0xf8, + 0x18, 0xb0, 0x06, 0x98, 0x70, 0x47, 0x07, 0x98, 0x00, 0xeb, 0x85, 0x09, + 0x09, 0xf1, 0x64, 0x01, 0x08, 0x68, 0x70, 0x61, 0x70, 0x47, 0x06, 0x98, + 0x00, 0x68, 0x40, 0x88, 0x45, 0x1c, 0x70, 0x47, 0x30, 0x6a, 0xdf, 0xf8, + 0x88, 0x18, 0xf5, 0xf7, 0x97, 0xb8, 0x00, 0x00, 0x77, 0xbe, 0x7f, 0x3f, + 0x6f, 0x12, 0x83, 0x3a, 0x80, 0x61, 0x0c, 0x4a, 0x00, 0x00, 0x80, 0xbf, + 0xac, 0xc5, 0x27, 0x37, 0x52, 0x49, 0x9d, 0x39, 0x30, 0x62, 0x00, 0x98, + 0x61, 0xe0, 0x06, 0x98, 0x80, 0x68, 0x00, 0xeb, 0x85, 0x00, 0x00, 0xf5, + 0x9c, 0x71, 0x70, 0x47, 0x06, 0x98, 0x80, 0x68, 0x00, 0xf5, 0x02, 0x71, + 0x0a, 0x68, 0x49, 0x68, 0xe9, 0x40, 0x01, 0xf0, 0x01, 0x01, 0x01, 0x91, + 0xea, 0x40, 0x61, 0x6a, 0xe9, 0x40, 0xc9, 0x07, 0x02, 0xf0, 0x01, 0x07, + 0x70, 0x47, 0x59, 0x46, 0xf5, 0xf7, 0x5e, 0xb9, 0x04, 0xeb, 0x87, 0x00, + 0x00, 0xf5, 0x34, 0x71, 0x08, 0x68, 0x49, 0x6e, 0xf5, 0xf7, 0x56, 0xb9, + 0x01, 0x46, 0xd9, 0xf8, 0x9c, 0x01, 0xf5, 0xf7, 0xed, 0xb9, 0x01, 0x46, + 0xdb, 0xf8, 0x64, 0x00, 0xf5, 0xf7, 0xe8, 0xb9, 0x01, 0x46, 0xdb, 0xf8, + 0x00, 0x00, 0xf5, 0xf7, 0xe3, 0xb9, 0xf0, 0x61, 0xa5, 0x63, 0x51, 0x46, + 0x02, 0x98, 0xf5, 0xf7, 0xdd, 0xb9, 0x01, 0x46, 0x31, 0x62, 0x06, 0x98, + 0x00, 0x68, 0x40, 0x69, 0xf5, 0xf7, 0xd6, 0xb9, 0x59, 0x46, 0xf5, 0xf7, + 0xd3, 0xb9, 0x01, 0xeb, 0x85, 0x00, 0x59, 0x46, 0xd0, 0xf8, 0xd4, 0x00, + 0xf0, 0x61, 0xe0, 0x6a, 0xf5, 0xf7, 0xca, 0xb9, 0xd8, 0xf8, 0x58, 0x02, + 0xda, 0xf8, 0x00, 0x10, 0xf5, 0xf7, 0xb4, 0xb8, 0x39, 0x46, 0xf5, 0xf7, + 0x25, 0xb9, 0x06, 0x98, 0x07, 0x68, 0x79, 0x68, 0x4f, 0xf0, 0x7e, 0x50, + 0xf5, 0xf7, 0xaa, 0xb8, 0xf0, 0x61, 0x01, 0x20, 0xa0, 0x63, 0x20, 0x6b, + 0x01, 0x46, 0xf5, 0xf7, 0xb3, 0xb9, 0x2d, 0xe9, 0xf8, 0x4f, 0x05, 0x46, + 0x05, 0xf1, 0x84, 0x06, 0xf1, 0x68, 0xff, 0xf7, 0x4e, 0xf8, 0xb1, 0x68, + 0xf5, 0xf7, 0xa8, 0xf9, 0x04, 0x46, 0x68, 0x68, 0xf5, 0xf7, 0x06, 0xf8, + 0x00, 0xf0, 0x01, 0xf9, 0x29, 0x6f, 0xf5, 0xf7, 0x03, 0xf9, 0x28, 0x67, + 0x4f, 0xf0, 0x01, 0x0b, 0x68, 0x68, 0x29, 0x68, 0x48, 0x43, 0xf4, 0xf7, + 0xf9, 0xff, 0x80, 0x46, 0xff, 0xf7, 0xc6, 0xf9, 0xb1, 0x68, 0xf5, 0xf7, + 0x91, 0xf9, 0x07, 0x46, 0x10, 0xe0, 0x40, 0x46, 0x39, 0x46, 0x05, 0xeb, + 0x8b, 0x04, 0xf5, 0xf7, 0x89, 0xf9, 0x21, 0x6f, 0xf5, 0xf7, 0xea, 0xf8, + 0x20, 0x67, 0x0b, 0xf1, 0x01, 0x0b, 0x00, 0xf0, 0x7f, 0xf8, 0x00, 0xf0, + 0x7a, 0xf8, 0x80, 0x46, 0xa8, 0x68, 0x83, 0x45, 0xeb, 0xd3, 0x68, 0x68, + 0x40, 0x43, 0xf4, 0xf7, 0xd9, 0xff, 0x83, 0x46, 0x74, 0x68, 0x00, 0xf0, + 0xd1, 0xf8, 0x00, 0xf0, 0xd0, 0xf8, 0xff, 0xf7, 0x99, 0xff, 0xe9, 0x68, + 0xf5, 0xf7, 0xd0, 0xf8, 0xe8, 0x60, 0x01, 0x24, 0x00, 0xf0, 0x66, 0xf8, + 0xff, 0xf7, 0x90, 0xff, 0x81, 0x46, 0xff, 0xf7, 0x95, 0xf9, 0x71, 0x68, + 0xf5, 0xf7, 0x60, 0xf9, 0x00, 0x90, 0xd5, 0xf8, 0x08, 0xa0, 0x19, 0xe0, + 0x00, 0x98, 0x00, 0xf0, 0x4f, 0xf8, 0x05, 0xeb, 0x84, 0x07, 0x80, 0x46, + 0xf8, 0x68, 0x41, 0x46, 0xf5, 0xf7, 0xb6, 0xf8, 0xf8, 0x60, 0x05, 0xeb, + 0x8a, 0x07, 0x41, 0x46, 0xf8, 0x68, 0xf5, 0xf7, 0xaf, 0xf8, 0xf8, 0x60, + 0x64, 0x1c, 0xa8, 0x68, 0x82, 0x44, 0x00, 0xf0, 0x43, 0xf8, 0x00, 0xf0, + 0x39, 0xf8, 0x81, 0x46, 0xd5, 0xf8, 0x08, 0x80, 0x44, 0x45, 0xe1, 0xd3, + 0x34, 0x68, 0x00, 0xf0, 0x99, 0xf8, 0x00, 0xf0, 0x98, 0xf8, 0x06, 0x46, + 0x00, 0xf0, 0x34, 0xf8, 0xff, 0xf7, 0x5e, 0xff, 0x83, 0x46, 0x4f, 0xf0, + 0x01, 0x0a, 0x16, 0xe0, 0x48, 0x46, 0x31, 0x46, 0x05, 0xeb, 0x88, 0x07, + 0xf5, 0xf7, 0x2a, 0xf9, 0xf9, 0x68, 0xf5, 0xf7, 0x8b, 0xf8, 0xf8, 0x60, + 0x08, 0xf1, 0x01, 0x08, 0x00, 0xf0, 0x20, 0xf8, 0x00, 0xf0, 0x16, 0xf8, + 0x81, 0x46, 0x64, 0x1c, 0xa8, 0x68, 0x84, 0x42, 0xea, 0xd3, 0x0a, 0xf1, + 0x01, 0x0a, 0xa8, 0x68, 0x82, 0x45, 0x09, 0xd2, 0x00, 0xf0, 0x12, 0xf8, + 0xff, 0xf7, 0x3c, 0xff, 0x83, 0x46, 0xd9, 0x46, 0x08, 0xf1, 0x01, 0x08, + 0x01, 0x24, 0xed, 0xe7, 0xbd, 0xe8, 0xf1, 0x8f, 0x49, 0x46, 0xf5, 0xf7, + 0x07, 0xb9, 0x81, 0x46, 0x78, 0x68, 0x41, 0x46, 0xf5, 0xf7, 0x02, 0xb9, + 0x28, 0x68, 0xf4, 0xf7, 0x61, 0xbf, 0x2d, 0xe9, 0xf8, 0x43, 0x80, 0x46, + 0x0d, 0x46, 0x16, 0x46, 0x99, 0x46, 0x00, 0x24, 0x00, 0x27, 0x0c, 0xe0, + 0x30, 0x46, 0xf4, 0xf7, 0x55, 0xff, 0x58, 0xf8, 0x27, 0x10, 0xf5, 0xf7, + 0xef, 0xf8, 0x21, 0x46, 0xf5, 0xf7, 0x50, 0xf8, 0x04, 0x46, 0x6e, 0x43, + 0x7f, 0x1c, 0x4f, 0x45, 0xf0, 0xd3, 0x20, 0x46, 0xbd, 0xe8, 0xf2, 0x83, + 0x2d, 0xe9, 0xf8, 0x43, 0x08, 0x9c, 0x80, 0x46, 0x0e, 0x46, 0x17, 0x46, + 0x99, 0x46, 0x00, 0x25, 0xa0, 0x07, 0x4c, 0xbf, 0x01, 0x22, 0x2a, 0x46, + 0x3b, 0x46, 0x29, 0x46, 0x30, 0x46, 0xff, 0xf7, 0xd4, 0xff, 0x48, 0xf8, + 0x25, 0x00, 0x6d, 0x1c, 0x19, 0x2d, 0xf1, 0xd3, 0xe0, 0x07, 0x4c, 0xbf, + 0x00, 0x26, 0x58, 0xf8, 0x29, 0x60, 0x4f, 0x46, 0x20, 0xe0, 0xc7, 0xf1, + 0x18, 0x00, 0xf4, 0xf7, 0x25, 0xff, 0x04, 0x46, 0xc9, 0xf1, 0x18, 0x00, + 0xf4, 0xf7, 0x20, 0xff, 0x01, 0x46, 0x20, 0x46, 0xf4, 0xf7, 0x2c, 0xff, + 0x04, 0x46, 0x58, 0xf8, 0x27, 0x00, 0x00, 0xf0, 0x14, 0xf8, 0x05, 0x46, + 0x4f, 0xf0, 0x7e, 0x50, 0x21, 0x46, 0xf4, 0xf7, 0x9f, 0xff, 0x31, 0x46, + 0xf5, 0xf7, 0xac, 0xf8, 0x29, 0x46, 0xf5, 0xf7, 0x0d, 0xf8, 0x48, 0xf8, + 0x27, 0x00, 0x7f, 0x1c, 0x19, 0x2f, 0xdc, 0xd3, 0xbd, 0xe8, 0xf1, 0x83, + 0xf0, 0x68, 0x21, 0x46, 0xf5, 0xf7, 0x9e, 0xb8, 0x2d, 0xe9, 0xf2, 0x4f, + 0x8a, 0xb0, 0x80, 0x46, 0x91, 0x46, 0x00, 0x26, 0x00, 0xe0, 0x76, 0x1c, + 0x4e, 0x45, 0x47, 0xd2, 0x00, 0x25, 0x12, 0xe0, 0x04, 0xeb, 0x0a, 0x00, + 0x00, 0xf0, 0x9a, 0xf8, 0xff, 0xf7, 0xc8, 0xfe, 0x07, 0x46, 0x64, 0x1c, + 0xac, 0x42, 0xf5, 0xd3, 0x06, 0xeb, 0x0a, 0x04, 0x58, 0xf8, 0x24, 0x00, + 0x00, 0xf0, 0x9c, 0xf8, 0x48, 0xf8, 0x24, 0x00, 0x6d, 0x1c, 0xae, 0x42, + 0x04, 0xd3, 0x00, 0x27, 0x00, 0x24, 0x05, 0xfb, 0x09, 0xfa, 0xed, 0xe7, + 0x06, 0xfb, 0x09, 0x61, 0x58, 0xf8, 0x21, 0x10, 0x4f, 0xf0, 0x7e, 0x50, + 0xf4, 0xf7, 0xe2, 0xfe, 0x05, 0x46, 0x05, 0xa8, 0x06, 0xf1, 0x01, 0x0a, + 0x40, 0xf8, 0x26, 0x50, 0x15, 0xe0, 0x04, 0xeb, 0x0b, 0x00, 0x00, 0xf0, + 0x71, 0xf8, 0xff, 0xf7, 0x9f, 0xfe, 0x07, 0x46, 0x64, 0x1c, 0xb4, 0x42, + 0xf5, 0xd3, 0x06, 0xeb, 0x0b, 0x04, 0x58, 0xf8, 0x24, 0x00, 0x00, 0xf0, + 0x73, 0xf8, 0x00, 0xf0, 0x6c, 0xf8, 0x48, 0xf8, 0x24, 0x00, 0x0a, 0xf1, + 0x01, 0x0a, 0xca, 0x45, 0xb9, 0xd2, 0x00, 0x27, 0x00, 0x24, 0x0a, 0xfb, + 0x09, 0xfb, 0xea, 0xe7, 0x0a, 0x98, 0x00, 0x68, 0x00, 0x90, 0x01, 0x25, + 0x15, 0xe0, 0x05, 0xfb, 0x09, 0x60, 0x58, 0xf8, 0x20, 0x00, 0x5d, 0xf8, + 0x26, 0x10, 0xf5, 0xf7, 0x3f, 0xf8, 0xff, 0xf7, 0x79, 0xfe, 0x07, 0x46, + 0x76, 0x1c, 0xae, 0x42, 0xf1, 0xd3, 0x0a, 0x98, 0x50, 0xf8, 0x25, 0x00, + 0x00, 0xf0, 0x4e, 0xf8, 0x4d, 0xf8, 0x25, 0x00, 0x6d, 0x1c, 0x4d, 0x45, + 0x02, 0xd2, 0x00, 0x27, 0x00, 0x26, 0xf0, 0xe7, 0x68, 0x46, 0x00, 0xeb, + 0x89, 0x00, 0xa9, 0xf1, 0x02, 0x05, 0x50, 0xf8, 0x04, 0x1c, 0x05, 0xa8, + 0x00, 0xeb, 0x89, 0x00, 0x50, 0xf8, 0x04, 0x0c, 0xf5, 0xf7, 0x1e, 0xf8, + 0x0a, 0x99, 0x01, 0xeb, 0x89, 0x01, 0x41, 0xf8, 0x04, 0x0c, 0x1b, 0xe0, + 0x0a, 0x99, 0x51, 0xf8, 0x26, 0x10, 0x05, 0xfb, 0x09, 0x60, 0x58, 0xf8, + 0x20, 0x00, 0xf5, 0xf7, 0x0f, 0xf8, 0xff, 0xf7, 0x49, 0xfe, 0x07, 0x46, + 0x76, 0x1c, 0x4e, 0x45, 0xf0, 0xd3, 0x5d, 0xf8, 0x25, 0x00, 0x00, 0xf0, + 0x1f, 0xf8, 0x05, 0xa9, 0x51, 0xf8, 0x25, 0x10, 0xf5, 0xf7, 0x00, 0xf8, + 0x0a, 0x99, 0x41, 0xf8, 0x25, 0x00, 0x6d, 0x1e, 0x00, 0x2d, 0x02, 0xd4, + 0x00, 0x27, 0x6e, 0x1c, 0xeb, 0xe7, 0x0b, 0xb0, 0xbd, 0xe8, 0xf0, 0x8f, + 0x04, 0xfb, 0x09, 0x61, 0x58, 0xf8, 0x20, 0x00, 0x58, 0xf8, 0x21, 0x10, + 0xf4, 0xf7, 0xec, 0xbf, 0x02, 0x98, 0x29, 0x46, 0xf4, 0xf7, 0xe8, 0xbf, + 0x4f, 0xf0, 0x7e, 0x50, 0x39, 0x46, 0xf4, 0xf7, 0xd3, 0xbe, 0x2d, 0xe9, + 0xf2, 0x4f, 0x04, 0x46, 0x04, 0xf5, 0x00, 0x75, 0x50, 0x08, 0x03, 0x22, + 0x59, 0x08, 0x2a, 0x60, 0x40, 0x00, 0x49, 0x00, 0x41, 0xea, 0x00, 0x02, + 0xa8, 0x60, 0x6a, 0x60, 0xe9, 0x60, 0x4f, 0xf0, 0x00, 0x09, 0x68, 0x68, + 0xc0, 0x08, 0xc0, 0x00, 0x68, 0x60, 0xa8, 0x68, 0xc0, 0x08, 0xc0, 0x00, + 0xa8, 0x60, 0xe8, 0x68, 0xc0, 0x08, 0xc0, 0x00, 0xe8, 0x60, 0x68, 0x68, + 0xc0, 0x02, 0xc0, 0x0a, 0x68, 0x60, 0xa8, 0x68, 0xc0, 0x02, 0xc0, 0x0a, + 0xa8, 0x60, 0xe8, 0x68, 0xc0, 0x02, 0xc0, 0x0a, 0xe8, 0x60, 0x18, 0x20, + 0x69, 0x68, 0xc1, 0x40, 0xc9, 0x07, 0x07, 0xd4, 0xa9, 0x68, 0xc1, 0x40, + 0xc9, 0x07, 0x03, 0xd4, 0xe9, 0x68, 0xc1, 0x40, 0xc9, 0x07, 0x01, 0xd5, + 0x81, 0x46, 0x01, 0xe0, 0x40, 0x1e, 0xef, 0xd5, 0x4f, 0xf0, 0x00, 0x0a, + 0x50, 0x46, 0xca, 0x45, 0xc8, 0xbf, 0x48, 0x46, 0x04, 0xeb, 0x80, 0x07, + 0x04, 0xeb, 0x8a, 0x08, 0x08, 0xf1, 0x04, 0x06, 0x78, 0x68, 0x30, 0x60, + 0x08, 0xf1, 0xd4, 0x0b, 0x78, 0x68, 0xcb, 0xf8, 0x00, 0x00, 0x0a, 0xf1, + 0x01, 0x0a, 0xb8, 0x6e, 0x70, 0x66, 0x21, 0x68, 0xb8, 0x6e, 0xf4, 0xf7, + 0x7d, 0xfe, 0xcb, 0xf8, 0x64, 0x00, 0xb8, 0x6e, 0x21, 0x68, 0x00, 0xf0, + 0xb1, 0xf8, 0xc8, 0xf8, 0x9c, 0x01, 0x08, 0xf5, 0x0b, 0x70, 0x31, 0x68, + 0x01, 0x60, 0xba, 0xf1, 0x19, 0x0f, 0x71, 0x6e, 0x41, 0x66, 0x20, 0x68, + 0xa8, 0x62, 0xd3, 0xdb, 0x20, 0x68, 0xa8, 0x62, 0x04, 0xf5, 0x3d, 0x70, + 0x9d, 0xf8, 0x00, 0x10, 0x00, 0xf0, 0x02, 0xf8, 0xbd, 0xe8, 0xf1, 0x8f, + 0x01, 0x70, 0x29, 0x68, 0x41, 0x60, 0x69, 0x68, 0x81, 0x60, 0xa9, 0x68, + 0xc1, 0x60, 0xe9, 0x68, 0x01, 0x61, 0x70, 0x47, 0x38, 0xb5, 0x04, 0x46, + 0x00, 0xf0, 0x89, 0xfa, 0x04, 0xf1, 0xcc, 0x01, 0x4f, 0xf0, 0x7e, 0x50, + 0x00, 0x22, 0x08, 0x60, 0x4a, 0x60, 0x00, 0x21, 0x00, 0x25, 0x04, 0xeb, + 0x81, 0x02, 0x02, 0xf1, 0xd4, 0x03, 0x49, 0x1c, 0x18, 0x60, 0xc2, 0xf8, + 0x9c, 0x51, 0x00, 0x22, 0x19, 0x29, 0x5a, 0x66, 0xf3, 0xd3, 0x04, 0xf5, + 0x00, 0x75, 0x01, 0x21, 0x29, 0x60, 0x6f, 0xf0, 0x01, 0x01, 0x69, 0x60, + 0xa9, 0x60, 0xe9, 0x60, 0x69, 0x68, 0xc9, 0x08, 0xc9, 0x00, 0x69, 0x60, + 0xa9, 0x68, 0xc9, 0x08, 0xc9, 0x00, 0xa9, 0x60, 0xe9, 0x68, 0xc9, 0x08, + 0xc9, 0x00, 0xe9, 0x60, 0x69, 0x68, 0xc9, 0x02, 0xc9, 0x0a, 0x69, 0x60, + 0xa9, 0x68, 0xc9, 0x02, 0xc9, 0x0a, 0xa9, 0x60, 0xe9, 0x68, 0xc9, 0x02, + 0xc9, 0x0a, 0xe9, 0x60, 0x2a, 0x61, 0x6a, 0x61, 0x28, 0x62, 0xaa, 0x61, + 0xea, 0x61, 0x6a, 0x62, 0x04, 0xf5, 0x0a, 0x70, 0x00, 0xf0, 0x49, 0xfa, + 0x04, 0xf5, 0x3d, 0x70, 0x00, 0x21, 0xff, 0xf7, 0xad, 0xff, 0x01, 0x21, + 0x01, 0x75, 0x31, 0xbd, 0x2d, 0xe9, 0xf8, 0x43, 0x80, 0x46, 0x08, 0xf5, + 0x00, 0x75, 0x00, 0x26, 0xa8, 0x6a, 0xc8, 0xf8, 0x00, 0x00, 0x08, 0xeb, + 0x86, 0x09, 0x09, 0xf5, 0x0b, 0x74, 0x09, 0xf1, 0x04, 0x00, 0x21, 0x68, + 0x01, 0x60, 0x09, 0xf1, 0xd4, 0x07, 0x21, 0x68, 0x39, 0x60, 0x76, 0x1c, + 0x61, 0x6e, 0x41, 0x66, 0x60, 0x6e, 0xa9, 0x6a, 0xf4, 0xf7, 0xee, 0xfd, + 0x78, 0x66, 0x60, 0x6e, 0xa9, 0x6a, 0x00, 0xf0, 0x23, 0xf8, 0x19, 0x2e, + 0xc9, 0xf8, 0x9c, 0x01, 0xe3, 0xd3, 0x08, 0xf1, 0xcc, 0x00, 0x4f, 0xf0, + 0x7e, 0x51, 0x00, 0x22, 0x01, 0x60, 0x42, 0x60, 0x08, 0xf5, 0x3e, 0x70, + 0x02, 0x68, 0x2a, 0x60, 0x42, 0x68, 0x6a, 0x60, 0x82, 0x68, 0xaa, 0x60, + 0xc0, 0x68, 0xe8, 0x60, 0x00, 0x20, 0x68, 0x61, 0x29, 0x62, 0x01, 0x20, + 0xa8, 0x61, 0x00, 0x20, 0xe8, 0x61, 0x68, 0x62, 0xbd, 0xe8, 0xf1, 0x83, + 0xd8, 0xf8, 0x58, 0x02, 0xda, 0xf8, 0x00, 0x10, 0x80, 0xf0, 0x00, 0x40, + 0xf4, 0xf7, 0xc2, 0xbd, 0x80, 0xb5, 0x01, 0x21, 0xfb, 0xf7, 0xd8, 0xff, + 0xbd, 0xe8, 0x04, 0x40, 0x74, 0x49, 0xf4, 0xf7, 0xc9, 0xbe, 0x00, 0x00, + 0x0a, 0xd7, 0x23, 0x3c, 0x2d, 0xe9, 0xfe, 0x4f, 0x04, 0x46, 0x04, 0xf1, + 0x14, 0x07, 0x07, 0xf5, 0xd0, 0x76, 0x01, 0x20, 0xb0, 0x62, 0x88, 0x46, + 0xe0, 0x68, 0x03, 0x21, 0x01, 0x62, 0x01, 0x22, 0x05, 0x21, 0x01, 0x60, + 0x20, 0x46, 0x39, 0x46, 0xfe, 0xf7, 0xe8, 0xfe, 0x30, 0x68, 0x00, 0x28, + 0x00, 0xf0, 0xc7, 0x80, 0x39, 0x46, 0x20, 0x46, 0xfe, 0xf7, 0x38, 0xfe, + 0x06, 0x46, 0x00, 0x20, 0x00, 0x90, 0x01, 0xab, 0x02, 0xaa, 0x39, 0x46, + 0x20, 0x46, 0xfe, 0xf7, 0xaf, 0xfd, 0xa0, 0x68, 0x00, 0xf5, 0x07, 0x77, + 0x3d, 0x68, 0x1d, 0xb9, 0x02, 0x98, 0x78, 0x60, 0x01, 0x98, 0x46, 0xe0, + 0x20, 0x68, 0x00, 0xf1, 0x88, 0x09, 0xd9, 0xf8, 0x0c, 0x00, 0x85, 0x42, + 0x23, 0xd2, 0x28, 0x46, 0xf4, 0xf7, 0xf0, 0xfc, 0x00, 0xf0, 0xb0, 0xf8, + 0x02, 0x99, 0xf4, 0xf7, 0xed, 0xfd, 0x81, 0x46, 0x68, 0x1c, 0xf4, 0xf7, + 0xe7, 0xfc, 0x01, 0x46, 0x48, 0x46, 0xf4, 0xf7, 0xf3, 0xfc, 0x78, 0x60, + 0x3d, 0x68, 0x28, 0x46, 0xf4, 0xf7, 0xde, 0xfc, 0xb9, 0x68, 0xf4, 0xf7, + 0x79, 0xfe, 0x01, 0x99, 0xf4, 0xf7, 0xda, 0xfd, 0x81, 0x46, 0x68, 0x1c, + 0xf4, 0xf7, 0xd4, 0xfc, 0x01, 0x46, 0x48, 0x46, 0xf4, 0xf7, 0xe0, 0xfc, + 0x1b, 0xe0, 0xd9, 0xf8, 0x08, 0x50, 0xfe, 0xf7, 0x0f, 0xfd, 0x00, 0xf0, + 0x8b, 0xf8, 0x82, 0x46, 0xff, 0xf7, 0x78, 0xfe, 0x51, 0x46, 0xf4, 0xf7, + 0xc5, 0xfd, 0x78, 0x60, 0x4f, 0xf0, 0x7e, 0x50, 0xd9, 0xf8, 0x08, 0x50, + 0xfe, 0xf7, 0x02, 0xfd, 0xb9, 0x68, 0xf4, 0xf7, 0x57, 0xfe, 0x81, 0x46, + 0x01, 0x98, 0xff, 0xf7, 0x68, 0xfe, 0xff, 0xf7, 0x13, 0xf9, 0xb8, 0x60, + 0x01, 0x2e, 0x18, 0xbf, 0x04, 0x2e, 0x07, 0xd1, 0x20, 0x68, 0xd0, 0xf8, + 0x88, 0x10, 0x34, 0x48, 0xf4, 0xf7, 0x46, 0xfe, 0x05, 0x46, 0x02, 0xe0, + 0x20, 0x68, 0xd0, 0xf8, 0x88, 0x50, 0x79, 0x68, 0x30, 0x48, 0xf4, 0xf7, + 0xa1, 0xfd, 0xd7, 0xf8, 0x08, 0x90, 0x01, 0x46, 0xf4, 0xf7, 0x38, 0xfe, + 0x83, 0x46, 0x48, 0x46, 0xff, 0xf7, 0x2a, 0xfd, 0xff, 0xf7, 0x35, 0xfc, + 0x4f, 0xf0, 0x7a, 0x5a, 0x51, 0x46, 0xf4, 0xf7, 0x2d, 0xfe, 0x81, 0x46, + 0x01, 0x20, 0x01, 0x2e, 0x18, 0xbf, 0x04, 0x2e, 0x03, 0xd1, 0x21, 0x68, + 0x88, 0x31, 0x49, 0x69, 0x02, 0xe0, 0x21, 0x68, 0x88, 0x31, 0x09, 0x69, + 0x88, 0x40, 0xf4, 0xf7, 0x75, 0xfc, 0xff, 0xf7, 0x30, 0xfe, 0x06, 0x46, + 0x02, 0x99, 0x1d, 0x48, 0xf4, 0xf7, 0x7a, 0xfd, 0x01, 0x46, 0xf4, 0xf7, + 0x13, 0xfe, 0x01, 0x99, 0x83, 0x46, 0x08, 0x46, 0xf4, 0xf7, 0x0e, 0xfe, + 0xff, 0xf7, 0x0f, 0xfc, 0x51, 0x46, 0xf4, 0xf7, 0x09, 0xfe, 0x01, 0x46, + 0x30, 0x46, 0xf4, 0xf7, 0xf3, 0xfd, 0x05, 0xd2, 0x08, 0x46, 0xff, 0xf7, + 0x2f, 0xff, 0xc8, 0xf8, 0x00, 0x00, 0x15, 0xe0, 0x21, 0x68, 0x38, 0x68, + 0x88, 0x31, 0xc9, 0x68, 0x88, 0x42, 0x03, 0xd2, 0x40, 0x1c, 0x38, 0x60, + 0x00, 0x20, 0x0c, 0xe0, 0x48, 0x46, 0xff, 0xf7, 0x1f, 0xff, 0xc8, 0xf8, + 0x00, 0x00, 0x29, 0x46, 0x48, 0x46, 0xf4, 0xf7, 0xd9, 0xfd, 0x38, 0xbf, + 0x01, 0x20, 0x00, 0xd3, 0x02, 0x20, 0xbd, 0xe8, 0xfe, 0x8f, 0x00, 0x00, + 0x00, 0x00, 0x20, 0x42, 0x00, 0x00, 0x20, 0xc1, 0x71, 0x1d, 0x9e, 0x43, + 0x00, 0x00, 0x80, 0xbf, 0x79, 0x68, 0xf4, 0xf7, 0xd9, 0xbd, 0x00, 0x00, + 0x1a, 0x48, 0x01, 0x78, 0x09, 0x06, 0x00, 0xd4, 0x70, 0x47, 0x2d, 0xe9, + 0xf0, 0x41, 0x00, 0x78, 0x17, 0x4d, 0x00, 0xf0, 0x07, 0x04, 0x68, 0x78, + 0x84, 0x42, 0x01, 0xd1, 0x28, 0x78, 0x18, 0xbb, 0x0f, 0xf2, 0x5c, 0x00, + 0x13, 0x4f, 0x50, 0xf8, 0x24, 0x80, 0x4f, 0xf6, 0xff, 0x70, 0x38, 0x80, + 0x01, 0x26, 0x30, 0x46, 0xf4, 0xf7, 0x1e, 0xfc, 0x41, 0x46, 0xf4, 0xf7, + 0xb9, 0xfd, 0x0e, 0x49, 0xf4, 0xf7, 0x28, 0xfc, 0x01, 0x46, 0x0d, 0x48, + 0xf5, 0xf7, 0x29, 0xf8, 0x4f, 0xf0, 0x8f, 0x41, 0xf4, 0xf7, 0xae, 0xfd, + 0xf4, 0xf7, 0x18, 0xfe, 0x27, 0xf8, 0x16, 0x00, 0x76, 0x1c, 0x40, 0x2e, + 0xe7, 0xd3, 0x01, 0x20, 0x6c, 0x70, 0x28, 0x70, 0xbd, 0xe8, 0xf0, 0x81, + 0x13, 0x07, 0x00, 0x46, 0x96, 0xf3, 0x00, 0x20, 0x30, 0xf0, 0x00, 0x20, + 0x00, 0x00, 0xa0, 0x41, 0x00, 0x00, 0x20, 0x41, 0x00, 0x00, 0x80, 0xbe, + 0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x80, 0xbf, 0x00, 0x00, 0x00, 0xc0, + 0x00, 0x00, 0x40, 0xc0, 0x00, 0x00, 0x80, 0xc0, 0x00, 0x00, 0xa0, 0xc0, + 0x00, 0x00, 0xc0, 0xc0, 0x80, 0xb5, 0x4f, 0xf0, 0x9e, 0x41, 0xf4, 0xf7, + 0x8b, 0xfe, 0x02, 0xd8, 0x6f, 0xf0, 0x00, 0x40, 0x02, 0xbd, 0x4d, 0x49, + 0xf4, 0xf7, 0x6a, 0xfd, 0x24, 0xbf, 0xbd, 0xe8, 0x02, 0x40, 0xf4, 0xf7, + 0xe3, 0xbd, 0x4f, 0xf0, 0x00, 0x40, 0x02, 0xbd, 0x38, 0xb5, 0x0c, 0x46, + 0xf4, 0xf7, 0xd2, 0xfb, 0x46, 0x49, 0xf4, 0xf7, 0x6d, 0xfd, 0x05, 0x46, + 0x20, 0x46, 0xf4, 0xf7, 0xcb, 0xfb, 0x01, 0x46, 0x28, 0x46, 0xf4, 0xf7, + 0xd7, 0xfb, 0x4f, 0xf0, 0x7e, 0x51, 0xf4, 0xf7, 0xc5, 0xfc, 0xbd, 0xe8, + 0x32, 0x40, 0xfb, 0xf7, 0x5d, 0xbc, 0x2d, 0xe9, 0xfe, 0x4f, 0x04, 0x46, + 0x0f, 0x46, 0x25, 0x68, 0x4f, 0xf0, 0x7c, 0x50, 0x29, 0x46, 0xf4, 0xf7, + 0x53, 0xfd, 0x29, 0x46, 0xf4, 0xf7, 0x50, 0xfd, 0x00, 0xf0, 0x70, 0xf8, + 0x81, 0x46, 0x28, 0x46, 0x49, 0x46, 0xf4, 0xf7, 0xbb, 0xfb, 0x4f, 0xf0, + 0x9d, 0x4b, 0x59, 0x46, 0xf4, 0xf7, 0x44, 0xfd, 0xff, 0xf7, 0xba, 0xff, + 0x38, 0x60, 0x4f, 0xf0, 0x7e, 0x58, 0x38, 0x1d, 0x00, 0x90, 0x68, 0x37, + 0x00, 0x25, 0xdf, 0xf8, 0xb4, 0xa0, 0x04, 0xeb, 0x85, 0x06, 0x4f, 0xf0, + 0x7c, 0x51, 0xb0, 0x6e, 0xf4, 0xf7, 0x32, 0xfd, 0xb1, 0x6e, 0xf4, 0xf7, + 0x2f, 0xfd, 0x00, 0xf0, 0x4f, 0xf8, 0x71, 0x68, 0xf4, 0xf7, 0x9c, 0xfb, + 0x59, 0x46, 0xf4, 0xf7, 0x27, 0xfd, 0x49, 0x46, 0xf4, 0xf7, 0x96, 0xfb, + 0x41, 0x46, 0xf4, 0xf7, 0x21, 0xfd, 0xff, 0xf7, 0x97, 0xff, 0x00, 0x99, + 0x41, 0xf8, 0x25, 0x00, 0x51, 0x46, 0xb0, 0x6e, 0xf4, 0xf7, 0x18, 0xfd, + 0x71, 0x68, 0xf4, 0xf7, 0x87, 0xfb, 0x59, 0x46, 0xf4, 0xf7, 0x12, 0xfd, + 0x49, 0x46, 0xf4, 0xf7, 0x81, 0xfb, 0x41, 0x46, 0xf4, 0xf7, 0x0c, 0xfd, + 0xff, 0xf7, 0x82, 0xff, 0x47, 0xf8, 0x25, 0x00, 0x51, 0x46, 0x40, 0x46, + 0xf4, 0xf7, 0x04, 0xfd, 0x6d, 0x1c, 0x18, 0x2d, 0x80, 0x46, 0xc6, 0xdb, + 0x60, 0x6e, 0x49, 0x46, 0xf4, 0xf7, 0xfc, 0xfc, 0x01, 0x46, 0x58, 0x46, + 0xf4, 0xf7, 0x6a, 0xfb, 0xff, 0xf7, 0x6e, 0xff, 0x00, 0x99, 0x08, 0x66, + 0x00, 0x20, 0x38, 0x66, 0x02, 0x98, 0x00, 0x68, 0x30, 0xb9, 0x01, 0x99, + 0x00, 0x98, 0x03, 0xb0, 0xbd, 0xe8, 0xf0, 0x4f, 0x00, 0xf0, 0x42, 0xb9, + 0xbd, 0xe8, 0xf7, 0x8f, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xce, + 0x00, 0x00, 0xc0, 0x41, 0x00, 0x00, 0x80, 0xbf, 0x01, 0x46, 0x4f, 0xf0, + 0x7e, 0x50, 0xf4, 0xf7, 0xc9, 0xbb, 0x00, 0x21, 0x01, 0x60, 0x00, 0xeb, + 0x81, 0x02, 0x4f, 0xf0, 0x7e, 0x53, 0x53, 0x60, 0x49, 0x1c, 0x00, 0x23, + 0x19, 0x29, 0x93, 0x66, 0xf5, 0xd3, 0x70, 0x47, 0xf8, 0xb5, 0x0f, 0x46, + 0xd7, 0xf8, 0x00, 0xe0, 0xd7, 0xf8, 0x04, 0xc0, 0x06, 0x46, 0x82, 0xfb, + 0x0e, 0x45, 0x83, 0xfb, 0x0c, 0x01, 0x20, 0x1a, 0x65, 0xeb, 0x01, 0x01, + 0x82, 0xfb, 0x0c, 0x45, 0xc3, 0xfb, 0x0e, 0x45, 0x32, 0x68, 0x73, 0x68, + 0xc0, 0x0d, 0x40, 0xea, 0x41, 0x20, 0x81, 0x18, 0x31, 0x60, 0xe4, 0x0d, + 0x44, 0xea, 0x45, 0x24, 0xe1, 0x18, 0x71, 0x60, 0x10, 0x1a, 0x38, 0x60, + 0x18, 0x1b, 0x78, 0x60, 0xf1, 0xbd, 0x10, 0xb5, 0x04, 0x46, 0x00, 0xf0, + 0x5b, 0xf8, 0x04, 0xf1, 0x08, 0x01, 0xff, 0xf7, 0xd5, 0xff, 0x00, 0xf0, + 0x55, 0xf8, 0x04, 0xf1, 0x18, 0x01, 0x04, 0xf1, 0x10, 0x00, 0xff, 0xf7, + 0xcd, 0xff, 0x00, 0xf0, 0x4d, 0xf8, 0x04, 0xf1, 0x10, 0x01, 0x20, 0x46, + 0xff, 0xf7, 0xc6, 0xff, 0x04, 0xf1, 0x18, 0x01, 0x04, 0xf1, 0x08, 0x00, + 0xbd, 0xe8, 0x10, 0x40, 0x4f, 0xf4, 0x00, 0x03, 0x00, 0x22, 0xbb, 0xe7, + 0x30, 0xb5, 0x85, 0xb0, 0x04, 0x46, 0x0d, 0x46, 0x68, 0x46, 0x0f, 0xf2, + 0x1c, 0x31, 0x10, 0x22, 0xf7, 0xf7, 0xf8, 0xfb, 0x00, 0x20, 0x10, 0xf8, + 0x0d, 0x10, 0x54, 0xf8, 0x21, 0x10, 0x45, 0xf8, 0x20, 0x10, 0x40, 0x1c, + 0x10, 0x28, 0xf6, 0xd3, 0x28, 0x46, 0xff, 0xf7, 0xc8, 0xff, 0x05, 0xf1, + 0x20, 0x00, 0xff, 0xf7, 0xc4, 0xff, 0x00, 0xf0, 0x21, 0xf8, 0x05, 0xf1, + 0x20, 0x01, 0x28, 0x46, 0xff, 0xf7, 0x9a, 0xff, 0xb1, 0x4c, 0x23, 0x46, + 0x22, 0x46, 0x05, 0xf1, 0x28, 0x01, 0x05, 0xf1, 0x08, 0x00, 0xff, 0xf7, + 0x91, 0xff, 0x4f, 0xf4, 0x00, 0x03, 0x00, 0x22, 0x05, 0xf1, 0x30, 0x01, + 0x05, 0xf1, 0x10, 0x00, 0xff, 0xf7, 0x88, 0xff, 0x23, 0x46, 0xa9, 0x4a, + 0x05, 0xf1, 0x38, 0x01, 0x05, 0xf1, 0x18, 0x00, 0xff, 0xf7, 0x80, 0xff, + 0x05, 0xb0, 0x30, 0xbd, 0x00, 0x23, 0x4f, 0xf4, 0x00, 0x02, 0x70, 0x47, + 0x2d, 0xe9, 0xf3, 0x43, 0x87, 0xb0, 0xff, 0xf7, 0xb9, 0xff, 0x08, 0x98, + 0x00, 0xf1, 0x40, 0x01, 0x07, 0x98, 0x08, 0x30, 0xff, 0xf7, 0xb2, 0xff, + 0x08, 0x98, 0x00, 0xf1, 0x80, 0x01, 0x07, 0x98, 0x10, 0x30, 0xff, 0xf7, + 0xab, 0xff, 0x00, 0x22, 0x08, 0x98, 0x07, 0x99, 0x50, 0xf8, 0x22, 0x00, + 0x41, 0xf8, 0x22, 0x00, 0x52, 0x1c, 0x30, 0x2a, 0xf6, 0xd3, 0x03, 0x20, + 0x4f, 0xf4, 0x00, 0x0e, 0x4f, 0xf0, 0x00, 0x08, 0x00, 0x27, 0x02, 0x90, + 0x00, 0x22, 0x07, 0x98, 0x50, 0xf8, 0x22, 0xc0, 0x00, 0xeb, 0x82, 0x01, + 0x08, 0x1d, 0x03, 0x68, 0xc4, 0x6b, 0x05, 0x6c, 0xc6, 0x6f, 0x01, 0x96, + 0xd1, 0xf8, 0x84, 0x10, 0x00, 0x91, 0x2f, 0xb9, 0x01, 0x98, 0x00, 0x19, + 0x00, 0xeb, 0x0c, 0x06, 0x48, 0x19, 0x52, 0xe0, 0x86, 0x48, 0x80, 0xfb, + 0x0e, 0x01, 0xcd, 0xe9, 0x04, 0x01, 0x85, 0x48, 0x80, 0xfb, 0x0e, 0x69, + 0x82, 0x48, 0x80, 0xfb, 0x08, 0x01, 0x30, 0x1a, 0x69, 0xeb, 0x01, 0x01, + 0xc0, 0x0d, 0x40, 0xea, 0x41, 0x2e, 0xdd, 0xe9, 0x04, 0x01, 0x7e, 0x4e, + 0xc6, 0xfb, 0x08, 0x01, 0xc0, 0x0d, 0x40, 0xea, 0x41, 0x28, 0x84, 0xfb, + 0x0e, 0x69, 0x85, 0xfb, 0x08, 0x01, 0x30, 0x1a, 0x69, 0xeb, 0x01, 0x01, + 0xc0, 0x0d, 0x40, 0xea, 0x41, 0x20, 0x84, 0x44, 0x85, 0xfb, 0x0e, 0x01, + 0xc4, 0xfb, 0x08, 0x01, 0xc0, 0x0d, 0x40, 0xea, 0x41, 0x20, 0xc3, 0x18, + 0x8e, 0xfb, 0x0e, 0x45, 0x88, 0xfb, 0x08, 0x01, 0x20, 0x1a, 0x65, 0xeb, + 0x01, 0x01, 0xc0, 0x0d, 0x40, 0xea, 0x41, 0x24, 0x88, 0xfb, 0x0e, 0x01, + 0x80, 0x0d, 0x40, 0xea, 0x81, 0x25, 0x01, 0x98, 0x80, 0xfb, 0x04, 0x69, + 0x00, 0x98, 0x80, 0xfb, 0x05, 0x01, 0x30, 0x1a, 0x69, 0xeb, 0x01, 0x01, + 0xc0, 0x0d, 0x40, 0xea, 0x41, 0x20, 0x00, 0xeb, 0x0c, 0x06, 0x00, 0x98, + 0xdd, 0xf8, 0x04, 0x90, 0x80, 0xfb, 0x04, 0x01, 0xc9, 0xfb, 0x05, 0x01, + 0xc0, 0x0d, 0x40, 0xea, 0x41, 0x20, 0x08, 0x99, 0x41, 0xf8, 0x27, 0x60, + 0x92, 0x1c, 0x08, 0x99, 0x01, 0xeb, 0x87, 0x01, 0xbf, 0x1c, 0xc0, 0x18, + 0x10, 0x2a, 0x48, 0x60, 0x8b, 0xd3, 0x02, 0x98, 0x40, 0x1e, 0x02, 0x90, + 0x86, 0xd1, 0x09, 0xb0, 0xbd, 0xe8, 0xf0, 0x83, 0x2d, 0xe9, 0xf3, 0x4f, + 0x87, 0xb0, 0x4f, 0xf4, 0x00, 0x02, 0x4f, 0xf0, 0x00, 0x0e, 0x00, 0x23, + 0x07, 0x98, 0x4f, 0xea, 0xee, 0x79, 0xde, 0xf5, 0x00, 0x0a, 0x50, 0xf8, + 0x23, 0x00, 0x69, 0xeb, 0x49, 0x07, 0xc1, 0x17, 0xaa, 0xfb, 0x00, 0x45, + 0x0a, 0xfb, 0x01, 0x55, 0x07, 0xfb, 0x00, 0x55, 0xcd, 0xe9, 0x04, 0x45, + 0x07, 0x99, 0x03, 0xf1, 0x19, 0x06, 0x51, 0xf8, 0x26, 0x60, 0x04, 0x46, + 0x50, 0x46, 0x39, 0x46, 0xf5, 0x17, 0xa0, 0xfb, 0x06, 0xa7, 0x00, 0xfb, + 0x05, 0x77, 0x1e, 0xf5, 0x00, 0x00, 0x01, 0xfb, 0x06, 0x77, 0x49, 0xf1, + 0x00, 0x01, 0xcd, 0xe9, 0x02, 0x01, 0xc2, 0xfb, 0x04, 0xa7, 0x07, 0x98, + 0x59, 0x42, 0x00, 0xeb, 0x81, 0x00, 0x50, 0xf8, 0x60, 0xcf, 0x40, 0x6e, + 0xcc, 0xf1, 0x00, 0x01, 0xdd, 0xe9, 0x02, 0x45, 0xc2, 0xfb, 0x01, 0xa7, + 0x40, 0x42, 0xd0, 0x46, 0xb9, 0x46, 0xc1, 0x17, 0xa4, 0xfb, 0x00, 0xa7, + 0x04, 0xfb, 0x01, 0x77, 0x05, 0xfb, 0x00, 0x77, 0x4d, 0x46, 0x18, 0xeb, + 0x0a, 0x04, 0x7d, 0x41, 0xdd, 0xe9, 0x04, 0xa7, 0x71, 0x42, 0xc2, 0xfb, + 0x01, 0xa7, 0xcd, 0xe9, 0x00, 0xa7, 0x4f, 0xea, 0xec, 0x71, 0xdd, 0xe9, + 0x02, 0xa7, 0xaa, 0xfb, 0x0c, 0x6b, 0x0a, 0xfb, 0x01, 0xbb, 0x07, 0xfb, + 0x0c, 0xbb, 0xdd, 0xe9, 0x00, 0x17, 0x11, 0xeb, 0x06, 0x0a, 0x47, 0xeb, + 0x0b, 0x07, 0xc2, 0xfb, 0x00, 0xa7, 0x4f, 0xea, 0xda, 0x50, 0x40, 0xea, + 0x47, 0x21, 0x21, 0x48, 0xff, 0x15, 0xa0, 0xfb, 0x01, 0x89, 0x00, 0xfb, + 0x07, 0x99, 0x4f, 0xea, 0xd8, 0x50, 0x40, 0xea, 0x49, 0x21, 0x08, 0x98, + 0xdf, 0xf8, 0x6c, 0xa0, 0x40, 0xf8, 0x33, 0x10, 0xe4, 0x0d, 0x44, 0xea, + 0x45, 0x24, 0xed, 0x15, 0xaa, 0xfb, 0x04, 0x01, 0x0a, 0xfb, 0x05, 0x11, + 0xc0, 0x0d, 0x40, 0xea, 0x41, 0x20, 0x08, 0x99, 0x01, 0xeb, 0xc3, 0x01, + 0x5b, 0x1c, 0x48, 0x60, 0x12, 0x49, 0x13, 0x48, 0x81, 0xfb, 0x02, 0x45, + 0xc0, 0xfb, 0x0e, 0x45, 0x06, 0x46, 0xce, 0xf1, 0x00, 0x00, 0x81, 0xfb, + 0x00, 0x01, 0xc6, 0xfb, 0x02, 0x01, 0xc0, 0x0d, 0xe4, 0x0d, 0x18, 0x2b, + 0x40, 0xea, 0x41, 0x22, 0x44, 0xea, 0x45, 0x2e, 0xff, 0xf4, 0x6a, 0xaf, + 0x07, 0x99, 0x08, 0x98, 0x09, 0xb0, 0xbd, 0xe8, 0xf0, 0x4f, 0xbb, 0xe6, + 0x7a, 0x82, 0x5a, 0x00, 0x86, 0x7d, 0xa5, 0xff, 0xfc, 0x20, 0x21, 0x00, + 0x75, 0xa3, 0x7b, 0x00, 0xab, 0xaa, 0x02, 0x00, 0x15, 0xb5, 0x10, 0x00, + 0xaa, 0xe7, 0x7e, 0x00, 0x00, 0x01, 0x18, 0x19, 0x0c, 0x0d, 0x24, 0x25, + 0x06, 0x07, 0x1e, 0x1f, 0x12, 0x13, 0x2a, 0x2b, 0x2d, 0xe9, 0xf0, 0x4f, + 0x04, 0x46, 0x8b, 0xb0, 0x00, 0x20, 0x20, 0x77, 0x04, 0xf1, 0x1d, 0x05, + 0x60, 0x69, 0x00, 0xf1, 0x68, 0x01, 0x00, 0x1d, 0x07, 0x90, 0x06, 0x91, + 0x04, 0xf5, 0xe8, 0x70, 0x02, 0x90, 0x04, 0xf5, 0x24, 0x70, 0x01, 0x90, + 0x04, 0xf1, 0x50, 0x00, 0x0a, 0x90, 0x01, 0x20, 0xa1, 0x68, 0x46, 0x42, + 0x01, 0xeb, 0x80, 0x02, 0x01, 0xeb, 0x86, 0x01, 0x13, 0x6e, 0xd1, 0xf8, + 0xc0, 0x60, 0x16, 0x66, 0xc1, 0xf8, 0xc0, 0x30, 0x40, 0x1c, 0xd2, 0xf8, + 0x20, 0x31, 0xd1, 0xf8, 0x80, 0x61, 0xc2, 0xf8, 0x20, 0x61, 0x0c, 0x28, + 0xc1, 0xf8, 0x80, 0x31, 0xe8, 0xdb, 0x00, 0x20, 0x28, 0x70, 0x01, 0x26, + 0x02, 0x99, 0x08, 0x60, 0x4f, 0xf0, 0x42, 0x58, 0x01, 0x99, 0x08, 0x60, + 0x20, 0x69, 0xf0, 0x40, 0x00, 0xf0, 0x01, 0x00, 0x70, 0x55, 0xa7, 0x68, + 0x57, 0xf8, 0x26, 0x00, 0xf4, 0xf7, 0x02, 0xf9, 0x00, 0xf0, 0x42, 0xfa, + 0x02, 0x99, 0x41, 0xf8, 0x26, 0x00, 0x07, 0xeb, 0x86, 0x00, 0xd0, 0xf8, + 0xc0, 0x00, 0xf4, 0xf7, 0xf7, 0xf8, 0x00, 0xf0, 0x37, 0xfa, 0x01, 0x99, + 0x41, 0xf8, 0x26, 0x00, 0xa9, 0x1b, 0xe0, 0x68, 0xf0, 0x40, 0x00, 0xf0, + 0x01, 0x00, 0x81, 0xf8, 0x30, 0x00, 0xa0, 0x68, 0x00, 0xeb, 0x86, 0x07, + 0x38, 0x6e, 0xf4, 0xf7, 0xe5, 0xf8, 0x00, 0xf0, 0x25, 0xfa, 0x02, 0x99, + 0x01, 0xeb, 0x86, 0x01, 0x08, 0x66, 0xd7, 0xf8, 0x20, 0x01, 0xf4, 0xf7, + 0xdb, 0xf8, 0x00, 0xf0, 0x1b, 0xfa, 0x01, 0x99, 0x01, 0xeb, 0x86, 0x01, + 0x76, 0x1c, 0x18, 0x2e, 0x08, 0x66, 0xc5, 0xdb, 0x01, 0x22, 0xdf, 0xf8, + 0x00, 0x08, 0x01, 0x46, 0x40, 0x08, 0x49, 0x08, 0xc3, 0x07, 0x5c, 0xbf, + 0x00, 0x23, 0x53, 0x55, 0xcb, 0x07, 0x03, 0xd4, 0xae, 0x1a, 0x00, 0x23, + 0x86, 0xf8, 0x30, 0x30, 0x52, 0x1c, 0x18, 0x2a, 0xf0, 0xdb, 0x00, 0x27, + 0x03, 0xe0, 0x00, 0x2f, 0x18, 0xbf, 0x18, 0x2f, 0x02, 0xd1, 0x4f, 0xf0, + 0xff, 0x39, 0x65, 0xe0, 0x78, 0x5d, 0x00, 0x28, 0x62, 0xd0, 0x01, 0x98, + 0x50, 0xf8, 0x27, 0xa0, 0x02, 0x98, 0x50, 0xf8, 0x27, 0xb0, 0x58, 0x46, + 0x59, 0x46, 0xf4, 0xf7, 0x51, 0xfa, 0x00, 0x90, 0x51, 0x46, 0x50, 0x46, + 0xf4, 0xf7, 0x4c, 0xfa, 0x00, 0x99, 0xf4, 0xf7, 0xad, 0xf9, 0xb9, 0xf1, + 0x00, 0x0f, 0x0e, 0xd5, 0x06, 0x46, 0x58, 0x46, 0x00, 0x21, 0xf4, 0xf7, + 0x21, 0xfa, 0xb9, 0x46, 0x08, 0xbf, 0x88, 0x46, 0x44, 0xd0, 0x50, 0x46, + 0x59, 0x46, 0xf4, 0xf7, 0xab, 0xf8, 0x80, 0x46, 0x3e, 0xe0, 0x00, 0x90, + 0x00, 0x21, 0x58, 0x46, 0xf4, 0xf7, 0x12, 0xfa, 0x08, 0xbf, 0x8a, 0x46, + 0x04, 0xd0, 0x50, 0x46, 0x59, 0x46, 0xf4, 0xf7, 0x9d, 0xf8, 0x82, 0x46, + 0x00, 0x98, 0x31, 0x46, 0xf4, 0xf7, 0x98, 0xf8, 0xf4, 0xf7, 0xca, 0xf9, + 0xdf, 0xf8, 0x58, 0x17, 0xf4, 0xf7, 0x84, 0xf9, 0x06, 0x46, 0x50, 0x46, + 0x41, 0x46, 0xf4, 0xf7, 0x0b, 0xf9, 0x80, 0x46, 0x30, 0x46, 0x31, 0x46, + 0xf4, 0xf7, 0x16, 0xfa, 0x06, 0x46, 0x40, 0x46, 0x00, 0xf0, 0xac, 0xf9, + 0x31, 0x46, 0xf4, 0xf7, 0x73, 0xf9, 0xa7, 0xeb, 0x09, 0x0b, 0x06, 0x46, + 0x0b, 0xfb, 0x0b, 0xf0, 0xf4, 0xf7, 0x60, 0xf8, 0x01, 0x46, 0x30, 0x46, + 0xf4, 0xf7, 0x76, 0xf8, 0xdf, 0xf8, 0x1c, 0x17, 0xf4, 0xf7, 0x08, 0xfb, + 0x03, 0xd8, 0x00, 0x20, 0x09, 0xf8, 0x05, 0x00, 0x78, 0x55, 0xb9, 0x46, + 0x00, 0x9e, 0xd0, 0x46, 0x7f, 0x1c, 0x30, 0x2f, 0x8f, 0xdb, 0x00, 0x20, + 0x00, 0x21, 0x4a, 0x5d, 0x01, 0x2a, 0x08, 0xbf, 0x40, 0x1c, 0x49, 0x1c, + 0x30, 0x29, 0xf8, 0xdb, 0xa1, 0x69, 0x89, 0x78, 0x88, 0x42, 0x03, 0xd2, + 0x20, 0x7f, 0x40, 0xf0, 0x02, 0x00, 0x20, 0x77, 0x00, 0x26, 0x00, 0x20, + 0x02, 0x21, 0x4a, 0x5d, 0x00, 0x2a, 0x1e, 0xbf, 0x6a, 0x1a, 0x92, 0xf8, + 0x30, 0x20, 0x00, 0x2a, 0x02, 0xd0, 0x01, 0x22, 0x8a, 0x40, 0x10, 0x43, + 0x49, 0x1c, 0x18, 0x29, 0xf1, 0xdb, 0x00, 0x21, 0x4f, 0xf4, 0x80, 0x72, + 0x80, 0x23, 0x4f, 0xf0, 0x17, 0x08, 0x18, 0x42, 0x1c, 0xbf, 0x1e, 0x43, + 0x49, 0x1c, 0x0c, 0x29, 0x07, 0xd0, 0x10, 0x42, 0x03, 0xd0, 0x16, 0x43, + 0x49, 0x1c, 0x0c, 0x29, 0x01, 0xd0, 0x5b, 0x10, 0x52, 0x00, 0xb8, 0xf1, + 0x01, 0x08, 0xee, 0xd1, 0x04, 0x29, 0x07, 0xda, 0x68, 0x78, 0x00, 0x28, + 0x1e, 0xbf, 0x95, 0xf8, 0x2f, 0x00, 0x00, 0x28, 0x46, 0xf0, 0x01, 0x06, + 0x00, 0x27, 0x4f, 0xf0, 0x01, 0x09, 0x19, 0xf8, 0x05, 0x00, 0x00, 0x28, + 0x1e, 0xbf, 0xa5, 0xeb, 0x09, 0x00, 0x90, 0xf8, 0x30, 0x00, 0x00, 0x28, + 0xc9, 0xf1, 0x30, 0x0a, 0x00, 0xf0, 0x93, 0x80, 0x01, 0x98, 0x02, 0x99, + 0x50, 0xf8, 0x29, 0x00, 0x51, 0xf8, 0x29, 0x10, 0xf4, 0xf7, 0x0c, 0xf8, + 0x00, 0x90, 0x02, 0x99, 0x01, 0x98, 0x51, 0xf8, 0x2a, 0x10, 0x50, 0xf8, + 0x2a, 0x00, 0xf4, 0xf7, 0x03, 0xf8, 0x83, 0x46, 0x4f, 0xf4, 0x80, 0x10, + 0x05, 0x90, 0x4f, 0xf0, 0x93, 0x40, 0x00, 0x99, 0xf4, 0xf7, 0x88, 0xf9, + 0xf4, 0xf7, 0xf2, 0xf9, 0x00, 0xf0, 0x14, 0xf9, 0x00, 0xf0, 0x1f, 0xf9, + 0x00, 0xf0, 0x20, 0xf9, 0x00, 0xf0, 0x22, 0xf9, 0x09, 0x90, 0x59, 0x46, + 0x00, 0xf0, 0x03, 0xf9, 0xf4, 0xf7, 0xe4, 0xf9, 0x00, 0xf0, 0x06, 0xf9, + 0x00, 0xf0, 0x11, 0xf9, 0x00, 0xf0, 0x12, 0xf9, 0x00, 0xf0, 0x14, 0xf9, + 0x08, 0x90, 0x01, 0x98, 0x50, 0xf8, 0x29, 0xb0, 0x02, 0x98, 0x50, 0xf8, + 0x29, 0x10, 0x08, 0x46, 0xf4, 0xf7, 0x66, 0xf9, 0x00, 0x90, 0x59, 0x46, + 0x58, 0x46, 0xf4, 0xf7, 0x61, 0xf9, 0x00, 0x99, 0xf4, 0xf7, 0xc2, 0xf8, + 0x00, 0x90, 0x01, 0x98, 0x50, 0xf8, 0x2a, 0xb0, 0x02, 0x98, 0x50, 0xf8, + 0x2a, 0x10, 0x08, 0x46, 0xf4, 0xf7, 0x54, 0xf9, 0x82, 0x46, 0x58, 0x46, + 0x59, 0x46, 0xf4, 0xf7, 0x4f, 0xf9, 0x51, 0x46, 0xf4, 0xf7, 0xb0, 0xf8, + 0x82, 0x46, 0x00, 0x98, 0xf4, 0xf7, 0xee, 0xf8, 0x50, 0x46, 0xf4, 0xf7, + 0xeb, 0xf8, 0x08, 0x98, 0x09, 0x99, 0xf4, 0xf7, 0x31, 0xf8, 0x4f, 0xf0, + 0x7c, 0x51, 0xf4, 0xf7, 0x3d, 0xf9, 0x06, 0x99, 0x41, 0xf8, 0x29, 0x00, + 0x51, 0x46, 0x00, 0x98, 0xf4, 0xf7, 0x36, 0xf9, 0xf4, 0xf7, 0xda, 0xf8, + 0xf4, 0xf7, 0xd8, 0xf8, 0x83, 0x46, 0x00, 0x98, 0xf4, 0xf7, 0xd4, 0xf8, + 0x50, 0x46, 0xf4, 0xf7, 0xd1, 0xf8, 0x07, 0x98, 0x40, 0xf8, 0x29, 0xb0, + 0x08, 0x99, 0x09, 0x98, 0xf4, 0xf7, 0x88, 0xf8, 0x4f, 0xf0, 0x7c, 0x51, + 0xf4, 0xf7, 0x20, 0xf9, 0x0a, 0x99, 0x41, 0xf8, 0x29, 0x00, 0x26, 0xfa, + 0x09, 0xf1, 0xc9, 0x07, 0x09, 0xd5, 0x41, 0x46, 0xf4, 0xf7, 0x7a, 0xf8, + 0x80, 0x46, 0x4f, 0xf0, 0x7e, 0x50, 0x39, 0x46, 0xf4, 0xf7, 0x74, 0xf8, + 0x07, 0x46, 0x09, 0xf1, 0x01, 0x09, 0xb9, 0xf1, 0x18, 0x0f, 0xff, 0xf6, + 0x5a, 0xaf, 0x38, 0x46, 0x00, 0x21, 0xf4, 0xf7, 0xe5, 0xf8, 0x08, 0xbf, + 0x00, 0x26, 0x04, 0xd0, 0x40, 0x46, 0x39, 0x46, 0xf3, 0xf7, 0x70, 0xff, + 0x06, 0x46, 0x60, 0x69, 0x06, 0x60, 0x4f, 0xf0, 0x01, 0x08, 0xc8, 0xf1, + 0x30, 0x0a, 0x18, 0xf8, 0x05, 0x00, 0x1a, 0xf8, 0x05, 0x10, 0x00, 0x28, + 0x02, 0xd0, 0x00, 0x29, 0x4d, 0xd1, 0x01, 0xe0, 0x00, 0x29, 0x4a, 0xd0, + 0x40, 0xb1, 0x02, 0x98, 0x50, 0xf8, 0x28, 0x70, 0x01, 0x98, 0x50, 0xf8, + 0x28, 0x00, 0x80, 0xf0, 0x00, 0x49, 0x07, 0xe0, 0x08, 0x00, 0x05, 0xd0, + 0x02, 0x98, 0x50, 0xf8, 0x2a, 0x70, 0x01, 0x98, 0x50, 0xf8, 0x2a, 0x90, + 0x48, 0x46, 0x39, 0x46, 0xf3, 0xf7, 0x48, 0xff, 0x01, 0x46, 0x06, 0x98, + 0x40, 0xf8, 0x28, 0x10, 0x00, 0xf0, 0x59, 0xf8, 0xf4, 0xf7, 0x3a, 0xf9, + 0x00, 0xf0, 0x5c, 0xf8, 0x00, 0xf0, 0x67, 0xf8, 0x00, 0xf0, 0x68, 0xf8, + 0x00, 0xf0, 0x6a, 0xf8, 0x01, 0x46, 0x06, 0x98, 0x40, 0xf8, 0x28, 0x10, + 0x18, 0xf8, 0x05, 0x00, 0x18, 0xb1, 0x30, 0x46, 0xf4, 0xf7, 0x20, 0xf8, + 0x06, 0xe0, 0x1a, 0xf8, 0x05, 0x00, 0x30, 0xb1, 0x08, 0x46, 0x31, 0x46, + 0xf3, 0xf7, 0xa4, 0xff, 0x06, 0x99, 0x41, 0xf8, 0x28, 0x00, 0x38, 0x46, + 0x00, 0xf0, 0x45, 0xf8, 0x82, 0x46, 0x48, 0x46, 0x49, 0x46, 0xf4, 0xf7, + 0xa9, 0xf8, 0x51, 0x46, 0xf4, 0xf7, 0x0a, 0xf8, 0xf4, 0xf7, 0x4a, 0xf8, + 0x07, 0x99, 0x41, 0xf8, 0x28, 0x00, 0x08, 0xf1, 0x01, 0x08, 0xb8, 0xf1, + 0x18, 0x0f, 0xa2, 0xdb, 0xa0, 0x69, 0x01, 0x90, 0x04, 0xf5, 0x88, 0x73, + 0x04, 0xf5, 0x54, 0x70, 0x00, 0x90, 0x04, 0xf1, 0x50, 0x02, 0x60, 0x69, + 0x04, 0xf1, 0x1d, 0x01, 0x00, 0xf0, 0x36, 0xf8, 0x00, 0x24, 0x07, 0x98, + 0x50, 0xf8, 0x24, 0x20, 0x10, 0x46, 0x00, 0x21, 0xf4, 0xf7, 0x66, 0xf8, + 0x4f, 0xf0, 0x7e, 0x50, 0x1c, 0xbf, 0x11, 0x46, 0xf3, 0xf7, 0xf2, 0xfe, + 0x07, 0x99, 0x41, 0xf8, 0x24, 0x00, 0x64, 0x1c, 0x19, 0x2c, 0xec, 0xdb, + 0x0b, 0xb0, 0xbd, 0xe8, 0xf0, 0x8f, 0x4f, 0xf4, 0x80, 0x10, 0x05, 0x90, + 0x4f, 0xf0, 0x93, 0x40, 0xf4, 0xf7, 0x70, 0xb8, 0x04, 0x90, 0x03, 0xab, + 0x00, 0x20, 0x03, 0x90, 0x05, 0xaa, 0x04, 0xa9, 0x8b, 0xe1, 0x39, 0x46, + 0xf4, 0xf7, 0x66, 0xb8, 0x41, 0x46, 0xf4, 0xf7, 0x63, 0xb8, 0x03, 0x98, + 0xf3, 0xf7, 0xb8, 0xbe, 0x4f, 0xf0, 0x56, 0x51, 0xf4, 0xf7, 0x5c, 0xb8, + 0xdf, 0xf8, 0xd0, 0x13, 0xf4, 0xf7, 0x58, 0xb8, 0x2d, 0xe9, 0xf0, 0x4f, + 0x9d, 0xb0, 0x0c, 0x46, 0x00, 0xf1, 0x68, 0x01, 0x00, 0x1d, 0x02, 0x91, + 0x01, 0x90, 0x90, 0x46, 0x9a, 0x46, 0x00, 0x20, 0x00, 0x21, 0x48, 0xf8, + 0x20, 0x10, 0x4a, 0xf8, 0x20, 0x10, 0x40, 0x1c, 0x30, 0x28, 0xf8, 0xdb, + 0x01, 0x20, 0x02, 0x99, 0x51, 0xf8, 0x20, 0x10, 0x81, 0xf0, 0x00, 0x41, + 0x48, 0xf8, 0x20, 0x10, 0x41, 0x42, 0x02, 0x9a, 0x52, 0xf8, 0x20, 0x20, + 0x08, 0xeb, 0x81, 0x03, 0x0a, 0xeb, 0x81, 0x01, 0xc3, 0xf8, 0xc0, 0x20, + 0x01, 0x9a, 0x52, 0xf8, 0x20, 0x20, 0x4a, 0xf8, 0x20, 0x20, 0x01, 0x9a, + 0x52, 0xf8, 0x20, 0x20, 0xc1, 0xf8, 0xc0, 0x20, 0x40, 0x1c, 0x18, 0x28, + 0xe1, 0xdb, 0x4f, 0xf0, 0x18, 0x0b, 0x01, 0x20, 0x01, 0x5d, 0x01, 0x29, + 0x1e, 0xbf, 0x21, 0x1a, 0x91, 0xf8, 0x30, 0x10, 0x01, 0x29, 0x01, 0xd1, + 0x83, 0x46, 0x02, 0xe0, 0x40, 0x1c, 0x18, 0x28, 0xf2, 0xdb, 0x60, 0x78, + 0x00, 0x28, 0x1c, 0xbf, 0x94, 0xf8, 0x2f, 0x10, 0x00, 0x29, 0x21, 0xd1, + 0x01, 0x28, 0x04, 0xbf, 0x94, 0xf8, 0x2f, 0x10, 0x00, 0x29, 0x03, 0xd1, + 0x02, 0x20, 0x84, 0xf8, 0x2f, 0x00, 0x17, 0xe0, 0x00, 0x28, 0x04, 0xbf, + 0x94, 0xf8, 0x2f, 0x00, 0x01, 0x28, 0x02, 0xd1, 0x02, 0x20, 0x60, 0x70, + 0x0e, 0xe0, 0x02, 0x20, 0x60, 0x70, 0x01, 0x98, 0x50, 0xf8, 0x2b, 0x00, + 0xca, 0xf8, 0x04, 0x00, 0x02, 0x20, 0x84, 0xf8, 0x2f, 0x00, 0x01, 0x98, + 0x50, 0xf8, 0x2b, 0x00, 0xca, 0xf8, 0xbc, 0x00, 0x05, 0x20, 0x26, 0x9f, + 0x00, 0xf0, 0x00, 0xf9, 0x00, 0xf0, 0xf9, 0xf8, 0x00, 0x26, 0x07, 0xf1, + 0x84, 0x05, 0x4f, 0xf0, 0x7e, 0x59, 0x03, 0xe0, 0x18, 0x2e, 0x18, 0xd0, + 0x18, 0x2e, 0x01, 0xda, 0x3e, 0x60, 0x02, 0xe0, 0xc6, 0xf1, 0x30, 0x00, + 0x38, 0x60, 0xc5, 0xf8, 0x00, 0x90, 0xc5, 0xf8, 0x04, 0x90, 0x30, 0x5d, + 0x28, 0xb1, 0x5a, 0xf8, 0x26, 0x00, 0xa8, 0x60, 0xc5, 0xf8, 0x0c, 0x90, + 0x03, 0xe0, 0xc5, 0xf8, 0x08, 0x90, 0xac, 0x48, 0xe8, 0x60, 0x00, 0xf0, + 0xe3, 0xf8, 0x76, 0x1c, 0x30, 0x2e, 0xe1, 0xdb, 0xdd, 0xf8, 0x9c, 0xa0, + 0x9a, 0xf9, 0x00, 0x60, 0xba, 0x68, 0x00, 0x2e, 0x3a, 0xd4, 0x96, 0x42, + 0x38, 0xd2, 0x00, 0x20, 0x00, 0x21, 0x0d, 0xf1, 0x0c, 0x0c, 0x10, 0xe0, + 0xb1, 0x42, 0x18, 0xbf, 0xb2, 0x42, 0x07, 0xd0, 0x03, 0xfb, 0x01, 0x23, + 0x07, 0xeb, 0x83, 0x03, 0xdb, 0x68, 0x4c, 0xf8, 0x20, 0x30, 0x40, 0x1c, + 0x52, 0x1c, 0xbb, 0x68, 0x9a, 0x42, 0xef, 0xd3, 0x49, 0x1c, 0xba, 0x68, + 0x91, 0x42, 0x38, 0xbf, 0x00, 0x22, 0xf6, 0xd3, 0x70, 0x1c, 0x04, 0xe0, + 0x07, 0xeb, 0x80, 0x01, 0x40, 0x1c, 0x0a, 0x6f, 0xca, 0x66, 0xb9, 0x68, + 0x88, 0x42, 0xf7, 0xd3, 0x4a, 0x1e, 0x07, 0xf1, 0x70, 0x01, 0x03, 0xa8, + 0xfe, 0xf7, 0xf0, 0xfe, 0xb8, 0x68, 0x03, 0xe0, 0x07, 0xeb, 0x80, 0x01, + 0xca, 0x6e, 0x0a, 0x67, 0x40, 0x1e, 0x86, 0x42, 0xf8, 0xd3, 0x07, 0xeb, + 0x86, 0x01, 0x00, 0x20, 0x08, 0x67, 0x01, 0xe0, 0x00, 0xf0, 0x8b, 0xf8, + 0x02, 0x20, 0x00, 0x90, 0x9a, 0xf8, 0x01, 0x30, 0xba, 0x68, 0x01, 0x98, + 0x07, 0xf1, 0x70, 0x01, 0xfe, 0xf7, 0x90, 0xfe, 0x00, 0x26, 0x0d, 0xe0, + 0x30, 0x5d, 0x02, 0x28, 0x04, 0xbf, 0x00, 0x20, 0x30, 0x55, 0xa0, 0x1b, + 0x90, 0xf8, 0x30, 0x10, 0x02, 0x29, 0x04, 0xbf, 0x00, 0x21, 0x80, 0xf8, + 0x30, 0x10, 0x76, 0x1c, 0x5e, 0x45, 0xef, 0xdb, 0x60, 0x78, 0x00, 0x28, + 0x1c, 0xbf, 0x94, 0xf8, 0x2f, 0x00, 0x00, 0x28, 0x1d, 0xd1, 0xab, 0xf1, + 0x01, 0x06, 0x18, 0xe0, 0x96, 0xfb, 0xfb, 0xf0, 0xf3, 0xf7, 0xac, 0xfd, + 0x02, 0x99, 0x51, 0xf8, 0x2b, 0x10, 0xf3, 0xf7, 0x4f, 0xff, 0x02, 0x21, + 0x31, 0x55, 0x02, 0x22, 0x80, 0xf0, 0x00, 0x41, 0x48, 0xf8, 0x26, 0x10, + 0x71, 0x42, 0x0b, 0x19, 0x08, 0xeb, 0x81, 0x01, 0x83, 0xf8, 0x30, 0x20, + 0xc1, 0xf8, 0xc0, 0x00, 0x76, 0x1e, 0x01, 0x2e, 0xe4, 0xda, 0x05, 0x20, + 0x00, 0xf0, 0x52, 0xf8, 0x00, 0xf0, 0x4b, 0xf8, 0x00, 0x26, 0x03, 0xe0, + 0x18, 0x2e, 0x19, 0xd0, 0x18, 0x2e, 0x03, 0xda, 0x3e, 0x60, 0x5d, 0x48, + 0x28, 0x60, 0x04, 0xe0, 0xc6, 0xf1, 0x30, 0x00, 0x38, 0x60, 0xc5, 0xf8, + 0x00, 0x90, 0xc5, 0xf8, 0x04, 0x90, 0x30, 0x5d, 0x28, 0xb1, 0x58, 0xf8, + 0x26, 0x00, 0xa8, 0x60, 0xc5, 0xf8, 0x0c, 0x90, 0x02, 0xe0, 0xa8, 0x60, + 0x56, 0x48, 0xe8, 0x60, 0x00, 0xf0, 0x38, 0xf8, 0x76, 0x1c, 0x30, 0x2e, + 0xe0, 0xdb, 0xba, 0x68, 0x00, 0xf0, 0x21, 0xf8, 0x00, 0x20, 0x38, 0x67, + 0x07, 0xf1, 0x70, 0x01, 0x03, 0x20, 0x00, 0x90, 0x9a, 0xf8, 0x01, 0x30, + 0xba, 0x68, 0x02, 0x98, 0xfe, 0xf7, 0x24, 0xfe, 0x00, 0x20, 0x0d, 0xe0, + 0x01, 0x5d, 0x02, 0x29, 0x04, 0xbf, 0x00, 0x21, 0x01, 0x55, 0x21, 0x1a, + 0x91, 0xf8, 0x30, 0x20, 0x02, 0x2a, 0x04, 0xbf, 0x00, 0x22, 0x81, 0xf8, + 0x30, 0x20, 0x40, 0x1c, 0x58, 0x45, 0xef, 0xdb, 0x1d, 0xb0, 0xbd, 0xe8, + 0xf0, 0x8f, 0x07, 0xf1, 0x70, 0x01, 0x07, 0xf1, 0x0c, 0x00, 0xfe, 0xf7, + 0x4f, 0xbe, 0x14, 0x21, 0x07, 0xf1, 0x70, 0x00, 0xf4, 0xf7, 0x98, 0xbd, + 0xb8, 0x60, 0x64, 0x21, 0x07, 0xf1, 0x0c, 0x00, 0xf4, 0xf7, 0x92, 0xbd, + 0x01, 0x20, 0x78, 0x60, 0x38, 0x46, 0xfe, 0xf7, 0x2a, 0xbd, 0x2d, 0xe9, + 0xf0, 0x43, 0x01, 0x24, 0x01, 0x26, 0x4f, 0xf0, 0xff, 0x39, 0xa8, 0xb1, + 0x1f, 0x68, 0xb7, 0xf5, 0x80, 0x2f, 0xc8, 0xbf, 0xa7, 0xf5, 0x00, 0x26, + 0x04, 0xdc, 0x17, 0xf5, 0x80, 0x2f, 0x03, 0xda, 0x07, 0xf5, 0x00, 0x26, + 0x1e, 0x60, 0x4e, 0x46, 0x2c, 0x4f, 0x17, 0x60, 0x00, 0x27, 0x0f, 0x60, + 0x1f, 0x68, 0x00, 0x2f, 0x13, 0xd5, 0x11, 0xe0, 0x00, 0x26, 0x1e, 0x60, + 0x17, 0x68, 0x00, 0x2f, 0x09, 0xd5, 0x0e, 0x68, 0x00, 0x2e, 0x54, 0xbf, + 0x01, 0x26, 0x4e, 0x46, 0x7f, 0x42, 0x17, 0x60, 0x0f, 0x68, 0x7f, 0x42, + 0x0f, 0x60, 0x0f, 0x68, 0x00, 0x2f, 0x00, 0xd4, 0x4c, 0x46, 0x00, 0x27, + 0x0f, 0xf2, 0x7c, 0x0c, 0xd2, 0xf8, 0x00, 0xe0, 0x0d, 0x68, 0x4e, 0xfa, + 0x07, 0xf8, 0x3d, 0x41, 0x05, 0xfb, 0x14, 0xee, 0xc2, 0xf8, 0x00, 0xe0, + 0xd1, 0xf8, 0x00, 0xe0, 0x08, 0xfb, 0x04, 0xee, 0xc1, 0xf8, 0x00, 0xe0, + 0x5c, 0xf8, 0x27, 0x50, 0xd3, 0xf8, 0x00, 0xe0, 0x05, 0xfb, 0x14, 0xee, + 0xc3, 0xf8, 0x00, 0xe0, 0x01, 0x24, 0x18, 0xb1, 0xbe, 0xf1, 0x00, 0x0f, + 0x04, 0xd5, 0x02, 0xe0, 0x0d, 0x68, 0x00, 0x2d, 0x00, 0xd4, 0x4c, 0x46, + 0x7f, 0x1c, 0x13, 0x2f, 0xda, 0xdb, 0x10, 0x68, 0x70, 0x43, 0x10, 0x60, + 0x08, 0x68, 0x70, 0x43, 0x08, 0x60, 0x18, 0x68, 0x00, 0xeb, 0xc6, 0x40, + 0x18, 0x60, 0xbd, 0xe8, 0xf0, 0x83, 0x00, 0x00, 0xfe, 0xff, 0xff, 0x00, + 0x00, 0x00, 0x80, 0xbf, 0xad, 0xc5, 0x27, 0x38, 0xdb, 0x0f, 0xc9, 0x40, + 0x95, 0xbf, 0xd6, 0x33, 0x4f, 0xb7, 0x09, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x40, 0x2e, 0x01, 0x00, 0xb4, 0x9f, 0x00, 0x00, 0x11, 0x51, 0x00, 0x00, + 0xb1, 0x28, 0x00, 0x00, 0x5d, 0x14, 0x00, 0x00, 0x2f, 0x0a, 0x00, 0x00, + 0x18, 0x05, 0x00, 0x00, 0x8c, 0x02, 0x00, 0x00, 0x46, 0x01, 0x00, 0x00, + 0xa3, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x70, 0x47, 0x38, 0xb5, 0xdf, 0xf8, 0x34, 0x04, 0x40, 0x89, 0xc0, 0xf3, + 0x81, 0x04, 0xc0, 0xf3, 0x01, 0x10, 0x08, 0xb1, 0x44, 0xf0, 0x04, 0x04, + 0x0c, 0xb9, 0x00, 0x20, 0x32, 0xbd, 0xdf, 0xf8, 0x20, 0x04, 0x05, 0x78, + 0x01, 0x21, 0x4f, 0xf4, 0x82, 0x70, 0xf2, 0xf7, 0x26, 0xf9, 0x20, 0x46, + 0xef, 0xf7, 0xca, 0xff, 0x08, 0xb9, 0x04, 0x20, 0x32, 0xbd, 0x20, 0x46, + 0x00, 0xf0, 0xbd, 0xf8, 0x04, 0x46, 0x29, 0x46, 0x4f, 0xf4, 0x82, 0x70, + 0xf2, 0xf7, 0x17, 0xf9, 0x20, 0x46, 0x32, 0xbd, 0x2d, 0xe9, 0xf0, 0x4c, + 0x06, 0x46, 0x15, 0xb2, 0x6f, 0xf0, 0x02, 0x00, 0x85, 0x42, 0x0c, 0x46, + 0x1f, 0x46, 0xb8, 0xbf, 0x05, 0x46, 0x02, 0xdb, 0x04, 0x2d, 0xa8, 0xbf, + 0x03, 0x25, 0xd7, 0xe9, 0x00, 0xab, 0x0f, 0x20, 0x00, 0x21, 0xa2, 0x00, + 0xf4, 0xf7, 0x82, 0xf8, 0x5b, 0x46, 0x2a, 0xea, 0x00, 0x0a, 0x23, 0xea, + 0x01, 0x0b, 0xe8, 0x1c, 0xc1, 0x17, 0xa2, 0x00, 0xf4, 0xf7, 0x78, 0xf8, + 0x4a, 0xea, 0x00, 0x00, 0x4b, 0xea, 0x01, 0x01, 0xc7, 0xe9, 0x00, 0x01, + 0x72, 0xb6, 0xdf, 0xf8, 0xa4, 0x03, 0x4f, 0xf6, 0xfe, 0x61, 0x01, 0x60, + 0x01, 0x60, 0x86, 0xf0, 0x01, 0x03, 0xdf, 0xf8, 0x98, 0x13, 0x0a, 0x78, + 0x1b, 0x01, 0x02, 0xf0, 0x8f, 0x02, 0x03, 0xf0, 0x70, 0x03, 0x1a, 0x43, + 0x0a, 0x70, 0x04, 0xf0, 0x0f, 0x03, 0x4a, 0x78, 0x02, 0xf0, 0xf0, 0x02, + 0x1a, 0x43, 0x4a, 0x70, 0x8d, 0x70, 0x00, 0x21, 0x01, 0x60, 0x62, 0xb6, + 0xbd, 0xe8, 0xf0, 0x8c, 0x2d, 0xe9, 0xf8, 0x4f, 0x90, 0x46, 0x01, 0xf0, + 0x04, 0x05, 0x72, 0xb6, 0xdf, 0xf8, 0x58, 0xa3, 0x4f, 0xf6, 0xfe, 0x69, + 0x80, 0x00, 0xca, 0xf8, 0x00, 0x90, 0x00, 0xf0, 0x1c, 0x00, 0xd4, 0x4f, + 0xd4, 0x4c, 0xca, 0xf8, 0x00, 0x90, 0x01, 0xf0, 0x03, 0x01, 0x01, 0x43, + 0x39, 0x70, 0x40, 0xea, 0x95, 0x00, 0x20, 0x70, 0x00, 0x20, 0xca, 0xf8, + 0x00, 0x00, 0x62, 0xb6, 0xce, 0x49, 0xf3, 0xf7, 0x91, 0xfb, 0x97, 0xf8, + 0x00, 0xb0, 0x26, 0x78, 0xf1, 0xf7, 0xc9, 0xf9, 0x08, 0xb1, 0x01, 0x26, + 0x0d, 0xe0, 0x03, 0x21, 0x1b, 0xea, 0x01, 0x0f, 0x03, 0xd1, 0xf0, 0x07, + 0x01, 0xd4, 0x00, 0x26, 0x05, 0xe0, 0x00, 0x20, 0xf3, 0xf7, 0x96, 0xfb, + 0x00, 0x28, 0xea, 0xd0, 0x02, 0x26, 0x00, 0x20, 0xf3, 0xf7, 0x08, 0xfb, + 0x86, 0xbb, 0x72, 0xb6, 0xca, 0xf8, 0x00, 0x90, 0xca, 0xf8, 0x00, 0x90, + 0x00, 0x20, 0x41, 0x01, 0x39, 0x70, 0x39, 0x79, 0xfa, 0x78, 0xbb, 0x78, + 0x97, 0xf8, 0x01, 0xc0, 0x42, 0xea, 0x01, 0x21, 0x43, 0xea, 0x01, 0x21, + 0x4c, 0xea, 0x01, 0x21, 0x48, 0xf8, 0x20, 0x10, 0x40, 0x1c, 0x08, 0x28, + 0xed, 0xd3, 0x9d, 0xb1, 0x00, 0x21, 0x08, 0x20, 0x4a, 0x01, 0x22, 0x70, + 0x49, 0x1c, 0x22, 0x79, 0xe3, 0x78, 0xa5, 0x78, 0x67, 0x78, 0x43, 0xea, + 0x02, 0x22, 0x45, 0xea, 0x02, 0x22, 0x47, 0xea, 0x02, 0x22, 0x48, 0xf8, + 0x20, 0x20, 0x40, 0x1c, 0x0c, 0x28, 0xed, 0xd3, 0x00, 0x20, 0xca, 0xf8, + 0x00, 0x00, 0x62, 0xb6, 0x30, 0x46, 0xbd, 0xe8, 0xf2, 0x8f, 0x2d, 0xe9, + 0xf0, 0x4f, 0xa9, 0xb0, 0x80, 0x46, 0x0b, 0xa8, 0x0f, 0xf2, 0xc0, 0x21, + 0x10, 0x22, 0xf6, 0xf7, 0xd9, 0xfc, 0x00, 0x20, 0x00, 0xf0, 0xe2, 0xf9, + 0x00, 0x21, 0x00, 0x20, 0xf0, 0xf7, 0xef, 0xf8, 0x00, 0xf0, 0xec, 0xf9, + 0x00, 0x25, 0x07, 0xae, 0xad, 0x55, 0x6d, 0x1c, 0x10, 0x2d, 0xfb, 0xd3, + 0x00, 0xf0, 0x44, 0xfa, 0x5f, 0xea, 0x00, 0x09, 0xfa, 0xd0, 0x00, 0x24, + 0xdf, 0xf8, 0x5c, 0xa2, 0x00, 0xf0, 0x39, 0xf9, 0x0a, 0xd5, 0x00, 0x25, + 0x0a, 0xf1, 0x30, 0x00, 0x00, 0xeb, 0xc4, 0x03, 0x00, 0x22, 0x00, 0xf0, + 0x37, 0xf9, 0x6d, 0x1c, 0x10, 0x2d, 0xf5, 0xd3, 0x0a, 0xeb, 0x84, 0x01, + 0x64, 0x1c, 0x6f, 0xf0, 0x00, 0x40, 0x06, 0x2c, 0x08, 0x66, 0xe9, 0xdb, + 0x00, 0xf0, 0x1f, 0xf9, 0x04, 0x00, 0x55, 0xd1, 0x01, 0x90, 0x0d, 0xf1, + 0x3c, 0x0b, 0x00, 0x20, 0x00, 0x90, 0x01, 0x98, 0x30, 0xb9, 0x00, 0x99, + 0x0f, 0xf2, 0x54, 0x20, 0x00, 0xeb, 0x41, 0x10, 0x03, 0x90, 0x24, 0xe0, + 0x15, 0xa8, 0x03, 0x90, 0x02, 0x20, 0x09, 0xf0, 0x01, 0x01, 0x49, 0x42, + 0x80, 0x4a, 0x11, 0x40, 0x81, 0xea, 0x59, 0x09, 0x00, 0x27, 0x3a, 0x1d, + 0x29, 0xfa, 0x07, 0xf1, 0x29, 0xfa, 0x02, 0xf3, 0x01, 0xf0, 0x0f, 0x01, + 0x03, 0xf0, 0x0f, 0x03, 0x8a, 0x5d, 0x9c, 0x5d, 0x8c, 0x55, 0x08, 0x37, + 0x9a, 0x55, 0x20, 0x2f, 0xef, 0xd3, 0x40, 0x1e, 0xe5, 0xd1, 0x00, 0x25, + 0x15, 0xa9, 0xa8, 0x5d, 0x21, 0xf8, 0x15, 0x00, 0x6d, 0x1c, 0x10, 0x2d, + 0xf9, 0xd3, 0x00, 0x25, 0x03, 0x98, 0x30, 0xf9, 0x15, 0x00, 0x02, 0x90, + 0x04, 0xaa, 0x00, 0x20, 0x6f, 0xf0, 0x00, 0x41, 0x4b, 0xf8, 0x20, 0x10, + 0x00, 0x21, 0x22, 0xf8, 0x10, 0x10, 0x40, 0x1c, 0x06, 0x28, 0xf5, 0xdb, + 0x00, 0x27, 0x00, 0x24, 0x00, 0xf0, 0xd9, 0xf8, 0x05, 0xd5, 0x00, 0xf0, + 0xcd, 0xf8, 0x02, 0x99, 0xfa, 0x1e, 0x00, 0xf0, 0xda, 0xf8, 0x64, 0x1c, + 0x06, 0x2c, 0xf3, 0xdb, 0x00, 0xf0, 0xc9, 0xf8, 0x04, 0x00, 0x06, 0xd0, + 0x00, 0xf0, 0x96, 0xf9, 0x00, 0x20, 0xf0, 0xf7, 0xc7, 0xf8, 0x20, 0x46, + 0xa4, 0xe0, 0x00, 0xeb, 0xd0, 0x71, 0x49, 0x10, 0x28, 0xfa, 0x01, 0xf2, + 0xd1, 0x07, 0x0b, 0xd5, 0x1d, 0xa9, 0x5b, 0xf8, 0x20, 0x20, 0x51, 0xf8, + 0x30, 0x10, 0x91, 0x42, 0x04, 0xda, 0x4b, 0xf8, 0x20, 0x10, 0x04, 0xa9, + 0x21, 0xf8, 0x10, 0x70, 0x40, 0x1c, 0x06, 0x28, 0xe9, 0xdb, 0x7f, 0x1c, + 0x07, 0x2f, 0xce, 0xd3, 0x00, 0xf0, 0xa9, 0xf8, 0x16, 0xd5, 0x04, 0xa8, + 0x0a, 0xeb, 0xc4, 0x07, 0x30, 0xf9, 0x14, 0x00, 0x02, 0x99, 0xc2, 0x1e, + 0x07, 0xf1, 0x30, 0x03, 0x00, 0xf0, 0xa5, 0xf8, 0x0a, 0xeb, 0x84, 0x03, + 0x5b, 0xf8, 0x24, 0x20, 0x18, 0x6e, 0x82, 0x42, 0x04, 0xda, 0xd7, 0xe9, + 0x0c, 0x01, 0xc7, 0xe9, 0x00, 0x01, 0x1a, 0x66, 0x64, 0x1c, 0x06, 0x2c, + 0xe2, 0xdb, 0x6d, 0x1c, 0x10, 0x2d, 0x9d, 0xd3, 0x00, 0x98, 0x40, 0x1c, + 0x04, 0x28, 0x00, 0x90, 0xff, 0xf4, 0x69, 0xaf, 0x01, 0x98, 0x07, 0x28, + 0x41, 0xd2, 0x40, 0x1c, 0x01, 0x90, 0x0b, 0xa8, 0x01, 0x99, 0x00, 0xeb, + 0x41, 0x00, 0x00, 0x25, 0x00, 0x90, 0x00, 0x24, 0x00, 0xf0, 0x77, 0xf8, + 0x2d, 0xd5, 0x0a, 0xeb, 0xc4, 0x02, 0xd2, 0xe9, 0x00, 0x01, 0xaa, 0x00, + 0xfb, 0xf7, 0xfa, 0xfd, 0x00, 0xf0, 0x0f, 0x00, 0xc7, 0x1e, 0x3f, 0xb2, + 0x00, 0x2f, 0x09, 0xd4, 0x01, 0x2f, 0x0c, 0xda, 0x00, 0xf0, 0x68, 0xf9, + 0x00, 0xeb, 0xd0, 0x71, 0x49, 0x10, 0xb0, 0xeb, 0x41, 0x00, 0x04, 0xd0, + 0x00, 0x98, 0x30, 0xf8, 0x02, 0x0c, 0xc2, 0x19, 0x03, 0xe0, 0x00, 0x98, + 0x30, 0xf8, 0x02, 0x0c, 0x3a, 0x1a, 0x12, 0xb2, 0x04, 0x2a, 0xa8, 0xbf, + 0x03, 0x22, 0x04, 0xda, 0x12, 0xf1, 0x03, 0x0f, 0xb8, 0xbf, 0x6f, 0xf0, + 0x02, 0x02, 0x00, 0xf0, 0x41, 0xf8, 0x00, 0xf0, 0x4f, 0xf8, 0x64, 0x1c, + 0x06, 0x2c, 0xcb, 0xdb, 0x6d, 0x1c, 0x10, 0x2d, 0xbf, 0xf4, 0x23, 0xaf, + 0xc5, 0xe7, 0x00, 0x25, 0x00, 0x24, 0x00, 0xf0, 0x3c, 0xf8, 0x0f, 0xd5, + 0x0a, 0xeb, 0xc4, 0x02, 0x00, 0xf0, 0x2e, 0xf8, 0xd2, 0xe9, 0x00, 0x01, + 0x1e, 0x46, 0xaa, 0x00, 0xfb, 0xf7, 0xbc, 0xfd, 0x00, 0xf0, 0x0f, 0x00, + 0xc2, 0x1e, 0x33, 0x46, 0x00, 0xf0, 0x32, 0xf8, 0x64, 0x1c, 0x06, 0x2c, + 0xe9, 0xdb, 0x6d, 0x1c, 0x10, 0x2d, 0xe5, 0xd3, 0x00, 0xf0, 0xf0, 0xf8, + 0x00, 0x20, 0xf0, 0xf7, 0x21, 0xf8, 0x00, 0x20, 0x29, 0xb0, 0xbd, 0xe8, + 0xf0, 0x8f, 0x00, 0x00, 0x78, 0x29, 0x00, 0x20, 0x04, 0x01, 0x00, 0x46, + 0x48, 0x00, 0x00, 0x50, 0xb0, 0x05, 0x00, 0x46, 0xb8, 0x05, 0x00, 0x46, + 0x48, 0x08, 0x00, 0x46, 0x20, 0xa1, 0x07, 0x00, 0xb0, 0xf0, 0x00, 0x20, + 0x01, 0x00, 0x00, 0xd0, 0x0a, 0xeb, 0xc4, 0x00, 0x00, 0xf1, 0x30, 0x03, + 0x70, 0x47, 0x1d, 0xaa, 0x41, 0x46, 0x04, 0x20, 0x34, 0xe6, 0x04, 0xeb, + 0xd4, 0x70, 0x40, 0x10, 0x28, 0xfa, 0x00, 0xf1, 0xc8, 0x07, 0x70, 0x47, + 0x29, 0x46, 0x20, 0x46, 0xe4, 0xe5, 0x00, 0x00, 0x04, 0x00, 0xfc, 0xff, + 0xfe, 0xff, 0x02, 0x00, 0x01, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x07, 0x00, 0x08, 0x00, 0x09, 0x00, 0x0a, 0x00, 0x0b, 0x00, + 0x0c, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0e, 0x00, + 0x0d, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x08, 0x00, + 0x07, 0x00, 0x06, 0x00, 0x05, 0x00, 0x04, 0x00, 0x03, 0x00, 0x02, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x09, 0x00, 0x0a, 0x00, 0x0b, 0x00, + 0x0c, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, + 0x07, 0x00, 0x06, 0x00, 0x05, 0x00, 0x04, 0x00, 0x03, 0x00, 0x02, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0x0d, 0x00, 0x0c, 0x00, + 0x0b, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x04, 0x00, 0x06, 0x00, 0x08, 0x00, 0x0a, 0x00, 0x0c, 0x00, 0x0e, 0x00, + 0x01, 0x00, 0x03, 0x00, 0x05, 0x00, 0x07, 0x00, 0x09, 0x00, 0x0b, 0x00, + 0x0d, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0x0b, 0x00, 0x09, 0x00, + 0x07, 0x00, 0x05, 0x00, 0x03, 0x00, 0x01, 0x00, 0x0e, 0x00, 0x0c, 0x00, + 0x0a, 0x00, 0x08, 0x00, 0x06, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x03, 0x00, 0x05, 0x00, 0x07, 0x00, 0x09, 0x00, 0x0b, 0x00, + 0x0d, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00, 0x06, 0x00, + 0x08, 0x00, 0x0a, 0x00, 0x0c, 0x00, 0x0e, 0x00, 0x0e, 0x00, 0x0c, 0x00, + 0x0a, 0x00, 0x08, 0x00, 0x06, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x0f, 0x00, 0x0d, 0x00, 0x0b, 0x00, 0x09, 0x00, 0x07, 0x00, 0x05, 0x00, + 0x03, 0x00, 0x01, 0x00, 0x10, 0xb5, 0x04, 0x46, 0x04, 0x48, 0xc0, 0x46, + 0xc0, 0x46, 0x00, 0x21, 0x01, 0x70, 0x03, 0x48, 0xc0, 0x46, 0xc0, 0x46, + 0x04, 0x60, 0x10, 0xbd, 0x90, 0xbc, 0x00, 0x20, 0x94, 0xbc, 0x00, 0x20, + 0x38, 0xb5, 0x2c, 0x48, 0x01, 0x78, 0x80, 0x7d, 0xc0, 0x07, 0x03, 0xd5, + 0x48, 0x07, 0x58, 0xbf, 0x08, 0x22, 0x00, 0xd5, 0x04, 0x22, 0x0c, 0x21, + 0x4f, 0xf4, 0xb6, 0x60, 0xef, 0xf7, 0xa6, 0xfc, 0x40, 0x22, 0x00, 0xf0, + 0x41, 0xf8, 0x40, 0x22, 0x00, 0xf0, 0x39, 0xf8, 0x40, 0x22, 0x00, 0xf0, + 0x31, 0xf8, 0x21, 0x4c, 0x21, 0x4d, 0x20, 0x78, 0x28, 0x70, 0x40, 0x22, + 0x00, 0xf0, 0x25, 0xf8, 0x60, 0x78, 0x68, 0x70, 0x40, 0x22, 0xbd, 0xe8, + 0x38, 0x40, 0x40, 0x21, 0x40, 0xf2, 0xe1, 0x50, 0xef, 0xf7, 0x8c, 0xbc, + 0x80, 0xb5, 0x00, 0x22, 0x00, 0xf0, 0x26, 0xf8, 0x00, 0x22, 0x00, 0xf0, + 0x1e, 0xf8, 0x00, 0x22, 0x00, 0xf0, 0x16, 0xf8, 0x00, 0x22, 0x00, 0xf0, + 0x0e, 0xf8, 0x00, 0x22, 0x40, 0x21, 0x40, 0xf2, 0xe1, 0x50, 0xef, 0xf7, + 0x79, 0xfc, 0xbd, 0xe8, 0x08, 0x40, 0x00, 0x22, 0x0c, 0x21, 0x4f, 0xf4, + 0xb6, 0x60, 0xef, 0xf7, 0x71, 0xbc, 0x40, 0x21, 0x4f, 0xf4, 0xbc, 0x60, + 0xef, 0xf7, 0x6c, 0xbc, 0x40, 0x21, 0x40, 0xf2, 0xdf, 0x50, 0xef, 0xf7, + 0x67, 0xbc, 0x40, 0x21, 0x40, 0xf2, 0xde, 0x50, 0xef, 0xf7, 0x62, 0xbc, + 0x40, 0x21, 0x40, 0xf2, 0xdd, 0x50, 0xef, 0xf7, 0x5d, 0xbc, 0x00, 0x00, + 0x02, 0x01, 0x00, 0x46, 0xe0, 0x05, 0x00, 0x46, 0x9a, 0xf3, 0x00, 0x20, + 0xf8, 0xb5, 0x34, 0x4f, 0x38, 0x46, 0xc0, 0x46, 0xc0, 0x46, 0x04, 0x46, + 0x38, 0x1d, 0xc0, 0x46, 0xc0, 0x46, 0x05, 0x46, 0x07, 0xf1, 0x08, 0x00, + 0xc0, 0x46, 0xc0, 0x46, 0x06, 0x46, 0x07, 0xf1, 0x0c, 0x00, 0xc0, 0x46, + 0xc0, 0x46, 0x23, 0x78, 0x2b, 0x49, 0x2c, 0x4a, 0x00, 0x2b, 0x40, 0xd1, + 0x2b, 0x68, 0x02, 0xfb, 0x03, 0x13, 0x2b, 0x60, 0x08, 0x27, 0x02, 0xfb, + 0x03, 0x13, 0x2b, 0x60, 0x02, 0xfb, 0x03, 0x13, 0x2b, 0x60, 0x02, 0xfb, + 0x03, 0x13, 0x2b, 0x60, 0x02, 0xfb, 0x03, 0x13, 0x2b, 0x60, 0x02, 0xfb, + 0x03, 0x13, 0x2b, 0x60, 0x02, 0xfb, 0x03, 0x13, 0x2b, 0x60, 0x02, 0xfb, + 0x03, 0x13, 0x2b, 0x60, 0x03, 0x46, 0xd5, 0xf8, 0x00, 0xc0, 0x02, 0xfb, + 0x0c, 0x1c, 0xc5, 0xf8, 0x00, 0xc0, 0x43, 0xf8, 0x04, 0xcb, 0x7f, 0x1e, + 0xd5, 0xf8, 0x00, 0xc0, 0x02, 0xfb, 0x0c, 0x1c, 0xc5, 0xf8, 0x00, 0xc0, + 0x43, 0xf8, 0x04, 0xcb, 0xd5, 0xf8, 0x00, 0xc0, 0x02, 0xfb, 0x0c, 0x1c, + 0xc5, 0xf8, 0x00, 0xc0, 0x43, 0xf8, 0x04, 0xcb, 0xd5, 0xf8, 0x00, 0xc0, + 0x02, 0xfb, 0x0c, 0x1c, 0xc5, 0xf8, 0x00, 0xc0, 0x43, 0xf8, 0x04, 0xcb, + 0xdd, 0xd1, 0xc3, 0x6f, 0x33, 0x60, 0x01, 0x23, 0x23, 0x70, 0x2b, 0x68, + 0x02, 0xfb, 0x03, 0x11, 0x29, 0x60, 0x31, 0x78, 0x01, 0xf0, 0x1f, 0x01, + 0x50, 0xf8, 0x21, 0x20, 0x32, 0x60, 0x2a, 0x68, 0x40, 0xf8, 0x21, 0x20, + 0x30, 0x68, 0x80, 0x00, 0x80, 0x08, 0xf2, 0xbd, 0x90, 0xbc, 0x00, 0x20, + 0x5f, 0xf3, 0x6e, 0x3c, 0x0d, 0x66, 0x19, 0x00, 0x00, 0xb5, 0x32, 0x38, + 0xa1, 0xfb, 0x00, 0x01, 0xdf, 0xf8, 0x98, 0x24, 0x00, 0x23, 0xf3, 0xf7, + 0x01, 0xfe, 0x80, 0xb2, 0x00, 0xbd, 0x10, 0xb5, 0xdf, 0xf8, 0x8c, 0x44, + 0x61, 0x89, 0x00, 0x20, 0xc1, 0xf3, 0x81, 0x01, 0x11, 0xb1, 0x00, 0xf0, + 0x1b, 0xf8, 0x28, 0xb9, 0x61, 0x89, 0xc1, 0xf3, 0x82, 0x11, 0x11, 0xb1, + 0x00, 0xf0, 0x85, 0xf9, 0x88, 0xb9, 0x61, 0x89, 0xc1, 0xf3, 0x01, 0x11, + 0x69, 0xb1, 0xf1, 0xf7, 0x0a, 0xf9, 0x21, 0x6c, 0xff, 0xf7, 0xda, 0xff, + 0xdf, 0xf8, 0x5c, 0x14, 0x08, 0x80, 0x08, 0x20, 0xf4, 0xf7, 0xae, 0xfa, + 0xbd, 0xe8, 0x10, 0x40, 0xb5, 0xe0, 0x10, 0xbd, 0x00, 0x21, 0x00, 0x20, + 0x2d, 0xe9, 0xf8, 0x4f, 0xef, 0xf7, 0xfb, 0xfd, 0x00, 0x22, 0x03, 0x21, + 0x40, 0xf6, 0x84, 0x50, 0xef, 0xf7, 0xaa, 0xfb, 0x10, 0x21, 0x4f, 0xf4, + 0xc6, 0x60, 0xef, 0xf7, 0x9b, 0xfb, 0x40, 0x21, 0x40, 0xf2, 0x31, 0x60, + 0xef, 0xf7, 0x96, 0xfb, 0x00, 0x21, 0x40, 0xf2, 0x32, 0x60, 0xef, 0xf7, + 0x91, 0xfb, 0x33, 0x21, 0x40, 0xf2, 0x33, 0x60, 0xef, 0xf7, 0x8c, 0xfb, + 0x00, 0xf0, 0x81, 0xf8, 0x00, 0xf0, 0x7a, 0xf8, 0x00, 0xf0, 0x73, 0xf8, + 0x32, 0x21, 0x40, 0xf2, 0x34, 0x60, 0xef, 0xf7, 0x81, 0xfb, 0x40, 0xf2, + 0x35, 0x65, 0x1b, 0x22, 0x1f, 0x21, 0x28, 0x46, 0xef, 0xf7, 0x84, 0xfb, + 0x40, 0xf2, 0x36, 0x66, 0x13, 0x21, 0x00, 0xf0, 0x16, 0xfa, 0x40, 0xf2, + 0x37, 0x6b, 0x0a, 0x21, 0x00, 0xf0, 0x1d, 0xfa, 0x40, 0xf2, 0x3a, 0x68, + 0x00, 0xf0, 0x14, 0xfa, 0x40, 0xf2, 0x3b, 0x69, 0x00, 0xf0, 0x68, 0xf8, + 0x40, 0xf2, 0x39, 0x6a, 0x00, 0xf0, 0x60, 0xf8, 0xdf, 0xf8, 0xbc, 0x03, + 0x00, 0x78, 0x8d, 0xf8, 0x00, 0x00, 0x40, 0xf2, 0x76, 0x67, 0x00, 0x21, + 0x38, 0x46, 0xef, 0xf7, 0x59, 0xfb, 0x02, 0x22, 0x00, 0xf0, 0x5a, 0xf8, + 0xe9, 0x4b, 0x00, 0x22, 0x02, 0x21, 0x4f, 0xf4, 0xd9, 0x70, 0xf6, 0xf7, + 0x13, 0xf8, 0x00, 0x24, 0x18, 0xb1, 0x00, 0x22, 0x00, 0xf0, 0x4e, 0xf8, + 0x01, 0x24, 0x9d, 0xf8, 0x00, 0x10, 0x38, 0x46, 0xef, 0xf7, 0x44, 0xfb, + 0xf1, 0xf7, 0x97, 0xf8, 0xdc, 0x49, 0xc9, 0x6a, 0xff, 0xf7, 0x62, 0xff, + 0x07, 0x46, 0xf9, 0xb2, 0x40, 0xf2, 0x31, 0x60, 0xef, 0xf7, 0x38, 0xfb, + 0x39, 0x0a, 0x40, 0xf2, 0x32, 0x60, 0xef, 0xf7, 0x33, 0xfb, 0x00, 0x21, + 0x40, 0xf2, 0x33, 0x60, 0xef, 0xf7, 0x2e, 0xfb, 0x61, 0x21, 0x00, 0xf0, + 0xcc, 0xf9, 0x0a, 0x21, 0x00, 0xf0, 0xd5, 0xf9, 0x00, 0xf0, 0x22, 0xf8, + 0x00, 0xf0, 0xcc, 0xf9, 0x00, 0xf0, 0x22, 0xf8, 0x00, 0xf0, 0x17, 0xf8, + 0x00, 0xf0, 0x10, 0xf8, 0x00, 0xf0, 0x09, 0xf8, 0x7b, 0x21, 0x00, 0xf0, + 0xbe, 0xf9, 0x00, 0x20, 0xef, 0xf7, 0xc8, 0xfd, 0x20, 0x46, 0xbd, 0xe8, + 0xf2, 0x8f, 0x11, 0x21, 0x40, 0xf2, 0x41, 0x60, 0xef, 0xf7, 0x0e, 0xbb, + 0x00, 0x21, 0x4f, 0xf4, 0xc8, 0x60, 0xef, 0xf7, 0x09, 0xbb, 0x00, 0x21, + 0x40, 0xf2, 0x3f, 0x60, 0xef, 0xf7, 0x04, 0xbb, 0x3f, 0x21, 0x50, 0x46, + 0xef, 0xf7, 0x00, 0xbb, 0x00, 0x21, 0x48, 0x46, 0xef, 0xf7, 0xfc, 0xba, + 0x02, 0x21, 0x4f, 0xf4, 0xd9, 0x70, 0xef, 0xf7, 0x01, 0xbb, 0x2d, 0xe9, + 0xf0, 0x4f, 0x87, 0xb0, 0x00, 0x21, 0x00, 0x20, 0xef, 0xf7, 0x45, 0xfd, + 0x10, 0x22, 0x00, 0xf0, 0xad, 0xf8, 0x00, 0xf0, 0xa0, 0xf9, 0x10, 0x21, + 0x40, 0xf2, 0x4f, 0x60, 0xef, 0xf7, 0xe6, 0xfa, 0x40, 0x21, 0x4f, 0xf4, + 0xca, 0x60, 0xef, 0xf7, 0xe1, 0xfa, 0x00, 0x21, 0x40, 0xf2, 0x51, 0x60, + 0xef, 0xf7, 0xdc, 0xfa, 0x40, 0xf2, 0x52, 0x64, 0x33, 0x21, 0x20, 0x46, + 0xef, 0xf7, 0xd6, 0xfa, 0x32, 0x21, 0x40, 0xf2, 0x53, 0x60, 0xef, 0xf7, + 0xd1, 0xfa, 0x7b, 0x22, 0x7f, 0x21, 0x40, 0xf2, 0x54, 0x60, 0xef, 0xf7, + 0xd5, 0xfa, 0x01, 0x21, 0x40, 0xf2, 0x55, 0x60, 0xef, 0xf7, 0xc6, 0xfa, + 0x40, 0xf2, 0x56, 0x65, 0x00, 0xf0, 0x66, 0xf9, 0x40, 0xf2, 0x57, 0x6a, + 0x3c, 0x21, 0xff, 0xf7, 0xba, 0xff, 0x40, 0xf2, 0x59, 0x6b, 0x00, 0xf0, + 0x65, 0xf9, 0x40, 0xf2, 0x5a, 0x68, 0x00, 0x21, 0x00, 0xf0, 0x5d, 0xf9, + 0x00, 0xf0, 0x6d, 0xf8, 0x98, 0x48, 0x97, 0x4f, 0x00, 0x78, 0x01, 0x90, + 0x40, 0xf2, 0x42, 0x69, 0x04, 0xa8, 0xf1, 0xf7, 0xe4, 0xfc, 0x00, 0x20, + 0xf1, 0xf7, 0x09, 0xfd, 0x93, 0x48, 0x00, 0x78, 0x00, 0x90, 0x02, 0x21, + 0xff, 0xf7, 0xa1, 0xff, 0x3b, 0x46, 0x00, 0x22, 0x02, 0x21, 0x48, 0x46, + 0xf5, 0xf7, 0x5e, 0xff, 0x06, 0x46, 0x00, 0x21, 0x04, 0xa8, 0xf1, 0xf7, + 0xe2, 0xfc, 0x1e, 0xb1, 0xff, 0xf7, 0x92, 0xff, 0x02, 0x26, 0x16, 0xe0, + 0x02, 0xa8, 0xf1, 0xf7, 0x3a, 0xff, 0x01, 0x21, 0x00, 0x20, 0xf1, 0xf7, + 0x37, 0xfe, 0x04, 0x21, 0xff, 0xf7, 0x87, 0xff, 0x3b, 0x46, 0x00, 0x22, + 0x04, 0x21, 0x48, 0x46, 0xf5, 0xf7, 0x44, 0xff, 0x10, 0xb1, 0xff, 0xf7, + 0x7d, 0xff, 0x03, 0x26, 0x02, 0xa8, 0xf1, 0xf7, 0x33, 0xff, 0x00, 0xf0, + 0x02, 0xf9, 0x00, 0x22, 0x00, 0xf0, 0x34, 0xf8, 0xff, 0x21, 0x40, 0xf2, + 0x4f, 0x60, 0xef, 0xf7, 0x6f, 0xfa, 0x74, 0x4f, 0x39, 0x88, 0xc9, 0xb2, + 0x4f, 0xf4, 0xca, 0x60, 0xef, 0xf7, 0x68, 0xfa, 0x38, 0x88, 0x01, 0x0a, + 0x40, 0xf2, 0x51, 0x60, 0xef, 0xf7, 0x62, 0xfa, 0x00, 0x21, 0x20, 0x46, + 0xef, 0xf7, 0x5e, 0xfa, 0x00, 0xf0, 0x00, 0xf9, 0x3c, 0x21, 0xff, 0xf7, + 0x56, 0xff, 0x00, 0xf0, 0x12, 0xf8, 0x00, 0xf0, 0x01, 0xf9, 0x00, 0x21, + 0x00, 0xf0, 0xfb, 0xf8, 0x00, 0x98, 0x40, 0xf0, 0x10, 0x01, 0xc9, 0xb2, + 0xff, 0xf7, 0x4d, 0xff, 0x00, 0x20, 0xef, 0xf7, 0xfb, 0xfc, 0x30, 0x46, + 0x07, 0xb0, 0xbd, 0xe8, 0xf0, 0x8f, 0x3f, 0x21, 0x4f, 0xf4, 0xcb, 0x60, + 0xef, 0xf7, 0x40, 0xba, 0x10, 0x21, 0x40, 0xf6, 0x82, 0x50, 0xef, 0xf7, + 0x45, 0xba, 0x00, 0x20, 0x2d, 0xe9, 0xfe, 0x4f, 0x00, 0x21, 0xef, 0xf7, + 0x8a, 0xfc, 0x00, 0xf0, 0xe8, 0xf8, 0x5b, 0x48, 0x00, 0x78, 0x8d, 0xf8, + 0x08, 0x00, 0x03, 0x21, 0x40, 0xf6, 0x1a, 0x00, 0xef, 0xf7, 0x2a, 0xfa, + 0x00, 0xf0, 0xd8, 0xf8, 0x40, 0x21, 0x40, 0xf2, 0x44, 0x60, 0xef, 0xf7, + 0x23, 0xfa, 0x30, 0x21, 0x40, 0xf2, 0x45, 0x60, 0xef, 0xf7, 0x1e, 0xfa, + 0x00, 0xf0, 0xb7, 0xf8, 0x32, 0x21, 0x40, 0xf2, 0x47, 0x60, 0xef, 0xf7, + 0x17, 0xfa, 0x1b, 0x22, 0x1f, 0x21, 0x4f, 0xf4, 0xc9, 0x60, 0xef, 0xf7, + 0x1b, 0xfa, 0x00, 0xf0, 0xa5, 0xf8, 0x00, 0xf0, 0x9e, 0xf8, 0x40, 0xf2, + 0x4b, 0x65, 0x08, 0x21, 0x00, 0xf0, 0xad, 0xf8, 0x40, 0xf2, 0x4d, 0x66, + 0x00, 0xf0, 0xa4, 0xf8, 0x40, 0xf2, 0x4e, 0x69, 0xff, 0xf7, 0x00, 0xff, + 0x40, 0xf2, 0x4c, 0x68, 0x14, 0x21, 0x00, 0xf0, 0xa4, 0xf8, 0x00, 0x22, + 0x00, 0xf0, 0x7e, 0xf8, 0x40, 0xf6, 0x1f, 0x07, 0x00, 0x22, 0xc0, 0x21, + 0x38, 0x46, 0xf1, 0xf7, 0xcd, 0xfb, 0x38, 0x48, 0x00, 0x78, 0x01, 0x90, + 0x04, 0x21, 0x4f, 0xf4, 0x82, 0x70, 0xf1, 0xf7, 0x9e, 0xfb, 0x40, 0xf6, + 0x15, 0x0a, 0x20, 0x22, 0x20, 0x21, 0x50, 0x46, 0xf1, 0xf7, 0xbe, 0xfb, + 0x31, 0x48, 0x00, 0x78, 0x00, 0x90, 0x40, 0xf2, 0x42, 0x6b, 0x01, 0x21, + 0x00, 0xf0, 0x87, 0xf8, 0x2b, 0x4b, 0x00, 0x22, 0x01, 0x21, 0x58, 0x46, + 0xf5, 0xf7, 0x98, 0xfe, 0x00, 0x24, 0x10, 0xb1, 0x00, 0xf0, 0x7c, 0xf8, + 0x04, 0x24, 0x00, 0x22, 0x20, 0x21, 0x50, 0x46, 0xf1, 0xf7, 0xa6, 0xfb, + 0x00, 0xf0, 0x53, 0xf8, 0x80, 0x22, 0x00, 0xf0, 0x4b, 0xf8, 0xc0, 0x22, + 0xc0, 0x21, 0x38, 0x46, 0xf1, 0xf7, 0x9c, 0xfb, 0x9d, 0xf8, 0x08, 0x10, + 0x40, 0xf6, 0x1a, 0x00, 0xef, 0xf7, 0xba, 0xf9, 0x00, 0xf0, 0x68, 0xf8, + 0xf0, 0xf7, 0x03, 0xff, 0x16, 0x49, 0x49, 0x6d, 0xff, 0xf7, 0xd6, 0xfd, + 0x07, 0x46, 0xf9, 0xb2, 0x40, 0xf2, 0x44, 0x60, 0xef, 0xf7, 0xac, 0xf9, + 0x39, 0x0a, 0x40, 0xf2, 0x45, 0x60, 0xef, 0xf7, 0xa7, 0xf9, 0x00, 0xf0, + 0x40, 0xf8, 0x00, 0xf0, 0x39, 0xf8, 0x00, 0xf0, 0x32, 0xf8, 0x08, 0x21, + 0x00, 0xf0, 0x43, 0xf8, 0x14, 0x21, 0x00, 0xf0, 0x44, 0xf8, 0x00, 0xf0, + 0x39, 0xf8, 0xff, 0xf7, 0x97, 0xfe, 0x00, 0x98, 0x40, 0xf0, 0x08, 0x01, + 0xc9, 0xb2, 0x00, 0xf0, 0x3e, 0xf8, 0x00, 0x20, 0xef, 0xf7, 0x40, 0xfc, + 0x20, 0x46, 0xbd, 0xe8, 0xfe, 0x8f, 0x00, 0x00, 0x00, 0x00, 0x09, 0x3d, + 0x78, 0x29, 0x00, 0x20, 0x94, 0xf3, 0x00, 0x20, 0x76, 0x06, 0x00, 0x46, + 0x40, 0x42, 0x0f, 0x00, 0x04, 0x01, 0x00, 0x46, 0x42, 0x06, 0x00, 0x46, + 0x1a, 0x08, 0x00, 0x46, 0x80, 0x21, 0x4f, 0xf4, 0x02, 0x60, 0xf1, 0xf7, + 0x51, 0xbb, 0x01, 0x99, 0xc9, 0xb2, 0x4f, 0xf4, 0x82, 0x70, 0xf1, 0xf7, + 0x24, 0xbb, 0x0a, 0x21, 0x40, 0xf2, 0x4a, 0x60, 0xef, 0xf7, 0x6a, 0xb9, + 0x13, 0x21, 0x40, 0xf2, 0x49, 0x60, 0xef, 0xf7, 0x65, 0xb9, 0x00, 0x21, + 0x40, 0xf2, 0x46, 0x60, 0xef, 0xf7, 0x60, 0xb9, 0x00, 0x21, 0x30, 0x46, + 0xef, 0xf7, 0x5c, 0xb9, 0x0a, 0x21, 0x28, 0x46, 0xef, 0xf7, 0x58, 0xb9, + 0x01, 0x21, 0x40, 0x46, 0xef, 0xf7, 0x54, 0xb9, 0x00, 0x21, 0x58, 0x46, + 0xef, 0xf7, 0x50, 0xb9, 0x10, 0x21, 0x40, 0xf2, 0x43, 0x60, 0xef, 0xf7, + 0x4b, 0xb9, 0x00, 0x22, 0x01, 0x21, 0x40, 0xf6, 0x87, 0x50, 0xef, 0xf7, + 0x4f, 0xb9, 0x00, 0x00, 0x2d, 0xe9, 0xf0, 0x4f, 0x00, 0xf1, 0x58, 0x06, + 0x83, 0xb0, 0x00, 0xf1, 0x08, 0x05, 0x30, 0x78, 0x0c, 0x46, 0x60, 0xb1, + 0xf1, 0x78, 0xb0, 0x78, 0x22, 0x46, 0xf0, 0xf7, 0x44, 0xff, 0x30, 0xb9, + 0x01, 0x20, 0x68, 0x64, 0x28, 0x64, 0xe8, 0x68, 0x40, 0xf0, 0x02, 0x00, + 0xe8, 0x60, 0x00, 0x2c, 0xc4, 0xf1, 0x00, 0x0b, 0x4f, 0xf0, 0x82, 0x40, + 0x4f, 0xf0, 0x01, 0x0a, 0x04, 0xd5, 0x0a, 0xfa, 0x0b, 0xf1, 0x01, 0x60, + 0x00, 0x21, 0x03, 0xe0, 0x00, 0x21, 0x01, 0x60, 0x0a, 0xfa, 0x04, 0xf1, + 0x41, 0x60, 0x68, 0x6c, 0x00, 0x28, 0x71, 0xd1, 0x70, 0x78, 0x00, 0x21, + 0xf0, 0xf7, 0xef, 0xff, 0x00, 0x28, 0x5f, 0xd1, 0x6a, 0x46, 0x01, 0xa9, + 0x20, 0x46, 0xf1, 0xf7, 0x35, 0xf8, 0xd6, 0xe9, 0x02, 0x23, 0x01, 0x98, + 0x12, 0xeb, 0x00, 0x08, 0x43, 0xeb, 0xe0, 0x79, 0xc6, 0xe9, 0x02, 0x89, + 0xd6, 0xe9, 0x04, 0x23, 0x00, 0x98, 0xc1, 0x17, 0x10, 0x18, 0x59, 0x41, + 0xc6, 0xe9, 0x04, 0x01, 0x72, 0x68, 0x52, 0x1c, 0x72, 0x60, 0x2b, 0x68, + 0x5b, 0x88, 0x9a, 0x42, 0xd9, 0xd3, 0x6f, 0x68, 0x00, 0x2c, 0x1d, 0xd4, + 0xa3, 0x46, 0x77, 0xb1, 0x00, 0x23, 0xf3, 0xf7, 0xf9, 0xfa, 0x07, 0xeb, + 0x8b, 0x01, 0x00, 0x23, 0xc1, 0xf8, 0xc0, 0x00, 0x40, 0x46, 0x72, 0x68, + 0x49, 0x46, 0xf3, 0xf7, 0xef, 0xfa, 0x47, 0xf8, 0x2b, 0x00, 0xac, 0x61, + 0xc5, 0xe9, 0x08, 0x89, 0xd6, 0xe9, 0x04, 0x01, 0xc5, 0xe9, 0x0a, 0x01, + 0xe8, 0x6c, 0x0a, 0xfa, 0x0b, 0xf1, 0x88, 0x43, 0xe8, 0x64, 0x1a, 0xe0, + 0x6f, 0xb1, 0x00, 0x23, 0x07, 0xeb, 0x8b, 0x07, 0xf3, 0xf7, 0xda, 0xfa, + 0xc7, 0xf8, 0x20, 0x01, 0x40, 0x46, 0x72, 0x68, 0x49, 0x46, 0x00, 0x23, + 0xf3, 0xf7, 0xd2, 0xfa, 0x38, 0x66, 0xec, 0x61, 0xc5, 0xe9, 0x0c, 0x89, + 0xd6, 0xe9, 0x04, 0x01, 0xc5, 0xe9, 0x0e, 0x01, 0xa8, 0x6c, 0x0a, 0xfa, + 0x0b, 0xf1, 0x88, 0x43, 0xa8, 0x64, 0x00, 0x20, 0x70, 0x60, 0xc6, 0xe9, + 0x04, 0x00, 0xc6, 0xe9, 0x02, 0x00, 0x0b, 0xe0, 0x01, 0x28, 0x08, 0xbf, + 0x68, 0x64, 0x07, 0xd0, 0xe8, 0x68, 0xc5, 0xf8, 0x44, 0xa0, 0x40, 0xf0, + 0x04, 0x00, 0xc5, 0xf8, 0x40, 0xa0, 0xe8, 0x60, 0xbd, 0xe8, 0xf7, 0x8f, + 0x2d, 0xe9, 0xfe, 0x4f, 0x04, 0x46, 0xdf, 0xf8, 0x90, 0x13, 0x20, 0x78, + 0xdf, 0xf8, 0x8c, 0x53, 0x00, 0xf0, 0x01, 0x00, 0x00, 0x90, 0x00, 0x20, + 0x60, 0x61, 0x60, 0x78, 0x01, 0x28, 0x04, 0xd1, 0xd1, 0xe9, 0x08, 0x6b, + 0x2b, 0x6c, 0xaa, 0x69, 0x03, 0xe0, 0xd1, 0xe9, 0x06, 0x6b, 0xeb, 0x6a, + 0x6a, 0x6b, 0xa1, 0x68, 0x0f, 0x88, 0x39, 0x0a, 0x01, 0xf0, 0x03, 0x0a, + 0x01, 0x28, 0x08, 0xbf, 0x4f, 0xf0, 0x00, 0x0a, 0x09, 0xd0, 0x00, 0x21, + 0x8b, 0x45, 0xd5, 0x48, 0x05, 0xd8, 0x86, 0x42, 0x3c, 0xbf, 0xba, 0xf1, + 0x03, 0x0f, 0x4f, 0xf0, 0x03, 0x0a, 0x4f, 0xf6, 0xff, 0x40, 0x38, 0x40, + 0x40, 0xea, 0x0a, 0x20, 0xad, 0xf8, 0x0a, 0x00, 0x28, 0x68, 0xb0, 0xeb, + 0x83, 0x0f, 0x39, 0xd3, 0x60, 0x68, 0x01, 0x89, 0xad, 0xf8, 0x04, 0x10, + 0x4f, 0xf0, 0x01, 0x09, 0x40, 0x89, 0xad, 0xf8, 0x06, 0x00, 0x4f, 0xf0, + 0x00, 0x0c, 0x01, 0xa8, 0x4f, 0xf4, 0x7a, 0x78, 0x30, 0xf8, 0x1c, 0x50, + 0xa8, 0x05, 0x80, 0x0d, 0xb3, 0xfb, 0xf8, 0xf8, 0xc5, 0xf3, 0x81, 0x21, + 0x08, 0xfb, 0x00, 0xf7, 0x21, 0xb9, 0x4f, 0xf4, 0x7a, 0x70, 0xb7, 0xfb, + 0xf0, 0xf0, 0x07, 0xe0, 0x01, 0x29, 0x05, 0xd1, 0xbc, 0x48, 0xa0, 0xfb, + 0x07, 0x01, 0xc0, 0x0f, 0x40, 0xea, 0x41, 0x00, 0xb0, 0xf5, 0x80, 0x6f, + 0x02, 0xd3, 0xc4, 0xf8, 0x14, 0x90, 0x64, 0xe1, 0x05, 0xf4, 0x70, 0x41, + 0x08, 0x43, 0x01, 0xa9, 0x40, 0xf4, 0x00, 0x60, 0x21, 0xf8, 0x1c, 0x00, + 0x0c, 0xf1, 0x01, 0x0c, 0xbc, 0xf1, 0x02, 0x0f, 0xd1, 0xd3, 0x01, 0xe0, + 0x4f, 0xf0, 0x00, 0x09, 0x19, 0x46, 0x10, 0x46, 0xfe, 0xf7, 0x76, 0xf9, + 0x05, 0x28, 0x38, 0xbf, 0x04, 0x20, 0x01, 0x21, 0x40, 0x1c, 0x01, 0xfa, + 0x00, 0xf0, 0x61, 0x68, 0x0a, 0x68, 0x49, 0x68, 0x40, 0x1e, 0x02, 0x40, + 0x08, 0x40, 0xa1, 0x78, 0xa2, 0x61, 0x22, 0x65, 0xe0, 0x61, 0x60, 0x65, + 0x00, 0x29, 0x18, 0xbf, 0x01, 0x29, 0x04, 0xf1, 0x58, 0x00, 0x28, 0xd1, + 0x01, 0x21, 0x01, 0x70, 0xa1, 0x78, 0x01, 0x29, 0x08, 0xbf, 0x04, 0x21, + 0x04, 0xd0, 0x00, 0x99, 0x00, 0x29, 0x0c, 0xbf, 0x01, 0x21, 0x02, 0x21, + 0xc1, 0x70, 0x61, 0x78, 0x09, 0xb9, 0x81, 0x70, 0x1a, 0xe0, 0x01, 0x21, + 0x81, 0x70, 0x02, 0x21, 0x41, 0x70, 0x00, 0x21, 0xa1, 0x64, 0xc0, 0xe9, + 0x02, 0x11, 0xc0, 0xe9, 0x04, 0x11, 0x41, 0x60, 0x30, 0x46, 0x59, 0x46, + 0xf1, 0xf7, 0x52, 0xfc, 0x8d, 0xf8, 0x08, 0x00, 0x04, 0xf1, 0x7a, 0x06, + 0xdf, 0xf8, 0x3c, 0x82, 0x40, 0xf6, 0x41, 0x4b, 0x21, 0xe0, 0x61, 0x78, + 0x00, 0x29, 0xe6, 0xd1, 0x00, 0x99, 0xe5, 0xe7, 0xee, 0xf7, 0xe4, 0xff, + 0xf1, 0x78, 0x40, 0xf2, 0x35, 0x40, 0xee, 0xf7, 0xdf, 0xff, 0x31, 0x79, + 0x40, 0xf2, 0x36, 0x40, 0xee, 0xf7, 0xda, 0xff, 0xb1, 0x78, 0x40, 0xf2, + 0x33, 0x40, 0xee, 0xf7, 0xd5, 0xff, 0x71, 0x78, 0x40, 0xf2, 0x2e, 0x40, + 0xee, 0xf7, 0xd0, 0xff, 0x00, 0xf0, 0x08, 0xf9, 0xee, 0xf7, 0xea, 0xff, + 0x00, 0x20, 0xef, 0xf7, 0x7b, 0xfa, 0xa1, 0x6c, 0x20, 0x6d, 0x00, 0x29, + 0x40, 0xf0, 0xe2, 0x80, 0x00, 0x28, 0x04, 0xbf, 0x60, 0x6d, 0x00, 0x28, + 0x00, 0xf0, 0xe1, 0x80, 0x00, 0x20, 0xe0, 0x64, 0xef, 0xf7, 0x0f, 0xfa, + 0x00, 0xf0, 0xf2, 0xf8, 0xee, 0xf7, 0xe7, 0xff, 0x73, 0x48, 0x00, 0x78, + 0x30, 0x70, 0x04, 0xf1, 0x70, 0x00, 0xf1, 0xf7, 0x5c, 0xfc, 0x60, 0x78, + 0x01, 0x28, 0x0c, 0xbf, 0x02, 0x21, 0x03, 0x21, 0x00, 0x98, 0xc0, 0xb2, + 0xf1, 0xf7, 0x54, 0xfb, 0x00, 0x98, 0x9d, 0xf8, 0x08, 0x10, 0xc0, 0xb2, + 0xf1, 0xf7, 0x1c, 0xfc, 0x50, 0x46, 0xf1, 0xf7, 0x21, 0xfc, 0x00, 0x98, + 0x03, 0x21, 0xc0, 0xb2, 0xf1, 0xf7, 0x2f, 0xfc, 0x00, 0x98, 0x3f, 0x21, + 0xc0, 0xb2, 0xf1, 0xf7, 0x35, 0xfc, 0xf1, 0xf7, 0x98, 0xfb, 0xf1, 0xf7, + 0x7a, 0xfb, 0x60, 0x78, 0x01, 0x28, 0x0b, 0xd1, 0x60, 0x68, 0x00, 0x7d, + 0x20, 0xb1, 0xc0, 0x22, 0xc0, 0x21, 0x58, 0x46, 0xf1, 0xf7, 0x60, 0xf9, + 0xff, 0x20, 0x60, 0x74, 0x04, 0x20, 0x5f, 0xe0, 0x98, 0xf8, 0x00, 0x00, + 0x70, 0x70, 0x98, 0xf8, 0x05, 0x00, 0xb0, 0x70, 0x00, 0xf0, 0xfc, 0x01, + 0x40, 0xf2, 0x33, 0x40, 0xee, 0xf7, 0x74, 0xff, 0x70, 0x78, 0x00, 0xf0, + 0xf0, 0x01, 0x40, 0xf2, 0x2e, 0x40, 0xee, 0xf7, 0x6d, 0xff, 0x98, 0xf8, + 0x07, 0x00, 0xf0, 0x70, 0x98, 0xf8, 0x08, 0x00, 0x30, 0x71, 0x00, 0x20, + 0xf8, 0xf7, 0x10, 0xfc, 0x00, 0x23, 0x99, 0x42, 0x4a, 0x4a, 0x05, 0xd8, + 0x90, 0x42, 0x03, 0xd2, 0x49, 0x48, 0x90, 0xf9, 0x1d, 0x50, 0x02, 0xe0, + 0x47, 0x48, 0x90, 0xf9, 0x24, 0x50, 0x60, 0x68, 0x00, 0x99, 0x00, 0x7d, + 0xc9, 0xb9, 0x20, 0xb1, 0x0c, 0x22, 0x0c, 0x21, 0x58, 0x46, 0xee, 0xf7, + 0x57, 0xff, 0xf0, 0x78, 0x60, 0x74, 0xff, 0x27, 0xf9, 0xb2, 0x00, 0x20, + 0xee, 0xf7, 0xf9, 0xff, 0x85, 0x42, 0x06, 0xdb, 0x67, 0x74, 0xf9, 0xb2, + 0x40, 0xf2, 0x35, 0x40, 0xee, 0xf7, 0x3e, 0xff, 0x01, 0xe0, 0x7f, 0x1e, + 0xf0, 0xd5, 0x00, 0x20, 0x18, 0xe0, 0x20, 0xb1, 0x30, 0x22, 0x30, 0x21, + 0x58, 0x46, 0xee, 0xf7, 0x3d, 0xff, 0x30, 0x79, 0x60, 0x74, 0xff, 0x27, + 0xf9, 0xb2, 0x01, 0x20, 0xee, 0xf7, 0xdf, 0xff, 0x85, 0x42, 0x06, 0xdb, + 0x67, 0x74, 0xf9, 0xb2, 0x40, 0xf2, 0x36, 0x40, 0xee, 0xf7, 0x24, 0xff, + 0x01, 0xe0, 0x7f, 0x1e, 0xf0, 0xd5, 0x01, 0x20, 0xee, 0xf7, 0xca, 0xff, + 0x20, 0x74, 0x60, 0x68, 0xf0, 0xf7, 0x8c, 0xfd, 0xbd, 0xf8, 0x0a, 0x00, + 0xf0, 0xf7, 0x84, 0xfd, 0xb9, 0xf1, 0x00, 0x0f, 0x06, 0xd0, 0xbd, 0xf8, + 0x04, 0x00, 0x24, 0x49, 0x08, 0x80, 0xbd, 0xf8, 0x06, 0x00, 0x48, 0x80, + 0x01, 0x25, 0x07, 0xe0, 0x60, 0x6d, 0xe8, 0x40, 0xc0, 0x07, 0x08, 0xd5, + 0x29, 0x46, 0x20, 0x46, 0xff, 0xf7, 0xbe, 0xfd, 0xe0, 0x6c, 0x00, 0x28, + 0xf4, 0xd0, 0xe0, 0x6c, 0x40, 0xb9, 0x20, 0x6d, 0xe8, 0x40, 0xc0, 0x07, + 0x04, 0xd5, 0x69, 0x42, 0x20, 0x46, 0xff, 0xf7, 0xb1, 0xfd, 0xf4, 0xe7, + 0x6d, 0x1c, 0x18, 0x2d, 0xee, 0xd3, 0xf0, 0xf7, 0xc1, 0xfd, 0x04, 0xf1, + 0x70, 0x00, 0xf1, 0xf7, 0xa5, 0xfb, 0x60, 0x78, 0x31, 0x78, 0x01, 0x28, + 0x58, 0x46, 0x7f, 0xf4, 0xff, 0xae, 0xf1, 0xf7, 0x98, 0xf8, 0x11, 0xe7, + 0x00, 0x28, 0x04, 0xbf, 0x60, 0x6d, 0x00, 0x28, 0x01, 0xd1, 0x01, 0x20, + 0x00, 0xe0, 0x00, 0x20, 0xbd, 0xe8, 0xfe, 0x8f, 0x00, 0xf2, 0x00, 0x20, + 0x78, 0x29, 0x00, 0x20, 0x00, 0x9c, 0xe4, 0xa6, 0x98, 0x6e, 0x12, 0x83, + 0x2e, 0x04, 0x00, 0x46, 0x41, 0x0c, 0x00, 0x46, 0x00, 0x28, 0x6b, 0xee, + 0xdc, 0x29, 0x00, 0x20, 0x08, 0x00, 0x00, 0x41, 0x02, 0x22, 0x04, 0xf1, + 0x78, 0x01, 0x0f, 0xf2, 0x1c, 0x00, 0x70, 0x47, 0x00, 0x29, 0x18, 0xbf, + 0x01, 0x29, 0x05, 0xd1, 0x01, 0x00, 0x18, 0xbf, 0x01, 0x21, 0x08, 0x46, + 0xf0, 0xf7, 0x7e, 0xbc, 0x70, 0x47, 0x00, 0x00, 0x82, 0x01, 0x0b, 0x02, + 0x38, 0xb5, 0x04, 0x46, 0x0d, 0x46, 0xf1, 0xf7, 0x7e, 0xfc, 0x20, 0x68, + 0xf1, 0xf7, 0x77, 0xfc, 0x28, 0x46, 0xbd, 0xe8, 0x32, 0x40, 0xf1, 0xf7, + 0x7d, 0xbc, 0x2d, 0xe9, 0xf0, 0x41, 0x0d, 0x46, 0x04, 0x46, 0x00, 0x26, + 0x05, 0xf5, 0x98, 0x77, 0x05, 0xf5, 0x90, 0x78, 0x64, 0x42, 0x28, 0x68, + 0x21, 0xb2, 0x00, 0xf0, 0x7a, 0xfa, 0xf1, 0xf7, 0x0a, 0xfc, 0xf1, 0xf7, + 0x24, 0xfc, 0x08, 0xb1, 0x04, 0x26, 0x17, 0xe0, 0xf9, 0x68, 0xa8, 0x68, + 0xf1, 0xf7, 0xe0, 0xfd, 0xa8, 0x68, 0x41, 0x46, 0x00, 0xf0, 0xa1, 0xfa, + 0x69, 0x68, 0xdf, 0xf8, 0x44, 0x04, 0xf2, 0xf7, 0x41, 0xfd, 0x01, 0x46, + 0x38, 0x68, 0xf2, 0xf7, 0x45, 0xfe, 0xe1, 0xd8, 0x28, 0x68, 0x05, 0xf5, + 0x9a, 0x72, 0x41, 0x46, 0x00, 0xf0, 0x32, 0xfb, 0xa8, 0x68, 0x00, 0xf0, + 0x8b, 0xfa, 0x30, 0x46, 0xbd, 0xe8, 0xf0, 0x81, 0x2d, 0xe9, 0xf8, 0x4f, + 0x04, 0x46, 0x80, 0x25, 0xb4, 0xf9, 0x18, 0x61, 0x31, 0x00, 0x48, 0xbf, + 0x49, 0x42, 0x80, 0x29, 0x4f, 0xf0, 0x00, 0x0a, 0x4f, 0xf0, 0x04, 0x08, + 0x04, 0xda, 0x00, 0x2e, 0x46, 0xbf, 0x75, 0x42, 0x2d, 0xb2, 0x35, 0x46, + 0x77, 0x1b, 0x3f, 0xb2, 0xd1, 0x46, 0x5f, 0xea, 0xc9, 0x70, 0x52, 0xbf, + 0x07, 0xeb, 0x45, 0x07, 0x3f, 0xb2, 0xa7, 0xeb, 0x45, 0x07, 0x20, 0x68, + 0x3a, 0xb2, 0x00, 0x21, 0xf1, 0xf7, 0x74, 0xfb, 0x21, 0x46, 0x40, 0x46, + 0xff, 0xf7, 0xa5, 0xff, 0x5f, 0xea, 0x00, 0x0b, 0x16, 0xd1, 0x04, 0xf5, + 0x8c, 0x70, 0x00, 0x21, 0xc2, 0x69, 0x10, 0x46, 0xf2, 0xf7, 0xec, 0xfc, + 0x38, 0xbf, 0x82, 0xf0, 0x00, 0x42, 0x50, 0x46, 0x11, 0x46, 0xf2, 0xf7, + 0xe5, 0xfc, 0x38, 0xbf, 0x92, 0x46, 0x09, 0xf1, 0x01, 0x09, 0xb9, 0xf1, + 0x04, 0x0f, 0x4f, 0xf0, 0x00, 0x08, 0xd4, 0xd3, 0x20, 0x68, 0x32, 0x46, + 0x00, 0x21, 0xf1, 0xf7, 0x51, 0xfb, 0xbb, 0xf1, 0x00, 0x0f, 0x14, 0xd1, + 0x28, 0x46, 0xf2, 0xf7, 0x3b, 0xfb, 0x51, 0x46, 0xf2, 0xf7, 0x52, 0xfb, + 0xdf, 0x49, 0xf2, 0xf7, 0xcb, 0xfc, 0x38, 0xbf, 0x08, 0x46, 0x04, 0xd3, + 0xdd, 0x49, 0xf2, 0xf7, 0xdf, 0xfd, 0x98, 0xbf, 0xdc, 0x48, 0x01, 0x46, + 0x20, 0x68, 0x00, 0xf0, 0xc4, 0xfa, 0x58, 0x46, 0xbd, 0xe8, 0xf2, 0x8f, + 0x2d, 0xe9, 0xf0, 0x47, 0x05, 0x46, 0x8a, 0x46, 0x17, 0x46, 0x4f, 0xf0, + 0x00, 0x09, 0x4f, 0xf0, 0x06, 0x08, 0x05, 0xf5, 0x8e, 0x74, 0x38, 0x68, + 0x41, 0x42, 0x39, 0x60, 0x09, 0xb2, 0x28, 0x68, 0x00, 0xf0, 0xe1, 0xf9, + 0xf1, 0xf7, 0x71, 0xfb, 0xf1, 0xf7, 0x8b, 0xfb, 0x10, 0xb1, 0x4f, 0xf0, + 0x04, 0x09, 0x28, 0xe0, 0x21, 0x6a, 0xa8, 0x68, 0xf1, 0xf7, 0x46, 0xfd, + 0x39, 0x68, 0xa8, 0x68, 0x05, 0xf5, 0x90, 0x72, 0x00, 0xf0, 0x14, 0xfb, + 0x21, 0x68, 0x08, 0x1a, 0x20, 0x60, 0x81, 0x11, 0x00, 0xeb, 0x51, 0x60, + 0x46, 0x02, 0x36, 0x14, 0x30, 0x46, 0x48, 0xbf, 0x40, 0x42, 0x7f, 0x28, + 0x04, 0xdb, 0x01, 0x2e, 0xac, 0xbf, 0x7f, 0x26, 0x6f, 0xf0, 0x7e, 0x06, + 0x28, 0x68, 0x32, 0x46, 0x02, 0x21, 0xf1, 0xf7, 0xfb, 0xfa, 0xa8, 0x68, + 0x00, 0xf0, 0xe8, 0xf9, 0xb8, 0xf1, 0x01, 0x08, 0xc9, 0xd1, 0xaa, 0xf8, + 0x00, 0x61, 0x48, 0x46, 0xbd, 0xe8, 0xf0, 0x87, 0x2d, 0xe9, 0xf0, 0x4f, + 0x04, 0x46, 0x8f, 0xb0, 0x20, 0x68, 0x02, 0x90, 0x88, 0x46, 0xf9, 0xf7, + 0x91, 0xfb, 0xb2, 0x4a, 0x06, 0x90, 0xd2, 0xe9, 0x08, 0x01, 0x27, 0x69, + 0xb0, 0x4a, 0x00, 0x23, 0xf2, 0xf7, 0xe6, 0xff, 0x39, 0x8b, 0x00, 0x26, + 0x80, 0xb2, 0x88, 0x42, 0x34, 0xbf, 0xb8, 0x7c, 0xb8, 0x7e, 0x8d, 0xf8, + 0x04, 0x00, 0xaa, 0x49, 0xb7, 0xf9, 0x0e, 0x00, 0x81, 0xfb, 0x00, 0x01, + 0x00, 0xf0, 0xa5, 0xf9, 0x05, 0x90, 0x04, 0xf5, 0x8a, 0x77, 0x02, 0x98, + 0xc0, 0xf1, 0x01, 0x00, 0x38, 0x70, 0xc0, 0xb2, 0x00, 0xf0, 0x86, 0xfc, + 0x78, 0x80, 0x00, 0x21, 0x00, 0x20, 0xee, 0xf7, 0xee, 0xff, 0x3a, 0x78, + 0x79, 0x88, 0x04, 0xf1, 0x14, 0x00, 0x00, 0xf0, 0xfa, 0xfb, 0x38, 0x78, + 0x00, 0xf0, 0x50, 0xfc, 0x20, 0xb1, 0x00, 0x20, 0xef, 0xf7, 0x3e, 0xf8, + 0x05, 0x20, 0x22, 0xe1, 0x02, 0x98, 0x0b, 0xa9, 0xf1, 0xf7, 0x82, 0xfd, + 0x40, 0xf2, 0xee, 0x20, 0xb8, 0x80, 0xfe, 0x80, 0xbe, 0x60, 0x02, 0x98, + 0xf1, 0xf7, 0x70, 0xfa, 0xa0, 0x68, 0x00, 0xf0, 0x91, 0xf9, 0x02, 0x98, + 0x09, 0xa9, 0xf2, 0xf7, 0xc1, 0xfe, 0xdd, 0xe9, 0x09, 0x01, 0xcd, 0xe9, + 0x07, 0x01, 0x8d, 0xf8, 0x1e, 0x60, 0x07, 0xaa, 0x02, 0x98, 0x02, 0x21, + 0xf2, 0xf7, 0xed, 0xfe, 0xe2, 0x68, 0x12, 0x78, 0x02, 0x99, 0x20, 0x69, + 0x52, 0x1e, 0x12, 0x04, 0x02, 0xf4, 0xfe, 0x02, 0x42, 0xea, 0x81, 0x71, + 0x9d, 0xf8, 0x04, 0x20, 0xd2, 0x05, 0x02, 0xf0, 0x7e, 0x52, 0x11, 0x43, + 0x82, 0x7d, 0xd2, 0x03, 0x02, 0xf4, 0x00, 0x42, 0x11, 0x43, 0x02, 0x7d, + 0x02, 0xf0, 0x07, 0x02, 0x11, 0x43, 0x41, 0xf0, 0x00, 0x41, 0x41, 0xf4, + 0x80, 0x41, 0x04, 0x91, 0x85, 0x78, 0x00, 0xe0, 0x6d, 0x1c, 0x20, 0x69, + 0xc1, 0x78, 0xa9, 0x42, 0xc0, 0xf0, 0x83, 0x80, 0x28, 0x18, 0x01, 0x79, + 0x03, 0x91, 0x06, 0x99, 0x03, 0x29, 0x07, 0xd1, 0x03, 0x98, 0x1b, 0x28, + 0x34, 0xbf, 0xc0, 0xf1, 0x64, 0x09, 0x4f, 0xf0, 0x32, 0x09, 0x01, 0xe0, + 0x90, 0xf8, 0x1b, 0x90, 0x03, 0x9a, 0x02, 0x98, 0x5f, 0xfa, 0x89, 0xf1, + 0xf2, 0xf7, 0xe8, 0xfe, 0x9d, 0xf8, 0x04, 0x10, 0x04, 0xa8, 0xff, 0xf7, + 0x79, 0xfe, 0xb8, 0x62, 0xe0, 0x68, 0x40, 0x78, 0xf1, 0xf7, 0x16, 0xfb, + 0x01, 0x2d, 0x03, 0xd1, 0x20, 0x46, 0xff, 0xf7, 0xaf, 0xfe, 0x06, 0x46, + 0x4f, 0xf0, 0x04, 0x0a, 0x86, 0xbb, 0x21, 0x46, 0x04, 0x20, 0xff, 0xf7, + 0x74, 0xfe, 0x06, 0x00, 0x2a, 0xd1, 0x78, 0x6a, 0x5e, 0x49, 0xf2, 0xf7, + 0xd1, 0xfb, 0x78, 0x62, 0x5c, 0x49, 0x38, 0x6a, 0xf2, 0xf7, 0xcc, 0xfb, + 0x83, 0x46, 0xf8, 0x88, 0xc7, 0xf8, 0x20, 0xb0, 0x00, 0x90, 0x78, 0x6a, + 0xf2, 0xf7, 0x30, 0xfc, 0x00, 0x99, 0x40, 0x18, 0xf8, 0x80, 0xb8, 0x88, + 0x00, 0x90, 0x58, 0x46, 0xf2, 0xf7, 0x28, 0xfc, 0x00, 0x99, 0x42, 0x18, + 0xba, 0x80, 0x12, 0xb2, 0x02, 0x98, 0x00, 0x21, 0xf1, 0xf7, 0x1c, 0xfa, + 0xb7, 0xf9, 0x06, 0x20, 0x02, 0x98, 0x01, 0x21, 0xf1, 0xf7, 0x16, 0xfa, + 0xba, 0xf1, 0x01, 0x0a, 0xcf, 0xd1, 0x00, 0xe0, 0x3e, 0xbb, 0x20, 0x69, + 0xb9, 0x88, 0x28, 0x18, 0x04, 0x2d, 0x00, 0x79, 0x28, 0xf8, 0x10, 0x10, + 0x08, 0xeb, 0x40, 0x00, 0xf9, 0x88, 0xa0, 0xf8, 0x80, 0x10, 0x91, 0xd2, + 0x0f, 0xf2, 0x0c, 0x10, 0x28, 0x5c, 0x03, 0x9a, 0x00, 0xeb, 0x09, 0x01, + 0x02, 0x98, 0xd2, 0xb2, 0xc9, 0xb2, 0xf2, 0xf7, 0x8b, 0xfe, 0x9d, 0xf8, + 0x04, 0x00, 0x29, 0x18, 0xc9, 0xb2, 0x04, 0xa8, 0xff, 0xf7, 0x1a, 0xfe, + 0xb8, 0x62, 0x05, 0xaa, 0x41, 0x46, 0x20, 0x46, 0xff, 0xf7, 0xb6, 0xfe, + 0x06, 0x00, 0x3f, 0xf4, 0x77, 0xaf, 0x00, 0xf0, 0x6d, 0xf8, 0x20, 0x69, + 0x80, 0x78, 0x45, 0x1c, 0x10, 0xe0, 0x28, 0x18, 0x90, 0xf8, 0x04, 0x90, + 0x90, 0xf8, 0x05, 0xa0, 0x52, 0x46, 0x49, 0x46, 0x40, 0x46, 0x00, 0xf0, + 0xc2, 0xfa, 0x52, 0x46, 0x49, 0x46, 0x08, 0xf1, 0x80, 0x00, 0x00, 0xf0, + 0xbc, 0xfa, 0x6d, 0x1c, 0x20, 0x69, 0xc1, 0x78, 0x8d, 0x42, 0xea, 0xd3, + 0x81, 0x78, 0x09, 0x18, 0x00, 0x22, 0x49, 0x79, 0x0c, 0xe0, 0x38, 0xf8, + 0x11, 0x30, 0x28, 0xf8, 0x12, 0x30, 0x08, 0xeb, 0x42, 0x05, 0x08, 0xeb, + 0x41, 0x03, 0x52, 0x1c, 0xb3, 0xf8, 0x80, 0x30, 0xa5, 0xf8, 0x80, 0x30, + 0x8a, 0x42, 0xf0, 0xdb, 0xc1, 0x78, 0x08, 0x18, 0x00, 0x79, 0x41, 0x1c, + 0x0c, 0xe0, 0x38, 0xf8, 0x10, 0x20, 0x28, 0xf8, 0x11, 0x20, 0x08, 0xeb, + 0x41, 0x03, 0x08, 0xeb, 0x40, 0x02, 0x49, 0x1c, 0xb2, 0xf8, 0x80, 0x20, + 0xa3, 0xf8, 0x80, 0x20, 0x40, 0x29, 0xf0, 0xdb, 0x02, 0x98, 0x09, 0xa9, + 0xf2, 0xf7, 0xe6, 0xfd, 0x02, 0x98, 0x0b, 0xa9, 0xf1, 0xf7, 0x8a, 0xfc, + 0x3a, 0x78, 0x79, 0x88, 0x04, 0xf1, 0x14, 0x00, 0x00, 0xf0, 0xff, 0xfa, + 0x08, 0xb1, 0x06, 0xb9, 0x05, 0x26, 0x00, 0x20, 0xee, 0xf7, 0x1e, 0xff, + 0x02, 0x98, 0x41, 0x46, 0x00, 0xf0, 0x27, 0xfa, 0x30, 0x46, 0x0f, 0xb0, + 0xbd, 0xe8, 0xf0, 0x8f, 0xb7, 0x43, 0xba, 0x51, 0xcd, 0xcc, 0xcc, 0x3e, + 0x01, 0x00, 0x20, 0x40, 0x00, 0x00, 0x20, 0x40, 0x00, 0xf2, 0x00, 0x20, + 0x40, 0x42, 0x0f, 0x00, 0x66, 0x66, 0x26, 0x3f, 0x00, 0x00, 0x0a, 0x1c, + 0x00, 0x21, 0x4f, 0xf4, 0x44, 0x60, 0xee, 0xf7, 0x4f, 0xbc, 0x80, 0xb5, + 0x80, 0x21, 0x4f, 0xf4, 0x44, 0x60, 0xee, 0xf7, 0x49, 0xfc, 0xbd, 0xe8, + 0x02, 0x40, 0x28, 0x20, 0xf2, 0xf7, 0x88, 0xb8, 0x70, 0xb5, 0x0d, 0x46, + 0x04, 0x46, 0x2e, 0x12, 0x00, 0x2c, 0x0c, 0xbf, 0x31, 0x46, 0x00, 0x21, + 0xc9, 0xb2, 0x40, 0xf6, 0xcb, 0x10, 0xee, 0xf7, 0x37, 0xfc, 0x00, 0x2c, + 0x0c, 0xbf, 0x29, 0x46, 0x00, 0x21, 0xc9, 0xb2, 0x40, 0xf6, 0xcc, 0x10, + 0xee, 0xf7, 0x2e, 0xfc, 0x04, 0xb9, 0x00, 0x26, 0xf1, 0xb2, 0x40, 0xf6, + 0xcd, 0x10, 0xee, 0xf7, 0x27, 0xfc, 0x04, 0xb9, 0x00, 0x25, 0xe9, 0xb2, + 0x40, 0xf6, 0xce, 0x10, 0xee, 0xf7, 0x20, 0xfc, 0xbd, 0xe8, 0x70, 0x40, + 0xcd, 0xe7, 0x31, 0xb1, 0xc9, 0x03, 0xc0, 0x22, 0x91, 0xfb, 0xf2, 0xf1, + 0xc1, 0xf5, 0x80, 0x31, 0xd0, 0xe7, 0x70, 0x47, 0x10, 0xb5, 0x04, 0x46, + 0x1b, 0x04, 0x43, 0xea, 0x12, 0x41, 0x10, 0x04, 0x0d, 0x4a, 0x52, 0x69, + 0x00, 0x23, 0xf2, 0xf7, 0x15, 0xfe, 0xc0, 0xf5, 0x80, 0x31, 0x20, 0x46, + 0xbd, 0xe8, 0x10, 0x40, 0xbe, 0xe7, 0x10, 0xb5, 0x4f, 0xf4, 0xc0, 0x74, + 0xa4, 0xfb, 0x00, 0x23, 0x10, 0x46, 0x05, 0x4a, 0x52, 0x69, 0x04, 0xfb, + 0x01, 0x33, 0x19, 0x46, 0x00, 0x23, 0xf2, 0xf7, 0x01, 0xfe, 0x00, 0xb2, + 0x10, 0xbd, 0x00, 0x00, 0x78, 0x29, 0x00, 0x20, 0xef, 0xf3, 0x11, 0x80, + 0x60, 0x21, 0x81, 0xf3, 0x11, 0x88, 0x70, 0x47, 0x50, 0x21, 0xee, 0xf7, + 0xa9, 0xbb, 0x2d, 0xe9, 0xf0, 0x41, 0x00, 0xf1, 0x34, 0x05, 0x0c, 0x46, + 0xd5, 0xf8, 0x04, 0x80, 0xaf, 0x68, 0x28, 0x68, 0x00, 0xf0, 0x98, 0xf9, + 0x06, 0x46, 0x00, 0xf0, 0x91, 0xf9, 0x01, 0x46, 0x30, 0x46, 0xf2, 0xf7, + 0x83, 0xf9, 0x06, 0x46, 0x31, 0x46, 0xf2, 0xf7, 0x8f, 0xfa, 0xba, 0x49, + 0xf2, 0xf7, 0x94, 0xfb, 0x4c, 0xd8, 0xe8, 0x68, 0x00, 0xf0, 0x86, 0xf9, + 0x80, 0x46, 0x68, 0x69, 0x00, 0xf0, 0x7f, 0xf9, 0x01, 0x46, 0x40, 0x46, + 0xf2, 0xf7, 0x70, 0xf9, 0x00, 0xf0, 0x48, 0xf8, 0x20, 0x60, 0x29, 0x69, + 0x68, 0x68, 0xf2, 0xf7, 0x79, 0xfa, 0x07, 0x46, 0xa9, 0x69, 0xa8, 0x68, + 0xf2, 0xf7, 0x74, 0xfa, 0x00, 0xf0, 0xd8, 0xf8, 0x00, 0xf0, 0x3a, 0xf8, + 0x60, 0x60, 0x69, 0x69, 0x28, 0x68, 0xf2, 0xf7, 0x6b, 0xfa, 0x07, 0x46, + 0xe9, 0x68, 0xa8, 0x68, 0xf2, 0xf7, 0x66, 0xfa, 0x00, 0xf0, 0xca, 0xf8, + 0x00, 0xf0, 0x2c, 0xf8, 0xa0, 0x60, 0xa9, 0x69, 0x28, 0x68, 0xf2, 0xf7, + 0x5d, 0xfa, 0x07, 0x46, 0x29, 0x69, 0xa8, 0x68, 0xf2, 0xf7, 0x58, 0xfa, + 0x00, 0xf0, 0xbc, 0xf8, 0x00, 0xf0, 0x1e, 0xf8, 0xe0, 0x60, 0x66, 0x68, + 0x27, 0x68, 0x29, 0x68, 0x68, 0x68, 0xf2, 0xf7, 0xb1, 0xf9, 0x05, 0x46, + 0x00, 0xf0, 0x44, 0xf9, 0x07, 0x46, 0x30, 0x46, 0x31, 0x46, 0xf2, 0xf7, + 0x45, 0xfa, 0x39, 0x46, 0xf2, 0xf7, 0xa6, 0xf9, 0x00, 0xf0, 0xa3, 0xf8, + 0x20, 0x61, 0x05, 0xe0, 0x20, 0x46, 0xbd, 0xe8, 0xf0, 0x41, 0x14, 0x21, + 0xee, 0xf7, 0x3c, 0xbb, 0xbd, 0xe8, 0xf0, 0x81, 0x31, 0x46, 0xf2, 0xf7, + 0xa5, 0xb8, 0x30, 0xb5, 0x0c, 0x46, 0x15, 0x46, 0x85, 0xb0, 0x29, 0x46, + 0xff, 0xf7, 0x87, 0xff, 0x69, 0x46, 0x20, 0x46, 0xff, 0xf7, 0x83, 0xff, + 0x28, 0x68, 0x00, 0x99, 0xf2, 0xf7, 0x14, 0xf9, 0x28, 0x60, 0x01, 0x99, + 0x68, 0x68, 0xf2, 0xf7, 0x0f, 0xf9, 0x68, 0x60, 0x02, 0x99, 0xa8, 0x68, + 0xf2, 0xf7, 0x0a, 0xf9, 0xa8, 0x60, 0x03, 0x99, 0xe8, 0x68, 0xf2, 0xf7, + 0x05, 0xf9, 0xe8, 0x60, 0x29, 0x69, 0x04, 0x98, 0xf2, 0xf7, 0x74, 0xf9, + 0x28, 0x61, 0x05, 0xb0, 0x30, 0xbd, 0x10, 0xb5, 0x04, 0x46, 0x79, 0x48, + 0xf2, 0xf7, 0x08, 0xfa, 0x78, 0x49, 0x41, 0xf8, 0x24, 0x00, 0x10, 0xbd, + 0x2d, 0xe9, 0xf0, 0x4f, 0x82, 0x46, 0x83, 0xb0, 0x0f, 0x46, 0x14, 0x46, + 0x01, 0x20, 0xf7, 0xf7, 0xe9, 0xff, 0x3d, 0x68, 0x7e, 0x68, 0xd7, 0xf8, + 0x08, 0xb0, 0xff, 0x68, 0x80, 0x46, 0x89, 0x46, 0x28, 0x46, 0x00, 0xf0, + 0x54, 0xf8, 0x00, 0x90, 0x31, 0x46, 0x30, 0x46, 0xf2, 0xf7, 0xec, 0xf9, + 0x00, 0x99, 0xf2, 0xf7, 0x4d, 0xf9, 0x01, 0x90, 0x59, 0x46, 0x58, 0x46, + 0xf2, 0xf7, 0xe4, 0xf9, 0x00, 0x90, 0x39, 0x46, 0x38, 0x46, 0xf2, 0xf7, + 0xdf, 0xf9, 0x00, 0x99, 0xf2, 0xf7, 0x40, 0xf9, 0x01, 0x46, 0x01, 0x98, + 0xf2, 0xf7, 0x4a, 0xf8, 0xf2, 0xf7, 0x7c, 0xf9, 0x60, 0x49, 0xf2, 0xf7, + 0x37, 0xf9, 0x60, 0x49, 0xf2, 0xf7, 0xd0, 0xf9, 0x60, 0x60, 0x59, 0x46, + 0x28, 0x46, 0xf2, 0xf7, 0xcb, 0xf9, 0x00, 0x90, 0x39, 0x46, 0x30, 0x46, + 0xf2, 0xf7, 0xc6, 0xf9, 0x00, 0x99, 0xf2, 0xf7, 0x27, 0xf9, 0x00, 0x90, + 0x39, 0x46, 0x28, 0x46, 0xf2, 0xf7, 0xbe, 0xf9, 0x07, 0x46, 0x30, 0x46, + 0x59, 0x46, 0xf2, 0xf7, 0xb9, 0xf9, 0x00, 0xf0, 0x1d, 0xf8, 0x01, 0x46, + 0x00, 0x98, 0xf2, 0xf7, 0x25, 0xf8, 0x4e, 0x49, 0x51, 0xf8, 0x2a, 0x10, + 0xf2, 0xf7, 0xae, 0xf9, 0x05, 0x46, 0x40, 0x46, 0x49, 0x46, 0xf1, 0xf7, + 0xdd, 0xff, 0x4c, 0x49, 0xf2, 0xf7, 0x18, 0xf8, 0x01, 0x46, 0x28, 0x46, + 0xf2, 0xf7, 0x14, 0xf8, 0x80, 0xf0, 0x00, 0x40, 0x20, 0x60, 0xbd, 0xe8, + 0xf7, 0x8f, 0x29, 0x46, 0xf2, 0xf7, 0x9a, 0xb9, 0x01, 0x46, 0x38, 0x46, + 0xf2, 0xf7, 0x86, 0xb8, 0x2d, 0xe9, 0xf2, 0x4f, 0x82, 0xb0, 0xd7, 0x68, + 0xd2, 0xf8, 0x00, 0x80, 0x95, 0x68, 0x56, 0x68, 0x00, 0xf1, 0x34, 0x04, + 0x40, 0x46, 0x00, 0xf0, 0x84, 0xf8, 0x81, 0x46, 0x30, 0x46, 0xff, 0xf7, + 0xe8, 0xff, 0x01, 0x46, 0x48, 0x46, 0xf2, 0xf7, 0x71, 0xf8, 0x81, 0x46, + 0x20, 0x69, 0x01, 0x90, 0x38, 0x46, 0xd4, 0xf8, 0x0c, 0xa0, 0x51, 0x46, + 0xf2, 0xf7, 0x78, 0xf9, 0x83, 0x46, 0x01, 0x98, 0xff, 0xf7, 0xd7, 0xff, + 0x01, 0x46, 0x58, 0x46, 0xf2, 0xf7, 0x60, 0xf8, 0x00, 0xf0, 0x62, 0xf8, + 0x83, 0x46, 0x01, 0x98, 0x00, 0xf0, 0x68, 0xf8, 0x00, 0x90, 0x51, 0x46, + 0x30, 0x46, 0xf2, 0xf7, 0x65, 0xf9, 0x01, 0x46, 0x00, 0x98, 0xf2, 0xf7, + 0x51, 0xf8, 0x00, 0xf0, 0x53, 0xf8, 0x82, 0x46, 0xa0, 0x69, 0x00, 0x90, + 0x38, 0x46, 0x64, 0x69, 0x00, 0xf0, 0x4f, 0xf8, 0x07, 0x46, 0x00, 0x98, + 0xff, 0xf7, 0xb7, 0xff, 0xff, 0xf7, 0xb8, 0xff, 0x00, 0xf0, 0x44, 0xf8, + 0x05, 0x46, 0x00, 0x98, 0x00, 0xf0, 0x4a, 0xf8, 0x07, 0x46, 0x30, 0x46, + 0x00, 0xf0, 0x3f, 0xf8, 0xff, 0xf7, 0xac, 0xff, 0x00, 0xf0, 0x38, 0xf8, + 0x04, 0x46, 0x28, 0x46, 0x00, 0xf0, 0x37, 0xf8, 0x06, 0x46, 0x58, 0x46, + 0x51, 0x46, 0xf2, 0xf7, 0x3b, 0xf9, 0x31, 0x46, 0xf2, 0xf7, 0x9c, 0xf8, + 0x06, 0x46, 0x28, 0x46, 0x51, 0x46, 0xf2, 0xf7, 0x33, 0xf9, 0x05, 0x46, + 0x58, 0x46, 0x00, 0xf0, 0x26, 0xf8, 0x01, 0x46, 0x28, 0x46, 0xf2, 0xf7, + 0x1b, 0xf8, 0x01, 0x46, 0x30, 0x46, 0xf1, 0xf7, 0x99, 0xff, 0x04, 0x46, + 0x02, 0x98, 0xf1, 0xf7, 0x7b, 0xff, 0x0a, 0x49, 0xf2, 0xf7, 0x20, 0xf9, + 0x00, 0xf0, 0x15, 0xf8, 0xbd, 0xe8, 0xfe, 0x4f, 0xf2, 0xf7, 0x86, 0xb9, + 0x00, 0x24, 0x74, 0x49, 0x00, 0xcc, 0x6e, 0x46, 0x84, 0xb8, 0x00, 0x20, + 0x00, 0x00, 0x80, 0xbf, 0x00, 0xff, 0x7f, 0x47, 0x28, 0x6b, 0x6e, 0x4e, + 0x00, 0x30, 0x81, 0x45, 0x49, 0x46, 0xf1, 0xf7, 0x7b, 0xbf, 0x21, 0x46, + 0xf2, 0xf7, 0x06, 0xb9, 0x38, 0x46, 0x39, 0x46, 0xf2, 0xf7, 0x02, 0xb9, + 0x41, 0x46, 0xf2, 0xf7, 0xff, 0xb8, 0xf8, 0xb5, 0x04, 0x46, 0x0d, 0x46, + 0xff, 0xf7, 0x4c, 0xfe, 0x06, 0x46, 0x20, 0x46, 0xee, 0xf7, 0xa0, 0xfb, + 0x07, 0x46, 0x35, 0xf9, 0x17, 0x20, 0x00, 0x21, 0x20, 0x46, 0xf0, 0xf7, + 0x57, 0xff, 0x05, 0xeb, 0x47, 0x00, 0x01, 0x21, 0xb0, 0xf9, 0x80, 0x20, + 0x20, 0x46, 0xf0, 0xf7, 0x4f, 0xff, 0x00, 0x20, 0x85, 0xf8, 0x02, 0x01, + 0x86, 0xf3, 0x11, 0x88, 0xf1, 0xbd, 0xf8, 0xb5, 0x04, 0x46, 0x0d, 0x46, + 0x17, 0x46, 0x1e, 0x46, 0xff, 0xf7, 0x2c, 0xfe, 0x06, 0x99, 0xfa, 0x07, + 0x44, 0xbf, 0x0a, 0x88, 0x25, 0xf8, 0x16, 0x20, 0xba, 0x07, 0x04, 0xd5, + 0x49, 0x88, 0x05, 0xeb, 0x46, 0x02, 0xa2, 0xf8, 0x80, 0x10, 0x80, 0xf3, + 0x11, 0x88, 0x29, 0x46, 0x20, 0x46, 0xbd, 0xe8, 0xf4, 0x40, 0xc6, 0xe7, + 0xf8, 0xb5, 0x04, 0x46, 0x0d, 0x46, 0x16, 0x46, 0xff, 0xf7, 0x12, 0xfe, + 0x07, 0x46, 0x20, 0x46, 0xee, 0xf7, 0x66, 0xfb, 0xa9, 0x19, 0x91, 0xf8, + 0x02, 0x21, 0x01, 0x2a, 0x18, 0xbf, 0x40, 0xf0, 0x00, 0x40, 0x01, 0x22, + 0x81, 0xf8, 0x02, 0x21, 0x87, 0xf3, 0x11, 0x88, 0xf2, 0xbd, 0xf0, 0xb5, + 0x30, 0xf9, 0x11, 0x30, 0x30, 0xf9, 0x12, 0x40, 0x4d, 0x1c, 0x09, 0xe0, + 0xe6, 0x1a, 0x6f, 0x1a, 0x7e, 0x43, 0x57, 0x1a, 0x96, 0xfb, 0xf7, 0xf6, + 0x9e, 0x19, 0x20, 0xf8, 0x15, 0x60, 0x6d, 0x1c, 0x95, 0x42, 0xf3, 0xdb, + 0xf0, 0xbd, 0x00, 0x00, 0x2d, 0xe9, 0xf0, 0x41, 0x05, 0x46, 0x0f, 0x46, + 0x16, 0x46, 0x98, 0x46, 0x00, 0x24, 0xef, 0xf7, 0xa8, 0xfc, 0x08, 0xb1, + 0x02, 0x24, 0x0d, 0xe0, 0x05, 0xf1, 0x8c, 0x40, 0x07, 0xea, 0x06, 0x01, + 0x00, 0x78, 0x38, 0x40, 0x88, 0x42, 0x05, 0xd0, 0x40, 0x46, 0xf1, 0xf7, + 0x75, 0xfe, 0x00, 0x28, 0xed, 0xd0, 0x01, 0x24, 0x20, 0x46, 0xbd, 0xe8, + 0xf0, 0x81, 0x10, 0xb5, 0x4f, 0xf4, 0x7a, 0x71, 0x00, 0x20, 0xf1, 0xf7, + 0x51, 0xfe, 0x00, 0x23, 0x00, 0x22, 0x40, 0x21, 0x40, 0xf6, 0xff, 0x50, + 0xff, 0xf7, 0xd6, 0xff, 0x04, 0x46, 0x00, 0x20, 0xf1, 0xf7, 0xd6, 0xfd, + 0x01, 0x2c, 0x16, 0xbf, 0x03, 0x2c, 0x01, 0x20, 0x00, 0x20, 0x10, 0xbd, + 0x10, 0xb5, 0x01, 0x21, 0x01, 0xfa, 0x00, 0xf0, 0x40, 0xf0, 0x80, 0x04, + 0xe1, 0xb2, 0x40, 0xf6, 0xff, 0x50, 0xee, 0xf7, 0x9d, 0xf9, 0x44, 0xf0, + 0x40, 0x00, 0xc0, 0xb2, 0x10, 0xbd, 0x2d, 0xe9, 0xf0, 0x41, 0x04, 0x46, + 0x88, 0x46, 0x10, 0x46, 0xff, 0xf7, 0xea, 0xff, 0x00, 0x27, 0x00, 0x26, + 0x12, 0xe0, 0x00, 0x20, 0x24, 0xf8, 0x16, 0x00, 0x00, 0x25, 0x00, 0xf0, + 0x44, 0xf8, 0x47, 0x48, 0x00, 0x78, 0x34, 0xf8, 0x16, 0x10, 0xa8, 0x40, + 0x7f, 0x1c, 0x08, 0x43, 0x08, 0x35, 0x24, 0xf8, 0x16, 0x00, 0x09, 0x2d, + 0xf1, 0xd3, 0x76, 0x1c, 0x46, 0x45, 0xea, 0xd3, 0xbd, 0xe8, 0xf0, 0x41, + 0x00, 0x21, 0x40, 0xf6, 0xff, 0x50, 0xee, 0xf7, 0x73, 0xb9, 0x2d, 0xe9, + 0xf8, 0x4f, 0x80, 0x46, 0x8a, 0x46, 0x10, 0x46, 0xff, 0xf7, 0xc4, 0xff, + 0x00, 0x26, 0x00, 0x27, 0x83, 0x46, 0x00, 0x24, 0x40, 0xf6, 0xff, 0x59, + 0x16, 0xe0, 0x00, 0x25, 0x00, 0xf0, 0x1d, 0xf8, 0x38, 0xf9, 0x14, 0x00, + 0x28, 0x41, 0xc1, 0xb2, 0x4f, 0xf4, 0x60, 0x60, 0xee, 0xf7, 0x5a, 0xf9, + 0x59, 0x46, 0x48, 0x46, 0xee, 0xf7, 0x56, 0xf9, 0xff, 0xf7, 0x95, 0xff, + 0x7f, 0x1c, 0x06, 0x43, 0x08, 0x35, 0x09, 0x2d, 0xea, 0xd3, 0x64, 0x1c, + 0x54, 0x45, 0xe6, 0xd3, 0x00, 0x21, 0x48, 0x46, 0xee, 0xf7, 0x48, 0xf9, + 0x30, 0x46, 0xbd, 0xe8, 0xf2, 0x8f, 0xf9, 0xb2, 0x40, 0xf6, 0x01, 0x60, + 0xee, 0xf7, 0x40, 0xb9, 0x2d, 0xe9, 0xf0, 0x41, 0x04, 0x46, 0xff, 0xf7, + 0x93, 0xff, 0x06, 0x46, 0x20, 0x46, 0x00, 0xf0, 0x1f, 0xf8, 0x44, 0x00, + 0x00, 0x25, 0xa4, 0xb2, 0x00, 0x27, 0x40, 0xf6, 0xff, 0x58, 0x0e, 0xe0, + 0xff, 0xf7, 0xe9, 0xff, 0x00, 0x21, 0x4f, 0xf4, 0x60, 0x60, 0xee, 0xf7, + 0x29, 0xf9, 0x31, 0x46, 0x40, 0x46, 0xee, 0xf7, 0x25, 0xf9, 0xff, 0xf7, + 0x64, 0xff, 0x05, 0x43, 0x7f, 0x1c, 0xa7, 0x42, 0xee, 0xd3, 0x00, 0x21, + 0x40, 0x46, 0xee, 0xf7, 0x1b, 0xf9, 0x28, 0x46, 0xbd, 0xe8, 0xf0, 0x81, + 0x18, 0x21, 0x04, 0x28, 0x0e, 0x4a, 0x12, 0xd8, 0xdf, 0xe8, 0x00, 0xf0, + 0x03, 0x03, 0x09, 0x09, 0x0d, 0x00, 0x0c, 0x48, 0x00, 0x78, 0x40, 0x09, + 0x40, 0x1c, 0x00, 0x01, 0x70, 0x47, 0x10, 0x78, 0xc0, 0xf3, 0x41, 0x10, + 0x06, 0xe0, 0x10, 0x78, 0xc0, 0xf3, 0x41, 0x00, 0x02, 0xe0, 0x10, 0x78, + 0xc0, 0xf3, 0xc1, 0x00, 0x40, 0x1c, 0x48, 0x43, 0x70, 0x47, 0x00, 0x00, + 0x00, 0x0e, 0x00, 0x46, 0x10, 0x04, 0x00, 0x46, 0x10, 0x09, 0x00, 0x46, + 0xef, 0xf3, 0x11, 0x80, 0x60, 0x21, 0x81, 0xf3, 0x11, 0x88, 0x70, 0x47, + 0x2d, 0xe9, 0xf0, 0x47, 0xad, 0xf5, 0x08, 0x7d, 0x04, 0x46, 0x4f, 0xf0, + 0x00, 0x08, 0xdf, 0xf8, 0xbc, 0x93, 0x00, 0x21, 0x00, 0x20, 0xee, 0xf7, + 0x36, 0xfb, 0x20, 0x88, 0x01, 0xa9, 0xf1, 0xf7, 0x94, 0xf8, 0xa2, 0x69, + 0x12, 0x78, 0x21, 0x88, 0xa0, 0x68, 0x52, 0x1e, 0x12, 0x04, 0x02, 0xf4, + 0xfe, 0x02, 0x42, 0xea, 0x81, 0x71, 0xa2, 0x78, 0xd2, 0x05, 0x02, 0xf0, + 0x7e, 0x52, 0x11, 0x43, 0x42, 0x78, 0x00, 0x79, 0xd2, 0x03, 0x02, 0xf4, + 0x00, 0x42, 0x11, 0x43, 0x00, 0xf0, 0x07, 0x00, 0x08, 0x43, 0x40, 0xf0, + 0x00, 0x40, 0x40, 0xf4, 0x80, 0x40, 0xf0, 0xf7, 0x8c, 0xfe, 0xa0, 0x69, + 0x40, 0x78, 0xf0, 0xf7, 0xab, 0xfe, 0x00, 0x27, 0x00, 0x25, 0x04, 0xeb, + 0x85, 0x00, 0x06, 0x69, 0x6d, 0xb1, 0x00, 0x2f, 0x02, 0xbf, 0xe0, 0x69, + 0x00, 0x68, 0x00, 0x28, 0x4b, 0xd1, 0x20, 0x88, 0x01, 0x21, 0xc0, 0xb2, + 0xf0, 0xf7, 0x77, 0xfd, 0x02, 0x20, 0xf1, 0xf7, 0xeb, 0xfc, 0x00, 0xf0, + 0x18, 0xf9, 0x0f, 0xfa, 0x80, 0xfa, 0x30, 0x6b, 0x82, 0x45, 0x18, 0xd0, + 0x04, 0xa8, 0x31, 0x46, 0x50, 0x22, 0xf4, 0xf7, 0xd3, 0xfe, 0x30, 0x46, + 0x06, 0xf1, 0x50, 0x01, 0x50, 0x22, 0xf4, 0xf7, 0xcd, 0xfe, 0x06, 0xf1, + 0x50, 0x00, 0x04, 0xa9, 0x50, 0x22, 0xf4, 0xf7, 0xc7, 0xfe, 0x30, 0x6b, + 0x82, 0x45, 0x04, 0xd0, 0x30, 0x46, 0xff, 0xf7, 0x9f, 0xfc, 0xc6, 0xf8, + 0x30, 0xa0, 0xf0, 0xf7, 0xfa, 0xfd, 0xf0, 0xf7, 0x14, 0xfe, 0x02, 0x28, + 0x06, 0xd1, 0xe0, 0x69, 0x81, 0x8a, 0x09, 0x04, 0x41, 0xf0, 0x01, 0x01, + 0x01, 0x60, 0x02, 0xe0, 0x01, 0x28, 0x08, 0xbf, 0x01, 0x27, 0x00, 0xf0, + 0xe8, 0xf8, 0x06, 0x46, 0x17, 0xb9, 0xef, 0xf7, 0x46, 0xfb, 0x00, 0xe0, + 0x01, 0x20, 0x36, 0xb2, 0x40, 0xea, 0xd6, 0x77, 0x18, 0xa8, 0xe0, 0x21, + 0x01, 0xfb, 0x05, 0x00, 0xf0, 0xf7, 0x9a, 0xfe, 0x6d, 0x1c, 0x02, 0x2d, + 0xa9, 0xd3, 0x01, 0xa8, 0xf1, 0xf7, 0x67, 0xf8, 0x00, 0x20, 0xee, 0xf7, + 0x0f, 0xfb, 0xe0, 0x69, 0x00, 0x68, 0x00, 0x28, 0x4a, 0xd1, 0x00, 0x2f, + 0x42, 0xd1, 0xa0, 0x78, 0xf0, 0xf7, 0x2c, 0xfe, 0x02, 0x46, 0xa0, 0x68, + 0x62, 0x64, 0xc1, 0x68, 0x18, 0xa8, 0xf0, 0xf7, 0xaf, 0xff, 0x98, 0xb3, + 0x62, 0x6c, 0x20, 0x69, 0x18, 0xa9, 0xf0, 0xf7, 0x85, 0xfe, 0x62, 0x6c, + 0x60, 0x69, 0x50, 0xa9, 0xf0, 0xf7, 0x80, 0xfe, 0x61, 0x69, 0x20, 0x69, + 0x04, 0xf1, 0x28, 0x02, 0xff, 0xf7, 0xc7, 0xfc, 0xa0, 0x6b, 0x49, 0x46, + 0xf1, 0xf7, 0xf6, 0xfe, 0x05, 0x46, 0x61, 0x68, 0x97, 0x48, 0xf1, 0xf7, + 0xf1, 0xfe, 0x01, 0x46, 0x28, 0x46, 0xf1, 0xf7, 0x5f, 0xfd, 0x80, 0x46, + 0xff, 0xf7, 0x38, 0xff, 0x07, 0x46, 0xe0, 0x69, 0xc1, 0x8a, 0x49, 0x1c, + 0xc1, 0x82, 0x40, 0x46, 0x49, 0x46, 0xf1, 0xf7, 0xe9, 0xff, 0x98, 0xbf, + 0x64, 0x20, 0x02, 0xd9, 0xf1, 0xf7, 0x48, 0xff, 0x80, 0xb2, 0xe1, 0x69, + 0x48, 0x60, 0x87, 0xf3, 0x11, 0x88, 0x03, 0xe0, 0xa0, 0x68, 0x80, 0x68, + 0xed, 0xf7, 0x7a, 0xfd, 0x40, 0x46, 0x49, 0x46, 0xf1, 0xf7, 0xbc, 0xfe, + 0xff, 0xf4, 0x29, 0xaf, 0xe0, 0x69, 0x00, 0x68, 0x00, 0x28, 0x72, 0xd1, + 0x20, 0x88, 0x03, 0x22, 0x04, 0xf1, 0x24, 0x01, 0xf0, 0xf7, 0x07, 0xfe, + 0xb4, 0xf9, 0x24, 0x60, 0xb4, 0xf9, 0x26, 0x90, 0x20, 0x88, 0x04, 0xf1, + 0x3c, 0x02, 0x04, 0xf1, 0x28, 0x01, 0xff, 0xf7, 0xb3, 0xfc, 0x27, 0x6c, + 0x38, 0x46, 0x00, 0x21, 0xf1, 0xf7, 0xa0, 0xfe, 0x38, 0xbf, 0x87, 0xf0, + 0x00, 0x47, 0xe0, 0x6b, 0xf1, 0xf7, 0x9a, 0xfe, 0x38, 0xbf, 0x80, 0xf0, + 0x00, 0x40, 0x39, 0x46, 0xf1, 0xf7, 0x0a, 0xfe, 0xf8, 0xf7, 0xa4, 0xfd, + 0x05, 0x46, 0x21, 0x46, 0x00, 0x20, 0x00, 0xf0, 0x59, 0xf8, 0x21, 0x46, + 0x01, 0x20, 0x00, 0xf0, 0x55, 0xf8, 0xb4, 0xf9, 0x26, 0x00, 0xb0, 0xf5, + 0x00, 0x5f, 0xa8, 0xbf, 0x41, 0xf6, 0xff, 0x70, 0x03, 0xda, 0x10, 0xf5, + 0x00, 0x5f, 0x01, 0xda, 0x66, 0x48, 0xe0, 0x84, 0xb4, 0xf9, 0x24, 0x00, + 0xb0, 0xf5, 0x80, 0x6f, 0xa8, 0xbf, 0x40, 0xf2, 0xff, 0x30, 0x02, 0xda, + 0x00, 0x28, 0x01, 0xd5, 0x00, 0x20, 0xa0, 0x84, 0xff, 0xf7, 0xce, 0xfe, + 0x07, 0x46, 0xb4, 0xf9, 0x26, 0x00, 0x48, 0x45, 0x04, 0xbf, 0xb4, 0xf9, + 0x24, 0x00, 0xb0, 0x42, 0x13, 0xd0, 0x04, 0xf1, 0x24, 0x00, 0x00, 0x90, + 0x03, 0x22, 0x60, 0x69, 0x03, 0x6b, 0xe1, 0x68, 0x20, 0x88, 0xff, 0xf7, + 0x8c, 0xfd, 0x22, 0x88, 0x20, 0x6a, 0x01, 0x21, 0x91, 0x40, 0x08, 0x43, + 0x20, 0x62, 0xe0, 0x69, 0x01, 0x69, 0x49, 0x1c, 0x01, 0x61, 0x64, 0x20, + 0xe1, 0x69, 0x48, 0x60, 0xe0, 0x69, 0x85, 0x60, 0xe0, 0x69, 0xc1, 0x68, + 0x49, 0x1c, 0xc1, 0x60, 0xe0, 0x69, 0xc1, 0x8a, 0x01, 0x83, 0x87, 0xf3, + 0x11, 0x88, 0x20, 0x69, 0xff, 0xf7, 0xaa, 0xfb, 0x60, 0x69, 0xff, 0xf7, + 0xa7, 0xfb, 0x0d, 0xf5, 0x08, 0x7d, 0xbd, 0xe8, 0xf0, 0x87, 0xe2, 0x68, + 0x20, 0x88, 0x00, 0x21, 0xff, 0xf7, 0x80, 0xbd, 0x2d, 0xe9, 0xf0, 0x41, + 0x8e, 0x68, 0x00, 0x28, 0xb0, 0x7c, 0x07, 0xbf, 0xcd, 0x6b, 0x01, 0xf1, + 0x24, 0x04, 0x0d, 0x6c, 0x01, 0xf1, 0x26, 0x04, 0x80, 0xb1, 0x28, 0x46, + 0x00, 0x21, 0xf1, 0xf7, 0x3d, 0xff, 0x38, 0xbf, 0x4f, 0xf0, 0x7c, 0x50, + 0x04, 0xd3, 0xf1, 0xf7, 0x1d, 0xfe, 0x05, 0xd2, 0x4f, 0xf0, 0x3f, 0x40, + 0x29, 0x46, 0xf1, 0xf7, 0x8d, 0xfd, 0x05, 0x46, 0x36, 0x7c, 0x27, 0x88, + 0x30, 0x09, 0xf1, 0xf7, 0x85, 0xfc, 0x80, 0x46, 0x06, 0xf0, 0x0f, 0x00, + 0xf1, 0xf7, 0x76, 0xfc, 0x01, 0x46, 0x40, 0x46, 0xf1, 0xf7, 0x8c, 0xfc, + 0x29, 0x46, 0xf1, 0xf7, 0x17, 0xfe, 0xf1, 0xf7, 0x81, 0xfe, 0xc0, 0x19, + 0x20, 0x80, 0xbd, 0xe8, 0xf0, 0x81, 0xfe, 0xb5, 0x0d, 0x46, 0x06, 0x46, + 0x28, 0x68, 0x00, 0x28, 0x41, 0xd0, 0x00, 0x21, 0x00, 0x20, 0xee, 0xf7, + 0x9e, 0xf9, 0x30, 0x88, 0x69, 0x46, 0xf0, 0xf7, 0xfc, 0xfe, 0x28, 0x68, + 0xc0, 0xf3, 0x07, 0x20, 0xc0, 0xb1, 0x95, 0xf9, 0x01, 0x00, 0x1e, 0x49, + 0x01, 0xfb, 0x00, 0xf4, 0x30, 0x88, 0x02, 0x21, 0xc0, 0xb2, 0xf0, 0xf7, + 0xe5, 0xfa, 0x30, 0x88, 0x1a, 0x49, 0x00, 0x28, 0x14, 0xbf, 0x02, 0x20, + 0x01, 0x20, 0xd1, 0xe9, 0x08, 0x67, 0x32, 0x19, 0x47, 0xeb, 0xe4, 0x73, + 0xf8, 0xf7, 0x79, 0xfc, 0xf8, 0xf7, 0x54, 0xfc, 0x14, 0x48, 0x04, 0x78, + 0x40, 0xf6, 0x41, 0x46, 0x00, 0x22, 0xc0, 0x21, 0x30, 0x46, 0xf0, 0xf7, + 0xfb, 0xf8, 0x01, 0x20, 0x68, 0x60, 0x28, 0x68, 0x18, 0xb1, 0xef, 0xf7, + 0xee, 0xf9, 0x00, 0x28, 0xf9, 0xd0, 0x00, 0x20, 0x68, 0x60, 0x21, 0x46, + 0x30, 0x46, 0xf0, 0xf7, 0xc6, 0xf8, 0x68, 0x46, 0xf0, 0xf7, 0x15, 0xff, + 0x00, 0x20, 0xee, 0xf7, 0xbd, 0xf9, 0x00, 0x20, 0xfe, 0xbd, 0x00, 0x00, + 0x00, 0x00, 0xc8, 0x42, 0xb7, 0x43, 0xba, 0x51, 0x00, 0xe0, 0xff, 0xff, + 0x40, 0x42, 0x0f, 0x00, 0x00, 0xf2, 0x00, 0x20, 0x41, 0x0c, 0x00, 0x46, + 0x2d, 0xe9, 0xf0, 0x47, 0xc0, 0x48, 0x04, 0x78, 0x45, 0x78, 0x86, 0x78, + 0xc7, 0x78, 0x90, 0xf8, 0x08, 0x80, 0x90, 0xf8, 0x09, 0x90, 0xbd, 0x48, + 0x00, 0x6a, 0xf1, 0xf7, 0x0d, 0xfc, 0x01, 0x46, 0xbb, 0x48, 0xf1, 0xf7, + 0x19, 0xfc, 0x82, 0x46, 0x07, 0xf0, 0x0f, 0x00, 0x06, 0xeb, 0x00, 0x20, + 0xf1, 0xf7, 0x02, 0xfc, 0x06, 0x46, 0x09, 0xf0, 0x0f, 0x00, 0x08, 0xeb, + 0x00, 0x20, 0xf1, 0xf7, 0xfb, 0xfb, 0x01, 0x46, 0x30, 0x46, 0xf1, 0xf7, + 0x07, 0xfc, 0x06, 0x46, 0x04, 0xeb, 0x05, 0x20, 0xf1, 0xf7, 0xe8, 0xfb, + 0x4f, 0xf0, 0x76, 0x51, 0xf1, 0xf7, 0x8c, 0xfd, 0x31, 0x46, 0xf1, 0xf7, + 0x89, 0xfd, 0x51, 0x46, 0xf1, 0xf7, 0x86, 0xfd, 0xf1, 0xf7, 0xf0, 0xfd, + 0x80, 0xf3, 0x09, 0x04, 0xa0, 0x05, 0x01, 0x0e, 0x40, 0xf6, 0xad, 0x10, + 0xed, 0xf7, 0xbe, 0xfe, 0x04, 0xf0, 0x03, 0x01, 0xbd, 0xe8, 0xf0, 0x47, + 0x40, 0xf6, 0xae, 0x10, 0xed, 0xf7, 0xb6, 0xbe, 0x10, 0xb5, 0xf1, 0xf7, + 0xe3, 0xfb, 0x4f, 0xf0, 0x81, 0x44, 0x21, 0x46, 0xf1, 0xf7, 0xe3, 0xff, + 0x4f, 0xf0, 0x7e, 0x51, 0xf1, 0xf7, 0xcc, 0xfc, 0x01, 0x21, 0xf8, 0xf7, + 0x6f, 0xfe, 0x9a, 0x49, 0xf1, 0xf7, 0x62, 0xfd, 0x99, 0x49, 0xf1, 0xf7, + 0xc3, 0xfc, 0x99, 0x49, 0xf1, 0xf7, 0xce, 0xfb, 0xf1, 0xf7, 0xc6, 0xfd, + 0xc0, 0xb2, 0x10, 0xbd, 0x2d, 0xe9, 0xf0, 0x4f, 0x0d, 0x46, 0x85, 0xb0, + 0x00, 0x21, 0x00, 0x20, 0xee, 0xf7, 0xe7, 0xf8, 0x92, 0x48, 0x00, 0x78, + 0x00, 0x24, 0xc0, 0x07, 0x00, 0xf1, 0x0c, 0x81, 0x8a, 0x4f, 0x97, 0xf8, + 0x10, 0x80, 0xb8, 0xf1, 0x03, 0x0f, 0xa8, 0xbf, 0x03, 0x24, 0x80, 0xf2, + 0x03, 0x81, 0x0f, 0xf2, 0x68, 0x21, 0x4c, 0xc9, 0x02, 0xa8, 0x40, 0xf2, + 0x01, 0x1a, 0x4c, 0xc0, 0x78, 0x6a, 0xf1, 0xf7, 0x99, 0xfb, 0x87, 0x49, + 0xf1, 0xf7, 0xa6, 0xfb, 0x06, 0x46, 0x86, 0x48, 0x00, 0x6b, 0xf1, 0xf7, + 0x91, 0xfb, 0x81, 0x46, 0x02, 0xa8, 0x84, 0x49, 0x50, 0xf8, 0x28, 0x00, + 0xf1, 0xf7, 0x28, 0xfd, 0x01, 0x46, 0x48, 0x46, 0xf1, 0xf7, 0x96, 0xfb, + 0x80, 0x46, 0xb8, 0x7a, 0x7f, 0x49, 0x00, 0xf0, 0x03, 0x00, 0x00, 0x90, + 0x40, 0xf2, 0xca, 0x2b, 0x40, 0x46, 0xf1, 0xf7, 0x19, 0xfd, 0x31, 0x46, + 0xf1, 0xf7, 0x04, 0xfd, 0x81, 0x46, 0x28, 0xbf, 0xb1, 0x46, 0x48, 0x46, + 0xff, 0xf7, 0x9c, 0xff, 0x8d, 0xf8, 0x04, 0x00, 0x4f, 0xf0, 0x7d, 0x51, + 0x48, 0x46, 0xf1, 0xf7, 0x09, 0xfd, 0x31, 0x46, 0xff, 0xf7, 0x92, 0xff, + 0x07, 0x46, 0x4f, 0xf0, 0x88, 0x41, 0x48, 0x46, 0xf1, 0xf7, 0x00, 0xfd, + 0x41, 0x46, 0xf1, 0xf7, 0x6f, 0xfb, 0xf1, 0xf7, 0x67, 0xfd, 0x80, 0x46, + 0x6c, 0x48, 0x00, 0x78, 0x05, 0xf5, 0x80, 0x79, 0x89, 0xf8, 0x00, 0x00, + 0x6a, 0x48, 0x00, 0x78, 0x89, 0xf8, 0x01, 0x00, 0x69, 0x48, 0x00, 0x78, + 0x89, 0xf8, 0x02, 0x00, 0x00, 0x98, 0x80, 0x01, 0x40, 0xf0, 0x11, 0x01, + 0xc9, 0xb2, 0x50, 0x46, 0xed, 0xf7, 0x26, 0xfe, 0x64, 0x48, 0x00, 0x57, + 0x06, 0x28, 0x0c, 0xbf, 0x01, 0x21, 0x00, 0x21, 0x4f, 0xf4, 0x11, 0x60, + 0xed, 0xf7, 0x1c, 0xfe, 0x6e, 0x21, 0x40, 0xf6, 0xc1, 0x10, 0xed, 0xf7, + 0x17, 0xfe, 0x03, 0x21, 0x40, 0xf6, 0xc2, 0x10, 0xed, 0xf7, 0x12, 0xfe, + 0x03, 0x21, 0x40, 0xf6, 0xac, 0x10, 0xed, 0xf7, 0x0d, 0xfe, 0x12, 0x21, + 0x58, 0x46, 0xed, 0xf7, 0x09, 0xfe, 0x30, 0x46, 0x56, 0x49, 0xf1, 0xf7, + 0xb1, 0xfc, 0x34, 0xbf, 0x02, 0x26, 0x01, 0x26, 0x31, 0x46, 0x4f, 0xf4, + 0x1a, 0x60, 0xed, 0xf7, 0xfd, 0xfd, 0x31, 0x46, 0x40, 0xf6, 0xa1, 0x10, + 0xed, 0xf7, 0xf8, 0xfd, 0x9d, 0xf8, 0x04, 0x10, 0x40, 0xf6, 0xc3, 0x10, + 0xed, 0xf7, 0xf2, 0xfd, 0x39, 0x46, 0x40, 0xf6, 0xc4, 0x10, 0xed, 0xf7, + 0xed, 0xfd, 0x3c, 0x21, 0x40, 0xf6, 0xc5, 0x10, 0xed, 0xf7, 0xe8, 0xfd, + 0x5f, 0xfa, 0x88, 0xf1, 0x40, 0xf6, 0xc6, 0x10, 0xed, 0xf7, 0xe2, 0xfd, + 0x00, 0x21, 0x40, 0xf6, 0xa4, 0x10, 0xed, 0xf7, 0xdd, 0xfd, 0x00, 0x21, + 0x40, 0xf6, 0xa5, 0x10, 0xed, 0xf7, 0xd8, 0xfd, 0x00, 0x21, 0x40, 0xf6, + 0xa8, 0x10, 0xed, 0xf7, 0xd3, 0xfd, 0x00, 0x21, 0x40, 0xf6, 0xa9, 0x10, + 0xed, 0xf7, 0xce, 0xfd, 0x00, 0x26, 0x01, 0x20, 0x00, 0x99, 0xb0, 0x40, + 0x01, 0x42, 0x34, 0xd0, 0x47, 0x1e, 0xf8, 0xb2, 0xff, 0xf7, 0xac, 0xfc, + 0x80, 0x46, 0xfa, 0xb2, 0x1f, 0xfa, 0x88, 0xf1, 0x28, 0x46, 0xff, 0xf7, + 0x24, 0xfc, 0xf8, 0xb2, 0xff, 0xf7, 0x7a, 0xfc, 0x18, 0xbb, 0xfa, 0xb2, + 0x10, 0x21, 0x2f, 0x48, 0xff, 0xf7, 0x41, 0xfc, 0xe8, 0xb9, 0x00, 0x2e, + 0x0c, 0xbf, 0x2d, 0x21, 0x2c, 0x21, 0x4f, 0xf4, 0x1c, 0x60, 0xed, 0xf7, + 0xab, 0xfd, 0x01, 0x22, 0x00, 0xf0, 0x54, 0xf8, 0x28, 0x4b, 0x00, 0x22, + 0x01, 0x21, 0x4f, 0xf4, 0xd9, 0x70, 0xf4, 0xf7, 0x65, 0xfa, 0x18, 0xb1, + 0x00, 0x22, 0x00, 0xf0, 0x49, 0xf8, 0x02, 0x24, 0xfa, 0xb2, 0x1f, 0xfa, + 0x88, 0xf1, 0x28, 0x46, 0xff, 0xf7, 0x23, 0xfc, 0x08, 0xb1, 0x04, 0x24, + 0x02, 0xe0, 0x76, 0x1c, 0x02, 0x2e, 0xc2, 0xd3, 0x99, 0xf8, 0x00, 0x10, + 0x50, 0x46, 0xed, 0xf7, 0x8b, 0xfd, 0x99, 0xf8, 0x01, 0x10, 0x4f, 0xf4, + 0x11, 0x60, 0xed, 0xf7, 0x85, 0xfd, 0x99, 0xf8, 0x02, 0x10, 0x58, 0x46, + 0xed, 0xf7, 0x80, 0xfd, 0x00, 0x20, 0xee, 0xf7, 0x2f, 0xf8, 0x20, 0x46, + 0x05, 0xb0, 0xbd, 0xe8, 0xf0, 0x8f, 0x00, 0x00, 0xd3, 0x05, 0x00, 0x46, + 0x78, 0x29, 0x00, 0x20, 0xc6, 0xe3, 0x33, 0x4c, 0x00, 0x00, 0x20, 0x41, + 0x00, 0x00, 0x40, 0x40, 0xcd, 0xcc, 0x4c, 0x3d, 0xe8, 0xf2, 0x00, 0x20, + 0x00, 0x00, 0x7a, 0x44, 0x00, 0xf2, 0x00, 0x20, 0x00, 0x00, 0xfa, 0x44, + 0x4e, 0x62, 0xd0, 0x3e, 0x01, 0x01, 0x00, 0x46, 0x10, 0x09, 0x00, 0x46, + 0xca, 0x02, 0x00, 0x46, 0xb8, 0x2a, 0x00, 0x20, 0x00, 0x40, 0x9c, 0x47, + 0xba, 0x2a, 0x00, 0x20, 0x20, 0xa1, 0x07, 0x00, 0x01, 0x21, 0x4f, 0xf4, + 0xd9, 0x70, 0xed, 0xf7, 0x59, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x20, 0x40, 0x00, 0x00, 0x80, 0x40, 0x70, 0x47, 0xf0, 0xb5, + 0x0d, 0x46, 0x83, 0xb0, 0x00, 0x21, 0x00, 0x20, 0xed, 0xf7, 0x95, 0xff, + 0x69, 0x46, 0x28, 0x46, 0x00, 0xf0, 0x54, 0xf8, 0x04, 0x00, 0x4c, 0xd1, + 0x00, 0x26, 0x69, 0x4f, 0x07, 0xeb, 0x46, 0x12, 0xf1, 0xb2, 0x28, 0x46, + 0x00, 0xf0, 0xe8, 0xf8, 0x76, 0x1c, 0x04, 0x2e, 0xf6, 0xdb, 0x07, 0xf1, + 0x80, 0x05, 0x40, 0xf2, 0xdd, 0x50, 0x29, 0x78, 0xed, 0xf7, 0x28, 0xfd, + 0x69, 0x78, 0x40, 0xf2, 0xde, 0x50, 0xed, 0xf7, 0x23, 0xfd, 0xa9, 0x78, + 0x40, 0xf2, 0xdf, 0x50, 0xed, 0xf7, 0x1e, 0xfd, 0xe9, 0x78, 0x4f, 0xf4, + 0xbc, 0x60, 0xed, 0xf7, 0x19, 0xfd, 0x29, 0x79, 0x40, 0xf2, 0xe1, 0x50, + 0xed, 0xf7, 0x14, 0xfd, 0x57, 0x48, 0x58, 0x4a, 0x01, 0x78, 0x40, 0x78, + 0x93, 0x78, 0xd5, 0x78, 0x43, 0xea, 0x05, 0x23, 0x15, 0x78, 0x52, 0x78, + 0x41, 0xea, 0x00, 0x20, 0x45, 0xea, 0x02, 0x21, 0xc0, 0x1a, 0xc9, 0x1a, + 0x00, 0x01, 0x49, 0x1c, 0x90, 0xfb, 0xf1, 0xf1, 0x89, 0xb2, 0x10, 0x29, + 0xa8, 0xbf, 0x0f, 0x21, 0xc9, 0xb2, 0x4f, 0xf4, 0x09, 0x70, 0xed, 0xf7, + 0xf7, 0xfc, 0x4b, 0x48, 0x80, 0x7a, 0x03, 0x21, 0x08, 0x42, 0x04, 0xd0, + 0xff, 0xf7, 0xf4, 0xfd, 0x68, 0x46, 0xf0, 0xf7, 0xe2, 0xf8, 0x00, 0x20, + 0xed, 0xf7, 0x9c, 0xff, 0x20, 0x46, 0xfe, 0xbd, 0x2d, 0xe9, 0xf0, 0x41, + 0x04, 0x46, 0x0d, 0x46, 0x00, 0x22, 0x03, 0x21, 0x40, 0xf2, 0xd1, 0x50, + 0xed, 0xf7, 0xe8, 0xfc, 0x4f, 0xf4, 0x7a, 0x70, 0xf1, 0xf7, 0x1e, 0xf9, + 0xc0, 0x22, 0xc0, 0x21, 0x4f, 0xf4, 0xd9, 0x70, 0xed, 0xf7, 0xde, 0xfc, + 0x41, 0xf2, 0x88, 0x33, 0x00, 0x22, 0xc0, 0x21, 0x4f, 0xf4, 0xd9, 0x70, + 0xf4, 0xf7, 0x90, 0xf9, 0x08, 0xb1, 0x01, 0x20, 0x60, 0xe0, 0x35, 0x4e, + 0x70, 0x79, 0xb1, 0x79, 0xf2, 0x79, 0x33, 0x7a, 0x37, 0x78, 0x01, 0xf0, + 0x07, 0x01, 0x40, 0xea, 0x01, 0x20, 0x03, 0xf0, 0x07, 0x01, 0x42, 0xea, + 0x01, 0x21, 0x08, 0x18, 0x80, 0xb2, 0x07, 0xf0, 0x3f, 0x01, 0xc1, 0xeb, + 0x50, 0x07, 0x2c, 0x48, 0x2c, 0x49, 0x00, 0x78, 0x09, 0x6b, 0x40, 0x07, + 0x4c, 0xbf, 0x2b, 0x48, 0x2b, 0x48, 0xb1, 0xfb, 0xf0, 0xf0, 0x00, 0x04, + 0xc0, 0x0a, 0xf1, 0xf7, 0xbd, 0xf9, 0x80, 0x46, 0xb8, 0xb2, 0xf1, 0xf7, + 0xc3, 0xf9, 0x01, 0x46, 0x40, 0x46, 0xf1, 0xf7, 0xcf, 0xf9, 0x07, 0x46, + 0x2f, 0x60, 0xf1, 0xf7, 0xc5, 0xfb, 0x80, 0x46, 0xa4, 0xf8, 0x00, 0x80, + 0x4f, 0xf0, 0x76, 0x50, 0x39, 0x46, 0xf1, 0xf7, 0x51, 0xfb, 0x28, 0x60, + 0x5f, 0xfa, 0x88, 0xf1, 0x40, 0xf2, 0xd3, 0x50, 0xed, 0xf7, 0x8c, 0xfc, + 0x20, 0x88, 0x01, 0x0a, 0x40, 0xf2, 0xd4, 0x50, 0xed, 0xf7, 0x86, 0xfc, + 0x70, 0x7a, 0xb1, 0x7a, 0xf7, 0x78, 0x36, 0x79, 0x40, 0xea, 0x01, 0x20, + 0x00, 0x03, 0xf1, 0xf7, 0x93, 0xf9, 0x80, 0x46, 0x47, 0xea, 0x06, 0x20, + 0xf1, 0xf7, 0x98, 0xf9, 0x01, 0x46, 0x40, 0x46, 0xf1, 0xf7, 0xa4, 0xf9, + 0x06, 0x46, 0x6e, 0x60, 0xf1, 0xf7, 0x9a, 0xfb, 0x60, 0x80, 0x31, 0x46, + 0x4f, 0xf0, 0x66, 0x50, 0xf1, 0xf7, 0x28, 0xfb, 0x68, 0x60, 0x00, 0x20, + 0xbd, 0xe8, 0xf0, 0x81, 0x00, 0x02, 0x00, 0x20, 0xdb, 0x05, 0x00, 0x46, + 0x20, 0x02, 0x00, 0x46, 0x78, 0x29, 0x00, 0x20, 0xd2, 0x05, 0x00, 0x46, + 0x02, 0x01, 0x00, 0x46, 0x00, 0xf2, 0x00, 0x20, 0x40, 0x4b, 0x4c, 0x00, + 0x00, 0x09, 0x3d, 0x00, 0x01, 0x22, 0x40, 0x1c, 0x02, 0xfa, 0x00, 0xf0, + 0x40, 0x1e, 0x80, 0xb2, 0x88, 0x42, 0x88, 0xbf, 0x08, 0x46, 0x70, 0x47, + 0x2d, 0xe9, 0xf0, 0x4f, 0x91, 0x46, 0x0f, 0xf2, 0xe0, 0x02, 0x83, 0xb0, + 0x04, 0x46, 0xb2, 0xe8, 0x08, 0x04, 0x68, 0x46, 0x00, 0x25, 0xa0, 0xe8, + 0x08, 0x04, 0x01, 0xf0, 0x07, 0x00, 0x40, 0xf0, 0x20, 0x01, 0x40, 0xf2, + 0xdd, 0x50, 0xed, 0xf7, 0x35, 0xfc, 0x00, 0x21, 0x40, 0xf2, 0xe2, 0x50, + 0xed, 0xf7, 0x30, 0xfc, 0x00, 0x27, 0x40, 0xf2, 0xe4, 0x5a, 0x40, 0xf2, + 0xe3, 0x5b, 0x0f, 0xf2, 0xc8, 0x08, 0x20, 0x88, 0x39, 0xf8, 0x17, 0x10, + 0x48, 0x43, 0x3d, 0xf8, 0x17, 0x10, 0xc1, 0xeb, 0x10, 0x11, 0x15, 0xf8, + 0x08, 0x00, 0x89, 0xb2, 0xff, 0xf7, 0xc8, 0xff, 0x00, 0xf0, 0x3e, 0xf8, + 0x00, 0xf0, 0x38, 0xf8, 0x6d, 0x1c, 0x7f, 0x1c, 0x04, 0x2f, 0xea, 0xdb, + 0x00, 0x27, 0x09, 0xeb, 0x47, 0x01, 0x60, 0x88, 0x09, 0x89, 0x48, 0x43, + 0x01, 0x01, 0x15, 0xf8, 0x08, 0x00, 0x09, 0x0c, 0xff, 0xf7, 0xb4, 0xff, + 0x00, 0xf0, 0x2a, 0xf8, 0x00, 0xf0, 0x24, 0xf8, 0x6d, 0x1c, 0x7f, 0x1c, + 0x07, 0x2f, 0xec, 0xdb, 0x00, 0x24, 0x09, 0xeb, 0x44, 0x00, 0x64, 0x1c, + 0xc1, 0x8a, 0x15, 0xf8, 0x08, 0x00, 0xff, 0xf7, 0xa3, 0xff, 0x00, 0xf0, + 0x19, 0xf8, 0x00, 0xf0, 0x13, 0xf8, 0x6d, 0x1c, 0x05, 0x2c, 0xf0, 0xdb, + 0x0f, 0xf2, 0x38, 0x05, 0x00, 0x24, 0x00, 0x21, 0x58, 0x46, 0xed, 0xf7, + 0xe9, 0xfb, 0x61, 0x5d, 0x50, 0x46, 0xed, 0xf7, 0xe5, 0xfb, 0x64, 0x1c, + 0x15, 0x2c, 0xf4, 0xdb, 0xbd, 0xe8, 0xf7, 0x8f, 0xf1, 0xb2, 0x50, 0x46, + 0xed, 0xf7, 0xdc, 0xbb, 0x06, 0x46, 0x30, 0x04, 0x01, 0x0e, 0x58, 0x46, + 0xed, 0xf7, 0xd6, 0xbb, 0x30, 0x01, 0xa0, 0x00, 0x70, 0x00, 0x40, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, + 0x2a, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x0a, 0x08, 0x06, 0x05, 0x0a, 0x0a, 0x0b, 0x09, 0x0a, 0x09, 0x0a, 0x05, + 0x05, 0x05, 0x05, 0x07, 0xb3, 0x49, 0x4f, 0xf4, 0x82, 0x72, 0x02, 0xfb, + 0x00, 0x11, 0x01, 0xf5, 0x21, 0x71, 0xff, 0xf7, 0x74, 0xb9, 0x38, 0xb5, + 0xae, 0x4c, 0x00, 0x20, 0x20, 0x70, 0x00, 0x21, 0x01, 0x20, 0xed, 0xf7, + 0xec, 0xfc, 0x00, 0x20, 0xf0, 0xf7, 0x9c, 0xf8, 0x00, 0x20, 0x01, 0x25, + 0x60, 0x70, 0x01, 0x21, 0x04, 0xe0, 0x00, 0x20, 0x28, 0x55, 0x29, 0x00, + 0x18, 0xbf, 0x01, 0x21, 0xc9, 0xb2, 0x01, 0x20, 0xed, 0xf7, 0xdb, 0xfc, + 0x28, 0x46, 0xf0, 0xf7, 0x8b, 0xf8, 0x6d, 0x1c, 0x02, 0x2d, 0xf0, 0xd3, + 0x31, 0xbd, 0x2d, 0xe9, 0xf0, 0x47, 0x9f, 0x4e, 0xdf, 0xf8, 0x7c, 0x82, + 0x70, 0x69, 0xdf, 0xf8, 0x70, 0x92, 0x0c, 0x46, 0xb1, 0x69, 0x00, 0x25, + 0x81, 0x42, 0x38, 0xbf, 0x08, 0x46, 0xf1, 0xf7, 0xa5, 0xf8, 0x4f, 0xf0, + 0x7c, 0x51, 0xf1, 0xf7, 0x3f, 0xfa, 0x98, 0x49, 0xf1, 0xf7, 0xae, 0xf8, + 0xf1, 0xf7, 0xa6, 0xfa, 0x96, 0x49, 0xb1, 0xf9, 0x0e, 0x20, 0x00, 0xb2, + 0x90, 0x42, 0xc8, 0xbf, 0x10, 0x46, 0xc8, 0x81, 0x00, 0x27, 0xb0, 0x7a, + 0x21, 0x61, 0x00, 0xf0, 0x03, 0x06, 0x08, 0x8a, 0x00, 0xf0, 0x03, 0xf9, + 0x60, 0x60, 0x26, 0xfa, 0x07, 0xf0, 0xc0, 0x07, 0x3e, 0xd5, 0x01, 0x20, + 0xb8, 0x40, 0xed, 0xf7, 0xcd, 0xfb, 0x08, 0xb9, 0x02, 0x25, 0x3a, 0xe0, + 0x39, 0x46, 0x01, 0x20, 0xf1, 0xf7, 0x73, 0xfe, 0x08, 0xb9, 0x03, 0x25, + 0x33, 0xe0, 0x27, 0x60, 0x39, 0x46, 0x00, 0xf0, 0xe7, 0xf8, 0xe0, 0x60, + 0x4f, 0xf4, 0xa0, 0x70, 0x00, 0xfb, 0x07, 0x9a, 0x0a, 0xf1, 0x04, 0x00, + 0xa0, 0x60, 0xed, 0xf7, 0x8d, 0xfc, 0x4f, 0xf0, 0x7e, 0x51, 0x38, 0x46, + 0xfe, 0xf7, 0xf7, 0xff, 0x4f, 0xf4, 0x82, 0x70, 0x00, 0xfb, 0x07, 0x90, + 0x00, 0xf5, 0x21, 0x71, 0x20, 0x46, 0xfe, 0xf7, 0x73, 0xfd, 0x05, 0x46, + 0x0a, 0xf1, 0x04, 0x00, 0xfe, 0xf7, 0x4e, 0xff, 0x0a, 0xf1, 0x54, 0x00, + 0xfe, 0xf7, 0x4a, 0xff, 0x43, 0x46, 0x01, 0x22, 0xf9, 0xb2, 0x01, 0x20, + 0xed, 0xf7, 0x5a, 0xfc, 0xed, 0xf7, 0x71, 0xfc, 0x15, 0xb9, 0x01, 0x20, + 0x07, 0xf8, 0x09, 0x00, 0x7f, 0x1c, 0x02, 0x2f, 0xb9, 0xd3, 0x28, 0x46, + 0xbd, 0xe8, 0xf0, 0x87, 0x38, 0x21, 0x6a, 0x48, 0xf2, 0xf7, 0x8c, 0xb8, + 0x2d, 0xe9, 0xfc, 0x4e, 0x81, 0x46, 0x68, 0x4e, 0x1c, 0x20, 0x00, 0xfb, + 0x09, 0x60, 0x0d, 0x46, 0x00, 0xf1, 0x28, 0x07, 0xef, 0xf3, 0x11, 0x80, + 0x60, 0x21, 0x81, 0xf3, 0x11, 0x88, 0x00, 0x21, 0xb9, 0x82, 0x39, 0x60, + 0x64, 0x21, 0x79, 0x60, 0x00, 0x21, 0xf9, 0x82, 0x80, 0xf3, 0x11, 0x88, + 0x06, 0xeb, 0xc9, 0x00, 0x01, 0x90, 0x34, 0x78, 0xdf, 0xf8, 0x54, 0xb1, + 0x20, 0x07, 0x44, 0xbf, 0x01, 0x98, 0x84, 0x69, 0x4f, 0xf4, 0x82, 0x70, + 0x00, 0xfb, 0x09, 0xb0, 0x00, 0xf5, 0x21, 0x7a, 0xe0, 0x07, 0x0a, 0xd5, + 0x01, 0x20, 0xb8, 0x82, 0x29, 0x46, 0x48, 0x46, 0x00, 0xf0, 0x3a, 0xf9, + 0x30, 0xb3, 0xb9, 0x8a, 0x40, 0xea, 0x01, 0x40, 0x38, 0x60, 0x38, 0x68, + 0x60, 0xb9, 0xa0, 0x07, 0x0d, 0xd5, 0x02, 0x20, 0xb8, 0x82, 0x29, 0x46, + 0x48, 0x46, 0x00, 0xf0, 0xd1, 0xf9, 0xc8, 0xb1, 0xb9, 0x8a, 0x40, 0xea, + 0x01, 0x40, 0x38, 0x60, 0x38, 0x68, 0x00, 0x28, 0x4d, 0xd1, 0x60, 0x07, + 0x4d, 0xd5, 0x03, 0x20, 0xb8, 0x82, 0x19, 0xf8, 0x0b, 0x00, 0x20, 0xb1, + 0x49, 0x46, 0x01, 0x20, 0xf1, 0xf7, 0xe3, 0xfd, 0x40, 0xb9, 0xb8, 0x8a, + 0x00, 0x04, 0x40, 0xf0, 0x03, 0x00, 0x3b, 0xe0, 0x38, 0x60, 0xdc, 0xe7, + 0x38, 0x60, 0xea, 0xe7, 0xa5, 0xf8, 0x00, 0x90, 0x30, 0x1d, 0xa8, 0x60, + 0xf0, 0x88, 0x00, 0xf0, 0x52, 0xf8, 0x68, 0x60, 0xc5, 0xf8, 0x0c, 0xa0, + 0x4f, 0xf4, 0xa0, 0x70, 0x00, 0xfb, 0x09, 0xb0, 0x01, 0x1d, 0xa4, 0x30, + 0x29, 0x61, 0x68, 0x61, 0x00, 0xf0, 0x3e, 0xf8, 0xa8, 0x61, 0x00, 0x20, + 0x28, 0x62, 0xee, 0xf7, 0x99, 0xfb, 0x83, 0x46, 0xbb, 0xf1, 0x2e, 0x0f, + 0x16, 0xd3, 0x00, 0xf0, 0x48, 0xf8, 0x29, 0x49, 0xf0, 0xf7, 0xd0, 0xff, + 0x00, 0x90, 0xab, 0xf1, 0x2d, 0x00, 0xf0, 0xf7, 0xbb, 0xff, 0x00, 0x99, + 0xf1, 0xf7, 0x56, 0xf9, 0xf8, 0xf7, 0x54, 0xf8, 0x40, 0x08, 0xf0, 0xf7, + 0x75, 0xf8, 0xa8, 0x70, 0x28, 0x46, 0xff, 0xf7, 0xa1, 0xf9, 0x04, 0xe0, + 0xb8, 0x8a, 0x00, 0x04, 0x40, 0xf0, 0x04, 0x00, 0x38, 0x60, 0x38, 0x68, + 0x98, 0xb9, 0x20, 0x07, 0x11, 0xd5, 0xa5, 0xf8, 0x00, 0x90, 0x30, 0x1d, + 0xa8, 0x60, 0xc5, 0xf8, 0x0c, 0xa0, 0x00, 0xf0, 0x0d, 0xf8, 0xa8, 0x61, + 0x00, 0x20, 0x28, 0x62, 0x01, 0x98, 0x00, 0xf1, 0x18, 0x01, 0x28, 0x46, + 0xff, 0xf7, 0x21, 0xfb, 0x38, 0x60, 0x38, 0x68, 0xbd, 0xe8, 0xf6, 0x8e, + 0xef, 0x61, 0x49, 0x46, 0x01, 0x20, 0xf1, 0xf7, 0x87, 0xbd, 0x00, 0xf0, + 0xc0, 0xb8, 0x10, 0xb5, 0xf0, 0xf7, 0x86, 0xff, 0x04, 0x46, 0x00, 0xf0, + 0x08, 0xf8, 0x21, 0x46, 0xf1, 0xf7, 0x1e, 0xf9, 0xbd, 0xe8, 0x10, 0x40, + 0x0a, 0x49, 0xf0, 0xf7, 0x8b, 0xbf, 0x03, 0x48, 0x00, 0x6c, 0xf0, 0xf7, + 0x77, 0xbf, 0x00, 0x00, 0x48, 0xa8, 0x00, 0x20, 0x78, 0x29, 0x00, 0x20, + 0xa5, 0x58, 0x01, 0x01, 0x00, 0x24, 0x74, 0x49, 0x68, 0x2b, 0x00, 0x20, + 0xb4, 0x2b, 0x00, 0x20, 0x8c, 0x2b, 0x00, 0x20, 0x00, 0x7c, 0x92, 0x4d, + 0x53, 0x48, 0x41, 0x89, 0x03, 0x22, 0x11, 0x42, 0x00, 0xd1, 0x70, 0x47, + 0x80, 0xb5, 0xc1, 0xf3, 0x01, 0x11, 0x61, 0xb1, 0x01, 0x6c, 0x80, 0x69, + 0xfc, 0xf7, 0x82, 0xfb, 0x05, 0x28, 0x28, 0xbf, 0x05, 0x20, 0x01, 0x21, + 0x01, 0xfa, 0x00, 0xf0, 0x4a, 0x49, 0x88, 0x60, 0xc8, 0x60, 0x01, 0xbd, + 0xc1, 0x68, 0xca, 0x07, 0x01, 0xd5, 0x04, 0x20, 0x70, 0x47, 0x8a, 0x07, + 0x01, 0xd5, 0x03, 0x20, 0x70, 0x47, 0x49, 0x07, 0x01, 0xd5, 0x05, 0x20, + 0x70, 0x47, 0x00, 0x69, 0x00, 0xb1, 0x06, 0x20, 0x70, 0x47, 0x2d, 0xe9, + 0xf0, 0x41, 0x04, 0x46, 0x0d, 0x46, 0xdf, 0xf8, 0xf8, 0x80, 0x08, 0xf1, + 0x08, 0x00, 0x68, 0x60, 0x00, 0x26, 0x00, 0x20, 0xee, 0xf7, 0x00, 0xfb, + 0x32, 0x28, 0x28, 0xd3, 0x6b, 0x68, 0x37, 0x49, 0x9f, 0x89, 0x93, 0xf8, + 0x0e, 0xc0, 0x5b, 0x8a, 0x09, 0x6c, 0x1b, 0x0a, 0x0c, 0xf0, 0x07, 0x0c, + 0x03, 0xf0, 0x07, 0x03, 0x01, 0x22, 0x63, 0x44, 0x9a, 0x40, 0x32, 0x38, + 0x92, 0xb2, 0xb0, 0xfb, 0xf2, 0xf0, 0xef, 0xf7, 0x8b, 0xf8, 0x4f, 0xf6, + 0xc0, 0x71, 0x39, 0x40, 0x01, 0x43, 0x29, 0x81, 0xef, 0xf7, 0xab, 0xf8, + 0xf0, 0xf7, 0x10, 0xff, 0x01, 0x46, 0x4f, 0xf0, 0x8f, 0x40, 0xf0, 0xf7, + 0x1b, 0xff, 0x00, 0xf0, 0xb5, 0xf9, 0xf7, 0xf7, 0xa5, 0xff, 0x68, 0x81, + 0x00, 0xe0, 0x07, 0x26, 0x00, 0x27, 0x86, 0xb9, 0x24, 0xfa, 0x07, 0xf0, + 0xc0, 0x07, 0x0c, 0xd5, 0x2f, 0x60, 0x28, 0x46, 0x00, 0xf0, 0xc7, 0xf9, + 0x28, 0x46, 0xff, 0xf7, 0xa9, 0xff, 0x06, 0x00, 0x03, 0xd1, 0x68, 0x69, + 0x08, 0xeb, 0x87, 0x01, 0x08, 0x62, 0x7f, 0x1c, 0x02, 0x2f, 0xea, 0xd3, + 0x30, 0x46, 0xbd, 0xe8, 0xf0, 0x81, 0x38, 0xb5, 0x0c, 0x46, 0x16, 0x48, + 0x14, 0x49, 0x00, 0x68, 0x89, 0x7a, 0x80, 0x08, 0x01, 0xf0, 0x03, 0x01, + 0x41, 0xea, 0x80, 0x05, 0x05, 0xf0, 0x03, 0x00, 0xed, 0xf7, 0x26, 0xfa, + 0x08, 0xb9, 0x02, 0x20, 0x32, 0xbd, 0x21, 0x46, 0x28, 0x46, 0xbd, 0xe8, + 0x34, 0x40, 0x96, 0xe7, 0x0b, 0x4a, 0x52, 0x68, 0x01, 0x23, 0x00, 0xf0, + 0x01, 0x00, 0x92, 0x08, 0x03, 0xfa, 0x00, 0xf0, 0x40, 0xea, 0x82, 0x00, + 0x8b, 0xe7, 0x02, 0x28, 0x06, 0xd2, 0x01, 0x46, 0x04, 0x4a, 0x02, 0xeb, + 0x80, 0x00, 0x00, 0x6a, 0x00, 0xf0, 0x2b, 0xba, 0x70, 0x47, 0x00, 0x00, + 0x78, 0x29, 0x00, 0x20, 0xf8, 0x28, 0x00, 0x20, 0xef, 0xf3, 0x11, 0x80, + 0x60, 0x21, 0x81, 0xf3, 0x11, 0x88, 0x70, 0x47, 0x80, 0xb5, 0x8a, 0x48, + 0xc1, 0x6a, 0x40, 0x6b, 0xfc, 0xf7, 0xd8, 0xfa, 0x88, 0x49, 0x4a, 0xe0, + 0x2d, 0xe9, 0xf8, 0x43, 0x0c, 0x46, 0x00, 0x27, 0x61, 0x68, 0x8d, 0x89, + 0x8e, 0x7d, 0x61, 0x78, 0x01, 0x29, 0x08, 0xbf, 0x01, 0x28, 0x32, 0xd1, + 0x00, 0x20, 0xee, 0xf7, 0x6d, 0xfa, 0x0f, 0x28, 0x38, 0xbf, 0x01, 0x27, + 0x2b, 0xd3, 0x62, 0x68, 0x7c, 0x49, 0x92, 0xf8, 0x0e, 0xc0, 0x52, 0x8a, + 0x09, 0x6c, 0x12, 0x0a, 0x0c, 0xf0, 0x07, 0x0c, 0x02, 0xf0, 0x07, 0x02, + 0x01, 0x23, 0x62, 0x44, 0x03, 0xfa, 0x02, 0xf2, 0x0f, 0x38, 0x92, 0xb2, + 0xb0, 0xfb, 0xf2, 0xf0, 0xee, 0xf7, 0xf6, 0xff, 0x80, 0x46, 0x05, 0xf0, + 0x3f, 0x00, 0xef, 0xf7, 0x18, 0xf8, 0x81, 0x46, 0x40, 0x46, 0xef, 0xf7, + 0x14, 0xf8, 0x48, 0x45, 0x0b, 0xd2, 0xb9, 0xfb, 0xf0, 0xf6, 0xb6, 0xb2, + 0x4f, 0xf6, 0xc0, 0x71, 0x70, 0x43, 0x29, 0x40, 0x48, 0x45, 0x48, 0xea, + 0x01, 0x05, 0x38, 0xbf, 0x76, 0x1c, 0x25, 0x81, 0x66, 0x81, 0x38, 0x46, + 0xbd, 0xe8, 0xf2, 0x83, 0x80, 0xb5, 0x64, 0x48, 0x01, 0x6c, 0x80, 0x69, + 0xfc, 0xf7, 0x8c, 0xfa, 0x63, 0x49, 0x81, 0xf8, 0x21, 0x00, 0x01, 0xbd, + 0x38, 0xb5, 0x0c, 0x46, 0x5f, 0x48, 0x5e, 0x49, 0x00, 0x68, 0x49, 0x89, + 0x80, 0x08, 0xc1, 0xf3, 0x81, 0x01, 0x41, 0xea, 0x80, 0x05, 0x05, 0xf0, + 0x03, 0x00, 0xed, 0xf7, 0x8b, 0xf9, 0x08, 0xb9, 0x01, 0x20, 0x32, 0xbd, + 0x22, 0x46, 0x29, 0x46, 0xbd, 0xe8, 0x38, 0x40, 0x00, 0x20, 0x22, 0xe0, + 0x38, 0xb5, 0x0c, 0x46, 0x54, 0x48, 0x52, 0x49, 0x00, 0x68, 0x89, 0x7a, + 0x80, 0x08, 0x01, 0xf0, 0x03, 0x01, 0x41, 0xea, 0x80, 0x05, 0x05, 0xf0, + 0x03, 0x00, 0xed, 0xf7, 0x81, 0xf9, 0x08, 0xb9, 0x02, 0x20, 0x32, 0xbd, + 0x22, 0x46, 0x29, 0x46, 0xbd, 0xe8, 0x38, 0x40, 0x00, 0x20, 0x54, 0xe0, + 0x0a, 0x46, 0x49, 0x49, 0x01, 0x23, 0x49, 0x68, 0x00, 0xf0, 0x01, 0x00, + 0x03, 0xfa, 0x00, 0xf0, 0x01, 0x43, 0x01, 0x20, 0x49, 0xe0, 0x2d, 0xe9, + 0xf8, 0x43, 0x0c, 0x46, 0x04, 0xf0, 0x04, 0x01, 0xdf, 0xf8, 0x00, 0x81, + 0x15, 0x46, 0x00, 0x26, 0xa9, 0x70, 0x6e, 0x70, 0x04, 0xf0, 0x08, 0x01, + 0xe9, 0x70, 0x2e, 0x61, 0x08, 0xf1, 0x08, 0x01, 0x69, 0x60, 0x29, 0x46, + 0xff, 0xf7, 0x62, 0xff, 0x00, 0xb1, 0x08, 0x26, 0x00, 0x27, 0x00, 0x20, + 0x02, 0xe0, 0x38, 0x00, 0x18, 0xbf, 0x01, 0x20, 0x2e, 0xbb, 0x24, 0xfa, + 0x07, 0xf1, 0xc9, 0x07, 0x21, 0xd5, 0x34, 0x49, 0x2f, 0x70, 0x4f, 0xf4, + 0x7c, 0x72, 0x02, 0xfb, 0x00, 0x16, 0x06, 0xf1, 0xe0, 0x00, 0xe8, 0x60, + 0x30, 0x1d, 0x68, 0x61, 0x14, 0x20, 0x00, 0xfb, 0x07, 0x89, 0x09, 0xf1, + 0x28, 0x01, 0x28, 0x46, 0x00, 0xf0, 0x58, 0xf8, 0x28, 0x46, 0x00, 0xf0, + 0x09, 0xfa, 0x6b, 0x6a, 0xaa, 0x6a, 0x29, 0x7e, 0x30, 0x46, 0xfa, 0xf7, + 0x37, 0xf9, 0x09, 0xf1, 0x28, 0x01, 0x28, 0x46, 0x00, 0xf0, 0x58, 0xf8, + 0x06, 0x46, 0x7f, 0x1c, 0x02, 0x2f, 0xd2, 0xd3, 0x30, 0x46, 0xbd, 0xe8, + 0xf2, 0x83, 0x2d, 0xe9, 0xf0, 0x41, 0x0c, 0x46, 0x15, 0x46, 0x01, 0x21, + 0x69, 0x70, 0x04, 0xf0, 0x04, 0x01, 0xa9, 0x70, 0x04, 0xf0, 0x08, 0x01, + 0xe9, 0x70, 0x00, 0x26, 0xdf, 0xf8, 0x60, 0x80, 0x6e, 0x61, 0x08, 0xf1, + 0x08, 0x01, 0x69, 0x60, 0x2e, 0x61, 0x05, 0xf5, 0xde, 0x71, 0xe9, 0x60, + 0x29, 0x46, 0xff, 0xf7, 0x13, 0xff, 0x00, 0xb1, 0x08, 0x26, 0x00, 0x27, + 0xae, 0xb9, 0x24, 0xfa, 0x07, 0xf0, 0xc0, 0x07, 0x11, 0xd5, 0x14, 0x20, + 0x00, 0xfb, 0x07, 0x86, 0x2f, 0x70, 0x06, 0xf1, 0x24, 0x01, 0x28, 0x46, + 0x00, 0xf0, 0x18, 0xf8, 0x28, 0x46, 0x00, 0xf0, 0xc9, 0xf9, 0x06, 0xf1, + 0x24, 0x01, 0x28, 0x46, 0x00, 0xf0, 0x1e, 0xf8, 0x06, 0x46, 0x7f, 0x1c, + 0x02, 0x2f, 0xe5, 0xd3, 0x30, 0x46, 0xbd, 0xe8, 0xf0, 0x81, 0x00, 0x00, + 0x78, 0x29, 0x00, 0x20, 0xdc, 0x29, 0x00, 0x20, 0x2c, 0x2a, 0x00, 0x20, + 0xc0, 0x92, 0x00, 0x20, 0x10, 0xb5, 0x0c, 0x46, 0xff, 0xf7, 0xd8, 0xfe, + 0x01, 0x21, 0x61, 0x60, 0x00, 0x21, 0x21, 0x60, 0xa1, 0x60, 0xe1, 0x60, + 0x21, 0x61, 0x80, 0xf3, 0x11, 0x88, 0x10, 0xbd, 0x70, 0xb5, 0x04, 0x46, + 0x0d, 0x46, 0x20, 0x6a, 0xc1, 0x07, 0x48, 0xbf, 0x04, 0x26, 0x1b, 0xd4, + 0x81, 0x07, 0x48, 0xbf, 0x03, 0x26, 0x17, 0xd4, 0x40, 0x07, 0x48, 0xbf, + 0x07, 0x26, 0x13, 0xd4, 0x60, 0x7e, 0x08, 0xb1, 0x0a, 0x26, 0x0f, 0xe0, + 0xa0, 0x7e, 0x81, 0x07, 0x48, 0xbf, 0x09, 0x26, 0x0a, 0xd4, 0xc0, 0x07, + 0x05, 0xd4, 0xe0, 0x7e, 0x08, 0xb1, 0x05, 0x26, 0x04, 0xe0, 0x20, 0x7f, + 0x08, 0xb1, 0x06, 0x26, 0x00, 0xe0, 0x00, 0x26, 0xff, 0xf7, 0xa8, 0xfe, + 0x2e, 0x60, 0xa1, 0x6a, 0xa9, 0x60, 0x61, 0x6a, 0xe9, 0x60, 0x21, 0x7e, + 0x29, 0x61, 0x00, 0x21, 0x69, 0x60, 0x80, 0xf3, 0x11, 0x88, 0x30, 0x46, + 0x70, 0xbd, 0x00, 0x00, 0xc0, 0xf3, 0xc7, 0x52, 0x7e, 0x3a, 0xcc, 0xbf, + 0xd2, 0xf1, 0x18, 0x0c, 0x07, 0xe0, 0x6f, 0xf0, 0x7f, 0x41, 0xd1, 0x40, + 0x00, 0x42, 0x58, 0xbf, 0x40, 0x18, 0x88, 0x43, 0x70, 0x47, 0x18, 0x2a, + 0x06, 0xda, 0x41, 0x00, 0x18, 0xbf, 0x4f, 0xf0, 0x7e, 0x50, 0x28, 0xbf, + 0x4f, 0xf0, 0x00, 0x40, 0x70, 0x47, 0x00, 0x00, 0x00, 0x21, 0xc0, 0xf8, + 0x98, 0x10, 0x40, 0xf8, 0x0c, 0x1f, 0x41, 0x60, 0x70, 0x47, 0x10, 0xb5, + 0x04, 0x46, 0xff, 0xf7, 0xf5, 0xff, 0x00, 0x21, 0x01, 0x20, 0xfe, 0xf7, + 0x4b, 0xf9, 0x20, 0x46, 0xbd, 0xe8, 0x10, 0x40, 0x2d, 0xe9, 0xf0, 0x41, + 0x05, 0x46, 0x4f, 0xf4, 0x80, 0x70, 0x29, 0x68, 0x00, 0xf0, 0x8b, 0xf8, + 0x00, 0xf0, 0x87, 0xf8, 0x04, 0x46, 0xd5, 0xf8, 0x98, 0x00, 0x00, 0x28, + 0x7a, 0xd1, 0x29, 0x68, 0x4f, 0xf4, 0x40, 0x70, 0x00, 0xf0, 0x7f, 0xf8, + 0x00, 0xf0, 0x7b, 0xf8, 0x01, 0x46, 0xd5, 0xf8, 0x98, 0x00, 0x00, 0x28, + 0x6e, 0xd1, 0x20, 0x46, 0xf0, 0xf7, 0x98, 0xfd, 0x01, 0x46, 0x4f, 0xf0, + 0x44, 0x40, 0xf0, 0xf7, 0x15, 0xfd, 0x80, 0x46, 0x20, 0x46, 0x41, 0x46, + 0xf0, 0xf7, 0x9e, 0xfe, 0x00, 0x21, 0xf0, 0xf7, 0xa3, 0xff, 0x94, 0xbf, + 0x4f, 0xf0, 0x7c, 0x51, 0x4f, 0xf0, 0x3f, 0x41, 0xf0, 0xf7, 0xf8, 0xfd, + 0xf0, 0xf7, 0xfe, 0xfe, 0xc0, 0xf5, 0x80, 0x70, 0x00, 0xf0, 0x54, 0xf8, + 0x00, 0xf0, 0x57, 0xf8, 0x07, 0x46, 0xd5, 0xf8, 0x98, 0x00, 0x00, 0x28, + 0x4a, 0xd1, 0x4f, 0xf0, 0x40, 0x40, 0x39, 0x46, 0xf0, 0xf7, 0x82, 0xfe, + 0x41, 0x46, 0xf0, 0xf7, 0x7f, 0xfe, 0x00, 0x21, 0xf0, 0xf7, 0x84, 0xff, + 0x04, 0x46, 0x94, 0xbf, 0x4f, 0xf0, 0x7c, 0x50, 0x4f, 0xf0, 0x3f, 0x40, + 0x21, 0x46, 0xf0, 0xf7, 0xd7, 0xfd, 0xf0, 0xf7, 0xdd, 0xfe, 0x00, 0x28, + 0x54, 0xbf, 0x08, 0x20, 0x6f, 0xf0, 0x07, 0x00, 0x84, 0x19, 0xb4, 0xf5, + 0x80, 0x6f, 0x28, 0xbf, 0x34, 0x1a, 0x29, 0x68, 0x20, 0x46, 0x00, 0xf0, + 0x30, 0xf8, 0x00, 0xf0, 0x2c, 0xf8, 0x80, 0x46, 0xd5, 0xf8, 0x98, 0x00, + 0x00, 0xbb, 0xa0, 0x1b, 0xf0, 0xf7, 0xb2, 0xfc, 0x39, 0x46, 0xf0, 0xf7, + 0x57, 0xfe, 0x04, 0x46, 0x40, 0x46, 0x39, 0x46, 0xf0, 0xf7, 0x42, 0xfd, + 0x01, 0x46, 0x20, 0x46, 0xf0, 0xf7, 0xc0, 0xfc, 0x00, 0x21, 0xf0, 0xf7, + 0x53, 0xff, 0x04, 0x46, 0x94, 0xbf, 0x4f, 0xf0, 0x7c, 0x50, 0x4f, 0xf0, + 0x3f, 0x40, 0x21, 0x46, 0xf0, 0xf7, 0xa6, 0xfd, 0xf0, 0xf7, 0xac, 0xfe, + 0x30, 0x1a, 0x00, 0xf0, 0x03, 0xf8, 0x6e, 0x61, 0xbd, 0xe8, 0xf0, 0x81, + 0x80, 0xf3, 0x0a, 0x06, 0x29, 0x68, 0x30, 0x46, 0x01, 0xe0, 0x28, 0x46, + 0x38, 0xe0, 0x70, 0xb5, 0x04, 0x46, 0x00, 0x29, 0x07, 0xbf, 0x40, 0xf2, + 0xe1, 0x65, 0x4f, 0xf4, 0xdc, 0x60, 0x40, 0xf2, 0xe3, 0x65, 0x40, 0xf2, + 0xe2, 0x60, 0xef, 0xf3, 0x11, 0x86, 0x60, 0x21, 0x81, 0xf3, 0x11, 0x88, + 0xa1, 0x05, 0x09, 0x0e, 0xec, 0xf7, 0x60, 0xff, 0x04, 0xf0, 0x03, 0x04, + 0x00, 0xf0, 0x0f, 0xf8, 0x44, 0xf0, 0x80, 0x01, 0x00, 0xf0, 0x0c, 0xf8, + 0x00, 0xf0, 0x09, 0xf8, 0x00, 0xf0, 0x07, 0xf8, 0x05, 0xf1, 0x8c, 0x40, + 0x01, 0x78, 0x00, 0x78, 0x86, 0xf3, 0x11, 0x88, 0x70, 0xbd, 0x21, 0x46, + 0x28, 0x46, 0xec, 0xf7, 0x49, 0xbf, 0x00, 0x21, 0x01, 0x22, 0x20, 0xfa, + 0x02, 0xf3, 0xdb, 0x07, 0x01, 0xd5, 0x11, 0x46, 0x02, 0xe0, 0x52, 0x1c, + 0x18, 0x2a, 0xf6, 0xd3, 0x08, 0x46, 0x70, 0x47, 0x70, 0xb5, 0x04, 0x46, + 0x60, 0x68, 0x40, 0x68, 0xff, 0xf7, 0xed, 0xff, 0x05, 0xb2, 0x20, 0x68, + 0x20, 0x76, 0x01, 0x20, 0x60, 0x76, 0x00, 0x20, 0xa0, 0x76, 0x60, 0x68, + 0xe0, 0x61, 0x04, 0xf1, 0x08, 0x00, 0x20, 0x62, 0x00, 0x20, 0x60, 0x62, + 0x04, 0xf1, 0x18, 0x00, 0xfd, 0xf7, 0x80, 0xfe, 0xe0, 0x6a, 0xe0, 0x60, + 0x08, 0xb1, 0x01, 0x20, 0x07, 0xe0, 0xa0, 0x6b, 0xa8, 0x42, 0x04, 0xbf, + 0xe0, 0x6b, 0xe8, 0x42, 0x03, 0xd0, 0x01, 0x20, 0x20, 0x61, 0xc4, 0xf8, + 0x98, 0x00, 0x00, 0x20, 0xd4, 0xf8, 0x98, 0x10, 0x00, 0x29, 0x41, 0xd1, + 0xd4, 0xe9, 0x12, 0x01, 0xf0, 0xf7, 0xf0, 0xfb, 0x05, 0x46, 0xd4, 0xe9, + 0x10, 0x01, 0xf0, 0xf7, 0xeb, 0xfb, 0x01, 0x46, 0x28, 0x46, 0xf0, 0xf7, + 0x33, 0xfc, 0x05, 0x46, 0xd4, 0xe9, 0x16, 0x01, 0xf0, 0xf7, 0xe2, 0xfb, + 0x06, 0x46, 0xd4, 0xe9, 0x14, 0x01, 0xf0, 0xf7, 0xdd, 0xfb, 0x01, 0x46, + 0x30, 0x46, 0xf0, 0xf7, 0x25, 0xfc, 0x04, 0x46, 0x28, 0x46, 0x29, 0x46, + 0xf0, 0xf7, 0xae, 0xfd, 0x29, 0x46, 0xf0, 0xf7, 0xab, 0xfd, 0x10, 0x49, + 0xf0, 0xf7, 0x1a, 0xfc, 0x01, 0x46, 0x28, 0x46, 0xf0, 0xf7, 0x94, 0xfc, + 0x05, 0x46, 0x20, 0x46, 0x21, 0x46, 0xf0, 0xf7, 0x9f, 0xfd, 0x21, 0x46, + 0xf0, 0xf7, 0x9c, 0xfd, 0x08, 0x49, 0xf0, 0xf7, 0x0b, 0xfc, 0x01, 0x46, + 0x20, 0x46, 0xf0, 0xf7, 0x85, 0xfc, 0x29, 0x46, 0xf0, 0xf7, 0xf6, 0xfc, + 0xbd, 0xe8, 0x70, 0x40, 0x4f, 0xf0, 0x7c, 0x51, 0xf0, 0xf7, 0x8c, 0xbd, + 0x70, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x00, 0x21, 0x41, 0x63, + 0x01, 0x62, 0x41, 0x76, 0x81, 0x76, 0xc1, 0x76, 0x01, 0x77, 0x70, 0x47, + 0x10, 0xb5, 0x04, 0x46, 0xff, 0xf7, 0xf4, 0xff, 0x20, 0x46, 0x00, 0xf0, + 0x8f, 0xf8, 0x20, 0x6a, 0x60, 0xb9, 0xa0, 0x78, 0x02, 0x28, 0x09, 0xd0, + 0xe0, 0x78, 0x00, 0x28, 0x04, 0xbf, 0x60, 0x6b, 0x00, 0x28, 0x03, 0xd1, + 0x20, 0x46, 0xbd, 0xe8, 0x10, 0x40, 0x13, 0xe0, 0x10, 0xbd, 0x10, 0xb5, + 0xb4, 0xb0, 0x04, 0x46, 0x00, 0x20, 0x00, 0x90, 0x69, 0x46, 0x20, 0x46, + 0xfc, 0xf7, 0x74, 0xfa, 0x6b, 0x46, 0x01, 0xaa, 0x04, 0xf5, 0x79, 0x71, + 0x04, 0xf5, 0x96, 0x60, 0xfb, 0xf7, 0xfb, 0xff, 0x34, 0xb0, 0x10, 0xbd, + 0xf8, 0xb5, 0x04, 0x46, 0x6a, 0x46, 0x60, 0x78, 0x25, 0x78, 0x00, 0x28, + 0x0c, 0xbf, 0x2e, 0x46, 0x02, 0x26, 0x00, 0x21, 0x00, 0x20, 0xed, 0xf7, + 0x92, 0xfa, 0x00, 0x98, 0x10, 0xb9, 0x01, 0x20, 0x60, 0x76, 0xf1, 0xbd, + 0x00, 0x99, 0x2b, 0x4a, 0x00, 0x20, 0x08, 0x60, 0x00, 0x99, 0x48, 0x71, + 0x00, 0x99, 0x94, 0xf8, 0xb8, 0x01, 0x08, 0x71, 0x00, 0x99, 0x60, 0x6a, + 0xc8, 0x60, 0x00, 0x99, 0xa0, 0x6a, 0x08, 0x61, 0x00, 0x99, 0x00, 0x98, + 0x00, 0xf5, 0x96, 0x60, 0x48, 0x61, 0x04, 0xf1, 0x38, 0x00, 0x00, 0x99, + 0x88, 0x60, 0x60, 0x68, 0x00, 0x99, 0x18, 0x30, 0x88, 0x61, 0x00, 0x21, + 0x00, 0x20, 0xed, 0xf7, 0xf8, 0xfa, 0x00, 0x98, 0x00, 0x7f, 0xa0, 0x76, + 0x60, 0x69, 0x28, 0xb1, 0x00, 0x99, 0xcc, 0x22, 0x01, 0xf5, 0x79, 0x71, + 0xf3, 0xf7, 0x92, 0xfc, 0xe0, 0x68, 0x28, 0xb1, 0x00, 0x99, 0xcc, 0x22, + 0x01, 0xf5, 0x96, 0x61, 0xf3, 0xf7, 0x8a, 0xfc, 0xef, 0xf3, 0x11, 0x87, + 0x60, 0x20, 0x80, 0xf3, 0x11, 0x88, 0x30, 0x46, 0xee, 0xf7, 0x23, 0xff, + 0x00, 0x99, 0x01, 0xf5, 0x79, 0x71, 0xee, 0xf7, 0xbd, 0xfe, 0x10, 0xb9, + 0x01, 0x20, 0xe0, 0x76, 0x0b, 0xe0, 0x00, 0x2d, 0x0c, 0xbf, 0x0a, 0x21, + 0x0e, 0x21, 0x30, 0x46, 0xee, 0xf7, 0x1f, 0xff, 0x60, 0x78, 0x10, 0xb9, + 0x28, 0x46, 0xf8, 0xf7, 0xf4, 0xf9, 0x87, 0xf3, 0x11, 0x88, 0x00, 0x20, + 0xed, 0xf7, 0x7f, 0xfa, 0xf1, 0xbd, 0x00, 0x00, 0xcb, 0x62, 0x01, 0x01, + 0x10, 0xb5, 0x04, 0x46, 0xa0, 0xb0, 0x20, 0x78, 0x8d, 0xf8, 0x00, 0x00, + 0x60, 0x78, 0x8d, 0xf8, 0x01, 0x00, 0xa0, 0x78, 0x8d, 0xf8, 0x02, 0x00, + 0x60, 0x68, 0x01, 0x90, 0x04, 0xf1, 0x08, 0x00, 0x02, 0x90, 0x04, 0xf1, + 0x38, 0x00, 0x03, 0x90, 0xa1, 0x78, 0x60, 0x78, 0xfd, 0xf7, 0x54, 0xff, + 0x68, 0x46, 0xfd, 0xf7, 0x6d, 0xfd, 0x20, 0x69, 0x20, 0xb1, 0x03, 0x99, + 0x4f, 0xf4, 0xc0, 0x72, 0xf3, 0xf7, 0x42, 0xfc, 0x9d, 0xf9, 0x10, 0x00, + 0x40, 0x42, 0x84, 0xf8, 0xb8, 0x01, 0x9d, 0xf8, 0x11, 0x00, 0x20, 0x76, + 0x05, 0x98, 0x20, 0x62, 0x06, 0x98, 0x60, 0x62, 0x07, 0x98, 0xa0, 0x62, + 0x20, 0xb0, 0x10, 0xbd, 0x00, 0x21, 0x00, 0x20, 0x10, 0xb5, 0xed, 0xf7, + 0x4a, 0xf8, 0x60, 0x48, 0x01, 0x78, 0x00, 0x24, 0x39, 0xb1, 0x41, 0x78, + 0x90, 0xf9, 0x02, 0x00, 0x40, 0x18, 0xc0, 0xb2, 0x00, 0xf0, 0x00, 0xf9, + 0x0d, 0xe0, 0x5b, 0x48, 0x80, 0x7a, 0x10, 0xf0, 0x03, 0x00, 0x08, 0xbf, + 0x01, 0x24, 0x06, 0xd0, 0x00, 0xf0, 0x01, 0x00, 0x80, 0xf0, 0x01, 0x00, + 0x00, 0xf0, 0x06, 0xf8, 0x04, 0x46, 0x00, 0x20, 0xed, 0xf7, 0x8a, 0xf8, + 0x20, 0x46, 0x10, 0xbd, 0x2d, 0xe9, 0xf0, 0x4f, 0x89, 0xb0, 0x05, 0x46, + 0x04, 0xa8, 0xef, 0xf7, 0x7c, 0xfa, 0x69, 0x46, 0x28, 0x46, 0xf0, 0xf7, + 0x15, 0xff, 0xdd, 0xe9, 0x00, 0x01, 0xcd, 0xe9, 0x02, 0x01, 0x02, 0xaa, + 0x02, 0x21, 0x28, 0x46, 0xf0, 0xf7, 0x43, 0xff, 0x00, 0x21, 0x00, 0x20, + 0x00, 0xf0, 0xd4, 0xf8, 0x01, 0x21, 0xe8, 0xb2, 0xef, 0xf7, 0x68, 0xf9, + 0x44, 0x4a, 0x0f, 0xf2, 0xc0, 0x19, 0xd2, 0xe9, 0x08, 0x01, 0xef, 0xf7, + 0x11, 0xfa, 0x01, 0x46, 0xe8, 0xb2, 0xef, 0xf7, 0x2b, 0xfa, 0x3e, 0x48, + 0xc0, 0x69, 0x40, 0x00, 0x05, 0x21, 0xb0, 0xfb, 0xf1, 0xf2, 0x00, 0x23, + 0x28, 0x46, 0xfe, 0xf7, 0x91, 0xf9, 0x3b, 0x48, 0x3b, 0x49, 0x00, 0x78, + 0x08, 0x70, 0x06, 0x23, 0x0f, 0xf2, 0x84, 0x12, 0x80, 0x08, 0x06, 0x21, + 0x90, 0xfb, 0xf1, 0xf1, 0x03, 0xfb, 0x11, 0x00, 0x88, 0x46, 0x10, 0xf8, + 0x02, 0xa0, 0x00, 0x26, 0x01, 0xe0, 0x00, 0x2c, 0x46, 0xd1, 0x00, 0x27, + 0x5f, 0xfa, 0x87, 0xfb, 0x19, 0xf8, 0x1b, 0x10, 0x40, 0xf2, 0x32, 0x70, + 0xec, 0xf7, 0x88, 0xfd, 0x09, 0xeb, 0x4b, 0x00, 0x00, 0x24, 0x41, 0x78, + 0x40, 0xf2, 0x34, 0x70, 0xec, 0xf7, 0x80, 0xfd, 0x01, 0x21, 0x40, 0xf2, + 0x33, 0x70, 0xec, 0xf7, 0x7b, 0xfd, 0x00, 0x21, 0x40, 0xf2, 0x35, 0x70, + 0xec, 0xf7, 0x76, 0xfd, 0x51, 0x46, 0x40, 0xf2, 0x36, 0x70, 0xec, 0xf7, + 0x71, 0xfd, 0xff, 0x21, 0x40, 0xf2, 0x31, 0x70, 0xec, 0xf7, 0x6c, 0xfd, + 0x00, 0x2d, 0x0c, 0xbf, 0x4f, 0xf0, 0x01, 0x0b, 0x4f, 0xf0, 0x02, 0x0b, + 0x4b, 0xea, 0x48, 0x11, 0xc9, 0xb2, 0x4f, 0xf4, 0xe6, 0x60, 0xec, 0xf7, + 0x5f, 0xfd, 0x42, 0xf2, 0x10, 0x73, 0x00, 0x22, 0x59, 0x46, 0x4f, 0xf4, + 0xe6, 0x60, 0xf3, 0xf7, 0x1b, 0xfa, 0x00, 0xb1, 0x03, 0x24, 0x4c, 0xb9, + 0x14, 0x48, 0x00, 0x78, 0x06, 0xa9, 0x71, 0x18, 0x07, 0xeb, 0x47, 0x02, + 0x7f, 0x1c, 0x50, 0x54, 0x02, 0x2f, 0xb9, 0xd3, 0x76, 0x1c, 0x03, 0x2e, + 0xb3, 0xd3, 0x1c, 0xb9, 0x06, 0xa8, 0x00, 0xf0, 0x1b, 0xf8, 0x04, 0x46, + 0x69, 0x46, 0x28, 0x46, 0xf0, 0xf7, 0xa8, 0xfe, 0xfe, 0xf7, 0xe8, 0xf8, + 0x04, 0xa8, 0xef, 0xf7, 0xf3, 0xf9, 0x20, 0x46, 0x09, 0xb0, 0xbd, 0xe8, + 0xf0, 0x8f, 0x00, 0x00, 0xb4, 0x2a, 0x00, 0x20, 0x78, 0x29, 0x00, 0x20, + 0x00, 0xf2, 0x00, 0x20, 0xe6, 0x04, 0x00, 0x46, 0x9f, 0xf3, 0x00, 0x20, + 0x37, 0x07, 0x00, 0x46, 0x70, 0xb5, 0x00, 0x24, 0x00, 0x22, 0x00, 0xeb, + 0x42, 0x03, 0x00, 0x21, 0xd9, 0x80, 0x02, 0xeb, 0x42, 0x06, 0x36, 0x18, + 0xdd, 0x88, 0x8e, 0x5d, 0x49, 0x1c, 0x75, 0x19, 0x03, 0x29, 0xdd, 0x80, + 0xf5, 0xd3, 0xad, 0xb2, 0x03, 0x21, 0x52, 0x1c, 0xb5, 0xfb, 0xf1, 0xf1, + 0x02, 0x2a, 0xd9, 0x80, 0xe9, 0xd3, 0x00, 0x22, 0x00, 0x21, 0x02, 0xeb, + 0x42, 0x03, 0x1b, 0x18, 0xcb, 0x5c, 0x5b, 0xb1, 0x80, 0x2b, 0x09, 0xda, + 0x00, 0xeb, 0x42, 0x06, 0xf6, 0x88, 0x9d, 0x1b, 0x4c, 0xbf, 0xf3, 0x1a, + 0x9b, 0x1b, 0x9b, 0xb2, 0x04, 0x2b, 0x00, 0xd3, 0x02, 0x24, 0x49, 0x1c, + 0x03, 0x29, 0xea, 0xd3, 0x52, 0x1c, 0x02, 0x2a, 0xe6, 0xd3, 0x3c, 0xb9, + 0xc1, 0x88, 0x00, 0x89, 0x09, 0x1a, 0xc9, 0xb2, 0x48, 0x1e, 0xc0, 0xb2, + 0x00, 0xf0, 0x02, 0xf8, 0x20, 0x46, 0x70, 0xbd, 0x10, 0xb5, 0x0c, 0x46, + 0x01, 0x46, 0x40, 0xf6, 0x65, 0x10, 0xec, 0xf7, 0xe3, 0xfc, 0x21, 0x46, + 0xbd, 0xe8, 0x10, 0x40, 0x40, 0xf6, 0x66, 0x10, 0xec, 0xf7, 0xdc, 0xbc, + 0xcb, 0xb5, 0xa1, 0x8f, 0x80, 0x72, 0x00, 0x00, 0x78, 0x00, 0x01, 0x28, + 0x3e, 0x48, 0x0f, 0xf2, 0x10, 0x12, 0x2d, 0xe9, 0xf0, 0x4f, 0x44, 0x68, + 0xef, 0xf3, 0x08, 0x80, 0x20, 0x60, 0x00, 0x21, 0xef, 0xf3, 0x09, 0x80, + 0x60, 0x60, 0xef, 0xf3, 0x03, 0x80, 0xe0, 0x60, 0x04, 0xf1, 0x10, 0x00, + 0x52, 0xf8, 0x21, 0x30, 0x1b, 0x68, 0x40, 0xf8, 0x21, 0x30, 0x49, 0x1c, + 0x13, 0x29, 0xf7, 0xd3, 0x15, 0x22, 0x04, 0xf1, 0x5c, 0x01, 0x0f, 0xf2, + 0x24, 0x10, 0xec, 0xf7, 0xe6, 0xfc, 0x20, 0x68, 0x41, 0x6c, 0xa1, 0x60, + 0x11, 0xf1, 0x0f, 0x0f, 0x18, 0xbf, 0x11, 0xf1, 0x07, 0x0f, 0x06, 0xd1, + 0xc1, 0x6d, 0x61, 0x67, 0x00, 0x6e, 0xa0, 0x67, 0x20, 0x68, 0x40, 0x6e, + 0x02, 0xe0, 0x00, 0x20, 0x60, 0x67, 0xa0, 0x67, 0xe0, 0x67, 0x25, 0x48, + 0x00, 0x68, 0x90, 0xf8, 0x32, 0x00, 0xc4, 0xf8, 0x80, 0x00, 0xbd, 0xe8, + 0xf0, 0x4f, 0x70, 0x47, 0x2d, 0xe9, 0xf0, 0x4f, 0x20, 0x4c, 0x4f, 0xf0, + 0xee, 0x31, 0x20, 0x46, 0xec, 0xf7, 0xd9, 0xfc, 0x1b, 0x4d, 0x1e, 0x49, + 0xef, 0xf3, 0x08, 0x80, 0xa8, 0x60, 0x88, 0x42, 0x24, 0xbf, 0x1c, 0x4a, + 0x82, 0x42, 0x04, 0xd2, 0x1b, 0x48, 0x08, 0x18, 0x40, 0x08, 0x80, 0xf3, + 0x08, 0x88, 0x05, 0xf1, 0x0c, 0x00, 0x68, 0x60, 0xff, 0xf7, 0xa6, 0xff, + 0x0d, 0x20, 0xf1, 0xf7, 0x56, 0xfc, 0x4f, 0xf0, 0xff, 0x31, 0x20, 0x46, + 0xec, 0xf7, 0xbd, 0xfc, 0x80, 0x22, 0x00, 0x23, 0x80, 0x20, 0x00, 0x21, + 0xf1, 0xf7, 0xd6, 0xfc, 0x0a, 0x20, 0xf7, 0xf7, 0xc1, 0xf8, 0xf8, 0xf7, + 0x77, 0xfe, 0x00, 0xb1, 0x01, 0x20, 0x28, 0x70, 0xf8, 0xf7, 0x5a, 0xfe, + 0x20, 0x68, 0x00, 0x28, 0xfc, 0xd1, 0x28, 0x78, 0x08, 0xb1, 0xf8, 0xf7, + 0x4d, 0xfe, 0xf7, 0xf7, 0xbb, 0xf8, 0xbd, 0xe8, 0xf0, 0x4f, 0x70, 0x47, + 0xe8, 0xb7, 0x00, 0x20, 0x40, 0xbd, 0x00, 0x20, 0xf0, 0x7f, 0x01, 0x01, + 0x90, 0xb8, 0x00, 0x20, 0x6c, 0xbc, 0x00, 0x20, 0x90, 0xbc, 0x00, 0x20, + 0x00, 0xe3, 0x00, 0xe0, 0x04, 0xe3, 0x00, 0xe0, 0x04, 0xed, 0x00, 0xe0, + 0x24, 0xed, 0x00, 0xe0, 0x28, 0xed, 0x00, 0xe0, 0x2c, 0xed, 0x00, 0xe0, + 0x38, 0xed, 0x00, 0xe0, 0x40, 0x00, 0x00, 0x50, 0x44, 0x00, 0x00, 0x50, + 0x48, 0x00, 0x00, 0x50, 0x40, 0x00, 0x00, 0x58, 0x44, 0x00, 0x00, 0x58, + 0x00, 0x00, 0x00, 0x49, 0x04, 0x00, 0x00, 0x49, 0x08, 0x00, 0x00, 0x49, + 0x0c, 0x00, 0x00, 0x49, 0x10, 0x00, 0x00, 0x49, 0x14, 0x00, 0x00, 0x49, + 0x18, 0x00, 0x00, 0x49, 0x00, 0x0d, 0x01, 0x0d, 0x08, 0x0d, 0x09, 0x0d, + 0x50, 0x0c, 0x51, 0x0c, 0x52, 0x0c, 0x53, 0x0c, 0x54, 0x0c, 0x55, 0x0c, + 0x56, 0x0c, 0x57, 0x0c, 0x58, 0x0c, 0x59, 0x0c, 0x5a, 0x0c, 0x5b, 0x0c, + 0x5c, 0x0c, 0x5d, 0x0c, 0x5e, 0x0c, 0x5f, 0x0c, 0x60, 0x0c, 0x00, 0x00, + 0xb8, 0x2a, 0x00, 0x20, 0x22, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x20, + 0x86, 0x00, 0x00, 0x00, 0x88, 0xf3, 0x00, 0x20, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb4, 0x2a, 0x00, 0x20, + 0x03, 0x00, 0x00, 0x00, 0x70, 0x29, 0x00, 0x20, 0x08, 0x00, 0x00, 0x00, + 0x68, 0xf3, 0x00, 0x20, 0x01, 0x00, 0x00, 0x00, 0x20, 0x29, 0x00, 0x20, + 0x2c, 0x00, 0x00, 0x00, 0xdc, 0x2a, 0x00, 0x20, 0x48, 0x00, 0x00, 0x00, + 0xdc, 0x2a, 0x00, 0x20, 0x48, 0x00, 0x00, 0x00, 0x68, 0x2b, 0x00, 0x20, + 0x24, 0x00, 0x00, 0x00, 0xf8, 0x28, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00, + 0x2c, 0x2a, 0x00, 0x20, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xdc, 0x29, 0x00, 0x20, 0x28, 0x00, 0x00, 0x00, + 0x9c, 0x28, 0x00, 0x20, 0x18, 0x00, 0x00, 0x00, 0xc0, 0x26, 0x00, 0x20, + 0x18, 0x00, 0x00, 0x00, 0x2c, 0x2c, 0x00, 0x20, 0x2c, 0x00, 0x00, 0x00, + 0x70, 0xf3, 0x00, 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x2a, 0x00, 0x20, + 0x64, 0x2a, 0x00, 0x20, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x2a, 0x00, 0x20, + 0x18, 0x2a, 0x00, 0x20, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x47, 0x2d, 0xe9, + 0xf8, 0x46, 0x89, 0x46, 0x00, 0x21, 0x00, 0x20, 0xec, 0xf7, 0x9f, 0xfd, + 0x48, 0x46, 0x00, 0xf0, 0x8d, 0xf8, 0x42, 0x4d, 0x42, 0x4c, 0x68, 0x89, + 0x00, 0x26, 0xc0, 0xf3, 0x01, 0x10, 0x00, 0x28, 0x40, 0xf2, 0x99, 0x6a, + 0x2c, 0xd0, 0xe8, 0x6c, 0x00, 0xf0, 0x6f, 0xf8, 0x10, 0xb1, 0xf7, 0xf7, + 0x63, 0xf8, 0x08, 0xb9, 0x01, 0x26, 0x42, 0xe0, 0xe8, 0x6c, 0x00, 0xf0, + 0x4e, 0xf8, 0xa8, 0xbf, 0x64, 0x20, 0x00, 0xf0, 0x45, 0xf8, 0x00, 0xf0, + 0x5b, 0xf8, 0x9c, 0x21, 0x00, 0xf0, 0x59, 0xf8, 0x00, 0xf0, 0x49, 0xf8, + 0x00, 0xf0, 0x4c, 0xf8, 0x08, 0xb1, 0x02, 0x26, 0x2f, 0xe0, 0x31, 0x4f, + 0x39, 0x78, 0x40, 0xf6, 0x93, 0x00, 0xec, 0xf7, 0x1b, 0xfb, 0x7a, 0x78, + 0x1f, 0x21, 0x40, 0xf6, 0x94, 0x00, 0xec, 0xf7, 0x1f, 0xfb, 0x39, 0x79, + 0x40, 0xf6, 0x95, 0x00, 0xec, 0xf7, 0x10, 0xfb, 0x68, 0x89, 0xc0, 0xf3, + 0x81, 0x00, 0xd0, 0xb1, 0xa8, 0x6b, 0x00, 0xf0, 0x3e, 0xf8, 0x10, 0xb1, + 0xf7, 0xf7, 0x32, 0xf8, 0x08, 0xb9, 0x03, 0x26, 0x11, 0xe0, 0xa8, 0x6b, + 0x00, 0xf0, 0x1d, 0xf8, 0xa8, 0xbf, 0x64, 0x20, 0x00, 0xf0, 0x14, 0xf8, + 0x00, 0xf0, 0x2a, 0xf8, 0x9c, 0x21, 0x00, 0xf0, 0x28, 0xf8, 0x00, 0xf0, + 0x18, 0xf8, 0x00, 0xf0, 0x1b, 0xf8, 0x00, 0xb1, 0x04, 0x26, 0x48, 0x46, + 0x00, 0xf0, 0x43, 0xf8, 0x00, 0x20, 0xec, 0xf7, 0x9d, 0xfd, 0x30, 0x46, + 0xbd, 0xe8, 0xf2, 0x86, 0x00, 0xf0, 0x7f, 0x01, 0x50, 0x46, 0xec, 0xf7, + 0xe3, 0xba, 0x13, 0x49, 0xb0, 0xfb, 0xf1, 0xf0, 0xc0, 0xb2, 0x65, 0x28, + 0x70, 0x47, 0x20, 0x21, 0x4f, 0xf4, 0xd9, 0x70, 0xec, 0xf7, 0xd8, 0xba, + 0x4f, 0xf4, 0x7a, 0x73, 0x00, 0x22, 0x20, 0x21, 0x4f, 0xf4, 0xd9, 0x70, + 0xf2, 0xf7, 0x94, 0xbf, 0x1c, 0x21, 0x4f, 0xf4, 0xd2, 0x60, 0xec, 0xf7, + 0xcb, 0xba, 0xa4, 0xfb, 0x00, 0x23, 0x12, 0x0f, 0x42, 0xea, 0x03, 0x12, + 0x1b, 0x0f, 0x00, 0x20, 0xf7, 0xf7, 0x11, 0xb8, 0x78, 0x29, 0x00, 0x20, + 0x22, 0x18, 0x09, 0x91, 0x93, 0x06, 0x00, 0x46, 0x40, 0x42, 0x0f, 0x00, + 0x80, 0xb5, 0x00, 0x21, 0xff, 0xf7, 0xda, 0xff, 0x00, 0xf0, 0x18, 0xf8, + 0x1b, 0x21, 0x40, 0xf2, 0x91, 0x60, 0xec, 0xf7, 0xaf, 0xfa, 0xbd, 0xe8, + 0x04, 0x40, 0x7c, 0x21, 0x0a, 0xe0, 0x80, 0xb5, 0x00, 0xf0, 0x0c, 0xf8, + 0xdb, 0x21, 0x40, 0xf2, 0x91, 0x60, 0xec, 0xf7, 0xa3, 0xfa, 0xbd, 0xe8, + 0x04, 0x40, 0x7e, 0x21, 0x40, 0xf2, 0x0b, 0x20, 0xec, 0xf7, 0x9c, 0xba, + 0x07, 0x21, 0x40, 0xf2, 0x83, 0x10, 0xec, 0xf7, 0x97, 0xba, 0x00, 0x00, + 0xfe, 0xe7, 0xfe, 0xe7, 0xfe, 0xe7, 0xfe, 0xe7, 0xfe, 0xe7, 0xfe, 0xe7, + 0xfe, 0xe7, 0xfe, 0xe7, 0xfe, 0xe7, 0xfe, 0xe7, 0xfe, 0xe7, 0xfe, 0xe7, + 0xfe, 0xe7, 0xfe, 0xe7, 0xfe, 0xe7, 0xfe, 0xe7, 0xfe, 0xe7, 0xfe, 0xe7, + 0xfe, 0xe7, 0xfe, 0xe7, 0xfe, 0xe7, 0xfe, 0xe7, 0xfe, 0xe7, 0xfe, 0xe7, + 0xfe, 0xe7, 0xfe, 0xe7, 0xfe, 0xe7, 0xfe, 0xe7, 0xfe, 0xe7, 0xfe, 0xe7, + 0xfe, 0xe7, 0xfe, 0xe7, 0x2e, 0x4c, 0x2f, 0x48, 0x2f, 0x4d, 0x30, 0x49, + 0x20, 0x60, 0x20, 0x60, 0x01, 0x22, 0x00, 0x20, 0x28, 0x60, 0x08, 0x60, + 0x2d, 0x49, 0x08, 0x60, 0x0f, 0xf2, 0xd0, 0x01, 0x0f, 0xf2, 0xc8, 0x00, + 0x00, 0xf0, 0x66, 0xf8, 0x2a, 0x49, 0x28, 0x60, 0x09, 0x68, 0x88, 0x42, + 0x00, 0xd0, 0xfe, 0xe7, 0x00, 0x20, 0x20, 0x60, 0x20, 0x60, 0x27, 0x49, + 0x27, 0x48, 0x01, 0x60, 0x4f, 0xf4, 0xe0, 0x21, 0xc1, 0x61, 0x00, 0xf0, + 0x02, 0xf8, 0x00, 0xf0, 0xab, 0xb8, 0x1c, 0x48, 0x23, 0x4c, 0x4f, 0xf6, + 0xfe, 0x61, 0x01, 0x60, 0x01, 0x60, 0x22, 0x49, 0x0a, 0x78, 0x0b, 0x78, + 0x43, 0xf0, 0x08, 0x03, 0x0b, 0x70, 0x23, 0x46, 0x1d, 0x68, 0x1d, 0x60, + 0x1e, 0x68, 0xae, 0x42, 0x03, 0xd0, 0x17, 0x48, 0x00, 0x68, 0x03, 0x60, + 0xfe, 0xe7, 0x1b, 0x1d, 0x04, 0xf5, 0x80, 0x75, 0xab, 0x42, 0xf1, 0xd3, + 0x18, 0x4d, 0xab, 0x42, 0x14, 0xd2, 0x4f, 0xf0, 0xff, 0x35, 0x1d, 0x60, + 0x1d, 0x68, 0x15, 0xf1, 0x01, 0x0f, 0x03, 0xd0, 0x0d, 0x48, 0x00, 0x68, + 0x03, 0x60, 0xfe, 0xe7, 0x00, 0x25, 0x1d, 0x60, 0x1d, 0x68, 0x1d, 0xb1, + 0x09, 0x48, 0x00, 0x68, 0x03, 0x60, 0xfe, 0xe7, 0x1b, 0x1d, 0xe7, 0xe7, + 0x0a, 0x70, 0x00, 0x21, 0x01, 0x60, 0x01, 0x60, 0x70, 0x47, 0x00, 0x00, + 0x48, 0x00, 0x00, 0x50, 0x00, 0x00, 0xab, 0xab, 0xe4, 0x7f, 0x01, 0x01, + 0xf0, 0x7f, 0x01, 0x01, 0xf4, 0x7f, 0x01, 0x01, 0xe0, 0x7f, 0x01, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x08, 0xed, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x20, + 0x00, 0x0d, 0x00, 0x46, 0xff, 0xff, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, + 0xdf, 0x7f, 0x01, 0x01, 0x2d, 0xe9, 0xf0, 0x41, 0x00, 0x23, 0x00, 0x25, + 0x0f, 0xf2, 0x64, 0x08, 0x15, 0xe0, 0x17, 0xf8, 0x06, 0xe0, 0x4f, 0xea, + 0x1e, 0x14, 0x44, 0xea, 0x03, 0x14, 0x1b, 0x0f, 0x58, 0xf8, 0x23, 0x30, + 0x63, 0x40, 0x0e, 0xf0, 0x0f, 0x04, 0x44, 0xea, 0x03, 0x14, 0x1b, 0x0f, + 0x58, 0xf8, 0x23, 0x30, 0x63, 0x40, 0x7f, 0x1c, 0x67, 0x45, 0xea, 0xd3, + 0x6d, 0x1c, 0x95, 0x42, 0x08, 0xd2, 0x50, 0xf8, 0x25, 0x60, 0x51, 0xf8, + 0x25, 0x70, 0xbf, 0x1b, 0x07, 0xf1, 0x01, 0x0c, 0x00, 0x27, 0xf1, 0xe7, + 0x04, 0x20, 0x19, 0x0f, 0x58, 0xf8, 0x21, 0x10, 0x81, 0xea, 0x03, 0x11, + 0x0a, 0x0f, 0x58, 0xf8, 0x22, 0x20, 0x40, 0x1e, 0x82, 0xea, 0x01, 0x13, + 0xf3, 0xd1, 0x18, 0x46, 0xbd, 0xe8, 0xf0, 0x81, 0x00, 0x00, 0x00, 0x00, + 0xb7, 0x1d, 0xc1, 0x04, 0x6e, 0x3b, 0x82, 0x09, 0xd9, 0x26, 0x43, 0x0d, + 0xdc, 0x76, 0x04, 0x13, 0x6b, 0x6b, 0xc5, 0x17, 0xb2, 0x4d, 0x86, 0x1a, + 0x05, 0x50, 0x47, 0x1e, 0xb8, 0xed, 0x08, 0x26, 0x0f, 0xf0, 0xc9, 0x22, + 0xd6, 0xd6, 0x8a, 0x2f, 0x61, 0xcb, 0x4b, 0x2b, 0x64, 0x9b, 0x0c, 0x35, + 0xd3, 0x86, 0xcd, 0x31, 0x0a, 0xa0, 0x8e, 0x3c, 0xbd, 0xbd, 0x4f, 0x38, + 0x01, 0x20, 0xc0, 0x46, 0x00, 0x28, 0x01, 0xd0, 0x00, 0xf0, 0x08, 0xf8, + 0x00, 0x20, 0xc0, 0x46, 0xc0, 0x46, 0x00, 0xf0, 0x17, 0xf8, 0x00, 0xf0, + 0x6f, 0xf8, 0x00, 0x00, 0x10, 0xb5, 0x07, 0x49, 0x79, 0x44, 0x18, 0x31, + 0x06, 0x4c, 0x7c, 0x44, 0x16, 0x34, 0x04, 0xe0, 0x0a, 0x68, 0x08, 0x1d, + 0x51, 0x18, 0x88, 0x47, 0x01, 0x46, 0xa1, 0x42, 0xf8, 0xd1, 0x10, 0xbd, + 0x20, 0x0a, 0x00, 0x00, 0xfc, 0x0a, 0x00, 0x00, 0x00, 0xb5, 0x87, 0xb0, + 0xf1, 0xf7, 0x12, 0xf9, 0xc0, 0x46, 0xc0, 0x46, 0xc0, 0x46, 0xc0, 0x46, + 0xea, 0xf7, 0x74, 0xff, 0x03, 0x21, 0x04, 0x91, 0x00, 0x21, 0x03, 0x91, + 0x64, 0x21, 0x02, 0x91, 0x05, 0x21, 0x1e, 0x48, 0x01, 0x90, 0x00, 0x91, + 0x00, 0xf5, 0xc6, 0x72, 0x05, 0x23, 0x00, 0x21, 0x0f, 0xf2, 0x1d, 0x00, + 0xeb, 0xf7, 0xdd, 0xfd, 0x05, 0xaa, 0x0f, 0xf2, 0x70, 0x01, 0x05, 0x20, + 0xeb, 0xf7, 0x8e, 0xfe, 0xeb, 0xf7, 0x2b, 0xf8, 0x00, 0x20, 0x07, 0xb0, + 0x00, 0xbd, 0x00, 0x00, 0x80, 0xb5, 0xf0, 0xf7, 0x71, 0xff, 0x40, 0x1e, + 0x80, 0x41, 0xc0, 0x0f, 0xf1, 0xf7, 0x6d, 0xf8, 0xf7, 0xf7, 0x54, 0xf8, + 0x0e, 0x48, 0x00, 0x6c, 0x40, 0x1e, 0xb0, 0xf1, 0x80, 0x7f, 0x08, 0xd2, + 0x0c, 0x49, 0x0d, 0x4a, 0x48, 0x60, 0xf0, 0x20, 0x10, 0x70, 0x00, 0x20, + 0x88, 0x60, 0x07, 0x20, 0x08, 0x60, 0xea, 0xf7, 0xe1, 0xff, 0x68, 0x46, + 0xf2, 0xf7, 0xba, 0xfb, 0xea, 0xf7, 0xf1, 0xff, 0xf2, 0xf7, 0xec, 0xff, + 0xf2, 0xf7, 0xb2, 0xff, 0xfc, 0xe7, 0x00, 0x00, 0x48, 0x80, 0x00, 0x20, + 0x00, 0xf2, 0x00, 0x20, 0x10, 0xe0, 0x00, 0xe0, 0x23, 0xed, 0x00, 0xe0, + 0x53, 0x74, 0x61, 0x72, 0x74, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0xb8, + 0x07, 0x46, 0x38, 0x46, 0x00, 0xf0, 0x02, 0xf8, 0xfb, 0xe7, 0x00, 0x00, + 0x80, 0xb5, 0xc0, 0x46, 0xc0, 0x46, 0x02, 0x4a, 0x11, 0x00, 0x18, 0x20, + 0xab, 0xbe, 0xfb, 0xe7, 0x26, 0x00, 0x02, 0x00, 0x49, 0x6e, 0x69, 0x74, + 0x20, 0x43, 0x61, 0x6c, 0x54, 0x61, 0x73, 0x6b, 0x00, 0x00, 0x00, 0x00, + 0x52, 0x78, 0x31, 0x20, 0x43, 0x61, 0x6c, 0x54, 0x61, 0x73, 0x6b, 0x00, + 0x52, 0x78, 0x32, 0x20, 0x43, 0x61, 0x6c, 0x54, 0x61, 0x73, 0x6b, 0x00, + 0x54, 0x78, 0x31, 0x20, 0x43, 0x61, 0x6c, 0x54, 0x61, 0x73, 0x6b, 0x00, + 0x54, 0x78, 0x32, 0x20, 0x43, 0x61, 0x6c, 0x54, 0x61, 0x73, 0x6b, 0x00, + 0x54, 0x78, 0x31, 0x20, 0x4c, 0x4f, 0x4c, 0x20, 0x43, 0x61, 0x6c, 0x54, + 0x61, 0x73, 0x6b, 0x00, 0x54, 0x78, 0x32, 0x20, 0x4c, 0x4f, 0x4c, 0x20, + 0x43, 0x61, 0x6c, 0x54, 0x61, 0x73, 0x6b, 0x00, 0x4f, 0x52, 0x58, 0x31, + 0x20, 0x43, 0x61, 0x6c, 0x54, 0x61, 0x73, 0x6b, 0x00, 0x00, 0x00, 0x00, + 0x4f, 0x52, 0x58, 0x32, 0x20, 0x43, 0x61, 0x6c, 0x54, 0x61, 0x73, 0x6b, + 0x00, 0x00, 0x00, 0x00, 0x54, 0x78, 0x31, 0x20, 0x44, 0x50, 0x44, 0x20, + 0x43, 0x61, 0x6c, 0x54, 0x61, 0x73, 0x6b, 0x00, 0x54, 0x78, 0x32, 0x20, + 0x44, 0x50, 0x44, 0x20, 0x43, 0x61, 0x6c, 0x54, 0x61, 0x73, 0x6b, 0x00, + 0x54, 0x78, 0x31, 0x20, 0x43, 0x4c, 0x47, 0x43, 0x20, 0x43, 0x61, 0x6c, + 0x54, 0x61, 0x73, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x54, 0x78, 0x32, 0x20, + 0x43, 0x4c, 0x47, 0x43, 0x20, 0x43, 0x61, 0x6c, 0x54, 0x61, 0x73, 0x6b, + 0x00, 0x00, 0x00, 0x00, 0x54, 0x78, 0x31, 0x20, 0x56, 0x53, 0x57, 0x52, + 0x20, 0x43, 0x61, 0x6c, 0x54, 0x61, 0x73, 0x6b, 0x00, 0x00, 0x00, 0x00, + 0x54, 0x78, 0x32, 0x20, 0x56, 0x53, 0x57, 0x52, 0x20, 0x43, 0x61, 0x6c, + 0x54, 0x61, 0x73, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x54, 0x78, 0x31, 0x20, + 0x50, 0x41, 0x20, 0x42, 0x49, 0x41, 0x53, 0x20, 0x43, 0x61, 0x6c, 0x54, + 0x61, 0x73, 0x6b, 0x00, 0x54, 0x78, 0x32, 0x20, 0x50, 0x41, 0x20, 0x42, + 0x49, 0x41, 0x53, 0x20, 0x43, 0x61, 0x6c, 0x54, 0x61, 0x73, 0x6b, 0x00, + 0xc5, 0xfe, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x31, 0x16, 0x00, 0x01, 0x38, 0x00, 0x00, 0x00, + 0xdd, 0x59, 0x01, 0x01, 0xe5, 0x59, 0x01, 0x01, 0x38, 0x00, 0x00, 0x00, + 0xc7, 0xdc, 0x00, 0x01, 0xe5, 0xdc, 0x00, 0x01, 0xf8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xf5, 0x61, 0x00, 0x01, 0xf7, 0x61, 0x00, 0x01, 0xf8, 0x00, 0x00, 0x00, + 0x4b, 0x34, 0x00, 0x01, 0x4d, 0x34, 0x00, 0x01, 0xf8, 0x00, 0x00, 0x00, + 0x98, 0x02, 0x00, 0x20, 0x10, 0x01, 0x00, 0x00, 0xa8, 0x03, 0x00, 0x20, + 0x10, 0x01, 0x00, 0x00, 0xdc, 0x2a, 0x00, 0x20, 0x48, 0x00, 0x00, 0x00, + 0x8c, 0x2b, 0x00, 0x20, 0x18, 0x00, 0x00, 0x00, 0x30, 0x27, 0x00, 0x20, + 0x44, 0x00, 0x01, 0x00, 0xd8, 0x26, 0x00, 0x20, 0x3a, 0x00, 0x01, 0x00, + 0xf8, 0x2b, 0x00, 0x20, 0x1a, 0x00, 0x00, 0x00, 0x74, 0xf3, 0x00, 0x20, + 0x02, 0x00, 0x00, 0x00, 0x04, 0xea, 0x00, 0x20, 0xa0, 0xea, 0x00, 0x20, + 0x9c, 0x00, 0x00, 0x00, 0x3c, 0xeb, 0x00, 0x20, 0xd8, 0xeb, 0x00, 0x20, + 0x9c, 0x00, 0x00, 0x00, 0x98, 0xf1, 0x00, 0x20, 0xcc, 0xf1, 0x00, 0x20, + 0x34, 0x00, 0x00, 0x00, 0xb4, 0x2b, 0x00, 0x20, 0xd0, 0x2b, 0x00, 0x20, + 0x1c, 0x00, 0x00, 0x00, 0x74, 0x27, 0x00, 0x20, 0x08, 0x28, 0x00, 0x20, + 0x94, 0x00, 0x00, 0x00, 0xa8, 0xef, 0x00, 0x20, 0xec, 0xef, 0x00, 0x20, + 0x44, 0x00, 0x00, 0x00, 0x94, 0xed, 0x00, 0x20, 0xe8, 0xed, 0x00, 0x20, + 0x54, 0x00, 0x00, 0x00, 0x40, 0xf3, 0x00, 0x20, 0x44, 0xf3, 0x00, 0x20, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x20, 0x70, 0x47, 0x2d, 0xe9, 0xf0, 0x4f, + 0x83, 0xb0, 0x07, 0x46, 0xed, 0xf7, 0x12, 0xf9, 0xed, 0xf7, 0xe6, 0xf8, + 0x00, 0x2f, 0x04, 0x46, 0x0c, 0xbf, 0x02, 0x25, 0x03, 0x25, 0x35, 0x4e, + 0xdf, 0xf8, 0xd4, 0x80, 0xed, 0xf7, 0x13, 0xf9, 0xb8, 0x55, 0x4f, 0xf0, + 0x6c, 0x0a, 0x28, 0x46, 0xf8, 0xf7, 0x65, 0xff, 0x07, 0xf1, 0x1f, 0x00, + 0x8d, 0xf8, 0x04, 0x00, 0x4c, 0xb9, 0x06, 0xe0, 0x01, 0x21, 0xed, 0xf7, + 0x27, 0xf9, 0x14, 0xb1, 0x14, 0xf1, 0x01, 0x0f, 0x01, 0xd0, 0xed, 0xf7, + 0x81, 0xf9, 0xb8, 0x5d, 0x03, 0x21, 0xed, 0xf7, 0x1d, 0xf9, 0xb8, 0x5d, + 0x00, 0x21, 0xed, 0xf7, 0x19, 0xf9, 0x9d, 0xf8, 0x04, 0x00, 0x01, 0x21, + 0xf0, 0xf7, 0xc3, 0xff, 0xed, 0xf7, 0x48, 0xf9, 0xed, 0xf7, 0xed, 0xf8, + 0x0a, 0xfb, 0x00, 0x89, 0xeb, 0xf7, 0x56, 0xfd, 0xc9, 0xf8, 0x38, 0x00, + 0x4f, 0xf4, 0x60, 0x71, 0x06, 0xf1, 0x08, 0x00, 0x01, 0xfb, 0x07, 0x02, + 0x01, 0x21, 0x28, 0x46, 0xf8, 0xf7, 0x3c, 0xff, 0x81, 0x46, 0x00, 0x20, + 0xec, 0xf7, 0xb5, 0xfa, 0xed, 0xf7, 0xd7, 0xf8, 0x83, 0x46, 0xeb, 0xf7, + 0x41, 0xfd, 0x0a, 0xfb, 0x0b, 0x81, 0x8a, 0x6b, 0x82, 0x42, 0x23, 0xbf, + 0x4f, 0xf0, 0xff, 0x33, 0x9a, 0x1a, 0x80, 0x18, 0x80, 0x1a, 0xc8, 0x63, + 0x00, 0x21, 0x9d, 0xf8, 0x04, 0x00, 0xf0, 0xf7, 0x96, 0xff, 0xb8, 0x5d, + 0xb9, 0xf1, 0x00, 0x0f, 0xb8, 0xd0, 0x02, 0x21, 0xed, 0xf7, 0xe0, 0xf8, + 0xb8, 0x5d, 0x01, 0x21, 0xed, 0xf7, 0xdc, 0xf8, 0xed, 0xf7, 0xbe, 0xf8, + 0x0d, 0xf1, 0x05, 0x01, 0x00, 0x91, 0x00, 0x23, 0x82, 0x22, 0x20, 0x21, + 0xeb, 0xf7, 0xbe, 0xf8, 0xa9, 0xe7, 0x00, 0x00, 0x48, 0xc8, 0x00, 0x20, + 0x8c, 0x09, 0x00, 0x20, 0x00, 0x20, 0x70, 0x47, 0x2d, 0xe9, 0xf0, 0x4f, + 0x83, 0xb0, 0x07, 0x46, 0xed, 0xf7, 0x94, 0xf8, 0xed, 0xf7, 0x68, 0xf8, + 0x04, 0x46, 0x38, 0x00, 0x18, 0xbf, 0x01, 0x20, 0x8d, 0xf8, 0x04, 0x00, + 0xed, 0xf7, 0x97, 0xf8, 0x32, 0x4d, 0xdf, 0xf8, 0xcc, 0x80, 0x78, 0x55, + 0x07, 0xf1, 0x1d, 0x06, 0x9d, 0xf8, 0x04, 0x00, 0xf8, 0xf7, 0xe5, 0xfe, + 0x4f, 0xf0, 0x6c, 0x0a, 0x4c, 0xb9, 0x06, 0xe0, 0x01, 0x21, 0xed, 0xf7, + 0xa9, 0xf8, 0x14, 0xb1, 0x14, 0xf1, 0x01, 0x0f, 0x01, 0xd0, 0xed, 0xf7, + 0x03, 0xf9, 0x78, 0x5d, 0x03, 0x21, 0xed, 0xf7, 0x9f, 0xf8, 0x78, 0x5d, + 0x00, 0x21, 0xed, 0xf7, 0x9b, 0xf8, 0x01, 0x21, 0xf0, 0xb2, 0xf0, 0xf7, + 0x46, 0xff, 0xed, 0xf7, 0xcb, 0xf8, 0xed, 0xf7, 0x70, 0xf8, 0x0a, 0xfb, + 0x00, 0x89, 0xeb, 0xf7, 0xd9, 0xfc, 0xc9, 0xf8, 0x38, 0x00, 0x4f, 0xf4, + 0x60, 0x71, 0x05, 0xf1, 0x08, 0x00, 0x01, 0xfb, 0x07, 0x02, 0x9d, 0xf8, + 0x04, 0x00, 0x01, 0x21, 0xf8, 0xf7, 0xbd, 0xfe, 0x81, 0x46, 0x00, 0x20, + 0xec, 0xf7, 0x37, 0xfa, 0xed, 0xf7, 0x59, 0xf8, 0x83, 0x46, 0xeb, 0xf7, + 0xc3, 0xfc, 0x0a, 0xfb, 0x0b, 0x81, 0x8a, 0x6b, 0x82, 0x42, 0x23, 0xbf, + 0x4f, 0xf0, 0xff, 0x33, 0x9a, 0x1a, 0x80, 0x18, 0x80, 0x1a, 0xc8, 0x63, + 0x00, 0x21, 0xf0, 0xb2, 0xf0, 0xf7, 0x19, 0xff, 0x78, 0x5d, 0xb9, 0xf1, + 0x00, 0x0f, 0xb9, 0xd0, 0x02, 0x21, 0xed, 0xf7, 0x63, 0xf8, 0x78, 0x5d, + 0x01, 0x21, 0xed, 0xf7, 0x5f, 0xf8, 0xed, 0xf7, 0x41, 0xf8, 0x0d, 0xf1, + 0x05, 0x01, 0x00, 0x91, 0x00, 0x23, 0x82, 0x22, 0x20, 0x21, 0xeb, 0xf7, + 0x41, 0xf8, 0xaa, 0xe7, 0x50, 0xcf, 0x00, 0x20, 0x8c, 0x09, 0x00, 0x20, + 0x00, 0x20, 0x70, 0x47, 0x2d, 0xe9, 0xfe, 0x4f, 0x05, 0x46, 0xed, 0xf7, + 0x19, 0xf8, 0xec, 0xf7, 0xed, 0xff, 0x04, 0x46, 0x02, 0x95, 0xed, 0xf7, + 0x20, 0xf8, 0x81, 0x46, 0x02, 0x98, 0xdf, 0xf8, 0xb8, 0x80, 0x01, 0x27, + 0x00, 0xf1, 0x25, 0x06, 0x4f, 0xf0, 0x6c, 0x0a, 0x44, 0xb9, 0x05, 0xe0, + 0x00, 0xf0, 0x56, 0xf8, 0x14, 0xb1, 0x14, 0xf1, 0x01, 0x0f, 0x01, 0xd0, + 0xed, 0xf7, 0x90, 0xf8, 0x00, 0x21, 0x00, 0xf0, 0x4e, 0xf8, 0x01, 0x21, + 0xf0, 0xb2, 0xf0, 0xf7, 0xd8, 0xfe, 0xed, 0xf7, 0x5d, 0xf8, 0xed, 0xf7, + 0x02, 0xf8, 0x0a, 0xfb, 0x00, 0x85, 0xeb, 0xf7, 0x6b, 0xfc, 0xa8, 0x63, + 0xc8, 0x23, 0x02, 0x99, 0x1d, 0x48, 0x03, 0xfb, 0x01, 0x01, 0x02, 0x98, + 0x3a, 0x46, 0xf6, 0xf7, 0x3b, 0xfd, 0x05, 0x46, 0x00, 0x21, 0xf0, 0xb2, + 0xf0, 0xf7, 0xc1, 0xfe, 0x00, 0x20, 0xec, 0xf7, 0xc8, 0xf9, 0xec, 0xf7, + 0xea, 0xff, 0x83, 0x46, 0xeb, 0xf7, 0x54, 0xfc, 0x0a, 0xfb, 0x0b, 0x81, + 0x00, 0x27, 0x8a, 0x6b, 0x82, 0x42, 0x23, 0xbf, 0x4f, 0xf0, 0xff, 0x33, + 0x9a, 0x1a, 0x80, 0x18, 0x80, 0x1a, 0xc8, 0x63, 0x01, 0x2d, 0x18, 0xbf, + 0x02, 0x2d, 0x04, 0xd0, 0x03, 0x2d, 0x1c, 0xbf, 0x04, 0x2d, 0x0c, 0x2d, + 0xbc, 0xd1, 0x02, 0x21, 0x00, 0xf0, 0x13, 0xf8, 0x00, 0xf0, 0x10, 0xf8, + 0xec, 0xf7, 0xd2, 0xff, 0x01, 0xa9, 0x00, 0x91, 0x00, 0x23, 0x82, 0x22, + 0x20, 0x21, 0xea, 0xf7, 0xd3, 0xff, 0xaf, 0xe7, 0x00, 0x00, 0x00, 0x00, + 0x8c, 0x09, 0x00, 0x20, 0x74, 0xe8, 0x00, 0x20, 0x01, 0x21, 0x48, 0x46, + 0xec, 0xf7, 0xdc, 0xbf, 0x00, 0x20, 0x70, 0x47, 0x2d, 0xe9, 0xf0, 0x4f, + 0x83, 0xb0, 0x83, 0x46, 0xec, 0xf7, 0xa4, 0xff, 0xec, 0xf7, 0x78, 0xff, + 0x04, 0x46, 0xec, 0xf7, 0xac, 0xff, 0x81, 0x46, 0x0b, 0xf1, 0x29, 0x06, + 0x6c, 0x27, 0xdf, 0xf8, 0xac, 0x80, 0x4c, 0xb9, 0x06, 0xe0, 0x01, 0x21, + 0x00, 0xf0, 0x54, 0xf8, 0x14, 0xb1, 0x14, 0xf1, 0x01, 0x0f, 0x01, 0xd0, + 0xed, 0xf7, 0x1e, 0xf8, 0x00, 0x21, 0x00, 0xf0, 0x4b, 0xf8, 0x01, 0x21, + 0xf0, 0xb2, 0xf0, 0xf7, 0x66, 0xfe, 0xec, 0xf7, 0xeb, 0xff, 0xec, 0xf7, + 0x90, 0xff, 0x07, 0xfb, 0x00, 0x85, 0xeb, 0xf7, 0xf9, 0xfb, 0xa8, 0x63, + 0x1d, 0x48, 0x00, 0xeb, 0x4b, 0x11, 0x58, 0x46, 0xee, 0xf7, 0x55, 0xff, + 0x05, 0x46, 0x00, 0x20, 0xec, 0xf7, 0x5d, 0xf9, 0xec, 0xf7, 0x7f, 0xff, + 0x82, 0x46, 0xeb, 0xf7, 0xe9, 0xfb, 0x07, 0xfb, 0x0a, 0x81, 0x8a, 0x6b, + 0x82, 0x42, 0x23, 0xbf, 0x4f, 0xf0, 0xff, 0x33, 0x9a, 0x1a, 0x80, 0x18, + 0x80, 0x1a, 0xc8, 0x63, 0x00, 0x21, 0xf0, 0xb2, 0xf0, 0xf7, 0x3f, 0xfe, + 0x01, 0x2d, 0x18, 0xbf, 0x02, 0x2d, 0x04, 0xd0, 0x04, 0x2d, 0x1c, 0xbf, + 0x05, 0x2d, 0x0b, 0x2d, 0xbf, 0xd1, 0x02, 0x21, 0x00, 0xf0, 0x14, 0xf8, + 0x01, 0x21, 0x00, 0xf0, 0x11, 0xf8, 0xec, 0xf7, 0x63, 0xff, 0x01, 0xa9, + 0x00, 0x91, 0x00, 0x23, 0x82, 0x22, 0x20, 0x21, 0xea, 0xf7, 0x64, 0xff, + 0x03, 0x21, 0xaf, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x8c, 0x09, 0x00, 0x20, + 0x48, 0xf2, 0x00, 0x20, 0x48, 0x46, 0xec, 0xf7, 0x6d, 0xbf, 0x00, 0x00, + 0x80, 0xb5, 0x01, 0x29, 0x08, 0xbf, 0xfe, 0xf7, 0xbe, 0xfb, 0x00, 0x20, + 0x02, 0xbd, 0x2d, 0xe9, 0xf0, 0x4f, 0x83, 0xb0, 0x83, 0x46, 0xec, 0xf7, + 0x2f, 0xff, 0xec, 0xf7, 0x03, 0xff, 0x04, 0x46, 0xec, 0xf7, 0x37, 0xff, + 0x81, 0x46, 0x0b, 0xf1, 0x23, 0x06, 0x6c, 0x27, 0xdf, 0xf8, 0x98, 0x80, + 0x44, 0xb9, 0x05, 0xe0, 0x00, 0xf0, 0x4c, 0xf8, 0x14, 0xb1, 0x14, 0xf1, + 0x01, 0x0f, 0x01, 0xd0, 0xec, 0xf7, 0xaa, 0xff, 0x00, 0x21, 0x00, 0xf0, + 0x44, 0xf8, 0x01, 0x21, 0xf0, 0xb2, 0xf0, 0xf7, 0xf2, 0xfd, 0xec, 0xf7, + 0x77, 0xff, 0xec, 0xf7, 0x1c, 0xff, 0x07, 0xfb, 0x00, 0x85, 0xeb, 0xf7, + 0x85, 0xfb, 0xa8, 0x63, 0x4f, 0xf4, 0x22, 0x71, 0x18, 0x48, 0x01, 0xfb, + 0x0b, 0x01, 0x58, 0x46, 0xfe, 0xf7, 0xd6, 0xfa, 0x05, 0x46, 0x00, 0x20, + 0xec, 0xf7, 0xe7, 0xf8, 0xec, 0xf7, 0x09, 0xff, 0x82, 0x46, 0xeb, 0xf7, + 0x73, 0xfb, 0x07, 0xfb, 0x0a, 0x81, 0x8a, 0x6b, 0x82, 0x42, 0x23, 0xbf, + 0x4f, 0xf0, 0xff, 0x33, 0x9a, 0x1a, 0x80, 0x18, 0x80, 0x1a, 0xc8, 0x63, + 0x00, 0x21, 0xf0, 0xb2, 0xf0, 0xf7, 0xc9, 0xfd, 0x00, 0x2d, 0xc5, 0xd0, + 0x02, 0x21, 0x00, 0xf0, 0x12, 0xf8, 0x00, 0xf0, 0x0f, 0xf8, 0xec, 0xf7, + 0xf5, 0xfe, 0x01, 0xa9, 0x00, 0x91, 0x00, 0x23, 0x82, 0x22, 0x20, 0x21, + 0xea, 0xf7, 0xf6, 0xfe, 0xb8, 0xe7, 0x00, 0x00, 0x8c, 0x09, 0x00, 0x20, + 0x58, 0xd6, 0x00, 0x20, 0x01, 0x21, 0x48, 0x46, 0xec, 0xf7, 0x00, 0xbf, + 0x00, 0x20, 0x70, 0x47, 0x2d, 0xe9, 0xf0, 0x4f, 0x83, 0xb0, 0x83, 0x46, + 0xec, 0xf7, 0xc8, 0xfe, 0xec, 0xf7, 0x9c, 0xfe, 0x04, 0x46, 0xec, 0xf7, + 0xd0, 0xfe, 0x81, 0x46, 0x0b, 0xf1, 0x27, 0x06, 0x6c, 0x27, 0xdf, 0xf8, + 0xa0, 0x80, 0x44, 0xb9, 0x05, 0xe0, 0x00, 0xf0, 0x4d, 0xf8, 0x14, 0xb1, + 0x14, 0xf1, 0x01, 0x0f, 0x01, 0xd0, 0xec, 0xf7, 0x43, 0xff, 0x00, 0x21, + 0x00, 0xf0, 0x45, 0xf8, 0x01, 0x21, 0xf0, 0xb2, 0xf0, 0xf7, 0x8b, 0xfd, + 0xec, 0xf7, 0x10, 0xff, 0xec, 0xf7, 0xb5, 0xfe, 0x07, 0xfb, 0x00, 0x85, + 0xeb, 0xf7, 0x1e, 0xfb, 0xa8, 0x63, 0x58, 0x46, 0xf3, 0xf7, 0xea, 0xf8, + 0x05, 0x46, 0x00, 0x20, 0xec, 0xf7, 0x85, 0xf8, 0xec, 0xf7, 0xa7, 0xfe, + 0x82, 0x46, 0xeb, 0xf7, 0x11, 0xfb, 0x07, 0xfb, 0x0a, 0x81, 0x8a, 0x6b, + 0x82, 0x42, 0x23, 0xbf, 0x4f, 0xf0, 0xff, 0x33, 0x9a, 0x1a, 0x80, 0x18, + 0x80, 0x1a, 0xc8, 0x63, 0x00, 0x21, 0xf0, 0xb2, 0xf0, 0xf7, 0x67, 0xfd, + 0x05, 0x2d, 0x18, 0xbf, 0x01, 0x2d, 0x04, 0xd0, 0x06, 0x2d, 0x1c, 0xbf, + 0x02, 0x2d, 0x0e, 0x2d, 0xc3, 0xd1, 0x02, 0x21, 0x00, 0xf0, 0x11, 0xf8, + 0x00, 0xf0, 0x0e, 0xf8, 0xec, 0xf7, 0x8c, 0xfe, 0x01, 0xa9, 0x00, 0x91, + 0x00, 0x23, 0x82, 0x22, 0x20, 0x21, 0xea, 0xf7, 0x8d, 0xfe, 0xb6, 0xe7, + 0x00, 0x00, 0x00, 0x00, 0x8c, 0x09, 0x00, 0x20, 0x01, 0x21, 0x48, 0x46, + 0xec, 0xf7, 0x98, 0xbe, 0x00, 0x20, 0x70, 0x47, 0x2d, 0xe9, 0xf0, 0x4f, + 0x83, 0xb0, 0x83, 0x46, 0xec, 0xf7, 0x60, 0xfe, 0xec, 0xf7, 0x34, 0xfe, + 0x04, 0x46, 0xec, 0xf7, 0x68, 0xfe, 0x81, 0x46, 0x0b, 0xf1, 0x21, 0x06, + 0x6c, 0x27, 0xdf, 0xf8, 0x98, 0x80, 0x44, 0xb9, 0x05, 0xe0, 0x00, 0xf0, + 0x4b, 0xf8, 0x14, 0xb1, 0x14, 0xf1, 0x01, 0x0f, 0x01, 0xd0, 0xec, 0xf7, + 0xdb, 0xfe, 0x00, 0x21, 0x00, 0xf0, 0x43, 0xf8, 0x01, 0x21, 0xf0, 0xb2, + 0xf0, 0xf7, 0x23, 0xfd, 0xec, 0xf7, 0xa8, 0xfe, 0xec, 0xf7, 0x4d, 0xfe, + 0x07, 0xfb, 0x00, 0x85, 0xeb, 0xf7, 0xb6, 0xfa, 0xa8, 0x63, 0x38, 0x21, + 0x18, 0x48, 0x01, 0xfb, 0x0b, 0x01, 0x58, 0x46, 0xea, 0xf7, 0x2e, 0xf8, + 0x05, 0x46, 0x00, 0x20, 0xec, 0xf7, 0x19, 0xf8, 0xec, 0xf7, 0x3b, 0xfe, + 0x82, 0x46, 0xeb, 0xf7, 0xa5, 0xfa, 0x07, 0xfb, 0x0a, 0x81, 0x8a, 0x6b, + 0x82, 0x42, 0x23, 0xbf, 0x4f, 0xf0, 0xff, 0x33, 0x9a, 0x1a, 0x80, 0x18, + 0x80, 0x1a, 0xc8, 0x63, 0x00, 0x21, 0xf0, 0xb2, 0xf0, 0xf7, 0xfb, 0xfc, + 0x00, 0x2d, 0xc6, 0xd0, 0x02, 0x21, 0x00, 0xf0, 0x12, 0xf8, 0x00, 0xf0, + 0x0f, 0xf8, 0xec, 0xf7, 0x27, 0xfe, 0x01, 0xa9, 0x00, 0x91, 0x00, 0x23, + 0x82, 0x22, 0x20, 0x21, 0xea, 0xf7, 0x28, 0xfe, 0xb9, 0xe7, 0x00, 0x00, + 0x8c, 0x09, 0x00, 0x20, 0x28, 0xf1, 0x00, 0x20, 0x01, 0x21, 0x48, 0x46, + 0xec, 0xf7, 0x32, 0xbe, 0x78, 0x29, 0x00, 0x20, 0x64, 0x00, 0x00, 0x00, + 0x4c, 0x1f, 0x00, 0x20, 0x84, 0x00, 0x00, 0x00, 0xd4, 0x28, 0x00, 0x20, + 0x21, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x20, 0x5c, 0x00, 0x00, 0x00, + 0x84, 0xf3, 0x00, 0x20, 0x04, 0x00, 0x00, 0x00, 0x1c, 0x1f, 0x00, 0x20, + 0x14, 0x00, 0x00, 0x00, 0x30, 0x1f, 0x00, 0x20, 0x08, 0x00, 0x00, 0x00, + 0x88, 0x02, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x19, 0xe0, 0x50, 0xf8, + 0x04, 0x1b, 0xcb, 0x07, 0x44, 0xbf, 0xa9, 0xf1, 0x01, 0x03, 0x59, 0x18, + 0x12, 0x1f, 0x00, 0x23, 0x04, 0x2a, 0x41, 0xf8, 0x04, 0x3b, 0xf9, 0xd2, + 0x5f, 0xea, 0x82, 0x7c, 0x0b, 0x46, 0x04, 0xd5, 0x4f, 0xf0, 0x00, 0x0c, + 0xa1, 0xf8, 0x00, 0xc0, 0x9b, 0x1c, 0xd1, 0x07, 0x44, 0xbf, 0x00, 0x21, + 0x19, 0x70, 0x50, 0xf8, 0x04, 0x2b, 0x00, 0x2a, 0xe1, 0xd1, 0x70, 0x47, + 0x80, 0xb5, 0x01, 0x29, 0x04, 0xd0, 0x02, 0x29, 0x08, 0xbf, 0xf2, 0xf7, + 0x8d, 0xf8, 0x01, 0xe0, 0xf2, 0xf7, 0xce, 0xf8, 0x00, 0x20, 0x02, 0xbd, + 0x10, 0xb5, 0x07, 0x4c, 0x02, 0x21, 0x21, 0x60, 0x00, 0x21, 0x61, 0x60, + 0xf2, 0xf7, 0xd9, 0xf8, 0x08, 0x21, 0x60, 0x60, 0x21, 0x60, 0x20, 0x46, + 0xeb, 0xf7, 0xbe, 0xff, 0xfe, 0xe7, 0x00, 0x00, 0x28, 0xf3, 0x00, 0x20, + 0x38, 0xb5, 0x0c, 0x4c, 0x0c, 0x49, 0x20, 0x68, 0xc9, 0x6a, 0x88, 0x42, + 0x34, 0xbf, 0x65, 0x79, 0x25, 0x79, 0x2a, 0x46, 0x7f, 0x21, 0x4f, 0xf4, + 0x9e, 0x60, 0xeb, 0xf7, 0x91, 0xfc, 0x94, 0xf9, 0x06, 0x00, 0x41, 0x19, + 0xc9, 0xb2, 0x4f, 0xf4, 0xe2, 0x60, 0xeb, 0xf7, 0x7f, 0xfc, 0x00, 0x20, + 0x32, 0xbd, 0x00, 0x00, 0x70, 0x29, 0x00, 0x20, 0x78, 0x29, 0x00, 0x20, + 0x49, 0xff, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x00, 0x68, 0x2c, 0x00, 0x20, + 0x00, 0x08, 0x00, 0x00, 0x68, 0x36, 0x00, 0x20, 0x00, 0x02, 0x00, 0x00, + 0x68, 0x76, 0x00, 0x20, 0x00, 0x06, 0x00, 0x00, 0x68, 0x4e, 0x00, 0x20, + 0x00, 0x06, 0x00, 0x00, 0x68, 0x54, 0x00, 0x20, 0x00, 0x06, 0x00, 0x00, + 0x68, 0x5a, 0x00, 0x20, 0x00, 0x06, 0x00, 0x00, 0x68, 0x60, 0x00, 0x20, + 0x00, 0x04, 0x00, 0x00, 0x68, 0x66, 0x00, 0x20, 0x00, 0x04, 0x00, 0x00, + 0x68, 0x6a, 0x00, 0x20, 0x00, 0x04, 0x00, 0x00, 0x68, 0x6e, 0x00, 0x20, + 0x00, 0x04, 0x00, 0x00, 0x68, 0x72, 0x00, 0x20, 0x00, 0x08, 0x00, 0x00, + 0x68, 0x3e, 0x00, 0x20, 0x00, 0x08, 0x00, 0x00, 0x68, 0x46, 0x00, 0x20, + 0xf0, 0x01, 0x00, 0x00, 0x68, 0x7c, 0x00, 0x20, 0xf0, 0x01, 0x00, 0x00, + 0x58, 0x7e, 0x00, 0x20, 0x70, 0x00, 0x00, 0x00, 0xd8, 0x81, 0x00, 0x20, + 0x70, 0x00, 0x00, 0x00, 0x48, 0x82, 0x00, 0x20, 0x00, 0x02, 0x00, 0x00, + 0x68, 0x78, 0x00, 0x20, 0x90, 0x01, 0x00, 0x00, 0x48, 0x80, 0x00, 0x20, + 0x00, 0x02, 0x00, 0x00, 0x68, 0x7a, 0x00, 0x20, 0x80, 0x36, 0x00, 0x00, + 0x20, 0xbd, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0xcb, 0xb7, 0xfe, 0xff, + 0xc8, 0x00, 0x00, 0x00, 0x72, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x20, + 0x59, 0x51, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x70, 0x89, 0xfe, 0xff, + 0x90, 0xbc, 0x00, 0x20, 0x84, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, + 0x9c, 0xbc, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x70, 0x47, + 0x80, 0xb5, 0xec, 0xf7, 0x11, 0xfd, 0xec, 0xf7, 0xe5, 0xfc, 0xbd, 0xe8, + 0x01, 0x40, 0xec, 0xf7, 0x18, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x25, 0xe0, 0x02, + 0xd4, 0x01, 0xbf, 0x00, 0x63, 0x00, 0x00, 0x05, 0x4b, 0x01, 0xc4, 0x07, + 0x32, 0x01, 0xf8, 0x04, 0x99, 0x00, 0xbc, 0x03, 0x24, 0x00, 0x30, 0x00, + 0x1e, 0x00, 0x17, 0x00, 0xcd, 0x00, 0xc4, 0x01, 0x80, 0x01, 0xc7, 0x00, + 0x69, 0x20, 0x10, 0x0b, 0xb6, 0x02, 0x22, 0x07, 0x56, 0x03, 0xd5, 0x05, + 0x72, 0x02, 0xe5, 0x03, 0x17, 0x20, 0x10, 0x0b, 0x26, 0x00, 0x1d, 0x00, + 0xe3, 0x00, 0xf0, 0x02, 0xc7, 0x01, 0xc1, 0x00, 0x65, 0x20, 0x10, 0x0b, + 0xbf, 0x00, 0x89, 0x07, 0xa8, 0x00, 0x04, 0x05, 0x56, 0x00, 0xe9, 0x03, + 0x27, 0x20, 0xf0, 0x04, 0x0f, 0x1f, 0x00, 0x18, 0x00, 0xcf, 0x00, 0x60, + 0x80, 0x04, 0x00, 0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x52, 0xff, 0x01, + 0x30, 0x01, 0x00, 0x00, 0x64, 0x16, 0x50, 0x01, 0xdf, 0xa2, 0x05, 0x1e, + 0x10, 0x01, 0x03, 0x00, 0x0a, 0x0a, 0xf0, 0x31, 0x00, 0xb8, 0x0c, 0xf6, + 0x0d, 0x42, 0x15, 0x4f, 0x1b, 0xf9, 0x24, 0xb1, 0x2d, 0xb7, 0x39, 0xd5, + 0x44, 0xeb, 0x52, 0xfe, 0x5f, 0x8b, 0x6f, 0xe2, 0x7d, 0x14, 0x8e, 0xc9, + 0x9c, 0x9f, 0xac, 0xa8, 0xba, 0x0e, 0xc9, 0x5d, 0xd5, 0x45, 0xe1, 0xde, + 0xea, 0x5f, 0xf3, 0x79, 0xf9, 0xe7, 0xfd, 0xff, 0xff, 0x1f, 0xe0, 0x00, + 0x01, 0x12, 0x03, 0x71, 0x10, 0x0a, 0x0a, 0xd7, 0xa3, 0x3b, 0x00, 0x00, + 0x80, 0x40, 0xac, 0xc5, 0xa7, 0x38, 0x22, 0x20, 0x0f, 0x3f, 0x6f, 0x12, + 0x83, 0x3a, 0x17, 0xb7, 0xd1, 0x38, 0x95, 0xbf, 0xd6, 0x33, 0x0a, 0xd7, + 0x23, 0x3c, 0x04, 0x11, 0x20, 0x20, 0x5f, 0x3f, 0xed, 0xdf, 0x4b, 0x3e, + 0x33, 0x63, 0x94, 0x35, 0xdc, 0x6e, 0xc8, 0x37, 0x5e, 0x72, 0x0b, 0x37, + 0x1a, 0xd6, 0x38, 0x36, 0x46, 0xf6, 0x71, 0x35, 0x0f, 0xde, 0x8e, 0x34, + 0xc7, 0xb4, 0x6f, 0x33, 0x63, 0x2e, 0x2e, 0x31, 0x06, 0xb1, 0xe7, 0x31, + 0x88, 0x5d, 0x01, 0x33, 0xe2, 0x10, 0x70, 0x33, 0x5b, 0xb5, 0xaf, 0x33, + 0x34, 0x9f, 0xe3, 0x33, 0xb3, 0x7c, 0x07, 0x34, 0xdb, 0x33, 0x1d, 0x34, + 0x6c, 0x83, 0x31, 0x34, 0xa5, 0x95, 0x47, 0x34, 0xae, 0xb5, 0x64, 0x34, + 0xb7, 0xff, 0x8a, 0x34, 0x99, 0x7f, 0xc1, 0x34, 0x10, 0x6f, 0x2e, 0x35, + 0xa0, 0xd0, 0x56, 0x36, 0xbd, 0x37, 0x86, 0x35, 0x9e, 0x21, 0x8c, 0x21, + 0xee, 0x12, 0x06, 0x04, 0x12, 0x08, 0x04, 0x20, 0x02, 0xf9, 0x83, 0x01, + 0x3d, 0x04, 0xc1, 0xba, 0x45, 0x10, 0xf4, 0x01, 0x5c, 0xb6, 0x5c, 0x38, + 0x10, 0x21, 0x04, 0xf5, 0x85, 0x10, 0xf1, 0xff, 0x01, 0xf1, 0xff, 0x01, + 0xf1, 0xff, 0x01, 0xf1, 0x21, 0x01, 0xb0, 0x05, 0xff, 0x00, 0x07, 0x00, + 0x01, 0x00, 0x00, 0x04, 0x43, 0x90, 0x01, 0x04, 0x43, 0x70, 0x17, 0x04, + 0xc3, 0x32, 0x00, 0x04, 0x52, 0xc8, 0x04, 0x43, 0xe8, 0x03, 0x04, 0xd2, + 0x20, 0x04, 0x2d, 0xf0, 0x05, 0xf2, 0xff, 0x00, 0x01, 0xf1, 0xff, 0x01, + 0xf1, 0xff, 0x01, 0xf1, 0xff, 0x01, 0xf1, 0xff, 0x01, 0xf1, 0xff, 0x01, + 0xf1, 0xff, 0x01, 0xf1, 0xff, 0x01, 0xf1, 0xff, 0x01, 0xf1, 0xff, 0x01, + 0xf1, 0xff, 0x01, 0xf1, 0xff, 0x01, 0xf1, 0xff, 0x01, 0xf1, 0xff, 0x01, + 0xf1, 0xff, 0x01, 0xf1, 0xff, 0x01, 0xf1, 0xff, 0x01, 0xf1, 0xff, 0x01, + 0xf1, 0xff, 0x01, 0xf1, 0xff, 0x01, 0xf1, 0xff, 0x01, 0xf1, 0x20, 0x01, + 0xfc, 0x0d, 0x02, 0x01, 0x06, 0x07, 0x04, 0x05, 0x02, 0x03, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x91, 0x16, 0x2d, 0x76, 0x1c, 0x8f, + 0xa0, 0x0f, 0xc8, 0x16, 0x21, 0x04, 0x2d, 0x00, 0x17, 0x12, 0x5e, 0x05, + 0x33, 0x30, 0x75, 0x31, 0x1e, 0x20, 0xa6, 0x1c, 0x2e, 0x20, 0x17, 0x17, + 0xe0, 0x02, 0xff, 0x7f, 0x01, 0x01, 0x43, 0x12, 0x0c, 0x11, 0x80, 0x06, + 0x3f, 0x0c, 0xc8, 0x16, 0xf0, 0x00, 0x00, 0x00, 0x1d, 0x10, 0x0a, 0x3c, + 0x3c, 0xb3, 0x28, 0x00, 0x00, 0x0f, 0xe0, 0x0f, 0xe0, 0x00, 0x80, 0x0e, + 0x13, 0x00, 0xb1, 0x0e, 0x3c, 0x01, 0x2d, 0xe0, 0x2d, 0x94, 0x1b, 0x1c, + 0x01, 0x30, 0x00, 0xb1, 0xed, 0x1a, 0x30, 0x01, 0x31, 0xe0, 0x31, 0x0e, + 0x43, 0x23, 0x00, 0x84, 0x1e, 0x23, 0x56, 0x17, 0x50, 0x0e, 0x03, 0x00, + 0xb4, 0x2c, 0x10, 0x20, 0x0f, 0xaa, 0x0f, 0xaa, 0x00, 0x89, 0xb7, 0x2d, + 0x00, 0x30, 0x0a, 0x40, 0x01, 0x2e, 0x00, 0x24, 0x0a, 0xfd, 0x07, 0x50, + 0x17, 0x40, 0x03, 0x44, 0x00, 0x00, 0x50, 0x40, 0x04, 0x21, 0x0c, 0x12, + 0x58, 0x08, 0x70, 0x02, 0x58, 0x00, 0x00, 0x10, 0x18, 0xb2, 0x80, 0x18, + 0x92, 0x08, 0x0c, 0xf1, 0x46, 0x01, 0xf2, 0x02, 0x80, 0x5a, 0xf1, 0x36, + 0x14, 0x54, 0x06, 0x01, 0x02, 0x07, 0x08, 0x05, 0x06, 0x03, 0x04, 0xd2, + 0x62, 0x10, 0x1a, 0x6d, 0x5c, 0x1e, 0x2c, 0x02, 0xb9, 0x76, 0x01, 0x01, + 0x5c, 0x1e, 0xf1, 0x13, 0xdc, 0x12, 0x04, 0x25, 0x10, 0x03, 0xf0, 0x6d, + 0x01, 0x01, 0xd1, 0x34, 0x17, 0x68, 0x36, 0xe4, 0x42, 0x02, 0x14, 0x2d, + 0xf0, 0x18, 0x56, 0x01, 0xce, 0x21, 0x58, 0x25, 0xa0, 0xf3, 0x19, 0x05, + 0x71, 0x58, 0x22, 0x12, 0x25, 0x10, 0x02, 0x6e, 0x01, 0x01, 0x09, 0x34, + 0x40, 0x04, 0x68, 0x5a, 0x00, 0x20, 0x80, 0x01, 0x58, 0x21, 0x52, 0x22, + 0x02, 0x65, 0x11, 0x01, 0xf1, 0x0b, 0x58, 0xf2, 0x06, 0x01, 0x65, 0x12, + 0x13, 0x18, 0x62, 0x0c, 0x58, 0xc2, 0x60, 0x58, 0x56, 0x03, 0x02, 0x21, + 0x06, 0x21, 0x14, 0xf3, 0x19, 0xc5, 0x73, 0xb0, 0x12, 0x0e, 0x25, 0x12, + 0x18, 0x58, 0x12, 0xd3, 0x34, 0x17, 0x68, 0x66, 0x08, 0x86, 0x01, 0x08, + 0x32, 0x04, 0x0a, 0xf1, 0x0d, 0x58, 0xf1, 0x07, 0xb0, 0x2d, 0x70, 0x03, + 0x62, 0x24, 0x58, 0xc2, 0x6e, 0x58, 0x32, 0x03, 0xfe, 0x41, 0x58, 0x21, + 0x40, 0xf3, 0x19, 0x6d, 0x75, 0xb0, 0x2d, 0x30, 0x1e, 0x12, 0x30, 0x58, + 0x12, 0x71, 0x34, 0x83, 0x68, 0x6a, 0x58, 0x32, 0x90, 0x08, 0xf2, 0x10, + 0x06, 0x58, 0xf1, 0x07, 0xb0, 0x12, 0x07, 0x18, 0x62, 0x40, 0x58, 0xc2, + 0x72, 0x58, 0x32, 0x05, 0x1e, 0x85, 0xb8, 0xf3, 0x19, 0x09, 0x70, 0xb0, + 0x29, 0xa5, 0x12, 0x50, 0x58, 0x12, 0x0d, 0x34, 0xc7, 0x68, 0x4e, 0xb8, + 0xf0, 0x01, 0x10, 0x06, 0x00, 0x08, 0x58, 0xf1, 0x07, 0xb0, 0x12, 0x11, + 0x18, 0x62, 0x60, 0x58, 0xea, 0x54, 0x10, 0x72, 0x09, 0x58, 0x29, 0x72, + 0xfa, 0x1a, 0xfd, 0xc0, 0x21, 0x92, 0x12, 0x70, 0x58, 0x13, 0x01, 0x72, + 0x58, 0x8e, 0x3e, 0x18, 0x03, 0x2d, 0xf8, 0x1b, 0xf0, 0x01, 0x10, 0x04, + 0x00, 0x0a, 0x58, 0xf1, 0x07, 0xb0, 0x21, 0x92, 0x62, 0x80, 0x58, 0xc2, + 0x46, 0x58, 0xb0, 0x01, 0x03, 0x00, 0x0b, 0x58, 0xf3, 0x19, 0x9d, 0x74, + 0xb0, 0x21, 0x92, 0x12, 0x90, 0x58, 0x12, 0xa1, 0x34, 0x17, 0xcc, 0xe2, + 0x08, 0xa2, 0x00, 0xb0, 0xf2, 0x10, 0x0c, 0x58, 0xf1, 0x07, 0xb0, 0x21, + 0x92, 0x62, 0xa4, 0x58, 0xc2, 0xe4, 0x58, 0x70, 0x01, 0x03, 0x00, 0x0d, + 0x58, 0x21, 0x04, 0xf3, 0x19, 0xe5, 0x72, 0xb0, 0x21, 0x92, 0x12, 0xb8, + 0x58, 0x26, 0xe9, 0x08, 0x50, 0x02, 0x7c, 0x00, 0x20, 0x7c, 0x58, 0x32, + 0xc8, 0x08, 0xf2, 0x10, 0x0e, 0x58, 0xf1, 0x07, 0xb0, 0x21, 0x92, 0x52, + 0xcc, 0x58, 0xc3, 0x58, 0x7e, 0x58, 0x70, 0x01, 0x03, 0x00, 0x0f, 0x58, + 0x25, 0x08, 0xf3, 0x19, 0x11, 0x78, 0x58, 0x12, 0x14, 0x18, 0x12, 0xe0, + 0x58, 0x12, 0x15, 0x34, 0x50, 0x03, 0xd8, 0x81, 0x00, 0x20, 0x1c, 0x58, + 0x2d, 0x2c, 0x07, 0x3a, 0x04, 0xde, 0xf1, 0x25, 0x58, 0x12, 0x15, 0x18, + 0x52, 0xf4, 0x58, 0xc3, 0x48, 0x82, 0x58, 0x81, 0x01, 0x23, 0x80, 0xbf, + 0x04, 0x12, 0x29, 0x13, 0x27, 0x40, 0x7f, 0x1c, 0x1e, 0xff, 0x89, 0x07, + 0x1d, 0x54, 0x03, 0x42, 0x01, 0x04, 0x60, 0x02, 0x30, 0xf8, 0x30, 0xf8, + 0x2e, 0x12, 0x4b, 0x02, 0x12, 0x64, 0x02, 0x3d, 0xbc, 0x05, 0x1d, 0x69, + 0x05, 0x12, 0xde, 0x02, 0x6d, 0xc8, 0x05, 0x50, 0x05, 0x58, 0x02, 0x58, + 0x02, 0x01, 0x01, 0xa4, 0x02, 0x21, 0x1a, 0xf1, 0x01, 0x95, 0xa1, 0xa8, + 0x1c, 0x03, 0x15, 0x07, 0x00, 0x02, 0x64, 0x79, 0x06, 0x70, 0x05, 0x10, + 0x27, 0x00, 0x10, 0x0a, 0x00, 0x40, 0x1a, 0x28, 0x02, 0x05, 0x00, 0x5a, + 0x0f, 0x08, 0xbc, 0x05, 0x3f, 0x3e, 0x3f, 0x1e, 0x04, 0x00, 0xfa, 0xaf, + 0x06, 0x1a, 0x01, 0x1a, 0x11, 0x44, 0x23, 0x01, 0x2c, 0x49, 0xf0, 0x01, + 0xff, 0x02, 0x64, 0x00, 0x01, 0xf1, 0x07, 0x01, 0xf5, 0x07, 0xdc, 0x1e, + 0x09, 0xda, 0x03, 0x1e, 0x0b, 0x2e, 0x03, 0xf2, 0x04, 0x13, 0x02, 0x2d, + 0x00, 0x05, 0x1f, 0x01, 0x02, 0x0b, 0x08, 0xf4, 0x09, 0x11, 0x05, 0x0b, + 0x0e, 0x0c, 0x07, 0x08, 0x0a, 0x11, 0x09, 0x0f, 0x10, 0x73, 0x4c, 0x02, + 0x0a, 0x20, 0x0a, 0x20, 0x8a, 0x04, 0x55, 0xf0, 0x29, 0x08, 0x4a, 0x02, + 0xc0, 0x20, 0x01, 0x20, 0x7f, 0x0b, 0x13, 0x80, 0x01, 0x10, 0x00, 0xf0, + 0x84, 0x11, 0x14, 0xd3, 0x00, 0x00, 0x14, 0x40, 0x04, 0x2e, 0x33, 0x33, + 0x2b, 0x28, 0x1c, 0x06, 0xa0, 0x04, 0x2c, 0x2c, 0x37, 0x20, 0x20, 0x11, + 0x12, 0x51, 0x84, 0xf8, 0x06, 0x5a, 0xe1, 0xf5, 0x05, 0x43, 0x44, 0x02, + 0x00, 0x01, 0x06, 0x1e, 0xfc, 0x77, 0x03, 0x21, 0x04, 0x21, 0xe4, 0x2d, + 0x00, 0x06, 0x11, 0xb3, 0xf0, 0x04, 0x26, 0x07, 0x01, 0xf6, 0x01, 0x00, + 0xff, 0x84, 0xa1, 0x50, 0x5e, 0x0e, 0xf8, 0x05, 0xf0, 0x01, 0x1d, 0x01, + 0x00, 0x01, 0xd4, 0x4d, 0xe7, 0x07, 0x5e, 0x47, 0x97, 0x07, 0x5e, 0x48, + 0x47, 0x07, 0x5e, 0x53, 0xf7, 0x06, 0x30, 0x01, 0x54, 0x00, 0x2f, 0x08, + 0x1e, 0x59, 0x17, 0x0b, 0x11, 0x01, 0x63, 0x10, 0x59, 0x5b, 0x21, 0x64, + 0x10, 0x01, 0x01, 0x1e, 0xff, 0x37, 0x11, 0x82, 0x10, 0x16, 0xff, 0xf7, + 0xff, 0x13, 0x00, 0xdc, 0xff, 0x58, 0x00, 0x9d, 0xfe, 0x45, 0x42, 0x9c, + 0xfe, 0x5a, 0x00, 0xd9, 0xff, 0x17, 0x00, 0xf3, 0xff, 0x05, 0x1c, 0x21, + 0x96, 0x20, 0x02, 0xc8, 0x00, 0xb8, 0x0b, 0x50, 0x32, 0x80, 0x99, 0x30, + 0x03, 0x10, 0x00, 0x30, 0x1b, 0x0f, 0x04, 0x1c, 0x04, 0x58, 0x3e, 0x0f, + 0x00, 0xa0, 0xbb, 0x16, 0x05, 0x3c, 0x04, 0x09, 0x11, 0x02, 0x00, 0x20, + 0x02, 0x1a, 0x04, 0x3e, 0x80, 0xcc, 0x03, 0x37, 0x01, 0x00, 0x9a, 0x34, + 0x02, 0x01, 0x00, 0x2f, 0x02, 0xfa, 0x42, 0x01, 0xde, 0x1c, 0x0c, 0xff, + 0x01, 0xff, 0x02, 0x03, 0xff, 0x04, 0xff, 0x05, 0x06, 0xff, 0x07, 0x08, + 0xff, 0x63, 0x0a, 0x2e, 0xff, 0x64, 0x0a, 0x40, 0x28, 0xff, 0x10, 0x11, + 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0xff, 0x1b, 0x1c, + 0x1d, 0xff, 0x1e, 0xff, 0x1f, 0x20, 0xff, 0x21, 0x22, 0x23, 0x24, 0xff, + 0x25, 0x26, 0x27, 0x28, 0xff, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x9d, 0xbd, 0x11, 0xe2, 0x5c, 0x09, 0x0d, 0x1b, 0x2b, 0x34, + 0x37, 0x39, 0x00, 0x00, 0x28, 0x00, 0x3c, 0x20, 0x05, 0x20, 0x05, 0xa0, + 0x0f, 0x11, 0x3c, 0x3c, 0x14, 0x02, 0x01, 0x55, 0x03, 0x3d, 0x26, 0x04, + 0x13, 0x00, 0xf4, 0x06, 0xf8, 0x03, 0x46, 0xff, 0xe6, 0xdb, 0x2e, 0x12, + 0x2a, 0x96, 0x01, 0xb2, 0x12, 0x32, 0x02, 0x2e, 0x20, 0xcb, 0x0c, 0xff, + 0x0c, 0x02, 0x00, 0x9c, 0x23, 0xfd, 0x07, 0x90, 0x03, 0xf1, 0x03, 0x14, + 0xa1, 0x01, 0x03, 0x01, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xe7, 0x0c, 0x37, 0xfb, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff +}; +unsigned int firmware_Mykonos_M3_bin_len = 98304; diff --git a/datalink814_ge/src/hardware/mykonos/Mykonos_M3.h b/datalink814_ge/src/hardware/mykonos/Mykonos_M3.h new file mode 100644 index 0000000..30215b8 --- /dev/null +++ b/datalink814_ge/src/hardware/mykonos/Mykonos_M3.h @@ -0,0 +1,13 @@ +/** +SOFTWARE LICENSE AGREEMENT +20180301-AD937X-CTSLA +**/ + +// Version 5.2.2 +#ifndef SRC_MYKONOS_BIN_H_ +#define SRC_MYKONOS_BIN_H_ + +unsigned char firmware_Mykonos_M3_bin[]; +unsigned int firmware_Mykonos_M3_bin_len; + +#endif diff --git a/datalink814_ge/src/hardware/mykonos/ad9528.c b/datalink814_ge/src/hardware/mykonos/ad9528.c new file mode 100644 index 0000000..645acf6 --- /dev/null +++ b/datalink814_ge/src/hardware/mykonos/ad9528.c @@ -0,0 +1,740 @@ +/** + * \file ad9528.c + * \brief Contains source code for configuring and initializing AD9528 clock device + */ + +/** +* \page Disclaimer Legal Disclaimer +* Copyright 2015-2017 Analog Devices Inc. +* Released under the AD9371 API license, for more information see the "LICENSE.txt" file in this zip file. +* +*/ + +#include "ad9528.h" + +/** + * \brief Performs a hard reset on the AD9528 DUT + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device is structure pointer to the AD9528 data structure containing settings + * \return Returns enum ADI_ERR, ADIERR_OK=pass, !ADIERR_OK=fail + */ +ADI_ERR AD9528_resetDevice(ad9528Device_t *device) +{ + /* toggle RESETB on device with matching spi chip select index */ + CMB_hardReset(device->spiSettings->chipSelectIndex); + return ADIERR_OK; +} + +/** + * \brief Sets the AD9528 device SPI settings (3wire/4wire, MSBFirst, etc). + * + * This function will use the settings in the device->spiSettings structure + * to set SPI stream mode, address auto increment direction, MSBFirst/LSBfirst, + * and 3wire/4wire mode. The AD9528 device always uses SPI MODE 0 (CPHA=0, CPOL=0). + * This function will update your device->spiSettings to set CHPA=0 and CPOL=0 and + * longInstructionWord =1 to use a 16bit instruction word. + * + * Dependencies + * - writes device->spiSettings->CPHA = 0 + * - writes device->spiSettings->CPOL = 0 + * - writes device->spiSettings->longInstructionWord = 1 + * + * - device->spiSettings->MSBFirst + * - device->spiSettings->enSpiStreaming + * - device->spiSettings->autoIncAddrUp + * - device->spiSettings->fourWireMode + * + * \param device is structure pointer to the AD9528 data structure containing settings + * + * \return Returns enum ADI_ERR, ADIERR_OK=pass, !ADIERR_OK=fail + */ +ADI_ERR AD9528_setSpiSettings(ad9528Device_t *device) +{ + //device->spiSettings->enSpiStreaming + uint8_t spiReg = 0; + + device->spiSettings->CPHA = 0; + device->spiSettings->CPOL = 0; + device->spiSettings->longInstructionWord = 1; + + if (device->spiSettings->MSBFirst == 0) + { + spiReg |= 0x42; /* SPI bit is 1=LSB first */ + } + + if (device->spiSettings->autoIncAddrUp > 0) + { + spiReg |= 0x24; + } + + if (device->spiSettings->fourWireMode > 0) + { + spiReg |= 0x18; + } + + CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_ADI_SPI_CONFIG_A, spiReg); + + if (device->spiSettings->enSpiStreaming > 0) + { + /* Allow SPI streaming mode: SPI message ends when chip select deasserts */ + CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_ADI_SPI_CONFIG_B, 0x00); + } + else + { + /* Force single instruction mode */ + CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_ADI_SPI_CONFIG_B, 0x80); + } + + return ADIERR_OK; +} + + +/** + * \brief Helper function for ADI transceiver eval boards to init the AD9528 data structure + * + * This function inits the AD9528 device data structure with defaults that + * are known to work with the ADI AD9369 and AD9371 evaluation boards. NOTE: This function will + * modify the contents of the AD9528 device data structure. + * + * Dependencies + * - spi->chipSelectIndex + * - spi + * + * \param device Pointer to the AD9528 device data structure to initialize + * \param vcxoFrequency_Hz The VCXO frequency that is connected to the AD9528 + * \param refAFrequency_Hz The reference clock frequency being input into the AD9528 REFCLK A input + * \param outputDeviceClock_Hz Desired output clock frequency to the FPGA and transceiver device + * + * \return Returns enum ADI_ERR, 0=pass, >0 = fail +*/ +ADI_ERR AD9528_initDeviceDataStruct(ad9528Device_t *device, uint32_t vcxoFrequency_Hz, uint32_t refAFrequency_Hz, uint32_t outputDeviceClock_Hz) +{ +// uint16_t chDiv; +// uint8_t i = 0; +// +// uint32_t pll1PfdFreq_Hz = 0; +// uint8_t pll1Ndiv = 0; +// uint8_t validPll1DivSetting = 0; +// uint8_t refAdiv = 1; +// +// +// uint8_t pll2RfDiv = 3; /* Valid values 3,4,5 */ +// uint16_t pll2Ndiv = 1; /* Valid values 1-256 */ +// uint32_t pll2InputFreq_Hz = 0; +// uint64_t pll2VcoFreq_Hz = 0; +// uint16_t pll2NdivStart = 0; +// uint8_t validPll2DivSetting = 0; +// uint64_t chDivU64 = 0; +// +// static const uint64_t PLL2_MIN_VCO_FREQ_HZ = 3450000000ULL; +// static const uint64_t PLL2_MAX_VCO_FREQ_HZ = 4025000000ULL; +// /******************************************************************* +// * PLL1 Settings +// ******************************************************************* +// */ +// +// /* find valid PLL1 Ndiv and REFA div */ +// for (pll1Ndiv = 1; pll1Ndiv < 20; pll1Ndiv++) +// { +// pll1PfdFreq_Hz = vcxoFrequency_Hz / pll1Ndiv; +// +// if ((pll1PfdFreq_Hz <= 110000000) && (pll1PfdFreq_Hz >= 1000000) && +// (pll1PfdFreq_Hz <= refAFrequency_Hz) && +// (refAFrequency_Hz % pll1PfdFreq_Hz == 0) +// ) +// { +// validPll1DivSetting = 1; +// refAdiv = refAFrequency_Hz / pll1PfdFreq_Hz ; +// break; +// } +// } +// +// if (validPll1DivSetting == 0) +// { +// return ADIERR_INV_PARM; +// } +// +// device->pll1Settings->nDivider = pll1Ndiv; //This init function always runs PLL1 at 30.72MHz Pfd rate +// device->pll1Settings->refA_bufferCtrl = DIFFERENTIAL; //DISABLED = 0, SINGLE_ENDED, NEG_SINGLE_ENDED, DIFFERENTIAL +// device->pll1Settings->refA_Divider = refAdiv; +// device->pll1Settings->refA_Frequency_Hz = refAFrequency_Hz; +// device->pll1Settings->refB_bufferCtrl = DISABLED; //DISABLED = 0, SINGLE_ENDED, NEG_SINGLE_ENDED, DIFFERENTIAL +// device->pll1Settings->refB_Divider = 1; +// device->pll1Settings->refB_Frequency_Hz = 0; +// device->pll1Settings->vcxoBufferCtrl = NEG_SINGLE_ENDED; //DISABLED = 0, SINGLE_ENDED, NEG_SINGLE_ENDED, DIFFERENTIAL +// device->pll1Settings->vcxo_Frequency_Hz = vcxoFrequency_Hz; +// +// /******************************************************************* +// * PLL2 Settings +// ******************************************************************* +// */ +// +// /******************************************************************* +// * Output Distribution Settings +// * 9369CE02A uses the following clock outputs +// * OUT 1: FPGA REFCLK +// * OUT 3: FPGA SYSREF +// * OUT 12: DUT SYSREF +// * OUT 13: DUT REFCLK +// ******************************************************************* +// */ +// +// /* PLL 2 input clock can be several different things. Currently hard coded by this init funciton to use +// * PLL 1 output (VCXO Frequency) with no scaling +// */ +// pll2InputFreq_Hz = device->pll1Settings->vcxo_Frequency_Hz; +// validPll2DivSetting = 0; +// +// /* Sweep PLL2 Divider settings to find something that has a valid integer divide (3,4,5)*/ +// for (pll2RfDiv = 3; pll2RfDiv <= 5; pll2RfDiv++) +// { +// +// pll2NdivStart = (PLL2_MIN_VCO_FREQ_HZ / pll2RfDiv / pll2InputFreq_Hz); +// /* find valid PLL2 Ndiv (1-256) */ +// for (pll2Ndiv = pll2NdivStart; pll2Ndiv <= 256; pll2Ndiv++) +// { +// pll2VcoFreq_Hz = (pll2InputFreq_Hz * pll2RfDiv * pll2Ndiv); +// +// if (pll2VcoFreq_Hz < PLL2_MIN_VCO_FREQ_HZ) +// { +// /* Continue to next PLL2 N div */ +// continue; +// } +// else if (pll2VcoFreq_Hz > PLL2_MAX_VCO_FREQ_HZ) +// { +// /* Break to next PLL2 RF div */ +// break; +// } +// +// if (((pll2VcoFreq_Hz / pll2RfDiv) % outputDeviceClock_Hz) == 0) +// { +// +// device->pll2Settings->rfDivider = pll2RfDiv; +// device->pll2Settings->n2Divider = pll2Ndiv; +// device->pll2Settings->totalNdiv = pll2RfDiv * pll2Ndiv; +// chDivU64 = ((pll2VcoFreq_Hz / pll2RfDiv) / outputDeviceClock_Hz); +// +// if ((chDivU64 < 1) || (chDivU64 > 256)) +// { +// return ADIERR_INV_PARM; +// } +// else +// { +// chDiv = (uint16_t)(chDivU64); +// } +// +// validPll2DivSetting = 1; +// break; +// } +// } +// +// if (validPll2DivSetting == 1) +// { +// break; +// } +// } +// +// if (validPll2DivSetting == 0) +// { +// return ADIERR_INV_PARM; +// } +// +// device->outputSettings->outPowerDown = (uint16_t)(~0x300A); //enable outputs 13,12,3 and 1 +// +// for (i=0; i<14; i++){ +// device->outputSettings->outSource[i] = CHANNEL_DIV; //CHANNEL_DIV , PLL1_OUTPUT, SYSREF, INV_PLL1_OUTPUT +// device->outputSettings->outBufferCtrl[i] = LVDS; //LVDS, LVDS_BOOST, HSTL +// device->outputSettings->outChannelDiv[i] = chDiv; +// device->outputSettings->outFrequency_Hz[i] = outputDeviceClock_Hz; +// device->outputSettings->outAnalogDelay[i] = 0; +// device->outputSettings->outDigitalDelay[i] = 0; +// } +// +// +// device->outputSettings->outSource[3] = SYSREF; +// device->outputSettings->outSource[12] = SYSREF; +// +// +// device->sysrefSettings->sysrefDivide = 512; //SYSREF frequency = VCXO / 2 / sysrefDivde +// device->sysrefSettings->sysrefNshotMode = ONE_PULSE; //ONE_PULSE=0, TWO_PULSES=2, FOUR_PULSES=3, SIX_PULSES=4, EIGHT_PULSES=5 +// device->sysrefSettings->sysrefPatternMode = NSHOT; //NSHOT=0, CONTINUOUS=1, PRBS=2, STOP=3 +// device->sysrefSettings->sysrefPinBufferMode = DISABLED; //DISABLED = 0, SINGLE_ENDED, NEG_SINGLE_ENDED, DIFFERENTIAL +// device->sysrefSettings->sysrefPinEdgeMode = LEVEL_ACTIVE_HIGH; //LEVEL_ACTIVE_HIGH=0, LEVEL_ACTIVE_LOW=1, RISING_EDGE=2, FALLING_EDGE=3 +// device->sysrefSettings->sysrefRequestMethod = SPI; //SPI=0,PIN=1 +// device->sysrefSettings->sysrefSource = INTERNAL; //EXTERNAL=0, EXT_RESAMPLED=1, INTERNAL=2 + return ADIERR_OK; +} + +/** + * \brief Debug function to print out summary of AD9528 setup + * + * \param device AD9528 Device data structure describing setup of device. + * + * \return Returns enum ADI_ERR, 0=pass, >0 = fail +***********************************************************************************/ +ADI_ERR AD9528_reportClockRates(ad9528Device_t *device) +{ + + return ADIERR_OK; +} //debug function to help verify data structure is setup correctly. + +/** + * \brief Initializes the AD9528 by writing all SPI registers + * + * Initializes the AD9528 for use with the AD9369 transceiver. Designed to work with + * a reference clock of 122.88MHz. Reference clock is expected to be 30.72MHz. + * The output clocks from the AD9528 can run at 122.88M, 153.6M, 184.32M, 245.76M, or 307.2M. + * Typical setup: REFA frequency = 30.72, VCXO = 122.88MHz + * SYNC(SYSREF) pulses output at rate of 120kHz + * + * Dependencies + * - All parameters in device structure + * + * \param device is structure pointer to AD9528 clock device structure + * + * \return Returns enum ADI_ERR, 0=pass, >0 = fail + */ +ADI_ERR AD9528_initialize(ad9528Device_t *device) { //writes all registers to desired values, leaves clock outputs off, SYSREF output disabled. + uint8_t pll2_Adiv=0; + uint8_t pll2_Bdiv=0; + uint8_t reg108=0; + uint8_t reg109=0; + uint8_t i = 0; + uint8_t j = 0; + uint8_t reg508; + ADI_ERR retval = ADIERR_OK; + + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, ADIERR_OK, "\n// AD9528_initialize\n"); + + //CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_ADI_SPI_CONFIG_A, 0x18); //[4] and [3] =1 enable 4 wire SPI + //CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_ADI_SPI_CONFIG_B, 0x00); + retval = AD9528_setSpiSettings(device); + if (retval != ADIERR_OK) + { + return retval; + } + + /********************************************************************** + * Configure PLL1 + ********************************************************************** + */ + + CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_REF_A_DIVIDER_LSB, + device->pll1Settings->refA_Divider & 0xFF); //REF A div[7:0] + CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_REF_A_DIVIDER_MSB, + (device->pll1Settings->refA_Divider >> 8) & 0x03); //REF A div[9:8] + CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_REF_B_DIVIDER_LSB, + device->pll1Settings->refB_Divider & 0xFF); //REF B div[7:0] + CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_REF_B_DIVIDER_MSB, + (device->pll1Settings->refB_Divider >> 8) & 0x03); //REF B div[9:8] + CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_PLL1_N_DIV_LSB, + device->pll1Settings->nDivider & 0xFF); //PLL1 N div[7:0] + CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_PLL1_N_DIV_MSB, + (device->pll1Settings->nDivider >> 8) & 0x03); //PLL1 N div[9:8] + CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_PLL1_CHARGEPUMP, + 0x0A); //PLL1 Charge Pump control 1 + CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_PLL1_CP_CTRL2, + 0x03); //PLL1 Charge Pump control 2 + + switch (device->pll1Settings->refA_bufferCtrl){ + case DISABLED: + reg108 &= ~0x28; + reg109 &= ~0x01; + break; //clear all REFA enable bits + case SINGLE_ENDED: + reg108 |= 0x08; + reg109 &= ~0x01; + break; //Set REFA receiver enable, clear REFA SE negative input enable + case NEG_SINGLE_ENDED: + reg108 |= 0x08; + reg108 &= ~0x10; + reg109 |= 0x01; + break; //Disable REFA diff receiver, enable REFA receiver and use negative REFA input + case DIFFERENTIAL: + reg108 |= 0x28; + reg109 &= ~0x01; + break; + default: + reg108 |= 0x08; + reg109 &= ~0x01; + break; //default to single ended case + } + switch (device->pll1Settings->refB_bufferCtrl){ + case DISABLED: + reg108 &= ~0x50; + reg109 &= ~0x02; + break; //clear all REFB enable bits + case SINGLE_ENDED: + reg108 |= 0x10; + reg109 &= ~0x02; + break; //Set REFB receiver enable, clear REFB SE negative input enable + case NEG_SINGLE_ENDED: + reg108 |= 0x10; + reg108 &= ~0x40; + reg109 |= 0x02; + break; //Disable REFB diff receiver, enable REFB receiver and use negative REFB input + case DIFFERENTIAL: + reg108 |= 0x50; + reg109 &= ~0x02; + break; + default: + reg108 |= 0x10; + reg109 &= ~0x02; + break; //default to single ended case + } + switch (device->pll1Settings->vcxoBufferCtrl){ + case DISABLED: + reg108 &= ~0x03; + reg108 |= 0x04; + break; //power down VCXO input + case SINGLE_ENDED: + reg108 &= ~0x07; + break; //Clear VCXO receiver power down, defaults to Single ended mode + case NEG_SINGLE_ENDED: + reg108 &= ~0x07; + reg108 |= 0x02; + break; //Clear VCXO power down, enable Negative single ended mode[1] + case DIFFERENTIAL: + reg108 &= ~0x07; + reg108 |= 0x01; + break; //Clear VCXO power down, enable differential input buffer[0] + default: + reg108 &= ~0x07; + break; //default to positive single ended case + } + + + CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_INPUT_RECEIVERS1, + reg108); //Input receiver settings (single ended or differential clock inputs) + CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_INPUT_RECEIVERS2, + reg109); //Input receiver settings + + + CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_INPUT_RECEIVERS3, + 0x0A); //Reference selection mode + CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_PLL1_FASTLOCK, + 0x00); //Disable Fast lock + + /********************************************************************** + * Configure PLL2 + ********************************************************************** + */ + pll2_Bdiv = device->pll2Settings->totalNdiv / 4; + pll2_Adiv = device->pll2Settings->totalNdiv % 4; + + if (pll2_Adiv > 3) { //A div valid range (0 to 3) + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, ADIERR_INV_PARM, "\n// AD9528 PLL2 A Divider out of range (0 to 3)\n"); + return ADIERR_INV_PARM; + } + if (pll2_Bdiv < 3 || pll2_Bdiv > 63) { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, ADIERR_INV_PARM, "\n// AD9528 PLL2 B Divider out of range (3 to 63)\n"); + return ADIERR_INV_PARM; + } + CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_PLL2_CHARGEPUMP, + 0xE6); //PLL2 Charge Pump[7:0] + CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_PLL2_N_DIV, + ((pll2_Adiv & 0x3) << 6) | (pll2_Bdiv & 0x3F)); //PLL2 A and B divider + CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_PLL2_CTRL, 0x03); //PLL2 control + CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_PLL2_VCO_CTRL, 0x01); //Manual VCO CAL + + if (device->pll2Settings->rfDivider < 3 || device->pll2Settings->rfDivider > 5) { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, ADIERR_INV_PARM, "\n// AD9528 PLL2 RF Divider out of range (3,4, or 5)\n"); + return ADIERR_INV_PARM; + } + + CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_PLL2_VCO_DIV, + device->pll2Settings->rfDivider); //VCO divider + CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_PLL2_LF_CTRL1, + 0x3A); //PLL2 Loop filter [7:0] + CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_PLL2_LF_CTRL2, + 0x00); //PLL2 Loop filter [8] + CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_PLL2_RDIV, + 0x00); //R divider + CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_PLL2_REPLICA_CHDIV, + (device->pll2Settings->totalNdiv / device->pll2Settings->rfDivider) + -1 ); //Replica channel divider: Ndivider = rfDivider * R divider + CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_PLL2_REPLICA_DIV_PHASE, + 0x00); //Replica Channel Divider phase + + /********************************************************************** + * Configure Output Distribution + ********************************************************************** + */ + for (i=0; i<14; i=i+1){ + CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_CH_OUT0_CTRL1 + j, + ((device->outputSettings->outSource[i] & 0x7) << 5) | + (device->outputSettings->outAnalogDelay[i] & 0x1F)); + CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_CH_OUT0_CTRL2 + j, + ((device->outputSettings->outBufferCtrl[i] & 0x3) << 6) | + (device->outputSettings->outDigitalDelay[i] & 0x3F)); + CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_CH_OUT0_CHDIV + j, + device->outputSettings->outChannelDiv[i]-1); + j = j+3; + } + + CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_OUTPUT_SYNC, 0x00); //Sync outputs + CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_MASK_SYNC1, 0x00); //Mask SYNC[7:0] + CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_MASK_SYNC2, 0x00); //Mask SYNC[13:8] + CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_EN_OUTPUT_PATH_SEL1, + 0x00); //Bypass SYSREF resample [6:0], bit0:Enable VCXO to feed output distrubution + CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_EN_OUTPUT_PATH_SEL2, + 0x00); //Bypass SYSREF resample [13:7] + + /********************************************************************** + * Configure SYSREF operation + ********************************************************************** + */ + CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_SYSERF_DIV_LSB, + device->sysrefSettings->sysrefDivide & 0xFF); //SYSREF divider [7:0] + CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_SYSERF_DIV_MSB, + (device->sysrefSettings->sysrefDivide >> 8) & 0xFF); //SYSREF divider [7:0] + + CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_SYSREF_CTRL3, + ((device->sysrefSettings->sysrefRequestMethod & 0x1) << 7) | + ((device->sysrefSettings->sysrefPinEdgeMode & 0x3) << 5) ); + + CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_SYSREF_CTRL4, + ((device->sysrefSettings->sysrefSource & 0x03) << 6) | + ((device->sysrefSettings->sysrefPatternMode & 0x3) << 4 ) | + ((device->sysrefSettings->sysrefNshotMode & 0x7) << 1) ); + + if(device->sysrefSettings->sysrefPinBufferMode == DISABLED) + { + CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_SYSREF_CTRL5, + 0x04); //power down input buffer for external SYSREF + } + else if(device->sysrefSettings->sysrefPinBufferMode == SINGLE_ENDED) + { + CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_SYSREF_CTRL5, + 0x00); //enable positive singled ended input + } + else if(device->sysrefSettings->sysrefPinBufferMode == NEG_SINGLE_ENDED) + { + CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_SYSREF_CTRL5, + 0x02); //enable negative singled ended input + } + else if(device->sysrefSettings->sysrefPinBufferMode == DIFFERENTIAL) + { + CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_SYSREF_CTRL5, + 0x01); //enable differential input buffer + } + else + { + CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_SYSREF_CTRL5, + 0x04); //power down input buffer for external SYSREF + } + + /********************************************************************** + * Power down control + ********************************************************************** + */ + + if (device->pll1Settings->bypassPll1 > 0) + { + CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_POWERDOWN_CTRL, + 0x14);// power up PLL2 and output distribution, power down PLL1 + } + else + { + CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_POWERDOWN_CTRL, + 0x10);// power up PLL1, PLL2 and output distribution + } + + CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_CH_POWERDOWN1, + device->outputSettings->outPowerDown & 0xFF); //power down out[7:0] + CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_CH_POWERDOWN2, + ((device->outputSettings->outPowerDown >> 8) & 0x3F)); //power down out[13:8] + CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_LDO_ENABLES1, + 0xFF); //LDO enable per output channel [7:0] + CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_LDO_ENABLES2, + 0xFF); //LDO enable per output channel [15:8] + CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_STATUS0_CTRL, + 0x07); //STATUS 0 outputs REFA present + CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_STATUS1_CTRL, + 0x01); //STATUS 1 outputs PLL1 and PLL2 locked + CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_STATUS_OE, + 0x0C);// Make Status0 and Status1 outputs after reset. + + CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_IO_UPDATE, + 0x01); //IO update to make all these settings valid in the 9528 + + CMB_setTimeout_ms(1000); + do{ + CMB_SPIReadByte(device->spiSettings, AD9528_ADDR_STATUS_READBACK0, ®508); + if(CMB_hasTimeoutExpired() > 0) + { + return ADIERR_FAILED; + } + }while((reg508 & 0xA2) != 0xA2); + + return ADIERR_OK; +} + +/// Send a SPI message to request a SYSREF pulse or continuous SYSREF from the AD9528. +/*******************************************************************************//** + * Requests a SYSREF from the AD9528. It will use whatever settings for SYSREF + * that are current configured in the AD9528. This could be a single pulse, + * multiple pulses, or continuous pulses. + * Dependencies + * - device->spiSettings + * - device->sysrefSettings->sysrefPatternMode + * + * \param device is structure pointer to AD9528 clock device structure + * \param enableSYSREF If NSHOT SYSREF mode, this parameter is ignored. If PRBS/CONTINUOUS SYSREF mode, 1= enable SYSREF, 0= disable SYSREF. + * + * \return Returns enum ADI_ERR, 0=pass, >0 = fail + ***********************************************************************************/ +ADI_ERR AD9528_requestSysref(ad9528Device_t *device, uint8_t enableSYSREF){ + uint8_t _enableSYSREF=0; + + if (device->sysrefSettings->sysrefPatternMode == NSHOT || enableSYSREF > 0) + { + _enableSYSREF = 1; + } + else + { + _enableSYSREF = 0; + } + + CMB_SPIWriteField(device->spiSettings, AD9528_ADDR_SYSREF_CTRL4, _enableSYSREF, 0x01, 0x00); //Set SPI SYSREF request bit + CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_IO_UPDATE, 0x01); //IO update to make all these settings valid in the 9528 + + return ADIERR_OK; +} + +/// Allow changing the 9528 SYSREF frequency and pattern mode(CONTINUOUS, PRBS vs NSHOT mode) +/*******************************************************************************//** + * NOTE: this function will update the device structure with the parameter values passed + * into this function. The device->sysrefSettings->sysrefPatternMode, device->sysrefSettings->sysrefNshotMode, + * and device->sysrefSettings->sysrefDivide values will be updated in the device structure. + * + * Dependencies + * - device->spiSettings + * + * \param device is structure pointer to AD9528 clock device structure + * \param divideFromPll1Out Sets the SYSREF pulse frequency. SYSREF frequency = PLL1_VCXO frequency/divideFromPll1Out + * \param sysrefPatternMode Valid settings: NSHOT, CONTINUOUS, PRBS, STOP + * \param nShotPulses Valid settings: ONE_PULSE=0, TWO_PULSES=2, FOUR_PULSES=3, SIX_PULSES=4, EIGHT_PULSES=5 + * + * \return Returns enum ADI_ERR, 0=pass, >0 = fail + ***********************************************************************************/ +ADI_ERR AD9528_setupSYSREF(ad9528Device_t *device, uint16_t divideFromPll1Out, sysrefPatternMode_t sysrefPatternMode, sysrefNshotMode_t nShotPulses) +{ + uint8_t reg403=0; + + device->sysrefSettings->sysrefPatternMode = sysrefPatternMode; + device->sysrefSettings->sysrefNshotMode = nShotPulses; + device->sysrefSettings->sysrefDivide = divideFromPll1Out >> 1; //SYSREF frequency is (PLL1)VCXO frequency / 2 / device->sysrefSettings->sysrefDivide + + CMB_SPIReadByte(device->spiSettings, AD9528_ADDR_SYSREF_CTRL4, ®403); + + reg403 = reg403 & ~0x01; //clear bit 0 to stop a continuous sysref if it is on. + CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_SYSREF_CTRL4, reg403); + + reg403 = reg403 & ~0x3E; //clear bits for pattern mode and Nshot mode bitfields + reg403 = reg403 | ((sysrefPatternMode & 0x3) << 4) | ((nShotPulses & 0x7) << 1); + CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_SYSREF_CTRL4, reg403); //update internal sysref pattern mode and Nshot mode (number of pulses) + + //SYSREF request bit x403[0] is left 0. The next call to AD9528_requestSysref will start the SYSREF + CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_IO_UPDATE, 0x01); //IO update to make all these settings valid in the 9528 + + + return ADIERR_OK; +} + +/// Update the AD9528 clock outputs that are enabled. +/*******************************************************************************//** + * NOTE: this function will update the device structure with the parameter values passed + * into this function. The device->sysrefSettings->sysrefPatternMode, device->sysrefSettings->sysrefNshotMode, + * and device->sysrefSettings->sysrefDivide values will be updated in the device structure. + * + * Dependencies + * - device->spiSettings + * + * \param device is structure pointer to AD9528 clock device structure + * \param clkEnable Sets which clock outputs are enabled. Bit per clock output. bit0 = out0, etc. + * + * \return Returns enum ADI_ERR, 0=pass, >0 = fail + ***********************************************************************************/ +ADI_ERR AD9528_enableClockOutputs(ad9528Device_t *device, uint16_t clkEnable) +{ //clkEnable: bit per clock output + + device->outputSettings->outPowerDown = ~clkEnable; + CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_CH_POWERDOWN1, device->outputSettings->outPowerDown & 0xFF); //power down out[7:0] + CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_CH_POWERDOWN2, ((device->outputSettings->outPowerDown >> 8) & 0x3F)); //power down out[13:8] + + CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_IO_UPDATE, 0x01); //IO update to make all these settings valid in the 9528 + return ADIERR_OK; +} + +/// Waits for PLL1 and PLL2 to lock and the REFA and VCXO clocks to be present +/*******************************************************************************//** + * Waits until Reference A clock and VCXO clock input to be detected (present), + * and PLL1 and PLL2 to lock. Will timeout after 1 second and return ADIERR_FAILED. + * If clock are detected and PLLs locked, returns ADIERR_OK. + * + * Dependencies + * - device->spiSettings + * + * \param device is structure pointer to AD9528 clock device structure + * + * \return Returns enum ADI_ERR, 0=pass, >0 = fail + ***********************************************************************************/ +ADI_ERR AD9528_waitForPllLock(ad9528Device_t *device) +{ + uint8_t reg508; + + CMB_setTimeout_ms(1000); + do{ + CMB_SPIReadByte(device->spiSettings, AD9528_ADDR_STATUS_READBACK0, ®508); + if(CMB_hasTimeoutExpired() > 0) + { + return ADIERR_FAILED; + } + }while((reg508 & 0x27) != 0x27); + + return ADIERR_OK; +} + +/// Reads the Lock Status of the PLLs and present detect of the reference clocks +/*******************************************************************************//** + * NOTE: This is a non blocking function that reads a register to see if PLL1 + * and PLL2 are locked and Reference clock A and the VCXO input clock are + * detected (present). If the *status parameter is not NULL, the status will + * be returned. If *status is NULL, the error return value will denote if + * the PllStatus is locked or not with ADIERR_OK or ADIERR_FAILED. + * + * Dependencies + * - device->spiSettings + * + * \param device is structure pointer to AD9528 clock device structure + * + * \return Returns enum ADI_ERR, 0=pass, >0 = fail + ***********************************************************************************/ +ADI_ERR AD9528_readPllStatus(ad9528Device_t *device, uint8_t *status) +{ + uint8_t reg508; + + //bit5 is VCXO clock detected + //bit2 is REFCLK A detected + //bit1 is PLL2 lock detect + //bit0 is PLL1 lock detect + + /* read twice to refresh status bits */ + CMB_SPIReadByte(device->spiSettings, AD9528_ADDR_STATUS_READBACK0, ®508); + CMB_SPIReadByte(device->spiSettings, AD9528_ADDR_STATUS_READBACK0, ®508); + /* if status is a valid pointer, return the PLL status */ + if (status > 0) + { + *status = reg508; + } + + /* PLLs 1 and 2 are locked and VCXO and REFA detected if reg508 has bits 5,2,1 and 0 set */ + if((reg508 & 0x27) == 0x27) + return ADIERR_OK; + else + return ADIERR_FAILED; +} diff --git a/datalink814_ge/src/hardware/mykonos/ad9528.h b/datalink814_ge/src/hardware/mykonos/ad9528.h new file mode 100644 index 0000000..b7e6cfe --- /dev/null +++ b/datalink814_ge/src/hardware/mykonos/ad9528.h @@ -0,0 +1,44 @@ +/** + * \file ad9528.h + * \brief Contains function declarations and ad9528Device_t structure typedef for ad9528.c + */ + +/** +* \page Disclaimer Legal Disclaimer +* Copyright 2015-2017 Analog Devices Inc. +* Released under the AD9371 API license, for more information see the "LICENSE.txt" file in this zip file. +* +*/ + +#ifndef _AD9528_LIB_H_ +#define _AD9528_LIB_H_ + +#include +#include "../common.h" +#include "t_ad9528.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define CLEMENTE_TDD_AD9528_CLKOUT_INDEX 13 + +//Helper function to setup the 9528 device data structure specifically for the ADI transceiver evaluation cards +ADI_ERR AD9528_initDeviceDataStruct(ad9528Device_t *device, uint32_t vcxoFrequency_Hz, uint32_t refAFrequency_Hz, uint32_t outputDeviceClock_Hz); +ADI_ERR AD9528_reportClockRates(ad9528Device_t *device); //debug function to help verify data structure is setup correctly. + +//AD9528 API functions +ADI_ERR AD9528_resetDevice(ad9528Device_t *device); +ADI_ERR AD9528_setSpiSettings(ad9528Device_t *device); +ADI_ERR AD9528_initialize(ad9528Device_t *device); //writes all registers to desired values, leaves clock outputs off. +ADI_ERR AD9528_waitForPllLock(ad9528Device_t *device); +ADI_ERR AD9528_readPllStatus(ad9528Device_t *device, uint8_t *status); +ADI_ERR AD9528_enableClockOutputs(ad9528Device_t *device, uint16_t clkEnable); //clkEnable: bit per clock output +ADI_ERR AD9528_setupSYSREF(ad9528Device_t *device, uint16_t divideFromPll1Out, sysrefPatternMode_t sysrefPatternMode, sysrefNshotMode_t nShotPulses); +ADI_ERR AD9528_requestSysref(ad9528Device_t *device, uint8_t enableSYSREF); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/datalink814_ge/src/hardware/mykonos/mykonos.c b/datalink814_ge/src/hardware/mykonos/mykonos.c new file mode 100644 index 0000000..c8db0e3 --- /dev/null +++ b/datalink814_ge/src/hardware/mykonos/mykonos.c @@ -0,0 +1,18444 @@ +/** + *\file mykonos.c + * + *\brief Contains Mykonos APIs for transceiver configuration and control + * + * Mykonos API version: 1.5.2.3566 + */ + +/** + * \mainpage Overview + * + * This document is intended for use by software engineering professionals and + * includes detailed information regarding the data types and function calls + * which comprise the Mykonos ANSI C API. + * References to "Mykonos" in the API refer to the Analog Devices development name for the AD9371 family of devices. + * + */ + +/** + * \page Use Suggested Use + * The purpose of this API library is to add abstraction for the low level + * SPI control and calculations necessary to control the Mykonos family of transceiver devices + * + * Add the included source code as required to your baseband processor software build. Please reference the integration document + * as well for further instructions. + */ + +/** +* \page Disclaimer Legal Disclaimer +* Copyright 2015-2017 Analog Devices Inc. +* Released under the AD9371 API license, for more information see the "LICENSE.txt" file in this zip file. +* +*/ + +#include +#include +#include "../common.h" +#include "mykonos.h" +#include "mykonos_gpio.h" +#include "mykonos_macros.h" +#include "mykonos_user.h" + +/* Private helper functions local to this file */ +static mykonosErr_t MYKONOS_calculateScaledDeviceClk_kHz(mykonosDevice_t *device, uint32_t *scaledRefClk_kHz, uint8_t *deviceClkDiv); +static mykonosErr_t MYKONOS_calculateDigitalClocks(mykonosDevice_t *device, uint32_t *hsDigClk_kHz, uint32_t *hsDigClkDiv4or5_kHz); +static mykonosErr_t enableDpdTracking(mykonosDevice_t *device, uint8_t tx1Enable, uint8_t tx2Enable); +static mykonosErr_t enableClgcTracking(mykonosDevice_t *device, uint8_t tx1Enable, uint8_t tx2Enable); + +/** + * \brief Verifies the Tx profile members are valid (in range) in the init structure + * + * If the Tx profile IQ data rate = 0, it is assumed that the Tx profile is + * not used. If Tx IQ data rate > 0, and Tx profile members are out of range, + * + * \pre This function is private and is not called directly by the user. + * + * Dependencies + * - device->tx->txProfile + * + * \param device Structure pointer to Mykonos device data structure + * \param txProfile txProfile settings to be verified + * \param txHsDigClk_kHz Return value of the calculated HS Dig Clock required by the Tx profile + * + * \retval MYKONOS_ERR_TXPROFILE_IQRATE Profile IQ rate out of range + * \retval MYKONOS_ERR_TXPROFILE_RFBW Tx Profile RF bandwidth out of range + * \retval MYKONOS_ERR_TXPROFILE_FILTER_INTERPOLATION Filter interpolation not valid + * \retval MYKONOS_ERR_TXPROFILE_FIR_INT FIR filter not valid + * \retval MYKONOS_ERR_OK All profile members are valid + */ +static mykonosErr_t mykVerifyTxProfile(mykonosDevice_t *device, mykonosTxProfile_t *txProfile, uint32_t *txHsDigClk_kHz) +{ + mykonosErr_t retVal = MYKONOS_ERR_OK; + + *txHsDigClk_kHz = 0; + + /********************************/ + /* Check for a valid Tx profile */ + /********************************/ + + if ((txProfile->iqRate_kHz < MIN_TX_IQRATE_KHZ) || (txProfile->iqRate_kHz > MAX_TX_IQRATE_KHZ)) + { + return MYKONOS_ERR_TXPROFILE_IQRATE; + } + + if ((txProfile->rfBandwidth_Hz < MIN_TX_RFBW_HZ) || (txProfile->rfBandwidth_Hz > MAX_TX_RFBW_HZ)) + { + return MYKONOS_ERR_TXPROFILE_RFBW; + } + + if ((txProfile->thb1Interpolation != 1) && (txProfile->thb1Interpolation != 2)) + { + return MYKONOS_ERR_TXPROFILE_FILTER_INTERPOLATION; + } + + if ((txProfile->thb2Interpolation != 1) && (txProfile->thb2Interpolation != 2)) + { + return MYKONOS_ERR_TXPROFILE_FILTER_INTERPOLATION; + } + + if ((txProfile->txFirInterpolation != 1) && (txProfile->txFirInterpolation != 2) && (txProfile->txFirInterpolation != 4)) + { + return MYKONOS_ERR_TXPROFILE_FILTER_INTERPOLATION; + } + + if ((txProfile->txFir->coefs == NULL) && (txProfile->txFirInterpolation != 1)) + { + return MYKONOS_ERR_TXPROFILE_FIR_COEFS; + } + + if ((txProfile->dacDiv != DACDIV_2) && (txProfile->dacDiv != DACDIV_2p5) && (txProfile->dacDiv != DACDIV_4)) + { + return MYKONOS_ERR_TXPROFILE_DACDIV; + } + + *txHsDigClk_kHz = (txProfile->iqRate_kHz * txProfile->txFirInterpolation * txProfile->thb1Interpolation * txProfile->thb2Interpolation * (uint32_t)txProfile->dacDiv); + + device->profilesValid |= TX_PROFILE_VALID; + + return retVal; +} + +/** + * \brief Verifies the Rx profile members are valid (in range) and calculates HS Dig Clock require for the Rx Profile + * + * Private helper function to verify the Rx profile members are valid (in range) + * and calculates HS Dig Clock require for the Rx Profile + * If the Rx profile IQ data rate = 0, it is assumed that the Rx profile is + * not used. If Rx IQ data rate > 0, and Rx profile members are out of range. + * + * \pre This function is private and is not called directly by the user. + * + * Dependencies + * - device->rx->rxProfile + * + * \param device Structure pointer to Talise device data structure + * \param rxChannel receiver channel to be checked + * \param rxProfile rxProfile settings to be verified + * \param rxHsDigClk_kHz Return value of the calculated HS Dig Clock required by the Rx profile + * + * \retval MYKONOS_ERR_RXPROFILE_RXCHANNEL Rx channel is not valid. + * \retval MYKONOS_ERR_RXPROFILE_IQRATE out of range IQ rate + * \retval MYKONOS_ERR_RXPROFILE_RFBW out of range RF bandwidth + * \retval MYKONOS_ERR_RXPROFILE_FILTER_DECIMATION not valid filter decimation setting + * \retval MYKONOS_ERR_RXPROFILE_FIR_COEFS FIR filter not valid + * \retval MYKONOS_ERR_RXPROFILE_ADCDIV not valid ADC divider + * \retval MYKONOS_ERR_OK all profile members are valid + */ +static mykonosErr_t mykVerifyRxProfile(mykonosDevice_t *device, mykonosRxProfType_t rxChannel, mykonosRxProfile_t *rxProfile, uint32_t *rxHsDigClk_kHz) +{ + mykonosErr_t retVal = MYKONOS_ERR_OK; + uint32_t minBwHz = 0; + uint32_t maxBwHz = 0; + + *rxHsDigClk_kHz = 0; + + switch (rxChannel) + { + case MYK_RX_PROFILE: + minBwHz = MIN_RX_RFBW_HZ; + maxBwHz = MAX_RX_RFBW_HZ; + break; + case MYK_OBS_PROFILE: + minBwHz = MIN_ORX_RFBW_HZ; + maxBwHz = MAX_ORX_RFBW_HZ; + break; + case MYK_SNIFFER_PROFILE: + minBwHz = MIN_SNIFFER_RFBW_HZ; + maxBwHz = MAX_SNIFFER_RFBW_HZ; + break; + + default: + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RXPROFILE_RXCHANNEL, + getMykonosErrorMessage(MYKONOS_ERR_RXPROFILE_RXCHANNEL)); + return MYKONOS_ERR_RXPROFILE_RXCHANNEL; + } + + /********************************/ + /* Check for a valid Rx profile */ + /********************************/ + if ((rxProfile->iqRate_kHz < MIN_RX_IQRATE_KHZ) || (rxProfile->iqRate_kHz > MAX_RX_IQRATE_KHZ)) + { + return MYKONOS_ERR_RXPROFILE_IQRATE; + } + + /* check for Rx/Obs or Sniffer BW */ + if ((rxProfile->rfBandwidth_Hz < minBwHz) || (rxProfile->rfBandwidth_Hz > maxBwHz)) + { + return MYKONOS_ERR_RXPROFILE_RFBW; + } + + if ((rxProfile->rhb1Decimation != 1) && (rxProfile->rhb1Decimation != 2)) + { + return MYKONOS_ERR_RXPROFILE_FILTER_DECIMATION; + } + + if ((rxProfile->rxDec5Decimation != 4) && (rxProfile->rxDec5Decimation != 5)) + { + return MYKONOS_ERR_RXPROFILE_FILTER_DECIMATION; + } + + if ((rxProfile->rxFirDecimation != 1) && (rxProfile->rxFirDecimation != 2) && (rxProfile->rxFirDecimation != 4)) + { + return MYKONOS_ERR_RXPROFILE_FILTER_DECIMATION; + } + + if ((rxProfile->rxFir->coefs == NULL) && (rxProfile->rxFirDecimation != 1)) + { + return MYKONOS_ERR_RXPROFILE_FIR_COEFS; + } + + if ((rxProfile->adcDiv != 1) && (rxProfile->adcDiv != 2)) + { + return MYKONOS_ERR_RXPROFILE_ADCDIV; + } + + *rxHsDigClk_kHz = (rxProfile->iqRate_kHz * rxProfile->rxFirDecimation * rxProfile->rhb1Decimation * rxProfile->rxDec5Decimation * rxProfile->adcDiv); + + switch (rxChannel) + { + case MYK_RX_PROFILE: + device->profilesValid |= RX_PROFILE_VALID; + break; + case MYK_OBS_PROFILE: + device->profilesValid |= ORX_PROFILE_VALID; + break; + /*case MYK_SNIFFER_PROFILE:*/ + default: + device->profilesValid |= SNIFF_PROFILE_VALID; + break; + } + + return retVal; +} + +/** + * \brief Performs a hard reset on the MYKONOS DUT (Toggles RESETB pin on device) + * + * Toggles the Mykonos devices RESETB pin. Only resets the device with + * the SPI chip select indicated in the device->spiSettings structure. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device Pointer to Mykonos device data structure containing settings + * + * \return Returns enum mykonosErr_t, MYKONOS_ERR_OK=pass, !MYKONOS_ERR_OK=fail + */ +mykonosErr_t MYKONOS_resetDevice(mykonosDevice_t *device) +{ + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_resetDevice()\n"); +#endif + + /* toggle RESETB on device with matching spi chip select index */ + CMB_hardReset(device->spiSettings->chipSelectIndex); + return MYKONOS_ERR_OK; +} + +/** + * \brief Reads back the silicon revision for the Mykonos Device + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device Pointer to Mykonos device data structure containing settings + * \param revision Return value of the Mykonos silicon revision + * + * \retval MYKONOS_ERR_OK Function completed successfully + */ +mykonosErr_t MYKONOS_getDeviceRev(mykonosDevice_t *device, uint8_t *revision) +{ +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getDeviceRev()\n"); +#endif + + CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_PRODUCT_ID, revision, 0x07, 0); + + return MYKONOS_ERR_OK; +} + +/** + * \brief Reads back the Product ID for the Mykonos Device + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device Pointer to Mykonos device data structure containing settings + * \param productId Return value of the Mykonos product Id + * + * \retval MYKONOS_ERR_GETPRODUCTID__NULL_PARAM recovery action for bad parameter check + * \retval MYKONOS_ERR_OK Function completed successfully + */ +mykonosErr_t MYKONOS_getProductId(mykonosDevice_t *device, uint8_t *productId) +{ + mykonosErr_t retVal = MYKONOS_ERR_OK; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getProductId()\n"); +#endif + + if (productId == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETPRODUCTID_NULL_PARAM, + getMykonosErrorMessage(MYKONOS_ERR_GETPRODUCTID_NULL_PARAM)); + return MYKONOS_ERR_GETPRODUCTID_NULL_PARAM; + } + + CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_PRODUCT_ID, productId, 0xF8, 3); + + return retVal; +} + +/** + * \brief Get API version number + * + * This function reads back the version number of the API + * + * \param device Pointer to the Mykonos data structure + * \param siVer A pointer to the current silicon version number. + * \param majorVer A pointer to the current major version number. + * \param minorVer A pointer to the current minor version number. + * \param buildVer A pointer to the current build version number. + * + * \retval MYKONOS_ERR_GET_API_VERSION_NULL_PARAM Null parameter passed to the function. + * \retval MYKONOS_ERR_OK Function completed successfully + */ +mykonosErr_t MYKONOS_getApiVersion(mykonosDevice_t *device, uint32_t *siVer, uint32_t *majorVer, uint32_t *minorVer, uint32_t *buildVer) +{ + mykonosErr_t retVal = MYKONOS_ERR_OK; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getApiVersion()\n"); +#endif + + if ((siVer == NULL) || (majorVer == NULL) || (minorVer == NULL) || (buildVer == NULL)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GET_API_VERSION_NULL_PARAM, + getMykonosErrorMessage(MYKONOS_ERR_GET_API_VERSION_NULL_PARAM)); + return MYKONOS_ERR_GET_API_VERSION_NULL_PARAM; + } + + *siVer = (uint32_t)MYKONOS_CURRENT_SI_VERSION; + *majorVer = (uint32_t)MYKONOS_CURRENT_MAJOR_VERSION; + *minorVer = (uint32_t)MYKONOS_CURRENT_MINOR_VERSION; + *buildVer = (uint32_t)MYKONOS_CURRENT_BUILD_VERSION; + return retVal; +} + +/** + * \brief Sets the Mykonos device SPI settings (3wire/4wire, MSBFirst, etc). + * + * This function will use the settings in the device->spiSettings structure + * to set SPI stream mode, address auto increment direction, MSBFirst/LSBfirst, + * and 3wire/4wire mode. The Mykonos device always uses SPI MODE 0 (CPHA=0, CPOL=0). + * This function will update your device->spiSettings to set CHPA=0 and CPOL=0 and + * longInstructionWord =1 to use a 16bit instruction word. + * + * Dependencies + * - writes device->spiSettings->CPHA = 0 + * - writes device->spiSettings->CPOL = 0 + * - writes device->spiSettings->longInstructionWord = 1 + * + * - device->spiSettings->MSBFirst + * - device->spiSettings->enSpiStreaming + * - device->spiSettings->autoIncAddrUp + * - device->spiSettings->fourWireMode + * + * \param device Pointer to Mykonos device data structure containing settings + * + * \return Returns enum mykonosErr_t, MYKONOS_ERR_OK=pass, !MYKONOS_ERR_OK=fail + */ +mykonosErr_t MYKONOS_setSpiSettings(mykonosDevice_t *device) +{ + //device->spiSettings->enSpiStreaming + uint8_t spiReg = 0; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setSpiSettings()\n"); +#endif + + device->spiSettings->CPHA = 0; + device->spiSettings->CPOL = 0; + device->spiSettings->longInstructionWord = 1; + + if (device->spiSettings->MSBFirst == 0) + { + spiReg |= 0x42; /* SPI bit is 1=LSB first */ + } + + if (device->spiSettings->autoIncAddrUp > 0) + { + spiReg |= 0x24; + } + + if (device->spiSettings->fourWireMode > 0) + { + spiReg |= 0x18; + } + + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CONFIGURATION_CONTROL_0, spiReg); + + if (device->spiSettings->enSpiStreaming > 0) + { + /* Allow SPI streaming mode: SPI message ends when chip select deasserts */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_SPI_CONFIGURATION_CONTROL_1, 0x00); + } + else + { + /* Force single instruction mode */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_SPI_CONFIGURATION_CONTROL_1, 0x80); + } + + return MYKONOS_ERR_OK; +} + +/** + * \brief Verifies the integrity of the Mykonos device data structure. + * + * The Mykonos device data structure has many pointers to other structures. The + * main purpose of this function to verify that the necessary pointers within the + * device data structure have non zero pointers. The focus is on the Rx/Tx/ObsRx + * profiles and FIR filters where if a channel is disabled, it may be valid for + * some pointers to be NULL. This function updates device->profileValid to remember + * which profile pointers are valid. + * profileValid[3:0] = {SnifferProfileValid, ObsRxProfileValid, RxProfileValid, TxProfileValid}; + * + * Dependencies + * - device (all variables) + * + * \param device Pointer to Mykonos device data structure containing settings + * + * \return Returns enum mykonosErr_t, MYKONOS_ERR_OK=pass, !MYKONOS_ERR_OK=fail + */ +mykonosErr_t MYKONOS_verifyDeviceDataStructure(mykonosDevice_t *device) +{ + if (device == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, 0, MYKONOS_ERR_CHECKDEVSTRUCT_NULLDEVPOINTER, getMykonosErrorMessage(MYKONOS_ERR_CHECKDEVSTRUCT_NULLDEVPOINTER)); + return MYKONOS_ERR_CHECKDEVSTRUCT_NULLDEVPOINTER; + } + + device->profilesValid = 0; /* Reset */ + + if (device->spiSettings == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, 0, MYKONOS_ERR_CHECKDEVSTRUCT_SPI, getMykonosErrorMessage(MYKONOS_ERR_CHECKDEVSTRUCT_SPI)); + return MYKONOS_ERR_CHECKDEVSTRUCT_SPI; + } + + /* place this writeToLog after verifying the spiSettings structure is not NULL */ +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_verifyDeviceDataStructure()\n"); +#endif + + /************************************************************************** + * Check Rx stucture pointers + ************************************************************************** + */ + if (device->rx == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CHECKDEVSTRUCT_RX, getMykonosErrorMessage(MYKONOS_ERR_CHECKDEVSTRUCT_RX)); + return MYKONOS_ERR_CHECKDEVSTRUCT_RX; + } + else + { + if (device->rx->rxChannels == RXOFF) + {/* If no Rx channel enabled, ok to have null pointers for rx gain control, framer, and Rx profile/Rx FIR Filter */ + } + else + { + if ((device->rx->framer == NULL) || (device->rx->rxGainCtrl == NULL) || (device->rx->rxProfile == NULL)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CHECKDEVSTRUCT_RXSUB, + getMykonosErrorMessage(MYKONOS_ERR_CHECKDEVSTRUCT_RXSUB)); + return MYKONOS_ERR_CHECKDEVSTRUCT_RXSUB; + } + + if ((device->rx->rxProfile->rxFir == NULL) && (device->rx->rxProfile->rxFirDecimation != 1)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CHECKDEVSTRUCT_RXFIR, + getMykonosErrorMessage(MYKONOS_ERR_CHECKDEVSTRUCT_RXFIR)); + return MYKONOS_ERR_CHECKDEVSTRUCT_RXFIR; + } + } + } + + /************************************************************************** + * Check Tx stucture pointers + ************************************************************************** + */ + if (device->tx == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CHECKDEVSTRUCT_TX, getMykonosErrorMessage(MYKONOS_ERR_CHECKDEVSTRUCT_TX)); + return MYKONOS_ERR_CHECKDEVSTRUCT_TX; + } + else + { + if (device->tx->txChannels == TXOFF) + {/* If no Tx channel enabled, ok to have null pointers for deframer, and Tx profile/Tx FIR filter */ + } + else + { + if ((device->tx->deframer == NULL) || (device->tx->txProfile == NULL)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CHECKDEVSTRUCT_TXSUB, + getMykonosErrorMessage(MYKONOS_ERR_CHECKDEVSTRUCT_TXSUB)); + return MYKONOS_ERR_CHECKDEVSTRUCT_TXSUB; + } + + if ((device->tx->txProfile->txFir == NULL) && (device->tx->txProfile->txFirInterpolation != 1)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CHECKDEVSTRUCT_TXFIR, + getMykonosErrorMessage(MYKONOS_ERR_CHECKDEVSTRUCT_TXFIR)); + return MYKONOS_ERR_CHECKDEVSTRUCT_TXFIR; + } + } + } + + /************************************************************************** + * Check ObsRx stucture pointers + ************************************************************************** + */ + if (device->obsRx == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CHECKDEVSTRUCT_OBSRX, + getMykonosErrorMessage(MYKONOS_ERR_CHECKDEVSTRUCT_OBSRX)); + return MYKONOS_ERR_CHECKDEVSTRUCT_OBSRX; + } + else + { + if (device->obsRx->obsRxChannelsEnable == MYK_OBS_RXOFF) + {/* If no ObsRx channel enabled, ok to have null pointers for ObsRx gain control, framer, and ObsRx profile/FIR Filter */ + } + else + { + if ((device->obsRx->framer == NULL)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CHECKDEVSTRUCT_OBSRXFRAMER, + getMykonosErrorMessage(MYKONOS_ERR_CHECKDEVSTRUCT_OBSRXFRAMER)); + return MYKONOS_ERR_CHECKDEVSTRUCT_OBSRXFRAMER; + } + + if (device->obsRx->snifferProfile != NULL) + { + if (device->obsRx->snifferGainCtrl == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CHECKDEVSTRUCT_SNIFFERGAINCTRL, + getMykonosErrorMessage(MYKONOS_ERR_CHECKDEVSTRUCT_SNIFFERGAINCTRL)); + return MYKONOS_ERR_CHECKDEVSTRUCT_SNIFFERGAINCTRL; + } + + if ((device->obsRx->snifferProfile->rxFir == NULL) && (device->obsRx->snifferProfile->rxFirDecimation != 1)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CHECKDEVSTRUCT_SNIFFERFIR, + getMykonosErrorMessage(MYKONOS_ERR_CHECKDEVSTRUCT_SNIFFERFIR)); + return MYKONOS_ERR_CHECKDEVSTRUCT_SNIFFERFIR; + } + } + + if (device->obsRx->orxProfile != NULL) + { + if (device->obsRx->orxGainCtrl == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CHECKDEVSTRUCT_ORXGAINCTRL, + getMykonosErrorMessage(MYKONOS_ERR_CHECKDEVSTRUCT_ORXGAINCTRL)); + return MYKONOS_ERR_CHECKDEVSTRUCT_ORXGAINCTRL; + } + + if ((device->obsRx->orxProfile->rxFir == NULL) && (device->obsRx->orxProfile->rxFirDecimation != 1)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CHECKDEVSTRUCT_ORXFIR, + getMykonosErrorMessage(MYKONOS_ERR_CHECKDEVSTRUCT_ORXFIR)); + return MYKONOS_ERR_CHECKDEVSTRUCT_ORXFIR; + } + } + } + } + + return MYKONOS_ERR_OK; +} + +/** + * \brief Initializes the Mykonos device based on the desired device settings. + * + * This function initializes the mykonos device, setting up the CLKPLL, digital clocks, + * JESD204b settings, FIR Filters, digital filtering. It does not load the ARM + * or perform any of the ARM init calibrations. It also sets the Rx Manual gain indexes and + * TxAttenuation settings to the initial values found in the device data structure. It leaves the + * Mykonos in a state ready for multichip sync (which can bring up the JESD204 links), the + * ARM to be loaded, and the init calibartions run. + * + * Dependencies + * - device (all variables) + * + * \param device Pointer to Mykonos device data structure containing settings + * + * \return Returns enum mykonosErr_t, MYKONOS_ERR_OK=pass, !MYKONOS_ERR_OK=fail + */ +mykonosErr_t MYKONOS_initialize(mykonosDevice_t *device) +{ + uint8_t txChannelSettings = 0; + uint8_t rxChannelSettings = 0; + uint8_t orxChannelSettings = 0; + uint8_t sniffChannelSettings = 0; + uint8_t adcDacClockRateSelect = 0; + uint8_t enableDpd = 0; + uint8_t obsRxRealIf = 0; + uint8_t enRxHighRejDec5 = 0; + uint8_t rxRealIfData = 0; + uint8_t txSyncb = 0x00; + uint8_t rxSyncb = 0x00; + uint8_t orxSyncb = 0x00; + mykonosErr_t retVal = MYKONOS_ERR_OK; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_initialize()\n"); +#endif + + retVal = MYKONOS_verifyDeviceDataStructure(device); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + /* Verify Rx/Tx and ObsRx profiles are valid combinations */ + retVal = MYKONOS_verifyProfiles(device); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + /* Set 3 or 4-wire SPI mode, MSBFirst/LSBfirst in device, pushes CPOL=0, CPHA=0, longInstWord=1 into device->spiSettings */ + retVal = MYKONOS_setSpiSettings(device); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + /* Increase SPI_DO drive strength */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DIGITAL_IO_CONTROL, 0x10); + + /* Enable Reference clock - Set REFCLK pad common mode voltage */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_REF_PAD_CONFIG2, 0x07); + + /* Set Mykonos IO pin settings, GPIO direction, enable relevant LVDS pads */ + /* Enable SYSREF LVDS input pad + 100ohm internal termination */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_SYSREF_PAD_CONFIG, 0x12); //Enable SYSREF input buffer + + if ((device->tx > 0) && (device->tx->txProfile > 0)) + { + /* Check for LVDS/CMOS mode */ + if (device->tx->deframer->txSyncbMode > 0) + { + txSyncb = 0xF0; + } + else + { + txSyncb = 0x02; + } + + /* Enable SYNCOUTB output buffer */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_TX1_SYNC_PAD_CONFIG, txSyncb); + } + + /* Look at each framer and enable the RXSYNCB used for each framer. + * It is possible that they use the same RXSYNCB pin */ + if ((device->rx > 0) && (device->rx->framer > 0)) + { + /* Check for LVDS/CMOS mode */ + if (device->rx->framer->rxSyncbMode > 0) + { + rxSyncb = 0x00; + } + else + { + rxSyncb = 0x12; + } + + if (device->rx->framer->obsRxSyncbSelect == 0) + { + /* Enable SYNCINB0 LVDS/CMOS input buffer */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RX1_SYNC_CONFIG, rxSyncb); + } + else + { + /* Enable SYNCINB1 LVDS/CMOS input buffer */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RX2_SYNC_CONFIG, rxSyncb); + } + } + if ((device->obsRx > 0) && (device->obsRx->framer > 0)) + { + /* Check for LVDS/CMOS mode */ + if (device->obsRx->framer->rxSyncbMode > 0) + { + orxSyncb = 0x00; + } + else + { + orxSyncb = 0x12; + } + + if (device->obsRx->framer->obsRxSyncbSelect == 0) + { + /* Check for rxSyncb and orxSyncb when using the same RXSYNCB */ + if ((orxSyncb != rxSyncb) && (device->rx->framer->obsRxSyncbSelect == 0)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_RXSYNCB_ORXSYNCB_MODE, + getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_RXSYNCB_ORXSYNCB_MODE)); + return MYKONOS_ERR_INIT_INV_RXSYNCB_ORXSYNCB_MODE; + } + + /* Enable SYNCINB0 LVDS input buffer */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RX1_SYNC_CONFIG, orxSyncb); + } + else + { + /* Check for rxSyncb and orxSyncb when using the same ORXSYNCB */ + if ((orxSyncb != rxSyncb) && (device->rx->framer->obsRxSyncbSelect == 1)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_RXSYNCB_ORXSYNCB_MODE, + getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_RXSYNCB_ORXSYNCB_MODE)); + return MYKONOS_ERR_INIT_INV_RXSYNCB_ORXSYNCB_MODE; + } + + /* Enable SYNCINB1 LVDS input buffer */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RX2_SYNC_CONFIG, orxSyncb); + } + } + + /* Set number of device clock cycles per microsecond [round(freq/2) - 1] */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_REFERENCE_CLOCK_CYCLES, (uint8_t)((((device->clocks->deviceClock_kHz / 1000) + 1) >> 1) - 1)); + + /* Set profile specific digital clock dividers */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CONFIGURATION_CONTROL_1, 0x04); /* Negate Rx2 so phase matches Rx1 */ + + if (device->profilesValid & TX_PROFILE_VALID) + { + txChannelSettings = (((uint8_t)device->tx->txChannels & 0x3) << 6); + switch (device->tx->txProfile->thb2Interpolation) + { + case 1: + break; /* keep bit as 0 in bitfield */ + case 2: + txChannelSettings |= 0x20; + break; + default: + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_TXHB2_INTERPOLATION, + getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_TXHB2_INTERPOLATION)); + return MYKONOS_ERR_INIT_INV_TXHB2_INTERPOLATION; + } + + switch (device->tx->txProfile->thb1Interpolation) + { + case 1: + break; /* keep bit as 0 in bitfield */ + case 2: + txChannelSettings |= 0x10; + break; + default: + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_TXHB1_INTERPOLATION, + getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_TXHB1_INTERPOLATION)); + return MYKONOS_ERR_INIT_INV_TXHB1_INTERPOLATION; + } + + if (device->tx->txProfile->txFir == NULL) + { + /* If invalid pointer to FIR filter, Bypass programmable FIR, keep txChannelSettings[1:0] == 0 */ + } + else + { + switch (device->tx->txProfile->txFirInterpolation) + { + case 1: + txChannelSettings |= 0x01; + break; + case 2: + txChannelSettings |= 0x02; + break; + case 4: + txChannelSettings |= 0x03; + break; + default: + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_TXFIR_INTERPOLATION, + getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_TXFIR_INTERPOLATION)); + return MYKONOS_ERR_INIT_INV_TXFIR_INTERPOLATION; + } + } + + switch (device->tx->txProfile->dacDiv) + { + case DACDIV_2: + break; /* Keep bit [1]=0 */ + case DACDIV_2p5: + break; /* Keep bit [1]=0, div 2.5 is set when Rx DEC5 filter enabled*/ + case DACDIV_4: + adcDacClockRateSelect |= 2; + break; + default: + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_DACDIV, getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_DACDIV)); + return MYKONOS_ERR_INIT_INV_DACDIV; + } + } + + if (device->profilesValid & RX_PROFILE_VALID) + { + rxChannelSettings = (((uint8_t)device->rx->rxChannels & 0x3) << 6); + switch (device->rx->rxProfile->rxDec5Decimation) + { + case 4: + break; /* keep bit as 0 in bitfield */ + case 5: + rxChannelSettings |= 0x04; + break; + default: + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_RXDEC5_DECIMATION, + getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_RXDEC5_DECIMATION)); + return MYKONOS_ERR_INIT_INV_RXDEC5_DECIMATION; + } + + switch (device->rx->rxProfile->rhb1Decimation) + { + case 1: + break; /* keep bit as 0 in bitfield */ + case 2: + rxChannelSettings |= 0x10; + break; + default: + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_RXHB1_DECIMATION, + getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_RXHB1_DECIMATION)); + return MYKONOS_ERR_INIT_INV_RXHB1_DECIMATION; + } + + if (device->rx->rxProfile->rxFir == NULL) + { + /* If invalid pointer to FIR filter, Bypass programmable FIR, keep rxChannelSettings[1:0] == 0 */ + } + else + { + switch (device->rx->rxProfile->rxFirDecimation) + { + case 1: + rxChannelSettings |= 0x01; + break; + case 2: + rxChannelSettings |= 0x02; + break; + case 4: + rxChannelSettings |= 0x03; + break; + default: + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_RXFIR_DECIMATION, + getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_RXFIR_DECIMATION)); + return MYKONOS_ERR_INIT_INV_RXFIR_DECIMATION; + } + } + + switch (device->rx->rxProfile->adcDiv) + { + case 1: + adcDacClockRateSelect |= 0; + break; + case 2: + adcDacClockRateSelect |= 1; + break; + default: + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_ADCDIV, getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_ADCDIV)); + return MYKONOS_ERR_INIT_INV_ADCDIV; + } + + rxRealIfData = (device->rx->realIfData > 0) ? 1 : 0; + enRxHighRejDec5 = (device->rx->rxProfile->enHighRejDec5 > 0) ? 1 : 0; + } + else if (device->profilesValid & ORX_PROFILE_VALID) + { + /* if Rx profile not valid, but ORX profile valid, set RX ADC divider and dec5 to match orx profile setting */ + /* ARM clock is derived from Rx clocking, so Rx ADC div needs to be set */ + switch (device->obsRx->orxProfile->rxDec5Decimation) + { + case 4: + break; /* keep bit as 0 in bitfield */ + case 5: + rxChannelSettings |= 0x04; + break; + default: + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_RXDEC5_DECIMATION, + getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_RXDEC5_DECIMATION)); + return MYKONOS_ERR_INIT_INV_RXDEC5_DECIMATION; + } + + switch (device->obsRx->orxProfile->adcDiv) + { + case 1: + adcDacClockRateSelect |= 0; + break; + case 2: + adcDacClockRateSelect |= 1; + break; + default: + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_ADCDIV, getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_ADCDIV)); + return MYKONOS_ERR_INIT_INV_ADCDIV; + } + } + else if (device->profilesValid & SNIFF_PROFILE_VALID) + { + /* if Rx profile not valid, and ORX profile not valid, set RX ADC divider and dec5 to match sniffer profile setting */ + /* ARM clock is derived from Rx clocking, so Rx ADC div needs to be set */ + switch (device->obsRx->snifferProfile->rxDec5Decimation) + { + case 4: + break; /* keep bit as 0 in bitfield */ + case 5: + rxChannelSettings |= 0x04; + break; + default: + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_RXDEC5_DECIMATION, + getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_RXDEC5_DECIMATION)); + return MYKONOS_ERR_INIT_INV_RXDEC5_DECIMATION; + } + + switch (device->obsRx->snifferProfile->adcDiv) + { + case 1: + adcDacClockRateSelect |= 0; + break; + case 2: + adcDacClockRateSelect |= 1; + break; + default: + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_ADCDIV, getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_ADCDIV)); + return MYKONOS_ERR_INIT_INV_ADCDIV; + } + } + + /* determine ObsRx ADC Div setting */ + if (device->profilesValid & ORX_PROFILE_VALID) + { + switch (device->obsRx->orxProfile->adcDiv) + { + case 1: + break; /* Keep bit[4]=0 */ + case 2: + adcDacClockRateSelect |= 0x10; + break; /* Set bit[4]=1 */ + default: + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_OBSRX_ADCDIV, + getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_OBSRX_ADCDIV)); + return MYKONOS_ERR_INIT_INV_OBSRX_ADCDIV; + } + } + else if (device->profilesValid & SNIFF_PROFILE_VALID) + { + switch (device->obsRx->snifferProfile->adcDiv) + { + case 1: + break; /* Keep bit[4]=0 */ + case 2: + adcDacClockRateSelect |= 0x10; + break; /* Set bit[4]=1 */ + default: + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_OBSRX_ADCDIV, + getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_OBSRX_ADCDIV)); + return MYKONOS_ERR_INIT_INV_OBSRX_ADCDIV; + } + } + else if (device->profilesValid & RX_PROFILE_VALID) + { /* if OBSRX profiles are not valid, set obsRx ADC div to match Rx ADC divider */ + switch (device->rx->rxProfile->adcDiv) + { + case 1: + break; /* Keep bit[4]=0 */ + case 2: + adcDacClockRateSelect |= 0x10; + break; /* Set bit[4]=1 */ + default: + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_OBSRX_ADCDIV, + getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_OBSRX_ADCDIV)); + return MYKONOS_ERR_INIT_INV_OBSRX_ADCDIV; + } + } + + /* Determine ORx and Sniffer channel settings */ + if (device->obsRx != NULL) + { + /* verify pointers in data structure are valid (non-zero) */ + if (device->profilesValid & (ORX_PROFILE_VALID | SNIFF_PROFILE_VALID)) + { + if (device->obsRx->realIfData > 0) + { + obsRxRealIf = 1; + } + } + + /* TODO: verify that the decimation matches the given IQ rate in the data structure */ + + /* Set Sniffer profile (digital filter enables) if sniffer profile enabled (valid pointer) */ + if (device->profilesValid & SNIFF_PROFILE_VALID) + { + sniffChannelSettings = 0; + switch (device->obsRx->snifferProfile->rhb1Decimation) + { + case 1: + break; + case 2: + sniffChannelSettings |= 0x10; + break; + default: + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_SNIFFER_RHB1, + getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_SNIFFER_RHB1)); + return MYKONOS_ERR_INIT_INV_SNIFFER_RHB1; + } + + if (device->obsRx->snifferProfile->rxFir != NULL) + { + + switch (device->obsRx->snifferProfile->rxFirDecimation) + { + case 1: + sniffChannelSettings |= 0x01; + break; + case 2: + sniffChannelSettings |= 0x02; + break; + case 4: + sniffChannelSettings |= 0x03; + break; + default: + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_SNIFFER_RFIR_DEC, + getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_SNIFFER_RFIR_DEC)); + return MYKONOS_ERR_INIT_INV_SNIFFER_RFIR_DEC; + } + } + } + + /* Set ORx profile (digital filter enables) if ORx profile enabled (valid pointer) */ + if (device->profilesValid & ORX_PROFILE_VALID) + { + orxChannelSettings = 0; + switch (device->obsRx->orxProfile->rhb1Decimation) + { + case 1: + break; + case 2: + orxChannelSettings |= 0x10; + break; + default: + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_ORX_RHB1, + getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_ORX_RHB1)); + return MYKONOS_ERR_INIT_INV_ORX_RHB1; + } + + if (device->obsRx->orxProfile->rxFir != NULL) + {/* if pointer to orx rxFIR is valid */ + + switch (device->obsRx->orxProfile->rxFirDecimation) + { + case 1: + orxChannelSettings |= 0x01; + break; + case 2: + orxChannelSettings |= 0x02; + break; + case 4: + orxChannelSettings |= 0x03; + break; + default: + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_ORX_RFIR_DEC, + getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_ORX_RFIR_DEC)); + return MYKONOS_ERR_INIT_INV_ORX_RFIR_DEC; + } + } + } + } + + /************************************************************************ + * Set channel config settings for Rx/Tx/oRx and Sniffer channels + *********************************************************************** + */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CONFIGURATION_CONTROL_2, txChannelSettings); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CONFIGURATION_CONTROL_4, rxChannelSettings); + + /* Set option to use new high rejection DEC5 filters in main Rx1/Rx2 path. */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CONFIGURATION_CONTROL_5, ((uint8_t)(rxRealIfData << 2) | (enRxHighRejDec5 ? 3 : 0))); + + if (rxRealIfData > 0) + { + /* Set Rx1 NCO frequency */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RX_NCO_CH1_FTW_BYTE_3, 0x40); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RX_NCO_CH1_FTW_BYTE_2, 0x00); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RX_NCO_CH1_FTW_BYTE_1, 0x01); + + /* Set Rx2 NCO frequency */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RX_NCO_CH2_FTW_BYTE_3, 0x40); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RX_NCO_CH2_FTW_BYTE_2, 0x00); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RX_NCO_CH2_FTW_BYTE_1, 0x01); + + /* Enable NCO for Rx1 and Rx2 to shift data from zero IF to real IF */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_RX_NCO_CONTROL, 3, 0x03, 0); + } + + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_DPD_SNIFFER_CONFIGURATION_CONTROL_2, obsRxRealIf, 0x40, 6); + + /* if sniffer profile disabled, Sniffer config reg is set to default = 0x80 */ + sniffChannelSettings |= 0x80; /* use PFIR coef set B = bit[7]=1*/ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_SNIFFER_CONFIGURATION_CONTROL, sniffChannelSettings); + + /* if orx profile not valid, SPI reg for orx config is set to default = 0x00 */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DPD_CONFIGURATION_CONTROL, orxChannelSettings); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_LOOPBACK_CONFIGURATION_CONTROL, orxChannelSettings); + + /* Set ADC divider, DAC divider, and ObsRx/sniffer dividers */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_CLOCK_CONTROL_1, adcDacClockRateSelect, 0x13, 0); + + /* Disable ORx digital DC offset - bad default SPI setting for ObsRx DC offset */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DIGITAL_DC_OFFSET_CH3_DPD_M_SHIFT, 0x60); + + /* Necessary write for ARM init cals to work */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_SNIFF_RXLOGEN_BYTE1, 0x0E); + + /* Increase Sniffer LNA gain */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_SNRX_LNA_BIAS_C, 0x0F); + + /* Set the CLKPLL with the frequency from the device data structure */ + retVal = MYKONOS_initDigitalClocks(device); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + /* Wait for CLKPLL CP Cal done and CLKPLL Lock or throw error message */ + CMB_wait_ms(500); + retVal = MYKONOS_waitForEvent(device, CLKPLLCP, 1000000); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + retVal = MYKONOS_waitForEvent(device, CLKPLL_LOCK, 1000000); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + /* Enable digital clocks - this is gated by the CLKPLL being locked */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLOCK_CONTROL_0, 0x14); + + /* Set the Tx PFIR synchronization clock */ + retVal = MYKONOS_setTxPfirSyncClk(device); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + /* Set the Rx PFIR synchronization clock */ + retVal = MYKONOS_setRxPfirSyncClk(device); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + if (device->profilesValid & TX_PROFILE_VALID) + { + /* Set pre TxPFIR Half band filter interpolation */ + if (device->tx->txProfile->txInputHbInterpolation == 1) + { + /* disable TX input half band ([3:2]=00) - but allow DPD to still be enabled for tx profiles with wide BW [1] */ + enableDpd = (device->tx->txProfile->enableDpdDataPath > 0) ? 1 : 0; + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_TX_FILTER_CONFIGURATION, enableDpd, 0x0E, 1); + } + else if (device->tx->txProfile->txInputHbInterpolation == 2) + { + if (device->tx->txProfile->iqRate_kHz > 160000) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_TXINPUTHB0_INV_RATE, + getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_TXINPUTHB0_INV_RATE)); + return MYKONOS_ERR_INIT_INV_TXINPUTHB0_INV_RATE; + } + + /* enable TX input half band[2]=1, and Enable DPD[1]=1*/ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_TX_FILTER_CONFIGURATION, 3, 0x0E, 1); + } + else if (device->tx->txProfile->txInputHbInterpolation == 4) + { + if (device->tx->txProfile->iqRate_kHz > 80000) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_TXINPUTHB_INV_RATE, + getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_TXINPUTHB_INV_RATE)); + return MYKONOS_ERR_INIT_INV_TXINPUTHB_INV_RATE; + } + + /* enable TX input HB0[3]=1 and Tx input HB[2]=1, and Enable DPD[1]=1*/ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_TX_FILTER_CONFIGURATION, 7, 0x0E, 1); + } + else + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_TXINPUTHB_PARM, + getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_TXINPUTHB_PARM)); + return MYKONOS_ERR_INIT_INV_TXINPUTHB_PARM; + } + + /* Enable SPI Tx Atten mode */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_TX_TPC_CONFIG, 0x01, 0x03, 0); + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_TX_TPC_CONFIG, 0x01, 0x0C, 2); + + /* Set Tx1 Atten step size */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_TX_INCR_DECR_WORD, device->tx->txAttenStepSize, 0x60, 5); + + /* Set Tx2 Atten step size */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_TX_TPC_CONFIG, device->tx->txAttenStepSize, 0x60, 5); + } + else + { + /* Power down DACs */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_TX_PD_OVERIDE_7_0, 3, 0x0C, 2); + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_TX_PD_OVERRIDE_CONTROL_7_0, 3, 0x0C, 2); + } + + /* Set RxFE LO Common mode */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RXFE1_LOCM, 0xF0); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RXFE2_LOCM, 0xF0); + + /* Set Rxloopback LO Common mode */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RXLOOPBACK1_CNTRL_1, 0xFF); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RXLOOPBACK2_CNTRL_1, 0xFF); + + /* Setup MGC or AGC Rx gain control */ + if ((retVal = MYKONOS_setupRxAgc(device)) != MYKONOS_ERR_OK) + { + return retVal; + } + + /* Default Rx to use manual gain control until AGC enabled by user */ + if ((retVal = MYKONOS_setRxGainControlMode(device, MGC)) != MYKONOS_ERR_OK) + { + return retVal; + } + + + if ((retVal = MYKONOS_setupObsRxAgc(device)) != MYKONOS_ERR_OK) + { + return retVal; + } + + /* Default ObsRx to use manual gain control until AGC enabled by user */ + if ((retVal = MYKONOS_setObsRxGainControlMode(device, MGC)) != MYKONOS_ERR_OK) + { + return retVal; + } + + /* Disable GPIO select bits by setting to b11 */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_CONFIGURATION_CONTROL_1, 3, 0x30, 4); + + /* Extra settings for ARM calibrations */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DIGITAL_DC_OFFSET_SHIFT, 0x11); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RX_LOOPBACK1_CNTRL_4, 0x04); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RX_LOOPBACK2_CNTRL_4, 0x04); + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_ORX_SNRX_CFG_2, 0x20, 0x20, 0); + + /* Extra settings for ADC initialisation */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RX_ADC_FLASH_DELAY, 0x28); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RX_ADC_FLASH_CTRL, 0x0E); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ORX_ADC_FLASH_DELAY, 0x28); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ORX_ADC_FLASH_CTRL, 0x0E); + + /* Move to Alert ENSM state */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ENSM_CONFIG_7_0, 0x05); + + return MYKONOS_ERR_OK; +} + +/** + * \brief Verifies the init structure profiles are valid combinations + * + * This function checks that the Rx/Tx/ORx/Sniffer profiles have valid clock rates in + * order to operate together. Rx/Tx and ORx/Sniffer share a common high speed digital + * clock. If an invalid combination of profiles is detected, an error will be + * returned. If a profile in the init structure is unused, the user should zero + * out all members of that particular profile structure. If a Rx/Tx/ORx/Sniffer profile + * has an IQ rate = 0, it is assumed that the profile is disabled. + * + * \pre This function is private and is not called directly by the user. + * + * This function uses mykVerifyTxProfile() and mykVerifyRxProfile() as helper functions. + * + * Dependencies + * - device->spiSettings + * - device->spiSettings->chipSelectIndex + * + * \param device Structure pointer to Mykonos device data structure + * + * \retval MYKONOS_ERR_PROFILES_HSDIGCLK profiles loaded are not valid + * \retval MYKONOS_ERR_OK Function completed successfully + */ +mykonosErr_t MYKONOS_verifyProfiles(mykonosDevice_t *device) +{ + mykonosErr_t retVal = MYKONOS_ERR_OK; + + uint32_t rxHsDigClk_kHz = 0; + uint32_t orxHsDigClk_kHz = 0; + uint32_t snifferHsDigClk_kHz = 0; + uint32_t txHsDigClk_kHz = 0; + + mykonosRxProfile_t *rxProfile = NULL; + mykonosTxProfile_t *txProfile = NULL; + mykonosRxProfile_t *orxProfile = NULL; + mykonosRxProfile_t *snifferProfile = NULL; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_verifyProfiles()\n"); +#endif + + device->profilesValid = 0; + + /* Check all loaded profiles */ + if (device->tx->txChannels != TXOFF) + { + txProfile = device->tx->txProfile; + retVal = mykVerifyTxProfile(device, txProfile, &txHsDigClk_kHz); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + } + + if (device->rx->rxChannels != RXOFF) + { + rxProfile = device->rx->rxProfile; + retVal = mykVerifyRxProfile(device, MYK_RX_PROFILE, rxProfile, &rxHsDigClk_kHz); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + } + + if (device->obsRx->obsRxChannelsEnable != MYK_OBS_RXOFF) + { + if ((uint32_t)device->obsRx->obsRxChannelsEnable & (uint32_t)MYK_ORX1_ORX2) + { + orxProfile = device->obsRx->orxProfile; + retVal = mykVerifyRxProfile(device, MYK_OBS_PROFILE, orxProfile, &orxHsDigClk_kHz); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + } + + if ((uint32_t)device->obsRx->obsRxChannelsEnable & (uint32_t)MYK_SNRXA_B_C) + { + snifferProfile = device->obsRx->snifferProfile; + retVal = mykVerifyRxProfile(device, MYK_SNIFFER_PROFILE, snifferProfile, &snifferHsDigClk_kHz); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + } + } + + return retVal; +} + +/** + * \brief Write indirect registers (Programmable FIRs, Rx gain tables, JESD204B settings). Must be done after Multi Chip Sync + * + * The BBP should never need to call this function. It is called automatically by the initArm function. + * This function is a continuation of the MYKONOS_initialize() function. This part of initialization must be done after + * the BBP has completed Multi chip Sync. These registers include FIR filters, Rx gain tables, and JESD204B framer/deframer + * config registers. + * + * Dependencies + * - device->spiSettings + * - device->spiSettings->chipSelectIndex + * + * \param device Pointer to the Mykonos device data structure containing settings + * an error. + * \return Returns enum mykonosErr_t, MYKONOS_ERR_OK=pass, !MYKONOS_ERR_OK=fail + */ +mykonosErr_t MYKONOS_initSubRegisterTables(mykonosDevice_t *device) +{ + mykonosErr_t retVal = MYKONOS_ERR_OK; + + /* ------------------------------------------------------------------------------------------- */ + /* Program submap register tables after digital clocks are up and running and Multi Chip Sync */ + /* has been completed by BBP */ + if (device->profilesValid & TX_PROFILE_VALID) + { + if (device->tx->txProfile->txFir != NULL) + { + retVal = MYKONOS_programFir(device, TX1TX2_FIR, device->tx->txProfile->txFir); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + } + } + + if (device->profilesValid & RX_PROFILE_VALID) + { + if (device->rx->rxProfile->rxFir != NULL) + { + retVal = MYKONOS_programFir(device, RX1RX2_FIR, device->rx->rxProfile->rxFir); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + /* Load Rx gain table */ + retVal = MYKONOS_programRxGainTable(device, &RxGainTable[0][0], (sizeof(RxGainTable) >> 2), RX1_RX2_GT); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + retVal = MYKONOS_setRx1ManualGain(device, device->rx->rxGainCtrl->rx1GainIndex); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + retVal = MYKONOS_setRx2ManualGain(device, device->rx->rxGainCtrl->rx2GainIndex); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + /* Enable Digital gain for Rx and ObsRx gain tables */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DIGITAL_GAIN_CONFIG, 0x80); + } + } + + if (device->profilesValid & SNIFF_PROFILE_VALID) + { + if (device->obsRx->snifferProfile->rxFir != NULL) + { + retVal = MYKONOS_programFir(device, OBSRX_B_FIR, device->obsRx->snifferProfile->rxFir); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + /* Load Sniffer Rx gain table */ + retVal = MYKONOS_programRxGainTable(device, &SnRxGainTable[0][0], (sizeof(SnRxGainTable) >> 2), SNRX_GT); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + retVal = MYKONOS_setObsRxManualGain(device, OBS_SNIFFER_A, device->obsRx->snifferGainCtrl->gainIndex); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + } + } + + if (device->profilesValid & ORX_PROFILE_VALID) + { + if (device->obsRx->orxProfile->rxFir != NULL) + {/* if pointer to orx rxFIR is valid */ + retVal = MYKONOS_programFir(device, OBSRX_A_FIR, device->obsRx->orxProfile->rxFir); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + /* Load ORx gain table */ + retVal = MYKONOS_programRxGainTable(device, &ORxGainTable[0][0], (sizeof(ORxGainTable) >> 2), ORX_GT); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + retVal = MYKONOS_setObsRxManualGain(device, OBS_RX1_TXLO, device->obsRx->orxGainCtrl->orx1GainIndex); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + retVal = MYKONOS_setObsRxManualGain(device, OBS_RX2_TXLO, device->obsRx->orxGainCtrl->orx2GainIndex); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + } + } + + /* Load Loopback Gain Table for ARM calibrations */ + { + uint8_t loopBackGainTable[6][4] = { + /* Order: {FE table, External Ctl, Digital Gain/Atten, Enable Atten} */ + {0, 0, 0, 0}, /* Gain index 255 */ + {7, 0, 0, 0}, /* Gain index 254 */ + {13, 0, 1, 1}, /* Gain index 253 */ + {18, 0, 3, 1}, /* Gain index 252 */ + {23, 0, 3, 1}, /* Gain index 251 */ + {28, 0, 0, 0} /* Gain index 250 */ + }; + retVal = MYKONOS_programRxGainTable(device, &loopBackGainTable[0][0], (sizeof(loopBackGainTable) >> 2), LOOPBACK_GT); + } + + /* Enable Digital gain for ORx/Sniffer/Loopback gain table */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DPD_SNIFFER_DIGITAL_GAIN_CONFIG, 0x80); + + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RCAL_CONTROL, 0x07);/* Set RCAL code to nominal */ + + /* If Valid Rx Profile or valid ObsRx profile, setup serializers */ + if ((device->profilesValid & RX_PROFILE_VALID) || (device->profilesValid & (ORX_PROFILE_VALID | SNIFF_PROFILE_VALID))) + { + retVal = MYKONOS_setupSerializers(device); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + } + + if ((device->rx->rxChannels != RXOFF) && (device->profilesValid & RX_PROFILE_VALID)) + { + retVal = MYKONOS_setupJesd204bFramer(device); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + } + + if ((device->obsRx->obsRxChannelsEnable != MYK_OBS_RXOFF) && (device->profilesValid & (ORX_PROFILE_VALID | SNIFF_PROFILE_VALID))) + { + retVal = MYKONOS_setupJesd204bObsRxFramer(device); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + } + + if ((device->tx->txChannels != TXOFF) && (device->profilesValid & TX_PROFILE_VALID)) + { + retVal = MYKONOS_setupDeserializers(device); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + retVal = MYKONOS_setupJesd204bDeframer(device); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + retVal = MYKONOS_setTx1Attenuation(device, device->tx->tx1Atten_mdB); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + retVal = MYKONOS_setTx2Attenuation(device, device->tx->tx2Atten_mdB); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + } + + return MYKONOS_ERR_OK; +} + +/** + * \brief Performs a blocking wait for a Mykonos calibration or Pll Lock + * + * Dependencies + * - device->spiSettings + * - device->spiSettings->chipSelectIndex + * + * \param device Pointer to the Mykonos device data structure containing settings + * \param waitEvent the enum value of the event to wait for + * \param timeout_us If timeout_us time has passed, function will return with + * an error. + * \return Returns enum mykonosErr_t, MYKONOS_ERR_OK=pass, !MYKONOS_ERR_OK=fail + */ +mykonosErr_t MYKONOS_waitForEvent(mykonosDevice_t *device, waitEvent_t waitEvent, uint32_t timeout_us) +{ + uint16_t spiAddr = 0; + uint8_t spiBit = 0; + uint8_t doneBitLevel = 0; + uint8_t data = 0; + mykonosErr_t errCode = MYKONOS_ERR_OK; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_waitForEvent()\n"); +#endif + + switch (waitEvent) + { + case CALPLL_LOCK:/* wait for x17F[7]=1 */ + spiAddr = MYKONOS_ADDR_CALPLL_SDM_CONTROL; + spiBit = 7; + doneBitLevel = 1; + errCode = MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_CALPLL_LOCK; + break; + case CLKPLLCP: /* wait for x154[5]=1 */ + spiAddr = MYKONOS_ADDR_CLK_SYNTH_CAL_STAT; + spiBit = 5; + doneBitLevel = 1; + errCode = MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_CLKPLLCP; + break; + case CLKPLL_LOCK: /* wait for x157[0]=1 */ + spiAddr = MYKONOS_ADDR_CLK_SYNTH_VCO_BAND_BYTE1; + spiBit = 0; + doneBitLevel = 1; + errCode = MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_CLKPLL_LOCK; + break; + case RF_RXPLLCP:/* wait for x254[5]=1 */ + spiAddr = MYKONOS_ADDR_RXSYNTH_CP_CAL_STAT; + spiBit = 5; + doneBitLevel = 1; + errCode = MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_RXPLLCP; + break; + case RF_RXPLL_LOCK: /* wait for x257[0]=1 */ + spiAddr = MYKONOS_ADDR_RXSYNTH_VCO_BAND_BYTE1; + spiBit = 0; + doneBitLevel = 1; + errCode = MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_RXPLL_LOCK; + break; + case RF_TXPLLCP: /* wait for x2C4[5]=1 */ + spiAddr = MYKONOS_ADDR_TXSYNTH_CP_CAL_STAT; + spiBit = 5; + doneBitLevel = 1; + errCode = MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_TXPLLCP; + break; + case RF_TXPLL_LOCK: /* wait for x2C7[0]=1 */ + spiAddr = MYKONOS_ADDR_TXSYNTH_VCO_BAND_BYTE1; + spiBit = 0; + doneBitLevel = 1; + errCode = MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_TXPLL_LOCK; + break; + case RF_SNIFFERPLLCP: /* wait for x354[7]=1 */ + spiAddr = MYKONOS_ADDR_SNIFF_RXSYNTH_CP_CAL_STAT; + spiBit = 5; + doneBitLevel = 1; + errCode = MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_SNIFFPLLCP; + break; + case RF_SNIFFERPLL_LOCK: /* wait for x357[0]=1 */ + spiAddr = MYKONOS_ADDR_SNIFF_RXSYNTH_VCO_BAND_BYTE1; + spiBit = 0; + doneBitLevel = 1; + errCode = MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_SNIFFPLL_LOCK; + break; + case RXBBF_CALDONE: /* wait for x1B2[5]=0 */ + spiAddr = MYKONOS_ADDR_CALIBRATION_CONTROL; + spiBit = 5; + doneBitLevel = 0; + errCode = MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_RXBBFCALDONE; + break; + case TXBBF_CALDONE:/* wait for x1B2[0]=0 */ + spiAddr = MYKONOS_ADDR_CALIBRATION_CONTROL; + spiBit = 0; + doneBitLevel = 0; + errCode = MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_TXBBFCALDONE; + break; + case RX_RFDC_CALDONE: /* wait for x1B2[1]=0 */ + spiAddr = MYKONOS_ADDR_CALIBRATION_CONTROL; + spiBit = 1; + doneBitLevel = 0; + errCode = MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_RFDCCALDONE; + break; + case RX_ADCTUNER_CALDONE:/* wait for x1B2[7]=0 */ + spiAddr = MYKONOS_ADDR_CALIBRATION_CONTROL; + spiBit = 7; + doneBitLevel = 0; + errCode = MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_ADCTUNECALDONE; + break; + case RX1_ADCPROFILE:/* wait for x5DD[5]=0 */ + spiAddr = MYKONOS_ADDR_RX_ADC1_PRFL; + spiBit = 5; + doneBitLevel = 0; + errCode = MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_RX1ADCPROFILE; + break; + case RX2_ADCPROFILE:/* wait for x5DE[5]=0 */ + spiAddr = MYKONOS_ADDR_RX_ADC2_PRFL; + spiBit = 5; + doneBitLevel = 0; + errCode = MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_RX2ADCPROFILE; + break; + case ORX_ADCPROFILE:/* wait for x5DF[5]=0 */ + spiAddr = MYKONOS_ADDR_ORX_ADC_PRFL; + spiBit = 5; + doneBitLevel = 0; + errCode = MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_ORXADCPROFILE; + break; + case RCAL_CALDONE: /* wait for x1B2[6]=0 */ + spiAddr = MYKONOS_ADDR_CALIBRATION_CONTROL; + spiBit = 6; + doneBitLevel = 0; + errCode = MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_RCALDONE; + break; + case ARMBUSY:/* wait for xD30[7]=0 */ + spiAddr = MYKONOS_ADDR_ARM_CMD; + spiBit = 7; + doneBitLevel = 0; + errCode = MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_ARMBUSY; + break; + case INITARM_DONE: + spiAddr = MYKONOS_ADDR_ARM_CMD; + spiBit = 7; + doneBitLevel = 0; + errCode = MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_INITARMDONE; + break; + default: + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_WAITFOREVENT_INV_PARM, + getMykonosErrorMessage(MYKONOS_ERR_WAITFOREVENT_INV_PARM)); + return MYKONOS_ERR_WAITFOREVENT_INV_PARM; + } + + CMB_setTimeout_us(timeout_us); /* timeout after desired time */ + + do + { + CMB_SPIReadByte(device->spiSettings, spiAddr, &data); + + /* For SW verification tests, allow API to think all cals are complete*/ +#ifdef MYK_CALS_DONE_SWDEBUG + if (doneBitLevel == 0) + { + data = 0x00; + } + else + { + data = 0xFF; + } +#endif + + if ((uint32_t)CMB_hasTimeoutExpired() > 0) + { + CMB_writeToLog(ADIHAL_LOG_WARNING, device->spiSettings->chipSelectIndex, errCode, getMykonosErrorMessage(errCode)); + return errCode; + } + } while (((data >> spiBit) & 0x01) != doneBitLevel); + + return MYKONOS_ERR_OK; +} + +/** + * \brief Performs a readback with no wait for a Mykonos calibration or Pll Lock + * + * Dependencies + * - device->spiSettings + * - device->spiSettings->chipSelectIndex + * + * \param device Pointer to the Mykonos device data structure containing settings + * \param waitEvent the enum value of the event to wait for + * \param eventDone Return value: 1= calibration event is complete. 0 = Event is still pending + * \return Returns enum mykonosErr_t, MYKONOS_ERR_OK=pass, !MYKONOS_ERR_OK=fail + */ +mykonosErr_t MYKONOS_readEventStatus(mykonosDevice_t *device, waitEvent_t waitEvent, uint8_t *eventDone) +{ + uint16_t spiAddr = 0; + uint8_t data = 0; + uint8_t spiBit = 0; + uint8_t doneBitLevel = 0; + + switch (waitEvent) + { + case CALPLL_LOCK:/* wait for x17F[7]=1 */ + spiAddr = MYKONOS_ADDR_CALPLL_SDM_CONTROL; + spiBit = 7; + doneBitLevel = 1; + break; + case CLKPLLCP: /* wait for x154[5]=1 */ + spiAddr = MYKONOS_ADDR_CLK_SYNTH_CAL_STAT; + spiBit = 5; + doneBitLevel = 1; + break; + case CLKPLL_LOCK: /* wait for x157[0]=1 */ + spiAddr = MYKONOS_ADDR_CLK_SYNTH_VCO_BAND_BYTE1; + spiBit = 0; + doneBitLevel = 1; + break; + case RF_RXPLLCP:/* wait for x254[5]=1 */ + spiAddr = MYKONOS_ADDR_RXSYNTH_CP_CAL_STAT; + spiBit = 5; + doneBitLevel = 1; + break; + case RF_RXPLL_LOCK: /* wait for x257[0]=1 */ + spiAddr = MYKONOS_ADDR_RXSYNTH_VCO_BAND_BYTE1; + spiBit = 0; + doneBitLevel = 1; + break; + case RF_TXPLLCP: /* wait for x2C4[5]=1 */ + spiAddr = MYKONOS_ADDR_TXSYNTH_CP_CAL_STAT; + spiBit = 5; + doneBitLevel = 1; + break; + case RF_TXPLL_LOCK: /* wait for x2C7[0]=1 */ + spiAddr = MYKONOS_ADDR_TXSYNTH_VCO_BAND_BYTE1; + spiBit = 0; + doneBitLevel = 1; + break; + case RF_SNIFFERPLLCP: /* wait for x354[7]=1 */ + spiAddr = MYKONOS_ADDR_SNIFF_RXSYNTH_CP_CAL_STAT; + spiBit = 5; + doneBitLevel = 1; + break; + case RF_SNIFFERPLL_LOCK: /* wait for x357[0]=1 */ + spiAddr = MYKONOS_ADDR_SNIFF_RXSYNTH_VCO_BAND_BYTE1; + spiBit = 0; + doneBitLevel = 1; + break; + case RXBBF_CALDONE: /* wait for x1B2[5]=0 */ + spiAddr = MYKONOS_ADDR_CALIBRATION_CONTROL; + spiBit = 5; + doneBitLevel = 0; + break; + case TXBBF_CALDONE:/* wait for x1B2[0]=0 */ + spiAddr = MYKONOS_ADDR_CALIBRATION_CONTROL; + spiBit = 0; + doneBitLevel = 0; + break; + case RX_RFDC_CALDONE: /* wait for x1B2[1]=0 */ + spiAddr = MYKONOS_ADDR_CALIBRATION_CONTROL; + spiBit = 1; + doneBitLevel = 0; + break; + case RX_ADCTUNER_CALDONE:/* wait for x1B2[7]=0 */ + spiAddr = MYKONOS_ADDR_CALIBRATION_CONTROL; + spiBit = 7; + doneBitLevel = 0; + break; + case RX1_ADCPROFILE:/* wait for x5DD[5]=0 */ + spiAddr = MYKONOS_ADDR_RX_ADC1_PRFL; + spiBit = 5; + doneBitLevel = 0; + break; + case RX2_ADCPROFILE:/* wait for x5DE[5]=0 */ + spiAddr = MYKONOS_ADDR_RX_ADC2_PRFL; + spiBit = 5; + doneBitLevel = 0; + break; + case ORX_ADCPROFILE:/* wait for x5DF[5]=0 */ + spiAddr = MYKONOS_ADDR_ORX_ADC_PRFL; + spiBit = 5; + doneBitLevel = 0; + break; + case RCAL_CALDONE: /* wait for x1B2[6]=0 */ + spiAddr = MYKONOS_ADDR_CALIBRATION_CONTROL; + spiBit = 6; + doneBitLevel = 0; + break; + case ARMBUSY:/* wait for xD30[7]=0 */ + spiAddr = MYKONOS_ADDR_ARM_CMD; + spiBit = 7; + doneBitLevel = 0; + break; + default: + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_WAITFOREVENT_INV_PARM, + getMykonosErrorMessage(MYKONOS_ERR_WAITFOREVENT_INV_PARM)); + return MYKONOS_ERR_WAITFOREVENT_INV_PARM; + } + + CMB_SPIReadByte(device->spiSettings, spiAddr, &data); + + if (doneBitLevel) + { + *eventDone = (data >> spiBit) & 0x01; + } + else + { + *eventDone = (~(data >> spiBit) & 0x01); + } + + return MYKONOS_ERR_OK; +} + +/** + * \brief Sets the CLKPLL output frequency. + * + * This code updates the Synth and Loop filter settings based on a VCO + * frequency LUT. The VCO frequency break points for the Synth LUT can be + * found in an array called vcoFreqArrayMhz. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * - device->spiSettings + * - device->deviceClock_kHz + * - device->rxSettings->rxProfile->vcoFreq_kHz + * - device->rxSettings->rxProfile->clkPllHsDiv + * - device->rxSettings->rxProfile->clkPllVcoDiv + * + * \param device is structure pointer to the MYKONOS data structure containing settings + * + * \return Returns enum MYKONOS_ERR, MYKONOS_ERR_OK=pass, !MYKONOS_ERR_OK=fail + */ +mykonosErr_t MYKONOS_initDigitalClocks(mykonosDevice_t *device) +{ + /* RF Synth variables */ + /* pull Synth and Loop filter values from a Look Up Table */ + uint8_t vcoOutLvl; + uint8_t vcoVaractor; /* [3:0] */ + uint8_t vcoBiasRef; /* [2:0] */ + uint8_t vcoBiasTcf; /* [1:0] */ + uint8_t vcoCalOffset; /* [3:0] */ + uint8_t vcoVaractorRef; /* [3:0] */ + uint8_t loopFilterIcp; /* Icp[5:0] */ + uint8_t loopFilterC2C1; /* C2[3:0],C1[3:0] */ + uint8_t loopFilterR1C3; /* R1[3:0],C3[3:0] */ + uint8_t loopFilterR3; /* R3[3:0] */ + uint8_t vcoIndex; + uint8_t i; + + /* RF PLL variables */ + uint16_t integerWord; + uint32_t fractionalWord; + uint32_t fractionalRemainder; + uint32_t scaledRefClk_Hz; + + /* common */ + uint64_t hsDigClk_Hz = 0; + uint32_t scaledRefClk_kHz = 0; + uint8_t deviceClkDiv = 0; + mykonosErr_t retVal = MYKONOS_ERR_OK; + + uint8_t clockControl2 = 0; + uint8_t sdmSettings = 0; + uint8_t hsDiv = 4; + uint8_t vcoDiv = 0; + uint8_t vcoDivTimes10 = 10; + + /******************RF Synth Section************************/ + static const uint8_t icp_46p08[53] = {15, 15, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 27, 27, 28, 29, 30, 31, 32, 33, 32, 33, 32, 33, 33, 34, 27, 28, 29, + 29, 30, 39, 29, 30, 31, 31, 30, 31, 31, 32, 30, 31, 31, 32, 32, 31, 31, 32, 32, 33}; + + static const uint8_t icp_61p44[53] = {13, 13, 13, 14, 15, 16, 16, 17, 18, 19, 20, 21, 22, 22, 23, 24, 24, 25, 25, 26, 27, 28, 29, 28, 29, 28, 29, 29, 30, 24, 25, 25, + 26, 26, 35, 33, 34, 35, 35, 26, 27, 27, 28, 27, 27, 27, 28, 28, 27, 27, 28, 28, 29}; + + static const uint8_t icp_76p8[53] = {7, 7, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 15, 16, 15, 16, 15, 16, 16, 17, 13, 14, 14, 14, 15, + 19, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 15, 15, 15, 16, 16}; + + static const uint32_t vcoFreqArray_kHz[53] = {12605000UL, 12245000UL, 11906000UL, 11588000UL, 11288000UL, 11007000UL, 10742000UL, 10492000UL, 10258000UL, 10036000UL, + 9827800UL, 9631100UL, 9445300UL, 9269800UL, 9103600UL, 8946300UL, 8797000UL, 8655300UL, 8520600UL, 8392300UL, 8269900UL, 8153100UL, 8041400UL, 7934400UL, + 7831800UL, 7733200UL, 7638400UL, 7547100UL, 7459000UL, 7374000UL, 7291900UL, 7212400UL, 7135500UL, 7061000UL, 6988700UL, 6918600UL, 6850600UL, 6784600UL, + 6720500UL, 6658200UL, 6597800UL, 6539200UL, 6482300UL, 6427000UL, 6373400UL, 6321400UL, 6270900UL, 6222000UL, 6174500UL, 6128400UL, 6083600UL, 6040100UL, + 5997700UL}; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_initDigitalClocks()\n"); +#endif + + retVal = MYKONOS_calculateScaledDeviceClk_kHz(device, &scaledRefClk_kHz, &deviceClkDiv); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + hsDiv = device->clocks->clkPllHsDiv; + vcoDiv = device->clocks->clkPllVcoDiv; + + switch (hsDiv) + { + case 4: + hsDiv = 4; /* clockControl2[3:2] = 00 */ + break; + case 5: + hsDiv = 5; + clockControl2 |= 0x04; /* Set bit[2]=1 */ + break; + default: + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CLKPLL_INV_HSDIV, getMykonosErrorMessage(MYKONOS_ERR_CLKPLL_INV_HSDIV)); + return MYKONOS_ERR_CLKPLL_INV_HSDIV; + } + + switch (vcoDiv) + { + case VCODIV_1: + vcoDivTimes10 = 10; /* clockControl2[1:0] = 00 */ + break; + case VCODIV_1p5: + vcoDivTimes10 = 15; + clockControl2 |= 0x01; + break; + case VCODIV_2: + vcoDivTimes10 = 20; + clockControl2 |= 0x02; + break; + case VCODIV_3: + vcoDivTimes10 = 30; + clockControl2 |= 0x03; + break; + default: + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CLKPLL_INV_VCODIV, getMykonosErrorMessage(MYKONOS_ERR_CLKPLL_INV_VCODIV)); + return MYKONOS_ERR_CLKPLL_INV_VCODIV; + } + + clockControl2 |= ((deviceClkDiv & 3) << 4); + + /* find vco table index based on vco frequency */ + for (i = 0; device->clocks->clkPllVcoFreq_kHz < vcoFreqArray_kHz[i]; i++) + { + /* Intentionally blank, for loop exits when condition met, index i used below */ + } + vcoIndex = i + 1; + + if (vcoIndex < 1 || vcoIndex > 53) + { + /* vco index out of range */ + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETCLKPLL_INV_VCOINDEX, + getMykonosErrorMessage(MYKONOS_ERR_SETCLKPLL_INV_VCOINDEX)); + return MYKONOS_ERR_SETCLKPLL_INV_VCOINDEX; + } + + /* valid for all refclk frequencies */ + vcoOutLvl = (vcoIndex <= 16) ? 13 : (vcoIndex <= 23) ? 12 : (vcoIndex <= 25) ? + 11 : (vcoIndex <= 35) ? 10 : (vcoIndex <= 39) ? 9 : (vcoIndex <= 43) ? + 8 : (vcoIndex <= 48) ? 7 : 6; + vcoVaractor = (vcoIndex <= 29 || vcoIndex == 35) ? 1 : 2; + vcoBiasRef = (vcoIndex <= 7 ) ? 4 : (vcoIndex <= 16) ? 6 : 7; + vcoBiasTcf = (vcoIndex <= 25 || (vcoIndex > 26 && vcoIndex <= 29) || + (vcoIndex > 37 && vcoIndex <= 39)) || (vcoIndex > 40 && vcoIndex <= 43) ? + 2 : 3; + + vcoVaractorRef = (vcoIndex <= 29) ? 12 : (vcoIndex == 35) ? 14 : 13; + + if ((scaledRefClk_kHz >= 40000) && (scaledRefClk_kHz < 53760)) + { /* Settings designed for 46.08 MHz PLL REFCLK */ + vcoCalOffset = (vcoIndex == 11 || (vcoIndex > 35 && vcoIndex <= 37) || (vcoIndex > 29 && vcoIndex <= 34)|| vcoIndex == 40 || vcoIndex == 44) ? + 14 :(vcoIndex <= 10 || vcoIndex > 44) ? + 15 : ((vcoIndex > 12 && vcoIndex <= 22) || (vcoIndex > 23 && vcoIndex <= 23) || (vcoIndex > 26 && vcoIndex <= 29) || (vcoIndex > 23 && vcoIndex <= 25) || vcoIndex == 35) ? + 12 : 13; + + loopFilterIcp = icp_46p08[vcoIndex - 1]; + loopFilterC2C1 = 0xF9; /* C2=0xF0 */ + loopFilterR1C3 = 0xD5; + loopFilterR3 = 0x0E; + } + else if ((scaledRefClk_kHz >= 53760) && (scaledRefClk_kHz < 69120)) + { /* Settings designed for 61.44 MHz PLL REFCLK */ + vcoCalOffset = (vcoIndex == 11 || (vcoIndex > 29 && vcoIndex <= 34) || vcoIndex == 40 || vcoIndex == 44) ? + 14 :(vcoIndex <= 10 || vcoIndex > 44) ? + 15 : ((vcoIndex > 12 && vcoIndex <= 22) || (vcoIndex > 23 && vcoIndex <= 25) || (vcoIndex > 26 && vcoIndex <= 29) || (vcoIndex > 34 && vcoIndex <= 37)) ? + 12 : (vcoIndex > 37 && vcoIndex <= 39) ? 11 : 13; + + vcoVaractor = (vcoIndex > 35 && vcoIndex <= 39) ? 1 : vcoVaractor; + vcoBiasRef = (vcoIndex > 4 && vcoIndex <= 7) ? 5 : vcoBiasRef; + vcoVaractorRef = (vcoIndex > 35 && vcoIndex <= 39) ? 14 : vcoVaractorRef; + loopFilterIcp = icp_61p44[vcoIndex-1]; + loopFilterC2C1 = ((vcoIndex > 2 && vcoIndex <= 6) || (vcoIndex > 8 && vcoIndex <= 13) || (vcoIndex > 14)) ? 0xFD : 0xFC; /* C2=0xF0 */ + loopFilterR1C3 = 0xC5; + loopFilterR3 = (vcoIndex <= 2 || (vcoIndex > 6 && vcoIndex <= 8) || vcoIndex == 14) ? 14 : 13 ; + } + else if ((scaledRefClk_kHz >= 69120) && (scaledRefClk_kHz <= 80000)) + { /* Settings designed for 76.8 MHz PLL REFCLK */ + vcoCalOffset = (vcoIndex == 11 || (vcoIndex > 35 && vcoIndex <= 37) || (vcoIndex > 29 && vcoIndex <= 34)|| vcoIndex == 40 || vcoIndex == 44) ? + 14 :(vcoIndex <= 10 || vcoIndex > 44) ? + 15 : ((vcoIndex > 12 && vcoIndex <= 22) || (vcoIndex > 23 && vcoIndex <= 23) || (vcoIndex > 26 && vcoIndex <= 29) || (vcoIndex > 23 && vcoIndex <= 25) || vcoIndex == 35) ? + 12 : 13; + + loopFilterIcp = icp_76p8[vcoIndex-1]; + loopFilterC2C1 = (vcoIndex == 20 ) ? 0xF7 : (vcoIndex == 4 || vcoIndex == 6 || vcoIndex == 8 ) ? 0xE6: 0xF6; /*C2=0xF0, C1=6 or 7 */ + loopFilterR1C3 = (vcoIndex == 4 ) ? 0xE4 : 0xD5; + loopFilterR3 = 0x0E; + } + else + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETRFPLL_INV_REFCLK, getMykonosErrorMessage(MYKONOS_ERR_SETRFPLL_INV_REFCLK)); + return MYKONOS_ERR_SETRFPLL_INV_REFCLK; /* invalid ref clk */ + } + + /* Hold CLKPLL digital logic in reset */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLOCK_CONTROL_4, 0x00); + + /* Set reference clock scaler + HSdiv + VCOdiv */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLOCK_CONTROL_2, clockControl2); + + /*Set VCO cal time */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_CAL_CONTROL, 0x02); + + /* Write Synth Setting regs */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_F_VCOTN_BYTE1, ((vcoCalOffset & 0x0F) << 3)); /* Set VCO Cal offset[3:0] */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_BYTE1, (0xC0 | (vcoVaractor & 0x0F))); /* Init ALC[3:0], VCO varactor[3:0] */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_BYTE2, (0x40 | (vcoOutLvl & 0x0F))); /* VCO output level */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_BYTE9, (((vcoBiasTcf & 0x03) << 3) | (vcoBiasRef & 0x07))); /* Set VCO Bias Tcf[1:0] and VCO Bias Ref[2:0] */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_VCO_CAL_REF, 0x30); /* Set VCO cal time (compare length) + Set VCO Cal Ref Tcf[2:0]=0 */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_VCO_VAR_CTL1, 0x70); /* Set VCO Varactor Ref Tcf[2:0] and VCO Varactor Offset[3:0] */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_VCO_VAR_CTL2, (vcoVaractorRef & 0x0F)); /* Set VCO Varactor Reference[3:0] */ + + /* Write Loop filter */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_BYTE3, (0x80 | (loopFilterIcp & 0x03F))); /* Set Loop Filter Icp[5:0] */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_BYTE6, loopFilterC2C1); /* Set Loop Filter C2[3:0] and C1[3:0] */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_BYTE7, loopFilterR1C3); /* Set Loop Filter R1[3:0] and C3[3:0] */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_LF_R3, (loopFilterR3 & 0x0F)); /*Set Loop Filter R3[3:0] */ + + /* Calculate PLL integer and fractional words with integer math */ + scaledRefClk_Hz = scaledRefClk_kHz * 1000; + hsDigClk_Hz = (((uint64_t)(device->clocks->clkPllVcoFreq_kHz) * 10000) / vcoDivTimes10) / hsDiv; + integerWord = (uint16_t)(hsDigClk_Hz / scaledRefClk_Hz); + fractionalRemainder = hsDigClk_Hz % scaledRefClk_Hz; + + /* +1 >> 1 is rounding (add .5) */ + fractionalWord = ((uint32_t)((((uint64_t)fractionalRemainder * 4177920) / (uint64_t)scaledRefClk_Hz) + 1) >> 1); + + /* if fractionalWord rounded up and == PLL modulus, fix it */ + if (fractionalWord == 2088960) + { + fractionalWord = 0; + integerWord = integerWord + 1; + } + + if (fractionalWord > 0) + { /* in normal case, the fractional word should be zero and SDM bypassed */ + CMB_writeToLog(ADIHAL_LOG_WARNING, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETCLKPLL_INV_FRACWORD, + getMykonosErrorMessage(MYKONOS_ERR_SETCLKPLL_INV_FRACWORD)); + /* down graded to warning, do not return error code */ + //return MYKONOS_ERR_SETCLKPLL_INV_FRACWORD; + sdmSettings = 0x20; + } + else + { + /* Bypass SDM */ + sdmSettings = 0xE0; + } + + /* Set PLL fractional word[22:0] */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_DIVIDER_FRAC_BYTE0, (fractionalWord & 0xFF)); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_DIVIDER_FRAC_BYTE1, ((fractionalWord >> 8) & 0xFF)); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_DIVIDER_FRAC_BYTE2, ((fractionalWord >> 16) & 0x7F)); + + /* Write PLL integer word [7:0] */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_DIVIDER_INT_BYTE1, (sdmSettings | ((integerWord >> 8) & 0x7))); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_DIVIDER_INT_BYTE0, (integerWord & 0xFF)); + + /* Release PLL from reset, and set start VCO cal bit to 0 */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLOCK_CONTROL_4, 0x80); + + /* Power up CLKPLL */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLOCK_CONTROL_0, 0x00); + CMB_wait_ms(200); /* Allow PLL time to power up */ + + /* Enable Charge pump cal after Charge Pump current set (Icp[5:0]) */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_BYTE5, 0x84); + + /* Start VCO Cal */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLOCK_CONTROL_4, 0x81); + + return MYKONOS_ERR_OK; +} + +/** + * \brief Sets the RF PLL local oscillator frequency (RF carrier frequency). + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * - device->spiSettings + * + * \param device is structure pointer to the MYKONOS data structure containing settings + * \param pllName Name of the PLL to configure + * \param rfPllLoFrequency_Hz Desired RF LO frequency + * + * \return MYKONOS_ERR_OK Function completed successfully + * \return MYKONOS_ERR_SETRFPLL_ARMERROR ARM Command to set RF PLL frequency failed + */ +mykonosErr_t MYKONOS_setRfPllFrequency(mykonosDevice_t *device, mykonosRfPllName_t pllName, uint64_t rfPllLoFrequency_Hz) +{ + const uint8_t SETCMD_OPCODE = 0x0A; + const uint8_t SET_PLL_FREQUENCY = 0x63; + + mykonosErr_t retVal = MYKONOS_ERR_OK; + uint8_t armData[8] = {0}; + uint8_t extData[2] = {0}; + uint32_t timeoutMs = 0; + uint8_t cmdStatusByte = 0; + + armData[0] = (uint8_t)(rfPllLoFrequency_Hz & 0xFF); + armData[1] = (uint8_t)((rfPllLoFrequency_Hz >> 8) & 0xFF); + armData[2] = (uint8_t)((rfPllLoFrequency_Hz >> 16) & 0xFF); + armData[3] = (uint8_t)((rfPllLoFrequency_Hz >> 24) & 0xFF); + armData[4] = (uint8_t)((rfPllLoFrequency_Hz >> 32) & 0xFF); + armData[5] = (uint8_t)((rfPllLoFrequency_Hz >> 40) & 0xFF); + armData[6] = (uint8_t)((rfPllLoFrequency_Hz >> 48) & 0xFF); + armData[7] = (uint8_t)((rfPllLoFrequency_Hz >> 56) & 0xFF); + + /* write 64-bit frequency to ARM memory */ + retVal = MYKONOS_writeArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR, &armData[0], 8); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + extData[0] = SET_PLL_FREQUENCY; + + switch (pllName) + { + case RX_PLL: + extData[1] = 0x00; + break; + case TX_PLL: + extData[1] = 0x01; + break; + case SNIFFER_PLL: + extData[1] = 0x02; + break; + default: + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETRFPLL_INV_PLLNAME, + getMykonosErrorMessage(MYKONOS_ERR_SETRFPLL_INV_PLLNAME)); + return MYKONOS_ERR_SETRFPLL_INV_PLLNAME; + } + } + + retVal = MYKONOS_sendArmCommand(device, SETCMD_OPCODE, &extData[0], sizeof(extData)); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + timeoutMs = 1000; + retVal = MYKONOS_waitArmCmdStatus(device, SETCMD_OPCODE, timeoutMs, &cmdStatusByte); + if (retVal != MYKONOS_ERR_OK) + { + if (cmdStatusByte > 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETRFPLL_ARMERROR, getMykonosErrorMessage(MYKONOS_ERR_SETRFPLL_ARMERROR)); + return MYKONOS_ERR_SETRFPLL_ARMERROR; + } + + return retVal; + } + + if (cmdStatusByte > 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETRFPLL_ARMERROR, getMykonosErrorMessage(MYKONOS_ERR_SETRFPLL_ARMERROR)); + return MYKONOS_ERR_SETRFPLL_ARMERROR; + } + + return MYKONOS_ERR_OK; +} + +/** + * \brief Gets the RF PLL local oscillator frequency (RF carrier frequency). + * + * This function is used to get the RF PLL's frequency. It can get the RX PLL, TX PLL + * Sniffer PLL, and CLKPLL. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * - device->spiSettings + * - device->clocks->deviceClock_kHz + * + * \param device is structure pointer to the MYKONOS data structure containing settings + * \param pllName Name of the PLL for which to read the frequency + * \param rfPllLoFrequency_Hz RF LO frequency currently set for the PLL specified + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_GET_PLLFREQ_INV_REFCLKDIV Invalid CLKPLL reference clock divider read from Mykonos device + * \retval MYKONOS_ERR_GET_PLLFREQ_INV_HSDIV Invalid CLKPLL high speed clock divider read from Mykonos device + * \retval MYKONOS_ERR_GETRFPLL_INV_PLLNAME Invalid PLL name, can not get PLL frequency. Use PLL name ENUM. + * \retval MYKONOS_ERR_GETRFPLL_ARMERROR ARM Command to get RF PLL frequency failed + * \retval MYKONOS_ERR_GETRFPLL_NULLPARAM rfPllLoFrequency_Hz function parameter pointer is NULL + */ +mykonosErr_t MYKONOS_getRfPllFrequency(mykonosDevice_t *device, mykonosRfPllName_t pllName, uint64_t *rfPllLoFrequency_Hz) +{ + const uint8_t RFPLL_LO_FREQUENCY = 0x63; + + mykonosErr_t retVal = MYKONOS_ERR_OK; + uint8_t armData[8] = {0, 0, 0, 0, 0, 0, 0, 0}; + uint8_t extData[2] = {0, 0}; + uint32_t timeoutMs = 0; + uint8_t cmdStatusByte = 0; + uint8_t getClkPllFrequency = 0; + + uint32_t clkPllIntWord = 0; + uint32_t clkPllFracWord = 0; + uint8_t clkPllRefClkDiv = 0; + uint8_t hsDiv = 0; + uint8_t vcoDivTimes10 = 0; + uint8_t hsDivReg = 0; + uint8_t vcoDivReg = 0; + uint8_t clkPllIntWord7_0 = 0; + uint8_t clkPllIntWord10_8 = 0; + uint8_t clkPllFracWord7_0 = 0; + uint8_t clkPllFracWord15_8 = 0; + uint8_t clkPllFracWord22_16 = 0; + uint64_t refclk_Hz = 0; + + extData[0] = RFPLL_LO_FREQUENCY; + + switch (pllName) + { + case CLK_PLL: + getClkPllFrequency = 1; + break; + case RX_PLL: + extData[1] = 0x00; + break; + case TX_PLL: + extData[1] = 0x01; + break; + case SNIFFER_PLL: + extData[1] = 0x02; + break; + default: + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETRFPLL_INV_PLLNAME, + getMykonosErrorMessage(MYKONOS_ERR_GETRFPLL_INV_PLLNAME)); + return MYKONOS_ERR_GETRFPLL_INV_PLLNAME; + } + } + + if (getClkPllFrequency > 0) + { + CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_CLOCK_CONTROL_2, &hsDivReg, 0x0C, 2); + CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_CLOCK_CONTROL_2, &vcoDivReg, 0x03, 0); + CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_CLOCK_CONTROL_2, &clkPllRefClkDiv, 0x70, 4); + + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_DIVIDER_INT_BYTE0, &clkPllIntWord7_0); + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_DIVIDER_INT_BYTE1, &clkPllIntWord10_8); + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_DIVIDER_FRAC_BYTE0, &clkPllFracWord7_0); + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_DIVIDER_FRAC_BYTE1, &clkPllFracWord15_8); + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_DIVIDER_FRAC_BYTE2, &clkPllFracWord22_16); + + clkPllIntWord = (((uint32_t)(clkPllIntWord10_8 & 0x7) << 8) | clkPllIntWord7_0); + clkPllFracWord = (((uint32_t)(clkPllFracWord22_16 & 0x7F) << 16) | ((uint32_t)(clkPllFracWord15_8) << 8) | clkPllFracWord7_0); + + switch (clkPllRefClkDiv) + { + case 0: + refclk_Hz = ((uint64_t)device->clocks->deviceClock_kHz * 1000); + break; + case 1: + refclk_Hz = (((uint64_t)device->clocks->deviceClock_kHz * 1000) >> 1); + break; /* div 2 */ + case 2: + refclk_Hz = (((uint64_t)device->clocks->deviceClock_kHz * 1000) >> 2); + break; /* div 4 */ + case 3: + refclk_Hz = (((uint64_t)device->clocks->deviceClock_kHz * 1000) << 1); + break; /* times 2 */ + default: + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GET_PLLFREQ_INV_REFCLKDIV, + getMykonosErrorMessage(MYKONOS_ERR_GET_PLLFREQ_INV_REFCLKDIV)); + return MYKONOS_ERR_GET_PLLFREQ_INV_REFCLKDIV; + } + } + + switch (vcoDivReg) + { + case 0: + vcoDivTimes10 = 10; + break; + case 1: + vcoDivTimes10 = 15; + break; + case 2: + vcoDivTimes10 = 20; + break; + case 3: + vcoDivTimes10 = 30; + break; + default: + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GET_PLLFREQ_INV_VCODIV, + getMykonosErrorMessage(MYKONOS_ERR_GET_PLLFREQ_INV_VCODIV)); + return MYKONOS_ERR_GET_PLLFREQ_INV_VCODIV; + } + } + + switch (hsDivReg) + { + case 0: + hsDiv = 4; + break; + case 1: + hsDiv = 5; + break; + default: + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GET_PLLFREQ_INV_HSDIV, + getMykonosErrorMessage(MYKONOS_ERR_GET_PLLFREQ_INV_HSDIV)); + return MYKONOS_ERR_GET_PLLFREQ_INV_HSDIV; + } + } + + /* round to nearest Hz for fractional word (fractional modulus = 2088960) */ + *rfPllLoFrequency_Hz = (uint64_t)(((refclk_Hz * clkPllIntWord) + (((refclk_Hz * clkPllFracWord / 1044480) + 1) >> 1)) * hsDiv * vcoDivTimes10 / 10); + } + else + { + retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_GET_OPCODE, &extData[0], sizeof(extData)); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + timeoutMs = 1000; + retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_GET_OPCODE, timeoutMs, &cmdStatusByte); + if (retVal != MYKONOS_ERR_OK) + { + if (cmdStatusByte > 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETRFPLL_ARMERROR, + getMykonosErrorMessage(MYKONOS_ERR_GETRFPLL_ARMERROR)); + return MYKONOS_ERR_GETRFPLL_ARMERROR; + } + + return retVal; + } + + /* read 64-bit frequency from ARM memory */ + retVal = MYKONOS_readArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR, &armData[0], 8, 1); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + if (cmdStatusByte > 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETRFPLL_ARMERROR, getMykonosErrorMessage(MYKONOS_ERR_GETRFPLL_ARMERROR)); + return MYKONOS_ERR_GETRFPLL_ARMERROR; + } + + if (rfPllLoFrequency_Hz == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETRFPLL_NULLPARAM, + getMykonosErrorMessage(MYKONOS_ERR_GETRFPLL_NULLPARAM)); + return MYKONOS_ERR_GETRFPLL_NULLPARAM; + } + + *rfPllLoFrequency_Hz = (uint64_t)((uint64_t)(armData[0])) | ((uint64_t)(armData[1]) << 8) | ((uint64_t)(armData[2]) << 16) | ((uint64_t)(armData[3]) << 24) + | ((uint64_t)(armData[4]) << 32) | ((uint64_t)(armData[5]) << 40) | ((uint64_t)(armData[6]) << 48) | ((uint64_t)(armData[7]) << 56); + } + return MYKONOS_ERR_OK; +} + +/** + * \brief Checks if the PLLs are locked + * + * This function updates the pllLockStatus pointer with a lock status it per + * PLL. + * pllLockStatus[0] = CLKPLL Locked + * pllLockStatus[1] = RX_PLL Locked + * pllLockStatus[2] = TX_PLL Locked + * pllLockStatus[3] = SNIFFER_PLL Locked + * pllLockStatus[4] = CAL_PLL Locked + * + * \param device the Mykonos device data structure + * \param pllLockStatus Lock status bit per PLL + * + * \return Returns enum MYKONOS_ERR, MYKONOS_ERR_OK=pass, !MYKONOS_ERR_OK=fail + */ +mykonosErr_t MYKONOS_checkPllsLockStatus(mykonosDevice_t *device, uint8_t *pllLockStatus) +{ + uint8_t readData = 0; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_checkPllsLockStatus()\n"); +#endif + + if (pllLockStatus == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CHECK_PLL_LOCK_NULL_PARM, + getMykonosErrorMessage(MYKONOS_ERR_CHECK_PLL_LOCK_NULL_PARM)); + return MYKONOS_ERR_CHECK_PLL_LOCK_NULL_PARM; + } + + *pllLockStatus = 0; + + CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_VCO_BAND_BYTE1, &readData, 0x01, 0); + *pllLockStatus = readData; + + CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_RXSYNTH_VCO_BAND_BYTE1, &readData, 0x01, 0); + *pllLockStatus = *pllLockStatus | (uint8_t)(readData << 1); + + CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_TXSYNTH_VCO_BAND_BYTE1, &readData, 0x01, 0); + *pllLockStatus = *pllLockStatus | (uint8_t)(readData << 2); + + CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_SNIFF_RXSYNTH_VCO_BAND_BYTE1, &readData, 0x01, 0); + *pllLockStatus = *pllLockStatus | (uint8_t)(readData << 3); + + CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_CALPLL_SDM_CONTROL, &readData, 0x80, 7); + *pllLockStatus = *pllLockStatus | (uint8_t)(readData << 4); + + return MYKONOS_ERR_OK; +} + +/* + ***************************************************************************** + * Shared Data path functions + ***************************************************************************** + */ + +/** + * \brief Sets the digital Tx PFIR SYNC clock divider. + * + * This function is a helper function. It is called automatically in + * MYKONOS_initialize() and should not need to be called by the BBIC. + * + * This function sets the digital clock divider that is used to synchronize the + * Tx PFIR each time the Tx channel power up. The Sync clock must + * be set equal to or slower than the FIR processing clock. + * + * Dependencies + * - device->spiSettings + * - device->spiSettings->chipSelectIndex + * - device->profilesValid + * - device->tx->txProfile->txFir + * - device->tx->txProfile->txFir->numFirCoefs + * - device->tx->txProfile->txFirInterpolation + * - device->tx->txProfile->iqRate_kHz + * + * \param device Pointer to the Mykonos data structure + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_TXFIR_INV_NUMTAPS_PARM: Invalid number of Tx FIR coefficients + * \retval MYKONOS_ERR_TXFIR_INV_NUMROWS Invalid number of PFIR coefficient rows + * \retval MYKONOS_ERR_TXFIR_TAPSEXCEEDED Too many Tx PFIR taps for the IQ sample rate. FIR processing clock can not run fast enough to handle the number of taps + */ +mykonosErr_t MYKONOS_setTxPfirSyncClk(mykonosDevice_t *device) +{ + const uint8_t numTapMultiple = 16; + const uint8_t maxNumTaps = 96; + uint8_t effectiveRows = 0; + uint8_t numRows = 0; + uint32_t dpClk_kHz = 0; + uint32_t syncClk_kHz = 0; + uint32_t hsDigClkDiv4or5_kHz = 0; + uint8_t syncDiv = 0; + mykonosErr_t retval = MYKONOS_ERR_OK; + + if (((device->profilesValid & TX_PROFILE_VALID) > 0) && (device->tx->txProfile->txFir != NULL)) + { + /* Calculate number of FIR rows for number of Taps */ + if ((device->tx->txProfile->txFir->numFirCoefs % numTapMultiple == 0) && (device->tx->txProfile->txFir->numFirCoefs > 0) + && (device->tx->txProfile->txFir->numFirCoefs <= maxNumTaps)) + { + numRows = (device->tx->txProfile->txFir->numFirCoefs / numTapMultiple); + } + else + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_TXFIR_INV_NUMTAPS_PARM, + getMykonosErrorMessage(MYKONOS_ERR_TXFIR_INV_NUMTAPS_PARM)); + return MYKONOS_ERR_TXFIR_INV_NUMTAPS_PARM; + } + + effectiveRows = ((numRows + (device->tx->txProfile->txFirInterpolation - 1)) / device->tx->txProfile->txFirInterpolation); + + /* round up to next power of 2 */ + switch (effectiveRows) + { + case 1: + effectiveRows = 1; + break; + case 2: + effectiveRows = 2; + break; + case 3: /* fall through */ + case 4: + effectiveRows = 4; + break; + case 5: /* fall through */ + case 6: /* fall through */ + case 7: /* fall through */ + case 8: + effectiveRows = 8; + break; + default: + { + /* invalid number of FIR taps */ + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_TXFIR_INV_NUMROWS, + getMykonosErrorMessage(MYKONOS_ERR_TXFIR_INV_NUMROWS)); + return MYKONOS_ERR_TXFIR_INV_NUMROWS; + } + } + + dpClk_kHz = (device->tx->txProfile->iqRate_kHz * device->tx->txProfile->txInputHbInterpolation * device->tx->txProfile->txFirInterpolation * effectiveRows); + + /* FIR DPCLK can only run at max of 500MHz */ + if (dpClk_kHz > 500000) + { + /* Max number of Tx PFIR taps exceeded for Tx Profile */ + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_TXFIR_TAPSEXCEEDED, + getMykonosErrorMessage(MYKONOS_ERR_TXFIR_TAPSEXCEEDED)); + return MYKONOS_ERR_TXFIR_TAPSEXCEEDED; + } + + /* SYNC CLOCK is the PFIR output rate / 2 */ + syncClk_kHz = device->tx->txProfile->iqRate_kHz * device->tx->txProfile->txFirInterpolation / 2; + if ((retval = MYKONOS_calculateDigitalClocks(device, NULL, &hsDigClkDiv4or5_kHz)) != MYKONOS_ERR_OK) + { + return retval; + } + + /* Select correct divider setting for SYNCCLK - must be == syncClk_kHz or slower */ + for (syncDiv = 0; syncDiv < 5; syncDiv++) + { + if ((hsDigClkDiv4or5_kHz / (uint32_t)(4 << syncDiv)) <= syncClk_kHz) + { + break; + } + } + + /* Write Tx PFIR SYNC Clock divider */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_CLOCK_CONTROL_5, syncDiv, 0x70, 4); + } + + return MYKONOS_ERR_OK; +} + +/** + * \brief Sets the digital Rx PFIR SYNC clock divider. + * + * This function is a helper function. It is called automatically in + * MYKONOS_initialize() and should not need to be called by the BBIC. + * + * This function sets the digital clock divider that is used to synchronize the + * Rx/ORx/Sniffer PFIRs each time the channels power up. The Sync clock must + * be set equal to or slower than the slowest Rx/ORx/Sniffer PFIR processing + * clock. + * + * Dependencies + * - device->spiSettings + * - device->spiSettings->chipSelectIndex + * - device->profilesValid + * - device->rx->rxProfile->rxFir + * - device->rx->rxProfile->rxFir->numFirCoefs + * - device->rx->rxProfile->iqRate_kHz + * - device->obsRx->orxProfile->rxFir + * - device->obsRx->orxProfile->rxFir->numFirCoefs + * - device->obsRx->orxProfile->iqRate_kHz + * - device->obsRx->snifferProfile->rxFir + * - device->obsRx->snifferProfile->rxFir->numFirCoefs + * - device->obsRx->snifferProfile->iqRate_kHz + * + * \param device Pointer to the Mykonos data structure + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_RXFIR_TAPSEXCEEDED ERROR: the number of Rx FIR taps exceeds the number of taps accommodated by the FIR processing clock + * \retval MYKONOS_ERR_ORXFIR_TAPSEXCEEDED ERROR: the number of ORx FIR Taps exceeds the number of taps accommodated by the FIR processing clock + * \retval MYKONOS_ERR_SNRXFIR_TAPSEXCEEDED ERROR: the number of sniffer FIR taps exceeds the number of taps accommodated by the FIR processing clock + */ +mykonosErr_t MYKONOS_setRxPfirSyncClk(mykonosDevice_t *device) +{ + uint32_t rxDpClk_kHz = 0; + uint32_t orxDpClk_kHz = 0; + uint32_t snRxDpClk_kHz = 0; + uint32_t slowestIqRate_kHz = 0; + uint32_t syncClk_kHz = 0; + uint8_t effectiveRxNumRows = 0; + uint8_t effectiveOrxNumRows = 0; + uint8_t effectiveSnrxNumRows = 0; + + uint32_t hsDigClkDiv4or5_kHz = 0; + uint8_t syncDiv = 0; + mykonosErr_t retval = MYKONOS_ERR_OK; + + /** + * Calculate Rx SYNC Clock divider for Rx PFIR. Same Rx SYNC Clock is used + * for Rx, ORx, and Sniffer PFIRs, and must be slow enough to handle the slowest + * PFIR rate. + **/ + + if (((device->profilesValid & RX_PROFILE_VALID) > 0) && (device->rx->rxProfile->rxFir != NULL)) + { + switch (device->rx->rxProfile->rxFir->numFirCoefs) + { + case 24: + effectiveRxNumRows = 1; + break; + case 48: + effectiveRxNumRows = 2; + break; + case 72: + effectiveRxNumRows = 4; + break; + default: + break; + } + + rxDpClk_kHz = device->rx->rxProfile->iqRate_kHz * effectiveRxNumRows; + + if (rxDpClk_kHz > 500000) + { + /* Max number of Rx PFIR taps exceeded for Profile */ + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RXFIR_TAPSEXCEEDED, + getMykonosErrorMessage(MYKONOS_ERR_RXFIR_TAPSEXCEEDED)); + return MYKONOS_ERR_RXFIR_TAPSEXCEEDED; + } + + slowestIqRate_kHz = device->rx->rxProfile->iqRate_kHz; + } + + if (((device->profilesValid & ORX_PROFILE_VALID) > 0) && (device->obsRx->orxProfile->rxFir != NULL)) + { + switch (device->obsRx->orxProfile->rxFir->numFirCoefs) + { + case 24: + effectiveOrxNumRows = 1; + break; + case 48: + effectiveOrxNumRows = 2; + break; + case 72: + effectiveOrxNumRows = 4; + break; + default: + break; + } + + orxDpClk_kHz = device->obsRx->orxProfile->iqRate_kHz * effectiveOrxNumRows; + + if (orxDpClk_kHz > 500000) + { + /* Max number of ORx PFIR taps exceeded for Profile */ + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_ORXFIR_TAPSEXCEEDED, + getMykonosErrorMessage(MYKONOS_ERR_ORXFIR_TAPSEXCEEDED)); + return MYKONOS_ERR_ORXFIR_TAPSEXCEEDED; + } + + if ((slowestIqRate_kHz == 0) || (slowestIqRate_kHz > device->obsRx->orxProfile->iqRate_kHz)) + { + slowestIqRate_kHz = device->obsRx->orxProfile->iqRate_kHz; + + } + } + + if (((device->profilesValid & SNIFF_PROFILE_VALID) > 0) && (device->obsRx->snifferProfile->rxFir != NULL)) + { + switch (device->obsRx->snifferProfile->rxFir->numFirCoefs) + { + case 24: + effectiveSnrxNumRows = 1; + break; + case 48: + effectiveSnrxNumRows = 2; + break; + case 72: + effectiveSnrxNumRows = 4; + break; + default: + break; + } + + snRxDpClk_kHz = device->obsRx->snifferProfile->iqRate_kHz * effectiveSnrxNumRows; + + if (snRxDpClk_kHz > 500000) + { + /* Max number of ORx PFIR taps exceeded for Profile */ + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SNRXFIR_TAPSEXCEEDED, + getMykonosErrorMessage(MYKONOS_ERR_SNRXFIR_TAPSEXCEEDED)); + return MYKONOS_ERR_SNRXFIR_TAPSEXCEEDED; + } + + if ((slowestIqRate_kHz == 0) || (slowestIqRate_kHz > device->obsRx->snifferProfile->iqRate_kHz)) + { + slowestIqRate_kHz = device->obsRx->snifferProfile->iqRate_kHz; + } + } + + /* SYNC CLOCK should be FIR output rate / 2 */ + syncClk_kHz = (slowestIqRate_kHz / 2); + if ((retval = MYKONOS_calculateDigitalClocks(device, NULL, &hsDigClkDiv4or5_kHz)) != MYKONOS_ERR_OK) + { + return retval; + } + + /* Select correct divider setting for SYNCCLK - must be == syncClk_kHz or slower */ + for (syncDiv = 0; syncDiv < 5; syncDiv++) + { + if ((hsDigClkDiv4or5_kHz / (uint32_t)(4 << syncDiv)) <= syncClk_kHz) + { + break; + } + } + + /* Write Rx PFIR SYNC Clock divider */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_CLOCK_CONTROL_5, syncDiv, 0x07, 0); + + return MYKONOS_ERR_OK; +} + +/** + * \brief Configures one or more FIR filters in the device + * + * The device stores up to 6 FIR filters (2Rx, 2Obs Rx/Sniffer, and 2Tx). + * Rx filters can have 24, 48, or 72 taps. Tx filters can have 16, 32, + * 48, 64, 80, or 96 taps. + * + * Dependencies + * - device->spiSettings + * - device->spiSettings->chipSelectIndex + * + * \param device Pointer to the Mykonos data structure + * \param filterToProgram Name of the desired filter to program + * \param firFilter Pointer to the filter to write into the device + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_PROGRAMFIR_NULL_PARM ERROR: firFilter parameter is a NULL pointer + * \retval MYKONOS_ERR_PROGRAMFIR_COEFS_NULL ERROR: firFilter->coefs is a NULL pointer + * \retval MYKONOS_ERR_PROGRAMFIR_INV_FIRNAME_PARM ERROR: Invalid FIR filter name in filterToProgram parameter + * \retval MYKONOS_ERR_PROGRAMFIR_INV_NUMTAPS_PARM ERROR: Invalid number of taps for the filter + * \retval MYKONOS_ERR_RXFIR_INV_GAIN_PARM ERROR: Rx FIR filter has invalid gain setting + * \retval MYKONOS_ERR_OBSRXFIR_INV_GAIN_PARM ERROR: OBSRX_A (ORX) FIR filter has invalid gain setting + * \retval MYKONOS_ERR_SRXFIR_INV_GAIN_PARM ERROR: OBSRX_B (Sniffer) FIR filter has invalid gain setting + * \retval MYKONOS_ERR_TXFIR_INV_GAIN_PARM ERROR: Tx FIR filter has invalid gain setting + */ +mykonosErr_t MYKONOS_programFir(mykonosDevice_t *device, mykonosfirName_t filterToProgram, mykonosFir_t *firFilter) +{ + uint8_t filterSelect = 0; + uint8_t i = 0; + uint8_t numTapsReg = 0; + uint8_t numTapMultiple = 24; /* Rx=24, Tx=16 */ + uint8_t maxNumTaps = 72; /* Rx=72, Tx=96 */ + uint8_t filterGain = 0; + +#if MYK_ENABLE_SPIWRITEARRAY == 1 + uint32_t addrIndex = 0; + uint32_t dataIndex = 0; + uint32_t spiBufferSize = ((MYK_SPIWRITEARRAY_BUFFERSIZE / 6) * 6); /* Make buffer size a multiple of 6 */ + uint16_t addrArray[MYK_SPIWRITEARRAY_BUFFERSIZE] = {0}; + uint8_t dataArray[MYK_SPIWRITEARRAY_BUFFERSIZE] = {0}; +#endif + + const uint8_t COEF_WRITE_EN = 0x40; + const uint8_t PROGRAM_CLK_EN = 0x80; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_programFir()\n"); +#endif + + if (firFilter == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_PROGRAMFIR_NULL_PARM, + getMykonosErrorMessage(MYKONOS_ERR_PROGRAMFIR_NULL_PARM)); + return MYKONOS_ERR_PROGRAMFIR_NULL_PARM; + } + + if (firFilter->coefs == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_PROGRAMFIR_COEFS_NULL, + getMykonosErrorMessage(MYKONOS_ERR_PROGRAMFIR_COEFS_NULL)); + return MYKONOS_ERR_PROGRAMFIR_COEFS_NULL; + } + + switch (filterToProgram) + { + case TX1_FIR: + filterSelect = 0x01; + numTapMultiple = 16; + maxNumTaps = 96; + break; + case TX2_FIR: + filterSelect = 0x02; + numTapMultiple = 16; + maxNumTaps = 96; + break; + case TX1TX2_FIR: + filterSelect = 0x03; + numTapMultiple = 16; + maxNumTaps = 96; + break; + case RX1_FIR: + filterSelect = 0x04; + numTapMultiple = 24; + maxNumTaps = 72; + break; + case RX2_FIR: + filterSelect = 0x08; + numTapMultiple = 24; + maxNumTaps = 72; + break; + case RX1RX2_FIR: + filterSelect = 0x0C; + numTapMultiple = 24; + maxNumTaps = 72; + break; + case OBSRX_A_FIR: + filterSelect = 0x10; + numTapMultiple = 24; + maxNumTaps = 72; + break; + case OBSRX_B_FIR: + filterSelect = 0x20; + numTapMultiple = 24; + maxNumTaps = 72; + break; + default: + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_PROGRAMFIR_INV_FIRNAME_PARM, + getMykonosErrorMessage(MYKONOS_ERR_PROGRAMFIR_INV_FIRNAME_PARM)); + return MYKONOS_ERR_PROGRAMFIR_INV_FIRNAME_PARM; + } + + /* Calculate register value for number of Taps */ + if ((firFilter->numFirCoefs % numTapMultiple == 0) && (firFilter->numFirCoefs > 0) && (firFilter->numFirCoefs <= maxNumTaps)) + { + numTapsReg = (firFilter->numFirCoefs / numTapMultiple) - 1; + } + else + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_PROGRAMFIR_INV_NUMTAPS_PARM, + getMykonosErrorMessage(MYKONOS_ERR_PROGRAMFIR_INV_NUMTAPS_PARM)); + return MYKONOS_ERR_PROGRAMFIR_INV_NUMTAPS_PARM; + } + + /* Select which FIR filter to program coeffs for */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PFIR_COEFF_CTL, (PROGRAM_CLK_EN | filterSelect)); //select filter and enable the programming clock + +#if (MYK_ENABLE_SPIWRITEARRAY == 0) + + /* write filter coefficients */ + for (i = 0; i < firFilter->numFirCoefs; i++) + { + /* Write Low byte of 16bit coefficient */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PFIR_COEFF_ADDR, (i * 2)); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PFIR_COEFF_DATA, (firFilter->coefs[i] & 0xFF)); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PFIR_COEFF_CTL, (PROGRAM_CLK_EN | COEF_WRITE_EN | filterSelect)); /* write enable (self clearing) */ + + /* Write High Byte of 16bit coefficient */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PFIR_COEFF_ADDR, ((i * 2) + 1)); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PFIR_COEFF_DATA, ((firFilter->coefs[i] >> 8) & 0xFF)); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PFIR_COEFF_CTL, (PROGRAM_CLK_EN | COEF_WRITE_EN | filterSelect));/* write enable (self clearing) */ + } + +#elif (MYK_ENABLE_SPIWRITEARRAY == 1) + + addrIndex = 0; + dataIndex = 0; + for (i = 0; i < firFilter->numFirCoefs; i++) + { + addrArray[addrIndex++] = MYKONOS_ADDR_PFIR_COEFF_ADDR; + addrArray[addrIndex++] = MYKONOS_ADDR_PFIR_COEFF_DATA; + addrArray[addrIndex++] = MYKONOS_ADDR_PFIR_COEFF_CTL; + addrArray[addrIndex++] = MYKONOS_ADDR_PFIR_COEFF_ADDR; + addrArray[addrIndex++] = MYKONOS_ADDR_PFIR_COEFF_DATA; + addrArray[addrIndex++] = MYKONOS_ADDR_PFIR_COEFF_CTL; + + dataArray[dataIndex++] = (uint8_t)(i * 2); + dataArray[dataIndex++] = (firFilter->coefs[i] & 0xFF); + dataArray[dataIndex++] = (PROGRAM_CLK_EN | COEF_WRITE_EN | filterSelect); + dataArray[dataIndex++] = (uint8_t)((i * 2) + 1); + dataArray[dataIndex++] = (((uint16_t)firFilter->coefs[i] >> 8) & 0xFF); + dataArray[dataIndex++] = (PROGRAM_CLK_EN | COEF_WRITE_EN | filterSelect); + + /* Send full buffer size when possible */ + /* spiBufferSize set to multiple of 6 at top of function */ + if (addrIndex >= spiBufferSize) + { + CMB_SPIWriteBytes(device->spiSettings, &addrArray[0], &dataArray[0], addrIndex); + dataIndex = 0; + addrIndex = 0; + } + } + + if (addrIndex > 0) + { + CMB_SPIWriteBytes(device->spiSettings, &addrArray[0], &dataArray[0], addrIndex); + } + +#endif + + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PFIR_COEFF_CTL, filterSelect); /* clear Program clock enable */ + /* write filter gain and #taps */ + if (filterToProgram == RX1_FIR || filterToProgram == RX2_FIR || filterToProgram == RX1RX2_FIR) + { + /* Write Rx FIR #taps */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_RX_FILTER_CONFIGURATION, numTapsReg, 0x60, 5); + + /* Set Rx filter gain */ + switch (firFilter->gain_dB) + { + case -12: + filterGain = 0x00; + break; + case -6: + filterGain = 0x01; + break; + case 0: + filterGain = 0x02; + break; + case 6: + filterGain = 0x03; + break; + default: + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RXFIR_INV_GAIN_PARM, + getMykonosErrorMessage(MYKONOS_ERR_RXFIR_INV_GAIN_PARM)); + return MYKONOS_ERR_RXFIR_INV_GAIN_PARM; + } + + /* Write Rx filter gain */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_RX_FILTER_GAIN, filterGain, 0x03, 0); + } + else if (filterToProgram == OBSRX_A_FIR) + { + /* Write Obs Rx FIR A #taps */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_RX_FILTER_CONFIGURATION, numTapsReg, 0x06, 1); + + /* Set Rx filter gain */ + switch (firFilter->gain_dB) + { + case -12: + filterGain = 0x00; + break; + case -6: + filterGain = 0x01; + break; + case 0: + filterGain = 0x02; + break; + case 6: + filterGain = 0x03; + break; + default: + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OBSRXFIR_INV_GAIN_PARM, + getMykonosErrorMessage(MYKONOS_ERR_OBSRXFIR_INV_GAIN_PARM)); + return MYKONOS_ERR_OBSRXFIR_INV_GAIN_PARM; + } + + /* Write Obs Rx filter gain */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_DPD_SNIFFER_RX_FILTER_GAIN, filterGain, 0x03, 0); + } + else if (filterToProgram == OBSRX_B_FIR) + { + /* Write Obs Rx FIR B #taps */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_RX_FILTER_CONFIGURATION, numTapsReg, 0x18, 3); + + /* Set Rx filter gain */ + switch (firFilter->gain_dB) + { + case -12: + filterGain = 0x00; + break; + case -6: + filterGain = 0x01; + break; + case 0: + filterGain = 0x02; + break; + case 6: + filterGain = 0x03; + break; + default: + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SRXFIR_INV_GAIN_PARM, + getMykonosErrorMessage(MYKONOS_ERR_SRXFIR_INV_GAIN_PARM)); + return MYKONOS_ERR_SRXFIR_INV_GAIN_PARM; + } + + /* Write Obs Rx filter gain */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_DPD_SNIFFER_RX_FILTER_GAIN, filterGain, 0x60, 5); + } + else if (filterToProgram == TX1_FIR || filterToProgram == TX2_FIR || filterToProgram == TX1TX2_FIR) + { + /* Write number of Taps */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_TX_FILTER_CONFIGURATION, numTapsReg, 0xE0, 5); + + switch (firFilter->gain_dB) + { + case 0: + filterGain = 0; + break; + case 6: + filterGain = 1; + break; + default: + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_TXFIR_INV_GAIN_PARM, + getMykonosErrorMessage(MYKONOS_ERR_TXFIR_INV_GAIN_PARM)); + return MYKONOS_ERR_TXFIR_INV_GAIN_PARM; + } + + /* Write Tx Filter gain */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_TX_FILTER_CONFIGURATION, filterGain, 0x01, 0); + + } + + return MYKONOS_ERR_OK; +} + +/** + * \brief Reads the FIR filter programmed into the device + * + * The device stores up to 6 FIR filters (2Rx, 2Obs Rx/Sniffer, and 2Tx). + * Rx filters can have 24, 48, or 72 taps. Tx filters can have 16, 32, + * 48, 64, 80, or 96 taps. + * + * Dependencies + * - device->spiSettings + * - device->spiSettings->chipSelectIndex + * + * \param device Pointer to the Mykonos data structure + * \param filterToRead Name of the desired filter to be read + * \param firFilter Pointer to the filter to be read from the device + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_READFIR_NULL_PARM ERROR: firFilter parameter is a NULL pointer + * \retval MYKONOS_ERR_READFIR_COEFS_NULL ERROR: firFilter->coefs is a NULL pointer + * \retval MYKONOS_ERR_READFIR_INV_FIRNAME_PARM ERROR: Invalid FIR filter name in filterToRead parameter + * \retval MYKONOS_ERR_READFIR_INV_NUMTAPS_PARM ERROR: Invalid number of taps for the filter + * \retval MYKONOS_ERR_RXFIR_INV_GAIN_PARM ERROR: Rx FIR filter has invalid gain setting + * \retval MYKONOS_ERR_OBSRXFIR_INV_GAIN_PARM ERROR: OBSRX_A (ORX) FIR filter has invalid gain setting + * \retval MYKONOS_ERR_SRXFIR_INV_GAIN_PARM ERROR: OBSRX_B (Sniffer) FIR filter has invalid gain setting + * \retval MYKONOS_ERR_TXFIR_INV_GAIN_PARM ERROR: Tx FIR filter has invalid gain setting + */ +mykonosErr_t MYKONOS_readFir(mykonosDevice_t *device, mykonosfirName_t filterToRead, mykonosFir_t *firFilter) +{ + uint8_t filterSelect = 0; + uint8_t i = 0; + uint8_t numTapsReg = 0; + uint8_t numTapMultiple = 24; + uint8_t maxNumTaps = 72; + uint8_t filterGain = 0; + uint8_t msbRead = 0; + uint8_t lsbRead = 0; + + const uint8_t PROGRAM_CLK_EN = 0x80; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_readFir()\n"); +#endif + + if (firFilter == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_READFIR_NULL_PARM, getMykonosErrorMessage(MYKONOS_ERR_READFIR_NULL_PARM)); + return MYKONOS_ERR_READFIR_NULL_PARM; + } + + if (firFilter->coefs == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_READFIR_COEFS_NULL, getMykonosErrorMessage(MYKONOS_ERR_READFIR_COEFS_NULL)); + return MYKONOS_ERR_READFIR_COEFS_NULL; + } + + switch (filterToRead) + { + case TX1_FIR: + filterSelect = 0x01; + numTapMultiple = 16; + maxNumTaps = 96; + break; + case TX2_FIR: + filterSelect = 0x02; + numTapMultiple = 16; + maxNumTaps = 96; + break; + case TX1TX2_FIR: + filterSelect = 0x03; + numTapMultiple = 16; + maxNumTaps = 96; + break; + case RX1_FIR: + filterSelect = 0x04; + numTapMultiple = 24; + maxNumTaps = 72; + break; + case RX2_FIR: + filterSelect = 0x08; + numTapMultiple = 24; + maxNumTaps = 72; + break; + case RX1RX2_FIR: + filterSelect = 0x0C; + numTapMultiple = 24; + maxNumTaps = 72; + break; + case OBSRX_A_FIR: + filterSelect = 0x10; + numTapMultiple = 24; + maxNumTaps = 72; + break; + case OBSRX_B_FIR: + filterSelect = 0x20; + numTapMultiple = 24; + maxNumTaps = 72; + break; + default: + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_READFIR_INV_FIRNAME_PARM, + getMykonosErrorMessage(MYKONOS_ERR_READFIR_INV_FIRNAME_PARM)); + return MYKONOS_ERR_READFIR_INV_FIRNAME_PARM; + } + + /* clear Program clock enable */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PFIR_COEFF_CTL, filterSelect); + + /* Read filter gain and #taps */ + if (filterToRead == RX1_FIR || filterToRead == RX2_FIR || filterToRead == RX1RX2_FIR) + { + /* Read Rx FIR #taps */ + CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_RX_FILTER_CONFIGURATION, &numTapsReg, 0x60, 5); + + firFilter->numFirCoefs = (uint8_t)((numTapsReg + 1) * numTapMultiple); + + /* Read Rx filter gain */ + CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_RX_FILTER_GAIN, &filterGain, 0x03, 0); + + switch (filterGain) + { + case 0x00: + firFilter->gain_dB = -12; + break; + case 0x01: + firFilter->gain_dB = -6; + break; + case 0x02: + firFilter->gain_dB = 0; + break; + case 0x03: + firFilter->gain_dB = 6; + break; + default: + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RXFIR_INV_GAIN_PARM, + getMykonosErrorMessage(MYKONOS_ERR_RXFIR_INV_GAIN_PARM)); + return MYKONOS_ERR_RXFIR_INV_GAIN_PARM; + } + } + else if (filterToRead == OBSRX_A_FIR) + { + /* Read Obs Rx FIR A #taps */ + CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_RX_FILTER_CONFIGURATION, &numTapsReg, 0x60, 1); + + firFilter->numFirCoefs = (uint8_t)((numTapsReg + 1) * numTapMultiple); + + /* Read Obs Rx FIR A gain */ + CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_DPD_SNIFFER_RX_FILTER_GAIN, &filterGain, 0x03, 0); + + switch (filterGain) + { + case 0x00: + firFilter->gain_dB = -12; + break; + case 0x01: + firFilter->gain_dB = -6; + break; + case 0x02: + firFilter->gain_dB = 0; + break; + case 0x03: + firFilter->gain_dB = 6; + break; + default: + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OBSRXFIR_INV_GAIN_PARM, + getMykonosErrorMessage(MYKONOS_ERR_OBSRXFIR_INV_GAIN_PARM)); + return MYKONOS_ERR_OBSRXFIR_INV_GAIN_PARM; + } + } + else if (filterToRead == OBSRX_B_FIR) + { + /* Read Obs Rx FIR B #taps */ + CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_RX_FILTER_CONFIGURATION, &numTapsReg, 0x18, 3); + + firFilter->numFirCoefs = (uint8_t)((numTapsReg + 1) * numTapMultiple); + + /* Read Obs Rx FIR B gain */ + CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_DPD_SNIFFER_RX_FILTER_GAIN, &filterGain, 0x60, 5); + + switch (filterGain) + { + case 0x00: + firFilter->gain_dB = -12; + break; + case 0x01: + firFilter->gain_dB = -6; + break; + case 0x02: + firFilter->gain_dB = 0; + break; + case 0x03: + firFilter->gain_dB = 6; + break; + default: + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SRXFIR_INV_GAIN_PARM, + getMykonosErrorMessage(MYKONOS_ERR_SRXFIR_INV_GAIN_PARM)); + return MYKONOS_ERR_SRXFIR_INV_GAIN_PARM; + } + } + else if (filterToRead == TX1_FIR || filterToRead == TX2_FIR || filterToRead == TX1TX2_FIR) + { + /* Read number of Taps */ + CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_TX_FILTER_CONFIGURATION, &numTapsReg, 0xE0, 5); + + firFilter->numFirCoefs = (uint8_t)((numTapsReg + 1) * numTapMultiple); + + /* Read Tx Filter gain */ + CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_TX_FILTER_CONFIGURATION, &filterGain, 0x01, 0); + + switch (filterGain) + { + case 0: + firFilter->gain_dB = 0; + break; + case 1: + firFilter->gain_dB = 6; + break; + default: + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_TXFIR_INV_GAIN_PARM, + getMykonosErrorMessage(MYKONOS_ERR_TXFIR_INV_GAIN_PARM)); + return MYKONOS_ERR_TXFIR_INV_GAIN_PARM; + } + } + + /* Select which FIR filter to read the coeffs for */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PFIR_COEFF_CTL, (PROGRAM_CLK_EN | filterSelect)); //select filter and enable the programming clock + + if (firFilter->numFirCoefs > maxNumTaps) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_READFIR_INV_NUMTAPS_PARM, + getMykonosErrorMessage(MYKONOS_ERR_READFIR_INV_NUMTAPS_PARM)); + return MYKONOS_ERR_READFIR_INV_NUMTAPS_PARM; + } + + /* write filter coefficients */ + for (i = 0; i < firFilter->numFirCoefs; i++) + { + /* Write Low byte of 16bit coefficient */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PFIR_COEFF_ADDR, (uint8_t)(i * 2)); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PFIR_COEFF_CTL, (PROGRAM_CLK_EN | filterSelect)); /* write enable (self clearing) */ + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_PFIR_COEFF_DATA, &lsbRead); + + /* Write High Byte of 16bit coefficient */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PFIR_COEFF_ADDR, (uint8_t)((i * 2) + 1)); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PFIR_COEFF_CTL, (PROGRAM_CLK_EN | filterSelect));/* write enable (self clearing) */ + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_PFIR_COEFF_DATA, &msbRead); + + firFilter->coefs[i] = (int16_t)((lsbRead & 0xFF) | ((msbRead << 8) & 0xFF00)); + } + + return MYKONOS_ERR_OK; +} + +/* + ***************************************************************************** + * Rx Data path functions + ***************************************************************************** + */ +/*! + * \brief Programs the gain table settings for either Rx1, Rx2, Rx1 + Rx2, ORx, or SnRx receiver types + * + * The gain table for a receiver type is set with the parameters passed by uint8_t gainTablePtr array. + * gainTablePtr is a 4 x n array, where there are four (4) elements per index, and the array + * length (n) is dependent upon receiver type. The (n) value is conveyed by numGainIndexesInTable. + * All gain tables have a maximum index of 255 when used with this function. The minimum gain index is + * application dependent. + * + * Where for Rx1, Rx2, and ObsRx: + * [A, B, C, D]: A = Front End Gain, B = External Control, C = Digital Attenuation/Gain, D = Attenuation/Gain select + * + * Where for SnRx: + * [A, B, C, D]: A = Front End Gain, B = LNA Bypass, C = Digital Attenuation/Gain, D = Attenuation/Gain select + * + * The gain table starting address changes with each receiver type. This function accounts for this change as well as the + * difference between byte [B] for {Rx1, Rx2, ObsRx} and SnRx receiver array values and programs the correct registers. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device Pointer to the Mykonos data structure + * \param gainTablePtr Pointer to 4 x n array containing gain table program values + * \param numGainIndexesInTable The number of 'n' indices in 4 x n array. A range check is performed to ensure the maximum is not exceeded. + * \param rxChannel mykonosGainTable_t enum type to select either Rx1, Rx2, Rx1 + Rx2, ORx, or SnRx gain table for programming. A + * channel check is performed to ensure a valid selection. + * + * \return Returns enum MYKONOS_ERR, MYKONOS_ERR_OK if successful, MYKONOS_ERR_RXGAINTABLE_INV_CHANNEL if invalid channel is selected, MYKONOS_ERR_RXGAINTABLE_INV_GAIN_INDEX_RANGE + * if numGainIndexesInTable exceeds range for selected receiver gain table + */ +mykonosErr_t MYKONOS_programRxGainTable(mykonosDevice_t *device, uint8_t *gainTablePtr, uint8_t numGainIndexesInTable, mykonosGainTable_t rxChannel) +{ + uint8_t ctlReg = 0; + uint8_t ch3CtlReg = 0; + uint16_t rxFEGainAddr = 0; + uint16_t rxExtCtlLnaAddr = 0; + uint16_t rxDigGainAttenAddr = 0; + uint16_t rx2FEGainAddr = 0; + uint16_t rx2ExtCtlAddr = 0; + uint16_t rx2DigGainAttenAddr = 0; + uint8_t minGainIndex = 0; + uint8_t startIndex = 0; + int16_t i = 0; + uint16_t tableRowIndex = 0; + uint8_t retFlag = 0; + +#if MYK_ENABLE_SPIWRITEARRAY + uint32_t addrIndex = 0; + uint32_t dataIndex = 0; + uint32_t spiBufferSize = (((MYK_SPIWRITEARRAY_BUFFERSIZE / 9) - 1) * 9); + uint16_t addrArray[MYK_SPIWRITEARRAY_BUFFERSIZE] = {0}; + uint8_t dataArray[MYK_SPIWRITEARRAY_BUFFERSIZE] = {0}; +#endif + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_programRxGainTable()\n"); +#endif + + if (gainTablePtr == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_PROGRAM_RXGAIN_TABLE_NULL_PARM, + getMykonosErrorMessage(MYKONOS_ERR_PROGRAM_RXGAIN_TABLE_NULL_PARM)); + return MYKONOS_ERR_PROGRAM_RXGAIN_TABLE_NULL_PARM; + } + + /* checking range of numGainIndexesInTable against maximums and for valid rxChannel selection */ + switch (rxChannel) + { + case RX1_GT: + /* Rx1 max gain index = 255, check is out of range of uint8_t */ + break; + case RX2_GT: + /* Rx1 max gain index = 255, check is out of range of uint8_t */ + break; + case RX1_RX2_GT: + /* Rx1 max gain index = 255, check is out of range of uint8_t */ + break; + case ORX_GT: + if (numGainIndexesInTable > MAX_ORX_GAIN_TABLE_NUMINDEXES) + { + retFlag = 1; + } + break; + case SNRX_GT: + if (numGainIndexesInTable > MAX_SNRX_GAIN_TABLE_NUMINDEXES) + { + retFlag = 1; + } + break; + case LOOPBACK_GT: + if (numGainIndexesInTable > MAX_LOOPBACK_GAIN_TABLE_NUMINDEXES) + { + retFlag = 1; + } + break; + default: + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RXGAINTABLE_INV_CHANNEL, + getMykonosErrorMessage(MYKONOS_ERR_RXGAINTABLE_INV_CHANNEL)); + return MYKONOS_ERR_RXGAINTABLE_INV_CHANNEL; + } + + if (retFlag) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RXGAINTABLE_INV_GAIN_INDEX_RANGE, + getMykonosErrorMessage(MYKONOS_ERR_RXGAINTABLE_INV_GAIN_INDEX_RANGE)); + return MYKONOS_ERR_RXGAINTABLE_INV_GAIN_INDEX_RANGE; + } + else + { + /* calculating minimum gain index value */ + minGainIndex = MAX_GAIN_TABLE_INDEX - numGainIndexesInTable + 1; + } + + /* forming control register words based on channel select, assigning starting index, and register addressing, also updating max and min gain table indices in structure */ + switch (rxChannel) + { + case RX1_GT: + ctlReg = ((uint8_t)rxChannel << 3) | 0x05; + startIndex = START_RX_GAIN_INDEX; + rxFEGainAddr = MYKONOS_ADDR_GAIN_TABLE_RX1_FE_GAIN; + rxExtCtlLnaAddr = MYKONOS_ADDR_GAIN_TABLE_RX1_EXT_CTL; + rxDigGainAttenAddr = MYKONOS_ADDR_GAIN_TABLE_RX1_DIG_GAIN; + device->rx->rxGainCtrl->rx1MaxGainIndex = MAX_GAIN_TABLE_INDEX; + device->rx->rxGainCtrl->rx1MinGainIndex = minGainIndex; + break; + case RX2_GT: + ctlReg = ((uint8_t)rxChannel << 3) | 0x05; + startIndex = START_RX_GAIN_INDEX; + rxFEGainAddr = MYKONOS_ADDR_GAIN_TABLE_RX2_FE_GAIN; + rxExtCtlLnaAddr = MYKONOS_ADDR_GAIN_TABLE_RX2_EXT_CTL; + rxDigGainAttenAddr = MYKONOS_ADDR_GAIN_TABLE_RX2_DIG_GAIN; + device->rx->rxGainCtrl->rx2MaxGainIndex = MAX_GAIN_TABLE_INDEX; + device->rx->rxGainCtrl->rx2MinGainIndex = minGainIndex; + break; + case RX1_RX2_GT: + ctlReg = ((uint8_t)rxChannel << 3) | 0x05; + startIndex = START_RX_GAIN_INDEX; + rxFEGainAddr = MYKONOS_ADDR_GAIN_TABLE_RX1_FE_GAIN; + rx2FEGainAddr = MYKONOS_ADDR_GAIN_TABLE_RX2_FE_GAIN; + rxExtCtlLnaAddr = MYKONOS_ADDR_GAIN_TABLE_RX1_EXT_CTL; + rx2ExtCtlAddr = MYKONOS_ADDR_GAIN_TABLE_RX2_EXT_CTL; + rxDigGainAttenAddr = MYKONOS_ADDR_GAIN_TABLE_RX1_DIG_GAIN; + rx2DigGainAttenAddr = MYKONOS_ADDR_GAIN_TABLE_RX2_DIG_GAIN; + device->rx->rxGainCtrl->rx1MaxGainIndex = MAX_GAIN_TABLE_INDEX; + device->rx->rxGainCtrl->rx1MinGainIndex = minGainIndex; + device->rx->rxGainCtrl->rx2MaxGainIndex = MAX_GAIN_TABLE_INDEX; + device->rx->rxGainCtrl->rx2MinGainIndex = minGainIndex; + break; + case ORX_GT: + ctlReg = 0x05; + ch3CtlReg = 0x08; + startIndex = START_ORX_GAIN_INDEX; + rxFEGainAddr = MYKONOS_ADDR_GAIN_TABLE_RX3_FE_GAIN; + rxExtCtlLnaAddr = MYKONOS_ADDR_GAIN_TABLE_RX3_LNA_ENAB; + rxDigGainAttenAddr = MYKONOS_ADDR_GAIN_TABLE_RX3_DIG_GAIN; + device->obsRx->orxGainCtrl->maxGainIndex = MAX_GAIN_TABLE_INDEX; + device->obsRx->orxGainCtrl->minGainIndex = minGainIndex; + break; + case SNRX_GT: + ctlReg = 0x05; + ch3CtlReg = 0x00; + startIndex = START_SNRX_GAIN_INDEX; + rxFEGainAddr = MYKONOS_ADDR_GAIN_TABLE_RX3_FE_GAIN; + rxExtCtlLnaAddr = MYKONOS_ADDR_GAIN_TABLE_RX3_LNA_ENAB; + rxDigGainAttenAddr = MYKONOS_ADDR_GAIN_TABLE_RX3_DIG_GAIN; + device->obsRx->snifferGainCtrl->maxGainIndex = MAX_GAIN_TABLE_INDEX; + device->obsRx->snifferGainCtrl->minGainIndex = minGainIndex; + break; + /*case LOOPBACK_GT: Loopback is only for ARM calibrations */ + default: + ctlReg = 0x05; + ch3CtlReg = 0x10; + startIndex = START_LOOPBACK_GAIN_INDEX; + rxFEGainAddr = MYKONOS_ADDR_GAIN_TABLE_RX3_FE_GAIN; + rxExtCtlLnaAddr = MYKONOS_ADDR_GAIN_TABLE_RX3_LNA_ENAB; + rxDigGainAttenAddr = MYKONOS_ADDR_GAIN_TABLE_RX3_DIG_GAIN; + break; + } + + /* starting the gain table clock and read from gain table address bits */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_GAIN_TABLE_CONFIGURATION, ctlReg); + + /* if ORx or Sniffer are selected also writing channel 3 readback bits for ObsRx or Sniffer selection */ + if (rxChannel > RX1_RX2_GT) + { + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CH3_GAIN_TABLE_CONFIGURATION, ch3CtlReg); + } + + /* programming a table selected by rxChannel enum type */ + +#if MYK_ENABLE_SPIWRITEARRAY == 0 + + for(i = startIndex; i >= ((startIndex + 1) - numGainIndexesInTable); i--) + { + tableRowIndex = (uint16_t)(startIndex - i) << 2; + + /* set current gain table index (address) */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_GAIN_TABLE_ADDR, i); + + /* Set Rx Front End gain[5:0] */ + CMB_SPIWriteByte(device->spiSettings, rxFEGainAddr, gainTablePtr[tableRowIndex]); + + /* Set external control [5:0] OR LNA bypass if rxChannel == SNRX_GT */ + if (rxChannel == SNRX_GT) + { + CMB_SPIWriteByte(device->spiSettings, rxExtCtlLnaAddr, gainTablePtr[tableRowIndex + 1] << 4); + } + else + { + CMB_SPIWriteByte(device->spiSettings, rxExtCtlLnaAddr, gainTablePtr[tableRowIndex + 1]); + } + + /* Set digital attenuation/gain[6:0] and set/clear attenuation bit */ + CMB_SPIWriteByte(device->spiSettings, rxDigGainAttenAddr, (gainTablePtr[tableRowIndex + 3] << 7) | gainTablePtr[tableRowIndex + 2]); + + /* repeating gain table settings if Rx1 and Rx2 are selected for Rx2 configuration */ + if (rxChannel == RX1_RX2_GT) + { + /* Set Rx Front End gain[5:0] */ + CMB_SPIWriteByte(device->spiSettings, rx2FEGainAddr, gainTablePtr[tableRowIndex]); + + /* Set external control [5:0] */ + CMB_SPIWriteByte(device->spiSettings, rx2ExtCtlAddr, gainTablePtr[tableRowIndex + 1]); + + /* Set digital attenuation/gain[6:0] */ + CMB_SPIWriteByte(device->spiSettings, rx2DigGainAttenAddr, (gainTablePtr[tableRowIndex + 3] << 7) | gainTablePtr[tableRowIndex + 2]); + } + + /* setting the write enable depending on rxChannel choice */ + if (rxChannel == ORX_GT) + { + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CH3_GAIN_TABLE_CONFIGURATION, ch3CtlReg | 0x02); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_GAIN_TABLE_CONFIGURATION, ctlReg | 0x02); + } + else if (rxChannel == SNRX_GT) + { + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CH3_GAIN_TABLE_CONFIGURATION, ch3CtlReg | 0x01); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_GAIN_TABLE_CONFIGURATION, ctlReg | 0x02); + } + else if (rxChannel == LOOPBACK_GT) + { + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CH3_GAIN_TABLE_CONFIGURATION, ch3CtlReg | 0x04); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_GAIN_TABLE_CONFIGURATION, ctlReg | 0x02); + } + else + { + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_GAIN_TABLE_CONFIGURATION, ctlReg | 0x02); + } + } + +#elif MYK_ENABLE_SPIWRITEARRAY == 1 +//#elif 0 + + addrIndex = 0; + dataIndex = 0; + for(i = startIndex; i >= ((startIndex + 1) - numGainIndexesInTable); i--) + { + tableRowIndex = (uint16_t)(startIndex - (uint8_t)i) << 2; + + /* set current gain table index (address) */ + addrArray[addrIndex++] = MYKONOS_ADDR_GAIN_TABLE_ADDR; + dataArray[dataIndex++] = (uint8_t)i; + + /* Set Rx Front End gain[5:0] */ + addrArray[addrIndex++] = rxFEGainAddr; + dataArray[dataIndex++] = gainTablePtr[tableRowIndex]; + + /* Set external control [5:0] OR LNA bypass if rxChannel == SNRX_GT */ + addrArray[addrIndex++] = rxExtCtlLnaAddr; + dataArray[dataIndex++] = (rxChannel == SNRX_GT) ? (uint8_t)(gainTablePtr[tableRowIndex + 1] << 4) : (gainTablePtr[tableRowIndex + 1]); + + /* Set digital attenuation/gain[6:0] and set/clear attenuation bit */ + addrArray[addrIndex++] = rxDigGainAttenAddr; + dataArray[dataIndex++] = ((uint8_t)(gainTablePtr[tableRowIndex + 3] << 7) | gainTablePtr[tableRowIndex + 2]); + + /* repeating gain table settings if Rx1 and Rx2 are selected for Rx2 configuration */ + if (rxChannel == RX1_RX2_GT) + { + /* Set Rx Front End gain[5:0] */ + addrArray[addrIndex++] = rx2FEGainAddr; + dataArray[dataIndex++] = gainTablePtr[tableRowIndex]; + + /* Set external control [5:0] */ + addrArray[addrIndex++] = rx2ExtCtlAddr; + dataArray[dataIndex++] = gainTablePtr[tableRowIndex + 1]; + + /* Set digital attenuation/gain[6:0] */ + addrArray[addrIndex++] = rx2DigGainAttenAddr; + dataArray[dataIndex++] = ((uint8_t)(gainTablePtr[tableRowIndex + 3] << 7) | gainTablePtr[tableRowIndex + 2]); + } + + /* setting the write enable depending on rxChannel choice */ + if (rxChannel == ORX_GT) + { + addrArray[addrIndex++] = MYKONOS_ADDR_CH3_GAIN_TABLE_CONFIGURATION; + dataArray[dataIndex++] = (ch3CtlReg | 0x02); + addrArray[addrIndex++] = MYKONOS_ADDR_GAIN_TABLE_CONFIGURATION; + dataArray[dataIndex++] = (ctlReg | 0x02); + } + else if (rxChannel == SNRX_GT) + { + addrArray[addrIndex++] = MYKONOS_ADDR_CH3_GAIN_TABLE_CONFIGURATION; + dataArray[dataIndex++] = (ch3CtlReg | 0x01); + addrArray[addrIndex++] = MYKONOS_ADDR_GAIN_TABLE_CONFIGURATION; + dataArray[dataIndex++] = (ctlReg | 0x02); + } + else if (rxChannel == LOOPBACK_GT) + { + addrArray[addrIndex++] = MYKONOS_ADDR_CH3_GAIN_TABLE_CONFIGURATION; + dataArray[dataIndex++] = (ch3CtlReg | 0x04); + addrArray[addrIndex++] = MYKONOS_ADDR_GAIN_TABLE_CONFIGURATION; + dataArray[dataIndex++] = (ctlReg | 0x02); + } + else + { + addrArray[addrIndex++] = MYKONOS_ADDR_GAIN_TABLE_CONFIGURATION; + dataArray[dataIndex++] = (ctlReg | 0x02); + } + + if (addrIndex >= spiBufferSize) + { + CMB_SPIWriteBytes(device->spiSettings, &addrArray[0], &dataArray[0], addrIndex); + dataIndex = 0; + addrIndex = 0; + } + } + + if (addrIndex > 0) + { + CMB_SPIWriteBytes(device->spiSettings, &addrArray[0], &dataArray[0], addrIndex); + } + +#endif + + /* clearing the channel 3 gain table configuration register if selected and stopping the gain table clock */ + if (rxChannel > RX1_RX2_GT) + { + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CH3_GAIN_TABLE_CONFIGURATION, 0x00); + } + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_GAIN_TABLE_CONFIGURATION, 0x08); + + return MYKONOS_ERR_OK; +} + +/** + * \brief Sets the Rx1 Manual Gain Index + * + * If the value passed in the gainIndex parameter is within range of the gain table minimum and + * maximum indexes, the Rx1 gain index will be updated in the device data structure + * and written to the transceiver. Else, an error will be returned. The maximum index is 255 + * and the minimum index is application specific. + * + * Dependencies + * - device->spiSettings + * - device->rxSettings->rxGainControl->rx1GainIndex + * - device->rxSettings->rxGainControl->rx1MaxGainIndex + * - device->rxSettings->rxGainControl->rx1MinGainIndex + * + * \param device Pointer to the Mykonos data structure + * \param gainIndex Desired Rx1 gain index + * + * \return Returns enum MYKONOS_ERR, MYKONOS_ERR_OK=pass, !MYKONOS_ERR_OK=fail + */ +mykonosErr_t MYKONOS_setRx1ManualGain(mykonosDevice_t *device, uint8_t gainIndex) +{ + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setRx1ManualGain()\n"); +#endif + + if ((gainIndex < device->rx->rxGainCtrl->rx1MinGainIndex) || (gainIndex > device->rx->rxGainCtrl->rx1MaxGainIndex)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETRX1GAIN_INV_GAIN_PARM, + getMykonosErrorMessage(MYKONOS_ERR_SETRX1GAIN_INV_GAIN_PARM)); + return MYKONOS_ERR_SETRX1GAIN_INV_GAIN_PARM; + + } + else + { + /* If the desired gain index is in range of the gain table, update the + * value in the device data structure, and write to device. + */ + device->rx->rxGainCtrl->rx1GainIndex = gainIndex; + + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_MANUAL_GAIN_INDEX_CH_1, gainIndex); + + return MYKONOS_ERR_OK; + } +} + +/** + * \brief Sets the Rx2 Manual Gain index + * + * If the value passed in the gainIndex parameter is within range of the gain table minimum and + * maximum indexes, the Rx2 gain index will be updated in the device data structure + * and written to the transceiver. Else, an error will be returned. The maximum index is 255 + * and the minimum index is application specific. + * + * Dependencies + * - device->spiSettings + * - device->rxTxSettings->rxGainControl->rx2GainIndex + * - device->rxTxSettings->rxGainControl->rx2MaxGainIndex + * - device->rxTxSettings->rxGainControl->rx2MinGainIndex + * + * \param device Pointer to the Mykonos data structure + * \param gainIndex Desired Rx2 gain index + * + * \return Returns enum MYKONOS_ERR, MYKONOS_ERR_OK=pass, !MYKONOS_ERR_OK=fail + */ +mykonosErr_t MYKONOS_setRx2ManualGain(mykonosDevice_t *device, uint8_t gainIndex) +{ + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setRx2ManualGain()\n"); +#endif + + if ((gainIndex < device->rx->rxGainCtrl->rx2MinGainIndex) || (gainIndex > device->rx->rxGainCtrl->rx2MaxGainIndex)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETRX2GAIN_INV_GAIN_PARM, + getMykonosErrorMessage(MYKONOS_ERR_SETRX2GAIN_INV_GAIN_PARM)); + return MYKONOS_ERR_SETRX2GAIN_INV_GAIN_PARM; + + } + else + { + /* If the desired gain index is in range of the gain table, update the + * value in the device data structure, and write to device. + */ + device->rx->rxGainCtrl->rx2GainIndex = gainIndex; + + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_MANUAL_GAIN_INDEX_CH_2, gainIndex); + + return MYKONOS_ERR_OK; + } +} + +/** + * \brief Reads the Rx1 Gain Index for Manual or AGC gain control mode + * + * This function reads the Rx1 gain index for manual or AGC modes. If the + * *rx1GainIndex pointer is nonzero, the read back gain index will + * be returned in the parameter. If the *rx1GainIndex pointer + * is NULL, the device data structure will be updated with the new read back value + * + * Dependencies + * - device->spiSettings + * - device->rxTxSettings->rxGainControl->rx1GainIndex + * + * \param device Pointer to the Mykonos data structure + * \param rx1GainIndex uint8_t Pointer to the Rx1 gain index value + * + * \return Returns enum MYKONOS_ERR, MYKONOS_ERR_OK=pass, !MYKONOS_ERR_OK=fail + */ +mykonosErr_t MYKONOS_getRx1Gain(mykonosDevice_t *device, uint8_t *rx1GainIndex) +{ + uint8_t readData = 0; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getRx1Gain()\n"); +#endif + + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_GAIN_CTL_CHANNEL_1, &readData); + + /* + * If rx1GainIndex address is not NULL, return the Rx1 gain index in the + * rx1GainIndex function parameter + */ + if (rx1GainIndex != NULL) + { + *rx1GainIndex = readData; + } + + /* + * set the current Rx1 gain in the device data structure + */ + if (device->profilesValid & RX_PROFILE_VALID) + { + device->rx->rxGainCtrl->rx1GainIndex = readData; + } + + return MYKONOS_ERR_OK; +} + +/** + * \brief Reads the Rx2 Gain Index for Manual or AGC gain control mode + * + * This function reads the Rx2 gain index for manual or AGC modes. If the + * *rx1GainIndex pointer is nonzero, the read back gain index will + * be returned in the parameter. If the *rx1GainIndex pointer + * is NULL, the device data structure will be updated with the new read back value + * + * Dependencies + * - device->spiSettings + * - device->rxTxSettings->rxGainControl->rx2GainIndex + * + * \param device Pointer to the Mykonos data structure + * \param rx2GainIndex Desired Rx2 gain index + * + * \return Returns enum MYKONOS_ERR, MYKONOS_ERR_OK=pass, !MYKONOS_ERR_OK=fail + */ +mykonosErr_t MYKONOS_getRx2Gain(mykonosDevice_t *device, uint8_t *rx2GainIndex) +{ + uint8_t readData = 0; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getRx2Gain()\n"); +#endif + + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_GAIN_CTL_CHANNEL_2, &readData); + + /* + * If rx1GainIndex address is not NULL, return the Rx1 gain index in the + * rx1GainIndex function parameter + */ + if (rx2GainIndex != NULL) + { + *rx2GainIndex = readData; + } + + /* + * set the current Rx2 gain in the device data structure + */ + if (device->profilesValid & RX_PROFILE_VALID) + { + device->rx->rxGainCtrl->rx2GainIndex = readData; + } + + return MYKONOS_ERR_OK; +} + +/** + * \brief Sets up the device Rx Automatic Gain Control (AGC) registers. + * + * Three data structures (mykonosAgcCfg_t, mykonosPeakDetAgcCfg_t, mykonosPowerMeasAgcCfg_t) + * must be instantiated prior to calling this function. Valid ranges for data structure members + * must also be provided. + * + * + * Dependencies: + * - device->spiSettings + * - device->spiSettings->chipSelectIndex + * - device->rx->rxAgcCtrl->agcRx1MaxGainIndex + * - device->rx->rxAgcCtrl->agcRx1MinGainIndex + * - device->rx->rxAgcCtrl->agcRx2MaxGainIndex + * - device->rx->rxAgcCtrl->agcRx2MinGainIndex + * - device->rx->rxAgcCtrl->agcObsRxMaxGainIndex + * - device->rx->rxAgcCtrl->agcObsRxMinGainIndex + * - device->rx->rxAgcCtrl->agcObsRxSelect + * - device->rx->rxAgcCtrl->agcPeakThresholdMode + * - device->rx->rxAgcCtrl->agcLowThsPreventGainIncrease + * - device->rx->rxAgcCtrl->agcGainUpdateCounter + * - device->rx->rxAgcCtrl->agcSlowLoopSettlingDelay + * - device->rx->rxAgcCtrl->agcPeakWaitTime + * - device->rx->rxAgcCtrl->agcResetOnRxEnable + * - device->rx->rxAgcCtrl->agcEnableSyncPulseForGainCounter + * - device->rx->rxAgcCtrl->peakAgc->apdHighThresh + * - device->rx->rxAgcCtrl->peakAgc->apdLowThresh + * - device->rx->rxAgcCtrl->peakAgc->hb2HighThresh + * - device->rx->rxAgcCtrl->peakAgc->hb2LowThresh + * - device->rx->rxAgcCtrl->peakAgc->hb2VeryLowThresh + * - device->rx->rxAgcCtrl->peakAgc->apdHighThreshExceededCnt + * - device->rx->rxAgcCtrl->peakAgc->apdLowThreshExceededCnt + * - device->rx->rxAgcCtrl->peakAgc->hb2HighThreshExceededCnt + * - device->rx->rxAgcCtrl->peakAgc->hb2LowThreshExceededCnt + * - device->rx->rxAgcCtrl->peakAgc->hb2VeryLowThreshExceededCnt + * - device->rx->rxAgcCtrl->peakAgc->apdHighGainStepAttack + * - device->rx->rxAgcCtrl->peakAgc->apdLowGainStepRecovery + * - device->rx->rxAgcCtrl->peakAgc->hb2HighGainStepAttack + * - device->rx->rxAgcCtrl->peakAgc->hb2LowGainStepRecovery + * - device->rx->rxAgcCtrl->peakAgc->hb2VeryLowGainStepRecovery + * - device->rx->rxAgcCtrl->peakAgc->apdFastAttack + * - device->rx->rxAgcCtrl->peakAgc->hb2FastAttack + * - device->rx->rxAgcCtrl->peakAgc->hb2OverloadDetectEnable + * - device->rx->rxAgcCtrl->peakAgc->hb2OverloadDurationCnt + * - device->rx->rxAgcCtrl->peakAgc->hb2OverloadThreshCnt + * - device->rx->rxAgcCtrl->powerAgc->pmdUpperHighThresh + * - device->rx->rxAgcCtrl->powerAgc->pmdUpperLowThresh + * - device->rx->rxAgcCtrl->powerAgc->pmdLowerHighThresh + * - device->rx->rxAgcCtrl->powerAgc->pmdLowerLowThresh + * - device->rx->rxAgcCtrl->powerAgc->pmdUpperHighGainStepAttack + * - device->rx->rxAgcCtrl->powerAgc->pmdUpperLowGainStepAttack + * - device->rx->rxAgcCtrl->powerAgc->pmdLowerHighGainStepRecovery + * - device->rx->rxAgcCtrl->powerAgc->pmdLowerLowGainStepRecovery + * - device->rx->rxAgcCtrl->powerAgc->pmdMeasDuration + * - device->rx->rxAgcCtrl->powerAgc->pmdMeasConfig + * + * \param device is structure pointer to the Mykonos data structure containing settings + * The pointer to the Mykonos AGC data structure containing settings is checked for a null pointer + * to ensure it has been initialized. If not an error is thrown. + * + * \retval Returns MYKONOS_ERR=pass, !MYKONOS_ERR=fail + * \retval MYKONOS_ERR_INV_AGC_RX_STRUCT_INIT + * \retval MYKONOS_ERR_INV_AGC_RX_PEAK_STRUCT_INIT + * \retval MYKONOS_ERR_INV_AGC_RX_PWR_STRUCT_INIT + * \retval MYKONOS_ERR_INV_AGC_RX1_MAX_GAIN_INDEX + * \retval MYKONOS_ERR_INV_AGC_RX1_MIN_GAIN_INDEX + * \retval MYKONOS_ERR_INV_AGC_RX2_MAX_GAIN_INDEX + * \retval MYKONOS_ERR_INV_AGC_RX2_MIN_GAIN_INDEX + * \retval MYKONOS_ERR_INV_AGC_RX_GAIN_UPDATE_TIME_PARM + * \retval MYKONOS_ERR_INV_AGC_RX_PEAK_WAIT_TIME_PARM + * \retval MYKONOS_ERR_INV_AGC_RX_SLOW_LOOP_SETTLING_DELAY + * \retval MYKONOS_ERR_INV_AGC_PMD_MEAS_DURATION + * \retval MYKONOS_ERR_INV_AGC_PMD_MEAS_CONFIG + * \retval MYKONOS_ERR_INV_AGC_RX_LOW_THS_PREV_GAIN_INC + * \retval MYKONOS_ERR_INV_AGC_RX_PEAK_THRESH_MODE + * \retval MYKONOS_ERR_INV_AGC_RX_RESET_ON_RX_ENABLE + * \retval MYKONOS_ERR_INV_AGC_RX_ENABLE_SYNC_PULSE_GAIN_COUNTER + * \retval MYKONOS_ERR_INV_AGC_RX_PMD_LOWER_HIGH_THRESH + * \retval MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_LOW_THRESH + * \retval MYKONOS_ERR_INV_AGC_RX_PMD_LOWER_LOW_THRESH + * \retval MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_HIGH_THRESH + * \retval MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_HIGH_GAIN_STEP + * \retval MYKONOS_ERR_INV_AGC_RX_PMD_LOWER_LOW_GAIN_STEP + * \retval MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_LOW_GAIN_STEP + * \retval MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_LOW_GAIN_STEP + * \retval MYKONOS_ERR_INV_AGC_RX_PKDET_FAST_ATTACK_VALUE + * \retval MYKONOS_ERR_INV_AGC_RX_APD_HIGH_THRESH_PARM + * \retval MYKONOS_ERR_INV_AGC_RX_APD_LOW_THRESH_PARM + * \retval MYKONOS_ERR_INV_AGC_RX_HB2_HIGH_THRESH_PARM + * \retval MYKONOS_ERR_INV_AGC_RX_HB2_LOW_THRESH_PARM + * \retval MYKONOS_ERR_INV_AGC_RX_HB2_VERY_LOW_THRESH_PARM + * \retval MYKONOS_ERR_INV_AGC_RX_APD_HIGH_GAIN_STEP_PARM + * \retval MYKONOS_ERR_INV_AGC_RX_APD_LOW_GAIN_STEP_PARM + * \retval MYKONOS_ERR_INV_AGC_RX_HB2_HIGH_GAIN_STEP_PARM + * \retval MYKONOS_ERR_INV_AGC_RX_HB2_LOW_GAIN_STEP_PARM + * \retval MYKONOS_ERR_INV_AGC_RX_HB2_VERY_LOW_GAIN_STEP_PARM + * \retval MYKONOS_ERR_INV_AGC_RX_HB2_OVLD_ENABLE + * \retval MYKONOS_ERR_INV_AGC_RX_HB2_OVLD_DUR_CNT + * \retval MYKONOS_ERR_INV_AGC_RX_HB2_OVLD_THRESH_CNT + */ +mykonosErr_t MYKONOS_setupRxAgc(mykonosDevice_t *device) +{ + uint8_t decPowerConfig = 0; + uint8_t lower1ThreshGainStepRegValue = 0; + uint8_t powerThresholdsRegValue = 0; + uint8_t hb2OvldCfgRegValue = 0; + uint8_t agcGainUpdateCtr[3] = {0}; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setRxAgc()\n"); +#endif + + /* Check mykonosAgcCfg_t device->rx->rxAgcCtrl pointer for initialization */ + if (device->rx->rxAgcCtrl == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_STRUCT_INIT, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_STRUCT_INIT)); + return MYKONOS_ERR_INV_AGC_RX_STRUCT_INIT; + } + + /* Check mykonosPeakDetAgcCfg_t device->rx->rxAgcCtrl->peakAgc pointer for initialization */ + if (device->rx->rxAgcCtrl->peakAgc == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_PEAK_STRUCT_INIT, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_PEAK_STRUCT_INIT)); + return MYKONOS_ERR_INV_AGC_RX_PEAK_STRUCT_INIT; + } + + /* Check mykonosPowerMeasAgcCfg_t device->rx->rxAgcCtrl->powerAgc pointer for initialization */ + if (device->rx->rxAgcCtrl->powerAgc == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_PWR_STRUCT_INIT, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_PWR_STRUCT_INIT)); + return MYKONOS_ERR_INV_AGC_RX_PWR_STRUCT_INIT; + } + + /* Range check agcRx1MaxGainIndex versus gain table limits */ + if ((device->rx->rxAgcCtrl->agcRx1MaxGainIndex > device->rx->rxGainCtrl->rx1MaxGainIndex) + || (device->rx->rxAgcCtrl->agcRx1MaxGainIndex < device->rx->rxAgcCtrl->agcRx1MinGainIndex)) + + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX1_MAX_GAIN_INDEX, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX1_MAX_GAIN_INDEX)); + return MYKONOS_ERR_INV_AGC_RX1_MAX_GAIN_INDEX; + } + else + { + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_RX1_MAX_GAIN_INDEX, device->rx->rxAgcCtrl->agcRx1MaxGainIndex); + } + + /* Range check agcRx1MinGainIndex versus gain table limits */ + if ((device->rx->rxAgcCtrl->agcRx1MinGainIndex < device->rx->rxGainCtrl->rx1MinGainIndex) + || (device->rx->rxAgcCtrl->agcRx1MaxGainIndex < device->rx->rxAgcCtrl->agcRx1MinGainIndex)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX1_MIN_GAIN_INDEX, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX1_MIN_GAIN_INDEX)); + return MYKONOS_ERR_INV_AGC_RX1_MIN_GAIN_INDEX; + } + else + { + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_RX1_MIN_GAIN_INDEX, device->rx->rxAgcCtrl->agcRx1MinGainIndex); + } + + /* Range check agcRx2MaxGainIndex versus gain table limits */ + if ((device->rx->rxAgcCtrl->agcRx2MaxGainIndex > device->rx->rxGainCtrl->rx2MaxGainIndex) + || (device->rx->rxAgcCtrl->agcRx2MaxGainIndex < device->rx->rxAgcCtrl->agcRx2MinGainIndex)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX2_MAX_GAIN_INDEX, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX2_MAX_GAIN_INDEX)); + return MYKONOS_ERR_INV_AGC_RX2_MAX_GAIN_INDEX; + } + else + { + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_RX2_MAX_GAIN_INDEX, device->rx->rxAgcCtrl->agcRx2MaxGainIndex); + } + + /* Range check agcRx2MinGainIndex versus gain table limits */ + if ((device->rx->rxAgcCtrl->agcRx2MinGainIndex < device->rx->rxGainCtrl->rx2MinGainIndex) + || (device->rx->rxAgcCtrl->agcRx2MaxGainIndex < device->rx->rxAgcCtrl->agcRx2MinGainIndex)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX2_MIN_GAIN_INDEX, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX2_MIN_GAIN_INDEX)); + return MYKONOS_ERR_INV_AGC_RX2_MIN_GAIN_INDEX; + } + else + { + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_RX2_MIN_GAIN_INDEX, device->rx->rxAgcCtrl->agcRx2MinGainIndex); + } + + /* Range check for agcGainUpdateCounter (22-bit) */ + if ((device->rx->rxAgcCtrl->agcGainUpdateCounter > 0x3FFFFF) || (device->rx->rxAgcCtrl->agcGainUpdateCounter < 1)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_GAIN_UPDATE_TIME_PARM, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_GAIN_UPDATE_TIME_PARM)); + return MYKONOS_ERR_INV_AGC_RX_GAIN_UPDATE_TIME_PARM; + } + else + { + /* Split agcGainUpdateCounter into three values */ + agcGainUpdateCtr[0] = (uint8_t)(device->rx->rxAgcCtrl->agcGainUpdateCounter); + agcGainUpdateCtr[1] = (uint8_t)(device->rx->rxAgcCtrl->agcGainUpdateCounter >> 8); + agcGainUpdateCtr[2] = (uint8_t)(device->rx->rxAgcCtrl->agcGainUpdateCounter >> 16); + + /* Write two bytes directly due. Third word has its upper two bits masked off. */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_GAIN_UPDATE_CNT_1, agcGainUpdateCtr[0]); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_GAIN_UPDATE_CNT_2, agcGainUpdateCtr[1]); + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_GAIN_UPDATE_CNT_3, agcGainUpdateCtr[2], 0x3F, 0); + } + + /* Range check on agcPeakWaitTime (5-bit) */ + if (device->rx->rxAgcCtrl->agcPeakWaitTime > 0x1F || device->rx->rxAgcCtrl->agcPeakWaitTime < 0x02) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_PEAK_WAIT_TIME_PARM, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_PEAK_WAIT_TIME_PARM)); + return MYKONOS_ERR_INV_AGC_RX_PEAK_WAIT_TIME_PARM; + } + else + { + /* Write agcPeakWaitTime */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_CFG_2, device->rx->rxAgcCtrl->agcPeakWaitTime, 0x1F, 0); + } + + /* Set MYKONOS_ADDR_AGC_CFG_2 bits [6:5] = b11 to enable AGC counters for MGC mode - needed for ARM cals to work correctly */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_CFG_2, 3, 0x60, 5); + + /* Range check for agcSlowLoopSettlingDelay (7-bit) */ + if (device->rx->rxAgcCtrl->agcSlowLoopSettlingDelay > 0x7F) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_SLOW_LOOP_SETTLING_DELAY, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_SLOW_LOOP_SETTLING_DELAY)); + return MYKONOS_ERR_INV_AGC_RX_SLOW_LOOP_SETTLING_DELAY; + } + else + { + /* Write agcSlowLoopSettlingDelay */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_LOOP_CFG, device->rx->rxAgcCtrl->agcSlowLoopSettlingDelay, 0x7F, 0); + } + + /* Range check for pmdMeasDuration */ + if ((uint32_t)(1 << (3 + device->rx->rxAgcCtrl->powerAgc->pmdMeasDuration)) >= (device->rx->rxAgcCtrl->agcGainUpdateCounter)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_PMD_MEAS_DURATION, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_PMD_MEAS_DURATION)); + return MYKONOS_ERR_INV_AGC_PMD_MEAS_DURATION; + } + else + { + /* Write pmdMeasDuration */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_DEC_POWER_CONFIG_2, device->rx->rxAgcCtrl->powerAgc->pmdMeasDuration, 0x0F, 0); + } + + /* Range check for pmdMeasConfig */ + if (device->rx->rxAgcCtrl->powerAgc->pmdMeasConfig > 0x3) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_PMD_MEAS_CONFIG, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_PMD_MEAS_CONFIG)); + return MYKONOS_ERR_INV_AGC_PMD_MEAS_CONFIG; + } + else + { + if (device->rx->rxAgcCtrl->powerAgc->pmdMeasConfig == 0) + { + decPowerConfig = 0x0; /* Dec Pwr measurement disable */ + } + else if (device->rx->rxAgcCtrl->powerAgc->pmdMeasConfig == 1) + { + decPowerConfig = 0x3; /* Dec Pwr measurement enable, HB2 for decPwr measurement */ + } + else if (device->rx->rxAgcCtrl->powerAgc->pmdMeasConfig == 2) + { + decPowerConfig = 0x5; /* Dec Pwr measurement enable, RFIR for decPwr measurement */ + } + else if (device->rx->rxAgcCtrl->powerAgc->pmdMeasConfig == 3) + { + decPowerConfig = 0x11; /* Dec Pwr measurement enable, BBDC2 for decPwr measurement */ + } + /* Write pmdMeasConfig */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_DEC_POWER_CONFIG_1, decPowerConfig); + } + + /* Range check agcLowThsPreventGainIncrease (1-bit) */ + if (device->rx->rxAgcCtrl->agcLowThsPreventGainIncrease > 1) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_LOW_THS_PREV_GAIN_INC, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_LOW_THS_PREV_GAIN_INC)); + return MYKONOS_ERR_INV_AGC_RX_LOW_THS_PREV_GAIN_INC; + } + else + { + /* Write agcLowThsPreventGainIncrease */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_LOCK_LEV_THRSH, device->rx->rxAgcCtrl->agcLowThsPreventGainIncrease, 0x80, 7); + } + + /* Range check agcPeakThresholdMode (1-bit), */ + if (device->rx->rxAgcCtrl->agcPeakThresholdMode > 1) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_PEAK_THRESH_MODE, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_PEAK_THRESH_MODE)); + return MYKONOS_ERR_INV_AGC_RX_PEAK_THRESH_MODE; + } + else + { + /* Save to lower1ThreshGainStepRegValue register variable */ + lower1ThreshGainStepRegValue |= (uint8_t)(device->rx->rxAgcCtrl->agcPeakThresholdMode << 5); + } + + /* Range check agcResetOnRxEnable (1-bit) */ + if (device->rx->rxAgcCtrl->agcResetOnRxEnable > 1) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_LOW_THS_PREV_GAIN_INC, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_LOW_THS_PREV_GAIN_INC)); + return MYKONOS_ERR_INV_AGC_RX_RESET_ON_RX_ENABLE; + } + else + { + /* Write agcResetOnRxEnable */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_GAIN_UPDATE_CNT_3, (uint8_t)(device->rx->rxAgcCtrl->agcResetOnRxEnable << 7), 0x80, 0); + } + + /* Range check agcEnableSyncPulseForGainCounter (1-bit) */ + if (device->rx->rxAgcCtrl->agcEnableSyncPulseForGainCounter > 1) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_ENABLE_SYNC_PULSE_GAIN_COUNTER, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_ENABLE_SYNC_PULSE_GAIN_COUNTER)); + return MYKONOS_ERR_INV_AGC_RX_ENABLE_SYNC_PULSE_GAIN_COUNTER; + } + else + { + /* Write agcEnableSyncPulseForGainCounter */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_LOOP_CFG, (uint8_t)(device->rx->rxAgcCtrl->agcEnableSyncPulseForGainCounter << 7), 0x80, 0); + } + + /* WRITE REGISTERS FOR THE AGC POWER MEASUREMENT DETECTOR (PMD) STRUCTURE */ + + /* Range check pmdLowerHighThresh (7-bit) vs 0x7F and pmdUpperLowThresh */ + if ((device->rx->rxAgcCtrl->powerAgc->pmdLowerHighThresh <= device->rx->rxAgcCtrl->powerAgc->pmdUpperLowThresh) + || device->rx->rxAgcCtrl->powerAgc->pmdLowerHighThresh > 0x7F) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_PMD_LOWER_HIGH_THRESH, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_PMD_LOWER_HIGH_THRESH)); + return MYKONOS_ERR_INV_AGC_RX_PMD_LOWER_HIGH_THRESH; + } + else + { + /* Write pmdLowerHighThresh */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_LOCK_LEV_THRSH, device->rx->rxAgcCtrl->powerAgc->pmdLowerHighThresh, 0x7F, 0); + } + + /* Range check pmdUpperLowThresh (7-bit): Comparison to pmdLowerHigh done earlier */ + if (device->rx->rxAgcCtrl->powerAgc->pmdUpperLowThresh > 0x7F) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_LOW_THRESH, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_LOW_THRESH)); + return MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_LOW_THRESH; + } + else + { + /* Write pmdUpperLowThresh */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_LOCK_LEVEL, device->rx->rxAgcCtrl->powerAgc->pmdUpperLowThresh); + } + + /* Range check pmdLowerLowThresh (4-bit) */ + if (device->rx->rxAgcCtrl->powerAgc->pmdLowerLowThresh > 0xF) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_PMD_LOWER_LOW_THRESH, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_PMD_LOWER_LOW_THRESH)); + return MYKONOS_ERR_INV_AGC_RX_PMD_LOWER_LOW_THRESH; + } + else + { + /* Write pmdUpperLowThresh to temp variable */ + powerThresholdsRegValue |= device->rx->rxAgcCtrl->powerAgc->pmdLowerLowThresh; + } + + /* Range check pmdUpperHighThresh (4-bit) */ + if (device->rx->rxAgcCtrl->powerAgc->pmdUpperHighThresh > 0xF) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_HIGH_THRESH, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_HIGH_THRESH)); + return MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_HIGH_THRESH; + } + else + { + /* Write pmdUpperHighThresh to temp var, then to register */ + powerThresholdsRegValue |= (uint8_t)(device->rx->rxAgcCtrl->powerAgc->pmdUpperHighThresh << 4); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_POWER_THRSH, powerThresholdsRegValue); + } + + /* Range check pmdUpperHighGainStepAttack (5-bit) */ + if (device->rx->rxAgcCtrl->powerAgc->pmdUpperHighGainStepAttack > 0x1F) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_HIGH_GAIN_STEP, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_HIGH_GAIN_STEP)); + return MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_HIGH_GAIN_STEP; + } + else + { + /* Write pmdUpperHighGainStepAttack */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_UPPER1_THRSH_GAIN_STEP, device->rx->rxAgcCtrl->powerAgc->pmdUpperHighGainStepAttack, 0x1F, 0); + } + + /* Range check pmdLowerLowGainStepRecovery (5-bit) */ + if (device->rx->rxAgcCtrl->powerAgc->pmdLowerLowGainStepRecovery > 0x1F) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_PMD_LOWER_LOW_GAIN_STEP, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_PMD_LOWER_LOW_GAIN_STEP)); + return MYKONOS_ERR_INV_AGC_RX_PMD_LOWER_LOW_GAIN_STEP; + } + else + { + /* Write pmdLowerLowGainStepRecovery to temp var, then to register */ + lower1ThreshGainStepRegValue |= (device->rx->rxAgcCtrl->powerAgc->pmdLowerLowGainStepRecovery); + } + + /* Range check pmdUpperLowGainStepRecovery (5-bit) */ + if (device->rx->rxAgcCtrl->powerAgc->pmdUpperLowGainStepAttack > 0x1F) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_LOW_GAIN_STEP, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_LOW_GAIN_STEP)); + return MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_LOW_GAIN_STEP; + } + else + { + /* Write pmdLowerLowGainStepRecovery to temp var, then to register */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_UPPER0_THRSH_GAIN_STEP, device->rx->rxAgcCtrl->powerAgc->pmdUpperLowGainStepAttack); + } + + /* Range check pmdLowerHighGainStepRecovery (5-bit) */ + if (device->rx->rxAgcCtrl->powerAgc->pmdLowerHighGainStepRecovery > 0x1F) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_PMD_LOWER_HIGH_GAIN_STEP, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_PMD_LOWER_HIGH_GAIN_STEP)); + return MYKONOS_ERR_INV_AGC_RX_PMD_LOWER_HIGH_GAIN_STEP; + } + else + { + /* Write pmdLowerLowGainStepRecovery to temp var, then to register */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_LOWER0_THRSH_GAIN_STEP, device->rx->rxAgcCtrl->powerAgc->pmdLowerHighGainStepRecovery); + } + + /* WRITE REGISTERS FOR THE AGC PEAK DETECTOR (APD/HB2) STRUCTURE */ + + /* Range check apdFastAttack and hb2FastAttack (1-bit) */ + if (device->rx->rxAgcCtrl->peakAgc->apdFastAttack > 0x1 || device->rx->rxAgcCtrl->peakAgc->hb2FastAttack > 0x1) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_PKDET_FAST_ATTACK_VALUE, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_PKDET_FAST_ATTACK_VALUE)); + return MYKONOS_ERR_INV_AGC_RX_PKDET_FAST_ATTACK_VALUE; + } + else + { + /* Write pmdLowerLowGainStepRecovery to temp var, then to register */ + lower1ThreshGainStepRegValue |= (uint8_t)(device->rx->rxAgcCtrl->peakAgc->apdFastAttack << 7); + lower1ThreshGainStepRegValue |= (uint8_t)(device->rx->rxAgcCtrl->peakAgc->hb2FastAttack << 6); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_LOWER1_THRSH_GAIN_STEP, lower1ThreshGainStepRegValue); + } + + /* Range check apdHighThresh */ + if ((device->rx->rxAgcCtrl->peakAgc->apdHighThresh > 0x3F) || (device->rx->rxAgcCtrl->peakAgc->apdHighThresh <= device->rx->rxAgcCtrl->peakAgc->apdLowThresh)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_APD_HIGH_THRESH_PARM, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_APD_HIGH_THRESH_PARM)); + return MYKONOS_ERR_INV_AGC_RX_APD_HIGH_THRESH_PARM; + } + else + { + /* Write apdHighThresh */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_ULB_THRSH, device->rx->rxAgcCtrl->peakAgc->apdHighThresh, 0X3F, 0); + } + + /* Range check apdLowThresh */ + if ((device->rx->rxAgcCtrl->peakAgc->apdLowThresh > 0x3F) || (device->rx->rxAgcCtrl->peakAgc->apdHighThresh < device->rx->rxAgcCtrl->peakAgc->apdLowThresh)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_APD_LOW_THRESH_PARM, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_APD_LOW_THRESH_PARM)); + return MYKONOS_ERR_INV_AGC_RX_APD_LOW_THRESH_PARM; + } + else + { + /* write apdLowThresh */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_LLB_THRSH, device->rx->rxAgcCtrl->peakAgc->apdLowThresh, 0x3F, 0); + } + + /* Range check hb2HighThresh */ + if (device->rx->rxAgcCtrl->peakAgc->hb2HighThresh < device->rx->rxAgcCtrl->peakAgc->hb2LowThresh) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_HB2_HIGH_THRESH_PARM, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_HB2_HIGH_THRESH_PARM)); + return MYKONOS_ERR_INV_AGC_RX_HB2_HIGH_THRESH_PARM; + } + else + { + /* write hb2HighThresh */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OVRLD_PD_DEC_OVRLD_UPPER_THRSH, device->rx->rxAgcCtrl->peakAgc->hb2HighThresh); + } + + /* Range check hb2LowThresh */ + if (device->rx->rxAgcCtrl->peakAgc->hb2LowThresh > device->rx->rxAgcCtrl->peakAgc->hb2HighThresh) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_HB2_LOW_THRESH_PARM, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_HB2_LOW_THRESH_PARM)); + return MYKONOS_ERR_INV_AGC_RX_HB2_LOW_THRESH_PARM; + } + else + { + /* write hb2LowThresh */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OVRLD_PD_DEC_OVRLD_LOWER_THRSH, device->rx->rxAgcCtrl->peakAgc->hb2LowThresh); + } + + /* Range check hb2VeryLowThresh */ + if (device->rx->rxAgcCtrl->peakAgc->hb2VeryLowThresh > device->rx->rxAgcCtrl->peakAgc->hb2LowThresh) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_HB2_VERY_LOW_THRESH_PARM, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_HB2_VERY_LOW_THRESH_PARM)); + return MYKONOS_ERR_INV_AGC_RX_HB2_VERY_LOW_THRESH_PARM; + } + else + { + /* write hb2VeryLowThresh */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OVRLD_PD_DEC_VERYLOW_THRSH, device->rx->rxAgcCtrl->peakAgc->hb2VeryLowThresh); + } + + /* Write threshold counter values for apdHigh/apdLow/hb2High/hb2Low/hb2VeryLow */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_ULB_CNT_THRSH, device->rx->rxAgcCtrl->peakAgc->apdHighThreshExceededCnt); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_LLB_CNT_THRSH, device->rx->rxAgcCtrl->peakAgc->apdLowThreshExceededCnt); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_HIGH_OVRG_CNT_THRSH, device->rx->rxAgcCtrl->peakAgc->hb2HighThreshExceededCnt); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_LOW_OVRG_CNT_THRSH, device->rx->rxAgcCtrl->peakAgc->hb2LowThreshExceededCnt); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_VERYLOW_OVRG_CNT_THRSH, device->rx->rxAgcCtrl->peakAgc->hb2VeryLowThreshExceededCnt); + + /* Range check on apdHighGainStepAttack (5-bit) */ + if (device->rx->rxAgcCtrl->peakAgc->apdHighGainStepAttack > 0x1F) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_APD_HIGH_GAIN_STEP_PARM, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_APD_HIGH_GAIN_STEP_PARM)); + return MYKONOS_ERR_INV_AGC_RX_APD_HIGH_GAIN_STEP_PARM; + } + else + { + /* Write apdHighGainStepAttack */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_OVRG_GAIN_STEP_1, device->rx->rxAgcCtrl->peakAgc->apdHighGainStepAttack); + } + + /* Range check on apdLowGainStepRecovery (5-bit) */ + if (device->rx->rxAgcCtrl->peakAgc->apdLowGainStepRecovery > 0x1F) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_APD_LOW_GAIN_STEP_PARM, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_APD_LOW_GAIN_STEP_PARM)); + return MYKONOS_ERR_INV_AGC_RX_APD_LOW_GAIN_STEP_PARM; + } + else + { + /* Write apdLowGainStepRecovery */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_OVRG_GAIN_STEP_4, device->rx->rxAgcCtrl->peakAgc->apdLowGainStepRecovery); + } + + /* Range check on hb2HighGainStepAttack (5-bit) */ + if (device->rx->rxAgcCtrl->peakAgc->hb2HighGainStepAttack > 0x1F) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_HB2_HIGH_GAIN_STEP_PARM, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_HB2_HIGH_GAIN_STEP_PARM)); + return MYKONOS_ERR_INV_AGC_RX_HB2_HIGH_GAIN_STEP_PARM; + } + else + { + /* Write hb2HighGainStepAttack */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_OVRG_GAIN_STEP_2, device->rx->rxAgcCtrl->peakAgc->hb2HighGainStepAttack); + } + + /* Range check on hb2LowGainStepRecovery (5-bit) */ + if (device->rx->rxAgcCtrl->peakAgc->hb2LowGainStepRecovery > 0x1F) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_HB2_LOW_GAIN_STEP_PARM, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_HB2_LOW_GAIN_STEP_PARM)); + return MYKONOS_ERR_INV_AGC_RX_HB2_LOW_GAIN_STEP_PARM; + } + else + { + /* Write hb2LowGainStepRecovery */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_OVRG_GAIN_STEP_5, device->rx->rxAgcCtrl->peakAgc->hb2LowGainStepRecovery); + } + + /* Range check on hb2VeryLowGainStepRecovery (5-bit) */ + if (device->rx->rxAgcCtrl->peakAgc->hb2VeryLowGainStepRecovery > 0x1F) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_HB2_VERY_LOW_GAIN_STEP_PARM, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_HB2_VERY_LOW_GAIN_STEP_PARM)); + return MYKONOS_ERR_INV_AGC_RX_HB2_VERY_LOW_GAIN_STEP_PARM; + } + else + { + /* Write hb2VeryLowGainStepRecovery */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_OVRG_GAIN_STEP_6, device->rx->rxAgcCtrl->peakAgc->hb2VeryLowGainStepRecovery); + } + + /* Range Check on hb2OverloadDetectEnable */ + if (device->rx->rxAgcCtrl->peakAgc->hb2OverloadDetectEnable > 0x1) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_HB2_OVLD_ENABLE, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_HB2_OVLD_ENABLE)); + return MYKONOS_ERR_INV_AGC_RX_HB2_OVLD_ENABLE; + } + + /* Range Check on hb2OverloadDetectEnable */ + if (device->rx->rxAgcCtrl->peakAgc->hb2OverloadDurationCnt > 0x7) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_HB2_OVLD_DUR_CNT, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_HB2_OVLD_DUR_CNT)); + return MYKONOS_ERR_INV_AGC_RX_HB2_OVLD_DUR_CNT; + } + + /* Range Check on hb2OverloadDetectEnable */ + if (device->rx->rxAgcCtrl->peakAgc->hb2OverloadThreshCnt > 0xF) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_HB2_OVLD_THRESH_CNT, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_HB2_OVLD_THRESH_CNT)); + return MYKONOS_ERR_INV_AGC_RX_HB2_OVLD_THRESH_CNT; + } + else + { + /* Write the hb2OvldCfgRegValue, the combination of hb2OverloadThreshCnt, hb2OverloadDurationCnt, and hb2OverloadDetectEnable */ + hb2OvldCfgRegValue = (device->rx->rxAgcCtrl->peakAgc->hb2OverloadThreshCnt) |(uint8_t)(device->rx->rxAgcCtrl->peakAgc->hb2OverloadDurationCnt << 4) + | (uint8_t)(device->rx->rxAgcCtrl->peakAgc->hb2OverloadDetectEnable << 7); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OVRLD_PD_DEC_OVRLD_CFG, hb2OvldCfgRegValue); + } + + /* Hard-coded value for the ADC overload configuration. Sets the HB2 offset to -6dB.*/ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OVRLD_ADC_OVRLD_CFG, 0x18); + /* Hard-coded value for APD decay setting. Setting allows for the quickest settling time of peak detector */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_RX_BLOCK_DET_DECAY, 0x0); + + /* performing a soft reset */ + return MYKONOS_resetRxAgc(device); +} + +/** + * \brief This function resets the AGC state machine + * + * Calling this function resets all state machines within the gain control and maximum gain. + * + * Dependencies: + * - device->spiSettings + * + * \param device is structure pointer to the Mykonos data structure containing the device SPI settings + * + * \retval MYKONOS_ERR_OK Function completed successfully + */ +mykonosErr_t MYKONOS_resetRxAgc(mykonosDevice_t *device) +{ + const uint8_t AGC_RESET = 0x80; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_resetRxAgc()\n"); +#endif + + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_CFG_2, 1, AGC_RESET, 7); + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_CFG_2, 0, AGC_RESET, 7); + + return MYKONOS_ERR_OK; + +} + +/** + * \brief This function sets the min/max gain indexes for AGC in the main RX channel + * + * Allows to change min/max gain index on runtime. + * If RX1_RX2 selected, then the maxGainIndex/minGainIndex value will be applied to both channels. + * If only Rx1 selected, then only Rx1 min/max gain indices will be updated, along with their device data structure values. + * If only Rx2 selected, then only Rx2 min/max gain indices will be updated, along with their device data structure values. + * + * Dependencies: + * - device->spiSettings + * - device->rx->rxAgcCtrl + * + * \param device is structure pointer to the Mykonos data structure containing the device SPI settings + * \param rxChannelSelect RX channel for setting the max and min gain index settings + * \param maxGainIndex Max gain index setting + * \param minGainIndex Min gain index setting + * + * \retval MYKONOS_ERR_SET_RX_MAX_GAIN_INDEX Max gain index bigger than max gain index loaded table. + * \retval MYKONOS_ERR_SET_RX_MIN_GAIN_INDEX Min gain index lower than min gain index loaded table. + * \retval MYKONOS_ERR_AGC_MIN_MAX_CHANNEL Wrong RX channel selected + * \retval MYKONOS_ERR_OK Function completed successfully + */ +mykonosErr_t MYKONOS_setRxAgcMinMaxGainIndex(mykonosDevice_t *device, mykonosRxChannels_t rxChannelSelect, uint8_t maxGainIndex, uint8_t minGainIndex) +{ + const uint8_t MIN_GAIN_INDEX = 1 + MAX_GAIN_TABLE_INDEX - (sizeof(RxGainTable) / sizeof(RxGainTable[0])); + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setRxAgcMinMaxGainIndex()\n"); +#endif + + /* Check for maxGainIndex */ + if (maxGainIndex > MAX_GAIN_TABLE_INDEX) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SET_RX_MAX_GAIN_INDEX, + getMykonosErrorMessage(MYKONOS_ERR_SET_RX_MAX_GAIN_INDEX)); + return MYKONOS_ERR_SET_RX_MAX_GAIN_INDEX; + } + + /* Check for minGainIndex */ + if (minGainIndex < MIN_GAIN_INDEX) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SET_RX_MIN_GAIN_INDEX, + getMykonosErrorMessage(MYKONOS_ERR_SET_RX_MIN_GAIN_INDEX)); + return MYKONOS_ERR_SET_RX_MIN_GAIN_INDEX; + } + + if ((uint32_t)rxChannelSelect & (uint32_t)RX1) + { + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_RX1_MAX_GAIN_INDEX, maxGainIndex); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_RX1_MIN_GAIN_INDEX, minGainIndex); + device->rx->rxAgcCtrl->agcRx1MaxGainIndex = maxGainIndex; + device->rx->rxAgcCtrl->agcRx1MinGainIndex = minGainIndex; + } + + if ((uint32_t)rxChannelSelect & (uint32_t)RX2) + { + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_RX2_MAX_GAIN_INDEX, maxGainIndex); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_RX2_MIN_GAIN_INDEX, minGainIndex); + device->rx->rxAgcCtrl->agcRx2MaxGainIndex = maxGainIndex; + device->rx->rxAgcCtrl->agcRx2MinGainIndex = minGainIndex; + } + + /* Check for invalid Rx channel */ + if (!((uint32_t)rxChannelSelect & (uint32_t)RX1_RX2)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_AGC_MIN_MAX_RX_CHANNEL, + getMykonosErrorMessage(MYKONOS_ERR_AGC_MIN_MAX_RX_CHANNEL)); + return MYKONOS_ERR_AGC_MIN_MAX_RX_CHANNEL; + } + + return MYKONOS_ERR_OK; +} + +/** + * \brief This function sets the min/max gain indexes for AGC in the observation channel + * + * Allows to change min/max gain index on runtime. + * + * Dependencies: + * - device->spiSettings + * - device->rx->rxAgcCtrl + * + * \param device is structure pointer to the Mykonos data structure containing the device SPI settings + * \param obsRxChannelSelect Observation channel for setting the max and min gain index settings + * \param maxGainIndex Max gain index setting + * \param minGainIndex Min gain index setting + * + * \retval MYKONOS_ERR_SET_ORX_MAX_GAIN_INDEX_CHANNEL Wrong read back channel. + * \retval MYKONOS_ERR_SET_ORX_MAX_GAIN_INDEX Max gain index bigger than max gain index loaded table. + * \retval MYKONOS_ERR_SET_ORX_MIN_GAIN_INDEX Min gain index lower than min gain index loaded table. + * \retval MYKONOS_ERR_AGC_MIN_MAX_ORX_CHANNEL Wrong observation channel selected + * \retval MYKONOS_ERR_OK Function completed successfully + */ +mykonosErr_t MYKONOS_setObsRxAgcMinMaxGainIndex(mykonosDevice_t *device, mykonosObsRxChannels_t obsRxChannelSelect, uint8_t maxGainIndex, uint8_t minGainIndex) +{ + uint8_t rdObsActive = 0x00; + uint8_t obsActive = 0x00; + uint8_t obsCheck = 0x00; + uint8_t minGainIndexCheck = 0x00; + uint8_t maxGainIndexCheck = 0x00; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setObsRxAgcMinMaxGainIndex()\n"); +#endif + + /* Read active channel */ + CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_AGC_ORX_SNRX_ACTIVE, &rdObsActive, 0x03, 0); + + /* Check active channel and set min/max checks */ + switch (rdObsActive) + { + case 0x00: + case 0x01: + /*sniffer*/ + maxGainIndexCheck = MAX_GAIN_TABLE_INDEX; + minGainIndexCheck = MAX_GAIN_TABLE_INDEX - (sizeof(SnRxGainTable) / sizeof(SnRxGainTable[0])); + obsActive = (uint32_t)OBS_SNIFFER | (uint32_t)OBS_SNIFFER_A | (uint32_t)OBS_SNIFFER_B | (uint32_t)OBS_SNIFFER_C; + break; + case 0x02: + case 0x03: + /*observation 1*/ + maxGainIndexCheck = MAX_GAIN_TABLE_INDEX; + minGainIndexCheck = MAX_GAIN_TABLE_INDEX - (sizeof(ORxGainTable) / sizeof(ORxGainTable[0])); + obsActive = (uint32_t)OBS_RX1_TXLO | (uint32_t)OBS_RX1_SNIFFERLO | (uint32_t)OBS_RX2_TXLO | (uint32_t)OBS_RX2_SNIFFERLO; + break; + + default: + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SET_ORX_MAX_GAIN_INDEX_CHANNEL, + getMykonosErrorMessage(MYKONOS_ERR_SET_ORX_MAX_GAIN_INDEX_CHANNEL)); + return MYKONOS_ERR_SET_ORX_MAX_GAIN_INDEX_CHANNEL; + } + + /* Check for maxGainIndex */ + if ((maxGainIndex > maxGainIndexCheck) || (maxGainIndex < minGainIndexCheck)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SET_ORX_MAX_GAIN_INDEX, + getMykonosErrorMessage(MYKONOS_ERR_SET_ORX_MAX_GAIN_INDEX)); + return MYKONOS_ERR_SET_ORX_MAX_GAIN_INDEX; + } + + /* Check for minGainIndex */ + if ((minGainIndex < minGainIndexCheck) || (minGainIndex > maxGainIndexCheck)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SET_ORX_MIN_GAIN_INDEX, + getMykonosErrorMessage(MYKONOS_ERR_SET_ORX_MIN_GAIN_INDEX)); + return MYKONOS_ERR_SET_ORX_MIN_GAIN_INDEX; + } + + device->obsRx->orxAgcCtrl->agcObsRxMaxGainIndex = maxGainIndex; + device->obsRx->orxAgcCtrl->agcObsRxMinGainIndex = minGainIndex; + + switch (obsRxChannelSelect) + { + case OBS_SNIFFER: + case OBS_SNIFFER_A: + case OBS_SNIFFER_B: + case OBS_SNIFFER_C: + obsCheck = (uint32_t)OBS_SNIFFER | (uint32_t)OBS_SNIFFER_A | (uint32_t)OBS_SNIFFER_B | (uint32_t)OBS_SNIFFER_C; + maxGainIndex = maxGainIndex - MAX_SNRX_GAIN_TABLE_NUMINDEXES; + minGainIndex = minGainIndex - MAX_SNRX_GAIN_TABLE_NUMINDEXES; + break; + + case OBS_RX1_TXLO: + case OBS_RX2_TXLO: + case OBS_RX1_SNIFFERLO: + case OBS_RX2_SNIFFERLO: + obsCheck = (uint32_t)OBS_RX1_TXLO | (uint32_t)OBS_RX1_SNIFFERLO | (uint32_t)OBS_RX2_TXLO | (uint32_t)OBS_RX2_SNIFFERLO; + maxGainIndex = maxGainIndex - MAX_ORX_GAIN_TABLE_NUMINDEXES; + minGainIndex = minGainIndex - MAX_ORX_GAIN_TABLE_NUMINDEXES; + break; + + default: + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_AGC_MIN_MAX_ORX_CHANNEL, + getMykonosErrorMessage(MYKONOS_ERR_AGC_MIN_MAX_ORX_CHANNEL)); + return MYKONOS_ERR_AGC_MIN_MAX_ORX_CHANNEL; + } + + if (obsCheck == obsActive) + { + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_ORX_SNRX_MAX_GAIN_INDEX, maxGainIndex); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_ORX_SNRX_MIN_GAIN_INDEX, minGainIndex); + } + else + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_AGC_MIN_MAX_ORX_CHANNEL, + getMykonosErrorMessage(MYKONOS_ERR_AGC_MIN_MAX_ORX_CHANNEL)); + return MYKONOS_ERR_AGC_MIN_MAX_ORX_CHANNEL; + } + + return MYKONOS_ERR_OK; +} + +/** + * \brief This function sets the Temperature gain compensation for Rx1 channel + * + * The temperature gain compensation control allow for a +3000mdB to -3000mdB digital gain + * in the data path. + * The resolution of the temperature compensation gain is 250mdB. + * + * Dependencies: + * - device->spiSettings + * + * \param device is structure pointer to the Mykonos data structure containing the device SPI settings + * \param rx1TempCompGain_mdB gain compensation for Rx1, the range is from -3000mdB to +3000mdB in steps of 250mdB + * + * \retval MYKONOS_ERR_RX1_TEMP_GAIN_COMP_RANGE The temp gain compensation is outside range (-3000mdB to 3000mdB) + * \retval MYKONOS_ERR_RX1_TEMP_GAIN_COMP_STEP Not valid temp gain compensation, step size is 250mdB + * \retval MYKONOS_ERR_OK Function completed successfully + */ +mykonosErr_t MYKONOS_setRx1TempGainComp(mykonosDevice_t *device, int16_t rx1TempCompGain_mdB) +{ + int8_t tempGainComp = 0x00; + + const int16_t LOW_LIMIT_GAIN_COMP = -3000; + const int16_t HIGH_LIMIT_GAIN_COMP = 3000; + const int16_t GAIN_COMP_STEP = 250; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setRx1TempGainComp()\n"); +#endif + + /* Check for Gain compensation range */ + if ((rx1TempCompGain_mdB > HIGH_LIMIT_GAIN_COMP) || (rx1TempCompGain_mdB < LOW_LIMIT_GAIN_COMP)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RX1_TEMP_GAIN_COMP_RANGE, + getMykonosErrorMessage(MYKONOS_ERR_RX1_TEMP_GAIN_COMP_RANGE)); + return MYKONOS_ERR_RX1_TEMP_GAIN_COMP_RANGE; + } + + /* Check for Gain compensation steps */ + if (rx1TempCompGain_mdB % GAIN_COMP_STEP) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RX1_TEMP_GAIN_COMP_STEP, + getMykonosErrorMessage(MYKONOS_ERR_RX1_TEMP_GAIN_COMP_STEP)); + return MYKONOS_ERR_RX1_TEMP_GAIN_COMP_STEP; + } + + /* Prepare register write */ + tempGainComp = (rx1TempCompGain_mdB / GAIN_COMP_STEP) & 0x1F; + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RX1_TEMP_GAIN_COMP, (uint8_t)tempGainComp); + + return MYKONOS_ERR_OK; +} + +/** + * \brief This function gets the Temperature gain compensation for Rx1 + * + * Dependencies: + * - device->spiSettings + * + * \param device is structure pointer to the Mykonos data structure containing the device SPI settings + * \param rx1TempCompGain_mdB Which will be populated with the Temperature Gain Compensation in mdB value for Rx1 channel. + * + * \retval MYKONOS_ERR_RX1_TEMP_GAIN_COMP_NULL rx1TempCompGain_mdB pointer is null. + * \retval MYKONOS_ERR_OK Function completed successfully + */ +mykonosErr_t MYKONOS_getRx1TempGainComp(mykonosDevice_t *device, int16_t *rx1TempCompGain_mdB) +{ + uint8_t tempGainComp = 0x00; + int8_t tempGainCompDB = 0x00; + + const int16_t GAIN_COMP_STEP = 250; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getRx1TempGainComp()\n"); +#endif + + /* Check for null passed parameter */ + if (rx1TempCompGain_mdB == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RX1_TEMP_GAIN_COMP_NULL, + getMykonosErrorMessage(MYKONOS_ERR_RX1_TEMP_GAIN_COMP_NULL)); + return MYKONOS_ERR_RX1_TEMP_GAIN_COMP_NULL; + } + + /* Read Temperature Gain Compensation */ + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_RX1_TEMP_GAIN_COMP, &tempGainComp); + + /* Convert to dB and prepare the signed return */ + tempGainCompDB = tempGainComp & 0x1F; + if (tempGainCompDB & 0x10) + { + tempGainCompDB = ((((~((uint8_t)tempGainCompDB)) & 0x0F) + 1) * (-1)); + } + + /* Assign value to the passed pointer */ + *rx1TempCompGain_mdB = tempGainCompDB * GAIN_COMP_STEP; + + return MYKONOS_ERR_OK; +} + +/** + * \brief This function sets the Temperature gain compensation for Rx2 channel + * + * The temperature gain compensation control allow for a +3000mdB to -3000mdB digital gain + * in the data path. + * The resolution of the temperature compensation gain is 250mdB. + * + * Dependencies: + * - device->spiSettings + * + * \param device is structure pointer to the Mykonos data structure containing the device SPI settings + * \param rx2TempCompGain_mdB gain compensation for Rx1, + * the range is from -3000mdB to +3000mdB in steps of 250mdB + * + * \retval MYKONOS_ERR_RX2_TEMP_GAIN_COMP_RANGE The temp gain compensation is outside range (-3000mdB to 3000mdB) + * \retval MYKONOS_ERR_RX2_TEMP_GAIN_COMP_STEP Not valid temp gain compensation, step size is 250mdB + * \retval MYKONOS_ERR_OK Function completed successfully + */ +mykonosErr_t MYKONOS_setRx2TempGainComp(mykonosDevice_t *device, int16_t rx2TempCompGain_mdB) +{ + int8_t tempGainComp = 0x00; + + const int16_t LOW_LIMIT_GAIN_COMP = -3000; + const int16_t HIGH_LIMIT_GAIN_COMP = 3000; + const int16_t GAIN_COMP_STEP = 250; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setRx2TempGainComp()\n"); +#endif + + /* Check for Gain compensation range */ + if ((rx2TempCompGain_mdB > HIGH_LIMIT_GAIN_COMP) || (rx2TempCompGain_mdB < LOW_LIMIT_GAIN_COMP)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RX2_TEMP_GAIN_COMP_RANGE, + getMykonosErrorMessage(MYKONOS_ERR_RX2_TEMP_GAIN_COMP_RANGE)); + return MYKONOS_ERR_RX2_TEMP_GAIN_COMP_RANGE; + } + + /* Check for Gain compensation range */ + if (rx2TempCompGain_mdB % GAIN_COMP_STEP) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RX2_TEMP_GAIN_COMP_STEP, + getMykonosErrorMessage(MYKONOS_ERR_RX2_TEMP_GAIN_COMP_STEP)); + return MYKONOS_ERR_RX2_TEMP_GAIN_COMP_STEP; + } + + /* Prepare register write */ + tempGainComp = (rx2TempCompGain_mdB / GAIN_COMP_STEP) & 0x1F; + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RX2_TEMP_GAIN_COMP, (uint8_t)tempGainComp); + + return MYKONOS_ERR_OK; +} + +/** + * \brief This function gets the Temperature gain compensation for Rx2 + * + * Dependencies: + * - device->spiSettings + * + * \param device is structure pointer to the Mykonos data structure containing the device SPI settings + * \param rx2TempCompGain_mdB Which will be populated with the Temperature Gain Compensation in mdB value for Rx2 channel. + * + * \retval MYKONOS_ERR_RX2_TEMP_GAIN_COMP_NULL rx2TempCompGain_mdB pointer is null. + * \retval MYKONOS_ERR_OK Function completed successfully + */ +mykonosErr_t MYKONOS_getRx2TempGainComp(mykonosDevice_t *device, int16_t *rx2TempCompGain_mdB) +{ + uint8_t tempGainComp = 0x00; + int8_t tempGainCompDB = 0x00; + + const int16_t GAIN_COMP_STEP = 250; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getRx2TempGainComp()\n"); +#endif + + /* Check for null passed parameter */ + if (rx2TempCompGain_mdB == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RX2_TEMP_GAIN_COMP_NULL, + getMykonosErrorMessage(MYKONOS_ERR_RX2_TEMP_GAIN_COMP_NULL)); + return MYKONOS_ERR_RX2_TEMP_GAIN_COMP_NULL; + } + + /* Read programmed Temperature Gain Compensation */ + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_RX2_TEMP_GAIN_COMP, &tempGainComp); + + /* Convert to dB and prepare the signed return */ + tempGainCompDB = tempGainComp & 0x1F; + if (tempGainCompDB & 0x10) + { + tempGainCompDB = (((~((uint8_t)tempGainCompDB)) & 0x0F) + 1) * (-1); + } + + /* Assign value to the passed pointer */ + *rx2TempCompGain_mdB = tempGainCompDB * GAIN_COMP_STEP; + + return MYKONOS_ERR_OK; +} + +/** + * \brief This function sets the Temperature gain compensation for the observation channel + * + * The temperature gain compensation control allow for a +3000mdB to -3000mdB digital gain + * in the data path. + * The resolution of the temperature compensation gain is 250mdB. + * + * Dependencies: + * - device->spiSettings + * + * \param device is structure pointer to the Mykonos data structure containing the device SPI settings + * \param obsRxTempCompGain_mdB gain compensation for observation channel, + * the range is from -3000mdB to +3000mdB in steps of 250mdB + * + * \retval MYKONOS_ERR_OBS_RX_TEMP_GAIN_COMP_RANGE The temp gain compensation is outside range (-3000mdB to 3000mdB) + * \retval MYKONOS_ERR_OBS_RX_TEMP_GAIN_COMP_STEP Not valid temp gain compensation, step size is 250mdB + * \retval MYKONOS_ERR_OK Function completed successfully + */ +mykonosErr_t MYKONOS_setObsRxTempGainComp(mykonosDevice_t *device, int16_t obsRxTempCompGain_mdB) +{ + int8_t tempGainComp = 0x00; + + const int16_t LOW_LIMIT_GAIN_COMP = -3000; + const int16_t HIGH_LIMIT_GAIN_COMP = 3000; + const int16_t GAIN_COMP_STEP = 250; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setObsRxTempGainComp()\n"); +#endif + + /* Check for Gain compensation range */ + if ((obsRxTempCompGain_mdB > HIGH_LIMIT_GAIN_COMP) || (obsRxTempCompGain_mdB < LOW_LIMIT_GAIN_COMP)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OBS_RX_TEMP_GAIN_COMP_RANGE, + getMykonosErrorMessage(MYKONOS_ERR_OBS_RX_TEMP_GAIN_COMP_RANGE)); + return MYKONOS_ERR_OBS_RX_TEMP_GAIN_COMP_RANGE; + } + + /* Check for Gain compensation range */ + if (obsRxTempCompGain_mdB % GAIN_COMP_STEP) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OBS_RX_TEMP_GAIN_COMP_STEP, + getMykonosErrorMessage(MYKONOS_ERR_OBS_RX_TEMP_GAIN_COMP_STEP)); + return MYKONOS_ERR_OBS_RX_TEMP_GAIN_COMP_STEP; + } + + /* Prepare register write */ + tempGainComp = (obsRxTempCompGain_mdB / GAIN_COMP_STEP) & 0x1F; + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OBS_TEMP_GAIN_COMP, (uint8_t)tempGainComp); + + return MYKONOS_ERR_OK; +} + +/** + * \brief This function gets the Temperature gain compensation for the observation channel + * + * + * Dependencies: + * - device->spiSettings + * + * \param device is structure pointer to the Mykonos data structure containing the device SPI settings + * \param obsRxTempCompGain_mdB Which will be populated with the Temperature Gain Compensation in mdB value for the observation channel. + * + * \retval MYKONOS_ERR_OBS_RX_TEMP_GAIN_COMP_NULL obsRxTempCompGain_mdB pointer is null. + * \retval MYKONOS_ERR_OK Function completed successfully + */ +mykonosErr_t MYKONOS_getObsRxTempGainComp(mykonosDevice_t *device, int16_t *obsRxTempCompGain_mdB) +{ + uint8_t tempGainComp = 0x00; + int8_t tempGainCompDB = 0x00; + + const int16_t GAIN_COMP_STEP = 250; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getObsRxTempGainComp()\n"); +#endif + + /* Check for null passed parameter */ + if (obsRxTempCompGain_mdB == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OBS_RX_TEMP_GAIN_COMP_NULL, + getMykonosErrorMessage(MYKONOS_ERR_OBS_RX_TEMP_GAIN_COMP_NULL)); + return MYKONOS_ERR_OBS_RX_TEMP_GAIN_COMP_NULL; + } + + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_OBS_TEMP_GAIN_COMP, &tempGainComp); + + /* Convert to dB and prepare the signed return */ + tempGainCompDB = tempGainComp & 0x1F; + if (tempGainCompDB & 0x10) + { + tempGainCompDB = (((~((uint8_t)tempGainCompDB)) & 0x0F) + 1) * (-1); + } + + /* Assign value to the passed pointer */ + *obsRxTempCompGain_mdB = tempGainCompDB * GAIN_COMP_STEP; + + return MYKONOS_ERR_OK; +} + +/** + * \brief Enables or disables the Rx slow loop gain counter to use the sync pulse + * + * Dependencies: + * - device->spiSettings + * + * \param device is structure pointer to the Mykonos data structure containing the device SPI settings + * \param enable is a uint8_t data type where '0' = disable Rx gain counter from using sync pulse, '1' = enable Rx gain. All other values will throw an error. + * counter to use the sync pulse. This value is written back to the device data structure for storage. + * + * \retval MYKONOS_ERR_OK Function completed successfully + */ +mykonosErr_t MYKONOS_enableRxGainCtrSyncPulse(mykonosDevice_t *device, uint8_t enable) +{ + const uint8_t syncPulseBitMask = 0x80; + uint8_t enableBit = 0; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setRxGainCtrSyncPulse()\n"); +#endif + + /* read, modify, write Rx gain counter sync pulse enable bit */ + enableBit = (enable > 0) ? 1 : 0; + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_LOOP_CFG, enableBit, syncPulseBitMask, 7); + + return MYKONOS_ERR_OK; +} + +/** + * \brief Configures the Rx gain control mode + * + * Dependencies: + * - device->spiSettings + * - device->spiSettings->chipSelectIndex + * - device->rx->rxGainCtrl->gainMode + * + * \param device is structure pointer to the Mykonos data structure containing settings + * \param mode is a mykonosGainMode_t enumerated gain control mode type where: + * Manual Gain = MGC, Automatic Gain Control = AGC, and hybrid mode = HYBRID + * + * When the mode enumerated type is passed, the Rx1 and Rx2 gain mode is set to this value and the + * Rx gainMode structure member is updated with the new value + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_INV_RX_GAIN_MODE_PARM Invalid AGC mode pass in function mode paramter + */ +mykonosErr_t MYKONOS_setRxGainControlMode(mykonosDevice_t *device, mykonosGainMode_t mode) +{ + uint8_t rxGainCfgReg = 0; + + const uint8_t RX_GAIN_TYPE_MASK = 0x1F; + const uint8_t RX_GAIN_HYBRID_MASK = 0x10; + const uint8_t RX_GAIN_TYPE_SHIFT = 0x02; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setRxGainControlMode()\n"); +#endif + + /* read AGC type for Rx1 and Rx2 for modify, write */ + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_AGC_CFG_1, &rxGainCfgReg); + rxGainCfgReg &= ~RX_GAIN_TYPE_MASK; + + /* performing AGC type check */ + switch (mode) + { + case MGC: + rxGainCfgReg &= ~RX_GAIN_HYBRID_MASK; + break; + case AGC: + rxGainCfgReg &= ~RX_GAIN_HYBRID_MASK; + break; + case HYBRID: + rxGainCfgReg |= RX_GAIN_HYBRID_MASK; + break; + default: + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_RX_GAIN_MODE_PARM, + getMykonosErrorMessage(MYKONOS_ERR_INV_RX_GAIN_MODE_PARM)); + return MYKONOS_ERR_INV_RX_GAIN_MODE_PARM; + } + + /* modify, write AGC type for Rx1 and Rx2 */ + rxGainCfgReg |= (uint8_t)mode; + rxGainCfgReg |= (uint8_t)((uint8_t)mode << RX_GAIN_TYPE_SHIFT); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_CFG_1, rxGainCfgReg); + + /* writing mode setting to data structure */ + if ((device->profilesValid & RX_PROFILE_VALID) > 0) + { + device->rx->rxGainCtrl->gainMode = mode; + } + + return MYKONOS_ERR_OK; +} + +/** + * \brief Performs a power measurement in the Rx1 digital data path. + * + * Due to interdependencies between the AGC and power measurement the power measurement duration and + * where the measurement is taken is variable. + * The location of the power measurement is given by device->rx->rxAgcCtrl->rxPwrAgc->pmdMeasConfig + * The number of samples the power measurement uses is given by 8*2^(device->rx->rxAgcCtrl->rxPwrAgc->pmdMeasDuration) at the IQ rate, + * if measured at RFIR output. This number of samples must be less than the agcGainUpdateCounter. + * If the receiver is disabled during the power measurement, this function returns a 0 value for rx1DecPower_mdBFS + * + * The resolution of this function is 0.25dB. + * The dynamic range of this function is 40dB. Signals lower than 40dBFS may not be measured accurately. + * + * Dependencies + * - device->spiSettings + * - device->rx->rxAgcCtrl->rxPwrAgc->pmdMeasConfig + * - device->rx->rxAgcCtrl->rxPwrAgc->pmdMeasDuration + * + * \param device Pointer to the Mykonos data structure + * \param rx1DecPower_mdBFS Pointer to store the Rx1 decimated power return. Value returned in mdBFS + * + * \retval MYKONOS_ERR_OK Function completed successfully + */ +mykonosErr_t MYKONOS_getRx1DecPower(mykonosDevice_t *device, uint16_t *rx1DecPower_mdBFS) +{ + uint8_t rx1DecPower_dBFS = 0; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getRx1DecPower()\n"); +#endif + + /* read Rx1 Dec Power Measurement */ + if (rx1DecPower_mdBFS != NULL) + { + CMB_SPIReadByte(device->spiSettings, MYKONOS_CH1_DECIMATED_PWR, &rx1DecPower_dBFS); + *rx1DecPower_mdBFS = (uint16_t)(rx1DecPower_dBFS * 250); /* 250 = 1000 * 0.25dB */ + } + else + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GET_RX1_DEC_POWER_NULL_PARM, + getMykonosErrorMessage(MYKONOS_ERR_GET_RX1_DEC_POWER_NULL_PARM)); + return MYKONOS_ERR_GET_RX1_DEC_POWER_NULL_PARM; + } + + return MYKONOS_ERR_OK; +} + +/** + * \brief Performs a power measurement in the Rx2 digital data path. + * + * Due to interdependencies between the AGC and power measurement the power measurement duration and + * where the measurement is taken is variable. + * The location of the power measurement is given by device->rx->rxAgcCtrl->rxPwrAgc->pmdMeasConfig + * The number of samples the power measurement uses is given by 8*2^(device->rx->rxAgcCtrl->rxPwrAgc->pmdMeasDuration) at the IQ rate, + * if measured at RFIR output. This number of samples must be less than the agcGainUpdateCounter. + * If the receiver is disabled during the power measurement, this function returns a 0 value for rx2DecPower_mdBFS + * + * The resolution of this function is 0.25dB. + * The dynamic range of this function is 40dB. Signals lower than 40dBFS may not be measured accurately. + * + * Dependencies + * - device->spiSettings + * + * \param device Pointer to the Mykonos data structure + * \param rx2DecPower_mdBFS Pointer to store the Rx1 decimated power return. Value returned in mdBFS + * + * \retval MYKONOS_ERR_OK Function completed successfully + */ +mykonosErr_t MYKONOS_getRx2DecPower(mykonosDevice_t *device, uint16_t *rx2DecPower_mdBFS) +{ + uint8_t rx2DecPower_dBFS = 0; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getRx2DecPower()\n"); +#endif + + /* read Rx2 Dec Power Measurement */ + if (rx2DecPower_mdBFS != NULL) + { + CMB_SPIReadByte(device->spiSettings, MYKONOS_CH2_DECIMATED_PWR, &rx2DecPower_dBFS); + *rx2DecPower_mdBFS = (uint16_t)(rx2DecPower_dBFS * 250); /* 250 = 1000 * 0.25dB */ + } + else + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GET_RX2_DEC_POWER_NULL_PARM, + getMykonosErrorMessage(MYKONOS_ERR_GET_RX2_DEC_POWER_NULL_PARM)); + return MYKONOS_ERR_GET_RX2_DEC_POWER_NULL_PARM; + } + + return MYKONOS_ERR_OK; +} + +/* + ***************************************************************************** + * Observation Rx Data path functions + ***************************************************************************** + */ + +/** + * \brief Sets the default Obs Rx channel to enter when device moves from + * radioOff to radioOn + * + * By default, the observation receiver remains powered down when the device + * moves into the radioOn state. If the BBIC prefers a particular ObsRx + * channel to be enabled, this function can be called in radioOff to set + * the default channel to power up when the device moves to radioOn. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * - device->obsRx->defaultObsRxChannel + * + * \param device is structure pointer to the Mykonos data structure containing settings + * \param defaultObsRxCh is mykonosObsRxChannels_t enum type which selects the desired observation receive path to power up + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_SETDEFOBSRXPATH_NULL_OBSRX_STRUCT Observation profile not valid, device->obsRx structure is NULL + * \retval MYKONOS_ERR_SETDEFOBSRXPATH_NULL_DEF_OBSRX_STRUCT Invalid defaultObsRxCh function parameter + */ +mykonosErr_t MYKONOS_setDefaultObsRxPath(mykonosDevice_t *device, mykonosObsRxChannels_t defaultObsRxCh) +{ + uint8_t orxEntryMode[1] = {0}; + uint16_t byteOffset = 0; + mykonosErr_t retVal = MYKONOS_ERR_OK; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setDefaultObsRxPath()\n"); +#endif + + if (device->obsRx == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETDEFOBSRXPATH_NULL_DEF_OBSRX_STRUCT, + getMykonosErrorMessage(MYKONOS_ERR_SETDEFOBSRXPATH_NULL_DEF_OBSRX_STRUCT)); + return MYKONOS_ERR_SETDEFOBSRXPATH_NULL_DEF_OBSRX_STRUCT; + } + + if (((defaultObsRxCh > OBS_RX2_SNIFFERLO) && (defaultObsRxCh != OBS_SNIFFER_A) && (defaultObsRxCh != OBS_SNIFFER_B) && (defaultObsRxCh != OBS_SNIFFER_C))) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_PU_OBSRXPATH_INV_PARAM, + getMykonosErrorMessage(MYKONOS_ERR_PU_OBSRXPATH_INV_PARAM)); + return MYKONOS_ERR_PU_OBSRXPATH_INV_PARAM; + } + + device->obsRx->defaultObsRxChannel = defaultObsRxCh; + orxEntryMode[0] = ((uint8_t)device->obsRx->defaultObsRxChannel & 0xFF); + + byteOffset = 6; + retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_RADIO_CONTROL, byteOffset, &orxEntryMode[0], 1); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + return MYKONOS_ERR_OK; +} + +/** + * \brief Powers up or down the Observation Rx signal chain in the radioOn state + * + * When the ARM radio control is in ARM command mode, this + * function allows the user to selectively power up or down the desired ObsRx + * data path. If this function is called when the ARM is expecting GPIO pin + * control of the ObsRx path source, an error will be returned. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device is structure pointer to the Mykonos data structure containing settings + * \param obsRxCh is mykonosObsRxChannels_t enum type which selects the desired observation receive path to power up + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_PU_OBSRXPATH_INV_PARAM Invalid obsRxCh function parameter + * \retval MYKONOS_ERR_PU_OBSRXPATH_ARMERROR ARM returned an error while trying to set the ObsRx Path source + */ +mykonosErr_t MYKONOS_setObsRxPathSource(mykonosDevice_t *device, mykonosObsRxChannels_t obsRxCh) +{ + uint8_t cmdStatByte = 0; + uint32_t timeoutMs = 0; + uint8_t payload[2] = {0, 0}; + mykonosErr_t retVal = MYKONOS_ERR_OK; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setObsRxPathSource()\n"); +#endif + + if (((obsRxCh > OBS_RX2_SNIFFERLO) && (obsRxCh != OBS_SNIFFER_A) && (obsRxCh != OBS_SNIFFER_B) && (obsRxCh != OBS_SNIFFER_C))) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_PU_OBSRXPATH_INV_PARAM, + getMykonosErrorMessage(MYKONOS_ERR_PU_OBSRXPATH_INV_PARAM)); + return MYKONOS_ERR_PU_OBSRXPATH_INV_PARAM; + } + + payload[0] = MYKONOS_ARM_OBJECTID_ORX_MODE; + payload[1] = (uint8_t)(obsRxCh); + + retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_SET_OPCODE, &payload[0], sizeof(payload)); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + timeoutMs = 1000; /* wait max of 1sec for command to complete */ + retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_SET_OPCODE, timeoutMs, &cmdStatByte); + if (retVal != MYKONOS_ERR_OK) + { + if (cmdStatByte > 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_PU_OBSRXPATH_ARMERROR, + getMykonosErrorMessage(MYKONOS_ERR_PU_OBSRXPATH_ARMERROR)); + return MYKONOS_ERR_PU_OBSRXPATH_ARMERROR; + } + + return retVal; + } + + /* Verify ARM command did not return an error */ + if (cmdStatByte > 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_PU_OBSRXPATH_ARMERROR, + getMykonosErrorMessage(MYKONOS_ERR_PU_OBSRXPATH_ARMERROR)); + return MYKONOS_ERR_PU_OBSRXPATH_ARMERROR; + } + + return MYKONOS_ERR_OK; +} + +/** + * \brief Reads back the currently enabled Observation Rx channel in the + * radioOn state + * + * In pin mode, the pin could change asynchronous to reading back the + * current enable ObsRx path. Calling this function while in radioOff will + * return OBS_RXOFF since all radio channels are powered down. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device is structure pointer to the Mykonos data structure containing settings + * \param obsRxCh Parameter to return enum of the current observation receive + * path powered up + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_PU_GETOBSRXPATH_ARMERROR ARM returned an error while trying to get the ObsRx Path source + */ +mykonosErr_t MYKONOS_getObsRxPathSource(mykonosDevice_t *device, mykonosObsRxChannels_t *obsRxCh) +{ + uint8_t extData[1] = {MYKONOS_ARM_OBJECTID_ORX_MODE}; + uint8_t cmdStatusByte = 0; + uint8_t armData[1] = {0}; + uint32_t timeoutMs = 0; + mykonosErr_t retVal = MYKONOS_ERR_OK; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getObsRxPathSource()\n"); +#endif + + retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_GET_OPCODE, &extData[0], sizeof(extData)); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + timeoutMs = 1000; + retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_GET_OPCODE, timeoutMs, &cmdStatusByte); + if (retVal != MYKONOS_ERR_OK) + { + if (cmdStatusByte > 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_PU_GETOBSRXPATH_ARMERROR, + getMykonosErrorMessage(MYKONOS_ERR_PU_GETOBSRXPATH_ARMERROR)); + return MYKONOS_ERR_PU_GETOBSRXPATH_ARMERROR; + } + + return retVal; + } + + /* read 64-bit frequency from ARM memory */ + retVal = MYKONOS_readArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR, &armData[0], 1, 1); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + if (cmdStatusByte > 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_PU_GETOBSRXPATH_ARMERROR, + getMykonosErrorMessage(MYKONOS_ERR_PU_GETOBSRXPATH_ARMERROR)); + return MYKONOS_ERR_PU_GETOBSRXPATH_ARMERROR; + } + + *obsRxCh = (mykonosObsRxChannels_t)(armData[0]); + + return MYKONOS_ERR_OK; +} + +/** + * \brief Sets the Rx gain of the ObsRx channel + * + * The ObsRx channel can have different RF inputs (ORx1/ORx2/SnRx A,B,C) + * This function sets the ObsRx gain index independently for ORx1/ORx2, or SnRx. + * SnRx A, B, and C share the same gain index. Please note that ORx1/ORx2 share a gain + * table, as does SnRx A, B, and C. The maximum index is 255 + * and the minimum index is application specific. + * + * Dependencies + * - device->spiSettings + * - device->obsRx->orxGainCtrl->maxGainIndex + * - device->obsRx->orxGainCtrl->minGainIndex + * - device->obsRx->orxGainCtrl->orx1GainIndex + * - device->obsRx->orxGainCtrl->orx2GainIndex + * - device->obsRx->snifferGainCtrl->maxGainIndex + * - device->obsRx->snifferGainCtrl->minGainIndex + * - device->obsRx->snifferGainCtrl->gainIndex + * + * \param device Pointer to the Mykonos device data structure + * \param obsRxCh is an enum type mykonosObsRxChannels_t to identify the desired RF input for gain change + * \param gainIndex Desired manual gain table index to set + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_SETORXGAIN_INV_ORX1GAIN Invalid gain requested for ORx1: outside gain table min/max index + * \retval MYKONOS_ERR_SETORXGAIN_INV_ORX2GAIN Invalid gain requested for ORx2: outside gain table min/max index + * \retval MYKONOS_ERR_SETORXGAIN_INV_SNRXGAIN Invalid gain requested for Sniffer: outside gain table min/max index + * \retval MYKONOS_ERR_SETORXGAIN_INV_CHANNEL Function parameter obsRxCh has an invalid enum value + */ +mykonosErr_t MYKONOS_setObsRxManualGain(mykonosDevice_t *device, mykonosObsRxChannels_t obsRxCh, uint8_t gainIndex) +{ + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setObsRxManualGain()\n"); +#endif + + if ((obsRxCh == OBS_RX1_TXLO) || (obsRxCh == OBS_RX1_SNIFFERLO)) + { + if (gainIndex <= device->obsRx->orxGainCtrl->maxGainIndex && gainIndex >= device->obsRx->orxGainCtrl->minGainIndex) + { + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_ORX1_MANUAL_GAIN_INDEX, (gainIndex - MIN_ORX_GAIN_TABLE_INDEX)); + device->obsRx->orxGainCtrl->orx1GainIndex = gainIndex; + } + else + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETORXGAIN_INV_ORX1GAIN, + getMykonosErrorMessage(MYKONOS_ERR_SETORXGAIN_INV_ORX1GAIN)); + return MYKONOS_ERR_SETORXGAIN_INV_ORX1GAIN; + } + } + else if ((obsRxCh == OBS_RX2_TXLO) || (obsRxCh == OBS_RX2_SNIFFERLO)) + { + if (gainIndex <= device->obsRx->orxGainCtrl->maxGainIndex && gainIndex >= device->obsRx->orxGainCtrl->minGainIndex) + { + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_ORX2_MANUAL_GAIN_INDEX, (gainIndex - MIN_ORX_GAIN_TABLE_INDEX)); + device->obsRx->orxGainCtrl->orx2GainIndex = gainIndex; + } + else + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETORXGAIN_INV_ORX2GAIN, + getMykonosErrorMessage(MYKONOS_ERR_SETORXGAIN_INV_ORX2GAIN)); + return MYKONOS_ERR_SETORXGAIN_INV_ORX2GAIN; + } + + } + else if (obsRxCh == OBS_SNIFFER_A || obsRxCh == OBS_SNIFFER_B || obsRxCh == OBS_SNIFFER_C || obsRxCh == OBS_SNIFFER) + { + if (gainIndex <= device->obsRx->snifferGainCtrl->maxGainIndex && gainIndex >= device->obsRx->snifferGainCtrl->minGainIndex) + { + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_SNRX_MANUAL_GAIN_INDEX, (gainIndex - MIN_SNRX_GAIN_TABLE_INDEX)); + device->obsRx->snifferGainCtrl->gainIndex = gainIndex; + } + else + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETORXGAIN_INV_SNRXGAIN, + getMykonosErrorMessage(MYKONOS_ERR_SETORXGAIN_INV_SNRXGAIN)); + return MYKONOS_ERR_SETORXGAIN_INV_SNRXGAIN; + } + } + else + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETORXGAIN_INV_CHANNEL, + getMykonosErrorMessage(MYKONOS_ERR_SETORXGAIN_INV_CHANNEL)); + return MYKONOS_ERR_SETORXGAIN_INV_CHANNEL; + } + + return MYKONOS_ERR_OK; +} + +/** + * \brief Gets the gain index of the currently enabled ObsRx channel + * + * The ObsRx data path can have multiple RF sources. This function will + * read back the gain index of the currently enabled RF source. If the ObsRx + * data path is disabled, an error is returned. If the functions uint8_t *gainIndex + * parameter is a valid pointer, the gain index is returned at the pointers + * address. Else, if the uint8_t *gainIndex pointer is NULL, the gainIndex read back + * is stored in the device data structure. + * + * NOTE: if the observation source is chosen by ORX_MODE pins, it is possible that + * the readback value will be incorrect if the obsRx channel changes while this function + * reads the gain. + * + * Dependencies + * - device->spiSettings + * - device->profilesValid + * - device->obsRx->orxGainCtrl->orx1GainIndex + * - device->obsRx->orxGainCtrl->orx2GainIndex + * - device->obsRx->snifferGainCtrl->gainIndex + * + * \param device Pointer to the Mykonos device data structure + * \param gainIndex Return value of the current gain index for the currently enabled ObsRx channel. + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_GETORX1GAIN_INV_POINTER The ObsRx profile is not valid in the device data structure + * \retval MYKONOS_ERR_GETORX2GAIN_INV_POINTER The ObsRx profile is not valid in the device data structure + * \retval MYKONOS_ERR_GETSNIFFGAIN_INV_POINTER The sniffer profile is not valid in the device data structure + * \retval MYKONOS_ERR_GETOBSRXGAIN_CH_DISABLED The observation receiver is currently disabled, can not read back gain index. + */ +mykonosErr_t MYKONOS_getObsRxGain(mykonosDevice_t *device, uint8_t *gainIndex) +{ + /* Potential issue, if ARM is using loopback path when this function is called, it will likely readback loopback gain */ + uint8_t readObsRxPathEnabled = 0; + uint8_t readObsRxGain = 0; + + const uint8_t ORX1_EN = 0x01; + const uint8_t ORX2_EN = 0x02; + const uint8_t SNRX_EN = 0x04; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getObsRxGain()\n"); +#endif + + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_DPD_SNIFFER_CONFIGURATION_CONTROL_1, &readObsRxPathEnabled); + + /* If obsRx channel enabled, then read gain index */ + if (readObsRxPathEnabled > 0) + { + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_GAIN_CTL_ORX_SNRX_GAIN, &readObsRxGain); + + switch (readObsRxPathEnabled) + { + case 0x01: + readObsRxGain += MIN_ORX_GAIN_TABLE_INDEX; + break; + case 0x02: + readObsRxGain += MIN_ORX_GAIN_TABLE_INDEX; + break; + case 0x04: + readObsRxGain += MIN_SNRX_GAIN_TABLE_INDEX; + break; + default: + break; + } + + if (gainIndex != NULL) + { + *gainIndex = readObsRxGain; + } + + /* Store the gain index in the device's gain control data structure. */ + + if (readObsRxPathEnabled == ORX1_EN) + { + /* verify valid data structure pointers */ + if (device->profilesValid & ORX_PROFILE_VALID) + { + device->obsRx->orxGainCtrl->orx1GainIndex = readObsRxGain; + } + else + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETORX1GAIN_INV_POINTER, + getMykonosErrorMessage(MYKONOS_ERR_GETORX1GAIN_INV_POINTER)); + return MYKONOS_ERR_GETORX1GAIN_INV_POINTER; + } + + } + else if (readObsRxPathEnabled == ORX2_EN) + { + /* verify valid pointers */ + if (device->profilesValid & ORX_PROFILE_VALID) + { + device->obsRx->orxGainCtrl->orx2GainIndex = readObsRxGain; + } + else + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETORX2GAIN_INV_POINTER, + getMykonosErrorMessage(MYKONOS_ERR_GETORX2GAIN_INV_POINTER)); + return MYKONOS_ERR_GETORX2GAIN_INV_POINTER; + } + + } + else if (readObsRxPathEnabled == SNRX_EN) + { + /* verify valid pointers */ + if (device->profilesValid & SNIFF_PROFILE_VALID) + { + device->obsRx->snifferGainCtrl->gainIndex = readObsRxGain; + } + else + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETSNIFFGAIN_INV_POINTER, + getMykonosErrorMessage(MYKONOS_ERR_GETSNIFFGAIN_INV_POINTER)); + return MYKONOS_ERR_GETSNIFFGAIN_INV_POINTER; + } + } + else + { + /* ignore gain index for Tx loopback input into obsRx channel */ + } + } + else + { + CMB_writeToLog(ADIHAL_LOG_WARNING, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETOBSRXGAIN_CH_DISABLED, + getMykonosErrorMessage(MYKONOS_ERR_GETOBSRXGAIN_CH_DISABLED)); + return MYKONOS_ERR_GETOBSRXGAIN_CH_DISABLED; + } + + return MYKONOS_ERR_OK; +} + +/** + * \brief Sets up the device ObsRx Automatic Gain Control (AGC) registers. + * + * Three data structures (of types mykonosAgcCfg_t, mykonosPeakDetAgcCfg_t, mykonosPowerMeasAgcCfg_t) + * must be instantiated prior to calling this function. Valid ranges for data structure members + * must also be provided. + * + * + * Dependencies: + * - device->spiSettings + * - device->spiSettings->chipSelectIndex + * - device->obsRx->orxAgcCtrl->agcRx1MaxGainIndex + * - device->obsRx->orxAgcCtrl->agcRx1MinGainIndex + * - device->obsRx->orxAgcCtrl->agcRx2MaxGainIndex + * - device->obsRx->orxAgcCtrl->agcRx2MinGainIndex + * - device->obsRx->orxAgcCtrl->agcObsRxMaxGainIndex + * - device->obsRx->orxAgcCtrl->agcObsRxMinGainIndex + * - device->obsRx->orxAgcCtrl->agcObsRxSelect + * - device->obsRx->orxAgcCtrl->agcPeakThresholdMode + * - device->obsRx->orxAgcCtrl->agcLowThsPreventGainIncrease + * - device->obsRx->orxAgcCtrl->agcGainUpdateCounter + * - device->obsRx->orxAgcCtrl->agcSlowLoopSettlingDelay + * - device->obsRx->orxAgcCtrl->agcPeakWaitTime + * - device->obsRx->orxAgcCtrl->agcResetOnRxEnable + * - device->obsRx->orxAgcCtrl->agcEnableSyncPulseForGainCounter + * - device->obsRx->orxAgcCtrl->peakAgc->apdHighThresh + * - device->obsRx->orxAgcCtrl->peakAgc->apdLowThresh + * - device->obsRx->orxAgcCtrl->peakAgc->hb2HighThresh + * - device->obsRx->orxAgcCtrl->peakAgc->hb2LowThresh + * - device->obsRx->orxAgcCtrl->peakAgc->hb2VeryLowThresh + * - device->obsRx->orxAgcCtrl->peakAgc->apdHighThreshExceededCnt + * - device->obsRx->orxAgcCtrl->peakAgc->apdLowThreshExceededCnt + * - device->obsRx->orxAgcCtrl->peakAgc->hb2HighThreshExceededCnt + * - device->obsRx->orxAgcCtrl->peakAgc->hb2LowThreshExceededCnt + * - device->obsRx->orxAgcCtrl->peakAgc->hb2VeryLowThreshExceededCnt + * - device->obsRx->orxAgcCtrl->peakAgc->apdHighGainStepAttack + * - device->obsRx->orxAgcCtrl->peakAgc->apdLowGainStepRecovery + * - device->obsRx->orxAgcCtrl->peakAgc->hb2HighGainStepAttack + * - device->obsRx->orxAgcCtrl->peakAgc->hb2LowGainStepRecovery + * - device->obsRx->orxAgcCtrl->peakAgc->hb2VeryLowGainStepRecovery + * - device->obsRx->orxAgcCtrl->peakAgc->apdFastAttack + * - device->obsRx->orxAgcCtrl->peakAgc->hb2FastAttack + * - device->obsRx->orxAgcCtrl->peakAgc->hb2OverloadDetectEnable + * - device->obsRx->orxAgcCtrl->peakAgc->hb2OverloadDurationCnt + * - device->obsRx->orxAgcCtrl->peakAgc->hb2OverloadThreshCnt + * - device->obsRx->orxAgcCtrl->powerAgc->pmdUpperHighThresh + * - device->obsRx->orxAgcCtrl->powerAgc->pmdUpperLowThresh + * - device->obsRx->orxAgcCtrl->powerAgc->pmdLowerHighThresh + * - device->obsRx->orxAgcCtrl->powerAgc->pmdLowerLowThresh + * - device->obsRx->orxAgcCtrl->powerAgc->pmdUpperHighGainStepAttack + * - device->obsRx->orxAgcCtrl->powerAgc->pmdUpperLowGainStepAttack + * - device->obsRx->orxAgcCtrl->powerAgc->pmdLowerHighGainStepRecovery + * - device->obsRx->orxAgcCtrl->powerAgc->pmdLowerLowGainStepRecovery + * - device->obsRx->orxAgcCtrl->powerAgc->pmdMeasDuration + * - device->obsRx->orxAgcCtrl->powerAgc->pmdMeasConfig + * + * \param device is structure pointer to the Mykonos data structure containing settings + * The pointer to the Mykonos AGC data structure containing settings is checked for a null pointer + * to ensure it has been initialized. If not an error is thrown. + * + * \retval Returns MYKONOS_ERR=pass, !MYKONOS_ERR=fail + * \retval MYKONOS_ERR_INV_AGC_OBSRX_STRUCT_INIT + * \retval MYKONOS_ERR_INV_AGC_OBSRX_PEAK_STRUCT_INIT + * \retval MYKONOS_ERR_INV_AGC_OBSRX_PWR_STRUCT_INIT + * \retval MYKONOS_ERR_INV_AGC_OBSRX_MAX_GAIN_INDEX + * \retval MYKONOS_ERR_INV_AGC_OBSRX_MIN_GAIN_INDEX + * \retval MYKONOS_ERR_INV_AGC_OBSRX_SELECT + * \retval MYKONOS_ERR_INV_AGC_OBSRX_GAIN_UPDATE_TIME_PARM + * \retval MYKONOS_ERR_INV_AGC_OBSRX_PEAK_WAIT_TIME_PARM + * \retval MYKONOS_ERR_INV_AGC_OBSRX_SLOW_LOOP_SETTLING_DELAY + * \retval MYKONOS_ERR_INV_AGC_OBSRX_PMD_MEAS_DURATION + * \retval MYKONOS_ERR_INV_AGC_OBSRX_PMD_MEAS_CONFIG + * \retval MYKONOS_ERR_INV_AGC_OBSRX_LOW_THS_PREV_GAIN_INC + * \retval MYKONOS_ERR_INV_AGC_OBSRX_PEAK_THRESH_MODE + * \retval MYKONOS_ERR_INV_AGC_OBSRX_RESET_ON_RX_ENABLE + * \retval MYKONOS_ERR_INV_AGC_OBSRX_ENABLE_SYNC_PULSE_GAIN_COUNTER + * \retval MYKONOS_ERR_INV_AGC_OBSRX_PMD_LOWER_HIGH_THRESH + * \retval MYKONOS_ERR_INV_AGC_OBSRX_PMD_UPPER_LOW_THRESH + * \retval MYKONOS_ERR_INV_AGC_OBSRX_PMD_LOWER_LOW_THRESH + * \retval MYKONOS_ERR_INV_AGC_OBSRX_PMD_UPPER_HIGH_THRESH + * \retval MYKONOS_ERR_INV_AGC_OBSRX_PMD_UPPER_HIGH_GAIN_STEP + * \retval MYKONOS_ERR_INV_AGC_OBSRX_PMD_LOWER_LOW_GAIN_STEP + * \retval MYKONOS_ERR_INV_AGC_OBSRX_PMD_UPPER_LOW_GAIN_STEP + * \retval MYKONOS_ERR_INV_AGC_OBSRX_PMD_LOWER_HIGH_GAIN_STEP + * \retval MYKONOS_ERR_INV_AGC_OBSRX_PKDET_FAST_ATTACK_VALUE + * \retval MYKONOS_ERR_INV_AGC_OBSRX_APD_HIGH_THRESH_PARM + * \retval MYKONOS_ERR_INV_AGC_OBSRX_APD_LOW_THRESH_PARM + * \retval MYKONOS_ERR_INV_AGC_OBSRX_HB2_HIGH_THRESH_PARM + * \retval MYKONOS_ERR_INV_AGC_OBSRX_HB2_LOW_THRESH_PARM + * \retval MYKONOS_ERR_INV_AGC_OBSRX_HB2_VERY_LOW_THRESH_PARM + * \retval MYKONOS_ERR_INV_AGC_OBSRX_APD_HIGH_GAIN_STEP_PARM + * \retval MYKONOS_ERR_INV_AGC_OBSRX_APD_LOW_GAIN_STEP_PARM + * \retval MYKONOS_ERR_INV_AGC_OBSRX_HB2_HIGH_GAIN_STEP_PARM + * \retval MYKONOS_ERR_INV_AGC_OBSRX_HB2_LOW_GAIN_STEP_PARM + * \retval MYKONOS_ERR_INV_AGC_OBSRX_HB2_VERY_LOW_GAIN_STEP_PARM + * \retval MYKONOS_ERR_INV_AGC_OBSRX_HB2_OVLD_ENABLE + * \retval MYKONOS_ERR_INV_AGC_OBSRX_HB2_OVLD_DUR_CNT + * \retval MYKONOS_ERR_INV_AGC_OBSRX_HB2_OVLD_THRESH_CNT + */ +mykonosErr_t MYKONOS_setupObsRxAgc(mykonosDevice_t *device) +{ + /* Current configuration does not support AGC on ORx channel */ + uint8_t decPowerConfig = 0; + uint8_t lower1ThreshGainStepRegValue = 0; + uint8_t powerThresholdsRegValue = 0; + uint8_t hb2OvldCfgRegValue = 0; + uint8_t agcGainUpdateCtr[3] = {0}; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setupObsRxAgc()\n"); +#endif + + /* Check mykonosAgcCfg_t device->obsRx->orxAgcCtrl pointer for initialization */ + if (device->obsRx->orxAgcCtrl == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_STRUCT_INIT, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_STRUCT_INIT)); + return MYKONOS_ERR_INV_AGC_OBSRX_STRUCT_INIT; + } + + /* Check mykonosPeakDetAgcCfg_t device->orx->orxAgcCtrl->peakAgc pointer for initialization */ + if (device->obsRx->orxAgcCtrl->peakAgc == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_PEAK_STRUCT_INIT, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_PEAK_STRUCT_INIT)); + return MYKONOS_ERR_INV_AGC_OBSRX_PEAK_STRUCT_INIT; + } + + /* Check mykonosPowerMeasAgcCfg_t device->obsRx->orxAgcCtrl->powerAgc pointer for initialization */ + if (device->obsRx->orxAgcCtrl->powerAgc == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_PWR_STRUCT_INIT, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_PWR_STRUCT_INIT)); + return MYKONOS_ERR_INV_AGC_OBSRX_PWR_STRUCT_INIT; + } + + /* Range check agcObsRxMaxGainIndex versus gain table limits and agcObsRxMinGainIndex */ + if ((device->obsRx->orxAgcCtrl->agcObsRxMaxGainIndex > device->obsRx->snifferGainCtrl->maxGainIndex) || + (device->obsRx->orxAgcCtrl->agcObsRxMaxGainIndex < device->obsRx->orxAgcCtrl->agcObsRxMinGainIndex)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_MAX_GAIN_INDEX, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_MAX_GAIN_INDEX)); + return MYKONOS_ERR_INV_AGC_OBSRX_MAX_GAIN_INDEX; + } + else + { + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_ORX_SNRX_MAX_GAIN_INDEX, + (device->obsRx->orxAgcCtrl->agcObsRxMaxGainIndex - MAX_SNRX_GAIN_TABLE_NUMINDEXES)); + } + + /* Range check agcObsRxMinGainIndex versus gain table limits and agcObsRxMaxGainIndex */ + if ((device->obsRx->orxAgcCtrl->agcObsRxMinGainIndex < device->obsRx->snifferGainCtrl->minGainIndex) || + (device->obsRx->orxAgcCtrl->agcObsRxMaxGainIndex < device->obsRx->orxAgcCtrl->agcObsRxMinGainIndex)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_MIN_GAIN_INDEX, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_MIN_GAIN_INDEX)); + return MYKONOS_ERR_INV_AGC_OBSRX_MIN_GAIN_INDEX; + } + else + { + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_ORX_SNRX_MIN_GAIN_INDEX, + (device->obsRx->orxAgcCtrl->agcObsRxMinGainIndex - MAX_SNRX_GAIN_TABLE_NUMINDEXES)); + } + + /* Range check agcObsRxSelect. Sniffer only support. Sniffer is selected if value is 0 or 1. 2 or 3 select ORx1/ORx2 respectively */ + if (device->obsRx->orxAgcCtrl->agcObsRxSelect > 1) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_SELECT, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_SELECT)); + return MYKONOS_ERR_INV_AGC_OBSRX_SELECT; + } + else + { + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_ORX_SNRX_ACTIVE, device->obsRx->orxAgcCtrl->agcObsRxSelect); + } + + /* Range check for agcGainUpdateCounter (22-bit) */ + if ((device->obsRx->orxAgcCtrl->agcGainUpdateCounter > 0x3FFFFF) || + (device->obsRx->orxAgcCtrl->agcGainUpdateCounter < 1)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_GAIN_UPDATE_TIME_PARM, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_GAIN_UPDATE_TIME_PARM)); + return MYKONOS_ERR_INV_AGC_OBSRX_GAIN_UPDATE_TIME_PARM; + } + else + { + /* Split agcGainUpdateCounter into three values */ + agcGainUpdateCtr[0] = (uint8_t)(device->obsRx->orxAgcCtrl->agcGainUpdateCounter); + agcGainUpdateCtr[1] = (uint8_t)(device->obsRx->orxAgcCtrl->agcGainUpdateCounter >> 8); + agcGainUpdateCtr[2] = (uint8_t)(device->obsRx->orxAgcCtrl->agcGainUpdateCounter >> 16); + + /* Write two bytes directly due. Third word has its upper two bits masked off. */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_GAIN_UPDATE_CTR_1, agcGainUpdateCtr[0]); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_GAIN_UPDATE_CTR_2, agcGainUpdateCtr[1]); + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_GAIN_UPDATE_CTR_3, agcGainUpdateCtr[2], 0x3F, 0); + } + + /* Range check on agcPeakWaitTime (5-bit) */ + if ((device->obsRx->orxAgcCtrl->agcPeakWaitTime > 0x1F) || + (device->obsRx->orxAgcCtrl->agcPeakWaitTime < 0x02)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_PEAK_WAIT_TIME_PARM, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_PEAK_WAIT_TIME_PARM)); + return MYKONOS_ERR_INV_AGC_OBSRX_PEAK_WAIT_TIME_PARM; + } + else + { + /* Write agcPeakWaitTime */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_ORX_SNRX_CFG_2, device->obsRx->orxAgcCtrl->agcPeakWaitTime, 0x1F, 0); + } + + /* Range check for agcSlowLoopSettlingDelay (7-bit) */ + if (device->obsRx->orxAgcCtrl->agcSlowLoopSettlingDelay > 0x7F) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_SLOW_LOOP_SETTLING_DELAY, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_SLOW_LOOP_SETTLING_DELAY)); + return MYKONOS_ERR_INV_AGC_OBSRX_SLOW_LOOP_SETTLING_DELAY; + } + else + { + /* Write agcSlowLoopSettlingDelay */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_LOOP_CFG, device->obsRx->orxAgcCtrl->agcSlowLoopSettlingDelay, 0x7F, 0); + } + + /* Range check for pmdMeasDuration */ + if ((uint32_t)(1 << (3 + device->obsRx->orxAgcCtrl->powerAgc->pmdMeasDuration)) >= (device->obsRx->orxAgcCtrl->agcGainUpdateCounter)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_PMD_MEAS_DURATION, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_PMD_MEAS_DURATION)); + return MYKONOS_ERR_INV_AGC_OBSRX_PMD_MEAS_DURATION; + } + else + { + /* Write pmdMeasDuration */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_SNIFFER_DEC_POWER_CONFIG_2, device->obsRx->orxAgcCtrl->powerAgc->pmdMeasDuration, 0x0F, 0); + } + + /* Range check for pmdMeasConfig */ + if (device->obsRx->orxAgcCtrl->powerAgc->pmdMeasConfig > 0x3) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_PMD_MEAS_CONFIG, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_PMD_MEAS_CONFIG)); + return MYKONOS_ERR_INV_AGC_OBSRX_PMD_MEAS_CONFIG; + } + else + { + if (device->obsRx->orxAgcCtrl->powerAgc->pmdMeasConfig == 0) + { + decPowerConfig = 0x0; /* Dec Pwr measurement disable */ + } + else if (device->obsRx->orxAgcCtrl->powerAgc->pmdMeasConfig == 1) + { + decPowerConfig = 0x3; /* Dec Pwr measurement enable, HB2 for decPwr measurement */ + } + else if (device->obsRx->orxAgcCtrl->powerAgc->pmdMeasConfig == 2) + { + decPowerConfig = 0x5; /* Dec Pwr measurement enable, RFIR for decPwr measurement */ + } + else if (device->obsRx->orxAgcCtrl->powerAgc->pmdMeasConfig == 3) + { + decPowerConfig = 0x11; /* Dec Pwr measurement enable, BBDC2 for decPwr measurement */ + } + /* Write pmdMeasConfig */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_SNIFFER_DEC_POWER_CONFIG_1, decPowerConfig); + } + + /* Range check agcLowThsPreventGainIncrease (1-bit) */ + if (device->obsRx->orxAgcCtrl->agcLowThsPreventGainIncrease > 1) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_LOW_THS_PREV_GAIN_INC, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_LOW_THS_PREV_GAIN_INC)); + return MYKONOS_ERR_INV_AGC_OBSRX_LOW_THS_PREV_GAIN_INC; + } + else + { + /* Write agcLowThsPreventGainIncrease */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_LOCK_LEV_THRSH, device->obsRx->orxAgcCtrl->agcLowThsPreventGainIncrease, 0x80, 7); + } + + /* Range check agcPeakThresholdMode (1-bit), */ + if (device->obsRx->orxAgcCtrl->agcPeakThresholdMode > 1) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_PEAK_THRESH_MODE, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_PEAK_THRESH_MODE)); + return MYKONOS_ERR_INV_AGC_OBSRX_PEAK_THRESH_MODE; + } + else + { + /* Save to lower1ThreshGainStepRegValue register variable */ + lower1ThreshGainStepRegValue |= (uint8_t)(device->obsRx->orxAgcCtrl->agcPeakThresholdMode << 5); + } + + /* Range check agcResetOnRxEnable (1-bit) */ + if (device->obsRx->orxAgcCtrl->agcResetOnRxEnable > 1) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_RESET_ON_RX_ENABLE, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_RESET_ON_RX_ENABLE)); + return MYKONOS_ERR_INV_AGC_OBSRX_RESET_ON_RX_ENABLE; + } + else + { + /* Write agcResetOnRxEnable */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_GAIN_UPDATE_CTR_3, (uint8_t)(device->obsRx->orxAgcCtrl->agcResetOnRxEnable << 7), 0x80, 0); + } + + /* Range check agcEnableSyncPulseForGainCounter (1-bit) */ + if (device->obsRx->orxAgcCtrl->agcEnableSyncPulseForGainCounter > 1) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_ENABLE_SYNC_PULSE_GAIN_COUNTER, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_ENABLE_SYNC_PULSE_GAIN_COUNTER)); + return MYKONOS_ERR_INV_AGC_OBSRX_ENABLE_SYNC_PULSE_GAIN_COUNTER; + } + else + { + /* Write agcEnableSyncPulseForGainCounter */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_LOOP_CFG, (uint8_t)(device->obsRx->orxAgcCtrl->agcEnableSyncPulseForGainCounter << 7), 0x80, 0); + } + + /* WRITE REGISTERS FOR THE AGC POWER MEASUREMENT DETECTOR (PMD) STRUCTURE */ + + /* Range check pmdLowerHighThresh (7-bit) vs 0x7F and pmdUpperLowThresh */ + if ((device->obsRx->orxAgcCtrl->powerAgc->pmdLowerHighThresh <= device->obsRx->orxAgcCtrl->powerAgc->pmdUpperLowThresh) || + device->obsRx->orxAgcCtrl->powerAgc->pmdLowerHighThresh > 0x7F) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_PMD_LOWER_HIGH_THRESH, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_PMD_LOWER_HIGH_THRESH)); + return MYKONOS_ERR_INV_AGC_OBSRX_PMD_LOWER_HIGH_THRESH; + } + else + { + /* Write pmdLowerHighThresh */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_LOCK_LEV_THRSH, device->obsRx->orxAgcCtrl->powerAgc->pmdLowerHighThresh, 0x7F, 0); + } + + /* Range check pmdUpperLowThresh (7-bit): Comparison to pmdLowerHigh done earlier */ + if (device->obsRx->orxAgcCtrl->powerAgc->pmdUpperLowThresh > 0x7F) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_PMD_UPPER_LOW_THRESH, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_PMD_UPPER_LOW_THRESH)); + return MYKONOS_ERR_INV_AGC_OBSRX_PMD_UPPER_LOW_THRESH; + } + else + { + /* Write pmdUpperLowThresh */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_ORX_SNRX_LOCK_LEVEL, device->obsRx->orxAgcCtrl->powerAgc->pmdUpperLowThresh); + } + + /* Range check pmdLowerLowThresh (4-bit) */ + if (device->obsRx->orxAgcCtrl->powerAgc->pmdLowerLowThresh > 0xF) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_PMD_LOWER_LOW_THRESH, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_PMD_LOWER_LOW_THRESH)); + return MYKONOS_ERR_INV_AGC_OBSRX_PMD_LOWER_LOW_THRESH; + } + else + { + /* Write pmdUpperLowThresh to temp variable */ + powerThresholdsRegValue |= device->obsRx->orxAgcCtrl->powerAgc->pmdLowerLowThresh; + } + + /* Range check pmdUpperHighThresh (4-bit) */ + if (device->obsRx->orxAgcCtrl->powerAgc->pmdUpperHighThresh > 0xF) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_PMD_UPPER_HIGH_THRESH, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_PMD_UPPER_HIGH_THRESH)); + return MYKONOS_ERR_INV_AGC_OBSRX_PMD_UPPER_HIGH_THRESH; + } + else + { + /* Write pmdUpperHighThresh to temp var, then to register */ + powerThresholdsRegValue |= (uint8_t)(device->obsRx->orxAgcCtrl->powerAgc->pmdUpperHighThresh << 4); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_POWER_THRSH, powerThresholdsRegValue); + } + + /* Range check pmdUpperHighGainStepAttack (5-bit) */ + if (device->obsRx->orxAgcCtrl->powerAgc->pmdUpperHighGainStepAttack > 0x1F) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_PMD_UPPER_HIGH_GAIN_STEP, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_PMD_UPPER_HIGH_GAIN_STEP)); + return MYKONOS_ERR_INV_AGC_OBSRX_PMD_UPPER_HIGH_GAIN_STEP; + } + else + { + /* Write pmdUpperHighGainStepAttack */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_UPPER1_THRSH_GAIN_STEP, device->obsRx->orxAgcCtrl->powerAgc->pmdUpperHighGainStepAttack, 0x1F, 0); + } + + /* Range check pmdLowerLowGainStepRecovery (5-bit) */ + if (device->obsRx->orxAgcCtrl->powerAgc->pmdLowerLowGainStepRecovery > 0x1F) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_PMD_LOWER_LOW_GAIN_STEP, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_PMD_LOWER_LOW_GAIN_STEP)); + return MYKONOS_ERR_INV_AGC_OBSRX_PMD_LOWER_LOW_GAIN_STEP; + } + else + { + /* Write pmdLowerLowGainStepRecovery to temp var, then to register */ + lower1ThreshGainStepRegValue |= (uint8_t)(device->obsRx->orxAgcCtrl->powerAgc->pmdLowerLowGainStepRecovery); + } + + /* Range check pmdUpperLowGainStepRecovery (5-bit) */ + if (device->obsRx->orxAgcCtrl->powerAgc->pmdUpperLowGainStepAttack > 0x1F) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_PMD_UPPER_LOW_GAIN_STEP, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_PMD_UPPER_LOW_GAIN_STEP)); + return MYKONOS_ERR_INV_AGC_OBSRX_PMD_UPPER_LOW_GAIN_STEP; + } + else + { + /* Write pmdUpperLowGainStepRecovery to register */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_UPPER0_THRSH_GAIN_STEP, device->obsRx->orxAgcCtrl->powerAgc->pmdUpperLowGainStepAttack); + } + + /* Range check pmdLowerHighGainStepRecovery (5-bit) */ + if (device->obsRx->orxAgcCtrl->powerAgc->pmdLowerHighGainStepRecovery > 0x1F) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_PMD_LOWER_HIGH_GAIN_STEP, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_PMD_LOWER_HIGH_GAIN_STEP)); + return MYKONOS_ERR_INV_AGC_OBSRX_PMD_LOWER_HIGH_GAIN_STEP; + } + else + { + /* Write pmdLowerLowGainStepRecovery to temp var, then to register */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_LOWER0_THRSH_GAIN_STEP, device->obsRx->orxAgcCtrl->powerAgc->pmdLowerHighGainStepRecovery); + } + + /* WRITE REGISTERS FOR THE AGC PEAK DETECTOR (APD/HB2) STRUCTURE */ + + /* Range check apdFastAttack and hb2FastAttack (1-bit) */ + if ((device->obsRx->orxAgcCtrl->peakAgc->apdFastAttack > 0x1) || + (device->obsRx->orxAgcCtrl->peakAgc->hb2FastAttack > 0x1)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_PKDET_FAST_ATTACK_VALUE, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_PKDET_FAST_ATTACK_VALUE)); + return MYKONOS_ERR_INV_AGC_OBSRX_PKDET_FAST_ATTACK_VALUE; + } + else + { + /* Write pmdLowerLowGainStepRecovery to temp var, then to register */ + lower1ThreshGainStepRegValue |= (uint8_t)(device->obsRx->orxAgcCtrl->peakAgc->apdFastAttack << 7); + lower1ThreshGainStepRegValue |= (uint8_t)(device->obsRx->orxAgcCtrl->peakAgc->hb2FastAttack << 6); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_LOWER1_THRSH_GAIN_STEP, lower1ThreshGainStepRegValue); + } + + /* Range check apdHighThresh */ + if ((device->obsRx->orxAgcCtrl->peakAgc->apdHighThresh > 0x3F) || + (device->obsRx->orxAgcCtrl->peakAgc->apdHighThresh <= device->obsRx->orxAgcCtrl->peakAgc->apdLowThresh)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_APD_HIGH_THRESH_PARM, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_APD_HIGH_THRESH_PARM)); + return MYKONOS_ERR_INV_AGC_OBSRX_APD_HIGH_THRESH_PARM; + } + else + { + /* Write apdHighThresh */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_ORX_SNRX_ULB_THRSH, device->obsRx->orxAgcCtrl->peakAgc->apdHighThresh, 0X3F, 0); + } + + /* Range check apdLowThresh */ + if ((device->obsRx->orxAgcCtrl->peakAgc->apdLowThresh > 0x3F) || + (device->obsRx->orxAgcCtrl->peakAgc->apdHighThresh < device->obsRx->orxAgcCtrl->peakAgc->apdLowThresh)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_APD_LOW_THRESH_PARM, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_APD_LOW_THRESH_PARM)); + return MYKONOS_ERR_INV_AGC_OBSRX_APD_LOW_THRESH_PARM; + } + else + { + /* write apdLowThresh */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_ORX_SNRX_LLB_THRSH, device->obsRx->orxAgcCtrl->peakAgc->apdLowThresh, 0x3F, 0); + } + + /* Range check hb2HighThresh */ + if (device->obsRx->orxAgcCtrl->peakAgc->hb2HighThresh < device->obsRx->orxAgcCtrl->peakAgc->hb2LowThresh) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_HB2_HIGH_THRESH_PARM, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_HB2_HIGH_THRESH_PARM)); + return MYKONOS_ERR_INV_AGC_OBSRX_HB2_HIGH_THRESH_PARM; + } + else + { + /* write hb2HighThresh */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ORX_SNRX_OVRLD_PD_DEC_OVRLD_UPPER_THRSH, device->obsRx->orxAgcCtrl->peakAgc->hb2HighThresh); + } + + /* Range check hb2LowThresh */ + if (device->obsRx->orxAgcCtrl->peakAgc->hb2LowThresh > device->obsRx->orxAgcCtrl->peakAgc->hb2HighThresh) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_HB2_LOW_THRESH_PARM, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_HB2_LOW_THRESH_PARM)); + return MYKONOS_ERR_INV_AGC_OBSRX_HB2_LOW_THRESH_PARM; + } + else + { + /* write hb2LowThresh */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ORX_SNRX_OVRLD_PD_DEC_OVRLD_LOWER_THRSH, device->obsRx->orxAgcCtrl->peakAgc->hb2LowThresh); + } + + /* Range check hb2VeryLowThresh */ + if (device->obsRx->orxAgcCtrl->peakAgc->hb2VeryLowThresh > device->obsRx->orxAgcCtrl->peakAgc->hb2LowThresh) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_HB2_VERY_LOW_THRESH_PARM, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_HB2_VERY_LOW_THRESH_PARM)); + return MYKONOS_ERR_INV_AGC_OBSRX_HB2_VERY_LOW_THRESH_PARM; + } + else + { + /* write hb2VeryLowThresh */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ORX_SNRX_OVRLD_PD_DEC_OVRLD_VERYLOW_THRSH, device->obsRx->orxAgcCtrl->peakAgc->hb2VeryLowThresh); + } + + /* Write threshold counter values for apdHigh/apdLow/hb2High/hb2Low/hb2VeryLow */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_ULB_CNT_THRSH, device->obsRx->orxAgcCtrl->peakAgc->apdHighThreshExceededCnt); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_LLB_CNT_THRSH, device->obsRx->orxAgcCtrl->peakAgc->apdLowThreshExceededCnt); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_ADC_HIGH_OVRG_CNT_THRSH, device->obsRx->orxAgcCtrl->peakAgc->hb2HighThreshExceededCnt); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_ADC_LOW_OVRG_CNT_THRSH, device->obsRx->orxAgcCtrl->peakAgc->hb2LowThreshExceededCnt); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_ADC_VERYLOW_OVRG_CNT_THRSH, device->obsRx->orxAgcCtrl->peakAgc->hb2VeryLowThreshExceededCnt); + + /* Range check on apdHighGainStepAttack (5-bit) */ + if (device->obsRx->orxAgcCtrl->peakAgc->apdHighGainStepAttack > 0x1F) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_APD_HIGH_GAIN_STEP_PARM, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_APD_HIGH_GAIN_STEP_PARM)); + return MYKONOS_ERR_INV_AGC_OBSRX_APD_HIGH_GAIN_STEP_PARM; + } + else + { + /* Write apdHighGainStepAttack */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_ORX_SNRX_OVRG_GAIN_STEP_1, device->obsRx->orxAgcCtrl->peakAgc->apdHighGainStepAttack); + } + + /* Range check on apdLowGainStepRecovery (5-bit) */ + if (device->obsRx->orxAgcCtrl->peakAgc->apdLowGainStepRecovery > 0x1F) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_APD_LOW_GAIN_STEP_PARM, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_APD_LOW_GAIN_STEP_PARM)); + return MYKONOS_ERR_INV_AGC_OBSRX_APD_LOW_GAIN_STEP_PARM; + } + else + { + /* Write apdLowGainStepRecovery */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_ORX_SNRX_OVRG_GAIN_STEP_4, device->obsRx->orxAgcCtrl->peakAgc->apdLowGainStepRecovery); + } + + /* Range check on hb2HighGainStepAttack (5-bit) */ + if (device->obsRx->orxAgcCtrl->peakAgc->hb2HighGainStepAttack > 0x1F) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_HB2_HIGH_GAIN_STEP_PARM, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_HB2_HIGH_GAIN_STEP_PARM)); + return MYKONOS_ERR_INV_AGC_OBSRX_HB2_HIGH_GAIN_STEP_PARM; + } + else + { + /* Write hb2HighGainStepAttack */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_ORX_SNRX_OVRG_GAIN_STEP_2, device->obsRx->orxAgcCtrl->peakAgc->hb2HighGainStepAttack); + } + + /* Range check on hb2LowGainStepRecovery (5-bit) */ + if (device->obsRx->orxAgcCtrl->peakAgc->hb2LowGainStepRecovery > 0x1F) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_HB2_LOW_GAIN_STEP_PARM, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_HB2_LOW_GAIN_STEP_PARM)); + return MYKONOS_ERR_INV_AGC_OBSRX_HB2_LOW_GAIN_STEP_PARM; + } + else + { + /* Write hb2LowGainStepRecovery */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_ORX_SNRX_OVRG_GAIN_STEP_5, device->obsRx->orxAgcCtrl->peakAgc->hb2LowGainStepRecovery); + } + + /* Range check on hb2VeryLowGainStepRecovery (5-bit) */ + if (device->obsRx->orxAgcCtrl->peakAgc->hb2VeryLowGainStepRecovery > 0x1F) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_HB2_VERY_LOW_GAIN_STEP_PARM, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_HB2_VERY_LOW_GAIN_STEP_PARM)); + return MYKONOS_ERR_INV_AGC_OBSRX_HB2_VERY_LOW_GAIN_STEP_PARM; + } + else + { + /* Write hb2VeryLowGainStepRecovery */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_ORX_SNRX_OVRG_GAIN_STEP_6, device->obsRx->orxAgcCtrl->peakAgc->hb2VeryLowGainStepRecovery); + } + + /* Range Check on hb2OverloadDetectEnable */ + if (device->obsRx->orxAgcCtrl->peakAgc->hb2OverloadDetectEnable > 0x1) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_HB2_OVLD_ENABLE, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_HB2_OVLD_ENABLE)); + return MYKONOS_ERR_INV_AGC_OBSRX_HB2_OVLD_ENABLE; + } + + /* Range Check on hb2OverloadDetectEnable */ + if (device->obsRx->orxAgcCtrl->peakAgc->hb2OverloadDurationCnt > 0x7) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_HB2_OVLD_DUR_CNT, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_HB2_OVLD_DUR_CNT)); + return MYKONOS_ERR_INV_AGC_OBSRX_HB2_OVLD_DUR_CNT; + } + + /* Range Check on hb2OverloadDetectEnable */ + if (device->obsRx->orxAgcCtrl->peakAgc->hb2OverloadThreshCnt > 0xF) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_HB2_OVLD_THRESH_CNT, + getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_HB2_OVLD_THRESH_CNT)); + return MYKONOS_ERR_INV_AGC_OBSRX_HB2_OVLD_THRESH_CNT; + } + else + { + /* Write the hb2OvldCfgRegValue, the combination of hb2OverloadThreshCnt, hb2OverloadDurationCnt, and hb2OverloadDetectEnable */ + hb2OvldCfgRegValue = (device->obsRx->orxAgcCtrl->peakAgc->hb2OverloadThreshCnt) | + (uint8_t)(device->obsRx->orxAgcCtrl->peakAgc->hb2OverloadDurationCnt << 4) | + (uint8_t)(device->obsRx->orxAgcCtrl->peakAgc->hb2OverloadDetectEnable << 7); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ORX_SNRX_OVRLD_PD_DEC_OVRLD_CFG, hb2OvldCfgRegValue); + } + + /* Hard-coded value for the ADC overload configuration. Sets the HB2 offset to -6dB.*/ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ORX_SNRX_OVRLD_ADC_OVRLD_CFG, 0x18); + /* Hard-coded value for APD decay setting. Setting allows for the quickest settling time of peak detector */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_ORX_SNRX_BLOCK_DET_DECAY, 0x0); + + /* performing a soft reset */ + return MYKONOS_resetRxAgc(device); +} + +/** + * \brief Enables or disables the ObsRx slow loop gain counter to use the sync pulse + * + * Dependencies: + * - device->spiSettings + * + * \param device is structure pointer to the Mykonos data structure containing the device SPI settings + * \param enable is a uint8_t data type where '0' = disable ObsRx gain counter from using sync pulse, '1' = enable ObsRx gain. All other values will throw an error. + * counter to use the sync pulse. This value is written back to the device data structure for storage. + * + * \retval MYKONOS_ERR_OK Function completed successfully + */ +mykonosErr_t MYKONOS_enableObsRxGainCtrSyncPulse(mykonosDevice_t *device, uint8_t enable) +{ + const uint8_t syncPulseBitMask = 0x80; + uint8_t enableBit = 0; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_enableObsRxGainCtrSyncPulse()\n"); +#endif + + enableBit = (enable > 0) ? 1 : 0; + + /* read, modify, write ObsRx gain counter sync pulse enable bit */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_LOOP_CFG, enableBit, syncPulseBitMask, 7); + + return MYKONOS_ERR_OK; +} + +/** + * \brief Configures the ObsRx gain control mode + * + * Dependencies: + * - device->spiSettings + * - device->obsRx->orxGainCtrl->gainMode + * + * \param device is structure pointer to the Mykonos data structure containing settings + * \param mode is a mykonosGainMode_t enumerated gain control mode type + * + * When the mode enumerated type is passed, the ObsRx gain mode is set to this value and the + * ObsRX agcType mykonosAgcCfg_t structure member is updated with the new value + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_INV_ORX_GAIN_MODE_PARM Invalid Observation Rx Gain control mode selected (use mykonosGainMode_t ENUM values) + */ +mykonosErr_t MYKONOS_setObsRxGainControlMode(mykonosDevice_t *device, mykonosGainMode_t mode) +{ + const uint8_t ORX_GAIN_TYPE_MASK = 0x3; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setObsRxGainControlMode()\n"); +#endif + + /* performing gain type check */ + switch (mode) + { + case MGC: + break; + case AGC: + break; + case HYBRID: + break; + default: + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_ORX_GAIN_MODE_PARM, + getMykonosErrorMessage(MYKONOS_ERR_INV_ORX_GAIN_MODE_PARM)); + return MYKONOS_ERR_INV_ORX_GAIN_MODE_PARM; + } + + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_ORX_SNRX_CFG_1, mode, ORX_GAIN_TYPE_MASK, 0); + + /* writing mode setting to data structure */ + if ((device->profilesValid & ORX_PROFILE_VALID) > 0) + { + device->obsRx->orxGainCtrl->gainMode = mode; + } + + return MYKONOS_ERR_OK; +} + +/** + * \brief Performs a power measurement in the ObsRx digital data path. + * + * Due to interdependencies between the AGC and power measurement the power measurement duration and + * where the measurement is taken is variable. + * The location of the power measurement is given by device->obsRx->obsRxAgcCtrl->obsRxPwrAgc->pmdMeasConfig + * The number of samples the power measurement uses is given by 8*2^(device->obsRx->obsRxAgcCtrl->obsRxPwrAgc->pmdMeasConfig) at the IQ rate, + * if measured at RFIR output. This number of samples must be less than the agcGainUpdateCounter. + * If the receiver is disabled during the power measurement, this function returns a 0 value for rx2DecPower_mdBFS + * + * The resolution of this function is 0.25dB. + * The dynamic range of this function is 40dB. Signals lower than 40dBFS may not be measured accurately. + * + * Dependencies + * - device->spiSettings + * - device->obsRx->obsRxAgcCtrl->obsRxPwrAgc->pmdMeasConfig + * - device->obsRx->obsRxAgcCtrl->obsRxPwrAgc->pmdMeasConfig + * + * \param device Pointer to the Mykonos data structure + * \param obsRxDecPower_mdBFS Pointer to store the Rx1 decimated power return. Value returned in mdBFS + * + * \retval MYKONOS_ERR_OK Function completed successfully + */ +mykonosErr_t MYKONOS_getObsRxDecPower(mykonosDevice_t *device, uint16_t *obsRxDecPower_mdBFS) +{ + uint8_t obsRxDecPower_dBFS = 0; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getObsRxDecPower()\n"); +#endif + + /* read ObsRx Dec Power Measurement */ + if (obsRxDecPower_mdBFS != NULL) + { + CMB_SPIReadByte(device->spiSettings, MYKONOS_SNIFFER_DECIMATED_PWR, &obsRxDecPower_dBFS); + *obsRxDecPower_mdBFS = (uint16_t)(obsRxDecPower_dBFS * 250); /* 250 = 1000 * 0.25dB */ + } + else + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GET_OBSRX_DEC_POWER_NULL_PARM, + getMykonosErrorMessage(MYKONOS_ERR_GET_OBSRX_DEC_POWER_NULL_PARM)); + return MYKONOS_ERR_GET_OBSRX_DEC_POWER_NULL_PARM; + } + + return MYKONOS_ERR_OK; +} + +/* + ***************************************************************************** + * Tx Data path functions + ***************************************************************************** + */ + +/** + * \brief Sets the Tx1 RF output Attenuation + * + * Dependencies + * - device->spiSettings + * - device->spiSettings->chipSelectIndex + * - device->tx->txAttenStepSize + * + * \param device Pointer to the Mykonos device's data structure + * \param tx1Attenuation_mdB The desired TxAttenuation in milli-dB (Range: 0 to 41950 mdB) + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_SETTX1ATTEN_INV_PARM tx1Attenuation_mdB parameter is out of range (0 - 41950) + * \retval MYKONOS_ERR_SETTX1ATTEN_INV_STEPSIZE_PARM device->tx->txAttenStepSize is not a valid enum value + */ +mykonosErr_t MYKONOS_setTx1Attenuation(mykonosDevice_t *device, uint16_t tx1Attenuation_mdB) +{ + uint16_t data = 0; + uint16_t attenStepSizeDiv = 50; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setTx1Attenuation()\n"); +#endif + + /* check input parameter is in valid range */ + if (tx1Attenuation_mdB > 41950) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETTX1ATTEN_INV_PARM, + getMykonosErrorMessage(MYKONOS_ERR_SETTX1ATTEN_INV_PARM)); + return MYKONOS_ERR_SETTX1ATTEN_INV_PARM; + } + + switch (device->tx->txAttenStepSize) + { + case TXATTEN_0P05_DB: + attenStepSizeDiv = 50; + break; + case TXATTEN_0P1_DB: + attenStepSizeDiv = 100; + break; + case TXATTEN_0P2_DB: + attenStepSizeDiv = 200; + break; + case TXATTEN_0P4_DB: + attenStepSizeDiv = 400; + break; + default: + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETTX1ATTEN_INV_STEPSIZE_PARM, + getMykonosErrorMessage(MYKONOS_ERR_SETTX1ATTEN_INV_STEPSIZE_PARM)); + return MYKONOS_ERR_SETTX1ATTEN_INV_STEPSIZE_PARM; + + } + + data = (tx1Attenuation_mdB / attenStepSizeDiv); + + /* Write MSB bits followed by LSB bits, TxAtten updates when [7:0] written */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_TX1_ATTENUATION_1, ((data >> 8) & 0x03)); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_TX1_ATTENUATION_0, (data & 0xFF)); + + return MYKONOS_ERR_OK; +} + +/** + * \brief Sets the Tx2 RF output Attenuation (Step size is 0.05dB.) + * + * Dependencies + * - device->spiSettings + * - device->spiSettings->chipSelectIndex + * - device->tx->txAttenStepSize + * + * \param device Pointer to the Mykonos device's data structure + * \param tx2Attenuation_mdB The desired TxAttenuation in milli-dB + * (Range: 0 to 41950 mdB) + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_SETTX2ATTEN_INV_PARM tx2Attenuation_mdB parameter is out of range (0 - 41950) + * \retval MYKONOS_ERR_SETTX2ATTEN_INV_STEPSIZE_PARM device->tx->txAttenStepSize is not a valid enum value + */ +mykonosErr_t MYKONOS_setTx2Attenuation(mykonosDevice_t *device, uint16_t tx2Attenuation_mdB) +{ + uint16_t attenStepSizeDiv = 50; + uint16_t data = 0; + //const uint8_t SPI_TXATTEN_MODE = 0x01; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setTx2Attenuation()\n"); +#endif + + /* check input parameter is in valid range */ + if (tx2Attenuation_mdB > 41950) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETTX2ATTEN_INV_PARM, + getMykonosErrorMessage(MYKONOS_ERR_SETTX2ATTEN_INV_PARM)); + return MYKONOS_ERR_SETTX2ATTEN_INV_PARM; + } + + switch (device->tx->txAttenStepSize) + { + case TXATTEN_0P05_DB: + attenStepSizeDiv = 50; + break; + case TXATTEN_0P1_DB: + attenStepSizeDiv = 100; + break; + case TXATTEN_0P2_DB: + attenStepSizeDiv = 200; + break; + case TXATTEN_0P4_DB: + attenStepSizeDiv = 400; + break; + default: + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETTX2ATTEN_INV_STEPSIZE_PARM, + getMykonosErrorMessage(MYKONOS_ERR_SETTX2ATTEN_INV_STEPSIZE_PARM)); + return MYKONOS_ERR_SETTX2ATTEN_INV_STEPSIZE_PARM; + } + + data = (tx2Attenuation_mdB / attenStepSizeDiv); + + /* Write MSB bits followed by LSB bits, TxAtten updates when [7:0] written */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_TX2_ATTENUATION_1, ((data >> 8) & 0x03)); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_TX2_ATTENUATION_0, (data & 0xFF)); + + return MYKONOS_ERR_OK; +} + +/** + * \brief Reads back the Tx1 RF output Attenuation + * + * This function reads back the TxAttenuation setting currently applied to the transmit chain. + * The function will work with SPI mode or pin controlled TxAtten mode using the increment/decrement GPIO + * pins. For the readback value to be valid the Tx data path must be powered up. If the Tx data path + * is powered down or radioOff state, the last TxAtten setting while the Tx was powered up will be + * read back. + * + * Dependencies + * - device->spiSettings + * - device->spiSettings->chipSelectIndex + * + * \param device Pointer to the Mykonos device's data structure + * \param tx1Attenuation_mdB The readback value of the Tx1 Attenuation in milli-dB (Range: 0 to 41950 mdB) + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_GETTX1ATTEN_NULL_PARM tx1Attenuation_mdB return parameter has NULL pointer + */ +mykonosErr_t MYKONOS_getTx1Attenuation(mykonosDevice_t *device, uint16_t *tx1Attenuation_mdB) +{ + uint8_t txAttenLsb = 0; + uint8_t txAttenMsb = 0; + uint16_t attenStepSizeDiv = 50; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getTx1Attenuation()\n"); +#endif + + /* check return parameter pointer is not NULL pointer */ + if (tx1Attenuation_mdB == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETTX1ATTEN_NULL_PARM, + getMykonosErrorMessage(MYKONOS_ERR_GETTX1ATTEN_NULL_PARM)); + return MYKONOS_ERR_GETTX1ATTEN_NULL_PARM; + } + + /* Write TxAtten read back reg to update readback values, then read Tx1Atten */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_TX1_ATTENUATION_1_READBACK, 0x00); + CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_TX1_ATTENUATION_0_READBACK, &txAttenLsb, 0xFF, 0); + CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_TX1_ATTENUATION_1_READBACK, &txAttenMsb, 0x03, 0); + + /* Readback word always reads back with 0.05dB resolution */ + *tx1Attenuation_mdB = (uint16_t)(((uint16_t)(txAttenLsb) | ((uint16_t)(txAttenMsb) << 8)) * attenStepSizeDiv); + + return MYKONOS_ERR_OK; +} + +/** + * \brief Reads back the Tx2 RF output Attenuation + * + * This function reads back the TxAttenuation setting currently applied to the transmit chain. + * The function will work with SPI mode or pin controlled TxAtten mode using the increment/decrement GPIO + * pins. For the readback value to be valid the Tx data path must be powered up. If the Tx data path + * is powered down or radioOff state, the last TxAtten setting while the Tx was powered up will be + * read back. + * + * Dependencies + * - device->spiSettings + * - device->spiSettings->chipSelectIndex + * + * \param device Pointer to the Mykonos device's data structure + * \param tx2Attenuation_mdB The readback value of the Tx2 Attenuation in milli-dB (Range: 0 to 41950 mdB) + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_GETTX2ATTEN_NULL_PARM tx2Attenuation_mdB return parameter pointer is NULL + */ +mykonosErr_t MYKONOS_getTx2Attenuation(mykonosDevice_t *device, uint16_t *tx2Attenuation_mdB) +{ + uint8_t txAttenLsb = 0; + uint8_t txAttenMsb = 0; + uint16_t attenStepSizeDiv = 50; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getTx2Attenuation()\n"); +#endif + + /* check return parameter pointer is not NULL pointer */ + if (tx2Attenuation_mdB == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETTX2ATTEN_NULL_PARM, + getMykonosErrorMessage(MYKONOS_ERR_GETTX2ATTEN_NULL_PARM)); + return MYKONOS_ERR_GETTX2ATTEN_NULL_PARM; + } + + /* Write TxAtten read back reg to update readback values, then read Tx1Atten */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_TX2_ATTENUATION_1_READBACK, 0x00); + CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_TX2_ATTENUATION_0_READBACK, &txAttenLsb, 0xFF, 0); + CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_TX2_ATTENUATION_1_READBACK, &txAttenMsb, 0x03, 0); + + /* Readback word always reads back with 0.05dB resolution */ + *tx2Attenuation_mdB = (uint16_t)(((uint16_t)(txAttenLsb) | ((uint16_t)(txAttenMsb) << 8)) * attenStepSizeDiv); + + return MYKONOS_ERR_OK; +} + +/** + * \brief Checks the Tx Filter over-range bit assignments for digital clipping in the Tx data path + * + * Dependencies + * - device->spiSettings + * + * txFilterStatus bit-field assignments are: + * txFilterStatus[0] = TFIR Ch1 Overflow + * txFilterStatus[1] = HB1 Ch1 Overflow + * txFilterStatus[2] = HB2 Ch1 Overflow + * txFilterStatus[3] = QEC Ch1 Overflow + * txFilterStatus[4] = TFIR Ch2 Overflow + * txFilterStatus[5] = HB1 Ch2 Overflow + * txFilterStatus[6] = HB2 Ch2 Overflow + * txFilterStatus[7] = QEC Ch2 Overflow + * + * \param device Pointer to the Mykonos device's data structure + * \param txFilterStatus is an 8-bit Tx filter over-range status bit-field + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_GET_TXFILTEROVRG_NULL_PARM Function txFilterStatus parameter pointer is NULL + */ +mykonosErr_t MYKONOS_getTxFilterOverRangeStatus(mykonosDevice_t *device, uint8_t *txFilterStatus) +{ + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getTxFilterOverRangeStatus()\n"); +#endif + + if (txFilterStatus == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GET_TXFILTEROVRG_NULL_PARM, + getMykonosErrorMessage(MYKONOS_ERR_GET_TXFILTEROVRG_NULL_PARM)); + return MYKONOS_ERR_GET_TXFILTEROVRG_NULL_PARM; + } + + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_TX_FILTER_OVERFLOW, txFilterStatus); + return MYKONOS_ERR_OK; +} + +/** + * \brief Enables/Disables the Tx NCO test tone + * + * This function enables/disables a digital numerically controlled oscillator + * in the Mykonos Digital to create a test CW tone on Tx1 and Tx2 RF outputs. + * + * The TxAttenuation is forced in this function to max analog output power, but + * the digital attenuation is backed off 6dB to make sure the digital filter + * does not clip and cause spurs in the tx spectrum. + * + * Dependencies + * - device->spiSettings + * - device->profilesValid + * - device->tx->txProfile->iqRate_kHz + * + * \param device Pointer to the Mykonos device's data structure + * \param enable 0 = Disable Tx NCO, 1 = Enable Tx NCO on both transmitters + * \param tx1ToneFreq_kHz Signed frequency in kHz of the desired Tx1 tone + * \param tx2ToneFreq_kHz Signed frequency in kHz of the desired Tx2 tone + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_ENTXNCO_TXPROFILE_INVALID Can not enable Tx NCO when Tx Profile is not enabled/valid + * \retval MYKONOS_ERR_ENTXNCO_TX1_FREQ_INVALID Tx1 NCO Tone frequency out of range (-IQrate/2 to IQrate/2) + * \retval MYKONOS_ERR_ENTXNCO_TX2_FREQ_INVALID Tx2 NCO Tone frequency out of range (-IQrate/2 to IQrate/2) + */ +mykonosErr_t MYKONOS_enableTxNco(mykonosDevice_t *device, uint8_t enable, int32_t tx1ToneFreq_kHz, int32_t tx2ToneFreq_kHz) +{ + int16_t tx1NcoTuneWord = 0; + int16_t tx2NcoTuneWord = 0; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_enableTxNco()\n"); +#endif + + if (enable > 0) + { + if ((device->profilesValid & TX_PROFILE_VALID) == 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_ENTXNCO_TXPROFILE_INVALID, + getMykonosErrorMessage(MYKONOS_ERR_ENTXNCO_TXPROFILE_INVALID)); + return MYKONOS_ERR_ENTXNCO_TXPROFILE_INVALID; + } + + if ((tx1ToneFreq_kHz > ((int32_t)(device->tx->txProfile->iqRate_kHz) / 2)) || (tx1ToneFreq_kHz < ((int32_t)(device->tx->txProfile->iqRate_kHz) * -1 / 2))) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_ENTXNCO_TX1_FREQ_INVALID, + getMykonosErrorMessage(MYKONOS_ERR_ENTXNCO_TX1_FREQ_INVALID)); + return MYKONOS_ERR_ENTXNCO_TX1_FREQ_INVALID; + } + + if ((tx2ToneFreq_kHz > ((int32_t)(device->tx->txProfile->iqRate_kHz) / 2)) || (tx2ToneFreq_kHz < ((int32_t)(device->tx->txProfile->iqRate_kHz) * -1 / 2))) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_ENTXNCO_TX2_FREQ_INVALID, + getMykonosErrorMessage(MYKONOS_ERR_ENTXNCO_TX2_FREQ_INVALID)); + return MYKONOS_ERR_ENTXNCO_TX2_FREQ_INVALID; + } + + /* Force Tx output power to max analog output power, but 6dB digital */ + /* backoff to prevent the NCO from clipping the Tx PFIR filter */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_TX1_GAIN_0, 0x78); + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_TX1_GAIN_1, 0x00, 0x3F, 0); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_TX1_GAIN_2, 0x0); + + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_TX2_GAIN_0, 0x78); + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_TX2_GAIN_1, 0x00, 0x3F, 0); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_TX2_GAIN_2, 0x0); + + /* Enable manual Tx output power mode */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_TX_TPC_CONFIG, 0x0A, 0x0F, 0); + + /* Set Tx NCO tuning words */ + tx1NcoTuneWord = (int16_t)(((int64_t)(tx1ToneFreq_kHz) << 16) / device->tx->txProfile->iqRate_kHz * -1); + tx2NcoTuneWord = (int16_t)(((int64_t)(tx2ToneFreq_kHz) << 16) / device->tx->txProfile->iqRate_kHz * -1); + + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_TX_ABBF_FREQ_CAL_NCO_I_MSB, (uint8_t)((uint16_t)tx1NcoTuneWord >> 8)); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_TX_ABBF_FREQ_CAL_NCO_I_LSB, (tx1NcoTuneWord & 0xFF)); + + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_TX_ABBF_FREQ_CAL_NCO_Q_MSB, (uint8_t)((uint16_t)tx2NcoTuneWord >> 8)); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_TX_ABBF_FREQ_CAL_NCO_Q_LSB, (tx2NcoTuneWord & 0xFF)); + + /* Enable Tx NCO - set [7] = 1 */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_DIGITAL_TEST_BYTE_0, 1, 0x80, 7); + } + else + { + /* Disable Tx NCO - set [7] = 0 */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_DIGITAL_TEST_BYTE_0, 0, 0x80, 7); + + /* Enable normal Tx Atten table mode */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_TX_TPC_CONFIG, 0x05, 0x0F, 0); + } + + return MYKONOS_ERR_OK; +} + +/** + * \brief Writes Mykonos device registers with settings for the PA Protection block. + * + * This function writes register settings for the Mykonos PA Protection Block. + * This function does not enable the PA Protection functionality. + * Note that independent control of PA protection for both Tx channels is not possible. + * The PA Protection block allows for error flags to go high if the accumulated TX power in the data path + * exceeds a programmable threshold level based on samples taken in a programmable duration. + * + * \post After calling this function the user will need to call MYKONOS_enablePaProtection(...) + * + * Dependencies + * - device->spiSettings + * - device->spiSettings->chipSelectIndex + * + * \param device Pointer to the Mykonos device's data structure + * \param powerThreshold PA Protection Threshold sets the power level that, if detected in the TX data path, raises the PA error flags. The range is 0 to 4096. + * To calculate the required setting for the power threshold: + * powerThreshold = MAX_DAC_CODE * (10^((txPowerThresh_dBFS/10))) + * For example: If the required dBFS for the threshold is -10 dBFS, then the powerThreshold passed should be 409. + * + * \param attenStepSize Attenuation Step Size sets the size of the attenuation step when Tx Atten Control is Enabled. The range is 0 to 128 with a resolution is 0.2dB/LSB. + * \param avgDuration Averaging Duration for the TX data path power measurement. The range is 0 to 14 specified in number of cycles of the TX IQ Rate. + * \param stickyFlagEnable "1" Enables the PA Error Flags to stay high after being triggered, even if the power decreases below threshold. "0" disables this functionality. + * \param txAttenControlEnable "1" Enables autonomous attenuation changes in response to PA error flags. "0" disables this functionality. + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_SETUP_PA_PROT_INV_AVG_DURATION avgDuration parameter invalid (valid 0-15) + * \retval MYKONOS_ERR_SETUP_PA_PROT_INV_ATTEN_STEP attenStepSize function parameter invalid (valid 0-127) + */ +mykonosErr_t MYKONOS_setupPaProtection(mykonosDevice_t *device, uint16_t powerThreshold, uint8_t attenStepSize, uint8_t avgDuration, uint8_t stickyFlagEnable, uint8_t txAttenControlEnable) +{ + uint8_t paProtectConfig = 0; + uint8_t paProtectAttenCntl = 0; + + const uint8_t PROTECT_AVG_DUR_MASK = 0x1E; + const uint8_t STICKY_FLAG_EN_MASK = 0x40; + const uint8_t ATT_STEP_MASK = 0xFE; + const uint8_t PROTECT_ATT_EN_MASK = 0x01; + const uint8_t AVG_DUR_MASK = 0x0F; + const uint8_t ATT_STEP_SIZE = 0x7F; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setupPaProtection()\n"); +#endif + + /* Overwrite PA Protection Config register data with averaging duration and sticky flag. Also performing range check on stickyFlagEnable and avgDuration */ + if (avgDuration > AVG_DUR_MASK) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETUP_PA_PROT_INV_AVG_DURATION, + getMykonosErrorMessage(MYKONOS_ERR_SETUP_PA_PROT_INV_AVG_DURATION)); + return MYKONOS_ERR_SETUP_PA_PROT_INV_AVG_DURATION; + } + + if (attenStepSize > ATT_STEP_SIZE) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETUP_PA_PROT_INV_ATTEN_STEP, + getMykonosErrorMessage(MYKONOS_ERR_SETUP_PA_PROT_INV_ATTEN_STEP)); + return MYKONOS_ERR_SETUP_PA_PROT_INV_ATTEN_STEP; + } + + paProtectConfig = (PROTECT_AVG_DUR_MASK & (avgDuration << 1)); + + if (stickyFlagEnable > 0) + { + paProtectConfig |= (STICKY_FLAG_EN_MASK); + } + + paProtectAttenCntl = ATT_STEP_MASK & (attenStepSize << 1); + + if (txAttenControlEnable > 0) + { + paProtectAttenCntl |= (PROTECT_ATT_EN_MASK); + } + + /* Clear and write all PA Protection setup registers */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PA_PROTECTION_ATTEN_CONTROL, 0x00); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PA_PROTECTION_CONFIGURATION, 0x00); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PA_PROTECTION_THRESHOLD_LSB, 0x00); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PA_PROTECTION_THRESHOLD_MSB, 0x00); + + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PA_PROTECTION_ATTEN_CONTROL, paProtectAttenCntl); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PA_PROTECTION_CONFIGURATION, paProtectConfig); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PA_PROTECTION_THRESHOLD_LSB, (powerThreshold & 0xFF)); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PA_PROTECTION_THRESHOLD_MSB, ((powerThreshold >> 8) & 0x0F)); + + return MYKONOS_ERR_OK; +} + +/** + * \brief Enables the Mykonos PA Protection block according to the parameters passed in MYKONOS_setupPaProtection(...). + * + * This function enables the PA Protection block according to the parameters passed in MYKONOS_setupPaProtection(...) + * The paProtectEnable signal enables the PA Protection block, allowing usage of the PA protection functions. + * + * \pre Before calling this function the user needs to setup the PA protection by calling MYKONOS_setupPaProtection(...) + * + * Dependencies + * - device->spiSettings + * - device->spiSettings->chipSelectIndex + * + * \param device Pointer to the Mykonos device's data structure + * \param paProtectEnable "1" Enables the PA Protection block. "0" Disables the PA Protection block + * + * \retval MYKONOS_ERR_OK Function completed successfully + */ +mykonosErr_t MYKONOS_enablePaProtection(mykonosDevice_t *device, uint8_t paProtectEnable) +{ + uint8_t paProtectEnableReg = 0; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_enablePaProtection()\n"); +#endif + + paProtectEnableReg = (paProtectEnable > 0) ? 1 : 0; + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_PA_PROTECTION_CONFIGURATION, paProtectEnableReg, 0x01, 0); + + return MYKONOS_ERR_OK; +} + +/** + * \brief Obtains an estimate of a TX channel's accumulated power over the sample duration provided in MYKONOS_setupPaProtection(...) + * + * This function uses the 'avgDuration' parameter provided in MYKONOS_setupPaProtection to set the number of samples to accumulate + * to obtain an estimate for a TX channel specified by the 'channel' parameter. + * A 12-bit field estimating the channel power is returned in the '*channelPower' pointer. + * To obtain the dBFS value of the reading: + * dBFS value = 10*log10(channelPower/MAX_DAC_CODE) + * where MAX_DAC_CODE = 2^12 = 4096 + * For example: If channelPower is reading 409 then the channel power in dBFS is -10dBFS. + * + * Dependencies + * - device->spiSettings + * - device->spiSettings->chipSelectIndex + * + * \param device Point to the Mykonos device's data structure + * \param channel Select the channel of interest. Only use TX1 (1) or TX2 (2) of mykonosTxChannels_t + * \param *channelPower A pointer that stores the selected channels power. Read back is provided as a 12 bit value. + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_GET_DAC_PWR_INV_POINTER Function channelPower parameter is a NULL pointer + * \retval MYKONOS_ERR_SETUP_PA_PROT_INV_TX_CHANNEL Invalid Tx Channel passed in function channel parameter (TX1 or TX2) + */ +mykonosErr_t MYKONOS_getDacPower(mykonosDevice_t *device, mykonosTxChannels_t channel, uint16_t *channelPower) +{ + uint8_t channelPowerLsb = 0; + uint8_t channelPowerMsb = 0; + + const uint8_t CHAN_POWER_MSB_MASK = 0xF; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getDacPower()\n"); +#endif + + if (channelPower == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GET_DAC_PWR_INV_POINTER, + getMykonosErrorMessage(MYKONOS_ERR_GET_DAC_PWR_INV_POINTER)); + return MYKONOS_ERR_GET_DAC_PWR_INV_POINTER; + } + + /* Set bit D5 to read the appropriate channel power */ + switch (channel) + { + case TX1: + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_PA_PROTECTION_CONFIGURATION, 0, 0x20, 5); + break; + case TX2: + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_PA_PROTECTION_CONFIGURATION, 1, 0x20, 5); + break; + default: + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETUP_PA_PROT_INV_TX_CHANNEL, + getMykonosErrorMessage(MYKONOS_ERR_SETUP_PA_PROT_INV_TX_CHANNEL)); + return MYKONOS_ERR_SETUP_PA_PROT_INV_TX_CHANNEL; + } + + /* SPI Write to register PA Protection power readback registers (write strobe) */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PA_PROTECTION_POWER_READBACK_LSB, 0x00); + + /* SPI Read of the PA Protection power readback registers */ + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_PA_PROTECTION_POWER_READBACK_LSB, &channelPowerLsb); + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_PA_PROTECTION_POWER_READBACK_MSB, &channelPowerMsb); + + *channelPower = (channelPowerLsb | (((uint16_t)(channelPowerMsb & CHAN_POWER_MSB_MASK)) << 8)); + + return MYKONOS_ERR_OK; +} + +/** + * \brief Returns PA Protection Error Flag Status + * + * This function provides a readback of the PA protection Error Flag Status through the '*errorFlagStatus' pointer + * + * Dependencies + * - device->spiSettings + * - device->spiSettings->chipSelectIndex + * + * \param device Point to the Mykonos device's data structure + * \param errorFlagStatus Pointer to store the error flag status. + * errorFlagStatus | error + * -----------------|------------ + * 0 | indicates no PA Error Flags are high + * 1 | indicates TX1 Error Flag + * 2 | indicates TX2 Error Flag + * 3 | indicates TX1 and TX2 Error Flags are high + * + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_GET_PA_FLAG_STATUS_INV_POINTER Function errorFlagStatus parameter has NULL pointer + */ +mykonosErr_t MYKONOS_getPaProtectErrorFlagStatus(mykonosDevice_t *device, uint8_t *errorFlagStatus) +{ + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getPaProtectErrorFlagStatus()\n"); +#endif + + if (errorFlagStatus == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GET_PA_FLAG_STATUS_INV_POINTER, + getMykonosErrorMessage(MYKONOS_ERR_GET_PA_FLAG_STATUS_INV_POINTER)); + return MYKONOS_ERR_GET_PA_FLAG_STATUS_INV_POINTER; + } + + /* SPI Write to register PA Protection power readback registers (write strobe) */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PA_PROTECTION_POWER_READBACK_LSB, 0x00); + + /* SPI Read of the PA Protection power readback registers */ + CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_PA_PROTECTION_POWER_READBACK_MSB, errorFlagStatus, 0x60, 5); + + return MYKONOS_ERR_OK; +} + +/** + * \brief Manually clears the PA Protection Error Flags. + * + * This function manually clears the PA Error Flags. The user must setup the PA Protection block to enable + * sticky error flags. Sticky error flags require the user to clear the bit manually even if the accumulated power is + * below the power threshold for the PA protection block. + * + * Dependencies + * - device->spiSettings + * - device->spiSettings->chipSelectIndex + * + * \param device Pointer to the Mykonos device's data structure + * + * \retval MYKONOS_ERR_OK Function completed successfully + */ +mykonosErr_t MYKONOS_clearPaErrorFlag(mykonosDevice_t *device) +{ + uint8_t paProtectConfig = 0; + + const uint8_t PA_ERROR_CLEAR_MASK = 0x80; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_clearPaErrorFlag()\n"); +#endif + + /* SPI Read of the PA Protection power readback registers */ + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_PA_PROTECTION_CONFIGURATION, &paProtectConfig); + + /* SPI Write to self clear the PA Error Flags */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PA_PROTECTION_CONFIGURATION, (paProtectConfig | PA_ERROR_CLEAR_MASK)); + + return MYKONOS_ERR_OK; +} + +/** + * \brief Helper function for return of character string based on 32-bit mykonosErr_t enum value + * + * To save codespace, these error strings are ifdef'd out unless the user + * adds a define MYKONOS_VERBOSE to their workspace. This function can be + * useful for debug. Each function also returns unique error codes to + * make it easier to determine where the code broke. + * + * \param errorCode is enumerated error code value + * + * \return Returns character string based on enumerated value + */ +const char* getMykonosErrorMessage(mykonosErr_t errorCode) +{ +#ifndef MYKONOS_VERBOSE + return ""; + +#else + + switch (errorCode) + { + case MYKONOS_ERR_OK: + return ""; + case MYKONOS_ERR_INV_PARM: + return "Mykonos: Invalid parameter\n"; + case MYKONOS_ERR_FAILED: + return "Mykonos: General Failure\n"; + case MYKONOS_ERR_WAITFOREVENT_INV_PARM: + return "waitForEvent had invalid parameter.\n"; + case MYKONOS_ERR_WAITFOREVENT_TIMEDOUT: + return "waitForEvent timed out.\n"; + case MYKONOS_ERR_SETENSM_INVALID_NEWSTATE_WAIT: + return "Requested new ENSM state is invalid from the WAIT state.\n"; + case MYKONOS_ERR_SETENSM_INVALID_NEWSTATE_ALERT: + return "Requested new ENSM state is invalid from the ALERT state.\n"; + case MYKONOS_ERR_SETENSM_INVALID_NEWSTATE_TXRX: + return "Requested new ENSM state is invalid from the TXRX state.\n"; + case MYKONOS_ERR_SETENSM_INVALIDSTATE: + return "Current ENSM state is an invalid state or calibration state.\n"; + case MYKONOS_ERR_PU_RXPATH_INV_PARAM: + return "Invalid Rx channel was requested to be powered up.\n"; + case MYKONOS_ERR_PU_TXPATH_INV_PARAM: + return "Invalid Tx channel was requested to be powered up.\n"; + case MYKONOS_ERR_PU_OBSRXPATH_INV_PARAM: + return "Invalid ObsRx channel was requested to be powered up.\n"; + case MYKONOS_ERR_SETDEFOBSRXPATH_NULL_DEF_OBSRX_STRUCT: + return "Invalid default ObsRx channel was requested to be powered up.\n"; + case MYKONOS_ERR_INIT_INV_ORXCHAN: + return "Invalid ObsRx channel requested during initialize().\n"; + case MYKONOS_ERR_INIT_INV_RXSYNCB_ORXSYNCB_MODE: + return "Invalid combination for rxsyncb and orxsyncb, if shared syncb they should have the CMOS/LVDS mode\n"; + case MYKONOS_ERR_INIT_INV_TXFIR_INTERPOLATION: + return "Invalid TxFIR interpolation value.(Valid: 1,2,4)\n"; + case MYKONOS_ERR_INIT_INV_TXHB2_INTERPOLATION: + return "Invalid TXHB2 interpolation value.(Valid: 1 or 2)\n"; + case MYKONOS_ERR_INIT_INV_TXHB1_INTERPOLATION: + return "Invalid TXHB1 interpolation value.(Valid: 1 or 2)\n"; + case MYKONOS_ERR_INIT_INV_RXFIR_DECIMATION: + return "Invalid RxFIR decimation value.(Valid: 1,2,4)\n"; + case MYKONOS_ERR_INIT_INV_RXDEC5_DECIMATION: + return "Invalid Rx DEC5 decimation value.(Valid: 4 or 5)\n"; + case MYKONOS_ERR_INIT_INV_RXHB1_DECIMATION: + return "Invalid RxHB1 decimation value.(Valid: 1 or 2)\n"; + case MYKONOS_ERR_INIT_INV_SNIFFER_RHB1: + return "Invalid Sniffer HB1 decimation value (Valid 1 or 2)\n"; + case MYKONOS_ERR_INIT_INV_SNIFFER_RFIR_DEC: + return "Invalid Sniffer RFIR decimation value (Valid 1,2,4)\n"; + case MYKONOS_ERR_INIT_INV_ORX_RHB1: + return "Invalid ORx HB1 decimation value (Valid 1 or 2)\n"; + case MYKONOS_ERR_INIT_INV_ORX_RFIR_DEC: + return "Invalid ORx RFIR decimation value. (Valid 1,2,4)\n"; + case MYKONOS_ERR_INIT_INV_ADCDIV: + return "Invalid Rx ADC divider. (Valid 1 or 2)\n"; + case MYKONOS_ERR_INIT_INV_DACDIV: + return "Invalid Tx DAC divider. Use enum DACDIV_2, DACDIV_2p5 or DACDIV_4.\n"; + case MYKONOS_ERR_INIT_INV_OBSRX_ADCDIV: + return "Invalid ObsRx ADC div. (Valid 1 or 2)\n"; + case MYKONOS_ERR_CLKPLL_INV_HSDIV: + return "Invalid CLKPLL HSDIV. (Valid 4 or 5)\n"; + case MYKONOS_ERR_CLKPLL_INV_VCODIV: + return "Invalid CLKPLL VCODIV. Use enum VCODIV_1, VCODIV_1p5, VCODIV_2, VCODIV_3\n"; + case MYKONOS_ERR_CLKPLL_INV_RXTXPROFILES: + return "No Rx or Tx profile is specified.\n"; + case MYKONOS_ERR_SETCLKPLL_INV_VCOINDEX: + return "CLKPLL VCO frequency out of range.\n"; + case MYKONOS_ERR_SETCLKPLL_INV_FRACWORD: + return "CLKPLL fractional word is non zero.\n"; + case MYKONOS_ERR_SETRFPLL_INV_PLLNAME: + return "Invalid pllName requested in setRfPllFreuquency()\n"; + case MYKONOS_ERR_SETRFPLL_INV_LO_PARM: + return "RF PLL frequency out of range\n"; + case MYKONOS_ERR_GETRFPLL_INV_PLLNAME: + return "Invalid pllName requested in getRfPllFrequency()\n"; + case MYKONOS_ERR_GETRFPLL_ARMERROR: + return "ARM Command Error in MYKONOS_getRfPllFrequency()\n"; + case MYKONOS_ERR_GETRFPLL_NULLPARAM: + return "NULL pointer in function parameter for MYKONOS_setRfPllFrequency()\n"; + case MYKONOS_ERR_INV_SCALEDDEVCLK_PARAM: + return "Could not scale device clock into range 40MHz to 80Mhz.\n"; + case MYKONOS_ERR_SETRFPLL_INV_VCOINDEX: + return "RFPLL VCO frequency out of range.\n"; + case MYKONOS_ERR_SETRFPLL_INV_REFCLK: + return "Unsupported PLL reference clock or refclk out of range.\n"; + case MYKONOS_ERR_SETORXGAIN_INV_CHANNEL: + return "Invalid ObsRx channel in setObsRxManualGain().\n"; + case MYKONOS_ERR_SETORXGAIN_INV_ORX1GAIN: + return "Invalid gain requested in setObsRxManualGain() for ORX1\n"; + case MYKONOS_ERR_SETORXGAIN_INV_ORX2GAIN: + return "Invalid gain requested in setObsRxManualGain() for ORX2\n"; + case MYKONOS_ERR_SETORXGAIN_INV_SNRXGAIN: + return "Invalid gain requested in setObsRxManualGain() for Sniffer\n"; + case MYKONOS_ERR_GETORX1GAIN_INV_POINTER: + return "Cannot return ORx1 gain to gain control data structure (invalid pointer).\n"; + case MYKONOS_ERR_GETORX2GAIN_INV_POINTER: + return "Cannot return ORx2 gain to gain control data structure (invalid pointer).\n"; + case MYKONOS_ERR_GETSNIFFGAIN_INV_POINTER: + return "Cannot return Sniffer gain to gain control data structure (invalid pointer).\n"; + case MYKONOS_ERR_GETOBSRXGAIN_CH_DISABLED: + return "Cannot read ObsRx gain index. ObsRx Channel is disabled.\n"; + case MYKONOS_ERR_SETTX1ATTEN_INV_PARM: + return "Tx1 attenuation is out of range (0 - 41950 mdB).\n"; + case MYKONOS_ERR_SETTX1ATTEN_INV_STEPSIZE_PARM: + return "Invalid Tx1Atten stepsize. Use enum mykonosTxAttenStepSize_t\n"; + case MYKONOS_ERR_SETTX2ATTEN_INV_PARM: + return "Tx2 attenuation is out of range (0 - 41950 mdB).\n"; + case MYKONOS_ERR_SETTX2ATTEN_INV_STEPSIZE_PARM: + return "Invalid Tx2Atten stepsize. Use enum mykonosTxAttenStepSize_t\n"; + case MYKONOS_ERR_PROGRAMFIR_INV_NUMTAPS_PARM: + return "Invalid number of FIR taps\n"; + case MYKONOS_ERR_READFIR_INV_NUMTAPS_PARM: + return "Invalid number of FIR taps read for the selected Filter\n"; + case MYKONOS_ERR_PROGRAMFIR_INV_FIRNAME_PARM: + return "Invalid FIR filter name requested. use enum mykonosfirName_t\n"; + case MYKONOS_ERR_RXFIR_INV_GAIN_PARM: + return "Rx FIR filter has invalid gain setting\n"; + case MYKONOS_ERR_OBSRXFIR_INV_GAIN_PARM: + return "ObsRx FIR filter A (ORx) has invalid gain setting\n"; + case MYKONOS_ERR_SRXFIR_INV_GAIN_PARM: + return "ObsRx FIR filter B (Sniffer) has invalid gain setting\n"; + case MYKONOS_ERR_TXFIR_INV_GAIN_PARM: + return "Tx FIR filter has invalid gain setting\n"; + case MYKONOS_ERR_READFIR_NULL_PARM: + return "MYKONOS_readFir() has a null *firFilter parameter\n"; + case MYKONOS_ERR_READFIR_COEFS_NULL: + return "MYKONOS_readFir() has a null coef array in *firFilter structure\n"; + case MYKONOS_ERR_READFIR_INV_FIRNAME_PARM: + return "Invalid FIR filter name requested. use enum mykonosfirName_t\n"; + case MYKONOS_ERR_SETRX1GAIN_INV_GAIN_PARM: + return "Rx1 manual gain index out of range of gain table\n"; + case MYKONOS_ERR_SETRX2GAIN_INV_GAIN_PARM: + return "Rx2 manual gain index out of range of gain table\n"; + case MYKONOS_ERR_INITSER_INV_VCODIV_PARM: + return "Found invalid VCO divider value during setupSerializers()\n"; + case MYKONOS_ERR_INITSER_INV_VCODIV1_HSCLK_PARM: + return "CLKPLL VCO frequency exceeded max(8Ghz) in VCO divider /1 case ()\n"; + case MYKONOS_ERR_INITSER_INV_VCODIV1P5_HSCLK_PARM: + return "CLKPLL VCO frequency exceeded max(9.216Ghz) in VCO divider /1.5 case ()\n"; + case MYKONOS_ERR_INITDES_INV_VCODIV_PARM: + return "Found invalid VCO divider value during setupDeserializers()\n"; + case MYKONOS_ERR_SER_INV_M_PARM: + return "Invalid JESD Framer M parameter during setupSerializers()\n"; + case MYKONOS_ERR_SER_INV_L_PARM: + return "Invalid JESD Framer L parameter during setupSerializers()\n"; + case MYKONOS_ERR_SER_INV_LANERATE_PARM: + return "Invalid Lanerate frequency in setupSerializer()\n"; + case MYKONOS_ERR_SER_INV_LANEEN_PARM: + return "Invalid number of JESD204 lanes enabled.\n"; + case MYKONOS_ERR_SER_INV_AMP_PARM: + return "Invalid JESD204 serializer amplitude\n"; + case MYKONOS_ERR_SER_INV_PREEMP_PARM: + return "Invalid JESD204 serializer preemphasis setting\n"; + case MYKONOS_ERR_SER_INV_LANEPN_PARM: + return "Invald JESD204 serializer PN invert setting\n"; + case MYKONOS_ERR_SER_LANE_CONFLICT_PARM: + return "Rx framer and ObsRx framer are attempting to use the same physical lanes\n"; + case MYKONOS_ERR_SER_INV_TXSER_DIV_PARM: + return "Invalid serializer lane clock divider\n"; + case MYKONOS_ERR_SER_LANE_RATE_CONFLICT_PARM: + return "Rx lane and ObsRx lane rate must match\n"; + case MYKONOS_ERR_SER_INV_REAL_IF_DATA_PARM: + return "Framer M can only =1 if Real IF data option is enabled\n"; + case MYKONOS_ERR_HS_AND_LANE_RATE_NOT_INTEGER_MULT: + return "Serializer HSCLK and lane clock are not integer multiples\n"; + case MYKONOS_ERR_DES_HS_AND_LANE_RATE_NOT_INTEGER_MULT: + return "Deserializer HSCLK and lane clock are not integer multiples\n"; + case MYKONOS_ERR_DESER_INV_M_PARM: + return "Invalid deserializer M value. (Valid 2 or 4)\n"; + case MYKONOS_ERR_DESER_INV_L_PARM: + return "Invalid deserializer L value. (Valid 1,2,4)\n"; + case MYKONOS_ERR_DESER_INV_HSCLK_PARM: + return "Invalid HSCLK in setupDeserializer()\n"; + case MYKONOS_ERR_DESER_INV_LANERATE_PARM: + return "Invalid deserializer lane rate\n"; + case MYKONOS_ERR_DESER_INV_LANEEN_PARM: + return "Invalid number of deserializer lanes enabled\n"; + case MYKONOS_ERR_DESER_INV_EQ_PARM: + return "Invalid deserializer EQ setting"; + case MYKONOS_ERR_DESER_INV_LANEPN_PARM: + return "Invalid deserializer invert Lane PN setting\n"; + case MYKONOS_ERR_FRAMER_INV_M_PARM: + return "Invalid Rx framer M setting\n"; + case MYKONOS_ERR_FRAMER_INV_BANKID_PARM: + return "Invalid Rx framer Bank ID\n"; + case MYKONOS_ERR_FRAMER_INV_LANEID_PARM: + return "Invalid Rx framer Lane ID\n"; + case MYKONOS_ERR_FRAMER_INV_K_OFFSET_PARAM: + return "Invalid Rx framer LMFC offset\n"; + case MYKONOS_ERR_FRAMER_INV_REAL_IF_DATA_PARM: + return "Invalid Rx framer Real IF setting\n"; + case MYKONOS_ERR_OBSRX_FRAMER_INV_M_PARM: + return "Invalid ObsRx Framer M value\n"; + case MYKONOS_ERR_OBSRX_FRAMER_INV_BANKID_PARM: + return "Invalid ObsRx Framer Bank ID\n"; + case MYKONOS_ERR_OBSRX_FRAMER_INV_LANEID_PARM: + return "Invalid ObsRx framer Lane ID\n"; + case MYKONOS_ERR_OBSRX_FRAMER_INV_K_OFFSET_PARAM: + return "Invalid ObsRx framer LMFC offset\n"; + case MYKONOS_ERR_OBSRX_FRAMER_INV_REAL_IF_DATA_PARM: + return "Invalid ObsRx framer Real IF setting, M must =1\n"; + case MYKONOS_ERR_DEFRAMER_INV_M_PARM: + return "Invalid Deframer M setting\n"; + case MYKONOS_ERR_DEFRAMER_INV_BANKID_PARM: + return "Invalid Deframer Bank ID\n"; + case MYKONOS_ERR_ERR_DEFRAMER_INV_LANEID_PARM: + return "Invalid Deframer Lane ID\n"; + case MYKONOS_ERR_DEFRAMER_INV_K_OFFSET_PARAM: + return "Invalid Deframer LMFC offset"; + case MYKONOS_ERR_DEFRAMER_INV_K_PARAM: + return "Invalid Deframer K setting\n"; + case MYKONOS_ERR_DEFRAMER_INV_FK_PARAM: + return "Invalid Deframer F*K value\n"; + case MYKONOS_ERR_RX_FRAMER_INV_PRBS_POLYORDER_PARAM: + return "Invalid polyOrder parameter in enableRxFramerPrbs()\n"; + case MYKONOS_ERR_OBSRX_FRAMER_INV_PRBS_POLYORDER_PARAM: + return "Invalid polyOrder parameter in enableObsRxFramerPrbs()\n"; + case MYKONOS_ERR_DEFRAMER_INV_PRBS_ENABLE_PARAM: + return "Invalid enable parameter value in enableDeframerPrbsChecker()\n"; + case MYKONOS_ERR_DEFRAMER_INV_PRBS_POLYORDER_PARAM: + return "Invalid polyOrder parameter in enableDeframerPrbsChecker()\n"; + case MYKONOS_ERR_DEFRAMER_INV_PRBS_CNTR_SEL_PARAM: + return "Invalid lane counter select in readDeframerPrbsCounters()\n"; + case MYKONOS_ERR_INITARM_INV_DATARATE_PARM: + return 0; + case MYKONOS_ERR_INITARM_INV_VCODIV: + return "Invalid ARM VCO divider\n"; + case MYKONOS_ERR_INITARM_INV_REGCLK: + return "Invalid ARM SPI register clock rate\n"; + case MYKONOS_ERR_INITARM_INV_ARMCLK_PARAM: + return "Invalid ARM clock rate\n"; + case MYKONOS_ERR_LOADHEX_INV_CHARCOUNT: + return "LoadHex() char count = 0\n"; + case MYKONOS_ERR_LOADHEX_INVALID_FIRSTCHAR: + return "LoadHex() First char is not :\n"; + case MYKONOS_ERR_LOADHEX_INVALID_CHKSUM: + return "LoadHex() line checksum is invalid\n"; + case MYKONOS_ERR_LOADBIN_INVALID_BYTECOUNT: + return "Invalid byte count passed to function MYKONOS_loadArmFromBinary()"; + case MYKONOS_ERR_LOADARMCON_INVALID_BYTECOUNT: + return "Invalid byte count passed to function MYKONOS_loadArmConcurrent()"; + case MYKONOS_ERR_ARM_INVALID_BUILDCHKSUM: + return "Verify ARM checksum failed\n"; + case MYKONOS_ERR_READARMMEM_INV_ADDR_PARM: + return "ReadArmMem() was given an invalid memory address\n"; + case MYKONOS_ERR_WRITEARMMEM_INV_ADDR_PARM: + return "WriteArmMem() was given an invalid memory address\n"; + case MYKONOS_ERR_ARM_INV_ADDR_PARM: + return "Invalid memory address in MYKONOS_loadArmConcurrent()"; + case MYKONOS_ERR_ARMCMD_INV_OPCODE_PARM: + return "Invalid ARM opcode given to sendArmCommand()\n"; + case MYKONOS_ERR_ARMCMD_INV_NUMBYTES_PARM: + return "Invalid number of extended data in sendArmCommand()\n"; + case MYKONOS_ERR_ARMCMDSTATUS_INV_OPCODE_PARM: + return "Invalid opcode given to waitArmCmdStatus()\n"; + case MYKONOS_ERR_CHECKDEVSTRUCT_NULLDEVPOINTER: + return "Pointer to Mykonos device data structure is NULL\n"; + case MYKONOS_ERR_CHECKDEVSTRUCT_SPI: + return "Invalid spiSettings pointer in device data structure\n"; + case MYKONOS_ERR_CHECKDEVSTRUCT_RX: + return "Invalid device->rx pointer in device data structure\n"; + case MYKONOS_ERR_CHECKDEVSTRUCT_RXSUB: + return "Invalid pointer within device->rx data structure\n"; + case MYKONOS_ERR_CHECKDEVSTRUCT_RXFIR: + return "Invalid RXFIR pointer in device data structure\n"; + case MYKONOS_ERR_CHECKDEVSTRUCT_TX: + return "Invalid device->tx pointer in device data structure\n"; + case MYKONOS_ERR_CHECKDEVSTRUCT_TXSUB: + return "Invalid pointer within device->tx data structure\n"; + case MYKONOS_ERR_CHECKDEVSTRUCT_TXFIR: + return "Invalid TXFIR pointer in device data structure\n"; + case MYKONOS_ERR_CHECKDEVSTRUCT_OBSRX: + return "Invalid device->obsRx pointer in device data structure\n"; + case MYKONOS_ERR_CHECKDEVSTRUCT_OBSRXSUB: + return "Invalid pointer within device->obsRx data structure\n"; + case MYKONOS_ERR_CHECKDEVSTRUCT_SNIFFERFIR: + return "Invalid Sniffer FIR pointer in device data structure\n"; + case MYKONOS_ERR_CHECKDEVSTRUCT_ORXFIR: + return "Invalid ORX FIR pointer in device data structure\n"; + case MYKONOS_ERR_CHECKDEVSTRUCT_ORXGAINCTRL: + return "Invalid Orx gain control pointer in device data structure\n"; + case MYKONOS_ERR_CHECKDEVSTRUCT_SNIFFERGAINCTRL: + return "Invalid Sniffer gain control pointer in device data structure\n"; + case MYKONOS_ERR_CHECKDEVSTRUCT_OBSRXFRAMER: + return "Invalid obsRx framer pointer in device data structure\n"; + case MYKONOS_ERR_INITSER_INV_PROFILE: + return "Invalid RX profile within device data structure detected in MYKONOS_setupSerializers()\n"; + case MYKONOS_ERR_INITDES_INV_TXPROFILE: + return "Invalid TX profile within device data structure detected in MYKONOS_setupDeserializers()\n"; + case MYKONOS_ERR_JESD204B_ILAS_MISMATCH: + return "Mismatch detected in MYKONOS_jesd204bIlasCheck()\n"; + case MYKONOS_ERR_RXGAINTABLE_INV_CHANNEL: + return "Invalid channel specified in MYKONOS_programRxGainTable()\n"; + case MYKONOS_ERR_RXGAINTABLE_INV_GAIN_INDEX_RANGE: + return "Invalid numGainIndicesinTable greater than possible number of gain indices for channel. \n"; + case MYKONOS_ERR_WRITE_CFG_MEMORY_FAILED: + return "Failed write to ARM memory in MYKONOS_writeArmProfile()\n"; + case MYKONOS_ERR_INV_RXFRAMER_PCLKDIV_PARM: + return "Invalid PCLKDIV parameter detected in MYKONOS_setupSerializers()\n"; + case MYKONOS_ERR_RXFRAMER_INV_FK_PARAM: + return "Invalid FK parameter detected in MYKONOS_setupJesd204bFramer()\n"; + case MYKONOS_ERR_OBSRXFRAMER_INV_FK_PARAM: + return "Invalid FK paramter detected in MYKONOS_setupJesd204bObsRxFramer()\n"; + case MYKONOS_ERR_INV_OBSRXFRAMER_PCLKDIV_PARM: + return "Invalid PCLKDIV paramter detected in MYKONOS_setupSerializers()\n"; + case MYKONOS_ERR_PU_OBSRXPATH_INV_LOSOURCE_PARAM: + return "Invalid LO Source for OBSRX data path \n"; + case MYKONOS_ERR_ARM_RADIOON_FAILED: + return "ARM command to move to radioOn state failed. \n"; + case MYKONOS_ERR_ARM_RADIOOFF_FAILED: + return "ARM command to move to radioOff state failed. \n"; + case MYKONOS_ERR_INV_RX_GAIN_MODE_PARM: + return "Invalid gain control mode detected in MYKONOS_setRxGainControlMode()\n"; + case MYKONOS_ERR_INV_ORX_GAIN_MODE_PARM: + return "Invalid gain control mode detected in MYKONOS_setObsRxGainControlMode()\n"; + case MYKONOS_ERR_INV_AGC_RX_STRUCT_INIT: + return "Invalid RX AGC structure detected at &device->rx->rxAgcCtrl in MYKONOS_setupRxAgc()\n"; + case MYKONOS_ERR_INV_AGC_RX_PEAK_WAIT_TIME_PARM: + return "device->rx->rxAgcCtrl->agcPeakWaitTime out of range in MYKONOS_setupRxAgc()\n"; + case MYKONOS_ERR_INV_AGC_RX_GAIN_UPDATE_TIME_PARM: + return "device->rx->rxAgcCtrl->agcGainUpdateTime_us out of range in MYKONOS_setupRxAgc()\n"; + case MYKONOS_ERR_INV_AGC_RX_APD_HIGH_THRESH_PARM: + return "device->rx->rxAgcCtrl->apdHighThresh out of range in MYKONOS_setupRxAgc()\n"; + case MYKONOS_ERR_INV_AGC_RX_APD_LOW_THRESH_PARM: + return "device->rx->rxAgcCtrl->apdLowThresh out of range in MYKONOS_setupRxAgc()\n"; + case MYKONOS_ERR_INV_AGC_RX_BLOCK_DET_DECAY_PARM: + return "device->rx->rxAgcCtrl->apdDecay out of range in MYKONOS_setupRxAgc()\n"; + case MYKONOS_ERR_INV_AGC_RX_PEAK_STRUCT_INIT: + return "Data structure for peakAgc not initialized when used in MYKONOS_setupRxAgc() \n"; + case MYKONOS_ERR_INV_AGC_RX_PWR_STRUCT_INIT: + return "Data structure for powerAgc not initialized when used in MYKONOS_setupRxAgc() \n"; + case MYKONOS_ERR_INV_AGC_RX1_MAX_GAIN_INDEX: + return "device->rx->rxAgcCtrl->agcRx1MaxGainIndex out of range in MYKONOS_setupRxAgc() \n"; + case MYKONOS_ERR_INV_AGC_RX1_MIN_GAIN_INDEX: + return "device->rx->rxAgcCtrl->agcRx1MinGainIndex out of range in MYKONOS_setupRxAgc() \n"; + case MYKONOS_ERR_INV_AGC_RX2_MAX_GAIN_INDEX: + return "device->rx->rxAgcCtrl->agcRx2MaxGainIndex out of range in MYKONOS_setupRxAgc() \n"; + case MYKONOS_ERR_INV_AGC_RX2_MIN_GAIN_INDEX: + return "device->rx->rxAgcCtrl->agcRx2MinGainIndex out of range in MYKONOS_setupRxAgc() \n"; + case MYKONOS_ERR_INV_AGC_RX_SLOW_LOOP_SETTLING_DELAY: + return "device->rx->rxAgcCtrl->agcSlowLoopSettlingDelay out of range in MYKONOS_setupRxAgc() \n"; + case MYKONOS_ERR_INV_AGC_PMD_MEAS_DURATION: + return "device->rx->rxAgcCtrl->powerAgc->pmdMeasDuration out of range in MYKONOS_setupRxAgc() \n"; + case MYKONOS_ERR_INV_AGC_PMD_MEAS_CONFIG: + return "device->rx->rxAgcCtrl->powerAgc->pmdMeasConfig out of range in MYKONOS_setupRxAgc() \n"; + case MYKONOS_ERR_INV_AGC_RX_LOW_THS_PREV_GAIN_INC: + return "device->rx->rxAgcCtrl->agcLowThsPreventGainIncrease out of range in MYKONOS_setupRxAgc() \n"; + case MYKONOS_ERR_INV_AGC_RX_PEAK_THRESH_MODE: + return "device->rx->rxAgcCtrl->agcPeakThresholdMode out of range in MYKONOS_setupRxAgc() \n"; + case MYKONOS_ERR_INV_AGC_RX_RESET_ON_RX_ENABLE: + return "device->rx->rxAgcCtrl->agcResetOnRxEnable out of range in MYKONOS_setupRxAgc() \n"; + case MYKONOS_ERR_INV_AGC_RX_ENABLE_SYNC_PULSE_GAIN_COUNTER: + return "device->rx->rxAgcCtrl->agcEnableSyncPulseForGainCounter out of range in MYKONOS_setupRxAgc() \n"; + case MYKONOS_ERR_INV_AGC_RX_PMD_LOWER_HIGH_THRESH: + return "device->rx->rxAgcCtrl->powerAgc->pmdLowerHighThresh out of range in MYKONOS_setupRxAgc() \n"; + case MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_LOW_THRESH: + return "device->rx->rxAgcCtrl->powerAgc->pmdUpperLowThresh out of range in MYKONOS_setupRxAgc() \n"; + case MYKONOS_ERR_INV_AGC_RX_PMD_LOWER_LOW_THRESH: + return "device->rx->rxAgcCtrl->powerAgc->pmdLowerLowThresh out of range in MYKONOS_setupRxAgc() \n"; + case MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_HIGH_THRESH: + return "device->rx->rxAgcCtrl->powerAgc->pmdUpperHighThresh out of range in MYKONOS_setupRxAgc() \n"; + case MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_HIGH_GAIN_STEP: + return "device->rx->rxAgcCtrl->powerAgc->pmdUpperHighGainStepAttack out of range in MYKONOS_setupRxAgc() \n"; + case MYKONOS_ERR_INV_AGC_RX_PMD_LOWER_LOW_GAIN_STEP: + return "device->rx->rxAgcCtrl->powerAgc->pmdLowerLowGainStepRecovery out of range in MYKONOS_setupRxAgc() \n"; + case MYKONOS_ERR_INV_AGC_RX_PMD_LOWER_HIGH_GAIN_STEP: + return "device->rx->rxAgcCtrl->powerAgc->pmdLowerHighGainStepRecovery out of range in MYKONOS_setupRxAgc() \n"; + case MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_LOW_GAIN_STEP: + return "device->rx->rxAgcCtrl->powerAgc->pmdUpperLowGainStepAttack out of range in MYKONOS_setupRxAgc() \n"; + case MYKONOS_ERR_INV_AGC_RX_PKDET_FAST_ATTACK_VALUE: + return "device->rx->rxAgcCtrl->peakAgc->apdFastAttack or hb2FastAttack out of range in MYKONOS_setupRxAgc() \n"; + case MYKONOS_ERR_INV_AGC_RX_HB2_HIGH_THRESH_PARM: + return "device->rx->rxAgcCtrl->peakAgc->hb2HighThresh out of range in MYKONOS_setupRxAgc() \n"; + case MYKONOS_ERR_INV_AGC_RX_HB2_LOW_THRESH_PARM: + return "device->rx->rxAgcCtrl->peakAgc->hb2LowThresh out of range in MYKONOS_setupRxAgc() \n"; + case MYKONOS_ERR_INV_AGC_RX_HB2_VERY_LOW_THRESH_PARM: + return "device->rx->rxAgcCtrl->peakAgc->hb2VeryLowThresh out of range in MYKONOS_setupRxAgc() \n"; + case MYKONOS_ERR_INV_AGC_RX_APD_HIGH_GAIN_STEP_PARM: + return "device->rx->rxAgcCtrl->peakAgc->apdHighGainStepAttack out of range in MYKONOS_setupRxAgc() \n"; + case MYKONOS_ERR_INV_AGC_RX_APD_LOW_GAIN_STEP_PARM: + return "device->rx->rxAgcCtrl->peakAgc->apdLowGainStepRecovery out of range in MYKONOS_setupRxAgc() \n"; + case MYKONOS_ERR_INV_AGC_RX_HB2_HIGH_GAIN_STEP_PARM: + return "device->rx->rxAgcCtrl->peakAgc->hb2HighGainStepAttack out of range in MYKONOS_setupRxAgc() \n"; + case MYKONOS_ERR_INV_AGC_RX_HB2_LOW_GAIN_STEP_PARM: + return "device->rx->rxAgcCtrl->peakAgc->hb2LowGainStepRecovery out of range in MYKONOS_setupRxAgc() \n"; + case MYKONOS_ERR_INV_AGC_RX_HB2_VERY_LOW_GAIN_STEP_PARM: + return "device->rx->rxAgcCtrl->peakAgc->hb2VeryLowGainStepRecovery out of range in MYKONOS_setupRxAgc() \n"; + case MYKONOS_ERR_INV_AGC_RX_HB2_OVLD_ENABLE: + return "device->rx->rxAgcCtrl->peakAgc->hb2OverloadEnable out of range in MYKONOS_setupRxAgc() \n"; + case MYKONOS_ERR_INV_AGC_RX_HB2_OVLD_THRESH_CNT: + return "device->rx->rxAgcCtrl->peakAgc->hb2OverloadThreshCnt out of range in MYKONOS_setupRxAgc() \n"; + case MYKONOS_ERR_INV_AGC_RX_HB2_OVLD_DUR_CNT: + return "device->rx->rxAgcCtrl->peakAgc->hb2OverloadDurationCnt out of range in MYKONOS_setupRxAgc() \n"; + case MYKONOS_ERR_INV_AGC_OBSRX_STRUCT_INIT: + return "Invalid OBSRX AGC structure detected at &device->obsRx->orxAgcCtrl in MYKONOS_setupObsRxAgc()\n"; + case MYKONOS_ERR_INV_AGC_OBSRX_PEAK_STRUCT_INIT: + return "Data structure for obsRx->orxAgcCtrl->peakAgc not initialized when used in MYKONOS_setupObsRxAgc() \n"; + case MYKONOS_ERR_INV_AGC_OBSRX_PWR_STRUCT_INIT: + return "Data structure for obsRx->orxAgcCtrl->powerAgc not initialized when used in MYKONOS_setupObsRxAgc() \n"; + case MYKONOS_ERR_INV_AGC_OBSRX_MAX_GAIN_INDEX: + return "device->obsRx->orxAgcCtrl->agcObsRxMaxGainIndex out of range in MYKONOS_setupObsRxAgc() \n"; + case MYKONOS_ERR_INV_AGC_OBSRX_MIN_GAIN_INDEX: + return "device->obsRx->orxAgcCtrl->agcObsRxMinGainIndex out of range in MYKONOS_setupObsRxAgc() \n"; + case MYKONOS_ERR_INV_AGC_OBSRX_SELECT: + return "device->obsRx->orxAgcCtrl->agcObsRxSelect out of range in MYKONOS_setupObsRxAgc() \n"; + case MYKONOS_ERR_INV_AGC_OBSRX_GAIN_UPDATE_TIME_PARM: + return "device->obsRx->orxAgcCtrl->agcGainUpdateTime_us out of range in MYKONOS_setupObsRxAgc()\n"; + case MYKONOS_ERR_INV_AGC_OBSRX_PEAK_WAIT_TIME_PARM: + return "device->obsRx->orxAgcCtrl->agcPeakWaitTime out of range in MYKONOS_setupObsRxAgc()\n"; + case MYKONOS_ERR_INV_AGC_OBSRX_SLOW_LOOP_SETTLING_DELAY: + return "device->obsRx->orxAgcCtrl->agcSlowLoopSettlingDelay out of range in MYKONOS_setupObsRxAgc() \n"; + case MYKONOS_ERR_INV_AGC_OBSRX_PMD_MEAS_DURATION: + return "device->obsRx->orxAgcCtrl->powerAgc->pmdMeasDuration out of range in MYKONOS_setupObsRxAgc() \n"; + case MYKONOS_ERR_INV_AGC_OBSRX_PMD_MEAS_CONFIG: + return "device->obsRx->orxAgcCtrl->powerAgc->pmdMeasConfig out of range in MYKONOS_setupObsRxAgc() \n"; + case MYKONOS_ERR_INV_AGC_OBSRX_LOW_THS_PREV_GAIN_INC: + return "device->obsRx->orxAgcCtrl->agcLowThsPreventGainIncrease out of range in MYKONOS_setupObsRxAgc() \n"; + case MYKONOS_ERR_INV_AGC_OBSRX_PEAK_THRESH_MODE: + return "device->obsRx->orxAgcCtrl->agcPeakThresholdMode out of range in MYKONOS_setupObsRxAgc() \n"; + case MYKONOS_ERR_INV_AGC_OBSRX_RESET_ON_RX_ENABLE: + return "device->obsRx->orxAgcCtrl->agcResetOnRxEnable out of range in MYKONOS_setupObsRxAgc() \n"; + case MYKONOS_ERR_INV_AGC_OBSRX_ENABLE_SYNC_PULSE_GAIN_COUNTER: + return "device->obsRx->orxAgcCtrl->agcEnableSyncPulseForGainCounter out of range in MYKONOS_setupObsRxAgc() \n"; + case MYKONOS_ERR_INV_AGC_OBSRX_PMD_LOWER_HIGH_THRESH: + return "device->obsRx->orxAgcCtrl->powerAgc->pmdLowerHighThresh out of range in MYKONOS_setupObsRxAgc() \n"; + case MYKONOS_ERR_INV_AGC_OBSRX_PMD_UPPER_LOW_THRESH: + return "device->obsRx->orxAgcCtrl->powerAgc->pmdUpperLowThresh out of range in MYKONOS_setupObsRxAgc() \n"; + case MYKONOS_ERR_INV_AGC_OBSRX_PMD_LOWER_LOW_THRESH: + return "device->obsRx->orxAgcCtrl->powerAgc->pmdLowerLowThresh out of range in MYKONOS_setupObsRxAgc() \n"; + case MYKONOS_ERR_INV_AGC_OBSRX_PMD_UPPER_HIGH_THRESH: + return "device->obsRx->orxAgcCtrl->powerAgc->pmdUpperHighThresh out of range in MYKONOS_setupObsRxAgc() \n"; + case MYKONOS_ERR_INV_AGC_OBSRX_PMD_UPPER_HIGH_GAIN_STEP: + return "device->obsRx->orxAgcCtrl->powerAgc->pmdUpperHighGainStepAttack out of range in MYKONOS_setupObsRxAgc() \n"; + case MYKONOS_ERR_INV_AGC_OBSRX_PMD_LOWER_LOW_GAIN_STEP: + return "device->obsRx->orxAgcCtrl->powerAgc->pmdLowerLowGainStepRecovery out of range in MYKONOS_setupObsRxAgc() \n"; + case MYKONOS_ERR_INV_AGC_OBSRX_PMD_UPPER_LOW_GAIN_STEP: + return "device->obsRx->orxAgcCtrl->powerAgc->pmdUpperLowGainStepAttack out of range in MYKONOS_setupObsRxAgc() \n"; + case MYKONOS_ERR_INV_AGC_OBSRX_PKDET_FAST_ATTACK_VALUE: + return "device->obsRx->orxAgcCtrl->peakAgc->apdFastAttack or hb2FastAttack out of range in MYKONOS_setupObsRxAgc() \n"; + case MYKONOS_ERR_INV_AGC_OBSRX_APD_HIGH_THRESH_PARM: + return "device->obsRx->orxAgcCtrl->apdHighThresh out of range in MYKONOS_setupObsRxAgc()\n"; + case MYKONOS_ERR_INV_AGC_OBSRX_APD_LOW_THRESH_PARM: + return "device->obsRx->orxAgcCtrl->apdLowThresh out of range in MYKONOS_setupObsRxAgc()\n"; + case MYKONOS_ERR_INV_AGC_OBSRX_HB2_HIGH_THRESH_PARM: + return "device->obsRx->orxAgcCtrl->peakAgc->hb2HighThresh out of range in MYKONOS_setupObsRxAgc() \n"; + case MYKONOS_ERR_INV_AGC_OBSRX_HB2_LOW_THRESH_PARM: + return "device->obsRx->orxAgcCtrl->peakAgc->hb2LowThresh out of range in MYKONOS_setupObsRxAgc() \n"; + case MYKONOS_ERR_INV_AGC_OBSRX_HB2_VERY_LOW_THRESH_PARM: + return "device->obsRx->orxAgcCtrl->peakAgc->hb2VeryLowThresh out of range in MYKONOS_setupObsRxAgc() \n"; + case MYKONOS_ERR_INV_AGC_OBSRX_APD_HIGH_GAIN_STEP_PARM: + return "device->obsRx->orxAgcCtrl->peakAgc->apdHighGainStepAttack out of range in MYKONOS_setupObsRxAgc() \n"; + case MYKONOS_ERR_INV_AGC_OBSRX_APD_LOW_GAIN_STEP_PARM: + return "device->obsRx->orxAgcCtrl->peakAgc->apdLowGainStepRecovery out of range in MYKONOS_setupObsRxAgc() \n"; + case MYKONOS_ERR_INV_AGC_OBSRX_HB2_HIGH_GAIN_STEP_PARM: + return "device->obsRx->orxAgcCtrl->peakAgc->hb2HighGainStepAttack out of range in MYKONOS_setupObsRxAgc() \n"; + case MYKONOS_ERR_INV_AGC_OBSRX_HB2_LOW_GAIN_STEP_PARM: + return "device->obsRx->orxAgcCtrl->peakAgc->hb2LowGainStepRecovery out of range in MYKONOS_setupObsRxAgc() \n"; + case MYKONOS_ERR_INV_AGC_OBSRX_HB2_VERY_LOW_GAIN_STEP_PARM: + return "device->obsRx->orxAgcCtrl->peakAgc->hb2VeryLowGainStepRecovery out of range in MYKONOS_setupObsRxAgc() \n"; + case MYKONOS_ERR_INV_AGC_OBSRX_HB2_OVLD_ENABLE: + return "device->obsRx->orxAgcCtrl->peakAgc->hb2OverloadEnable out of range in MYKONOS_setupObsRxAgc() \n"; + case MYKONOS_ERR_INV_AGC_OBSRX_HB2_OVLD_DUR_CNT: + return "device->obsRx->orxAgcCtrl->peakAgc->hb2OverloadDurationCnt out of range in MYKONOS_setupObsRxAgc() \n"; + case MYKONOS_ERR_INV_AGC_OBSRX_HB2_OVLD_THRESH_CNT: + return "device->obsRx->orxAgcCtrl->peakAgc->hb2OverloadThresholdCnt out of range in MYKONOS_setupObsRxAgc() \n"; + case MYKONOS_ERR_INV_AGC_OBSRX_PMD_LOWER_HIGH_GAIN_STEP: + return "device->obsRx->orxAgcCtrl->powerAgc->pmdLowerHighGainStepRecovery out of range in MYKONOS_setupObsRxAgc() \n"; + case MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_CALPLL_LOCK: + return "CAL PLL Lock event timed out in MYKONOS_waitForEvent()\n"; + case MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_CLKPLLCP: + return "Clock PLL Charge Pump Cal event timed out in MYKONOS_waitForEvent()\n"; + case MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_CLKPLL_LOCK: + return "Clock PLL Lock event timed out in MYKONOS_waitForEvent()\n"; + case MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_RXPLLCP: + return "RX PLL Charge Pump Cal event timed out in MYKONOS_waitForEvent()\n"; + case MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_RXPLL_LOCK: + return "RX PLL Lock event timed out in MYKONOS_waitForEvent()\n"; + case MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_TXPLLCP: + return "TX PLL Charge Pump Cal event timed out in MYKONOS_waitForEvent()\n"; + case MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_TXPLL_LOCK: + return "TX PLL Lock event timed out in MYKONOS_waitForEvent()\n"; + case MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_SNIFFPLLCP: + return "Sniffer PLL Charge Pump Cal event timed out in MYKONOS_waitForEvent()\n"; + case MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_SNIFFPLL_LOCK: + return "Sniffer PLL Lock event timed out in MYKONOS_waitForEvent()\n"; + case MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_RXBBFCALDONE: + return "RX Baseband Filter Cal event timed out in MYKONOS_waitForEvent()\n"; + case MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_TXBBFCALDONE: + return "TX Baseband Filter Cal timed out in MYKONOS_waitForEvent()\n"; + case MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_RFDCCALDONE: + return "RF DC Offset Cal event timed out in MYKONOS_waitForEvent()\n"; + case MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_ADCTUNECALDONE: + return "ADC Tuner Cal event timed out in MYKONOS_waitForEvent()\n"; + case MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_RX1ADCPROFILE: + return "Rx1 ADC Profile Loading event timed out in MYKONOS_waitForEvent()\n"; + case MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_RX2ADCPROFILE: + return "Rx2 ADC Profile Loading event timed out in MYKONOS_waitForEvent()\n"; + case MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_ORXADCPROFILE: + return "ObsRx ADC Profile Loading event timed out in MYKONOS_waitForEvent()\n"; + case MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_RCALDONE: + return "Resistor Cal event timed out in MYKONOS_waitForEvent()\n"; + case MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_ARMBUSY: + return "ARM Busy event timed out in MYKONOS_waitForEvent()\n"; + case MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_INITARMDONE: + return "Initialize ARM event timed out in MYKONOS_waitForEvent()\n"; + case MYKONOS_ERR_TIMEDOUT_ARMMAILBOXBUSY: + return "ARM Mailbox Busy. Command not executed in MYKONOS_sendArmCommand()\n"; + case MYKONOS_ERR_PU_OBSRXPATH_ARMERROR: + return "ARM Command Error in MYKONOS_setObsRxPathSource()\n"; + case MYKONOS_ERR_EN_TRACKING_CALS_ARMSTATE_ERROR: + return "Device not in radioOff/IDLE state. Error in MYKONOS_enableTrackingCals()\n"; + case MYKONOS_ERR_SET_RADIOCTRL_PINS_ARMERROR: + return "ARM command Error in MYKONOS_setRadioControlPinMode()\n"; + case MYKONOS_ERR_EN_TRACKING_CALS_ARMERROR: + return "ARM Command Error in MYKONOS_enableTrackingCals()\n"; + case MYKONOS_ERR_SETRFPLL_ARMERROR: + return "ARM Command Error in MYKONOS_setRfPllFrequency()\n"; + case MYKONOS_ERR_INIT_INV_TXINPUTHB_PARM: + return "device->tx->txProfile->txInputHbInterpolation out of range in MYKONOS_initialize(): valid = 1,2 or 4\n"; + case MYKONOS_ERR_LOAD_ADCPROFILE_INV_VCODIV: + return "device->clocks->clkPllVcoDiv value not supported in MYKONOS_loadAdcProfiles\n"; + case MYKONOS_ERR_LOAD_ADCPROFILE_CUSTOM_RXREQUIRED: + return "Custom RX ADC Profile required\n"; + case MYKONOS_ERR_LOAD_ADCPROFILE_CUSTOM_ORXREQUIRED: + return "Custom ORX ADC Profile required\n"; + case MYKONOS_ERR_LOAD_ADCPROFILE_CUSTOM_SNRXREQUIRED: + return "Custom SNRX ADC Profile required\n"; + case MYKONOS_ERR_LOAD_ADCPROFILE_CUSTOM_LBREQUIRED: + return "Custom Loopback ADC profile required\n"; + case MYKONOS_ERR_LOAD_LBADCPROFILE_ARMMEM_FAILED: + return "WriteArmMemory call failed while writing the Loopback ADC profile into ARM memory\n"; + case MYKONOS_ERR_LOAD_SNRXADCPROFILE_ARMMEM_FAILED: + return "WriteArmMemory call failed while writing the Sniffer ADC profile into ARM memory\n"; + case MYKONOS_ERR_LOAD_ORXADCPROFILE_ARMMEM_FAILED: + return "WriteArmMemory call failed while writing the ObsRx ADC profile into ARM memory\n"; + case MYKONOS_ERR_LOAD_RXADCPROFILE_ARMMEM_FAILED: + return "WriteArmMemory call failed while writing the RX ADC profile into ARM memory\n"; + case MYKONOS_ERR_LOAD_ADCPROFILE_SNRX_ADCDIV_ZERO: + return "SnRx profile has invalid ADC divider of 0, causing a divide by zero\n"; + case MYKONOS_ERR_LOAD_ADCPROFILE_ORXADCDIV_ZERO: + return "ORx profile has invalid ADC divider of 0, causing a divide by zero\n"; + case MYKONOS_ERR_LOAD_ADCPROFILE_RXADCDIV_ZERO: + return "Rx profile has invalid ADC divider of 0, causing a divide by zero\n"; + case MYKONOS_ERR_LOAD_ADCPROFILE_MISSING_ORX_PROFILE: + return "If Tx Profile is valid, a matching ORx profile must be provided to set ADC divider and digital filtering for loopback calibrations\n"; + case MYKONOS_ERR_SETUP_PA_PROT_INV_AVG_DURATION: + return "Invalid setting for avgDuration in MYKONOS_setupPaProtection(...)\n"; + case MYKONOS_ERR_SETUP_PA_PROT_INV_ATTEN_STEP: + return "Invalid setting for attenStepSize in MYKONOS_setupPaProtection(...)\n"; + case MYKONOS_ERR_SETUP_PA_PROT_INV_ATTEN_ENABLE: + return "Invalid setting for txAttenControlEnable in MYKONOS_setupPaProtection(...)\n"; + case MYKONOS_ERR_SETUP_PA_PROT_INV_POWER_THRESH: + return "Invalid setting for powerThreshold in MYKONOS_setupPaProtection(...)\n"; + case MYKONOS_ERR_SETUP_PA_PROT_INV_TX_CHANNEL: + return "Invalid TX channel selected for MYKONOS_getDacPower(...)\n"; + case MYKONOS_ERR_GET_DAC_PWR_INV_POINTER: + return "Cannot return DAC Power information (invalid pointer)\n"; + case MYKONOS_ERR_GET_PA_FLAG_STATUS_INV_POINTER: + return "Cannot return PA Protection Flag Status information (invalid pointer)\n"; + case MYKONOS_ERR_GET_OBSRX_OVERLOADS_NULL_PARM: + return "MYKONOS_getObsRxPathOverloads() has null *obsRxOverloads parameter\n"; + case MYKONOS_ERR_GET_RX1_OVERLOADS_NULL_PARM: + return "MYKONOS_getRxPathOverloads() has null *rx1Overloads parameter\n"; + case MYKONOS_ERR_GET_RX2_OVERLOADS_NULL_PARM: + return "MYKONOS_getRxPathOverloads() has null *rx2Overloads parameter\n"; + case MYKONOS_ERR_GETRADIOSTATE_NULL_PARAM: + return "MYKONOS_getRadioState() has null *radioStatus parameter\n"; + case MYKONOS_ERR_ABORT_INITCALS_NULL_PARAM: + return "MYKONOS_abortInitCals() has null *calsCompleted parameter\n"; + case MYKONOS_ERR_WAIT_INITCALS_ARMERROR: + return "MYKONOS_waitInitCals() returned an ARM error\n"; + case MYKONOS_ERR_WAIT_INITCALS_NULL_PARAM: + return "MYKONOS_waitInitCals() has one or more null parameters\n"; + case MYKONOS_ERR_CHECK_PLL_LOCK_NULL_PARM: + return "MYKONOS_checkPllsLockStatus() has a null *pllLockStatus parameter\n"; + case MYKONOS_ERR_GET_TXFILTEROVRG_NULL_PARM: + return "MYKONOS_getTxFilterOverRangeStatus() has a null *txFilterStatus parameter\n"; + case MYKONOS_ERR_PROGRAM_RXGAIN_TABLE_NULL_PARM: + return "MYKONOS_programRxGainTable() has a null *gainTablePtr parameter\n"; + case MYKONOS_ERR_PROGRAMFIR_NULL_PARM: + return "MYKONOS_programFir() has a null *firFilter parameter\n"; + case MYKONOS_ERR_PROGRAMFIR_COEFS_NULL: + return "MYKONOS_programFir() has a null coef array in *firFilter structure\n"; + case MYKONOS_ERR_READ_DEFRAMERSTATUS_NULL_PARAM: + return "MYKONOS_readDeframerStatus() has a null *deframerStatus parameter\n"; + case MYKONOS_ERR_READ_DEFRAMERPRBS_NULL_PARAM: + return "MYKONOS_readDeframerPrbscounters() has a null *prbsErrorCount parameter\n"; + case MYKONOS_ERR_READ_ORXFRAMERSTATUS_NULL_PARAM: + return "MYKONOS_readOrxFramerStatus() has a null *obsFramerStatus parameter\n"; + case MYKONOS_ERR_READ_RXFRAMERSTATUS_NULL_PARAM: + return "MYKONOS_readRxFramerStatus() has a null *framerStatus parameter\n"; + case MYKONOS_ERR_ARMCMDSTATUS_NULL_PARM: + return "MYKONOS_waitArmCmdStatus() has a null *cmdStatByte parameter\n"; + case MYKONOS_ERR_READARMCMDSTATUS_NULL_PARM: + return "MYKONOS_readArmCmdStatus() has one or more null pointer parameters\n"; + case MYKONOS_ERR_READARMCMDSTATUS_INV_OPCODE_PARM: + return "MYKONOS_readArmCmdStatusByte() has an invalid opcode parameter\n"; + case MYKONOS_ERR_READARMCMDSTATUSBYTE_NULL_PARM: + return "MYKONOS_readArmCmdStatusByte() has a null *cmdStatByte parameter\n"; + case MYKONOS_ERR_ARMCMD_NULL_PARM: + return "MYKONOS_sendArmCommand() has a null *extendedData parameter\n"; + case MYKONOS_ERR_WRITEARMMEM_NULL_PARM: + return "MYKONOS_writeArmMem() has a null *data parameter\n"; + case MYKONOS_ERR_LOADBIN_NULL_PARAM: + return "MYKONOS_loadArmFromBinary() has a null *binary parameter\n"; + case MYKONOS_ERR_LOADARMCON_NULL_PARAM: + return "MYKONOS_loadArmConcurrent() has a null *binary parameter\n"; + case MYKONOS_ERR_GETTX1ATTEN_NULL_PARM: + return "MYKONOS_getTx1Attenuation() has NULL tx1Attenuation_mdB parameter\n"; + case MYKONOS_ERR_GETTX2ATTEN_NULL_PARM: + return "MYKONOS_getTx2Attenuation() has NULL tx2Attenuation_mdB parameter\n"; + case MYKONOS_ERR_ENFRAMERLINK_INV_LANESEN_PARM: + return "Invalid serializer Lanes Enable parameter in Rx framer structure\n"; + case MYKONOS_ERR_ENOBSFRAMERLINK_INV_LANESEN_PARM: + return "Invalid serializer Lanes Enable parameter in ObsRx framer structure\n"; + case MYKONOS_ERR_ENTXNCO_TXPROFILE_INVALID: + return "Can not enable Tx NCO when Tx Profile is invalid\n"; + case MYKONOS_ERR_ENTXNCO_TX1_FREQ_INVALID: + return "Invalid Tx1 NCO frequency\n"; + case MYKONOS_ERR_ENTXNCO_TX2_FREQ_INVALID: + return "Invalid Tx2 NCO frequency\n"; + case MYKONOS_ERR_JESD204B_ILAS_MISMATCH_NULLPARAM: + return "Function parameter has NULL pointer in MYKONOS_jesd204bIlasCheck()\n"; + case MYKONOS_ERR_GET_PLLFREQ_INV_REFCLKDIV: + return "CLKPLL refclk divider was read back as an invalid setting in MYKONOS_getRfPllFrequency()\n"; + case MYKONOS_ERR_GET_PLLFREQ_INV_HSDIV: + return "CLKPLL HSDIV divider was read back as an invalid setting in MYKONOS_getRfPllFrequency()\n"; + case MYKONOS_ERR_GET_PLLFREQ_INV_VCODIV: + return "CLKPLL VCODIV divider was read back as an invalid setting in MYKONOS_getRfPllFrequency()\n"; + case MYKONOS_ERR_GET_RX1_DEC_POWER_NULL_PARM: + return "MYKONOS_getRx1DecPower() has a null *rx1DecPower_mdBFS parameter\n"; + case MYKONOS_ERR_GET_RX1_DEC_POWER_NUM_SAMPLES: + return "MYKONOS_getRx1DecPower() numSamples greater than agcGainUpdateCounter\n"; + case MYKONOS_ERR_GET_RX2_DEC_POWER_NULL_PARM: + return "MYKONOS_getRx2DecPower() has a null *rx2DecPower_mdBFS parameter\n"; + case MYKONOS_ERR_GET_RX2_DEC_POWER_NUM_SAMPLES: + return "MYKONOS_getRx2DecPower() numSamples greater than agcGainUpdateCounter\n"; + case MYKONOS_ERR_GET_OBSRX_DEC_POWER_NULL_PARM: + return "MYKONOS_getObsRxDecPower() has a null *obsRxDecPower_mdBFS parameter\n"; + case MYKONOS_ERR_GET_OBSRX_DEC_POWER_NUM_SAMPLES: + return "MYKONOS_getObsRxDecPower() numSamples greater than agcGainUpdateCounter\n"; + case MYKONOS_ERR_GETARMVER_NULL_PARM: + return "MYKONOS_getArmVersion() has a NULL pointer in one of the function parameters\n"; + case MYKONOS_ERR_EN_DPDTRACKING_ARMSTATE_ERROR: + return "ARM is not in the RadioOff state before MYKONOS_enableDpdTracking(), call MYKONOS_radioOff()\n"; + case MYKONOS_ERR_RESTDPDMOD_WRONGBUFFERSIZE: + return "MYKONOS_restoreDpdModel() supplied DPD Model Data Buffer is incorrect size\n"; + case MYKONOS_ERR_RESTDPDMOD_ARMERRFLAG: + return "The ARM reported a error while in MYKONOS_restoreDpdModel().\n"; + case MYKONOS_ERR_RESTDPDMOD_INVALID_TXCHANNEL: + return "MYKONOS_restoreDpdModel() invalid txChannel specified\n"; + case MYKONOS_ERR_SAVDPDMOD_WRONGBUFFERSIZE: + return "MYKONOS_saveDpdModel() supplied DPD Model Data Buffer is incorrect size\n"; + case MYKONOS_ERR_SAVDPDMOD_ARMSTATE: + return "ARM is not in the RadioOff state before MYKONOS_saveDpdModel(), call MYKONOS_radioOff()\n"; + case MYKONOS_ERR_SAVDPDMOD_INVALID_TXCHANNEL: + return "MYKONOS_saveDpdModel() invalid txChannel specified\n"; + case MYKONOS_ERR_EN_CLGCTRACKING_ARMSTATE_ERROR: + return "ARM is not in the RadioOff state before MYKONOS_enableClgcTracking(), call MYKONOS_radioOff()\n"; + case MYKONOS_ERR_CFGDPD_TXORX_PROFILE_INV: + return "Tx or ORx profile is not valid, both are necessary for DPD features in MYKONOS_configDpd()\n"; + case MYKONOS_ERR_CFGDPD_NULL_DPDCFGSTRUCT: + return "device->tx->dpdConfig structure has NULL pointer in MYKONOS_configDpd()\n"; + case MYKONOS_ERR_WRITEARMCFG_ARMERRFLAG: + return "The ARM reported a error while writing to an ARM config structure in MYKONOS_writeArmCfgStruct()\n"; + case MYKONOS_ERR_CFGDPD_INV_DPDDAMPING: + return "ERROR: device->tx->dpdConfig->damping parameter is out of range (0-15)\n"; + case MYKONOS_ERR_CFGDPD_INV_DPDSAMPLES: + return "ERROR: device->tx->dpdConfig->samples parameter is out of range (64 - 32768)\n"; + case MYKONOS_ERR_CFGDPD_INV_NUMWEIGHTS: + return "ERROR: device->tx->dpdConfig->numWeights parameter is out of range (0-3)\n"; + case MYKONOS_ERR_CFGDPD_INV_DPDOUTLIERTHRESH: + return "ERROR: device->tx->dpdConfig->outlierThreshold parameter is out of range\n"; + case MYKONOS_ERR_CFGDPD_INV_DPDPRIORWEIGHT: + return "ERROR: device->tx->dpdConfig->modelPriorWeight parameter is out of range (Valid 0-32)\n"; + case MYKONOS_ERR_CFGCLGC_INV_DESIREDGAIN: + return "ERROR: device->tx->clgcConfig->tx1DesiredGain or tx2DesiredGain parameter is out of range\n"; + case MYKONOS_ERR_CFGCLGC_INV_TXATTENLIMIT: + return "ERROR: device->tx->clgcConfig->tx1AttenLimit or tx2AttenLimit parameter is out of range\n"; + case MYKONOS_ERR_CFGCLGC_INV_CLGC_CTRLRATIO: + return "ERROR: device->tx->clgcConfig->tx1ControlRatio or tx2ControlRatio parameter is out of range\n"; + case MYKONOS_ERR_CFGDPD_INV_DPD_ADDDELAY: + return "ERROR: device->tx->dpdConfig->additionalDelayOffset parameter is out of range\n"; + case MYKONOS_ERR_CFGDPD_INV_PNSEQLEVEL: + return "ERROR: device->tx->dpdConfig->pathDelayPnSeqLevel parameter is out of range\n"; + case MYKONOS_ERR_CFGDPD_INV_MODELVERSION: + return "ERROR: device->tx->dpdConfig->modelVersion parameter is out of range\n"; + case MYKONOS_ERR_READARMCFG_ARMERRFLAG: + return "ERROR: MYKONOS_readArmConfig failed due to an ARM error\n"; + case MYKONOS_ERR_GETPENDTRKCALS_NULL_PARAM: + return "MYKONOS_getPendingTrackingCals() has NULL function parameter\n"; + case MYKONOS_ERR_ARMCMDSTATUS_ARMERROR: + return "MYKONOS_waitArmCmdStatus() exited due to ARM error for the desired ARM opcode\n"; + case MYKONOS_ERR_WAITARMCMDSTATUS_TIMEOUT: + return "MYKONOS_waitArmCmdStatus() timed out waiting for the ARM to complete the requested command\n"; + case MYKONOS_ERR_PU_GETOBSRXPATH_ARMERROR: + return "ARM returned an error while trying to get the ObsRx Path source in MYKONOS_getObsRxPathSource()\n"; + case MYKONOS_ERR_GETDPDCFG_NULL_DPDCFGSTRUCT: + return "MYKONOS_getDpdConfig() could not complete due to a NULL pointer to device->tx->dpdConfig structure\n"; + case MYKONOS_ERR_GETDPDCFG_TXORX_PROFILE_INV: + return "The Tx and ORx profiles must be valid for DPD related functions\n"; + case MYKONOS_ERR_GETDPDSTATUS_ARMERRFLAG: + return "MYKONOS_getDpdStatus() reported an ARM error with the ARM Get command\n"; + case MYKONOS_ERR_GETDPDSTATUS_NULLPARAM: + return "MYKONOS_getDpdStatus() has NULL pointer in the function parameter\n"; + case MYKONOS_ERR_SETDEFOBSRXPATH_NULL_OBSRX_STRUCT: + return "Observation profile not valid, device->obsRx structure is NULL in MYKONOS_setDefaultObsRxPath()\n"; + case MYKONOS_ERR_GETCLGCSTATUS_NULLPARAM: + return "MYKONOS_getClgcStatus() has NULL clgcStatus parameter\n"; + case MYKONOS_ERR_GETCLGCSTATUS_ARMERRFLAG: + return "ARM reported an error with the ARM GET command during MYKONOS_getClgcStatus()\n"; + case MYKONOS_ERR_READ_DEFFIFODEPTH_NULL_PARAM: + return "MYKONOS_getDeframerFifoDepth() function parameter fifoDepth is a NULL pointer\n"; + case MYKONOS_ERR_READ_DEFFIFODEPTH_LMFCCOUNT_NULL_PARAM: + return "MYKONOS_getDeframerFifoDepth() function parameter readEnLmfcCount is a NULL pointer\n"; + case MYKONOS_ERR_GETDPDSTATUS_INV_CH: + return "MYKONOS_getDpdStatus() txChannel parameter is not valid (TX1 and TX2 are the only valid options)\n"; + case MYKONOS_ERR_GETCLGCSTATUS_INV_CH: + return "MYKONOS_getClgcStatus() txChannel parameter is not valid (TX1 and TX2 are the only valid options)\n"; + case MYKONOS_ERR_INIT_INV_TXINPUTHB_INV_RATE: + return "Invalid Tx profile: When using Tx Input halfband, IQ rate must not exceed 160MSPS\n"; + case MYKONOS_ERR_INIT_INV_TXINPUTHB0_INV_RATE: + return "Invalid Tx profile: When using Tx Input halfband 0, IQ rate must not exceed 80MSPS\n"; + case MYKONOS_ERR_RXFIR_TAPSEXCEEDED: + return "Rx PFIR can not be clocked fast enough to handle the number of FIR coefficents provided\n"; + case MYKONOS_ERR_ORXFIR_TAPSEXCEEDED: + return "ORx PFIR can not be clocked fast enough to handle the number of FIR coefficents provided\n"; + case MYKONOS_ERR_SNRXFIR_TAPSEXCEEDED: + return "Sniffer Rx PFIR can not be clocked fast enough to handle the number of FIR coefficents provided\n"; + case MYKONOS_ERR_TXFIR_INV_NUMTAPS_PARM: + return "Invalid number of Tx FIR coefficients\n"; + case MYKONOS_ERR_TXFIR_INV_NUMROWS: + return "Invalid number of PFIR coefficient rows\n"; + case MYKONOS_ERR_TXFIR_TAPSEXCEEDED: + return "Too many Tx PFIR taps for the IQ sample rate. FIR processing clock can not run fast enough to handle the number of taps\n"; + case MYKONOS_ERR_GETINITCALSTATUS_NULL_PARAM: + return "MYKONOS_getInitCalStatus() has a null pointer in parameter list\n"; + case MYKONOS_ERR_GETINITCALSTATUS_ARMERROR: + return "MYKONOS_getInitCalStatus() returned an ARM error while getting the init cal status information"; + case MYKONOS_ERR_CFGCLGC_TXORX_PROFILE_INV: + return "Tx and ObsRx profiles must be valid to use the CLGC feature in MYKONOS_configClgc()\n"; + case MYKONOS_ERR_CFGCLGC_NULL_CLGCCFGSTRUCT: + return "CLGC config structure is NULL in device->tx->clgcConfig in MYKONOS_configClgc()\n"; + case MYKONOS_ERR_GETCLGCCFG_TXORX_PROFILE_INV: + return "Could not read back CLGC status because Tx and ORx profiles are not valid\n"; + case MYKONOS_ERR_GETCLGCCFG_NULL_CFGSTRUCT: + return "Could not read back CLGC status because return structure device->tx->clgcConfig pointer is NULL\n"; + case MYKONOS_ERR_CALCDIGCLK_NULLDEV_PARAM: + return "device structure pointer is NULL in MYKONOS_calculateDigitalClocks()\n"; + case MYKONOS_ERR_CALCDIGCLK_NULL_CLKSTRUCT: + return "device->clocks structure pointer is NULL in MYKONOS_calculateDigitalClocks()\n"; + case MYKONOS_ERR_NULL_DEVICE_PARAM: + return "The device pointer in the calling function's parameter list is a NULL pointer\n"; + case MYKONOS_ERR_CALCDEVCLK_NULLPARAM: + return "MYKONOS_calculateScaledDeviceClk_kHz() has a NULL pointer in one of the function parameters\n"; + case MYKONOS_ERR_CFGCLGC_INV_CLGC_ADDDELAY: + return "CLGC Additional Delay parameter is out of range in MYKONOS_configClgc\n"; + case MYKONOS_ERR_CFGCLGC_INV_PNSEQLEVEL: + return "CLGC PN Sequence level parameter is out of range in MYKONOS_configClgc\n"; + case MYKONOS_ERR_CFGVSWR_TXORX_PROFILE_INV: + return "The Tx and ORx profiles must be valid to use the VSWR feature in MYKONOS_configVswr()\n"; + case MYKONOS_ERR_CFGVSWR_ARMSTATE_ERROR: + return "ARM must be in radioOff state to configure the VSWR config parameters in MYKONOS_configVswr()\n"; + case MYKONOS_ERR_CFGVSWR_INV_3P3GPIOPIN: + return "VSWR 3.3v GPIO pin selection is out of range (0-11) in MYKONOS_configVswr()\n"; + case MYKONOS_ERR_CFGVSWR_INV_PNSEQLEVEL: + return "VSWR init PN sequence level is out of range in MYKONOS_configVswr()\n"; + case MYKONOS_ERR_CFGVSWR_INV_VSWR_ADDDELAY: + return "VSWR additionalDelay member is out of range in MYKONOS_configVswr()\n"; + case MYKONOS_ERR_CFGVSWR_NULL_VSWRCFGSTRUCT: + return "device->tx->vswrConfig pointer is null in MYKONOS_confgiVswr()\n"; + case MYKONOS_ERR_GETVSWRCFG_NULL_CFGSTRUCT: + return "device->tx->vswrConfig pointer is null in MYKONOS_getVswrConfig()\n"; + case MYKONOS_ERR_GETVSWRCFG_TXORX_PROFILE_INV: + return "Tx and ORx profiles must be valid in MYKONOS_getVswrConfig()\n"; + case MYKONOS_ERR_GETVSWRSTATUS_ARMERRFLAG: + return "ARM returned an error while attempting to read the VSWR status structure\n"; + case MYKONOS_ERR_GETVSWRSTATUS_INV_CH: + return "Invalid Tx channel parameter passed to MYKONOS_getVswrStatus()\n"; + case MYKONOS_ERR_GETVSWRSTATUS_NULLPARAM: + return "vswrStatus function parameter is null in MYKONOS_getVswrStatus\n"; + case MYKONOS_ERR_SET_RX_MAX_GAIN_INDEX: + return "Max gain index bigger than max gain index loaded table in MYKONOS_setRxAgcMinMaxGainIndex().\n"; + case MYKONOS_ERR_SET_RX_MIN_GAIN_INDEX: + return "Min gain index lower than min gain index loaded table in MYKONOS_setRxAgcMinMaxGainIndex().\n"; + case MYKONOS_ERR_AGC_MIN_MAX_RX_CHANNEL: + return "Wrong RX channel selected in MYKONOS_setRxAgcMinMaxGainIndex().\n"; + case MYKONOS_ERR_SET_ORX_MAX_GAIN_INDEX_CHANNEL: + return "Wrong read back channel in MYKONOS_setObsRxAgcMinMaxGainIndex().\n"; + case MYKONOS_ERR_SET_ORX_MAX_GAIN_INDEX: + return "Max gain index bigger than max gain index loaded table in MYKONOS_setObsRxAgcMinMaxGainIndex().\n"; + case MYKONOS_ERR_SET_ORX_MIN_GAIN_INDEX: + return "Min gain index lower than min gain index loaded table in MYKONOS_setObsRxAgcMinMaxGainIndex().\n"; + case MYKONOS_ERR_AGC_MIN_MAX_ORX_CHANNEL: + return "Wrong observation channel selected in MYKONOS_setObsRxAgcMinMaxGainIndex().\n"; + case MYKONOS_ERR_RX1_TEMP_GAIN_COMP_RANGE: + return "The temp gain compensation is outside range (-3000mdB to 3000mdB) in MYKONOS_setRx1TempGainComp().\n"; + case MYKONOS_ERR_RX1_TEMP_GAIN_COMP_STEP: + return "Not valid temp gain compensation, step size is 250mdB in MYKONOS_setRx1TempGainComp().\n"; + case MYKONOS_ERR_RX2_TEMP_GAIN_COMP_RANGE: + return "The temp gain compensation is outside range (-3000mdB to 3000mdB) in MYKONOS_setRx2TempGainComp().\n"; + case MYKONOS_ERR_RX2_TEMP_GAIN_COMP_STEP: + return "Not valid temp gain compensation, step size is 250mdB in MYKONOS_setRx2TempGainComp().\n"; + case MYKONOS_ERR_OBS_RX_TEMP_GAIN_COMP_RANGE: + return "The temp gain compensation is outside range (-3000mdB to 3000mdB) in MYKONOS_setObsRxTempGainComp().\n"; + case MYKONOS_ERR_OBS_RX_TEMP_GAIN_COMP_STEP: + return "Not valid temp gain compensation, step size is 250mdB in MYKONOS_setObsRxTempGainComp().\n"; + case MYKONOS_ERR_RX1_TEMP_GAIN_COMP_NULL: + return "rx1TempCompGain_mdB pointer is null MYKONOS_getRx1TempGainComp().\n"; + case MYKONOS_ERR_RX2_TEMP_GAIN_COMP_NULL: + return "rx2TempCompGain_mdB pointer is null MYKONOS_getRx2TempGainComp().\n"; + case MYKONOS_ERR_OBS_RX_TEMP_GAIN_COMP_NULL: + return "obsRxTempCompGain_mdB pointer is null MYKONOS_getObsRxTempGainComp().\n"; + case MYKONOS_ERR_GETORXQECSTATUS_NULLPARAM: + return "Function parameter mykonosOrxQecStatus_t is a NULL pointer in MYKONOS_getOrxQecStatus().\n"; + case MYKONOS_ERR_GETORXQECSTATUS_INV_CH: + return "Channel selection not valid in MYKONOS_getOrxQecStatus().\n"; + case MYKONOS_ERR_GETORXQECSTATUS_ARMERRFLAG: + return "ARM command error in MYKONOS_getOrxQecStatus().\n"; + case MYKONOS_ERR_GETRXQECSTATUS_NULLPARAM: + return "Function parameter mykonosRxQecStatus_t is a NULL pointer in MYKONOS_getRxQecStatus().\n"; + case MYKONOS_ERR_GETRXQECSTATUS_INV_CH: + return "Channel selection not valid in MYKONOS_getRxQecStatus().\n"; + case MYKONOS_ERR_GETRXQECSTATUS_ARMERRFLAG: + return "ARM command error in MYKONOS_getRxQecStatus().\n"; + case MYKONOS_ERR_GETTXQECSTATUS_NULLPARAM: + return "Function parameter mykonosTxQecStatus_t is a NULL pointer in MYKONOS_getRxQecStatus().\n"; + case MYKONOS_ERR_GETTXQECSTATUS_INV_CH: + return "Channel selection not valid in MYKONOS_getTxQecStatus().\n"; + case MYKONOS_ERR_GETTXQECSTATUS_ARMERRFLAG: + return "ARM command error in MYKONOS_getTxQecStatus().\n"; + case MYKONOS_ERR_GETTXLOLSTATUS_NULLPARAM: + return "Function parameter mykonosTxLolStatus_t is a NULL pointer in MYKONOS_getTLolStatus().\n"; + case MYKONOS_ERR_GETTXLOLSTATUS_INV_CH: + return "Channel selection not valid in MYKONOS_getTLolStatus().\n"; + case MYKONOS_ERR_GETTXLOLSTATUS_ARMERRFLAG: + return "ARM command error in MYKONOS_getTLolStatus().\n"; + case MYKONOS_ERR_RESCHEDULE_TRACK_CAL_INV: + return "Not valid calibration passed to MYKONOS_rescheduleTrackingCal().\n"; + case MYKONOS_ERR_RESCHEDULE_TRACK_ARMERRFLAG: + return "ARM error in MYKONOS_rescheduleTrackingCal().\n"; + case MYKONOS_ERR_ARMSTATE_EXCEPTION: + return "ARM system problem has been detected.\n"; + case MYKONOS_ERR_ARMSTATE_CAL_ERROR: + return "ARM has detected an error in the tracking calibrations.\n"; + case MYKONOS_ERR_ARMSTATE_PROFILE_ERROR: + return "ARM has detected an illegal profile.\n"; + case MYKONOS_ERR_WAITARMCSTATE_TIMEOUT: + return "Timeout occurred in MYKONOS_checkArmState().\n"; + case MYKONOS_ERR_GET_API_VERSION_NULL_PARAM: + return "Null parameter passed to the function MYKONOS_getApiVersion().\n"; + case MYKONOS_ERR_GETPRODUCTID_NULL_PARAM: + return "Null parameter passed to the function MYKONOS_getProductId().\n"; + case MYKONOS_ERR_TXPROFILE_IQRATE: + return "Tx Profile IQ rate out of range.\n"; + case MYKONOS_ERR_TXPROFILE_RFBW: + return "Tx Profile RF bandwidth out of range.\n"; + case MYKONOS_ERR_TXPROFILE_FILTER_INTERPOLATION: + return "Tx Filter interpolation not valid.\n"; + case MYKONOS_ERR_TXPROFILE_FIR_COEFS: + return "Tx FIR filter not valid.\n"; + case MYKONOS_ERR_RXPROFILE_RXCHANNEL: + return " Rx channel is not valid.\n"; + case MYKONOS_ERR_RXPROFILE_IQRATE: + return "Receiver profile out of range IQ rate.\n"; + case MYKONOS_ERR_RXPROFILE_RFBW: + return "Receiver profile out of range RF bandwidth.\n"; + case MYKONOS_ERR_RXPROFILE_FILTER_DECIMATION: + return "Receiver profile not valid filter decimation setting.\n"; + case MYKONOS_ERR_RXPROFILE_FIR_COEFS: + return "Receiver profile FIR filter not valid.\n"; + case MYKONOS_ERR_RXPROFILE_ADCDIV: + return "Receiver profile not valid ADC divider.\n"; + case MYKONOS_ERR_PROFILES_HSDIGCLK: + return "Profile combinations loaded are not valid.\n"; + case MYKONOS_ERR_RESET_TXLOL_INV_PARAM: + return "Selected channel is not valid.\n"; + case MYKONOS_ERR_RESET_TXLOL_ARMERROR: + return "ARM command error in MYKONOS_resetExtTxLolChannel().\n"; + case MYKONOS_ERR_SETSTATEALL_TRACK_CAL_INV: + return "Not valid calibration mask passed for trackCals.\n"; + case MYKONOS_ERR_SETSTATEALL_TRACK_ARMERRFLAG: + return "ARM error flag set.\n"; + case MYKONOS_ERR_GETSTATEALL_TRACK_ARMERRFLAG: + return "ARM error flag set.\n"; + case MYKONOS_ERR_GETSTATEALL_TRACK_ARMERROR: + return "ARM command error.\n"; + case MYKONOS_ERR_GETSTATEALL_TRACK_NULL_PARAM: + return "Null parameter passed for trackCals.\n"; + case MYKONOS_ERR_SETSTATE_TRACK_CAL_INV: + return "Not valid calibration passed.\n"; + case MYKONOS_ERR_SETSTATE_TRACK_ARMERRFLAG: + return "ARM command error.\n"; + case MYKONOS_ERR_GETSTATE_TRACK_NULL_PARAM: + return "Null parameter passed to trackCalState.\n"; + case MYKONOS_ERR_GETSTATE_TRACK_ARMERRFLAG: + return "ARM command error flag set.\n"; + case MYKONOS_ERR_GETSTATE_TRACK_ARMERROR: + return "ARM command error.\n"; + case MYKONOS_ERR_SETCLGCGAIN_INV_TXCHANNEL: + return "Tx channel is not valid (Valid ENUM values: TX1 or TX2 only).\n"; + case MYKONOS_ERR_SETCLGCGAIN_TRACK_ARMERRFLAG: + return "ARM command flag error set.\n"; + case MYKONOS_ERR_SETCLGCGAIN_INV_DESIREDGAIN: + return "CLGC gain parameter is out of range, valid range is from -10000 to 10000.\n"; + case MYKONOS_ERR_SETDPDACT_INV_TXCHANNEL: + return "Tx channel is not valid (Valid ENUM values: TX1, TX2 or TX1_TX2).\n"; + case MYKONOS_ERR_SETDPDACT_INV_STATE: + return "Invalid Actuator state, valid states are 0-disable and 1-enable.\n"; + case MYKONOS_ERR_SETDPDACT_ARMERRFLAG: + return "ARM command flag error set.\n"; + case MYKONOS_ERR_SETRFPLL_LF_PLLNAME: + return "Invalid pllName requested in MYKONOS_setRfPllLoopFilter()\n"; + case MYKONOS_ERR_SETRFPLL_LF_INV_STABILITY: + return "Invalid stability value requested in MYKONOS_setRfPllLoopFilter()\n"; + case MYKONOS_ERR_SETRFPLL_LF_ARMERROR: + return "ARM Command Error in MYKONOS_setRfPllLoopFilter()\n"; + case MYKONOS_ERR_SETRFPLL_LF_INV_TXRX_LOOPBANDWIDTH: + return "Invalid Tx/Rx value bandwith requested in MYKONOS_setRfPllLoopFilter()\n"; + case MYKONOS_ERR_SETRFPLL_LF_INV_SNF_LOOPBANDWIDTH: + return "Invalid Sniffer value bandwith in MYKONOS_setRfPllLoopFilter()\n"; + case MYKONOS_ERR_GETRFPLL_LF_INV_PLLNAME: + return "Invalid pllName requested in MYKONOS_getRfPllLoopFilter()\n"; + case MYKONOS_ERR_GETRFPLL_LF_ARMERROR: + return "ARM Command Error in MYKONOS_getRfPllLoopFilter()\n"; + case MYKONOS_ERR_GETRFPLL_LF_NULLPARAM: + return "NULL pointer in function parameter for MYKONOS_getRfPllLoopFilter()\n"; + case MYKONOS_ERR_SET_RF_DC_OFFSET_INV_MEASURECNT: + return "Invalid value passed as parameter for measureCount to function MYKONOS_setRfDcOffsetCnt().\n"; + case MYKONOS_ERR_SET_RF_DC_OFFSET_MEASURECNT_MIN_LIMIT: + return "The measureCount value passed to function MYKONOS_setRfDcOffsetCnt() is less than the minimum limit allowed.\n"; + case MYKONOS_ERR_DC_OFFSET_INV_CHAN: + return "Invalid channel passed as parameter, for valid channel refer mykonosDcOffsetChannels_t enum.\n"; + case MYKONOS_ERR_GET_RF_DC_OFFSET_NULL_MEASURECNT: + return "Null parameter passed for measureCount MYKONOS_getRfDcOffsetCnt().\n"; + case MYKONOS_ERR_SET_DIG_DC_OFFSET_INV_MSHIFT: + return "Invalid MShift value passed as parameter to function MYKONOS_setDigDcOffsetMShift().\n"; + case MYKONOS_ERR_GET_DIG_DC_OFFSET_NULL_MSHIFT: + return "MShift passed to the function MYKONOS_getDigDcOffsetMShift() is NULL.\n"; + case MYKONOS_ERR_DIG_DC_OFFSET_INV_ENABLE_MASK: + return "Invalid enable mask passed to the function MYKONOS_setDigDcOffsetEn().\n"; + case MYKONOS_ERR_DIG_DC_OFFSET_NULL_ENABLE_MASK: + return "Enable mask passed to the function MYKONOS_getDigDcOffsetEn() is NULL.\n"; + case MYKONOS_ERR_RESETDPD_WRONG_PARAM: + return "reset parameter passed to function MYKONOS_resetDpd() is not valid, possible values are: MYK_DPD_RESET_FULL, MYK_DPD_RESET_PRIOR or MYK_DPD_RESET_CORRELATOR \n"; + case MYKONOS_ERR_RESETDPD_ARMERRFLAG: + return "ARM command flag error set in function MYKONOS_resetDpd().\n"; + case MYKONOS_ERR_CFGCLGC_INV_THRESHOLD: + return "tx1RelThreshold or tx2RelThreshold parameter is out of range in function MYKONOS_configClgc().\n"; + case MYKONOS_ERR_RESETDPD_INV_TXCHANNEL: + return "Tx channel is not valid (Valid ENUM values: TX1, TX2 or TX1_TX2 in function MYKONOS_resetDpd().\n"; + case MYKONOS_ERR_SET_PATH_DELAY_NULL_PARAM: + return "pathDelay structure is null in function MYKONOS_setPathDelay().\n"; + case MYKONOS_ERR_SET_PATH_DELAY_PARAM_OUT_OF_RANGE: + return "path delay not valid range in MYKONOS_setPathDelay(), valid ranges are from 0 to 4095 at 1/16 sample resolution of ORx sample rate.\n"; + case MYKONOS_ERR_GET_PATH_DELAY_NULL_PARAM: + return "pathDelay structure is null in function MYKONOS_getPathDelay().\n"; + case MYKONOS_ERR_GET_PATH_DELAY_INVALID_SELECTION: + return "invalid selection for getting the path delay, valid selections are given by mykonosPathDelaySel_t.\n"; + case MYKONOS_ERR_GET_PATH_DELAY_ARMERRFLAG: + return "Arm error while reading path delay for the selected calibration status.\n"; + case MYKONOS_ERR_GETDPD_ERROR_CNT_NULLPARAM: + return "dpdErrCnt is null in function MYKONOS_getDpdErrorCounters().\n"; + case MYKONOS_ERR_GETDPD_ERROR_CNT_INV_CH: + return "invalid selection for getting the error counters tx channel in MYKONOS_getDpdErrorCounters().\n"; + case MYKONOS_ERR_GETDPD_ERROR_CNT_ARMERRFLAG: + return "Arm error while reading the error counters for the DPD status MYKONOS_getDpdErrorCounters().\n"; + case MYKONOS_ERR_SETDPDACT_NULL_ACTSTRUCT: + return "Passed structure is null in MYKONOS_setDpdBypassConfig().\n"; + case MYKONOS_ERR_SETDPDACT_INV_ACTMODE: + return "Invalid mode passed detected in MYKONOS_setDpdBypassConfig(), actConfig->bypassActuatorMode for valid modes mykonosDpdResetMode_t.\n"; + case MYKONOS_ERR_SETDPDACT_INV_LEVEL: + return "Passed actConfig->bypassActuatorLevel outside the range in MYKONOS_setDpdBypassConfig().\n"; + case MYKONOS_ERR_GETDPDACT_NULL_ACTSTRUCT: + return "Passed structure is null in MYKONOS_getDpdBypassConfig().\n"; + case MYKONOS_ERR_SETDPDACTCHECK_NULL_ACTSTRUCT: + return "Passed structure is null in MYKONOS_setDpdActuatorCheck().\n"; + case MYKONOS_ERR_SETDPDACTCHECK_INV_ACTMODE: + return "Invalid mode detected in MYKONOS_setDpdActuatorCheck(), actCheck->actuatorGainCheckMode for valid modes mykonosDpdResetMode_t.\n"; + case MYKONOS_ERR_SETDPDACTCHECK_INV_LEVEL: + return "Passed actCheck->actuatorGainCheckLevel outside the range in MYKONOS_setDpdActuatorCheck().\n"; + case MYKONOS_ERR_GETDPDACTCHECK_NULL_ACTSTRUCT: + return "Passed structure is null in MYKONOS_getDpdActuatorCheck().\n"; + case MYKONOS_ERR_CLGCATTENTUNCFG_NULL_ATTRANGECFGSTRUCT: + return "Passed structure is null in MYKONOS_setClgcAttenTuningConfig().\n"; + case MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_MODE: + return "Invalid mode detected for attRangeCfg member in MYKONOS_getClgcAttenTuningConfig(), for valid modes ::mykonosClgcAttenTuningMode_t.\n"; + case MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_PRESET: + return "Invalid AttenTuningPreset detected for attRangeCfg member in MYKONOS_getClgcAttenTuningConfig(), valid range is from 0 to 839 (0 to 41.95dB).\n"; + case MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_RANGE: + return "Invalid AttenTuningRange detected for attRangeCfg member in MYKONOS_getClgcAttenTuningConfig(), valid range is from 0 to 420 (0 to 21dB).\n"; + case MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_TX1_SETTINGS: + return "Invalid Tx1 AttenTuningRange and AttenTuningPreset combination in MYKONOS_getClgcAttenTuningConfig().\n"; + case MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_TX2_SETTINGS: + return "Invalid Tx2 AttenTuningRange and AttenTuningPreset combination in MYKONOS_getClgcAttenTuningConfig().\n"; + case MYKONOS_ERR_CLGCATTENTUNCFGGET_NULL_ATTRANGECFGSTRUCT: + return "Passed structure is null in MYKONOS_getClgcAttenTuningConfig().\n"; + + default: + return "Unknown error was encountered.\n"; + } + +#endif +} + +/** + * \brief Calculates the scaled device clock frequency at the input of the + * CLKPLL or RFPLL + * + * Use this helper function any time the scaled device clock frequency is needed. + * + * Dependencies + * - device->clocks->deviceClock_kHz + * - device->spiSettings->chipSelectIndex + * + * \param device is structure pointer to the Mykonos data structure containing settings + * \param scaledRefClk_kHz Output: The returned scaled reference clock for the device's PLLs + * \param deviceClkDiv Output: The device clock divider setting that gets set in the devices SPI register. + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_NULL_DEVICE_PARAM Function parameter device pointer is NULL + * \retval MYKONOS_ERR_INV_SCALEDDEVCLK_PARAM The scaled PLL refclk frequency is out of range (40MHz to 80MHz) + * \retval MYKONOS_ERR_CALCDEVCLK_NULLPARAM Function parameter scaledRefClk_kHz or deviceClkDiv has a NULL pointer + */ +static mykonosErr_t MYKONOS_calculateScaledDeviceClk_kHz(mykonosDevice_t *device, uint32_t *scaledRefClk_kHz, uint8_t *deviceClkDiv) +{ + uint32_t deviceClock_kHz = 0; + + if ((device == NULL) || (device->clocks == NULL)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, 0, MYKONOS_ERR_NULL_DEVICE_PARAM, getMykonosErrorMessage(MYKONOS_ERR_NULL_DEVICE_PARAM)); + return MYKONOS_ERR_NULL_DEVICE_PARAM; + } + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_calculateScaledDeviceClk_kHz()\n"); +#endif + + deviceClock_kHz = device->clocks->deviceClock_kHz; + + if ((scaledRefClk_kHz == NULL) || (deviceClkDiv == NULL)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CALCDEVCLK_NULLPARAM, + getMykonosErrorMessage(MYKONOS_ERR_CALCDEVCLK_NULLPARAM)); + return MYKONOS_ERR_CALCDEVCLK_NULLPARAM; + } + + /* scaled Ref Clock at input to CLKPLL must be in range 40-80MHz. */ + if (deviceClock_kHz > 20000 && deviceClock_kHz <= 40000) + { + *scaledRefClk_kHz = deviceClock_kHz << 1; + *deviceClkDiv = 3; + } /* x2 */ + else if (deviceClock_kHz > 40000 && deviceClock_kHz <= 80000) + { + *scaledRefClk_kHz = deviceClock_kHz; + *deviceClkDiv = 0; + } /* x1 */ + else if (deviceClock_kHz > 80000 && deviceClock_kHz <= 160000) + { + *scaledRefClk_kHz = deviceClock_kHz >> 1; + *deviceClkDiv = 1; + } /* div2 */ + else if (deviceClock_kHz > 160000 && deviceClock_kHz <= 320000) + { + *scaledRefClk_kHz = deviceClock_kHz >> 2; + *deviceClkDiv = 2; + } /* div4 */ + else + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_SCALEDDEVCLK_PARAM, + getMykonosErrorMessage(MYKONOS_ERR_INV_SCALEDDEVCLK_PARAM)); + return MYKONOS_ERR_INV_SCALEDDEVCLK_PARAM; + } + return MYKONOS_ERR_OK; +} + +/** + * \brief Resets the JESD204B Deframer + * + * Dependencies + * - device->spiSettings + * + * \param device is a pointer to the device settings structure + * + * \retval MYKONOS_ERR_OK Function completed successfully + */ +mykonosErr_t MYKONOS_resetDeframer(mykonosDevice_t *device) +{ + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_resetDeframer()\n"); +#endif + + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_RESET, 0x03); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_RESET, 0x00); + + return MYKONOS_ERR_OK; +} + +/** + * \brief Sets up the JESD204B Serializers + * + * This function uses the Rx framer and ObsRx framer structures to setup the 4 + * serializer lanes that are shared between the two framers. If the Rx profile is valid + * the serializer amplitude and preEmphasis are used from the Rx framer. If only the ObsRx + * profile is valid, the obsRx framer settings are used. + * + * Dependencies + * - device->spiSettings + * - device->spiSettings->chipSelectIndex + * - device->rx->framer->M + * - device->rx->framer->serializerAmplitude + * - device->rx->framer->preEmphasis + * - device->rx->framer->serializerLanesEnabled + * - device->rx->framer->invertLanePolarity + * - device->obsRx->framer->serializerLanesEnabled + * - device->obsRx->framer->invertLanePolarity + * - device->obsRx->framer->M + * - device->obsRx->framer->serializerLanesEnabled + * - device->obsRx->framer->serializerAmplitude + * - device->obsRx->framer->preEmphasis + * + * \param device Pointer to the device settings structure + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_INITSER_INV_VCODIV_PARM Mykonos CLKPLL has invalid VCO divider, verify CLKPLL config + * \retval MYKONOS_ERR_SER_LANE_CONFLICT_PARM When both Rx and ObsRx framers are enabled, framers can not share the same physical lane. + * \retval MYKONOS_ERR_SER_INV_REAL_IF_DATA_PARM Rx Framer M can only = 1 when Real IF mode is enabled + * \retval MYKONOS_ERR_SER_INV_M_PARM Invalid Rx Framer M (valid 1,2,4) + * \retval MYKONOS_ERR_SER_INV_LANEEN_PARM Invalid Rx framer serializerLanesEnabled (valid 0-15) + * \retval MYKONOS_ERR_SER_INV_AMP_PARM Invalid Rx serializer amplitude (valid 0-31) + * \retval MYKONOS_ERR_SER_INV_PREEMP_PARM Invalid Rx serializer pre-emphesis (valid 0-7) + * \retval MYKONOS_ERR_SER_INV_LANEPN_PARM Invalid Rx serializer PN invert setting (valid 0-15) + * \retval MYKONOS_ERR_SER_INV_L_PARM Invalid Rx serializer lanes enabled (must use 1, 2 or 4 lanes) + * \retval MYKONOS_ERR_SER_INV_LANERATE_PARM Invalid Rx serializer lane rate (valid 614.4Mbps - 6144Mbps) + * + * \retval MYKONOS_ERR_SER_INV_REAL_IF_DATA_PARM + * \retval MYKONOS_ERR_SER_INV_LANEEN_PARM + * \retval MYKONOS_ERR_SER_INV_AMP_PARM + * \retval MYKONOS_ERR_SER_INV_PREEMP_PARM + * \retval MYKONOS_ERR_SER_INV_LANEPN_PARM + * \retval MYKONOS_ERR_SER_INV_L_PARM + * \retval MYKONOS_ERR_SER_INV_LANERATE_PARM + * + * \retval MYKONOS_ERR_SER_LANE_RATE_CONFLICT_PARM Necessary lane rates for Rx and ObsRx framer can not be obtained with possible divider settings + * \retval MYKONOS_ERR_HS_AND_LANE_RATE_NOT_INTEGER_MULT HSCLK is not an integer multiple of the lane clock rate + * \retval MYKONOS_ERR_SER_INV_TXSER_DIV_PARM No valid Tx serializer divider to obtain desired lane rates + * \retval MYKONOS_ERR_INITSER_INV_PROFILE Rx/ObsRx and sniffer profiles are not valid - can not config serializers + * \retval MYKONOS_ERR_INV_RXFRAMER_PCLKDIV_PARM Invalid Rx framer PCLK divider + * \retval MYKONOS_ERR_INV_OBSRXFRAMER_PCLKDIV_PARM Invalid ORx/Sniffer framer PCLK divider + * + */ +mykonosErr_t MYKONOS_setupSerializers(mykonosDevice_t *device) +{ + uint8_t serializerHalfRateReg = 0; + uint8_t txser_div = 0; + uint8_t txser_div_reg = 0; + uint32_t clkPllVcoFrequency_kHz = 0; + uint32_t hsclkRate_kHz = 0; + uint32_t rxLaneRate_kHz = 0; + uint32_t obsRxLaneRate_kHz = 0; + uint32_t fasterLaneRate_kHz = 0; + uint32_t slowerLaneRate_kHz = 0; + uint8_t modHsLaneRate = 0; + uint8_t rxL = 0; + uint8_t obsRxL = 0; + uint8_t i = 0; + uint8_t amplitudeEmphasis = 0; + uint8_t lanePowerDown = 0x00; + mykonosVcoDiv_t vcoDiv = VCODIV_1; + uint8_t rxLanePn = 0; + uint8_t obsRxLanePn = 0; + + uint32_t hsDigClkdiv4_5_kHz = 0; + uint32_t rxPclkDiv = 0; + uint32_t obsRxPclkDiv = 0; + uint32_t tempPclkDiv = 0; + uint32_t rxFramerPclk_kHz = 0; + uint32_t obsRxFramerPclk_kHz = 0; + uint8_t rxSyncbSelect = 0; + uint8_t obsRxSyncbSelect = 0; + + static const uint32_t MAX_HSCLK_KHZ_IF_VCODIV1P5 = 6144000; /* max VCO /1.5 output is 6144Mhz. This limits VCO to 9216MHz */ + static const uint32_t MAX_HSCLK_KHZ_IF_VCODIV1 = 8000000; /* max VCO div1 output is 8000Mhz. This limits VCO to 8000MHz */ + static const uint32_t MIN_SERIALIZER_RATE_KHZ = 614400; /* max serializer lane rate = 0.6144 Gbps */ + static const uint32_t MAX_SERIALIZER_RATE_KHZ = 6144000; /* max serializer lane rate = 6.144 Gbps */ +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setupSerializers()\n"); +#endif + + vcoDiv = device->clocks->clkPllVcoDiv; + clkPllVcoFrequency_kHz = device->clocks->clkPllVcoFreq_kHz; + + switch (vcoDiv) + { + case VCODIV_1: + hsclkRate_kHz = clkPllVcoFrequency_kHz; + + /* max VCO /1 output is 8000Mhz. This limits VCO to 8000MHz */ + if (hsclkRate_kHz > MAX_HSCLK_KHZ_IF_VCODIV1) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INITSER_INV_VCODIV1_HSCLK_PARM, + getMykonosErrorMessage(MYKONOS_ERR_INITSER_INV_VCODIV1_HSCLK_PARM)); + return MYKONOS_ERR_INITSER_INV_VCODIV1_HSCLK_PARM; + } + + break; + + case VCODIV_1p5: + hsclkRate_kHz = (clkPllVcoFrequency_kHz / 15) * 10; + + /* max VCO /1.5 output is 6144Mhz. This limits VCO to 9216MHz */ + if (hsclkRate_kHz > MAX_HSCLK_KHZ_IF_VCODIV1P5) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INITSER_INV_VCODIV1P5_HSCLK_PARM, + getMykonosErrorMessage(MYKONOS_ERR_INITSER_INV_VCODIV1P5_HSCLK_PARM)); + return MYKONOS_ERR_INITSER_INV_VCODIV1P5_HSCLK_PARM; + } + + break; + + case VCODIV_2: + hsclkRate_kHz = clkPllVcoFrequency_kHz >> 1; + break; + + case VCODIV_3: + hsclkRate_kHz = (clkPllVcoFrequency_kHz / 30) * 10; + break; + + default: + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INITSER_INV_VCODIV_PARM, + getMykonosErrorMessage(MYKONOS_ERR_INITSER_INV_VCODIV_PARM)); + return MYKONOS_ERR_INITSER_INV_VCODIV_PARM; + } + } + + if ((device->profilesValid & RX_PROFILE_VALID) && (device->profilesValid & (ORX_PROFILE_VALID | SNIFF_PROFILE_VALID))) + { + if (device->rx->framer->serializerLanesEnabled & device->obsRx->framer->serializerLanesEnabled) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SER_LANE_CONFLICT_PARM, + getMykonosErrorMessage(MYKONOS_ERR_SER_LANE_CONFLICT_PARM)); + return MYKONOS_ERR_SER_LANE_CONFLICT_PARM; + } + } + + lanePowerDown = 0x9F; + if (device->profilesValid & RX_PROFILE_VALID) + { + if (device->rx->framer->M == 1 && !(device->rx->realIfData)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SER_INV_REAL_IF_DATA_PARM, + getMykonosErrorMessage(MYKONOS_ERR_SER_INV_REAL_IF_DATA_PARM)); + return MYKONOS_ERR_SER_INV_REAL_IF_DATA_PARM; + } + + if (device->rx->framer->M != 1 && device->rx->framer->M != 2 && device->rx->framer->M != 4) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SER_INV_M_PARM, getMykonosErrorMessage(MYKONOS_ERR_SER_INV_M_PARM)); + return MYKONOS_ERR_SER_INV_M_PARM; + } + + for (i = 0; i < 4; i++) + { + rxL += ((device->rx->framer->serializerLanesEnabled >> i) & 0x01); + } + + if (device->rx->framer->serializerLanesEnabled > 15) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SER_INV_LANEEN_PARM, + getMykonosErrorMessage(MYKONOS_ERR_SER_INV_LANEEN_PARM)); + return MYKONOS_ERR_SER_INV_LANEEN_PARM; + } + + if (device->rx->framer->serializerAmplitude > 31) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SER_INV_AMP_PARM, getMykonosErrorMessage(MYKONOS_ERR_SER_INV_AMP_PARM)); + return MYKONOS_ERR_SER_INV_AMP_PARM; + } + + if (device->rx->framer->preEmphasis > 7) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SER_INV_PREEMP_PARM, + getMykonosErrorMessage(MYKONOS_ERR_SER_INV_PREEMP_PARM)); + return MYKONOS_ERR_SER_INV_PREEMP_PARM; + } + + if (device->rx->framer->invertLanePolarity > 15) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SER_INV_LANEPN_PARM, + getMykonosErrorMessage(MYKONOS_ERR_SER_INV_LANEPN_PARM)); + return MYKONOS_ERR_SER_INV_LANEPN_PARM; + } + if ((rxL != 1) && (rxL != 2) && (rxL != 4)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SER_INV_L_PARM, getMykonosErrorMessage(MYKONOS_ERR_SER_INV_L_PARM)); + return MYKONOS_ERR_SER_INV_L_PARM; + } + + rxLaneRate_kHz = device->rx->rxProfile->iqRate_kHz * 20 * device->rx->framer->M / rxL; + lanePowerDown &= (~(device->rx->framer->serializerLanesEnabled)); + + if ((rxLaneRate_kHz < MIN_SERIALIZER_RATE_KHZ) || (rxLaneRate_kHz > MAX_SERIALIZER_RATE_KHZ)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SER_INV_LANERATE_PARM, + getMykonosErrorMessage(MYKONOS_ERR_SER_INV_LANERATE_PARM)); + return MYKONOS_ERR_SER_INV_LANERATE_PARM; + } + } + + if ((device->obsRx->framer != NULL) && (device->profilesValid & (ORX_PROFILE_VALID | SNIFF_PROFILE_VALID))) + { + if ((device->obsRx->framer->M == 1) && !(device->obsRx->realIfData)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SER_INV_REAL_IF_DATA_PARM, + getMykonosErrorMessage(MYKONOS_ERR_SER_INV_REAL_IF_DATA_PARM)); + return MYKONOS_ERR_SER_INV_REAL_IF_DATA_PARM; + } + + for (i = 0; i < 4; i++) + { + obsRxL += ((device->obsRx->framer->serializerLanesEnabled >> i) & 0x01); + } + + if (device->obsRx->framer->serializerLanesEnabled > 15) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SER_INV_LANEEN_PARM, + getMykonosErrorMessage(MYKONOS_ERR_SER_INV_LANEEN_PARM)); + return MYKONOS_ERR_SER_INV_LANEEN_PARM; + } + + if (device->obsRx->framer->serializerAmplitude > 31) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SER_INV_AMP_PARM, getMykonosErrorMessage(MYKONOS_ERR_SER_INV_AMP_PARM)); + return MYKONOS_ERR_SER_INV_AMP_PARM; + } + + if (device->obsRx->framer->preEmphasis > 7) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SER_INV_PREEMP_PARM, + getMykonosErrorMessage(MYKONOS_ERR_SER_INV_PREEMP_PARM)); + return MYKONOS_ERR_SER_INV_PREEMP_PARM; + } + + if (device->obsRx->framer->invertLanePolarity > 15) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SER_INV_LANEPN_PARM, + getMykonosErrorMessage(MYKONOS_ERR_SER_INV_LANEPN_PARM)); + return MYKONOS_ERR_SER_INV_LANEPN_PARM; + } + + if ((obsRxL != 0) && (obsRxL != 1) && (obsRxL != 2) && (obsRxL != 4)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SER_INV_L_PARM, getMykonosErrorMessage(MYKONOS_ERR_SER_INV_L_PARM)); + return MYKONOS_ERR_SER_INV_L_PARM; + } + + /* check for valid pointer */ + if (obsRxL == 0) + { + /* Allow ORx receiver to work but disable Obs Rx framer link - valid on a DPD-enabled transceiver */ + obsRxLaneRate_kHz = 0; + } + else if (device->profilesValid & ORX_PROFILE_VALID) + { + obsRxLaneRate_kHz = device->obsRx->orxProfile->iqRate_kHz * 20 * device->obsRx->framer->M / obsRxL; + } + else if (device->profilesValid & SNIFF_PROFILE_VALID) + { + obsRxLaneRate_kHz = device->obsRx->snifferProfile->iqRate_kHz * 20 * device->obsRx->framer->M / obsRxL; + } + + lanePowerDown &= (~(device->obsRx->framer->serializerLanesEnabled)); + + if ((obsRxLaneRate_kHz != 0) && ((obsRxLaneRate_kHz < MIN_SERIALIZER_RATE_KHZ) || (obsRxLaneRate_kHz > MAX_SERIALIZER_RATE_KHZ))) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SER_INV_LANERATE_PARM, + getMykonosErrorMessage(MYKONOS_ERR_SER_INV_LANERATE_PARM)); + return MYKONOS_ERR_SER_INV_LANERATE_PARM; + } + } + + /* checking for RX and OBSRX effective lane rates match */ + /* Need to account for oversampling, verify that the 2 lane rate are integer related */ + + if ((rxLaneRate_kHz > 0) && (obsRxLaneRate_kHz > 0)) + { + fasterLaneRate_kHz = (rxLaneRate_kHz >= obsRxLaneRate_kHz) ? (rxLaneRate_kHz) : (obsRxLaneRate_kHz); + slowerLaneRate_kHz = (rxLaneRate_kHz >= obsRxLaneRate_kHz) ? (obsRxLaneRate_kHz) : (rxLaneRate_kHz); + + /* Verify that lane rates are integer multiples of each other */ + if ((fasterLaneRate_kHz % slowerLaneRate_kHz) != 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SER_LANE_RATE_CONFLICT_PARM, + getMykonosErrorMessage(MYKONOS_ERR_SER_LANE_RATE_CONFLICT_PARM)); + return MYKONOS_ERR_SER_LANE_RATE_CONFLICT_PARM; + } + } + else + { + fasterLaneRate_kHz = (rxLaneRate_kHz >= obsRxLaneRate_kHz) ? (rxLaneRate_kHz) : (obsRxLaneRate_kHz); + } + + /* performing integer multiple check on HS clock and lane rate clock */ + if (fasterLaneRate_kHz == 0) + { + /* All serializer lanes are disabled */ + txser_div = 1; + txser_div_reg = 0; + serializerHalfRateReg = 0; + } + else + { + if ((fasterLaneRate_kHz > hsclkRate_kHz) || + (fasterLaneRate_kHz > MAX_SERIALIZER_RATE_KHZ)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SER_INV_LANERATE_PARM, + getMykonosErrorMessage(MYKONOS_ERR_SER_INV_LANERATE_PARM)); + return MYKONOS_ERR_SER_INV_LANERATE_PARM; + } + + modHsLaneRate = (uint8_t)(hsclkRate_kHz % fasterLaneRate_kHz); + if (modHsLaneRate != 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_HS_AND_LANE_RATE_NOT_INTEGER_MULT, + getMykonosErrorMessage(MYKONOS_ERR_HS_AND_LANE_RATE_NOT_INTEGER_MULT)); + return MYKONOS_ERR_HS_AND_LANE_RATE_NOT_INTEGER_MULT; + } + + txser_div = (uint8_t)(hsclkRate_kHz / fasterLaneRate_kHz); /* Total serializer Divider (1,2,4,8) */ + switch (txser_div) + { + case 1: + txser_div_reg = 0; /* Divide hsclk by 1 */ + serializerHalfRateReg = 0; /* 0 = divide serializer clock by 1 */ + break; + case 2: + txser_div_reg = 1; /* Divide hsclk by 2 */ + serializerHalfRateReg = 0; /* 0 = divide serializer clock by 1 */ + break; + case 4: + txser_div_reg = 2; /* Divide hsclk by 4 */ + serializerHalfRateReg = 0; /* 0 = divide serializer clock by 1 */ + break; + case 8: + txser_div_reg = 2; /* Divide hsclk by 4 */ + serializerHalfRateReg = 1; /* 1 = divide serializer clock by 2 */ + break; + default: + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SER_INV_TXSER_DIV_PARM, + getMykonosErrorMessage(MYKONOS_ERR_SER_INV_TXSER_DIV_PARM)); + return MYKONOS_ERR_SER_INV_TXSER_DIV_PARM; + } + } + + if (device->profilesValid & RX_PROFILE_VALID) + { + amplitudeEmphasis = ((device->rx->framer->serializerAmplitude & 0x1f) << 3) | (device->rx->framer->preEmphasis & 0x07); + } + else if (device->profilesValid & (ORX_PROFILE_VALID | SNIFF_PROFILE_VALID)) + { + amplitudeEmphasis = ((device->obsRx->framer->serializerAmplitude & 0x1f) << 3) | (device->obsRx->framer->preEmphasis & 0x07); + } + else + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INITSER_INV_PROFILE, getMykonosErrorMessage(MYKONOS_ERR_INITSER_INV_PROFILE)); + return MYKONOS_ERR_INITSER_INV_PROFILE; + } + + if (device->profilesValid & RX_PROFILE_VALID) + { + rxSyncbSelect = (device->rx->framer->obsRxSyncbSelect > 0) ? 1 : 0; + rxLanePn = (uint8_t)(rxSyncbSelect << 7) | (device->rx->framer->invertLanePolarity & 0xF); + } + + if (device->profilesValid & (ORX_PROFILE_VALID | SNIFF_PROFILE_VALID)) + { + obsRxSyncbSelect = (device->obsRx->framer->obsRxSyncbSelect > 0) ? 1 : 0; + obsRxLanePn = (uint8_t)(obsRxSyncbSelect << 7) | (device->obsRx->framer->invertLanePolarity & 0xF); + } + + /* Serializer lane clock frequency */ + /* serLaneClock_kHz = fasterLaneRate_kHz / txser_div / 20; */ + if (device->profilesValid & RX_PROFILE_VALID) + { + /* calculate manual PCLK frequency for Rx framer = Rx IQrate * F, where F = (2*M/L) or PCLK = lanerate /10 */ + if (device->rx->framer->overSample) + { + rxFramerPclk_kHz = fasterLaneRate_kHz / 10; + } + else + { + rxFramerPclk_kHz = rxLaneRate_kHz / 10; + } + + hsDigClkdiv4_5_kHz = hsclkRate_kHz / device->clocks->clkPllHsDiv / device->rx->rxProfile->rxDec5Decimation; + + /* PCLKDiv: 0=4x, 1=2x, 2=1x, 3=/2, 4=/4, 5=/8, 6=/16 */ + if (hsDigClkdiv4_5_kHz == rxFramerPclk_kHz) + { + rxPclkDiv = 2; + } + else if (hsDigClkdiv4_5_kHz > rxFramerPclk_kHz) + { + if (rxFramerPclk_kHz == 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_RXFRAMER_PCLKDIV_PARM, + getMykonosErrorMessage(MYKONOS_ERR_INV_RXFRAMER_PCLKDIV_PARM)); + return MYKONOS_ERR_INV_RXFRAMER_PCLKDIV_PARM; + } + + tempPclkDiv = hsDigClkdiv4_5_kHz / rxFramerPclk_kHz; + switch (tempPclkDiv) + { + case 2: + rxPclkDiv = 3; + break; + case 4: + rxPclkDiv = 4; + break; + case 8: + rxPclkDiv = 5; + break; + case 16: + rxPclkDiv = 6; + break; + default: + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_RXFRAMER_PCLKDIV_PARM, + getMykonosErrorMessage(MYKONOS_ERR_INV_RXFRAMER_PCLKDIV_PARM)); + return MYKONOS_ERR_INV_RXFRAMER_PCLKDIV_PARM; + } + } + } + else if (hsDigClkdiv4_5_kHz < rxFramerPclk_kHz) + { + tempPclkDiv = rxFramerPclk_kHz / hsDigClkdiv4_5_kHz; + switch (tempPclkDiv) + { + case 2: + rxPclkDiv = 1; + break; + case 4: + rxPclkDiv = 0; + break; + default: + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_RXFRAMER_PCLKDIV_PARM, + getMykonosErrorMessage(MYKONOS_ERR_INV_RXFRAMER_PCLKDIV_PARM)); + return MYKONOS_ERR_INV_RXFRAMER_PCLKDIV_PARM; + } + } + } + } + + if (obsRxL == 0) + { + /* Make sure PCLK is set as low as possible because it interacts with Rx Framer logic, */ + /* even though ObsRx Framer disabled */ + obsRxPclkDiv = 6; + } + else if (device->profilesValid & (ORX_PROFILE_VALID | SNIFF_PROFILE_VALID)) + { + /* calculate manual PCLK frequency for obsRx framer = obsRx IQrate * F, where F = (2*M/L) */ + if (device->profilesValid & ORX_PROFILE_VALID) + { + if (device->obsRx->framer->overSample) + { + obsRxFramerPclk_kHz = fasterLaneRate_kHz / 10; + } + else + { + obsRxFramerPclk_kHz = obsRxLaneRate_kHz / 10; + } + + hsDigClkdiv4_5_kHz = hsclkRate_kHz / device->clocks->clkPllHsDiv / device->obsRx->orxProfile->rxDec5Decimation; + } + else if (device->profilesValid & SNIFF_PROFILE_VALID) + { + if (device->obsRx->framer->overSample) + { + obsRxFramerPclk_kHz = fasterLaneRate_kHz / 10; + } + else + { + obsRxFramerPclk_kHz = obsRxLaneRate_kHz / 10; + } + + hsDigClkdiv4_5_kHz = hsclkRate_kHz / device->clocks->clkPllHsDiv / device->obsRx->snifferProfile->rxDec5Decimation; + } + + /* PCLKDiv: 0=4x, 1=2x, 2=1x, 3=/2, 4=/4, 5=/8, 6=/16 */ + if (hsDigClkdiv4_5_kHz == obsRxFramerPclk_kHz) + { + obsRxPclkDiv = 2; + } + else if ((hsDigClkdiv4_5_kHz > obsRxFramerPclk_kHz) && (obsRxFramerPclk_kHz != 0)) + { + tempPclkDiv = hsDigClkdiv4_5_kHz / obsRxFramerPclk_kHz; + switch (tempPclkDiv) + { + case 2: + obsRxPclkDiv = 3; + break; + case 4: + obsRxPclkDiv = 4; + break; + case 8: + obsRxPclkDiv = 5; + break; + case 16: + obsRxPclkDiv = 6; + break; + default: + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_OBSRXFRAMER_PCLKDIV_PARM, + getMykonosErrorMessage(MYKONOS_ERR_INV_OBSRXFRAMER_PCLKDIV_PARM)); + return MYKONOS_ERR_INV_OBSRXFRAMER_PCLKDIV_PARM; + } + } + } + else if (hsDigClkdiv4_5_kHz < obsRxFramerPclk_kHz) + { + if (hsDigClkdiv4_5_kHz == 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_OBSRXFRAMER_PCLKDIV_PARM, + getMykonosErrorMessage(MYKONOS_ERR_INV_OBSRXFRAMER_PCLKDIV_PARM)); + return MYKONOS_ERR_INV_OBSRXFRAMER_PCLKDIV_PARM; + } + + tempPclkDiv = obsRxFramerPclk_kHz / hsDigClkdiv4_5_kHz; + switch (tempPclkDiv) + { + case 2: + obsRxPclkDiv = 1; + break; + case 4: + obsRxPclkDiv = 0; + break; + default: + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_OBSRXFRAMER_PCLKDIV_PARM, + getMykonosErrorMessage(MYKONOS_ERR_INV_OBSRXFRAMER_PCLKDIV_PARM)); + return MYKONOS_ERR_INV_OBSRXFRAMER_PCLKDIV_PARM; + } + } + } + } + + /* set lane rate divide setting */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_CLOCK_CONTROL_3, txser_div_reg, 0x03, 0); + + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_SERIALIZER_CTL_2, amplitudeEmphasis); + + /* Serializer: Release Reset */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_SERIALIZER_SPECIAL, 0x03); + + /* Serializer: txser clk enable */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_SERIALIZER_HS_DIV_TXSER_CLK_EN, 0x01); + + /* Serializer: Enable 2 to 1 serializer */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_SERIALIZER_CTL_3, 0x20 | serializerHalfRateReg); + + /* power up desired serializer lanes */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_SERIALIZER_CTL_1, lanePowerDown); + + /* apply desired lane PN inversions to the TX and OBSRX framers */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_LANE_DATA_CTL, rxLanePn); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_LANE_DATA_CTL, obsRxLanePn); + + /* set Rx framer manual PCLK frequency based on lane rate of the serializers */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_FRAMER_CLK_EN, (uint8_t)rxPclkDiv, 0x70, 4); + + /* enable bit repeat mode in Rx framer - since manual PCLK, oversample will still work */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_FRAMER_CLK_EN, 0, 0x80, 7); + + /* enable manual PCLK mode in Rx framer */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_FRAMER_CLK_EN, 1, 0x04, 2); + + /* set obsRx framer manual PCLK frequency based on lane rate of the serializers */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_CLK_EN, (uint8_t)obsRxPclkDiv, 0x70, 4); + + /* enable bit repeat mode in ObsRx framer - since manual PCLK, oversample will still work */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_CLK_EN, 0, 0x80, 7); + + /* enable manual PCLK mode in ObsRx framer */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_CLK_EN, 1, 0x04, 2); + + return MYKONOS_ERR_OK; +} + +/** + * \brief Sets up the JESD204B Deserializers + * + * This function enables the necessary deserializer lanes, sets the deserializer clocks + * PN inversion settings, and EQ settings based on the info found in the device data structure. + * + * Dependencies + * - device->spiSettings + * - device->spiSettings->chipSelectIndex + * - device->tx->txProfile->clkPllVcoDiv + * - device->tx->txProfile->vcoFreq_kHz + * - device->tx->txProfile->txIqRate_kHz + * - device->tx->deframer->M + * - device->tx->deframer->deserializerLanesEnabled + * - device->tx->deframer->invertLanePolarity + * - device->tx->deframer->EQSetting + * + * \param device Pointer to the device settings structure + + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_INITDES_INV_TXPROFILE Tx Profile is not valid in data structure - can not setup deserializer + * \retval MYKONOS_ERR_INITDES_INV_VCODIV_PARM Mykonos CLKPLL VCO divider is invalid + * \retval MYKONOS_ERR_DESER_INV_M_PARM Invalid M (valid 2 or 4) + * \retval MYKONOS_ERR_DESER_INV_L_PARM Invalid L (valid 1,2,4) + * \retval MYKONOS_ERR_DESER_INV_HSCLK_PARM Invalid HSCLK, must be 6.144G or less after CLKPLL VCO divider - verify CLKPLL config + * \retval MYKONOS_ERR_DESER_INV_LANERATE_PARM Invalid lanerate, must be between 614.4 Mbps to 6144 Mbps + * \retval MYKONOS_ERR_DESER_INV_LANEEN_PARM Invalid deserializerLanesEnabled (valid 0-15 in 1,2,4 lane combinations) + * \retval MYKONOS_ERR_DESER_INV_EQ_PARM Invalid EQ parameter (valid 0-4) + * \retval MYKONOS_ERR_DESER_INV_LANEPN_PARM Invalid PN invert setting, (valid 0-15, invert bit per lane) + * \retval MYKONOS_ERR_DES_HS_AND_LANE_RATE_NOT_INTEGER_MULT Invalid clock settings, HSCLK is not an integer multiple of lane rate + * + */ +mykonosErr_t MYKONOS_setupDeserializers(mykonosDevice_t *device) +{ + uint8_t lanePowerDown = 0xF; + uint8_t des_div = 0; + uint8_t des_div_bitfield = 0; + uint8_t rxcdr_div = 0; + uint8_t rxcdr_div_bitfield = 0; + uint32_t hsclkRate_kHz = 0; + uint8_t i = 0; + uint8_t L = 0; + uint32_t laneRate_kHz = 0; + uint8_t invertLanePolarity = 0; + uint8_t modHsLaneRate = 0; + + const uint32_t MAX_HSCLKRATE_KHZ = 12288000; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setupDeserializers()\n"); +#endif + + if ((device->profilesValid & TX_PROFILE_VALID) == 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INITDES_INV_TXPROFILE, + getMykonosErrorMessage(MYKONOS_ERR_INITDES_INV_TXPROFILE)); + return MYKONOS_ERR_INITDES_INV_TXPROFILE; + } + + if (device->tx->deframer->M != 2 && device->tx->deframer->M != 4) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DESER_INV_M_PARM, getMykonosErrorMessage(MYKONOS_ERR_DESER_INV_M_PARM)); + return MYKONOS_ERR_DESER_INV_M_PARM; + } + + for (i = 0; i < 4; i++) + { + L += ((device->tx->deframer->deserializerLanesEnabled >> i) & 0x01); + } + + if ((L == 0) || (L == 3) || (L > 4)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DESER_INV_L_PARM, getMykonosErrorMessage(MYKONOS_ERR_DESER_INV_L_PARM)); + return MYKONOS_ERR_DESER_INV_L_PARM; + } + + //laneRate_kHz calculation and checks + laneRate_kHz = device->tx->txProfile->iqRate_kHz * 20 * device->tx->deframer->M / L; + + if ((laneRate_kHz < 614400) || (laneRate_kHz > 6144000)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DESER_INV_LANERATE_PARM, + getMykonosErrorMessage(MYKONOS_ERR_DESER_INV_LANERATE_PARM)); + return MYKONOS_ERR_DESER_INV_LANERATE_PARM; + } + + if (device->tx->deframer->deserializerLanesEnabled > 15) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DESER_INV_LANEEN_PARM, + getMykonosErrorMessage(MYKONOS_ERR_DESER_INV_LANEEN_PARM)); + return MYKONOS_ERR_DESER_INV_LANEEN_PARM; + } + + if ((device->tx->deframer->deserializerLanesEnabled == 0x7) || (device->tx->deframer->deserializerLanesEnabled == 0xB) + || (device->tx->deframer->deserializerLanesEnabled == 0xD) || (device->tx->deframer->deserializerLanesEnabled == 0xE)) + { + /* 3 lanes not valid, only 1,2, or 4 lanes */ + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DESER_INV_LANEEN_PARM, + getMykonosErrorMessage(MYKONOS_ERR_DESER_INV_LANEEN_PARM)); + return MYKONOS_ERR_DESER_INV_LANEEN_PARM; + } + + if (device->tx->deframer->EQSetting > 4) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DESER_INV_EQ_PARM, getMykonosErrorMessage(MYKONOS_ERR_DESER_INV_EQ_PARM)); + return MYKONOS_ERR_DESER_INV_EQ_PARM; + } + + if (device->tx->deframer->invertLanePolarity > 15) + { + /* only lower 4 bits of parameter are valid */ + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DESER_INV_LANEPN_PARM, + getMykonosErrorMessage(MYKONOS_ERR_DESER_INV_LANEPN_PARM)); + return MYKONOS_ERR_DESER_INV_LANEPN_PARM; + } + + //hsclkRate_kHz calculations + switch (device->clocks->clkPllVcoDiv) + { + case VCODIV_1: + hsclkRate_kHz = device->clocks->clkPllVcoFreq_kHz; + break; + case VCODIV_1p5: + hsclkRate_kHz = (device->clocks->clkPllVcoFreq_kHz / 15) * 10; + break; + case VCODIV_2: + hsclkRate_kHz = device->clocks->clkPllVcoFreq_kHz >> 1; + break; + case VCODIV_3: + hsclkRate_kHz = (device->clocks->clkPllVcoFreq_kHz / 30) * 10; + break; + default: + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INITDES_INV_VCODIV_PARM, + getMykonosErrorMessage(MYKONOS_ERR_INITDES_INV_VCODIV_PARM)); + return MYKONOS_ERR_INITDES_INV_VCODIV_PARM; + } + + /* The deserializer clock needs to be in the range 3.8GHz to 6.144 GHz in reg x107. The rest of the division is in xDD */ + if (hsclkRate_kHz <= 6144000) + { + rxcdr_div = 1; + } + else if ((hsclkRate_kHz > 6144000) && (hsclkRate_kHz <= MAX_HSCLKRATE_KHZ)) + { + rxcdr_div = 2; + } + else if ((hsclkRate_kHz > MAX_HSCLKRATE_KHZ) && (hsclkRate_kHz < 24576000)) + { + rxcdr_div = 4; + } + else + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DESER_INV_HSCLK_PARM, + getMykonosErrorMessage(MYKONOS_ERR_DESER_INV_HSCLK_PARM)); + return MYKONOS_ERR_DESER_INV_HSCLK_PARM; + } + + switch (rxcdr_div) + { + case 1: + rxcdr_div_bitfield = 0; + break; + case 2: + rxcdr_div_bitfield = 1; + break; + + default: + /* Default case is when rxcdr_div == 4 */ + rxcdr_div_bitfield = 2; + break; + } + + /* performing integer multiple check on HS clock and lane rate clock */ + modHsLaneRate = (uint8_t)(hsclkRate_kHz % laneRate_kHz); + if (modHsLaneRate) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DES_HS_AND_LANE_RATE_NOT_INTEGER_MULT, + getMykonosErrorMessage(MYKONOS_ERR_DES_HS_AND_LANE_RATE_NOT_INTEGER_MULT)); + return MYKONOS_ERR_DES_HS_AND_LANE_RATE_NOT_INTEGER_MULT; + } + + des_div = (uint8_t)(hsclkRate_kHz / laneRate_kHz / rxcdr_div); + + switch (des_div) + { + case 1: + des_div_bitfield = 0; + break; + case 2: + des_div_bitfield = 1; + break; + case 4: + des_div_bitfield = 2; + break; + case 8: + des_div_bitfield = 3; + break; + default: + des_div_bitfield = 0; + break; + } + + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_CLOCK_CONTROL_3, rxcdr_div_bitfield, 0x0C, 0x02); + + invertLanePolarity = (device->tx->deframer->invertLanePolarity & 0xF); + + lanePowerDown = (~(device->tx->deframer->deserializerLanesEnabled)) & 0xF; + + /* Deserializer: PLL clock enable */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DESERIALIZER_HS_DIV_RXCDR_CLK_EN, 0x01); + + /* Deserializer: Set Pdet control */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DESERIALIZER_PDET_CTL, 0x09); + + /* Deserializer: Set Power down control */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DESERIALIZER_CTL_0, (0x80U | lanePowerDown | (uint8_t)(des_div_bitfield << 4))); + + /* Deserializer: Set Sine Shape */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DESERIALIZER_SIN_SHAPE_0, 0x00); + + /* Deserializer: Set ss gain and vga */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DESERIALIZER_SIN_SHAPE_1, 0x00); + + /* Deserializer: Enable EQ, AC coupled JESD204B lanes */ + /* TODO: add ability to set this for AC coupling or DC coupling */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DESERIALIZER_EQ_CTL_1, 0x07); + + /* Deserializer: Clear Data present at negedge, disable peak adjust */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DESERIALIZER_MISC_CTL, 0x04); + + /* Deserializer: Set Equalizer for lanes 1 and 0 */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DESERIALIZER_EQ_CTL_1_TO_0, ((uint8_t)(device->tx->deframer->EQSetting << 3) | device->tx->deframer->EQSetting)); + + /* Deserializer: Set Equalizer for lanes 2 and 3 */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DESERIALIZER_EQ_CTL_3_TO_2, ((uint8_t)(device->tx->deframer->EQSetting << 3) | device->tx->deframer->EQSetting)); + + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_LANE_DATA_CTL, invertLanePolarity); + + /* Reset Deserializers - toggle resetb bit in [0] */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DESERIALIZER_SPECIAL, 0x00); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DESERIALIZER_SPECIAL, 0x01); + + /* Start ALC cal */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DESERIALIZER_CDR_CAL_CTL, 0x02); + + /* Deframer: Enable clocks and lane clocks */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_CLK_EN, 0x03); + + return MYKONOS_ERR_OK; +} + +/** + * \brief Sets up the JESD204B Framer + * + * Dependencies + * - device->spiSettings + * - device->spiSettings->chipSelectIndex + * - device->rx->framer->M + * - device->rx->realIfData + * - device->rx->framer->bankId + * - device->rx->framer->lane0Id + * - device->rx->framer->serializerLanesEnabled + * - device->rx->framer->obsRxSyncbSelect + * - device->rx->framer->K + * - device->rx->framer->externalSysref + * - device->rx->rxChannels + * - device->rx->framer->newSysrefOnRelink + * - device->rx->framer->enableAutoChanXbar + * - device->rx->framer->lmfcOffset + * - device->rx->framer->scramble + * + * \param device Pointer to the device settings structure + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_FRAMER_INV_REAL_IF_DATA_PARM Invalid framer M, M can only = 1 in real IF mode + * \retval MYKONOS_ERR_FRAMER_INV_M_PARM Invalid framer M (valid 1,2,4) + * \retval MYKONOS_ERR_FRAMER_INV_BANKID_PARM Invalid BankId (valid 0-15) + * \retval MYKONOS_ERR_FRAMER_INV_LANEID_PARM Invalid Lane0Id (valid 0-31) + * \retval MYKONOS_ERR_RXFRAMER_INV_FK_PARAM + * \retval MYKONOS_ERR_FRAMER_INV_K_OFFSET_PARAM + */ +mykonosErr_t MYKONOS_setupJesd204bFramer(mykonosDevice_t *device) +{ + uint8_t i = 0; + uint8_t fifoLaneEnable = 0; + uint8_t L = 0; + uint8_t ML = 0; + uint8_t framerConfigF = 0; + + uint8_t subaddr[29] = {0}; /* holds address to framer sub register map */ + uint8_t subdata[29] = {0}; /* holds data for framer sub register map */ + + /* Setup submap registers */ + uint8_t SUBCLASSV = 1; /* JESD subclass 1 */ + uint8_t JESDV = 1; /* Version: JESD204B */ + uint8_t DID = 0; + uint8_t BID = 0; + uint8_t LID0 = 0; + uint8_t LID1 = 1; + uint8_t LID2 = 2; + uint8_t LID3 = 3; + uint8_t CS = 0; + uint8_t N = 0x0F; + uint8_t Np = 0x0F; + uint8_t S = 0; + uint8_t CF = 0; + uint8_t K = 31; + uint8_t HD = 0; + uint8_t FramerL = 1; + uint8_t FramerM = 2; + uint8_t FramerF = 1; + uint8_t framerADC_XBar = 0xE4; + uint16_t FK = 0; + + uint8_t regE0 = 0; + uint8_t regE2 = 0; + uint8_t framerLaneXbar = 0xE4; + uint16_t CheckSum = 0; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setupJesd204bFramer()\n"); +#endif + + if (device->rx->framer->M == 1 && !(device->rx->realIfData)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_FRAMER_INV_REAL_IF_DATA_PARM, + getMykonosErrorMessage(MYKONOS_ERR_FRAMER_INV_REAL_IF_DATA_PARM)); + return MYKONOS_ERR_FRAMER_INV_REAL_IF_DATA_PARM; + } + + if (device->rx->framer->M != 1 && device->rx->framer->M != 2 && device->rx->framer->M != 4) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_FRAMER_INV_M_PARM, getMykonosErrorMessage(MYKONOS_ERR_FRAMER_INV_M_PARM)); + return MYKONOS_ERR_FRAMER_INV_M_PARM; + } + + if (device->rx->framer->bankId > 15) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_FRAMER_INV_BANKID_PARM, + getMykonosErrorMessage(MYKONOS_ERR_FRAMER_INV_BANKID_PARM)); + return MYKONOS_ERR_FRAMER_INV_BANKID_PARM; + } + + /* no need to check deviceId, its range is full uint8_t range */ + if (device->rx->framer->lane0Id > 31) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_FRAMER_INV_LANEID_PARM, + getMykonosErrorMessage(MYKONOS_ERR_FRAMER_INV_LANEID_PARM)); + return MYKONOS_ERR_FRAMER_INV_LANEID_PARM; + } + + //count number of lanes + L = 0; + ML = 0; + + for (i = 0; i < 4; i++) + { + L += ((device->rx->framer->serializerLanesEnabled >> i) & 0x01); + } + ML = (uint8_t)(device->rx->framer->M * 10) + L; + + FK = (uint16_t)(device->rx->framer->K * 2 * device->rx->framer->M / L); + + if (FK < 20 || FK > 256 || FK % 4 != 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RXFRAMER_INV_FK_PARAM, + getMykonosErrorMessage(MYKONOS_ERR_RXFRAMER_INV_FK_PARAM)); + return MYKONOS_ERR_RXFRAMER_INV_FK_PARAM; + } + + if (device->rx->framer->externalSysref == 0) + { + /* Framer: Generate SYSREF internally */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_TEST_CNTR_CTL, 0x20); + } + + framerADC_XBar = 0xB1; + if (ML == 24) + { + if (device->rx->rxChannels == RX1) + { + /* adc 0 and 2 used */ + framerADC_XBar = ((framerADC_XBar & 0x0C) << 2) | (framerADC_XBar & 0x03); + } + else if (device->rx->rxChannels == RX2) + { + /* swap ADC xbar for Rx1 and Rx2 */ + framerADC_XBar = ((framerADC_XBar & 0xF) << 4) | ((framerADC_XBar & 0xF0) >> 4); + /* adc 0 and 2 used */ + framerADC_XBar = ((framerADC_XBar & 0x0C) << 2) | (framerADC_XBar & 0x03); + } + + /* Framer: Set ADC Crossbar */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_ADC_XBAR_SEL, framerADC_XBar); + } + else + { + /* Framer: Set ADC Crossbar */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_ADC_XBAR_SEL, framerADC_XBar); + } + + if (device->rx->framer->enableManualLaneXbar == 1) + { + framerLaneXbar = device->rx->framer->serializerLaneCrossbar; + } + else + { + if (ML == 42) + { + /* uses framer outputs 0 and 2 instead of 0 and 1...fix framer lane XBar */ + /* only 2 lane cases here */ + switch ((device->rx->framer->serializerLanesEnabled & 0x0F)) + { + case 3: + framerLaneXbar = 0x08; + break; + case 5: + framerLaneXbar = 0x20; + break; + case 6: + framerLaneXbar = 0x20; + break; + case 9: + framerLaneXbar = 0x80; + break; + case 10: + framerLaneXbar = 0x80; + break; + case 12: + framerLaneXbar = 0x80; + break; + default: + /* default to valid setting for Lane 0 */ + framerLaneXbar = 0x08; + break; + } + } + else + { + switch ((device->rx->framer->serializerLanesEnabled & 0x0F)) + { + /* all 4 lanes get framer 0 output */ + case 1: + framerLaneXbar = 0x00; + break; + case 2: + framerLaneXbar = 0x00; + break; + case 3: + framerLaneXbar = 0x04; + break; + case 4: + framerLaneXbar = 0x00; + break; + case 5: + framerLaneXbar = 0x10; + break; + case 6: + framerLaneXbar = 0x10; + break; + case 8: + framerLaneXbar = 0x00; + break; + case 9: + framerLaneXbar = 0x40; + break; + case 10: + framerLaneXbar = 0x40; + break; + case 12: + framerLaneXbar = 0x40; + break; + case 15: + framerLaneXbar = 0xE4; + break; + default: + /* default to valid setting for all Lanes */ + framerLaneXbar = 0xE4; + break; + } + } + } + + /* Framer: Set Lane Crossbar */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_LANE_XBAR_SEL, framerLaneXbar); + + if (ML == 24) + { + /* Framer: Clear ADC Xbar channel auto switch */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_CONFIG_LOOPBACK_XBAR_REV, 0x00); + } + else + { + /* Framer: Set ADC Xbar channel auto switch */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_CONFIG_LOOPBACK_XBAR_REV, 0x04); + } + + /* enabling the SYSREF for relink if newSysrefOnRelink is set */ + if (device->rx->framer->newSysrefOnRelink) + { + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_FRAMER_SYSREF_FIFO_EN, 0x01, 0x40, 6); + } + + /* enabling auto channel if the enableAutoChanXbar structure member is set */ + if (device->rx->framer->enableAutoChanXbar) + { + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_FRAMER_CONFIG_LOOPBACK_XBAR_REV, 0x01, 0x04, 2); + } + + /* determining F octets per frame based on 2*M/L */ + framerConfigF = (uint8_t)(2 * (device->rx->framer->M / L)); + + /* Framer: Soft Reset */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_RESET, 0x03); + + /* Framer: Clear Soft Reset */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_RESET, 0x00); + + /* Framer: Set F (Octets in Frame) */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_CONFIG_F, framerConfigF); + + /* Framer: Enable framer clock and lane clocks */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_FRAMER_CLK_EN, 0x03, 0x03, 0); + + /* Set Framer lane FIFO enable for each lane enabled */ + fifoLaneEnable = (((device->rx->framer->serializerLanesEnabled & 0x0F) << 4) | 0x01); + + /* Framer: Enable Lane FIFOs */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_LANE_CTL, fifoLaneEnable); + + /* Setup submap registers */ + SUBCLASSV = 1; /* JESD subclass 1 */ + JESDV = 1; /* Version: JESD204B */ + DID = device->rx->framer->deviceId; + BID = device->rx->framer->bankId; + LID0 = device->rx->framer->lane0Id; + LID1 = device->rx->framer->lane0Id + 1; + LID2 = device->rx->framer->lane0Id + 2; + LID3 = device->rx->framer->lane0Id + 3; + + CS = 0; + N = 0x0F; + Np = 0x0F; + S = 0; + CF = 0; + HD = 0; + K = device->rx->framer->K - 1; + FramerL = L - 1; + FramerM = device->rx->framer->M - 1; + FramerF = (uint8_t)(2 * device->rx->framer->M / L) - 1; + + if (ML == 11) + { + regE0 = 0x01; + regE2 = 0x01; + } + else if (ML == 12) + { + regE0 = 0x01; + regE2 = 0x03; + HD = 0x01; + } + else if (ML == 21) + { + regE0 = 0x03; + regE2 = 0x01; + } + else if (ML == 22) + { + regE0 = 0x03; + regE2 = 0x03; + } + else if (ML == 24) + { + regE0 = 0x05; + regE2 = 0x0F; + HD = 0x01; + } + else if (ML == 41) + { + regE0 = 0x0F; + regE2 = 0x01; + } + else if (ML == 42) + { + regE0 = 0x0F; + regE2 = 0x05; + } + else if (ML == 44) + { + regE0 = 0x0F; + regE2 = 0x0F; + } + else + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_FRAMER_INV_M_PARM, getMykonosErrorMessage(MYKONOS_ERR_FRAMER_INV_M_PARM)); + return MYKONOS_ERR_FRAMER_INV_M_PARM; + } + + /* setting K offset for framer */ + if (device->rx->framer->lmfcOffset < device->rx->framer->K) + { + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_LMFC_K_OFFSET, device->rx->framer->lmfcOffset); + } + else + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_FRAMER_INV_K_OFFSET_PARAM, + getMykonosErrorMessage(MYKONOS_ERR_FRAMER_INV_K_OFFSET_PARAM)); + return MYKONOS_ERR_FRAMER_INV_K_OFFSET_PARAM; + } + + subaddr[0] = 0x00; + subdata[0] = (DID & 0xFF); /* Device ID */ + subaddr[1] = 0x01; + subdata[1] = (BID & 0x0F); /* Bank ID */ + subaddr[2] = 0x02; + subdata[2] = (LID0 & 0x1F); /* Lane 0 ID */ + subaddr[3] = 0x03; + subdata[3] = (uint8_t)(device->rx->framer->scramble << 7) | (FramerL & 0x1F); /* [7] Scramble, #Lanes[4:0]-1 */ + subaddr[4] = 0x04; + subdata[4] = (FramerF & 0xFF); /* F[7:0]-1 */ + subaddr[5] = 0x05; + subdata[5] = (K & 0x1F); /* K[4:0]-1 */ + subaddr[6] = 0x06; + subdata[6] = (FramerM & 0xFF); /* M[7:0]-1 */ + subaddr[7] = 0x07; + subdata[7] = ((CS & 0x3) << 6) | (N & 0x1F); /* [7:6] = CS[1:0], N[4:0]-1 */ + subaddr[8] = 0x08; + subdata[8] = ((SUBCLASSV & 7) << 5) | (Np & 0x1F); /* NP[4:0] -1 */ + subaddr[9] = 0x09; + subdata[9] = ((JESDV & 7) << 5) | (S & 0x1F); /* S[4:0]-1 */ + subaddr[10] = 0x0A; + subdata[10] = ((HD & 1) << 7) | (CF & 0x1F); /* [7] = HD, CF[4:0] */ + subaddr[11] = 0x0B; + subdata[11] = 0x00; /* reserved */ + subaddr[12] = 0x0C; + subdata[12] = 0x00; /* reserved */ + + CheckSum = (DID & 0xFF) + (BID & 0xF) + (LID0 & 0x1F) + (device->rx->framer->scramble) + (FramerL & 0x1F) + (FramerF & 0xFF) + (K & 0x1F) + (FramerM & 0xFF) + + (CS & 0x3) + (N & 0x1F) + (Np & 0x1F) + (S & 0x1F) + (HD & 1) + (CF & 0x1F) + (SUBCLASSV & 7) + (JESDV & 7); + + /* Checksum Lane 0 */ + subaddr[13] = 0x0D; + subdata[13] = CheckSum & 0xFF; + + /* in JESD204B ML=42 case, framer ip lanes 0 and 2 are used, write lane 1 id and checksum to ip lane 2 regs */ + if (ML == 42) + { + /* Lane 1 ID */ + subaddr[14] = 0x1A; + subdata[14] = LID1; + + CheckSum = (DID & 0xFF) + (BID & 0xF) + (LID1 & 0x1F) + (device->rx->framer->scramble) + (FramerL & 0x1F) + (FramerF & 0xFF) + (K & 0x1F) + (FramerM & 0xFF) + + (CS & 0x3) + (N & 0x1F) + (Np & 0x1F) + (S & 0x1F) + (HD & 1) + (CF & 0x1F) + (SUBCLASSV & 7) + (JESDV & 7); + + /* Checksum Lane 1 */ + subaddr[15] = 0x1D; + subdata[15] = CheckSum & 0xFF; + } + else + { + /* Lane 1 ID */ + subaddr[14] = 0x12; + subdata[14] = LID1; + + CheckSum = (DID & 0xFF) + (BID & 0xF) + (LID1 & 0x1F) + (device->rx->framer->scramble) + (FramerL & 0x1F) + (FramerF & 0xFF) + (K & 0x1F) + (FramerM & 0xFF) + + (CS & 0x3) + (N & 0x1F) + (Np & 0x1F) + (S & 0x1F) + (HD & 1) + (CF & 0x1F) + (SUBCLASSV & 7) + (JESDV & 7); + + /* Checksum Lane 1 */ + subaddr[15] = 0x15; + subdata[15] = CheckSum & 0xFF; + + /* Lane 2 ID */ + subaddr[16] = 0x1A; + subdata[16] = LID2; + + CheckSum = (DID & 0xFF) + (BID & 0xF) + (LID2 & 0x1F) + (device->rx->framer->scramble) + (FramerL & 0x1F) + (FramerF & 0xFF) + (K & 0x1F) + (FramerM & 0xFF) + + (CS & 0x3) + (N & 0x1F) + (Np & 0x1F) + (S & 0x1F) + (HD & 1) + (CF & 0x1F) + (SUBCLASSV & 7) + (JESDV & 7); + + /* Checksum Lane 2 */ + subaddr[17] = 0x1D; + subdata[17] = CheckSum & 0xFF; + + /* Lane 3 ID */ + subaddr[18] = 0x22; + subdata[18] = LID3; + + CheckSum = (DID & 0xFF) + (BID & 0xF) + (LID3 & 0x1F) + (device->rx->framer->scramble) + (FramerL & 0x1F) + (FramerF & 0xFF) + (K & 0x1F) + (FramerM & 0xFF) + + (CS & 0x3) + (N & 0x1F) + (Np & 0x1F) + (S & 0x1F) + (HD & 1) + (CF & 0x1F) + (SUBCLASSV & 7) + (JESDV & 7); + + subaddr[19] = 0x25; + subdata[19] = CheckSum & 0xFF; + } + + subaddr[20] = 0xE0; + subdata[20] = regE0; /* Enable converter n logic */ + subaddr[21] = 0xE2; + subdata[21] = regE2; /* Enable Lane n logic */ + subaddr[22] = 0xE4; + subdata[22] = 0x00; + subaddr[23] = 0xE6; + subdata[23] = 0x00; + subaddr[24] = 0xF0; + subdata[24] = 0x00; /* #multiframes in ILAS */ + subaddr[25] = 0xF2; + subdata[25] = 0x00; + subaddr[26] = 0xF3; + subdata[26] = 0x00; + subaddr[27] = 0xF4; + subdata[27] = 0x00; + subaddr[28] = 0xC0; + subdata[28] = 0x03; /* Framer enable, both sides perform lane sync */ + + for (i = 0; i <= 28; i++) + { + /* Set framer sub register map address */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_ADDR, subaddr[i]); + + /* Set framer sub register map data word */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_DATA, subdata[i]); + + /* Write enable */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_WRITE_EN, 0x01); + } + + if (device->rx->framer->externalSysref > 0) + { + /* Framer: Enable lane FIFO sync (Enable CGS) */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_SYSREF_FIFO_EN, 0x30); + } + else + { + /* Framer: Enable lane FIFO sync (Enable CGS) */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_SYSREF_FIFO_EN, 0x10); + } + + return MYKONOS_ERR_OK; +} + +/** + * \brief Sets up the JESD204B OBSRX Framer + * + * Dependencies + * - device->rxChannels + * - device->spiSettings->chipSelectIndex + * - device->obsRx->framer->bankId + * - device->obsRx->framer->M + * - device->obsRx->framer->serializerLanesEnabled + * - device->obsRx->framer->externalSysref + * - device->spiSettings + * - device->obsRx->framer->deviceId + * - device->obsRx->framer->lane0Id + * - device->obsRx->framer->K + * - device->obsRx->framer->lmfcOffset + * - device->obsRx->framer->scramble + * - device->obsRx->framer->obsRxSyncbSelect + * + * \param device Pointer to the device settings structure + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_OBSRX_FRAMER_INV_REAL_IF_DATA_PARM M parameter can only be 1 when real IF data mode is enabled + * \retval MYKONOS_ERR_OBSRX_FRAMER_INV_M_PARM ObsRx Framer M parameter can only be 1 or 2 + * \retval MYKONOS_ERR_OBSRX_FRAMER_INV_BANKID_PARM Invalid BankId (0-15) + * \retval MYKONOS_ERR_OBSRX_FRAMER_INV_LANEID_PARM Invalid lane0Id (0-31) + * \retval MYKONOS_ERR_OBSRXFRAMER_INV_FK_PARAM Invalid F*K value (F * K must be > 20 and divisible by 4) + * \retval MYKONOS_ERR_OBSRX_FRAMER_INV_K_OFFSET_PARAM Invalid K offset, must be less than K + */ +mykonosErr_t MYKONOS_setupJesd204bObsRxFramer(mykonosDevice_t *device) +{ + uint8_t i = 0; + uint8_t laneFifoEnable = 0; + uint8_t L = 1; + uint8_t ML = 2; + uint8_t framerConfigF = 0; + + uint8_t subaddr[29] = {0}; /* holds address to framer sub register map */ + uint8_t subdata[29] = {0}; /* holds data for framer sub register map */ + + /* Setup submap registers */ + uint8_t SUBCLASSV = 1; /* JESD subclass 1 */ + uint8_t JESDV = 1; /* Version: JESD204B */ + uint8_t DID = 0; + uint8_t BID = 0; + uint8_t LID0 = 0; + uint8_t LID1 = 1; + uint8_t LID2 = 2; + uint8_t LID3 = 3; + uint8_t CS = 0; + uint8_t N = 0x0F; + uint8_t Np = 0x0F; + uint8_t S = 0; + uint8_t CF = 0; + uint8_t K = 31; + uint8_t HD = 0; + uint8_t FramerL = 1; + uint8_t FramerM = 2; + uint8_t FramerF = 1; + uint8_t framerADC_XBar = 0xE4; + uint8_t regE0 = 0; + uint8_t regE2 = 0; + uint8_t framerLaneXbar = 0xE4; + uint16_t CheckSum = 0; + uint16_t FK = 0; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setupJesd204bObsRxFramer()\n"); +#endif + + if (device->obsRx->framer->M == 1 && !(device->obsRx->realIfData)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OBSRX_FRAMER_INV_REAL_IF_DATA_PARM, + getMykonosErrorMessage(MYKONOS_ERR_OBSRX_FRAMER_INV_REAL_IF_DATA_PARM)); + return MYKONOS_ERR_OBSRX_FRAMER_INV_REAL_IF_DATA_PARM; + } + + if (device->obsRx->framer->M != 1 && device->obsRx->framer->M != 2) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OBSRX_FRAMER_INV_M_PARM, + getMykonosErrorMessage(MYKONOS_ERR_OBSRX_FRAMER_INV_M_PARM)); + return MYKONOS_ERR_OBSRX_FRAMER_INV_M_PARM; + } + + if (device->obsRx->framer->bankId > 15) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OBSRX_FRAMER_INV_BANKID_PARM, + getMykonosErrorMessage(MYKONOS_ERR_OBSRX_FRAMER_INV_BANKID_PARM)); + return MYKONOS_ERR_OBSRX_FRAMER_INV_BANKID_PARM; + } + + /* no need to check deviceId, its range is full uint8_t range */ + if (device->obsRx->framer->lane0Id > 31) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OBSRX_FRAMER_INV_LANEID_PARM, + getMykonosErrorMessage(MYKONOS_ERR_OBSRX_FRAMER_INV_LANEID_PARM)); + return MYKONOS_ERR_OBSRX_FRAMER_INV_LANEID_PARM; + } + + //count number of lanes + L = 0; + ML = 0; + + for (i = 0; i < 4; i++) + { + L += ((device->obsRx->framer->serializerLanesEnabled >> i) & 0x01); + } + + ML = (uint8_t)(device->obsRx->framer->M * 10 + L); + + if (L == 0) + { + /* Disable framer and return successfully */ + /* Disable framer clock and lane clocks */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_CLK_EN, 0, 0x03, 0); + + /* Disable lane FIFO enables */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_LANE_CTL, 0, 0xF0, 4); + return MYKONOS_ERR_OK; + } + + FK = (uint16_t)(device->obsRx->framer->K * 2 * device->obsRx->framer->M / L); + if (FK < 20 || FK > 256 || FK % 4 != 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OBSRXFRAMER_INV_FK_PARAM, + getMykonosErrorMessage(MYKONOS_ERR_OBSRXFRAMER_INV_FK_PARAM)); + return MYKONOS_ERR_OBSRXFRAMER_INV_FK_PARAM; + } + + if (device->obsRx->framer->externalSysref == 0) + { + /* Framer: Generate SYSREF internally */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_TEST_CNTR_CTL, 0x20); + } + + /* Framer: Set ADC Crossbar */ + framerADC_XBar = 0xB1; + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_ADC_XBAR_SEL, framerADC_XBar); + + if (device->obsRx->framer->enableManualLaneXbar == 1) + { + framerLaneXbar = device->obsRx->framer->serializerLaneCrossbar; + } + else + { + if (ML == 42) + { + /* uses framer outputs 0 and 2 instead of 0 and 1...fix framer lane XBar */ + /* only 2 lane cases here */ + switch ((device->obsRx->framer->serializerLanesEnabled & 0x0F)) + { + case 3: + framerLaneXbar = 0x08; + break; + case 5: + framerLaneXbar = 0x20; + break; + case 6: + framerLaneXbar = 0x20; + break; + case 9: + framerLaneXbar = 0x80; + break; + case 10: + framerLaneXbar = 0x80; + break; + case 12: + framerLaneXbar = 0x80; + break; + default: + /* default to valid setting for Lane 0 */ + framerLaneXbar = 0x08; + break; + } + } + else + { + switch ((device->obsRx->framer->serializerLanesEnabled & 0x0F)) + { + /* all 4 lanes get framer 0 output */ + case 1: + framerLaneXbar = 0x00; + break; + case 2: + framerLaneXbar = 0x00; + break; + case 3: + framerLaneXbar = 0x04; + break; + case 4: + framerLaneXbar = 0x00; + break; + case 5: + framerLaneXbar = 0x10; + break; + case 6: + framerLaneXbar = 0x10; + break; + case 8: + framerLaneXbar = 0x00; + break; + case 9: + framerLaneXbar = 0x40; + break; + case 10: + framerLaneXbar = 0x40; + break; + case 12: + framerLaneXbar = 0x40; + break; + case 15: + framerLaneXbar = 0xE4; + break; + default: + /* default to valid setting for all Lanes */ + framerLaneXbar = 0xE4; + break; + } + } + } + + /* Framer: set Lane Crossbar */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_LANE_XBAR_SEL, framerLaneXbar); + + /* Framer: determine the framerConfigF value (2*M/L) */ + framerConfigF = (uint8_t)(2 * (device->obsRx->framer->M/L)); + + /* Framer: Soft Reset */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_RESET, 0x03); + + /* Framer: Clear Soft Reset */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_RESET, 0x00); + + /* Framer: Set F (Octets in Frame) */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_CONFIG_F, framerConfigF); + + /* Framer: Enable framer clock and lane clocks */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_CLK_EN, 0x03, 0x03, 0); + + /* Set Framer lane FIFO enable for each lane enabled */ + laneFifoEnable = (uint8_t)(((device->obsRx->framer->serializerLanesEnabled & 0x0F) << 4) | 0x01); + + /* Framer: Enable Lane FIFOs */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_LANE_CTL, laneFifoEnable); + + /* enabling the SYSREF for relink if newSysrefOnRelink is set */ + if (device->obsRx->framer->newSysrefOnRelink) + { + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_SYSREF_FIFO_EN, 0x01, 0x40, 6); + } + + /* enabling auto channel if the enableAutoChanXbar structure member is set */ + if (device->obsRx->framer->enableAutoChanXbar) + { + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_CONFIG_LOOPBACK_XBAR_REV, 0x01, 0x04, 2); + } + + /* Setup submap registers */ + SUBCLASSV = 1; /* JESD subclass 1 */ + JESDV = 1; /* Version: JESD204B */ + DID = device->obsRx->framer->deviceId; + BID = device->obsRx->framer->bankId; + LID0 = device->obsRx->framer->lane0Id; + LID1 = device->obsRx->framer->lane0Id + 1; + LID2 = device->obsRx->framer->lane0Id + 2; + LID3 = device->obsRx->framer->lane0Id + 3; + + CS = 0; + N = 0x0F; + Np = 0x0F; + S = 0; + CF = 0; + K = device->obsRx->framer->K - 1; + HD = 0; + FramerL = L - 1; + FramerM = device->obsRx->framer->M - 1; + FramerF = (uint8_t)((2*device->obsRx->framer->M/L) - 1); + + if (ML == 11) + { + regE0 = 0x1; + regE2 = 0x1; + } + else if (ML == 12) + { + regE0 = 0x1; + regE2 = 0x3; + HD = 1; + } + else if (ML == 21) + { + regE0 = 0x3; + regE2 = 0x1; + } + else if (ML == 22) + { + regE0 = 0x3; + regE2 = 0x3; + } + else + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OBSRX_FRAMER_INV_M_PARM, + getMykonosErrorMessage(MYKONOS_ERR_OBSRX_FRAMER_INV_M_PARM)); + return MYKONOS_ERR_OBSRX_FRAMER_INV_M_PARM; + } + + /* setting K offset for framer */ + if (device->obsRx->framer->lmfcOffset < device->rx->framer->K) + { + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_LMFC_K_OFFSET, device->obsRx->framer->lmfcOffset); + } + else + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OBSRX_FRAMER_INV_K_OFFSET_PARAM, + getMykonosErrorMessage(MYKONOS_ERR_OBSRX_FRAMER_INV_K_OFFSET_PARAM)); + return MYKONOS_ERR_OBSRX_FRAMER_INV_K_OFFSET_PARAM; + } + + subaddr[0] = 0x00; + subdata[0] = (DID & 0xFF); /* Device ID */ + subaddr[1] = 0x01; + subdata[1] = (BID & 0x0F); /* Bank ID */ + subaddr[2] = 0x02; + subdata[2] = (LID0 & 0x1F); /* Lane 0 ID */ + subaddr[3] = 0x03; + subdata[3] = (uint8_t)(device->obsRx->framer->scramble << 7) | (FramerL & 0x1F); /* [7] Scramble, #Lanes[4:0]-1 */ + subaddr[4] = 0x04; + subdata[4] = (FramerF & 0xFF); /* F[7:0]-1 */ + subaddr[5] = 0x05; + subdata[5] = (K & 0x1F); /* K[4:0]-1 */ + subaddr[6] = 0x06; + subdata[6] = (FramerM & 0xFF); /* M[7:0]-1 */ + subaddr[7] = 0x07; + subdata[7] = ((CS & 0x3) << 6) | (N & 0x1F); /* [7:6] = CS[1:0], N[4:0]-1 */ + subaddr[8] = 0x08; + subdata[8] = ((SUBCLASSV & 7) << 5) | (Np & 0x1F); /* NP[4:0] -1 */ + subaddr[9] = 0x09; + subdata[9] = ((JESDV & 7) << 5) | (S & 0x1F); /* S[4:0]-1 */ + subaddr[10] = 0x0a; + subdata[10] = ((HD & 1) << 7) | (CF & 0x1F); /* [7] = HD, CF[4:0] */ + subaddr[11] = 0x0b; + subdata[11] = 0x00; /* reserved */ + subaddr[12] = 0x0c; + subdata[12] = 0x00; /* reserved */ + + CheckSum = (DID & 0xFF) + (BID & 0xF) + (LID0 & 0x1F) + (device->obsRx->framer->scramble) + (FramerL & 0x1F) + (FramerF & 0xFF) + (K & 0x1F) + (FramerM & 0xFF) + + (CS & 0x3) + (N & 0x1F) + (Np & 0x1F) + (S & 0x1F) + (HD & 1) + (CF & 0x1F) + (SUBCLASSV & 7) + (JESDV & 7); + + /* Checksum Lane 0 */ + subaddr[13] = 0x0d; + subdata[13] = CheckSum & 0xFF; + + /* Lane 1 ID */ + subaddr[14] = 0x12; + subdata[14] = LID1; + + CheckSum = (DID & 0xFF) + (BID & 0xF) + (LID1 & 0x1F) + (device->obsRx->framer->scramble) + (FramerL & 0x1F) + (FramerF & 0xFF) + (K & 0x1F) + (FramerM & 0xFF) + + (CS & 0x3) + (N & 0x1F) + (Np & 0x1F) + (S & 0x1F) + (HD & 1) + (CF & 0x1F) + (SUBCLASSV & 7) + (JESDV & 7); + + /* Checksum Lane 1 */ + subaddr[15] = 0x15; + subdata[15] = CheckSum & 0xFF; + + /* Lane 2 ID */ + subaddr[16] = 0x1a; + subdata[16] = LID2; + + CheckSum = (DID & 0xFF) + (BID & 0xF) + (LID2 & 0x1F) + (device->obsRx->framer->scramble) + (FramerL & 0x1F) + (FramerF & 0xFF) + (K & 0x1F) + (FramerM & 0xFF) + + (CS & 0x3) + (N & 0x1F) + (Np & 0x1F) + (S & 0x1F) + (HD & 1) + (CF & 0x1F) + (SUBCLASSV & 7) + (JESDV & 7); + + /* Checksum Lane 2 */ + subaddr[17] = 0x1d; + subdata[17] = CheckSum & 0xFF; + + /* Lane 3 ID */ + subaddr[18] = 0x22; + subdata[18] = LID3; + + CheckSum = (DID & 0xFF) + (BID & 0xF) + (LID3 & 0x1F) + (device->obsRx->framer->scramble) + (FramerL & 0x1F) + (FramerF & 0xFF) + (K & 0x1F) + (FramerM & 0xFF) + + (CS & 0x3) + (N & 0x1F) + (Np & 0x1F) + (S & 0x1F) + (HD & 1) + (CF & 0x1F) + (SUBCLASSV & 7) + (JESDV & 7); + + subaddr[19] = 0x25; + subdata[19] = CheckSum & 0xFF; + + subaddr[20] = 0xe0; + subdata[20] = regE0; /* Enable converter n logic */ + subaddr[21] = 0xe2; + subdata[21] = regE2; /* Enable Lane n logic */ + subaddr[22] = 0xe4; + subdata[22] = 0x00; + subaddr[23] = 0xe6; + subdata[23] = 0x00; + subaddr[24] = 0xf0; + subdata[24] = 0x00; /* #multiframes in ILAS */ + subaddr[25] = 0xf2; + subdata[25] = 0x00; + subaddr[26] = 0xf3; + subdata[26] = 0x00; + subaddr[27] = 0xf4; + subdata[27] = 0x00; + subaddr[28] = 0xc0; + subdata[28] = 0x03; /* Framer enable, both sides perform lane sync */ + + for (i = 0; i <= 28; i++) + { + /* Set framer sub register map address */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_ADDR, subaddr[i]); + + /* Set framer sub register map data word */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_DATA, subdata[i]); + + /* Write enable */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_WRITE_EN, 0x01); + } + + if (device->obsRx->framer->externalSysref > 0) + { + /* Framer: Enable lane FIFO sync (Enable CGS) */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_SYSREF_FIFO_EN, 0x30); + } + else + { + /* Framer: Enable lane FIFO sync (Enable CGS) */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_SYSREF_FIFO_EN, 0x10); + } + + return MYKONOS_ERR_OK; +} + +/** + * \brief Enables/Disables the JESD204B Rx Framer + * + * This function is normally not necessary. In the event that the link needs to be reset, this + * function allows the Rx framer to be disabled and re-enabled. + * + * Dependencies + * - device->spiSettings + * - device->rx->framer->serializerLanesEnabled + * + * \param device is a pointer to the device settings structure + * \param enable 0 = Disable the selected framer, 1 = enable the selected framer link + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_ENFRAMERLINK_INV_LANESEN_PARM Invalid serializerLanesEnabled parameter in device data structure + */ +mykonosErr_t MYKONOS_enableRxFramerLink(mykonosDevice_t *device, uint8_t enable) +{ + uint8_t enableLink = 0; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_enableFramerLink()\n"); +#endif + + enableLink = (enable > 0) ? 1 : 0; + + if (enableLink) + { + /* Power Up serializer lanes */ + if (device->rx->framer->serializerLanesEnabled > 15) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_ENFRAMERLINK_INV_LANESEN_PARM, + getMykonosErrorMessage(MYKONOS_ERR_ENFRAMERLINK_INV_LANESEN_PARM)); + return MYKONOS_ERR_ENFRAMERLINK_INV_LANESEN_PARM; + } + + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_SERIALIZER_CTL_1, ((~device->rx->framer->serializerLanesEnabled) & 0x0F), + device->rx->framer->serializerLanesEnabled, 0); + + /* Enable Clocks to Framer */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_FRAMER_CLK_EN, 3, 0x03, 0); + + /* Release reset to framer and lane FIFOs */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_RESET, 0x00); + } + else + { + /* Disable Link */ + /* Hold Rx framer in reset */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_RESET, 0x03); + + /* Disable Clocks to Framer */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_FRAMER_CLK_EN, 0, 0x03, 0); + + /* Power down serializer lanes */ + if (device->rx->framer->serializerLanesEnabled > 15) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_ENFRAMERLINK_INV_LANESEN_PARM, + getMykonosErrorMessage(MYKONOS_ERR_ENFRAMERLINK_INV_LANESEN_PARM)); + return MYKONOS_ERR_ENFRAMERLINK_INV_LANESEN_PARM; + } + + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_SERIALIZER_CTL_1, device->rx->framer->serializerLanesEnabled, device->rx->framer->serializerLanesEnabled, 0); + } + + return MYKONOS_ERR_OK; +} + +/** + * \brief Enables/Disables the JESD204B ObsRx Framer + * + * This function is normally not necessary. In the event that the link needs to be reset, this + * function allows the ObsRx framer to be disabled and re-enabled. + * + * Dependencies + * - device->spiSettings + * - device->obsRx->framer->serializerLanesEnabled + * + * \param device is a pointer to the device settings structure + * \param enable 0 = Disable the selected framer, 1 = enable the selected framer link + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_ENFRAMERLINK_INV_LANESEN_PARM Invalid serializerLanesEnabled parameter in device data structure (Valid 0-15) + */ +mykonosErr_t MYKONOS_enableObsRxFramerLink(mykonosDevice_t *device, uint8_t enable) +{ + uint8_t enableLink = 0; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_enableObsRxFramerLink()\n"); +#endif + + enableLink = (enable > 0) ? 1 : 0; + + if (enableLink) + { + /* Power Up serializer lanes */ + if (device->rx->framer->serializerLanesEnabled > 15) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_ENOBSFRAMERLINK_INV_LANESEN_PARM, + getMykonosErrorMessage(MYKONOS_ERR_ENOBSFRAMERLINK_INV_LANESEN_PARM)); + return MYKONOS_ERR_ENOBSFRAMERLINK_INV_LANESEN_PARM; + } + + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_SERIALIZER_CTL_1, ((~device->obsRx->framer->serializerLanesEnabled) & 0x0F), + device->obsRx->framer->serializerLanesEnabled, 0); + + /* Enable Clocks to Framer */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_CLK_EN, 3, 0x03, 0); + + /* Release reset to framer and lane FIFOs */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_RESET, 0x00); + } + else + { + /* Disable Link */ + /* Hold Rx framer in reset */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_RESET, 0x03); + + /* Disable Clocks to Framer */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_CLK_EN, 0, 0x03, 0); + + /* Power down serializer lanes */ + if (device->obsRx->framer->serializerLanesEnabled > 15) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_ENOBSFRAMERLINK_INV_LANESEN_PARM, + getMykonosErrorMessage(MYKONOS_ERR_ENOBSFRAMERLINK_INV_LANESEN_PARM)); + return MYKONOS_ERR_ENOBSFRAMERLINK_INV_LANESEN_PARM; + } + + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_SERIALIZER_CTL_1, device->obsRx->framer->serializerLanesEnabled, + device->obsRx->framer->serializerLanesEnabled, 0); + } + + return MYKONOS_ERR_OK; +} + +/** + * \brief Sets up the JESD204B Deframer + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * - device->tx->deframer->M + * - device->tx->deframer->bankId + * - device->tx->deframer->lane0Id + * - device->tx->deframer->K + * - device->tx->deframer->deserializerLanesEnabled + * - device->tx->deframer->externalSysref + * - device->tx->deframer->newSysrefOnRelink + * - device->tx->deframer->enableAutoChanXbar + * - device->tx->deframer->lmfcOffset + * - device->tx->deframer->scramble + * + * \param device Pointer to device settings structure + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_DEFRAMER_INV_M_PARM Invalid M parameter in deframer structure + * \retval MYKONOS_ERR_DEFRAMER_INV_BANKID_PARM Invalid BankId parameter in deframer structure (Valid 0-15) + * \retval MYKONOS_ERR_ERR_DEFRAMER_INV_LANEID_PARM Invalid Lane0Id parameter in deframer structure (Valid 0-31) + * \retval MYKONOS_ERR_DEFRAMER_INV_K_PARAM Invalid K parameter in deframer structure (valid 1-32 with other constraints) + * \retval MYKONOS_ERR_DEFRAMER_INV_FK_PARAM Invalid F*K parameter (Valid F*K > 20, F*K must be divisible by 4), K must be <= 32 + * \retval MYKONOS_ERR_DEFRAMER_INV_K_OFFSET_PARAM Invalid K offset parameter in deframer structure (must be less than K) + */ +mykonosErr_t MYKONOS_setupJesd204bDeframer(mykonosDevice_t *device) +{ + uint8_t i = 0; + uint8_t temp = 0; + uint8_t reg080 = 0; + uint8_t laneXbar = 0; + uint8_t L = 0; + uint8_t ML = 0; + + /* Setup submap registers */ + uint8_t SUBCLASSV = 1; + uint8_t JESDV = 1; + uint8_t DID = 0; + uint8_t BID = 0; + uint8_t LID0 = 0; + uint8_t CS = 2; /* 2 control bits */ + uint8_t N = 0x0D; /* 14 bits */ + uint8_t Np = 0x0F; /* 16 bits */ + uint8_t S = 0; + uint8_t CF = 0; + uint8_t K = 0x1F; + uint16_t FK = 0; + uint8_t HD = 0; /* only one case has HD == 1 */ + uint8_t CTRLREG0 = 0; + uint8_t DeframerL = 1; + uint8_t DeframerM = 2; + uint8_t DeframerF = 0; + uint8_t CTRLREG1 = 0; + uint8_t CTRLREG2 = 0; + uint8_t DeframerLaneEnable = 0x00; + uint16_t CheckSum = 0; + uint8_t subaddr[25] = {0}; + uint8_t subdata[25] = {0}; + + uint8_t deframerInput = 0; + uint8_t lane = 0; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setupJesd204bDeframer()\n"); +#endif + + if (device->tx->deframer->M != 0 && device->tx->deframer->M != 2 && device->tx->deframer->M != 4) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DEFRAMER_INV_M_PARM, getMykonosErrorMessage(MYKONOS_ERR_DEFRAMER_INV_M_PARM)); + return MYKONOS_ERR_DEFRAMER_INV_M_PARM; + } + + if (device->tx->deframer->bankId > 15) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DEFRAMER_INV_BANKID_PARM, + getMykonosErrorMessage(MYKONOS_ERR_DEFRAMER_INV_BANKID_PARM)); + return MYKONOS_ERR_DEFRAMER_INV_BANKID_PARM; + } + + if (device->tx->deframer->lane0Id > 31) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_ERR_DEFRAMER_INV_LANEID_PARM, + getMykonosErrorMessage(MYKONOS_ERR_ERR_DEFRAMER_INV_LANEID_PARM)); + return MYKONOS_ERR_ERR_DEFRAMER_INV_LANEID_PARM; + } + + //count number of lanes + L = 0; + ML = 0; + + for (i = 0; i < 4; i++) + { + L += ((device->tx->deframer->deserializerLanesEnabled >> i) & 0x01); + } + + ML = (uint8_t)(device->tx->deframer->M * 10 + L); + + if (device->tx->deframer->K > 32) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DEFRAMER_INV_K_PARAM, + getMykonosErrorMessage(MYKONOS_ERR_DEFRAMER_INV_K_PARAM)); + return MYKONOS_ERR_DEFRAMER_INV_K_PARAM; + } + + FK = (uint16_t)(device->tx->deframer->K * 2 * device->tx->deframer->M / L); + + if (FK < 20 || FK > 256 || FK % 4 != 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DEFRAMER_INV_FK_PARAM, + getMykonosErrorMessage(MYKONOS_ERR_DEFRAMER_INV_FK_PARAM)); + return MYKONOS_ERR_DEFRAMER_INV_FK_PARAM; + } + + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_DEFRAMER_SYNC_REQ_RETIME, (device->tx->deframer->K - 1), 0x1F, 0x00); + + if (!device->tx->deframer->externalSysref) + { + /* Deframer: Generate SYSREF internally */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_TEST, 0x02); + } + + /* enabling the SYSREF for relink if newSysrefOnRelink is set */ + if (device->tx->deframer->newSysrefOnRelink) + { + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_DEFRAMER_SYSREF_FIFO_EN, 0x01, 0x40, 6); + } + + /* enabling auto channel if the enableAutoChanXbar structure member is set */ + if (device->tx->deframer->enableAutoChanXbar) + { + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_DEFRAMER_DET_FIFO_WR_STRT_DAC_XBAR_REV, 0x01, 0x04, 2); + } + + /* Fix bad default bit to allow deterministic latency on deframer (Clear bit 4)*/ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_DEFRAMER_DET_FIFO_WR_STRT_DAC_XBAR_REV, 0x00, 0x10, 4); + + /* Deframer: Set DAC Crossbar */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_DAC_XBAR_SEL, 0xB1); + + if (device->tx->deframer->enableManualLaneXbar == 1) + { + laneXbar = device->tx->deframer->deserializerLaneCrossbar; + } + else + { + /* Lane crossbar - Allow user to reorder lanes in deframer->deserializerLaneCrossbar, but this code still */ + /* maps used lanes to deframer inputs */ + deframerInput = 0; + for (lane = 0; lane < 4; lane++) + { + if ((device->tx->deframer->deserializerLanesEnabled >> lane) & 1) + { + laneXbar |= (uint8_t)(((device->tx->deframer->deserializerLaneCrossbar >> (lane << 1)) & 3) << (deframerInput << 1)); + deframerInput += 1; + } + } + + if (ML == 42) + { + /* M4L2 uses internal deframer ports 0 and 2 */ + /* swap bits 3:2 and 5:4, keep 1:0 and 7:6 in place */ + laneXbar = (laneXbar & 0xC3U) | ((laneXbar & 0x30) >> 2) | ((laneXbar & 0x0C) << 2); + } + } + + /* Deframer: Set Lane Crossbar */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_LANE_XBAR_SEL, laneXbar); + + //Find value for Framer F depending on M and L + switch (ML) + { + case 21: + reg080 = 0x04; + break; + case 22: + reg080 = 0x22; + break; + case 24: + reg080 = 0x41; + break; + case 41: + reg080 = 0x18; + break; + case 42: + reg080 = 0x34; + break; + case 44: + reg080 = 0x52; + break; + default: + reg080 = 0x04; + break; + } + + /* Deframer: Set F (Octets in Frame) */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_CONFIG_F, reg080); + + /* Deframer: Enable clocks and lane clocks */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_CLK_EN, 0x03); + + /* Set deframer lane FIFO enable for each lane enabled */ + temp = (device->tx->deframer->deserializerLanesEnabled & 0x0F); + + /* Deframer: Enable Lane FIFOs */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_LANE_FIFO_CTL, temp); + + /* Setup submap registers */ + SUBCLASSV = 1; /* JESD subclass 1 */ + JESDV = 1; /* Version: JESD204B */ + DID = device->tx->deframer->deviceId; + BID = device->tx->deframer->bankId; + LID0 = device->tx->deframer->lane0Id; + CS = 2; /* 2 control bits */ + N = 0x0D; /* 14 bits */ + Np = 0x0F; + S = 0; + CF = 0; + K = device->tx->deframer->K - 1; + HD = 0; /* only one case has HD = 1 */ + CTRLREG0 = 1; + DeframerL = L - 1; + DeframerM = device->tx->deframer->M - 1; + DeframerF = (uint8_t)((2*device->tx->deframer->M/L) - 1); + CheckSum = 0; + + if (ML == 21) + { + CTRLREG1 = 4; + CTRLREG2 = 0x14; + DeframerLaneEnable = 1; + } + else if (ML == 22) + { + CTRLREG1 = 2; + CTRLREG2 = 4; + DeframerLaneEnable = 3; + } + else if (ML == 24) + { + HD = 1; + CTRLREG1 = 1; + CTRLREG2 = 0; + DeframerLaneEnable = 0x0F; + } + else if (ML == 41) + { + CTRLREG1 = 8; + CTRLREG2 = 0; + DeframerLaneEnable = 1; + } + else if (ML == 42) + { + CTRLREG1 = 4; + CTRLREG2 = 0; + DeframerLaneEnable = 5; + } + else if (ML == 44) + { + CTRLREG1 = 2; + CTRLREG2 = 0; + DeframerLaneEnable = 0x0F; + } + else + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DEFRAMER_INV_M_PARM, getMykonosErrorMessage(MYKONOS_ERR_DEFRAMER_INV_M_PARM)); + return MYKONOS_ERR_DEFRAMER_INV_M_PARM; + } + + /* LMFC offset limit check */ + if (device->tx->deframer->lmfcOffset < device->tx->deframer->K) + { + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_LMFC_K_OFFSET, device->tx->deframer->lmfcOffset); + } + else + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DEFRAMER_INV_K_OFFSET_PARAM, + getMykonosErrorMessage(MYKONOS_ERR_DEFRAMER_INV_K_OFFSET_PARAM)); + return MYKONOS_ERR_DEFRAMER_INV_K_OFFSET_PARAM; + } + + subaddr[0] = 0x50; + subdata[0] = DID & 0xFFU; /* Device ID */ + subaddr[1] = 0x51; + subdata[1] = BID & 0x0F; /* Bank ID */ + subaddr[2] = 0x52; + subdata[2] = LID0 & 0x1F; /* Lane 0 ID */ + subaddr[3] = 0x53; + subdata[3] = (uint8_t)(device->tx->deframer->scramble << 7) | (DeframerL & 0x1F); /* [7] = Scramble Enable, #Lanes[4:0] */ + subaddr[4] = 0x54; + subdata[4] = DeframerF & 0xFFU; /* F[7:0] */ + subaddr[5] = 0x55; + subdata[5] = K & 0x1F; /* K[4:0] */ + subaddr[6] = 0x56; + subdata[6] = DeframerM & 0xFFU; /* M[7:0] */ + subaddr[7] = 0x57; + subdata[7] = ((CS & 0x3) << 6) | (N & 0x1F); /* [7:6] = CS[1:0], N[4:0] */ + subaddr[8] = 0x58; + subdata[8] = ((SUBCLASSV & 7) << 5) | (Np & 0x1F); /* Np[4:0] */ + subaddr[9] = 0x59; + subdata[9] = ((JESDV & 7) << 5) | (S & 0x1F); /* S[4:0] */ + subaddr[10] = 0x5A; + subdata[10] = ((HD & 1) << 7) | (CF & 0x1F); /* [7]=HD, CF[4:0] */ + subaddr[11] = 0x5B; + subdata[11] = 0x00; /* reserved */ + subaddr[12] = 0x5C; + subdata[12] = 0x00; /* reserved */ + CheckSum = (DID & 0xFF) + (BID & 0xF) + (LID0 & 0x1F) + (device->tx->deframer->scramble) + (DeframerL & 0x1F) + (DeframerF & 0xFF) + (K & 0x1F) + (DeframerM & 0xFF) + + (CS & 0x3) + (N & 0x1F) + (Np & 0x1F) + (S & 0x1F) + (HD & 1) + (CF & 0x1F) + (SUBCLASSV & 7) + (JESDV & 7); + subaddr[13] = 0x5D; + subdata[13] = CheckSum & 0xFFU; /* Checksum Lane 0 */ + subaddr[14] = 0x6D; + subdata[14] = 0xA0U; /* Bad Disparity setup */ + subaddr[15] = 0x6E; + subdata[15] = 0xA0U; /* Not in Table setup */ + subaddr[16] = 0x6F; + subdata[16] = 0xA0U; /* UnExpected K character setup */ + subaddr[17] = 0x75; + subdata[17] = CTRLREG0; /* CTRLREG 0 */ + subaddr[18] = 0x76; + subdata[18] = CTRLREG1; /* CTRLREG 1 (Bytes per frame) */ + subaddr[19] = 0x77; + subdata[19] = CTRLREG2; /* CTRLREG 2 */ + subaddr[20] = 0x78; + subdata[20] = 0x01; /* # 4*K multiframes during ILAS */ + subaddr[21] = 0x7A; + subdata[21] = 0xE0U; /* Setup JESD interrupt sources */ + subaddr[22] = 0x7B; + subdata[22] = 0x08U; /* Sync assertion setup */ + subaddr[23] = 0x7C; + subdata[23] = 0xFFU; /* Error count threshold */ + subaddr[24] = 0x7D; + subdata[24] = DeframerLaneEnable & 0xFFU; /* Lane enable */ + + for (i = 0; i <= 24; i++) + { + /* Set deframer sub-register map address */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_ADDR, subaddr[i]); + + /* Set deframer sub-register map data word */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_DATA, subdata[i]); + + /* Set write enable to latch data into deframer sub register map */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_WR_EN, 0x01); + } + + /* Deframer: Enable lane FIFO sync */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_DEFRAMER_SYSREF_FIFO_EN, 0x01, 0x10, 4); + + return MYKONOS_ERR_OK; +} + +/** + * \brief Sets up the chip for multichip sync, and cleans up after MCS. + * + * When working with multiple transceivers or even only one transceiver that requires deterministic + * latency between the Tx and observation and or main Rx JESD204B data path, Multichip sync is + * necessary. This function should be run after all transceivers are initialized. + * + * After the SYSREF pulses have been sent, call the MYKONOS_enableMultichipSync() function again with the + * enableMcs parameter set to 0. When enableMcs = 0, the MCS status will be returned in the mcsStatus + * parameter. + * + * Typical sequence: + * 1) Initialize all Mykonos devices in system using MYKONOS_initialize() + * 2) Run MYKONOS_enableMultichipSync with enableMcs = 1 + * 3) Send at least 3 SYSREF pulses + * 4) Run MYKONOS_enableMultichipSync with enableMcs = 0 + * 5) Load ARM, run ARM cals and continue to active Transmit/Receive + * + * mcsStatus | bit Description + * -----------|-------------------------------------------------------- + * [0] | MCS JESD SYSREF Status (1 = sync occurred) + * [1] | MCS Digital Clocks Sync Status (1 = sync occurred) + * [2] | MCS CLKPLL SDM Sync Status (1 = sync occurred) + * [3] | MCS Device Clock divider Sync Status (1 = sync occurred) + * + * Dependencies + * - device->spiSettings + * + * \param device is a pointer to the device settings structure + * \param enableMcs =1 will enable the MCS state machine, =0 will allow reading back MCS status + * \param mcsStatus optional parameter, if pointer is not null the function Which will be populated with the mcsStatus word described in the table above. + * + * \retval MYKONOS_ERR_OK Function completed successfully + */ +mykonosErr_t MYKONOS_enableMultichipSync(mykonosDevice_t *device, uint8_t enableMcs, uint8_t *mcsStatus) +{ + uint8_t clkPllSdmBypass = 0; + uint8_t mcsEnable = 0x9B; /* [7] Keeps RF LO divider enabled, Enable MCS[4] and reset Device Clock divider[3], Digital clocks[1], and JESD204 SYSREF[0] */ + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_enableMultichipSync()\n"); +#endif + + if (enableMcs) + { + /* If CLKPLL SDM not bypassed, reset CLKPLL SDM as well. */ + CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_DIVIDER_INT_BYTE1, &clkPllSdmBypass, 0x40, 6); + + if (clkPllSdmBypass == 0) + { + mcsEnable |= 0x04; /* enable MCS for CLKPLL SDM */ + } + + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_MCS_CONTROL, mcsEnable); + } + + /* if mcsStatus is a valid pointer, return the MCS status */ + if (mcsStatus != NULL) + { + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_MCS_STATUS, mcsStatus); + } + + return MYKONOS_ERR_OK; +} + +/** + * \brief Enables or disables SYSREF to the transceiver's RX framer + * + * Dependencies + * - device->spiSettings + * + * \param device is a pointer to the device settings structure + * \param enable = '1' enables SYSREF to RX framer, '0' disables SYSREF to framer + * + * \retval MYKONOS_ERR_OK Function completed successfully + */ +mykonosErr_t MYKONOS_enableSysrefToRxFramer(mykonosDevice_t *device, uint8_t enable) +{ + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_enableSysrefToRxFramer()\n"); +#endif + + if (enable) + { + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_FRAMER_SYSREF_FIFO_EN, 0x01, 0x01, 0); + } + else + { + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_FRAMER_SYSREF_FIFO_EN, 0x00, 0x01, 0); + } + + return MYKONOS_ERR_OK; +} + +/** + * \brief Enables or disables SYSREF to the transceiver's Observation RX framer + * + * Dependencies + * - device->spiSettings + * + * \param device is a pointer to the device settings structure + * \param enable = '1' enables SYSREF to OBSRX framer, '0' disables SYSREF to framer + * + * \retval MYKONOS_ERR_OK Function completed successfully + */ +mykonosErr_t MYKONOS_enableSysrefToObsRxFramer(mykonosDevice_t *device, uint8_t enable) +{ + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_enableSysrefToObsRxFramer()\n"); +#endif + + if (enable) + { + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_SYSREF_FIFO_EN, 0x01, 0x01, 0); + } + else + { + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_SYSREF_FIFO_EN, 0x00, 0x01, 0); + } + + return MYKONOS_ERR_OK; +} + +/** + * \brief Enables or disables SYSREF to the transceiver's deframer + * + * Dependencies + * - device->spiSettings + * + * \param device is a pointer to the device settings structure + * \param enable = '1' enables SYSREF to deframer, '0' disables SYSREF to deframer + * + * \retval MYKONOS_ERR_OK Function completed successfully + */ +mykonosErr_t MYKONOS_enableSysrefToDeframer(mykonosDevice_t *device, uint8_t enable) +{ + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_enableSysrefToDeframer()\n"); +#endif + + if (enable) + { + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_DEFRAMER_SYSREF_FIFO_EN, 0x01, 0x01, 0); + } + else + { + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_DEFRAMER_SYSREF_FIFO_EN, 0x00, 0x01, 0); + } + + return MYKONOS_ERR_OK; +} + +/** + * \brief Reads the transceiver's RX framer status + * + * Dependencies + * - device->spiSettings + * + * framerStatus | Description + * -------------|----------------------------------------------------------------------------- + * [7] | SYSREF phase error ? a new SYSREF had different timing than the first that set the LMFC timing. + * [6] | Framer lane FIFO read/write pointer delta has changed. Can help debug issues with deterministic latency. + * [5] | Framer has received the SYSREF and has retimed its LMFC + * [4:2] | Framer ILAS state: 0=CGS, 1= 1st Multframe, 2= 2nd Multiframe, 3= 3rd Multiframe, 4= 4th multiframe, 5= Last multiframe, 6=invalid, 7= ILAS complete + * [1:0] | Framer Tx state: 0=CGS, 1= ILAS, 2 = ADC Data + * + * \param device is a pointer to the device settings structure + * \param framerStatus is the RX framer status byte read + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_READ_RXFRAMERSTATUS_NULL_PARAM Function parameter framerStatus has NULL pointer + */ +mykonosErr_t MYKONOS_readRxFramerStatus(mykonosDevice_t *device, uint8_t *framerStatus) +{ + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_readRxFramerStatus()\n"); +#endif + + if (framerStatus == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_READ_RXFRAMERSTATUS_NULL_PARAM, + getMykonosErrorMessage(MYKONOS_ERR_READ_RXFRAMERSTATUS_NULL_PARAM)); + return MYKONOS_ERR_READ_RXFRAMERSTATUS_NULL_PARAM; + } + + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_STATUS_STRB, 0x01); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_STATUS_STRB, 0x00); + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_FRAMER_STATUS, framerStatus); + + return MYKONOS_ERR_OK; +} + +/** + * \brief Reads the transceiver's Observation RX framer status + * + * Dependencies + * * - device->spiSettings + * + * obsFramerStatus | Description + * ----------------|----------------------------------------------------------------------------- + * [7] | SYSREF phase error ? a new SYSREF had different timing than the first that set the LMFC timing. + * [6] | Framer lane FIFO read/write pointer delta has changed. Can help debug issues with deterministic latency. + * [5] | Framer has received the SYSREF and has retimed its LMFC + * [4:2] | Framer ILAS state: 0=CGS, 1= 1st Multframe, 2= 2nd Multiframe, 3= 3rd Multiframe, 4= 4th multiframe, 5= Last multiframe, 6=invalid, 7= ILAS complete + * [1:0] | Framer Tx state: 0=CGS, 1= ILAS, 2 = ADC Data + * + * \param device is a pointer to the device settings structure + * \param obsFramerStatus is the OBSRX framer status byte read + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_READ_ORXFRAMERSTATUS_NULL_PARAM Function parameter obsFramerStatus has NULL pointer + */ +mykonosErr_t MYKONOS_readOrxFramerStatus(mykonosDevice_t *device, uint8_t *obsFramerStatus) +{ + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_readOrxFramerStatus()\n"); +#endif + + if (obsFramerStatus == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_READ_ORXFRAMERSTATUS_NULL_PARAM, + getMykonosErrorMessage(MYKONOS_ERR_READ_ORXFRAMERSTATUS_NULL_PARAM)); + return MYKONOS_ERR_READ_ORXFRAMERSTATUS_NULL_PARAM; + } + + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_STATUS_STRB, 0x01); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_STATUS_STRB, 0x00); + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_STATUS, obsFramerStatus); + + return MYKONOS_ERR_OK; +} + +/** + * \brief Reads the transceiver's deframer status + * + * Dependencies + * - device->spiSettings + * + * deframerStatus | Bit Name | Description + * ----------------|--------------------------|--------------------------------------------- + * [7] | Unused | Unused + * [6] | Deframer IRQ | This bit indicates that the IRQ interrupt was asserted. + * [5] | Deframer SYSREF Received | When this bit is set, it indicates that the SYSREF pulse was received by the deframer IP + * [4] | Deframer Receiver Error | This bit is set when PRBS has received an error. + * [3] | Valid Checksum | This bit is set when the received ILAS checksum is valid. + * [2] | EOF Event | This bit captures the internal status of the framer End of Frame event. Value =1 if framing error during ILAS + * [1] | EOMF Event | This bit captures the internal status of the framer End of Multi-Frame event. Value =1 if framing error during ILAS + * [0] | FS Lost | This bit captures the internal status of the framer Frame Symbol event. Value =1 if framing error during ILAS or user data (invalid replacement characters) + * + * + * \param device is a pointer to the device settings structure + * \param deframerStatus is the deframer status byte read + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_READ_DEFRAMERSTATUS_NULL_PARAM Function parameter deframerStatus has NULL pointer + */ +mykonosErr_t MYKONOS_readDeframerStatus(mykonosDevice_t *device, uint8_t *deframerStatus) +{ + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_readDeframerStatus()\n"); +#endif + + if (deframerStatus == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_READ_DEFRAMERSTATUS_NULL_PARAM, + getMykonosErrorMessage(MYKONOS_ERR_READ_DEFRAMERSTATUS_NULL_PARAM)); + return MYKONOS_ERR_READ_DEFRAMERSTATUS_NULL_PARAM; + } + + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_STAT_STRB, 0x01); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_STAT_STRB, 0x00); + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_STAT, deframerStatus); + + return MYKONOS_ERR_OK; +} + +/** + * \brief Reads the Mykonos JESD204b Deframer determinstic FIFO depth + * + * To verify that the deterministic latency FIFO is not close to a underflow or + * overflow condition, it is recommended to check the FIFO depth. If the FIFO + * is close to an overflow or underflow condition, it is possible that from + * power up to powerup, deterministic latency may not be met. If a underflow + * or overflow occurred, the data would still be correct, but would possibly + * slip by 1 multiframe (losing deterministic latency). To correct for an + * overflow/underflow, the BBIC would need to add delay from SYSREF until + * the first symbol in a multiframe + * + * Dependencies + * - device->spiSettings + * + * \param device is a pointer to the device settings structure + * \param fifoDepth Return value that describes the depth of the Mykonos + * deterministic latency deframer FIFO. + * \param readEnLmfcCount Returns the LMFC count value when the deterministic FIFO read enable was asserted. + * Counts at the Mykonos internal deframer PCLK frequency. + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_READ_DEFFIFODEPTH_NULL_PARAM Error: function parameter fifoDepth is a NULL pointer + * \retval MYKONOS_ERR_READ_DEFFIFODEPTH_LMFCCOUNT_NULL_PARAM Error: function parameter readEnLmfcCount is a NULL pointer + * + */ +mykonosErr_t MYKONOS_getDeframerFifoDepth(mykonosDevice_t *device, uint8_t *fifoDepth, uint8_t *readEnLmfcCount) +{ + uint8_t fifoReadPtr = 0; + uint8_t fifoWritePtr = 0; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getDeframerFifoDepth()\n"); +#endif + + if (fifoDepth == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_READ_DEFFIFODEPTH_NULL_PARAM, + getMykonosErrorMessage(MYKONOS_ERR_READ_DEFFIFODEPTH_NULL_PARAM)); + return MYKONOS_ERR_READ_DEFFIFODEPTH_NULL_PARAM; + } + + if (readEnLmfcCount == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_READ_DEFFIFODEPTH_LMFCCOUNT_NULL_PARAM, + getMykonosErrorMessage(MYKONOS_ERR_READ_DEFFIFODEPTH_LMFCCOUNT_NULL_PARAM)); + return MYKONOS_ERR_READ_DEFFIFODEPTH_LMFCCOUNT_NULL_PARAM; + } + + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_STAT_STRB, 0x01); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_STAT_STRB, 0x00); + + /* read/write pointers are 7 bits, (0 - 127) */ + CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_DEFRAMER_DET_FIFO_RD_ADDR, &fifoReadPtr, 0x7F, 0); + CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_DEFRAMER_DET_FIFO_WR_ADDR, &fifoWritePtr, 0x7F, 0); + + /* Adding 128 and modulus 128 handle the wrap cases where the read pointer + * is less than write pointer + */ + *fifoDepth = (((fifoWritePtr + 128) - fifoReadPtr) % 128); + + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_DET_FIFO_PHASE, readEnLmfcCount); + + return MYKONOS_ERR_OK; +} + +/** + * \brief Selects the PRBS type and enables or disables RX Framer PRBS20 generation + * + * Dependencies + * - device->spiSettings + * + * \param device is a pointer to the device settings structure + * \param polyOrder selects the PRBS type based on a two-bit value range from 0-3 + * \param enable '1' = enables PRBS RX framer PRBS generator, '0' = disables PRBS generator + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_RX_FRAMER_INV_PRBS_POLYORDER_PARAM Invalid polyOrder parameter, use ENUM + * + */ +mykonosErr_t MYKONOS_enableRxFramerPrbs(mykonosDevice_t *device, mykonosPrbsOrder_t polyOrder, uint8_t enable) +{ + uint8_t wrmask = 0; + uint8_t enableBit = 0; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_enableRxFramerPrbs()\n"); +#endif + + enableBit = (enable > 0) ? 1 : 0; + + if ((polyOrder == MYK_PRBS7) || (polyOrder == MYK_PRBS15) || (polyOrder == MYK_PRBS31)) + { + wrmask = ((uint8_t)polyOrder << 1) | enableBit; + } + else + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RX_FRAMER_INV_PRBS_POLYORDER_PARAM, + getMykonosErrorMessage(MYKONOS_ERR_RX_FRAMER_INV_PRBS_POLYORDER_PARAM)); + return MYKONOS_ERR_RX_FRAMER_INV_PRBS_POLYORDER_PARAM; + } + + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_PRBS20_CTL, wrmask); + + return MYKONOS_ERR_OK; +} + +/** + * \brief Selects the PRBS type and enables or disables OBSRX Framer PRBS20 generation + * + * Dependencies + * - device->spiSettings + * + * \param device is a pointer to the device settings structure + * \param polyOrder selects the PRBS type based on a two-bit value range from 0-3 + * \param enable '1' = enables PRBS OBSRX framer PRBS generator, '0' = disables PRBS generator + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_OBSRX_FRAMER_INV_PRBS_POLYORDER_PARAM polyOrder parameter is not a valid value - use ENUM + */ +mykonosErr_t MYKONOS_enableObsRxFramerPrbs(mykonosDevice_t *device, mykonosPrbsOrder_t polyOrder, uint8_t enable) +{ + uint8_t wrmask = 0; + uint8_t enableBit = 0; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_enableObsRxFramerPrbs()\n"); +#endif + + enableBit = (enable > 0) ? 1 : 0; + + if ((polyOrder == MYK_PRBS7) || (polyOrder == MYK_PRBS15) || (polyOrder == MYK_PRBS31)) + { + wrmask = ((uint8_t)polyOrder << 1) | enableBit; + } + else + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OBSRX_FRAMER_INV_PRBS_POLYORDER_PARAM, + getMykonosErrorMessage(MYKONOS_ERR_OBSRX_FRAMER_INV_PRBS_POLYORDER_PARAM)); + return MYKONOS_ERR_OBSRX_FRAMER_INV_PRBS_POLYORDER_PARAM; + } + + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_PRBS20_CTL, wrmask); + + return MYKONOS_ERR_OK; +} + +/** + * \brief Injects a PRBS error into the RX data path + * + * Dependencies + * - device->spiSettings + * + * \param device is a pointer to the device settings structure + * + * \retval MYKONOS_ERR_OK Function completed successfully + */ +mykonosErr_t MYKONOS_rxInjectPrbsError(mykonosDevice_t *device) +{ + uint8_t prbsControl = 0x00; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_rxInjectPrbsError()\n"); +#endif + + /* reading current PRBS20 control register contents */ + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_FRAMER_PRBS20_CTL, &prbsControl); + + /* setting bit 4 in framer PRBS20 control register and then clearing it for error injection */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_PRBS20_CTL, prbsControl |= 0x10); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_PRBS20_CTL, prbsControl &= ~0x10); + + return MYKONOS_ERR_OK; +} + +/** + * \brief Initiates a PRBS error injection into the Observation RX data path + * + * Dependencies + * - device->spiSettings + * + * \param device is a pointer to the device settings structure + * + * \retval MYKONOS_ERR_OK Function completed successfully + */ +mykonosErr_t MYKONOS_obsRxInjectPrbsError(mykonosDevice_t *device) +{ + uint8_t prbsControl = 0x00; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_obsRxInjectPrbsError()\n"); +#endif + + /* reading current PRBS20 control register contents */ + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_PRBS20_CTL, &prbsControl); + + /* setting bit 4 in framer PRBS20 control register and then clearing it for error injection */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_PRBS20_CTL, prbsControl |= 0x10); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_PRBS20_CTL, prbsControl &= ~0x10); + + return MYKONOS_ERR_OK; +} + +/** + * \brief Configures and enables or disables the transceiver's deframer PRBS checker + * + * Dependencies + * - device->spiSettings + * + * \param device is a pointer to the device settings structure + * \param lanes selects the lane for PRBS checking based on a 4-bit mask, where each weighted bit + * corresponds with a different lane selection as such: '1' = lane 0, '2' = lane 1, '4' = lane 2, '8' = lane 3 + * \param polyOrder selects the PRBS type based on enum values (MYK_PRBS7, MYK_PRBS15, MYK_PRBS31) + * \param enable '1' = enables checking, '0' = disables checking + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_DEFRAMER_INV_PRBS_POLYORDER_PARAM Invalid polyOrder parameter - use ENUM + * \retval MYKONOS_ERR_DEFRAMER_INV_PRBS_ENABLE_PARAM Invalid enable (valid 0-1) or lanes (valid 0-15) parameter + */ +mykonosErr_t MYKONOS_enableDeframerPrbsChecker(mykonosDevice_t *device, uint8_t lanes, mykonosPrbsOrder_t polyOrder, uint8_t enable) +{ + uint8_t wrmask = 0x00; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_enableDeframerPrbsChecker()\n"); +#endif + + if ((enable <= 0x01) && (lanes <= 0x0F)) + { + if ((polyOrder == MYK_PRBS7) || (polyOrder == MYK_PRBS15) || (polyOrder == MYK_PRBS31)) + { + wrmask = ((lanes << 4) | ((uint8_t)polyOrder << 1) | enable); + } + else + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DEFRAMER_INV_PRBS_POLYORDER_PARAM, + getMykonosErrorMessage(MYKONOS_ERR_DEFRAMER_INV_PRBS_POLYORDER_PARAM)); + return MYKONOS_ERR_DEFRAMER_INV_PRBS_POLYORDER_PARAM; + } + } + else + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DEFRAMER_INV_PRBS_ENABLE_PARAM, + getMykonosErrorMessage(MYKONOS_ERR_DEFRAMER_INV_PRBS_ENABLE_PARAM)); + return MYKONOS_ERR_DEFRAMER_INV_PRBS_ENABLE_PARAM; + } + + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_PRBS20_CTL, wrmask); + + return MYKONOS_ERR_OK; +} + +/** + * \brief Reads the deframer PRBS counters + * + * Dependencies + * - device->spiSettings + * + * \param device is a pointer to the device settings structure + * \param counterSelect selects the PRBS error counter to be read based on values between 0-3 + * If counterSelect exceeds this value an error is thrown. + * + * \param prbsErrorCount is return value after reading the PRBS error count + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_READ_DEFRAMERPRBS_NULL_PARAM Function parameter prbsErrorCount has NULL pointer + * \retval MYKONOS_ERR_DEFRAMER_INV_PRBS_CNTR_SEL_PARAM if counterSelect is out of bounds + */ +mykonosErr_t MYKONOS_readDeframerPrbsCounters(mykonosDevice_t *device, uint8_t counterSelect, uint32_t *prbsErrorCount) +{ + uint8_t wrmask = 0x00; + uint8_t errorCnt[3] = {0}; + const uint8_t COUNTER_SATURATE = 0x40; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_readDeframerPrbsCounters()\n"); +#endif + + if (prbsErrorCount == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_READ_DEFRAMERPRBS_NULL_PARAM, + getMykonosErrorMessage(MYKONOS_ERR_READ_DEFRAMERPRBS_NULL_PARAM)); + return MYKONOS_ERR_READ_DEFRAMERPRBS_NULL_PARAM; + } + + if (counterSelect & ~0x03) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DEFRAMER_INV_PRBS_CNTR_SEL_PARAM, + getMykonosErrorMessage(MYKONOS_ERR_DEFRAMER_INV_PRBS_CNTR_SEL_PARAM)); + return MYKONOS_ERR_DEFRAMER_INV_PRBS_CNTR_SEL_PARAM; + } + else + { + wrmask = (uint8_t)(COUNTER_SATURATE | (counterSelect << 4)); + *prbsErrorCount = 0x00000000; + } + + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_PRBS20_STRB_CHKSUM_TYPE, wrmask); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_PRBS20_STRB_CHKSUM_TYPE, wrmask |= 0x01); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_PRBS20_STRB_CHKSUM_TYPE, wrmask &= ~0x01); + + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_PRBS20_ERR_CNTR_7_TO_0, &errorCnt[0]); + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_PRBS20_ERR_CNTR_15_TO_8, &errorCnt[1]); + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_PRBS20_ERR_CNTR_23_TO_16, &errorCnt[2]); + + *prbsErrorCount = (uint32_t)(errorCnt[2] << 16) | (uint32_t)(errorCnt[1] << 8) | (uint32_t)(errorCnt[0]); + + return MYKONOS_ERR_OK; +} + +/** + * \brief Clears the deframer/deserializer PRBS counters + * + * Dependencies + * - device->spiSettings + * + * \param device is a pointer to the device settings structure + * + * \retval MYKONOS_ERR_OK Function completed successfully + */ +mykonosErr_t MYKONOS_clearDeframerPrbsCounters(mykonosDevice_t *device) +{ + uint8_t spiReg = 0; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_clearDeframerPrbsCounters()\n"); +#endif + + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_PRBS20_CTL, &spiReg); + spiReg &= ~0x08; //make sure PRBS clear bit is 0 + + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_PRBS20_CTL, (spiReg | 0xF8)); //clear counters for all lanes + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_PRBS20_CTL, spiReg); //set reg back to previous value + + return MYKONOS_ERR_OK; +} + +/** + * \brief Reads the lane 0 JESD204B deframer configuration and compares it against the ILAS received values + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device is a pointer to the device settings structure + * \param mismatch [15-0] is a bit-encoded word which for mismatch[15] = '0' = no mismatch, '1' = mismatch for one or more parameters + * mismatch bits [14-0] are aligned with the mykonosJesd204bLane0Config_t structure members starting at '0' = DID. The aligned bit is set to + * '1' if the configuration parameter does not agree with its corresponding received ILAS value, otherwise '0' if they agree. + * + * The bit assignments for the 16-bit word are: + * mismatch | bit description + * -----------|-------------------------------------------------------- + * [0] | JESD204B DID: device ID + * [1] | JESD204B BID: bank ID + * [2] | JESD204B LID0: lane ID + * [3] | JESD204B L: lanes per data converter + * [4] | JESD204B SCR: scramble setting + * [5] | JESD204B F: octets per frame + * [6] | JESD204B K: frames per multiframe + * [7] | JESD204B M: number of data converters + * [8] | JESD204B N: data converter sample resolution + * [9] | JESD204B CS: number of control bits transferred per sample per frame + * [10] | JESD204B NP: JESD204B word size based on the highest data converter resolution + * [11] | JESD204B S: number of samples per converter per frame + * [12] | JESD204B CF: '0' = control bits appended to each sample, '1' = control bits appended to end of frame + * [13] | JESD204B HD: high density bit, where '0' = samples are contained with single lane, '1' = samples are divided over more than one lane + * [14] | JESD204B FCHK0: configuration checksum OK bit. where '1' = fail, '0' = pass + * [15] | MISMATCH DETECTED BIT: bits 0-14 are ored together to set this bit + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_JESD204B_ILAS_MISMATCH_NULLPARAM Function parameter mismatch has NULL pointer + */ +mykonosErr_t MYKONOS_jesd204bIlasCheck(mykonosDevice_t *device, uint16_t *mismatch) +{ + uint8_t i = 0; + uint8_t ilasdata[15] = {0}; + uint8_t cfgdata[15] = {0}; + mykonosJesd204bLane0Config_t lane0ILAS; + mykonosJesd204bLane0Config_t lane0Cfg; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_jesd204bIlasCheck()\n"); +#endif + + if (mismatch == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_JESD204B_ILAS_MISMATCH_NULLPARAM, + getMykonosErrorMessage(MYKONOS_ERR_JESD204B_ILAS_MISMATCH_NULLPARAM)); + return MYKONOS_ERR_JESD204B_ILAS_MISMATCH_NULLPARAM; + } + + *mismatch = 0; + + /* setting deframer read received ILAS data */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_WR_EN, 0x00); + + /* reading deframer received ILAS register contents into array */ + for (i = 0; i < 15; i++) + { + /* setting the deframer sub-address for received ilas data */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_ADDR, MYKONOS_SUBADDR_DEFRAMER_LANE0_ILAS_RECVD + i); + + /* reading the received ILAS data into byte array */ + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_DATA, &ilasdata[i]); + } + + /* reading deframer config register contents into array */ + for (i = 0; i < 15; i++) + { + /* setting the deframer sub-address for received ilas data */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_ADDR, MYKONOS_SUBADDR_DEFRAMER_LANE0_ILAS_CFG + i); + + /* reading the received ILAS data into byte array */ + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_DATA, &cfgdata[i]); + } + + /* loading the structures with the read values for easier reading when doing compares */ + lane0ILAS.DID = ilasdata[0]; + lane0ILAS.BID = ilasdata[1] & 0x0F; + lane0ILAS.LID0 = ilasdata[2] & 0x1F; + lane0ILAS.L = ilasdata[3] & 0x1F; + lane0ILAS.SCR = ilasdata[3] >> 7; + lane0ILAS.F = ilasdata[4]; + lane0ILAS.K = ilasdata[5] & 0x1F; + lane0ILAS.M = ilasdata[6]; + lane0ILAS.N = ilasdata[7] & 0x1F; + lane0ILAS.CS = ilasdata[7] >> 6; + lane0ILAS.NP = ilasdata[8] & 0x1F; + lane0ILAS.S = ilasdata[9] & 0x1F; + lane0ILAS.CF = ilasdata[10] & 0x1F; + lane0ILAS.HD = ilasdata[10] >> 7; + lane0ILAS.FCHK0 = ilasdata[13]; + + lane0Cfg.DID = cfgdata[0]; + lane0Cfg.BID = cfgdata[1] & 0x0F; + lane0Cfg.LID0 = cfgdata[2] & 0x0F; + lane0Cfg.L = cfgdata[3] & 0x1F; + lane0Cfg.SCR = cfgdata[3] >> 7; + lane0Cfg.F = cfgdata[4]; + lane0Cfg.K = cfgdata[5] & 0x1F; + lane0Cfg.M = cfgdata[6]; + lane0Cfg.N = cfgdata[7] & 0x1F; + lane0Cfg.CS = cfgdata[7] >> 6; + lane0Cfg.NP = cfgdata[8] & 0x1F; + lane0Cfg.S = cfgdata[9] & 0x1F; + lane0Cfg.CF = cfgdata[10] & 0x1F; + lane0Cfg.HD = cfgdata[10] >> 7; + lane0Cfg.FCHK0 = cfgdata[13]; + + /* performing ILAS mismatch check */ + if (lane0ILAS.DID != lane0Cfg.DID) + { + *mismatch |= 0x0001; + } + + if (lane0ILAS.BID != lane0Cfg.BID) + { + *mismatch |= 0x0002; + } + + if (lane0ILAS.LID0 != lane0Cfg.LID0) + { + *mismatch |= 0x0004; + } + + if (lane0ILAS.L != lane0Cfg.L) + { + *mismatch |= 0x0008; + } + + if (lane0ILAS.SCR != lane0Cfg.SCR) + { + *mismatch |= 0x0010; + } + + if (lane0ILAS.F != lane0Cfg.F) + { + *mismatch |= 0x0020; + } + + if (lane0ILAS.K != lane0Cfg.K) + { + *mismatch |= 0x0040; + } + + if (lane0ILAS.M != lane0Cfg.M) + { + *mismatch |= 0x0080; + } + + if (lane0ILAS.N != lane0Cfg.N) + { + *mismatch |= 0x0100; + } + + if (lane0ILAS.CS != lane0Cfg.CS) + { + *mismatch |= 0x0200; + } + + if (lane0ILAS.NP != lane0Cfg.NP) + { + *mismatch |= 0x0400; + } + + if (lane0ILAS.S != lane0Cfg.S) + { + *mismatch |= 0x0800; + } + + if (lane0ILAS.CF != lane0Cfg.CF) + { + *mismatch |= 0x1000; + } + + if (lane0ILAS.HD != lane0Cfg.HD) + { + *mismatch |= 0x2000; + } + + if (lane0ILAS.FCHK0 != lane0Cfg.FCHK0) + { + *mismatch |= 0x4000; + } + + if (*mismatch) + { + *mismatch |= 0x8000; + CMB_writeToLog(ADIHAL_LOG_WARNING, device->spiSettings->chipSelectIndex, MYKONOS_ERR_JESD204B_ILAS_MISMATCH, + getMykonosErrorMessage(MYKONOS_ERR_JESD204B_ILAS_MISMATCH)); + } + + return MYKONOS_ERR_OK; +} + +/** + * \brief Select data to inject into the Rx framer input (ADC data or Loopback data from deframer output) + * + * This function allows inputting deframed data (IQ samples) from the Tx data path into the Rx framer. + * For this to work correctly, the IQ data rate of the Tx data path must match the Rx IQ data rate. + * Framer/Deframer JESD204 config parameters can vary as long as the Rx and Tx IQ rates match. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device A pointer to the device settings structure + * \param dataSource 0 = ADC data at Rx Framer input, 1 = Deframed Tx JESD204 IQ samples input into Rx framer + * + * \retval MYKONOS_ERR_OK Function completed successfully + */ +mykonosErr_t MYKONOS_setRxFramerDataSource(mykonosDevice_t *device, uint8_t dataSource) +{ + uint8_t enableLoopBack = 0; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setRxFramerDataSource()\n"); +#endif + + enableLoopBack = (dataSource > 0) ? 1 : 0; + + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_FRAMER_CONFIG_LOOPBACK_XBAR_REV, enableLoopBack, 0x10, 4); + + return MYKONOS_ERR_OK; +} + +/** + * \brief Select data to inject into the ObsRx framer input (ADC data or Loopback data from deframer output) + * + * This function allows inputting deframed data (IQ samples) from the Tx data path into the Obs Rx framer. + * For this to work correctly, the IQ data rate of the Tx data path must match the ORx IQ data rate. + * Framer/Deframer JESD204 config parameters can vary as long as the Obs Rx and Tx IQ rates match. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device A pointer to the device settings structure + * \param dataSource 0 = ADC data at ObsRx Framer input, 1 = Deframed Tx JESD204 IQ samples input into Obs Rx framer + * + * \retval MYKONOS_ERR_OK Function completed successfully + */ +mykonosErr_t MYKONOS_setObsRxFramerDataSource(mykonosDevice_t *device, uint8_t dataSource) +{ + uint8_t enableLoopBack = 0; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setObsRxFramerDataSource()\n"); +#endif + + enableLoopBack = (dataSource > 0) ? 1 : 0; + + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_CONFIG_LOOPBACK_XBAR_REV, enableLoopBack, 0x10, 4); + + return MYKONOS_ERR_OK; +} + +/** + * \brief Runs the Mykonos initialization calibrations + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * ENUM mykonosInitCalibrations_t can be used to OR together to generate the calMask parameter. + * + * calMask Bit | Calibration + * ------------|---------------------- + * 0 | Tx BB Filter + * 1 | ADC Tuner + * 2 | TIA 3dB Corner + * 3 | DC Offset + * 4 | Tx Attenuation Delay + * 5 | Rx Gain Delay + * 6 | Flash Cal + * 7 | Path Delay + * 8 | Tx LO Leakage Internal + * 9 | Tx LO Leakage External + * 10 | Tx QEC Init + * 11 | LoopBack Rx LO Delay + * 12 | LoopBack Rx Rx QEC Init + * 13 | Rx LO Delay + * 14 | Rx QEC Init + * 15 | DPD Init + * 16 | Tx CLGC (Closed Loop Gain Control) + * 17 | Tx VSWR Init + * [31-18] | Ignored - Future space for new calibrations + * + * \param device A pointer to the device settings structure + * \param calMask A bitmask that informs the Mykonos ARM processor which calibrations to run + * + * \retval MYKONOS_ERR_OK Function completed successfully + */ +mykonosErr_t MYKONOS_runInitCals(mykonosDevice_t *device, uint32_t calMask) +{ + mykonosErr_t retVal = MYKONOS_ERR_OK; + const uint8_t RUNINITCALS_OPCODE = 0x02; + uint8_t payload[4] = {0}; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_runInitCals()\n"); +#endif + + payload[0] = (uint8_t)(calMask & 0xFF); + payload[1] = (uint8_t)((calMask >> 8) & 0xFF); + payload[2] = (uint8_t)((calMask >> 16) & 0xFF); + payload[3] = (uint8_t)((calMask >> 24) & 0xFF); + + retVal = MYKONOS_sendArmCommand(device, RUNINITCALS_OPCODE, &payload[0], sizeof(payload)); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + return MYKONOS_ERR_OK; +} + +/** + * \brief Blocking waits for the Mykonos initialization calibrations to complete + * + * The *errorFlag and *errorCode parameters are optional. If the pointers are + * set to null, no values will be returned. If the function returns an error + * that the init calibration failed, use the MYKONOS_getInitCalStatus() function + * to get more detailed information about why the init cal failed. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device A pointer to the device settings structure + * \param timeoutMs A timeout value in Ms to wait for the calibrations to complete + * \param errorFlag A 3bit error flag that helps identify what went wrong in the ARM. 0=No Error + * \param errorCode The value represents the init calibration object ID that caused a failure. + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_WAIT_INITCALS_ARMERROR ARM returned error unrelated to init cals + */ +mykonosErr_t MYKONOS_waitInitCals(mykonosDevice_t *device, uint32_t timeoutMs, uint8_t *errorFlag, uint8_t *errorCode) +{ + mykonosErr_t retVal = MYKONOS_ERR_OK; + mykonosErr_t retValCalStatus = MYKONOS_ERR_OK; + uint8_t cmdStatusByte = 0; + uint8_t _errorFlag = 0; /* Local version of parameter */ + mykonosInitCalStatus_t initCalStatus = {0}; + + const uint8_t INITCALS_CAL_ERROR = 0x07; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_waitInitCals()\n"); +#endif + + /* Clear before making any calls that can throw errors */ + if (errorFlag != NULL) + { + *errorFlag = 0; + } + + /* Clear before making any calls that can throw errors */ + if (errorCode != NULL) + { + *errorCode = 0; + } + + retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_RUNINIT_OPCODE, timeoutMs, &cmdStatusByte); + _errorFlag = cmdStatusByte >> 1; /* remove pending bit in [0], error flag is in bits [3:1] */ + + if (errorFlag != NULL) + { + *errorFlag = _errorFlag; + } + + if (retVal != MYKONOS_ERR_OK) + { + if (_errorFlag == INITCALS_CAL_ERROR) + { + /* return Error code if a calibration had an error */ + retValCalStatus = MYKONOS_getInitCalStatus(device, &initCalStatus); + if (retValCalStatus == MYKONOS_ERR_OK) + { + if (errorCode != NULL) + { + *errorCode = initCalStatus.initErrCal; + } + } + + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_WAIT_INITCALS_CALFAILED, + getMykonosErrorMessage(MYKONOS_ERR_WAIT_INITCALS_CALFAILED)); + return MYKONOS_ERR_WAIT_INITCALS_CALFAILED; + } + else if (cmdStatusByte > 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_WAIT_INITCALS_ARMERROR, + getMykonosErrorMessage(MYKONOS_ERR_WAIT_INITCALS_ARMERROR)); + return MYKONOS_ERR_WAIT_INITCALS_ARMERROR; + } + } + + /* Same logic if MYKONOS_waitArmCmdStatus() did not return an error, but cmdStatusByte shows an ARM error */ + if (_errorFlag == INITCALS_CAL_ERROR) + { + /* return Error code if a calibration had an error */ + retValCalStatus = MYKONOS_getInitCalStatus(device, &initCalStatus); + if (retValCalStatus == MYKONOS_ERR_OK) + { + if (errorCode != NULL) + { + *errorCode = initCalStatus.initErrCal; + } + } + + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_WAIT_INITCALS_CALFAILED, + getMykonosErrorMessage(MYKONOS_ERR_WAIT_INITCALS_CALFAILED)); + return MYKONOS_ERR_WAIT_INITCALS_CALFAILED; + } + else if (cmdStatusByte > 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_WAIT_INITCALS_ARMERROR, + getMykonosErrorMessage(MYKONOS_ERR_WAIT_INITCALS_ARMERROR)); + return MYKONOS_ERR_WAIT_INITCALS_ARMERROR; + } + + return MYKONOS_ERR_OK; +} + +/** + * \brief Aborts from an on going ARM init calibration operation. + * + * The ARM init calibrations can take several seconds. If for any reason the Baseband processor + * needs to stop the running ARM calibration sequence, call this function. The *calsCompleted + * parameter is an option parameter that will return which cals completed before the abort + * command was received. If *calsCompleted is a null pointer, no value will be returned. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device A pointer to the device settings structure + * \param calsCompleted A bitmask is returned which describes which cals completed during the previous + * MYKONOS_runInitCals() call. + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_ABORT_INITCALS_NULL_PARAM Function parameter calsCompleted has NULL pointer + */ +mykonosErr_t MYKONOS_abortInitCals(mykonosDevice_t *device, uint32_t *calsCompleted) +{ + mykonosErr_t retVal = MYKONOS_ERR_OK; + uint32_t timeoutMs = 1000; //1 second timeout + uint8_t cmdStatusByte = 0; + uint8_t payload = 0x43; /* object ID to get INIT_CAL_DONE status */ + uint8_t calCompleteBitField[4] = {0, 0, 0, 0}; + + retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_ABORT_OPCODE, 0, 0); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; /* Will return if mailbox busy bit is busy for more than 2 seconds */ + } + + retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_ABORT_OPCODE, timeoutMs, &cmdStatusByte); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; /* Will return if timeout occurred */ + } + + /* Read back Calibration Completion status */ + retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_GET_OPCODE, &payload, sizeof(payload)); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; /* Will return if mailbox busy bit is busy for more than 2 seconds */ + } + + retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_GET_OPCODE, timeoutMs, &cmdStatusByte); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; /* Will return if timeout occurred */ + } + + retVal = MYKONOS_readArmMem(device, (MYKONOS_ADDR_ARM_START_DATA_ADDR + 4), &calCompleteBitField[0], 4, 1); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + if (calsCompleted != NULL) + { + *calsCompleted = ((uint32_t)(calCompleteBitField[3]) << 24) | ((uint32_t)(calCompleteBitField[2]) << 16) | ((uint32_t)(calCompleteBitField[1]) << 8) + | ((uint32_t)(calCompleteBitField[0])); + } + else + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_ABORT_INITCALS_NULL_PARAM, + getMykonosErrorMessage(MYKONOS_ERR_ABORT_INITCALS_NULL_PARAM)); + return MYKONOS_ERR_ABORT_INITCALS_NULL_PARAM; + } + + return MYKONOS_ERR_OK; +} + +/** + * \brief Gets the device initialization calibration status + * + * This function requests the init cal status information from the Mykonos ARM + * processor. The ARM returns information including a bitmask that describes + * which calibrations have completed during the last cal of runInitCals, as + * well as the init cals that have run successfully since loading the ARM. If + * an ARM error does occur during one of the init calibrations, the initErrCal + * member returns the object ID of the failing calibration. The initErrCode + * returns the specific ARM error code that caused that calibration to fail. + * The calsMinimum structure member describes the minimum set of init calibrations + * required to complete by the ARM before it will allow the device to move to + * the radioOn state. + * + * Dependencies + * - device->spiSettings + * - device->spiSettings->chipSelectIndex + * + * \param device A pointer to the device settings structure + * \param initCalStatus Pointer to a structure that returns cal status information such as cals completed since last run, and init error codes + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_GETINITCALSTATUS_NULL_PARAM if initCalStatus parameter is a NULL pointer + * \retval MYKONOS_ERR_GETINITCALSTATUS_ARMERROR if ARM returned an error while requesting the init cal status information + */ +mykonosErr_t MYKONOS_getInitCalStatus(mykonosDevice_t *device, mykonosInitCalStatus_t *initCalStatus) +{ + mykonosErr_t retVal = MYKONOS_ERR_OK; + uint8_t cmdStatusByte = 0; + uint8_t calStatusArray[14] = {0}; + uint8_t payload[1] = {MYKONOS_ARM_OBJECTID_INIT_CAL_DONE}; + + uint32_t timeoutMs = 1000; + + /* Verify function parameter pointer is not NULL */ + if (initCalStatus == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETINITCALSTATUS_NULL_PARAM, + getMykonosErrorMessage(MYKONOS_ERR_GETINITCALSTATUS_NULL_PARAM)); + return MYKONOS_ERR_GETINITCALSTATUS_NULL_PARAM; + } + + retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_GET_OPCODE, &payload[0], sizeof(payload)); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; /* Will return if mailbox busy bit is busy for more than 2 seconds */ + } + + retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_GET_OPCODE, timeoutMs, &cmdStatusByte); + if (retVal != MYKONOS_ERR_OK) + { + if (cmdStatusByte > 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETINITCALSTATUS_ARMERROR, + getMykonosErrorMessage(MYKONOS_ERR_GETINITCALSTATUS_ARMERROR)); + return MYKONOS_ERR_GETINITCALSTATUS_ARMERROR; + } + + return retVal; /* Will return if timeout occurred */ + } + + if (cmdStatusByte > 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETINITCALSTATUS_ARMERROR, + getMykonosErrorMessage(MYKONOS_ERR_GETINITCALSTATUS_ARMERROR)); + return MYKONOS_ERR_GETINITCALSTATUS_ARMERROR; + } + + retVal = MYKONOS_readArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR, &calStatusArray[0], sizeof(calStatusArray), 1); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + initCalStatus->calsDoneLifetime = ((uint32_t)(calStatusArray[3]) << 24) | ((uint32_t)(calStatusArray[2]) << 16) | ((uint32_t)(calStatusArray[1]) << 8) + | ((uint32_t)(calStatusArray[0])); + initCalStatus->calsDoneLastRun = ((uint32_t)(calStatusArray[7]) << 24) | ((uint32_t)(calStatusArray[6]) << 16) | ((uint32_t)(calStatusArray[5]) << 8) + | ((uint32_t)(calStatusArray[4])); + initCalStatus->calsMinimum = ((uint32_t)(calStatusArray[11]) << 24) | ((uint32_t)(calStatusArray[10]) << 16) | ((uint32_t)(calStatusArray[9]) << 8) + | ((uint32_t)(calStatusArray[8])); + initCalStatus->initErrCal = calStatusArray[12]; + initCalStatus->initErrCode = calStatusArray[13]; + + return MYKONOS_ERR_OK; +} + +/** + * \brief Instructs the ARM processor to move the radio state to the Radio ON state + * + * When the ARM to the Radio On state, the enabled Rx and Tx signal chains will power up, + * and the ARM tracking calibrations will begin. To exit this state back to a low power, + * offline state, call the MYKONOS_radioOff() function. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device Pointer to the device settings structure + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_ARM_RADIOON_FAILED ARM returned error running this command + */ +mykonosErr_t MYKONOS_radioOn(mykonosDevice_t *device) +{ + mykonosErr_t retVal = MYKONOS_ERR_OK; + uint32_t timeoutMs = 1000; //1 second timeout + uint8_t cmdStatusByte = 0; + + retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_RADIOON_OPCODE, 0, 0); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; /* Will return if mailbox busy bit is busy for more than 2 seconds */ + } + + retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_RADIOON_OPCODE, timeoutMs, &cmdStatusByte); + if (retVal != MYKONOS_ERR_OK) + { + if (cmdStatusByte > 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_ARM_RADIOON_FAILED, + getMykonosErrorMessage(MYKONOS_ERR_ARM_RADIOON_FAILED)); + return MYKONOS_ERR_ARM_RADIOON_FAILED; + } + + return retVal; /* Will return if timeout occurred */ + } + + /* If ARM command error flag is 2, the command was not accepted, RUN_INIT must complete first */ + if (cmdStatusByte > 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_ARM_RADIOON_FAILED, getMykonosErrorMessage(MYKONOS_ERR_ARM_RADIOON_FAILED)); + return MYKONOS_ERR_ARM_RADIOON_FAILED; + } + + return MYKONOS_ERR_OK; +} + +/** + * \brief Instructs the ARM processor to move the radio state to the off state + * + * When the ARM moves from the Radio On state to Radio Off (Idle) the ARM tracking calibrations + * are stopped and the TxEnable/RxEnable, etc GPIO control pins will be ignored. This will also + * keep the receive and transmit chains powered down until the MYKONOS_radioOn() function + * is called again. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device Pointer to the device settings structure + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_ARM_RADIOOFF_FAILED ARM returned error running this command + */ +mykonosErr_t MYKONOS_radioOff(mykonosDevice_t *device) +{ + mykonosErr_t retVal = MYKONOS_ERR_OK; + const uint8_t ABORTCAL_OPCODE = 0x00; + uint32_t timeoutMs = 1000; //1 second timeout + uint8_t cmdStatusByte = 0; + + retVal = MYKONOS_sendArmCommand(device, ABORTCAL_OPCODE, 0, 0); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; /* Will return if mailbox busy bit is busy for more than 2 seconds */ + } + + retVal = MYKONOS_waitArmCmdStatus(device, ABORTCAL_OPCODE, timeoutMs, &cmdStatusByte); + if (retVal != MYKONOS_ERR_OK) + { + if (cmdStatusByte > 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_ARM_RADIOOFF_FAILED, + getMykonosErrorMessage(MYKONOS_ERR_ARM_RADIOOFF_FAILED)); + return MYKONOS_ERR_ARM_RADIOOFF_FAILED; + } + + return retVal; /* Will return if timeout occurred */ + } + + if (cmdStatusByte > 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_ARM_RADIOOFF_FAILED, getMykonosErrorMessage(MYKONOS_ERR_ARM_RADIOOFF_FAILED)); + return MYKONOS_ERR_ARM_RADIOOFF_FAILED; + } + + return MYKONOS_ERR_OK; +} + +/** + * \brief Reads the current ARM radio state + * + * Currently, *radioStatus only returns data in the lower 8 bits, but + * is defined as a 32bit status to allow for more information to be returned + * in the future. + * + * radioStatus | Bitfield + * -------------|------------------ + * [1:0] | State[1:0], 0=POWERUP, 1=READY, 2=INIT, 3=RADIO ON + * [3:2] | unused + * [4] | TDD_nFDD , 1= TDD, 0=FDD + * [7:5] | unused + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device Pointer to the device settings structure + * \param radioStatus The current ARM radio state is returned in this parameter + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_GETRADIOSTATE_NULL_PARAM Function parameter radioStatus has a NULL pointer + */ +mykonosErr_t MYKONOS_getRadioState(mykonosDevice_t *device, uint32_t *radioStatus) +{ + uint8_t status = 0; + + /* if radioStatus is not null */ + if (radioStatus != NULL) + { + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_ARM_OPCODE_STATE_0, &status); + *radioStatus = (uint32_t)status; + } + else + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETRADIOSTATE_NULL_PARAM, + getMykonosErrorMessage(MYKONOS_ERR_GETRADIOSTATE_NULL_PARAM)); + return MYKONOS_ERR_GETRADIOSTATE_NULL_PARAM; + } + + return MYKONOS_ERR_OK; +} + +/** + * \brief Sets which ARM tracking cals are enabled during the radioOn state. + * + * This command must be called during radioOff state. If called during radioOn, + * an error will be returned. The enum mykonosTrackingCalibrations_t can be used to + * OR together to form the enableMask parameter. + * + * enableMask | Bit description + * ------------|------------ + * [0] | TRACK_RX1_QEC + * [1] | TRACK_RX2_QEC + * [2] | TRACK_ORX1_QEC + * [3] | TRACK_ORX2_QEC + * [4] | TRACK_TX1_LOL + * [5] | TRACK_TX2_LOL + * [6] | TRACK_TX1_QEC + * [7] | TRACK_TX2_QEC + * [8] | TRACK_TX1_DPD + * [9] | TRACK_TX2_DPD + * [10] | TRACK_TX1_CLGC + * [11] | TRACK_TX2_CLGC + * [12] | TRACK_TX1_VSWR + * [13] | TRACK_TX2_VSWR + * [16] | TRACK_ORX1_QEC_SNLO + * [17] | TRACK_ORX2_QEC_SNLO + * [18] | TRACK_SRX_QEC + * + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device Pointer to the device settings structure + * \param enableMask A bitmask that selects which cals to run during radioOn state. + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_EN_TRACKING_CALS_ARMSTATE_ERROR Error: Tracking cals can only be enabled in the radioOff state. + * \retval MYKONOS_ERR_EN_TRACKING_CALS_ARMERROR ARM returned error when executing this command + */ +mykonosErr_t MYKONOS_enableTrackingCals(mykonosDevice_t *device, uint32_t enableMask) +{ + mykonosErr_t retVal = MYKONOS_ERR_OK; + uint8_t armData[4] = {0, 0, 0, 0}; + uint8_t extData[4] = {MYKONOS_ARM_OBJECTID_CALSCHEDULER, 0x00, 0x00, 0x04}; //Target ARM Object ID, Offset LSB, Offset MSB, Length + uint32_t timeoutMs = 0; + uint8_t cmdStatusByte = 0; + uint32_t radioStatus = 0; + uint8_t allowTx1AttenUpdates = 0; + uint8_t allowTx2AttenUpdates = 0; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_enableTrackingCals()\n"); +#endif + + /* read radio state to make sure ARM is in radioOff /IDLE */ + retVal = MYKONOS_getRadioState(device, &radioStatus); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + /* throw error if not in radioOff/IDLE state */ + if ((radioStatus & 0x03) != MYKONOS_ARM_SYSTEMSTATE_IDLE) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_EN_TRACKING_CALS_ARMSTATE_ERROR, + getMykonosErrorMessage(MYKONOS_ERR_EN_TRACKING_CALS_ARMSTATE_ERROR)); + return MYKONOS_ERR_EN_TRACKING_CALS_ARMSTATE_ERROR; + } + + /* In the ARM, DPD tracking and CLGC tracking share the same cal. Must + * set extra enable bits in ARM Memory to tell which cal to run. */ + retVal = enableDpdTracking(device, ((enableMask & (uint32_t)TRACK_TX1_DPD) ? 1 : 0), ((enableMask & (uint32_t)TRACK_TX2_DPD) ? 1 : 0)); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + if (((device->profilesValid & TX_PROFILE_VALID) > 0) && (device->tx->clgcConfig != NULL)) + { + allowTx1AttenUpdates = device->tx->clgcConfig->allowTx1AttenUpdates; + allowTx2AttenUpdates = device->tx->clgcConfig->allowTx2AttenUpdates; + } + else + { + allowTx1AttenUpdates = 0; + allowTx2AttenUpdates = 0; + } + + retVal = enableClgcTracking(device, ((allowTx1AttenUpdates > 0) ? 1 : 0), ((allowTx2AttenUpdates > 0) ? 1 : 0)); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + armData[0] = (uint8_t)(enableMask & 0xFF); + armData[1] = (uint8_t)((enableMask >> 8) & 0xFF); + armData[2] = (uint8_t)((enableMask >> 16) & 0xFF); + armData[3] = (uint8_t)((enableMask >> 24) & 0xFF); + retVal = MYKONOS_writeArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR, &armData[0], sizeof(armData)); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_WRITECFG_OPCODE, &extData[0], sizeof(extData)); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + timeoutMs = 1000; + retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_WRITECFG_OPCODE, timeoutMs, &cmdStatusByte); + if (retVal != MYKONOS_ERR_OK) + { + if (cmdStatusByte > 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_EN_TRACKING_CALS_ARMERROR, + getMykonosErrorMessage(MYKONOS_ERR_EN_TRACKING_CALS_ARMERROR)); + return MYKONOS_ERR_EN_TRACKING_CALS_ARMERROR; + } + + return retVal; + } + + if (cmdStatusByte > 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_EN_TRACKING_CALS_ARMERROR, + getMykonosErrorMessage(MYKONOS_ERR_EN_TRACKING_CALS_ARMERROR)); + return MYKONOS_ERR_EN_TRACKING_CALS_ARMERROR; + } + + return MYKONOS_ERR_OK; +} + +/** + * \brief Reschedules a tracking calibration to run. Can be used to + * override the tracking calibration timer and force a tracking calibration to run. + * Can be used to reschedule a tracking calibration after a tracking calibration + * error has been detected. Only one tracking calibration object can be scheduled + * per channel per function call. + * + * \pre Command can be called in either Radio On or Radio Off state. ARM must be + * initialized. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device Pointer to the device settings structure + * \param trackingCal Selects the tracking calibration to schedule. + * + * \retval MYKONOS_ERR_RESCHEDULE_TRACK_CAL_INV Not valid calibration passed + * \retval MYKONOS_ERR_RESCHEDULE_TRACK_ARMERRFLAG ARM error + * \retval MYKONOS_ERR_OK Function completed successfully + */ +mykonosErr_t MYKONOS_rescheduleTrackingCal(mykonosDevice_t *device, mykonosTrackingCalibrations_t trackingCal) +{ + mykonosErr_t retVal = MYKONOS_ERR_OK; + uint8_t extData[3] = {0}; + uint8_t cmdStatusByte = 0; + uint32_t timeoutMs = 1000; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_rescheduleTrackingCal()\n"); +#endif + + switch (trackingCal) + { + case TRACK_RX1_QEC: + extData[1] = MYKONOS_ARM_OBJECTID_RXQEC_TRACKING; + extData[2] = 0; + break; + + case TRACK_RX2_QEC: + extData[1] = MYKONOS_ARM_OBJECTID_RXQEC_TRACKING; + extData[2] = 1; + break; + + case TRACK_ORX1_QEC: + extData[1] = MYKONOS_ARM_OBJECTID_ORXQEC_TRACKING; + extData[2] = 0; + break; + + case TRACK_ORX2_QEC: + extData[1] = MYKONOS_ARM_OBJECTID_ORXQEC_TRACKING; + extData[2] = 1; + break; + + case TRACK_TX1_LOL: + extData[1] = MYKONOS_ARM_OBJECTID_TXLOL_TRACKING; + extData[2] = 0; + break; + + case TRACK_TX2_LOL: + extData[1] = MYKONOS_ARM_OBJECTID_TXLOL_TRACKING; + extData[2] = 1; + break; + + case TRACK_TX1_QEC: + extData[1] = MYKONOS_ARM_OBJECTID_TXQEC_TRACKING; + extData[2] = 0; + break; + + case TRACK_TX2_QEC: + extData[1] = MYKONOS_ARM_OBJECTID_TXQEC_TRACKING; + extData[2] = 1; + break; + + case TRACK_TX1_DPD: + extData[1] = MYKONOS_ARM_OBJECTID_DPDCONFIG; + extData[2] = 0; + break; + + case TRACK_TX2_DPD: + extData[1] = MYKONOS_ARM_OBJECTID_DPDCONFIG; + extData[2] = 1; + break; + + case TRACK_TX1_CLGC: + extData[1] = MYKONOS_ARM_OBJECTID_CLGCCONFIG; + extData[2] = 0; + break; + + case TRACK_TX2_CLGC: + extData[1] = MYKONOS_ARM_OBJECTID_CLGCCONFIG; + extData[2] = 1; + break; + + case TRACK_TX1_VSWR: + extData[1] = MYKONOS_ARM_OBJECTID_VSWRCONFIG; + extData[2] = 0; + break; + + case TRACK_TX2_VSWR: + extData[1] = MYKONOS_ARM_OBJECTID_VSWRCONFIG; + extData[2] = 1; + break; + + default: + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RESCHEDULE_TRACK_CAL_INV, + getMykonosErrorMessage(MYKONOS_ERR_RESCHEDULE_TRACK_CAL_INV)); + return MYKONOS_ERR_RESCHEDULE_TRACK_CAL_INV; + } + + extData[0] = MYKONOS_ARM_OBJECTID_TRACKING_CAL_PENDING; + + /* sending ARM command */ + retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_SET_OPCODE, &extData[0], sizeof(extData)); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + /* check for completion */ + retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_SET_OPCODE, timeoutMs, &cmdStatusByte); + if (retVal != MYKONOS_ERR_OK) + { + if (cmdStatusByte > 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RESCHEDULE_TRACK_ARMERRFLAG, + getMykonosErrorMessage(MYKONOS_ERR_RESCHEDULE_TRACK_ARMERRFLAG)); + return MYKONOS_ERR_RESCHEDULE_TRACK_ARMERRFLAG; + } + + return retVal; + } + + if (cmdStatusByte > 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RESCHEDULE_TRACK_ARMERRFLAG, + getMykonosErrorMessage(MYKONOS_ERR_RESCHEDULE_TRACK_ARMERRFLAG)); + return MYKONOS_ERR_RESCHEDULE_TRACK_ARMERRFLAG; + } + + return retVal; +} + +/** + * \brief Suspend or resume tracking calibrations in RADIO_ON. + * + * This function is used to suspend or resume active tracking calibrations based on the passed mask trackingCals. + * + * \pre Command can be called in Radio On. + * + * trackCals[bit] | Bit description + * ----------------|------------ + * [0] | TRACK_RX1_QEC + * [1] | TRACK_RX2_QEC + * [2] | TRACK_ORX1_QEC + * [3] | TRACK_ORX2_QEC + * [4] | TRACK_TX1_LOL + * [5] | TRACK_TX2_LOL + * [6] | TRACK_TX1_QEC + * [7] | TRACK_TX2_QEC + * [8] | TRACK_TX1_DPD + * [9] | TRACK_TX2_DPD + * [10] | TRACK_TX1_CLGC + * [11] | TRACK_TX2_CLGC + * [12] | TRACK_TX1_VSWR + * [13] | TRACK_TX2_VSWR + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device Pointer to the device settings structure + * \param trackCals Selects the tracking calibrations to suspend or resume during the radio ON state. + * mykonosTrackingCalibrations_t enumerated types are or'd together to form the tracking calibration + * mask word. If the bit is high the calibration will resume, if the bit is low the calibration will be suspended. + * + * \retval MYKONOS_ERR_SETSTATEALL_TRACK_CAL_INV Not valid calibration mask passed for trackCals + * \retval MYKONOS_ERR_SETSTATEALL_TRACK_ARMERRFLAG ARM error + * \retval MYKONOS_ERR_OK Function completed successfully + */ +mykonosErr_t MYKONOS_setAllTrackCalState(mykonosDevice_t *device, uint32_t trackCals) +{ + mykonosErr_t retVal = MYKONOS_ERR_OK; + uint8_t cfgData[4] = {0}; + uint8_t extData[3] = {MYKONOS_ARM_OBJECTID_TRACKING_CAL_SUSPEND_RESUME, 0x0F, 0}; + uint8_t cmdStatusByte = 0; + uint32_t enTrackCal = 0x00; + uint32_t timeoutMs = 1000; + + const uint32_t TRACKING_MASK = 0x3FFF; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setAllTrackCalState()\n"); +#endif + + /* reading enabled tracking calibrations */ + retVal = MYKONOS_getEnabledTrackingCals(device, &enTrackCal); + + /* trackingCalMask check */ + if (((trackCals | enTrackCal) > enTrackCal) || (trackCals > TRACKING_MASK)) + { + /* invalid cal mask error return, tracking cal not enable so we can not resume it */ + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETSTATEALL_TRACK_CAL_INV, + getMykonosErrorMessage(MYKONOS_ERR_SETSTATEALL_TRACK_CAL_INV)); + return MYKONOS_ERR_SETSTATEALL_TRACK_CAL_INV; + } + + /* convert tracking mask to array of uint8_t type */ + cfgData[0] = (uint8_t)(trackCals & 0xFF); + cfgData[1] = (uint8_t)((trackCals >> 8) & 0xFF); + cfgData[2] = (uint8_t)((trackCals >> 16) & 0x0FF); + cfgData[3] = (uint8_t)((trackCals >> 24) & 0xFF); + + retVal = MYKONOS_writeArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR, &cfgData[0], sizeof(cfgData)); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_SET_OPCODE, &extData[0], sizeof(extData)); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + /* check for completion */ + retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_SET_OPCODE, timeoutMs, &cmdStatusByte); + if (retVal != MYKONOS_ERR_OK) + { + if (cmdStatusByte > 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETSTATEALL_TRACK_ARMERRFLAG, + getMykonosErrorMessage(MYKONOS_ERR_SETSTATEALL_TRACK_ARMERRFLAG)); + return MYKONOS_ERR_SETSTATEALL_TRACK_ARMERRFLAG; + } + + return retVal; + } + + if (cmdStatusByte > 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETSTATEALL_TRACK_ARMERRFLAG, + getMykonosErrorMessage(MYKONOS_ERR_SETSTATEALL_TRACK_ARMERRFLAG)); + return MYKONOS_ERR_SETSTATEALL_TRACK_ARMERRFLAG; + } + + return retVal; +} + +/** + * \brief Get the Suspended or Resumed state for tracking calibrations + * + * This function is used to get the suspend or resume state of all active tracking calibrations and the state is stored in trackCals. + * + * \pre Command can be called in Radio On. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device Pointer to the device settings structure + * \param trackCals pointer to store the tracking calibration state. + * If the bit is set then the tracking calibration is resumed and if not set then the tracking cal is suspended, the bit field follows: + * + * trackCals[bit] | Bit description + * ---------------|------------ + * [0] | TRACK_RX1_QEC + * [1] | TRACK_RX2_QEC + * [2] | TRACK_ORX1_QEC + * [3] | TRACK_ORX2_QEC + * [4] | TRACK_TX1_LOL + * [5] | TRACK_TX2_LOL + * [6] | TRACK_TX1_QEC + * [7] | TRACK_TX2_QEC + * [8] | TRACK_TX1_DPD + * [9] | TRACK_TX2_DPD + * [10] | TRACK_TX1_CLGC + * [11] | TRACK_TX2_CLGC + * [12] | TRACK_TX1_VSWR + * [13] | TRACK_TX2_VSWR + * + * \retval MYKONOS_ERR_GETSTATEALL_TRACK_NULL_PARAM Null parameter passed for trackCals + * \retval MYKONOS_ERR_GETSTATEALL_TRACK_ARMERRFLAG ARM error flag set. + * \retval MYKONOS_ERR_GETSTATEALL_TRACK_ARMERROR ARM command error. + * \retval MYKONOS_ERR_OK Function completed successfully + */ +mykonosErr_t MYKONOS_getAllTrackCalState(mykonosDevice_t *device, uint32_t *trackCals) +{ + mykonosErr_t retVal = MYKONOS_ERR_OK; + uint8_t extData = MYKONOS_ARM_OBJECTID_TRACKING_CAL_SUSPEND_RESUME; + uint8_t armData[4] = {0}; + uint8_t cmdStatusByte = 0; + uint32_t timeoutMs = 1000; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getAllTrackCalState()\n"); +#endif + + /* Check for passed parameter */ + if (trackCals == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETSTATEALL_TRACK_NULL_PARAM, + getMykonosErrorMessage(MYKONOS_ERR_GETSTATEALL_TRACK_NULL_PARAM)); + return MYKONOS_ERR_GETSTATEALL_TRACK_NULL_PARAM; + } + + /* sending ARM command */ + retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_GET_OPCODE, &extData, sizeof(extData)); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + /* check for completion */ + retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_GET_OPCODE, timeoutMs, &cmdStatusByte); + if (retVal != MYKONOS_ERR_OK) + { + if (cmdStatusByte > 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETSTATEALL_TRACK_ARMERRFLAG, + getMykonosErrorMessage(MYKONOS_ERR_GETSTATEALL_TRACK_ARMERRFLAG)); + return MYKONOS_ERR_GETSTATEALL_TRACK_ARMERRFLAG; + } + + return retVal; + } + + if (cmdStatusByte > 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETSTATEALL_TRACK_ARMERRFLAG, + getMykonosErrorMessage(MYKONOS_ERR_GETSTATEALL_TRACK_ARMERRFLAG)); + return MYKONOS_ERR_GETSTATEALL_TRACK_ARMERRFLAG; + } + + /* read 32-bit tracking state from ARM memory */ + retVal = MYKONOS_readArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR, &armData[0], sizeof(armData), 1); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + *trackCals = (uint32_t)armData[0] | ((uint32_t)armData[1] << 8) | ((uint32_t)armData[2] << 16) | ((uint32_t)armData[3] << 24); + + return retVal; +} + +/** + * \brief Suspend or resume individual tracking calibration + * + * \pre The tracking calibration must have been enabled with MYKONOS_enableTrackingCals(), this command can be called in Radio On. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device Pointer to the device settings structure + * \param trackingCal Selects the tracking calibration to resume or suspend. + * \param trackCalState if set then the selected tracking calibration will be resumed and if not set then the tracking cal will be suspended + * + * \retval MYKONOS_ERR_SETSTATE_TRACK_CAL_INV Not valid calibration passed + * \retval MYKONOS_ERR_SETSTATE_TRACK_ARMERRFLAG ARM error + * \retval MYKONOS_ERR_OK Function completed successfully + */ +mykonosErr_t MYKONOS_setTrackingCalState(mykonosDevice_t *device, mykonosTrackingCalibrations_t trackingCal, uint8_t trackCalState) +{ + mykonosErr_t retVal = MYKONOS_ERR_OK; + uint8_t extData[2] = {0}; + uint8_t cmdStatusByte = 0; + uint8_t suspendTrack = 0x0F; + uint32_t timeoutMs = 1000; + uint32_t enTrackCal = 0x00; + + const uint8_t CHANNEL_1 = 0x00; + const uint8_t CHANNEL_2 = 0x10; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setTrackingCalState()\n"); +#endif + + if (trackCalState > 0) + { + suspendTrack = 0x2F; + } + + /* reading enabled tracking calibrations */ + retVal = MYKONOS_getEnabledTrackingCals(device, &enTrackCal); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + /* trackingCalMask check */ + if (((uint8_t)trackingCal & enTrackCal) != (uint8_t)trackingCal) + { + /* invalid cal mask error return, tracking cal not enable so we can not resume or suspend it */ + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETSTATE_TRACK_CAL_INV, + getMykonosErrorMessage(MYKONOS_ERR_SETSTATE_TRACK_CAL_INV)); + return MYKONOS_ERR_SETSTATE_TRACK_CAL_INV; + } + + switch (trackingCal) + { + case TRACK_RX1_QEC: + extData[1] = MYKONOS_ARM_OBJECTID_RXQEC_TRACKING & suspendTrack; + extData[1] |= CHANNEL_1; + break; + + case TRACK_RX2_QEC: + extData[1] = MYKONOS_ARM_OBJECTID_RXQEC_TRACKING & suspendTrack; + extData[1] |= CHANNEL_2; + break; + + case TRACK_ORX1_QEC: + extData[1] = MYKONOS_ARM_OBJECTID_ORXQEC_TRACKING & suspendTrack; + extData[1] |= CHANNEL_1; + break; + + case TRACK_ORX2_QEC: + extData[1] = MYKONOS_ARM_OBJECTID_ORXQEC_TRACKING & suspendTrack; + extData[1] |= CHANNEL_2; + break; + + case TRACK_TX1_LOL: + extData[1] = MYKONOS_ARM_OBJECTID_TXLOL_TRACKING & suspendTrack; + extData[1] |= CHANNEL_1; + break; + + case TRACK_TX2_LOL: + extData[1] = MYKONOS_ARM_OBJECTID_TXLOL_TRACKING & suspendTrack; + extData[1] |= CHANNEL_2; + break; + + case TRACK_TX1_QEC: + extData[1] = MYKONOS_ARM_OBJECTID_TXQEC_TRACKING & suspendTrack; + extData[1] |= CHANNEL_1; + break; + + case TRACK_TX2_QEC: + extData[1] = MYKONOS_ARM_OBJECTID_TXQEC_TRACKING & suspendTrack; + extData[1] |= CHANNEL_2; + break; + + case TRACK_TX1_DPD: + extData[1] = MYKONOS_ARM_OBJECTID_DPDCONFIG & suspendTrack; + extData[1] |= CHANNEL_1; + break; + + case TRACK_TX2_DPD: + extData[1] = MYKONOS_ARM_OBJECTID_DPDCONFIG & suspendTrack; + extData[1] |= CHANNEL_2; + break; + + case TRACK_TX1_CLGC: + extData[1] = MYKONOS_ARM_OBJECTID_CLGCCONFIG & suspendTrack; + extData[1] |= CHANNEL_1; + break; + + case TRACK_TX2_CLGC: + extData[1] = MYKONOS_ARM_OBJECTID_CLGCCONFIG & suspendTrack; + extData[1] |= CHANNEL_2; + break; + + case TRACK_TX1_VSWR: + extData[1] = MYKONOS_ARM_OBJECTID_VSWRCONFIG & suspendTrack; + extData[1] |= CHANNEL_1; + break; + + case TRACK_TX2_VSWR: + extData[1] = MYKONOS_ARM_OBJECTID_VSWRCONFIG & suspendTrack; + extData[1] |= CHANNEL_2; + break; + + default: + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETSTATE_TRACK_CAL_INV, + getMykonosErrorMessage(MYKONOS_ERR_SETSTATE_TRACK_CAL_INV)); + return MYKONOS_ERR_SETSTATE_TRACK_CAL_INV; + } + + extData[0] = MYKONOS_ARM_OBJECTID_TRACKING_CAL_SUSPEND_RESUME; + + /* sending ARM command */ + retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_SET_OPCODE, &extData[0], sizeof(extData)); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + /* check for completion */ + retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_SET_OPCODE, timeoutMs, &cmdStatusByte); + if (retVal != MYKONOS_ERR_OK) + { + if (cmdStatusByte > 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETSTATE_TRACK_ARMERRFLAG, + getMykonosErrorMessage(MYKONOS_ERR_SETSTATE_TRACK_ARMERRFLAG)); + return MYKONOS_ERR_SETSTATE_TRACK_ARMERRFLAG; + } + } + + return retVal; +} + +/** + * \brief Get the Suspended or Resumed state for individual tracking calibration + * + * \pre Command can be called in Radio On. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device Pointer to the device settings structure + * \param trackingCal Selects the tracking calibration to get the resumed or suspended state. + * \param trackCalState pointer to store the tracking calibration state, + * if set then the selected tracking calibration is resumed and if not set then the tracking cal is suspended + * + * \retval MYKONOS_ERR_GETSTATE_TRACK_NULL_PARAM Null parameter passed to trackCalState + * \retval MYKONOS_ERR_GETSTATE_TRACK_ARMERRFLAG ARM command error flag set. + * \retval MYKONOS_ERR_GETSTATE_TRACK_ARMERROR ARM command error. + * \retval MYKONOS_ERR_OK Function completed successfully + */ +mykonosErr_t MYKONOS_getTrackingCalState(mykonosDevice_t *device, mykonosTrackingCalibrations_t trackingCal, uint8_t *trackCalState) +{ + mykonosErr_t retVal = MYKONOS_ERR_OK; + uint8_t extData = MYKONOS_ARM_OBJECTID_TRACKING_CAL_SUSPEND_RESUME; + uint8_t armData[4] = {0}; + uint8_t cmdStatusByte = 0; + uint32_t timeoutMs = 1000; + uint32_t trackMask = 0x00; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getTrackingCalState()\n"); +#endif + + /* Check for passed parameter */ + if (trackCalState == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETSTATE_TRACK_NULL_PARAM, + getMykonosErrorMessage(MYKONOS_ERR_GETSTATE_TRACK_NULL_PARAM)); + return MYKONOS_ERR_GETSTATE_TRACK_NULL_PARAM; + } + + /* sending ARM command */ + retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_GET_OPCODE, &extData, sizeof(extData)); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + /* check for completion */ + retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_GET_OPCODE, timeoutMs, &cmdStatusByte); + if (retVal != MYKONOS_ERR_OK) + { + if (cmdStatusByte > 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETSTATE_TRACK_ARMERRFLAG, + getMykonosErrorMessage(MYKONOS_ERR_GETSTATE_TRACK_ARMERRFLAG)); + return MYKONOS_ERR_GETSTATE_TRACK_ARMERRFLAG; + } + + return retVal; + } + + if (cmdStatusByte > 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETSTATE_TRACK_ARMERRFLAG, + getMykonosErrorMessage(MYKONOS_ERR_GETSTATE_TRACK_ARMERRFLAG)); + return MYKONOS_ERR_GETSTATE_TRACK_ARMERRFLAG; + } + + /* read 32-bit tracking state from ARM memory */ + retVal = MYKONOS_readArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR, &armData[0], sizeof(armData), 1); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + trackMask = (uint32_t)armData[0] | ((uint32_t)armData[1] << 8) | ((uint32_t)armData[2] << 16) | ((uint32_t)armData[3] << 24); + + if (trackMask & (uint32_t)trackingCal) + { + *trackCalState = 1; + } + else + { + *trackCalState = 0; + } + + return retVal; +} + +/** + * \brief Reads back which ARM tracking cals are enabled + * + * enableMask | Bit description + * ------------|---------------------- + * [0] | TRACK_RX1_QEC + * [1] | TRACK_RX2_QEC + * [2] | TRACK_ORX1_QEC + * [3] | TRACK_ORX2_QEC + * [4] | TRACK_TX1_LOL + * [5] | TRACK_TX2_LOL + * [6] | TRACK_TX1_QEC + * [7] | TRACK_TX2_QEC + * [8] | TRACK_TX1_DPD + * [9] | TRACK_TX2_DPD + * [10] | TRACK_TX1_CLGC + * [11] | TRACK_TX2_CLGC + * [12] | TRACK_TX1_VSWR + * [13] | TRACK_TX2_VSWR + * [16] | TRACK_ORX1_QEC_SNLO + * [17] | TRACK_ORX1_QEC_SNLO + * [18] | TRACK_SRX_QEC + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device Pointer to the device settings structure + * \param enableMask Returned bitmask that shows which tracking cals are enabled + * to run during radioOn state. See mykonosTrackingCalibrations_t enum of tracking cals. + * + * \retval MYKONOS_ERR_OK Function completed successfully + */ +mykonosErr_t MYKONOS_getEnabledTrackingCals(mykonosDevice_t *device, uint32_t *enableMask) +{ + mykonosErr_t retVal = MYKONOS_ERR_OK; + uint8_t armData[4] = {0}; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getEnabledTrackingCals()\n"); +#endif + + /* Ask ARM to read tracking cal enable bits and place in mailbox buffer memory */ + retVal = MYKONOS_readArmConfig(device, MYKONOS_ARM_OBJECTID_CALSCHEDULER, 0, &armData[0], 4); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + *enableMask = ((uint32_t)(armData[0]) | ((uint32_t)(armData[1]) << 8) | ((uint32_t)(armData[2]) << 16) | ((uint32_t)(armData[3]) << 24)); + + return MYKONOS_ERR_OK; +} + +/** + * \brief Returns the tracking calibration pending and error status. + * + * When in radioOn state, the enabled tracking calibrations will set the pending + * flag when the particular calibration is ready to be run, but has not completed + * yet. For Tx tracking cals to complete, the BBIC must set the ObsRx path to + * the INTERNAL CALS mode. If a tracking calibration had an error, the corresponding + * error flag will be asserted. + * + * pendingCalMask | bit Description + * ----------------|-------------------------------------------------------- + * [0] | Rx1 QEC tracking pending + * [1] | Rx1 QEC tracking error + * [2] | Rx2 QEC tracking pending + * [3] | Rx2 QEC tracking error + * [4] | ORx1 QEC tracking pending + * [5] | ORx1 QEC tracking error + * [6] | ORx2 QEC tracking pending + * [7] | ORx2 QEC tracking error + * [8] | Tx1 LOL tracking pending + * [9] | Tx1 LOL tracking error + * [10] | Tx2 LOL tracking pending + * [11] | Tx2 LOL tracking error + * [12] | Tx1 QEC tracking pending + * [13] | Tx1 QEC tracking error + * [14] | Tx2 QEC tracking pending + * [15] | Tx2 QEC tracking error + * [16] | Tx1 DPD tracking pending + * [17] | Tx1 DPD tracking error + * [18] | Tx2 DPD tracking pending + * [19] | Tx2 DPD tracking error + * [20] | Tx1 CLGC tracking pending + * [21] | Tx1 CLGC tracking error + * [22] | Tx2 CLGC tracking pending + * [23] | Tx2 CLGC tracking error + * [24] | Tx1 VSWR tracking pending + * [25] | Tx1 VSWR tracking error + * [26] | Tx2 VSWR tracking pending + * [27] | Tx2 VSWR tracking error + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device Pointer to the device settings structure + * \param pendingCalMask Bit mask that describes which tracking cals are pending + * or had errors + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_GETPENDTRKCALS_NULL_PARAM Function parameter pendingCalMask is a NULL pointer + */ +mykonosErr_t MYKONOS_getPendingTrackingCals(mykonosDevice_t *device, uint32_t *pendingCalMask) +{ + uint8_t readData[4] = {0}; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getPendingTrackingCals()\n"); +#endif + + if (pendingCalMask == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETPENDTRKCALS_NULL_PARAM, + getMykonosErrorMessage(MYKONOS_ERR_GETPENDTRKCALS_NULL_PARAM)); + return MYKONOS_ERR_GETPENDTRKCALS_NULL_PARAM; + } + + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_ARM_OPCODE_STATE_3, &readData[0]); + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_ARM_OPCODE_STATE_4, &readData[1]); + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_ARM_OPCODE_STATE_5, &readData[2]); + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_ARM_OPCODE_STATE_6, &readData[3]); + *pendingCalMask = ((uint32_t)readData[3] << 24) | ((uint32_t)readData[2] << 16) | ((uint32_t)readData[1] << 8) | ((uint32_t)readData[0]); + + return MYKONOS_ERR_OK; +} + +/** + * \brief Returns the status of the TxLOL external tracking calibration + * + * The Tx LOL external tracking calibration is run during the radioOn state. + * The function can be called to read back the status of the TxLOL external + * calibration including metrics like error codes, percentage of data + * collected for current cal, the performance of the cal and the number of + * times the cal has run and updated the hardware. + * + * \pre Before the function is called, the device must be initialized, the ARM + * loaded, and init cals run. These functions can be called in radioOff or + * radioOn state. + * + * \param device Pointer to the device settings structure + * \param txChannel The channel (Tx1/Tx2) whose status is to be read back + * \param txLolStatus Status of the TxLOL external calibration, as a structure + * of type mykonosTxLolStatus_t is returned to this pointer address + * + * \retval MYKONOS_ERR_GETTXLOLSTATUS_NULLPARAM Function parameter mykonosTxLolStatus_t is a NULL pointer + * \retval MYKONOS_ERR_GETTXLOLSTATUS_INV_CH Channel selection not valid + * \retval MYKONOS_ERR_GETTXLOLSTATUS_ARMERRFLAG ARM command error + * \retval MYKONOS_ERR_OK Function completed successfully + */ +mykonosErr_t MYKONOS_getTxLolStatus(mykonosDevice_t *device, mykonosTxChannels_t txChannel, mykonosTxLolStatus_t *txLolStatus) +{ + uint8_t extData[3] = {MYKONOS_ARM_OBJECTID_CAL_STATUS, MYKONOS_ARM_OBJECTID_TXLOL_TRACKING, 0}; + uint8_t cmdStatusByte = 0; + uint32_t offset = 0; + uint32_t timeoutMs = 0; + uint8_t armReadBack[20] = {0}; + mykonosErr_t retVal = MYKONOS_ERR_OK; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getTxLolStatus()\n"); +#endif + + if (txLolStatus == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETTXLOLSTATUS_NULLPARAM, + getMykonosErrorMessage(MYKONOS_ERR_GETTXLOLSTATUS_NULLPARAM)); + return MYKONOS_ERR_GETTXLOLSTATUS_NULLPARAM; + } + + switch (txChannel) + { + case TX1: + extData[2] = 0; + break; + case TX2: + extData[2] = 1; + break; + default: + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETTXLOLSTATUS_INV_CH, + getMykonosErrorMessage(MYKONOS_ERR_GETTXLOLSTATUS_INV_CH)); + return MYKONOS_ERR_GETTXLOLSTATUS_INV_CH; + } + } + + retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_GET_OPCODE, &extData[0], sizeof(extData)); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + timeoutMs = 1000; + retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_GET_OPCODE, timeoutMs, &cmdStatusByte); + if (retVal != MYKONOS_ERR_OK) + { + if (cmdStatusByte > 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETTXLOLSTATUS_ARMERRFLAG, + getMykonosErrorMessage(MYKONOS_ERR_GETTXLOLSTATUS_ARMERRFLAG)); + return MYKONOS_ERR_GETTXLOLSTATUS_ARMERRFLAG; + } + + return retVal; + } + + if (cmdStatusByte > 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETTXLOLSTATUS_ARMERRFLAG, + getMykonosErrorMessage(MYKONOS_ERR_GETTXLOLSTATUS_ARMERRFLAG)); + return MYKONOS_ERR_GETTXLOLSTATUS_ARMERRFLAG; + } + + /* read status from ARM memory */ + offset = 0; + retVal = MYKONOS_readArmMem(device, (MYKONOS_ADDR_ARM_START_DATA_ADDR + offset), &armReadBack[0], sizeof(armReadBack), 1); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + /* Assign to data structure */ + txLolStatus->errorCode = (((uint32_t)armReadBack[3]) << 24) | (((uint32_t)armReadBack[2]) << 16) | (((uint32_t)armReadBack[1]) << 8) | ((uint32_t)armReadBack[0]); + txLolStatus->percentComplete = (((uint32_t)armReadBack[7]) << 24) | (((uint32_t)armReadBack[6]) << 16) | (((uint32_t)armReadBack[5]) << 8) + | ((uint32_t)armReadBack[4]); + txLolStatus->performanceMetric = (((uint32_t)armReadBack[11]) << 24) | (((uint32_t)armReadBack[10]) << 16) | (((uint32_t)armReadBack[9]) << 8) + | ((uint32_t)armReadBack[8]); + txLolStatus->iterCount = (((uint32_t)armReadBack[15]) << 24) | (((uint32_t)armReadBack[14]) << 16) | (((uint32_t)armReadBack[13]) << 8) | ((uint32_t)armReadBack[12]); + txLolStatus->updateCount = (((uint32_t)armReadBack[19]) << 24) | (((uint32_t)armReadBack[18]) << 16) | (((uint32_t)armReadBack[17]) << 8) + | ((uint32_t)armReadBack[16]); + + return MYKONOS_ERR_OK; +} + +/** + * \brief Returns the status of the TxQEC tracking calibration + * + * The Tx QEC tracking calibration is run during the radioOn state. + * The function can be called to read back the status of the TxQEC + * calibration including metrics like error codes, percentage of data + * collected for current cal, the performance of the cal and the number of + * times the cal has run and updated the hardware. + * + * \pre Before the function is called, the device must be initialized, the ARM + * loaded, and init cals run. These functions can be called in radioOff or + * radioOn state. + * + * \param device Pointer to the device settings structure + * \param txChannel The channel (Tx1/Tx2) whose status is to be read back + * \param txQecStatus Status of the TxQEC external calibration, as a structure + * of type mykonosTxQecStatus_t is returned to this pointer address + * + * \retval MYKONOS_ERR_GETTXQECSTATUS_NULLPARAM Function parameter txQecStatus is a NULL pointer + * \retval MYKONOS_ERR_GETTXQECSTATUS_INV_CH Channel selection not valid + * \retval MYKONOS_ERR_GETTXQECSTATUS_ARMERRFLAG ARM command error + * \retval MYKONOS_ERR_OK Function completed successfully + */ +mykonosErr_t MYKONOS_getTxQecStatus(mykonosDevice_t *device, mykonosTxChannels_t txChannel, mykonosTxQecStatus_t *txQecStatus) +{ + uint8_t extData[3] = {MYKONOS_ARM_OBJECTID_CAL_STATUS, MYKONOS_ARM_OBJECTID_TXQEC_TRACKING, 0}; + uint8_t cmdStatusByte = 0; + uint32_t offset = 0; + uint32_t timeoutMs = 0; + uint8_t armReadBack[20] = {0}; + mykonosErr_t retVal = MYKONOS_ERR_OK; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getTxQecStatus()\n"); +#endif + + if (txQecStatus == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETTXQECSTATUS_NULLPARAM, + getMykonosErrorMessage(MYKONOS_ERR_GETTXQECSTATUS_NULLPARAM)); + return MYKONOS_ERR_GETTXQECSTATUS_NULLPARAM; + } + + switch (txChannel) + { + case TX1: + extData[2] = 0; + break; + case TX2: + extData[2] = 1; + break; + default: + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETTXQECSTATUS_INV_CH, + getMykonosErrorMessage(MYKONOS_ERR_GETTXQECSTATUS_INV_CH)); + return MYKONOS_ERR_GETTXQECSTATUS_INV_CH; + } + } + + retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_GET_OPCODE, &extData[0], sizeof(extData)); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + timeoutMs = 1000; + retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_GET_OPCODE, timeoutMs, &cmdStatusByte); + if (retVal != MYKONOS_ERR_OK) + { + if (cmdStatusByte > 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETTXQECSTATUS_ARMERRFLAG, + getMykonosErrorMessage(MYKONOS_ERR_GETTXQECSTATUS_ARMERRFLAG)); + return MYKONOS_ERR_GETTXQECSTATUS_ARMERRFLAG; + } + + return retVal; + } + + if (cmdStatusByte > 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETTXQECSTATUS_ARMERRFLAG, + getMykonosErrorMessage(MYKONOS_ERR_GETTXQECSTATUS_ARMERRFLAG)); + return MYKONOS_ERR_GETTXQECSTATUS_ARMERRFLAG; + } + + /* read status from ARM memory */ + offset = 0; + retVal = MYKONOS_readArmMem(device, (MYKONOS_ADDR_ARM_START_DATA_ADDR + offset), &armReadBack[0], sizeof(armReadBack), 1); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + /* Assign to data structure */ + txQecStatus->errorCode = (((uint32_t)armReadBack[3]) << 24) | (((uint32_t)armReadBack[2]) << 16) | (((uint32_t)armReadBack[1]) << 8) | ((uint32_t)armReadBack[0]); + txQecStatus->percentComplete = (((uint32_t)armReadBack[7]) << 24) | (((uint32_t)armReadBack[6]) << 16) | (((uint32_t)armReadBack[5]) << 8) + | ((uint32_t)armReadBack[4]); + txQecStatus->performanceMetric = (((uint32_t)armReadBack[11]) << 24) | (((uint32_t)armReadBack[10]) << 16) | (((uint32_t)armReadBack[9]) << 8) + | ((uint32_t)armReadBack[8]); + txQecStatus->iterCount = (((uint32_t)armReadBack[15]) << 24) | (((uint32_t)armReadBack[14]) << 16) | (((uint32_t)armReadBack[13]) << 8) | ((uint32_t)armReadBack[12]); + txQecStatus->updateCount = (((uint32_t)armReadBack[19]) << 24) | (((uint32_t)armReadBack[18]) << 16) | (((uint32_t)armReadBack[17]) << 8) + | ((uint32_t)armReadBack[16]); + + return MYKONOS_ERR_OK; +} + +/** + * \brief Returns the status of the RxQEC tracking calibration + * + * The Rx QEC tracking calibration is run during the radioOn state. + * The function can be called to read back the status of the RxQEC external + * calibration including metrics like error codes, percentage of data + * collected for current cal, the performance of the cal and the number of + * times the cal has run and updated the hardware. + * + * \pre Before the function is called, the device must be initialized, the ARM + * loaded, and init cals run. These functions can be called in radioOff or + * radioOn state. + * + * \param device Pointer to the device settings structure + * \param rxChannel The channel (Rx1/Rx2) whose status is to be read back + * \param rxQecStatus Status of the RxQEC calibration, as a structure + * of type mykonosRxQecStatus_t is returned to this pointer address + * + * \retval MYKONOS_ERR_GETRXQECSTATUS_NULLPARAM Function parameter rxQecStatus is a NULL pointer + * \retval MYKONOS_ERR_GETRXQECSTATUS_INV_CH Channel selection not valid + * \retval MYKONOS_ERR_GETRXQECSTATUS_ARMERRFLAG ARM command error + * \retval MYKONOS_ERR_OK Function completed successfully + */ +mykonosErr_t MYKONOS_getRxQecStatus(mykonosDevice_t *device, mykonosRxChannels_t rxChannel, mykonosRxQecStatus_t *rxQecStatus) +{ + uint8_t extData[3] = {MYKONOS_ARM_OBJECTID_CAL_STATUS, MYKONOS_ARM_OBJECTID_RXQEC_TRACKING, 0}; + uint8_t cmdStatusByte = 0; + uint32_t offset = 0; + uint32_t timeoutMs = 0; + uint8_t armReadBack[20] = {0}; + mykonosErr_t retVal = MYKONOS_ERR_OK; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getRxQecStatus()\n"); +#endif + + if (rxQecStatus == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETRXQECSTATUS_NULLPARAM, + getMykonosErrorMessage(MYKONOS_ERR_GETRXQECSTATUS_NULLPARAM)); + return MYKONOS_ERR_GETRXQECSTATUS_NULLPARAM; + } + + switch (rxChannel) + { + case RX1: + extData[2] = 0; + break; + case RX2: + extData[2] = 1; + break; + default: + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETRXQECSTATUS_INV_CH, + getMykonosErrorMessage(MYKONOS_ERR_GETRXQECSTATUS_INV_CH)); + return MYKONOS_ERR_GETRXQECSTATUS_INV_CH; + } + } + + retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_GET_OPCODE, &extData[0], sizeof(extData)); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + timeoutMs = 1000; + retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_GET_OPCODE, timeoutMs, &cmdStatusByte); + if (retVal != MYKONOS_ERR_OK) + { + if (cmdStatusByte > 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETRXQECSTATUS_ARMERRFLAG, + getMykonosErrorMessage(MYKONOS_ERR_GETRXQECSTATUS_ARMERRFLAG)); + return MYKONOS_ERR_GETRXQECSTATUS_ARMERRFLAG; + } + + return retVal; + } + + if (cmdStatusByte > 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETRXQECSTATUS_ARMERRFLAG, + getMykonosErrorMessage(MYKONOS_ERR_GETRXQECSTATUS_ARMERRFLAG)); + return MYKONOS_ERR_GETRXQECSTATUS_ARMERRFLAG; + } + + /* read status from ARM memory */ + offset = 0; + retVal = MYKONOS_readArmMem(device, (MYKONOS_ADDR_ARM_START_DATA_ADDR + offset), &armReadBack[0], sizeof(armReadBack), 1); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + /* Assign to data structure */ + rxQecStatus->errorCode = (((uint32_t)armReadBack[3]) << 24) | (((uint32_t)armReadBack[2]) << 16) | (((uint32_t)armReadBack[1]) << 8) | ((uint32_t)armReadBack[0]); + rxQecStatus->percentComplete = (((uint32_t)armReadBack[7]) << 24) | (((uint32_t)armReadBack[6]) << 16) | (((uint32_t)armReadBack[5]) << 8) + | ((uint32_t)armReadBack[4]); + rxQecStatus->selfcheckIrrDb = (((uint32_t)armReadBack[11]) << 24) | (((uint32_t)armReadBack[10]) << 16) | (((uint32_t)armReadBack[9]) << 8) + | ((uint32_t)armReadBack[8]); + rxQecStatus->iterCount = (((uint32_t)armReadBack[15]) << 24) | (((uint32_t)armReadBack[14]) << 16) | (((uint32_t)armReadBack[13]) << 8) | ((uint32_t)armReadBack[12]); + rxQecStatus->updateCount = (((uint32_t)armReadBack[19]) << 24) | (((uint32_t)armReadBack[18]) << 16) | (((uint32_t)armReadBack[17]) << 8) + | ((uint32_t)armReadBack[16]); + + return MYKONOS_ERR_OK; +} + +/** + * \brief Returns the status of the ORxQEC tracking calibration + * + * The ORx QEC tracking calibration is run during the radioOn state. + * The function can be called to read back the status of the ORxQEC external + * calibration including metrics like error codes, percentage of data + * collected for current cal, the performance of the cal and the number of + * times the cal has run and updated the hardware. + * + * \pre Before the function is called, the device must be initialized, the ARM + * loaded, and init cals run. These functions can be called in radioOff or + * radioOn state. + * + * \param device Pointer to the device settings structure + * \param orxChannel The channel whose status is to be read back + * \param orxQecStatus Status of the ORxQEC external calibration, as a structure + * of type mykonosOrxQecStatus_t is returned to this pointer address + * + * \retval MYKONOS_ERR_GETORXQECSTATUS_NULLPARAM Function parameter orxQecStatus is a NULL pointer + * \retval MYKONOS_ERR_GETORXQECSTATUS_INV_CH Channel selection not valid + * \retval MYKONOS_ERR_GETORXQECSTATUS_ARMERRFLAG ARM command error + * \retval MYKONOS_ERR_OK Function completed successfully + */ +mykonosErr_t MYKONOS_getOrxQecStatus(mykonosDevice_t *device, mykonosObsRxChannels_t orxChannel, mykonosOrxQecStatus_t *orxQecStatus) +{ + uint8_t extData[3] = {MYKONOS_ARM_OBJECTID_CAL_STATUS, MYKONOS_ARM_OBJECTID_ORXQEC_TRACKING, 0}; + uint8_t cmdStatusByte = 0; + uint32_t offset = 0; + uint32_t timeoutMs = 0; + uint8_t armReadBack[20] = {0}; + mykonosErr_t retVal = MYKONOS_ERR_OK; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getOrxQecStatus()\n"); +#endif + + if (orxQecStatus == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETORXQECSTATUS_NULLPARAM, + getMykonosErrorMessage(MYKONOS_ERR_GETORXQECSTATUS_NULLPARAM)); + return MYKONOS_ERR_GETORXQECSTATUS_NULLPARAM; + } + + switch (orxChannel) + { + case OBS_RX1_TXLO: + case OBS_RX1_SNIFFERLO: + extData[2] = 0; + break; + case OBS_RX2_TXLO: + case OBS_RX2_SNIFFERLO: + extData[2] = 1; + break; + default: + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETORXQECSTATUS_INV_CH, + getMykonosErrorMessage(MYKONOS_ERR_GETORXQECSTATUS_INV_CH)); + return MYKONOS_ERR_GETORXQECSTATUS_INV_CH; + } + } + + retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_GET_OPCODE, &extData[0], sizeof(extData)); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + timeoutMs = 1000; + retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_GET_OPCODE, timeoutMs, &cmdStatusByte); + if (retVal != MYKONOS_ERR_OK) + { + if (cmdStatusByte > 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETORXQECSTATUS_ARMERRFLAG, + getMykonosErrorMessage(MYKONOS_ERR_GETORXQECSTATUS_ARMERRFLAG)); + return MYKONOS_ERR_GETORXQECSTATUS_ARMERRFLAG; + } + + return retVal; + } + + if (cmdStatusByte > 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETORXQECSTATUS_ARMERRFLAG, + getMykonosErrorMessage(MYKONOS_ERR_GETORXQECSTATUS_ARMERRFLAG)); + return MYKONOS_ERR_GETORXQECSTATUS_ARMERRFLAG; + } + + /* read status from ARM memory */ + offset = 0; + retVal = MYKONOS_readArmMem(device, (MYKONOS_ADDR_ARM_START_DATA_ADDR + offset), &armReadBack[0], sizeof(armReadBack), 1); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + /* Assign to data structure */ + orxQecStatus->errorCode = (((uint32_t)armReadBack[3]) << 24) | (((uint32_t)armReadBack[2]) << 16) | (((uint32_t)armReadBack[1]) << 8) | ((uint32_t)armReadBack[0]); + orxQecStatus->percentComplete = (((uint32_t)armReadBack[7]) << 24) | (((uint32_t)armReadBack[6]) << 16) | (((uint32_t)armReadBack[5]) << 8) + | ((uint32_t)armReadBack[4]); + orxQecStatus->selfcheckIrrDb = (((uint32_t)armReadBack[11]) << 24) | (((uint32_t)armReadBack[10]) << 16) | (((uint32_t)armReadBack[9]) << 8) + | ((uint32_t)armReadBack[8]); + orxQecStatus->iterCount = (((uint32_t)armReadBack[15]) << 24) | (((uint32_t)armReadBack[14]) << 16) | (((uint32_t)armReadBack[13]) << 8) + | ((uint32_t)armReadBack[12]); + orxQecStatus->updateCount = (((uint32_t)armReadBack[19]) << 24) | (((uint32_t)armReadBack[18]) << 16) | (((uint32_t)armReadBack[17]) << 8) + | ((uint32_t)armReadBack[16]); + + return MYKONOS_ERR_OK; +} + +/** + * \brief Selects the Sniffer RF input to use for the observation receiver when in ObsRx pin mode and ORX_MODE = SNIFFER(4) + * + * This function is only valid when using the ObsRx Pin mode. In pin mode, 3 GPIO pins select an Observation Rx source. + * See mykonosObsRxChannels_t enum values less than 7. When the ORX_MODE GPIO pins are set to 4 for Sniffer, Sniffer inputs + * A, B, and C can be chosen by calling this function. This function can be called any time after the ARM is loaded and running. + * It can be called in radioOn or radioOff state. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device Pointer to the device settings structure + * \param snifferChannel Desired channel to set. This channel will be enabled when ORX_MODE = SNIFFER. + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_SET_ARMGPIO_PINS_ARMERROR ARM returned an error + */ +mykonosErr_t MYKONOS_setSnifferChannel(mykonosDevice_t *device, mykonosSnifferChannel_t snifferChannel) +{ + uint8_t armData[2] = {0}; + uint32_t timeoutMs = 0; + uint8_t cmdStatusByte = 0; + mykonosErr_t retVal = MYKONOS_ERR_OK; + + armData[0] = 0x6A; /* SET SRX_SOURCE ARM object ID */ + armData[1] = (uint8_t)snifferChannel; + + retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_SET_OPCODE, &armData[0], sizeof(armData)); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + timeoutMs = 1000; + retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_SET_OPCODE, timeoutMs, &cmdStatusByte); + if (retVal != MYKONOS_ERR_OK) + { + if (cmdStatusByte > 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SET_ARMGPIO_PINS_ARMERROR, + getGpioMykonosErrorMessage(MYKONOS_ERR_SET_ARMGPIO_PINS_ARMERROR)); + retVal = (mykonosErr_t)MYKONOS_ERR_SET_ARMGPIO_PINS_ARMERROR; + } + + return retVal; + } + + if (cmdStatusByte > 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SET_ARMGPIO_PINS_ARMERROR, + getGpioMykonosErrorMessage(MYKONOS_ERR_SET_ARMGPIO_PINS_ARMERROR)); + return (mykonosErr_t)MYKONOS_ERR_SET_ARMGPIO_PINS_ARMERROR; + } + + return MYKONOS_ERR_OK; +} + +/** + * \brief Resets the ARM processor and performs initialization + * + * Sets ARM Run = 0, Disables parity checks, sets ARM and SPI reg clock selects, + * resets ARM, and enables ARM SPI register access + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * - device->rx->rxProfile->iqRate_kHz + * - device->deviceClock_kHz + * - device->rx->rxProfile->rfBandwidth_Hz + * - device->tx->txProfile->rfBandwidth_Hz + * - device->rx->rxProfile->rxFirDecimation + * - device->rx->rxProfile->rhb1Decimation + * - device->spiSettings + * + * \param device Pointer to the device settings structure + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_INITARM_INV_VCODIV + * \retval MYKONOS_ERR_INITARM_INV_REGCLK Could not calculate a valid ARM Register clock divider + * \retval MYKONOS_ERR_INITARM_INV_ARMCLK_PARAM Could not calculate a valid ARM clock divider + */ +mykonosErr_t MYKONOS_initArm(mykonosDevice_t *device) +{ + uint8_t regClkSel = 0; + uint8_t armClkSel = 0; + uint32_t hsClkRateDiv4or5_Khz = 0; + uint32_t hb1Clk = 0; + uint32_t vcoDivTimes10 = 1; + uint8_t adcDiv = 0; + mykonosErr_t retVal = MYKONOS_ERR_OK; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_initArm()\n"); +#endif + + /* Finish init - this is part of init that must run after Multi Chip Sync */ + retVal = MYKONOS_initSubRegisterTables(device); + if (retVal != MYKONOS_ERR_OK) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, retVal, getMykonosErrorMessage(retVal)); + return retVal; + } + + switch (device->clocks->clkPllVcoDiv) + { + case VCODIV_1: + vcoDivTimes10 = 10; + break; + case VCODIV_1p5: + vcoDivTimes10 = 15; + break; + case VCODIV_2: + vcoDivTimes10 = 20; + break; + case VCODIV_3: + vcoDivTimes10 = 30; + break; + default: + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INITARM_INV_VCODIV, + getMykonosErrorMessage(MYKONOS_ERR_INITARM_INV_VCODIV)); + return MYKONOS_ERR_INITARM_INV_VCODIV; + } + } + + hsClkRateDiv4or5_Khz = device->clocks->clkPllVcoFreq_kHz * 10 / vcoDivTimes10 / 20; + + /* If ADC divider is set, divide hsClkRateDiv4or5_kHz by 2 (ADC divider) */ + CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_CLOCK_CONTROL_1, &adcDiv, 0x01, 0); + hb1Clk = (adcDiv == 1) ? (hsClkRateDiv4or5_Khz >> 1) : (hsClkRateDiv4or5_Khz); + + /* the ARM clock should not exceed 250 Mhz */ + if (hb1Clk <= 250000) + { + armClkSel = 0x00; + } + else if (hb1Clk > 250000 && hb1Clk <= 500000) + { + armClkSel = 0x02; + } + else if (hb1Clk > 500000 && hb1Clk <= 1000000) + { + armClkSel = 0x04; + } + else + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INITARM_INV_ARMCLK_PARAM, + getMykonosErrorMessage(MYKONOS_ERR_INITARM_INV_ARMCLK_PARAM)); + return MYKONOS_ERR_INITARM_INV_ARMCLK_PARAM; + } + + /* the SPI read reg clock must be equal or less than 100MHz and the SPI write reg clock must be less equal or less than 200 Mhz*/ + if (hb1Clk <= 100000) + { + regClkSel = 0x00; + } + else if (hb1Clk > 100000 && hb1Clk <= 200000) + { + regClkSel = 0x04; + } + else if (hb1Clk > 200000 && hb1Clk <= 400000) + { + regClkSel = 0x09; + } + else if (hb1Clk > 400000 && hb1Clk <= 800000) + { + regClkSel = 0x0E; + } + else + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INITARM_INV_REGCLK, getMykonosErrorMessage(MYKONOS_ERR_INITARM_INV_REGCLK)); + return MYKONOS_ERR_INITARM_INV_REGCLK; + } + + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_CTL_1, 0x8C); /* arm_debug_enable[7]=1, mem_hresp_mask[3]=1, auto_incr[2]=1, arm_m3_run[0]=0 */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_CLK_CTL, armClkSel |= 0x41); /* setting the ARM clock rate, resetting the PC, and enabling the ARM clock */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_CLK_CTL, armClkSel &= ~0x40); /* maintaining the ARM clock rate, disabling the PC reset, and maintaining ARM clock enable */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_BRIDGE_CLK_CTL, regClkSel); /* setting the SPI read and write clock rates */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AHB_SPI_BRIDGE, 0x13); /* blockout_window_size[4:1] = 9, ahb_spi_bridge_enable[0] = 1 */ + + retVal = MYKONOS_writeArmProfile(device); + if (retVal != MYKONOS_ERR_OK) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, retVal, getMykonosErrorMessage(retVal)); + return retVal; + } + + retVal = MYKONOS_loadAdcProfiles(device); + if (retVal != MYKONOS_ERR_OK) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, retVal, getMykonosErrorMessage(retVal)); + return retVal; + } + + return MYKONOS_ERR_OK; +} + +/** + * \brief Loads binary byte array into ARM program memory + * + * This function assumes the ARM auto increment bit is set in 0x0D00[2]. Valid memory + * addresses are: Program Memory (0x01000000 - 0x01017FFF) + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * - device->spiSettings + * + * \param device is structure pointer to the Mykonos data structure containing settings + * \param binary is a byte array containing ARM program memory data bytes (directly from .bin file) + * \param count is the number of bytes in the byte array + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_LOADBIN_NULL_PARAM Function parameter binary has a NULL pointer + * \retval MYKONOS_ERR_LOADBIN_INVALID_BYTECOUNT Count parameter must be 98304 bytes + */ +mykonosErr_t MYKONOS_loadArmFromBinary(mykonosDevice_t *device, uint8_t *binary, uint32_t count) +{ + mykonosErr_t retVal = MYKONOS_ERR_OK; + uint8_t stackPtr[4] = {0}; + uint8_t bootAddr[4] = {0}; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_loadArmFromBinary()\n"); +#endif + + if (binary == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_LOADBIN_NULL_PARAM, getMykonosErrorMessage(MYKONOS_ERR_LOADBIN_NULL_PARAM)); + return MYKONOS_ERR_LOADBIN_NULL_PARAM; + } + + if (count != 98304) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_LOADBIN_INVALID_BYTECOUNT, + getMykonosErrorMessage(MYKONOS_ERR_LOADBIN_INVALID_BYTECOUNT)); + return MYKONOS_ERR_LOADBIN_INVALID_BYTECOUNT; + } + else + { + /* extraction of stack pointer and boot address from top of array */ + stackPtr[0] = binary[0]; + stackPtr[1] = binary[1]; + stackPtr[2] = binary[2]; + stackPtr[3] = binary[3]; + + bootAddr[0] = binary[4]; + bootAddr[1] = binary[5]; + bootAddr[2] = binary[6]; + bootAddr[3] = binary[7]; + + /* writing binary data to ARM memory */ + retVal = MYKONOS_writeArmMem(device, MYKONOS_ADDR_ARM_START_PROG_ADDR, &binary[0], count); + } + + if (retVal != MYKONOS_ERR_OK) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, retVal, getMykonosErrorMessage(retVal)); + return retVal; + } + else + { + /* writing the stack pointer address */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_STACK_PTR_BYTE_0, stackPtr[0]); /* stack pointer [7:0] */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_STACK_PTR_BYTE_1, stackPtr[1]); /* stack pointer [15:8] */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_STACK_PTR_BYTE_2, stackPtr[2]); /* stack pointer [23:16] */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_STACK_PTR_BYTE_3, stackPtr[3]); /* stack pointer [31:24] */ + + /* writing the boot address */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_BOOT_ADDR_BYTE_0, bootAddr[0]); /* boot address [7:0] */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_BOOT_ADDR_BYTE_1, bootAddr[1]); /* boot address [15:8] */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_BOOT_ADDR_BYTE_2, bootAddr[2]); /* boot address [23:16] */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_BOOT_ADDR_BYTE_3, bootAddr[3]); /* boot address [31:24] */ + + /* setting the ARM run bit */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_CTL_1, 0x8D); /* arm_debug_enable[7]=1, mem_hresp_mask[3]=1, auto_incr[2]=1, arm_m3_run[0]=1 */ + } + + /* verifying ARM checksum */ + if ((retVal = MYKONOS_verifyArmChecksum(device)) != MYKONOS_ERR_OK) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, retVal, getMykonosErrorMessage(retVal)); + return retVal; + } + + /* verifying ARM state is in MYKONOS_ARM_READY state, otherwise return error */ + if ((retVal = MYKONOS_checkArmState(device, MYK_ARM_READY)) != MYKONOS_ERR_OK) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, retVal, getMykonosErrorMessage(retVal)); + return retVal; + } + + /* Setup ARM GPIO pins and program ARMs radio control structure */ + if ((retVal = (mykonosErr_t)MYKONOS_setArmGpioPins(device)) != MYKONOS_ERR_OK) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, retVal, getMykonosErrorMessage(retVal)); + return retVal; + } + + if ((retVal = MYKONOS_setRadioControlPinMode(device)) != MYKONOS_ERR_OK) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, retVal, getMykonosErrorMessage(retVal)); + return retVal; + } + + /* Set the default ObsRx Path source for when the device moves to RadioOn */ + if ((retVal = MYKONOS_setDefaultObsRxPath(device, device->obsRx->defaultObsRxChannel)) != MYKONOS_ERR_OK) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, retVal, getMykonosErrorMessage(retVal)); + return retVal; + } + + return MYKONOS_ERR_OK; +} + +/** + * \brief Loads binary byte array into ARM program memory. This API function allows user to load the ARM concurrently. + * This is specially to reduce the system initialization time. + * + * \pre MYKONOS_initArm() function must be called before calling this API. + * + * \post after calling this function the user must verify: + * Arm Checksum using MYKONOS_verifyArmChecksum(mykonosDevice_t *device) + * verify ARM state is in MYKONOS_ARM_READY state using MYKONOS_checkArmState(device, MYK_ARM_READY); + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * - device->spiSettings + * + * \param device is structure pointer to the Mykonos data structure containing settings + * \param binary is a byte array containing ARM program memory data bytes (directly from .bin file) + * \param count is the number of bytes in the byte array + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_LOADARMCON_NULL_PARAM Function parameter binary has a NULL pointer + * \retval MYKONOS_ERR_LOADARMCON_INVALID_BYTECOUNT Count parameter must be 98304 bytes + * \retval MYKONOS_ERR_ARM_INV_ADDR_PARM Invalid memory address + */ +mykonosErr_t MYKONOS_loadArmConcurrent(mykonosDevice_t *device, uint8_t *binary, uint32_t count) +{ + uint8_t stackPtr[4] = {0}; + uint8_t bootAddr[4] = {0}; + uint32_t i; + uint32_t address = MYKONOS_ADDR_ARM_START_PROG_ADDR; + +#if MYK_ENABLE_SPIWRITEARRAY == 1 + uint32_t addrIndex = 0; + uint32_t dataIndex = 0; + uint32_t spiBufferSize = MYK_SPIWRITEARRAY_BUFFERSIZE; + uint16_t addrArray[MYK_SPIWRITEARRAY_BUFFERSIZE] = {0}; +#endif + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_loadArmConcurrent()\n"); +#endif + + if (binary == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_LOADARMCON_NULL_PARAM, getMykonosErrorMessage(MYKONOS_ERR_LOADARMCON_NULL_PARAM)); + return MYKONOS_ERR_LOADARMCON_NULL_PARAM; + } + + if (count != 98304) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_LOADARMCON_INVALID_BYTECOUNT, + getMykonosErrorMessage(MYKONOS_ERR_LOADARMCON_INVALID_BYTECOUNT)); + return MYKONOS_ERR_LOADARMCON_INVALID_BYTECOUNT; + } + else + { + /* extraction of stack pointer and boot address from top of array */ + stackPtr[0] = binary[0]; + stackPtr[1] = binary[1]; + stackPtr[2] = binary[2]; + stackPtr[3] = binary[3]; + + bootAddr[0] = binary[4]; + bootAddr[1] = binary[5]; + bootAddr[2] = binary[6]; + bootAddr[3] = binary[7]; + + /* set auto increment address bit */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_CTL_1, 0x8C); + + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_ADDR_BYTE_0, (uint8_t)((address) >> 2)); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_ADDR_BYTE_1, (uint8_t)(address >> 10)); + + /* start write at correct byte offset */ + /* write data is located at SPI address 0xD04=data[7:0], 0xD05=data[15:8], 0xD06=data[23:16], 0xD07=data[31:24] */ + /* with address auto increment set, after x407 is written, the address will automatically increment */ + +#if (MYK_ENABLE_SPIWRITEARRAY == 0) + + for (i = 0; i < byteCount; i++) + { + CMB_SPIWriteByte(device->spiSettings, (MYKONOS_ADDR_ARM_DATA_BYTE_0 | (((address & 0x3) + i) % 4)), data[i]); + } + +#elif (MYK_ENABLE_SPIWRITEARRAY == 1) + + addrIndex = 0; + dataIndex = 0; + for (i = 0; i < count; i++) + { + addrArray[addrIndex++] = (MYKONOS_ADDR_ARM_DATA_BYTE_0 | (((address & 0x3) + i) % 4)); + + if (addrIndex == spiBufferSize) + { + CMB_SPIWriteBytes(device->spiSettings, &addrArray[0], &binary[dataIndex], addrIndex); + dataIndex = dataIndex + addrIndex; + addrIndex = 0; + } + } + + if (addrIndex > 0) + { + CMB_SPIWriteBytes(device->spiSettings, &addrArray[0], &binary[dataIndex], addrIndex); + } + +#endif + + /* writing the stack pointer address */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_STACK_PTR_BYTE_0, stackPtr[0]); /* stack pointer [7:0] */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_STACK_PTR_BYTE_1, stackPtr[1]); /* stack pointer [15:8] */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_STACK_PTR_BYTE_2, stackPtr[2]); /* stack pointer [23:16] */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_STACK_PTR_BYTE_3, stackPtr[3]); /* stack pointer [31:24] */ + + /* writing the boot address */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_BOOT_ADDR_BYTE_0, bootAddr[0]); /* boot address [7:0] */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_BOOT_ADDR_BYTE_1, bootAddr[1]); /* boot address [15:8] */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_BOOT_ADDR_BYTE_2, bootAddr[2]); /* boot address [23:16] */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_BOOT_ADDR_BYTE_3, bootAddr[3]); /* boot address [31:24] */ + + /* setting the ARM run bit */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_CTL_1, 0x8D); + + } + + return MYKONOS_ERR_OK; +} + +/** + * \brief Verifies the ARM checksum value + * + * The checksum which is written into the .hex file is verified with the calculated checksum + * in the Mykonos ARM after the hex file has been loaded + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device is structure pointer to the Mykonos data structure containing settings + * + * \retval MYKONOS_ERR_OK Function completed successfully + */ +mykonosErr_t MYKONOS_verifyArmChecksum(mykonosDevice_t *device) +{ + uint32_t buildTimeChecksum = 0x00000000; + uint32_t calculatedChecksum = 0x00000000; + uint8_t buildData[4] = {0}; + uint8_t calcData[4] = {0}; + mykonosErr_t retVal = MYKONOS_ERR_OK; + + const uint8_t CHECKSUM_BYTES = 0x4; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_verifyArmChecksum()\n"); +#endif + + /* disabling auto increment and reading four (4) bytes at ARM checksum memory location */ + retVal = MYKONOS_readArmMem(device, MYKONOS_ADDR_ARM_BUILD_CHKSUM_ADDR, buildData, CHECKSUM_BYTES, 0); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + /* determining build time checksum */ + buildTimeChecksum = (((uint32_t)buildData[3] << 24) | ((uint32_t)buildData[2] << 16) | ((uint32_t)buildData[1] << 8) | (uint32_t)buildData[0]); + + /* using 200 msec timeout for exit out of while loop [maximum checksum calculation time = 5 ms] */ + CMB_setTimeout_ms(200); + + /* determining calculated checksum */ + do + { + if ((retVal = MYKONOS_readArmMem(device, MYKONOS_ADDR_ARM_CALC_CHKSUM_ADDR, calcData, CHECKSUM_BYTES, 0)) != MYKONOS_ERR_OK) + { + return retVal; + } + calculatedChecksum = (((uint32_t)calcData[3] << 24) | ((uint32_t)calcData[2] << 16) | ((uint32_t)calcData[1] << 8) | (uint32_t)calcData[0]); + } while ((!calculatedChecksum) && (!CMB_hasTimeoutExpired())); + + /* performing consistency check */ + if (buildTimeChecksum == calculatedChecksum) + { + return MYKONOS_ERR_OK; + } + else + { + return MYKONOS_ERR_ARM_INVALID_BUILDCHKSUM; + } +} + +/** + * \brief Verifies the ARM status once it is start running + * + * Wait for ARM to go into radio state, if takes longer there is and ARM error + * get error in Application layer calling MYKONOS_getRadioState() + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device is structure pointer to the Mykonos data structure containing settings + * \param armStateCheck if the ARM is not in this state it will return an error, + * + * \retval MYKONOS_ERR_ARMSTATE_EXCEPTION ARM system problem has been detected. + * \retval MYKONOS_ERR_ARMSTATE_CAL_ERROR ARM has detected an error in the tracking calibrations. + * \retval MYKONOS_ERR_ARMSTATE_EXCEPTION ARM has detected an illegal profile. + * \retval MYKONOS_ERR_WAITARMCSTATE_TIMEOUT Timeout occurred in check ARM state. + * \retval MYKONOS_ERR_OK Function completed successfully + */ +mykonosErr_t MYKONOS_checkArmState(mykonosDevice_t *device, mykonosArmState_t armStateCheck) +{ + mykonosErr_t retVal = MYKONOS_ERR_OK; + uint32_t armStatus = 0x00; + uint32_t armStatusMapped = 0x00; + uint32_t timeoutMs = 500; /* 500ms timeOut */ + uint8_t endCheck = 0x00; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_checkArmState()\n"); +#endif + + CMB_setTimeout_ms(timeoutMs); + + do + { + if ((retVal = MYKONOS_getRadioState(device, &armStatus)) != MYKONOS_ERR_OK) + { + return retVal; + } + + /* Mapping of the armStatus bit to the enum value. */ + switch(armStatus) + { + case 0: + armStatusMapped = (uint32_t)MYK_ARM_POWERUP; + break; + case 1: + armStatusMapped = (uint32_t)MYK_ARM_READY; + break; + case 2: + armStatusMapped = (uint32_t)MYK_ARM_IDLE; + break; + case 3: + armStatusMapped = (uint32_t)MYK_ARM_RADIO_ON; + break; + case 4: + armStatusMapped = (uint32_t)MYK_ARM_PROFILE_ERROR; + break; + default: + armStatusMapped = armStatus; + break; + } + + if (armStateCheck && armStatusMapped) + { + retVal = MYKONOS_ERR_OK; + break; + } + + if (CMB_hasTimeoutExpired()) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_WAITARMCSTATE_TIMEOUT, + getMykonosErrorMessage(MYKONOS_ERR_WAITARMCSTATE_TIMEOUT)); + retVal = MYKONOS_ERR_WAITARMCSTATE_TIMEOUT; + break; + } + + switch (armStatusMapped) + { + /* this cases are not ARM errors */ + case MYK_ARM_POWERUP: + case MYK_ARM_READY: + case MYK_ARM_IDLE: + case MYK_ARM_RADIO_ON: + break; + + case MYK_ARM_PROFILE_ERROR: + /* return error directly */ + retVal = MYKONOS_ERR_ARMSTATE_PROFILE_ERROR; + endCheck = 1; + break; + + case MYK_ARM_CAL_ERROR: + /* return error directly */ + retVal = MYKONOS_ERR_ARMSTATE_CAL_ERROR; + endCheck = 1; + break; + + case MYK_ARM_EXCEPTION: + /* return error directly */ + retVal = MYKONOS_ERR_ARMSTATE_EXCEPTION; + endCheck = 1; + break; + + case (uint32_t)MYK_ARM_EXCEPTION | (uint32_t)MYK_ARM_PROFILE_ERROR: + /* return error directly */ + retVal = MYKONOS_ERR_ARMSTATE_EXCEPTION; + endCheck = 1; + break; + + default: + endCheck = 0; + break; + } + + } while (!endCheck); + + return retVal; +} + +/** + * \brief Reads back the version of the ARM binary loaded into the Mykonos ARM memory + * + * This function reads the ARM memory to read back the major.minor.releaseCandidate + * version for the ARM binary loaded into ARM memory. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device is structure pointer to the Mykonos data structure containing settings + * \param majorVer The Major version is returned in this parameter + * \param minorVer The Minor version is returned in this parameter + * \param rcVer The release candidate version (build number) is returned in this parameter + * \param buildType The Type of the build [Debug / Test_Object / Release] + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_GETARMVER_NULL_PARM One of the function parameters has a NULL pointer + */ +mykonosErr_t MYKONOS_getArmVersion(mykonosDevice_t *device, uint8_t *majorVer, uint8_t *minorVer, uint8_t *rcVer, mykonosBuild_t *buildType) +{ + mykonosErr_t retVal = MYKONOS_ERR_OK; + uint8_t ver[5] = {0}; + uint32_t fullVersion = 0; + uint8_t validBuilds = 0x05; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getArmVersion()\n"); +#endif + + if ((majorVer == NULL) || (minorVer == NULL) || (rcVer == NULL)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETARMVER_NULL_PARM, getMykonosErrorMessage(MYKONOS_ERR_GETARMVER_NULL_PARM)); + return MYKONOS_ERR_GETARMVER_NULL_PARM; + } + + retVal = MYKONOS_readArmMem(device, MYKONOS_ADDR_ARM_VERSION, &ver[0], sizeof(ver), 1); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + fullVersion = ((uint32_t)(ver[0]) | (uint32_t)((uint32_t)(ver[1]) << 8) | (uint32_t)((uint32_t)(ver[2]) << 16) | (uint32_t)((uint32_t)(ver[3]) << 24)); + *rcVer = (uint8_t)(fullVersion % 100); + *minorVer = (uint8_t)((fullVersion / 100) % 100); + *majorVer = (uint8_t)(fullVersion / 10000); + + switch (ver[4] & validBuilds) + { + case MYK_BUILD_DEBUG: + *buildType = MYK_BUILD_DEBUG; + break; + case MYK_BUILD_TEST_OBJECT: + *buildType = MYK_BUILD_TEST_OBJECT; + break; + default: + *buildType = MYK_BUILD_RELEASE; + break; + } + + return MYKONOS_ERR_OK; +} + +/** + * \brief This function will configure DPD settings + * + * A DPD-enabled transceiver is required for DPD to be enabled. The DPD has several user + * adjustable settings that can be configured before running the runInitCals + * with the calMask set for the DPD init cal. Call this function with desired + * settings set before running the DPD init cal or enabling DPD tracking. + * + * This function can be called in either Radio On or Off state. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * - device->profilesValid + * - device->tx->dpdConfig (All members) + * + * + * \retval MYKONOS_ERR_CFGDPD_TXORX_PROFILE_INV ERROR: to use these features, a valid Tx and ORx profile must exist in the device data structure + * \retval MYKONOS_ERR_CFGDPD_NULL_DPDCFGSTRUCT ERROR: device->tx->dpdConfig is a NULL pointer + * \retval MYKONOS_ERR_CFGDPD_INV_DPDDAMPING ERROR: damping parameter is out of range + * \retval MYKONOS_ERR_CFGDPD_INV_DPDSAMPLES ERROR: samples parameter is out of range + * \retval MYKONOS_ERR_CFGDPD_INV_NUMWEIGHTS ERROR: numWeights parameter is out of range (0-3) + * \retval MYKONOS_ERR_CFGDPD_INV_MODELVERSION ERROR: modelVersion parameter is out of range (0-3) + * \retval MYKONOS_ERR_CFGDPD_INV_DPDOUTLIERTHRESH ERROR: outlierThreshold parameter is out of range + * \retval MYKONOS_ERR_CFGDPD_INV_DPD_ADDDELAY ERROR: additionalDelayOffset parameter is out of range + * \retval MYKONOS_ERR_CFGDPD_INV_PNSEQLEVEL ERROR: pathDelayPnSeqLevel parameter is out of range + * \retval MYKONOS_ERR_OK Function completed successfully + */ +mykonosErr_t MYKONOS_configDpd(mykonosDevice_t *device) +{ + mykonosErr_t retVal = MYKONOS_ERR_OK; + uint8_t armFieldValue[6] = {0}; + uint8_t byteOffset = 0; + uint16_t negPnLevel = 0; + uint8_t highPowerModelUpdate = 0; + uint8_t robustModeling = 0; + uint32_t radioStatus = 0; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_configDpd()\n"); +#endif + + /* DPD requires Tx and ORx enabled, throw error if both are not enabled */ + if ((device->profilesValid & (TX_PROFILE_VALID | ORX_PROFILE_VALID)) != (TX_PROFILE_VALID | ORX_PROFILE_VALID)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGDPD_TXORX_PROFILE_INV, + getMykonosErrorMessage(MYKONOS_ERR_CFGDPD_TXORX_PROFILE_INV)); + return MYKONOS_ERR_CFGDPD_TXORX_PROFILE_INV; + } + + if (device->tx->dpdConfig == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGDPD_NULL_DPDCFGSTRUCT, + getMykonosErrorMessage(MYKONOS_ERR_CFGDPD_NULL_DPDCFGSTRUCT)); + return MYKONOS_ERR_CFGDPD_NULL_DPDCFGSTRUCT; + } + + /* check DPD damping and samples parameters */ + if (device->tx->dpdConfig->damping > 15) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGDPD_INV_DPDDAMPING, + getMykonosErrorMessage(MYKONOS_ERR_CFGDPD_INV_DPDDAMPING)); + return MYKONOS_ERR_CFGDPD_INV_DPDDAMPING; + } + + if ((device->tx->dpdConfig->samples < 64) || (device->tx->dpdConfig->samples > 32768)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGDPD_INV_DPDSAMPLES, + getMykonosErrorMessage(MYKONOS_ERR_CFGDPD_INV_DPDSAMPLES)); + return MYKONOS_ERR_CFGDPD_INV_DPDSAMPLES; + } + + if (device->tx->dpdConfig->numWeights > 3) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGDPD_INV_NUMWEIGHTS, + getMykonosErrorMessage(MYKONOS_ERR_CFGDPD_INV_NUMWEIGHTS)); + return MYKONOS_ERR_CFGDPD_INV_NUMWEIGHTS; + } + + if (device->tx->dpdConfig->modelVersion > 3) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGDPD_INV_MODELVERSION, + getMykonosErrorMessage(MYKONOS_ERR_CFGDPD_INV_MODELVERSION)); + return MYKONOS_ERR_CFGDPD_INV_MODELVERSION; + } + + highPowerModelUpdate = (device->tx->dpdConfig->highPowerModelUpdate > 0) ? 1 : 0; + robustModeling = (device->tx->dpdConfig->robustModeling > 0) ? 1 : 0; + + armFieldValue[0] = (uint8_t)(((device->tx->dpdConfig->numWeights & 3) << 4) | (device->tx->dpdConfig->damping & 0xF)); + armFieldValue[1] = (uint8_t)((robustModeling << 3) | (highPowerModelUpdate << 2) | (device->tx->dpdConfig->modelVersion & 3)); + armFieldValue[2] = (device->tx->dpdConfig->samples & 0xFF); + armFieldValue[3] = ((device->tx->dpdConfig->samples >> 8) & 0xFF); + byteOffset = 0; + retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_DPDCONFIG, byteOffset, &armFieldValue[0], 4); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + /* set DPD outlier threshold parameter */ + if ((device->tx->dpdConfig->outlierThreshold < 1) || (device->tx->dpdConfig->outlierThreshold > 8192)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGDPD_INV_DPDOUTLIERTHRESH, + getMykonosErrorMessage(MYKONOS_ERR_CFGDPD_INV_DPDOUTLIERTHRESH)); + return MYKONOS_ERR_CFGDPD_INV_DPDOUTLIERTHRESH; + } + + armFieldValue[0] = (device->tx->dpdConfig->outlierThreshold & 0xFF); + armFieldValue[1] = ((device->tx->dpdConfig->outlierThreshold >> 8) & 0xFF); + byteOffset = 10; + retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_DPDCONFIG, byteOffset, &armFieldValue[0], 2); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + /* set DPD Model Prior Weight parameter */ + if (device->tx->dpdConfig->modelPriorWeight > 32) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGDPD_INV_DPDPRIORWEIGHT, + getMykonosErrorMessage(MYKONOS_ERR_CFGDPD_INV_DPDPRIORWEIGHT)); + return MYKONOS_ERR_CFGDPD_INV_DPDPRIORWEIGHT; + } + armFieldValue[0] = (device->tx->dpdConfig->modelPriorWeight & 0xFF); + armFieldValue[1] = 0; + byteOffset = 12; + retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_DPDCONFIG, byteOffset, &armFieldValue[0], 2); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + /* no need to verify weights min/max as all int8 values are valid */ + armFieldValue[0] = (uint8_t)(device->tx->dpdConfig->weights[0].real); + armFieldValue[1] = (uint8_t)(device->tx->dpdConfig->weights[0].imag); + armFieldValue[2] = (uint8_t)(device->tx->dpdConfig->weights[1].real); + armFieldValue[3] = (uint8_t)(device->tx->dpdConfig->weights[1].imag); + armFieldValue[4] = (uint8_t)(device->tx->dpdConfig->weights[2].real); + armFieldValue[5] = (uint8_t)(device->tx->dpdConfig->weights[2].imag); + + byteOffset = 14; + retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_DPDCONFIG, byteOffset, &armFieldValue[0], 6); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + /* set DPD additional delay offset parameter */ + if ((device->tx->dpdConfig->additionalDelayOffset < -64) || (device->tx->dpdConfig->additionalDelayOffset > 64)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGDPD_INV_DPD_ADDDELAY, + getMykonosErrorMessage(MYKONOS_ERR_CFGDPD_INV_DPD_ADDDELAY)); + return MYKONOS_ERR_CFGDPD_INV_DPD_ADDDELAY; + } + + /* read radio state to make sure ARM is in radioOff /IDLE */ + retVal = MYKONOS_getRadioState(device, &radioStatus); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + /* Radio state check */ + if (((radioStatus & 0x03) == MYKONOS_ARM_SYSTEMSTATE_IDLE) || ((radioStatus & 0x03) == MYKONOS_ARM_SYSTEMSTATE_READY)) + { + armFieldValue[0] = (uint8_t)(device->tx->dpdConfig->additionalDelayOffset & 0xFF); + armFieldValue[1] = (uint8_t)(((uint16_t)device->tx->dpdConfig->additionalDelayOffset >> 8) & 0xFF); + byteOffset = 2; + retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_DPDINIT_CONFIG, byteOffset, &armFieldValue[0], 2); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + if ((device->tx->dpdConfig->pathDelayPnSeqLevel < 1) || (device->tx->dpdConfig->pathDelayPnSeqLevel > 8191)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGDPD_INV_PNSEQLEVEL, + getMykonosErrorMessage(MYKONOS_ERR_CFGDPD_INV_PNSEQLEVEL)); + return MYKONOS_ERR_CFGDPD_INV_PNSEQLEVEL; + } + + /* Set Path Delay PN sequence amplitude - positive and negative */ + armFieldValue[0] = (uint8_t)(device->tx->dpdConfig->pathDelayPnSeqLevel & 0xFF); + armFieldValue[1] = (uint8_t)((device->tx->dpdConfig->pathDelayPnSeqLevel >> 8) & 0xFF); + + negPnLevel = ((~device->tx->dpdConfig->pathDelayPnSeqLevel) + 1); /* times -1 */ + armFieldValue[2] = (uint8_t)(negPnLevel & 0xFF); + armFieldValue[3] = (uint8_t)(((negPnLevel) >> 8) & 0xFF); + byteOffset = 10; + retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_DPDINIT_CONFIG, byteOffset, &armFieldValue[0], 4); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + } + else + { + /* record warning about not updated members */ + CMB_writeToLog(ADIHAL_LOG_WARNING, device->spiSettings->chipSelectIndex, MYKONOS_WRN_RADIO_ON_NOT_MODIFIABLE, + getMykonosErrorMessage(MYKONOS_WRN_RADIO_ON_NOT_MODIFIABLE)); + } + + return MYKONOS_ERR_OK; +} + +/* \brief Reads the DPD config structure from ARM memory + * + * This function reads the DPD structure + * from ARM memory and returns in the device->tx->dpdConfig structure. + * + * A DPD-enabled transceiver is required for DPD to be enabled. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * - device->profilesValid + * - device->tx->dpdConfig (All members) + * + * \param device is structure pointer to the Mykonos data structure containing settings + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_GETDPDCFG_TXORX_PROFILE_INV Error: Tx and ORx profiles must be valid for DPD functions + * \retval MYKONOS_ERR_GETDPDCFG_NULL_DPDCFGSTRUCT Error: NULL pointer to device->tx->dpdConfig structure + */ +mykonosErr_t MYKONOS_getDpdConfig(mykonosDevice_t *device) +{ + uint16_t byteOffset = 0; + uint8_t armMem[20] = {0}; + mykonosErr_t retVal = MYKONOS_ERR_OK; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getDpdConfig()\n"); +#endif + + /* DPD requires Tx and ORx enabled, throw error if both are not enabled */ + if ((device->profilesValid & (TX_PROFILE_VALID | ORX_PROFILE_VALID)) != (TX_PROFILE_VALID | ORX_PROFILE_VALID)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETDPDCFG_TXORX_PROFILE_INV, + getMykonosErrorMessage(MYKONOS_ERR_GETDPDCFG_TXORX_PROFILE_INV)); + return MYKONOS_ERR_GETDPDCFG_TXORX_PROFILE_INV; + } + + if (device->tx->dpdConfig == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETDPDCFG_NULL_DPDCFGSTRUCT, + getMykonosErrorMessage(MYKONOS_ERR_GETDPDCFG_NULL_DPDCFGSTRUCT)); + return MYKONOS_ERR_GETDPDCFG_NULL_DPDCFGSTRUCT; + } + + byteOffset = 0; + retVal = MYKONOS_readArmConfig(device, MYKONOS_ARM_OBJECTID_DPDCONFIG, byteOffset, &armMem[0], 20); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + device->tx->dpdConfig->damping = (armMem[0] & 0x0F); + device->tx->dpdConfig->numWeights = ((armMem[0] >> 4) & 0x03); + + device->tx->dpdConfig->modelVersion = (armMem[1] & 0x03); + device->tx->dpdConfig->highPowerModelUpdate = ((armMem[1] >> 2) & 0x01); + device->tx->dpdConfig->robustModeling = 0; + device->tx->dpdConfig->samples = ((uint16_t)(armMem[3]) << 8) | (uint16_t)(armMem[2]); + + device->tx->dpdConfig->outlierThreshold = ((uint16_t)(armMem[11]) << 8) | (uint16_t)(armMem[10]); + device->tx->dpdConfig->modelPriorWeight = armMem[12]; + device->tx->dpdConfig->weights[0].real = (int8_t)(armMem[14]); + device->tx->dpdConfig->weights[0].imag = (int8_t)(armMem[15]); + device->tx->dpdConfig->weights[1].real = (int8_t)(armMem[16]); + device->tx->dpdConfig->weights[1].imag = (int8_t)(armMem[17]); + device->tx->dpdConfig->weights[2].real = (int8_t)(armMem[18]); + device->tx->dpdConfig->weights[2].imag = (int8_t)(armMem[19]); + + byteOffset = 2; + retVal = MYKONOS_readArmConfig(device, MYKONOS_ARM_OBJECTID_DPDINIT_CONFIG, byteOffset, &armMem[0], 2); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + device->tx->dpdConfig->additionalDelayOffset = (int16_t)(((uint16_t)(armMem[1]) << 8) | (uint16_t)(armMem[0])); + + byteOffset = 10; + retVal = MYKONOS_readArmConfig(device, MYKONOS_ARM_OBJECTID_DPDINIT_CONFIG, byteOffset, &armMem[0], 2); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + device->tx->dpdConfig->pathDelayPnSeqLevel = (((uint16_t)(armMem[1]) << 8) | (uint16_t)(armMem[0])); + + return MYKONOS_ERR_OK; +} + +/** + * \brief This function reads the DPD calibration status from the Mykonos ARM processor. + * + * The dpdStatus is read back from the ARM processor and returned in the function + * parameter dpdStatus. + * + * A DPD-enabled transceiver is required for this feature to be enabled. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device is structure pointer to the Mykonos data structure containing settings + * \param txChannel Desired Transmit channel to read back DPD status for (Valid ENUM values: TX1 or TX2 only) + * \param dpdStatus Pointer to a structure to return the status information to + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_GETDPDSTATUS_NULLPARAM dpdStatus function parameter is a NULL pointer + * \retval MYKONOS_ERR_GETDPDSTATUS_INV_CH txChannel parameter is a non-supported value. + * \retval MYKONOS_ERR_GETDPDSTATUS_ARMERRFLAG ARM reported an error while processing the GET ARM command + */ +mykonosErr_t MYKONOS_getDpdStatus(mykonosDevice_t *device, mykonosTxChannels_t txChannel, mykonosDpdStatus_t *dpdStatus) +{ + uint8_t extData[3] = {MYKONOS_ARM_OBJECTID_CAL_STATUS, MYKONOS_ARM_OBJECTID_DPDCONFIG, 0}; + uint8_t armData[64] = {0}; + uint32_t timeoutMs = 0; + uint8_t cmdStatusByte = 0; + uint8_t channelSelect = 0; + mykonosErr_t retVal = MYKONOS_ERR_OK; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getDpdStatus()\n"); +#endif + + if (dpdStatus == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETDPDSTATUS_NULLPARAM, + getMykonosErrorMessage(MYKONOS_ERR_GETDPDSTATUS_NULLPARAM)); + return MYKONOS_ERR_GETDPDSTATUS_NULLPARAM; + } + + switch (txChannel) + { + case TX1: + channelSelect = 0; + break; + case TX2: + channelSelect = 1; + break; + default: + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETDPDSTATUS_INV_CH, + getMykonosErrorMessage(MYKONOS_ERR_GETDPDSTATUS_INV_CH)); + return MYKONOS_ERR_GETDPDSTATUS_INV_CH; + } + } + + extData[2] = channelSelect; + + retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_GET_OPCODE, &extData[0], sizeof(extData)); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + timeoutMs = 1000; + retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_GET_OPCODE, timeoutMs, &cmdStatusByte); + if (retVal != MYKONOS_ERR_OK) + { + if (cmdStatusByte > 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETDPDSTATUS_ARMERRFLAG, + getMykonosErrorMessage(MYKONOS_ERR_GETDPDSTATUS_ARMERRFLAG)); + return MYKONOS_ERR_GETDPDSTATUS_ARMERRFLAG; + } + + return retVal; + } + + if (cmdStatusByte > 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETDPDSTATUS_ARMERRFLAG, + getMykonosErrorMessage(MYKONOS_ERR_GETDPDSTATUS_ARMERRFLAG)); + return MYKONOS_ERR_GETDPDSTATUS_ARMERRFLAG; + } + + /* read status from ARM memory */ + retVal = MYKONOS_readArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR, &armData[0], sizeof(armData), 1); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + dpdStatus->dpdErrorStatus = ((uint32_t)(armData[1]) << 8) | (uint32_t)(armData[0]); /* Only lower 16 bits */ + dpdStatus->dpdTrackCount = ((uint32_t)(armData[11]) << 24) | ((uint32_t)(armData[10]) << 16) | ((uint32_t)(armData[9]) << 8) | (uint32_t)(armData[8]); + dpdStatus->dpdModelErrorPercent = ((uint32_t)(armData[15]) << 24) | ((uint32_t)(armData[14]) << 16) | ((uint32_t)(armData[13]) << 8) | (uint32_t)(armData[12]); + dpdStatus->dpdExtPathDelay = ((uint32_t)(armData[26]) * 16) + (uint32_t)(armData[24]); + dpdStatus->dpdMaxAdaptationCurrent = ((uint16_t)(armData[41]) << 8) + (uint16_t)(armData[40]); + dpdStatus->dpdMaxAdaptation = ((uint16_t)(armData[43]) << 8) + (uint16_t)(armData[42]); + dpdStatus->dpdIterCount = ((uint32_t)(armData[47]) << 24) | ((uint32_t)(armData[46]) << 16) | ((uint32_t)(armData[45]) << 8) | (uint32_t)(armData[44]); + + return MYKONOS_ERR_OK; +} + +/** + * \brief This private helper function called during RadioOff, will allow DPD tracking to be scheduled + * by the ARM when back in the RadioOn state. + * + * This function sets a flag in the ARM memory that if the enableDpd tracking cal mask + * and this setting are both set, then the ARM will schedule DPD tracking to occur + * in the radioOn ARM state. + * + * A DPD-enabled transceiver is required for DPD to be enabled. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * - device->tx->dpdConfig + * + * \param device is structure pointer to the Mykonos data structure containing settings + * \param tx1Enable 0=disable DPD Tx1 tracking, 1= enable DPD Tx1 tracking + * \param tx2Enable 0=disable DPD Tx2 tracking, 1= enable DPD Tx2 tracking + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_EN_DPDTRACKING_ARMSTATE_ERROR ARM is not in the RadioOff state, call MYKONOS_radioOff() + */ +static mykonosErr_t enableDpdTracking(mykonosDevice_t *device, uint8_t tx1Enable, uint8_t tx2Enable) +{ + uint32_t radioStatus = 0; + mykonosErr_t retVal = MYKONOS_ERR_OK; + uint8_t enableBit[4] = {0}; + uint8_t byteOffset = 20; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_enableDpdTracking()\n"); +#endif + + /* read radio state to make sure ARM is in radioOff /IDLE */ + retVal = MYKONOS_getRadioState(device, &radioStatus); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + /* throw error if not in radioOff/IDLE state */ + if (((radioStatus & 0x03) != MYKONOS_ARM_SYSTEMSTATE_IDLE) && ((radioStatus & 0x03) != MYKONOS_ARM_SYSTEMSTATE_READY)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_EN_DPDTRACKING_ARMSTATE_ERROR, + getMykonosErrorMessage(MYKONOS_ERR_EN_DPDTRACKING_ARMSTATE_ERROR)); + return MYKONOS_ERR_EN_DPDTRACKING_ARMSTATE_ERROR; + } + + enableBit[0] = (tx1Enable > 0) ? 1 : 0; + enableBit[1] = 0; + enableBit[2] = (tx2Enable > 0) ? 1 : 0; + enableBit[3] = 0; + + retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_DPDCONFIG, byteOffset, &enableBit[0], 4); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + return MYKONOS_ERR_OK; +} + +/** + * \brief This function will allow loading of the DPD model file. + * + * This function writes a copy of the user's DPD model to ARM memory and instructs the ARM to install that DPD model + * into hardware. Note that initializing the device will over write DPD model data. Note that the DPD model being + * restored must match the PA for which it is configured. Restoring a DPD model to a different PA than for which it + * is configured will not yield the desired performance. The user is responsible to insure the DPD model matches the + * PA configuration. + * + * \param device Structure pointer to the Mykonos data structure containing settings + * \param txChannel Desired transmit channel to which to write the DPD model file (Valid ENUM type mykonosTxChannels_t: TX1 or TX2 or TX1_TX2) + * \param modelDataBuffer Pointer to the user buffer containing the history/model data to be loaded to a txChannel + * Valid sizes: 182 bytes for a single model load to either TX1 or TX2. + * 364 bytes for a dual model load to both TX1_TX2, where the TX1 model data will occupy the first 182 bytes + * and TX2 model data will occupy the second 182 bytes. + * \param modelNumberBytes Total buffer size of the user history/model data buffer. Allowed sizes are 182 bytes for TX1 or TX2 and + * 364 bytes for TX1_TX2. + * + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_RESTDPDMOD_WRONGBUFFERSIZE User suppled modelNumberBytes size is incorrect. TX1 or TX2 = 182, TX1_TX2 = 364 + * \retval MYKONOS_ERR_RESTDPDMOD_INVALID_TXCHANNEL User supplied txChannel does not match TX1 or TX2 or TX1_TX2 + * \retval MYKONOS_ERR_RESTDPDMOD_ARMERRFLAG ARM returned error for Set ARM Command + */ +mykonosErr_t MYKONOS_restoreDpdModel(mykonosDevice_t *device, mykonosTxChannels_t txChannel, uint8_t *modelDataBuffer, uint32_t modelNumberBytes) +{ + uint32_t radioStatus = 0; + mykonosErr_t retVal = MYKONOS_ERR_OK; + uint8_t armData[4] = {0}; + uint32_t armBufferAddr = 0; + uint8_t *bufferPtr = 0; + uint8_t extendedData[4] = {0}; + uint8_t cmdStatusByte = 0; + + const uint8_t RESTORE = 0x08; + const uint32_t timeoutMs = 1000; + const uint32_t MODEL_SIZE = 182; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_restoreDpdModel()\n"); +#endif + + /* read radio state to make sure ARM is in radioOff /IDLE */ + retVal = MYKONOS_getRadioState(device, &radioStatus); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + if (txChannel == TX1) + { + /* check for single valid provided buffer size */ + if (modelNumberBytes != MODEL_SIZE) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RESTDPDMOD_WRONGBUFFERSIZE, + getMykonosErrorMessage(MYKONOS_ERR_RESTDPDMOD_WRONGBUFFERSIZE)); + return MYKONOS_ERR_RESTDPDMOD_WRONGBUFFERSIZE; + } + + /* retrieve the arm TX1 model buffer address */ + retVal = MYKONOS_readArmMem(device, (MYKONOS_ADDR_ARM_START_PROG_ADDR + MYKONOS_ADDR_TX1_DPD_MODEL_INDIRECT_PTR), &armData[0], 4, 1); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + armBufferAddr = (((uint32_t)armData[0]) | (((uint32_t)armData[1]) << 8) | (((uint32_t)armData[2]) << 16) | (((uint32_t)armData[3]) << 24)); + + /* write the TX1 model */ + bufferPtr = modelDataBuffer; + retVal = MYKONOS_writeArmMem(device, armBufferAddr, bufferPtr, MODEL_SIZE); /* write TX1 model */ + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + }/*end TX1 */ + + else if (txChannel == TX2) + { + /* check for single valid provided buffer size */ + if (modelNumberBytes != MODEL_SIZE) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RESTDPDMOD_WRONGBUFFERSIZE, + getMykonosErrorMessage(MYKONOS_ERR_RESTDPDMOD_WRONGBUFFERSIZE)); + return MYKONOS_ERR_RESTDPDMOD_WRONGBUFFERSIZE; + } + + /* retrieve the arm TX2 model buffer address */ + retVal = MYKONOS_readArmMem(device, (MYKONOS_ADDR_ARM_START_PROG_ADDR + MYKONOS_ADDR_TX2_DPD_MODEL_INDIRECT_PTR), &armData[0], 4, 1); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + armBufferAddr = (((uint32_t)armData[0]) | (((uint32_t)armData[1]) << 8) | (((uint32_t)armData[2]) << 16) | (((uint32_t)armData[3]) << 24)); + + /* write the TX2 model */ + bufferPtr = modelDataBuffer; + retVal = MYKONOS_writeArmMem(device, armBufferAddr, bufferPtr, MODEL_SIZE); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + }/* end TX2 */ + + /* check for dual txChannel type */ + else if (txChannel == TX1_TX2) + { + /* check for single valid provided buffer size */ + if (modelNumberBytes != (2 * MODEL_SIZE)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RESTDPDMOD_WRONGBUFFERSIZE, + getMykonosErrorMessage(MYKONOS_ERR_RESTDPDMOD_WRONGBUFFERSIZE)); + return MYKONOS_ERR_RESTDPDMOD_WRONGBUFFERSIZE; + } + + /* retrieve the arm TX1 model buffer address */ + retVal = MYKONOS_readArmMem(device, (MYKONOS_ADDR_ARM_START_PROG_ADDR + MYKONOS_ADDR_TX1_DPD_MODEL_INDIRECT_PTR), &armData[0], 4, 1); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + armBufferAddr = (((uint32_t)armData[0]) | (((uint32_t)armData[1]) << 8) | (((uint32_t)armData[2]) << 16) | (((uint32_t)armData[3]) << 24)); + + /* write the TX1 model */ + bufferPtr = modelDataBuffer; + retVal = MYKONOS_writeArmMem(device, armBufferAddr, bufferPtr, MODEL_SIZE); /* write TX1 model */ + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + bufferPtr += MODEL_SIZE; + + /* retrieve the arm TX2 model buffer address */ + retVal = MYKONOS_readArmMem(device, (MYKONOS_ADDR_ARM_START_PROG_ADDR + MYKONOS_ADDR_TX2_DPD_MODEL_INDIRECT_PTR), &armData[0], 4, 1); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + armBufferAddr = (((uint32_t)armData[0]) | (((uint32_t)armData[1]) << 8) | (((uint32_t)armData[2]) << 16) | (((uint32_t)armData[3]) << 24)); + + /* write the TX2 model */ + retVal = MYKONOS_writeArmMem(device, armBufferAddr, bufferPtr, MODEL_SIZE); /* write TX2 model */ + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + }/*end two txChannel model data load */ + + /* invalid txChannel for this API command */ + else + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RESTDPDMOD_INVALID_TXCHANNEL, + getMykonosErrorMessage(MYKONOS_ERR_RESTDPDMOD_INVALID_TXCHANNEL)); + return MYKONOS_ERR_RESTDPDMOD_INVALID_TXCHANNEL; + }/* end invalid txChannel check */ + + /* instruct ARM to load DPD Model */ + extendedData[0] = MYKONOS_ARM_OBJECTID_GS_TRACKCALS; + extendedData[1] = MYKONOS_ARM_DPD_RESET; + extendedData[2] = (uint8_t)txChannel + RESTORE; + + retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_SET_OPCODE, &extendedData[0], sizeof(extendedData)); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + /* wait max of 1sec for command to complete */ + retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_SET_OPCODE, timeoutMs, &cmdStatusByte); + if (retVal != MYKONOS_ERR_OK) + { + if (cmdStatusByte > 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RESTDPDMOD_ARMERRFLAG, + getMykonosErrorMessage(MYKONOS_ERR_RESTDPDMOD_ARMERRFLAG)); + return MYKONOS_ERR_RESTDPDMOD_ARMERRFLAG; + } + return retVal; + } + + return MYKONOS_ERR_OK; +} + + +/** + * \brief This function called during RadioOff, will allow retrieval of the DPD model file. + * + * This function reads a copy of the DPD model from ARM memory to user memory specified by the modelDataBuffer pointer. + * The user must provide the correct buffer size with the modelNumberBytes argument. + * + * \param device is structure pointer to the Mykonos data structure containing settings + * \param txChannel Desired Transmit channel to read back DPD status for (Valid ENUM type mykonosTxChannels_t: TX1 or TX2 or TX1_TX2) + * \param modelDataBuffer a pointer to the user buffer where the model data is to be written. + * Valid sizes: 182 bytes for a single model load to either TX1 or TX2. + * 364 bytes for a dual model load to both TX1_TX2, where the TX1 model data will occupy the first 182 bytes + * and TX2 model data will occupy the second 182 bytes. + * \param modelNumberBytes is the total buffer size of the user model data buffer. Allowed sizes are 182 bytes for TX1 or TX2 and + * 364 bytes for TX1_TX2. + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_SAVEDPDMODEL_ARMSTATE_ERROR ARM is not in the RadioOff state, call MYKONOS_radioOff() + * \retval MYKONOS_ERR_SAVEDPDMODEL_BUFFERSIZE_ERROR suppled modelNumberBytes size is incorrect. TX1 or TX2 = 182, TX1_TX2 = 364 + * \retval MYKONOS_ERR_SAVEDPDMODEL_INVALID_TXCHANNEL_ERROR supplied txChannel does not match TX1 or TX2 or TX1_TX2 + */ +mykonosErr_t MYKONOS_saveDpdModel(mykonosDevice_t *device, mykonosTxChannels_t txChannel, uint8_t *modelDataBuffer, uint32_t modelNumberBytes) +{ + uint32_t radioStatus = 0; + mykonosErr_t retVal = MYKONOS_ERR_OK; + uint16_t modelSize = 0; + uint8_t armData[4] = {0}; + uint32_t armBufferAddr = 0; + + const uint32_t MODEL_SIZE = 182; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_saveDpdModel()\n"); +#endif + + /* read radio state to make sure ARM is in radioOff /IDLE */ + retVal = MYKONOS_getRadioState(device, &radioStatus); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + /* throw error if not in radioOff/IDLE state */ + if (((radioStatus & 0x03) != MYKONOS_ARM_SYSTEMSTATE_IDLE) && ((radioStatus & 0x03) != MYKONOS_ARM_SYSTEMSTATE_READY)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SAVDPDMOD_ARMSTATE, getMykonosErrorMessage(MYKONOS_ERR_SAVDPDMOD_ARMSTATE)); /* radio not off or initialized */ + return MYKONOS_ERR_SAVDPDMOD_ARMSTATE; + } + + if (txChannel == TX1) + { + /* check for single valid provided buffer size */ + if (modelNumberBytes != MODEL_SIZE) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SAVDPDMOD_WRONGBUFFERSIZE, + getMykonosErrorMessage(MYKONOS_ERR_SAVDPDMOD_WRONGBUFFERSIZE)); + return MYKONOS_ERR_SAVDPDMOD_WRONGBUFFERSIZE; /* wrong buffer size */ + } + + /* retrieve the arm TX1 model buffer address */ + retVal = MYKONOS_readArmMem(device, MYKONOS_ADDR_ARM_START_PROG_ADDR + MYKONOS_ADDR_TX1_DPD_MODEL_WORKING_PTR, &armData[0], 4, 1); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + armBufferAddr = (((uint32_t)armData[0]) | (((uint32_t)armData[1]) << 8) | (((uint32_t)armData[2]) << 16) | (((uint32_t)armData[3]) << 24)); + + /* read the TX1 model */ + retVal = MYKONOS_readArmMem(device, armBufferAddr, modelDataBuffer, MODEL_SIZE, 1); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + modelDataBuffer += modelSize; + }/*end TX1 */ + + else if (txChannel == TX2) + { + /* check for single valid provided buffer size */ + if (modelNumberBytes != MODEL_SIZE) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SAVDPDMOD_WRONGBUFFERSIZE, + getMykonosErrorMessage(MYKONOS_ERR_SAVDPDMOD_WRONGBUFFERSIZE)); + return MYKONOS_ERR_SAVDPDMOD_WRONGBUFFERSIZE; /* wrong buffer size */ + } + + /* retrieve the arm TX2 model buffer address */ + retVal = MYKONOS_readArmMem(device, MYKONOS_ADDR_ARM_START_PROG_ADDR + MYKONOS_ADDR_TX2_DPD_MODEL_WORKING_PTR, &armData[0], 4, 1); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + armBufferAddr = (((uint32_t)armData[0]) | (((uint32_t)armData[1]) << 8) | (((uint32_t)armData[2]) << 16) | (((uint32_t)armData[3]) << 24)); + + /* read the TX2 model */ + retVal = MYKONOS_readArmMem(device, armBufferAddr, modelDataBuffer, MODEL_SIZE, 1); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + }/*end TX2 */ + + /* check for dual txChannel type */ + else if (txChannel == TX1_TX2) + { + /* check for single valid provided buffer size */ + if (modelNumberBytes != (2 * MODEL_SIZE)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SAVDPDMOD_WRONGBUFFERSIZE, + getMykonosErrorMessage(MYKONOS_ERR_SAVDPDMOD_WRONGBUFFERSIZE)); + return MYKONOS_ERR_SAVDPDMOD_WRONGBUFFERSIZE; /* wrong buffer size */ + } + + /* retrieve the arm TX1 model buffer address */ + retVal = MYKONOS_readArmMem(device, MYKONOS_ADDR_ARM_START_PROG_ADDR + MYKONOS_ADDR_TX1_DPD_MODEL_WORKING_PTR, &armData[0], 4, 1); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + armBufferAddr = (((uint32_t)armData[0]) | (((uint32_t)armData[1]) << 8) | (((uint32_t)armData[2]) << 16) | (((uint32_t)armData[3]) << 24)); + + /* read the TX1 model */ + retVal = MYKONOS_readArmMem(device, armBufferAddr, modelDataBuffer, MODEL_SIZE, 1); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + modelDataBuffer += MODEL_SIZE; + + /* retrieve the arm TX2 model buffer address */ + retVal = MYKONOS_readArmMem(device, MYKONOS_ADDR_ARM_START_PROG_ADDR + MYKONOS_ADDR_TX2_DPD_MODEL_WORKING_PTR, &armData[0], 4, 1); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + armBufferAddr = (((uint32_t)armData[0]) | (((uint32_t)armData[1]) << 8) | (((uint32_t)armData[2]) << 16) | (((uint32_t)armData[3]) << 24)); + + /* read the TX2 model */ + retVal = MYKONOS_readArmMem(device, armBufferAddr, modelDataBuffer, MODEL_SIZE, 1); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + }/* end TX1_TX2 txChannel */ + + /* invalid txChannel for this API command */ + else + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SAVDPDMOD_INVALID_TXCHANNEL, + getMykonosErrorMessage(MYKONOS_ERR_SAVDPDMOD_INVALID_TXCHANNEL)); + return MYKONOS_ERR_SAVDPDMOD_INVALID_TXCHANNEL; /* invalid txChannel */ + }/* end invalid txChannel check */ + + return MYKONOS_ERR_OK; +} + +/** + * \brief This function sets the state of the DPD actuator. + * + * This function can be called in either Radio On or Off state. + * + * \pre A DPD-enabled transceiver is required for DPD to be enabled. DPD init cal has been run and DPD tracking enable. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device is structure pointer to the Mykonos data structure containing settings + * \param txChannel Desired Transmit channel to set the Actuator State (Valid ENUM values: TX1, TX2 or TX1_TX2) + * \param actState Desired actuator state for the DPD, valid states are 0-disable and 1-enable + * + * \retval MYKONOS_ERR_SETDPDACT_INV_TXCHANNEL ERROR: Tx channel is not valid (Valid ENUM values: TX1, TX2 or TX1_TX2) + * \retval MYKONOS_ERR_SETDPDACT_INV_STATE ERROR: Invalid Actuator state, valid states are 0-disable and 1-enable. + * \retval MYKONOS_ERR_SETDPDACT_ARMERRFLAG ERROR: ARM command flag error set + * \retval MYKONOS_ERR_OK Function completed successfully + */ +mykonosErr_t MYKONOS_setDpdActState(mykonosDevice_t *device, mykonosTxChannels_t txChannel, uint8_t actState) +{ + mykonosErr_t retVal = MYKONOS_ERR_OK; + uint32_t timeoutMs = 1000; + uint8_t extData[3] = {0}; + uint8_t actuatorSet = 0x00; + uint8_t cmdStatusByte = 0; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setDpdActState()\n"); +#endif + + switch (txChannel) + { + case TX1: + break; + case TX2: + break; + case TX1_TX2: + break; + + default: + /* this function allow single channel gain only */ + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETDPDACT_INV_TXCHANNEL, + getMykonosErrorMessage(MYKONOS_ERR_SETDPDACT_INV_TXCHANNEL)); + return MYKONOS_ERR_SETDPDACT_INV_TXCHANNEL; + } + switch (actState) + { + case 0: + actuatorSet = DISABLE_DPD_ACTUATOR; + break; + case 1: + actuatorSet = ENABLE_DPD_ACTUATOR; + break; + + default: + /* this function allow single channel gain only */ + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETDPDACT_INV_STATE, + getMykonosErrorMessage(MYKONOS_ERR_SETDPDACT_INV_STATE)); + return MYKONOS_ERR_SETDPDACT_INV_STATE; + } + + extData[0] = MYKONOS_ARM_OBJECTID_TRACKING_CAL_CONTROL; + extData[1] = actuatorSet; + extData[2] = (uint8_t)txChannel; + + retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_SET_OPCODE, &extData[0], sizeof(extData)); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + /* check for completion */ + retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_SET_OPCODE, timeoutMs, &cmdStatusByte); + if (retVal != MYKONOS_ERR_OK) + { + if (cmdStatusByte > 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETDPDACT_ARMERRFLAG, + getMykonosErrorMessage(MYKONOS_ERR_SETDPDACT_ARMERRFLAG)); + return MYKONOS_ERR_SETDPDACT_ARMERRFLAG; + } + + return retVal; + } + + if (cmdStatusByte > 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETDPDACT_ARMERRFLAG, + getMykonosErrorMessage(MYKONOS_ERR_SETDPDACT_ARMERRFLAG)); + return MYKONOS_ERR_SETDPDACT_ARMERRFLAG; + } + + return MYKONOS_ERR_OK; +} + +/** + * \brief This function resets the DPD model. + * + * This function allows the user to reset the DPD actuator and prior model in radioOn or radioOff mode. + * The reset can restore prior model if the parameter passed is set to 2: this resets DPD first and then restores the previously loaded + * model into ARM memory for use with subsequent iterations of DPD. + * + * If reset is 1 then the reset function just reset the DPD actuator and not use any model. + * + * \pre A DPD-enabled transceiver is required for DPD to be enabled. DPD init cal has been run and DPD tracking enable. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device is structure pointer to the Mykonos data structure containing settings + * \param txChannel Desired Transmit channel to be reseted (Valid ENUM values: TX1, TX2 or TX1_TX2) + * \param reset is the required reset condition that is needed, the available options are given by the enum + * ::mykonosDpdResetMode_t + * + * \retval MYKONOS_ERR_RESETDPD_INV_TXCHANNEL: Tx channel is not valid (Valid ENUM values: TX1, TX2 or TX1_TX2) + * \retval MYKONOS_ERR_RESETDPD_WRONG_PARAM ERROR: reset parameter is not valid (Valid values: MYK_DPD_RESET_FULL, MYK_DPD_RESET_PRIOR or MYK_DPD_RESET_CORRELATOR) + * \retval MYKONOS_ERR_RESETDPD_ARMERRFLAG ERROR: ARM command flag error set + * \retval MYKONOS_ERR_OK Function completed successfully + */ +mykonosErr_t MYKONOS_resetDpd(mykonosDevice_t *device, mykonosTxChannels_t txChannel, mykonosDpdResetMode_t reset) +{ + mykonosErr_t retVal = MYKONOS_ERR_OK; + uint32_t timeoutMs = 1000; + uint8_t extData[3] = {0}; + uint8_t cmdStatusByte = 0; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_resetDpd()\n"); +#endif + + switch (txChannel) + { + case TX1: + break; + case TX2: + break; + case TX1_TX2: + break; + + default: + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RESETDPD_INV_TXCHANNEL, + getMykonosErrorMessage(MYKONOS_ERR_RESETDPD_INV_TXCHANNEL)); + return MYKONOS_ERR_RESETDPD_INV_TXCHANNEL; + } + + if ((reset >= MYK_DPD_RESET_END) || (reset == MYK_DPD_NO_ACTION)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RESETDPD_WRONG_PARAM, + getMykonosErrorMessage(MYKONOS_ERR_RESETDPD_WRONG_PARAM)); + return MYKONOS_ERR_RESETDPD_WRONG_PARAM; + } + + /* instruct ARM to reset DPD Model */ + extData[0] = MYKONOS_ARM_OBJECTID_GS_TRACKCALS; + extData[1] = MYKONOS_ARM_DPD_RESET; + extData[2] = (uint8_t)(reset << 2) + (uint8_t)txChannel; + + retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_SET_OPCODE, &extData[0], sizeof(extData)); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + /* wait max of 1sec for command to complete */ + retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_SET_OPCODE, timeoutMs, &cmdStatusByte); + if (retVal != MYKONOS_ERR_OK) + { + if (cmdStatusByte > 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RESETDPD_ARMERRFLAG, + getMykonosErrorMessage(MYKONOS_ERR_RESETDPD_ARMERRFLAG)); + return MYKONOS_ERR_RESETDPD_ARMERRFLAG; + } + return retVal; + } + + return MYKONOS_ERR_OK; +} +/** + * \brief This function will configure CLGC settings + * + * A DPD-enabled transceiver is required for CLGC to be enabled. The CLGC has several user + * adjustable settings that can be configured before running the runInitCals + * with the calMask set for the CLGC init cal. Call this function with desired + * settings set before running the CLGC init cal or enabling CLGC tracking. + * + * This function can be called in either Radio On or Off state. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * - device->profilesValid + * - device->tx->clgcConfig (All members) + * + * \retval MYKONOS_ERR_CFGCLGC_TXORX_PROFILE_INV ERROR: Tx and ObsRx profiles must be valid to use the CLGC feature + * \retval MYKONOS_ERR_CFGCLGC_NULL_CLGCCFGSTRUCT ERROR: CLGC config structure pointer is null in device->tx->clgcConfig + * \retval MYKONOS_ERR_CFGCLGC_INV_DESIREDGAIN ERROR: CLGC tx1DesiredGain or tx2DesiredGain parameter is out of range + * \retval MYKONOS_ERR_CFGCLGC_INV_TXATTENLIMIT ERROR: CLGC tx1AttenLimit or tx2AttenLimit parameter is out of range + * \retval MYKONOS_ERR_CFGCLGC_INV_CLGC_CTRLRATIO ERROR: clgcControlRatio parameter is out of range + * \retval MYKONOS_ERR_CFGCLGC_INV_THRESHOLD Error: tx1RelThreshold or tx2RelThreshold parameter is out of range + * \retval MYKONOS_ERR_OK Function completed successfully + */ +mykonosErr_t MYKONOS_configClgc(mykonosDevice_t *device) +{ + mykonosErr_t retVal = MYKONOS_ERR_OK; + uint8_t armFieldValue[4] = {0}; + uint8_t byteOffset = 0; + uint16_t negPnLevel = 0; + uint32_t radioStatus = 0x00; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_configClgc()\n"); +#endif + + /* CLGC requires Tx and ORx enabled, throw error if both are not enabled */ + if ((device->profilesValid & (TX_PROFILE_VALID | ORX_PROFILE_VALID)) != (TX_PROFILE_VALID | ORX_PROFILE_VALID)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGCLGC_TXORX_PROFILE_INV, + getMykonosErrorMessage(MYKONOS_ERR_CFGCLGC_TXORX_PROFILE_INV)); + return MYKONOS_ERR_CFGCLGC_TXORX_PROFILE_INV; + } + + if (device->tx->clgcConfig == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGCLGC_NULL_CLGCCFGSTRUCT, + getMykonosErrorMessage(MYKONOS_ERR_CFGCLGC_NULL_CLGCCFGSTRUCT)); + return MYKONOS_ERR_CFGCLGC_NULL_CLGCCFGSTRUCT; + } + + /* set CLGC desired gain parameter */ + if ((device->tx->clgcConfig->tx1DesiredGain < -10000) || (device->tx->clgcConfig->tx1DesiredGain > 10000) || (device->tx->clgcConfig->tx2DesiredGain < -10000) + || (device->tx->clgcConfig->tx2DesiredGain > 10000)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGCLGC_INV_DESIREDGAIN, + getMykonosErrorMessage(MYKONOS_ERR_CFGCLGC_INV_DESIREDGAIN)); + return MYKONOS_ERR_CFGCLGC_INV_DESIREDGAIN; + } + + armFieldValue[0] = (device->tx->clgcConfig->tx1DesiredGain & 0xFF); + armFieldValue[1] = (((uint16_t)device->tx->clgcConfig->tx1DesiredGain >> 8) & 0xFF); + armFieldValue[2] = (device->tx->clgcConfig->tx2DesiredGain & 0xFF); + armFieldValue[3] = (((uint16_t)device->tx->clgcConfig->tx2DesiredGain >> 8) & 0xFF); + + byteOffset = 0; + retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_CLGCCONFIG, byteOffset, &armFieldValue[0], sizeof(armFieldValue)); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + /* set CLGC Tx Atten limit parameter */ + if ((device->tx->clgcConfig->tx1AttenLimit > 40) || (device->tx->clgcConfig->tx2AttenLimit > 40)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGCLGC_INV_TXATTENLIMIT, + getMykonosErrorMessage(MYKONOS_ERR_CFGCLGC_INV_TXATTENLIMIT)); + return MYKONOS_ERR_CFGCLGC_INV_TXATTENLIMIT; + } + + armFieldValue[0] = (device->tx->clgcConfig->tx1AttenLimit & 0xFF); + armFieldValue[1] = ((device->tx->clgcConfig->tx1AttenLimit >> 8) & 0xFF); + armFieldValue[2] = (device->tx->clgcConfig->tx2AttenLimit & 0xFF); + armFieldValue[3] = ((device->tx->clgcConfig->tx2AttenLimit >> 8) & 0xFF); + + byteOffset = 8; + retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_CLGCCONFIG, byteOffset, &armFieldValue[0], sizeof(armFieldValue)); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + /* set CLGC Control Ratio parameter */ + if ((device->tx->clgcConfig->tx1ControlRatio < 1) || (device->tx->clgcConfig->tx1ControlRatio > 100) || (device->tx->clgcConfig->tx2ControlRatio < 1) + || (device->tx->clgcConfig->tx2ControlRatio > 100)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGCLGC_INV_CLGC_CTRLRATIO, + getMykonosErrorMessage(MYKONOS_ERR_CFGCLGC_INV_CLGC_CTRLRATIO)); + return MYKONOS_ERR_CFGCLGC_INV_CLGC_CTRLRATIO; + } + + armFieldValue[0] = (device->tx->clgcConfig->tx1ControlRatio & 0xFF); + armFieldValue[1] = ((device->tx->clgcConfig->tx1ControlRatio >> 8) & 0xFF); + armFieldValue[2] = (device->tx->clgcConfig->tx2ControlRatio & 0xFF); + armFieldValue[3] = ((device->tx->clgcConfig->tx2ControlRatio >> 8) & 0xFF); + + byteOffset = 12; + retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_CLGCCONFIG, byteOffset, &armFieldValue[0], sizeof(armFieldValue)); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + /* set enable threshold for channel 1 */ + armFieldValue[0] = (device->tx->clgcConfig->tx1RelThresholdEn > 0) ? 1 : 0; + byteOffset = 0x24; + retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_CLGCCONFIG, byteOffset, &armFieldValue[0], 1); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + /* set enable threshold for channel 2 */ + armFieldValue[0] = (device->tx->clgcConfig->tx2RelThresholdEn > 0) ? 1 : 0; + byteOffset = 0x26; + retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_CLGCCONFIG, byteOffset, &armFieldValue[0], 1); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + /* set thresholds */ + if ((device->tx->clgcConfig->tx1RelThreshold > 10000) || (device->tx->clgcConfig->tx2RelThreshold > 10000)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGCLGC_INV_THRESHOLD, + getMykonosErrorMessage(MYKONOS_ERR_CFGCLGC_INV_THRESHOLD)); + return MYKONOS_ERR_CFGCLGC_INV_THRESHOLD; + } + + /* set threshold for channel 1 */ + armFieldValue[0] = (device->tx->clgcConfig->tx1RelThreshold & 0xFF); + armFieldValue[1] = ((device->tx->clgcConfig->tx1RelThreshold >> 8) & 0xFF); + byteOffset = 0x28; + retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_CLGCCONFIG, byteOffset, &armFieldValue[0], 2); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + /* set threshold for channel 2 */ + armFieldValue[0] = (device->tx->clgcConfig->tx2RelThreshold & 0xFF); + armFieldValue[1] = ((device->tx->clgcConfig->tx2RelThreshold >> 8) & 0xFF); + byteOffset = 0x2A; + retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_CLGCCONFIG, byteOffset, &armFieldValue[0], 2); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + if ((device->tx->clgcConfig->pathDelayPnSeqLevel < 1) || (device->tx->clgcConfig->pathDelayPnSeqLevel > 8191)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGCLGC_INV_PNSEQLEVEL, + getMykonosErrorMessage(MYKONOS_ERR_CFGCLGC_INV_PNSEQLEVEL)); + return MYKONOS_ERR_CFGCLGC_INV_PNSEQLEVEL; + } + + /* read radio state to make sure ARM is in radioOff /IDLE */ + retVal = MYKONOS_getRadioState(device, &radioStatus); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + /* Radio state check */ + if (((radioStatus & 0x03) == MYKONOS_ARM_SYSTEMSTATE_IDLE) || ((radioStatus & 0x03) == MYKONOS_ARM_SYSTEMSTATE_READY)) + { + /* set CLGC additional delay offset parameter (init cal)*/ + if ((device->tx->clgcConfig->additionalDelayOffset < -64) || (device->tx->clgcConfig->additionalDelayOffset > 64)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGCLGC_INV_CLGC_ADDDELAY, + getMykonosErrorMessage(MYKONOS_ERR_CFGCLGC_INV_CLGC_ADDDELAY)); + return MYKONOS_ERR_CFGCLGC_INV_CLGC_ADDDELAY; + } + + armFieldValue[0] = (device->tx->clgcConfig->additionalDelayOffset & 0xFF); + armFieldValue[1] = (((uint16_t)device->tx->clgcConfig->additionalDelayOffset >> 8) & 0xFF); + byteOffset = 2; + retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_CLGCINIT_CONFIG, byteOffset, &armFieldValue[0], 2); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + if ((device->tx->clgcConfig->pathDelayPnSeqLevel < 1) || (device->tx->clgcConfig->pathDelayPnSeqLevel > 8191)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGCLGC_INV_PNSEQLEVEL, + getMykonosErrorMessage(MYKONOS_ERR_CFGCLGC_INV_PNSEQLEVEL)); + return MYKONOS_ERR_CFGCLGC_INV_PNSEQLEVEL; + } + + /* Can not be changed in radio on */ + /* Set Path Delay PN sequence amplitude - positive and negative (init cal)*/ + armFieldValue[0] = (device->tx->clgcConfig->pathDelayPnSeqLevel & 0xFF); + armFieldValue[1] = ((device->tx->clgcConfig->pathDelayPnSeqLevel >> 8) & 0xFF); + + negPnLevel = ((~device->tx->clgcConfig->pathDelayPnSeqLevel) + 1); /* times -1 */ + armFieldValue[2] = (negPnLevel & 0xFF); + armFieldValue[3] = (((negPnLevel) >> 8) & 0xFF); + byteOffset = 10; + retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_CLGCINIT_CONFIG, byteOffset, &armFieldValue[0], sizeof(armFieldValue)); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + retVal = enableClgcTracking(device, ((device->tx->clgcConfig->allowTx1AttenUpdates > 0) ? 1 : 0), ((device->tx->clgcConfig->allowTx2AttenUpdates > 0) ? 1 : 0)); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + } + else + { + /* record warning about not updated members */ + CMB_writeToLog(ADIHAL_LOG_WARNING, device->spiSettings->chipSelectIndex, MYKONOS_WRN_RADIO_ON_NOT_MODIFIABLE, + getMykonosErrorMessage(MYKONOS_WRN_RADIO_ON_NOT_MODIFIABLE)); + } + + return MYKONOS_ERR_OK; +} + +/* \brief Reads the CLGC config structure from ARM memory + * + * This function reads the Closed Loop Gain Control structure + * from ARM memory and returns in the device->tx->clgcConfig structure. + * + * A DPD-enabled transceiver is required for CLGC to be enabled. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * - device->profilesValid + * - device->tx->clgcConfig (All members) + * + * \param device is structure pointer to the Mykonos data structure containing settings + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_GETCLGCCFG_TXORX_PROFILE_INV Error: Tx and ORx profiles must be valid for CLGC functions + * \retval MYKONOS_ERR_GETCLGCCFG_NULL_CFGSTRUCT Error: NULL pointer to device->tx->clgcConfig structure + */ +mykonosErr_t MYKONOS_getClgcConfig(mykonosDevice_t *device) +{ + uint16_t byteOffset = 0; + uint8_t armMem[16] = {0}; + mykonosErr_t retVal = MYKONOS_ERR_OK; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getClgcConfig()\n"); +#endif + + /* CLGC requires Tx and ORx enabled, throw error if both are not enabled */ + if ((device->profilesValid & (TX_PROFILE_VALID | ORX_PROFILE_VALID)) != (TX_PROFILE_VALID | ORX_PROFILE_VALID)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETCLGCCFG_TXORX_PROFILE_INV, + getMykonosErrorMessage(MYKONOS_ERR_GETCLGCCFG_TXORX_PROFILE_INV)); + return MYKONOS_ERR_GETCLGCCFG_TXORX_PROFILE_INV; + } + + if (device->tx->clgcConfig == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETCLGCCFG_NULL_CFGSTRUCT, + getMykonosErrorMessage(MYKONOS_ERR_GETCLGCCFG_NULL_CFGSTRUCT)); + return MYKONOS_ERR_GETCLGCCFG_NULL_CFGSTRUCT; + } + + byteOffset = 0; + retVal = MYKONOS_readArmConfig(device, MYKONOS_ARM_OBJECTID_CLGCCONFIG, byteOffset, &armMem[0], sizeof(armMem)); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + device->tx->clgcConfig->tx1DesiredGain = (int16_t)(((uint16_t)(armMem[1]) << 8) | (uint16_t)(armMem[0])); + device->tx->clgcConfig->tx2DesiredGain = (int16_t)(((uint16_t)(armMem[3]) << 8) | (uint16_t)(armMem[2])); + device->tx->clgcConfig->tx1AttenLimit = (((uint16_t)(armMem[9]) << 8) | (uint16_t)(armMem[8])); + device->tx->clgcConfig->tx2AttenLimit = (((uint16_t)(armMem[11]) << 8) | (uint16_t)(armMem[10])); + device->tx->clgcConfig->tx1ControlRatio = (((uint16_t)(armMem[13]) << 8) | (uint16_t)(armMem[12])); + device->tx->clgcConfig->tx2ControlRatio = (((uint16_t)(armMem[15]) << 8) | (uint16_t)(armMem[14])); + + byteOffset = 2; + retVal = MYKONOS_readArmConfig(device, MYKONOS_ARM_OBJECTID_CLGCINIT_CONFIG, byteOffset, &armMem[0], 2); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + device->tx->clgcConfig->additionalDelayOffset = (int16_t)(((uint16_t)(armMem[1]) << 8) | (uint16_t)(armMem[0])); + + byteOffset = 10; + retVal = MYKONOS_readArmConfig(device, MYKONOS_ARM_OBJECTID_CLGCINIT_CONFIG, byteOffset, &armMem[0], 2); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + device->tx->clgcConfig->pathDelayPnSeqLevel = (((uint16_t)(armMem[1]) << 8) | (uint16_t)(armMem[0])); + + /* need to figure out if this are the right addresses */ + byteOffset = 0x24; + retVal = MYKONOS_readArmConfig(device, MYKONOS_ARM_OBJECTID_CLGCCONFIG, byteOffset, &armMem[0], 1); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + device->tx->clgcConfig->tx1RelThresholdEn = (uint8_t)armMem[0]; + + byteOffset = 0x26; + retVal = MYKONOS_readArmConfig(device, MYKONOS_ARM_OBJECTID_CLGCCONFIG, byteOffset, &armMem[0], 1); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + device->tx->clgcConfig->tx2RelThresholdEn = (uint8_t)armMem[0]; + + byteOffset = 0x28; + retVal = MYKONOS_readArmConfig(device, MYKONOS_ARM_OBJECTID_CLGCCONFIG, byteOffset, &armMem[0], 2); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + device->tx->clgcConfig->tx1RelThreshold = (((uint16_t)(armMem[1]) << 8) | (uint16_t)(armMem[0])); + + byteOffset = 0x2A; + retVal = MYKONOS_readArmConfig(device, MYKONOS_ARM_OBJECTID_CLGCCONFIG, byteOffset, &armMem[0], 2); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + device->tx->clgcConfig->tx2RelThreshold = (((uint16_t)(armMem[1]) << 8) | (uint16_t)(armMem[0])); + + return MYKONOS_ERR_OK; +} + +/** + * \brief This function reads the CLGC calibration status from the Mykonos ARM processor. + * + * The Closed Loop Gain Control Status is read back from the ARM processor and + * returned in the function parameter clgcStatus. + * + * A DPD-enabled transceiver is required for this feature to be enabled. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device is structure pointer to the Mykonos data structure containing settings + * \param txChannel Desired Transmit channel to read back CLGC status for (Valid ENUM values: TX1 or TX2 only) + * \param clgcStatus Pointer to a structure to return the status information to + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_GETCLGCSTATUS_NULLPARAM clgcStatus function parameter is a NULL pointer + * \retval MYKONOS_ERR_GETCLGCSTATUS_INV_CH txChannel parameter is a non supported value. + * \retval MYKONOS_ERR_GETCLGCSTATUS_ARMERRFLAG ARM reported an error while processing the GET ARM command + */ +mykonosErr_t MYKONOS_getClgcStatus(mykonosDevice_t *device, mykonosTxChannels_t txChannel, mykonosClgcStatus_t *clgcStatus) +{ + uint8_t extData[3] = {MYKONOS_ARM_OBJECTID_CAL_STATUS, MYKONOS_ARM_OBJECTID_CLGCCONFIG, 0}; + uint8_t armData[52] = {0}; + uint32_t timeoutMs = 0; + uint8_t cmdStatusByte = 0; + uint32_t offset = 0; + mykonosErr_t retVal = MYKONOS_ERR_OK; + uint8_t channelSelect = 0; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getClgcStatus()\n"); +#endif + + if (clgcStatus == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETCLGCSTATUS_NULLPARAM, + getMykonosErrorMessage(MYKONOS_ERR_GETCLGCSTATUS_NULLPARAM)); + return MYKONOS_ERR_GETCLGCSTATUS_NULLPARAM; + } + + switch (txChannel) + { + case TX1: + channelSelect = 0; + break; + case TX2: + channelSelect = 1; + break; + default: + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETCLGCSTATUS_INV_CH, + getMykonosErrorMessage(MYKONOS_ERR_GETCLGCSTATUS_INV_CH)); + return MYKONOS_ERR_GETCLGCSTATUS_INV_CH; + } + } + + extData[2] = channelSelect; + + retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_GET_OPCODE, &extData[0], sizeof(extData)); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + timeoutMs = 1000; + retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_GET_OPCODE, timeoutMs, &cmdStatusByte); + if (retVal != MYKONOS_ERR_OK) + { + if (cmdStatusByte > 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETCLGCSTATUS_ARMERRFLAG, + getMykonosErrorMessage(MYKONOS_ERR_GETCLGCSTATUS_ARMERRFLAG)); + return MYKONOS_ERR_GETCLGCSTATUS_ARMERRFLAG; + } + + return retVal; + } + + if (cmdStatusByte > 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETCLGCSTATUS_ARMERRFLAG, + getMykonosErrorMessage(MYKONOS_ERR_GETCLGCSTATUS_ARMERRFLAG)); + return MYKONOS_ERR_GETCLGCSTATUS_ARMERRFLAG; + } + + /* read status from ARM memory */ + offset = 0; + retVal = MYKONOS_readArmMem(device, (MYKONOS_ADDR_ARM_START_DATA_ADDR + offset), &armData[0], sizeof(armData), 1); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + clgcStatus->errorStatus = ((uint32_t)(armData[3]) << 24) | ((uint32_t)(armData[2]) << 16) | ((uint32_t)(armData[1]) << 8) | (uint32_t)(armData[0]); + clgcStatus->desiredGain = (int32_t)(((uint32_t)(armData[23]) << 24) | ((uint32_t)(armData[22]) << 16) | ((uint32_t)(armData[21]) << 8) | (uint32_t)(armData[20])); + clgcStatus->currentGain = (int32_t)(((uint32_t)(armData[27]) << 24) | ((uint32_t)(armData[26]) << 16) | ((uint32_t)(armData[25]) << 8) | (uint32_t)(armData[24])); + clgcStatus->txGain = ((uint32_t)(armData[39]) << 24) | ((uint32_t)(armData[38]) << 16) | ((uint32_t)(armData[37]) << 8) | (uint32_t)(armData[36]); + clgcStatus->txRms = (int32_t)(((uint32_t)(armData[43]) << 24) | ((uint32_t)(armData[42]) << 16) | ((uint32_t)(armData[41]) << 8) | (uint32_t)(armData[40])); + clgcStatus->orxRms = (int32_t)(((uint32_t)(armData[47]) << 24) | ((uint32_t)(armData[46]) << 16) | ((uint32_t)(armData[45]) << 8) | (uint32_t)(armData[44])); + clgcStatus->trackCount = ((uint32_t)(armData[51]) << 24) | ((uint32_t)(armData[50]) << 16) | ((uint32_t)(armData[49]) << 8) | (uint32_t)(armData[48]); + + return retVal; +} + +/** + * \brief This private helper function called during RadioOff, will allow CLGC tracking to be scheduled + * by the ARM when back in the RadioOn state. + * + * This function sets a flag in the ARM memory that if the enableDpd tracking cal mask + * and this setting are both set, then the ARM will schedule closed loop gain control + * tracking to occur in the radioOn ARM state. + * + * A DPD-enabled transceiver is required for this feature to be enabled. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * - device->tx->dpdConfig + * + * \param device is structure pointer to the Mykonos data structure containing settings + * \param tx1Enable 0=disable CLGC Tx1 tracking, 1= enable CLGC Tx1 tracking + * \param tx2Enable 0=disable CLGC Tx2 tracking, 1= enable CLGC Tx2 tracking + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_EN_CLGCTRACKING_ARMSTATE_ERROR ARM is not in the RadioOff state, call MYKONOS_radioOff() + */ +static mykonosErr_t enableClgcTracking(mykonosDevice_t *device, uint8_t tx1Enable, uint8_t tx2Enable) +{ + uint32_t radioStatus = 0; + mykonosErr_t retVal = MYKONOS_ERR_OK; + uint8_t enableBit[4] = {0}; + uint8_t byteOffset = 4; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_enableClgcTracking()\n"); +#endif + + /* read radio state to make sure ARM is in radioOff /IDLE */ + retVal = MYKONOS_getRadioState(device, &radioStatus); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + /* throw error if not in radioOff/IDLE state */ + if (((radioStatus & 0x03) != MYKONOS_ARM_SYSTEMSTATE_IDLE) && ((radioStatus & 0x03) != MYKONOS_ARM_SYSTEMSTATE_READY)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_EN_CLGCTRACKING_ARMSTATE_ERROR, + getMykonosErrorMessage(MYKONOS_ERR_EN_CLGCTRACKING_ARMSTATE_ERROR)); + return MYKONOS_ERR_EN_CLGCTRACKING_ARMSTATE_ERROR; + } + + enableBit[0] = (tx1Enable > 0) ? 1 : 0; + enableBit[1] = 0; + enableBit[2] = (tx2Enable > 0) ? 1 : 0; + enableBit[3] = 0; + + retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_CLGCCONFIG, byteOffset, &enableBit[0], 4); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + return MYKONOS_ERR_OK; +} + +/** + * \brief This function updates the CLGC desired gain parameter. + * + * This function can be called in either Radio On or Off state. + * + * \pre A DPD-enabled transceiver is required for CLGC to be enabled. CLGC init cal has been run and CLGC tracking enable. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device is structure pointer to the Mykonos data structure containing settings + * \param txChannel Desired Transmit channel to set the (Valid ENUM values: TX1 or TX2 only) + * \param gain Total gain and attenuation (dB * 100) for the selected channel txChannel + * + * \retval MYKONOS_ERR_SETCLGCGAIN_INV_TXCHANNEL ERROR: Tx channel is not valid (Valid ENUM values: TX1 or TX2 only) + * \retval MYKONOS_ERR_SETCLGCGAIN_TRACK_ARMERRFLAG ERROR: ARM command flag error set + * \retval MYKONOS_ERR_SETCLGCGAIN_INV_DESIREDGAIN ERROR: CLGC gain parameter is out of range, valid range is from -10000 to 10000. + * \retval MYKONOS_ERR_OK Function completed successfully + */ +mykonosErr_t MYKONOS_setClgcGain(mykonosDevice_t *device, mykonosTxChannels_t txChannel, int16_t gain) +{ + mykonosErr_t retVal = MYKONOS_ERR_OK; + uint32_t timeoutMs = 1000; + uint8_t extData[4] = {0}; + uint8_t clcgChannel = 0x00; + uint8_t cmdStatusByte = 0; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setClgcGain()\n"); +#endif + + /* Range check for desired gain parameter */ + if ((gain < -10000) || (gain > 10000)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETCLGCGAIN_INV_DESIREDGAIN, + getMykonosErrorMessage(MYKONOS_ERR_SETCLGCGAIN_INV_DESIREDGAIN)); + return MYKONOS_ERR_SETCLGCGAIN_INV_DESIREDGAIN; + } + + switch (txChannel) + { + case TX1: + clcgChannel = SET_CLGC_DESIRED_GAIN_1; + break; + case TX2: + clcgChannel = SET_CLGC_DESIRED_GAIN_2; + break; + + default: + /* this function allow single channel gain only */ + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETCLGCGAIN_INV_TXCHANNEL, + getMykonosErrorMessage(MYKONOS_ERR_SETCLGCGAIN_INV_TXCHANNEL)); + return MYKONOS_ERR_SETCLGCGAIN_INV_TXCHANNEL; + } + + extData[0] = MYKONOS_ARM_OBJECTID_TRACKING_CAL_CONTROL; + extData[1] = clcgChannel; + extData[2] = (gain & 0xFF); + extData[3] = (((uint16_t)gain >> 8) & 0xFF); + + retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_SET_OPCODE, &extData[0], sizeof(extData)); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + /* check for completion */ + retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_SET_OPCODE, timeoutMs, &cmdStatusByte); + if (retVal != MYKONOS_ERR_OK) + { + if (cmdStatusByte > 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETCLGCGAIN_TRACK_ARMERRFLAG, + getMykonosErrorMessage(MYKONOS_ERR_SETCLGCGAIN_TRACK_ARMERRFLAG)); + return MYKONOS_ERR_SETCLGCGAIN_TRACK_ARMERRFLAG; + } + + return retVal; + } + + if (cmdStatusByte > 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETCLGCGAIN_TRACK_ARMERRFLAG, + getMykonosErrorMessage(MYKONOS_ERR_SETCLGCGAIN_TRACK_ARMERRFLAG)); + return MYKONOS_ERR_SETCLGCGAIN_TRACK_ARMERRFLAG; + } + + return MYKONOS_ERR_OK; +} + +/** + * \brief This function, when called during RadioOff, will configure VSWR settings + * + * A DPD-enabled transceiver is required for VSWR to be enabled. The VSWR has several user + * adjustable settings that can be configured before running the runInitCals + * with the calMask set for the VSWR init cal. Call this function with desired + * settings set before running the VSWR init cal or enabling VSWR tracking. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * - device->profilesValid + * - device->tx->vswrConfig (All members) + * + * \retval MYKONOS_ERR_CFGVSWR_TXORX_PROFILE_INV ERROR: Tx and ObsRx profiles must be valid to use the VSWR feature + * \retval MYKONOS_ERR_CFGVSWR_NULL_VSWRCFGSTRUCT ERROR: CLGC config structure pointer is null in device->tx->clgcConfig + * \retval MYKONOS_ERR_CFGVSWR_ARMSTATE_ERROR ERROR: ARM is not in the IDLE(radioOff) or Ready state. + */ +mykonosErr_t MYKONOS_configVswr(mykonosDevice_t *device) +{ + uint32_t radioStatus = 0; + mykonosErr_t retVal = MYKONOS_ERR_OK; + uint8_t armFieldValue[16] = {0}; + uint8_t byteOffset = 0; + uint16_t negPnLevel = 0; + + const uint8_t ENABLE_VSWR = 1; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_configVswr()\n"); +#endif + + /* VSWR requires Tx and ORx enabled, throw error if both are not enabled */ + if ((device->profilesValid & (TX_PROFILE_VALID | ORX_PROFILE_VALID)) != (TX_PROFILE_VALID | ORX_PROFILE_VALID)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGVSWR_TXORX_PROFILE_INV, + getMykonosErrorMessage(MYKONOS_ERR_CFGVSWR_TXORX_PROFILE_INV)); + return MYKONOS_ERR_CFGVSWR_TXORX_PROFILE_INV; + } + + if (device->tx->vswrConfig == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGVSWR_NULL_VSWRCFGSTRUCT, + getMykonosErrorMessage(MYKONOS_ERR_CFGVSWR_NULL_VSWRCFGSTRUCT)); + return MYKONOS_ERR_CFGVSWR_NULL_VSWRCFGSTRUCT; + } + + /* read radio state to make sure ARM is in radioOff /IDLE */ + retVal = MYKONOS_getRadioState(device, &radioStatus); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + /* throw error if not in radioOff/IDLE state */ + if (((radioStatus & 0x03) != MYKONOS_ARM_SYSTEMSTATE_IDLE) && ((radioStatus & 0x03) != MYKONOS_ARM_SYSTEMSTATE_READY)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGVSWR_ARMSTATE_ERROR, + getMykonosErrorMessage(MYKONOS_ERR_CFGVSWR_ARMSTATE_ERROR)); + return MYKONOS_ERR_CFGVSWR_ARMSTATE_ERROR; + } + + /* range check valid 3p3 GPIO pin */ + if ((device->tx->vswrConfig->tx1VswrSwitchGpio3p3Pin > 11) || (device->tx->vswrConfig->tx2VswrSwitchGpio3p3Pin > 11)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGVSWR_INV_3P3GPIOPIN, + getMykonosErrorMessage(MYKONOS_ERR_CFGVSWR_INV_3P3GPIOPIN)); + return MYKONOS_ERR_CFGVSWR_INV_3P3GPIOPIN; + } + + armFieldValue[0] = ENABLE_VSWR; + armFieldValue[1] = 0; + armFieldValue[2] = ENABLE_VSWR; + armFieldValue[3] = 0; + armFieldValue[4] = (device->tx->vswrConfig->tx1VswrSwitchGpio3p3Pin & 0xFF); + armFieldValue[5] = 0; + armFieldValue[6] = (device->tx->vswrConfig->tx2VswrSwitchGpio3p3Pin & 0xFF); + armFieldValue[7] = 0; + armFieldValue[8] = (device->tx->vswrConfig->tx1VswrSwitchPolarity > 0) ? 1 : 0; + armFieldValue[9] = 0; + armFieldValue[10] = (device->tx->vswrConfig->tx2VswrSwitchPolarity > 0) ? 1 : 0; + armFieldValue[11] = 0; + armFieldValue[12] = device->tx->vswrConfig->tx1VswrSwitchDelay_us; /* support full 0 to 255 us range */ + armFieldValue[13] = 0; + armFieldValue[14] = device->tx->vswrConfig->tx2VswrSwitchDelay_us; /* support full 0 to 255 us range */ + armFieldValue[15] = 0; + byteOffset = 0; + retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_VSWRCONFIG, byteOffset, &armFieldValue[0], 16); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + /* set VSWR additional delay offset parameter (init cal)*/ + if ((device->tx->vswrConfig->additionalDelayOffset < -64) || (device->tx->vswrConfig->additionalDelayOffset > 64)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGVSWR_INV_VSWR_ADDDELAY, + getMykonosErrorMessage(MYKONOS_ERR_CFGVSWR_INV_VSWR_ADDDELAY)); + return MYKONOS_ERR_CFGVSWR_INV_VSWR_ADDDELAY; + } + + armFieldValue[0] = (device->tx->vswrConfig->additionalDelayOffset & 0xFF); + armFieldValue[1] = (((uint16_t)device->tx->vswrConfig->additionalDelayOffset >> 8) & 0xFF); + byteOffset = 2; + retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_VSWRINIT_CONFIG, byteOffset, &armFieldValue[0], 2); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + if ((device->tx->vswrConfig->pathDelayPnSeqLevel < 1) || (device->tx->vswrConfig->pathDelayPnSeqLevel > 8191)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGVSWR_INV_PNSEQLEVEL, + getMykonosErrorMessage(MYKONOS_ERR_CFGVSWR_INV_PNSEQLEVEL)); + return MYKONOS_ERR_CFGVSWR_INV_PNSEQLEVEL; + } + + /* Set Path Delay PN sequence amplitude - positive and negative (init cal)*/ + armFieldValue[0] = (device->tx->vswrConfig->pathDelayPnSeqLevel & 0xFF); + armFieldValue[1] = ((device->tx->vswrConfig->pathDelayPnSeqLevel >> 8) & 0xFF); + + negPnLevel = ((~device->tx->vswrConfig->pathDelayPnSeqLevel) + 1); /* times -1 */ + armFieldValue[2] = (negPnLevel & 0xFF); + armFieldValue[3] = (((negPnLevel) >> 8) & 0xFF); + byteOffset = 10; + + /* Set for Tx1 channel */ + retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_VSWRINIT_CONFIG, byteOffset, &armFieldValue[0], 4); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + /* Set for Tx2 channel */ + byteOffset = 30; + retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_VSWRINIT_CONFIG, byteOffset, &armFieldValue[0], 4); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + return MYKONOS_ERR_OK; +} + +/* \brief Reads the VSWR config structure from ARM memory + * + * This function reads the VSWR structure + * from ARM memory and returns in the device->tx->vswrConfig structure. + * + * A DPD-enabled transceiver is required for VSWR to be enabled. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * - device->profilesValid + * - device->tx->vswrConfig (All members) + * + * \param device is structure pointer to the Mykonos data structure containing settings + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_GETVSWRCFG_TXORX_PROFILE_INV Error: Tx and ORx profiles must be valid for VSWR functions + * \retval MYKONOS_ERR_GETVSWRCFG_NULL_CFGSTRUCT Error: NULL pointer to device->tx->vswrConfig structure + */ +mykonosErr_t MYKONOS_getVswrConfig(mykonosDevice_t *device) +{ + uint16_t byteOffset = 0; + uint8_t armMem[12] = {0}; + mykonosErr_t retVal = MYKONOS_ERR_OK; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getVswrConfig()\n"); +#endif + + /* VSWR requires Tx and ORx enabled, throw error if both are not enabled */ + if ((device->profilesValid & (TX_PROFILE_VALID | ORX_PROFILE_VALID)) != (TX_PROFILE_VALID | ORX_PROFILE_VALID)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETVSWRCFG_TXORX_PROFILE_INV, + getMykonosErrorMessage(MYKONOS_ERR_GETVSWRCFG_TXORX_PROFILE_INV)); + return MYKONOS_ERR_GETVSWRCFG_TXORX_PROFILE_INV; + } + + if (device->tx->vswrConfig == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETVSWRCFG_NULL_CFGSTRUCT, + getMykonosErrorMessage(MYKONOS_ERR_GETVSWRCFG_NULL_CFGSTRUCT)); + return MYKONOS_ERR_GETVSWRCFG_NULL_CFGSTRUCT; + } + + byteOffset = 4; + retVal = MYKONOS_readArmConfig(device, MYKONOS_ARM_OBJECTID_VSWRCONFIG, byteOffset, &armMem[0], sizeof(armMem)); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + device->tx->vswrConfig->tx1VswrSwitchGpio3p3Pin = armMem[0]; + device->tx->vswrConfig->tx2VswrSwitchGpio3p3Pin = armMem[2]; + device->tx->vswrConfig->tx1VswrSwitchPolarity = armMem[4]; + device->tx->vswrConfig->tx2VswrSwitchPolarity = armMem[6]; + device->tx->vswrConfig->tx1VswrSwitchDelay_us = armMem[8]; + device->tx->vswrConfig->tx2VswrSwitchDelay_us = armMem[10]; + + byteOffset = 2; + retVal = MYKONOS_readArmConfig(device, MYKONOS_ARM_OBJECTID_VSWRINIT_CONFIG, byteOffset, &armMem[0], 2); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + device->tx->vswrConfig->additionalDelayOffset = (int16_t)(((uint16_t)(armMem[1]) << 8) | (uint16_t)(armMem[0])); + + byteOffset = 10; + retVal = MYKONOS_readArmConfig(device, MYKONOS_ARM_OBJECTID_VSWRINIT_CONFIG, byteOffset, &armMem[0], 2); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + device->tx->vswrConfig->pathDelayPnSeqLevel = (((uint16_t)(armMem[1]) << 8) | (uint16_t)(armMem[0])); + + return MYKONOS_ERR_OK; +} + +/** + * \brief This function reads the VSWR calibration status from the Mykonos ARM processor. + * + * The VSWR Status is read back from the ARM processor and + * returned in the function parameter vswrStatus. + * + * A DPD-enabled transceiver is required for this feature to be enabled. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device is structure pointer to the Mykonos data structure containing settings + * \param txChannel Desired Transmit channel to read back VSWR status for (Valid ENUM values: TX1 or TX2 only) + * \param vswrStatus Pointer to a structure to return the status information to + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_GETVSWRSTATUS_NULLPARAM vswrStatus function parameter is a NULL pointer + * \retval MYKONOS_ERR_GETVSWRSTATUS_INV_CH txChannel parameter is a non supported value. + * \retval MYKONOS_ERR_GETVSWRSTATUS_ARMERRFLAG ARM reported an error while processing the GET ARM command + */ +mykonosErr_t MYKONOS_getVswrStatus(mykonosDevice_t *device, mykonosTxChannels_t txChannel, mykonosVswrStatus_t *vswrStatus) +{ + uint8_t extData[3] = {MYKONOS_ARM_OBJECTID_CAL_STATUS, MYKONOS_ARM_OBJECTID_VSWRCONFIG, 0}; + uint8_t armData[64] = {0}; + uint32_t timeoutMs = 0; + uint8_t cmdStatusByte = 0; + uint32_t offset = 0; + mykonosErr_t retVal = MYKONOS_ERR_OK; + uint8_t channelSelect = 0; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getVswrStatus()\n"); +#endif + + if (vswrStatus == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETVSWRSTATUS_NULLPARAM, + getMykonosErrorMessage(MYKONOS_ERR_GETVSWRSTATUS_NULLPARAM)); + return MYKONOS_ERR_GETVSWRSTATUS_NULLPARAM; + } + + switch (txChannel) + { + case TX1: + channelSelect = 0; + break; + case TX2: + channelSelect = 1; + break; + default: + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETVSWRSTATUS_INV_CH, + getMykonosErrorMessage(MYKONOS_ERR_GETVSWRSTATUS_INV_CH)); + return MYKONOS_ERR_GETVSWRSTATUS_INV_CH; + } + } + + extData[2] = channelSelect; + + retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_GET_OPCODE, &extData[0], sizeof(extData)); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + timeoutMs = 1000; + retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_GET_OPCODE, timeoutMs, &cmdStatusByte); + if (retVal != MYKONOS_ERR_OK) + { + /* throw more specific error message instead of returning error code from waitArmCmdStatus */ + if (cmdStatusByte > 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETVSWRSTATUS_ARMERRFLAG, + getMykonosErrorMessage(MYKONOS_ERR_GETVSWRSTATUS_ARMERRFLAG)); + return MYKONOS_ERR_GETVSWRSTATUS_ARMERRFLAG; + } + + return retVal; + } + + if (cmdStatusByte > 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETVSWRSTATUS_ARMERRFLAG, + getMykonosErrorMessage(MYKONOS_ERR_GETVSWRSTATUS_ARMERRFLAG)); + return MYKONOS_ERR_GETVSWRSTATUS_ARMERRFLAG; + } + + /* read status from ARM memory */ + offset = 0; + retVal = MYKONOS_readArmMem(device, (MYKONOS_ADDR_ARM_START_DATA_ADDR + offset), &armData[0], sizeof(armData), 1); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + vswrStatus->errorStatus = ((uint32_t)(armData[3]) << 24) | ((uint32_t)(armData[2]) << 16) | ((uint32_t)(armData[1]) << 8) | (uint32_t)(armData[0]); + vswrStatus->forwardGainRms_dB = (int32_t)(((uint32_t)(armData[23]) << 24) | ((uint32_t)(armData[22]) << 16) | ((uint32_t)(armData[21]) << 8) | (uint32_t)(armData[20])); + vswrStatus->forwardGainReal = (int32_t)(((uint32_t)(armData[27]) << 24) | ((uint32_t)(armData[26]) << 16) | ((uint32_t)(armData[25]) << 8) | (uint32_t)(armData[24])); + vswrStatus->forwardGainImag = (int32_t)(((uint32_t)(armData[31]) << 24) | ((uint32_t)(armData[30]) << 16) | ((uint32_t)(armData[29]) << 8) | (uint32_t)(armData[28])); + vswrStatus->reflectedGainRms_dB = (int32_t)(((uint32_t)(armData[35]) << 24) | ((uint32_t)(armData[34]) << 16) | ((uint32_t)(armData[33]) << 8) | (uint32_t)(armData[32])); + vswrStatus->reflectedGainReal = (int32_t)(((uint32_t)(armData[39]) << 24) | ((uint32_t)(armData[38]) << 16) | ((uint32_t)(armData[37]) << 8) | (uint32_t)(armData[36])); + vswrStatus->reflectedGainImag = (int32_t)(((uint32_t)(armData[43]) << 24) | ((uint32_t)(armData[42]) << 16) | ((uint32_t)(armData[41]) << 8) | (uint32_t)(armData[40])); + vswrStatus->trackCount = ((uint32_t)(armData[63]) << 24) | ((uint32_t)(armData[62]) << 16) | ((uint32_t)(armData[61]) << 8) | (uint32_t)(armData[60]); + vswrStatus->vswr_forward_tx_rms = (int32_t)(((uint32_t)(armData[47]) << 24) | ((uint32_t)(armData[46]) << 16) | ((uint32_t)(armData[45]) << 8) | (uint32_t)(armData[44])); + vswrStatus->vswr_forward_orx_rms = (int32_t)(((uint32_t)(armData[51]) << 24) | ((uint32_t)(armData[50]) << 16) | ((uint32_t)(armData[49]) << 8) | (uint32_t)(armData[48])); + vswrStatus->vswr_reflection_tx_rms = (int32_t)(((uint32_t)(armData[55]) << 24) | ((uint32_t)(armData[54]) << 16) | ((uint32_t)(armData[53]) << 8) | (uint32_t)(armData[52])); + vswrStatus->vswr_reflection_orx_rms = (int32_t)(((uint32_t)(armData[59]) << 24) | ((uint32_t)(armData[58]) << 16) | ((uint32_t)(armData[57]) << 8) | (uint32_t)(armData[56])); + + return MYKONOS_ERR_OK; +} + +/** + * \brief Read from the Mykonos ARM program or data memory + * + * Valid memory addresses are: Program Memory (0x01000000 - 0x01017FFF), + * Data Memory (0x20000000 - 0x2000FFFF) + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * - device->spiSettings + * + * \param device is structure pointer to the Mykonos data structure containing settings + * \param address The 32bit ARM address to read from. + * \param returnData Byte(uint8_t) array containing the data read from the ARM memory. + * \param bytesToRead Number of bytes in the returnData array. + * \param autoIncrement is boolean flag to enable or disable autoincrement of ARM register address + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_READARMMEM_INV_ADDR_PARM ARM memory address is out of range + * + */ +mykonosErr_t MYKONOS_readArmMem(mykonosDevice_t *device, uint32_t address, uint8_t *returnData, uint32_t bytesToRead, uint8_t autoIncrement) +{ + uint8_t dataMem; + uint32_t i; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_readArmMem()\n"); +#endif + + /* check that start and stop address are in valid range */ + if ((!(address >= MYKONOS_ADDR_ARM_START_PROG_ADDR && address <= MYKONOS_ADDR_ARM_END_PROG_ADDR)) + && !(address >= MYKONOS_ADDR_ARM_START_DATA_ADDR && address <= MYKONOS_ADDR_ARM_END_DATA_ADDR)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_READARMMEM_INV_ADDR_PARM, + getMykonosErrorMessage(MYKONOS_ERR_READARMMEM_INV_ADDR_PARM)); + return MYKONOS_ERR_READARMMEM_INV_ADDR_PARM; + } + + if ((!(((address + bytesToRead - 1) >= MYKONOS_ADDR_ARM_START_PROG_ADDR) && (address + bytesToRead - 1) <= MYKONOS_ADDR_ARM_END_PROG_ADDR)) + && (!(((address + bytesToRead - 1) >= MYKONOS_ADDR_ARM_START_DATA_ADDR) && (address + bytesToRead - 1) <= MYKONOS_ADDR_ARM_END_DATA_ADDR))) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_READARMMEM_INV_ADDR_PARM, + getMykonosErrorMessage(MYKONOS_ERR_READARMMEM_INV_ADDR_PARM)); + return MYKONOS_ERR_READARMMEM_INV_ADDR_PARM; + } + + if (address >= MYKONOS_ADDR_ARM_START_DATA_ADDR && address <= MYKONOS_ADDR_ARM_END_DATA_ADDR) + { + dataMem = 1; + } + else + { + dataMem = 0; + } + + /* NOT assuming auto increment bit is already set from MYKONOS_initARM function call */ + /* setting auto increment address bit if autoIncrement evaluates true */ + if (autoIncrement) + { + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_ARM_CTL_1, 0x01, 0x04, 2); + } + else + { + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_ARM_CTL_1, 0x00, 0x04, 2); + } + + /* setting up for ARM read */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_ARM_CTL_1, 0x01, 0x20, 5); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_ADDR_BYTE_0, (uint8_t)((address) >> 2)); /* write address[9:2] */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_ADDR_BYTE_1, (uint8_t)(address >> 10) | (uint8_t)(dataMem << 7)); /* write address[15:10] */ + + /* start read-back at correct byte offset */ + /* read data is located at SPI address 0xD04=data[7:0], 0xD05=data[15:8], 0xD06=data[23:16], 0xD07=data[31:24]. */ + /* with address auto increment set, after xD07 is read, the address will automatically increment */ + /* without address auto increment set, 0x4 must be added to the address for correct indexing */ + if (autoIncrement) + { + for (i = 0; i < bytesToRead; i++) + { + CMB_SPIReadByte(device->spiSettings, (MYKONOS_ADDR_ARM_DATA_BYTE_0 | (((address & 0x3) + i) % 4)), &returnData[i]); + } + } + else + { + for (i = 0; i < bytesToRead; i++) + { + CMB_SPIReadByte(device->spiSettings, (MYKONOS_ADDR_ARM_DATA_BYTE_0 | (((address & 0x3) + i) % 4)), &returnData[i]); + + if ((MYKONOS_ADDR_ARM_DATA_BYTE_0 | (((address & 0x3) + i) % 4)) == MYKONOS_ADDR_ARM_DATA_BYTE_3) + { + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_ADDR_BYTE_0, (uint8_t)(((address + 0x4) & 0x3FF) >> 2)); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_ADDR_BYTE_1, ((address + 0x4) & 0x1FC00U) >> 10 | (uint8_t)(dataMem << 7)); + } + } + } + + return MYKONOS_ERR_OK; +} + +/** + * \brief Write to the Mykonos ARM program or data memory + * + * Valid memory addresses are: Program Memory (0x01000000 - 0x01017FFF), + * Data Memory (0x20000000 - 0x2000FFFF) + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * - device->spiSettings + * + * \param device is structure pointer to the Mykonos data structure containing settings + * \param address The 32bit ARM address to write to. + * \param data Byte(uint8_t) array containing the data to write to the ARM memory. + * \param byteCount Number of bytes in the data array. + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_WRITEARMMEM_NULL_PARM Function parameter data has NULL pointer when byteCount is >0 + * \retval MYKONOS_ERR_WRITEARMMEM_INV_ADDR_PARM ARM memory address is out of range of valid ARM memory + */ +mykonosErr_t MYKONOS_writeArmMem(mykonosDevice_t *device, uint32_t address, uint8_t *data, uint32_t byteCount) +{ + /* write address, then data with auto increment enabled. */ + uint8_t dataMem; + uint32_t i; + +#if MYK_ENABLE_SPIWRITEARRAY == 1 + uint32_t addrIndex = 0; + uint32_t dataIndex = 0; + uint32_t spiBufferSize = MYK_SPIWRITEARRAY_BUFFERSIZE; + uint16_t addrArray[MYK_SPIWRITEARRAY_BUFFERSIZE] = {0}; +#endif + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_writeArmMem()\n"); +#endif + + if ((data == NULL) && (byteCount > 0)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_WRITEARMMEM_NULL_PARM, + getMykonosErrorMessage(MYKONOS_ERR_WRITEARMMEM_NULL_PARM)); + return MYKONOS_ERR_WRITEARMMEM_NULL_PARM; + } + + if ((!(address >= MYKONOS_ADDR_ARM_START_PROG_ADDR && address <= MYKONOS_ADDR_ARM_END_PROG_ADDR)) + && !(address >= MYKONOS_ADDR_ARM_START_DATA_ADDR && address <= MYKONOS_ADDR_ARM_END_DATA_ADDR)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_WRITEARMMEM_INV_ADDR_PARM, + getMykonosErrorMessage(MYKONOS_ERR_WRITEARMMEM_INV_ADDR_PARM)); + return MYKONOS_ERR_WRITEARMMEM_INV_ADDR_PARM; + } + + if ((!(((address + byteCount - 1) >= MYKONOS_ADDR_ARM_START_PROG_ADDR) && ((address + byteCount - 1) <= MYKONOS_ADDR_ARM_END_PROG_ADDR))) + && (!(((address + byteCount - 1) >= MYKONOS_ADDR_ARM_START_DATA_ADDR) && ((address + byteCount - 1) <= MYKONOS_ADDR_ARM_END_DATA_ADDR)))) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_WRITEARMMEM_INV_ADDR_PARM, + getMykonosErrorMessage(MYKONOS_ERR_WRITEARMMEM_INV_ADDR_PARM)); + return MYKONOS_ERR_WRITEARMMEM_INV_ADDR_PARM; + } + + if (address >= MYKONOS_ADDR_ARM_START_DATA_ADDR && address <= MYKONOS_ADDR_ARM_END_DATA_ADDR) + { + dataMem = 1; + } + else + { + dataMem = 0; + } + + /* set auto increment address bit */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_ARM_CTL_1, 0x01, 0x04, 2); + + /* writing the address */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_ARM_CTL_1, 0x00, 0x20, 5); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_ADDR_BYTE_0, (uint8_t)((address) >> 2)); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_ADDR_BYTE_1, (uint8_t)(address >> 10) | (uint8_t)(dataMem << 7)); + + /* start write at correct byte offset */ + /* write data is located at SPI address 0xD04=data[7:0], 0xD05=data[15:8], 0xD06=data[23:16], 0xD07=data[31:24] */ + /* with address auto increment set, after x407 is written, the address will automatically increment */ + +#if (MYK_ENABLE_SPIWRITEARRAY == 0) + + for (i = 0; i < byteCount; i++) + { + CMB_SPIWriteByte(device->spiSettings, (MYKONOS_ADDR_ARM_DATA_BYTE_0 | (((address & 0x3) + i) % 4)), data[i]); + } + +#elif (MYK_ENABLE_SPIWRITEARRAY == 1) + + addrIndex = 0; + dataIndex = 0; + for (i = 0; i < byteCount; i++) + { + addrArray[addrIndex++] = (MYKONOS_ADDR_ARM_DATA_BYTE_0 | (((address & 0x3) + i) % 4)); + + if (addrIndex == spiBufferSize) + { + CMB_SPIWriteBytes(device->spiSettings, &addrArray[0], &data[dataIndex], addrIndex); + dataIndex = dataIndex + addrIndex; + addrIndex = 0; + } + } + + if (addrIndex > 0) + { + CMB_SPIWriteBytes(device->spiSettings, &addrArray[0], &data[dataIndex], addrIndex); + } + +#endif + + return MYKONOS_ERR_OK; +} + +/** + * \brief Low level helper function used by Mykonos API to write the ARM memory config structures + * + * Normally this function should not be required to be used directly by the BBIC. This is a helper + * function used by other Mykonos API commands to write settings into the ARM memory. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * - device->spiSettings + * + * \param device is structure pointer to the Mykonos data structure containing settings + * \param objectId ARM id of a particular structure or setting in ARM memory + * \param offset Byte offset from the start of the objectId's memory location in ARM memory + * \param data A byte array containing data to write to the ARM memory buffer. + * \param byteCount Number of bytes in the data array (Valid size = 1-255 bytes) + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_WRITEARMCFG_ARMERRFLAG ARM write config command failed with a nonzero error code + */ +mykonosErr_t MYKONOS_writeArmConfig(mykonosDevice_t *device, uint8_t objectId, uint16_t offset, uint8_t *data, uint8_t byteCount) +{ + mykonosErr_t retVal = MYKONOS_ERR_OK; + uint8_t extendedData[4] = {0}; /* ARM Object id, byte offset LSB, offset MSB = 0, copy 2 bytes */ + uint32_t timeoutMs = 1000; + uint8_t cmdStatusByte = 0; + + retVal = MYKONOS_writeArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR, &data[0], byteCount); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + extendedData[0] = objectId; + extendedData[1] = (offset & 0xFF); + extendedData[2] = ((offset >> 8) & 0xFF); + extendedData[3] = byteCount; + retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_WRITECFG_OPCODE, &extendedData[0], sizeof(extendedData)); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_WRITECFG_OPCODE, timeoutMs, &cmdStatusByte); + if (retVal != MYKONOS_ERR_OK) + { + if (cmdStatusByte > 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_WRITEARMCFG_ARMERRFLAG, + getMykonosErrorMessage(MYKONOS_ERR_WRITEARMCFG_ARMERRFLAG)); + return MYKONOS_ERR_WRITEARMCFG_ARMERRFLAG; + } + + return retVal; + } + + if (cmdStatusByte > 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_WRITEARMCFG_ARMERRFLAG, + getMykonosErrorMessage(MYKONOS_ERR_WRITEARMCFG_ARMERRFLAG)); + return MYKONOS_ERR_WRITEARMCFG_ARMERRFLAG; + } + + return MYKONOS_ERR_OK; +} + +/** + * \brief Low level helper function used by Mykonos API to read the ARM memory config structures + * + * Normally this function should not be required to be used directly by the BBIC. This is a helper + * function used by other Mykonos API commands to read settings from the ARM memory. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * - device->spiSettings + * + * \param device is structure pointer to the Mykonos data structure containing settings + * \param objectId ARM id of a particular structure or setting in ARM memory + * \param offset Byte offset from the start of the objectId's memory location in ARM memory + * \param data A byte array containing data to write to the ARM memory buffer. + * \param byteCount Number of bytes in the data array (Valid size = 1-255 bytes) + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_READARMCFG_ARMERRFLAG ARM read config command failed with a nonzero error code + */ +mykonosErr_t MYKONOS_readArmConfig(mykonosDevice_t *device, uint8_t objectId, uint16_t offset, uint8_t *data, uint8_t byteCount) +{ + mykonosErr_t retVal = MYKONOS_ERR_OK; + uint8_t extendedData[4] = {0}; /* ARM Object id, byte offset LSB, offset MSB = 0, copy 2 bytes */ + uint32_t timeoutMs = 1000; + uint8_t cmdStatusByte = 0; + const uint8_t AUTO_INCREMENT = 1; + extendedData[0] = objectId; + extendedData[1] = (offset & 0xFF); + extendedData[2] = ((offset >> 8) & 0xFF); + extendedData[3] = byteCount; + + retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_READCFG_OPCODE, &extendedData[0], sizeof(extendedData)); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_READCFG_OPCODE, timeoutMs, &cmdStatusByte); + if (retVal != MYKONOS_ERR_OK) + { + if (cmdStatusByte > 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_READARMCFG_ARMERRFLAG, + getMykonosErrorMessage(MYKONOS_ERR_READARMCFG_ARMERRFLAG)); + return MYKONOS_ERR_READARMCFG_ARMERRFLAG; + } + + return retVal; + } + + if (cmdStatusByte > 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_READARMCFG_ARMERRFLAG, + getMykonosErrorMessage(MYKONOS_ERR_READARMCFG_ARMERRFLAG)); + return MYKONOS_ERR_READARMCFG_ARMERRFLAG; + } + + retVal = MYKONOS_readArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR, &data[0], byteCount, AUTO_INCREMENT); + + return retVal; +} + +/** + * \brief Sends a command to the Mykonos ARM processor + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * - device->spiSettings + * + * \param device is structure pointer to the Mykonos data structure containing settings + * \param opCode Value (0-30, even only) indicating the desired function to run in the ARM. + * \param extendedData A byte array containing extended data to write to the ARM command interface. + * \param extendedDataNumBytes Number of bytes in the extendedData array (Valid size = 0-4 bytes) + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_ARMCMD_NULL_PARM Function parameter extendedData is NULL and extendedDataNumBytes is positive + * \retval MYKONOS_ERR_ARMCMD_INV_OPCODE_PARM ARM opcode is out of range (valid 0-30, even only) + * \retval MYKONOS_ERR_ARMCMD_INV_NUMBYTES_PARM Number of extended bytes parameter is out of range (valid 0-4) + * \retval MYKONOS_ERR_TIMEDOUT_ARMMAILBOXBUSY ARM control interface is busy, command could not be executed by ARM + */ +mykonosErr_t MYKONOS_sendArmCommand(mykonosDevice_t *device, uint8_t opCode, uint8_t *extendedData, uint8_t extendedDataNumBytes) +{ + uint8_t armCommandBusy = 0; + uint8_t i = 0; + uint16_t extCmdByteStartAddr = MYKONOS_ADDR_ARM_EXT_CMD_BYTE_1; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_sendArmCommand()\n"); +#endif + + if ((extendedData == NULL) && (extendedDataNumBytes > 0)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_ARMCMD_NULL_PARM, getMykonosErrorMessage(MYKONOS_ERR_ARMCMD_NULL_PARM)); + return MYKONOS_ERR_ARMCMD_NULL_PARM; + } + + /* check for even-numbered opCodes only including opcode 0, but not must be greater than opCode 30 */ + if ((opCode != 0) && ((opCode % 2) || (opCode > 30))) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_ARMCMD_INV_OPCODE_PARM, + getMykonosErrorMessage(MYKONOS_ERR_ARMCMD_INV_OPCODE_PARM)); + return MYKONOS_ERR_ARMCMD_INV_OPCODE_PARM; + } + + /* the number of valid extended data bytes is from 0-4 */ + if (extendedDataNumBytes > 4) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_ARMCMD_INV_NUMBYTES_PARM, + getMykonosErrorMessage(MYKONOS_ERR_ARMCMD_INV_NUMBYTES_PARM)); + return MYKONOS_ERR_ARMCMD_INV_NUMBYTES_PARM; + } + + /* setting a 2 sec timeout for mailbox busy bit to be clear (can't send an arm mailbox command until mailbox is ready) */ + CMB_setTimeout_ms(2000); + + do + { + CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_ARM_CMD, &armCommandBusy, 0x80, 7); + + if (CMB_hasTimeoutExpired()) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_TIMEDOUT_ARMMAILBOXBUSY, + getMykonosErrorMessage(MYKONOS_ERR_TIMEDOUT_ARMMAILBOXBUSY)); + return MYKONOS_ERR_TIMEDOUT_ARMMAILBOXBUSY; + } + } while (armCommandBusy); + + if (extendedDataNumBytes) + { + for (i = 0; i < extendedDataNumBytes; i++) + { + CMB_SPIWriteByte(device->spiSettings, extCmdByteStartAddr + i, extendedData[i]); + } + } + + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_CMD, opCode); + + return MYKONOS_ERR_OK; +} + +/** + * \brief Reads the Mykonos ARM 64-bit command status register + * + * A 64-bit status register consisting of a pending bit and three-bit error type is read one byte at + * a time for opcodes 0-30. The function parses the pending bits and error bits into + * two (2) separate 16-bit words containing pending bits, and error bits if the error type > 0 + * The words are weighted according to each even-numbered opcode from 0-30, + * where, 0x0001 = opcode '0', 0x0002 = opcode '2', 0x0004 = opcode '4', 0x0008 = opcode '6' and so on. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device is a pointer to the device settings structure + * \param errorWord 16-bit error word comprised of weighted bits according to each opcode number + * The weighted bit = '1' if error type > 0, '0' if OK + * \param statusWord 16-bit pending bits word comprised of weighted bits according to each opcode number + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_READARMCMDSTATUS_NULL_PARM Function parameters errorWord or statusWord have a NULL pointer + */ +mykonosErr_t MYKONOS_readArmCmdStatus(mykonosDevice_t *device, uint16_t *errorWord, uint16_t *statusWord) +{ + uint8_t i = 0; + uint8_t bytes[8] = {0}; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_readArmCmdStatus()\n"); +#endif + + if (errorWord == NULL || statusWord == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_READARMCMDSTATUS_NULL_PARM, + getMykonosErrorMessage(MYKONOS_ERR_READARMCMDSTATUS_NULL_PARM)); + return MYKONOS_ERR_READARMCMDSTATUS_NULL_PARM; + } + + /* making sure the errorWord and statusWord are clear */ + *errorWord = 0; + *statusWord = 0; + + /* read in the entire 64-bit status register into a byte array for parsing */ + for (i = 0; i < 8; i++) + { + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_ARM_CMD_STATUS_0 + i, &bytes[i]); + } + + /* parse the byte array for pending bits and error types and generate statusWord and errorWord bits */ + for (i = 0; i < 8; i++) + { + *statusWord |= (uint16_t)((uint16_t)(((bytes[i] & 0x10) >> 3) | (bytes[i] & 0x01)) << (i * 2)); + + if (bytes[i] & 0x0E) + { + *errorWord |= (uint16_t)(0x0001 << (i * 2)); + } + else if (bytes[i] & 0xE0) + { + *errorWord |= (uint16_t)(0x0002 << (i * 2)); + } + } + + return MYKONOS_ERR_OK; +} + +/** + * \brief Isolated byte read of the Mykonos ARM 64-bit command status register based on the opcode + * + * A single byte read is performed on the 64-bit command status register according to + * the opcode of interest. The pending bit and the error type are extracted from the status + * register and returned as a single byte in the lower nibble. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device is a pointer to the device settings structure + * \param opCode Valid values are even increments from 0-30. The ARM opCode is used to determine which status register byte to read + * \param cmdStatByte returns cmdStatByte[3:1] = error type, cmdStatByte[0] = pending flag for selected opCode + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_READARMCMDSTATUSBYTE_NULL_PARM Function parameter cmdStatByte has NULL pointer + * \retval MYKONOS_ERR_READARMCMDSTATUS_INV_OPCODE_PARM ARM opcode is out of range (valid 0-30, even only) + */ +mykonosErr_t MYKONOS_readArmCmdStatusByte(mykonosDevice_t *device, uint8_t opCode, uint8_t *cmdStatByte) +{ + uint8_t cmdByteIndex = 0; + uint8_t cmdByte = 0; + +#if 0 +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_readArmCmdStatByte()\n"); +#endif +#endif + + if (cmdStatByte == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_READARMCMDSTATUSBYTE_NULL_PARM, + getMykonosErrorMessage(MYKONOS_ERR_READARMCMDSTATUSBYTE_NULL_PARM)); + return MYKONOS_ERR_READARMCMDSTATUSBYTE_NULL_PARM; + } + + /* check for even-numbered opCodes only including opcode 0, but not must be greater than opCode 30 */ + if ((opCode != 0) && ((opCode % 2) || (opCode > 30))) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_READARMCMDSTATUS_INV_OPCODE_PARM, + getMykonosErrorMessage(MYKONOS_ERR_READARMCMDSTATUS_INV_OPCODE_PARM)); + return MYKONOS_ERR_READARMCMDSTATUS_INV_OPCODE_PARM; + } + else + { + cmdByteIndex = (opCode / 4); + + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_ARM_CMD_STATUS_0 + cmdByteIndex, &cmdByte); + + if ((opCode / 2) % 2) + { + *cmdStatByte = ((cmdByte >> 4) & 0x0F); + } + else + { + *cmdStatByte = (cmdByte & 0x0F); + } + + return MYKONOS_ERR_OK; + } +} + +/** + * \brief Mykonos ARM command status wait function polls command status until opcode completes + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device is a pointer to the device settings structure + * \param opCode Valid values are even increments from 0-30. The ARM opCode is used to determine which pending bit to wait for + * \param timeoutMs conveys the time-out period in milliseconds + * \param cmdStatByte returns cmdStatByte[3:1] = error type, cmdStatByte[0] = pending flag for selected opCode + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_ARMCMDSTATUS_NULL_PARM Function parameter cmdStatByte has NULL pointer + * \retval MYKONOS_ERR_ARMCMDSTATUS_INV_OPCODE_PARM Invalid ARM opcode (valid 0-30, even numbers only) + * \retval MYKONOS_ERR_ARMCMDSTATUS_ARMERROR ARM Mailbox error flag for requested opcode returned a nonzero error flag + * \retval MYKONOS_ERR_WAITARMCMDSTATUS_TIMEOUT Timeout occurred before ARM command completed + */ +mykonosErr_t MYKONOS_waitArmCmdStatus(mykonosDevice_t *device, uint8_t opCode, uint32_t timeoutMs, uint8_t *cmdStatByte) +{ + mykonosErr_t retVal = MYKONOS_ERR_OK; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_waitArmCmdStatus()\n"); +#endif + + if (cmdStatByte == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_ARMCMDSTATUS_NULL_PARM, + getMykonosErrorMessage(MYKONOS_ERR_ARMCMDSTATUS_NULL_PARM)); + return MYKONOS_ERR_ARMCMDSTATUS_NULL_PARM; + } + + /* check for even-numbered opCodes only including opcode 0, but not must be greater than opCode 30 */ + if ((opCode != 0) && ((opCode % 2) || (opCode > 30))) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_ARMCMDSTATUS_INV_OPCODE_PARM, + getMykonosErrorMessage(MYKONOS_ERR_ARMCMDSTATUS_INV_OPCODE_PARM)); + return MYKONOS_ERR_ARMCMDSTATUS_INV_OPCODE_PARM; + } + + /* start wait */ + CMB_setTimeout_ms(timeoutMs); + + do + { + retVal = MYKONOS_readArmCmdStatusByte(device, opCode, cmdStatByte); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + /* If error flag is non zero in [3:1], - return error */ + if ((*cmdStatByte & 0x0E) > 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_ARMCMDSTATUS_ARMERROR, + getMykonosErrorMessage(MYKONOS_ERR_ARMCMDSTATUS_ARMERROR)); + return MYKONOS_ERR_ARMCMDSTATUS_ARMERROR; + } + + if (CMB_hasTimeoutExpired()) + { + return MYKONOS_ERR_WAITARMCMDSTATUS_TIMEOUT; + } + } while (*cmdStatByte & 0x01); + + return MYKONOS_ERR_OK; +} + +/** + * \brief Mykonos ARM configuration write + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device is a pointer to the device settings structure + * + * \retval MYKONOS_ERR_OK Function completed successfully + */ +mykonosErr_t MYKONOS_writeArmProfile(mykonosDevice_t *device) +{ + const uint8_t length = 100; + + int32_t i = 0; + uint8_t vcoDiv = 0; + uint8_t hsDiv = 0; + uint16_t channelsEnabled = 0; + uint8_t cfgData[100] = {0}; + + mykonosErr_t retVal = MYKONOS_ERR_OK; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_writeArmConfig()\n"); +#endif + + /* reading in required mykonosDevice_t structure data into array - not pretty but it works */ + for (i = 0; i < 4; i++) + { + cfgData[i] = (uint8_t)(((device->clocks->deviceClock_kHz * 1000) >> (i * 8)) & 0x000000FF); + } + + for (i = 4; i < 8; i++) + { + cfgData[i] = (uint8_t)(((device->clocks->clkPllVcoFreq_kHz) >> ((i - 4) * 8)) & 0x000000FF); + } + + vcoDiv = (uint8_t)(device->clocks->clkPllVcoDiv); + hsDiv = device->clocks->clkPllHsDiv; + + cfgData[8] = vcoDiv; /* uint8_t vco_div */ + cfgData[9] = hsDiv; /* uint8_t hs_div */ + + channelsEnabled |= ((uint16_t)device->tx->txChannels & 0x03); + channelsEnabled |= ((uint16_t)device->rx->rxChannels & 0x03) << 2; + if (device->profilesValid & ORX_PROFILE_VALID) + { + channelsEnabled |= (((uint16_t)device->obsRx->obsRxChannelsEnable & 3) << 4); + } + + if (device->profilesValid & SNIFF_PROFILE_VALID) + { + channelsEnabled |= ((((uint16_t)device->obsRx->obsRxChannelsEnable >> 2) & 7) << 6); + } + + for (i = 10; i < 12; i++) + { + cfgData[i] = (uint8_t)((channelsEnabled >> ((i - 10) * 8)) & 0xFF); + } + + cfgData[12] = ((device->rx->rxPllUseExternalLo & 0x01) << 1) | (device->tx->txPllUseExternalLo & 0x01); + cfgData[13] = 0x00; /* Not used...padding */ + cfgData[14] = 0x00; /* Not used...padding */ + cfgData[15] = 0x00; /* Not used...padding */ + + if (device->profilesValid & TX_PROFILE_VALID) + { + /* start of Tx profile data */ + cfgData[16] = (uint8_t)device->tx->txProfile->dacDiv; + cfgData[17] = device->tx->txProfile->txFirInterpolation; + cfgData[18] = device->tx->txProfile->thb1Interpolation; + cfgData[19] = device->tx->txProfile->thb2Interpolation; + + for (i = 20; i < 24; i++) + { + cfgData[i] = (uint8_t)(((device->tx->txProfile->iqRate_kHz * 1000) >> ((i - 20) * 8)) & 0x000000FF); + } + + for (i = 24; i < 28; i++) + { + cfgData[i] = (uint8_t)(((device->tx->txProfile->primarySigBandwidth_Hz) >> ((i - 24) * 8)) & 0x000000FF); + } + + for (i = 28; i < 32; i++) + { + cfgData[i] = (uint8_t)(((device->tx->txProfile->rfBandwidth_Hz) >> ((i - 28) * 8)) & 0x000000FF); + } + + for (i = 32; i < 36; i++) + { + cfgData[i] = (uint8_t)(((device->tx->txProfile->txDac3dBCorner_kHz) >> ((i - 32) * 8)) & 0x000000FF); + } + + for (i = 36; i < 40; i++) + { + cfgData[i] = (uint8_t)(((device->tx->txProfile->txBbf3dBCorner_kHz * 1000) >> ((i - 36) * 8)) & 0x000000FF); + } + } + else + { + cfgData[16] = 0; + cfgData[17] = 0; + cfgData[18] = 0; + cfgData[19] = 0; + cfgData[20] = 0; + cfgData[21] = 0; + cfgData[22] = 0; + cfgData[23] = 0; + cfgData[24] = 0; + cfgData[25] = 0; + cfgData[26] = 0; + cfgData[27] = 0; + cfgData[28] = 0; + cfgData[29] = 0; + cfgData[30] = 0; + cfgData[31] = 0; + cfgData[32] = 0; + cfgData[33] = 0; + cfgData[34] = 0; + cfgData[35] = 0; + cfgData[36] = 0; + cfgData[37] = 0; + cfgData[38] = 0; + cfgData[39] = 0; + } + + if (device->profilesValid & RX_PROFILE_VALID) + { + /* start of Rx profile data */ + cfgData[40] = device->rx->rxProfile->adcDiv; + cfgData[41] = device->rx->rxProfile->rxFirDecimation; + cfgData[42] = device->rx->rxProfile->rxDec5Decimation; + cfgData[43] = device->rx->rxProfile->rhb1Decimation; + + for (i = 44; i < 48; i++) + { + cfgData[i] = (uint8_t)(((device->rx->rxProfile->iqRate_kHz * 1000) >> ((i - 44) * 8)) & 0x000000FF); + } + + for (i = 48; i < 52; i++) + { + /* sig bw placeholder */ + cfgData[i] = (uint8_t)(((device->rx->rxProfile->rfBandwidth_Hz) >> ((i - 48) * 8)) & 0x000000FF); + } + + for (i = 52; i < 56; i++) + { + cfgData[i] = (uint8_t)(((device->rx->rxProfile->rfBandwidth_Hz) >> ((i - 52) * 8)) & 0x000000FF); + } + + for (i = 56; i < 60; i++) + { + cfgData[i] = (uint8_t)(((device->rx->rxProfile->rxBbf3dBCorner_kHz * 1000) >> ((i - 56) * 8)) & 0x000000FF); + } + } + else + { + cfgData[40] = 0; + cfgData[41] = 0; + cfgData[42] = 0; + cfgData[43] = 0; + cfgData[44] = 0; + cfgData[45] = 0; + cfgData[46] = 0; + cfgData[47] = 0; + cfgData[48] = 0; + cfgData[49] = 0; + cfgData[50] = 0; + cfgData[51] = 0; + cfgData[52] = 0; + cfgData[53] = 0; + cfgData[54] = 0; + cfgData[55] = 0; + cfgData[56] = 0; + cfgData[57] = 0; + cfgData[58] = 0; + cfgData[59] = 0; + } + + if (device->profilesValid & ORX_PROFILE_VALID) + { + /* start of ObsRx profile data */ + cfgData[60] = device->obsRx->orxProfile->adcDiv; + cfgData[61] = device->obsRx->orxProfile->rxFirDecimation; + cfgData[62] = device->obsRx->orxProfile->rxDec5Decimation; + cfgData[63] = device->obsRx->orxProfile->rhb1Decimation; + + for (i = 64; i < 68; i++) + { + cfgData[i] = (uint8_t)(((device->obsRx->orxProfile->iqRate_kHz * 1000) >> ((i - 64) * 8)) & 0x000000FF); + } + + for (i = 68; i < 72; i++) + { + /* sig bw placeholder */ + cfgData[i] = (uint8_t)(((device->obsRx->orxProfile->rfBandwidth_Hz) >> ((i - 68) * 8)) & 0x000000FF); + } + + for (i = 72; i < 76; i++) + { + cfgData[i] = (uint8_t)(((device->obsRx->orxProfile->rfBandwidth_Hz) >> ((i - 72) * 8)) & 0x000000FF); + } + + for (i = 76; i < 80; i++) + { + cfgData[i] = (uint8_t)(((device->obsRx->orxProfile->rxBbf3dBCorner_kHz * 1000) >> ((i - 76) * 8)) & 0x000000FF); + } + } + else + { + cfgData[60] = 0; + cfgData[61] = 0; + cfgData[62] = 0; + cfgData[63] = 0; + cfgData[64] = 0; + cfgData[65] = 0; + cfgData[66] = 0; + cfgData[67] = 0; + cfgData[68] = 0; + cfgData[69] = 0; + cfgData[70] = 0; + cfgData[71] = 0; + cfgData[72] = 0; + cfgData[73] = 0; + cfgData[74] = 0; + cfgData[75] = 0; + cfgData[76] = 0; + cfgData[77] = 0; + cfgData[78] = 0; + cfgData[79] = 0; + } + + if (device->profilesValid & SNIFF_PROFILE_VALID) + { + /* start of SnRx profile data */ + cfgData[80] = device->obsRx->snifferProfile->adcDiv; + cfgData[81] = device->obsRx->snifferProfile->rxFirDecimation; + cfgData[82] = device->obsRx->snifferProfile->rxDec5Decimation; + cfgData[83] = device->obsRx->snifferProfile->rhb1Decimation; + + for (i = 84; i < 88; i++) + { + cfgData[i] = (uint8_t)(((device->obsRx->snifferProfile->iqRate_kHz * 1000) >> ((i - 84) * 8)) & 0x000000FF); + } + + for (i = 88; i < 92; i++) + { + /* sig bw placeholder */ + cfgData[i] = (uint8_t)(((device->obsRx->snifferProfile->rfBandwidth_Hz) >> ((i - 88) * 8)) & 0x000000FF); + } + + for (i = 92; i < 96; i++) + { + cfgData[i] = (uint8_t)(((device->obsRx->snifferProfile->rfBandwidth_Hz) >> ((i - 92) * 8)) & 0x000000FF); + } + + for (i = 96; i < 100; i++) + { + cfgData[i] = (uint8_t)(((device->obsRx->snifferProfile->rxBbf3dBCorner_kHz * 1000) >> ((i - 96) * 8)) & 0x000000FF); + } + } + else + { + cfgData[80] = 0; + cfgData[81] = 0; + cfgData[82] = 0; + cfgData[83] = 0; + cfgData[84] = 0; + cfgData[85] = 0; + cfgData[86] = 0; + cfgData[87] = 0; + cfgData[88] = 0; + cfgData[89] = 0; + cfgData[90] = 0; + cfgData[91] = 0; + cfgData[92] = 0; + cfgData[93] = 0; + cfgData[94] = 0; + cfgData[95] = 0; + cfgData[96] = 0; + cfgData[97] = 0; + cfgData[98] = 0; + cfgData[99] = 0; + } + + /* writing to the ARM memory with the array data */ + retVal = MYKONOS_writeArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR, &cfgData[0], length); + + return retVal; +} + +/** + * \brief Function called automatically that loads the ADC profiles into the ARM + * + * User should not need to call this function normally. It is called automatically + * during MYKONOS_initArm() to load the ADC profiles (tunes the ADC performance). + * + * Rx ADC profile is only loaded if the Rx Profile is valid, ORx ADC profile is + * only loaded if the ORx Profile is valid. Sniffer ADC profile is only loaded + * if the Sniffer profile is valid. The Loopback ADC profile is always + * loaded. If Tx profile is valid, the loopback ADC profile is chosen based + * on the Tx Primary Signal bandwidth. If no valid Tx Profile, the Rx profile + * is used to set the Loopback ADC profile. Else, ORx, then sniffer profiles + * are used to set the loopback ADC profile. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device Pointer to the device settings structure + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_LOAD_ADCPROFILE_INV_VCODIV Mykonos CLKPLL has invalid VCO divider in the clocks structure + * \retval MYKONOS_ERR_LOAD_ADCPROFILE_MISSING_ORX_PROFILE When Tx Profile used, a matching ORx Profile must be provided with a valid ADC divider. + * The ORx digital filters and clock dividers are used with the Loopback Rx path for Tx calibrations. + * \retval MYKONOS_ERR_LOAD_ADCPROFILE_CUSTOM_RXREQUIRED ADC Profile Lookup table does not have a match + * for current Rx Profile settings. Custom ADC profile required + * \retval MYKONOS_ERR_LOAD_ADCPROFILE_CUSTOM_ORXREQUIRED ADC Profile Lookup table does not have a match + * for current ORx Profile settings. Custom ADC profile required + * \retval MYKONOS_ERR_LOAD_ADCPROFILE_CUSTOM_SNRXREQUIRED ADC Profile Lookup table does not have a match + * for current Sniffer Rx Profile settings. Custom ADC profile required + * \retval MYKONOS_ERR_LOAD_ADCPROFILE_CUSTOM_LBREQUIRED ADC Profile Lookup table does not have a match + * for Loopback passband BW and ADC Clock frequency settings. Custom ADC profile required + * \retval MYKONOS_ERR_LOAD_ADCPROFILE_RXADCDIV_ZERO Rx Profile has invalid ADC divider = 0, causing a divide by zero error + * \retval MYKONOS_ERR_LOAD_ADCPROFILE_ORXADCDIV_ZERO ORx profile has invalid ADC divider = 0, causing a divide by zero error + * \retval MYKONOS_ERR_LOAD_ADCPROFILE_SNRX_ADCDIV_ZERO Sniffer profile has invalid ADC divider = 0, causing a divide by zero error + * \retval MYKONOS_ERR_LOAD_RXADCPROFILE_ARMMEM_FAILED Error returned while trying to write Rx ADC profile to ARM memory + * \retval MYKONOS_ERR_LOAD_ORXADCPROFILE_ARMMEM_FAILED Error returned while trying to write ORx ADC profile to ARM memory + * \retval MYKONOS_ERR_LOAD_SNRXADCPROFILE_ARMMEM_FAILED Error returned while trying to write Sniffer ADC profile into ARM memory + * \retval MYKONOS_ERR_LOAD_LBADCPROFILE_ARMMEM_FAILED Error returned while trying to write Loopback ADC profile into ARM memory + */ +mykonosErr_t MYKONOS_loadAdcProfiles(mykonosDevice_t *device) +{ + uint8_t adcProfile[32] = {0}; + uint8_t i = 0; + mykonosErr_t retVal = MYKONOS_ERR_OK; + uint32_t hsDigClk_MHz = 0; + uint32_t adcClk_MHz = 0; + uint32_t vcoDiv = 0; + uint32_t vcoDivTimes10 = 10; + uint8_t profileIndex = 0; + const uint8_t ARM_CONFIG_OFFSET = 100; /* number of bytes written in MYKONOS_writeArmProfile() to ARM memory */ + + const uint8_t NUM_ADCPROFILE_COEFS = 16; + const uint8_t NUM_ADC_PROFILES = 20; + static const uint16_t adcProfileLut[20][18] = { + /* Max RFBW, ADCCLK_MHz, adcProfile[16] */ + { 20, 491, 1494, 564, 201, 98, 1280, 134, 945, 40, 529, 10, 326, 39, 30, 16, 9, 201}, + { 60, 983, 712, 462, 201, 98, 1280, 291, 1541, 149, 1054, 46, 645, 34, 48, 32, 18, 193}, + { 75, 983, 680, 477, 201, 98, 1280, 438, 1577, 242, 1046, 73, 636, 30, 48, 31, 18, 192}, + {100, 983, 655, 446, 201, 98, 1280, 336, 1631, 334, 1152, 207, 733, 33, 48, 32, 21, 212}, + { 75, 1228, 569, 369, 201, 98, 1280, 291, 1541, 149, 1320, 58, 807, 34, 48, 40, 23, 189}, + {100, 1228, 534, 386, 201, 98, 1280, 491, 1591, 279, 1306, 104, 792, 28, 48, 39, 23, 187}, + {160, 1228, 491, 375, 201, 98, 1280, 514, 1728, 570, 1455, 443, 882, 27, 48, 39, 25, 205}, + {200, 1228, 450, 349, 201, 98, 1280, 730, 1626, 818, 1476, 732, 834, 20, 41, 36, 24, 200}, + { 80, 1250, 555, 365, 201, 98, 1280, 317, 1547, 165, 1341, 65, 819, 33, 48, 40, 24, 188}, + {102, 1250, 524, 379, 201, 98, 1280, 494, 1592, 281, 1328, 107, 805, 28, 48, 40, 23, 187}, + { 80, 1333, 526, 339, 201, 98, 1280, 281, 1539, 143, 1433, 60, 877, 35, 48, 43, 25, 188}, + {217, 1333, 414, 321, 201, 98, 1280, 730, 1626, 818, 1603, 794, 905, 20, 41, 40, 26, 199}, + { 75, 1474, 486, 302, 199, 98, 1280, 206, 1523, 101, 1578, 47, 977, 37, 48, 48, 28, 186}, + {100, 1474, 465, 311, 201, 98, 1280, 353, 1556, 187, 1581, 86, 964, 32, 48, 47, 28, 185}, + {150, 1474, 436, 296, 190, 98, 1280, 336, 1631, 334, 1638, 293, 1102, 33, 48, 46, 31, 205}, + { 40, 1536, 479, 285, 190, 98, 1280, 112, 1505, 53, 1574, 25, 1026, 40, 48, 48, 29, 186}, + {100, 1536, 450, 297, 193, 98, 1280, 328, 1550, 171, 1586, 79, 1006, 33, 48, 48, 29, 184}, + {150, 1536, 421, 283, 182, 98, 1280, 313, 1620, 306, 1638, 269, 1153, 34, 48, 46, 33, 204}, + {200, 1536, 392, 299, 180, 98, 1280, 514, 1728, 570, 1638, 498, 1104, 27, 48, 44, 32, 200}, + {240, 1536, 366, 301, 178, 98, 1280, 686, 1755, 818, 1638, 742, 1056, 22, 45, 41, 31, 196}}; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_loadAdcProfiles\n"); +#endif + + vcoDiv = (uint32_t)device->clocks->clkPllVcoDiv; + switch (vcoDiv) + { + case VCODIV_1: + vcoDivTimes10 = 10; + break; + case VCODIV_1p5: + vcoDivTimes10 = 15; + break; + case VCODIV_2: + vcoDivTimes10 = 20; + break; + case VCODIV_3: + vcoDivTimes10 = 30; + break; + default: + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_LOAD_ADCPROFILE_INV_VCODIV, + getMykonosErrorMessage(MYKONOS_ERR_LOAD_ADCPROFILE_INV_VCODIV)); + return MYKONOS_ERR_LOAD_ADCPROFILE_INV_VCODIV; + } + } + + hsDigClk_MHz = device->clocks->clkPllVcoFreq_kHz / vcoDivTimes10 / 100 / device->clocks->clkPllHsDiv; + + /* If Tx Profile is valid, set loopback ADC profile based on Tx primary signal BW */ + if ((device->profilesValid & TX_PROFILE_VALID) > 0) + { + /* If custom profile, load it */ + if (device->obsRx->customLoopbackAdcProfile != NULL) + { + for (i = 0; i < NUM_ADCPROFILE_COEFS; i++) + { + adcProfile[i * 2] = device->obsRx->customLoopbackAdcProfile[i] & 0xFF; + adcProfile[i * 2 + 1] = (device->obsRx->customLoopbackAdcProfile[i] >> 8) & 0xFF; + } + } + else + { + /* Tx requires ORx profile is configured */ + if (((device->profilesValid & TX_PROFILE_VALID) > 0) && ((device->profilesValid & ORX_PROFILE_VALID) == 0)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_LOAD_ADCPROFILE_MISSING_ORX_PROFILE, + getMykonosErrorMessage(MYKONOS_ERR_LOAD_ADCPROFILE_MISSING_ORX_PROFILE)); + return MYKONOS_ERR_LOAD_ADCPROFILE_MISSING_ORX_PROFILE; + } + + if (device->obsRx->orxProfile->adcDiv == 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_LOAD_ADCPROFILE_ORXADCDIV_ZERO, + getMykonosErrorMessage(MYKONOS_ERR_LOAD_ADCPROFILE_ORXADCDIV_ZERO)); + return MYKONOS_ERR_LOAD_ADCPROFILE_ORXADCDIV_ZERO; + } + + adcClk_MHz = hsDigClk_MHz / device->obsRx->orxProfile->adcDiv; + + /* find correct ADC profile in the LUT */ + profileIndex = NUM_ADC_PROFILES; + for (i = 0; i < NUM_ADC_PROFILES; i++) + { + /* Find a row in the LUT that matches the ADC clock frequency */ + if ((adcProfileLut[i][1] == adcClk_MHz) && (adcProfileLut[i][0] >= (device->tx->txProfile->primarySigBandwidth_Hz / 1000000))) + { + profileIndex = i; + break; + } + } + + /* Verify that a profile was found in the LUT, if not return error */ + /* In this case a custom profile would need to be passed in */ + if (profileIndex >= NUM_ADC_PROFILES) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_LOAD_ADCPROFILE_CUSTOM_LBREQUIRED, + getMykonosErrorMessage(MYKONOS_ERR_LOAD_ADCPROFILE_CUSTOM_LBREQUIRED)); + return MYKONOS_ERR_LOAD_ADCPROFILE_CUSTOM_LBREQUIRED; + } + + for (i = 0; i < NUM_ADCPROFILE_COEFS; i++) + { + adcProfile[i * 2] = adcProfileLut[profileIndex][i + 2] & 0xFF; + adcProfile[i * 2 + 1] = (adcProfileLut[profileIndex][i + 2] >> 8) & 0xFF; + } + } + + /* writing to the ARM memory: Set Loopback ADC Profile based on Tx Primary signal Bandwidth */ + retVal = MYKONOS_writeArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR + ARM_CONFIG_OFFSET + 96, &adcProfile[0], sizeof(adcProfile)); + if (retVal) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_LOAD_LBADCPROFILE_ARMMEM_FAILED, + getMykonosErrorMessage(MYKONOS_ERR_LOAD_LBADCPROFILE_ARMMEM_FAILED)); + return MYKONOS_ERR_LOAD_LBADCPROFILE_ARMMEM_FAILED; + } + } + + if ((device->profilesValid & RX_PROFILE_VALID) > 0) + { + /* If custom profile, load it */ + if (device->rx->rxProfile->customAdcProfile != NULL) + { + for (i = 0; i < NUM_ADCPROFILE_COEFS; i++) + { + adcProfile[i * 2] = device->rx->rxProfile->customAdcProfile[i] & 0xFF; + adcProfile[i * 2 + 1] = (device->rx->rxProfile->customAdcProfile[i] >> 8) & 0xFF; + } + } + else + { + if (device->rx->rxProfile->adcDiv == 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_LOAD_ADCPROFILE_RXADCDIV_ZERO, + getMykonosErrorMessage(MYKONOS_ERR_LOAD_ADCPROFILE_RXADCDIV_ZERO)); + return MYKONOS_ERR_LOAD_ADCPROFILE_RXADCDIV_ZERO; + } + + adcClk_MHz = hsDigClk_MHz / device->rx->rxProfile->adcDiv; + + /* find correct ADC profile in the LUT */ + profileIndex = NUM_ADC_PROFILES; + for (i = 0; i < NUM_ADC_PROFILES; i++) + { + /* Find a row in the LUT that matches the ADC clock frequency */ + if ((adcProfileLut[i][1] == adcClk_MHz) && (adcProfileLut[i][0] >= (device->rx->rxProfile->rfBandwidth_Hz / 1000000))) + { + profileIndex = i; + break; + } + } + + /* Verify that a profile was found in the LUT, if not return error */ + /* In this case a custom profile would need to be passed in */ + if (profileIndex >= NUM_ADC_PROFILES) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_LOAD_ADCPROFILE_CUSTOM_RXREQUIRED, + getMykonosErrorMessage(MYKONOS_ERR_LOAD_ADCPROFILE_CUSTOM_RXREQUIRED)); + return MYKONOS_ERR_LOAD_ADCPROFILE_CUSTOM_RXREQUIRED; + } + + for (i = 0; i < NUM_ADCPROFILE_COEFS; i++) + { + adcProfile[i * 2] = adcProfileLut[profileIndex][i + 2] & 0xFF; + adcProfile[i * 2 + 1] = (adcProfileLut[profileIndex][i + 2] >> 8) & 0xFF; + } + } + + /* writing to the ARM memory with ADC Profile for Rx path */ + retVal = MYKONOS_writeArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR + ARM_CONFIG_OFFSET, &adcProfile[0], sizeof(adcProfile)); + if (retVal) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_LOAD_RXADCPROFILE_ARMMEM_FAILED, + getMykonosErrorMessage(MYKONOS_ERR_LOAD_RXADCPROFILE_ARMMEM_FAILED)); + return MYKONOS_ERR_LOAD_RXADCPROFILE_ARMMEM_FAILED; + } + + /* writing to the ARM memory: Set Loopback ADC Profile = Rx ADC Profile ONLY if Tx profile is not valid */ + if ((device->profilesValid & TX_PROFILE_VALID) == 0) + { + retVal = MYKONOS_writeArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR + ARM_CONFIG_OFFSET + 96, &adcProfile[0], sizeof(adcProfile)); + if (retVal) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_LOAD_LBADCPROFILE_ARMMEM_FAILED, + getMykonosErrorMessage(MYKONOS_ERR_LOAD_LBADCPROFILE_ARMMEM_FAILED)); + return MYKONOS_ERR_LOAD_LBADCPROFILE_ARMMEM_FAILED; + } + } + } + + if ((device->profilesValid & ORX_PROFILE_VALID) > 0) + { + /* If custom profile, load it */ + if (device->obsRx->orxProfile->customAdcProfile != NULL) + { + for (i = 0; i < NUM_ADCPROFILE_COEFS; i++) + { + adcProfile[i * 2] = device->obsRx->orxProfile->customAdcProfile[i] & 0xFF; + adcProfile[i * 2 + 1] = (device->obsRx->orxProfile->customAdcProfile[i] >> 8) & 0xFF; + } + } + else + { + if (device->obsRx->orxProfile->adcDiv == 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_LOAD_ADCPROFILE_ORXADCDIV_ZERO, + getMykonosErrorMessage(MYKONOS_ERR_LOAD_ADCPROFILE_ORXADCDIV_ZERO)); + return MYKONOS_ERR_LOAD_ADCPROFILE_ORXADCDIV_ZERO; + } + + adcClk_MHz = hsDigClk_MHz / device->obsRx->orxProfile->adcDiv; + + /* find correct ADC profile in the LUT */ + profileIndex = NUM_ADC_PROFILES; + for (i = 0; i < NUM_ADC_PROFILES; i++) + { + /* Find a row in the LUT that matches the ADC clock frequency */ + if ((adcProfileLut[i][1] == adcClk_MHz) && (adcProfileLut[i][0] >= (device->obsRx->orxProfile->rfBandwidth_Hz / 1000000))) + { + profileIndex = i; + break; + } + } + + /* Verify that a profile was found in the LUT, if not return error */ + /* In this case a custom profile would need to be passed in */ + if (profileIndex >= NUM_ADC_PROFILES) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_LOAD_ADCPROFILE_CUSTOM_ORXREQUIRED, + getMykonosErrorMessage(MYKONOS_ERR_LOAD_ADCPROFILE_CUSTOM_ORXREQUIRED)); + return MYKONOS_ERR_LOAD_ADCPROFILE_CUSTOM_ORXREQUIRED; + } + + for (i = 0; i < NUM_ADCPROFILE_COEFS; i++) + { + adcProfile[i * 2] = adcProfileLut[profileIndex][i + 2] & 0xFF; + adcProfile[i * 2 + 1] = (adcProfileLut[profileIndex][i + 2] >> 8) & 0xFF; + } + } + + /* writing to the ARM memory with ADC Profile for ORx path */ + retVal = MYKONOS_writeArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR + ARM_CONFIG_OFFSET + 32, &adcProfile[0], sizeof(adcProfile)); + if (retVal) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_LOAD_ORXADCPROFILE_ARMMEM_FAILED, + getMykonosErrorMessage(MYKONOS_ERR_LOAD_ORXADCPROFILE_ARMMEM_FAILED)); + return MYKONOS_ERR_LOAD_ORXADCPROFILE_ARMMEM_FAILED; + } + + /* If Rx and Tx Profiles are not valid, set Loopback ADC profile to ORx ADC Profile */ + if (((device->profilesValid & TX_PROFILE_VALID) == 0) && ((device->profilesValid & RX_PROFILE_VALID) == 0)) + { + retVal = MYKONOS_writeArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR + ARM_CONFIG_OFFSET + 96, &adcProfile[0], sizeof(adcProfile)); + if (retVal) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_LOAD_LBADCPROFILE_ARMMEM_FAILED, + getMykonosErrorMessage(MYKONOS_ERR_LOAD_LBADCPROFILE_ARMMEM_FAILED)); + return MYKONOS_ERR_LOAD_LBADCPROFILE_ARMMEM_FAILED; + } + } + } + + if ((device->profilesValid & SNIFF_PROFILE_VALID) > 0) + { + /* If custom profile, load it */ + if (device->obsRx->snifferProfile->customAdcProfile != NULL) + { + for (i = 0; i < NUM_ADCPROFILE_COEFS; i++) + { + adcProfile[i * 2] = device->obsRx->snifferProfile->customAdcProfile[i] & 0xFF; + adcProfile[i * 2 + 1] = (device->obsRx->snifferProfile->customAdcProfile[i] >> 8) & 0xFF; + } + } + else + { + + if (device->obsRx->snifferProfile->adcDiv == 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_LOAD_ADCPROFILE_SNRX_ADCDIV_ZERO, + getMykonosErrorMessage(MYKONOS_ERR_LOAD_ADCPROFILE_SNRX_ADCDIV_ZERO)); + return MYKONOS_ERR_LOAD_ADCPROFILE_SNRX_ADCDIV_ZERO; + } + + adcClk_MHz = hsDigClk_MHz / device->obsRx->snifferProfile->adcDiv; + + /* find correct ADC profile in the LUT */ + profileIndex = NUM_ADC_PROFILES; + for (i = 0; i < NUM_ADC_PROFILES; i++) + { + /* Find a row in the LUT that matches the ADC clock frequency */ + if ((adcProfileLut[i][1] == adcClk_MHz) && (adcProfileLut[i][0] >= (device->obsRx->snifferProfile->rfBandwidth_Hz / 1000000))) + { + profileIndex = i; + break; + } + } + + /* Verify that a profile was found in the LUT, if not return error */ + /* In this case a custom profile would need to be passed in */ + if (profileIndex >= NUM_ADC_PROFILES) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_LOAD_ADCPROFILE_CUSTOM_SNRXREQUIRED, + getMykonosErrorMessage(MYKONOS_ERR_LOAD_ADCPROFILE_CUSTOM_SNRXREQUIRED)); + return MYKONOS_ERR_LOAD_ADCPROFILE_CUSTOM_SNRXREQUIRED; + } + + for (i = 0; i < NUM_ADCPROFILE_COEFS; i++) + { + adcProfile[i * 2] = adcProfileLut[profileIndex][i + 2] & 0xFF; + adcProfile[i * 2 + 1] = (adcProfileLut[profileIndex][i + 2] >> 8) & 0xFF; + } + } + + /* writing to the ARM memory with ADC Profile for sniffer Rx path */ + retVal = MYKONOS_writeArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR + ARM_CONFIG_OFFSET + 64, &adcProfile[0], sizeof(adcProfile)); + if (retVal) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_LOAD_SNRXADCPROFILE_ARMMEM_FAILED, + getMykonosErrorMessage(MYKONOS_ERR_LOAD_SNRXADCPROFILE_ARMMEM_FAILED)); + return MYKONOS_ERR_LOAD_SNRXADCPROFILE_ARMMEM_FAILED; + } + + /* If Tx, Rx, and ORx Profiles are not valid, set Loopback ADC profile to Sniffer Rx ADC Profile */ + if (((device->profilesValid & TX_PROFILE_VALID) == 0) && ((device->profilesValid & RX_PROFILE_VALID) == 0) && ((device->profilesValid & ORX_PROFILE_VALID) == 0)) + { + retVal = MYKONOS_writeArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR + ARM_CONFIG_OFFSET + 96, &adcProfile[0], sizeof(adcProfile)); + if (retVal) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_LOAD_LBADCPROFILE_ARMMEM_FAILED, + getMykonosErrorMessage(MYKONOS_ERR_LOAD_LBADCPROFILE_ARMMEM_FAILED)); + return MYKONOS_ERR_LOAD_LBADCPROFILE_ARMMEM_FAILED; + } + } + } + + return MYKONOS_ERR_OK; +} + +/** + * \brief Helper function to calculate commonly used digital clock frequencies in the device + * + * User should not need to call this function normally. It is called automatically + * within other API functions to calculate the main digital clock. If the pointers + * to the return parameters are NULL, that calculation will be skipped and not + * returned. + * + * + * Dependencies + * -device->clocks->clkPllVcoFreq_kHz; + * -device->clocks->clkPllVcoDiv; + * -device->clocks->clkPllHsDiv; + * + * \param device Pointer to the device settings structure + * \param hsDigClk_kHz Return value for the calculated Mykonos high speed Digital clock at the output of the CLKPLL in kHz + * \param hsDigClkDiv4or5_kHz Return value for the Mykonos high speed digital clock divided by 4 or 5 in kHz + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_CALCDIGCLK_NULLDEV_PARAM device parameter is a NULL pointer + * \retval MYKONOS_ERR_CALCDIGCLK_NULL_CLKSTRUCT device->clocks structure is a NULL pointer + * \retval MYKONOS_ERR_CLKPLL_INV_VCODIV Invalid CLKPLL VCO divider in device->clocks->clkPllVcoDiv + * \retval MYKONOS_ERR_CLKPLL_INV_HSDIV Invalid CLKPLL High speed divider in device->clocks->clkPllHsDiv + */ +static mykonosErr_t MYKONOS_calculateDigitalClocks(mykonosDevice_t *device, uint32_t *hsDigClk_kHz, uint32_t *hsDigClkDiv4or5_kHz) +{ + uint32_t hsclkRate_kHz = 0; + uint32_t clkPllVcoFrequency_kHz = 0; + mykonosVcoDiv_t vcoDiv = VCODIV_1; + uint8_t hsDiv = 4; + + if (device == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, 0, MYKONOS_ERR_CALCDIGCLK_NULLDEV_PARAM, getMykonosErrorMessage(MYKONOS_ERR_CALCDIGCLK_NULLDEV_PARAM)); + return MYKONOS_ERR_CALCDIGCLK_NULLDEV_PARAM; + } + + if ((device->clocks == NULL)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CALCDIGCLK_NULL_CLKSTRUCT, + getMykonosErrorMessage(MYKONOS_ERR_CALCDIGCLK_NULL_CLKSTRUCT)); + return MYKONOS_ERR_CALCDIGCLK_NULL_CLKSTRUCT; + } + + clkPllVcoFrequency_kHz = device->clocks->clkPllVcoFreq_kHz; + vcoDiv = device->clocks->clkPllVcoDiv; + hsDiv = device->clocks->clkPllHsDiv; + + switch (vcoDiv) + { + case VCODIV_1: + hsclkRate_kHz = clkPllVcoFrequency_kHz; + break; + case VCODIV_1p5: + hsclkRate_kHz = (clkPllVcoFrequency_kHz / 15) * 10; + break; + case VCODIV_2: + hsclkRate_kHz = clkPllVcoFrequency_kHz >> 1; + break; + case VCODIV_3: + hsclkRate_kHz = (clkPllVcoFrequency_kHz / 30) * 10; + break; + default: + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CLKPLL_INV_VCODIV, getMykonosErrorMessage(MYKONOS_ERR_CLKPLL_INV_VCODIV)); + return MYKONOS_ERR_CLKPLL_INV_VCODIV; + } + } + + switch (hsDiv) + { + case 4: + hsDiv = 4; + break; + case 5: + hsDiv = 5; + break; + default: + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CLKPLL_INV_HSDIV, getMykonosErrorMessage(MYKONOS_ERR_CLKPLL_INV_HSDIV)); + return MYKONOS_ERR_CLKPLL_INV_HSDIV; + } + } + + if (hsDigClk_kHz != NULL) + { + *hsDigClk_kHz = hsclkRate_kHz / hsDiv; + } + + if (hsDigClkDiv4or5_kHz != NULL) + { + /* This digital div 4 or 5 is always mutually exclusive with the HS Divider (4 or 5) to always + * create a /20 from the hsclk. + */ + *hsDigClkDiv4or5_kHz = hsclkRate_kHz / 20; + } + + return MYKONOS_ERR_OK; +} + +/** + * \brief Performs reset to the External Tx LO Leakage tracking calibration channel estimate + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device Pointer to the Mykonos device data structure containing settings + * \param channelSel Enum selects the channel to reset + * + * \retval MYKONOS_ERR_RESET_TXLOL_INV_PARAM Selected channel is not valid + * \retval MYKONOS_ERR_RESET_TXLOL_ARMERROR ARM error + * \retval MYKONOS_ERR_OK Function completed successfully + */ +mykonosErr_t MYKONOS_resetExtTxLolChannel(mykonosDevice_t *device, mykonosTxChannels_t channelSel) +{ + const uint8_t TXLOL_RESET_CHANNEL_ESTIMATE = 0x01; + const uint32_t GETTXLOLSTATUS_TIMEOUT_MS = 1000; + + mykonosErr_t retVal = MYKONOS_ERR_OK; + uint8_t extData[3] = {MYKONOS_ARM_OBJECTID_GS_TRACKCALS, TXLOL_RESET_CHANNEL_ESTIMATE, 0}; + uint8_t cmdStatusByte = 0; + uint8_t armErrorFlag = 0; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_resetExtTxLolChannel()\n"); +#endif + + /* Check Channel */ + switch (channelSel) + { + case TX1: + extData[2] = 0x01; + break; + case TX2: + extData[2] = 0x02; + break; + case TX1_TX2: + extData[2] = 0x03; + break; + default: + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RESET_TXLOL_INV_PARAM, + getMykonosErrorMessage(MYKONOS_ERR_RESET_TXLOL_INV_PARAM)); + return MYKONOS_ERR_RESET_TXLOL_INV_PARAM; + } + + /* throw error if not in the right state */ + retVal = MYKONOS_checkArmState(device, (MYK_ARM_IDLE | MYK_ARM_RADIO_ON)); + if (retVal) + { + return retVal; + } + + retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_SET_OPCODE, &extData[0], sizeof(extData)); + if (retVal) + { + return retVal; + } + retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_SET_OPCODE, GETTXLOLSTATUS_TIMEOUT_MS, &cmdStatusByte); + + /* Error check WaitArmCmdStatus return */ + armErrorFlag = (cmdStatusByte >> 1); + if (armErrorFlag > 0) + { + return MYKONOS_ERR_RESET_TXLOL_ARMERROR; + } + + return retVal; +} + +/** + * \brief Configures the Radio power up/down control for Rx and Tx paths to be controlled by pins + * (TX1/2_ENABLE, RX1/2_ENABLE, and GPIO pins) or an API function call. + * + * The BBP should not have to call this as it will automatically be setup at the end of the + * MYKONOS_loadArmFromBinary() function call. If the BBP wishes to change the radio power up/down + * control method this function can be called again to change the configuration while + * the ARM is in the radioOff state. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * - device->auxIo->armGpio->useRx2EnablePin + * - device->auxIo->armGpio->useTx2EnablePin + * - device->auxIo->armGpio->txRxPinMode + * - device->auxIo->armGpio->orxPinMode + * + * \param device is a pointer to the device settings structure + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_SET_RADIOCTRL_PINS_ARMERROR ARM returned an error and did not accept the command. + */ +mykonosErr_t MYKONOS_setRadioControlPinMode(mykonosDevice_t *device) +{ + uint8_t extData[4] = {0x81, 0, 0, 4}; /*Object ID 0x81 (radio control structure), offset lsb, offset msb, length*/ + uint8_t armRadioControlStruct[4] = {0}; + uint32_t timeoutMs = 0; + uint8_t cmdStatusByte = 0; + mykonosErr_t retval = MYKONOS_ERR_OK; + +#if MYKONOS_VERBOSE == 1 + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setRadioControlPinMode()\n"); +#endif + + /* write ARM radio control structure to enable pin mode/command mode */ + if (device->auxIo->armGpio->useRx2EnablePin > 0) + { + armRadioControlStruct[0] = 0x01; + } + + if (device->auxIo->armGpio->useTx2EnablePin > 0) + { + armRadioControlStruct[1] = 0x01; + } + + if (device->auxIo->armGpio->txRxPinMode > 0) + { + armRadioControlStruct[2] = 0x01; + } + + if (device->auxIo->armGpio->orxPinMode > 0) + { + armRadioControlStruct[3] = 0x01; + } + + retval = MYKONOS_writeArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR, &armRadioControlStruct[0], sizeof(armRadioControlStruct)); + if (retval != MYKONOS_ERR_OK) + { + return retval; + } + + retval = MYKONOS_sendArmCommand(device, MYKONOS_ARM_WRITECFG_OPCODE, &extData[0], sizeof(extData)); + if (retval != MYKONOS_ERR_OK) + { + return retval; + } + + timeoutMs = 1000; + retval = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_WRITECFG_OPCODE, timeoutMs, &cmdStatusByte); + if (retval != MYKONOS_ERR_OK) + { + return retval; + } + + if (cmdStatusByte > 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SET_RADIOCTRL_PINS_ARMERROR, + getMykonosErrorMessage(MYKONOS_ERR_SET_RADIOCTRL_PINS_ARMERROR)); + return MYKONOS_ERR_SET_RADIOCTRL_PINS_ARMERROR; + } + + return MYKONOS_ERR_OK; +} + +/** + * \brief Sets the measure count which is the number of samples taken before DC offset correction is applied for the given RF channel. + * This value should be changed after ARM initialization. + * channel can be one of the following ( ::mykonosDcOffsetChannels_t ). + * + * Channel | Channel description + * ------------------------|-------------------------------- + * MYK_DC_OFFSET_RX_CHN | Selects Rx channel + * MYK_DC_OFFSET_ORX_CHN | Selects ORx channel + * MYK_DC_OFFSET_SNF_CHN | Selects Sniffer channel + * + * The total duration 'tCount' is calculated as, + * [tCount = (measureCount * 1024) / IQ data rate of the channel]. + * There is a minimum limit for the value of measureCount, the value passed should satisfy the condition 'tCount > 800us'. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device Pointer to the Mykonos device data structure containing settings + * \param channel Receive channel to be selected. + * \param measureCount Value to be configured for the selected channel which is the number of samples taken before DC offset correction is applied. + * + * \retval MYKONOS_ERR_DC_OFFSET_INV_CHAN channel passed to the function is invalid, refer mykonosDcOffsetChannels_t enum for valid channels. + * \retval MYKONOS_ERR_SET_RF_DC_OFFSET_INV_MEASURECNT measurement count value passed is invalid + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_SET_RF_DC_OFFSET_MEASURECNT_MIN_LIMIT The measureCount value passed is less than the minimum limit allowed. + */ +mykonosErr_t MYKONOS_setRfDcOffsetCnt(mykonosDevice_t *device, mykonosDcOffsetChannels_t channel, uint16_t measureCount) +{ + mykonosErr_t retVal = MYKONOS_ERR_OK; + uint16_t REG_ADDRESS_H = 0; /* Address for Higher byte */ + uint16_t REG_ADDRESS_L = 0; /* Address for Lower byte */ + uint16_t MEASURE_CNT_RANGE = 0xFFFF; /* Mask for measure count range checking */ + + const uint8_t MEASURE_CNT_H = (measureCount & 0xFF00) >> 8; /* Higher byte of the measure count */ + const uint8_t MEASURE_CNT_L = measureCount & 0x00FF; /* Lower byte of the measure count */ + + /* Calculation of Total Duration [ tCount = (measureCount * 0x400) / IQ data rate cycles ] */ + const uint8_t FACTOR = 10; + uint32_t tCount = (measureCount << FACTOR); /* precalculations for Total duration in us */ + uint32_t IQ_RATE = 0; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setRfDcOffsetCnt()\n"); +#endif + + /* check for channel and update the appropriate register address */ + switch (channel) + { + case MYK_DC_OFFSET_RX_CHN: + REG_ADDRESS_H = MYKONOS_ADDR_RFDC_MEASURE_COUNT_2; + REG_ADDRESS_L = MYKONOS_ADDR_RFDC_MEASURE_COUNT_1; + IQ_RATE = device->rx->rxProfile->iqRate_kHz / 1000; /* IQ Rate to calculate total duration */ + break; + case MYK_DC_OFFSET_ORX_CHN: + REG_ADDRESS_H = MYKONOS_ADDR_RFDC_ORX_MEASURE_COUNT_2; + REG_ADDRESS_L = MYKONOS_ADDR_RFDC_ORX_MEASURE_COUNT_1; + IQ_RATE = device->obsRx->orxProfile->iqRate_kHz / 1000; /* IQ Rate to calculate total duration */ + break; + case MYK_DC_OFFSET_SNF_CHN: + REG_ADDRESS_H = MYKONOS_ADDR_RFDC_SNF_MEASURE_COUNT_2; + REG_ADDRESS_L = MYKONOS_ADDR_RFDC_SNF_MEASURE_COUNT_1; + /* measureCount for Sniffer should be 10 bit */ + MEASURE_CNT_RANGE= 0x03FF; + IQ_RATE = device->obsRx->snifferProfile->iqRate_kHz / 1000; /* IQ Rate to calculate total duration */ + break; + + default: + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DC_OFFSET_INV_CHAN, + getMykonosErrorMessage(MYKONOS_ERR_DC_OFFSET_INV_CHAN)); + return MYKONOS_ERR_DC_OFFSET_INV_CHAN; + } + + tCount = (tCount / IQ_RATE); /* Calculating total duration in us */ + if (tCount < 800) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SET_RF_DC_OFFSET_MEASURECNT_MIN_LIMIT, + getMykonosErrorMessage(MYKONOS_ERR_SET_RF_DC_OFFSET_MEASURECNT_MIN_LIMIT)); + return MYKONOS_ERR_SET_RF_DC_OFFSET_MEASURECNT_MIN_LIMIT ; + } + + if ((measureCount < 0x11) || (measureCount & ~MEASURE_CNT_RANGE)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SET_RF_DC_OFFSET_INV_MEASURECNT, + getMykonosErrorMessage(MYKONOS_ERR_SET_RF_DC_OFFSET_INV_MEASURECNT)); + return MYKONOS_ERR_SET_RF_DC_OFFSET_INV_MEASURECNT ; + } + + CMB_SPIWriteField(device->spiSettings, REG_ADDRESS_H, MEASURE_CNT_H, ((MEASURE_CNT_RANGE >>8) & 0xFF),0); + CMB_SPIWriteByte(device->spiSettings, REG_ADDRESS_L, MEASURE_CNT_L); + + return retVal; +} + +/** + * \brief retrieves the measure count which is the number of samples taken before DC offset correction is applied for the given Rf channel. + * channel can be one of the following ( ::mykonosDcOffsetChannels_t ). + * + * Channel | Channel description + * ------------------------|-------------------------------- + * MYK_DC_OFFSET_RX_CHN | Selects Rx channel + * MYK_DC_OFFSET_ORX_CHN | Selects ORx channel + * MYK_DC_OFFSET_SNF_CHN | Selects Sniffer channel + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device Pointer to the Mykonos device data structure containing settings + * \param channel receive channel to be selected. + * \param measureCount pointer to the variable to store the read value. + * + * \retval MYKONOS_ERR_DC_OFFSET_INV_CHAN channel passed to the function is invalid, refer mykonosDcOffsetChannels_t enum for valid channels. + * \retval MYKONOS_ERR_SET_RF_DC_OFFSET_NULL_MEASURECNT passed pointer of measureCount is NULL + * \retval MYKONOS_ERR_OK Function completed successfully + */ +mykonosErr_t MYKONOS_getRfDcOffsetCnt(mykonosDevice_t *device, mykonosDcOffsetChannels_t channel, uint16_t *measureCount) +{ + mykonosErr_t retVal = MYKONOS_ERR_OK; + uint16_t REG_ADDRESS_H = 0; /* Address for Higher byte */ + uint16_t REG_ADDRESS_L = 0; /* Address for Lower byte */ + uint16_t MEASURE_CNT_RANGE = 0xFFFF; /* Mask for measure count range checking */ + uint16_t mCount = 0; /* Temporary variable to store readback from register. */ + uint8_t readbackData = 0; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getRfDcOffsetCnt()\n"); +#endif + + switch (channel) + { + case MYK_DC_OFFSET_RX_CHN: + REG_ADDRESS_H = MYKONOS_ADDR_RFDC_MEASURE_COUNT_2; + REG_ADDRESS_L = MYKONOS_ADDR_RFDC_MEASURE_COUNT_1; + break; + case MYK_DC_OFFSET_ORX_CHN: + REG_ADDRESS_H = MYKONOS_ADDR_RFDC_ORX_MEASURE_COUNT_2; + REG_ADDRESS_L = MYKONOS_ADDR_RFDC_ORX_MEASURE_COUNT_1; + break; + case MYK_DC_OFFSET_SNF_CHN: + REG_ADDRESS_H = MYKONOS_ADDR_RFDC_SNF_MEASURE_COUNT_2; + REG_ADDRESS_L = MYKONOS_ADDR_RFDC_SNF_MEASURE_COUNT_1; + /* measureCount for Sniffer should be 10 bit */ + MEASURE_CNT_RANGE= 0x03FF; + break; + + default: + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DC_OFFSET_INV_CHAN, + getMykonosErrorMessage(MYKONOS_ERR_DC_OFFSET_INV_CHAN)); + return MYKONOS_ERR_DC_OFFSET_INV_CHAN; + } + + if (measureCount == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GET_RF_DC_OFFSET_NULL_MEASURECNT, + getMykonosErrorMessage(MYKONOS_ERR_GET_RF_DC_OFFSET_NULL_MEASURECNT)); + return MYKONOS_ERR_GET_RF_DC_OFFSET_NULL_MEASURECNT; + } + + /* Store Higher byte of measureCount */ + CMB_SPIReadField(device->spiSettings, REG_ADDRESS_H, &readbackData, ((MEASURE_CNT_RANGE >>8) & 0xFF),0); + mCount = readbackData; + mCount = mCount << 8; + + /* Store Lower byte of measureCount */ + readbackData = 0; + CMB_SPIReadByte(device->spiSettings, REG_ADDRESS_L, &readbackData); + mCount = mCount | readbackData; + + *measureCount = mCount; + + return retVal; +} + +/** + * \brief Sets M-Shift value which is the Corner frequency of Rx notch filter for the given channel. + * channel can be one of the following ( ::mykonosDcOffsetChannels_t ). + * + * Channel | Channel description + * ------------------------|-------------------------------- + * MYK_DC_OFFSET_RX_CHN | Selects Rx channel + * MYK_DC_OFFSET_ORX_CHN | Selects ORx channel + * MYK_DC_OFFSET_SNF_CHN | Selects Sniffer channel + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device Pointer to the Mykonos device data structure containing settings + * \param channel receive channel to be selected. + * \param mShift value to be configured for the given channel + * + * \retval MYKONOS_ERR_DC_OFFSET_INV_CHAN channel passed to the function is invalid, refer mykonosDcOffsetChannels_t enum for valid channels. + * \retval MYKONOS_ERR_SET_DIG_DC_OFFSET_INV_MSHIFT mShift value passed is invalid. + * \retval MYKONOS_ERR_OK Function completed successfully + */ +mykonosErr_t MYKONOS_setDigDcOffsetMShift(mykonosDevice_t *device, mykonosDcOffsetChannels_t channel, uint8_t mShift) +{ + mykonosErr_t retVal = MYKONOS_ERR_OK; + uint16_t REG_ADDRESS = 0; + + const uint8_t MSHIFT_MIN_RANGE= 0x08; + const uint8_t MSHIFT_MAX_RANGE= 0x14; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setDigDcOffsetMShift()\n"); +#endif + + if ((mShift < MSHIFT_MIN_RANGE) || (mShift > MSHIFT_MAX_RANGE)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SET_DIG_DC_OFFSET_INV_MSHIFT, + getMykonosErrorMessage(MYKONOS_ERR_SET_DIG_DC_OFFSET_INV_MSHIFT)); + return MYKONOS_ERR_SET_DIG_DC_OFFSET_INV_MSHIFT; + } + + /* check channel and set the address */ + switch (channel) + { + case MYK_DC_OFFSET_RX_CHN: + REG_ADDRESS = MYKONOS_ADDR_DIGITAL_DC_OFFSET_SHIFT; + break; + case MYK_DC_OFFSET_ORX_CHN: + REG_ADDRESS = MYKONOS_ADDR_DIGITAL_DC_OFFSET_CH3_DPD_M_SHIFT; + break; + case MYK_DC_OFFSET_SNF_CHN: + REG_ADDRESS = MYKONOS_ADDR_DIGITAL_DC_OFFSET_SNF; + break; + + default: + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DC_OFFSET_INV_CHAN, + getMykonosErrorMessage(MYKONOS_ERR_DC_OFFSET_INV_CHAN)); + return MYKONOS_ERR_DC_OFFSET_INV_CHAN; + } + + CMB_SPIWriteField(device->spiSettings, REG_ADDRESS, mShift, 0x1F, 0); + + return retVal; +} + +/** + * \brief retrieves the M-Shift value which is the Corner frequency of Rx notch filter for the given channel. + * channel can be one of the following ( ::mykonosDcOffsetChannels_t ). + * + * Channel | Channel description + * ------------------------|-------------------------------- + * MYK_DC_OFFSET_RX_CHN | Selects Rx channel + * MYK_DC_OFFSET_ORX_CHN | Selects ORx channel + * MYK_DC_OFFSET_SNF_CHN | Selects Sniffer channel + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device Pointer to the Mykonos device data structure containing settings + * \param channel receive channel to be selected. + * \param mShift Pointer to the variable to store mshift value of the given channel + * + * \retval MYKONOS_ERR_DC_OFFSET_INV_CHAN channel passed to the function is invalid, refer mykonosDcOffsetChannels_t enum for valid channels. + * \retval MYKONOS_ERR_GET_DIG_DC_OFFSET_NULL_MSHIFT mShift pointer is NULL + * \retval MYKONOS_ERR_OK Function completed successfully + */ +mykonosErr_t MYKONOS_getDigDcOffsetMShift(mykonosDevice_t *device, mykonosDcOffsetChannels_t channel, uint8_t *mShift) +{ + mykonosErr_t retVal = MYKONOS_ERR_OK; + uint16_t REG_ADDRESS = 0x0; + uint8_t readbackData = 0x0; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getDigDcOffsetMShift()\n"); +#endif + + if (mShift == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GET_DIG_DC_OFFSET_NULL_MSHIFT, + getMykonosErrorMessage(MYKONOS_ERR_GET_DIG_DC_OFFSET_NULL_MSHIFT)); + return MYKONOS_ERR_GET_DIG_DC_OFFSET_NULL_MSHIFT; + } + + /* check for the channel and set the address */ + switch (channel) + { + case MYK_DC_OFFSET_RX_CHN: + REG_ADDRESS = MYKONOS_ADDR_DIGITAL_DC_OFFSET_SHIFT; + break; + case MYK_DC_OFFSET_ORX_CHN: + REG_ADDRESS = MYKONOS_ADDR_DIGITAL_DC_OFFSET_CH3_DPD_M_SHIFT; + break; + case MYK_DC_OFFSET_SNF_CHN: + REG_ADDRESS = MYKONOS_ADDR_DIGITAL_DC_OFFSET_SNF; + break; + + default: + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DC_OFFSET_INV_CHAN, + getMykonosErrorMessage(MYKONOS_ERR_DC_OFFSET_INV_CHAN)); + return MYKONOS_ERR_DC_OFFSET_INV_CHAN; + } + + CMB_SPIReadField(device->spiSettings, REG_ADDRESS, &readbackData, 0x1F,0); + + *mShift = readbackData; + + return retVal; +} + +/** + * \brief Sets the RF PLL loop filter bandwith. + * + * \pre Command should be called in Radio Off state. ARM must be initialized. + * + * \post Loop filter should lock successfully + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * - device->spiSettings + * + * \param device is structure pointer to the MYKONOS data structure containing settings + * \param pllName Name of the PLL to configure.RX_PLL and TX_PLL can be configured.SNIFFER_PLL can not be configured. + * \param loopBandwidth_kHz Desired RF pll bandwith to be set. The valid values range of loopBandwidth_kHz for Rx and Tx is 50 to 750.For SRX valid values lies from 500 to 750. + * \param stability PLL Loop stability to be set.The valid values range of stability is from 3 to 15. + * + * \return MYKONOS_ERR_OK Function completed successfully + * \return MYKONOS_ERR_SETRFPLL_LF_ARMERROR ARM Command to set RF PLL loop filter bandwidth failed + * \return MYKONOS_ERR_SETRFPLL_LF_INV_TXRX_LOOPBANDWIDTH Invalid Tx/Rx value bandwith + * \return MYKONOS_ERR_SETRFPLL_LF_PLLNAME Invalid pllName requested + * \return MYKONOS_ERR_SETRFPLL_LF_INV_STABILITY Invalid stability range, valid range is 3-15 + */ +mykonosErr_t MYKONOS_setRfPllLoopFilter(mykonosDevice_t *device, mykonosRfPllName_t pllName, uint16_t loopBandwidth_kHz, uint8_t stability) +{ + const uint8_t SETCMD_OPCODE = 0x0A; + const uint8_t SET_PLL_BANDWIDTH = 0x6D; + const uint16_t LOOP_BW_HIGH = 750; + + uint16_t LOOP_BW_LOW = 50; + uint8_t extData[4] = {0}; + uint8_t cmdStatusByte = 0; + mykonosErr_t retVal = MYKONOS_ERR_OK; + mykonosErr_t errLoopBw = MYKONOS_ERR_OK; + uint32_t timeoutMs = 1000; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setRfPllLoopFilter()\n"); +#endif + + switch (pllName) + { + case RX_PLL: + extData[1] = 0x00; + LOOP_BW_LOW = 50; + errLoopBw = MYKONOS_ERR_SETRFPLL_LF_INV_TXRX_LOOPBANDWIDTH; + break; + case TX_PLL: + extData[1] = 0x10; + LOOP_BW_LOW = 50; + errLoopBw = MYKONOS_ERR_SETRFPLL_LF_INV_TXRX_LOOPBANDWIDTH; + break; + case SNIFFER_PLL: +#if 0 /* Set for Sniffer PLL loop bandwidth is not supported */ + extData[1] = 0x20; + LOOP_BW_LOW = 500; + errLoopBw = MYKONOS_ERR_SETRFPLL_LF_INV_SNF_LOOPBANDWIDTH; + break; +#endif + default: + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETRFPLL_LF_PLLNAME, + getMykonosErrorMessage(MYKONOS_ERR_SETRFPLL_LF_PLLNAME)); + return MYKONOS_ERR_SETRFPLL_LF_PLLNAME; + } + } + + /* Range check for loopBandwidth - Should be between 50kHz and 750kHz for TX/RX and between 500kHz and 750 for SRX*/ + if ((loopBandwidth_kHz< LOOP_BW_LOW) || (loopBandwidth_kHz >LOOP_BW_HIGH)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, errLoopBw, + getMykonosErrorMessage(errLoopBw)); + return errLoopBw; + } + + /* Range check for stability - Should be between 3 and 15 */ + if ((stability < 3) || (stability > 15)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETRFPLL_LF_INV_STABILITY, + getMykonosErrorMessage(MYKONOS_ERR_SETRFPLL_LF_INV_STABILITY)); + return MYKONOS_ERR_SETRFPLL_LF_INV_STABILITY; + } + + /* Generate payload for SET command */ + extData[0] = SET_PLL_BANDWIDTH; + /*left shift and truncate left side*/ + extData[1] |= stability; + extData[2] = (uint8_t)(loopBandwidth_kHz & 0xFF); //full first byte + extData[3] = (uint8_t)(loopBandwidth_kHz >> 8); //two extra bits + + /* executing the SET command */ + retVal = MYKONOS_sendArmCommand(device, SETCMD_OPCODE, &extData[0], sizeof(extData)); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + /* waiting for command to complete */ + retVal = MYKONOS_waitArmCmdStatus(device, SETCMD_OPCODE, timeoutMs, &cmdStatusByte); + + /* performing command status check */ + if (retVal != MYKONOS_ERR_OK) + { + if (cmdStatusByte > 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETRFPLL_LF_ARMERROR, + getMykonosErrorMessage(MYKONOS_ERR_SETRFPLL_LF_ARMERROR)); + return MYKONOS_ERR_SETRFPLL_LF_ARMERROR; + } + + return retVal; + } + + return retVal; +} + +/** + * \brief Gets the RF PLL loop filter bandwidth and stability. + * + * This function is used to get the RF PLL loop bandwidth. It can get the RX PLL, TX PLL + * Sniffer PLL. + * + * \pre Command can be called in Radio Off state or On state. ARM must be initialized. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * - device->spiSettings + * - device->clocks->deviceClock_kHz + * + * \param device is structure pointer to the MYKONOS data structure containing settings + * \param pllName Name of the PLL for which to read the frequency + * \param loopBandwidth_kHz RF PLL loop bandwidth for the PLL specified + * \param stability RF PLL loop stability + * + * \retval MYKONOS_ERR_OK Function completed successfully + * \retval MYKONOS_ERR_GETRFPLL_LF_INV_PLLNAME Invalid PLL name, can not get PLL frequency. Use PLL name ENUM. + * \retval MYKONOS_ERR_GETRFPLL_LF_ARMERROR ARM Command to get RF PLL frequency failed + * \retval MYKONOS_ERR_GETRFPLL_LF_NULLPARAM input parameter is NULL + */ +mykonosErr_t MYKONOS_getRfPllLoopFilter(mykonosDevice_t *device, mykonosRfPllName_t pllName, uint16_t *loopBandwidth_kHz, uint8_t *stability) +{ + const uint8_t GET_PLL_BANDWIDTH = 0x6D; + + mykonosErr_t retVal = MYKONOS_ERR_OK; + uint8_t armData[8] = {0, 0, 0, 0, 0, 0, 0, 0}; + uint8_t extData[2] = {GET_PLL_BANDWIDTH, 0}; + uint32_t timeoutMs = 0; + uint8_t cmdStatusByte = 0; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getRfPllLoopFilter()\n"); +#endif + + /* Check for NULL */ + if ((loopBandwidth_kHz == NULL)|| (stability == NULL)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETRFPLL_LF_NULLPARAM, + getMykonosErrorMessage(MYKONOS_ERR_GETRFPLL_LF_NULLPARAM)); + return MYKONOS_ERR_GETRFPLL_LF_NULLPARAM; + } + + switch(pllName) + { + case RX_PLL: extData[1] = 0x00; break; + case TX_PLL: extData[1] = 0x10; break; + case SNIFFER_PLL: extData[1] = 0x20; break; + default: + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETRFPLL_LF_INV_PLLNAME, + getMykonosErrorMessage(MYKONOS_ERR_GETRFPLL_LF_INV_PLLNAME)); + return MYKONOS_ERR_GETRFPLL_LF_INV_PLLNAME; + } + } + /* executing the GET command */ + retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_GET_OPCODE, &extData[0], sizeof(extData)); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + timeoutMs = 1000; + + /* waiting for command to complete */ + retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_GET_OPCODE, timeoutMs, &cmdStatusByte); + + /* performing command status check */ + if (retVal != MYKONOS_ERR_OK) + { + if (cmdStatusByte > 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETRFPLL_LF_ARMERROR, + getMykonosErrorMessage(MYKONOS_ERR_GETRFPLL_LF_ARMERROR)); + return MYKONOS_ERR_GETRFPLL_LF_ARMERROR; + } + + return retVal; + } + + /* Read from ARM memory */ + retVal = MYKONOS_readArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR, &armData[0], 8, 1); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + /* Assign to variables */ + *stability = armData[3]; + *loopBandwidth_kHz = (((uint16_t)armData[1]) << 8) | ((uint16_t)armData[0]); + + return MYKONOS_ERR_OK; +} + +/** + * \brief Enable/ Disable Digital DC Offset channels using the channel mask. + * The mask can be a combination of the following channel values ( ::mykonosRxDcOffsettEn_t ). + * + * Channel | Value | Channel description + * -------------------------|---------|-------------------------- + * MYK_DC_OFFSET_ALL_OFF | 0x00 | Disable all the channels + * MYK_DC_OFFSET_RX1 | 0x01 | Enables Rx1 + * MYK_DC_OFFSET_RX2 | 0x02 | Enables Rx1 + * MYK_DC_OFFSET_SNF | 0x04 | Enables Sniffer + * MYK_DC_OFFSET_ORX | 0x08 | Enables ORx + * MYK_DC_OFFSET_AVAILABLE | 0x0F | Enables all the channels + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device Pointer to the Mykonos device data structure containing settings + * \param enableMask with bits of channels to be enabled. + * + * \retval MYKONOS_ERR_DIG_DC_OFFSET_INV_ENABLE_MASK enable mask passed to the function is invalid, refer mykonosRxDcOffsettEn_t enum. + * \retval MYKONOS_ERR_OK Function completed successfully + */ +mykonosErr_t MYKONOS_setDigDcOffsetEn(mykonosDevice_t *device, uint8_t enableMask) +{ + mykonosErr_t retVal = MYKONOS_ERR_OK; + uint16_t REG_ADDRESS = 0x00; + uint8_t dataToWrite = 0x00; + + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setDigDcOffsetEn()\n"); +#endif + + if (enableMask & ~((uint8_t)MYK_DC_OFFSET_AVAILABLE)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DIG_DC_OFFSET_INV_ENABLE_MASK, + getMykonosErrorMessage(MYKONOS_ERR_DIG_DC_OFFSET_INV_ENABLE_MASK)); + return MYKONOS_ERR_DIG_DC_OFFSET_INV_ENABLE_MASK; + } + + REG_ADDRESS = MYKONOS_ADDR_DIGITAL_DC_OFFSET_CONFIG; /* Address for Rx Digital tracking Enable bits register */ + if (enableMask & ((uint8_t)MYK_DC_OFFSET_RX1 | (uint8_t)MYK_DC_OFFSET_RX2)) /* Enable / Disable Rx1 and/or Rx2 */ + { + dataToWrite |= ((enableMask & ((uint8_t)MYK_DC_OFFSET_RX1 |(uint8_t) MYK_DC_OFFSET_RX2)) << 1 ); + } + CMB_SPIWriteField(device->spiSettings, REG_ADDRESS, dataToWrite, 0x06,0); /* Write RX enable bits to the register */ + + dataToWrite = 0x0; /* Reset dataToWrite */ + REG_ADDRESS = MYKONOS_DIGITAL_DC_OFFSET_CH3_TRACKING; /* Address for ORx and Sniffer Digital trackingEnable bits register */ + if (enableMask & ((uint8_t)MYK_DC_OFFSET_SNF | (uint8_t)MYK_DC_OFFSET_ORX)) /* Check for channel ORx and/or Sniffer */ + { + dataToWrite |= ((enableMask & ((uint8_t)MYK_DC_OFFSET_SNF | (uint8_t)MYK_DC_OFFSET_ORX))>>2); + } + CMB_SPIWriteField(device->spiSettings, REG_ADDRESS, dataToWrite, 0x03,0); /* Write Loopback, ORx and Sniffer enable bits to the register */ + + return retVal; +} + +/** + * \brief reads Enable/ Disable channels Digital DC Offset and returns a mask of it. + * The mask returned will be a combination of the following channel values ( ::mykonosRxDcOffsettEn_t ). + * + * Channel | Value | Channel description + * -------------------------|---------|-------------------------- + * MYK_DC_OFFSET_ALL_OFF | 0x00 | All channels are disabled + * MYK_DC_OFFSET_RX1 | 0x01 | Rx1 is enabled + * MYK_DC_OFFSET_RX2 | 0x02 | Rx2 is enabled + * MYK_DC_OFFSET_SNF | 0x04 | Sniffer is enabled + * MYK_DC_OFFSET_ORX | 0x08 | ORx is enabled + * MYK_DC_OFFSET_AVAILABLE | 0x0F | All channels are enabled + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device Pointer to the Mykonos device data structure containing settings + * \param enableMask pointer to the variable to store Enable mask of channels + * + * \retval MYKONOS_ERR_DIG_DC_OFFSET_NULL_ENABLE_MASK enableMask is NULL + * \retval MYKONOS_ERR_OK Function completed successfully + */ +mykonosErr_t MYKONOS_getDigDcOffsetEn(mykonosDevice_t *device,uint8_t *enableMask) +{ + mykonosErr_t retVal = MYKONOS_ERR_OK; + uint16_t REG_ADDRESS = 0; + uint8_t readbackData = 0; + uint8_t enableMaskData = 0; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getDigDcOffsetEn()\n"); +#endif + + if (enableMask == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DIG_DC_OFFSET_NULL_ENABLE_MASK, + getMykonosErrorMessage(MYKONOS_ERR_DIG_DC_OFFSET_NULL_ENABLE_MASK)); + return MYKONOS_ERR_DIG_DC_OFFSET_NULL_ENABLE_MASK; + } + + REG_ADDRESS = MYKONOS_ADDR_DIGITAL_DC_OFFSET_CONFIG; /* register address of Rx1 and Rx2 enable bits*/ + CMB_SPIReadField(device->spiSettings, REG_ADDRESS, &readbackData, 0x06,0); + enableMaskData |= (readbackData>>1); /* adjust bits to match channel :refer enum mykonosRfDcOffsettEn_t. */ + + readbackData = 0x00; + REG_ADDRESS = MYKONOS_DIGITAL_DC_OFFSET_CH3_TRACKING; /* register address of Orx and sniffer enable bits*/ + CMB_SPIReadField(device->spiSettings, REG_ADDRESS, &readbackData, 0x03,0); + enableMaskData |= (uint8_t)(readbackData<<2); /* adjust bits to match channel :refer enum mykonosRfDcOffsettEn_t. */ + + *enableMask = enableMaskData; + + return retVal; +} + +/** + * \brief This function will configure the path delay settings for all the features: + * DPD, VSWR and CLGC. + * + * A DPD device is required. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * - device->profilesValid + * + * \param device Pointer to the Mykonos device data structure containing settings + * \param pathDelay pointer to structure of type ::mykonosPathdelay_t to be programmed + * + * \retval MYKONOS_ERR_SET_PATH_DELAY_NULL_PARAM pathDelay is null + * \retval MYKONOS_ERR_SET_PATH_DELAY_PARAM_OUT_OF_RANGE path delay valid range is from 0 to 4095 at 1/16 sample resolution of ORx sample rate + * \retval MYKONOS_ERR_OK Function completed successfully + */ +mykonosErr_t MYKONOS_setPathDelay(mykonosDevice_t *device, mykonosPathdelay_t *pathDelay) +{ + mykonosErr_t retVal = MYKONOS_ERR_OK; + uint8_t armFieldValue[16] = {0}; + uint8_t extData[3] = {(uint8_t)MYKONOS_ARM_OBJECTID_TRACKING_CAL_CONTROL, (uint8_t)SET_PATH_DELAY, 0}; + uint8_t writeSize = 0; + uint8_t fifoDel[4] = {0}; + uint8_t interpIndex[4] = {0}; + uint32_t *delPointer = &pathDelay->forwardPathDelayCh1; + uint8_t i = 0; + + const uint32_t RANGE_PATH_DELAY = 4095; + const uint8_t PATH_DELAY_SIZE = 4; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setPathDelay()\n"); +#endif + + if (pathDelay == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SET_PATH_DELAY_NULL_PARAM, + getMykonosErrorMessage(MYKONOS_ERR_SET_PATH_DELAY_NULL_PARAM)); + return MYKONOS_ERR_SET_PATH_DELAY_NULL_PARAM; + } + + /* Loop to set the ARM memory data */ + for (i = 0; i < PATH_DELAY_SIZE ; i++) + { + /* Verify all the data in the structure is in range */ + if (*delPointer > RANGE_PATH_DELAY) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SET_PATH_DELAY_PARAM_OUT_OF_RANGE, + getMykonosErrorMessage(MYKONOS_ERR_SET_PATH_DELAY_PARAM_OUT_OF_RANGE)); + return MYKONOS_ERR_SET_PATH_DELAY_PARAM_OUT_OF_RANGE; + } + + fifoDel[i] = (uint8_t)(*delPointer >> 4); + interpIndex[i] = (uint8_t)(*delPointer - (fifoDel[i] * 16)); + + delPointer++; + } + + if ((device->tx->vswrConfig == NULL) || ((pathDelay->reversePathDelayCh1 == 0) && (pathDelay->reversePathDelayCh2 == 0))) + { + armFieldValue[0] = interpIndex[0]; + armFieldValue[1] = 0; + armFieldValue[2] = fifoDel[0]; + armFieldValue[3] = 0; + armFieldValue[4] = interpIndex[2]; + armFieldValue[5] = 0; + armFieldValue[6] = fifoDel[2]; + armFieldValue[7] = 0; + extData[2] = 0; + writeSize = 8; + } + else + { + armFieldValue[0] = interpIndex[0]; + armFieldValue[1] = 0; + armFieldValue[2] = fifoDel[0]; + armFieldValue[3] = 0; + armFieldValue[4] = interpIndex[2]; + armFieldValue[5] = 0; + armFieldValue[6] = fifoDel[2]; + armFieldValue[7] = 0; + armFieldValue[8] = interpIndex[1]; + armFieldValue[9] = 0; + armFieldValue[10] = fifoDel[1]; + armFieldValue[11] = 0; + armFieldValue[12] = interpIndex[3]; + armFieldValue[13] = 0; + armFieldValue[14] = fifoDel[3]; + armFieldValue[15] = 0; + extData[2] = 1; + writeSize = 16; + } + + retVal = MYKONOS_writeArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR, &armFieldValue[0], writeSize); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_SET_OPCODE, &extData[0], sizeof(extData)); + + return retVal; +} + +/** + * \brief This function will read the current path delay settings for the selected calibration. + * + * A DPD-enabled transceiver is required + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * - device->profilesValid + * + * \param device Pointer to the Mykonos device data structure containing settings + * \param select path delay status selection from ::mykonosPathDelaySel_t + * \param pathDelay pointer to structure of type ::mykonosPathdelay_t to store the read back path delay + * + * \retval MYKONOS_ERR_GET_PATH_DELAY_NULL_PARAM pathDelay is null + * \retval MYKONOS_ERR_GET_PATH_DELAY_INVALID_SELECTION invalid selection for getting the path delay, valid selections are given by mykonosPathDelaySel_t + * \retval MYKONOS_ERR_GET_PATH_DELAY_ARMERRFLAG Arm error while reading path delay for the selected calibration status + * \retval MYKONOS_ERR_OK Function completed successfully + */ +mykonosErr_t MYKONOS_getPathDelay(mykonosDevice_t *device, mykonosPathDelaySel_t select, mykonosPathdelay_t *pathDelay) +{ + uint8_t extData[3] = {(uint8_t)MYKONOS_ARM_OBJECTID_CAL_STATUS, (uint8_t)MYKONOS_ARM_OBJECTID_VSWRCONFIG, 0}; + uint8_t armData[80] = {0}; + uint32_t timeoutMs = 0; + uint8_t cmdStatusByte = 0; + uint32_t *delPointer = &pathDelay->forwardPathDelayCh1; + uint8_t channel = 0; + uint8_t addr[4] = {0}; + mykonosErr_t retVal = MYKONOS_ERR_OK; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getPathDelay()\n"); +#endif + + if (pathDelay == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GET_PATH_DELAY_NULL_PARAM, + getMykonosErrorMessage(MYKONOS_ERR_GET_PATH_DELAY_NULL_PARAM)); + return MYKONOS_ERR_GET_PATH_DELAY_NULL_PARAM; + } + + switch (select) + { + case MYK_DPD_PATH_DELAY: + extData[1] = MYKONOS_ARM_OBJECTID_DPDCONFIG; + addr[0] = 24; + addr[1] = 26; + addr[2] = 0; + addr[3] = 0; + break; + case MYK_CLGC_PATH_DELAY: + extData[1] = MYKONOS_ARM_OBJECTID_CLGCCONFIG; + addr[0] = 60; + addr[1] = 62; + addr[2] = 0; + addr[3] = 0; + break; + case MYK_VSWR_PATH_DELAY: + extData[1] = MYKONOS_ARM_OBJECTID_VSWRCONFIG; + addr[0] = 72; + addr[1] = 74; + addr[2] = 76; + addr[3] = 78; + break; + default: + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GET_PATH_DELAY_INVALID_SELECTION, + getMykonosErrorMessage(MYKONOS_ERR_GET_PATH_DELAY_INVALID_SELECTION)); + return MYKONOS_ERR_GET_PATH_DELAY_INVALID_SELECTION; + } + + /* reading 2 channels, channel being the channel selector */ + for (channel = 0; channel < 2; channel++) + { + if (channel) + { + delPointer++; + } + + extData[2] = channel; + + retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_GET_OPCODE, &extData[0], sizeof(extData)); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + timeoutMs = 1000; + retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_GET_OPCODE, timeoutMs, &cmdStatusByte); + if (retVal != MYKONOS_ERR_OK) + { + /* throw more specific error message instead of returning error code from waitArmCmdStatus */ + if (cmdStatusByte > 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GET_PATH_DELAY_ARMERRFLAG, + getMykonosErrorMessage(MYKONOS_ERR_GET_PATH_DELAY_ARMERRFLAG)); + return MYKONOS_ERR_GET_PATH_DELAY_ARMERRFLAG; + } + + return retVal; + } + + if (cmdStatusByte > 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GET_PATH_DELAY_ARMERRFLAG, + getMykonosErrorMessage(MYKONOS_ERR_GET_PATH_DELAY_ARMERRFLAG)); + return MYKONOS_ERR_GET_PATH_DELAY_ARMERRFLAG; + } + + /* read status from ARM memory */ + retVal = MYKONOS_readArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR, &armData[0], sizeof(armData), 1); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + *delPointer = ((uint32_t)(armData[addr[1]]) * 16) + (uint32_t)(armData[addr[0]]); + delPointer++; + if ((addr[2] != 0) && (addr[3] != 0)) + { + /* reverse path delay only applies to VSWR */ + *delPointer = ((uint32_t)(armData[addr[3]]) * 16) + (uint32_t)(armData[addr[2]]); + } + else + { + /* the rest of path delays will not have a reverse delay value */ + *delPointer = 0; + } + } + + return retVal; +} + +/** + * \brief This function reads the current error counters for all the DPD error codes from ::mykonosDpdErrors_t. + * + * A DPD-enabled transceiver is required + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * - device->profilesValid + * + * \param device Pointer to the Mykonos device data structure containing settings + * \param txChannel Tx channel selection from ::mykonosTxChannels_t + * \param dpdErrCnt pointer to structure of type ::mykonosDpdErrorCounters_t to store the read back error counters + * + * \retval MYKONOS_ERR_GETDPD_ERROR_CNT_NULLPARAM dpdErrCnt is null + * \retval MYKONOS_ERR_GETDPD_ERROR_CNT_INV_CH invalid selection for getting the error counters tx channel, only valid values are Tx1 and Tx2 + * \retval MYKONOS_ERR_GETDPD_ERROR_CNT_ARMERRFLAG Arm error while reading the error counters for the DPD status + * \retval MYKONOS_ERR_OK Function completed successfully + */ +mykonosErr_t MYKONOS_getDpdErrorCounters(mykonosDevice_t *device, mykonosTxChannels_t txChannel, mykonosDpdErrorCounters_t *dpdErrCnt) +{ + uint8_t extData[3] = {MYKONOS_ARM_OBJECTID_CAL_STATUS, MYKONOS_ARM_OBJECTID_DPDCONFIG, 0}; + uint8_t armData[200] = {0}; + uint32_t timeoutMs = 0; + uint8_t cmdStatusByte = 0; + uint8_t loop = 0; + uint8_t index = 0; + uint8_t channelSelect = 0; + mykonosErr_t retVal = MYKONOS_ERR_OK; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getDpdErrorCounters()\n"); +#endif + + if (dpdErrCnt == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETDPD_ERROR_CNT_NULLPARAM, + getMykonosErrorMessage(MYKONOS_ERR_GETDPD_ERROR_CNT_NULLPARAM)); + return MYKONOS_ERR_GETDPD_ERROR_CNT_NULLPARAM; + } + + switch (txChannel) + { + case TX1: + channelSelect = 0; + break; + case TX2: + channelSelect = 1; + break; + default: + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETDPD_ERROR_CNT_INV_CH, + getMykonosErrorMessage(MYKONOS_ERR_GETDPD_ERROR_CNT_INV_CH)); + return MYKONOS_ERR_GETDPD_ERROR_CNT_INV_CH; + } + } + + extData[2] = channelSelect; + + retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_GET_OPCODE, &extData[0], sizeof(extData)); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + timeoutMs = 1000; + retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_GET_OPCODE, timeoutMs, &cmdStatusByte); + if (retVal != MYKONOS_ERR_OK) + { + if (cmdStatusByte > 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETDPD_ERROR_CNT_ARMERRFLAG, + getMykonosErrorMessage(MYKONOS_ERR_GETDPD_ERROR_CNT_ARMERRFLAG)); + return MYKONOS_ERR_GETDPD_ERROR_CNT_ARMERRFLAG; + } + + return retVal; + } + + if (cmdStatusByte > 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETDPD_ERROR_CNT_ARMERRFLAG, + getMykonosErrorMessage(MYKONOS_ERR_GETDPD_ERROR_CNT_ARMERRFLAG)); + return MYKONOS_ERR_GETDPD_ERROR_CNT_ARMERRFLAG; + } + + /* read status from ARM memory */ + retVal = MYKONOS_readArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR, &armData[0], sizeof(armData), 1); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + dpdErrCnt->dpdErrorCount = ((uint32_t)(armData[67]) << 24) | ((uint32_t)(armData[66]) << 16) | ((uint32_t)(armData[65]) << 8) | (uint32_t)(armData[64]); + index = 68; + for (loop = 1; loop < (uint8_t)MYK_DPD_ERROR_END; loop++) + { + dpdErrCnt->errorCounter[loop] = ((uint32_t)(armData[index + 3]) << 24) | ((uint32_t)(armData[index + 2]) << 16) | ((uint32_t)(armData[index + 1]) << 8) | (uint32_t)(armData[index]); + index +=4; + } + + return MYKONOS_ERR_OK; +} + +/** + * \brief DPD feature to set the bypassing actuator when Tx signal power is below a programmable threshold given in + * ::mykonosDpdBypassConfig_t lowPowerActuatorBypassLevel. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * - device->profilesValid + * + * \param device Pointer to the Mykonos device data structure containing settings + * \param actConfig Pointer to actuator structure of type ::mykonosDpdBypassConfig_t which contains the settings to be programmed + * + * \retval MYKONOS_ERR_SETDPDACT_NULL_ACTSTRUCT passed structure is null + * \retval MYKONOS_ERR_SETDPDACT_INV_ACTMODE invalid mode in actConfig->lowPowerActuatorBypassMode for valid modes ::mykonosDpdResetMode_t + * \retval MYKONOS_ERR_SETDPDACT_INV_LEVEL actConfig->lowPowerActuatorBypassLevel outside the range, valid range is 0 to 6000 (0 to 60dB) + * \retval MYKONOS_ERR_OK Function completed successfully + */ +mykonosErr_t MYKONOS_setDpdBypassConfig(mykonosDevice_t *device, mykonosDpdBypassConfig_t *actConfig) +{ + mykonosErr_t retVal = MYKONOS_ERR_OK; + uint8_t armFieldValue[4] = {0}; + uint8_t byteOffset = 62; + + const uint16_t LEVEL_RANGE_CHECK = 6000; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setDpdBypassConfig()\n"); +#endif + + if (actConfig == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETDPDACT_NULL_ACTSTRUCT, + getMykonosErrorMessage(MYKONOS_ERR_SETDPDACT_NULL_ACTSTRUCT)); + return MYKONOS_ERR_SETDPDACT_NULL_ACTSTRUCT; + } + + if (actConfig->bypassActuatorMode >= MYK_DPD_RESET_END) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETDPDACT_INV_ACTMODE, + getMykonosErrorMessage(MYKONOS_ERR_SETDPDACT_INV_ACTMODE)); + return MYKONOS_ERR_SETDPDACT_INV_ACTMODE; + } + + if (actConfig->bypassActuatorLevel > LEVEL_RANGE_CHECK) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETDPDACT_INV_LEVEL, + getMykonosErrorMessage(MYKONOS_ERR_SETDPDACT_INV_LEVEL)); + return MYKONOS_ERR_SETDPDACT_INV_LEVEL; + } + + armFieldValue[0] = (actConfig->bypassActuatorEn > 0) ? 1 : 0; + armFieldValue[1] = (uint8_t)(actConfig->bypassActuatorMode); + armFieldValue[2] = (uint8_t)(actConfig->bypassActuatorLevel & 0xFF); + armFieldValue[3] = (uint8_t)((actConfig->bypassActuatorLevel >> 8) & 0xFF); + + retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_DPDCONFIG, byteOffset, &armFieldValue[0], sizeof(armFieldValue)); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + return MYKONOS_ERR_OK; +} + +/** + * \brief Get configuration for bypassing DPD actuator + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * - device->profilesValid + * + * \param device Pointer to the Mykonos device data structure containing settings + * \param actConfig actuator structure of type ::mykonosDpdBypassConfig_t + * + * \retval MYKONOS_ERR_GETDPDACT_NULL_ACTSTRUCT passed structure is null + * \retval MYKONOS_ERR_OK Function completed successfully + */ +mykonosErr_t MYKONOS_getDpdBypassConfig(mykonosDevice_t *device, mykonosDpdBypassConfig_t *actConfig) +{ + mykonosErr_t retVal = MYKONOS_ERR_OK; + uint8_t armFieldValue[4] = {0}; + uint8_t byteOffset = 62; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getDpdBypassConfig()\n"); +#endif + + if (actConfig == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETDPDACT_NULL_ACTSTRUCT, + getMykonosErrorMessage(MYKONOS_ERR_GETDPDACT_NULL_ACTSTRUCT)); + return MYKONOS_ERR_GETDPDACT_NULL_ACTSTRUCT; + } + + retVal = MYKONOS_readArmConfig(device, MYKONOS_ARM_OBJECTID_DPDCONFIG, byteOffset, &armFieldValue[0], sizeof(armFieldValue)); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + actConfig->bypassActuatorEn = armFieldValue[0]; + actConfig->bypassActuatorMode = (mykonosDpdResetMode_t)armFieldValue[1]; + actConfig->bypassActuatorLevel = (uint16_t)(((uint16_t)(armFieldValue[3]) << 8) | (uint16_t)(armFieldValue[2])); + + return MYKONOS_ERR_OK; +} + +/** + * \brief DPD feature to set the actuator gain difference check. + * If the gain before and after the actuator exceeds the value actCheck->actuatorGainCheckLevel an error will be issued + * and the actuator will reset depending on the actCheck->actuatorGainCheckMode. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * - device->profilesValid + * + * \param device Pointer to the Mykonos device data structure containing settings + * \param actCheck Pointer to structure of type mykonosDpdActuatorCheck_t which contains the settings to be programmed + * + * \retval MYKONOS_ERR_SETDPDACTCHECK_NULL_ACTSTRUCT passed structure is null + * \retval MYKONOS_ERR_SETDPDACTCHECK_INV_ACTMODE invalid mode in actCheck->actuatorGainCheckMode for valid modes ::mykonosDpdResetMode_t + * \retval MYKONOS_ERR_SETDPDACTCHECK_INV_LEVEL actCheck->actuatorGainCheckLevel outside the range, valid range is from 0 to 3000 (0 to 30dB) + * \retval MYKONOS_ERR_OK Function completed successfully + */ +mykonosErr_t MYKONOS_setDpdActuatorCheck(mykonosDevice_t *device, mykonosDpdActuatorCheck_t *actCheck) +{ + mykonosErr_t retVal = MYKONOS_ERR_OK; + uint8_t armFieldValue[4] = {0}; + uint8_t byteOffset = 58; + + const uint16_t LEVEL_RANGE_CHECK = 3000; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setDpdActuatorCheck()\n"); +#endif + + if (actCheck == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETDPDACTCHECK_NULL_ACTSTRUCT, + getMykonosErrorMessage(MYKONOS_ERR_SETDPDACTCHECK_NULL_ACTSTRUCT)); + return MYKONOS_ERR_SETDPDACTCHECK_NULL_ACTSTRUCT; + } + + if (actCheck->actuatorGainCheckMode >= MYK_DPD_RESET_END) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETDPDACTCHECK_INV_ACTMODE, + getMykonosErrorMessage(MYKONOS_ERR_SETDPDACTCHECK_INV_ACTMODE)); + return MYKONOS_ERR_SETDPDACTCHECK_INV_ACTMODE; + } + + if (actCheck->actuatorGainCheckLevel > LEVEL_RANGE_CHECK) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETDPDACTCHECK_INV_LEVEL, + getMykonosErrorMessage(MYKONOS_ERR_SETDPDACTCHECK_INV_LEVEL)); + return MYKONOS_ERR_SETDPDACTCHECK_INV_LEVEL; + } + + armFieldValue[0] = (actCheck->actuatorGainCheckEn > 0) ? 1 : 0; + armFieldValue[1] = (uint8_t)(actCheck->actuatorGainCheckMode); + armFieldValue[2] = (uint8_t)(actCheck->actuatorGainCheckLevel & 0xFF); + armFieldValue[3] = (uint8_t)((actCheck->actuatorGainCheckLevel >> 8) & 0xFF); + + retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_DPDCONFIG, byteOffset, &armFieldValue[0], sizeof(armFieldValue)); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + return MYKONOS_ERR_OK; +} + + +/** + * \brief Get configuration for DPD actuator check + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * - device->profilesValid + * + * \param device Pointer to the Mykonos device data structure containing settings + * \param actCheck Pointer to structure of type mykonosDpdActuatorCheck_t which will contain the programmed settings + * + * \retval MYKONOS_ERR_GETDPDACTCHECK_NULL_ACTSTRUCT passed structure is null + * \retval MYKONOS_ERR_OK Function completed successfully + */ +mykonosErr_t MYKONOS_getDpdActuatorCheck(mykonosDevice_t *device, mykonosDpdActuatorCheck_t *actCheck) +{ + mykonosErr_t retVal = MYKONOS_ERR_OK; + uint8_t armFieldValue[4] = {0}; + uint8_t byteOffset = 58; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getDpdActuatorCheck()\n"); +#endif + + if (actCheck == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETDPDACTCHECK_NULL_ACTSTRUCT, + getMykonosErrorMessage(MYKONOS_ERR_GETDPDACTCHECK_NULL_ACTSTRUCT)); + return MYKONOS_ERR_GETDPDACTCHECK_NULL_ACTSTRUCT; + } + + retVal = MYKONOS_readArmConfig(device, MYKONOS_ARM_OBJECTID_DPDCONFIG, byteOffset, &armFieldValue[0], sizeof(armFieldValue)); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + actCheck->actuatorGainCheckEn = armFieldValue[0]; + actCheck->actuatorGainCheckMode = (mykonosDpdResetMode_t)armFieldValue[1]; + actCheck->actuatorGainCheckLevel = (uint16_t)(((uint16_t)(armFieldValue[3]) << 8) | (uint16_t)(armFieldValue[2])); + + return MYKONOS_ERR_OK; +} + + +/** + * \brief CLGC feature to set the TX attenuation tuning range to a relative range around a nominal value + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * - device->profilesValid + * + * \param device Pointer to the Mykonos device data structure containing settings + * \param attRangeCfg Pointer to structure of type mykonosClgcAttenTuningConfig_t which contains the settings to be programmed + * + * \retval MYKONOS_ERR_CFGCLGC_TXORX_PROFILE_INV Tx and ObsRx profiles must be valid to use the CLGC feature + * \retval MYKONOS_ERR_CLGCATTENTUNCFG_NULL_ATTRANGECFGSTRUCT Passed structure is null + * \retval MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_MODE Invalid mode in attRangeCfg member, for valid modes ::mykonosClgcAttenTuningMode_t + * \retval MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_PRESET Invalid AttenTuningPreset in attRangeCfg member, valid range is from 0 to 839 (0 to 41.95dB) + * \retval MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_RANGE Invalid AttenTuningRange in attRangeCfg member, valid range is from 0 to 420 (0 to 21dB) + * \retval MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_TX1_SETTINGS Invalid Tx1 AttenTuningRange and AttenTuningPreset combination + * \retval MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_TX2_SETTINGS Invalid Tx2 AttenTuningRange and AttenTuningPreset combination + * \retval MYKONOS_ERR_OK Function completed successfully + */ +mykonosErr_t MYKONOS_setClgcAttenTuningConfig(mykonosDevice_t *device, mykonosClgcAttenTuningConfig_t *attRangeCfg) +{ + mykonosErr_t retVal = MYKONOS_ERR_OK; + uint8_t armFieldValue[10] = {0}; + uint8_t byteOffset = 0x2C; + + const uint16_t PRESET_CHECK = 840; + const uint16_t RANGE_CHECK = 420; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setClgcAttenTuningConfig()\n"); +#endif + + /* CLGC requires Tx and ORx enabled, throw error if both are not enabled */ + if ((device->profilesValid & (TX_PROFILE_VALID | ORX_PROFILE_VALID)) != (TX_PROFILE_VALID | ORX_PROFILE_VALID)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGCLGC_TXORX_PROFILE_INV, + getMykonosErrorMessage(MYKONOS_ERR_CFGCLGC_TXORX_PROFILE_INV)); + return MYKONOS_ERR_CFGCLGC_TXORX_PROFILE_INV; + } + + if (attRangeCfg == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CLGCATTENTUNCFG_NULL_ATTRANGECFGSTRUCT, + getMykonosErrorMessage(MYKONOS_ERR_CLGCATTENTUNCFG_NULL_ATTRANGECFGSTRUCT)); + return MYKONOS_ERR_CLGCATTENTUNCFG_NULL_ATTRANGECFGSTRUCT; + } + + /* Range checks */ + if ((attRangeCfg->tx1AttenTuningLimitMode >= MYK_CLGC_ATTEN_END) || (attRangeCfg->tx2AttenTuningLimitMode >= MYK_CLGC_ATTEN_END)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_MODE, + getMykonosErrorMessage(MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_MODE)); + return MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_MODE; + } + + if ((attRangeCfg->tx1AttenTuningPreset >= PRESET_CHECK) || (attRangeCfg->tx2AttenTuningPreset >= PRESET_CHECK)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_PRESET, + getMykonosErrorMessage(MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_PRESET)); + return MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_PRESET; + } + + if ((attRangeCfg->tx1AttenTuningRange > RANGE_CHECK) || (attRangeCfg->tx2AttenTuningRange > RANGE_CHECK)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_RANGE, + getMykonosErrorMessage(MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_RANGE)); + return MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_RANGE; + } + + if (((attRangeCfg->tx1AttenTuningPreset - attRangeCfg->tx1AttenTuningRange) < 0) || + ((attRangeCfg->tx1AttenTuningPreset + attRangeCfg->tx1AttenTuningRange) > PRESET_CHECK)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_TX1_SETTINGS, + getMykonosErrorMessage(MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_TX1_SETTINGS)); + return MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_TX1_SETTINGS; + } + + if (((attRangeCfg->tx2AttenTuningPreset - attRangeCfg->tx2AttenTuningRange) < 0) || + ((attRangeCfg->tx2AttenTuningPreset + attRangeCfg->tx2AttenTuningRange) > PRESET_CHECK)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_TX2_SETTINGS, + getMykonosErrorMessage(MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_TX2_SETTINGS)); + return MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_TX2_SETTINGS; + } + + armFieldValue[0] = (uint8_t)(attRangeCfg->tx1AttenTuningLimitMode & 0xFF); + armFieldValue[1] = (uint8_t)(attRangeCfg->tx2AttenTuningLimitMode & 0xFF); + armFieldValue[2] = (uint8_t)(attRangeCfg->tx1AttenTuningPreset & 0xFF); + armFieldValue[3] = (uint8_t)((attRangeCfg->tx1AttenTuningPreset >> 8) & 0xFF); + armFieldValue[4] = (uint8_t)(attRangeCfg->tx2AttenTuningPreset & 0xFF); + armFieldValue[5] = (uint8_t)((attRangeCfg->tx2AttenTuningPreset >> 8) & 0xFF); + armFieldValue[6] = (uint8_t)(attRangeCfg->tx1AttenTuningRange & 0xFF); + armFieldValue[7] = (uint8_t)((attRangeCfg->tx1AttenTuningRange >> 8) & 0xFF); + armFieldValue[8] = (uint8_t)(attRangeCfg->tx2AttenTuningRange & 0xFF); + armFieldValue[9] = (uint8_t)((attRangeCfg->tx2AttenTuningRange >> 8) & 0xFF); + + retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_CLGCCONFIG, byteOffset, &armFieldValue[0], sizeof(armFieldValue)); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + return MYKONOS_ERR_OK; +} + + +/** + * \brief Get configuration for CLGC Tx attenuation tuning range. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * - device->profilesValid + * + * \param device Pointer to the Mykonos device data structure containing settings + * \param attRangeCfg Pointer to structure of type mykonosClgcAttenTuningConfig_t which will contain the programmed settings + * + * \retval MYKONOS_ERR_CLGCATTENTUNCFGGET_NULL_ATTRANGECFGSTRUCT passed structure is null + * \retval MYKONOS_ERR_OK Function completed successfully + */ +mykonosErr_t MYKONOS_getClgcAttenTuningConfig(mykonosDevice_t *device, mykonosClgcAttenTuningConfig_t *attRangeCfg) +{ + mykonosErr_t retVal = MYKONOS_ERR_OK; + uint8_t armFieldValue[10] = {0}; + uint8_t byteOffset = 0x2C; + +#if (MYKONOS_VERBOSE == 1) + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getClgcAttenTuningConfig()\n"); +#endif + + if (attRangeCfg == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CLGCATTENTUNCFGGET_NULL_ATTRANGECFGSTRUCT, + getMykonosErrorMessage(MYKONOS_ERR_CLGCATTENTUNCFGGET_NULL_ATTRANGECFGSTRUCT)); + return MYKONOS_ERR_CLGCATTENTUNCFGGET_NULL_ATTRANGECFGSTRUCT; + } + + retVal = MYKONOS_readArmConfig(device, MYKONOS_ARM_OBJECTID_CLGCCONFIG, byteOffset, &armFieldValue[0], sizeof(armFieldValue)); + if (retVal != MYKONOS_ERR_OK) + { + return retVal; + } + + attRangeCfg->tx1AttenTuningLimitMode = (mykonosClgcAttenTuningMode_t)armFieldValue[0]; + attRangeCfg->tx2AttenTuningLimitMode = (mykonosClgcAttenTuningMode_t)armFieldValue[1]; + attRangeCfg->tx1AttenTuningPreset = (uint16_t)(((uint16_t)(armFieldValue[3]) << 8) | (uint16_t)(armFieldValue[2])); + attRangeCfg->tx2AttenTuningPreset = (uint16_t)(((uint16_t)(armFieldValue[5]) << 8) | (uint16_t)(armFieldValue[4])); + attRangeCfg->tx1AttenTuningRange = (uint16_t)(((uint16_t)(armFieldValue[7]) << 8) | (uint16_t)(armFieldValue[6])); + attRangeCfg->tx2AttenTuningRange = (uint16_t)(((uint16_t)(armFieldValue[9]) << 8) | (uint16_t)(armFieldValue[8])); + + return MYKONOS_ERR_OK; +} diff --git a/datalink814_ge/src/hardware/mykonos/mykonos.h b/datalink814_ge/src/hardware/mykonos/mykonos.h new file mode 100644 index 0000000..b852b58 --- /dev/null +++ b/datalink814_ge/src/hardware/mykonos/mykonos.h @@ -0,0 +1,277 @@ +/*! + * \file mykonos.h + * \brief Contains macro definitions and function prototypes for mykonos.c + * + * Mykonos API version: 1.5.2.3566 + */ + +/** +* \page Disclaimer Legal Disclaimer +* Copyright 2015-2017 Analog Devices Inc. +* Released under the AD9371 API license, for more information see the "LICENSE.txt" file in this zip file. +* +*/ + +#ifndef _MYKONOS_LIB_H_ +#define _MYKONOS_LIB_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "t_mykonos.h" +#include "mykonos_version.h" + +#define TX_PROFILE_VALID 0x01 +#define RX_PROFILE_VALID 0x02 +#define ORX_PROFILE_VALID 0x04 +#define SNIFF_PROFILE_VALID 0x08 + +/* + **************************************************************************** + * General Initialization functions + **************************************************************************** + */ +mykonosErr_t MYKONOS_resetDevice(mykonosDevice_t *device); +mykonosErr_t MYKONOS_getDeviceRev(mykonosDevice_t *device, uint8_t *revision); +mykonosErr_t MYKONOS_getProductId(mykonosDevice_t *device, uint8_t *productId); +mykonosErr_t MYKONOS_setSpiSettings(mykonosDevice_t *device); +mykonosErr_t MYKONOS_verifyDeviceDataStructure(mykonosDevice_t *device); +mykonosErr_t MYKONOS_verifyProfiles(mykonosDevice_t *device); +mykonosErr_t MYKONOS_initialize(mykonosDevice_t *device); +mykonosErr_t MYKONOS_waitForEvent(mykonosDevice_t *device, waitEvent_t waitEvent, uint32_t timeout_us); +mykonosErr_t MYKONOS_readEventStatus(mykonosDevice_t *device, waitEvent_t waitEvent, uint8_t *eventDone); +mykonosErr_t MYKONOS_getApiVersion (mykonosDevice_t *device, uint32_t *siVer, uint32_t *majorVer, uint32_t *minorVer, uint32_t *buildVer); + +/* + ***************************************************************************** + * PLL / Synthesizer functions + ***************************************************************************** + */ +mykonosErr_t MYKONOS_initDigitalClocks(mykonosDevice_t *device); +mykonosErr_t MYKONOS_setRfPllFrequency(mykonosDevice_t *device, mykonosRfPllName_t pllName, uint64_t rfPllLoFrequency_Hz); +mykonosErr_t MYKONOS_getRfPllFrequency(mykonosDevice_t *device, mykonosRfPllName_t pllName, uint64_t *rfPllLoFrequency_Hz); +mykonosErr_t MYKONOS_checkPllsLockStatus(mykonosDevice_t *device, uint8_t *pllLockStatus); +mykonosErr_t MYKONOS_setRfPllLoopFilter(mykonosDevice_t *device, mykonosRfPllName_t pllName, uint16_t loopBandwidth_kHz, uint8_t stability); +mykonosErr_t MYKONOS_getRfPllLoopFilter(mykonosDevice_t *device, mykonosRfPllName_t pllName, uint16_t *loopBandwidth_kHz, uint8_t *stability); +/* + ***************************************************************************** + * ARM Processor Control Functions + ***************************************************************************** + */ +mykonosErr_t MYKONOS_initArm(mykonosDevice_t *device); +mykonosErr_t MYKONOS_loadArmFromBinary(mykonosDevice_t *device, uint8_t *binary, uint32_t count); +mykonosErr_t MYKONOS_loadArmConcurrent(mykonosDevice_t *device, uint8_t *binary, uint32_t count); +mykonosErr_t MYKONOS_verifyArmChecksum(mykonosDevice_t *device); +mykonosErr_t MYKONOS_checkArmState(mykonosDevice_t *device, mykonosArmState_t armStateCheck); +mykonosErr_t MYKONOS_getArmVersion(mykonosDevice_t *device, uint8_t *majorVer, uint8_t *minorVer, uint8_t *rcVer, mykonosBuild_t *buildType); + +mykonosErr_t MYKONOS_configDpd(mykonosDevice_t *device); +mykonosErr_t MYKONOS_getDpdConfig(mykonosDevice_t *device); +mykonosErr_t MYKONOS_getDpdStatus(mykonosDevice_t *device, mykonosTxChannels_t txChannel, mykonosDpdStatus_t *dpdStatus); +mykonosErr_t MYKONOS_restoreDpdModel(mykonosDevice_t *device, mykonosTxChannels_t txChannel, uint8_t *modelDataBuffer, uint32_t modelNumberBytes); +mykonosErr_t MYKONOS_saveDpdModel(mykonosDevice_t *device, mykonosTxChannels_t txChannel, uint8_t *modelDataBuffer, uint32_t modelNumberBytes); +mykonosErr_t MYKONOS_setDpdActState(mykonosDevice_t *device, mykonosTxChannels_t txChannel, uint8_t actState); +mykonosErr_t MYKONOS_resetDpd(mykonosDevice_t *device, mykonosTxChannels_t txChannel, mykonosDpdResetMode_t reset); +mykonosErr_t MYKONOS_setDpdBypassConfig(mykonosDevice_t *device, mykonosDpdBypassConfig_t *actConfig); +mykonosErr_t MYKONOS_getDpdBypassConfig(mykonosDevice_t *device, mykonosDpdBypassConfig_t *actConfig); +mykonosErr_t MYKONOS_setDpdActuatorCheck(mykonosDevice_t *device, mykonosDpdActuatorCheck_t *actCheck); +mykonosErr_t MYKONOS_getDpdActuatorCheck(mykonosDevice_t *device, mykonosDpdActuatorCheck_t *actCheck); + +mykonosErr_t MYKONOS_setClgcAttenTuningConfig(mykonosDevice_t *device, mykonosClgcAttenTuningConfig_t *attRangeCfg); +mykonosErr_t MYKONOS_getClgcAttenTuningConfig(mykonosDevice_t *device, mykonosClgcAttenTuningConfig_t *attRangeCfg); + +mykonosErr_t MYKONOS_configClgc(mykonosDevice_t *device); +mykonosErr_t MYKONOS_getClgcConfig(mykonosDevice_t *device); +mykonosErr_t MYKONOS_getClgcStatus(mykonosDevice_t *device, mykonosTxChannels_t txChannel, mykonosClgcStatus_t *clgcStatus); +mykonosErr_t MYKONOS_setClgcGain(mykonosDevice_t *device, mykonosTxChannels_t txChannel, int16_t gain); + +mykonosErr_t MYKONOS_configVswr(mykonosDevice_t *device); +mykonosErr_t MYKONOS_getVswrConfig(mykonosDevice_t *device); +mykonosErr_t MYKONOS_getVswrStatus(mykonosDevice_t *device, mykonosTxChannels_t txChannel, mykonosVswrStatus_t *vswrStatus); + +mykonosErr_t MYKONOS_runInitCals(mykonosDevice_t *device, uint32_t calMask); +mykonosErr_t MYKONOS_waitInitCals(mykonosDevice_t *device, uint32_t timeoutMs, uint8_t *errorFlag, uint8_t *errorCode); +mykonosErr_t MYKONOS_abortInitCals(mykonosDevice_t *device, uint32_t *calsCompleted); +mykonosErr_t MYKONOS_getInitCalStatus(mykonosDevice_t *device, mykonosInitCalStatus_t *initCalStatus); + +mykonosErr_t MYKONOS_resetExtTxLolChannel(mykonosDevice_t *device, mykonosTxChannels_t channelSel); + +mykonosErr_t MYKONOS_radioOn(mykonosDevice_t *device); +mykonosErr_t MYKONOS_radioOff(mykonosDevice_t *device); +mykonosErr_t MYKONOS_getRadioState(mykonosDevice_t *device, uint32_t *radioStatus); +mykonosErr_t MYKONOS_enableTrackingCals(mykonosDevice_t *device, uint32_t enableMask); +mykonosErr_t MYKONOS_rescheduleTrackingCal(mykonosDevice_t *device, mykonosTrackingCalibrations_t trackingCal); +mykonosErr_t MYKONOS_setAllTrackCalState(mykonosDevice_t *device, uint32_t trackingCalMask); +mykonosErr_t MYKONOS_getAllTrackCalState(mykonosDevice_t *device, uint32_t *trackCals); +mykonosErr_t MYKONOS_setTrackingCalState(mykonosDevice_t *device, mykonosTrackingCalibrations_t trackingCal, uint8_t trackCalState); +mykonosErr_t MYKONOS_getTrackingCalState(mykonosDevice_t *device, mykonosTrackingCalibrations_t trackingCal, uint8_t *trackCalState); +mykonosErr_t MYKONOS_getEnabledTrackingCals(mykonosDevice_t *device, uint32_t *enableMask); +mykonosErr_t MYKONOS_getPendingTrackingCals(mykonosDevice_t *device, uint32_t *pendingCalMask); +mykonosErr_t MYKONOS_getTxLolStatus(mykonosDevice_t *device, mykonosTxChannels_t txChannel, mykonosTxLolStatus_t *txLolStatus); +mykonosErr_t MYKONOS_getTxQecStatus(mykonosDevice_t *device, mykonosTxChannels_t txChannel, mykonosTxQecStatus_t *txQecStatus); + +mykonosErr_t MYKONOS_getRxQecStatus(mykonosDevice_t *device, mykonosRxChannels_t rxChannel, mykonosRxQecStatus_t *rxQecStatus); +mykonosErr_t MYKONOS_getOrxQecStatus(mykonosDevice_t *device, mykonosObsRxChannels_t orxChannel, mykonosOrxQecStatus_t *orxQecStatus); + +mykonosErr_t MYKONOS_setSnifferChannel(mykonosDevice_t *device, mykonosSnifferChannel_t snifferChannel); +mykonosErr_t MYKONOS_setRadioControlPinMode(mykonosDevice_t *device); + +mykonosErr_t MYKONOS_setPathDelay(mykonosDevice_t *device, mykonosPathdelay_t *pathDelay); +mykonosErr_t MYKONOS_getPathDelay(mykonosDevice_t *device, mykonosPathDelaySel_t select, mykonosPathdelay_t *pathDelay); + +mykonosErr_t MYKONOS_getDpdErrorCounters(mykonosDevice_t *device, mykonosTxChannels_t txChannel, mykonosDpdErrorCounters_t *dpdErrCnt); + +/* Low level ARM functions */ +mykonosErr_t MYKONOS_readArmMem(mykonosDevice_t *device, uint32_t address, uint8_t *returnData, uint32_t bytesToRead, uint8_t autoIncrement); +mykonosErr_t MYKONOS_writeArmMem(mykonosDevice_t *device, uint32_t address, uint8_t *data, uint32_t byteCount); +mykonosErr_t MYKONOS_writeArmConfig(mykonosDevice_t *device, uint8_t objectId, uint16_t offset, uint8_t *data, uint8_t byteCount); +mykonosErr_t MYKONOS_readArmConfig(mykonosDevice_t *device, uint8_t objectId, uint16_t offset, uint8_t *data, uint8_t byteCount); +mykonosErr_t MYKONOS_sendArmCommand(mykonosDevice_t *device, uint8_t opCode, uint8_t *extendedData, uint8_t extendedDataNumBytes); +mykonosErr_t MYKONOS_readArmCmdStatus(mykonosDevice_t *device, uint16_t *errorWord, uint16_t *statusWord); +mykonosErr_t MYKONOS_readArmCmdStatusByte(mykonosDevice_t *device, uint8_t opCode, uint8_t *cmdStatByte); +mykonosErr_t MYKONOS_waitArmCmdStatus(mykonosDevice_t *device, uint8_t opCode, uint32_t timeoutMs, uint8_t *cmdStatByte); +mykonosErr_t MYKONOS_writeArmProfile(mykonosDevice_t *device); +mykonosErr_t MYKONOS_loadAdcProfiles(mykonosDevice_t *device); + + +/* + ***************************************************************************** + * JESD204B Datapath Functions + ***************************************************************************** + */ +/* Functions to setup the JESD204B IP */ +mykonosErr_t MYKONOS_resetDeframer(mykonosDevice_t *device); +mykonosErr_t MYKONOS_setupSerializers(mykonosDevice_t *device); +mykonosErr_t MYKONOS_setupDeserializers(mykonosDevice_t *device); +mykonosErr_t MYKONOS_setupJesd204bFramer(mykonosDevice_t *device); +mykonosErr_t MYKONOS_setupJesd204bObsRxFramer(mykonosDevice_t *device); +mykonosErr_t MYKONOS_setupJesd204bDeframer(mykonosDevice_t *device); +mykonosErr_t MYKONOS_enableRxFramerLink(mykonosDevice_t *device, uint8_t enable); +mykonosErr_t MYKONOS_enableObsRxFramerLink(mykonosDevice_t *device, uint8_t enable); + +/* Functions to initialize the JESD204B link */ +mykonosErr_t MYKONOS_enableMultichipSync(mykonosDevice_t *device, uint8_t enableMcs, uint8_t *mcsStatus); +mykonosErr_t MYKONOS_enableSysrefToRxFramer(mykonosDevice_t *device, uint8_t enable); +mykonosErr_t MYKONOS_enableSysrefToObsRxFramer(mykonosDevice_t *device, uint8_t enable); +mykonosErr_t MYKONOS_enableSysrefToDeframer(mykonosDevice_t *device, uint8_t enable); + +/* Functions to help debug the JESD204B link */ +mykonosErr_t MYKONOS_readRxFramerStatus(mykonosDevice_t *device, uint8_t *framerStatus); +mykonosErr_t MYKONOS_readOrxFramerStatus(mykonosDevice_t *device, uint8_t *obsFramerStatus); +mykonosErr_t MYKONOS_readDeframerStatus(mykonosDevice_t *device, uint8_t *deframerStatus); +mykonosErr_t MYKONOS_getDeframerFifoDepth(mykonosDevice_t *device, uint8_t *fifoDepth, uint8_t *readEnLmfcCount); + +/* PRBS debug functions */ +mykonosErr_t MYKONOS_enableRxFramerPrbs(mykonosDevice_t *device, mykonosPrbsOrder_t polyOrder, uint8_t enable); +mykonosErr_t MYKONOS_enableObsRxFramerPrbs(mykonosDevice_t *device, mykonosPrbsOrder_t polyOrder, uint8_t enable); +mykonosErr_t MYKONOS_rxInjectPrbsError(mykonosDevice_t *device); +mykonosErr_t MYKONOS_obsRxInjectPrbsError(mykonosDevice_t *device); +mykonosErr_t MYKONOS_enableDeframerPrbsChecker(mykonosDevice_t *device, uint8_t lanes, mykonosPrbsOrder_t polyOrder, uint8_t enable); +mykonosErr_t MYKONOS_clearDeframerPrbsCounters(mykonosDevice_t *device); +mykonosErr_t MYKONOS_readDeframerPrbsCounters(mykonosDevice_t *device, uint8_t counterSelect, uint32_t *prbsErrorCount); + +/* Miscellaneous debug functions */ +mykonosErr_t MYKONOS_jesd204bIlasCheck(mykonosDevice_t *device, uint16_t *mismatch); +mykonosErr_t MYKONOS_setRxFramerDataSource(mykonosDevice_t *device, uint8_t dataSource); +mykonosErr_t MYKONOS_setObsRxFramerDataSource(mykonosDevice_t *device, uint8_t dataSource); + +/* + ***************************************************************************** + * Shared Data path functions + ***************************************************************************** + */ +mykonosErr_t MYKONOS_programFir(mykonosDevice_t *device, mykonosfirName_t filterToProgram, mykonosFir_t *firFilter); +mykonosErr_t MYKONOS_readFir(mykonosDevice_t *device, mykonosfirName_t filterToRead, mykonosFir_t *firFilter); + +/* + ***************************************************************************** + * Rx Data path functions + ***************************************************************************** + */ +mykonosErr_t MYKONOS_programRxGainTable(mykonosDevice_t *device, uint8_t *gainTablePtr, uint8_t numGainIndexesInTable, mykonosGainTable_t rxChannel); +mykonosErr_t MYKONOS_setRx1ManualGain(mykonosDevice_t *device, uint8_t gainIndex); +mykonosErr_t MYKONOS_setRx2ManualGain(mykonosDevice_t *device, uint8_t gainIndex); +mykonosErr_t MYKONOS_getRx1Gain(mykonosDevice_t *device, uint8_t *rx1GainIndex); +mykonosErr_t MYKONOS_getRx2Gain(mykonosDevice_t *device, uint8_t *rx2GainIndex); +mykonosErr_t MYKONOS_setupRxAgc(mykonosDevice_t *device); +mykonosErr_t MYKONOS_resetRxAgc(mykonosDevice_t *device); +mykonosErr_t MYKONOS_setRxAgcMinMaxGainIndex(mykonosDevice_t *device, mykonosRxChannels_t rxChannelSelect, uint8_t maxGainIndex, uint8_t minGainIndex); +mykonosErr_t MYKONOS_setObsRxAgcMinMaxGainIndex(mykonosDevice_t *device, mykonosObsRxChannels_t obsRxChannelSelect, uint8_t maxGainIndex, uint8_t minGainIndex); +mykonosErr_t MYKONOS_setRx1TempGainComp(mykonosDevice_t *device, int16_t rx1TempCompGain_mdB); +mykonosErr_t MYKONOS_getRx1TempGainComp(mykonosDevice_t *device, int16_t *rx1TempCompGain_mdB); +mykonosErr_t MYKONOS_setRx2TempGainComp(mykonosDevice_t *device, int16_t rx2TempCompGain_mdB); +mykonosErr_t MYKONOS_getRx2TempGainComp(mykonosDevice_t *device, int16_t *rx2TempCompGain_mdB); +mykonosErr_t MYKONOS_setObsRxTempGainComp(mykonosDevice_t *device, int16_t obsRxTempCompGain_mdB); +mykonosErr_t MYKONOS_getObsRxTempGainComp(mykonosDevice_t *device, int16_t *obsRxTempCompGain_mdB); +mykonosErr_t MYKONOS_enableRxGainCtrSyncPulse(mykonosDevice_t *device, uint8_t enable); +mykonosErr_t MYKONOS_setRxGainControlMode(mykonosDevice_t *device, mykonosGainMode_t mode); +mykonosErr_t MYKONOS_getRx1DecPower(mykonosDevice_t *device, uint16_t *rx1DecPower_mdBFS); +mykonosErr_t MYKONOS_getRx2DecPower(mykonosDevice_t *device, uint16_t *rx2DecPower_mdBFS); + +/* + ***************************************************************************** + * Observation Rx Data path functions + ***************************************************************************** + */ +mykonosErr_t MYKONOS_setDefaultObsRxPath(mykonosDevice_t *device, mykonosObsRxChannels_t defaultObsRxCh); +mykonosErr_t MYKONOS_setObsRxPathSource(mykonosDevice_t *device, mykonosObsRxChannels_t obsRxCh); +mykonosErr_t MYKONOS_getObsRxPathSource(mykonosDevice_t *device, mykonosObsRxChannels_t *obsRxCh); +mykonosErr_t MYKONOS_setObsRxManualGain(mykonosDevice_t *device, mykonosObsRxChannels_t obsRxCh, uint8_t gainIndex); +mykonosErr_t MYKONOS_getObsRxGain(mykonosDevice_t *device, uint8_t *gainIndex); +mykonosErr_t MYKONOS_setupObsRxAgc(mykonosDevice_t *device); +mykonosErr_t MYKONOS_enableObsRxGainCtrSyncPulse(mykonosDevice_t *device, uint8_t enable); +mykonosErr_t MYKONOS_setObsRxGainControlMode(mykonosDevice_t *device, mykonosGainMode_t mode); +mykonosErr_t MYKONOS_getObsRxDecPower(mykonosDevice_t *device, uint16_t *obsRxDecPower_mdBFS); + +/* + ***************************************************************************** + * Tx Data path functions + ***************************************************************************** + */ +mykonosErr_t MYKONOS_setTx1Attenuation(mykonosDevice_t *device, uint16_t tx1Attenuation_mdB); +mykonosErr_t MYKONOS_setTx2Attenuation(mykonosDevice_t *device, uint16_t tx2Attenuation_mdB); +mykonosErr_t MYKONOS_getTx1Attenuation(mykonosDevice_t *device, uint16_t *tx1Attenuation_mdB); +mykonosErr_t MYKONOS_getTx2Attenuation(mykonosDevice_t *device, uint16_t *tx2Attenuation_mdB); +mykonosErr_t MYKONOS_getTxFilterOverRangeStatus(mykonosDevice_t *device, uint8_t *txFilterStatus); +mykonosErr_t MYKONOS_enableTxNco(mykonosDevice_t *device, uint8_t enable, int32_t tx1ToneFreq_kHz, int32_t tx2ToneFreq_kHz); + +/* + ***************************************************************************** + * PA Protection Functions + ***************************************************************************** + */ +mykonosErr_t MYKONOS_setupPaProtection(mykonosDevice_t *device, uint16_t powerThreshold, uint8_t attenStepSize, uint8_t avgDuration, uint8_t stickyFlagEnable, uint8_t txAttenControlEnable); +mykonosErr_t MYKONOS_enablePaProtection(mykonosDevice_t *device, uint8_t enable); +mykonosErr_t MYKONOS_getDacPower(mykonosDevice_t *device, mykonosTxChannels_t channel, uint16_t *channelPower); +mykonosErr_t MYKONOS_getPaProtectErrorFlagStatus(mykonosDevice_t *device, uint8_t *errorFlagStatus); +mykonosErr_t MYKONOS_clearPaErrorFlag(mykonosDevice_t *device); + +/* + ***************************************************************************** + * Low level functions and helper functions. BBP should not need to call + ***************************************************************************** + */ +const char* getMykonosErrorMessage(mykonosErr_t errorCode); + +mykonosErr_t MYKONOS_initSubRegisterTables(mykonosDevice_t *device); +mykonosErr_t MYKONOS_setTxPfirSyncClk(mykonosDevice_t *device); /* Helper function */ +mykonosErr_t MYKONOS_setRxPfirSyncClk(mykonosDevice_t *device); /* Helper function */ + +/* + ***************************************************************************** + * Functions to configure DC offsets + ***************************************************************************** + */ +mykonosErr_t MYKONOS_setRfDcOffsetCnt(mykonosDevice_t *device, mykonosDcOffsetChannels_t channel, uint16_t measureCount); +mykonosErr_t MYKONOS_getRfDcOffsetCnt(mykonosDevice_t *device, mykonosDcOffsetChannels_t channel, uint16_t *measureCount); +mykonosErr_t MYKONOS_setDigDcOffsetMShift(mykonosDevice_t *device, mykonosDcOffsetChannels_t channel, uint8_t mShift); +mykonosErr_t MYKONOS_getDigDcOffsetMShift(mykonosDevice_t *device, mykonosDcOffsetChannels_t channel, uint8_t *mShift); +mykonosErr_t MYKONOS_setDigDcOffsetEn(mykonosDevice_t *device, uint8_t enableMask); +mykonosErr_t MYKONOS_getDigDcOffsetEn(mykonosDevice_t *device, uint8_t *enableMask); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/datalink814_ge/src/hardware/mykonos/mykonosMmap.c b/datalink814_ge/src/hardware/mykonos/mykonosMmap.c new file mode 100644 index 0000000..076be0c --- /dev/null +++ b/datalink814_ge/src/hardware/mykonos/mykonosMmap.c @@ -0,0 +1,136 @@ +/** + * \file mykonosMmap.c + * \brief Contains the Mykonos memory mapping + * + * Mykonos API version: 1.5.2.3566 + */ + +/** +* \page Disclaimer Legal Disclaimer +* Copyright 2015-2017 Analog Devices Inc. +* Released under the AD9371 API license, for more information see the "LICENSE.txt" file in this zip file. +* +*/ + +#include +uint8_t mykonosMmap [] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x13,0x03,0x03,0x13,0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, + 0x00,0xE4,0xE4,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA5,0xA5,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x00,0xE4,0xE4,0x00,0x00,0x00,0x1F,0x00,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9F,0xE0,0x20,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0xF5,0x8F,0x0F,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; +/*!< Mykonos memory map */ diff --git a/datalink814_ge/src/hardware/mykonos/mykonos_gpio.c b/datalink814_ge/src/hardware/mykonos/mykonos_gpio.c new file mode 100644 index 0000000..caf1e04 --- /dev/null +++ b/datalink814_ge/src/hardware/mykonos/mykonos_gpio.c @@ -0,0 +1,5357 @@ +/** + *\file mykonos_gpio.c + * + *\brief Contains Mykonos APIs for transceiver GPIO configuration and control. + * + * Mykonos API version: 1.5.2.3566 + */ + +/** +* \page Disclaimer Legal Disclaimer +* Copyright 2015-2017 Analog Devices Inc. +* Released under the AD9371 API license, for more information see the "LICENSE.txt" file in this zip file. +* +*/ + +#include +#include +#include "../common.h" +#include "mykonos.h" +#include "mykonos_gpio.h" +#include "mykonos_macros.h" +#include "mykonos_user.h" + + +/** + * \brief Helper function for return of character string based on 32-bit mykonosGpioErr_t enum value + * + * To save codespace, these error strings are ifdef'd out unless the user + * adds a define MYKONOS_VERBOSE to their workspace. This function can be + * useful for debug. Each function also returns unique error codes to + * make it easier to determine where the code broke. + * + * \param errorCode is enumerated error code value + * + * \return Returns character string based on enumerated value + */ +const char* getGpioMykonosErrorMessage(mykonosGpioErr_t errorCode) +{ +#if MYKONOS_VERBOSE == 0 + return ""; + + #else + + switch (errorCode) + { + case MYKONOS_ERR_GPIO_OK: + return ""; + + case MYKONOS_ERR_EN_MONITOR_OUT_NOT_ENABLED: + return "MYKONOS_setGpioMonitorOut() Mykonos monitor output not enable, please run GPIO setup with the correct setup for enabling the monitor output functionality\n"; + + case MYKONOS_ERR_MONITOR_OUT_INDEX_RANGE: + return "MYKONOS_setGpioMonitorOut()The index specified is incorrect, index available are from 0x01 to 0x42\n"; + + case MYKONOS_ERR_GETGPIOMON_INDEX_NULL_PARM: + return "MYKONOS_getGpioMonitorOut() if the monitorIndex is null.\n"; + + case MYKONOS_ERR_GETGPIOMON_MONITORMASK_NULL_PARM: + return "MYKONOS_getGpioMonitorOut() if the monitorMask is null.\n"; + + case MYKONOS_ERR_MGCRX1_STEP_INV_PARAM: + return "MYKONOS_setRx1GainCtrlPin() An invalid step size has been passed, valid step sizes for increment/decrement is 0-7\n"; + + case MYKONOS_ERR_MGCRX1_GPIO_DECPIN_INV_PARAM: + return "MYKONOS_setRx1GainCtrlPin() An invalid decrement pin has been passed \n"; + + case MYKONOS_ERR_MGCRX1_GPIO_INCPIN_INV_PARAM: + return "MYKONOS_setRx1GainCtrlPin() An invalid increment pin has been passed, \n"; + + case MYKONOS_ERR_MGCRX2_STEP_INV_PARAM: + return "MYKONOS_setRx2GainCtrlPin() An invalid step size has been passed, valid step sizes for increment/decrement is 0-7\n"; + + case MYKONOS_ERR_MGCRX2_GPIO_DECPIN_INV_PARAM: + return "MYKONOS_setRx2GainCtrlPin() An invalid decrement pin has been passed\n"; + + case MYKONOS_ERR_MGCRX2_GPIO_INCPIN_INV_PARAM: + return "MYKONOS_setRx2GainCtrlPin() An invalid increment pin has been passed\n"; + + case MYKONOS_ERR_GETRX1PIN_INCSTEP_NULL_PARM: + return "MYKONOS_getRx1GainCtrlPin() if a null value has been passed to incStep.\n"; + + case MYKONOS_ERR_GETRX1PIN_DECSTEP_NULL_PARM: + return "MYKONOS_getRx1GainCtrlPin() if a null value has been passed to decStep.\n"; + + case MYKONOS_ERR_GETRX1PIN_INCPIN_NULL_PARM: + return "MYKONOS_getRx1GainCtrlPin() if a null value has been passed to rx1GainIncPin.\n"; + + case MYKONOS_ERR_GETRX1PIN_DECPIN_NULL_PARM: + return "MYKONOS_getRx1GainCtrlPin() if a null value has been passed to rx1GainDecPin.\n"; + + case MYKONOS_ERR_GETRX1PIN_EN_NULL_PARM: + return "MYKONOS_getRx1GainCtrlPin() if a null value has been passed to enable.\n"; + + case MYKONOS_ERR_GETRX2PIN_INCSTEP_NULL_PARM: + return "MYKONOS_getRx2GainCtrlPin() if a null value has been passed to incStep.\n"; + + case MYKONOS_ERR_GETRX2PIN_DECSTEP_NULL_PARM: + return "MYKONOS_getRx2GainCtrlPin() if a null value has been passed to decStep.\n"; + + case MYKONOS_ERR_GETRX2PIN_INCPIN_NULL_PARM: + return "MYKONOS_getRx2GainCtrlPin() if a null value has been passed to rx1GainIncPin.\n"; + + case MYKONOS_ERR_GETRX2PIN_DECPIN_NULL_PARM: + return "MYKONOS_getRx2GainCtrlPin() if a null value has been passed to rx1GainDecPin.\n"; + + case MYKONOS_ERR_GETRX2PIN_EN_NULL_PARM: + return "MYKONOS_getRx2GainCtrlPin() if a null value has been passed to enable.\n"; + + case MYKONOS_ERR_TPCTX1_GPIO_STEP_INV_PARAM: + return "MYKONOS_setTx1AttenCtrlPin() An invalid step size has been passed, valid step sizes for att are 0x00-0x1F\n"; + + case MYKONOS_ERR_TPCTX1_GPIO_INCPIN_INV_PARAM: + return "MYKONOS_setTx1AttenCtrlPin() An invalid decrement pin has been passed\n"; + + case MYKONOS_ERR_TPCTX1_GPIO_DECPIN_INV_PARAM: + return "MYKONOS_setTx1AttenCtrlPin() An invalid decrement pin has been passed\n"; + + case MYKONOS_ERR_TPCTX2_GPIO_STEP_INV_PARAM: + return "MYKONOS_setTx2AttenCtrlPin() An invalid step size has been passed, valid step sizes for att are 0x00-0x1F\n"; + + case MYKONOS_ERR_TPCTX2_GPIO_INCPIN_INV_PARAM: + return "MYKONOS_setTx2AttenCtrlPin() An invalid decrement pin has been passed\n"; + + case MYKONOS_ERR_TPCTX2_GPIO_DECPIN_INV_PARAM: + return "MYKONOS_setTx2AttenCtrlPin() An invalid decrement pin has been passed\n"; + + case MYKONOS_ERR_GETTX2PIN_STEP_NULL_PARM: + return "MYKONOS_getTx2AttenCtrlPin() if a null value has been passed to stepSize.\n"; + + case MYKONOS_ERR_GETTX2PIN_INC_NULL_PARM: + return "MYKONOS_getTx2AttenCtrlPin() if a null value has been passed to tx2AttenIncPin.\n"; + + case MYKONOS_ERR_GETTX2PIN_DEC_NULL_PARM: + return "MYKONOS_getTx2AttenCtrlPin() if a null value has been passed to tx2AttenDecPin.\n"; + + case MYKONOS_ERR_GETTX2PIN_EN_NULL_PARM: + return "MYKONOS_getTx2AttenCtrlPin() if a null value has been passed to enable.\n"; + + case MYKONOS_ERR_GETTX2PIN_TX1TX2_NULL_PARM: + return "MYKONOS_getTx2AttenCtrlPin() if a null value has been passed to useTx1ForTx2.\n"; + + case MYKONOS_ERR_GETTX1PIN_STEP_NULL_PARM: + return "MYKONOS_getTx1AttenCtrlPin() if a null value has been passed to stepSize.\n"; + + case MYKONOS_ERR_GETTX1PIN_INC_NULL_PARM: + return "MYKONOS_getTx1AttenCtrlPin() if a null value has been passed to tx1AttenIncPin.\n"; + + case MYKONOS_ERR_GETTX1PIN_DEC_NULL_PARM: + return "MYKONOS_getTx1AttenCtrlPin() if a null value has been passed to tx1AttenDecPin.\n"; + + case MYKONOS_ERR_GETTX1PIN_EN_NULL_PARM: + return "MYKONOS_getTx1AttenCtrlPin() if a null value has been passed to enable.\n"; + + case MYKONOS_ERR_GETTX1PIN_TX1TX2_NULL_PARM: + return "MYKONOS_getTx1AttenCtrlPin() if a null value has been passed to useTx1ForTx2.\n"; + + case MYKONOS_ERR_GPIO_SRC_PARAM_INV: + return "MYKONOS_setGpioSourceCtrl() An invalid source control parameter has been passed\n"; + + case MYKONOS_ERR_GETGPIOSETLEVEL_NULL_PARM: + return "MYKONOS_getGpioSetLevel() gpioPinSetLevel pointer is NULL in function parameter\n"; + + case MYKONOS_ERR_READGPIOSPI_NULL_PARM: + return "MYKONOS_readGpioPinLevel() has a null *gpioPinLevel parameter\n"; + + case MYKONOS_ERR_GETGPIO3V3SPI_NULL_PARM: + return "MYKONOS_getGpio3v3PinLevel() has a null *gpio3v3PinLevel parameter\n"; + + case MYKONOS_ERR_SETUPAUXDAC_NULL_PARAM: + return "MYKONOS_setupAuxDac() has a null device->auxIo pointer\n"; + + case MYKONOS_ERR_GPIO3V3OUTEN_NULL_PARM: + return "MYKONOS_getGpio3v3Oe() has NULL pointer for function parameter gpio3v3OutEn\n;"; + + case MYKONOS_ERR_INV_GP_INT_MASK_PARM: + return "General Purpose Interrupt source mask parameter is invalid\n"; + + case MYKONOS_ERR_GP_INT_STATUS_NULL_PARAM: + return "MYKONOS_readGpInterruptStatus() has NULL status parameter\n"; + + case MYKONOS_ERR_SET_GPIO_3V3_INV_MODE: + return "Invalid GPIO3v3 source control mode\n"; + + case MYKONOS_ERR_SET_GPIO_3V3_INV_SRC_CTRL: + return "gpio3v3 members have invalid value for the GPIO3v3 source control mode.\n"; + + case MYKONOS_ERR_SET_GPIO_1V8_INV_MODE: + return "The GPIO mode enum is not a valid value in MYKONOS_setupGpio\n"; + + case MYKONOS_ERR_GETGPIO3V3OUT_NULL_PARM: + return "MYKONOS_getGpio3v3SetLevel() has NULL pointer for function parameter gpio3v3SetLevel\n"; + + case MYKONOS_ERR_GPIO_OE_INV_PARAM: + return "MYKONOS_setGpioOe() had invalid parameter gpioOutEn (valid range 0 - 0x07FFFF)\n"; + + case MYKONOS_ERR_GETGPIO_OE_NULL_PARM: + return "MYKONOS_getGpioOe() has NULL function parameter\n"; + + case MYKONOS_ERR_WRITEAUXDAC_NULL_AUXIO: + return "device->auxIo structure has NULL pointer in MYKONOS_writeAuxDac()\n"; + + case MYKONOS_ERR_READAUXADC_NULL_PARAM: + return "MYKONOS_readAuxAdc() has NULL function parameter\n"; + + case MYKONOS_ERR_SET_GPIO_3V3_INV_POINTER: + return "Invalid pointer detected in MYKONOS_setupGpio3v3()\n"; + + case MYKONOS_ERR_SET_GPIO_1V8_INV_POINTER: + return "Invalid pointer detected in MYKONOS_setupGpio()\n"; + + case MYKONOS_ERR_SET_ARMGPIO_INV_POINTER: + return "Invalid pointer detected at device->auxIo->armGpio in MYKONOS_setArmGpioPins() \n"; + + case MYKONOS_ERR_SET_ARMGPIO_PINS_ARMERROR: + return "ARM Command Error in MYKONOS_setArmGpioPins()\n"; + + case MYKONOS_ERR_SET_ARMGPIO_PINS_INV_SIGNALID: + return "Invalid Signal ID detected in device->auxIo->armGpio \n"; + + case MYKONOS_ERR_SET_ARMGPIO_PINS_INV_GPIOPIN: + return "Out of range GPIO pin detected \n"; + + case MYKONOS_ERR_SETUPAUXDAC_INV_AUXDACCODE: + return "device->auxIo->auxDacValue, AUXDAC value out of range in MYKONOS_setupAuxDacs()\n"; + + case MYKONOS_ERR_WRITEAUXDAC_INV_AUXDACCODE: + return "auxDacCode value out of range in MYKONOS_writeAuxDac()\n"; + + case MYKONOS_ERR_WRITEAUXDAC_INV_AUXDACINDEX: + return "auxDacIndex value out of range in MYKONOS_writeAuxDac()\n"; + + case MYKONOS_ERR_INV_AUX_ADC_CHAN_PARM: + return "auxAdcChannel value out of range in MYKONOS_setAuxAdcChannel()\n"; + + case MYKONOS_ERR_SETUPAUXADC_INV_VCODIV: + return "device->clocks->clkPllVcoDiv value not supported in MYKONOS_setupAuxAdcs()\n"; + + case MYKONOS_ERR_INV_AUX_ADC_DEC_PARM: + return "adcDecimation value out of range in MYKONOS_setupAuxAdcs()\n"; + + case MYKONOS_ERR_SLICER_INV_RX1_SEL: + return "invalid RX1 GPIO pin selection for Slicer control in MYKONOS_setRxSlicerCtrl()\n"; + + case MYKONOS_ERR_SLICER_INV_RX2_SEL: + return "invalid RX2 GPIO pin selection for Slicer control in MYKONOS_setRxSlicerCtrl()\n"; + + case MYKONOS_ERR_SLICER_STEP_OUT_OF_RANGE: + return "slicer step is out of range for the SLicer control in MYKONOS_setRxSlicerCtrl()\n"; + + case MYKONOS_ERR_SLICER_EN_INV: + return "invalid enable in MYKONOS_setRxSlicerCtrl()\n"; + + case MYKONOS_ERR_SLICER_RX1PIN_NULL_PARM: + return "rx1Pins is null pointer for the passed parameter in MYKONOS_getRxSlicerCtrl()\n"; + + case MYKONOS_ERR_SLICER_RX2PIN_NULL_PARM: + return "rx1Pins is null pointer for the passed parameter in MYKONOS_getRxSlicerCtrl()\n"; + + case MYKONOS_ERR_SLICER_STEP_NULL_PARM: + return "slicerStep is null pointer for the passed parameter in MYKONOS_getRxSlicerCtrl()\n"; + + case MYKONOS_ERR_SLICER_EN_NULL_PARM: + return "enable is null pointer for the passed parameter in MYKONOS_getRxSlicerCtrl()\n"; + + case MYKONOS_ERR_GAINCOMP_NULL_STRUCT: + return "gain compensation structure gainComp is not initialised in MYKONOS_getRxGainCompensation()\n"; + + case MYKONOS_ERR_GAINCOMP_EN_NULL_PARM: + return "enable is null pointer for the passed parameter in MYKONOS_getRxGainCompensation()\n"; + + case MYKONOS_ERR_GAINCOMP_SET_NULL_STRUCT: + return "gain compensation structure gainComp is not initialised in MYKONOS_setRxGainCompensation()\n"; + + case MYKONOS_ERR_GAINCOMP_INV_RX1_OFFSET: + return "gain compensation structure gainComp->rx1Offset is invalid in MYKONOS_setRxGainCompensation()\n"; + + case MYKONOS_ERR_GAINCOMP_INV_RX2_OFFSET: + return "gain compensation structure gainComp->rx2Offset is invalid in MYKONOS_setRxGainCompensation()\n"; + + case MYKONOS_ERR_GAINCOMP_INV_STEP: + return "gain compensation structure gainComp->compStep is invalid in MYKONOS_setRxGainCompensation()\n"; + + case MYKONOS_ERR_GAINCOMP_INV_EN: + return "enable is not valid in MYKONOS_setRxGainCompensation()\n"; + + case MYKONOS_ERR_FLOATFRMT_NULL_STRUCT: + return "floating point formatter structure floatFrmt not initialised in MYKONOS_getFloatPointFrmt()\n"; + + case MYKONOS_ERR_FLOATFRMT_SET_NULL_STRUCT: + return "floating point formatter structure floatFrmt not initialised in MYKONOS_setFloatPointFrmt()\n"; + + case MYKONOS_ERR_FLOATFRMT_INV_ROUND_MODE: + return "floating point formatter structure floatFrmt.roundMode not valid parameter in MYKONOS_setFloatPointFrmt()\n"; + + case MYKONOS_ERR_FLOATFRMT_INV_DATA_FORMAT: + return "floating point formatter structure floatFrmt.dataFormat not valid parameter in MYKONOS_setFloatPointFrmt()\n"; + + case MYKONOS_ERR_FLOATFRMT_INV_ENC_NAN: + return "floating point formatter structure floatFrmt.encNan not valid parameter in MYKONOS_setFloatPointFrmt()\n"; + + case MYKONOS_ERR_FLOATFRMT_INV_EXP_BITS: + return "floating point formatter structure floatFrmt.expBits not valid parameter in MYKONOS_setFloatPointFrmt()\n"; + + case MYKONOS_ERR_FLOATFRMT_INV_LEADING: + return "floating point formatter structure floatFrmt.leading not valid parameter in MYKONOS_setFloatPointFrmt()\n"; + + case MYKONOS_ERR_FLOATFRMT_INV_RX1ATT: + return "not valid rx1 attenuation parameter passed in MYKONOS_setFloatPointFrmt()\n"; + + case MYKONOS_ERR_FLOATFRMT_INV_RX2ATT: + return "not valid rx2 attenuation parameter passed in MYKONOS_setFloatPointFrmt()\n"; + + case MYKONOS_ERR_FLOATFRMT_SET_INV_RX2ATT: + return "not valid rx2 attenuation parameter passed in MYKONOS_setRxEnFloatPntFrmt()\n"; + + case MYKONOS_ERR_FLOATFRMT_SET_INV_RX1ATT: + return "not valid rx1 attenuation parameter passed in MYKONOS_setRxEnFloatPntFrmt()\n"; + + case MYKONOS_ERR_FLOATFRMT_SET_INV_EN: + return "not valid enable parameter passed in MYKONOS_setRxEnFloatPntFrmt()\n"; + + case MYKONOS_ERR_FLOATFRMT_NULL_RX1ATT: + return "null pointer passed for rx1 attenuation in MYKONOS_setRxEnFloatPntFrmt()\n"; + + case MYKONOS_ERR_FLOATFRMT_NULL_RX2ATT: + return "null pointer passed for rx2 attenuation in MYKONOS_setRxEnFloatPntFrmt()\n"; + + case MYKONOS_ERR_FLOATFRMT_NULL_ENABLE: + return "null pointer passed for enable in MYKONOS_setRxEnFloatPntFrmt()\n"; + + case MYKONOS_ERR_SETUPTEMPSENSOR_NULL_PARAM: + return "MYKONOS_setupTempSensor() has NULL function parameter\n"; + + case MYKONOS_ERR_SETUPTEMPSENSOR_INV_TEMPDECIMATION: + return "tempDecimation value out of range in MYKONOS_setupTempSensor()\n"; + + case MYKONOS_ERR_SETUPTEMPSENSOR_INV_TEMPWINDOW: + return "tempWindow value out of range in MYKONOS_setupTempSensor()\n"; + + case MYKONOS_ERR_SETUPTEMPSENSOR_INV_OFFSET: + return "offset value out of range in MYKONOS_setupTempSensor()\n"; + + case MYKONOS_ERR_GETTEMPSENSORCFG_NULL_PARAM: + return "MYKONOS_getTempSensorConfig() has NULL function parameter\n"; + + case MYKONOS_ERR_READTEMPSENSOR_NULL_PARAM: + return "MYKONOS_readTempSensor() has NULL function parameter\n"; + + case MYKONOS_ERR_READTEMPSENSOR_NOT_LOCKED: + return "MYKONOS_readTempSensor() temperature sensor reading is not locked\n"; + + case MYKONOS_ERR_GPIO_HYBRID_RX1_PIN: + return "MYKONOS_setRxHybridGainChangePin() not valid pin has been passed for RX1 hybrid gain control.\n"; + + case MYKONOS_ERR_GPIO_HYBRID_RX2_PIN: + return "MYKONOS_setRxHybridGainChangePin() not valid pin has been passed for RX2 hybrid gain control.\n"; + + case MYKONOS_ERR_GPIO_HYBRID_ORX_PIN: + return "MYKONOS_setObsRxHybridGainChangePin() if invalid pin has been passed for ORX hybrid gain control.\n"; + + case MYKONOS_ERR_AGC_OBS_NOT_IN_HYBRID: + return "MYKONOS_setObsRxHybridGainChangePin() if the observation gain mode is not set to Hybrid.\n"; + + case MYKONOS_ERR_GPIO_HYBRID_RX1_PIN_NULL_PARM: + return "MYKONOS_getRxHybridGainChangePin() null value has been passed to rx1GainChangePin.\n"; + + case MYKONOS_ERR_GPIO_HYBRID_RX2_PIN_NULL_PARM: + return "MYKONOS_getRxHybridGainChangePin() null value has been passed to rx1GainChangePin.\n"; + + case MYKONOS_ERR_GAIN_CONTROL_NOT_HYBRID: + return "MYKONOS_setRxHybridGainChangePin() if gain control is not hybrid.\n"; + + case MYKONOS_ERR_GAIN_CONTROL_NOT_AGC : + return "MYKONOS_setRxAgcEnSyncPin() or MYKONOS_getObsRxAgcEnSyncPin() if the observation gain control mode is not set to AGC.\n"; + + case MYKONOS_ERR_OBS_GAIN_CONTROL_NOT_AGC: + return "MYKONOS_getObsRxAgcEnSyncPin() if the observation gain control mode is not set to AGC.\n"; + + case MYKONOS_ERR_GPIO_AGC_SYNC_RX1_PIN: + return "MYKONOS_setRxAgcEnSyncPin() if invalid pin has been passed for RX1 AGC sync gain control.\n"; + + case MYKONOS_ERR_GPIO_AGC_SYNC_RX2_PIN: + return "MYKONOS_setRxAgcEnSyncPin() if invalid pin has been passed for RX2 AGC sync gain control.\n"; + + case MYKONOS_ERR_GPIO_AGC_SYNC_RX1_PIN_NULL_PARM: + return "MYKONOS_getRxAgcEnSyncPin() if a null value has been passed to rx1AgcSyncPin.\n"; + + case MYKONOS_ERR_GPIO_AGC_SYNC_RX2_PIN_NULL_PARM: + return "MYKONOS_getRxAgcEnSyncPin() if a null value has been passed to rx2AgcSyncPin.\n"; + + case MYKONOS_ERR_GPIO_AGC_SYNC_ORX_PIN: + return "MYKONOS_setObsRxAgcEnSyncPin() if invalid pin has been passed for ORX AGC sync gain control.\n"; + + case MYKONOS_ERR_GPIO_AGC_SYNC_ORX_PIN_NULL_PARM: + return "MYKONOS_getObsRxAgcEnSyncPin() if a null value has been passed to obsRxAgcSyncPin.\n"; + + case MYKONOS_ERR_SLICER_INV_OBS_RX_SEL: + return "Invalid observation channel GPIO pin selection for Slicer control passed to MYKONOS_setObsRxSlicerCtrl().\n"; + + case MYKONOS_ERR_SLICER_OBS_RX_STEP_OUT_OF_RANGE: + return "Slicer step is out of range passed to MYKONOS_setObsRxSlicerCtrl().\n"; + + case MYKONOS_ERR_SLICER_OBS_RX_EN_INV: + return "Invalid enable passed to MYKONOS_setObsRxSlicerCtrl().\n"; + + case MYKONOS_ERR_SLICER_OBS_RXPIN_NULL_PARM: + return "ObsRxPins is null pointer for the passed parameter passed to MYKONOS_getObsRxSlicerCtrl().\n"; + + case MYKONOS_ERR_SLICER_OBS_RX_STEP_NULL_PARM: + return "SlicerStep is null pointer for the passed parameter passed to MYKONOS_getObsRxSlicerCtrl().\n"; + + case MYKONOS_ERR_SLICER_OBS_RX_EN_NULL_PARM: + return "Enable is null pointer for the passed parameter passed to MYKONOS_getObsRxSlicerCtrl().\n"; + + case MYKONOS_ERR_OBS_RX_GAINCOMP_SET_NULL_STRUCT: + return "Gain compensation structure gainComp is not initialised in MYKONOS_setObsRxGainCompensation().\n"; + + case MYKONOS_ERR_OBS_RX_GAINCOMP_INV_OFFSET: + return "Gain compensation structure gainComp->obsRxOffset is invalid in MYKONOS_setObsRxGainCompensation().\n"; + + case MYKONOS_ERR_OBS_RX_GAINCOMP_INV_STEP: + return "Gain compensation structure gainComp->compStep is invalid in MYKONOS_setObsRxGainCompensation().\n"; + + case MYKONOS_ERR_OBS_RX_GAINCOMP_INV_EN: + return "Enable is not valid in MYKONOS_setObsRxGainCompensation().\n"; + + case MYKONOS_ERR_OBS_RX_GAINCOMP_NULL_STRUCT: + return "Observation channel gain compensation structure gainComp is not initialised in MYKONOS_getObsRxGainCompensation().\n"; + + case MYKONOS_ERR_OBS_RX_GAINCOMP_EN_NULL_PARAM: + return "enabled is null pointer for the parameter passed to MYKONOS_getObsRxGainCompensation().\n"; + + case MYKONOS_ERR_GETGPIODRV_NULL_PARAM: + return "Null parameter passed to the function MYKONOS_getGpioDrv().\n"; + + case MYKONOS_ERR_GPIO_DRV_INV_PARAM: + return "GPIO out of range passed to function MYKONOS_setGpioDrv(), valid GPIOs are in the range 0x00000 to 0x7FFFF.\n"; + + case MYKONOS_ERR_GPIO_SLEW_RATE_INV_PARAM: + return "GPIO out of range -valid GPIOs are in the range 0x00000 to 0x7FFFF.\n"; + + case MYKONOS_ERR_GPIO_GETSLEW_NULL_PARAM: + return "Null parameter passed to the function MYKONOS_getGpioSlewRate().\n"; + + case MYKONOS_ERR_CMOS_DRV_NULL_PARAM: + return "Null parameter passed to the function.\n"; + + case MYKONOS_ERR_CMOS_DRV_INV_PARAM: + return "Incorrect drive strength, valid settings are given by mykonosCmosPadDrvStr_t.\n"; + + case MYKONOS_ERR_SPI2_INV_GPIO: + return "if an invalid GPIO pin configuration is passed to MYKONOS_spi2GpioSetup().\n"; + + case MYKONOS_ERR_GET_GPIO_SOURCE_CONTROL_NULL_PARM: + return "Null parameter passed to the function MYKONOS_getGpioSourceCtrl().\n"; + + default: + return "Unknown error was encountered.\n"; + } + + #endif +} + +/** + * \brief This API function configures the monitor output function for the GPIOs + * + * The monitor outputs are grouped in set of nibbles, the user can set + * individual nibbles for having the monitor output function across the available GPIO. + * In order to enable the GPIO monitor function the function setupGpio has to be run and the + * structure should have the proper setup: + * - device->auxIo->gpio->gpioOe = 0xXXXFF the first D7:D0 GPIOs will have the output enable + * - device->auxIo->gpio->gpioSrcCtrl3_0 = GPIO_MONITOR_MODE + * - device->auxIo->gpio->gpioSrcCtrl4_7 = GPIO_MONITOR_MODE + + * + * Dependencies + * - device->spiSettings + * - device->spiSettings->chipSelectIndex + * - device->auxIo->gpio->gpioOe + * - device->auxIo->gpio->gpioSrcCtrl3_0 + * - device->auxIo->gpio->gpioSrcCtrl4_7 + * + * \param device is structure pointer to the Mykonos data structure containing settings + * + * \param monitorIndex which will be the index at which the outputs are going to be set. see table in documentation + * + * \param monitorMask which GPIO outputs are going to active, the available GPIO + * bit 0 will represent MYKGPIO0 and bit 7 will represent MYKGPIO7. + * + * \retval MYKONOS_ERR_MONITOR_OUT_INDEX_RANGE if GPIO Monitor output index is not in table + * \retval MYKONOS_ERR_EN_MONITOR_OUT_NOT_ENABLED if GPIO source control not set for Monitor output + * \retval MYKONOS_ERR_GPIO_OK Function completed successfully + */ +mykonosGpioErr_t MYKONOS_setGpioMonitorOut(mykonosDevice_t *device, uint8_t monitorIndex, uint8_t monitorMask) +{ + mykonosGpioErr_t error = MYKONOS_ERR_GPIO_OK; + + const uint8_t INDEX_MASK = 0x42; + +#if MYKONOS_VERBOSE == 1 + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_setGpioMonitorOut()\n"); +#endif + + /* Error checking for correct index. */ + if (monitorIndex > INDEX_MASK) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_MONITOR_OUT_INDEX_RANGE, + getGpioMykonosErrorMessage(MYKONOS_ERR_MONITOR_OUT_INDEX_RANGE)); + return MYKONOS_ERR_MONITOR_OUT_INDEX_RANGE; + } + + /* Set the GPIO monitor index and the required pin configuration. */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_GPIO_MONITOR_INDEX, monitorIndex); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_GPIO_MONITOR_ENABLE, monitorMask); + + return error; +} + +/** + * \brief This API function reads the GPIO monitor index from Mykonos + * + * The monitor outputs are grouped in two set of nibbles, the user can set + * individual nibbles for having the monitor output function, this nibbles + * will output the monitor output as per the index set. + * + * Dependencies + * - device->spiSettings + * - device->spiSettings->chipSelectIndex + * - GPIO output enable + * - GPIO source control + * + * \param device is structure pointer to the Mykonos data structure containing settings + * \param monitorIndex which will be the index at which the outputs are set to. + * \param monitorMask which will be enable the monitor function. + * + * \retval MYKONOS_ERR_GPIO_OK Function completed successfully + * \retval MYKONOS_ERR_GETGPIOMON_INDEX_NULL_PARM if the monitorIndex is null. + * \retval MYKONOS_ERR_GETGPIOMON_MONITORMASK_NULL_PARM if the monitorMask is null. + */ +mykonosGpioErr_t MYKONOS_getGpioMonitorOut(mykonosDevice_t *device, uint8_t *monitorIndex, uint8_t *monitorMask) +{ + mykonosGpioErr_t error = MYKONOS_ERR_GPIO_OK; + + uint8_t indexRd = 0; + uint8_t monMaskRd = 0; + +#if MYKONOS_VERBOSE == 1 + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_getGpioMonitorOut()\n"); +#endif + + /* Checking for null passed parameters */ + if (monitorIndex == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETGPIOMON_INDEX_NULL_PARM, + getGpioMykonosErrorMessage(MYKONOS_ERR_GETGPIOMON_INDEX_NULL_PARM)); + return MYKONOS_ERR_GETGPIOMON_INDEX_NULL_PARM; + } + + if (monitorMask == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETGPIOMON_MONITORMASK_NULL_PARM, + getGpioMykonosErrorMessage(MYKONOS_ERR_GETGPIOMON_MONITORMASK_NULL_PARM)); + return MYKONOS_ERR_GETGPIOMON_MONITORMASK_NULL_PARM; + } + + /* Get GPIO monitor out enable. */ + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_GPIO_MONITOR_ENABLE, &monMaskRd); + + /* Get the GPIO monitor index and the required pin configuration. */ + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_GPIO_MONITOR_INDEX, &indexRd); + + /* assigning return values to the pointers passed */ + *monitorMask = monMaskRd; + *monitorIndex = indexRd; + + return error; +} + + + + +/** + * \brief This API function configures the GPIO inputs for controlling RX gain + * + * This API function configures the GPIO input pin and step size to allow the BBP to control gain changes in Rx1 signal chain. + * A high pulse on the 'rx1GainIncPin' in pin control mode will increment the gain by the value set in incStep'. + * A high pulse on the 'rx1GainDecPin' in pin control mode will decrement the gain by the value set in 'decStep'. + * Dependencies + * - device->spiSettings + * - device->spiSettings->chipSelectIndex + + * + * \param device is structure pointer to the Mykonos data structure containing settings + * + * \param incStep This sets the change (increase) in gain index that is applied when the + * increment gain pin (in MGC pin control mode) is pulsed. + * + * \param decStep This configures the decrement in gain index that should be applied + * when the decrement gain pin (in MGC pin control mode) is pulsed. + * + * \param rx1GainIncPin mykonosGpioSelect_t These bits select the GPIO used as the enable for + * the Rx1 Manual Increment gain input according to the following: + * MYKGPIO0 or MYKGPIO10 + * + * \param rx1GainDecPin mykonosGpioSelect_t These bits select the GPIO used as the enable for + * the Rx1 Manual Decrement gain input according to the following: + * MYKGPIO1 or MYKGPIO11 + * + * \param enable 0 = Disable the gain pin control for Rx1 + * 1 = enable the gain pin control for Rx1 + * + * \retval MYKONOS_ERR_MGCRX1_STEP_INV_PARAM if an invalid step size has been passed + * \retval MYKONOS_ERR_MGCRX1_GPIO_INCPIN_INV_PARAM if invalid increment pin has been passed + * \retval MYKONOS_ERR_MGCRX1_GPIO_DECPIN_INV_PARAM if invalid decrement pin has been passed + * \retval MYKONOS_ERR_GPIO_OK Function completed successfully + */ +mykonosGpioErr_t MYKONOS_setRx1GainCtrlPin(mykonosDevice_t *device, uint8_t incStep, uint8_t decStep, mykonosGpioSelect_t rx1GainIncPin, mykonosGpioSelect_t rx1GainDecPin, uint8_t enable) +{ + uint8_t wrtPin = 0x00; + uint8_t wrtStep = 0x00; + mykonosGpioErr_t error = MYKONOS_ERR_GPIO_OK; + + const uint8_t SHIFT_CH1 = 0x00; + const uint8_t SHIFT_INC = 0x05; + const uint8_t SHIFT_DEC = 0x02; + const uint8_t MAX_STEP = 0x07; + +#if MYKONOS_VERBOSE == 1 + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_setRx1GainCtrlPin()\n"); +#endif + + /* If enable then check for the next otherwise go directly to disable */ + if (enable > 0) + { + /* Error checking for correct step. */ + if ((uint8_t)(incStep > MAX_STEP) || (uint8_t)(decStep > MAX_STEP)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_MGCRX1_STEP_INV_PARAM, + getGpioMykonosErrorMessage(MYKONOS_ERR_MGCRX1_STEP_INV_PARAM)); + return MYKONOS_ERR_MGCRX1_STEP_INV_PARAM; + } + + /* Pin configuration assignment*/ + switch (rx1GainIncPin) + { + case MYKGPIO0: + wrtPin |= 0x00; + break; + case MYKGPIO10: + wrtPin |= 0x04; + break; + + default: + return MYKONOS_ERR_MGCRX1_GPIO_INCPIN_INV_PARAM; + } + + switch (rx1GainDecPin) + { + case MYKGPIO1: + wrtPin |= 0x00; + break; + case MYKGPIO11: + wrtPin |= 0x01; + break; + + default: + return MYKONOS_ERR_MGCRX1_GPIO_DECPIN_INV_PARAM; + } + } + + /* Setting increment step. */ + wrtStep = (uint8_t)(incStep<spiSettings, MYKONOS_ADDR_AGC_MANUAL_GAIN_CFG, wrtStep, 0xFD, 0); + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_MANUAL_GAIN_GPIO_SEL, wrtPin, 0x0F, 0); + + return error; +} + +/** + * \brief This API function returns the configuration RX1 gain Pin control + * + * + * Dependencies + * - device->spiSettings + * - device->spiSettings->chipSelectIndex + + * + * \param device is structure pointer to the Mykonos data structure containing settings + * \param incStep will contain the step that is used for increment. + * \param decStep will contain the step that is used for decrement. + * \param rx1GainIncPin this will have the pin used for increment. + * \param rx1GainDecPin this will have the pin used for decrement. + * \param enable will contain the enable status for this channel if it is set to 1 then this + * function is enable for this channel, if it is 0 it is not enable + * + * \retval MYKONOS_ERR_GETRX1PIN_INCSTEP_NULL_PARM if a null value has been passed to incStep + * \retval MYKONOS_ERR_GETRX1PIN_DECSTEP_NULL_PARM if a null value has been passed to decStep + * \retval MYKONOS_ERR_GETRX1PIN_INCPIN_NULL_PARM if a null value has been passed to rx1GainIncPin + * \retval MYKONOS_ERR_GETRX1PIN_DECPIN_NULL_PARM if a null value has been passed to rx1GainDecPin + * \retval MYKONOS_ERR_GETRX1PIN_EN_NULL_PARM if a null value has been passed to enable + * \retval MYKONOS_ERR_GPIO_OK Function completed successfully + */ +mykonosGpioErr_t MYKONOS_getRx1GainCtrlPin(mykonosDevice_t *device, uint8_t *incStep, uint8_t *decStep, mykonosGpioSelect_t *rx1GainIncPin, mykonosGpioSelect_t *rx1GainDecPin, uint8_t *enable) +{ + uint8_t readVal = 0x00; + + const uint8_t MASK_GPIO_CH1 = 0x0F; + const uint8_t MASK_EN_CH1 = 0x01; + const uint8_t MASK_STEP_INC = 0xE0; + const uint8_t MASK_STEP_DEC = 0x1C; + +#if MYKONOS_VERBOSE == 1 + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_getRx1GainCtrlPin()\n"); +#endif + + /* Checking for null passed parameters */ + if (incStep == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETRX1PIN_INCSTEP_NULL_PARM, + getGpioMykonosErrorMessage(MYKONOS_ERR_GETRX1PIN_INCSTEP_NULL_PARM)); + return MYKONOS_ERR_GETRX1PIN_INCSTEP_NULL_PARM; + } + + if (decStep == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETRX1PIN_DECSTEP_NULL_PARM, + getGpioMykonosErrorMessage(MYKONOS_ERR_GETRX1PIN_DECSTEP_NULL_PARM)); + return MYKONOS_ERR_GETRX1PIN_DECSTEP_NULL_PARM; + } + + if (rx1GainIncPin == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETRX1PIN_INCPIN_NULL_PARM, + getGpioMykonosErrorMessage(MYKONOS_ERR_GETRX1PIN_INCPIN_NULL_PARM)); + return MYKONOS_ERR_GETRX1PIN_INCPIN_NULL_PARM; + } + + if (rx1GainDecPin == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETRX1PIN_DECPIN_NULL_PARM, + getGpioMykonosErrorMessage(MYKONOS_ERR_GETRX1PIN_DECPIN_NULL_PARM)); + return MYKONOS_ERR_GETRX1PIN_DECPIN_NULL_PARM; + } + + if (enable == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETRX1PIN_EN_NULL_PARM, + getGpioMykonosErrorMessage(MYKONOS_ERR_GETRX1PIN_EN_NULL_PARM)); + return MYKONOS_ERR_GETRX1PIN_EN_NULL_PARM; + } + + /* Getting Pin configuration assignment*/ + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_AGC_MANUAL_GAIN_GPIO_SEL, &readVal); + readVal = readVal & MASK_GPIO_CH1; + + if (readVal & 0x04) + { + *rx1GainIncPin = MYKGPIO10; + } + else + { + *rx1GainIncPin = MYKGPIO0; + } + + if (readVal & 0x01) + { + *rx1GainDecPin = MYKGPIO11; + } + else + { + *rx1GainDecPin = MYKGPIO1; + } + + /* Getting Pin configuration assignment*/ + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_AGC_MANUAL_GAIN_CFG, &readVal); + + *enable = readVal & MASK_EN_CH1; + + *incStep = (readVal & MASK_STEP_INC) >> 5; + + *decStep = (readVal & MASK_STEP_DEC) >> 2; + + return MYKONOS_ERR_GPIO_OK; +} + +/** + * \brief This API function configures the GPIO inputs for controlling RX gain + * + * This API function configures the GPIO input pin and step size to allow the BBP to control gain changes in Rx2 signal chain. + * A high pulse on the 'rx2GainIncPin' in pin control mode will increment the gain by the value set in incStep'. + * A high pulse on the 'rx2GainDecPin' in pin control mode will decrement the gain by the value set in 'decStep'. + * + * Dependencies + * - device->spiSettings + * - device->spiSettings->chipSelectIndex + + * + * \param device is structure pointer to the Mykonos data structure containing settings + * + * \param incStep This sets the change (increase) in gain index that is applied when the + * increment gain pin (in MGC pin control mode) is pulsed. + * + * \param decStep This configures the decrement in gain index that should be applied + * when the decrement gain pin (in MGC pin control mode) is pulsed. + * + * \param rx2GainIncPin mykonosGpioSelect_t These bits select the GPIO used as the enable for + * the Rx2 Manual Increment gain input according to the following: + * MYKGPIO3 or MYKGPIO13 + * + * \param rx2GainDecPin mykonosGpioSelect_t These bits select the GPIO used as the enable for + * the Rx2 Manual Decrement gain input according to the following: + * MYKGPIO4 or MYKGPIO14 + * + * \param enable 0 = Disable the gain pin control for Rx2 + * 1 = enable the gain pin control for Rx2 + * + * + * \retval MYKONOS_ERR_MGCRX2_STEP_INV_PARAM if an invalid step size is passed + * \retval MYKONOS_ERR_MGCRX2_GPIO_INCPIN_INV_PARAM if invalid increment pin has been passed + * \retval MYKONOS_ERR_MGCRX2_GPIO_DECPIN_INV_PARAM if invalid decrement pin has been passed + * \retval MYKONOS_ERR_GPIO_OK Function completed successfully + */ +mykonosGpioErr_t MYKONOS_setRx2GainCtrlPin(mykonosDevice_t *device, uint8_t incStep, uint8_t decStep, mykonosGpioSelect_t rx2GainIncPin, mykonosGpioSelect_t rx2GainDecPin, uint8_t enable) +{ + uint8_t wrtPin = 0x00; + uint8_t wrtStep = 0x00; + mykonosGpioErr_t error = MYKONOS_ERR_GPIO_OK; + + const uint8_t SHIFT_CH2 = 0x01; + const uint8_t SHIFT_INC = 0x5; + const uint8_t SHIFT_DEC = 0x2; + const uint8_t MAX_STEP = 0x07; + +#if MYKONOS_VERBOSE == 1 + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_setRx2GainCtrlPin()\n"); +#endif + + /* If enable then check for the next otherwise go directly to disable */ + if (enable > 0) + { + /* Error checking for correct step. */ + if ((uint8_t)(incStep > MAX_STEP) || (uint8_t)(decStep > MAX_STEP)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_MGCRX2_STEP_INV_PARAM, + getGpioMykonosErrorMessage(MYKONOS_ERR_MGCRX2_STEP_INV_PARAM)); + return MYKONOS_ERR_MGCRX2_STEP_INV_PARAM; + } + + /* Pin configuration assignment*/ + switch (rx2GainIncPin) + { + case MYKGPIO3: + wrtPin |= 0x00; + break; + case MYKGPIO13: + wrtPin |= 0x40; + break; + + default: + return MYKONOS_ERR_MGCRX2_GPIO_INCPIN_INV_PARAM; + } + + switch (rx2GainDecPin) + { + case MYKGPIO4: + wrtPin |= 0x00; + break; + case MYKGPIO14: + wrtPin |= 0x10; + break; + + default: + return MYKONOS_ERR_MGCRX2_GPIO_DECPIN_INV_PARAM; + } + } + + /* Setting increment step. */ + wrtStep = (uint8_t)(incStep<spiSettings, MYKONOS_ADDR_AGC_MANUAL_GAIN_CFG, wrtStep, 0xFE, 0); + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_MANUAL_GAIN_GPIO_SEL, wrtPin, 0xF0, 0); + + return error; +} + +/** + * \brief This API function returns the configuration RX2 gain Pin control + * + * + * Dependencies + * - device->spiSettings + * - device->spiSettings->chipSelectIndex + + * + * \param device is structure pointer to the Mykonos data structure containing settings + * \param incStep will contain the step that is used for increment. + * \param decStep will contain the step that is used for decrement. + * \param rx2GainIncPin this will have the pin used for increment. + * \param rx2GainDecPin this will have the pin used for decrement. + * \param enable will contain the enable status for this channel if it is set to 1 then this + * function is enable for this channel, if it is 0 it is not enable + * + * \retval MYKONOS_ERR_GETRX2PIN_INCSTEP_NULL_PARM if a null value has been passed to incStep + * \retval MYKONOS_ERR_GETRX2PIN_DECSTEP_NULL_PARM if a null value has been passed to decStep + * \retval MYKONOS_ERR_GETRX2PIN_INCPIN_NULL_PARM if a null value has been passed to rx1GainIncPin + * \retval MYKONOS_ERR_GETRX2PIN_DECPIN_NULL_PARM if a null value has been passed to rx1GainDecPin + * \retval MYKONOS_ERR_GETRX2PIN_EN_NULL_PARM if a null value has been passed to enable + * \retval MYKONOS_ERR_GPIO_OK Function completed successfully + */ +mykonosGpioErr_t MYKONOS_getRx2GainCtrlPin(mykonosDevice_t *device, uint8_t *incStep, uint8_t *decStep, mykonosGpioSelect_t *rx2GainIncPin, mykonosGpioSelect_t *rx2GainDecPin, uint8_t *enable) +{ + uint8_t readVal = 0x00; + + const uint8_t MASK_GPIO_CH2 = 0xF0; + const uint8_t MASK_EN_CH2 = 0x02; + const uint8_t MASK_STEP_INC = 0xE0; + const uint8_t MASK_STEP_DEC = 0x1C; + +#if MYKONOS_VERBOSE == 1 + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_getRx2GainCtrlPin()\n"); +#endif + + /* Checking for null passed parameters */ + if (incStep == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETRX2PIN_INCSTEP_NULL_PARM, + getGpioMykonosErrorMessage(MYKONOS_ERR_GETRX2PIN_INCSTEP_NULL_PARM)); + return MYKONOS_ERR_GETRX2PIN_INCSTEP_NULL_PARM; + } + + if (decStep == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETRX2PIN_DECSTEP_NULL_PARM, + getGpioMykonosErrorMessage(MYKONOS_ERR_GETRX2PIN_DECSTEP_NULL_PARM)); + return MYKONOS_ERR_GETRX2PIN_DECSTEP_NULL_PARM; + } + + if (rx2GainIncPin == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETRX2PIN_INCPIN_NULL_PARM, + getGpioMykonosErrorMessage(MYKONOS_ERR_GETRX2PIN_INCPIN_NULL_PARM)); + return MYKONOS_ERR_GETRX2PIN_INCPIN_NULL_PARM; + } + + if (rx2GainDecPin == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETRX2PIN_DECPIN_NULL_PARM, + getGpioMykonosErrorMessage(MYKONOS_ERR_GETRX2PIN_DECPIN_NULL_PARM)); + return MYKONOS_ERR_GETRX2PIN_DECPIN_NULL_PARM; + } + + if (enable == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETRX2PIN_EN_NULL_PARM, + getGpioMykonosErrorMessage(MYKONOS_ERR_GETRX2PIN_EN_NULL_PARM)); + return MYKONOS_ERR_GETRX2PIN_EN_NULL_PARM; + } + + /* Getting Pin configuration assignment*/ + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_AGC_MANUAL_GAIN_GPIO_SEL, &readVal); + readVal = readVal & MASK_GPIO_CH2; + + if (readVal & 0x40) + { + *rx2GainIncPin = MYKGPIO13; + } + else + { + *rx2GainIncPin = MYKGPIO3; + } + + if (readVal & 0x10) + { + *rx2GainDecPin = MYKGPIO14; + } + else + { + *rx2GainDecPin = MYKGPIO4; + } + + /* Getting Pin configuration assignment*/ + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_AGC_MANUAL_GAIN_CFG, &readVal); + + *enable = (readVal & MASK_EN_CH2) >> 1; + + *incStep = (readVal & MASK_STEP_INC) >> 5; + + *decStep = (readVal & MASK_STEP_DEC) >> 2; + + return MYKONOS_ERR_GPIO_OK; +} + +/** + * \brief This API function set the pins for hybrid gain control + * + * In order to call this function the gain mode should be set to Hybrid. + * The AGC gain change will be controlled with the selected GPIO pin: + * A pulse on the 'rx1GainChangePin' in hybrid pin control will enable the AGC gain change for RX1 + * A pulse on the 'rx2GainChangePin' in hybrid pin control will enable the AGC gain change for RX2 + * + * Dependencies + * - device->spiSettings + * - device->spiSettings->chipSelectIndex + * + * \param device is structure pointer to the Mykonos data structure containing settings + * \param rx1GainChangePin GPIO pin that will be used for hybrid gain change control, the available pins for RX1 channel + * hybrid control are: + * MYKGPIO1 + * MYKGPIO10 + * MYKGPIO11 + * MYKGPIONAN for no GPIO selected + * + * \param rx2GainChangePin GPIO pin that will be used for hybrid gain change control, the available pins for RX2 channel + * hybrid control are: + * MYKGPIO4 + * MYKGPIO10 + * MYKGPIO13 + * MYKGPIONAN for no GPIO selected + * + * \retval MYKONOS_ERR_GAIN_CONTROL_NOT_HYBRID if gain control is not hybrid + * \retval MYKONOS_ERR_GPIO_HYBRID_RX1_PIN if invalid pin has been passed for RX1 hybrid gain control. + * \retval MYKONOS_ERR_GPIO_HYBRID_RX2_PIN if invalid pin has been passed for RX2 hybrid gain control. + * \retval MYKONOS_ERR_GPIO_OK Function completed successfully + */ +mykonosGpioErr_t MYKONOS_setRxHybridGainChangePin(mykonosDevice_t *device, mykonosGpioSelect_t rx1GainChangePin, mykonosGpioSelect_t rx2GainChangePin) +{ + uint8_t hybridPinWrite = 0x00; + uint8_t pinRx1 = 0x00; + uint8_t pinRx2 = 0x00; + + const uint8_t HYBRID_RX_PIN_MASK = 0x0F; + +#if MYKONOS_VERBOSE == 1 + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_setRxHybridGainChangePin()\n"); +#endif + + /* Check if in Hybrid Mode */ + if (device->rx->rxGainCtrl->gainMode != HYBRID) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GAIN_CONTROL_NOT_HYBRID, + getGpioMykonosErrorMessage(MYKONOS_ERR_GAIN_CONTROL_NOT_HYBRID)); + return MYKONOS_ERR_GAIN_CONTROL_NOT_HYBRID; + } + + /* Pin configuration assignment for RX1 and RX2 */ + switch (rx1GainChangePin) + { + case MYKGPIO1: + pinRx1 |= 0x00; + break; + case MYKGPIO10: + pinRx1 |= 0x01; + break; + case MYKGPIO11: + pinRx1 |= 0x02; + break; + case MYKGPIONAN: + pinRx1 |= 0x03; + break; + default: + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_HYBRID_RX1_PIN, + getGpioMykonosErrorMessage(MYKONOS_ERR_GPIO_HYBRID_RX1_PIN)); + return MYKONOS_ERR_GPIO_HYBRID_RX1_PIN; + } + + switch (rx2GainChangePin) + { + case MYKGPIO4: + pinRx2 |= 0x00; + break; + case MYKGPIO10: + pinRx2 |= 0x04; + break; + case MYKGPIO13: + pinRx2 |= 0x08; + break; + case MYKGPIONAN: + pinRx2 |= 0x0C; + break; + default: + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_HYBRID_RX2_PIN, + getGpioMykonosErrorMessage(MYKONOS_ERR_GPIO_HYBRID_RX2_PIN)); + return MYKONOS_ERR_GPIO_HYBRID_RX2_PIN; + } + + /* Setting GPIO control for RX1 and RX2 */ + hybridPinWrite = (pinRx1 | pinRx2); + + /* Writing GPIO pin configuration for hybrid mode. */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_GAIN_CHANGE_GPIO_SEL, hybridPinWrite, HYBRID_RX_PIN_MASK, 0); + + return MYKONOS_ERR_GPIO_OK; +} + + + +/** + * \brief This API function gets the pin configuration for hybrid gain control of RX1 and RX2 + * + * Dependencies + * - device->spiSettings + * - device->spiSettings->chipSelectIndex + * + * \param device is structure pointer to the Mykonos data structure containing settings + * \param rx1GainChangePin Will return the GPIO pin used for Rx1 in hybrid gain control. + * \param rx2GainChangePin Will return the GPIO pin used for Rx2 in hybrid gain control. + * + * \retval MYKONOS_ERR_GPIO_HYBRID_RX1_PIN_NULL_PARM if a null value has been passed to rx1GainChangePin + * \retval MYKONOS_ERR_GPIO_HYBRID_RX2_PIN_NULL_PARM if a null value has been passed to rx2GainChangePin + * \retval MYKONOS_ERR_GPIO_OK Function completed successfully + */ +mykonosGpioErr_t MYKONOS_getRxHybridGainChangePin(mykonosDevice_t *device, mykonosGpioSelect_t *rx1GainChangePin, mykonosGpioSelect_t *rx2GainChangePin) +{ + uint8_t hybridPinRead = 0x00; + uint8_t pinRx1 = 0x00; + uint8_t pinRx2 = 0x00; + mykonosGpioSelect_t rx1Pin = MYKGPIONAN; + mykonosGpioSelect_t rx2Pin = MYKGPIONAN; + + const uint8_t MASK_RX1_PIN = 0x03; + const uint8_t MASK_RX2_PIN = 0x0C; + +#if MYKONOS_VERBOSE == 1 + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_getRxHybridGainChangePin()\n"); +#endif + + /* Checking for null passed parameters */ + if (rx1GainChangePin == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_HYBRID_RX1_PIN_NULL_PARM, + getGpioMykonosErrorMessage(MYKONOS_ERR_GPIO_HYBRID_RX1_PIN_NULL_PARM)); + return MYKONOS_ERR_GPIO_HYBRID_RX1_PIN_NULL_PARM; + } + + if (rx2GainChangePin == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_HYBRID_RX2_PIN_NULL_PARM, + getGpioMykonosErrorMessage(MYKONOS_ERR_GPIO_HYBRID_RX2_PIN_NULL_PARM)); + return MYKONOS_ERR_GPIO_HYBRID_RX2_PIN_NULL_PARM; + } + + /* Getting Pin configuration assignment */ + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_AGC_GAIN_CHANGE_GPIO_SEL, &hybridPinRead); + pinRx1 = hybridPinRead & MASK_RX1_PIN; + pinRx2 = hybridPinRead & MASK_RX2_PIN; + + /* Pin configuration mapping assignment for RX1 and RX2 */ + switch (pinRx1) + { + case 0x00: + rx1Pin = MYKGPIO1; + break; + case 0x01: + rx1Pin = MYKGPIO10; + break; + case 0x02: + rx1Pin = MYKGPIO11; + break; + default: + rx1Pin = MYKGPIONAN; + break; + } + + switch (pinRx2) + { + case 0x00: + rx2Pin = MYKGPIO4; + break; + case 0x04: + rx2Pin = MYKGPIO10; + break; + case 0x08: + rx2Pin = MYKGPIO13; + break; + default: + rx2Pin = MYKGPIONAN; + break; + } + + /* Setting pins to passed pointers */ + *rx1GainChangePin = rx1Pin; + *rx2GainChangePin = rx2Pin; + + return MYKONOS_ERR_GPIO_OK; +} + + +/** + * \brief This API function set the pins for hybrid gain control + * + * In order to call this function the gain mode should be set to Hybrid. + * The AGC gain change will be controlled with the selected GPIO pin: + * A pulse on the 'obsRxGainChangePin' in hybrid pin control will enable the AGC gain change for observation channel + * + * Dependencies + * - device->spiSettings + * - device->spiSettings->chipSelectIndex + * + * \param device is structure pointer to the Mykonos data structure containing settings + * \param obsRxGainChangePin GPIO pin that will be used for hybrid gain change control, the available pins for observation channel + * hybrid control are: + * MYKGPIO6 + * MYKGPIO10 + * MYKGPIO17 + * MYKGPIONAN for none selected + * + * \retval MYKONOS_ERR_AGC_OBS_NOT_IN_HYBRID if the observation gain mode is not set to Hybrid + * \retval MYKONOS_ERR_GPIO_HYBRID_ORX_PIN if invalid pin has been passed for ORX hybrid gain control. + * \retval MYKONOS_ERR_GPIO_OK Function completed successfully + */ +mykonosGpioErr_t MYKONOS_setObsRxHybridGainChangePin(mykonosDevice_t *device, mykonosGpioSelect_t obsRxGainChangePin) +{ + uint8_t hybridPinWrite = 0x00; + uint8_t pinOrx = 0x00; + + const uint8_t HYBRID_ORX_PIN_MASK = 0x30; + +#if MYKONOS_VERBOSE == 1 + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_setObsRxHybridGainChangePin()\n"); +#endif + + /* Check if in Hybrid Mode */ + if (device->obsRx->orxGainCtrl->gainMode != HYBRID) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_AGC_OBS_NOT_IN_HYBRID, + getGpioMykonosErrorMessage(MYKONOS_ERR_AGC_OBS_NOT_IN_HYBRID)); + return MYKONOS_ERR_AGC_OBS_NOT_IN_HYBRID; + } + + /* Pin configuration assignment for RX1 and RX2 */ + switch (obsRxGainChangePin) + { + case MYKGPIO6: + pinOrx |= 0x00; + break; + case MYKGPIO10: + pinOrx |= 0x10; + break; + case MYKGPIO17: + pinOrx |= 0x20; + break; + case MYKGPIONAN: + pinOrx |= 0x30; + break; + default: + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_HYBRID_ORX_PIN, + getGpioMykonosErrorMessage(MYKONOS_ERR_GPIO_HYBRID_ORX_PIN)); + return MYKONOS_ERR_GPIO_HYBRID_ORX_PIN; + } + + /* Setting GPIO control for observation channel */ + hybridPinWrite = pinOrx; + + /* Writing GPIO pin configuration for hybrid mode. */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_ORX_SNRX_GPIO_SEL, hybridPinWrite, HYBRID_ORX_PIN_MASK, 0); + + return MYKONOS_ERR_GPIO_OK; +} + +/** + * \brief This API function gets the pin configuration for hybrid gain control of observation channel + * + * Dependencies + * - device->spiSettings + * - device->spiSettings->chipSelectIndex + * + * \param device is structure pointer to the Mykonos data structure containing settings + * \param obsRxGainChangePin Will return the GPIO pin used for observation channel in hybrid gain control. + * + * \retval MYKONOS_ERR_GPIO_HYBRID_ORX_PIN_NULL_PARM if a null value has been passed to obsRxGainChangePin + * \retval MYKONOS_ERR_GPIO_OK Function completed successfully + */ +mykonosGpioErr_t MYKONOS_getObsRxHybridGainChangePin(mykonosDevice_t *device, mykonosGpioSelect_t *obsRxGainChangePin) +{ + uint8_t hybridPinRead = 0x00; + uint8_t pinOrx = 0x00; + mykonosGpioSelect_t orxPin = MYKGPIONAN; + + const uint8_t MASK_ORX_PIN = 0x30; + +#if MYKONOS_VERBOSE == 1 + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_getObsRxHybridGainChangePin()\n"); +#endif + + /* Checking for null passed parameters */ + if (obsRxGainChangePin == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_HYBRID_ORX_PIN_NULL_PARM, + getGpioMykonosErrorMessage(MYKONOS_ERR_GPIO_HYBRID_ORX_PIN_NULL_PARM)); + return MYKONOS_ERR_GPIO_HYBRID_ORX_PIN_NULL_PARM; + } + + /* Getting Pin configuration assignment */ + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_AGC_ORX_SNRX_GPIO_SEL, &hybridPinRead); + pinOrx = hybridPinRead & MASK_ORX_PIN; + + /* Pin configuration mapping assignment for RX1 and RX2 */ + switch (pinOrx) + { + case 0x00: + orxPin = MYKGPIO6; + break; + case 0x10: + orxPin = MYKGPIO10; + break; + case 0x20: + orxPin = MYKGPIO17; + break; + default: + orxPin = MYKGPIONAN; + break; + } + + /* Setting pins to passed pointer */ + *obsRxGainChangePin = orxPin; + + return MYKONOS_ERR_GPIO_OK; +} + +/** + * \brief This API function set the pins for sync AGC gain control + * + * In order to call this function the RX gain control should be set to AGC mode. + * The AGC gain sync will be controlled with the selected GPIO pin: + * A pulse on the 'rx1AgcSyncPin' in hybrid pin control will enable the AGC gain sync for RX1 + * A pulse on the 'rx2AgcSyncPin' in hybrid pin control will enable the AGC gain sync for RX2 + * + * Dependencies + * - device->spiSettings + * - device->spiSettings->chipSelectIndex + * + * \param device is structure pointer to the Mykonos data structure containing settings + * \param rx1AgcSyncPin GPIO pin that will be used for AGC sync gain control, the available pins for RX1 channel are: + * MYKGPIO1 + * MYKGPIO10 + * MYKGPIO11 + * MYKGPIONAN for no GPIO selected + * + * \param rx2AgcSyncPin GPIO pin that will be used for AGC sync gain control, the available pins for RX2 channel are: + * MYKGPIO4 + * MYKGPIO10 + * MYKGPIO13 + * MYKGPIONAN for no GPIO selected + * + * \retval MYKONOS_ERR_GAIN_CONTROL_NOT_AGC if the RX gain control mode is not set to AGC. + * \retval MYKONOS_ERR_GPIO_AGC_SYNC_RX1_PIN if invalid pin has been passed for RX1 AGC sync gain control. + * \retval MYKONOS_ERR_GPIO_AGC_SYNC_RX2_PIN if invalid pin has been passed for RX2 AGC sync gain control. + * \retval MYKONOS_ERR_GPIO_OK Function completed successfully + */ +mykonosGpioErr_t MYKONOS_setRxAgcEnSyncPin(mykonosDevice_t *device, mykonosGpioSelect_t rx1AgcSyncPin, mykonosGpioSelect_t rx2AgcSyncPin) +{ + uint8_t agcSyncPinWrite = 0x00; + uint8_t pinRx1 = 0x00; + uint8_t pinRx2 = 0x00; + + const uint8_t SYNC_RX_PIN_MASK = 0x0F; + +#if MYKONOS_VERBOSE == 1 + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_setRxAgcEnSyncPin()\n"); +#endif + + /* Check if in Hybrid Mode */ + if (device->rx->rxGainCtrl->gainMode != AGC) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GAIN_CONTROL_NOT_AGC, + getGpioMykonosErrorMessage(MYKONOS_ERR_GAIN_CONTROL_NOT_AGC)); + return MYKONOS_ERR_GAIN_CONTROL_NOT_AGC; + } + + /* Pin configuration assignment for RX1 and RX2 */ + switch (rx1AgcSyncPin) + { + case MYKGPIO1: + pinRx1 |= 0x00; + break; + case MYKGPIO10: + pinRx1 |= 0x01; + break; + case MYKGPIO11: + pinRx1 |= 0x02; + break; + case MYKGPIONAN: + pinRx1 |= 0x03; + break; + default: + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_AGC_SYNC_RX1_PIN, + getGpioMykonosErrorMessage(MYKONOS_ERR_GPIO_AGC_SYNC_RX1_PIN)); + return MYKONOS_ERR_GPIO_AGC_SYNC_RX1_PIN; + } + + switch (rx2AgcSyncPin) + { + case MYKGPIO4: + pinRx2 |= 0x00; + break; + case MYKGPIO10: + pinRx2 |= 0x04; + break; + case MYKGPIO13: + pinRx2 |= 0x08; + break; + case MYKGPIONAN: + pinRx2 |= 0x0C; + break; + default: + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_AGC_SYNC_RX2_PIN, + getGpioMykonosErrorMessage(MYKONOS_ERR_GPIO_AGC_SYNC_RX2_PIN)); + return MYKONOS_ERR_GPIO_AGC_SYNC_RX2_PIN; + } + + /* Setting GPIO control for RX1 and RX2 */ + agcSyncPinWrite = (pinRx1 | pinRx2); + + /* Writing GPIO pin configuration for Sync AGC. */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_GAIN_CHANGE_GPIO_SEL, agcSyncPinWrite, SYNC_RX_PIN_MASK, 0); + + return MYKONOS_ERR_GPIO_OK; +} + +/** + * \brief This API function gets the GPIO pin configuration for AGC gain sync control of RX1 and RX2 + * + * Dependencies + * - device->spiSettings + * - device->spiSettings->chipSelectIndex + * + * \param device is structure pointer to the Mykonos data structure containing settings + * \param rx1AgcSyncPin Will return the GPIO pin used for RX1 channel AGC gain sync control, + * + * \param rx2AgcSyncPin Will return the GPIO pin used for RX2 channel AGC gain sync control, + * + * \retval MYKONOS_ERR_GPIO_AGC_SYNC_RX1_PIN_NULL_PARM if a null value has been passed to rx1AgcSyncPin + * \retval MYKONOS_ERR_GPIO_AGC_SYNC_RX2_PIN_NULL_PARM if a null value has been passed to rx2AgcSyncPin + * \retval MYKONOS_ERR_GPIO_OK Function completed successfully + */ +mykonosGpioErr_t MYKONOS_getRxAgcEnSyncPin(mykonosDevice_t *device, mykonosGpioSelect_t *rx1AgcSyncPin, mykonosGpioSelect_t *rx2AgcSyncPin) +{ + uint8_t agcSyncPinRead = 0x00; + uint8_t pinRx1 = 0x00; + uint8_t pinRx2 = 0x00; + mykonosGpioSelect_t rx1Pin = MYKGPIONAN; + mykonosGpioSelect_t rx2Pin = MYKGPIONAN; + + const uint8_t MASK_RX1_PIN = 0x03; + const uint8_t MASK_RX2_PIN = 0x0C; + +#if MYKONOS_VERBOSE == 1 + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_getRxHybridGainChangePin()\n"); +#endif + + /* Checking for null passed parameters */ + if (rx1AgcSyncPin == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_AGC_SYNC_RX1_PIN_NULL_PARM, + getGpioMykonosErrorMessage(MYKONOS_ERR_GPIO_AGC_SYNC_RX1_PIN_NULL_PARM)); + return MYKONOS_ERR_GPIO_AGC_SYNC_RX1_PIN_NULL_PARM; + } + + if (rx2AgcSyncPin == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_AGC_SYNC_RX2_PIN_NULL_PARM, + getGpioMykonosErrorMessage(MYKONOS_ERR_GPIO_AGC_SYNC_RX2_PIN_NULL_PARM)); + return MYKONOS_ERR_GPIO_AGC_SYNC_RX2_PIN_NULL_PARM; + } + + /* Getting Pin configuration assignment */ + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_AGC_GAIN_CHANGE_GPIO_SEL, &agcSyncPinRead); + pinRx1 = agcSyncPinRead & MASK_RX1_PIN; + pinRx2 = agcSyncPinRead & MASK_RX2_PIN; + + /* Pin configuration mapping assignment for RX1 and RX2 */ + switch (pinRx1) + { + case 0x00: + rx1Pin = MYKGPIO1; + break; + case 0x01: + rx1Pin = MYKGPIO10; + break; + case 0x02: + rx1Pin = MYKGPIO11; + break; + default: + rx1Pin = MYKGPIONAN; + break; + } + + switch (pinRx2) + { + case 0x00: + rx2Pin = MYKGPIO4; + break; + case 0x04: + rx2Pin = MYKGPIO10; + break; + case 0x08: + rx2Pin = MYKGPIO13; + break; + default: + rx2Pin = MYKGPIONAN; + break; + } + + /* Setting pins to passed pointers */ + *rx1AgcSyncPin = rx1Pin; + *rx2AgcSyncPin = rx2Pin; + + return MYKONOS_ERR_GPIO_OK; +} + + +/** + * \brief This API function set the pins for AGC gain Sync control + * + * In order to call this function the gain mode should be set to AGC mode. + * The AGC gain sync will be controlled with the selected GPIO pin: + * A pulse on the 'obsRxGainChangePin' in hybrid pin control will enable the AGC gain change for observation channel + * + * Dependencies + * - device->spiSettings + * - device->spiSettings->chipSelectIndex + * + * \param device is structure pointer to the Mykonos data structure containing settings + * \param obsRxAgcSyncPin GPIO pin that will be used for AGC sync gain control, the available pins for observation channel are: + * MYKGPIO6 + * MYKGPIO10 + * MYKGPIO17 + * MYKGPIONAN for none selected + * + * \retval MYKONOS_ERR_OBS_GAIN_CONTROL_NOT_AGC if the observation gain control mode is not set to AGC + * \retval MYKONOS_ERR_GPIO_AGC_SYNC_ORX_PIN if invalid pin has been passed for ORX AGC sync gain control. + * \retval MYKONOS_ERR_GPIO_OK Function completed successfully + */ +mykonosGpioErr_t MYKONOS_setObsRxAgcEnSyncPin(mykonosDevice_t *device, mykonosGpioSelect_t obsRxAgcSyncPin) +{ + uint8_t agcSyncPinWrite = 0x00; + uint8_t pinOrx = 0x00; + + const uint8_t SYNC_ORX_PIN_MASK = 0x30; + +#if MYKONOS_VERBOSE == 1 + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_setObsRxAgcEnSyncPin()\n"); +#endif + + /* Check if in Hybrid Mode */ + if (device->obsRx->orxGainCtrl->gainMode != AGC) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OBS_GAIN_CONTROL_NOT_AGC, + getGpioMykonosErrorMessage(MYKONOS_ERR_OBS_GAIN_CONTROL_NOT_AGC)); + return MYKONOS_ERR_OBS_GAIN_CONTROL_NOT_AGC; + } + + /* Pin configuration assignment for observation channel */ + switch (obsRxAgcSyncPin) + { + case MYKGPIO6: + pinOrx |= 0x00; + break; + case MYKGPIO10: + pinOrx |= 0x10; + break; + case MYKGPIO17: + pinOrx |= 0x20; + break; + case MYKGPIONAN: + pinOrx |= 0x30; + break; + default: + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_AGC_SYNC_ORX_PIN, + getGpioMykonosErrorMessage(MYKONOS_ERR_GPIO_AGC_SYNC_ORX_PIN)); + return MYKONOS_ERR_GPIO_AGC_SYNC_ORX_PIN; + } + + /* Setting GPIO control for observation channel */ + agcSyncPinWrite = pinOrx; + + /* Writing GPIO pin configuration for Sync AGC mode. */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_ORX_SNRX_GPIO_SEL, agcSyncPinWrite, SYNC_ORX_PIN_MASK, 0); + + return MYKONOS_ERR_GPIO_OK; +} + +/** + * \brief This API function gets the pin configuration for AGC Sync gain control of observation channel + * + * Dependencies + * - device->spiSettings + * - device->spiSettings->chipSelectIndex + * + * \param device is structure pointer to the Mykonos data structure containing settings + * \param obsRxAgcSyncPin Will return the GPIO pin used for observation channel AGC gain sync control, + * + * \retval MYKONOS_ERR_GPIO_AGC_SYNC_ORX_PIN_NULL_PARM if a null value has been passed to obsRxAgcSyncPin + * \retval MYKONOS_ERR_GPIO_OK Function completed successfully + */ +mykonosGpioErr_t MYKONOS_getObsRxAgcEnSyncPin(mykonosDevice_t *device, mykonosGpioSelect_t *obsRxAgcSyncPin) +{ + uint8_t agcSyncPinRead = 0x00; + uint8_t pinOrx = 0x00; + mykonosGpioSelect_t orxPin = MYKGPIONAN; + + const uint8_t MASK_ORX_PIN = 0x30; + +#if MYKONOS_VERBOSE == 1 + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_getObsRxAgcEnSyncPin()\n"); +#endif + + /* Checking for null passed parameters */ + if (obsRxAgcSyncPin == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_AGC_SYNC_ORX_PIN_NULL_PARM, + getGpioMykonosErrorMessage(MYKONOS_ERR_GPIO_AGC_SYNC_ORX_PIN_NULL_PARM)); + return MYKONOS_ERR_GPIO_AGC_SYNC_ORX_PIN_NULL_PARM; + } + + /* Getting Pin configuration assignment */ + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_AGC_ORX_SNRX_GPIO_SEL, &agcSyncPinRead); + pinOrx = agcSyncPinRead & MASK_ORX_PIN; + + /* Pin configuration mapping assignment for observation channel */ + switch (pinOrx) + { + case 0x00: + orxPin = MYKGPIO6; + break; + case 0x10: + orxPin = MYKGPIO10; + break; + case 0x20: + orxPin = MYKGPIO17; + break; + default: + orxPin = MYKGPIONAN; + break; + } + + /* Setting pins to passed pointer */ + *obsRxAgcSyncPin = orxPin; + + return MYKONOS_ERR_GPIO_OK; +} + + +/** + * \brief This API function configures the GPIO inputs for controlling Tx attenuation settings + * + * This allows to control the TX attenuation using GPIO inputs. When a low to high transition is + * applied to the configure GPIO input the attenuation will change by the desire step. + * The stepSize parameter will set the attenuation change applied. + * + * + * Dependencies + * - device->spiSettings + * - device->spiSettings->chipSelectIndex + * + * \param device is structure pointer to the Mykonos data structure containing settings + * + * \param stepSize the step that will increase or decrease the Tx1 channel attenuation. + * This parameter sets the change in Tx attenuation for each increment or decrement signal received in incr/decr mode. + * Step of 1 changes attenuation by 0.05dB. + * + * \param tx1AttenIncPin This parameter is the GPIO pin configuration that will be controlling the increment + * of Tx attenuation. Available pins are: + * Tx1 increment: MYKGPIO4 or MYKGPIO12 + * + * \param tx1AttenDecPin This parameter is the GPIO pin configuration that will be controlling the decrement + * of Tx attenuation. Available pins are: + * Tx1 decrement: MYKGPIO5 or MYKGPIO13 + * + * \param enable 0 = Disable the attenuation pin control for Tx1 + * 1 = enable the attenuation pin control for Tx1 + * + * \param useTx1ForTx2 is used to return if TX1 settings are used for TX2 channel. + * + * \retval MYKONOS_ERR_TPCTX1_GPIO_STEP_INV_PARAM if an invalid step size is passed + * \retval MYKONOS_ERR_TPCTX1_GPIO_INCPIN_INV_PARAM if an invalid channel for TX is passed + * \retval MYKONOS_ERR_TPCTX1_GPIO_DECPIN_INV_PARAM if an invalid channel for TX is passed + * \retval MYKONOS_ERR_GPIO_OK Function completed successfully + */ +mykonosGpioErr_t MYKONOS_setTx1AttenCtrlPin(mykonosDevice_t *device, uint8_t stepSize, mykonosGpioSelect_t tx1AttenIncPin, mykonosGpioSelect_t tx1AttenDecPin, uint8_t enable, uint8_t useTx1ForTx2) +{ + uint8_t wrtPin = 0; + uint8_t tpcMode = 0x0; + uint8_t tpcMaskTx2 = 0x00; + mykonosGpioErr_t error = MYKONOS_ERR_GPIO_OK; + + const uint8_t TX_INCDEC_MASK = 0x1F; + const uint8_t TX_PIN_MASK = 0x0F; + +#if MYKONOS_VERBOSE == 1 + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_setTx1AttenCtrlPin()\n"); +#endif + + /* If enable then check for the next otherwise go directly to disable */ + if (enable > 0) + { + /* Error checking for correct step. */ + if (stepSize > TX_INCDEC_MASK) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_TPCTX1_GPIO_STEP_INV_PARAM, + getGpioMykonosErrorMessage(MYKONOS_ERR_TPCTX1_GPIO_STEP_INV_PARAM)); + return MYKONOS_ERR_TPCTX1_GPIO_STEP_INV_PARAM; + } + + /* Pin configuration assignment for Tx1 increments */ + switch (tx1AttenIncPin) + { + case MYKGPIO4: + wrtPin |= 0x00; + break; + case MYKGPIO12: + wrtPin |= 0x01; + break; + + default: + return MYKONOS_ERR_TPCTX1_GPIO_INCPIN_INV_PARAM; + } + + /* Pin configuration assignment for Tx1 decrements */ + switch (tx1AttenDecPin) + { + case MYKGPIO5: + wrtPin |= 0x00; + break; + case MYKGPIO13: + wrtPin |= 0x04; + break; + + default: + return MYKONOS_ERR_TPCTX1_GPIO_DECPIN_INV_PARAM; + } + + /* Setting TPC mode corresponding to the enable */ + tpcMode = 0x03; + + /* Setting TPC control for Tx2 using Tx1 */ + if (useTx1ForTx2 > 0) + { + tpcMode |= 0x1C; + tpcMaskTx2 = 0x1F; + } + else + { + tpcMaskTx2 = 0x13; + } + } + else + { + /* Setting TPC mode corresponding for no Pin control */ + tpcMode = 0x05; + tpcMaskTx2 = 0x1F; + } + + /* Setting increment step. */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_TX_INCR_DECR_WORD, stepSize, TX_INCDEC_MASK, 0); + + /* Set the TPC mode for GPIO control. */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_TX_TPC_CONFIG, tpcMode, tpcMaskTx2, 0); + + /* Set the GPIO input pin configuration and the step size. */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_TX_TPC_GPIO_CFG, wrtPin, TX_PIN_MASK, 0); + + return error; +} + +/** + * \brief This API function returns the configuration TX1 attenuation Pin control + * + * + * Dependencies + * - device->spiSettings + * - device->spiSettings->chipSelectIndex + + * + * \param device is structure pointer to the Mykonos data structure containing settings + * \param stepSize will contain the step that is used for increment and decrement. + * \param tx1AttenIncPin this will have the pin used for increment. + * \param tx1AttenDecPin this will have the pin used for decrement. + * \param enable will contain the enable status for this channel if it is set to 1 then this + * function is enable for this channel, if it is 0 it is not enable + * \param useTx1ForTx2 is used to return if TX1 settings are used for TX2 channel. + * + * \retval MYKONOS_ERR_GETTX1PIN_STEP_NULL_PARM if a null value has been passed to stepSize + * \retval MYKONOS_ERR_GETTX1PIN_INC_NULL_PARM if a null value has been passed to tx1AttenIncPin + * \retval MYKONOS_ERR_GETTX1PIN_DEC_NULL_PARM if a null value has been passed to tx1AttenDecPin + * \retval MYKONOS_ERR_GETTX1PIN_EN_NULL_PARM if a null value has been passed to enable + * \retval MYKONOS_ERR_GETTX1PIN_TX1TX2_NULL_PARM if a null value has been passed to useTx1ForTx2 + * \retval MYKONOS_ERR_GPIO_OK Function completed successfully + */ +mykonosGpioErr_t MYKONOS_getTx1AttenCtrlPin(mykonosDevice_t *device, uint8_t *stepSize, mykonosGpioSelect_t *tx1AttenIncPin, mykonosGpioSelect_t *tx1AttenDecPin, uint8_t *enable, uint8_t *useTx1ForTx2) +{ + uint8_t readVal = 0x00; + uint8_t en = 0x00; + + const uint8_t MASK_TPC_CH1 = 0x03; + const uint8_t MASK_TPC_CH1FCH2 = 0x10; + const uint8_t MASK_TPC_STEP = 0x1F; + const uint8_t MASK_TPC_GPIO_CH1 = 0x0F; + +#if MYKONOS_VERBOSE == 1 + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_getTx1AttenCtrlPin()\n"); +#endif + + /* Checking for null passed parameters */ + if (stepSize == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETTX1PIN_STEP_NULL_PARM, + getGpioMykonosErrorMessage(MYKONOS_ERR_GETTX1PIN_STEP_NULL_PARM)); + return MYKONOS_ERR_GETTX1PIN_STEP_NULL_PARM; + } + + if (tx1AttenIncPin == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETTX1PIN_INC_NULL_PARM, + getGpioMykonosErrorMessage(MYKONOS_ERR_GETTX1PIN_INC_NULL_PARM)); + return MYKONOS_ERR_GETTX1PIN_INC_NULL_PARM; + } + + if (tx1AttenDecPin == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETTX1PIN_DEC_NULL_PARM, + getGpioMykonosErrorMessage(MYKONOS_ERR_GETTX1PIN_DEC_NULL_PARM)); + return MYKONOS_ERR_GETTX1PIN_DEC_NULL_PARM; + } + + if (enable == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETTX1PIN_EN_NULL_PARM, + getGpioMykonosErrorMessage(MYKONOS_ERR_GETTX1PIN_EN_NULL_PARM)); + return MYKONOS_ERR_GETTX1PIN_EN_NULL_PARM; + } + + if (useTx1ForTx2 == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETTX1PIN_TX1TX2_NULL_PARM, + getGpioMykonosErrorMessage(MYKONOS_ERR_GETTX1PIN_TX1TX2_NULL_PARM)); + return MYKONOS_ERR_GETTX1PIN_TX1TX2_NULL_PARM; + } + + /* Getting Pin configuration assignment*/ + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_TX_TPC_GPIO_CFG, &readVal); + readVal = readVal & MASK_TPC_GPIO_CH1; + + if (readVal & 0x01) + { + *tx1AttenIncPin = MYKGPIO12; + } + else + { + *tx1AttenIncPin = MYKGPIO4; + } + + if (readVal & 0x04) + { + *tx1AttenDecPin = MYKGPIO13; + } + else + { + *tx1AttenDecPin = MYKGPIO5; + } + + /* Getting Pin configuration assignment*/ + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_TX_TPC_CONFIG, &readVal); + + en = readVal & MASK_TPC_CH1; + + *enable = (en == MASK_TPC_CH1) ? 1 : 0; + + *useTx1ForTx2 = readVal & MASK_TPC_CH1FCH2; + + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_TX_INCR_DECR_WORD, &readVal); + + *stepSize = readVal & MASK_TPC_STEP; + + return MYKONOS_ERR_GPIO_OK; +} + +/** + * \brief This API function configures the GPIO inputs for controlling Tx attenuation settings + * + * This allows to control the TX attenuation using GPIO inputs. when a low to high transition is + * applied to the configure GPIO input the attenuation will change by the desire step. + * The stepSize parameter will set the attenuation change applied. + * + * + * Dependencies + * - device->spiSettings + * - device->spiSettings->chipSelectIndex + * + * \param device is structure pointer to the Mykonos data structure containing settings + * + * \param stepSize the step that will increase or decrease the Tx2 channel attenuation. + * This parameter sets the change in Tx attenuation for each increment or decrement signal received in incr/decr mode. + * Step of 1 changes attenuation by 0.05dB. + * + * \param tx2AttenIncPin This parameter is the GPIO pin configuration that will be controlling the increment + * of Tx attenuation. Available pins are: + * Tx2 increment: MYKGPIO6 or MYKGPIO14 + * + * \param tx2AttenDecPin This parameter is the GPIO pin configuration that will be controlling the decrement + * of Tx attenuation. Available pins are: + * Tx2 decrement: MYKGPIO7 or MYKGPIO15 + * + * \param enable 0 = Disable the attenuation pin control for Tx2 + * 1 = enable the attenuation pin control for Tx2 + * + * \retval MYKONOS_ERR_TPCTX2_GPIO_STEP_INV_PARAM if an invalid step size is passed + * \retval MYKONOS_ERR_TPCTX2_GPIO_INCPIN_INV_PARAM if an invalid channel for TX is passed + * \retval MYKONOS_ERR_TPCTX2_GPIO_INCPIN_INV_PARAM if an invalid channel for TX is passed + * \retval MYKONOS_ERR_GPIO_OK Function completed successfully + */ +mykonosGpioErr_t MYKONOS_setTx2AttenCtrlPin(mykonosDevice_t *device, uint8_t stepSize, mykonosGpioSelect_t tx2AttenIncPin, mykonosGpioSelect_t tx2AttenDecPin, uint8_t enable) +{ + uint8_t wrtPin = 0; + uint8_t tpcMode = 0x0; + mykonosGpioErr_t error = MYKONOS_ERR_GPIO_OK; + + + const uint8_t TX_INCDEC_MASK = 0x1F; + const uint8_t TX2_TPC_MASK = 0x1C; + const uint8_t TX2_WRTPIN = 0xf0; + +#if MYKONOS_VERBOSE == 1 + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_setTx2AttenCtrlPin()\n"); +#endif + + /* If enable then check for the next otherwise go directly to disable */ + if (enable > 0) + { + /* Error checking for correct step. */ + if (stepSize > TX_INCDEC_MASK) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_TPCTX2_GPIO_STEP_INV_PARAM, + getGpioMykonosErrorMessage(MYKONOS_ERR_TPCTX2_GPIO_STEP_INV_PARAM)); + return MYKONOS_ERR_TPCTX2_GPIO_STEP_INV_PARAM; + } + + /* Pin configuration assignment for Tx2 increments */ + switch (tx2AttenIncPin) + { + case MYKGPIO6: + wrtPin |= 0x00; + break; + case MYKGPIO14: + wrtPin |= 0x10; + break; + + default: + return MYKONOS_ERR_TPCTX2_GPIO_INCPIN_INV_PARAM; + } + + /* Pin configuration assignment for Tx2 decrements */ + switch (tx2AttenDecPin) + { + case MYKGPIO7: + wrtPin |= 0x00; + break; + case MYKGPIO15: + wrtPin |= 0x40; + break; + + default: + return MYKONOS_ERR_TPCTX2_GPIO_DECPIN_INV_PARAM; + } + + /* Setting TPC mode corresponding to the enable */ + tpcMode = 0x0C; + } + else + { + /* Setting TPC mode corresponding for no Pin control */ + tpcMode = 0x05; + } + + /* Setting increment step. */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_TX_INCR_DECR_WORD, stepSize, TX_INCDEC_MASK, 0); + + /* Set the TPC mode for GPIO control. */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_TX_TPC_CONFIG, tpcMode, TX2_TPC_MASK, 0); + + /* Set the GPIO input pin configuration and the step size. */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_TX_TPC_GPIO_CFG, wrtPin, TX2_WRTPIN, 0); + + return error; +} + +/** + * \brief This API function returns the configuration TX2 attenuation Pin control + * + * + * Dependencies + * - device->spiSettings + * - device->spiSettings->chipSelectIndex + + * + * \param device is structure pointer to the Mykonos data structure containing settings + * \param stepSize will contain the step that is used for increment and decrement. + * \param tx2AttenIncPin this will have the pin used for increment. + * \param tx2AttenDecPin this will have the pin used for decrement. + * \param enable will contain the enable status for this channel if it is set to 1 then this + * function is enable for this channel, if it is 0 it is not enable + * \param useTx1ForTx2 is used to return if TX1 settings are used for TX2 channel. + * + * \retval MYKONOS_ERR_GETTX2PIN_STEP_NULL_PARM if a null value has been passed to stepSize + * \retval MYKONOS_ERR_GETTX2PIN_STEP_NULL_PARM if a null value has been passed to tx1AttenIncPin + * \retval MYKONOS_ERR_GETTX2PIN_DEC_NULL_PARM if a null value has been passed to tx1AttenDecPin + * \retval MYKONOS_ERR_GETTX2PIN_EN_NULL_PARM if a null value has been passed to enable + * \retval MYKONOS_ERR_GETTX2PIN_TX1TX2_NULL_PARM if a null value has been passed to useTx1ForTx2 + * \retval MYKONOS_ERR_GPIO_OK Function completed successfully + */ +mykonosGpioErr_t MYKONOS_getTx2AttenCtrlPin(mykonosDevice_t *device, uint8_t *stepSize, mykonosGpioSelect_t *tx2AttenIncPin, mykonosGpioSelect_t *tx2AttenDecPin, uint8_t *enable, uint8_t *useTx1ForTx2) +{ + uint8_t readVal = 0x00; + uint8_t en = 0x00; + + const uint8_t MASK_TPC_CH2 = 0x0C; + const uint8_t MASK_TPC_CH1FCH2 = 0x10; + const uint8_t MASK_TPC_STEP = 0x1F; + const uint8_t MASK_TPC_GPIO_CH2 = 0xF0; + +#if MYKONOS_VERBOSE == 1 + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_getTx2AttenCtrlPin()\n"); +#endif + + /* Checking for null passed parameters */ + if (stepSize == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETTX2PIN_STEP_NULL_PARM, + getGpioMykonosErrorMessage(MYKONOS_ERR_GETTX2PIN_STEP_NULL_PARM)); + return MYKONOS_ERR_GETTX2PIN_STEP_NULL_PARM; + } + + if (tx2AttenIncPin == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETTX2PIN_INC_NULL_PARM, + getGpioMykonosErrorMessage(MYKONOS_ERR_GETTX2PIN_INC_NULL_PARM)); + return MYKONOS_ERR_GETTX2PIN_INC_NULL_PARM; + } + + if (tx2AttenDecPin == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETTX2PIN_DEC_NULL_PARM, + getGpioMykonosErrorMessage(MYKONOS_ERR_GETTX2PIN_DEC_NULL_PARM)); + return MYKONOS_ERR_GETTX2PIN_DEC_NULL_PARM; + } + + if (enable == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETTX2PIN_EN_NULL_PARM, + getGpioMykonosErrorMessage(MYKONOS_ERR_GETTX2PIN_EN_NULL_PARM)); + return MYKONOS_ERR_GETTX2PIN_EN_NULL_PARM; + } + + if (useTx1ForTx2 == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETTX2PIN_TX1TX2_NULL_PARM, + getGpioMykonosErrorMessage(MYKONOS_ERR_GETTX2PIN_TX1TX2_NULL_PARM)); + return MYKONOS_ERR_GETTX2PIN_TX1TX2_NULL_PARM; + } + + /* Getting Pin configuration assignment*/ + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_TX_TPC_GPIO_CFG, &readVal); + readVal = readVal & MASK_TPC_GPIO_CH2; + + if (readVal & 0x10) + { + *tx2AttenIncPin = MYKGPIO14; + } + else + { + *tx2AttenIncPin = MYKGPIO6; + } + + if (readVal & 0x40) + { + *tx2AttenDecPin = MYKGPIO15; + } + else + { + *tx2AttenDecPin = MYKGPIO7; + } + + /* Getting Pin configuration assignment*/ + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_TX_TPC_CONFIG, &readVal); + + en = readVal & MASK_TPC_CH2; + + *enable = (en == MASK_TPC_CH2) ? 1 : 0; + + *useTx1ForTx2 = readVal & MASK_TPC_CH1FCH2; + + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_TX_INCR_DECR_WORD, &readVal); + + *stepSize = readVal & MASK_TPC_STEP; + + return MYKONOS_ERR_GPIO_OK; +} + +/** + * \brief Sets the Mykonos low voltage GPIO output pins level + * + * This function will only affect the GPIO pins that have their OE direction set to output and + * that have the correct source control for the nibbles in GPIO_BITBANG_MODE + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device is a pointer to the device settings structure + * \param gpioPinLevel bit per GPIO pin, level to output for each GPIO pin. 0 = low output, 1= high output + * + * \retval MYKONOS_ERR_GPIO_OK Function completed successfully + */ +mykonosGpioErr_t MYKONOS_setGpioPinLevel(mykonosDevice_t *device, uint32_t gpioPinLevel) +{ + + mykonosGpioErr_t error = MYKONOS_ERR_GPIO_OK; + +#if MYKONOS_VERBOSE == 1 + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_setGpioPinLevel()\n"); +#endif + + /* writing GPIO configuration registers */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_GPIO_SPI_SRC_7_0, (gpioPinLevel & 0xFF)); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_GPIO_SPI_SRC_15_8, ((gpioPinLevel >> 8) & 0xFF)); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_GPIO_SPI_SRC_18_16, ((gpioPinLevel >> 16) & 0x07)); + + /* Return */ + return error; +} + +/** + * \brief Reads the Mykonos low voltage GPIO pin levels and returns their contents in a single 32-bit word + * + * The GPIO pins that are set to be inputs in BITBANG mode will read back and be returned + * in the gpioPinLevel parameter. The return value is a bit per pin. GPIO 0 returns on bit 0 of + * the gpioPinLevel parameter. A logic low level returns a 0, a logic high level returns a 1. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device is a pointer to the device settings structure + * \param gpioPinLevel Input Gpio pin levels read back on the pins assigned as inputs (bit per pin) + * + * \retval MYKONOS_ERR_GPIO_OK Function completed successfully + * \retval MYKONOS_ERR_READGPIOSPI_NULL_PARM The pointer passed for gpioPinLevel parameter is NULL + */ +mykonosGpioErr_t MYKONOS_getGpioPinLevel(mykonosDevice_t *device, uint32_t *gpioPinLevel) +{ + uint8_t readBytes[3] = {0, 0, 0}; + +#if MYKONOS_VERBOSE == 1 + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_getGpioPinLevel()\n"); +#endif + + if (gpioPinLevel == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_READGPIOSPI_NULL_PARM, + getGpioMykonosErrorMessage(MYKONOS_ERR_READGPIOSPI_NULL_PARM)); + return MYKONOS_ERR_READGPIOSPI_NULL_PARM; + } + + /* reading the registers into three-byte array */ + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_GPIO_SPI_READ_7_0, &readBytes[0]); + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_GPIO_SPI_READ_15_8, &readBytes[1]); + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_GPIO_SPI_READ_18_16, &readBytes[2]); + + /* performing concatenation and assigning value to gpio1v8SpiRead */ + *gpioPinLevel = ((uint32_t)(readBytes[2] & 0x07) << 16) | ((uint32_t)(readBytes[1]) << 8) | (uint32_t)(readBytes[0]); + + return MYKONOS_ERR_GPIO_OK; +} + +/** + * \brief Reads the Mykonos GPIO pin output levels for BITBANG mode + * + * This function allows reading the value that the GPIO output pins are + * set to drive out the pins. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device is a pointer to the device settings structure + * \param gpioPinSetLevel is a unit32_t pointer which contains the level of each GPIO pin (bit per pin) + * + * + * \retval MYKONOS_ERR_GPIO_OK Function completed successfully + * \retval MYKONOS_ERR_GETGPIOSETLEVEL_NULL_PARM gpioPinSetLevel pointer is NULL in function parameter + * + */ +mykonosGpioErr_t MYKONOS_getGpioSetLevel(mykonosDevice_t *device, uint32_t *gpioPinSetLevel) +{ + uint8_t readBytes[3] = {0, 0, 0}; + +#if MYKONOS_VERBOSE == 1 + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_getGpioSetLevel()\n"); +#endif + + if (gpioPinSetLevel == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETGPIOSETLEVEL_NULL_PARM, + getGpioMykonosErrorMessage(MYKONOS_ERR_GETGPIOSETLEVEL_NULL_PARM)); + return MYKONOS_ERR_GETGPIOSETLEVEL_NULL_PARM; + } + + /* reading the registers into two-byte array */ + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_GPIO_SPI_SRC_7_0, &readBytes[0]); + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_GPIO_SPI_SRC_15_8, &readBytes[1]); + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_GPIO_SPI_SRC_18_16, &readBytes[2]); + + /* performing concatenation and assigning value to gpioPinSetLevel */ + *gpioPinSetLevel = ((uint32_t)(readBytes[2] & 0x07) << 16) | ((uint32_t)(readBytes[1]) << 8) | (uint32_t)(readBytes[0]); + + return MYKONOS_ERR_GPIO_OK; +} + + + +/** + * \brief Sets the General Purpose (GP) interrupt register bit mask to enable interrupt sources to assert the GP Interrupt pin + * + * Mykonos has a single output pin called General Purpose Interrupt that asserts to a logic high level + * when certain events occur. The events that cause the GP Interrupt pin to assert are user + * selectable by setting the gpMask parameter in this function. Device default is mask = x1FF = ignore + * all events. The ARM Error interrupt can not be ignored and can always assert the GP interrupt pin. + * + * gpMask | Bit description + * ------------|------------ + * [0] | TXPLL LOCK - 0 = allow PLL unlocking to assert GP Interrupt pin, 1 = ignore TXPLL LOCK + * [1] | RXPLL LOCK - 0 = allow PLL unlocking to assert GP Interrupt pin, 1 = ignore RXPLL LOCK + * [2] | SNIFFER PLL LOCK - 0 = allow PLL unlocking to assert GP Interrupt pin, 1 = ignore SNIFFER PLL LOCK + * [3] | CALIBRATION PLL LOCK - 0 = allow PLL unlocking to assert GP Interrupt pin, 1 = ignore CALIBRATION PLL LOCK + * [4] | CLKPLL LOCK - 0 = allow PLL unlocking to assert GP Interrupt pin, 1 = ignore CLKPLL LOCK + * [5] | 0 = Allow JESD204 deframer interrupt to assert GP Interrupt pin, 1 = ignore JESD204 deframer interrupt + * [6] | Tx1 PA protection - 0 = allow Tx1 PA protection event to assert GP Interrupt pin, 1 = ignore Tx1 PA protection + * [7] | Tx2 PA protection - 0 = allow Tx2 PA protection event to assert GP Interrupt pin, 1 = ignore Tx2 PA protection + * [8] | Mykonos ARM Watchdog - 0 = allow Mykonos ARM Watchdog timeout to assert GP Interrupt pin, 1 = ignore Watchdog timeout event + * [15-9] | Reserved for future use + * + * Dependencies + * - device->spiSettings + * + * \param device Pointer to the device settings structure + * \param gpMask Value is passed to enable one or more general purpose interrupt sources + * (1=ignore source, 0 = enable source interrupt to GP Interrupt pin) + * + * \retval MYKONOS_ERR_GPIO_OK Function completed successfully + * \retval MYKONOS_ERR_INV_GP_INT_MASK_PARM if invalid interrupt mask is passed + */ +mykonosGpioErr_t MYKONOS_configGpInterrupt(mykonosDevice_t *device, uint16_t gpMask) +{ + const uint16_t GP_INT_VALID_MASK = 0x1FF; + +#if MYKONOS_VERBOSE == 1 + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_configGpInterrupt()\n"); +#endif + + /* checking for valid mask setting */ + if (gpMask & ~GP_INT_VALID_MASK) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_GP_INT_MASK_PARM, + getGpioMykonosErrorMessage(MYKONOS_ERR_INV_GP_INT_MASK_PARM)); + return MYKONOS_ERR_INV_GP_INT_MASK_PARM; + } + + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_GP_INTERRUPT_MASK_1, (gpMask & 0xFF)); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_GP_INTERRUPT_MASK_0, ((gpMask >> 8) & 0x01)); + + return MYKONOS_ERR_GPIO_OK; +} + +/** + * \brief Reads the General Purpose (GP) interrupt status to determine what caused the GP Interrupt pin to assert + * + * When the BBIC detects a rising edge on the General Purpose Interrupt pin, this function + * allows the BBIC to determine the source of the interrupt. The value returned in the status parameter + * will show one or more sources for the interrupt based on the following table. + * + * The PLL unlock bits are not sticky. They will follow the current status of the PLLs. If the PLL relocks, the + * status bit will clear as well. The GP Interrupt pin is the logical OR of all the sources. When all the status + * bits are low, the GP Interrupt pin will be low. The status word readback will show the current value + * for all interrupt sources, even if they are disabled by the masked. However, the GP Interrupt pin will only assert + * for the enabled sources. + * + * status | Bit description + * ------------|------------ + * [0] | 1 = TXPLL UNLOCK + * [1] | 1 = RXPLL UNLOCK + * [2] | 1 = SNIFFER PLL UNLOCK + * [3] | 1 = CALIBRATION PLL UNLOCK + * [4] | 1 = CLK PLL UNLOCK + * [5] | 1 = JESD204 deframer interrupt occurred + * [6] | 1 = Tx1 PA protection event + * [7] | 1 = Tx2 PA protection event + * [8] | 1 = Mykonos ARM Watchdog timeout + * [9] | 1 = ARM interrupt occurred + * [15-10] | Reserved for future use + * + * Dependencies + * - device->spiSettings + * + * \param device Pointer to the device settings structure + * \param status parameter to return the IRQ source(s) that caused the GP Interrpt pin to assert. + * + * \retval MYKONOS_ERR_GPIO_OK Function completed successfully + * \retval MYKONOS_ERR_GP_INT_STATUS_NULL_PARAM if null *status pointer is passed + */ +mykonosGpioErr_t MYKONOS_readGpInterruptStatus(mykonosDevice_t *device, uint16_t *status) +{ + uint8_t readStatus1 = 0; + uint8_t readStatus0 = 0; + +#if MYKONOS_VERBOSE == 1 + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_readGpInterruptStatus()\n"); +#endif + /* checking for null pointer */ + if (status == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GP_INT_STATUS_NULL_PARAM, + getGpioMykonosErrorMessage(MYKONOS_ERR_GP_INT_STATUS_NULL_PARAM)); + return MYKONOS_ERR_GP_INT_STATUS_NULL_PARAM; + } + + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_GP_INTERRUPT_READ_1, &readStatus1); + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_GP_INTERRUPT_READ_0, &readStatus0); + + /* PLL Lock status bits are high when locked, invert to match up with other bits */ + *status = ((((uint16_t)(readStatus1) & 0xE0U) | ((~(uint16_t)(readStatus1)) & 0x1F)) | (((uint16_t)(readStatus0) & 0x0003) << 8)) ; + + return MYKONOS_ERR_GPIO_OK; +} + +/** + * \brief Sets the input and output GPIO pin selections for ARM related signals. + * + * The BBP should not have to call this as it will automatically be setup during the + * MYKONOS_loadArmFromBinary() function call. If the BBP wishes to change the GPIO + * assignments this function can be called again to change the configuration while + * the ARM is in the radioOff state. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * - device->auxIo->armGpio : all members in structure + * + * \param device is a pointer to the device settings structure + * + * \retval MYKONOS_ERR_GPIO_OK Function completed successfully + * \retval MYKONOS_ERR_SET_ARMGPIO_INV_POINTER device->auxIo->armGpio pointer is null + * \retval MYKONOS_ERR_SET_ARMGPIO_PINS_INV_SIGNALID Invalid ARM GPIO pin signal ID + * \retval MYKONOS_ERR_SET_ARMGPIO_PINS_INV_GPIOPIN Invalid GPIO pin selected for ARM output (valid 0-15 + output enable in bit[4]) + * \retval MYKONOS_ERR_SET_ARMGPIO_PINS_ARMERROR ARM returned error setting GPIO pins + */ +mykonosGpioErr_t MYKONOS_setArmGpioPins(mykonosDevice_t *device) +{ + uint8_t i = 0; + uint8_t gpioConfig[3] = {0}; + uint8_t signalId[12] = {ORX_TRIGGER_SIGNALID, ORX_MODE_0_SIGNALID, ORX_MODE_1_SIGNALID, ORX_MODE_2_SIGNALID, RX1_ENABLE_ACK_SIGNALID, + RX2_ENABLE_ACK_SIGNALID, TX1_ENABLE_ACK_SIGNALID, TX2_ENABLE_ACK_SIGNALID, ORX1_ENABLE_ACK_SIGNALID, ORX2_ENABLE_ACK_SIGNALID, + SRX_ENABLE_ACK_SIGNALID, TX_OBS_SELECT_SIGNALID}; + uint32_t timeoutMs = 0; + uint8_t cmdStatusByte = 0; + uint32_t gpioOe = 0; + uint32_t gpioUsedMask = 0; + mykonosGpioErr_t retval = MYKONOS_ERR_GPIO_OK; + + const uint8_t GPIO_CTRL_OBJECTID = 0x60; + +#if MYKONOS_VERBOSE == 1 + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_setArmGpioPins()\n"); +#endif + + if (device->auxIo->armGpio == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SET_ARMGPIO_INV_POINTER, + getGpioMykonosErrorMessage(MYKONOS_ERR_SET_ARMGPIO_INV_POINTER)); + return MYKONOS_ERR_SET_ARMGPIO_INV_POINTER; + } + + /* Write ARM set command to setup which ARM signals are using which GPIO pins */ + /* Setup input pins for ORX_MODE[2:0] and ORX_MODE_Trigger if orx is in pin mode */ + for(i = 0; i < sizeof(signalId); i++) + { + gpioConfig[0] = GPIO_CTRL_OBJECTID; + gpioConfig[1] = signalId[i]; + + switch(signalId[i]) + { + case ORX_TRIGGER_SIGNALID: gpioConfig[2] = device->auxIo->armGpio->orxTriggerPin; break; + case ORX_MODE_0_SIGNALID: gpioConfig[2] = device->auxIo->armGpio->orxMode0Pin; break; + case ORX_MODE_1_SIGNALID: gpioConfig[2] = device->auxIo->armGpio->orxMode1Pin; break; + case ORX_MODE_2_SIGNALID: gpioConfig[2] = device->auxIo->armGpio->orxMode2Pin; break; + case RX1_ENABLE_ACK_SIGNALID: gpioConfig[2] = device->auxIo->armGpio->rx1EnableAck; break; + case RX2_ENABLE_ACK_SIGNALID: gpioConfig[2] = device->auxIo->armGpio->rx2EnableAck; break; + case TX1_ENABLE_ACK_SIGNALID: gpioConfig[2] = device->auxIo->armGpio->tx1EnableAck; break; + case TX2_ENABLE_ACK_SIGNALID: gpioConfig[2] = device->auxIo->armGpio->tx2EnableAck; break; + case ORX1_ENABLE_ACK_SIGNALID: gpioConfig[2] = device->auxIo->armGpio->orx1EnableAck; break; + case ORX2_ENABLE_ACK_SIGNALID: gpioConfig[2] = device->auxIo->armGpio->orx2EnableAck; break; + case SRX_ENABLE_ACK_SIGNALID: gpioConfig[2] = device->auxIo->armGpio->srxEnableAck; break; + case TX_OBS_SELECT_SIGNALID: gpioConfig[2] = device->auxIo->armGpio->txObsSelect; break; + default: + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SET_ARMGPIO_PINS_INV_SIGNALID, + getGpioMykonosErrorMessage(MYKONOS_ERR_SET_ARMGPIO_PINS_INV_SIGNALID)); + return MYKONOS_ERR_SET_ARMGPIO_PINS_INV_SIGNALID; + } + } + + if (gpioConfig[2] > 0x1F) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SET_ARMGPIO_PINS_INV_GPIOPIN, + getGpioMykonosErrorMessage(MYKONOS_ERR_SET_ARMGPIO_PINS_INV_GPIOPIN)); + return MYKONOS_ERR_SET_ARMGPIO_PINS_INV_GPIOPIN; + } + + /* if output signal */ + if ((signalId[i] >= RX1_ENABLE_ACK_SIGNALID) && (gpioConfig[2] != 0)) + { + gpioOe |= (uint32_t)(((gpioConfig[2] >> 4) & 0x01) << (gpioConfig[2] & 0x0F)); /* 1 = output */ + gpioUsedMask |= (uint32_t)(1 << (gpioConfig[2] & 0x0F)); + } + + /* if input signal and orx Pin mode enabled - currently only input pins are orx pin mode control */ + if ((signalId[i] < RX1_ENABLE_ACK_SIGNALID) && (device->auxIo->armGpio->orxPinMode > 0)) + { + gpioUsedMask |= (1 << (gpioConfig[2] & 0x1F)); + } + + retval = (mykonosGpioErr_t)MYKONOS_sendArmCommand(device, MYKONOS_ARM_SET_OPCODE, &gpioConfig[0], sizeof(gpioConfig)); + if (retval != MYKONOS_ERR_GPIO_OK) + { + return retval; + } + + timeoutMs = 1000; + + if (( retval = (mykonosGpioErr_t)MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_SET_OPCODE, timeoutMs, &cmdStatusByte)) != MYKONOS_ERR_GPIO_OK) + { + return retval; + } + + if (cmdStatusByte > 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SET_ARMGPIO_PINS_ARMERROR, + getGpioMykonosErrorMessage(MYKONOS_ERR_SET_ARMGPIO_PINS_ARMERROR)); + return MYKONOS_ERR_SET_ARMGPIO_PINS_ARMERROR; + } + } + + /* Mykonos SPI regs to set GPIO OE direction only for pins used by ARM */ + if ((retval = MYKONOS_setGpioOe(device, gpioOe, gpioUsedMask)) != MYKONOS_ERR_GPIO_OK) + { + return retval; + } + + /* if any output pins enabled, write GPIO nibble source control. ARM outputs only allowed on GPIO[15:0]*/ + if (gpioOe & 0x000F) + { + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_SOURCE_CONTROL_LOWER_BYTE, 0x09, 0x0F, 0); + } + + if (gpioOe & 0x00F0) + { + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_SOURCE_CONTROL_LOWER_BYTE, 0x09, 0xF0, 4); + } + + if (gpioOe & 0x0F00) + { + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_SOURCE_CONTROL_UPPER_BYTE, 0x09, 0x0F, 0); + } + + if (gpioOe & 0xF000) + { + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_SOURCE_CONTROL_UPPER_BYTE, 0x09, 0xF0, 4); + } + + return MYKONOS_ERR_GPIO_OK; +} + +/** + * \brief Sets up the auxiliary ADC + * + * This function configures the AuxADC with the requested decimation. The AuxADC clock is set as close + * as possible to 40MHz. The AuxADC conversion time = (1/40Mhz) * decimation, where the decimation ranges + * from 256 AuxADC clock cycles to 32768 AuxADc clock cycles. + * + * Note: The AuxADC is intended for relative measurements. Two back to back measurements can allow a delta + * measurement with 12bit resolution. If absolute measurements are required, an accurate + * reference should be first measured on AuxADC0 input and used to calibrate the offset/gain error of the AuxADC. + * The reference would need to be measured before each measurement to account for measurement variations caused + * by the transmitter/receiver transients as other circuits in the device are being powered up/down. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device Pointer to the device settings structure + * \param adcDecimation ADC decimation factor (0-7). Decimates by 256 * 2^(adcDecimation) ADC clock cycles. + * \param enable Stop/run ADC (0/1) + * + * \retval MYKONOS_ERR_GPIO_OK Function completed successfully + * \retval MYKONOS_ERR_SETUPAUXADC_INV_VCODIV CLKPLL VCO divider is invalid - Check CLKPLL setup + * \retval MYKONOS_ERR_INV_AUX_ADC_DEC_PARM AuxADC decimation out of range (valid 0-7) + */ +mykonosGpioErr_t MYKONOS_setupAuxAdcs(mykonosDevice_t *device, uint8_t adcDecimation, uint8_t enable) +{ + uint32_t hsDigClk_kHz = 0; + uint32_t auxAdcDiv = 0; + uint32_t auxAdcClk_kHz = 40000; + uint32_t vcoDiv = (uint32_t)device->clocks->clkPllVcoDiv; + uint8_t vcoDivTimes10 = 10; + + const uint8_t AUXADC_POWER_BIT_MASK = 0x80; + +#if MYKONOS_VERBOSE == 1 + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_setupAuxAdcs()\n"); +#endif + + if (enable == 0) + { + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AUX_ADC_BUFFER_CONFIG_0, 0xCF); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AUX_ADC_CFG, 0x01); + + return MYKONOS_ERR_GPIO_OK; + } + else + { + switch(vcoDiv) + { + case VCODIV_1: + vcoDivTimes10 = 10; + break; + case VCODIV_1p5: + vcoDivTimes10 = 15; + break; + case VCODIV_2: + vcoDivTimes10 = 20; + break; + case VCODIV_3: + vcoDivTimes10 = 30; + break; + + default: + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETUPAUXADC_INV_VCODIV, + getGpioMykonosErrorMessage(MYKONOS_ERR_SETUPAUXADC_INV_VCODIV)); + return MYKONOS_ERR_SETUPAUXADC_INV_VCODIV; + } + + hsDigClk_kHz = (device->clocks->clkPllVcoFreq_kHz / vcoDivTimes10 / device->clocks->clkPllHsDiv) * 10; + auxAdcDiv = ((hsDigClk_kHz / 2) / (auxAdcClk_kHz)) - 1; + + if (auxAdcDiv > 63) + { + auxAdcDiv = 63; + } + + if (adcDecimation > 0x07) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AUX_ADC_DEC_PARM, + getGpioMykonosErrorMessage(MYKONOS_ERR_INV_AUX_ADC_DEC_PARM)); + return MYKONOS_ERR_INV_AUX_ADC_DEC_PARM; + } + + CMB_SPIWriteByte (device->spiSettings, MYKONOS_ADR_AUX_ADC_CLOCK_DIVIDE, (uint8_t)(auxAdcDiv)); + CMB_SPIWriteByte (device->spiSettings, MYKONOS_ADDR_AUX_ADC_CFG, (uint8_t)((adcDecimation << 1))); + CMB_SPIWriteByte (device->spiSettings, MYKONOS_ADDR_AUX_ADC_SEL, 0x00); /* Set AuxADC select to AuxADC0 */ + CMB_SPIWriteField (device->spiSettings, MYKONOS_ADDR_AUX_ADC_BUFFER_CONFIG_0, 0, AUXADC_POWER_BIT_MASK, 7); + + /* Set Clock enable bit to latch divider */ + CMB_SPIWriteByte (device->spiSettings, MYKONOS_ADR_AUX_ADC_CLOCK_DIVIDE, (uint8_t)(auxAdcDiv | 0x80)); + } + return MYKONOS_ERR_GPIO_OK; +} + +/** + * \brief Sets the selected channel of the auxiliary ADC + * + * After setting the AuxADC channel, wait at least 1 AuxADC conversion time before + * reading back the AuxADC value. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device is a pointer to the device settings structure + * \param auxAdcChannel desired Aux ADC input(0-4 and 16 = temperature sensor) + * + * \retval MYKONOS_ERR_GPIO_OK Function completed successfully + * \retval MYKONOS_ERR_INV_AUX_ADC_CHAN_PARM Invalid AuxADC channel (valid 0-4 and 16) + */ +mykonosGpioErr_t MYKONOS_setAuxAdcChannel(mykonosDevice_t *device, mykonosAuxAdcChannels_t auxAdcChannel) +{ + uint8_t currentAuxAdcChan = 0x00; + + const uint8_t CHANNEL_MASK = 0x17; + const uint8_t POWER_UP_AUXADC = 0x00; + const uint8_t POWER_DOWN_AUXADC = 0x01; + +#if MYKONOS_VERBOSE == 1 + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_setAuxAdcChannel()\n"); +#endif + + if (((uint8_t)auxAdcChannel & ~CHANNEL_MASK) > 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AUX_ADC_CHAN_PARM, + getGpioMykonosErrorMessage(MYKONOS_ERR_INV_AUX_ADC_CHAN_PARM)); + return MYKONOS_ERR_INV_AUX_ADC_CHAN_PARM; + } + + /* Read current selected channel, if different power down AUXADC and change AUXADC */ + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_AUX_ADC_SEL, ¤tAuxAdcChan); + if (currentAuxAdcChan != (uint8_t)auxAdcChannel) + { + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AUX_ADC_CFG, POWER_DOWN_AUXADC, 0x01, 0); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AUX_ADC_SEL, ((auxAdcChannel & MYK_AUXADC_0_DIV2) ? 0: auxAdcChannel)); + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AUX_ADC_CFG, POWER_UP_AUXADC, 0x01, 0); + } + + /* Invalid AuxADC channel, the only valid channel for external ref is channel 0 */ + if (auxAdcChannel == MYK_AUXADC_0_DIV2) + { + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AUX_ADC_BUFFER_CONFIG_1, 0x01, 0x04, 2); + } + else if (auxAdcChannel == MYK_AUXADC_0) + { + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AUX_ADC_BUFFER_CONFIG_1, 0x00, 0x04, 2); + } + + return MYKONOS_ERR_GPIO_OK; +} + +/** + * \brief Reads from the selected channel of the auxiliary ADC + * + * Before using this function to read back the AuxADC value of the + * currently selected AuxADC, make sure that at least 1 conversion time + * of the ADC has passed since setting the AuxADC channel. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device is a pointer to the device settings structure + * \param adcCode is a pointer for return of the 12bit ADC read value + * + * \retval MYKONOS_ERR_GPIO_OK Function completed successfully + * \retval MYKONOS_ERR_READAUXADC_NULL_PARAM Function parameter adcCode is a NULL pointer + */ +mykonosGpioErr_t MYKONOS_readAuxAdc(mykonosDevice_t *device, uint16_t *adcCode) +{ + uint8_t adcNibble = 0; + + const uint8_t AUXADC_LOCK_BIT_MASK = 0x80; + +#if MYKONOS_VERBOSE == 1 + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_readAuxAdcs()\n"); +#endif + + if (adcCode == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_READAUXADC_NULL_PARAM, + getGpioMykonosErrorMessage(MYKONOS_ERR_READAUXADC_NULL_PARAM)); + return MYKONOS_ERR_READAUXADC_NULL_PARAM; + } + + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AUX_ADC_CFG, 1, AUXADC_LOCK_BIT_MASK, 7); + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_AUX_ADC_READ_MSB, &adcNibble); + *adcCode = adcNibble << 4; + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_AUX_ADC_READ_LSB, &adcNibble); + *adcCode |= (adcNibble & 0x0F); + + return MYKONOS_ERR_GPIO_OK; +} + +/** + * \brief Sets up the 10 AuxDACs on the Mykonos device. + * + * This function uses the configuration in the Mykonos device data structure AuxIO substructure to + * setup which of the ten AuxDACs are enabled, their slope, Vref(mid point) and their initial DAC code. + * + * This function can be called any time after MYKONOS_initialize() to reconfigure, enable, disable the + * different AuxDAC outputs. The AuxDACs are used in manual control mode. After calling this setup + * function, it is possible to change a particular AuxDAC code by calling the writeAuxDac() function. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * - device->auxIo->auxDacEnable: 1= enabled, 0 = disabled + * - device->auxIo->auxDacSlope[i]: 0 = 1.404mv/code, 1= 0.702mV/code + * - device->auxIo->auxDacVref: 0 = 1v midpoint, 1 = 1.5v midpoint, 2 = 2v midpoint, 3 = 2.5v midpoint + * - device->auxIo->auxDacValue[i]: 10bit DAC code (0-1023) + * + * \param device is a pointer to the device settings structure + * + * \retval MYKONOS_ERR_GPIO_OK Function completed successfully + * \retval MYKONOS_ERR_SETUPAUXDAC_NULL_PARAM device->auxIo structure has a NULL pointer + * \retval MYKONOS_ERR_SETUPAUXDAC_INV_AUXDACCODE auxDAC code is out of range (valid 0-1023) + */ +mykonosGpioErr_t MYKONOS_setupAuxDacs(mykonosDevice_t *device) +{ + uint8_t i = 0; /* for loop index */ + uint8_t auxDacConfig = 0 ; + mykonosGpioErr_t error = MYKONOS_ERR_GPIO_OK; + +#if MYKONOS_VERBOSE == 1 + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_setupAuxDacs()\n"); +#endif + + if (device->auxIo == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETUPAUXDAC_NULL_PARAM, + getGpioMykonosErrorMessage(MYKONOS_ERR_SETUPAUXDAC_NULL_PARAM)); + return MYKONOS_ERR_SETUPAUXDAC_NULL_PARAM; + } + + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PDAUXDAC_MANUAL_CONTROL_5_0, 0x3F); /* Enable Manual AuxDAC control for all AuxDACs[5:0] */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PDAUXDAC_MANUAL_CONTROL_9_6, 0x0F); /* Enable Manual AuxDAC control for all AuxDACs[9:6] */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PDAUXDAC_MANUAL_IN_5_0, 0x3F); /* Power down all AuxDACs[5:0] */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PDAUXDAC_MANUAL_IN_9_6, 0x0F); /* Power down all AuxDACs[9:6] */ + + for (i = 0; i < 10; i++) + { + /* If auxDac enabled, setup AuxDAC configuration */ + if ((device->auxIo->auxDacEnable >> i) & 0x01) + { + if (device->auxIo->auxDacValue[i] > 1023) + { + device->auxIo->auxDacValue[i] = 1023; /* clip value to max */ + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETUPAUXDAC_INV_AUXDACCODE, + getGpioMykonosErrorMessage(MYKONOS_ERR_SETUPAUXDAC_INV_AUXDACCODE)); + error = MYKONOS_ERR_SETUPAUXDAC_INV_AUXDACCODE; /* Complete AuxDAC configuration before returning error code */ + } + + auxDacConfig = 0x00; /* initialize config variable */ + + if (device->auxIo->auxDacSlope[i] > 0) + { + auxDacConfig = 0x40; /* bit [6] sets the slope */ + } + + auxDacConfig |= ((device->auxIo->auxDacVref[i] & 0x03) << 4); + + /* Write AuxDAC config and DAC code */ + CMB_SPIWriteByte(device->spiSettings, (MYKONOS_ADDR_AUXDAC_0_WORD_MSB + (i * 2)), (auxDacConfig | ((device->auxIo->auxDacValue[i] >> 8) & 0x0F))); + CMB_SPIWriteByte(device->spiSettings, (MYKONOS_ADDR_AUXDAC_0_WORD_MSB + (i * 2 ) + 1), (device->auxIo->auxDacValue[i] & 0xFF)); + } + } + + /* Write enable bit to latch DAC codes into DACs */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AUX_DAC_LATCH_CONTROL, 0x01); + + /* Power up selected AuxDacs */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PDAUXDAC_MANUAL_IN_5_0, (~device->auxIo->auxDacEnable & 0x3F)); /* Power up enabled AuxDACs[5:0] */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PDAUXDAC_MANUAL_IN_9_6, (((uint16_t)(~device->auxIo->auxDacEnable) >> 6) & 0x0F)); /* Power up enabled AuxDACs[9:6] */ + + return error; +} + +/** + * \brief Writes the current AuxDAC code for a particular AuxDAC + * + * This function updates the 10bit code that controls the AuxDAC output voltage. + * The auxDacCode is updated for the specified auxDAC. Also the auxDacCode is written + * to the device data structure for future reference. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * - device->auxIo->auxDacValue[i] + * + * \param device is a pointer to the device settings structure + * \param auxDacIndex AuxDAC to set the DAC code for (0-9) + * \param auxDacCode DAC code to update the AuxDAC to. Sets the output voltage of the DAC (valid 0-1023) + * + * \retval MYKONOS_ERR_GPIO_OK Function completed successfully + * \retval MYKONOS_ERR_WRITEAUXDAC_INV_AUXDACCODE AuxDac code invalid (valid 0-1023) + * \retval MYKONOS_ERR_WRITEAUXDAC_INV_AUXDACINDEX AuxDAC index out of range (valid 0-9) + * \retval MYKONOS_ERR_WRITEAUXDAC_NULL_AUXIO device->auxIo has NULL pointer + */ +mykonosGpioErr_t MYKONOS_writeAuxDac(mykonosDevice_t *device, uint8_t auxDacIndex, uint16_t auxDacCode) +{ + uint16_t auxDacAddr = 0; + +#if MYKONOS_VERBOSE == 1 + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_writeAuxDac()\n"); +#endif + + if (auxDacCode > 1023) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_WRITEAUXDAC_INV_AUXDACCODE, + getGpioMykonosErrorMessage(MYKONOS_ERR_WRITEAUXDAC_INV_AUXDACCODE)); + return MYKONOS_ERR_WRITEAUXDAC_INV_AUXDACCODE; + } + + if (auxDacIndex > 9) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_WRITEAUXDAC_INV_AUXDACINDEX, + getGpioMykonosErrorMessage(MYKONOS_ERR_WRITEAUXDAC_INV_AUXDACINDEX)); + return MYKONOS_ERR_WRITEAUXDAC_INV_AUXDACINDEX; + } + + if (device->auxIo == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_WRITEAUXDAC_NULL_AUXIO, + getGpioMykonosErrorMessage(MYKONOS_ERR_WRITEAUXDAC_NULL_AUXIO)); + return MYKONOS_ERR_WRITEAUXDAC_NULL_AUXIO; + } + + device->auxIo->auxDacValue[auxDacIndex] = auxDacCode; + + auxDacAddr = MYKONOS_ADDR_AUXDAC_0_WORD_MSB + (auxDacIndex * 2); + + /* Write AuxDAC config and DAC code */ + CMB_SPIWriteField(device->spiSettings, auxDacAddr, (auxDacCode >> 8), 0x0F, 0); + CMB_SPIWriteByte(device->spiSettings, (auxDacAddr + 1), (auxDacCode & 0xFF)); + + /* Write enable bit to latch DAC codes into DACs */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AUX_DAC_LATCH_CONTROL, 0x01); + + return MYKONOS_ERR_GPIO_OK; +} + +/** + * \brief Sets the Mykonos low voltage GPIO configuration registers + * + * Sets the low voltage GPIO pin direction for each low voltage GPIO pin and + * sets the source control mode (feature) for each group of 4 GPIO pins. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * - device->auxIo->gpio - all members + * + * \param device is a pointer to the device settings structure + * + * \retval MYKONOS_ERR_GPIO_OK Function completed successfully + * \retval MYKONOS_ERR_SET_GPIO_1V8_INV_POINTER device->auxIo->gpio pointer is NULL + * \retval MYKONOS_ERR_SET_GPIO_1V8_INV_MODE gpio structure members have invalid enum value for the GPIO source control mode. + */ +mykonosGpioErr_t MYKONOS_setupGpio(mykonosDevice_t *device) +{ + uint32_t srcWrite = 0x000000; + uint32_t oEnMask = 0x7FFFF; + mykonosGpioErr_t error = MYKONOS_ERR_GPIO_OK; + +#if MYKONOS_VERBOSE == 1 + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_setupGpio()\n"); +#endif + + if (device->auxIo->gpio == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SET_GPIO_1V8_INV_POINTER, + getGpioMykonosErrorMessage(MYKONOS_ERR_SET_GPIO_1V8_INV_POINTER)); + return MYKONOS_ERR_SET_GPIO_1V8_INV_POINTER; + } + + /* write GPIO pin direction registers */ + if ((error = MYKONOS_setGpioOe(device, device->auxIo->gpio->gpioOe, oEnMask)) != MYKONOS_ERR_GPIO_OK) + { + return error; + } + + /* write GPIO source control mode */ + if (((uint8_t)device->auxIo->gpio->gpioSrcCtrl3_0 > 15) || ((uint8_t)device->auxIo->gpio->gpioSrcCtrl7_4 > 15) || + ((uint8_t)device->auxIo->gpio->gpioSrcCtrl11_8 > 15) || ((uint8_t)device->auxIo->gpio->gpioSrcCtrl15_12 > 15) || + ((uint8_t)device->auxIo->gpio->gpioSrcCtrl18_16 > 15)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SET_GPIO_1V8_INV_MODE, + getGpioMykonosErrorMessage(MYKONOS_ERR_SET_GPIO_1V8_INV_MODE)); + return MYKONOS_ERR_SET_GPIO_1V8_INV_MODE; + } + + srcWrite = (uint32_t)device->auxIo->gpio->gpioSrcCtrl3_0 + ((uint32_t)device->auxIo->gpio->gpioSrcCtrl7_4 << 4) + + ((uint32_t)device->auxIo->gpio->gpioSrcCtrl11_8 << 8) + ((uint32_t)device->auxIo->gpio->gpioSrcCtrl15_12 << 12) + + ((uint32_t)device->auxIo->gpio->gpioSrcCtrl18_16 << 16); + + error = MYKONOS_setGpioSourceCtrl(device, srcWrite); + + return error; +} + +/** + * \brief Sets the Mykonos low voltage GPIO output pins direction + * + * This function will set the GPIO direction given by the passed parameter, + * the direction can be either output or input. The gpioUsedMask parameter + * allows the function to only affect the GPIO pins of interest. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * - device->auxIo->gpio->gpioOe + * + * \param device is a pointer to the device settings structure + * \param gpioOutEn (valid range 0 - 0x07FFFF), bit per GPIO pin, the direction is + * + * gpioOutEn[bit] | GPIO[bit] direction + * ----------------|------------------- + * 0 | input + * 1 | output + * + * \param gpioUsedMask Mask used to control which Oe bits are set/cleared. If + * mask bit =1, that bit will be modified by gpioOutEn bit + * + * \retval MYKONOS_ERR_GPIO_OE_INV_PARAM If the Output enable parameter is invalid + * \retval MYKONOS_ERR_GPIO_OK Function completed successfully + */ +mykonosGpioErr_t MYKONOS_setGpioOe(mykonosDevice_t *device, uint32_t gpioOutEn, uint32_t gpioUsedMask) +{ + mykonosGpioErr_t error = MYKONOS_ERR_GPIO_OK; + + const uint32_t GPIO_OE_MASK = 0x7FFFF; + +#if MYKONOS_VERBOSE == 1 + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_setGpioOe()\n"); +#endif + + /* Error checking for correct number of GPIOs available. */ + if (gpioOutEn > GPIO_OE_MASK ) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OE_INV_PARAM, + getGpioMykonosErrorMessage(MYKONOS_ERR_GPIO_OE_INV_PARAM)); + return MYKONOS_ERR_GPIO_OE_INV_PARAM; + } + + /* Mykonos SPI regs to set GPIO OE direction */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_GPIO_DIR_CTL_7_0, (gpioOutEn & 0xFF), (gpioUsedMask & 0xFF), 0); + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_GPIO_DIR_CTL_15_8, ((gpioOutEn >> 8) & 0xFF), ((gpioUsedMask >> 8) & 0xFF), 0); + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_GPIO_DIR_CTL_18_16, ((gpioOutEn >> 16) & 0xFF), ((gpioUsedMask >> 16) & 0xFF), 0); + + /* Updating gpioConfig->gpioSetup->gpioOe output enable */ + if ((error = MYKONOS_getGpioOe(device, &gpioOutEn)) != MYKONOS_ERR_GPIO_OK) + { + return error; + } + + device->auxIo->gpio->gpioOe = gpioOutEn; + + /* Return */ + return MYKONOS_ERR_GPIO_OK; +} + + +/** + * \brief Gets the Mykonos low voltage GPIO output pins direction + * + * This function will get the GPIO direction currently set in the device, + * the direction can be either output or input. The return gpioOutEn function + * parameter returns a bit per GPIO pin. 1 = output from the Mykonos Device, + * 0 = input into the Mykonos device. + * + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device is a pointer to the device settings structure + * \param *gpioOutEn a pointer to the data to be returned with the output enable reading + * + * gpioOutEn[bit] | GPIO[bit] direction + * ----------------|------------------- + * 0 | input + * 1 | output + * + * + * \retval MYKONOS_ERR_GPIO_OK Function completed successfully + * \retval MYKONOS_ERR_GETGPIO_OE_NULL_PARM gpioOutEn function parameter is NULL + */ +mykonosGpioErr_t MYKONOS_getGpioOe(mykonosDevice_t *device, uint32_t *gpioOutEn) +{ + uint8_t readBytes[3] = {0}; + +#if MYKONOS_VERBOSE == 1 + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_getGpioOe()\n"); +#endif + + if (gpioOutEn == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETGPIO_OE_NULL_PARM, + getGpioMykonosErrorMessage(MYKONOS_ERR_GETGPIO_OE_NULL_PARM)); + return MYKONOS_ERR_GETGPIO_OE_NULL_PARM; + } + + /* Reading GPIO output enable registers */ + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_GPIO_DIR_CTL_7_0, &readBytes[0]); + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_GPIO_DIR_CTL_15_8, &readBytes[1]); + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_GPIO_DIR_CTL_18_16, &readBytes[2]); + + /* Updating gpioConfig->gpioSetup->gpioOe output enable */ + *gpioOutEn = ((uint32_t)(readBytes[2] & 0x07) << 16) | ((uint32_t)(readBytes[1]) << 8) | (uint32_t)(readBytes[0]); + + /* Return */ + return MYKONOS_ERR_GPIO_OK; +} + + + +/** + * \brief Sets the Mykonos GPIO source control for different GPIO functionality + * + * This function will only affect the GPIO pins that have their OE direction set to output. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device is a pointer to the device settings structure + * \param gpioSrcCtrl nibble based source control, this is a 32 bit containing + * 5 nibbles that will be set the source control. + * + * \retval MYKONOS_ERR_GPIO_SRC_PARAM_INV If the source control parameter is invalid + * \retval MYKONOS_ERR_GPIO_OK Function completed successfully + */ +mykonosGpioErr_t MYKONOS_setGpioSourceCtrl(mykonosDevice_t *device, uint32_t gpioSrcCtrl) +{ + const uint32_t GPIO_SRC_MASK = 0xFFFFF; + +#if MYKONOS_VERBOSE == 1 + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_setGpioSourceCtrl()\n"); +#endif + + /* writing GPIO configuration registers */ + if (gpioSrcCtrl > GPIO_SRC_MASK) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_SRC_PARAM_INV, + getGpioMykonosErrorMessage(MYKONOS_ERR_GPIO_SRC_PARAM_INV)); + return MYKONOS_ERR_GPIO_SRC_PARAM_INV; + } + + /* writing GPIO configuration registers */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_SOURCE_CONTROL_LOWER_BYTE, (gpioSrcCtrl & 0xFF)); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_SOURCE_CONTROL_UPPER_BYTE, ((gpioSrcCtrl >> 8) & 0xFF)); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_SOURCE_CONTROL_EXTRA_BITS, ((gpioSrcCtrl >> 16) & 0x0F)); + + /* Updating gpioConfig->gpioSetup source control */ + device->auxIo->gpio->gpioSrcCtrl3_0 = (mykonosGpioMode_t)(gpioSrcCtrl & 0x0F); + device->auxIo->gpio->gpioSrcCtrl7_4 = (mykonosGpioMode_t)((gpioSrcCtrl >> 4) & 0x0F); + device->auxIo->gpio->gpioSrcCtrl11_8 = (mykonosGpioMode_t)((gpioSrcCtrl >> 8) & 0x0F); + device->auxIo->gpio->gpioSrcCtrl15_12 = (mykonosGpioMode_t)((gpioSrcCtrl >> 12) & 0x0F); + device->auxIo->gpio->gpioSrcCtrl18_16 = (mykonosGpioMode_t)((gpioSrcCtrl >> 16) & 0x0F); + + /* Return */ + return MYKONOS_ERR_GPIO_OK; +} + +/** + * \brief Reads the Mykonos GPIO source control for different GPIO functionality + * + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device is a pointer to the device settings structure + * \param gpioSrcCtrl nibble based source control, this is a 32 bit containing + * 5 nibbles that will be set the source control. + * + * \retval MYKONOS_ERR_GPIO_OK Function completed successfully + */ +mykonosGpioErr_t MYKONOS_getGpioSourceCtrl(mykonosDevice_t *device, uint32_t *gpioSrcCtrl) +{ + uint8_t readBytes[3] = {0}; + +#if MYKONOS_VERBOSE == 1 + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_getGpioSourceCtrl()\n"); +#endif + + if (gpioSrcCtrl == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GET_GPIO_SOURCE_CONTROL_NULL_PARM, + getGpioMykonosErrorMessage(MYKONOS_ERR_GET_GPIO_SOURCE_CONTROL_NULL_PARM)); + return MYKONOS_ERR_GET_GPIO_SOURCE_CONTROL_NULL_PARM; + } + + /* Reading GPIO output enable registers */ + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_SOURCE_CONTROL_LOWER_BYTE, &readBytes[0]); + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_SOURCE_CONTROL_UPPER_BYTE, &readBytes[1]); + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_SOURCE_CONTROL_EXTRA_BITS, &readBytes[2]); + + /* Updating gpioConfig->gpioSetup->gpioOe output enable */ + *gpioSrcCtrl = ((uint32_t)(readBytes[2] & 0x0F) << 16) | ((uint32_t)(readBytes[1]) << 8) | (uint32_t)(readBytes[0]); + + /* Return */ + return MYKONOS_ERR_GPIO_OK; +} + + + +/** + * \brief Sets the Mykonos 3.3 VDC GPIO configuration registers + * + * This function sets the GPIO 3.3v pin direction (1=output, 0=input) and + * sets the mode of each nibble of GPIO 3.3v pins. See the mykonosGpio3v3Mode_t + * enum for possible modes. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * - device->auxIo->gpio3v3 - all members + * + * \param device is a pointer to the device settings structure + * + * \retval MYKONOS_ERR_GPIO_OK Function completed successfully + * \retval MYKONOS_ERR_SET_GPIO_3V3_INV_POINTER device->auxIo->gpio3v3 pointer is NULL + * \retval MYKONOS_ERR_SET_GPIO_3V3_INV_MODE gpio3v3 members have invalid enum value for the GPIO3v3 source control mode. + */ +mykonosGpioErr_t MYKONOS_setupGpio3v3(mykonosDevice_t *device) +{ + mykonosGpioErr_t error = MYKONOS_ERR_GPIO_OK; + +#if MYKONOS_VERBOSE == 1 + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_setupGpio3v3()\n"); +#endif + + if (device->auxIo->gpio3v3 == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SET_GPIO_3V3_INV_POINTER, + getGpioMykonosErrorMessage(MYKONOS_ERR_SET_GPIO_3V3_INV_POINTER)); + return MYKONOS_ERR_SET_GPIO_3V3_INV_POINTER; + } + else + { + /* write GPIO pin direction registers */ + if ((error = MYKONOS_setGpio3v3Oe(device, device->auxIo->gpio3v3->gpio3v3Oe)) != MYKONOS_ERR_GPIO_OK) + + /* write GPIO3v3 mode */ + if (((uint8_t)device->auxIo->gpio3v3->gpio3v3SrcCtrl3_0 > 15) || + ((uint8_t)device->auxIo->gpio3v3->gpio3v3SrcCtrl7_4 > 15) || + ((uint8_t)device->auxIo->gpio3v3->gpio3v3SrcCtrl11_8 > 15)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SET_GPIO_3V3_INV_MODE, + getGpioMykonosErrorMessage(MYKONOS_ERR_SET_GPIO_3V3_INV_MODE)); + return MYKONOS_ERR_SET_GPIO_3V3_INV_MODE; + } + + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_GPIO_3V3_LSB_SRC_CTL, ((device->auxIo->gpio3v3->gpio3v3SrcCtrl7_4 << 4) | device->auxIo->gpio3v3->gpio3v3SrcCtrl3_0)); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_GPIO_3V3_MSB_SRC_CTL, (device->auxIo->gpio3v3->gpio3v3SrcCtrl11_8 & 0x0F)); + + return error; + } +} + +/** + * \brief If the GPIO3v3 pins are setup for BITBANG mode, this function sets + * the output pin levels per pin + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * - device->auxIo->gpio3v3 - all members + * + * \param device is a pointer to the device settings structure + * \param gpio3v3PinLevel Bit per pin to set the level of each GPIO3v3 output pin + * + * \retval MYKONOS_ERR_GPIO_OK Function completed successfully + */ +mykonosGpioErr_t MYKONOS_setGpio3v3PinLevel(mykonosDevice_t *device, uint16_t gpio3v3PinLevel) +{ + +#if MYKONOS_VERBOSE == 1 + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_setGpio3v3PinLevel()\n"); +#endif + + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_GPIO_3V3_SPI_SRC_7_0, (gpio3v3PinLevel & 0xFF)); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_GPIO_3V3_SPI_SRC_15_8, ((gpio3v3PinLevel >> 8) & 0x0F)); + + return MYKONOS_ERR_GPIO_OK; +} + +/** + * \brief Reads the Mykonos 3.3 VDC GPIO pin output levels for BITBANG mode + * + * This function allows reading the value that the 3.3v GPIO output pins are + * set to drive out the pins. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device is a pointer to the device settings structure + * \param gpio3v3SetLevel is a unit16_t pointer which contains the level of each GPIO3V3 pin (bit per pin) + * + * + * \retval MYKONOS_ERR_GPIO_OK Function completed successfully + * \retval MYKONOS_ERR_GETGPIO3V3OUT_NULL_PARM gpio3v3SetLevel pointer is NULL in function parameter + */ +mykonosGpioErr_t MYKONOS_getGpio3v3SetLevel(mykonosDevice_t *device, uint16_t *gpio3v3SetLevel) +{ + uint8_t readBytes[2] = {0}; + +#if MYKONOS_VERBOSE == 1 + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_getGpio3v3SetLevel()\n"); +#endif + + if (gpio3v3SetLevel == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETGPIO3V3OUT_NULL_PARM, + getGpioMykonosErrorMessage(MYKONOS_ERR_GETGPIO3V3OUT_NULL_PARM)); + return MYKONOS_ERR_GETGPIO3V3OUT_NULL_PARM; + } + + /* reading the registers into two-byte array */ + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_GPIO_3V3_SPI_SRC_7_0, &readBytes[0]); + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_GPIO_3V3_SPI_SRC_15_8, &readBytes[1]); + + /* performing concatenation and assigning value to gpio3v3SpiRead */ + *gpio3v3SetLevel = ((uint16_t)(readBytes[1] & 0x0F) << 8) | (uint16_t)(readBytes[0]); + + return MYKONOS_ERR_GPIO_OK; +} + +/** + * \brief Reads the Mykonos 3.3 VDC GPIO pin levels for BITBANG mode + * + * Note: this function is only capable of reading back pin levels for the + * 3.3v pins set to be inputs. Any pins set to be a GPIO output will read + * back as zero. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device is a pointer to the device settings structure + * \param gpio3v3PinLevel is a unit16_t pointer which contains the level of each GPIO3V3 pin + * that is defined as an input + * + * \retval MYKONOS_ERR_GPIO_OK Function completed successfully + * \retval MYKONOS_ERR_GETGPIO3V3SPI_NULL_PARM gpio3v3PinLevel pointer is NULL in function parameter + */ +mykonosGpioErr_t MYKONOS_getGpio3v3PinLevel(mykonosDevice_t *device, uint16_t *gpio3v3PinLevel) +{ + uint8_t readBytes[2] = {0}; + +#if MYKONOS_VERBOSE == 1 + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_getGpio3v3PinLevel()\n"); +#endif + + if (gpio3v3PinLevel == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETGPIO3V3SPI_NULL_PARM, + getGpioMykonosErrorMessage(MYKONOS_ERR_GETGPIO3V3SPI_NULL_PARM)); + return MYKONOS_ERR_GETGPIO3V3SPI_NULL_PARM; + } + + /* reading the registers for input pin levels */ + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_GPIO_3V3_SPI_READ_7_0, &readBytes[0]); + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_GPIO_3V3_SPI_READ_15_8, &readBytes[1]); + + *gpio3v3PinLevel = ((uint16_t)(readBytes[1] & 0x0F) << 8) | (uint16_t)(readBytes[0]); + + return MYKONOS_ERR_GPIO_OK; +} + +/** + * \brief This function sets the Pin direction control for the Mykonos 3.3 VDC GPIO. + * + * The bits in gpio3v3OutEn are used to configure each corresponding pin as an input or an output. + * If the bit is set, the pin is configured as an output, and if it is clear the pin is configured as an input. + * For example, setting gpio3v3OutEn = 0x02 will configure GPIO_3p3_2 as an output and the rest pins as inputs. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * - device->auxIo->gpio3v3 - all members + * + * \param device is a pointer to the device settings structure + * \param gpio3v3OutEn Bit per pin to set the level of each GPIO3v3 output pin + * + * \retval MYKONOS_ERR_GPIO_OK Function completed successfully + */ +mykonosGpioErr_t MYKONOS_setGpio3v3Oe(mykonosDevice_t *device, uint16_t gpio3v3OutEn) +{ + +#if MYKONOS_VERBOSE == 1 + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_getGpio3v3Oe()\n"); +#endif + + /* write GPIO pin direction registers */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_GPIO_3V3_DIR_CTL_7_0, (gpio3v3OutEn & 0xFF)); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_GPIO_3V3_DIR_CTL_15_8, ((gpio3v3OutEn >> 8) & 0x0F)); + + /* update device->auxIo->gpio3v3 structure */ + device->auxIo->gpio3v3->gpio3v3Oe = gpio3v3OutEn; + + return MYKONOS_ERR_GPIO_OK; +} + +/** + * \brief Reads the Mykonos 3.3 VDC GPIO pin direction + * + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device is a pointer to the device settings structure + * \param gpio3v3OutEn is a unit16_t pointer which will contain the output enable parameter, + * this will be a bit field, if a bit is set then the corresponding GPIO pin is an output, + * if the bit is not set then the corresponding pin is an input + * + * \retval MYKONOS_ERR_GPIO_OK Function completed successfully + * \retval MYKONOS_ERR_GPIO3V3OUTEN_NULL_PARM gpio3v3OutEn pointer is NULL in function parameter + */ +mykonosGpioErr_t MYKONOS_getGpio3v3Oe(mykonosDevice_t *device, uint16_t *gpio3v3OutEn) +{ + uint8_t readBytes[2] = {0}; + +#if MYKONOS_VERBOSE == 1 + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_getGpio3v3Oe()\n"); +#endif + + /* checking for null parameter */ + if (gpio3v3OutEn == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO3V3OUTEN_NULL_PARM, + getGpioMykonosErrorMessage(MYKONOS_ERR_GPIO3V3OUTEN_NULL_PARM)); + return MYKONOS_ERR_GPIO3V3OUTEN_NULL_PARM; + } + + /* reading the registers for input pin levels */ + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_GPIO_3V3_DIR_CTL_7_0, &readBytes[0]); + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_GPIO_3V3_DIR_CTL_15_8, &readBytes[1]); + + *gpio3v3OutEn = ((uint16_t)(readBytes[1] & 0x0F) << 8) | (uint16_t)(readBytes[0]); + + return MYKONOS_ERR_GPIO_OK; +} + + +/** + * \brief Sets the Mykonos GPIO 3.3 VDC source control for different GPIO fucntionality + * + * This function will only affect the GPIO pins that have their OE direction set to output. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device is a pointer to the device settings structure + * \param gpio3v3SrcCtrl nibble based source control, this is a 12 bit containing + * 3 nibbles that will be set the source control. + * + * \retval MYKONOS_ERR_SET_GPIO_3V3_INV_SRC_CTRL gpio3v3 members have invalid value for the GPIO3v3 source control mode. + * \retval MYKONOS_ERR_GPIO_OK Function completed successfully + */ +mykonosGpioErr_t MYKONOS_setGpio3v3SourceCtrl(mykonosDevice_t *device, uint16_t gpio3v3SrcCtrl) +{ + const uint16_t GPIO_SRC_MASK = 0x0FFF; + +#if MYKONOS_VERBOSE == 1 + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_setGpio3v3SourceCtrl()\n"); +#endif + + /* writing GPIO configuration registers */ + if (gpio3v3SrcCtrl > GPIO_SRC_MASK) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SET_GPIO_3V3_INV_SRC_CTRL, + getGpioMykonosErrorMessage(MYKONOS_ERR_SET_GPIO_3V3_INV_SRC_CTRL)); + return MYKONOS_ERR_SET_GPIO_3V3_INV_SRC_CTRL; + } + + /* writing GPIO configuration registers */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_GPIO_3V3_LSB_SRC_CTL, (gpio3v3SrcCtrl & 0xFF)); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_GPIO_3V3_MSB_SRC_CTL, ((gpio3v3SrcCtrl >> 8) & 0xFF)); + + /* Updating gpioConfig->gpioSetup source control */ + device->auxIo->gpio3v3->gpio3v3SrcCtrl3_0 = (mykonosGpio3v3Mode_t)(gpio3v3SrcCtrl & 0x0F); + device->auxIo->gpio3v3->gpio3v3SrcCtrl7_4 = (mykonosGpio3v3Mode_t)(gpio3v3SrcCtrl & 0xF0); + device->auxIo->gpio3v3->gpio3v3SrcCtrl11_8 = (mykonosGpio3v3Mode_t)((gpio3v3SrcCtrl >> 8) & 0x0F); + + /* Return */ + return MYKONOS_ERR_GPIO_OK; +} + +/** + * \brief Reads the Mykonos 3v3 GPIO source control for different GPIO functionality + * + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device is a pointer to the device settings structure + * \param gpio3v3SrcCtrl nibble based source control, this is a 12 bit containing + * 3 nibbles that will be set the source control. + * + * \retval MYKONOS_ERR_GPIO_OK Function completed successfully + */ +mykonosGpioErr_t MYKONOS_getGpio3v3SourceCtrl(mykonosDevice_t *device, uint16_t *gpio3v3SrcCtrl) +{ + uint8_t readBytes[2] = {0}; + +#if MYKONOS_VERBOSE == 1 + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_getGpio3v3SourceCtrl()\n"); +#endif + + /* checking for null parameter */ + if (gpio3v3SrcCtrl == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO3V3OUTEN_NULL_PARM, + getGpioMykonosErrorMessage(MYKONOS_ERR_GPIO3V3OUTEN_NULL_PARM)); + return MYKONOS_ERR_GPIO3V3OUTEN_NULL_PARM; + } + + /* Reading GPIO output enable registers */ + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_GPIO_3V3_LSB_SRC_CTL, &readBytes[0]); + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_GPIO_3V3_MSB_SRC_CTL, &readBytes[1]); + + /* Updating gpioConfig->gpioSetup->gpioOe output enable */ + *gpio3v3SrcCtrl = ((uint16_t)(readBytes[1] & 0xFF) << 8) | ((uint16_t)(readBytes[0])); + + /* Return */ + return MYKONOS_ERR_GPIO_OK; +} + + +/** + * \brief Gain compensation enable and setup function. + * + * The gain compensation block is a function that compensates for the attenuation in the internal attenuator for the Rx channels. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device is a pointer to the device settings structure + * \param gainComp which is a mykonosGainComp_t structure. + * \param enable this parameter enables or disables the gain compensation block. + * enable = 1 + * disable = 0 + * + * \retval MYKONOS_ERR_GPIO_OK Function completed successfully + * \retval MYKONOS_ERR_GAINCOMP_SET_NULL_STRUCT gain compensation structure gainComp is not initialised + * \retval MYKONOS_ERR_GAINCOMP_INV_RX1_OFFSET gain compensation structure gainComp->rx1Offset is invalid + * \retval MYKONOS_ERR_GAINCOMP_INV_RX2_OFFSET gain compensation structure gainComp->rx2Offset is invalid + * \retval MYKONOS_ERR_GAINCOMP_INV_STEP gain compensation structure gainComp->compStep is invalid + * \retval MYKONOS_ERR_GAINCOMP_INV_EN enable is not valid + */ +mykonosGpioErr_t MYKONOS_setRxGainCompensation (mykonosDevice_t *device, mykonosGainComp_t *gainComp, uint8_t enable) +{ + uint8_t regWr2 = 0x00; + uint8_t regWr3 = 0x00; + uint8_t regWr4 = 0x00; + + /* Max parameter values for error checking */ + const uint8_t RXOFFSET_RANGE = 0x1F; + const uint8_t STEP_RANGE = 0x07; + +#if MYKONOS_VERBOSE == 1 + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_setRxGainCompensation()\n"); +#endif + + /* Check for gainComp initialised */ + if (gainComp == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GAINCOMP_SET_NULL_STRUCT, + getGpioMykonosErrorMessage(MYKONOS_ERR_GAINCOMP_SET_NULL_STRUCT)); + return MYKONOS_ERR_GAINCOMP_SET_NULL_STRUCT; + } + + /* Check for enable */ + if (enable > 1) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GAINCOMP_INV_EN, + getGpioMykonosErrorMessage(MYKONOS_ERR_GAINCOMP_INV_EN)); + return MYKONOS_ERR_GAINCOMP_INV_EN; + } + else if (enable == 1) + { + /* Check for gain compensation Rx1 offset range */ + if (gainComp->rx1Offset > RXOFFSET_RANGE) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GAINCOMP_INV_RX1_OFFSET, + getGpioMykonosErrorMessage(MYKONOS_ERR_GAINCOMP_INV_RX1_OFFSET)); + return MYKONOS_ERR_GAINCOMP_INV_RX1_OFFSET; + } + + /* Check for gain compensation Rx2 offset range */ + if (gainComp->rx2Offset > RXOFFSET_RANGE) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GAINCOMP_INV_RX2_OFFSET, + getGpioMykonosErrorMessage(MYKONOS_ERR_GAINCOMP_INV_RX2_OFFSET)); + return MYKONOS_ERR_GAINCOMP_INV_RX2_OFFSET; + } + + /* Check for gain compensation step range */ + if (gainComp->compStep > STEP_RANGE) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GAINCOMP_INV_STEP, + getGpioMykonosErrorMessage(MYKONOS_ERR_GAINCOMP_INV_STEP)); + return MYKONOS_ERR_GAINCOMP_INV_STEP; + } + + /* Enabling gain compensation block */ + regWr4 = 0x88 | gainComp->compStep; + regWr3 = gainComp->rx2Offset; + regWr2 = gainComp->rx1Offset; + } + + /* Write gain compensation setup to device */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RX1_GAIN_COMP_OFFSET, regWr2); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RX2_GAIN_COMP_OFFSET, regWr3); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RX_GAIN_COMP_CFG, regWr4); + + /* Return */ + return MYKONOS_ERR_GPIO_OK; +} + +/** + * \brief Get gain compensation setup and enabled function. + * + * The gain compensation block is a function that compensates for the attenuation in the internal attenuator for the Rx channels. + * This function will get the current setup and the enable state of the block. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device is a pointer to the device settings structure + * \param gainComp pointer to a mykonosGainComp_t structure, will held the current device gain compensation settings. + * \param enabled pointer this parameter will contain the enable state of the gain compensation block. + * enabled = 1 + * disabled = 0 + * + * \retval MYKONOS_ERR_GPIO_OK Function completed successfully + * \retval MYKONOS_ERR_GAINCOMP_NULL_STRUCT gain compensation structure gainComp is not initialised + * \retval MYKONOS_ERR_GAINCOMP_EN_NULL_PARM enable is null pointer for the passed parameter + */ +mykonosGpioErr_t MYKONOS_getRxGainCompensation (mykonosDevice_t *device, mykonosGainComp_t *gainComp, uint8_t *enabled) +{ + uint8_t regWr2 = 0x00; + uint8_t regWr3 = 0x00; + uint8_t regWr4 = 0x00; + + /* Mask parameter values populating mykonosGainComp_t structure */ + const uint8_t ENABLED_MASK = 0x80; + const uint8_t STEP_MASK = 0x07; + + /* Shift values for writing gain values */ + const uint8_t ENABLED_SHIFT = 0x07; + +#if MYKONOS_VERBOSE == 1 + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_getRxGainCompensation()\n"); +#endif + + /* Check for gainComp for Null */ + if (gainComp == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GAINCOMP_NULL_STRUCT, + getGpioMykonosErrorMessage(MYKONOS_ERR_GAINCOMP_NULL_STRUCT)); + return MYKONOS_ERR_GAINCOMP_NULL_STRUCT; + } + + if (enabled == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GAINCOMP_EN_NULL_PARM, + getGpioMykonosErrorMessage(MYKONOS_ERR_GAINCOMP_EN_NULL_PARM)); + return MYKONOS_ERR_GAINCOMP_EN_NULL_PARM; + } + + /* Read gain compensation setup from device */ + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_RX1_GAIN_COMP_OFFSET, ®Wr2); + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_RX2_GAIN_COMP_OFFSET, ®Wr3); + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_RX_GAIN_COMP_CFG, ®Wr4); + + + /* Parsing read data to passed by reference parameters */ + *enabled = (regWr4 & ENABLED_MASK) >> ENABLED_SHIFT; + gainComp->compStep = (regWr4 & STEP_MASK); + gainComp->rx2Offset = regWr3; + gainComp->rx1Offset = regWr2; + + /* Return */ + return MYKONOS_ERR_GPIO_OK; +} + + +/** + * \brief Gain compensation enable and setup function for the observation channel. + * + * The gain compensation block is a function that compensates for the attenuation in the internal attenuator for the observation channels. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device is a pointer to the device settings structure + * \param gainComp is a pointer to the mykonosObsRxGainComp_t structure. + * \param enable enables or disables the gain compensation block. + * enable = 1 + * disable = 0 + * + * \retval MYKONOS_ERR_OBS_RX_GAINCOMP_SET_NULL_STRUCT gain compensation structure gainComp is not initialised + * \retval MYKONOS_ERR_OBS_RX_GAINCOMP_INV_OFFSET gain compensation structure gainComp->obsRxOffset is invalid + * \retval MYKONOS_ERR_OBS_RX_GAINCOMP_INV_STEP gain compensation structure gainComp->compStep is invalid + * \retval MYKONOS_ERR_OBS_RX_GAINCOMP_INV_EN enable is not valid + * \retval MYKONOS_ERR_GPIO_OK Function completed successfully + */ +mykonosGpioErr_t MYKONOS_setObsRxGainCompensation (mykonosDevice_t *device, mykonosObsRxGainComp_t *gainComp, uint8_t enable) +{ + uint8_t regWr2 = 0x00; + uint8_t regWr3 = 0x00; + + /* Max parameter values for error checking */ + const uint8_t RXOFFSET_RANGE = 0x1F; + + /* Shift values for writing gain values */ + const uint8_t STEP_RANGE = 0x07; + +#if MYKONOS_VERBOSE == 1 + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_setObsRxGainCompensation()\n"); +#endif + + /* Check for gainComp initialised */ + if (gainComp == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OBS_RX_GAINCOMP_SET_NULL_STRUCT, + getGpioMykonosErrorMessage(MYKONOS_ERR_OBS_RX_GAINCOMP_SET_NULL_STRUCT)); + return MYKONOS_ERR_OBS_RX_GAINCOMP_SET_NULL_STRUCT; + } + + /* Check for enable */ + if (enable > 1) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OBS_RX_GAINCOMP_INV_EN, + getGpioMykonosErrorMessage(MYKONOS_ERR_OBS_RX_GAINCOMP_INV_EN)); + return MYKONOS_ERR_OBS_RX_GAINCOMP_INV_EN; + } + else if (enable == 1) + { + /* Check for gain compensation offset range */ + if (gainComp->obsRxOffset > RXOFFSET_RANGE) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OBS_RX_GAINCOMP_INV_OFFSET, + getGpioMykonosErrorMessage(MYKONOS_ERR_OBS_RX_GAINCOMP_INV_OFFSET)); + return MYKONOS_ERR_OBS_RX_GAINCOMP_INV_OFFSET; + } + + /* Check for gain compensation step range */ + if (gainComp->compStep > STEP_RANGE) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OBS_RX_GAINCOMP_INV_STEP, + getGpioMykonosErrorMessage(MYKONOS_ERR_OBS_RX_GAINCOMP_INV_STEP)); + return MYKONOS_ERR_OBS_RX_GAINCOMP_INV_STEP; + } + + /* Enabling gain compensation block */ + regWr3 = 0x88 | gainComp->compStep; + regWr2 = ((gainComp->obsRxOffset & 0x1E) >> 1) | ((gainComp->obsRxOffset & 0x01) << 4); + } + + /* Write gain compensation setup to device */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DPD_SNF_RX_GAIN_COMP_OFFSET, regWr2); + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DPD_SNF_RX_GAIN_COMP_CFG, regWr3); + + /* Return */ + return MYKONOS_ERR_GPIO_OK; +} + +/** + * \brief Get gain compensation setup and enabled function for the observation channel. + * + * The gain compensation block is a function that compensates for the attenuation in the internal attenuator for the observation + * channels. + * This function will get the current setup and the enable state of the block. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device is a pointer to the device settings structure + * \param gainComp pointer to a mykonosObsRxGainComp_t structure, will held the current device gain compensation settings. + * \param enabled pointer this parameter will contain the enable state of the gain compensation block. + * enabled = 1 + * disabled = 0 + * + * \retval MYKONOS_ERR_GPIO_OK Function completed successfully + * \retval MYKONOS_ERR_OBS_RX_GAINCOMP_NULL_STRUCT observation channel gain compensation structure gainComp is not initialised + * \retval MYKONOS_ERR_OBS_RX_GAINCOMP_EN_NULL_PARAM enabled is null pointer for the parameter passed + */ +mykonosGpioErr_t MYKONOS_getObsRxGainCompensation (mykonosDevice_t *device, mykonosObsRxGainComp_t *gainComp, uint8_t *enabled) +{ + uint8_t regRd2 = 0x00; + uint8_t regRd3 = 0x00; + + /* Masks values for populating mykonosObsRxGainComp_t structure */ + const uint8_t ENABLED_MASK = 0x80; + const uint8_t STEP_MASK = 0x07; + + /* Shift values for populating mykonosObsRxGainComp_t structure */ + const uint8_t ENABLED_SHIFT = 0x07; + +#if MYKONOS_VERBOSE == 1 + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_getObsRxGainCompensation()\n"); +#endif + + /* Check for gainComp for Null */ + if (gainComp == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OBS_RX_GAINCOMP_NULL_STRUCT, + getGpioMykonosErrorMessage(MYKONOS_ERR_OBS_RX_GAINCOMP_NULL_STRUCT)); + return MYKONOS_ERR_OBS_RX_GAINCOMP_NULL_STRUCT; + } + + if (enabled == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OBS_RX_GAINCOMP_EN_NULL_PARAM, + getGpioMykonosErrorMessage(MYKONOS_ERR_OBS_RX_GAINCOMP_EN_NULL_PARAM)); + return MYKONOS_ERR_OBS_RX_GAINCOMP_EN_NULL_PARAM; + } + + /* Read gain compensation setup from device */ + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_DPD_SNF_RX_GAIN_COMP_OFFSET, ®Rd2); + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_DPD_SNF_RX_GAIN_COMP_CFG, ®Rd3); + + + /* Parsing read data to passed by reference parameters */ + *enabled = (regRd3 & ENABLED_MASK) >> ENABLED_SHIFT; + gainComp->compStep = (regRd3 & STEP_MASK); + gainComp->obsRxOffset = ((regRd2 & 0x0F) << 1) | ((regRd2 & 0x10) >> 4); + + /* Return */ + return MYKONOS_ERR_GPIO_OK; +} + +/** + * \brief Slicer control over GPIO inputs. + * + * The user can control the slicer position via 3 GPIO inputs per channel. + * There are various configurations for the GPIO pins, this configurations are enumerated in the mykonosRxSlicer_t. + * + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * - Gain compensation block has to be enabled in order to user the slicer control + * + * \param device is a pointer to the device settings structure + * \param slicerStep configures the step size of the slicer when external pin contol mode is enabled. + * Slicer gain in this mode is determined by multiplying the step size by the input bit code from the BBP. + * Step sizes are as follows: + * sllicerStep | step + * -------------|------------ + * 0 | 1 + * 1 | 2 + * 2 | 3 + * 3 | 4 + * + * \param rx1Pins Rx1 slicer inputs can take values from one of the following combinations that are specified in mykonosRxSlicer_t enum: + * -GPIO_2, GPIO_1, and GPIO_0 + * -GPIO_7, GPIO_6, and GPIO_5 + * -GPIO_10, GPIO_9, and GPIO_8 + * \param rx2Pins Rx2 slicer inputs can take values from one of the following combinations that are specified in mykonosRxSlicer_t enum: + * -GPIO_7, GPIO_6, and GPIO_5 + * -GPIO_13, GPIO_12, and GPIO_11 + * \param enable this parameter enables the external pin control mode so the BBP can control the slicer setting. + * enable = 1 + * disable = 0 + * + * \retval MYKONOS_ERR_GPIO_OK Function completed successfully + * \retval MYKONOS_ERR_SLICER_INV_RX1_SEL invalid RX1 GPIO pin selection for Slicer control + * \retval MYKONOS_ERR_SLICER_INV_RX2_SEL invalid RX2 GPIO pin selection for Slicer control + * \retval MYKONOS_ERR_SLICER_STEP_OUT_OF_RANGE slicer step is out of range + * \retval MYKONOS_ERR_SLICER_EN_INV invalid enable + */ +mykonosGpioErr_t MYKONOS_setRxSlicerCtrl(mykonosDevice_t *device, uint8_t slicerStep, mykonosRxSlicer_t rx1Pins, mykonosRxSlicer_t rx2Pins, uint8_t enable) +{ + uint8_t regWr = 0x00; + + const uint8_t STEP_MASK = 0x03; + const uint8_t STEP_SHIFT = 0x05; + +#if MYKONOS_VERBOSE == 1 + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_setRxSlicerCtrl()\n"); +#endif + + if (enable > 1) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SLICER_EN_INV, + getGpioMykonosErrorMessage(MYKONOS_ERR_SLICER_EN_INV)); + return MYKONOS_ERR_SLICER_EN_INV; + } + else if (enable == 1) + { + /* Enabling Slicer input control */ + regWr = 0x80; + + /* Check for Rx1 Slicer input control */ + switch (rx1Pins) + { + case GPIO_0_1_2: + regWr |= 0x00; + break; + case GPIO_5_6_7: + regWr |= 0x01; + break; + case GPIO_8_9_10: + regWr |= 0x02; + break; + default: + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SLICER_INV_RX1_SEL, + getGpioMykonosErrorMessage(MYKONOS_ERR_SLICER_INV_RX1_SEL)); + return MYKONOS_ERR_SLICER_INV_RX1_SEL; + } + + /* Check for Rx2 Slicer input control */ + switch (rx2Pins) + { + case GPIO_11_12_13: + regWr |= 0x00; + break; + case GPIO_5_6_7: + regWr |= 0x04; + break; + default: + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SLICER_INV_RX2_SEL, + getGpioMykonosErrorMessage(MYKONOS_ERR_SLICER_INV_RX2_SEL)); + return MYKONOS_ERR_SLICER_INV_RX2_SEL; + } + + /* Check for Slicer input step size control */ + if (slicerStep > STEP_MASK) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SLICER_STEP_OUT_OF_RANGE, + getGpioMykonosErrorMessage(MYKONOS_ERR_SLICER_STEP_OUT_OF_RANGE)); + return MYKONOS_ERR_SLICER_STEP_OUT_OF_RANGE; + } + else + { + regWr |= (uint8_t)(slicerStep << STEP_SHIFT); + } + } + + /* Write to device the slicer configuration */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RX_SLCR_PIN_CFG, regWr); + + return MYKONOS_ERR_GPIO_OK; +} + +/** + * \brief This function will get the programmed Slicer control for Rx1 and Rx2 channels. + * + * The user can control the slicer position via 3 GPIO inputs per channel. + * There are various configurations for the GPIO pins, this configurations are enumerated in the mykonosRxSlicer_t. + * + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device is a pointer to the device settings structure + * \param slicerStep will contain the configured step size + * \param rx1Pins will contain the configured GPIO combination for Rx1 + * \param rx2Pins will contain the configured GPIO combination for Rx2 + * \param enable will contain the programmed enable setting + * + * \retval MYKONOS_ERR_GPIO_OK Function completed successfully + * \retval MYKONOS_ERR_SLICER_RX1PIN_NULL_PARM rx1Pins is null pointer for the passed parameter + * \retval MYKONOS_ERR_SLICER_RX2PIN_NULL_PARM rx1Pins is null pointer for the passed parameter + * \retval MYKONOS_ERR_SLICER_STEP_NULL_PARM slicerStep is null pointer for the passed parameter + * \retval MYKONOS_ERR_SLICER_EN_NULL_PARM enable is null pointer for the passed parameter + */ +mykonosGpioErr_t MYKONOS_getRxSlicerCtrl(mykonosDevice_t *device, uint8_t *slicerStep, mykonosRxSlicer_t *rx1Pins, mykonosRxSlicer_t *rx2Pins, uint8_t *enable) +{ + uint8_t regRd = 0x00; + + /* Mask parameter values populating parameters */ + const uint8_t EN_MASK = 0x80; + const uint8_t STEP_MASK = 0x60; + const uint8_t RX1_MASK = 0x03; + const uint8_t RX2_MASK = 0x0C; + + /* Shift values for populating passed parameters */ + const uint8_t EN_SHIFT = 0x07; + const uint8_t STEP_SHIFT = 0x05; + const uint8_t RX1_SHIFT = 0x00; + const uint8_t RX2_SHIFT = 0x02; + +#if MYKONOS_VERBOSE == 1 + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_getRxSlicerCtrl()\n"); +#endif + + /* Check for Rx1 Slicer input control null parameter */ + if (rx1Pins == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SLICER_RX1PIN_NULL_PARM, + getGpioMykonosErrorMessage(MYKONOS_ERR_SLICER_RX1PIN_NULL_PARM)); + return MYKONOS_ERR_SLICER_RX1PIN_NULL_PARM; + } + + /* Check for Rx2 Slicer input control null parameter */ + if (rx2Pins == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SLICER_RX2PIN_NULL_PARM, + getGpioMykonosErrorMessage(MYKONOS_ERR_SLICER_RX2PIN_NULL_PARM)); + return MYKONOS_ERR_SLICER_RX2PIN_NULL_PARM; + } + + /* Check for Slicer step control null parameter */ + if (slicerStep == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SLICER_STEP_NULL_PARM, + getGpioMykonosErrorMessage(MYKONOS_ERR_SLICER_STEP_NULL_PARM)); + return MYKONOS_ERR_SLICER_STEP_NULL_PARM; + } + + /* Check for Slicer step control null parameter */ + if (enable == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SLICER_EN_NULL_PARM, + getGpioMykonosErrorMessage(MYKONOS_ERR_SLICER_EN_NULL_PARM)); + return MYKONOS_ERR_SLICER_EN_NULL_PARM; + } + + /* Reading SLicer control register */ + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_RX_SLCR_PIN_CFG, ®Rd); + + /* Parsing values */ + *enable = (regRd & EN_MASK) >> EN_SHIFT; + *slicerStep = (regRd & STEP_MASK) >> STEP_SHIFT; + + /* Map to enum */ + switch ((regRd & RX2_MASK) >> RX2_SHIFT) + { + case 0: + *rx2Pins = GPIO_11_12_13; + break; + case 1: + *rx2Pins = GPIO_5_6_7; + break; + + default: + *rx2Pins = GPIO_11_12_13; + break; + } + + *rx1Pins = (mykonosRxSlicer_t)((regRd & RX1_MASK) >> RX1_SHIFT); + + /* Return */ + return MYKONOS_ERR_GPIO_OK; +} + +/** + * \brief Slicer control over GPIO inputs for the observation channel. + * + * The user can control the slicer position via 3 GPIO inputs for the observation channel. + * There are various configurations for the GPIO pins, this configurations are enumerated in the mykonosObsRxSlicer_t. + * + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * - Gain compensation block has to be enabled in order to user the slicer control + * + * \param device is a pointer to the device settings structure + * \param slicerStep configures the step size of the slicer when external pin contol mode is enabled. + * Slicer gain in this mode is determined by multiplying the step size by the input bit code from the BBP. + * Step sizes are as follows: + * sllicerStep | step + * -------------|------------ + * 0 | 1 + * 1 | 2 + * 2 | 3 + * 3 | 4 + * + * \param obsRxPins observation slicer inputs can take values from one of the following combinations that are specified in mykonosObsRxSlicer_t enum: + * -GPIO_18, GPIO_17 and GPIO_16 + * -GPIO_16, GPIO_15 and GPIO_14 + * \param enable enables the external pin control mode so the BBP can control the slicer setting. + * enable = 1 + * disable = 0 + * + * \retval MYKONOS_ERR_SLICER_INV_OBS_RX_SEL invalid observation channel GPIO pin selection for Slicer control + * \retval MYKONOS_ERR_SLICER_OBS_RX_STEP_OUT_OF_RANGE slicer step is out of range + * \retval MYKONOS_ERR_SLICER_OBS_RX_EN_INV invalid enable + * \retval MYKONOS_ERR_GPIO_OK Function completed successfully + */ +mykonosGpioErr_t MYKONOS_setObsRxSlicerCtrl(mykonosDevice_t *device, uint8_t slicerStep, mykonosObsRxSlicer_t obsRxPins, uint8_t enable) +{ + uint8_t regWr = 0x00; + + const uint8_t STEP_MASK = 0x03; + const uint8_t STEP_SHIFT = 0x05; + +#if MYKONOS_VERBOSE == 1 + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_setObsRxSlicerCtrl()\n"); +#endif + + if (enable > 1) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SLICER_OBS_RX_EN_INV, + getGpioMykonosErrorMessage(MYKONOS_ERR_SLICER_OBS_RX_EN_INV)); + return MYKONOS_ERR_SLICER_OBS_RX_EN_INV; + } + else if (enable == 1) + { + /* Enabling Slicer input control */ + regWr = 0x80; + + /* Check for Rx1 Slicer input control */ + switch (obsRxPins) + { + case GPIO_18_17_16: + regWr |= 0x00; + break; + case GPIO_16_15_14: + regWr |= 0x01; + break; + + default: + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SLICER_INV_OBS_RX_SEL, + getGpioMykonosErrorMessage(MYKONOS_ERR_SLICER_INV_OBS_RX_SEL)); + return MYKONOS_ERR_SLICER_INV_OBS_RX_SEL; + } + + /* Check for Slicer input step size control */ + if (slicerStep & ~STEP_MASK) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SLICER_OBS_RX_STEP_OUT_OF_RANGE, + getGpioMykonosErrorMessage(MYKONOS_ERR_SLICER_OBS_RX_STEP_OUT_OF_RANGE)); + return MYKONOS_ERR_SLICER_OBS_RX_STEP_OUT_OF_RANGE; + } + else + { + regWr |= (uint8_t)((slicerStep << STEP_SHIFT)); + } + } + + /* Write to device the slicer configuration */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DPD_SNF_RX_SLCR_PIN_CFG, regWr); + + return MYKONOS_ERR_GPIO_OK; +} + +/** + * \brief This function will get the programmed Slicer control for observation channel. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device is a pointer to the device settings structure + * \param slicerStep will contain the configured step size + * \param obsRxPins will contain the configured GPIO combination + * \param enable will contain the programmed enable setting + * + * \retval MYKONOS_ERR_SLICER_OBS_RXPIN_NULL_PARM obsRxPins is null pointer for the passed parameter + * \retval MYKONOS_ERR_SLICER_OBS_RX_STEP_NULL_PARM slicerStep is null pointer for the passed parameter + * \retval MYKONOS_ERR_SLICER_OBS_RX_EN_NULL_PARM, enable is null pointer for the passed parameter + * \retval MYKONOS_ERR_GPIO_OK Function completed successfully + */ +mykonosGpioErr_t MYKONOS_getObsRxSlicerCtrl(mykonosDevice_t *device, uint8_t *slicerStep, mykonosObsRxSlicer_t *obsRxPins, uint8_t *enable) +{ + uint8_t regRd = 0x00; + + /* Mask parameter values populating slicer parameters */ + const uint8_t EN_MASK = 0x80; + const uint8_t STEP_MASK = 0x60; + const uint8_t OBS_RX_MASK = 0x03; + + /* Shift values for writing slicer parameters */ + const uint8_t EN_SHIFT = 0x07; + const uint8_t STEP_SHIFT = 0x05; + +#if MYKONOS_VERBOSE == 1 + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_getObsRxSlicerCtrl()\n"); +#endif + + /* Check for Rx1 Slicer input control null parameter */ + if (obsRxPins == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SLICER_OBS_RXPIN_NULL_PARM, + getGpioMykonosErrorMessage(MYKONOS_ERR_SLICER_OBS_RXPIN_NULL_PARM)); + return MYKONOS_ERR_SLICER_OBS_RXPIN_NULL_PARM; + } + + /* Check for Slicer step control null parameter */ + if (slicerStep == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SLICER_OBS_RX_STEP_NULL_PARM, + getGpioMykonosErrorMessage(MYKONOS_ERR_SLICER_OBS_RX_STEP_NULL_PARM)); + return MYKONOS_ERR_SLICER_OBS_RX_STEP_NULL_PARM; + } + + /* Check for Slicer step control null parameter */ + if (enable == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SLICER_OBS_RX_EN_NULL_PARM, + getGpioMykonosErrorMessage(MYKONOS_ERR_SLICER_OBS_RX_EN_NULL_PARM)); + return MYKONOS_ERR_SLICER_OBS_RX_EN_NULL_PARM; + } + + /* Reading Slicer control register */ + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_DPD_SNF_RX_SLCR_PIN_CFG, ®Rd); + + /* Parsing values */ + *enable = (regRd & EN_MASK) >> EN_SHIFT; + *slicerStep = (regRd & STEP_MASK) >> STEP_SHIFT; + + /* Map to enum */ + switch (regRd & OBS_RX_MASK) + { + case 0: + *obsRxPins = GPIO_18_17_16; + break; + case 1: + *obsRxPins = GPIO_16_15_14; + break; + + default: + *obsRxPins = (mykonosObsRxSlicer_t)0; + break; + } + + /* Return */ + return MYKONOS_ERR_GPIO_OK; +} + + +/** + * \brief Floating point formatter enable and setup function. + * + * The floating point formatter block is a function that works in conjunction with the gain + * compensating block, as the gain compensation requires increased dynamic range (total gain range on AD9371 is 42dB) + * which increases the bitwidth in the digital datapath. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * - Gain compensation block has to be enabled in order to user floating point formatter + * + * \param device is a pointer to the device settings structure + * \param floatFrmt which is a mykonosFloatPntFrmt_t structure. + * + * \retval MYKONOS_ERR_GPIO_OK Function completed successfully + * \retval MYKONOS_ERR_FLOATFRMT_SET_NULL_STRUCT floating point formatter structure floatFrmt not initialized + * \retval MYKONOS_ERR_FLOATFRMT_INV_ROUND_MODE floating point formatter structure floatFrmt.roundMode not valid parameter + * \retval MYKONOS_ERR_FLOATFRMT_INV_DATA_FORMAT floating point formatter structure floatFrmt.dataFormat not valid parameter + * \retval MYKONOS_ERR_FLOATFRMT_INV_ENC_NAN floating point formatter structure floatFrmt.encNan not valid parameter + * \retval MYKONOS_ERR_FLOATFRMT_INV_EXP_BITS floating point formatter structure floatFrmt.expBits not valid parameter + * \retval MYKONOS_ERR_FLOATFRMT_INV_LEADING floating point formatter structure floatFrmt.leading not valid parameter + */ +mykonosGpioErr_t MYKONOS_setFloatPointFrmt (mykonosDevice_t *device, mykonosFloatPntFrmt_t *floatFrmt) +{ + uint8_t regWr1 = 0x00; + + /* Max parameter values for error checking */ + const uint8_t ROUND_RANGE = 0x04; + const uint8_t DATA_FRMT_RANGE = 0x01; + const uint8_t ENCODE_RANGE = 0x01; + const uint8_t EXPBITS_RANGE = 0x03; + const uint8_t LEADING_RANGE = 0x01; + + /* Shift values for writing mykonosFloatPntFrmt_t values */ + const uint8_t ROUND_SHIFT = 0x05; + const uint8_t DATA_FRMT_SHIFT = 0x04; + const uint8_t ENCODE_SHIFT = 0x03; + const uint8_t EXPBITS_SHIFT = 0x01; + const uint8_t LEADING_SHIFT = 0x00; + +#if MYKONOS_VERBOSE == 1 + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_setFloatPointFrmt()\n"); +#endif + + /* Check for gainComp initialised */ + if (floatFrmt == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_FLOATFRMT_SET_NULL_STRUCT, + getGpioMykonosErrorMessage(MYKONOS_ERR_FLOATFRMT_SET_NULL_STRUCT)); + return MYKONOS_ERR_FLOATFRMT_SET_NULL_STRUCT; + } + + /* Check for floating point round mode */ + if (floatFrmt->roundMode > ROUND_RANGE) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_FLOATFRMT_INV_ROUND_MODE, + getGpioMykonosErrorMessage(MYKONOS_ERR_FLOATFRMT_INV_ROUND_MODE)); + return MYKONOS_ERR_FLOATFRMT_INV_ROUND_MODE; + } + + /* Check for floating point data format */ + if (floatFrmt->dataFormat > DATA_FRMT_RANGE) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_FLOATFRMT_INV_DATA_FORMAT, + getGpioMykonosErrorMessage(MYKONOS_ERR_FLOATFRMT_INV_DATA_FORMAT)); + return MYKONOS_ERR_FLOATFRMT_INV_DATA_FORMAT; + } + + /* Check for floating point encode NaN */ + if (floatFrmt->encNan > ENCODE_RANGE) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_FLOATFRMT_INV_ENC_NAN, + getGpioMykonosErrorMessage(MYKONOS_ERR_FLOATFRMT_INV_ENC_NAN)); + return MYKONOS_ERR_FLOATFRMT_INV_ENC_NAN; + } + + /* Check for floating point exponent bits range */ + if (floatFrmt->expBits > EXPBITS_RANGE) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_FLOATFRMT_INV_EXP_BITS, + getGpioMykonosErrorMessage(MYKONOS_ERR_FLOATFRMT_INV_EXP_BITS)); + return MYKONOS_ERR_FLOATFRMT_INV_EXP_BITS; + } + + /* Check for floating point hide leading ones */ + if (floatFrmt->leading > LEADING_RANGE) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_FLOATFRMT_INV_LEADING, + getGpioMykonosErrorMessage(MYKONOS_ERR_FLOATFRMT_INV_LEADING)); + return MYKONOS_ERR_FLOATFRMT_INV_LEADING; + } + + regWr1 = (uint8_t)((floatFrmt->roundMode << ROUND_SHIFT) | (floatFrmt->dataFormat << DATA_FRMT_SHIFT) | + (floatFrmt->encNan << ENCODE_SHIFT) | (floatFrmt->expBits << EXPBITS_SHIFT) | + (floatFrmt->leading << LEADING_SHIFT)); + + + /* Write gain compensation setup to device */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FLOATING_POINT_CFG, regWr1); + + /* Return */ + return MYKONOS_ERR_GPIO_OK; +} + +/** + * \brief Floating point formatter setup function. + * + * The floating point formatter block is a function that works in conjunction with the gain + * compensating block, as the gain compensation requires increased dynamic range + * which increases the bit-width in the digital data-path. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * - Gain compensation block has to be enabled in order to user floating point formatter + * + * \param device is a pointer to the device settings structure + * \param floatFrmt which is a mykonosFloatPntFrmt_t structure. + * + * \retval MYKONOS_ERR_GPIO_OK Function completed successfully + * \retval MYKONOS_ERR_FLOATFRMT_NULL_STRUCT floating point formatter structure floatFrmt not initialized + * + */ +mykonosGpioErr_t MYKONOS_getFloatPointFrmt (mykonosDevice_t *device, mykonosFloatPntFrmt_t *floatFrmt) +{ + uint8_t regRd1 = 0x00; + + /* Mask parameter values populating mykonosGainComp_t structure */ + const uint8_t ROUND_MASK = 0xE0; + const uint8_t DATA_FRMT_MASK = 0x10; + const uint8_t ENCODE_MASK = 0x08; + const uint8_t EXPBITS_MASK = 0x06; + const uint8_t LEADING_MASK = 0x01; + + /* Shift values for writing gain values */ + const uint8_t ROUND_SHIFT = 0x05; + const uint8_t DATA_FRMT_SHIFT = 0x04; + const uint8_t ENCODE_SHIFT = 0x03; + const uint8_t EXPBITS_SHIFT = 0x01; + +#if MYKONOS_VERBOSE == 1 + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_getFloatPointFrmt()\n"); +#endif + + /* Check floatFrmt for Null */ + if (floatFrmt == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_FLOATFRMT_NULL_STRUCT, + getGpioMykonosErrorMessage(MYKONOS_ERR_FLOATFRMT_NULL_STRUCT)); + return MYKONOS_ERR_FLOATFRMT_NULL_STRUCT; + } + + /* Read gain compensation setup from device */ + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_FLOATING_POINT_CFG, ®Rd1); + + /* Parsing read data to passed by reference parameters */ + floatFrmt->roundMode = (regRd1 & ROUND_MASK) >> ROUND_SHIFT; + floatFrmt->dataFormat = (regRd1 & DATA_FRMT_MASK) >> DATA_FRMT_SHIFT; + floatFrmt->encNan = (regRd1 & ENCODE_MASK) >> ENCODE_SHIFT; + floatFrmt->expBits = (regRd1 & EXPBITS_MASK) >> EXPBITS_SHIFT; + floatFrmt->leading = regRd1 & LEADING_MASK; + + /* Return */ + return MYKONOS_ERR_GPIO_OK; +} + +/** + * \brief Floating point formatter enable/disable Rx1 and Rx2 function. + * + * The floating point formatter block is a function that works in conjunction with the gain + * compensating block, as the gain compensation requires increased dynamic range + * which increases the bit-width in the digital data-path. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * - Gain compensation block has to be enabled in order to user floating point formatter + * + * \param device is a pointer to the device settings structure + * \param rx1Att this parameter sets the integer data attenuation for the Rx1 channel in 6dB steps + * to enable the entire data range to be represented in the selected floating point format. + * \param rx2Att this parameter sets the integer data attenuation for the Rx2 channel in 6dB steps + * to enable the entire data range to be represented in the selected floating point format. + * \param enable this parameter enables or disables the gain compensation block. + * enable = 1 + * disable = 0 + * + * \retval MYKONOS_ERR_GPIO_OK Function completed successfully + * \retval MYKONOS_ERR_FLOATFRMT_SET_INV_RX1ATT not valid rx1 attenuation parameter passed in MYKONOS_setRxEnFloatPntFrmt() + * \retval MYKONOS_ERR_FLOATFRMT_SET_INV_RX2ATT not valid rx2 attenuation parameter passed in MYKONOS_setRxEnFloatPntFrmt() + * \retval MYKONOS_ERR_FLOATFRMT_SET_INV_EN not valid enable parameter passed in MYKONOS_setRxEnFloatPntFrmt() + */ +mykonosGpioErr_t MYKONOS_setRxEnFloatPntFrmt (mykonosDevice_t *device, uint8_t rx1Att, uint8_t rx2Att, uint8_t enable) +{ + uint8_t regWr = 0x00; + + const uint8_t RXATT_RANGE = 0x07; + const uint8_t RX1ATT_SHIFT = 0x01; + const uint8_t RX2ATT_SHIFT = 0x05; + +#if MYKONOS_VERBOSE == 1 + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_setRxEnFloatPntFrmt()\n"); +#endif + + if (enable > 1) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_FLOATFRMT_SET_INV_EN, + getGpioMykonosErrorMessage(MYKONOS_ERR_FLOATFRMT_SET_INV_EN)); + return MYKONOS_ERR_FLOATFRMT_SET_INV_EN; + } + else if (enable == 1) + { + /* Check for rx1Att range */ + if (rx1Att > RXATT_RANGE) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_FLOATFRMT_SET_INV_RX1ATT, + getGpioMykonosErrorMessage(MYKONOS_ERR_FLOATFRMT_SET_INV_RX1ATT)); + return MYKONOS_ERR_FLOATFRMT_SET_INV_RX1ATT; + } + + /* Check for rx2Att range */ + if (rx2Att > RXATT_RANGE) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_FLOATFRMT_SET_INV_RX2ATT, + getGpioMykonosErrorMessage(MYKONOS_ERR_FLOATFRMT_SET_INV_RX2ATT)); + return MYKONOS_ERR_FLOATFRMT_SET_INV_RX2ATT; + } + + /* Enabling floating point formatter for Rx1 and Rx2 */ + regWr = 0x11; + regWr |= (uint8_t)((rx1Att << RX1ATT_SHIFT) | (rx2Att << RX2ATT_SHIFT)); + } + + /* Writing floating point formatter enables for Rx1 and Rx2 */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FLOATING_POINT_RX_CTRL, regWr); + + /* Return */ + return MYKONOS_ERR_GPIO_OK; +} + +/** + * \brief Floating point formatter setup function. + * + * The floating point formatter block is a function that works in conjunction with the gain + * compensating block, as the gain compensation requires increased dynamic range (total gain range on AD9371 is 42dB) + * which increases the bitwidth in the digital datapath. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device is a pointer to the device settings structure + * \param rx1Att this parameter sets the integer data attenuation for the Rx1 channel in 6dB steps + * to enable the entire data range to be represented in the selected floating point format. + * \param rx2Att this parameter sets the integer data attenuation for the Rx2 channel in 6dB steps + * to enable the entire data range to be represented in the selected floating point format. + * \param enable this parameter enables or disables the gain compensation block. + * enable = 1 + * disable = 0 + * + * \retval MYKONOS_ERR_GPIO_OK Function completed successfully + * \retval MYKONOS_ERR_FLOATFRMT_NULL_RX1ATT null pointer passed for rx1 attenuation in MYKONOS_setRxEnFloatPntFrmt() + * \retval MYKONOS_ERR_FLOATFRMT_NULL_RX2ATT null pointer passed for rx2 attenuation in MYKONOS_setRxEnFloatPntFrmt() + * \retval MYKONOS_ERR_FLOATFRMT_NULL_ENABLE null pointer passed for enable in MYKONOS_setRxEnFloatPntFrmt() + */ +mykonosGpioErr_t MYKONOS_getRxEnFloatPntFrmt (mykonosDevice_t *device, uint8_t *rx1Att, uint8_t *rx2Att, uint8_t *enable) +{ + uint8_t regRd = 0x00; + + const uint8_t EN_MASK = 0x11; + const uint8_t RX1ATT_MASK = 0x0E; + const uint8_t RX1ATT_SHIFT = 0x01; + const uint8_t RX2ATT_MASK = 0xE0; + const uint8_t RX2ATT_SHIFT = 0x05; + +#if MYKONOS_VERBOSE == 1 + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_getRxEnFloatPntFrmt()\n"); +#endif + + /* Check for rx1Att NULL parameter */ + if (rx1Att == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_FLOATFRMT_NULL_RX1ATT, + getGpioMykonosErrorMessage(MYKONOS_ERR_FLOATFRMT_NULL_RX1ATT)); + return MYKONOS_ERR_FLOATFRMT_NULL_RX1ATT; + } + + /* Check for rx2Att NULL parameter */ + if (rx2Att == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_FLOATFRMT_NULL_RX2ATT, + getGpioMykonosErrorMessage(MYKONOS_ERR_FLOATFRMT_NULL_RX2ATT)); + return MYKONOS_ERR_FLOATFRMT_NULL_RX2ATT; + } + + /* Check for enable NULL parameter */ + if (enable == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_FLOATFRMT_NULL_ENABLE, + getGpioMykonosErrorMessage(MYKONOS_ERR_FLOATFRMT_NULL_ENABLE)); + return MYKONOS_ERR_FLOATFRMT_NULL_ENABLE; + } + + /* Read Rx1 and Rx2 floating point enables */ + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_FLOATING_POINT_RX_CTRL, ®Rd); + + *rx1Att = (regRd & RX1ATT_MASK) >> RX1ATT_SHIFT; + *rx2Att = (regRd & RX2ATT_MASK) >> RX2ATT_SHIFT ; + *enable = (regRd & EN_MASK) ? 1 : 0; + + /* Return */ + return MYKONOS_ERR_GPIO_OK; +} + + + +/** + * \brief Floating point formatter enable function for ORx channel. + * + * The floating point formatter block is a function that works in conjunction with the gain + * compensating block, as the gain compensation requires increased dynamic range + * which increases the bit-width in the digital data-path. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device is a pointer to the device settings structure + * \param orxAtt this parameter sets the integer data attenuation for the ORx channel in 6dB steps + * to enable the entire data range to be represented in the selected floating point format. + * * \param enable this parameter enables or disables the gain compensation block. + * enable = 1 + * disable = 0 + * + * \retval MYKONOS_ERR_GPIO_OK Function completed successfully + * \retval MYKONOS_ERR_FLOATFRMT_INV_ORXATT not valid Orx attenuation parameter passed in MYKONOS_setOrxEnFloatPntFrmt() + * \retval MYKONOS_ERR_FLOATFRMT_INV_ORXEN not valid enable parameter passed in MYKONOS_setOrxEnFloatPntFrmt() + */ +mykonosGpioErr_t MYKONOS_setOrxEnFloatPntFrmt (mykonosDevice_t *device, uint8_t orxAtt, uint8_t enable) +{ + uint8_t regWr = 0x00; + + const uint8_t ORXATT_RANGE = 0x07; + const uint8_t ORXATT_SHIFT = 0x01; + +#if MYKONOS_VERBOSE == 1 + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_setOrxEnFloatPntFrmt()\n"); +#endif + + /* Check for enable */ + if (enable > 1) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_FLOATFRMT_INV_ORXEN, + getGpioMykonosErrorMessage(MYKONOS_ERR_FLOATFRMT_INV_ORXEN)); + return MYKONOS_ERR_FLOATFRMT_INV_ORXEN; + } + else if (enable == 1) + { + /* Check for rx1Att range */ + if (orxAtt > ORXATT_RANGE) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_FLOATFRMT_INV_ORXATT, + getGpioMykonosErrorMessage(MYKONOS_ERR_FLOATFRMT_INV_ORXATT)); + return MYKONOS_ERR_FLOATFRMT_INV_ORXATT; + } + + /* Enabling floating point formatter for Rx1 and Rx2 */ + regWr = 0x01; + regWr |= (uint8_t)(orxAtt << ORXATT_SHIFT); + } + + /* Writing floating point formatter enable for ORX channel */ + CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FLOATING_POINT_ORX_CTRL, regWr); + + /* Return */ + return MYKONOS_ERR_GPIO_OK; +} + + +/** + * \brief Floating point formatter enable and setup function. + * + * The floating point formatter block is a function that works in conjunction with the gain + * compensating block, as the gain compensation requires increased dynamic range (total gain range on AD9371 is 42dB) + * which increases the bitwidth in the digital datapath. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device is a pointer to the device settings structure + * \param orxAtt this parameter sets the integer data attenuation for the ORx channel in 6dB steps + * to enable the entire data range to be represented in the selected floating point format. + * \param enable this parameter enables or disables the gain compensation block. + * enable = 1 + * disable = 0 + * + * \retval MYKONOS_ERR_GPIO_OK Function completed successfully + * \retval MYKONOS_ERR_FLOATFRMT_NULL_ORXATT null pointer passed for orxAtt + * \retval MYKONOS_ERR_FLOATFRMT_NULL_ORXENABLE null pointer passed for enable + */ +mykonosGpioErr_t MYKONOS_getOrxEnFloatPntFrmt (mykonosDevice_t *device, uint8_t *orxAtt, uint8_t *enable) +{ + uint8_t regRd = 0x00; + + const uint8_t EN_MASK = 0x01; + const uint8_t ORXATT_MASK = 0x0E; + const uint8_t ORXATT_SHIFT = 0x01; + +#if MYKONOS_VERBOSE == 1 + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_getOrxEnFloatPntFrmt()\n"); +#endif + + /* Check for orxAtt NULL parameter */ + if (orxAtt == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_FLOATFRMT_NULL_ORXATT, + getGpioMykonosErrorMessage(MYKONOS_ERR_FLOATFRMT_NULL_ORXATT)); + return MYKONOS_ERR_FLOATFRMT_NULL_ORXATT; + } + + /* Check for enable NULL parameter */ + if (enable == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_FLOATFRMT_NULL_ORXENABLE, + getGpioMykonosErrorMessage(MYKONOS_ERR_FLOATFRMT_NULL_ORXENABLE)); + return MYKONOS_ERR_FLOATFRMT_NULL_ORXENABLE; + } + + /* Read Rx1 and Rx2 floating point enables */ + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_FLOATING_POINT_ORX_CTRL, ®Rd); + + *orxAtt = (regRd & ORXATT_MASK) >> ORXATT_SHIFT; + *enable = (regRd & EN_MASK) ? 1 : 0; + + /* Return */ + return MYKONOS_ERR_GPIO_OK; +} + + +/** + * \brief Sets up the Temperature Sensor + * + * Before using this function to set up the temp sensor, + * make sure that you call the MYKONOS_setupAuxADC() function + * to ensure that the AuxADC clock is setup and running correctly at 40 MHz, + * and that the structure mykonosTempSensorConfig_t tempSensor is populated. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device is a pointer to the device settings structure + * \param tempSensor is a pointer to the mykonosTempSensorConfig_t which holds + * the configuration settings for the temperature sensor + * + * \retval MYKONOS_ERR_SETUPTEMPSENSOR_NULL_PARAM Function parameter tempSensor is a NULL pointer + * \retval MYKONOS_ERR_SETUPTEMPSENSOR_INV_TEMPDECIMATION tempDecimation value out of range (0-7) + * \retval MYKONOS_ERR_SETUPTEMPSENSOR_INV_OFFSET offset value out of range (0-255) + * \retval MYKONOS_ERR_SETUPTEMPSENSOR_INV_TEMPWINDOW tempWindow out of range (0-15) + * \retval MYKONOS_ERR_GPIO_OK Function completed successfully + */ +mykonosGpioErr_t MYKONOS_setupTempSensor(mykonosDevice_t *device, mykonosTempSensorConfig_t *tempSensor) +{ + uint8_t offsetFromDevice = 0; + + const uint8_t OFFSET_API = 0x43; +/* const uint8_t TEMP_OFFSET_MASK = 0xFF;*/ + const uint8_t TEMP_WINDOW_MASK = 0xF0; + const uint8_t TEMP_WINDOW_CHECK = 0x0F; + const uint8_t TEMP_DEC_MASK = 0x07; + const uint8_t OFFSET_OVERRIDE_MASK = 0x10; + +#ifdef MYKONOS_VERBOSE + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_setupTempSensor()\n"); +#endif + + /* Check for structure initialisation mykonosTempSensorConfig_t */ + if (tempSensor == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETUPTEMPSENSOR_NULL_PARAM, + getGpioMykonosErrorMessage(MYKONOS_ERR_SETUPTEMPSENSOR_NULL_PARAM)); + return MYKONOS_ERR_SETUPTEMPSENSOR_NULL_PARAM; + } + + /* Check Temperature sensor decimation range */ + if ((tempSensor->tempDecimation & ~TEMP_DEC_MASK) > 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETUPTEMPSENSOR_INV_TEMPDECIMATION, + getGpioMykonosErrorMessage(MYKONOS_ERR_SETUPTEMPSENSOR_INV_TEMPDECIMATION)); + return MYKONOS_ERR_SETUPTEMPSENSOR_INV_TEMPDECIMATION; + } + + /* Override fused offset */ + if (tempSensor->overrideFusedOffset > 0) + { + /* Check Temperature sensor offset range */ +/* if (tempSensor->offset & ~TEMP_OFFSET_MASK) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETUPTEMPSENSOR_INV_OFFSET, + getGpioMykonosErrorMessage(MYKONOS_ERR_SETUPTEMPSENSOR_INV_OFFSET)); + return MYKONOS_ERR_SETUPTEMPSENSOR_INV_OFFSET; + }*/ + + CMB_SPIWriteField (device->spiSettings, MYKONOS_ADDR_TEMP_SENSOR_CONFIG, 1, OFFSET_OVERRIDE_MASK, 4); + CMB_SPIWriteByte (device->spiSettings, MYKONOS_ADDR_TEMP_SENSOR_OFFSET, tempSensor->offset); + } + else + { + /* If manual override was not requested, read back device offset value. + * If factory fused it is non-zero; else API adds a typical offset value */ + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_TEMP_SENSOR_OFFSET, &(offsetFromDevice)); + if (offsetFromDevice == 0) + { + CMB_SPIWriteByte (device->spiSettings, MYKONOS_ADDR_TEMP_SENSOR_OFFSET, OFFSET_API); + } + } + + /* Check Temperature sensor window range */ + if ((tempSensor->tempWindow & ~TEMP_WINDOW_CHECK) > 0) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETUPTEMPSENSOR_INV_TEMPWINDOW, + getGpioMykonosErrorMessage(MYKONOS_ERR_SETUPTEMPSENSOR_INV_TEMPWINDOW)); + return MYKONOS_ERR_SETUPTEMPSENSOR_INV_TEMPWINDOW; + } + else + { + CMB_SPIWriteField (device->spiSettings, MYKONOS_ADDR_TEMP_SENSOR_CONTROL_LSB, tempSensor->tempWindow, TEMP_WINDOW_MASK, 4); + } + + /* Single shot setup */ + CMB_SPIWriteByte (device->spiSettings, MYKONOS_ADDR_TEMP_SENSOR_CONTROL_MSB, 0x00); + + /* Write decimation factor for the Temperature sensor */ + CMB_SPIWriteField (device->spiSettings, MYKONOS_ADDR_TEMP_SENSOR_CONFIG, tempSensor->tempDecimation, TEMP_DEC_MASK, 0); + + return MYKONOS_ERR_GPIO_OK; +} + +/** + * \brief Reads from the Temperature Sensor registers and populates device data structure + * + * After this function is executed, the tempSensor parameter holds updated values + * from the device registers. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device is a pointer to the device settings structure + * \param tempSensor is a pointer to the mykonosTempSensorConfig_t which holds + * the configuration settings for the tempSensor + * + * \retval MYKONOS_ERR_GPIO_OK Function completed successfully + * \retval MYKONOS_ERR_GETTEMPSENSORCONFIG_NULL_PARAM Function parameter tempSensor is a NULL pointer + */ +mykonosGpioErr_t MYKONOS_getTempSensorConfig(mykonosDevice_t *device, mykonosTempSensorConfig_t *tempSensor) +{ + uint8_t tempConfig = 0; + + const uint8_t TEMP_WINDOW_MASK = 0xF0; + const uint8_t TEMP_FUSE_MASK = 0x10; + const uint8_t TEMP_DECIMATION_MASK = 0x07; + const uint8_t TEMP_FUSE_SHIFT = 0x04; + +#ifdef MYKONOS_VERBOSE + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_getTempSensorConfig()\n"); +#endif + + /* Check tempSensor null parameter passed */ + if (tempSensor == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETTEMPSENSORCFG_NULL_PARAM, + getGpioMykonosErrorMessage(MYKONOS_ERR_GETTEMPSENSORCFG_NULL_PARAM)); + return MYKONOS_ERR_GETTEMPSENSORCFG_NULL_PARAM; + } + + /* Read back factory offset, if fused; else manual offset value */ + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_TEMP_SENSOR_OFFSET, &(tempSensor->offset)); + + /* Read back Decimation and override Offset Temperature sensor parameters */ + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_TEMP_SENSOR_CONFIG, &tempConfig); + tempSensor->overrideFusedOffset = (tempConfig & TEMP_FUSE_MASK) >> TEMP_FUSE_SHIFT; + tempSensor->tempDecimation = (tempConfig & TEMP_DECIMATION_MASK); + + /* Read back tempWindow */ + CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_TEMP_SENSOR_CONTROL_LSB, &tempConfig, TEMP_WINDOW_MASK, 4); + tempSensor->tempWindow = tempConfig; + + return MYKONOS_ERR_GPIO_OK; +} + +/** + * \brief Initiates temperature measurement + * + * This function will initiate the Temperature sensor measurement. + * + * \pre + * MYKONOS_setupTempSensor() function to set the temperature sensor. + * MYKONOS_setAuxAdcChannel() function with the AuxADC setting for Temperature sensor channel MYK_TEMPSENSOR + * from the enum type mykonosAuxAdcChannels_t. + * + * \post + * Internal temperature sensor will perform measurement and updated register values, + * read back using MYKONOS_readTempSensor() function. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device is a pointer to the device settings structure + * + * \retval MYKONOS_ERR_GPIO_OK Function completed successfully + */ +mykonosGpioErr_t MYKONOS_startTempMeasurement(mykonosDevice_t *device) +{ + const uint8_t TEMP_LOCK_MASK = 0x80; + const uint8_t TEMP_LOCK_BIT = 0x01; + const uint8_t MEASUREMENT_MASK = 0x01; + +#ifdef MYKONOS_VERBOSE + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_startTempMeasurement()\n"); +#endif + + /* Write the lock bit to ensure that a valid measurement is achieved */ + CMB_SPIWriteField (device->spiSettings, MYKONOS_ADDR_TEMP_SENSOR_CONFIG, TEMP_LOCK_BIT, TEMP_LOCK_MASK, 7); + + /* Initiate Temperature measurement */ + CMB_SPIWriteField (device->spiSettings, MYKONOS_ADDR_TEMP_SENSOR_CONTROL_LSB, 1, MEASUREMENT_MASK, 0); + CMB_SPIWriteField (device->spiSettings, MYKONOS_ADDR_TEMP_SENSOR_CONTROL_LSB, 0, MEASUREMENT_MASK, 0); + + return MYKONOS_ERR_GPIO_OK; +} + +/** + * \brief Reads temperature code and statuses from the Temperature Sensor registers + * + * This function reads the temperature sensor's statuses and temperature code. + * Allow at least one computation period to elapse. + * The temperature sensor computation period is as 6 times the AuxADC conversion time. + * AuxADC conversion time = (1/40Mhz) * (256 * 2^(tempDecimation)) + * + * Before using this function to read back the temperature, make sure that temperature sensor + * is setup using the MYKONOS_setupTempSensor() function. + * + * \pre Before using this function to read back the sensor value: + * MYKONOS_setupTempSensor() function is needed in order to set up the Temperature sensor. + * MYKONOS_setAuxAdcChannel() function has to be called in order to set the proper AuxADC + * channel. AuxADC channel MYK_TEMPSENSOR is used for the Temperature sensor. + * MYKONOS_startTempMeasurement() this function will start the Temperature sensor, this + * function is needed to be called for every reading that needs to be performed. + * + * \post "tempStatus" structure will contain the status information and the temperature + * code. + * If a valid measurement is achieved then tempStatus->tempValid will be set and + * tempStatus->tempCode will contain the actual reading. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device is a pointer to the device settings structure + * \param tempStatus is a pointer to the mykonosTempSensorStatus_t structure which will be updated + * with the temp sensor readings + * + * \retval MYKONOS_ERR_GPIO_OK Function completed successfully + * \retval MYKONOS_ERR_READTEMPSENSOR_NULL_PARAM Function parameter tempSensor is a NULL pointer + * \retval MYKONOS_ERR_READTEMPSENSOR_NOT_LOCKED temperature sensor reading is not locked + */ +mykonosGpioErr_t MYKONOS_readTempSensor(mykonosDevice_t *device, mykonosTempSensorStatus_t *tempStatus) +{ + int16_t temperature = 0; + uint8_t statusWord = 0; + uint8_t rgRd = 0x00; + + const uint8_t CODE_TO_DEGREE_CELSIUS = 0x67; + const uint8_t TEMP_VALID_MASK = 0x02; + const uint8_t WINDOW_EXCEED_MASK = 0x08; + const uint8_t WINDOW_HI_LO_MASK = 0x04; + const uint8_t TEMP_LOCK = 0x80; + +#ifdef MYKONOS_VERBOSE + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_readTempSensor()\n"); +#endif + + if (tempStatus == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_READTEMPSENSOR_NULL_PARAM, + getGpioMykonosErrorMessage(MYKONOS_ERR_READTEMPSENSOR_NULL_PARAM)); + return MYKONOS_ERR_READTEMPSENSOR_NULL_PARAM; + } + + /* Check for temperature sensor value lock */ + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_TEMP_SENSOR_CONFIG, &rgRd); + if ((rgRd & TEMP_LOCK) == TEMP_LOCK) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_READTEMPSENSOR_NOT_LOCKED, + getGpioMykonosErrorMessage(MYKONOS_ERR_READTEMPSENSOR_NOT_LOCKED)); + return MYKONOS_ERR_READTEMPSENSOR_NOT_LOCKED; + } + + /* Perform temperature status reading */ + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_TEMP_SENSOR_CONTROL_LSB, &statusWord); + tempStatus->windowExceeded = (statusWord & WINDOW_EXCEED_MASK) >> 3; + tempStatus->windowHiLo = (statusWord & WINDOW_HI_LO_MASK) >> 2; + tempStatus->tempValid = (0x01 & ~((statusWord & TEMP_VALID_MASK) >> 1)); + + /* Perform temperature reading */ + CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_TEMP_SENSOR_READ, &rgRd); + temperature = rgRd - CODE_TO_DEGREE_CELSIUS; + tempStatus->tempCode = temperature; + + return MYKONOS_ERR_GPIO_OK; +} + +/** + * \brief This function sets the drive strength for the required GPIOs. + * + * This function will set the required drive strength, the settings for GPIO drive strength are normal drive and double drive. + * + * GPIO pins that can be assigned independent drive strength are: + * -MYKGPIO0 to MYKGPIO7 and MYKGPIO18 + * + * The rest of GPIOs are paired as: + * -MYKGPIO17 and MYKGPIO16 + * -MYKGPIO8 and MYKGPIO15 + * -MYKGPIO14 and MYKGPIO13 + * -MYKGPIO10 and MYKGPIO9 + * -MYKGPIO12 and MYKGPIO11 + * + * This means that if it is required to double the drive strength for MYKGPIO17 then the drive strength will also be doubled for MYKGPIO16. + * + * If the particular bitfield for gpioDrv is set then the drive strength will be doubled. Note that multiple GPIOs can be set at a time. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device is a pointer to the device settings structure + * \param gpioDrv GPIO drive strength setup, valid range is from 0x00000 to 0x7FFFF. + * + * \retval MYKONOS_ERR_GPIO_DRV_INV_PARAM GPIO out of range- valid GPIOs are in the range 0x00000 to 0x7FFFF. + * \retval MYKONOS_ERR_GPIO_OK Function completed successfully + */ +mykonosGpioErr_t MYKONOS_setGpioDrv(mykonosDevice_t *device, uint32_t gpioDrv) +{ + mykonosGpioErr_t error = MYKONOS_ERR_GPIO_OK; + uint8_t reg0 = 0x00; + uint8_t reg1 = 0x00; + + const uint32_t GPIO_MASK = 0x7FFFF; + +#if MYKONOS_VERBOSE == 1 + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_setGpioDrv()\n"); +#endif + + /* Error checking for correct number of GPIOs. */ + if (gpioDrv > GPIO_MASK ) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_DRV_INV_PARAM, + getGpioMykonosErrorMessage(MYKONOS_ERR_GPIO_DRV_INV_PARAM)); + return MYKONOS_ERR_GPIO_DRV_INV_PARAM; + } + + CMB_SPIReadByte(device->spiSettings, MYKONOS_GPIO_DRV_CTL_0, ®0); + CMB_SPIReadByte(device->spiSettings, MYKONOS_GPIO_DRV_CTL_1, ®1); + + reg1 = reg1 & 0xC0; + + if (gpioDrv & 0xFF) + { + reg0 = (uint8_t)(gpioDrv & 0xFF); + } + else + { + reg0 = 0x00; + } + + if (gpioDrv & (uint32_t)MYKGPIO18) + { + reg1 |= 0x01; + } + + if ((gpioDrv & (uint32_t)MYKGPIO17) || (gpioDrv & (uint32_t)MYKGPIO16)) + { + reg1 |= 0x02; + } + + if ((gpioDrv & (uint32_t)MYKGPIO15) || (gpioDrv & (uint32_t)MYKGPIO8)) + { + reg1 |= 0x04; + } + + if ((gpioDrv & (uint32_t)MYKGPIO14) || (gpioDrv & (uint32_t)MYKGPIO13)) + { + reg1 |= 0x08; + } + + if ((gpioDrv & (uint32_t)MYKGPIO10) || (gpioDrv & (uint32_t)MYKGPIO9)) + { + reg1 |= 0x10; + } + + if ((gpioDrv & (uint32_t)MYKGPIO12) || (gpioDrv & (uint32_t)MYKGPIO11)) + { + reg1 |= 0x20; + } + + CMB_SPIWriteByte (device->spiSettings, MYKONOS_GPIO_DRV_CTL_0, reg0); + CMB_SPIWriteByte (device->spiSettings, MYKONOS_GPIO_DRV_CTL_1, reg1); + + return error; +} + + +/** + * \brief This function gets the GPIOs drive strength. + * + * This function will get the programmed drive strength for all the GPIOs + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device is a pointer to the device settings structure. + * \param gpioDrv will contain the current GPIOs drive strength setting. + * + * \retval MYKONOS_ERR_GETGPIODRV_NULL_PARAM null parameter passed to the function. + * \retval MYKONOS_ERR_GPIO_OK Function completed successfully + */ +mykonosGpioErr_t MYKONOS_getGpioDrv(mykonosDevice_t *device, uint32_t *gpioDrv) +{ + mykonosGpioErr_t error = MYKONOS_ERR_GPIO_OK; + uint8_t reg0 = 0x00; + uint8_t reg1 = 0x00; + uint32_t gpioDrvRd = 0x00; + +#if MYKONOS_VERBOSE == 1 + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_getGpioDrv()\n"); +#endif + + /* Error checking for correct number of GPIOs. */ + if (gpioDrv == NULL ) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETGPIODRV_NULL_PARAM, + getGpioMykonosErrorMessage(MYKONOS_ERR_GETGPIODRV_NULL_PARAM)); + return MYKONOS_ERR_GETGPIODRV_NULL_PARAM; + } + + CMB_SPIReadByte(device->spiSettings, MYKONOS_GPIO_DRV_CTL_0, ®0); + CMB_SPIReadByte(device->spiSettings, MYKONOS_GPIO_DRV_CTL_1, ®1); + + gpioDrvRd = (uint32_t)reg0 & 0xFF; + + if (reg1 & 0x01) + { + gpioDrvRd |= (uint32_t)MYKGPIO18; + } + + if (reg1 & 0x02) + { + gpioDrvRd |= (uint32_t)MYKGPIO17 | (uint32_t)MYKGPIO16; + } + + if (reg1 & 0x04) + { + gpioDrvRd |= (uint32_t)MYKGPIO8 | (uint32_t)MYKGPIO15; + } + + if (reg1 & 0x08) + { + gpioDrvRd |= (uint32_t)MYKGPIO14 | (uint32_t)MYKGPIO13; + } + + if (reg1 & 0x10) + { + gpioDrvRd |= (uint32_t)MYKGPIO10 | (uint32_t)MYKGPIO9; + } + + if (reg1 & 0x20) + { + gpioDrvRd |= (uint32_t)MYKGPIO12 | (uint32_t)MYKGPIO11; + } + + *gpioDrv = (mykonosGpioSelect_t)gpioDrvRd; + + return error; +} + +/** + * \brief This function sets the slew rate for the required GPIOs. + * + * This function will set the required slew rate, the settings for GPIO slew rate are given by the enumeration type mykonosGpioSlewRate_t. + * + * GPIO pins that can be assigned independent slew rate are: + * -MYKGPIO0 to MYKGPIO7 and MYKGPIO18 + * + * The rest of GPIOs are paired as: + * -MYKGPIO17 and MYKGPIO16 + * -MYKGPIO8 and MYKGPIO15 + * -MYKGPIO14 and MYKGPIO13 + * -MYKGPIO10 and MYKGPIO9 + * -MYKGPIO12 and MYKGPIO11 + * + * This means that if it is required to set the slew rate for MYKGPIO17 then the same slew rate will be applied for MYKGPIO16. + * + * If the particular bitfield for gpioSelect is set then slewRate will be set for that GPIO. Note that multiple GPIOs can be set at a time. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device is a pointer to the device settings structure + * \param gpioSelect GPIO for which the slew rate will be changed, valid range 0x00000 to 0x7FFFF. + * \param slewRate slew rate setting, valid slew rate settings are given by the enumeration type mykonosGpioSlewRate_t + * + * \retval MYKONOS_ERR_GPIO_SLEW_RATE_INV_PARAM GPIO out of range- valid GPIOs are in the range 0x00000 to 0x7FFFF. + * \retval MYKONOS_ERR_GPIO_OK Function completed successfully + */ +mykonosGpioErr_t MYKONOS_setGpioSlewRate(mykonosDevice_t *device, mykonosGpioSelect_t gpioSelect, mykonosGpioSlewRate_t slewRate) +{ + mykonosGpioErr_t error = MYKONOS_ERR_GPIO_OK; + uint8_t reg0 = 0x00; + uint8_t reg1 = 0x00; + uint8_t reg2 = 0x00; + uint8_t reg3 = 0x00; + + const uint32_t GPIO_MASK = 0x7FFFF; + const uint8_t SLEWRATE_MASK = 0x03; + const uint32_t SHIFT4NIBLE = 0x06; + const uint32_t SHIFT3NIBLE = 0x04; + const uint32_t SHIFT2NIBLE = 0x02; + +#if MYKONOS_VERBOSE == 1 + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_setGpioSlewRate()\n"); +#endif + + /* Error checking for correct number of GPIOs. */ + if (((uint32_t)gpioSelect > GPIO_MASK) || ((uint8_t)slewRate > SLEWRATE_MASK)) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_SLEW_RATE_INV_PARAM, + getGpioMykonosErrorMessage(MYKONOS_ERR_GPIO_SLEW_RATE_INV_PARAM)); + return MYKONOS_ERR_GPIO_SLEW_RATE_INV_PARAM; + } + + CMB_SPIReadByte(device->spiSettings, MYKONOS_GPIO_SLEW_CTL_0, ®0); + CMB_SPIReadByte(device->spiSettings, MYKONOS_GPIO_SLEW_CTL_1, ®1); + CMB_SPIReadByte(device->spiSettings, MYKONOS_GPIO_SLEW_CTL_2, ®2); + CMB_SPIReadByte(device->spiSettings, MYKONOS_GPIO_SLEW_CTL_3, ®3); + + if ((uint32_t)gpioSelect & (uint32_t)MYKGPIO18) + { + reg0 = (reg0 & ~(SLEWRATE_MASK << SHIFT4NIBLE)) | ((uint8_t)slewRate << SHIFT4NIBLE); + } + if (((uint32_t)gpioSelect & (uint32_t)MYKGPIO17) || ((uint32_t)gpioSelect & (uint32_t)MYKGPIO16)) + { + reg0 = (reg0 & ~(SLEWRATE_MASK << SHIFT3NIBLE)) | ((uint8_t)slewRate << SHIFT3NIBLE); + } + if (((uint32_t)gpioSelect & (uint32_t)MYKGPIO15) || ((uint32_t)gpioSelect & (uint32_t)MYKGPIO8)) + { + reg0 = (reg0 & ~(SLEWRATE_MASK << SHIFT2NIBLE)) | ((uint8_t)slewRate << SHIFT2NIBLE); + } + if (((uint32_t)gpioSelect & (uint32_t)MYKGPIO14) || ((uint32_t)gpioSelect & (uint32_t)MYKGPIO13)) + { + reg0 = (reg0 & ~(SLEWRATE_MASK)) | (uint8_t)slewRate; + } + if (((uint32_t)gpioSelect & (uint32_t)MYKGPIO11) || ((uint32_t)gpioSelect & (uint32_t)MYKGPIO12)) + { + reg1 = (reg1 & ~(SLEWRATE_MASK << SHIFT4NIBLE)) | ((uint8_t)slewRate << SHIFT4NIBLE); + } + if (((uint32_t)gpioSelect & (uint32_t)MYKGPIO9) || ((uint32_t)gpioSelect & (uint32_t)MYKGPIO10)) + { + reg1 = (reg1 & ~(SLEWRATE_MASK << SHIFT3NIBLE)) | ((uint8_t)slewRate << SHIFT3NIBLE); + } + if ((uint32_t)gpioSelect & (uint32_t)MYKGPIO7) + { + reg1 = (reg1 & ~(SLEWRATE_MASK << SHIFT2NIBLE)) | ((uint8_t)slewRate << SHIFT2NIBLE); + } + if ((uint32_t)gpioSelect & (uint32_t)MYKGPIO6) + { + reg1 = (reg1 & ~(SLEWRATE_MASK)) | (uint8_t)slewRate; + } + if ((uint32_t)gpioSelect & (uint32_t)MYKGPIO5) + { + reg2 = (reg2 & ~(SLEWRATE_MASK << SHIFT4NIBLE)) | ((uint8_t)slewRate << SHIFT4NIBLE); + } + if ((uint32_t)gpioSelect & (uint32_t)MYKGPIO4) + { + reg2 = (reg2 & ~(SLEWRATE_MASK << SHIFT3NIBLE)) | ((uint8_t)slewRate << SHIFT3NIBLE); + } + if ((uint32_t)gpioSelect & (uint32_t)MYKGPIO3) + { + reg2 = (reg2 & ~(SLEWRATE_MASK << SHIFT2NIBLE)) | ((uint8_t)slewRate << SHIFT2NIBLE); + } + if ((uint32_t)gpioSelect & (uint32_t)MYKGPIO2) + { + reg2 = (reg2 & ~(SLEWRATE_MASK)) | (uint8_t)slewRate; + } + if ((uint32_t)gpioSelect & (uint32_t)MYKGPIO1) + { + reg3 = (reg3 & ~(SLEWRATE_MASK << SHIFT2NIBLE)) | ((uint8_t)slewRate << SHIFT2NIBLE); + } + if ((uint32_t)gpioSelect & (uint32_t)MYKGPIO0) + { + reg3 = (reg3 & ~(SLEWRATE_MASK)) | (uint8_t)slewRate; + } + + /* Prepare registers */ + CMB_SPIWriteByte (device->spiSettings, MYKONOS_GPIO_SLEW_CTL_0, reg0); + CMB_SPIWriteByte (device->spiSettings, MYKONOS_GPIO_SLEW_CTL_1, reg1); + CMB_SPIWriteByte (device->spiSettings, MYKONOS_GPIO_SLEW_CTL_2, reg2); + CMB_SPIWriteByte (device->spiSettings, MYKONOS_GPIO_SLEW_CTL_3, reg3); + + return error; +} + + +/** + * \brief This function gets the GPIO slew rate setting. + * + * This function will get the programmed slew rate for the GPIO given by slewRateGpio. + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device is a pointer to the device settings structure. + * \param gpioSelect GPIO selection for getting the slew rate setting. + * \param slewRate will contain the GPIO slew rate setting. + * + * \retval MYKONOS_ERR_GPIO_GETSLEW_NULL_PARAM null parameter passed to the function. + * \retval MYKONOS_ERR_GPIO_SLEW_RATE_INV_PARAM GPIO out of range- valid GPIOs are in the range 0x00000 to 0x7FFFF. + * \retval MYKONOS_ERR_GPIO_OK Function completed successfully + */ +mykonosGpioErr_t MYKONOS_getGpioSlewRate(mykonosDevice_t *device, mykonosGpioSelect_t gpioSelect, mykonosGpioSlewRate_t *slewRate) +{ + uint8_t reg0 = 0x00; + uint8_t reg1 = 0x00; + uint8_t reg2 = 0x00; + uint8_t reg3 = 0x00; + mykonosGpioSlewRate_t slewSetting = MYK_SLEWRATE_NONE; + + const uint32_t SLEWRATE_MASK = 0x03; + const uint32_t SHIFT4NIBLE = 0x06; + const uint32_t SHIFT3NIBLE = 0x04; + const uint32_t SHIFT2NIBLE = 0x02; + +#if MYKONOS_VERBOSE == 1 + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_getGpioSlewRate()\n"); +#endif + + /* Error checking for NULL parameter. */ + if (slewRate == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_GETSLEW_NULL_PARAM, + getGpioMykonosErrorMessage(MYKONOS_ERR_GPIO_GETSLEW_NULL_PARAM)); + return MYKONOS_ERR_GPIO_GETSLEW_NULL_PARAM; + } + + CMB_SPIReadByte(device->spiSettings, MYKONOS_GPIO_SLEW_CTL_0, ®0); + CMB_SPIReadByte(device->spiSettings, MYKONOS_GPIO_SLEW_CTL_1, ®1); + CMB_SPIReadByte(device->spiSettings, MYKONOS_GPIO_SLEW_CTL_2, ®2); + CMB_SPIReadByte(device->spiSettings, MYKONOS_GPIO_SLEW_CTL_3, ®3); + + switch (gpioSelect) + { + case MYKGPIO18: + slewSetting = (mykonosGpioSlewRate_t)((reg0 & (SLEWRATE_MASK << SHIFT4NIBLE)) >> SHIFT4NIBLE); + break; + case MYKGPIO17: + case MYKGPIO16: + slewSetting = (mykonosGpioSlewRate_t)((reg0 & (SLEWRATE_MASK << SHIFT3NIBLE)) >> SHIFT3NIBLE); + break; + case MYKGPIO15: + case MYKGPIO8: + slewSetting = (mykonosGpioSlewRate_t)((reg0 & (SLEWRATE_MASK << SHIFT2NIBLE)) >> SHIFT2NIBLE); + break; + case MYKGPIO14: + case MYKGPIO13: + slewSetting = (mykonosGpioSlewRate_t)(reg0 & (SLEWRATE_MASK)); + break; + case MYKGPIO11: + case MYKGPIO12: + slewSetting = (mykonosGpioSlewRate_t)((reg1 & (SLEWRATE_MASK << SHIFT4NIBLE)) >> SHIFT4NIBLE); + break; + case MYKGPIO9: + case MYKGPIO10: + slewSetting = (mykonosGpioSlewRate_t)((reg1 & (SLEWRATE_MASK << SHIFT3NIBLE)) >> SHIFT3NIBLE); + break; + case MYKGPIO7: + slewSetting = (mykonosGpioSlewRate_t)((reg1 & (SLEWRATE_MASK << SHIFT2NIBLE)) >> SHIFT2NIBLE); + break; + case MYKGPIO6: + slewSetting = (mykonosGpioSlewRate_t)(reg1 & (SLEWRATE_MASK)); + break; + case MYKGPIO5: + slewSetting = (mykonosGpioSlewRate_t)((reg2 & (SLEWRATE_MASK << SHIFT4NIBLE)) >> SHIFT4NIBLE); + break; + case MYKGPIO4: + slewSetting = (mykonosGpioSlewRate_t)((reg2 & (SLEWRATE_MASK << SHIFT3NIBLE)) >> SHIFT3NIBLE); + break; + case MYKGPIO3: + slewSetting = (mykonosGpioSlewRate_t)((reg2 & (SLEWRATE_MASK << SHIFT2NIBLE)) >> SHIFT2NIBLE); + break; + case MYKGPIO2: + slewSetting = (mykonosGpioSlewRate_t)(reg2 & (SLEWRATE_MASK)); + break; + case MYKGPIO1: + slewSetting = (mykonosGpioSlewRate_t)((reg3 & (SLEWRATE_MASK << SHIFT2NIBLE)) >> SHIFT2NIBLE); + break; + case MYKGPIO0: + slewSetting = (mykonosGpioSlewRate_t)(reg3 & (SLEWRATE_MASK)); + break; + default: + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_SLEW_RATE_INV_PARAM, + getGpioMykonosErrorMessage(MYKONOS_ERR_GPIO_SLEW_RATE_INV_PARAM)); + return MYKONOS_ERR_GPIO_SLEW_RATE_INV_PARAM; + } + + *slewRate = slewSetting; + + return MYKONOS_ERR_GPIO_OK; +} + + +/** + * \brief This function sets the CMOS output driver. + * + * This function sets the CMOS output driver to increase pad drive strength for the SPI_DIO and GP_INTERRUPT pads + * according to the following settings of the enumeration type mykonosCmosPadDrvStr_t + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device is a pointer to the device settings structure + * \param cmosDrv drive for the CMOS output driver + * + * \retval MYKONOS_ERR_CMOS_DRV_INV_PARAM invalid drive strength, valid settings are given by mykonosCmosPadDrvStr_t + * \retval MYKONOS_ERR_GPIO_OK Function completed successfully + */ +mykonosGpioErr_t MYKONOS_setCmosDrv(mykonosDevice_t *device, mykonosCmosPadDrvStr_t cmosDrv) +{ + const uint8_t CMOS_DRV_MASK = 0x0F; + const uint8_t CMOS_DRV_SHIFT = 0x04; + +#if MYKONOS_VERBOSE == 1 + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_setCmosDrv()\n"); +#endif + + /* Error checking for correct drive */ + switch (cmosDrv) + { /* fall through since this is only checking */ + case MYK_CMOSPAD_DRV_1X: + case MYK_CMOSPAD_DRV_2X: + case MYK_CMOSPAD_DRV_3X: + case MYK_CMOSPAD_DRV_4X: + case MYK_CMOSPAD_DRV_5X: + break; + default: + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CMOS_DRV_INV_PARAM, + getGpioMykonosErrorMessage(MYKONOS_ERR_CMOS_DRV_INV_PARAM)); + return MYKONOS_ERR_CMOS_DRV_INV_PARAM; + } + + CMB_SPIWriteField(device->spiSettings, MYKONOS_GPIO_SLEW_CTL_3, cmosDrv, (~CMOS_DRV_MASK), CMOS_DRV_SHIFT); + + return MYKONOS_ERR_GPIO_OK; +} + +/** + * \brief This function gets the programmed CMOS output driver + * + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device is a pointer to the device settings structure + * \param cmosDrv will be the programmed drive for the CMOS output driver + * + * \retval MYKONOS_ERR_CMOS_DRV_NULL_PARAM Null parameter passed to the function + * \retval MYKONOS_ERR_GPIO_OK Function completed successfully + */ +mykonosGpioErr_t MYKONOS_getCmosDrv(mykonosDevice_t *device, mykonosCmosPadDrvStr_t *cmosDrv) +{ + uint8_t regRd = 0x00; + + const uint8_t CMOS_DRV_MASK = 0xF0; + const uint8_t CMOS_DRV_SHIFT = 0x04; + +#if MYKONOS_VERBOSE == 1 + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_getCmosDrv()\n"); +#endif + + if (cmosDrv == NULL) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CMOS_DRV_NULL_PARAM, + getGpioMykonosErrorMessage(MYKONOS_ERR_CMOS_DRV_NULL_PARAM)); + return MYKONOS_ERR_CMOS_DRV_NULL_PARAM; + } + + CMB_SPIReadByte(device->spiSettings, MYKONOS_GPIO_SLEW_CTL_3, ®Rd); + + *cmosDrv = (mykonosCmosPadDrvStr_t)((regRd & CMOS_DRV_MASK) >> CMOS_DRV_SHIFT); + + return MYKONOS_ERR_GPIO_OK; +} + +/** +* \brief This API function configures and enables the secondary SPI port. +* +* This port allows control compatibility with BBPs that employ dual SPI ports. +* The GPIO mapping for the SPI2 is fixed: +* SPI signal | GPIO +* -------------|------------------- +* CSB_2 | GPIO 3 +* SCLK_2 | GPIO 2 +* SDO_2 | GPIO 1 +* SDO_2/SDI2 | GPIO 0 +* +* The secondary SPI port only has a small subset of registers that affect the +* attenuation of the TX channels. It uses a fifth GPIO pin in order to decide +* which TxAttenuation word is active. The Tx Attenuation words in the 2nd SPI +* port are different than the first SPI port. On the 2nd SPI port, each +* transmitter has two Tx Attenuation words (an active word and an inactive +* word). The BBIC should write to the inactive TxAttenuation word. Then the +* fifth GPIO pin should be asserted to make the inactive TxAttenuation word +* active. This allows the BBIC to tightly control in real time when the +* TxAttenuation updates. +* +* Dependencies +* - device->spiSettings +* - device->spiSettings->chipSelectIndex +* +* \param device is a pointer to the device settings structure +* \param enable This is parameter will enable the secondary SPI port: 1 = enable, 0 = disable +* \param updateTxAttenPinSelect This parameter set the GPIO pin to be toggle for using the inactive attenuation words for both channels +* tx update | GPIO +* ------------|------------------- +* 0x00 | GPIO 4 +* 0x01 | GPIO 8 +* 0x02 | GPIO 14 +* 0x03 | none selected +* +* \retval MYKONOS_ERR_SPI2_INV_GPIO if an invalid GPIO pin configuration is passed +* \retval MYKONOS_ERR_HAL_LAYER if HAL function error is passed +* \retval MYKONOS_ERR_OK Function completed successfully +*/ +mykonosGpioErr_t MYKONOS_spi2GpioSetup(mykonosDevice_t *device, uint8_t enable, uint8_t updateTxAttenPinSelect) +{ + uint8_t regWrite = 0; + uint8_t enableBit = 0; + + const uint32_t SPI2_PIN_MASK = 0x03; + +#ifdef MYKONOS_VERBOSE + CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_spi2GpioSetup()\n"); +#endif + + /* Error checking for correctness of GPIO to control attenuation word. */ + if (updateTxAttenPinSelect & ~SPI2_PIN_MASK) + { + CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SPI2_INV_GPIO, + getGpioMykonosErrorMessage(MYKONOS_ERR_SPI2_INV_GPIO)); + return MYKONOS_ERR_SPI2_INV_GPIO; + } + + /* masking the enable bit and the required pin */ + enableBit = (enable > 0) ? 1 : 0; + regWrite = (uint8_t)((updateTxAttenPinSelect << 4) | (enableBit << 3)); + + /* Set the SPI2 enable and the GPIO pin associated. */ + CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_CONFIGURATION_CONTROL_1, regWrite, 0x38, 0); + + return MYKONOS_ERR_GPIO_OK; +} + diff --git a/datalink814_ge/src/hardware/mykonos/mykonos_gpio.h b/datalink814_ge/src/hardware/mykonos/mykonos_gpio.h new file mode 100644 index 0000000..f69ec74 --- /dev/null +++ b/datalink814_ge/src/hardware/mykonos/mykonos_gpio.h @@ -0,0 +1,172 @@ +/*! + * \file mykonos_gpio.h + * \brief Contains macro definitions and function prototypes for mykonos_gpio.c + * + * Mykonos API version: 1.5.2.3566 + */ + +/** +* \page Disclaimer Legal Disclaimer +* Copyright 2015-2017 Analog Devices Inc. +* Released under the AD9371 API license, for more information see the "LICENSE.txt" file in this zip file. +* +*/ + +#ifndef MYKONOSGPIO_H_ +#define MYKONOSGPIO_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "t_mykonos.h" +#include "t_mykonos_gpio.h" + +/* + ***************************************************************************** + * GPIO functions + ***************************************************************************** + */ + +/* GPIO CMOS and SPI setting Functions */ +mykonosGpioErr_t MYKONOS_setGpioDrv(mykonosDevice_t *device, uint32_t gpioDrv); +mykonosGpioErr_t MYKONOS_getGpioDrv(mykonosDevice_t *device, uint32_t *gpioDrv); + +mykonosGpioErr_t MYKONOS_setGpioSlewRate(mykonosDevice_t *device, mykonosGpioSelect_t gpioSelect, mykonosGpioSlewRate_t slewRate); +mykonosGpioErr_t MYKONOS_getGpioSlewRate(mykonosDevice_t *device, mykonosGpioSelect_t gpioSelect, mykonosGpioSlewRate_t *slewRate); + +mykonosGpioErr_t MYKONOS_setCmosDrv(mykonosDevice_t *device, mykonosCmosPadDrvStr_t spiDrv); +mykonosGpioErr_t MYKONOS_getCmosDrv(mykonosDevice_t *device, mykonosCmosPadDrvStr_t *spiDrv); + + +/* Monitor output Functions */ +mykonosGpioErr_t MYKONOS_setGpioMonitorOut(mykonosDevice_t *device, uint8_t monitorIndex, uint8_t monitorMask); +mykonosGpioErr_t MYKONOS_getGpioMonitorOut(mykonosDevice_t *device, uint8_t *monitorIndex, uint8_t *monitorMask); + +/* RX GPIO Functions */ +mykonosGpioErr_t MYKONOS_setRx1GainCtrlPin(mykonosDevice_t *device, uint8_t incStep, uint8_t decStep, mykonosGpioSelect_t rx1GainIncPin, mykonosGpioSelect_t rx1GainDecPin, uint8_t enable); +mykonosGpioErr_t MYKONOS_setRx2GainCtrlPin(mykonosDevice_t *device, uint8_t incStep, uint8_t decStep, mykonosGpioSelect_t rx2GainIncPin, mykonosGpioSelect_t rx2GainDecPin, uint8_t enable); +mykonosGpioErr_t MYKONOS_getRx1GainCtrlPin(mykonosDevice_t *device, uint8_t *incStep, uint8_t *decStep, mykonosGpioSelect_t *rx1GainIncPin, mykonosGpioSelect_t *rx1GainDecPin, uint8_t *enable); +mykonosGpioErr_t MYKONOS_getRx2GainCtrlPin(mykonosDevice_t *device, uint8_t *incStep, uint8_t *decStep, mykonosGpioSelect_t *rx2GainIncPin, mykonosGpioSelect_t *rx2GainDecPin, uint8_t *enable); + +mykonosGpioErr_t MYKONOS_setRxHybridGainChangePin(mykonosDevice_t *device, mykonosGpioSelect_t rx1GainChangePin, mykonosGpioSelect_t rx2GainChangePin); +mykonosGpioErr_t MYKONOS_getRxHybridGainChangePin(mykonosDevice_t *device, mykonosGpioSelect_t *rx1GainChangePin, mykonosGpioSelect_t *rx2GainChangePin); +mykonosGpioErr_t MYKONOS_setObsRxHybridGainChangePin(mykonosDevice_t *device, mykonosGpioSelect_t obsRxGainChangePin); +mykonosGpioErr_t MYKONOS_getObsRxHybridGainChangePin(mykonosDevice_t *device, mykonosGpioSelect_t *obsRxGainChangePin); + +mykonosGpioErr_t MYKONOS_setRxAgcEnSyncPin(mykonosDevice_t *device, mykonosGpioSelect_t rx1AgcSyncPin, mykonosGpioSelect_t rx2AgcSyncPin); +mykonosGpioErr_t MYKONOS_getRxAgcEnSyncPin(mykonosDevice_t *device, mykonosGpioSelect_t *rx1AgcSyncPin, mykonosGpioSelect_t *rx2AgcSyncPin); +mykonosGpioErr_t MYKONOS_setObsRxAgcEnSyncPin(mykonosDevice_t *device, mykonosGpioSelect_t obsRxAgcSyncPin); +mykonosGpioErr_t MYKONOS_getObsRxAgcEnSyncPin(mykonosDevice_t *device, mykonosGpioSelect_t *obsRxAgcSyncPin); + +/* TX GPIO Functions */ +mykonosGpioErr_t MYKONOS_setTx1AttenCtrlPin(mykonosDevice_t *device, uint8_t stepSize, mykonosGpioSelect_t tx1AttenIncPin, mykonosGpioSelect_t tx1AttenDecPin, uint8_t enable, uint8_t useTx1ForTx2); +mykonosGpioErr_t MYKONOS_setTx2AttenCtrlPin(mykonosDevice_t *device, uint8_t stepSize, mykonosGpioSelect_t tx2AttenIncPin, mykonosGpioSelect_t tx2AttenDecPin, uint8_t enable); +mykonosGpioErr_t MYKONOS_getTx1AttenCtrlPin(mykonosDevice_t *device, uint8_t *stepSize, mykonosGpioSelect_t *tx1AttenIncPin, mykonosGpioSelect_t *tx1AttenDecPin, uint8_t *enable, uint8_t *useTx1ForTx2); +mykonosGpioErr_t MYKONOS_getTx2AttenCtrlPin(mykonosDevice_t *device, uint8_t *stepSize, mykonosGpioSelect_t *tx2AttenIncPin, mykonosGpioSelect_t *tx2AttenDecPin, uint8_t *enable, uint8_t *useTx1ForTx2); + +mykonosGpioErr_t MYKONOS_spi2GpioSetup(mykonosDevice_t *device, uint8_t enable, uint8_t updateTxAttenPinSelect); + +/* GPIO memory source Functions */ +mykonosGpioErr_t MYKONOS_setGpioPinLevel(mykonosDevice_t *device, uint32_t gpioPinLevel); +mykonosGpioErr_t MYKONOS_getGpioPinLevel(mykonosDevice_t *device, uint32_t *gpioPinLevel); +mykonosGpioErr_t MYKONOS_getGpioSetLevel(mykonosDevice_t *device, uint32_t *gpioPinSetLevel); + +/* Gain Compensation Functions */ +mykonosGpioErr_t MYKONOS_setRxGainCompensation (mykonosDevice_t *device, mykonosGainComp_t *gainComp, uint8_t enable); +mykonosGpioErr_t MYKONOS_getRxGainCompensation (mykonosDevice_t *device, mykonosGainComp_t *gainComp, uint8_t *enabled); + +mykonosGpioErr_t MYKONOS_setObsRxGainCompensation (mykonosDevice_t *device, mykonosObsRxGainComp_t *gainComp, uint8_t enable); +mykonosGpioErr_t MYKONOS_getObsRxGainCompensation (mykonosDevice_t *device, mykonosObsRxGainComp_t *gainComp, uint8_t *enabled); + +/* SLICER Functions */ +mykonosGpioErr_t MYKONOS_setRxSlicerCtrl(mykonosDevice_t *device, uint8_t slicerStep, mykonosRxSlicer_t rx1Pins, mykonosRxSlicer_t rx2Pins, uint8_t enable); +mykonosGpioErr_t MYKONOS_getRxSlicerCtrl(mykonosDevice_t *device, uint8_t *slicerStep, mykonosRxSlicer_t *rx1Pins, mykonosRxSlicer_t *rx2Pins, uint8_t *enable); + +mykonosGpioErr_t MYKONOS_setObsRxSlicerCtrl(mykonosDevice_t *device, uint8_t slicerStep, mykonosObsRxSlicer_t obsRxPins, uint8_t enable); +mykonosGpioErr_t MYKONOS_getObsRxSlicerCtrl(mykonosDevice_t *device, uint8_t *slicerStep, mykonosObsRxSlicer_t *obsRxPins, uint8_t *enable); + +/* Floating Point Formatter Functions */ +mykonosGpioErr_t MYKONOS_setFloatPointFrmt (mykonosDevice_t *device, mykonosFloatPntFrmt_t *floatFrmt); +mykonosGpioErr_t MYKONOS_getFloatPointFrmt (mykonosDevice_t *device, mykonosFloatPntFrmt_t *floatFrmt); + +mykonosGpioErr_t MYKONOS_setRxEnFloatPntFrmt (mykonosDevice_t *device, uint8_t rx1Att, uint8_t rx2Att, uint8_t enable); +mykonosGpioErr_t MYKONOS_getRxEnFloatPntFrmt (mykonosDevice_t *device, uint8_t *rx1Att, uint8_t *rx2Att, uint8_t *enable); + +mykonosGpioErr_t MYKONOS_setOrxEnFloatPntFrmt (mykonosDevice_t *device, uint8_t orxAtt, uint8_t enable); +mykonosGpioErr_t MYKONOS_getOrxEnFloatPntFrmt (mykonosDevice_t *device, uint8_t *orxAtt, uint8_t *enable); + +/* + ***************************************************************************** + * General Purpose Interrupt functions + ***************************************************************************** + */ +mykonosGpioErr_t MYKONOS_configGpInterrupt(mykonosDevice_t *device, uint16_t gpMask); +mykonosGpioErr_t MYKONOS_readGpInterruptStatus(mykonosDevice_t *device, uint16_t *status); + +/* + ***************************************************************************** + * ARM GPIO usage functions + ***************************************************************************** + */ +mykonosGpioErr_t MYKONOS_setArmGpioPins(mykonosDevice_t *device); + +/* + ***************************************************************************** + * AuxADC/AuxDAC functions + ***************************************************************************** + */ +mykonosGpioErr_t MYKONOS_setupAuxAdcs(mykonosDevice_t *device, uint8_t adcDecimation, uint8_t enable); +mykonosGpioErr_t MYKONOS_setAuxAdcChannel(mykonosDevice_t *device, mykonosAuxAdcChannels_t auxAdcChannel); +mykonosGpioErr_t MYKONOS_readAuxAdc(mykonosDevice_t *device, uint16_t *adcCode); +mykonosGpioErr_t MYKONOS_setupAuxDacs(mykonosDevice_t *device); +mykonosGpioErr_t MYKONOS_writeAuxDac(mykonosDevice_t *device, uint8_t auxDacIndex, uint16_t auxDacCode); + +/* + ***************************************************************************** + * GPIO3v3 functions + ***************************************************************************** + */ +mykonosGpioErr_t MYKONOS_setupGpio3v3(mykonosDevice_t *device); + +mykonosGpioErr_t MYKONOS_setGpio3v3PinLevel(mykonosDevice_t *device, uint16_t gpio3v3PinLevel); +mykonosGpioErr_t MYKONOS_getGpio3v3SetLevel(mykonosDevice_t *device, uint16_t *gpio3v3SetLevel); + +mykonosGpioErr_t MYKONOS_getGpio3v3PinLevel(mykonosDevice_t *device, uint16_t *gpio3v3PinLevel); + +mykonosGpioErr_t MYKONOS_setGpio3v3Oe(mykonosDevice_t *device, uint16_t gpio3v3OutEn); +mykonosGpioErr_t MYKONOS_getGpio3v3Oe(mykonosDevice_t *device, uint16_t *gpio3v3OutEn); + +mykonosGpioErr_t MYKONOS_setGpio3v3SourceCtrl(mykonosDevice_t *device, uint16_t gpio3v3SrcCtrl); +mykonosGpioErr_t MYKONOS_getGpio3v3SourceCtrl(mykonosDevice_t *device, uint16_t *gpio3v3SrcCtrl); + +/* + ***************************************************************************** + * GPIO helper functions + ***************************************************************************** + */ +mykonosGpioErr_t MYKONOS_setupGpio(mykonosDevice_t *device); +mykonosGpioErr_t MYKONOS_setGpioOe(mykonosDevice_t *device, uint32_t gpioOutEn, uint32_t gpioUsedMask); +mykonosGpioErr_t MYKONOS_getGpioOe(mykonosDevice_t *device, uint32_t *gpioOutEn); + +mykonosGpioErr_t MYKONOS_setGpioSourceCtrl(mykonosDevice_t *device, uint32_t gpioSrcCtrl); +mykonosGpioErr_t MYKONOS_getGpioSourceCtrl(mykonosDevice_t *device, uint32_t *gpioSrcCtrl); + +/* + ***************************************************************************** + * Temperature Sensor functions + ***************************************************************************** + */ +mykonosGpioErr_t MYKONOS_setupTempSensor(mykonosDevice_t *device, mykonosTempSensorConfig_t *tempSensor); +mykonosGpioErr_t MYKONOS_getTempSensorConfig(mykonosDevice_t *device, mykonosTempSensorConfig_t *tempSensor); + +mykonosGpioErr_t MYKONOS_startTempMeasurement(mykonosDevice_t *device); +mykonosGpioErr_t MYKONOS_readTempSensor(mykonosDevice_t *device, mykonosTempSensorStatus_t *tempStatus); + +const char* getGpioMykonosErrorMessage(mykonosGpioErr_t errorCode); + +#ifdef __cplusplus +} +#endif + +#endif /* MYKONOSGPIO_H_ */ diff --git a/datalink814_ge/src/hardware/mykonos/mykonos_macros.h b/datalink814_ge/src/hardware/mykonos/mykonos_macros.h new file mode 100644 index 0000000..354f561 --- /dev/null +++ b/datalink814_ge/src/hardware/mykonos/mykonos_macros.h @@ -0,0 +1,707 @@ +/** + * \file mykonos_macros.h + * \brief Contains address and miscellaneous macro definitions for Mykonos API + * + * Mykonos API version: 1.5.2.3566 + */ + +/** +* \page Disclaimer Legal Disclaimer +* Copyright 2015-2017 Analog Devices Inc. +* Released under the AD9371 API license, for more information see the "LICENSE.txt" file in this zip file. +* +*/ + +#ifndef CLEMENTE_TDD_MACROS_H +#define CLEMENTE_TDD_MACROS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define MYKONOS_ADDR_CONFIGURATION_CONTROL_0 0x000 +#define MYKONOS_ADDR_SPI_CONFIGURATION_CONTROL_1 0x001 +#define MYKONOS_ADDR_PRODUCT_ID 0x004 +#define MYKONOS_GPIO_DRV_CTL_0 0x020 +#define MYKONOS_GPIO_DRV_CTL_1 0x021 +#define MYKONOS_GPIO_SLEW_CTL_0 0x022 +#define MYKONOS_GPIO_SLEW_CTL_1 0x023 +#define MYKONOS_GPIO_SLEW_CTL_2 0x024 +#define MYKONOS_GPIO_SLEW_CTL_3 0x025 + +#define MYKONOS_ADDR_DIGITAL_IO_CONTROL 0x028 + +#define MYKONOS_ADDR_SYSREF_PAD_CONFIG 0x040 +#define MYKONOS_ADDR_TX1_SYNC_PAD_CONFIG 0x041 +#define MYKONOS_ADDR_TX2_SYNC_PAD_CONFIG 0x042 +#define MYKONOS_ADDR_RX1_SYNC_CONFIG 0x043 +#define MYKONOS_ADDR_RX2_SYNC_CONFIG 0x044 + +/* Mykonos Framer Registers */ +#define MYKONOS_ADDR_FRAMER_RESET 0x059 +#define MYKONOS_ADDR_FRAMER_CLK_EN 0x05A +#define MYKONOS_ADDR_FRAMER_ADDR 0x05B +#define MYKONOS_ADDR_FRAMER_DATA 0x05C +#define MYKONOS_ADDR_FRAMER_WRITE_EN 0x05D +#define MYKONOS_ADDR_FRAMER_SYSREF_FIFO_EN 0x05E +#define MYKONOS_ADDR_FRAMER_CONFIG_F 0x05F +#define MYKONOS_ADDR_FRAMER_LANE_CTL 0x060 +#define MYKONOS_ADDR_FRAMER_ADC_XBAR_SEL 0x061 +#define MYKONOS_ADDR_FRAMER_LANE_XBAR_SEL 0x062 +#define MYKONOS_ADDR_FRAMER_CONFIG_LOOPBACK_XBAR_REV 0x063 +#define MYKONOS_ADDR_FRAMER_SYNCN_FILT 0x064 +#define MYKONOS_ADDR_FRAMER_LMFC_F_OFFSET 0x065 +#define MYKONOS_ADDR_FRAMER_LMFC_K_OFFSET 0x066 +#define MYKONOS_ADDR_FRAMER_TEST_CNTR_CTL 0x067 +#define MYKONOS_ADDR_FRAMER_STATUS_STRB 0x068 +#define MYKONOS_ADDR_FRAMER_STATUS 0x069 +#define MYKONOS_ADDR_FRAMER_SYSREF_TO_LMFC_CNTR_STAT 0x06A +#define MYKONOS_ADDR_FRAMER_SYSREF_TO_LMFC_ERR_MARGIN 0x06B +#define MYKONOS_ADDR_FRAMER_LANE_FIFO_STRB 0x06C +#define MYKONOS_ADDR_FRAMER_LANE0_FIFO_RDWR_ADDR 0x06D +#define MYKONOS_ADDR_FRAMER_LANE1_FIFO_RDWR_ADDR 0x06E +#define MYKONOS_ADDR_FRAMER_LANE2_FIFO_RDWR_ADDR 0x06F +#define MYKONOS_ADDR_FRAMER_LANE3_FIFO_RDWR_ADDR 0x070 +#define MYKONOS_ADDR_FRAMER_PRBS10_CTL 0x071 +#define MYKONOS_ADDR_FRAMER_PRBS20_CTL 0x072 +#define MYKONOS_ADDR_FRAMER_PATTERN_GEN_EN 0x073 +#define MYKONOS_ADDR_FRAMER_PATTERN_GEN_7_TO_0 0x074 +#define MYKONOS_ADDR_FRAMER_PATTERN_GEN_15_TO_8 0x075 +#define MYKONOS_ADDR_FRAMER_PATTERN_GEN_19_TO_16 0x076 +#define MYKONOS_ADDR_FRAMER_CONFIG_JTX_GEN 0x077 +#define MYKONOS_ADDR_FRAMER_LANE_DATA_CTL 0x078 +#define MYKONOS_ADDR_FRAMER_DATA_SAMPLE_CTL 0x079 + +/* Mykonos Deframer Sub Address Map */ +#define MYKONOS_SUBADDR_DEFRAMER_LANE0_ILAS_RECVD 0x00 +#define MYKONOS_SUBADDR_DEFRAMER_LANE0_ILAS_CFG 0x50 + +/* Mykonos Deframer Registers */ +#define MYKONOS_ADDR_DEFRAMER_RESET 0x07A +#define MYKONOS_ADDR_DEFRAMER_CLK_EN 0x07B +#define MYKONOS_ADDR_DEFRAMER_ADDR 0x07C +#define MYKONOS_ADDR_DEFRAMER_DATA 0x07D +#define MYKONOS_ADDR_DEFRAMER_WR_EN 0x07E +#define MYKONOS_ADDR_DEFRAMER_SYSREF_FIFO_EN 0x07F +#define MYKONOS_ADDR_DEFRAMER_CONFIG_F 0x080 +#define MYKONOS_ADDR_DEFRAMER_LANE_FIFO_CTL 0x081 +#define MYKONOS_ADDR_DEFRAMER_DAC_XBAR_SEL 0x082 +#define MYKONOS_ADDR_DEFRAMER_LANE_XBAR_SEL 0x083 +#define MYKONOS_ADDR_DEFRAMER_LMFC_F_OFFSET 0x084 +#define MYKONOS_ADDR_DEFRAMER_LMFC_K_OFFSET 0x085 +#define MYKONOS_ADDR_DEFRAMER_CONFIG_SYNC_USER_DATA_CTL 0x086 +#define MYKONOS_ADDR_DEFRAMER_SYNC_REQ_RETIME 0x087 +#define MYKONOS_ADDR_DEFRAMER_TEST 0x088 +#define MYKONOS_ADDR_DEFRAMER_DET_FIFO_WR_STRT_DAC_XBAR_REV 0x089 +#define MYKONOS_ADDR_DEFRAMER_STAT_STRB 0x08A +#define MYKONOS_ADDR_DEFRAMER_STAT 0x08B +#define MYKONOS_ADDR_DEFRAMER_TEST_ERR_CNT_STAT 0x08C +#define MYKONOS_ADDR_DEFRAMER_DET_FIFO_RD_ADDR 0x08D +#define MYKONOS_ADDR_DEFRAMER_DET_FIFO_WR_ADDR 0x08E +#define MYKONOS_ADDR_DEFRAMER_QBLMFC_VS_EXTLMFC_CNTR_STAT 0x08F +#define MYKONOS_ADDR_DEFRAMER_DET_FIFO_STAT 0x090 +#define MYKONOS_ADDR_DEFRAMER_STRT_RD_DEL_STOP_WR 0x091 +#define MYKONOS_ADDR_DEFRAMER_FIFO_SAMPLE_SPI_ADDR_RD 0x092 +#define MYKONOS_ADDR_DEFRAMER_FIFO_BYTE_SPI_ADDR_RD 0x093 +#define MYKONOS_ADDR_DEFRAMER_FIFO_BYTE_SPI_DATA_RD 0x094 +#define MYKONOS_ADDR_DEFRAMER_SAMPLE0_7_TO_0 0x095 +#define MYKONOS_ADDR_DEFRAMER_SAMPLE0_15_TO_8 0x096 +#define MYKONOS_ADDR_DEFRAMER_SAMPLE1_7_TO_0 0x097 +#define MYKONOS_ADDR_DEFRAMER_SAMPLE1_15_TO_8 0x098 +#define MYKONOS_ADDR_DEFRAMER_SAMPLE2_7_TO_0 0x099 +#define MYKONOS_ADDR_DEFRAMER_SAMPLE2_15_TO_8 0x09A +#define MYKONOS_ADDR_DEFRAMER_SAMPLE3_7_TO_0 0x09B +#define MYKONOS_ADDR_DEFRAMER_SAMPLE3_15_TO_8 0x09C +#define MYKONOS_ADDR_DEFRAMER_LANE_FIFO_STRB 0x09D +#define MYKONOS_ADDR_DEFRAMER_LANE0_FIFO_RDWR_ADDR 0x09E +#define MYKONOS_ADDR_DEFRAMER_LANE1_FIFO_RDWR_ADDR 0x09F +#define MYKONOS_ADDR_DEFRAMER_LANE2_FIFO_RDWR_ADDR 0x0A0 +#define MYKONOS_ADDR_DEFRAMER_LANE3_FIFO_RDWR_ADDR 0x0A1 +#define MYKONOS_ADDR_DEFRAMER_SYSREF_TO_LMFC_CNTR_STAT 0x0A2 +#define MYKONOS_ADDR_DEFRAMER_SYSREF_TO_LMFC_ERR_MARGIN 0x0A3 +#define MYKONOS_ADDR_DEFRAMER_PRBS10_CTL 0x0A4 +#define MYKONOS_ADDR_DEFRAMER_PRBS20_CTL 0x0A5 +#define MYKONOS_ADDR_DEFRAMER_PRBS20_STRB_CHKSUM_TYPE 0x0A6 +#define MYKONOS_ADDR_DEFRAMER_PRBS20_ERR_CNTR_7_TO_0 0x0A7 +#define MYKONOS_ADDR_DEFRAMER_PRBS20_ERR_CNTR_15_TO_8 0x0A8 +#define MYKONOS_ADDR_DEFRAMER_PRBS20_ERR_CNTR_23_TO_16 0x0A9 +#define MYKONOS_ADDR_DEFRAMER_LANE_DATA_CTL 0x0AA +#define MYKONOS_ADDR_DEFRAMER_STATUS_2 0x0AB +#define MYKONOS_ADDR_DEFRAMER_DET_FIFO_PHASE 0x0AC + +/* Mykonos Serializer Registers */ +#define MYKONOS_ADDR_SERIALIZER_CTL_0 0x0B0 +#define MYKONOS_ADDR_SERIALIZER_CTL_1 0x0B1 +#define MYKONOS_ADDR_SERIALIZER_CTL_2 0x0B2 +#define MYKONOS_ADDR_SERIALIZER_CTL_3 0x0B3 +#define MYKONOS_ADDR_SERIALIZER_HS_DIV_TXSER_CLK_EN 0x0B4 +#define MYKONOS_ADDR_SERIALIZER_SPECIAL 0x0B5 + +/* Mykonos Deserializer Registers */ +#define MYKONOS_ADDR_DESERIALIZER_PDET_CTL 0x0BC +#define MYKONOS_ADDR_DESERIALIZER_CTL_0 0x0BD +#define MYKONOS_ADDR_DESERIALIZER_SIN_SHAPE_0 0x0BE +#define MYKONOS_ADDR_DESERIALIZER_SIN_SHAPE_1 0x0BF +#define MYKONOS_ADDR_DESERIALIZER_EQ_CTL_0 0x0C1 +#define MYKONOS_ADDR_DESERIALIZER_EQ_CTL_1 0x0C2 +#define MYKONOS_ADDR_DESERIALIZER_MISC_CTL 0x0C3 +#define MYKONOS_ADDR_DESERIALIZER_EQ_HP_EN 0x0C4 +#define MYKONOS_ADDR_DESERIALIZER_EQ_CTL_1_TO_0 0x0C5 +#define MYKONOS_ADDR_DESERIALIZER_EQ_CTL_3_TO_2 0x0C6 +#define MYKONOS_ADDR_DESERIALIZER_HS_DIV_RXCDR_CLK_EN 0x0CD +#define MYKONOS_ADDR_DESERIALIZER_SPECIAL 0x0CE +#define MYKONOS_ADDR_DESERIALIZER_CDR_CAL_CTL 0x0D0 + +#define MYKONOS_ADDR_CONFIGURATION_CONTROL_1 0x100 +#define MYKONOS_ADDR_CONFIGURATION_CONTROL_2 0x101 +#define MYKONOS_ADDR_CONFIGURATION_CONTROL_4 0x102 +#define MYKONOS_ADDR_CONFIGURATION_CONTROL_5 0x103 +#define MYKONOS_ADDR_DPD_SNIFFER_CONFIGURATION_CONTROL_1 0x104 +#define MYKONOS_ADDR_DPD_SNIFFER_CONFIGURATION_CONTROL_2 0x105 +#define MYKONOS_ADDR_DPD_SNIFFER_GPIO_SELECT 0x106 +#define MYKONOS_ADDR_SNIFFER_CONFIGURATION_CONTROL 0x107 +#define MYKONOS_ADDR_DPD_CONFIGURATION_CONTROL 0x108 +#define MYKONOS_ADDR_LOOPBACK_CONFIGURATION_CONTROL 0x109 + +#define MYKONOS_ADDR_CLOCK_CONTROL_0 0x117 +#define MYKONOS_ADDR_CLOCK_CONTROL_1 0x118 +#define MYKONOS_ADDR_CLOCK_CONTROL_2 0x119 +#define MYKONOS_ADDR_CLOCK_CONTROL_3 0x11A +#define MYKONOS_ADDR_CLOCK_CONTROL_4 0x11B +#define MYKONOS_ADDR_CLOCK_CONTROL_5 0x11C + +#define MYKONOS_ADDR_MCS_CONTROL 0x120 +#define MYKONOS_ADDR_MCS_STATUS 0x121 + +/* CLK PLL Registers */ +#define MYKONOS_ADDR_CLK_SYNTH_DIVIDER_INT_BYTE0 0x141 +#define MYKONOS_ADDR_CLK_SYNTH_DIVIDER_INT_BYTE1 0x142 +#define MYKONOS_ADDR_CLK_SYNTH_DIVIDER_FRAC_BYTE0 0x143 +#define MYKONOS_ADDR_CLK_SYNTH_DIVIDER_FRAC_BYTE1 0x144 +#define MYKONOS_ADDR_CLK_SYNTH_DIVIDER_FRAC_BYTE2 0x145 +#define MYKONOS_ADDR_CLK_SYNTH_F_VCOTN_BYTE1 0x148 +#define MYKONOS_ADDR_CLK_SYNTH_BYTE1 0x149 +#define MYKONOS_ADDR_CLK_SYNTH_BYTE2 0x14A +#define MYKONOS_ADDR_CLK_SYNTH_BYTE3 0x14B +#define MYKONOS_ADDR_CLK_SYNTH_BYTE5 0x14D +#define MYKONOS_ADDR_CLK_SYNTH_BYTE6 0x14E +#define MYKONOS_ADDR_CLK_SYNTH_BYTE7 0x14F +#define MYKONOS_ADDR_CLK_SYNTH_LF_R3 0x150 +#define MYKONOS_ADDR_CLK_SYNTH_BYTE9 0x152 +#define MYKONOS_ADDR_CLK_SYNTH_CAL_STAT 0x154 +#define MYKONOS_ADDR_CLK_SYNTH_VCO_CAL_REF 0x155 +#define MYKONOS_ADDR_CLK_SYNTH_VCO_BAND_BYTE1 0x157 +#define MYKONOS_ADDR_CLK_SYNTH_CAL_CONTROL 0x159 +#define MYKONOS_ADDR_CLK_SYNTH_VCO_VAR_CTL1 0x15E +#define MYKONOS_ADDR_CLK_SYNTH_VCO_VAR_CTL2 0x15F + +/* DPD Registers */ +#define MYKONOS_ADDR_TX1_DPD_MODEL_INDIRECT_PTR 0x178 +#define MYKONOS_ADDR_TX2_DPD_MODEL_INDIRECT_PTR 0x17C +#define MYKONOS_ADDR_DPD_RMS_BUF_SIZE 0x180 +#define MYKONOS_ADDR_TX1_DPD_MODEL_WORKING_PTR 0x188 +#define MYKONOS_ADDR_TX2_DPD_MODEL_WORKING_PTR 0x18C + +/* Rx NCO Control registers */ +#define MYKONOS_ADDR_CALPLL_SDM_CONTROL 0x17F +#define MYKONOS_ADDR_RX_NCO_CONTROL 0x190 +#define MYKONOS_ADDR_RX_NCO_CH1_FTW_BYTE_3 0x191 +#define MYKONOS_ADDR_RX_NCO_CH1_FTW_BYTE_2 0x192 +#define MYKONOS_ADDR_RX_NCO_CH1_FTW_BYTE_1 0x193 +#define MYKONOS_ADDR_RX_NCO_CH2_FTW_BYTE_3 0x194 +#define MYKONOS_ADDR_RX_NCO_CH2_FTW_BYTE_2 0x195 +#define MYKONOS_ADDR_RX_NCO_CH2_FTW_BYTE_1 0x196 +#define MYKONOS_ADDR_RX_NCO_DPD_SNIFFER_FTW_BYTE_3 0x197 +#define MYKONOS_ADDR_RX_NCO_DPD_SNIFFER_FTW_BYTE_2 0x198 +#define MYKONOS_ADDR_RX_NCO_DPD_SNIFFER_FTW_BYTE_1 0x199 + +#define MYKONOS_ADDR_ENSM_CONFIG_7_0 0x1B0 +#define MYKONOS_ADDR_CALIBRATION_CONTROL 0x1B2 +#define MYKONOS_ADDR_ENSM_MANUAL_GAIN_LOCK_GPIO_SELECT 0x1B5 +#define MYKONOS_ADDR_REFERENCE_CLOCK_CYCLES 0x1C0 +#define MYKONOS_ADDR_TX_PD_OVERIDE_7_0 0x209 +#define MYKONOS_ADDR_RCAL_CONTROL 0x224 +#define MYKONOS_ADDR_REF_PAD_CONFIG1 0x230 +#define MYKONOS_ADDR_REF_PAD_CONFIG2 0x231 + +#define MYKONOS_ADDR_RXSYNTH_CP_CAL_STAT 0x254 +#define MYKONOS_ADDR_RXSYNTH_VCO_BAND_BYTE1 0x257 +#define MYKONOS_ADDR_TXSYNTH_CP_CAL_STAT 0x2C4 +#define MYKONOS_ADDR_TXSYNTH_VCO_BAND_BYTE1 0x2C7 +#define MYKONOS_ADDR_SNIFF_RXSYNTH_CP_CAL_STAT 0x354 +#define MYKONOS_ADDR_SNIFF_RXSYNTH_VCO_BAND_BYTE1 0x357 +#define MYKONOS_ADDR_SNIFF_RXLOGEN_BYTE1 0x380 + +#define MYKONOS_ADDR_RX_FILTER_CONFIGURATION 0x410 +#define MYKONOS_ADDR_RX_FILTER_GAIN 0x411 +#define MYKONOS_ADDR_DPD_SNIFFER_RX_FILTER_GAIN 0x412 + +/* Mykonos Temperature Gain Compensation Registers */ +#define MYKONOS_ADDR_RX1_TEMP_GAIN_COMP 0x420 +#define MYKONOS_ADDR_RX2_TEMP_GAIN_COMP 0x421 +#define MYKONOS_ADDR_OBS_TEMP_GAIN_COMP 0x422 + +/* Mykonos AGC General Registers */ +#define MYKONOS_ADDR_AGC_CFG_1 0x42E +#define MYKONOS_ADDR_AGC_CFG_2 0x42F +#define MYKONOS_ADDR_AGC_GAIN_CHANGE_GPIO_SEL 0x430 +#define MYKONOS_ADDR_AGC_RX1_MAX_GAIN_INDEX 0x431 +#define MYKONOS_ADDR_AGC_RX1_MIN_GAIN_INDEX 0x432 +#define MYKONOS_ADDR_AGC_MANUAL_GAIN_CFG 0x433 +#define MYKONOS_ADDR_AGC_MANUAL_GAIN_GPIO_SEL 0x434 +#define MYKONOS_ADDR_AGC_MANUAL_GAIN_INDEX_CH_1 0x435 +#define MYKONOS_ADDR_AGC_MANUAL_GAIN_INDEX_CH_2 0x436 +#define MYKONOS_ADDR_AGC_LOCK_LEVEL 0x437 +#define MYKONOS_ADDR_AGC_OVRG_GAIN_STEP_1 0x438 +#define MYKONOS_ADDR_AGC_OVRG_GAIN_STEP_2 0x439 +#define MYKONOS_ADDR_AGC_OVRG_GAIN_STEP_3 0x43A +#define MYKONOS_ADDR_AGC_OVRG_GAIN_STEP_4 0x43B +#define MYKONOS_ADDR_AGC_OVRG_GAIN_STEP_5 0x43C +#define MYKONOS_ADDR_AGC_OVRG_GAIN_STEP_6 0x43D +#define MYKONOS_ADDR_AGC_RX1_GAIN_LOCK_DELAY 0x43E +#define MYKONOS_ADDR_AGC_RX2_GAIN_LOCK_DELAY 0x43F +#define MYKONOS_ADDR_AGC_RX1_ATTACK_DELAY 0x440 +#define MYKONOS_ADDR_AGC_RX2_ATTACK_DELAY 0x441 +#define MYKONOS_ADDR_AGC_ULB_THRSH 0x442 +#define MYKONOS_ADDR_AGC_LLB_THRSH 0x443 +#define MYKONOS_ADDR_AGC_RX_BLOCK_DET_DECAY 0x444 +#define MYKONOS_ADDR_AGC_RESET_PD_HIGH_CNT 0x445 +#define MYKONOS_ADDR_AGC_RX2_MAX_GAIN_INDEX 0x446 +#define MYKONOS_ADDR_AGC_RX2_MIN_GAIN_INDEX 0x447 +#define MYKONOS_ADDR_AGC_ORX_SNRX_CFG_1 0x448 +#define MYKONOS_ADDR_AGC_ORX_SNRX_CFG_2 0x449 +#define MYKONOS_ADDR_AGC_ORX_SNRX_MAX_GAIN_INDEX 0x44A +#define MYKONOS_ADDR_AGC_ORX_SNRX_MIN_GAIN_INDEX 0x44B +#define MYKONOS_ADDR_AGC_ORX_SNRX_MANUAL_GAIN_CFG 0x44C +#define MYKONOS_ADDR_AGC_ORX_SNRX_GPIO_SEL 0x44D +#define MYKONOS_ADDR_AGC_ORX_SNRX_LOCK_LEVEL 0x44E +#define MYKONOS_ADDR_AGC_ORX_SNRX_OVRG_GAIN_STEP_1 0x44F +#define MYKONOS_ADDR_AGC_ORX_SNRX_OVRG_GAIN_STEP_2 0x450 +#define MYKONOS_ADDR_AGC_ORX_SNRX_OVRG_GAIN_STEP_3 0x451 +#define MYKONOS_ADDR_AGC_ORX_SNRX_OVRG_GAIN_STEP_4 0x452 +#define MYKONOS_ADDR_AGC_ORX_SNRX_OVRG_GAIN_STEP_5 0x453 +#define MYKONOS_ADDR_AGC_ORX_SNRX_OVRG_GAIN_STEP_6 0x454 +#define MYKONOS_ADDR_AGC_ORX_SNRX_GAIN_LOCK_DELAY 0x455 +#define MYKONOS_ADDR_AGC_ORX_SNRX_ATTACK_DELAY 0x456 +#define MYKONOS_ADDR_AGC_ORX_SNRX_ULB_THRSH 0x457 +#define MYKONOS_ADDR_AGC_ORX_SNRX_LLB_THRSH 0x458 +#define MYKONOS_ADDR_AGC_ORX_SNRX_BLOCK_DET_DECAY 0x459 +#define MYKONOS_ADDR_AGC_ORX_SNRX_RESET_PD_HIGH_CNT 0x45A +#define MYKONOS_ADDR_AGC_ORX1_MANUAL_GAIN_INDEX 0x45B +#define MYKONOS_ADDR_AGC_ORX2_MANUAL_GAIN_INDEX 0x45C +#define MYKONOS_ADDR_AGC_SNRX_MANUAL_GAIN_INDEX 0x45D +#define MYKONOS_ADDR_AGC_LOOPBACK1_MANUAL_GAIN_INDEX 0x45E +#define MYKONOS_ADDR_AGC_LOOPBACK2_MANUAL_GAIN_INDEX 0x45F +#define MYKONOS_ADDR_AGC_ORX_SNRX_ACTIVE 0x460 + +/* Mykonos Fast Attack AGC Registers */ +#define MYKONOS_ADDR_AGC_FAST_CFG_1 0x468 +#define MYKONOS_ADDR_AGC_FAST_CFG_2 0x469 +#define MYKONOS_ADDR_AGC_FAST_ENRGY_LOST_THRSH 0x46A +#define MYKONOS_ADDR_AGC_FAST_STRONG_SIG_THRSH 0x46B +#define MYKONOS_ADDR_AGC_FAST_SETTING_DELAY 0x46C +#define MYKONOS_ADDR_AGC_FAST_OPT_MAX_GAIN 0x46D +#define MYKONOS_ADDR_AGC_FAST_ENRGY_DET_CNT 0x46E +#define MYKONOS_ADDR_AGC_FAST_AGCLL_UPPER_LIMIT 0x46F +#define MYKONOS_ADDR_AGC_FAST_GAIN_LOCK_EXIT_CNT 0x470 +#define MYKONOS_ADDR_AGC_FAST_ORX_SNRX_CFG_1 0x471 +#define MYKONOS_ADDR_AGC_FAST_ORX_SNRX_CFG_2 0x472 +#define MYKONOS_ADDR_AGC_FAST_ORX_SNRX_ENRGY_LOST_THRSH 0x473 +#define MYKONOS_ADDR_AGC_FAST_ORX_SNRX_STRONG_SIG_THRSH 0x474 +#define MYKONOS_ADDR_AGC_FAST_ORX_SNRX_SET_DELAY 0x475 +#define MYKONOS_ADDR_AGC_FAST_ORX_SNRX_OPT_MAX_GAIN 0x476 +#define MYKONOS_ADDR_AGC_FAST_ORX_SNRX_ENRGY_DET_CNT 0x477 +#define MYKONOS_ADDR_AGC_FAST_ORX_SNRX_AGCLL_UPPER_LIMIT 0x478 +#define MYKONOS_ADDR_AGC_FAST_ORX_SNRX_GAIN_LOCK_EXIT_CNT 0x479 + +/* Mykonos Slow Loop - Hybrid AGC Registers */ +#define MYKONOS_ADDR_AGC_SLOW_LOCK_LEV_THRSH 0x480 +#define MYKONOS_ADDR_AGC_SLOW_ULB_CNT_THRSH 0x481 +#define MYKONOS_ADDR_AGC_SLOW_LLB_CNT_THRSH 0x482 +#define MYKONOS_ADDR_AGC_SLOW_HIGH_OVRG_CNT_THRSH 0x483 +#define MYKONOS_ADDR_AGC_SLOW_LOW_OVRG_CNT_THRSH 0x484 +#define MYKONOS_ADDR_AGC_SLOW_VERYLOW_OVRG_CNT_THRSH 0x485 +#define MYKONOS_ADDR_AGC_SLOW_DIG_SAT_CNT_THRSH 0x486 +#define MYKONOS_ADDR_AGC_SLOW_UPPER0_THRSH_GAIN_STEP 0x487 +#define MYKONOS_ADDR_AGC_SLOW_LOWER0_THRSH_GAIN_STEP 0x488 +#define MYKONOS_ADDR_AGC_SLOW_UPPER1_THRSH_GAIN_STEP 0x489 +#define MYKONOS_ADDR_AGC_SLOW_LOWER1_THRSH_GAIN_STEP 0x48A +#define MYKONOS_ADDR_AGC_SLOW_GAIN_UPDATE_CNT_1 0x48B +#define MYKONOS_ADDR_AGC_SLOW_GAIN_UPDATE_CNT_2 0x48C +#define MYKONOS_ADDR_AGC_SLOW_GAIN_UPDATE_CNT_3 0x48D +#define MYKONOS_ADDR_AGC_SLOW_LOOP_CFG 0x48E +#define MYKONOS_ADDR_AGC_SLOW_POWER_THRSH 0x48F +#define MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_LOCK_LEV_THRSH 0x490 + +#define MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_ULB_CNT_THRSH 0x491 +#define MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_LLB_CNT_THRSH 0x492 +#define MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_ADC_HIGH_OVRG_CNT_THRSH 0x493 +#define MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_ADC_LOW_OVRG_CNT_THRSH 0x494 +#define MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_ADC_VERYLOW_OVRG_CNT_THRSH 0x495 + +#define MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_DIG_SAT_CNT_THRSH 0x496 +#define MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_UPPER0_THRSH_GAIN_STEP 0x497 +#define MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_LOWER0_THRSH_GAIN_STEP 0x498 +#define MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_UPPER1_THRSH_GAIN_STEP 0x499 +#define MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_LOWER1_THRSH_GAIN_STEP 0x49A +#define MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_GAIN_UPDATE_CTR_1 0x49B +#define MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_GAIN_UPDATE_CTR_2 0x49C +#define MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_GAIN_UPDATE_CTR_3 0x49D +#define MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_LOOP_CFG 0x49E +#define MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_POWER_THRSH 0x49F +#define MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_UL_SIG_POW_MEAS_DEL_1 0x4A0 +#define MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_UL_SIG_POW_MEAS_DEL_2 0x4A1 +#define MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_UL_SIG_POW_MEAS_DUR_1 0x4A2 +#define MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_UL_SIG_POW_MEAS_DUR_2 0x4A3 + +/* Mykonos Gain Control Read Registers */ +#define MYKONOS_ADDR_GAIN_CTL_CHANNEL_1 0x4B0 +#define MYKONOS_ADDR_GAIN_CTL_FAST_ATTK_STATE 0x4B1 +#define MYKONOS_ADDR_GAIN_CTL_SLOW_LOOP_STATE 0x4B2 +#define MYKONOS_ADDR_GAIN_CTL_CHANNEL_2 0x4B3 +#define MYKONOS_ADDR_GAIN_CTL_OVRG_SIGS_CHANNEL_1 0x4B4 +#define MYKONOS_ADDR_GAIN_CTL_OVRG_SIGS_CHANNEL_2 0x4B5 +#define MYKONOS_ADDR_GAIN_CTL_ORX_SNRX_GAIN 0x4B6 +#define MYKONOS_ADDR_GAIN_CTL_ORX_SNRX_LOOP_STATE 0x4B7 +#define MYKONOS_ADDR_GAIN_CTL_ORX_SNRX_OVRG_SIGS 0x4B8 + +/* Mykonos Rx Data Path Overrange Registers */ +#define MYKONOS_ADDR_RX_OVRG_DATAPATH_OVRFLW 0x4B9 +#define MYKONOS_ADDR_RX_OVRG_ORX_SNRX_DATAPATH_OVRFLW 0x4BA + +/* Mykonos RSSI Measurement Registers and Dec Power Measurement Registers*/ +#define MYKONOS_ADDR_RSSI_MEAS_DURATION_0_1 0x4C0 +#define MYKONOS_ADDR_RSSI_MEAS_DURATION_2_3 0x4C1 +#define MYKONOS_ADDR_RSSI_CFG 0x4C6 +#define MYKONOS_DEC_POWER_CONFIG_1 0x4C7 +#define MYKONOS_DEC_POWER_CONFIG_2 0x4C8 +#define MYKONOS_ADDR_DPD_SNF_RSSI_CFG 0x4CF +#define MYKONOS_ADDR_DPD_RSSI_CFG 0x4D6 +#define MYKONOS_SNIFFER_DEC_POWER_CONFIG_1 0x4D7 +#define MYKONOS_SNIFFER_DEC_POWER_CONFIG_2 0x4D8 +#define MYKONOS_CH1_DECIMATED_PWR 0x4DE +#define MYKONOS_CH2_DECIMATED_PWR 0x4DF +#define MYKONOS_SNIFFER_DECIMATED_PWR 0x4E6 + +#define MYKONOS_ADDR_DIGITAL_GAIN_CONFIG 0x4F0 +#define MYKONOS_ADDR_DPD_SNIFFER_DIGITAL_GAIN_CONFIG 0x4F1 +#define MYKONOS_ADDR_GAIN_TABLE_ADDR 0x500 +#define MYKONOS_ADDR_GAIN_TABLE_RX1_FE_GAIN 0x501 +#define MYKONOS_ADDR_GAIN_TABLE_RX1_EXT_CTL 0x502 +#define MYKONOS_ADDR_GAIN_TABLE_RX1_DIG_GAIN 0x503 +#define MYKONOS_ADDR_GAIN_TABLE_RX2_FE_GAIN 0x504 +#define MYKONOS_ADDR_GAIN_TABLE_RX2_EXT_CTL 0x505 +#define MYKONOS_ADDR_GAIN_TABLE_RX2_DIG_GAIN 0x506 +#define MYKONOS_ADDR_GAIN_TABLE_RX3_FE_GAIN 0x507 +#define MYKONOS_ADDR_GAIN_TABLE_RX3_LNA_ENAB 0x508 +#define MYKONOS_ADDR_GAIN_TABLE_RX3_DIG_GAIN 0x509 +#define MYKONOS_ADDR_GAIN_TABLE_CONFIGURATION 0x516 +#define MYKONOS_ADDR_CH3_GAIN_TABLE_CONFIGURATION 0x517 +#define MYKONOS_ADDR_RXFE1_LOCM 0x520 +#define MYKONOS_ADDR_RXFE2_LOCM 0x521 +#define MYKONOS_ADDR_RXLOOPBACK1_CNTRL_1 0x540 +#define MYKONOS_ADDR_RXLOOPBACK2_CNTRL_1 0x541 +#define MYKONOS_ADDR_RX_LOOPBACK1_CNTRL_4 0x546 +#define MYKONOS_ADDR_RX_LOOPBACK2_CNTRL_4 0x547 + +/* Mykonos Overload/Peak Detection Registers */ +#define MYKONOS_ADDR_OVRLD_ADC_OVRLD_CFG 0x580 +#define MYKONOS_ADDR_OVRLD_ADC_OVRLD_UPPER_THRSH 0x581 +#define MYKONOS_ADDR_OVRLD_ADC_OVRLD_LOWER_THRSH 0x582 + +#define MYKONOS_ADDR_OVRLD_PD_DEC_OVRLD_CFG 0x583 +#define MYKONOS_ADDR_OVRLD_PD_DEC_OVRLD_UPPER_THRSH 0x584 +#define MYKONOS_ADDR_OVRLD_PD_DEC_OVRLD_LOWER_THRSH 0x585 +#define MYKONOS_ADDR_OVRLD_PD_DEC_VERYLOW_THRSH 0x586 +#define MYKONOS_ADDR_ORX_SNRX_OVRLD_ADC_OVRLD_CFG 0x587 +#define MYKONOS_ADDR_ORX_SNRX_OVRLD_PD_DEC_OVRLD_CFG 0x58A +#define MYKONOS_ADDR_ORX_SNRX_OVRLD_PD_DEC_OVRLD_UPPER_THRSH 0x58B +#define MYKONOS_ADDR_ORX_SNRX_OVRLD_PD_DEC_OVRLD_LOWER_THRSH 0x58C +#define MYKONOS_ADDR_ORX_SNRX_OVRLD_PD_DEC_OVRLD_VERYLOW_THRSH 0x58D + +#define MYKONOS_ADDR_RX_ADC_FLASH_DELAY 0x5B6 +#define MYKONOS_ADDR_RX_ADC_FLASH_CTRL 0x5B7 +#define MYKONOS_ADDR_RX_ADC1_PRFL 0x5DD +#define MYKONOS_ADDR_RX_ADC2_PRFL 0x5DE +#define MYKONOS_ADDR_ORX_ADC_PRFL 0x5DF + +#define MYKONOS_ADDR_RFDC_MEASURE_COUNT_1 0x631 +#define MYKONOS_ADDR_RFDC_MEASURE_COUNT_2 0x632 +#define MYKONOS_ADDR_RFDC_PROGRAM_SHIFT 0x635 +#define MYKONOS_ADDR_RFDC_CONFIG2 0x636 +#define MYKONOS_DPD_Sniffer_RFDC_CAL_TRACK_EN 0x642 +#define MYKONOS_ADDR_RFDC_SNF_MEASURE_COUNT_1 0x644 +#define MYKONOS_ADDR_RFDC_SNF_MEASURE_COUNT_2 0x645 +#define MYKONOS_ADDR_RFDC_ORX_MEASURE_COUNT_1 0x650 +#define MYKONOS_ADDR_RFDC_ORX_MEASURE_COUNT_2 0x651 +#define MYKONOS_ADDR_DIGITAL_DC_MIN_CAL_IDX 0x63A +#define MYKONOS_ADDR_DIGITAL_DC_OFFSET_SHIFT 0x674 +#define MYKONOS_ADDR_DIGITAL_DC_OFFSET_CONFIG 0x676 +#define MYKONOS_DIGITAL_DC_OFFSET_CH3_TRACKING 0x67A +#define MYKONOS_ADDR_DIGITAL_DC_OFFSET_SNF 0x67C +#define MYKONOS_ADDR_DIGITAL_DC_OFFSET_CH3_DPD_M_SHIFT 0x67D + +#define MYKONOS_ADDR_RX_GAIN_COMP_DELAY 0x710 +#define MYKONOS_ADDR_RX1_GAIN_COMP_OFFSET 0x711 +#define MYKONOS_ADDR_RX2_GAIN_COMP_OFFSET 0x712 +#define MYKONOS_ADDR_RX_GAIN_COMP_CFG 0x713 +#define MYKONOS_ADDR_RX_SLCR_PIN_CFG 0x714 +#define MYKONOS_ADDR_DPD_SNF_RX_GAIN_COMP_DELAY 0x715 +#define MYKONOS_ADDR_DPD_SNF_RX_GAIN_COMP_OFFSET 0x716 +#define MYKONOS_ADDR_DPD_SNF_RX_GAIN_COMP_CFG 0x717 +#define MYKONOS_ADDR_DPD_SNF_RX_SLCR_PIN_CFG 0x718 + +#define MYKONOS_ADDR_FLOATING_POINT_CFG 0x750 +#define MYKONOS_ADDR_FLOATING_POINT_RX_CTRL 0x751 +#define MYKONOS_ADDR_FLOATING_POINT_ORX_CTRL 0x752 + + +#define MYKONOS_ADDR_SNRX_LNA_BIAS_C 0x81B + + +#define MYKONOS_ADDR_ORX_ADC_FLASH_DELAY 0x846 +#define MYKONOS_ADDR_ORX_ADC_FLASH_CTRL 0x847 + +#define MYKONOS_ADDR_TX_FILTER_CONFIGURATION 0x910 +#define MYKONOS_ADDR_TX1_ATTENUATION_0_READBACK 0x940 +#define MYKONOS_ADDR_TX1_ATTENUATION_1_READBACK 0x941 +#define MYKONOS_ADDR_TX2_ATTENUATION_0_READBACK 0x942 +#define MYKONOS_ADDR_TX2_ATTENUATION_1_READBACK 0x943 +#define MYKONOS_ADDR_TX_FILTER_OVERFLOW 0x950 + +/* Mykonos PA Protection Block Registers */ +#define MYKONOS_ADDR_PA_PROTECTION_CONFIGURATION 0x955 +#define MYKONOS_ADDR_PA_PROTECTION_ATTEN_CONTROL 0x956 +#define MYKONOS_ADDR_PA_PROTECTION_THRESHOLD_LSB 0x957 +#define MYKONOS_ADDR_PA_PROTECTION_THRESHOLD_MSB 0x958 +#define MYKONOS_ADDR_PA_PROTECTION_POWER_READBACK_LSB 0x959 +#define MYKONOS_ADDR_PA_PROTECTION_POWER_READBACK_MSB 0x95A +#define MYKONOS_ADDR_TX1_ATTENUATION_0 0x960 +#define MYKONOS_ADDR_TX1_ATTENUATION_1 0x961 +#define MYKONOS_ADDR_TX2_ATTENUATION_0 0x962 +#define MYKONOS_ADDR_TX2_ATTENUATION_1 0x963 +#define MYKONOS_ADDR_TX1_GAIN_0 0x967 +#define MYKONOS_ADDR_TX1_GAIN_1 0x968 +#define MYKONOS_ADDR_TX1_GAIN_2 0x969 +#define MYKONOS_ADDR_TX2_GAIN_0 0x96A +#define MYKONOS_ADDR_TX2_GAIN_1 0x96B +#define MYKONOS_ADDR_TX2_GAIN_2 0x96C +#define MYKONOS_ADDR_TX_INCR_DECR_WORD 0x96D +#define MYKONOS_ADDR_TX_TPC_CONFIG 0x96E +#define MYKONOS_ADDR_TX_TPC_GPIO_CFG 0x96F + +#define MYKONOS_ADDR_TX_ABBF_FREQ_CAL_NCO_I_MSB 0x9CB +#define MYKONOS_ADDR_TX_ABBF_FREQ_CAL_NCO_I_LSB 0x9CC +#define MYKONOS_ADDR_TX_ABBF_FREQ_CAL_NCO_Q_MSB 0x9CD +#define MYKONOS_ADDR_TX_ABBF_FREQ_CAL_NCO_Q_LSB 0x9CE + +/* Mykonos GPIO Registers */ +#define MYKONOS_ADDR_GPIO_3V3_DIR_CTL_7_0 0xB00 +#define MYKONOS_ADDR_GPIO_3V3_DIR_CTL_15_8 0xB01 +#define MYKONOS_ADDR_GPIO_3V3_SPI_SRC_7_0 0xB02 +#define MYKONOS_ADDR_GPIO_3V3_SPI_SRC_15_8 0xB03 +#define MYKONOS_ADDR_GPIO_3V3_SPI_READ_7_0 0xB04 +#define MYKONOS_ADDR_GPIO_3V3_SPI_READ_15_8 0xB05 +#define MYKONOS_ADDR_GPIO_3V3_LSB_SRC_CTL 0xB06 +#define MYKONOS_ADDR_GPIO_3V3_MSB_SRC_CTL 0xB07 + +#define MYKONOS_ADDR_GPIO_DIR_CTL_7_0 0xB20 +#define MYKONOS_ADDR_GPIO_DIR_CTL_15_8 0xB21 +#define MYKONOS_ADDR_GPIO_DIR_CTL_18_16 0xB22 +#define MYKONOS_ADDR_GPIO_SPI_SRC_7_0 0xB23 +#define MYKONOS_ADDR_GPIO_SPI_SRC_15_8 0xB24 +#define MYKONOS_ADDR_GPIO_SPI_SRC_18_16 0xB25 +#define MYKONOS_ADDR_GPIO_SPI_READ_7_0 0xB26 +#define MYKONOS_ADDR_GPIO_SPI_READ_15_8 0xB27 +#define MYKONOS_ADDR_GPIO_SPI_READ_18_16 0xB28 +#define MYKONOS_ADDR_SOURCE_CONTROL_LOWER_BYTE 0xB29 +#define MYKONOS_ADDR_SOURCE_CONTROL_UPPER_BYTE 0xB2A +#define MYKONOS_ADDR_SOURCE_CONTROL_EXTRA_BITS 0xB2B + +#define MYKONOS_ADDR_GPIO_MONITOR_INDEX 0xB40 +#define MYKONOS_ADDR_GPIO_MONITOR_ENABLE 0xB41 + +#define MYKONOS_ADDR_GP_INTERRUPT_MASK_1 0xB42 +#define MYKONOS_ADDR_GP_INTERRUPT_MASK_0 0xB43 +#define MYKONOS_ADDR_GP_INTERRUPT_READ_1 0xB44 +#define MYKONOS_ADDR_GP_INTERRUPT_READ_0 0xB45 + +#define MYKONOS_ADDR_PDAUXDAC_MANUAL_CONTROL_5_0 0xB73 +#define MYKONOS_ADDR_PDAUXDAC_MANUAL_CONTROL_9_6 0xB74 +#define MYKONOS_ADDR_PDAUXDAC_MANUAL_IN_5_0 0xB75 +#define MYKONOS_ADDR_PDAUXDAC_MANUAL_IN_9_6 0xB76 +#define MYKONOS_ADDR_AUX_DAC_LATCH_CONTROL 0xB9F +#define MYKONOS_ADDR_AUXDAC_0_WORD_MSB 0xBA0 + +#define MYKONOS_ADR_AUX_ADC_CLOCK_DIVIDE 0xBC0 +#define MYKONOS_ADDR_AUX_ADC_CFG 0xBC1 +#define MYKONOS_ADDR_AUX_ADC_READ_MSB 0xBC2 +#define MYKONOS_ADDR_AUX_ADC_READ_LSB 0xBC3 +#define MYKONOS_ADDR_AUX_ADC_SEL 0xBC4 +#define MYKONOS_ADDR_AUX_ADC_BUFFER_CONFIG_0 0xBC5 +#define MYKONOS_ADDR_AUX_ADC_BUFFER_CONFIG_1 0xBC6 + +#define MYKONOS_ADDR_TEMP_SENSOR_OFFSET 0xBE0 +#define MYKONOS_ADDR_TEMP_SENSOR_CONTROL_LSB 0xBE1 +#define MYKONOS_ADDR_TEMP_SENSOR_CONTROL_MSB 0xBE2 +#define MYKONOS_ADDR_TEMP_SENSOR_READ 0xBE3 +#define MYKONOS_ADDR_TEMP_SENSOR_CONFIG 0xBE4 + +#define MYKONOS_ADDR_DIGITAL_TEST_BYTE_0 0xC40 + +/* ARM subsystem registers */ +#define MYKONOS_ADDR_ARM_CTL_1 0xD00 +#define MYKONOS_ADDR_ARM_CTL_2 0xD01 +#define MYKONOS_ADDR_ARM_ADDR_BYTE_0 0xD02 +#define MYKONOS_ADDR_ARM_ADDR_BYTE_1 0xD03 +#define MYKONOS_ADDR_ARM_DATA_BYTE_0 0xD04 +#define MYKONOS_ADDR_ARM_DATA_BYTE_1 0xD05 +#define MYKONOS_ADDR_ARM_DATA_BYTE_2 0xD06 +#define MYKONOS_ADDR_ARM_DATA_BYTE_3 0xD07 +#define MYKONOS_ADDR_ARM_CLK_CTL 0xD08 +#define MYKONOS_ADDR_AHB_SPI_BRIDGE 0xD09 +#define MYKONOS_ADDR_ARM_BOOT_ADDR_BYTE_0 0xD0A +#define MYKONOS_ADDR_ARM_BOOT_ADDR_BYTE_1 0xD0B +#define MYKONOS_ADDR_ARM_BOOT_ADDR_BYTE_2 0xD0C +#define MYKONOS_ADDR_ARM_BOOT_ADDR_BYTE_3 0xD0D +#define MYKONOS_ADDR_ARM_STACK_PTR_BYTE_0 0xD0E +#define MYKONOS_ADDR_ARM_STACK_PTR_BYTE_1 0xD0F +#define MYKONOS_ADDR_ARM_STACK_PTR_BYTE_2 0xD10 +#define MYKONOS_ADDR_ARM_STACK_PTR_BYTE_3 0xD11 +#define MYKONOS_ADDR_ARM_BRIDGE_CLK_CTL 0xD14 + +/* ARM mailbox registers */ +#define MYKONOS_ADDR_ARM_CMD 0xD30 +#define MYKONOS_ADDR_ARM_EXT_CMD_BYTE_1 0xD31 +#define MYKONOS_ADDR_ARM_EXT_CMD_BYTE_2 0xD32 +#define MYKONOS_ADDR_ARM_EXT_CMD_BYTE_3 0xD33 +#define MYKONOS_ADDR_ARM_EXT_CMD_BYTE_4 0xD34 +#define MYKONOS_ADDR_ARM_EXT_CMD_BYTE_5 0xD35 +#define MYKONOS_ADDR_ARM_EXT_CMD_BYTE_6 0xD36 +#define MYKONOS_ADDR_ARM_EXT_CMD_BYTE_7 0xD37 +#define MYKONOS_ADDR_ARM_CMD_STATUS_0 0xD38 +#define MYKONOS_ADDR_ARM_CMD_STATUS_1 0xD39 +#define MYKONOS_ADDR_ARM_CMD_STATUS_2 0xD3A +#define MYKONOS_ADDR_ARM_CMD_STATUS_3 0xD3B +#define MYKONOS_ADDR_ARM_CMD_STATUS_4 0xD3C +#define MYKONOS_ADDR_ARM_CMD_STATUS_5 0xD3D +#define MYKONOS_ADDR_ARM_CMD_STATUS_6 0xD3E +#define MYKONOS_ADDR_ARM_CMD_STATUS_7 0xD3F + +#define MYKONOS_ADDR_ARM_OPCODE_STATE_0 0xD40 +#define MYKONOS_ADDR_ARM_OPCODE_STATE_1 0xD41 +#define MYKONOS_ADDR_ARM_OPCODE_STATE_2 0xD42 +#define MYKONOS_ADDR_ARM_OPCODE_STATE_3 0xD43 +#define MYKONOS_ADDR_ARM_OPCODE_STATE_4 0xD44 +#define MYKONOS_ADDR_ARM_OPCODE_STATE_5 0xD45 +#define MYKONOS_ADDR_ARM_OPCODE_STATE_6 0xD46 +#define MYKONOS_ADDR_ARM_OPCODE_STATE_7 0xD47 + +/* Mykonos Power-Down Override Control Registers */ +#define MYKONOS_ADDR_TX_PD_OVERRIDE_CONTROL_7_0 0xD89 + +/* Mykonos Observation Framer Registers */ +#define MYKONOS_ADDR_OBS_FRAMER_RESET 0xDC0 +#define MYKONOS_ADDR_OBS_FRAMER_CLK_EN 0xDC1 +#define MYKONOS_ADDR_OBS_FRAMER_ADDR 0xDC2 +#define MYKONOS_ADDR_OBS_FRAMER_DATA 0xDC3 +#define MYKONOS_ADDR_OBS_FRAMER_WRITE_EN 0xDC4 +#define MYKONOS_ADDR_OBS_FRAMER_SYSREF_FIFO_EN 0xDC5 +#define MYKONOS_ADDR_OBS_FRAMER_CONFIG_F 0xDC6 +#define MYKONOS_ADDR_OBS_FRAMER_LANE_CTL 0xDC7 +#define MYKONOS_ADDR_OBS_FRAMER_ADC_XBAR_SEL 0xDC8 +#define MYKONOS_ADDR_OBS_FRAMER_LANE_XBAR_SEL 0xDC9 +#define MYKONOS_ADDR_OBS_FRAMER_CONFIG_LOOPBACK_XBAR_REV 0xDCA +#define MYKONOS_ADDR_OBS_FRAMER_SYNCN_FILT 0xDCB +#define MYKONOS_ADDR_OBS_FRAMER_LMFC_F_OFFSET 0xDCC +#define MYKONOS_ADDR_OBS_FRAMER_LMFC_K_OFFSET 0xDCD +#define MYKONOS_ADDR_OBS_FRAMER_TEST_CNTR_CTL 0xDCE +#define MYKONOS_ADDR_OBS_FRAMER_STATUS_STRB 0xDCF +#define MYKONOS_ADDR_OBS_FRAMER_STATUS 0xDD0 +#define MYKONOS_ADDR_OBS_FRAMER_SYSREF_TO_LMFC_CNTR_STAT 0xDD1 +#define MYKONOS_ADDR_OBS_FRAMER_SYSREF_TO_LMFC_ERR_MARGIN 0xDD2 +#define MYKONOS_ADDR_OBS_FRAMER_LANE_FIFO_STRB 0xDD3 +#define MYKONOS_ADDR_OBS_FRAMER_LANE0_FIFO_RDWR_ADDR 0xDD4 +#define MYKONOS_ADDR_OBS_FRAMER_LANE1_FIFO_RDWR_ADDR 0xDD5 +#define MYKONOS_ADDR_OBS_FRAMER_LANE2_FIFO_RDWR_ADDR 0xDD6 +#define MYKONOS_ADDR_OBS_FRAMER_LANE3_FIFO_RDWR_ADDR 0xDD7 +#define MYKONOS_ADDR_OBS_FRAMER_PRBS10_CTL 0xDD8 +#define MYKONOS_ADDR_OBS_FRAMER_PRBS20_CTL 0xDD9 +#define MYKONOS_ADDR_OBS_FRAMER_PATTERN_GEN_EN 0xDDA +#define MYKONOS_ADDR_OBS_FRAMER_PATTERN_GEN_7_TO_0 0xDDB +#define MYKONOS_ADDR_OBS_FRAMER_PATTERN_GEN_15_TO_8 0xDDC +#define MYKONOS_ADDR_OBS_FRAMER_PATTERN_GEN_19_TO_16 0xDDD +#define MYKONOS_ADDR_OBS_FRAMER_CONFIG_JTX_GEN 0xDDE +#define MYKONOS_ADDR_OBS_FRAMER_LANE_DATA_CTL 0xDDF +#define MYKONOS_ADDR_OBS_FRAMER_DATA_SAMPLE_CTL 0xDE0 + +#define MYKONOS_ADDR_PFIR_COEFF_CTL 0xDFF +#define MYKONOS_ADDR_PFIR_COEFF_DATA 0xE00 +#define MYKONOS_ADDR_PFIR_COEFF_ADDR 0xE01 + +/* ARM memory */ +#define MYKONOS_ADDR_ARM_START_PROG_ADDR 0x01000000 +#define MYKONOS_ADDR_ARM_END_PROG_ADDR 0x01017FFF +#define MYKONOS_ADDR_ARM_START_DATA_ADDR 0x20000000 +#define MYKONOS_ADDR_ARM_END_DATA_ADDR 0x2000FFFF +#define MYKONOS_ADDR_ARM_BUILD_CHKSUM_ADDR 0x01017FE0 +#define MYKONOS_ADDR_ARM_CALC_CHKSUM_ADDR 0x01017FE4 +#define MYKONOS_ADDR_ARM_VERSION 0x01000128 +#define MYKONOS_ARM_ABORT_OPCODE 0x00 +#define MYKONOS_ARM_RUNINIT_OPCODE 0x02 +#define MYKONOS_ARM_RADIOON_OPCODE 0x04 +#define MYKONOS_ARM_WRITECFG_OPCODE 0x06 +#define MYKONOS_ARM_READCFG_OPCODE 0x08 +#define MYKONOS_ARM_SET_OPCODE 0x0A +#define MYKONOS_ARM_GET_OPCODE 0x0C + +#define MYKONOS_ARM_OBJECTID_DPDINIT_CONFIG 0x0F +#define MYKONOS_ARM_OBJECTID_CLGCINIT_CONFIG 0x10 +#define MYKONOS_ARM_OBJECTID_VSWRINIT_CONFIG 0x11 +#define MYKONOS_ARM_OBJECTID_DPDCONFIG 0x24 +#define MYKONOS_ARM_DPD_RESET 0x02 +#define MYKONOS_ARM_OBJECTID_GS_TRACKCALS 0x66 +#define MYKONOS_ARM_OBJECTID_RXQEC_TRACKING 0x20 +#define MYKONOS_ARM_OBJECTID_ORXQEC_TRACKING 0x21 +#define MYKONOS_ARM_OBJECTID_TXLOL_TRACKING 0x22 +#define MYKONOS_ARM_OBJECTID_TXQEC_TRACKING 0x23 +#define MYKONOS_ARM_OBJECTID_CLGCCONFIG 0x25 +#define MYKONOS_ARM_OBJECTID_VSWRCONFIG 0x26 +#define MYKONOS_ARM_OBJECTID_CAL_STATUS 0x42 +#define MYKONOS_ARM_OBJECTID_INIT_CAL_DONE 0x43 +#define MYKONOS_ARM_OBJECTID_ORX_MODE 0x61 +#define MYKONOS_ARM_OBJECTID_TRACKING_CAL_SUSPEND_RESUME 0x65 +#define MYKONOS_ARM_OBJECTID_TRACKING_CAL_CONTROL 0x66 +#define MYKONOS_ARM_OBJECTID_TRACKING_CAL_PENDING 0x67 +#define MYKONOS_ARM_OBJECTID_RADIO_CONTROL 0x81 +#define MYKONOS_ARM_OBJECTID_CALSCHEDULER 0x83 + +#define MYKONOS_ARM_SYSTEMSTATE_POWERUP 0x00 +#define MYKONOS_ARM_SYSTEMSTATE_READY 0x01 +#define MYKONOS_ARM_SYSTEMSTATE_IDLE 0x02 +#define MYKONOS_ARM_SYSTEMSTATE_RADIO_ON 0x03 + +#define ORX_TRIGGER_SIGNALID 0x00 +#define ORX_MODE_0_SIGNALID 0x01 +#define ORX_MODE_1_SIGNALID 0x02 +#define ORX_MODE_2_SIGNALID 0x03 +#define RX1_ENABLE_ACK_SIGNALID 0x04 +#define RX2_ENABLE_ACK_SIGNALID 0x05 +#define TX1_ENABLE_ACK_SIGNALID 0x06 +#define TX2_ENABLE_ACK_SIGNALID 0x07 +#define ORX1_ENABLE_ACK_SIGNALID 0x08 +#define ORX2_ENABLE_ACK_SIGNALID 0x09 +#define SRX_ENABLE_ACK_SIGNALID 0x0A +#define TX_OBS_SELECT_SIGNALID 0x0B + +#define DISABLE_DPD_ACTUATOR 0x03 +#define ENABLE_DPD_ACTUATOR 0x04 +#define SET_CLGC_DESIRED_GAIN_1 0x05 +#define SET_CLGC_DESIRED_GAIN_2 0x06 +#define SET_PATH_DELAY 0x08 + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/datalink814_ge/src/hardware/mykonos/mykonos_user.c b/datalink814_ge/src/hardware/mykonos/mykonos_user.c new file mode 100644 index 0000000..5cedb57 --- /dev/null +++ b/datalink814_ge/src/hardware/mykonos/mykonos_user.c @@ -0,0 +1,176 @@ +/** + * \file mykonos_user.c + * \brief Contains Mykonos default gain table values for Rx, ObsRx, and SnRx + * + * Mykonos API version: 1.5.2.3566 + */ + +/** +* \page Disclaimer Legal Disclaimer +* Copyright 2015-2017 Analog Devices Inc. +* Released under the AD9371 API license, for more information see the "LICENSE.txt" file in this zip file. +* +*/ + +#include +#include "t_mykonos.h" +#include "mykonos_user.h" + +/** + * \brief Default Rx gain table settings + */ +uint8_t RxGainTable [61][4] = +{ + /* Order: {FE table, External Ctl, Digital Gain/Atten, Enable Atten} */ + {0, 0, 0, 0}, /* Gain index 255 */ + {3, 0, 2, 1}, /* Gain index 254 */ + {6, 0, 3, 1}, /* Gain index 253 */ + {10, 0, 0, 0}, /* Gain index 252 */ + {13, 0, 1, 1}, /* Gain index 251 */ + {16, 0, 0, 0}, /* Gain index 250 */ + {18, 0, 3, 1}, /* Gain index 249 */ + {21, 0, 1, 1}, /* Gain index 248 */ + {23, 0, 3, 1}, /* Gain index 247 */ + {25, 0, 4, 1}, /* Gain index 246 */ + {28, 0, 0, 0}, /* Gain index 245 */ + {30, 0, 0, 0}, /* Gain index 244 */ + {31, 0, 5, 1}, /* Gain index 243 */ + {33, 0, 4, 1}, /* Gain index 242 */ + {35, 0, 2, 1}, /* Gain index 241 */ + {37, 0, 0, 0}, /* Gain index 240 */ + {38, 0, 4, 1}, /* Gain index 239 */ + {39, 0, 7, 1}, /* Gain index 238 */ + {41, 0, 2, 1}, /* Gain index 237 */ + {42, 0, 4, 1}, /* Gain index 236 */ + {43, 0, 6, 1}, /* Gain index 235 */ + {44, 0, 8, 1}, /* Gain index 234 */ + {45, 0, 9, 1}, /* Gain index 233 */ + {46, 0, 10, 1}, /* Gain index 232 */ + {47, 0, 10, 1}, /* Gain index 231 */ + {48, 0, 9, 1}, /* Gain index 230 */ + {49, 0, 8, 1}, /* Gain index 229 */ + {50, 0, 6, 1}, /* Gain index 228 */ + {51, 0, 3, 1}, /* Gain index 227 */ + {51, 0, 13, 1}, /* Gain index 226 */ + {52, 0, 9, 1}, /* Gain index 225 */ + {53, 0, 5, 1}, /* Gain index 224 */ + {53, 0, 15, 1}, /* Gain index 223 */ + {54, 0, 9, 1}, /* Gain index 222 */ + {54, 0, 19, 1}, /* Gain index 221 */ + {55, 0, 11, 1}, /* Gain index 220 */ + {55, 0, 21, 1}, /* Gain index 219 */ + {56, 0, 11, 1}, /* Gain index 218 */ + {56, 0, 21, 1}, /* Gain index 217 */ + {57, 0, 9, 1}, /* Gain index 216 */ + {57, 0, 19, 1}, /* Gain index 215 */ + {57, 0, 29, 1}, /* Gain index 214 */ + {58, 0, 12, 1}, /* Gain index 213 */ + {58, 0, 22, 1}, /* Gain index 212 */ + {58, 0, 32, 1}, /* Gain index 211 */ + {59, 0, 11, 1}, /* Gain index 210 */ + {59, 0, 21, 1}, /* Gain index 209 */ + {59, 0, 31, 1}, /* Gain index 208 */ + {59, 0, 41, 1}, /* Gain index 207 */ + {60, 0, 13, 1}, /* Gain index 206 */ + {60, 0, 23, 1}, /* Gain index 205 */ + {60, 0, 33, 1}, /* Gain index 204 */ + {60, 0, 43, 1}, /* Gain index 203 */ + {60, 0, 53, 1}, /* Gain index 202 */ + {61, 0, 14, 1}, /* Gain index 201 */ + {61, 0, 24, 1}, /* Gain index 200 */ + {61, 0, 34, 1}, /* Gain index 199 */ + {61, 0, 44, 1}, /* Gain index 198 */ + {61, 0, 54, 1}, /* Gain index 197 */ + {61, 0, 64, 1}, /* Gain index 196 */ + {61, 0, 74, 1}, /* Gain index 195 */ +}; + +/** + * \brief Default ORx gain table settings + */ +uint8_t ORxGainTable [19][4] = +{ + /* Order: {FE table, External Ctl, Digital Gain/Atten, Enable Atten} */ + {0, 0, 0, 0}, /* Gain index 255 */ + {7, 0, 0, 0}, /* Gain index 254 */ + {13, 0, 1, 1}, /* Gain index 253 */ + {18, 0, 3, 1}, /* Gain index 252 */ + {23, 0, 3, 1}, /* Gain index 251 */ + {28, 0, 0, 0}, /* Gain index 250 */ + {32, 0, 0, 0}, /* Gain index 249 */ + {35, 0, 2, 1}, /* Gain index 248 */ + {38, 0, 4, 1}, /* Gain index 247 */ + {41, 0, 2, 1}, /* Gain index 246 */ + {43, 0, 6, 1}, /* Gain index 245 */ + {46, 0, 0, 0}, /* Gain index 244 */ + {47, 0, 10, 1}, /* Gain index 243 */ + {49, 0, 8, 1}, /* Gain index 242 */ + {51, 0, 3, 1}, /* Gain index 241 */ + {52, 0, 9, 1}, /* Gain index 240 */ + {53, 0, 14, 1}, /* Gain index 239 */ + {54, 0, 18, 1}, /* Gain index 238 */ + {56, 0, 0, 0} /* Gain index 237 */ + +}; + +/** + * \brief Default SnRx gain table settings + */ +uint8_t SnRxGainTable [53][4] = +{ + /* Order: {FE table, LNA Bypass, Digital Gain/Atten, Enable Atten} */ + {0, 0, 0, 0}, /* Gain index 255 */ + {1, 0, 7, 1}, /* Gain index 254 */ + {3, 0, 1, 0}, /* Gain index 253 */ + {3, 0, 15, 1}, /* Gain index 252 */ + {5, 0, 0, 0}, /* Gain index 251 */ + {6, 0, 2, 1}, /* Gain index 250 */ + {7, 0, 2, 1}, /* Gain index 249 */ + {8, 0, 12, 1}, /* Gain index 248 */ + {9, 0, 7, 1}, /* Gain index 247 */ + {11, 0, 1, 0}, /* Gain index 246 */ + {11, 0, 15, 1},/* Gain index 245 */ + {13, 0, 1, 0}, /* Gain index 244 */ + {14, 0, 2, 0}, /* Gain index 243 */ + {14, 0, 10, 1},/* Gain index 242 */ + {15, 0, 0, 0}, /* Gain index 241 */ + {15, 0, 20, 1},/* Gain index 240 */ + {16, 0, 2, 1}, /* Gain index 239 */ + {16, 0, 22, 1},/* Gain index 238 */ + {17, 0, 1, 0}, /* Gain index 237 */ + {17, 0, 15, 1},/* Gain index 236 */ + {17, 0, 35, 1},/* Gain index 235 */ + {17, 0, 55, 1},/* Gain index 234 */ + {18, 0, 7, 1}, /* Gain index 233 */ + {18, 0, 27, 1},/* Gain index 232 */ + { 6, 1, 7, 1}, /* Gain index 231 */ + { 7, 1, 7, 1}, /* Gain index 230 */ + { 8, 1, 17, 1}, /* Gain index 229 */ + { 9, 1, 12, 1}, /* Gain index 228 */ + {11, 1, 0, 0}, /* Gain index 227 */ + {12, 1, 3, 1}, /* Gain index 226 */ + {13, 1, 0, 0}, /* Gain index 225 */ + {14, 1, 1, 0}, /* Gain index 224 */ + {14, 1, 15, 1},/* Gain index 223 */ + {15, 1, 5, 1}, /* Gain index 222 */ + {15, 1, 25, 1},/* Gain index 221 */ + {16, 1, 7, 1}, /* Gain index 220 */ + {16, 1, 27, 1},/* Gain index 219 */ + {17, 1, 0, 0}, /* Gain index 218 */ + {17, 1, 20, 1},/* Gain index 217 */ + {17, 1, 40, 1},/* Gain index 216 */ + {17, 1, 60, 1},/* Gain index 215 */ + {18, 1, 12, 1},/* Gain index 214 */ + {18, 1, 32, 1},/* Gain index 213 */ + {18, 1, 52, 1},/* Gain index 212 */ + {18, 1, 72, 1},/* Gain index 211 */ + {18, 1, 92, 1},/* Gain index 210 */ + {19, 1, 1, 0}, /* Gain index 209 */ + {19, 1, 15, 1},/* Gain index 208 */ + {19, 1, 35, 1},/* Gain index 207 */ + {19, 1, 55, 1},/* Gain index 206 */ + {19, 1, 75, 1},/* Gain index 205 */ + {19, 1, 95, 1},/* Gain index 204 */ + {19, 1, 115, 1}/* Gain index 203 */ +}; + diff --git a/datalink814_ge/src/hardware/mykonos/mykonos_user.h b/datalink814_ge/src/hardware/mykonos/mykonos_user.h new file mode 100644 index 0000000..2875837 --- /dev/null +++ b/datalink814_ge/src/hardware/mykonos/mykonos_user.h @@ -0,0 +1,85 @@ +/** + * \file mykonos_user.h + * + * \brief Contains macro definitions and global structure declarations for mykonos_user.c + * + * Mykonos API version: 1.5.2.3566 + */ + +/** +* \page Disclaimer Legal Disclaimer +* Copyright 2015-2017 Analog Devices Inc. +* Released under the AD9371 API license, for more information see the "LICENSE.txt" file in this zip file. +* +*/ + +#ifndef _MYKONOSPROFILES_H_ +#define _MYKONOSPROFILES_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* turns verbose messaging on */ +#define MYKONOS_VERBOSE 1 +#define MYK_ENABLE_SPIWRITEARRAY 1 + +/* 3 Bytes per SPI transaction * 341 transactions = ~1024 byte buffer size */ +/* Minimum MYK_SPIWRITEARRAY_BUFFERSIZE = 27 */ +#define MYK_SPIWRITEARRAY_BUFFERSIZE 341 +/* + ***************************************** + * Rx, ObsRx, and Sniffer gain tables + ****************************************** + */ +#define MAX_GAIN_TABLE_INDEX 255 + +#define START_RX_GAIN_INDEX 255 +#define MAX_RX_GAIN_TABLE_NUMINDEXES (START_RX_GAIN_INDEX + 1) +#define MIN_RX_GAIN_TABLE_INDEX 0 + +#define START_ORX_GAIN_INDEX 47 +#define MAX_ORX_GAIN_TABLE_NUMINDEXES (START_ORX_GAIN_INDEX + 1) +#define MIN_ORX_GAIN_TABLE_INDEX (MAX_GAIN_TABLE_INDEX - START_ORX_GAIN_INDEX) + +#define START_SNRX_GAIN_INDEX 127 +#define MAX_SNRX_GAIN_TABLE_NUMINDEXES (START_SNRX_GAIN_INDEX + 1) +#define MIN_SNRX_GAIN_TABLE_INDEX (MAX_GAIN_TABLE_INDEX - START_SNRX_GAIN_INDEX) + +#define START_LOOPBACK_GAIN_INDEX 47 +#define MAX_LOOPBACK_GAIN_TABLE_NUMINDEXES (START_LOOPBACK_GAIN_INDEX + 1) +#define MIN_LOOPBACK_GAIN_TABLE_INDEX (MAX_GAIN_TABLE_INDEX - START_SNRX_GAIN_INDEX) + +extern uint8_t RxGainTable [61][4]; +extern uint8_t ORxGainTable [19][4]; +extern uint8_t SnRxGainTable [53][4]; + + +/* + ******************************************** + * Rx, Sniffer, ObsRx and Tx Profiles limits + ******************************************** + */ +#define MIN_RX_IQRATE_KHZ 15000 /*!< Mykonos minimum IQ rate for the Rx channel, expressed in KHz */ +#define MAX_RX_IQRATE_KHZ 320000 /*!< Mykonos maximum IQ rate for the Rx channel, expressed in KHz */ + +#define MIN_TX_IQRATE_KHZ 15000 /*!< Mykonos minimum IQ rate for the Tx channel, expressed in KHz */ +#define MAX_TX_IQRATE_KHZ 492000 /*!< Mykonos maximum IQ rate for the Tx channel, expressed in KHz */ + +#define MIN_SNIFFER_RFBW_HZ 5000000 /*!< Mykonos minimum Sniffer channel bandwidth expressed in Hz */ +#define MAX_SNIFFER_RFBW_HZ 20000000 /*!< Mykonos maximum Sniffer channel bandwidth expressed in Hz */ + +#define MIN_ORX_RFBW_HZ 5000000 /*!< Mykonos minimum Observation channel bandwidth expressed in Hz */ +#define MAX_ORX_RFBW_HZ 250000000 /*!< Mykonos maximum Observation channel bandwidth expressed in Hz */ + +#define MIN_RX_RFBW_HZ 5000000 /*!< Mykonos minimum Rx channel bandwidth expressed in Hz */ +#define MAX_RX_RFBW_HZ 100000000 /*!< Mykonos maximum Rx channel bandwidth expressed in Hz */ + +#define MIN_TX_RFBW_HZ 20000000 /*!< Mykonos minimum Tx channel bandwidth expressed in Hz */ +#define MAX_TX_RFBW_HZ 250000000 /*!< Mykonos maximum Tx channel bandwidth expressed in Hz */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/datalink814_ge/src/hardware/mykonos/mykonos_version.h b/datalink814_ge/src/hardware/mykonos/mykonos_version.h new file mode 100644 index 0000000..c7f58d2 --- /dev/null +++ b/datalink814_ge/src/hardware/mykonos/mykonos_version.h @@ -0,0 +1,31 @@ +/** + * \file mykonos_version.h + * \brief Contains the version number for the Mykonos API + * + * Mykonos API version: 1.5.2.3566 + */ + +/** +* \page Disclaimer Legal Disclaimer +* Copyright 2015-2017 Analog Devices Inc. +* Released under the AD9371 API license, for more information see the "LICENSE.txt" file in * this zip file. +* +*/ + +#ifndef MYKONOS_VERSION_H_ +#define MYKONOS_VERSION_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#define MYKONOS_CURRENT_SI_VERSION 1 /*!< Mykonos current silicon version */ +#define MYKONOS_CURRENT_MAJOR_VERSION 5 /*!< Mykonos current ARM major version */ +#define MYKONOS_CURRENT_MINOR_VERSION 2 /*!< Mykonos current ARM minor version */ +#define MYKONOS_CURRENT_BUILD_VERSION 3566 /*!< Mykonos current API build version */ + +#ifdef __cplusplus +} +#endif + +#endif /* MYKONOS_VERSION_H_ */ diff --git a/datalink814_ge/src/hardware/mykonos/t_ad9528.h b/datalink814_ge/src/hardware/mykonos/t_ad9528.h new file mode 100644 index 0000000..02cd278 --- /dev/null +++ b/datalink814_ge/src/hardware/mykonos/t_ad9528.h @@ -0,0 +1,194 @@ +/** + * \file t_ad9528.h + * \brief Contains enum and structure data types for all AD9528 function calls + */ + +/** +* \page Disclaimer Legal Disclaimer +* Copyright 2015-2017 Analog Devices Inc. +* Released under the AD9371 API license, for more information see the "LICENSE.txt" file in this zip file. +* +*/ + +#ifndef _AD9528_TYPES_H_ +#define _AD9528_TYPES_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "../common.h" + +/* AD9528 SPI Address defines */ +#define AD9528_ADDR_ADI_SPI_CONFIG_A 0x000 +#define AD9528_ADDR_ADI_SPI_CONFIG_B 0x001 +#define AD9528_ADDR_IO_UPDATE 0x00F + +#define AD9528_ADDR_REF_A_DIVIDER_LSB 0x100 +#define AD9528_ADDR_REF_A_DIVIDER_MSB 0x101 +#define AD9528_ADDR_REF_B_DIVIDER_LSB 0x102 +#define AD9528_ADDR_REF_B_DIVIDER_MSB 0x103 +#define AD9528_ADDR_PLL1_N_DIV_LSB 0x104 +#define AD9528_ADDR_PLL1_N_DIV_MSB 0x105 +#define AD9528_ADDR_PLL1_CHARGEPUMP 0x106 +#define AD9528_ADDR_PLL1_CP_CTRL2 0x107 +#define AD9528_ADDR_INPUT_RECEIVERS1 0x108 +#define AD9528_ADDR_INPUT_RECEIVERS2 0x109 +#define AD9528_ADDR_INPUT_RECEIVERS3 0x10A +#define AD9528_ADDR_PLL1_FASTLOCK 0x10B + +#define AD9528_ADDR_PLL2_CHARGEPUMP 0x200 +#define AD9528_ADDR_PLL2_N_DIV 0x201 +#define AD9528_ADDR_PLL2_CTRL 0x202 +#define AD9528_ADDR_PLL2_VCO_CTRL 0x203 +#define AD9528_ADDR_PLL2_VCO_DIV 0x204 +#define AD9528_ADDR_PLL2_LF_CTRL1 0x205 +#define AD9528_ADDR_PLL2_LF_CTRL2 0x206 +#define AD9528_ADDR_PLL2_RDIV 0x207 +#define AD9528_ADDR_PLL2_REPLICA_CHDIV 0x208 +#define AD9528_ADDR_PLL2_REPLICA_DIV_PHASE 0x209 + +#define AD9528_ADDR_CH_OUT0_CTRL1 0x300 +#define AD9528_ADDR_CH_OUT0_CTRL2 0x301 +#define AD9528_ADDR_CH_OUT0_CHDIV 0x302 +#define AD9528_ADDR_OUTPUT_SYNC 0x32A +#define AD9528_ADDR_MASK_SYNC1 0x32B +#define AD9528_ADDR_MASK_SYNC2 0x32C +#define AD9528_ADDR_EN_OUTPUT_PATH_SEL1 0x32D +#define AD9528_ADDR_EN_OUTPUT_PATH_SEL2 0x32E + +#define AD9528_ADDR_SYSERF_DIV_LSB 0x400 +#define AD9528_ADDR_SYSERF_DIV_MSB 0x401 +#define AD9528_ADDR_SYSREF_CTRL3 0x402 +#define AD9528_ADDR_SYSREF_CTRL4 0x403 +#define AD9528_ADDR_SYSREF_CTRL5 0x404 + +#define AD9528_ADDR_POWERDOWN_CTRL 0x500 +#define AD9528_ADDR_CH_POWERDOWN1 0x501 +#define AD9528_ADDR_CH_POWERDOWN2 0x502 +#define AD9528_ADDR_LDO_ENABLES1 0x503 +#define AD9528_ADDR_LDO_ENABLES2 0x504 +#define AD9528_ADDR_STATUS0_CTRL 0x505 +#define AD9528_ADDR_STATUS1_CTRL 0x506 +#define AD9528_ADDR_STATUS_OE 0x507 +#define AD9528_ADDR_STATUS_READBACK0 0x508 +#define AD9528_ADDR_STATUS_READBACK1 0x509 + + + +///Enum to select what source outputs from each AD9528 output channel +typedef enum +{ + CHANNEL_DIV = 0, PLL1_OUTPUT = 1, //VCXO frequency + SYSREF = 2, + INV_PLL1_OUTPUT = 5 //VCXO inverted +} ad9528outSourceSel_t; + +///Enum to select what output buffer standard is used for the clock outputs +typedef enum +{ + LVDS = 0, LVDS_BOOST = 1, HSTL = 2 +} ad9528outBufferControl_t; + +///Enum to select the clock input buffer mode. +typedef enum +{ + DISABLED = 0, SINGLE_ENDED, NEG_SINGLE_ENDED, DIFFERENTIAL +} ad9528RefBuffer_t; + +/// Structure to hold AD9528 PLL1 settings +typedef struct +{ + uint32_t refA_Frequency_Hz; + uint16_t refA_Divider; + ad9528RefBuffer_t refA_bufferCtrl; + + uint32_t refB_Frequency_Hz; + uint16_t refB_Divider; + ad9528RefBuffer_t refB_bufferCtrl; + + uint32_t vcxo_Frequency_Hz; + ad9528RefBuffer_t vcxoBufferCtrl; + + uint16_t nDivider; + uint8_t bypassPll1; +} ad9528pll1Settings_t; + +/// Structure to hold AD9528 PLL2 settings +typedef struct +{ + uint8_t rfDivider; //VCO divider: Valid range (3,4,5) + uint8_t n2Divider; //PLL2 N2 Divider + uint8_t totalNdiv; //NDiv = 4*Bdiv + Adiv //Bdiv valid range (3 to 63), Adiv valid range (0-3) +} ad9528pll2Settings_t; + +/// Structure to hold AD9528 Output Clock settings +typedef struct +{ + uint16_t outPowerDown; //bit per output, if 1 power down that output. + ad9528outSourceSel_t outSource[14]; //CHANNEL_DIV, PLL1_OUTPUT, SYSREF, INV_PLL1_OUTPUT + ad9528outBufferControl_t outBufferCtrl[14]; //LVDS, LVDS_BOOST, HSTL + uint8_t outAnalogDelay[14]; //5 bits + uint8_t outDigitalDelay[14]; //6 bits, 1/2 clock resolution @ channel div input frequency + uint8_t outChannelDiv[14]; //8 bit channel divider + uint32_t outFrequency_Hz[14]; //output clock frequency per clock output +} ad9528outputSettings_t; + +///Enum to select the SYSREF output source +typedef enum +{ + EXTERNAL = 0, EXT_RESAMPLED = 1, INTERNAL = 2 +} sysrefSourceSelection_t; + +///Enum to choose the SYSREF pattern mode. +typedef enum +{ + NSHOT = 0, CONTINUOUS = 1, PRBS = 2, STOP = 3 +} sysrefPatternMode_t; + +///Enum to select the SYSREF input pin mode. +typedef enum +{ + LEVEL_ACTIVE_HIGH = 0, LEVEL_ACTIVE_LOW = 1, RISING_EDGE = 2, FALLING_EDGE = 3 +} sysrefPinEdgeMode_t; + +///Enum to select the SYSREF output # of pulses for NSHOT mode. +typedef enum +{ + ONE_PULSE = 0, TWO_PULSES = 2, FOUR_PULSES = 3, SIX_PULSES = 4, EIGHT_PULSES = 5 +} sysrefNshotMode_t; + +//Enum to select how a SYSREF is requested. +typedef enum +{ + SPI = 0, PIN = 1 +} sysrefRequestMethod_t; + +/// Structure to hold AD9528 SYSREF output settings +typedef struct +{ + sysrefRequestMethod_t sysrefRequestMethod; + sysrefSourceSelection_t sysrefSource; + sysrefPinEdgeMode_t sysrefPinEdgeMode; + ad9528RefBuffer_t sysrefPinBufferMode; + sysrefPatternMode_t sysrefPatternMode; + sysrefNshotMode_t sysrefNshotMode; + uint16_t sysrefDivide; + +} ad9528sysrefSettings_t; + +/// Structure to hold AD9528 settings +typedef struct +{ + spiSettings_t *spiSettings; + ad9528pll1Settings_t *pll1Settings; + ad9528pll2Settings_t *pll2Settings; + ad9528outputSettings_t *outputSettings; + ad9528sysrefSettings_t *sysrefSettings; +} ad9528Device_t; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/datalink814_ge/src/hardware/mykonos/t_mykonos.h b/datalink814_ge/src/hardware/mykonos/t_mykonos.h new file mode 100644 index 0000000..66db0d7 --- /dev/null +++ b/datalink814_ge/src/hardware/mykonos/t_mykonos.h @@ -0,0 +1,1710 @@ +/*! + * \file t_mykonos.h + * \brief Contains type definitions for Mykonos API + * + * Mykonos API version: 1.5.2.3566 + */ + +/** +* \page Disclaimer Legal Disclaimer +* Copyright 2015-2017 Analog Devices Inc. +* Released under the AD9371 API license, for more information see the "LICENSE.txt" file in this zip file. +* +*/ + +#ifndef _T_MYKONOS_LIB_H_ +#define _T_MYKONOS_LIB_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "../common.h" + + +/** + * \brief Enum of unique error codes from the Mykonos API functions. + * Each error condition in the library should get its own enum value to allow + * easy debug of errors. + */ +typedef enum +{ + MYKONOS_ERR_OK=0, + MYKONOS_ERR_HAL_LAYER, + MYKONOS_ERR_INV_PARM, + MYKONOS_ERR_FAILED, + MYKONOS_ERR_WAITFOREVENT_INV_PARM, + MYKONOS_ERR_WAITFOREVENT_TIMEDOUT, + MYKONOS_ERR_SETENSM_INVALID_NEWSTATE_WAIT, + MYKONOS_ERR_SETENSM_INVALID_NEWSTATE_ALERT, + MYKONOS_ERR_SETENSM_INVALID_NEWSTATE_TXRX, + MYKONOS_ERR_SETENSM_INVALIDSTATE, + MYKONOS_ERR_PU_RXPATH_INV_PARAM, + MYKONOS_ERR_PU_TXPATH_INV_PARAM, + MYKONOS_ERR_PU_OBSRXPATH_INV_PARAM, + MYKONOS_ERR_INIT_INV_ORXCHAN, + MYKONOS_ERR_INIT_INV_RXSYNCB_ORXSYNCB_MODE, + MYKONOS_ERR_INIT_INV_TXFIR_INTERPOLATION, + MYKONOS_ERR_INIT_INV_TXHB2_INTERPOLATION, + MYKONOS_ERR_INIT_INV_TXHB1_INTERPOLATION, + MYKONOS_ERR_INIT_INV_RXFIR_DECIMATION, + MYKONOS_ERR_INIT_INV_RXDEC5_DECIMATION, + MYKONOS_ERR_INIT_INV_RXHB1_DECIMATION, + MYKONOS_ERR_INIT_INV_SNIFFER_RHB1, + MYKONOS_ERR_INIT_INV_SNIFFER_RFIR_DEC, + MYKONOS_ERR_INIT_INV_ORX_RHB1, + MYKONOS_ERR_INIT_INV_ORX_RFIR_DEC, + MYKONOS_ERR_INIT_INV_ADCDIV, + MYKONOS_ERR_INIT_INV_DACDIV, + MYKONOS_ERR_INIT_INV_OBSRX_ADCDIV, + MYKONOS_ERR_CLKPLL_INV_HSDIV, + MYKONOS_ERR_CLKPLL_INV_VCODIV, + MYKONOS_ERR_CLKPLL_INV_RXTXPROFILES, + MYKONOS_ERR_SETCLKPLL_INV_VCOINDEX, + MYKONOS_ERR_SETCLKPLL_INV_FRACWORD, + MYKONOS_ERR_SETRFPLL_INV_PLLNAME, + MYKONOS_ERR_SETRFPLL_INV_LO_PARM, + MYKONOS_ERR_INV_SCALEDDEVCLK_PARAM, + MYKONOS_ERR_NULL_DEVICE_PARAM, + MYKONOS_ERR_CALCDEVCLK_NULLPARAM, + MYKONOS_ERR_SETRFPLL_INV_VCOINDEX, + MYKONOS_ERR_SETRFPLL_INV_REFCLK, + MYKONOS_ERR_SETORXGAIN_INV_CHANNEL, + MYKONOS_ERR_SETORXGAIN_INV_GAIN, + MYKONOS_ERR_GETORX1GAIN_INV_POINTER, + MYKONOS_ERR_GETORX2GAIN_INV_POINTER, + MYKONOS_ERR_GETSNIFFGAIN_INV_POINTER, + MYKONOS_ERR_GETOBSRXGAIN_CH_DISABLED, + MYKONOS_ERR_SETTX1ATTEN_INV_PARM, + MYKONOS_ERR_SETTX1ATTEN_INV_STEPSIZE_PARM, + MYKONOS_ERR_SETTX2ATTEN_INV_PARM, + MYKONOS_ERR_SETTX2ATTEN_INV_STEPSIZE_PARM, + MYKONOS_ERR_PROGRAMFIR_INV_NUMTAPS_PARM, + MYKONOS_ERR_PROGRAMFIR_INV_FIRNAME_PARM, + MYKONOS_ERR_RXFIR_INV_GAIN_PARM, + MYKONOS_ERR_OBSRXFIR_INV_GAIN_PARM, + MYKONOS_ERR_SRXFIR_INV_GAIN_PARM, + MYKONOS_ERR_TXFIR_INV_GAIN_PARM, + MYKONOS_ERR_READFIR_NULL_PARM, + MYKONOS_ERR_READFIR_COEFS_NULL, + MYKONOS_ERR_READFIR_INV_FIRNAME_PARM, + MYKONOS_ERR_READFIR_INV_NUMTAPS_PARM, + MYKONOS_ERR_SETRX1GAIN_INV_GAIN_PARM, + MYKONOS_ERR_SETRX2GAIN_INV_GAIN_PARM, + MYKONOS_ERR_INITSER_INV_VCODIV_PARM, + MYKONOS_ERR_INITSER_INV_VCODIV1_HSCLK_PARM, + MYKONOS_ERR_INITSER_INV_VCODIV1P5_HSCLK_PARM, + MYKONOS_ERR_INITDES_INV_VCODIV_PARM, + MYKONOS_ERR_SER_INV_M_PARM, + MYKONOS_ERR_SER_INV_L_PARM, + MYKONOS_ERR_SER_INV_LANERATE_PARM, + MYKONOS_ERR_SER_INV_LANEEN_PARM, + MYKONOS_ERR_SER_INV_AMP_PARM, + MYKONOS_ERR_SER_INV_PREEMP_PARM, + MYKONOS_ERR_SER_INV_LANEPN_PARM, + MYKONOS_ERR_SER_LANE_CONFLICT_PARM, + MYKONOS_ERR_SER_INV_TXSER_DIV_PARM, + MYKONOS_ERR_SER_LANE_RATE_CONFLICT_PARM, + MYKONOS_ERR_SER_INV_REAL_IF_DATA_PARM, + MYKONOS_ERR_HS_AND_LANE_RATE_NOT_INTEGER_MULT, + MYKONOS_ERR_DES_HS_AND_LANE_RATE_NOT_INTEGER_MULT, + MYKONOS_ERR_DESER_INV_M_PARM, + MYKONOS_ERR_DESER_INV_L_PARM, + MYKONOS_ERR_DESER_INV_HSCLK_PARM, + MYKONOS_ERR_DESER_INV_LANERATE_PARM, + MYKONOS_ERR_DESER_INV_LANEEN_PARM, + MYKONOS_ERR_DESER_INV_EQ_PARM, + MYKONOS_ERR_DESER_INV_LANEPN_PARM, + MYKONOS_ERR_FRAMER_INV_M_PARM, + MYKONOS_ERR_FRAMER_INV_BANKID_PARM, + MYKONOS_ERR_FRAMER_INV_LANEID_PARM, + MYKONOS_ERR_FRAMER_INV_K_OFFSET_PARAM, + MYKONOS_ERR_FRAMER_INV_REAL_IF_DATA_PARM, + MYKONOS_ERR_OBSRX_FRAMER_INV_M_PARM, + MYKONOS_ERR_OBSRX_FRAMER_INV_BANKID_PARM, + MYKONOS_ERR_OBSRX_FRAMER_INV_LANEID_PARM, + MYKONOS_ERR_OBSRX_FRAMER_INV_K_OFFSET_PARAM, + MYKONOS_ERR_OBSRX_FRAMER_INV_REAL_IF_DATA_PARM, + MYKONOS_ERR_DEFRAMER_INV_M_PARM, + MYKONOS_ERR_DEFRAMER_INV_BANKID_PARM, + MYKONOS_ERR_ERR_DEFRAMER_INV_LANEID_PARM, + MYKONOS_ERR_DEFRAMER_INV_K_OFFSET_PARAM, + MYKONOS_ERR_DEFRAMER_INV_K_PARAM, + MYKONOS_ERR_DEFRAMER_INV_FK_PARAM, + MYKONOS_ERR_RX_FRAMER_INV_PRBS_POLYORDER_PARAM, + MYKONOS_ERR_OBSRX_FRAMER_INV_PRBS_POLYORDER_PARAM, + MYKONOS_ERR_DEFRAMER_INV_PRBS_ENABLE_PARAM, + MYKONOS_ERR_DEFRAMER_INV_PRBS_POLYORDER_PARAM, + MYKONOS_ERR_DEFRAMER_INV_PRBS_CNTR_SEL_PARAM, + MYKONOS_ERR_INITARM_INV_DATARATE_PARM, + MYKONOS_ERR_INITARM_INV_REGCLK, + MYKONOS_ERR_INITARM_INV_ARMCLK_PARAM, + MYKONOS_ERR_LOADHEX_INV_CHARCOUNT, + MYKONOS_ERR_LOADHEX_INVALID_FIRSTCHAR, + MYKONOS_ERR_LOADHEX_INVALID_CHKSUM, + MYKONOS_ERR_LOADBIN_INVALID_BYTECOUNT, + MYKONOS_ERR_ARM_INVALID_BUILDCHKSUM, + MYKONOS_ERR_READARMMEM_INV_ADDR_PARM, + MYKONOS_ERR_WRITEARMMEM_INV_ADDR_PARM, + MYKONOS_ERR_ARMCMD_INV_OPCODE_PARM, + MYKONOS_ERR_ARMCMD_INV_NUMBYTES_PARM, + MYKONOS_ERR_ARMCMDSTATUS_INV_OPCODE_PARM, + MYKONOS_ERR_CHECKDEVSTRUCT_SPI, + MYKONOS_ERR_CHECKDEVSTRUCT_RX, + MYKONOS_ERR_CHECKDEVSTRUCT_RXSUB, + MYKONOS_ERR_CHECKDEVSTRUCT_RXFIR, + MYKONOS_ERR_CHECKDEVSTRUCT_TX, + MYKONOS_ERR_CHECKDEVSTRUCT_TXSUB, + MYKONOS_ERR_CHECKDEVSTRUCT_TXFIR, + MYKONOS_ERR_CHECKDEVSTRUCT_OBSRX, + MYKONOS_ERR_CHECKDEVSTRUCT_OBSRXSUB, + MYKONOS_ERR_CHECKDEVSTRUCT_SNIFFERFIR, + MYKONOS_ERR_CHECKDEVSTRUCT_ORXFIR, + MYKONOS_ERR_CHECKDEVSTRUCT_ORXGAINCTRL, + MYKONOS_ERR_CHECKDEVSTRUCT_SNIFFERGAINCTRL, + MYKONOS_ERR_CHECKDEVSTRUCT_OBSRXFRAMER, + MYKONOS_ERR_INITSER_INV_PROFILE, + MYKONOS_ERR_INITDES_INV_TXPROFILE, + MYKONOS_ERR_JESD204B_ILAS_MISMATCH, + MYKONOS_ERR_RXGAINTABLE_INV_CHANNEL, + MYKONOS_ERR_RXGAINTABLE_INV_GAIN_INDEX_RANGE, + MYKONOS_ERR_WRITE_CFG_MEMORY_FAILED, + MYKONOS_ERR_INV_RXFRAMER_PCLKDIV_PARM, + MYKONOS_ERR_RXFRAMER_INV_FK_PARAM, + MYKONOS_ERR_OBSRXFRAMER_INV_FK_PARAM, + MYKONOS_ERR_INV_OBSRXFRAMER_PCLKDIV_PARM, + MYKONOS_ERR_PU_OBSRXPATH_INV_LOSOURCE_PARAM, + MYKONOS_ERR_ARM_RADIOON_FAILED, + MYKONOS_ERR_INV_RX_GAIN_MODE_PARM, + MYKONOS_ERR_INV_ORX_GAIN_MODE_PARM, + MYKONOS_ERR_INV_AGC_RX_STRUCT_INIT, + MYKONOS_ERR_INV_AGC_RX_APD_THRESH_DIFF_VS_ATTACK_GAIN_STEP, + MYKONOS_ERR_INV_AGC_RX_PEAK_WAIT_TIME_PARM, + MYKONOS_ERR_INV_AGC_RX_GAIN_UPDATE_TIME_PARM, + MYKONOS_ERR_INV_AGC_RX_APD_HIGH_THRESH_PARM, + MYKONOS_ERR_INV_AGC_RX_APD_LOW_THRESH_PARM, + MYKONOS_ERR_INV_AGC_RX_BLOCK_DET_DECAY_PARM, + MYKONOS_ERR_INV_AGC_RX_APD_GAIN_STEP_PARM, + MYKONOS_ERR_INV_AGC_RX_HB2_GAIN_STEP_PARM, + MYKONOS_ERR_INV_AGC_RX_RECOVERY_GAIN_STEP_PARM, + MYKONOS_ERR_INV_AGC_PMD_MEAS_CONFIG, + MYKONOS_ERR_INV_AGC_PMD_MEAS_DURATION, + MYKONOS_ERR_INV_AGC_RX_ENABLE_SYNC_PULSE_GAIN_COUNTER, + MYKONOS_ERR_INV_AGC_RX_LOW_THS_PREV_GAIN_INC, + MYKONOS_ERR_INV_AGC_RX_PEAK_STRUCT_INIT, + MYKONOS_ERR_INV_AGC_RX_PEAK_THRESH_MODE, + MYKONOS_ERR_INV_AGC_RX_PWR_STRUCT_INIT, + MYKONOS_ERR_INV_AGC_RX_RESET_ON_RX_ENABLE, + MYKONOS_ERR_INV_AGC_RX_SLOW_LOOP_SETTLING_DELAY, + MYKONOS_ERR_INV_AGC_RX1_MAX_GAIN_INDEX, + MYKONOS_ERR_INV_AGC_RX1_MIN_GAIN_INDEX, + MYKONOS_ERR_INV_AGC_RX2_MAX_GAIN_INDEX, + MYKONOS_ERR_INV_AGC_RX2_MIN_GAIN_INDEX, + MYKONOS_ERR_INV_AGC_RX_PMD_LOWER_HIGH_THRESH, + MYKONOS_ERR_INV_AGC_RX_PMD_LOWER_LOW_THRESH, + MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_HIGH_THRESH, + MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_LOW_THRESH, + MYKONOS_ERR_INV_AGC_RX_PMD_LOWER_LOW_GAIN_STEP, + MYKONOS_ERR_INV_AGC_RX_PMD_LOWER_HIGH_GAIN_STEP, + MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_LOW_GAIN_STEP, + MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_HIGH_GAIN_STEP, + MYKONOS_ERR_INV_AGC_RX_APD_HIGH_GAIN_STEP_PARM, + MYKONOS_ERR_INV_AGC_RX_APD_LOW_GAIN_STEP_PARM, + MYKONOS_ERR_INV_AGC_RX_HB2_HIGH_GAIN_STEP_PARM, + MYKONOS_ERR_INV_AGC_RX_HB2_HIGH_THRESH_PARM, + MYKONOS_ERR_INV_AGC_RX_HB2_LOW_GAIN_STEP_PARM, + MYKONOS_ERR_INV_AGC_RX_HB2_LOW_THRESH_PARM, + MYKONOS_ERR_INV_AGC_RX_HB2_VERY_LOW_GAIN_STEP_PARM, + MYKONOS_ERR_INV_AGC_RX_HB2_VERY_LOW_THRESH_PARM, + MYKONOS_ERR_INV_AGC_RX_PKDET_FAST_ATTACK_VALUE, + MYKONOS_ERR_INV_AGC_RX_HB2_OVLD_ENABLE, + MYKONOS_ERR_INV_AGC_RX_HB2_OVLD_DUR_CNT, + MYKONOS_ERR_INV_AGC_RX_HB2_OVLD_THRESH_CNT, + MYKONOS_ERR_INV_AGC_OBSRX_STRUCT_INIT, + MYKONOS_ERR_INV_AGC_OBSRX_APD_THRESH_DIFF_VS_ATTACK_GAIN_STEP, + MYKONOS_ERR_INV_AGC_OBSRX_PEAK_WAIT_TIME_PARM, + MYKONOS_ERR_INV_AGC_OBSRX_GAIN_UPDATE_TIME_PARM, + MYKONOS_ERR_INV_AGC_OBSRX_APD_HIGH_THRESH_PARM, + MYKONOS_ERR_INV_AGC_OBSRX_APD_LOW_THRESH_PARM, + MYKONOS_ERR_INV_AGC_OBSRX_BLOCK_DET_DECAY_PARM, + MYKONOS_ERR_INV_AGC_OBSRX_APD_GAIN_STEP_PARM, + MYKONOS_ERR_INV_AGC_OBSRX_HB2_GAIN_STEP_PARM, + MYKONOS_ERR_INV_AGC_OBSRX_RECOVERY_GAIN_STEP_PARM, + MYKONOS_ERR_INV_AGC_OBSRX_MAX_GAIN_INDEX, + MYKONOS_ERR_INV_AGC_OBSRX_MIN_GAIN_INDEX, + MYKONOS_ERR_INV_AGC_OBSRX_SELECT, + MYKONOS_ERR_INV_AGC_OBSRX_PMD_MEAS_CONFIG, + MYKONOS_ERR_INV_AGC_OBSRX_PMD_MEAS_DURATION, + MYKONOS_ERR_INV_AGC_OBSRX_ENABLE_SYNC_PULSE_GAIN_COUNTER, + MYKONOS_ERR_INV_AGC_OBSRX_LOW_THS_PREV_GAIN_INC, + MYKONOS_ERR_INV_AGC_OBSRX_PEAK_STRUCT_INIT, + MYKONOS_ERR_INV_AGC_OBSRX_PEAK_THRESH_MODE, + MYKONOS_ERR_INV_AGC_OBSRX_PWR_STRUCT_INIT, + MYKONOS_ERR_INV_AGC_OBSRX_RESET_ON_RX_ENABLE, + MYKONOS_ERR_INV_AGC_OBSRX_SLOW_LOOP_SETTLING_DELAY, + MYKONOS_ERR_INV_AGC_OBSRX1_MAX_GAIN_INDEX, + MYKONOS_ERR_INV_AGC_OBSRX1_MIN_GAIN_INDEX, + MYKONOS_ERR_INV_AGC_OBSRX2_MAX_GAIN_INDEX, + MYKONOS_ERR_INV_AGC_OBSRX2_MIN_GAIN_INDEX, + MYKONOS_ERR_INV_AGC_OBSRX_PMD_LOWER_HIGH_THRESH, + MYKONOS_ERR_INV_AGC_OBSRX_PMD_LOWER_LOW_THRESH, + MYKONOS_ERR_INV_AGC_OBSRX_PMD_UPPER_HIGH_THRESH, + MYKONOS_ERR_INV_AGC_OBSRX_PMD_UPPER_LOW_THRESH, + MYKONOS_ERR_INV_AGC_OBSRX_PMD_LOWER_LOW_GAIN_STEP, + MYKONOS_ERR_INV_AGC_OBSRX_PMD_LOWER_HIGH_GAIN_STEP, + MYKONOS_ERR_INV_AGC_OBSRX_PMD_UPPER_LOW_GAIN_STEP, + MYKONOS_ERR_INV_AGC_OBSRX_PMD_UPPER_HIGH_GAIN_STEP, + MYKONOS_ERR_INV_AGC_OBSRX_APD_HIGH_GAIN_STEP_PARM, + MYKONOS_ERR_INV_AGC_OBSRX_APD_LOW_GAIN_STEP_PARM, + MYKONOS_ERR_INV_AGC_OBSRX_HB2_HIGH_GAIN_STEP_PARM, + MYKONOS_ERR_INV_AGC_OBSRX_HB2_HIGH_THRESH_PARM, + MYKONOS_ERR_INV_AGC_OBSRX_HB2_LOW_GAIN_STEP_PARM, + MYKONOS_ERR_INV_AGC_OBSRX_HB2_LOW_THRESH_PARM, + MYKONOS_ERR_INV_AGC_OBSRX_HB2_VERY_LOW_GAIN_STEP_PARM, + MYKONOS_ERR_INV_AGC_OBSRX_HB2_VERY_LOW_THRESH_PARM, + MYKONOS_ERR_INV_AGC_OBSRX_PKDET_FAST_ATTACK_VALUE, + MYKONOS_ERR_INV_AGC_OBSRX_HB2_OVLD_ENABLE, + MYKONOS_ERR_INV_AGC_OBSRX_HB2_OVLD_DUR_CNT, + MYKONOS_ERR_INV_AGC_OBSRX_HB2_OVLD_THRESH_CNT, + MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_CALPLL_LOCK, + MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_CLKPLLCP, + MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_CLKPLL_LOCK, + MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_RXPLLCP, + MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_RXPLL_LOCK, + MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_TXPLLCP, + MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_TXPLL_LOCK, + MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_SNIFFPLLCP, + MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_SNIFFPLL_LOCK, + MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_RXBBFCALDONE, + MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_TXBBFCALDONE, + MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_RFDCCALDONE, + MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_ADCTUNECALDONE, + MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_RX1ADCPROFILE, + MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_RX2ADCPROFILE, + MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_ORXADCPROFILE, + MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_RCALDONE, + MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_ARMBUSY, + MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_INITARMDONE, + MYKONOS_ERR_TIMEDOUT_ARMMAILBOXBUSY, + MYKONOS_ERR_PU_OBSRXPATH_ARMERROR, + MYKONOS_ERR_EN_TRACKING_CALS_ARMSTATE_ERROR, + MYKONOS_ERR_SET_RADIOCTRL_PINS_ARMERROR, + MYKONOS_ERR_EN_TRACKING_CALS_ARMERROR, + MYKONOS_ERR_SETRFPLL_ARMERROR, + MYKONOS_ERR_INIT_INV_TXINPUTHB_PARM, + MYKONOS_ERR_LOAD_ADCPROFILE_INV_VCODIV, + MYKONOS_ERR_LOAD_ADCPROFILE_CUSTOM_RXREQUIRED, + MYKONOS_ERR_LOAD_ADCPROFILE_CUSTOM_ORXREQUIRED, + MYKONOS_ERR_LOAD_ADCPROFILE_CUSTOM_SNRXREQUIRED, + MYKONOS_ERR_SETUP_PA_PROT_INV_AVG_DURATION, + MYKONOS_ERR_SETUP_PA_PROT_INV_STICKY_ENABLE, + MYKONOS_ERR_SETUP_PA_PROT_INV_ATTEN_STEP, + MYKONOS_ERR_SETUP_PA_PROT_INV_ATTEN_ENABLE, + MYKONOS_ERR_SETUP_PA_PROT_INV_POWER_THRESH, + MYKONOS_ERR_SETUP_PA_PROT_INV_TX_CHANNEL, + MYKONOS_ERR_GET_DAC_PWR_INV_POINTER, + MYKONOS_ERR_GET_PA_FLAG_STATUS_INV_POINTER, + MYKONOS_ERR_GET_OBSRX_OVERLOADS_NULL_PARM, + MYKONOS_ERR_GET_RX1_OVERLOADS_NULL_PARM, + MYKONOS_ERR_GET_RX2_OVERLOADS_NULL_PARM, + MYKONOS_ERR_GETRADIOSTATE_NULL_PARAM, + MYKONOS_ERR_ABORT_INITCALS_NULL_PARAM, + MYKONOS_ERR_ARM_RADIOOFF_FAILED, + MYKONOS_ERR_WAIT_INITCALS_NULL_PARAM, + MYKONOS_ERR_WAIT_INITCALS_CALFAILED, + MYKONOS_ERR_WAIT_INITCALS_ARMERROR, + MYKONOS_ERR_CHECK_PLL_LOCK_NULL_PARM, + MYKONOS_ERR_GET_TXFILTEROVRG_NULL_PARM, + MYKONOS_ERR_PROGRAM_RXGAIN_TABLE_NULL_PARM, + MYKONOS_ERR_PROGRAMFIR_NULL_PARM, + MYKONOS_ERR_PROGRAMFIR_COEFS_NULL, + MYKONOS_ERR_READ_DEFRAMERSTATUS_NULL_PARAM, + MYKONOS_ERR_READ_DEFRAMERPRBS_NULL_PARAM, + MYKONOS_ERR_READ_ORXFRAMERSTATUS_NULL_PARAM, + MYKONOS_ERR_READ_RXFRAMERSTATUS_NULL_PARAM, + MYKONOS_ERR_ARMCMDSTATUS_NULL_PARM, + MYKONOS_ERR_READARMCMDSTATUS_INV_OPCODE_PARM, + MYKONOS_ERR_READARMCMDSTATUS_NULL_PARM, + MYKONOS_ERR_READARMCMDSTATUSBYTE_NULL_PARM, + MYKONOS_ERR_ARMCMD_NULL_PARM, + MYKONOS_ERR_WRITEARMMEM_NULL_PARM, + MYKONOS_ERR_LOADBIN_NULL_PARAM, + MYKONOS_ERR_ARM_INV_ADDR_PARM, + MYKONOS_ERR_LOADARMCON_INVALID_BYTECOUNT, + MYKONOS_ERR_LOADARMCON_NULL_PARAM, + MYKONOS_ERR_GETTX1ATTEN_NULL_PARM, + MYKONOS_ERR_GETTX2ATTEN_NULL_PARM, + MYKONOS_ERR_ENFRAMERLINK_INV_LANESEN_PARM, + MYKONOS_ERR_ENOBSFRAMERLINK_INV_LANESEN_PARM, + MYKONOS_ERR_ENTXNCO_TXPROFILE_INVALID, + MYKONOS_ERR_ENTXNCO_TX1_FREQ_INVALID, + MYKONOS_ERR_ENTXNCO_TX2_FREQ_INVALID, + MYKONOS_ERR_JESD204B_ILAS_MISMATCH_NULLPARAM, + MYKONOS_ERR_LOAD_LBADCPROFILE_ARMMEM_FAILED, + MYKONOS_ERR_LOAD_SNRXADCPROFILE_ARMMEM_FAILED, + MYKONOS_ERR_LOAD_ADCPROFILE_SNRX_ADCDIV_ZERO, + MYKONOS_ERR_LOAD_ORXADCPROFILE_ARMMEM_FAILED, + MYKONOS_ERR_LOAD_ADCPROFILE_ORXADCDIV_ZERO, + MYKONOS_ERR_LOAD_RXADCPROFILE_ARMMEM_FAILED, + MYKONOS_ERR_LOAD_ADCPROFILE_RXADCDIV_ZERO, + MYKONOS_ERR_LOAD_ADCPROFILE_CUSTOM_LBREQUIRED, + MYKONOS_ERR_LOAD_ADCPROFILE_MISSING_ORX_PROFILE, + MYKONOS_ERR_GETRFPLL_INV_PLLNAME, + MYKONOS_ERR_GETRFPLL_ARMERROR, + MYKONOS_ERR_GETRFPLL_NULLPARAM, + MYKONOS_ERR_INITARM_INV_VCODIV, + MYKONOS_ERR_GET_PLLFREQ_INV_HSDIV, + MYKONOS_ERR_GET_PLLFREQ_INV_VCODIV, + MYKONOS_ERR_GET_PLLFREQ_INV_REFCLKDIV, + MYKONOS_ERR_SETORXGAIN_INV_ORX1GAIN, + MYKONOS_ERR_SETORXGAIN_INV_ORX2GAIN, + MYKONOS_ERR_SETORXGAIN_INV_SNRXGAIN, + MYKONOS_ERR_GET_RX1_DEC_POWER_NUM_SAMPLES, + MYKONOS_ERR_GET_RX1_DEC_POWER_NULL_PARM, + MYKONOS_ERR_GET_RX2_DEC_POWER_NUM_SAMPLES, + MYKONOS_ERR_GET_RX2_DEC_POWER_NULL_PARM, + MYKONOS_ERR_GET_OBSRX_DEC_POWER_NUM_SAMPLES, + MYKONOS_ERR_GET_OBSRX_DEC_POWER_NULL_PARM, + MYKONOS_ERR_GETARMVER_NULL_PARM, + MYKONOS_ERR_EN_CLGCTRACKING_ARMSTATE_ERROR, + MYKONOS_ERR_EN_DPDTRACKING_ARMSTATE_ERROR, + MYKONOS_ERR_RESTDPDMOD_WRONGBUFFERSIZE, + MYKONOS_ERR_RESTDPDMOD_ARMSTATE, + MYKONOS_ERR_RESTDPDMOD_INVALID_TXCHANNEL, + MYKONOS_ERR_RESTDPDMOD_ARMERRFLAG, + MYKONOS_ERR_SAVDPDMOD_WRONGBUFFERSIZE, + MYKONOS_ERR_SAVDPDMOD_ARMSTATE, + MYKONOS_ERR_SAVDPDMOD_INVALID_TXCHANNEL, + MYKONOS_ERR_SAVDPDMOD_ARMERRFLAG, + MYKONOS_ERR_WRITEARMCFG_ARMERRFLAG, + MYKONOS_ERR_CFGDPD_TXORX_PROFILE_INV, + MYKONOS_ERR_CFGDPD_NULL_DPDCFGSTRUCT, + MYKONOS_ERR_CFGDPD_INV_DPDDAMPING, + MYKONOS_ERR_CFGDPD_INV_DPDSAMPLES, + MYKONOS_ERR_CFGDPD_INV_DPDOUTLIERTHRESH, + MYKONOS_ERR_CFGDPD_INV_DPDPRIORWEIGHT, + MYKONOS_ERR_CFGCLGC_INV_DESIREDGAIN, + MYKONOS_ERR_CFGCLGC_INV_TXATTENLIMIT, + MYKONOS_ERR_CFGCLGC_INV_CLGC_CTRLRATIO, + MYKONOS_ERR_SETCLGCGAIN_INV_DESIREDGAIN, + MYKONOS_ERR_SETCLGCGAIN_INV_TXCHANNEL, + MYKONOS_ERR_SETCLGCGAIN_TRACK_ARMERRFLAG, + MYKONOS_ERR_CFGDPD_INV_DPD_ADDDELAY, + MYKONOS_ERR_CFGDPD_INV_PNSEQLEVEL, + MYKONOS_ERR_READARMCFG_ARMERRFLAG, + MYKONOS_ERR_GETPENDTRKCALS_NULL_PARAM, + MYKONOS_ERR_ARMCMDSTATUS_ARMERROR, + MYKONOS_ERR_WAITARMCMDSTATUS_TIMEOUT, + MYKONOS_ERR_PU_GETOBSRXPATH_ARMERROR, + MYKONOS_ERR_GETDPDCFG_NULL_DPDCFGSTRUCT, + MYKONOS_ERR_GETDPDCFG_TXORX_PROFILE_INV, + MYKONOS_ERR_GETDPDSTATUS_ARMERRFLAG, + MYKONOS_ERR_GETDPDSTATUS_NULLPARAM, + MYKONOS_ERR_SETDEFOBSRXPATH_NULL_OBSRX_STRUCT, + MYKONOS_ERR_SETDEFOBSRXPATH_NULL_DEF_OBSRX_STRUCT, + MYKONOS_ERR_GETCLGCSTATUS_NULLPARAM, + MYKONOS_ERR_GETCLGCSTATUS_ARMERRFLAG, + MYKONOS_ERR_CHECKDEVSTRUCT_NULLDEVPOINTER, + MYKONOS_ERR_READ_DEFFIFODEPTH_NULL_PARAM, + MYKONOS_ERR_READ_DEFFIFODEPTH_LMFCCOUNT_NULL_PARAM, + MYKONOS_ERR_GETDPDSTATUS_INV_CH, + MYKONOS_ERR_GETCLGCSTATUS_INV_CH, + MYKONOS_ERR_INIT_INV_TXINPUTHB_INV_RATE, + MYKONOS_ERR_INIT_INV_TXINPUTHB0_INV_RATE, + MYKONOS_ERR_TXFIR_TAPSEXCEEDED, + MYKONOS_ERR_TXFIR_INV_NUMROWS, + MYKONOS_ERR_TXFIR_INV_NUMTAPS_PARM, + MYKONOS_ERR_RXFIR_TAPSEXCEEDED, + MYKONOS_ERR_ORXFIR_TAPSEXCEEDED, + MYKONOS_ERR_SNRXFIR_TAPSEXCEEDED, + MYKONOS_ERR_GETINITCALSTATUS_NULL_PARAM, + MYKONOS_ERR_GETINITCALSTATUS_ARMERROR, + MYKONOS_ERR_CFGDPD_INV_NUMWEIGHTS, + MYKONOS_ERR_CFGDPD_INV_MODELVERSION, + MYKONOS_ERR_SETDPDACT_INV_TXCHANNEL, + MYKONOS_ERR_SETDPDACT_INV_STATE, + MYKONOS_ERR_SETDPDACT_ARMERRFLAG, + MYKONOS_ERR_CFGCLGC_TXORX_PROFILE_INV, + MYKONOS_ERR_CFGCLGC_NULL_CLGCCFGSTRUCT, + MYKONOS_ERR_GETCLGCCFG_TXORX_PROFILE_INV, + MYKONOS_ERR_GETCLGCCFG_NULL_CFGSTRUCT, + MYKONOS_ERR_CALCDIGCLK_NULLDEV_PARAM, + MYKONOS_ERR_CALCDIGCLK_NULL_CLKSTRUCT, + MYKONOS_ERR_CFGCLGC_INV_CLGC_ADDDELAY, + MYKONOS_ERR_CFGCLGC_INV_PNSEQLEVEL, + MYKONOS_ERR_CFGVSWR_TXORX_PROFILE_INV, + MYKONOS_ERR_CFGVSWR_ARMSTATE_ERROR, + MYKONOS_ERR_CFGVSWR_INV_3P3GPIOPIN, + MYKONOS_ERR_CFGVSWR_INV_PNSEQLEVEL, + MYKONOS_ERR_CFGVSWR_INV_VSWR_ADDDELAY, + MYKONOS_ERR_CFGVSWR_NULL_VSWRCFGSTRUCT, + MYKONOS_ERR_GETVSWRCFG_NULL_CFGSTRUCT, + MYKONOS_ERR_GETVSWRCFG_TXORX_PROFILE_INV, + MYKONOS_ERR_GETVSWRSTATUS_ARMERRFLAG, + MYKONOS_ERR_GETVSWRSTATUS_INV_CH, + MYKONOS_ERR_GETVSWRSTATUS_NULLPARAM, + MYKONOS_ERR_SET_RX_MAX_GAIN_INDEX, + MYKONOS_ERR_SET_RX_MIN_GAIN_INDEX, + MYKONOS_ERR_AGC_MIN_MAX_RX_CHANNEL, + MYKONOS_ERR_SET_ORX_MAX_GAIN_INDEX_CHANNEL, + MYKONOS_ERR_SET_ORX_MAX_GAIN_INDEX, + MYKONOS_ERR_SET_ORX_MIN_GAIN_INDEX, + MYKONOS_ERR_AGC_MIN_MAX_ORX_CHANNEL, + MYKONOS_ERR_RX1_TEMP_GAIN_COMP_RANGE, + MYKONOS_ERR_RX2_TEMP_GAIN_COMP_RANGE, + MYKONOS_ERR_OBS_RX_TEMP_GAIN_COMP_RANGE, + MYKONOS_ERR_RX1_TEMP_GAIN_COMP_STEP, + MYKONOS_ERR_RX2_TEMP_GAIN_COMP_STEP, + MYKONOS_ERR_OBS_RX_TEMP_GAIN_COMP_STEP, + MYKONOS_ERR_RX1_TEMP_GAIN_COMP_NULL, + MYKONOS_ERR_RX2_TEMP_GAIN_COMP_NULL, + MYKONOS_ERR_OBS_RX_TEMP_GAIN_COMP_NULL, + MYKONOS_ERR_GETTXLOLSTATUS_NULLPARAM, + MYKONOS_ERR_GETTXLOLSTATUS_INV_CH, + MYKONOS_ERR_GETTXLOLSTATUS_ARMERRFLAG, + MYKONOS_ERR_GETTXQECSTATUS_NULLPARAM, + MYKONOS_ERR_GETTXQECSTATUS_INV_CH, + MYKONOS_ERR_GETTXQECSTATUS_ARMERRFLAG, + MYKONOS_ERR_GETRXQECSTATUS_NULLPARAM, + MYKONOS_ERR_GETRXQECSTATUS_INV_CH, + MYKONOS_ERR_GETRXQECSTATUS_ARMERRFLAG, + MYKONOS_ERR_GETORXQECSTATUS_NULLPARAM, + MYKONOS_ERR_GETORXQECSTATUS_INV_CH, + MYKONOS_ERR_GETORXQECSTATUS_ARMERRFLAG, + MYKONOS_ERR_RESCHEDULE_TRACK_CAL_INV, + MYKONOS_ERR_RESCHEDULE_TRACK_ARMERRFLAG, + + MYKONOS_ERR_SETSTATEALL_TRACK_CAL_INV, + MYKONOS_ERR_SETSTATEALL_TRACK_ARMERRFLAG, + + MYKONOS_ERR_GETSTATEALL_TRACK_NULL_PARAM, + MYKONOS_ERR_GETSTATEALL_TRACK_ARMERRFLAG, + MYKONOS_ERR_GETSTATEALL_TRACK_ARMERROR, + + MYKONOS_ERR_SETSTATE_TRACK_CAL_INV, + MYKONOS_ERR_SETSTATE_TRACK_ARMERRFLAG, + + MYKONOS_ERR_GETSTATE_TRACK_NULL_PARAM, + MYKONOS_ERR_GETSTATE_TRACK_ARMERRFLAG, + MYKONOS_ERR_GETSTATE_TRACK_ARMERROR, + + MYKONOS_ERR_ARMSTATE_PROFILE_ERROR, + MYKONOS_ERR_ARMSTATE_CAL_ERROR, + MYKONOS_ERR_ARMSTATE_EXCEPTION, + MYKONOS_ERR_WAITARMCSTATE_TIMEOUT, + + MYKONOS_ERR_GETPRODUCTID_NULL_PARAM, + MYKONOS_ERR_GET_API_VERSION_NULL_PARAM, + + MYKONOS_ERR_PROFILES_HSDIGCLK, + MYKONOS_ERR_RXPROFILE_RXCHANNEL, + MYKONOS_ERR_RXPROFILE_IQRATE, + MYKONOS_ERR_RXPROFILE_RFBW, + MYKONOS_ERR_RXPROFILE_FILTER_DECIMATION, + MYKONOS_ERR_RXPROFILE_FIR_COEFS, + MYKONOS_ERR_RXPROFILE_ADCDIV, + MYKONOS_ERR_TXPROFILE_IQRATE, + MYKONOS_ERR_TXPROFILE_RFBW, + MYKONOS_ERR_TXPROFILE_FILTER_INTERPOLATION, + MYKONOS_ERR_TXPROFILE_FIR_COEFS, + MYKONOS_ERR_TXPROFILE_DACDIV, + MYKONOS_ERR_RESET_TXLOL_INV_PARAM, + MYKONOS_ERR_RESET_TXLOL_ARMERROR, + MYKONOS_ERR_SETRFPLL_LF_INV_STABILITY, + MYKONOS_ERR_SETRFPLL_LF_PLLNAME, + MYKONOS_ERR_SETRFPLL_LF_INV_TXRX_LOOPBANDWIDTH, + MYKONOS_ERR_SETRFPLL_LF_INV_SNF_LOOPBANDWIDTH, + MYKONOS_ERR_SETRFPLL_LF_ARMERROR, + MYKONOS_ERR_GETRFPLL_LF_ARMERROR, + MYKONOS_ERR_GETRFPLL_LF_NULLPARAM, + MYKONOS_ERR_GETRFPLL_LF_INV_PLLNAME, + MYKONOS_ERR_DC_OFFSET_INV_CHAN, + MYKONOS_ERR_SET_RF_DC_OFFSET_INV_MEASURECNT, + MYKONOS_ERR_SET_RF_DC_OFFSET_MEASURECNT_MIN_LIMIT, + MYKONOS_ERR_GET_RF_DC_OFFSET_NULL_MEASURECNT, + MYKONOS_ERR_RF_DC_OFFSET_INV_ENABLE_MASK, + MYKONOS_ERR_RF_DC_OFFSET_NULL_ENABLE_MASK, + MYKONOS_ERR_SET_DIG_DC_OFFSET_INV_MSHIFT, + MYKONOS_ERR_GET_DIG_DC_OFFSET_NULL_MSHIFT, + MYKONOS_ERR_DIG_DC_OFFSET_INV_ENABLE_MASK, + MYKONOS_ERR_DIG_DC_OFFSET_NULL_ENABLE_MASK, + MYKONOS_ERR_CFGCLGC_INV_THRESHOLD, + MYKONOS_ERR_RESETDPD_INV_TXCHANNEL, + MYKONOS_ERR_RESETDPD_ARMERRFLAG, + MYKONOS_ERR_RESETDPD_WRONG_PARAM, + MYKONOS_WRN_RADIO_ON_NOT_MODIFIABLE, + MYKONOS_ERR_SET_PATH_DELAY_NULL_PARAM, + MYKONOS_ERR_SET_PATH_DELAY_PARAM_OUT_OF_RANGE, + MYKONOS_ERR_GET_PATH_DELAY_NULL_PARAM, + MYKONOS_ERR_GET_PATH_DELAY_INVALID_SELECTION, + MYKONOS_ERR_GET_PATH_DELAY_ARMERRFLAG, + + + MYKONOS_ERR_GETDPD_ERROR_CNT_NULLPARAM, + MYKONOS_ERR_GETDPD_ERROR_CNT_INV_CH, + MYKONOS_ERR_GETDPD_ERROR_CNT_ARMERRFLAG, + + MYKONOS_ERR_SETDPDACT_NULL_ACTSTRUCT, + MYKONOS_ERR_SETDPDACT_INV_ACTMODE, + MYKONOS_ERR_SETDPDACT_INV_LEVEL, + MYKONOS_ERR_GETDPDACT_NULL_ACTSTRUCT, + + MYKONOS_ERR_SETDPDACTCHECK_NULL_ACTSTRUCT, + MYKONOS_ERR_SETDPDACTCHECK_INV_ACTMODE, + MYKONOS_ERR_SETDPDACTCHECK_INV_LEVEL, + MYKONOS_ERR_GETDPDACTCHECK_NULL_ACTSTRUCT, + + MYKONOS_ERR_CLGCATTENTUNCFG_NULL_ATTRANGECFGSTRUCT, + MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_MODE, + MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_PRESET, + MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_RANGE, + MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_TX1_SETTINGS, + MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_TX2_SETTINGS, + + MYKONOS_ERR_CLGCATTENTUNCFGGET_NULL_ATTRANGECFGSTRUCT, + + MYKONOS_ERR_END +} mykonosErr_t; + +/** + * \brief Enum for Mykonos low voltage GPIO available pins + */ +typedef enum +{ + MYKGPIONAN = 0x00, + MYKGPIO0 = 0x1, + MYKGPIO1 = 0x2, + MYKGPIO2 = 0x4, + MYKGPIO3 = 0x8, + MYKGPIO4 = 0x10, + MYKGPIO5 = 0x20, + MYKGPIO6 = 0x40, + MYKGPIO7 = 0x80, + MYKGPIO8 = 0x100, + MYKGPIO9 = 0x200, + MYKGPIO10 = 0x400, + MYKGPIO11 = 0x800, + MYKGPIO12 = 0x1000, + MYKGPIO13 = 0x2000, + MYKGPIO14 = 0x4000, + MYKGPIO15 = 0x8000, + MYKGPIO16 = 0x10000, + MYKGPIO17 = 0x20000, + MYKGPIO18 = 0x40000 +} mykonosGpioSelect_t; + + +/** + * \brief Enum of valid Mykonos Enable State Machine (ENSM) states + */ +typedef enum +{ + WAIT = 0, /*!< Mykonos ENSM state upon which a power up in the WAIT/SLEEP state occurs */ + INIT = 1, /*!< Mykonos ENSM state upon which a power up delay state ocurrs to allow clocks to stabilize */ + WAITCALS = 2, /*!< Mykonos ENSM state upon which calibrations are initializing */ + ALERTCALS = 3, /*!< Mykonos ENSM state upon which calibrations are occurring */ + ALERTLDS = 4, /*!< Mykonos ENSM state upon which a delay state is occurring when moving from WAIT to ALERT to allow internal circuits to power up */ + ALERT = 5, /*!< Mykonos ENSM state upon which the internal RF synth is powered up, and TX and RX data paths are still powered down */ + TX_RX = 6, /*!< Mykonos ENSM state upon which the ability to power up data paths depending on the TxEnable/RxEnable pins or SPI bits */ + FLUSH = 7 /*!< Mykonos ENSM state upon which the data paths are cleared when exiting the TX_RX state */ +} mykonosEnsmState_t; + + +/** + * \brief Enum of possible Tx channels + */ +typedef enum +{ + TXOFF = 0, + TX1 = 1, + TX2 = 2, + TX1_TX2 = 3 +} mykonosTxChannels_t; + +/** + * \brief Enum of possible Rx channels + */ +typedef enum +{ + RXOFF = 0, + RX1 = 1, + RX2 = 2, + RX1_RX2 = 3 +} mykonosRxChannels_t; + +/** + * \brief Enum of possible Observation Rx channels + */ +typedef enum +{ + OBS_RXOFF = 0, + OBS_RX1_TXLO = 1, + OBS_RX2_TXLO = 2, + OBS_INTERNALCALS = 3, + OBS_SNIFFER = 4, + OBS_RX1_SNIFFERLO = 5, + OBS_RX2_SNIFFERLO = 6, + OBS_SNIFFER_A = 0x14, + OBS_SNIFFER_B = 0x24, + OBS_SNIFFER_C = 0x34 +} mykonosObsRxChannels_t; + +/** + * \brief Enum of possible Sniffer Rx channels + */ +typedef enum +{ + SNIFFER_A = 1, + SNIFFER_B = 2, + SNIFFER_C = 3 +} mykonosSnifferChannel_t; + +/** + * \brief Enum of possible Observation Rx channels to enable and run calibrations for during init. + * Choose ENUM value that enables all channels that will be used in the system. During system use, + * only one channel can be used at a time. This is also used to alert the ARM processor + * which observation channels are valid for the current desired system setup. + */ +typedef enum +{ + MYK_OBS_RXOFF = 0x00, + MYK_ORX1 = 0x01, + MYK_ORX2 = 0x02, + MYK_ORX1_ORX2 = 0x03, + MYK_SNRXA = 0x04, + MYK_SNRXB = 0x08, + MYK_SNRXC = 0x10, + MYK_SNRXA_B_C = 0x1C +} mykonosObsRxChannelsEn_t; + +/** + * \brief Enum of possible DAC divider settings (2x, 2.5x, 4x) + */ +typedef enum +{ + DACDIV_2, + DACDIV_2p5, + DACDIV_4 +} mykonosDacDiv_t; + +/** + * \brief Enum of possible VCO divider settings (1x, 1.5x, 2x, 3x) + */ +typedef enum +{ + VCODIV_1 = 0, + VCODIV_1p5 = 1, + VCODIV_2 = 2, + VCODIV_3 = 3 +} mykonosVcoDiv_t; + +/** + * \brief Enum of possible PRBS pattern settings + */ +typedef enum +{ + MYK_PRBS7 = 0, + MYK_PRBS15 = 1, + MYK_PRBS31 = 2 +} mykonosPrbsOrder_t; + +/** + * \brief Enum of RF PLL names + */ +typedef enum +{ + CLK_PLL, + RX_PLL, + TX_PLL, + SNIFFER_PLL +} mykonosRfPllName_t; + +/** + * \brief Enum of Rx profile types + */ +typedef enum +{ + MYK_RX_PROFILE, + MYK_OBS_PROFILE, + MYK_SNIFFER_PROFILE +} mykonosRxProfType_t; + +/** + * \brief Enum of ORx PLL names + */ +typedef enum +{ + OBSLO_TX_PLL, + OBSLO_SNIFFER_PLL +} mykonosObsRxLoSource_t; + +/** + * \brief Enum of possible wait events to use with MYKONOS_waitForEvent() + */ +typedef enum +{ + CALPLL_LOCK, + CLKPLLCP, + CLKPLL_LOCK, + RF_RXPLLCP, + RF_RXPLL_LOCK, + RF_TXPLLCP, + RF_TXPLL_LOCK, + RF_SNIFFERPLLCP, + RF_SNIFFERPLL_LOCK, + RXBBF_CALDONE, + TXBBF_CALDONE, + RX_RFDC_CALDONE, + RX_ADCTUNER_CALDONE, + RX1_ADCPROFILE, + RX2_ADCPROFILE, + ORX_ADCPROFILE, + RCAL_CALDONE, + ARMBUSY, + INITARM_DONE +} waitEvent_t; + +/** + * \brief Enum to set the desired FIR filter type for related functions + */ +typedef enum +{ + TX1_FIR = 1, + TX2_FIR = 2, + TX1TX2_FIR = 3, + RX1_FIR = 4, + RX2_FIR = 8, + RX1RX2_FIR = 12, + OBSRX_A_FIR = 16, + OBSRX_B_FIR = 32 +} mykonosfirName_t; + +/** + * \brief Enum to set the desired Rx gain table channel + */ +typedef enum +{ + RX1_GT = 1, + RX2_GT, + RX1_RX2_GT, + ORX_GT, + SNRX_GT, + LOOPBACK_GT +}mykonosGainTable_t; + +/** + * \brief Enum to set the Rx Gain control mode + */ +typedef enum +{ + MGC = 0, /*!< Manual Gain Control */ + AGC = 2, /*!< Automatic Gain Control (AGC) */ + HYBRID = 3 /*!< Hybrid AGC Gain Control */ + +} mykonosGainMode_t; + +/** + * \brief Enum to set the Tx Atenuation step size + */ +typedef enum +{ + TXATTEN_0P05_DB = 0, /*!< Tx attenuation 0.05dB step size */ + TXATTEN_0P1_DB = 1, /*!< Tx attenuation 0.1dB step size */ + TXATTEN_0P2_DB = 2, /*!< Tx attenuation 0.2dB step size */ + TXATTEN_0P4_DB = 3 /*!< Tx attenuation 0.4dB step size */ +} mykonosTxAttenStepSize_t; + +/** + * \brief Enum to help set the init calibration mask + */ +typedef enum +{ + TX_BB_FILTER = 0x0001, + ADC_TUNER = 0x0002, + TIA_3DB_CORNER = 0x0004, + DC_OFFSET = 0x0008, + TX_ATTENUATION_DELAY = 0x0010, + RX_GAIN_DELAY = 0x0020, + FLASH_CAL = 0x0040, + PATH_DELAY = 0x0080, + TX_LO_LEAKAGE_INTERNAL = 0x0100, + TX_LO_LEAKAGE_EXTERNAL = 0x0200, + TX_QEC_INIT = 0x0400, + LOOPBACK_RX_LO_DELAY = 0x0800, + LOOPBACK_RX_RX_QEC_INIT = 0x1000, + RX_LO_DELAY = 0x2000, + RX_QEC_INIT = 0x4000, + DPD_INIT = 0x8000, + CLGC_INIT = 0x10000, + VSWR_INIT = 0x20000 +} mykonosInitCalibrations_t; + +/** + * \brief Enum to help set the tracking calibration mask + */ +typedef enum +{ + TRACK_RX1_QEC = 0x00001, + TRACK_RX2_QEC = 0x00002, + TRACK_ORX1_QEC = 0x00004, + TRACK_ORX2_QEC = 0x00008, + TRACK_TX1_LOL = 0x00010, + TRACK_TX2_LOL = 0x00020, + TRACK_TX1_QEC = 0x00040, + TRACK_TX2_QEC = 0x00080, + TRACK_TX1_DPD = 0x00100, + TRACK_TX2_DPD = 0x00200, + TRACK_TX1_CLGC = 0x00400, + TRACK_TX2_CLGC = 0x00800, + TRACK_TX1_VSWR = 0x01000, + TRACK_TX2_VSWR = 0x02000, + TRACK_ORX1_QEC_SNLO = 0x10000, + TRACK_ORX2_QEC_SNLO = 0x20000, + TRACK_SRX_QEC = 0x40000 +} mykonosTrackingCalibrations_t; + + +/** + * \brief Enum to select the desired status calibration path delay read back + */ +typedef enum +{ + MYK_DPD_PATH_DELAY = 0, + MYK_CLGC_PATH_DELAY = 1, + MYK_VSWR_PATH_DELAY = 2 +} mykonosPathDelaySel_t; + +/** + * \brief Enum to set the GPIO3v3 mode + */ +typedef enum +{ + GPIO3V3_LEVELTRANSLATE_MODE = 1, /*!< Level translate mode, signal level on low voltage GPIO output on GPIO3v3 pins */ + GPIO3V3_INVLEVELTRANSLATE_MODE = 2, /*!< Inverted Level translate mode, inverse of signal level on low voltage GPIO output on GPIO3v3 pins */ + GPIO3V3_BITBANG_MODE = 3, /*!< Manual mode, API function sets output pin levels and reads input pin levels */ + GPIO3V3_EXTATTEN_LUT_MODE = 4 /*!< GPIO3v3 output level follows Rx1/Rx2 gain table external control 6bit field. */ +} mykonosGpio3v3Mode_t; + +/** + * \brief Enum to set the low voltage GPIO mode + */ +typedef enum +{ + GPIO_MONITOR_MODE = 0, /*!< Allows a choice of debug signals to output from Mykonos to monitor the state of the device */ + GPIO_BITBANG_MODE = 3, /*!< Manual mode, API function sets output pin levels and reads input pin levels */ + GPIO_ARM_OUT_MODE = 9, /*!< Allows internal ARM processor to output on GPIO pins */ + GPIO_SLICER_OUT_MODE = 10 /*!< Allows Slicer active configuration to the GPIO output pins */ +} mykonosGpioMode_t; + +/** + * \brief Enum for ARM states + */ +typedef enum +{ + MYK_ARM_POWERUP = 0x00, /*!< ARM is powered up and ready to be programmed */ + MYK_ARM_READY = 0x01, /*!< ARM enter this state once the boot up sequence is completed */ + MYK_ARM_IDLE = 0x02, /*!< ARM enter this state after initial calibrations are completed */ + MYK_ARM_RADIO_ON = 0x04, /*!< ARM has moved from MYKONOS_ARM_IDLE state into MYKONOS_ARM_RADIO_ON after the proper command, an abort command will move back to MYKONOS_ARM_IDLE state */ + MYK_ARM_PROFILE_ERROR = 0x08, /*!< ARM has detected an illegal profile */ + MYK_ARM_CAL_ERROR = 0x40, /*!< ARM has detected an error in the tracking calibrations */ + MYK_ARM_EXCEPTION = 0x80 /*!< ARM system problem has been detected */ +} mykonosArmState_t; + +/** + * \brief Enum for channel selection for DC offset settings. + */ +typedef enum +{ + MYK_DC_OFFSET_RX_CHN = 0x01, /*!< Select Rx channel */ + MYK_DC_OFFSET_ORX_CHN = 0x02, /*!< Select ORx channel */ + MYK_DC_OFFSET_SNF_CHN = 0x04 /*!< Select Sniffer channel */ +}mykonosDcOffsetChannels_t; + +/** + * \brief Enum of Rx channels for configuring (Enable /disable) DC offsets. + */ +typedef enum +{ + MYK_DC_OFFSET_ALL_OFF = 0x00, /*!< Disable all the channels */ + MYK_DC_OFFSET_RX1 = 0x01, /*!< Enables Rx1 */ + MYK_DC_OFFSET_RX2 = 0x02, /*!< Enables Rx2 */ + MYK_DC_OFFSET_SNF = 0x04, /*!< Enables Sniffer */ + MYK_DC_OFFSET_ORX = 0x08, /*!< Enables ORx */ + MYK_DC_OFFSET_AVAILABLE = 0x0F /*!< Enables all the channels */ +}mykonosRxDcOffsettEn_t; + +/** + * \brief Enum of build type + */ +typedef enum +{ + MYK_BUILD_RELEASE = 0X00, + MYK_BUILD_DEBUG = 0x01, + MYK_BUILD_TEST_OBJECT = 0x04 +}mykonosBuild_t; + +/** + * \brief Enum for DPD error codes + */ +typedef enum +{ + MYK_NO_ERROR = 0, /*!< No Error */ + MYK_ORX_DISABLED = 1, /*!< ORX_DISABLED */ + MYK_TX_DISABLED = 2, /*!< TX_DISABLED */ + MYK_PATHDELAY_NOT_SETUP = 3, /*!< PATHDELAY_NOT_SETUP */ + MYK_DPD_INIT_NOT_RUN = 4, /*!< DPD_INIT_NOT_RUN */ + MYK_ORX_SIG_TOO_LOW = 5, /*!< ORX_SIG_TOO_LOW */ + MYK_ORX_SIG_SATURATED = 6, /*!< ORX_SIG_SATURATED */ + MYK_TX_SIG_TOO_LOW = 7, /*!< TX_SIG_TOO_LOW */ + MYK_TX_SIG_SATURATED = 8, /*!< TX_SIG_SATURATED */ + MYK_MODEL_ERROR_HIGH = 9, /*!< MODEL_ERROR_HIGH */ + MYK_AM_AM_OUTLIERS = 10, /*!< AM_AM_OUTLIERS */ + MYK_INVALID_TX_PROFILE = 11, /*!< INVALID_TX_PROFILE */ + MYK_ORX_TRACKING_DISABLED = 12, /*!< ORX_TRACKING_DISABLED ORx tracking must be enabled */ + MYK_ERR_RESERVED_13 = 13, /*!< Reserved DPD error */ + MYK_ERR_BAD_ACTUATOR_MODEL = 14, /*!< DPD actuator model is in bad state */ + MYK_ERR_LOW_POWER_ACTUATOR_BYPASS = 15, /*!< DPD actuator bypassed due to low input power */ + + MYK_DPD_ERROR_END +} mykonosDpdErrors_t; + +/** + * \brief Enum for DPD reset modes + */ +typedef enum +{ + MYK_DPD_NO_ACTION = 0, /*!< DPD no Action error */ + MYK_DPD_RESET_FULL = 1, /*!< Full DPD reset */ + MYK_DPD_RESET_PRIOR = 4, /*!< Reset only prior model */ + MYK_DPD_RESET_CORRELATOR = 8, /*!< Reset correlator only */ + + MYK_DPD_RESET_END +} mykonosDpdResetMode_t; + + +/** + * \brief Enum for CLGC Tx attenuation tuning range modes + */ +typedef enum +{ + MYK_CLGC_ATTEN_TUNING_PRESET = 0, /*!< Set attenuation to the tx[]AttenTuningPreset */ + MYK_CLGC_ATTEN_DISCARD = 1, /*!< Ignore calculated attenuation level and keep the existing one */ + MYK_CLGC_ATTEN_UPDATE = 2, /*!< Set attenuation to tx[]AttenTuningPreset + tx[]AttenTuningRange if calculated attenuation is above this level + Set attenuation to tx[]AttenTuningPreset - tx[]AttenTuningRange if calculated attenuation is below this level*/ + + MYK_CLGC_ATTEN_END +} mykonosClgcAttenTuningMode_t; + +/** + * \brief Data structure to hold 3.3 VDC GPIO settings + */ +typedef struct +{ + uint16_t gpio3v3Oe; /*!< Pin direction: bit per 3.3v GPIO, 0=Input, 1=Output from Mykonos device */ + mykonosGpio3v3Mode_t gpio3v3SrcCtrl3_0; /*!< Mode for GPIO3v3[3:0] pins */ + mykonosGpio3v3Mode_t gpio3v3SrcCtrl7_4; /*!< Mode for GPIO3v3[7:4] pins */ + mykonosGpio3v3Mode_t gpio3v3SrcCtrl11_8; /*!< Mode for GPIO3v3[11:8] pins */ +} mykonosGpio3v3_t; + +/** + * \brief Data structure to hold low voltage GPIO settings + */ +typedef struct +{ + uint32_t gpioOe; /*!< Output Enable per low voltage GPIO pin (1=output, 0=input) */ + mykonosGpioMode_t gpioSrcCtrl3_0; /*!< Mode for low voltage GPIO[3:0] pins */ + mykonosGpioMode_t gpioSrcCtrl7_4; /*!< Mode for low voltage GPIO[7:4] pins */ + mykonosGpioMode_t gpioSrcCtrl11_8; /*!< Mode for low voltage GPIO[11:8] pins */ + mykonosGpioMode_t gpioSrcCtrl15_12; /*!< Mode for low voltage GPIO[15:12] pins */ + mykonosGpioMode_t gpioSrcCtrl18_16; /*!< Mode for low voltage GPIO[18:16] pins */ +} mykonosGpioLowVoltage_t; + +/** + * \brief Structure used within the DPD config structure to hold a int8_t complex number + */ +typedef struct{ + int8_t real; /*!< real part of the complex number */ + int8_t imag; /*!< imaginary part of the complex number */ +} int8_cpx; + +/** + * \brief Structure to configure DPD (Only valid for a DPD-enabled transceiver) + * \deprecated robustModeling member of this structure is no longer in use. + * This information is loaded into the ARM memory using the + * MYKONOS_configDpd() function before running the DPD init or tracking + * calibrations. These values can only be changed when the ARM is in the + * radioOff state. + */ +typedef struct +{ + uint8_t damping; /*!< 1/2^(damping + 8) fraction of previous model 'forgotten' per adaptation (default: 5 = '1/8192' , valid 0 to 15), 0 = infinite damping */ + uint8_t numWeights; /*!< number of weights to use for int8_cpx weights weights member of this structure (default = 1) */ + uint8_t modelVersion; /*!< DPD model version: one of four different generalized polynomial models: 0 = same as R0 silicon, 1-3 are new and the best one depends on the PA (default: 2) */ + uint8_t highPowerModelUpdate; /*!< 1 = Update saved model whenever peak Tx digital RMS is within 1dB of historical peak Tx RMS */ + uint8_t modelPriorWeight; /*!< Determines how much weight the loaded prior model has on DPD modeling (Valid 0 - 32, default 20) */ + uint8_t robustModeling; /*!< This is deprecated and no longer in use */ + uint16_t samples; /*!< number of samples to capture (default: 512, valid 64 - 32768) */ + uint16_t outlierThreshold; /*!< threshold for sample in AM-AM plot outside of 1:1 line to be thrown out. (default: 50% = 8192/2, valid 8192 to 1) */ + int16_t additionalDelayOffset; /*!< 16th of an ORx sample (16=1sample), (default 0, valid -64 to 64) */ + uint16_t pathDelayPnSeqLevel; /*!< Default 255 (-30dBFs=(20Log10(value/8192)), (valid range 1 to 8191) */ + int8_cpx weights[3]; /*!< DPD model error weighting (real/imag valid from -128 to 127) */ +} mykonosDpdConfig_t; + +/** + * \brief Structure to configure the feature to bypass DPD actuator when signal power below a threshold + * + */ +typedef struct +{ + uint8_t bypassActuatorEn; /*!< Enable/Disable feature to bypass actuator when input power below a certain threshold */ + mykonosDpdResetMode_t bypassActuatorMode; /*!< Follows reset DPD enum */ + uint16_t bypassActuatorLevel; /*!< Tx RMS level below which actuator is bypassed. P_dBFS = 20*log10(bypassActuatorLevel/8192) */ +} mykonosDpdBypassConfig_t; + + + +/** + * \brief Structure to configure the DPD actuator gain check + * + */ +typedef struct +{ + uint8_t actuatorGainCheckEn; /*!< Enable Gain check for DPD actuator */ + mykonosDpdResetMode_t actuatorGainCheckMode; /*!< Follows reset DPD enum */ + uint16_t actuatorGainCheckLevel; /*!< If the gain difference before and after the actuator exceeds this value an error will be issued + and the actuator will reset depending on the actuatorGainCheckMode, in 0.01dB, where a value of 200 => 2dB*/ +} mykonosDpdActuatorCheck_t; + +/** + * \brief Structure to configure CLGC (Closed Loop Gain Control) (Only valid for a DPD-enabled transceiver) + * + * This information is loaded into the ARM memory using the + * MYKONOS_configClgc() function before running the CLGC init or tracking + * calibrations. + * These values can be changed when the ARM is in the radioOff or radioOn states. + */ +typedef struct +{ + int16_t tx1DesiredGain; /*!< (value = 100 * dB (valid range -32768 to 32767) - total gain and attenuation from Mykonos Tx1 output to ORx1 input in (dB * 100) */ + int16_t tx2DesiredGain; /*!< (value = 100 * dB (valid range -32768 to 32767) - total gain and attenuation from Mykonos Tx2 output to ORx2 input in (dB * 100) */ + uint16_t tx1AttenLimit; /*!< (valid range 0 - 40dB), no default, depends on PA, Protects PA by making sure Tx1Atten is not reduced below the limit */ + uint16_t tx2AttenLimit; /*!< (valid range 0 - 40dB), no default, depends on PA, Protects PA by making sure Tx2Atten is not reduced below the limit */ + uint16_t tx1ControlRatio; /*!< valid range 1-100, default 45 */ + uint16_t tx2ControlRatio; /*!< valid range 1-100, default 45 */ + uint8_t allowTx1AttenUpdates; /*!< 0= allow CLGC to run, but Tx1Atten will not be updated. User can still read back power measurements. 1=CLGC runs, and Tx1Atten automatically updated */ + uint8_t allowTx2AttenUpdates; /*!< 0= allow CLGC to run, but Tx2Atten will not be updated. User can still read back power measurements. 1=CLGC runs, and Tx2Atten automatically updated */ + + int16_t additionalDelayOffset; /*!< 16th of an ORx sample (16=1sample), (default 0, valid -64 to 64) */ + uint16_t pathDelayPnSeqLevel; /*!< Default 255 (-30dBFs=(20Log10(value/8192)), (valid range 1 to 8191) */ + + uint16_t tx1RelThreshold; /*!< Threshold for Tx1 in order to stop tracking, value = 100 * dB, default 6db then value = 600 */ + uint16_t tx2RelThreshold; /*!< Threshold for Tx2 in order to stop tracking, value = 100 * dB, default 6db then value = 600 */ + uint8_t tx1RelThresholdEn; /*!< Threshold feature enable for Tx1, 0 = disable, 1 = enable, default = 0 */ + uint8_t tx2RelThresholdEn; /*!< Threshold feature enable for Tx2, 0 = disable, 1 = enable, default = 0 */ +} mykonosClgcConfig_t; + +/** + * \brief Structure to configure the CLGC attenuation tuning range + */ +typedef struct +{ + mykonosClgcAttenTuningMode_t tx1AttenTuningLimitMode; /*!< Tx1 CLGC Attenuation tuning mode */ + mykonosClgcAttenTuningMode_t tx2AttenTuningLimitMode; /*!< Tx2 CLGC Attenuation tuning mode */ + uint16_t tx1AttenTuningPreset; /*!< Tx1 CLGC nominal attenuation, valid range is 0 to 839 with a 0.05dB*/ + uint16_t tx2AttenTuningPreset; /*!< Tx2 CLGC nominal attenuation, valid range is 0 to 839 with a 0.05dB*/ + uint16_t tx1AttenTuningRange; /*!< Tx1 CLGC relative attenuation range around nominal attenuation, valid range is 0 to 420 with a 0.05dB*/ + uint16_t tx2AttenTuningRange; /*!< Tx2 CLGC relative attenuation range around nominal attenuation, valid range is 0 to 420 with a 0.05dB*/ +} mykonosClgcAttenTuningConfig_t; + +/** + * \brief Structure to configure VSWR (Only valid for a DPD-enabled transceiver) + * + * This information is loaded into the ARM memory using the + * MYKONOS_configVswr() function before running the VSWR init or tracking + * calibrations. + * These values can be changed when the ARM is in the radioOff states. + */ +typedef struct +{ + /* VSWR init cal parameters */ + int16_t additionalDelayOffset; /*!< 16th of an ORx sample (16=1sample), (default 0, valid -64 to 64) */ + uint16_t pathDelayPnSeqLevel; /*!< Default 255 (-30dBFs=(20Log10(value/8192)), (valid range 1 to 8191) */ + + /* VSWR tracking cal parameters */ + uint8_t tx1VswrSwitchGpio3p3Pin; /*!< 3p3V GPIO pin to use to control VSWR switch for Tx1 (valid 0-11) (output from Mykonos) */ + uint8_t tx2VswrSwitchGpio3p3Pin; /*!< 3p3V GPIO pin to use to control VSWR switch for Tx2 (valid 0-11) (output from Mykonos) */ + uint8_t tx1VswrSwitchPolarity; /*!< 3p3v GPIO pin polarity for forward path of Tx1, opposite used for reflection path (1 = high level, 0 = low level) */ + uint8_t tx2VswrSwitchPolarity; /*!< 3p3v GPIO pin polarity for forward path of Tx2, opposite used for reflection path (1 = high level, 0 = low level) */ + uint8_t tx1VswrSwitchDelay_us; /*!< Delay for Tx1 after flipping the VSWR switch until measurement is made. In us resolution with a range from 0 to 255us */ + uint8_t tx2VswrSwitchDelay_us; /*!< Delay for Tx2 after flipping the VSWR switch until measurement is made. In us resolution with a range from 0 to 255us */ +} mykonosVswrConfig_t; + +typedef struct +{ + /** + * errorStatus(decimal) | Description + * ---------------------|----------------------- + * 0 | NO ERROR (Tracking success) + * 1 | Tx data path not enabled + * 2 | ORX data path is not enabled + * 3 | Loopback switch closed + * 4 | VSWR init cal was not run + * 5 | Path delay not setup + * 6 | Data measurement was aborted + * 7 | VSWR disabled + * 8 | If set, entered cal but not finished + * 9 | No GPIO configured in single ORx configuration + * 10 | Tx is not observable with any of the ORx Channels + * 11 | ORX_TRACKING_DISABLED ORx tracking must be enabled + * + */ + uint32_t errorStatus; + uint32_t trackCount; /*!< Number of times VSWR tracking has run since last reset */ + int32_t forwardGainRms_dB; /*!< Forward RMS gain measured from Tx to ORx path (1 = 0.01 dB Gain) */ + int32_t forwardGainReal; /*!< Real part of the forward path complex gain (1 = 0.01 linear Gain) */ + int32_t forwardGainImag; /*!< Imaginary part of the forward path complex gain (1 = 0.01 linear Gain) */ + int32_t reflectedGainRms_dB; /*!< Measured reflection path gain in RMS (1 = 0.01 dB Gain) */ + int32_t reflectedGainReal; /*!< Real part of the reflection path complex gain (1 = 0.01 linear Gain) */ + int32_t reflectedGainImag; /*!< Imaginary part of the reflection path complex gain (1 = 0.01 linear Gain) */ + int32_t vswr_forward_tx_rms; /*!< Forward RMS measured from Tx path (1 = 0.01 dBFS) */ + int32_t vswr_forward_orx_rms; /*!< Forward RMS measured from ORx path (1 = 0.01 dBFS) */ + int32_t vswr_reflection_tx_rms; /*!< Reflected RMS measured from Tx path (1 = 0.01 dBFS) */ + int32_t vswr_reflection_orx_rms; /*!< Reflected RMS measured from ORx path (1 = 0.01 dBFS) */ +} mykonosVswrStatus_t; + +/** + * \brief Data structure to hold Mykonos FIR filter settings + */ +typedef struct +{ + int8_t gain_dB; /*!< Filter gain in dB*/ + uint8_t numFirCoefs; /*!< Number of coefficients in the FIR filter */ + int16_t *coefs; /*!< A pointer to an array of filter coefficients */ +} mykonosFir_t; + +/** + * \brief Data structure to hold Mykonos JESD204b Framer configuration settings + */ +typedef struct +{ + uint8_t bankId; /*!< JESD204B Configuration Bank ID extension to Device ID. Range is 0..15 */ + uint8_t deviceId; /*!< JESD204B Configuration Device ID link identification number. Range is 0..255 */ + uint8_t lane0Id; /*!< JESD204B Configuration starting Lane ID. If more than one lane is used, each lane will increment from the Lane0 ID. Range is 0..31 */ + uint8_t M; /*!< Number of ADCs (0, 2, or 4) where 2 ADCs are required per receive chain (I and Q) */ + uint8_t K; /*!< Number of frames in a multiframe. Default = 32, F*K must be modulo 4. Where, F=2*M/numberOfLanes */ + uint8_t scramble; /*!< Scrambling off if framerScramble = 0, if framerScramble > 0 scrambling is enabled */ + uint8_t externalSysref; /*!< External SYSREF select. 0 = use internal SYSREF, 1 = use external SYSREF */ + uint8_t serializerLanesEnabled; /*!< Serializer lane select bit field. Where, [0] = Lane0 enabled, [1] = Lane1 enabled, etc */ + uint8_t serializerLaneCrossbar; /*!< Lane crossbar to map framer lane outputs to physical lanes */ + uint8_t serializerAmplitude; /*!< Serializer amplitude setting. Default = 22. Range is 0..31 */ + uint8_t preEmphasis; /*!< Serializer pre-emphasis setting. Default = 4 Range is 0..7 */ + uint8_t invertLanePolarity; /*!< Lane inversion select. Default = 0. Where, bit[0] = 0 will invert lane [0], bit[1] = 0 will invert lane 1, etc. */ + uint8_t lmfcOffset; /*!< LMFC offset value for deterministic latency setting. Range is 0..31 */ + uint8_t newSysrefOnRelink; /*!< Flag for determining if SYSREF on relink should be set. Where, if > 0 = set, 0 = not set */ + uint8_t enableAutoChanXbar; /*!< Flag for determining if auto channel select for the xbar should be set. Where, if > 0 = set, '0' = not set */ + uint8_t obsRxSyncbSelect; /*!< Selects SYNCb input source. Where, 0 = use RXSYNCB for this framer, 1 = use OBSRX_SYNCB for this framer */ + uint8_t rxSyncbMode; /*!< Flag for determining if CMOS mode for RX Sync signal is used. Where, if > 0 = CMOS, '0' = LVDS */ + uint8_t overSample; /*!< Selects framer bit repeat or oversampling mode for lane rate matching. Where, 0 = bitRepeat mode (changes effective lanerate), 1 = overSample (maintains same lane rate between ObsRx framer and Rx framer and oversamples the ADC samples) */ + uint8_t enableManualLaneXbar; /*!< Flag for determining if API will calculate the appropriate settings for framer lane outputs to physical lanes. Where, if '0' = API will set automatic lane crossbar, '1' = set to manual mode and the value in serializerLaneCrossbar will be used */ +} mykonosJesd204bFramerConfig_t; + +/* NO Doxygen content required for this data structure as this is used internally */ +/// @cond +typedef struct +{ + uint8_t DID; /*!< JESD204B Configuration Device ID for ILAS check */ + uint8_t BID; /*!< JESD204B Configuration Bank ID for ILAS check */ + uint8_t LID0; /*!< JESD204B Configuration starting Lane ID for ILAS check */ + uint8_t L; /*!< JESD204B Configuration L = lanes per data converter for ILAS check */ + uint8_t SCR; /*!< JESD204B Configuration scramble setting for ILAS check */ + uint8_t F; /*!< JESD204B Configuration F = octets per frame for ILAS check */ + uint8_t K; /*!< JESD204B Configuration K = frames per multiframe for ILAS check */ + uint8_t M; /*!< JESD204B Configuration M = number of data converters for ILAS check */ + uint8_t N; /*!< JESD204B Configuration N = data converter sample resolution for ILAS check */ + uint8_t CS; /*!< JESD204B Configuration CS = number of control bits transferred per sample per frame for ILAS check */ + uint8_t NP; /*!< JESD204B Configuration NP = JESD204B word size based on the highest resolution of the data converter for ILAS check */ + uint8_t S; /*!< JESD204B Configuration S = number of samples/data converter/frame for ILAS check */ + uint8_t CF; /*!< JESD204B Configuration CF = '0' = control bits appended to each sample, '1' = appended to end of frame for ILAS check */ + uint8_t HD; /*!< JESD204B Configuration HD = high density bit - samples are contained within lane (0) or divided over more than one lane (1) for ILAS check */ + uint8_t FCHK0; /*!< JESD204B Configuration checksum for ILAS check */ +} mykonosJesd204bLane0Config_t; +/// @endcond + +/** +* \brief Data structure to hold the settings for the deserializer and deframer configuration +* +* EQ Settings | 3GHz Loss (dB) |6GHz Loss (dB) | max FR408HR Length (in) | max FR4 Length (in) +*-------------|----------------|---------------|-------------------------|--------------------- +* 0 | 6.5 | 14 | 20 | 12 +* 1 | 11.5 | 21 | 30 | 20 +* 2 | 18 | 31 | 46 | 32 +* 3 | 21.5 | 38 | 56 | 40 +* 4 | 22 | 39 | 60 | 43 +*/ +typedef struct +{ + uint8_t bankId; /*!< Extension to Device ID. Range is 0..15 */ + uint8_t deviceId; /*!< Link identification number. Range is 0..255 */ + uint8_t lane0Id; /*!< Lane0 ID. Range is 0..31 */ + uint8_t M; /*!< Number of DACs (0, 2, or 4) - 2 DACs per transmit chain (I and Q) */ + uint8_t K; /*!< Number of frames in a multiframe. Default = 32, F*K = modulo 4. Where, F=2*M/numberOfLanes */ + uint8_t scramble; /*!< Scrambling off if scramble = 0, if framerScramble > 0 scrambling is enabled */ + uint8_t externalSysref; /*!< External SYSREF select. 0 = use internal SYSREF, 1 = external SYSREF */ + uint8_t deserializerLanesEnabled; /*!< Deserializer lane select bit field. Where, [0] = Lane0 enabled, [1] = Lane1 enabled, etc */ + uint8_t deserializerLaneCrossbar; /*!< Lane crossbar to map physical lanes to deframer lane inputs [1:0] = Deframer Input 0 Lane section, [3:2] = Deframer Input 1 lane select, etc */ + uint8_t EQSetting; /*!< Equalizer setting. Applied to all deserializer lanes. Range is 0..4 */ + uint8_t invertLanePolarity; /*!< PN inversion per each lane. bit[0] = 1 Invert PN of Lane 0, bit[1] = Invert PN of Lane 1, etc */ + uint8_t lmfcOffset; /*!< LMFC offset value to adjust deterministic latency. Range is 0..31 */ + uint8_t newSysrefOnRelink; /*!< Flag for determining if SYSREF on relink should be set. Where, if > 0 = set, '0' = not set */ + uint8_t enableAutoChanXbar; /*!< Flag for determining if auto channel select for the xbar should be set. Where, if > 0 = set, '0' = not set */ + uint8_t txSyncbMode; /*!< Flag for determining if CMOS mode for TX Sync signal is used. Where, if > 0 = CMOS, '0' = LVDS */ + uint8_t enableManualLaneXbar; /*!< Flag for determining if API will calculate the appropriate settings for deframer lane in to physical lanes. Where, if '0' = API will set automatic lane crossbar, '1' = set to manual mode and the value in deserializerLaneCrossbar will be used */ +} mykonosJesd204bDeframerConfig_t; + +/** + * \brief Data structure to hold settings for the current Rx specific use case profile + */ +typedef struct +{ + uint8_t adcDiv; /*!< The divider used to generate the ADC clock (Valid: 1,2) */ + mykonosFir_t *rxFir; /*!< Pointer to Rx FIR filter structure */ + uint8_t rxFirDecimation; /*!< Rx FIR decimation (1,2,4) */ + uint8_t rxDec5Decimation; /*!< Decimation of Dec5 or Dec4 filter (5,4) */ + uint8_t enHighRejDec5; /*!< If set, and DEC5 filter used, will use a higher rejection DEC5 FIR filter. Where, 1 = enabled, 0 = disabled */ + uint8_t rhb1Decimation; /*!< RX Halfband1 (HB1) decimation. Can be either 1 or 2 */ + uint32_t iqRate_kHz; /*!< Rx IQ data rate in kHz */ + uint32_t rfBandwidth_Hz; /*!< Rx RF passband bandwidth for the profile */ + uint32_t rxBbf3dBCorner_kHz; /*!< Rx BBF (TIA) 3dB corner in kHz */ + uint16_t *customAdcProfile; /*!< Custom ADC profile to set the bandwidth of the ADC response */ +} mykonosRxProfile_t; + +/** + * \brief Data structure to hold settings for the current Tx specific use case profile + */ +typedef struct +{ + mykonosDacDiv_t dacDiv; /*!< The divider used to generate the DAC clock (ENUM Values)*/ + mykonosFir_t *txFir; /*!< Pointer to Tx FIR filter structure */ + uint8_t txFirInterpolation; /*!< The TX digital FIR filter interpolation (1,2,4) */ + uint8_t thb1Interpolation; /*!< Tx Halfband1 (HB1) filter interpolation (1,2) */ + uint8_t thb2Interpolation; /*!< Tx Halfband2 (HB2) filter interpolation (1,2) */ + uint8_t txInputHbInterpolation; /*!< Interpolation of half band filter before the programmable FIR (valid 1,2,4) */ + uint32_t iqRate_kHz; /*!< Tx IQ data rate in kHz */ + uint32_t primarySigBandwidth_Hz; /*!< Tx primary signal BW */ + uint32_t rfBandwidth_Hz; /*!< Tx RF passband bandwidth for the profile */ + uint32_t txDac3dBCorner_kHz; /*!< DAC filter 3dB corner in kHz */ + uint32_t txBbf3dBCorner_kHz; /*!< Tx BBF 3dB corner in kHz */ + uint8_t enableDpdDataPath; /*!< Enable Tx Dynamic pre distortion - only valid for a DPD-enabled transceiver */ +} mykonosTxProfile_t; + +/** + * \brief Data structure to hold SnRx gain control settings for initialization and during use + */ +typedef struct +{ + mykonosGainMode_t gainMode; /*!< Current Sniffer gain control mode setting */ + uint8_t gainIndex; /*!< Current Sniffer gain index. Can be used differently for Manual Gain control/AGC */ + uint8_t maxGainIndex; /*!< Max gain index for the currently loaded Sniffer Gain table */ + uint8_t minGainIndex; /*!< Min gain index for the currently loaded Sniffer Gain table */ +} mykonosSnifferGainControl_t; + +/** + * \brief Data structure to hold ORx gain control settings for initialization and during use + */ +typedef struct +{ + mykonosGainMode_t gainMode; /*!< Current ORx gain control mode setting */ + uint8_t orx1GainIndex; /*!< ORx1 Gain Index, can be used in different ways for manual and AGC gain control */ + uint8_t orx2GainIndex; /*!< ORx2 Gain Index, can be used in different ways for manual and AGC gain control */ + uint8_t maxGainIndex; /*!< Max gain index for the currently loaded ORx Gain table */ + uint8_t minGainIndex; /*!< Min gain index for the currently loaded ORx Gain table */ +} mykonosORxGainControl_t; + +/** + * \brief Data structure to hold Rx gain control settings for initialization and during use + */ +typedef struct +{ + mykonosGainMode_t gainMode; /*!< Current Rx gain control mode setting */ + uint8_t rx1GainIndex; /*!< Rx1 Gain Index, can be used in different ways for manual and AGC gain control */ + uint8_t rx2GainIndex; /*!< Rx2 Gain Index, can be used in different ways for manual and AGC gain control */ + uint8_t rx1MaxGainIndex; /*!< Max gain index for the currently loaded Rx1 Gain table */ + uint8_t rx1MinGainIndex; /*!< Min gain index for the currently loaded Rx1 Gain table */ + uint8_t rx2MaxGainIndex; /*!< Max gain index for the currently loaded Rx2 Gain table */ + uint8_t rx2MinGainIndex; /*!< Min gain index for the currently loaded Rx2 Gain table */ + uint8_t rx1Rssi; /*!< Stores Rx1 RSSI value read back from the Mykonos */ + uint8_t rx2Rssi; /*!< Stores Rx2 RSSI value read back from the Mykonos */ +} mykonosRxGainControl_t; + +/** + * \brief Data structure to hold peak detector settings for the AGC + */ +typedef struct +{ + /* Threshold Settings */ + uint8_t apdHighThresh; /*!< APD high threshold. Must be greater than apdLowThresh. Min = apdLowThresh, Max = 0x3F. 6-bit field. */ + uint8_t apdLowThresh; /*!< APD low threshold. Must be less than apdHighThresh. Min = 0, Max = apdHighThresh. 6-bit field. */ + uint8_t hb2HighThresh; /*!< HB2 high threshold. Must be greater than hb2LowThresh. Min = hb2LowThresh, Max = 0xFF. 8-bit field. */ + uint8_t hb2LowThresh; /*!< HB2 low threshold. Must be less than hb2HighThresh. Min = 0, Max = hb2HighThresh. 8-bit field. */ + uint8_t hb2VeryLowThresh; /*!< HB2 very low threshold. Must be less than hb2LowThresh. Min = 0, Max = hb2LowThresh. 8-bit field. */ + + /* Threshold Counter Settings */ + uint8_t apdHighThreshExceededCnt; /*!< APD high threshold exceeded counter. Sets number of peaks to detect above apdHighThresh to cause gain decrement according to apdHighGainStepAttack. 8-bit field. */ + uint8_t apdLowThreshExceededCnt; /*!< APD low threshold exceeded counter. Sets number of peaks to detect below apdLowThresh to cause gain increment according to apdLowGainStepRecovery. 8-bit field. */ + uint8_t hb2HighThreshExceededCnt; /*!< HB2 high threshold exceeded counter. Sets number of overloads to detect above hb2HighThresh to cause gain decrement according to hb2HighGainStepAttack. 8-bit field. */ + uint8_t hb2LowThreshExceededCnt; /*!< HB2 low threshold exceeded counter. Sets number of peaks to detect below hb2LowThresh to cause gain increment according to hb2LowGainStepRecovery. 8-bit field. */ + uint8_t hb2VeryLowThreshExceededCnt; /*!< HB2 very low threshold exceeded counter. Sets number of peaks to detect below hb2VeryLowThresh to cause gain increment according to hb2VeryLowGainStepRecovery. 8-bit field. */ + + /* Gain Step Settings */ + uint8_t apdHighGainStepAttack; /*!< Number of gain indices to decrement gain when apdHighThreshExceededCnt is exceeded. 5-bit field. */ + uint8_t apdLowGainStepRecovery; /*!< Number of gain indices to increment gain when apdLowThreshExceededCnt is exceeded. 5-bit field */ + uint8_t hb2HighGainStepAttack; /*!< Number of gain indices to decrement gain when hb2HighThreshExceededCnt is exceeded. 5-bit field */ + uint8_t hb2LowGainStepRecovery; /*!< Number of gain indices to increment gain when hb2LowThreshExceededCnt is exceeded. 5-bit field*/ + uint8_t hb2VeryLowGainStepRecovery; /*!< Number of gain indices to increment gain when hb2VeryLowThreshExceededCnt is exceeded. 5-bit field */ + + /* Fast Attack Settings */ + uint8_t apdFastAttack; /*!< [1] Enables APD fast attack mode - gain decrements immediately when apdHighThreshExceededCnt is exceeded. [0] disables APD fast attack mode - gain decrements at the expiry of agcGainUpdateCounter. 1-bit field. */ + uint8_t hb2FastAttack; /*!< [1] Enables HB2 fast attack mode - gain decrements immediately when hb2HighThreshExceededCnt is exceeded. [0] disables HB2 fast attack mode - gain decrements at the expiry of agcGainUpdateCounter. 1-bit field. */ + + /* HB2 Configuration Settings */ + uint8_t hb2OverloadDetectEnable; /*!< [1] Enables the HB2 overload detector. [0] Disables the HB2 overload detector. 1-bit field. */ + uint8_t hb2OverloadDurationCnt; /*!< Sets the samples size window of the HB2 overload detector. If hb2OverloadThreshCnt number of overloads are detected, the hb2xxxThreshExceededCnt increments. 3-bit field. [001]=1, [001]=4, [010]=8, [011]=12, [100]=16, [101]=24, [110]=32, [111]=INVALID */ + uint8_t hb2OverloadThreshCnt; /*!< Sets the number of individual overloads necessary within hb2OverloadDurationCnt samples to increment the hb2xxxThreshExceededCnt */ +} mykonosPeakDetAgcCfg_t; + +/** + * \brief Data structure to hold power measurement settings for the AGC + */ +typedef struct +{ + /* Threshold Settings */ + uint8_t pmdUpperHighThresh; /*!< Power measurement upper band, high threshold . This value is a positive offset to the pmdUpperLowThresh threshold. 4-bit field */ + uint8_t pmdUpperLowThresh; /*!< Power measurement upper band, low threshold. This value sets the threshold in (negative) -dBFS. Byte value must be less than pmdLowerHighThresh. 7-bit field */ + uint8_t pmdLowerHighThresh; /*!< Power measurement lower band, high threshold. This value sets the threshold in (negative) -dBFS. Byte value must be greater than pmdUpperLowThresh. 7-bit field */ + uint8_t pmdLowerLowThresh; /*!< Power measurement lower band, low threshold. This value is a negative offset to the pmdLowerHighThresh threshold. 4-bit field */ + + /* Gain Step Settings */ + uint8_t pmdUpperHighGainStepAttack; /*!< Number of gain indices to decrement gain if pmdUpperHighThresh is exceeded by the end of the agcGainUpdateCounter. 5-bit field */ + uint8_t pmdUpperLowGainStepAttack; /*!< Number of gain indices to decrement gain if pmdUpperLowThresh is exceeded by the end of the agcGainUpdateCounter. 5-bit field */ + uint8_t pmdLowerHighGainStepRecovery; /*!< Number of gain indices to increment gain if pmdLowerHighThresh is not exceeded by the end of the agcGainUpdateCounter. 5-bit field */ + uint8_t pmdLowerLowGainStepRecovery; /*!< Number of gain indices to increment gain if pmdLowerLowThresh is not exceeded by the end of the agcGainUpdateCounter. 5-bit field */ + + /* PMD Configuration Settings */ + uint8_t pmdMeasDuration; /*!< Number of samples to measure power on. The number of samples corresponding to the 4-bit word is 8*2^(pmdMeasDuration[3:0]). This value must be less than agcGainUpdateCounter */ + uint8_t pmdMeasConfig; /*!< Power measurement configuration. 2-bit field. [00]=PMD disabled, [01]=PMD Enabled at HB2 output, [10]=Enabled at RFIR output (recommended), [11]=PMD Enabled at BBDC2 */ +} mykonosPowerMeasAgcCfg_t; + +/** + * \brief Data structure to hold general AGC settings for initialization and during use + */ +typedef struct +{ + /* Gain Table Settings */ + uint8_t agcRx1MaxGainIndex; /*!< Maximum Rx1 gain index allowed in AGC mode. Must be greater than agcRx1MinGainIndex and valid gain index. 8-bit field */ + uint8_t agcRx1MinGainIndex; /*!< Minimum Rx1 gain index allowed in AGC mode. Must be less than agcRx1MinGainIndex and valid gain index. 8-bit field */ + uint8_t agcRx2MaxGainIndex; /*!< Maximum Rx2 gain index allowed in AGC mode. Must be greater than agcRx2MinGainIndex and valid gain index. 8-bit field */ + uint8_t agcRx2MinGainIndex; /*!< Minimum Rx2 gain index allowed in AGC mode. Must be less than agcRx2MinGainIndex and valid gain index. 8-bit field */ + uint8_t agcObsRxMaxGainIndex; /*!< Maximum ObsRx gain index allowed in AGC mode. Must be greater than agcObsRxMinGainIndex and valid gain index. 8-bit field */ + uint8_t agcObsRxMinGainIndex; /*!< Minimum ObsRx gain index allowed in AGC mode. Must be less than agcObsRxMaxGainIndex and valid gain index. 8-bit field */ + uint8_t agcObsRxSelect; /*!< Sniffer or ObsRx AGC channel select. [1] = SnRx */ + + /* AGC Mode Selection */ + uint8_t agcPeakThresholdMode; /*!< [1] = Peak Threshold Mode, power based gain changes are disabled. [0] = Peak and overload detectors are ignored for gain changes */ + uint8_t agcLowThsPreventGainIncrease; /*!< [1] PMD based gain increments are ignored if apd/hb2LowThreshExceedCnt is high [0] apdLowThreshExceededCnt and hb2LowThreshExceededCnt are "Don't cares" to the AGC gain recovery */ + + /* AGC General Settings */ + uint32_t agcGainUpdateCounter; /*!< Number of samples for the AGC gain update counter. Counter operates on the IQ data rate. 22-bit field. Min = 0x000001, Max = 0x3FFFFF */ + uint8_t agcSlowLoopSettlingDelay; /*!< Number of IQ data rate clock cycles to wait after a gain change before peak/power measurements resume. 7-bit field */ + uint8_t agcPeakWaitTime; /*!< Number of IQ data rate clock cycles to wait to enable peak/overload detectors after AGC is enabled. 5-bit field. Min = 0x02. Max = 0x1F */ + uint8_t agcResetOnRxEnable; /*!< [1] = Performs a reset of the AGC slow loop state machine when Rx is disabled. [0] = AGC slow loop state machine maintains its state when Rx is disabled. */ + uint8_t agcEnableSyncPulseForGainCounter; /*!< [1] = Allows sync of agcGainUpdateCounter to the time-slot boundary. GPIO setup required. [0] = agcGainUpdateCounter functions as normal */ + + mykonosPeakDetAgcCfg_t *peakAgc; /*!< pointer to structure for Peak AGC */ + mykonosPowerMeasAgcCfg_t *powerAgc; /*!< pointer to structure for Power AGC */ +} mykonosAgcCfg_t; + +/** + * \brief Data structure to hold Tx data path settings + */ +typedef struct +{ + mykonosTxProfile_t *txProfile; /*!< Tx datapath profile, 3dB corner frequencies, and digital filter enables */ + mykonosJesd204bDeframerConfig_t *deframer; /*!< Mykonos JESD204b deframer config for the Tx data path */ + mykonosTxChannels_t txChannels; /*!< The desired Tx channels to enable during initialization */ + uint8_t txPllUseExternalLo; /*!< Internal LO=0, external LO*2 if =1 */ + uint64_t txPllLoFrequency_Hz; /*!< Tx PLL LO frequency (internal or external LO) */ + mykonosTxAttenStepSize_t txAttenStepSize; /*!< Tx Attenuation step size */ + uint16_t tx1Atten_mdB; /*!< Initial and current Tx1 Attenuation */ + uint16_t tx2Atten_mdB; /*!< Initial and current Tx2 Attenuation */ + mykonosDpdConfig_t *dpdConfig; /*!< DPD settings. Only valid for a DPD-enabled transceiver, set pointer to NULL otherwise */ + mykonosClgcConfig_t *clgcConfig; /*!< CLGC settings. Only valid for a DPD-enabled transceiver, set pointer to NULL otherwise */ + mykonosVswrConfig_t *vswrConfig; /*!< VSWR settings. Only valid for a DPD-enabled transceiver, set pointer to NULL otherwise */ +} mykonosTxSettings_t; + +/** + * \brief Data structure to hold Rx data path settings + */ +typedef struct +{ + mykonosRxProfile_t *rxProfile; /*!< Rx datapath profile, 3dB corner frequencies, and digital filter enables */ + mykonosJesd204bFramerConfig_t *framer; /*!< Rx JESD204b framer configuration structure */ + mykonosRxGainControl_t *rxGainCtrl; /*!< Rx Gain control settings structure */ + mykonosAgcCfg_t *rxAgcCtrl; /*!< Rx AGC control settings structure */ + mykonosRxChannels_t rxChannels; /*!< The desired Rx Channels to enable during initialization */ + uint8_t rxPllUseExternalLo; /*!< Internal LO = 0, external LO*2 = 1 */ + uint64_t rxPllLoFrequency_Hz; /*!< Rx PLL LO Frequency (internal or external LO) */ + uint8_t realIfData; /*!< Flag to choose if complex baseband or real IF data are selected for Rx and ObsRx paths. Where, if > 0 = real IF data, '0' = zero IF (IQ) data*/ +} mykonosRxSettings_t; + +/** + * \brief Data structure to hold ORx data path settings + */ +typedef struct +{ + mykonosRxProfile_t *orxProfile; /*!< ORx datapath profile, 3dB corner frequencies, and digital filter enables. */ + mykonosORxGainControl_t *orxGainCtrl; /*!< ObsRx gain control settings structure */ + mykonosAgcCfg_t *orxAgcCtrl; /*!< ORx AGC control settings structure */ + mykonosRxProfile_t *snifferProfile; /*!< Sniffer datapath profile, 3dB corner frequencies, and digital filter enables. */ + mykonosSnifferGainControl_t *snifferGainCtrl; /*!< SnRx gain control settings structure */ + mykonosJesd204bFramerConfig_t *framer; /*!< ObsRx JESD204b framer configuration structure */ + mykonosObsRxChannelsEn_t obsRxChannelsEnable; /*!< The desired ObsRx channels to configure/calibrate during initialization */ + mykonosObsRxLoSource_t obsRxLoSource; /*!< The sniffer/ORx mixers can use the TX_PLL or SNIFFER_PLL */ + uint64_t snifferPllLoFrequency_Hz; /*!< SnRx PLL LO frequency in Hz */ + uint8_t realIfData; /*!< Flag to choose if complex baseband or real IF data are selected for Rx and ObsRx paths. Where if > 0 = real IF data, '0' = complex data */ + uint16_t *customLoopbackAdcProfile; /*!< Custom Loopback ADC profile to set the bandwidth of the ADC response */ + mykonosObsRxChannels_t defaultObsRxChannel; /*!< Default ObsRx channel to enter when radioOn called */ +} mykonosObsRxSettings_t; + + +/** + * \brief Data structure to hold ARM GPIO pin assignments for each ARM input/output pin. + */ +typedef struct +{ + uint8_t useRx2EnablePin; /*!< 0= RX1_ENABLE controls RX1 and RX2, 1 = separate RX1_ENABLE/RX2_ENABLE pins */ + uint8_t useTx2EnablePin; /*!< 0= TX1_ENABLE controls TX1 and TX2, 1 = separate TX1_ENABLE/TX2_ENABLE pins */ + uint8_t txRxPinMode; /*!< 0= ARM command mode, 1 = Pin mode to power up Tx/Rx chains */ + uint8_t orxPinMode; /*!< 0= ARM command mode, 1 = Pin mode to power up ObsRx receiver*/ + + /* Mykonos ARM input GPIO pins -- Only valid if orxPinMode = 1 */ + uint8_t orxTriggerPin; /*!< Select desired GPIO pin (valid 4-15) */ + uint8_t orxMode2Pin; /*!< Select desired GPIO pin (valid 0-18) */ + uint8_t orxMode1Pin; /*!< Select desired GPIO pin (valid 0-18) */ + uint8_t orxMode0Pin; /*!< Select desired GPIO pin (valid 0-18) */ + + /* Mykonos ARM output GPIO pins -- always available, even when pin mode not enabled*/ + uint8_t rx1EnableAck; /*!< Select desired GPIO pin (0-15), [4] = Output Enable */ + uint8_t rx2EnableAck; /*!< Select desired GPIO pin (0-15), [4] = Output Enable */ + uint8_t tx1EnableAck; /*!< Select desired GPIO pin (0-15), [4] = Output Enable */ + uint8_t tx2EnableAck; /*!< Select desired GPIO pin (0-15), [4] = Output Enable */ + uint8_t orx1EnableAck; /*!< Select desired GPIO pin (0-15), [4] = Output Enable */ + uint8_t orx2EnableAck; /*!< Select desired GPIO pin (0-15), [4] = Output Enable */ + uint8_t srxEnableAck; /*!< Select desired GPIO pin (0-15), [4] = Output Enable */ + uint8_t txObsSelect; /*!< Select desired GPIO pin (0-15), [4] = Output Enable */ + /* When 2Tx are used with only 1 ORx input, this GPIO tells the BBIC which Tx channel is */ + /* active for calibrations, so BBIC can route correct RF Tx path into the single ORx input */ +} mykonosArmGpioConfig_t; + +/** + * \brief Data structure to hold auxiliary IO settings (AuxDAC, ARM GPIO, GPIO3.3v, low voltage GPIO, HSCP, etc) + */ +typedef struct +{ + uint16_t auxDacEnable; /*!< Aux DAC enable. One bit per Aux DAC. Where bit[0] = Aux DAC 0, bit[1] = Aux DAC 1, etc */ + uint16_t auxDacValue[10]; /*!< Aux DAC value */ + uint8_t auxDacSlope[10]; /*!< Aux DAC slope */ + uint8_t auxDacVref[10]; /*!< Aux DAC voltage reference value */ + + mykonosGpio3v3_t *gpio3v3; /*!< GPIO 3.3 VDC settings data structure pointer */ + mykonosGpioLowVoltage_t *gpio; /*!< Low voltage GPIO settings data structure pointer */ + mykonosArmGpioConfig_t *armGpio; /*!< Mykonos ARM GPIO settings*/ +} mykonosAuxIo_t; + +/** + * \brief Data structure to hold digital clock settings + */ +typedef struct +{ + uint32_t deviceClock_kHz; /*!< CLKPLL and device reference clock frequency in kHz */ + uint32_t clkPllVcoFreq_kHz; /*!< CLKPLL VCO frequency in kHz */ + mykonosVcoDiv_t clkPllVcoDiv; /*!< CLKPLL VCO divider */ + uint8_t clkPllHsDiv; /*!< CLKPLL high speed clock divider */ +} mykonosDigClocks_t; + + +/** + * \brief Data structure used to read back the Init Calibration Status + */ +typedef struct +{ + uint32_t calsDoneLastRun; /*!< Init cals that completed in the last call to MYKONOS_runInitCals() */ + uint32_t calsDoneLifetime; /*!< Init cals that have completed successfully since loading of the ARM processor */ + uint32_t calsMinimum; /*!< Minimum set of init cals that must complete before device can move to radioOn state */ + uint8_t initErrCal; /*!< If an init cal had an error, this represents the opcode of the init cal that reported an error */ + uint8_t initErrCode; /*!< If an init cal had an error, this represents the ARM error code describing the failure */ +} mykonosInitCalStatus_t; + +/** + * \brief Data structure used to read back DPD calibration status + */ +typedef struct +{ + /** + * dpdErrorStatus (decimal) | Description + * --------------------------|----------------------- + * 0 | No Error + * 1 | ORX_DISABLED + * 2 | TX_DISABLED + * 3 | PATHDELAY_NOT_SETUP + * 4 | DPD_INIT_NOT_RUN + * 5 | ORX_SIG_TOO_LOW + * 6 | ORX_SIG_SATURATED + * 7 | TX_SIG_TOO_LOW + * 8 | TX_SIG_SATURATED + * 9 | MODEL_ERROR_HIGH + * 10 | AM_AM_OUTLIERS + * 11 | INVALID_TX_PROFILE + * 12 | ORX_TRACKING_DISABLED ORx tracking must be enabled + * 13 | Cal suspended + * 14 | Reserved + * 15 | Reserved + * 16 | Reserved + * 17 | Reserved + * 18 | Reserved + */ + uint32_t dpdErrorStatus; + uint32_t dpdTrackCount; /*!< Number of times DPD tracking has run since last reset */ + uint32_t dpdModelErrorPercent; /*!< Percent Error of PA model * 10 to include 1 decimal place */ + uint32_t dpdExtPathDelay; /*!< External path delay from Tx output to ORx input, at 1/16 sample resolution of ORx sample rate */ + uint16_t dpdMaxAdaptationCurrent; /*!< max amplitude of current adaptation */ + uint16_t dpdMaxAdaptation; /*!< max amplitude of adaptation since DPD started*/ + uint32_t dpdIterCount; /*!< number of times DPD tracking has run since last reset*/ +} mykonosDpdStatus_t; + +/** + * \brief Data structure used to read back CLGC calibration status + */ +typedef struct +{ + /** + * clgcErrorStatus(decimal) | Description + * -------------------------|----------------------- + * 0 | NO ERROR + * 1 | TX Disabled + * 2 | ORx is disabled + * 3 | Loopback switch is clo + * 4 | Data measurement aborted during capture + * 5 | No initial calibration was done + * 6 | Path delay not setup + * 7 | No apply control is possible + * 8 | Control value is out of range + * 9 | CLGC feature is disabled + * 10 | TX attenuation is capped + * 11 | Gain measurement + * 12 | No GPIO configured in single ORx configuration + * 13 | Tx is not observable with any of the ORx Channels + * 14 | ORX_TRACKING_DISABLED ORx tracking must be enabled + * 15 | PA Protection Activated + * 16 | Relative Threshold Violated + * 17 | RESERVED + * 18 | Tx power too low + * 19 | ORx power too low + */ + uint32_t errorStatus; + uint32_t trackCount; /*!< Number of times CLGC tracking has run since last reset */ + int32_t desiredGain; /*!< Desired gain/attenuation from Tx output to ORx input of Mykonos device. 0.01 dB resolution */ + int32_t currentGain; /*!< Current measured gain in 0.01 dB resolution. */ + uint32_t txGain; /*!< Current TxAttenuation setting, same as MYKONOS_getTx1/2Attenuation(), in 0.05dB resolution */ + int32_t txRms; /*!< Tx digital sample power measured at DPD block input (0.01 dB resolution) */ + int32_t orxRms; /*!< ORx digital sample power measured at ORx port (0.01 dB resolution) */ +} mykonosClgcStatus_t; + +/** + * \brief Data structure to hold Tx LOL Status + */ +typedef struct +{ + uint32_t errorCode; /*!< error code from Tx LOL */ + uint32_t percentComplete; /*!< percent of required data collected for the current cal. Range 0 to 100 */ + uint32_t performanceMetric; /*!< Variance of the corrections, and gives an indication in dB on how much LO leakage is corrected on an average tracking pass. */ + uint32_t iterCount; /*!< running counter that increments each time the cal runs to completion */ + uint32_t updateCount; /*!< running counter that increments each time the cal updates the correction/actuator hardware */ +} mykonosTxLolStatus_t; + +/** + * \brief This structure contains the internal path delay + * + */ +typedef struct +{ + uint32_t forwardPathDelayCh1; /*!< Forward path delay for Channel 1 valid range is from 0 to 4095 at 1/16 sample resolution of ORx sample rate */ + uint32_t reversePathDelayCh1; /*!< Reverse path delay for Channel 1 valid range is from 0 to 4095 at 1/16 sample resolution of ORx sample rate */ + uint32_t forwardPathDelayCh2; /*!< Forward path delay for Channel 2 valid range is from 0 to 4095 at 1/16 sample resolution of ORx sample rate */ + uint32_t reversePathDelayCh2; /*!< Reverse path delay for Channel 2 valid range is from 0 to 4095 at 1/16 sample resolution of ORx sample rate */ +} mykonosPathdelay_t; + +/** + * \brief This structure contains the DPD error status counters for the different errors + * + */ +typedef struct +{ + uint32_t dpdErrorCount; /*!< DPD total error count */ + uint32_t errorCounter[MYK_DPD_ERROR_END]; /*!< array for individual error counters corresponding to ::mykonosDpdErrors_t */ +} mykonosDpdErrorCounters_t; + +/** + * \brief Data structure to hold Tx QEC Status + */ +typedef struct +{ + uint32_t errorCode; /*!< error code from Tx QEC */ + uint32_t percentComplete; /*!< percent of required data collected for the current cal. Range 0 to 100 */ + uint32_t performanceMetric; /*!< Number of codes adjusted which is the number of codes of correction made last time which can be converted to an IRR power metric as with Rx QEC, if desired. */ + uint32_t iterCount; /*!< running counter that increments each time the cal runs to completion */ + uint32_t updateCount; /*!< running counter that increments each time the cal updates the correction/actuator hardware */ +} mykonosTxQecStatus_t; + +/** + * \brief Data structure to hold Rx QEC Status + */ +typedef struct +{ + uint32_t errorCode; /*!< error code from Rx QEC */ + uint32_t percentComplete; /*!< percent of required data collected for the current cal. Range 0 to 100 */ + uint32_t selfcheckIrrDb; /*!< selfCheckIrrdDb - Power-weighted average Image Rejection Ratio (IRR) in dBc. */ + uint32_t iterCount; /*!< running counter that increments each time the cal runs to completion */ + uint32_t updateCount; /*!< running counter that increments each time the cal updates the correction/actuator hardware */ +} mykonosRxQecStatus_t; + +/** + * \brief Data structure to hold Orx QEC Status + */ +typedef struct +{ + uint32_t errorCode; /*!< error code from Orx QEC */ + uint32_t percentComplete; /*!< percent of required data collected for the current cal. Range 0 to 100 */ + uint32_t selfcheckIrrDb; /*!< selfCheckIrrdDb - Power-weighted average Image Rejection Ratio (IRR) in dBc. */ + uint32_t iterCount; /*!< running counter that increments each time the cal runs to completion */ + uint32_t updateCount; /*!< running counter that increments each time the cal updates the correction/actuator hardware */ +} mykonosOrxQecStatus_t; + +/** + * \brief Data structure to hold Mykonos device settings + */ +typedef struct +{ + spiSettings_t *spiSettings; /*!< SPI settings data structure pointer */ + mykonosRxSettings_t *rx; /*!< Rx settings data structure pointer */ + mykonosTxSettings_t *tx; /*!< Tx settings data structure pointer */ + mykonosObsRxSettings_t *obsRx; /*!< ObsRx settings data structure pointer */ + mykonosAuxIo_t *auxIo; /*!< Auxiliary IO settings data structure pointer */ + mykonosDigClocks_t *clocks; /*!< Holds settings for CLKPLL and reference clock */ + uint8_t profilesValid; /*!< Mykonos initialize function uses this as an output to remember which profile data structure pointers are valid */ +} mykonosDevice_t; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/datalink814_ge/src/hardware/mykonos/t_mykonos_gpio.h b/datalink814_ge/src/hardware/mykonos/t_mykonos_gpio.h new file mode 100644 index 0000000..71f2cf9 --- /dev/null +++ b/datalink814_ge/src/hardware/mykonos/t_mykonos_gpio.h @@ -0,0 +1,375 @@ +/*! + * \file t_mykonos_gpio.h + * \brief Mykonos GPIO error handling and type defines + * + * Mykonos API version: 1.5.2.3566 + */ + +/** +* \page Disclaimer Legal Disclaimer +* Copyright 2015-2017 Analog Devices Inc. +* Released under the AD9371 API license, for more information see the "LICENSE.txt" file in this zip file. +* +*/ + +#ifndef T_MYKONOSGPIO_H_ +#define T_MYKONOSGPIO_H_ + +#ifdef __cplusplus +extern "C" { +#endif + + +#include "../common.h" + +/** + * \brief Enum of unique error codes from the Mykonos GPIO API functions. + * Each error condition in the library should get its own enum value to allow + * easy debug of errors. + */ +typedef enum +{ + MYKONOS_ERR_GPIO_OK = 0, + MYKONOS_ERR_EN_MONITOR_OUT_NOT_ENABLED, + MYKONOS_ERR_EN_MONITOR_OUT_SRC_CTRL, + MYKONOS_ERR_MONITOR_OUT_INDEX_RANGE, + MYKONOS_ERR_GETGPIOMON_INDEX_NULL_PARM, + MYKONOS_ERR_GETGPIOMON_MONITORMASK_NULL_PARM, + + MYKONOS_ERR_MGCRX2_GPIO_DECPIN_INV_PARAM, + MYKONOS_ERR_MGCRX2_GPIO_INCPIN_INV_PARAM, + MYKONOS_ERR_MGCRX2_SOURCE_CONFIG, + MYKONOS_ERR_MGCRX2_STEP_INV_PARAM, + MYKONOS_ERR_MGCRX1_GPIO_DECPIN_INV_PARAM, + MYKONOS_ERR_MGCRX1_GPIO_INCPIN_INV_PARAM, + MYKONOS_ERR_MGCRX1_STEP_INV_PARAM, + MYKONOS_ERR_GETRX2PIN_INCSTEP_NULL_PARM, + MYKONOS_ERR_GETRX2PIN_DECSTEP_NULL_PARM, + MYKONOS_ERR_GETRX2PIN_INCPIN_NULL_PARM, + MYKONOS_ERR_GETRX2PIN_DECPIN_NULL_PARM, + MYKONOS_ERR_GETRX2PIN_EN_NULL_PARM, + MYKONOS_ERR_GETRX1PIN_INCSTEP_NULL_PARM, + MYKONOS_ERR_GETRX1PIN_DECSTEP_NULL_PARM, + MYKONOS_ERR_GETRX1PIN_INCPIN_NULL_PARM, + MYKONOS_ERR_GETRX1PIN_DECPIN_NULL_PARM, + MYKONOS_ERR_GETRX1PIN_EN_NULL_PARM, + + MYKONOS_ERR_TPCTX2_GPIO_DECPIN_INV_PARAM, + MYKONOS_ERR_TPCTX2_GPIO_INCPIN_INV_PARAM, + MYKONOS_ERR_TPCTX2_GPIO_STEP_INV_PARAM, + MYKONOS_ERR_TPCTX1_GPIO_DECPIN_INV_PARAM, + MYKONOS_ERR_TPCTX1_GPIO_INCPIN_INV_PARAM, + MYKONOS_ERR_TPCTX1_GPIO_STEP_INV_PARAM, + MYKONOS_ERR_GETTX2PIN_STEP_NULL_PARM, + MYKONOS_ERR_GETTX2PIN_INC_NULL_PARM, + MYKONOS_ERR_GETTX2PIN_DEC_NULL_PARM, + MYKONOS_ERR_GETTX2PIN_EN_NULL_PARM, + MYKONOS_ERR_GETTX2PIN_TX1TX2_NULL_PARM, + MYKONOS_ERR_GETTX1PIN_STEP_NULL_PARM, + MYKONOS_ERR_GETTX1PIN_INC_NULL_PARM, + MYKONOS_ERR_GETTX1PIN_DEC_NULL_PARM, + MYKONOS_ERR_GETTX1PIN_EN_NULL_PARM, + MYKONOS_ERR_GETTX1PIN_TX1TX2_NULL_PARM, + + MYKONOS_ERR_SPI2_INV_GPIO, + MYKONOS_ERR_SPI2_INV_SETUP, + + MYKONOS_ERR_SET_GPIO_1V8_INV_POINTER, + + MYKONOS_ERR_GETGPIOSETLEVEL_NULL_PARM, + MYKONOS_ERR_READGPIOSPI_NULL_PARM, + MYKONOS_ERR_SET_GPIO_1V8_INV_MODE, + MYKONOS_ERR_GETGPIO_OE_NULL_PARM, + MYKONOS_ERR_GPIO_OE_INV_PARAM, + MYKONOS_ERR_GPIO_SRC_PARAM_INV, + MYKONOS_ERR_GET_GPIO_SOURCE_CONTROL_NULL_PARM, + + MYKONOS_ERR_INV_GP_INT_MASK_PARM, + MYKONOS_ERR_GP_INT_STATUS_NULL_PARAM, + + MYKONOS_ERR_GETGPIO3V3OUT_NULL_PARM, + MYKONOS_ERR_SET_GPIO_3V3_INV_POINTER, + MYKONOS_ERR_GETGPIO3V3SPI_NULL_PARM, + MYKONOS_ERR_GPIO3V3OUTEN_NULL_PARM, + MYKONOS_ERR_SET_GPIO_3V3_INV_MODE, + MYKONOS_ERR_SET_GPIO_3V3_INV_SRC_CTRL, + + MYKONOS_ERR_SET_ARMGPIO_INV_POINTER, + MYKONOS_ERR_SET_ARMGPIO_PINS_ARMERROR, + MYKONOS_ERR_SET_ARMGPIO_PINS_INV_SIGNALID, + MYKONOS_ERR_SET_ARMGPIO_PINS_INV_GPIOPIN, + + MYKONOS_ERR_SETUPAUXDAC_NULL_PARAM, + MYKONOS_ERR_WRITEAUXDAC_NULL_AUXIO, + MYKONOS_ERR_READAUXADC_NULL_PARAM, + MYKONOS_ERR_SETUPAUXDAC_INV_AUXDACCODE, + MYKONOS_ERR_WRITEAUXDAC_INV_AUXDACCODE, + MYKONOS_ERR_WRITEAUXDAC_INV_AUXDACINDEX, + MYKONOS_ERR_INV_AUX_ADC_CHAN_PARM, + MYKONOS_ERR_SETUPAUXADC_INV_VCODIV, + MYKONOS_ERR_INV_AUX_ADC_DEC_PARM, + + MYKONOS_ERR_GAINCOMP_NULL_STRUCT, + MYKONOS_ERR_GAINCOMP_EN_NULL_PARM, + MYKONOS_ERR_GAINCOMP_SET_NULL_STRUCT, + MYKONOS_ERR_GAINCOMP_INV_RX1_OFFSET, + MYKONOS_ERR_GAINCOMP_INV_RX2_OFFSET, + MYKONOS_ERR_GAINCOMP_INV_STEP, + MYKONOS_ERR_GAINCOMP_INV_EN, + + MYKONOS_ERR_OBS_RX_GAINCOMP_SET_NULL_STRUCT, + MYKONOS_ERR_OBS_RX_GAINCOMP_EN_NULL_PARAM, + MYKONOS_ERR_OBS_RX_GAINCOMP_INV_EN, + MYKONOS_ERR_OBS_RX_GAINCOMP_INV_OFFSET, + MYKONOS_ERR_OBS_RX_GAINCOMP_INV_STEP, + MYKONOS_ERR_OBS_RX_GAINCOMP_NULL_STRUCT, + + MYKONOS_ERR_SLICER_STEP_OUT_OF_RANGE, + MYKONOS_ERR_SLICER_INV_RX1_SEL, + MYKONOS_ERR_SLICER_INV_RX2_SEL, + MYKONOS_ERR_SLICER_EN_INV, + + MYKONOS_ERR_SLICER_RX1PIN_NULL_PARM, + MYKONOS_ERR_SLICER_RX2PIN_NULL_PARM, + MYKONOS_ERR_SLICER_STEP_NULL_PARM, + MYKONOS_ERR_SLICER_EN_NULL_PARM, + + MYKONOS_ERR_SLICER_INV_OBS_RX_SEL, + MYKONOS_ERR_SLICER_OBS_RX_STEP_OUT_OF_RANGE, + MYKONOS_ERR_SLICER_OBS_RX_EN_INV, + MYKONOS_ERR_SLICER_OBS_RX_EN_NULL_PARM, + MYKONOS_ERR_SLICER_OBS_RX_STEP_NULL_PARM, + MYKONOS_ERR_SLICER_OBS_RXPIN_NULL_PARM, + + MYKONOS_ERR_FLOATFRMT_NULL_STRUCT, + MYKONOS_ERR_FLOATFRMT_SET_NULL_STRUCT, + MYKONOS_ERR_FLOATFRMT_INV_ROUND_MODE, + MYKONOS_ERR_FLOATFRMT_INV_DATA_FORMAT, + MYKONOS_ERR_FLOATFRMT_INV_ENC_NAN, + MYKONOS_ERR_FLOATFRMT_INV_EXP_BITS, + MYKONOS_ERR_FLOATFRMT_INV_LEADING, + MYKONOS_ERR_FLOATFRMT_INV_RX1ATT, + MYKONOS_ERR_FLOATFRMT_INV_RX2ATT, + MYKONOS_ERR_FLOATFRMT_INV_EN, + MYKONOS_ERR_FLOATFRMT_NULL_RX1ATT, + MYKONOS_ERR_FLOATFRMT_NULL_RX2ATT, + MYKONOS_ERR_FLOATFRMT_NULL_ENABLE, + MYKONOS_ERR_FLOATFRMT_SET_INV_EN, + MYKONOS_ERR_FLOATFRMT_SET_INV_RX1ATT, + MYKONOS_ERR_FLOATFRMT_SET_INV_RX2ATT, + + MYKONOS_ERR_FLOATFRMT_INV_ORXATT, + MYKONOS_ERR_FLOATFRMT_INV_ORXEN, + MYKONOS_ERR_FLOATFRMT_NULL_ORXATT, + MYKONOS_ERR_FLOATFRMT_NULL_ORXENABLE, + + MYKONOS_ERR_SETUPTEMPSENSOR_NULL_PARAM, + MYKONOS_ERR_SETUPTEMPSENSOR_INV_TEMPDECIMATION, + MYKONOS_ERR_SETUPTEMPSENSOR_INV_OFFSET, + MYKONOS_ERR_SETUPTEMPSENSOR_INV_TEMPWINDOW, + MYKONOS_ERR_GETTEMPSENSORCFG_NULL_PARAM, + MYKONOS_ERR_READTEMPSENSOR_NULL_PARAM, + MYKONOS_ERR_READTEMPSENSOR_NOT_LOCKED, + + MYKONOS_ERR_GAIN_CONTROL_NOT_HYBRID, + MYKONOS_ERR_GPIO_HYBRID_RX1_PIN, + MYKONOS_ERR_GPIO_HYBRID_RX2_PIN, + MYKONOS_ERR_GPIO_HYBRID_RX1_PIN_NULL_PARM, + MYKONOS_ERR_GPIO_HYBRID_RX2_PIN_NULL_PARM, + MYKONOS_ERR_GPIO_HYBRID_RX1_PIN_READ, + MYKONOS_ERR_GPIO_HYBRID_RX2_PIN_READ, + MYKONOS_ERR_AGC_OBS_NOT_IN_HYBRID, + MYKONOS_ERR_GPIO_HYBRID_ORX_PIN, + MYKONOS_ERR_GPIO_HYBRID_ORX_PIN_NULL_PARM, + + MYKONOS_ERR_GAIN_CONTROL_NOT_AGC, + MYKONOS_ERR_GPIO_AGC_SYNC_RX1_PIN, + MYKONOS_ERR_GPIO_AGC_SYNC_RX2_PIN, + MYKONOS_ERR_GPIO_AGC_SYNC_RX1_PIN_NULL_PARM, + MYKONOS_ERR_GPIO_AGC_SYNC_RX2_PIN_NULL_PARM, + MYKONOS_ERR_OBS_GAIN_CONTROL_NOT_AGC, + MYKONOS_ERR_GPIO_AGC_SYNC_ORX_PIN, + MYKONOS_ERR_GPIO_AGC_SYNC_ORX_PIN_NULL_PARM, + + MYKONOS_ERR_GETGPIODRV_NULL_PARAM, + MYKONOS_ERR_GPIO_DRV_INV_PARAM, + + MYKONOS_ERR_GPIO_SLEW_RATE_INV_PARAM, + MYKONOS_ERR_GPIO_GETSLEW_NULL_PARAM, + + MYKONOS_ERR_CMOS_DRV_INV_PARAM, + MYKONOS_ERR_CMOS_DRV_NULL_PARAM +} mykonosGpioErr_t; + +/** + * \brief Enum of possible Rx Slicer pin combinations + */ +typedef enum +{ + GPIO_0_1_2 = 0, /*!< GPIO combination for RX1 */ + GPIO_5_6_7 = 1, /*!< GPIO combination for RX1 or RX2 */ + GPIO_8_9_10 = 2, /*!< GPIO combination for RX1 */ + GPIO_11_12_13 = 3 /*!< GPIO combination for RX2 */ +} mykonosRxSlicer_t; + +/** + * \brief Enum of possible observation channel Slicer pin combinations + */ +typedef enum +{ + GPIO_18_17_16 = 0, /*!< GPIO combination for observation channel */ + GPIO_16_15_14 = 1 /*!< GPIO combination for observation channel */ +} mykonosObsRxSlicer_t; + +/** + * \brief Enum of possible GPIO slew rate settings + */ +typedef enum +{ + MYK_SLEWRATE_NONE = 0, /*!< Lower slew rate for the GPIO */ + MYK_SLEWRATE_LOW = 1, /*!< Low slew rate for the GPIO */ + MYK_SLEWRATE_MEDIUM = 2, /*!< Medium slew rate for the GPIO */ + MYK_SLEWRATE_HIGH = 3 /*!< High slew rate for the GPIO */ +} mykonosGpioSlewRate_t; + +/** + * \brief Enumerated list of CMOS pads drive strength options + */ +typedef enum +{ + MYK_CMOSPAD_DRV_1X = 0x00, /*!< 2.5pF load @ 65MHz */ + MYK_CMOSPAD_DRV_2X = 0x01, /*!< 5pF load @ 65MHz */ + MYK_CMOSPAD_DRV_3X = 0x03, /*!< 7.5pF load @ 65MHz */ + MYK_CMOSPAD_DRV_4X = 0x07, /*!< 10pF load @ 65MHz */ + MYK_CMOSPAD_DRV_5X = 0x0F /*!< 12.5pF load @ 65MHz */ +} mykonosCmosPadDrvStr_t; + + +/** + * \brief Enumerated list for Aux ADCs + */ +typedef enum +{ + MYK_AUXADC_0 = 0x00, /*!< Aux ADC channel 0 */ + MYK_AUXADC_1 = 0x01, /*!< Aux ADC channel 1 */ + MYK_AUXADC_2 = 0x02, /*!< Aux ADC channel 2 */ + MYK_AUXADC_3 = 0x03, /*!< Aux ADC channel 3 */ + MYK_AUXADC_0_DIV2 = 0x04, /*!< Aux ADC channel 0 with the divider by 2 set */ + MYK_TEMPSENSOR = 0x10 /*!< Temperature sensor channel */ +} mykonosAuxAdcChannels_t; + + +/** + * \brief Data structure to hold Gain compensation settings for the main receive channels + **/ +typedef struct +{ + uint8_t rx1Offset; /*!< These parameter contains the Rx1 offset word used for the gain compensation + when the gain index is at its maximum setting. + It has a range of 0 to 0x1F with a resolution is 0.5dB per LSB. */ + uint8_t rx2Offset; /*!< These parameter contains the Rx2 offset word used for the gain compensation + when the gain index is at its maximum setting. + It has a range of 0 to 0x1F with a resolution is 0.5dB per LSB. */ + uint8_t compStep; /*!< These bits contains the value in dB that the total Rx gain changes + when there is an LSB change in the gain index according to the following settings: + compStep | dB ramp + ---------|------------ + 0 | 0.25dB + 1 | 0.5dB + 2 | 1.0dB + 3 | 2.0dB + 4 | 3.0dB + 5 | 4.0dB + 6 | 6.0dB + 7 | Not valid defaulted to 0.25dB */ +} mykonosGainComp_t; + +/** + * \brief Data structure to hold Gain compensation settings for the observation channel + **/ +typedef struct +{ + uint8_t obsRxOffset; /*!< These parameter contains the Rx1 offset word used for the gain compensation + when the gain index is at its maximum setting. + It has a range of 0 to 0x1F with a resolution is 0.5dB per LSB. */ + uint8_t compStep; /*!< These bits contains the value in dB that the total Rx gain changes + when there is an LSB change in the gain index according to the following settings: + compStep | dB ramp + ---------|------------ + 0 | 0.25dB + 1 | 0.5dB + 2 | 1.0dB + 3 | 2.0dB + 4 | 3.0dB + 5 | 4.0dB + 6 | 6.0dB + 7 | Not valid defaulted to 0.25dB */ +} mykonosObsRxGainComp_t; + +/** + * \brief Data structure to hold floating point formatter settings for the floating point + * number generation + **/ +typedef struct +{ + uint8_t roundMode; /*! +#include +#include "platform_drivers.h" + +/******************************************************************************/ +/************************ Functions Definitions *******************************/ +/******************************************************************************/ + +/** + * @brief Initialize the I2C communication peripheral. + * @param desc - The I2C descriptor. + * @param init_param - The structure that contains the I2C parameters. + * @return SUCCESS in case of success, FAILURE otherwise. + */ +int32_t i2c_init(struct i2c_desc **desc, + const struct i2c_init_param *param) +{ + if (desc) { + // Unused variable - fix compiler warning + } + + if (param->type) { + // Unused variable - fix compiler warning + } + + return SUCCESS; +} + +/** + * @brief Free the resources allocated by i2c_init(). + * @param desc - The I2C descriptor. + * @return SUCCESS in case of success, FAILURE otherwise. + */ +int32_t i2c_remove(struct i2c_desc *desc) +{ + if (desc) { + // Unused variable - fix compiler warning + } + + return SUCCESS; +} + +/** + * @brief Write data to a slave device. + * @param desc - The I2C descriptor. + * @param data - Buffer that stores the transmission data. + * @param bytes_number - Number of bytes to write. + * @param stop_bit - Stop condition control. + * Example: 0 - A stop condition will not be generated; + * 1 - A stop condition will be generated. + * @return SUCCESS in case of success, FAILURE otherwise. + */ +int32_t i2c_write(struct i2c_desc *desc, + uint8_t *data, + uint8_t bytes_number, + uint8_t stop_bit) +{ + if (desc) { + // Unused variable - fix compiler warning + } + + if (data) { + // Unused variable - fix compiler warning + } + + if (bytes_number) { + // Unused variable - fix compiler warning + } + + if (stop_bit) { + // Unused variable - fix compiler warning + } + + return SUCCESS; +} + +/** + * @brief Read data from a slave device. + * @param desc - The I2C descriptor. + * @param data - Buffer that will store the received data. + * @param bytes_number - Number of bytes to read. + * @param stop_bit - Stop condition control. + * Example: 0 - A stop condition will not be generated; + * 1 - A stop condition will be generated. + * @return SUCCESS in case of success, FAILURE otherwise. + */ +int32_t i2c_read(struct i2c_desc *desc, + uint8_t *data, + uint8_t bytes_number, + uint8_t stop_bit) +{ + if (desc) { + // Unused variable - fix compiler warning + } + + if (data) { + // Unused variable - fix compiler warning + } + + if (bytes_number) { + // Unused variable - fix compiler warning + } + + if (stop_bit) { + // Unused variable - fix compiler warning + } + + return SUCCESS; +} + +/** + * @brief Initialize the SPI communication peripheral. + * @param desc - The SPI descriptor. + * @param init_param - The structure that contains the SPI parameters. + * @return SUCCESS in case of success, FAILURE otherwise. + */ +int32_t spi_init(struct spi_desc **desc, + const struct spi_init_param *param) +{ + spi_desc *descriptor; + int32_t ret; + + descriptor = (struct spi_desc *) calloc(1, sizeof(*descriptor)); + if (!descriptor) + return FAILURE; + + descriptor->mode = param->mode; + descriptor->chip_select = param->chip_select; + descriptor->flags = param->flags; + +#ifdef _XPARAMETERS_PS_H_ + descriptor->config = XSpiPs_LookupConfig(param->id); + if (descriptor->config == NULL) + goto error; + + ret = XSpiPs_CfgInitialize(&descriptor->instance, + descriptor->config, descriptor->config->BaseAddress); + if (ret != 0) + goto error; + + XSpiPs_SetOptions(&descriptor->instance, + XSPIPS_MASTER_OPTION | + ((descriptor->flags & SPI_CS_DECODE) ? + XSPIPS_DECODE_SSELECT_OPTION : 0) | + XSPIPS_FORCE_SSELECT_OPTION | + ((descriptor->mode & SPI_CPOL) ? + XSPIPS_CLK_ACTIVE_LOW_OPTION : 0) | + ((descriptor->mode & SPI_CPHA) ? + XSPIPS_CLK_PHASE_1_OPTION : 0)); + + XSpiPs_SetClkPrescaler(&descriptor->instance, + XSPIPS_CLK_PRESCALE_64); + + XSpiPs_SetSlaveSelect(&descriptor->instance, 0xf); +#else + ret = XSpi_Initialize(&descriptor->instance, param->id); + if (ret != 0) + goto error; + + XSpi_SetOptions(&descriptor->instance, + XSP_MASTER_OPTION | + ((descriptor->mode & SPI_CPOL) ? + XSP_CLK_ACTIVE_LOW_OPTION : 0) | + ((descriptor->mode & SPI_CPHA) ? + XSP_CLK_PHASE_1_OPTION : 0)); + + XSpi_Start(&descriptor->instance); + + XSpi_IntrGlobalDisable(&descriptor->instance); +#endif + + *desc = descriptor; + + return SUCCESS; + +error: + free(descriptor); + + return FAILURE; +} + +/** + * @brief Free the resources allocated by spi_init(). + * @param desc - The SPI descriptor. + * @return SUCCESS in case of success, FAILURE otherwise. + */ +int32_t spi_remove(struct spi_desc *desc) +{ + if (desc) { + // Unused variable - fix compiler warning + } + + return SUCCESS; +} + +/** + * @brief Write and read data to/from SPI. + * @param desc - The SPI descriptor. + * @param data - The buffer with the transmitted/received data. + * @param bytes_number - Number of bytes to write/read. + * @return SUCCESS in case of success, FAILURE otherwise. + */ + +int32_t spi_write_and_read(struct spi_desc *desc, + uint8_t *data, + uint8_t bytes_number) +{ +#ifdef _XPARAMETERS_PS_H_ + XSpiPs_SetOptions(&desc->instance, + XSPIPS_MASTER_OPTION | + ((desc->flags & SPI_CS_DECODE) ? + XSPIPS_DECODE_SSELECT_OPTION : 0) | + XSPIPS_FORCE_SSELECT_OPTION | + ((desc->mode & SPI_CPOL) ? + XSPIPS_CLK_ACTIVE_LOW_OPTION : 0) | + ((desc->mode & SPI_CPHA) ? + XSPIPS_CLK_PHASE_1_OPTION : 0)); + + XSpiPs_SetSlaveSelect(&desc->instance, desc->chip_select); + // 0xf & ~desc->chip_select); + XSpiPs_PolledTransfer(&desc->instance, + data, data, bytes_number); +#else + XSpi_SetOptions(&desc->instance, + XSP_MASTER_OPTION | + ((desc->mode & SPI_CPOL) ? + XSP_CLK_ACTIVE_LOW_OPTION : 0) | + ((desc->mode & SPI_CPHA) ? + XSP_CLK_PHASE_1_OPTION : 0)); + + XSpi_SetSlaveSelect(&desc->instance, + desc->chip_select); + + XSpi_Transfer(&desc->instance, + data, data, bytes_number); +#endif + return 0; +} + +/** + * @brief Obtain the GPIO decriptor. + * @param desc - The GPIO descriptor. + * @param gpio_number - The number of the GPIO. + * @return SUCCESS in case of success, FAILURE otherwise. + */ +int32_t gpio_get(struct gpio_desc **desc, + uint8_t gpio_number) +{ + gpio_desc *descriptor; + int32_t ret; + + descriptor = (struct gpio_desc *) malloc(sizeof(*descriptor)); + if (!descriptor) + return FAILURE; + +#ifdef _XPARAMETERS_PS_H_ + descriptor->config = XGpioPs_LookupConfig(0); + if (descriptor->config == NULL) + goto error; + + ret = XGpioPs_CfgInitialize(&descriptor->instance, + descriptor->config, descriptor->config->BaseAddr); + if (ret != 0) + goto error; +#else + ret = XGpio_Initialize(&descriptor->instance, 0); + if (ret != 0) + goto error; +#endif + + descriptor->number = gpio_number; + + *desc = descriptor; + + return SUCCESS; + +error: + free(descriptor); + + return FAILURE; +} + +/** + * @brief Free the resources allocated by gpio_get(). + * @param desc - The SPI descriptor. + * @return SUCCESS in case of success, FAILURE otherwise. + */ +int32_t gpio_remove(struct gpio_desc *desc) +{ + if (desc) { + // Unused variable - fix compiler warning + } + + return SUCCESS; +} + +/** + * @brief Enable the input direction of the specified GPIO. + * @param desc - The GPIO descriptor. + * @return SUCCESS in case of success, FAILURE otherwise. + */ +int32_t gpio_direction_input(struct gpio_desc *desc) +{ + if (desc) { + // Unused variable - fix compiler warning + } + + return 0; +} + +/** + * @brief Enable the output direction of the specified GPIO. + * @param desc - The GPIO descriptor. + * @param value - The value. + * Example: GPIO_HIGH + * GPIO_LOW + * @return SUCCESS in case of success, FAILURE otherwise. + */ +int32_t gpio_direction_output(struct gpio_desc *desc, + uint8_t value) +{ +#ifdef _XPARAMETERS_PS_H_ + XGpioPs_SetDirectionPin(&desc->instance, desc->number, 1); + + XGpioPs_SetOutputEnablePin(&desc->instance, desc->number, 1); + + XGpioPs_WritePin(&desc->instance, desc->number, value); +#else + uint8_t pin = desc->number; + uint8_t channel; + uint32_t reg_val; + + if (pin >= 32) { + channel = 2; + pin -= 32; + } else + channel = 1; + + reg_val = XGpio_GetDataDirection(&desc->instance, channel); + reg_val &= ~(1 << pin); + XGpio_SetDataDirection(&desc->instance, channel, reg_val); + + reg_val = XGpio_DiscreteRead(&desc->instance, channel); + if(value) + reg_val |= (1 << pin); + else + reg_val &= ~(1 << pin); + XGpio_DiscreteWrite(&desc->instance, channel, reg_val); +#endif + + return SUCCESS; +} + +/** + * @brief Get the direction of the specified GPIO. + * @param desc - The GPIO descriptor. + * @param direction - The direction. + * Example: GPIO_OUT + * GPIO_IN + * @return SUCCESS in case of success, FAILURE otherwise. + */ +int32_t gpio_get_direction(struct gpio_desc *desc, + uint8_t *direction) +{ + if (desc) { + // Unused variable - fix compiler warning + } + + if (direction) { + // Unused variable - fix compiler warning + } + + return 0; +} + +/** + * @brief Set the value of the specified GPIO. + * @param desc - The GPIO descriptor. + * @param value - The value. + * Example: GPIO_HIGH + * GPIO_LOW + * @return SUCCESS in case of success, FAILURE otherwise. + */ +int32_t gpio_set_value(struct gpio_desc *desc, + uint8_t value) +{ +#ifdef _XPARAMETERS_PS_H_ + XGpioPs_WritePin(&desc->instance, desc->number, value); +#else + uint8_t pin = desc->number; + uint8_t channel; + uint32_t reg_val; + + if (pin >= 32) { + channel = 2; + pin -= 32; + } else + channel = 1; + + reg_val = XGpio_DiscreteRead(&desc->instance, channel); + if(value) + reg_val |= (1 << pin); + else + reg_val &= ~(1 << pin); + XGpio_DiscreteWrite(&desc->instance, channel, reg_val); +#endif + + return 0; +} + +/** + * @brief Get the value of the specified GPIO. + * @param desc - The GPIO descriptor. + * @param value - The value. + * Example: GPIO_HIGH + * GPIO_LOW + * @return SUCCESS in case of success, FAILURE otherwise. + */ +int32_t gpio_get_value(struct gpio_desc *desc, + uint8_t *value) +{ + if (desc) { + // Unused variable - fix compiler warning + } + + if (value) { + // Unused variable - fix compiler warning + } + + return 0; +} + +/** + * @brief Generate microseconds delay. + * @param usecs - Delay in microseconds. + * @return None. + */ +void udelay(uint32_t usecs) +{ + usleep(usecs); +} + +/** + * @brief Generate miliseconds delay. + * @param msecs - Delay in miliseconds. + * @return None. + */ +void mdelay(uint32_t msecs) +{ +#ifdef _XPARAMETERS_PS_H_ + usleep(msecs * 1000); +#else + usleep(msecs * 50); // FIXME +#endif +} diff --git a/datalink814_ge/src/hardware/platform_drivers.h b/datalink814_ge/src/hardware/platform_drivers.h new file mode 100644 index 0000000..5a744b9 --- /dev/null +++ b/datalink814_ge/src/hardware/platform_drivers.h @@ -0,0 +1,223 @@ +/***************************************************************************//** + * @file platform_drivers.h + * @brief Header file of Xilinx Platform Drivers. + * @author DBogdan (dragos.bogdan@analog.com) +******************************************************************************** + * Copyright 2018(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#ifndef PLATFORM_DRIVERS_H_ +#define PLATFORM_DRIVERS_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include +#include +#ifdef _XPARAMETERS_PS_H_ +#include +#include +#else +#include +#include +#endif + +/******************************************************************************/ +/********************** Macros and Constants Definitions **********************/ +/******************************************************************************/ + +#define SUCCESS 0 +#define FAILURE -1 + +#define SPI_CPHA 0x01 +#define SPI_CPOL 0x02 + +#define SPI_CS_DECODE 0x01 +#define SPI_CS_DECODE_DISABLE 0x00 + +#define GPIO_OUT 0x01 +#define GPIO_IN 0x00 + +#define GPIO_HIGH 0x01 +#define GPIO_LOW 0x00 + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ + +typedef enum i2c_type { + XILINX_I2C +} i2c_type; + +typedef struct i2c_init_param { + enum i2c_type type; + uint32_t id; + uint32_t max_speed_hz; + uint8_t slave_address; +} i2c_init_param; + +typedef struct i2c_desc { + enum i2c_type type; + uint32_t id; + uint32_t max_speed_hz; + uint8_t slave_address; +} i2c_desc; + +typedef enum spi_type { + XILINX_SPI +} spi_type; + +/** + * @enum spi_mode + * @brief SPI configuration for clock phase and polarity. + */ +typedef enum spi_mode { + /** Data on rising, shift out on falling */ + SPI_MODE_0 = (0 | 0), + /** Data on falling, shift out on rising */ + SPI_MODE_1 = (0 | SPI_CPHA), + /** Data on falling, shift out on rising */ + SPI_MODE_2 = (SPI_CPOL | 0), + /** Data on rising, shift out on falling */ + SPI_MODE_3 = (SPI_CPOL | SPI_CPHA) +} spi_mode; + +typedef struct spi_init_param { + enum spi_type type; + uint32_t id; + uint32_t max_speed_hz; + enum spi_mode mode; + uint8_t chip_select; + uint32_t flags; +} spi_init_param; + +typedef struct spi_desc { + enum spi_type type; + uint32_t id; + uint32_t max_speed_hz; + enum spi_mode mode; + uint8_t chip_select; + uint32_t flags; +#ifdef _XPARAMETERS_PS_H_ + XSpiPs_Config *config; + XSpiPs instance; +#else + XSpi instance; +#endif +} spi_desc; + +typedef enum gpio_type { + XILINX_GPIO +} gpio_type; + +typedef struct gpio_desc { + enum gpio_type type; + uint32_t id; + uint8_t number; +#ifdef _XPARAMETERS_PS_H_ + XGpioPs_Config *config; + XGpioPs instance; +#else + XGpio instance; +#endif +} gpio_desc; + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ + +/* Initialize the I2C communication peripheral. */ +int32_t i2c_init(struct i2c_desc **desc, + const struct i2c_init_param *param); + +/* Free the resources allocated by i2c_init(). */ +int32_t i2c_remove(struct i2c_desc *desc); + +/* Write data to a slave device. */ +int32_t i2c_write(struct i2c_desc *desc, + uint8_t *data, + uint8_t bytes_number, + uint8_t stop_bit); + +/* Read data from a slave device. */ +int32_t i2c_read(struct i2c_desc *desc, + uint8_t *data, + uint8_t bytes_number, + uint8_t stop_bit); + +/* Initialize the SPI communication peripheral. */ +int32_t spi_init(struct spi_desc **desc, + const struct spi_init_param *param); + +/* Free the resources allocated by spi_init() */ +int32_t spi_remove(struct spi_desc *desc); + +/* Write and read data to/from SPI. */ +int32_t spi_write_and_read(struct spi_desc *desc, + uint8_t *data, + uint8_t bytes_number); + +/* Obtain the GPIO decriptor. */ +int32_t gpio_get(struct gpio_desc **desc, + uint8_t gpio_number); + +/* Free the resources allocated by gpio_get() */ +int32_t gpio_remove(struct gpio_desc *desc); + +/* Enable the input direction of the specified GPIO. */ +int32_t gpio_direction_input(struct gpio_desc *desc); + +/* Enable the output direction of the specified GPIO. */ +int32_t gpio_direction_output(struct gpio_desc *desc, + uint8_t value); + +/* Get the direction of the specified GPIO. */ +int32_t gpio_get_direction(struct gpio_desc *desc, + uint8_t *direction); + +/* Set the value of the specified GPIO. */ +int32_t gpio_set_value(struct gpio_desc *desc, + uint8_t value); + +/* Get the value of the specified GPIO. */ +int32_t gpio_get_value(struct gpio_desc *desc, + uint8_t *value); + +/* Generate microseconds delay. */ +void udelay(uint32_t usecs); + +/* Generate miliseconds delay. */ +void mdelay(uint32_t msecs); + +#endif // PLATFORM_DRIVERS_H_ diff --git a/datalink814_ge/src/linklayer/framing.c b/datalink814_ge/src/linklayer/framing.c new file mode 100644 index 0000000..a4c2c50 --- /dev/null +++ b/datalink814_ge/src/linklayer/framing.c @@ -0,0 +1,327 @@ +/*****************************************************************************/ +/** + * Description: Functions for framing operations. + * + * Date: 2022-07-16 14:17 + * LastEditors: Fan Hao + * LastEditTime: 2022-07-16 17:11 + * Revisions: Rev x.x + * History: + * [YYYY-MM-DD]: Description of modification. + * + * Copyright(c) 2022 Beijing Institute of Technology. + * Lab of Communication and Networking + * +******************************************************************************/ + +/***************************** Include Files *********************************/ +#include +#include "linklayer814.h" +#include "msg_def.h" +#include "../error.h" +#include "../common.h" +#include "../bit_array/bit_array.h" + +/************************** Constant Definitions *****************************/ +// Definition of each slot content +L2_MSG_TYPE intraBmFrameMsgs[1] = { + L2_MSG_BM +}; +L2_MSG_TYPE intraW2AcqFrameMsgs[6] = { + L2_MSG_SCAN_INIT, + L2_MSG_SCAN_CONT_1, + L2_MSG_SCAN_CONT_2, + L2_MSG_SCAN_CONT_3, + L2_MSG_SCAN_CONT_4, + L2_MSG_SCAN_CONT_5 +}; + +L2_MSG_TYPE intraMgmtFrameMsgs[6] = { + L2_MSG_TK_INIT, + L2_MSG_TK_EXTD, + L2_MSG_TK_CONT_1, + L2_MSG_TK_CONT_2, + L2_MSG_TK_CONT_3, + L2_MSG_NQT_INIT +}; + +L2_MSG_TYPE taFrameMsgs[4] = { + L2_MSG_TA_INIT, + L2_MSG_TA_EXTD, + L2_MSG_TA_CONT_1, + L2_MSG_TA_CONT_2 +}; + +L2_MSG_TYPE interSvcFrameMsgs[2] = { + L2_MSG_LINK_INIT, + L2_MSG_LINK_CONT_1 +}; + +L2_MSG_TYPE rttReqFrameMsgs[3] = { + L2_MSG_RTT_REQ_INIT, + L2_MSG_RTT_REQ_EXTD, + L2_MSG_RTT_REQ_CONT +}; + +L2_MSG_TYPE rttRspFrameMsgs[3] = { + L2_MSG_RTT_RSP_INIT, + L2_MSG_RTT_RSP_EXTD, + L2_MSG_RTT_RSP_CONT +}; + + +/*****************************************************************************/ +/** + * @brief Insert a data chunk to a bit array. + * + * @param bitarr pointer to target bit array. + * offset offset of insert start position. + * numBit number of insert bits + * chunk 64 bit data chunk, contains the data should be stored + * in LSB style. + * + * @return FAILURE insert operation exceed bit array size. + * SUCCESS + * + ******************************************************************************/ +void FrameInsertChunk(BIT_ARRAY* bitarr, uint32_t offset, uint32_t numBit, uint64_t chunk){ + ASSERT(bitarr != NULL); + ASSERT(bitarr->num_of_bits >= offset+numBit && numBit <= 64); +#ifdef CHUNK_FILL_STYLE_XJY + int32_t bitRmn = numBit; + uint64_t dataWr = 0; + uint32_t bitOff = 0; + uint32_t byteOff = 0; + uint32_t bitWr = 0; + uint32_t bitWrCnt = 0; + while (bitRmn > 0){ + bitOff = offset%8; + byteOff = offset/8; + bitWr = (bitRmn > (8-bitOff)) ? (8-bitOff) : bitRmn; + dataWr = chunk>>(numBit-(bitWr + bitWrCnt)); + bit_array_set_wordn(bitarr, byteOff*8 + (8-bitOff-bitWr), dataWr, bitWr); + bitWrCnt += bitWr; + bitRmn -= bitWr; + offset += bitWr; + } +#else + bit_array_set_wordn(bitarr, offset, chunk, numBit); +#endif +} + +/*****************************************************************************/ +/** + * @brief Get a data chunk to a bit array. + * + * @param bitarr pointer to target bit array. + * offset offset of data chunk start position. + * numBit number of data chunk + * chunk pointer to a 64 bit data chunk container, data will be stored + * in LSB style. + * + * @return FAILURE read operation exceed bit array size. + * SUCCESS + * + ******************************************************************************/ +void FrameGetChunk(BIT_ARRAY* bitarr, uint32_t offset, uint32_t numBit, uint64_t* chunk){ + ASSERT(bitarr != NULL); + ASSERT(bitarr->num_of_bits >= offset+numBit && numBit <= 64); + +#ifdef CHUNK_FILL_STYLE_XJY + int32_t bitRmn = numBit; + uint64_t dataRd = 0; + uint32_t bitOff = offset%8; + uint32_t byteOff = offset/8; + uint32_t bitRd = (bitRmn > (8-bitOff)) ? (8-bitOff) : bitRmn; + uint32_t bitRdCnt = 0; + while (bitRmn > 0){ + dataRd |= bit_array_get_wordn(bitarr, byteOff*8 + (8-bitOff-bitRd), bitRd); + bitRdCnt += bitRd; + bitRmn -= bitRd; + offset += bitRd; + bitOff = offset%8; + byteOff = offset/8; + bitRd = (bitRmn > (8-bitOff)) ? (8-bitOff) : bitRmn; + dataRd = dataRd<>8); + *(crcPtr+1) = (uint8_t)(crcVal); + break; + case L2_CRC16_8005: + *crcPtr = (uint8_t)(crcVal>>8); + *(crcPtr+1) = (uint8_t)(crcVal); + break; + case L2_CRC8_31: + *crcPtr = (uint8_t)crcVal; + break; + default: + Status = EPARAM; + break; + } +#else + switch (crcType){ + case L2_CRC16_1021: + *(crcPtr+1) = (uint8_t)(crcVal>>8); + *crcPtr = (uint8_t)(crcVal); + break; + case L2_CRC16_8005: + *(crcPtr+1) = (uint8_t)(crcVal>>8); + *crcPtr = (uint8_t)(crcVal); + break; + case L2_CRC8_31: + *crcPtr = (uint8_t)crcVal; + break; + default: + Status = EPARAM; + break; + } +#endif + return Status; +} + +/*****************************************************************************/ +/** + * @brief Check data validation by crc. + * + * @param dataBuff pointer to data buffer. + * dataLen length of specified data. + * crcPos position of crc insert position + * crcType type of crc + * + * @return FAILURE crc type not support. + * SUCCESS + * + ******************************************************************************/ +bool L2_CrcCheck(uint8_t* dataBuff, uint32_t dataLen, uint32_t crcPos, L2_CRC_TYPE crcType){ + ASSERT(dataBuff != NULL); + + int32_t Status = SUCCESS; + uint32_t crcVal = 0; + uint32_t crcComp = 0; + uint8_t* crcPtr = dataBuff+crcPos; + Status = L2_CrcGen(dataBuff,dataLen, crcType, &crcVal); + if(Status != SUCCESS){ + return false; + } +#ifdef CHUNK_FILL_STYLE_XJY + switch (crcType){ + case L2_CRC16_1021: + crcComp = ((uint32_t)(*crcPtr)) << 8; + crcComp |= (uint32_t)(*(crcPtr+1)); + break; + case L2_CRC16_8005: + crcComp = ((uint32_t)(*crcPtr)) << 8; + crcComp |= (uint32_t)(*(crcPtr+1)); + break; + case L2_CRC8_31: + crcComp = (uint32_t)(*crcPtr); + break; + default: + Status = EPARAM; + break; + } +#else + switch (crcType){ + case L2_CRC16_1021: + crcComp = ((uint32_t)(*(crcPtr+1))) << 8; + crcComp |= (uint32_t)(*crcPtr); + break; + case L2_CRC16_8005: + crcComp = ((uint32_t)(*(crcPtr+1))) << 8; + crcComp |= (uint32_t)(*crcPtr); + break; + case L2_CRC8_31: + crcComp = (uint32_t)(*crcPtr); + break; + default: + Status = EPARAM; + break; + } +#endif + if(Status == SUCCESS){ +// if ( crcVal == 0 ) +// { +// return false ; +// } +// else + if(crcComp == crcVal){ + return true; + } + else{ + return false; + } + } + else{ + return false; + } + +} diff --git a/datalink814_ge/src/linklayer/geometry/coord.c b/datalink814_ge/src/linklayer/geometry/coord.c new file mode 100644 index 0000000..68d4108 --- /dev/null +++ b/datalink814_ge/src/linklayer/geometry/coord.c @@ -0,0 +1,195 @@ +// +// Copyright (C) 2020 OpenSim Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// + +#include +#include "coord.h" + + +const COORD COORD_NIL = {NAN, NAN, NAN}; +const COORD COORD_ZERO = {0.0, 0.0, 0.0}; +const COORD COORD_ONE = {1.0, 1.0, 1.0}; +const COORD COORD_X_AXIS = {1.0, 0.0, 0.0}; +const COORD COORD_Y_AXIS = {0.0, 1.0, 0.0}; +const COORD COORD_Z_AXIS = {0.0, 0.0, 1.0}; + + /** @brief Subtracts two coordinate vectors. */ +COORD Coord_Sub(COORD a, COORD b) { + COORD ret; + ret.x = a.x - b.x; + ret.y = a.y - b.y; + ret.z = a.z - b.z; + return ret; +} + +/** @brief Adds two coordinate vectors. */ +COORD Coord_Add(COORD a, COORD b) { + COORD ret; + ret.x = a.x + b.x; + ret.y = a.y + b.y; + ret.z = a.z + b.z; + return ret; +} + +/** @brief Multiplies a coordinate vector by a real number. */ +void Coord_ScalarMult(COORD *a, double t) { + a->x *= t; + a->y *= t; + a->z *= t; +} + +/** @brief Multiplies a coordinate vector by a real number. */ +COORD Coord_GetScalarMult(COORD a, double t) { + COORD ret; + ret.x = a.x * t; + ret.y = a.y * t; + ret.z = a.z * t; + return ret; +} + +/** @brief Divides a coordinate vector by a real number. */ +void Coord_ScalarDiv(COORD *a, double t) { + a->x /= t; + a->y /= t; + a->z /= t; +} + +/** @brief Divides a coordinate vector by a real number. */ +COORD Coord_GetScalarDiv(COORD a, double t) { + COORD ret; + ret.x = a.x / t; + ret.y = a.y / t; + ret.z = a.z / t; + return ret; +} + +/** @brief Dot product. */ +inline double Coord_Dot(COORD a, COORD b) { + return (a.x * b.x + a.y * b.y + a.z * b.z); +} + +/** @brief Cross product. */ +COORD Coord_Cross(COORD a, COORD b) { + COORD ret; + ret.x = a.y * b.z - a.z * b.y; + ret.y = a.z * b.x - a.x * b.z; + ret.z = a.x * b.y - a.y * b.x; + return ret; +} + +/** @brief Multiplies two coordinate vector in elementwise. */ +COORD Coord_ElementwiseMult(COORD a, COORD b) { + COORD ret; + ret.x = a.x * b.x; + ret.y = a.y * b.y; + ret.z = a.z * b.z; + return ret; +} + +/** @brief Divides two coordinate vector in elementwise. */ +COORD Coord_ElementwiseDiv(COORD a, COORD b) { + COORD ret; + ret.x = a.x / b.x; + ret.y = a.y / b.y; + ret.z = a.z / b.z; + return ret; +} + +/** @brief Calculate a coordinate vector length^2 (omits calling square root). */ +double Coord_SquareLength(COORD a) { + return (a.x*a.x + a.y*a.y + a.z*a.z); +} + +/** @brief Calculate a coordinate vector length. */ +double Coord_Length(COORD a) { + return sqrt(Coord_SquareLength(a)); +} + +/** @brief Calculate two coordinates' distance. */ +double Coord_Distance(COORD a, COORD b) { + return Coord_Length(Coord_Sub(a, b)); +} + +/** @brief Normalize coordinate vector. */ +void Coord_Normalize(COORD *a) { + Coord_ScalarDiv(a, Coord_Length(*a)); +} + +/** @brief Normalize coordinate vector. */ +COORD Coord_GetNormalized(COORD a) { + Coord_Normalize(&a); + return a; +} + +/** @brief Returns the angle between the two vectors. */ +double Coord_Angle(COORD a, COORD b) { + Coord_Normalize(&a); + Coord_Normalize(&b); + return acos(Coord_Dot(a, b)); +} + + +// Additional Coordinates convert +// TODO: Confirm correctness +/** @brief Convert coordinate from Launch coordinate system to ECEF. */ +COORD Coord_Launch2Ecef(COORD o, COORD p, double A, double B, double lambda) { + COORD ret; + double sinA,cosA, sinB, cosB, sinL, cosL; + double S11, S12, S13, S21, S22, S23, S31, S32, S33; + sinA = sin(A); + cosA = cos(A); + sinB = sin(B); + cosB = cos(B); + sinL = sin(lambda); + cosL = cos(lambda); + + S11 = -sinA*sinL - cosA*sinB*cosL; + S12 = cosB*cosL; + S13 = -cosA*sinL + sinA*sinB*cosL; + + S21 = sinA*cosL - cosA*sinB*sinL; + S22 = cosB*sinL; + S23 = cosA*cosL + sinA*sinB*sinL; + + S31 = cosA*cosB; + S32 = sinB; + S33 = -sinA*cosB; + + ret.x = p.x*(S11 + S21 + S31) + o.x; + ret.y = p.y*(S12 + S22 + S32) + o.y; + ret.z = p.z*(S13 + S23 + S33) + o.z; + + return ret; +} + +/** @brief Convert coordinate from launch coordinate system to Inertia coordinate system. */ +COORD Coord_Launch2Inertia(COORD o, COORD p, double A, double B, double we, double t) { + COORD ret; + double OmgX, OmgY, OmgZ, sinwet, coswet; + double M11, M12, M13, M21, M22, M23, M31, M32, M33; + OmgX = cos(A)*cos(B); + OmgY = sin(B); + OmgZ = -sin(A)*cos(B); + sinwet = sin(we*t); + coswet = cos(we*t); + + M11 = 1 - (1 - OmgX*OmgX)*(1-coswet); + M12 = OmgX*OmgY*(1-coswet) + OmgZ*sinwet; + M13 = OmgX*OmgZ*(1-coswet)-OmgY*sinwet; + + M21 = OmgY*OmgX*(1-coswet) - OmgZ*sinwet; + M22 = 1-(1-OmgY*OmgY)*(1-coswet); + M23 = OmgY*OmgZ*(1-coswet) + OmgX*sinwet; + + M31 = OmgZ*OmgX*(1-coswet) + OmgY*sinwet; + M32 = OmgZ*OmgY*(1-coswet) - OmgX*sinwet; + M33 = 1 - (1-OmgZ*OmgZ)*(1-coswet); + + ret.x = p.x*(M11 + M21 + M31) + o.x; + ret.y = p.y*(M12 + M22 + M32) + o.y; + ret.z = p.z*(M13 + M23 + M33) + o.z; + + return ret; +} diff --git a/datalink814_ge/src/linklayer/geometry/coord.h b/datalink814_ge/src/linklayer/geometry/coord.h new file mode 100644 index 0000000..9bdf7e0 --- /dev/null +++ b/datalink814_ge/src/linklayer/geometry/coord.h @@ -0,0 +1,81 @@ +// +// Copyright (C) 2020 OpenSim Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// + + +#ifndef _COORD_H +#define _COORD_H + +/** + * @brief Structure for storing 3D coordinates. + * + * Some comparison and basic arithmetic operators are implemented. + * + * @ingroup utils + */ + +typedef struct{ + double x; + double y; + double z; +} COORD; + +extern const COORD COORD_NIL; +extern const COORD COORD_ZERO; +extern const COORD COORD_ONE; +extern const COORD COORD_X_AXIS; +extern const COORD COORD_Y_AXIS; +extern const COORD COORD_Z_AXIS; + +/** @brief Subtracts two coordinate vectors. */ +COORD Coord_Sub(COORD a, COORD b); + +/** @brief Adds two coordinate vectors. */ +COORD Coord_Add(COORD a, COORD b); + +/** @brief Multiplies a coordinate vector by a real number. */ +void Coord_ScalarMult(COORD *a, double t); + +/** @brief Multiplies a coordinate vector by a real number. */ +COORD Coord_GetScalarMult(COORD a, double t); + +/** @brief Divides a coordinate vector by a real number. */ +void Coord_ScalarDiv(COORD *a, double t); + +/** @brief Divides a coordinate vector by a real number. */ +COORD Coord_GetScalarDiv(COORD a, double t); + +/** @brief Dot product. */ +double Coord_Dot(COORD a, COORD b); + +/** @brief Cross product. */ +COORD Coord_Cross(COORD a, COORD b); + +/** @brief Multiplies two coordinate vector in elementwise. */ +COORD Coord_ElementwiseMult(COORD a, COORD b); + +/** @brief Divides two coordinate vector in elementwise. */ +COORD Coord_ElementwiseDiv(COORD a, COORD b); + +/** @brief Calculate a coordinate vector length^2 (omits calling square root). */ +double Coord_SquareLength(COORD a); + +/** @brief Calculate a coordinate vector length. */ +double Coord_Length(COORD a); + +/** @brief Calculate two coordinates' distance. */ +double Coord_Distance(COORD a, COORD b); + +/** @brief Normalize coordinate vector. */ +void Coord_Normalize(COORD *a); + +/** @brief Normalize coordinate vector. */ +COORD Coord_GetNormalized(COORD a); + +/** @brief Returns the angle between the two vectors. */ +double Coord_Angle(COORD a, COORD b); + +#endif + diff --git a/datalink814_ge/src/linklayer/geometry/eulerangles.c b/datalink814_ge/src/linklayer/geometry/eulerangles.c new file mode 100644 index 0000000..76755df --- /dev/null +++ b/datalink814_ge/src/linklayer/geometry/eulerangles.c @@ -0,0 +1,57 @@ +// +// Copyright (C) 2020 OpenSim Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// + +#include +#include "eulerangles.h" + + +const EULERANGLES EULERANGLES_NIL = {NAN, NAN, NAN}; +const EULERANGLES EULERANGLES_ZERO = {0.0, 0.0, 0.0}; + + +/** @brief Add two EulerAngles. */ +EULERANGLES EulerAngles_Add(EULERANGLES e1, EULERANGLES e2) { + EULERANGLES ret; + ret.alpha = e1.alpha + e2.alpha; + ret.beta = e1.beta + e2.beta ; + ret.gamma = e1.gamma + e2.gamma; + return ret; +} + +/** @brief Subtracts two EulerAngles. */ +EULERANGLES EulerAngles_Sub(EULERANGLES e1, EULERANGLES e2) { + EULERANGLES ret; + ret.alpha = e1.alpha - e2.alpha; + ret.beta = e1.beta - e2.beta ; + ret.gamma = e1.gamma - e2.gamma; + return ret; +} + +/** @brief Multiplies EulerAngles by a real number. */ +void EulerAngles_ScalarMult(EULERANGLES *e, double f) { + e->alpha *= f; + e->beta *= f; + e->gamma *= f; +} + +/** @brief Multiplies EulerAngles by a real number. */ +EULERANGLES EulerAngles_GetScalarMult(EULERANGLES e, double f) { + EulerAngles_ScalarMult(&e, f); + return e; +} + +/** @brief Normalize EulerAngles. */ +void EulerAngles_Normalize(EULERANGLES *e) { + e->alpha = fmod(e->alpha, 2*EUL_PI); + e->beta = fmod(e->beta , 2*EUL_PI); + e->gamma = fmod(e->gamma, 2*EUL_PI); +} + +/** @brief Normalize EulerAngles. */ +EULERANGLES EulerAngles_GetNormalize(EULERANGLES e) { + EulerAngles_Normalize(&e); + return e; +} diff --git a/datalink814_ge/src/linklayer/geometry/eulerangles.h b/datalink814_ge/src/linklayer/geometry/eulerangles.h new file mode 100644 index 0000000..6a82c8f --- /dev/null +++ b/datalink814_ge/src/linklayer/geometry/eulerangles.h @@ -0,0 +1,54 @@ +#ifndef __EULERANGLES_H +#define __EULERANGLES_H + +#define EUL_PI 3.14159265358979323846 + +#define DEG2RAD(d) ((EUL_PI/180.0)*d) +#define RAD2DEG(r) ((180.0/EUL_PI)*r) + +/** + * Orientations are represented by 3D double precision Tait-Bryan (Euler) tuples + * called EulerAngles. The angles are in Z, Y', X" order that is often called + * intrinsic rotations, they are measured in radians. The default (unrotated) + * orientation is along the X axis. Conceptually, the Z axis rotation is heading, + * the Y' axis rotation is descending (negative elevation), the X" axis rotation is bank. + * For example, positive rotation along the Z axis rotates X into Y (turns left), positive + * rotation along the Y axis rotates Z into X (leans forward), positive rotation + * along the X axis rotates Y into Z (leans right). + */ +typedef struct { + double alpha; // unit rad + double beta; // unit rad + double gamma; // unit rad +} EULERANGLES; + +typedef enum { + EULERANGLES_NONE = 0, + EULERANGLES_ZYX = 1, + EULERANGLES_ZYZ = 2, + EULERANGLES_XYZ = 3, +}EULERANGLES_TYPE; + +extern const EULERANGLES EULERANGLES_ZERO; +extern const EULERANGLES EULERANGLES_NIL; + +/** @brief Add two EulerAngles. */ +EULERANGLES EulerAngles_Add(EULERANGLES e1, EULERANGLES e2); + +/** @brief Subtracts two EulerAngles. */ +EULERANGLES EulerAngles_Sub(EULERANGLES e1, EULERANGLES e2); + +/** @brief Multiplies EulerAngles by a real number. */ +void EulerAngles_ScalarMult(EULERANGLES *e, double f); + +/** @brief Multiplies EulerAngles by a real number. */ +EULERANGLES EulerAngles_GetScalarMult(EULERANGLES e, double f); + +/** @brief Normalize EulerAngles. */ +void EulerAngles_Normalize(EULERANGLES *e); + +/** @brief Normalize EulerAngles. */ +EULERANGLES EulerAngles_GetNormalize(EULERANGLES e); + +#endif + diff --git a/datalink814_ge/src/linklayer/geometry/quaternion.c b/datalink814_ge/src/linklayer/geometry/quaternion.c new file mode 100644 index 0000000..4ca1004 --- /dev/null +++ b/datalink814_ge/src/linklayer/geometry/quaternion.c @@ -0,0 +1,413 @@ +// +// Copyright (C) 2014 OpenSim Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// + +#include +#include +#include +#include "coord.h" +#include "eulerangles.h" +#include "quaternion.h" + +typedef union { + float value; + uint32_t raw; +} SOFT_FLOAT; + +typedef union { + double value; + uint64_t raw; +} SOFT_DOUBLE; + +const SOFT_FLOAT EPS_FLOAT = {.raw = 0x34000000}; +const SOFT_DOUBLE EPS_DOUBLE = {.raw = 0x3CB0000000000000}; + +const QUATERNION QUATERNION_IDENTITY = {1.0, 0.0, 0.0 ,0.0}; +const QUATERNION QUATERNION_NIL = {NAN, NAN, NAN, NAN}; +/** @brief Subtracts two quaternions. */ +QUATERNION Quaternion_Sub(QUATERNION q1, QUATERNION q2) { + QUATERNION ret; + ret.s = q1.s - q2.s; + ret.i = q1.i - q2.i; + ret.j = q1.j - q2.j; + ret.k = q1.k - q2.k; + return ret; +} + +/** @brief Adds two quaternions. */ +QUATERNION Quaternion_Add(QUATERNION q1, QUATERNION q2) { + QUATERNION ret; + ret.s = q1.s + q2.s; + ret.i = q1.i + q2.i; + ret.j = q1.j + q2.j; + ret.k = q1.k + q2.k; + return ret; +} + +/** @brief Multiplies a quaternion by a real number. */ +void Quaternion_ScalarMult(QUATERNION *q, double t) { + q->s *= t; + q->i *= t; + q->j *= t; + q->k *= t; +} + +/** @brief Multiplies a quaternion by a real number. */ +QUATERNION Quaternion_GetScalarMult(QUATERNION a, double t) { + Quaternion_ScalarMult(&a, t); + return a; +} + +/** @brief Divides a quaternion by a real number. */ +void Quaternion_ScalarDiv(QUATERNION *q, double t) { + q->s /= t; + q->i /= t; + q->j /= t; + q->k /= t; +} + +/** @brief Divides a quaternion by a real number. */ +QUATERNION Quaternion_GetScalarDiv(QUATERNION q, double t) { + Quaternion_ScalarDiv(&q, t); + return q; +} + +/** @brief Multiplies two quaternions. */ +QUATERNION Quaternion_Mult(QUATERNION q1, QUATERNION q2) { + QUATERNION ret; + ret.s = q1.s * q2.s - (q1.i*q2.i + q1.j*q2.j + q1.k*q2.k); + ret.i = q1.j * q2.k - q1.k * q2.j + q1.s * q2.i + q1.i * q2.s; + ret.j = q1.k * q2.i - q1.i * q2.k + q1.s * q2.j + q1.j * q2.s; + ret.k = q1.i * q2.j - q1.j * q2.i + q1.s * q2.k + q1.k * q2.s; + return ret; +} + +/** @brief Divides two quaternions. */ +QUATERNION Quaternion_Div(QUATERNION q1, QUATERNION q2) { + Quaternion_Inverse(&q2); + return Quaternion_Mult(q1, q2); +} + +/** @brief Dot product. */ +inline double Quaternion_Dot(QUATERNION q1, QUATERNION q2) { + return (q1.s*q2.s + q1.i*q2.i + q1.j*q2.j + q1.k*q2.k); +} + +/** @brief Calculate a quaternion length^2 (omits calling square root). */ +inline double Quaternion_SquareLength(QUATERNION q) { + return (q.s*q.s + q.i*q.i + q.j*q.j + q.k*q.k); +} + +/** @brief Calculate a quaternion length. */ +inline double Quaternion_Length(QUATERNION q) { + return sqrt(Quaternion_SquareLength(q)); +} + +/** @brief Normalize quaternion. */ +void Quaternion_Normalize(QUATERNION *q) { + Quaternion_ScalarDiv(q, Quaternion_Length(*q)); +} + +/** @brief Normalize quaternion. */ +QUATERNION Quaternion_GetNormalized(QUATERNION q) { + Quaternion_Normalize(&q); + return q; +} + +/** @brief Conjugated quaternion. */ +void Quaternion_Conjugated(QUATERNION *q) { + q->i = -q->i; + q->j = -q->j; + q->k = -q->k; +} + +/** @brief Conjugated quaternion. */ +QUATERNION Quaternion_GetConjugated(QUATERNION q) { + Quaternion_Conjugated(&q); + return q; +} + +/** @brief Inverse quaternion. */ +void Quaternion_Inverse(QUATERNION *q) { + Quaternion_Conjugated(q); + Quaternion_ScalarDiv(q, Quaternion_SquareLength(*q)); +} + +/** @brief Inverse quaternion. */ +QUATERNION Quaternion_GeInverse(QUATERNION q) { + Quaternion_Inverse(&q); + return q; +} + +inline double Quaternion_GetRotationAngle(QUATERNION q) { + return (acos(q.s) * 2); +} + + +/** @brief Get axis of quaternion. */ +COORD Quaternion_GetRotationAxis(QUATERNION q) { + double sin_theta_inv; + COORD ret; + sin_theta_inv = 1.0 / sin(acos(q.s)); + ret.x = q.i * sin_theta_inv; + ret.y = q.j * sin_theta_inv; + ret.z = q.k * sin_theta_inv; + return ret; +} + +/** @brief Get the axis and rotate angle of a unit Quaternion */ +void Quaternion_GetRotationAxisAndAngle(QUATERNION q, COORD *axis, double *angle) { + double sin_theta_inv; + *angle = acos(q.s); + + // pre-compute to save time + sin_theta_inv = 1.0 / sin(*angle); + + // now the vector + axis->x = q.i * sin_theta_inv; + axis->y = q.j * sin_theta_inv; + axis->z = q.k * sin_theta_inv; + *angle = (*angle) * 2; +} + +/** @brief Decompose the rotation on to 2 parts. */ +void Quaternion_GetSwingAndTwist(QUATERNION q, COORD axis, QUATERNION *swing, QUATERNION *twist) { + double p; + COORD v; + v.x = q.i; + v.y = q.j; + v.z = q.k; + // return projection v1 on to v2 (parallel component) + p = Coord_Dot(v, axis); + v = Coord_GetScalarMult(axis, p); + twist->s = q.s; + twist->i = v.x; + twist->j = v.y; + twist->k = v.z; + Quaternion_Normalize(twist); + *swing = Quaternion_Mult(q, Quaternion_GetConjugated(*twist)); +} + +/** @brief rotates v by this quaternion (quaternion must be unit) */ +COORD Quaternion_Rotate(QUATERNION q, COORD v) { + QUATERNION temp; + COORD ret; + temp.s = 0; + temp.i = v.x; + temp.j = v.y; + temp.k = v.z; + temp = Quaternion_Mult(q,temp); + Quaternion_Conjugated(&q); + temp = Quaternion_Mult(temp,q); + ret.x = temp.i; + ret.y = temp.j; + ret.z = temp.k; + return ret; +} + +/** @brief returns the euler angles from a rotation Quaternion */ +EULERANGLES Quaternion_ToEulerAngles(QUATERNION q, EULERANGLES_TYPE type) { + EULERANGLES ret; + switch (type) { + case EULERANGLES_ZYX : { + /* Covert form matlab 2023a */ + // Cap all inputs to asin to 1, since values >1 produce complex + // results + // Since the quaternion is of unit length, this should never happen, + // but some code generation configuration seem to hit this edge case + // under some circumstances. + + double asinValue; + bool mask1, mask2; + + asinValue = -2.0 *(q.i*q.k - q.s*q.j); + mask1 = asinValue >= 1.0 - 10*EPS_DOUBLE.value; + mask2 = asinValue <= -1.0 + 10*EPS_DOUBLE.value; + if (mask1) + asinValue = 1; + if (mask2) + asinValue = -1; + + if(mask1 || mask2) { + ret.alpha = (asinValue > 0) ? (-2.0 * atan2(q.i, q.s)) : (2.0 * atan2(q.i, q.s)); + ret.gamma = 0; + } + else { + ret.alpha = atan2(2.0*(q.i*q.j + q.s*q.k), q.s*q.s + q.i*q.i - q.j*q.j - q.k*q.k); + ret.gamma = atan2(2.0*(q.j*q.k + q.s*q.i), q.s*q.s - q.i*q.i - q.j*q.j + q.k*q.k); + } + ret.beta = asin( asinValue ); + break; + } + + case EULERANGLES_ZYZ : { + // TODO; + ret = EULERANGLES_NIL; + break; + } + + case EULERANGLES_XYZ : { + /* Covert form matlab 2023a */ + // Prevent singularities as done in ZYX case + // Alternative to rotm2eul(quat2rotm(q), 'XYZ') with fewer + // operations + // sin(y) = R13 = 2 * (qx*qz + qy*qw) + // tan(x) = sin(x) / cos(x) = -R23 / R33 + // = -2 * (qy*qz - qx*qw) / (1 - 2*(qx^2 + qy^2)) + // = -2 * (qy*qz - qx*qw) / (qw^2 - qx^2 - qy^2 + qz^2) + // tan(z) = sin(z) / cos(z) = -R12 / R11 + // = -2 * (qx*qy - qz*qw) / (1 - 2*(qy^2 + qz^2)) + // = -2 * (qy*qz - qx*qw) / (qw^2 + qx^2 - qy^2 - qz^2) + + double asinValue; + bool mask1, mask2; + + asinValue = 2.0 *(q.i*q.k + q.s*q.j); + mask1 = asinValue >= 1.0 - 10*EPS_DOUBLE.value; + mask2 = asinValue <= -1.0 + 10*EPS_DOUBLE.value; + if (mask1) + asinValue = 1; + if (mask2) + asinValue = -1; + if(mask1 || mask2) { + ret.alpha = 0; + ret.gamma = (asinValue > 0) ? (2.0 * atan2(q.i, q.s)) : (-2.0 * atan2(q.i, q.s)); + } + else { + ret.alpha = atan2(-2.0*(q.j*q.k - q.s*q.i), q.s*q.s - q.i*q.i - q.j*q.j + q.k*q.k); + ret.gamma = atan2(-2.0*(q.i*q.j - q.s*q.k), q.s*q.s + q.i*q.i - q.j*q.j - q.k*q.k); + } + ret.beta = asin( asinValue ); + break; + } + + + default: + ret = EULERANGLES_NIL; + } + return ret; +} + +/** @brief returns the rotation Quaternion from a euler angles */ +QUATERNION Quaternion_FromeEulerAngles(EULERANGLES e, EULERANGLES_TYPE type) { + QUATERNION ret; + double cosx, sinx, cosy, siny, cosz, sinz; + cosx = cos(e.alpha * 0.5); + sinx = sin(e.alpha * 0.5); + cosy = cos(e.beta * 0.5); + siny = sin(e.beta * 0.5); + cosz = cos(e.gamma * 0.5); + sinz = sin(e.gamma * 0.5); + switch (type) { + case EULERANGLES_ZYX : + ret.s = cosx * cosy * cosz + sinx * siny * sinz; + ret.i = cosx * cosy * sinz - sinx * siny * cosz; + ret.j = cosx * siny * cosz + sinx * cosy * sinz; + ret.k = sinx * cosy * cosz - cosx * siny * sinz; + break; + case EULERANGLES_ZYZ : + ret.s = cosx * cosy * cosz - sinx * cosy * sinz; + ret.i = cosx * siny * sinz - sinx * siny * cosz; + ret.j = cosx * siny * cosz + sinx * siny * sinz; + ret.k = sinx * cosy * cosz + cosx * cosy * sinz; + break; + case EULERANGLES_XYZ : + ret.s = cosx * cosy * cosz - sinx * siny * sinz; + ret.i = sinx * cosy * cosz + cosx * siny * sinz; + ret.j = -sinx * cosy * sinz + cosx * siny * cosz; + ret.k = cosx * cosy * sinz + sinx * siny * cosz; + break; + default: + ret = QUATERNION_NIL; + break; + } + return ret; +} + +/** @brief adapted from https://svn.code.sf.net/p/irrlicht/code/trunk/include/quaternion.h */ +QUATERNION Quaternion_RotationFromTo(COORD from, COORD to) +{ + // Based on Stan Melax's article in Game Programming Gems + COORD axis; + QUATERNION ret; + double c, s; + Coord_Normalize(&from); + Coord_Normalize(&to); + + c = Coord_Dot(from, to); + + if (c >= 1.0) { // If dot == 1, vectors are the same + return QUATERNION_IDENTITY; // identity + } + else if (c <= -1.0) { // exactly opposite + axis = Coord_Cross(COORD_X_AXIS, from); + + if (Coord_Length(axis) == 0) + axis = Coord_Cross(COORD_Y_AXIS, from); + + // same as fromAxisAngle(axis, PI).normalize(); + ret.s = 0; + ret.i = axis.x; + ret.j = axis.y; + ret.k = axis.z; + Quaternion_Normalize(&ret); + return ret; + } + + s = sqrt((1 + c) * 2); + axis = Coord_Cross(from, to); + Coord_ScalarDiv(&axis, s); + ret.s = s * 0.5; + ret.i = axis.x; + ret.j = axis.y; + ret.k = axis.z; + Quaternion_Normalize(&ret); + return ret; +} + + +/** @brief linear quaternion interpolation */ +QUATERNION Quaternion_Lerp(QUATERNION q1, QUATERNION q2, double t) { + QUATERNION ret; + Quaternion_ScalarMult(&q1, 1 - t); + Quaternion_ScalarMult(&q1, t); + ret = Quaternion_Add(q1, q2); + Quaternion_Normalize(&ret); + return ret; +} + + +/** @brief spherical linear interpolation */ +QUATERNION Quaternion_Slerp(QUATERNION q1, QUATERNION q2, double t) { + double dot; + QUATERNION q3, ret; + dot = Quaternion_Dot(q1, q2); + /* dot = cos(theta) + if (dot < 0), q1 and q2 are more than 90 degrees apart, + so we can invert one to reduce spinning */ + if (dot < 0) { + dot = -dot; + q3.s = -q2.s; + q3.i = -q2.i; + q3.j = -q2.j; + q3.k = -q2.k; + } + else { + q3 = q2; + } + + if (dot < 0.95) { + double angle = acos(dot); + Quaternion_ScalarMult(&q1, sin(angle * (1 - t))); + Quaternion_ScalarMult(&q3, sin(angle * t)); + ret = Quaternion_Add(q1, q3); + Quaternion_ScalarDiv(&ret, sin(angle)); + return ret; + } + // if the angle is small, use linear interpolation + else { + return Quaternion_Lerp(q1, q3, t); + } +} diff --git a/datalink814_ge/src/linklayer/geometry/quaternion.h b/datalink814_ge/src/linklayer/geometry/quaternion.h new file mode 100644 index 0000000..c0806a2 --- /dev/null +++ b/datalink814_ge/src/linklayer/geometry/quaternion.h @@ -0,0 +1,109 @@ + +#ifndef __QUATERNION_H +#define __QUATERNION_H + +#include "coord.h" +#include "eulerangles.h" + +// borrowed and adapted from https://github.com/MegaManSE/willperone/blob/master/Math/quaternion.h +typedef struct { + double s; + double i; + double j; + double k; +} QUATERNION; + +extern const QUATERNION QUATERNION_IDENTITY; +extern const QUATERNION QUATERNION_NIL; + +/** @brief Subtracts two quaternions. */ +QUATERNION Quaternion_Sub(QUATERNION q1, QUATERNION q2); + +/** @brief Adds two quaternions. */ +QUATERNION Quaternion_Add(QUATERNION q1, QUATERNION q2); + +/** @brief Multiplies a quaternion by a real number. */ +void Quaternion_ScalarMult(QUATERNION *q, double t); + +/** @brief Multiplies a quaternion by a real number. */ +QUATERNION Quaternion_GetScalarMult(QUATERNION a, double t); + +/** @brief Divides a quaternion by a real number. */ +void Quaternion_ScalarDiv(QUATERNION *q, double t); + +/** @brief Divides a quaternion by a real number. */ +QUATERNION Quaternion_GetScalarDiv(QUATERNION a, double t); + +/** @brief Multiplies two quaternions. */ +QUATERNION Quaternion_Mult(QUATERNION q1, QUATERNION q2); + +/** @brief Divides two quaternions. */ +QUATERNION Quaternion_Div(QUATERNION q1, QUATERNION q2); + +/** @brief Dot product. */ +double Quaternion_Dot(QUATERNION q1, QUATERNION q2); + +/** @brief Calculate a quaternion length^2 (omits calling square root). */ +double Quaternion_SquareLength(QUATERNION q); + +/** @brief Calculate a quaternion length. */ +double Quaternion_Length(QUATERNION q); + +/** @brief Normalize quaternion. */ +void Quaternion_Normalize(QUATERNION *q); + +/** @brief Normalize quaternion. */ +QUATERNION Quaternion_GetNormalized(QUATERNION q); + +/** @brief Conjugated quaternion. */ +void Quaternion_Conjugated(QUATERNION *q); + +/** @brief Conjugated quaternion. */ +QUATERNION Quaternion_GetConjugated(QUATERNION q); + +/** @brief Inverse quaternion. */ +void Quaternion_Inverse(QUATERNION *q); + +/** @brief Inverse quaternion. */ +QUATERNION Quaternion_GeInverse(QUATERNION q); + +/** @brief Get rotate angle of quaternion. */ +double Quaternion_GetRotationAngle(QUATERNION q); + +/** @brief Get axis of quaternion. */ +COORD Quaternion_GetRotationAxis(QUATERNION q); + +/** @brief Get the axis and rotate angle of a unit Quaternion */ +void Quaternion_GetRotationAxisAndAngle(QUATERNION q, COORD *axis, double *angle); + +/** @brief Decompose the rotation on to 2 parts. + 1. Twist - rotation around the "direction" vector + 2. Swing - rotation around axis that is perpendicular to "direction" vector + The rotation can be composed back by rotation = swing * twist + + has singularity in case of swing_rotation close to 180 degrees rotation. + if the input quaternion is of non-unit length, the outputs are non-unit as well + otherwise, outputs are both unit +*/ +void Quaternion_GetSwingAndTwist(QUATERNION q, COORD axis, QUATERNION *swing, QUATERNION *twist); + +/** @brief rotates v by this quaternion (quaternion must be unit) */ +COORD Quaternion_Rotate(QUATERNION q, COORD v); + +/** @brief returns the euler angles from a rotation Quaternion */ +EULERANGLES Quaternion_ToEulerAngles(QUATERNION q, EULERANGLES_TYPE type); + +/** @brief returns the rotation Quaternion from a euler angles */ +QUATERNION Quaternion_FromeEulerAngles(EULERANGLES e, EULERANGLES_TYPE type); + +/** @brief adapted from https://svn.code.sf.net/p/irrlicht/code/trunk/include/quaternion.h */ +QUATERNION Quaternion_RotationFromTo(COORD from, COORD to); + +/** @brief linear quaternion interpolation */ +QUATERNION Quaternion_Lerp(QUATERNION q1, QUATERNION q2, double t); + +/** @brief spherical linear interpolation */ +QUATERNION Quaternion_Slerp(QUATERNION q1, QUATERNION q2, double t); + +#endif + diff --git a/datalink814_ge/src/linklayer/linklayer814.c b/datalink814_ge/src/linklayer/linklayer814.c new file mode 100644 index 0000000..f5be3e4 --- /dev/null +++ b/datalink814_ge/src/linklayer/linklayer814.c @@ -0,0 +1,1316 @@ +/*****************************************************************************/ +/** + * Description: A brief description of this file + * + * Date: 2021-11-13 13:32 + * LastEditors: Fan Hao + * LastEditTime: 2021-11-23 10:57 + * Revisions: Rev 0.0 + * History: + * [2021-11-23]: Initial version. + * [2022-03-28]: Add bre test mode. + * + * Copyright(c) 2021 Beijing Institute of Technology. + * Lab of Communication and Networking + * + ******************************************************************************/ + +/***************************** Include Files *********************************/ +#include +#include +#include "linklayer814.h" +#include "linklayer814_types.h" +#include "msg_def.h" +#include "../error.h" +#include "../phy_ctrl/phy_ctrlreg.h" +#include "../time_ctrl/time_ctrl.h" +#include "../util/util.h" +#include "../common.h" + + +/************************** Constant Definitions *****************************/ +#define NET_START_TIME_INFTY UINT32_MAX +/************************** Variable Definitions *****************************/ +/***************** Macros (Inline Functions) Definitions *********************/ + +/**************************** Type Definitions *******************************/ + +/************************** Function Prototypes ******************************/ +static void UpdateMainSate(L2_INST* instPtr, L2_NODE_STATE newSate); +static void L2_SetSlotNum(L2_INST* instPtr, uint32_t newSlotNum); +static void L2_SetFrameNum(L2_INST* instPtr, uint32_t newFrameNum); +static void L2_UpdateSlotNum(L2_INST* instPtr); +static void L2_DataAvailUpdate(L2_INST* instPtr, bool status); +static void L2_EventPoolHandler(L2_INST* instPtr); + +static inline void UpdateMainSate(L2_INST* instPtr, L2_NODE_STATE newSate) { + ASSERT(instPtr != NULL); + DBG_INFO("MainStateUpdate: %d -> %d\n", instPtr->mainState, newSate); + instPtr->nextState = newSate; +} + +static void L2_SetSlotNum(L2_INST* instPtr, uint32_t newSlotNum){ + ASSERT(instPtr != NULL); + DBG_INFO("Set new slot number to %u\n", newSlotNum); + instPtr->slotNum.next = newSlotNum; +} + +static void L2_SetFrameNum(L2_INST* instPtr, uint32_t newFrameNum){ + ASSERT(instPtr != NULL); + DBG_INFO("Set new frame number to %u\n", newFrameNum); + instPtr->frameNum.next = newFrameNum; +} + +/** + * @brief Update frame number + */ +static inline void L2_UpdateSlotNum(L2_INST* instPtr) { + ASSERT(instPtr != NULL); + uint32_t slotCnt; + // Shift record + L2_RcdShift(&(instPtr->frameNum), instPtr->frameNum.next); + L2_RcdShift(&(instPtr->slotNum), instPtr->slotNum.next); + + // FIXME: Consider time wrapping + // Compute and set new slot and frame num + slotCnt = TimeCtrl_GetIntCnt(instPtr->config.tmcInstPtr) + 1; + instPtr->frameNum.next = slotCnt / L2_SLOTS_PER_FRAME - instPtr->netStartTime; + instPtr->slotNum.next = slotCnt % L2_SLOTS_PER_FRAME; +} + +/** + * @brief Update l2 frame buffer state + * infer that if there is a new valid l2 frame up. + */ +static inline void L2_DataAvailUpdate(L2_INST* instPtr, bool status) { + ASSERT(instPtr != NULL); + instPtr->dataAvail = status; +} + +L2_NODE_STATE L2_GetMainState(L2_INST* instPtr){ + ASSERT(instPtr != NULL); + return instPtr->mainState; +} + +/** + * @brief Check if there is a valid l2 frame. + */ +inline bool L2_isDataAvail(L2_INST* instPtr) { + ASSERT(instPtr != NULL); + return instPtr->dataAvail; +} + +/** + * @brief Check if node is connected to the network + */ +inline bool L2_isCxn2Net(L2_INST* instPtr) { + ASSERT(instPtr != NULL); + return instPtr->cxn2Net; +} + +/** + * @brief Get last frame number. + */ +inline uint32_t L2_GetLastFrameNum(L2_INST* instPtr) { + ASSERT(instPtr != NULL); + return instPtr->frameNum.last; +} + +/** + * @brief Get last slot number. + */ +inline uint32_t L2_GetLastSlotNum(L2_INST* instPtr) { + ASSERT(instPtr != NULL); + return instPtr->slotNum.last; +} + +/** + * @brief Get current frame number. + */ +inline uint32_t L2_GetCurrentFrameNum(L2_INST* instPtr) { + ASSERT(instPtr != NULL); + return instPtr->frameNum.curr; +} + +/** + * @brief Get current slot number. + */ +inline uint32_t L2_GetCurrentSlotNum(L2_INST* instPtr) { + ASSERT(instPtr != NULL); + return instPtr->slotNum.curr; +} + +/** + * @brief Get next frame number. + */ +inline uint32_t L2_GetNextFrameNum(L2_INST* instPtr) { + ASSERT(instPtr != NULL); + return instPtr->frameNum.next; +} +/** + * @brief Get next slot number. + */ +inline uint32_t L2_GetNextSlotNum(L2_INST* instPtr) { + ASSERT(instPtr != NULL); + return instPtr->slotNum.next; +} + +// TODO: Multi-node RTT +inline L2_RTT_FSM* L2_GetRttDesc(L2_INST* instPtr){ + ASSERT(instPtr != NULL); + return instPtr->rttFSM; +} +/*****************************************************************************/ +/** + * @brief Creat a new schedule envent, register event in schedule event pool. + * + * @param event event type of the new schedule event. + * + * @return NULL error occurred + * Pointer to schedule event. + * + ******************************************************************************/ +L2_SCHD_EVENT* L2_CreatNewSchdEvent(L2_INST* instPtr, L2_EVENT_TYPE event){ + L2_SCHD_EVENT* schdEventPtr = NULL; + if(instPtr->schdEventCnt >= L2_SCHD_EVENT_MAX){ + DBG_ERROR("Schedule event number exceeds the max, no more schedule event can be created.\n"); + return NULL; + } + schdEventPtr = (L2_SCHD_EVENT*)malloc(sizeof(L2_SCHD_EVENT)); + if(schdEventPtr == NULL){ + free(schdEventPtr); + return NULL; + } + if(event < L2_EV_SCAN_PROC_DONE || event > L2_ROUTINE_UPDATE){ + DBG_ERROR("Unknown event type: %d.\n", event); + return NULL; + } + schdEventPtr->eventId = instPtr->schdEventCnt; + schdEventPtr->l2Event.msg = NULL; + schdEventPtr->isSchd = false; + schdEventPtr->schdSlot = L2_SLOTNO_NONE; + schdEventPtr->schdFrame = L2_FRAMENO_NONE; + instPtr->l2SchdEventPool[instPtr->schdEventCnt] = schdEventPtr; + instPtr->schdEventCnt++; + return schdEventPtr; +} + + +/*****************************************************************************/ +/** + * @brief Delete a schedule event, remove the event from event pool, + * release memory, release event ID. + * + * @param schdEvent pointer to the schedule event which is aboute to be deleted. + * + * @return SUCCESS + * error code + * + ******************************************************************************/ +int32_t L2_DeletSchdEvent(L2_INST* instPtr, int32_t eventId){ + ASSERT(instPtr != NULL); + if (eventId > instPtr->schdEventCnt) { + return EIGNORE; + } + L2_SCHD_EVENT* schdEvent = instPtr->l2SchdEventPool[eventId]; + for(int32_t i = schdEvent->eventId; i < instPtr->schdEventCnt; i++){ + if(i == instPtr->schdEventCnt - 1){ + instPtr->l2SchdEventPool[i] = NULL; + } + else{ + instPtr->l2SchdEventPool[i] = instPtr->l2SchdEventPool[i+1]; + } + } + instPtr->schdEventCnt --; + + if(schdEvent->l2Event.msg != NULL) { + free(schdEvent->l2Event.msg); + } + free(schdEvent); + return SUCCESS; +} + + +void L2_ClearSchdEvent(L2_INST* instPtr){ + ASSERT(instPtr != NULL); + for(int32_t i = 0; i < instPtr->schdEventCnt; i++){ + if(instPtr->l2SchdEventPool[i]->l2Event.msg != NULL) { + free(instPtr->l2SchdEventPool[i]->l2Event.msg); + } + free(instPtr->l2SchdEventPool[i]); + } + instPtr->schdEventCnt = 0; +} +/*****************************************************************************/ +/** + * @brief Append extra message content to specific schedule event. + * + * @param schdEvent pointer to the schedule event. + * msg pointer to the append content. + * + * @return SUCCESS. + * error code. + * + ******************************************************************************/ +inline int32_t L2_SchdEventAppendMsg(L2_SCHD_EVENT* schdEvent, void* msg){ + ASSERT(schdEvent != NULL); + schdEvent->l2Event.msg = msg; + return SUCCESS; +} + + +/*****************************************************************************/ +/** + * @brief Cancel a scheduled event. + * + * @param schdEvent pointer to the schedule event. + * + * @return SUCCESS. + * + ******************************************************************************/ +int32_t L2_CancelEvent(L2_SCHD_EVENT* schdEvent){ + ASSERT(schdEvent != NULL); + if(schdEvent->isSchd == false){ + DBG_WARNING("Event %d has not been scheduled yet.\n", schdEvent->eventId); + } + schdEvent->isSchd = false; + return SUCCESS; +} + +/*****************************************************************************/ +/** + * @brief Check if the event was scheduled. + * + * @param schdEvent pointer to the schedule event. + * + * @return true. + * false. + * + ******************************************************************************/ +inline bool L2_isEventScheduled(L2_SCHD_EVENT* schdEvent){ + ASSERT(schdEvent != NULL); + return schdEvent->isSchd; +} + +/*****************************************************************************/ +/** + * @brief Schedule a event at a specific time(indexed by frame and slot number) + * + * @param schdEvent pointer to the schedule event. + * @param frameNum schedule frame number + * @param slotNum schedule slot number + * + * @return FAILURE, event has already been scheduled/schedule time not allowed. + * SUCCESS + * + ******************************************************************************/ +int32_t L2_ScheduleEventAt(L2_INST* instPtr, L2_SCHD_EVENT* schdEvent, uint32_t frameNum, uint32_t slotNum){ + ASSERT(schdEvent != NULL); + if(L2_isEventScheduled(schdEvent) == true){ + DBG_ERROR("Event %d has already been scheduled.\n", schdEvent->eventId); + return FAILURE; + } + if(frameNum <= L2_GetCurrentFrameNum(instPtr) && slotNum < L2_GetCurrentSlotNum(instPtr)){ + DBG_ERROR("Cannot schedule event %d to the past(current: [%u-%u], schedule: [%u-%u]).\n", + schdEvent->eventId, L2_GetCurrentFrameNum(instPtr), L2_GetCurrentSlotNum(instPtr), frameNum, slotNum); + return FAILURE; + } + schdEvent->isSchd = true; + schdEvent->schdFrame = frameNum; + schdEvent->schdSlot = slotNum; + return SUCCESS; +} + +/*****************************************************************************/ +/** + * @brief Schedule a event after a specific time period. + * + * @param schdEvent pointer to the schedule event. + * @param numSlots how many slot later the event should be scheduled + * + * @return FAILURE, event has already been scheduled/schedule time not allowed. + * SUCCESS + * + ******************************************************************************/ +int32_t L2_ScheduleEventAfter(L2_INST* instPtr, L2_SCHD_EVENT* schdEvent, uint32_t numSlots){ + ASSERT(schdEvent != NULL); + if(L2_isEventScheduled(schdEvent) == true){ + DBG_ERROR("Event %d has already been scheduled.\n", schdEvent->eventId); + return FAILURE; + } + uint32_t frameNum = L2_GetCurrentFrameNum(instPtr) + (numSlots/L2_SLOTS_PER_FRAME); + uint32_t slotNum = L2_GetCurrentSlotNum(instPtr) + (numSlots%L2_SLOTS_PER_FRAME); + return L2_ScheduleEventAt(instPtr, schdEvent, frameNum, slotNum); +} + +/*****************************************************************************/ +/** + * @brief Reschedule a event at a specific time(indexed by frame and slot number) + * + * @param schdEvent pointer to the schedule event. + * @param frameNum schedule frame number + * @param slotNum schedule slot number + * + * @return FAILURE, event has already been scheduled/schedule time not allowed. + * SUCCESS + * + ******************************************************************************/ +int32_t L2_RecheduleEventAt(L2_INST* instPtr, L2_SCHD_EVENT* schdEvent, uint32_t frameNum, uint32_t slotNum){ + ASSERT(schdEvent != NULL); + if(schdEvent->isSchd == false){ + DBG_WARNING("Event %d has not been scheduled yet.\n", schdEvent->eventId); + } + schdEvent->isSchd = false; + return L2_ScheduleEventAt(instPtr, schdEvent, frameNum, slotNum); +} + +/*****************************************************************************/ +/** + * @brief Rechedule a event after a specific time period. + * + * @param schdEvent pointer to the schedule event. + * @param numSlots how many slot later the event should be scheduled + * + * @return FAILURE, event has already been scheduled/schedule time not allowed. + * SUCCESS + * + * @return NONE. + * + ******************************************************************************/ +int32_t L2_RecheduleEventAfter(L2_INST* instPtr, L2_SCHD_EVENT* schdEvent, uint32_t numSlots){ + ASSERT(schdEvent != NULL); + if(schdEvent->isSchd == false){ + DBG_WARNING("Event %d has not been scheduled yet.\n", schdEvent->eventId); + } + return L2_ScheduleEventAfter(instPtr, schdEvent, numSlots); +} + + + +/*****************************************************************************/ +/** + * @brief Check and excute schedule event in event pool illiterate. + * + * @param NONE. + * + * @return NONE. + * + ******************************************************************************/ +static void L2_EventPoolHandler(L2_INST* instPtr){ + ASSERT(instPtr != NULL); + for(int32_t i = 0; i < instPtr->schdEventCnt; i++){ + if(instPtr->l2SchdEventPool[i]->isSchd == true){ + if(instPtr->l2SchdEventPool[i]->schdFrame == instPtr->frameNum.curr + && instPtr->l2SchdEventPool[i]->schdSlot == instPtr->slotNum.curr){ + AssertL2Event(instPtr, &(instPtr->l2SchdEventPool[i]->l2Event)); + } + } + } +} +/*****************************************************************************/ +/** + * @brief Shift L2 status record.(newval->next->curr->last) + * + * @param instPtr A pointer to physical layer control instance. + * + * @return NONE. + * + ******************************************************************************/ +inline void L2_RcdShift(L2_RCD* rcd, int32_t netxVal) { + ASSERT(rcd != NULL); + rcd->last = rcd->curr; + rcd->curr = rcd->next; + rcd->next = netxVal; +} + +/*****************************************************************************/ +/** + * @brief Get the valid frame data type received in last slot. + * + * @param NONE. + * + * @return NONE. + * + ******************************************************************************/ + +L2_FRAME_TYPE L2_GetLastRcvFrameType(L2_INST* instPtr) { + if (instPtr->dataAvail == false) { + return L2_NONE_FRAME; + } + else { + return instPtr->frame.last; + } +} + +/*****************************************************************************/ +/** + * @brief Update L2 frame state, check if there is any valid L2 frame data in + * data buffer, update receive frame status. + * + * @param NONE. + * + * @return NONE. + * + ******************************************************************************/ +// FIXME: Only for test +int w2AcqRecvCnt = 0; +int w2AcqRecvSuccessCnt = 0; +int mgmtRecvCnt = 0; +int mgmtRecvSuccessCnt = 0; +int tsyncRecvCnt = 0; +int tsyncRecvSuccessCnt = 0; +int svcRecvCnt = 0; +int svcRecvSuccessCnt = 0; +int recvCnt = 0; +int frameLen = 0; +void L2_FrameStateUpdate(L2_INST* instPtr) { + ASSERT(instPtr != NULL); + PHY_INST* phyRef = instPtr->config.phyInstPtr; + + // Update physical layer status. + // Phy_UpdateState(phyRef); + + // Frame types shift (last <- curr <- next) + L2_RcdShift(&(instPtr->frame), L2_NONE_FRAME); + + // Update frame state. + if (Phy_IsFrameValid(phyRef) == false) { + L2_DataAvailUpdate(instPtr, false); + return; + } + DBG_INFO("A frame received, checking data validation...\n"); + DBG_INFO("Last frame type is: %u.\n", instPtr->frame.last); + Phy_RetrieveRecvData(phyRef, instPtr->recvPktData); + switch (instPtr->frame.last) { + case L2_INTRA_SCAN_FRAME: + // INTRA_BM_FRAME could be received if current frame type is INTRA_BM_FRAME + case L2_INTRA_BM_FRAME: + if (L2_CrcCheck(instPtr->recvPktData, BM_MSG_CRC_OFFSET / 8, + BM_MSG_CRC_OFFSET / 8, L2_CRC8_31) == true) { + L2_DataAvailUpdate(instPtr, true); + } + else { + L2_DataAvailUpdate(instPtr, false); + } + break; + case L2_INTRA_W2_ACQ_FRAME: + // FIXME: Only for test + w2AcqRecvCnt++; + if (L2_CrcCheck(instPtr->recvPktData, + W2ACQ_FRAME_CRC_DLEN, W2ACQ_FRAME_CRC_POS, + L2_CRC16_8005) == true) { + L2_DataAvailUpdate(instPtr, true); + // FIXME: Only for test + w2AcqRecvSuccessCnt++; + } + else { + L2_DataAvailUpdate(instPtr, false); + } + break; + case L2_INTRA_MGMT_FRAME: + // FIXME: Only for test + mgmtRecvCnt++; + recvCnt ++ ; + L2_DataAvailUpdate(instPtr, true); + // FIXME: Only for test + mgmtRecvSuccessCnt ++; + break; + case L2_INTRA_TSYNC_FRAME: + // FIXME: Only for test + tsyncRecvCnt++; + recvCnt ++ ; + L2_DataAvailUpdate(instPtr, true); + // FIXME: Only for test + tsyncRecvSuccessCnt ++; + break; + case L2_INTRA_SVC_FRAME: + // FIXME: Only for test + svcRecvCnt++; + recvCnt ++ ; + if (L2_CrcCheck(instPtr->recvPktData, + PDUH0_HEADER_CRC_OFFSET/8, PDUH0_HEADER_CRC_OFFSET/8, + L2_CRC8_31) == true) { + L2_DataAvailUpdate(instPtr, true); + // FIXME: Only for test + svcRecvSuccessCnt++; + } + else { + L2_DataAvailUpdate(instPtr, false); + } + break; + default: + L2_DataAvailUpdate(instPtr, false); + break; + } +} + +/*****************************************************************************/ +/** + * @brief Layer 2 setup next slot operation, update current operating frame. + * + * @param instPtr a pointer to physical layer controller instance + * @param txrxMode tx/rx state for next slot + * @param frameType frame type of next slot. + * + * @return Corresponding frame length + * L2_FRAME_NONE_LEN if the frame type code cannot be recognized. + * + ******************************************************************************/ +int32_t L2_SetupNextSlot(L2_INST* instPtr, L2_TOR_TYPE txrxMode, L2_FRAME_TYPE frameType) { + ASSERT(instPtr != NULL); + PHY_INST* phyRef = instPtr->config.phyInstPtr; + int32_t Status = SUCCESS; + if (frameType < L2_INTER_SCAN_FRAME || frameType > L2_INTRA_SVC_FRAME) { + return FAILURE; + } +#if _814_DEBUG_LEVEL >= 3 + char* torStr = NULL; + char* frameStr = NULL; + switch(txrxMode){ + case L2_TOR_SUSPEND: + torStr = "SUSPEND"; + break; + case L2_TOR_TX: + torStr = "TX"; + break; + case L2_TOR_RX: + torStr = "RX"; + break; + } + switch(frameType){ + case L2_INTER_SCAN_FRAME: + frameStr = "intER Scan"; + break; + case L2_INTRA_SCAN_FRAME: + frameStr = "intRA Scan"; + break; + case L2_INTER_BM_FRAME: + frameStr = "intER BM"; + break; + case L2_INTRA_BM_FRAME: + frameStr = "intRA BM"; + break; + case L2_INTER_W2_ACQ_FRAME: + frameStr = "intER W2Acq"; + break; + case L2_INTRA_W2_ACQ_FRAME: + frameStr = "intRA W2Acq"; + break; + case L2_INTER_MGMT_FRAME: + frameStr = "intER Mgmt"; + break; + case L2_INTRA_MGMT_FRAME: + frameStr = "intRA Mgmt"; + break; + case L2_INTER_TSYNC_FRAME: + frameStr = "intER TSync"; + break; + case L2_INTRA_TSYNC_FRAME: + frameStr = "intRA TSync"; + break; + case L2_INTER_SVC_FRAME: + frameStr = "intER Svc"; + break; + case L2_INTRA_SVC_FRAME: + frameStr = "intRA Svc"; + break; + default: + break; + } + DBG_INFO("# Setup Next Slot # [%u-%u], %s, %s.\n", + instPtr->frameNum.next, + instPtr->slotNum.next, + torStr, frameStr); +#endif + + TIME_WORD pullTime = {0, 0}; + pullTime.int_part = TimeCtrl_GetIntCnt(instPtr->config.tmcInstPtr) + 1; + Status = Phy_SetTimeWord(phyRef, &pullTime, TIME_WORD_POLL); + if(Status != SUCCESS){ + DBG_ERROR("Physical set pull time failed, with error code: %d\n", Status); + } + instPtr->frame.next = frameType; + + PHY_TOR_TYPE tor; + switch(txrxMode) { + case L2_TOR_SUSPEND: + tor = PHY_TOR_SUSPEND; + break; + case L2_TOR_TX: + tor = PHY_TOR_TX; + break; + case L2_TOR_RX: + tor = PHY_TOR_RX; + break; + default: + DBG_ERROR("Invalid txrx mode :%d.\n", txrxMode); + return EPARAM; + } + + Status = Phy_SetupNextSlot(phyRef, tor, L2_L2frame2L1frame(frameType), instPtr->sendPktData); + if(Status != SUCCESS){ + DBG_ERROR("Physical setup failed, with error code: %d\n", Status); + } + return Status; +} + +/*****************************************************************************/ +/** + * @brief Get corresponding frame length in byte of L2 frame. + * + * @param l2FrameType + * + * @return Corresponding frame length + * L2_FRAME_NONE_LEN if the frame type code cannot be recognized. + * + ******************************************************************************/ +uint32_t L2_GetFrameLen(L2_FRAME_TYPE l2FrameType) { + return Phy_GetFrameLen(L2_L2frame2L1frame(l2FrameType)); +} + +/*****************************************************************************/ +/** + * @brief Convert L2 frame type to L1 frame type + * + * @param phyInstPtr A pointer to physical layer control instance. + * + * @return L1 frame type. + * + ******************************************************************************/ +#ifdef TEST_200KBPS +L1_FRAME_TYPE L2_L2frame2L1frame(L2_FRAME_TYPE l2Frame) { + switch (l2Frame) { + case L2_INTER_SCAN_FRAME: + return L1_2KBPS_20MS_FRAME; + case L2_INTRA_SCAN_FRAME: + return L1_10KBPS_10MS_FRAME; + case L2_INTER_BM_FRAME: + return L1_2KBPS_100MS_FRAME; + case L2_INTRA_BM_FRAME: + return L1_10KBPS_20MS_FRAME; + case L2_INTER_W2_ACQ_FRAME: + return L1_40KBPS_10MS_FRAME; + case L2_INTRA_W2_ACQ_FRAME: + return L1_200KBPS_5MS_FRAME; + case L2_INTER_MGMT_FRAME: + return L1_40KBPS_20MS_FRAME; + case L2_INTRA_MGMT_FRAME: + return L1_200KBPS_5MS_FRAME; + case L2_INTER_TSYNC_FRAME: + return L1_40KBPS_20MS_FRAME; + case L2_INTRA_TSYNC_FRAME: + return L1_200KBPS_5MS_FRAME; + case L2_INTER_SVC_FRAME: + return L1_40KBPS_20MS_FRAME; + case L2_INTRA_SVC_FRAME: + return L1_200KBPS_5MS_FRAME; + default: + return L1_NONE_FRAME; + } +} +// FIXME: Only for test 1.2Mbps Frame +#else +L1_FRAME_TYPE L2_L2frame2L1frame(L2_FRAME_TYPE l2Frame) { + switch (l2Frame) { + case L2_INTER_SCAN_FRAME: + return L1_2KBPS_20MS_FRAME; + case L2_INTRA_SCAN_FRAME: + return L1_10KBPS_10MS_FRAME; + case L2_INTER_BM_FRAME: + return L1_2KBPS_100MS_FRAME; + case L2_INTRA_BM_FRAME: + return L1_10KBPS_20MS_FRAME; + case L2_INTER_W2_ACQ_FRAME: + return L1_40KBPS_10MS_FRAME; + case L2_INTRA_W2_ACQ_FRAME: + return L1_200KBPS_5MS_FRAME; + case L2_INTER_MGMT_FRAME: + return L1_40KBPS_20MS_FRAME; + case L2_INTRA_MGMT_FRAME: + return L1_1M2BPS_5MS_FRAME; + case L2_INTER_TSYNC_FRAME: + return L1_40KBPS_20MS_FRAME; + case L2_INTRA_TSYNC_FRAME: + return L1_1M2BPS_5MS_FRAME; + case L2_INTER_SVC_FRAME: + return L1_40KBPS_20MS_FRAME; + case L2_INTRA_SVC_FRAME: + return L1_1M2BPS_5MS_FRAME; + default: + return L1_NONE_FRAME; + } +} +#endif +/*****************************************************************************/ +/** + * @brief Initialize link layer fsm instance, allocate memory to storage fsm + * data. Apply the default values to fsm. + * + * @param instPtr a pointer to physical layer controller instance + * + * @return SUCCESS + * Other error code. + * + ******************************************************************************/ +int32_t Linklayer_Init(L2_INST** instPtr, const L2_CONFIG *config) { + ASSERT(instPtr != NULL); + ASSERT(config != NULL); + + int32_t Status; + + if (config->phyInstPtr == NULL) { + return EDINVAL; + } + if (config->tmcInstPtr == NULL) { + return EDINVAL; + } + (*instPtr) = (L2_INST*) malloc(sizeof(L2_INST)); + if (*instPtr == NULL) { + DBG_ERROR("Allocate memory for L2_INST failed.\n"); + return EALLOC; + } + memset(*instPtr, 0x00, sizeof(L2_INST)); + memcpy(&((*instPtr)->config), config, sizeof(L2_CONFIG)); + + // Packet buffer + (*instPtr)->sendPktData = calloc(L2_PACKET_LEN_MAX/sizeof(uint64_t), sizeof(uint64_t)); + if((*instPtr)->sendPktData == NULL) { + DBG_ERROR("Allocate memory for sendPktData failed.\n"); + Status = EALLOC; + goto error; + } + (*instPtr)->recvPktData = calloc(L2_PACKET_LEN_MAX/sizeof(uint64_t), sizeof(uint64_t)); + if((*instPtr)->recvPktData == NULL) { + DBG_ERROR("Allocate memory for recvPktData failed.\n"); + Status = EALLOC; + goto error; + } + + // Mpc buff Init + (*instPtr)->mgmtMsgRecvBuff0 = calloc(MSG_STROAGE_BUFF_MAX/sizeof(uint64_t), sizeof(uint64_t)); + if((*instPtr)->mgmtMsgRecvBuff0 == NULL) { + DBG_ERROR("Allocate memory for mgmtMsgRecvBuff0 failed.\n"); + Status = EALLOC; + goto error; + } + (*instPtr)->svcMsgRecvBuff0 = calloc(MSG_STROAGE_BUFF_MAX/sizeof(uint64_t), sizeof(uint64_t)); + if((*instPtr)->svcMsgRecvBuff0 == NULL) { + DBG_ERROR("Allocate memory for svcMsgRecvBuff0 failed.\n"); + Status = EALLOC; + goto error; + } + (*instPtr)->mgmtMsgRecvBuff1 = calloc(MSG_STROAGE_BUFF_MAX/sizeof(uint64_t), sizeof(uint64_t)); + if((*instPtr)->mgmtMsgRecvBuff1 == NULL) { + DBG_ERROR("Allocate memory for mgmtMsgRecvBuff1 failed.\n"); + Status = EALLOC; + goto error; + } + (*instPtr)->svcMsgRecvBuff1 = calloc(MSG_STROAGE_BUFF_MAX/sizeof(uint64_t), sizeof(uint64_t)); + if((*instPtr)->svcMsgRecvBuff1 == NULL) { + DBG_ERROR("Allocate memory for svcMsgRecvBuff1 failed.\n"); + Status = EALLOC; + goto error; + } + + // Reset basic info + (*instPtr)->netStartTime = UINT32_MAX; + (*instPtr)->schdEventCnt = 0; + (*instPtr)->rtneConfig.last = NULL; + (*instPtr)->rtneConfig.curr = NULL; + (*instPtr)->rtneConfig.next = NULL; + (*instPtr)->isEnable = false; + (*instPtr)->cxn2Net = false; + (*instPtr)->dataAvail = false; + (*instPtr)->frame.last = L2_NONE_FRAME; + (*instPtr)->frame.curr = L2_NONE_FRAME; + (*instPtr)->frame.next = L2_NONE_FRAME; + (*instPtr)->rtneConfig.rtneTable = initTable; + (*instPtr)->rtneConfig.rtnePrd = ARRAY_SIZE(initTable); + (*instPtr)->mainState = INIT_STATE; + (*instPtr)->nextState = INIT_STATE; + (*instPtr)->frameNum.last = 0; + (*instPtr)->frameNum.curr = 0; + (*instPtr)->frameNum.next = 0; + (*instPtr)->slotNum.last = 0; + (*instPtr)->slotNum.curr = 0; + (*instPtr)->slotNum.next = 0; + (*instPtr)->myInfo.nodeType = config->myType; + (*instPtr)->myInfo.nodeId = config->myId; + (*instPtr)->myInfo.clustId = config->clustId; + (*instPtr)->myInfo.pos.x = 0; + (*instPtr)->myInfo.pos.y = 0; + (*instPtr)->myInfo.pos.z = 0; + (*instPtr)->myInfo.speed.x = 0; + (*instPtr)->myInfo.speed.y = 0; + (*instPtr)->myInfo.speed.z = 0; + + // Reset buffer count + (*instPtr)->mgmtMsgRecvCnt0 = 0; + (*instPtr)->mgmtMsgRecvCnt1 = 0; + (*instPtr)->svcMsgRecvCnt0 = 0; + (*instPtr)->svcMsgRecvCnt1 = 0; + (*instPtr)->buffSwitch = 0; + + NodeList_Init(&((*instPtr)->nodeList)); + + Status = ScanNet_Init(&((*instPtr)->scanNetFSM)); + if (Status != SUCCESS) { + DBG_ERROR("ScanNet_Init runs failed, with error code: %d.\n", Status); + goto error; + } + + Status = MgmtNet_Init(&((*instPtr)->mgmtNetFSM)); + if (Status != SUCCESS) { + DBG_ERROR("MgmtNet_Init runs failed, with error code: %d.\n", Status); + goto error; + } + + Status = ServiceNet_Init(&((*instPtr)->serviceNetFSM)); + if (Status != SUCCESS) { + DBG_ERROR("ServiceNet_Init runs failed, with error code: %d.\n", Status); + goto error; + } + + Status = RTT_Init(&((*instPtr)->rttFSM)); + if (Status != SUCCESS) { + DBG_ERROR("RTT_Init runs failed, with error code: %d.\n", Status); + goto error; + } + return SUCCESS; +error: + Linklayer_Destroy(*instPtr); + return Status; +} + +int32_t Linklayer_Reconfig(L2_INST* instPtr, const L2_CONFIG *config) { + ASSERT(instPtr != NULL); + ASSERT(config != NULL); + + if (config->phyInstPtr == NULL) { + return EDINVAL; + } + if (config->tmcInstPtr == NULL) { + return EDINVAL; + } + memcpy(&(instPtr->config), config, sizeof(L2_CONFIG)); + + // Reset basic info + instPtr->netStartTime = UINT32_MAX; + instPtr->schdEventCnt = 0; + instPtr->rtneConfig.last = NULL; + instPtr->rtneConfig.curr = NULL; + instPtr->rtneConfig.next = NULL; + instPtr->cxn2Net = false; + instPtr->dataAvail = false; + instPtr->frame.last = L2_NONE_FRAME; + instPtr->frame.curr = L2_NONE_FRAME; + instPtr->frame.next = L2_NONE_FRAME; + instPtr->rtneConfig.rtneTable = initTable; + instPtr->rtneConfig.rtnePrd = ARRAY_SIZE(initTable); + instPtr->mainState = INIT_STATE; + instPtr->nextState = INIT_STATE; + instPtr->frameNum.last = 0; + instPtr->frameNum.curr = 0; + instPtr->frameNum.next = 0; + instPtr->slotNum.last = 0; + instPtr->slotNum.curr = 0; + instPtr->slotNum.next = 0; + instPtr->myInfo.nodeType = config->myType; + instPtr->myInfo.nodeId = config->myId; + instPtr->myInfo.clustId = config->clustId; + instPtr->myInfo.pos.x = 0; + instPtr->myInfo.pos.y = 0; + instPtr->myInfo.pos.z = 0; + instPtr->myInfo.speed.x = 0; + instPtr->myInfo.speed.y = 0; + instPtr->myInfo.speed.z = 0; + + // Reset buffer count + instPtr->mgmtMsgRecvCnt0 = 0; + instPtr->mgmtMsgRecvCnt1 = 0; + instPtr->svcMsgRecvCnt0 = 0; + instPtr->svcMsgRecvCnt1 = 0; + instPtr->buffSwitch = 0; + + // Reset according instance + L2_ClearSchdEvent(instPtr); + NodeList_Clear(instPtr->nodeList); + ScanNet_Reset(instPtr->scanNetFSM); + MgmtNet_Reset(instPtr->mgmtNetFSM); + ServiceNet_Reset(instPtr->serviceNetFSM); + RTT_Reset(instPtr->rttFSM); + return SUCCESS; +} + + +void Linklayer_Destroy(L2_INST* instPtr){ + ASSERT(instPtr != NULL); + free(instPtr->sendPktData); + free(instPtr->recvPktData); + free(instPtr->mgmtMsgRecvBuff0); + free(instPtr->svcMsgRecvBuff0); + free(instPtr->mgmtMsgRecvBuff1); + free(instPtr->svcMsgRecvBuff1); + // Destroy FSMs and nodeList + NodeList_Destroy(instPtr->nodeList); + ScanNet_Destroy(instPtr->scanNetFSM); + MgmtNet_Destroy(instPtr->mgmtNetFSM); + ServiceNet_Destroy(instPtr->serviceNetFSM); + RTT_Destroy(instPtr->rttFSM); + free(instPtr); +} + + +int32_t Linklayer_Start(L2_INST* instPtr){ + ASSERT(instPtr != NULL); + instPtr->netStartTime = TimeCtrl_GetIntCnt(instPtr->config.tmcInstPtr)/L2_SLOTS_PER_FRAME + 1; + instPtr->isEnable = true; + return SUCCESS; +} + +int32_t Linklayer_Halt(L2_INST* instPtr){ + ASSERT(instPtr != NULL); + instPtr->isEnable = false; + return SUCCESS; +} + +/*****************************************************************************/ +/** + * @brief Handle l2 event called by other model. + * + * @param instPtr a pointer to physical layer controller instance + * @param l2Event + * + * @return SUCCESS - Event has been successfully handled. + * FAIL - Event cannot be recognized or error occurred while process. + * + ******************************************************************************/ +int32_t Linklayer_EventHandler(L2_INST* instPtr, const L2_EVENT* l2Event) { + switch (l2Event->event) { + case L2_EV_SET_FRAME_NUM: { + DBG_INFO("Event L2_EV_FRAME_NO_UPDATE asserted....\n"); + L2_SetFrameNum(instPtr, *((uint32_t*) l2Event->msg)); + break; + } + case L2_EV_SET_SLOT_NUM: { + DBG_INFO("Event L2_EV_SLOT_NO_UPDATE asserted....\n"); + L2_SetSlotNum(instPtr, *((uint32_t*) l2Event->msg)); + break; + } + case L2_EV_MAIN_STATE_UPDATE: { + DBG_INFO("Event L2_EV_MAIN_STATE_UPDATE asserted....\n"); + UpdateMainSate(instPtr, *((L2_NODE_STATE*) l2Event->msg)); + break; + } + case L2_EV_SCAN_PROC_DONE: { + DBG_INFO("Event L2_EV_SCAN_PROC_DONE asserted....\n"); + //TODO: Clear ACK + break; + } + case L2_EV_MGMT_PROC_DONE: { + DBG_INFO("Event L2_EV_MGMT_PROC_DONE asserted....\n"); + break; + } + case L2_EV_NET_SETUP_DONE: { + DBG_INFO("Event L2_EV_NETSETUP_DONE asserted....\n"); + if(instPtr->myInfo.nodeType != HEAD_NODE){ + instPtr->cxn2Net = true; + } + else{ // Head node + UpdateMainSate(instPtr, NORMAL_STATE); + } + break; + } + case L2_EV_TIME_SYNC: { + DBG_INFO("Event L2_EV_TIME_SYNC asserted....\n"); + break; + } + case L2_EV_LINK_SET_REQ: { + DBG_INFO("Event L2_EV_LINK_SET_REQ asserted....\n"); + break; + } + case L2_EV_LOST_CXN: { + DBG_INFO("Event L2_EV_LOST_CXN asserted....\n"); + DBG_WARNING("Lost connection with head node [%d].\n", instPtr->config.headId); + instPtr->cxn2Net = false; + break; + } + case L2_EV_LOST_NODE: { + DBG_INFO("Event L2_EV_LOST_NODE asserted....\n"); + break; + } + case L2_ROUTINE_FINISH: { + DBG_INFO("Event L2_ROUTINE_FINISH asserted....\n"); + if(instPtr->nextState == INIT_STATE){ + UpdateMainSate(instPtr, NORMAL_STATE); + instPtr->rtneConfig.rtneTable = normalTable; + instPtr->rtneConfig.rtnePrd = ARRAY_SIZE(normalTable); + } + else if(instPtr->nextState == NORMAL_STATE){ + instPtr->rtneConfig.rtneTable = normalTable; + instPtr->rtneConfig.rtnePrd = ARRAY_SIZE(normalTable); + } + else if(instPtr->nextState == SEEK_STATE){ + instPtr->rtneConfig.rtneTable = seekTable; + instPtr->rtneConfig.rtnePrd = ARRAY_SIZE(seekTable); + } + else if(instPtr->nextState == INTRA_SEEK_STATE){ + instPtr->rtneConfig.rtneTable = intraSeekTable; + instPtr->rtneConfig.rtnePrd = ARRAY_SIZE(intraSeekTable); + } + else if(instPtr->nextState == INTER_SEEK_STATE){ + instPtr->rtneConfig.rtneTable = interSeekTable; + instPtr->rtneConfig.rtnePrd = ARRAY_SIZE(interSeekTable); + } + break; + } + case L2_ROUTINE_UPDATE: { + DBG_INFO("Event L2_ROUTINE_UPDATE asserted....\n"); + L2_RTNE_CONFIG* newRtneConfig = (L2_RTNE_CONFIG*) l2Event->msg; + instPtr->rtneConfig.rtneTable = newRtneConfig->rtneTable; + instPtr->rtneConfig.rtnePrd = newRtneConfig->rtnePrd; + break; + } + default: { + DBG_WARNING("UNKNOWN Event %d asserted.\n", l2Event->event); + break; + } + } + return SUCCESS; +} + +/*****************************************************************************/ +/** + * @brief Handle l2 packet correctly received. + * + * @param instPtr a pointer to physical layer controller instance + * @param frameType + * + * @return Status code. + * + ******************************************************************************/ +int mgmtFrameRecv = 0; +int svcFrameRecv = 0; +int32_t Linklayer_PktHandler(L2_INST* instPtr, L2_FRAME_TYPE frameType) { + ASSERT(instPtr != NULL); + DBG_INFO("Link layer handling packet...\n"); + int32_t Status = SUCCESS; + + if (instPtr->dataAvail == false) { + return FAILURE; + } + + switch (frameType) { + case L2_INTER_SCAN_FRAME: + case L2_INTRA_SCAN_FRAME: + case L2_INTER_BM_FRAME: + case L2_INTRA_BM_FRAME: + case L2_INTER_W2_ACQ_FRAME: + case L2_INTRA_W2_ACQ_FRAME: + Status = ScanNet_PktHandler(instPtr); + break; + case L2_INTER_MGMT_FRAME: + case L2_INTRA_MGMT_FRAME: + case L2_INTER_TSYNC_FRAME: + case L2_INTRA_TSYNC_FRAME: + // TODO: + if(frameType == L2_INTRA_MGMT_FRAME){ + if (instPtr->buffSwitch == 0) { + memcpy(instPtr->mgmtMsgRecvBuff0 + (size_t)(instPtr->mgmtMsgRecvCnt0*(MGMT_MSG_LEN*ARRAY_SIZE(intraMgmtFrameMsgs)/8)), + instPtr->recvPktData, (size_t)(MGMT_MSG_LEN*ARRAY_SIZE(intraMgmtFrameMsgs)/8)); + instPtr->mgmtMsgRecvCnt0++; + } + else { + memcpy(instPtr->mgmtMsgRecvBuff1+ (size_t)(instPtr->mgmtMsgRecvCnt1*(MGMT_MSG_LEN*ARRAY_SIZE(intraMgmtFrameMsgs)/8)), + instPtr->recvPktData, (size_t)(MGMT_MSG_LEN*ARRAY_SIZE(intraMgmtFrameMsgs)/8)); + instPtr->mgmtMsgRecvCnt1++; + } + } + mgmtFrameRecv++; + Status = MgmtNet_PktHandler(instPtr); + break; + case L2_INTER_SVC_FRAME: + case L2_INTRA_SVC_FRAME: + // TODO: + if(frameType == L2_INTRA_SVC_FRAME){ + if (instPtr->buffSwitch == 0) { + memcpy(instPtr->svcMsgRecvBuff0 + (size_t) (instPtr->svcMsgRecvCnt0 * (INTRA_SVC_FRAME_LENGTH_MAX)), + instPtr->recvPktData, (size_t)(INTRA_SVC_FRAME_LENGTH_MAX)); + instPtr->svcMsgRecvCnt0 ++; + } + else { + memcpy(instPtr->svcMsgRecvBuff1+ (size_t)(instPtr->svcMsgRecvCnt1 * (INTRA_SVC_FRAME_LENGTH_MAX)), + instPtr->recvPktData, (size_t)(INTRA_SVC_FRAME_LENGTH_MAX)); + instPtr->svcMsgRecvCnt1 ++; + } + } + svcFrameRecv++; + Status = ServiceNet_PktHandler(instPtr); + break; + default: + DBG_WARNING("L2FrameHandler: UNKNOWN L2-FrameType %d", frameType); + Status = FAILURE; + break; + } + return Status; +} + +/*****************************************************************************/ +/** + * @brief Schedule next slot based on time allocate slice. + * + * @param instPtr a pointer to physical layer controller instance + * + * @return SUCCESS + * Other error code. + * + ******************************************************************************/ +static int32_t Linklayer_Routine (L2_INST* instPtr) { + ASSERT(instPtr != NULL); + int32_t Status; + uint32_t tableIndx, entryIndx; + + // FIXME: Consider time wrapping. + uint32_t currTime = TimeCtrl_GetIntCnt(instPtr->config.tmcInstPtr)/L2_SLOTS_PER_FRAME; + if(currTime < instPtr->netStartTime) { + DBG_WARNING("Linklayer not start yet, current time unit: %u, start time unit: %u.\n", + currTime, instPtr->netStartTime); + return EIGNORE; + } + + // Determine which routine entry is going to be performed. + tableIndx = L2_GetCurrentFrameNum(instPtr) % instPtr->rtneConfig.rtnePrd; + entryIndx = L2_GetCurrentSlotNum(instPtr); + L2_RTNE_TABLE_ENTRY rtneEntry = {0}; + + // Shift routine entry record. + instPtr->rtneConfig.last = instPtr->rtneConfig.curr; + instPtr->rtneConfig.curr = instPtr->rtneConfig.next; + instPtr->rtneConfig.next = &(instPtr->rtneConfig.rtneTable[tableIndx][entryIndx]); + rtneEntry = instPtr->rtneConfig.rtneTable[tableIndx][entryIndx]; + DBG_INFO("## Routine: %u-%u, Routine period: %u.\n", tableIndx, entryIndx, instPtr->rtneConfig.rtnePrd); + + // Implement a RTT procedure. + RTT_Proc(instPtr); + + switch (rtneEntry.slotType) { + case SLOT_IDLE: + // Skip a 5ms slot. + Status = SUCCESS; + DBG_INFO("Skipping idle slot (5ms)...\n"); + break; + case SLOT_INTER_SCAN_ACQ: + case SLOT_INTRA_SCAN_ACQ: + case SLOT_INTER_SCAN_BM: + case SLOT_INTRA_SCAN_BM: + case SLOT_INTER_SCAN_2W: + case SLOT_INTRA_SCAN_2W: + Status = ScanNet_Routine(instPtr, &rtneEntry); + break; + case SLOT_INTER_SVC: + case SLOT_INTRA_SVC: + Status = ServiceNet_Routine(instPtr, &rtneEntry); + break; + case SLOT_INTER_MGMT: + case SLOT_INTRA_MGMT: + case SLOT_INTER_TSYNC: + case SLOT_INTRA_TSYNC: + Status = MgmtNet_Routine(instPtr, &rtneEntry); + break; + default: + DBG_ERROR("UNKNOWN slot type [%d].\n", rtneEntry.slotType); + return EPARAM; + } + + // check if routine is finished. + if(entryIndx >= L2_SLOTS_PER_FRAME - 1 && tableIndx >= instPtr->rtneConfig.rtnePrd - 1){ + L2_EVENT rtneFinishEvent = {L2_ROUTINE_FINISH, &(instPtr->rtneConfig)}; + AssertL2Event(instPtr, &rtneFinishEvent); + } + + // FIXME: Increase TTL counter + if (instPtr->mainState != INIT_STATE) + { + if ( IsNodeInList (instPtr->nodeList, rtneEntry.src0) ) + { +// IncNodeTTL(usedSlots, rtneEntry.src0 ); + } + } + return Status; +} + +/*****************************************************************************/ +/** + * @brief Execute a link layer fsm process. + * + * @param instPtr a pointer to physical layer controller instance + * + * @return SUCCESS + * Other error code. + * + ******************************************************************************/ +int32_t Linklayer_Proc(L2_INST* instPtr) { + ASSERT(instPtr != NULL); + int32_t Status; + + if(instPtr->isEnable == false) { + DBG_INFO("######## Link Layer is not Enabled ########\n"); + return SUCCESS; + } + + DBG_INFO("######## Current frameNum: %u, SlotNo: %u ########\n", + instPtr->frameNum.curr, instPtr->slotNum.curr); + + // Update frame status. + L2_FrameStateUpdate(instPtr); + + // Handle frame received in last slot. + if(L2_isDataAvail(instPtr) == true){ + Linklayer_PktHandler(instPtr, L2_GetLastRcvFrameType(instPtr)); + } + + // Run Link layer routine, setup next slot procedure. + if (instPtr->myInfo.nodeType == HEAD_NODE) { + Phy_SetMode(instPtr->config.phyInstPtr, PHY_MODE_PULL); + Status = Linklayer_Routine(instPtr); + } + else { //MEMBER_NODE + if (L2_isCxn2Net(instPtr)) { + Phy_SetMode(instPtr->config.phyInstPtr, PHY_MODE_PULL); + Status = Linklayer_Routine(instPtr); + } + else { + Phy_SetMode(instPtr->config.phyInstPtr, PHY_MODE_LISTEN); + Status = ScanNet_Proc(instPtr); + } + } + // Check if previous runs has error occurred. + if (Status != SUCCESS) { + return Status; + } + + // Check and execute scheduled event. + L2_EventPoolHandler(instPtr); + + // Update slot number. + L2_UpdateSlotNum(instPtr); + + // Update link layer state. + instPtr->mainState = instPtr->nextState; + + // Upload data per 500ms + if (instPtr->slotNum.next % DATA_STORE_INTERVAL == 0) { + instPtr->buffSwitch = (instPtr->buffSwitch == 0) ? 1 : 0; + + if(instPtr->buffSwitch == 0){ + instPtr->mgmtMsgRecvCnt0 = 0; + instPtr->svcMsgRecvCnt0 = 0; + } + else{ + instPtr->mgmtMsgRecvCnt1 = 0; + instPtr->svcMsgRecvCnt1 = 0; + } + } + + return SUCCESS; +} diff --git a/datalink814_ge/src/linklayer/linklayer814.h b/datalink814_ge/src/linklayer/linklayer814.h new file mode 100644 index 0000000..fd146a1 --- /dev/null +++ b/datalink814_ge/src/linklayer/linklayer814.h @@ -0,0 +1,179 @@ +/*****************************************************************************/ +/** + * Description: Header file for 814 linklayer functions + * + * Date: 2021-11-13 13:33 + * LastEditors: Fan Hao + * LastEditTime: 2022-07-16 10:12 + * Revisions: Rev 0.1 + * History: + * [2022-07-16]: New branch for DiJian. + * [2021-11-23]: Initial version. + * + * Copyright(c) 2021 Beijing Institute of Technology. + * Lab of Communication and Networking + * + ******************************************************************************/ + +#ifndef LINKLAYER814_H_ +#define LINKLAYER814_H_ + +/***************************** Include Files *********************************/ +#include +#include "linklayer814_types.h" +#include "node_list.h" +#include "rtt.h" +#include "../bit_array/bit_array.h" +#include "../phy_ctrl/phy_ctrl.h" +#include "../time_ctrl/time_ctrl.h" + + + +/************************** Constant Definitions *****************************/ +#define DATA_STORE_INTERVAL 100 // 250ms + +#define NET_INI_STAGE 0 +#define NET_NORMAL_STAGE 1 +#define NET_INTER_SEEK_STAGE 2 +#define NET_INTRA_SEEK_STAGE 3 +#define NET_SEEK_STAGE 4 +#define NET_ERROR_STAGE -1 + +#define L2_PACKET_LEN_MAX 1024 //bit +/***************** Macros (Inline Functions) Definitions *********************/ +#define AssertL2Event(instPtr, event) Linklayer_EventHandler(instPtr, event) +/**************************** Type Definitions *******************************/ + +typedef struct { + L2_NODE_TYPE myType; + bool isInterHead; + uint8_t clustId; + uint8_t myId; + uint8_t headId; + uint8_t bkpHeadId; + uint8_t netScale; + PHY_INST* phyInstPtr; + TIMECTRL_INST* tmcInstPtr; +} L2_CONFIG; + +typedef struct { + L2_CONFIG config; + L2_NODE_INFO myInfo; + NODE_LIST* nodeList; + L2_SCHD_EVENT* l2SchdEventPool[L2_SCHD_EVENT_MAX]; + uint32_t schdEventCnt; + uint32_t netStartTime; + bool isEnable; // if the node is connected to the network + bool dataAvail; // if there is a valid received frame data in rx buffer + bool cxn2Net; // if the node is connected to the network + L2_RCD frameNum; // stores the last current and next frame number. + L2_RCD slotNum; // stores the last current and next slot number. + L2_RCD frame; // stores the last current and next link layer frame type. + L2_NODE_STATE mainState; // the main state of link layer state + L2_NODE_STATE nextState; // next state of link layer state, which will be applied to mainState every second. + L2_RTNE_CONFIG rtneConfig; // current routine table configuration and status. + L2_SCAN_FSM* scanNetFSM; // FSM of scan net (link set up) + L2_MGMT_FSM* mgmtNetFSM; // FSM of management net (link management and time sync) + L2_SVC_FSM* serviceNetFSM; // FSM of service net (data service) + L2_RTT_FSM* rttFSM; // FSM for RTT (time sync algorithm) + uint8_t* sendPktData; + uint8_t* recvPktData; + // for MPC + uint8_t buffSwitch; + uint8_t mgmtMsgRecvCnt0; + uint8_t svcMsgRecvCnt0; + uint8_t* mgmtMsgRecvBuff0; // mgmtMsg receive data buffer + uint8_t* svcMsgRecvBuff0; // svc receive data buffer + uint8_t mgmtMsgRecvCnt1; + uint8_t svcMsgRecvCnt1; + uint8_t* mgmtMsgRecvBuff1; // mgmtMsg receive data buffer + uint8_t* svcMsgRecvBuff1; // svc receive data buffer +} L2_INST; + +/************************** Variable Definitions *****************************/ +extern L2_RTNE_TABLE_ENTRY* initTable[L2_INIT_RTNE_PERIOD]; +extern L2_RTNE_TABLE_ENTRY* seekTable[L2_SEEK_RTNE_PERIOD]; +extern L2_RTNE_TABLE_ENTRY* interSeekTable[L2_NORMAL_RTNE_PERIOD]; +extern L2_RTNE_TABLE_ENTRY* intraSeekTable[L2_NORMAL_RTNE_PERIOD]; +extern L2_RTNE_TABLE_ENTRY* normalTable[L2_NORMAL_RTNE_PERIOD]; +/************************** Function Prototypes ******************************/ +// Main +int32_t Linklayer_Init(L2_INST** instPtr, const L2_CONFIG *config); +int32_t Linklayer_Reconfig(L2_INST* instPtr, const L2_CONFIG *config); +void Linklayer_Destroy(L2_INST* instPtr); +int32_t Linklayer_Start(L2_INST* instPtr); +int32_t Linklayer_Halt(L2_INST* instPtr); +int32_t Linklayer_Proc(L2_INST* instPtr); +int32_t Linklayer_EventHandler(L2_INST* instPtr, const L2_EVENT* l2Event); +int32_t Linklayer_PktHandler(L2_INST* instPtr, L2_FRAME_TYPE frameType); +int32_t L2_SetupNextSlot(L2_INST* instPtr, L2_TOR_TYPE txrxMode, L2_FRAME_TYPE frameType); + +// Event +bool L2_isEventScheduled(L2_SCHD_EVENT* schdEvent); +int32_t L2_CancelEvent(L2_SCHD_EVENT* schdEvent); +int32_t L2_SchdEventAppendMsg(L2_SCHD_EVENT* schdEvent, void* msg); +L2_SCHD_EVENT* L2_CreatNewSchdEvent(L2_INST* instPtr, L2_EVENT_TYPE event); +int32_t L2_DeletSchdEvent(L2_INST* instPtr, int32_t eventId); +void L2_ClearSchdEvent(L2_INST* instPtr); +int32_t L2_ScheduleEventAt(L2_INST* instPtr, L2_SCHD_EVENT* schdEvent, uint32_t frameNo, uint32_t slotNo); +int32_t L2_ScheduleEventAfter(L2_INST* instPtr, L2_SCHD_EVENT* schdEvent, uint32_t numSlots); +int32_t L2_RecheduleEventAt(L2_INST* instPtr, L2_SCHD_EVENT* schdEvent, uint32_t frameNo, uint32_t slotNo); +int32_t L2_RecheduleEventAfter(L2_INST* instPtr, L2_SCHD_EVENT* schdEvent, uint32_t numSlots); + +// Framing +void L2_FrameStateUpdate(L2_INST* instPtr); +L2_FRAME_TYPE L2_GetLastRcvFrameType(L2_INST* instPtr); +L1_FRAME_TYPE L2_L2frame2L1frame(L2_FRAME_TYPE l2Frame); +void FrameGetChunk(BIT_ARRAY* bitarr, uint32_t offset, uint32_t numBit, uint64_t* chunk); +void FrameInsertChunk(BIT_ARRAY* bitarr, uint32_t offset, uint32_t numBit, uint64_t chunck); +int32_t L2_CrcAppend(uint8_t* dataBuff, uint32_t dataLen, uint32_t crcPos, L2_CRC_TYPE crcType); +bool L2_CrcCheck(uint8_t* dataBuff, uint32_t dataLen, uint32_t crcPos, L2_CRC_TYPE crcType); + +// Scan Net +int32_t ScanNet_Init(L2_SCAN_FSM** scanFSMPtr); +void ScanNet_Reset(L2_SCAN_FSM* scanFSMPtr); +void ScanNet_Destroy(L2_SCAN_FSM* scanFSMPtr); +int32_t ScanNet_Proc(L2_INST* instPtr); +int32_t ScanNet_PktHandler(L2_INST* instPtr); +int32_t ScanNet_Routine(L2_INST* instPtr, const L2_RTNE_TABLE_ENTRY* rtneEntry); + +// Management Net +int32_t MgmtNet_Init(L2_MGMT_FSM** mgmtFSM); +void MgmtNet_Reset(L2_MGMT_FSM* mgmtFSM); +void MgmtNet_Destroy(L2_MGMT_FSM* mgmtFSM); +int32_t MgmtNet_PktHandler(L2_INST* instPtr); +int32_t MgmtNet_Routine(L2_INST* instPtr, const L2_RTNE_TABLE_ENTRY* rtneEntry); + + +// Service net +int32_t ServiceNet_Init(L2_SVC_FSM** serviceFSM); +void ServiceNet_Reset(L2_SVC_FSM* serviceFSM); +void ServiceNet_Destroy(L2_SVC_FSM* serviceFSM); +int32_t ServiceNet_PktHandler(L2_INST* instPtr); +int32_t ServiceNet_Routine(L2_INST* instPtr, const L2_RTNE_TABLE_ENTRY* schedEntry); + +// Miscellaneous +L2_NODE_STATE L2_GetMainState(L2_INST* instPtr); +L2_RTT_FSM* L2_GetRttDesc(L2_INST* instPtr); +bool L2_isDataAvail(L2_INST* instPtr); +bool L2_isCxn2Net(L2_INST* instPtr); +void L2_RcdShift(L2_RCD* rcd, int32_t netxVal); +uint32_t L2_GetFrameLen(L2_FRAME_TYPE l2FrameType); +uint32_t L2_GetLastFrameNum(L2_INST* instPtr); +uint32_t L2_GetLastSlotNum(L2_INST* instPtr); +uint32_t L2_GetCurrentFrameNum(L2_INST* instPtr); +uint32_t L2_GetCurrentSlotNum(L2_INST* instPtr); +uint32_t L2_GetNextFrameNum(L2_INST* instPtr); +uint32_t L2_GetNextSlotNum(L2_INST* instPtr); + +// Time syncronization +int32_t L2_TimeAlign(L2_INST* instPtr, uint32_t frameNum, uint32_t slotNum); + +// RTT +int32_t RTT_Init(L2_RTT_FSM** rttFsmPtr); +void RTT_Reset(L2_RTT_FSM* rttFsmPtr); +void RTT_Destroy(L2_RTT_FSM* rttFsmPtr); +int32_t RTT_Proc(L2_INST* instPtr); + + +#endif /* LINKLAYER814_H_ */ diff --git a/datalink814_ge/src/linklayer/linklayer814_types.h b/datalink814_ge/src/linklayer/linklayer814_types.h new file mode 100644 index 0000000..ce14166 --- /dev/null +++ b/datalink814_ge/src/linklayer/linklayer814_types.h @@ -0,0 +1,324 @@ +/*****************************************************************************/ +/** + * Description: A brief description of this file + * + * Date: 2022-08-28 22:53 + * LastEditors: Fan Hao + * LastEditTime: 2022-08-29 00:45 + * Revisions: Rev x.x + * History: + * [YYYY-MM-DD]: Description of modification. + * + * Copyright(c) 2022 Beijing Institute of Technology. + * Lab of Communication and Networking + * +******************************************************************************/ + +#ifndef LINKLAYER814_DEF_H_ +#define LINKLAYER814_DEF_H_ + +/***************************** Include Files *********************************/ +#include +#include +#include "geometry/coord.h" +#include "../phy_ctrl/phy_ctrl.h" +/************************** Constant Definitions *****************************/ +// Common node ID definition +#define BROADCAST_ID 0x1F +#define NONE_ID BROADCAST_ID + +// for MPC Configure +#define MSG_STROAGE_BUFF_MAX 16384 // 16K Bytes + +// Routine configure +#define L2_INIT_RTNE_PERIOD 24 +#define L2_NORMAL_RTNE_PERIOD 60 +#define L2_SEEK_RTNE_PERIOD 60 +#define L2_INTER_SEEK_RTNE_PERIOD 60 +#define L2_INTRA_SEEK_RTNE_PERIOD 60 + +// Common slot number definition +#define L2_SLOTNO_NONE 0 +#define L2_FRAMENO_NONE 0 + +// Common number of slots definition +#define L2_SLOTS_PER_FRAME 200 +#define L2_SLOTS_PER_SUBFRAME 20 + +#define NUM_SLOTS_NONE UINT32_MAX +#define NUM_SLOTS_20MS 4 +#define NUM_SLOTS_10MS 2 +#define NUM_SLOTS_5MS 1 +#define NUM_SLOTS_SKIP 0 + +// Common schedule event definition +#define L2_SCHD_EVENT_MAX 16 + +/**************************** Type Definitions *******************************/ + +typedef struct { + uint32_t last; + uint32_t curr; + uint32_t next; +} L2_RCD; + +/** @name Tx/Rx mode code + */ +typedef enum { + L2_TOR_SUSPEND = 0, + L2_TOR_TX = 1, + L2_TOR_RX = 2 +} L2_TOR_TYPE; + +/** @name Prior information type definition + */ +typedef enum { + NONE_TYPE = 0, + HEAD_NODE = 1, + MEMBER_NODE = 2, + BACKUP_HEAD = 3 +} L2_NODE_TYPE; + +/** @name Node state type definition + */ +typedef enum { + NONE_STATE = 0, + INIT_STATE = 1, + NORMAL_STATE = 2, + INTRA_SEEK_STATE = 3, + INTER_SEEK_STATE = 4, + SEEK_STATE = 5 +} L2_NODE_STATE; + +typedef struct { + uint8_t nodeId; + uint8_t clustId; + L2_NODE_TYPE nodeType; + uint8_t beamNo; + COORD pos; + COORD speed; +} L2_NODE_INFO; + +/** @name L2 event enum + * A enum of L2 event types. + */ +typedef enum { + L2_EV_NONE = 0, + L2_EV_SCAN_PROC_DONE = 1, + L2_EV_MGMT_PROC_DONE = 2, + L2_EV_NET_SETUP_DONE = 3, + L2_EV_TIME_SYNC = 4, + L2_EV_LINK_SET_REQ = 6, + L2_EV_LOST_CXN = 7, + L2_EV_LOST_NODE = 8, + L2_EV_SET_FRAME_NUM = 9, + L2_EV_SET_SLOT_NUM = 10, + L2_EV_MAIN_STATE_UPDATE = 11, + L2_ROUTINE_FINISH = 12, + L2_ROUTINE_UPDATE = 13 +} L2_EVENT_TYPE; + +/** @name L2 event + * A definition of L2 event instance. + */ +typedef struct { + L2_EVENT_TYPE event; + void* msg; +} L2_EVENT; + +/** @name L2 event + * A definition of L2 event instance. + */ +typedef struct { + uint8_t eventId; + bool isSchd; + L2_EVENT l2Event; + uint32_t schdFrame; + uint32_t schdSlot; +} L2_SCHD_EVENT; + +/** @name Slot types + * A definition of different slots. + */ +typedef enum { + SLOT_NONE = 0, + SLOT_IDLE = 1, + SLOT_INTER_SCAN_ACQ = 2, + SLOT_INTRA_SCAN_ACQ = 3, + SLOT_INTER_SCAN_BM = 4, + SLOT_INTRA_SCAN_BM = 5, + SLOT_INTER_SCAN_2W = 6, + SLOT_INTRA_SCAN_2W = 7, + SLOT_INTER_SVC = 8, + SLOT_INTRA_SVC = 9, + SLOT_INTER_MGMT = 10, + SLOT_INTRA_MGMT = 11, + SLOT_INTER_TSYNC = 12, + SLOT_INTRA_TSYNC = 13, +} L2_SLOT_TYPE; + +/** @name Frame types + * A definition of different frame types. + */ +typedef enum { + L2_CRC_NONE = 0, + L2_CRC16_1021 = 1, + L2_CRC16_8005 = 2, + L2_CRC8_31 = 3 +} L2_CRC_TYPE; + +/** @name Frame types + * A definition of different frame types. + */ +typedef enum { + L2_NONE_FRAME = 0, + L2_INTER_SCAN_FRAME = 1, + L2_INTRA_SCAN_FRAME = 2, + L2_INTER_BM_FRAME = 3, + L2_INTRA_BM_FRAME = 4, + L2_INTER_W2_ACQ_FRAME = 5, + L2_INTRA_W2_ACQ_FRAME = 6, + L2_INTER_MGMT_FRAME = 7, + L2_INTRA_MGMT_FRAME = 8, + L2_INTER_TSYNC_FRAME = 9, + L2_INTRA_TSYNC_FRAME = 10, + L2_INTER_SVC_FRAME = 11, + L2_INTRA_SVC_FRAME = 12 +} L2_FRAME_TYPE; + +/** @name Schedule subtable entry + * A definition of Schedule subtable entry. + */ +typedef struct { + L2_SLOT_TYPE slotType : 8; + uint8_t slotSeq; + uint8_t src0; + uint8_t dst0; + uint8_t src1; + uint8_t dst1; +} L2_RTNE_TABLE_ENTRY; + + + + // Scan net +typedef struct { + uint8_t NodeId; + uint8_t ClusterId; + uint32_t frameNum; + uint32_t slotNum; + uint16_t EastSpeed; + uint16_t NorthSpeed; + uint16_t UpperSpeed; + uint32_t Height; + uint32_t Longitude; + uint32_t Latitude; +} L2_BM_LOG; + +typedef struct { + uint8_t NodeId; + uint8_t ClusterId; + uint16_t EastSpeed; + uint16_t NorthSpeed; + uint16_t UpperSpeed; + uint32_t Height; + uint32_t Longitude; + uint32_t Latitude; + L2_NODE_STATE NetStage; + uint32_t NetScanTime; +} L2_W2ACQ_LOG; + +typedef enum { + NONE_STAGE = 0, + INIT_SCAN_STAGE = 1, + BM_ADVT_STAGE = 2, // Benchmark advertisement + WAY2_ACQ_STAGE = 3 +} SCAN_STAGE; + +typedef enum { + NONE_MODE = 0, + INTRA_CLUSTER_MODE = 1, + INTER_CLUSTER_MODE = 2 +} SCAN_MODE; + +typedef struct { + bool isLocked; // init acq done. + bool isBmRcved;// bm received. + bool isAcked; // 2way acq done. + uint32_t bmTimeout; + uint32_t w2acqTimeout; + SCAN_STAGE scanStage; // only for member node + SCAN_MODE scanMode; // inter sanc or intra scan + L2_BM_LOG BMrcvLog; + L2_W2ACQ_LOG W2ACQrcvLog; +} L2_SCAN_FSM; + +// Service Net +typedef struct { + bool isBisar; + bool isBisarEven; // Send frame at even slot at bisar mode. + uint8_t bisarDst; + uint32_t bisarEndframe; +} L2_SVC_FSM; + + +// Management net +typedef struct { + uint8_t wordTag ; + uint8_t msgTag ; + uint8_t msgSubTag; + uint8_t srcNodeId ; + uint8_t quitNodeId ; + uint8_t quitCtrlWord ; + uint8_t nextNetState; + uint16_t EastSpeed ; + uint16_t NorthSpeed; + uint16_t UpperSpeed; + uint32_t Height ; + uint32_t Longitude ; + uint32_t Latitude ; + bool isValid; +} MGMT_MSG_RECORD; + +typedef struct { + uint16_t wordTag; + uint16_t msgTag; + uint16_t msgSubTag; + uint16_t msgLen; + uint16_t srcAddr; + uint16_t dstAddr; + uint32_t timeWordL; + uint32_t timeWordH; + int32_t doppler; +} RTT_MSG_RECORD; + +typedef struct { + uint32_t timeH; + uint32_t timeL; +} L2_TIME_WORD; + +typedef struct { + L2_TIME_WORD rttTime; + uint32_t rttDoppler; +} RTT_DATA; + +typedef struct { + bool isBisarProc; + bool isPendTimeAlloc; + bool isPendSlotAlloc; + MGMT_MSG_RECORD mgmtMsgLog; + RTT_MSG_RECORD rttMsgRspLog; + RTT_MSG_RECORD rttMsgReqLog; + RTT_DATA rttData; +} L2_MGMT_FSM; + + +typedef struct{ + L2_RTNE_TABLE_ENTRY** rtneTable; + uint32_t rtnePrd; + L2_RTNE_TABLE_ENTRY* last; + L2_RTNE_TABLE_ENTRY* curr; + L2_RTNE_TABLE_ENTRY* next; +}L2_RTNE_CONFIG; + +/************************** Variable Definitions *****************************/ +#endif /* LINKLAYER814_H_ */ diff --git a/datalink814_ge/src/linklayer/linklayer_routine.c b/datalink814_ge/src/linklayer/linklayer_routine.c new file mode 100644 index 0000000..6b2a67a --- /dev/null +++ b/datalink814_ge/src/linklayer/linklayer_routine.c @@ -0,0 +1,791 @@ +/*****************************************************************************/ +/** + * Description: Time allocations for 814 datalink, + * Date: 2022-07-16 17:05 + * LastEditors: Fan Hao + * LastEditTime: 2022-07-16 17:05 + * Revisions: Rev 0.1 + * History: + * [2021-11-13]: Initial version. + * + * Copyright(c) 2021 Beijing Institute of Technology. + * Lab of Communication and Networking + * + ******************************************************************************/ + +#include + +#include "linklayer814_types.h" + +L2_RTNE_TABLE_ENTRY normalSubT_0[L2_SLOTS_PER_FRAME] = { +// Frame 1 + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + +// Frame 2 + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + +// Frame 3 + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + +// Frame 4 + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + +// Frame 5 + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + +// Frame 6 + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + +// Frame 7 + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + +// Frame 8 + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + +// Frame 9 + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + +// Frame 10 + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00} +}; + + + +L2_RTNE_TABLE_ENTRY normalSubT_1[L2_SLOTS_PER_FRAME] = { +// Frame 1 + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + +// Frame 2 + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + +// Frame 3 + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + +// Frame 4 + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + +// Frame 5 + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + +// Frame 6 + {SLOT_INTRA_TSYNC,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + +// Frame 7 + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_TSYNC,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_TSYNC,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + +// Frame 8 + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, {SLOT_INTRA_TSYNC,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + +// Frame 9 + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + +// Frame 10 + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, {SLOT_INTRA_SVC ,0x00,0x02,0x01,0x00,0x00}, + {SLOT_INTRA_MGMT ,0x00,0x01,0x02,0x00,0x00}, {SLOT_INTRA_MGMT ,0x00,0x02,0x01,0x00,0x00} +}; + +// L2_RTNE_TABLE_ENTRY interScanSubT_0[L2_SLOTS_PER_FRAME] = { +// // Frame 1 +// {SLOT_INTER_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_ACQ,0x00,0x02,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x03,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_ACQ,0x00,0x02,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x03,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_ACQ,0x00,0x02,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x03,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_ACQ,0x00,0x02,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x03,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_ACQ,0x00,0x02,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x03,0x01,0x1F,0x00,0x00}, +// // Frame 2 +// {SLOT_INTER_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_ACQ,0x00,0x02,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x03,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_ACQ,0x00,0x02,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x03,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_ACQ,0x00,0x02,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x03,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_ACQ,0x00,0x02,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x03,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_ACQ,0x00,0x02,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x03,0x01,0x1F,0x00,0x00}, +// // Frame 3 +// {SLOT_INTER_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_ACQ,0x00,0x02,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x03,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_ACQ,0x00,0x02,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x03,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_ACQ,0x00,0x02,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x03,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_ACQ,0x00,0x02,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x03,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_ACQ,0x00,0x02,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x03,0x01,0x1F,0x00,0x00}, +// // Frame 4 +// {SLOT_INTER_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_ACQ,0x00,0x02,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x03,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_ACQ,0x00,0x02,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x03,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_ACQ,0x00,0x02,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x03,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_ACQ,0x00,0x02,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x03,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_ACQ,0x00,0x02,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x03,0x01,0x1F,0x00,0x00}, +// // Frame 5 +// {SLOT_INTER_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_ACQ,0x00,0x02,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x03,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_ACQ,0x00,0x02,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x03,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_ACQ,0x00,0x02,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x03,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_ACQ,0x00,0x02,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x03,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_ACQ,0x00,0x02,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x03,0x01,0x1F,0x00,0x00}, +// // Frame 6 +// {SLOT_INTER_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_ACQ,0x00,0x02,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x03,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_ACQ,0x00,0x02,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x03,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_ACQ,0x00,0x02,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x03,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_ACQ,0x00,0x02,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x03,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_ACQ,0x00,0x02,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x03,0x01,0x1F,0x00,0x00}, +// // Frame 7 +// {SLOT_INTER_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_ACQ,0x00,0x02,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x03,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_ACQ,0x00,0x02,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x03,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_ACQ,0x00,0x02,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x03,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_ACQ,0x00,0x02,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x03,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_ACQ,0x00,0x02,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x03,0x01,0x1F,0x00,0x00}, +// // Frame 8 +// {SLOT_INTER_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_ACQ,0x00,0x02,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x03,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_ACQ,0x00,0x02,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_ACQ,0x03,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_BM,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_BM,0x01,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_BM,0x02,0x01,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_BM,0x03,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_BM,0x04,0x01,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_BM,0x05,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_BM,0x06,0x01,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_BM,0x07,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_BM,0x08,0x01,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_BM,0x09,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_BM,0x0A,0x01,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_BM,0x0B,0x01,0x1F,0x00,0x00}, +// // Frame 9 +// {SLOT_INTER_SCAN_BM,0x0C,0x01,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_BM,0x0D,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_BM,0x0E,0x01,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_BM,0x0F,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_BM,0x10,0x01,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_BM,0x11,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_BM,0x12,0x01,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_BM,0x13,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_2W,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_2W,0x01,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_2W,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_2W,0x01,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_2W,0x00,0x1F,0x01,0x00,0x00}, {SLOT_INTER_SCAN_2W,0x01,0x1F,0x01,0x00,0x00}, +// {SLOT_INTER_SCAN_2W,0x00,0x1F,0x01,0x00,0x00}, {SLOT_INTER_SCAN_2W,0x01,0x1F,0x01,0x00,0x00}, +// {SLOT_INTER_SCAN_2W,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_2W,0x01,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_2W,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_2W,0x01,0x01,0x1F,0x00,0x00}, +// // Frame 10 +// {SLOT_INTER_SCAN_2W,0x00,0x1F,0x01,0x00,0x00}, {SLOT_INTER_SCAN_2W,0x01,0x1F,0x01,0x00,0x00}, +// {SLOT_INTER_SCAN_2W,0x00,0x1F,0x01,0x00,0x00}, {SLOT_INTER_SCAN_2W,0x01,0x1F,0x01,0x00,0x00}, +// {SLOT_INTER_SCAN_2W,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_2W,0x01,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_2W,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_2W,0x01,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_2W,0x00,0x1F,0x01,0x00,0x00}, {SLOT_INTER_SCAN_2W,0x01,0x1F,0x01,0x00,0x00}, +// {SLOT_INTER_SCAN_2W,0x00,0x1F,0x01,0x00,0x00}, {SLOT_INTER_SCAN_2W,0x01,0x1F,0x01,0x00,0x00}, +// {SLOT_INTER_SCAN_2W,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_2W,0x01,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_2W,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTER_SCAN_2W,0x01,0x01,0x1F,0x00,0x00}, +// {SLOT_INTER_SCAN_2W,0x00,0x1F,0x01,0x00,0x00}, {SLOT_INTER_SCAN_2W,0x01,0x1F,0x01,0x00,0x00}, +// {SLOT_INTER_SCAN_2W,0x00,0x1F,0x01,0x00,0x00}, {SLOT_INTER_SCAN_2W,0x01,0x1F,0x01,0x00,0x00} +// }; + + +L2_RTNE_TABLE_ENTRY interScanSubT_0[L2_SLOTS_PER_FRAME] = { +// Frame 1 + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, +// Frame 2 + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, +// Frame 3 + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, +// Frame 4 + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, +// Frame 5 + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, +// Frame 6 + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, +// Frame 7 + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, +// Frame 8 + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, +// Frame 9 + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, +// Frame 10 + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00} +}; + +L2_RTNE_TABLE_ENTRY interScanSubT_1[L2_SLOTS_PER_FRAME] = { +// Frame 1 + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, +// Frame 2 + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, +// Frame 3 + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, +// Frame 4 + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, +// Frame 5 + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, +// Frame 6 + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, +// Frame 7 + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, +// Frame 8 + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, +// Frame 9 + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, +// Frame 10 + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, +}; + +L2_RTNE_TABLE_ENTRY intraScanSubT[L2_SLOTS_PER_FRAME] = { +// Frame 1 + {SLOT_INTRA_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTRA_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, + {SLOT_INTRA_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTRA_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, + {SLOT_INTRA_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTRA_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, + {SLOT_INTRA_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTRA_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, + {SLOT_INTRA_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTRA_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, + {SLOT_INTRA_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTRA_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, + {SLOT_INTRA_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTRA_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, + {SLOT_INTRA_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTRA_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, + {SLOT_INTRA_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTRA_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, + {SLOT_INTRA_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTRA_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, +// Frame 2 + {SLOT_INTRA_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTRA_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, + {SLOT_INTRA_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTRA_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, + {SLOT_INTRA_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTRA_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, + {SLOT_INTRA_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTRA_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, + {SLOT_INTRA_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTRA_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, + {SLOT_INTRA_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTRA_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, + {SLOT_INTRA_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTRA_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, + {SLOT_INTRA_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTRA_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, + {SLOT_INTRA_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTRA_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, + {SLOT_INTRA_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTRA_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, +// Frame 3 + {SLOT_INTRA_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTRA_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, + {SLOT_INTRA_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTRA_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, + {SLOT_INTRA_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTRA_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, + {SLOT_INTRA_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTRA_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, + {SLOT_INTRA_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTRA_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, + {SLOT_INTRA_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTRA_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, + {SLOT_INTRA_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTRA_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, + {SLOT_INTRA_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTRA_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, + {SLOT_INTRA_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTRA_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, + {SLOT_INTRA_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTRA_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, +// Frame 4 + {SLOT_INTRA_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTRA_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, + {SLOT_INTRA_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTRA_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, + {SLOT_INTRA_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTRA_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, + {SLOT_INTRA_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTRA_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, + {SLOT_INTRA_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTRA_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, + {SLOT_INTRA_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTRA_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, + {SLOT_INTRA_SCAN_ACQ,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTRA_SCAN_ACQ,0x01,0x01,0x1F,0x00,0x00}, + {SLOT_INTRA_SCAN_BM,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTRA_SCAN_BM,0x01,0x01,0x1F,0x00,0x00}, + {SLOT_INTRA_SCAN_BM,0x02,0x01,0x1F,0x00,0x00}, {SLOT_INTRA_SCAN_BM,0x03,0x01,0x1F,0x00,0x00}, + {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, {SLOT_IDLE,0x00,0x00,0x00,0x00,0x00}, +// Frame 5 + {SLOT_INTRA_SCAN_2W,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTRA_SCAN_2W,0x00,0x01,0x1F,0x00,0x00}, + {SLOT_INTRA_SCAN_2W,0x00,0x1F,0x01,0x00,0x00}, {SLOT_INTRA_SCAN_2W,0x00,0x1F,0x01,0x00,0x00}, + {SLOT_INTRA_SCAN_2W,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTRA_SCAN_2W,0x00,0x01,0x1F,0x00,0x00}, + {SLOT_INTRA_SCAN_2W,0x00,0x1F,0x01,0x00,0x00}, {SLOT_INTRA_SCAN_2W,0x00,0x1F,0x01,0x00,0x00}, + {SLOT_INTRA_SCAN_2W,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTRA_SCAN_2W,0x00,0x01,0x1F,0x00,0x00}, + {SLOT_INTRA_SCAN_2W,0x00,0x1F,0x01,0x00,0x00}, {SLOT_INTRA_SCAN_2W,0x00,0x1F,0x01,0x00,0x00}, + {SLOT_INTRA_SCAN_2W,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTRA_SCAN_2W,0x00,0x01,0x1F,0x00,0x00}, + {SLOT_INTRA_SCAN_2W,0x00,0x1F,0x01,0x00,0x00}, {SLOT_INTRA_SCAN_2W,0x00,0x1F,0x01,0x00,0x00}, + {SLOT_INTRA_SCAN_2W,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTRA_SCAN_2W,0x00,0x01,0x1F,0x00,0x00}, + {SLOT_INTRA_SCAN_2W,0x00,0x1F,0x01,0x00,0x00}, {SLOT_INTRA_SCAN_2W,0x00,0x1F,0x01,0x00,0x00}, +// Frame 6 + {SLOT_INTRA_SCAN_2W,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTRA_SCAN_2W,0x00,0x01,0x1F,0x00,0x00}, + {SLOT_INTRA_SCAN_2W,0x00,0x1F,0x01,0x00,0x00}, {SLOT_INTRA_SCAN_2W,0x00,0x1F,0x01,0x00,0x00}, + {SLOT_INTRA_SCAN_2W,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTRA_SCAN_2W,0x00,0x01,0x1F,0x00,0x00}, + {SLOT_INTRA_SCAN_2W,0x00,0x1F,0x01,0x00,0x00}, {SLOT_INTRA_SCAN_2W,0x00,0x1F,0x01,0x00,0x00}, + {SLOT_INTRA_SCAN_2W,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTRA_SCAN_2W,0x00,0x01,0x1F,0x00,0x00}, + {SLOT_INTRA_SCAN_2W,0x00,0x1F,0x01,0x00,0x00}, {SLOT_INTRA_SCAN_2W,0x00,0x1F,0x01,0x00,0x00}, + {SLOT_INTRA_SCAN_2W,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTRA_SCAN_2W,0x00,0x01,0x1F,0x00,0x00}, + {SLOT_INTRA_SCAN_2W,0x00,0x1F,0x01,0x00,0x00}, {SLOT_INTRA_SCAN_2W,0x00,0x1F,0x01,0x00,0x00}, + {SLOT_INTRA_SCAN_2W,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTRA_SCAN_2W,0x00,0x01,0x1F,0x00,0x00}, + {SLOT_INTRA_SCAN_2W,0x00,0x1F,0x01,0x00,0x00}, {SLOT_INTRA_SCAN_2W,0x00,0x1F,0x01,0x00,0x00}, +// Frame 7 + {SLOT_INTRA_SCAN_2W,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTRA_SCAN_2W,0x00,0x01,0x1F,0x00,0x00}, + {SLOT_INTRA_SCAN_2W,0x00,0x1F,0x01,0x00,0x00}, {SLOT_INTRA_SCAN_2W,0x00,0x1F,0x01,0x00,0x00}, + {SLOT_INTRA_SCAN_2W,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTRA_SCAN_2W,0x00,0x01,0x1F,0x00,0x00}, + {SLOT_INTRA_SCAN_2W,0x00,0x1F,0x01,0x00,0x00}, {SLOT_INTRA_SCAN_2W,0x00,0x1F,0x01,0x00,0x00}, + {SLOT_INTRA_SCAN_2W,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTRA_SCAN_2W,0x00,0x01,0x1F,0x00,0x00}, + {SLOT_INTRA_SCAN_2W,0x00,0x1F,0x01,0x00,0x00}, {SLOT_INTRA_SCAN_2W,0x00,0x1F,0x01,0x00,0x00}, + {SLOT_INTRA_SCAN_2W,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTRA_SCAN_2W,0x00,0x01,0x1F,0x00,0x00}, + {SLOT_INTRA_SCAN_2W,0x00,0x1F,0x01,0x00,0x00}, {SLOT_INTRA_SCAN_2W,0x00,0x1F,0x01,0x00,0x00}, + {SLOT_INTRA_SCAN_2W,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTRA_SCAN_2W,0x00,0x01,0x1F,0x00,0x00}, + {SLOT_INTRA_SCAN_2W,0x00,0x1F,0x01,0x00,0x00}, {SLOT_INTRA_SCAN_2W,0x00,0x1F,0x01,0x00,0x00}, +// Frame 8 + {SLOT_INTRA_SCAN_2W,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTRA_SCAN_2W,0x00,0x01,0x1F,0x00,0x00}, + {SLOT_INTRA_SCAN_2W,0x00,0x1F,0x01,0x00,0x00}, {SLOT_INTRA_SCAN_2W,0x00,0x1F,0x01,0x00,0x00}, + {SLOT_INTRA_SCAN_2W,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTRA_SCAN_2W,0x00,0x01,0x1F,0x00,0x00}, + {SLOT_INTRA_SCAN_2W,0x00,0x1F,0x01,0x00,0x00}, {SLOT_INTRA_SCAN_2W,0x00,0x1F,0x01,0x00,0x00}, + {SLOT_INTRA_SCAN_2W,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTRA_SCAN_2W,0x00,0x01,0x1F,0x00,0x00}, + {SLOT_INTRA_SCAN_2W,0x00,0x1F,0x01,0x00,0x00}, {SLOT_INTRA_SCAN_2W,0x00,0x1F,0x01,0x00,0x00}, + {SLOT_INTRA_SCAN_2W,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTRA_SCAN_2W,0x00,0x01,0x1F,0x00,0x00}, + {SLOT_INTRA_SCAN_2W,0x00,0x1F,0x01,0x00,0x00}, {SLOT_INTRA_SCAN_2W,0x00,0x1F,0x01,0x00,0x00}, + {SLOT_INTRA_SCAN_2W,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTRA_SCAN_2W,0x00,0x01,0x1F,0x00,0x00}, + {SLOT_INTRA_SCAN_2W,0x00,0x1F,0x01,0x00,0x00}, {SLOT_INTRA_SCAN_2W,0x00,0x1F,0x01,0x00,0x00}, +// Frame 9 + {SLOT_INTRA_SCAN_2W,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTRA_SCAN_2W,0x00,0x01,0x1F,0x00,0x00}, + {SLOT_INTRA_SCAN_2W,0x00,0x1F,0x01,0x00,0x00}, {SLOT_INTRA_SCAN_2W,0x00,0x1F,0x01,0x00,0x00}, + {SLOT_INTRA_SCAN_2W,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTRA_SCAN_2W,0x00,0x01,0x1F,0x00,0x00}, + {SLOT_INTRA_SCAN_2W,0x00,0x1F,0x01,0x00,0x00}, {SLOT_INTRA_SCAN_2W,0x00,0x1F,0x01,0x00,0x00}, + {SLOT_INTRA_SCAN_2W,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTRA_SCAN_2W,0x00,0x01,0x1F,0x00,0x00}, + {SLOT_INTRA_SCAN_2W,0x00,0x1F,0x01,0x00,0x00}, {SLOT_INTRA_SCAN_2W,0x00,0x1F,0x01,0x00,0x00}, + {SLOT_INTRA_SCAN_2W,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTRA_SCAN_2W,0x00,0x01,0x1F,0x00,0x00}, + {SLOT_INTRA_SCAN_2W,0x00,0x1F,0x01,0x00,0x00}, {SLOT_INTRA_SCAN_2W,0x00,0x1F,0x01,0x00,0x00}, + {SLOT_INTRA_SCAN_2W,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTRA_SCAN_2W,0x00,0x01,0x1F,0x00,0x00}, + {SLOT_INTRA_SCAN_2W,0x00,0x1F,0x01,0x00,0x00}, {SLOT_INTRA_SCAN_2W,0x00,0x1F,0x01,0x00,0x00}, +// Frame 10 + {SLOT_INTRA_SCAN_2W,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTRA_SCAN_2W,0x00,0x01,0x1F,0x00,0x00}, + {SLOT_INTRA_SCAN_2W,0x00,0x1F,0x01,0x00,0x00}, {SLOT_INTRA_SCAN_2W,0x00,0x1F,0x01,0x00,0x00}, + {SLOT_INTRA_SCAN_2W,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTRA_SCAN_2W,0x00,0x01,0x1F,0x00,0x00}, + {SLOT_INTRA_SCAN_2W,0x00,0x1F,0x01,0x00,0x00}, {SLOT_INTRA_SCAN_2W,0x00,0x1F,0x01,0x00,0x00}, + {SLOT_INTRA_SCAN_2W,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTRA_SCAN_2W,0x00,0x01,0x1F,0x00,0x00}, + {SLOT_INTRA_SCAN_2W,0x00,0x1F,0x01,0x00,0x00}, {SLOT_INTRA_SCAN_2W,0x00,0x1F,0x01,0x00,0x00}, + {SLOT_INTRA_SCAN_2W,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTRA_SCAN_2W,0x00,0x01,0x1F,0x00,0x00}, + {SLOT_INTRA_SCAN_2W,0x00,0x1F,0x01,0x00,0x00}, {SLOT_INTRA_SCAN_2W,0x00,0x1F,0x01,0x00,0x00}, + {SLOT_INTRA_SCAN_2W,0x00,0x01,0x1F,0x00,0x00}, {SLOT_INTRA_SCAN_2W,0x00,0x01,0x1F,0x00,0x00}, + {SLOT_INTRA_SCAN_2W,0x00,0x1F,0x01,0x00,0x00}, {SLOT_INTRA_SCAN_2W,0x00,0x1F,0x01,0x00,0x00} +}; + + +L2_RTNE_TABLE_ENTRY* initTable[L2_INIT_RTNE_PERIOD] = { + interScanSubT_0, interScanSubT_1, interScanSubT_0, interScanSubT_1, interScanSubT_0, interScanSubT_1, + interScanSubT_0, interScanSubT_1, interScanSubT_0, interScanSubT_1, interScanSubT_0, interScanSubT_1, + intraScanSubT, intraScanSubT, intraScanSubT, intraScanSubT, intraScanSubT, intraScanSubT, + intraScanSubT, intraScanSubT, intraScanSubT, intraScanSubT, intraScanSubT, intraScanSubT +}; + + +L2_RTNE_TABLE_ENTRY* seekTable[L2_SEEK_RTNE_PERIOD] = { + interScanSubT_0, interScanSubT_1, interScanSubT_0, interScanSubT_1, interScanSubT_0, interScanSubT_1, + interScanSubT_0, interScanSubT_1, interScanSubT_0, interScanSubT_1, interScanSubT_0, interScanSubT_1, + normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, + normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, + normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, + intraScanSubT, intraScanSubT, intraScanSubT, intraScanSubT, intraScanSubT, intraScanSubT, + normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, + normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, + normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, + normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1 +}; + +// L2_RTNE_TABLE_ENTRY* seekTable[L2_SEEK_RTNE_PERIOD] = { +// normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, +// normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, +// normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, +// normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, +// normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, +// intraScanSubT, intraScanSubT, intraScanSubT, intraScanSubT, intraScanSubT, intraScanSubT, +// normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, +// normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, +// normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, +// normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1 +// }; + +L2_RTNE_TABLE_ENTRY* interSeekTable[L2_INTER_SEEK_RTNE_PERIOD] = { + interScanSubT_0, interScanSubT_1, interScanSubT_0, interScanSubT_1, interScanSubT_0, interScanSubT_1, + interScanSubT_0, interScanSubT_1, interScanSubT_0, interScanSubT_1, interScanSubT_0, interScanSubT_1, + normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, + normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, + normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, + normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, + normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, + normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, + normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, + normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1 +}; + +L2_RTNE_TABLE_ENTRY* intraSeekTable[L2_INTRA_SEEK_RTNE_PERIOD] = { + normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, + normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, + normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, + normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, + normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, + intraScanSubT, intraScanSubT, intraScanSubT, intraScanSubT, intraScanSubT, intraScanSubT, + normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, + normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, + normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, + normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1 +}; + +L2_RTNE_TABLE_ENTRY* normalTable[L2_NORMAL_RTNE_PERIOD] = { + normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, + normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, + normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, + normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, + normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, + normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, + normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, + normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, + normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, + normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1, normalSubT_1 +}; diff --git a/datalink814_ge/src/linklayer/msg_def.h b/datalink814_ge/src/linklayer/msg_def.h new file mode 100644 index 0000000..ee9c2d2 --- /dev/null +++ b/datalink814_ge/src/linklayer/msg_def.h @@ -0,0 +1,614 @@ +/*****************************************************************************/ +/** + * Description: Header of 814 linklayer messages + * + * Date: 2022-07-14 00:08 + * LastEditors: Fan Hao + * LastEditTime: 2022-07-14 22:52 + * Revisions: Rev 0.0 + * History: + * [2022-07-14]: Initial version. + * + * Copyright(c) 2021 Beijing Institute of Technology. + * Lab of Communication and Networking + * + ******************************************************************************/ +#ifndef MSG_DEF_H_ +#define MSG_DEF_H_ + +#define L2_MSG_LEN 72 // bit +#define L2_MSG_MAX 512 // bit +#define PDU_CRC_LEN 16 +// ** 77 Basic Header 1 Format ** // +#define PDUH0_LEN 112 +#define PDUH0_TYPE_LEN 1 +#define PDUH0_TYPE_OFFSET 0 +#define PDUH0_RESV_LEN 7 +#define PDUH0_RESV_OFFSET 1 +#define PDUH0_LENGTH_LEN 16 +#define PDUH0_LENGTH_OFFSET 8 +#define PDUH0_SRC_ADDR_LEN 10 +#define PDUH0_SRC_ADDR_OFFSET 24 +#define PDUH0_DST_ADDR_LEN 10 +#define PDUH0_DST_ADDR_OFFSET 34 +#define PDUH0_SEQ_NUM_LEN 16 +#define PDUH0_SEQ_NUM_OFFSET 44 +#define PDUH0_RESV_1_LEN 44 +#define PDUH0_RESV_1_OFFSET 60 +#define PDUH0_HEADER_CRC_LEN 8 +#define PDUH0_HEADER_CRC_OFFSET 104 + +// ** 78 Message Key Format ** // +#define MSG_KEY_LENGTH_LEN 88 + +// ** 79 Basic Header 2 Format ** // +#define PDUH1_LEN 48 +#define PDUH1_TYPE_LEN 1 +#define PDUH1_TYPE_OFFSET 0 +#define PDUH1_LENGTH_LEN 8 +#define PDUH1_LENGTH_OFFSET 1 +#define PDUH1_SRC_ADDR_LEN 10 +#define PDUH1_SRC_ADDR_OFFSET 9 +#define PDUH1_DST_ADDR_LEN 10 +#define PDUH1_DST_ADDR_OFFSET 19 +#define PDUH1_SLICEH_TAGE_LEN 1 +#define PDUH1_SLICEH_TAGE_OFFSET 29 +#define PDUH1_SLICET_TAGE_LEN 1 +#define PDUH1_SLICET_TAGE_OFFSET 30 +#define PDUH1_RESV_LEN 1 +#define PDUH1_RESV_OFFSET 31 +#define PDUH1_HEADER_CRC_LEN 8 +#define PDUH1_HEADER_CRC_OFFSET 32 + +// ** 74 Assembling Header Format ** // +#define UDUH_LEN 64 +#define UDUH_PRI_LEN 3 +#define UDUH_PRI_OFFSET 0 +#define UDUH_RESERV_LEN 1 +#define UDUH_RESERV_OFFSET 3 +#define UDUH_MSG_TYPE_LEN 4 +#define UDUH_MSG_TYPE_OFFSET 4 +#define UDUH_LENGTH_LEN 16 +#define UDUH_LENGTH_OFFSET 8 +#define UDUH_SRC_ADDR_LEN 10 +#define UDUH_SRC_ADDR_OFFSET 24 +#define UDUH_DST_ADDR_LEN 10 +#define UDUH_DST_ADDR_OFFSET 34 +#define UDUH_UDU_SEQ_NUM_LEN 10 +#define UDUH_UDU_SEQ_NUM_OFFSET 44 +#define UDUH_RETRANS_NUM_LEN 2 +#define UDUH_RETRANS_NUM_OFFSET 54 +#define UDUH_NUM_SLICE_LEN 4 +#define UDUH_NUM_SLICE_OFFSET 56 +#define UDUH_SLICE_ID_LEN 4 +#define UDUH_SLICE_ID_OFFSET 60 + +// ** 88 Benchmark Message ** // +#define BM_MSG_LEN 232 // bit +#define BM_MSG_TYPE_LEN 3 +#define BM_MSG_TYPE_OFFSET 0 +#define BM_MSG_SRC_ADDR_LEN 10 +#define BM_MSG_SRC_ADDR_OFFSET 3 +#define BM_MSG_NETMG_ADDR_LEN 10 +#define BM_MSG_NETMG_ADDR_OFFSET 13 +#define BM_MSG_TUNIT_NUM_LEN 17 +#define BM_MSG_TUNIT_NUM_OFFSET 23 +#define BM_MSG_TFRAME_NUM_LEN 4 +#define BM_MSG_TFRAME_NUM_OFFSET 40 +#define BM_MSG_TSLOT_NUM_LEN 6 +#define BM_MSG_TSLOT_NUM_OFFSET 44 +#define BM_MSG_LAG_TIME_TAG_LEN 6 +#define BM_MSG_LAG_TIME_TAG_OFFSET 50 +#define BM_MSG_LONGITUDE_LEN 21 +#define BM_MSG_LONGITUDE_OFFSET 56 +#define BM_MSG_LATITUDE_LEN 20 +#define BM_MSG_LATITUDE_OFFSET 77 +#define BM_MSG_HEIGHT_LEN 15 +#define BM_MSG_HEIGHT_OFFSET 97 +#define BM_MSG_EAST_SPEED_LEN 8 +#define BM_MSG_EAST_SPEED_OFFSET 112 +#define BM_MSG_NORTH_SPEED_LEN 8 +#define BM_MSG_NORTH_SPEED_OFFSET 120 +#define BM_MSG_UPPER_SPEED_LEN 8 +#define BM_MSG_UPPER_SPEED_OFFSET 128 +#define BM_MSG_CRC_LEN 8 +#define BM_MSG_CRC_OFFSET 136 +#define BM_MSG_KEY_LEN 88 +#define BM_MSG_KEY_OFFSET 144 + +// ** 82 Net Scan Message - INI ** // +#define NS_MSG_LEN 72 +#define NS_MSG_INI_SER_TAG_LEN 2 +#define NS_MSG_INI_SER_TAG_OFFSET 0 +#define NS_MSG_INI_WTAG_LEN 2 +#define NS_MSG_INI_WTAG_OFFSET 2 +#define NS_MSG_INI_MTAG_LEN 5 +#define NS_MSG_INI_MTAG_OFFSET 4 +#define NS_MSG_INI_STAG_LEN 3 +#define NS_MSG_INI_STAG_OFFSET 9 +#define NS_MSG_INI_LEN_LEN 3 +#define NS_MSG_INI_LEN_OFFSET 12 +#define NS_MSG_INI_TYPE_LEN 1 +#define NS_MSG_INI_TYPE_OFFSET 15 +#define NS_MSG_INI_SRC_ADDR_LEN 10 +#define NS_MSG_INI_SRC_ADDR_OFFSET 16 +#define NS_MSG_INI_DEST_ADDR_LEN 10 +#define NS_MSG_INI_DEST_ADDR_OFFSET 26 +#define NS_MSG_INI_NET_STAGE_LEN 4 +#define NS_MSG_INI_NET_STAGE_OFFSET 36 +#define NS_MSG_INI_SCAN_TIME_LEN 32 +#define NS_MSG_INI_SCAN_TIME_OFFSET 40 + +// ** 83 Net Scan Message - Continue 1 ** // +#define NS_MSG_CONT_1_RESV_LEN 2 +#define NS_MSG_CONT_1_RESV_OFFSET 0 +#define NS_MSG_CONT_1_WTAG_LEN 2 +#define NS_MSG_CONT_1_WTAG_OFFSET 2 +#define NS_MSG_CONT_1_CONTID_LEN 4 +#define NS_MSG_CONT_1_CONTID_OFFSET 4 +#define NS_MSG_CONT_1_TIME_TAG_LEN 48 +#define NS_MSG_CONT_1_TIME_TAG_OFFSET 8 +#define NS_MSG_CONT_1_EAST_SPEED_LEN 16 +#define NS_MSG_CONT_1_EAST_SPEED_OFFSET 56 + +// ** 84 Net Scan Message - Continue 2 ** // +#define NS_MSG_CONT_2_RESV_1_LEN 2 +#define NS_MSG_CONT_2_RESV_1_OFFSET 0 +#define NS_MSG_CONT_2_WTAG_LEN 2 +#define NS_MSG_CONT_2_WTAG_OFFSET 2 +#define NS_MSG_CONT_2_CONTID_LEN 4 +#define NS_MSG_CONT_2_CONTID_OFFSET 4 +#define NS_MSG_CONT_2_NORTH_SPEED_LEN 16 +#define NS_MSG_CONT_2_NORTH_SPEED_OFFSET 8 +#define NS_MSG_CONT_2_UPPER_SPEED_LEN 16 +#define NS_MSG_CONT_2_UPPER_SPEED_OFFSET 24 +#define NS_MSG_CONT_2_HEIGHT_LEN 24 +#define NS_MSG_CONT_2_HEIGHT_OFFSET 40 +#define NS_MSG_CONT_2_RESV_2_LEN 8 +#define NS_MSG_CONT_2_RESV_2_OFFSET 64 + +// ** 85 Net Scan Message - Continue 3 ** // +#define NS_MSG_CONT_3_RESV_LEN 2 +#define NS_MSG_CONT_3_RESV_OFFSET 0 +#define NS_MSG_CONT_3_WTAG_LEN 2 +#define NS_MSG_CONT_3_WTAG_OFFSET 2 +#define NS_MSG_CONT_3_CONTID_LEN 4 +#define NS_MSG_CONT_3_CONTID_OFFSET 4 +#define NS_MSG_CONT_3_LONGITUDE_LEN 32 +#define NS_MSG_CONT_3_LONGITUDE_OFFSET 8 +#define NS_MSG_CONT_3_LATITUDE_LEN 32 +#define NS_MSG_CONT_3_LATITUDE_OFFSET 40 + +// ** 86 Net Scan Message - Continue 4 ** // +#define NS_MSG_CONT_4_RESV_LEN 2 +#define NS_MSG_CONT_4_RESV_OFFSET 0 +#define NS_MSG_CONT_4_WTAG_LEN 2 +#define NS_MSG_CONT_4_WTAG_OFFSET 2 +#define NS_MSG_CONT_4_CONTID_LEN 4 +#define NS_MSG_CONT_4_CONTID_OFFSET 4 +#define NS_MSG_CONT_4_CRC_LEN 16 +#define NS_MSG_CONT_4_CRC_OFFSET 8 +#define NS_MSG_CONT_4_KEY_LEN 48 +#define NS_MSG_CONT_4_KEY_OFFSET 24 + +// ** 87 Net Scan Message - Continue 5 ** // +#define NS_MSG_CONT_5_RESV_1_LEN 2 +#define NS_MSG_CONT_5_RESV_1_OFFSET 0 +#define NS_MSG_CONT_5_WTAG_LEN 2 +#define NS_MSG_CONT_5_WTAG_OFFSET 2 +#define NS_MSG_CONT_5_CONTID_LEN 4 +#define NS_MSG_CONT_5_CONTID_OFFSET 4 +#define NS_MSG_CONT_5_KEY_LEN 40 +#define NS_MSG_CONT_5_KEY_OFFSET 8 +#define NS_MSG_CONT_5_RESV_2_LEN 24 +#define NS_MSG_CONT_5_RESV_2_OFFSET 48 + +#define MGMT_MSG_LEN 72 +// ** 89 Tracking Message INI ** // +#define TK_MSG_INI_SER_TAG_LEN 2 +#define TK_MSG_INI_SER_TAG_OFFSET 0 +#define TK_MSG_INI_WTAG_LEN 2 +#define TK_MSG_INI_WTAG_OFFSET 2 +#define TK_MSG_INI_TAG_LEN 5 +#define TK_MSG_INI_TAG_OFFSET 4 +#define TK_MSG_INI_STAG_LEN 3 +#define TK_MSG_INI_STAG_OFFSET 9 +#define TK_MSG_INI_LEN 3 +#define TK_MSG_INI_OFFSET 12 +#define TK_MSG_INI_TK_TAG_LEN 4 +#define TK_MSG_INI_TK_TAG_OFFSET 15 +#define TK_MSG_INI_TQLT_LEN 4 +#define TK_MSG_INI_TQLT_OFFSET 19 +#define TK_MSG_INI_TBASE_ID_INDICATE_LEN 1 +#define TK_MSG_INI_TBASE_ID_INDICATE_OFFSET 23 +#define TK_MSG_INI_CSCALE_NUM_LEN 4 +#define TK_MSG_INI_CSCALE_NUM_OFFSET 24 +#define TK_MSG_INI_MEMBER_NUM_LEN 4 +#define TK_MSG_INI_MEMBER_NUM_OFFSET 28 +#define TK_MSG_INI_MUTE_TAG_LEN 1 +#define TK_MSG_INI_MUTE_TAG_OFFSET 32 +#define TK_MSG_INI_NET_STATE_LEN 4 +#define TK_MSG_INI_NET_STATE_OFFSET 33 +#define TK_MSG_INI_RESV_LEN 35 +#define TK_MSG_INI_RESV_OFFSET 37 + +// ** 90 Tracking Message Extend ** // +#define TK_MSG_EXTEND_RESV_1_LEN 2 +#define TK_MSG_EXTEND_RESV_1_OFFSET 0 +#define TK_MSG_EXTEND_WTAG_LEN 2 +#define TK_MSG_EXTEND_WTAG_OFFSET 2 +#define TK_MSG_EXTEND_TIME_TAG_LEN 48 +#define TK_MSG_EXTEND_TIME_TAG_OFFSET 4 +#define TK_MSG_EXTEND_EAST_SPEED_LEN 16 +#define TK_MSG_EXTEND_EAST_SPEED_OFFSET 52 +#define TK_MSG_EXTEND_RESV_2_LEN 4 +#define TK_MSG_EXTEND_RESV_2_OFFSET 68 + +// ** 91 Tracking Message Continue 1 ** // +#define TK_MSG_CONT_1_RESV_1_LEN 2 +#define TK_MSG_CONT_1_RESV_1_OFFSET 0 +#define TK_MSG_CONT_1_WTAG_LEN 2 +#define TK_MSG_CONT_1_WTAG_OFFSET 2 +#define TK_MSG_CONT_1_CONTID_LEN 4 +#define TK_MSG_CONT_1_CONTID_OFFSET 4 +#define TK_MSG_CONT_1_NORTH_SPEED_LEN 16 +#define TK_MSG_CONT_1_NORTH_SPEED_OFFSET 8 +#define TK_MSG_CONT_1_UPPER_SPEED_LEN 16 +#define TK_MSG_CONT_1_UPPER_SPEED_OFFSET 24 +#define TK_MSG_CONT_1_HEIGHT_LEN 24 +#define TK_MSG_CONT_1_HEIGHT_OFFSET 40 +#define TK_MSG_CONT_1_RESV_2_LEN 8 +#define TK_MSG_CONT_1_RESV_2_OFFSET 64 + +// ** 92 Tracking Message Continue 2 ** // +#define TK_MSG_CONT_2_RESV_1_LEN 2 +#define TK_MSG_CONT_2_RESV_1_OFFSET 0 +#define TK_MSG_CONT_2_WTAG_LEN 2 +#define TK_MSG_CONT_2_WTAG_OFFSET 2 +#define TK_MSG_CONT_2_CONTID_LEN 4 +#define TK_MSG_CONT_2_CONTID_OFFSET 4 +#define TK_MSG_CONT_2_LONGITUDE_LEN 32 +#define TK_MSG_CONT_2_LONGITUDE_OFFSET 8 +#define TK_MSG_CONT_2_LATITUDE_LEN 32 +#define TK_MSG_CONT_2_LATITUDE_OFFSET 40 + +// ** 93 Tracking Message Continue 3 ** // +#define TK_MSG_CONT_3_RESV_1_LEN 2 +#define TK_MSG_CONT_3_RESV_1_OFFSET 0 +#define TK_MSG_CONT_3_WTAG_LEN 2 +#define TK_MSG_CONT_3_WTAG_OFFSET 2 +#define TK_MSG_CONT_3_CONTID_LEN 4 +#define TK_MSG_CONT_3_CONTID_OFFSET 4 +#define TK_MSG_CONT_3_MEMBER_ADDR_LEN 10 +#define TK_MSG_CONT_3_MEMBER_ADDR_OFFSET 8 +#define TK_MSG_CONT_3_RESV_2_LEN 6 +#define TK_MSG_CONT_3_RESV_2_OFFSET 18 +#define TK_MSG_CONT_3_EAST_ACC_LEN 16 +#define TK_MSG_CONT_3_EAST_ACC_OFFSET 24 +#define TK_MSG_CONT_3_NORTH_ACC_LEN 16 +#define TK_MSG_CONT_3_NORTH_ACC_OFFSET 40 +#define TK_MSG_CONT_3_UPPER_ACC_LEN 16 +#define TK_MSG_CONT_3_UPPER_ACC_OFFSET 56 + + +// ** 94 Time Announcements Initial ** // +#define TA_MSG_SER_TAG_LEN 2 +#define TA_MSG_SER_TAG_OFFSET 0 +#define TA_MSG_WTAG_LEN 2 +#define TA_MSG_WTAG_OFFSET 2 +#define TA_MSG_MSG_TAG_LEN 5 +#define TA_MSG_MSG_TAG_OFFSET 4 +#define TA_MSG_MSG_STAG_LEN 3 +#define TA_MSG_MSG_STAG_OFFSET 9 +#define TA_MSG_MSG_LEN 3 +#define TA_MSG_MSG_OFFSET 12 +#define TA_MSG_RESV_LEN 2 +#define TA_MSG_RESV_OFFSET 14 +#define TA_MSG_SRC_ADDR_LEN 10 +#define TA_MSG_SRC_ADDR_OFFSET 16 +#define TA_MSG_CURR_TUNIT_NUM_LEN 17 +#define TA_MSG_CURR_TUNIT_NUM_OFFSET 26 +#define TA_MSG_CURR_TFRAME_NUM_LEN 4 +#define TA_MSG_CURR_TFRAME_NUM_OFFSET 43 +#define TA_MSG_HEIGHT_LEN 24 +#define TA_MSG_HEIGHT_OFFSET 46 + +// ** 95 Time Announcements Extend ** // +#define TA_MSG_EX_RESV0_LEN 2 +#define TA_MSG_EX_RESV0_OFFSET 0 +#define TA_MSG_EX_WTAG_LEN 2 +#define TA_MSG_EX_WTAG_OFFSET 2 +#define TA_MSG_EX_LONGITUDE_LEN 32 +#define TA_MSG_EX_LONGITUDE_OFFSET 4 +#define TA_MSG_EX_LATITUDE_LEN 32 +#define TA_MSG_EX_LATITUDE_OFFSET 36 +#define TA_MSG_EX_RESV1_LEN 4 +#define TA_MSG_EX_RESV1_OFFSET 68 + +// ** 96 Time Announcements Continue 1 ** // +#define TA_MSG_CONT_1_RESV0_LEN 2 +#define TA_MSG_CONT_1_RESV0_OFFSET 0 +#define TA_MSG_CONT_1_WTAG_LEN 2 +#define TA_MSG_CONT_1_WTAG_OFFSET 2 +#define TA_MSG_CONT_1_TAG_LEN 4 +#define TA_MSG_CONT_1_TAG_OFFSET 4 +#define TA_MSG_CONT_1_TIME_TAG_LEN 48 +#define TA_MSG_CONT_1_TIME_TAG_OFFSET 8 +#define TA_MSG_CONT_1_TSLOT_LEN 6 +#define TA_MSG_CONT_1_TSLOT_OFFSET 56 +#define TA_MSG_CONT_1_RESV1_LEN 10 +#define TA_MSG_CONT_1_RESV1_OFFSET 62 + + +// ** 97 Time Announcements Continue 2 ** // +#define TA_MSG_CONT_2_RESV0_LEN 2 +#define TA_MSG_CONT_2_RESV0_OFFSET 0 +#define TA_MSG_CONT_2_WTAG_LEN 2 +#define TA_MSG_CONT_2_WTAG_OFFSET 2 +#define TA_MSG_CONT_2_TAG_LEN 4 +#define TA_MSG_CONT_2_TAG_OFFSET 4 +#define TA_MSG_CONT_2_EAST_LEN 16 +#define TA_MSG_CONT_2_EAST_OFFSET 8 +#define TA_MSG_CONT_2_NORTH_LEN 16 +#define TA_MSG_CONT_2_NORTH_OFFSET 24 +#define TA_MSG_CONT_2_UPPER_LEN 16 +#define TA_MSG_CONT_2_UPPER_OFFSET 40 +#define TA_MSG_CONT_2_RESV1_LEN 16 +#define TA_MSG_CONT_2_RESV1_OFFSET 56 + +// ** 98 Mission Network Adjustment Notification Message Initial Word ** // +#define MADJ_MSG_INI_SER_TAG_LEN 2 +#define MADJ_MSG_INI_SER_TAG_OFFSET 0 +#define MADJ_MSG_INI_WTAG_LEN 2 +#define MADJ_MSG_INI_WTAG_OFFSET 2 +#define MADJ_MSG_INI_MSG_TAG_LEN 5 +#define MADJ_MSG_INI_MSG_TAG_OFFSET 4 +#define MADJ_MSG_INI_MSG_STAG_LEN 3 +#define MADJ_MSG_INI_MSG_STAG_OFFSET 9 +#define MADJ_MSG_INI_MSG_LEN 3 +#define MADJ_MSG_INI_MSG_OFFSET 12 +#define MADJ_MSG_INI_CTRL_CODE_LEN 4 +#define MADJ_MSG_INI_CTRL_CODE_OFFSET 15 +#define MADJ_MSG_INI_TCHIP_LEN 8 +#define MADJ_MSG_INI_TCHIP_OFFSET 19 +#define MADJ_MSG_INI_ADJ_TUNIT_NUM_LEN 17 +#define MADJ_MSG_INI_ADJ_TUNIT_NUM_OFFSET 27 +#define MADJ_MSG_INI_ADJ_TFRAME_NUM_LEN 4 +#define MADJ_MSG_INI_ADJ_TFRAME_NUM_OFFSET 44 +#define MADJ_MSG_INI_ADJ_ANNED_NODE_ADDR_LEN 10 +#define MADJ_MSG_INI_ADJ_ANNED_NODE_ADDR_OFFSET 48 +#define MADJ_MSG_INI_ADJ_RESV_LEN 14 +#define MADJ_MSG_INI_ADJ_RESV_OFFSET 58 + +// ** 99 Mission Network Adjustment Notification Message Extend Word ** // +#define MADJ_MSG_EX_RESV_1_LEN 2 +#define MADJ_MSG_EX_RESV_1_OFFSET 0 +#define MADJ_MSG_EX_WTAG_LEN 2 +#define MADJ_MSG_EX_WTAG_OFFSET 2 +#define MADJ_MSG_EX_PNODE_ADDR_1_LEN 10 +#define MADJ_MSG_EX_PNODE_ADDR_1_OFFSET 4 +#define MADJ_MSG_EX_PNODE_ADDR_2_LEN 10 +#define MADJ_MSG_EX_PNODE_ADDR_2_OFFSET 14 +#define MADJ_MSG_EX_PNODE_ADDR_3_LEN 10 +#define MADJ_MSG_EX_PNODE_ADDR_3_OFFSET 24 +#define MADJ_MSG_EX_PNODE_ADDR_4_LEN 10 +#define MADJ_MSG_EX_PNODE_ADDR_4_OFFSET 34 +#define MADJ_MSG_EX_PNODE_ADDR_5_LEN 10 +#define MADJ_MSG_EX_PNODE_ADDR_5_OFFSET 44 +#define MADJ_MSG_EX_PNODE_ADDR_6_LEN 10 +#define MADJ_MSG_EX_PNODE_ADDR_6_OFFSET 54 +#define MADJ_MSG_EX_RESV_2_LEN 8 +#define MADJ_MSG_EX_RESV_2_OFFSET 64 + +// ** 100 RTT Inquiry Initial Word ** // +#define RTT_MSG_LEN 72 +#define RTT_REQ_SER_TAG_LEN 2 +#define RTT_REQ_SER_TAG_OFFSET 0 +#define RTT_REQ_WTAG_LEN 2 +#define RTT_REQ_WTAG_OFFSET 2 +#define RTT_REQ_MSG_TAG_LEN 5 +#define RTT_REQ_MSG_TAG_OFFSET 4 +#define RTT_REQ_MSG_STAG_LEN 3 +#define RTT_REQ_MSG_STAG_OFFSET 9 +#define RTT_REQ_MSG_LEN 3 +#define RTT_REQ_MSG_OFFSET 12 +#define RTT_REQ_SRC_ADDR_LEN 10 +#define RTT_REQ_SRC_ADDR_OFFSET 15 +#define RTT_REQ_DST_ADDR_LEN 10 +#define RTT_REQ_DST_ADDR_OFFSET 25 +#define RTT_REQ_RESV_LEN 37 +#define RTT_REQ_RESV_OFFSET 35 + +// ** RTT Inquiry Extend Word ** // +#define RTT_REQ_EX_RESV0_LEN 2 +#define RTT_REQ_EX_RESV0_OFFSET 0 +#define RTT_REQ_EX_WTAG_LEN 2 +#define RTT_REQ_EX_WTAG_OFFSET 2 +#define RTT_REQ_EX_TTAGL_LEN 32 +#define RTT_REQ_EX_TTAGL_OFFSET 4 +#define RTT_REQ_EX_TTAGH_LEN 32 +#define RTT_REQ_EX_TTAGH_OFFSET 36 +#define RTT_REQ_EX_RESV1_LEN 4 +#define RTT_REQ_EX_RESV1_OFFSET 68 + +// ** RTT Inquiry Continue Word ** // +#define RTT_REQ_CONT_RESV0_LEN 2 +#define RTT_REQ_CONT_RESV0_OFFSET 0 +#define RTT_REQ_CONT_WTAG_LEN 2 +#define RTT_REQ_CONT_WTAG_OFFSET 2 +#define RTT_REQ_CONT_TAG_LEN 4 +#define RTT_REQ_CONT_TAG_OFFSET 4 +#define RTT_REQ_CONT_DOP_LEN 24 +#define RTT_REQ_CONT_DOP_OFFSET 8 +#define RTT_REQ_CONT_RESV1_LEN 40 +#define RTT_REQ_CONT_RESV1_OFFSET 32 + + +// ** 101 RTT Response Initial Word ** // +#define RTT_RSP_SER_TAG_LEN 2 +#define RTT_RSP_SER_TAG_OFFSET 0 +#define RTT_RSP_WTAG_LEN 2 +#define RTT_RSP_WTAG_OFFSET 2 +#define RTT_RSP_MSG_TAG_LEN 5 +#define RTT_RSP_MSG_TAG_OFFSET 4 +#define RTT_RSP_MSG_STAG_LEN 3 +#define RTT_RSP_MSG_STAG_OFFSET 9 +#define RTT_RSP_MSG_LEN 3 +#define RTT_RSP_MSG_OFFSET 12 +#define RTT_RSP_SRC_ADDR_LEN 10 +#define RTT_RSP_SRC_ADDR_OFFSET 15 +#define RTT_RSP_DST_ADDR_LEN 10 +#define RTT_RSP_DST_ADDR_OFFSET 25 +#define RTT_RSP_ARV_TIME_LEN 25 +#define RTT_RSP_ARV_TIME_OFFSET 35 +#define RTT_RSP_RESV_LEN 12 +#define RTT_RSP_RESV_OFFSET 60 + +// ** RTT Response Extend Word ** // +#define RTT_RSP_EX_RESV0_LEN 2 +#define RTT_RSP_EX_RESV0_OFFSET 0 +#define RTT_RSP_EX_WTAG_LEN 2 +#define RTT_RSP_EX_WTAG_OFFSET 2 +#define RTT_RSP_EX_TTAGL_LEN 32 +#define RTT_RSP_EX_TTAGL_OFFSET 4 +#define RTT_RSP_EX_TTAGH_LEN 32 +#define RTT_RSP_EX_TTAGH_OFFSET 36 +#define RTT_RSP_EX_RESV1_LEN 4 +#define RTT_RSP_EX_RESV1_OFFSET 68 + +// ** RTT Response Continue Word ** // +#define RTT_RSP_CONT_RESV0_LEN 2 +#define RTT_RSP_CONT_RESV0_OFFSET 0 +#define RTT_RSP_CONT_WTAG_LEN 2 +#define RTT_RSP_CONT_WTAG_OFFSET 2 +#define RTT_RSP_CONT_TAG_LEN 4 +#define RTT_RSP_CONT_TAG_OFFSET 4 +#define RTT_RSP_CONT_DOP_LEN 24 +#define RTT_RSP_CONT_DOP_OFFSET 8 +#define RTT_RSP_CONT_RESV1_LEN 40 +#define RTT_RSP_CONT_RESV1_OFFSET 32 + +// ** 102 Network Exit Initial Word ** // +#define NQT_MSG_SER_TAG_LEN 2 +#define NQT_MSG_SER_TAG_OFFSET 0 +#define NQT_MSG_WTAG_LEN 2 +#define NQT_MSG_WTAG_OFFSET 2 +#define NQT_MSG_MSG_TAG_LEN 5 +#define NQT_MSG_MSG_TAG_OFFSET 4 +#define NQT_MSG_MSG_STAG_LEN 3 +#define NQT_MSG_MSG_STAG_OFFSET 9 +#define NQT_MSG_MSG_LEN 3 +#define NQT_MSG_MSG_OFFSET 12 +#define NQT_MSG_CTRL_MUTE_LEN 7 +#define NQT_MSG_CTRL_MUTE_OFFSET 15 +#define NQT_MSG_OBJ_LEN 10 +#define NQT_MSG_OBJ_OFFSET 22 +#define NQT_MSG_RESV_LEN 40 +#define NQT_MSG_RESV_OFFSET 32 + +// ** 103 Cluster Merge Message Initial Word ** // +#define CMG_MSG_SER_TAG_LEN 2 +#define CMG_MSG_SER_TAG_OFFSET 0 +#define CMG_MSG_WTAG_LEN 2 +#define CMG_MSG_WTAG_OFFSET 2 +#define CMG_MSG_MSG_TAG_LEN 5 +#define CMG_MSG_MSG_TAG_OFFSET 4 +#define CMG_MSG_MSG_STAG_LEN 3 +#define CMG_MSG_MSG_STAG_OFFSET 9 +#define CMG_MSG_MSG_LEN 3 +#define CMG_MSG_MSG_OFFSET 12 +#define CMG_MSG_CTRL_MUTE_LEN 7 +#define CMG_MSG_CTRL_MUTE_OFFSET 15 +#define CMG_MSG_NEW_CLR_ADDR_LEN 10 +#define CMG_MSG_NEW_CLR_ADDR_OFFSET 22 +#define CMG_MSG_RESV_LEN 40 +#define CMG_MSG_RESV_OFFSET 32 + +// ** 104 Backup Cluster Head Upgrade Message Initial Word ** // +#define BCU_MSG_SER_TAG_LEN 2 +#define BCU_MSG_SER_TAG_OFFSET 0 +#define BCU_MSG_WTAG_LEN 2 +#define BCU_MSG_WTAG_OFFSET 2 +#define BCU_MSG_MSG_TAG_LEN 5 +#define BCU_MSG_MSG_TAG_OFFSET 4 +#define BCU_MSG_MSG_STAG_LEN 3 +#define BCU_MSG_MSG_STAG_OFFSET 9 +#define BCU_MSG_MSG_LEN 3 +#define BCU_MSG_MSG_OFFSET 12 +#define BCU_MSG_CTRL_MUTE_LEN 7 +#define BCU_MSG_CTRL_MUTE_OFFSET 15 +#define BCU_MSG_NEW_CLR_ADDR_LEN 10 +#define BCU_MSG_NEW_CLR_ADDR_OFFSET 22 +#define BCU_MSG_BEGIN_TUNIT_NUM_LEN 17 +#define BCU_MSG_BEGIN_TUNIT_NUM_OFFSET 32 +#define BCU_MSG_BEGIN_TFRANE_NUM_LEN 4 +#define BCU_MSG_BEGIN_TFRANE_NUM_OFFSET 49 +#define BCU_MSG_RESV_LEN 19 +#define BCU_MSG_RESV_OFFSET 53 + +typedef enum{ + L2_MSG_NONE = 0, + L2_MSG_BM = 1, + L2_MSG_SCAN_INIT = 2, + L2_MSG_SCAN_CONT_1 = 3, + L2_MSG_SCAN_CONT_2 = 4, + L2_MSG_SCAN_CONT_3 = 5, + L2_MSG_SCAN_CONT_4 = 6, + L2_MSG_SCAN_CONT_5 = 7, + L2_MSG_TK_INIT = 8, + L2_MSG_TK_EXTD = 9, + L2_MSG_TK_CONT_1 = 10, + L2_MSG_TK_CONT_2 = 11, + L2_MSG_TK_CONT_3 = 12, + L2_MSG_TA_INIT = 13, + L2_MSG_TA_EXTD = 14, + L2_MSG_TA_CONT_1 = 15, + L2_MSG_TA_CONT_2 = 16, + L2_MSG_MADJ_INIT = 17, + L2_MSG_MADJ_EXTD = 18, + L2_MSG_RTT_REQ_INIT = 19, + L2_MSG_RTT_REQ_EXTD = 20, + L2_MSG_RTT_REQ_CONT = 21, + L2_MSG_RTT_RSP_INIT = 22, + L2_MSG_RTT_RSP_EXTD = 23, + L2_MSG_RTT_RSP_CONT = 24, + L2_MSG_NQT_INIT = 25, + L2_MSG_CMG_INIT = 26, + L2_MSG_BCU_INIT = 27, + L2_MSG_LINK_INIT = 28, + L2_MSG_LINK_CONT_1 = 29 +}L2_MSG_TYPE; + +typedef enum{ + L2_PDU_HEADER_NONE = 0, + L2_PDU_HEADER_0 = 1, + L2_PDU_HEADER_1 = 2 +}L2_PDU_HEADER_TYPE; + +// Intra-cluster frames +#define INTRA_BM_FRAME_LENGTH_MAX (232/8) // byte +#define INTRA_W2ACQ_FRAME_LENGTH_MAX (2040/8) // byte +#define INTRA_MGMT_FRAME_LENGTH_MAX (2040/8) // byte +#define INTRA_TA_FRAME_LENGTH_MAX (2040/8) // byte +#define INTRA_SVC_FRAME_LENGTH_MAX (2040/8) // byte +#define INTRA_RTT_FRAME_LENGTH_MAX (2040/8) // byte + +// Inter-cluster frames +#define INTER_BM_FRAME_LENGTH_MAX (312/8) // byte +#define INTER_W2ACQ_FRAME_LENGTH_MAX (712/8) // byte +#define W2ACQ_FRAME_CRC_DLEN ((NS_MSG_LEN*4)/8) //byte +#define W2ACQ_FRAME_CRC_POS ((NS_MSG_LEN*4 + NS_MSG_CONT_4_CRC_OFFSET)/8)// byte + +#define INTER_MGMT_FRAME_LENGTH_MAX (2152/8) // byte +#define INTER_TA_FRAME_LENGTH_MAX (2152/8) // byte +#define INTER_SVC_FRAME_LENGTH_MAX (2152/8) // byte +#define INTER_RTT_FRAME_LENGTH_MAX (2152/8) // byte + +extern L2_MSG_TYPE intraBmFrameMsgs[1]; +extern L2_MSG_TYPE intraW2AcqFrameMsgs[6]; +extern L2_MSG_TYPE intraMgmtFrameMsgs[6]; +extern L2_MSG_TYPE taFrameMsgs[4]; +extern L2_MSG_TYPE interSvcFrameMsgs[2]; +extern L2_MSG_TYPE rttReqFrameMsgs[3]; +extern L2_MSG_TYPE rttRspFrameMsgs[3]; +#endif //MSG_DEF_H_ diff --git a/datalink814_ge/src/linklayer/net_mgmt.c b/datalink814_ge/src/linklayer/net_mgmt.c new file mode 100644 index 0000000..d3d7713 --- /dev/null +++ b/datalink814_ge/src/linklayer/net_mgmt.c @@ -0,0 +1,991 @@ +/*****************************************************************************/ +/** + * Description: Implementations of 814 linklayer management net. + * + * Date: 2021-11-18 17:27 + * LastEditors: Fan Hao + * LastEditTime: 2022-01-16 15:52 + * Revisions: Rev 0.1 + * History: + * [2022-07-16]: New branch for DiJian. + * [2021-11-18]: Initial version. + * + * Copyright(c) 2022 Beijing Institute of Technology. + * Lab of Communication and Networking + * + ******************************************************************************/ + +/***************************** Include Files *********************************/ +#include +#include "linklayer814.h" +#include "linklayer814_types.h" +#include "msg_def.h" +#include "rtt.h" +#include "../error.h" +#include "../common.h" +#include "node_list.h" +/************************** Constant Definitions *****************************/ +#define SQUENCE_MGMT_SLOTS 0 +#define INTER_MGMT_SLOTS 2 +#define INTRA_MGMT_SLOTS 1 +#define NONE_MGMT_SLOTS -1 +#define CONN_LOST_TH 10 // 10 count of mgmt msg no response to delete +#define TIME2QUIT 80 // time to send quit message + +#define SENDRTT 0 +#define RCVDRTT 1 + +/***************** Macros (Inline Functions) Definitions *********************/ + +/**************************** Type Definitions *******************************/ +typedef enum { + MGMTPKT_NONE = 0, + MGMTPKT_INTER_MGMT = 1, + MGMTPKT_INTRA_MGMT = 2, + MGMTPKT_INTER_RTTREQ = 3, + MGMTPKT_INTER_RTTRSP = 4, + MGMTPKT_INTRA_RTTREQ = 5, + MGMTPKT_INTRA_RTTRSP = 6 +} MGMTPKT_TYPE; +/************************** Variable Definitions *****************************/ + +/************************** Function Prototypes ******************************/ +static int32_t MgmtMsg_Packing(L2_INST* instPtr, BIT_ARRAY* bitarr, L2_MSG_TYPE msgType); +static int32_t MgmtPkt_Packing(L2_INST* instPtr, MGMTPKT_TYPE pktType); +/*****************************************************************************/ +/** + * @brief Packing management message to a bit array. + * + * @param bitarr pointer to bit array buffer. + * msgType message type. + * + * @return EPARAM + * SUCCESS + * + ******************************************************************************/ +static int32_t MgmtMsg_Packing(L2_INST* instPtr, BIT_ARRAY* bitarr, L2_MSG_TYPE msgType) { + ASSERT(instPtr != NULL); + ASSERT(bitarr != NULL); + if (bitarr->num_of_bits < MGMT_MSG_LEN || msgType < L2_MSG_TK_INIT + || msgType > L2_MSG_BCU_INIT) { + return EPARAM; + } + uint64_t dataChunk = 0; + memset(bitarr->words, 0x99, (size_t) (MGMT_MSG_LEN / 8)); + switch (msgType) { + case L2_MSG_TK_INIT: + if (bitarr->num_of_bits < MGMT_MSG_LEN) { + return EPARAM; + } + // Series tag + dataChunk = 0; + FrameInsertChunk(bitarr, TK_MSG_INI_SER_TAG_OFFSET, TK_MSG_INI_SER_TAG_LEN, dataChunk); + + // word tag + dataChunk = 3; + FrameInsertChunk(bitarr, TK_MSG_INI_WTAG_OFFSET, TK_MSG_INI_WTAG_LEN, dataChunk); + + // message tag + dataChunk = 28; + FrameInsertChunk(bitarr, TK_MSG_INI_TAG_OFFSET, TK_MSG_INI_TAG_LEN, dataChunk); + + // message sub tag + dataChunk = 1; + FrameInsertChunk(bitarr, TK_MSG_INI_STAG_OFFSET, TK_MSG_INI_STAG_LEN, dataChunk); + + // message length tag + dataChunk = 4; + FrameInsertChunk(bitarr, TK_MSG_INI_OFFSET, TK_MSG_INI_LEN, dataChunk); + + // Next net stage + if (instPtr->myInfo.nodeType == HEAD_NODE) { + switch (instPtr->nextState) { + case INIT_STATE: + dataChunk = NET_INI_STAGE; + break; + case NORMAL_STATE: + dataChunk = NET_NORMAL_STAGE; + break; + case INTRA_SEEK_STATE: + dataChunk = NET_INTRA_SEEK_STAGE; + break; + case INTER_SEEK_STATE: + dataChunk = NET_INTER_SEEK_STAGE; + break; + case SEEK_STATE: + dataChunk = NET_SEEK_STAGE; + break; + default: + dataChunk = NET_ERROR_STAGE; + break; + } + FrameInsertChunk(bitarr, TK_MSG_INI_NET_STATE_OFFSET, TK_MSG_INI_NET_STATE_LEN, dataChunk); + } + break; + case L2_MSG_TK_EXTD: + if (bitarr->num_of_bits < MGMT_MSG_LEN) { + return EPARAM; + } + // Word tag + dataChunk = 1; + FrameInsertChunk(bitarr, TK_MSG_EXTEND_WTAG_OFFSET, TK_MSG_EXTEND_WTAG_LEN, dataChunk); + + // Time tag + dataChunk = 0xAAAAAAAAAAAA; + FrameInsertChunk(bitarr, TK_MSG_EXTEND_TIME_TAG_OFFSET, TK_MSG_EXTEND_TIME_TAG_LEN, dataChunk); + + // East speed + dataChunk = 0xBBBB; + FrameInsertChunk(bitarr, TK_MSG_EXTEND_EAST_SPEED_OFFSET, TK_MSG_EXTEND_EAST_SPEED_LEN, dataChunk); + break; + case L2_MSG_TK_CONT_1: + // Word tag + dataChunk = 2; + FrameInsertChunk(bitarr, TK_MSG_CONT_1_WTAG_OFFSET, TK_MSG_CONT_1_WTAG_LEN, dataChunk); + + // Continue word identification. + dataChunk = 1; + FrameInsertChunk(bitarr, TK_MSG_CONT_1_CONTID_OFFSET, TK_MSG_CONT_1_CONTID_LEN, dataChunk); + + // North speed + dataChunk = 0xCCCC; + FrameInsertChunk(bitarr, TK_MSG_CONT_1_NORTH_SPEED_OFFSET, TK_MSG_CONT_1_NORTH_SPEED_LEN, dataChunk); + + // Upper speed + dataChunk = 0xDDDD; + FrameInsertChunk(bitarr, TK_MSG_CONT_1_UPPER_SPEED_OFFSET, + TK_MSG_CONT_1_UPPER_SPEED_LEN, dataChunk); + + // Height + dataChunk = 0xEEEEEE; + FrameInsertChunk(bitarr, TK_MSG_CONT_1_HEIGHT_OFFSET, TK_MSG_CONT_1_HEIGHT_LEN, dataChunk); + break; + + case L2_MSG_TK_CONT_2: + // Word tag + dataChunk = 2; + FrameInsertChunk(bitarr, TK_MSG_CONT_2_WTAG_OFFSET, TK_MSG_CONT_2_WTAG_LEN, dataChunk); + + // Continue word identification. + dataChunk = 2; + FrameInsertChunk(bitarr, TK_MSG_CONT_2_CONTID_OFFSET, TK_MSG_CONT_2_CONTID_LEN, dataChunk); + + // Longitude + dataChunk = 0xAAAAAAAA; + FrameInsertChunk(bitarr, TK_MSG_CONT_2_LONGITUDE_OFFSET, TK_MSG_CONT_2_LONGITUDE_LEN, dataChunk); + + // Latitude + dataChunk = 0xBBBBBBBB; + FrameInsertChunk(bitarr, TK_MSG_CONT_2_LATITUDE_OFFSET, TK_MSG_CONT_2_LATITUDE_LEN, dataChunk); + break; + case L2_MSG_TK_CONT_3: + + // Word tag + dataChunk = 2; + FrameInsertChunk(bitarr, TK_MSG_CONT_3_WTAG_OFFSET, TK_MSG_CONT_3_WTAG_LEN, dataChunk); + + // Continue word identification. + dataChunk = 3; + FrameInsertChunk(bitarr, TK_MSG_CONT_3_CONTID_OFFSET, TK_MSG_CONT_3_CONTID_LEN, dataChunk); + + // source node id + dataChunk = (instPtr->myInfo.nodeId & 0x1F) + | (((uint16_t) (instPtr->myInfo.clustId & 0x1F)) << 5); + FrameInsertChunk(bitarr, TK_MSG_CONT_3_MEMBER_ADDR_OFFSET, TK_MSG_CONT_3_MEMBER_ADDR_LEN, dataChunk); + + // East speed + dataChunk = 0xBBBB; + FrameInsertChunk(bitarr, TK_MSG_CONT_3_EAST_ACC_OFFSET, TK_MSG_CONT_3_EAST_ACC_LEN, dataChunk); + + // North speed + dataChunk = 0xCCCC; + FrameInsertChunk(bitarr, TK_MSG_CONT_3_NORTH_ACC_OFFSET, TK_MSG_CONT_3_NORTH_ACC_LEN, dataChunk); + + // Upper speed + dataChunk = 0xDDDD; + FrameInsertChunk(bitarr, TK_MSG_CONT_3_UPPER_ACC_OFFSET, TK_MSG_CONT_3_UPPER_ACC_LEN, dataChunk); + + break; + + case L2_MSG_TA_INIT: + + // Word tag + dataChunk = 3; + FrameInsertChunk(bitarr, TA_MSG_WTAG_OFFSET, TA_MSG_WTAG_LEN, dataChunk); + + // Msg tag + dataChunk = 29; + FrameInsertChunk(bitarr, TA_MSG_MSG_TAG_OFFSET, TA_MSG_MSG_TAG_LEN, dataChunk); + + // Sub msg tag + dataChunk = 0; + FrameInsertChunk(bitarr, TA_MSG_MSG_STAG_OFFSET, TA_MSG_MSG_STAG_LEN, dataChunk); + + // Source node id + dataChunk = (instPtr->myInfo.nodeId & 0x1F) + | (((uint16_t) (instPtr->myInfo.clustId & 0x1F)) << 5); + FrameInsertChunk(bitarr, TA_MSG_SRC_ADDR_OFFSET, TA_MSG_SRC_ADDR_LEN, dataChunk); + + // Height + dataChunk = 0xEEEEEE; + FrameInsertChunk(bitarr, TA_MSG_HEIGHT_OFFSET, TA_MSG_HEIGHT_LEN, dataChunk); + + break; + case L2_MSG_TA_EXTD: + + // Longitude + dataChunk = 0xAAAAAAAA; + FrameInsertChunk(bitarr, TA_MSG_EX_LONGITUDE_OFFSET, TA_MSG_EX_LONGITUDE_LEN, dataChunk); + + // Latitude + dataChunk = 0xBBBBBBBB; + FrameInsertChunk(bitarr, TA_MSG_EX_LATITUDE_OFFSET, TA_MSG_EX_LATITUDE_LEN, dataChunk); + + break; + case L2_MSG_TA_CONT_1: + + // Time tag + dataChunk = 0xCCCCCCCCCCCC; + FrameInsertChunk(bitarr, TA_MSG_CONT_1_TIME_TAG_OFFSET, TA_MSG_CONT_1_TIME_TAG_LEN, dataChunk); + + break; + case L2_MSG_TA_CONT_2: + + // East speed + dataChunk = 0xBBBB; + FrameInsertChunk(bitarr, TA_MSG_CONT_2_EAST_OFFSET, TA_MSG_CONT_2_EAST_LEN, dataChunk); + + // North speed + dataChunk = 0xCCCC; + FrameInsertChunk(bitarr, TA_MSG_CONT_2_NORTH_OFFSET, TA_MSG_CONT_2_NORTH_LEN, dataChunk); + + // Upper speed + dataChunk = 0xDDDD; + FrameInsertChunk(bitarr, TA_MSG_CONT_2_UPPER_OFFSET, TA_MSG_CONT_2_UPPER_LEN, dataChunk); + + break; + case L2_MSG_MADJ_INIT: + break; + case L2_MSG_MADJ_EXTD: + break; + case L2_MSG_RTT_REQ_INIT: + // Series tag + dataChunk = 0; + FrameInsertChunk(bitarr, RTT_REQ_SER_TAG_OFFSET, RTT_REQ_SER_TAG_LEN, dataChunk); + + // Word tag + dataChunk = 3; + FrameInsertChunk(bitarr, RTT_REQ_WTAG_OFFSET, RTT_REQ_WTAG_LEN, dataChunk); + + // message identification. + dataChunk = 29; + FrameInsertChunk(bitarr, RTT_REQ_MSG_TAG_OFFSET, RTT_REQ_MSG_TAG_LEN, dataChunk); + + // message identification. + dataChunk = 1; + FrameInsertChunk(bitarr, RTT_REQ_MSG_STAG_OFFSET, RTT_REQ_MSG_STAG_LEN, dataChunk); + + // message length. + dataChunk = 2; //request + FrameInsertChunk(bitarr, RTT_REQ_MSG_OFFSET, RTT_REQ_MSG_LEN, dataChunk); + + // source node address length. + dataChunk = (instPtr->myInfo.nodeId & 0x1F) + | (((uint16_t) (instPtr->myInfo.clustId & 0x1F)) << 5); + FrameInsertChunk(bitarr, RTT_REQ_SRC_ADDR_OFFSET, RTT_REQ_SRC_ADDR_LEN, dataChunk); + + // destination node address length. + dataChunk = (0x02) | (((uint16_t) (instPtr->myInfo.clustId & 0x1F)) << 5); + FrameInsertChunk(bitarr, RTT_REQ_DST_ADDR_OFFSET, RTT_REQ_DST_ADDR_LEN, dataChunk); + break; + + case L2_MSG_RTT_REQ_EXTD: + // Word tag + dataChunk = 1; + FrameInsertChunk(bitarr, RTT_REQ_EX_WTAG_OFFSET, RTT_REQ_EX_WTAG_LEN, dataChunk); + + // Time tag Low. + dataChunk = instPtr->mgmtNetFSM->rttData.rttTime.timeL; + FrameInsertChunk(bitarr, RTT_REQ_EX_TTAGL_OFFSET, RTT_REQ_EX_TTAGL_LEN, dataChunk); + + // Time tag High. + dataChunk = instPtr->mgmtNetFSM->rttData.rttTime.timeH; + FrameInsertChunk(bitarr, RTT_REQ_EX_TTAGH_OFFSET, RTT_REQ_EX_TTAGH_LEN, dataChunk); + break; + case L2_MSG_RTT_REQ_CONT: + // Doppler + dataChunk = instPtr->mgmtNetFSM->rttData.rttDoppler; + FrameInsertChunk(bitarr, RTT_REQ_CONT_DOP_OFFSET, RTT_REQ_CONT_DOP_LEN, dataChunk); + + //////////////////////////////////////////////////////////////////////////////////////////// + break; + case L2_MSG_RTT_RSP_INIT: + // Series tag + dataChunk = 0; + FrameInsertChunk(bitarr, RTT_RSP_SER_TAG_OFFSET, RTT_RSP_SER_TAG_LEN, dataChunk); + + // Word tag + dataChunk = 3; + FrameInsertChunk(bitarr, RTT_RSP_WTAG_OFFSET, RTT_RSP_WTAG_LEN, dataChunk); + + // message identification. + dataChunk = 29; + FrameInsertChunk(bitarr, RTT_RSP_MSG_TAG_OFFSET, + RTT_RSP_MSG_TAG_LEN, dataChunk); + + // message identification. + dataChunk = 2; // response + FrameInsertChunk(bitarr, RTT_RSP_MSG_STAG_OFFSET, RTT_RSP_MSG_STAG_LEN, dataChunk); + + // message length. + dataChunk = 2; + FrameInsertChunk(bitarr, RTT_RSP_MSG_OFFSET, RTT_RSP_MSG_LEN, dataChunk); + + // source node address length. + dataChunk = (instPtr->myInfo.nodeId & 0x1F) + | (((uint16_t) (instPtr->myInfo.clustId & 0x1F)) << 5); + FrameInsertChunk(bitarr, RTT_RSP_SRC_ADDR_OFFSET, RTT_RSP_SRC_ADDR_LEN, dataChunk); + + // destination node address length. + dataChunk = (0x01) | (((uint16_t) (instPtr->myInfo.clustId & 0x1F)) << 5); + FrameInsertChunk(bitarr, RTT_RSP_DST_ADDR_OFFSET, RTT_RSP_DST_ADDR_LEN, dataChunk); + break; + case L2_MSG_RTT_RSP_EXTD: + + // Word tag + dataChunk = 1; + FrameInsertChunk(bitarr, RTT_RSP_EX_WTAG_OFFSET, RTT_RSP_EX_WTAG_LEN, dataChunk); + + // Time tag Low. + dataChunk = instPtr->mgmtNetFSM->rttData.rttTime.timeL; + FrameInsertChunk(bitarr, RTT_RSP_EX_TTAGL_OFFSET, RTT_RSP_EX_TTAGL_LEN, dataChunk); + + // Time tag High. + dataChunk = instPtr->mgmtNetFSM->rttData.rttTime.timeH; + FrameInsertChunk(bitarr, RTT_RSP_EX_TTAGH_OFFSET, RTT_RSP_EX_TTAGH_LEN, dataChunk); + break; + case L2_MSG_RTT_RSP_CONT: + // Doppler + dataChunk = instPtr->mgmtNetFSM->rttData.rttDoppler; + FrameInsertChunk(bitarr, RTT_RSP_CONT_DOP_OFFSET, RTT_RSP_CONT_DOP_LEN, dataChunk); + break; + case L2_MSG_NQT_INIT: +// if (priorInfo.myType == MEMBER_NODE && ( L2_GetCurrentFrameNo() == ( myInfo->netScanTime + TIME2QUIT ) )) { +// // word tag +// dataChunk = 3; +// FrameInsertChunk(bitarr, NQT_MSG_WTAG_OFFSET, +// NQT_MSG_WTAG_LEN, dataChunk); +// +// // msg tag +// dataChunk = 30; +// FrameInsertChunk(bitarr, NQT_MSG_MSG_TAG_OFFSET, +// NQT_MSG_MSG_TAG_LEN, dataChunk); +// +// // msg sub tag +// dataChunk = 1; +// FrameInsertChunk(bitarr, NQT_MSG_MSG_STAG_OFFSET, +// NQT_MSG_MSG_STAG_LEN, dataChunk); +// +// // msg length +// dataChunk = 0; +// FrameInsertChunk(bitarr, NQT_MSG_MSG_OFFSET, +// NQT_MSG_MSG_LEN, dataChunk); +// +// // Ctrol Word +// dataChunk = 1; +// FrameInsertChunk(bitarr, NQT_MSG_CTRL_MUTE_OFFSET, +// NQT_MSG_CTRL_MUTE_LEN, dataChunk); +// +// // Quit object +// dataChunk = (priorInfo.myId & 0x1F) +// | (((uint16_t) (priorInfo.clustId & 0x1F)) << 5); +// FrameInsertChunk(bitarr, NQT_MSG_OBJ_OFFSET, +// NQT_MSG_OBJ_LEN, dataChunk); +// L2_NODE_STATE newState = INIT_STATE; +// L2_EVENT stateEvent = { +// .event = L2_EV_MAIN_STATE_UPDATE, +// .msg = &newState +// }; +// AssertL2Event(&stateEvent); +// L2_EVENT lostCxnEvent = { +// .event = L2_EV_LOST_CXN, +// .msg = NULL +// }; +// AssertL2Event(&lostCxnEvent); +// } + break; + case L2_MSG_CMG_INIT: + break; + case L2_MSG_BCU_INIT: + break; + default: + return EPARAM; + break; + } + return SUCCESS; +} + + + +static int32_t MgmtPkt_Packing(L2_INST* instPtr, MGMTPKT_TYPE pktType) { + ASSERT(instPtr != NULL); + uint8_t* buff = instPtr->sendPktData; + uint32_t filedSize = 0; + BIT_ARRAY* mgmtPkt = bit_array_create(L2_MSG_MAX); + if (mgmtPkt == NULL) { + DBG_ERROR("Failed to allocate memory for scanMsg.\n"); + return NUM_SLOTS_NONE; + } + switch (pktType) { + case MGMTPKT_INTRA_MGMT: + for (int i = 0; i < ARRAY_SIZE(intraMgmtFrameMsgs); i++) { + if (MgmtMsg_Packing(instPtr, mgmtPkt, intraMgmtFrameMsgs[i]) == SUCCESS) { + memcpy((uint8_t*)buff + (size_t) (i * (MGMT_MSG_LEN / 8)), + mgmtPkt->words, (size_t) (MGMT_MSG_LEN / 8)); + } + else { + DBG_ERROR("Failed to packing intraMgmtFrameMsgs[%d].\n", i); + goto failed; + } + filedSize += MGMT_MSG_LEN; + if (filedSize / 8 >= INTRA_MGMT_FRAME_LENGTH_MAX) { + DBG_ERROR("Message is too long to be properly packed.\n"); + goto failed; + } + } + break; + case MGMTPKT_INTRA_RTTREQ: + for(int i = 0; i < ARRAY_SIZE(rttReqFrameMsgs); i++) { + if (MgmtMsg_Packing(instPtr, mgmtPkt, rttReqFrameMsgs[i]) == SUCCESS) { + memcpy(buff + (size_t)(i * (MGMT_MSG_LEN / 8)), + mgmtPkt->words, + (size_t)(MGMT_MSG_LEN / 8)); + } + else { + DBG_ERROR("Failed to packing rttReqFrameMsgs[%d].\n", i); + goto failed; + } + filedSize += MGMT_MSG_LEN; + if (filedSize / 8 >= INTRA_MGMT_FRAME_LENGTH_MAX) { + DBG_ERROR("Message is too long to be properly packed.\n"); + goto failed; + } + } + break; + case MGMTPKT_INTRA_RTTRSP: + for (int i = 0; i < ARRAY_SIZE(rttRspFrameMsgs); i++) { + if (MgmtMsg_Packing(instPtr, mgmtPkt, rttRspFrameMsgs[i]) == SUCCESS) { + memcpy(buff + (size_t) (i * (MGMT_MSG_LEN / 8)), + mgmtPkt->words, + (size_t) (MGMT_MSG_LEN / 8)); + } + else { + DBG_ERROR("Failed to packing rttRspFrameMsgs[%d].\n", i); + goto failed; + } + filedSize += MGMT_MSG_LEN; + if (filedSize / 8 >= INTRA_MGMT_FRAME_LENGTH_MAX) { + DBG_ERROR("Message is too long to be properly packed.\n"); + goto failed; + } + } + break; + default: + DBG_ERROR("Scan Packet type [%d] is not surpported yet.\n", pktType); + goto failed; + } + bit_array_free(mgmtPkt); + return SUCCESS; +failed: + bit_array_free(mgmtPkt); + return FAILURE; +} + +/*****************************************************************************/ +/** + * @brief initialize the management FSM instance. + * + * @param mgmtFSM A second rank pointer to management FSM instance. + * + * @return SUCCESS Initialize successfully + * EALLOC Memory allocation error. + * + ******************************************************************************/ +int32_t MgmtNet_Init(L2_MGMT_FSM** mgmtFSM) { + (*mgmtFSM) = (L2_MGMT_FSM*) malloc(sizeof(L2_MGMT_FSM)); + if (*mgmtFSM == NULL) { + return EALLOC; + } + MgmtNet_Reset(*mgmtFSM); + return SUCCESS; +} + +void MgmtNet_Reset(L2_MGMT_FSM* mgmtFSM) { + mgmtFSM->isBisarProc = false; + mgmtFSM->isPendSlotAlloc = false; + mgmtFSM->isPendTimeAlloc = false; + + mgmtFSM->mgmtMsgLog.nextNetState = NONE_STATE; + mgmtFSM->mgmtMsgLog.isValid = false; + mgmtFSM->mgmtMsgLog.quitCtrlWord = 0; + mgmtFSM->mgmtMsgLog.quitNodeId = 0; + mgmtFSM->mgmtMsgLog.msgSubTag = 0 ; + mgmtFSM->mgmtMsgLog.msgTag = 0; + mgmtFSM->mgmtMsgLog.wordTag = 0; + mgmtFSM->mgmtMsgLog.srcNodeId = 0; + + // Position value + mgmtFSM->mgmtMsgLog.EastSpeed = 0 ; + mgmtFSM->mgmtMsgLog.NorthSpeed = 0 ; + mgmtFSM->mgmtMsgLog.UpperSpeed = 0 ; + mgmtFSM->mgmtMsgLog.Height = 0 ; + mgmtFSM->mgmtMsgLog.Longitude = 0 ; + mgmtFSM->mgmtMsgLog.Latitude = 0 ; + + // clear buffer. + memset(&(mgmtFSM->rttMsgRspLog), 0x00, sizeof(RTT_MSG_RECORD)); + memset(&(mgmtFSM->rttMsgReqLog), 0x00, sizeof(RTT_MSG_RECORD)); + memset(&(mgmtFSM->rttData), 0x00, sizeof(RTT_DATA)); +} + +void MgmtNet_Destroy(L2_MGMT_FSM* mgmtFSM){ + free(mgmtFSM); +} +/*****************************************************************************/ +/** + * @brief Handles management net packet, apply time sync and other management + * net functions. + * + * @param msg A pointer to packet data buffer. + * + * @return SUCCESS Packet was successfully handled. + * Other Packed was dumped(not addressed to me, unrecognized frame type) + * + ******************************************************************************/ +int32_t MgmtNet_PktHandler(L2_INST* instPtr) { + ASSERT(instPtr != NULL); + int32_t Status; + uint32_t filedSize = 0; + uint64_t dataChunk = 0; + MGMT_MSG_RECORD *mgmtMsgLog = &(instPtr->mgmtNetFSM->mgmtMsgLog); + RTT_MSG_RECORD *rttMsgRspLog = &(instPtr->mgmtNetFSM->rttMsgRspLog); + RTT_MSG_RECORD *rttMsgReqLog = &(instPtr->mgmtNetFSM->rttMsgReqLog); + + BIT_ARRAY* mgmtMsg = bit_array_create(L2_MSG_MAX); + if (mgmtMsg == NULL) { + free(mgmtMsg); + return EALLOC; + } + switch (L2_GetLastRcvFrameType(instPtr)) { + case L2_INTER_MGMT_FRAME: + case L2_INTRA_MGMT_FRAME: { + for (int i = 0; i < ARRAY_SIZE(intraMgmtFrameMsgs); i++) { + memcpy(mgmtMsg->words, + instPtr->recvPktData + (size_t) (i * (MGMT_MSG_LEN / 8)), + (size_t) (MGMT_MSG_LEN / 8)); + switch (intraMgmtFrameMsgs[i]) { + case L2_MSG_TK_INIT: + FrameGetChunk(mgmtMsg, TK_MSG_INI_NET_STATE_OFFSET, TK_MSG_INI_NET_STATE_LEN, &dataChunk); + mgmtMsgLog->nextNetState = (uint8_t) (dataChunk); + + FrameGetChunk(mgmtMsg, TK_MSG_INI_WTAG_OFFSET, TK_MSG_INI_WTAG_LEN, &dataChunk); + mgmtMsgLog->wordTag = (uint8_t) (dataChunk); + + FrameGetChunk(mgmtMsg, TK_MSG_INI_TAG_OFFSET, TK_MSG_INI_TAG_LEN, &dataChunk); + mgmtMsgLog->msgTag = (uint8_t) (dataChunk); + + FrameGetChunk(mgmtMsg, TK_MSG_INI_STAG_OFFSET, TK_MSG_INI_STAG_LEN, &dataChunk); + mgmtMsgLog->msgSubTag = (uint8_t) (dataChunk); + + if ( mgmtMsgLog->wordTag == 3 + && mgmtMsgLog->msgTag == 28 + && mgmtMsgLog->msgSubTag == 1 ) { + mgmtMsgLog->isValid = true; + } + else { + mgmtMsgLog->isValid = false ; + } + break; + case L2_MSG_TK_EXTD : + FrameGetChunk(mgmtMsg, TK_MSG_EXTEND_EAST_SPEED_OFFSET, TK_MSG_EXTEND_EAST_SPEED_LEN, &dataChunk); + mgmtMsgLog->EastSpeed = (uint16_t) (dataChunk); + + break; + case L2_MSG_TK_CONT_1: + FrameGetChunk(mgmtMsg, TK_MSG_EXTEND_EAST_SPEED_OFFSET, TK_MSG_EXTEND_EAST_SPEED_LEN, &dataChunk); + mgmtMsgLog->EastSpeed = (uint16_t) (dataChunk); + + FrameGetChunk(mgmtMsg, TK_MSG_CONT_1_NORTH_SPEED_OFFSET, TK_MSG_CONT_1_NORTH_SPEED_LEN, &dataChunk); + mgmtMsgLog->NorthSpeed = (uint16_t) (dataChunk); + + FrameGetChunk(mgmtMsg, TK_MSG_CONT_1_UPPER_SPEED_OFFSET, TK_MSG_CONT_1_UPPER_SPEED_LEN, &dataChunk); + mgmtMsgLog->UpperSpeed = (uint16_t) (dataChunk); + + FrameGetChunk(mgmtMsg, TK_MSG_CONT_1_HEIGHT_OFFSET, TK_MSG_CONT_1_HEIGHT_LEN, &dataChunk); + mgmtMsgLog->Height = (uint32_t) (dataChunk); + + break; + case L2_MSG_TK_CONT_2: + FrameGetChunk(mgmtMsg, TK_MSG_CONT_2_LONGITUDE_OFFSET, TK_MSG_CONT_2_LONGITUDE_LEN, &dataChunk); + mgmtMsgLog->Longitude = (uint32_t) (dataChunk); + + FrameGetChunk(mgmtMsg, TK_MSG_CONT_2_LATITUDE_OFFSET, TK_MSG_CONT_2_LATITUDE_LEN, &dataChunk); + mgmtMsgLog->Latitude = (uint32_t) (dataChunk); + + break; + case L2_MSG_TK_CONT_3: + FrameGetChunk(mgmtMsg, TK_MSG_CONT_3_MEMBER_ADDR_OFFSET, TK_MSG_CONT_3_MEMBER_ADDR_LEN, &dataChunk); + mgmtMsgLog->srcNodeId = (uint8_t) (dataChunk & 0x1F); + + break; + case L2_MSG_NQT_INIT: + FrameGetChunk(mgmtMsg, NQT_MSG_OBJ_OFFSET, NQT_MSG_OBJ_LEN, &dataChunk); + mgmtMsgLog->quitNodeId = (uint8_t) (dataChunk & 0x1F); + if (mgmtMsgLog->quitNodeId != instPtr->myInfo.nodeId) { + FrameGetChunk(mgmtMsg, NQT_MSG_CTRL_MUTE_OFFSET, NQT_MSG_CTRL_MUTE_LEN, &dataChunk); + mgmtMsgLog->quitCtrlWord = (uint8_t)(dataChunk & 0x7F); + if (mgmtMsgLog->quitCtrlWord == 0x01) { + DeletNode(instPtr->nodeList, mgmtMsgLog->quitNodeId); + } + } + else { + DBG_WARNING("Ignore node quit request(ID not mine), target node id is [%d]\n", mgmtMsgLog->quitNodeId); + } + break; + default: + DBG_ERROR("Cannot decapsulate message type [%d] in L2_INTRA_MGMT_FRAME.\n", intraMgmtFrameMsgs[i]); + Status = EPARAM; + goto failed; + } + filedSize += MGMT_MSG_LEN; + if (filedSize / 8 >= INTRA_MGMT_FRAME_LENGTH_MAX) { + DBG_ERROR("Message decapsulate exceeds frame length.\n"); + Status = EPARAM; + goto failed; + } + } + // Member Node update state with received message + if(instPtr->myInfo.nodeId != HEAD_NODE && mgmtMsgLog->isValid == true ){ + L2_NODE_STATE newState = NONE_STATE; + // FIXME : + switch (mgmtMsgLog->nextNetState) { + case NET_INI_STAGE: + newState = INIT_STATE; + break; + case NET_NORMAL_STAGE: + newState = NORMAL_STATE; + break; + case NET_INTRA_SEEK_STAGE: + newState = INTRA_SEEK_STATE; + break; + case NET_INTER_SEEK_STAGE: + newState = INTER_SEEK_STATE; + break; + case NET_SEEK_STAGE: + newState = SEEK_STATE; + break; + default: + DBG_WARNING("Unknown Head node state [%d].\n", mgmtMsgLog->nextNetState); + newState = L2_GetMainState(instPtr); + break; + } + L2_EVENT stateUpEvent = { + .event = L2_EV_MAIN_STATE_UPDATE, + .msg = &newState + }; + AssertL2Event(instPtr, &stateUpEvent); + } + // TODO: Reset of tracking message src + RstNodeTTL(instPtr->nodeList, mgmtMsgLog->srcNodeId); + + if(mgmtMsgLog->srcNodeId == instPtr->config.headId){ + L2_TimeAlign(instPtr, L2_GetCurrentFrameNum(instPtr), L2_GetCurrentSlotNum(instPtr)); + } + break; + } + case L2_INTER_TSYNC_FRAME: + case L2_INTRA_TSYNC_FRAME: { + L2_RTT_FSM* rttFsmPtr = L2_GetRttDesc(instPtr); + L2_RTT_SATGE rttStage = RTT_GetCurrentStage(rttFsmPtr); + if(rttStage == RTT_REQ1 || rttStage == RTT_REQ2){ + for (int i = 0; i < ARRAY_SIZE(rttReqFrameMsgs); i++) { + memcpy(mgmtMsg->words, + instPtr->recvPktData + (size_t) (i * (RTT_MSG_LEN / 8)), + (size_t) (RTT_MSG_LEN / 8)); + switch (rttReqFrameMsgs[i]) { + case L2_MSG_RTT_REQ_INIT: + FrameGetChunk(mgmtMsg, RTT_REQ_WTAG_OFFSET, RTT_REQ_WTAG_LEN, &dataChunk); + rttMsgReqLog->wordTag = (uint16_t) (dataChunk); + + FrameGetChunk(mgmtMsg, RTT_REQ_MSG_TAG_OFFSET, RTT_REQ_MSG_TAG_LEN, &dataChunk); + rttMsgReqLog->msgTag = (uint16_t) (dataChunk); + + FrameGetChunk(mgmtMsg, RTT_REQ_MSG_STAG_OFFSET, RTT_REQ_MSG_STAG_LEN, &dataChunk); + rttMsgReqLog->msgSubTag = (uint16_t) (dataChunk); + + FrameGetChunk(mgmtMsg, RTT_REQ_MSG_OFFSET, RTT_REQ_MSG_LEN, &dataChunk); + rttMsgReqLog->msgLen = (uint16_t) (dataChunk); + + FrameGetChunk(mgmtMsg, RTT_REQ_SRC_ADDR_OFFSET, RTT_REQ_SRC_ADDR_LEN, &dataChunk); + rttMsgReqLog->srcAddr = (uint16_t) (dataChunk); + + FrameGetChunk(mgmtMsg, RTT_REQ_DST_ADDR_OFFSET, RTT_REQ_DST_ADDR_LEN, &dataChunk); + rttMsgReqLog->dstAddr = (uint16_t) (dataChunk); + + break; + case L2_MSG_RTT_REQ_EXTD: + FrameGetChunk(mgmtMsg, RTT_REQ_EX_TTAGL_OFFSET, RTT_REQ_EX_TTAGL_LEN, &dataChunk); + rttMsgReqLog->timeWordL = (uint32_t) (dataChunk); + + FrameGetChunk(mgmtMsg, RTT_REQ_EX_TTAGH_OFFSET, RTT_REQ_EX_TTAGH_LEN, &dataChunk); + rttMsgReqLog->timeWordH = (uint32_t) (dataChunk); + + break; + case L2_MSG_RTT_REQ_CONT: + FrameGetChunk(mgmtMsg, RTT_REQ_CONT_DOP_OFFSET, RTT_REQ_CONT_DOP_LEN, &dataChunk); + rttMsgReqLog->doppler = (int32_t) (dataChunk); + + break; + default: + DBG_ERROR("Cannot decapsulate message type [%d] in L2_INTRA_TSYNC_FRAME.\n", rttReqFrameMsgs[i]); + Status = EPARAM; + goto failed; + } + filedSize += RTT_MSG_LEN; + if (filedSize / 8 >= INTRA_RTT_FRAME_LENGTH_MAX) { + DBG_ERROR("Message decapsulate exceeds frame length.\n"); + Status = EPARAM; + goto failed; + } + } + } + else if(rttStage == RTT_RSP1 || rttStage == RTT_RSP2){ + for (int i = 0; i < ARRAY_SIZE(rttRspFrameMsgs); i++) { + memcpy(mgmtMsg->words, + instPtr->recvPktData + (size_t) (i * (RTT_MSG_LEN / 8)), + (size_t) (RTT_MSG_LEN / 8)); + switch (rttRspFrameMsgs[i]) { + case L2_MSG_RTT_RSP_INIT: + FrameGetChunk(mgmtMsg, RTT_RSP_WTAG_OFFSET, RTT_RSP_WTAG_LEN, &dataChunk); + rttMsgRspLog->wordTag = (uint16_t) (dataChunk); + + FrameGetChunk(mgmtMsg, RTT_RSP_MSG_TAG_OFFSET, RTT_RSP_MSG_TAG_LEN, &dataChunk); + rttMsgRspLog->msgTag = (uint16_t) (dataChunk); + + FrameGetChunk(mgmtMsg, RTT_RSP_MSG_STAG_OFFSET, RTT_RSP_MSG_STAG_LEN, &dataChunk); + rttMsgRspLog->msgSubTag = (uint16_t) (dataChunk); + + FrameGetChunk(mgmtMsg, RTT_RSP_MSG_OFFSET, RTT_RSP_MSG_LEN, &dataChunk); + rttMsgRspLog->msgLen = (uint16_t) (dataChunk); + + FrameGetChunk(mgmtMsg, RTT_RSP_SRC_ADDR_OFFSET, RTT_RSP_SRC_ADDR_LEN, &dataChunk); + rttMsgRspLog->srcAddr = (uint16_t) (dataChunk); + + FrameGetChunk(mgmtMsg, RTT_RSP_DST_ADDR_OFFSET, RTT_RSP_DST_ADDR_LEN, &dataChunk); + rttMsgRspLog->dstAddr = (uint16_t) (dataChunk); + + break; + case L2_MSG_RTT_RSP_EXTD: + FrameGetChunk(mgmtMsg, RTT_RSP_EX_TTAGL_OFFSET, RTT_RSP_EX_TTAGL_LEN, &dataChunk); + rttMsgRspLog->timeWordL = (uint32_t) (dataChunk); + + FrameGetChunk(mgmtMsg, RTT_RSP_EX_TTAGH_OFFSET, RTT_RSP_EX_TTAGH_LEN, &dataChunk); + rttMsgRspLog->timeWordH = (uint32_t) (dataChunk); + + break; + case L2_MSG_RTT_RSP_CONT: + FrameGetChunk(mgmtMsg, RTT_RSP_CONT_DOP_OFFSET, + RTT_RSP_CONT_DOP_LEN, &dataChunk); + rttMsgRspLog->doppler = (int32_t) (dataChunk); + + break; + default: + DBG_ERROR("Cannot decapsulate message type [%d] in L2_INTRA_TSYNC_FRAME.\n", rttRspFrameMsgs[i]); + Status = EPARAM; + goto failed; + } + filedSize += RTT_MSG_LEN; + if (filedSize / 8 >= INTRA_RTT_FRAME_LENGTH_MAX) { + DBG_ERROR("Message decapsulate exceeds frame length.\n"); + Status = EPARAM; + goto failed; + } + } + } + // TODO: Reset of tracking message src + RstNodeTTL(instPtr->nodeList, rttMsgRspLog->srcAddr & 0x001F); + if((rttMsgRspLog->srcAddr&0x001F) == instPtr->config.headId){ + L2_TimeAlign(instPtr, L2_GetCurrentFrameNum(instPtr), L2_GetCurrentSlotNum(instPtr)); + } + break; + } + default: + DBG_ERROR("Cannot handle frame type [%d] properly.\n", L2_GetLastRcvFrameType(instPtr)); + Status = EPARAM; + goto failed; + } + bit_array_free(mgmtMsg); + return SUCCESS; +failed: + bit_array_free(mgmtMsg); + return Status; +} + +// helper function +static bool IsTTLValid(NODE_ENTRY* entry) { + ASSERT(entry != NULL); + return (entry->ttlCnt <= CONN_LOST_TH); +} +/*****************************************************************************/ +/** + * @brief Management net FSM procedure. + * + * @param mgmtFSM + * mainState + * + * @return Slot has be used. + * + ******************************************************************************/ +int32_t MgmtNet_Routine(L2_INST* instPtr, const L2_RTNE_TABLE_ENTRY* rtneEntry){ + ASSERT(instPtr != NULL); + int32_t Status; + RTT_DATA *rttData = &(instPtr->mgmtNetFSM->rttData); + RTT_RECORD *rttRecord = &(L2_GetRttDesc(instPtr)->rttRecord); + DBG_INFO("-------- MgmtNet Routine --------\n"); + + if(rtneEntry->slotSeq != 0){ + return SUCCESS; + } + + // Check if there is any node exceeds the ttl threshold. + IterDeleteNode(instPtr->nodeList, IsTTLValid); + + // Determine next slot TOR state. + L2_TOR_TYPE torState = L2_TOR_SUSPEND; + if ((rtneEntry->src0 == instPtr->myInfo.nodeId) + || (rtneEntry->src1 == instPtr->myInfo.nodeId)) { + torState = L2_TOR_TX; + } + else if ((rtneEntry->dst0 == instPtr->myInfo.nodeId) + || (rtneEntry->dst1 == instPtr->myInfo.nodeId)) { + torState = L2_TOR_RX; + } + else { + torState = L2_TOR_SUSPEND; + } + + switch (rtneEntry->slotType) { + case SLOT_INTER_MGMT: + // TODO: + L2_SetupNextSlot(instPtr, torState, L2_INTER_MGMT_FRAME); + break; + case SLOT_INTRA_MGMT: + memset(instPtr->sendPktData, 0xAA, INTRA_MGMT_FRAME_LENGTH_MAX); + if (torState == L2_TOR_TX) { + if(MgmtPkt_Packing(instPtr, MGMTPKT_INTRA_MGMT) != SUCCESS) { + Status = FAILURE; + goto routine_err; + } + } + L2_SetupNextSlot(instPtr, torState, L2_INTRA_MGMT_FRAME); + break; + case SLOT_INTER_TSYNC: + // TODO: + L2_SetupNextSlot(instPtr, torState, L2_INTER_TSYNC_FRAME); + break; + case SLOT_INTRA_TSYNC: + if (torState == L2_TOR_TX) { + // TODO: + memset(instPtr->sendPktData, 0x00, INTRA_RTT_FRAME_LENGTH_MAX); // FIXME + L2_RTT_FSM* rttFsmPtr = L2_GetRttDesc(instPtr); + L2_RTT_SATGE rttStage = RTT_GetCurrentStage(rttFsmPtr); + if(rttStage == RTT_REQ1 || rttStage == RTT_REQ2){ + if(rttStage == RTT_REQ1){ + DBG_INFO("MGMT Sending RTT REQ-1\n"); + rttData->rttTime.timeH = rttRecord->Tt1.timeH; + rttData->rttTime.timeL = rttRecord->Tt1.timeL; + rttData->rttDoppler = RTT_DOPPLER_NONE; + } + else{ //RTT_REQ2 + DBG_INFO("MGMT Sending RTT REQ-2\n"); + rttData->rttTime.timeH = (rttFsmPtr->isR2Valid)? rttRecord->TroundA.timeH : RTT_TIME_NONE; + rttData->rttTime.timeL = (rttFsmPtr->isR2Valid)? rttRecord->TroundA.timeL : RTT_TIME_NONE; + rttData->rttDoppler = (rttFsmPtr->isR2Valid)? rttRecord->dopplerR2:RTT_DOPPLER_NONE; + } + if(MgmtPkt_Packing(instPtr, MGMTPKT_INTRA_RTTREQ) != SUCCESS) { + Status = FAILURE; + goto routine_err; + } + } + else if(rttStage == RTT_RSP1 || rttStage == RTT_RSP2){ + if(rttStage == RTT_RSP1){ + DBG_INFO("MGMT Sending RTT RSP-1\n"); + rttData->rttTime.timeH = (rttFsmPtr->isR1Valid) ? rttRecord->TreplyB.timeH : RTT_TIME_NONE; + rttData->rttTime.timeL = (rttFsmPtr->isR1Valid) ? rttRecord->TreplyB.timeL : RTT_TIME_NONE; + rttData->rttDoppler = (rttFsmPtr->isR1Valid) ? rttRecord->dopplerR1 : RTT_DOPPLER_NONE; + } + else{ //RTT_RSP2 + DBG_INFO("MGMT Sending RTT RSP-2\n"); + rttData->rttTime.timeH = (rttFsmPtr->isR3Valid) ? rttRecord->TreplyB.timeH : RTT_TIME_NONE; + rttData->rttTime.timeL = (rttFsmPtr->isR3Valid) ? rttRecord->TreplyB.timeL : RTT_TIME_NONE; + rttData->rttDoppler = (rttFsmPtr->isR3Valid) ? rttRecord->dopplerR3 : RTT_DOPPLER_NONE; + } + // Packing message. + if(MgmtPkt_Packing(instPtr, MGMTPKT_INTRA_RTTRSP) != SUCCESS) { + Status = FAILURE; + goto routine_err; + } + + } + else{ + DBG_ERROR("Unexpected RTT Stage: %d.\n", rttStage); + torState = L2_TOR_SUSPEND; + } + } + L2_SetupNextSlot(instPtr, torState, L2_INTRA_TSYNC_FRAME); + break; + default: + DBG_ERROR("UNKNOWN slot type [%d].\n", rtneEntry->slotType); + Status = FAILURE; + goto routine_err; + } + + /*************************************************/ + // Update link layer state... + if (instPtr->myInfo.nodeType == HEAD_NODE) { + L2_NODE_STATE newState = NONE_STATE; + L2_EVENT stateEvent = { + .event = L2_EV_MAIN_STATE_UPDATE, + .msg = &newState + }; + if (instPtr->nodeList->nodeNum < instPtr->config.netScale + && L2_GetMainState(instPtr) != INTRA_SEEK_STATE) { + newState = INTRA_SEEK_STATE; + AssertL2Event(instPtr, &stateEvent); + } + else if(instPtr->nodeList->nodeNum >= instPtr->config.netScale && + L2_GetMainState(instPtr) != NORMAL_STATE){ + newState = NORMAL_STATE; + AssertL2Event(instPtr, &stateEvent); + } + } + else{ // MEMBER_NODE or BACKUP_HEAD + if(IsNodeInList(instPtr->nodeList, instPtr->config.headId) == false){ + L2_NODE_STATE newState = INIT_STATE; + L2_EVENT stateEvent = { + .event = L2_EV_MAIN_STATE_UPDATE, + .msg = &newState + }; + AssertL2Event(instPtr, &stateEvent); + L2_EVENT lostCxnEvent = { + .event = L2_EV_LOST_CXN, + .msg = NULL + }; + AssertL2Event(instPtr, &lostCxnEvent); + DBG_WARNING("Lost connection with head node [%d].\n", instPtr->config.headId); + } + } + return SUCCESS; +routine_err: + return Status; +} diff --git a/datalink814_ge/src/linklayer/net_scan.c b/datalink814_ge/src/linklayer/net_scan.c new file mode 100644 index 0000000..7949fa6 --- /dev/null +++ b/datalink814_ge/src/linklayer/net_scan.c @@ -0,0 +1,1016 @@ +/*****************************************************************************/ +/** + * Description: Implementations of 814 linklayer scan net. + * + * Date: 2021-11-10 19:04 + * LastEditors: Fan Hao + * LastEditTime: 2022-07-16 17:04 + * Revisions: Rev 0.1 + * History: + * [2022-07-16]: New branch for DiJian. + * [2021-11-10]: Initial version. + * + * Copyright(c) 2021 Beijing Institute of Technology. + * Lab of Communication and Networking + * + ******************************************************************************/ + +/***************************** Include Files *********************************/ +#include +#include "linklayer814.h" +#include "linklayer814_types.h" +#include "node_list.h" +#include "msg_def.h" +#include "../error.h" +#include "../common.h" +#include "../bit_array/bit_array.h" +#include "../bit_array/bit_macros.h" + +/************************** Constant Definitions *****************************/ +#define INIT_BEAM_NO 0 +#define BEAM_PER_ANT 37 +#define INIT_ANT_NO 0 +#define ANT_NUM 6 + +#define BM_LSTEN_TIMEOUT 40 + +#define SQUENCE_SCAN_SLOTS 0 + +#define INTRA_INIT_SCAN_SLOTS 2 +#define INTRA_BM_ADVT_SLOTS 4 +#define INTRA_WAY2ACQ_SLOTS 1 + +#define INTER_INIT_SCAN_SLOTS 4 +#define INTER_BM_ADVT_SLOTS 20 +#define INTER_WAY2ACQ_SLOTS 2 + +//#define INIT_SCAN_SLOT_MAX 37 +//#define BM_ADVT_SLOT_MAX 2 +#define WAY2_ACQ_SLOT_MAX 120 + +/***************** Macros (Inline Functions) Definitions *********************/ + +/**************************** Type Definitions *******************************/ +typedef enum { + SCANPKT_NONE = 0, + SCANPKT_INTER_BM = 1, + SCANPKT_INTRA_BM = 2, + SCANPKT_INTER_2WACQ = 3, + SCANPKT_INTRA_2WACQ = 4 +} SCANPKT_TYPE; +/************************** Variable Definitions *****************************/ + +/************************** Function Prototypes ******************************/ +static void LockStateUpdate(L2_SCAN_FSM* scanFsmPtr, bool state); +static void BmrecvStateUpdate(L2_SCAN_FSM* scanFsmPtr, bool state); +static void W2ackStateUpdate(L2_SCAN_FSM* scanFsmPtr, bool state); + +static void StageUpdate(L2_SCAN_FSM* scanFsmPtr, SCAN_STAGE newStage); +//static int32_t Check_W2AcqAck(NODE_ENTRY* nodeEntry); +static int32_t Scan_InitScanHandler(L2_INST* instPtr); +static int32_t Scan_BmAdvtHandler(L2_INST* instPtr); +static int32_t Scan_2WAcqHandler(L2_INST* instPtr); +static int32_t ScanMsg_Packing(L2_INST* instPtr, BIT_ARRAY* bitarr, L2_MSG_TYPE msgType); +static int32_t ScanPkt_Packing(L2_INST* instPtr, SCANPKT_TYPE pktType); + + + +static inline void LockStateUpdate(L2_SCAN_FSM* scanFsmPtr, bool state){ + ASSERT(scanFsmPtr != NULL); + DBG_INFO("Update BeamLockState from [%d] to [%d].\n", + scanFsmPtr->isLocked, state); + scanFsmPtr->isLocked = state; + return; +} +static void BmrecvStateUpdate(L2_SCAN_FSM* scanFsmPtr, bool state){ + ASSERT(scanFsmPtr != NULL); + DBG_INFO("Update BmRecvState from [%d] to [%d].\n", + scanFsmPtr->isBmRcved, state); + scanFsmPtr->isBmRcved = state; + return; +} +static void W2ackStateUpdate(L2_SCAN_FSM* scanFsmPtr, bool state){ + ASSERT(scanFsmPtr != NULL); + DBG_INFO("Update W2acqAckState from [%d] to [%d].\n", + scanFsmPtr->isAcked, state); + scanFsmPtr->isAcked = state; + return; +} + +/*****************************************************************************/ + +/** + * @brief Update current Scan-Net stage + * + * @param scanFsmPtr A pointer to scan net fsm. + * newStage New state. + * + * @return NONE. + * + ******************************************************************************/ +static void StageUpdate(L2_SCAN_FSM* scanFsmPtr, SCAN_STAGE newStage) { + DBG_INFO("ScanNet current stage: %u -> ScanNet new stage: %u \n", + scanFsmPtr->scanStage, newStage); + scanFsmPtr->scanStage = newStage; +} +/*****************************************************************************/ +/** + * @brief Packing Scan message to a bit array. + * + * @param bitarr pointer to bit array buffer. + * msgType message type. + * + * @return EPARAM + * SUCCESS + * + ******************************************************************************/ +static int32_t ScanMsg_Packing(L2_INST* instPtr, BIT_ARRAY* bitarr, L2_MSG_TYPE msgType) { + ASSERT(bitarr != NULL); + int32_t Status = SUCCESS; + if (bitarr->num_of_bits < NS_MSG_LEN || msgType < L2_MSG_BM + || msgType > L2_MSG_SCAN_CONT_5) { + return (EPARAM); + } + uint64_t dataChunk = 0; + memset(bitarr->words, 0xAA, (size_t)(bitarr->num_of_bits / 8)); + switch (msgType) { + case L2_MSG_BM: + if (bitarr->num_of_bits < BM_MSG_LEN) { + return EPARAM; + } + /* message type all zero */ + dataChunk = 0; + FrameInsertChunk(bitarr, BM_MSG_TYPE_OFFSET, BM_MSG_TYPE_LEN, dataChunk); + + /* source node id */ + dataChunk = (instPtr->myInfo.nodeId & 0x1F) + | (((uint16_t)(instPtr->myInfo.clustId & 0x1F)) << 5); + FrameInsertChunk(bitarr, BM_MSG_SRC_ADDR_OFFSET, BM_MSG_SRC_ADDR_LEN, dataChunk); + + /* net management node id */ + dataChunk = (instPtr->config.headId & 0x1F) + | (((uint16_t)(instPtr->myInfo.clustId & 0x1F)) << 5); + FrameInsertChunk(bitarr, BM_MSG_NETMG_ADDR_OFFSET, BM_MSG_NETMG_ADDR_LEN, dataChunk); + + /* time unit number */ + dataChunk = L2_GetNextFrameNum(instPtr); + FrameInsertChunk(bitarr, BM_MSG_TUNIT_NUM_OFFSET, BM_MSG_TUNIT_NUM_LEN, dataChunk); + + /* frame number */ + dataChunk = L2_GetNextSlotNum(instPtr) / L2_SLOTS_PER_SUBFRAME; + FrameInsertChunk(bitarr, BM_MSG_TFRAME_NUM_OFFSET, BM_MSG_TFRAME_NUM_LEN, dataChunk); + + /* mini slot number, 20 mini slots per frame. */ + dataChunk = L2_GetNextSlotNum(instPtr) % L2_SLOTS_PER_SUBFRAME; + FrameInsertChunk(bitarr, BM_MSG_TSLOT_NUM_OFFSET, BM_MSG_TSLOT_NUM_LEN, dataChunk); + + /* FIXME : Only for test */ + /* longitude. */ + dataChunk = 203; + FrameInsertChunk(bitarr, BM_MSG_LONGITUDE_OFFSET, BM_MSG_LONGITUDE_LEN, dataChunk); + + /* latitude. */ + dataChunk = 589; + FrameInsertChunk(bitarr, BM_MSG_LATITUDE_OFFSET, BM_MSG_LATITUDE_LEN, dataChunk); + + /* Height. */ + dataChunk = 589; + FrameInsertChunk(bitarr, BM_MSG_HEIGHT_OFFSET, BM_MSG_HEIGHT_LEN, dataChunk); + + /* East. */ + dataChunk = 19; + FrameInsertChunk(bitarr, BM_MSG_EAST_SPEED_OFFSET, BM_MSG_EAST_SPEED_LEN, dataChunk); + + /* North. */ + dataChunk = 30; + FrameInsertChunk(bitarr, BM_MSG_NORTH_SPEED_OFFSET, BM_MSG_NORTH_SPEED_LEN, dataChunk); + + /* Upper. */ + dataChunk = 69; + FrameInsertChunk(bitarr, BM_MSG_UPPER_SPEED_OFFSET, BM_MSG_UPPER_SPEED_LEN, dataChunk); + + /* Append CRC */ + L2_CrcAppend((uint8_t *) bitarr->words, BM_MSG_CRC_OFFSET / 8, BM_MSG_CRC_OFFSET / 8, L2_CRC8_31); + + break; + case L2_MSG_SCAN_INIT: + if (bitarr->num_of_bits < NS_MSG_LEN) { + return EPARAM; + } + /* Sequence tag */ + dataChunk = 0; + FrameInsertChunk(bitarr, NS_MSG_INI_SER_TAG_OFFSET, NS_MSG_INI_SER_TAG_LEN, dataChunk); + + /* word tag */ + dataChunk = 3; + FrameInsertChunk(bitarr, NS_MSG_INI_WTAG_OFFSET, NS_MSG_INI_WTAG_LEN, dataChunk); + + /* message tag */ + dataChunk = 28; + FrameInsertChunk(bitarr, NS_MSG_INI_MTAG_OFFSET, NS_MSG_INI_MTAG_LEN, dataChunk); + + /* message sub tag */ + dataChunk = 0; + FrameInsertChunk(bitarr, NS_MSG_INI_STAG_OFFSET, NS_MSG_INI_STAG_LEN, dataChunk); + + /* message length tag */ + dataChunk = 5; + FrameInsertChunk(bitarr, NS_MSG_INI_LEN_OFFSET, NS_MSG_INI_LEN_LEN, dataChunk); + + /* message type */ + dataChunk = (instPtr->myInfo.nodeId == HEAD_NODE) ? 0 : 1; + FrameInsertChunk(bitarr, NS_MSG_INI_TYPE_OFFSET, NS_MSG_INI_TYPE_LEN, dataChunk); + + /* source node id */ + dataChunk = (instPtr->myInfo.nodeId & 0x1F) + | (((uint16_t)(instPtr->myInfo.clustId & 0x1F)) << 5); + FrameInsertChunk(bitarr, NS_MSG_INI_SRC_ADDR_OFFSET, NS_MSG_INI_SRC_ADDR_LEN, dataChunk); + + /* destination node id */ + dataChunk = (instPtr->myInfo.nodeId == HEAD_NODE) ? + (0x3F | (0x3F << 5)) : + (instPtr->config.headId & 0x1F) | (((uint16_t)(instPtr->myInfo.clustId & 0x1F)) << 5); + FrameInsertChunk(bitarr, NS_MSG_INI_LEN_OFFSET, NS_MSG_INI_LEN_LEN, dataChunk); + if (instPtr->myInfo.nodeType == HEAD_NODE) { + /* current net stage */ + switch (instPtr->mainState) { + case INIT_STATE: + dataChunk = NET_INI_STAGE; + break; + case SEEK_STATE: + dataChunk = NET_INTER_SEEK_STAGE; + break; + case NORMAL_STATE: + dataChunk = NET_NORMAL_STAGE; + break; + default: + dataChunk = NET_ERROR_STAGE; + break; + } + FrameInsertChunk(bitarr, NS_MSG_INI_NET_STAGE_OFFSET, NS_MSG_INI_NET_STAGE_LEN, dataChunk); + + // Begin Scan Time Word + dataChunk = instPtr->netStartTime; + FrameInsertChunk(bitarr, NS_MSG_INI_SCAN_TIME_OFFSET, NS_MSG_INI_SCAN_TIME_LEN, dataChunk); + } + break; + case L2_MSG_SCAN_CONT_1: + if (bitarr->num_of_bits < NS_MSG_LEN) { + return EPARAM; + } + /* word tag */ + dataChunk = 2; + FrameInsertChunk(bitarr, NS_MSG_CONT_1_WTAG_OFFSET, NS_MSG_CONT_1_WTAG_LEN, dataChunk); + + /* Continue word identification. */ + dataChunk = 1; + FrameInsertChunk(bitarr, NS_MSG_CONT_1_CONTID_OFFSET, NS_MSG_CONT_1_CONTID_LEN, dataChunk); + + /* Time tag */ + dataChunk = 0x00FF00FF00FF; + FrameInsertChunk(bitarr, NS_MSG_CONT_1_TIME_TAG_OFFSET, NS_MSG_CONT_1_TIME_TAG_LEN, dataChunk); + + /* East speed */ + dataChunk = 0xF0F0; + FrameInsertChunk(bitarr, NS_MSG_CONT_1_EAST_SPEED_OFFSET, NS_MSG_CONT_1_EAST_SPEED_LEN, dataChunk); + + break; + case L2_MSG_SCAN_CONT_2: + if (bitarr->num_of_bits < NS_MSG_LEN) { + return EPARAM; + } + /* word tag */ + dataChunk = 2; + FrameInsertChunk(bitarr, NS_MSG_CONT_2_WTAG_OFFSET, NS_MSG_CONT_2_WTAG_LEN, dataChunk); + + /* Continue word identification. */ + dataChunk = 2; + FrameInsertChunk(bitarr, NS_MSG_CONT_2_CONTID_OFFSET, NS_MSG_CONT_2_CONTID_LEN, dataChunk); + + /* North speed */ + dataChunk = 0x0F0F; + FrameInsertChunk(bitarr, NS_MSG_CONT_2_NORTH_SPEED_OFFSET, NS_MSG_CONT_2_NORTH_SPEED_LEN, dataChunk); + + /* Upper speed */ + dataChunk = 0x0FF0; + FrameInsertChunk(bitarr, NS_MSG_CONT_2_UPPER_SPEED_OFFSET, NS_MSG_CONT_2_UPPER_SPEED_LEN, dataChunk); + + /* Height */ + dataChunk = 0x00FF00; + FrameInsertChunk(bitarr, NS_MSG_CONT_2_HEIGHT_OFFSET, NS_MSG_CONT_2_HEIGHT_LEN, dataChunk); + + break; + case L2_MSG_SCAN_CONT_3: + if (bitarr->num_of_bits < NS_MSG_LEN) { + return EPARAM; + } + /* word tag */ + dataChunk = 2; + FrameInsertChunk(bitarr, NS_MSG_CONT_3_WTAG_OFFSET, NS_MSG_CONT_3_WTAG_LEN, dataChunk); + + /* Continue word identification. */ + dataChunk = 3; + FrameInsertChunk(bitarr, NS_MSG_CONT_3_CONTID_OFFSET, NS_MSG_CONT_3_CONTID_LEN, dataChunk); + + /* Longitude */ + dataChunk = 0x00FF00FF; + FrameInsertChunk(bitarr, NS_MSG_CONT_3_LONGITUDE_OFFSET, NS_MSG_CONT_3_LONGITUDE_LEN, dataChunk); + + /* Latitude */ + dataChunk = 0xFF00FF00; + FrameInsertChunk(bitarr, NS_MSG_CONT_3_LATITUDE_OFFSET, NS_MSG_CONT_3_LATITUDE_LEN, dataChunk); + + break; + case L2_MSG_SCAN_CONT_4: + if (bitarr->num_of_bits < NS_MSG_LEN) { + return EPARAM; + } + /* word tag */ + dataChunk = 2; + FrameInsertChunk(bitarr, NS_MSG_CONT_4_WTAG_OFFSET, NS_MSG_CONT_4_WTAG_LEN, dataChunk); + + /* Continue word identification. */ + dataChunk = 4; + FrameInsertChunk(bitarr, NS_MSG_CONT_4_CONTID_OFFSET, NS_MSG_CONT_4_CONTID_LEN, dataChunk); + + /* Message key */ + dataChunk = 0xF0F0F0F0F0F0; + FrameInsertChunk(bitarr, NS_MSG_CONT_4_KEY_OFFSET, NS_MSG_CONT_4_KEY_LEN, dataChunk); + break; + case L2_MSG_SCAN_CONT_5: + if (bitarr->num_of_bits < NS_MSG_LEN) { + return EPARAM; + } + /* word tag */ + dataChunk = 2; + FrameInsertChunk(bitarr, NS_MSG_CONT_5_WTAG_OFFSET, NS_MSG_CONT_5_WTAG_LEN, dataChunk); + + /* Continue word identification. */ + dataChunk = 5; + FrameInsertChunk(bitarr, NS_MSG_CONT_5_CONTID_OFFSET, NS_MSG_CONT_5_CONTID_LEN, dataChunk); + + /* Message key */ + dataChunk = 0x0F0F0F0F0F; + FrameInsertChunk(bitarr, NS_MSG_CONT_5_KEY_OFFSET, NS_MSG_CONT_5_KEY_LEN, dataChunk); + break; + default: + Status = EPARAM; + break; + } + return Status; +} + +static int32_t ScanPkt_Packing(L2_INST* instPtr, SCANPKT_TYPE pktType){ + uint32_t filedSize = 0; + uint8_t* buff = instPtr->sendPktData; + BIT_ARRAY* scanPkt = bit_array_create(L2_MSG_MAX); + if (scanPkt == NULL) { + DBG_ERROR("Failed to allocate memory for scanMsg.\n"); + return NUM_SLOTS_NONE; + } + switch (pktType) { + case SCANPKT_INTRA_BM: + if (ScanMsg_Packing(instPtr, scanPkt, L2_MSG_BM) != SUCCESS) { + DBG_ERROR("Failed to packing L2_MSG_BM frame.\n"); + goto failed; + } + memcpy(buff, scanPkt->words, (size_t)(BM_MSG_LEN / 8)); + break; + case SCANPKT_INTRA_2WACQ: + for (int i = 0; i < ARRAY_SIZE(intraW2AcqFrameMsgs); i++) { + if (ScanMsg_Packing(instPtr, scanPkt, intraW2AcqFrameMsgs[i]) == SUCCESS) { + memcpy((uint8_t*)buff + (size_t)(i * (NS_MSG_LEN / 8)), + scanPkt->words, (size_t)(NS_MSG_LEN / 8)); + } + else { + DBG_ERROR("Failed to packing intraW2AcqFrameMsgs[%d].\n", i); + goto failed; + } + filedSize += NS_MSG_LEN; + if (filedSize / 8 >= INTRA_W2ACQ_FRAME_LENGTH_MAX) { + DBG_ERROR("Message is too long to be properly packed.\n"); + goto failed; + } + } + L2_CrcAppend(buff, W2ACQ_FRAME_CRC_DLEN, W2ACQ_FRAME_CRC_POS, L2_CRC16_8005); + break; + default: + DBG_ERROR("Scan Packet type [%d] is not surpported yet.\n", pktType); + goto failed; + } + bit_array_free(scanPkt); + return SUCCESS; +failed: + bit_array_free(scanPkt); + return FAILURE; +} + +/*****************************************************************************/ +/** + * @brief Member node scan net InitScan stage handler. + * + * @param instPtr A pointer to l2 instance + * + * @return used slot (5ms slot). + * + ******************************************************************************/ +static int32_t Scan_InitScanHandler(L2_INST* instPtr) { + ASSERT(instPtr != NULL); + L2_SCAN_FSM* scanFsmPtr = instPtr->scanNetFSM; + PHY_INST* phyRef = instPtr->config.phyInstPtr; + static uint32_t scanCnt = 0; + DBG_INFO("** Netsetup - InitScan Procedure--**\n"); + /* clear ack state and lock state in a new scan procedure. */ + if(scanCnt == 0){ + LockStateUpdate(scanFsmPtr, false); + BmrecvStateUpdate(scanFsmPtr, false); + W2ackStateUpdate(scanFsmPtr, false); + } + if(Phy_IsFrameDetected(phyRef)){ + LockStateUpdate(scanFsmPtr, true); + } + + if(scanFsmPtr->scanMode == INTRA_CLUSTER_MODE){ + if (scanFsmPtr->isLocked == true) { + StageUpdate(scanFsmPtr, BM_ADVT_STAGE); + /* Antenna setting (reserved.) */ + L2_SetupNextSlot(instPtr, L2_TOR_RX, L2_INTRA_BM_FRAME); + scanCnt = 0; + } /* Otherwise remain INIT_SCAN_STAGE */ + else { + /* Antenna setting (reserved.) */ + L2_SetupNextSlot(instPtr, L2_TOR_RX, L2_INTRA_SCAN_FRAME); + scanCnt++; + } + } + else if(scanFsmPtr->scanMode == INTER_CLUSTER_MODE){ + if (scanFsmPtr->isLocked == true) { + StageUpdate(scanFsmPtr, BM_ADVT_STAGE); + /* Antenna setting (reserved.) */ + L2_SetupNextSlot(instPtr, L2_TOR_RX, L2_INTER_BM_FRAME); + scanCnt = 0; + } /* Otherwise remain INIT_SCAN_STAGE */ + else { + /* Antenna setting (reserved.) */ + L2_SetupNextSlot(instPtr, L2_TOR_RX, L2_INTER_SCAN_FRAME); + scanCnt++; + } + } + else{ + DBG_ERROR("UNKNOWN Scan Mode: %d.\n", scanFsmPtr->scanMode); + return NUM_SLOTS_NONE; + } + return (NUM_SLOTS_SKIP); +} + +/*****************************************************************************/ + +/** + * @brief Member node scan net BmAdvt stage handler. + * + * @param scanFsmPtr A pointer to scan net fsm. + * mainState A pointer to main node state. + * + * @return used slot (5ms slot). + * + ******************************************************************************/ +static int32_t Scan_BmAdvtHandler(L2_INST* instPtr) { + L2_SCAN_FSM* scanFsmPtr = instPtr->scanNetFSM; + DBG_INFO("** Netsetup - BmAdvt Procedure--**\n"); + DBG_INFO("BM Timeout: %u.\n", scanFsmPtr->bmTimeout); + + // if received a valid bm frame. + if (scanFsmPtr->isBmRcved == true) { + scanFsmPtr->bmTimeout = 0; /* reset listen counter. */ + /* First BM Advt Frame. */ + DBG_INFO("Received Bm frame.\n"); + DBG_INFO("Skipping 10ms for turn around.\n"); + /* Antenna setting (reserved.) */ + // FIXME: SUSPEND how many slots in inter net setup mode? + L2_SetupNextSlot(instPtr, L2_TOR_SUSPEND, L2_INTRA_W2_ACQ_FRAME); + StageUpdate(scanFsmPtr, WAY2_ACQ_STAGE); + return NUM_SLOTS_10MS; + } + // no valid bm frame was received. + else { + /* if time out reached, go back to init scan stage. */ + if (scanFsmPtr->bmTimeout > BM_LSTEN_TIMEOUT) { + if(scanFsmPtr->scanMode == INTRA_CLUSTER_MODE){ + /* Antenna setting (reserved.) */ + L2_SetupNextSlot(instPtr, L2_TOR_RX, L2_INTRA_SCAN_FRAME); + } + else if(scanFsmPtr->scanMode == INTER_CLUSTER_MODE){ + /* Antenna setting (reserved.) */ + L2_SetupNextSlot(instPtr, L2_TOR_RX, L2_INTER_SCAN_FRAME); + } + else{ + DBG_ERROR("UNKNOWN Scan Mode: %d.\n", scanFsmPtr->scanMode); + return NUM_SLOTS_NONE; + } + StageUpdate(scanFsmPtr, INIT_SCAN_STAGE); + scanFsmPtr->bmTimeout = 0; /* reset listen counter. */ + } + else { + if(scanFsmPtr->scanMode == INTRA_CLUSTER_MODE){ + /* Antenna setting (reserved.) */ + L2_SetupNextSlot(instPtr, L2_TOR_RX, L2_INTRA_BM_FRAME); + } + else if(scanFsmPtr->scanMode == INTER_CLUSTER_MODE){ + /* Antenna setting (reserved.) */ + L2_SetupNextSlot(instPtr, L2_TOR_RX, L2_INTER_BM_FRAME); + } + else{ + DBG_ERROR("UNKNOWN Scan Mode: %d.\n", scanFsmPtr->scanMode); + return NUM_SLOTS_NONE; + } + scanFsmPtr->bmTimeout++; + } + return NUM_SLOTS_SKIP; + } +} + +/*****************************************************************************/ +/** + * @brief Scan net 2Way-Acq stage handler. + * + * @param instPtr a pointer to linklayer layer instance + * + * @return used slot (5ms slot). + * + ******************************************************************************/ +static int32_t Scan_2WAcqHandler (L2_INST* instPtr){ + L2_SCAN_FSM* scanFsmPtr = instPtr->scanNetFSM; + DBG_INFO("** Netsetup - 2WAcq Procedure--**\n"); + DBG_INFO("2WAcq Timeout: %u.\n", scanFsmPtr->w2acqTimeout); + L2_FRAME_TYPE frameType = L2_NONE_FRAME; + + if(scanFsmPtr->scanMode == INTRA_CLUSTER_MODE){ + frameType = L2_INTRA_W2_ACQ_FRAME; + } + else if(scanFsmPtr->scanMode == INTER_CLUSTER_MODE){ + frameType = L2_INTER_W2_ACQ_FRAME; + } + else{ + DBG_ERROR("UNKNOWN Scan Mode: %d.\n", scanFsmPtr->scanMode); + return FAILURE; + } + + // 2 way acq failed, back to init stage. + if (scanFsmPtr->w2acqTimeout >= WAY2_ACQ_SLOT_MAX) { + scanFsmPtr->w2acqTimeout = 0; // reset counter for next scan. + StageUpdate(scanFsmPtr, INIT_SCAN_STAGE); + } + else { + scanFsmPtr->w2acqTimeout++; // increase counter. + } + L2_SetupNextSlot(instPtr, L2_TOR_RX, frameType); + return SUCCESS; +} + +/*****************************************************************************/ + +/** + * @brief Scan net packet handler. + * + * @param instPtr a pointer to linklayer layer instance + * + * @return SUCCESS + * error code + * + ******************************************************************************/ +int32_t ScanNet_PktHandler(L2_INST* instPtr) { + ASSERT(instPtr != NULL); + uint32_t Status; + L2_SCAN_FSM* scanFsmPtr = instPtr->scanNetFSM; + uint64_t dataChunk; + BIT_ARRAY* scanMsg = bit_array_create(L2_MSG_MAX); + if (scanMsg == NULL) { + free(scanMsg); + return EALLOC; + } + switch (L2_GetLastRcvFrameType(instPtr)) { + case L2_INTER_SCAN_FRAME: + case L2_INTRA_SCAN_FRAME: + // refer to "linklayer814.c/L2_FrameStateUpdate" + // INTRA_BM_FRAME could be received if current frame type is INTRA_BM_FRAME + // in net setup stage(for member node). + // When SCAN frame was considered as received, handle the frame as BM frame. + break; + case L2_INTER_BM_FRAME: + case L2_INTRA_BM_FRAME: { + for (int i = 0; i < ARRAY_SIZE(intraBmFrameMsgs); i++) { + memcpy(scanMsg->words, + instPtr->recvPktData + (size_t)(i * (BM_MSG_LEN / 8)), + (size_t)(BM_MSG_LEN / 8)); + switch (intraBmFrameMsgs[i]) { + case L2_MSG_BM: + FrameGetChunk(scanMsg, BM_MSG_SRC_ADDR_OFFSET, BM_MSG_SRC_ADDR_LEN, &dataChunk); + scanFsmPtr->BMrcvLog.NodeId = dataChunk & 0x000000000000001F; + scanFsmPtr->BMrcvLog.ClusterId = (dataChunk>>5) & 0x000000000000001F; + + FrameGetChunk(scanMsg, BM_MSG_TUNIT_NUM_OFFSET, BM_MSG_TUNIT_NUM_LEN, &dataChunk); + scanFsmPtr->BMrcvLog.frameNum = (uint32_t) dataChunk; + + FrameGetChunk(scanMsg, BM_MSG_TFRAME_NUM_OFFSET, BM_MSG_TFRAME_NUM_LEN, &dataChunk); + scanFsmPtr->BMrcvLog.slotNum = (uint32_t)(dataChunk * L2_SLOTS_PER_SUBFRAME); + + FrameGetChunk(scanMsg, BM_MSG_TSLOT_NUM_OFFSET, BM_MSG_TSLOT_NUM_LEN, &dataChunk); + scanFsmPtr->BMrcvLog.slotNum = scanFsmPtr->BMrcvLog.slotNum + (uint32_t) dataChunk; + + FrameGetChunk(scanMsg, BM_MSG_LONGITUDE_OFFSET, BM_MSG_LONGITUDE_LEN, &dataChunk); + scanFsmPtr->BMrcvLog.Longitude = (uint32_t)(dataChunk); + + FrameGetChunk(scanMsg, BM_MSG_LATITUDE_OFFSET, BM_MSG_LATITUDE_LEN, &dataChunk); + scanFsmPtr->BMrcvLog.Latitude = (uint32_t)(dataChunk); + + FrameGetChunk(scanMsg, BM_MSG_HEIGHT_OFFSET, BM_MSG_HEIGHT_LEN, &dataChunk); + scanFsmPtr->BMrcvLog.Height = (uint32_t)(dataChunk); + + FrameGetChunk(scanMsg, BM_MSG_EAST_SPEED_OFFSET, BM_MSG_EAST_SPEED_LEN, &dataChunk); + scanFsmPtr->BMrcvLog.EastSpeed = (uint32_t)(dataChunk); + + FrameGetChunk(scanMsg, BM_MSG_NORTH_SPEED_OFFSET, BM_MSG_NORTH_SPEED_LEN, &dataChunk); + scanFsmPtr->BMrcvLog.NorthSpeed = (uint32_t)(dataChunk); + + FrameGetChunk(scanMsg, BM_MSG_UPPER_SPEED_OFFSET, BM_MSG_UPPER_SPEED_LEN, &dataChunk); + scanFsmPtr->BMrcvLog.UpperSpeed = (uint32_t)(dataChunk); + break; + default: + DBG_ERROR("UNSURPPORTED message type [%d]. \n", intraBmFrameMsgs[i]); + Status = EIGNORE; + goto failed; + } + } + if(instPtr->myInfo.nodeType != HEAD_NODE){ + if (IsNodeInList(instPtr->nodeList, scanFsmPtr->BMrcvLog.NodeId) == false) { + AppendNode(instPtr->nodeList, scanFsmPtr->BMrcvLog.NodeId, (uint8_t) MEMBER_NODE); + } + // TODO: Update Node Info + + if ( L2_isCxn2Net(instPtr) == false ) { + // TODO: Check + L2_TimeAlign(instPtr, scanFsmPtr->BMrcvLog.frameNum, scanFsmPtr->BMrcvLog.slotNum); + } + // trigger flag + BmrecvStateUpdate(scanFsmPtr, true); + } + else{ + DBG_ERROR("Node type [%d] is not supposed to receive BM frame", instPtr->myInfo.nodeType); + Status = EUNEXP; + goto failed; + } + break; + } + case L2_INTER_W2_ACQ_FRAME: + case L2_INTRA_W2_ACQ_FRAME: { + for (int i = 0; i < ARRAY_SIZE(intraW2AcqFrameMsgs); i++) { + memcpy(scanMsg->words, + instPtr->recvPktData + (size_t)(i * (NS_MSG_LEN / 8)), + (size_t)(NS_MSG_LEN / 8)); + switch (intraW2AcqFrameMsgs[i]) { + case L2_MSG_SCAN_INIT: + FrameGetChunk(scanMsg, NS_MSG_INI_SRC_ADDR_OFFSET, NS_MSG_INI_SRC_ADDR_LEN, &dataChunk); + scanFsmPtr->W2ACQrcvLog.NodeId = dataChunk & 0x001F; + scanFsmPtr->W2ACQrcvLog.ClusterId = (dataChunk>>5) & 0x0001F; + + FrameGetChunk(scanMsg, NS_MSG_INI_NET_STAGE_OFFSET, NS_MSG_INI_NET_STAGE_LEN, &dataChunk); + switch (dataChunk) { + case NET_INI_STAGE: + scanFsmPtr->W2ACQrcvLog.NetStage = INIT_STATE; + break; + case NET_NORMAL_STAGE: + scanFsmPtr->W2ACQrcvLog.NetStage = NORMAL_STATE; + break; + case NET_INTRA_SEEK_STAGE: + scanFsmPtr->W2ACQrcvLog.NetStage = INTRA_SEEK_STATE; + break; + case NET_INTER_SEEK_STAGE: + scanFsmPtr->W2ACQrcvLog.NetStage = INTER_SEEK_STATE; + break; + case NET_SEEK_STAGE: + scanFsmPtr->W2ACQrcvLog.NetStage = SEEK_STATE; + break; + default: + scanFsmPtr->W2ACQrcvLog.NetStage = NONE_STATE; + DBG_WARNING("UNEXPECTED head node state."); + break; + } + + FrameGetChunk(scanMsg, NS_MSG_INI_SCAN_TIME_OFFSET, NS_MSG_INI_SCAN_TIME_LEN, &dataChunk); + scanFsmPtr->W2ACQrcvLog.NetScanTime = (uint32_t)(dataChunk); + break; + case L2_MSG_SCAN_CONT_1: + FrameGetChunk(scanMsg, NS_MSG_CONT_1_EAST_SPEED_OFFSET, NS_MSG_CONT_1_EAST_SPEED_LEN, &dataChunk); + scanFsmPtr->W2ACQrcvLog.EastSpeed = (uint16_t)(dataChunk); + break; + case L2_MSG_SCAN_CONT_2: + FrameGetChunk(scanMsg, NS_MSG_CONT_2_NORTH_SPEED_OFFSET, NS_MSG_CONT_2_NORTH_SPEED_LEN, &dataChunk); + scanFsmPtr->W2ACQrcvLog.NorthSpeed = (uint16_t)(dataChunk); + + FrameGetChunk(scanMsg, NS_MSG_CONT_2_UPPER_SPEED_OFFSET, NS_MSG_CONT_2_UPPER_SPEED_LEN, &dataChunk); + scanFsmPtr->W2ACQrcvLog.UpperSpeed = (uint16_t)(dataChunk); + + FrameGetChunk(scanMsg, NS_MSG_CONT_2_HEIGHT_OFFSET, NS_MSG_CONT_2_HEIGHT_LEN, &dataChunk); + scanFsmPtr->W2ACQrcvLog.Height = (uint32_t)(dataChunk); + break; + case L2_MSG_SCAN_CONT_3: + FrameGetChunk(scanMsg, NS_MSG_CONT_3_LONGITUDE_OFFSET, NS_MSG_CONT_3_LONGITUDE_LEN, &dataChunk); + scanFsmPtr->W2ACQrcvLog.Longitude = (uint32_t)(dataChunk); + + FrameGetChunk(scanMsg, NS_MSG_CONT_3_LATITUDE_OFFSET, NS_MSG_CONT_3_LATITUDE_LEN, &dataChunk); + scanFsmPtr->W2ACQrcvLog.Latitude = (uint32_t)(dataChunk); + break; + case L2_MSG_SCAN_CONT_4: + break; + case L2_MSG_SCAN_CONT_5: + break; + default: + DBG_ERROR("UNSURPPORTED message type [%d]. \n", intraW2AcqFrameMsgs[i]); + Status = EIGNORE; + goto failed; + } + } + // Update net start time + if(instPtr->myInfo.nodeType != HEAD_NODE){ + instPtr->netStartTime = scanFsmPtr->W2ACQrcvLog.NetScanTime; + } + + if(instPtr->myInfo.nodeType == HEAD_NODE){ + if (IsNodeInList(instPtr->nodeList, scanFsmPtr->W2ACQrcvLog.NodeId) == false) { + AppendNode(instPtr->nodeList, scanFsmPtr->W2ACQrcvLog.NodeId, (uint8_t) MEMBER_NODE); + } + // TODO: Update Node Info + } + + if(instPtr->myInfo.nodeType != HEAD_NODE && scanFsmPtr->W2ACQrcvLog.NetStage != NONE_STATE){ + // sync state with head node + L2_NODE_STATE newState = scanFsmPtr->W2ACQrcvLog.NetStage; + L2_EVENT stateUpEvent = { + .event = L2_EV_MAIN_STATE_UPDATE, + .msg = &newState + }; + AssertL2Event(instPtr, &stateUpEvent); + + // check if net setup finished. + if(L2_GetMainState(instPtr) == INIT_STATE && L2_isCxn2Net(instPtr) == false){ + L2_RTNE_CONFIG newRtneConfig = {0}; + L2_EVENT rtneUpEvent = { + .event = L2_ROUTINE_UPDATE, + .msg = &newRtneConfig + }; + if(scanFsmPtr->W2ACQrcvLog.NetStage == INIT_STATE){ + newRtneConfig.rtneTable = initTable; + newRtneConfig.rtnePrd = ARRAY_SIZE(initTable); + AssertL2Event(instPtr, &rtneUpEvent); + } + else if(scanFsmPtr->W2ACQrcvLog.NetStage == INTRA_SEEK_STATE){ + newRtneConfig.rtneTable = intraSeekTable; + newRtneConfig.rtnePrd = ARRAY_SIZE(intraSeekTable); + AssertL2Event(instPtr, &rtneUpEvent); + } + L2_EVENT netSetupDoneEvent = { + .event = L2_EV_NET_SETUP_DONE, + .msg = NULL + }; + AssertL2Event(instPtr, &netSetupDoneEvent); + } + } + break; + } + default: { + DBG_ERROR("Cannot handler message type [%d] properly.\n", + L2_GetLastRcvFrameType(instPtr)); + Status = EIGNORE; + goto failed; + } + } + bit_array_free(scanMsg); + return SUCCESS; +failed: + bit_array_free(scanMsg); + return Status; +} + +/*****************************************************************************/ +/** + * @brief Initialize ScanNet FSM, allocate memory for FSM instance. + * + * @param scanFsmPtr a pointer to scan net finite state machine + * + * @return SUCCESS Initialization successful. + * EMAC_MEMORY_ALLOC_ERROR Memory allocate error. + * + ******************************************************************************/ +int32_t ScanNet_Init(L2_SCAN_FSM** scanFSMPtr) { + *scanFSMPtr = (L2_SCAN_FSM *) malloc(sizeof(L2_SCAN_FSM)); + if (*scanFSMPtr == NULL) { + DBG_ERROR("Failed to allocate memory for scanFsmPtr.\n"); + return EALLOC; + } + ScanNet_Reset(*scanFSMPtr); + return (SUCCESS); +} + + +/*****************************************************************************/ +/** + * @brief Reset ScanNet FSM + * + * @param scanFsmPtr a pointer to scan net finite state machine + * + * @return NONE + * + ******************************************************************************/ +void ScanNet_Reset(L2_SCAN_FSM* scanFSMPtr) { + ASSERT(scanFSMPtr != NULL); + scanFSMPtr->isLocked = false; + scanFSMPtr->isBmRcved = false; + scanFSMPtr->isAcked = false; + scanFSMPtr->scanStage = NONE_STAGE; + scanFSMPtr->scanMode = INTRA_CLUSTER_MODE; + // FIXME: Only for test + scanFSMPtr->BMrcvLog.Height = 0; + scanFSMPtr->BMrcvLog.Latitude = 0; + scanFSMPtr->BMrcvLog.Longitude = 0; + scanFSMPtr->BMrcvLog.EastSpeed = 0; + scanFSMPtr->BMrcvLog.NorthSpeed = 0; + scanFSMPtr->BMrcvLog.UpperSpeed = 0; + scanFSMPtr->BMrcvLog.frameNum = 0; + scanFSMPtr->BMrcvLog.slotNum = 0; + scanFSMPtr->W2ACQrcvLog.Height = 0; + scanFSMPtr->W2ACQrcvLog.Latitude = 0; + scanFSMPtr->W2ACQrcvLog.Longitude = 0; + scanFSMPtr->W2ACQrcvLog.EastSpeed = 0; + scanFSMPtr->W2ACQrcvLog.NorthSpeed = 0; + scanFSMPtr->W2ACQrcvLog.UpperSpeed = 0; + scanFSMPtr->W2ACQrcvLog.NetStage = NONE_STATE; + scanFSMPtr->W2ACQrcvLog.NetScanTime = 0; +} + +/*****************************************************************************/ +/** + * @brief Destroy ScanNet FSM, free memory + * + * @param scanFsmPtr a pointer to scan net finite state machine + * + * @return NONE + * + ******************************************************************************/ +void ScanNet_Destroy(L2_SCAN_FSM* scanFSMPtr) { + free(scanFSMPtr); +} + +/*****************************************************************************/ +/** + * @brief Execute a member node scan net procedure. + * + * @param instPtr a pointer to linklayer layer instance + * + * @return used slot (5ms slot). + * + ******************************************************************************/ +int32_t ScanNet_Proc(L2_INST* instPtr) { + L2_SCAN_FSM* scanFsmPtr = instPtr->scanNetFSM; + if (instPtr->myInfo.nodeType == HEAD_NODE) { + DBG_ERROR("Only member node needs to execute ScanNet_Proc. \n"); + return NUM_SLOTS_NONE; + } + int32_t Status; + DBG_INFO("-------- ScanNet Process --------\n"); + switch (scanFsmPtr->scanStage) { + case NONE_STAGE: + /* Start Scan. */ + StageUpdate(scanFsmPtr, INIT_SCAN_STAGE); + Status = Scan_InitScanHandler(instPtr); + break; + case INIT_SCAN_STAGE: + Status = Scan_InitScanHandler(instPtr); + break; + case BM_ADVT_STAGE: + Status = Scan_BmAdvtHandler(instPtr); + break; + case WAY2_ACQ_STAGE: + Status = Scan_2WAcqHandler(instPtr); + break; + default: + DBG_ERROR("Unexpected scan net stage: %d.\n", scanFsmPtr->scanStage); + Status = FAILURE; + break; + } + return Status; +} + +/*****************************************************************************/ + +/** + * @brief Execute a scan net Routine procedure. + * + * @param rtneEntry Routine configuration + * + * @return used slot (5ms slot). + * + ******************************************************************************/ +int acqSend = 0; +int32_t ScanNet_Routine(L2_INST* instPtr, const L2_RTNE_TABLE_ENTRY* rtneEntry) { + ASSERT(instPtr != NULL); + L2_TOR_TYPE torState; + int32_t Status; + DBG_INFO("-------- ScanNet Routine --------\n"); + + if(rtneEntry->slotSeq != 0){ + return SQUENCE_SCAN_SLOTS; + } + + if(instPtr->myInfo.nodeType != HEAD_NODE){ + if (rtneEntry->dst0 == instPtr->myInfo.nodeId || rtneEntry->dst0 == BROADCAST_ID){ + torState = L2_TOR_RX; + } + else if (rtneEntry->src0 == instPtr->myInfo.nodeId || rtneEntry->src0 == BROADCAST_ID){ + torState = L2_TOR_TX; + } + else { + torState = L2_TOR_SUSPEND; + } + } + else{ + if (rtneEntry->dst0 == instPtr->myInfo.nodeId){ + torState = L2_TOR_RX; + } + else if (rtneEntry->src0 == instPtr->myInfo.nodeId){ + torState = L2_TOR_TX; + } + else { + torState = L2_TOR_SUSPEND; + } + } + + switch (rtneEntry->slotType) { + case SLOT_INTER_SCAN_ACQ: + // TODO: + L2_SetupNextSlot(instPtr, L2_TOR_SUSPEND, L2_INTER_SCAN_FRAME); + break; + + case SLOT_INTRA_SCAN_ACQ: + if (instPtr->myInfo.nodeType != HEAD_NODE && torState == L2_TOR_TX) { + DBG_ERROR("Only head node can send init-scan Frame.\n"); + Status = FAILURE; + goto routine_err; + } + L2_SetupNextSlot(instPtr, torState, L2_INTRA_SCAN_FRAME); + break; + + case SLOT_INTER_SCAN_BM: + // TODO: + L2_SetupNextSlot(instPtr, L2_TOR_SUSPEND, L2_INTER_BM_FRAME); + break; + + case SLOT_INTRA_SCAN_BM: + if (torState == L2_TOR_TX) { + if (instPtr->myInfo.nodeType != HEAD_NODE) { + DBG_ERROR("Only head node can send BM Frame.\n"); + Status = FAILURE; + goto routine_err; + } + memset(instPtr->sendPktData, 0xAA, INTRA_BM_FRAME_LENGTH_MAX); + if(ScanPkt_Packing(instPtr, SCANPKT_INTRA_BM) != SUCCESS) { + Status = FAILURE; + goto routine_err; + } + } + /* Antenna setting (reserved.) */ + L2_SetupNextSlot(instPtr, L2_TOR_TX, L2_INTRA_BM_FRAME); + break; + case SLOT_INTER_SCAN_2W: + // TODO: + DBG_INFO("#Routine# [Inter Scan-W2_ACQ SUSPEND].\n"); + L2_SetupNextSlot(instPtr, L2_TOR_SUSPEND, L2_INTER_W2_ACQ_FRAME); + break; + case SLOT_INTRA_SCAN_2W: + if (torState == L2_TOR_TX) { + if(instPtr->myInfo.nodeType != HEAD_NODE && L2_isDataAvail(instPtr) == false) { + /* Antenna setting (reserved.) */ + L2_SetupNextSlot(instPtr, L2_TOR_SUSPEND, L2_INTRA_W2_ACQ_FRAME); + break; + } + /* Prepare Request/ACK data. */ + memset(instPtr->sendPktData, 0xAA, (size_t) INTRA_W2ACQ_FRAME_LENGTH_MAX); + /* Pack message words */ + if(ScanPkt_Packing(instPtr, SCANPKT_INTRA_2WACQ) != SUCCESS) { + Status = FAILURE; + goto routine_err; + } + acqSend ++; + } + /* Antenna setting (reserved.) */ + L2_SetupNextSlot(instPtr, torState, L2_INTRA_W2_ACQ_FRAME); + break; + default: + DBG_ERROR("Cannot start a routine for slot type [%d] properly.\n", rtneEntry->slotType); + Status = FAILURE; + goto routine_err; + } + return SUCCESS; +routine_err: + return Status; +} + diff --git a/datalink814_ge/src/linklayer/net_service.c b/datalink814_ge/src/linklayer/net_service.c new file mode 100644 index 0000000..fa99736 --- /dev/null +++ b/datalink814_ge/src/linklayer/net_service.c @@ -0,0 +1,295 @@ +/*****************************************************************************/ +/** + * Description: Implementations for 814 datalink service net. + * Date: 2021-11-16 00:08 + * LastEditors: Fan Hao + * LastEditTime: 2022-07-16 17:04 + * Revisions: Rev 0.1 + * History: + * [2022-07-16]: New branch for DiJian. + * [2021-11-16]: Initial version. + * + * Copyright(c) 2021 Beijing Institute of Technology. + * Lab of Communication and Networking + * + ******************************************************************************/ + +/***************************** Include Files *********************************/ +#include +#include "linklayer814.h" +#include "linklayer814_types.h" +#include "msg_def.h" +#include "../error.h" +#include "../common.h" + + +#ifdef _MPC_CTRL + +#endif + +/************************** Constant Definitions *****************************/ +#define SQUENCE_SVC_SLOTS 0 +#define INER_SVC_SLOTS 2 +#define INRA_SVC_SLOTS 1 +#define NONE_SVC_SLOTS 0 +#define TEST_UDU_PDLEN 16 +#define TEST_UDU_LEN (UDUH_LEN/8 + TEST_UDU_PDLEN + PDU_CRC_LEN/8 ) +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ +#ifdef _MPC_CTRL +#endif + +/**************************** Type Definitions *******************************/ + +/************************** Variable Definitions *****************************/ +#ifdef _MPC_CTRL + +#endif + +/*****************************************************************************/ +/** + * @brief Packing UDU Header to a bit array. + * + * @param bitarr pointer to bit array buffer. + * dst Destination node address. + * dataLen Length of UDU data. + * + * @return EPARAM + * SUCCESS + * + ******************************************************************************/ +static int UduHeader_Packing(L2_INST* instPtr, BIT_ARRAY* bitarr, uint8_t dst, uint32_t dataLen){ + ASSERT(bitarr != NULL); + if(bitarr->num_of_bits < UDUH_LEN){ + return EPARAM; + } + uint64_t dataChunk = 0; + memset(bitarr->words, 0xF0, (size_t)(UDUH_LEN/8)); + // priority + dataChunk = 1; + FrameInsertChunk(bitarr, UDUH_PRI_OFFSET, UDUH_PRI_LEN, dataChunk); + // message type + dataChunk = 2; + FrameInsertChunk(bitarr, UDUH_MSG_TYPE_OFFSET, UDUH_MSG_TYPE_LEN, dataChunk); + // data length + dataChunk = dataLen; + FrameInsertChunk(bitarr, UDUH_LENGTH_OFFSET, UDUH_LENGTH_LEN, dataChunk); + // source node id + dataChunk = (instPtr->myInfo.nodeId & 0x1F)|((instPtr->myInfo.clustId & 0x1F) << 5); + FrameInsertChunk(bitarr, UDUH_SRC_ADDR_OFFSET, UDUH_SRC_ADDR_LEN, dataChunk); + // destination node id + dataChunk = (dst & 0x1F)|((instPtr->myInfo.clustId & 0x1F) << 5); + FrameInsertChunk(bitarr, UDUH_DST_ADDR_OFFSET, UDUH_DST_ADDR_LEN, dataChunk); + // UDU Sequence number + dataChunk = 0; + FrameInsertChunk(bitarr, UDUH_UDU_SEQ_NUM_OFFSET, UDUH_UDU_SEQ_NUM_LEN, dataChunk); + // retransmission times + dataChunk = 0; + FrameInsertChunk(bitarr, UDUH_RETRANS_NUM_OFFSET, UDUH_RETRANS_NUM_LEN, dataChunk); + // number of slice + dataChunk = 1; + FrameInsertChunk(bitarr, UDUH_NUM_SLICE_OFFSET, UDUH_NUM_SLICE_LEN, dataChunk); + // slice id + dataChunk = 1; + FrameInsertChunk(bitarr, UDUH_SLICE_ID_OFFSET, UDUH_SLICE_ID_LEN, dataChunk); + return SUCCESS; +} + +/*****************************************************************************/ +/** + * @brief Packing PDU Header to a bit array. + * + * @param bitarr pointer to bit array buffer. + * headerType PDU header type. + * dst Destination node address. + * + * @return EPARAM + * SUCCESS + * + ******************************************************************************/ +static int PduHeader_Packing(L2_INST* instPtr, BIT_ARRAY* bitarr, L2_PDU_HEADER_TYPE headerType, uint8_t dst){ + ASSERT(bitarr != NULL); + if(headerType < L2_PDU_HEADER_0 || headerType > L2_PDU_HEADER_1){ + return EPARAM; + } + uint64_t dataChunk = 0; + if(headerType == L2_PDU_HEADER_0){ + if(bitarr->num_of_bits < PDUH0_LEN){ + return EPARAM; + } + memset(bitarr->words, 0xF0, (size_t)(PDUH0_LEN/8)); + // PDU type + dataChunk = 0; + FrameInsertChunk(bitarr, PDUH0_TYPE_OFFSET, PDUH0_TYPE_LEN, dataChunk); + // frame length + dataChunk = INTRA_SVC_FRAME_LENGTH_MAX; + FrameInsertChunk(bitarr, PDUH0_LENGTH_OFFSET, PDUH0_LENGTH_LEN, dataChunk); + // source node id + dataChunk = (instPtr->myInfo.nodeId & 0x1F)|((instPtr->myInfo.clustId & 0x1F) << 5); + FrameInsertChunk(bitarr, PDUH0_SRC_ADDR_OFFSET, PDUH0_SRC_ADDR_LEN, dataChunk); + // destination node id + dataChunk = (dst & 0x1F)|((instPtr->myInfo.clustId & 0x1F) << 5); + FrameInsertChunk(bitarr, PDUH0_DST_ADDR_OFFSET, PDUH0_DST_ADDR_LEN, dataChunk); + // Sequence number + dataChunk = 0; + FrameInsertChunk(bitarr, PDUH0_SEQ_NUM_OFFSET, PDUH0_SEQ_NUM_LEN, dataChunk); + // Append CRC + L2_CrcAppend((uint8_t*)bitarr->words, PDUH0_HEADER_CRC_OFFSET/8, PDUH0_HEADER_CRC_OFFSET/8, L2_CRC8_31); + } + else if(headerType == L2_PDU_HEADER_1){ + if(bitarr->num_of_bits < PDUH1_LEN){ + return EPARAM; + } + memset(bitarr->words, 0xF0, (size_t)(PDUH1_LEN/8)); + // PDU type + dataChunk = 1; + FrameInsertChunk(bitarr, PDUH1_TYPE_OFFSET, PDUH1_TYPE_LEN, dataChunk); + // frame length + dataChunk = INTRA_SVC_FRAME_LENGTH_MAX; + FrameInsertChunk(bitarr, PDUH1_LENGTH_OFFSET, PDUH1_LENGTH_LEN, dataChunk); + // source node id + dataChunk = (instPtr->myInfo.nodeId & 0x1F)|((instPtr->myInfo.clustId & 0x1F) << 5); + FrameInsertChunk(bitarr, PDUH1_SRC_ADDR_OFFSET, PDUH1_SRC_ADDR_LEN, dataChunk); + // destination node id + dataChunk = (dst & 0x1F)|((instPtr->myInfo.clustId & 0x1F) << 5); + FrameInsertChunk(bitarr, PDUH1_DST_ADDR_OFFSET, PDUH1_DST_ADDR_LEN, dataChunk); + // Slice tage... + // Append CRC + L2_CrcAppend((uint8_t*)bitarr->words, PDUH1_HEADER_CRC_OFFSET/8, PDUH1_HEADER_CRC_OFFSET/8, L2_CRC8_31); + } + else{ + return FAILURE; + } + return SUCCESS; +} + +/*****************************************************************************/ +/** + * @brief Initialize service net FSM + * + * @param serviceFSM A pointer to service FSM instance. + * + * @return SUCCESS Initialize successfully. + * Other Initialize failed. + * + ******************************************************************************/ +int32_t ServiceNet_Init(L2_SVC_FSM** serviceFSM) { + (*serviceFSM) = (L2_SVC_FSM*) malloc(sizeof(L2_SVC_FSM)); + if (*serviceFSM == NULL) { + return EALLOC; + } + ServiceNet_Reset(*serviceFSM); + return SUCCESS; +} + + +void ServiceNet_Reset(L2_SVC_FSM* serviceFSM) { + serviceFSM->isBisar = false; + serviceFSM->isBisarEven = false; + serviceFSM->bisarDst = NONE_ID; +} + +void ServiceNet_Destroy(L2_SVC_FSM* serviceFSM){ + free(serviceFSM); +} +/*****************************************************************************/ +/** + * @brief Handle service received packet. Send data up to MPC + * + * @param instPtr a pointer to linklayer layer instance + * + * @return SUCCESS message has been successfully handled. + * other error occurred. + * + ******************************************************************************/ +int32_t ServiceNet_PktHandler(L2_INST* instPtr) { + // TODO: + return SUCCESS; +} + +/*****************************************************************************/ +/** + * @brief Service net FSM procedure. + * + * @param instPtr a pointer to linklayer layer instance + * @param rtneEntry + * + * @return Slot has been used. + * + ******************************************************************************/ +int32_t ServiceNet_Routine(L2_INST* instPtr, const L2_RTNE_TABLE_ENTRY* rtneEntry) { + ASSERT(instPtr != NULL); + int32_t Status; + L2_TOR_TYPE torState; + DBG_INFO("-------- ServiceNet Routine --------\n"); + + if(rtneEntry->slotSeq != 0){ + return SQUENCE_SVC_SLOTS; + } + + // Determine TOR State. + if(rtneEntry->src0 == instPtr->myInfo.nodeId){ + torState = L2_TOR_TX; + } + else if(rtneEntry->dst0 == instPtr->myInfo.nodeId){ + torState = L2_TOR_RX; + } + else{ + torState = L2_TOR_SUSPEND; + } + + BIT_ARRAY* svcMsg = bit_array_create(L2_MSG_MAX); + if(svcMsg == NULL){ + DBG_ERROR("Failed to allocate memory for svcMsg.\n"); + return NUM_SLOTS_NONE; + } + memset(instPtr->sendPktData, 0xCC, (size_t)(INTRA_SVC_FRAME_LENGTH_MAX)); + switch(rtneEntry->slotType){ + case SLOT_INTER_SVC: + L2_SetupNextSlot(instPtr, torState, L2_INTER_SVC_FRAME); + break; + case SLOT_INTRA_SVC: + if(torState == L2_TOR_TX){ + //TODO: + memset(instPtr->sendPktData, 0xAA, INTRA_SVC_FRAME_LENGTH_MAX); + // Pack PDU header + if(PduHeader_Packing(instPtr, svcMsg, L2_PDU_HEADER_0, rtneEntry->dst0) != SUCCESS){ + DBG_ERROR("Failed to packing PduHeader.\n"); + Status = FAILURE; + goto routine_err; + } + memcpy(instPtr->sendPktData, svcMsg->words, (size_t)(PDUH0_LEN/8)); + // Pack UDU Header + if(UduHeader_Packing(instPtr, svcMsg, rtneEntry->dst0, + INTRA_SVC_FRAME_LENGTH_MAX-(PDUH0_LEN+MSG_KEY_LENGTH_LEN)/8) + != SUCCESS){ + DBG_ERROR("Failed to packing UduHeader.\n"); + Status = FAILURE; + goto routine_err; + } + memcpy(instPtr->sendPktData + ((PDUH0_LEN+MSG_KEY_LENGTH_LEN)/8), svcMsg->words, (size_t)(UDUH_LEN/8)); + // For ZhiQiang + // Payload Byte3, bit0~2: message class, bit3~7 message subclass + // FIXME: message class tag 0x01, only for test. + memset(instPtr->sendPktData+((PDUH0_LEN+MSG_KEY_LENGTH_LEN+UDUH_LEN)/8) + 3, 0x01, 1); + L2_CrcAppend(instPtr->sendPktData + ((PDUH0_LEN+MSG_KEY_LENGTH_LEN)/8), + INTRA_SVC_FRAME_LENGTH_MAX-(PDUH0_LEN+MSG_KEY_LENGTH_LEN+PDU_CRC_LEN)/8, + INTRA_SVC_FRAME_LENGTH_MAX-(PDUH0_LEN+MSG_KEY_LENGTH_LEN+PDU_CRC_LEN)/8, + L2_CRC16_8005 + ); + } + L2_SetupNextSlot(instPtr, torState, L2_INTRA_SVC_FRAME); + break; + default: + DBG_ERROR("UNKNOWN slot type [%d].\n", rtneEntry->slotType); + DBG_ERROR("Failed to packing PduHeader.\n"); + Status = FAILURE; + goto routine_err; + } + bit_array_free(svcMsg);// free memory + return SUCCESS; +routine_err: + bit_array_free(svcMsg);// free memory + return Status; +} diff --git a/datalink814_ge/src/linklayer/node_list.c b/datalink814_ge/src/linklayer/node_list.c new file mode 100644 index 0000000..1776b72 --- /dev/null +++ b/datalink814_ge/src/linklayer/node_list.c @@ -0,0 +1,477 @@ +/*****************************************************************************/ +/** + * Description: Implementations of 814 linklayer local record. + * + * Date: 2022-07-14 00:08 + * LastEditors: Fan Hao + * LastEditTime: 2022-07-14 22:52 + * Revisions: Rev 0.0 + * History: + * [2022-07-14]: Initial version. + * + * Copyright(c) 2021 Beijing Institute of Technology. + * Lab of Communication and Networking + * + ******************************************************************************/ + +/***************************** Include Files *********************************/ +#include +#include +#include "linklayer814_types.h" +#include "node_list.h" +#include "../common.h" +#include "../error.h" + +/***************** Macros (Inline Functions) Definitions *********************/ +inline int32_t GetNodeNum(NODE_LIST *list) { + ASSERT(list != NULL); + return list->nodeNum; +} +/**************************** Type Definitions *******************************/ + +/************************** Variable Definitions *****************************/ + +/************************** Function Prototypes ******************************/ + +/*****************************************************************************/ +/** + * @brief Initialize node list + * + * @param list + * + * @return SUCCESS + * ENOMEM - not enough memory. + * + ******************************************************************************/ +int32_t NodeList_Init(NODE_LIST **list) { + NODE_ENTRY *entry; + (*list) = malloc(sizeof(NODE_LIST)); + if (*list == NULL) { + return ENOMEM; + } + entry = malloc(sizeof(NODE_ENTRY)); + if(entry == NULL) { + free(*list); + return ENOMEM; + } + entry->nodeInfo.nodeId = 0; + entry->nextNode = entry; + entry->preNode = entry; + (*list)->head = entry; + (*list)->nodeNum = 0; + return SUCCESS; +} + +void NodeList_Clear(NODE_LIST *list){ + ASSERT(list != NULL); + NODE_ENTRY *nodeEntry, *deletEntry; + nodeEntry = list->head->nextNode; + while (nodeEntry != list->head) { + deletEntry = nodeEntry; + nodeEntry = nodeEntry->nextNode; + deletEntry->preNode->nextNode = deletEntry->nextNode; + deletEntry->nextNode->preNode = deletEntry->preNode; + DBG_INFO("Deleting node [%d].\n", deletEntry->nodeInfo.nodeId); + free(deletEntry); + list->nodeNum--; + } +} + +void NodeList_Destroy(NODE_LIST *list){ + if(list == NULL){ + return; + } + NodeList_Clear(list); + free(list->head); + free(list); +} +/*****************************************************************************/ +/** + * @brief Get node entry frome node list base on node id. + * + * @param list + * @param nodeId + * + * @return Node entry + * NULL if node dose not exist. + * + ******************************************************************************/ +NODE_ENTRY* GetNode(NODE_LIST *list, uint32_t nodeId) { + ASSERT(list != NULL); + NODE_ENTRY* nodeEntry = list->head->nextNode; + while (nodeEntry != list->head) { + if (nodeEntry->nodeInfo.nodeId == nodeId) { + break; + } + else { + nodeEntry = nodeEntry->nextNode; + } + } + if (nodeEntry == list->head) { + return NULL; + } + else { + return nodeEntry; + } +} + +/*****************************************************************************/ +/** + * @brief Check whether the node is already in the node list. + * + * @param list + * @param nodeId + * + * @return true node in the list + * false node not in the list + * + ******************************************************************************/ +inline bool IsNodeInList(NODE_LIST *list, uint8_t nodeId) { + ASSERT(list != NULL); + return (GetNode(list, nodeId) != NULL); +} + +/*****************************************************************************/ +/** + * @brief Append a new node entry to the node list + * + * @param list + * @param nodeId + * @param nodeType + * + * @return SUCCESS Node was added successfully. + * Other Error occurred.(Node already exist, memory alloc error ect.) + * + ******************************************************************************/ +int32_t AppendNode(NODE_LIST *list, uint8_t nodeId, L2_NODE_TYPE nodeType) +{ + ASSERT(list != NULL); + if(IsNodeInList(list, nodeId)){ + DBG_WARNING("Node [%d] already exist.\n", nodeId); + return FAILURE; + } + DBG_INFO("Link layer appending node [%d] to node list.\n", nodeId); + NODE_ENTRY* nodeEntry = (NODE_ENTRY*) malloc(sizeof(NODE_ENTRY)); + if (nodeEntry == NULL) { + return ENOMEM; + } + nodeEntry->nodeInfo.nodeId = nodeId; + nodeEntry->nodeInfo.nodeType = (uint8_t) nodeType; + nodeEntry->nodeInfo.pos.x = 0; + nodeEntry->nodeInfo.pos.y = 0; + nodeEntry->nodeInfo.pos.z = 0; + nodeEntry->nodeInfo.speed.x = 0; + nodeEntry->nodeInfo.speed.y = 0; + nodeEntry->nodeInfo.speed.z = 0; + nodeEntry->nodeInfo.beamNo = 0; + nodeEntry->ttlCnt = 0; + + nodeEntry->nextNode = list->head; + nodeEntry->preNode = list->head->nextNode; + list->head->nextNode = nodeEntry; + + list->nodeNum++; + return SUCCESS; +} + +/*****************************************************************************/ +/** + * @brief Delete a node in list based on node id. + * + * @param list + * @param nodeId + * + * @return SUCCESS Node has been successfully deleted. + * Other Node not exist. + * + ******************************************************************************/ +int32_t DeletNode(NODE_LIST *list, uint8_t nodeId) { + ASSERT(list != NULL); + NODE_ENTRY* nodeEntry = GetNode(list, nodeId); + if(nodeEntry == NULL){ + DBG_WARNING("Node [%d] in not in node list, skip deleting process.\n", nodeId); + return SUCCESS; + } + nodeEntry->preNode->nextNode = nodeEntry->nextNode; + nodeEntry->nextNode->preNode = nodeEntry->preNode; + DBG_INFO("Deleting node [%d].\n", nodeId); + free(nodeEntry); + list->nodeNum--; + return SUCCESS; +} + + +/*****************************************************************************/ +/** + * @brief Get the distance between me and the node. + * + * @param list + * @param nodeId + * @param dst A pointer to store distance. + * + * @return SUCCESS distance has been successfully store in dst + * FAILURE Node dose not exit. + * + ******************************************************************************/ + +int32_t GetDistance(NODE_LIST *list, COORD myCoord, uint8_t nodeId, double* dst) { + ASSERT(list != NULL); + NODE_ENTRY* nodeEntry = GetNode(list, nodeId); + if (nodeEntry == NULL) { + return FAILURE; + } + else { + *dst = Coord_Distance(myCoord, nodeEntry->nodeInfo.pos); + return SUCCESS; + } +} + +/*****************************************************************************/ +/** + * @brief Update node positions information. + * + * @param list + * @param nodeId + * @param newPos A structure stores the corresponding node position info. + * + * @return SUCCESS update successfully. + * FAILURE node not exist. + * + ******************************************************************************/ +int32_t UpdateNodePos(NODE_LIST *list, uint8_t nodeId, const COORD *newPos) { + ASSERT(list != NULL); + NODE_ENTRY* nodeEntry = GetNode(list, nodeId); + if (nodeEntry == NULL) { + return FAILURE; + } + else { + memcpy(&(nodeEntry->nodeInfo.pos), newPos, sizeof(COORD)); + } + return SUCCESS; +} + + +/*****************************************************************************/ +/** + * @brief Get node positions information. + * + * @param list + * @param nodeId + * @param newPos A structure stores the corresponding node position info. + * + * @return SUCCESS update successfully. + * FAILURE node not exist. + * + ******************************************************************************/ +int32_t GetNodePos(NODE_LIST *list, uint8_t nodeId, COORD *pos) { + ASSERT(list != NULL); + NODE_ENTRY* nodeEntry = GetNode(list, nodeId); + if (nodeEntry == NULL) { + return FAILURE; + } + else { + memcpy(pos, &(nodeEntry->nodeInfo.pos), sizeof(COORD)); + } + return SUCCESS; +} + +/*****************************************************************************/ +/** + * @brief Update node speed information. + * + * @param list + * @param nodeId + * @param newSpeed A structure stores the corresponding node speed info. + * + * @return SUCCESS update successfully. + * FAILURE node not exist. + * + ******************************************************************************/ +int32_t UpdateNodeSpeed(NODE_LIST *list, uint8_t nodeId, const COORD *newSpeed) { + ASSERT(list != NULL); + NODE_ENTRY* nodeEntry = GetNode(list, nodeId); + if (nodeEntry == NULL) { + return FAILURE; + } + else { + memcpy(&(nodeEntry->nodeInfo.speed), newSpeed, sizeof(COORD)); + } + return SUCCESS; +} + + +/*****************************************************************************/ +/** + * @brief Get node speed information. + * + * @param list + * @param nodeId + * @param newSpeed A structure stores the corresponding node speed info. + * + * @return SUCCESS update successfully. + * FAILURE node not exist. + * + ******************************************************************************/ +int32_t GetNodeSpeed(NODE_LIST *list, uint8_t nodeId, COORD *speed) { + ASSERT(list != NULL); + NODE_ENTRY* nodeEntry = GetNode(list, nodeId); + if (nodeEntry == NULL) { + return FAILURE; + } + else { + memcpy(speed, &(nodeEntry->nodeInfo.speed), sizeof(COORD)); + } + return SUCCESS; +} +/*****************************************************************************/ +/** + * @brief Update node ACK status. + * + * @param list + * @param nodeId + * @param defl + * + * @return SUCCESS update successfully. + * FAILURE Node not exist. + * + ******************************************************************************/ +int32_t UpdateNodeTimeDeviation(NODE_LIST *list, uint8_t nodeId, int32_t devi) { + ASSERT(list != NULL); + NODE_ENTRY* nodeEntry = GetNode(list, nodeId); + if (nodeEntry == NULL) { + return FAILURE; + } + else { + nodeEntry->timeDevi = devi; + } + return SUCCESS; +} + +/*****************************************************************************/ +/** + * @brief Increase TTL of specified node in the list. + * + * @param list + * @param inc cnt of slot to add + * @param nodeId + * + * @return NONE + * + ******************************************************************************/ +int32_t IncNodeTTL(NODE_LIST *list, uint8_t nodeId, uint32_t inc) { + ASSERT(list != NULL); + NODE_ENTRY* nodeEntry = GetNode(list, nodeId); + if (nodeEntry == NULL) { + return FAILURE; + } + else { + nodeEntry->ttlCnt += inc; + } + return SUCCESS; +} + +/*****************************************************************************/ +/** + * @brief Reset node TTL based on node id. + * + * @param list + * @param nodeId + * + * @return SUCCESS TTL has been successfully cleared. + * FAILURE Node not exist. + * + ******************************************************************************/ +int32_t RstNodeTTL(NODE_LIST *list, uint8_t nodeId) { + ASSERT(list != NULL); + NODE_ENTRY* nodeEntry = GetNode(list, nodeId); + if (nodeEntry == NULL) { + return FAILURE; + } + else { + nodeEntry->ttlCnt = 0; + } + return SUCCESS; +} + +/*****************************************************************************/ +/** + * @brief Get TTL of specified node in the list. + * + * @param list + * @param nodeId + * @param ttl + * + * @return NONE + * + ******************************************************************************/ +int32_t GetNodeTTL(NODE_LIST *list, uint8_t nodeId, uint32_t *ttl) { + ASSERT(list != NULL); + NODE_ENTRY* nodeEntry = GetNode(list, nodeId); + if (nodeEntry == NULL) { + return FAILURE; + } + else { + *ttl = nodeEntry->ttlCnt; + } + return SUCCESS; +} + +/*****************************************************************************/ +/** + * @brief Implements a edit operations to each node. + * + * @param list + * @param param + * @param operation A pointer to a function handled "NODE_ENTRY*" as input + * which defines the operations need to be apply. + * + * @return SUCCESS Operations has been applied successfully to all nodes. + * Other Error occurred. + * + ******************************************************************************/ +int32_t IterEditNode(NODE_LIST *list, const void *param, int32_t (*operation)(NODE_ENTRY *, const void *)) { + ASSERT(list != NULL); + int32_t Status = SUCCESS; + NODE_ENTRY *nodeEntry = list->head->nextNode; + while (nodeEntry != list->head) { + Status = operation(nodeEntry, param); + if(Status != SUCCESS){ + break; + } + nodeEntry = nodeEntry->nextNode; + } + return Status; +} + +/*****************************************************************************/ +/** + * @brief Filter all node, delete all the node not satisfied the condition. + * + * @param list + * @param condition A pointer to a function handled "NODE_ENTRY*" as input + * which defines the condition need to be verify. + * + * @return SUCCESS + * + ******************************************************************************/ +int32_t IterDeleteNode(NODE_LIST *list, bool (*condition)(NODE_ENTRY *)) { + ASSERT(list != NULL); + NODE_ENTRY *nodeEntry, *deletEntry; + nodeEntry = list->head->nextNode; + while (nodeEntry != list->head) { + if (condition(nodeEntry) == false) { + deletEntry = nodeEntry; + nodeEntry = nodeEntry->nextNode; + deletEntry->preNode->nextNode = deletEntry->nextNode; + deletEntry->nextNode->preNode = deletEntry->preNode; + DBG_INFO("Deleting node [%d].\n", deletEntry->nodeInfo.nodeId); + free(deletEntry); + list->nodeNum--; + } + else { + nodeEntry = nodeEntry->nextNode; + } + } + return SUCCESS; +} + diff --git a/datalink814_ge/src/linklayer/node_list.h b/datalink814_ge/src/linklayer/node_list.h new file mode 100644 index 0000000..8aaa367 --- /dev/null +++ b/datalink814_ge/src/linklayer/node_list.h @@ -0,0 +1,67 @@ +/*****************************************************************************/ +/** + * Description: Header of 814 linklayer local record. + * + * Date: 2022-07-14 00:08 + * LastEditors: Fan Hao + * LastEditTime: 2022-07-14 22:52 + * Revisions: Rev 0.0 + * History: + * [2022-07-14]: Initial version. + * + * Copyright(c) 2021 Beijing Institute of Technology. + * Lab of Communication and Networking + * + ******************************************************************************/ + +/***************************** Include Files *********************************/ +#ifndef NODE_LIST_H_ +#define NODE_LIST_H_ +#include +#include +#include +#include +#include "linklayer814_types.h" +#include "geometry/coord.h" +#include "../util/util.h" + +/************************** Constant Definitions *****************************/ +/***************** Macros (Inline Functions) Definitions *********************/ +/**************************** Type Definitions *******************************/ +typedef struct NODE_LIST_ENTRY { + L2_NODE_INFO nodeInfo; + uint32_t ttlCnt; + int32_t timeDevi; + struct NODE_LIST_ENTRY *nextNode; + struct NODE_LIST_ENTRY *preNode; +} NODE_ENTRY; + +typedef struct { + uint32_t nodeNum; + NODE_ENTRY *head; +} NODE_LIST; + +/************************** Variable Definitions *****************************/ + +/************************** Function Prototypes ******************************/ +int32_t NodeList_Init(NODE_LIST **list); +void NodeList_Clear(NODE_LIST *list); +void NodeList_Destroy(NODE_LIST *list); +NODE_ENTRY *GetNode(NODE_LIST *list, uint32_t nodeId); +int32_t AppendNode(NODE_LIST *list, uint8_t nodeId, L2_NODE_TYPE nodeType); +int32_t DeletNode(NODE_LIST *list, uint8_t nodeId); +int32_t UpdateNodePos(NODE_LIST *list, uint8_t nodeId, const COORD *newPos); +int32_t GetNodePos(NODE_LIST *list, uint8_t nodeId, COORD *newPos); +int32_t UpdateNodeSpeed(NODE_LIST *list, uint8_t nodeId, const COORD *newSpeed); +int32_t GetNodeSpeed(NODE_LIST *list, uint8_t nodeId, COORD *speed); +int32_t UpdateNodeTimeDeviation(NODE_LIST *list, uint8_t nodeId, int32_t devi); +int32_t GetDistance(NODE_LIST *list, COORD myCoord, uint8_t nodeId, double* dst); +int32_t GetNodeNum(NODE_LIST *list); +int32_t RstNodeTTL(NODE_LIST *list, uint8_t nodeId); +int32_t IncNodeTTL(NODE_LIST *list, uint8_t nodeId, uint32_t inc); +int32_t GetNodeTTL(NODE_LIST *list, uint8_t nodeId, uint32_t *ttl); +bool IsNodeInList(NODE_LIST *list, uint8_t nodeId); +int32_t IterEditNode(NODE_LIST *list, const void *param, int32_t (*operation)(NODE_ENTRY*, const void*)); +int32_t IterDeleteNode(NODE_LIST *list, bool (*condition)(NODE_ENTRY *)); + +#endif /* NODE_LIST_H_ */ diff --git a/datalink814_ge/src/linklayer/rtt.h b/datalink814_ge/src/linklayer/rtt.h new file mode 100644 index 0000000..9943b6e --- /dev/null +++ b/datalink814_ge/src/linklayer/rtt.h @@ -0,0 +1,102 @@ +/*****************************************************************************/ +/** + * Description: A simplified version of timesync for datalink 814 (Dijian) + * + * Date: 2021-12-04 16:32 + * LastEditors: Fan Hao + * LastEditTime: 2022-07-06 16:32 + * Revisions: Rev 0.0 + * History: + * [2022-07-06]: Initial version. + * [2021-12-04]: Initial version. + * + * Copyright(c) 2021 Beijing Institute of Technology. + * Lab of Communication and Networking + * + ******************************************************************************/ + +#ifndef RTT_H_ +#define RTT_H_ + +/***************************** Include Files *********************************/ +#include +#include "linklayer814.h" +#include "linklayer814_types.h" + +/************************** Constant Definitions *****************************/ +#define MAX_FREQ_EST_NUM 128 // 32bit word +#define SVC_FREQ_EST_NUM 512 // byte +#define MGMT_FREQ_EST_NUM 512 // byte +#define BISAR_FREQ_EST_NUM 480 // byte + +#define CXR_FREQ 3800000000.0 // Hz + +#define LIGHT_SPPED_AIR 299702547.0 // m/s +#define LIGHT_SPPED_VAC 299792458.0 // m/s + +#define RCV2FSYNC_CLOCKS 0 // clocks from frame sync time to receive time +#define PHYRSP_DELAY_CLOCKS 0// clocks from frame sync time to receive time +//#define PHY_SYNCT2FEND_200K 904052L +//#define PHY_SYNCT2FEND_200K 924232L +#define PHY_SYNCT2FEND_200K 905052L + +#define RTT_TIME_NONE UINT32_MAX +#define RTT_DOPPLER_NONE UINT32_MAX + + +/***************** Macros (Inline Functions) Definitions *********************/ + +/**************************** Type Definitions *******************************/ + +// TODO: Multi-node RTT +typedef struct { + L2_TIME_WORD Tt1; + L2_TIME_WORD Tr1; + L2_TIME_WORD Tt2; + L2_TIME_WORD Tr2; + L2_TIME_WORD Tt3; + L2_TIME_WORD Tr3; + L2_TIME_WORD Tt4; + L2_TIME_WORD Tr4; + int32_t dopplerR1; + int32_t dopplerR2; + int32_t dopplerR3; + int32_t dopplerR4; + L2_TIME_WORD TroundA; + L2_TIME_WORD TreplyA; + L2_TIME_WORD TroundB; + L2_TIME_WORD TreplyB; + int32_t rttAdj; +} RTT_RECORD; + +typedef enum { + RTT_NONE_STAGE = 0, + RTT_REQ1 = 1, + RTT_RSP1 = 2, + RTT_REQ2 = 3, + RTT_RSP2 = 4, // Rtt Stages +} L2_RTT_SATGE; + +typedef struct { + L2_RCD rttStatge; + bool isR1Valid; + bool isR2Valid; + bool isR3Valid; + bool isR4Valid; + RTT_RECORD rttRecord; +} L2_RTT_FSM; + +typedef enum { + RTT_NONE = 0, + RTT_SEND = 1, + RTT_RCV = 2, +} L2_RTT_TOR; + +/************************** Function Prototypes ******************************/ + +// RTT +L2_RTT_SATGE RTT_GetLastStage(L2_RTT_FSM* rttFsmPtr); +L2_RTT_SATGE RTT_GetCurrentStage(L2_RTT_FSM* rttFsmPtr); +L2_RTT_SATGE RTT_GetNextStage(L2_RTT_FSM* rttFsmPtr); + +#endif /* RTT_H_ */ diff --git a/datalink814_ge/src/linklayer/time_sync.c b/datalink814_ge/src/linklayer/time_sync.c new file mode 100644 index 0000000..3f677b2 --- /dev/null +++ b/datalink814_ge/src/linklayer/time_sync.c @@ -0,0 +1,523 @@ +/*****************************************************************************/ +/** + * Description: Time sync implementation file. + * + * Author: Author's name + * Date: 2021-12-04 16:32 + * LastEditors: FanHao + * LastEditTime: 2022-07-10 20:43 + * Revisions: Rev 0.0 + * History: + * [2022-07-10]: New branch for Dijian. + * [2021-12-04]: Initial version. + * + * Copyright(c) 2021 Beijing Institute of Technology. + * Lab of Communication and Networking + * + ******************************************************************************/ + +/***************************** Include Files *********************************/ +#include +#include +#include "linklayer814.h" +#include "rtt.h" +#include "../time_ctrl/time_ctrl.h" +#include "../error.h" +#include "../common.h" + +/************************** Constant Definitions *****************************/ +/***************** Macros (Inline Functions) Definitions *********************/ +/**************************** Type Definitions *******************************/ +/************************** Variable Definitions *****************************/ +/************************** Function Prototypes ******************************/ + +static void RTT_StageUpdate(L2_RTT_FSM* rttFsmPtr, L2_RTT_SATGE newSatge); +static void RTT_ResetRecord(RTT_RECORD* recordPtr); +static int32_t RTT_GetCounter10nsDeviation(PHY_INST *phyRef); + + +/*****************************************************************************/ +/** + * @brief a slot alignment, base on physical layer information. + * + * @param instPtr a pointer to linklayer layer instance + * @param frameNum + * @param slotNum + * + * @return SUCCESS Initialize successfully. + * FAILURE Initialization failed, allocate memory fail or initial + * bram controller fail. + * + ******************************************************************************/ +// TODO: Check +int32_t L2_TimeAlign(L2_INST* instPtr, uint32_t frameNum, uint32_t slotNum){ + L1_FRAME_TYPE lastRecvdFrame; + lastRecvdFrame = Phy_GetLastRecvFrameType(instPtr->config.phyInstPtr); + if(lastRecvdFrame != L1_NONE_FRAME){ + return EIGNORE; + } + + // read nextSendTime from physical layer + uint64_t currTime, expctTime; + int64_t timeDiff; + TIME_WORD timeStamp, slotTimerAdjmet; + expctTime = ((uint64_t)(frameNum*L2_SLOTS_PER_FRAME + slotNum))*COUNTE_FRAC_MAX; + expctTime += Phy_GetTimeComp(lastRecvdFrame); + + Phy_GetFrameSyncTimeStamp(instPtr->config.phyInstPtr, &timeStamp); + currTime = (uint64_t)timeStamp.frac_part; + currTime += ((uint64_t)timeStamp.int_part) * COUNTE_FRAC_MAX; + + timeDiff = (int64_t)(expctTime - currTime); + + slotTimerAdjmet.int_part = (uint32_t)(timeDiff/COUNTE_FRAC_MAX); + slotTimerAdjmet.frac_part = (uint32_t)(timeDiff%COUNTE_FRAC_MAX); + TimeCtrl_TimeAdjust(instPtr->config.tmcInstPtr, &slotTimerAdjmet, TM_ADJ_ADD); + return SUCCESS; +} + +/** + * @brief Get last RTT stage of a specified RTT descriptor. + */ +inline L2_RTT_SATGE RTT_GetLastStage(L2_RTT_FSM* rttFsmPtr){ + ASSERT(rttFsmPtr != NULL); + return rttFsmPtr->rttStatge.last; +} +/** + * @brief Get current RTT stage of a specified RTT descriptor. + */ +inline L2_RTT_SATGE RTT_GetCurrentStage(L2_RTT_FSM* rttFsmPtr){ + ASSERT(rttFsmPtr != NULL); + return rttFsmPtr->rttStatge.curr; +} +/** + * @brief Get next RTT stage of a specified RTT descriptor. + */ +inline L2_RTT_SATGE RTT_GetNextStage(L2_RTT_FSM* rttFsmPtr){ + ASSERT(rttFsmPtr != NULL); + return rttFsmPtr->rttStatge.next; +} +/** + * @brief Get next RTT stage of a specified RTT descriptor. + */ +static inline void RTT_ResetRecord(RTT_RECORD* recordPtr){ + ASSERT(recordPtr != NULL); + memset(recordPtr, 0x00, sizeof(RTT_RECORD)); + return; +} + +/*****************************************************************************/ +/** + * @brief Update corrent time-sync for RTT stage + * + * @param scanFsmPtr A pointer to scan net fsm. + * newSatge New state. + * + * @return NONE. + * + ******************************************************************************/ +static void RTT_StageUpdate(L2_RTT_FSM* rttFsmPtr, L2_RTT_SATGE newSatge) { + ASSERT(rttFsmPtr != NULL); + ASSERT(newSatge >= RTT_NONE_STAGE && newSatge <= RTT_RSP2); + DBG_INFO("RTT current Stage: %u -> RTT new Stage: %u, Stage: arranged.%d.\n", + rttFsmPtr->rttStatge.curr, rttFsmPtr->rttStatge.next, newSatge); + L2_RcdShift(&(rttFsmPtr->rttStatge), newSatge); + return; +} + +/*****************************************************************************/ +/** + * @brief Reset RTT systerm . + * + * @param rttFsmPtr + * + * @return SUCCESS Initialization successful. + * EMAC_MEMORY_ALLOC_ERROR Memory allocate error. + * + ******************************************************************************/ +void RTT_Reset(L2_RTT_FSM* rttFsmPtr){ + ASSERT(rttFsmPtr != NULL); + RTT_ResetRecord(&(rttFsmPtr->rttRecord)); + rttFsmPtr->rttStatge.last = RTT_NONE_STAGE; + rttFsmPtr->rttStatge.curr = RTT_NONE_STAGE; + rttFsmPtr->rttStatge.next = RTT_NONE_STAGE; + rttFsmPtr->isR1Valid = false; + rttFsmPtr->isR2Valid = false; + rttFsmPtr->isR3Valid = false; + rttFsmPtr->isR4Valid = false; +} + +void RTT_Destroy(L2_RTT_FSM* rttFsmPtr){ + free(rttFsmPtr); +} + + +static int32_t RTT_GetCounter10nsDeviation(PHY_INST *phyRef) { + TIME_WORD timeStamp; + int64_t lastFrameSyncT, lastSlotStartT; + Phy_GetFrameSyncTimeStamp(phyRef, &timeStamp); + lastFrameSyncT = (uint64_t) timeStamp.frac_part; + lastFrameSyncT += ((uint64_t)timeStamp.int_part) * COUNTE_FRAC_MAX; + Phy_GetLastSlotStartTimeStamp(phyRef, &timeStamp); + lastSlotStartT = (uint64_t) timeStamp.frac_part; + lastSlotStartT += ((uint64_t)timeStamp.int_part) * COUNTE_FRAC_MAX; + return (PHY_SYNCT2FEND_200K - (lastSlotStartT - lastFrameSyncT)); +} + +/*****************************************************************************/ +/** + * @brief Initialize RTT FSM, allocate memory for FSM instance. + * + * @param rttFsmPtr + * + * @return SUCCESS Initialization successful. + * EMAC_MEMORY_ALLOC_ERROR Memory allocate error. + * + ******************************************************************************/ +int32_t RTT_Init(L2_RTT_FSM** rttFsmPtr){ + (*rttFsmPtr) = (L2_RTT_FSM*) malloc(sizeof(L2_RTT_FSM)); + if (*rttFsmPtr == NULL) { + free(*rttFsmPtr); + return EALLOC; + } + RTT_Reset(*rttFsmPtr); + return SUCCESS; +} + +/*****************************************************************************/ +/** + * @brief Execute a Time-Sync Process. + * + * @param instPtr a pointer to linklayer layer instance + * + * @return SUCCESS Time-Sync Process Done. + * FAILURE Time-Sync Process end with error. + * + ******************************************************************************/ +int32_t RTT_Proc(L2_INST* instPtr) { + ASSERT(instPtr != NULL); + L2_RTT_FSM* rttFsmPtr = L2_GetRttDesc(instPtr); + RTT_RECORD* rttRecord = &(rttFsmPtr->rttRecord); + PHY_INST *phyRef = instPtr->config.phyInstPtr; + int32_t Status = SUCCESS; + L2_RTT_TOR lastTor, nextTor; + if(instPtr->rtneConfig.last != NULL && instPtr->rtneConfig.last->slotType == SLOT_INTRA_TSYNC){ + // Get last tor state + if(instPtr->rtneConfig.last->src0 == instPtr->myInfo.nodeId){ + lastTor = RTT_SEND; + } + else if(instPtr->rtneConfig.last->dst0 == instPtr->myInfo.nodeId){ + lastTor = RTT_RCV; + } + else{ + lastTor = RTT_NONE; + } + } + else{ + lastTor = RTT_NONE; + } + + if(instPtr->rtneConfig.next != NULL && instPtr->rtneConfig.next->slotType == SLOT_INTRA_TSYNC){ + // Get next tor state + if(instPtr->rtneConfig.next->src0 == instPtr->myInfo.nodeId){ + nextTor = RTT_SEND; + } + else if(instPtr->rtneConfig.next->dst0 == instPtr->myInfo.nodeId){ + nextTor = RTT_RCV; + } + else{ + nextTor = RTT_NONE; + } + } + else{ + nextTor = RTT_NONE; + } + + DBG_INFO("-------- RTT Procedure --------\n"); + // Stage trans + // For Head Node: Tx->Rx->Tx->Rx + if(instPtr->myInfo.nodeType == HEAD_NODE){ + switch(rttFsmPtr->rttStatge.next) { + case RTT_NONE_STAGE : + DBG_INFO("RTT procedure start...\n"); + // TODO +// RTT_ResetRecord(rttRecord); + RTT_StageUpdate(rttFsmPtr, RTT_REQ1); + break; + case RTT_REQ1 : + if(nextTor == RTT_SEND){ + DBG_INFO("Prepare data for RTT REQ-1\n"); + rttRecord->Tt1.timeH = L2_GetNextFrameNum(instPtr)*L2_SLOTS_PER_FRAME + L2_GetNextSlotNum(instPtr); + rttRecord->Tt1.timeL = 0 ; + DBG_INFO("Tt1-timeL:%u.\n", rttRecord->Tt1.timeL); + DBG_INFO("Tt1-timeH:%u.\n", rttRecord->Tt1.timeH); + RTT_StageUpdate(rttFsmPtr, RTT_RSP1); + } + else{ + DBG_INFO("Skip RTT slot, [Stage: %u].\n", rttFsmPtr->rttStatge.next); + } + break; + case RTT_RSP1 : + if(lastTor == RTT_RCV){ + if(L2_isDataAvail(instPtr) == true){ + DBG_INFO("RTT RSP-1 have been received.\n"); + DBG_INFO("Preparing data for RTT REQ-2.\n"); + rttFsmPtr->isR2Valid = true; + // Calculate doppler + double doppler = Phy_GetCoarseFreqEst(phyRef); + rttRecord->dopplerR2 = (int32_t)doppler; + DBG_INFO("rttRecord->dopplerR2: %u.\n", rttRecord->dopplerR2); + + // Calculate last frame receive time. + int32_t counter10ns = RTT_GetCounter10nsDeviation(phyRef); + // response for rtt Adj + counter10ns += 10000; + counter10ns -= rttRecord->rttAdj; + if ( counter10ns < 0) { + counter10ns += COUNTE_FRAC_MAX; + rttRecord->Tr2.timeH -- ; + _nop_(); + } + rttRecord->Tr2.timeH = L2_GetLastFrameNum(instPtr)*L2_SLOTS_PER_FRAME + L2_GetLastSlotNum(instPtr); + rttRecord->Tr2.timeL = (uint32_t)counter10ns; + DBG_INFO("Tr2-timeL:%u.\n", rttRecord->Tr2.timeL); + DBG_INFO("Tr2-timeH:%u.\n", rttRecord->Tr2.timeH); + + // Calculate TroundA + rttRecord->TroundA.timeL = rttRecord->Tr2.timeL; + rttRecord->TroundA.timeH = rttRecord->Tr2.timeH - rttRecord->Tt1.timeH; + DBG_INFO("TroundA-timeL:%u.\n", rttRecord->TroundA.timeL); + DBG_INFO("TroundA-timeH:%u.\n", rttRecord->TroundA.timeH); + } + else{ + rttFsmPtr->isR2Valid = false; + rttRecord->dopplerR2 = RTT_DOPPLER_NONE; + rttRecord->TroundA.timeL = RTT_TIME_NONE; + rttRecord->TroundA.timeH = RTT_TIME_NONE; + DBG_WARNING("RTT RSP-1 have not been received [Stage: %u].\n", rttFsmPtr->rttStatge.next); + DBG_WARNING("Set dopplerR2 and TroundA to dummy value.\n"); + DBG_INFO("dopplerR2:%08X.\n", rttRecord->dopplerR2); + DBG_INFO("TroundA-timeL:%08X.\n", rttRecord->TroundA.timeL); + DBG_INFO("TroundA-timeH:%08X.\n", rttRecord->TroundA.timeH); + } + RTT_StageUpdate(rttFsmPtr, RTT_REQ2); + } + else{ + DBG_INFO("Skip RTT slot, [Stage: %u].\n", rttFsmPtr->rttStatge.next); + } + break; + case RTT_REQ2 : + if(nextTor == RTT_SEND){ + DBG_INFO("Prepare data for RTT REQ-2\n"); + rttRecord->Tt3.timeH = L2_GetNextFrameNum(instPtr)*L2_SLOTS_PER_FRAME + L2_GetNextSlotNum(instPtr); + rttRecord->Tt3.timeL = 0 ; + DBG_INFO("Tt3-timeL:%u.\n", rttRecord->Tt3.timeL); + DBG_INFO("Tt3-timeH:%u.\n", rttRecord->Tt3.timeH); + + if ( rttFsmPtr->isR2Valid ) { + // Calculate reply A + rttRecord->TreplyA.timeL = COUNTE_FRAC_MAX - rttRecord->Tr2.timeL; + rttRecord->TreplyA.timeH = rttRecord->Tt3.timeH - rttRecord->Tr2.timeH - 1; + DBG_INFO("TreplyA-timeL:%u.\n", rttRecord->TreplyA.timeL); + DBG_INFO("TreplyA-timeH:%u.\n", rttRecord->TreplyA.timeH); + } + else { + rttRecord->TreplyA.timeL = RTT_TIME_NONE; + rttRecord->TreplyA.timeH = RTT_TIME_NONE; + DBG_WARNING("RTT RSP-1 have not been received [Stage: %u].\n", rttFsmPtr->rttStatge.next); + DBG_WARNING("Set TreplyA to dummy value.\n"); + DBG_INFO("TreplyA-timeL:%08X.\n", rttRecord->TreplyA.timeL); + DBG_INFO("TreplyA-timeH:%08X.\n", rttRecord->TreplyA.timeH); + } + RTT_StageUpdate(rttFsmPtr, RTT_RSP2); + } + else{ + DBG_INFO("Skip RTT slot, [Stage: %u].\n", rttFsmPtr->rttStatge.next); + } + break; + case RTT_RSP2 : + if(lastTor == RTT_RCV){ + if(L2_isDataAvail(instPtr) == true){ + DBG_INFO("RTT RSP-2 have been received.\n"); + rttFsmPtr->isR4Valid = true; + // Calculate doppler + double doppler = Phy_GetCoarseFreqEst(phyRef); + rttRecord->dopplerR2 = (int32_t)doppler; + DBG_INFO("rttRecord->dopplerR2: %d.\n", rttRecord->dopplerR2); + + // Calculate last frame receive time. + int32_t counter10ns = RTT_GetCounter10nsDeviation(phyRef); + if ( counter10ns < 0) { + counter10ns += COUNTE_FRAC_MAX; + rttRecord->Tr4.timeH -- ; + } + rttRecord->Tr2.timeH = L2_GetLastFrameNum(instPtr)*L2_SLOTS_PER_FRAME + L2_GetLastSlotNum(instPtr); + // Get a cnt with clk of 192MHz + rttRecord->Tr4.timeL = (uint32_t)counter10ns; + DBG_INFO("Tr4-timeL:%u.\n", rttRecord->Tr4.timeL); + DBG_INFO("Tr4-timeH:%u.\n", rttRecord->Tr4.timeH); + } + else{ + rttFsmPtr->isR4Valid = false; + rttRecord->Tr4.timeL = RTT_TIME_NONE; + rttRecord->Tr4.timeH = RTT_TIME_NONE; + DBG_WARNING("RTT RSP-2 have not been received [Stage: %u].\n", rttFsmPtr->rttStatge.next); + DBG_WARNING("Set Tr4 to dummy value.\n"); + DBG_INFO("Tr4-timeL:%08X.\n", rttRecord->Tr4.timeL); + DBG_INFO("Tr4-timeH:%08X.\n", rttRecord->Tr4.timeH); + } + RTT_StageUpdate(rttFsmPtr, RTT_NONE_STAGE); + DBG_INFO("RTT procedure end...\n"); + } + break; + default : + break; + } + } + // For Member Node: Rx->Tx->Rx->Tx + else{ + switch (rttFsmPtr->rttStatge.next) { + case RTT_NONE_STAGE : + DBG_INFO("RTT procedure start...\n"); + // TODO +// RTT_ResetRecord(rttRecord); + RTT_StageUpdate(rttFsmPtr, RTT_REQ1); + break; + case RTT_REQ1 : + if(lastTor == RTT_RCV){ + if(L2_isDataAvail(instPtr) == true){ + DBG_INFO("RTT REQ-1 have been received.\n"); + DBG_INFO("Preparing data for RTT RSP-1.\n"); + rttFsmPtr->isR2Valid = true; + // Calculate doppler + double doppler = Phy_GetCoarseFreqEst(phyRef); + rttRecord->dopplerR2 = (int32_t)doppler; + DBG_INFO("rttRecord->dopplerR2: %d.\n", rttRecord->dopplerR2); + + // Calculate last frame receive time. + int32_t counter10ns = RTT_GetCounter10nsDeviation(phyRef); + if ( counter10ns < 0) { + counter10ns += COUNTE_FRAC_MAX; + rttRecord->Tr1.timeH -- ; + } + rttRecord->Tr1.timeH = L2_GetLastFrameNum(instPtr)*L2_SLOTS_PER_FRAME + L2_GetLastSlotNum(instPtr); + rttRecord->Tr1.timeL = (uint32_t)counter10ns; + DBG_INFO("Tr1-timeL:%u.\n", rttRecord->Tr1.timeL); + DBG_INFO("Tr1-timeH:%u.\n", rttRecord->Tr1.timeH); + } + else{ + rttFsmPtr->isR1Valid = false; + rttRecord->dopplerR1 = RTT_DOPPLER_NONE; + rttRecord->Tr1.timeL = RTT_TIME_NONE; + rttRecord->Tr1.timeH = RTT_TIME_NONE; + DBG_WARNING("RTT REQ-1 have not been received [Stage: %u].\n", rttFsmPtr->rttStatge.next); + DBG_WARNING("Set dopplerR1 and Tr1 to dummy value.\n"); + DBG_INFO("dopplerR1:%08X.\n", rttRecord->dopplerR1); + DBG_INFO("Tr1-timeL:%08X.\n", rttRecord->Tr1.timeL); + DBG_INFO("Tr1-timeH:%08X.\n", rttRecord->Tr1.timeH); + } + RTT_StageUpdate(rttFsmPtr, RTT_RSP1); + } + break; + case RTT_RSP1 : + if(nextTor == RTT_SEND){ + DBG_INFO("Prepare data for RTT RSP-1\n"); + rttRecord->Tt2.timeH = L2_GetNextFrameNum(instPtr)*L2_SLOTS_PER_FRAME + L2_GetNextSlotNum(instPtr); + rttRecord->Tt2.timeL = 0 ; + DBG_INFO("Tt2-timeL:%u.\n", rttRecord->Tt2.timeL); + DBG_INFO("Tt2-timeH:%u.\n", rttRecord->Tt2.timeH); + + if ( rttFsmPtr->isR1Valid ) { + // Calculate reply B + rttRecord->TreplyB.timeL = COUNTE_FRAC_MAX - rttRecord->Tr1.timeL; + rttRecord->TreplyB.timeH = rttRecord->Tt2.timeH - rttRecord->Tr1.timeH - 1; + DBG_INFO("TreplyB-timeL:%u.\n", rttRecord->TreplyB.timeL); + DBG_INFO("TreplyB-timeH:%u.\n", rttRecord->TreplyB.timeH); + } + else { + rttRecord->TreplyB.timeL = RTT_TIME_NONE; + rttRecord->TreplyB.timeH = RTT_TIME_NONE; + DBG_WARNING("RTT REQ-1 have not been received [Stage: %u].\n", rttFsmPtr->rttStatge.next); + DBG_WARNING("Set ReplayB to dummy value.\n"); + DBG_INFO("TreplyB-timeL:%08X.\n", rttRecord->TreplyB.timeL); + DBG_INFO("TreplyB-timeH:%08X.\n", rttRecord->TreplyB.timeH); + } + RTT_StageUpdate(rttFsmPtr, RTT_REQ2); + } + break; + case RTT_REQ2 : + if(lastTor == RTT_RCV){ + if(L2_isDataAvail(instPtr) == true){ + DBG_INFO("RTT REQ-2 have been received.\n"); + DBG_INFO("Preparing data for RTT RSP-2.\n"); + rttFsmPtr->isR3Valid = true; + + // Calculate doppler + double doppler = Phy_GetCoarseFreqEst(phyRef); + rttRecord->dopplerR2 = (int32_t)doppler; + DBG_INFO("rttRecord->dopplerR2: %d.\n", rttRecord->dopplerR2); + + // Calculate last frame receive time. + int32_t counter10ns = RTT_GetCounter10nsDeviation(phyRef); + if ( counter10ns < 0) { + counter10ns += COUNTE_FRAC_MAX; + rttRecord->Tr3.timeH -- ; + } + rttRecord->Tr3.timeL = (uint32_t)counter10ns; + DBG_INFO("Tr3-timeL:%u.\n", rttRecord->Tr3.timeL); + DBG_INFO("Tr3-timeH:%u.\n", rttRecord->Tr3.timeH); + + // Calculate TroundB + rttRecord->TroundB.timeL = rttRecord->Tr3.timeL; + rttRecord->TroundB.timeH = rttRecord->Tr3.timeH - rttRecord->Tt2.timeH; + DBG_INFO("TroundB-timeL:%u.\n", rttRecord->TroundB.timeL); + DBG_INFO("TroundB-timeH:%u.\n", rttRecord->TroundB.timeH); + } + else{ + rttFsmPtr->isR3Valid = false; + rttRecord->dopplerR3 = RTT_DOPPLER_NONE; + rttRecord->TroundB.timeL = RTT_TIME_NONE; + rttRecord->TroundB.timeH = RTT_TIME_NONE; + DBG_WARNING("RTT REQ-2 have not been received [Stage: %u].\n", rttFsmPtr->rttStatge.next); + DBG_WARNING("Set dopplerR3 and ReplayB to dummy value.\n"); + DBG_INFO("dopplerR3:%08X.\n", rttRecord->dopplerR3); + DBG_INFO("TroundB-timeL:%08X.\n", rttRecord->TroundB.timeL); + DBG_INFO("TroundB-timeH:%08X.\n", rttRecord->TroundB.timeH); + } + RTT_StageUpdate(rttFsmPtr, RTT_RSP2); + } + break; + case RTT_RSP2 : + if(nextTor == RTT_SEND){ + DBG_INFO("Prepare data for RTT RSP-2\n"); + rttRecord->Tt4.timeH = L2_GetNextFrameNum(instPtr)*L2_SLOTS_PER_FRAME + L2_GetNextSlotNum(instPtr); + rttRecord->Tt4.timeL = 0; + DBG_INFO("Tt4-timeL:%u.\n", rttRecord->Tt4.timeL); + DBG_INFO("Tt4-timeH:%u.\n", rttRecord->Tt4.timeH); + + if ( rttFsmPtr->isR3Valid ) { + // Calculate reply B + rttRecord->TreplyB.timeL = COUNTE_FRAC_MAX - rttRecord->Tr3.timeL; + rttRecord->TreplyB.timeH = rttRecord->Tt4.timeH - rttRecord->Tr3.timeH - 1; + DBG_INFO("TreplyB-timeL:%u.\n", rttRecord->TreplyB.timeL); + DBG_INFO("TreplyB-timeH:%u.\n", rttRecord->TreplyB.timeH); + // TODO implement a time adjustment. + DBG_INFO("RTT procedure end...\n"); + } + else { + rttRecord->TreplyB.timeL = RTT_TIME_NONE; + rttRecord->TreplyB.timeH = RTT_TIME_NONE; + DBG_WARNING("RTT REQ-2 have not been received [Stage: %u].\n", rttFsmPtr->rttStatge.next); + DBG_WARNING("Set ReplayB to dummy value.\n"); + DBG_INFO("TreplyB-timeL:%08X.\n", rttRecord->TreplyB.timeL); + DBG_INFO("TreplyB-timeH:%08X.\n", rttRecord->TreplyB.timeH); + } + RTT_StageUpdate(rttFsmPtr, RTT_NONE_STAGE); + } + break; + default : + break; + } + } + return Status; +} diff --git a/datalink814_ge/src/lscript.ld b/datalink814_ge/src/lscript.ld new file mode 100644 index 0000000..f97258d --- /dev/null +++ b/datalink814_ge/src/lscript.ld @@ -0,0 +1,292 @@ +/*******************************************************************/ +/* */ +/* This file is automatically generated by linker script generator.*/ +/* */ +/* Version: 2019.1.3 */ +/* */ +/* Copyright (c) 2010-2016 Xilinx, Inc. All rights reserved. */ +/* */ +/* Description : Cortex-A9 Linker Script */ +/* */ +/*******************************************************************/ + +_STACK_SIZE = DEFINED(_STACK_SIZE) ? _STACK_SIZE : 0x2000; +_HEAP_SIZE = DEFINED(_HEAP_SIZE) ? _HEAP_SIZE : 0x40000; + +_ABORT_STACK_SIZE = DEFINED(_ABORT_STACK_SIZE) ? _ABORT_STACK_SIZE : 1024; +_SUPERVISOR_STACK_SIZE = DEFINED(_SUPERVISOR_STACK_SIZE) ? _SUPERVISOR_STACK_SIZE : 2048; +_IRQ_STACK_SIZE = DEFINED(_IRQ_STACK_SIZE) ? _IRQ_STACK_SIZE : 1024; +_FIQ_STACK_SIZE = DEFINED(_FIQ_STACK_SIZE) ? _FIQ_STACK_SIZE : 1024; +_UNDEF_STACK_SIZE = DEFINED(_UNDEF_STACK_SIZE) ? _UNDEF_STACK_SIZE : 1024; + +/* Define Memories in the system */ + +MEMORY +{ + phy_data_interface_tx_frame_bram_ctrl_Mem0 : ORIGIN = 0x40000000, LENGTH = 0x2000 + phy_data_interface_ant_info_bram_ctrl_Mem0 : ORIGIN = 0x42000000, LENGTH = 0x2000 + mpc_bram_interface_mpc_bram_ctrl_Mem0 : ORIGIN = 0x44000000, LENGTH = 0x8000 + phy_data_interface_rx_frame_bram_ctrl_Mem0 : ORIGIN = 0x46000000, LENGTH = 0x2000 + ps7_ddr_0 : ORIGIN = 0x100000, LENGTH = 0x1FF00000 + ps7_qspi_linear_0 : ORIGIN = 0xFC000000, LENGTH = 0x1000000 + ps7_ram_0 : ORIGIN = 0x0, LENGTH = 0x30000 + ps7_ram_1 : ORIGIN = 0xFFFF0000, LENGTH = 0xFE00 +} + +/* Specify the default entry point to the program */ + +ENTRY(_vector_table) + +/* Define the sections, and where they are mapped in memory */ + +SECTIONS +{ +.text : { + KEEP (*(.vectors)) + *(.boot) + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + *(.plt) + *(.gnu_warning) + *(.gcc_execpt_table) + *(.glue_7) + *(.glue_7t) + *(.vfp11_veneer) + *(.ARM.extab) + *(.gnu.linkonce.armextab.*) +} > ps7_ddr_0 + +.init : { + KEEP (*(.init)) +} > ps7_ddr_0 + +.fini : { + KEEP (*(.fini)) +} > ps7_ddr_0 + +.rodata : { + __rodata_start = .; + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + __rodata_end = .; +} > ps7_ddr_0 + +.rodata1 : { + __rodata1_start = .; + *(.rodata1) + *(.rodata1.*) + __rodata1_end = .; +} > ps7_ddr_0 + +.sdata2 : { + __sdata2_start = .; + *(.sdata2) + *(.sdata2.*) + *(.gnu.linkonce.s2.*) + __sdata2_end = .; +} > ps7_ddr_0 + +.sbss2 : { + __sbss2_start = .; + *(.sbss2) + *(.sbss2.*) + *(.gnu.linkonce.sb2.*) + __sbss2_end = .; +} > ps7_ddr_0 + +.data : { + __data_start = .; + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + *(.jcr) + *(.got) + *(.got.plt) + __data_end = .; +} > ps7_ddr_0 + +.data1 : { + __data1_start = .; + *(.data1) + *(.data1.*) + __data1_end = .; +} > ps7_ddr_0 + +.got : { + *(.got) +} > ps7_ddr_0 + +.ctors : { + __CTOR_LIST__ = .; + ___CTORS_LIST___ = .; + KEEP (*crtbegin.o(.ctors)) + KEEP (*(EXCLUDE_FILE(*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + __CTOR_END__ = .; + ___CTORS_END___ = .; +} > ps7_ddr_0 + +.dtors : { + __DTOR_LIST__ = .; + ___DTORS_LIST___ = .; + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE(*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + __DTOR_END__ = .; + ___DTORS_END___ = .; +} > ps7_ddr_0 + +.fixup : { + __fixup_start = .; + *(.fixup) + __fixup_end = .; +} > ps7_ddr_0 + +.eh_frame : { + *(.eh_frame) +} > ps7_ddr_0 + +.eh_framehdr : { + __eh_framehdr_start = .; + *(.eh_framehdr) + __eh_framehdr_end = .; +} > ps7_ddr_0 + +.gcc_except_table : { + *(.gcc_except_table) +} > ps7_ddr_0 + +.mmu_tbl (ALIGN(16384)) : { + __mmu_tbl_start = .; + *(.mmu_tbl) + __mmu_tbl_end = .; +} > ps7_ddr_0 + +.ARM.exidx : { + __exidx_start = .; + *(.ARM.exidx*) + *(.gnu.linkonce.armexidix.*.*) + __exidx_end = .; +} > ps7_ddr_0 + +.preinit_array : { + __preinit_array_start = .; + KEEP (*(SORT(.preinit_array.*))) + KEEP (*(.preinit_array)) + __preinit_array_end = .; +} > ps7_ddr_0 + +.init_array : { + __init_array_start = .; + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + __init_array_end = .; +} > ps7_ddr_0 + +.fini_array : { + __fini_array_start = .; + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array)) + __fini_array_end = .; +} > ps7_ddr_0 + +.ARM.attributes : { + __ARM.attributes_start = .; + *(.ARM.attributes) + __ARM.attributes_end = .; +} > ps7_ddr_0 + +.sdata : { + __sdata_start = .; + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s.*) + __sdata_end = .; +} > ps7_ddr_0 + +.sbss (NOLOAD) : { + __sbss_start = .; + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.sb.*) + __sbss_end = .; +} > ps7_ddr_0 + +.tdata : { + __tdata_start = .; + *(.tdata) + *(.tdata.*) + *(.gnu.linkonce.td.*) + __tdata_end = .; +} > ps7_ddr_0 + +.tbss : { + __tbss_start = .; + *(.tbss) + *(.tbss.*) + *(.gnu.linkonce.tb.*) + __tbss_end = .; +} > ps7_ddr_0 + +.bss (NOLOAD) : { + __bss_start = .; + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + __bss_end = .; +} > ps7_ddr_0 + +_SDA_BASE_ = __sdata_start + ((__sbss_end - __sdata_start) / 2 ); + +_SDA2_BASE_ = __sdata2_start + ((__sbss2_end - __sdata2_start) / 2 ); + +/* Generate Stack and Heap definitions */ + +.heap (NOLOAD) : { + . = ALIGN(16); + _heap = .; + HeapBase = .; + _heap_start = .; + . += _HEAP_SIZE; + _heap_end = .; + HeapLimit = .; +} > ps7_ddr_0 + +.stack (NOLOAD) : { + . = ALIGN(16); + _stack_end = .; + . += _STACK_SIZE; + . = ALIGN(16); + _stack = .; + __stack = _stack; + . = ALIGN(16); + _irq_stack_end = .; + . += _IRQ_STACK_SIZE; + . = ALIGN(16); + __irq_stack = .; + _supervisor_stack_end = .; + . += _SUPERVISOR_STACK_SIZE; + . = ALIGN(16); + __supervisor_stack = .; + _abort_stack_end = .; + . += _ABORT_STACK_SIZE; + . = ALIGN(16); + __abort_stack = .; + _fiq_stack_end = .; + . += _FIQ_STACK_SIZE; + . = ALIGN(16); + __fiq_stack = .; + _undef_stack_end = .; + . += _UNDEF_STACK_SIZE; + . = ALIGN(16); + __undef_stack = .; +} > ps7_ddr_0 + +_end = .; +} + diff --git a/datalink814_ge/src/main.c b/datalink814_ge/src/main.c new file mode 100644 index 0000000..20844fa --- /dev/null +++ b/datalink814_ge/src/main.c @@ -0,0 +1,422 @@ +/*****************************************************************************/ +/** + * Description: main.c + * + + * Date: 2021-11-13 13:19 + * Last Editors: Fan Hao + * Last Edit Time: [2022-03-28 20:32] + * + * Revisions: Rev 0.0 + * History: + * [2021-11-13]: Initial edition. + * [2022-03-28]: Add bit error test mode. + * + * Copyright(c) 2021 Beijing Institute of Technology. + * Lab of Communication and Networking + * + ******************************************************************************/ + +/***************************** Include Files *********************************/ +#include +#include "config/app_config.h" +#include "xscugic.h" // The generic interrupt controller driver component +#include "xil_exception.h" // ARM Cortex A9 specific exception related APIs +#include "xgpio.h" +#include "sleep.h" // Sleep APIs for Cortex A9 +#include "xil_cache.h" +#include "linklayer/linklayer814.h" +#include "linklayer/msg_def.h" +#include "phy_ctrl/phy_ctrl.h" +#include "bit_array/bit_array.h" +#include "mpc/mpc_ctrl.h" + +#ifdef _MPC_CTRL +#include "./mpc/mpc_ctrl.h" +#endif + +#include "hardware/headless.h" + +/************************** Constant Definitions *****************************/ +L2_CONFIG l2Config = { + .myType = MEMBER_NODE, + .isInterHead = false, + .myId = 2, + .clustId = 1, + .headId = 1, + .bkpHeadId = 1, + .netScale = 2, + .phyInstPtr = NULL, + .tmcInstPtr = NULL +}; + +TIMECTRL_CONFIG tmcConfig = { + .baseAddr = TIME_CONTROLLER_BASEADDR, + .reset = 10 +}; + +PHY_CONFIG l1Config = { + .devId = PHY_DEVICE_ID, + .txBramId = TXBUFF_BRAM_ID, + .rxBramId = RXBUFF_BRAM_ID, + .antBramId = ANTCONFIG_BRAM_ID, + .baseAddr = PHY_CTRL_BASEADDR +}; +MPC_CONFIG mpcConfig = { + .bramDevId = MPC_PCIE_BRAM_ID, + .msgLenMax = MPC_BUFFER_LENGTH //byte +}; +static bool mpcStatusUpAssert = false; +/************************** Function Prototypes ******************************/ +int SetupInterruptSystem(XScuGic* instPtr, uint32_t devId); +void PeriodicPull_Handler(void *callBackRef); +#ifdef _MPC_CTRL +void MPC_IntrHandler(void* CallBackRef); +#endif + +/*********************** Driver Instance Definitions **************************/ +TIMECTRL_INST* tmcInstPtr = NULL; +PHY_INST* phyInstPtr = NULL; +L2_INST* linkInstPtr = NULL; +static XScuGic gicInst; //General interrupt controller intance +// FIXME: Only for test... +XGpio configGpio; /* The Instance of the GPIO Driver */ +/****************************************************************************/ +/** + * This function is responsible for initializing the SCUGIC instance, looking + * for the device configuration based on the unique device ID, initializing a + * SCUGIC instance, and initialize the interrupt at IRQ_F2P[0:0] + * + * @param devId is the XPAR__DEVICE_ID value from + * "xparameters.h". + * @param instPtr is a reference to the XScuGic driver Instance. + * + * @return SUCCESS if initialize successful. + * FAILURE if initialization failed. + * + *****************************************************************************/ +int SetupInterruptSystem(XScuGic* instPtr, uint32_t devId){ + XScuGic_Config *configPtr; + int Status; + uint32_t intrState; + // Initialize the GIC instance. + configPtr = XScuGic_LookupConfig(devId); + Status = XScuGic_CfgInitialize(instPtr, configPtr, + configPtr->CpuBaseAddress); + if (Status != SUCCESS) { + return Status; + } + + // Perform a self-test to ensure that the hardware was built correctly. + Status = XScuGic_SelfTest(instPtr); + if (Status != SUCCESS) { + return Status; + } + // Clear any pending interrupt flags + intrState = XScuGic_CPUReadReg(instPtr, XSCUGIC_INT_ACK_OFFSET); + XScuGic_CPUWriteReg(instPtr, XSCUGIC_EOI_OFFSET, intrState); + /* + * FOR PRIORITY: + * 0 is highest priority, 0xF8(248) is lowest. There are 32 priority levels + * supported with a step of 8. Hence the supported priorities are 0, 8, 16, + * 32, 40 ..., 248. + * + * FOR TRIGGER: + * SFI Read Only b10 always + * PPI Read Only depending on how the PPIs are configured. + * b01 Active HIGH level sensitive + * b11 Rising edge sensitive + * SPI LSB is read only. + * b01 Active HIGH level sensitive + * b11 Rising edge sensitive + */ + /* Set the priority of IRQ_F2P[1:1] to 0x00 (highest) and a trigger for a + * rising edge 0x03. + */ + + // Initialize physical layer interrupt. + XScuGic_SetPriorityTriggerType(instPtr, PERIODIC_5MS_INTR_ID, 0x00, 0x03); + + // Connect the interrupt service routine isr1 to the interrupt controller + Status = XScuGic_Connect(instPtr, PERIODIC_5MS_INTR_ID, + (Xil_ExceptionHandler) PeriodicPull_Handler, (void *) instPtr); + if (Status != SUCCESS) { + return Status; + } + XScuGic_Enable(instPtr, PERIODIC_5MS_INTR_ID); + +#ifdef _MPC_CTRL + // Initialize MPC interrupt. + XScuGic_SetPriorityTriggerType(instPtr, MPC_RX_DONE_INTR_ID, 0x00, 0x03); + // Connect the interrupt service routine isr1 to the interrupt controller + Status = XScuGic_Connect(instPtr, MPC_RX_DONE_INTR_ID, + (Xil_ExceptionHandler) MPC_IntrHandler, (void *) instPtr); + if (Status != XST_SUCCESS) { + return Status; + } + XScuGic_Enable(instPtr, MPC_RX_DONE_INTR_ID); +#endif + + /* Initialize the exception table and register the interrupt controller + * handler with the exception table + */ + Xil_ExceptionInit(); + + Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, + (Xil_ExceptionHandler) XScuGic_InterruptHandler, + (void *) instPtr); + + // Enable non-critical exceptions + Xil_ExceptionEnable(); + + return Status; +} // SetupInterruptSystem + + + +#ifdef _MPC_CTRL +void MPC_PCIESentStart(){ + uint32_t GpioConfig = XGpio_DiscreteRead(&configGpio, 2); + GpioConfig ^= 0x00000002; + XGpio_DiscreteWrite(&configGpio, 2, GpioConfig); +} + +/*****************************************************************************/ +/** + * @brief Handler of mater pc contrl interrupt. + * + * @param CallBackRef A pointer to corresponding frame UART instance. + * + * @return None. + * + ******************************************************************************/ +void MPC_IntrHandler(void* CallBackRef) { + MPC_MsgHandler(mpcInstPtr); +} +#endif + +/****************************************************************************/ +/** + * This function is a interrupt service routine for IRQ_F2P[1:1], IRQ_F2P[1:1] + * tells CPU that the data in OCM is ready! + * + * @param callBackRef is the SCUGIC instance pointer. + * + * @return None. + * + * @note None. + * + *****************************************************************************/ +void PeriodicPull_Handler(void *callBackRef) { + int32_t Status; + Phy_UpdateState(phyInstPtr); + uint32_t GpioConfig = XGpio_DiscreteRead(&configGpio, 2); + if(phyInstPtr->TOR.curr == PHY_TOR_TX){ + switch(phyInstPtr->frameType.curr){ + case L1_1M2BPS_5MS_FRAME: + mpcRecord->frame1Sent ++ ; + break; + case L1_200KBPS_5MS_FRAME: + mpcRecord->frame2Sent ++ ; + break; + case L1_40KBPS_10MS_FRAME: + mpcRecord->frame3Sent ++ ; + break; + case L1_40KBPS_20MS_FRAME: + mpcRecord->frame4Sent ++ ; + break; + case L1_10KBPS_20MS_FRAME: + mpcRecord->frame5Sent ++ ; + break; + case L1_2KBPS_100MS_FRAME: + mpcRecord->frame6Sent ++ ; + break; + case L1_10KBPS_10MS_FRAME: + mpcRecord->frame7Sent ++ ; + break; + case L1_2KBPS_20MS_FRAME: + mpcRecord->frame8Sent ++ ; + break; + default: + break; + } + } + if(phyInstPtr->TOR.last == PHY_TOR_RX && phyInstPtr->isFrameSync){ + switch(phyInstPtr->frameType.last){ + case L1_1M2BPS_5MS_FRAME: + mpcRecord->frame1Recv ++ ; + break; + case L1_200KBPS_5MS_FRAME: + mpcRecord->frame2Recv ++ ; + break; + case L1_40KBPS_10MS_FRAME: + mpcRecord->frame3Recv ++ ; + break; + case L1_40KBPS_20MS_FRAME: + mpcRecord->frame4Recv ++ ; + break; + case L1_10KBPS_20MS_FRAME: + mpcRecord->frame5Recv ++ ; + break; + case L1_2KBPS_100MS_FRAME: + mpcRecord->frame6Recv ++ ; + break; + case L1_10KBPS_10MS_FRAME: + mpcRecord->frame7Recv ++ ; + break; + case L1_2KBPS_20MS_FRAME: + mpcRecord->frame8Recv ++ ; + break; + default: + break; + } + } + + Status = Linklayer_Proc(linkInstPtr); + if(Status != SUCCESS){ + DBG_ERROR("Link layer runs failed, with error code: %ld\n", Status); + _nop_(); + } + + if(L2_isDataAvail(linkInstPtr) == true ){ + GpioConfig^=0x00000001; + } + + if (linkInstPtr->slotNum.next % DATA_STORE_INTERVAL == 1) { + mpcStatusUpAssert = true; + mpcRecord->frame1Cnt = mpcRecord->frame1Recv - mpcRecord->frame1CntLast; + mpcRecord->frame2Cnt = mpcRecord->frame2Recv - mpcRecord->frame2CntLast; + mpcRecord->frame3Cnt = mpcRecord->frame3Recv - mpcRecord->frame3CntLast; + mpcRecord->frame4Cnt = mpcRecord->frame4Recv - mpcRecord->frame4CntLast; + mpcRecord->frame5Cnt = mpcRecord->frame5Recv - mpcRecord->frame5CntLast; + mpcRecord->frame6Cnt = mpcRecord->frame6Recv - mpcRecord->frame6CntLast; + mpcRecord->frame7Cnt = mpcRecord->frame7Recv - mpcRecord->frame7CntLast; + mpcRecord->frame8Cnt = mpcRecord->frame8Recv - mpcRecord->frame8CntLast; + + // Store last time received frame number + mpcRecord->frame1CntLast = mpcRecord->frame1Recv; + mpcRecord->frame2CntLast = mpcRecord->frame2Recv; + mpcRecord->frame3CntLast = mpcRecord->frame3Recv; + mpcRecord->frame4CntLast = mpcRecord->frame4Recv; + mpcRecord->frame5CntLast = mpcRecord->frame5Recv; + mpcRecord->frame6CntLast = mpcRecord->frame6Recv; + mpcRecord->frame7CntLast = mpcRecord->frame7Recv; + mpcRecord->frame8CntLast = mpcRecord->frame8Recv; + } + + // TODO: Dijian frequency pattern TX_RX State. + GpioConfig ^= 0x80000000; + GpioConfig = (phyInstPtr->TOR.next == PHY_TOR_TX) ? GpioConfig|0x40000000 : GpioConfig&0xBFFFFFFF; + XGpio_DiscreteWrite(&configGpio, 2, GpioConfig); +} // PhyIntr_Handler + +/*****************************************************************************/ +/** + * @brief Main function, initialize all the device needed, initialize + * interrupt system, halt in while(1) wait for event interrupt. + * + * @param None. + * + * @return + * + ******************************************************************************/ +int main(void) { + int Status; + Status = HARDWARE_initialize(); + if (Status == SUCCESS) { + DBG_PRINT("Hardware Init SUCCESS! \n"); + } + else { + DBG_PRINT("Hardware Init FAILED! \n"); + return Status; + } + + Status = XGpio_Initialize(&configGpio, XPAR_CONFIG_GPIO_DEVICE_ID); + if (Status != SUCCESS) { + DBG_PRINT("Config Gpio Initialization Failed\n"); + return FAILURE; + } + XGpio_SetDataDirection(&configGpio, 1, 0xFFFFFFFF); + XGpio_SetDataDirection(&configGpio, 2, 0x00000000); + + // Init time controller + Status = TimeCtrl_Init(&tmcInstPtr, &tmcConfig); + if (Status == SUCCESS) { + DBG_PRINT("TmcCtrl Init SUCCESS! \n"); + } + else { + DBG_PRINT("TmcCtrl Init FAILED! \n"); + return Status; + } + + // Init physical layer + Status = Phy_InstInit(&phyInstPtr, &l1Config); + if (Status == SUCCESS) { + DBG_PRINT("PhyCtrl Init SUCCESS! \n"); + } + else { + DBG_PRINT("PhyCtrl Init FAILED! \n"); + return Status; + } + + // Update l2 config + l2Config.phyInstPtr = phyInstPtr; + l2Config.tmcInstPtr = tmcInstPtr; + + Status = Linklayer_Init(&linkInstPtr, &l2Config); + if (Status == SUCCESS) { + DBG_PRINT("LinkLayer Init SUCCESS! \n"); + } + else { + DBG_PRINT("Linklayer Init FAILED! \n"); + return Status; + } + + // Init MPC + Status = MPC_Init(&mpcInstPtr, &mpcConfig); + if (Status == SUCCESS) { + DBG_PRINT("MPC Init SUCCESS! \n"); + } + else { + DBG_PRINT("MPC Init FAILED! \n"); + return Status; + } + + // Initialize GIC. + Status = SetupInterruptSystem(&gicInst ,SCUGIC_DEVICE_ID); + if (Status == SUCCESS) { + DBG_PRINT("Intc Init SUCCESS! \n"); + } + else { + DBG_PRINT("Intc Init FAILED! \n"); + return Status; + } + + Status = Phy_SetMode(phyInstPtr, PHY_MODE_SCHEDULE); + if (Status == SUCCESS) { + DBG_PRINT("Physical Mode %u Setup SUCCESS! \n", PHY_MODE_LISTEN); + } + else { + DBG_PRINT("Physical Mode %u Setup FAILED! \n", PHY_MODE_LISTEN); + return Status; + } + + DBG_PRINT("Starting Physical Layer..."); + Phy_Start(phyInstPtr); + + Linklayer_Start(linkInstPtr); + + while(true) { + if (mpcStatusUpAssert == true) { + mpcStatusUpAssert = false; + if (linkInstPtr->buffSwitch == 0) { + MPC_StateUpload(mpcInstPtr, linkInstPtr->mgmtMsgRecvBuff1, linkInstPtr->mgmtMsgRecvCnt1, + linkInstPtr->svcMsgRecvBuff1, linkInstPtr->svcMsgRecvCnt1, &(linkInstPtr->mgmtNetFSM->mgmtMsgLog)); + } + else { + MPC_StateUpload(mpcInstPtr, linkInstPtr->mgmtMsgRecvBuff0, linkInstPtr->mgmtMsgRecvCnt0, + linkInstPtr->svcMsgRecvBuff0, linkInstPtr->svcMsgRecvCnt0, &(linkInstPtr->mgmtNetFSM->mgmtMsgLog)); + } + } + } +} // main diff --git a/datalink814_ge/src/mpc/mpc_ctrl.c b/datalink814_ge/src/mpc/mpc_ctrl.c new file mode 100644 index 0000000..20967bd --- /dev/null +++ b/datalink814_ge/src/mpc/mpc_ctrl.c @@ -0,0 +1,474 @@ +/*****************************************************************************/ +/** + * Description: A brief description of this file + * + * Date: 2022-01-19 00:54 + * LastEditors: Fan Hao + * LastEditTime: 2022-03-28 20:24 + * Revisions: Rev 0.0 + * History: + * [2022-01-19]: Initial version. + * [2022-03-28]: Add general information print function. + * + * Copyright(c) 2022 Beijing Institute of Technology. + * Lab of Communication and Networking + * + ******************************************************************************/ + +#include +#include +#include "mpc_ctrl.h" +#include "mpc_msg_def.h" +#include "../error.h" +#include "../config/app_config.h" +#include "../bit_array/bit_array.h" +#include "../util/util.h" +#include "../linklayer/linklayer814.h" +#include "../linklayer/msg_def.h" +#include "../linklayer/node_list.h" +#include "../linklayer/rtt.h" +#ifdef _MPC_CTRL + +#define STATE_STROAGE_BUFF_MAX 32768 // 32K Bytes + +static int32_t MPC_InsertChunk(BIT_ARRAY* bitarr, uint32_t offset, uint32_t numBit, uint64_t chunk); +static int32_t MPC_GetChunk(BIT_ARRAY* bitarr, uint32_t offset, uint32_t numBit, uint64_t* chunk); + +#ifdef _MPC_UART +#include + +//... +#endif //_MPC_CTRL + +#ifdef _MPC_PCIE +#include "../phy_ctrl/phy_ctrl.h" + +extern L2_CONFIG l2Config; +extern PHY_INST* phyInstPtr; +extern L2_INST* linkInstPtr; + +MPC_INST* mpcInstPtr = NULL; +MPC_RECORD* mpcRecord = NULL; +BIT_ARRAY* mpcTxMsgBuff = NULL; +BIT_ARRAY* mpcRxMsgBuff = NULL; + +static MPC_MSG_HEADER mpcHeader = { + .head = 0x5302, +}; + + +/*****************************************************************************/ +/** + * @brief Insert a data chunk to a bit array. + * + * @param bitarr pointer to target bit array. + * offset offset of insert start position. + * numBit number of insert bits + * chunk 64 bit data chunk, contains the data should be stored + * in LSB style. + * + * @return FAILURE insert operation exceed bit array size. + * SUCCESS + * + ******************************************************************************/ +static int32_t MPC_InsertChunk(BIT_ARRAY* bitarr, uint32_t offset, uint32_t numBit, uint64_t chunk){ + ASSERT(bitarr != NULL); + if(bitarr->num_of_bits < offset+numBit){ + return FAILURE; + } + bit_array_set_wordn(bitarr, offset, chunk, numBit); + return SUCCESS; +} + +/*****************************************************************************/ +/** + * @brief Get a data chunk to a bit array. + * + * @param bitarr pointer to target bit array. + * offset offset of data chunk start position. + * numBit number of data chunk + * chunk pointer to a 64 bit data chunk container, data will be stored + * in LSB style. + * + * @return FAILURE read operation exceed bit array size. + * SUCCESS + * + ******************************************************************************/ +static int32_t MPC_GetChunk(BIT_ARRAY* bitarr, uint32_t offset, uint32_t numBit, uint64_t* chunk){ + ASSERT(bitarr != NULL); + if(bitarr->num_of_bits < offset+numBit || numBit > 64){ + return FAILURE; + } + *chunk = bit_array_get_wordn(bitarr, offset, numBit); + return SUCCESS; +} + +static uint32_t MPC_GetMsgLen(MPC_MSG_TYPE type){ + switch(type){ + case MPC_MSG_TEST: + return (MPC_MSG_TEST_LEN/8); + case MPC_MSG_STATE: + return (MPC_MSG_STATE_LEN/8); + default: + return MPC_MSG_LEN_NONE; + } +} +/*****************************************************************************/ +/** + * @brief Initialize mpc instance, apply customize configurations. + * + * @param instPtr pointer mpc descriptor. + * configPtr pointer to mpc configurations. + * + * @return SUCCESS MPC init successfully. + * error code. + * + ******************************************************************************/ +int MPC_Init(MPC_INST** instPtr, MPC_CONFIG* configPtr){ + ASSERT(instPtr != NULL); + ASSERT(configPtr != NULL); + int Status = SUCCESS; + XBram_Config *bramConfigPtr; + (*instPtr) = (MPC_INST*)malloc(sizeof(MPC_INST)); + if((*instPtr) == NULL){ + Status = EALLOC; + goto init_failed; + } + (*instPtr)->configs.bramDevId = configPtr->bramDevId; + (*instPtr)->configs.msgLenMax = configPtr->msgLenMax; + + bramConfigPtr = XBram_LookupConfig(configPtr->bramDevId); + if (bramConfigPtr == NULL) { + Status = EDINVAL; + goto init_failed; + } + Status = XBram_CfgInitialize(&((*instPtr)->pcieBram), bramConfigPtr, + bramConfigPtr->CtrlBaseAddress); + if (Status != SUCCESS) { + goto init_failed; + } + /* Execute the BRAM driver selftest. */ + Status = XBram_SelfTest(&((*instPtr)->pcieBram), 0); + if (Status != SUCCESS) { + goto init_failed; + } + (*instPtr)->txBaseAddr = (uint8_t*)((*instPtr)->pcieBram.Config.MemBaseAddress); + (*instPtr)->rxBaseAddr = (uint8_t*)((*instPtr)->pcieBram.Config.MemBaseAddress); + + mpcRecord = (MPC_RECORD*) malloc(sizeof(MPC_RECORD)); + if(mpcRecord == NULL){ + Status = EALLOC; + goto init_failed; + } + + memset(mpcRecord, 0x00, sizeof(MPC_RECORD)); + + mpcTxMsgBuff = bit_array_create(STATE_STROAGE_BUFF_MAX*8); + if(mpcTxMsgBuff == NULL){ + goto init_failed; + } + mpcRxMsgBuff = bit_array_create(MPC_MSG_LEN_MAX); + if(mpcRxMsgBuff == NULL){ + goto init_failed; + } + return Status; + +init_failed: + free(*instPtr); + free(mpcRecord); + free(mpcTxMsgBuff); + free(mpcRxMsgBuff); + return Status; +} + +/*****************************************************************************/ +/** + * @brief Handle a mpc message in rx buffer. + * + * @param instPtr pointer mpc descriptor. + * + * @return SUCCESS MPC handler runs successfully. + * error code. + * + ******************************************************************************/ +int MPC_MsgHandler(MPC_INST* instPtr){ + ASSERT(instPtr != NULL); + MPC_MSG_HEADER* pktHeader = (MPC_MSG_HEADER*)(instPtr->rxBaseAddr); + // instPtr->txBaseAddr + MPC_MSG_HEAD_LEN; + uint64_t dataChunk = 0; + switch(pktHeader->type){ + case MPC_MSG_TEST_CODE: + memcpy(mpcRxMsgBuff->words, + instPtr->rxBaseAddr + (MPC_MSG_HEAD_LEN/8), + DIV_ROUND_UP(MPC_MSG_TEST_LEN,8)); + MPC_GetChunk(mpcRxMsgBuff, TEST_REQ_CMD_OFFSET, TEST_REQ_CMD_LEN, &dataChunk); + if((uint8_t)dataChunk == TEST_REQ_CMD_START){ + MPC_GetChunk(mpcRxMsgBuff, TEST_MODE_SET_OFFSET, TEST_MODE_SET_LEN, &dataChunk); + // FIXME + if((uint8_t)dataChunk == TEST_MODE_HEAD){ + l2Config.myType = HEAD_NODE; + l2Config.myId = 1; + } + else{ + l2Config.myType = MEMBER_NODE; + l2Config.myId = 2; + } + MPC_InsertChunk(mpcTxMsgBuff, TEST_REQ_FPGA_ST_OFFSET, TEST_REQ_FPGA_ST_LEN, 0x01); + MPC_InsertChunk(mpcTxMsgBuff, TEST_REQ_AD_ST_OFFSET, TEST_REQ_AD_ST_LEN, 0x01); + MPC_InsertChunk(mpcTxMsgBuff, TEST_REQ_RF_ST_OFFSET, TEST_REQ_RF_ST_LEN, 0x01); + MPC_SendMsg(instPtr, MPC_MSG_TEST, (uint8_t*)mpcTxMsgBuff->words, MPC_MSG_TEST_LEN); + Linklayer_Reconfig(linkInstPtr, &l2Config); + Linklayer_Start(linkInstPtr); + } + else if((uint8_t)dataChunk == TEST_REQ_CMD_END){ + MPC_InsertChunk(mpcTxMsgBuff, TEST_REQ_FPGA_ST_OFFSET, TEST_REQ_FPGA_ST_LEN, 0x00); + MPC_InsertChunk(mpcTxMsgBuff, TEST_REQ_AD_ST_OFFSET, TEST_REQ_AD_ST_LEN, 0x00); + MPC_InsertChunk(mpcTxMsgBuff, TEST_REQ_RF_ST_OFFSET, TEST_REQ_RF_ST_LEN, 0x00); + MPC_SendMsg(instPtr, MPC_MSG_TEST, (uint8_t*)mpcTxMsgBuff->words, MPC_MSG_TEST_LEN); + memset(mpcRecord, 0x00, sizeof(MPC_RECORD)); + memset((uint8_t*)mpcTxMsgBuff->words,0x00,STATE_STROAGE_BUFF_MAX); + Linklayer_Halt(linkInstPtr); + MPC_SendMsg(instPtr, MPC_MSG_STATE, (uint8_t*)mpcTxMsgBuff->words, STATE_STROAGE_BUFF_MAX); + Phy_SetupNextSlot(phyInstPtr, PHY_TOR_SUSPEND, L1_200KBPS_5MS_FRAME, NULL); // any frame type is okay + + } + else{ + DBG_WARNING("Unexpected self-test command.\n"); + } + break; + case MPC_MSG_TSYNC_CODE: + memcpy(mpcRxMsgBuff->words, + instPtr->rxBaseAddr + ((MPC_MSG_HEAD_LEN/8)/2), + DIV_ROUND_UP(MPC_MSG_TSYNC_LEN,8)); + //FIXME: +// MPC_GetChunk(mpcRxMsgBuff, RTT_ADJ_OFFSET, RTT_ADJ_LEN, &dataChunk); +// rttRecord->rttAdj = (double)dataChunk ; +// MPC_GetChunk(mpcRxMsgBuff, TSYNC_ADJ_OFFSET, TSYNC_ADJ_LEN, &dataChunk); +// double tsyncAdj = (double)dataChunk * 0.192; + //FIXME: +// PhyWrite(TSYNC_PULS_ADJ, (uint32_t)tsyncAdj); +// MPC_GetChunk(mpcRxMsgBuff, DOPPLER_OFFSET, DOPPLER_LEN, &dataChunk); +// double dopplerAdj = (double)((dataChunk << 32)/192000000) ; +// PhyWrite(DOPPLER_ADJ, (uint32_t)dopplerAdj); + break; + default: + DBG_ERROR("Unknown message type code: %04X.\n\r", pktHeader->type); + return EPARAM; + } + return SUCCESS; +} + +/*****************************************************************************/ +/** + * @brief Encapsulate upload a packet to master pc, upload content defined + * in the mpc message protocols. + * + * @param instPtr pointer mpc descriptor. + * type packet type + * buffer pinter to send packet buffer. + * dlen length of data need to be sent. + * + * @return SUCCESS MPC handler runs successfully. + * error code. + * + ******************************************************************************/ +int MPC_SendMsg(MPC_INST* instPtr, MPC_MSG_TYPE type, uint8_t* buffer, uint32_t dlen){ + ASSERT(instPtr != NULL); + if(buffer == NULL || + dlen >= instPtr->configs.msgLenMax || + (type <= MPC_MSG_NONE || type > MPC_MSG_STATE)){ + return EPARAM; + } + if(instPtr->pcieBram.IsReady == false){ + return EDINVAL; + } + int Status = SUCCESS; + switch(type){ + case MPC_MSG_TEST: + mpcHeader.type = MPC_MSG_TEST_CODE; + break; + case MPC_MSG_STATE: + mpcHeader.type = MPC_MSG_STATE_CODE; + break; + default: + DBG_ERROR("Unknown mpc message type: %d.\n", type); + break; + } + memcpy(instPtr->txBaseAddr, &mpcHeader, MPC_MSG_HEAD_LEN/8); + memcpy(instPtr->txBaseAddr + (MPC_MSG_HEAD_LEN/8), buffer, dlen); + MPC_PCIESentStart(); + return Status; +} + + +/*****************************************************************************/ +/** + * @brief Upload current state to master pc.(content detail defined in mpc + * mesage protocol) + * + * @param instPtr pointer mpc descriptor. + * + * @return SUCCESS MPC handler runs successfully. + * error code. + * + ******************************************************************************/ +int MPC_StateUpload(MPC_INST* instPtr , uint8_t* mgmtBuffer , uint32_t mgmtMsgCnt , + uint8_t* svcBuffer , uint32_t svcMsgCnt , MGMT_MSG_RECORD* mgmtMsg){ + ASSERT(instPtr != NULL); + int32_t Status = SUCCESS; + uint64_t dataChunk = 0; + if(instPtr->pcieBram.IsReady == false){ + return EDINVAL; + } + + // Stage + switch (linkInstPtr->mainState) { + case INIT_STATE : + dataChunk = STATE_STAGE_SETUP; + break; + case INTRA_SEEK_STATE: + dataChunk = STATE_STAGE_RTNE; + break; + case NORMAL_STATE : + dataChunk = STATE_STAGE_SVC; + break; + default: + return EUNEXP; + } + MPC_InsertChunk(mpcTxMsgBuff, STATE_STAGE_OFFSET, STATE_STAGE_LEN, dataChunk); + + // Net setup time + dataChunk = (L2_GetNextFrameNum(linkInstPtr) - linkInstPtr->netStartTime) * 1000 + L2_GetNextSlotNum(linkInstPtr) * 5 ; + MPC_InsertChunk(mpcTxMsgBuff, STATE_SETUP_TIME_OFFSET, STATE_SETUP_TIME_LEN, dataChunk); + // number of nodes + dataChunk = GetNodeNum(linkInstPtr->nodeList); + MPC_InsertChunk(mpcTxMsgBuff, STATE_NUM_NODE_OFFSET, STATE_NUM_NODE_LEN, dataChunk); + + // frame 1 counter + dataChunk = mpcRecord->frame1Cnt; + MPC_InsertChunk(mpcTxMsgBuff, STATE_FRAME_1_CNT_OFFSET, STATE_FRAME_1_CNT_LEN, dataChunk); + // frame 2 counter + dataChunk = mpcRecord->frame2Cnt; + MPC_InsertChunk(mpcTxMsgBuff, STATE_FRAME_2_CNT_OFFSET, STATE_FRAME_2_CNT_LEN, dataChunk); + // frame 3 counter + dataChunk = mpcRecord->frame3Cnt; + MPC_InsertChunk(mpcTxMsgBuff, STATE_FRAME_3_CNT_OFFSET, STATE_FRAME_3_CNT_LEN, dataChunk); + // frame 4 counter + dataChunk = mpcRecord->frame4Cnt; + MPC_InsertChunk(mpcTxMsgBuff, STATE_FRAME_4_CNT_OFFSET, STATE_FRAME_4_CNT_LEN, dataChunk); + // frame 5 counter + dataChunk = mpcRecord->frame5Cnt; + MPC_InsertChunk(mpcTxMsgBuff, STATE_FRAME_5_CNT_OFFSET, STATE_FRAME_5_CNT_LEN, dataChunk); + // frame 6 counter + dataChunk = mpcRecord->frame6Cnt; + MPC_InsertChunk(mpcTxMsgBuff, STATE_FRAME_6_CNT_OFFSET, STATE_FRAME_6_CNT_LEN, dataChunk); + // frame 7 counter + dataChunk = mpcRecord->frame7Cnt; + MPC_InsertChunk(mpcTxMsgBuff, STATE_FRAME_7_CNT_OFFSET, STATE_FRAME_7_CNT_LEN, dataChunk); + // frame 8 counter + dataChunk = mpcRecord->frame8Cnt; + MPC_InsertChunk(mpcTxMsgBuff, STATE_FRAME_8_CNT_OFFSET, STATE_FRAME_8_CNT_LEN, dataChunk); + + // frame 1 sent counter + dataChunk = mpcRecord->frame1Sent; + MPC_InsertChunk(mpcTxMsgBuff, STATE_FRAME_1_SENT_OFFSET, STATE_FRAME_1_SENT_LEN, dataChunk); + // frame 2 sent counter + dataChunk = mpcRecord->frame2Sent; + MPC_InsertChunk(mpcTxMsgBuff, STATE_FRAME_2_SENT_OFFSET, STATE_FRAME_2_SENT_LEN, dataChunk); + // frame 3 sent counter + dataChunk = mpcRecord->frame3Sent; + MPC_InsertChunk(mpcTxMsgBuff, STATE_FRAME_3_SENT_OFFSET, STATE_FRAME_3_SENT_LEN, dataChunk); + // frame 4 sent counter + dataChunk = mpcRecord->frame4Sent; + MPC_InsertChunk(mpcTxMsgBuff, STATE_FRAME_4_SENT_OFFSET, STATE_FRAME_4_SENT_LEN, dataChunk); + // frame 5 sent counter + dataChunk = mpcRecord->frame5Sent; + MPC_InsertChunk(mpcTxMsgBuff, STATE_FRAME_5_SENT_OFFSET, STATE_FRAME_5_SENT_LEN, dataChunk); + // frame 6 sent counter + dataChunk = mpcRecord->frame6Sent; + MPC_InsertChunk(mpcTxMsgBuff, STATE_FRAME_6_SENT_OFFSET, STATE_FRAME_6_SENT_LEN, dataChunk); + // frame 7 sent counter + dataChunk = mpcRecord->frame7Sent; + MPC_InsertChunk(mpcTxMsgBuff, STATE_FRAME_7_SENT_OFFSET, STATE_FRAME_7_SENT_LEN, dataChunk); + // frame 8 sent counter + dataChunk = mpcRecord->frame8Sent; + MPC_InsertChunk(mpcTxMsgBuff, STATE_FRAME_8_SENT_OFFSET, STATE_FRAME_8_SENT_LEN, dataChunk); + + // frame 1 received counter + dataChunk = mpcRecord->frame1Recv; + MPC_InsertChunk(mpcTxMsgBuff, STATE_FRAME_1_RECV_OFFSET, STATE_FRAME_1_RECV_LEN, dataChunk); + // frame 2 received counter + dataChunk = mpcRecord->frame2Recv; + MPC_InsertChunk(mpcTxMsgBuff, STATE_FRAME_2_RECV_OFFSET, STATE_FRAME_2_RECV_LEN, dataChunk); + // frame 3 received counter + dataChunk = mpcRecord->frame3Recv; + MPC_InsertChunk(mpcTxMsgBuff, STATE_FRAME_3_RECV_OFFSET, STATE_FRAME_3_RECV_LEN, dataChunk); + // frame 4 received counter + dataChunk = mpcRecord->frame4Recv; + MPC_InsertChunk(mpcTxMsgBuff, STATE_FRAME_4_RECV_OFFSET, STATE_FRAME_4_RECV_LEN, dataChunk); + // frame 5 received counter + dataChunk = mpcRecord->frame5Recv; + MPC_InsertChunk(mpcTxMsgBuff, STATE_FRAME_5_RECV_OFFSET, STATE_FRAME_5_RECV_LEN, dataChunk); + // frame 6 received counter + dataChunk = mpcRecord->frame6Recv; + MPC_InsertChunk(mpcTxMsgBuff, STATE_FRAME_6_RECV_OFFSET, STATE_FRAME_6_RECV_LEN, dataChunk); + // frame 7 received counter + dataChunk = mpcRecord->frame7Recv; + MPC_InsertChunk(mpcTxMsgBuff, STATE_FRAME_7_RECV_OFFSET, STATE_FRAME_7_RECV_LEN, dataChunk); + // frame 8 received counter + dataChunk = mpcRecord->frame8Recv; + MPC_InsertChunk(mpcTxMsgBuff, STATE_FRAME_8_RECV_OFFSET, STATE_FRAME_8_RECV_LEN, dataChunk); + + // Trajectory pos X + dataChunk = mgmtMsg->Longitude % 1000 ; + MPC_InsertChunk(mpcTxMsgBuff, STATE_TRAJ_X_OFFSET, STATE_TRAJ_X_LEN, dataChunk); + // Trajectory pos Y + dataChunk = mgmtMsg->Latitude % 1000 ; + MPC_InsertChunk(mpcTxMsgBuff, STATE_TRAJ_Y_OFFSET, STATE_TRAJ_Y_LEN, dataChunk); + // Trajectory alpha + dataChunk = 45; + MPC_InsertChunk(mpcTxMsgBuff, STATE_TRAJ_ALPHA_OFFSET, STATE_TRAJ_ALPHA_LEN, dataChunk); + + // TODO : Currently DJ is node 1 , only Byte 1 is activate , others is useless + // Topo node 1 + dataChunk = BIT(linkInstPtr->myInfo.nodeId - 1); + if (GetNodeNum(linkInstPtr->nodeList) > 1 ) { + for(int i = 1; i <= linkInstPtr->config.netScale; i++){ + if (IsNodeInList(linkInstPtr->nodeList, i)) { + dataChunk |= BIT(i-1); + } + } + } + MPC_InsertChunk(mpcTxMsgBuff, STATE_TOPO_1_OFFSET, STATE_TOPO_1_LEN, dataChunk); + // Topo node 2 + dataChunk = 0x00; + MPC_InsertChunk(mpcTxMsgBuff, STATE_TOPO_2_OFFSET, STATE_TOPO_2_LEN, dataChunk); + // Topo node 3 + dataChunk = 0x00; + MPC_InsertChunk(mpcTxMsgBuff, STATE_TOPO_3_OFFSET, STATE_TOPO_3_LEN, dataChunk); + // Topo node 4 + dataChunk = 0x00; + MPC_InsertChunk(mpcTxMsgBuff, STATE_TOPO_4_OFFSET, STATE_TOPO_4_LEN, dataChunk); + + // Mgmt message Number + dataChunk = mgmtMsgCnt; + MPC_InsertChunk(mpcTxMsgBuff, MGMT_MSG_NUM_OFFSET, MGMT_MSG_NUM_LEN, dataChunk); + + // Svc message Number + dataChunk = svcMsgCnt; + MPC_InsertChunk(mpcTxMsgBuff, SVC_MSG_NUM_OFFSET, SVC_MSG_NUM_LEN, dataChunk); + + // Copy msg data + size_t svcLen = mgmtMsgCnt*(72/8*6); + size_t mgmtLen = svcMsgCnt*(2040/8); + memcpy(((uint8_t*)mpcTxMsgBuff->words) + MPC_MSG_STATE_LEN/8, mgmtBuffer, svcLen); + memcpy(((uint8_t*)mpcTxMsgBuff->words) + MPC_MSG_STATE_LEN/8 + mgmtMsgCnt*(72/8*6), + svcBuffer, mgmtLen); + + Status = MPC_SendMsg(instPtr, MPC_MSG_STATE,(uint8_t*)mpcTxMsgBuff->words, MPC_MSG_STATE_LEN/8 + svcLen + mgmtLen); +// Status = MPC_SendMsg(instPtr, MPC_MSG_STATE,(uint8_t*)stateMsg->words, MPC_MSG_STATE_LEN/8); + return Status; +} + +#endif //_MPC_PCIE +#endif //_MPC_CTRL diff --git a/datalink814_ge/src/mpc/mpc_ctrl.h b/datalink814_ge/src/mpc/mpc_ctrl.h new file mode 100644 index 0000000..adcd737 --- /dev/null +++ b/datalink814_ge/src/mpc/mpc_ctrl.h @@ -0,0 +1,106 @@ +/*****************************************************************************/ +/** + * Description: A brief description of this file + * + * Date: 2022-01-19 00:54 + * LastEditors: Fan Hao + * LastEditTime: 2022-03-28 20:24 + * Revisions: Rev 0.0 + * History: + * [2022-01-19]: Initial version. + * [2022-03-28]: Add general information print function. + * + * Copyright(c) 2022 Beijing Institute of Technology. + * Lab of Communication and Networking + * + ******************************************************************************/ + +#ifndef MPC_CTRL_H_ +#define MPC_CTRL_H_ + +#include +#include "../config/app_config.h" +#ifdef _MPC_CTRL +#ifdef _MPC_UART +//... +#endif //_MPC_UART + +#ifdef _MPC_PCIE +#include "xbram.h" +#include "../phy_ctrl/phy_ctrl.h" +#include "../linklayer/linklayer814.h" + +typedef struct { + const uint16_t head; + uint16_t type; + uint8_t reserve[4]; +} MPC_MSG_HEADER; + +typedef struct{ + uint32_t bramDevId; + uint32_t msgLenMax; +} MPC_CONFIG; + +typedef struct{ + MPC_CONFIG configs; + XBram pcieBram; + uint8_t* txBaseAddr; + uint8_t* rxBaseAddr; +} MPC_INST; + +typedef enum{ + MPC_MSG_NONE = 0, + MPC_MSG_TEST = 1, + MPC_MSG_STATE = 2, +} MPC_MSG_TYPE; + +// FIXME: Simplify this part. +typedef struct { + uint8_t frame1Cnt; + uint8_t frame2Cnt; + uint8_t frame3Cnt; + uint8_t frame4Cnt; + uint8_t frame5Cnt; + uint8_t frame6Cnt; + uint8_t frame7Cnt; + uint8_t frame8Cnt; + uint8_t frame1CntLast; + uint8_t frame2CntLast; + uint8_t frame3CntLast; + uint8_t frame4CntLast; + uint8_t frame5CntLast; + uint8_t frame6CntLast; + uint8_t frame7CntLast; + uint8_t frame8CntLast; + uint16_t frame1Sent; + uint16_t frame2Sent; + uint16_t frame3Sent; + uint16_t frame4Sent; + uint16_t frame5Sent; + uint16_t frame6Sent; + uint16_t frame7Sent; + uint16_t frame8Sent; + uint16_t frame1Recv; + uint16_t frame2Recv; + uint16_t frame3Recv; + uint16_t frame4Recv; + uint16_t frame5Recv; + uint16_t frame6Recv; + uint16_t frame7Recv; + uint16_t frame8Recv; +} MPC_RECORD; + + +extern void MPC_PCIESentStart(); +extern MPC_RECORD* mpcRecord; +extern MPC_INST* mpcInstPtr; + +int MPC_Init(MPC_INST** instPtr, MPC_CONFIG* configPtr); +int MPC_MsgHandler(MPC_INST* instPtr); +int MPC_StateUpload(MPC_INST* instPtr , uint8_t* mgmtBuffer , uint32_t mgmtMsgCnt + , uint8_t* svcBuffer , uint32_t svcMsgCnt , MGMT_MSG_RECORD* mgmtmsg); +int MPC_SendMsg(MPC_INST* instPtr, MPC_MSG_TYPE type, uint8_t* buffer, uint32_t dlen); + +#endif //_MPC_PCIE +#endif //_MPC_CTRL +#endif //MPC_CTRL_H_ diff --git a/datalink814_ge/src/mpc/mpc_msg_def.h b/datalink814_ge/src/mpc/mpc_msg_def.h new file mode 100644 index 0000000..46880b1 --- /dev/null +++ b/datalink814_ge/src/mpc/mpc_msg_def.h @@ -0,0 +1,134 @@ +/* + * mpc_msg_def.h + * + * Created on: Sep 19, 2022 + */ + +#ifndef _MPC_MSG_DEF +#define _MPC_MSG_DEF +#define MPC_MSG_HEAD_LEN 64 //bit +#define MPC_MSG_LEN_MAX 1024 //bit +#define MPC_MSG_LEN_NONE UINT32_MAX + +// ** Self Test Message ** // +// Type code +#define MPC_MSG_TEST_CODE 0x00AA +#define MPC_MSG_TEST_LEN 128 // bit +// data segment - self test request message. +#define TEST_REQ_CMD_OFFSET 0 +#define TEST_REQ_CMD_LEN 8 +#define TEST_REQ_CMD_START 0xAA +#define TEST_REQ_CMD_END 0xFF +#define TEST_MODE_SET_OFFSET 8 +#define TEST_MODE_SET_LEN 8 +#define TEST_MODE_HEAD 0x01 +#define TEST_MODE_MEMBER 0x02 +// data segment - self test response message. +#define TEST_REQ_FPGA_ST_OFFSET 0 +#define TEST_REQ_FPGA_ST_LEN 8 +#define TEST_REQ_AD_ST_OFFSET 8 +#define TEST_REQ_AD_ST_LEN 8 +#define TEST_REQ_RF_ST_OFFSET 16 +#define TEST_REQ_RF_ST_LEN 8 + +// ** State Report Message ** // +// Type code +#define MPC_MSG_STATE_CODE 0x00FF +#define MPC_MSG_STATE_LEN 544 // bit +// data segment +#define STATE_STAGE_OFFSET 0 +#define STATE_STAGE_LEN 8 +#define STATE_STAGE_SETUP 0x51 +#define STATE_STAGE_RTNE 0x52 +#define STATE_STAGE_SVC 0x53 +#define STATE_SETUP_TIME_OFFSET 8 +#define STATE_SETUP_TIME_LEN 32 +#define STATE_NUM_NODE_OFFSET 40 +#define STATE_NUM_NODE_LEN 8 +#define STATE_FRAME_1_CNT_OFFSET 48 +#define STATE_FRAME_1_CNT_LEN 8 +#define STATE_FRAME_2_CNT_OFFSET 56 +#define STATE_FRAME_2_CNT_LEN 8 +#define STATE_FRAME_3_CNT_OFFSET 64 +#define STATE_FRAME_3_CNT_LEN 8 +#define STATE_FRAME_4_CNT_OFFSET 72 +#define STATE_FRAME_4_CNT_LEN 8 +#define STATE_FRAME_5_CNT_OFFSET 80 +#define STATE_FRAME_5_CNT_LEN 8 +#define STATE_FRAME_6_CNT_OFFSET 88 +#define STATE_FRAME_6_CNT_LEN 8 +#define STATE_FRAME_7_CNT_OFFSET 96 +#define STATE_FRAME_7_CNT_LEN 8 +#define STATE_FRAME_8_CNT_OFFSET 104 +#define STATE_FRAME_8_CNT_LEN 8 + +#define STATE_FRAME_1_SENT_OFFSET 112 +#define STATE_FRAME_1_SENT_LEN 16 +#define STATE_FRAME_2_SENT_OFFSET 128 +#define STATE_FRAME_2_SENT_LEN 16 +#define STATE_FRAME_3_SENT_OFFSET 144 +#define STATE_FRAME_3_SENT_LEN 16 +#define STATE_FRAME_4_SENT_OFFSET 160 +#define STATE_FRAME_4_SENT_LEN 16 +#define STATE_FRAME_5_SENT_OFFSET 176 +#define STATE_FRAME_5_SENT_LEN 16 +#define STATE_FRAME_6_SENT_OFFSET 192 +#define STATE_FRAME_6_SENT_LEN 16 +#define STATE_FRAME_7_SENT_OFFSET 208 +#define STATE_FRAME_7_SENT_LEN 16 +#define STATE_FRAME_8_SENT_OFFSET 224 +#define STATE_FRAME_8_SENT_LEN 16 + +#define STATE_FRAME_1_RECV_OFFSET 240 +#define STATE_FRAME_1_RECV_LEN 16 +#define STATE_FRAME_2_RECV_OFFSET 256 +#define STATE_FRAME_2_RECV_LEN 16 +#define STATE_FRAME_3_RECV_OFFSET 272 +#define STATE_FRAME_3_RECV_LEN 16 +#define STATE_FRAME_4_RECV_OFFSET 288 +#define STATE_FRAME_4_RECV_LEN 16 +#define STATE_FRAME_5_RECV_OFFSET 304 +#define STATE_FRAME_5_RECV_LEN 16 +#define STATE_FRAME_6_RECV_OFFSET 320 +#define STATE_FRAME_6_RECV_LEN 16 +#define STATE_FRAME_7_RECV_OFFSET 336 +#define STATE_FRAME_7_RECV_LEN 16 +#define STATE_FRAME_8_RECV_OFFSET 352 +#define STATE_FRAME_8_RECV_LEN 16 + +#define STATE_TRAJ_X_OFFSET 368 +#define STATE_TRAJ_X_LEN 32 +#define STATE_TRAJ_Y_OFFSET 400 +#define STATE_TRAJ_Y_LEN 32 +#define STATE_TRAJ_ALPHA_OFFSET 432 +#define STATE_TRAJ_ALPHA_LEN 64 + +#define STATE_TOPO_1_OFFSET 496 +#define STATE_TOPO_1_LEN 8 +#define STATE_TOPO_2_OFFSET 504 +#define STATE_TOPO_2_LEN 8 +#define STATE_TOPO_3_OFFSET 512 +#define STATE_TOPO_3_LEN 8 +#define STATE_TOPO_4_OFFSET 520 +#define STATE_TOPO_4_LEN 8 + +#define MGMT_MSG_NUM_OFFSET 528 +#define MGMT_MSG_NUM_LEN 8 +#define SVC_MSG_NUM_OFFSET 536 +#define SVC_MSG_NUM_LEN 8 + +#define STORE_ADDR_START_OFFSET 544 + + +// ** Time SyncAdj Message ** // +// Type code +#define MPC_MSG_TSYNC_CODE 0x00FF +#define MPC_MSG_TSYNC_LEN 128 // bit +// data segment - self test response message. +#define RTT_ADJ_OFFSET 0 +#define RTT_ADJ_LEN 32 +#define TSYNC_ADJ_OFFSET 32 +#define TSYNC_ADJ_LEN 32 +#define DOPPLER_OFFSET 64 +#define DOPPLER_LEN 32 +#endif //_MPC_MSG_DEF diff --git a/datalink814_ge/src/phy_ctrl/antenna.c b/datalink814_ge/src/phy_ctrl/antenna.c new file mode 100644 index 0000000..e771e89 --- /dev/null +++ b/datalink814_ge/src/phy_ctrl/antenna.c @@ -0,0 +1,371 @@ +/*****************************************************************************/ +/** + * Description: Antenna configuration functions. + * + * Author: Fan Hao + * Date: 2022-06-18 16:37 + * LastEditors: Fan Hao + * LastEditTime: 2022-06-18 17:15 + * Revisions: Rev 0.0 + * History: + * [2022-06-18]: Initial version. + * + * Copyright(c) 2022 Beijing Institute of Technology. + * Lab of Communication and Networking + * + ******************************************************************************/ +#include +#include +#include +#include "phy_ctrl.h" +#include "../error.h" + +#define ANT_PI 3.14159265358979323846 +#define ANT_COINFO_HEAD 0xAA +#define ANT_COINFO_TAIL 0xCC + +#define CTRL_WORD_DEFAULT 0x00 + +#define ANT_MODE_BEAM_MASK 0xF0 +#define ANT_MODE_NARROR_BEAM 0x00 // 8 +#define ANT_MODE_WIDE_BEAM_1 0x10 // 25 +#define ANT_MODE_WIDE_BEAM_2 0x20 // 60 +#define ANT_MODE_WIDE_BEAM_3 0x30 // 120 + +#define ANT_MODE_HIGH_POWER 0x00 +#define ANT_MODE_LOWAPOWER 0x04 +#define ANT_MODE_STANDBY 0x0F +#define ATN_MODE_DEFAULT (ANT_MODE_WIDE_BEAM_1 | ANT_MODE_LOWAPOWER) +#define ATN_MODE_HIGH (ANT_MODE_WIDE_BEAM_1 | ANT_MODE_HIGH_POWER) + +#define DEFAULT_CENTRTAL_FREQ 0x06D7 // 26.25GHz + +#define RXTXMODE_RX 0x00 +#define RXTXMODE_TX 0x01 + +#define CALIBRMODE_NORMAL 0x00 +#define CALIBRMODE_SINGLE_TR_CAL 0x01 + +#define MODECTRL_DEFAULT 0x00 + +uint16_t hopPattern_Config[L1_FRAME_MAX_HOPS] = {0}; + +uint16_t hopPattern_2KBPS_20MS[L1_FRAME_2KBPS_20MS_HOPS] = {1500}; + +uint16_t hopPattern_2KBPS_100MS[L1_FRAME_2KBPS_100MS_HOPS] = { + 2400, 2400, 2400, 2400, 2400, 2400, 2400, 2400, 2400, 2400, 2400, 2400, + 2400, 2400, 2400, 2400, 2400, 2400, 2400, 2400, 2400, 2400, 2400, 2400, + 2400, 2400, 2400, 2400, 2400, 2400, 2400, 2400, 2400, 2400, 2400, 2400, + 2400, 2400, 2400, 2400, 2400, 2400, 2400, 2400, 2400, 2400, 2400, 2400, + 2400, 2400, 2400, 2400, 2400, 2400, 2400, 2400, 2400, 2400, 2400, 2400, + 2400, 2400, 2400, 2400, 2400, 2400, 2400, 2400, 2400, 2400, 2400, 2400, + 2400, 2400, 2400, 2400, 2400, 2400, 2400, 2400, 2400 +}; + +uint16_t hopPattern_10KBPS_10MS[L1_FRAME_10KBPS_10MS_HOPS] = {1500}; + +uint16_t hopPattern_10KBPS_20MS[L1_FRAME_10KBPS_20MS_HOPS] = { 1500, 1600, 1700, + 1800, 1900, 2000, 1500, 1600, 1700, 1800, 1900 }; + +uint16_t hopPattern_40KBPS_10MS[L1_FRAME_40KBPS_10MS_HOPS] = { + 2400, 2400, 2400, 2400, 2400, 2400, 2400, 2400, 2400 +}; + +uint16_t hopPattern_40KBPS_20MS[L1_FRAME_40KBPS_20MS_HOPS] = { + 2400, 2400, 2400, 2400, 2400, 2400, 2400, 2400, 2400, 2400, 2400, 2400, + 2400, 2400, 2400, 2400, 2400, 2400, 2400 +}; + +uint16_t hopPattern_200KBPS_5MS[L1_FRAME_200KBPS_5MS_HOPS] ={ 1500, 1600, 1700, 1800, 1900, 2000, 1500, 1600 , 1700, + 1800, 1900, 2000, 1500, 1600 , 1700, 1800, 1900, 2000, 1500, 1500}; + +uint16_t hopPattern_1M2BPS_5MS[L1_FRAME_1M2BPS_5MS_HOPS] = { 500, 600, 700, 800, 900, 1000, 500, 600 , 700, + 800, 900, 1000, 500, 600 , 700, 800, 900, 1000, 500, 500 }; + +// Pair by regex +// Regex: ((\{\.oaxis = [0-9]+[ ,]+\.raxis = [0-9]+[ ]*\}, ){2}) +#if defined(PHY_BEAM_SET_PRESET) +ANT_ANGLE antSubnrrwPattern[NUM_ANT_SUBNRRW_PATTERN] = { + {.oaxis = 0 , .raxis = 222}, {.oaxis = 10, .raxis = 85 }, + {.oaxis = 14, .raxis = 307}, {.oaxis = 17, .raxis = 170}, + {.oaxis = 19, .raxis = 32 }, {.oaxis = 21, .raxis = 255}, + {.oaxis = 24, .raxis = 117}, {.oaxis = 25, .raxis = 340}, + {.oaxis = 27, .raxis = 202}, {.oaxis = 29, .raxis = 65 }, + {.oaxis = 31, .raxis = 287}, {.oaxis = 32, .raxis = 150}, + {.oaxis = 34, .raxis = 12 }, {.oaxis = 35, .raxis = 235}, + {.oaxis = 36, .raxis = 97 }, {.oaxis = 38, .raxis = 320}, + {.oaxis = 39, .raxis = 182}, {.oaxis = 40, .raxis = 45 }, + {.oaxis = 41, .raxis = 267}, {.oaxis = 43, .raxis = 130}, + {.oaxis = 44, .raxis = 352}, {.oaxis = 45, .raxis = 215}, + {.oaxis = 46, .raxis = 77 }, {.oaxis = 47, .raxis = 300}, + {.oaxis = 48, .raxis = 162}, {.oaxis = 49, .raxis = 25 }, + {.oaxis = 50, .raxis = 247}, {.oaxis = 51, .raxis = 110}, + {.oaxis = 52, .raxis = 332}, {.oaxis = 53, .raxis = 195}, + {.oaxis = 54, .raxis = 57 }, {.oaxis = 55, .raxis = 280}, + {.oaxis = 56, .raxis = 142}, {.oaxis = 57, .raxis = 5 }, + {.oaxis = 58, .raxis = 227}, {.oaxis = 59, .raxis = 90 }, + {.oaxis = 60, .raxis = 312} +}; +ANT_ANGLE antNrrwPattern[NUM_ANT_NRRW_PATTERN] = { + {.oaxis = 0 , .raxis = 222}, {.oaxis = 7 , .raxis = 85 }, + {.oaxis = 10, .raxis = 307}, {.oaxis = 13, .raxis = 170}, + {.oaxis = 15, .raxis = 32 }, {.oaxis = 17, .raxis = 255}, + {.oaxis = 18, .raxis = 117}, {.oaxis = 20, .raxis = 340}, + {.oaxis = 21, .raxis = 202}, {.oaxis = 22, .raxis = 65 }, + {.oaxis = 24, .raxis = 287}, {.oaxis = 25, .raxis = 150}, + {.oaxis = 26, .raxis = 12 }, {.oaxis = 27, .raxis = 235}, + {.oaxis = 28, .raxis = 97 }, {.oaxis = 29, .raxis = 320}, + {.oaxis = 30, .raxis = 182}, {.oaxis = 31, .raxis = 45 }, + {.oaxis = 32, .raxis = 267}, {.oaxis = 33, .raxis = 130}, + {.oaxis = 34, .raxis = 352}, {.oaxis = 34, .raxis = 215}, + {.oaxis = 35, .raxis = 77 }, {.oaxis = 36, .raxis = 300}, + {.oaxis = 37, .raxis = 162}, {.oaxis = 38, .raxis = 25 }, + {.oaxis = 38, .raxis = 247}, {.oaxis = 39, .raxis = 110}, + {.oaxis = 40, .raxis = 332}, {.oaxis = 41, .raxis = 195}, + {.oaxis = 41, .raxis = 57 }, {.oaxis = 42, .raxis = 280}, + {.oaxis = 43, .raxis = 142}, {.oaxis = 44, .raxis = 5 }, + {.oaxis = 44, .raxis = 227}, {.oaxis = 45, .raxis = 90 }, + {.oaxis = 46, .raxis = 312}, {.oaxis = 46, .raxis = 175}, + {.oaxis = 47, .raxis = 37 }, {.oaxis = 48, .raxis = 260}, + {.oaxis = 48, .raxis = 122}, {.oaxis = 49, .raxis = 345}, + {.oaxis = 49, .raxis = 207}, {.oaxis = 50, .raxis = 70 }, + {.oaxis = 51, .raxis = 292}, {.oaxis = 51, .raxis = 155}, + {.oaxis = 52, .raxis = 17 }, {.oaxis = 53, .raxis = 240}, + {.oaxis = 53, .raxis = 102}, {.oaxis = 54, .raxis = 325}, + {.oaxis = 54, .raxis = 187}, {.oaxis = 55, .raxis = 50 }, + {.oaxis = 55, .raxis = 272}, {.oaxis = 56, .raxis = 135}, + {.oaxis = 57, .raxis = 357}, {.oaxis = 57, .raxis = 220}, + {.oaxis = 58, .raxis = 82 }, {.oaxis = 58, .raxis = 305}, + {.oaxis = 59, .raxis = 167}, {.oaxis = 59, .raxis = 30 }, + {.oaxis = 60, .raxis = 252} +}; +#elif defined(PHY_BEAM_SET_PRESET_LSX) +ANT_ANGLE antSubnrrwPattern[NUM_ANT_SUBNRRW_PATTERN] = { + {.oaxis = 0 , .raxis =2225},{.oaxis = 96 , .raxis =850 }, + {.oaxis = 135, .raxis =3075},{.oaxis = 166, .raxis =1700}, + {.oaxis = 192, .raxis =325 },{.oaxis = 215, .raxis =2550}, + {.oaxis = 236, .raxis =1174},{.oaxis = 255, .raxis =3399}, + {.oaxis = 273, .raxis =2024},{.oaxis = 290, .raxis =649 }, + {.oaxis = 306, .raxis =2874},{.oaxis = 321, .raxis =1499}, + {.oaxis = 336, .raxis =124 },{.oaxis = 350, .raxis =2349}, + {.oaxis = 363, .raxis =974 },{.oaxis = 377, .raxis =3199}, + {.oaxis = 389, .raxis =1824},{.oaxis = 402, .raxis =449 }, + {.oaxis = 414, .raxis =2674},{.oaxis = 426, .raxis =1298}, + {.oaxis = 438, .raxis =3523},{.oaxis = 449, .raxis =2148}, + {.oaxis = 460, .raxis =773 },{.oaxis = 471, .raxis =2998}, + {.oaxis = 482, .raxis =1623},{.oaxis = 492, .raxis =248 }, + {.oaxis = 503, .raxis =2473},{.oaxis = 513, .raxis =1098}, + {.oaxis = 523, .raxis =3323},{.oaxis = 533, .raxis =1948}, + {.oaxis = 543, .raxis =573 },{.oaxis = 553, .raxis =2798}, + {.oaxis = 563, .raxis =1422},{.oaxis = 572, .raxis =47 }, + {.oaxis = 581, .raxis =2272},{.oaxis = 591, .raxis =897 }, + {.oaxis = 600, .raxis =3122} +}; +ANT_ANGLE antNrrwPattern[NUM_ANT_NRRW_PATTERN] = { + {.oaxis = 0 , .raxis =2225},{.oaxis = 74 , .raxis =850 }, + {.oaxis = 105, .raxis =3075},{.oaxis = 128, .raxis =1700}, + {.oaxis = 148, .raxis =325 },{.oaxis = 166, .raxis =2550}, + {.oaxis = 182, .raxis =1174},{.oaxis = 197, .raxis =3399}, + {.oaxis = 210, .raxis =2024},{.oaxis = 223, .raxis =649 }, + {.oaxis = 236, .raxis =2874},{.oaxis = 247, .raxis =1499}, + {.oaxis = 258, .raxis =124 },{.oaxis = 269, .raxis =2349}, + {.oaxis = 280, .raxis =974 },{.oaxis = 290, .raxis =3199}, + {.oaxis = 299, .raxis =1824},{.oaxis = 309, .raxis =449 }, + {.oaxis = 318, .raxis =2674},{.oaxis = 327, .raxis =1298}, + {.oaxis = 336, .raxis =3523},{.oaxis = 344, .raxis =2148}, + {.oaxis = 352, .raxis =773 },{.oaxis = 361, .raxis =2998}, + {.oaxis = 369, .raxis =1623},{.oaxis = 377, .raxis =248 }, + {.oaxis = 384, .raxis =2473},{.oaxis = 392, .raxis =1098}, + {.oaxis = 399, .raxis =3323},{.oaxis = 407, .raxis =1948}, + {.oaxis = 414, .raxis =573 },{.oaxis = 421, .raxis =2798}, + {.oaxis = 428, .raxis =1422},{.oaxis = 435, .raxis =47 }, + {.oaxis = 442, .raxis =2272},{.oaxis = 449, .raxis =897 }, + {.oaxis = 456, .raxis =3122},{.oaxis = 462, .raxis =1747}, + {.oaxis = 469, .raxis =372 },{.oaxis = 475, .raxis =2597}, + {.oaxis = 482, .raxis =1222},{.oaxis = 488, .raxis =3447}, + {.oaxis = 495, .raxis =2072},{.oaxis = 501, .raxis =697 }, + {.oaxis = 507, .raxis =2922},{.oaxis = 513, .raxis =1546}, + {.oaxis = 519, .raxis =171 },{.oaxis = 525, .raxis =2396}, + {.oaxis = 531, .raxis =1021},{.oaxis = 537, .raxis =3246}, + {.oaxis = 543, .raxis =1871},{.oaxis = 549, .raxis =496 }, + {.oaxis = 555, .raxis =2721},{.oaxis = 561, .raxis =1346}, + {.oaxis = 566, .raxis =3571},{.oaxis = 572, .raxis =2196}, + {.oaxis = 578, .raxis =821 },{.oaxis = 583, .raxis =3045}, + {.oaxis = 589, .raxis =1670},{.oaxis = 594, .raxis =295 }, + {.oaxis = 600, .raxis =2520} +}; +#else +PHY_ANT_ANGLE antSubnrrwPattern[NUM_ANT_SUBNRRW_PATTERN] = {0}; +PHY_ANT_ANGLE antNrrwPattern[NUM_ANT_NRRW_PATTERN] = {0}; +#endif +/*****************************************************************************/ +/** + * @brief + * + * @param antCoinfoPtr + * + * @return + * + ******************************************************************************/ +int32_t Phy_AntCoinfoInit(PHY_ANT_CONFIG *antCoinfoPtr) +{ + if (antCoinfoPtr == NULL) + { + return FAILURE; + } + antCoinfoPtr->head = ANT_COINFO_HEAD; + antCoinfoPtr->tail = ANT_COINFO_TAIL; + antCoinfoPtr->ctrlWord = 0x00; +#ifdef ANT_HIGH_POWER + antCoinfoPtr->antMode = ATN_MODE_HIGH; +#else + antCoinfoPtr->antMode = ATN_MODE_DEFAULT; +#endif + + + // FIXME: Dummy default value. + // off axis angle setting + antCoinfoPtr->oaxis[0] = 0; + antCoinfoPtr->oaxis[1] = 0; + // round axis angle setting + antCoinfoPtr->raxis[0] = 0; + antCoinfoPtr->raxis[1] = 0; + // *********************** + + antCoinfoPtr->antFreq[0] = (uint8_t)(DEFAULT_CENTRTAL_FREQ); + antCoinfoPtr->antFreq[1] = (uint8_t)(DEFAULT_CENTRTAL_FREQ >> 8); + + // FIXME: Dummy default value. + // trSelect + antCoinfoPtr->trSlect = 0; + // Antenna attenuation setting + antCoinfoPtr->antAtt = 20; + // phase setting + antCoinfoPtr->phase = 0; + // *********************** + + antCoinfoPtr->rxtxMode = RXTXMODE_RX; + antCoinfoPtr->calibrMode = CALIBRMODE_NORMAL; + + // FIXME: Dummy default value. + // DD enable + antCoinfoPtr->ddEn = 0; + // DD mgc + antCoinfoPtr->ddMgc = 0; + // RF mode control + antCoinfoPtr->rfCtrl = 0; + // RF MGC control + antCoinfoPtr->rfMgc = 0; + // RF channel 1&2 calibration mgc + antCoinfoPtr->rf12CalMgc = 0; + // RF channel 2&3 calibration mgc + antCoinfoPtr->rf34CalMgc = 0; + // Receive channel 1 MGC + antCoinfoPtr->rcv1Mgc = 0; + // Receive channel 2 MGC + antCoinfoPtr->rcv2Mgc = 0; + // Receive channel 3 MGC + antCoinfoPtr->rcv3Mgc = 0; + // Receive channel 4 MGC + antCoinfoPtr->rcv4Mgc = 0; + // *********************** + + memset(antCoinfoPtr->dummy, 0x00, sizeof(antCoinfoPtr->dummy)); + + return SUCCESS; +} + +int32_t Phy_SetBeamNo(PHY_INST *instPtr, int32_t beamNo) +{ + if(instPtr->beamWd.next == ANT_BEAM_8){ + if (beamNo >= NUM_ANT_NRRW_PATTERN) + { + return FAILURE; + } + else + { + instPtr->beamNo.next = beamNo; + instPtr->antCoinfoPtr.oaxis[1] = (uint8_t)(antNrrwPattern[beamNo].oaxis); + instPtr->antCoinfoPtr.oaxis[0] = (uint8_t)((antNrrwPattern[beamNo].oaxis) >> 8); + instPtr->antCoinfoPtr.raxis[1] = (uint8_t)(antNrrwPattern[beamNo].raxis); + instPtr->antCoinfoPtr.raxis[0] = (uint8_t)((antNrrwPattern[beamNo].raxis) >> 8); + return SUCCESS; + } + } + else if(instPtr->beamWd.next == ANT_BEAM_25){ + if (beamNo >= NUM_ANT_SUBNRRW_PATTERN) + { + return FAILURE; + } + else + { + instPtr->beamNo.next = beamNo; + instPtr->antCoinfoPtr.oaxis[1] = (uint8_t)(antSubnrrwPattern[beamNo].oaxis); + instPtr->antCoinfoPtr.oaxis[0] = (uint8_t)((antSubnrrwPattern[beamNo].oaxis) >> 8); + instPtr->antCoinfoPtr.raxis[1] = (uint8_t)(antSubnrrwPattern[beamNo].raxis); + instPtr->antCoinfoPtr.raxis[0] = (uint8_t)((antSubnrrwPattern[beamNo].raxis) >> 8); + return SUCCESS; + } + } + else{ + // Beam number assign not support. + // Assign default angle (0,0) + instPtr->beamNo.next = 0; + instPtr->antCoinfoPtr.oaxis[1] = 0; + instPtr->antCoinfoPtr.oaxis[0] = 0; + instPtr->antCoinfoPtr.raxis[1] = 0; + instPtr->antCoinfoPtr.raxis[0] = 0; + DBG_WARNING("Using default beam number..."); + return SUCCESS; + } +} + +int32_t Phy_SetBeamWidth(PHY_INST *instPtr, PHY_ANT_BEAM_WIDTH beamWidth) +{ + uint8_t beamConfig = instPtr->antCoinfoPtr.antMode & (~ANT_MODE_BEAM_MASK); + switch (beamWidth) + { + case ANT_BEAM_120: + beamConfig |= ANT_MODE_WIDE_BEAM_3; + break; + case ANT_BEAM_60: + beamConfig |= ANT_MODE_WIDE_BEAM_2; + break; + case ANT_BEAM_25: + beamConfig |= ANT_MODE_WIDE_BEAM_1; + break; + case ANT_BEAM_8: + beamConfig |= ANT_MODE_NARROR_BEAM; + break; + default: + DBG_ERROR("Beam width code: 0x%08X is illegal.\n\r", beamWidth); + return EPARAM; + break; + } + instPtr->antCoinfoPtr.antMode = beamConfig; + instPtr->beamWd.next = beamWidth; + return SUCCESS; +} + +// Common version radius double input +int32_t Phy_SetBeamAngle(PHY_INST *instPtr, double offAx, double rndAx) +{ + uint16_t offAxDeg = 0; + uint16_t rndAxDeg = 0; + offAxDeg = (offAx > 0) ? (((int32_t)(offAx * 180 / ANT_PI)) % 360) : (((int32_t)(offAx * 180 / ANT_PI)) % 360 + 360); + rndAxDeg = (rndAx > 0) ? (((int32_t)(rndAx * 180 / ANT_PI)) % 360) : (((int32_t)(rndAx * 180 / ANT_PI)) % 360 + 360); + if (offAxDeg > 60) + { + DBG_ERROR("Angle out of range, off axis angle: %u(should be 0~60), round axis angle: %u(should be 0~360).", + offAxDeg, rndAxDeg); + return EPARAM; + } + offAxDeg = offAxDeg * 10; + rndAxDeg = rndAxDeg * 10; + instPtr->antCoinfoPtr.oaxis[1] = (uint8_t)offAxDeg; + instPtr->antCoinfoPtr.oaxis[0] = (uint8_t)(offAxDeg >> 8); + instPtr->antCoinfoPtr.raxis[1] = (uint8_t)rndAxDeg; + instPtr->antCoinfoPtr.raxis[0] = (uint8_t)(rndAxDeg >> 8); + return SUCCESS; +} + diff --git a/datalink814_ge/src/phy_ctrl/phy_ctrl.c b/datalink814_ge/src/phy_ctrl/phy_ctrl.c new file mode 100644 index 0000000..4dc8bb3 --- /dev/null +++ b/datalink814_ge/src/phy_ctrl/phy_ctrl.c @@ -0,0 +1,813 @@ +/*****************************************************************************/ +/** + * Description: Implementation of physical control functions + * + * Date: 2021-11-16 00:08 + * LastEditTime: 2023-04-23 17:48 + * Revisions: Rev 0.2 + * History: + * [2021-11-16]: Initial version. + * [2022-06-18]: New branch for glink control purpose: + * -Add poll mode, physical layer will start Tx/Rx procedure + * at specific time stamp. + * -Add 61/37 beam switch + * -Code simplification. + * [2023-04-24]: Feature add: + * - Read frame type from PL status register. + * + * Copyright(c) 2021 Beijing Institute of Technology. + * Lab of Communication and Networking + * + ******************************************************************************/ + +/***************************** Include Files *********************************/ +#include +#include +#include +#include "phy_ctrl.h" +#include "../util/util.h" +#include "../error.h" +#ifndef EMULATION +#include "xbram.h" +#endif +/************************** Constant Definitions *****************************/ +/***************** Macros (Inline Functions) Definitions *********************/ +/************************** Function Prototypes ******************************/ +static void Phy_RcdShift(PHY_RCD* rcd, int32_t netxVal); +static int32_t Phy_SetSendData(PHY_INST* instPtr, L1_FRAME_TYPE frameType, uint8_t* dataBuff); + +/**************************** Type Definitions *******************************/ + +/************************** Variable Definitions *****************************/ + +/*****************************************************************************/ +/** + * @brief Setup data will be sent in next slot. + * + * @param instPtr A pointer to physical layer control instance. + * + * @return FAILURE Error occurred. + * SUCCESS Setting data successful. + * + ******************************************************************************/ +static int32_t Phy_SetSendData(PHY_INST* instPtr, L1_FRAME_TYPE frameType, uint8_t* dataBuff) { + ASSERT(instPtr != NULL); + ASSERT(dataBuff != NULL); + uint32_t frameLen, sendCmd; + + frameLen = Phy_GetFrameLen(frameType); + + if (frameLen == L1_FRAME_NONE_LEN) { + DBG_ERROR("Invalid frame length.\n"); + return EPARAM; + } + instPtr->sendDataOffset = (TXRXDATA_MAX_LEN >> 1) - instPtr->sendDataOffset; + memcpy((uint8_t*)(instPtr->sendDataAddr + instPtr->sendDataOffset), dataBuff, frameLen); + + sendCmd = frameLen & SEND_DATA_CMD_LEN_MASK; + sendCmd |= (instPtr->sendDataOffset << SEND_DATA_CMD_OFFSET_SHIFT) & SEND_DATA_CMD_OFFSET_MASK; + + // Physical layer start fetching data. + PhyWrite(instPtr, SEND_DATA_CMD, sendCmd); + return SUCCESS; +} + + +/*****************************************************************************/ +/** + * @brief Check whether a frame was detected. (Do not check if the frame was + * deoced.) + * + * @param instPtr A pointer to physical layer control instance. + * + * @return true + * false + * + ******************************************************************************/ +inline bool Phy_IsFrameDetected(PHY_INST* instPtr) { + ASSERT(instPtr != NULL); + if(instPtr->TOR.last == PHY_TOR_RX && instPtr->isAcq && instPtr->isFrameSync) { + return true; + } + else { + return false; + } +} + +/*****************************************************************************/ +/** + * @brief Check whether a frame was received. (Do not check if the frame was + * crashed.) + * + * @param instPtr A pointer to physical layer control instance. + * + * @return true + * false + * + ******************************************************************************/ +inline bool Phy_IsFrameReceived(PHY_INST* instPtr) { + ASSERT(instPtr != NULL); + if(instPtr->TOR.last == PHY_TOR_RX && instPtr->isAcq + && instPtr->isFrameSync && instPtr->isDecode) { + return true; + } + else { + return false; + } +} + +/*****************************************************************************/ +/** + * @brief Check whether a frame was valid. (if the frame was crashed, it will + * be regarded as not valid. + * + * @param instPtr + * + * @return true + * false + * + ******************************************************************************/ +inline bool Phy_IsFrameValid(PHY_INST* instPtr) { + ASSERT(instPtr != NULL); + if (instPtr->TOR.last == PHY_TOR_RX && instPtr->isAcq && instPtr->isFrameSync + && instPtr->isDecode && instPtr->isValid) { + return true; + } + else { + return false; + } +} + +/*****************************************************************************/ +/** + * @brief Get frame type of the frame in receive data buffer (Base on PL Record). + * + * @param instPtr A pointer to physical layer control instance. + * + * @return Layer2 frame type. Refer "frame_def.h" + * + ******************************************************************************/ +inline L1_FRAME_TYPE Phy_GetLastRecvFrameType(PHY_INST *instPtr) { + ASSERT(instPtr != NULL); + if (Phy_IsFrameReceived(instPtr) == false) { + return L1_NONE_FRAME; + } + int32_t frame_type = (PhyRead(instPtr, PHY_MODE_CTRL) & PHY_MODE_CTRL_FRAME_MASK) + >> PHY_MODE_CTRL_FRAME_SHIFT; + if(frame_type < L1_1M2BPS_5MS_FRAME) + return frame_type; + else + return L1_NONE_FRAME; +} + +/*****************************************************************************/ +/** + * @brief Get frame type of the frame was sent in last slot. + * + * @param instPtr A pointer to physical layer control instance. + * + * @return Layer2 frame type. Refer "frame_def.h" + * + ******************************************************************************/ +inline L1_FRAME_TYPE Phy_GetLastSendFrameType(PHY_INST* instPtr) { + ASSERT(instPtr != NULL); + if (instPtr->TOR.last != PHY_TOR_TX) { + return L1_NONE_FRAME; + } + return instPtr->frameType.last; +} + +/*****************************************************************************/ +/** + * @brief Shift l1 status record.(newval->next->curr->last) + * + * @param instPtr A pointer to physical layer control instance. + * + * @return NONE. + * + ******************************************************************************/ +static void Phy_RcdShift(PHY_RCD* rcd, int32_t netxVal){ + ASSERT(rcd != NULL); + rcd->last = rcd->curr; + rcd->curr = rcd->next; + rcd->next = netxVal; +} + +/*****************************************************************************/ +/** + * @brief Get corresponding frame length in byte of L1 frame. + * + * @param frameType + * + * @return Corresponding frame length + * L1_FRAME_NONE_LEN if the frame type code cannot be recognized. + * + ******************************************************************************/ +uint32_t Phy_GetFrameLen(L1_FRAME_TYPE frameType) { + switch (frameType) { + case L1_2KBPS_20MS_FRAME: + return L1_FRAME_2KBPS_20MS_LEN; + case L1_2KBPS_100MS_FRAME: + return L1_FRAME_2KBPS_100MS_LEN; + case L1_10KBPS_10MS_FRAME: + return L1_FRAME_10KBPS_10MS_LEN; + case L1_10KBPS_20MS_FRAME: + return L1_FRAME_10KBPS_20MS_LEN; + case L1_40KBPS_20MS_FRAME: + return L1_FRAME_40KBPS_20MS_LEN; + case L1_40KBPS_10MS_FRAME: + return L1_FRAME_40KBPS_10MS_LEN; + case L1_200KBPS_5MS_FRAME: + return L1_FRAME_200KBPS_5MS_LEN; + case L1_1M2BPS_5MS_FRAME: + return L1_FRAME_1M2BPS_5MS_LEN; + default: + return L1_FRAME_NONE_LEN; + } +} + +/*****************************************************************************/ +/** + * @brief Update physical layer status cache. + * + * @param instPtr A pointer to physical layer control instance. + * + * @return NONE. + * + ******************************************************************************/ +void Phy_UpdateState(PHY_INST* instPtr) { + ASSERT(instPtr != NULL); + + Phy_RcdShift(&(instPtr->TOR),PHY_TOR_SUSPEND); + Phy_RcdShift(&(instPtr->frameType),L1_NONE_FRAME); + Phy_RcdShift(&(instPtr->antNo), INIT_ANT_NO); + Phy_RcdShift(&(instPtr->beamNo), INIT_BEAM_NO); + Phy_RcdShift(&(instPtr->beamWd), INIT_ANT_WD); + /* Update Frame Sate. */ + uint32_t txrxSate = PhyRead(instPtr, TXRX_STATE); + instPtr->isAcq = ((txrxSate & TXRX_STATE_ACQ_MASK) == TXRX_STATE_ACQ_SUCCESS) ? true : false; + instPtr->isFrameSync = ((txrxSate & TXRX_STATE_FSYNC_MASK) == TXRX_STATE_FSYNC_SUCCESS) ? true : false; + instPtr->isDecode = ((txrxSate & TXRX_STATE_DECODE_MASK) == TXRX_STATE_DECODE_SUCCESS) ? true : false; + if (Phy_IsFrameReceived(instPtr)) { + instPtr->isValid = ((txrxSate & TXRX_STATE_CRC_MASK) == TXRX_STATE_CRC_OK) ? true : false; + } + else { + instPtr->isValid = false; + } + return; +} + + +/*****************************************************************************/ +/** + * @brief Initialize physical layer instance accordingly. + * + * @param instPtr a pointer to physical instance + * @param phyConfig a pointer to cinfiguration staructure. + * + * @return SUCCESS + * + ******************************************************************************/ +int32_t Phy_InstInit(PHY_INST** instPtr, PHY_CONFIG *phyConfig) { + ASSERT(instPtr != NULL); + ASSERT(phyConfig != NULL); + int32_t Status; + + *instPtr = (PHY_INST*) malloc(sizeof(PHY_INST)); + if ((*instPtr) == NULL) { + return EALLOC; + } + memcpy(&(*instPtr)->phyCofig, phyConfig, sizeof(PHY_CONFIG)); + + (*instPtr)->isPhyEn = false; + (*instPtr)->isAcq = false; + (*instPtr)->isFrameSync = false; + (*instPtr)->isDecode = false; + (*instPtr)->isValid = false; + (*instPtr)->isPresetHop = false; + (*instPtr)->antConfigOffset = 0; + (*instPtr)->sendDataOffset = 0; + Phy_AntCoinfoInit(&((*instPtr)->antCoinfoPtr)); + + memset(&((*instPtr))->TOR, PHY_TOR_SUSPEND, sizeof(PHY_RCD)); + memset(&((*instPtr)->frameType), L1_NONE_FRAME, sizeof(PHY_RCD)); + memset(&((*instPtr)->antNo), (int32_t)INIT_BEAM_NO, sizeof(PHY_RCD)); + memset(&((*instPtr)->beamNo), (int32_t)INIT_ANT_NO, sizeof(PHY_RCD)); + memset(&((*instPtr)->beamWd), (int32_t)INIT_ANT_WD, sizeof(PHY_RCD)); + +#ifndef EMULATION + XBram antInfoBram; + XBram txFrameBram; + XBram rxFrameBram; + + XBram_Config *ConfigPtr; + ConfigPtr = XBram_LookupConfig(phyConfig->antBramId); + if (ConfigPtr == NULL) { + Status = EDINVAL; + goto error; + } + Status = XBram_CfgInitialize(&antInfoBram, ConfigPtr, + ConfigPtr->CtrlBaseAddress); + if (Status != SUCCESS) { + goto error; + } + /* + * Execute the BRAM driver selftest. + */ + Status = XBram_SelfTest(&antInfoBram, 0); + if (Status != SUCCESS) { + goto error; + } + + ConfigPtr = XBram_LookupConfig(phyConfig->txBramId); + if (ConfigPtr == NULL) { + Status = EDINVAL; + goto error; + } + Status = XBram_CfgInitialize(&txFrameBram, ConfigPtr, + ConfigPtr->CtrlBaseAddress); + if (Status != SUCCESS) { + goto error; + } + /* + * Execute the BRAM driver selftest. + */ + Status = XBram_SelfTest(&txFrameBram, 0); + if (Status != SUCCESS) { + goto error; + } + + ConfigPtr = XBram_LookupConfig(phyConfig->rxBramId); + if (ConfigPtr == NULL) { + Status = EDINVAL; + goto error; + } + Status = XBram_CfgInitialize(&rxFrameBram, ConfigPtr, + ConfigPtr->CtrlBaseAddress); + if (Status != SUCCESS) { + goto error; + } + /* + * Execute the BRAM driver selftest. + */ + Status = XBram_SelfTest(&rxFrameBram, 0); + if (Status != SUCCESS) { + goto error; + } + + (*instPtr)->antConfigAddr = antInfoBram.Config.MemBaseAddress; + (*instPtr)->recvDataAddr = rxFrameBram.Config.MemBaseAddress; + (*instPtr)->sendDataAddr = txFrameBram.Config.MemBaseAddress; +#else + (*instPtr)->antConfigAddr = (uintptr_t)calloc(ANTCONFIG_MAX_LEN/sizeof(uint64_t), sizeof(uint64_t)); + if ((*instPtr)->antConfigAddr == (uintptr_t)NULL) { + Status = EALLOC; + goto error; + } + (*instPtr)->recvDataAddr = (uintptr_t)calloc(TXRXDATA_MAX_LEN/sizeof(uint64_t), sizeof(uint64_t)); + if ((*instPtr)->recvDataAddr == (uintptr_t)NULL) { + Status = EALLOC; + goto error; + } + (*instPtr)->sendDataAddr = (uintptr_t)calloc(TXRXDATA_MAX_LEN/sizeof(uint64_t), sizeof(uint64_t)); + if ((*instPtr)->sendDataAddr == (uintptr_t)NULL) { + Status = EALLOC; + goto error; + } +#endif + return SUCCESS; +error: + Phy_Destroy(*instPtr); + return Status; +} + +/*****************************************************************************/ +/** + * @brief Destroy physical layer inctance, free allocated memory. + * + * @param instPtr a pointer to physical instance + * + * @return NONE + * + ******************************************************************************/ +void Phy_Destroy(PHY_INST* instPtr) { + if (instPtr == NULL){ + return; + } +#ifdef EMULATION + free((void*)instPtr->antConfigAddr); + free((void*)instPtr->recvDataAddr); + free((void*)instPtr->sendDataAddr); +#endif + free(instPtr); +} + +/*****************************************************************************/ +/** + * @brief Start physical layer + * + * @param instPtr a pointer to physical instance + * + * @return NONE + * + ******************************************************************************/ +void Phy_Start(PHY_INST* instPtr) { + ASSERT(instPtr != NULL); + uint32_t phyMainCtrl = PhyRead(instPtr, PHY_MAIN_CTRL); + if((phyMainCtrl & PHY_MAIN_CTRL_EN_MASK) == PHY_MAIN_CTRL_EN_EN) { + DBG_WARNING("Physical layer was allready enabled.\n"); + } + instPtr->isPhyEn = true; + // Enable CRC check automatically + PhyWrite(instPtr, PHY_MAIN_CTRL, (phyMainCtrl | PHY_MAIN_CTRL_EN_EN)); +} + +/*****************************************************************************/ +/** + * @brief Halt physical layer operation + * + * @param instPtr a pointer to physical instance + * + * @return NONE + * + ******************************************************************************/ +void Phy_Halt(PHY_INST* instPtr) { + ASSERT(instPtr != NULL); + uint32_t phyMainCtrl = PhyRead(instPtr, PHY_MAIN_CTRL); + if((phyMainCtrl & PHY_MAIN_CTRL_EN_MASK) == PHY_MAIN_CTRL_EN_DSBL) { + DBG_WARNING("Physical layer was allready halted.\n"); + } + instPtr->isPhyEn = false; + PhyWrite(instPtr, PHY_MAIN_CTRL, (phyMainCtrl & (~PHY_MAIN_CTRL_EN_MASK))); +} + +/*****************************************************************************/ +/** + * @brief Set physical layer working mode. + * + * @param instPtr a pointer to physical instance + * @param modeCod intened mode code + * + * @return SUCCESS + * other + * + ******************************************************************************/ +int32_t Phy_SetMode(PHY_INST* instPtr, PHY_MODE modeCod) { + ASSERT(instPtr != NULL); + + uint32_t phyMainCtrl = PhyRead(instPtr, PHY_MAIN_CTRL) & ~PHY_MAIN_CTRL_MODE_MASK; + switch (modeCod) { + case PHY_MODE_NONE: + phyMainCtrl |= PHY_MAIN_CTRL_MODE_NONE; + break; + case PHY_MODE_LISTEN: + phyMainCtrl |= PHY_MAIN_CTRL_MODE_LISTEN; + break; + case PHY_MODE_SCHEDULE: + phyMainCtrl |= PHY_MAIN_CTRL_MODE_SCHEDULE; + break; + case PHY_MODE_PULL: + phyMainCtrl |= PHY_MAIN_CTRL_MODE_PULL; + break; + default: + return FAILURE; + break; + } + PhyWrite(instPtr, PHY_MAIN_CTRL, phyMainCtrl); + return SUCCESS; +} + +/*****************************************************************************/ +/** + * @brief Setup next slot operation. + * + * @param instPtr a pointer to physical instance + * @param txrxMode tor type of next slot + * @param frameType frame type of next slot + * + * @return SUCCESS + * other + * + ******************************************************************************/ +int32_t Phy_SetupNextSlot(PHY_INST* instPtr, PHY_TOR_TYPE txrxMode, + L1_FRAME_TYPE frameType, uint8_t* dataBuff) { + ASSERT(instPtr != NULL); + int32_t Status; + uint32_t phyModeCtrl, hopNum; + uint16_t* hopPattern = NULL; + // Implement a ping-pong flow, offset always is 0 or half of buffer depth. + instPtr->antConfigOffset = (ANTCONFIG_MAX_LEN >> 1) - instPtr->antConfigOffset; + uint32_t antConfigAddr = instPtr->antConfigAddr + instPtr->antConfigOffset; + + instPtr->TOR.next = txrxMode; + instPtr->frameType.next = frameType; + + switch (txrxMode) { + case PHY_TOR_SUSPEND: + phyModeCtrl = PHY_MODE_CTRL_TOR_SUSPEND; + break; + case PHY_TOR_RX: + phyModeCtrl = PHY_MODE_CTRL_TOR_RX; + break; + case PHY_TOR_TX: + phyModeCtrl = PHY_MODE_CTRL_TOR_TX; + break; + default: + return EPARAM; + } + switch (frameType) { + case L1_2KBPS_20MS_FRAME: + phyModeCtrl |= PHY_MODE_CTRL_FRAME_2KBPS_20MS; + hopNum = L1_FRAME_2KBPS_20MS_HOPS; + hopPattern = hopPattern_10KBPS_10MS; + break; + case L1_2KBPS_100MS_FRAME: + phyModeCtrl |= PHY_MODE_CTRL_FRAME_2KBPS_100MS; + hopNum = L1_FRAME_2KBPS_100MS_HOPS; + hopPattern = hopPattern_2KBPS_100MS; + break; + case L1_10KBPS_10MS_FRAME: + phyModeCtrl |= PHY_MODE_CTRL_FRAME_10KBPS_10MS; + hopNum = L1_FRAME_10KBPS_10MS_HOPS; + hopPattern = hopPattern_10KBPS_10MS; + break; + case L1_10KBPS_20MS_FRAME: + phyModeCtrl |= PHY_MODE_CTRL_FRAME_10KBPS_20MS; + hopNum = L1_FRAME_10KBPS_20MS_HOPS; + hopPattern = hopPattern_10KBPS_20MS; + break; + case L1_40KBPS_20MS_FRAME: + phyModeCtrl |= PHY_MODE_CTRL_FRAME_200KBPS_5MS; + hopNum = L1_FRAME_200KBPS_5MS_HOPS; + hopPattern = hopPattern_200KBPS_5MS; + break; + case L1_40KBPS_10MS_FRAME: + phyModeCtrl |= PHY_MODE_CTRL_FRAME_40KBPS_10MS; + hopNum = L1_FRAME_40KBPS_10MS_HOPS; + hopPattern = hopPattern_40KBPS_10MS; + break; + case L1_200KBPS_5MS_FRAME: + phyModeCtrl |= PHY_MODE_CTRL_FRAME_200KBPS_5MS; + hopNum = L1_FRAME_200KBPS_5MS_HOPS; + hopPattern = hopPattern_200KBPS_5MS; + break; + case L1_1M2BPS_5MS_FRAME: + phyModeCtrl |= PHY_MODE_CTRL_FRAME_1M2BPS_5MS; + hopNum = L1_FRAME_1M2BPS_5MS_HOPS; + hopPattern = hopPattern_1M2BPS_5MS; + break; + default: + return EPARAM; + break; + } + hopPattern = (instPtr->isPresetHop) ? hopPattern : hopPattern_Config; + + uint8_t* dataSrcPtr = (uint8_t*)(&(instPtr->antCoinfoPtr)); + for (int32_t i = 0; i < hopNum; i++) { + instPtr->antCoinfoPtr.antFreq[1] = (uint8_t)(hopPattern[i] & 0x00FF); + instPtr->antCoinfoPtr.antFreq[0] = (uint8_t)( + (hopPattern[i] >> 8) & 0x00FF); + memcpy((uint8_t*) (antConfigAddr + i * sizeof(PHY_ANT_CONFIG)), + dataSrcPtr, sizeof(PHY_ANT_CONFIG)); + } + uint32_t antCtrl = (instPtr->antConfigOffset & ANT_CONFIG_OFFSET_MASK) + | ((hopNum << ANT_CONFIG_NUM_SHIFT) & ANT_CONFIG_NUM_MASK) + | ((sizeof(PHY_ANT_CONFIG) << ANT_CONFIG_LEN_SHIFT) & ANT_CONFIG_LEN_MASK); + +/* + memcpy((uint8_t*)antConfigDataAddr, hopPattern, hopNum*sizeof(uint16_t)); + uint32_t antCtrl = (instPtr->antCoinfigOffset & ANT_CONFIG_OFFSET_MASK) + | ((hopNum << ANT_CONFIG_NUM_SHIFT) & ANT_CONFIG_NUM_MASK) + | ((sizeof(uint16_t) << ANT_CONFIG_LEN_SHIFT) & ANT_CONFIG_LEN_MASK); +*/ + PhyWrite(instPtr, PHY_MODE_CTRL, phyModeCtrl|PHY_MODE_CTRL_CRC_EN); + PhyWrite(instPtr, ANT_CONFIG, antCtrl); + + + // Trigger physical configuration. + if(txrxMode == PHY_TOR_TX) { + Status = Phy_SetSendData(instPtr, frameType, dataBuff); + if(Status != SUCCESS) { + DBG_ERROR("Failed to apply send data.\n"); + return Status; + } + } + PhyWrite(instPtr, SLOT_CMD, SLOT_CMD_KEY); // Phy statr fetching data. + return SUCCESS; +} + + +/*****************************************************************************/ +/** + * @brief Get coarse frequency estimation of last valid frame. + * + * @param instPtr a pointer to physical instance + * + * @return SUCCESS If load the data successfully. + * FAILURE If last receive frame is not valid. + * + ******************************************************************************/ + +double Phy_GetCoarseFreqEst(PHY_INST* instPtr) { + ASSERT(instPtr != NULL); + uint32_t regValue; + uint8_t acqFreqIdx; + int8_t syncFreqIdx; + L1_FRAME_TYPE frameType; + double freqEst; + + frameType = Phy_GetLastRecvFrameType(instPtr); + if(frameType > L1_1M2BPS_5MS_FRAME || frameType == L1_NONE_FRAME){ + return INFINITY; // FIXME + } + regValue = PhyRead(instPtr, COASE_FREQEST); + acqFreqIdx = (regValue >> COASE_FREQEST_ACQ_SHIFT) && COASE_FREQEST_ACQ_MASK; + acqFreqIdx = 80 - acqFreqIdx; + syncFreqIdx = (regValue >> COASE_FREQEST_SYNC_SHIFT) && COASE_FREQEST_SYNC_MASK; + syncFreqIdx = 8 - syncFreqIdx; + if(frameType >= L1_200KBPS_5MS_FRAME) { + freqEst = (double)acqFreqIdx*(250e3/4); + freqEst += (double)syncFreqIdx*1.5e6/64/128; + } + else { + freqEst = acqFreqIdx*(250e3/4); + freqEst += (double)syncFreqIdx*12e6/64/128; + } + + return freqEst; +} + +/*****************************************************************************/ +/** + * @brief Get the corresponding frequency hopping pattern length of a + * specified L1 frame type. + * + * @param frameType a L1 frame type enumeration. + * + * @return SUCCESS + * FAILURE frame type cannot be recognized + * + ******************************************************************************/ +uint32_t Phy_GetHopLength(L1_FRAME_TYPE frameType){ + switch (frameType) { + case L1_2KBPS_20MS_FRAME: + return L1_FRAME_2KBPS_20MS_HOPS; + case L1_2KBPS_100MS_FRAME: + return L1_FRAME_2KBPS_100MS_HOPS; + case L1_10KBPS_10MS_FRAME: + return L1_FRAME_10KBPS_10MS_HOPS; + case L1_10KBPS_20MS_FRAME: + return L1_FRAME_10KBPS_20MS_HOPS; + case L1_40KBPS_20MS_FRAME: + return L1_FRAME_40KBPS_20MS_HOPS; + case L1_40KBPS_10MS_FRAME: + return L1_FRAME_40KBPS_10MS_HOPS; + case L1_200KBPS_5MS_FRAME: + return L1_FRAME_200KBPS_5MS_HOPS; + case L1_1M2BPS_5MS_FRAME: + return L1_FRAME_1M2BPS_5MS_HOPS; + default: + return L1_FRAME_NONE_LEN; + } +} + +/*****************************************************************************/ +/** + * @brief Get the corresponding time compensation value (time interval from + * frame start to frame sync) + * + * @param frameType a L1 frame type enumeration. + * + * @return SUCCESS + * FAILURE frame type cannot be recognized + * + ******************************************************************************/ +uint32_t Phy_GetTimeComp(L1_FRAME_TYPE frameType){ + switch (frameType) { + case L1_2KBPS_20MS_FRAME: + return L1_FRAME_2KBPS_20MS_COMP; + case L1_2KBPS_100MS_FRAME: + return L1_FRAME_2KBPS_100MS_COMP; + case L1_10KBPS_10MS_FRAME: + return L1_FRAME_10KBPS_10MS_COMP; + case L1_10KBPS_20MS_FRAME: + return L1_FRAME_10KBPS_20MS_COMP; + case L1_40KBPS_20MS_FRAME: + return L1_FRAME_40KBPS_20MS_COMP; + case L1_40KBPS_10MS_FRAME: + return L1_FRAME_40KBPS_10MS_COMP; + case L1_200KBPS_5MS_FRAME: + return L1_FRAME_200KBPS_5MS_COMP; + case L1_1M2BPS_5MS_FRAME: + return L1_FRAME_1M2BPS_5MS_COMP; + default: + return L1_FRAME_NONE_LEN; + } +} + +/*****************************************************************************/ +/** + * @brief Setup a frequency hopping pattern. + * + * @param patternBuff a pointer to hopping pattern buffer + * @param patternLen a integer indicate the length of hopping pattern. + * + * @return SUCCESS + * FAILURE pattern length exceeds maximum length. + * + ******************************************************************************/ +int32_t Phy_SetHopPattern(void* patternBuff, uint32_t patternLen){ + ASSERT(patternBuff != NULL); + if(patternLen > L1_FRAME_MAX_HOPS){ + return FAILURE; + } + memcpy(hopPattern_Config, patternBuff, patternLen*sizeof(uint16_t)); + return SUCCESS; +} + +/*****************************************************************************/ +/** + * @brief Setup a specific timer word register in physical controller. + * + * @param patternBuff a pointer to hopping pattern buffer + * @param patternLen a integer indicate the length of hopping pattern. + * + * @return SUCCESS + * FAILURE pattern length exceeds maximum length. + * + ******************************************************************************/ +int32_t Phy_SetTimeWord(PHY_INST* instPtr, const TIME_WORD* tmWord, PHY_TIME_WORD_TYPE tmType){ + ASSERT(instPtr != NULL); + if(tmWord->frac_part>=PHY_TIME_WORD_L_MAX){ + return EPARAM; + } + switch(tmType){ + case TIME_WORD_POLL: + PhyWrite(instPtr, POLLTIME_L, tmWord->frac_part); + PhyWrite(instPtr, POLLTIME_H, tmWord->int_part); + break; + case TIME_WORD_LISTEN_TIMEOUT: + PhyWrite(instPtr, LISTENTIMEOUT_L, tmWord->frac_part); + PhyWrite(instPtr, LISTENTIMEOUT_H, tmWord->int_part); + break; + default: + return EPARAM; + } + return SUCCESS; +} + + +/*****************************************************************************/ +/** + * @brief Get the frame sync time of last received frame. + * + * @param instPtr a pointer to physical instance + * @param frameSycT a pointer to the frame sync time data buffer. + * + * @return NONE + * + ******************************************************************************/ +void Phy_GetFrameSyncTimeStamp(PHY_INST* instPtr, TIME_WORD* frameSyncT) { + ASSERT(instPtr != NULL); + ASSERT(frameSyncT != NULL); + frameSyncT->int_part = PhyRead(instPtr, TM_TARGET_H); + frameSyncT->frac_part = PhyRead(instPtr, TM_TARGET_L); +} + +/*****************************************************************************/ +/** + * @brief Get the frame sync time of last received frame. + * + * @param instPtr a pointer to physical instance + * @param slotStart a pointer to the time data buffer. + * + * @return NONE + * + ******************************************************************************/ +void Phy_GetLastSlotStartTimeStamp(PHY_INST* instPtr, TIME_WORD* slotStart) { + ASSERT(instPtr != NULL); + ASSERT(slotStart != NULL); + slotStart->int_part = PhyRead(instPtr, FSTIME_H); + slotStart->frac_part = PhyRead(instPtr, FSTIME_L); +} + +/*****************************************************************************/ +/** + * @brief Get received data (base on PL Record), store it to data buffer. + * + * @param instPtr a pointer to physical layer control instance. + * + * @return SUCCESS + * FAILURE last frame type cannot be recognized. + * + ******************************************************************************/ +void Phy_RetrieveRecvData(PHY_INST* instPtr, uint8_t* dataBuff) { + ASSERT(instPtr != NULL); + ASSERT(dataBuff != NULL); + uint32_t frameLen, offset; + + frameLen = (PhyRead(instPtr, RECVDATA_STATE) & RECVDATA_STATE_LEN_MASK) >> RECVDATA_STATE_LEN_SHIFT; + offset = (PhyRead(instPtr, RECVDATA_STATE) & RECVDATA_STATE_OFFSET_MASK) >> RECVDATA_STATE_OFFSET_SHIFT; + + memcpy(dataBuff, (uint8_t*)(instPtr->recvDataAddr + offset), frameLen); +} diff --git a/datalink814_ge/src/phy_ctrl/phy_ctrl.h b/datalink814_ge/src/phy_ctrl/phy_ctrl.h new file mode 100644 index 0000000..74d9d3c --- /dev/null +++ b/datalink814_ge/src/phy_ctrl/phy_ctrl.h @@ -0,0 +1,268 @@ +/*****************************************************************************/ +/** + * Description: Physical layer control definitions and function prototypes. + * + * Date: 2021-12-04 16:32 + * LastEditTime: 2023-04-24 17:41 + * Revisions: Rev 0.1 + * History: + * [2021-12-08]: Initial version. + * [2022-06-18]: New branch for glink control purpose: + * -Add poll mode, physical layer will start Tx/Rx procedure + * at specific time stamp. + * -Add 61/37 beam switch + * -Code simplification. + * [2023-04-24]: Feature add: + * - Read frame type from PL status register. + * Copyright(c) 2021 Beijing Institute of Technology. + * Lab of Communication and Networking + * + ******************************************************************************/ + +#ifndef PHY_CTRL_H_ +#define PHY_CTRL_H_ + +/***************************** Include Files *********************************/ +#include +#include "phy_ctrlreg.h" +#include "../common.h" +#include "../time_ctrl/time_ctrl.h" +/************************** Constant Definitions *****************************/ +#define TMWORD_FRAC_MAX 500000 +#define ANTCONFIG_MAX_LEN 8192 +#define TXRXDATA_MAX_LEN 2048 +#define NUM_ANT_SUBNRRW_PATTERN 37 +#define NUM_ANT_NRRW_PATTERN 61 +#define INIT_BEAM_NO 0 +#define INIT_ANT_WD ANT_BEAM_120 +#define INIT_ANT_NO 0 + +#define L1_FRAME_NONE_HOPS UINT32_MAX +#define L1_FRAME_MAX_HOPS 81 +#define L1_FRAME_2KBPS_20MS_HOPS 1 +#define L1_FRAME_2KBPS_100MS_HOPS 81 +#define L1_FRAME_10KBPS_10MS_HOPS 1 +#define L1_FRAME_10KBPS_20MS_HOPS 11 +#define L1_FRAME_40KBPS_20MS_HOPS 19 +#define L1_FRAME_40KBPS_10MS_HOPS 9 +#define L1_FRAME_200KBPS_5MS_HOPS 20 +#define L1_FRAME_1M2BPS_5MS_HOPS 20 + +#define L1_FRAME_NONE_LEN UINT32_MAX// byte +#define L1_FRAME_LEN_MAX (8192/8) // byte +#define L1_FRAME_2KBPS_20MS_LEN 1 // byte +#define L1_FRAME_2KBPS_100MS_LEN 312/8 // byte +#define L1_FRAME_10KBPS_10MS_LEN 1 // byte +#define L1_FRAME_10KBPS_20MS_LEN (232/8) // byte +#define L1_FRAME_40KBPS_20MS_LEN (2152/8) // byte +#define L1_FRAME_40KBPS_10MS_LEN (712/8) // byte +#define L1_FRAME_200KBPS_5MS_LEN (2040/8) // byte +#define L1_FRAME_1M2BPS_5MS_LEN (8176/8) // byte + +#define L1_FRAME_NONE_COMP UINT32_MAX // *10ns(Timer_L) +#define L1_FRAME_2KBPS_20MS_COMP 1841158 // *10ns(Timer_L) +#define L1_FRAME_2KBPS_100MS_COMP 1841158 // *10ns(Timer_L) +#define L1_FRAME_10KBPS_10MS_COMP 847733 // *10ns(Timer_L) +#define L1_FRAME_10KBPS_20MS_COMP 847733 // *10ns(Timer_L) +#define L1_FRAME_40KBPS_20MS_COMP 110667 // *10ns(Timer_L) +#define L1_FRAME_40KBPS_10MS_COMP 110667 // *10ns(Timer_L) +#define L1_FRAME_200KBPS_5MS_COMP 19725 // *10ns(Timer_L) +#define L1_FRAME_1M2BPS_5MS_COMP 19725 // *10ns(Timer_L) + + +#define PHY_TIME_WORD_H_MAX UINT32_MAX +#define PHY_TIME_WORD_L_MAX 0x0007A120 // 5ms/10ns + +/***************** Macros (Inline Functions) Definitions *********************/ + +/**************************** Type Definitions *******************************/ +typedef enum { + L1_NONE_FRAME = 0, + L1_2KBPS_20MS_FRAME = 1, + L1_2KBPS_100MS_FRAME = 2, + L1_10KBPS_10MS_FRAME = 3, + L1_10KBPS_20MS_FRAME = 4, + L1_40KBPS_20MS_FRAME = 5, + L1_40KBPS_10MS_FRAME = 6, + L1_200KBPS_5MS_FRAME = 7, + L1_1M2BPS_5MS_FRAME = 8 +} L1_FRAME_TYPE; + +typedef struct { + /* Antenna control frame head 0xAA */ + uint8_t head; + /* default 0, reserved for further use */ + uint8_t ctrlWord; + /* high 4 bits specified beam mode. + * low 4 bits specified power control */ + uint8_t antMode; + /* off-axis angle range is 0~60, + * 0.1 degree each LSB */ + uint8_t oaxis[2]; + /* round-axis angle range is 0~360, + * 0.1 degree each LSB */ + uint8_t raxis[2]; + /* 0~3500Mhz, step 1MHz */ + uint8_t antFreq[2]; + /* in single tr mode, 0~63 specified tr channel + * in single subarray mode, 0~3 specified the subarray + * Only in debug mode*/ + uint8_t trSlect; + /* Antenna attenuation 0~31, 0.5dB each LSB, Only in debug mode */ + uint8_t antAtt; + /* 0~63, 5.625 degree each LSB, Only in debug mode*/ + uint8_t phase; + /* 0x00 Nromal RX, 0x01 Normal TX + * 0x11~0xA1 beam debug mode (TR duty 1%~10%)*/ + uint8_t rxtxMode; + /* 0x00 Normal, 0x01 single tr calibration */ + uint8_t calibrMode; + /* reserved for further use */ + uint8_t reserved; + /* DD enable */ + uint8_t ddEn; + /* DD mgc */ + uint8_t ddMgc; + /* [7:4]RF enable: 0-On, 1-Off(Default); [3:0]Work mode: 0(default) */ + uint8_t rfCtrl; + /* RF MGC control: 0~31, 1dB each LSB*/ + uint8_t rfMgc; + /* RF channel 1&2 calibration mgc: [7:4] Channle1 - max 15db, 1dB each LSB + * [3:0] Channle2 - max 15db, 1dB each LSB*/ + uint8_t rf12CalMgc; + /* RF channel 3&4 calibration mgc: [7:4] Channle3 - max 15db, 1dB each LSB + * [3:0] Channle4 - max 15db, 1dB each LSB*/ + uint8_t rf34CalMgc; + /* Receive channel 1 MGC: 0~31, 1dB each LSB */ + uint8_t rcv1Mgc; + /* Receive channel 2 MGC: 0~31, 1dB each LSB */ + uint8_t rcv2Mgc; + /* Receive channel 3 MGC: 0~31, 1dB each LSB */ + uint8_t rcv3Mgc; + /* Receive channel 4 MGC: 0~31, 1dB each LSB */ + uint8_t rcv4Mgc; + /* Antenna control frame tail 0xCC */ + uint8_t tail; + uint8_t dummy[6]; +} PHY_ANT_CONFIG; + +typedef struct { + /* off-axis angle range is 0~60, + * 0.1 degree each LSB */ + uint16_t oaxis; + /* round-axis angle range is 0~360, + * 0.1 degree each LSB */ + uint16_t raxis; +} PHY_ANT_ANGLE; + +typedef enum { + TIME_WORD_NONE = 0, + TIME_WORD_POLL = 1, + TIME_WORD_LISTEN_TIMEOUT = 2 +} PHY_TIME_WORD_TYPE; + +typedef enum { + ANT_BEAM_NONE = 0, + ANT_BEAM_120 = 1, + ANT_BEAM_60 = 2, + ANT_BEAM_25 = 3, + ANT_BEAM_8 = 4 +} PHY_ANT_BEAM_WIDTH; + +typedef enum { + PHY_TOR_SUSPEND = 0, + PHY_TOR_TX = 1, + PHY_TOR_RX = 2 +} PHY_TOR_TYPE; + +typedef enum { + PHY_MODE_NONE = 0, + PHY_MODE_LISTEN = 1, + PHY_MODE_SCHEDULE = 2, + PHY_MODE_PULL = 3 +} PHY_MODE; + +typedef struct { + uint32_t devId; + uint32_t txBramId; + uint32_t rxBramId; + uint32_t antBramId; + uintptr_t baseAddr; +} PHY_CONFIG; + +typedef struct { + int32_t last; + int32_t curr; + int32_t next; +} PHY_RCD; + +typedef struct { + PHY_CONFIG phyCofig; // Device address configs + uintptr_t recvDataAddr; + uintptr_t sendDataAddr; + uintptr_t antConfigAddr; + bool isPhyEn; // is physical layer running + bool isAcq; // is last reception acquisition success + bool isFrameSync; // is last reception frame sync success + bool isDecode; // is last reception decode success + bool isValid; // is last reception frame data valid (crc check pass) + bool isPresetHop; // is using preset frequency hop + PHY_RCD antNo; // antenna number record + PHY_RCD beamNo; // beam number record + PHY_RCD beamWd; // beam width record + PHY_RCD TOR; // tx rx state record + PHY_RCD frameType; // frame type record + uint32_t sendDataOffset; // antenna configuration bram offset (to implement ping-pong data flow) + uint32_t antConfigOffset; // antenna configuration bram offset (to implement ping-pong data flow) + PHY_ANT_CONFIG antCoinfoPtr;// antenna configuration pointer +} PHY_INST; + +/************************** Variable Definitions *****************************/ +extern uint16_t hopPattern_Config[L1_FRAME_MAX_HOPS]; +extern uint16_t hopPattern_2KBPS_20MS[L1_FRAME_2KBPS_20MS_HOPS]; +extern uint16_t hopPattern_2KBPS_100MS[L1_FRAME_2KBPS_100MS_HOPS]; +extern uint16_t hopPattern_10KBPS_10MS[L1_FRAME_10KBPS_10MS_HOPS]; +extern uint16_t hopPattern_10KBPS_20MS[L1_FRAME_10KBPS_20MS_HOPS]; +extern uint16_t hopPattern_40KBPS_10MS[L1_FRAME_40KBPS_10MS_HOPS]; +extern uint16_t hopPattern_40KBPS_20MS[L1_FRAME_40KBPS_20MS_HOPS]; +extern uint16_t hopPattern_200KBPS_5MS[L1_FRAME_200KBPS_5MS_HOPS]; +extern uint16_t hopPattern_1M2BPS_5MS[L1_FRAME_1M2BPS_5MS_HOPS]; + +extern PHY_ANT_ANGLE antSubnrrwPattern[NUM_ANT_SUBNRRW_PATTERN]; +extern PHY_ANT_ANGLE antNrrwPattern[NUM_ANT_NRRW_PATTERN]; + +/************************** Function Prototypes ******************************/ +int32_t Phy_InstInit(PHY_INST** instPtr, PHY_CONFIG *phyConfig); +void Phy_Destroy(PHY_INST* instPtr); + +void Phy_UpdateState(PHY_INST* instPtr); + +void Phy_Start(PHY_INST* instPtr); +void Phy_Halt(PHY_INST* instPtr); +int32_t Phy_SetMode(PHY_INST* instPtr, PHY_MODE modeCod); + +int32_t Phy_SetupNextSlot(PHY_INST* instPtr, PHY_TOR_TYPE txrxMode, L1_FRAME_TYPE frameType, uint8_t* dataBuff); +void Phy_RetrieveRecvData(PHY_INST* instPtr, uint8_t* dataBuff); + +bool Phy_IsFrameDetected(PHY_INST* instPtr); +bool Phy_IsFrameReceived(PHY_INST* instPtr); +bool Phy_IsFrameValid(PHY_INST* instPtr); +uint32_t Phy_GetFrameLen(L1_FRAME_TYPE frameType); + +L1_FRAME_TYPE Phy_GetLastRecvFrameType(PHY_INST* instPtr); +L1_FRAME_TYPE Phy_GetLastSendFrameType(PHY_INST* instPtr); + +int32_t Phy_SetHopPattern(void* patternBuff, uint32_t patternLen); +uint32_t Phy_GetHopLength(L1_FRAME_TYPE frameType); +uint32_t Phy_GetTimeComp(L1_FRAME_TYPE frameType); + +int32_t Phy_AntCoinfoInit(PHY_ANT_CONFIG* antCoinfoPtr); +int32_t Phy_SetBeamWidth(PHY_INST* instPtr, PHY_ANT_BEAM_WIDTH beamWidth); +int32_t Phy_SetBeamNo(PHY_INST* instPtr, int32_t beamNo); +int32_t Phy_SetBeamAngle(PHY_INST* phyInstPtr, double offAx, double rndAx); +int32_t Phy_SetTimeWord(PHY_INST* instPtr, const TIME_WORD* tmWord, PHY_TIME_WORD_TYPE tmType); + +double Phy_GetCoarseFreqEst(PHY_INST* instPtr); +void Phy_GetFrameSyncTimeStamp(PHY_INST* instPtr, TIME_WORD* frameSyncT); +void Phy_GetLastSlotStartTimeStamp(PHY_INST* instPtr, TIME_WORD* slotStart); +#endif /* PHY_CTRL_H_ */ diff --git a/datalink814_ge/src/phy_ctrl/phy_ctrlreg.h b/datalink814_ge/src/phy_ctrl/phy_ctrlreg.h new file mode 100644 index 0000000..784f41d --- /dev/null +++ b/datalink814_ge/src/phy_ctrl/phy_ctrlreg.h @@ -0,0 +1,262 @@ +/*****************************************************************************/ +/** + * Description: Physical layer register definitions + * + * Author: Fan Hao + * Date: 2021-11-16 00:08 + * LastEditors: Fan Hao + * LastEditTime: 2022-06-18 17:32 + * Revisions: Rev 0.0 + * History: + * [2021-11-16]: Initial version. + * [2022-06-18]: New branch for glink control purpose: + * -Add poll modephysical layer will start Tx/Rx procedure + * at specific time stamp. + * + * Copyright(c) 2021 Beijing Institute of Technology. + * Lab of Communication and Networking + * + ******************************************************************************/ + +#ifndef PHY_CTRLREG_H_ +#define PHY_CTRLREG_H_ + +/***************************** Include Files *********************************/ +#include "../util/util.h" + +/***************** Macros (Inline Functions) Definitions *********************/ +#define PhyRead(instPtr, addr) IO_In32(instPtr->phyCofig.baseAddr + addr) +#define PhyWrite(instPtr, addr, value) IO_Out32(instPtr->phyCofig.baseAddr + addr, value) + +/************************** Constant Definitions *****************************/ +/** + * Register: PHY_MAIN_CTRL + */ +#define PHY_MAIN_CTRL 0X00000000U +#define PHY_MAIN_CTRL_EN_SHIFT 0 +#define PHY_MAIN_CTRL_EN_WIDTH 1 +#define PHY_MAIN_CTRL_EN_MASK 0x00000001U +#define PHY_MAIN_CTRL_MODE_SHIFT 8 +#define PHY_MAIN_CTRL_MODE_WIDTH 8 +#define PHY_MAIN_CTRL_MODE_MASK 0x0000FF00U + +#define PHY_MAIN_CTRL_EN_EN 0x00000001U +#define PHY_MAIN_CTRL_EN_DSBL 0x00000000U +#define PHY_MAIN_CTRL_MODE_NONE 0x00000000U +#define PHY_MAIN_CTRL_MODE_LISTEN 0x00000100U +#define PHY_MAIN_CTRL_MODE_SCHEDULE 0x00000200U +#define PHY_MAIN_CTRL_MODE_PULL 0x00000300U + +/** + * Register: TXRX_CTRL + */ +#define PHY_MODE_CTRL 0x00000004U +#define PHY_MODE_CTRL_TOR_SHIFT 0 +#define PHY_MODE_CTRL_TOR_WIDTH 8 +#define PHY_MODE_CTRL_TOR_MASK 0x000000FFU +#define PHY_MODE_CTRL_FRAME_SHIFT 8 +#define PHY_MODE_CTRL_FRAME_WIDTH 8 +#define PHY_MODE_CTRL_FRAME_MASK 0x0000FF00U +#define PHY_MODE_CTRL_CRC_SHIFT 8 +#define PHY_MODE_CTRL_CRC_WIDTH 16 +#define PHY_MODE_CTRL_CRC_MASK 0x00FF0000U + +#define PHY_MODE_CTRL_TOR_SUSPEND 0x00000000U +#define PHY_MODE_CTRL_TOR_TX 0x00000001U +#define PHY_MODE_CTRL_TOR_RX 0x00000002U + +#define PHY_MODE_CTRL_FRAME_NONE 0x00000000U +#define PHY_MODE_CTRL_FRAME_2KBPS_20MS 0x00000100U +#define PHY_MODE_CTRL_FRAME_2KBPS_100MS 0x00000200U +#define PHY_MODE_CTRL_FRAME_10KBPS_10MS 0x00000300U // Initial Scan Frame +#define PHY_MODE_CTRL_FRAME_10KBPS_20MS 0x00000400U // Benchmark Frame +#define PHY_MODE_CTRL_FRAME_40KBPS_20MS 0x00000500U +#define PHY_MODE_CTRL_FRAME_40KBPS_10MS 0x00000600U +#define PHY_MODE_CTRL_FRAME_200KBPS_5MS 0x00000700U // 2-Way ACQ Frame, Management Frame, Service Frame +#define PHY_MODE_CTRL_FRAME_1M2BPS_5MS 0x00000800U // Bistatic Synthetic Aperture Radar Frame + +#define PHY_MODE_CTRL_CRC_EN 0x00010000U +#define PHY_MODE_CTRL_CRC_DSBL 0x00000000U +/** + * Register: POLLTIME_L + */ +#define POLLTIME_L 0x00000008U +#define POLLTIME_L_SHIFT 0 +#define POLLTIME_L_WIDTH 32 +#define POLLTIME_L_MASK 0xFFFFFFFFU + +/** + * Register: POLLTIME_H + */ +#define POLLTIME_H 0x0000000CU +#define POLLTIME_H_SHIFT 0 +#define POLLTIME_H_WIDTH 32 +#define POLLTIME_H_MASK 0xFFFFFFFFU + + +/** + * Register: TIMEOUT_L + */ +#define LISTENTIMEOUT_L 0x00000010U +#define LISTENTIMEOUT_L_SHIFT 0 +#define LISTENTIMEOUT_L_WIDTH 32 +#define LISTENTIMEOUT_L_MASK 0xFFFFFFFFU + +/** + * Register: TIMEOUT_H + */ +#define LISTENTIMEOUT_H 0x00000014U +#define LISTENTIMEOUT_H_SHIFT 0 +#define LISTENTIMEOUT_H_WIDTH 32 +#define LISTENTIMEOUT_H_MASK 0xFFFFFFFFU + +/** + * Register: ANT_CTRL + */ +#define ANT_CONFIG 0x00000018U +#define ANT_CONFIG_OFFSET_SHIFT 0 +#define ANT_CONFIG_OFFSET_WIDTH 16 +#define ANT_CONFIG_OFFSET_MASK 0x0000FFFFU +#define ANT_CONFIG_LEN_SHIFT 16 +#define ANT_CONFIG_LEN_WIDTH 8 +#define ANT_CONFIG_LEN_MASK 0x00FF0000U +#define ANT_CONFIG_NUM_SHIFT 24 +#define ANT_CONFIG_NUM_WIDTH 8 +#define ANT_CONFIG_NUM_MASK 0xFF000000U + +/** + * Register: SEND_DATA_CMD + */ +#define SEND_DATA_CMD 0x0000001CU +#define SEND_DATA_CMD_SHIFT 0 +#define SEND_DATA_CMD_WIDTH 32 +#define SEND_DATA_CMD_MASK 0xFFFFFFFFU + +#define SEND_DATA_CMD_LEN_SHIFT 0 +#define SEND_DATA_CMD_LEN_WIDTH 16 +#define SEND_DATA_CMD_LEN_MASK 0x0000FFFFU +#define SEND_DATA_CMD_OFFSET_SHIFT 16 +#define SEND_DATA_CMD_OFFSET_WIDTH 16 +#define SEND_DATA_CMD_OFFSET_MASK 0xFFFF0000U + +/** + * Register: SEND_CONFIG_CMD + */ +#define SLOT_CMD 0x00000020U +#define SLOT_CMD_SHIFT 0 +#define SLOT_CMD_WIDTH 32 +#define SLOT_CMD_MASK 0xFFFFFFFFU +#define SLOT_CMD_KEY 0x434D442EU + +/** + * Register: TXRX_STATE + */ +#define TXRX_STATE 0x00000024U +#define TXRX_STATE_ACQ_SHIFT 0 +#define TXRX_STATE_ACQ_WIDTH 8 +#define TXRX_STATE_ACQ_MASK 0x000000FFU +#define TXRX_STATE_ACQ_SUCCESS 0x00000001U +#define TXRX_STATE_ACQ_FAIL 0x00000002U + +#define TXRX_STATE_FSYNC_SHIFT 8 +#define TXRX_STATE_FSYNC_WIDTH 8 +#define TXRX_STATE_FSYNC_MASK 0x0000FF00U +#define TXRX_STATE_FSYNC_SUCCESS 0x00000100U +#define TXRX_STATE_FSYNC_FAIL 0x00000200U + +#define TXRX_STATE_DECODE_SHIFT 16 +#define TXRX_STATE_DECODE_WIDTH 8 +#define TXRX_STATE_DECODE_MASK 0x00FF0000U +#define TXRX_STATE_DECODE_SUCCESS 0x00010000U +#define TXRX_STATE_DECODE_FAIL 0x00020000U + +#define TXRX_STATE_CRC_SHIFT 24 +#define TXRX_STATE_CRC_WIDTH 8 +#define TXRX_STATE_CRC_MASK 0xFF000000U +#define TXRX_STATE_CRC_OK 0x01000000U +#define TXRX_STATE_CRC_ERROR 0x02000000U + + +/** + * Register: RECVDATA_STATE + */ +#define RECVDATA_STATE 0x00000028U +#define RECVDATA_STATE_LEN_SHIFT 0 +#define RECVDATA_STATE_LEN_WIDTH 16 +#define RECVDATA_STATE_LEN_MASK 0x0000FFFFU + +#define RECVDATA_STATE_OFFSET_SHIFT 16 +#define RECVDATA_STATE_OFFSET_WIDTH 16 +#define RECVDATA_STATE_OFFSET_MASK 0xFFFF0000U +/** + * Register: FSTIME_L + */ +#define FSTIME_L 0x000002CU +#define FSTIME_L_SHIFT 0 +#define FSTIME_L_WIDTH 32 +#define FSTIME_L_MASK 0xFFFFFFFFU + +/** + * Register: FSTIME_INT1 + */ +#define FSTIME_H 0x0000030U +#define FSTIME_H_SHIFT 0 +#define FSTIME_H_WIDTH 32 +#define FSTIME_H_MASK 0xFFFFFFFFU + +/** + * Register: TM_TARGET_L + */ +#define TM_TARGET_L 0x0000064U +#define TM_TARGET_L_SHIFT 0 +#define TM_TARGET_L_WIDTH 32 +#define TM_TARGET_L_MASK 0xFFFFFFFFU + +/** + * Register: TM_TARGET_H + */ +#define TM_TARGET_H 0x0000038U +#define TM_TARGET_H_SHIFT 0 +#define TM_TARGET_H_WIDTH 32 +#define TM_TARGET_H_MASK 0xFFFFFFFFU + +/** + * Register: COASEFREQEST + */ +#define COASE_FREQEST 0x0000003CU +#define COASE_FREQEST_ACQ_SHIFT 0 +#define COASE_FREQEST_ACQ_WIDTH 8 +#define COASE_FREQEST_ACQ_MASK 0x000000FFU +#define COASE_FREQEST_SYNC_SHIFT 0 +#define COASE_FREQEST_SYNC_WIDTH 16 +#define COASE_FREQEST_SYNC_MASK 0x000FF00U + +/** + * Register: FINE_FREQEST + */ +#define FINE_FREQEST 0x00000040U +#define FINE_FREQEST_SHIFT 0 +#define FINE_FREQEST_WIDTH 32 +#define FINE_FREQEST_MASK 0xFFFFFFFFU + +/** + * Register: BEAM_SELECT + */ +#define BEAM_SELECT_INDEX 0x00000044U +#define BEAM_SELECT_INDEX_SHIFT 0 +#define BEAM_SELECT_INDEX_WIDTH 32 +#define BEAM_SELECT_INDEX_MASK 0xFFFFFFFFU + +/** + * Register: BEAM_SELECT + */ +#define BEAM_AXIS 0x00000044U +#define BEAM_AXIS_EL_SHIFT 0 +#define BEAM_AXIS_EL_WIDTH 16 +#define BEAM_AXIS_EL_MASK 0x0000FFFFU +#define BEAM_AXIS_AZ_SHIFT 16 +#define BEAM_AXIS_AZ_WIDTH 16 +#define BEAM_AXIS_AZ_MASK 0xFFFF0000U + +// Reserved. +#endif /* PHY_CTRLREG_H_ */ diff --git a/datalink814_ge/src/time_ctrl/time_ctrl.c b/datalink814_ge/src/time_ctrl/time_ctrl.c new file mode 100644 index 0000000..e437fce --- /dev/null +++ b/datalink814_ge/src/time_ctrl/time_ctrl.c @@ -0,0 +1,221 @@ +/*****************************************************************************/ +/** + * Description: Time sync implementation file. + * + * Author: Author's name + * Date: 2021-12-04 16:32 + * LastEditors: FanHao + * LastEditTime: 2022-07-10 20:43 + * Revisions: Rev 0.0 + * History: + * [2022-07-10]: New branch for Dijian. + * [2021-12-04]: Initial version. + * + * Copyright(c) 2021 Beijing Institute of Technology. + * Lab of Communication and Networking + * + ******************************************************************************/ + +/***************************** Include Files *********************************/ +#include +#include "time_ctrl.h" +#include "../error.h" +#include "../common.h" +#include "../util/util.h" + +/************************** Constant Definitions *****************************/ +#define VERSION_REG 0x00000004 +#define TIME_INT_REG 0x00000008 +#define TIME_FRAC_REG 0x0000000C +#define TIME_RESET 0x00000010 +#define PRESET_HIGH 0x00000014 +#define PRESET_LOW 0x00000018 +#define TIME_ADJ_INT 0x0000001C +#define TIME_ADJ_FRAC 0x00000020 +#define TIME_ADJ_TRIG 0x00000024 +#define CNTSTEP_OPT 0x00000028 + +#define TM_RESET_CODE 0x5253542E +/***************** Macros (Inline Functions) Definitions *********************/ +#define TMC_Read(instPtr, addr) IO_In32(instPtr->config.baseAddr + addr) +#define TMC_Write(instPtr, addr, value) IO_Out32(instPtr->config.baseAddr + addr, value) + + +/*****************************************************************************/ +/** + * @brief Initialize Time-Controller Process + * + * @param instPtr a second rank pointer to time controller instance + * @param config time controller configurations + * + * @return SUCCESS Initialize successfully. + * FAILURE Initialization failed + * + ******************************************************************************/ +int32_t TimeCtrl_Init(TIMECTRL_INST **instPtr, TIMECTRL_CONFIG *config){ + ASSERT(config != NULL); + ASSERT(instPtr != NULL); + (*instPtr) = malloc(sizeof(TIMECTRL_INST)); + memcpy(&((*instPtr)->config), config, sizeof(TIMECTRL_CONFIG)); + (*instPtr)->modelVer = TMC_Read((*instPtr), VERSION_REG); + return SUCCESS; +} + +void TimeCtrl_Destroy(TIMECTRL_INST *instPtr) { + free(instPtr); +} + +uint32_t TimeCtrl_GetVersion(TIMECTRL_INST *instPtr){ + return TMC_Read(instPtr, VERSION_REG); +} +/*****************************************************************************/ +/** + * @brief Apply a reset process to time controller + * + * @param instPtr a pointer to time controller instance + * + * @return SUCCESS Initialize successfully. + * FAILURE Initialization failed + * + ******************************************************************************/ +void TimeCtrl_Reset(TIMECTRL_INST *instPtr){ + ASSERT(instPtr != NULL); + TMC_Write(instPtr, CNTSTEP_OPT, TM_RESET_CODE); +} + + +/*****************************************************************************/ +/** + * @brief Assert time controller reset high + * + * @param instPtr a pointer to time controller instance + * + * @return NONE + * + ******************************************************************************/ +void TimeCtrl_ResetHigh(TIMECTRL_INST *instPtr){ + ASSERT(instPtr != NULL); + // TODO: +} + + +/*****************************************************************************/ +/** + * @brief Assert time controller reset low + * + * @param instPtr a pointer to time controller instance + * + * @return NONE + * + ******************************************************************************/ +void TimeCtrl_ResetLow(TIMECTRL_INST *instPtr){ + ASSERT(instPtr != NULL); + // TODO: +} + + +/*****************************************************************************/ +/** + * @brief Get current time integer value. + * + * @param instPtr a pointer to time controller instance + * + * @return integer value + * + ******************************************************************************/ +inline TIME_INT TimeCtrl_GetIntCnt(TIMECTRL_INST *instPtr){ + ASSERT(instPtr != NULL); + return TMC_Read(instPtr, TIME_INT_REG); +} + +/*****************************************************************************/ +/** + * @brief Get current time fractional value. + * + * @param instPtr a pointer to time controller instance + * + * @return fractional value + * + ******************************************************************************/ +inline TIME_FRAC TimeCtrl_GetFracCnt(TIMECTRL_INST *instPtr){ + ASSERT(instPtr != NULL); + return TMC_Read(instPtr, TIME_FRAC_REG); +} + +/*****************************************************************************/ +/** + * @brief Get current time value. + * + * @param instPtr a pointer to time controller instance + * @param tmWord a pointer to time data buffer + * + * @return NONE + * + ******************************************************************************/ +void TimeCtrl_GetCurrentTime(TIMECTRL_INST *instPtr, TIME_WORD* tmWord){ + ASSERT(instPtr != NULL); + ASSERT(tmWord != NULL); + tmWord->frac_part = TMC_Read(instPtr, TIME_FRAC_REG); + tmWord->int_part = TMC_Read(instPtr, TIME_INT_REG); +} + +/*****************************************************************************/ +/** + * @brief Get current optimal counter step adjustment value. + * + * @param instPtr a pointer to time controller instance + * @param config a pointer to time data buffer + * + * @return NONE. + * + ******************************************************************************/ +void TimeCtrl_GetCurrentStep(TIMECTRL_INST *instPtr, TIME_FRAC* tmFrac) { + ASSERT(instPtr != NULL); + ASSERT(tmFrac != NULL); + *tmFrac = TMC_Read(instPtr, CNTSTEP_OPT); +} + + +/*****************************************************************************/ +/** + * @brief Set a new optimal adjustment value to the counter step. + * + * @param instPtr a pointer to time controller instance + * @param tmWord a pointer to the time data + * @param type adjustment type + * + * @return NONE. + * + ******************************************************************************/ +void TimeCtrl_TimeAdjust(TIMECTRL_INST *instPtr, const TIME_WORD* tmWord, TIMECTRL_ADJ_TYPE type){ + ASSERT(instPtr != NULL); + ASSERT(tmWord != NULL); + if(type < TM_ADJ_ADD || TM_ADJ_ADD > TM_ADJ_SET){ + DBG_ERROR("Unsupported adjustment type: %d", type); + return; + } + if(((int32_t)tmWord->frac_part) > COUNTE_FRAC_MAX ) { + DBG_ERROR("Invalid fractional value 0x%08X (should <= 0x%08X).\n", + tmWord->frac_part, COUNTE_FRAC_MAX); + return; + } + TMC_Write(instPtr, TIME_ADJ_FRAC, tmWord->frac_part); + TMC_Write(instPtr, TIME_ADJ_INT, tmWord->int_part); + TMC_Write(instPtr, TIME_ADJ_TRIG, type); +} + +/*****************************************************************************/ +/** + * @brief Set a new optimal adjustment value to the counter step. + * + * @param instPtr a pointer to time controller instance + * @param tmFrac a pointer to the time data + * + * @return NONE. + * + ******************************************************************************/ +void TimeCtrl_SetOptimizeStep(TIMECTRL_INST* instPtr, TIME_FRAC* tmFrac) { + ASSERT(instPtr != NULL); + ASSERT(tmFrac != NULL); + TMC_Write(instPtr, CNTSTEP_OPT, *tmFrac); +} diff --git a/datalink814_ge/src/time_ctrl/time_ctrl.h b/datalink814_ge/src/time_ctrl/time_ctrl.h new file mode 100644 index 0000000..7f35e06 --- /dev/null +++ b/datalink814_ge/src/time_ctrl/time_ctrl.h @@ -0,0 +1,71 @@ +/*****************************************************************************/ +/** + * Description: A simplified version of timesync for datalink 814 (Dijian) + * + * Date: 2021-12-04 16:32 + * LastEditors: Fan Hao + * LastEditTime: 2022-07-06 16:32 + * Revisions: Rev 0.0 + * History: + * [2022-07-06]: Initial version. + * [2021-12-04]: Initial version. + * + * Copyright(c) 2021 Beijing Institute of Technology. + * Lab of Communication and Networking + * + ******************************************************************************/ + +#ifndef TIME_CTRL_H_ +#define TIME_CTRL_H_ + +/***************************** Include Files *********************************/ +#include +/************************** Constant Definitions *****************************/ +#define COUNTE_FRAC_MAX 500000 // how many 10ns in a 5ms +/***************** Macros (Inline Functions) Definitions *********************/ +/**************************** Type Definitions *******************************/ +typedef enum { + TM_ADJ_NONE = 0, + TM_ADJ_ADD = 1, + TM_ADJ_SET = 2 +} TIMECTRL_ADJ_TYPE; + +typedef uint32_t TIME_FRAC; +typedef uint32_t TIME_INT; + +typedef struct { + /* 5ms each LSB */ + TIME_INT int_part; + /* 10ns each LSB */ + TIME_FRAC frac_part; +} TIME_WORD; + +typedef struct { + uintptr_t baseAddr; + uint32_t reset; //time for reset (unit: us) +} TIMECTRL_CONFIG; + +typedef struct { + TIMECTRL_CONFIG config; + uint32_t modelVer; +} TIMECTRL_INST; + +/************************** Function Prototypes ******************************/ +int32_t TimeCtrl_Init(TIMECTRL_INST **instPtr, TIMECTRL_CONFIG *config); +uint32_t TimeCtrl_GetVersion(TIMECTRL_INST *instPtr); +void TimeCtrl_Destroy(TIMECTRL_INST *instPtr); +void TimeCtrl_Reset(TIMECTRL_INST *instPtr); +void TimeCtrl_ResetLow(TIMECTRL_INST *instPtr); +void TimeCtrl_ResetHigh(TIMECTRL_INST *instPtr); + +TIME_INT TimeCtrl_GetIntCnt(TIMECTRL_INST *instPtr); +TIME_FRAC TimeCtrl_GetFracCnt(TIMECTRL_INST *instPtr); + +void TimeCtrl_GetCurrentTime(TIMECTRL_INST *instPtr, TIME_WORD* tmWord); +void TimeCtrl_GetCurrentStep(TIMECTRL_INST *instPtr, TIME_FRAC* tmFrac); + +void TimeCtrl_SetOptimizeStep(TIMECTRL_INST *instPtr, TIME_FRAC* tmFrac); +void TimeCtrl_TimeAdjust(TIMECTRL_INST *instPtr, const TIME_WORD* tmWord, TIMECTRL_ADJ_TYPE type); + + +#endif /* TIME_SYNC_H_ */ diff --git a/datalink814_ge/src/util/crc.c b/datalink814_ge/src/util/crc.c new file mode 100644 index 0000000..0fb8efe --- /dev/null +++ b/datalink814_ge/src/util/crc.c @@ -0,0 +1,417 @@ +/*****************************************************************************/ +/** + * Description: CRC implementation file + * + * Author: Hao Fan + * Date: 2021-11-16 00:50 + * LastEditors: Hao Fan + * LastEditTime: 2022-07-17 20:53 + * Revisions: Rev 0.0 + * History: + * [2022-07-17]: Add CRC16_0x8005 CRC8_0x31. + * [2022-01-06]: Initial verion (Basic CRC-16). + * + * Copyright(c) 2021 Beijing Institute of Technology. + * Lab of Communication and Networking + * + ******************************************************************************/ + +#include "util.h" +#include "../error.h" + +#ifdef __CRC_LSB +// CRC-16-CCITT G(X)=X16+X12+X5+1 +// Reversed +static const uint16_t crc16_1021_lsb_lut[256] = { + 0x0000, 0x1189, 0x2312, 0x329B, 0x4624, 0x57AD, 0x6536, 0x74BF, + 0x8C48, 0x9DC1, 0xAF5A, 0xBED3, 0xCA6C, 0xDBE5, 0xE97E, 0xF8F7, + 0x1081, 0x0108, 0x3393, 0x221A, 0x56A5, 0x472C, 0x75B7, 0x643E, + 0x9CC9, 0x8D40, 0xBFDB, 0xAE52, 0xDAED, 0xCB64, 0xF9FF, 0xE876, + 0x2102, 0x308B, 0x0210, 0x1399, 0x6726, 0x76AF, 0x4434, 0x55BD, + 0xAD4A, 0xBCC3, 0x8E58, 0x9FD1, 0xEB6E, 0xFAE7, 0xC87C, 0xD9F5, + 0x3183, 0x200A, 0x1291, 0x0318, 0x77A7, 0x662E, 0x54B5, 0x453C, + 0xBDCB, 0xAC42, 0x9ED9, 0x8F50, 0xFBEF, 0xEA66, 0xD8FD, 0xC974, + 0x4204, 0x538D, 0x6116, 0x709F, 0x0420, 0x15A9, 0x2732, 0x36BB, + 0xCE4C, 0xDFC5, 0xED5E, 0xFCD7, 0x8868, 0x99E1, 0xAB7A, 0xBAF3, + 0x5285, 0x430C, 0x7197, 0x601E, 0x14A1, 0x0528, 0x37B3, 0x263A, + 0xDECD, 0xCF44, 0xFDDF, 0xEC56, 0x98E9, 0x8960, 0xBBFB, 0xAA72, + 0x6306, 0x728F, 0x4014, 0x519D, 0x2522, 0x34AB, 0x0630, 0x17B9, + 0xEF4E, 0xFEC7, 0xCC5C, 0xDDD5, 0xA96A, 0xB8E3, 0x8A78, 0x9BF1, + 0x7387, 0x620E, 0x5095, 0x411C, 0x35A3, 0x242A, 0x16B1, 0x0738, + 0xFFCF, 0xEE46, 0xDCDD, 0xCD54, 0xB9EB, 0xA862, 0x9AF9, 0x8B70, + 0x8408, 0x9581, 0xA71A, 0xB693, 0xC22C, 0xD3A5, 0xE13E, 0xF0B7, + 0x0840, 0x19C9, 0x2B52, 0x3ADB, 0x4E64, 0x5FED, 0x6D76, 0x7CFF, + 0x9489, 0x8500, 0xB79B, 0xA612, 0xD2AD, 0xC324, 0xF1BF, 0xE036, + 0x18C1, 0x0948, 0x3BD3, 0x2A5A, 0x5EE5, 0x4F6C, 0x7DF7, 0x6C7E, + 0xA50A, 0xB483, 0x8618, 0x9791, 0xE32E, 0xF2A7, 0xC03C, 0xD1B5, + 0x2942, 0x38CB, 0x0A50, 0x1BD9, 0x6F66, 0x7EEF, 0x4C74, 0x5DFD, + 0xB58B, 0xA402, 0x9699, 0x8710, 0xF3AF, 0xE226, 0xD0BD, 0xC134, + 0x39C3, 0x284A, 0x1AD1, 0x0B58, 0x7FE7, 0x6E6E, 0x5CF5, 0x4D7C, + 0xC60C, 0xD785, 0xE51E, 0xF497, 0x8028, 0x91A1, 0xA33A, 0xB2B3, + 0x4A44, 0x5BCD, 0x6956, 0x78DF, 0x0C60, 0x1DE9, 0x2F72, 0x3EFB, + 0xD68D, 0xC704, 0xF59F, 0xE416, 0x90A9, 0x8120, 0xB3BB, 0xA232, + 0x5AC5, 0x4B4C, 0x79D7, 0x685E, 0x1CE1, 0x0D68, 0x3FF3, 0x2E7A, + 0xE70E, 0xF687, 0xC41C, 0xD595, 0xA12A, 0xB0A3, 0x8238, 0x93B1, + 0x6B46, 0x7ACF, 0x4854, 0x59DD, 0x2D62, 0x3CEB, 0x0E70, 0x1FF9, + 0xF78F, 0xE606, 0xD49D, 0xC514, 0xB1AB, 0xA022, 0x92B9, 0x8330, + 0x7BC7, 0x6A4E, 0x58D5, 0x495C, 0x3DE3, 0x2C6A, 0x1EF1, 0x0F78 +}; + +// CRC-16-MAXIM G(X)=X16+X15+X2+1 +const uint16_t crc16_8005_lsb_lut[256] = { + 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, + 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440, + 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40, + 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841, + 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40, + 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41, + 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641, + 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040, + 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240, + 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441, + 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41, + 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840, + 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41, + 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40, + 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640, + 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041, + 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240, + 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441, + 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41, + 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840, + 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41, + 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40, + 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640, + 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041, + 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241, + 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440, + 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40, + 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841, + 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40, + 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41, + 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641, + 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040 +}; + +// CRC-8-MAXIM G(X)=X8+X5+X4+1 +const uint8_t crc8_31_lsb_lut[256] = { + 0x00, 0x5E, 0xBC, 0xE2, 0x61, 0x3F, 0xDD, 0x83, + 0xC2, 0x9C, 0x7E, 0x20, 0xA3, 0xFD, 0x1F, 0x41, + 0x9D, 0xC3, 0x21, 0x7F, 0xFC, 0xA2, 0x40, 0x1E, + 0x5F, 0x01, 0xE3, 0xBD, 0x3E, 0x60, 0x82, 0xDC, + 0x23, 0x7D, 0x9F, 0xC1, 0x42, 0x1C, 0xFE, 0xA0, + 0xE1, 0xBF, 0x5D, 0x03, 0x80, 0xDE, 0x3C, 0x62, + 0xBE, 0xE0, 0x02, 0x5C, 0xDF, 0x81, 0x63, 0x3D, + 0x7C, 0x22, 0xC0, 0x9E, 0x1D, 0x43, 0xA1, 0xFF, + 0x46, 0x18, 0xFA, 0xA4, 0x27, 0x79, 0x9B, 0xC5, + 0x84, 0xDA, 0x38, 0x66, 0xE5, 0xBB, 0x59, 0x07, + 0xDB, 0x85, 0x67, 0x39, 0xBA, 0xE4, 0x06, 0x58, + 0x19, 0x47, 0xA5, 0xFB, 0x78, 0x26, 0xC4, 0x9A, + 0x65, 0x3B, 0xD9, 0x87, 0x04, 0x5A, 0xB8, 0xE6, + 0xA7, 0xF9, 0x1B, 0x45, 0xC6, 0x98, 0x7A, 0x24, + 0xF8, 0xA6, 0x44, 0x1A, 0x99, 0xC7, 0x25, 0x7B, + 0x3A, 0x64, 0x86, 0xD8, 0x5B, 0x05, 0xE7, 0xB9, + 0x8C, 0xD2, 0x30, 0x6E, 0xED, 0xB3, 0x51, 0x0F, + 0x4E, 0x10, 0xF2, 0xAC, 0x2F, 0x71, 0x93, 0xCD, + 0x11, 0x4F, 0xAD, 0xF3, 0x70, 0x2E, 0xCC, 0x92, + 0xD3, 0x8D, 0x6F, 0x31, 0xB2, 0xEC, 0x0E, 0x50, + 0xAF, 0xF1, 0x13, 0x4D, 0xCE, 0x90, 0x72, 0x2C, + 0x6D, 0x33, 0xD1, 0x8F, 0x0C, 0x52, 0xB0, 0xEE, + 0x32, 0x6C, 0x8E, 0xD0, 0x53, 0x0D, 0xEF, 0xB1, + 0xF0, 0xAE, 0x4C, 0x12, 0x91, 0xCF, 0x2D, 0x73, + 0xCA, 0x94, 0x76, 0x28, 0xAB, 0xF5, 0x17, 0x49, + 0x08, 0x56, 0xB4, 0xEA, 0x69, 0x37, 0xD5, 0x8B, + 0x57, 0x09, 0xEB, 0xB5, 0x36, 0x68, 0x8A, 0xD4, + 0x95, 0xCB, 0x29, 0x77, 0xF4, 0xAA, 0x48, 0x16, + 0xE9, 0xB7, 0x55, 0x0B, 0x88, 0xD6, 0x34, 0x6A, + 0x2B, 0x75, 0x97, 0xC9, 0x4A, 0x14, 0xF6, 0xA8, + 0x74, 0x2A, 0xC8, 0x96, 0x15, 0x4B, 0xA9, 0xF7, + 0xB6, 0xE8, 0x0A, 0x54, 0xD7, 0x89, 0x6B, 0x35 +}; +#else +// CRC-16-CCITT G(X)=X16+X12+X5+1 +static const uint16_t crc16_1021_msb_lut[256] = { + 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, + 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, + 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, + 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, + 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485, + 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D, + 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4, + 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC, + 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823, + 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, + 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, + 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, + 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, + 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49, + 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70, + 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78, + 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F, + 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067, + 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, + 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, + 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, + 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, + 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C, + 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634, + 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB, + 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3, + 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, + 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, + 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, + 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, + 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, + 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0 +}; + +// CRC-16-MAXIM G(X)=X16+X15+X2+1 +const uint16_t crc16_8005_msb_lut[256] = { + 0x0000, 0x8005, 0x800F, 0x000A, 0x801B, 0x001E, 0x0014, 0x8011, + 0x8033, 0x0036, 0x003C, 0x8039, 0x0028, 0x802D, 0x8027, 0x0022, + 0x8063, 0x0066, 0x006C, 0x8069, 0x0078, 0x807D, 0x8077, 0x0072, + 0x0050, 0x8055, 0x805F, 0x005A, 0x804B, 0x004E, 0x0044, 0x8041, + 0x80C3, 0x00C6, 0x00CC, 0x80C9, 0x00D8, 0x80DD, 0x80D7, 0x00D2, + 0x00F0, 0x80F5, 0x80FF, 0x00FA, 0x80EB, 0x00EE, 0x00E4, 0x80E1, + 0x00A0, 0x80A5, 0x80AF, 0x00AA, 0x80BB, 0x00BE, 0x00B4, 0x80B1, + 0x8093, 0x0096, 0x009C, 0x8099, 0x0088, 0x808D, 0x8087, 0x0082, + 0x8183, 0x0186, 0x018C, 0x8189, 0x0198, 0x819D, 0x8197, 0x0192, + 0x01B0, 0x81B5, 0x81BF, 0x01BA, 0x81AB, 0x01AE, 0x01A4, 0x81A1, + 0x01E0, 0x81E5, 0x81EF, 0x01EA, 0x81FB, 0x01FE, 0x01F4, 0x81F1, + 0x81D3, 0x01D6, 0x01DC, 0x81D9, 0x01C8, 0x81CD, 0x81C7, 0x01C2, + 0x0140, 0x8145, 0x814F, 0x014A, 0x815B, 0x015E, 0x0154, 0x8151, + 0x8173, 0x0176, 0x017C, 0x8179, 0x0168, 0x816D, 0x8167, 0x0162, + 0x8123, 0x0126, 0x012C, 0x8129, 0x0138, 0x813D, 0x8137, 0x0132, + 0x0110, 0x8115, 0x811F, 0x011A, 0x810B, 0x010E, 0x0104, 0x8101, + 0x8303, 0x0306, 0x030C, 0x8309, 0x0318, 0x831D, 0x8317, 0x0312, + 0x0330, 0x8335, 0x833F, 0x033A, 0x832B, 0x032E, 0x0324, 0x8321, + 0x0360, 0x8365, 0x836F, 0x036A, 0x837B, 0x037E, 0x0374, 0x8371, + 0x8353, 0x0356, 0x035C, 0x8359, 0x0348, 0x834D, 0x8347, 0x0342, + 0x03C0, 0x83C5, 0x83CF, 0x03CA, 0x83DB, 0x03DE, 0x03D4, 0x83D1, + 0x83F3, 0x03F6, 0x03FC, 0x83F9, 0x03E8, 0x83ED, 0x83E7, 0x03E2, + 0x83A3, 0x03A6, 0x03AC, 0x83A9, 0x03B8, 0x83BD, 0x83B7, 0x03B2, + 0x0390, 0x8395, 0x839F, 0x039A, 0x838B, 0x038E, 0x0384, 0x8381, + 0x0280, 0x8285, 0x828F, 0x028A, 0x829B, 0x029E, 0x0294, 0x8291, + 0x82B3, 0x02B6, 0x02BC, 0x82B9, 0x02A8, 0x82AD, 0x82A7, 0x02A2, + 0x82E3, 0x02E6, 0x02EC, 0x82E9, 0x02F8, 0x82FD, 0x82F7, 0x02F2, + 0x02D0, 0x82D5, 0x82DF, 0x02DA, 0x82CB, 0x02CE, 0x02C4, 0x82C1, + 0x8243, 0x0246, 0x024C, 0x8249, 0x0258, 0x825D, 0x8257, 0x0252, + 0x0270, 0x8275, 0x827F, 0x027A, 0x826B, 0x026E, 0x0264, 0x8261, + 0x0220, 0x8225, 0x822F, 0x022A, 0x823B, 0x023E, 0x0234, 0x8231, + 0x8213, 0x0216, 0x021C, 0x8219, 0x0208, 0x820D, 0x8207, 0x0202 +}; + +// CRC-8-MAXIM G(X)=X8+X5+X4+1 +const uint8_t crc8_31_msb_lut[256] = { + 0x00, 0x31, 0x62, 0x53, 0xC4, 0xF5, 0xA6, 0x97, + 0xB9, 0x88, 0xDB, 0xEA, 0x7D, 0x4C, 0x1F, 0x2E, + 0x43, 0x72, 0x21, 0x10, 0x87, 0xB6, 0xE5, 0xD4, + 0xFA, 0xCB, 0x98, 0xA9, 0x3E, 0x0F, 0x5C, 0x6D, + 0x86, 0xB7, 0xE4, 0xD5, 0x42, 0x73, 0x20, 0x11, + 0x3F, 0x0E, 0x5D, 0x6C, 0xFB, 0xCA, 0x99, 0xA8, + 0xC5, 0xF4, 0xA7, 0x96, 0x01, 0x30, 0x63, 0x52, + 0x7C, 0x4D, 0x1E, 0x2F, 0xB8, 0x89, 0xDA, 0xEB, + 0x3D, 0x0C, 0x5F, 0x6E, 0xF9, 0xC8, 0x9B, 0xAA, + 0x84, 0xB5, 0xE6, 0xD7, 0x40, 0x71, 0x22, 0x13, + 0x7E, 0x4F, 0x1C, 0x2D, 0xBA, 0x8B, 0xD8, 0xE9, + 0xC7, 0xF6, 0xA5, 0x94, 0x03, 0x32, 0x61, 0x50, + 0xBB, 0x8A, 0xD9, 0xE8, 0x7F, 0x4E, 0x1D, 0x2C, + 0x02, 0x33, 0x60, 0x51, 0xC6, 0xF7, 0xA4, 0x95, + 0xF8, 0xC9, 0x9A, 0xAB, 0x3C, 0x0D, 0x5E, 0x6F, + 0x41, 0x70, 0x23, 0x12, 0x85, 0xB4, 0xE7, 0xD6, + 0x7A, 0x4B, 0x18, 0x29, 0xBE, 0x8F, 0xDC, 0xED, + 0xC3, 0xF2, 0xA1, 0x90, 0x07, 0x36, 0x65, 0x54, + 0x39, 0x08, 0x5B, 0x6A, 0xFD, 0xCC, 0x9F, 0xAE, + 0x80, 0xB1, 0xE2, 0xD3, 0x44, 0x75, 0x26, 0x17, + 0xFC, 0xCD, 0x9E, 0xAF, 0x38, 0x09, 0x5A, 0x6B, + 0x45, 0x74, 0x27, 0x16, 0x81, 0xB0, 0xE3, 0xD2, + 0xBF, 0x8E, 0xDD, 0xEC, 0x7B, 0x4A, 0x19, 0x28, + 0x06, 0x37, 0x64, 0x55, 0xC2, 0xF3, 0xA0, 0x91, + 0x47, 0x76, 0x25, 0x14, 0x83, 0xB2, 0xE1, 0xD0, + 0xFE, 0xCF, 0x9C, 0xAD, 0x3A, 0x0B, 0x58, 0x69, + 0x04, 0x35, 0x66, 0x57, 0xC0, 0xF1, 0xA2, 0x93, + 0xBD, 0x8C, 0xDF, 0xEE, 0x79, 0x48, 0x1B, 0x2A, + 0xC1, 0xF0, 0xA3, 0x92, 0x05, 0x34, 0x67, 0x56, + 0x78, 0x49, 0x1A, 0x2B, 0xBC, 0x8D, 0xDE, 0xEF, + 0x82, 0xB3, 0xE0, 0xD1, 0x46, 0x77, 0x24, 0x15, + 0x3B, 0x0A, 0x59, 0x68, 0xFF, 0xCE, 0x9D, 0xAC +}; +#endif + +/* CRC lookup table algorithm +#define CRC_BIT_NUM 8u/16u/32u/64u +#define BITS_IN_BYTE 8u +uint8_t dataBuff[ARRAY_SIZE] = { 0x32, 0x33, …}; +uint8_t/uint16_t/uint32_t crc_val = 0x0; +// LSB +for(int i = 0; i < sizeof(dataBuff); i++) +{ + crc_val = (crc_val >> BITS_IN_BYTE) ^ crc_lsb_lut[(uint8)(crc_val^dataBuff[i])]; +} +// MSB +for(int i = 0; i < sizeof(dataBuff); i++) +{ + crc_val = (crc_val << BITS_IN_BYTE) ^ crc_msb_lut[(uint8)((crc_val>>8)^dataBuff[i])]; +} +*/ + +/*****************************************************************************/ +/** + * @brief CRC8 generator + * + * @param buffPtr data buffer pointer. + * @param dataLen data length + * @param poly polynomials of crc + * @param crcVal a pointer to store generated crc value + * + * @return SUCCESS + * FAILURE + * + ******************************************************************************/ +int crc8_gen(uint8_t* buffPtr, uint32_t dataLen, uint16_t poly, uint8_t* crcVal) { + uint8_t crc = CRC8_INIT; + const uint8_t* crc_lut = NULL; + + switch(poly){ +#ifdef __CRC_LSB + case 0x31: + crc_lut = crc8_31_lsb_lut; + break; + default: + return FAILURE; +#else + case 0x31: + crc_lut = crc8_31_msb_lut; + break; + default: + return FAILURE; +#endif + } + + for(int i = 0; i < dataLen; i++){ + crc = crc_lut[(uint8_t)(crc^buffPtr[i])]; + } + *crcVal = crc; + return SUCCESS; +} + + +/*****************************************************************************/ +/** + * @brief CRC16 generator + * + * @param buffPtr data buffer pointer. + * @param dataLen data length + * @param poly polynomials of crc + * @param crcVal a pointer to store generated crc value + * + * @return SUCCESS + * FAILURE + * + ******************************************************************************/ +int crc16_gen(uint8_t* buffPtr, uint32_t dataLen, uint16_t poly, uint16_t* crcVal) { + uint16_t crc = CRC16_INIT; + const uint16_t* crc_lut = NULL; + switch(poly){ +#ifdef __CRC_LSB + case 0x8005: + crc_lut = crc16_8005_lsb_lut; + break; + case 0x1021: + crc_lut = crc16_1021_lsb_lut; + break; + default: + return FAILURE; +#else + case 0x8005: + crc_lut = crc16_8005_msb_lut; + break; + case 0x1021: + crc_lut = crc16_1021_msb_lut; + break; + default: + return FAILURE; +#endif + } + for(int i = 0; i < dataLen; i++){ +#ifdef __CRC_LSB + crc = (crc>>8) ^ crc_lut[(uint8_t)(crc^buffPtr[i])]; +#else + crc = (crc<<8) ^ crc_lut[(uint8_t)((crc >> 8)^buffPtr[i])]; +#endif + } + *crcVal = crc; + return SUCCESS; +} + +/*****************************************************************************/ +/** + * @brief CRC8 compare cheker + * + * @param buffPtr data buffer pointer. + * @param dataLen data length + * @param crcOffset byte offset of crc stored position. + * @param poly polynomials of crc + * + * @return true + * false + * +******************************************************************************/ +bool crc8_check(uint8_t* buffPtr, uint32_t dataLen, uint32_t crcOffset, uint16_t poly) { + int Status = SUCCESS; + uint8_t crc_comp; + uint8_t crc; + if (dataLen == 0) { + return false; + } + crc_comp = (uint8_t)(*(buffPtr + crcOffset)); + Status = crc8_gen(buffPtr, dataLen, poly, &crc); + if(Status == SUCCESS){ + if (crc == crc_comp) { + return true; + } + else { + return false; + } + } + else{ + return false; + } +} + + +/*****************************************************************************/ +/** + * @brief CRC16 compare cheker + * + * @param buffPtr data buffer pointer. + * @param dataLen data length + * @param crcOffset byte offset of crc stored position. + * @param poly polynomials of crc + * + * @return true + * fasle + * +******************************************************************************/ +bool crc16_check(uint8_t* buffPtr, uint32_t dataLen, uint32_t crcOffset, uint16_t poly) { + int Status = SUCCESS; + uint16_t crc_comp; + uint16_t crc; + if (dataLen == 0) { + return false; + } + crc_comp = (uint16_t)(*(buffPtr + crcOffset)); + crc_comp |= (uint16_t)((*(buffPtr + crcOffset + 1)) << 8); + Status = crc16_gen(buffPtr, dataLen, poly, &crc); + if(Status == SUCCESS){ + if (crc == crc_comp) { + return true; + } + else { + return false; + } + } + else{ + return false; + } +} diff --git a/datalink814_ge/src/util/tables.txt b/datalink814_ge/src/util/tables.txt new file mode 100644 index 0000000..b3bff8c --- /dev/null +++ b/datalink814_ge/src/util/tables.txt @@ -0,0 +1,231 @@ +Generating CRC table for crc8-31-lsb + +0x00, 0x5E, 0xBC, 0xE2, 0x61, 0x3F, 0xDD, 0x83, +0xC2, 0x9C, 0x7E, 0x20, 0xA3, 0xFD, 0x1F, 0x41, +0x9D, 0xC3, 0x21, 0x7F, 0xFC, 0xA2, 0x40, 0x1E, +0x5F, 0x01, 0xE3, 0xBD, 0x3E, 0x60, 0x82, 0xDC, +0x23, 0x7D, 0x9F, 0xC1, 0x42, 0x1C, 0xFE, 0xA0, +0xE1, 0xBF, 0x5D, 0x03, 0x80, 0xDE, 0x3C, 0x62, +0xBE, 0xE0, 0x02, 0x5C, 0xDF, 0x81, 0x63, 0x3D, +0x7C, 0x22, 0xC0, 0x9E, 0x1D, 0x43, 0xA1, 0xFF, +0x46, 0x18, 0xFA, 0xA4, 0x27, 0x79, 0x9B, 0xC5, +0x84, 0xDA, 0x38, 0x66, 0xE5, 0xBB, 0x59, 0x07, +0xDB, 0x85, 0x67, 0x39, 0xBA, 0xE4, 0x06, 0x58, +0x19, 0x47, 0xA5, 0xFB, 0x78, 0x26, 0xC4, 0x9A, +0x65, 0x3B, 0xD9, 0x87, 0x04, 0x5A, 0xB8, 0xE6, +0xA7, 0xF9, 0x1B, 0x45, 0xC6, 0x98, 0x7A, 0x24, +0xF8, 0xA6, 0x44, 0x1A, 0x99, 0xC7, 0x25, 0x7B, +0x3A, 0x64, 0x86, 0xD8, 0x5B, 0x05, 0xE7, 0xB9, +0x8C, 0xD2, 0x30, 0x6E, 0xED, 0xB3, 0x51, 0x0F, +0x4E, 0x10, 0xF2, 0xAC, 0x2F, 0x71, 0x93, 0xCD, +0x11, 0x4F, 0xAD, 0xF3, 0x70, 0x2E, 0xCC, 0x92, +0xD3, 0x8D, 0x6F, 0x31, 0xB2, 0xEC, 0x0E, 0x50, +0xAF, 0xF1, 0x13, 0x4D, 0xCE, 0x90, 0x72, 0x2C, +0x6D, 0x33, 0xD1, 0x8F, 0x0C, 0x52, 0xB0, 0xEE, +0x32, 0x6C, 0x8E, 0xD0, 0x53, 0x0D, 0xEF, 0xB1, +0xF0, 0xAE, 0x4C, 0x12, 0x91, 0xCF, 0x2D, 0x73, +0xCA, 0x94, 0x76, 0x28, 0xAB, 0xF5, 0x17, 0x49, +0x08, 0x56, 0xB4, 0xEA, 0x69, 0x37, 0xD5, 0x8B, +0x57, 0x09, 0xEB, 0xB5, 0x36, 0x68, 0x8A, 0xD4, +0x95, 0xCB, 0x29, 0x77, 0xF4, 0xAA, 0x48, 0x16, +0xE9, 0xB7, 0x55, 0x0B, 0x88, 0xD6, 0x34, 0x6A, +0x2B, 0x75, 0x97, 0xC9, 0x4A, 0x14, 0xF6, 0xA8, +0x74, 0x2A, 0xC8, 0x96, 0x15, 0x4B, 0xA9, 0xF7, +0xB6, 0xE8, 0x0A, 0x54, 0xD7, 0x89, 0x6B, 0x35, + + +Generating CRC table for crc8-31-msb + +0x00, 0x31, 0x62, 0x53, 0xC4, 0xF5, 0xA6, 0x97, +0xB9, 0x88, 0xDB, 0xEA, 0x7D, 0x4C, 0x1F, 0x2E, +0x43, 0x72, 0x21, 0x10, 0x87, 0xB6, 0xE5, 0xD4, +0xFA, 0xCB, 0x98, 0xA9, 0x3E, 0x0F, 0x5C, 0x6D, +0x86, 0xB7, 0xE4, 0xD5, 0x42, 0x73, 0x20, 0x11, +0x3F, 0x0E, 0x5D, 0x6C, 0xFB, 0xCA, 0x99, 0xA8, +0xC5, 0xF4, 0xA7, 0x96, 0x01, 0x30, 0x63, 0x52, +0x7C, 0x4D, 0x1E, 0x2F, 0xB8, 0x89, 0xDA, 0xEB, +0x3D, 0x0C, 0x5F, 0x6E, 0xF9, 0xC8, 0x9B, 0xAA, +0x84, 0xB5, 0xE6, 0xD7, 0x40, 0x71, 0x22, 0x13, +0x7E, 0x4F, 0x1C, 0x2D, 0xBA, 0x8B, 0xD8, 0xE9, +0xC7, 0xF6, 0xA5, 0x94, 0x03, 0x32, 0x61, 0x50, +0xBB, 0x8A, 0xD9, 0xE8, 0x7F, 0x4E, 0x1D, 0x2C, +0x02, 0x33, 0x60, 0x51, 0xC6, 0xF7, 0xA4, 0x95, +0xF8, 0xC9, 0x9A, 0xAB, 0x3C, 0x0D, 0x5E, 0x6F, +0x41, 0x70, 0x23, 0x12, 0x85, 0xB4, 0xE7, 0xD6, +0x7A, 0x4B, 0x18, 0x29, 0xBE, 0x8F, 0xDC, 0xED, +0xC3, 0xF2, 0xA1, 0x90, 0x07, 0x36, 0x65, 0x54, +0x39, 0x08, 0x5B, 0x6A, 0xFD, 0xCC, 0x9F, 0xAE, +0x80, 0xB1, 0xE2, 0xD3, 0x44, 0x75, 0x26, 0x17, +0xFC, 0xCD, 0x9E, 0xAF, 0x38, 0x09, 0x5A, 0x6B, +0x45, 0x74, 0x27, 0x16, 0x81, 0xB0, 0xE3, 0xD2, +0xBF, 0x8E, 0xDD, 0xEC, 0x7B, 0x4A, 0x19, 0x28, +0x06, 0x37, 0x64, 0x55, 0xC2, 0xF3, 0xA0, 0x91, +0x47, 0x76, 0x25, 0x14, 0x83, 0xB2, 0xE1, 0xD0, +0xFE, 0xCF, 0x9C, 0xAD, 0x3A, 0x0B, 0x58, 0x69, +0x04, 0x35, 0x66, 0x57, 0xC0, 0xF1, 0xA2, 0x93, +0xBD, 0x8C, 0xDF, 0xEE, 0x79, 0x48, 0x1B, 0x2A, +0xC1, 0xF0, 0xA3, 0x92, 0x05, 0x34, 0x67, 0x56, +0x78, 0x49, 0x1A, 0x2B, 0xBC, 0x8D, 0xDE, 0xEF, +0x82, 0xB3, 0xE0, 0xD1, 0x46, 0x77, 0x24, 0x15, +0x3B, 0x0A, 0x59, 0x68, 0xFF, 0xCE, 0x9D, 0xAC, + + +Generating CRC table for crc16-8005-lsb + +0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, +0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440, +0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40, +0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841, +0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40, +0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41, +0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641, +0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040, +0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240, +0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441, +0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41, +0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840, +0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41, +0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40, +0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640, +0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041, +0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240, +0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441, +0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41, +0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840, +0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41, +0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40, +0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640, +0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041, +0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241, +0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440, +0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40, +0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841, +0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40, +0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41, +0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641, +0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040, + + +Generating CRC table for crc16-8005-msb + +0x0000, 0x8005, 0x800F, 0x000A, 0x801B, 0x001E, 0x0014, 0x8011, +0x8033, 0x0036, 0x003C, 0x8039, 0x0028, 0x802D, 0x8027, 0x0022, +0x8063, 0x0066, 0x006C, 0x8069, 0x0078, 0x807D, 0x8077, 0x0072, +0x0050, 0x8055, 0x805F, 0x005A, 0x804B, 0x004E, 0x0044, 0x8041, +0x80C3, 0x00C6, 0x00CC, 0x80C9, 0x00D8, 0x80DD, 0x80D7, 0x00D2, +0x00F0, 0x80F5, 0x80FF, 0x00FA, 0x80EB, 0x00EE, 0x00E4, 0x80E1, +0x00A0, 0x80A5, 0x80AF, 0x00AA, 0x80BB, 0x00BE, 0x00B4, 0x80B1, +0x8093, 0x0096, 0x009C, 0x8099, 0x0088, 0x808D, 0x8087, 0x0082, +0x8183, 0x0186, 0x018C, 0x8189, 0x0198, 0x819D, 0x8197, 0x0192, +0x01B0, 0x81B5, 0x81BF, 0x01BA, 0x81AB, 0x01AE, 0x01A4, 0x81A1, +0x01E0, 0x81E5, 0x81EF, 0x01EA, 0x81FB, 0x01FE, 0x01F4, 0x81F1, +0x81D3, 0x01D6, 0x01DC, 0x81D9, 0x01C8, 0x81CD, 0x81C7, 0x01C2, +0x0140, 0x8145, 0x814F, 0x014A, 0x815B, 0x015E, 0x0154, 0x8151, +0x8173, 0x0176, 0x017C, 0x8179, 0x0168, 0x816D, 0x8167, 0x0162, +0x8123, 0x0126, 0x012C, 0x8129, 0x0138, 0x813D, 0x8137, 0x0132, +0x0110, 0x8115, 0x811F, 0x011A, 0x810B, 0x010E, 0x0104, 0x8101, +0x8303, 0x0306, 0x030C, 0x8309, 0x0318, 0x831D, 0x8317, 0x0312, +0x0330, 0x8335, 0x833F, 0x033A, 0x832B, 0x032E, 0x0324, 0x8321, +0x0360, 0x8365, 0x836F, 0x036A, 0x837B, 0x037E, 0x0374, 0x8371, +0x8353, 0x0356, 0x035C, 0x8359, 0x0348, 0x834D, 0x8347, 0x0342, +0x03C0, 0x83C5, 0x83CF, 0x03CA, 0x83DB, 0x03DE, 0x03D4, 0x83D1, +0x83F3, 0x03F6, 0x03FC, 0x83F9, 0x03E8, 0x83ED, 0x83E7, 0x03E2, +0x83A3, 0x03A6, 0x03AC, 0x83A9, 0x03B8, 0x83BD, 0x83B7, 0x03B2, +0x0390, 0x8395, 0x839F, 0x039A, 0x838B, 0x038E, 0x0384, 0x8381, +0x0280, 0x8285, 0x828F, 0x028A, 0x829B, 0x029E, 0x0294, 0x8291, +0x82B3, 0x02B6, 0x02BC, 0x82B9, 0x02A8, 0x82AD, 0x82A7, 0x02A2, +0x82E3, 0x02E6, 0x02EC, 0x82E9, 0x02F8, 0x82FD, 0x82F7, 0x02F2, +0x02D0, 0x82D5, 0x82DF, 0x02DA, 0x82CB, 0x02CE, 0x02C4, 0x82C1, +0x8243, 0x0246, 0x024C, 0x8249, 0x0258, 0x825D, 0x8257, 0x0252, +0x0270, 0x8275, 0x827F, 0x027A, 0x826B, 0x026E, 0x0264, 0x8261, +0x0220, 0x8225, 0x822F, 0x022A, 0x823B, 0x023E, 0x0234, 0x8231, +0x8213, 0x0216, 0x021C, 0x8219, 0x0208, 0x820D, 0x8207, 0x0202, + + +Generating CRC table for crc16-1021-lsb + +0x0000, 0x1189, 0x2312, 0x329B, 0x4624, 0x57AD, 0x6536, 0x74BF, +0x8C48, 0x9DC1, 0xAF5A, 0xBED3, 0xCA6C, 0xDBE5, 0xE97E, 0xF8F7, +0x1081, 0x0108, 0x3393, 0x221A, 0x56A5, 0x472C, 0x75B7, 0x643E, +0x9CC9, 0x8D40, 0xBFDB, 0xAE52, 0xDAED, 0xCB64, 0xF9FF, 0xE876, +0x2102, 0x308B, 0x0210, 0x1399, 0x6726, 0x76AF, 0x4434, 0x55BD, +0xAD4A, 0xBCC3, 0x8E58, 0x9FD1, 0xEB6E, 0xFAE7, 0xC87C, 0xD9F5, +0x3183, 0x200A, 0x1291, 0x0318, 0x77A7, 0x662E, 0x54B5, 0x453C, +0xBDCB, 0xAC42, 0x9ED9, 0x8F50, 0xFBEF, 0xEA66, 0xD8FD, 0xC974, +0x4204, 0x538D, 0x6116, 0x709F, 0x0420, 0x15A9, 0x2732, 0x36BB, +0xCE4C, 0xDFC5, 0xED5E, 0xFCD7, 0x8868, 0x99E1, 0xAB7A, 0xBAF3, +0x5285, 0x430C, 0x7197, 0x601E, 0x14A1, 0x0528, 0x37B3, 0x263A, +0xDECD, 0xCF44, 0xFDDF, 0xEC56, 0x98E9, 0x8960, 0xBBFB, 0xAA72, +0x6306, 0x728F, 0x4014, 0x519D, 0x2522, 0x34AB, 0x0630, 0x17B9, +0xEF4E, 0xFEC7, 0xCC5C, 0xDDD5, 0xA96A, 0xB8E3, 0x8A78, 0x9BF1, +0x7387, 0x620E, 0x5095, 0x411C, 0x35A3, 0x242A, 0x16B1, 0x0738, +0xFFCF, 0xEE46, 0xDCDD, 0xCD54, 0xB9EB, 0xA862, 0x9AF9, 0x8B70, +0x8408, 0x9581, 0xA71A, 0xB693, 0xC22C, 0xD3A5, 0xE13E, 0xF0B7, +0x0840, 0x19C9, 0x2B52, 0x3ADB, 0x4E64, 0x5FED, 0x6D76, 0x7CFF, +0x9489, 0x8500, 0xB79B, 0xA612, 0xD2AD, 0xC324, 0xF1BF, 0xE036, +0x18C1, 0x0948, 0x3BD3, 0x2A5A, 0x5EE5, 0x4F6C, 0x7DF7, 0x6C7E, +0xA50A, 0xB483, 0x8618, 0x9791, 0xE32E, 0xF2A7, 0xC03C, 0xD1B5, +0x2942, 0x38CB, 0x0A50, 0x1BD9, 0x6F66, 0x7EEF, 0x4C74, 0x5DFD, +0xB58B, 0xA402, 0x9699, 0x8710, 0xF3AF, 0xE226, 0xD0BD, 0xC134, +0x39C3, 0x284A, 0x1AD1, 0x0B58, 0x7FE7, 0x6E6E, 0x5CF5, 0x4D7C, +0xC60C, 0xD785, 0xE51E, 0xF497, 0x8028, 0x91A1, 0xA33A, 0xB2B3, +0x4A44, 0x5BCD, 0x6956, 0x78DF, 0x0C60, 0x1DE9, 0x2F72, 0x3EFB, +0xD68D, 0xC704, 0xF59F, 0xE416, 0x90A9, 0x8120, 0xB3BB, 0xA232, +0x5AC5, 0x4B4C, 0x79D7, 0x685E, 0x1CE1, 0x0D68, 0x3FF3, 0x2E7A, +0xE70E, 0xF687, 0xC41C, 0xD595, 0xA12A, 0xB0A3, 0x8238, 0x93B1, +0x6B46, 0x7ACF, 0x4854, 0x59DD, 0x2D62, 0x3CEB, 0x0E70, 0x1FF9, +0xF78F, 0xE606, 0xD49D, 0xC514, 0xB1AB, 0xA022, 0x92B9, 0x8330, +0x7BC7, 0x6A4E, 0x58D5, 0x495C, 0x3DE3, 0x2C6A, 0x1EF1, 0x0F78, + + +Generating CRC table for crc16-1021-msb + +0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, +0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, +0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, +0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, +0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485, +0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D, +0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4, +0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC, +0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823, +0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, +0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, +0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, +0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, +0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49, +0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70, +0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78, +0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F, +0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067, +0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, +0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, +0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, +0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, +0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C, +0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634, +0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB, +0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3, +0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, +0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, +0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, +0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, +0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, +0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0, + + + +#define CRC_BIT_NUM 8u/16u/32u/64u +#define BITS_IN_BYTE 8u +uint8_t dataBuff[ARRAY_SIZE] = { 0x32, 0x33, ...; +uint8_t/uint16_t/uint32_t crc_val = 0x0; +// LSB +for(int i = 0; i < sizeof(dataBuff); i++) +{ + crc_val = (crc_val >> BITS_IN_BYTE) ^ crc_lsb_lut[(uint8)(crc_val^dataBuff[i])]; +} +// MSB +for(int i = 0; i < sizeof(dataBuff); i++) +{ + crc_val = (crc_val << BITS_IN_BYTE) ^ crc_msb_lut[(uint8)((crc_val>>8)^dataBuff[i])]; +} \ No newline at end of file diff --git a/datalink814_ge/src/util/util.c b/datalink814_ge/src/util/util.c new file mode 100644 index 0000000..c30365a --- /dev/null +++ b/datalink814_ge/src/util/util.c @@ -0,0 +1,351 @@ +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include +#include +// #include +#include "util.h" +#include "../error.h" + +/******************************************************************************/ +/************************** Functions Implementation **************************/ +/******************************************************************************/ +#ifdef __BITSWAP_TABLE +static uint8_t byte_flipLR[256] = { + 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, + 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0, + 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, + 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, + 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, + 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4, + 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, + 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC, + 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, + 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2, + 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, + 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA, + 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, + 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6, + 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, + 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE, + 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, + 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1, + 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, + 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9, + 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, + 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5, + 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, + 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD, + 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, + 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3, + 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, + 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB, + 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, + 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7, + 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, + 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF +}; +#endif + +inline void IO_Out32(uintptr_t addr, uint32_t value){ + volatile uint32_t *localAddr = (volatile uint32_t *)addr; + *localAddr = value; +} + +inline uint32_t IO_In32(uintptr_t addr){ + return *(volatile uint32_t*) addr; +} + +uint8_t byte_bit_swap(uint8_t byte){ +#ifdef __BITSWAP_TABLE + return byte_flipLR[byte]; +#else + return bit_swap_constant_8(byte); +#endif +} + +uint32_t word_bit_swap(uint32_t word){ +#ifdef __BITSWAP_TABLE + uint32_t rv_word = (byte_flipLR[word & 0xff] << 24) | + (byte_flipLR[(word >> 8) & 0xff] << 16) | + (byte_flipLR[(word >> 16) & 0xff] << 8) | + (byte_flipLR[(word >> 24) & 0xff]); + return rv_word; +#else + word = (((word & 0xaaaaaaaa) >> 1) | ((word & 0x55555555) << 1)); + word = (((word & 0xcccccccc) >> 2) | ((word & 0x33333333) << 2)); + word = (((word & 0xf0f0f0f0) >> 4) | ((word & 0x0f0f0f0f) << 4)); + word = (((word & 0xff00ff00) >> 8) | ((word & 0x00ff00ff) << 8)); + return((word >> 16) | (word << 16)); +#endif +} + +uint32_t count_ones(uint32_t word){ +#ifdef __GNUC__ + return __builtin_popcount(word); +#else + uint32_t one_count = 0; + while (word) { + if (word & 0x00000001) + one_count ++; + word >>= 1; + } + return one_count; +#endif +} + +double fix2double(int32_t val, uint8_t frac_bits){ + return (((double)val)/(BIT(frac_bits))); +} + +/** + * Find first set bit in word. + */ +uint32_t find_first_set_bit(uint32_t word) +{ +#ifdef __GNUC__ + if(word != 0){ + return __builtin_ctz(word); + } + else{ + return 32; + } +#else + uint32_t first_set_bit = 0; + + while (word) { + if (word & 0x1) + return first_set_bit; + word >>= 1; + first_set_bit ++; + } + + return 32; +#endif +} + +/** + * Find last set bit in word. + */ +uint32_t find_last_set_bit(uint32_t word) +{ +#ifdef __GNUC__ + if(word != 0){ + return (31-__builtin_clz(word)); + } + else{ + return 32; + } +#else + uint32_t bit = 0; + uint32_t last_set_bit = 32; + + while (word) { + if (word & 0x1) + last_set_bit = bit; + word >>= 1; + bit ++; + } + + return last_set_bit; +#endif +} + +/** + * Locate the closest element in an array. + */ +uint32_t find_closest(int32_t val, + const int32_t *array, + uint32_t size) +{ + int32_t diff = abs(array[0] - val); + uint32_t ret = 0; + uint32_t i; + + for (i = 1; i < size; i++) { + if (abs(array[i] - val) < diff) { + diff = abs(array[i] - val); + ret = i; + } + } + + return ret; +} + +/** + * Shift the value and apply the specified mask. + */ +uint32_t field_prep(uint32_t mask, uint32_t val) +{ + return (val << find_first_set_bit(mask)) & mask; +} + +/** + * Get a field specified by a mask from a word. + */ +uint32_t field_get(uint32_t mask, uint32_t word) +{ + return (word & mask) >> find_first_set_bit(mask); +} + +/** + * Log base 2 of the given number. + */ +int32_t log_base_2(uint32_t x) +{ + return find_last_set_bit(x); +} + +/** + * Find greatest common divisor of the given two numbers. + */ +uint32_t greatest_common_divisor(uint32_t a, + uint32_t b) +{ + uint32_t div; + uint32_t common_div = 1; + + if ((a == 0) || (b == 0)) + return max(a, b); + + for (div = 1; (div <= a) && (div <= b); div++) + if (!(a % div) && !(b % div)) + common_div = div; + + return common_div; +} + +/** + * Calculate best rational approximation for a given fraction. + */ +void rational_best_approximation(uint32_t given_numerator, + uint32_t given_denominator, + uint32_t max_numerator, + uint32_t max_denominator, + uint32_t *best_numerator, + uint32_t *best_denominator) +{ + uint32_t gcd; + + gcd = greatest_common_divisor(given_numerator, given_denominator); + + *best_numerator = given_numerator / gcd; + *best_denominator = given_denominator / gcd; + + if ((*best_numerator > max_numerator) || + (*best_denominator > max_denominator)) { + *best_numerator = 0; + *best_denominator = 0; + } +} + +/** + * Calculate the number of set bits. + */ +uint32_t hweight8(uint32_t word) +{ + uint32_t count = 0; + + while (word) { + if (word & 0x1) + count++; + word >>= 1; + } + + return count; +} + +/** + * Calculate the quotient and the remainder of an integer division. + */ +uint64_t do_div(uint64_t* n, + uint64_t base) +{ + uint64_t mod = 0; + + mod = *n % base; + *n = *n / base; + + return mod; +} + +/** + * Unsigned 64bit divide with 64bit divisor and remainder + */ +uint64_t div64_u64_rem(uint64_t dividend, uint64_t divisor, uint64_t *remainder) +{ + *remainder = dividend % divisor; + + return dividend / divisor; +} + +/** + * Unsigned 64bit divide with 32bit divisor with remainder + */ +uint64_t div_u64_rem(uint64_t dividend, uint32_t divisor, uint32_t *remainder) +{ + *remainder = do_div(÷nd, divisor); + + return dividend; +} + +/** + * Signed 64bit divide with 32bit divisor with remainder + */ +int64_t div_s64_rem(int64_t dividend, int32_t divisor, int32_t *remainder) +{ + *remainder = dividend % divisor; + return dividend / divisor; +} + +/** + * Unsigned 64bit divide with 32bit divisor + */ +uint64_t div_u64(uint64_t dividend, uint32_t divisor) +{ + uint32_t remainder; + + return div_u64_rem(dividend, divisor, &remainder); +} + +/** + * Signed 64bit divide with 32bit divisor + */ +int64_t div_s64(int64_t dividend, int32_t divisor) +{ + int32_t remainder; + return div_s64_rem(dividend, divisor, &remainder); +} + +/** + * Converts from string to int32_t + * @param *str + * @return int32_t + */ +int32_t str_to_int32(const char *str) +{ + char *end; + int32_t value = strtol(str, &end, 0); + + if (end == str) + return FAILURE; + else + return value; +} + +/** + * Converts from string to uint32_t + * @param *str + * @return uint32_t + */ +uint32_t srt_to_uint32(const char *str) +{ + char *end; + uint32_t value = strtoul(str, &end, 0); + + if (end == str) + return FAILURE; + else + return value; +} + diff --git a/datalink814_ge/src/util/util.h b/datalink814_ge/src/util/util.h new file mode 100644 index 0000000..fa8ff80 --- /dev/null +++ b/datalink814_ge/src/util/util.h @@ -0,0 +1,192 @@ +/***************************************************************************//** + * @file util.h + * @brief Implementation of utility functions. + * @author DBogdan (dragos.bogdan@analog.com) +******************************************************************************** + * Copyright 2018(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ +#ifndef UTIL_H_ +#define UTIL_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include +#include +#include +/******************************************************************************/ +/********************** Macros and Constants Definitions **********************/ +/******************************************************************************/ +//#define __CRC_LSB +#define __BITSWAP_TABLE +#define __CRC_LSB +#define CRC16_INIT 0x0000 +#define CRC8_INIT 0x00 + +#define BIT(x) (1 << (x)) + +#define ARRAY_SIZE(x) \ + (sizeof(x) / sizeof((x)[0])) + +#define DIV_ROUND_UP(x,y) \ + (((x) + (y) - 1) / (y)) +#define DIV_ROUND_CLOSEST(x, y) \ + (((x) + (y) / 2) / (y)) +#define DIV_ROUND_CLOSEST_ULL(x, y) \ + DIV_ROUND_CLOSEST(x, y) + +#define min(x, y) \ + (((x) < (y)) ? (x) : (y)) +#define min_t(type, x, y) \ + (type)min((type)(x), (type)(y)) + +#define max(x, y) \ + (((x) > (y)) ? (x) : (y)) +#define max_t(type, x, y) \ + (type)max((type)(x), (type)(y)) + +#define clamp(val, min_val, max_val) \ + (max(min((val), (max_val)), (min_val))) +#define clamp_t(type, val, min_val, max_val) \ + (type)clamp((type)(val), (type)(min_val), (type)(max_val)) + +#define swap(x, y) \ + {typeof(x) _tmp_ = (x); (x) = (y); (y) = _tmp_;} + +#define round_up(x,y) \ + (((x)+(y)-1)/(y)) + +#define BITS_PER_LONG 32 + +#define GENMASK(h, l) ({ \ + uint32_t t = (uint32_t)(~0UL); \ + t = t << (BITS_PER_LONG - (h - l + 1)); \ + t = t >> (BITS_PER_LONG - (h + 1)); \ + t; \ +}) + +#define bswap_constant_32(x) \ + ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \ + (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24)) + +#define bswap_constant_16(x) ((((x) & (uint16_t)0xff00) >> 8) | \ + (((x) & (uint16_t)0x00ff) << 8)) + +#define bit_swap_constant_8(x) \ + ((((x) & 0x80) >> 7) | \ + (((x) & 0x40) >> 5) | \ + (((x) & 0x20) >> 3) | \ + (((x) & 0x10) >> 1) | \ + (((x) & 0x08) << 1) | \ + (((x) & 0x04) << 3) | \ + (((x) & 0x02) << 5) | \ + (((x) & 0x01) << 7)) + +#define U16_MAX ((uint16_t)~0U) +#define S16_MAX ((int16_t)(U16_MAX>>1)) + +#define DIV_U64(x, y) (x / y) + +#define UNUSED_PARAM(x) ((void)x) + +#define shift_right(x, s) ((x) < 0 ? -(-(x) >> (s)) : (x) >> (s)) + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ + +void IO_Out32(uintptr_t addr, uint32_t value); +uint32_t IO_In32(uintptr_t addr); + +/* flip a byte left to right*/ +uint8_t byte_bit_swap(uint8_t byte); + +/* flip a 32bit word left to right */ +uint32_t word_bit_swap(uint32_t word); + +/* Returns the number of 1-bits in digit. */ +uint32_t count_ones(uint32_t word); + +/* convert a fixed number to a double. */ +double fix2double(int32_t val, uint8_t frac_bits); + +/* Find first set bit in word. */ +uint32_t find_first_set_bit(uint32_t word); +/* Find last set bit in word. */ +uint32_t find_last_set_bit(uint32_t word); +/* Locate the closest element in an array. */ +uint32_t find_closest(int32_t val, + const int32_t *array, + uint32_t size); +/* Shift the value and apply the specified mask. */ +uint32_t field_prep(uint32_t mask, uint32_t val); +/* Get a field specified by a mask from a word. */ +uint32_t field_get(uint32_t mask, uint32_t word); +/* Log base 2 of the given number. */ +int32_t log_base_2(uint32_t x); +/* Find greatest common divisor of the given two numbers. */ +uint32_t greatest_common_divisor(uint32_t a, + uint32_t b); +/* Calculate best rational approximation for a given fraction. */ +void rational_best_approximation(uint32_t given_numerator, + uint32_t given_denominator, + uint32_t max_numerator, + uint32_t max_denominator, + uint32_t *best_numerator, + uint32_t *best_denominator); +/* Calculate the number of set bits. */ +uint32_t hweight8(uint32_t word); +/* Calculate the quotient and the remainder of an integer division. */ +uint64_t do_div(uint64_t* n, + uint64_t base); +/* Unsigned 64bit divide with 64bit divisor and remainder */ +uint64_t div64_u64_rem(uint64_t dividend, uint64_t divisor, + uint64_t *remainder); +/* Unsigned 64bit divide with 32bit divisor with remainder */ +uint64_t div_u64_rem(uint64_t dividend, uint32_t divisor, uint32_t *remainder); +int64_t div_s64_rem(int64_t dividend, int32_t divisor, int32_t *remainder); +/* Unsigned 64bit divide with 32bit divisor */ +uint64_t div_u64(uint64_t dividend, uint32_t divisor); +int64_t div_s64(int64_t dividend, int32_t divisor); +/* Converts from string to int32_t */ +int32_t str_to_int32(const char *str); +/* Converts from string to uint32_t */ +uint32_t srt_to_uint32(const char *str); + +int crc16_gen(uint8_t* buffPtr, uint32_t dataLen, uint16_t poly, uint16_t* crcVal); +bool crc16_check(uint8_t* buffPtr, uint32_t dataLen, uint32_t crcOffset, uint16_t poly); +int crc8_gen(uint8_t* buffPtr, uint32_t dataLen, uint16_t poly, uint8_t* crcVal); +bool crc8_check(uint8_t* buffPtr, uint32_t dataLen, uint32_t crcOffset, uint16_t poly); +#endif // UTIL_H_ + diff --git a/datalink814_ge/unit_test/Makefile b/datalink814_ge/unit_test/Makefile new file mode 100644 index 0000000..7248181 --- /dev/null +++ b/datalink814_ge/unit_test/Makefile @@ -0,0 +1,78 @@ + +PMD_HOME ?= /home/gatsby/Software/pmd-bin-6.0.1 +OCLINT_HOME ?= /home/gatsby/Software/oclint-0.13.1 + +# Source files +COMMON_SRC := ../src/error.h ../src/common.h ../src/common.c +TEST_FRAME := ../../unit_test_framework.h +UTIL_SRC := $(wildcard ../src/util/*.c ../src/util/*.h) +TMC_SRC := $(wildcard ../src/time_ctrl/*.c ../src/time_ctrl/*.h) +PHY_SRC := $(wildcard ../src/phy_ctrl/*.c ../src/phy_ctrl/*.h) +GEOMETRY_SRC := $(wildcard ../src/linklayer/geometry/*.c ../src/linklayer/geometry/*.h) +LINK_SRC := $(wildcard ../src/linklayer/*.c ../src/linklayer/*.h) +BIARRAY_SRC := $(wildcard ../src/bit_array/*.c ../src/bit_array/*.h) + +# Compiler +CC ?= gcc + +# Compiler flags +CFLAGS ?= --std=c11 -O0 -I../src -Wall -Werror -pedantic -g -Wno-sign-compare -Wno-comment + +# Add sanitizer flags for identifying undefined behavior. The flags are +# different on macOS (AKA Darwin) and Windows/WSL/Linux. +UNAME := $(shell uname -s) +ifeq "$(UNAME)" "Darwin" + CFLAGS += -fsanitize=address -fsanitize=undefined +else + CFLAGS += -m32 -fsanitize=address -fsanitize=undefined -D_GLIBCC_DEBUG +endif + +tmc_board_unit_test: tmc_board_unit_test.c $(TMC_SRC) $(UTIL_SRC) $(COMMON_SRC) $(TEST_FRAME) + $(CC) $(CFLAGS) $(filter %.c, $^) -o $@ + +tmc_emulate_unit_test: tmc_emulate_unit_test.c $(TMC_SRC) $(UTIL_SRC) $(COMMON_SRC) $(TEST_FRAME) + $(CC) $(CFLAGS) -DEMULATION $(filter %.c, $^) -o $@ + +linklayer_emulate_unit_test: linklayer_emulate_unit_test.c \ + $(LINK_SRC) \ + $(BIARRAY_SRC) \ + $(GEOMETRY_SRC) \ + $(PHY_SRC) \ + $(TMC_SRC) \ + $(UTIL_SRC) \ + $(COMMON_SRC) \ + $(TEST_FRAME) + $(CC) $(CFLAGS) -lm -DEMULATION $(filter %.c, $^) -o $@ +clean: + rm -f *_unit_test + +# Style check +CPD ?= $(PMD_HOME)/bin/run.sh cpd +OCLINT ?= $(OCLINT_HOME)/bin/oclint +FILES := $(SRCS) +CPD_FILES := $(SRCS) +style : + $(OCLINT) \ + -no-analytics \ + -rule=LongLine \ + -rule=HighNcssMethod \ + -rule=DeepNestedBlock \ + -rule=TooManyParameters \ + -rc=LONG_LINE=80 \ + -rc=NCSS_METHOD=1000 \ + -rc=NESTED_BLOCK_DEPTH=4 \ + -rc=TOO_MANY_PARAMETERS=4 \ + -max-priority-1 0 \ + -max-priority-2 0 \ + -max-priority-3 0 \ + $(FILES) \ + -- -xc++ --std=c99 + $(CPD) \ + --minimum-tokens 100 \ + --language c \ + --failOnViolation true \ + --files $(CPD_FILES) + @echo "########################################" + @echo "Style checks PASS" + +.PHONY: clean test \ No newline at end of file diff --git a/datalink814_ge/unit_test/linklayer_emulate_unit_test b/datalink814_ge/unit_test/linklayer_emulate_unit_test new file mode 100755 index 0000000..8221619 Binary files /dev/null and b/datalink814_ge/unit_test/linklayer_emulate_unit_test differ diff --git a/datalink814_ge/unit_test/linklayer_emulate_unit_test.c b/datalink814_ge/unit_test/linklayer_emulate_unit_test.c new file mode 100644 index 0000000..a35ee5c --- /dev/null +++ b/datalink814_ge/unit_test/linklayer_emulate_unit_test.c @@ -0,0 +1,369 @@ +#include +#include +#include "error.h" +#include "unit_test_framework.h" +#include "time_ctrl/time_ctrl.h" +#include "phy_ctrl/phy_ctrl.h" +#include "linklayer/linklayer814.h" +#include "linklayer/msg_def.h" + +#define TIME_INT_REG (0x00000008>>2) +#define TIME_FRAC_REG (0x0000000C>>2) +#define TIME_ADJ_INT (0x0000001C>>2) +#define TIME_ADJ_FRAC (0x00000020>>2) +#define TIME_ADJ_TRIG (0x00000024>>2) +#define CNTSTEP_OPT (0x00000028>>2) + +TIMECTRL_INST* tmcInstPtr = NULL; +PHY_INST* phyInstPtr = NULL; +L2_INST* linkInstPtr = NULL; + +uint32_t tmcReg[32] = {0}; +uint32_t phycReg[512] = {0}; + +uint8_t bmTemplate[INTRA_BM_FRAME_LENGTH_MAX] __attribute__ ((aligned (8))) = { + 0x08, 0x21, 0x04, 0x06, 0x00, 0xF3, 0xA8, 0xCB, + 0x00, 0xA0, 0x49, 0x00, 0x9A, 0x04, 0x13, 0x1E, + 0x45, 0xE7, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA +}; +uint8_t w2acqTemplate[INTRA_W2ACQ_FRAME_LENGTH_MAX] __attribute__ ((aligned (8))) = { + 0xCC, 0x71, 0x21, 0xA8, 0x0A, 0x00, 0x00, 0x00, + 0x00, 0x1A, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, + 0xF0, 0xF0, 0x2A, 0x0F, 0x0F, 0xF0, 0x0F, 0x00, + 0xFF, 0x00, 0xAA, 0x3A, 0xFF, 0x00, 0xFF, 0x00, + 0x00, 0xFF, 0x00, 0xFF, 0x4A, 0xB2, 0xBA, 0xF0, + 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0x5A, 0x0F, 0x0F, + 0x0F, 0x0F, 0x0F, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA +}; +uint8_t mgmtTemplate[INTRA_MGMT_FRAME_LENGTH_MAX] __attribute__ ((aligned (8))) = { + 0xCC, 0xC3, 0x99, 0x99, 0x83, 0x99, 0x99, 0x99, + 0x99, 0xA5, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xBA, + 0xBB, 0x9B, 0x19, 0xCC, 0xCC, 0xDD, 0xDD, 0xEE, + 0xEE, 0xEE, 0x99, 0x29, 0xAA, 0xAA, 0xAA, 0xAA, + 0xBB, 0xBB, 0xBB, 0xBB, 0x39, 0x21, 0x98, 0xBB, + 0xBB, 0xCC, 0xCC, 0xDD, 0xDD, 0x99, 0x99, 0x99, + 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +uint8_t rttReqTemplate[INTRA_RTT_FRAME_LENGTH_MAX] __attribute__ ((aligned (8))) = { + 0xDC, 0xA3, 0x10, 0x44, 0x98, 0x99, 0x99, 0x99, + 0x99, 0x05, 0x00, 0x00, 0x00, 0x50, 0x32, 0x01, + 0x00, 0x90, 0x99, 0xFF, 0xFF, 0xFF, 0x99, 0x99, + 0x99, 0x99, 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +uint8_t rttRspTemplate[INTRA_RTT_FRAME_LENGTH_MAX] __attribute__ ((aligned (8))) = { + 0 +}; +uint8_t svcTemplate[INTRA_SVC_FRAME_LENGTH_MAX] __attribute__ ((aligned (8))) = { + 0xF0, 0xFF, 0x00, 0x21, 0x88, 0x00, 0x00, 0xF0, + 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0x56, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x21, 0xE6, 0x00, 0x21, 0x88, 0x00, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + + +L2_CONFIG l2Config = { + .myType = HEAD_NODE, + .isInterHead = false, + .myId = 1, + .clustId = 1, + .headId = 1, + .bkpHeadId = 1, + .netScale = 2, + .phyInstPtr = NULL, + .tmcInstPtr = NULL +}; + +PHY_CONFIG l1Config = { + .devId = 0, + .txBramId = 0, + .rxBramId = 0, + .antBramId = 0, + .baseAddr = (uintptr_t)phycReg +}; + +TIMECTRL_CONFIG tmcConfig = { + .baseAddr = (uintptr_t)tmcReg, + .reset = 10 +}; + +void linklayer_setup(void){ + int32_t Status; + Status = TimeCtrl_Init(&tmcInstPtr, &tmcConfig); + ASSERT_EQUAL(SUCCESS, Status); + Status = Phy_InstInit(&phyInstPtr, &l1Config); + ASSERT_EQUAL(SUCCESS, Status); + + // Update l2 config + l2Config.phyInstPtr = phyInstPtr; + l2Config.tmcInstPtr = tmcInstPtr; + + Status = Linklayer_Init(&linkInstPtr, &l2Config); + ASSERT_EQUAL(SUCCESS, Status); +} + +void linklayer_teardown(void){ + Linklayer_Destroy(linkInstPtr); + Phy_Destroy(phyInstPtr); + TimeCtrl_Destroy(tmcInstPtr); +} + +void forge_bm_frame(uint16_t nodeId, uint16_t clustId, uint16_t headId, uint64_t time) { + BIT_ARRAY bitarr = { + .words = (uint64_t*)bmTemplate, + .num_of_bits = INTRA_BM_FRAME_LENGTH_MAX*8, + .num_of_words = roundup_bits2words64(INTRA_BM_FRAME_LENGTH_MAX*8), + .capacity_in_words = roundup_bits2words64(INTRA_BM_FRAME_LENGTH_MAX*8), + }; + uint64_t dataChunk; + dataChunk = (nodeId & 0x001F) | ((clustId & 0x001F) << 5); + FrameInsertChunk(&bitarr, BM_MSG_SRC_ADDR_OFFSET, BM_MSG_SRC_ADDR_LEN, dataChunk); + + /* net management node id */ + dataChunk = (headId & 0x001F) | ((clustId & 0x001F) << 5); + FrameInsertChunk(&bitarr, BM_MSG_NETMG_ADDR_OFFSET, BM_MSG_NETMG_ADDR_LEN, dataChunk); + + /* time unit number */ + dataChunk = time / L2_SLOTS_PER_FRAME; + FrameInsertChunk(&bitarr, BM_MSG_TUNIT_NUM_OFFSET, BM_MSG_TUNIT_NUM_LEN, dataChunk); + + /* frame number */ + dataChunk = (time % L2_SLOTS_PER_FRAME) / L2_SLOTS_PER_SUBFRAME; + FrameInsertChunk(&bitarr, BM_MSG_TFRAME_NUM_OFFSET, BM_MSG_TFRAME_NUM_LEN, dataChunk); + + /* mini slot number, 20 mini slots per frame. */ + dataChunk = time % L2_SLOTS_PER_SUBFRAME; + FrameInsertChunk(&bitarr, BM_MSG_TSLOT_NUM_OFFSET, BM_MSG_TSLOT_NUM_LEN, dataChunk); + + // Append CRC + L2_CrcAppend(bmTemplate, BM_MSG_CRC_OFFSET / 8, BM_MSG_CRC_OFFSET / 8, L2_CRC8_31); +} + +void forge_w2acq_frame(L2_NODE_TYPE nodeType, uint16_t srcId, uint16_t destId, + uint16_t clustId, uint32_t netStartTime, L2_NODE_STATE state) { + BIT_ARRAY bitarr = { + .words = (uint64_t*)w2acqTemplate, + .num_of_bits = INTRA_W2ACQ_FRAME_LENGTH_MAX*8, + .num_of_words = roundup_bits2words64(INTRA_W2ACQ_FRAME_LENGTH_MAX*8), + .capacity_in_words = roundup_bits2words64(INTRA_W2ACQ_FRAME_LENGTH_MAX*8), + }; + uint64_t dataChunk; + /* message type */ + dataChunk = (nodeType == HEAD_NODE) ? 0 : 1; + FrameInsertChunk(&bitarr, NS_MSG_INI_TYPE_OFFSET, NS_MSG_INI_TYPE_LEN, dataChunk); + + /* source node id */ + dataChunk = (srcId & 0x001F) | ((clustId & 0x001F) << 5); + FrameInsertChunk(&bitarr, NS_MSG_INI_SRC_ADDR_OFFSET, NS_MSG_INI_SRC_ADDR_LEN, dataChunk); + + /* destination node id */ + dataChunk = (destId & 0x001F) | ((clustId & 0x001F) << 5); + FrameInsertChunk(&bitarr, NS_MSG_INI_LEN_OFFSET, NS_MSG_INI_LEN_LEN, dataChunk); + /* current net stage */ + switch (state) { + case INIT_STATE: + dataChunk = NET_INI_STAGE; + break; + case SEEK_STATE: + dataChunk = NET_INTER_SEEK_STAGE; + break; + case NORMAL_STATE: + dataChunk = NET_NORMAL_STAGE; + break; + default: + dataChunk = NET_ERROR_STAGE; + break; + } + FrameInsertChunk(&bitarr, NS_MSG_INI_NET_STAGE_OFFSET, NS_MSG_INI_NET_STAGE_LEN, dataChunk); + + // Begin Scan Time Word + dataChunk = netStartTime; + FrameInsertChunk(&bitarr, NS_MSG_INI_SCAN_TIME_OFFSET, NS_MSG_INI_SCAN_TIME_LEN, dataChunk); + + // Update CRC + L2_CrcAppend(w2acqTemplate, W2ACQ_FRAME_CRC_DLEN, W2ACQ_FRAME_CRC_POS, L2_CRC16_8005); +} + +void forge_mgmt_frame(L2_NODE_STATE state) { + BIT_ARRAY bitarr = { + .words = (uint64_t*)mgmtTemplate, + .num_of_bits = INTRA_MGMT_FRAME_LENGTH_MAX*8, + .num_of_words = roundup_bits2words64(INTRA_MGMT_FRAME_LENGTH_MAX*8), + .capacity_in_words = roundup_bits2words64(INTRA_MGMT_FRAME_LENGTH_MAX*8), + }; + uint64_t dataChunk; + switch (state) { + case INIT_STATE: + dataChunk = NET_INI_STAGE; + break; + case NORMAL_STATE: + dataChunk = NET_NORMAL_STAGE; + break; + case INTRA_SEEK_STATE: + dataChunk = NET_INTRA_SEEK_STAGE; + break; + case INTER_SEEK_STATE: + dataChunk = NET_INTER_SEEK_STAGE; + break; + case SEEK_STATE: + dataChunk = NET_SEEK_STAGE; + break; + default: + dataChunk = NET_ERROR_STAGE; + break; + FrameInsertChunk(&bitarr, TK_MSG_INI_NET_STATE_OFFSET, TK_MSG_INI_NET_STATE_LEN, dataChunk); + } +} + +void forge_rtt_frame(L2_INST* instPtr) { + return; +} + +TEST(linklayer_master_routine) { + int32_t Status; + Linklayer_Start(linkInstPtr); + // 30 seconds + for(int i = 0; i < 200*30; i++) { + tmcReg[TIME_INT_REG]++; + + if(phyInstPtr->TOR.last == PHY_TOR_RX && linkInstPtr->frame.last == L2_INTRA_W2_ACQ_FRAME) + + Phy_UpdateState(phyInstPtr); + + Status = Linklayer_Proc(linkInstPtr); + + if(tmcReg[TIME_INT_REG]/200 < linkInstPtr->netStartTime) { + ASSERT_EQUAL(EIGNORE, Status); + } + else{ + ASSERT_EQUAL(SUCCESS, Status); + } + } +} + + +TEST(linklayer_reconfig) { + int32_t Status; + Status = Linklayer_Reconfig(linkInstPtr, &l2Config); + ASSERT_EQUAL(SUCCESS, Status); +} + +TEST_SUITE(linklayer_unit_test) { + TEST_SUITE_CONFIGURE(linklayer_setup, linklayer_teardown); + RUN_TEST(linklayer_master_routine); + RUN_TEST(linklayer_reconfig); +} + +int main(void) { + RUN_TEST_SUITE(linklayer_unit_test); + TEST_REPORT(); + return TEST_EXIT_CODE; +} + + diff --git a/datalink814_ge/unit_test/tmc_board_unit_test.c b/datalink814_ge/unit_test/tmc_board_unit_test.c new file mode 100644 index 0000000..4288df2 --- /dev/null +++ b/datalink814_ge/unit_test/tmc_board_unit_test.c @@ -0,0 +1,137 @@ +#include +#include +#include "error.h" +#include "unit_test_framework.h" +#include "time_ctrl/time_ctrl.h" + +#define HARDWARE_VERSION 0x00000001 +#define MAX_OPT_DELAY 100 // 1us = 100*10ns + + +TIMECTRL_CONFIG tmcConfig = { + .baseAddr = 0/*TODO: fill withe real base address*/, + .reset = 10 +}; + +TIMECTRL_INST* tmcInstPtr = NULL; + +void tmc_setup(void){ + int32_t Status; + Status = TimeCtrl_Init(&tmcInstPtr, &tmcConfig); + ASSERT_TRUE(SUCCESS == Status); +} + +void tmc_teardown(void){ + TimeCtrl_Destroy(tmcInstPtr); +} + +TEST(tmc_version) { + ASSERT_EQUAL(HARDWARE_VERSION, TimeCtrl_GetVersion(tmcInstPtr)); + return; +} + +TEST(tmc_read_time) { + TIME_WORD timeStamp; + TIME_INT timeH; + TIME_FRAC timeL; + + // Test time stamp read operation + TimeCtrl_GetCurrentTime(tmcInstPtr, &timeStamp); + timeH = TimeCtrl_GetIntCnt(tmcInstPtr); + timeL = TimeCtrl_GetFracCnt(tmcInstPtr); + if(timeL >= timeStamp.frac_part) { + ASSERT_EQUAL(timeH, timeStamp.int_part); + ASSERT_TRUE(timeL - timeStamp.frac_part < MAX_OPT_DELAY); + } + else { + ASSERT_EQUAL(timeH, timeStamp.int_part+1); + ASSERT_TRUE(timeL + COUNTE_FRAC_MAX - timeStamp.frac_part < MAX_OPT_DELAY); + } +} + +TEST(tmc_reset) { + TIME_WORD timeStamp; + + TimeCtrl_Reset(tmcInstPtr); + TimeCtrl_GetCurrentTime(tmcInstPtr, &timeStamp); + ASSERT_EQUAL(0, timeStamp.int_part); + ASSERT_TRUE(timeStamp.frac_part < MAX_OPT_DELAY); +} + +TEST(tmc_adjustment) { + TIME_WORD timeStampPre, timeStampPost, timeAdj; + + // Adjustment -- set + timeAdj.frac_part = 0; + timeAdj.int_part = 0x00000203; + TimeCtrl_TimeAdjust(tmcInstPtr, &timeAdj, TM_ADJ_SET); + TimeCtrl_GetCurrentTime(tmcInstPtr, &timeStampPost); + ASSERT_EQUAL(timeAdj.int_part, timeStampPost.int_part); + ASSERT_TRUE(timeStampPost.frac_part < MAX_OPT_DELAY); + + timeAdj.frac_part = COUNTE_FRAC_MAX; + timeAdj.int_part = 0x00000203; + TimeCtrl_TimeAdjust(tmcInstPtr, &timeAdj, TM_ADJ_SET); + TimeCtrl_GetCurrentTime(tmcInstPtr, &timeStampPost); + ASSERT_EQUAL(timeAdj.int_part, timeStampPost.int_part+1); + ASSERT_TRUE(timeStampPost.frac_part < MAX_OPT_DELAY); + + timeAdj.frac_part = COUNTE_FRAC_MAX*2; + timeAdj.int_part = 0x00000203; + TimeCtrl_GetCurrentTime(tmcInstPtr, &timeStampPre); + TimeCtrl_TimeAdjust(tmcInstPtr, &timeAdj, TM_ADJ_SET); + TimeCtrl_GetCurrentTime(tmcInstPtr, &timeStampPost); + if(timeStampPost.frac_part >= timeStampPre.frac_part) { + ASSERT_EQUAL(timeStampPost.int_part, timeStampPre.int_part); + ASSERT_TRUE(timeStampPost.frac_part - timeStampPre.frac_part < MAX_OPT_DELAY); + } + else { + ASSERT_EQUAL(timeStampPost.int_part, timeStampPre.int_part + 1); + ASSERT_TRUE(timeStampPost.frac_part + COUNTE_FRAC_MAX - timeStampPre.frac_part < MAX_OPT_DELAY); + } + + // Adjustment -- add + timeAdj.frac_part = 253; + timeAdj.int_part = 253; + TimeCtrl_GetCurrentTime(tmcInstPtr, &timeStampPre); + TimeCtrl_TimeAdjust(tmcInstPtr, &timeAdj, TM_ADJ_ADD); + TimeCtrl_GetCurrentTime(tmcInstPtr, &timeStampPost); + if(timeStampPre.frac_part + timeAdj.frac_part > COUNTE_FRAC_MAX) { + ASSERT_TRUE(timeStampPost.int_part <= timeStampPre.int_part + timeAdj.int_part + 2); + ASSERT_TRUE(timeStampPost.frac_part + COUNTE_FRAC_MAX - timeStampPre.frac_part + < MAX_OPT_DELAY + timeAdj.frac_part); + } + + timeAdj.frac_part = -253; + timeAdj.int_part = -253; + TimeCtrl_GetCurrentTime(tmcInstPtr, &timeStampPre); + TimeCtrl_TimeAdjust(tmcInstPtr, &timeAdj, TM_ADJ_ADD); + TimeCtrl_GetCurrentTime(tmcInstPtr, &timeStampPost); + if(timeStampPre.frac_part + timeAdj.frac_part > COUNTE_FRAC_MAX) { + ASSERT_TRUE(timeStampPost.int_part <= timeStampPre.int_part + timeAdj.int_part + 2); + ASSERT_TRUE(timeStampPost.frac_part + COUNTE_FRAC_MAX - timeStampPre.frac_part + < MAX_OPT_DELAY + timeAdj.frac_part); + } +} + +TEST(tmc_setopt) { + // TODO: + return; +} + +TEST_SUITE(tmc_unit_test) { + TEST_SUITE_CONFIGURE(tmc_setup, tmc_teardown); + RUN_TEST(tmc_version); + RUN_TEST(tmc_read_time); + RUN_TEST(tmc_reset); + RUN_TEST(tmc_adjustment); + RUN_TEST(tmc_setopt); +} + +int main(void) { + RUN_TEST_SUITE(tmc_unit_test); + TEST_REPORT(); + return TEST_EXIT_CODE; +} + + diff --git a/datalink814_ge/unit_test/tmc_emulate_unit_test.c b/datalink814_ge/unit_test/tmc_emulate_unit_test.c new file mode 100644 index 0000000..dface93 --- /dev/null +++ b/datalink814_ge/unit_test/tmc_emulate_unit_test.c @@ -0,0 +1,84 @@ +#include +#include +#include "error.h" +#include "unit_test_framework.h" +#include "time_ctrl/time_ctrl.h" + +#define HARDWARE_VERSION 0x00000001 +#define TIMER_H 0x00253253 +#define TIMER_L 0x00225533 +#define MAX_OPT_DELAY 100 // 1us = 100*10ns + +uint32_t tmcReg[32] = {0}; + +TIMECTRL_CONFIG tmcConfig = { + .baseAddr = 0, + .reset = 10 +}; + +TIMECTRL_INST* tmcInstPtr = NULL; + +void tmc_setup(void){ + int32_t Status; + tmcReg[1] = HARDWARE_VERSION; // Version + tmcReg[2] = 253; // Int + tmcReg[3] = 253; // Frac + tmcReg[4] = 0; // Reset + tmcReg[5] = 0; // Preset H + tmcReg[6] = 0; // Preset L + tmcReg[7] = 0; // Adjustment H + tmcReg[8] = 0; // Adjustment L + tmcReg[9] = 0; // Adjustment Trigger + tmcReg[10] = 0; // step opt + tmcConfig.baseAddr = (uintptr_t)tmcReg; + Status = TimeCtrl_Init(&tmcInstPtr, &tmcConfig); + ASSERT_EQUAL(SUCCESS, Status); +} + +void tmc_teardown(void){ + TimeCtrl_Destroy(tmcInstPtr); +} + +TEST(tmc_version) { + ASSERT_EQUAL(HARDWARE_VERSION, TimeCtrl_GetVersion(tmcInstPtr)); + return; +} + +TEST(tmc_basic_operations) { + TIME_WORD timeStamp; + TIME_INT timeH; + TIME_FRAC timeL; + TimeCtrl_GetCurrentTime(tmcInstPtr, &timeStamp); + timeH = TimeCtrl_GetIntCnt(tmcInstPtr); + timeL = TimeCtrl_GetFracCnt(tmcInstPtr); + if(timeL >= timeStamp.frac_part) { + ASSERT_EQUAL(timeH, timeStamp.int_part); + ASSERT_TRUE(timeL - timeStamp.frac_part < MAX_OPT_DELAY); + } + else { + ASSERT_EQUAL(timeH, timeStamp.int_part+1); + ASSERT_TRUE(timeL + COUNTE_FRAC_MAX - timeStamp.frac_part < MAX_OPT_DELAY); + } + + TIME_FRAC stepOpt; + stepOpt = 0x00000253; + TimeCtrl_SetOptimizeStep(tmcInstPtr, &stepOpt); + TimeCtrl_GetCurrentStep(tmcInstPtr, &stepOpt); + ASSERT_EQUAL(0x00000253, stepOpt); + TimeCtrl_Reset(tmcInstPtr); + return; +} + +TEST_SUITE(tmc_unit_test) { + TEST_SUITE_CONFIGURE(tmc_setup, tmc_teardown); + RUN_TEST(tmc_version); + RUN_TEST(tmc_basic_operations); +} + +int main(void) { + RUN_TEST_SUITE(tmc_unit_test); + TEST_REPORT(); + return TEST_EXIT_CODE; +} + + diff --git a/datalink814_ge/unit_test/unit_test_framework.h b/datalink814_ge/unit_test/unit_test_framework.h new file mode 120000 index 0000000..f5fd5de --- /dev/null +++ b/datalink814_ge/unit_test/unit_test_framework.h @@ -0,0 +1 @@ +../../unit_test_framework.h \ No newline at end of file diff --git a/datalink814_sp/bsp/Makefile b/datalink814_sp/bsp/Makefile new file mode 100644 index 0000000..4573c01 --- /dev/null +++ b/datalink814_sp/bsp/Makefile @@ -0,0 +1,35 @@ +# Makefile generated by Xilinx. + +PROCESSOR = microblaze_ps +LIBRARIES = ${PROCESSOR}/lib/libxil.a +BSP_MAKEFILES := $(wildcard $(PROCESSOR)/libsrc/*/src/Makefile) +SUBDIRS := $(patsubst %/Makefile, %, $(BSP_MAKEFILES)) + +ifneq (,$(findstring win,$(RDI_PLATFORM))) + SHELL = CMD +endif + +all: libs + @echo 'Finished building libraries' + +include: $(addsuffix /make.include,$(SUBDIRS)) + +libs: $(addsuffix /make.libs,$(SUBDIRS)) + +clean: $(addsuffix /make.clean,$(SUBDIRS)) + +$(PROCESSOR)/lib/libxil.a: $(PROCESSOR)/lib/libxil_init.a + cp -f $< $@ + +%/make.include: $(if $(wildcard $(PROCESSOR)/lib/libxil_init.a),$(PROCESSOR)/lib/libxil.a,) + @echo "Running Make include in $(subst /make.include,,$@)" + $(MAKE) -C $(subst /make.include,,$@) -s include "SHELL=$(SHELL)" "COMPILER=$(CC)" "ARCHIVER=mb-ar" "COMPILER_FLAGS= -O2 -c -mcpu=v11.0 -mlittle-endian -mno-xl-soft-div -mno-xl-soft-mul -mxl-barrel-shift -mxl-pattern-compare" "EXTRA_COMPILER_FLAGS=-ffunction-sections -fdata-sections -Wall -Wextra" + +%/make.libs: include + @echo "Running Make libs in $(subst /make.libs,,$@)" + $(MAKE) -C $(subst /make.libs,,$@) -s libs "SHELL=$(SHELL)" "COMPILER=$(CC)" "ARCHIVER=mb-ar" "COMPILER_FLAGS= -O2 -c -mcpu=v11.0 -mlittle-endian -mno-xl-soft-div -mno-xl-soft-mul -mxl-barrel-shift -mxl-pattern-compare" "EXTRA_COMPILER_FLAGS=-ffunction-sections -fdata-sections -Wall -Wextra" + +%/make.clean: + $(MAKE) -C $(subst /make.clean,,$@) -s clean +clean: + rm -f ${PROCESSOR}/lib/libxil.a diff --git a/datalink814_sp/bsp/microblaze_ps/include/_profile_timer_hw.h b/datalink814_sp/bsp/microblaze_ps/include/_profile_timer_hw.h new file mode 100644 index 0000000..1647600 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/include/_profile_timer_hw.h @@ -0,0 +1,308 @@ +/****************************************************************************** +* +* Copyright (C) 2004 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +****************************************************************************** +* +* _program_timer_hw.h: +* Timer related functions +* +******************************************************************************/ + +#ifndef PROFILE_TIMER_HW_H +#define PROFILE_TIMER_HW_H + +#include "profile.h" + +#ifdef PROC_PPC +#if defined __GNUC__ +# define SYNCHRONIZE_IO __asm__ volatile ("eieio") +#elif defined __DCC__ +# define SYNCHRONIZE_IO __asm volatile(" eieio") +#else +# define SYNCHRONIZE_IO +#endif +#endif + +#ifdef PROC_PPC +#define ProfIo_In32(InputPtr) { (*(volatile u32 *)(InputPtr)); SYNCHRONIZE_IO; } +#define ProfIo_Out32(OutputPtr, Value) { (*(volatile u32 *)(OutputPtr) = Value); SYNCHRONIZE_IO; } +#else +#define ProfIo_In32(InputPtr) (*(volatile u32 *)(InputPtr)); +#define ProfIo_Out32(OutputPtr, Value) { (*(volatile u32 *)(OutputPtr) = (Value)); } +#endif + +#define ProfTmrCtr_mWriteReg(BaseAddress, TmrCtrNumber, RegOffset, ValueToWrite)\ + ProfIo_Out32(((u32)(BaseAddress) + (u32)XTmrCtr_Offsets[(TmrCtrNumber)] + \ + (u32)(RegOffset)), (u32)(ValueToWrite)) + +#define ProfTimerCtr_mReadReg(BaseAddress, TmrCtrNumber, RegOffset) \ + ProfIo_In32((u32)(BaseAddress) + (u32)XTmrCtr_Offsets[(TmrCtrNumber)] + (u32)(RegOffset)) + +#define ProfTmrCtr_mSetControlStatusReg(BaseAddress, TmrCtrNumber, RegisterValue)\ + ProfTmrCtr_mWriteReg((BaseAddress), (TmrCtrNumber), XTC_TCSR_OFFSET, \ + (RegisterValue)) + +#define ProfTmrCtr_mGetControlStatusReg(BaseAddress, TmrCtrNumber) \ + ProfTimerCtr_mReadReg((u32)(BaseAddress), (TmrCtrNumber), XTC_TCSR_OFFSET) + + + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef PROC_PPC +#include "xexception_l.h" +#include "xtime_l.h" +#include "xpseudo_asm.h" +#endif + +#ifdef TIMER_CONNECT_INTC +#include "xintc_l.h" +#include "xintc.h" +#endif /* TIMER_CONNECT_INTC */ + +#if (!defined PPC_PIT_INTERRUPT && !defined PROC_CORTEXA9) +#include "xtmrctr_l.h" +#endif + +#ifdef PROC_CORTEXA9 +#include "xscutimer_hw.h" +#include "xscugic.h" +#endif + +extern u32 timer_clk_ticks ; + +/*-------------------------------------------------------------------- + * PowerPC Target - Timer related functions + *-------------------------------------------------------------------- */ +#ifdef PROC_PPC + +#ifdef PPC_PIT_INTERRUPT +u32 timer_lo_clk_ticks ; /* Clk ticks when Timer is disabled in CG */ +#endif + +#ifdef PROC_PPC440 +#define XREG_TCR_PIT_INTERRUPT_ENABLE XREG_TCR_DEC_INTERRUPT_ENABLE +#define XREG_TSR_PIT_INTERRUPT_STATUS XREG_TSR_DEC_INTERRUPT_STATUS +#define XREG_SPR_PIT XREG_SPR_DEC +#define XEXC_ID_PIT_INT XEXC_ID_DEC_INT +#endif + +/* -------------------------------------------------------------------- + * Disable the Timer - During Profiling + * + * For PIT Timer - + * 1. XTime_PITDisableInterrupt() ; + * 2. Store the remaining timer clk tick + * 3. Stop the PIT Timer + *-------------------------------------------------------------------- */ + +#ifdef PPC_PIT_INTERRUPT +#define disable_timer() \ + { \ + u32 val; \ + val=mfspr(XREG_SPR_TCR); \ + mtspr(XREG_SPR_TCR, val & (~XREG_TCR_PIT_INTERRUPT_ENABLE)); \ + timer_lo_clk_ticks = mfspr(XREG_SPR_PIT); \ + mtspr(XREG_SPR_PIT, 0); \ + } +#else +#define disable_timer() \ + { \ + u32 addr = (PROFILE_TIMER_BASEADDR) + XTmrCtr_Offsets[(0)] + XTC_TCSR_OFFSET; \ + u32 tmp_v = ProfIo_In32(addr); \ + tmp_v = tmp_v & (~XTC_CSR_ENABLE_TMR_MASK); \ + ProfIo_Out32((PROFILE_TIMER_BASEADDR) + XTmrCtr_Offsets[(0)] + XTC_TCSR_OFFSET, tmp_v); \ + } +#endif + + + +/* -------------------------------------------------------------------- + * Enable the Timer + * + * For PIT Timer - + * 1. Load the remaining timer clk ticks + * 2. XTime_PITEnableInterrupt() ; + *-------------------------------------------------------------------- */ +#ifdef PPC_PIT_INTERRUPT +#define enable_timer() \ + { \ + u32 val; \ + val=mfspr(XREG_SPR_TCR); \ + mtspr(XREG_SPR_PIT, timer_lo_clk_ticks); \ + mtspr(XREG_SPR_TCR, val | XREG_TCR_PIT_INTERRUPT_ENABLE); \ + } +#else +#define enable_timer() \ + { \ + u32 addr = (PROFILE_TIMER_BASEADDR) + XTmrCtr_Offsets[(0)] + XTC_TCSR_OFFSET; \ + u32 tmp_v = ProfIo_In32(addr); \ + tmp_v = tmp_v | XTC_CSR_ENABLE_TMR_MASK; \ + ProfIo_Out32((PROFILE_TIMER_BASEADDR) + XTmrCtr_Offsets[(0)] + XTC_TCSR_OFFSET, tmp_v); \ + } +#endif + + + +/* -------------------------------------------------------------------- + * Send Ack to Timer Interrupt + * + * For PIT Timer - + * 1. Load the timer clk ticks + * 2. Enable AutoReload and Interrupt + * 3. Clear PIT Timer Status bits + *-------------------------------------------------------------------- */ +#ifdef PPC_PIT_INTERRUPT +#define timer_ack() \ + { \ + u32 val; \ + mtspr(XREG_SPR_PIT, timer_clk_ticks); \ + mtspr(XREG_SPR_TSR, XREG_TSR_PIT_INTERRUPT_STATUS); \ + val=mfspr(XREG_SPR_TCR); \ + mtspr(XREG_SPR_TCR, val| XREG_TCR_PIT_INTERRUPT_ENABLE| XREG_TCR_AUTORELOAD_ENABLE); \ + } +#else +#define timer_ack() \ + { \ + u32 csr; \ + csr = ProfTmrCtr_mGetControlStatusReg(PROFILE_TIMER_BASEADDR, 0); \ + ProfTmrCtr_mSetControlStatusReg(PROFILE_TIMER_BASEADDR, 0, csr); \ + } +#endif + +/*-------------------------------------------------------------------- */ +#endif /* PROC_PPC */ +/* -------------------------------------------------------------------- */ + + + + +/* -------------------------------------------------------------------- + * MicroBlaze Target - Timer related functions + *-------------------------------------------------------------------- */ +#ifdef PROC_MICROBLAZE + +/* -------------------------------------------------------------------- + * Disable the Timer during Call-Graph Data collection + * + *-------------------------------------------------------------------- */ +#define disable_timer() \ + { \ + u32 Addr = ((u32)PROFILE_TIMER_BASEADDR); \ + Addr += (u32)XTmrCtr_Offsets[(u16)(0)]; \ + Addr += (u32)XTC_TCSR_OFFSET; \ + u32 tmp_v = ProfIo_In32(Addr); \ + tmp_v = tmp_v & (u32)(~XTC_CSR_ENABLE_TMR_MASK); \ + u32 OutAddr = (u32)PROFILE_TIMER_BASEADDR; \ + OutAddr += (u32)XTmrCtr_Offsets[(u16)(0)]; \ + OutAddr += (u32)XTC_TCSR_OFFSET; \ + ProfIo_Out32(OutAddr, (u32)tmp_v); \ + } + + +/* -------------------------------------------------------------------- + * Enable the Timer after Call-Graph Data collection + * + *-------------------------------------------------------------------- */ +#define enable_timer() \ + { \ + u32 Addr = ((u32)PROFILE_TIMER_BASEADDR); \ + Addr += (u32)XTmrCtr_Offsets[(u16)(0)]; \ + Addr += (u32)XTC_TCSR_OFFSET; \ + u32 tmp_v = (u32)ProfIo_In32(Addr); \ + tmp_v = tmp_v | (u32)XTC_CSR_ENABLE_TMR_MASK; \ + ProfIo_Out32((u32)(PROFILE_TIMER_BASEADDR) + (u32)XTmrCtr_Offsets[(u16)(0)] + (u32)XTC_TCSR_OFFSET, (u32)tmp_v); \ + } + + +/* -------------------------------------------------------------------- + * Send Ack to Timer Interrupt + * + *-------------------------------------------------------------------- */ +#define timer_ack() \ + { \ + u32 csr; \ + csr = ProfTmrCtr_mGetControlStatusReg((u32)PROFILE_TIMER_BASEADDR, (u16)0); \ + ProfTmrCtr_mSetControlStatusReg((u32)PROFILE_TIMER_BASEADDR, (u16)0, (u32)csr); \ + } + +/*-------------------------------------------------------------------- */ +#endif /* PROC_MICROBLAZE */ +/*-------------------------------------------------------------------- */ + +/* -------------------------------------------------------------------- + * Cortex A9 Target - Timer related functions + *-------------------------------------------------------------------- */ +#ifdef PROC_CORTEXA9 + +/* -------------------------------------------------------------------- + * Disable the Timer during Call-Graph Data collection + * + *-------------------------------------------------------------------- */ +#define disable_timer() \ +{ \ + u32 Reg; \ + Reg = Xil_In32(PROFILE_TIMER_BASEADDR + XSCUTIMER_CONTROL_OFFSET); \ + Reg &= (~XSCUTIMER_CONTROL_ENABLE_MASK);\ + Xil_Out32(PROFILE_TIMER_BASEADDR + XSCUTIMER_CONTROL_OFFSET, Reg);\ +} + + +/* -------------------------------------------------------------------- + * Enable the Timer after Call-Graph Data collection + * + *-------------------------------------------------------------------- */ +#define enable_timer() \ +{ \ + u32 Reg; \ + Reg = Xil_In32(PROFILE_TIMER_BASEADDR + XSCUTIMER_CONTROL_OFFSET); \ + Reg |= XSCUTIMER_CONTROL_ENABLE_MASK; \ + Xil_Out32(PROFILE_TIMER_BASEADDR + XSCUTIMER_CONTROL_OFFSET, Reg);\ +} + + +/* -------------------------------------------------------------------- + * Send Ack to Timer Interrupt + * + *-------------------------------------------------------------------- */ +#define timer_ack() \ +{ \ + Xil_Out32((u32)PROFILE_TIMER_BASEADDR + (u32)XSCUTIMER_ISR_OFFSET, \ + (u32)XSCUTIMER_ISR_EVENT_FLAG_MASK);\ +} + +/*-------------------------------------------------------------------- */ +#endif /* PROC_CORTEXA9 */ +/*-------------------------------------------------------------------- */ + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/datalink814_sp/bsp/microblaze_ps/include/bspconfig.h b/datalink814_sp/bsp/microblaze_ps/include/bspconfig.h new file mode 100644 index 0000000..dfedab2 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/include/bspconfig.h @@ -0,0 +1,41 @@ + +/******************************************************************* +* +* CAUTION: This file is automatically generated by HSI. +* Version: 2019.1.3 +* DO NOT EDIT. +* +* Copyright (C) 2010-2023 Xilinx, Inc. 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 +*XILINX 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. +* +*Except as contained in this notice, the name of the Xilinx shall not be used +*in advertising or otherwise to promote the sale, use or other dealings in +*this Software without prior written authorization from Xilinx. +* + +* +* Description: Configurations for Standalone BSP +* +*******************************************************************/ + +#ifndef BSPCONFIG_H /* prevent circular inclusions */ +#define BSPCONFIG_H /* by using protection macros */ + +#define MICROBLAZE_PVR_NONE + +#endif /*end of __BSPCONFIG_H_*/ diff --git a/datalink814_sp/bsp/microblaze_ps/include/fsl.h b/datalink814_sp/bsp/microblaze_ps/include/fsl.h new file mode 100644 index 0000000..8291414 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/include/fsl.h @@ -0,0 +1,113 @@ +#ifndef FSL_H +#define FSL_H +/*****************************************************************************/ +/** +* +* @file fsl.h +* +* @addtogroup microblaze_fsl_macro MicroBlaze Processor FSL Macros +* +* Microblaze BSP includes macros to provide convenient access to accelerators +* connected to the MicroBlaze Fast Simplex Link (FSL) Interfaces.To use these functions, +* include the header file fsl.h in your source code +* +* @{ +* +******************************************************************************/ +#include "mb_interface.h" /* Legacy reasons. We just have to include this guy who defines the FSL stuff */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Extended FSL macros. These now replace all of the previous FSL macros */ +#define FSL_DEFAULT +#define FSL_NONBLOCKING n +#define FSL_EXCEPTION e +#define FSL_CONTROL c +#define FSL_ATOMIC a + +#define FSL_NONBLOCKING_EXCEPTION ne +#define FSL_NONBLOCKING_CONTROL nc +#define FSL_NONBLOCKING_ATOMIC na +#define FSL_EXCEPTION_CONTROL ec +#define FSL_EXCEPTION_ATOMIC ea +#define FSL_CONTROL_ATOMIC ca + +#define FSL_NONBLOCKING_EXCEPTION_CONTROL nec +#define FSL_NONBLOCKING_EXCEPTION_ATOMIC nea +#define FSL_NONBLOCKING_CONTROL_ATOMIC nca +#define FSL_EXCEPTION_CONTROL_ATOMIC eca + +#define FSL_NONBLOCKING_EXCEPTION_CONTROL_ATOMIC neca + +/** +Performs a get function on an input FSL of the MicroBlaze processor +@param val variable to sink data from get function +@param id literal in the range of 0 to 7 (0 to 15 for MicroBlaze v7.00.a and later) +@param flags valid FSL macro flags +*/ +#define getfslx(val, id, flags) asm volatile (stringify(flags) "get\t%0,rfsl" stringify(id) : "=d" (val)) + +/** +Performs a put function on an input FSL of the MicroBlaze processor +@param val variable to source data to put function +@param id literal in the range of 0 to 7 (0 to 15 for MicroBlaze v7.00.a and later) +@param flags valid FSL macro flags +*/ +#define putfslx(val, id, flags) asm volatile (stringify(flags) "put\t%0,rfsl" stringify(id) :: "d" (val)) + +/** +Performs a test get function on an input FSL of the MicroBlaze processor +@param val variable to sink data from get function +@param id literal in the range of 0 to 7 (0 to 15 for MicroBlaze v7.00.a and later) +@param flags valid FSL macro flags +*/ +#define tgetfslx(val, id, flags) asm volatile ("t" stringify(flags) "get\t%0,rfsl" stringify(id) : "=d" (val)) + +/** +Performs a put function on an input FSL of the MicroBlaze processor +@param id FSL identifier +@param flags valid FSL macro flags +*/ +#define tputfslx(id, flags) asm volatile ("t" stringify(flags) "put\trfsl" stringify(id)) + +/** +Performs a getd function on an input FSL of the MicroBlaze processor +@param val variable to sink data from getd function +@param var literal in the range of 0 to 7 (0 to 15 for MicroBlaze v7.00.a and later) +@param flags valid FSL macro flags +*/ +#define getdfslx(val, var, flags) asm volatile (stringify(flags) "getd\t%0,%1" : "=d" (val) : "d" (var)) + +/** +Performs a putd function on an input FSL of the MicroBlaze processor +@param val variable to source data to putd function +@param var literal in the range of 0 to 7 (0 to 15 for MicroBlaze v7.00.a and later) +@param flags valid FSL macro flags +*/ +#define putdfslx(val, var, flags) asm volatile (stringify(flags) "putd\t%0,%1" :: "d" (val), "d" (var)) + +/** +Performs a test getd function on an input FSL of the MicroBlaze processor; +@param val variable to sink data from getd function +@param var literal in the range of 0 to 7 (0 to 15 for MicroBlaze v7.00.a and later) +@param flags valid FSL macro flags +*/ +#define tgetdfslx(val, var, flags) asm volatile ("t" stringify(flags) "getd\t%0,%1" : "=d" (val) : "d" (var)) + +/** +Performs a put function on an input FSL of the MicroBlaze processor +@param var FSL identifier +@param flags valid FSL macro flags +*/ +#define tputdfslx(var, flags) asm volatile ("t" stringify(flags) "putd\t%0" :: "d" (var)) + + +#ifdef __cplusplus +} +#endif +#endif /* FSL_H */ +/** +* @} End of "addtogroup microblaze_fsl_macro". +*/ diff --git a/datalink814_sp/bsp/microblaze_ps/include/mb_interface.h b/datalink814_sp/bsp/microblaze_ps/include/mb_interface.h new file mode 100644 index 0000000..fc45555 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/include/mb_interface.h @@ -0,0 +1,470 @@ +/****************************************************************************** +* +* Copyright (C) 2004 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file mb_interface.h +* +* @addtogroup microblaze_pseudo_asm_macro Microblaze Pseudo-asm Macros and Interrupt Handling APIs +* +* Microblaze BSP includes macros to provide convenient access to various registers +* in the MicroBlaze processor. Some of these macros are very useful within +* exception handlers for retrieving information about the exception.Also, +* the interrupt handling functions help manage interrupt handling on MicroBlaze +* processor devices.To use these functions, include the header file +* mb_interface.h in your source code +* +* @{ +* +******************************************************************************/ +#ifndef _MICROBLAZE_INTERFACE_H_ +#define _MICROBLAZE_INTERFACE_H_ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_exception.h" + +#ifdef __cplusplus +extern "C" { +#endif +extern void microblaze_enable_interrupts(void); /* Enable Interrupts */ +extern void microblaze_disable_interrupts(void); /* Disable Interrupts */ +extern void microblaze_enable_icache(void); /* Enable Instruction Cache */ +extern void microblaze_disable_icache(void); /* Disable Instruction Cache */ +extern void microblaze_enable_dcache(void); /* Enable Instruction Cache */ +extern void microblaze_disable_dcache(void); /* Disable Instruction Cache */ +extern void microblaze_enable_exceptions(void); /* Enable hardware exceptions */ +extern void microblaze_disable_exceptions(void); /* Disable hardware exceptions */ +extern void microblaze_register_handler(XInterruptHandler Handler, void *DataPtr); /* Register top level interrupt handler */ +extern void microblaze_register_exception_handler(u32 ExceptionId, Xil_ExceptionHandler Handler, void *DataPtr); /* Register exception handler */ + +extern void microblaze_invalidate_icache(void); /* Invalidate the entire icache */ +extern void microblaze_invalidate_dcache(void); /* Invalidate the entire dcache */ +extern void microblaze_flush_dcache(void); /* Flush the whole dcache */ +extern void microblaze_invalidate_icache_range(UINTPTR cacheaddr, u32 len); /* Invalidate a part of the icache */ +extern void microblaze_invalidate_dcache_range(UINTPTR cacheaddr, u32 len); /* Invalidate a part of the dcache */ +extern void microblaze_flush_dcache_range(UINTPTR cacheaddr, u32 len); /* Flush a part of the dcache */ +extern void microblaze_scrub(void); /* Scrub LMB and internal BRAM */ +extern void microblaze_invalidate_cache_ext(void); /* Invalidate cache ext */ +extern void microblaze_flush_cache_ext(void); /* Flush cache ext */ +extern void microblaze_flush_cache_ext_range(UINTPTR cacheaddr, + u32 len); /* Flush cache ext range */ +extern void microblaze_invalidate_cache_ext_range(UINTPTR cacheaddr, + u32 len); /* Invalidate cache ext range */ + +/* Deprecated */ +extern void microblaze_update_icache (s32 , s32 , s32 ) __attribute__((deprecated)); +extern void microblaze_init_icache_range (s32 , s32 ) __attribute__((deprecated)); +extern void microblaze_update_dcache (s32 , s32 , s32 ) __attribute__((deprecated)); +extern void microblaze_init_dcache_range (s32 , s32 ) __attribute__((deprecated)); + +/* necessary for pre-processor */ +#define stringify(s) tostring(s) +#define tostring(s) #s + +/* FSL Access Macros */ + +/* Blocking Data Read and Write to FSL no. id */ +#define getfsl(val, id) asm volatile ("get\t%0,rfsl" stringify(id) : "=d" (val)) +#define putfsl(val, id) asm volatile ("put\t%0,rfsl" stringify(id) :: "d" (val)) + +/* Non-blocking Data Read and Write to FSL no. id */ +#define ngetfsl(val, id) asm volatile ("nget\t%0,rfsl" stringify(id) : "=d" (val)) +#define nputfsl(val, id) asm volatile ("nput\t%0,rfsl" stringify(id) :: "d" (val)) + +/* Blocking Control Read and Write to FSL no. id */ +#define cgetfsl(val, id) asm volatile ("cget\t%0,rfsl" stringify(id) : "=d" (val)) +#define cputfsl(val, id) asm volatile ("cput\t%0,rfsl" stringify(id) :: "d" (val)) + +/* Non-blocking Control Read and Write to FSL no. id */ +#define ncgetfsl(val, id) asm volatile ("ncget\t%0,rfsl" stringify(id) : "=d" (val)) +#define ncputfsl(val, id) asm volatile ("ncput\t%0,rfsl" stringify(id) :: "d" (val)) + +/* Polling versions of FSL access macros. This makes the FSL access interruptible */ +#define getfsl_interruptible(val, id) asm volatile ("\n1:\n\tnget\t%0,rfsl" stringify(id) "\n\t" \ + "addic\tr18,r0,0\n\t" \ + "bnei\tr18,1b\n" \ + : "=d" (val) :: "r18") + +#define putfsl_interruptible(val, id) asm volatile ("\n1:\n\tnput\t%0,rfsl" stringify(id) "\n\t" \ + "addic\tr18,r0,0\n\t" \ + "bnei\tr18,1b\n" \ + :: "d" (val) : "r18") + +#define cgetfsl_interruptible(val, id) asm volatile ("\n1:\n\tncget\t%0,rfsl" stringify(id) "\n\t" \ + "addic\tr18,r0,0\n\t" \ + "bnei\tr18,1b\n" \ + : "=d" (val) :: "r18") + +#define cputfsl_interruptible(val, id) asm volatile ("\n1:\n\tncput\t%0,rfsl" stringify(id) "\n\t" \ + "addic\tr18,r0,0\n\t" \ + "bnei\tr18,1b\n" \ + :: "d" (val) : "r18") +/* FSL valid and error check macros. */ +#define fsl_isinvalid(result) asm volatile ("addic\t%0,r0,0" : "=d" (result)) +#define fsl_iserror(error) asm volatile ("mfs\t%0,rmsr\n\t" \ + "andi\t%0,%0,0x10" : "=d" (error)) + +/* Pseudo assembler instructions */ +#define clz(v) ({ u32 _rval; \ + __asm__ __volatile__ ( \ + "clz\t%0,%1\n" : "=d"(_rval): "d" (v) \ + ); \ + _rval; \ + }) + +#define mbar(mask) ({ __asm__ __volatile__ ("mbar\t" stringify(mask) ); }) +#define mb_sleep() ({ __asm__ __volatile__ ("sleep\t"); }) +#define mb_hibernate() ({ __asm__ __volatile__ ("hibernate\t"); }) +#define mb_suspend() ({ __asm__ __volatile__ ("suspend\t"); }) +#define mb_swapb(v) ({ u32 _rval; \ + __asm__ __volatile__ ( \ + "swapb\t%0,%1\n" : "=d"(_rval) : "d" (v) \ + ); \ + _rval; \ + }) + +#define mb_swaph(v) ({ u32 _rval; \ + __asm__ __volatile__ ( \ + "swaph\t%0,%1\n" : "=d"(_rval) : "d" (v) \ + ); \ + _rval; \ + }) + +/** @name Microblaze pseudo-asm macros + * + * The following is a summary of the MicroBlaze processor pseudo-asm macros. + * @{ + */ + + /** + Return value from the general purpose register (GPR) rn. + @param rn General purpose register to be read. +*/ +#define mfgpr(rn) ({ UINTPTR _rval; \ + __asm__ __volatile__ ( \ + "or\t%0,r0," stringify(rn) "\n" : "=d"(_rval) \ + ); \ + _rval; \ + }) + + /** + Return the current value of the MSR. + @param None +*/ +#define mfmsr() ({ UINTPTR _rval; \ + __asm__ __volatile__ ( \ + "mfs\t%0,rmsr\n" : "=d"(_rval) \ + ); \ + _rval; \ + }) + + /** + Return the current value of the Exception Address Register (EAR). + @param None +*/ +#define mfear() ({ UINTPTR _rval; \ + __asm__ __volatile__ ( \ + "mfs\t%0,rear\n" : "=d"(_rval) \ + ); \ + _rval; \ + }) + +#define mfeare() ({ UINTPTR _rval; \ + __asm__ __volatile__ ( \ + "mfse\t%0,rear\n" : "=d"(_rval) \ + ); \ + _rval; \ + }) + /** + Return the current value of the Exception Status Register (ESR). + @param None +*/ +#define mfesr() ({ UINTPTR _rval; \ + __asm__ __volatile__ ( \ + "mfs\t%0,resr\n" : "=d"(_rval) \ + ); \ + _rval; \ + }) + + /** + Return the current value of the Floating Point Status (FPS). + @param None +*/ +#define mffsr() ({ UINTPTR _rval; \ + __asm__ __volatile__ ( \ + "mfs\t%0,rfsr\n" : "=d"(_rval) \ + ); \ + _rval; \ + }) +/*@}*/ +#define mfpvr(rn) ({ UINTPTR _rval; \ + __asm__ __volatile__ ( \ + "mfs\t%0,rpvr" stringify(rn) "\n" : "=d"(_rval) \ + ); \ + _rval; \ + }) + +#define mfpvre(rn) ({ UINTPTR _rval; \ + __asm__ __volatile__ ( \ + "mfse\t%0,rpvr" stringify(rn) "\n" : "=d"(_rval) \ + ); \ + _rval; \ + }) + +#define mfbtr() ({ UINTPTR _rval; \ + __asm__ __volatile__ ( \ + "mfs\t%0,rbtr\n" : "=d"(_rval) \ + ); \ + _rval; \ + }) + +#define mfedr() ({ UINTPTR _rval; \ + __asm__ __volatile__ ( \ + "mfs\t%0,redr\n" : "=d"(_rval) \ + ); \ + _rval; \ + }) + +#define mfpid() ({ UINTPTR _rval; \ + __asm__ __volatile__ ( \ + "mfs\t%0,rpid\n" : "=d"(_rval)\ + ); \ + _rval; \ + }) + +#define mfzpr() ({ UINTPTR _rval; \ + __asm__ __volatile__ ( \ + "mfs\t%0,rzpr\n" : "=d"(_rval) \ + ); \ + _rval; \ + }) + +#define mftlbx() ({ UINTPTR _rval; \ + __asm__ __volatile__ ( \ + "mfs\t%0,rtlbx\n" : "=d"(_rval) \ + ); \ + _rval; \ + }) + +#define mftlblo() ({ UINTPTR _rval; \ + __asm__ __volatile__ ( \ + "mfs\t%0,rtlblo\n" : "=d"(_rval) \ + ); \ + _rval; \ + }) + +#define mftlbhi() ({ UINTPTR _rval; \ + __asm__ __volatile__ ( \ + "mfs\t%0,rtlbhi\n" : "=d"(_rval) \ + ); \ + _rval; \ + }) + +#define mfslr() ({ UINTPTR _rval; \ + __asm__ __volatile__ ( \ + "mfs\t%0,rslr\n" : "=d"(_rval) \ + ); \ + _rval; \ + }) + +#define mfshr() ({ UINTPTR _rval; \ + __asm__ __volatile__ ( \ + "mfs\t%0,rshr\n" : "=d"(_rval) \ + ); \ + _rval; \ + }) + +#define mtgpr(rn, v) ({ __asm__ __volatile__ ( \ + "or\t" stringify(rn) ",r0,%0\n" :: "d" (v) \ + ); \ + }) + +#define mtmsr(v) ({ __asm__ __volatile__ ( \ + "mts\trmsr,%0\n\tnop\n" :: "d" (v) \ + ); \ + }) + + +#define mtfsr(v) ({ __asm__ __volatile__ ( \ + "mts\trfsr,%0\n\tnop\n" :: "d" (v) \ + ); \ + }) + +#define mtpid(v) ({ __asm__ __volatile__ ( \ + "mts\trpid,%0\n\tnop\n" :: "d" (v) \ + ); \ + }) + +#define mtzpr(v) ({ __asm__ __volatile__ ( \ + "mts\trzpr,%0\n\tnop\n" :: "d" (v) \ + ); \ + }) + +#define mttlbx(v) ({ __asm__ __volatile__ ( \ + "mts\trtlbx,%0\n\tnop\n" :: "d" (v) \ + ); \ + }) + +#define mttlblo(v) ({ __asm__ __volatile__ ( \ + "mts\trtlblo,%0\n\tnop\n" :: "d" (v) \ + ); \ + }) + +#define mttlbhi(v) ({ __asm__ __volatile__ ( \ + "mts\trtlbhi,%0\n\tnop\n" :: "d" (v) \ + ); \ + }) + +#define mttlbsx(v) ({ __asm__ __volatile__ ( \ + "mts\trtlbsx,%0\n\tnop\n" :: "d" (v) \ + ); \ + }) + +#define mtslr(v) ({ __asm__ __volatile__ ( \ + "mts\trslr,%0\n\tnop\n" :: "d" (v) \ + ); \ + }) + +#define mtshr(v) ({ __asm__ __volatile__ ( \ + "mts\trshr,%0\n\tnop\n" :: "d" (v) \ + ); \ + }) + +#define lwx(address) ({ u32 _rval; \ + __asm__ __volatile__ ( \ + "lwx\t%0,%1,r0\n" : "=d"(_rval) : "d" (address) \ + ); \ + _rval; \ + }) + +#define lwr(address) ({ u32 _rval; \ + __asm__ __volatile__ ( \ + "lwr\t%0,%1,r0\n" : "=d"(_rval) : "d" (address) \ + ); \ + _rval; \ + }) + + +#define lwea(lladdr) ({ u32 _rval; \ + __asm__ __volatile__ ( \ + "lwea\t%0,%M1,%L1\n" : "=d"(_rval) : "d" (lladdr) \ + ); \ + _rval; \ + }) + +#define lhur(address) ({ u32 _rval; \ + __asm__ __volatile__ ( \ + "lhur\t%0,%1,r0\n" : "=d"(_rval) : "d" (address) \ + ); \ + _rval; \ + }) + +#define lhuea(lladdr) ({ u32 _rval; \ + __asm__ __volatile__ ( \ + "lhuea\t%0,%M1,%L1\n" : "=d"(_rval) : "d" (lladdr) \ + ); \ + _rval; \ + }) + +#define lbur(address) ({ u32 _rval; \ + __asm__ __volatile__ ( \ + "lbur\t%0,%1,r0\n" : "=d"(_rval) : "d" (address) \ + ); \ + _rval; \ + }) + +#define lbuea(lladdr) ({ u32 _rval; \ + __asm__ __volatile__ ( \ + "lbuea\t%0,%M1,%L1\n" : "=d"(_rval) : "d" (lladdr) \ + ); \ + _rval; \ + }) + +#define swx(address, data) ({ __asm__ __volatile__ ( \ + "swx\t%0,%1,r0\n" :: "d" (data), "d" (address) \ + ); \ + }) + +#define swr(address, data) ({ __asm__ __volatile__ ( \ + "swr\t%0,%1,r0\n" :: "d" (data), "d" (address) \ + ); \ + }) + +#define swea(lladdr, data) ({ __asm__ __volatile__ ( \ + "swea\t%0,%M1,%L1\n" :: "d" (data), "d" (lladdr) \ + ); \ + }) + +#define shr(address, data) ({ __asm__ __volatile__ ( \ + "shr\t%0,%1,r0\n" :: "d" (data), "d" (address) \ + ); \ + }) + +#define shea(lladdr, data) ({ __asm__ __volatile__ ( \ + "shea\t%0,%M1,%L1\n" :: "d" (data), "d" (lladdr) \ + ); \ + }) + +#define sbr(address, data) ({ __asm__ __volatile__ ( \ + "sbr\t%0,%1,r0\n" :: "d" (data), "d" (address) \ + ); \ + }) + +#define sbea(lladdr, data) ({ __asm__ __volatile__ ( \ + "sbea\t%0,%M1,%L1\n" :: "d" (data), "d" (lladdr) \ + ); \ + }) + +#define microblaze_getfpex_operand_a() ({ \ + extern u32 mb_fpex_op_a; \ + mb_fpex_op_a; \ + }) + +#define microblaze_getfpex_operand_b() ({ \ + extern u32 mb_fpex_op_b; \ + mb_fpex_op_b; \ + }) + +/* Deprecated MicroBlaze FSL macros */ +#define microblaze_bread_datafsl(val, id) getfsl(val,id) +#define microblaze_bwrite_datafsl(val, id) putfsl(val,id) +#define microblaze_nbread_datafsl(val, id) ngetfsl(val,id) +#define microblaze_nbwrite_datafsl(val, id) nputfsl(val,id) +#define microblaze_bread_cntlfsl(val, id) cgetfsl(val,id) +#define microblaze_bwrite_cntlfsl(val, id) cputfsl(val,id) +#define microblaze_nbread_cntlfsl(val, id) ncgetfsl(val,id) +#define microblaze_nbwrite_cntlfsl(val, id) ncputfsl(val,id) + +#ifdef __cplusplus +} +#endif +#endif // _MICROBLAZE_INTERFACE_H_ +/** +* @} End of "addtogroup microblaze_pseudo_asm_macro". +*/ diff --git a/datalink814_sp/bsp/microblaze_ps/include/mblaze_nt_types.h b/datalink814_sp/bsp/microblaze_ps/include/mblaze_nt_types.h new file mode 100644 index 0000000..807dda3 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/include/mblaze_nt_types.h @@ -0,0 +1,50 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + + +#ifndef _MBLAZE_NT_TYPES_H +#define _MBLAZE_NT_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef char byte; +typedef short half; +typedef int word; +typedef unsigned char ubyte; +typedef unsigned short uhalf; +typedef unsigned int uword; +typedef ubyte boolean; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/datalink814_sp/bsp/microblaze_ps/include/microblaze_exceptions_g.h b/datalink814_sp/bsp/microblaze_ps/include/microblaze_exceptions_g.h new file mode 100644 index 0000000..9d665a0 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/include/microblaze_exceptions_g.h @@ -0,0 +1,39 @@ + +/******************************************************************* +* +* CAUTION: This file is automatically generated by HSI. +* Version: 2019.1.3 +* DO NOT EDIT. +* +* Copyright (C) 2010-2023 Xilinx, Inc. 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 +*XILINX 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. +* +*Except as contained in this notice, the name of the Xilinx shall not be used +*in advertising or otherwise to promote the sale, use or other dealings in +*this Software without prior written authorization from Xilinx. +* + +* +* Description: Exception Handling Header for MicroBlaze Processor +* +*******************************************************************/ + +#define MICROBLAZE_EXCEPTIONS_ENABLED 1 +#define MICROBLAZE_CAN_HANDLE_EXCEPTIONS_IN_DELAY_SLOTS + + diff --git a/datalink814_sp/bsp/microblaze_ps/include/microblaze_exceptions_i.h b/datalink814_sp/bsp/microblaze_ps/include/microblaze_exceptions_i.h new file mode 100644 index 0000000..b31b257 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/include/microblaze_exceptions_i.h @@ -0,0 +1,83 @@ +/****************************************************************************** +* +* Copyright (C) 2012 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file microblaze_exceptions_i.h +* +* This header file contains defines for structures used by the microblaze +* hardware exception handler. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Date     Changes
+* ----- -------- -----------------------------------------------
+* 1.00a 06/24/04 First release
+* 
+* +******************************************************************************/ + +#ifndef MICROBLAZE_EXCEPTIONS_I_H /* prevent circular inclusions */ +#define MICROBLAZE_EXCEPTIONS_I_H /* by using protection macros */ + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_exception.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct +{ + Xil_ExceptionHandler Handler; + void *CallBackRef; +} MB_ExceptionVectorTableEntry; + +/* Exception IDs */ +#define XEXC_ID_FSL 0U +#define XEXC_ID_UNALIGNED_ACCESS 1U +#define XEXC_ID_ILLEGAL_OPCODE 2U +#define XEXC_ID_M_AXI_I_EXCEPTION 3U +#define XEXC_ID_IPLB_EXCEPTION 3U +#define XEXC_ID_M_AXI_D_EXCEPTION 4U +#define XEXC_ID_DPLB_EXCEPTION 4U +#define XEXC_ID_DIV_BY_ZERO 5U +#define XEXC_ID_FPU 6U +#define XEXC_ID_STACK_VIOLATION 7U +#define XEXC_ID_MMU 7U + +void microblaze_register_exception_handler(u32 ExceptionId, Xil_ExceptionHandler Handler, void *DataPtr); + +#ifdef __cplusplus +} +#endif +#endif /* end of protection macro */ diff --git a/datalink814_sp/bsp/microblaze_ps/include/microblaze_instructions.h b/datalink814_sp/bsp/microblaze_ps/include/microblaze_instructions.h new file mode 100644 index 0000000..fdaa508 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/include/microblaze_instructions.h @@ -0,0 +1,118 @@ +/****************************************************************************** +* +* Copyright (C) 2018-2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file microblaze_instructions.h +* +* It provides wrapper macros to call 32/64 bit variant of specific +* arithmetic/logical instructions, based on the processor in execution. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 6.8 	mus  	 10/09/18 First release
+*
+*
+* 
+* +******************************************************************************/ +#ifndef MICROBLAZE_INSTRUCTIONS_H /* prevent circular inclusions */ +#define MICROBLAZE_INSTRUCTIONS_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined (__arch64__) +#define ADDIK addlik +#define ADDK addlk +#define ADDI addli +#define ADD addl +#define ANDI andli +#define SUBK sublk +#define RSUBK rsublk +#define ORI orli +#define LI lli +#define LOAD ll +#define SI sli +#define STORE sl +#define BRLID brealid +#define BGTID beageid +#define BGEI beagei +#define BNEID beaneid +#define BLTI bealti +#define CMPU cmplu +#define BRID breaid +#define BNEID beaneid +#define BLEI bealei +#define BEQI beaeqi +#define BRI breai +#define XORI xorli +#define BNEI beanei +#define OR orl +#define BRALID brealid +#define XOR xorl +#else +#define ADDIK addik +#define ADDK addk +#define ADDI addi +#define ADD add +#define ANDI andi +#define SUBK subk +#define RSUBK rsubk +#define ORI ori +#define LI lwi +#define LOAD lw +#define SI swi +#define STORE sw +#define BRLID brlid +#define BGTID bgtid +#define BGEI bgei +#define BNEID bneid +#define BLTI blti +#define CMPU cmpu +#define BRID brid +#define BNEID bneid +#define BLEI blei +#define BEQI beqi +#define BRI bri +#define XORI xori +#define BNEI bnei +#define OR or +#define BRALID bralid +#define XOR xor +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* MICROBLAZE_INSTRUCTIONS_H */ diff --git a/datalink814_sp/bsp/microblaze_ps/include/microblaze_interrupts_i.h b/datalink814_sp/bsp/microblaze_ps/include/microblaze_interrupts_i.h new file mode 100644 index 0000000..c5465ad --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/include/microblaze_interrupts_i.h @@ -0,0 +1,73 @@ +/****************************************************************************** +* +* Copyright (C) 2008 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file microblaze_interrupts_i.h +* +* This header file contains identifiers and low-level driver functions (or +* macros) that can be used to access the device. The user should refer to the +* hardware device specification for more details of the device operation. +* High-level driver functions are defined in xintc.h. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Date     Changes
+* ----- -------- -----------------------------------------------
+* 1.00b 10/03/03 First release
+* 
+* +******************************************************************************/ + +#ifndef MICROBLAZE_INTERRUPTS_I_H /* prevent circular inclusions */ +#define MICROBLAZE_INTERRUPTS_I_H /* by using protection macros */ + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_exception.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct +{ + XInterruptHandler Handler; + void *CallBackRef; +} MB_InterruptVectorTableEntry; + +#define MB_INTERRUPT_VECTOR_TABLE_ENTRIES 1 + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ diff --git a/datalink814_sp/bsp/microblaze_ps/include/microblaze_sleep.h b/datalink814_sp/bsp/microblaze_ps/include/microblaze_sleep.h new file mode 100644 index 0000000..929f811 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/include/microblaze_sleep.h @@ -0,0 +1,129 @@ +/****************************************************************************** +* +* Copyright (C) 2014-2017 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file microblaze_sleep.h +* +* @addtogroup microblaze_sleep_routines Sleep Routines for Microblaze +* +* The microblaze_sleep.h file contains microblaze sleep APIs. These APIs +* provides delay for requested duration. +* +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 4.1   asa  04/18/14 Add sleep function - first release.
+* 6.6   srm  10/18/17 Added the Register offset definitions and Control/Status
+*                     Register bit masks of the Axi timer.
+*
+* 
+* +* @note +* The microblaze_sleep.h file may contain architecture-dependent items. +* +******************************************************************************/ + +#ifndef MICROBLAZE_SLEEP_H /* prevent circular inclusions */ +#define MICROBLAZE_SLEEP_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "mb_interface.h" +#include "xparameters.h" +#include "sleep.h" + +/************************** Constant Definitions *****************************/ + +#if defined (XSLEEP_TIMER_IS_AXI_TIMER) + +/** @name Register Offset Definitions + * Register offsets within the Axi timer counter, there are multiple + * timer counters within a single device + * @{ + */ +#define XSLEEP_TIMER_AXITIMER_TCSR0_OFFSET 0U /**< Control/Status register */ +#define XSLEEP_TIMER_AXITIMER_TLR_OFFSET 4U /**< Load register */ +#define XSLEEP_TIMER_AXITIMER_TCR_OFFSET 8U /**< Timer counter register */ +/* @} */ + +/** @name Control Status Register Bit Definitions + * Control Status Register bit masks + * Used to configure the Axi timer counter device. + * @{ + */ +#define XSLEEP_TIMER_AXITIMER_CSR_ENABLE_TMR_MASK 0x00000080U + /**< Enables only the specific timer */ +#define XSLEEP_TIMER_AXITIMER_CSR_AUTO_RELOAD_MASK 0x00000010U + /**< In compare mode, configures the timer + * counter to reload from the Load Register. + * The default mode causes the timer counter + * to hold when the compare value is hit. In + * capture mode, configures the timer counter + * to not hold the previous capture value if + * a new event occurs. The default mode cause + * the timer counter to hold the capture value + * until recognized.*/ +#define XSLEEP_TIMER_AXITIMER_CSR_LOAD_MASK 0x00000020U + /**< Loads the timer using the load value + * provided earlier in the Load Register, + * XSLEEP_TIMER_AXITIMER_TLR_OFFSET. */ +#define XSLEEP_TIMER_AXITIMER_CSR_INT_OCCURED_MASK 0x00000100U + /**< If bit is set, an interrupt has occured. + * If set and '1' is written to this bit + * position, bit is cleared.*/ +#define XSLEEP_TIMER_AXITIMER_CSR_ENABLE_TMR_MASK 0x00000080U + /**< Enables only the specific timer */ +/* @} */ + +/**************************** Type Definitions *******************************/ + +/************************** Function Prototypes ******************************/ + +static void Xil_SleepAxiTimer(u32 delay, u64 frequency); +static void XTime_StartAxiTimer(); +#endif +void MB_Sleep(u32 MilliSeconds) __attribute__((__deprecated__)); + + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** +* @} End of "addtogroup microblaze_sleep_routines". +*/ \ No newline at end of file diff --git a/datalink814_sp/bsp/microblaze_ps/include/profile.h b/datalink814_sp/bsp/microblaze_ps/include/profile.h new file mode 100644 index 0000000..63f503a --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/include/profile.h @@ -0,0 +1,127 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +#ifndef PROFILE_H +#define PROFILE_H 1 + +#include +#include "xil_types.h" +#include "profile_config.h" + +#ifdef PROC_MICROBLAZE +#include "mblaze_nt_types.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +void _system_init( void ) ; +void _system_clean( void ) ; +void mcount(u32 frompc, u32 selfpc); +void profile_intr_handler( void ) ; +void _profile_init( void ); + + + +/**************************************************************************** + * Profiling on hardware - Hash table maintained on hardware and data sent + * to xmd for gmon.out generation. + ****************************************************************************/ +/* + * histogram counters are unsigned shorts (according to the kernel). + */ +#define HISTCOUNTER u16 + +struct tostruct { + u32 selfpc; + s32 count; + s16 link; + u16 pad; +}; + +struct fromstruct { + u32 frompc ; + s16 link ; + u16 pad ; +} ; + +/* + * general rounding functions. + */ +#define ROUNDDOWN(x,y) (((x)/(y))*(y)) +#define ROUNDUP(x,y) ((((x)+(y)-1)/(y))*(y)) + +/* + * The profiling data structures are housed in this structure. + */ +struct gmonparam { + s32 state; + + /* Histogram Information */ + u16 *kcount; /* No. of bins in histogram */ + u32 kcountsize; /* Histogram samples */ + + /* Call-graph Information */ + struct fromstruct *froms; + u32 fromssize; + struct tostruct *tos; + u32 tossize; + + /* Initialization I/Ps */ + u32 lowpc; + u32 highpc; + u32 textsize; + /* u32 cg_froms, */ + /* u32 cg_tos, */ +}; +extern struct gmonparam *_gmonparam; +extern s32 n_gmon_sections; + +/* + * Possible states of profiling. + */ +#define GMON_PROF_ON 0 +#define GMON_PROF_BUSY 1 +#define GMON_PROF_ERROR 2 +#define GMON_PROF_OFF 3 + +/* + * Sysctl definitions for extracting profiling information from the kernel. + */ +#define GPROF_STATE 0 /* int: profiling enabling variable */ +#define GPROF_COUNT 1 /* struct: profile tick count buffer */ +#define GPROF_FROMS 2 /* struct: from location hash bucket */ +#define GPROF_TOS 3 /* struct: destination/count structure */ +#define GPROF_GMONPARAM 4 /* struct: profiling parameters (see above) */ + +#ifdef __cplusplus +} +#endif + +#endif /* PROFILE_H */ diff --git a/datalink814_sp/bsp/microblaze_ps/include/pvr.h b/datalink814_sp/bsp/microblaze_ps/include/pvr.h new file mode 100644 index 0000000..e413cfb --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/include/pvr.h @@ -0,0 +1,532 @@ +/****************************************************************************** +* +* Copyright (C) 2006 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file pvr.h +* +* @addtogroup microblaze_pvr_macros Microblaze PVR access routines and macros +* +* MicroBlaze processor v5.00.a and later versions have configurable +* Processor Version Registers (PVRs). The contents of the PVR are captured +* using the pvr_t data structure, which is defined as an array of 32-bit words, +* with each word corresponding to a PVR register on hardware. The number of PVR +* words is determined by the number of PVRs configured in the hardware. You should +* not attempt to access PVR registers that are not present in hardware, as the +* pvr_t data structure is resized to hold only as many PVRs as are present in +* hardware. +* To access information in the PVR: +* 1. Use the microblaze_get_pvr() function to populate the PVR data into a pvr_t +* data structure. +* 2. In subsequent steps, you can use any one of the PVR access macros list to +* get individual data stored in the PVR. +* 3. pvr.h header file must be included to source to use PVR macros. +* +* @{ +* +******************************************************************************/ + +#ifndef _PVR_H +#define _PVR_H + +#include "xil_types.h" +#include "xil_assert.h" +#include "xparameters.h" +#include "mb_interface.h" +#include "bspconfig.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Defs */ +typedef struct pvr_s { +#ifdef MICROBLAZE_PVR_FULL + unsigned int pvr[16]; +#else + unsigned int pvr[1]; +#endif +} pvr_t; + + +#define getpvr(pvrid, val) asm volatile ("mfs\t%0,rpvr" stringify(pvrid) "\n\t" : "=d" (val)) + +/* Basic PVR mask */ +#define MICROBLAZE_PVR0_PVR_FULL_MASK 0x80000000 +#define MICROBLAZE_PVR0_USE_BARREL_MASK 0x40000000 +#define MICROBLAZE_PVR0_USE_DIV_MASK 0x20000000 +#define MICROBLAZE_PVR0_USE_HW_MUL_MASK 0x10000000 +#define MICROBLAZE_PVR0_USE_FPU_MASK 0x08000000 +#define MICROBLAZE_PVR0_USE_EXCEPTION_MASK 0x04000000 +#define MICROBLAZE_PVR0_USE_ICACHE_MASK 0x02000000 +#define MICROBLAZE_PVR0_USE_DCACHE_MASK 0x01000000 +#define MICROBLAZE_PVR0_USE_MMU_MASK 0x00800000 +#define MICROBLAZE_PVR0_USE_BTC_MASK 0x00400000 +#define MICROBLAZE_PVR0_ENDIANNESS_MASK 0x00200000 +#define MICROBLAZE_PVR0_FAULT_TOLERANT_MASK 0x00100000 +#define MICROBLAZE_PVR0_STACK_PROTECTION_MASK 0x00080000 +#define MICROBLAZE_PVR0_MICROBLAZE_VERSION_MASK 0x0000FF00 +#define MICROBLAZE_PVR0_USER1_MASK 0x000000FF + +/* User 2 PVR mask */ +#define MICROBLAZE_PVR1_USER2_MASK 0xFFFFFFFF + +/* Configuration PVR masks */ +#define MICROBLAZE_PVR2_D_AXI_MASK 0x80000000 +#define MICROBLAZE_PVR2_D_LMB_MASK 0x40000000 +#define MICROBLAZE_PVR2_D_PLB_MASK 0x02000000 +#define MICROBLAZE_PVR2_I_AXI_MASK 0x20000000 +#define MICROBLAZE_PVR2_I_LMB_MASK 0x10000000 +#define MICROBLAZE_PVR2_I_PLB_MASK 0x01000000 +#define MICROBLAZE_PVR2_INTERRUPT_IS_EDGE_MASK 0x08000000 +#define MICROBLAZE_PVR2_EDGE_IS_POSITIVE_MASK 0x04000000 +#define MICROBLAZE_PVR2_INTERCONNECT_MASK 0x00800000 +#define MICROBLAZE_PVR2_STREAM_INTERCONNECT_MASK 0x00400000 +#define MICROBLAZE_PVR2_USE_EXTENDED_FSL_INSTR_MASK 0x00080000 +#define MICROBLAZE_PVR2_USE_MSR_INSTR_MASK 0x00020000 +#define MICROBLAZE_PVR2_USE_PCMP_INSTR_MASK 0x00010000 +#define MICROBLAZE_PVR2_AREA_OPTIMIZED_MASK 0x00008000 +#define MICROBLAZE_PVR2_USE_BARREL_MASK 0x00004000 +#define MICROBLAZE_PVR2_USE_DIV_MASK 0x00002000 +#define MICROBLAZE_PVR2_USE_HW_MUL_MASK 0x00001000 +#define MICROBLAZE_PVR2_USE_FPU_MASK 0x00000800 +#define MICROBLAZE_PVR2_USE_FPU2_MASK 0x00000200 +#define MICROBLAZE_PVR2_USE_MUL64_MASK 0x00000400 +#define MICROBLAZE_PVR2_OPCODE_0x0_ILLEGAL_MASK 0x00000040 +#define MICROBLAZE_PVR2_UNALIGNED_EXCEPTION_MASK 0x00000020 +#define MICROBLAZE_PVR2_ILL_OPCODE_EXCEPTION_MASK 0x00000010 +#define MICROBLAZE_PVR2_M_AXI_I_BUS_EXCEPTION_MASK 0x00000008 +#define MICROBLAZE_PVR2_M_AXI_D_BUS_EXCEPTION_MASK 0x00000004 +#define MICROBLAZE_PVR2_IPLB_BUS_EXCEPTION_MASK 0x00000100 +#define MICROBLAZE_PVR2_DPLB_BUS_EXCEPTION_MASK 0x00000080 +#define MICROBLAZE_PVR2_DIV_ZERO_EXCEPTION_MASK 0x00000002 +#define MICROBLAZE_PVR2_FPU_EXCEPTION_MASK 0x00000001 +#define MICROBLAZE_PVR2_FSL_EXCEPTION_MASK 0x00040000 + +/* Debug and exception PVR masks */ +#define MICROBLAZE_PVR3_DEBUG_ENABLED_MASK 0x80000000 +#define MICROBLAZE_PVR3_NUMBER_OF_PC_BRK_MASK 0x1E000000 +#define MICROBLAZE_PVR3_NUMBER_OF_RD_ADDR_BRK_MASK 0x00380000 +#define MICROBLAZE_PVR3_NUMBER_OF_WR_ADDR_BRK_MASK 0x0000E000 +#define MICROBLAZE_PVR3_FSL_LINKS_MASK 0x00000380 +#define MICROBLAZE_PVR3_BTC_SIZE_MASK 0x00000007 + +/* ICache config PVR masks */ +#define MICROBLAZE_PVR4_USE_ICACHE_MASK 0x80000000 +#define MICROBLAZE_PVR4_ICACHE_ADDR_TAG_BITS_MASK 0x7C000000 +#define MICROBLAZE_PVR4_ICACHE_ALLOW_WR_MASK 0x01000000 +#define MICROBLAZE_PVR4_ICACHE_LINE_LEN_MASK 0x00E00000 +#define MICROBLAZE_PVR4_ICACHE_BYTE_SIZE_MASK 0x001F0000 +#define MICROBLAZE_PVR4_ICACHE_ALWAYS_USED_MASK 0x00008000 +#define MICROBLAZE_PVR4_ICACHE_INTERFACE_MASK 0x00002000 +#define MICROBLAZE_PVR4_ICACHE_VICTIMS_MASK 0x00001C00 +#define MICROBLAZE_PVR4_ICACHE_STREAMS_MASK 0x00000300 +#define MICROBLAZE_PVR4_ICACHE_FORCE_TAG_LUTRAM_MASK 0x00000080 +#define MICROBLAZE_PVR4_ICACHE_DATA_WIDTH_MASK 0x00000040 + +/* DCache config PVR masks */ +#define MICROBLAZE_PVR5_USE_DCACHE_MASK 0x80000000 +#define MICROBLAZE_PVR5_DCACHE_ADDR_TAG_BITS_MASK 0x7C000000 +#define MICROBLAZE_PVR5_DCACHE_ALLOW_WR_MASK 0x01000000 +#define MICROBLAZE_PVR5_DCACHE_LINE_LEN_MASK 0x00E00000 +#define MICROBLAZE_PVR5_DCACHE_BYTE_SIZE_MASK 0x001F0000 +#define MICROBLAZE_PVR5_DCACHE_ALWAYS_USED_MASK 0x00008000 +#define MICROBLAZE_PVR5_DCACHE_USE_WRITEBACK_MASK 0x00004000 +#define MICROBLAZE_PVR5_DCACHE_INTERFACE_MASK 0x00002000 +#define MICROBLAZE_PVR5_DCACHE_VICTIMS_MASK 0x00001C00 +#define MICROBLAZE_PVR5_DCACHE_FORCE_TAG_LUTRAM_MASK 0x00000080 +#define MICROBLAZE_PVR5_DCACHE_DATA_WIDTH_MASK 0x00000040 + +#if defined(__arch64__) +/* ICache base address PVR mask */ +#define MICROBLAZE_PVR6_ICACHE_BASEADDR_MASK 0xFFFFFFFFFFFFFFFF + +/* ICache high address PVR mask */ +#define MICROBLAZE_PVR7_ICACHE_HIGHADDR_MASK 0xFFFFFFFFFFFFFFFF + +/* DCache base address PVR mask */ +#define MICROBLAZE_PVR8_DCACHE_BASEADDR_MASK 0xFFFFFFFFFFFFFFFF + +/* DCache high address PVR mask */ +#define MICROBLAZE_PVR9_DCACHE_HIGHADDR_MASK 0xFFFFFFFFFFFFFFFF + +#else +/* ICache base address PVR mask */ +#define MICROBLAZE_PVR6_ICACHE_BASEADDR_MASK 0xFFFFFFFF + +/* ICache high address PVR mask */ +#define MICROBLAZE_PVR7_ICACHE_HIGHADDR_MASK 0xFFFFFFFF + +/* DCache base address PVR mask */ +#define MICROBLAZE_PVR8_DCACHE_BASEADDR_MASK 0xFFFFFFFF + +/* DCache high address PVR mask */ +#define MICROBLAZE_PVR9_DCACHE_HIGHADDR_MASK 0xFFFFFFFF +#endif + +/* Target family PVR mask */ +#define MICROBLAZE_PVR10_TARGET_FAMILY_MASK 0xFF000000 + +/* MSR Reset value PVR mask */ +#define MICROBLAZE_PVR11_MSR_RESET_VALUE_MASK 0x000007FF + +/* MMU value PVR mask */ +#define MICROBLAZE_PVR11_MMU_MASK 0xC0000000 +#define MICROBLAZE_PVR11_MMU_ITLB_SIZE_MASK 0x38000000 +#define MICROBLAZE_PVR11_MMU_DTLB_SIZE_MASK 0x07000000 +#define MICROBLAZE_PVR11_MMU_TLB_ACCESS_MASK 0x00C00000 +#define MICROBLAZE_PVR11_MMU_ZONES_MASK 0x003E0000 +#define MICROBLAZE_PVR11_MMU_PRIVILEGED_INSTR_MASK 0x00010000 + +/* PVR access macros */ + +/** +Return non-zero integer if PVR is of type FULL, 0 if basic +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_IS_FULL(_pvr) (_pvr.pvr[0] & MICROBLAZE_PVR0_PVR_FULL_MASK) +/** +Return non-zero integer if hardware barrel shifter present. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_USE_BARREL(_pvr) (_pvr.pvr[0] & MICROBLAZE_PVR0_USE_BARREL_MASK) +/** +Return non-zero integer if hardware divider present. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_USE_DIV(_pvr) (_pvr.pvr[0] & MICROBLAZE_PVR0_USE_DIV_MASK) +/** +Return non-zero integer if hardware multiplier present. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_USE_HW_MUL(_pvr) (_pvr.pvr[0] & MICROBLAZE_PVR0_USE_HW_MUL_MASK) +/** +Return non-zero integer if hardware floating point unit (FPU) present. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_USE_FPU(_pvr) (_pvr.pvr[0] & MICROBLAZE_PVR0_USE_FPU_MASK) +/** +Return non-zero integer if I-cache present. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_USE_ICACHE(_pvr) (_pvr.pvr[0] & MICROBLAZE_PVR0_USE_ICACHE_MASK) +/** +Return non-zero integer if D-cache present. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_USE_DCACHE(_pvr) (_pvr.pvr[0] & MICROBLAZE_PVR0_USE_DCACHE_MASK) +#define MICROBLAZE_PVR_USE_MMU(_pvr) (_pvr.pvr[0] & MICROBLAZE_PVR0_USE_MMU_MASK) +#define MICROBLAZE_PVR_USE_BTC(_pvr) (_pvr.pvr[0] & MICROBLAZE_PVR0_USE_BTC_MASK) +#define MICROBLAZE_PVR_ENDIANNESS(_pvr) (_pvr.pvr[0] & MICROBLAZE_PVR0_ENDIANNESS_MASK) +#define MICROBLAZE_PVR_FAULT_TOLERANT(_pvr) (_pvr.pvr[0] & MICROBLAZE_PVR0_FAULT_TOLERANT_MASK) +#define MICROBLAZE_PVR_STACK_PROTECTION(_pvr) (_pvr.pvr[0] & MICROBLAZE_PVR0_STACK_PROTECTION_MASK) +/** +Return MicroBlaze processor version encoding. Refer to the MicroBlaze Processor +Reference Guide (UG081) for mappings from encodings to actual hardware versions. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_MICROBLAZE_VERSION(_pvr) ((_pvr.pvr[0] & MICROBLAZE_PVR0_MICROBLAZE_VERSION_MASK) >> 8) +/** +Return the USER1 field stored in the PVR. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_USER1(_pvr) (_pvr.pvr[0] & MICROBLAZE_PVR0_USER1_MASK) + +/** +Return the USER2 field stored in the PVR. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_USER2(_pvr) (_pvr.pvr[1] & MICROBLAZE_PVR1_USER2_MASK) + +#define MICROBLAZE_PVR_D_AXI(_pvr) (_pvr.pvr[2] & MICROBLAZE_PVR2_D_AXI_MASK) + +/** +Return non-zero integer if Data Side PLB +interface is present. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_D_LMB(_pvr) (_pvr.pvr[2] & MICROBLAZE_PVR2_D_LMB_MASK) + +/** +Return non-zero integer if Data Side PLB interface is present. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_D_PLB(_pvr) (_pvr.pvr[2] & MICROBLAZE_PVR2_D_PLB_MASK) + +#define MICROBLAZE_PVR_I_AXI(_pvr) (_pvr.pvr[2] & MICROBLAZE_PVR2_I_AXI_MASK) + +/** +Return non-zero integer if Instruction Side Local Memory Bus (LMB) interface present. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_I_LMB(_pvr) (_pvr.pvr[2] & MICROBLAZE_PVR2_I_LMB_MASK) + +/** +Return non-zero integer if Instruction Side PLB interface present. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_I_PLB(_pvr) (_pvr.pvr[2] & MICROBLAZE_PVR2_I_PLB_MASK) + +/** +Return non-zero integer if interrupts are configured as edge-triggered. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_INTERRUPT_IS_EDGE(_pvr) (_pvr.pvr[2] & MICROBLAZE_PVR2_INTERRUPT_IS_EDGE_MASK) + +/** +Return non-zero integer if interrupts are configured as positive edge triggered. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_EDGE_IS_POSITIVE(_pvr) (_pvr.pvr[2] & MICROBLAZE_PVR2_EDGE_IS_POSITIVE_MASK) + +/** +Return non-zero if MicroBlaze processor has PLB interconnect; otherwise return zero. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_INTERCONNECT(_pvr) (_pvr.pvr[2] & MICROBLAZE_PVR2_INTERCONNECT_MASK) + +#define MICROBLAZE_PVR_STREAM_INTERCONNECT(_pvr) (_pvr.pvr[2] & MICROBLAZE_PVR2_STREAM_INTERCONNECT_MASK) +#define MICROBLAZE_PVR_USE_EXTENDED_FSL_INSTR(_pvr) (_pvr.pvr[2] & MICROBLAZE_PVR2_USE_EXTENDED_FSL_INSTR_MASK) +#define MICROBLAZE_PVR_USE_MSR_INSTR(_pvr) (_pvr.pvr[2] & MICROBLAZE_PVR2_USE_MSR_INSTR_MASK) +#define MICROBLAZE_PVR_USE_PCMP_INSTR(_pvr) (_pvr.pvr[2] & MICROBLAZE_PVR2_USE_PCMP_INSTR_MASK) +#define MICROBLAZE_PVR_AREA_OPTIMIZED(_pvr) (_pvr.pvr[2] & MICROBLAZE_PVR2_AREA_OPTIMIZED_MASK) + +/** +Return non-zero integer if MicroBlaze processor supports 64-bit products for +multiplies. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_USE_MUL64(_pvr) (_pvr.pvr[2] & MICROBLAZE_PVR2_USE_MUL64_MASK) + +/** +Return non-zero integer if opcode 0x0 is treated as an illegal opcode. +multiplies. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_OPCODE_0x0_ILLEGAL(_pvr) (_pvr.pvr[2] & MICROBLAZE_PVR2_OPCODE_0x0_ILLEGAL_MASK) + +/** +Return non-zero integer if unaligned exceptions are supported. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_UNALIGNED_EXCEPTION(_pvr) (_pvr.pvr[2] & MICROBLAZE_PVR2_UNALIGNED_EXCEPTION_MASK) + +/** +Return non-zero integer if illegal opcode exceptions are supported. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_ILL_OPCODE_EXCEPTION(_pvr) (_pvr.pvr[2] & MICROBLAZE_PVR2_ILL_OPCODE_EXCEPTION_MASK) + +#define MICROBLAZE_PVR_M_AXI_I_BUS_EXCEPTION(_pvr) (_pvr.pvr[2] & MICROBLAZE_PVR2_M_AXI_I_BUS_EXCEPTION_MASK) + +/** +Return non-zero integer if I-PLB exceptions are supported. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_IPLB_BUS_EXCEPTION(_pvr) (_pvr.pvr[2] & MICROBLAZE_PVR2_IPLB_BUS_EXCEPTION_MASK) + +#define MICROBLAZE_PVR_M_AXI_D_BUS_EXCEPTION(_pvr) (_pvr.pvr[2] & MICROBLAZE_PVR2_M_AXI_D_BUS_EXCEPTION_MASK) + +/** +Return non-zero integer if I-PLB exceptions are supported. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_DPLB_BUS_EXCEPTION(_pvr) (_pvr.pvr[2] & MICROBLAZE_PVR2_DPLB_BUS_EXCEPTION_MASK) + +/** +Return non-zero integer if divide by zero exceptions are supported. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_DIV_ZERO_EXCEPTION(_pvr) (_pvr.pvr[2] & MICROBLAZE_PVR2_DIV_ZERO_EXCEPTION_MASK) + +/** +Return non-zero integer if FPU exceptions are supported. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_FPU_EXCEPTION(_pvr) (_pvr.pvr[2] & MICROBLAZE_PVR2_FPU_EXCEPTION_MASK) + +/** +Return non-zero integer if FSL exceptions are present. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_FSL_EXCEPTION(_pvr) (_pvr.pvr[2] & MICROBLAZE_PVR2_FSL_EXCEPTION_MASK) + +/** +Return non-zero integer if debug is enabled. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_DEBUG_ENABLED(_pvr) (_pvr.pvr[3] & MICROBLAZE_PVR3_DEBUG_ENABLED_MASK) + +/** +Return the number of hardware PC breakpoints available. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_NUMBER_OF_PC_BRK(_pvr) ((_pvr.pvr[3] & MICROBLAZE_PVR3_NUMBER_OF_PC_BRK_MASK) >> 25) + +/** +Return the number of read address hardware watchpoints supported. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_NUMBER_OF_RD_ADDR_BRK(_pvr) ((_pvr.pvr[3] & MICROBLAZE_PVR3_NUMBER_OF_RD_ADDR_BRK_MASK) >> 19) + +/** +Return the number of write address hardware watchpoints supported. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_NUMBER_OF_WR_ADDR_BRK(_pvr) ((_pvr.pvr[3] & MICROBLAZE_PVR3_NUMBER_OF_WR_ADDR_BRK_MASK) >> 13) + +/** +Return the number of FSL links present. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_FSL_LINKS(_pvr) ((_pvr.pvr[3] & MICROBLAZE_PVR3_FSL_LINKS_MASK) >> 7) +#define MICROBLAZE_PVR_BTC_SIZE(_pvr) (_pvr.pvr[3] & MICROBLAZE_PVR3_BTC_SIZE_MASK) + +/** +Return the number of address tag bits for the I-cache. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_ICACHE_ADDR_TAG_BITS(_pvr) ((_pvr.pvr[4] & MICROBLAZE_PVR4_ICACHE_ADDR_TAG_BITS_MASK) >> 26) + +/** +Return non-zero if writes to I-caches are allowed. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_ICACHE_ALLOW_WR(_pvr) (_pvr.pvr[4] & MICROBLAZE_PVR4_ICACHE_ALLOW_WR_MASK) + +/** +Return the length of each I-cache line in bytes. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_ICACHE_LINE_LEN(_pvr) (1 << ((_pvr.pvr[4] & MICROBLAZE_PVR4_ICACHE_LINE_LEN_MASK) >> 21)) + +/** +Return the size of the D-cache in bytes. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_ICACHE_BYTE_SIZE(_pvr) (1 << ((_pvr.pvr[4] & MICROBLAZE_PVR4_ICACHE_BYTE_SIZE_MASK) >> 16)) + +#define MICROBLAZE_PVR_ICACHE_ALWAYS_USED(_pvr) (_pvr.pvr[4] & MICROBLAZE_PVR4_ICACHE_ALWAYS_USED_MASK) +#define MICROBLAZE_PVR_ICACHE_INTERFACE(_pvr) (_pvr.pvr[4] & MICROBLAZE_PVR4_ICACHE_INTERFACE_MASK) +#define MICROBLAZE_PVR_ICACHE_VICTIMS(_pvr) ((_pvr.pvr[4] & MICROBLAZE_PVR4_ICACHE_VICTIMS_MASK) >> 10) +#define MICROBLAZE_PVR_ICACHE_STREAMS(_pvr) ((_pvr.pvr[4] & MICROBLAZE_PVR4_ICACHE_STREAMS_MASK) >> 8) +#define MICROBLAZE_PVR_ICACHE_FORCE_TAG_LUTRAM(_pvr) (_pvr.pvr[4] & MICROBLAZE_PVR4_ICACHE_FORCE_TAG_LUTRAM_MASK) +#define MICROBLAZE_PVR_ICACHE_DATA_WIDTH(_pvr) (_pvr.pvr[4] & MICROBLAZE_PVR4_ICACHE_DATA_WIDTH_MASK) + +/** +Return the number of address tag bits for the D-cache. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_DCACHE_ADDR_TAG_BITS(_pvr) ((_pvr.pvr[5] & MICROBLAZE_PVR5_DCACHE_ADDR_TAG_BITS_MASK) >> 26) + +/** +Return non-zero if writes to D-cache are allowed. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_DCACHE_ALLOW_WR(_pvr) (_pvr.pvr[5] & MICROBLAZE_PVR5_DCACHE_ALLOW_WR_MASK) + +/** +Return the length of each line in the D-cache in bytes. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_DCACHE_LINE_LEN(_pvr) (1 << ((_pvr.pvr[5] & MICROBLAZE_PVR5_DCACHE_LINE_LEN_MASK) >> 21)) + +/** +Return the size of the D-cache in bytes. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_DCACHE_BYTE_SIZE(_pvr) (1 << ((_pvr.pvr[5] & MICROBLAZE_PVR5_DCACHE_BYTE_SIZE_MASK) >> 16)) + + +#define MICROBLAZE_PVR_DCACHE_ALWAYS_USED(_pvr) (_pvr.pvr[5] & MICROBLAZE_PVR5_DCACHE_ALWAYS_USED_MASK) +#define MICROBLAZE_PVR_DCACHE_USE_WRITEBACK(_pvr) (_pvr.pvr[5] & MICROBLAZE_PVR5_DCACHE_USE_WRITEBACK_MASK) +#define MICROBLAZE_PVR_DCACHE_INTERFACE(_pvr) (_pvr.pvr[5] & MICROBLAZE_PVR5_DCACHE_INTERFACE_MASK) +#define MICROBLAZE_PVR_DCACHE_VICTIMS(_pvr) ((_pvr.pvr[5] & MICROBLAZE_PVR5_DCACHE_VICTIMS_MASK) >> 10) +#define MICROBLAZE_PVR_DCACHE_FORCE_TAG_LUTRAM(_pvr) (_pvr.pvr[5] & MICROBLAZE_PVR5_DCACHE_FORCE_TAG_LUTRAM_MASK) +#define MICROBLAZE_PVR_DCACHE_DATA_WIDTH(_pvr) (_pvr.pvr[5] & MICROBLAZE_PVR5_DCACHE_DATA_WIDTH_MASK) + +/** +Return the base address of the I-cache. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_ICACHE_BASEADDR(_pvr) (_pvr.pvr[6] & MICROBLAZE_PVR6_ICACHE_BASEADDR_MASK) + +/** +Return the high address of the I-cache. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_ICACHE_HIGHADDR(_pvr) (_pvr.pvr[7] & MICROBLAZE_PVR7_ICACHE_HIGHADDR_MASK) + +/** +Return the base address of the D-cache. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_DCACHE_BASEADDR(_pvr) (_pvr.pvr[8] & MICROBLAZE_PVR8_DCACHE_BASEADDR_MASK) + +/** +Return the high address of the D-cache. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_DCACHE_HIGHADDR(_pvr) (_pvr.pvr[9] & MICROBLAZE_PVR9_DCACHE_HIGHADDR_MASK) + +/** +Return the encoded target family identifier. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_TARGET_FAMILY(_pvr) ((_pvr.pvr[10] & MICROBLAZE_PVR10_TARGET_FAMILY_MASK) >> 24) + +/** +Refer to the MicroBlaze Processor Reference Guide (UG081) for mappings from encodings +to target family name strings. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_MSR_RESET_VALUE(_pvr) (_pvr.pvr[11] & MICROBLAZE_PVR11_MSR_RESET_VALUE_MASK) + +/** +Returns the value of C_USE_MMU. Refer to the MicroBlaze Processor Reference Guide +(UG081) for mappings from MMU type values to MMU function. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_MMU_TYPE(_pvr) ((_pvr.pvr[11] & MICROBLAZE_PVR11_MMU_MASK) >> 30) +#define MICROBLAZE_PVR_MMU_ITLB_SIZE(_pvr) ((_pvr.pvr[11] & MICROBLAZE_PVR11_MMU_ITLB_SIZE_MASK) >> 27) +#define MICROBLAZE_PVR_MMU_DTLB_SIZE(_pvr) ((_pvr.pvr[11] & MICROBLAZE_PVR11_MMU_DTLB_SIZE_MASK) >> 24) +#define MICROBLAZE_PVR_MMU_TLB_ACCESS(_pvr) ((_pvr.pvr[11] & MICROBLAZE_PVR11_MMU_TLB_ACCESS_MASK) >> 22) +#define MICROBLAZE_PVR_MMU_ZONES(_pvr) ((_pvr.pvr[11] & MICROBLAZE_PVR11_MMU_ZONES_MASK) >> 17) +#define MICROBLAZE_PVR_MMU_PRIVILEGED_INSTR(_pvr) ((_pvr.pvr[11] & MICROBLAZE_PVR11_MMU_PRIVILEGED_INSTR_MASK) >> 16) + +/* Protos */ +int microblaze_get_pvr (pvr_t *pvr); + +#ifdef __cplusplus +} +#endif +#endif /* _PVR_H */ +/** +* @} End of "addtogroup microblaze_pvr_macros". +*/ diff --git a/datalink814_sp/bsp/microblaze_ps/include/sleep.h b/datalink814_sp/bsp/microblaze_ps/include/sleep.h new file mode 100644 index 0000000..f3a632b --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/include/sleep.h @@ -0,0 +1,115 @@ +/****************************************************************************** +* +* Copyright (C) 2014 - 2017 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +/*****************************************************************************/ +/** +* @file sleep.h +* +* This header file contains ARM Cortex A53,A9,R5,Microblaze specific sleep +* related APIs. +* +*
+* MODIFICATION HISTORY :
+*
+* Ver   Who  Date	 Changes
+* ----- ---- -------- -------------------------------------------------------
+* 6.6   srm  11/02/17 Added processor specific sleep rountines
+*								 function prototypes.
+*
+* 
+* +******************************************************************************/ + +#ifndef SLEEP_H +#define SLEEP_H + +#include "xil_types.h" +#include "xil_io.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*****************************************************************************/ +/** +* +* This macro polls an address periodically until a condition is met or till the +* timeout occurs. +* The minimum timeout for calling this macro is 100us. If the timeout is less +* than 100us, it still waits for 100us. Also the unit for the timeout is 100us. +* If the timeout is not a multiple of 100us, it waits for a timeout of +* the next usec value which is a multiple of 100us. +* +* @param IO_func - accessor function to read the register contents. +* Depends on the register width. +* @param ADDR - Address to be polled +* @param VALUE - variable to read the value +* @param COND - Condition to checked (usually involves VALUE) +* @param TIMEOUT_US - timeout in micro seconds +* +* @return 0 - when the condition is met +* -1 - when the condition is not met till the timeout period +* +* @note none +* +*****************************************************************************/ +#define Xil_poll_timeout(IO_func, ADDR, VALUE, COND, TIMEOUT_US) \ + ( { \ + u64 timeout = TIMEOUT_US/100; \ + if(TIMEOUT_US%100!=0) \ + timeout++; \ + for(;;) { \ + VALUE = IO_func(ADDR); \ + if(COND) \ + break; \ + else { \ + usleep(100); \ + timeout--; \ + if(timeout==0) \ + break; \ + } \ + } \ + (timeout>0) ? 0 : -1; \ + } ) + +void usleep(unsigned long useconds); +void sleep(unsigned int seconds); +int usleep_R5(unsigned long useconds); +unsigned sleep_R5(unsigned int seconds); +int usleep_MB(unsigned long useconds); +unsigned sleep_MB(unsigned int seconds); +int usleep_A53(unsigned long useconds); +unsigned sleep_A53(unsigned int seconds); +int usleep_A9(unsigned long useconds); +unsigned sleep_A9(unsigned int seconds); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/datalink814_sp/bsp/microblaze_ps/include/xaxidma.h b/datalink814_sp/bsp/microblaze_ps/include/xaxidma.h new file mode 100644 index 0000000..e053b19 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/include/xaxidma.h @@ -0,0 +1,761 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xaxidma.h +* @addtogroup axidma_v9_9 +* @{ +* @details +* +* This is the driver API for the AXI DMA engine. +* +* For a full description of DMA features, please see the hardware spec. This +* driver supports the following features: +* +* - Scatter-Gather DMA (SGDMA) +* - Simple DMA +* - Interrupts +* - Programmable interrupt coalescing for SGDMA +* - APIs to manage Buffer Descriptors (BD) movement to and from the SGDMA +* engine +* +* Simple DMA +* +* Simple DMA allows the application to define a single transaction between DMA +* and Device. It has two channels: one from the DMA to Device and the other +* from Device to DMA. Application has to set the buffer address and +* length fields to initiate the transfer in respective channel. +* +* Transactions +* +* The object used to describe a transaction is referred to as a Buffer +* Descriptor (BD). Buffer descriptors are allocated in the user application. +* The user application needs to set buffer address, transfer length, and +* control information for this transfer. The control information includes +* SOF and EOF. Definition of those masks are in xaxidma_hw.h +* +* Scatter-Gather DMA +* +* SGDMA allows the application to define a list of transactions in memory which +* the hardware will process without further application intervention. During +* this time, the application is free to continue adding more work to keep the +* Hardware busy. +* +* User can check for the completion of transactions through polling the +* hardware, or interrupts. +* +* SGDMA processes whole packets. A packet is defined as a series of +* data bytes that represent a message. SGDMA allows a packet of data to be +* broken up into one or more transactions. For example, take an Ethernet IP +* packet which consists of a 14 byte header followed by a 1 or more bytes of +* payload. With SGDMA, the application may point a BD to the header and another +* BD to the payload, then transfer them as a single message. This strategy can +* make a TCP/IP stack more efficient by allowing it to keep packet header and +* data in different memory regions instead of assembling packets into +* contiguous blocks of memory. +* +* BD Ring Management +* +* BD rings are shared by the software and the hardware. +* +* The hardware expects BDs to be setup as a linked list. The DMA hardware walks +* through the list by following the next pointer field of a completed BD. +* The hardware stops processing when the just completed BD is the same as the +* BD specified in the Tail Ptr register in the hardware. +* +* The last BD in the ring is linked to the first BD in the ring. +* +* All BD management are done inside the driver. The user application should not +* directly modify the BD fields. Modifications to the BD fields should always +* go through the specific API functions. +* +* Within the ring, the driver maintains four groups of BDs. Each group consists +* of 0 or more adjacent BDs: +* +* - Free: The BDs that can be allocated by the application with +* XAxiDma_BdRingAlloc(). +* +* - Pre-process: The BDs that have been allocated with +* XAxiDma_BdRingAlloc(). These BDs are under application control. The +* application modifies these BDs through driver API to prepare them +* for DMA transactions. +* +* - Hardware: The BDs that have been enqueued to hardware with +* XAxiDma_BdRingToHw(). These BDs are under hardware control and may be in a +* state of awaiting hardware processing, in process, or processed by +* hardware. It is considered an error for the application to change BDs +* while they are in this group. Doing so can cause data corruption and lead +* to system instability. +* +* - Post-process: The BDs that have been processed by hardware and have +* been extracted from the Hardware group with XAxiDma_BdRingFromHw(). +* These BDs are under application control. The application can check the +* transfer status of these BDs. The application use XAxiDma_BdRingFree() +* to put them into the Free group. +* +* BDs are expected to transition in the following way for continuous +* DMA transfers: +*
+*
+*         XAxiDma_BdRingAlloc()                   XAxiDma_BdRingToHw()
+*   Free ------------------------> Pre-process ----------------------> Hardware
+*                                                                      |
+*    /|\                                                               |
+*     |   XAxiDma_BdRingFree()                  XAxiDma_BdRingFromHw() |
+*     +--------------------------- Post-process <----------------------+
+*
+* 
+* +* When a DMA transfer is to be cancelled before enqueuing to hardware, +* application can return the requested BDs to the Free group using +* XAxiDma_BdRingUnAlloc(), as shown below: +*
+*
+*         XAxiDma_BdRingUnAlloc()
+*   Free <----------------------- Pre-process
+*
+* 
+* +* The API provides functions for BD list traversal: +* - XAxiDma_BdRingNext() +* - XAxiDma_BdRingPrev() +* +* These functions should be used with care as they do not understand where +* one group ends and another begins. +* +* SGDMA Descriptor Ring Creation +* +* BD ring is created using XAxiDma_BdRingCreate(). The memory for the BD ring +* is allocated by the application, and it has to be contiguous. Physical +* address is required to setup the BD ring. +* +* The applicaiton can use XAxiDma_BdRingMemCalc() to find out the amount of +* memory needed for a certain number of BDs. XAxiDma_BdRingCntCalc() can be +* used to find out how many BDs can be allocated for certain amount of memory. +* +* A helper function, XAxiDma_BdRingClone(), can speed up the BD ring setup if +* the BDs have same types of controls, for example, SOF and EOF. After +* using the XAxiDma_BdRingClone(), the application only needs to setup the +* buffer address and transfer length. Note that certain BDs in one packet, +* for example, the first BD and the last BD, may need to setup special +* control information. +* +* Descriptor Ring State Machine +* +* There are two states of the BD ring: +* +* - HALTED (H), where hardware is not running +* +* - NOT HALTED (NH), where hardware is running +* +* The following diagram shows the state transition for the DMA engine: +* +*
+*   _____ XAxiDma_StartBdRingHw(), or XAxiDma_BdRingStart(),   ______
+*   |   |               or XAxiDma_Resume()                    |    |
+*   | H |----------------------------------------------------->| NH |
+*   |   |<-----------------------------------------------------|    |
+*   -----   XAxiDma_Pause() or XAxiDma_Reset()                 ------
+* 
+* +* Interrupt Coalescing +* +* SGDMA provides control over the frequency of interrupts through interrupt +* coalescing. The DMA engine provides two ways to tune the interrupt +* coalescing: +* +* - The packet threshold counter. Interrupt will fire once the +* programmable number of packets have been processed by the engine. +* +* - The packet delay timer counter. Interrupt will fire once the +* programmable amount of time has passed after processing the last packet, +* and no new packets to process. Note that the interrupt will only fire if +* at least one packet has been processed. +* +* Interrupt +* +* Interrupts are handled by the user application. Each DMA channel has its own +* interrupt ID. The driver provides APIs to enable/disable interrupt, +* and tune the interrupt frequency regarding to packet processing frequency. +* +* Software Initialization +* +* +* To use the Simple mode DMA engine for transfers, the following setup is +* required: +* +* - DMA Initialization using XAxiDma_CfgInitialize() function. This step +* initializes a driver instance for the given DMA engine and resets the +* engine. +* +* - Enable interrupts if chosen to use interrupt mode. The application is +* responsible for setting up the interrupt system, which includes providing +* and connecting interrupt handlers and call back functions, before +* enabling the interrupts. +* +* - Set the buffer address and length field in respective channels to start +* the DMA transfer +* +* To use the SG mode DMA engine for transfers, the following setup are +* required: +* +* - DMA Initialization using XAxiDma_CfgInitialize() function. This step +* initializes a driver instance for the given DMA engine and resets the +* engine. +* +* - BD Ring creation. A BD ring is needed per DMA channel and can be built by +* calling XAxiDma_BdRingCreate(). +* +* - Enable interrupts if chose to use interrupt mode. The application is +* responsible for setting up the interrupt system, which includes providing +* and connecting interrupt handlers and call back functions, before +* enabling the interrupts. +* +* - Start a DMA transfer: Call XAxiDma_BdRingStart() to start a transfer for +* the first time or after a reset, and XAxiDma_BdRingToHw() if the channel +* is already started. Calling XAxiDma_BdRingToHw() when a DMA channel is not +* running will not put the BDs to the hardware, and the BDs will be processed +* later when the DMA channel is started through XAxiDma_BdRingStart(). +* +* How to start DMA transactions +* +* The user application uses XAxiDma_BdRingToHw() to submit BDs to the hardware +* to start DMA transfers. +* +* For both channels, if the DMA engine is currently stopped (using +* XAxiDma_Pause()), the newly added BDs will be accepted but not processed +* until the DMA engine is started, using XAxiDma_BdRingStart(), or resumed, +* using XAxiDma_Resume(). +* +* Software Post-Processing on completed DMA transactions +* +* If the interrupt system has been set up and the interrupts are enabled, +* a DMA channels notifies the software about the completion of a transfer +* through interrupts. Otherwise, the user application can poll for +* completions of the BDs, using XAxiDma_BdRingFromHw() or +* XAxiDma_BdHwCompleted(). +* +* - Once BDs are finished by a channel, the application first needs to fetch +* them from the channel using XAxiDma_BdRingFromHw(). +* +* - On the TX side, the application now could free the data buffers attached to +* those BDs as the data in the buffers has been transmitted. +* +* - On the RX side, the application now could use the received data in the +* buffers attached to those BDs. +* +* - For both channels, completed BDs need to be put back to the Free group +* using XAxiDma_BdRingFree(), so they can be used for future transactions. +* +* - On the RX side, it is the application's responsibility to have BDs ready +* to receive data at any time. Otherwise, the RX channel refuses to +* accept any data if it has no RX BDs. +* +* Examples +* +* We provide five examples to show how to use the driver API: +* - One for SG interrupt mode (xaxidma_example_sg_intr.c), multiple BD/packets transfer +* - One for SG polling mode (xaxidma_example_sg_poll.c), single BD transfer. +* - One for SG polling mode (xaxidma_poll_multi_pkts.c), multiple BD/packets transfer +* - One for simple polling mode (xaxidma_example_simple_poll.c) +* - One for simple Interrupt mode (xaxidma_example_simple_intr.c) +* +* Address Translation +* +* All buffer addresses and BD addresses for the hardware are physical +* addresses. The user application is responsible to provide physical buffer +* address for the BD upon BD ring creation. The user application accesses BD +* through its virtual addess. The driver maintains the address translation +* between the physical and virtual address for BDs. +* +* Cache Coherency +* +* This driver expects all application buffers attached to BDs to be in cache +* coherent memory. If cache is used in the system, buffers for transmit MUST +* be flushed from the cache before passing the associated BD to this driver. +* Buffers for receive MUST be invalidated before accessing the data. +* +* Alignment +* +* For BDs: +* +* Minimum alignment is defined by the constant XAXIDMA_BD_MINIMUM_ALIGNMENT. +* This is the smallest alignment allowed by both hardware and software for them +* to properly work. +* +* If the descriptor ring is to be placed in cached memory, alignment also MUST +* be at least the processor's cache-line size. Otherwise, system instability +* occurs. For alignment larger than the cache line size, multiple cache line +* size alignment is required. +* +* Aside from the initial creation of the descriptor ring (see +* XAxiDma_BdRingCreate()), there are no other run-time checks for proper +* alignment of BDs. +* +* For application data buffers: +* +* Application data buffers may reside on any alignment if DRE is built into the +* hardware. Otherwise, application data buffer must be word-aligned. The word +* is defined by XPAR_AXIDMA_0_M_AXIS_MM2S_TDATA_WIDTH for transmit and +* XPAR_AXIDMA_0_S_AXIS_S2MM_TDATA_WIDTH for receive. +* +* For scatter gather transfers that have more than one BDs in the chain of BDs, +* Each BD transfer length must be multiple of word too. Otherwise, internal +* error happens in the hardware. +* +* Error Handling +* +* The DMA engine will halt on all error conditions. It requires the software +* to do a reset before it can start process new transfer requests. +* +* Restart After Stopping +* +* After the DMA engine has been stopped (through reset or reset after an error) +* the software keeps track of the current BD pointer when reset happens, and +* processing of BDs can be resumed through XAxiDma_BdRingStart(). +* +* Limitations +* +* This driver does not have any mechanisms for mutual exclusion. It is up to +* the application to provide this protection. +* +* Hardware Defaults & Exclusive Use +* +* After the initialization or reset, the DMA engine is in the following +* default mode: +* - All interrupts are disabled. +* +* - Interrupt coalescing counter is 1. +* +* - The DMA engine is not running (halted). Each DMA channel is started +* separately, using XAxiDma_StartBdRingHw() if no BDs are setup for transfer +* yet, or XAxiDma_BdRingStart() otherwise. +* +* The driver has exclusive use of the registers and BDs. All accesses to the +* registers and BDs should go through the driver interface. +* +* Debug Print +* +* To see the debug print for the driver, please put "-DDEBUG" as the extra +* compiler flags in software platform settings. Also comment out the line in +* xdebug.h: "#undef DEBUG". +* +* Changes From v1.00a +* +* . We have changes return type for XAxiDma_BdSetBufAddr() from void to int +* . We added XAxiDma_LookupConfig() so that user does not need to look for the +* hardware settings anymore. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a jz   05/18/10 First release
+* 2.00a jz   08/10/10 Second release, added in xaxidma_g.c, xaxidma_sinit.c,
+*                     updated tcl file, added xaxidma_porting_guide.h
+* 3.00a jz   11/22/10 Support IP core parameters change
+* 4.00a rkv  02/22/11 Added support for simple DMA mode
+*		      New API added for simple DMA mode are
+*			- XAxiDma_Busy
+*			- XAxiDma_SimpleTransfer
+*		      New Macros added for simple DMA mode are
+* 			- XAxiDma_HasSg
+* 			- XAxiDma_IntrEnable
+* 			- XAxiDma_IntrGetEnabled
+* 			- XAxiDma_IntrDisable
+* 			- XAxiDma_IntrGetIrq
+* 			- XAxiDma_IntrAckIrq
+* 5.00a srt  08/25/11  Added support for memory barrier and modified
+*			Cache Macros to have a common API for Microblaze
+*			and Zynq.
+* 6.00a srt  01/24/12 Added support for Multi-Channel DMA mode.
+*		      - Changed APIs:
+*			* XAxiDma_GetRxRing(InstancePtr, RingIndex)
+*			* XAxiDma_Start(XAxiDma * InstancePtr, int RingIndex)
+*			* XAxiDma_Started(XAxiDma * InstancePtr, int RingIndex)
+*			* XAxiDma_Pause(XAxiDma * InstancePtr, int RingIndex)
+*			* XAxiDma_Resume(XAxiDma * InstancePtr, int RingIndex)
+*			* XAxiDma_SimpleTransfer(XAxiDma *InstancePtr,
+*        					u32 BuffAddr, u32 Length,
+*						int Direction, int RingIndex)
+*			* XAxiDma_StartBdRingHw(XAxiDma_BdRing * RingPtr,
+*					int RingIndex)
+*			* XAxiDma_BdRingStart(XAxiDma_BdRing * RingPtr,
+*						 int RingIndex)
+*			* XAxiDma_BdRingToHw(XAxiDma_BdRing * RingPtr,
+*        			int NumBd, XAxiDma_Bd * BdSetPtr, int RingIndex)
+*			* XAxiDma_BdRingDumpRegs(XAxiDma_BdRing * RingPtr,
+*						 int RingIndex)
+*			* XAxiDma_BdRingSnapShotCurrBd(XAxiDma_BdRing * RingPtr,
+*						 int RingIndex)
+*			* XAxiDma_BdSetLength(XAxiDma_Bd *BdPtr,
+*					u32 LenBytes, u32 LengthMask)
+*       		* XAxiDma_BdGetActualLength(BdPtr, LengthMask)
+*			* XAxiDma_BdGetLength(BdPtr, LengthMask)
+*		       - New APIs
+*			* XAxiDma_SelectKeyHole(XAxiDma *InstancePtr,
+*						int Direction, int Select)
+*			* XAxiDma_UpdateBdRingCDesc(XAxiDma_BdRing * RingPtr,
+*						int RingIndex)
+* 7.00a srt  06/18/12  All the APIs changed in v6_00_a are reverted back for
+*		       backward compatibility.
+*			- New API:
+*			  XAxiDma_GetRxIndexRing(InstancePtr, RingIndex)
+* 7.01a srt  10/26/12  - Fixed issue with driver as it fails with IP version
+*		         < 6.00a as the parameter C_NUM_*_CHANNELS is not
+*			 applicable.
+*		       - Changed the logic of MCDMA BD fields Set APIs, to
+*			 clear the field first and then set it.
+* 7.02a srt  01/23/13  Replaced *_TDATA_WIDTH parameters to *_DATA_WIDTH
+*		       (CR 691867)
+*		       Updated DDR base address for IPI designs (CR 703656).
+* 8.0   adk  19/12/13  Updated as per the New Tcl API's
+*	srt  01/29/14  Added support for Micro DMA Mode and cyclic mode of
+*		       operations.
+*		      - New APIs:
+*			* XAxiDma_SelectCyclicMode(XAxiDma *InstancePtr,
+*						int Direction, int Select)
+ *			* XAxiDma_BdSetBufAddrMicroMode(XAxiDma_Bd*, u32)
+* 8.1   adk  20/01/15  Added support for peripheral test. Created the self
+*		       test example to include it on peripheral test's(CR#823144).
+* 8.1   adk  29/01/15  Added the sefltest api (XAxiDma_Selftest) to the driver source files
+* 		      (xaxidma_selftest.c) and called this from the selftest example
+* 9.0 	adk  27/07/15  Added support for 64-bit Addressing.
+* 9.0   adk  19/08/15  Fixed CR#873125 DMA SG Mode example tests are failing on
+*		       HW in 2015.3.
+* 9.1   sk   11/10/15 Used UINTPTR instead of u32 for Baseaddress CR# 867425.
+* 9.3   adk  26/07/16 Reduce the size of the buffer descriptor to 64 bytes.
+*       ms   01/23/17 Modified xil_printf statement in main function for all
+*            examples to ensure that "Successfully ran" and "Failed" strings
+*            are available in all examples. This is a fix for CR-965028.
+*       ms   03/17/17 Added readme.txt file in examples folder for doxygen
+*                     generation.
+*       ms   04/05/17 Modified Comment lines in functions to recognize
+*                     it as documentation block and added tabspace at return
+*                     statements in functions of axidma examples for proper
+*                     documentation while generating doxygen.
+*                     Modified readme file in examples folder.
+* 9.4  adk   25/07/17 Added example for cyclic dma mode CR#974218.
+*      adk   08/08/17 Fixed CR#980607 Can't select individual AXI DMA code examples.
+*		      Fixed compilation warning in the driver
+* 9.5  adk   17/10/17 Fixed CR#987026 mulit packet example fails on A53.
+* 	     26/10/17 Fixed CR#987214 Fix race condition in the XAxiDma_Reset().
+*      rsp   11/01/17 Fixed CR#988210 Add interface to do config lookup based
+*                     on base address.
+*      adk   13/11/17 Fixed CR#989455 multi-channel interrupt example fails on A53.
+* 9.6  rsp   01/11/18 Fixed CR#976392 In XAxiDma struct use UINTPTR for RegBase.
+*                     In XAxiDma_LookupConfigBaseAddr() use UINTPTR for Baseaddr.
+* 9.7  rsp   04/25/18 Add SgLengthWidth member in dma config structure. CR #1000474
+* 
+* +******************************************************************************/ + +#ifndef XAXIDMA_H_ /* prevent circular inclusions */ +#define XAXIDMA_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ +#include "xaxidma_bdring.h" +#ifdef __MICROBLAZE__ +#include "xenv.h" +#else +#include +#include "xil_cache.h" +#endif + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + +/** + * The XAxiDma driver instance data. An instance must be allocated for each DMA + * engine in use. + */ +typedef struct XAxiDma { + UINTPTR RegBase; /* Virtual base address of DMA engine */ + + int HasMm2S; /* Has transmit channel */ + int HasS2Mm; /* Has receive channel */ + int Initialized; /* Driver has been initialized */ + int HasSg; + + XAxiDma_BdRing TxBdRing; /* BD container management for TX channel */ + XAxiDma_BdRing RxBdRing[16]; /* BD container management for RX channel */ + int TxNumChannels; + int RxNumChannels; + int MicroDmaMode; + int AddrWidth; /**< Address Width */ +} XAxiDma; + +/** + * The configuration structure for AXI DMA engine + * + * This structure passes the hardware building information to the driver + */ +typedef struct { + u32 DeviceId; + UINTPTR BaseAddr; + + int HasStsCntrlStrm; + int HasMm2S; + int HasMm2SDRE; + int Mm2SDataWidth; + int HasS2Mm; + int HasS2MmDRE; + int S2MmDataWidth; + int HasSg; + int Mm2sNumChannels; + int S2MmNumChannels; + int Mm2SBurstSize; + int S2MmBurstSize; + int MicroDmaMode; + int AddrWidth; /**< Address Width */ + int SgLengthWidth; +} XAxiDma_Config; + + +/***************** Macros (Inline Functions) Definitions *********************/ +/*****************************************************************************/ +/** +* Get Transmit (Tx) Ring ptr +* +* Warning: This has a different API than the LLDMA driver. It now returns +* the pointer to the BD ring. +* +* @param InstancePtr is a pointer to the DMA engine instance to be +* worked on. +* +* @return Pointer to the Tx Ring +* +* @note C-style signature: +* XAxiDma_BdRing * XAxiDma_GetTxRing(XAxiDma * InstancePtr) +* This function is used only when system is configured as SG mode +* +*****************************************************************************/ +#define XAxiDma_GetTxRing(InstancePtr) \ + (&((InstancePtr)->TxBdRing)) + +/*****************************************************************************/ +/** +* Get Receive (Rx) Ring ptr +* +* Warning: This has a different API than the LLDMA driver. It now returns +* the pointer to the BD ring. +* +* @param InstancePtr is a pointer to the DMA engine instance to be +* worked on. +* +* @return Pointer to the Rx Ring +* +* @note +* C-style signature: +* XAxiDma_BdRing * XAxiDma_GetRxRing(XAxiDma * InstancePtr) +* This function is used only when system is configured as SG mode +* +*****************************************************************************/ +#define XAxiDma_GetRxRing(InstancePtr) \ + (&((InstancePtr)->RxBdRing[0])) + +/*****************************************************************************/ +/** +* Get Receive (Rx) Ring ptr of a Index +* +* Warning: This has a different API than the LLDMA driver. It now returns +* the pointer to the BD ring. +* +* @param InstancePtr is a pointer to the DMA engine instance to be +* worked on. +* @param RingIndex is the channel Index. +* +* @return Pointer to the Rx Ring +* +* @note +* C-style signature: +* XAxiDma_BdRing * XAxiDma_GetRxIndexRing(XAxiDma * InstancePtr, + int RingIndex) +* This function is used only when system is configured as SG mode +* +*****************************************************************************/ +#define XAxiDma_GetRxIndexRing(InstancePtr, RingIndex) \ + (&((InstancePtr)->RxBdRing[RingIndex])) + +/*****************************************************************************/ +/** +* This function checks whether system is configured as Simple or +* Scatter Gather mode +* +* @param InstancePtr is a pointer to the DMA engine instance to be +* worked on. +* +* @return +* - TRUE if configured as SG mode +* - FALSE if configured as simple mode +* +* @note None +* +*****************************************************************************/ +#define XAxiDma_HasSg(InstancePtr) ((InstancePtr)->HasSg) ? TRUE : FALSE + +/*****************************************************************************/ +/** + * This function enables interrupts specified by the Mask in specified + * direction, Interrupts that are not in the mask are not affected. + * + * @param InstancePtr is the driver instance we are working on + * @param Mask is the mask for the interrupts to be enabled + * @param Direction is DMA transfer direction, valid values are + * - XAXIDMA_DMA_TO_DEVICE. + * - XAXIDMA_DEVICE_TO_DMA. + * @return None + * + * @note None + * + *****************************************************************************/ +#define XAxiDma_IntrEnable(InstancePtr, Mask, Direction) \ + XAxiDma_WriteReg((InstancePtr)->RegBase + \ + (XAXIDMA_RX_OFFSET * Direction), XAXIDMA_CR_OFFSET, \ + (XAxiDma_ReadReg((InstancePtr)->RegBase + \ + (XAXIDMA_RX_OFFSET * Direction), XAXIDMA_CR_OFFSET)) \ + | (Mask & XAXIDMA_IRQ_ALL_MASK)) + + +/*****************************************************************************/ +/** + * This function gets the mask for the interrupts that are currently enabled + * + * @param InstancePtr is the driver instance we are working on + * @param Direction is DMA transfer direction, valid values are + * - XAXIDMA_DMA_TO_DEVICE. + * - XAXIDMA_DEVICE_TO_DMA. + * + * @return The bit mask for the interrupts that are currently enabled + * + * @note None + * + *****************************************************************************/ +#define XAxiDma_IntrGetEnabled(InstancePtr, Direction) \ + XAxiDma_ReadReg((InstancePtr)->RegBase + \ + (XAXIDMA_RX_OFFSET * Direction), XAXIDMA_CR_OFFSET) &\ + XAXIDMA_IRQ_ALL_MASK) + + + +/*****************************************************************************/ +/** + * This function disables interrupts specified by the Mask. Interrupts that + * are not in the mask are not affected. + * + * @param InstancePtr is the driver instance we are working on + * @param Mask is the mask for the interrupts to be disabled + * @param Direction is DMA transfer direction, valid values are + * - XAXIDMA_DMA_TO_DEVICE. + * - XAXIDMA_DEVICE_TO_DMA. + * @return None + * + * @note None + * + *****************************************************************************/ + #define XAxiDma_IntrDisable(InstancePtr, Mask, Direction) \ + XAxiDma_WriteReg((InstancePtr)->RegBase + \ + (XAXIDMA_RX_OFFSET * Direction), XAXIDMA_CR_OFFSET, \ + (XAxiDma_ReadReg((InstancePtr)->RegBase + \ + (XAXIDMA_RX_OFFSET * Direction), XAXIDMA_CR_OFFSET)) \ + & ~(Mask & XAXIDMA_IRQ_ALL_MASK)) + + +/*****************************************************************************/ +/** + * This function gets the interrupts that are asserted. + * + * @param InstancePtr is the driver instance we are working on + * @param Direction is DMA transfer direction, valid values are + * - XAXIDMA_DMA_TO_DEVICE. + * - XAXIDMA_DEVICE_TO_DMA. + * + * @return The bit mask for the interrupts asserted. + * + * @note None + * + *****************************************************************************/ +#define XAxiDma_IntrGetIrq(InstancePtr, Direction) \ + (XAxiDma_ReadReg((InstancePtr)->RegBase + \ + (XAXIDMA_RX_OFFSET * Direction), XAXIDMA_SR_OFFSET) &\ + XAXIDMA_IRQ_ALL_MASK) + +/*****************************************************************************/ +/** + * This function acknowledges the interrupts that are specified in Mask + * + * @param InstancePtr is the driver instance we are working on + * @param Mask is the mask for the interrupts to be acknowledge + * @param Direction is DMA transfer direction, valid values are + * - XAXIDMA_DMA_TO_DEVICE. + * - XAXIDMA_DEVICE_TO_DMA. + * + * @return None + * + * @note None. + * + *****************************************************************************/ +#define XAxiDma_IntrAckIrq(InstancePtr, Mask, Direction) \ + XAxiDma_WriteReg((InstancePtr)->RegBase + \ + (XAXIDMA_RX_OFFSET * Direction), XAXIDMA_SR_OFFSET, \ + (Mask) & XAXIDMA_IRQ_ALL_MASK) + + + +/************************** Function Prototypes ******************************/ + +/* + * Initialization and control functions in xaxidma.c + */ +XAxiDma_Config *XAxiDma_LookupConfig(u32 DeviceId); +XAxiDma_Config *XAxiDma_LookupConfigBaseAddr(UINTPTR Baseaddr); +int XAxiDma_CfgInitialize(XAxiDma * InstancePtr, XAxiDma_Config *Config); +void XAxiDma_Reset(XAxiDma * InstancePtr); +int XAxiDma_ResetIsDone(XAxiDma * InstancePtr); +int XAxiDma_Pause(XAxiDma * InstancePtr); +int XAxiDma_Resume(XAxiDma * InstancePtr); +u32 XAxiDma_Busy(XAxiDma *InstancePtr,int Direction); +u32 XAxiDma_SimpleTransfer(XAxiDma *InstancePtr, UINTPTR BuffAddr, u32 Length, + int Direction); +int XAxiDma_SelectKeyHole(XAxiDma *InstancePtr, int Direction, int Select); +int XAxiDma_SelectCyclicMode(XAxiDma *InstancePtr, int Direction, int Select); +int XAxiDma_Selftest(XAxiDma * InstancePtr); +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/datalink814_sp/bsp/microblaze_ps/include/xaxidma_bd.h b/datalink814_sp/bsp/microblaze_ps/include/xaxidma_bd.h new file mode 100644 index 0000000..e17aa61 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/include/xaxidma_bd.h @@ -0,0 +1,696 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** + * + * @file xaxidma_bd.h +* @addtogroup axidma_v9_9 +* @{ + * + * Buffer descriptor (BD) management API. + * + * Buffer Descriptors + * + * A BD defines a DMA transaction (see "Transaction" section in xaxidma.h). + * All accesses to a BD go through this set of API. + * + * The XAxiDma_Bd structure defines a BD. The first XAXIDMA_BD_HW_NUM_BYTES + * are shared between hardware and software. + * + * Actual Transfer Length + * + * The actual transfer length for receive could be smaller than the requested + * transfer length. The hardware sets the actual transfer length in the + * completed BD. The API to retrieve the actual transfer length is + * XAxiDma_GetActualLength(). + * + * User IP words + * + * There are 5 user IP words in each BD. + * + * If hardware does not have the StsCntrl stream built in, then these words + * are not usable. Retrieving these words get a NULL pointer and setting + * these words results an error. + * + * Performance + * + * BDs are typically in a non-cached memory space. Reducing the number of + * I/O operations to BDs can improve overall performance of the DMA channel. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- ------------------------------------------------------
+ * 1.00a jz   05/18/10 First release
+ * 2.00a jz   08/10/10 Second release, added in xaxidma_g.c, xaxidma_sinit.c,
+ *                     updated tcl file, added xaxidma_porting_guide.h
+ * 3.00a jz   11/22/10 Support IP core parameters change
+ * 5.00a srt  08/25/11 Changed Cache Macros to have a common API for Zynq
+ *		           and Microblaze.
+ * 6.00a srt  01/24/12 Added APIs to support Multi-Channel DMA:
+ *			XAxiDma_BdSetTId()
+ *			XAxiDma_BdGetTId()
+ *			XAxiDma_BdSetTDest()
+ *			XAxiDma_BdGetTDest()
+ *			XAxiDma_BdSetTUser()
+ *			XAxiDma_BdGetTUser()
+ *			XAxiDma_BdSetARCache()
+ *			XAxiDma_BdGetARCache()
+ *			XAxiDma_BdSetARUser()
+ *			XAxiDma_BdGetARUser()
+ *			XAxiDma_BdSetStride()
+ *			XAxiDma_BdGetStride()
+ *			XAxiDma_BdSetVSize()
+ *			XAxiDma_BdGetVSize()
+ *			- Changed APIs
+ *			XAxiDma_BdGetActualLength(BdPtr, LengthMask)
+ *			XAxiDma_BdGetLength(BdPtr, LengthMask)
+ *			XAxiDma_BdSetLength(XAxiDma_Bd* BdPtr,
+ *					u32 LenBytes, u32 LengthMask)
+ * 7.01a srt  10/26/12  Changed the logic of MCDMA BD fields Set APIs, to
+ *			clear the field first and set it.
+ * 8.0   srt  01/29/14 Added support for Micro DMA Mode.
+ * 9.2   vak  15/04/16 Fixed compilation warnings in axidma driver
+ * 9.8   rsp  07/11/18 Fix cppcheck portability warnings. CR #1006164
+ *
+ * 
+ *****************************************************************************/ + +#ifndef XAXIDMA_BD_H_ /* To prevent circular inclusions */ +#define XAXIDMA_BD_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xaxidma_hw.h" +#include "xstatus.h" +#include "xdebug.h" +#include "xil_cache.h" + +#ifdef __MICROBLAZE__ +#include "xenv.h" +#else +#include +#endif + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/** + * The XAxiDma_Bd is the type for a buffer descriptor (BD). + */ + +typedef u32 XAxiDma_Bd[XAXIDMA_BD_NUM_WORDS]; + + +/***************** Macros (Inline Functions) Definitions *********************/ + +/****************************************************************************** + * Define methods to flush and invalidate cache for BDs should they be + * located in cached memory. + *****************************************************************************/ +#ifdef __aarch64__ +#define XAXIDMA_CACHE_FLUSH(BdPtr) +#define XAXIDMA_CACHE_INVALIDATE(BdPtr) +#else +#define XAXIDMA_CACHE_FLUSH(BdPtr) \ + Xil_DCacheFlushRange((UINTPTR)(BdPtr), XAXIDMA_BD_HW_NUM_BYTES) + +#define XAXIDMA_CACHE_INVALIDATE(BdPtr) \ + Xil_DCacheInvalidateRange((UINTPTR)(BdPtr), XAXIDMA_BD_HW_NUM_BYTES) +#endif + +/*****************************************************************************/ +/** +* +* Read the given Buffer Descriptor word. +* +* @param BaseAddress is the base address of the BD to read +* @param Offset is the word offset to be read +* +* @return The 32-bit value of the field +* +* @note +* C-style signature: +* u32 XAxiDma_BdRead(u32 BaseAddress, u32 Offset) +* +******************************************************************************/ +#define XAxiDma_BdRead(BaseAddress, Offset) \ + (*(u32 *)((UINTPTR)(BaseAddress) + (u32)(Offset))) + +/*****************************************************************************/ +/** +* +* Write the given Buffer Descriptor word. +* +* @param BaseAddress is the base address of the BD to write +* @param Offset is the word offset to be written +* @param Data is the 32-bit value to write to the field +* +* @return None. +* +* @note +* C-style signature: +* void XAxiDma_BdWrite(u32 BaseAddress, u32 RegOffset, u32 Data) +* +******************************************************************************/ +#define XAxiDma_BdWrite(BaseAddress, Offset, Data) \ + (*(u32 *)((UINTPTR)(void *)(BaseAddress) + (u32)(Offset))) = (u32)(Data) + +/*****************************************************************************/ +/** +* +* Write the given Buffer Descriptor word. +* +* @param BaseAddress is the base address of the BD to write +* @param Offset is the word offset to be written +* @param Data is the 64-bit value to write to the field +* +* @return None. +* +* @note +* C-style signature: +* void XAxiDma_BdWrite(u64 BaseAddress, u32 RegOffset, u64 Data) +* +******************************************************************************/ +#define XAxiDma_BdWrite64(BaseAddress, Offset, Data) \ + (*(u64 *)((UINTPTR)(void *)(BaseAddress) + (u32)(Offset))) = (u64)(Data) + +/*****************************************************************************/ +/** + * Zero out BD specific fields. BD fields that are for the BD ring or for the + * system hardware build information are not touched. + * + * @param BdPtr is the BD to operate on + * + * @return None + * + * @note + * C-style signature: + * void XAxiDma_BdClear(XAxiDma_Bd* BdPtr) + * + *****************************************************************************/ +#define XAxiDma_BdClear(BdPtr) \ + memset((void *)(((UINTPTR)(BdPtr)) + XAXIDMA_BD_START_CLEAR), 0, \ + XAXIDMA_BD_BYTES_TO_CLEAR) + +/*****************************************************************************/ +/** + * Get the control bits for the BD + * + * @param BdPtr is the BD to operate on + * + * @return The bit mask for the control of the BD + * + * @note + * C-style signature: + * u32 XAxiDma_BdGetCtrl(XAxiDma_Bd* BdPtr) + * + *****************************************************************************/ +#define XAxiDma_BdGetCtrl(BdPtr) \ + (XAxiDma_BdRead((BdPtr), XAXIDMA_BD_CTRL_LEN_OFFSET) \ + & XAXIDMA_BD_CTRL_ALL_MASK) +/*****************************************************************************/ +/** + * Retrieve the status of a BD + * + * @param BdPtr is the BD to operate on + * + * @return Word at offset XAXIDMA_BD_DMASR_OFFSET. Use XAXIDMA_BD_STS_*** + * values defined in xaxidma_hw.h to interpret the returned value + * + * @note + * C-style signature: + * u32 XAxiDma_BdGetSts(XAxiDma_Bd* BdPtr) + * + *****************************************************************************/ +#define XAxiDma_BdGetSts(BdPtr) \ + (XAxiDma_BdRead((BdPtr), XAXIDMA_BD_STS_OFFSET) & \ + XAXIDMA_BD_STS_ALL_MASK) +/*****************************************************************************/ +/** + * Retrieve the length field value from the given BD. The returned value is + * the same as what was written with XAxiDma_BdSetLength(). Note that in the + * this value does not reflect the real length of received data. + * See the comments of XAxiDma_BdSetLength() for more details. To obtain the + * actual transfer length, use XAxiDma_BdGetActualLength(). + * + * @param BdPtr is the BD to operate on. + * @param LengthMask is the Maximum Transfer Length. + * + * @return The length value set in the BD. + * + * @note + * C-style signature: + * u32 XAxiDma_BdGetLength(XAxiDma_Bd* BdPtr) + * + *****************************************************************************/ +#define XAxiDma_BdGetLength(BdPtr, LengthMask) \ + (XAxiDma_BdRead((BdPtr), XAXIDMA_BD_CTRL_LEN_OFFSET) & \ + LengthMask) + + +/*****************************************************************************/ +/** + * Set the ID field of the given BD. The ID is an arbitrary piece of data the + * application can associate with a specific BD. + * + * @param BdPtr is the BD to operate on + * @param Id is a 32 bit quantity to set in the BD + * + * @return None + * + * @note + * C-style signature: + * void XAxiDma_BdSetId(XAxiDma_Bd* BdPtr, void Id) + * + *****************************************************************************/ +#define XAxiDma_BdSetId(BdPtr, Id) \ + (XAxiDma_BdWrite((BdPtr), XAXIDMA_BD_ID_OFFSET, (UINTPTR)(Id))) + + +/*****************************************************************************/ +/** + * Retrieve the ID field of the given BD previously set with XAxiDma_BdSetId. + * + * @param BdPtr is the BD to operate on + * + * @return None + * + * @note + * C-style signature: + * u32 XAxiDma_BdGetId(XAxiDma_Bd* BdPtr) + * + *****************************************************************************/ +#define XAxiDma_BdGetId(BdPtr) (XAxiDma_BdRead((BdPtr), XAXIDMA_BD_ID_OFFSET)) + +/*****************************************************************************/ +/** + * Get the BD's buffer address + * + * @param BdPtr is the BD to operate on + * + * @return None + * + * @note + * C-style signature: + * u32 XAxiDma_BdGetBufAddr(XAxiDma_Bd* BdPtr) + * + *****************************************************************************/ +#define XAxiDma_BdGetBufAddr(BdPtr) \ + (XAxiDma_BdRead((BdPtr), XAXIDMA_BD_BUFA_OFFSET)) + +/*****************************************************************************/ +/** + * Check whether a BD has completed in hardware. This BD has been submitted + * to hardware. The application can use this function to poll for the + * completion of the BD. + * + * This function may not work if the BD is in cached memory. + * + * @param BdPtr is the BD to check on + * + * @return + * - 0 if not complete + * - XAXIDMA_BD_STS_COMPLETE_MASK if completed, may contain + * XAXIDMA_BD_STS_*_ERR_MASK bits. + * + * @note + * C-style signature: + * int XAxiDma_BdHwCompleted(XAxiDma_Bd* BdPtr) + * + *****************************************************************************/ +#define XAxiDma_BdHwCompleted(BdPtr) \ + (XAxiDma_BdRead((BdPtr), XAXIDMA_BD_STS_OFFSET) & \ + XAXIDMA_BD_STS_COMPLETE_MASK) + +/*****************************************************************************/ +/** + * Get the actual transfer length of a BD. The BD has completed in hw. + * + * This function may not work if the BD is in cached memory. + * + * @param BdPtr is the BD to check on + * @param LengthMask is the Maximum Transfer Length. + * + * @return None + * + * @note + * C-style signature: + * int XAxiDma_BdGetActualLength(XAxiDma_Bd* BdPtr) + * + *****************************************************************************/ +#define XAxiDma_BdGetActualLength(BdPtr, LengthMask) \ + (XAxiDma_BdRead((BdPtr), XAXIDMA_BD_STS_OFFSET) & \ + LengthMask) + +/*****************************************************************************/ +/** + * Set the TID field of the TX BD. + * Provides a stream identifier and can be used to differentiate between + * multiple streams of data that are being transferred across the same + * interface. + * + * @param BdPtr is the BD to operate on + * @param TId is a 8 bit quantity to set in the BD + * + * @return None + * + * @note + * C-style signature: + * void XAxiDma_BdSetTId(XAxiDma_Bd* BdPtr, void TId) + * + *****************************************************************************/ +#define XAxiDma_BdSetTId(BdPtr, TId) \ +{ \ + u32 val; \ + val = (XAxiDma_BdRead((BdPtr), XAXIDMA_BD_MCCTL_OFFSET) & \ + ~XAXIDMA_BD_TID_FIELD_MASK); \ + val |= ((u32)(TId) << XAXIDMA_BD_TID_FIELD_SHIFT); \ + XAxiDma_BdWrite((BdPtr), XAXIDMA_BD_MCCTL_OFFSET, val); \ +} + +/*****************************************************************************/ +/** + * Retrieve the TID field of the RX BD previously set with XAxiDma_BdSetTId. + * + * @param BdPtr is the BD to operate on + * + * @return None + * + * @note + * C-style signature: + * u32 XAxiDma_BdGetTId(XAxiDma_Bd* BdPtr) + * + *****************************************************************************/ +#define XAxiDma_BdGetTId(BdPtr) \ + ((XAxiDma_BdRead((BdPtr), XAXIDMA_BD_STS_OFFSET)) & \ + XAXIDMA_BD_TID_FIELD_MASK) + +/*****************************************************************************/ +/** + * Set the TDEST field of the TX BD. + * Provides coarse routing information for the data stream. + * + * @param BdPtr is the BD to operate on + * @param TDest is a 8 bit quantity to set in the BD + * + * @return None + * + * @note + * C-style signature: + * void XAxiDma_BdSetTDest(XAxiDma_Bd* BdPtr, void TDest) + * + *****************************************************************************/ +#define XAxiDma_BdSetTDest(BdPtr, TDest) \ +{ \ + u32 val; \ + val = (XAxiDma_BdRead((BdPtr), XAXIDMA_BD_MCCTL_OFFSET) & \ + ~XAXIDMA_BD_TDEST_FIELD_MASK); \ + val |= ((u32)(TDest) << XAXIDMA_BD_TDEST_FIELD_SHIFT); \ + XAxiDma_BdWrite((BdPtr), XAXIDMA_BD_MCCTL_OFFSET, val); \ +} + +/*****************************************************************************/ +/** + * Retrieve the TDest field of the RX BD previously set with i + * XAxiDma_BdSetTDest. + * + * @param BdPtr is the BD to operate on + * + * @return None + * + * @note + * C-style signature: + * u32 XAxiDma_BdGetTDest(XAxiDma_Bd* BdPtr) + * + *****************************************************************************/ +#define XAxiDma_BdGetTDest(BdPtr) \ + ((XAxiDma_BdRead((BdPtr), XAXIDMA_BD_STS_OFFSET)) & \ + XAXIDMA_BD_TDEST_FIELD_MASK) + +/*****************************************************************************/ +/** + * Set the TUSER field of the TX BD. + * User defined sideband signaling. + * + * @param BdPtr is the BD to operate on + * @param TUser is a 8 bit quantity to set in the BD + * + * @return None + * + * @note + * C-style signature: + * void XAxiDma_BdSetTUser(XAxiDma_Bd* BdPtr, void TUser) + * + *****************************************************************************/ +#define XAxiDma_BdSetTUser(BdPtr, TUser) \ +{ \ + u32 val; \ + val = (XAxiDma_BdRead((BdPtr), XAXIDMA_BD_MCCTL_OFFSET) & \ + ~XAXIDMA_BD_TUSER_FIELD_MASK); \ + val |= ((u32)(TUser) << XAXIDMA_BD_TUSER_FIELD_SHIFT); \ + XAxiDma_BdWrite((BdPtr), XAXIDMA_BD_MCCTL_OFFSET, val); \ +} + +/*****************************************************************************/ +/** + * Retrieve the TUSER field of the RX BD previously set with + * XAxiDma_BdSetTUser. + * + * @param BdPtr is the BD to operate on + * + * @return None + * + * @note + * C-style signature: + * u32 XAxiDma_BdGetTUser(XAxiDma_Bd* BdPtr) + * + *****************************************************************************/ +#define XAxiDma_BdGetTUser(BdPtr) \ + ((XAxiDma_BdRead((BdPtr), XAXIDMA_BD_STS_OFFSET)) & \ + XAXIDMA_BD_TUSER_FIELD_MASK) + +/*****************************************************************************/ +/** + * Set the ARCACHE field of the given BD. + * This signal provides additional information about the cacheable + * characteristics of the transfer. + * + * @param BdPtr is the BD to operate on + * @param ARCache is a 8 bit quantity to set in the BD + * + * @return None + * + * @note + * C-style signature: + * void XAxiDma_BdSetARCache(XAxiDma_Bd* BdPtr, void ARCache) + * + *****************************************************************************/ +#define XAxiDma_BdSetARCache(BdPtr, ARCache) \ +{ \ + u32 val; \ + val = (XAxiDma_BdRead((BdPtr), XAXIDMA_BD_MCCTL_OFFSET) & \ + ~XAXIDMA_BD_ARCACHE_FIELD_MASK); \ + val |= ((u32)(ARCache) << XAXIDMA_BD_ARCACHE_FIELD_SHIFT); \ + XAxiDma_BdWrite((BdPtr), XAXIDMA_BD_MCCTL_OFFSET, val); \ +} + +/*****************************************************************************/ +/** + * Retrieve the ARCACHE field of the given BD previously set with + * XAxiDma_BdSetARCache. + * + * @param BdPtr is the BD to operate on + * + * @return None + * + * @note + * C-style signature: + * u32 XAxiDma_BdGetARCache(XAxiDma_Bd* BdPtr) + * + *****************************************************************************/ +#define XAxiDma_BdGetARCache(BdPtr) \ + ((XAxiDma_BdRead((BdPtr), XAXIDMA_BD_MCCTL_OFFSET)) & \ + XAXIDMA_BD_ARCACHE_FIELD_MASK) + + +/*****************************************************************************/ +/** + * Set the ARUSER field of the given BD. + * Sideband signals used for user defined information. + * + * @param BdPtr is the BD to operate on + * @param ARUser is a 8 bit quantity to set in the BD + * + * @return None + * + * @note + * C-style signature: + * void XAxiDma_BdSetARUser(XAxiDma_Bd* BdPtr, void ARUser) + * + *****************************************************************************/ +#define XAxiDma_BdSetARUser(BdPtr, ARUser) \ +{ \ + u32 val; \ + val = (XAxiDma_BdRead((BdPtr), XAXIDMA_BD_MCCTL_OFFSET) & \ + ~XAXIDMA_BD_ARUSER_FIELD_MASK); \ + val |= ((u32)(ARUser) << XAXIDMA_BD_ARUSER_FIELD_SHIFT); \ + XAxiDma_BdWrite((BdPtr), XAXIDMA_BD_MCCTL_OFFSET, val); \ +} + + +/*****************************************************************************/ +/** + * Retrieve the ARUSER field of the given BD previously set with + * XAxiDma_BdSetARUser. + * + * @param BdPtr is the BD to operate on + * + * @return None + * + * @note + * C-style signature: + * u32 XAxiDma_BdGetARUser(XAxiDma_Bd* BdPtr) + * + *****************************************************************************/ +#define XAxiDma_BdGetARUser(BdPtr) \ + ((XAxiDma_BdRead((BdPtr), XAXIDMA_BD_MCCTL_OFFSET)) & \ + XAXIDMA_BD_ARUSER_FIELD_MASK) + +/*****************************************************************************/ +/** + * Set the STRIDE field of the given BD. + * It is the address distance between the first address of successive + * horizontal reads. + * + * @param BdPtr is the BD to operate on + * @param Stride is a 32 bit quantity to set in the BD + * + * @return None + * + * @note + * C-style signature: + * void XAxiDma_BdSetStride(XAxiDma_Bd* BdPtr, void Stride) + * + *****************************************************************************/ +#define XAxiDma_BdSetStride(BdPtr, Stride) \ +{ \ + u32 val; \ + val = (XAxiDma_BdRead((BdPtr), XAXIDMA_BD_STRIDE_VSIZE_OFFSET) & \ + ~XAXIDMA_BD_STRIDE_FIELD_MASK); \ + val |= ((u32)(Stride) << XAXIDMA_BD_STRIDE_FIELD_SHIFT); \ + XAxiDma_BdWrite((BdPtr), XAXIDMA_BD_STRIDE_VSIZE_OFFSET, val); \ +} + +/*****************************************************************************/ +/** + * Retrieve the STRIDE field of the given BD previously set with + * XAxiDma_BdSetStride. + * + * @param BdPtr is the BD to operate on + * + * @return None + * + * @note + * C-style signature: + * u32 XAxiDma_BdGetStride(XAxiDma_Bd* BdPtr) + * + *****************************************************************************/ +#define XAxiDma_BdGetStride(BdPtr) \ + ((XAxiDma_BdRead((BdPtr), XAXIDMA_BD_STRIDE_VSIZE_OFFSET)) & \ + XAXIDMA_BD_STRIDE_FIELD_MASK) + +/*****************************************************************************/ +/** + * Set the VSIZE field of the given BD. + * Number of horizontal lines for strided access. + * + * @param BdPtr is the BD to operate on + * @param VSize is a 32 bit quantity to set in the BD + * + * @return None + * + * @note + * C-style signature: + * void XAxiDma_BdSetVSize(XAxiDma_Bd* BdPtr, void VSize) + * + *****************************************************************************/ +#define XAxiDma_BdSetVSize(BdPtr, VSize) \ +{ \ + u32 val; \ + val = (XAxiDma_BdRead((BdPtr), XAXIDMA_BD_STRIDE_VSIZE_OFFSET) & \ + ~XAXIDMA_BD_VSIZE_FIELD_MASK); \ + val |= ((u32)(VSize) << XAXIDMA_BD_VSIZE_FIELD_SHIFT); \ + XAxiDma_BdWrite((BdPtr), XAXIDMA_BD_STRIDE_VSIZE_OFFSET, val); \ +} + +/*****************************************************************************/ +/** + * Retrieve the STRIDE field of the given BD previously set with + * XAxiDma_BdSetVSize. + * + * @param BdPtr is the BD to operate on + * + * @return None + * + * @note + * C-style signature: + * u32 XAxiDma_BdGetVSize(XAxiDma_Bd* BdPtr) + * + *****************************************************************************/ +#define XAxiDma_BdGetVSize(BdPtr) \ + ((XAxiDma_BdRead((BdPtr), XAXIDMA_BD_STRIDE_VSIZE_OFFSET)) & \ + XAXIDMA_BD_VSIZE_FIELD_MASK) + +/*****************************************************************************/ + +/************************** Function Prototypes ******************************/ + +int XAxiDma_BdSetLength(XAxiDma_Bd* BdPtr, u32 LenBytes, u32 LengthMask); +u32 XAxiDma_BdSetBufAddr(XAxiDma_Bd* BdPtr, UINTPTR Addr); +u32 XAxiDma_BdSetBufAddrMicroMode(XAxiDma_Bd* BdPtr, UINTPTR Addr); +int XAxiDma_BdSetAppWord(XAxiDma_Bd * BdPtr, int Offset, u32 Word); +u32 XAxiDma_BdGetAppWord(XAxiDma_Bd * BdPtr, int Offset, int *Valid); +void XAxiDma_BdSetCtrl(XAxiDma_Bd *BdPtr, u32 Data); + +/* Debug utility + */ +void XAxiDma_DumpBd(XAxiDma_Bd* BdPtr); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/datalink814_sp/bsp/microblaze_ps/include/xaxidma_bdring.h b/datalink814_sp/bsp/microblaze_ps/include/xaxidma_bdring.h new file mode 100644 index 0000000..75cf96c --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/include/xaxidma_bdring.h @@ -0,0 +1,542 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xaxidma_bdring.h +* @addtogroup axidma_v9_9 +* @{ +* +* This file contains DMA channel related structure and constant definition +* as well as function prototypes. Each DMA channel is managed by a Buffer +* Descriptor ring, and XAxiDma_BdRing is chosen as the symbol prefix used in +* this file. See xaxidma.h for more information on how a BD ring is managed. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a jz   05/18/10 First release
+* 2.00a jz   08/10/10 Second release, added in xaxidma_g.c, xaxidma_sinit.c,
+*                     updated tcl file, added xaxidma_porting_guide.h
+* 3.00a jz   11/22/10 Support IP core parameters change
+* 6.00a srt  01/24/12 Added support for Multi-Channel DMA.
+*		      - New API
+*			* XAxiDma_UpdateBdRingCDesc(XAxiDma_BdRing * RingPtr,
+*						int RingIndex)
+*		      - Changed APIs
+*			* XAxiDma_StartBdRingHw(XAxiDma_BdRing * RingPtr,
+*					int RingIndex)
+*			* XAxiDma_BdRingStart(XAxiDma_BdRing * RingPtr,
+*						 int RingIndex)
+*			* XAxiDma_BdRingToHw(XAxiDma_BdRing * RingPtr,
+*        			int NumBd, XAxiDma_Bd * BdSetPtr, int RingIndex)
+*			* XAxiDma_BdRingDumpRegs(XAxiDma_BdRing * RingPtr,
+*						 int RingIndex)
+*			* XAxiDma_BdRingSnapShotCurrBd(XAxiDma_BdRing * RingPtr,
+*						 int RingIndex)
+* 7.00a srt  06/18/12  All the APIs changed in v6_00_a are reverted back for
+*		       backward compatibility.
+* 9.2   vak  15/04/16  Fixed the compilation warnings in axidma driver
+* 9.7   rsp  01/11/18  Use UINTPTR instead of u32 for ChanBase CR#976392
+*
+* 
+* +******************************************************************************/ + +#ifndef XAXIDMA_BDRING_H_ /* prevent circular inclusions */ +#define XAXIDMA_BDRING_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xstatus.h" +#include "xaxidma_bd.h" +#include + +/************************** Constant Definitions *****************************/ +/* State of a DMA channel + */ +#define AXIDMA_CHANNEL_NOT_HALTED 1 +#define AXIDMA_CHANNEL_HALTED 2 + +/* Argument constant to simplify argument setting + */ +#define XAXIDMA_NO_CHANGE 0xFFFFFFFF +#define XAXIDMA_ALL_BDS 0x0FFFFFFF /* 268 Million */ + +/**************************** Type Definitions *******************************/ + +/** Container structure for descriptor storage control. If address translation + * is enabled, then all addresses and pointers excluding FirstBdPhysAddr are + * expressed in terms of the virtual address. + */ +typedef struct { + UINTPTR ChanBase; /**< physical base address*/ + + int IsRxChannel; /**< Is this a receive channel */ + volatile int RunState; /**< Whether channel is running */ + int HasStsCntrlStrm; /**< Whether has stscntrl stream */ + int HasDRE; + int DataWidth; + int Addr_ext; + u32 MaxTransferLen; + + UINTPTR FirstBdPhysAddr; /**< Physical address of 1st BD in list */ + UINTPTR FirstBdAddr; /**< Virtual address of 1st BD in list */ + UINTPTR LastBdAddr; /**< Virtual address of last BD in the list */ + u32 Length; /**< Total size of ring in bytes */ + UINTPTR Separation; /**< Number of bytes between the starting + address of adjacent BDs */ + XAxiDma_Bd *FreeHead; /**< First BD in the free group */ + XAxiDma_Bd *PreHead; /**< First BD in the pre-work group */ + XAxiDma_Bd *HwHead; /**< First BD in the work group */ + XAxiDma_Bd *HwTail; /**< Last BD in the work group */ + XAxiDma_Bd *PostHead; /**< First BD in the post-work group */ + XAxiDma_Bd *BdaRestart; /**< BD to load when channel is started */ + XAxiDma_Bd *CyclicBd; /**< Useful for Cyclic DMA operations */ + int FreeCnt; /**< Number of allocatable BDs in free group */ + int PreCnt; /**< Number of BDs in pre-work group */ + int HwCnt; /**< Number of BDs in work group */ + int PostCnt; /**< Number of BDs in post-work group */ + int AllCnt; /**< Total Number of BDs for channel */ + int RingIndex; /**< Ring Index */ + int Cyclic; /**< Check for cyclic DMA Mode */ +} XAxiDma_BdRing; + +/***************** Macros (Inline Functions) Definitions *********************/ + +/*****************************************************************************/ +/** +* Use this macro at initialization time to determine how many BDs will fit +* within the given memory constraints. +* +* The results of this macro can be provided to XAxiDma_BdRingCreate(). +* +* @param Alignment specifies what byte alignment the BDs must fall +* on and must be a power of 2 to get an accurate calculation +* (32, 64, 126,...) +* @param Bytes is the number of bytes to be used to store BDs. +* +* @return Number of BDs that can fit in the given memory area +* +* @note +* C-style signature: +* int XAxiDma_BdRingCntCalc(u32 Alignment, u32 Bytes) +* This function is used only when system is configured as SG mode +* +******************************************************************************/ +#define XAxiDma_BdRingCntCalc(Alignment, Bytes) \ + (uint32_t)((Bytes)/((sizeof(XAxiDma_Bd)+((Alignment)-1))&~((Alignment)-1))) + +/*****************************************************************************/ +/** +* Use this macro at initialization time to determine how many bytes of memory +* are required to contain a given number of BDs at a given alignment. +* +* @param Alignment specifies what byte alignment the BDs must fall on. +* This parameter must be a power of 2 to get an accurate +* calculation (32, 64,128,...) +* @param NumBd is the number of BDs to calculate memory size +* requirements +* +* @return The number of bytes of memory required to create a BD list +* with the given memory constraints. +* +* @note +* C-style signature: +* int XAxiDma_BdRingMemCalc(u32 Alignment, u32 NumBd) +* This function is used only when system is configured as SG mode +* +******************************************************************************/ +#define XAxiDma_BdRingMemCalc(Alignment, NumBd) \ + (int)((sizeof(XAxiDma_Bd)+((Alignment)-1)) & ~((Alignment)-1))*(NumBd) + +/****************************************************************************/ +/** +* Return the total number of BDs allocated by this channel with +* XAxiDma_BdRingCreate(). +* +* @param RingPtr is the BD ring to operate on. +* +* @return The total number of BDs allocated for this channel. +* +* @note +* C-style signature: +* int XAxiDma_BdRingGetCnt(XAxiDma_BdRing* RingPtr) +* This function is used only when system is configured as SG mode +* +*****************************************************************************/ +#define XAxiDma_BdRingGetCnt(RingPtr) ((RingPtr)->AllCnt) + +/****************************************************************************/ +/** +* Return the number of BDs allocatable with XAxiDma_BdRingAlloc() for pre- +* processing. +* +* @param RingPtr is the BD ring to operate on. +* +* @return The number of BDs currently allocatable. +* +* @note +* C-style signature: +* int XAxiDma_BdRingGetFreeCnt(XAxiDma_BdRing* RingPtr) +* This function is used only when system is configured as SG mode +* +*****************************************************************************/ +#define XAxiDma_BdRingGetFreeCnt(RingPtr) ((RingPtr)->FreeCnt) + + +/****************************************************************************/ +/** +* Snap shot the latest BD a BD ring is processing. +* +* @param RingPtr is the BD ring to operate on. +* +* @return None +* +* @note +* C-style signature: +* void XAxiDma_BdRingSnapShotCurrBd(XAxiDma_BdRing* RingPtr) +* This function is used only when system is configured as SG mode +* +*****************************************************************************/ +#define XAxiDma_BdRingSnapShotCurrBd(RingPtr) \ + { \ + if (!RingPtr->IsRxChannel) { \ + (RingPtr)->BdaRestart = \ + (XAxiDma_Bd *)(UINTPTR)XAxiDma_ReadReg( \ + (RingPtr)->ChanBase, \ + XAXIDMA_CDESC_OFFSET); \ + } else { \ + if (!RingPtr->RingIndex) { \ + (RingPtr)->BdaRestart = \ + (XAxiDma_Bd *)(UINTPTR)XAxiDma_ReadReg( \ + (RingPtr)->ChanBase, \ + XAXIDMA_CDESC_OFFSET); \ + } else { \ + (RingPtr)->BdaRestart = \ + (XAxiDma_Bd *)(UINTPTR)XAxiDma_ReadReg( \ + (RingPtr)->ChanBase, \ + (XAXIDMA_RX_CDESC0_OFFSET + \ + (RingPtr->RingIndex - 1) * \ + XAXIDMA_RX_NDESC_OFFSET)); \ + } \ + } \ + } + +/****************************************************************************/ +/** +* Get the BD a BD ring is processing. +* +* @param RingPtr is the BD ring to operate on. +* +* @return The current BD that the BD ring is working on +* +* @note +* C-style signature: +* XAxiDma_Bd * XAxiDma_BdRingGetCurrBd(XAxiDma_BdRing* RingPtr) +* This function is used only when system is configured as SG mode +* +*****************************************************************************/ +#define XAxiDma_BdRingGetCurrBd(RingPtr) \ + (XAxiDma_Bd *)XAxiDma_ReadReg((RingPtr)->ChanBase, \ + XAXIDMA_CDESC_OFFSET) \ + +/****************************************************************************/ +/** +* Return the next BD in the ring. +* +* @param RingPtr is the BD ring to operate on. +* @param BdPtr is the current BD. +* +* @return The next BD in the ring relative to the BdPtr parameter. +* +* @note +* C-style signature: +* XAxiDma_Bd *XAxiDma_BdRingNext(XAxiDma_BdRing* RingPtr, +* XAxiDma_Bd *BdPtr) +* This function is used only when system is configured as SG mode +* +*****************************************************************************/ +#define XAxiDma_BdRingNext(RingPtr, BdPtr) \ + (((UINTPTR)(BdPtr) >= (RingPtr)->LastBdAddr) ? \ + (UINTPTR)(RingPtr)->FirstBdAddr : \ + (UINTPTR)((UINTPTR)(BdPtr) + (RingPtr)->Separation)) + +/****************************************************************************/ +/** +* Return the previous BD in the ring. +* +* @param RingPtr is the DMA channel to operate on. +* @param BdPtr is the current BD. +* +* @return The previous BD in the ring relative to the BdPtr parameter. +* +* @note +* C-style signature: +* XAxiDma_Bd *XAxiDma_BdRingPrev(XAxiDma_BdRing* RingPtr, +* XAxiDma_Bd *BdPtr) +* This function is used only when system is configured as SG mode +* +*****************************************************************************/ +#define XAxiDma_BdRingPrev(RingPtr, BdPtr) \ + (((u32)(BdPtr) <= (RingPtr)->FirstBdAddr) ? \ + (XAxiDma_Bd*)(RingPtr)->LastBdAddr : \ + (XAxiDma_Bd*)((u32)(BdPtr) - (RingPtr)->Separation)) + +/****************************************************************************/ +/** +* Retrieve the contents of the channel status register +* +* @param RingPtr is the channel instance to operate on. +* +* @return Current contents of status register +* +* @note +* C-style signature: +* u32 XAxiDma_BdRingGetSr(XAxiDma_BdRing* RingPtr) +* This function is used only when system is configured as SG mode +* +*****************************************************************************/ +#define XAxiDma_BdRingGetSr(RingPtr) \ + XAxiDma_ReadReg((RingPtr)->ChanBase, XAXIDMA_SR_OFFSET) + +/****************************************************************************/ +/** +* Get error bits of a DMA channel +* +* @param RingPtr is the channel instance to operate on. +* +* @return Rrror bits in the status register, they should be interpreted +* with XAXIDMA_ERR_*_MASK defined in xaxidma_hw.h +* +* @note +* C-style signature: +* u32 XAxiDma_BdRingGetError(XAxiDma_BdRing* RingPtr) +* This function is used only when system is configured as SG mode +* +*****************************************************************************/ +#define XAxiDma_BdRingGetError(RingPtr) \ + (XAxiDma_ReadReg((RingPtr)->ChanBase, XAXIDMA_SR_OFFSET) \ + & XAXIDMA_ERR_ALL_MASK) + +/****************************************************************************/ +/** +* Check whether a DMA channel is started, meaning the channel is not halted. +* +* @param RingPtr is the channel instance to operate on. +* +* @return +* - 1 if channel is started +* - 0 otherwise +* +* @note +* C-style signature: +* int XAxiDma_BdRingHwIsStarted(XAxiDma_BdRing* RingPtr) +* +*****************************************************************************/ +#define XAxiDma_BdRingHwIsStarted(RingPtr) \ + ((XAxiDma_ReadReg((RingPtr)->ChanBase, XAXIDMA_SR_OFFSET) \ + & XAXIDMA_HALTED_MASK) ? FALSE : TRUE) + +/****************************************************************************/ +/** +* Check if the current DMA channel is busy with a DMA operation. +* +* @param RingPtr is the channel instance to operate on. +* +* @return +* - 1 if the DMA is busy. +* - 0 otherwise +* +* @note +* C-style signature: +* int XAxiDma_BdRingBusy(XAxiDma_BdRing* RingPtr) +* This function is used only when system is configured as SG mode +* +*****************************************************************************/ +#define XAxiDma_BdRingBusy(RingPtr) \ + (XAxiDma_BdRingHwIsStarted(RingPtr) && \ + ((XAxiDma_ReadReg((RingPtr)->ChanBase, XAXIDMA_SR_OFFSET) \ + & XAXIDMA_IDLE_MASK) ? FALSE : TRUE)) + +/****************************************************************************/ +/** +* Set interrupt enable bits for a channel. This operation will modify the +* XAXIDMA_CR_OFFSET register. +* +* @param RingPtr is the channel instance to operate on. +* @param Mask consists of the interrupt signals to enable.Bits not +* specified in the mask are not affected. +* +* @note +* C-style signature: +* void XAxiDma_BdRingIntEnable(XAxiDma_BdRing* RingPtr, u32 Mask) +* This function is used only when system is configured as SG mode +* +*****************************************************************************/ +#define XAxiDma_BdRingIntEnable(RingPtr, Mask) \ + (XAxiDma_WriteReg((RingPtr)->ChanBase, XAXIDMA_CR_OFFSET, \ + XAxiDma_ReadReg((RingPtr)->ChanBase, XAXIDMA_CR_OFFSET) \ + | ((Mask) & XAXIDMA_IRQ_ALL_MASK))) + +/****************************************************************************/ +/** +* Get enabled interrupts of a channel. It is in XAXIDMA_CR_OFFSET register. +* +* @param RingPtr is the channel instance to operate on. +* @return Enabled interrupts of a channel. Use XAXIDMA_IRQ_* defined in +* xaxidma_hw.h to interpret this returned value. +* +* @note +* C-style signature: +* u32 XAxiDma_BdRingIntGetEnabled(XAxiDma_BdRing* RingPtr) +* This function is used only when system is configured as SG mode +* +*****************************************************************************/ +#define XAxiDma_BdRingIntGetEnabled(RingPtr) \ + (XAxiDma_ReadReg((RingPtr)->ChanBase, XAXIDMA_CR_OFFSET) \ + & XAXIDMA_IRQ_ALL_MASK) + +/****************************************************************************/ +/** +* Clear interrupt enable bits for a channel. It modifies the +* XAXIDMA_CR_OFFSET register. +* +* @param RingPtr is the channel instance to operate on. +* @param Mask consists of the interrupt signals to disable.Bits not +* specified in the Mask are not affected. +* +* @note +* C-style signature: +* void XAxiDma_BdRingIntDisable(XAxiDma_BdRing* RingPtr, +* u32 Mask) +* This function is used only when system is configured as SG mode +* +*****************************************************************************/ +#define XAxiDma_BdRingIntDisable(RingPtr, Mask) \ + (XAxiDma_WriteReg((RingPtr)->ChanBase, XAXIDMA_CR_OFFSET, \ + XAxiDma_ReadReg((RingPtr)->ChanBase, XAXIDMA_CR_OFFSET) & \ + ~((Mask) & XAXIDMA_IRQ_ALL_MASK))) + +/****************************************************************************/ +/** +* Retrieve the contents of the channel's IRQ register XAXIDMA_SR_OFFSET. This +* operation can be used to see which interrupts are pending. +* +* @param RingPtr is the channel instance to operate on. +* +* @return Current contents of the IRQ_OFFSET register. Use +* XAXIDMA_IRQ_*** values defined in xaxidma_hw.h to interpret +* the returned value. +* +* @note +* C-style signature: +* u32 XAxiDma_BdRingGetIrq(XAxiDma_BdRing* RingPtr) +* This function is used only when system is configured as SG mode +* +*****************************************************************************/ +#define XAxiDma_BdRingGetIrq(RingPtr) \ + (XAxiDma_ReadReg((RingPtr)->ChanBase, XAXIDMA_SR_OFFSET) \ + & XAXIDMA_IRQ_ALL_MASK) + +/****************************************************************************/ +/** +* Acknowledge asserted interrupts. It modifies XAXIDMA_SR_OFFSET register. +* A mask bit set for an unasserted interrupt has no effect. +* +* @param RingPtr is the channel instance to operate on. +* @param Mask are the interrupt signals to acknowledge +* +* @note +* C-style signature: +* void XAxiDma_BdRingAckIrq(XAxiDma_BdRing* RingPtr) +* This function is used only when system is configured as SG mode +* +*****************************************************************************/ +#define XAxiDma_BdRingAckIrq(RingPtr, Mask) \ + XAxiDma_WriteReg((RingPtr)->ChanBase, XAXIDMA_SR_OFFSET,\ + (Mask) & XAXIDMA_IRQ_ALL_MASK) + +/****************************************************************************/ +/** +* Enable Cyclic DMA Mode. +* +* @param RingPtr is the channel instance to operate on. +* +* @note +* C-style signature: +* void XAxiDma_BdRingEnableCyclicDMA(XAxiDma_BdRing* RingPtr) +* This function is used only when system is configured as SG mode +* +*****************************************************************************/ +#define XAxiDma_BdRingEnableCyclicDMA(RingPtr) \ + (RingPtr->Cyclic = 1) + +/****************************************************************************/ + +/************************* Function Prototypes ******************************/ + +/* + * Descriptor ring functions xaxidma_bdring.c + */ +int XAxiDma_StartBdRingHw(XAxiDma_BdRing* RingPtr); +int XAxiDma_UpdateBdRingCDesc(XAxiDma_BdRing* RingPtr); +u32 XAxiDma_BdRingCreate(XAxiDma_BdRing * RingPtr, UINTPTR PhysAddr, + UINTPTR VirtAddr, u32 Alignment, int BdCount); +int XAxiDma_BdRingClone(XAxiDma_BdRing * RingPtr, XAxiDma_Bd * SrcBdPtr); +int XAxiDma_BdRingAlloc(XAxiDma_BdRing * RingPtr, int NumBd, + XAxiDma_Bd ** BdSetPtr); +int XAxiDma_BdRingUnAlloc(XAxiDma_BdRing * RingPtr, int NumBd, + XAxiDma_Bd * BdSetPtr); +int XAxiDma_BdRingToHw(XAxiDma_BdRing * RingPtr, int NumBd, + XAxiDma_Bd * BdSetPtr); +int XAxiDma_BdRingFromHw(XAxiDma_BdRing * RingPtr, int BdLimit, + XAxiDma_Bd ** BdSetPtr); +int XAxiDma_BdRingFree(XAxiDma_BdRing * RingPtr, int NumBd, + XAxiDma_Bd * BdSetPtr); +int XAxiDma_BdRingStart(XAxiDma_BdRing * RingPtr); +int XAxiDma_BdRingSetCoalesce(XAxiDma_BdRing * RingPtr, u32 Counter, u32 Timer); +void XAxiDma_BdRingGetCoalesce(XAxiDma_BdRing * RingPtr, + u32 *CounterPtr, u32 *TimerPtr); + +/* The following functions are for debug only + */ +int XAxiDma_BdRingCheck(XAxiDma_BdRing * RingPtr); +void XAxiDma_BdRingDumpRegs(XAxiDma_BdRing *RingPtr); +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/datalink814_sp/bsp/microblaze_ps/include/xaxidma_hw.h b/datalink814_sp/bsp/microblaze_ps/include/xaxidma_hw.h new file mode 100644 index 0000000..171fca6 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/include/xaxidma_hw.h @@ -0,0 +1,342 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** + * @file xaxidma_hw.h +* @addtogroup axidma_v9_9 +* @{ + * + * Hardware definition file. It defines the register interface and Buffer + * Descriptor (BD) definitions. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -------------------------------------------------------
+ * 1.00a jz   05/18/10 First release
+ * 2.00a jz   08/10/10 Second release, added in xaxidma_g.c, xaxidma_sinit.c,
+ *                     updated tcl file, added xaxidma_porting_guide.h
+ * 3.00a jz   11/22/10 Support IP core parameters change
+ * 4.00a rkv  02/22/11 Added support for simple DMA mode
+ * 6.00a srt  01/24/12 Added support for Multi-Channel DMA mode
+ * 8.0   srt  01/29/14 Added support for Micro DMA Mode and Cyclic mode of
+ *		       operations.
+ * 9.7   rsp  04/24/18 Added support for 64MB data transfer.Instead of #define
+ *                     read max buffer width from IP config.
+ *
+ * 
+ * + *****************************************************************************/ + +#ifndef XAXIDMA_HW_H_ /* prevent circular inclusions */ +#define XAXIDMA_HW_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "xil_types.h" +#include "xil_io.h" + +/************************** Constant Definitions *****************************/ + +/** @name DMA Transfer Direction + * @{ + */ +#define XAXIDMA_DMA_TO_DEVICE 0x00 +#define XAXIDMA_DEVICE_TO_DMA 0x01 + + +/** @name Buffer Descriptor Alignment + * @{ + */ +#define XAXIDMA_BD_MINIMUM_ALIGNMENT 0x40 /**< Minimum byte alignment + requirement for descriptors to + satisfy both hardware/software + needs */ +/*@}*/ + +/** @name Micro DMA Buffer Address Alignment + * @{ + */ +#define XAXIDMA_MICROMODE_MIN_BUF_ALIGN 0xFFF /**< Minimum byte alignment + requirement for buffer address + in Micro DMA mode */ +/*@}*/ + +/** @name Maximum transfer length + * This is determined by hardware + * @{ + */ +#define XAXIDMA_MCHAN_MAX_TRANSFER_LEN 0x00FFFF /* Max length MCDMA + hw supports */ +/*@}*/ + +/* Register offset definitions. Register accesses are 32-bit. + */ +/** @name Device registers + * Register sets on TX and RX channels are identical + * @{ + */ +#define XAXIDMA_TX_OFFSET 0x00000000 /**< TX channel registers base + * offset */ +#define XAXIDMA_RX_OFFSET 0x00000030 /**< RX channel registers base + * offset */ + +/* This set of registers are applicable for both channels. Add + * XAXIDMA_TX_OFFSET to get to TX channel, and XAXIDMA_RX_OFFSET to get to RX + * channel + */ +#define XAXIDMA_CR_OFFSET 0x00000000 /**< Channel control */ +#define XAXIDMA_SR_OFFSET 0x00000004 /**< Status */ +#define XAXIDMA_CDESC_OFFSET 0x00000008 /**< Current descriptor pointer */ +#define XAXIDMA_CDESC_MSB_OFFSET 0x0000000C /**< Current descriptor pointer */ +#define XAXIDMA_TDESC_OFFSET 0x00000010 /**< Tail descriptor pointer */ +#define XAXIDMA_TDESC_MSB_OFFSET 0x00000014 /**< Tail descriptor pointer */ +#define XAXIDMA_SRCADDR_OFFSET 0x00000018 /**< Simple mode source address + pointer */ +#define XAXIDMA_SRCADDR_MSB_OFFSET 0x0000001C /**< Simple mode source address + pointer */ +#define XAXIDMA_DESTADDR_OFFSET 0x00000018 /**< Simple mode destination address pointer */ +#define XAXIDMA_DESTADDR_MSB_OFFSET 0x0000001C /**< Simple mode destination address pointer */ +#define XAXIDMA_BUFFLEN_OFFSET 0x00000028 /**< Tail descriptor pointer */ +#define XAXIDMA_SGCTL_OFFSET 0x0000002c /**< SG Control Register */ + +/** Multi-Channel DMA Descriptor Offsets **/ +#define XAXIDMA_RX_CDESC0_OFFSET 0x00000040 /**< Rx Current Descriptor 0 */ +#define XAXIDMA_RX_CDESC0_MSB_OFFSET 0x00000044 /**< Rx Current Descriptor 0 */ +#define XAXIDMA_RX_TDESC0_OFFSET 0x00000048 /**< Rx Tail Descriptor 0 */ +#define XAXIDMA_RX_TDESC0_MSB_OFFSET 0x0000004C /**< Rx Tail Descriptor 0 */ +#define XAXIDMA_RX_NDESC_OFFSET 0x00000020 /**< Rx Next Descriptor Offset */ +/*@}*/ + +/** @name Bitmasks of XAXIDMA_CR_OFFSET register + * @{ + */ +#define XAXIDMA_CR_RUNSTOP_MASK 0x00000001 /**< Start/stop DMA channel */ +#define XAXIDMA_CR_RESET_MASK 0x00000004 /**< Reset DMA engine */ +#define XAXIDMA_CR_KEYHOLE_MASK 0x00000008 /**< Keyhole feature */ +#define XAXIDMA_CR_CYCLIC_MASK 0x00000010 /**< Cyclic Mode */ +/*@}*/ + +/** @name Bitmasks of XAXIDMA_SR_OFFSET register + * + * This register reports status of a DMA channel, including + * run/stop/idle state, errors, and interrupts (note that interrupt + * masks are shared with XAXIDMA_CR_OFFSET register, and are defined + * in the _IRQ_ section. + * + * The interrupt coalescing threshold value and delay counter value are + * also shared with XAXIDMA_CR_OFFSET register, and are defined in a + * later section. + * @{ + */ +#define XAXIDMA_HALTED_MASK 0x00000001 /**< DMA channel halted */ +#define XAXIDMA_IDLE_MASK 0x00000002 /**< DMA channel idle */ +#define XAXIDMA_ERR_INTERNAL_MASK 0x00000010 /**< Datamover internal + * err */ +#define XAXIDMA_ERR_SLAVE_MASK 0x00000020 /**< Datamover slave err */ +#define XAXIDMA_ERR_DECODE_MASK 0x00000040 /**< Datamover decode + * err */ +#define XAXIDMA_ERR_SG_INT_MASK 0x00000100 /**< SG internal err */ +#define XAXIDMA_ERR_SG_SLV_MASK 0x00000200 /**< SG slave err */ +#define XAXIDMA_ERR_SG_DEC_MASK 0x00000400 /**< SG decode err */ +#define XAXIDMA_ERR_ALL_MASK 0x00000770 /**< All errors */ + +/** @name Bitmask for interrupts + * These masks are shared by XAXIDMA_CR_OFFSET register and + * XAXIDMA_SR_OFFSET register + * @{ + */ +#define XAXIDMA_IRQ_IOC_MASK 0x00001000 /**< Completion intr */ +#define XAXIDMA_IRQ_DELAY_MASK 0x00002000 /**< Delay interrupt */ +#define XAXIDMA_IRQ_ERROR_MASK 0x00004000 /**< Error interrupt */ +#define XAXIDMA_IRQ_ALL_MASK 0x00007000 /**< All interrupts */ +/*@}*/ + +/** @name Bitmask and shift for delay and coalesce + * These masks are shared by XAXIDMA_CR_OFFSET register and + * XAXIDMA_SR_OFFSET register + * @{ + */ +#define XAXIDMA_DELAY_MASK 0xFF000000 /**< Delay timeout + * counter */ +#define XAXIDMA_COALESCE_MASK 0x00FF0000 /**< Coalesce counter */ + +#define XAXIDMA_DELAY_SHIFT 24 +#define XAXIDMA_COALESCE_SHIFT 16 +/*@}*/ + + +/* Buffer Descriptor (BD) definitions + */ + +/** @name Buffer Descriptor offsets + * USR* fields are defined by higher level IP. + * setup for EMAC type devices. The first 13 words are used by hardware. + * All words after the 13rd word are for software use only. + * @{ + */ +#define XAXIDMA_BD_NDESC_OFFSET 0x00 /**< Next descriptor pointer */ +#define XAXIDMA_BD_NDESC_MSB_OFFSET 0x04 /**< Next descriptor pointer */ +#define XAXIDMA_BD_BUFA_OFFSET 0x08 /**< Buffer address */ +#define XAXIDMA_BD_BUFA_MSB_OFFSET 0x0C /**< Buffer address */ +#define XAXIDMA_BD_MCCTL_OFFSET 0x10 /**< Multichannel Control Fields */ +#define XAXIDMA_BD_STRIDE_VSIZE_OFFSET 0x14 /**< 2D Transfer Sizes */ +#define XAXIDMA_BD_CTRL_LEN_OFFSET 0x18 /**< Control/buffer length */ +#define XAXIDMA_BD_STS_OFFSET 0x1C /**< Status */ + +#define XAXIDMA_BD_USR0_OFFSET 0x20 /**< User IP specific word0 */ +#define XAXIDMA_BD_USR1_OFFSET 0x24 /**< User IP specific word1 */ +#define XAXIDMA_BD_USR2_OFFSET 0x28 /**< User IP specific word2 */ +#define XAXIDMA_BD_USR3_OFFSET 0x2C /**< User IP specific word3 */ +#define XAXIDMA_BD_USR4_OFFSET 0x30 /**< User IP specific word4 */ + +#define XAXIDMA_BD_ID_OFFSET 0x34 /**< Sw ID */ +#define XAXIDMA_BD_HAS_STSCNTRL_OFFSET 0x38 /**< Whether has stscntrl strm */ +#define XAXIDMA_BD_HAS_DRE_OFFSET 0x3C /**< Whether has DRE */ + +#define XAXIDMA_BD_HAS_DRE_MASK 0xF00 /**< Whether has DRE mask */ +#define XAXIDMA_BD_WORDLEN_MASK 0xFF /**< Whether has DRE mask */ + +#define XAXIDMA_BD_HAS_DRE_SHIFT 8 /**< Whether has DRE shift */ +#define XAXIDMA_BD_WORDLEN_SHIFT 0 /**< Whether has DRE shift */ + +#define XAXIDMA_BD_START_CLEAR 8 /**< Offset to start clear */ +#define XAXIDMA_BD_BYTES_TO_CLEAR 48 /**< BD specific bytes to be + * cleared */ + +#define XAXIDMA_BD_NUM_WORDS 16U /**< Total number of words for + * one BD*/ +#define XAXIDMA_BD_HW_NUM_BYTES 52 /**< Number of bytes hw used */ + +/* The offset of the last app word. + */ +#define XAXIDMA_LAST_APPWORD 4 + +/*@}*/ +#define XAXIDMA_DESC_LSB_MASK (0xFFFFFFC0U) /**< LSB Address mask */ + +/** @name Bitmasks of XAXIDMA_BD_CTRL_OFFSET register + * @{ + */ +#define XAXIDMA_BD_CTRL_TXSOF_MASK 0x08000000 /**< First tx packet */ +#define XAXIDMA_BD_CTRL_TXEOF_MASK 0x04000000 /**< Last tx packet */ +#define XAXIDMA_BD_CTRL_ALL_MASK 0x0C000000 /**< All control bits */ +/*@}*/ + +/** @name Bitmasks of XAXIDMA_BD_STS_OFFSET register + * @{ + */ +#define XAXIDMA_BD_STS_COMPLETE_MASK 0x80000000 /**< Completed */ +#define XAXIDMA_BD_STS_DEC_ERR_MASK 0x40000000 /**< Decode error */ +#define XAXIDMA_BD_STS_SLV_ERR_MASK 0x20000000 /**< Slave error */ +#define XAXIDMA_BD_STS_INT_ERR_MASK 0x10000000 /**< Internal err */ +#define XAXIDMA_BD_STS_ALL_ERR_MASK 0x70000000 /**< All errors */ +#define XAXIDMA_BD_STS_RXSOF_MASK 0x08000000 /**< First rx pkt */ +#define XAXIDMA_BD_STS_RXEOF_MASK 0x04000000 /**< Last rx pkt */ +#define XAXIDMA_BD_STS_ALL_MASK 0xFC000000 /**< All status bits */ +/*@}*/ + +/** @name Bitmasks and shift values for XAXIDMA_BD_MCCTL_OFFSET register + * @{ + */ +#define XAXIDMA_BD_TDEST_FIELD_MASK 0x0000000F +#define XAXIDMA_BD_TID_FIELD_MASK 0x00000F00 +#define XAXIDMA_BD_TUSER_FIELD_MASK 0x000F0000 +#define XAXIDMA_BD_ARCACHE_FIELD_MASK 0x0F000000 +#define XAXIDMA_BD_ARUSER_FIELD_MASK 0xF0000000 + +#define XAXIDMA_BD_TDEST_FIELD_SHIFT 0 +#define XAXIDMA_BD_TID_FIELD_SHIFT 8 +#define XAXIDMA_BD_TUSER_FIELD_SHIFT 16 +#define XAXIDMA_BD_ARCACHE_FIELD_SHIFT 24 +#define XAXIDMA_BD_ARUSER_FIELD_SHIFT 28 +/*@}*/ + +/** @name Bitmasks and shift values for XAXIDMA_BD_STRIDE_VSIZE_OFFSET register + * @{ + */ +#define XAXIDMA_BD_STRIDE_FIELD_MASK 0x0000FFFF +#define XAXIDMA_BD_VSIZE_FIELD_MASK 0xFFF80000 + +#define XAXIDMA_BD_STRIDE_FIELD_SHIFT 0 +#define XAXIDMA_BD_VSIZE_FIELD_SHIFT 19 +/*@}*/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +#define XAxiDma_In32 Xil_In32 +#define XAxiDma_Out32 Xil_Out32 + +/*****************************************************************************/ +/** +* +* Read the given register. +* +* @param BaseAddress is the base address of the device +* @param RegOffset is the register offset to be read +* +* @return The 32-bit value of the register +* +* @note +* C-style signature: +* u32 XAxiDma_ReadReg(u32 BaseAddress, u32 RegOffset) +* +******************************************************************************/ +#define XAxiDma_ReadReg(BaseAddress, RegOffset) \ + XAxiDma_In32((BaseAddress) + (RegOffset)) + +/*****************************************************************************/ +/** +* +* Write the given register. +* +* @param BaseAddress is the base address of the device +* @param RegOffset is the register offset to be written +* @param Data is the 32-bit value to write to the register +* +* @return None. +* +* @note +* C-style signature: +* void XAxiDma_WriteReg(u32 BaseAddress, u32 RegOffset, u32 Data) +* +******************************************************************************/ +#define XAxiDma_WriteReg(BaseAddress, RegOffset, Data) \ + XAxiDma_Out32((BaseAddress) + (RegOffset), (Data)) + +#ifdef __cplusplus +} +#endif + +#endif +/** @} */ diff --git a/datalink814_sp/bsp/microblaze_ps/include/xaxidma_porting_guide.h b/datalink814_sp/bsp/microblaze_ps/include/xaxidma_porting_guide.h new file mode 100644 index 0000000..84875b1 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/include/xaxidma_porting_guide.h @@ -0,0 +1,250 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xaxidma_porting_guide.h +* @addtogroup axidma_v9_9 +* @{ +* +* This is a guide on how to move from using the xlldma driver to use xaxidma +* driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a jz   05/18/10 First release
+* 2.00a jz   08/10/10 Second release, added in xaxidma_g.c, xaxidma_sinit.c,
+*                     updated tcl file, added xaxidma_porting_guide.h
+* 4.00a rkv  02/22/11 Added support for simple DMA mode
+* 6.00a srt  03/27/12 Added support for MCDMA mode
+* 7.00a srt  06/18/12 API calls are reverted back for backward compatibility.
+*
+* 
+* +* Overview +* +* The API for xaxidma driver is similar to xlldma driver. The prefix for the +* API functions and structures is XAxiDma_ for the xaxidma driver. +* +* Due to hardware feature changes, signatures of some API functions are a +* little bit different from the xlldma API functions. +* +* We present API functions: +* - That only have prefix changes +* - That have different return type +* - That are new API functions +* - That have been removed +* +* Note that data structures have different prefix of XAxiDma_. Those API +* functions, that have data structures with prefix change, are considered as +* prefix change. +* +* API Functions That Only Have Prefix Changes +* +*
+*         xlldma driver              |         xaxidma driver (upto v5_00_a)
+* -----------------------------------------------------------------------
+*    XLlDma_Reset(...)               |  XAxiDma_Reset(...)
+*    XLlDma_BdRingSnapShotCurrBd(...)|  XAxiDma_BdRingSnapShotCurrBd(...)
+*    XLlDma_BdRingNext(...)          |  XAxiDma_BdRingNext(...)
+*    XLlDma_BdRingPrev(...)          |  XAxiDma_BdRingPrev(...)
+*    XLlDma_BdRingGetSr(...)         |  XAxiDma_BdRingGetSr(...)
+*    XLlDma_BdRingBusy(...)          |  XAxiDma_BdRingBusy(...)
+*    XLlDma_BdRingIntEnable(...)     |  XAxiDma_BdRingIntEnable(...)
+*    XLlDma_BdRingIntDisable(...)    |  XAxiDma_BdRingIntDisable(...)
+*    XLlDma_BdRingIntGetEnabled(...) |  XAxiDma_BdRingIntGetEnabled(...)
+*    XLlDma_BdRingGetIrq(...)        |  XAxiDma_BdRingGetIrq(...)
+*    XLlDma_BdRingAckIrq(...)        |  XAxiDma_BdRingAckIrq(...)
+*    XLlDma_BdRingCreate(...)        |  XAxiDma_BdRingCreate(...)
+*    XLlDma_BdRingClone(...)         |  XAxiDma_BdRingClone(...)
+*    XLlDma_BdRingAlloc(...)         |  XAxiDma_BdRingAlloc(...)
+*    XLlDma_BdRingUnAlloc(...)       |  XAxiDma_BdRingUnAlloc(...)
+*    XLlDma_BdRingToHw(...)          |  XAxiDma_BdRingToHw(...)
+*    XLlDma_BdRingFromHw(...)        |  XAxiDma_BdRingFromHw(...)
+*    XLlDma_BdRingFree(...)          |  XAxiDma_BdRingFree(...)
+*    XLlDma_BdRingStart(...)         |  XAxiDma_BdRingStart(...)
+*    XLlDma_BdRingCheck(...)         |  XAxiDma_BdRingCheck(...)
+*    XLlDma_BdRingSetCoalesce(...)   |  XAxiDma_BdRingSetCoalesce(...)
+*    XLlDma_BdRingGetCoalesce(...)   |  XAxiDma_BdRingGetCoalesce(...)
+*    XLlDma_BdRead(...)              |  XAxiDma_BdRead(...)
+*    XLlDma_BdWrite(...)             |  XAxiDma_BdWrite(...)
+*    XLlDma_BdClear(...)             |  XAxiDma_BdClear(...)
+*    XLlDma_BdSetId(...)             |  XAxiDma_BdSetId(...)
+*    XLlDma_BdGetId(...)             |  XAxiDma_BdGetId(...)
+*    XLlDma_BdGetLength(...)         |  XAxiDma_BdGetLength(...)
+*    XLlDma_BdGetBufAddr(...)        |  XAxiDma_BdGetBufAddr(...)
+*
+*
+* +* API Functions That Have Different Return Type +* +* Due to possible hardware failures, The caller should check the return value +* of the following functions. +* +*
+*         xlldma driver              |         xaxidma driver
+* -----------------------------------------------------------------------
+* void XLlDma_Pause(...)             | int XAxiDma_Pause(...)
+* void XLlDma_Resume(...)            | int XAxiDma_Resume(...)
+* 
+* +* The following functions have return type changed: +* +*
+*         xlldma driver              |         xaxidma driver
+* -----------------------------------------------------------------------
+* XLlDma_BdRing XLlDma_GetRxRing(...)| XAxiDma_BdRing * XAxiDma_GetRxRing(...)
+* XLlDma_BdRing XLlDma_GetTxRing(...)| XAxiDma_BdRing * XAxiDma_GetTxRing(...)
+* u32 XLlDma_BdRingMemCalc(...)      | int XAxiDma_BdRingMemCalc(...)
+* u32 XLlDma_BdRingCntCalc(...)      | int XAxiDma_BdRingCntCalc(...)
+* u32 XLlDma_BdRingGetCnt(...)       | int XAxiDma_BdRingGetCnt(...)
+* u32 XLlDma_BdRingGetFreeCnt(...)   | int XAxiDma_BdRingGetFreeCnt(...)
+* void XLlDma_BdSetLength(...)       | int XAxiDma_BdSetLength(...)
+* void XLlDma_BdSetBufAddr(...)      | int XAxiDma_BdSetBufAddr(...)
+*
+* +* API Functions That Are New API Functions +* +* Now that the AXI DMA core is a standalone core, some new API are intrduced. +* Some other functions are added due to hardware interface change, so to +* replace old API functions. +* +* - XAxiDma_Config *XAxiDma_LookupConfig(u32 DeviceId); +* - int XAxiDma_CfgInitialize(XAxiDma * InstancePtr, XAxiDma_Config *Config); +* - int XAxiDma_ResetIsDone(XAxiDma * InstancePtr); +* - XAxiDma_Bd * XAxiDma_BdRingGetCurrBd(XAxiDma_BdRing* RingPtr); +* - int XAxiDma_BdRingHwIsStarted(XAxiDma_BdRing* RingPtr); +* - void XAxiDma_BdRingDumpRegs(XAxiDma_BdRing *RingPtr); +* - int XAxiDma_StartBdRingHw(XAxiDma_BdRing* RingPtr); +* - void XAxiDma_BdSetCtrl(XAxiDma_Bd *BdPtr, u32 Data); +* - u32 XAxiDma_BdGetCtrl(XAxiDma_Bd* BdPtr); +* - u32 XAxiDma_BdGetSts(XAxiDma_Bd* BdPtr); +* - int XAxiDma_BdHwCompleted(XAxiDma_Bd* BdPtr); +* - int XAxiDma_BdGetActualLength(XAxiDma_Bd* BdPtr); +* - int XAxiDma_BdSetAppWord(XAxiDma_Bd * BdPtr, int Offset, u32 Word); +* - u32 XAxiDma_BdGetAppWord(XAxiDma_Bd * BdPtr, int Offset, int *Valid); +* +* API Functions That Have Been Removed +* +* Please see individual function comments for how to replace the removed API +* function with new API functions. +* +* - void XLlDma_Initialize(XLlDma * InstancePtr, u32 BaseAddress). +* This function is replaced by XAxiDma_LookupConfig()/XAxiDma_CfgInitialize() +* +* - u32 XLlDma_BdRingGetCr(XLlDma_BdRing* RingPtr). +* This is replaced by XAxiDma_BdRingGetError(XAxiDma_BdRing* RingPtr) +* +* - u32 XLlDma_BdRingSetCr(XLlDma_BdRing* RingPtr, u32 Data). +* This function is covered by other API functions: +* - void XAxiDma_BdRingIntEnable(XAxiDma_BdRing* RingPtr, u32 Mask) +* - void XAxiDma_BdRingIntDisable(XAxiDma_BdRing* RingPtr, u32 Mask) +* - int XAxiDma_BdRingSetCoalesce(XAxiDma_BdRing * RingPtr, u32 Counter, +* u32 Timer) +* +* - u32 XLlDma_BdSetStsCtrl(XLlDma_Bd* BdPtr, u32 Data). +* Replaced by XAxiDma_BdSetCtrl(XAxiDma_Bd *BdPtr, u32 Data); +* +* - u32 XLlDma_BdGetStsCtrl(XLlDma_Bd* BdPtr). +* Replaced by XAxiDma_BdGetCtrl(XAxiDma_Bd* BdPtr) and +* XAxiDma_BdGetSts(XAxiDma_Bd* BdPtr). +* +* API Functions That Have Been Added to support simple DMA mode +* +* - u32 XAxiDma_Busy(XAxiDma *InstancePtr,int Direction); +* - int XAxiDma_SimpleTransfer(XAxiDma *InstancePtr, u32 BuffAddr, int Length, +* int Direction); +* - XAxiDma_HasSg(InstancePtr); +* - XAxiDma_IntrEnable(InstancePtr,Mask,Direction); +* - XAxiDma_IntrGetEnabled(InstancePtr, Direction); +* - XAxiDma_IntrDisable(InstancePtr, Mask, Direction); +* - XAxiDma_IntrGetIrq(InstancePtr, Direction); +* - XAxiDma_IntrAckIrq(InstancePtr, Mask, Direction); +* +* For xaxidma driver v6_00_a Multiple Channel Support +* --------------------------------------------------- +* This driver supports Multi-channel mode and accordingly some APIs are +* changed to index multiple channels. Few new APIs are added. +* - Changed APIs +* * XAxiDma_GetRxRing(InstancePtr, RingIndex) +* * XAxiDma_Start(XAxiDma * InstancePtr, int RingIndex) +* * XAxiDma_Started(XAxiDma * InstancePtr, int RingIndex) +* * XAxiDma_Pause(XAxiDma * InstancePtr, int RingIndex) +* * XAxiDma_Resume(XAxiDma * InstancePtr, int RingIndex) +* * XAxiDma_SimpleTransfer(XAxiDma *InstancePtr, +* u32 BuffAddr, u32 Length, +* int Direction, int RingIndex) +* * XAxiDma_StartBdRingHw(XAxiDma_BdRing * RingPtr, +* int RingIndex) +* * XAxiDma_BdRingStart(XAxiDma_BdRing * RingPtr, +* int RingIndex) +* * XAxiDma_BdRingToHw(XAxiDma_BdRing * RingPtr, +* int NumBd, XAxiDma_Bd * BdSetPtr, int RingIndex) +* * XAxiDma_BdRingDumpRegs(XAxiDma_BdRing * RingPtr, +* int RingIndex) +* * XAxiDma_BdRingSnapShotCurrBd(XAxiDma_BdRing * RingPtr, +* int RingIndex) +* * XAxiDma_BdSetLength(XAxiDma_Bd *BdPtr, +* u32 LenBytes, u32 LengthMask) +* * XAxiDma_BdGetActualLength(BdPtr, LengthMask) +* * XAxiDma_BdGetLength(BdPtr, LengthMask) +* +* - New APIs +* * XAxiDma_SelectKeyHole(XAxiDma *InstancePtr, +* int Direction, int Select) +* * XAxiDma_UpdateBdRingCDesc(XAxiDma_BdRing * RingPtr, +* int RingIndex) +* * XAxiDma_BdSetTId() +* * XAxiDma_BdGetTId() +* * XAxiDma_BdSetTDest() +* * XAxiDma_BdGetTDest() +* * XAxiDma_BdSetTUser() +* * XAxiDma_BdGetTUser() +* * XAxiDma_BdSetARCache() +* * XAxiDma_BdGetARCache() +* * XAxiDma_BdSetARUser() +* * XAxiDma_BdGetARUser() +* * XAxiDma_BdSetStride() +* * XAxiDma_BdGetStride() +* * XAxiDma_BdSetVSize() +* * XAxiDma_BdGetVSize() +* For xaxidma driver v7_00_a +* --------------------------------------------------- +* - New API +* * XAxiDma_GetRxIndexRing(InstancePtr, RingIndex) +* +* - Changed APIs +* All the APIs changed in v6_00_a are reverted back for backward +* compatibility. +* +* +******************************************************************************/ +/** @} */ diff --git a/datalink814_sp/bsp/microblaze_ps/include/xbasic_types.h b/datalink814_sp/bsp/microblaze_ps/include/xbasic_types.h new file mode 100644 index 0000000..2d9b245 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/include/xbasic_types.h @@ -0,0 +1,127 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xbasic_types.h +* +* +* @note Dummy File for backwards compatibility +* + +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date   Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a adk   1/31/14  Added in bsp common folder for backward compatibility
+* 7.0   aru   01/21/19 Modified the typedef of u32,u16,u8
+* 7.0 	aru   02/06/19 Included stdint.h and stddef.h
+* 
+* +******************************************************************************/ + +#ifndef XBASIC_TYPES_H /* prevent circular inclusions */ +#define XBASIC_TYPES_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +/** @name Legacy types + * Deprecated legacy types. + * @{ + */ +typedef uint8_t Xuint8; /**< unsigned 8-bit */ +typedef char Xint8; /**< signed 8-bit */ +typedef uint16_t Xuint16; /**< unsigned 16-bit */ +typedef short Xint16; /**< signed 16-bit */ +typedef uint32_t Xuint32; /**< unsigned 32-bit */ +typedef long Xint32; /**< signed 32-bit */ +typedef float Xfloat32; /**< 32-bit floating point */ +typedef double Xfloat64; /**< 64-bit double precision FP */ +typedef unsigned long Xboolean; /**< boolean (XTRUE or XFALSE) */ + +#if !defined __XUINT64__ +typedef struct +{ + Xuint32 Upper; + Xuint32 Lower; +} Xuint64; +#endif + +/** @name New types + * New simple types. + * @{ + */ +#ifndef __KERNEL__ +#ifndef XIL_TYPES_H +typedef Xuint32 u32; +typedef Xuint16 u16; +typedef Xuint8 u8; +#endif +#else +#include +#endif + +#ifndef TRUE +# define TRUE 1U +#endif + +#ifndef FALSE +# define FALSE 0U +#endif + +#ifndef NULL +#define NULL 0U +#endif + +/* + * Xilinx NULL, TRUE and FALSE legacy support. Deprecated. + * Please use NULL, TRUE and FALSE + */ +#define XNULL NULL +#define XTRUE TRUE +#define XFALSE FALSE + +/* + * This file is deprecated and users + * should use xil_types.h and xil_assert.h\n\r + */ +#warning The xbasics_type.h file is deprecated and users should use xil_types.h and xil_assert. +#warning Please refer the Standalone BSP UG647 for further details + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ diff --git a/datalink814_sp/bsp/microblaze_ps/include/xbram.h b/datalink814_sp/bsp/microblaze_ps/include/xbram.h new file mode 100644 index 0000000..246df6d --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/include/xbram.h @@ -0,0 +1,223 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file xbram.h +* @addtogroup bram_v4_2 +* @{ +* @details +* +* If ECC is not enabled, this driver exists only to allow the tools to +* create a memory test application and to populate xparameters.h with memory +* range constants. In this case there is no source code. +* +* If ECC is enabled, this file contains the software API definition of the +* Xilinx BRAM Interface Controller (XBram) device driver. +* +* The Xilinx BRAM controller is a soft IP core designed for Xilinx +* FPGAs and contains the following general features: +* - LMB v2.0 bus interfaces with byte enable support +* - Used in conjunction with bram_block peripheral to provide fast BRAM +* memory solution for MicroBlaze ILMB and DLMB ports +* - Supports byte, half-word, and word transfers +* - Supports optional BRAM error correction and detection. +* +* The driver provides interrupt management functions. Implementation of +* interrupt handlers is left to the user. Refer to the provided interrupt +* example in the examples directory for details. +* +* This driver is intended to be RTOS and processor independent. Any needs for +* dynamic memory management, threads or thread mutual exclusion, virtual +* memory, or cache control must be satisfied by the layer above this driver. +* +* Initialization & Configuration +* +* The XBram_Config structure is used by the driver to configure +* itself. This configuration structure is typically created by the tool-chain +* based on HW build properties. +* +* To support multiple runtime loading and initialization strategies employed +* by various operating systems, the driver instance can be initialized as +* follows: +* +* - XBram_CfgInitialize(InstancePtr, CfgPtr, EffectiveAddr) - +* Uses a configuration structure provided by the caller. If running in a +* system with address translation, the provided virtual memory base address +* replaces the physical address present in the configuration structure. +* +* @note +* +* This API utilizes 32 bit I/O to the BRAM registers. With less +* than 32 bits, the unused bits from registers are read as zero and written as +* don't cares. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 3.00a sa  05/11/10 Added ECC support
+* 3.01a sa  01/13/12  Changed Selftest API from
+*		      XBram_SelfTest(XBram *InstancePtr) to
+*		      XBram_SelfTest(XBram *InstancePtr, u8 IntMask) and
+*		      fixed a problem with interrupt generation for CR 639274
+*		      Modified Selftest example to return XST_SUCCESS when
+*		      ECC is not enabled and return XST_FAILURE when ECC is
+*		      enabled and Control Base Address is zero (CR 636581)
+*		      Modified Selftest to use correct CorrectableCounterBits
+*		      for CR 635655
+*		      Updated to check CorrectableFailingDataRegs in the case
+*		      of LMB BRAM.
+* 		      Added CorrectableFailingDataRegs and
+*		      UncorrectableFailingDataRegs to the config structure to
+*		      distinguish between AXI BRAM and LMB BRAM.
+*		      These registers are not present in the current version of
+*		      the AXI BRAM Controller.
+* 3.02a sa 04/16/12   Added test of byte and halfword read-modify-write
+* 3.02a sa 04/16/12   Modified driver tcl to sort the address parameters
+*  	       	      to support both xps and vivado designs.
+* 3.02a adk 24/4/13   Modified the tcl file to avoid warnings
+*	       	      when ecc is disabled cr:705002.
+* 3.03a bss 05/22/13  Added Xil_DCacheFlushRange in xbram_selftest.c to
+*		      flush the Cache after writing to BRAM in InjectErrors
+*		      API(CR #719011)
+* 4.0   adk  19/12/13 Updated as per the New Tcl API's
+* 4.1   sk   11/10/15 Used UINTPTR instead of u32 for Baseaddress CR# 867425.
+*                     Changed the prototype of XBram_CfgInitialize API.
+*       ms  01/23/17 Modified xil_printf statement in main function for all
+*                    examples to ensure that "Successfully ran" and "Failed"
+*                    strings are available in all examples. This is a fix
+*                    for CR-965028.
+*       ms  03/17/17 Added readme.txt file in examples folder for doxygen
+*                    generation.
+* 4.2   ms  04/18/17 Modified tcl file to add suffix U for all macro
+*                    definitions of bram in xparameters.h
+*       ms  08/07/17 Fixed compilation warnings in xbram_sinit.c
+* 4.3   aru 03/23/19 Used UINTPTR instead of u32 for MemBaseAddress and
+*                    MemHighAddress.
+* 
+*****************************************************************************/ +#ifndef XBRAM_H /* prevent circular inclusions */ +#define XBRAM_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files ********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xstatus.h" +#include "xbram_hw.h" + +/************************** Constant Definitions ****************************/ + + +/**************************** Type Definitions ******************************/ + +/** + * This typedef contains configuration information for the device. + */ +typedef struct { + u16 DeviceId; /**< Unique ID of device */ + u32 DataWidth; /**< BRAM data width */ + int EccPresent; /**< Is ECC supported in H/W */ + int FaultInjectionPresent; /**< Is Fault Injection + * supported in H/W */ + int CorrectableFailingRegisters; /**< Is Correctable Failing Registers + * supported in H/W */ + int CorrectableFailingDataRegs; /**< Is Correctable Failing Data + * Registers supported in H/W */ + int UncorrectableFailingRegisters; /**< Is Un-correctable Failing + * Registers supported in H/W */ + int UncorrectableFailingDataRegs; /**< Is Un-correctable Failing Data + * Registers supported in H/W */ + int EccStatusInterruptPresent; /**< Are ECC status and interrupts + * supported in H/W */ + int CorrectableCounterBits; /**< Number of bits in the + * Correctable Error Counter */ + int EccOnOffRegister; /**< Is ECC on/off register supported + * in h/w */ + int EccOnOffResetValue; /**< Reset value of the ECC on/off + * register in h/w */ + int WriteAccess; /**< Is write access enabled in + * h/w */ + UINTPTR MemBaseAddress; /**< Device memory base address */ + UINTPTR MemHighAddress; /**< Device memory high address */ + UINTPTR CtrlBaseAddress; /**< Device register base address.*/ + UINTPTR CtrlHighAddress; /**< Device register base address.*/ +} XBram_Config; + +/** + * The XBram driver instance data. The user is required to + * allocate a variable of this type for every BRAM device in the + * system. A pointer to a variable of this type is then passed to the driver + * API functions. + */ +typedef struct { + XBram_Config Config; /* BRAM config structure */ + u32 IsReady; /* Device is initialized and ready */ +} XBram; + +/***************** Macros (Inline Functions) Definitions ********************/ + + +/************************** Function Prototypes *****************************/ + +/* + * Functions in xbram_sinit.c + */ +XBram_Config *XBram_LookupConfig(u16 DeviceId); + +/* + * Functions implemented in xbram.c + */ +int XBram_CfgInitialize(XBram *InstancePtr, XBram_Config *Config, + UINTPTR EffectiveAddr); + +/* + * Functions implemented in xbram_selftest.c + */ +int XBram_SelfTest(XBram *InstancePtr, u8 IntMask); + +/* + * Functions implemented in xbram_intr.c + */ +void XBram_InterruptEnable(XBram *InstancePtr, u32 Mask); +void XBram_InterruptDisable(XBram *InstancePtr, u32 Mask); +void XBram_InterruptClear(XBram *InstancePtr, u32 Mask); +u32 XBram_InterruptGetEnabled(XBram *InstancePtr); +u32 XBram_InterruptGetStatus(XBram *InstancePtr); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/datalink814_sp/bsp/microblaze_ps/include/xbram_hw.h b/datalink814_sp/bsp/microblaze_ps/include/xbram_hw.h new file mode 100644 index 0000000..55a2505 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/include/xbram_hw.h @@ -0,0 +1,405 @@ +/****************************************************************************** +* +* Copyright (C) 2011 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xbram_hw.h +* @addtogroup bram_v4_2 +* @{ +* +* This header file contains identifiers and driver functions (or +* macros) that can be used to access the device. The user should refer to the +* hardware device specification for more details of the device operation. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a sa   24/11/10 First release
+* 
+* +******************************************************************************/ +#ifndef XBRAM_HW_H /* prevent circular inclusions */ +#define XBRAM_HW_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_io.h" + +/************************** Constant Definitions *****************************/ + +/** @name Registers + * + * Register offsets for this device. + * @{ + */ + +#define XBRAM_ECC_STATUS_OFFSET 0x0 /**< ECC status Register */ +#define XBRAM_ECC_EN_IRQ_OFFSET 0x4 /**< ECC interrupt enable Register */ +#define XBRAM_ECC_ON_OFF_OFFSET 0x8 /**< ECC on/off register */ +#define XBRAM_CE_CNT_OFFSET 0xC /**< Correctable error counter Register */ + +#define XBRAM_CE_FFD_0_OFFSET 0x100 /**< Correctable error first failing + * data Register, 31-0 */ +#define XBRAM_CE_FFD_1_OFFSET 0x104 /**< Correctable error first failing + * data Register, 63-32 */ +#define XBRAM_CE_FFD_2_OFFSET 0x108 /**< Correctable error first failing + * data Register, 95-64 */ +#define XBRAM_CE_FFD_3_OFFSET 0x10C /**< Correctable error first failing + * data Register, 127-96 */ +#define XBRAM_CE_FFD_4_OFFSET 0x110 /**< Correctable error first failing + * data Register, 159-128 */ +#define XBRAM_CE_FFD_5_OFFSET 0x114 /**< Correctable error first failing + * data Register, 191-160 */ +#define XBRAM_CE_FFD_6_OFFSET 0x118 /**< Correctable error first failing + * data Register, 223-192 */ +#define XBRAM_CE_FFD_7_OFFSET 0x11C /**< Correctable error first failing + * data Register, 255-224 */ +#define XBRAM_CE_FFD_8_OFFSET 0x120 /**< Correctable error first failing + * data Register, 287-256 */ +#define XBRAM_CE_FFD_9_OFFSET 0x124 /**< Correctable error first failing + * data Register, 319-288 */ +#define XBRAM_CE_FFD_10_OFFSET 0x128 /**< Correctable error first failing + * data Register, 351-320 */ +#define XBRAM_CE_FFD_11_OFFSET 0x12C /**< Correctable error first failing + * data Register, 383-352 */ +#define XBRAM_CE_FFD_12_OFFSET 0x130 /**< Correctable error first failing + * data Register, 415-384 */ +#define XBRAM_CE_FFD_13_OFFSET 0x134 /**< Correctable error first failing + * data Register, 447-416 */ +#define XBRAM_CE_FFD_14_OFFSET 0x138 /**< Correctable error first failing + * data Register, 479-448 */ +#define XBRAM_CE_FFD_15_OFFSET 0x13C /**< Correctable error first failing + * data Register, 511-480 */ +#define XBRAM_CE_FFD_16_OFFSET 0x140 /**< Correctable error first failing + * data Register, 543-512 */ +#define XBRAM_CE_FFD_17_OFFSET 0x144 /**< Correctable error first failing + * data Register, 575-544 */ +#define XBRAM_CE_FFD_18_OFFSET 0x148 /**< Correctable error first failing + * data Register, 607-576 */ +#define XBRAM_CE_FFD_19_OFFSET 0x14C /**< Correctable error first failing + * data Register, 639-608 */ +#define XBRAM_CE_FFD_20_OFFSET 0x150 /**< Correctable error first failing + * data Register, 671-640 */ +#define XBRAM_CE_FFD_21_OFFSET 0x154 /**< Correctable error first failing + * data Register, 703-672 */ +#define XBRAM_CE_FFD_22_OFFSET 0x158 /**< Correctable error first failing + * data Register, 735-704 */ +#define XBRAM_CE_FFD_23_OFFSET 0x15C /**< Correctable error first failing + * data Register, 767-736 */ +#define XBRAM_CE_FFD_24_OFFSET 0x160 /**< Correctable error first failing + * data Register, 799-768 */ +#define XBRAM_CE_FFD_25_OFFSET 0x164 /**< Correctable error first failing + * data Register, 831-800 */ +#define XBRAM_CE_FFD_26_OFFSET 0x168 /**< Correctable error first failing + * data Register, 863-832 */ +#define XBRAM_CE_FFD_27_OFFSET 0x16C /**< Correctable error first failing + * data Register, 895-864 */ +#define XBRAM_CE_FFD_28_OFFSET 0x170 /**< Correctable error first failing + * data Register, 927-896 */ +#define XBRAM_CE_FFD_29_OFFSET 0x174 /**< Correctable error first failing + * data Register, 959-928 */ +#define XBRAM_CE_FFD_30_OFFSET 0x178 /**< Correctable error first failing + * data Register, 991-960 */ +#define XBRAM_CE_FFD_31_OFFSET 0x17C /**< Correctable error first failing + * data Register, 1023-992 */ + +#define XBRAM_CE_FFE_0_OFFSET 0x180 /**< Correctable error first failing + * ECC Register, 31-0 */ +#define XBRAM_CE_FFE_1_OFFSET 0x184 /**< Correctable error first failing + * ECC Register, 63-32 */ +#define XBRAM_CE_FFE_2_OFFSET 0x188 /**< Correctable error first failing + * ECC Register, 95-64 */ +#define XBRAM_CE_FFE_3_OFFSET 0x18C /**< Correctable error first failing + * ECC Register, 127-96 */ +#define XBRAM_CE_FFE_4_OFFSET 0x190 /**< Correctable error first failing + * ECC Register, 159-128 */ +#define XBRAM_CE_FFE_5_OFFSET 0x194 /**< Correctable error first failing + * ECC Register, 191-160 */ +#define XBRAM_CE_FFE_6_OFFSET 0x198 /**< Correctable error first failing + * ECC Register, 223-192 */ +#define XBRAM_CE_FFE_7_OFFSET 0x19C /**< Correctable error first failing + * ECC Register, 255-224 */ + +#define XBRAM_CE_FFA_0_OFFSET 0x1C0 /**< Correctable error first failing + * address Register 31-0 */ +#define XBRAM_CE_FFA_1_OFFSET 0x1C4 /**< Correctable error first failing + * address Register 63-32 */ + +#define XBRAM_UE_FFD_0_OFFSET 0x200 /**< Uncorrectable error first failing + * data Register, 31-0 */ +#define XBRAM_UE_FFD_1_OFFSET 0x204 /**< Uncorrectable error first failing + * data Register, 63-32 */ +#define XBRAM_UE_FFD_2_OFFSET 0x208 /**< Uncorrectable error first failing + * data Register, 95-64 */ +#define XBRAM_UE_FFD_3_OFFSET 0x20C /**< Uncorrectable error first failing + * data Register, 127-96 */ +#define XBRAM_UE_FFD_4_OFFSET 0x210 /**< Uncorrectable error first failing + * data Register, 159-128 */ +#define XBRAM_UE_FFD_5_OFFSET 0x214 /**< Uncorrectable error first failing + * data Register, 191-160 */ +#define XBRAM_UE_FFD_6_OFFSET 0x218 /**< Uncorrectable error first failing + * data Register, 223-192 */ +#define XBRAM_UE_FFD_7_OFFSET 0x21C /**< Uncorrectable error first failing + * data Register, 255-224 */ +#define XBRAM_UE_FFD_8_OFFSET 0x220 /**< Uncorrectable error first failing + * data Register, 287-256 */ +#define XBRAM_UE_FFD_9_OFFSET 0x224 /**< Uncorrectable error first failing + * data Register, 319-288 */ +#define XBRAM_UE_FFD_10_OFFSET 0x228 /**< Uncorrectable error first failing + * data Register, 351-320 */ +#define XBRAM_UE_FFD_11_OFFSET 0x22C /**< Uncorrectable error first failing + * data Register, 383-352 */ +#define XBRAM_UE_FFD_12_OFFSET 0x230 /**< Uncorrectable error first failing + * data Register, 415-384 */ +#define XBRAM_UE_FFD_13_OFFSET 0x234 /**< Uncorrectable error first failing + * data Register, 447-416 */ +#define XBRAM_UE_FFD_14_OFFSET 0x238 /**< Uncorrectable error first failing + * data Register, 479-448 */ +#define XBRAM_UE_FFD_15_OFFSET 0x23C /**< Uncorrectable error first failing + * data Register, 511-480 */ +#define XBRAM_UE_FFD_16_OFFSET 0x240 /**< Uncorrectable error first failing + * data Register, 543-512 */ +#define XBRAM_UE_FFD_17_OFFSET 0x244 /**< Uncorrectable error first failing + * data Register, 575-544 */ +#define XBRAM_UE_FFD_18_OFFSET 0x248 /**< Uncorrectable error first failing + * data Register, 607-576 */ +#define XBRAM_UE_FFD_19_OFFSET 0x24C /**< Uncorrectable error first failing + * data Register, 639-608 */ +#define XBRAM_UE_FFD_20_OFFSET 0x250 /**< Uncorrectable error first failing + * data Register, 671-640 */ +#define XBRAM_UE_FFD_21_OFFSET 0x254 /**< Uncorrectable error first failing + * data Register, 703-672 */ +#define XBRAM_UE_FFD_22_OFFSET 0x258 /**< Uncorrectable error first failing + * data Register, 735-704 */ +#define XBRAM_UE_FFD_23_OFFSET 0x25C /**< Uncorrectable error first failing + * data Register, 767-736 */ +#define XBRAM_UE_FFD_24_OFFSET 0x260 /**< Uncorrectable error first failing + * data Register, 799-768 */ +#define XBRAM_UE_FFD_25_OFFSET 0x264 /**< Uncorrectable error first failing + * data Register, 831-800 */ +#define XBRAM_UE_FFD_26_OFFSET 0x268 /**< Uncorrectable error first failing + * data Register, 863-832 */ +#define XBRAM_UE_FFD_27_OFFSET 0x26C /**< Uncorrectable error first failing + * data Register, 895-864 */ +#define XBRAM_UE_FFD_28_OFFSET 0x270 /**< Uncorrectable error first failing + * data Register, 927-896 */ +#define XBRAM_UE_FFD_29_OFFSET 0x274 /**< Uncorrectable error first failing + * data Register, 959-928 */ +#define XBRAM_UE_FFD_30_OFFSET 0x278 /**< Uncorrectable error first failing + * data Register, 991-960 */ +#define XBRAM_UE_FFD_31_OFFSET 0x27C /**< Uncorrectable error first failing + * data Register, 1023-992 */ + +#define XBRAM_UE_FFE_0_OFFSET 0x280 /**< Uncorrectable error first failing + * ECC Register, 31-0 */ +#define XBRAM_UE_FFE_1_OFFSET 0x284 /**< Uncorrectable error first failing + * ECC Register, 63-32 */ +#define XBRAM_UE_FFE_2_OFFSET 0x288 /**< Uncorrectable error first failing + * ECC Register, 95-64 */ +#define XBRAM_UE_FFE_3_OFFSET 0x28C /**< Uncorrectable error first failing + * ECC Register, 127-96 */ +#define XBRAM_UE_FFE_4_OFFSET 0x290 /**< Uncorrectable error first failing + * ECC Register, 159-128 */ +#define XBRAM_UE_FFE_5_OFFSET 0x294 /**< Uncorrectable error first failing + * ECC Register, 191-160 */ +#define XBRAM_UE_FFE_6_OFFSET 0x298 /**< Uncorrectable error first failing + * ECC Register, 223-192 */ +#define XBRAM_UE_FFE_7_OFFSET 0x29C /**< Uncorrectable error first failing + * ECC Register, 255-224 */ + +#define XBRAM_UE_FFA_0_OFFSET 0x2C0 /**< Uncorrectable error first failing + * address Register 31-0 */ +#define XBRAM_UE_FFA_1_OFFSET 0x2C4 /**< Uncorrectable error first failing + * address Register 63-32 */ + +#define XBRAM_FI_D_0_OFFSET 0x300 /**< Fault injection Data Register, + * 31-0 */ +#define XBRAM_FI_D_1_OFFSET 0x304 /**< Fault injection Data Register, + * 63-32 */ +#define XBRAM_FI_D_2_OFFSET 0x308 /**< Fault injection Data Register, + * 95-64 */ +#define XBRAM_FI_D_3_OFFSET 0x30C /**< Fault injection Data Register, + * 127-96 */ +#define XBRAM_FI_D_4_OFFSET 0x310 /**< Fault injection Data Register, + * 159-128 */ +#define XBRAM_FI_D_5_OFFSET 0x314 /**< Fault injection Data Register, + * 191-160 */ +#define XBRAM_FI_D_6_OFFSET 0x318 /**< Fault injection Data Register, + * 223-192 */ +#define XBRAM_FI_D_7_OFFSET 0x31C /**< Fault injection Data Register, + * 255-224 */ +#define XBRAM_FI_D_8_OFFSET 0x320 /**< Fault injection Data Register, + * 287-256 */ +#define XBRAM_FI_D_9_OFFSET 0x324 /**< Fault injection Data Register, + * 319-288 */ +#define XBRAM_FI_D_10_OFFSET 0x328 /**< Fault injection Data Register, + * 351-320 */ +#define XBRAM_FI_D_11_OFFSET 0x32C /**< Fault injection Data Register, + * 383-352 */ +#define XBRAM_FI_D_12_OFFSET 0x330 /**< Fault injection Data Register, + * 415-384 */ +#define XBRAM_FI_D_13_OFFSET 0x334 /**< Fault injection Data Register, + * 447-416 */ +#define XBRAM_FI_D_14_OFFSET 0x338 /**< Fault injection Data Register, + * 479-448 */ +#define XBRAM_FI_D_15_OFFSET 0x33C /**< Fault injection Data Register, + * 511-480 */ +#define XBRAM_FI_D_16_OFFSET 0x340 /**< Fault injection Data Register, + * 543-512 */ +#define XBRAM_FI_D_17_OFFSET 0x344 /**< Fault injection Data Register, + * 575-544 */ +#define XBRAM_FI_D_18_OFFSET 0x348 /**< Fault injection Data Register, + * 607-576 */ +#define XBRAM_FI_D_19_OFFSET 0x34C /**< Fault injection Data Register, + * 639-608 */ +#define XBRAM_FI_D_20_OFFSET 0x350 /**< Fault injection Data Register, + * 671-640 */ +#define XBRAM_FI_D_21_OFFSET 0x354 /**< Fault injection Data Register, + * 703-672 */ +#define XBRAM_FI_D_22_OFFSET 0x358 /**< Fault injection Data Register, + * 735-704 */ +#define XBRAM_FI_D_23_OFFSET 0x35C /**< Fault injection Data Register, + * 767-736 */ +#define XBRAM_FI_D_24_OFFSET 0x360 /**< Fault injection Data Register, + * 799-768 */ +#define XBRAM_FI_D_25_OFFSET 0x364 /**< Fault injection Data Register, + * 831-800 */ +#define XBRAM_FI_D_26_OFFSET 0x368 /**< Fault injection Data Register, + * 863-832 */ +#define XBRAM_FI_D_27_OFFSET 0x36C /**< Fault injection Data Register, + * 895-864 */ +#define XBRAM_FI_D_28_OFFSET 0x370 /**< Fault injection Data Register, + * 927-896 */ +#define XBRAM_FI_D_29_OFFSET 0x374 /**< Fault injection Data Register, + * 959-928 */ +#define XBRAM_FI_D_30_OFFSET 0x378 /**< Fault injection Data Register, + * 991-960 */ +#define XBRAM_FI_D_31_OFFSET 0x37C /**< Fault injection Data Register, + * 1023-992 */ + +#define XBRAM_FI_ECC_0_OFFSET 0x380 /**< Fault injection ECC Register, + * 31-0 */ +#define XBRAM_FI_ECC_1_OFFSET 0x384 /**< Fault injection ECC Register, + * 63-32 */ +#define XBRAM_FI_ECC_2_OFFSET 0x388 /**< Fault injection ECC Register, + * 95-64 */ +#define XBRAM_FI_ECC_3_OFFSET 0x38C /**< Fault injection ECC Register, + * 127-96 */ +#define XBRAM_FI_ECC_4_OFFSET 0x390 /**< Fault injection ECC Register, + * 159-128 */ +#define XBRAM_FI_ECC_5_OFFSET 0x394 /**< Fault injection ECC Register, + * 191-160 */ +#define XBRAM_FI_ECC_6_OFFSET 0x398 /**< Fault injection ECC Register, + * 223-192 */ +#define XBRAM_FI_ECC_7_OFFSET 0x39C /**< Fault injection ECC Register, + * 255-224 */ + + +/* @} */ + +/** @name Interrupt Status and Enable Register bitmaps and masks + * + * Bit definitions for the ECC status register and ECC interrupt enable register. + * @{ + */ +#define XBRAM_IR_CE_MASK 0x2 /**< Mask for the correctable error */ +#define XBRAM_IR_UE_MASK 0x1 /**< Mask for the uncorrectable error */ +#define XBRAM_IR_ALL_MASK 0x3 /**< Mask of all bits */ +/*@}*/ + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + +#define XBram_In32 Xil_In32 +#define XBram_Out32 Xil_Out32 + +#define XBram_In16 Xil_In16 +#define XBram_Out16 Xil_Out16 + +#define XBram_In8 Xil_In8 +#define XBram_Out8 Xil_Out8 + + +/****************************************************************************/ +/** +* +* Write a value to a BRAM register. A 32 bit write is performed. +* +* @param BaseAddress is the base address of the BRAM device register. +* @param RegOffset is the register offset from the base to write to. +* @param Data is the data written to the register. +* +* @return None. +* +* @note C-style signature: +* void XBram_WriteReg(u32 BaseAddress, u32 RegOffset, u32 Data) +* +****************************************************************************/ +#define XBram_WriteReg(BaseAddress, RegOffset, Data) \ + XBram_Out32((BaseAddress) + (RegOffset), (u32)(Data)) + +/****************************************************************************/ +/** +* +* Read a value from a BRAM register. A 32 bit read is performed. +* +* @param BaseAddress is the base address of the BRAM device registers. +* @param RegOffset is the register offset from the base to read from. +* +* @return Data read from the register. +* +* @note C-style signature: +* u32 XBram_ReadReg(u32 BaseAddress, u32 RegOffset) +* +****************************************************************************/ +#define XBram_ReadReg(BaseAddress, RegOffset) \ + XBram_In32((BaseAddress) + (RegOffset)) + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + + + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/datalink814_sp/bsp/microblaze_ps/include/xdebug.h b/datalink814_sp/bsp/microblaze_ps/include/xdebug.h new file mode 100644 index 0000000..b09c02d --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/include/xdebug.h @@ -0,0 +1,40 @@ +#ifndef XDEBUG /* prevent circular inclusions */ +#define XDEBUG /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(DEBUG) && !defined(NDEBUG) + +#ifndef XDEBUG_WARNING +#define XDEBUG_WARNING +#warning DEBUG is enabled +#endif + +int printf(const char *format, ...); + +#define XDBG_DEBUG_ERROR 0x00000001U /* error condition messages */ +#define XDBG_DEBUG_GENERAL 0x00000002U /* general debug messages */ +#define XDBG_DEBUG_ALL 0xFFFFFFFFU /* all debugging data */ + +#define xdbg_current_types (XDBG_DEBUG_GENERAL) + +#define xdbg_stmnt(x) x + +#define xdbg_printf(type, ...) (((type) & xdbg_current_types) ? printf (__VA_ARGS__) : 0) + + +#else /* defined(DEBUG) && !defined(NDEBUG) */ + +#define xdbg_stmnt(x) + +#define xdbg_printf(...) + +#endif /* defined(DEBUG) && !defined(NDEBUG) */ + +#ifdef __cplusplus +} +#endif + +#endif /* XDEBUG */ diff --git a/datalink814_sp/bsp/microblaze_ps/include/xenv.h b/datalink814_sp/bsp/microblaze_ps/include/xenv.h new file mode 100644 index 0000000..9c7c4c3 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/include/xenv.h @@ -0,0 +1,183 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xenv.h +* +* Defines common services that are typically found in a host operating. +* environment. This include file simply includes an OS specific file based +* on the compile-time constant BUILD_ENV_*, where * is the name of the target +* environment. +* +* All services are defined as macros. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00b ch   10/24/02 Added XENV_LINUX
+* 1.00a rmm  04/17/02 First release
+* 
+* +******************************************************************************/ + +#ifndef XENV_H /* prevent circular inclusions */ +#define XENV_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Select which target environment we are operating under + */ + +/* VxWorks target environment */ +#if defined XENV_VXWORKS +#include "xenv_vxworks.h" + +/* Linux target environment */ +#elif defined XENV_LINUX +#include "xenv_linux.h" + +/* Unit test environment */ +#elif defined XENV_UNITTEST +#include "ut_xenv.h" + +/* Integration test environment */ +#elif defined XENV_INTTEST +#include "int_xenv.h" + +/* Standalone environment selected */ +#else +#include "xenv_standalone.h" +#endif + + +/* + * The following comments specify the types and macro wrappers that are + * expected to be defined by the target specific header files + */ + +/**************************** Type Definitions *******************************/ + +/*****************************************************************************/ +/** + * + * XENV_TIME_STAMP + * + * A structure that contains a time stamp used by other time stamp macros + * defined below. This structure is processor dependent. + */ + + +/***************** Macros (Inline Functions) Definitions *********************/ + +/*****************************************************************************/ +/** + * + * XENV_MEM_COPY(void *DestPtr, void *SrcPtr, unsigned Bytes) + * + * Copies a non-overlapping block of memory. + * + * @param DestPtr is the destination address to copy data to. + * @param SrcPtr is the source address to copy data from. + * @param Bytes is the number of bytes to copy. + * + * @return None + */ + +/*****************************************************************************/ +/** + * + * XENV_MEM_FILL(void *DestPtr, char Data, unsigned Bytes) + * + * Fills an area of memory with constant data. + * + * @param DestPtr is the destination address to set. + * @param Data contains the value to set. + * @param Bytes is the number of bytes to set. + * + * @return None + */ +/*****************************************************************************/ +/** + * + * XENV_TIME_STAMP_GET(XTIME_STAMP *StampPtr) + * + * Samples the processor's or external timer's time base counter. + * + * @param StampPtr is the storage for the retrieved time stamp. + * + * @return None + */ + +/*****************************************************************************/ +/** + * + * XENV_TIME_STAMP_DELTA_US(XTIME_STAMP *Stamp1Ptr, XTIME_STAMP* Stamp2Ptr) + * + * Computes the delta between the two time stamps. + * + * @param Stamp1Ptr - First sampled time stamp. + * @param Stamp1Ptr - Sedond sampled time stamp. + * + * @return An unsigned int value with units of microseconds. + */ + +/*****************************************************************************/ +/** + * + * XENV_TIME_STAMP_DELTA_MS(XTIME_STAMP *Stamp1Ptr, XTIME_STAMP* Stamp2Ptr) + * + * Computes the delta between the two time stamps. + * + * @param Stamp1Ptr - First sampled time stamp. + * @param Stamp1Ptr - Sedond sampled time stamp. + * + * @return An unsigned int value with units of milliseconds. + */ + +/*****************************************************************************//** + * + * XENV_USLEEP(unsigned delay) + * + * Delay the specified number of microseconds. + * + * @param delay is the number of microseconds to delay. + * + * @return None + */ + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ diff --git a/datalink814_sp/bsp/microblaze_ps/include/xenv_standalone.h b/datalink814_sp/bsp/microblaze_ps/include/xenv_standalone.h new file mode 100644 index 0000000..ef905af --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/include/xenv_standalone.h @@ -0,0 +1,364 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xenv_standalone.h +* +* Defines common services specified by xenv.h. +* +* @note +* This file is not intended to be included directly by driver code. +* Instead, the generic xenv.h file is intended to be included by driver +* code. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a wgr  02/28/07 Added cache handling macros.
+* 1.00a wgr  02/27/07 Simplified code. Deprecated old-style macro names.
+* 1.00a rmm  01/24/06 Implemented XENV_USLEEP. Assume implementation is being
+*                     used under Xilinx standalone BSP.
+* 1.00a xd   11/03/04 Improved support for doxygen.
+* 1.00a rmm  03/21/02 First release
+* 1.00a wgr  03/22/07 Converted to new coding style.
+* 1.00a rpm  06/29/07 Added udelay macro for standalone
+* 1.00a xd   07/19/07 Included xparameters.h as XPAR_ constants are referred
+*                     to in MICROBLAZE section
+* 1.00a ecm  09/19/08 updated for v7.20 of Microblaze, new functionality
+*
+* 
+* +* +******************************************************************************/ + +#ifndef XENV_STANDALONE_H +#define XENV_STANDALONE_H + +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ +/****************************************************************************** + * + * Get the processor dependent includes + * + ******************************************************************************/ + +#include + +#if defined __MICROBLAZE__ +# include "mb_interface.h" +# include "xparameters.h" /* XPAR constants used below in MB section */ + +#elif defined __PPC__ +# include "sleep.h" +# include "xcache_l.h" /* also include xcache_l.h for caching macros */ +#endif + +/****************************************************************************** + * + * MEMCPY / MEMSET related macros. + * + * The following are straight forward implementations of memset and memcpy. + * + * NOTE: memcpy may not work if source and target memory area are overlapping. + * + ******************************************************************************/ +/*****************************************************************************/ +/** + * + * Copies a non-overlapping block of memory. + * + * @param DestPtr + * Destination address to copy data to. + * + * @param SrcPtr + * Source address to copy data from. + * + * @param Bytes + * Number of bytes to copy. + * + * @return None. + * + * @note + * The use of XENV_MEM_COPY is deprecated. Use memcpy() instead. + * + * @note + * This implemention MAY BREAK work if source and target memory + * area are overlapping. + * + *****************************************************************************/ + +#define XENV_MEM_COPY(DestPtr, SrcPtr, Bytes) \ + memcpy((void *) DestPtr, (const void *) SrcPtr, (size_t) Bytes) + + + +/*****************************************************************************/ +/** + * + * Fills an area of memory with constant data. + * + * @param DestPtr + * Destination address to copy data to. + * + * @param Data + * Value to set. + * + * @param Bytes + * Number of bytes to copy. + * + * @return None. + * + * @note + * The use of XENV_MEM_FILL is deprecated. Use memset() instead. + * + *****************************************************************************/ + +#define XENV_MEM_FILL(DestPtr, Data, Bytes) \ + memset((void *) DestPtr, (s32) Data, (size_t) Bytes) + + + +/****************************************************************************** + * + * TIME related macros + * + ******************************************************************************/ + +/** + * A structure that contains a time stamp used by other time stamp macros + * defined below. This structure is processor dependent. + */ +typedef s32 XENV_TIME_STAMP; + +/*****************************************************************************/ +/** + * + * Time is derived from the 64 bit PPC timebase register + * + * @param StampPtr is the storage for the retrieved time stamp. + * + * @return None. + * + * @note + * + * Signature: void XENV_TIME_STAMP_GET(XTIME_STAMP *StampPtr) + *

+ * This macro must be implemented by the user. + * + *****************************************************************************/ +#define XENV_TIME_STAMP_GET(StampPtr) + +/*****************************************************************************/ +/** + * + * This macro is not yet implemented and always returns 0. + * + * @param Stamp1Ptr is the first sampled time stamp. + * @param Stamp2Ptr is the second sampled time stamp. + * + * @return 0 + * + * @note + * + * This macro must be implemented by the user. + * + *****************************************************************************/ +#define XENV_TIME_STAMP_DELTA_US(Stamp1Ptr, Stamp2Ptr) (0) + +/*****************************************************************************/ +/** + * + * This macro is not yet implemented and always returns 0. + * + * @param Stamp1Ptr is the first sampled time stamp. + * @param Stamp2Ptr is the second sampled time stamp. + * + * @return 0 + * + * @note + * + * This macro must be implemented by the user. + * + *****************************************************************************/ +#define XENV_TIME_STAMP_DELTA_MS(Stamp1Ptr, Stamp2Ptr) (0) + +/*****************************************************************************/ +/** + * XENV_USLEEP(unsigned delay) + * + * Delay the specified number of microseconds. Not implemented without OS + * support. + * + * @param delay + * Number of microseconds to delay. + * + * @return None. + * + *****************************************************************************/ + +#ifdef __PPC__ +#define XENV_USLEEP(delay) usleep(delay) +#define udelay(delay) usleep(delay) +#else +#define XENV_USLEEP(delay) +#define udelay(delay) +#endif + + +/****************************************************************************** + * + * CACHE handling macros / mappings + * + ******************************************************************************/ +/****************************************************************************** + * + * Processor independent macros + * + ******************************************************************************/ + +#define XCACHE_ENABLE_CACHE() \ + { XCACHE_ENABLE_DCACHE(); XCACHE_ENABLE_ICACHE(); } + +#define XCACHE_DISABLE_CACHE() \ + { XCACHE_DISABLE_DCACHE(); XCACHE_DISABLE_ICACHE(); } + + +/****************************************************************************** + * + * MicroBlaze case + * + * NOTE: Currently the following macros will only work on systems that contain + * only ONE MicroBlaze processor. Also, the macros will only be enabled if the + * system is built using a xparameters.h file. + * + ******************************************************************************/ + +#if defined __MICROBLAZE__ + +/* Check if MicroBlaze data cache was built into the core. + */ +#if (XPAR_MICROBLAZE_USE_DCACHE == 1) +# define XCACHE_ENABLE_DCACHE() microblaze_enable_dcache() +# define XCACHE_DISABLE_DCACHE() microblaze_disable_dcache() +# define XCACHE_INVALIDATE_DCACHE() microblaze_invalidate_dcache() + +# define XCACHE_INVALIDATE_DCACHE_RANGE(Addr, Len) \ + microblaze_invalidate_dcache_range((s32)(Addr), (s32)(Len)) + +#if (XPAR_MICROBLAZE_DCACHE_USE_WRITEBACK == 1) +# define XCACHE_FLUSH_DCACHE() microblaze_flush_dcache() +# define XCACHE_FLUSH_DCACHE_RANGE(Addr, Len) \ + microblaze_flush_dcache_range((s32)(Addr), (s32)(Len)) +#else +# define XCACHE_FLUSH_DCACHE() microblaze_invalidate_dcache() +# define XCACHE_FLUSH_DCACHE_RANGE(Addr, Len) \ + microblaze_invalidate_dcache_range((s32)(Addr), (s32)(Len)) +#endif /*XPAR_MICROBLAZE_DCACHE_USE_WRITEBACK*/ + +#else +# define XCACHE_ENABLE_DCACHE() +# define XCACHE_DISABLE_DCACHE() +# define XCACHE_INVALIDATE_DCACHE_RANGE(Addr, Len) +# define XCACHE_FLUSH_DCACHE_RANGE(Addr, Len) +#endif /*XPAR_MICROBLAZE_USE_DCACHE*/ + + +/* Check if MicroBlaze instruction cache was built into the core. + */ +#if (XPAR_MICROBLAZE_USE_ICACHE == 1) +# define XCACHE_ENABLE_ICACHE() microblaze_enable_icache() +# define XCACHE_DISABLE_ICACHE() microblaze_disable_icache() + +# define XCACHE_INVALIDATE_ICACHE() microblaze_invalidate_icache() + +# define XCACHE_INVALIDATE_ICACHE_RANGE(Addr, Len) \ + microblaze_invalidate_icache_range((s32)(Addr), (s32)(Len)) + +#else +# define XCACHE_ENABLE_ICACHE() +# define XCACHE_DISABLE_ICACHE() +#endif /*XPAR_MICROBLAZE_USE_ICACHE*/ + + +/****************************************************************************** + * + * PowerPC case + * + * Note that the XCACHE_ENABLE_xxx functions are hardcoded to enable a + * specific memory region (0x80000001). Each bit (0-30) in the regions + * bitmask stands for 128MB of memory. Bit 31 stands for the upper 2GB + * range. + * + * regions --> cached address range + * ------------|-------------------------------------------------- + * 0x80000000 | [0, 0x7FFFFFF] + * 0x00000001 | [0xF8000000, 0xFFFFFFFF] + * 0x80000001 | [0, 0x7FFFFFF],[0xF8000000, 0xFFFFFFFF] + * + ******************************************************************************/ + +#elif defined __PPC__ + +#define XCACHE_ENABLE_DCACHE() XCache_EnableDCache(0x80000001) +#define XCACHE_DISABLE_DCACHE() XCache_DisableDCache() +#define XCACHE_ENABLE_ICACHE() XCache_EnableICache(0x80000001) +#define XCACHE_DISABLE_ICACHE() XCache_DisableICache() + +#define XCACHE_INVALIDATE_DCACHE_RANGE(Addr, Len) \ + XCache_InvalidateDCacheRange((u32)(Addr), (u32)(Len)) + +#define XCACHE_FLUSH_DCACHE_RANGE(Addr, Len) \ + XCache_FlushDCacheRange((u32)(Addr), (u32)(Len)) + +#define XCACHE_INVALIDATE_ICACHE() XCache_InvalidateICache() + + +/****************************************************************************** + * + * Unknown processor / architecture + * + ******************************************************************************/ + +#else +/* #error "Unknown processor / architecture. Must be MicroBlaze or PowerPC." */ +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* #ifndef XENV_STANDALONE_H */ diff --git a/datalink814_sp/bsp/microblaze_ps/include/xgpio.h b/datalink814_sp/bsp/microblaze_ps/include/xgpio.h new file mode 100644 index 0000000..b498fe0 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/include/xgpio.h @@ -0,0 +1,211 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file xgpio.h +* @addtogroup gpio_v4_4 +* @{ +* @details +* +* This file contains the software API definition of the Xilinx General Purpose +* I/O (XGpio) device driver. +* +* The Xilinx GPIO controller is a soft IP core designed for Xilinx FPGAs and +* contains the following general features: +* - Support for up to 32 I/O discretes for each channel (64 bits total). +* - Each of the discretes can be configured for input or output. +* - Configurable support for dual channels and interrupt generation. +* +* The driver provides interrupt management functions. Implementation of +* interrupt handlers is left to the user. Refer to the provided interrupt +* example in the examples directory for details. +* +* This driver is intended to be RTOS and processor independent. Any needs for +* dynamic memory management, threads or thread mutual exclusion, virtual +* memory, or cache control must be satisfied by the layer above this driver. +* +* Initialization & Configuration +* +* The XGpio_Config structure is used by the driver to configure itself. This +* configuration structure is typically created by the tool-chain based on HW +* build properties. +* +* To support multiple runtime loading and initialization strategies employed +* by various operating systems, the driver instance can be initialized in one +* of the following ways: +* +* - XGpio_Initialize(InstancePtr, DeviceId) - The driver looks up its own +* configuration structure created by the tool-chain based on an ID provided +* by the tool-chain. +* +* - XGpio_CfgInitialize(InstancePtr, CfgPtr, EffectiveAddr) - Uses a +* configuration structure provided by the caller. If running in a system +* with address translation, the provided virtual memory base address +* replaces the physical address present in the configuration structure. +* +* @note +* +* This API utilizes 32 bit I/O to the GPIO registers. With less than 32 bits, +* the unused bits from registers are read as zero and written as don't cares. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a rmm  03/13/02 First release
+* 2.00a jhl  11/26/03 Added support for dual channels and interrupts
+* 2.01a jvb  12/14/05 I separated dependency on the static config table and
+*                     xparameters.h from the driver initialization by moving
+*                     _Initialize and _LookupConfig to _sinit.c. I also added
+*                     the new _CfgInitialize routine.
+* 2.11a mta  03/21/07 Updated to new coding style, added GetDataDirection
+* 2.12a sv   11/21/07 Updated driver to support access through DCR bus
+* 2.12a sv   06/05/08 Updated driver to fix the XGpio_InterruptDisable function
+*		      to properly update the Interrupt Enable register
+* 2.13a sdm  08/22/08 Removed support for static interrupt handlers from the MDD
+*		      file
+* 3.00a sv   11/21/09 Updated to use HAL Processor APIs.
+*		      Renamed the macros XGpio_mWriteReg to XGpio_WriteReg and
+*		      XGpio_mReadReg to XGpio_ReadReg. Removed the macros
+*		      XGpio_mSetDataDirection, XGpio_mGetDataReg and
+*		      XGpio_mSetDataReg. Users should use XGpio_WriteReg and
+*		      XGpio_ReadReg to achieve the same functionality.
+* 3.01a bss  04/18/13 Updated driver tcl to generate Canonical params in
+*		      xparameters.h. CR#698589
+* 4.0   adk  19/12/13 Updated as per the New Tcl API's
+* 4.1   lks  11/18/15 Updated to use cannonical xparameters in examples and
+*		      clean up of the comments, removed support for DCR bridge
+*		      and removed xgpio_intr_example for CR 900381
+* 4.2   sk   08/16/16 Used UINTPTR instead of u32 for Baseaddress as part of
+*                     adding 64 bit support. CR# 867425.
+*                     Changed the prototype of XGpio_CfgInitialize API.
+* 4.3   sk   09/29/16 Modified the example to make it work when LED_bits are
+*                     configured as an output. CR# 958644
+*       ms   01/23/17 Added xil_printf statement in main function for all
+*                     examples to ensure that "Successfully ran" and "Failed"
+*                     strings are available in all examples. This is a fix
+*                     for CR-965028.
+*       ms   03/17/17 Added readme.txt file in examples folder for doxygen
+*                     generation.
+* 4.4   sne  04/25/19 Updated Makefile for IAR compier (CR-1029421).
+*
+* 
+*****************************************************************************/ + +#ifndef XGPIO_H /* prevent circular inclusions */ +#define XGPIO_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files ********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xstatus.h" +#include "xgpio_l.h" + +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + +/** + * This typedef contains configuration information for the device. + */ +typedef struct { + u16 DeviceId; /* Unique ID of device */ + UINTPTR BaseAddress; /* Device base address */ + int InterruptPresent; /* Are interrupts supported in h/w */ + int IsDual; /* Are 2 channels supported in h/w */ +} XGpio_Config; + +/** + * The XGpio driver instance data. The user is required to allocate a + * variable of this type for every GPIO device in the system. A pointer + * to a variable of this type is then passed to the driver API functions. + */ +typedef struct { + UINTPTR BaseAddress; /* Device base address */ + u32 IsReady; /* Device is initialized and ready */ + int InterruptPresent; /* Are interrupts supported in h/w */ + int IsDual; /* Are 2 channels supported in h/w */ +} XGpio; + +/***************** Macros (Inline Functions) Definitions ********************/ + + +/************************** Function Prototypes *****************************/ + +/* + * Initialization functions in xgpio_sinit.c + */ +int XGpio_Initialize(XGpio *InstancePtr, u16 DeviceId); +XGpio_Config *XGpio_LookupConfig(u16 DeviceId); + +/* + * API Basic functions implemented in xgpio.c + */ +int XGpio_CfgInitialize(XGpio *InstancePtr, XGpio_Config * Config, + UINTPTR EffectiveAddr); +void XGpio_SetDataDirection(XGpio *InstancePtr, unsigned Channel, + u32 DirectionMask); +u32 XGpio_GetDataDirection(XGpio *InstancePtr, unsigned Channel); +u32 XGpio_DiscreteRead(XGpio *InstancePtr, unsigned Channel); +void XGpio_DiscreteWrite(XGpio *InstancePtr, unsigned Channel, u32 Mask); + + +/* + * API Functions implemented in xgpio_extra.c + */ +void XGpio_DiscreteSet(XGpio *InstancePtr, unsigned Channel, u32 Mask); +void XGpio_DiscreteClear(XGpio *InstancePtr, unsigned Channel, u32 Mask); + +/* + * API Functions implemented in xgpio_selftest.c + */ +int XGpio_SelfTest(XGpio *InstancePtr); + +/* + * API Functions implemented in xgpio_intr.c + */ +void XGpio_InterruptGlobalEnable(XGpio *InstancePtr); +void XGpio_InterruptGlobalDisable(XGpio *InstancePtr); +void XGpio_InterruptEnable(XGpio *InstancePtr, u32 Mask); +void XGpio_InterruptDisable(XGpio *InstancePtr, u32 Mask); +void XGpio_InterruptClear(XGpio *InstancePtr, u32 Mask); +u32 XGpio_InterruptGetEnabled(XGpio *InstancePtr); +u32 XGpio_InterruptGetStatus(XGpio *InstancePtr); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/datalink814_sp/bsp/microblaze_ps/include/xgpio_i.h b/datalink814_sp/bsp/microblaze_ps/include/xgpio_i.h new file mode 100644 index 0000000..7938b0f --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/include/xgpio_i.h @@ -0,0 +1,83 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/******************************************************************************/ +/** +* @file xgpio_i.h +* @addtogroup gpio_v4_3 +* @{ +* +* This header file contains internal identifiers, which are those shared +* between the files of the driver. It is intended for internal use only. +* +* NOTES: +* +* None. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a rmm  03/13/02 First release
+* 2.11a mta  03/21/07 Updated to new coding style
+* 
+******************************************************************************/ + +#ifndef XGPIO_I_H /* prevent circular inclusions */ +#define XGPIO_I_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xgpio.h" + +/************************** Constant Definitions ****************************/ + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + + +/************************** Variable Definitions ****************************/ + +extern XGpio_Config XGpio_ConfigTable[]; + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/datalink814_sp/bsp/microblaze_ps/include/xgpio_l.h b/datalink814_sp/bsp/microblaze_ps/include/xgpio_l.h new file mode 100644 index 0000000..be6d04a --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/include/xgpio_l.h @@ -0,0 +1,189 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xgpio_l.h +* @addtogroup gpio_v4_4 +* @{ +* +* This header file contains identifiers and driver functions (or +* macros) that can be used to access the device. The user should refer to the +* hardware device specification for more details of the device operation. +* +* The macros that are available in this file use a multiply to calculate the +* addresses of registers. The user can control whether that multiply is done +* at run time or at compile time. A constant passed as the channel parameter +* will cause the multiply to be done at compile time. A variable passed as the +* channel parameter will cause it to occur at run time. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a jhl  04/24/02 First release of low level driver
+* 2.00a jhl  11/26/03 Added support for dual channels and interrupts. This
+*                     change required the functions to be changed such that
+*                     the interface is not compatible with previous versions.
+*                     See the examples in the example directory for macros
+*                     to help compile an application that was designed for
+*                     previous versions of the driver. The interrupt registers
+*                     are accessible using the ReadReg and WriteReg macros and
+*                     a channel parameter was added to the other macros.
+* 2.11a mta  03/21/07 Updated to new coding style
+* 2.12a sv   11/21/07 Updated driver to support access through DCR bus.
+* 3.00a sv   11/21/09 Renamed the macros XGpio_mWriteReg to XGpio_WriteReg
+*		      XGpio_mReadReg to XGpio_ReadReg.
+*		      Removed the macros XGpio_mSetDataDirection,
+*		      XGpio_mGetDataReg and XGpio_mSetDataReg. Users
+*		      should use XGpio_WriteReg/XGpio_ReadReg to achieve the
+*		      same functionality.
+* 4.1  lks   11/18/15 Removed support for DCR bridge
+* 
+* +******************************************************************************/ + +#ifndef XGPIO_L_H /* prevent circular inclusions */ +#define XGPIO_L_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_io.h" + + +/************************** Constant Definitions *****************************/ + +/** @name Registers + * + * Register offsets for this device. + * @{ + */ +#define XGPIO_DATA_OFFSET 0x0 /**< Data register for 1st channel */ +#define XGPIO_TRI_OFFSET 0x4 /**< I/O direction reg for 1st channel */ +#define XGPIO_DATA2_OFFSET 0x8 /**< Data register for 2nd channel */ +#define XGPIO_TRI2_OFFSET 0xC /**< I/O direction reg for 2nd channel */ + +#define XGPIO_GIE_OFFSET 0x11C /**< Glogal interrupt enable register */ +#define XGPIO_ISR_OFFSET 0x120 /**< Interrupt status register */ +#define XGPIO_IER_OFFSET 0x128 /**< Interrupt enable register */ + +/* @} */ + +/* The following constant describes the offset of each channels data and + * tristate register from the base address. + */ +#define XGPIO_CHAN_OFFSET 8 + +/** @name Interrupt Status and Enable Register bitmaps and masks + * + * Bit definitions for the interrupt status register and interrupt enable + * registers. + * @{ + */ +#define XGPIO_IR_MASK 0x3 /**< Mask of all bits */ +#define XGPIO_IR_CH1_MASK 0x1 /**< Mask for the 1st channel */ +#define XGPIO_IR_CH2_MASK 0x2 /**< Mask for the 2nd channel */ +/*@}*/ + + +/** @name Global Interrupt Enable Register bitmaps and masks + * + * Bit definitions for the Global Interrupt Enable register + * @{ + */ +#define XGPIO_GIE_GINTR_ENABLE_MASK 0x80000000 +/*@}*/ + + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + +#define XGpio_In32 Xil_In32 +#define XGpio_Out32 Xil_Out32 + + +/****************************************************************************/ +/** +* +* Write a value to a GPIO register. A 32 bit write is performed. If the +* GPIO core is implemented in a smaller width, only the least significant data +* is written. +* +* @param BaseAddress is the base address of the GPIO device. +* @param RegOffset is the register offset from the base to write to. +* @param Data is the data written to the register. +* +* @return None. +* +* @note C-style signature: +* void XGpio_WriteReg(u32 BaseAddress, u32 RegOffset, u32 Data) +* +****************************************************************************/ +#define XGpio_WriteReg(BaseAddress, RegOffset, Data) \ + XGpio_Out32((BaseAddress) + (RegOffset), (u32)(Data)) + +/****************************************************************************/ +/** +* +* Read a value from a GPIO register. A 32 bit read is performed. If the +* GPIO core is implemented in a smaller width, only the least +* significant data is read from the register. The most significant data +* will be read as 0. +* +* @param BaseAddress is the base address of the GPIO device. +* @param RegOffset is the register offset from the base to read from. +* +* @return Data read from the register. +* +* @note C-style signature: +* u32 XGpio_ReadReg(u32 BaseAddress, u32 RegOffset) +* +****************************************************************************/ +#define XGpio_ReadReg(BaseAddress, RegOffset) \ + XGpio_In32((BaseAddress) + (RegOffset)) + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/datalink814_sp/bsp/microblaze_ps/include/xil_assert.h b/datalink814_sp/bsp/microblaze_ps/include/xil_assert.h new file mode 100644 index 0000000..917de31 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/include/xil_assert.h @@ -0,0 +1,191 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_assert.h +* +* @addtogroup common_assert_apis Assert APIs and Macros +* +* The xil_assert.h file contains assert related functions and macros. +* Assert APIs/Macros specifies that a application program satisfies certain +* conditions at particular points in its execution. These function can be +* used by application programs to ensure that, application code is satisfying +* certain conditions. +* +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date   Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a hbm  07/14/09 First release
+* 6.0   kvn  05/31/16 Make Xil_AsserWait a global variable
+* 
+* +******************************************************************************/ + +#ifndef XIL_ASSERT_H /* prevent circular inclusions */ +#define XIL_ASSERT_H /* by using protection macros */ + +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/***************************** Include Files *********************************/ + + +/************************** Constant Definitions *****************************/ + +#define XIL_ASSERT_NONE 0U +#define XIL_ASSERT_OCCURRED 1U +#define XNULL NULL + +extern u32 Xil_AssertStatus; +extern s32 Xil_AssertWait; +extern void Xil_Assert(const char8 *File, s32 Line); +void XNullHandler(void *NullParameter); + +/** + * This data type defines a callback to be invoked when an + * assert occurs. The callback is invoked only when asserts are enabled + */ +typedef void (*Xil_AssertCallback) (const char8 *File, s32 Line); + +/***************** Macros (Inline Functions) Definitions *********************/ + +#ifndef NDEBUG + +/*****************************************************************************/ +/** +* @brief This assert macro is to be used for void functions. This in +* conjunction with the Xil_AssertWait boolean can be used to +* accomodate tests so that asserts which fail allow execution to +* continue. +* +* @param Expression: expression to be evaluated. If it evaluates to +* false, the assert occurs. +* +* @return Returns void unless the Xil_AssertWait variable is true, in which +* case no return is made and an infinite loop is entered. +* +******************************************************************************/ +#define Xil_AssertVoid(Expression) \ +{ \ + if (Expression) { \ + Xil_AssertStatus = XIL_ASSERT_NONE; \ + } else { \ + Xil_Assert(__FILE__, __LINE__); \ + Xil_AssertStatus = XIL_ASSERT_OCCURRED; \ + return; \ + } \ +} + +/*****************************************************************************/ +/** +* @brief This assert macro is to be used for functions that do return a +* value. This in conjunction with the Xil_AssertWait boolean can be +* used to accomodate tests so that asserts which fail allow execution +* to continue. +* +* @param Expression: expression to be evaluated. If it evaluates to false, +* the assert occurs. +* +* @return Returns 0 unless the Xil_AssertWait variable is true, in which +* case no return is made and an infinite loop is entered. +* +******************************************************************************/ +#define Xil_AssertNonvoid(Expression) \ +{ \ + if (Expression) { \ + Xil_AssertStatus = XIL_ASSERT_NONE; \ + } else { \ + Xil_Assert(__FILE__, __LINE__); \ + Xil_AssertStatus = XIL_ASSERT_OCCURRED; \ + return 0; \ + } \ +} + +/*****************************************************************************/ +/** +* @brief Always assert. This assert macro is to be used for void functions. +* Use for instances where an assert should always occur. +* +* @return Returns void unless the Xil_AssertWait variable is true, in which +* case no return is made and an infinite loop is entered. +* +******************************************************************************/ +#define Xil_AssertVoidAlways() \ +{ \ + Xil_Assert(__FILE__, __LINE__); \ + Xil_AssertStatus = XIL_ASSERT_OCCURRED; \ + return; \ +} + +/*****************************************************************************/ +/** +* @brief Always assert. This assert macro is to be used for functions that +* do return a value. Use for instances where an assert should always +* occur. +* +* @return Returns void unless the Xil_AssertWait variable is true, in which +* case no return is made and an infinite loop is entered. +* +******************************************************************************/ +#define Xil_AssertNonvoidAlways() \ +{ \ + Xil_Assert(__FILE__, __LINE__); \ + Xil_AssertStatus = XIL_ASSERT_OCCURRED; \ + return 0; \ +} + + +#else + +#define Xil_AssertVoid(Expression) +#define Xil_AssertVoidAlways() +#define Xil_AssertNonvoid(Expression) +#define Xil_AssertNonvoidAlways() + +#endif + +/************************** Function Prototypes ******************************/ + +void Xil_AssertSetCallback(Xil_AssertCallback Routine); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** +* @} End of "addtogroup common_assert_apis". +*/ diff --git a/datalink814_sp/bsp/microblaze_ps/include/xil_cache.h b/datalink814_sp/bsp/microblaze_ps/include/xil_cache.h new file mode 100644 index 0000000..c9ff61d --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/include/xil_cache.h @@ -0,0 +1,433 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_cache.h +* +* The xil_cache.h file contains cache related driver functions (or macros) +* that can be used to access the device. The user should refer to the +* hardware device specification for more details of the device operation. +* The functions in this header file can be used across all Xilinx supported +* processors. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00  hbm  07/28/09 Initial release
+* 3.02a sdm  10/24/11 Updated the file to include xparameters.h so that
+*                     the correct cache flush routines are used based on
+*                     whether the write-back or write-through caches are
+*                     used (cr #630532).
+* 3.10a asa  05/04/13 This version of MicroBlaze BSP adds support for system
+*					  cache/L2 cache. The existing/old APIs/macros in this
+*					  file are renamed to imply that they deal with L1 cache.
+*					  New macros/APIs are added to address similar features for
+*					  L2 cache. Users can include this file in their application
+*					  to use the various cache related APIs. These changes are
+*					  done for implementing PR #697214.
+*
+* 
+* +* @note +* +******************************************************************************/ + +#ifndef XIL_CACHE_H +#define XIL_CACHE_H + +#if defined XENV_VXWORKS +/* VxWorks environment */ +#error "Unknown processor / architecture. Must be PPC for VxWorks." +#else +/* standalone environment */ + +#include "mb_interface.h" +#include "xil_types.h" +#include "xparameters.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/****************************************************************************/ +/** +* +* @brief Invalidate the entire L1 data cache. If the cacheline is modified +* (dirty), the modified contents are lost. +* +* @param None. +* +* @return None. +* +* @note +* +* Processor must be in real mode. +****************************************************************************/ +#define Xil_L1DCacheInvalidate() microblaze_invalidate_dcache() + +/****************************************************************************/ +/** +* +* @brief Invalidate the entire L2 data cache. If the cacheline is modified +* (dirty),the modified contents are lost. +* +* @param None. +* +* @return None. +* +* @note +* +* Processor must be in real mode. +****************************************************************************/ +#define Xil_L2CacheInvalidate() microblaze_invalidate_cache_ext() + +/****************************************************************************/ +/** +* +* @brief Invalidate the L1 data cache for the given address range. +* If the bytes specified by the address (Addr) are cached by the L1 +* data cache, the cacheline containing that byte is invalidated.If +* the cacheline is modified (dirty), the modified contents are lost. +* +* @param Addr is address of ragne to be invalidated. +* @param Len is the length in bytes to be invalidated. +* +* @return None. +* +* @note +* +* Processor must be in real mode. +****************************************************************************/ +#define Xil_L1DCacheInvalidateRange(Addr, Len) \ + microblaze_invalidate_dcache_range((Addr), (Len)) + +/****************************************************************************/ +/** +* +* @brief Invalidate the L1 data cache for the given address range. +* If the bytes specified by the address (Addr) are cached by the +* L1 data cache, the cacheline containing that byte is invalidated. +* If the cacheline is modified (dirty), the modified contents are lost. +* +* @param Addr: address of ragne to be invalidated. +* @param Len: length in bytes to be invalidated. +* +* @return None. +* +* @note +* Processor must be in real mode. +****************************************************************************/ +#define Xil_L2CacheInvalidateRange(Addr, Len) \ + microblaze_invalidate_cache_ext_range((Addr), (Len)) + +/****************************************************************************/ +/** +* @brief Flush the L1 data cache for the given address range. +* If the bytes specified by the address (Addr) are cached by the +* data cache, and is modified (dirty), the cacheline will be written +* to system memory.The cacheline will also be invalidated. +* +* @param Addr: the starting address of the range to be flushed. +* @param Len: length in byte to be flushed. +* +* @return None. +* +****************************************************************************/ +#if (XPAR_MICROBLAZE_DCACHE_USE_WRITEBACK == 1) +# define Xil_L1DCacheFlushRange(Addr, Len) \ + microblaze_flush_dcache_range((Addr), (Len)) +#else +# define Xil_L1DCacheFlushRange(Addr, Len) \ + microblaze_invalidate_dcache_range((Addr), (Len)) +#endif /* XPAR_MICROBLAZE_DCACHE_USE_WRITEBACK */ + +/****************************************************************************/ +/** +* @brief Flush the L2 data cache for the given address range. +* If the bytes specified by the address (Addr) are cached by the +* data cache, and is modified (dirty), the cacheline will be +* written to system memory. The cacheline will also be invalidated. +* +* @param Addr: the starting address of the range to be flushed. +* @param Len: length in byte to be flushed. +* +* @return None. +* +****************************************************************************/ +#define Xil_L2CacheFlushRange(Addr, Len) \ + microblaze_flush_cache_ext_range((Addr), (Len)) + +/****************************************************************************/ +/** +* @brief Flush the entire L1 data cache. If any cacheline is dirty, the +* cacheline will be written to system memory. The entire data cache +* will be invalidated. +* +* @return None. +* +****************************************************************************/ +#if (XPAR_MICROBLAZE_DCACHE_USE_WRITEBACK == 1) +# define Xil_L1DCacheFlush() microblaze_flush_dcache() +#else +# define Xil_L1DCacheFlush() microblaze_invalidate_dcache() +#endif /* XPAR_MICROBLAZE_DCACHE_USE_WRITEBACK */ + +/****************************************************************************/ +/** +* @brief Flush the entire L2 data cache. If any cacheline is dirty, the +* cacheline will be written to system memory. The entire data cache +* will be invalidated. +* +* @return None. +* +****************************************************************************/ +#define Xil_L2CacheFlush() microblaze_flush_cache_ext() + +/****************************************************************************/ +/** +* +* @brief Invalidate the instruction cache for the given address range. +* +* @param Addr is address of ragne to be invalidated. +* @param Len is the length in bytes to be invalidated. +* +* @return None. +* +****************************************************************************/ +#define Xil_L1ICacheInvalidateRange(Addr, Len) \ + microblaze_invalidate_icache_range((Addr), (Len)) + +/****************************************************************************/ +/** +* +* @brief Invalidate the entire instruction cache. +* +* @param None +* +* @return None. +* +****************************************************************************/ +#define Xil_L1ICacheInvalidate() \ + microblaze_invalidate_icache() + + +/****************************************************************************/ +/** +* +* @brief Enable the L1 data cache. +* +* @return None. +* +* @note This is processor specific. +* +****************************************************************************/ +#define Xil_L1DCacheEnable() \ + microblaze_enable_dcache() + +/****************************************************************************/ +/** +* +* @brief Disable the L1 data cache. +* +* @return None. +* +* @note This is processor specific. +* +****************************************************************************/ +#define Xil_L1DCacheDisable() \ + microblaze_disable_dcache() + +/****************************************************************************/ +/** +* +* @brief Enable the instruction cache. +* +* @return None. +* +* @note This is processor specific. +* +****************************************************************************/ +#define Xil_L1ICacheEnable() \ + microblaze_enable_icache() + +/****************************************************************************/ +/** +* +* @brief Disable the L1 Instruction cache. +* +* @return None. +* +* @note This is processor specific. +* +****************************************************************************/ +#define Xil_L1ICacheDisable() \ + microblaze_disable_icache() + +/****************************************************************************/ +/** +* +* @brief Enable the data cache. +* +* @param None +* +* @return None. +* +****************************************************************************/ +#define Xil_DCacheEnable() Xil_L1DCacheEnable() + +/****************************************************************************/ +/** +* +* @brief Enable the instruction cache. +* +* @param None +* +* @return None. +* +* @note +* +* +****************************************************************************/ +#define Xil_ICacheEnable() Xil_L1ICacheEnable() + +/**************************************************************************** +* +* @brief Invalidate the entire Data cache. +* +* @param None. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +#define Xil_DCacheInvalidate() \ + Xil_L2CacheInvalidate(); \ + Xil_L1DCacheInvalidate(); + + +/**************************************************************************** +* +* @brief Invalidate the Data cache for the given address range. +* If the bytes specified by the address (adr) are cached by the +* Data cache, the cacheline containing that byte is invalidated. +* If the cacheline is modified (dirty), the modified contents are +* lost and are NOT written to system memory before the line is +* invalidated. +* +* @param Addr: Start address of ragne to be invalidated. +* @param Len: Length of range to be invalidated in bytes. +* +* @return None. +* +****************************************************************************/ +#define Xil_DCacheInvalidateRange(Addr, Len) \ + Xil_L2CacheInvalidateRange((Addr), (Len)); \ + Xil_L1DCacheInvalidateRange((Addr), (Len)); + + +/**************************************************************************** +* +* @brief Flush the entire Data cache. +* +* @param None. +* +* @return None. +* +****************************************************************************/ +#define Xil_DCacheFlush() \ + Xil_L2CacheFlush(); \ + Xil_L1DCacheFlush(); + +/**************************************************************************** +* @brief Flush the Data cache for the given address range. +* If the bytes specified by the address (adr) are cached by the +* Data cache, the cacheline containing that byte is invalidated. +* If the cacheline is modified (dirty), the written to system +* memory first before the before the line is invalidated. +* +* @param Addr: Start address of range to be flushed. +* @param Len: Length of range to be flushed in bytes. +* +* @return None. +* +****************************************************************************/ +#define Xil_DCacheFlushRange(Addr, Len) \ + Xil_L2CacheFlushRange((Addr), (Len)); \ + Xil_L1DCacheFlushRange((Addr), (Len)); + + +/**************************************************************************** +* +* @brief Invalidate the entire instruction cache. +* +* @param None. +* +* @return None. +* +****************************************************************************/ +#define Xil_ICacheInvalidate() \ + Xil_L2CacheInvalidate(); \ + Xil_L1ICacheInvalidate(); + + +/**************************************************************************** +* +* @brief Invalidate the instruction cache for the given address range. +* If the bytes specified by the address (adr) are cached by the +* Data cache, the cacheline containing that byte is invalidated. +* If the cacheline is modified (dirty), the modified contents are +* lost and are NOT written to system memory before the line is +* invalidated. +* +* @param Addr: Start address of ragne to be invalidated. +* @param Len: Length of range to be invalidated in bytes. +* +* @return None. +* +****************************************************************************/ +#define Xil_ICacheInvalidateRange(Addr, Len) \ + Xil_L2CacheInvalidateRange((Addr), (Len)); \ + Xil_L1ICacheInvalidateRange((Addr), (Len)); + +void Xil_DCacheDisable(void); +void Xil_ICacheDisable(void); + +#ifdef __cplusplus +} +#endif + +#endif + +#endif +/** +* @} End of "addtogroup microblaze_cache_apis". +*/ diff --git a/datalink814_sp/bsp/microblaze_ps/include/xil_cache_vxworks.h b/datalink814_sp/bsp/microblaze_ps/include/xil_cache_vxworks.h new file mode 100644 index 0000000..7e2a7d9 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/include/xil_cache_vxworks.h @@ -0,0 +1,89 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_cache_vxworks.h +* +* Contains the cache related functions for VxWorks that is wrapped by +* xil_cache. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date	 Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a hbm  12/11/09 Initial release
+*
+* 
+* +* @note +* +******************************************************************************/ + +#ifndef XIL_CACHE_VXWORKS_H +#define XIL_CACHE_VXWORKS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "vxWorks.h" +#include "vxLib.h" +#include "sysLibExtra.h" +#include "cacheLib.h" + +#if (CPU_FAMILY==PPC) + +#define Xil_DCacheEnable() cacheEnable(DATA_CACHE) + +#define Xil_DCacheDisable() cacheDisable(DATA_CACHE) + +#define Xil_DCacheInvalidateRange(Addr, Len) \ + cacheInvalidate(DATA_CACHE, (void *)(Addr), (Len)) + +#define Xil_DCacheFlushRange(Addr, Len) \ + cacheFlush(DATA_CACHE, (void *)(Addr), (Len)) + +#define Xil_ICacheEnable() cacheEnable(INSTRUCTION_CACHE) + +#define Xil_ICacheDisable() cacheDisable(INSTRUCTION_CACHE) + +#define Xil_ICacheInvalidateRange(Addr, Len) \ + cacheInvalidate(INSTRUCTION_CACHE, (void *)(Addr), (Len)) + + +#else +#error "Unknown processor / architecture. Must be PPC for VxWorks." +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/datalink814_sp/bsp/microblaze_ps/include/xil_exception.h b/datalink814_sp/bsp/microblaze_ps/include/xil_exception.h new file mode 100644 index 0000000..07c5357 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/include/xil_exception.h @@ -0,0 +1,127 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_exception.h +* +* @addtogroup microblaze_exception_apis Microblaze Exception APIs +* +* The xil_exception.h file contains Microblaze specific exception +* related APIs and macros. Application programs can use these APIs/Macros +* for various exception related operations (i.e. enable exception, disable +* exception, register exception hander etc.) +* +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00  hbm  07/28/09 Initial release
+*
+* 
+* +* @note +* To use exception related functions, the xil_exception.h file must be added in +* source code +* +******************************************************************************/ + +#ifndef XIL_EXCEPTION_H /* prevent circular inclusions */ +#define XIL_EXCEPTION_H /* by using protection macros */ + +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************** Constant Definitions *****************************/ + +/* + * These constants are specific to Microblaze processor. + */ + +#define XIL_EXCEPTION_ID_FIRST 0U +#define XIL_EXCEPTION_ID_FSL 0U +#define XIL_EXCEPTION_ID_UNALIGNED_ACCESS 1U +#define XIL_EXCEPTION_ID_ILLEGAL_OPCODE 2U +#define XIL_EXCEPTION_ID_M_AXI_I_EXCEPTION 3U +#define XIL_EXCEPTION_ID_IPLB_EXCEPTION 3U +#define XIL_EXCEPTION_ID_M_AXI_D_EXCEPTION 4U +#define XIL_EXCEPTION_ID_DPLB_EXCEPTION 4U +#define XIL_EXCEPTION_ID_DIV_BY_ZERO 5U +#define XIL_EXCEPTION_ID_FPU 6U +#define XIL_EXCEPTION_ID_STACK_VIOLATION 7U +#define XIL_EXCEPTION_ID_MMU 7U +#define XIL_EXCEPTION_ID_LAST XIL_EXCEPTION_ID_MMU + +/* + * XIL_EXCEPTION_ID_INT is defined for all processors, but with different value. + */ +#define XIL_EXCEPTION_ID_INT 16U /** + * exception ID for interrupt + */ + +/**************************** Type Definitions *******************************/ + +/** + * This typedef is the exception handler function. + */ +typedef void (*Xil_ExceptionHandler)(void *Data); + +/** + * This data type defines an interrupt handler for a device. + * The argument points to the instance of the component + */ +typedef void (*XInterruptHandler) (void *InstancePtr); + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + +extern void Xil_ExceptionRegisterHandler(u32 Id, + Xil_ExceptionHandler Handler, + void *Data); + +extern void Xil_ExceptionRemoveHandler(u32 Id); + +extern void Xil_ExceptionInit(void); +extern void Xil_ExceptionEnable(void); +extern void Xil_ExceptionDisable(void); + +#ifdef __cplusplus +} +#endif + +#endif +/** +* @} End of "addtogroup microblaze_exception_apis". +*/ \ No newline at end of file diff --git a/datalink814_sp/bsp/microblaze_ps/include/xil_hal.h b/datalink814_sp/bsp/microblaze_ps/include/xil_hal.h new file mode 100644 index 0000000..e8971c9 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/include/xil_hal.h @@ -0,0 +1,65 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_hal.h +* +* Contains all the HAL header files. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date	 Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a hbm  07/28/09 Initial release
+*
+* 
+* +* @note +* +******************************************************************************/ + +#ifndef XIL_HAL_H +#define XIL_HAL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "xil_cache.h" +#include "xil_io.h" +#include "xil_assert.h" +#include "xil_exception.h" +#include "xil_types.h" + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/datalink814_sp/bsp/microblaze_ps/include/xil_io.h b/datalink814_sp/bsp/microblaze_ps/include/xil_io.h new file mode 100644 index 0000000..00207cf --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/include/xil_io.h @@ -0,0 +1,341 @@ +/****************************************************************************** +* +* Copyright (C) 2014 - 2016 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_io.h +* +* @addtogroup common_io_interfacing_apis Register IO interfacing APIs +* +* The xil_io.h file contains the interface for the general I/O component, which +* encapsulates the Input/Output functions for the processors that do not +* require any special I/O handling. +* +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 5.00 	pkp  	 05/29/14 First release
+* 6.00  mus      08/19/16 Remove checking of __LITTLE_ENDIAN__ flag for
+*                         ARM processors
+* 
+******************************************************************************/ + +#ifndef XIL_IO_H /* prevent circular inclusions */ +#define XIL_IO_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_printf.h" + +#if defined (__MICROBLAZE__) +#include "mb_interface.h" +#else +#include "xpseudo_asm.h" +#endif + +/************************** Function Prototypes ******************************/ +u16 Xil_EndianSwap16(u16 Data); +u32 Xil_EndianSwap32(u32 Data); +#ifdef ENABLE_SAFETY +extern u32 XStl_RegUpdate(u32 RegAddr, u32 RegVal); +#endif + +/***************** Macros (Inline Functions) Definitions *********************/ +#if defined __GNUC__ +#if defined (__MICROBLAZE__) +# define INST_SYNC mbar(0) +# define DATA_SYNC mbar(1) +# else +# define SYNCHRONIZE_IO dmb() +# define INST_SYNC isb() +# define DATA_SYNC dsb() +# endif +#else +# define SYNCHRONIZE_IO +# define INST_SYNC +# define DATA_SYNC +# define INST_SYNC +# define DATA_SYNC +#endif + +#if defined (__GNUC__) || defined (__ICCARM__) || defined (__MICROBLAZE__) +#define INLINE inline +#else +#define INLINE __inline +#endif + +/*****************************************************************************/ +/** +* +* @brief Performs an input operation for a memory location by reading +* from the specified address and returning the 8 bit Value read from +* that address. +* +* @param Addr: contains the address to perform the input operation +* +* @return The 8 bit Value read from the specified input address. + +* +******************************************************************************/ +static INLINE u8 Xil_In8(UINTPTR Addr) +{ + return *(volatile u8 *) Addr; +} + +/*****************************************************************************/ +/** +* +* @brief Performs an input operation for a memory location by reading from +* the specified address and returning the 16 bit Value read from that +* address. +* +* @param Addr: contains the address to perform the input operation +* +* @return The 16 bit Value read from the specified input address. +* +******************************************************************************/ +static INLINE u16 Xil_In16(UINTPTR Addr) +{ + return *(volatile u16 *) Addr; +} + +/*****************************************************************************/ +/** +* +* @brief Performs an input operation for a memory location by +* reading from the specified address and returning the 32 bit Value +* read from that address. +* +* @param Addr: contains the address to perform the input operation +* +* @return The 32 bit Value read from the specified input address. +* +******************************************************************************/ +static INLINE u32 Xil_In32(UINTPTR Addr) +{ + return *(volatile u32 *) Addr; +} + +/*****************************************************************************/ +/** +* +* @brief Performs an input operation for a memory location by reading the +* 64 bit Value read from that address. +* +* +* @param Addr: contains the address to perform the input operation +* +* @return The 64 bit Value read from the specified input address. +* +******************************************************************************/ +static INLINE u64 Xil_In64(UINTPTR Addr) +{ + return *(volatile u64 *) Addr; +} + +/*****************************************************************************/ +/** +* +* @brief Performs an output operation for an memory location by +* writing the 8 bit Value to the the specified address. +* +* @param Addr: contains the address to perform the output operation +* @param Value: contains the 8 bit Value to be written at the specified +* address. +* +* @return None. +* +******************************************************************************/ +static INLINE void Xil_Out8(UINTPTR Addr, u8 Value) +{ + volatile u8 *LocalAddr = (volatile u8 *)Addr; + *LocalAddr = Value; +} + +/*****************************************************************************/ +/** +* +* @brief Performs an output operation for a memory location by writing the +* 16 bit Value to the the specified address. +* +* @param Addr contains the address to perform the output operation +* @param Value contains the Value to be written at the specified address. +* +* @return None. +* +******************************************************************************/ +static INLINE void Xil_Out16(UINTPTR Addr, u16 Value) +{ + volatile u16 *LocalAddr = (volatile u16 *)Addr; + *LocalAddr = Value; +} + +/*****************************************************************************/ +/** +* +* @brief Performs an output operation for a memory location by writing the +* 32 bit Value to the the specified address. +* +* @param Addr contains the address to perform the output operation +* @param Value contains the 32 bit Value to be written at the specified +* address. +* +* @return None. +* +******************************************************************************/ +static INLINE void Xil_Out32(UINTPTR Addr, u32 Value) +{ +#ifndef ENABLE_SAFETY + volatile u32 *LocalAddr = (volatile u32 *)Addr; + *LocalAddr = Value; +#else + XStl_RegUpdate(Addr, Value); +#endif +} + +/*****************************************************************************/ +/** +* +* @brief Performs an output operation for a memory location by writing the +* 64 bit Value to the the specified address. +* +* @param Addr contains the address to perform the output operation +* @param Value contains 64 bit Value to be written at the specified address. +* +* @return None. +* +******************************************************************************/ +static INLINE void Xil_Out64(UINTPTR Addr, u64 Value) +{ + volatile u64 *LocalAddr = (volatile u64 *)Addr; + *LocalAddr = Value; +} + +#if defined (__MICROBLAZE__) +#ifdef __LITTLE_ENDIAN__ +# define Xil_In16LE Xil_In16 +# define Xil_In32LE Xil_In32 +# define Xil_Out16LE Xil_Out16 +# define Xil_Out32LE Xil_Out32 +# define Xil_Htons Xil_EndianSwap16 +# define Xil_Htonl Xil_EndianSwap32 +# define Xil_Ntohs Xil_EndianSwap16 +# define Xil_Ntohl Xil_EndianSwap32 +# else +# define Xil_In16BE Xil_In16 +# define Xil_In32BE Xil_In32 +# define Xil_Out16BE Xil_Out16 +# define Xil_Out32BE Xil_Out32 +# define Xil_Htons(Data) (Data) +# define Xil_Htonl(Data) (Data) +# define Xil_Ntohs(Data) (Data) +# define Xil_Ntohl(Data) (Data) +#endif +#else +# define Xil_In16LE Xil_In16 +# define Xil_In32LE Xil_In32 +# define Xil_Out16LE Xil_Out16 +# define Xil_Out32LE Xil_Out32 +# define Xil_Htons Xil_EndianSwap16 +# define Xil_Htonl Xil_EndianSwap32 +# define Xil_Ntohs Xil_EndianSwap16 +# define Xil_Ntohl Xil_EndianSwap32 +#endif + +#if defined (__MICROBLAZE__) +#ifdef __LITTLE_ENDIAN__ +static INLINE u16 Xil_In16BE(UINTPTR Addr) +#else +static INLINE u16 Xil_In16LE(UINTPTR Addr) +#endif +#else +static INLINE u16 Xil_In16BE(UINTPTR Addr) +#endif +{ + u16 value = Xil_In16(Addr); + return Xil_EndianSwap16(value); +} + +#if defined (__MICROBLAZE__) +#ifdef __LITTLE_ENDIAN__ +static INLINE u32 Xil_In32BE(UINTPTR Addr) +#else +static INLINE u32 Xil_In32LE(UINTPTR Addr) +#endif +#else +static INLINE u32 Xil_In32BE(UINTPTR Addr) +#endif +{ + u32 value = Xil_In32(Addr); + return Xil_EndianSwap32(value); +} + +#if defined (__MICROBLAZE__) +#ifdef __LITTLE_ENDIAN__ +static INLINE void Xil_Out16BE(UINTPTR Addr, u16 Value) +#else +static INLINE void Xil_Out16LE(UINTPTR Addr, u16 Value) +#endif +#else +static INLINE void Xil_Out16BE(UINTPTR Addr, u16 Value) +#endif +{ + Value = Xil_EndianSwap16(Value); + Xil_Out16(Addr, Value); +} + +#if defined (__MICROBLAZE__) +#ifdef __LITTLE_ENDIAN__ +static INLINE void Xil_Out32BE(UINTPTR Addr, u32 Value) +#else +static INLINE void Xil_Out32LE(UINTPTR Addr, u32 Value) +#endif +#else +static INLINE void Xil_Out32BE(UINTPTR Addr, u32 Value) +#endif +{ + Value = Xil_EndianSwap32(Value); + Xil_Out32(Addr, Value); +} + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** +* @} End of "addtogroup common_io_interfacing_apis". +*/ diff --git a/datalink814_sp/bsp/microblaze_ps/include/xil_macroback.h b/datalink814_sp/bsp/microblaze_ps/include/xil_macroback.h new file mode 100644 index 0000000..b245c18 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/include/xil_macroback.h @@ -0,0 +1,1056 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +/*********************************************************************/ +/** + * @file xil_macroback.h + * + * This header file is meant to bring back the removed _m macros. + * This header file must be included last. + * The following macros are not defined here due to the driver change: + * XGpio_mSetDataDirection + * XGpio_mGetDataReg + * XGpio_mSetDataReg + * XIIC_RESET + * XIIC_CLEAR_STATS + * XSpi_mReset + * XSysAce_mSetCfgAddr + * XSysAce_mIsCfgDone + * XTft_mSetPixel + * XTft_mGetPixel + * XWdtTb_mEnableWdt + * XWdtTb_mDisbleWdt + * XWdtTb_mRestartWdt + * XWdtTb_mGetTimebaseReg + * XWdtTb_mHasReset + * + * Please refer the corresonding driver document for replacement. + * + *********************************************************************/ + +#ifndef XIL_MACROBACK_H +#define XIL_MACROBACK_H + +#ifdef __cplusplus +extern "C" { +#endif + +/*********************************************************************/ +/** + * Macros for Driver XCan + * + *********************************************************************/ +#ifndef XCan_mReadReg +#define XCan_mReadReg XCan_ReadReg +#endif + +#ifndef XCan_mWriteReg +#define XCan_mWriteReg XCan_WriteReg +#endif + +#ifndef XCan_mIsTxDone +#define XCan_mIsTxDone XCan_IsTxDone +#endif + +#ifndef XCan_mIsTxFifoFull +#define XCan_mIsTxFifoFull XCan_IsTxFifoFull +#endif + +#ifndef XCan_mIsHighPriorityBufFull +#define XCan_mIsHighPriorityBufFull XCan_IsHighPriorityBufFull +#endif + +#ifndef XCan_mIsRxEmpty +#define XCan_mIsRxEmpty XCan_IsRxEmpty +#endif + +#ifndef XCan_mIsAcceptFilterBusy +#define XCan_mIsAcceptFilterBusy XCan_IsAcceptFilterBusy +#endif + +#ifndef XCan_mCreateIdValue +#define XCan_mCreateIdValue XCan_CreateIdValue +#endif + +#ifndef XCan_mCreateDlcValue +#define XCan_mCreateDlcValue XCan_CreateDlcValue +#endif + +/*********************************************************************/ +/** + * Macros for Driver XDmaCentral + * + *********************************************************************/ +#ifndef XDmaCentral_mWriteReg +#define XDmaCentral_mWriteReg XDmaCentral_WriteReg +#endif + +#ifndef XDmaCentral_mReadReg +#define XDmaCentral_mReadReg XDmaCentral_ReadReg +#endif + +/*********************************************************************/ +/** + * Macros for Driver XDsAdc + * + *********************************************************************/ +#ifndef XDsAdc_mWriteReg +#define XDsAdc_mWriteReg XDsAdc_WriteReg +#endif + +#ifndef XDsAdc_mReadReg +#define XDsAdc_mReadReg XDsAdc_ReadReg +#endif + +#ifndef XDsAdc_mIsEmpty +#define XDsAdc_mIsEmpty XDsAdc_IsEmpty +#endif + +#ifndef XDsAdc_mSetFstmReg +#define XDsAdc_mSetFstmReg XDsAdc_SetFstmReg +#endif + +#ifndef XDsAdc_mGetFstmReg +#define XDsAdc_mGetFstmReg XDsAdc_GetFstmReg +#endif + +#ifndef XDsAdc_mEnableConversion +#define XDsAdc_mEnableConversion XDsAdc_EnableConversion +#endif + +#ifndef XDsAdc_mDisableConversion +#define XDsAdc_mDisableConversion XDsAdc_DisableConversion +#endif + +#ifndef XDsAdc_mGetFifoOccyReg +#define XDsAdc_mGetFifoOccyReg XDsAdc_GetFifoOccyReg +#endif + +/*********************************************************************/ +/** + * Macros for Driver XDsDac + * + *********************************************************************/ +#ifndef XDsDac_mWriteReg +#define XDsDac_mWriteReg XDsDac_WriteReg +#endif + +#ifndef XDsDac_mReadReg +#define XDsDac_mReadReg XDsDac_ReadReg +#endif + +#ifndef XDsDac_mIsEmpty +#define XDsDac_mIsEmpty XDsDac_IsEmpty +#endif + +#ifndef XDsDac_mFifoIsFull +#define XDsDac_mFifoIsFull XDsDac_FifoIsFull +#endif + +#ifndef XDsDac_mGetVacancy +#define XDsDac_mGetVacancy XDsDac_GetVacancy +#endif + +/*********************************************************************/ +/** + * Macros for Driver XEmacLite + * + *********************************************************************/ +#ifndef XEmacLite_mReadReg +#define XEmacLite_mReadReg XEmacLite_ReadReg +#endif + +#ifndef XEmacLite_mWriteReg +#define XEmacLite_mWriteReg XEmacLite_WriteReg +#endif + +#ifndef XEmacLite_mGetTxStatus +#define XEmacLite_mGetTxStatus XEmacLite_GetTxStatus +#endif + +#ifndef XEmacLite_mSetTxStatus +#define XEmacLite_mSetTxStatus XEmacLite_SetTxStatus +#endif + +#ifndef XEmacLite_mGetRxStatus +#define XEmacLite_mGetRxStatus XEmacLite_GetRxStatus +#endif + +#ifndef XEmacLite_mSetRxStatus +#define XEmacLite_mSetRxStatus XEmacLite_SetRxStatus +#endif + +#ifndef XEmacLite_mIsTxDone +#define XEmacLite_mIsTxDone XEmacLite_IsTxDone +#endif + +#ifndef XEmacLite_mIsRxEmpty +#define XEmacLite_mIsRxEmpty XEmacLite_IsRxEmpty +#endif + +#ifndef XEmacLite_mNextTransmitAddr +#define XEmacLite_mNextTransmitAddr XEmacLite_NextTransmitAddr +#endif + +#ifndef XEmacLite_mNextReceiveAddr +#define XEmacLite_mNextReceiveAddr XEmacLite_NextReceiveAddr +#endif + +#ifndef XEmacLite_mIsMdioConfigured +#define XEmacLite_mIsMdioConfigured XEmacLite_IsMdioConfigured +#endif + +#ifndef XEmacLite_mIsLoopbackConfigured +#define XEmacLite_mIsLoopbackConfigured XEmacLite_IsLoopbackConfigured +#endif + +#ifndef XEmacLite_mGetReceiveDataLength +#define XEmacLite_mGetReceiveDataLength XEmacLite_GetReceiveDataLength +#endif + +#ifndef XEmacLite_mGetTxActive +#define XEmacLite_mGetTxActive XEmacLite_GetTxActive +#endif + +#ifndef XEmacLite_mSetTxActive +#define XEmacLite_mSetTxActive XEmacLite_SetTxActive +#endif + +/*********************************************************************/ +/** + * Macros for Driver XGpio + * + *********************************************************************/ +#ifndef XGpio_mWriteReg +#define XGpio_mWriteReg XGpio_WriteReg +#endif + +#ifndef XGpio_mReadReg +#define XGpio_mReadReg XGpio_ReadReg +#endif + +/*********************************************************************/ +/** + * Macros for Driver XHwIcap + * + *********************************************************************/ +#ifndef XHwIcap_mFifoWrite +#define XHwIcap_mFifoWrite XHwIcap_FifoWrite +#endif + +#ifndef XHwIcap_mFifoRead +#define XHwIcap_mFifoRead XHwIcap_FifoRead +#endif + +#ifndef XHwIcap_mSetSizeReg +#define XHwIcap_mSetSizeReg XHwIcap_SetSizeReg +#endif + +#ifndef XHwIcap_mGetControlReg +#define XHwIcap_mGetControlReg XHwIcap_GetControlReg +#endif + +#ifndef XHwIcap_mStartConfig +#define XHwIcap_mStartConfig XHwIcap_StartConfig +#endif + +#ifndef XHwIcap_mStartReadBack +#define XHwIcap_mStartReadBack XHwIcap_StartReadBack +#endif + +#ifndef XHwIcap_mGetStatusReg +#define XHwIcap_mGetStatusReg XHwIcap_GetStatusReg +#endif + +#ifndef XHwIcap_mIsTransferDone +#define XHwIcap_mIsTransferDone XHwIcap_IsTransferDone +#endif + +#ifndef XHwIcap_mIsDeviceBusy +#define XHwIcap_mIsDeviceBusy XHwIcap_IsDeviceBusy +#endif + +#ifndef XHwIcap_mIntrGlobalEnable +#define XHwIcap_mIntrGlobalEnable XHwIcap_IntrGlobalEnable +#endif + +#ifndef XHwIcap_mIntrGlobalDisable +#define XHwIcap_mIntrGlobalDisable XHwIcap_IntrGlobalDisable +#endif + +#ifndef XHwIcap_mIntrGetStatus +#define XHwIcap_mIntrGetStatus XHwIcap_IntrGetStatus +#endif + +#ifndef XHwIcap_mIntrDisable +#define XHwIcap_mIntrDisable XHwIcap_IntrDisable +#endif + +#ifndef XHwIcap_mIntrEnable +#define XHwIcap_mIntrEnable XHwIcap_IntrEnable +#endif + +#ifndef XHwIcap_mIntrGetEnabled +#define XHwIcap_mIntrGetEnabled XHwIcap_IntrGetEnabled +#endif + +#ifndef XHwIcap_mIntrClear +#define XHwIcap_mIntrClear XHwIcap_IntrClear +#endif + +#ifndef XHwIcap_mGetWrFifoVacancy +#define XHwIcap_mGetWrFifoVacancy XHwIcap_GetWrFifoVacancy +#endif + +#ifndef XHwIcap_mGetRdFifoOccupancy +#define XHwIcap_mGetRdFifoOccupancy XHwIcap_GetRdFifoOccupancy +#endif + +#ifndef XHwIcap_mSliceX2Col +#define XHwIcap_mSliceX2Col XHwIcap_SliceX2Col +#endif + +#ifndef XHwIcap_mSliceY2Row +#define XHwIcap_mSliceY2Row XHwIcap_SliceY2Row +#endif + +#ifndef XHwIcap_mSliceXY2Slice +#define XHwIcap_mSliceXY2Slice XHwIcap_SliceXY2Slice +#endif + +#ifndef XHwIcap_mReadReg +#define XHwIcap_mReadReg XHwIcap_ReadReg +#endif + +#ifndef XHwIcap_mWriteReg +#define XHwIcap_mWriteReg XHwIcap_WriteReg +#endif + +/*********************************************************************/ +/** + * Macros for Driver XIic + * + *********************************************************************/ +#ifndef XIic_mReadReg +#define XIic_mReadReg XIic_ReadReg +#endif + +#ifndef XIic_mWriteReg +#define XIic_mWriteReg XIic_WriteReg +#endif + +#ifndef XIic_mEnterCriticalRegion +#define XIic_mEnterCriticalRegion XIic_IntrGlobalDisable +#endif + +#ifndef XIic_mExitCriticalRegion +#define XIic_mExitCriticalRegion XIic_IntrGlobalEnable +#endif + +#ifndef XIIC_GINTR_DISABLE +#define XIIC_GINTR_DISABLE XIic_IntrGlobalDisable +#endif + +#ifndef XIIC_GINTR_ENABLE +#define XIIC_GINTR_ENABLE XIic_IntrGlobalEnable +#endif + +#ifndef XIIC_IS_GINTR_ENABLED +#define XIIC_IS_GINTR_ENABLED XIic_IsIntrGlobalEnabled +#endif + +#ifndef XIIC_WRITE_IISR +#define XIIC_WRITE_IISR XIic_WriteIisr +#endif + +#ifndef XIIC_READ_IISR +#define XIIC_READ_IISR XIic_ReadIisr +#endif + +#ifndef XIIC_WRITE_IIER +#define XIIC_WRITE_IIER XIic_WriteIier +#endif + +#ifndef XIic_mClearIisr +#define XIic_mClearIisr XIic_ClearIisr +#endif + +#ifndef XIic_mSend7BitAddress +#define XIic_mSend7BitAddress XIic_Send7BitAddress +#endif + +#ifndef XIic_mDynSend7BitAddress +#define XIic_mDynSend7BitAddress XIic_DynSend7BitAddress +#endif + +#ifndef XIic_mDynSendStartStopAddress +#define XIic_mDynSendStartStopAddress XIic_DynSendStartStopAddress +#endif + +#ifndef XIic_mDynSendStop +#define XIic_mDynSendStop XIic_DynSendStop +#endif + +#ifndef XIic_mSend10BitAddrByte1 +#define XIic_mSend10BitAddrByte1 XIic_Send10BitAddrByte1 +#endif + +#ifndef XIic_mSend10BitAddrByte2 +#define XIic_mSend10BitAddrByte2 XIic_Send10BitAddrByte2 +#endif + +#ifndef XIic_mSend7BitAddr +#define XIic_mSend7BitAddr XIic_Send7BitAddr +#endif + +#ifndef XIic_mDisableIntr +#define XIic_mDisableIntr XIic_DisableIntr +#endif + +#ifndef XIic_mEnableIntr +#define XIic_mEnableIntr XIic_EnableIntr +#endif + +#ifndef XIic_mClearIntr +#define XIic_mClearIntr XIic_ClearIntr +#endif + +#ifndef XIic_mClearEnableIntr +#define XIic_mClearEnableIntr XIic_ClearEnableIntr +#endif + +#ifndef XIic_mFlushRxFifo +#define XIic_mFlushRxFifo XIic_FlushRxFifo +#endif + +#ifndef XIic_mFlushTxFifo +#define XIic_mFlushTxFifo XIic_FlushTxFifo +#endif + +#ifndef XIic_mReadRecvByte +#define XIic_mReadRecvByte XIic_ReadRecvByte +#endif + +#ifndef XIic_mWriteSendByte +#define XIic_mWriteSendByte XIic_WriteSendByte +#endif + +#ifndef XIic_mSetControlRegister +#define XIic_mSetControlRegister XIic_SetControlRegister +#endif + +/*********************************************************************/ +/** + * Macros for Driver XIntc + * + *********************************************************************/ +#ifndef XIntc_mMasterEnable +#define XIntc_mMasterEnable XIntc_MasterEnable +#endif + +#ifndef XIntc_mMasterDisable +#define XIntc_mMasterDisable XIntc_MasterDisable +#endif + +#ifndef XIntc_mEnableIntr +#define XIntc_mEnableIntr XIntc_EnableIntr +#endif + +#ifndef XIntc_mDisableIntr +#define XIntc_mDisableIntr XIntc_DisableIntr +#endif + +#ifndef XIntc_mAckIntr +#define XIntc_mAckIntr XIntc_AckIntr +#endif + +#ifndef XIntc_mGetIntrStatus +#define XIntc_mGetIntrStatus XIntc_GetIntrStatus +#endif + +/*********************************************************************/ +/** + * Macros for Driver XLlDma + * + *********************************************************************/ +#ifndef XLlDma_mBdRead +#define XLlDma_mBdRead XLlDma_BdRead +#endif + +#ifndef XLlDma_mBdWrite +#define XLlDma_mBdWrite XLlDma_BdWrite +#endif + +#ifndef XLlDma_mWriteReg +#define XLlDma_mWriteReg XLlDma_WriteReg +#endif + +#ifndef XLlDma_mReadReg +#define XLlDma_mReadReg XLlDma_ReadReg +#endif + +#ifndef XLlDma_mBdClear +#define XLlDma_mBdClear XLlDma_BdClear +#endif + +#ifndef XLlDma_mBdSetStsCtrl +#define XLlDma_mBdSetStsCtrl XLlDma_BdSetStsCtrl +#endif + +#ifndef XLlDma_mBdGetStsCtrl +#define XLlDma_mBdGetStsCtrl XLlDma_BdGetStsCtrl +#endif + +#ifndef XLlDma_mBdSetLength +#define XLlDma_mBdSetLength XLlDma_BdSetLength +#endif + +#ifndef XLlDma_mBdGetLength +#define XLlDma_mBdGetLength XLlDma_BdGetLength +#endif + +#ifndef XLlDma_mBdSetId +#define XLlDma_mBdSetId XLlDma_BdSetId +#endif + +#ifndef XLlDma_mBdGetId +#define XLlDma_mBdGetId XLlDma_BdGetId +#endif + +#ifndef XLlDma_mBdSetBufAddr +#define XLlDma_mBdSetBufAddr XLlDma_BdSetBufAddr +#endif + +#ifndef XLlDma_mBdGetBufAddr +#define XLlDma_mBdGetBufAddr XLlDma_BdGetBufAddr +#endif + +#ifndef XLlDma_mBdGetLength +#define XLlDma_mBdGetLength XLlDma_BdGetLength +#endif + +#ifndef XLlDma_mGetTxRing +#define XLlDma_mGetTxRing XLlDma_GetTxRing +#endif + +#ifndef XLlDma_mGetRxRing +#define XLlDma_mGetRxRing XLlDma_GetRxRing +#endif + +#ifndef XLlDma_mGetCr +#define XLlDma_mGetCr XLlDma_GetCr +#endif + +#ifndef XLlDma_mSetCr +#define XLlDma_mSetCr XLlDma_SetCr +#endif + +#ifndef XLlDma_mBdRingCntCalc +#define XLlDma_mBdRingCntCalc XLlDma_BdRingCntCalc +#endif + +#ifndef XLlDma_mBdRingMemCalc +#define XLlDma_mBdRingMemCalc XLlDma_BdRingMemCalc +#endif + +#ifndef XLlDma_mBdRingGetCnt +#define XLlDma_mBdRingGetCnt XLlDma_BdRingGetCnt +#endif + +#ifndef XLlDma_mBdRingGetFreeCnt +#define XLlDma_mBdRingGetFreeCnt XLlDma_BdRingGetFreeCnt +#endif + +#ifndef XLlDma_mBdRingSnapShotCurrBd +#define XLlDma_mBdRingSnapShotCurrBd XLlDma_BdRingSnapShotCurrBd +#endif + +#ifndef XLlDma_mBdRingNext +#define XLlDma_mBdRingNext XLlDma_BdRingNext +#endif + +#ifndef XLlDma_mBdRingPrev +#define XLlDma_mBdRingPrev XLlDma_BdRingPrev +#endif + +#ifndef XLlDma_mBdRingGetSr +#define XLlDma_mBdRingGetSr XLlDma_BdRingGetSr +#endif + +#ifndef XLlDma_mBdRingSetSr +#define XLlDma_mBdRingSetSr XLlDma_BdRingSetSr +#endif + +#ifndef XLlDma_mBdRingGetCr +#define XLlDma_mBdRingGetCr XLlDma_BdRingGetCr +#endif + +#ifndef XLlDma_mBdRingSetCr +#define XLlDma_mBdRingSetCr XLlDma_BdRingSetCr +#endif + +#ifndef XLlDma_mBdRingBusy +#define XLlDma_mBdRingBusy XLlDma_BdRingBusy +#endif + +#ifndef XLlDma_mBdRingIntEnable +#define XLlDma_mBdRingIntEnable XLlDma_BdRingIntEnable +#endif + +#ifndef XLlDma_mBdRingIntDisable +#define XLlDma_mBdRingIntDisable XLlDma_BdRingIntDisable +#endif + +#ifndef XLlDma_mBdRingIntGetEnabled +#define XLlDma_mBdRingIntGetEnabled XLlDma_BdRingIntGetEnabled +#endif + +#ifndef XLlDma_mBdRingGetIrq +#define XLlDma_mBdRingGetIrq XLlDma_BdRingGetIrq +#endif + +#ifndef XLlDma_mBdRingAckIrq +#define XLlDma_mBdRingAckIrq XLlDma_BdRingAckIrq +#endif + +/*********************************************************************/ +/** + * Macros for Driver XMbox + * + *********************************************************************/ +#ifndef XMbox_mWriteReg +#define XMbox_mWriteReg XMbox_WriteReg +#endif + +#ifndef XMbox_mReadReg +#define XMbox_mReadReg XMbox_ReadReg +#endif + +#ifndef XMbox_mWriteMBox +#define XMbox_mWriteMBox XMbox_WriteMBox +#endif + +#ifndef XMbox_mReadMBox +#define XMbox_mReadMBox XMbox_ReadMBox +#endif + +#ifndef XMbox_mFSLReadMBox +#define XMbox_mFSLReadMBox XMbox_FSLReadMBox +#endif + +#ifndef XMbox_mFSLWriteMBox +#define XMbox_mFSLWriteMBox XMbox_FSLWriteMBox +#endif + +#ifndef XMbox_mFSLIsEmpty +#define XMbox_mFSLIsEmpty XMbox_FSLIsEmpty +#endif + +#ifndef XMbox_mFSLIsFull +#define XMbox_mFSLIsFull XMbox_FSLIsFull +#endif + +#ifndef XMbox_mIsEmpty +#define XMbox_mIsEmpty XMbox_IsEmptyHw +#endif + +#ifndef XMbox_mIsFull +#define XMbox_mIsFull XMbox_IsFullHw +#endif + +/*********************************************************************/ +/** + * Macros for Driver XMpmc + * + *********************************************************************/ +#ifndef XMpmc_mReadReg +#define XMpmc_mReadReg XMpmc_ReadReg +#endif + +#ifndef XMpmc_mWriteReg +#define XMpmc_mWriteReg XMpmc_WriteReg +#endif + +/*********************************************************************/ +/** + * Macros for Driver XMutex + * + *********************************************************************/ +#ifndef XMutex_mWriteReg +#define XMutex_mWriteReg XMutex_WriteReg +#endif + +#ifndef XMutex_mReadReg +#define XMutex_mReadReg XMutex_ReadReg +#endif + +/*********************************************************************/ +/** + * Macros for Driver XPcie + * + *********************************************************************/ +#ifndef XPcie_mReadReg +#define XPcie_mReadReg XPcie_ReadReg +#endif + +#ifndef XPcie_mWriteReg +#define XPcie_mWriteReg XPcie_WriteReg +#endif + +/*********************************************************************/ +/** + * Macros for Driver XSpi + * + *********************************************************************/ +#ifndef XSpi_mIntrGlobalEnable +#define XSpi_mIntrGlobalEnable XSpi_IntrGlobalEnable +#endif + +#ifndef XSpi_mIntrGlobalDisable +#define XSpi_mIntrGlobalDisable XSpi_IntrGlobalDisable +#endif + +#ifndef XSpi_mIsIntrGlobalEnabled +#define XSpi_mIsIntrGlobalEnabled XSpi_IsIntrGlobalEnabled +#endif + +#ifndef XSpi_mIntrGetStatus +#define XSpi_mIntrGetStatus XSpi_IntrGetStatus +#endif + +#ifndef XSpi_mIntrClear +#define XSpi_mIntrClear XSpi_IntrClear +#endif + +#ifndef XSpi_mIntrEnable +#define XSpi_mIntrEnable XSpi_IntrEnable +#endif + +#ifndef XSpi_mIntrDisable +#define XSpi_mIntrDisable XSpi_IntrDisable +#endif + +#ifndef XSpi_mIntrGetEnabled +#define XSpi_mIntrGetEnabled XSpi_IntrGetEnabled +#endif + +#ifndef XSpi_mSetControlReg +#define XSpi_mSetControlReg XSpi_SetControlReg +#endif + +#ifndef XSpi_mGetControlReg +#define XSpi_mGetControlReg XSpi_GetControlReg +#endif + +#ifndef XSpi_mGetStatusReg +#define XSpi_mGetStatusReg XSpi_GetStatusReg +#endif + +#ifndef XSpi_mSetSlaveSelectReg +#define XSpi_mSetSlaveSelectReg XSpi_SetSlaveSelectReg +#endif + +#ifndef XSpi_mGetSlaveSelectReg +#define XSpi_mGetSlaveSelectReg XSpi_GetSlaveSelectReg +#endif + +#ifndef XSpi_mEnable +#define XSpi_mEnable XSpi_Enable +#endif + +#ifndef XSpi_mDisable +#define XSpi_mDisable XSpi_Disable +#endif + +/*********************************************************************/ +/** + * Macros for Driver XSysAce + * + *********************************************************************/ +#ifndef XSysAce_mGetControlReg +#define XSysAce_mGetControlReg XSysAce_GetControlReg +#endif + +#ifndef XSysAce_mSetControlReg +#define XSysAce_mSetControlReg XSysAce_SetControlReg +#endif + +#ifndef XSysAce_mOrControlReg +#define XSysAce_mOrControlReg XSysAce_OrControlReg +#endif + +#ifndef XSysAce_mAndControlReg +#define XSysAce_mAndControlReg XSysAce_AndControlReg +#endif + +#ifndef XSysAce_mGetErrorReg +#define XSysAce_mGetErrorReg XSysAce_GetErrorReg +#endif + +#ifndef XSysAce_mGetStatusReg +#define XSysAce_mGetStatusReg XSysAce_GetStatusReg +#endif + +#ifndef XSysAce_mWaitForLock +#define XSysAce_mWaitForLock XSysAce_WaitForLock +#endif + +#ifndef XSysAce_mEnableIntr +#define XSysAce_mEnableIntr XSysAce_EnableIntr +#endif + +#ifndef XSysAce_mDisableIntr +#define XSysAce_mDisableIntr XSysAce_DisableIntr +#endif + +#ifndef XSysAce_mIsReadyForCmd +#define XSysAce_mIsReadyForCmd XSysAce_IsReadyForCmd +#endif + +#ifndef XSysAce_mIsMpuLocked +#define XSysAce_mIsMpuLocked XSysAce_IsMpuLocked +#endif + +#ifndef XSysAce_mIsIntrEnabled +#define XSysAce_mIsIntrEnabled XSysAce_IsIntrEnabled +#endif + +/*********************************************************************/ +/** + * Macros for Driver XSysMon + * + *********************************************************************/ +#ifndef XSysMon_mIsEventSamplingModeSet +#define XSysMon_mIsEventSamplingModeSet XSysMon_IsEventSamplingModeSet +#endif + +#ifndef XSysMon_mIsDrpBusy +#define XSysMon_mIsDrpBusy XSysMon_IsDrpBusy +#endif + +#ifndef XSysMon_mIsDrpLocked +#define XSysMon_mIsDrpLocked XSysMon_IsDrpLocked +#endif + +#ifndef XSysMon_mRawToTemperature +#define XSysMon_mRawToTemperature XSysMon_RawToTemperature +#endif + +#ifndef XSysMon_mRawToVoltage +#define XSysMon_mRawToVoltage XSysMon_RawToVoltage +#endif + +#ifndef XSysMon_mTemperatureToRaw +#define XSysMon_mTemperatureToRaw XSysMon_TemperatureToRaw +#endif + +#ifndef XSysMon_mVoltageToRaw +#define XSysMon_mVoltageToRaw XSysMon_VoltageToRaw +#endif + +#ifndef XSysMon_mReadReg +#define XSysMon_mReadReg XSysMon_ReadReg +#endif + +#ifndef XSysMon_mWriteReg +#define XSysMon_mWriteReg XSysMon_WriteReg +#endif + +/*********************************************************************/ +/** + * Macros for Driver XTmrCtr + * + *********************************************************************/ +#ifndef XTimerCtr_mReadReg +#define XTimerCtr_mReadReg XTimerCtr_ReadReg +#endif + +#ifndef XTmrCtr_mWriteReg +#define XTmrCtr_mWriteReg XTmrCtr_WriteReg +#endif + +#ifndef XTmrCtr_mSetControlStatusReg +#define XTmrCtr_mSetControlStatusReg XTmrCtr_SetControlStatusReg +#endif + +#ifndef XTmrCtr_mGetControlStatusReg +#define XTmrCtr_mGetControlStatusReg XTmrCtr_GetControlStatusReg +#endif + +#ifndef XTmrCtr_mGetTimerCounterReg +#define XTmrCtr_mGetTimerCounterReg XTmrCtr_GetTimerCounterReg +#endif + +#ifndef XTmrCtr_mSetLoadReg +#define XTmrCtr_mSetLoadReg XTmrCtr_SetLoadReg +#endif + +#ifndef XTmrCtr_mGetLoadReg +#define XTmrCtr_mGetLoadReg XTmrCtr_GetLoadReg +#endif + +#ifndef XTmrCtr_mEnable +#define XTmrCtr_mEnable XTmrCtr_Enable +#endif + +#ifndef XTmrCtr_mDisable +#define XTmrCtr_mDisable XTmrCtr_Disable +#endif + +#ifndef XTmrCtr_mEnableIntr +#define XTmrCtr_mEnableIntr XTmrCtr_EnableIntr +#endif + +#ifndef XTmrCtr_mDisableIntr +#define XTmrCtr_mDisableIntr XTmrCtr_DisableIntr +#endif + +#ifndef XTmrCtr_mLoadTimerCounterReg +#define XTmrCtr_mLoadTimerCounterReg XTmrCtr_LoadTimerCounterReg +#endif + +#ifndef XTmrCtr_mHasEventOccurred +#define XTmrCtr_mHasEventOccurred XTmrCtr_HasEventOccurred +#endif + +/*********************************************************************/ +/** + * Macros for Driver XUartLite + * + *********************************************************************/ +#ifndef XUartLite_mUpdateStats +#define XUartLite_mUpdateStats XUartLite_UpdateStats +#endif + +#ifndef XUartLite_mWriteReg +#define XUartLite_mWriteReg XUartLite_WriteReg +#endif + +#ifndef XUartLite_mReadReg +#define XUartLite_mReadReg XUartLite_ReadReg +#endif + +#ifndef XUartLite_mClearStats +#define XUartLite_mClearStats XUartLite_ClearStats +#endif + +#ifndef XUartLite_mSetControlReg +#define XUartLite_mSetControlReg XUartLite_SetControlReg +#endif + +#ifndef XUartLite_mGetStatusReg +#define XUartLite_mGetStatusReg XUartLite_GetStatusReg +#endif + +#ifndef XUartLite_mIsReceiveEmpty +#define XUartLite_mIsReceiveEmpty XUartLite_IsReceiveEmpty +#endif + +#ifndef XUartLite_mIsTransmitFull +#define XUartLite_mIsTransmitFull XUartLite_IsTransmitFull +#endif + +#ifndef XUartLite_mIsIntrEnabled +#define XUartLite_mIsIntrEnabled XUartLite_IsIntrEnabled +#endif + +#ifndef XUartLite_mEnableIntr +#define XUartLite_mEnableIntr XUartLite_EnableIntr +#endif + +#ifndef XUartLite_mDisableIntr +#define XUartLite_mDisableIntr XUartLite_DisableIntr +#endif + +/*********************************************************************/ +/** + * Macros for Driver XUartNs550 + * + *********************************************************************/ +#ifndef XUartNs550_mUpdateStats +#define XUartNs550_mUpdateStats XUartNs550_UpdateStats +#endif + +#ifndef XUartNs550_mReadReg +#define XUartNs550_mReadReg XUartNs550_ReadReg +#endif + +#ifndef XUartNs550_mWriteReg +#define XUartNs550_mWriteReg XUartNs550_WriteReg +#endif + +#ifndef XUartNs550_mClearStats +#define XUartNs550_mClearStats XUartNs550_ClearStats +#endif + +#ifndef XUartNs550_mGetLineStatusReg +#define XUartNs550_mGetLineStatusReg XUartNs550_GetLineStatusReg +#endif + +#ifndef XUartNs550_mGetLineControlReg +#define XUartNs550_mGetLineControlReg XUartNs550_GetLineControlReg +#endif + +#ifndef XUartNs550_mSetLineControlReg +#define XUartNs550_mSetLineControlReg XUartNs550_SetLineControlReg +#endif + +#ifndef XUartNs550_mEnableIntr +#define XUartNs550_mEnableIntr XUartNs550_EnableIntr +#endif + +#ifndef XUartNs550_mDisableIntr +#define XUartNs550_mDisableIntr XUartNs550_DisableIntr +#endif + +#ifndef XUartNs550_mIsReceiveData +#define XUartNs550_mIsReceiveData XUartNs550_IsReceiveData +#endif + +#ifndef XUartNs550_mIsTransmitEmpty +#define XUartNs550_mIsTransmitEmpty XUartNs550_IsTransmitEmpty +#endif + +/*********************************************************************/ +/** + * Macros for Driver XUsb + * + *********************************************************************/ +#ifndef XUsb_mReadReg +#define XUsb_mReadReg XUsb_ReadReg +#endif + +#ifndef XUsb_mWriteReg +#define XUsb_mWriteReg XUsb_WriteReg +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/datalink814_sp/bsp/microblaze_ps/include/xil_mem.h b/datalink814_sp/bsp/microblaze_ps/include/xil_mem.h new file mode 100644 index 0000000..9aae942 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/include/xil_mem.h @@ -0,0 +1,68 @@ +/******************************************************************************/ +/** +* Copyright (C) 2015 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* @file xil_mem.h +* +* @addtogroup common_mem_operation_api Customized APIs for Memory Operations +* +* The xil_mem.h file contains prototype for functions related +* to memory operations. These APIs are applicable for all processors supported +* by Xilinx. +* +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 6.1   nsk      11/07/16 First release.
+* 7.0   mus      01/07/19 Add cpp extern macro
+*
+* 
+* +*****************************************************************************/ +#ifndef XIL_MEM_H /* prevent circular inclusions */ +#define XIL_MEM_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/************************** Function Prototypes *****************************/ + +void Xil_MemCpy(void* dst, const void* src, u32 cnt); + +#ifdef __cplusplus +} +#endif + +#endif /* XIL_MEM_H */ +/** +* @} End of "addtogroup common_mem_operation_api". +*/ \ No newline at end of file diff --git a/datalink814_sp/bsp/microblaze_ps/include/xil_misc_psreset_api.h b/datalink814_sp/bsp/microblaze_ps/include/xil_misc_psreset_api.h new file mode 100644 index 0000000..f795f2e --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/include/xil_misc_psreset_api.h @@ -0,0 +1,273 @@ +/****************************************************************************** +* +* Copyright (C) 2013 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file xil_misc_psreset_api.h +* +* This file contains the various register defintions and function prototypes for +* implementing the reset functionality of zynq ps devices +* +* MODIFICATION HISTORY: +* +* Ver Who Date Changes +* ----- ---- -------- ------------------------------------------------------- +* 1.00b kpc 03/07/13 First release. +* +* +******************************************************************************/ + +#ifndef XIL_MISC_RESET_H /* prevent circular inclusions */ +#define XIL_MISC_RESET_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + + +/***************************** Include Files *********************************/ +#include "xil_types.h" +#include "xil_io.h" + +/************************** Constant Definitions *****************************/ +#define XDDRC_CTRL_BASEADDR 0xF8006000U +#define XSLCR_BASEADDR 0xF8000000U +/**< OCM configuration register */ +#define XSLCR_OCM_CFG_ADDR (XSLCR_BASEADDR + 0x00000910U) +/**< SLCR unlock register */ +#define XSLCR_UNLOCK_ADDR (XSLCR_BASEADDR + 0x00000008U) +/**< SLCR GEM0 rx clock control register */ +#define XSLCR_GEM0_RCLK_CTRL_ADDR (XSLCR_BASEADDR + 0x00000138U) +/**< SLCR GEM1 rx clock control register */ +#define XSLCR_GEM1_RCLK_CTRL_ADDR (XSLCR_BASEADDR + 0x0000013CU) +/**< SLCR GEM0 clock control register */ +#define XSLCR_GEM0_CLK_CTRL_ADDR (XSLCR_BASEADDR + 0x00000140U) +/**< SLCR GEM1 clock control register */ +#define XSLCR_GEM1_CLK_CTRL_ADDR (XSLCR_BASEADDR + 0x00000144U) +/**< SLCR SMC clock control register */ +#define XSLCR_SMC_CLK_CTRL_ADDR (XSLCR_BASEADDR + 0x00000148U) +/**< SLCR GEM reset control register */ +#define XSLCR_GEM_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000214U) +/**< SLCR USB0 clock control register */ +#define XSLCR_USB0_CLK_CTRL_ADDR (XSLCR_BASEADDR + 0x00000130U) +/**< SLCR USB1 clock control register */ +#define XSLCR_USB1_CLK_CTRL_ADDR (XSLCR_BASEADDR + 0x00000134U) +/**< SLCR USB1 reset control register */ +#define XSLCR_USB_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000210U) +/**< SLCR SMC reset control register */ +#define XSLCR_SMC_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000234U) +/**< SLCR Level shifter enable register */ +#define XSLCR_LVL_SHFTR_EN_ADDR (XSLCR_BASEADDR + 0x00000900U) +/**< SLCR ARM pll control register */ +#define XSLCR_ARM_PLL_CTRL_ADDR (XSLCR_BASEADDR + 0x00000100U) +/**< SLCR DDR pll control register */ +#define XSLCR_DDR_PLL_CTRL_ADDR (XSLCR_BASEADDR + 0x00000104U) +/**< SLCR IO pll control register */ +#define XSLCR_IO_PLL_CTRL_ADDR (XSLCR_BASEADDR + 0x00000108U) +/**< SLCR ARM pll configuration register */ +#define XSLCR_ARM_PLL_CFG_ADDR (XSLCR_BASEADDR + 0x00000110U) +/**< SLCR DDR pll configuration register */ +#define XSLCR_DDR_PLL_CFG_ADDR (XSLCR_BASEADDR + 0x00000114U) +/**< SLCR IO pll configuration register */ +#define XSLCR_IO_PLL_CFG_ADDR (XSLCR_BASEADDR + 0x00000118U) +/**< SLCR ARM clock control register */ +#define XSLCR_ARM_CLK_CTRL_ADDR (XSLCR_BASEADDR + 0x00000120U) +/**< SLCR DDR clock control register */ +#define XSLCR_DDR_CLK_CTRL_ADDR (XSLCR_BASEADDR + 0x00000124U) +/**< SLCR MIO pin address register */ +#define XSLCR_MIO_PIN_00_ADDR (XSLCR_BASEADDR + 0x00000700U) +/**< SLCR DMAC reset control address register */ +#define XSLCR_DMAC_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x0000020CU) +/**< SLCR USB reset control address register */ +/*#define XSLCR_USB_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000210U)*/ +/**< SLCR GEM reset control address register */ +/*#define XSLCR_GEM_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000214U)*/ +/**< SLCR SDIO reset control address register */ +#define XSLCR_SDIO_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000218U) +/**< SLCR SPI reset control address register */ +#define XSLCR_SPI_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x0000021CU) +/**< SLCR CAN reset control address register */ +#define XSLCR_CAN_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000220U) +/**< SLCR I2C reset control address register */ +#define XSLCR_I2C_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000224U) +/**< SLCR UART reset control address register */ +#define XSLCR_UART_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000228U) +/**< SLCR GPIO reset control address register */ +#define XSLCR_GPIO_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x0000022CU) +/**< SLCR LQSPI reset control address register */ +#define XSLCR_LQSPI_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000230U) +/**< SLCR SMC reset control address register */ +/*#define XSLCR_SMC_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000234U)*/ +/**< SLCR OCM reset control address register */ +#define XSLCR_OCM_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000238U) + +/**< SMC mem controller clear config register */ +#define XSMC_MEMC_CLR_CONFIG_OFFSET 0x0000000CU +/**< SMC idlecount configuration register */ +#define XSMC_REFRESH_PERIOD_0_OFFSET 0x00000020U +#define XSMC_REFRESH_PERIOD_1_OFFSET 0x00000024U +/**< SMC ECC configuration register */ +#define XSMC_ECC_MEMCFG1_OFFSET 0x00000404U +/**< SMC ECC command 1 register */ +#define XSMC_ECC_MEMCMD1_OFFSET 0x00000404U +/**< SMC ECC command 2 register */ +#define XSMC_ECC_MEMCMD2_OFFSET 0x00000404U + +/**< SLCR unlock code */ +#define XSLCR_UNLOCK_CODE 0x0000DF0DU + +/**< SMC mem clear configuration mask */ +#define XSMC_MEMC_CLR_CONFIG_MASK 0x0000005FU +/**< SMC ECC memconfig 1 reset value */ +#define XSMC_ECC_MEMCFG1_RESET_VAL 0x00000043U +/**< SMC ECC memcommand 1 reset value */ +#define XSMC_ECC_MEMCMD1_RESET_VAL 0x01300080U +/**< SMC ECC memcommand 2 reset value */ +#define XSMC_ECC_MEMCMD2_RESET_VAL 0x01E00585U + +/**< DDR controller reset bit mask */ +#define XDDRPS_CTRL_RESET_MASK 0x00000001U +/**< SLCR OCM configuration reset value*/ +#define XSLCR_OCM_CFG_RESETVAL 0x00000008U +/**< SLCR OCM bank selection mask*/ +#define XSLCR_OCM_CFG_HIADDR_MASK 0x0000000FU +/**< SLCR level shifter enable mask*/ +#define XSLCR_LVL_SHFTR_EN_MASK 0x0000000FU + +/**< SLCR PLL register reset values */ +#define XSLCR_ARM_PLL_CTRL_RESET_VAL 0x0001A008U +#define XSLCR_DDR_PLL_CTRL_RESET_VAL 0x0001A008U +#define XSLCR_IO_PLL_CTRL_RESET_VAL 0x0001A008U +#define XSLCR_ARM_PLL_CFG_RESET_VAL 0x00177EA0U +#define XSLCR_DDR_PLL_CFG_RESET_VAL 0x00177EA0U +#define XSLCR_IO_PLL_CFG_RESET_VAL 0x00177EA0U +#define XSLCR_ARM_CLK_CTRL_RESET_VAL 0x1F000400U +#define XSLCR_DDR_CLK_CTRL_RESET_VAL 0x18400003U + +/**< SLCR MIO register default values */ +#define XSLCR_MIO_PIN_00_RESET_VAL 0x00001601U +#define XSLCR_MIO_PIN_02_RESET_VAL 0x00000601U + +/**< SLCR Reset control registers default values */ +#define XSLCR_DMAC_RST_CTRL_VAL 0x00000001U +#define XSLCR_GEM_RST_CTRL_VAL 0x000000F3U +#define XSLCR_USB_RST_CTRL_VAL 0x00000003U +#define XSLCR_I2C_RST_CTRL_VAL 0x00000003U +#define XSLCR_SPI_RST_CTRL_VAL 0x0000000FU +#define XSLCR_UART_RST_CTRL_VAL 0x0000000FU +#define XSLCR_QSPI_RST_CTRL_VAL 0x00000003U +#define XSLCR_GPIO_RST_CTRL_VAL 0x00000001U +#define XSLCR_SMC_RST_CTRL_VAL 0x00000003U +#define XSLCR_OCM_RST_CTRL_VAL 0x00000001U +#define XSLCR_SDIO_RST_CTRL_VAL 0x00000033U +#define XSLCR_CAN_RST_CTRL_VAL 0x00000003U +/**************************** Type Definitions *******************************/ + +/* the following data type is used to hold a null terminated version string + * consisting of the following format, "X.YYX" + */ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ +/* + * Performs reset operation to the ddr interface + */ +void XDdr_ResetHw(void); +/* + * Map the ocm region to post bootrom state + */ +void XOcm_Remap(void); +/* + * Performs the smc interface reset + */ +void XSmc_ResetHw(u32 BaseAddress); +/* + * updates the MIO registers with reset values + */ +void XSlcr_MioWriteResetValues(void); +/* + * updates the PLL and clock registers with reset values + */ +void XSlcr_PllWriteResetValues(void); +/* + * Disables the level shifters + */ +void XSlcr_DisableLevelShifters(void); +/* + * provides softreset to the GPIO interface + */ +void XSlcr_GpioPsReset(void); +/* + * provides softreset to the DMA interface + */ +void XSlcr_DmaPsReset(void); +/* + * provides softreset to the SMC interface + */ +void XSlcr_SmcPsReset(void); +/* + * provides softreset to the CAN interface + */ +void XSlcr_CanPsReset(void); +/* + * provides softreset to the Uart interface + */ +void XSlcr_UartPsReset(void); +/* + * provides softreset to the I2C interface + */ +void XSlcr_I2cPsReset(void); +/* + * provides softreset to the SPI interface + */ +void XSlcr_SpiPsReset(void); +/* + * provides softreset to the QSPI interface + */ +void XSlcr_QspiPsReset(void); +/* + * provides softreset to the USB interface + */ +void XSlcr_UsbPsReset(void); +/* + * provides softreset to the GEM interface + */ +void XSlcr_EmacPsReset(void); +/* + * provides softreset to the OCM interface + */ +void XSlcr_OcmReset(void); + + +#ifdef __cplusplus +} +#endif + +#endif /* XIL_MISC_RESET_H */ diff --git a/datalink814_sp/bsp/microblaze_ps/include/xil_printf.h b/datalink814_sp/bsp/microblaze_ps/include/xil_printf.h new file mode 100644 index 0000000..a0177fc --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/include/xil_printf.h @@ -0,0 +1,48 @@ + #ifndef XIL_PRINTF_H + #define XIL_PRINTF_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include "xil_types.h" +#include "xparameters.h" +#include "bspconfig.h" +#if defined (__aarch64__) && HYP_GUEST && EL1_NONSECURE && XEN_USE_PV_CONSOLE +#include "xen_console.h" +#endif + +/*----------------------------------------------------*/ +/* Use the following parameter passing structure to */ +/* make xil_printf re-entrant. */ +/*----------------------------------------------------*/ + +struct params_s; + + +/*---------------------------------------------------*/ +/* The purpose of this routine is to output data the */ +/* same as the standard printf function without the */ +/* overhead most run-time libraries involve. Usually */ +/* the printf brings in many kilobytes of code and */ +/* that is unacceptable in most embedded systems. */ +/*---------------------------------------------------*/ + +typedef char8* charptr; +typedef s32 (*func_ptr)(int c); + +/* */ + +void xil_printf( const char8 *ctrl1, ...); +void print( const char8 *ptr); +extern void outbyte (char8 c); +extern char8 inbyte(void); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ diff --git a/datalink814_sp/bsp/microblaze_ps/include/xil_testcache.h b/datalink814_sp/bsp/microblaze_ps/include/xil_testcache.h new file mode 100644 index 0000000..8289ca9 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/include/xil_testcache.h @@ -0,0 +1,67 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_testcache.h +* +* @addtogroup common_test_utils +*

Cache test

+* The xil_testcache.h file contains utility functions to test cache. +* +* @{ +*
+* Ver    Who    Date    Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a hbm  07/29/09 First release
+* 
+* +******************************************************************************/ + +#ifndef XIL_TESTCACHE_H /* prevent circular inclusions */ +#define XIL_TESTCACHE_H /* by using protection macros */ + +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern s32 Xil_TestDCacheRange(void); +extern s32 Xil_TestDCacheAll(void); +extern s32 Xil_TestICacheRange(void); +extern s32 Xil_TestICacheAll(void); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** +* @} End of "addtogroup common_test_utils". +*/ \ No newline at end of file diff --git a/datalink814_sp/bsp/microblaze_ps/include/xil_testio.h b/datalink814_sp/bsp/microblaze_ps/include/xil_testio.h new file mode 100644 index 0000000..6f0fc1c --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/include/xil_testio.h @@ -0,0 +1,90 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_testio.h +* +* @addtogroup common_test_utils Test Utilities +*

I/O test

+* The xil_testio.h file contains utility functions to test endian related memory +* IO functions. +* +* A subset of the memory tests can be selected or all of the tests can be run +* in order. If there is an error detected by a subtest, the test stops and the +* failure code is returned. Further tests are not run even if all of the tests +* are selected. +* +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver    Who    Date    Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00 hbm  08/05/09 First release
+* 
+* +******************************************************************************/ + +#ifndef XIL_TESTIO_H /* prevent circular inclusions */ +#define XIL_TESTIO_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ +#include "xil_types.h" + +/************************** Constant Definitions *****************************/ + + +#define XIL_TESTIO_DEFAULT 0 +#define XIL_TESTIO_LE 1 +#define XIL_TESTIO_BE 2 + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + +extern s32 Xil_TestIO8(u8 *Addr, s32 Length, u8 Value); +extern s32 Xil_TestIO16(u16 *Addr, s32 Length, u16 Value, s32 Kind, s32 Swap); +extern s32 Xil_TestIO32(u32 *Addr, s32 Length, u32 Value, s32 Kind, s32 Swap); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** +* @} End of "addtogroup common_test_utils". +*/ diff --git a/datalink814_sp/bsp/microblaze_ps/include/xil_testmem.h b/datalink814_sp/bsp/microblaze_ps/include/xil_testmem.h new file mode 100644 index 0000000..ecce6b7 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/include/xil_testmem.h @@ -0,0 +1,154 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_testmem.h +* @addtogroup common_test_utils +* +*

Memory test

+* +* The xil_testmem.h file contains utility functions to test memory. +* A subset of the memory tests can be selected or all of the tests can be run +* in order. If there is an error detected by a subtest, the test stops and the +* failure code is returned. Further tests are not run even if all of the tests +* are selected. +* Following list describes the supported memory tests: +* +* - XIL_TESTMEM_ALLMEMTESTS: This test runs all of the subtests. +* +* - XIL_TESTMEM_INCREMENT: This test +* starts at 'XIL_TESTMEM_INIT_VALUE' and uses the incrementing value as the +* test value for memory. +* +* - XIL_TESTMEM_WALKONES: Also known as the Walking ones test. This test +* uses a walking '1' as the test value for memory. +* @code +* location 1 = 0x00000001 +* location 2 = 0x00000002 +* ... +* @endcode +* +* - XIL_TESTMEM_WALKZEROS: Also known as the Walking zero's test. +* This test uses the inverse value of the walking ones test +* as the test value for memory. +* @code +* location 1 = 0xFFFFFFFE +* location 2 = 0xFFFFFFFD +* ... +*@endcode +* +* - XIL_TESTMEM_INVERSEADDR: Also known as the inverse address test. +* This test uses the inverse of the address of the location under test +* as the test value for memory. +* +* - XIL_TESTMEM_FIXEDPATTERN: Also known as the fixed pattern test. +* This test uses the provided patters as the test value for memory. +* If zero is provided as the pattern the test uses '0xDEADBEEF". +* +* @warning +* The tests are DESTRUCTIVE. Run before any initialized memory spaces +* have been set up. +* The address provided to the memory tests is not checked for +* validity except for the NULL case. It is possible to provide a code-space +* pointer for this test to start with and ultimately destroy executable code +* causing random failures. +* +* @note +* Used for spaces where the address range of the region is smaller than +* the data width. If the memory range is greater than 2 ** width, +* the patterns used in XIL_TESTMEM_WALKONES and XIL_TESTMEM_WALKZEROS will +* repeat on a boundry of a power of two making it more difficult to detect +* addressing errors. The XIL_TESTMEM_INCREMENT and XIL_TESTMEM_INVERSEADDR +* tests suffer the same problem. Ideally, if large blocks of memory are to be +* tested, break them up into smaller regions of memory to allow the test +* patterns used not to repeat over the region tested. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver    Who    Date    Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a hbm  08/25/09 First release
+* 
+* +******************************************************************************/ + +#ifndef XIL_TESTMEM_H /* prevent circular inclusions */ +#define XIL_TESTMEM_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ +#include "xil_types.h" + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + +/* xutil_memtest defines */ + +#define XIL_TESTMEM_INIT_VALUE 1U + +/** @name Memory subtests + * @{ + */ +/** + * See the detailed description of the subtests in the file description. + */ +#define XIL_TESTMEM_ALLMEMTESTS 0x00U +#define XIL_TESTMEM_INCREMENT 0x01U +#define XIL_TESTMEM_WALKONES 0x02U +#define XIL_TESTMEM_WALKZEROS 0x03U +#define XIL_TESTMEM_INVERSEADDR 0x04U +#define XIL_TESTMEM_FIXEDPATTERN 0x05U +#define XIL_TESTMEM_MAXTEST XIL_TESTMEM_FIXEDPATTERN +/* @} */ + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + +/* xutil_testmem prototypes */ + +extern s32 Xil_TestMem32(u32 *Addr, u32 Words, u32 Pattern, u8 Subtest); +extern s32 Xil_TestMem16(u16 *Addr, u32 Words, u16 Pattern, u8 Subtest); +extern s32 Xil_TestMem8(u8 *Addr, u32 Words, u8 Pattern, u8 Subtest); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** +* @} End of "addtogroup common_test_utils". +*/ diff --git a/datalink814_sp/bsp/microblaze_ps/include/xil_types.h b/datalink814_sp/bsp/microblaze_ps/include/xil_types.h new file mode 100644 index 0000000..625ff8c --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/include/xil_types.h @@ -0,0 +1,214 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_types.h +* +* @addtogroup common_types Basic Data types for Xilinx® Software IP +* +* The xil_types.h file contains basic types for Xilinx software IP. These data types +* are applicable for all processors supported by Xilinx. +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date   Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a hbm  07/14/09 First release
+* 3.03a sdm  05/30/11 Added Xuint64 typedef and XUINT64_MSW/XUINT64_LSW macros
+* 5.00 	pkp  05/29/14 Made changes for 64 bit architecture
+*	srt  07/14/14 Use standard definitions from stdint.h and stddef.h
+*		      Define LONG and ULONG datatypes and mask values
+* 7.00  mus  01/07/19 Add cpp extern macro
+* 
+* +******************************************************************************/ + +#ifndef XIL_TYPES_H /* prevent circular inclusions */ +#define XIL_TYPES_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +/************************** Constant Definitions *****************************/ + +#ifndef TRUE +# define TRUE 1U +#endif + +#ifndef FALSE +# define FALSE 0U +#endif + +#ifndef NULL +#define NULL 0U +#endif + +#define XIL_COMPONENT_IS_READY 0x11111111U /**< In device drivers, This macro will be + assigend to "IsReady" member of driver + instance to indicate that driver + instance is initialized and ready to use. */ +#define XIL_COMPONENT_IS_STARTED 0x22222222U /**< In device drivers, This macro will be assigend to + "IsStarted" member of driver instance + to indicate that driver instance is + started and it can be enabled. */ + +/* @name New types + * New simple types. + * @{ + */ +#ifndef __KERNEL__ +#ifndef XBASIC_TYPES_H +/* + * guarded against xbasic_types.h. + */ +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; +/** @}*/ +#define __XUINT64__ +typedef struct +{ + u32 Upper; + u32 Lower; +} Xuint64; + + +/*****************************************************************************/ +/** +* @brief Return the most significant half of the 64 bit data type. +* +* @param x is the 64 bit word. +* +* @return The upper 32 bits of the 64 bit word. +* +******************************************************************************/ +#define XUINT64_MSW(x) ((x).Upper) + +/*****************************************************************************/ +/** +* @brief Return the least significant half of the 64 bit data type. +* +* @param x is the 64 bit word. +* +* @return The lower 32 bits of the 64 bit word. +* +******************************************************************************/ +#define XUINT64_LSW(x) ((x).Lower) + +#endif /* XBASIC_TYPES_H */ + +/* + * xbasic_types.h does not typedef s* or u64 + */ +/** @{ */ +typedef char char8; +typedef int8_t s8; +typedef int16_t s16; +typedef int32_t s32; +typedef int64_t s64; +typedef uint64_t u64; +typedef int sint32; + +typedef intptr_t INTPTR; +typedef uintptr_t UINTPTR; +typedef ptrdiff_t PTRDIFF; +/** @}*/ +#if !defined(LONG) || !defined(ULONG) +typedef long LONG; +typedef unsigned long ULONG; +#endif + +#define ULONG64_HI_MASK 0xFFFFFFFF00000000U +#define ULONG64_LO_MASK ~ULONG64_HI_MASK + +#else +#include +#endif + +/** @{ */ +/** + * This data type defines an interrupt handler for a device. + * The argument points to the instance of the component + */ +typedef void (*XInterruptHandler) (void *InstancePtr); + +/** + * This data type defines an exception handler for a processor. + * The argument points to the instance of the component + */ +typedef void (*XExceptionHandler) (void *InstancePtr); + +/** + * @brief Returns 32-63 bits of a number. + * @param n : Number being accessed. + * @return Bits 32-63 of number. + * + * @note A basic shift-right of a 64- or 32-bit quantity. + * Use this to suppress the "right shift count >= width of type" + * warning when that quantity is 32-bits. + */ +#define UPPER_32_BITS(n) ((u32)(((n) >> 16) >> 16)) + +/** + * @brief Returns 0-31 bits of a number + * @param n : Number being accessed. + * @return Bits 0-31 of number + */ +#define LOWER_32_BITS(n) ((u32)(n)) + + + + +/************************** Constant Definitions *****************************/ + +#ifndef TRUE +#define TRUE 1U +#endif + +#ifndef FALSE +#define FALSE 0U +#endif + +#ifndef NULL +#define NULL 0U +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** +* @} End of "addtogroup common_types". +*/ diff --git a/datalink814_sp/bsp/microblaze_ps/include/xil_util.h b/datalink814_sp/bsp/microblaze_ps/include/xil_util.h new file mode 100644 index 0000000..194c425 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/include/xil_util.h @@ -0,0 +1,57 @@ +/******************************************************************************/ +/** +* Copyright (C) 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* @file xil_util.h +* +* This file contains xil utility functions declaration +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 6.4   mmd      04/21/19 First release.
+*
+* 
+* +*****************************************************************************/ + +#ifndef XIL_UTIL_H_ +#define XIL_UTIL_H_ + +/* Converts input character to nibble */ +u32 Xil_ConvertCharToNibble(u8 InChar, u8 *Num); + +/* Conver input hex string to array of 32-bits integers */ +u32 Xil_ConvertStringToHex(const char *Str, u32 *buf, u8 Len); + +/* Waits for specified event */ +u32 Xil_WaitForEvent(u32 RegAddr, u32 EventMask, u32 Event, u32 Timeout); + +#endif /* XIL_UTIL_H_ */ diff --git a/datalink814_sp/bsp/microblaze_ps/include/xintc.h b/datalink814_sp/bsp/microblaze_ps/include/xintc.h new file mode 100644 index 0000000..34643e5 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/include/xintc.h @@ -0,0 +1,379 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xintc.h +* @addtogroup intc_v3_9 +* @{ +* @details +* +* The Xilinx interrupt controller driver component. This component supports the +* Xilinx interrupt controller. +* +* The interrupt controller driver uses the idea of priority for the various +* handlers. Priority is an integer within the range of 0 and 31 inclusive with +* 0 being the highest priority interrupt source. +* +* The Xilinx interrupt controller supports the following features: +* +* - specific individual interrupt enabling/disabling +* - specific individual interrupt acknowledging +* - attaching specific callback function to handle interrupt source +* - master enable/disable +* - single callback per interrupt or all pending interrupts handled for +* each interrupt of the processor +* +* The acknowledgement of the interrupt within the interrupt controller is +* selectable, either prior to the device's handler being called or after +* the handler is called. This is necessary to support interrupt signal inputs +* which are either edge or level signals. Edge driven interrupt signals +* require that the interrupt is acknowledged prior to the interrupt being +* serviced in order to prevent the loss of interrupts which are occurring +* extremely close together. A level driven interrupt input signal requires +* the interrupt to acknowledged after servicing the interrupt to ensure that +* the interrupt only generates a single interrupt condition. +* +* Details about connecting the interrupt handler of the driver are contained +* in the source file specific to interrupt processing, xintc_intr.c. +* +* This driver is intended to be RTOS and processor independent. It works with +* physical addresses only. Any needs for dynamic memory management, threads +* or thread mutual exclusion, virtual memory, or cache control must be +* satisfied by the layer above this driver. +* +* Interrupt Vector Tables +* +* The interrupt vector table for each interrupt controller device is declared +* statically in xintc_g.c within the configuration data for each instance. +* The device ID of the interrupt controller device is used by the driver as a +* direct index into the configuration data table - to retrieve the vector table +* for an instance of the interrupt controller. The user should populate the +* vector table with handlers and callbacks at run-time using the XIntc_Connect() +* and XIntc_Disconnect() functions. +* +* Each vector table entry corresponds to a device that can generate an +* interrupt. Each entry contains an interrupt handler function and an argument +* to be passed to the handler when an interrupt occurs. The tools default this +* argument to the base address of the interrupting device. Note that the +* device driver interrupt handlers given in this file do not take a base +* address as an argument, but instead take a pointer to the driver instance. +* This means that although the table is created statically, the user must still +* use XIntc_Connect() when the interrupt handler takes an argument other than +* the base address. This is only to say that the existence of the static vector +* tables should not mislead the user into thinking they no longer need to +* register/connect interrupt handlers with this driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a ecm  08/16/01 First release
+* 1.00a rpm  01/09/02 Removed the AckLocation argument from XIntc_Connect().
+*                     This information is now internal in xintc_g.c.
+* 1.00b jhl  02/13/02 Repartitioned the driver for smaller files
+* 1.00b jhl  04/24/02 Made LookupConfig function global and relocated config
+*                     data type
+* 1.00c rpm  10/17/03 New release. Support the static vector table created
+*                     in the xintc_g.c configuration table. Moved vector
+*                     table and options out of instance structure and into
+*                     the configuration table.
+* 1.10c mta  03/21/07 Updated to new coding style
+* 1.11a sv   11/21/07 Updated driver to support access through a DCR bridge
+* 2.00a ktn  10/20/09 Updated to use HAL Processor APIs and _m is removed from
+*		      all the macro names/definitions.
+* 2.01a sdm  04/27/10 Updated the tcl so that the defintions are generated in
+*		      the xparameters.h to know whether the optional registers
+*		      SIE, CIE and IVR are enabled in the HW - Refer CR 555392.
+*		      This driver doesnot make use of these definitions and does
+*		      not use the optional registers.
+* 2.03a hvm  05/24/11 Updated the tcl to generate vector Ids for external
+*		      interrupts. CR565336
+* 2.04a bss  01/13/12 Added XIntc_ConnectFastHandler API for Fast Interrupt
+*		      and XIntc_SetNormalIntrMode for setting to normal
+*		      interrupt mode.
+* 2.04a asa  03/19/12 Changed the XIntc_Config struct. The order of entries
+*		      declared in the structure now matches with the
+*		      XIntc_ConfigTable generated by the driver tcl.
+* 2.05a bss  08/16/12 Updated to support relocatable vectors in Microblaze,
+*		      added IntVectorAddr to XIntc_Config for this.
+*		      Added XIntc_RegisterFastHandler API to register fast
+*		      interrupt handlers using base address.
+* 2.06a bss  01/28/13 To support Cascade mode:
+* 		      Added XIN_INTC_NOCASCADE,XIN_INTC_PRIMARY,
+*		      XIN_INTC_SECONDARY,XIN_INTC_LAST and
+*		      XIN_CONTROLLER_MAX_INTRS  macros
+*		      Added NumberofIntrs and IntcType fields in XIntc_Config
+*		      structure.
+*		      Modified XIntc_Initialize,XIntc_Start,XIntc_Connect
+*		      XIntc_Disconnect,XIntc_Enable,XIntc_Disable,
+*		      XIntc_Acknowledge,XIntc_ConnectFastHandler and
+*		      XIntc_SetNormalIntrMode APIs.Added XIntc_InitializeSlaves
+*		      API in xintc.c
+*  		      Modified XIntc_DeviceInterruptHandler,
+*  		      XIntc_SetIntrSvcOption,XIntc_RegisterHandler and
+*		      XIntc_RegisterFastHandler APIs.Added XIntc_CascadeHandler
+*		      API in xintc_l.c.
+*		      Modified XIntc_SetOptions API in xintc_options.c.
+*		      Modified XIntc_SimulateIntr API in xintc_selftest.c.
+*		      Modified driver tcl:
+*			to check for Cascade mode and generate XPAR_INTC_TYPE
+*			for each controller.
+*			Generate XPAR_INTC_MAX_NUM_INTR_INPUTS by adding all
+*			interrupt sources of all Controllers in Cascade mode.
+* 2.07a bss  10/18/13 To support Nested interrupts:
+*		      Modified XIntc_DeviceInterruptHandler API.
+*		      Added XIN_ILR_OFFSET macro in xintc_l.h.
+*		      Modified driver tcl to generate HAS_ILR parameter in
+*		      xparameters.h
+* 3.0   bss  01/28/13 Modified xintc.c to initialize IVAR register with
+*		      XPAR_MICROBLAZE_BASE_VECTORS + 0x10 to fix
+*		      CR#765931.
+*		      Modified driver tcl to generate XPAR_AXI_INTC_0_TYPE
+*		      correctly(CR#764865).
+*
+* @note
+*		For Cascade mode, Interrupt IDs are generated in xparameters.h
+*		as shown below:
+*
+*	    Master/Primary INTC
+*		 ______
+*		|      |-0      Secondary INTC
+*		|      |-.         ______
+*		|      |-.        |      |-32        Last INTC
+*		|      |-.        |      |-.          ______
+*		|______|<-31------|      |-.         |      |-64
+*			          |      |-.         |      |-.
+*			          |______|<-63-------|      |-.
+*                                                    |      |-.
+*                                                    |______|-95
+*
+*		All driver functions has to be called using DeviceId/
+*		InstancePtr/BaseAddress of Primary/Master Controller and
+*		Interrupts IDs generated in xparameters.h only.
+*		Driver functions takes care of Slave Controllers based on
+*		Interrupt ID passed. User must not use Interrupt source/ID
+*		31 of Primary and Secondary controllers to call driver
+*		functions.
+*
+*		For nested interrupts, XIntc_DeviceInterruptHandler saves
+*		microblaze r14 register on entry and restores on exit. This is
+*		required since compiler does not support nesting. It enables
+*		Microblaze interrupts after blocking further interrupts from
+*		the current interrupt number and interrupts below current
+*		interrupt proirity by writing to Interrupt Level Register of
+*		INTC on entry. On exit, it disables microblaze interrupts and
+*		restores ILR register default value(0xFFFFFFFF)back. It is
+*		recommended to increase STACK_SIZE in linker script for nested
+*		interrupts.
+* 3.0     adk    12/10/13  Updated as per the New Tcl API's
+* 3.0 	  adk 	 17/02/14  Fixed the CR:771287 Changes are made in the intc
+* 		           driver tcl.
+* 3.1     adk    8/4/14    Fixed the CR:783248 Changes are made in
+*			   the test-app tcl
+* 3.2     bss    4/8/14    Fixed driver tcl to handle external interrupt pins
+*			   correctly (CR#799609).
+* 3.3     adk    11/3/14   added generation of C_HAS_ILR parameter to
+*			   xparameters.h.Changes are made in the driver tcl file
+*			   (CR#828046).
+* 3.5   sk   11/10/15 Used UINTPTR instead of u32 for Baseaddress CR# 867425.
+* 3.6   ms   01/23/17 Added xil_printf statement in main function for all
+*                     examples to ensure that "Successfully ran" and "Failed"
+*                     strings are available in all examples. This is a fix
+*                     for CR-965028.
+*       ms   03/17/17 Added readme.txt file in examples folder for doxygen
+*                     generation.
+* 3.7   ms   04/18/17 Modified tcl file to add suffix U for macro definitions
+*                     of intc in xparameters.h
+* 3.9   adk  19/12/18 If design contains unconnected interrupt pins
+*		      return proper error message(CR#1018878).
+* 
+* +******************************************************************************/ + +#ifndef XINTC_H /* prevent circular inclusions */ +#define XINTC_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xparameters.h" +#include "xstatus.h" +#include "xintc_l.h" + +/************************** Constant Definitions *****************************/ + +/** + * @name Configuration options + * These options are used in XIntc_SetOptions() to configure the device. + * @{ + */ +/** + *
+ * XIN_SVC_SGL_ISR_OPTION	Service the highest priority pending interrupt
+ *				and then return.
+ * XIN_SVC_ALL_ISRS_OPTION	Service all of the pending interrupts and then
+ *				return.
+ * 
+ */ +#define XIN_SVC_SGL_ISR_OPTION 1UL +#define XIN_SVC_ALL_ISRS_OPTION 2UL +/*@}*/ + +/** + * @name Start modes + * One of these values is passed to XIntc_Start() to start the device. + * @{ + */ +/** Simulation only mode, no hardware interrupts recognized */ +#define XIN_SIMULATION_MODE 0 +/** Real mode, no simulation allowed, hardware interrupts recognized */ +#define XIN_REAL_MODE 1 +/*@}*/ + +/** + * @name Masks to specify Interrupt Controller Mode + * @{ + */ +#define XIN_INTC_NOCASCADE 0 /* Normal - No Cascade Mode */ +#define XIN_INTC_PRIMARY 1 /* Master/Primary controller */ +#define XIN_INTC_SECONDARY 2 /* Secondary Slave Controllers */ +#define XIN_INTC_LAST 3 /* Last Slave Controller */ + +/*@}*/ + +/** + * @name Mask to specify maximum number of interrupt sources per controller + * @{ + */ +#define XIN_CONTROLLER_MAX_INTRS 32 /* Each Controller has 32 + interrupt pins */ + +#define XINTC_STANDARD_VECTOR_ADDRESS_WIDTH 32U +/*@}*/ + +/**************************** Type Definitions *******************************/ + +/** + * This typedef contains configuration information for the device. + */ +typedef struct { + u16 DeviceId; /**< Unique ID of device */ + UINTPTR BaseAddress; /**< Register base address */ + u32 AckBeforeService; /**< Ack location per interrupt */ + int FastIntr; /**< Fast Interrupt enabled */ + u32 IntVectorAddr; /**< Interrupt Vector Address */ + int NumberofIntrs; /**< Number of Interrupt sources */ + u8 VectorAddrWidth; /**< Width of vector address */ + u32 Options; /**< Device options */ + int IntcType; /**< Intc type 0 - No Cascade Mode + 1 - primary instance + 2 - secondary instance + 3 - last instance */ + +/** Static vector table of interrupt handlers */ +#if XPAR_INTC_0_INTC_TYPE != XIN_INTC_NOCASCADE + XIntc_VectorTableEntry HandlerTable[XIN_CONTROLLER_MAX_INTRS]; +#else + XIntc_VectorTableEntry HandlerTable[XPAR_INTC_MAX_NUM_INTR_INPUTS]; +#endif + +} XIntc_Config; + +/** + * The XIntc driver instance data. The user is required to allocate a + * variable of this type for every intc device in the system. A pointer + * to a variable of this type is then passed to the driver API functions. + */ +typedef struct { + UINTPTR BaseAddress; /**< Base address of registers */ + u32 IsReady; /**< Device is initialized and ready */ + u32 IsStarted; /**< Device has been started */ + u32 UnhandledInterrupts; /**< Intc Statistics */ + XIntc_Config *CfgPtr; /**< Pointer to instance config entry */ + +} XIntc; + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/* + * Required functions in xintc.c + */ +int XIntc_Initialize(XIntc * InstancePtr, u16 DeviceId); + +int XIntc_Start(XIntc * InstancePtr, u8 Mode); +void XIntc_Stop(XIntc * InstancePtr); + +int XIntc_Connect(XIntc * InstancePtr, u8 Id, + XInterruptHandler Handler, void *CallBackRef); +void XIntc_Disconnect(XIntc * InstancePtr, u8 Id); + +void XIntc_Enable(XIntc * InstancePtr, u8 Id); +void XIntc_Disable(XIntc * InstancePtr, u8 Id); + +void XIntc_Acknowledge(XIntc * InstancePtr, u8 Id); + +XIntc_Config *XIntc_LookupConfig(u16 DeviceId); + +int XIntc_ConnectFastHandler(XIntc *InstancePtr, u8 Id, + XFastInterruptHandler Handler); +void XIntc_SetNormalIntrMode(XIntc *InstancePtr, u8 Id); + +/* + * Interrupt functions in xintr_intr.c + */ +void XIntc_VoidInterruptHandler(void); +void XIntc_InterruptHandler(XIntc * InstancePtr); + +/* + * Options functions in xintc_options.c + */ +int XIntc_SetOptions(XIntc * InstancePtr, u32 Options); +u32 XIntc_GetOptions(XIntc * InstancePtr); + +/* + * Self-test functions in xintc_selftest.c + */ +int XIntc_SelfTest(XIntc * InstancePtr); +int XIntc_SimulateIntr(XIntc * InstancePtr, u8 Id); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/datalink814_sp/bsp/microblaze_ps/include/xintc_i.h b/datalink814_sp/bsp/microblaze_ps/include/xintc_i.h new file mode 100644 index 0000000..6a09e43 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/include/xintc_i.h @@ -0,0 +1,89 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xintc_i.h +* @addtogroup intc_v3_9 +* @{ +* +* This file contains data which is shared between files and internal to the +* XIntc component. It is intended for internal use only. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00b jhl  02/06/02 First release
+* 1.00b jhl  04/24/02 Moved register definitions to xintc_l.h
+* 1.00c rpm  10/17/03 New release. Removed extern of global, single instance
+*                     pointer.
+* 1.10c mta  03/21/07 Updated to new coding style
+* 2.00a ktn  10/20/09 Updated to use HAL Processor APIs.
+* 
+* +******************************************************************************/ + +#ifndef XINTC_I_H /* prevent circular inclusions */ +#define XINTC_I_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xintc.h" + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + + +/************************** Variable Definitions *****************************/ + +extern u32 XIntc_BitPosMask[]; + +extern XIntc_Config XIntc_ConfigTable[]; + +#ifdef __cplusplus +} +#endif + +#endif +/** @} */ diff --git a/datalink814_sp/bsp/microblaze_ps/include/xintc_l.h b/datalink814_sp/bsp/microblaze_ps/include/xintc_l.h new file mode 100644 index 0000000..49b417e --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/include/xintc_l.h @@ -0,0 +1,331 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xintc_l.h +* @addtogroup intc_v3_9 +* @{ +* +* This header file contains identifiers and low-level driver functions (or +* macros) that can be used to access the device. The user should refer to the +* hardware device specification for more details of the device operation. +* +* +* Note that users of the driver interface given in this file can register +* an interrupt handler dynamically (at run-time) using the +* XIntc_RegisterHandler() function. +* User of the driver interface given in xintc.h should still use +* XIntc_Connect(), as always. +* Also see the discussion of the interrupt vector tables in xintc.h. +* +* There are currently two interrupt handlers specified in this interface. +* +* - XIntc_LowLevelInterruptHandler() is a handler without any arguments that +* is used in cases where there is a single interrupt controller device in +* the system and the handler cannot be passed an argument. This function is +* provided mostly for backward compatibility. +* +* - XIntc_DeviceInterruptHandler() is a handler that takes a device ID as an +* argument, indicating which interrupt controller device in the system is +* causing the interrupt - thereby supporting multiple interrupt controllers. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------------
+* 1.00b jhl  04/24/02 First release
+* 1.00c rpm  10/17/03 New release. Support the static vector table created
+*                     in the xintc_g.c configuration table.
+* 1.10c mta  03/21/07 Updated to new coding style
+* 1.11a sv   11/21/07 Updated driver to support access through a DCR bridge
+* 2.00a ktn  10/20/09 Updated to use HAL Processor APIs. _m is removed from all
+*		      the macro definitions.
+* 2.04a bss  01/13/12 Updated for adding defines for IMR and IVAR for
+*                     the FAST Interrupt
+* 2.05a bss  08/18/12 Added XIntc_RegisterFastHandler API to register fast
+*		      interrupt handlers using base address.
+* 2.07a bss  10/18/13 Added XIN_ILR_OFFSET macro for nested interrupts.
+* 3.5   sk   11/10/15 Used UINTPTR instead of u32 for Baseaddress CR# 867425.
+*                     Changed the prototypes of XIntc_RegisterFastHandler,
+*                     XIntc_SetIntrSvcOption, XIntc_RegisterHandler APIs.
+*
+* 
+* +******************************************************************************/ + +#ifndef XINTC_L_H /* prevent circular inclusions */ +#define XINTC_L_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xparameters.h" +#include "xil_io.h" + +/* + * XPAR_XINTC_USE_DCR_BRIDGE has to be set to 1 if the Intc device will be + * accessed through a DCR bus connected to a bridge. + */ +#define XPAR_XINTC_USE_DCR_BRIDGE 0 + +#if ((XPAR_XINTC_USE_DCR != 0) || (XPAR_XINTC_USE_DCR_BRIDGE != 0)) +#include "xio_dcr.h" +#endif + +/************************** Constant Definitions *****************************/ + +/* define the offsets from the base address for all the registers of the + * interrupt controller, some registers may be optional in the hardware device + */ +#if ((XPAR_XINTC_USE_DCR != 0) || (XPAR_XINTC_USE_DCR_BRIDGE != 0)) + +#define XIN_ISR_OFFSET 0 /* Interrupt Status Register */ +#define XIN_IPR_OFFSET 1 /* Interrupt Pending Register */ +#define XIN_IER_OFFSET 2 /* Interrupt Enable Register */ +#define XIN_IAR_OFFSET 3 /* Interrupt Acknowledge Register */ +#define XIN_SIE_OFFSET 4 /* Set Interrupt Enable Register */ +#define XIN_CIE_OFFSET 5 /* Clear Interrupt Enable Register */ +#define XIN_IVR_OFFSET 6 /* Interrupt Vector Register */ +#define XIN_MER_OFFSET 7 /* Master Enable Register */ +#define XIN_IMR_OFFSET 8 /* Interrupt Mode Register , this is present + * only for Fast Interrupt */ +#define XIN_IVAR_OFFSET 64 /* Interrupt Vector Address Register + * Interrupt 0 Offest, this is present + * only for Fast Interrupt */ + +#else /* ((XPAR_XINTC_USE_DCR != 0) || (XPAR_XINTC_USE_DCR_BRIDGE != 0)) */ + +#define XIN_ISR_OFFSET 0 /* Interrupt Status Register */ +#define XIN_IPR_OFFSET 4 /* Interrupt Pending Register */ +#define XIN_IER_OFFSET 8 /* Interrupt Enable Register */ +#define XIN_IAR_OFFSET 12 /* Interrupt Acknowledge Register */ +#define XIN_SIE_OFFSET 16 /* Set Interrupt Enable Register */ +#define XIN_CIE_OFFSET 20 /* Clear Interrupt Enable Register */ +#define XIN_IVR_OFFSET 24 /* Interrupt Vector Register */ +#define XIN_MER_OFFSET 28 /* Master Enable Register */ +#define XIN_IMR_OFFSET 32 /* Interrupt Mode Register , this is present + * only for Fast Interrupt */ +#define XIN_ILR_OFFSET 36 /* Interrupt level register */ +#define XIN_IVAR_OFFSET 0x100 /* Interrupt Vector Address Register + * Interrupt 0 Offest, this is present + * only for Fast Interrupt */ +#define XIN_IVEAR_OFFSET 0x200 /* Interrupt Vector Extended Address + Register */ + + +#endif /* ((XPAR_XINTC_USE_DCR != 0) || (XPAR_XINTC_USE_DCR_BRIDGE != 0)) */ + +/* Bit definitions for the bits of the MER register */ + +#define XIN_INT_MASTER_ENABLE_MASK 0x1UL +#define XIN_INT_HARDWARE_ENABLE_MASK 0x2UL /* once set cannot be cleared */ + +/**************************** Type Definitions *******************************/ + +/* The following data type defines each entry in an interrupt vector table. + * The callback reference is the base address of the interrupting device + * for the driver interface given in this file and an instance pointer for the + * driver interface given in xintc.h file. + */ +typedef struct { + XInterruptHandler Handler; + void *CallBackRef; +} XIntc_VectorTableEntry; + +typedef void (*XFastInterruptHandler) (void); + +/***************** Macros (Inline Functions) Definitions *********************/ + +/* + * Define the appropriate I/O access method to memory mapped I/O or DCR. + */ +#if ((XPAR_XINTC_USE_DCR != 0) || (XPAR_XINTC_USE_DCR_BRIDGE != 0)) + +#define XIntc_In32 XIo_DcrIn +#define XIntc_Out32 XIo_DcrOut + +#else + +#define XIntc_In32 Xil_In32 +#define XIntc_Out32 Xil_Out32 +#define XIntc_Out64 Xil_Out64 + +#endif + +/****************************************************************************/ +/** +* +* Enable all interrupts in the Master Enable register of the interrupt +* controller. The interrupt controller defaults to all interrupts disabled +* from reset such that this macro must be used to enable interrupts. +* +* @param BaseAddress is the base address of the device. +* +* @return None. +* +* @note C-style signature: +* void XIntc_MasterEnable(u32 BaseAddress); +* +*****************************************************************************/ +#define XIntc_MasterEnable(BaseAddress) \ + XIntc_Out32((BaseAddress) + XIN_MER_OFFSET, \ + XIN_INT_MASTER_ENABLE_MASK | XIN_INT_HARDWARE_ENABLE_MASK) + +/****************************************************************************/ +/** +* +* Disable all interrupts in the Master Enable register of the interrupt +* controller. +* +* @param BaseAddress is the base address of the device. +* +* @return None. +* +* @note C-style signature: +* void XIntc_MasterDisable(u32 BaseAddress); +* +*****************************************************************************/ +#define XIntc_MasterDisable(BaseAddress) \ + XIntc_Out32((BaseAddress) + XIN_MER_OFFSET, 0) + +/****************************************************************************/ +/** +* +* Enable specific interrupt(s) in the interrupt controller. +* +* @param BaseAddress is the base address of the device +* @param EnableMask is the 32-bit value to write to the enable register. +* Each bit of the mask corresponds to an interrupt input signal +* that is connected to the interrupt controller (INT0 = LSB). +* Only the bits which are set in the mask will enable interrupts. +* +* @return None. +* +* @note C-style signature: +* void XIntc_EnableIntr(u32 BaseAddress, u32 EnableMask); +* +*****************************************************************************/ +#define XIntc_EnableIntr(BaseAddress, EnableMask) \ + XIntc_Out32((BaseAddress) + XIN_IER_OFFSET, (EnableMask)) + +/****************************************************************************/ +/** +* +* Disable specific interrupt(s) in the interrupt controller. +* +* @param BaseAddress is the base address of the device +* @param DisableMask is the 32-bit value to write to the enable register. +* Each bit of the mask corresponds to an interrupt input signal +* that is connected to the interrupt controller (INT0 = LSB). +* Only the bits which are set in the mask will disable interrupts. +* +* @return None. +* +* @note C-style signature: +* void XIntc_DisableIntr(u32 BaseAddress, u32 DisableMask); +* +*****************************************************************************/ +#define XIntc_DisableIntr(BaseAddress, DisableMask) \ + XIntc_Out32((BaseAddress) + XIN_IER_OFFSET, ~(DisableMask)) + +/****************************************************************************/ +/** +* +* Acknowledge specific interrupt(s) in the interrupt controller. +* +* @param BaseAddress is the base address of the device +* @param AckMask is the 32-bit value to write to the acknowledge +* register. Each bit of the mask corresponds to an interrupt input +* signal that is connected to the interrupt controller (INT0 = +* LSB). Only the bits which are set in the mask will acknowledge +* interrupts. +* +* @return None. +* +* @note C-style signature: +* void XIntc_AckIntr(u32 BaseAddress, u32 AckMask); +* +*****************************************************************************/ +#define XIntc_AckIntr(BaseAddress, AckMask) \ + XIntc_Out32((BaseAddress) + XIN_IAR_OFFSET, (AckMask)) + +/****************************************************************************/ +/** +* +* Get the interrupt status from the interrupt controller which indicates +* which interrupts are active and enabled. +* +* @param BaseAddress is the base address of the device +* +* @return The 32-bit contents of the interrupt status register. Each bit +* corresponds to an interrupt input signal that is connected to +* the interrupt controller (INT0 = LSB). Bits which are set +* indicate an active interrupt which is also enabled. +* +* @note C-style signature: +* u32 XIntc_GetIntrStatus(u32 BaseAddress); +* +*****************************************************************************/ +#define XIntc_GetIntrStatus(BaseAddress) \ + (XIntc_In32((BaseAddress) + XIN_ISR_OFFSET) & \ + XIntc_In32((BaseAddress) + XIN_IER_OFFSET)) + +/************************** Function Prototypes ******************************/ + +/* + * Interrupt controller handlers, to be connected to processor exception + * handling code. + */ +void XIntc_LowLevelInterruptHandler(void); +void XIntc_DeviceInterruptHandler(void *DeviceId); + +/* Various configuration functions */ +void XIntc_SetIntrSvcOption(UINTPTR BaseAddress, int Option); + +void XIntc_RegisterHandler(UINTPTR BaseAddress, int InterruptId, + XInterruptHandler Handler, void *CallBackRef); + +void XIntc_RegisterFastHandler(UINTPTR BaseAddress, u8 Id, + XFastInterruptHandler FastHandler); + +/************************** Variable Definitions *****************************/ + + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/datalink814_sp/bsp/microblaze_ps/include/xio.h b/datalink814_sp/bsp/microblaze_ps/include/xio.h new file mode 100644 index 0000000..a923a4d --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/include/xio.h @@ -0,0 +1,269 @@ +/****************************************************************************** +* +* Copyright (C) 2007 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xio.h +* @addtogroup cpu_v2_9 +* @{ +* @details +* +* This file contains the interface for the XIo component, which encapsulates +* the Input/Output functions for processors that do not require any special +* I/O handling. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a rpm  11/07/03 Added InSwap/OutSwap routines for endian conversion
+* 1.00a xd   11/04/04 Improved support for doxygen
+* 1.01a ecm  02/24/06 CR225908 corrected the extra curly braces in macros
+*                     and bumped version to 1.01.a.
+* 1.11a mta  03/21/07 Updated to new coding style.
+* 1.11b va   04/17/08 Updated Tcl for better CORE_CLOCK_FREQ_HZ definition
+* 1.11a sdm  03/12/09 Updated Tcl to define correct value for CORE_CLOCK_FREQ_HZ
+*                     (CR  #502010)
+* 1.13a sdm  03/12/09 Updated the Tcl to pull appropriate libraries for Little
+*                     Endian Microblaze
+* 2.0   adk  19/12/13 Updated as per the New Tcl API's
+* 2.1   bss  04/14/14 Updated tcl to copy libgloss.a and libgcc.a libraries
+* 2.1   bss  04/29/14 Updated to copy libgloss.a if exists otherwise libxil.a
+*			CR#794205
+* 2.2   bss  08/04/14 Updated driver tcl to add protection macros for
+*		      xparameters.h (CR#802257).
+* 2.3	sk	 12/15/14 Updated mdd file to delete �ffunction-sections &
+*					  -fdata-sections flags from extra compiler flags CR#838648
+*					  Changed default os to latest version in mdd file.
+* 2.4   nsk  11/05/15 Updated generate and post_generate procs in driver tcl
+*                     not to generate cpu macros, when microblaze is connected
+*                     as one of the streaming slaves to itself. CR#876604
+*
+* 
+* +* @note +* +* This file may contain architecture-dependent items (memory-mapped or +* non-memory-mapped I/O). +* +******************************************************************************/ + +#ifndef XIO_H /* prevent circular inclusions */ +#define XIO_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + +/** + * Typedef for an I/O address. Typically correlates to the width of the + * address bus. + */ +typedef u32 XIo_Address; + +/***************** Macros (Inline Functions) Definitions *********************/ + +/* + * The following macros allow optimized I/O operations for memory mapped I/O. + * It should be noted that macros cannot be used if synchronization of the I/O + * operation is needed as it will likely break some code. + */ + +/*****************************************************************************/ +/** +* +* Performs an input operation for an 8-bit memory location by reading from the +* specified address and returning the value read from that address. +* +* @param InputPtr contains the address to perform the input operation at. +* +* @return The value read from the specified input address. +* +* @note None. +* +******************************************************************************/ +#define XIo_In8(InputPtr) (*(volatile u8 *)(InputPtr)) + +/*****************************************************************************/ +/** +* +* Performs an input operation for a 16-bit memory location by reading from the +* specified address and returning the value read from that address. +* +* @param InputPtr contains the address to perform the input operation at. +* +* @return The value read from the specified input address. +* +* @note None. +* +******************************************************************************/ +#define XIo_In16(InputPtr) (*(volatile u16 *)(InputPtr)) + +/*****************************************************************************/ +/** +* +* Performs an input operation for a 32-bit memory location by reading from the +* specified address and returning the value read from that address. +* +* @param InputPtr contains the address to perform the input operation at. +* +* @return The value read from the specified input address. +* +* @note None. +* +******************************************************************************/ +#define XIo_In32(InputPtr) (*(volatile u32 *)(InputPtr)) + + +/*****************************************************************************/ +/** +* +* Performs an output operation for an 8-bit memory location by writing the +* specified value to the the specified address. +* +* @param OutputPtr contains the address to perform the output operation +* at. +* @param Value contains the value to be output at the specified address. +* +* @return None +* +* @note None. +* +******************************************************************************/ +#define XIo_Out8(OutputPtr, Value) \ + (*(volatile u8 *)((OutputPtr)) = (Value)) + +/*****************************************************************************/ +/** +* +* Performs an output operation for a 16-bit memory location by writing the +* specified value to the the specified address. +* +* @param OutputPtr contains the address to perform the output operation +* at. +* @param Value contains the value to be output at the specified address. +* +* @return None +* +* @note None. +* +******************************************************************************/ +#define XIo_Out16(OutputPtr, Value) \ + (*(volatile u16 *)((OutputPtr)) = (Value)) + +/*****************************************************************************/ +/** +* +* Performs an output operation for a 32-bit memory location by writing the +* specified value to the the specified address. +* +* @param OutputPtr contains the address to perform the output operation +* at. +* @param Value contains the value to be output at the specified address. +* +* @return None +* +* @note None. +* +******************************************************************************/ +#define XIo_Out32(OutputPtr, Value) \ + (*(volatile u32 *)((OutputPtr)) = (Value)) + + +/* The following macros allow the software to be transportable across + * processors which use big or little endian memory models. + * + * Defined first is a no-op endian conversion macro. This macro is not to + * be used directly by software. Instead, the XIo_To/FromLittleEndianXX and + * XIo_To/FromBigEndianXX macros below are to be used to allow the endian + * conversion to only be performed when necessary + */ +#define XIo_EndianNoop(Source, DestPtr) (*DestPtr = Source) + +#ifdef XLITTLE_ENDIAN + +#define XIo_ToLittleEndian16 XIo_EndianNoop +#define XIo_ToLittleEndian32 XIo_EndianNoop +#define XIo_FromLittleEndian16 XIo_EndianNoop +#define XIo_FromLittleEndian32 XIo_EndianNoop + +#define XIo_ToBigEndian16(Source, DestPtr) XIo_EndianSwap16(Source, DestPtr) +#define XIo_ToBigEndian32(Source, DestPtr) XIo_EndianSwap32(Source, DestPtr) +#define XIo_FromBigEndian16 XIo_ToBigEndian16 +#define XIo_FromBigEndian32 XIo_ToBigEndian32 + +#else + +#define XIo_ToLittleEndian16(Source, DestPtr) XIo_EndianSwap16(Source, DestPtr) +#define XIo_ToLittleEndian32(Source, DestPtr) XIo_EndianSwap32(Source, DestPtr) +#define XIo_FromLittleEndian16 XIo_ToLittleEndian16 +#define XIo_FromLittleEndian32 XIo_ToLittleEndian32 + +#define XIo_ToBigEndian16 XIo_EndianNoop +#define XIo_ToBigEndian32 XIo_EndianNoop +#define XIo_FromBigEndian16 XIo_EndianNoop +#define XIo_FromBigEndian32 XIo_EndianNoop + +#endif + +/************************** Function Prototypes ******************************/ + +/* The following functions allow the software to be transportable across + * processors which use big or little endian memory models. These functions + * should not be directly called, but the macros XIo_To/FromLittleEndianXX and + * XIo_To/FromBigEndianXX should be used to allow the endian conversion to only + * be performed when necessary. + */ +void XIo_EndianSwap16(u16 Source, u16 *DestPtr); +void XIo_EndianSwap32(u32 Source, u32 *DestPtr); + +/* The following functions handle IO addresses where data must be swapped + * They cannot be implemented as macros + */ +u16 XIo_InSwap16(XIo_Address InAddress); +u32 XIo_InSwap32(XIo_Address InAddress); +void XIo_OutSwap16(XIo_Address OutAddress, u16 Value); +void XIo_OutSwap32(XIo_Address OutAddress, u32 Value); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/datalink814_sp/bsp/microblaze_ps/include/xparameters.h b/datalink814_sp/bsp/microblaze_ps/include/xparameters.h new file mode 100644 index 0000000..b7aee07 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/include/xparameters.h @@ -0,0 +1,950 @@ +#ifndef XPARAMETERS_H /* prevent circular inclusions */ +#define XPARAMETERS_H /* by using protection macros */ + +/* Definitions for bus frequencies */ +#define XPAR_CPU_M_AXI_DP_FREQ_HZ 150000000 +/******************************************************************/ + +/* Canonical definitions for bus frequencies */ +/******************************************************************/ + +#define XPAR_CPU_CORE_CLOCK_FREQ_HZ 150000000 +#define XPAR_MICROBLAZE_CORE_CLOCK_FREQ_HZ 150000000 + +/******************************************************************/ + + +/* Definitions for peripheral MICROBLAZE_PS */ +#define XPAR_MICROBLAZE_PS_ADDR_SIZE 32 +#define XPAR_MICROBLAZE_PS_ADDR_TAG_BITS 17 +#define XPAR_MICROBLAZE_PS_ALLOW_DCACHE_WR 1 +#define XPAR_MICROBLAZE_PS_ALLOW_ICACHE_WR 1 +#define XPAR_MICROBLAZE_PS_AREA_OPTIMIZED 0 +#define XPAR_MICROBLAZE_PS_ASYNC_INTERRUPT 1 +#define XPAR_MICROBLAZE_PS_ASYNC_WAKEUP 3 +#define XPAR_MICROBLAZE_PS_AVOID_PRIMITIVES 0 +#define XPAR_MICROBLAZE_PS_BASE_VECTORS 0x0000000000000000 +#define XPAR_MICROBLAZE_PS_BRANCH_TARGET_CACHE_SIZE 0 +#define XPAR_MICROBLAZE_PS_CACHE_BYTE_SIZE 16384 +#define XPAR_MICROBLAZE_PS_DADDR_SIZE 32 +#define XPAR_MICROBLAZE_PS_DATA_SIZE 32 +#define XPAR_MICROBLAZE_PS_DCACHE_ADDR_TAG 17 +#define XPAR_MICROBLAZE_PS_DCACHE_ALWAYS_USED 0 +#define XPAR_MICROBLAZE_PS_DCACHE_BASEADDR 0x80000000 +#define XPAR_MICROBLAZE_PS_DCACHE_BYTE_SIZE 16384 +#define XPAR_MICROBLAZE_PS_DCACHE_DATA_WIDTH 0 +#define XPAR_MICROBLAZE_PS_DCACHE_FORCE_TAG_LUTRAM 0 +#define XPAR_MICROBLAZE_PS_DCACHE_HIGHADDR 0xFFFFFFFF +#define XPAR_MICROBLAZE_PS_DCACHE_LINE_LEN 4 +#define XPAR_MICROBLAZE_PS_DCACHE_USE_WRITEBACK 1 +#define XPAR_MICROBLAZE_PS_DCACHE_VICTIMS 0 +#define XPAR_MICROBLAZE_PS_DC_AXI_MON 0 +#define XPAR_MICROBLAZE_PS_DEBUG_COUNTER_WIDTH 32 +#define XPAR_MICROBLAZE_PS_DEBUG_ENABLED 1 +#define XPAR_MICROBLAZE_PS_DEBUG_EVENT_COUNTERS 5 +#define XPAR_MICROBLAZE_PS_DEBUG_EXTERNAL_TRACE 0 +#define XPAR_MICROBLAZE_PS_DEBUG_INTERFACE 0 +#define XPAR_MICROBLAZE_PS_DEBUG_LATENCY_COUNTERS 1 +#define XPAR_MICROBLAZE_PS_DEBUG_PROFILE_SIZE 0 +#define XPAR_MICROBLAZE_PS_DEBUG_TRACE_ASYNC_RESET 0 +#define XPAR_MICROBLAZE_PS_DEBUG_TRACE_SIZE 8192 +#define XPAR_MICROBLAZE_PS_DIV_ZERO_EXCEPTION 1 +#define XPAR_MICROBLAZE_PS_DP_AXI_MON 0 +#define XPAR_MICROBLAZE_PS_DYNAMIC_BUS_SIZING 0 +#define XPAR_MICROBLAZE_PS_D_AXI 1 +#define XPAR_MICROBLAZE_PS_D_LMB 1 +#define XPAR_MICROBLAZE_PS_D_LMB_MON 0 +#define XPAR_MICROBLAZE_PS_ECC_USE_CE_EXCEPTION 0 +#define XPAR_MICROBLAZE_PS_EDGE_IS_POSITIVE 1 +#define XPAR_MICROBLAZE_PS_ENABLE_DISCRETE_PORTS 0 +#define XPAR_MICROBLAZE_PS_ENDIANNESS 1 +#define XPAR_MICROBLAZE_PS_FAULT_TOLERANT 0 +#define XPAR_MICROBLAZE_PS_FPU_EXCEPTION 0 +#define XPAR_MICROBLAZE_PS_FREQ 150000000 +#define XPAR_MICROBLAZE_PS_FSL_EXCEPTION 0 +#define XPAR_MICROBLAZE_PS_FSL_LINKS 0 +#define XPAR_MICROBLAZE_PS_IADDR_SIZE 32 +#define XPAR_MICROBLAZE_PS_ICACHE_ALWAYS_USED 1 +#define XPAR_MICROBLAZE_PS_ICACHE_BASEADDR 0x80000000 +#define XPAR_MICROBLAZE_PS_ICACHE_DATA_WIDTH 0 +#define XPAR_MICROBLAZE_PS_ICACHE_FORCE_TAG_LUTRAM 0 +#define XPAR_MICROBLAZE_PS_ICACHE_HIGHADDR 0xFFFFFFFF +#define XPAR_MICROBLAZE_PS_ICACHE_LINE_LEN 4 +#define XPAR_MICROBLAZE_PS_ICACHE_STREAMS 0 +#define XPAR_MICROBLAZE_PS_ICACHE_VICTIMS 0 +#define XPAR_MICROBLAZE_PS_IC_AXI_MON 0 +#define XPAR_MICROBLAZE_PS_ILL_OPCODE_EXCEPTION 1 +#define XPAR_MICROBLAZE_PS_IMPRECISE_EXCEPTIONS 0 +#define XPAR_MICROBLAZE_PS_INSTR_SIZE 32 +#define XPAR_MICROBLAZE_PS_INTERCONNECT 2 +#define XPAR_MICROBLAZE_PS_INTERRUPT_IS_EDGE 0 +#define XPAR_MICROBLAZE_PS_INTERRUPT_MON 0 +#define XPAR_MICROBLAZE_PS_IP_AXI_MON 0 +#define XPAR_MICROBLAZE_PS_I_AXI 0 +#define XPAR_MICROBLAZE_PS_I_LMB 1 +#define XPAR_MICROBLAZE_PS_I_LMB_MON 0 +#define XPAR_MICROBLAZE_PS_LMB_DATA_SIZE 32 +#define XPAR_MICROBLAZE_PS_LOCKSTEP_MASTER 0 +#define XPAR_MICROBLAZE_PS_LOCKSTEP_SELECT 0 +#define XPAR_MICROBLAZE_PS_LOCKSTEP_SLAVE 0 +#define XPAR_MICROBLAZE_PS_M0_AXIS_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_PS_M0_AXIS_PROTOCOL GENERIC +#define XPAR_MICROBLAZE_PS_M1_AXIS_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_PS_M1_AXIS_PROTOCOL GENERIC +#define XPAR_MICROBLAZE_PS_M2_AXIS_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_PS_M2_AXIS_PROTOCOL GENERIC +#define XPAR_MICROBLAZE_PS_M3_AXIS_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_PS_M3_AXIS_PROTOCOL GENERIC +#define XPAR_MICROBLAZE_PS_M4_AXIS_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_PS_M4_AXIS_PROTOCOL GENERIC +#define XPAR_MICROBLAZE_PS_M5_AXIS_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_PS_M5_AXIS_PROTOCOL GENERIC +#define XPAR_MICROBLAZE_PS_M6_AXIS_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_PS_M6_AXIS_PROTOCOL GENERIC +#define XPAR_MICROBLAZE_PS_M7_AXIS_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_PS_M7_AXIS_PROTOCOL GENERIC +#define XPAR_MICROBLAZE_PS_M8_AXIS_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_PS_M8_AXIS_PROTOCOL GENERIC +#define XPAR_MICROBLAZE_PS_M9_AXIS_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_PS_M9_AXIS_PROTOCOL GENERIC +#define XPAR_MICROBLAZE_PS_M10_AXIS_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_PS_M10_AXIS_PROTOCOL GENERIC +#define XPAR_MICROBLAZE_PS_M11_AXIS_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_PS_M11_AXIS_PROTOCOL GENERIC +#define XPAR_MICROBLAZE_PS_M12_AXIS_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_PS_M12_AXIS_PROTOCOL GENERIC +#define XPAR_MICROBLAZE_PS_M13_AXIS_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_PS_M13_AXIS_PROTOCOL GENERIC +#define XPAR_MICROBLAZE_PS_M14_AXIS_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_PS_M14_AXIS_PROTOCOL GENERIC +#define XPAR_MICROBLAZE_PS_M15_AXIS_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_PS_M15_AXIS_PROTOCOL GENERIC +#define XPAR_MICROBLAZE_PS_MMU_DTLB_SIZE 2 +#define XPAR_MICROBLAZE_PS_MMU_ITLB_SIZE 1 +#define XPAR_MICROBLAZE_PS_MMU_PRIVILEGED_INSTR 0 +#define XPAR_MICROBLAZE_PS_MMU_TLB_ACCESS 3 +#define XPAR_MICROBLAZE_PS_MMU_ZONES 2 +#define XPAR_MICROBLAZE_PS_M_AXI_DC_ADDR_WIDTH 32 +#define XPAR_MICROBLAZE_PS_M_AXI_DC_ARUSER_WIDTH 5 +#define XPAR_MICROBLAZE_PS_M_AXI_DC_AWUSER_WIDTH 5 +#define XPAR_MICROBLAZE_PS_M_AXI_DC_BUSER_WIDTH 1 +#define XPAR_MICROBLAZE_PS_M_AXI_DC_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_PS_M_AXI_DC_EXCLUSIVE_ACCESS 0 +#define XPAR_MICROBLAZE_PS_M_AXI_DC_RUSER_WIDTH 1 +#define XPAR_MICROBLAZE_PS_M_AXI_DC_THREAD_ID_WIDTH 1 +#define XPAR_MICROBLAZE_PS_M_AXI_DC_USER_SIGNALS 0 +#define XPAR_MICROBLAZE_PS_M_AXI_DC_USER_VALUE 31 +#define XPAR_MICROBLAZE_PS_M_AXI_DC_WUSER_WIDTH 1 +#define XPAR_MICROBLAZE_PS_M_AXI_DP_ADDR_WIDTH 32 +#define XPAR_MICROBLAZE_PS_M_AXI_DP_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_PS_M_AXI_DP_EXCLUSIVE_ACCESS 0 +#define XPAR_MICROBLAZE_PS_M_AXI_DP_THREAD_ID_WIDTH 1 +#define XPAR_MICROBLAZE_PS_M_AXI_D_BUS_EXCEPTION 1 +#define XPAR_MICROBLAZE_PS_M_AXI_IC_ADDR_WIDTH 32 +#define XPAR_MICROBLAZE_PS_M_AXI_IC_ARUSER_WIDTH 5 +#define XPAR_MICROBLAZE_PS_M_AXI_IC_AWUSER_WIDTH 5 +#define XPAR_MICROBLAZE_PS_M_AXI_IC_BUSER_WIDTH 1 +#define XPAR_MICROBLAZE_PS_M_AXI_IC_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_PS_M_AXI_IC_RUSER_WIDTH 1 +#define XPAR_MICROBLAZE_PS_M_AXI_IC_THREAD_ID_WIDTH 1 +#define XPAR_MICROBLAZE_PS_M_AXI_IC_USER_SIGNALS 0 +#define XPAR_MICROBLAZE_PS_M_AXI_IC_USER_VALUE 31 +#define XPAR_MICROBLAZE_PS_M_AXI_IC_WUSER_WIDTH 1 +#define XPAR_MICROBLAZE_PS_M_AXI_IP_ADDR_WIDTH 32 +#define XPAR_MICROBLAZE_PS_M_AXI_IP_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_PS_M_AXI_IP_THREAD_ID_WIDTH 1 +#define XPAR_MICROBLAZE_PS_M_AXI_I_BUS_EXCEPTION 1 +#define XPAR_MICROBLAZE_PS_NUMBER_OF_PC_BRK 2 +#define XPAR_MICROBLAZE_PS_NUMBER_OF_RD_ADDR_BRK 0 +#define XPAR_MICROBLAZE_PS_NUMBER_OF_WR_ADDR_BRK 0 +#define XPAR_MICROBLAZE_PS_NUM_SYNC_FF_CLK 2 +#define XPAR_MICROBLAZE_PS_NUM_SYNC_FF_CLK_DEBUG 2 +#define XPAR_MICROBLAZE_PS_NUM_SYNC_FF_CLK_IRQ 1 +#define XPAR_MICROBLAZE_PS_NUM_SYNC_FF_DBG_CLK 1 +#define XPAR_MICROBLAZE_PS_NUM_SYNC_FF_DBG_TRACE_CLK 2 +#define XPAR_MICROBLAZE_PS_OPCODE_0X0_ILLEGAL 1 +#define XPAR_MICROBLAZE_PS_OPTIMIZATION 0 +#define XPAR_MICROBLAZE_PS_PC_WIDTH 32 +#define XPAR_MICROBLAZE_PS_PIADDR_SIZE 32 +#define XPAR_MICROBLAZE_PS_PVR 0 +#define XPAR_MICROBLAZE_PS_PVR_USER1 0x00 +#define XPAR_MICROBLAZE_PS_PVR_USER2 0x00000000 +#define XPAR_MICROBLAZE_PS_RESET_MSR 0x00000000 +#define XPAR_MICROBLAZE_PS_RESET_MSR_BIP 0 +#define XPAR_MICROBLAZE_PS_RESET_MSR_DCE 0 +#define XPAR_MICROBLAZE_PS_RESET_MSR_EE 0 +#define XPAR_MICROBLAZE_PS_RESET_MSR_EIP 0 +#define XPAR_MICROBLAZE_PS_RESET_MSR_ICE 0 +#define XPAR_MICROBLAZE_PS_RESET_MSR_IE 0 +#define XPAR_MICROBLAZE_PS_S0_AXIS_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_PS_S0_AXIS_PROTOCOL GENERIC +#define XPAR_MICROBLAZE_PS_S1_AXIS_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_PS_S1_AXIS_PROTOCOL GENERIC +#define XPAR_MICROBLAZE_PS_S2_AXIS_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_PS_S2_AXIS_PROTOCOL GENERIC +#define XPAR_MICROBLAZE_PS_S3_AXIS_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_PS_S3_AXIS_PROTOCOL GENERIC +#define XPAR_MICROBLAZE_PS_S4_AXIS_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_PS_S4_AXIS_PROTOCOL GENERIC +#define XPAR_MICROBLAZE_PS_S5_AXIS_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_PS_S5_AXIS_PROTOCOL GENERIC +#define XPAR_MICROBLAZE_PS_S6_AXIS_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_PS_S6_AXIS_PROTOCOL GENERIC +#define XPAR_MICROBLAZE_PS_S7_AXIS_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_PS_S7_AXIS_PROTOCOL GENERIC +#define XPAR_MICROBLAZE_PS_S8_AXIS_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_PS_S8_AXIS_PROTOCOL GENERIC +#define XPAR_MICROBLAZE_PS_S9_AXIS_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_PS_S9_AXIS_PROTOCOL GENERIC +#define XPAR_MICROBLAZE_PS_S10_AXIS_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_PS_S10_AXIS_PROTOCOL GENERIC +#define XPAR_MICROBLAZE_PS_S11_AXIS_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_PS_S11_AXIS_PROTOCOL GENERIC +#define XPAR_MICROBLAZE_PS_S12_AXIS_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_PS_S12_AXIS_PROTOCOL GENERIC +#define XPAR_MICROBLAZE_PS_S13_AXIS_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_PS_S13_AXIS_PROTOCOL GENERIC +#define XPAR_MICROBLAZE_PS_S14_AXIS_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_PS_S14_AXIS_PROTOCOL GENERIC +#define XPAR_MICROBLAZE_PS_S15_AXIS_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_PS_S15_AXIS_PROTOCOL GENERIC +#define XPAR_MICROBLAZE_PS_SCO 0 +#define XPAR_MICROBLAZE_PS_TRACE 0 +#define XPAR_MICROBLAZE_PS_UNALIGNED_EXCEPTIONS 1 +#define XPAR_MICROBLAZE_PS_USE_BARREL 1 +#define XPAR_MICROBLAZE_PS_USE_BRANCH_TARGET_CACHE 0 +#define XPAR_MICROBLAZE_PS_USE_CONFIG_RESET 0 +#define XPAR_MICROBLAZE_PS_USE_DCACHE 1 +#define XPAR_MICROBLAZE_PS_USE_DIV 1 +#define XPAR_MICROBLAZE_PS_USE_EXTENDED_FSL_INSTR 0 +#define XPAR_MICROBLAZE_PS_USE_EXT_BRK 0 +#define XPAR_MICROBLAZE_PS_USE_EXT_NM_BRK 0 +#define XPAR_MICROBLAZE_PS_USE_FPU 0 +#define XPAR_MICROBLAZE_PS_USE_HW_MUL 1 +#define XPAR_MICROBLAZE_PS_USE_ICACHE 1 +#define XPAR_MICROBLAZE_PS_USE_INTERRUPT 1 +#define XPAR_MICROBLAZE_PS_USE_MMU 0 +#define XPAR_MICROBLAZE_PS_USE_MSR_INSTR 1 +#define XPAR_MICROBLAZE_PS_USE_NON_SECURE 0 +#define XPAR_MICROBLAZE_PS_USE_PCMP_INSTR 1 +#define XPAR_MICROBLAZE_PS_USE_REORDER_INSTR 1 +#define XPAR_MICROBLAZE_PS_USE_STACK_PROTECTION 0 +#define XPAR_MICROBLAZE_PS_COMPONENT_NAME system_microblaze_ps_0 +#define XPAR_MICROBLAZE_PS_EDK_IPTYPE PROCESSOR +#define XPAR_MICROBLAZE_PS_EDK_SPECIAL microblaze +#define XPAR_MICROBLAZE_PS_G_TEMPLATE_LIST 9 +#define XPAR_MICROBLAZE_PS_G_USE_EXCEPTIONS 1 + +/******************************************************************/ + +#define XPAR_CPU_ID 0 +#define XPAR_MICROBLAZE_ID 0 +#define XPAR_MICROBLAZE_ADDR_SIZE 32 +#define XPAR_MICROBLAZE_ADDR_TAG_BITS 17 +#define XPAR_MICROBLAZE_ALLOW_DCACHE_WR 1 +#define XPAR_MICROBLAZE_ALLOW_ICACHE_WR 1 +#define XPAR_MICROBLAZE_AREA_OPTIMIZED 0 +#define XPAR_MICROBLAZE_ASYNC_INTERRUPT 1 +#define XPAR_MICROBLAZE_ASYNC_WAKEUP 3 +#define XPAR_MICROBLAZE_AVOID_PRIMITIVES 0 +#define XPAR_MICROBLAZE_BASE_VECTORS 0x0000000000000000 +#define XPAR_MICROBLAZE_BRANCH_TARGET_CACHE_SIZE 0 +#define XPAR_MICROBLAZE_CACHE_BYTE_SIZE 16384 +#define XPAR_MICROBLAZE_DADDR_SIZE 32 +#define XPAR_MICROBLAZE_DATA_SIZE 32 +#define XPAR_MICROBLAZE_DCACHE_ADDR_TAG 17 +#define XPAR_MICROBLAZE_DCACHE_ALWAYS_USED 0 +#define XPAR_MICROBLAZE_DCACHE_BASEADDR 0x80000000 +#define XPAR_MICROBLAZE_DCACHE_BYTE_SIZE 16384 +#define XPAR_MICROBLAZE_DCACHE_DATA_WIDTH 0 +#define XPAR_MICROBLAZE_DCACHE_FORCE_TAG_LUTRAM 0 +#define XPAR_MICROBLAZE_DCACHE_HIGHADDR 0xFFFFFFFF +#define XPAR_MICROBLAZE_DCACHE_LINE_LEN 4 +#define XPAR_MICROBLAZE_DCACHE_USE_WRITEBACK 1 +#define XPAR_MICROBLAZE_DCACHE_VICTIMS 0 +#define XPAR_MICROBLAZE_DC_AXI_MON 0 +#define XPAR_MICROBLAZE_DEBUG_COUNTER_WIDTH 32 +#define XPAR_MICROBLAZE_DEBUG_ENABLED 1 +#define XPAR_MICROBLAZE_DEBUG_EVENT_COUNTERS 5 +#define XPAR_MICROBLAZE_DEBUG_EXTERNAL_TRACE 0 +#define XPAR_MICROBLAZE_DEBUG_INTERFACE 0 +#define XPAR_MICROBLAZE_DEBUG_LATENCY_COUNTERS 1 +#define XPAR_MICROBLAZE_DEBUG_PROFILE_SIZE 0 +#define XPAR_MICROBLAZE_DEBUG_TRACE_ASYNC_RESET 0 +#define XPAR_MICROBLAZE_DEBUG_TRACE_SIZE 8192 +#define XPAR_MICROBLAZE_DIV_ZERO_EXCEPTION 1 +#define XPAR_MICROBLAZE_DP_AXI_MON 0 +#define XPAR_MICROBLAZE_DYNAMIC_BUS_SIZING 0 +#define XPAR_MICROBLAZE_D_AXI 1 +#define XPAR_MICROBLAZE_D_LMB 1 +#define XPAR_MICROBLAZE_D_LMB_MON 0 +#define XPAR_MICROBLAZE_ECC_USE_CE_EXCEPTION 0 +#define XPAR_MICROBLAZE_EDGE_IS_POSITIVE 1 +#define XPAR_MICROBLAZE_ENABLE_DISCRETE_PORTS 0 +#define XPAR_MICROBLAZE_ENDIANNESS 1 +#define XPAR_MICROBLAZE_FAULT_TOLERANT 0 +#define XPAR_MICROBLAZE_FPU_EXCEPTION 0 +#define XPAR_MICROBLAZE_FREQ 150000000 +#define XPAR_MICROBLAZE_FSL_EXCEPTION 0 +#define XPAR_MICROBLAZE_FSL_LINKS 0 +#define XPAR_MICROBLAZE_IADDR_SIZE 32 +#define XPAR_MICROBLAZE_ICACHE_ALWAYS_USED 1 +#define XPAR_MICROBLAZE_ICACHE_BASEADDR 0x80000000 +#define XPAR_MICROBLAZE_ICACHE_DATA_WIDTH 0 +#define XPAR_MICROBLAZE_ICACHE_FORCE_TAG_LUTRAM 0 +#define XPAR_MICROBLAZE_ICACHE_HIGHADDR 0xFFFFFFFF +#define XPAR_MICROBLAZE_ICACHE_LINE_LEN 4 +#define XPAR_MICROBLAZE_ICACHE_STREAMS 0 +#define XPAR_MICROBLAZE_ICACHE_VICTIMS 0 +#define XPAR_MICROBLAZE_IC_AXI_MON 0 +#define XPAR_MICROBLAZE_ILL_OPCODE_EXCEPTION 1 +#define XPAR_MICROBLAZE_IMPRECISE_EXCEPTIONS 0 +#define XPAR_MICROBLAZE_INSTR_SIZE 32 +#define XPAR_MICROBLAZE_INTERCONNECT 2 +#define XPAR_MICROBLAZE_INTERRUPT_IS_EDGE 0 +#define XPAR_MICROBLAZE_INTERRUPT_MON 0 +#define XPAR_MICROBLAZE_IP_AXI_MON 0 +#define XPAR_MICROBLAZE_I_AXI 0 +#define XPAR_MICROBLAZE_I_LMB 1 +#define XPAR_MICROBLAZE_I_LMB_MON 0 +#define XPAR_MICROBLAZE_LMB_DATA_SIZE 32 +#define XPAR_MICROBLAZE_LOCKSTEP_MASTER 0 +#define XPAR_MICROBLAZE_LOCKSTEP_SELECT 0 +#define XPAR_MICROBLAZE_LOCKSTEP_SLAVE 0 +#define XPAR_MICROBLAZE_M0_AXIS_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_M0_AXIS_PROTOCOL GENERIC +#define XPAR_MICROBLAZE_M1_AXIS_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_M1_AXIS_PROTOCOL GENERIC +#define XPAR_MICROBLAZE_M2_AXIS_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_M2_AXIS_PROTOCOL GENERIC +#define XPAR_MICROBLAZE_M3_AXIS_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_M3_AXIS_PROTOCOL GENERIC +#define XPAR_MICROBLAZE_M4_AXIS_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_M4_AXIS_PROTOCOL GENERIC +#define XPAR_MICROBLAZE_M5_AXIS_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_M5_AXIS_PROTOCOL GENERIC +#define XPAR_MICROBLAZE_M6_AXIS_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_M6_AXIS_PROTOCOL GENERIC +#define XPAR_MICROBLAZE_M7_AXIS_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_M7_AXIS_PROTOCOL GENERIC +#define XPAR_MICROBLAZE_M8_AXIS_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_M8_AXIS_PROTOCOL GENERIC +#define XPAR_MICROBLAZE_M9_AXIS_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_M9_AXIS_PROTOCOL GENERIC +#define XPAR_MICROBLAZE_M10_AXIS_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_M10_AXIS_PROTOCOL GENERIC +#define XPAR_MICROBLAZE_M11_AXIS_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_M11_AXIS_PROTOCOL GENERIC +#define XPAR_MICROBLAZE_M12_AXIS_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_M12_AXIS_PROTOCOL GENERIC +#define XPAR_MICROBLAZE_M13_AXIS_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_M13_AXIS_PROTOCOL GENERIC +#define XPAR_MICROBLAZE_M14_AXIS_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_M14_AXIS_PROTOCOL GENERIC +#define XPAR_MICROBLAZE_M15_AXIS_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_M15_AXIS_PROTOCOL GENERIC +#define XPAR_MICROBLAZE_MMU_DTLB_SIZE 2 +#define XPAR_MICROBLAZE_MMU_ITLB_SIZE 1 +#define XPAR_MICROBLAZE_MMU_PRIVILEGED_INSTR 0 +#define XPAR_MICROBLAZE_MMU_TLB_ACCESS 3 +#define XPAR_MICROBLAZE_MMU_ZONES 2 +#define XPAR_MICROBLAZE_M_AXI_DC_ADDR_WIDTH 32 +#define XPAR_MICROBLAZE_M_AXI_DC_ARUSER_WIDTH 5 +#define XPAR_MICROBLAZE_M_AXI_DC_AWUSER_WIDTH 5 +#define XPAR_MICROBLAZE_M_AXI_DC_BUSER_WIDTH 1 +#define XPAR_MICROBLAZE_M_AXI_DC_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_M_AXI_DC_EXCLUSIVE_ACCESS 0 +#define XPAR_MICROBLAZE_M_AXI_DC_RUSER_WIDTH 1 +#define XPAR_MICROBLAZE_M_AXI_DC_THREAD_ID_WIDTH 1 +#define XPAR_MICROBLAZE_M_AXI_DC_USER_SIGNALS 0 +#define XPAR_MICROBLAZE_M_AXI_DC_USER_VALUE 31 +#define XPAR_MICROBLAZE_M_AXI_DC_WUSER_WIDTH 1 +#define XPAR_MICROBLAZE_M_AXI_DP_ADDR_WIDTH 32 +#define XPAR_MICROBLAZE_M_AXI_DP_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_M_AXI_DP_EXCLUSIVE_ACCESS 0 +#define XPAR_MICROBLAZE_M_AXI_DP_THREAD_ID_WIDTH 1 +#define XPAR_MICROBLAZE_M_AXI_D_BUS_EXCEPTION 1 +#define XPAR_MICROBLAZE_M_AXI_IC_ADDR_WIDTH 32 +#define XPAR_MICROBLAZE_M_AXI_IC_ARUSER_WIDTH 5 +#define XPAR_MICROBLAZE_M_AXI_IC_AWUSER_WIDTH 5 +#define XPAR_MICROBLAZE_M_AXI_IC_BUSER_WIDTH 1 +#define XPAR_MICROBLAZE_M_AXI_IC_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_M_AXI_IC_RUSER_WIDTH 1 +#define XPAR_MICROBLAZE_M_AXI_IC_THREAD_ID_WIDTH 1 +#define XPAR_MICROBLAZE_M_AXI_IC_USER_SIGNALS 0 +#define XPAR_MICROBLAZE_M_AXI_IC_USER_VALUE 31 +#define XPAR_MICROBLAZE_M_AXI_IC_WUSER_WIDTH 1 +#define XPAR_MICROBLAZE_M_AXI_IP_ADDR_WIDTH 32 +#define XPAR_MICROBLAZE_M_AXI_IP_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_M_AXI_IP_THREAD_ID_WIDTH 1 +#define XPAR_MICROBLAZE_M_AXI_I_BUS_EXCEPTION 1 +#define XPAR_MICROBLAZE_NUMBER_OF_PC_BRK 2 +#define XPAR_MICROBLAZE_NUMBER_OF_RD_ADDR_BRK 0 +#define XPAR_MICROBLAZE_NUMBER_OF_WR_ADDR_BRK 0 +#define XPAR_MICROBLAZE_NUM_SYNC_FF_CLK 2 +#define XPAR_MICROBLAZE_NUM_SYNC_FF_CLK_DEBUG 2 +#define XPAR_MICROBLAZE_NUM_SYNC_FF_CLK_IRQ 1 +#define XPAR_MICROBLAZE_NUM_SYNC_FF_DBG_CLK 1 +#define XPAR_MICROBLAZE_NUM_SYNC_FF_DBG_TRACE_CLK 2 +#define XPAR_MICROBLAZE_OPCODE_0X0_ILLEGAL 1 +#define XPAR_MICROBLAZE_OPTIMIZATION 0 +#define XPAR_MICROBLAZE_PC_WIDTH 32 +#define XPAR_MICROBLAZE_PIADDR_SIZE 32 +#define XPAR_MICROBLAZE_PVR 0 +#define XPAR_MICROBLAZE_PVR_USER1 0x00 +#define XPAR_MICROBLAZE_PVR_USER2 0x00000000 +#define XPAR_MICROBLAZE_RESET_MSR 0x00000000 +#define XPAR_MICROBLAZE_RESET_MSR_BIP 0 +#define XPAR_MICROBLAZE_RESET_MSR_DCE 0 +#define XPAR_MICROBLAZE_RESET_MSR_EE 0 +#define XPAR_MICROBLAZE_RESET_MSR_EIP 0 +#define XPAR_MICROBLAZE_RESET_MSR_ICE 0 +#define XPAR_MICROBLAZE_RESET_MSR_IE 0 +#define XPAR_MICROBLAZE_S0_AXIS_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_S0_AXIS_PROTOCOL GENERIC +#define XPAR_MICROBLAZE_S1_AXIS_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_S1_AXIS_PROTOCOL GENERIC +#define XPAR_MICROBLAZE_S2_AXIS_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_S2_AXIS_PROTOCOL GENERIC +#define XPAR_MICROBLAZE_S3_AXIS_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_S3_AXIS_PROTOCOL GENERIC +#define XPAR_MICROBLAZE_S4_AXIS_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_S4_AXIS_PROTOCOL GENERIC +#define XPAR_MICROBLAZE_S5_AXIS_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_S5_AXIS_PROTOCOL GENERIC +#define XPAR_MICROBLAZE_S6_AXIS_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_S6_AXIS_PROTOCOL GENERIC +#define XPAR_MICROBLAZE_S7_AXIS_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_S7_AXIS_PROTOCOL GENERIC +#define XPAR_MICROBLAZE_S8_AXIS_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_S8_AXIS_PROTOCOL GENERIC +#define XPAR_MICROBLAZE_S9_AXIS_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_S9_AXIS_PROTOCOL GENERIC +#define XPAR_MICROBLAZE_S10_AXIS_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_S10_AXIS_PROTOCOL GENERIC +#define XPAR_MICROBLAZE_S11_AXIS_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_S11_AXIS_PROTOCOL GENERIC +#define XPAR_MICROBLAZE_S12_AXIS_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_S12_AXIS_PROTOCOL GENERIC +#define XPAR_MICROBLAZE_S13_AXIS_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_S13_AXIS_PROTOCOL GENERIC +#define XPAR_MICROBLAZE_S14_AXIS_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_S14_AXIS_PROTOCOL GENERIC +#define XPAR_MICROBLAZE_S15_AXIS_DATA_WIDTH 32 +#define XPAR_MICROBLAZE_S15_AXIS_PROTOCOL GENERIC +#define XPAR_MICROBLAZE_SCO 0 +#define XPAR_MICROBLAZE_TRACE 0 +#define XPAR_MICROBLAZE_UNALIGNED_EXCEPTIONS 1 +#define XPAR_MICROBLAZE_USE_BARREL 1 +#define XPAR_MICROBLAZE_USE_BRANCH_TARGET_CACHE 0 +#define XPAR_MICROBLAZE_USE_CONFIG_RESET 0 +#define XPAR_MICROBLAZE_USE_DCACHE 1 +#define XPAR_MICROBLAZE_USE_DIV 1 +#define XPAR_MICROBLAZE_USE_EXTENDED_FSL_INSTR 0 +#define XPAR_MICROBLAZE_USE_EXT_BRK 0 +#define XPAR_MICROBLAZE_USE_EXT_NM_BRK 0 +#define XPAR_MICROBLAZE_USE_FPU 0 +#define XPAR_MICROBLAZE_USE_HW_MUL 1 +#define XPAR_MICROBLAZE_USE_ICACHE 1 +#define XPAR_MICROBLAZE_USE_INTERRUPT 1 +#define XPAR_MICROBLAZE_USE_MMU 0 +#define XPAR_MICROBLAZE_USE_MSR_INSTR 1 +#define XPAR_MICROBLAZE_USE_NON_SECURE 0 +#define XPAR_MICROBLAZE_USE_PCMP_INSTR 1 +#define XPAR_MICROBLAZE_USE_REORDER_INSTR 1 +#define XPAR_MICROBLAZE_USE_STACK_PROTECTION 0 +#define XPAR_MICROBLAZE_COMPONENT_NAME system_microblaze_ps_0 +#define XPAR_MICROBLAZE_EDK_IPTYPE PROCESSOR +#define XPAR_MICROBLAZE_EDK_SPECIAL microblaze +#define XPAR_MICROBLAZE_G_TEMPLATE_LIST 9 +#define XPAR_MICROBLAZE_G_USE_EXCEPTIONS 1 + +/******************************************************************/ + + +/* Definitions for interface PHYC */ +#define XPAR_PHYC_BASEADDR 0x44A10000 +#define XPAR_PHYC_HIGHADDR 0x44A1FFFF + + +/* Definitions for interface PHYC */ +#define XPAR_PHYC_BASEADDR 0x44A10000 +#define XPAR_PHYC_HIGHADDR 0x44A1FFFF + + +/******************************************************************/ + +/* Platform specific definitions */ +#define PLATFORM_MB + +/* Definitions for sleep timer configuration */ +#define XSLEEP_TIMER_IS_DEFAULT_TIMER + + +/******************************************************************/ +/* Definitions for driver AXIDMA */ +#define XPAR_XAXIDMA_NUM_INSTANCES 1 + +/* Definitions for peripheral AXI_DMA_C2C */ +#define XPAR_AXI_DMA_C2C_DEVICE_ID 0 +#define XPAR_AXI_DMA_C2C_BASEADDR 0x41E00000 +#define XPAR_AXI_DMA_C2C_HIGHADDR 0x41E0FFFF +#define XPAR_AXI_DMA_C2C_SG_INCLUDE_STSCNTRL_STRM 0 +#define XPAR_AXI_DMA_C2C_INCLUDE_MM2S_DRE 1 +#define XPAR_AXI_DMA_C2C_INCLUDE_S2MM_DRE 1 +#define XPAR_AXI_DMA_C2C_INCLUDE_MM2S 1 +#define XPAR_AXI_DMA_C2C_INCLUDE_S2MM 1 +#define XPAR_AXI_DMA_C2C_M_AXI_MM2S_DATA_WIDTH 32 +#define XPAR_AXI_DMA_C2C_M_AXI_S2MM_DATA_WIDTH 32 +#define XPAR_AXI_DMA_C2C_INCLUDE_SG 0 +#define XPAR_AXI_DMA_C2C_ENABLE_MULTI_CHANNEL 0 +#define XPAR_AXI_DMA_C2C_NUM_MM2S_CHANNELS 1 +#define XPAR_AXI_DMA_C2C_NUM_S2MM_CHANNELS 1 +#define XPAR_AXI_DMA_C2C_MM2S_BURST_SIZE 64 +#define XPAR_AXI_DMA_C2C_S2MM_BURST_SIZE 64 +#define XPAR_AXI_DMA_C2C_MICRO_DMA 0 +#define XPAR_AXI_DMA_C2C_ADDR_WIDTH 32 +#define XPAR_AXI_DMA_C2C_SG_LENGTH_WIDTH 14 + + +/******************************************************************/ + +/* Canonical definitions for peripheral AXI_DMA_C2C */ +#define XPAR_AXIDMA_0_DEVICE_ID XPAR_AXI_DMA_C2C_DEVICE_ID +#define XPAR_AXIDMA_0_BASEADDR 0x41E00000 +#define XPAR_AXIDMA_0_SG_INCLUDE_STSCNTRL_STRM 0 +#define XPAR_AXIDMA_0_INCLUDE_MM2S 1 +#define XPAR_AXIDMA_0_INCLUDE_MM2S_DRE 1 +#define XPAR_AXIDMA_0_M_AXI_MM2S_DATA_WIDTH 32 +#define XPAR_AXIDMA_0_INCLUDE_S2MM 1 +#define XPAR_AXIDMA_0_INCLUDE_S2MM_DRE 1 +#define XPAR_AXIDMA_0_M_AXI_S2MM_DATA_WIDTH 32 +#define XPAR_AXIDMA_0_INCLUDE_SG 0 +#define XPAR_AXIDMA_0_ENABLE_MULTI_CHANNEL 0 +#define XPAR_AXIDMA_0_NUM_MM2S_CHANNELS 1 +#define XPAR_AXIDMA_0_NUM_S2MM_CHANNELS 1 +#define XPAR_AXIDMA_0_MM2S_BURST_SIZE 64 +#define XPAR_AXIDMA_0_S2MM_BURST_SIZE 64 +#define XPAR_AXIDMA_0_MICRO_DMA 0 +#define XPAR_AXIDMA_0_c_addr_width 32 +#define XPAR_AXIDMA_0_c_sg_length_width 14 + + +/******************************************************************/ + +/* Definitions for driver BRAM */ +#define XPAR_XBRAM_NUM_INSTANCES 7U + +/* Definitions for peripheral ANT_CONFIG_BRAM_CTRL */ +#define XPAR_ANT_CONFIG_BRAM_CTRL_DEVICE_ID 0U +#define XPAR_ANT_CONFIG_BRAM_CTRL_DATA_WIDTH 32U +#define XPAR_ANT_CONFIG_BRAM_CTRL_ECC 0U +#define XPAR_ANT_CONFIG_BRAM_CTRL_FAULT_INJECT 0U +#define XPAR_ANT_CONFIG_BRAM_CTRL_CE_FAILING_REGISTERS 0U +#define XPAR_ANT_CONFIG_BRAM_CTRL_UE_FAILING_REGISTERS 0U +#define XPAR_ANT_CONFIG_BRAM_CTRL_ECC_STATUS_REGISTERS 0U +#define XPAR_ANT_CONFIG_BRAM_CTRL_CE_COUNTER_WIDTH 0U +#define XPAR_ANT_CONFIG_BRAM_CTRL_ECC_ONOFF_REGISTER 0U +#define XPAR_ANT_CONFIG_BRAM_CTRL_ECC_ONOFF_RESET_VALUE 0U +#define XPAR_ANT_CONFIG_BRAM_CTRL_WRITE_ACCESS 0U +#define XPAR_ANT_CONFIG_BRAM_CTRL_S_AXI_BASEADDR 0xC0000000U +#define XPAR_ANT_CONFIG_BRAM_CTRL_S_AXI_HIGHADDR 0xC0001FFFU +#define XPAR_ANT_CONFIG_BRAM_CTRL_S_AXI_CTRL_BASEADDR 0xFFFFFFFFU +#define XPAR_ANT_CONFIG_BRAM_CTRL_S_AXI_CTRL_HIGHADDR 0xFFFFFFFFU + + +/* Definitions for peripheral C2C_RX_AXI_BRAM_CTRL */ +#define XPAR_C2C_RX_AXI_BRAM_CTRL_DEVICE_ID 1U +#define XPAR_C2C_RX_AXI_BRAM_CTRL_DATA_WIDTH 32U +#define XPAR_C2C_RX_AXI_BRAM_CTRL_ECC 0U +#define XPAR_C2C_RX_AXI_BRAM_CTRL_FAULT_INJECT 0U +#define XPAR_C2C_RX_AXI_BRAM_CTRL_CE_FAILING_REGISTERS 0U +#define XPAR_C2C_RX_AXI_BRAM_CTRL_UE_FAILING_REGISTERS 0U +#define XPAR_C2C_RX_AXI_BRAM_CTRL_ECC_STATUS_REGISTERS 0U +#define XPAR_C2C_RX_AXI_BRAM_CTRL_CE_COUNTER_WIDTH 0U +#define XPAR_C2C_RX_AXI_BRAM_CTRL_ECC_ONOFF_REGISTER 0U +#define XPAR_C2C_RX_AXI_BRAM_CTRL_ECC_ONOFF_RESET_VALUE 0U +#define XPAR_C2C_RX_AXI_BRAM_CTRL_WRITE_ACCESS 0U +#define XPAR_C2C_RX_AXI_BRAM_CTRL_S_AXI_BASEADDR 0xC6000000U +#define XPAR_C2C_RX_AXI_BRAM_CTRL_S_AXI_HIGHADDR 0xC6001FFFU +#define XPAR_C2C_RX_AXI_BRAM_CTRL_S_AXI_CTRL_BASEADDR 0xFFFFFFFFU +#define XPAR_C2C_RX_AXI_BRAM_CTRL_S_AXI_CTRL_HIGHADDR 0xFFFFFFFFU + + +/* Definitions for peripheral C2C_TX_AXI_BRAM_CTRL */ +#define XPAR_C2C_TX_AXI_BRAM_CTRL_DEVICE_ID 2U +#define XPAR_C2C_TX_AXI_BRAM_CTRL_DATA_WIDTH 32U +#define XPAR_C2C_TX_AXI_BRAM_CTRL_ECC 0U +#define XPAR_C2C_TX_AXI_BRAM_CTRL_FAULT_INJECT 0U +#define XPAR_C2C_TX_AXI_BRAM_CTRL_CE_FAILING_REGISTERS 0U +#define XPAR_C2C_TX_AXI_BRAM_CTRL_UE_FAILING_REGISTERS 0U +#define XPAR_C2C_TX_AXI_BRAM_CTRL_ECC_STATUS_REGISTERS 0U +#define XPAR_C2C_TX_AXI_BRAM_CTRL_CE_COUNTER_WIDTH 0U +#define XPAR_C2C_TX_AXI_BRAM_CTRL_ECC_ONOFF_REGISTER 0U +#define XPAR_C2C_TX_AXI_BRAM_CTRL_ECC_ONOFF_RESET_VALUE 0U +#define XPAR_C2C_TX_AXI_BRAM_CTRL_WRITE_ACCESS 0U +#define XPAR_C2C_TX_AXI_BRAM_CTRL_S_AXI_BASEADDR 0xC8000000U +#define XPAR_C2C_TX_AXI_BRAM_CTRL_S_AXI_HIGHADDR 0xC8001FFFU +#define XPAR_C2C_TX_AXI_BRAM_CTRL_S_AXI_CTRL_BASEADDR 0xFFFFFFFFU +#define XPAR_C2C_TX_AXI_BRAM_CTRL_S_AXI_CTRL_HIGHADDR 0xFFFFFFFFU + + +/* Definitions for peripheral MICROBLAZE_PS_LOCAL_MEMORY_DLMB_BRAM_IF_CNTLR */ +#define XPAR_MICROBLAZE_PS_LOCAL_MEMORY_DLMB_BRAM_IF_CNTLR_DEVICE_ID 3U +#define XPAR_MICROBLAZE_PS_LOCAL_MEMORY_DLMB_BRAM_IF_CNTLR_DATA_WIDTH 32U +#define XPAR_MICROBLAZE_PS_LOCAL_MEMORY_DLMB_BRAM_IF_CNTLR_ECC 0U +#define XPAR_MICROBLAZE_PS_LOCAL_MEMORY_DLMB_BRAM_IF_CNTLR_FAULT_INJECT 0U +#define XPAR_MICROBLAZE_PS_LOCAL_MEMORY_DLMB_BRAM_IF_CNTLR_CE_FAILING_REGISTERS 0U +#define XPAR_MICROBLAZE_PS_LOCAL_MEMORY_DLMB_BRAM_IF_CNTLR_UE_FAILING_REGISTERS 0U +#define XPAR_MICROBLAZE_PS_LOCAL_MEMORY_DLMB_BRAM_IF_CNTLR_ECC_STATUS_REGISTERS 0U +#define XPAR_MICROBLAZE_PS_LOCAL_MEMORY_DLMB_BRAM_IF_CNTLR_CE_COUNTER_WIDTH 0U +#define XPAR_MICROBLAZE_PS_LOCAL_MEMORY_DLMB_BRAM_IF_CNTLR_ECC_ONOFF_REGISTER 0U +#define XPAR_MICROBLAZE_PS_LOCAL_MEMORY_DLMB_BRAM_IF_CNTLR_ECC_ONOFF_RESET_VALUE 1U +#define XPAR_MICROBLAZE_PS_LOCAL_MEMORY_DLMB_BRAM_IF_CNTLR_WRITE_ACCESS 2U +#define XPAR_MICROBLAZE_PS_LOCAL_MEMORY_DLMB_BRAM_IF_CNTLR_BASEADDR 0x00000000U +#define XPAR_MICROBLAZE_PS_LOCAL_MEMORY_DLMB_BRAM_IF_CNTLR_HIGHADDR 0x0003FFFFU +#define XPAR_MICROBLAZE_PS_LOCAL_MEMORY_DLMB_BRAM_IF_CNTLR_S_AXI_CTRL_BASEADDR 0xFFFFFFFFU +#define XPAR_MICROBLAZE_PS_LOCAL_MEMORY_DLMB_BRAM_IF_CNTLR_S_AXI_CTRL_HIGHADDR 0xFFFFFFFFU + + +/* Definitions for peripheral MICROBLAZE_PS_LOCAL_MEMORY_ILMB_BRAM_IF_CNTLR */ +#define XPAR_MICROBLAZE_PS_LOCAL_MEMORY_ILMB_BRAM_IF_CNTLR_DEVICE_ID 4U +#define XPAR_MICROBLAZE_PS_LOCAL_MEMORY_ILMB_BRAM_IF_CNTLR_DATA_WIDTH 32U +#define XPAR_MICROBLAZE_PS_LOCAL_MEMORY_ILMB_BRAM_IF_CNTLR_ECC 0U +#define XPAR_MICROBLAZE_PS_LOCAL_MEMORY_ILMB_BRAM_IF_CNTLR_FAULT_INJECT 0U +#define XPAR_MICROBLAZE_PS_LOCAL_MEMORY_ILMB_BRAM_IF_CNTLR_CE_FAILING_REGISTERS 0U +#define XPAR_MICROBLAZE_PS_LOCAL_MEMORY_ILMB_BRAM_IF_CNTLR_UE_FAILING_REGISTERS 0U +#define XPAR_MICROBLAZE_PS_LOCAL_MEMORY_ILMB_BRAM_IF_CNTLR_ECC_STATUS_REGISTERS 0U +#define XPAR_MICROBLAZE_PS_LOCAL_MEMORY_ILMB_BRAM_IF_CNTLR_CE_COUNTER_WIDTH 0U +#define XPAR_MICROBLAZE_PS_LOCAL_MEMORY_ILMB_BRAM_IF_CNTLR_ECC_ONOFF_REGISTER 0U +#define XPAR_MICROBLAZE_PS_LOCAL_MEMORY_ILMB_BRAM_IF_CNTLR_ECC_ONOFF_RESET_VALUE 1U +#define XPAR_MICROBLAZE_PS_LOCAL_MEMORY_ILMB_BRAM_IF_CNTLR_WRITE_ACCESS 2U +#define XPAR_MICROBLAZE_PS_LOCAL_MEMORY_ILMB_BRAM_IF_CNTLR_BASEADDR 0x00000000U +#define XPAR_MICROBLAZE_PS_LOCAL_MEMORY_ILMB_BRAM_IF_CNTLR_HIGHADDR 0x0003FFFFU +#define XPAR_MICROBLAZE_PS_LOCAL_MEMORY_ILMB_BRAM_IF_CNTLR_S_AXI_CTRL_BASEADDR 0xFFFFFFFFU +#define XPAR_MICROBLAZE_PS_LOCAL_MEMORY_ILMB_BRAM_IF_CNTLR_S_AXI_CTRL_HIGHADDR 0xFFFFFFFFU + + +/* Definitions for peripheral RX_FRAME_BRAM_CTRL */ +#define XPAR_RX_FRAME_BRAM_CTRL_DEVICE_ID 5U +#define XPAR_RX_FRAME_BRAM_CTRL_DATA_WIDTH 32U +#define XPAR_RX_FRAME_BRAM_CTRL_ECC 0U +#define XPAR_RX_FRAME_BRAM_CTRL_FAULT_INJECT 0U +#define XPAR_RX_FRAME_BRAM_CTRL_CE_FAILING_REGISTERS 0U +#define XPAR_RX_FRAME_BRAM_CTRL_UE_FAILING_REGISTERS 0U +#define XPAR_RX_FRAME_BRAM_CTRL_ECC_STATUS_REGISTERS 0U +#define XPAR_RX_FRAME_BRAM_CTRL_CE_COUNTER_WIDTH 0U +#define XPAR_RX_FRAME_BRAM_CTRL_ECC_ONOFF_REGISTER 0U +#define XPAR_RX_FRAME_BRAM_CTRL_ECC_ONOFF_RESET_VALUE 0U +#define XPAR_RX_FRAME_BRAM_CTRL_WRITE_ACCESS 0U +#define XPAR_RX_FRAME_BRAM_CTRL_S_AXI_BASEADDR 0xC4000000U +#define XPAR_RX_FRAME_BRAM_CTRL_S_AXI_HIGHADDR 0xC4000FFFU +#define XPAR_RX_FRAME_BRAM_CTRL_S_AXI_CTRL_BASEADDR 0xFFFFFFFFU +#define XPAR_RX_FRAME_BRAM_CTRL_S_AXI_CTRL_HIGHADDR 0xFFFFFFFFU + + +/* Definitions for peripheral TX_FRAME_BRAM_CTRL */ +#define XPAR_TX_FRAME_BRAM_CTRL_DEVICE_ID 6U +#define XPAR_TX_FRAME_BRAM_CTRL_DATA_WIDTH 32U +#define XPAR_TX_FRAME_BRAM_CTRL_ECC 0U +#define XPAR_TX_FRAME_BRAM_CTRL_FAULT_INJECT 0U +#define XPAR_TX_FRAME_BRAM_CTRL_CE_FAILING_REGISTERS 0U +#define XPAR_TX_FRAME_BRAM_CTRL_UE_FAILING_REGISTERS 0U +#define XPAR_TX_FRAME_BRAM_CTRL_ECC_STATUS_REGISTERS 0U +#define XPAR_TX_FRAME_BRAM_CTRL_CE_COUNTER_WIDTH 0U +#define XPAR_TX_FRAME_BRAM_CTRL_ECC_ONOFF_REGISTER 0U +#define XPAR_TX_FRAME_BRAM_CTRL_ECC_ONOFF_RESET_VALUE 0U +#define XPAR_TX_FRAME_BRAM_CTRL_WRITE_ACCESS 0U +#define XPAR_TX_FRAME_BRAM_CTRL_S_AXI_BASEADDR 0xC2000000U +#define XPAR_TX_FRAME_BRAM_CTRL_S_AXI_HIGHADDR 0xC2000FFFU +#define XPAR_TX_FRAME_BRAM_CTRL_S_AXI_CTRL_BASEADDR 0xFFFFFFFFU +#define XPAR_TX_FRAME_BRAM_CTRL_S_AXI_CTRL_HIGHADDR 0xFFFFFFFFU + + +/******************************************************************/ + +/* Canonical definitions for peripheral ANT_CONFIG_BRAM_CTRL */ +#define XPAR_BRAM_0_DEVICE_ID XPAR_ANT_CONFIG_BRAM_CTRL_DEVICE_ID +#define XPAR_BRAM_0_DATA_WIDTH 32U +#define XPAR_BRAM_0_ECC 0U +#define XPAR_BRAM_0_FAULT_INJECT 0U +#define XPAR_BRAM_0_CE_FAILING_REGISTERS 0U +#define XPAR_BRAM_0_UE_FAILING_REGISTERS 0U +#define XPAR_BRAM_0_ECC_STATUS_REGISTERS 0U +#define XPAR_BRAM_0_CE_COUNTER_WIDTH 0U +#define XPAR_BRAM_0_ECC_ONOFF_REGISTER 0U +#define XPAR_BRAM_0_ECC_ONOFF_RESET_VALUE 0U +#define XPAR_BRAM_0_WRITE_ACCESS 0U +#define XPAR_BRAM_0_BASEADDR 0xC0000000U +#define XPAR_BRAM_0_HIGHADDR 0xC0001FFFU +#define XPAR_BRAM_0_CTRL_BASEADDR 0xFFFFFFFFU +#define XPAR_BRAM_0_CTRL_HIGHADDR 0xFFFFFFFEU + +/* Canonical definitions for peripheral C2C_RX_AXI_BRAM_CTRL */ +#define XPAR_BRAM_1_DEVICE_ID XPAR_C2C_RX_AXI_BRAM_CTRL_DEVICE_ID +#define XPAR_BRAM_1_DATA_WIDTH 32U +#define XPAR_BRAM_1_ECC 0U +#define XPAR_BRAM_1_FAULT_INJECT 0U +#define XPAR_BRAM_1_CE_FAILING_REGISTERS 0U +#define XPAR_BRAM_1_UE_FAILING_REGISTERS 0U +#define XPAR_BRAM_1_ECC_STATUS_REGISTERS 0U +#define XPAR_BRAM_1_CE_COUNTER_WIDTH 0U +#define XPAR_BRAM_1_ECC_ONOFF_REGISTER 0U +#define XPAR_BRAM_1_ECC_ONOFF_RESET_VALUE 0U +#define XPAR_BRAM_1_WRITE_ACCESS 0U +#define XPAR_BRAM_1_BASEADDR 0xC6000000U +#define XPAR_BRAM_1_HIGHADDR 0xC6001FFFU +#define XPAR_BRAM_1_CTRL_BASEADDR 0xFFFFFFFFU +#define XPAR_BRAM_1_CTRL_HIGHADDR 0xFFFFFFFEU + +/* Canonical definitions for peripheral C2C_TX_AXI_BRAM_CTRL */ +#define XPAR_BRAM_2_DEVICE_ID XPAR_C2C_TX_AXI_BRAM_CTRL_DEVICE_ID +#define XPAR_BRAM_2_DATA_WIDTH 32U +#define XPAR_BRAM_2_ECC 0U +#define XPAR_BRAM_2_FAULT_INJECT 0U +#define XPAR_BRAM_2_CE_FAILING_REGISTERS 0U +#define XPAR_BRAM_2_UE_FAILING_REGISTERS 0U +#define XPAR_BRAM_2_ECC_STATUS_REGISTERS 0U +#define XPAR_BRAM_2_CE_COUNTER_WIDTH 0U +#define XPAR_BRAM_2_ECC_ONOFF_REGISTER 0U +#define XPAR_BRAM_2_ECC_ONOFF_RESET_VALUE 0U +#define XPAR_BRAM_2_WRITE_ACCESS 0U +#define XPAR_BRAM_2_BASEADDR 0xC8000000U +#define XPAR_BRAM_2_HIGHADDR 0xC8001FFFU +#define XPAR_BRAM_2_CTRL_BASEADDR 0xFFFFFFFFU +#define XPAR_BRAM_2_CTRL_HIGHADDR 0xFFFFFFFEU + +/* Canonical definitions for peripheral MICROBLAZE_PS_LOCAL_MEMORY_DLMB_BRAM_IF_CNTLR */ +#define XPAR_BRAM_3_DEVICE_ID XPAR_MICROBLAZE_PS_LOCAL_MEMORY_DLMB_BRAM_IF_CNTLR_DEVICE_ID +#define XPAR_BRAM_3_DATA_WIDTH 32U +#define XPAR_BRAM_3_ECC 0U +#define XPAR_BRAM_3_FAULT_INJECT 0U +#define XPAR_BRAM_3_CE_FAILING_REGISTERS 0U +#define XPAR_BRAM_3_UE_FAILING_REGISTERS 0U +#define XPAR_BRAM_3_ECC_STATUS_REGISTERS 0U +#define XPAR_BRAM_3_CE_COUNTER_WIDTH 0U +#define XPAR_BRAM_3_ECC_ONOFF_REGISTER 0U +#define XPAR_BRAM_3_ECC_ONOFF_RESET_VALUE 1U +#define XPAR_BRAM_3_WRITE_ACCESS 2U +#define XPAR_BRAM_3_BASEADDR 0x00000000U +#define XPAR_BRAM_3_HIGHADDR 0x0003FFFFU +#define XPAR_BRAM_3_CTRL_BASEADDR 0xFFFFFFFFU +#define XPAR_BRAM_3_CTRL_HIGHADDR 0xFFFFFFFEU + +/* Canonical definitions for peripheral MICROBLAZE_PS_LOCAL_MEMORY_ILMB_BRAM_IF_CNTLR */ +#define XPAR_BRAM_4_DEVICE_ID XPAR_MICROBLAZE_PS_LOCAL_MEMORY_ILMB_BRAM_IF_CNTLR_DEVICE_ID +#define XPAR_BRAM_4_DATA_WIDTH 32U +#define XPAR_BRAM_4_ECC 0U +#define XPAR_BRAM_4_FAULT_INJECT 0U +#define XPAR_BRAM_4_CE_FAILING_REGISTERS 0U +#define XPAR_BRAM_4_UE_FAILING_REGISTERS 0U +#define XPAR_BRAM_4_ECC_STATUS_REGISTERS 0U +#define XPAR_BRAM_4_CE_COUNTER_WIDTH 0U +#define XPAR_BRAM_4_ECC_ONOFF_REGISTER 0U +#define XPAR_BRAM_4_ECC_ONOFF_RESET_VALUE 1U +#define XPAR_BRAM_4_WRITE_ACCESS 2U +#define XPAR_BRAM_4_BASEADDR 0x00000000U +#define XPAR_BRAM_4_HIGHADDR 0x0003FFFFU +#define XPAR_BRAM_4_CTRL_BASEADDR 0xFFFFFFFFU +#define XPAR_BRAM_4_CTRL_HIGHADDR 0xFFFFFFFEU + +/* Canonical definitions for peripheral RX_FRAME_BRAM_CTRL */ +#define XPAR_BRAM_5_DEVICE_ID XPAR_RX_FRAME_BRAM_CTRL_DEVICE_ID +#define XPAR_BRAM_5_DATA_WIDTH 32U +#define XPAR_BRAM_5_ECC 0U +#define XPAR_BRAM_5_FAULT_INJECT 0U +#define XPAR_BRAM_5_CE_FAILING_REGISTERS 0U +#define XPAR_BRAM_5_UE_FAILING_REGISTERS 0U +#define XPAR_BRAM_5_ECC_STATUS_REGISTERS 0U +#define XPAR_BRAM_5_CE_COUNTER_WIDTH 0U +#define XPAR_BRAM_5_ECC_ONOFF_REGISTER 0U +#define XPAR_BRAM_5_ECC_ONOFF_RESET_VALUE 0U +#define XPAR_BRAM_5_WRITE_ACCESS 0U +#define XPAR_BRAM_5_BASEADDR 0xC4000000U +#define XPAR_BRAM_5_HIGHADDR 0xC4000FFFU +#define XPAR_BRAM_5_CTRL_BASEADDR 0xFFFFFFFFU +#define XPAR_BRAM_5_CTRL_HIGHADDR 0xFFFFFFFEU + +/* Canonical definitions for peripheral TX_FRAME_BRAM_CTRL */ +#define XPAR_BRAM_6_DEVICE_ID XPAR_TX_FRAME_BRAM_CTRL_DEVICE_ID +#define XPAR_BRAM_6_DATA_WIDTH 32U +#define XPAR_BRAM_6_ECC 0U +#define XPAR_BRAM_6_FAULT_INJECT 0U +#define XPAR_BRAM_6_CE_FAILING_REGISTERS 0U +#define XPAR_BRAM_6_UE_FAILING_REGISTERS 0U +#define XPAR_BRAM_6_ECC_STATUS_REGISTERS 0U +#define XPAR_BRAM_6_CE_COUNTER_WIDTH 0U +#define XPAR_BRAM_6_ECC_ONOFF_REGISTER 0U +#define XPAR_BRAM_6_ECC_ONOFF_RESET_VALUE 0U +#define XPAR_BRAM_6_WRITE_ACCESS 0U +#define XPAR_BRAM_6_BASEADDR 0xC2000000U +#define XPAR_BRAM_6_HIGHADDR 0xC2000FFFU +#define XPAR_BRAM_6_CTRL_BASEADDR 0xFFFFFFFFU +#define XPAR_BRAM_6_CTRL_HIGHADDR 0xFFFFFFFEU + + +/******************************************************************/ + + +/* Definitions for peripheral AXI_SPI_ENGINE_AXI_SPI_ENGINE */ +#define XPAR_AXI_SPI_ENGINE_AXI_SPI_ENGINE_BASEADDR 0x44A00000 +#define XPAR_AXI_SPI_ENGINE_AXI_SPI_ENGINE_HIGHADDR 0x44A0FFFF + + +/******************************************************************/ + +/* Definitions for driver GPIO */ +#define XPAR_XGPIO_NUM_INSTANCES 3 + +/* Definitions for peripheral AXI_GPIO */ +#define XPAR_AXI_GPIO_BASEADDR 0x40000000 +#define XPAR_AXI_GPIO_HIGHADDR 0x4000FFFF +#define XPAR_AXI_GPIO_DEVICE_ID 0 +#define XPAR_AXI_GPIO_INTERRUPT_PRESENT 0 +#define XPAR_AXI_GPIO_IS_DUAL 1 + + +/* Definitions for peripheral STATUS_GPIO_I */ +#define XPAR_STATUS_GPIO_I_BASEADDR 0x40010000 +#define XPAR_STATUS_GPIO_I_HIGHADDR 0x4001FFFF +#define XPAR_STATUS_GPIO_I_DEVICE_ID 1 +#define XPAR_STATUS_GPIO_I_INTERRUPT_PRESENT 0 +#define XPAR_STATUS_GPIO_I_IS_DUAL 1 + + +/* Definitions for peripheral STATUS_GPIO_O */ +#define XPAR_STATUS_GPIO_O_BASEADDR 0x40020000 +#define XPAR_STATUS_GPIO_O_HIGHADDR 0x4002FFFF +#define XPAR_STATUS_GPIO_O_DEVICE_ID 2 +#define XPAR_STATUS_GPIO_O_INTERRUPT_PRESENT 0 +#define XPAR_STATUS_GPIO_O_IS_DUAL 1 + + +/******************************************************************/ + +/* Canonical definitions for peripheral AXI_GPIO */ +#define XPAR_GPIO_0_BASEADDR 0x40000000 +#define XPAR_GPIO_0_HIGHADDR 0x4000FFFF +#define XPAR_GPIO_0_DEVICE_ID XPAR_AXI_GPIO_DEVICE_ID +#define XPAR_GPIO_0_INTERRUPT_PRESENT 0 +#define XPAR_GPIO_0_IS_DUAL 1 + +/* Canonical definitions for peripheral STATUS_GPIO_I */ +#define XPAR_GPIO_1_BASEADDR 0x40010000 +#define XPAR_GPIO_1_HIGHADDR 0x4001FFFF +#define XPAR_GPIO_1_DEVICE_ID XPAR_STATUS_GPIO_I_DEVICE_ID +#define XPAR_GPIO_1_INTERRUPT_PRESENT 0 +#define XPAR_GPIO_1_IS_DUAL 1 + +/* Canonical definitions for peripheral STATUS_GPIO_O */ +#define XPAR_GPIO_2_BASEADDR 0x40020000 +#define XPAR_GPIO_2_HIGHADDR 0x4002FFFF +#define XPAR_GPIO_2_DEVICE_ID XPAR_STATUS_GPIO_O_DEVICE_ID +#define XPAR_GPIO_2_INTERRUPT_PRESENT 0 +#define XPAR_GPIO_2_IS_DUAL 1 + + +/******************************************************************/ + +#define XPAR_INTC_MAX_NUM_INTR_INPUTS 6 +#define XPAR_XINTC_HAS_IPR 1 +#define XPAR_XINTC_HAS_SIE 1 +#define XPAR_XINTC_HAS_CIE 1 +#define XPAR_XINTC_HAS_IVR 1 +/* Definitions for driver INTC */ +#define XPAR_XINTC_NUM_INSTANCES 1 + +/* Definitions for peripheral AXI_INTC */ +#define XPAR_AXI_INTC_DEVICE_ID 0 +#define XPAR_AXI_INTC_BASEADDR 0x41200000 +#define XPAR_AXI_INTC_HIGHADDR 0x4120FFFF +#define XPAR_AXI_INTC_KIND_OF_INTR 0xFFFFFFC0 +#define XPAR_AXI_INTC_HAS_FAST 0 +#define XPAR_AXI_INTC_IVAR_RESET_VALUE 0x0000000000000010 +#define XPAR_AXI_INTC_NUM_INTR_INPUTS 6 +#define XPAR_AXI_INTC_ADDR_WIDTH 32 + + +/******************************************************************/ + +#define XPAR_INTC_SINGLE_BASEADDR 0x41200000 +#define XPAR_INTC_SINGLE_HIGHADDR 0x4120FFFF +#define XPAR_INTC_SINGLE_DEVICE_ID XPAR_AXI_INTC_DEVICE_ID +#define XPAR_AXI_INTC_TYPE 0U +#define XPAR_SYSTEM_PHY_IRQ_MASK 0X000001U +#define XPAR_AXI_INTC_SYSTEM_PHY_IRQ_INTR 0U +#define XPAR_AXI_DMA_C2C_MM2S_INTROUT_MASK 0X000002U +#define XPAR_AXI_INTC_AXI_DMA_C2C_MM2S_INTROUT_INTR 1U +#define XPAR_AXI_DMA_C2C_S2MM_INTROUT_MASK 0X000004U +#define XPAR_AXI_INTC_AXI_DMA_C2C_S2MM_INTROUT_INTR 2U +#define XPAR_SYSTEM_PHY_5MS_MASK 0X000008U +#define XPAR_AXI_INTC_SYSTEM_PHY_5MS_INTR 3U +#define XPAR_AXI_TIMER_0_INTERRUPT_MASK 0X000010U +#define XPAR_AXI_INTC_AXI_TIMER_0_INTERRUPT_INTR 4U +#define XPAR_XADC_WIZ_0_IP2INTC_IRPT_MASK 0X000020U +#define XPAR_AXI_INTC_XADC_WIZ_0_IP2INTC_IRPT_INTR 5U + +/******************************************************************/ + +/* Canonical definitions for peripheral AXI_INTC */ +#define XPAR_INTC_0_DEVICE_ID XPAR_AXI_INTC_DEVICE_ID +#define XPAR_INTC_0_BASEADDR 0x41200000U +#define XPAR_INTC_0_HIGHADDR 0x4120FFFFU +#define XPAR_INTC_0_KIND_OF_INTR 0xFFFFFFC0U +#define XPAR_INTC_0_HAS_FAST 0U +#define XPAR_INTC_0_IVAR_RESET_VALUE 0x0000000000000010U +#define XPAR_INTC_0_NUM_INTR_INPUTS 6U +#define XPAR_INTC_0_ADDR_WIDTH 32U +#define XPAR_INTC_0_INTC_TYPE 0U + +#define XPAR_INTC_0_AXIDMA_0_MM2S_INTROUT_VEC_ID XPAR_AXI_INTC_AXI_DMA_C2C_MM2S_INTROUT_INTR +#define XPAR_INTC_0_AXIDMA_0_S2MM_INTROUT_VEC_ID XPAR_AXI_INTC_AXI_DMA_C2C_S2MM_INTROUT_INTR +#define XPAR_INTC_0_TMRCTR_0_VEC_ID XPAR_AXI_INTC_AXI_TIMER_0_INTERRUPT_INTR +#define XPAR_INTC_0_SYSMON_0_VEC_ID XPAR_AXI_INTC_XADC_WIZ_0_IP2INTC_IRPT_INTR + +/******************************************************************/ + +/* Definitions for driver SYSMON */ +#define XPAR_XSYSMON_NUM_INSTANCES 1U + +/* Definitions for peripheral XADC_WIZ_0 */ +#define XPAR_XADC_WIZ_0_IP_TYPE 0U +#define XPAR_XADC_WIZ_0_DEVICE_ID 0U +#define XPAR_XADC_WIZ_0_BASEADDR 0x44A20000U +#define XPAR_XADC_WIZ_0_HIGHADDR 0x44A2FFFFU +#define XPAR_XADC_WIZ_0_INCLUDE_INTR 1U + + +/******************************************************************/ + +/* Canonical definitions for peripheral XADC_WIZ_0 */ +#define XPAR_SYSMON_0_IP_TYPE 0U +#define XPAR_SYSMON_0_DEVICE_ID XPAR_XADC_WIZ_0_DEVICE_ID +#define XPAR_SYSMON_0_BASEADDR 0x44A20000U +#define XPAR_SYSMON_0_HIGHADDR 0x44A2FFFFU +#define XPAR_SYSMON_0_INCLUDE_INTR 1U + + +/******************************************************************/ + +/* Definitions for driver TMRCTR */ +#define XPAR_XTMRCTR_NUM_INSTANCES 1U + +/* Definitions for peripheral AXI_TIMER_0 */ +#define XPAR_AXI_TIMER_0_DEVICE_ID 0U +#define XPAR_AXI_TIMER_0_BASEADDR 0x41C00000U +#define XPAR_AXI_TIMER_0_HIGHADDR 0x41C0FFFFU +#define XPAR_AXI_TIMER_0_CLOCK_FREQ_HZ 150000000U + + +/******************************************************************/ + +/* Canonical definitions for peripheral AXI_TIMER_0 */ +#define XPAR_TMRCTR_0_DEVICE_ID 0U +#define XPAR_TMRCTR_0_BASEADDR 0x41C00000U +#define XPAR_TMRCTR_0_HIGHADDR 0x41C0FFFFU +#define XPAR_TMRCTR_0_CLOCK_FREQ_HZ XPAR_AXI_TIMER_0_CLOCK_FREQ_HZ + +/******************************************************************/ + +#endif /* end of protection macro */ diff --git a/datalink814_sp/bsp/microblaze_ps/include/xplatform_info.h b/datalink814_sp/bsp/microblaze_ps/include/xplatform_info.h new file mode 100644 index 0000000..88851bb --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/include/xplatform_info.h @@ -0,0 +1,120 @@ +/****************************************************************************** +* +* Copyright (C) 2014 - 2017 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xplatform_info.h +* +* @addtogroup common_platform_info APIs to Get Platform Information +* +* The xplatform_info.h file contains definitions for various available Xilinx® +* platforms. Also, it contains prototype of APIs, which can be used to get the +* platform information. +* +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date    Changes
+* ----- ---- --------- -------------------------------------------------------
+* 6.4    ms   05/23/17 Added PSU_PMU macro to support XGetPSVersion_Info
+*                      function for PMUFW.
+* 
+* +******************************************************************************/ + +#ifndef XPLATFORM_INFO_H /* prevent circular inclusions */ +#define XPLATFORM_INFO_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" + +/************************** Constant Definitions *****************************/ +#if defined (versal) +#define XPAR_PMC_TAP_BASEADDR 0xF11A0000U +#define XPAR_PMC_TAP_VERSION_OFFSET 0x00000004U +#define XPLAT_PS_VERSION_ADDRESS (XPAR_PMC_TAP_BASEADDR + \ + XPAR_PMC_TAP_VERSION_OFFSET) +#else +#define XPAR_CSU_BASEADDR 0xFFCA0000U +#define XPAR_CSU_VER_OFFSET 0x00000044U +#define XPLAT_PS_VERSION_ADDRESS (XPAR_CSU_BASEADDR + \ + XPAR_CSU_VER_OFFSET) +#endif +#define XPLAT_ZYNQ_ULTRA_MP_SILICON 0x0 +#define XPLAT_ZYNQ_ULTRA_MP 0x1 +#define XPLAT_ZYNQ_ULTRA_MPVEL 0x2 +#define XPLAT_ZYNQ_ULTRA_MPQEMU 0x3 +#define XPLAT_ZYNQ 0x4 +#define XPLAT_MICROBLAZE 0x5 +#define XPLAT_versal 0x6U + +#define XPS_VERSION_1 0x0 +#define XPS_VERSION_2 0x1 +#define XPLAT_INFO_MASK (0xF) + +#if defined (versal) +#define XPS_VERSION_INFO_MASK 0xFF00U +#define XPS_VERSION_INFO_SHIFT 0x8U +#define XPLAT_INFO_SHIFT 0x18U +#else +#define XPS_VERSION_INFO_MASK (0xF) +#define XPS_VERSION_INFO_SHIFT 0x0U +#define XPLAT_INFO_SHIFT 0xCU +#endif + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + + +u32 XGetPlatform_Info(void); + +#if defined (ARMR5) || (__aarch64__) || (ARMA53_32) || (PSU_PMU) +u32 XGetPSVersion_Info(); +#endif + +#if defined (ARMR5) || (__aarch64__) || (ARMA53_32) +u32 XGet_Zynq_UltraMp_Platform_info(); +#endif +/************************** Function Prototypes ******************************/ + + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** +* @} End of "addtogroup common_platform_info". +*/ diff --git a/datalink814_sp/bsp/microblaze_ps/include/xstatus.h b/datalink814_sp/bsp/microblaze_ps/include/xstatus.h new file mode 100644 index 0000000..1a212bf --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/include/xstatus.h @@ -0,0 +1,533 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xstatus.h +* +* @addtogroup common_status_codes Xilinx® software status codes +* +* The xstatus.h file contains the Xilinx® software status codes.These codes are +* used throughout the Xilinx device drivers. +* +* @{ +******************************************************************************/ + +#ifndef XSTATUS_H /* prevent circular inclusions */ +#define XSTATUS_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" + +/************************** Constant Definitions *****************************/ + +/*********************** Common statuses 0 - 500 *****************************/ +/** +@name Common Status Codes for All Device Drivers +@{ +*/ +#define XST_SUCCESS 0L +#define XST_FAILURE 1L +#define XST_DEVICE_NOT_FOUND 2L +#define XST_DEVICE_BLOCK_NOT_FOUND 3L +#define XST_INVALID_VERSION 4L +#define XST_DEVICE_IS_STARTED 5L +#define XST_DEVICE_IS_STOPPED 6L +#define XST_FIFO_ERROR 7L /*!< An error occurred during an + operation with a FIFO such as + an underrun or overrun, this + error requires the device to + be reset */ +#define XST_RESET_ERROR 8L /*!< An error occurred which requires + the device to be reset */ +#define XST_DMA_ERROR 9L /*!< A DMA error occurred, this error + typically requires the device + using the DMA to be reset */ +#define XST_NOT_POLLED 10L /*!< The device is not configured for + polled mode operation */ +#define XST_FIFO_NO_ROOM 11L /*!< A FIFO did not have room to put + the specified data into */ +#define XST_BUFFER_TOO_SMALL 12L /*!< The buffer is not large enough + to hold the expected data */ +#define XST_NO_DATA 13L /*!< There was no data available */ +#define XST_REGISTER_ERROR 14L /*!< A register did not contain the + expected value */ +#define XST_INVALID_PARAM 15L /*!< An invalid parameter was passed + into the function */ +#define XST_NOT_SGDMA 16L /*!< The device is not configured for + scatter-gather DMA operation */ +#define XST_LOOPBACK_ERROR 17L /*!< A loopback test failed */ +#define XST_NO_CALLBACK 18L /*!< A callback has not yet been + registered */ +#define XST_NO_FEATURE 19L /*!< Device is not configured with + the requested feature */ +#define XST_NOT_INTERRUPT 20L /*!< Device is not configured for + interrupt mode operation */ +#define XST_DEVICE_BUSY 21L /*!< Device is busy */ +#define XST_ERROR_COUNT_MAX 22L /*!< The error counters of a device + have maxed out */ +#define XST_IS_STARTED 23L /*!< Used when part of device is + already started i.e. + sub channel */ +#define XST_IS_STOPPED 24L /*!< Used when part of device is + already stopped i.e. + sub channel */ +#define XST_DATA_LOST 26L /*!< Driver defined error */ +#define XST_RECV_ERROR 27L /*!< Generic receive error */ +#define XST_SEND_ERROR 28L /*!< Generic transmit error */ +#define XST_NOT_ENABLED 29L /*!< A requested service is not + available because it has not + been enabled */ +#define XST_NO_ACCESS 30L /* Generic access error */ +/** @} */ +/***************** Utility Component statuses 401 - 500 *********************/ +/** +@name Utility Component Status Codes 401 - 500 +@{ +*/ +#define XST_MEMTEST_FAILED 401L /*!< Memory test failed */ + +/** @} */ +/***************** Common Components statuses 501 - 1000 *********************/ +/** +@name Packet Fifo Status Codes 501 - 510 +@{ +*/ +/********************* Packet Fifo statuses 501 - 510 ************************/ + +#define XST_PFIFO_LACK_OF_DATA 501L /*!< Not enough data in FIFO */ +#define XST_PFIFO_NO_ROOM 502L /*!< Not enough room in FIFO */ +#define XST_PFIFO_BAD_REG_VALUE 503L /*!< Self test, a register value + was invalid after reset */ +#define XST_PFIFO_ERROR 504L /*!< Generic packet FIFO error */ +#define XST_PFIFO_DEADLOCK 505L /*!< Packet FIFO is reporting + * empty and full simultaneously + */ +/** @} */ +/** +@name DMA Status Codes 511 - 530 +@{ +*/ +/************************** DMA statuses 511 - 530 ***************************/ + +#define XST_DMA_TRANSFER_ERROR 511L /*!< Self test, DMA transfer + failed */ +#define XST_DMA_RESET_REGISTER_ERROR 512L /*!< Self test, a register value + was invalid after reset */ +#define XST_DMA_SG_LIST_EMPTY 513L /*!< Scatter gather list contains + no buffer descriptors ready + to be processed */ +#define XST_DMA_SG_IS_STARTED 514L /*!< Scatter gather not stopped */ +#define XST_DMA_SG_IS_STOPPED 515L /*!< Scatter gather not running */ +#define XST_DMA_SG_LIST_FULL 517L /*!< All the buffer desciptors of + the scatter gather list are + being used */ +#define XST_DMA_SG_BD_LOCKED 518L /*!< The scatter gather buffer + descriptor which is to be + copied over in the scatter + list is locked */ +#define XST_DMA_SG_NOTHING_TO_COMMIT 519L /*!< No buffer descriptors have been + put into the scatter gather + list to be commited */ +#define XST_DMA_SG_COUNT_EXCEEDED 521L /*!< The packet count threshold + specified was larger than the + total # of buffer descriptors + in the scatter gather list */ +#define XST_DMA_SG_LIST_EXISTS 522L /*!< The scatter gather list has + already been created */ +#define XST_DMA_SG_NO_LIST 523L /*!< No scatter gather list has + been created */ +#define XST_DMA_SG_BD_NOT_COMMITTED 524L /*!< The buffer descriptor which was + being started was not committed + to the list */ +#define XST_DMA_SG_NO_DATA 525L /*!< The buffer descriptor to start + has already been used by the + hardware so it can't be reused + */ +#define XST_DMA_SG_LIST_ERROR 526L /*!< General purpose list access + error */ +#define XST_DMA_BD_ERROR 527L /*!< General buffer descriptor + error */ +/** @} */ +/** +@name IPIF Status Codes Codes 531 - 550 +@{ +*/ +/************************** IPIF statuses 531 - 550 ***************************/ + +#define XST_IPIF_REG_WIDTH_ERROR 531L /*!< An invalid register width + was passed into the function */ +#define XST_IPIF_RESET_REGISTER_ERROR 532L /*!< The value of a register at + reset was not valid */ +#define XST_IPIF_DEVICE_STATUS_ERROR 533L /*!< A write to the device interrupt + status register did not read + back correctly */ +#define XST_IPIF_DEVICE_ACK_ERROR 534L /*!< The device interrupt status + register did not reset when + acked */ +#define XST_IPIF_DEVICE_ENABLE_ERROR 535L /*!< The device interrupt enable + register was not updated when + other registers changed */ +#define XST_IPIF_IP_STATUS_ERROR 536L /*!< A write to the IP interrupt + status register did not read + back correctly */ +#define XST_IPIF_IP_ACK_ERROR 537L /*!< The IP interrupt status register + did not reset when acked */ +#define XST_IPIF_IP_ENABLE_ERROR 538L /*!< IP interrupt enable register was + not updated correctly when other + registers changed */ +#define XST_IPIF_DEVICE_PENDING_ERROR 539L /*!< The device interrupt pending + register did not indicate the + expected value */ +#define XST_IPIF_DEVICE_ID_ERROR 540L /*!< The device interrupt ID register + did not indicate the expected + value */ +#define XST_IPIF_ERROR 541L /*!< Generic ipif error */ +/** @} */ + +/****************** Device specific statuses 1001 - 4095 *********************/ +/** +@name Ethernet Status Codes 1001 - 1050 +@{ +*/ +/********************* Ethernet statuses 1001 - 1050 *************************/ + +#define XST_EMAC_MEMORY_SIZE_ERROR 1001L /*!< Memory space is not big enough + * to hold the minimum number of + * buffers or descriptors */ +#define XST_EMAC_MEMORY_ALLOC_ERROR 1002L /*!< Memory allocation failed */ +#define XST_EMAC_MII_READ_ERROR 1003L /*!< MII read error */ +#define XST_EMAC_MII_BUSY 1004L /*!< An MII operation is in progress */ +#define XST_EMAC_OUT_OF_BUFFERS 1005L /*!< Driver is out of buffers */ +#define XST_EMAC_PARSE_ERROR 1006L /*!< Invalid driver init string */ +#define XST_EMAC_COLLISION_ERROR 1007L /*!< Excess deferral or late + * collision on polled send */ +/** @} */ +/** +@name UART Status Codes 1051 - 1075 +@{ +*/ +/*********************** UART statuses 1051 - 1075 ***************************/ +#define XST_UART + +#define XST_UART_INIT_ERROR 1051L +#define XST_UART_START_ERROR 1052L +#define XST_UART_CONFIG_ERROR 1053L +#define XST_UART_TEST_FAIL 1054L +#define XST_UART_BAUD_ERROR 1055L +#define XST_UART_BAUD_RANGE 1056L + +/** @} */ +/** +@name IIC Status Codes 1076 - 1100 +@{ +*/ +/************************ IIC statuses 1076 - 1100 ***************************/ + +#define XST_IIC_SELFTEST_FAILED 1076 /*!< self test failed */ +#define XST_IIC_BUS_BUSY 1077 /*!< bus found busy */ +#define XST_IIC_GENERAL_CALL_ADDRESS 1078 /*!< mastersend attempted with */ + /* general call address */ +#define XST_IIC_STAND_REG_RESET_ERROR 1079 /*!< A non parameterizable reg */ + /* value after reset not valid */ +#define XST_IIC_TX_FIFO_REG_RESET_ERROR 1080 /*!< Tx fifo included in design */ + /* value after reset not valid */ +#define XST_IIC_RX_FIFO_REG_RESET_ERROR 1081 /*!< Rx fifo included in design */ + /* value after reset not valid */ +#define XST_IIC_TBA_REG_RESET_ERROR 1082 /*!< 10 bit addr incl in design */ + /* value after reset not valid */ +#define XST_IIC_CR_READBACK_ERROR 1083 /*!< Read of the control register */ + /* didn't return value written */ +#define XST_IIC_DTR_READBACK_ERROR 1084 /*!< Read of the data Tx reg */ + /* didn't return value written */ +#define XST_IIC_DRR_READBACK_ERROR 1085 /*!< Read of the data Receive reg */ + /* didn't return value written */ +#define XST_IIC_ADR_READBACK_ERROR 1086 /*!< Read of the data Tx reg */ + /* didn't return value written */ +#define XST_IIC_TBA_READBACK_ERROR 1087 /*!< Read of the 10 bit addr reg */ + /* didn't return written value */ +#define XST_IIC_NOT_SLAVE 1088 /*!< The device isn't a slave */ +#define XST_IIC_ARB_LOST 1089 /*!< Arbitration lost for master */ +/** @} */ +/** +@name ATMC Status Codes 1101 - 1125 +@{ +*/ +/*********************** ATMC statuses 1101 - 1125 ***************************/ + +#define XST_ATMC_ERROR_COUNT_MAX 1101L /*!< the error counters in the ATM + controller hit the max value + which requires the statistics + to be cleared */ +/** @} */ +/** +@name Flash Status Codes 1126 - 1150 +@{ +*/ +/*********************** Flash statuses 1126 - 1150 **************************/ + +#define XST_FLASH_BUSY 1126L /*!< Flash is erasing or programming + */ +#define XST_FLASH_READY 1127L /*!< Flash is ready for commands */ +#define XST_FLASH_ERROR 1128L /*!< Flash had detected an internal + error. Use XFlash_DeviceControl + to retrieve device specific codes + */ +#define XST_FLASH_ERASE_SUSPENDED 1129L /*!< Flash is in suspended erase state + */ +#define XST_FLASH_WRITE_SUSPENDED 1130L /*!< Flash is in suspended write state + */ +#define XST_FLASH_PART_NOT_SUPPORTED 1131L /*!< Flash type not supported by + driver */ +#define XST_FLASH_NOT_SUPPORTED 1132L /*!< Operation not supported */ +#define XST_FLASH_TOO_MANY_REGIONS 1133L /*!< Too many erase regions */ +#define XST_FLASH_TIMEOUT_ERROR 1134L /*!< Programming or erase operation + aborted due to a timeout */ +#define XST_FLASH_ADDRESS_ERROR 1135L /*!< Accessed flash outside its + addressible range */ +#define XST_FLASH_ALIGNMENT_ERROR 1136L /*!< Write alignment error */ +#define XST_FLASH_BLOCKING_CALL_ERROR 1137L /*!< Couldn't return immediately from + write/erase function with + XFL_NON_BLOCKING_WRITE/ERASE + option cleared */ +#define XST_FLASH_CFI_QUERY_ERROR 1138L /*!< Failed to query the device */ +/** @} */ +/** +@name SPI Status Codes 1151 - 1175 +@{ +*/ +/*********************** SPI statuses 1151 - 1175 ****************************/ + +#define XST_SPI_MODE_FAULT 1151 /*!< master was selected as slave */ +#define XST_SPI_TRANSFER_DONE 1152 /*!< data transfer is complete */ +#define XST_SPI_TRANSMIT_UNDERRUN 1153 /*!< slave underruns transmit register */ +#define XST_SPI_RECEIVE_OVERRUN 1154 /*!< device overruns receive register */ +#define XST_SPI_NO_SLAVE 1155 /*!< no slave has been selected yet */ +#define XST_SPI_TOO_MANY_SLAVES 1156 /*!< more than one slave is being + * selected */ +#define XST_SPI_NOT_MASTER 1157 /*!< operation is valid only as master */ +#define XST_SPI_SLAVE_ONLY 1158 /*!< device is configured as slave-only + */ +#define XST_SPI_SLAVE_MODE_FAULT 1159 /*!< slave was selected while disabled */ +#define XST_SPI_SLAVE_MODE 1160 /*!< device has been addressed as slave */ +#define XST_SPI_RECEIVE_NOT_EMPTY 1161 /*!< device received data in slave mode */ + +#define XST_SPI_COMMAND_ERROR 1162 /*!< unrecognised command - qspi only */ +#define XST_SPI_POLL_DONE 1163 /*!< controller completed polling the + device for status */ +/** @} */ +/** +@name OPB Arbiter Status Codes 1176 - 1200 +@{ +*/ +/********************** OPB Arbiter statuses 1176 - 1200 *********************/ + +#define XST_OPBARB_INVALID_PRIORITY 1176 /*!< the priority registers have either + * one master assigned to two or more + * priorities, or one master not + * assigned to any priority + */ +#define XST_OPBARB_NOT_SUSPENDED 1177 /*!< an attempt was made to modify the + * priority levels without first + * suspending the use of priority + * levels + */ +#define XST_OPBARB_PARK_NOT_ENABLED 1178 /*!< bus parking by id was enabled but + * bus parking was not enabled + */ +#define XST_OPBARB_NOT_FIXED_PRIORITY 1179 /*!< the arbiter must be in fixed + * priority mode to allow the + * priorities to be changed + */ +/** @} */ +/** +@name INTC Status Codes 1201 - 1225 +@{ +*/ +/************************ Intc statuses 1201 - 1225 **************************/ + +#define XST_INTC_FAIL_SELFTEST 1201 /*!< self test failed */ +#define XST_INTC_CONNECT_ERROR 1202 /*!< interrupt already in use */ +/** @} */ +/** +@name TmrCtr Status Codes 1226 - 1250 +@{ +*/ +/********************** TmrCtr statuses 1226 - 1250 **************************/ + +#define XST_TMRCTR_TIMER_FAILED 1226 /*!< self test failed */ +/** @} */ +/** +@name WdtTb Status Codes 1251 - 1275 +@{ +*/ +/********************** WdtTb statuses 1251 - 1275 ***************************/ + +#define XST_WDTTB_TIMER_FAILED 1251L +/** @} */ +/** +@name PlbArb status Codes 1276 - 1300 +@{ +*/ +/********************** PlbArb statuses 1276 - 1300 **************************/ + +#define XST_PLBARB_FAIL_SELFTEST 1276L +/** @} */ +/** +@name Plb2Opb Status Codes 1301 - 1325 +@{ +*/ +/********************** Plb2Opb statuses 1301 - 1325 *************************/ + +#define XST_PLB2OPB_FAIL_SELFTEST 1301L +/** @} */ +/** +@name Opb2Plb Status 1326 - 1350 +@{ +*/ +/********************** Opb2Plb statuses 1326 - 1350 *************************/ + +#define XST_OPB2PLB_FAIL_SELFTEST 1326L +/** @} */ +/** +@name SysAce Status Codes 1351 - 1360 +@{ +*/ +/********************** SysAce statuses 1351 - 1360 **************************/ + +#define XST_SYSACE_NO_LOCK 1351L /*!< No MPU lock has been granted */ +/** @} */ +/** +@name PCI Bridge Status Codes 1361 - 1375 +@{ +*/ +/********************** PCI Bridge statuses 1361 - 1375 **********************/ + +#define XST_PCI_INVALID_ADDRESS 1361L +/** @} */ +/** +@name FlexRay Constants 1400 - 1409 +@{ +*/ +/********************** FlexRay constants 1400 - 1409 *************************/ + +#define XST_FR_TX_ERROR 1400 +#define XST_FR_TX_BUSY 1401 +#define XST_FR_BUF_LOCKED 1402 +#define XST_FR_NO_BUF 1403 +/** @} */ +/** +@name USB constants 1410 - 1420 +@{ +*/ +/****************** USB constants 1410 - 1420 *******************************/ + +#define XST_USB_ALREADY_CONFIGURED 1410 +#define XST_USB_BUF_ALIGN_ERROR 1411 +#define XST_USB_NO_DESC_AVAILABLE 1412 +#define XST_USB_BUF_TOO_BIG 1413 +#define XST_USB_NO_BUF 1414 +/** @} */ +/** +@name HWICAP constants 1421 - 1429 +@{ +*/ +/****************** HWICAP constants 1421 - 1429 *****************************/ + +#define XST_HWICAP_WRITE_DONE 1421 + +/** @} */ +/** +@name AXI VDMA constants 1430 - 1440 +@{ +*/ +/****************** AXI VDMA constants 1430 - 1440 *****************************/ + +#define XST_VDMA_MISMATCH_ERROR 1430 +/** @} */ +/** +@name NAND Flash Status Codes 1441 - 1459 +@{ +*/ +/*********************** NAND Flash statuses 1441 - 1459 *********************/ + +#define XST_NAND_BUSY 1441L /*!< Flash is erasing or + * programming + */ +#define XST_NAND_READY 1442L /*!< Flash is ready for commands + */ +#define XST_NAND_ERROR 1443L /*!< Flash had detected an + * internal error. + */ +#define XST_NAND_PART_NOT_SUPPORTED 1444L /*!< Flash type not supported by + * driver + */ +#define XST_NAND_OPT_NOT_SUPPORTED 1445L /*!< Operation not supported + */ +#define XST_NAND_TIMEOUT_ERROR 1446L /*!< Programming or erase + * operation aborted due to a + * timeout + */ +#define XST_NAND_ADDRESS_ERROR 1447L /*!< Accessed flash outside its + * addressible range + */ +#define XST_NAND_ALIGNMENT_ERROR 1448L /*!< Write alignment error + */ +#define XST_NAND_PARAM_PAGE_ERROR 1449L /*!< Failed to read parameter + * page of the device + */ +#define XST_NAND_CACHE_ERROR 1450L /*!< Flash page buffer error + */ + +#define XST_NAND_WRITE_PROTECTED 1451L /*!< Flash is write protected + */ +/** @} */ + +/**************************** Type Definitions *******************************/ + +typedef s32 XStatus; + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** +* @} End of "addtogroup common_status_codes". +*/ diff --git a/datalink814_sp/bsp/microblaze_ps/include/xsysmon.h b/datalink814_sp/bsp/microblaze_ps/include/xsysmon.h new file mode 100644 index 0000000..c01dddc --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/include/xsysmon.h @@ -0,0 +1,654 @@ +/****************************************************************************** +* +* Copyright (C) 2007 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xsysmon.h +* @addtogroup sysmon_v7_5 +* @{ +* @details +* +* The XSysMon driver supports the Xilinx System Monitor/ADC device. +* +* The System Monitor/ADC device has the following features: +* - 10-bit, 200-KSPS (kilo samples per second) +* Analog-to-Digital Converter (ADC) +* - Monitoring of on-chip supply voltages and temperature +* - 1 dedicated differential analog-input pair and +* 16 auxiliary differential analog-input pairs +* - Automatic alarms based on user defined limits for the on-chip +* supply voltages and temperature +* - Automatic Channel Sequencer, programmable averaging, programmable +* acquisition time for the external inputs, unipolar or differential +* input selection for the external inputs +* - Inbuilt Calibration +* - Optional interrupt request generation +* - External Mux (7 Series and Zynq XADC) +* +* +* The user should refer to the hardware device specification for detailed +* information about the device. +* +* This header file contains the prototypes of driver functions that can +* be used to access the System Monitor/ADC device. +* +* +* System Monitor Channel Sequencer Modes +* +* The System Monitor Channel Sequencer supports the following operating modes: +* +* - Default : This is the default mode after power up. +* In this mode of operation the System Monitor operates in +* a sequence mode, monitoring the on chip sensors: +* Temperature, VCCINT, and VCCAUX. +* - One pass through sequence : In this mode the System Monitor +* converts the channels enabled in the Sequencer Channel Enable +* registers for a single pass and then stops. +* - Continuous cycling of sequence : In this mode the System Monitor +* converts the channels enabled in the Sequencer Channel Enable +* registers continuously. +* - Single channel mode: In this mode the System Monitor Channel +* Sequencer is disabled and the System Monitor operates in a +* Single Channel Mode. +* The System Monitor can operate either in a Continuous or Event +* driven sampling mode in the single channel mode. +* - Simultaneous sampling mode: This mode is available only in +* 7 Series and Zynq XADC devices. In this mode both ADCs sample and +* digitizes two different analog input signals at the same time. +* - Independent ADC mode: This mode is available only in 7 Series and +* Zynq XADC devices. In this mode ADC A is used to implement a +* fixed monitoring mode which is similar to default mode, but the +* fixed alarm functions are enabled. ADC B is available to be used +* with the external analog input channels only. +* +* Initialization and Configuration +* +* The device driver enables higher layer software (e.g., an application) to +* communicate to the System Monitor/ADC device. +* +* XSysMon_CfgInitialize() API is used to initialize the System Monitor/ADC +* device. The user needs to first call the XSysMon_LookupConfig() API which +* returns the Configuration structure pointer which is passed as a parameter to +* the XSysMon_CfgInitialize() API. +* +* +* Interrupts +* +* The System Monitor/ADC device supports interrupt driven mode and the default +* operation mode is polling mode. +* +* The interrupt mode is available only if hardware is configured to support +* interrupts. +* +* This driver does not provide a Interrupt Service Routine (ISR) for the device. +* It is the responsibility of the application to provide one if needed. Refer to +* the interrupt example provided with this driver for details on using the +* device in interrupt mode. +* +* +* Virtual Memory +* +* This driver supports Virtual Memory. The RTOS is responsible for calculating +* the correct device base address in Virtual Memory space. +* +* +* Threads +* +* This driver is not thread safe. Any needs for threads or thread mutual +* exclusion must be satisfied by the layer above this driver. +* +* +* Asserts +* +* Asserts are used within all Xilinx drivers to enforce constraints on argument +* values. Asserts can be turned off on a system-wide basis by defining, at +* compile time, the NDEBUG identifier. By default, asserts are turned on and it +* is recommended that users leave asserts on during development. +* +* +* Building the driver +* +* The XSysMon driver is composed of several source files. This allows the user +* to build and link only those parts of the driver that are necessary. +* +* Limitations of the driver +* +* System Monitor/ADC device can be accessed through the JTAG port and the AXI +* interface. The driver implementation does not support the simultaneous access +* of the device by both these interfaces. The user has to care of this situation +* in the user application code. +* +* +* +*

+* +*
+*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- -----  -------- -----------------------------------------------------
+* 1.00a xd/sv  05/22/07 First release
+* 2.00a sv     07/07/08 Added bit definitions for new Alarm Interrupts in the
+*			Interrupt Registers. Changed the ADC data functions
+*			to return 16 bits of data. Added macros for conversion
+*			from Raw Data to Temperature/Voltage and vice-versa.
+* 3.00a sdm    02/09/09 Added APIs and bit definitions for V6 SysMon.
+* 4.00a ktn    10/22/09 Updated the driver to use the HAL Processor APIs/macros.
+*		        The macros have been renamed to remove _m from the name
+*		        in all the driver files.
+* 5.00a sdm    06/15/11 Added support for XADC 7 Series.
+* 5.01a bss    02/28/12 Added support for Zynq,
+*			renamed XSM_ATR_BRAM_UPPER to XSM_ATR_VBRAM_UPPER
+*			renamed XSM_ATR_BRAM_LOWER to XSM_ATR_VBRAM_LOWER
+* 5.02a bss    11/23/12 Added APIs and Macros to support Temperature Updation
+*			over TEMP_OUT port(CR #679872)
+* 5.03a bss    04/25/13 Modified XSysMon_SetSeqChEnables,
+*			XSysMon_SetSeqAvgEnables, XSysMon_SetSeqInputMode
+*			and XSysMon_SetSeqAcqTime APIs to check for Safe Mode
+*			instead of Single Channel mode(CR #703729) in xsysmon.c
+*			Modified examples: xsysmon_polled_example.c,
+*			xsysmon_low_level_example.c,
+*			xsysmon_intr_printf_example.c, xsysmon_intr_example.c
+*			xsysmon_extmux_example.c and
+*			xsysmon_polled_printf_example.c to set Sequencer Mode
+*			as Safe mode instead of Single channel mode before
+*			configuring Sequencer registers.
+* 6.0   adk  19/12/13   Updated as per the New Tcl API's
+* 7.0   bss  7/25/14    To support Ultrascale:
+*			Added XSM_CH_VUSR0 - XSMXSM_CH_VUSR3,XSM_MAX_VUSR0 -
+*			XSM_MIN_VUSR3,XSM_ATR_VUSR0_UPPER -
+*			XSM_ATR_VUSR3_LOWER macros.
+*			Added XSM_IP_OFFSET macro(since register
+*			offsets are different for Ultrascale comapared to
+*			earlier familes),Offsets,Masks for VUSER0 to
+*			VUSER3 channels, Configuration Register 3 and
+*			Sequence Registers 8 and 9 in xsysmon_hw.h.
+*			Modified XSysMon_GetAdcData,
+*			XSysMon_GetMinMaxMeasurement,
+*			XSysMon_SetSingleChParams, XSysMon_SetAlarmEnables,
+*			XSysMon_GetAlarmEnables,XSysMon_SetSeqChEnables,
+*			XSysMon_GetSeqChEnables,XSysMon_SetSeqAvgEnables,
+*			XSysMon_GetSeqAvgEnables,XSysMon_SetAlarmThreshold
+*			and XSysMon_GetAlarmThreshold in xsysmon.c.
+*			Modified driver tcl to generate XPAR_SYSMON_0_IP_TYPE
+*			parameter.
+* 7.1	bss  05/06/15 Modified temperature transfer function for
+* 					  for Ultrascale CR#859369
+* 7.2   sk   11/10/15 Used UINTPTR instead of u32 for Baseaddress CR# 867425.
+*                     Changed the prototype of XSysMon_CfgInitialize API.
+* 7.2  adk  29/02/16 Updated interrupt example to support Zynq and ZynqMP
+*                    CR#938326.
+* 7.2  asa  11/03/16  Made changes to use configuration register 3 only for
+*					  Ultrascale. This fixes the CR#910905.
+* 7.2  adk  14/03/16 Fix compilation issues when sysmon is configured
+*                    with streaming interface CR#940976.
+* 7.3  vns  15/04/16 Corrected Ultrascale conversion formulae CR#949949
+*      ms   01/23/17 Added xil_printf statement in main function for all
+*                    examples to ensure that "Successfully ran" and "Failed"
+*                    strings are available in all examples. This is a fix
+*                    for CR-965028.
+*      ms   03/17/17 Added readme.txt file in examples folder for doxygen
+*                    generation.
+*      ms   04/05/17 Modified Comment lines in functions of sysmon
+*                    examples to recognize it as documentation block
+*                    for doxygen generation.
+* 7.4  ms   04/18/17 Modified tcl file to add suffix U for all macros
+*                    definitions of sysmon in xparameters.h
+* 
+* +*****************************************************************************/ + +#ifndef XSYSMON_H /* Prevent circular inclusions */ +#define XSYSMON_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files ********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xstatus.h" +#include "xsysmon_hw.h" + +/************************** Constant Definitions ****************************/ + + +/** + * @name Indexes for the different channels. + * @{ + */ +#define XSM_CH_TEMP 0x0 /**< On Chip Temperature */ +#define XSM_CH_VCCINT 0x1 /**< VCCINT */ +#define XSM_CH_VCCAUX 0x2 /**< VCCAUX */ +#define XSM_CH_VPVN 0x3 /**< VP/VN Dedicated analog inputs */ +#define XSM_CH_VREFP 0x4 /**< VREFP */ +#define XSM_CH_VREFN 0x5 /**< VREFN */ +#define XSM_CH_VBRAM 0x6 /**< VBRAM - 7 Series and Zynq */ +#define XSM_CH_SUPPLY_CALIB 0x07 /**< Supply Calib Data Reg */ +#define XSM_CH_ADC_CALIB 0x08 /**< ADC Offset Channel Reg */ +#define XSM_CH_GAINERR_CALIB 0x09 /**< Gain Error Channel Reg */ +#define XSM_CH_VCCPINT 0x0D /**< On-chip PS VCCPINT Channel, Zynq */ +#define XSM_CH_VCCPAUX 0x0E /**< On-chip PS VCCPAUX Channel, Zynq */ +#define XSM_CH_VCCPDRO 0x0F /**< On-chip PS VCCPDRO Channel, Zynq */ +#define XSM_CH_AUX_MIN 16 /**< Channel number for 1st Aux Channel */ +#define XSM_CH_AUX_MAX 31 /**< Channel number for Last Aux channel */ +#define XSM_CH_VUSR0 32 /**< VUSER0 Supply - UltraScale */ +#define XSM_CH_VUSR1 33 /**< VUSER1 Supply - UltraScale */ +#define XSM_CH_VUSR2 34 /**< VUSER2 Supply - UltraScale */ +#define XSM_CH_VUSR3 35 /**< VUSER3 Supply - UltraScale */ + + +/*@}*/ + + +/** + * @name Indexes for reading the Calibration Coefficient Data. + * @{ + */ +#define XSM_CALIB_SUPPLY_OFFSET_COEFF 0 /**< Supply Offset Calib Coefficient */ +#define XSM_CALIB_ADC_OFFSET_COEFF 1 /**< ADC Offset Calib Coefficient */ +#define XSM_CALIB_GAIN_ERROR_COEFF 2 /**< Gain Error Calib Coefficient*/ + +/*@}*/ + + +/** + * @name Indexes for reading the Minimum/Maximum Measurement Data. + * @{ + */ +#define XSM_MAX_TEMP 0 /**< Maximum Temperature Data */ +#define XSM_MAX_VCCINT 1 /**< Maximum VCCINT Data */ +#define XSM_MAX_VCCAUX 2 /**< Maximum VCCAUX Data */ +#define XSM_MAX_VCCBRAM 3 /**< Maximum VCCBRAM Data, 7 Series/Zynq */ +#define XSM_MIN_TEMP 4 /**< Minimum Temperature Data */ +#define XSM_MIN_VCCINT 5 /**< Minimum VCCINT Data */ +#define XSM_MIN_VCCAUX 6 /**< Minimum VCCAUX Data */ +#define XSM_MIN_VCCBRAM 7 /**< Minimum VCCBRAM Data, 7 Series/Zynq */ +#define XSM_MAX_VCCPINT 8 /**< Maximum VCCPINT Data, Zynq */ +#define XSM_MAX_VCCPAUX 9 /**< Maximum VCCPAUX Data, Zynq */ +#define XSM_MAX_VCCPDRO 0xA /**< Maximum VCCPDRO Data, Zynq */ +#define XSM_MIN_VCCPINT 0xC /**< Minimum VCCPINT Data, Zynq */ +#define XSM_MIN_VCCPAUX 0xD /**< Minimum VCCPAUX Data, Zynq */ +#define XSM_MIN_VCCPDRO 0xE /**< Minimum VCCPDRO Data, Zynq */ +#define XSM_MAX_VUSR0 0x80 /**< Maximum VUSR0 Data, Ultrascale */ +#define XSM_MAX_VUSR1 0x81 /**< Maximum VUSR1 Data, Ultrascale */ +#define XSM_MAX_VUSR2 0x82 /**< Maximum VUSR2 Data, Ultrascale */ +#define XSM_MAX_VUSR3 0x83 /**< Maximum VUSR3 Data, Ultrascale */ +#define XSM_MIN_VUSR0 0x88 /**< Minimum VUSR0 Data, Ultrascale */ +#define XSM_MIN_VUSR1 0x89 /**< Minimum VUSR1 Data, Ultrascale */ +#define XSM_MIN_VUSR2 0x8A /**< Minimum VUSR2 Data, Ultrascale */ +#define XSM_MIN_VUSR3 0x8B /**< Minimum VUSR3 Data, Ultrascale */ + + +/*@}*/ + + +/** + * @name Alarm Threshold(Limit) Register (ATR) indexes. + * @{ + */ +#define XSM_ATR_TEMP_UPPER 0 /**< High user Temperature */ +#define XSM_ATR_VCCINT_UPPER 1 /**< VCCINT high voltage limit */ +#define XSM_ATR_VCCAUX_UPPER 2 /**< VCCAUX high voltage limit */ +#define XSM_ATR_OT_UPPER 3 /**< Lower Over Temperature limit */ +#define XSM_ATR_TEMP_LOWER 4 /**< Low user Temperature */ +#define XSM_ATR_VCCINT_LOWER 5 /**< VCCINT low voltage limit */ +#define XSM_ATR_VCCAUX_LOWER 6 /**< VCCAUX low voltage limit */ +#define XSM_ATR_OT_LOWER 7 /**< Lower Over Temperature limit */ +#define XSM_ATR_VBRAM_UPPER 8 /**< VBRAM high voltage limit */ +#define XSM_ATR_VCCPINT_UPPER 9 /**< VCCPINT Upper Alarm, Zynq */ +#define XSM_ATR_VCCPAUX_UPPER 0xA /**< VCCPAUX Upper Alarm, Zynq */ +#define XSM_ATR_VCCPDRO_UPPER 0xB /**< VCCPDRO Upper Alarm, Zynq */ +#define XSM_ATR_VBRAM_LOWER 0xC /**< VRBAM Lower Alarm, 7 Series and Zynq*/ +#define XSM_ATR_VCCPINT_LOWER 0xD /**< VCCPINT Lower Alarm, Zynq */ +#define XSM_ATR_VCCPAUX_LOWER 0xE /**< VCCPAUX Lower Alarm, Zynq */ +#define XSM_ATR_VCCPDRO_LOWER 0xF /**< VCCPDRO Lower Alarm, Zynq */ +#define XSM_ATR_VUSR0_UPPER 0x10 /**< VUSER0 Upper Alarm, Ultrascale */ +#define XSM_ATR_VUSR1_UPPER 0x11 /**< VUSER1 Upper Alarm, Ultrascale */ +#define XSM_ATR_VUSR2_UPPER 0x12 /**< VUSER2 Upper Alarm, Ultrascale */ +#define XSM_ATR_VUSR3_UPPER 0x13 /**< VUSER3 Upper Alarm, Ultrascale */ +#define XSM_ATR_VUSR0_LOWER 0x18 /**< VUSER0 Lower Alarm, Ultrascale */ +#define XSM_ATR_VUSR1_LOWER 0x19 /**< VUSER1 Lower Alarm, Ultrascale */ +#define XSM_ATR_VUSR2_LOWER 0x1A /**< VUSER2 Lower Alarm, Ultrascale */ +#define XSM_ATR_VUSR3_LOWER 0x1B /**< VUSER3 Lower Alarm, Ultrascale */ + +/*@}*/ + + +/** + * @name Averaging to be done for the channels. + * @{ + */ +#define XSM_AVG_0_SAMPLES 0 /**< No Averaging */ +#define XSM_AVG_16_SAMPLES 1 /**< Average 16 samples */ +#define XSM_AVG_64_SAMPLES 2 /**< Average 64 samples */ +#define XSM_AVG_256_SAMPLES 3 /**< Average 256 samples */ + +/*@}*/ + + +/** + * @name Channel Sequencer Modes of operation. + * @{ + */ +#define XSM_SEQ_MODE_SAFE 0 /**< Default Safe Mode */ +#define XSM_SEQ_MODE_ONEPASS 1 /**< Onepass through Sequencer */ +#define XSM_SEQ_MODE_CONTINPASS 2 /**< Continuous Cycling Seqquencer */ +#define XSM_SEQ_MODE_SINGCHAN 3 /**< Single channel - No Sequencing */ +#define XSM_SEQ_MODE_SIMUL 4 /**< Simultaneous Cycling Sequencer, + * 7 Series and Zynq XADC only */ +#define XSM_SEQ_MODE_INDEPENDENT 8 /**< Independent ADC Sequencer, + * 7 Series and Zynq XADC only */ + +/*@}*/ + +/* For backwards compatabilty */ +#define XSM_CH_CALIBRATION XSM_CH_ADC_CALIB +#define XSM_ATR_BRAM_UPPER XSM_ATR_VBRAM_UPPER +#define XSM_ATR_BRAM_LOWER XSM_ATR_VBRAM_LOWER + + +/**************************** Type Definitions ******************************/ + +/** + * This typedef contains configuration information for the System Monitor/ADC + * device. + */ +typedef struct { + u16 DeviceId; /**< Unique ID of device */ + UINTPTR BaseAddress; /**< Device base address */ + int IncludeInterrupt; /**< Supports Interrupt driven mode */ + u8 IpType; /**< 1 - System Management */ + /**< 0 - XADC/System Monoitor */ +} XSysMon_Config; + + +/** + * The driver's instance data. The user is required to allocate a variable + * of this type for every System Monitor/ADC device in the system. A pointer to + * a variable of this type is then passed to the driver API functions. + */ +typedef struct { + XSysMon_Config Config; /**< XSysMon_Config of current device */ + u32 IsReady; /**< Device is initialized and ready */ + u32 Mask; /**< Store the previously written value + in CONVST register */ +} XSysMon; + +/***************** Macros (Inline Functions) Definitions ********************/ + +/****************************************************************************/ +/** +* +* This macro checks if the SysMonitor/ADC device is in Event Sampling mode. +* +* @param InstancePtr is a pointer to the XSysMon instance. +* +* @return +* - TRUE if the device is in Event Sampling Mode. +* - FALSE if the device is in Continuous Sampling Mode. +* +* @note C-Style signature: +* int XSysMon_IsEventSamplingMode(XSysMon *InstancePtr); +* +*****************************************************************************/ +#define XSysMon_IsEventSamplingModeSet(InstancePtr) \ + (((XSysMon_ReadReg((InstancePtr)->Config.BaseAddress, \ + XSM_CFR0_OFFSET) & XSM_CFR0_EC_MASK) ? \ + TRUE : FALSE)) + +/****************************************************************************/ +/** +* +* This macro checks if the Dynamic Reconfiguration Port (DRP) transaction from +* the JTAG is in progress. +* +* @param InstancePtr is a pointer to the XSysMon instance. +* +* @return +* - TRUE if the DRP transaction from JTAG is in Progress. +* - FALSE if there is no DRP transaction from the JTAG. +* +* @note C-Style signature: +* int XSysMon_IsDrpBusy(XSysMon *InstancePtr); +* +*****************************************************************************/ +#define XSysMon_IsDrpBusy(InstancePtr) \ + ((XSysMon_ReadReg((InstancePtr)->Config.BaseAddress, \ + XSM_SR_OFFSET) & XSM_SR_JTAG_BUSY_MASK) ? \ + TRUE : FALSE) + +/****************************************************************************/ +/** +* +* This macro checks if the Dynamic Reconfiguration Port (DRP) is locked by the +* JTAG. +* +* @param InstancePtr is a pointer to the XSysMon instance. +* +* @return +* - TRUE if the DRP is locked by the JTAG. +* - FALSE if the DRP is not locked by the JTAG. +* +* @note C-Style signature: +* int XSysMon_IsDrpLocked(XSysMon *InstancePtr); +* +*****************************************************************************/ +#define XSysMon_IsDrpLocked(InstancePtr) \ + (((XSysMon_ReadReg((InstancePtr)->Config.BaseAddress, \ + XSM_SR_OFFSET) & XSM_SR_JTAG_LOCKED_MASK) ? \ + TRUE : FALSE)) + +/****************************************************************************/ +/** +* +* This macro converts System Monitor/ADC Raw Data to Temperature(centigrades). +* +* @param AdcData is the SysMon Raw ADC Data. +* +* @return The Temperature in centigrades. +* +* @note C-Style signature: +* float XSysMon_RawToTemperature(u32 AdcData); +* +*****************************************************************************/ +#if XPAR_SYSMON_0_IP_TYPE == SYSTEM_MANAGEMENT + +#define XSysMon_RawToTemperature(AdcData) \ + ((((float)(AdcData)/65536.0f)/0.00199451786f ) - 273.67f) + +#else + +#define XSysMon_RawToTemperature(AdcData) \ + ((((float)(AdcData)/65536.0f)/0.00198421639f ) - 273.15f) + +#endif +/****************************************************************************/ +/** +* +* This macro converts System Monitor/ADC Raw Data to Voltage(volts). +* +* @param AdcData is the System Monitor/ADC Raw Data. +* +* @return The Voltage in volts. +* +* @note C-Style signature: +* float XSysMon_RawToVoltage(u32 AdcData); +* +*****************************************************************************/ +#define XSysMon_RawToVoltage(AdcData) \ + ((((float)(AdcData))* (3.0f))/65536.0f) + +/****************************************************************************/ +/** +* +* This macro converts Temperature in centigrades to System Monitor/ADC Raw Data. +* +* @param Temperature is the Temperature in centigrades to be +* converted to System Monitor/ADC Raw Data. +* +* @return The System Monitor/ADC Raw Data. +* +* @note C-Style signature: +* int XSysMon_TemperatureToRaw(float Temperature); +* +*****************************************************************************/ +#if XPAR_SYSMON_0_IP_TYPE == SYSTEM_MANAGEMENT + +#define XSysMon_TemperatureToRaw(Temperature) \ + ((int)(((Temperature) + 273.67f)*65536.0f*0.00199451786f)) + +#else + +#define XSysMon_TemperatureToRaw(Temperature) \ + ((int)(((Temperature) + 273.15f)*65536.0f*0.00198421639f)) + +#endif +/****************************************************************************/ +/** +* +* This macro converts Voltage in Volts to System Monitor/ADC Raw Data. +* +* @param Voltage is the Voltage in volts to be converted to +* System Monitor/ADC Raw Data. +* +* @return The System Monitor/ADC Raw Data. +* +* @note C-Style signature: +* int XSysMon_VoltageToRaw(float Voltage); +* +*****************************************************************************/ +#define XSysMon_VoltageToRaw(Voltage) \ + ((int)((Voltage)*65536.0f/3.0f)) + + +/************************** Function Prototypes *****************************/ + +/** + * Functions in xsysmon_sinit.c + */ +XSysMon_Config *XSysMon_LookupConfig(u16 DeviceId); + +/** + * Functions in xsysmon.c + */ +int XSysMon_CfgInitialize(XSysMon *InstancePtr, + XSysMon_Config *ConfigPtr, UINTPTR EffectiveAddr); + +void XSysMon_Reset(XSysMon *InstancePtr); + +u32 XSysMon_GetStatus(XSysMon *InstancePtr); + +u32 XSysMon_GetAlarmOutputStatus(XSysMon *InstancePtr); + +void XSysMon_StartAdcConversion(XSysMon *InstancePtr); + +void XSysMon_ResetAdc(XSysMon *InstancePtr); + +u16 XSysMon_GetAdcData(XSysMon *InstancePtr, u8 Channel); + +u16 XSysMon_GetCalibCoefficient(XSysMon *InstancePtr, u8 CoeffType); + +u16 XSysMon_GetMinMaxMeasurement(XSysMon *InstancePtr, u8 MeasurementType); + +void XSysMon_SetAvg(XSysMon *InstancePtr, u8 Average); +u8 XSysMon_GetAvg(XSysMon *InstancePtr); + +int XSysMon_SetSingleChParams(XSysMon *InstancePtr, u8 Channel, + int IncreaseAcqCycles, int IsEventMode, + int IsDifferentialMode); + +void XSysMon_SetAlarmEnables(XSysMon *InstancePtr, u32 AlmEnableMask); +u32 XSysMon_GetAlarmEnables(XSysMon *InstancePtr); + +void XSysMon_SetCalibEnables(XSysMon *InstancePtr, u16 Calibration); +u16 XSysMon_GetCalibEnables(XSysMon *InstancePtr); + +void XSysMon_SetSequencerMode(XSysMon *InstancePtr, u8 SequencerMode); +u8 XSysMon_GetSequencerMode(XSysMon *InstancePtr); +void XSysMon_SetSequencerEvent(XSysMon *InstancePtr, int IsEventMode); + +void XSysMon_SetExtenalMux(XSysMon *InstancePtr, u8 Channel); + +void XSysMon_SetAdcClkDivisor(XSysMon *InstancePtr, u8 Divisor); +u8 XSysMon_GetAdcClkDivisor(XSysMon *InstancePtr); + +int XSysMon_SetSeqChEnables(XSysMon *InstancePtr, u64 ChEnableMask); +u64 XSysMon_GetSeqChEnables(XSysMon *InstancePtr); + +int XSysMon_SetSeqAvgEnables(XSysMon *InstancePtr, u64 AvgEnableChMask); +u64 XSysMon_GetSeqAvgEnables(XSysMon *InstancePtr); + +int XSysMon_SetSeqInputMode(XSysMon *InstancePtr, u32 InputModeChMask); +u32 XSysMon_GetSeqInputMode(XSysMon *InstancePtr); + +int XSysMon_SetSeqAcqTime(XSysMon *InstancePtr, u32 AcqCyclesChMask); +u32 XSysMon_GetSeqAcqTime(XSysMon *InstancePtr); + +void XSysMon_SetAlarmThreshold(XSysMon *InstancePtr, u8 AlarmThrReg, u16 Value); +u16 XSysMon_GetAlarmThreshold(XSysMon *InstancePtr, u8 AlarmThrReg); + +void XSysMon_SetOverTemp(XSysMon *InstancePtr, u16 Value); +u16 XSysMon_GetOverTemp(XSysMon *InstancePtr); + +void XSysMon_EnableUserOverTemp(XSysMon *InstancePtr); +void XSysMon_DisableUserOverTemp(XSysMon *InstancePtr); + +void XSysMon_EnableTempUpdate(XSysMon *InstancePtr); +void XSysMon_DisableTempUpdate(XSysMon *InstancePtr); +void XSysMon_SetTempWaitCycles(XSysMon *InstancePtr, u16 WaitCycles); + + +/** + * Functions in xsysmon_selftest.c + */ +int XSysMon_SelfTest(XSysMon *InstancePtr); + +/** + * Functions in xsysmon_intr.c + */ +void XSysMon_IntrGlobalEnable(XSysMon *InstancePtr); +void XSysMon_IntrGlobalDisable(XSysMon *InstancePtr); + +void XSysMon_IntrEnable(XSysMon *InstancePtr, u32 Mask); +void XSysMon_IntrDisable(XSysMon *InstancePtr, u32 Mask); +u32 XSysMon_IntrGetEnabled(XSysMon *InstancePtr); + +u32 XSysMon_IntrGetStatus(XSysMon *InstancePtr); +void XSysMon_IntrClear(XSysMon *InstancePtr, u32 Mask); + + +#ifdef __cplusplus +} +#endif + +#endif /* End of protection macro. */ +/** @} */ diff --git a/datalink814_sp/bsp/microblaze_ps/include/xsysmon_hw.h b/datalink814_sp/bsp/microblaze_ps/include/xsysmon_hw.h new file mode 100644 index 0000000..9316273 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/include/xsysmon_hw.h @@ -0,0 +1,686 @@ +/****************************************************************************** +* +* Copyright (C) 2007 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xsysmon_hw.h +* @addtogroup sysmon_v7_5 +* @{ +* +* This header file contains identifiers and basic driver functions (or +* macros) that can be used to access the System Monitor/ADC device or XADC. +* +* Refer to the device specification for more information about this driver. +* +* @note None. +* +*
+*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- -----  -------- -----------------------------------------------------
+* 1.00a xd/sv  05/22/07 First release
+* 2.00a sv     07/07/08 Added bit definitions for new Alarm Interrupts in the
+*			Interrupt Registers.
+* 3.00a sdm    02/09/09 Added register and bit definitions for V6 SysMon.
+* 4.00a ktn    10/22/09 The macros have been renamed to remove _m from the name
+*		       	of the macro.
+* 5.00a sdm    06/15/11 Added new definitions for XADC.
+* 5.01a bss    02/15/12 Updated for Zynq.
+* 5.02a bss    11/23/12 Added macros XSM_CONVST_TEMPUPDT_MASK,
+*			XSM_CONVST_WAITCYCLES_MASK and
+*			XSM_CONVST_WAITCYCLES_SHIFT (CR #679872)
+* 7.0	bss    7/25/14	To support Ultrascale:
+*			Added XSM_IP_OFFSET macro.
+*			Added Offsets and Masks for VUSER0 to VUSER3 channels.
+*			Added Configuration Register 3 and Sequence Registers
+*			8 and 9.
+* 7.2   asa     03/11/16 Made changes so that XSM_CFR3_OFFSET is
+*             visible only for Ultrasacle. Fix for CR#910905.
+*
+* 
+* +*****************************************************************************/ + +#ifndef XSYSMON_HW_H /* Prevent circular inclusions */ +#define XSYSMON_HW_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files ********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_io.h" +#include "xparameters.h" + +/************************** Constant Definitions ****************************/ + +#define SYSTEM_MANAGEMENT 1 /* Ultrascale */ +#define XADC 0 /* 7 Series, Zynq */ + + +#if XPAR_SYSMON_0_IP_TYPE == SYSTEM_MANAGEMENT +#define XSM_IP_OFFSET 0x200 +#else +#define XSM_IP_OFFSET 0x00 +#endif + + +/**@name Register offsets + * + * The following constants provide access to each of the registers of the + * System Monitor/ADC device. + * @{ + */ + +/* + * System Monitor/ADC Local Registers + */ +#define XSM_SRR_OFFSET 0x00 /**< Software Reset Register */ +#define XSM_SR_OFFSET 0x04 /**< Status Register */ +#define XSM_AOR_OFFSET 0x08 /**< Alarm Output Register */ +#define XSM_CONVST_OFFSET 0x0C /**< ADC Convert Start Register */ +#define XSM_ARR_OFFSET 0x10 /**< ADC Reset Register */ + +/* + * System Monitor/ADC Interrupt Registers + */ +#define XSM_GIER_OFFSET 0x5C /**< Global Interrupt Enable */ +#define XSM_IPISR_OFFSET 0x60 /**< Interrupt Status Register */ +#define XSM_IPIER_OFFSET 0x68 /**< Interrupt Enable register */ + +/* + * System Monitor/ADC Internal Channel Registers + */ +#define XSM_TEMP_OFFSET (XSM_IP_OFFSET + 0x200) + /**< On-chip Temperature Reg */ +#define XSM_VCCINT_OFFSET (XSM_IP_OFFSET + 0x204) + /**< On-chip VCCINT Data Reg */ +#define XSM_VCCAUX_OFFSET (XSM_IP_OFFSET + 0x208) + /**< On-chip VCCAUX Data Reg */ +#define XSM_VPVN_OFFSET (XSM_IP_OFFSET + 0x20C) + /**< ADC out of VP/VN */ +#define XSM_VREFP_OFFSET (XSM_IP_OFFSET + 0x210) + /**< On-chip VREFP Data Reg */ +#define XSM_VREFN_OFFSET (XSM_IP_OFFSET + 0x214) + /**< On-chip VREFN Data Reg */ +#define XSM_VBRAM_OFFSET (XSM_IP_OFFSET + 0x218) + /**< On-chip VBRAM Data,7-series/Zynq */ +#define XSM_SUPPLY_CALIB_OFFSET (XSM_IP_OFFSET + 0x220) + /**< Supply Offset Data Reg */ +#define XSM_ADC_CALIB_OFFSET (XSM_IP_OFFSET + 0x224) + /**< ADC Offset Data Reg */ +#define XSM_GAINERR_CALIB_OFFSET (XSM_IP_OFFSET + 0x228) + /**< Gain Error Data Reg */ +#define XSM_VCCPINT_OFFSET (XSM_IP_OFFSET + 0x22C) + /**< PS VCCPINT Data Reg - Zynq */ +#define XSM_VCCPAUX_OFFSET (XSM_IP_OFFSET + 0x230) + /**< PS VCCPAUX Data Reg - Zynq */ +#define XSM_VCCPDRO_OFFSET (XSM_IP_OFFSET + 0x234) + /**< PS VCCPDRO Data Reg - Zynq */ +#define XSM_VUSR0_OFFSET (XSM_IP_OFFSET + 0x400) + /**< VUSER0 Supply - Ultrascale */ +#define XSM_VUSR1_OFFSET (XSM_IP_OFFSET + 0x404) + /**< VUSER0 Supply - Ultrascale */ +#define XSM_VUSR2_OFFSET (XSM_IP_OFFSET + 0x408) + /**< VUSER0 Supply - Ultrascale */ +#define XSM_VUSR3_OFFSET (XSM_IP_OFFSET + 0x40C) + /**< VUSER0 Supply - Ultrascale */ + +/* + * System Monitor/ADC External Channel Registers + */ +#define XSM_AUX00_OFFSET (XSM_IP_OFFSET + 0x240) + /**< ADC out of VAUXP0/VAUXN0 */ +#define XSM_AUX01_OFFSET (XSM_IP_OFFSET + 0x244) + /**< ADC out of VAUXP1/VAUXN1 */ +#define XSM_AUX02_OFFSET (XSM_IP_OFFSET + 0x248) + /**< ADC out of VAUXP2/VAUXN2 */ +#define XSM_AUX03_OFFSET (XSM_IP_OFFSET + 0x24C) + /**< ADC out of VAUXP3/VAUXN3 */ +#define XSM_AUX04_OFFSET (XSM_IP_OFFSET + 0x250) + /**< ADC out of VAUXP4/VAUXN4 */ +#define XSM_AUX05_OFFSET (XSM_IP_OFFSET + 0x254) + /**< ADC out of VAUXP5/VAUXN5 */ +#define XSM_AUX06_OFFSET (XSM_IP_OFFSET + 0x258) + /**< ADC out of VAUXP6/VAUXN6 */ +#define XSM_AUX07_OFFSET (XSM_IP_OFFSET + 0x25C) + /**< ADC out of VAUXP7/VAUXN7 */ +#define XSM_AUX08_OFFSET (XSM_IP_OFFSET + 0x260) + /**< ADC out of VAUXP8/VAUXN8 */ +#define XSM_AUX09_OFFSET (XSM_IP_OFFSET + 0x264) + /**< ADC out of VAUXP9/VAUXN9 */ +#define XSM_AUX10_OFFSET (XSM_IP_OFFSET + 0x268) + /**< ADC out of VAUXP10/VAUXN10 */ +#define XSM_AUX11_OFFSET (XSM_IP_OFFSET + 0x26C) + /**< ADC out of VAUXP11/VAUXN11 */ +#define XSM_AUX12_OFFSET (XSM_IP_OFFSET + 0x270) + /**< ADC out of VAUXP12/VAUXN12 */ +#define XSM_AUX13_OFFSET (XSM_IP_OFFSET + 0x274) + /**< ADC out of VAUXP13/VAUXN13 */ +#define XSM_AUX14_OFFSET (XSM_IP_OFFSET + 0x278) + /**< ADC out of VAUXP14/VAUXN14 */ +#define XSM_AUX15_OFFSET (XSM_IP_OFFSET + 0x27C) + /**< ADC out of VAUXP15/VAUXN15 */ + +/* + * System Monitor/ADC Registers for Maximum/Minimum data captured for the + * on chip Temperature/VCCINT/VCCAUX data. + */ +#define XSM_MAX_TEMP_OFFSET (XSM_IP_OFFSET + 0x280) + /**< Maximum Temperature Reg */ +#define XSM_MAX_VCCINT_OFFSET (XSM_IP_OFFSET + 0x284) + /**< Maximum VCCINT Register */ +#define XSM_MAX_VCCAUX_OFFSET (XSM_IP_OFFSET + 0x288) + /**< Maximum VCCAUX Register */ +#define XSM_MAX_VBRAM_OFFSET (XSM_IP_OFFSET + 0x28C) + /**< Maximum VBRAM Reg, 7 Series/Zynq */ +#define XSM_MIN_TEMP_OFFSET (XSM_IP_OFFSET + 0x290) + /**< Minimum Temperature Reg */ +#define XSM_MIN_VCCINT_OFFSET (XSM_IP_OFFSET + 0x294) + /**< Minimum VCCINT Register */ +#define XSM_MIN_VCCAUX_OFFSET (XSM_IP_OFFSET + 0x298) + /**< Minimum VCCAUX Register */ +#define XSM_MIN_VBRAM_OFFSET (XSM_IP_OFFSET + 0x29C) + /**< Maximum VBRAM Reg, 7 Series/Zynq */ +#define XSM_MAX_VCCPINT_OFFSET (XSM_IP_OFFSET + 0x2A0) + /**< Max VCCPINT Register, Zynq */ +#define XSM_MAX_VCCPAUX_OFFSET (XSM_IP_OFFSET + 0x2A4) + /**< Max VCCPAUX Register, Zynq */ +#define XSM_MAX_VCCPDRO_OFFSET (XSM_IP_OFFSET + 0x2A8) + /**< Max VCCPDRO Register, Zynq */ +#define XSM_MIN_VCCPINT_OFFSET (XSM_IP_OFFSET + 0x2AC) + /**< Min VCCPINT Register, Zynq */ +#define XSM_MIN_VCCPAUX_OFFSET (XSM_IP_OFFSET + 0x2B0) + /**< Min VCCPAUX Register, Zynq */ +#define XSM_MIN_VCCPDRO_OFFSET (XSM_IP_OFFSET + 0x2B4) + /**< Min VCCPDRO Register, Zynq */ +#define XSM_MAX_VUSR0_OFFSET (XSM_IP_OFFSET + 0x480) + /**< Maximum VUSER0 Supply Reg */ +#define XSM_MAX_VUSR1_OFFSET (XSM_IP_OFFSET + 0x484) + /**< Maximum VUSER1 Supply Reg */ +#define XSM_MAX_VUSR2_OFFSET (XSM_IP_OFFSET + 0x488) + /**< Maximum VUSER2 Supply Reg */ +#define XSM_MAX_VUSR3_OFFSET (XSM_IP_OFFSET + 0x48C) + /**< Maximum VUSER3 Supply Reg */ +#define XSM_MIN_VUSR0_OFFSET (XSM_IP_OFFSET + 0x4A0) + /**< Minimum VUSER0 Supply Reg */ +#define XSM_MIN_VUSR1_OFFSET (XSM_IP_OFFSET + 0x4A4) + /**< Minimum VUSER1 Supply Reg */ +#define XSM_MIN_VUSR2_OFFSET (XSM_IP_OFFSET + 0x4A8) + /**< Minimum VUSER2 Supply Reg */ +#define XSM_MIN_VUSR3_OFFSET (XSM_IP_OFFSET + 0x4AC) + /**< Minimum VUSER3 Supply Reg */ + + +#define XSM_FLAG_REG_OFFSET (XSM_IP_OFFSET + 0x2FC) /**< General Status */ + +/* + * System Monitor/ADC Configuration Registers + */ +#define XSM_CFR0_OFFSET (XSM_IP_OFFSET + 0x300) + /**< Configuration Register 0 */ +#define XSM_CFR1_OFFSET (XSM_IP_OFFSET + 0x304) + /**< Configuration Register 1 */ +#define XSM_CFR2_OFFSET (XSM_IP_OFFSET + 0x308) + /**< Configuration Register 2 */ + +#if XPAR_SYSMON_0_IP_TYPE == SYSTEM_MANAGEMENT +#define XSM_CFR3_OFFSET (XSM_IP_OFFSET + 0x30C) + /**< Configuration Register 3 */ +#endif +/* + * System Monitor/ADC Sequence Registers + */ +#define XSM_SEQ00_OFFSET (XSM_IP_OFFSET + 0x320) + /**< Seq Reg 00 Adc Channel Selection */ +#define XSM_SEQ01_OFFSET (XSM_IP_OFFSET + 0x324) + /**< Seq Reg 01 Adc Channel Selection */ +#define XSM_SEQ02_OFFSET (XSM_IP_OFFSET + 0x328) + /**< Seq Reg 02 Adc Average Enable */ +#define XSM_SEQ03_OFFSET (XSM_IP_OFFSET + 0x32C) + /**< Seq Reg 03 Adc Average Enable */ +#define XSM_SEQ04_OFFSET (XSM_IP_OFFSET + 0x330) + /**< Seq Reg 04 Adc Input Mode Select */ +#define XSM_SEQ05_OFFSET (XSM_IP_OFFSET + 0x334) + /**< Seq Reg 05 Adc Input Mode Select */ +#define XSM_SEQ06_OFFSET (XSM_IP_OFFSET + 0x338) + /**< Seq Reg 06 Adc Acquisition Select */ +#define XSM_SEQ07_OFFSET (XSM_IP_OFFSET + 0x33C) + /**< Seq Reg 07 Adc Acquisition Select */ +#define XSM_SEQ08_OFFSET (XSM_IP_OFFSET + 0x318) + /**< Seq Reg 08 Adc Channel Selection */ +#define XSM_SEQ09_OFFSET (XSM_IP_OFFSET + 0x31C) + /**< Seq Reg 09 Adc Average Enable */ + +/* + * System Monitor/ADC Alarm Threshold/Limit Registers (ATR) + */ +#define XSM_ATR_TEMP_UPPER_OFFSET (XSM_IP_OFFSET + 0x340) + /**< Temp Upper Alarm Register */ +#define XSM_ATR_VCCINT_UPPER_OFFSET (XSM_IP_OFFSET + 0x344) + /**< VCCINT Upper Alarm Reg */ +#define XSM_ATR_VCCAUX_UPPER_OFFSET (XSM_IP_OFFSET + 0x348) + /**< VCCAUX Upper Alarm Reg */ +#define XSM_ATR_OT_UPPER_OFFSET (XSM_IP_OFFSET + 0x34C) + /**< Over Temp Upper Alarm Reg */ +#define XSM_ATR_TEMP_LOWER_OFFSET (XSM_IP_OFFSET + 0x350) + /**< Temp Lower Alarm Register */ +#define XSM_ATR_VCCINT_LOWER_OFFSET (XSM_IP_OFFSET + 0x354) + /**< VCCINT Lower Alarm Reg */ +#define XSM_ATR_VCCAUX_LOWER_OFFSET (XSM_IP_OFFSET + 0x358) + /**< VCCAUX Lower Alarm Reg */ +#define XSM_ATR_OT_LOWER_OFFSET (XSM_IP_OFFSET + 0x35C) + /**< Over Temp Lower Alarm Reg */ +#define XSM_ATR_VBRAM_UPPER_OFFSET (XSM_IP_OFFSET + 0x360) + /**< VBBAM Upper Alarm,7 Series */ +#define XSM_ATR_VCCPINT_UPPER_OFFSET (XSM_IP_OFFSET + 0x364) + /**< VCCPINT Upper Alarm, Zynq */ +#define XSM_ATR_VCCPAUX_UPPER_OFFSET (XSM_IP_OFFSET + 0x368) + /**< VCCPAUX Upper Alarm, Zynq */ +#define XSM_ATR_VCCPDRO_UPPER_OFFSET (XSM_IP_OFFSET + 0x36C) + /**< VCCPDRO Upper Alarm, Zynq */ +#define XSM_ATR_VBRAM_LOWER_OFFSET (XSM_IP_OFFSET + 0x370) + /**< VRBAM Lower Alarm, 7 Series*/ +#define XSM_ATR_VCCPINT_LOWER_OFFSET (XSM_IP_OFFSET + 0x374) + /**< VCCPINT Lower Alarm, Zynq */ +#define XSM_ATR_VCCPAUX_LOWER_OFFSET (XSM_IP_OFFSET + 0x378) + /**< VCCPAUX Lower Alarm, Zynq */ +#define XSM_ATR_VCCPDRO_LOWER_OFFSET (XSM_IP_OFFSET + 0x37C) + /**< VCCPDRO Lower Alarm, Zynq */ +#define XSM_ATR_VUSR0_UPPER_OFFSET (XSM_IP_OFFSET + 0x380) + /**< VUSER0 Upper Alarm Reg */ +#define XSM_ATR_VUSR1_UPPER_OFFSET (XSM_IP_OFFSET + 0x384) + /**< VUSER1 Upper Alarm Reg */ +#define XSM_ATR_VUSR2_UPPER_OFFSET (XSM_IP_OFFSET + 0x388) + /**< VUSER2 Upper Alarm Reg */ +#define XSM_ATR_VUSR3_UPPER_OFFSET (XSM_IP_OFFSET + 0x38C) + /**< VUSER3 Upper Alarm Reg */ +#define XSM_ATR_VUSR0_LOWER_OFFSET (XSM_IP_OFFSET + 0x3A0) + /**< VUSER0 Lower Alarm Reg */ +#define XSM_ATR_VUSR1_LOWER_OFFSET (XSM_IP_OFFSET + 0x3A4) + /**< VUSER1 Lower Alarm Reg */ +#define XSM_ATR_VUSR2_LOWER_OFFSET (XSM_IP_OFFSET + 0x3A8) + /**< VUSER2 Lower Alarm Reg */ +#define XSM_ATR_VUSR3_LOWER_OFFSET (XSM_IP_OFFSET + 0x3AC) + /**< VUSER3 Lower Alarm Reg */ + +/*@}*/ + +/** + * @name System Monitor/ADC Software Reset Register (SRR) mask(s) + * @{ + */ +#define XSM_SRR_IPRST_MASK 0x0000000A /**< Device Reset Mask */ + +/*@}*/ + +/** + * @name System Monitor/ADC Status Register (SR) mask(s) + * @{ + */ +#define XSM_SR_JTAG_BUSY_MASK 0x00000400 /**< JTAG is busy */ +#define XSM_SR_JTAG_MODIFIED_MASK 0x00000200 /**< JTAG Write has occurred */ +#define XSM_SR_JTAG_LOCKED_MASK 0x00000100 /**< JTAG is locked */ +#define XSM_SR_BUSY_MASK 0x00000080 /**< ADC is busy in conversion */ +#define XSM_SR_EOS_MASK 0x00000040 /**< End of Sequence */ +#define XSM_SR_EOC_MASK 0x00000020 /**< End of Conversion */ +#define XSM_SR_CH_MASK 0x0000001F /**< Input ADC channel */ + +/*@}*/ + +/** + * @name System Monitor/ADC Alarm Output Register (AOR) mask(s) + * @{ + */ +#define XSM_AOR_ALARM_ALL_MASK 0x00001FFF /**< Mask for all Alarms */ +#define XSM_AOR_VUSR3_MASK 0x00001000 /**< ALM11 - VUSER3 Alarm Mask */ +#define XSM_AOR_VUSR2_MASK 0x00000800 /**< ALM10 - VUSER2 Alarm Mask */ +#define XSM_AOR_VUSR1_MASK 0x00000400 /**< ALM9 - VUSER1 Alarm Mask */ +#define XSM_AOR_VUSR0_MASK 0x00000200 /**< ALM8 - VUSER0 Alarm Mask */ +#define XSM_AOR_ALL_MASK 0x00000100 /**< ALM7 - All Alarms 0 to 6 */ +#define XSM_AOR_VCCPDRO_MASK 0x00000080 /**< ALM6 - VCCPDRO Mask, Zynq */ +#define XSM_AOR_VCCPAUX_MASK 0x00000040 /**< ALM5 - VCCPAUX Mask, Zynq */ +#define XSM_AOR_VCCPINT_MASK 0x00000020 /**< ALM4 - VCCPINT Mask, Zynq */ +#define XSM_AOR_VBRAM_MASK 0x00000010 /**< ALM3 - VBRAM Output Mask + * - 7 Series and Zynq */ +#define XSM_AOR_VCCAUX_MASK 0x00000008 /**< ALM2 - VCCAUX Output Mask */ +#define XSM_AOR_VCCINT_MASK 0x00000004 /**< ALM1 - VCCINT Alarm Mask */ +#define XSM_AOR_TEMP_MASK 0x00000002 /**< ALM0 - Temp sensor Alarm Mask */ +#define XSM_AOR_OT_MASK 0x00000001 /**< Over Temp Alarm Output */ + +/*@}*/ + +/** + * @name System Monitor/ADC CONVST Register (CONVST) mask(s) + * @{ + */ +#define XSM_CONVST_CONVST_MASK 0x00000001 + /**< Conversion Start Mask */ +#define XSM_CONVST_TEMPUPDT_MASK 0x00000002 + /**< Temperature Update + Enable Mask */ +#define XSM_CONVST_WAITCYCLES_SHIFT 2 /**< Wait Cycles Shift */ +#define XSM_CONVST_WAITCYCLES_MASK 0x0003FFFC /**< Wait Cycles Mask */ +#define XSM_CONVST_WAITCYCLES_DEFAULT 0x03E8 /**< Wait Cycles + default value */ +/*@}*/ + +/** + * @name System Monitor/ADC Reset Register (ARR) mask(s) + * @{ + */ +#define XSM_ARR_RST_MASK 0x00000001 /**< ADC Reset bit mask */ + +/*@}*/ + +/** + * @name Global Interrupt Enable Register (GIER) mask(s) + * @{ + */ +#define XSM_GIER_GIE_MASK 0x80000000 /**< Global interrupt enable */ +/*@}*/ + +/** + * @name System Monitor/ADC device Interrupt Status/Enable Registers + * + * Interrupt Status Register (IPISR) + * + * This register holds the interrupt status flags for the device. + * + * Interrupt Enable Register (IPIER) + * + * This register is used to enable interrupt sources for the device. + * Writing a '1' to a bit in this register enables the corresponding Interrupt. + * Writing a '0' to a bit in this register disables the corresponding Interrupt + * + * IPISR/IPIER registers have the same bit definitions and are only defined + * once. + * @{ + */ +#define XSM_IPIXR_VBRAM_MASK 0x00000400 /**< ALM3 - VBRAM Output Mask + * - 7 Series and Zynq */ +#define XSM_IPIXR_TEMP_DEACTIVE_MASK 0x00000200 /**< Alarm 0 DEACTIVE */ +#define XSM_IPIXR_OT_DEACTIVE_MASK 0x00000100 /**< Over Temp DEACTIVE */ +#define XSM_IPIXR_JTAG_MODIFIED_MASK 0x00000080 /**< JTAG Modified */ +#define XSM_IPIXR_JTAG_LOCKED_MASK 0x00000040 /**< JTAG Locked */ +#define XSM_IPIXR_EOC_MASK 0x00000020 /**< End Of Conversion */ +#define XSM_IPIXR_EOS_MASK 0x00000010 /**< End Of Sequence */ +#define XSM_IPIXR_VCCAUX_MASK 0x00000008 /**< Alarm 2 - VCCAUX */ +#define XSM_IPIXR_VCCINT_MASK 0x00000004 /**< Alarm 1 - VCCINT */ +#define XSM_IPIXR_TEMP_MASK 0x00000002 /**< Alarm 0 - Temp ACTIVE */ +#define XSM_IPIXR_OT_MASK 0x00000001 /**< Over Temperature ACTIVE */ +#define XSM_IPIXR_VUSR0_MASK 0x00004000 /**< Alarm 8 VUSER0 */ +#define XSM_IPIXR_VUSR1_MASK 0x00008000 /**< Alarm 9 VUSER1 */ +#define XSM_IPIXR_VUSR2_MASK 0x00010000 /**< Alarm 10 VUSER2 */ +#define XSM_IPIXR_VUSR3_MASK 0x00020000 /**< Alarm 11 VUSER3 */ +#define XSM_IPIXR_ALL_MASK 0x0003C7FF /**< Mask of all interrupts */ + + +/*@}*/ + +/** + * @name Mask for all ADC converted data including Minimum/Maximum Measurements + * and Threshold data. + * @{ + */ +#define XSM_ADCDATA_MAX_MASK 0x03FF + +/*@}*/ + +/** + * @name Configuration Register 0 (CFR0) mask(s) + * @{ + */ +#define XSM_CFR0_CAL_AVG_MASK 0x8000 /**< Averaging enable Mask */ +#define XSM_CFR0_AVG_VALID_MASK 0x3000 /**< Averaging bit Mask */ +#define XSM_CFR0_AVG1_MASK 0x0000 /**< No Averaging */ +#define XSM_CFR0_AVG16_MASK 0x1000 /**< Average 16 samples */ +#define XSM_CFR0_AVG64_MASK 0x2000 /**< Average 64 samples */ +#define XSM_CFR0_AVG256_MASK 0x3000 /**< Average 256 samples */ +#define XSM_CFR0_AVG_SHIFT 12 /**< Shift for the Averaging bits */ +#define XSM_CFR0_MUX_MASK 0x0800 /**< External Mux Mask Enable + * - 7 Series and Zynq */ +#define XSM_CFR0_DU_MASK 0x0400 /**< Bipolar/Unipolar mode */ +#define XSM_CFR0_EC_MASK 0x0200 /**< Event driven/Continuous mode */ +#define XSM_CFR0_ACQ_MASK 0x0100 /**< Add acquisition by 6 ADCCLK */ +#define XSM_CFR0_CHANNEL_MASK 0x003F /**< Channel number bit Mask */ + +/*@}*/ + +/** + * @name Configuration Register 1 (CFR1) mask(s) + * @{ + */ +#define XSM_CFR1_SEQ_VALID_MASK 0xF000 /**< Sequence bit Mask */ +#define XSM_CFR1_SEQ_SAFEMODE_MASK 0x0000 /**< Default Safe Mode */ +#define XSM_CFR1_SEQ_ONEPASS_MASK 0x1000 /**< Onepass through Seq */ +#define XSM_CFR1_SEQ_CONTINPASS_MASK 0x2000 /**< Continuous Cycling Seq */ +#define XSM_CFR1_SEQ_SINGCHAN_MASK 0x3000 /**< Single channel - No Seq */ +#define XSM_CFR1_SEQ_SIMUL_SAMPLING_MASK 0x4000 /**< Simulataneous Sampling + * Mask */ +#define XSM_CFR1_SEQ_INDEPENDENT_MASK 0x8000 /**< Independent Mode */ +#define XSM_CFR1_SEQ_SHIFT 12 /**< Sequence bit shift */ +#define XSM_CFR1_ALM_VCCPDRO_MASK 0x0800 /**< Alarm 6 - VCCPDRO, Zynq */ +#define XSM_CFR1_ALM_VCCPAUX_MASK 0x0400 /**< Alarm 5 - VCCPAUX, Zynq */ +#define XSM_CFR1_ALM_VCCPINT_MASK 0x0200 /**< Alarm 4 - VCCPINT, Zynq */ +#define XSM_CFR1_ALM_VBRAM_MASK 0x0100 /**< Alarm 3 - VBRAM Enable + * 7 Series and Zynq */ +#define XSM_CFR1_CAL_VALID_MASK 0x00F0 /**< Valid Calibration Mask */ +#define XSM_CFR1_CAL_PS_GAIN_OFFSET_MASK 0x0080 /**< Calibration 3 -Power + Supply Gain/Offset + Enable */ +#define XSM_CFR1_CAL_PS_OFFSET_MASK 0x0040 /**< Calibration 2 -Power + Supply Offset Enable */ +#define XSM_CFR1_CAL_ADC_GAIN_OFFSET_MASK 0x0020 /**< Calibration 1 -ADC Gain + Offset Enable */ +#define XSM_CFR1_CAL_ADC_OFFSET_MASK 0x0010 /**< Calibration 0 -ADC Offset + Enable */ +#define XSM_CFR1_CAL_DISABLE_MASK 0x0000 /**< No Calibration */ +#define XSM_CFR1_ALM_ALL_MASK 0x0F0F /**< Mask for all alarms */ +#define XSM_CFR1_ALM_VCCAUX_MASK 0x0008 /**< Alarm 2 - VCCAUX Enable */ +#define XSM_CFR1_ALM_VCCINT_MASK 0x0004 /**< Alarm 1 - VCCINT Enable */ +#define XSM_CFR1_ALM_TEMP_MASK 0x0002 /**< Alarm 0 - Temperature */ +#define XSM_CFR1_OT_MASK 0x0001 /**< Over Temperature Enable */ + +/*@}*/ + +/** + * @name Configuration Register 2 (CFR2) mask(s) + * @{ + */ +#define XSM_CFR2_CD_VALID_MASK 0xFF00 /**Interrupts
+* +* It is the responsibility of the application to connect the interrupt +* handler of the timer/counter to the interrupt source. The interrupt +* handler function, XTmrCtr_InterruptHandler, is visible such that the user +* can connect it to the interrupt source. Note that this interrupt handler +* does not provide interrupt context save and restore processing, the user +* must perform this processing. +* +* The driver services interrupts and passes timeouts to the upper layer +* software through callback functions. The upper layer software must register +* its callback functions during initialization. The driver requires callback +* functions for timers. +* +* @note +* The default settings for the timers are: +* - Interrupt generation disabled +* - Count up mode +* - Compare mode +* - Hold counter (will not reload the timer) +* - External compare output disabled +* - External capture input disabled +* - Pulse width modulation disabled +* - Timer disabled, waits for Start function to be called +*

+* A timer counter device may contain multiple timer counters. The symbol +* XTC_DEVICE_TIMER_COUNT defines the number of timer counters in the device. +* The device currently contains 2 timer counters. +*

+* This driver is intended to be RTOS and processor independent. It works with +* physical addresses only. Any needs for dynamic memory management, threads +* or thread mutual exclusion, virtual memory, or cache control must be +* satisfied by the layer above this driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a ecm  08/16/01 First release
+* 1.00b jhl  02/21/02 Repartitioned the driver for smaller files
+* 1.10b mta  03/21/07 Updated to new coding style.
+* 1.11a sdm  08/22/08 Removed support for static interrupt handlers from the MDD
+*		      file
+* 2.00a ktn  10/30/09 Updated to use HAL API's. _m is removed from all the macro
+*		      definitions.
+* 2.01a ktn  07/12/10 Renamed the macro XTimerCtr_ReadReg as XTmrCtr_ReadReg
+*		      for naming consistency (CR 559142).
+* 2.02a sdm  09/28/10 Updated the driver tcl to generate the xparameters
+*		      for the timer clock frequency (CR 572679).
+* 2.03a rvo  11/30/10 Added check to see if interrupt is enabled before further
+*		      processing for CR 584557.
+* 2.04a sdm  07/12/11 Added support for cascade mode operation.
+* 		      The cascade mode of operation is present in the latest
+*		      versions of the axi_timer IP. Please check the HW
+*		      Datasheet to see whether this feature is present in the
+*		      version of the IP that you are using.
+* 2.05a adk  15/05/13 Fixed the CR:693066
+*		      Added the IsStartedTmrCtr0/IsStartedTmrCtr1 members to the
+*		      XTmrCtr instance structure.
+*		      The IsStartedTmrCtrX will be assigned XIL_COMPONENT_IS_STARTED in
+*		      the XTmrCtr_Start function.
+*		      The IsStartedTmrCtrX will be cleared in the XTmrCtr_Stop function.
+*		      There will be no Initialization done in the
+*		      XTmrCtr_Initialize if both the timers have already started and
+*		      the XST_DEVICE_IS_STARTED Status is returned.
+*		      Removed the logic in the XTmrCtr_Initialize function
+*		      which was checking the Register Value to know whether
+*		      a timer has started or not.
+* 3.0   adk  19/12/13 Updated as per the New Tcl API's
+* 4.0   als  09/30/15 Updated initialization API.
+* 4.1   sk   11/10/15 Used UINTPTR instead of u32 for Baseaddress CR# 867425.
+*                     Changed the prototype of XTmrCtr_CfgInitialize API.
+* 4.2   nsk  15/09/16 Updated tcl, to get correct device id for canonical defines,
+*                     when there exist more than one timer perepheral
+*       ms   01/23/17 Added xil_printf statement in main function for all
+*                     examples to ensure that "Successfully ran" and "Failed"
+*                     strings are available in all examples. This is a fix
+*                     for CR-965028.
+*       ms   03/17/17 Added readme.txt file in examples folder for doxygen
+*                     generation.
+* 4.4   ms   04/18/17 Modified tcl file to add suffix U for all macros
+*                     definitions of tmrctr in xparameters.h
+* 4.5   cjp  03/22/18 Added APIs to support PWM feature. XTmrCtr_PwmConfigure
+*                     is used to configure PWM to operate for specific period
+*                     and high time. XTmrCtr_PwmEnable and XTmrCtr_PwmDisable
+*                     are used to enable/disable the PWM output.
+* 4.6   mus  03/13/19 tmrctr_tapp tcl is updated to support scenario where
+*                     AXI TIMER is interrupting ARM processor through more
+*                     than one interrupt pin. Fix for CR#1024699
+* 
+* +******************************************************************************/ + +#ifndef XTMRCTR_H /* prevent circular inclusions */ +#define XTMRCTR_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xstatus.h" +#include "xtmrctr_l.h" + +/************************** Constant Definitions *****************************/ + +/** + * @name Configuration options + * These options are used in XTmrCtr_SetOptions() and XTmrCtr_GetOptions() + * @{ + */ +/** + * Used to configure the timer counter device. + *
+ * XTC_CASCADE_MODE_OPTION	Enables the Cascade Mode only valid for TCSRO.
+ * XTC_ENABLE_ALL_OPTION	Enables all timer counters at once.
+ * XTC_DOWN_COUNT_OPTION	Configures the timer counter to count down from
+ *				start value, the default is to count up.
+ * XTC_CAPTURE_MODE_OPTION	Configures the timer to capture the timer
+ *				counter value when the external capture line is
+ *				asserted. The default mode is compare mode.
+ * XTC_INT_MODE_OPTION		Enables the timer counter interrupt output.
+ * XTC_AUTO_RELOAD_OPTION	In compare mode, configures the timer counter to
+ *				reload from the compare value. The default mode
+ *				causes the timer counter to hold when the
+ *				compare value is hit.
+ *				In capture mode, configures the timer counter to
+ *				not hold the previous capture value if a new
+ *				event occurs. The default mode cause the timer
+ *				counter to hold the capture value until
+ *				recognized.
+ * XTC_EXT_COMPARE_OPTION	Enables the external compare output signal.
+ * 
+ */ +#define XTC_CASCADE_MODE_OPTION 0x00000080UL +#define XTC_ENABLE_ALL_OPTION 0x00000040UL +#define XTC_DOWN_COUNT_OPTION 0x00000020UL +#define XTC_CAPTURE_MODE_OPTION 0x00000010UL +#define XTC_INT_MODE_OPTION 0x00000008UL +#define XTC_AUTO_RELOAD_OPTION 0x00000004UL +#define XTC_EXT_COMPARE_OPTION 0x00000002UL +/*@}*/ + +/* Round division */ +#define XTC_ROUND_DIV(a, b) ((a + (b / 2)) / b) + +/* Convert clock frequency in hertz to period in nano seconds */ +#define XTC_HZ_TO_NS(Hz) XTC_ROUND_DIV(1000000000, Hz) + +/**************************** Type Definitions *******************************/ + +/** + * This typedef contains configuration information for the device. + */ +typedef struct { + u16 DeviceId; /**< Unique ID of device */ + UINTPTR BaseAddress; /**< Register base address */ + u32 SysClockFreqHz; /**< The AXI bus clock frequency */ +} XTmrCtr_Config; + +/** + * Signature for the callback function. + * + * @param CallBackRef is a callback reference passed in by the upper layer + * when setting the callback functions, and passed back to the + * upper layer when the callback is invoked. Its type is + * unimportant to the driver, so it is a void pointer. + * @param TmrCtrNumber is the number of the timer/counter within the + * device. The device typically contains at least two + * timer/counters. The timer number is a zero based number with a + * range of 0 to (XTC_DEVICE_TIMER_COUNT - 1). + */ +typedef void (*XTmrCtr_Handler) (void *CallBackRef, u8 TmrCtrNumber); + + +/** + * Timer/Counter statistics + */ +typedef struct { + u32 Interrupts; /**< The number of interrupts that have occurred */ +} XTmrCtrStats; + +/** + * The XTmrCtr driver instance data. The user is required to allocate a + * variable of this type for every timer/counter device in the system. A + * pointer to a variable of this type is then passed to the driver API + * functions. + */ +typedef struct { + XTmrCtr_Config Config; /**< Core configuration. */ + XTmrCtrStats Stats; /**< Component Statistics */ + UINTPTR BaseAddress; /**< Base address of registers */ + u32 IsReady; /**< Device is initialized and ready */ + u32 IsStartedTmrCtr0; /**< Is Timer Counter 0 started */ + u32 IsStartedTmrCtr1; /**< Is Timer Counter 1 started */ + u32 IsPwmEnabled; /**< Is PWM Enabled */ + + XTmrCtr_Handler Handler; /**< Callback function */ + void *CallBackRef; /**< Callback reference for handler */ +} XTmrCtr; + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + +/* Required functions, in file xtmrctr.c */ +void XTmrCtr_CfgInitialize(XTmrCtr *InstancePtr, XTmrCtr_Config *ConfigPtr, + UINTPTR EffectiveAddr); +int XTmrCtr_InitHw(XTmrCtr *InstancePtr); +int XTmrCtr_Initialize(XTmrCtr * InstancePtr, u16 DeviceId); +void XTmrCtr_Start(XTmrCtr * InstancePtr, u8 TmrCtrNumber); +void XTmrCtr_Stop(XTmrCtr * InstancePtr, u8 TmrCtrNumber); +u32 XTmrCtr_GetValue(XTmrCtr * InstancePtr, u8 TmrCtrNumber); +void XTmrCtr_SetResetValue(XTmrCtr * InstancePtr, u8 TmrCtrNumber, + u32 ResetValue); +u32 XTmrCtr_GetCaptureValue(XTmrCtr * InstancePtr, u8 TmrCtrNumber); +int XTmrCtr_IsExpired(XTmrCtr * InstancePtr, u8 TmrCtrNumber); +void XTmrCtr_Reset(XTmrCtr * InstancePtr, u8 TmrCtrNumber); +u8 XTmrCtr_PwmConfigure(XTmrCtr *InstancePtr, u32 PwmPeriod, u32 PwmHighTime); +void XTmrCtr_PwmEnable(XTmrCtr *InstancePtr); +void XTmrCtr_PwmDisable(XTmrCtr *InstancePtr); + +/* Lookup configuration in xtmrctr_sinit.c */ +XTmrCtr_Config *XTmrCtr_LookupConfig(u16 DeviceId); + +/* Functions for options, in file xtmrctr_options.c */ +void XTmrCtr_SetOptions(XTmrCtr * InstancePtr, u8 TmrCtrNumber, u32 Options); +u32 XTmrCtr_GetOptions(XTmrCtr * InstancePtr, u8 TmrCtrNumber); + +/* Functions for statistics, in file xtmrctr_stats.c */ +void XTmrCtr_GetStats(XTmrCtr * InstancePtr, XTmrCtrStats * StatsPtr); +void XTmrCtr_ClearStats(XTmrCtr * InstancePtr); + +/* Functions for self-test, in file xtmrctr_selftest.c */ +int XTmrCtr_SelfTest(XTmrCtr * InstancePtr, u8 TmrCtrNumber); + +/* Functions for interrupts, in file xtmrctr_intr.c */ +void XTmrCtr_SetHandler(XTmrCtr * InstancePtr, XTmrCtr_Handler FuncPtr, + void *CallBackRef); +void XTmrCtr_InterruptHandler(void *InstancePtr); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/datalink814_sp/bsp/microblaze_ps/include/xtmrctr_i.h b/datalink814_sp/bsp/microblaze_ps/include/xtmrctr_i.h new file mode 100644 index 0000000..6fc562d --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/include/xtmrctr_i.h @@ -0,0 +1,76 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xtmrctr_i.h +* @addtogroup tmrctr_v4_6 +* @{ +* +* This file contains data which is shared between files internal to the +* XTmrCtr component. It is intended for internal use only. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00b jhl  02/06/02 First release
+* 1.10b mta  03/21/07 Updated to new coding style
+* 2.00a ktn  10/30/09 _m is removed from all the macro definitions.
+* 
+* +******************************************************************************/ + +#ifndef XTMRCTR_I_H /* prevent circular inclusions */ +#define XTMRCTR_I_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" + +/************************** Constant Definitions *****************************/ + + +/************************** Function Prototypes ******************************/ + + +/************************** Variable Definitions *****************************/ + +extern u8 XTmrCtr_Offsets[]; + +#ifdef __cplusplus +} +#endif + +#endif +/** @} */ diff --git a/datalink814_sp/bsp/microblaze_ps/include/xtmrctr_l.h b/datalink814_sp/bsp/microblaze_ps/include/xtmrctr_l.h new file mode 100644 index 0000000..976e601 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/include/xtmrctr_l.h @@ -0,0 +1,437 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xtmrctr_l.h +* @addtogroup tmrctr_v4_6 +* @{ +* +* This header file contains identifiers and low-level driver functions (or +* macros) that can be used to access the device. The user should refer to the +* hardware device specification for more details of the device operation. +* High-level driver functions are defined in xtmrctr.h. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00b jhl  04/24/02 First release
+* 1.10b mta  03/21/07 Updated to new coding style
+* 2.00a ktn  10/30/09 Updated to use HAL API's. _m is removed from all the macro
+*		      definitions.
+* 2.01a ktn  07/12/10 Renamed the macro XTimerCtr_ReadReg as XTmrCtr_ReadReg
+*		      for naming consistency (CR 559142).
+* 2.04a sdm  07/12/11 Added the CASC mode bit in the TCSRO register for the
+*		      cascade mode operation.
+*		      The cascade mode of operation is present in the latest
+*		      versions of the axi_timer IP. Please check the HW
+*		      Datasheet to see whether this feature is present in the
+*		      version of the IP that you are using.
+* 4.4   mus  07/21/17 Updated XTmrCtr_DisableIntr macro to not to clear
+*             T0INT flag
+* 4.5   cjp  03/22/18 Added macros for timer/counter instance number and max
+*                     load value.
+* 
+* +******************************************************************************/ + +#ifndef XTMRCTR_L_H /* prevent circular inclusions */ +#define XTMRCTR_L_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_io.h" + +/************************** Constant Definitions *****************************/ + +/** + * Defines the number of timer counters within a single hardware device. This + * number is not currently parameterized in the hardware but may be in the + * future. + */ +#define XTC_DEVICE_TIMER_COUNT 2 + +/* Each timer counter consumes 16 bytes of address space */ + +#define XTC_TIMER_COUNTER_OFFSET 16 + +/* Timer counter instance number used for PWM */ +#define XTC_TIMER_0 0 +#define XTC_TIMER_1 1 + +/* Max supported load value for timer/counter */ +#define XTC_MAX_LOAD_VALUE 0xFFFFFFFF + +/** @name Register Offset Definitions + * Register offsets within a timer counter, there are multiple + * timer counters within a single device + * @{ + */ + +#define XTC_TCSR_OFFSET 0 /**< Control/Status register */ +#define XTC_TLR_OFFSET 4 /**< Load register */ +#define XTC_TCR_OFFSET 8 /**< Timer counter register */ + +/* @} */ + +/** @name Control Status Register Bit Definitions + * Control Status Register bit masks + * Used to configure the timer counter device. + * @{ + */ + +#define XTC_CSR_CASC_MASK 0x00000800 /**< Cascade Mode */ +#define XTC_CSR_ENABLE_ALL_MASK 0x00000400 /**< Enables all timer + counters */ +#define XTC_CSR_ENABLE_PWM_MASK 0x00000200 /**< Enables the Pulse Width + Modulation */ +#define XTC_CSR_INT_OCCURED_MASK 0x00000100 /**< If bit is set, an + interrupt has occured. + If set and '1' is + written to this bit + position, bit is + cleared. */ +#define XTC_CSR_ENABLE_TMR_MASK 0x00000080 /**< Enables only the + specific timer */ +#define XTC_CSR_ENABLE_INT_MASK 0x00000040 /**< Enables the interrupt + output. */ +#define XTC_CSR_LOAD_MASK 0x00000020 /**< Loads the timer using + the load value provided + earlier in the Load + Register, + XTC_TLR_OFFSET. */ +#define XTC_CSR_AUTO_RELOAD_MASK 0x00000010 /**< In compare mode, + configures + the timer counter to + reload from the + Load Register. The + default mode + causes the timer counter + to hold when the compare + value is hit. In capture + mode, configures the + timer counter to not + hold the previous + capture value if a new + event occurs. The + default mode cause the + timer counter to hold + the capture value until + recognized. */ +#define XTC_CSR_EXT_CAPTURE_MASK 0x00000008 /**< Enables the + external input + to the timer counter. */ +#define XTC_CSR_EXT_GENERATE_MASK 0x00000004 /**< Enables the + external generate output + for the timer. */ +#define XTC_CSR_DOWN_COUNT_MASK 0x00000002 /**< Configures the timer + counter to count down + from start value, the + default is to count + up.*/ +#define XTC_CSR_CAPTURE_MODE_MASK 0x00000001 /**< Enables the timer to + capture the timer + counter value when the + external capture line is + asserted. The default + mode is compare mode.*/ +/* @} */ + +/**************************** Type Definitions *******************************/ + +extern u8 XTmrCtr_Offsets[]; + +/***************** Macros (Inline Functions) Definitions *********************/ + +/*****************************************************************************/ +/** +* Read one of the timer counter registers. +* +* @param BaseAddress contains the base address of the timer counter +* device. +* @param TmrCtrNumber contains the specific timer counter within the +* device, a zero based number, 0 - (XTC_DEVICE_TIMER_COUNT - 1). +* @param RegOffset contains the offset from the 1st register of the timer +* counter to select the specific register of the timer counter. +* +* @return The value read from the register, a 32 bit value. +* +* @note C-Style signature: +* u32 XTmrCtr_ReadReg(u32 BaseAddress, u8 TimerNumber, + unsigned RegOffset); +******************************************************************************/ +#define XTmrCtr_ReadReg(BaseAddress, TmrCtrNumber, RegOffset) \ + Xil_In32((BaseAddress) + XTmrCtr_Offsets[(TmrCtrNumber)] + \ + (RegOffset)) + +#ifndef XTimerCtr_ReadReg +#define XTimerCtr_ReadReg XTmrCtr_ReadReg +#endif + +/*****************************************************************************/ +/** +* Write a specified value to a register of a timer counter. +* +* @param BaseAddress is the base address of the timer counter device. +* @param TmrCtrNumber is the specific timer counter within the device, a +* zero based number, 0 - (XTC_DEVICE_TIMER_COUNT - 1). +* @param RegOffset contain the offset from the 1st register of the timer +* counter to select the specific register of the timer counter. +* @param ValueToWrite is the 32 bit value to be written to the register. +* +* @note C-Style signature: +* void XTmrCtr_WriteReg(u32 BaseAddress, u8 TimerNumber, +* unsigned RegOffset, u32 ValueToWrite); +******************************************************************************/ +#define XTmrCtr_WriteReg(BaseAddress, TmrCtrNumber, RegOffset, ValueToWrite)\ + Xil_Out32(((BaseAddress) + XTmrCtr_Offsets[(TmrCtrNumber)] + \ + (RegOffset)), (ValueToWrite)) + +/****************************************************************************/ +/** +* +* Set the Control Status Register of a timer counter to the specified value. +* +* @param BaseAddress is the base address of the device. +* @param TmrCtrNumber is the specific timer counter within the device, a +* zero based number, 0 - (XTC_DEVICE_TIMER_COUNT - 1). +* @param RegisterValue is the 32 bit value to be written to the register. +* +* @return None. +* +* @note C-Style signature: +* void XTmrCtr_SetControlStatusReg(u32 BaseAddress, +* u8 TmrCtrNumber,u32 RegisterValue); +*****************************************************************************/ +#define XTmrCtr_SetControlStatusReg(BaseAddress, TmrCtrNumber, RegisterValue)\ + XTmrCtr_WriteReg((BaseAddress), (TmrCtrNumber), XTC_TCSR_OFFSET, \ + (RegisterValue)) + +/****************************************************************************/ +/** +* +* Get the Control Status Register of a timer counter. +* +* @param BaseAddress is the base address of the device. +* @param TmrCtrNumber is the specific timer counter within the device, +* a zero based number, 0 - (XTC_DEVICE_TIMER_COUNT - 1). +* +* @return The value read from the register, a 32 bit value. +* +* @note C-Style signature: +* u32 XTmrCtr_GetControlStatusReg(u32 BaseAddress, +* u8 TmrCtrNumber); +*****************************************************************************/ +#define XTmrCtr_GetControlStatusReg(BaseAddress, TmrCtrNumber) \ + XTmrCtr_ReadReg((BaseAddress), (TmrCtrNumber), XTC_TCSR_OFFSET) + +/****************************************************************************/ +/** +* +* Get the Timer Counter Register of a timer counter. +* +* @param BaseAddress is the base address of the device. +* @param TmrCtrNumber is the specific timer counter within the device, +* a zero based number, 0 - (XTC_DEVICE_TIMER_COUNT - 1). +* +* @return The value read from the register, a 32 bit value. +* +* @note C-Style signature: +* u32 XTmrCtr_GetTimerCounterReg(u32 BaseAddress, +* u8 TmrCtrNumber); +*****************************************************************************/ +#define XTmrCtr_GetTimerCounterReg(BaseAddress, TmrCtrNumber) \ + XTmrCtr_ReadReg((BaseAddress), (TmrCtrNumber), XTC_TCR_OFFSET) \ + +/****************************************************************************/ +/** +* +* Set the Load Register of a timer counter to the specified value. +* +* @param BaseAddress is the base address of the device. +* @param TmrCtrNumber is the specific timer counter within the device, a +* zero based number, 0 - (XTC_DEVICE_TIMER_COUNT - 1). +* @param RegisterValue is the 32 bit value to be written to the register. +* +* @return None. +* +* @note C-Style signature: +* void XTmrCtr_SetLoadReg(u32 BaseAddress, u8 TmrCtrNumber, +* u32 RegisterValue); +*****************************************************************************/ +#define XTmrCtr_SetLoadReg(BaseAddress, TmrCtrNumber, RegisterValue) \ + XTmrCtr_WriteReg((BaseAddress), (TmrCtrNumber), XTC_TLR_OFFSET, \ + (RegisterValue)) + +/****************************************************************************/ +/** +* +* Get the Load Register of a timer counter. +* +* @param BaseAddress is the base address of the device. +* @param TmrCtrNumber is the specific timer counter within the device, a +* zero based number, 0 - (XTC_DEVICE_TIMER_COUNT - 1). +* +* @return The value read from the register, a 32 bit value. +* +* @note C-Style signature: +* u32 XTmrCtr_GetLoadReg(u32 BaseAddress, u8 TmrCtrNumber); +*****************************************************************************/ +#define XTmrCtr_GetLoadReg(BaseAddress, TmrCtrNumber) \ +XTmrCtr_ReadReg((BaseAddress), (TmrCtrNumber), XTC_TLR_OFFSET) + +/****************************************************************************/ +/** +* +* Enable a timer counter such that it starts running. +* +* @param BaseAddress is the base address of the device. +* @param TmrCtrNumber is the specific timer counter within the device, a +* zero based number, 0 - (XTC_DEVICE_TIMER_COUNT - 1). +* +* @return None. +* +* @note C-Style signature: +* void XTmrCtr_Enable(u32 BaseAddress, u8 TmrCtrNumber); +*****************************************************************************/ +#define XTmrCtr_Enable(BaseAddress, TmrCtrNumber) \ + XTmrCtr_WriteReg((BaseAddress), (TmrCtrNumber), XTC_TCSR_OFFSET, \ + (XTmrCtr_ReadReg((BaseAddress), ( TmrCtrNumber), \ + XTC_TCSR_OFFSET) | XTC_CSR_ENABLE_TMR_MASK)) + +/****************************************************************************/ +/** +* +* Disable a timer counter such that it stops running. +* +* @param BaseAddress is the base address of the device. +* @param TmrCtrNumber is the specific timer counter within the device, +* a zero based number, 0 - (XTC_DEVICE_TIMER_COUNT - 1). +* +* @return None. +* +* @note C-Style signature: +* void XTmrCtr_Disable(u32 BaseAddress, u8 TmrCtrNumber); +*****************************************************************************/ +#define XTmrCtr_Disable(BaseAddress, TmrCtrNumber) \ + XTmrCtr_WriteReg((BaseAddress), (TmrCtrNumber), XTC_TCSR_OFFSET, \ + (XTmrCtr_ReadReg((BaseAddress), (TmrCtrNumber),\ + XTC_TCSR_OFFSET) & ~ XTC_CSR_ENABLE_TMR_MASK)) + +/****************************************************************************/ +/** +* +* Enable the interrupt for a timer counter. +* +* @param BaseAddress is the base address of the device. +* @param TmrCtrNumber is the specific timer counter within the device, a +* zero based number, 0 - (XTC_DEVICE_TIMER_COUNT - 1). +* +* @return None. +* +* @note C-Style signature: +* void XTmrCtr_EnableIntr(u32 BaseAddress, u8 TmrCtrNumber); +*****************************************************************************/ +#define XTmrCtr_EnableIntr(BaseAddress, TmrCtrNumber) \ + XTmrCtr_WriteReg((BaseAddress), (TmrCtrNumber), XTC_TCSR_OFFSET, \ + (XTmrCtr_ReadReg((BaseAddress), (TmrCtrNumber), \ + XTC_TCSR_OFFSET) | XTC_CSR_ENABLE_INT_MASK)) + +/****************************************************************************/ +/** +* +* Disable the interrupt for a timer counter. +* +* @param BaseAddress is the base address of the device. +* @param TmrCtrNumber is the specific timer counter within the device, a +* zero based number, 0 - (XTC_DEVICE_TIMER_COUNT - 1). +* +* @return None. +* +* @note C-Style signature: +* void XTmrCtr_DisableIntr(u32 BaseAddress, u8 TmrCtrNumber); +*****************************************************************************/ +#define XTmrCtr_DisableIntr(BaseAddress, TmrCtrNumber) \ + XTmrCtr_WriteReg((BaseAddress), (TmrCtrNumber), XTC_TCSR_OFFSET, \ + (XTmrCtr_ReadReg((BaseAddress), (TmrCtrNumber), \ + XTC_TCSR_OFFSET) & ~ (XTC_CSR_ENABLE_INT_MASK \ + | XTC_CSR_INT_OCCURED_MASK))) + +/****************************************************************************/ +/** +* +* Cause the timer counter to load it's Timer Counter Register with the value +* in the Load Register. +* +* @param BaseAddress is the base address of the device. +* @param TmrCtrNumber is the specific timer counter within the device, a +* zero based number, 0 - (XTC_DEVICE_TIMER_COUNT - 1). +* +* @return None. +* +* @note C-Style signature: +* void XTmrCtr_LoadTimerCounterReg(u32 BaseAddress, + u8 TmrCtrNumber); +*****************************************************************************/ +#define XTmrCtr_LoadTimerCounterReg(BaseAddress, TmrCtrNumber) \ + XTmrCtr_WriteReg((BaseAddress), (TmrCtrNumber), XTC_TCSR_OFFSET, \ + (XTmrCtr_ReadReg((BaseAddress), (TmrCtrNumber),\ + XTC_TCSR_OFFSET) | XTC_CSR_LOAD_MASK)) + +/****************************************************************************/ +/** +* +* Determine if a timer counter event has occurred. Events are defined to be +* when a capture has occurred or the counter has roller over. +* +* @param BaseAddress is the base address of the device. +* @param TmrCtrNumber is the specific timer counter within the device, a +* zero based number, 0 - (XTC_DEVICE_TIMER_COUNT - 1). +* +* @note C-Style signature: +* int XTmrCtr_HasEventOccurred(u32 BaseAddress, u8 TmrCtrNumber); +*****************************************************************************/ +#define XTmrCtr_HasEventOccurred(BaseAddress, TmrCtrNumber) \ + ((XTmrCtr_ReadReg((BaseAddress), (TmrCtrNumber), \ + XTC_TCSR_OFFSET) & XTC_CSR_INT_OCCURED_MASK) == \ + XTC_CSR_INT_OCCURED_MASK) + +/************************** Function Prototypes ******************************/ +/************************** Variable Definitions *****************************/ +#ifdef __cplusplus +} +#endif +#endif /* end of protection macro */ +/** @} */ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/axidma_v9_9/src/Makefile b/datalink814_sp/bsp/microblaze_ps/libsrc/axidma_v9_9/src/Makefile new file mode 100644 index 0000000..4c85aa7 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/axidma_v9_9/src/Makefile @@ -0,0 +1,28 @@ +COMPILER= +ARCHIVER= +CP=cp +COMPILER_FLAGS= +EXTRA_COMPILER_FLAGS= +LIB=libxil.a + +RELEASEDIR=../../../lib +INCLUDEDIR=../../../include +INCLUDES=-I${INCLUDEDIR} + +OUTS = *.o +OBJECTS = $(addsuffix .o, $(basename $(wildcard *.c))) + +LIBSOURCES=*.c +INCLUDEFILES=*.h + +libs: + echo "Compiling axidma" + $(COMPILER) $(COMPILER_FLAGS) $(EXTRA_COMPILER_FLAGS) $(INCLUDES) $(LIBSOURCES) + $(ARCHIVER) -r ${RELEASEDIR}/${LIB} $(OBJECTS) + make clean + +include: + ${CP} $(INCLUDEFILES) $(INCLUDEDIR) + +clean: + rm -rf $(OBJECTS) diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/axidma_v9_9/src/xaxidma.c b/datalink814_sp/bsp/microblaze_ps/libsrc/axidma_v9_9/src/xaxidma.c new file mode 100644 index 0000000..1c66431 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/axidma_v9_9/src/xaxidma.c @@ -0,0 +1,985 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xaxidma.c +* @addtogroup axidma_v9_9 +* @{ +* +* This file implements DMA engine-wise initialization and control functions. +* For more information on the implementation of this driver, see xaxidma.h. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a jz   05/18/10 First release
+* 2.00a jz   08/10/10 Second release, added in xaxidma_g.c, xaxidma_sinit.c,
+*                     updated tcl file, added xaxidma_porting_guide.h
+* 3.00a jz   11/22/10 Support IP core parameters change
+* 4.00a rkv  02/22/11 Added support for simple DMA mode
+*		      New API added for simple DMA mode are
+*			- XAxiDma_Busy
+*			- XAxiDma_SimpleTransfer
+* 6.00a srt  01/24/12 Added support for Multi-Channel DMA mode.
+*		      - Changed APIs:
+*			* XAxiDma_Start(XAxiDma * InstancePtr, int RingIndex)
+*			* XAxiDma_Started(XAxiDma * InstancePtr, int RingIndex)
+*			* XAxiDma_Pause(XAxiDma * InstancePtr, int RingIndex)
+*			* XAxiDma_Resume(XAxiDma * InstancePtr, int RingIndex)
+*			* XAxiDma_SimpleTransfer(XAxiDma *InstancePtr,
+*        					u32 BuffAddr, u32 Length,
+*						int Direction, int RingIndex)
+*		      - New API:
+*			* XAxiDma_SelectKeyHole(XAxiDma *InstancePtr,
+*						int Direction, int Select)
+* 7.00a srt  06/18/12  All the APIs changed in v6_00_a are reverted back for
+*		       backward compatibility.
+* 7.01a srt  10/26/12  Fixed issue with driver as it fails with IP version
+*		       < 6.00a as the parameter C_NUM_*_CHANNELS is not
+*		       applicable.
+* 8.0   srt  01/29/14  Added support for Micro DMA Mode and Cyclic mode of
+*		       operations.
+*		      - New API:
+*			* XAxiDma_SelectCyclicMode(XAxiDma *InstancePtr,
+*						int Direction, int Select)
+* 9.1   sk   11/10/15 Used UINTPTR instead of u32 for Baseaddress CR# 867425.
+*
+* 9.1	vak  11/18/15 Removed warnings in the driver and examples (CR# 911664)
+* 9.5   adk  26/10/17 Fix race condition in the XAxiDma_Reset() API. This API
+*		      assumes a tx channel is always present it may be configured
+*		      for rx only.
+* 9.6   rsp  01/11/18 In XAxiDma_Reset() use UINTPTR for storing RegBase CR#976392
+* 9.7   rsp  04/25/18 Add support for 64MB data transfer. Read max buffer length
+*                     width from config structure. CR #1000474
+* 9.8   rsp  07/11/18 Fix cppcheck style warnings. CR #1006164
+*
+* 
+******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xaxidma.h" + +/************************** Constant Definitions *****************************/ + +/* Loop counter to check reset done + */ +#define XAXIDMA_RESET_TIMEOUT 500 + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ +static int XAxiDma_Start(XAxiDma * InstancePtr); +static int XAxiDma_Started(XAxiDma * InstancePtr); + +/************************** Variable Definitions *****************************/ + +/*****************************************************************************/ +/** + * This function initializes a DMA engine. This function must be called + * prior to using a DMA engine. Initializing a engine includes setting + * up the register base address, setting up the instance data, and ensuring the + * hardware is in a quiescent state. + * + * @param InstancePtr is a pointer to the DMA engine instance to be + * worked on. + * @param Config is a pointer to an XAxiDma_Config structure. It contains + * the information about the hardware build, including base + * address,and whether status control stream (StsCntrlStrm), MM2S + * and S2MM are included in the build. + * + * @return + * - XST_SUCCESS for successful initialization + * - XST_INVALID_PARAM if pointer to the configuration structure + * is NULL + * - XST_DMA_ERROR if reset operation failed at the end of + * initialization + * + * @note We assume the hardware building tool will check and error out + * for a hardware build that has no transfer channels. + *****************************************************************************/ +int XAxiDma_CfgInitialize(XAxiDma * InstancePtr, XAxiDma_Config *Config) +{ + UINTPTR BaseAddr; + int TimeOut; + int Index; + u32 MaxTransferLen; + + InstancePtr->Initialized = 0; + + if(!Config) { + return XST_INVALID_PARAM; + } + + BaseAddr = Config->BaseAddr; + + /* Setup the instance */ + memset(InstancePtr, 0, sizeof(XAxiDma)); + InstancePtr->RegBase = BaseAddr; + + /* Get hardware setting information from the configuration structure + */ + InstancePtr->HasMm2S = Config->HasMm2S; + InstancePtr->HasS2Mm = Config->HasS2Mm; + + InstancePtr->HasSg = Config->HasSg; + + InstancePtr->MicroDmaMode = Config->MicroDmaMode; + InstancePtr->AddrWidth = Config->AddrWidth; + + /* Get the number of channels */ + InstancePtr->TxNumChannels = Config->Mm2sNumChannels; + InstancePtr->RxNumChannels = Config->S2MmNumChannels; + + /* This condition is for IP version < 6.00a */ + if (!InstancePtr->TxNumChannels) + InstancePtr->TxNumChannels = 1; + if (!InstancePtr->RxNumChannels) + InstancePtr->RxNumChannels = 1; + + if ((InstancePtr->RxNumChannels > 1) || + (InstancePtr->TxNumChannels > 1)) { + MaxTransferLen = + XAXIDMA_MCHAN_MAX_TRANSFER_LEN; + } + else { + MaxTransferLen = (1U << Config->SgLengthWidth) - 1; + } + + /* Initialize the ring structures */ + InstancePtr->TxBdRing.RunState = AXIDMA_CHANNEL_HALTED; + InstancePtr->TxBdRing.IsRxChannel = 0; + if (!InstancePtr->MicroDmaMode) { + InstancePtr->TxBdRing.MaxTransferLen = MaxTransferLen; + } + else { + /* In MicroDMA mode, Maximum length that can be transferred + * is '(Memory Data Width / 4) * Burst Size' + */ + InstancePtr->TxBdRing.MaxTransferLen = + ((Config->Mm2SDataWidth / 4) * + Config->Mm2SBurstSize); + } + InstancePtr->TxBdRing.RingIndex = 0; + + for (Index = 0; Index < InstancePtr->RxNumChannels; Index++) { + InstancePtr->RxBdRing[Index].RunState + = AXIDMA_CHANNEL_HALTED; + InstancePtr->RxBdRing[Index].IsRxChannel = 1; + InstancePtr->RxBdRing[Index].RingIndex = Index; + } + + if (InstancePtr->HasMm2S) { + InstancePtr->TxBdRing.ChanBase = + BaseAddr + XAXIDMA_TX_OFFSET; + InstancePtr->TxBdRing.HasStsCntrlStrm = + Config->HasStsCntrlStrm; + if (InstancePtr->AddrWidth > 32) + InstancePtr->TxBdRing.Addr_ext = 1; + else + InstancePtr->TxBdRing.Addr_ext = 0; + + InstancePtr->TxBdRing.HasDRE = Config->HasMm2SDRE; + InstancePtr->TxBdRing.DataWidth = + ((unsigned int)Config->Mm2SDataWidth >> 3); + } + + if (InstancePtr->HasS2Mm) { + for (Index = 0; + Index < InstancePtr->RxNumChannels; Index++) { + InstancePtr->RxBdRing[Index].ChanBase = + BaseAddr + XAXIDMA_RX_OFFSET; + InstancePtr->RxBdRing[Index].HasStsCntrlStrm = + Config->HasStsCntrlStrm; + InstancePtr->RxBdRing[Index].HasDRE = + Config->HasS2MmDRE; + InstancePtr->RxBdRing[Index].DataWidth = + ((unsigned int)Config->S2MmDataWidth >> 3); + + if (!InstancePtr->MicroDmaMode) { + InstancePtr->RxBdRing[Index].MaxTransferLen = + MaxTransferLen; + } + else { + /* In MicroDMA mode, Maximum length that can be transferred + * is '(Memory Data Width / 4) * Burst Size' + */ + InstancePtr->RxBdRing[Index].MaxTransferLen = + ((Config->S2MmDataWidth / 4) * + Config->S2MmBurstSize); + } + if (InstancePtr->AddrWidth > 32) + InstancePtr->RxBdRing[Index].Addr_ext = 1; + else + InstancePtr->RxBdRing[Index].Addr_ext = 0; + } + } + + /* Reset the engine so the hardware starts from a known state + */ + XAxiDma_Reset(InstancePtr); + + /* At the initialization time, hardware should finish reset quickly + */ + TimeOut = XAXIDMA_RESET_TIMEOUT; + + while (TimeOut) { + + if(XAxiDma_ResetIsDone(InstancePtr)) { + break; + } + + TimeOut -= 1; + + } + + if (!TimeOut) { + xdbg_printf(XDBG_DEBUG_ERROR, "Failed reset in" + "initialize\r\n"); + + /* Need system hard reset to recover + */ + InstancePtr->Initialized = 0; + return XST_DMA_ERROR; + } + + /* Initialization is successful + */ + InstancePtr->Initialized = 1; + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* Reset both TX and RX channels of a DMA engine. +* +* Reset one channel resets the whole AXI DMA engine. +* +* Any DMA transaction in progress will finish gracefully before engine starts +* reset. Any other transactions that have been submitted to hardware will be +* discarded by the hardware. +* +* @param InstancePtr is a pointer to the DMA engine instance to be +* worked on. +* +* @return None +* +* @note After the reset: +* - All interrupts are disabled. +* - Engine is halted +* +******************************************************************************/ +void XAxiDma_Reset(XAxiDma * InstancePtr) +{ + UINTPTR RegBase; + XAxiDma_BdRing *TxRingPtr; + XAxiDma_BdRing *RxRingPtr; + int RingIndex; + + if (InstancePtr->HasMm2S) { + TxRingPtr = XAxiDma_GetTxRing(InstancePtr); + + /* Save the locations of current BDs both rings are working on + * before the reset so later we can resume the rings smoothly. + */ + if(XAxiDma_HasSg(InstancePtr)){ + XAxiDma_BdRingSnapShotCurrBd(TxRingPtr); + + for (RingIndex = 0; RingIndex < InstancePtr->RxNumChannels; + RingIndex++) { + RxRingPtr = XAxiDma_GetRxIndexRing(InstancePtr, + RingIndex); + XAxiDma_BdRingSnapShotCurrBd(RxRingPtr); + } + } + } + + /* Reset + */ + if (InstancePtr->HasMm2S) { + RegBase = InstancePtr->RegBase + XAXIDMA_TX_OFFSET; + } + else { + RegBase = InstancePtr->RegBase + XAXIDMA_RX_OFFSET; + } + + XAxiDma_WriteReg(RegBase, XAXIDMA_CR_OFFSET, XAXIDMA_CR_RESET_MASK); + + /* Set TX/RX Channel state */ + if (InstancePtr->HasMm2S) { + TxRingPtr = XAxiDma_GetTxRing(InstancePtr); + + TxRingPtr->RunState = AXIDMA_CHANNEL_HALTED; + } + + if (InstancePtr->HasS2Mm) { + for (RingIndex = 0; RingIndex < InstancePtr->RxNumChannels; + RingIndex++) { + RxRingPtr = XAxiDma_GetRxIndexRing(InstancePtr, RingIndex); + if (InstancePtr->HasS2Mm) { + RxRingPtr->RunState = AXIDMA_CHANNEL_HALTED; + } + } + } +} + +/*****************************************************************************/ +/** +* +* Check whether reset is done +* +* @param InstancePtr is a pointer to the DMA engine instance to be +* worked on. +* +* @return +* - 1 if reset is done. +* - 0 if reset is not done +* +* @note None +* +******************************************************************************/ +int XAxiDma_ResetIsDone(XAxiDma * InstancePtr) +{ + u32 RegisterValue; + XAxiDma_BdRing *TxRingPtr; + XAxiDma_BdRing *RxRingPtr; + + TxRingPtr = XAxiDma_GetTxRing(InstancePtr); + RxRingPtr = XAxiDma_GetRxRing(InstancePtr); + + /* Check transmit channel + */ + if (InstancePtr->HasMm2S) { + RegisterValue = XAxiDma_ReadReg(TxRingPtr->ChanBase, + XAXIDMA_CR_OFFSET); + + /* Reset is done when the reset bit is low + */ + if(RegisterValue & XAXIDMA_CR_RESET_MASK) { + + return 0; + } + } + + /* Check receive channel + */ + if (InstancePtr->HasS2Mm) { + RegisterValue = XAxiDma_ReadReg(RxRingPtr->ChanBase, + XAXIDMA_CR_OFFSET); + + /* Reset is done when the reset bit is low + */ + if(RegisterValue & XAXIDMA_CR_RESET_MASK) { + + return 0; + } + } + + return 1; +} +/*****************************************************************************/ +/* +* Start the DMA engine. +* +* Start a halted engine. Processing of BDs is not started. +* +* @param InstancePtr is a pointer to the DMA engine instance to be +* worked on. +* +* @return +* - XST_SUCCESS for success +* - XST_NOT_SGDMA if the driver instance has not been initialized +* - XST_DMA_ERROR if starting the hardware channel fails +* +* @note None +* +*****************************************************************************/ +static int XAxiDma_Start(XAxiDma * InstancePtr) +{ + int Status; + + if (!InstancePtr->Initialized) { + + xdbg_printf(XDBG_DEBUG_ERROR, "Start: Driver not initialized " + "%d\r\n", InstancePtr->Initialized); + + return XST_NOT_SGDMA; + } + + if (InstancePtr->HasMm2S) { + XAxiDma_BdRing *TxRingPtr; + TxRingPtr = XAxiDma_GetTxRing(InstancePtr); + + if (TxRingPtr->RunState == AXIDMA_CHANNEL_HALTED) { + + /* Start the channel + */ + if(XAxiDma_HasSg(InstancePtr)) { + Status = XAxiDma_BdRingStart(TxRingPtr); + if (Status != XST_SUCCESS) { + xdbg_printf(XDBG_DEBUG_ERROR, + "Start hw tx channel failed %d\r\n", + Status); + + return XST_DMA_ERROR; + } + } + else { + XAxiDma_WriteReg(TxRingPtr->ChanBase, + XAXIDMA_CR_OFFSET, + XAxiDma_ReadReg(TxRingPtr->ChanBase, + XAXIDMA_CR_OFFSET) + | XAXIDMA_CR_RUNSTOP_MASK); + } + TxRingPtr->RunState = AXIDMA_CHANNEL_NOT_HALTED; + } + } + + if (InstancePtr->HasS2Mm) { + int RingIndex = 0; + + for (RingIndex = 0; RingIndex < InstancePtr->RxNumChannels; + RingIndex++) { + XAxiDma_BdRing *RxRingPtr; + RxRingPtr = XAxiDma_GetRxIndexRing(InstancePtr, + RingIndex); + + if (RxRingPtr->RunState != AXIDMA_CHANNEL_HALTED) { + return XST_SUCCESS; + } + + /* Start the channel + */ + if(XAxiDma_HasSg(InstancePtr)) { + Status = XAxiDma_BdRingStart(RxRingPtr); + if (Status != XST_SUCCESS) { + xdbg_printf(XDBG_DEBUG_ERROR, + "Start hw tx channel failed %d\r\n", + Status); + + return XST_DMA_ERROR; + } + } + else { + XAxiDma_WriteReg(RxRingPtr->ChanBase, + XAXIDMA_CR_OFFSET, + XAxiDma_ReadReg(RxRingPtr->ChanBase, + XAXIDMA_CR_OFFSET) | + XAXIDMA_CR_RUNSTOP_MASK); + } + + RxRingPtr->RunState = AXIDMA_CHANNEL_NOT_HALTED; + } + } + + return XST_SUCCESS; +} +/*****************************************************************************/ +/** +* Pause DMA transactions on both channels. +* +* If the engine is running and doing transfers, this function does not stop +* the DMA transactions immediately, because then hardware will throw away +* our previously queued transfers. All submitted transfers will finish. +* Transfers submitted after this function will not start until +* XAxiDma_BdRingStart() or XAxiDma_Resume() is called. +* +* @param InstancePtr is a pointer to the DMA engine instance to be +* worked on. +* +* @return +* - XST_SUCCESS if successful +* - XST_NOT_SGDMA, if the driver instance is not initialized +* +* @note None +* +*****************************************************************************/ +int XAxiDma_Pause(XAxiDma * InstancePtr) +{ + + if (!InstancePtr->Initialized) { + + xdbg_printf(XDBG_DEBUG_ERROR, "Pause: Driver not initialized" + " %d\r\n",InstancePtr->Initialized); + + return XST_NOT_SGDMA; + } + + if (InstancePtr->HasMm2S) { + XAxiDma_BdRing *TxRingPtr; + TxRingPtr = XAxiDma_GetTxRing(InstancePtr); + + /* If channel is halted, then we do not need to do anything + */ + if(!XAxiDma_HasSg(InstancePtr)) { + XAxiDma_WriteReg(TxRingPtr->ChanBase, + XAXIDMA_CR_OFFSET, + XAxiDma_ReadReg(TxRingPtr->ChanBase, + XAXIDMA_CR_OFFSET) + & ~XAXIDMA_CR_RUNSTOP_MASK); + } + + TxRingPtr->RunState = AXIDMA_CHANNEL_HALTED; + } + + if (InstancePtr->HasS2Mm) { + int RingIndex = 0; + for (RingIndex = 0; RingIndex < InstancePtr->RxNumChannels; + RingIndex++) { + XAxiDma_BdRing *RxRingPtr; + RxRingPtr = XAxiDma_GetRxIndexRing(InstancePtr, RingIndex); + + /* If channel is halted, then we do not need to do anything + */ + + if(!XAxiDma_HasSg(InstancePtr) && !RingIndex) { + XAxiDma_WriteReg(RxRingPtr->ChanBase, + XAXIDMA_CR_OFFSET, + XAxiDma_ReadReg(RxRingPtr->ChanBase, + XAXIDMA_CR_OFFSET) + & ~XAXIDMA_CR_RUNSTOP_MASK); + } + + RxRingPtr->RunState = AXIDMA_CHANNEL_HALTED; + } + } + + return XST_SUCCESS; + +} + +/*****************************************************************************/ +/** +* Resume DMA transactions on both channels. +* +* @param InstancePtr is a pointer to the DMA engine instance to be +* worked on. +* +* @return +* - XST_SUCCESS for success +* - XST_NOT_SGDMA if the driver instance has not been initialized +* - XST_DMA_ERROR if one of the channels fails to start +* +* @note None +* +*****************************************************************************/ +int XAxiDma_Resume(XAxiDma * InstancePtr) +{ + int Status; + + if (!InstancePtr->Initialized) { + + xdbg_printf(XDBG_DEBUG_ERROR, "Resume: Driver not initialized" + " %d\r\n",InstancePtr->Initialized); + + return XST_NOT_SGDMA; + } + + /* If the DMA engine is not running, start it. Start may fail. + */ + if (!XAxiDma_Started(InstancePtr)) { + Status = XAxiDma_Start(InstancePtr); + + if (Status != XST_SUCCESS) { + xdbg_printf(XDBG_DEBUG_ERROR, "Resume: failed to start" + " engine %d\r\n", Status); + + return Status; + } + } + + /* Mark the state to be not halted + */ + if (InstancePtr->HasMm2S) { + XAxiDma_BdRing *TxRingPtr; + TxRingPtr = XAxiDma_GetTxRing(InstancePtr); + + if(XAxiDma_HasSg(InstancePtr)) { + Status = XAxiDma_BdRingStart(TxRingPtr); + if (Status != XST_SUCCESS) { + xdbg_printf(XDBG_DEBUG_ERROR, "Resume: failed" + " to start tx ring %d\r\n", Status); + + return XST_DMA_ERROR; + } + } + + TxRingPtr->RunState = AXIDMA_CHANNEL_NOT_HALTED; + } + + if (InstancePtr->HasS2Mm) { + int RingIndex = 0; + for (RingIndex = 0 ; RingIndex < InstancePtr->RxNumChannels; + RingIndex++) { + XAxiDma_BdRing *RxRingPtr; + RxRingPtr = XAxiDma_GetRxIndexRing(InstancePtr, RingIndex); + + if(XAxiDma_HasSg(InstancePtr)) { + Status = XAxiDma_BdRingStart(RxRingPtr); + if (Status != XST_SUCCESS) { + xdbg_printf(XDBG_DEBUG_ERROR, "Resume: failed" + "to start rx ring %d\r\n", Status); + + return XST_DMA_ERROR; + } + } + + RxRingPtr->RunState = AXIDMA_CHANNEL_NOT_HALTED; + } + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/* +* Check whether the DMA engine is started. +* +* @param InstancePtr is a pointer to the DMA engine instance to be +* worked on. +* +* @return +* - 1 if engine is started +* - 0 otherwise. +* +* @note None +* +*****************************************************************************/ +static int XAxiDma_Started(XAxiDma * InstancePtr) +{ + + if (!InstancePtr->Initialized) { + + xdbg_printf(XDBG_DEBUG_ERROR, "Started: Driver not initialized" + " %d\r\n",InstancePtr->Initialized); + + return 0; + } + + if (InstancePtr->HasMm2S) { + XAxiDma_BdRing *TxRingPtr; + TxRingPtr = XAxiDma_GetTxRing(InstancePtr); + + if (!XAxiDma_BdRingHwIsStarted(TxRingPtr)) { + xdbg_printf(XDBG_DEBUG_ERROR, + "Started: tx ring not started\r\n"); + + return 0; + } + } + + if (InstancePtr->HasS2Mm) { + XAxiDma_BdRing *RxRingPtr; + RxRingPtr = XAxiDma_GetRxRing(InstancePtr); + + if (!XAxiDma_BdRingHwIsStarted(RxRingPtr)) { + xdbg_printf(XDBG_DEBUG_ERROR, + "Started: rx ring not started\r\n"); + + return 0; + } + } + + return 1; +} + +/*****************************************************************************/ +/** + * This function checks whether specified DMA channel is busy + * + * @param InstancePtr is the driver instance we are working on + * + * @param Direction is DMA transfer direction, valid values are + * - XAXIDMA_DMA_TO_DEVICE. + * - XAXIDMA_DEVICE_TO_DMA. + * + * @return - TRUE if channel is busy + * - FALSE if channel is idle + * + * @note None. + * + *****************************************************************************/ +u32 XAxiDma_Busy(XAxiDma *InstancePtr, int Direction) +{ + + return ((XAxiDma_ReadReg(InstancePtr->RegBase + + (XAXIDMA_RX_OFFSET * Direction), + XAXIDMA_SR_OFFSET) & + XAXIDMA_IDLE_MASK) ? FALSE : TRUE); +} + + +/*****************************************************************************/ +/** + * This function Enable or Disable KeyHole Feature + * + * @param InstancePtr is the driver instance we are working on + * + * @param Direction is DMA transfer direction, valid values are + * - XAXIDMA_DMA_TO_DEVICE. + * - XAXIDMA_DEVICE_TO_DMA. + * @param Select is the option to enable (TRUE) or disable (FALSE). + * + * @return - XST_SUCCESS for success + * + * @note None. + * + *****************************************************************************/ +int XAxiDma_SelectKeyHole(XAxiDma *InstancePtr, int Direction, int Select) +{ + u32 Value; + + Value = XAxiDma_ReadReg(InstancePtr->RegBase + + (XAXIDMA_RX_OFFSET * Direction), + XAXIDMA_CR_OFFSET); + + if (Select) + Value |= XAXIDMA_CR_KEYHOLE_MASK; + else + Value &= ~XAXIDMA_CR_KEYHOLE_MASK; + + XAxiDma_WriteReg(InstancePtr->RegBase + + (XAXIDMA_RX_OFFSET * Direction), + XAXIDMA_CR_OFFSET, Value); + + return XST_SUCCESS; + +} + +/*****************************************************************************/ +/** + * This function Enable or Disable Cyclic Mode Feature + * + * @param InstancePtr is the driver instance we are working on + * + * @param Direction is DMA transfer direction, valid values are + * - XAXIDMA_DMA_TO_DEVICE. + * - XAXIDMA_DEVICE_TO_DMA. + * @param Select is the option to enable (TRUE) or disable (FALSE). + * + * @return - XST_SUCCESS for success + * + * @note None. + * + *****************************************************************************/ +int XAxiDma_SelectCyclicMode(XAxiDma *InstancePtr, int Direction, int Select) +{ + u32 Value; + + Value = XAxiDma_ReadReg(InstancePtr->RegBase + + (XAXIDMA_RX_OFFSET * Direction), + XAXIDMA_CR_OFFSET); + + if (Select) + Value |= XAXIDMA_CR_CYCLIC_MASK; + else + Value &= ~XAXIDMA_CR_CYCLIC_MASK; + + XAxiDma_WriteReg(InstancePtr->RegBase + + (XAXIDMA_RX_OFFSET * Direction), + XAXIDMA_CR_OFFSET, Value); + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** + * This function does one simple transfer submission + * + * It checks in the following sequence: + * - if engine is busy, cannot submit + * - if engine is in SG mode , cannot submit + * + * @param InstancePtr is the pointer to the driver instance + * @param BuffAddr is the address of the source/destination buffer + * @param Length is the length of the transfer + * @param Direction is DMA transfer direction, valid values are + * - XAXIDMA_DMA_TO_DEVICE. + * - XAXIDMA_DEVICE_TO_DMA. + + * @return + * - XST_SUCCESS for success of submission + * - XST_FAILURE for submission failure, maybe caused by: + * Another simple transfer is still going + * - XST_INVALID_PARAM if:Length out of valid range [1:8M] + * Or, address not aligned when DRE is not built in + * + * @note This function is used only when system is configured as + * Simple mode. + * + *****************************************************************************/ +u32 XAxiDma_SimpleTransfer(XAxiDma *InstancePtr, UINTPTR BuffAddr, u32 Length, + int Direction) +{ + u32 WordBits; + int RingIndex = 0; + + /* If Scatter Gather is included then, cannot submit + */ + if (XAxiDma_HasSg(InstancePtr)) { + xdbg_printf(XDBG_DEBUG_ERROR, "Simple DMA mode is not" + " supported\r\n"); + + return XST_FAILURE; + } + + if(Direction == XAXIDMA_DMA_TO_DEVICE){ + if ((Length < 1) || + (Length > InstancePtr->TxBdRing.MaxTransferLen)) { + return XST_INVALID_PARAM; + } + + if (!InstancePtr->HasMm2S) { + xdbg_printf(XDBG_DEBUG_ERROR, "MM2S channel is not" + "supported\r\n"); + + return XST_FAILURE; + } + + /* If the engine is doing transfer, cannot submit + */ + + if(!(XAxiDma_ReadReg(InstancePtr->TxBdRing.ChanBase, + XAXIDMA_SR_OFFSET) & XAXIDMA_HALTED_MASK)) { + if (XAxiDma_Busy(InstancePtr,Direction)) { + xdbg_printf(XDBG_DEBUG_ERROR, + "Engine is busy\r\n"); + return XST_FAILURE; + } + } + + if (!InstancePtr->MicroDmaMode) { + WordBits = (u32)((InstancePtr->TxBdRing.DataWidth) - 1); + } + else { + WordBits = XAXIDMA_MICROMODE_MIN_BUF_ALIGN; + } + + if ((BuffAddr & WordBits)) { + + if (!InstancePtr->TxBdRing.HasDRE) { + xdbg_printf(XDBG_DEBUG_ERROR, + "Unaligned transfer without" + " DRE %x\r\n",(unsigned int)BuffAddr); + + return XST_INVALID_PARAM; + } + } + + + XAxiDma_WriteReg(InstancePtr->TxBdRing.ChanBase, + XAXIDMA_SRCADDR_OFFSET, LOWER_32_BITS(BuffAddr)); + if (InstancePtr->AddrWidth > 32) + XAxiDma_WriteReg(InstancePtr->TxBdRing.ChanBase, + XAXIDMA_SRCADDR_MSB_OFFSET, + UPPER_32_BITS(BuffAddr)); + + XAxiDma_WriteReg(InstancePtr->TxBdRing.ChanBase, + XAXIDMA_CR_OFFSET, + XAxiDma_ReadReg( + InstancePtr->TxBdRing.ChanBase, + XAXIDMA_CR_OFFSET)| XAXIDMA_CR_RUNSTOP_MASK); + + /* Writing to the BTT register starts the transfer + */ + XAxiDma_WriteReg(InstancePtr->TxBdRing.ChanBase, + XAXIDMA_BUFFLEN_OFFSET, Length); + } + else if(Direction == XAXIDMA_DEVICE_TO_DMA){ + if ((Length < 1) || + (Length > + InstancePtr->RxBdRing[RingIndex].MaxTransferLen)) { + return XST_INVALID_PARAM; + } + + + if (!InstancePtr->HasS2Mm) { + xdbg_printf(XDBG_DEBUG_ERROR, "S2MM channel is not" + " supported\r\n"); + + return XST_FAILURE; + } + + if(!(XAxiDma_ReadReg(InstancePtr->RxBdRing[RingIndex].ChanBase, + XAXIDMA_SR_OFFSET) & XAXIDMA_HALTED_MASK)) { + if (XAxiDma_Busy(InstancePtr,Direction)) { + xdbg_printf(XDBG_DEBUG_ERROR, + "Engine is busy\r\n"); + return XST_FAILURE; + } + } + + if (!InstancePtr->MicroDmaMode) { + WordBits = + (u32)((InstancePtr->RxBdRing[RingIndex].DataWidth) - 1); + } + else { + WordBits = XAXIDMA_MICROMODE_MIN_BUF_ALIGN; + } + + if ((BuffAddr & WordBits)) { + + if (!InstancePtr->RxBdRing[RingIndex].HasDRE) { + xdbg_printf(XDBG_DEBUG_ERROR, + "Unaligned transfer without" + " DRE %x\r\n", (unsigned int)BuffAddr); + + return XST_INVALID_PARAM; + } + } + + + XAxiDma_WriteReg(InstancePtr->RxBdRing[RingIndex].ChanBase, + XAXIDMA_DESTADDR_OFFSET, LOWER_32_BITS(BuffAddr)); + if (InstancePtr->AddrWidth > 32) + XAxiDma_WriteReg(InstancePtr->RxBdRing[RingIndex].ChanBase, + XAXIDMA_DESTADDR_MSB_OFFSET, + UPPER_32_BITS(BuffAddr)); + + XAxiDma_WriteReg(InstancePtr->RxBdRing[RingIndex].ChanBase, + XAXIDMA_CR_OFFSET, + XAxiDma_ReadReg(InstancePtr->RxBdRing[RingIndex].ChanBase, + XAXIDMA_CR_OFFSET)| XAXIDMA_CR_RUNSTOP_MASK); + /* Writing to the BTT register starts the transfer + */ + XAxiDma_WriteReg(InstancePtr->RxBdRing[RingIndex].ChanBase, + XAXIDMA_BUFFLEN_OFFSET, Length); + + } + + return XST_SUCCESS; +} +/** @} */ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/axidma_v9_9/src/xaxidma.h b/datalink814_sp/bsp/microblaze_ps/libsrc/axidma_v9_9/src/xaxidma.h new file mode 100644 index 0000000..e053b19 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/axidma_v9_9/src/xaxidma.h @@ -0,0 +1,761 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xaxidma.h +* @addtogroup axidma_v9_9 +* @{ +* @details +* +* This is the driver API for the AXI DMA engine. +* +* For a full description of DMA features, please see the hardware spec. This +* driver supports the following features: +* +* - Scatter-Gather DMA (SGDMA) +* - Simple DMA +* - Interrupts +* - Programmable interrupt coalescing for SGDMA +* - APIs to manage Buffer Descriptors (BD) movement to and from the SGDMA +* engine +* +* Simple DMA +* +* Simple DMA allows the application to define a single transaction between DMA +* and Device. It has two channels: one from the DMA to Device and the other +* from Device to DMA. Application has to set the buffer address and +* length fields to initiate the transfer in respective channel. +* +* Transactions +* +* The object used to describe a transaction is referred to as a Buffer +* Descriptor (BD). Buffer descriptors are allocated in the user application. +* The user application needs to set buffer address, transfer length, and +* control information for this transfer. The control information includes +* SOF and EOF. Definition of those masks are in xaxidma_hw.h +* +* Scatter-Gather DMA +* +* SGDMA allows the application to define a list of transactions in memory which +* the hardware will process without further application intervention. During +* this time, the application is free to continue adding more work to keep the +* Hardware busy. +* +* User can check for the completion of transactions through polling the +* hardware, or interrupts. +* +* SGDMA processes whole packets. A packet is defined as a series of +* data bytes that represent a message. SGDMA allows a packet of data to be +* broken up into one or more transactions. For example, take an Ethernet IP +* packet which consists of a 14 byte header followed by a 1 or more bytes of +* payload. With SGDMA, the application may point a BD to the header and another +* BD to the payload, then transfer them as a single message. This strategy can +* make a TCP/IP stack more efficient by allowing it to keep packet header and +* data in different memory regions instead of assembling packets into +* contiguous blocks of memory. +* +* BD Ring Management +* +* BD rings are shared by the software and the hardware. +* +* The hardware expects BDs to be setup as a linked list. The DMA hardware walks +* through the list by following the next pointer field of a completed BD. +* The hardware stops processing when the just completed BD is the same as the +* BD specified in the Tail Ptr register in the hardware. +* +* The last BD in the ring is linked to the first BD in the ring. +* +* All BD management are done inside the driver. The user application should not +* directly modify the BD fields. Modifications to the BD fields should always +* go through the specific API functions. +* +* Within the ring, the driver maintains four groups of BDs. Each group consists +* of 0 or more adjacent BDs: +* +* - Free: The BDs that can be allocated by the application with +* XAxiDma_BdRingAlloc(). +* +* - Pre-process: The BDs that have been allocated with +* XAxiDma_BdRingAlloc(). These BDs are under application control. The +* application modifies these BDs through driver API to prepare them +* for DMA transactions. +* +* - Hardware: The BDs that have been enqueued to hardware with +* XAxiDma_BdRingToHw(). These BDs are under hardware control and may be in a +* state of awaiting hardware processing, in process, or processed by +* hardware. It is considered an error for the application to change BDs +* while they are in this group. Doing so can cause data corruption and lead +* to system instability. +* +* - Post-process: The BDs that have been processed by hardware and have +* been extracted from the Hardware group with XAxiDma_BdRingFromHw(). +* These BDs are under application control. The application can check the +* transfer status of these BDs. The application use XAxiDma_BdRingFree() +* to put them into the Free group. +* +* BDs are expected to transition in the following way for continuous +* DMA transfers: +*
+*
+*         XAxiDma_BdRingAlloc()                   XAxiDma_BdRingToHw()
+*   Free ------------------------> Pre-process ----------------------> Hardware
+*                                                                      |
+*    /|\                                                               |
+*     |   XAxiDma_BdRingFree()                  XAxiDma_BdRingFromHw() |
+*     +--------------------------- Post-process <----------------------+
+*
+* 
+* +* When a DMA transfer is to be cancelled before enqueuing to hardware, +* application can return the requested BDs to the Free group using +* XAxiDma_BdRingUnAlloc(), as shown below: +*
+*
+*         XAxiDma_BdRingUnAlloc()
+*   Free <----------------------- Pre-process
+*
+* 
+* +* The API provides functions for BD list traversal: +* - XAxiDma_BdRingNext() +* - XAxiDma_BdRingPrev() +* +* These functions should be used with care as they do not understand where +* one group ends and another begins. +* +* SGDMA Descriptor Ring Creation +* +* BD ring is created using XAxiDma_BdRingCreate(). The memory for the BD ring +* is allocated by the application, and it has to be contiguous. Physical +* address is required to setup the BD ring. +* +* The applicaiton can use XAxiDma_BdRingMemCalc() to find out the amount of +* memory needed for a certain number of BDs. XAxiDma_BdRingCntCalc() can be +* used to find out how many BDs can be allocated for certain amount of memory. +* +* A helper function, XAxiDma_BdRingClone(), can speed up the BD ring setup if +* the BDs have same types of controls, for example, SOF and EOF. After +* using the XAxiDma_BdRingClone(), the application only needs to setup the +* buffer address and transfer length. Note that certain BDs in one packet, +* for example, the first BD and the last BD, may need to setup special +* control information. +* +* Descriptor Ring State Machine +* +* There are two states of the BD ring: +* +* - HALTED (H), where hardware is not running +* +* - NOT HALTED (NH), where hardware is running +* +* The following diagram shows the state transition for the DMA engine: +* +*
+*   _____ XAxiDma_StartBdRingHw(), or XAxiDma_BdRingStart(),   ______
+*   |   |               or XAxiDma_Resume()                    |    |
+*   | H |----------------------------------------------------->| NH |
+*   |   |<-----------------------------------------------------|    |
+*   -----   XAxiDma_Pause() or XAxiDma_Reset()                 ------
+* 
+* +* Interrupt Coalescing +* +* SGDMA provides control over the frequency of interrupts through interrupt +* coalescing. The DMA engine provides two ways to tune the interrupt +* coalescing: +* +* - The packet threshold counter. Interrupt will fire once the +* programmable number of packets have been processed by the engine. +* +* - The packet delay timer counter. Interrupt will fire once the +* programmable amount of time has passed after processing the last packet, +* and no new packets to process. Note that the interrupt will only fire if +* at least one packet has been processed. +* +* Interrupt +* +* Interrupts are handled by the user application. Each DMA channel has its own +* interrupt ID. The driver provides APIs to enable/disable interrupt, +* and tune the interrupt frequency regarding to packet processing frequency. +* +* Software Initialization +* +* +* To use the Simple mode DMA engine for transfers, the following setup is +* required: +* +* - DMA Initialization using XAxiDma_CfgInitialize() function. This step +* initializes a driver instance for the given DMA engine and resets the +* engine. +* +* - Enable interrupts if chosen to use interrupt mode. The application is +* responsible for setting up the interrupt system, which includes providing +* and connecting interrupt handlers and call back functions, before +* enabling the interrupts. +* +* - Set the buffer address and length field in respective channels to start +* the DMA transfer +* +* To use the SG mode DMA engine for transfers, the following setup are +* required: +* +* - DMA Initialization using XAxiDma_CfgInitialize() function. This step +* initializes a driver instance for the given DMA engine and resets the +* engine. +* +* - BD Ring creation. A BD ring is needed per DMA channel and can be built by +* calling XAxiDma_BdRingCreate(). +* +* - Enable interrupts if chose to use interrupt mode. The application is +* responsible for setting up the interrupt system, which includes providing +* and connecting interrupt handlers and call back functions, before +* enabling the interrupts. +* +* - Start a DMA transfer: Call XAxiDma_BdRingStart() to start a transfer for +* the first time or after a reset, and XAxiDma_BdRingToHw() if the channel +* is already started. Calling XAxiDma_BdRingToHw() when a DMA channel is not +* running will not put the BDs to the hardware, and the BDs will be processed +* later when the DMA channel is started through XAxiDma_BdRingStart(). +* +* How to start DMA transactions +* +* The user application uses XAxiDma_BdRingToHw() to submit BDs to the hardware +* to start DMA transfers. +* +* For both channels, if the DMA engine is currently stopped (using +* XAxiDma_Pause()), the newly added BDs will be accepted but not processed +* until the DMA engine is started, using XAxiDma_BdRingStart(), or resumed, +* using XAxiDma_Resume(). +* +* Software Post-Processing on completed DMA transactions +* +* If the interrupt system has been set up and the interrupts are enabled, +* a DMA channels notifies the software about the completion of a transfer +* through interrupts. Otherwise, the user application can poll for +* completions of the BDs, using XAxiDma_BdRingFromHw() or +* XAxiDma_BdHwCompleted(). +* +* - Once BDs are finished by a channel, the application first needs to fetch +* them from the channel using XAxiDma_BdRingFromHw(). +* +* - On the TX side, the application now could free the data buffers attached to +* those BDs as the data in the buffers has been transmitted. +* +* - On the RX side, the application now could use the received data in the +* buffers attached to those BDs. +* +* - For both channels, completed BDs need to be put back to the Free group +* using XAxiDma_BdRingFree(), so they can be used for future transactions. +* +* - On the RX side, it is the application's responsibility to have BDs ready +* to receive data at any time. Otherwise, the RX channel refuses to +* accept any data if it has no RX BDs. +* +* Examples +* +* We provide five examples to show how to use the driver API: +* - One for SG interrupt mode (xaxidma_example_sg_intr.c), multiple BD/packets transfer +* - One for SG polling mode (xaxidma_example_sg_poll.c), single BD transfer. +* - One for SG polling mode (xaxidma_poll_multi_pkts.c), multiple BD/packets transfer +* - One for simple polling mode (xaxidma_example_simple_poll.c) +* - One for simple Interrupt mode (xaxidma_example_simple_intr.c) +* +* Address Translation +* +* All buffer addresses and BD addresses for the hardware are physical +* addresses. The user application is responsible to provide physical buffer +* address for the BD upon BD ring creation. The user application accesses BD +* through its virtual addess. The driver maintains the address translation +* between the physical and virtual address for BDs. +* +* Cache Coherency +* +* This driver expects all application buffers attached to BDs to be in cache +* coherent memory. If cache is used in the system, buffers for transmit MUST +* be flushed from the cache before passing the associated BD to this driver. +* Buffers for receive MUST be invalidated before accessing the data. +* +* Alignment +* +* For BDs: +* +* Minimum alignment is defined by the constant XAXIDMA_BD_MINIMUM_ALIGNMENT. +* This is the smallest alignment allowed by both hardware and software for them +* to properly work. +* +* If the descriptor ring is to be placed in cached memory, alignment also MUST +* be at least the processor's cache-line size. Otherwise, system instability +* occurs. For alignment larger than the cache line size, multiple cache line +* size alignment is required. +* +* Aside from the initial creation of the descriptor ring (see +* XAxiDma_BdRingCreate()), there are no other run-time checks for proper +* alignment of BDs. +* +* For application data buffers: +* +* Application data buffers may reside on any alignment if DRE is built into the +* hardware. Otherwise, application data buffer must be word-aligned. The word +* is defined by XPAR_AXIDMA_0_M_AXIS_MM2S_TDATA_WIDTH for transmit and +* XPAR_AXIDMA_0_S_AXIS_S2MM_TDATA_WIDTH for receive. +* +* For scatter gather transfers that have more than one BDs in the chain of BDs, +* Each BD transfer length must be multiple of word too. Otherwise, internal +* error happens in the hardware. +* +* Error Handling +* +* The DMA engine will halt on all error conditions. It requires the software +* to do a reset before it can start process new transfer requests. +* +* Restart After Stopping +* +* After the DMA engine has been stopped (through reset or reset after an error) +* the software keeps track of the current BD pointer when reset happens, and +* processing of BDs can be resumed through XAxiDma_BdRingStart(). +* +* Limitations +* +* This driver does not have any mechanisms for mutual exclusion. It is up to +* the application to provide this protection. +* +* Hardware Defaults & Exclusive Use +* +* After the initialization or reset, the DMA engine is in the following +* default mode: +* - All interrupts are disabled. +* +* - Interrupt coalescing counter is 1. +* +* - The DMA engine is not running (halted). Each DMA channel is started +* separately, using XAxiDma_StartBdRingHw() if no BDs are setup for transfer +* yet, or XAxiDma_BdRingStart() otherwise. +* +* The driver has exclusive use of the registers and BDs. All accesses to the +* registers and BDs should go through the driver interface. +* +* Debug Print +* +* To see the debug print for the driver, please put "-DDEBUG" as the extra +* compiler flags in software platform settings. Also comment out the line in +* xdebug.h: "#undef DEBUG". +* +* Changes From v1.00a +* +* . We have changes return type for XAxiDma_BdSetBufAddr() from void to int +* . We added XAxiDma_LookupConfig() so that user does not need to look for the +* hardware settings anymore. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a jz   05/18/10 First release
+* 2.00a jz   08/10/10 Second release, added in xaxidma_g.c, xaxidma_sinit.c,
+*                     updated tcl file, added xaxidma_porting_guide.h
+* 3.00a jz   11/22/10 Support IP core parameters change
+* 4.00a rkv  02/22/11 Added support for simple DMA mode
+*		      New API added for simple DMA mode are
+*			- XAxiDma_Busy
+*			- XAxiDma_SimpleTransfer
+*		      New Macros added for simple DMA mode are
+* 			- XAxiDma_HasSg
+* 			- XAxiDma_IntrEnable
+* 			- XAxiDma_IntrGetEnabled
+* 			- XAxiDma_IntrDisable
+* 			- XAxiDma_IntrGetIrq
+* 			- XAxiDma_IntrAckIrq
+* 5.00a srt  08/25/11  Added support for memory barrier and modified
+*			Cache Macros to have a common API for Microblaze
+*			and Zynq.
+* 6.00a srt  01/24/12 Added support for Multi-Channel DMA mode.
+*		      - Changed APIs:
+*			* XAxiDma_GetRxRing(InstancePtr, RingIndex)
+*			* XAxiDma_Start(XAxiDma * InstancePtr, int RingIndex)
+*			* XAxiDma_Started(XAxiDma * InstancePtr, int RingIndex)
+*			* XAxiDma_Pause(XAxiDma * InstancePtr, int RingIndex)
+*			* XAxiDma_Resume(XAxiDma * InstancePtr, int RingIndex)
+*			* XAxiDma_SimpleTransfer(XAxiDma *InstancePtr,
+*        					u32 BuffAddr, u32 Length,
+*						int Direction, int RingIndex)
+*			* XAxiDma_StartBdRingHw(XAxiDma_BdRing * RingPtr,
+*					int RingIndex)
+*			* XAxiDma_BdRingStart(XAxiDma_BdRing * RingPtr,
+*						 int RingIndex)
+*			* XAxiDma_BdRingToHw(XAxiDma_BdRing * RingPtr,
+*        			int NumBd, XAxiDma_Bd * BdSetPtr, int RingIndex)
+*			* XAxiDma_BdRingDumpRegs(XAxiDma_BdRing * RingPtr,
+*						 int RingIndex)
+*			* XAxiDma_BdRingSnapShotCurrBd(XAxiDma_BdRing * RingPtr,
+*						 int RingIndex)
+*			* XAxiDma_BdSetLength(XAxiDma_Bd *BdPtr,
+*					u32 LenBytes, u32 LengthMask)
+*       		* XAxiDma_BdGetActualLength(BdPtr, LengthMask)
+*			* XAxiDma_BdGetLength(BdPtr, LengthMask)
+*		       - New APIs
+*			* XAxiDma_SelectKeyHole(XAxiDma *InstancePtr,
+*						int Direction, int Select)
+*			* XAxiDma_UpdateBdRingCDesc(XAxiDma_BdRing * RingPtr,
+*						int RingIndex)
+* 7.00a srt  06/18/12  All the APIs changed in v6_00_a are reverted back for
+*		       backward compatibility.
+*			- New API:
+*			  XAxiDma_GetRxIndexRing(InstancePtr, RingIndex)
+* 7.01a srt  10/26/12  - Fixed issue with driver as it fails with IP version
+*		         < 6.00a as the parameter C_NUM_*_CHANNELS is not
+*			 applicable.
+*		       - Changed the logic of MCDMA BD fields Set APIs, to
+*			 clear the field first and then set it.
+* 7.02a srt  01/23/13  Replaced *_TDATA_WIDTH parameters to *_DATA_WIDTH
+*		       (CR 691867)
+*		       Updated DDR base address for IPI designs (CR 703656).
+* 8.0   adk  19/12/13  Updated as per the New Tcl API's
+*	srt  01/29/14  Added support for Micro DMA Mode and cyclic mode of
+*		       operations.
+*		      - New APIs:
+*			* XAxiDma_SelectCyclicMode(XAxiDma *InstancePtr,
+*						int Direction, int Select)
+ *			* XAxiDma_BdSetBufAddrMicroMode(XAxiDma_Bd*, u32)
+* 8.1   adk  20/01/15  Added support for peripheral test. Created the self
+*		       test example to include it on peripheral test's(CR#823144).
+* 8.1   adk  29/01/15  Added the sefltest api (XAxiDma_Selftest) to the driver source files
+* 		      (xaxidma_selftest.c) and called this from the selftest example
+* 9.0 	adk  27/07/15  Added support for 64-bit Addressing.
+* 9.0   adk  19/08/15  Fixed CR#873125 DMA SG Mode example tests are failing on
+*		       HW in 2015.3.
+* 9.1   sk   11/10/15 Used UINTPTR instead of u32 for Baseaddress CR# 867425.
+* 9.3   adk  26/07/16 Reduce the size of the buffer descriptor to 64 bytes.
+*       ms   01/23/17 Modified xil_printf statement in main function for all
+*            examples to ensure that "Successfully ran" and "Failed" strings
+*            are available in all examples. This is a fix for CR-965028.
+*       ms   03/17/17 Added readme.txt file in examples folder for doxygen
+*                     generation.
+*       ms   04/05/17 Modified Comment lines in functions to recognize
+*                     it as documentation block and added tabspace at return
+*                     statements in functions of axidma examples for proper
+*                     documentation while generating doxygen.
+*                     Modified readme file in examples folder.
+* 9.4  adk   25/07/17 Added example for cyclic dma mode CR#974218.
+*      adk   08/08/17 Fixed CR#980607 Can't select individual AXI DMA code examples.
+*		      Fixed compilation warning in the driver
+* 9.5  adk   17/10/17 Fixed CR#987026 mulit packet example fails on A53.
+* 	     26/10/17 Fixed CR#987214 Fix race condition in the XAxiDma_Reset().
+*      rsp   11/01/17 Fixed CR#988210 Add interface to do config lookup based
+*                     on base address.
+*      adk   13/11/17 Fixed CR#989455 multi-channel interrupt example fails on A53.
+* 9.6  rsp   01/11/18 Fixed CR#976392 In XAxiDma struct use UINTPTR for RegBase.
+*                     In XAxiDma_LookupConfigBaseAddr() use UINTPTR for Baseaddr.
+* 9.7  rsp   04/25/18 Add SgLengthWidth member in dma config structure. CR #1000474
+* 
+* +******************************************************************************/ + +#ifndef XAXIDMA_H_ /* prevent circular inclusions */ +#define XAXIDMA_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ +#include "xaxidma_bdring.h" +#ifdef __MICROBLAZE__ +#include "xenv.h" +#else +#include +#include "xil_cache.h" +#endif + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + +/** + * The XAxiDma driver instance data. An instance must be allocated for each DMA + * engine in use. + */ +typedef struct XAxiDma { + UINTPTR RegBase; /* Virtual base address of DMA engine */ + + int HasMm2S; /* Has transmit channel */ + int HasS2Mm; /* Has receive channel */ + int Initialized; /* Driver has been initialized */ + int HasSg; + + XAxiDma_BdRing TxBdRing; /* BD container management for TX channel */ + XAxiDma_BdRing RxBdRing[16]; /* BD container management for RX channel */ + int TxNumChannels; + int RxNumChannels; + int MicroDmaMode; + int AddrWidth; /**< Address Width */ +} XAxiDma; + +/** + * The configuration structure for AXI DMA engine + * + * This structure passes the hardware building information to the driver + */ +typedef struct { + u32 DeviceId; + UINTPTR BaseAddr; + + int HasStsCntrlStrm; + int HasMm2S; + int HasMm2SDRE; + int Mm2SDataWidth; + int HasS2Mm; + int HasS2MmDRE; + int S2MmDataWidth; + int HasSg; + int Mm2sNumChannels; + int S2MmNumChannels; + int Mm2SBurstSize; + int S2MmBurstSize; + int MicroDmaMode; + int AddrWidth; /**< Address Width */ + int SgLengthWidth; +} XAxiDma_Config; + + +/***************** Macros (Inline Functions) Definitions *********************/ +/*****************************************************************************/ +/** +* Get Transmit (Tx) Ring ptr +* +* Warning: This has a different API than the LLDMA driver. It now returns +* the pointer to the BD ring. +* +* @param InstancePtr is a pointer to the DMA engine instance to be +* worked on. +* +* @return Pointer to the Tx Ring +* +* @note C-style signature: +* XAxiDma_BdRing * XAxiDma_GetTxRing(XAxiDma * InstancePtr) +* This function is used only when system is configured as SG mode +* +*****************************************************************************/ +#define XAxiDma_GetTxRing(InstancePtr) \ + (&((InstancePtr)->TxBdRing)) + +/*****************************************************************************/ +/** +* Get Receive (Rx) Ring ptr +* +* Warning: This has a different API than the LLDMA driver. It now returns +* the pointer to the BD ring. +* +* @param InstancePtr is a pointer to the DMA engine instance to be +* worked on. +* +* @return Pointer to the Rx Ring +* +* @note +* C-style signature: +* XAxiDma_BdRing * XAxiDma_GetRxRing(XAxiDma * InstancePtr) +* This function is used only when system is configured as SG mode +* +*****************************************************************************/ +#define XAxiDma_GetRxRing(InstancePtr) \ + (&((InstancePtr)->RxBdRing[0])) + +/*****************************************************************************/ +/** +* Get Receive (Rx) Ring ptr of a Index +* +* Warning: This has a different API than the LLDMA driver. It now returns +* the pointer to the BD ring. +* +* @param InstancePtr is a pointer to the DMA engine instance to be +* worked on. +* @param RingIndex is the channel Index. +* +* @return Pointer to the Rx Ring +* +* @note +* C-style signature: +* XAxiDma_BdRing * XAxiDma_GetRxIndexRing(XAxiDma * InstancePtr, + int RingIndex) +* This function is used only when system is configured as SG mode +* +*****************************************************************************/ +#define XAxiDma_GetRxIndexRing(InstancePtr, RingIndex) \ + (&((InstancePtr)->RxBdRing[RingIndex])) + +/*****************************************************************************/ +/** +* This function checks whether system is configured as Simple or +* Scatter Gather mode +* +* @param InstancePtr is a pointer to the DMA engine instance to be +* worked on. +* +* @return +* - TRUE if configured as SG mode +* - FALSE if configured as simple mode +* +* @note None +* +*****************************************************************************/ +#define XAxiDma_HasSg(InstancePtr) ((InstancePtr)->HasSg) ? TRUE : FALSE + +/*****************************************************************************/ +/** + * This function enables interrupts specified by the Mask in specified + * direction, Interrupts that are not in the mask are not affected. + * + * @param InstancePtr is the driver instance we are working on + * @param Mask is the mask for the interrupts to be enabled + * @param Direction is DMA transfer direction, valid values are + * - XAXIDMA_DMA_TO_DEVICE. + * - XAXIDMA_DEVICE_TO_DMA. + * @return None + * + * @note None + * + *****************************************************************************/ +#define XAxiDma_IntrEnable(InstancePtr, Mask, Direction) \ + XAxiDma_WriteReg((InstancePtr)->RegBase + \ + (XAXIDMA_RX_OFFSET * Direction), XAXIDMA_CR_OFFSET, \ + (XAxiDma_ReadReg((InstancePtr)->RegBase + \ + (XAXIDMA_RX_OFFSET * Direction), XAXIDMA_CR_OFFSET)) \ + | (Mask & XAXIDMA_IRQ_ALL_MASK)) + + +/*****************************************************************************/ +/** + * This function gets the mask for the interrupts that are currently enabled + * + * @param InstancePtr is the driver instance we are working on + * @param Direction is DMA transfer direction, valid values are + * - XAXIDMA_DMA_TO_DEVICE. + * - XAXIDMA_DEVICE_TO_DMA. + * + * @return The bit mask for the interrupts that are currently enabled + * + * @note None + * + *****************************************************************************/ +#define XAxiDma_IntrGetEnabled(InstancePtr, Direction) \ + XAxiDma_ReadReg((InstancePtr)->RegBase + \ + (XAXIDMA_RX_OFFSET * Direction), XAXIDMA_CR_OFFSET) &\ + XAXIDMA_IRQ_ALL_MASK) + + + +/*****************************************************************************/ +/** + * This function disables interrupts specified by the Mask. Interrupts that + * are not in the mask are not affected. + * + * @param InstancePtr is the driver instance we are working on + * @param Mask is the mask for the interrupts to be disabled + * @param Direction is DMA transfer direction, valid values are + * - XAXIDMA_DMA_TO_DEVICE. + * - XAXIDMA_DEVICE_TO_DMA. + * @return None + * + * @note None + * + *****************************************************************************/ + #define XAxiDma_IntrDisable(InstancePtr, Mask, Direction) \ + XAxiDma_WriteReg((InstancePtr)->RegBase + \ + (XAXIDMA_RX_OFFSET * Direction), XAXIDMA_CR_OFFSET, \ + (XAxiDma_ReadReg((InstancePtr)->RegBase + \ + (XAXIDMA_RX_OFFSET * Direction), XAXIDMA_CR_OFFSET)) \ + & ~(Mask & XAXIDMA_IRQ_ALL_MASK)) + + +/*****************************************************************************/ +/** + * This function gets the interrupts that are asserted. + * + * @param InstancePtr is the driver instance we are working on + * @param Direction is DMA transfer direction, valid values are + * - XAXIDMA_DMA_TO_DEVICE. + * - XAXIDMA_DEVICE_TO_DMA. + * + * @return The bit mask for the interrupts asserted. + * + * @note None + * + *****************************************************************************/ +#define XAxiDma_IntrGetIrq(InstancePtr, Direction) \ + (XAxiDma_ReadReg((InstancePtr)->RegBase + \ + (XAXIDMA_RX_OFFSET * Direction), XAXIDMA_SR_OFFSET) &\ + XAXIDMA_IRQ_ALL_MASK) + +/*****************************************************************************/ +/** + * This function acknowledges the interrupts that are specified in Mask + * + * @param InstancePtr is the driver instance we are working on + * @param Mask is the mask for the interrupts to be acknowledge + * @param Direction is DMA transfer direction, valid values are + * - XAXIDMA_DMA_TO_DEVICE. + * - XAXIDMA_DEVICE_TO_DMA. + * + * @return None + * + * @note None. + * + *****************************************************************************/ +#define XAxiDma_IntrAckIrq(InstancePtr, Mask, Direction) \ + XAxiDma_WriteReg((InstancePtr)->RegBase + \ + (XAXIDMA_RX_OFFSET * Direction), XAXIDMA_SR_OFFSET, \ + (Mask) & XAXIDMA_IRQ_ALL_MASK) + + + +/************************** Function Prototypes ******************************/ + +/* + * Initialization and control functions in xaxidma.c + */ +XAxiDma_Config *XAxiDma_LookupConfig(u32 DeviceId); +XAxiDma_Config *XAxiDma_LookupConfigBaseAddr(UINTPTR Baseaddr); +int XAxiDma_CfgInitialize(XAxiDma * InstancePtr, XAxiDma_Config *Config); +void XAxiDma_Reset(XAxiDma * InstancePtr); +int XAxiDma_ResetIsDone(XAxiDma * InstancePtr); +int XAxiDma_Pause(XAxiDma * InstancePtr); +int XAxiDma_Resume(XAxiDma * InstancePtr); +u32 XAxiDma_Busy(XAxiDma *InstancePtr,int Direction); +u32 XAxiDma_SimpleTransfer(XAxiDma *InstancePtr, UINTPTR BuffAddr, u32 Length, + int Direction); +int XAxiDma_SelectKeyHole(XAxiDma *InstancePtr, int Direction, int Select); +int XAxiDma_SelectCyclicMode(XAxiDma *InstancePtr, int Direction, int Select); +int XAxiDma_Selftest(XAxiDma * InstancePtr); +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/axidma_v9_9/src/xaxidma_bd.c b/datalink814_sp/bsp/microblaze_ps/libsrc/axidma_v9_9/src/xaxidma_bd.c new file mode 100644 index 0000000..6513d2c --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/axidma_v9_9/src/xaxidma_bd.c @@ -0,0 +1,346 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** + * + * @file xaxidma_bd.c +* @addtogroup axidma_v9_9 +* @{ + * + * Buffer descriptor (BD) management API implementation. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -------------------------------------------------------
+ * 1.00a jz   05/18/10 First release
+ * 2.00a jz   08/10/10 Second release, added in xaxidma_g.c, xaxidma_sinit.c,
+ *                     updated tcl file, added xaxidma_porting_guide.h
+ * 3.00a jz   11/22/10 Support IP core parameters change
+ * 6.00a srt  01/24/12 Added support for Multi-Channel DMA.
+ *		       - Changed APIs
+ *			* XAxiDma_BdSetLength(XAxiDma_Bd *BdPtr,
+ *					u32 LenBytes, u32 LengthMask)
+ *       		* XAxiDma_BdGetActualLength(BdPtr, LengthMask)
+ *			* XAxiDma_BdGetLength(BdPtr, LengthMask)
+ * 8.0   srt  01/29/14 Added support for Micro DMA Mode:
+ *		       - New API
+ *			 XAxiDma_BdSetBufAddrMicroMode(XAxiDma_Bd*, u32)
+ * 9.8   mus  11/05/18 Support 64 bit DMA addresses for Microblaze-X
+ *
+ * 
+ * + *****************************************************************************/ + +#include "xaxidma_bd.h" + +/************************** Function Prototypes ******************************/ + +/*****************************************************************************/ +/** + * Set the length field for the given BD. + * + * Length has to be non-zero and less than LengthMask. + * + * For TX channels, the value passed in should be the number of bytes to + * transmit from the TX buffer associated with the given BD. + * + * For RX channels, the value passed in should be the size of the RX buffer + * associated with the given BD in bytes. This is to notify the RX channel + * the capability of the RX buffer to avoid buffer overflow. + * + * The actual receive length can be equal or smaller than the specified length. + * The actual transfer length will be updated by the hardware in the + * XAXIDMA_BD_STS_OFFSET word in the BD. + * + * @param BdPtr is the BD to operate on. + * @param LenBytes is the requested transfer length + * @param LengthMask is the maximum transfer length + * + * @returns + * - XST_SUCCESS for success + * - XST_INVALID_PARAM for invalid BD length + * + * @note This function can be used only when DMA is in SG mode + * + *****************************************************************************/ +int XAxiDma_BdSetLength(XAxiDma_Bd *BdPtr, u32 LenBytes, u32 LengthMask) +{ + if (LenBytes <= 0 || (LenBytes > LengthMask)) { + + xdbg_printf(XDBG_DEBUG_ERROR, "invalid length %d\n", + (int)LenBytes); + + return XST_INVALID_PARAM; + } + + XAxiDma_BdWrite((BdPtr), XAXIDMA_BD_CTRL_LEN_OFFSET, + ((XAxiDma_BdRead((BdPtr), XAXIDMA_BD_CTRL_LEN_OFFSET) & \ + ~LengthMask)) | LenBytes); + + return XST_SUCCESS; +} +/*****************************************************************************/ +/** + * Set the BD's buffer address. + * + * @param BdPtr is the BD to operate on + * @param Addr is the address to set + * + * @return + * - XST_SUCCESS if buffer address set successfully + * - XST_INVALID_PARAM if hardware has no DRE and address is not + * aligned + * + * @note This function can be used only when DMA is in SG mode + * + *****************************************************************************/ +u32 XAxiDma_BdSetBufAddr(XAxiDma_Bd* BdPtr, UINTPTR Addr) +{ + u32 HasDRE; + u8 WordLen; + + HasDRE = XAxiDma_BdRead(BdPtr, XAXIDMA_BD_HAS_DRE_OFFSET); + WordLen = HasDRE & XAXIDMA_BD_WORDLEN_MASK; + + if (Addr & (WordLen - 1)) { + if ((HasDRE & XAXIDMA_BD_HAS_DRE_MASK) == 0) { + xil_printf("Error set buf addr %x with %x and %x," + " %x\r\n",Addr, HasDRE, (WordLen - 1), + Addr & (WordLen - 1)); + + return XST_INVALID_PARAM; + } + } + +#if defined(__aarch64__) || defined(__arch64__) + XAxiDma_BdWrite64(BdPtr, XAXIDMA_BD_BUFA_OFFSET, Addr); +#else + XAxiDma_BdWrite(BdPtr, XAXIDMA_BD_BUFA_OFFSET, Addr); +#endif + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** + * Set the BD's buffer address when configured for Micro Mode. The buffer + * address should be 4K aligned. + * + * @param BdPtr is the BD to operate on + * @param Addr is the address to set + * + * @return + * - XST_SUCCESS if buffer address set successfully + * - XST_INVALID_PARAM if hardware has no DRE and address is not + * aligned + * + * @note This function can be used only when DMA is in SG mode + * + *****************************************************************************/ +u32 XAxiDma_BdSetBufAddrMicroMode(XAxiDma_Bd* BdPtr, UINTPTR Addr) +{ + if (Addr & XAXIDMA_MICROMODE_MIN_BUF_ALIGN) { + xil_printf("Error set buf addr %x and %x," + " %x\r\n", Addr, XAXIDMA_MICROMODE_MIN_BUF_ALIGN, + Addr & XAXIDMA_MICROMODE_MIN_BUF_ALIGN); + + return XST_INVALID_PARAM; + } + +#if defined(__aarch64__) || defined(__arch64__) + XAxiDma_BdWrite64(BdPtr, XAXIDMA_BD_BUFA_OFFSET, Addr); +#else + XAxiDma_BdWrite(BdPtr, XAXIDMA_BD_BUFA_OFFSET, Addr); +#endif + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** + * Set the APP word at the specified APP word offset for a BD. + * + * @param BdPtr is the BD to operate on. + * @param Offset is the offset inside the APP word, it is valid from + * 0 to 4 + * @param Word is the value to set + * + * @returns + * - XST_SUCCESS for success + * - XST_INVALID_PARAM under following error conditions: + * 1) StsCntrlStrm is not built in hardware + * 2) Offset is not in valid range + * + * @note + * If the hardware build has C_SG_USE_STSAPP_LENGTH set to 1, + * then the last APP word, XAXIDMA_LAST_APPWORD, must have + * non-zero value when AND with 0x7FFFFF. Not doing so will cause + * the hardware to stall. + * This function can be used only when DMA is in SG mode + * + *****************************************************************************/ +int XAxiDma_BdSetAppWord(XAxiDma_Bd* BdPtr, int Offset, u32 Word) +{ + if (XAxiDma_BdRead(BdPtr, XAXIDMA_BD_HAS_STSCNTRL_OFFSET) == 0) { + + xdbg_printf(XDBG_DEBUG_ERROR, "BdRingSetAppWord: no sts cntrl" + "stream in hardware build, cannot set app word\r\n"); + + return XST_INVALID_PARAM; + } + + if ((Offset < 0) || (Offset > XAXIDMA_LAST_APPWORD)) { + + xdbg_printf(XDBG_DEBUG_ERROR, "BdRingSetAppWord: invalid" + "offset %d",Offset); + + return XST_INVALID_PARAM; + } + + XAxiDma_BdWrite(BdPtr, XAXIDMA_BD_USR0_OFFSET + Offset * 4, Word); + + return XST_SUCCESS; +} +/*****************************************************************************/ +/** + * Get the APP word at the specified APP word offset for a BD. + * + * @param BdPtr is the BD to operate on. + * @param Offset is the offset inside the APP word, it is valid from + * 0 to 4 + * @param Valid is to tell the caller whether parameters are valid + * + * @returns + * The APP word. Passed in parameter Valid holds 0 for failure, + * and 1 for success. + * + * @note This function can be used only when DMA is in SG mode + * + *****************************************************************************/ +u32 XAxiDma_BdGetAppWord(XAxiDma_Bd* BdPtr, int Offset, int *Valid) +{ + *Valid = 0; + + if (XAxiDma_BdRead(BdPtr, XAXIDMA_BD_HAS_STSCNTRL_OFFSET) == 0) { + + xdbg_printf(XDBG_DEBUG_ERROR, "BdRingGetAppWord: no sts cntrl " + "stream in hardware build, no app word available\r\n"); + + return (u32)0; + } + + if((Offset < 0) || (Offset > XAXIDMA_LAST_APPWORD)) { + + xdbg_printf(XDBG_DEBUG_ERROR, "BdRingGetAppWord: invalid" + " offset %d", Offset); + + return (u32)0; + } + + *Valid = 1; + + return XAxiDma_BdRead(BdPtr, XAXIDMA_BD_USR0_OFFSET + Offset * 4); +} + +/*****************************************************************************/ +/** + * Set the control bits for a BD. + * + * @param BdPtr is the BD to operate on. + * @param Data is the bit value to set + * + * @return None + * + * @note This function can be used only when DMA is in SG mode + * + *****************************************************************************/ +void XAxiDma_BdSetCtrl(XAxiDma_Bd* BdPtr, u32 Data) +{ + u32 RegValue = XAxiDma_BdRead(BdPtr, XAXIDMA_BD_CTRL_LEN_OFFSET); + + RegValue &= ~XAXIDMA_BD_CTRL_ALL_MASK; + + RegValue |= (Data & XAXIDMA_BD_CTRL_ALL_MASK); + + XAxiDma_BdWrite((BdPtr), XAXIDMA_BD_CTRL_LEN_OFFSET, RegValue); + + return; +} +/*****************************************************************************/ +/** + * Dump the fields of a BD. + * + * @param BdPtr is the BD to operate on. + * + * @return None + * + * @note This function can be used only when DMA is in SG mode + * + *****************************************************************************/ +void XAxiDma_DumpBd(XAxiDma_Bd* BdPtr) +{ + + xil_printf("Dump BD %x:\r\n", (UINTPTR)BdPtr); + xil_printf("\tNext Bd Ptr: %x\r\n", + (unsigned int)XAxiDma_BdRead(BdPtr, XAXIDMA_BD_NDESC_OFFSET)); + xil_printf("\tBuff addr: %x\r\n", + (unsigned int)XAxiDma_BdRead(BdPtr, XAXIDMA_BD_BUFA_OFFSET)); + xil_printf("\tMCDMA Fields: %x\r\n", + (unsigned int)XAxiDma_BdRead(BdPtr, XAXIDMA_BD_MCCTL_OFFSET)); + xil_printf("\tVSIZE_STRIDE: %x\r\n", + (unsigned int)XAxiDma_BdRead(BdPtr, + XAXIDMA_BD_STRIDE_VSIZE_OFFSET)); + xil_printf("\tContrl len: %x\r\n", + (unsigned int)XAxiDma_BdRead(BdPtr, XAXIDMA_BD_CTRL_LEN_OFFSET)); + xil_printf("\tStatus: %x\r\n", + (unsigned int)XAxiDma_BdRead(BdPtr, XAXIDMA_BD_STS_OFFSET)); + + xil_printf("\tAPP 0: %x\r\n", + (unsigned int)XAxiDma_BdRead(BdPtr, XAXIDMA_BD_USR0_OFFSET)); + xil_printf("\tAPP 1: %x\r\n", + (unsigned int)XAxiDma_BdRead(BdPtr, XAXIDMA_BD_USR1_OFFSET)); + xil_printf("\tAPP 2: %x\r\n", + (unsigned int)XAxiDma_BdRead(BdPtr, XAXIDMA_BD_USR2_OFFSET)); + xil_printf("\tAPP 3: %x\r\n", + (unsigned int)XAxiDma_BdRead(BdPtr, XAXIDMA_BD_USR3_OFFSET)); + xil_printf("\tAPP 4: %x\r\n", + (unsigned int)XAxiDma_BdRead(BdPtr, XAXIDMA_BD_USR4_OFFSET)); + + xil_printf("\tSW ID: %x\r\n", + (unsigned int)XAxiDma_BdRead(BdPtr, XAXIDMA_BD_ID_OFFSET)); + xil_printf("\tStsCtrl: %x\r\n", + (unsigned int)XAxiDma_BdRead(BdPtr, + XAXIDMA_BD_HAS_STSCNTRL_OFFSET)); + xil_printf("\tDRE: %x\r\n", + (unsigned int)XAxiDma_BdRead(BdPtr, XAXIDMA_BD_HAS_DRE_OFFSET)); + + xil_printf("\r\n"); +} +/** @} */ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/axidma_v9_9/src/xaxidma_bd.h b/datalink814_sp/bsp/microblaze_ps/libsrc/axidma_v9_9/src/xaxidma_bd.h new file mode 100644 index 0000000..e17aa61 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/axidma_v9_9/src/xaxidma_bd.h @@ -0,0 +1,696 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** + * + * @file xaxidma_bd.h +* @addtogroup axidma_v9_9 +* @{ + * + * Buffer descriptor (BD) management API. + * + * Buffer Descriptors + * + * A BD defines a DMA transaction (see "Transaction" section in xaxidma.h). + * All accesses to a BD go through this set of API. + * + * The XAxiDma_Bd structure defines a BD. The first XAXIDMA_BD_HW_NUM_BYTES + * are shared between hardware and software. + * + * Actual Transfer Length + * + * The actual transfer length for receive could be smaller than the requested + * transfer length. The hardware sets the actual transfer length in the + * completed BD. The API to retrieve the actual transfer length is + * XAxiDma_GetActualLength(). + * + * User IP words + * + * There are 5 user IP words in each BD. + * + * If hardware does not have the StsCntrl stream built in, then these words + * are not usable. Retrieving these words get a NULL pointer and setting + * these words results an error. + * + * Performance + * + * BDs are typically in a non-cached memory space. Reducing the number of + * I/O operations to BDs can improve overall performance of the DMA channel. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- ------------------------------------------------------
+ * 1.00a jz   05/18/10 First release
+ * 2.00a jz   08/10/10 Second release, added in xaxidma_g.c, xaxidma_sinit.c,
+ *                     updated tcl file, added xaxidma_porting_guide.h
+ * 3.00a jz   11/22/10 Support IP core parameters change
+ * 5.00a srt  08/25/11 Changed Cache Macros to have a common API for Zynq
+ *		           and Microblaze.
+ * 6.00a srt  01/24/12 Added APIs to support Multi-Channel DMA:
+ *			XAxiDma_BdSetTId()
+ *			XAxiDma_BdGetTId()
+ *			XAxiDma_BdSetTDest()
+ *			XAxiDma_BdGetTDest()
+ *			XAxiDma_BdSetTUser()
+ *			XAxiDma_BdGetTUser()
+ *			XAxiDma_BdSetARCache()
+ *			XAxiDma_BdGetARCache()
+ *			XAxiDma_BdSetARUser()
+ *			XAxiDma_BdGetARUser()
+ *			XAxiDma_BdSetStride()
+ *			XAxiDma_BdGetStride()
+ *			XAxiDma_BdSetVSize()
+ *			XAxiDma_BdGetVSize()
+ *			- Changed APIs
+ *			XAxiDma_BdGetActualLength(BdPtr, LengthMask)
+ *			XAxiDma_BdGetLength(BdPtr, LengthMask)
+ *			XAxiDma_BdSetLength(XAxiDma_Bd* BdPtr,
+ *					u32 LenBytes, u32 LengthMask)
+ * 7.01a srt  10/26/12  Changed the logic of MCDMA BD fields Set APIs, to
+ *			clear the field first and set it.
+ * 8.0   srt  01/29/14 Added support for Micro DMA Mode.
+ * 9.2   vak  15/04/16 Fixed compilation warnings in axidma driver
+ * 9.8   rsp  07/11/18 Fix cppcheck portability warnings. CR #1006164
+ *
+ * 
+ *****************************************************************************/ + +#ifndef XAXIDMA_BD_H_ /* To prevent circular inclusions */ +#define XAXIDMA_BD_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xaxidma_hw.h" +#include "xstatus.h" +#include "xdebug.h" +#include "xil_cache.h" + +#ifdef __MICROBLAZE__ +#include "xenv.h" +#else +#include +#endif + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/** + * The XAxiDma_Bd is the type for a buffer descriptor (BD). + */ + +typedef u32 XAxiDma_Bd[XAXIDMA_BD_NUM_WORDS]; + + +/***************** Macros (Inline Functions) Definitions *********************/ + +/****************************************************************************** + * Define methods to flush and invalidate cache for BDs should they be + * located in cached memory. + *****************************************************************************/ +#ifdef __aarch64__ +#define XAXIDMA_CACHE_FLUSH(BdPtr) +#define XAXIDMA_CACHE_INVALIDATE(BdPtr) +#else +#define XAXIDMA_CACHE_FLUSH(BdPtr) \ + Xil_DCacheFlushRange((UINTPTR)(BdPtr), XAXIDMA_BD_HW_NUM_BYTES) + +#define XAXIDMA_CACHE_INVALIDATE(BdPtr) \ + Xil_DCacheInvalidateRange((UINTPTR)(BdPtr), XAXIDMA_BD_HW_NUM_BYTES) +#endif + +/*****************************************************************************/ +/** +* +* Read the given Buffer Descriptor word. +* +* @param BaseAddress is the base address of the BD to read +* @param Offset is the word offset to be read +* +* @return The 32-bit value of the field +* +* @note +* C-style signature: +* u32 XAxiDma_BdRead(u32 BaseAddress, u32 Offset) +* +******************************************************************************/ +#define XAxiDma_BdRead(BaseAddress, Offset) \ + (*(u32 *)((UINTPTR)(BaseAddress) + (u32)(Offset))) + +/*****************************************************************************/ +/** +* +* Write the given Buffer Descriptor word. +* +* @param BaseAddress is the base address of the BD to write +* @param Offset is the word offset to be written +* @param Data is the 32-bit value to write to the field +* +* @return None. +* +* @note +* C-style signature: +* void XAxiDma_BdWrite(u32 BaseAddress, u32 RegOffset, u32 Data) +* +******************************************************************************/ +#define XAxiDma_BdWrite(BaseAddress, Offset, Data) \ + (*(u32 *)((UINTPTR)(void *)(BaseAddress) + (u32)(Offset))) = (u32)(Data) + +/*****************************************************************************/ +/** +* +* Write the given Buffer Descriptor word. +* +* @param BaseAddress is the base address of the BD to write +* @param Offset is the word offset to be written +* @param Data is the 64-bit value to write to the field +* +* @return None. +* +* @note +* C-style signature: +* void XAxiDma_BdWrite(u64 BaseAddress, u32 RegOffset, u64 Data) +* +******************************************************************************/ +#define XAxiDma_BdWrite64(BaseAddress, Offset, Data) \ + (*(u64 *)((UINTPTR)(void *)(BaseAddress) + (u32)(Offset))) = (u64)(Data) + +/*****************************************************************************/ +/** + * Zero out BD specific fields. BD fields that are for the BD ring or for the + * system hardware build information are not touched. + * + * @param BdPtr is the BD to operate on + * + * @return None + * + * @note + * C-style signature: + * void XAxiDma_BdClear(XAxiDma_Bd* BdPtr) + * + *****************************************************************************/ +#define XAxiDma_BdClear(BdPtr) \ + memset((void *)(((UINTPTR)(BdPtr)) + XAXIDMA_BD_START_CLEAR), 0, \ + XAXIDMA_BD_BYTES_TO_CLEAR) + +/*****************************************************************************/ +/** + * Get the control bits for the BD + * + * @param BdPtr is the BD to operate on + * + * @return The bit mask for the control of the BD + * + * @note + * C-style signature: + * u32 XAxiDma_BdGetCtrl(XAxiDma_Bd* BdPtr) + * + *****************************************************************************/ +#define XAxiDma_BdGetCtrl(BdPtr) \ + (XAxiDma_BdRead((BdPtr), XAXIDMA_BD_CTRL_LEN_OFFSET) \ + & XAXIDMA_BD_CTRL_ALL_MASK) +/*****************************************************************************/ +/** + * Retrieve the status of a BD + * + * @param BdPtr is the BD to operate on + * + * @return Word at offset XAXIDMA_BD_DMASR_OFFSET. Use XAXIDMA_BD_STS_*** + * values defined in xaxidma_hw.h to interpret the returned value + * + * @note + * C-style signature: + * u32 XAxiDma_BdGetSts(XAxiDma_Bd* BdPtr) + * + *****************************************************************************/ +#define XAxiDma_BdGetSts(BdPtr) \ + (XAxiDma_BdRead((BdPtr), XAXIDMA_BD_STS_OFFSET) & \ + XAXIDMA_BD_STS_ALL_MASK) +/*****************************************************************************/ +/** + * Retrieve the length field value from the given BD. The returned value is + * the same as what was written with XAxiDma_BdSetLength(). Note that in the + * this value does not reflect the real length of received data. + * See the comments of XAxiDma_BdSetLength() for more details. To obtain the + * actual transfer length, use XAxiDma_BdGetActualLength(). + * + * @param BdPtr is the BD to operate on. + * @param LengthMask is the Maximum Transfer Length. + * + * @return The length value set in the BD. + * + * @note + * C-style signature: + * u32 XAxiDma_BdGetLength(XAxiDma_Bd* BdPtr) + * + *****************************************************************************/ +#define XAxiDma_BdGetLength(BdPtr, LengthMask) \ + (XAxiDma_BdRead((BdPtr), XAXIDMA_BD_CTRL_LEN_OFFSET) & \ + LengthMask) + + +/*****************************************************************************/ +/** + * Set the ID field of the given BD. The ID is an arbitrary piece of data the + * application can associate with a specific BD. + * + * @param BdPtr is the BD to operate on + * @param Id is a 32 bit quantity to set in the BD + * + * @return None + * + * @note + * C-style signature: + * void XAxiDma_BdSetId(XAxiDma_Bd* BdPtr, void Id) + * + *****************************************************************************/ +#define XAxiDma_BdSetId(BdPtr, Id) \ + (XAxiDma_BdWrite((BdPtr), XAXIDMA_BD_ID_OFFSET, (UINTPTR)(Id))) + + +/*****************************************************************************/ +/** + * Retrieve the ID field of the given BD previously set with XAxiDma_BdSetId. + * + * @param BdPtr is the BD to operate on + * + * @return None + * + * @note + * C-style signature: + * u32 XAxiDma_BdGetId(XAxiDma_Bd* BdPtr) + * + *****************************************************************************/ +#define XAxiDma_BdGetId(BdPtr) (XAxiDma_BdRead((BdPtr), XAXIDMA_BD_ID_OFFSET)) + +/*****************************************************************************/ +/** + * Get the BD's buffer address + * + * @param BdPtr is the BD to operate on + * + * @return None + * + * @note + * C-style signature: + * u32 XAxiDma_BdGetBufAddr(XAxiDma_Bd* BdPtr) + * + *****************************************************************************/ +#define XAxiDma_BdGetBufAddr(BdPtr) \ + (XAxiDma_BdRead((BdPtr), XAXIDMA_BD_BUFA_OFFSET)) + +/*****************************************************************************/ +/** + * Check whether a BD has completed in hardware. This BD has been submitted + * to hardware. The application can use this function to poll for the + * completion of the BD. + * + * This function may not work if the BD is in cached memory. + * + * @param BdPtr is the BD to check on + * + * @return + * - 0 if not complete + * - XAXIDMA_BD_STS_COMPLETE_MASK if completed, may contain + * XAXIDMA_BD_STS_*_ERR_MASK bits. + * + * @note + * C-style signature: + * int XAxiDma_BdHwCompleted(XAxiDma_Bd* BdPtr) + * + *****************************************************************************/ +#define XAxiDma_BdHwCompleted(BdPtr) \ + (XAxiDma_BdRead((BdPtr), XAXIDMA_BD_STS_OFFSET) & \ + XAXIDMA_BD_STS_COMPLETE_MASK) + +/*****************************************************************************/ +/** + * Get the actual transfer length of a BD. The BD has completed in hw. + * + * This function may not work if the BD is in cached memory. + * + * @param BdPtr is the BD to check on + * @param LengthMask is the Maximum Transfer Length. + * + * @return None + * + * @note + * C-style signature: + * int XAxiDma_BdGetActualLength(XAxiDma_Bd* BdPtr) + * + *****************************************************************************/ +#define XAxiDma_BdGetActualLength(BdPtr, LengthMask) \ + (XAxiDma_BdRead((BdPtr), XAXIDMA_BD_STS_OFFSET) & \ + LengthMask) + +/*****************************************************************************/ +/** + * Set the TID field of the TX BD. + * Provides a stream identifier and can be used to differentiate between + * multiple streams of data that are being transferred across the same + * interface. + * + * @param BdPtr is the BD to operate on + * @param TId is a 8 bit quantity to set in the BD + * + * @return None + * + * @note + * C-style signature: + * void XAxiDma_BdSetTId(XAxiDma_Bd* BdPtr, void TId) + * + *****************************************************************************/ +#define XAxiDma_BdSetTId(BdPtr, TId) \ +{ \ + u32 val; \ + val = (XAxiDma_BdRead((BdPtr), XAXIDMA_BD_MCCTL_OFFSET) & \ + ~XAXIDMA_BD_TID_FIELD_MASK); \ + val |= ((u32)(TId) << XAXIDMA_BD_TID_FIELD_SHIFT); \ + XAxiDma_BdWrite((BdPtr), XAXIDMA_BD_MCCTL_OFFSET, val); \ +} + +/*****************************************************************************/ +/** + * Retrieve the TID field of the RX BD previously set with XAxiDma_BdSetTId. + * + * @param BdPtr is the BD to operate on + * + * @return None + * + * @note + * C-style signature: + * u32 XAxiDma_BdGetTId(XAxiDma_Bd* BdPtr) + * + *****************************************************************************/ +#define XAxiDma_BdGetTId(BdPtr) \ + ((XAxiDma_BdRead((BdPtr), XAXIDMA_BD_STS_OFFSET)) & \ + XAXIDMA_BD_TID_FIELD_MASK) + +/*****************************************************************************/ +/** + * Set the TDEST field of the TX BD. + * Provides coarse routing information for the data stream. + * + * @param BdPtr is the BD to operate on + * @param TDest is a 8 bit quantity to set in the BD + * + * @return None + * + * @note + * C-style signature: + * void XAxiDma_BdSetTDest(XAxiDma_Bd* BdPtr, void TDest) + * + *****************************************************************************/ +#define XAxiDma_BdSetTDest(BdPtr, TDest) \ +{ \ + u32 val; \ + val = (XAxiDma_BdRead((BdPtr), XAXIDMA_BD_MCCTL_OFFSET) & \ + ~XAXIDMA_BD_TDEST_FIELD_MASK); \ + val |= ((u32)(TDest) << XAXIDMA_BD_TDEST_FIELD_SHIFT); \ + XAxiDma_BdWrite((BdPtr), XAXIDMA_BD_MCCTL_OFFSET, val); \ +} + +/*****************************************************************************/ +/** + * Retrieve the TDest field of the RX BD previously set with i + * XAxiDma_BdSetTDest. + * + * @param BdPtr is the BD to operate on + * + * @return None + * + * @note + * C-style signature: + * u32 XAxiDma_BdGetTDest(XAxiDma_Bd* BdPtr) + * + *****************************************************************************/ +#define XAxiDma_BdGetTDest(BdPtr) \ + ((XAxiDma_BdRead((BdPtr), XAXIDMA_BD_STS_OFFSET)) & \ + XAXIDMA_BD_TDEST_FIELD_MASK) + +/*****************************************************************************/ +/** + * Set the TUSER field of the TX BD. + * User defined sideband signaling. + * + * @param BdPtr is the BD to operate on + * @param TUser is a 8 bit quantity to set in the BD + * + * @return None + * + * @note + * C-style signature: + * void XAxiDma_BdSetTUser(XAxiDma_Bd* BdPtr, void TUser) + * + *****************************************************************************/ +#define XAxiDma_BdSetTUser(BdPtr, TUser) \ +{ \ + u32 val; \ + val = (XAxiDma_BdRead((BdPtr), XAXIDMA_BD_MCCTL_OFFSET) & \ + ~XAXIDMA_BD_TUSER_FIELD_MASK); \ + val |= ((u32)(TUser) << XAXIDMA_BD_TUSER_FIELD_SHIFT); \ + XAxiDma_BdWrite((BdPtr), XAXIDMA_BD_MCCTL_OFFSET, val); \ +} + +/*****************************************************************************/ +/** + * Retrieve the TUSER field of the RX BD previously set with + * XAxiDma_BdSetTUser. + * + * @param BdPtr is the BD to operate on + * + * @return None + * + * @note + * C-style signature: + * u32 XAxiDma_BdGetTUser(XAxiDma_Bd* BdPtr) + * + *****************************************************************************/ +#define XAxiDma_BdGetTUser(BdPtr) \ + ((XAxiDma_BdRead((BdPtr), XAXIDMA_BD_STS_OFFSET)) & \ + XAXIDMA_BD_TUSER_FIELD_MASK) + +/*****************************************************************************/ +/** + * Set the ARCACHE field of the given BD. + * This signal provides additional information about the cacheable + * characteristics of the transfer. + * + * @param BdPtr is the BD to operate on + * @param ARCache is a 8 bit quantity to set in the BD + * + * @return None + * + * @note + * C-style signature: + * void XAxiDma_BdSetARCache(XAxiDma_Bd* BdPtr, void ARCache) + * + *****************************************************************************/ +#define XAxiDma_BdSetARCache(BdPtr, ARCache) \ +{ \ + u32 val; \ + val = (XAxiDma_BdRead((BdPtr), XAXIDMA_BD_MCCTL_OFFSET) & \ + ~XAXIDMA_BD_ARCACHE_FIELD_MASK); \ + val |= ((u32)(ARCache) << XAXIDMA_BD_ARCACHE_FIELD_SHIFT); \ + XAxiDma_BdWrite((BdPtr), XAXIDMA_BD_MCCTL_OFFSET, val); \ +} + +/*****************************************************************************/ +/** + * Retrieve the ARCACHE field of the given BD previously set with + * XAxiDma_BdSetARCache. + * + * @param BdPtr is the BD to operate on + * + * @return None + * + * @note + * C-style signature: + * u32 XAxiDma_BdGetARCache(XAxiDma_Bd* BdPtr) + * + *****************************************************************************/ +#define XAxiDma_BdGetARCache(BdPtr) \ + ((XAxiDma_BdRead((BdPtr), XAXIDMA_BD_MCCTL_OFFSET)) & \ + XAXIDMA_BD_ARCACHE_FIELD_MASK) + + +/*****************************************************************************/ +/** + * Set the ARUSER field of the given BD. + * Sideband signals used for user defined information. + * + * @param BdPtr is the BD to operate on + * @param ARUser is a 8 bit quantity to set in the BD + * + * @return None + * + * @note + * C-style signature: + * void XAxiDma_BdSetARUser(XAxiDma_Bd* BdPtr, void ARUser) + * + *****************************************************************************/ +#define XAxiDma_BdSetARUser(BdPtr, ARUser) \ +{ \ + u32 val; \ + val = (XAxiDma_BdRead((BdPtr), XAXIDMA_BD_MCCTL_OFFSET) & \ + ~XAXIDMA_BD_ARUSER_FIELD_MASK); \ + val |= ((u32)(ARUser) << XAXIDMA_BD_ARUSER_FIELD_SHIFT); \ + XAxiDma_BdWrite((BdPtr), XAXIDMA_BD_MCCTL_OFFSET, val); \ +} + + +/*****************************************************************************/ +/** + * Retrieve the ARUSER field of the given BD previously set with + * XAxiDma_BdSetARUser. + * + * @param BdPtr is the BD to operate on + * + * @return None + * + * @note + * C-style signature: + * u32 XAxiDma_BdGetARUser(XAxiDma_Bd* BdPtr) + * + *****************************************************************************/ +#define XAxiDma_BdGetARUser(BdPtr) \ + ((XAxiDma_BdRead((BdPtr), XAXIDMA_BD_MCCTL_OFFSET)) & \ + XAXIDMA_BD_ARUSER_FIELD_MASK) + +/*****************************************************************************/ +/** + * Set the STRIDE field of the given BD. + * It is the address distance between the first address of successive + * horizontal reads. + * + * @param BdPtr is the BD to operate on + * @param Stride is a 32 bit quantity to set in the BD + * + * @return None + * + * @note + * C-style signature: + * void XAxiDma_BdSetStride(XAxiDma_Bd* BdPtr, void Stride) + * + *****************************************************************************/ +#define XAxiDma_BdSetStride(BdPtr, Stride) \ +{ \ + u32 val; \ + val = (XAxiDma_BdRead((BdPtr), XAXIDMA_BD_STRIDE_VSIZE_OFFSET) & \ + ~XAXIDMA_BD_STRIDE_FIELD_MASK); \ + val |= ((u32)(Stride) << XAXIDMA_BD_STRIDE_FIELD_SHIFT); \ + XAxiDma_BdWrite((BdPtr), XAXIDMA_BD_STRIDE_VSIZE_OFFSET, val); \ +} + +/*****************************************************************************/ +/** + * Retrieve the STRIDE field of the given BD previously set with + * XAxiDma_BdSetStride. + * + * @param BdPtr is the BD to operate on + * + * @return None + * + * @note + * C-style signature: + * u32 XAxiDma_BdGetStride(XAxiDma_Bd* BdPtr) + * + *****************************************************************************/ +#define XAxiDma_BdGetStride(BdPtr) \ + ((XAxiDma_BdRead((BdPtr), XAXIDMA_BD_STRIDE_VSIZE_OFFSET)) & \ + XAXIDMA_BD_STRIDE_FIELD_MASK) + +/*****************************************************************************/ +/** + * Set the VSIZE field of the given BD. + * Number of horizontal lines for strided access. + * + * @param BdPtr is the BD to operate on + * @param VSize is a 32 bit quantity to set in the BD + * + * @return None + * + * @note + * C-style signature: + * void XAxiDma_BdSetVSize(XAxiDma_Bd* BdPtr, void VSize) + * + *****************************************************************************/ +#define XAxiDma_BdSetVSize(BdPtr, VSize) \ +{ \ + u32 val; \ + val = (XAxiDma_BdRead((BdPtr), XAXIDMA_BD_STRIDE_VSIZE_OFFSET) & \ + ~XAXIDMA_BD_VSIZE_FIELD_MASK); \ + val |= ((u32)(VSize) << XAXIDMA_BD_VSIZE_FIELD_SHIFT); \ + XAxiDma_BdWrite((BdPtr), XAXIDMA_BD_STRIDE_VSIZE_OFFSET, val); \ +} + +/*****************************************************************************/ +/** + * Retrieve the STRIDE field of the given BD previously set with + * XAxiDma_BdSetVSize. + * + * @param BdPtr is the BD to operate on + * + * @return None + * + * @note + * C-style signature: + * u32 XAxiDma_BdGetVSize(XAxiDma_Bd* BdPtr) + * + *****************************************************************************/ +#define XAxiDma_BdGetVSize(BdPtr) \ + ((XAxiDma_BdRead((BdPtr), XAXIDMA_BD_STRIDE_VSIZE_OFFSET)) & \ + XAXIDMA_BD_VSIZE_FIELD_MASK) + +/*****************************************************************************/ + +/************************** Function Prototypes ******************************/ + +int XAxiDma_BdSetLength(XAxiDma_Bd* BdPtr, u32 LenBytes, u32 LengthMask); +u32 XAxiDma_BdSetBufAddr(XAxiDma_Bd* BdPtr, UINTPTR Addr); +u32 XAxiDma_BdSetBufAddrMicroMode(XAxiDma_Bd* BdPtr, UINTPTR Addr); +int XAxiDma_BdSetAppWord(XAxiDma_Bd * BdPtr, int Offset, u32 Word); +u32 XAxiDma_BdGetAppWord(XAxiDma_Bd * BdPtr, int Offset, int *Valid); +void XAxiDma_BdSetCtrl(XAxiDma_Bd *BdPtr, u32 Data); + +/* Debug utility + */ +void XAxiDma_DumpBd(XAxiDma_Bd* BdPtr); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/axidma_v9_9/src/xaxidma_bdring.c b/datalink814_sp/bsp/microblaze_ps/libsrc/axidma_v9_9/src/xaxidma_bdring.c new file mode 100644 index 0000000..1a50af9 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/axidma_v9_9/src/xaxidma_bdring.c @@ -0,0 +1,1615 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xaxidma_bdring.c +* @addtogroup axidma_v9_9 +* @{ +* +* This file implements buffer descriptor ring related functions. For more +* information on how to manage the BD ring, please see xaxidma.h. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a jz   05/18/10 First release
+* 2.00a jz   08/10/10 Second release, added in xaxidma_g.c, xaxidma_sinit.c,
+*                     updated tcl file, added xaxidma_porting_guide.h
+* 3.00a jz   11/22/10 Support IP core parameters change
+* 5.00a srt  08/25/11 Added support for memory barrier.
+* 6.00a srt  01/24/12 Added support for Multi-Channel DMA.
+*		      - New API
+*			* XAxiDma_UpdateBdRingCDesc(XAxiDma_BdRing * RingPtr,
+*						int RingIndex)
+*		      - Changed APIs
+*			* XAxiDma_StartBdRingHw(XAxiDma_BdRing * RingPtr,
+*					int RingIndex)
+*			* XAxiDma_BdRingStart(XAxiDma_BdRing * RingPtr,
+*						 int RingIndex)
+*			* XAxiDma_BdRingToHw(XAxiDma_BdRing * RingPtr,
+*        			int NumBd, XAxiDma_Bd * BdSetPtr, int RingIndex)
+*			* XAxiDma_BdRingDumpRegs(XAxiDma_BdRing * RingPtr,
+*						 int RingIndex)
+*			* XAxiDma_BdRingSnapShotCurrBd(XAxiDma_BdRing * RingPtr,
+*						 int RingIndex)
+* 7.00a srt  06/18/12  All the APIs changed in v6_00_a are reverted back for
+*		       backward compatibility.
+* 9.6   rsp  01/11/18  Use UINTPTR for all RegBase instances CR#976392
+*       rsp  01/17/18  Use virtual address for register read/write.
+*                      In _BdRingCreate() assign VA to BdaRestart CR#976392
+* 9.9   rsp  02/05/19  Fix XAxiDma_BdRingFromHw implementation for cyclic mode.
+*
+* 
+******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xaxidma_bdring.h" + +/************************** Constant Definitions *****************************/ +/* Use 100 milliseconds for 100 MHz + * This interval is sufficient for hardware to finish 40MB transfer with + * 32-bit bus. + */ +#define XAXIDMA_STOP_TIMEOUT 500000 /* about 100 milliseconds on 100MHz */ + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ +/* The following macros are helper functions inside this file. + */ + +/****************************************************************************** + * Compute the physical address of a descriptor from its virtual address + * + * @param BdPtr is the virtual address of the BD + * + * @returns Physical address of BdPtr + * + * @note Assume virtual and physical mapping is flat. + * RingPtr is an implicit parameter + * + *****************************************************************************/ +#define XAXIDMA_VIRT_TO_PHYS(BdPtr) \ + ((UINTPTR)(BdPtr) + (RingPtr->FirstBdPhysAddr - RingPtr->FirstBdAddr)) + +/****************************************************************************** + * Move the BdPtr argument ahead an arbitrary number of BDs wrapping around + * to the beginning of the ring if needed. + * + * We know if a wraparound should occur if the new BdPtr is greater than + * the high address in the ring OR if the new BdPtr crosses the 0xFFFFFFFF + * to 0 boundary. + * + * @param RingPtr is the ring BdPtr appears in + * @param BdPtr on input is the starting BD position and on output is the + * final BD position + * @param NumBd is the number of BD spaces to increment + * + * @returns None + * + * @note This function can be used only when DMA is in SG mode + * + *****************************************************************************/ +#define XAXIDMA_RING_SEEKAHEAD(RingPtr, BdPtr, NumBd) \ + { \ + UINTPTR Addr = (UINTPTR)(void *)(BdPtr); \ + \ + Addr += ((RingPtr)->Separation * (NumBd)); \ + if ((Addr > (RingPtr)->LastBdAddr) || ((UINTPTR)(BdPtr) > Addr)) \ + { \ + Addr -= (RingPtr)->Length; \ + } \ + \ + (BdPtr) = (XAxiDma_Bd*)(void *)Addr; \ + } +/****************************************************************************** + * Move the BdPtr argument backwards an arbitrary number of BDs wrapping + * around to the end of the ring if needed. + * + * We know if a wraparound should occur if the new BdPtr is less than + * the base address in the ring OR if the new BdPtr crosses the 0xFFFFFFFF + * to 0 boundary. + * + * @param RingPtr is the ring BdPtr appears in + * @param BdPtr on input is the starting BD position and on output is the + * final BD position + * @param NumBd is the number of BD spaces to increment + * + * @returns None + * + * @note This function can be used only when DMA is in SG mode + * + *****************************************************************************/ +#define XAXIDMA_RING_SEEKBACK(RingPtr, BdPtr, NumBd) \ + { \ + UINTPTR Addr = (UINTPTR)(BdPtr); \ + \ + Addr -= ((RingPtr)->Separation * (NumBd)); \ + if ((Addr < (RingPtr)->FirstBdAddr) || ((UINTPTR)(BdPtr) < Addr)) \ + { \ + Addr += (RingPtr)->Length; \ + } \ + \ + (BdPtr) = (XAxiDma_Bd*)Addr; \ + } + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + + +/*****************************************************************************/ +/** + * Update Current Descriptor + * + * @param RingPtr is the Channel instance to be worked on + * + * @return + * - XST_SUCCESS upon success + * - XST_DMA_ERROR if no valid BD available to put into current + * BD register + * + * @note This function can be used only when DMA is in SG mode + * + *****************************************************************************/ +int XAxiDma_UpdateBdRingCDesc(XAxiDma_BdRing* RingPtr) +{ + UINTPTR RegBase; + UINTPTR BdPtr; + int RingIndex = RingPtr->RingIndex; + + /* BD list has yet to be created for this channel */ + if (RingPtr->AllCnt == 0) { + + xdbg_printf(XDBG_DEBUG_ERROR, "BdRingStart: no bds\r\n"); + + return XST_DMA_SG_NO_LIST; + } + + /* Do nothing if already started */ + if (RingPtr->RunState == AXIDMA_CHANNEL_NOT_HALTED) { + /* Need to update tail pointer if needed (Engine is not + * transferring) + */ + return XST_SUCCESS; + } + + if (!XAxiDma_BdRingHwIsStarted(RingPtr)) { + /* If hardware is not running, then we need to put a valid current + * BD pointer to the current BD register before start the hardware + */ + RegBase = RingPtr->ChanBase; + + /* Put a valid BD pointer in the current BD pointer register + * So, the hardware is ready to go when tail BD pointer is updated + */ + BdPtr = (UINTPTR)(void *)(RingPtr->BdaRestart); + + if (!XAxiDma_BdHwCompleted(BdPtr)) { + if (RingPtr->IsRxChannel) { + if (!RingIndex) { + XAxiDma_WriteReg(RegBase, + XAXIDMA_CDESC_OFFSET, + (XAXIDMA_VIRT_TO_PHYS(BdPtr) & XAXIDMA_DESC_LSB_MASK)); + if (RingPtr->Addr_ext) + XAxiDma_WriteReg(RegBase, + XAXIDMA_CDESC_MSB_OFFSET, + UPPER_32_BITS(XAXIDMA_VIRT_TO_PHYS(BdPtr))); + } + else { + XAxiDma_WriteReg(RegBase, + (XAXIDMA_RX_CDESC0_OFFSET + + (RingIndex - 1) * XAXIDMA_RX_NDESC_OFFSET), + (XAXIDMA_VIRT_TO_PHYS(BdPtr) & XAXIDMA_DESC_LSB_MASK)); + if (RingPtr->Addr_ext) + XAxiDma_WriteReg(RegBase, + (XAXIDMA_RX_CDESC0_MSB_OFFSET + + (RingIndex - 1) * XAXIDMA_RX_NDESC_OFFSET), + UPPER_32_BITS(XAXIDMA_VIRT_TO_PHYS(BdPtr))); + } + } + else { + XAxiDma_WriteReg(RegBase, + XAXIDMA_CDESC_OFFSET, + (XAXIDMA_VIRT_TO_PHYS(BdPtr) & XAXIDMA_DESC_LSB_MASK)); + if (RingPtr->Addr_ext) + XAxiDma_WriteReg(RegBase, XAXIDMA_CDESC_MSB_OFFSET, + UPPER_32_BITS(XAXIDMA_VIRT_TO_PHYS(BdPtr))); + } + } + else { + /* Look for an uncompleted BD + */ + while (XAxiDma_BdHwCompleted(BdPtr)) { + BdPtr = XAxiDma_BdRingNext(RingPtr, BdPtr); + + if ((UINTPTR)BdPtr == (UINTPTR) RingPtr->BdaRestart) { + xdbg_printf(XDBG_DEBUG_ERROR, + "StartBdRingHw: Cannot find valid cdesc\r\n"); + + return XST_DMA_ERROR; + } + + if (!XAxiDma_BdHwCompleted(BdPtr)) { + if (RingPtr->IsRxChannel) { + if (!RingIndex) { + XAxiDma_WriteReg(RegBase, + XAXIDMA_CDESC_OFFSET, + (XAXIDMA_VIRT_TO_PHYS(BdPtr) & XAXIDMA_DESC_LSB_MASK)); + if (RingPtr->Addr_ext) + XAxiDma_WriteReg(RegBase, XAXIDMA_CDESC_MSB_OFFSET, + UPPER_32_BITS(XAXIDMA_VIRT_TO_PHYS(BdPtr))); + } + else { + XAxiDma_WriteReg(RegBase, + (XAXIDMA_RX_CDESC0_OFFSET + + (RingIndex - 1) * XAXIDMA_RX_NDESC_OFFSET), + (XAXIDMA_VIRT_TO_PHYS(BdPtr) & XAXIDMA_DESC_LSB_MASK)); + if (RingPtr->Addr_ext) + XAxiDma_WriteReg(RegBase, + (XAXIDMA_RX_CDESC0_MSB_OFFSET + + (RingIndex - 1) * XAXIDMA_RX_NDESC_OFFSET), + UPPER_32_BITS(XAXIDMA_VIRT_TO_PHYS(BdPtr))); + } + } + else { + XAxiDma_WriteReg(RegBase, + XAXIDMA_CDESC_OFFSET, + (XAXIDMA_VIRT_TO_PHYS(BdPtr) & XAXIDMA_DESC_LSB_MASK)); + if (RingPtr->Addr_ext) + XAxiDma_WriteReg(RegBase, XAXIDMA_CDESC_MSB_OFFSET, + UPPER_32_BITS(XAXIDMA_VIRT_TO_PHYS(BdPtr))); + } + break; + } + } + } + + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** + * Using a memory segment allocated by the caller, This fundtion creates and + * setup the BD ring. + * + * @param RingPtr is the BD ring instance to be worked on. + * @param PhysAddr is the physical base address of application memory + * region. + * @param VirtAddr is the virtual base address of the application memory + * region.If address translation is not being utilized, then + * VirtAddr should be equivalent to PhysAddr. + * @param Alignment governs the byte alignment of individual BDs. This + * function will enforce a minimum alignment of + * XAXIDMA_BD_MINIMUM_ALIGNMENT bytes with no maximum as long as + * it is specified as a power of 2. + * @param BdCount is the number of BDs to setup in the application memory + * region. It is assumed the region is large enough to contain the + * BDs.Refer to the "SGDMA Ring Creation" section in xaxidma.h + * for more information. The minimum valid value for this + * parameter is 1. + * + * @return + * - XST_SUCCESS if initialization was successful + * - XST_NO_FEATURE if the provided instance is a non SGDMA type + * of DMA channel. + * - XST_INVALID_PARAM under any of the following conditions: + * 1) BdCount is not positive + * + * 2) PhysAddr and/or VirtAddr are not aligned to the given + * Alignment parameter; + * + * 3) Alignment parameter does not meet minimum requirements or + * is not a power of 2 value. + * + * - XST_DMA_SG_LIST_ERROR if the memory segment containing the + * list spans over address 0x00000000 in virtual address space. + * + * @note This function can be used only when DMA is in SG mode + * + *****************************************************************************/ +u32 XAxiDma_BdRingCreate(XAxiDma_BdRing *RingPtr, UINTPTR PhysAddr, + UINTPTR VirtAddr, u32 Alignment, int BdCount) +{ + int i; + UINTPTR BdVirtAddr; + UINTPTR BdPhysAddr; + + if (BdCount <= 0) { + + xdbg_printf(XDBG_DEBUG_ERROR, "BdRingCreate: non-positive BD" + " number %d\r\n", BdCount); + + return XST_INVALID_PARAM; + } + + /* In case there is a failure prior to creating list, make sure the + * following attributes are 0 to prevent calls to other SG functions + * from doing anything + */ + RingPtr->AllCnt = 0; + RingPtr->FreeCnt = 0; + RingPtr->HwCnt = 0; + RingPtr->PreCnt = 0; + RingPtr->PostCnt = 0; + RingPtr->Cyclic = 0; + + /* Make sure Alignment parameter meets minimum requirements */ + if (Alignment < XAXIDMA_BD_MINIMUM_ALIGNMENT) { + + xdbg_printf(XDBG_DEBUG_ERROR, "BdRingCreate: alignment too " + "small %d, need to be at least %d\r\n", (int)Alignment, + XAXIDMA_BD_MINIMUM_ALIGNMENT); + + return XST_INVALID_PARAM; + } + + /* Make sure Alignment is a power of 2 */ + if ((Alignment - 1) & Alignment) { + + xdbg_printf(XDBG_DEBUG_ERROR, "BdRingCreate: alignment not" + " valid %d\r\n", (int)Alignment); + + return XST_INVALID_PARAM; + } + + /* Make sure PhysAddr and VirtAddr are on same Alignment */ + if ((PhysAddr % Alignment) || (VirtAddr % Alignment)) { + + xdbg_printf(XDBG_DEBUG_ERROR, "BdRingCreate: Physical address" + " %x and virtual address %x have different alignment\r\n", + (unsigned int)PhysAddr, (unsigned int)VirtAddr); + + return XST_INVALID_PARAM; + } + + /* Compute how many bytes will be between the start of adjacent BDs */ + RingPtr->Separation = + (sizeof(XAxiDma_Bd) + (Alignment - 1)) & ~(Alignment - 1); + + /* Must make sure the ring doesn't span address 0x00000000. If it does, + * then the next/prev BD traversal macros will fail. + */ + if (VirtAddr > (VirtAddr + (RingPtr->Separation * BdCount) - 1)) { + + xdbg_printf(XDBG_DEBUG_ERROR, "BdRingCreate: BD space cross " + "0x0\r\n"); + + return XST_DMA_SG_LIST_ERROR; + } + + /* Initial ring setup: + * - Clear the entire space + * - Setup each BD's next pointer with the physical address of the + * next BD + * - Put hardware information in each BD + */ + memset((void *) VirtAddr, 0, (RingPtr->Separation * BdCount)); + + BdVirtAddr = VirtAddr; + BdPhysAddr = PhysAddr + RingPtr->Separation; + for (i = 1; i < BdCount; i++) { + XAxiDma_BdWrite(BdVirtAddr, XAXIDMA_BD_NDESC_OFFSET, + (BdPhysAddr & XAXIDMA_DESC_LSB_MASK)); + XAxiDma_BdWrite(BdVirtAddr, XAXIDMA_BD_NDESC_MSB_OFFSET, + UPPER_32_BITS(BdPhysAddr)); + + /* Put hardware information in the BDs + */ + XAxiDma_BdWrite(BdVirtAddr, XAXIDMA_BD_HAS_STSCNTRL_OFFSET, + (u32)RingPtr->HasStsCntrlStrm); + + XAxiDma_BdWrite(BdVirtAddr, XAXIDMA_BD_HAS_DRE_OFFSET, + (((u32)(RingPtr->HasDRE)) << XAXIDMA_BD_HAS_DRE_SHIFT) | + RingPtr->DataWidth); + + XAXIDMA_CACHE_FLUSH(BdVirtAddr); + BdVirtAddr += RingPtr->Separation; + BdPhysAddr += RingPtr->Separation; + } + + /* At the end of the ring, link the last BD back to the top */ + XAxiDma_BdWrite(BdVirtAddr, XAXIDMA_BD_NDESC_OFFSET, + (PhysAddr & XAXIDMA_DESC_LSB_MASK)); + XAxiDma_BdWrite(BdVirtAddr, XAXIDMA_BD_NDESC_MSB_OFFSET, + UPPER_32_BITS(PhysAddr)); + + + /* Setup the last BD's hardware information */ + XAxiDma_BdWrite(BdVirtAddr, XAXIDMA_BD_HAS_STSCNTRL_OFFSET, + (u32)RingPtr->HasStsCntrlStrm); + + XAxiDma_BdWrite(BdVirtAddr, XAXIDMA_BD_HAS_DRE_OFFSET, + (((u32)(RingPtr->HasDRE)) << XAXIDMA_BD_HAS_DRE_SHIFT) | + RingPtr->DataWidth); + + /* Setup and initialize pointers and counters */ + RingPtr->RunState = AXIDMA_CHANNEL_HALTED; + RingPtr->FirstBdAddr = VirtAddr; + RingPtr->FirstBdPhysAddr = PhysAddr; + RingPtr->LastBdAddr = BdVirtAddr; + RingPtr->Length = RingPtr->LastBdAddr - RingPtr->FirstBdAddr + + RingPtr->Separation; + RingPtr->AllCnt = BdCount; + RingPtr->FreeCnt = BdCount; + RingPtr->FreeHead = (XAxiDma_Bd *) VirtAddr; + RingPtr->PreHead = (XAxiDma_Bd *) VirtAddr; + RingPtr->HwHead = (XAxiDma_Bd *) VirtAddr; + RingPtr->HwTail = (XAxiDma_Bd *) VirtAddr; + RingPtr->PostHead = (XAxiDma_Bd *) VirtAddr; + RingPtr->BdaRestart = (XAxiDma_Bd *) VirtAddr; + RingPtr->CyclicBd = (XAxiDma_Bd *) malloc(sizeof(XAxiDma_Bd)); + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** + * Clone the given BD into every BD in the ring. Only the fields offset from + * XAXIDMA_BD_START_CLEAR are copied, for XAXIDMA_BD_BYTES_TO_CLEAR bytes. + * This covers: BufferAddr, Control/Buffer length, status, APP words 0 - 4, + * and software ID fields. + * + * This function can be called only when all BDs are in the free group such as + * immediately after creation of the ring. This prevents modification + * of BDs while they are in use by hardware or the application. + * + * @param RingPtr is the BD ring instance to be worked on. + * @param SrcBdPtr is the source BD template to be cloned into the list. + * + * @return + * - XST_SUCCESS if the list was modified. + * - XST_DMA_SG_NO_LIST if a list has not been created. + * - XST_DEVICE_IS_STARTED if the DMA channel has not been stopped. + * - XST_DMA_SG_LIST_ERROR if some of the BDs in this channel are + * under hardware or application control. + * + * @note This function can be used only when DMA is in SG mode + * + *****************************************************************************/ +int XAxiDma_BdRingClone(XAxiDma_BdRing * RingPtr, XAxiDma_Bd * SrcBdPtr) +{ + int i; + UINTPTR CurBd; + u32 Save; + XAxiDma_Bd TmpBd; + + /* Can't do this function if there isn't a ring */ + if (RingPtr->AllCnt == 0) { + + xdbg_printf(XDBG_DEBUG_ERROR, "BdRingClone: no bds\r\n"); + + return XST_DMA_SG_NO_LIST; + } + + /* Can't do this function with the channel running */ + if (RingPtr->RunState == AXIDMA_CHANNEL_NOT_HALTED) { + + xdbg_printf(XDBG_DEBUG_ERROR, "BdRingClone: bd ring started " + "already, cannot do\r\n"); + + return XST_DEVICE_IS_STARTED; + } + + /* Can't do this function with some of the BDs in use */ + if (RingPtr->FreeCnt != RingPtr->AllCnt) { + + xdbg_printf(XDBG_DEBUG_ERROR, "BdRingClone: some bds already " + "in use %d/%d\r\n",RingPtr->FreeCnt, RingPtr->AllCnt); + + return XST_DMA_SG_LIST_ERROR; + } + + /* Make a copy of the template then modify it by clearing + * the complete bit in status/control field + */ + memcpy(&TmpBd, SrcBdPtr, sizeof(XAxiDma_Bd)); + + Save = XAxiDma_BdRead(&TmpBd, XAXIDMA_BD_STS_OFFSET); + Save &= ~XAXIDMA_BD_STS_COMPLETE_MASK; + XAxiDma_BdWrite(&TmpBd, XAXIDMA_BD_STS_OFFSET, Save); + + for (i = 0, CurBd = RingPtr->FirstBdAddr; + i < RingPtr->AllCnt; i++, CurBd += RingPtr->Separation) { + + memcpy((void *)((UINTPTR)CurBd + XAXIDMA_BD_START_CLEAR), + (void *)((UINTPTR)(&TmpBd) + XAXIDMA_BD_START_CLEAR), + XAXIDMA_BD_BYTES_TO_CLEAR); + + XAXIDMA_CACHE_FLUSH(CurBd); + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** + * Start a DMA channel and + * Allow DMA transactions to commence on a given channel if descriptors are + * ready to be processed. + * + * After a DMA channel is started, it is not halted, and it is idle (no active + * DMA transfers). + * + * @param RingPtr is the Channel instance to be worked on + * + * @return + * - XST_SUCCESS upon success + * - XST_DMA_ERROR if no valid BD available to put into current + * BD register + * + * @note This function can be used only when DMA is in SG mode + * + *****************************************************************************/ +int XAxiDma_StartBdRingHw(XAxiDma_BdRing * RingPtr) +{ + UINTPTR RegBase; + int RingIndex = RingPtr->RingIndex; + + if (!XAxiDma_BdRingHwIsStarted(RingPtr)) { + /* Start the hardware + */ + RegBase = RingPtr->ChanBase; + XAxiDma_WriteReg(RegBase, XAXIDMA_CR_OFFSET, + XAxiDma_ReadReg(RegBase, XAXIDMA_CR_OFFSET) + | XAXIDMA_CR_RUNSTOP_MASK); + } + + if (XAxiDma_BdRingHwIsStarted(RingPtr)) { + /* Note as started */ + RingPtr->RunState = AXIDMA_CHANNEL_NOT_HALTED; + + /* If there are unprocessed BDs then we want the channel to begin + * processing right away + */ + if (RingPtr->HwCnt > 0) { + + XAXIDMA_CACHE_INVALIDATE(RingPtr->HwTail); + if (RingPtr->Cyclic) { + XAxiDma_WriteReg(RingPtr->ChanBase, + XAXIDMA_TDESC_OFFSET, + (u32)XAXIDMA_VIRT_TO_PHYS(RingPtr->CyclicBd)); + if (RingPtr->Addr_ext) + XAxiDma_WriteReg(RingPtr->ChanBase, + XAXIDMA_TDESC_MSB_OFFSET, + UPPER_32_BITS(XAXIDMA_VIRT_TO_PHYS(RingPtr->CyclicBd))); + return XST_SUCCESS; + } + + if ((XAxiDma_BdRead(RingPtr->HwTail, + XAXIDMA_BD_STS_OFFSET) & + XAXIDMA_BD_STS_COMPLETE_MASK) == 0) { + if (RingPtr->IsRxChannel) { + if (!RingIndex) { + XAxiDma_WriteReg(RingPtr->ChanBase, + XAXIDMA_TDESC_OFFSET, (XAXIDMA_VIRT_TO_PHYS(RingPtr->HwTail) & XAXIDMA_DESC_LSB_MASK)); + if (RingPtr->Addr_ext) + XAxiDma_WriteReg(RingPtr->ChanBase, XAXIDMA_TDESC_MSB_OFFSET, + UPPER_32_BITS(XAXIDMA_VIRT_TO_PHYS(RingPtr->HwTail))); + } + else { + XAxiDma_WriteReg(RingPtr->ChanBase, + (XAXIDMA_RX_TDESC0_OFFSET + + (RingIndex - 1) * XAXIDMA_RX_NDESC_OFFSET), + (XAXIDMA_VIRT_TO_PHYS(RingPtr->HwTail) & XAXIDMA_DESC_LSB_MASK )); + if (RingPtr->Addr_ext) + XAxiDma_WriteReg(RingPtr->ChanBase, + (XAXIDMA_RX_TDESC0_MSB_OFFSET + + (RingIndex - 1) * XAXIDMA_RX_NDESC_OFFSET), + UPPER_32_BITS(XAXIDMA_VIRT_TO_PHYS(RingPtr->HwTail))); + } + } + else { + XAxiDma_WriteReg(RingPtr->ChanBase, + XAXIDMA_TDESC_OFFSET, (XAXIDMA_VIRT_TO_PHYS(RingPtr->HwTail) & XAXIDMA_DESC_LSB_MASK)); + if (RingPtr->Addr_ext) + XAxiDma_WriteReg(RingPtr->ChanBase, XAXIDMA_TDESC_MSB_OFFSET, + UPPER_32_BITS(XAXIDMA_VIRT_TO_PHYS(RingPtr->HwTail))); + } + } + } + + return XST_SUCCESS; + } + + return XST_DMA_ERROR; +} + +/*****************************************************************************/ +/** + * Start a DMA channel, updates current descriptors and + * Allow DMA transactions to commence on a given channel if descriptors are + * ready to be processed. + * + * After a DMA channel is started, it is not halted, and it is idle (no active + * DMA transfers). + * + * @param RingPtr is the Channel instance to be worked on + * + * @return + * - XST_SUCCESS upon success + * - XST_DMA_ERROR if no valid BD available to put into current + * BD register + * + * @note This function can be used only when DMA is in SG mode + * + *****************************************************************************/ +int XAxiDma_BdRingStart(XAxiDma_BdRing * RingPtr) +{ + int Status; + + Status = XAxiDma_UpdateBdRingCDesc(RingPtr); + if (Status != XST_SUCCESS) { + xdbg_printf(XDBG_DEBUG_ERROR, "BdRingStart: " + "Updating Current Descriptor Failed\n\r"); + return Status; + } + + Status = XAxiDma_StartBdRingHw(RingPtr); + if (Status != XST_SUCCESS) { + xdbg_printf(XDBG_DEBUG_ERROR, "BdRingStart: " + "Starting Hardware Failed\n\r"); + return Status; + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** + * Set interrupt coalescing parameters for the given descriptor ring channel. + * + * @param RingPtr is a pointer to the descriptor ring instance to be + * worked on. + * @param Counter sets the packet counter on the channel. Valid range is + * - 1..255. + * - XAXIDMA_NO_CHANGE to leave this setting unchanged. + * @param Timer sets the waitbound timer on the channel. Valid range is + * - 0..255. + * - XAXIDMA_NO_CHANGE to leave this setting unchanged. + * Each unit depend on hardware building parameter + * C_DLYTMR_RESOLUTION,which is in the range from 0 to 100,000 + * clock cycles. A value of 0 disables the delay interrupt. + * + * @return + * - XST_SUCCESS if interrupt coalescing settings updated + * - XST_FAILURE if Counter or Timer parameters are out of range + * + * @note This function can be used only when DMA is in SG mode + * + *****************************************************************************/ +int XAxiDma_BdRingSetCoalesce(XAxiDma_BdRing *RingPtr, u32 Counter, u32 Timer) +{ + u32 Cr; + + Cr = XAxiDma_ReadReg(RingPtr->ChanBase, XAXIDMA_CR_OFFSET); + + if (Counter != XAXIDMA_NO_CHANGE) { + if ((Counter == 0) || (Counter > 0xFF)) { + + xdbg_printf(XDBG_DEBUG_ERROR, "BdRingSetCoalesce: " + "invalid coalescing threshold %d", (int)Counter); + return XST_FAILURE; + } + + Cr = (Cr & ~XAXIDMA_COALESCE_MASK) | + (Counter << XAXIDMA_COALESCE_SHIFT); + } + + if (Timer != XAXIDMA_NO_CHANGE) { + if (Timer > 0xFF) { + + xdbg_printf(XDBG_DEBUG_ERROR, "BdRingSetCoalesce: " + "invalid delay counter %d", (int)Timer); + + return XST_FAILURE; + } + + Cr = (Cr & ~XAXIDMA_DELAY_MASK) | + (Timer << XAXIDMA_DELAY_SHIFT); + } + + XAxiDma_WriteReg(RingPtr->ChanBase, XAXIDMA_CR_OFFSET, Cr); + + return XST_SUCCESS; +} +/*****************************************************************************/ +/** + * Retrieve current interrupt coalescing parameters from the given descriptor + * ring channel. + * + * @param RingPtr is a pointer to the descriptor ring instance to be + * worked on. + * @param CounterPtr points to a memory location where the current packet + * counter will be written. + * @param TimerPtr points to a memory location where the current + * waitbound timer will be written. + * + * @return The passed in parameters, CounterPtr and TimerPtr, holds the + * references to the return values. + * + * @note This function can be used only when DMA is in SG mode + * + *****************************************************************************/ +void XAxiDma_BdRingGetCoalesce(XAxiDma_BdRing * RingPtr, + u32 *CounterPtr, u32 *TimerPtr) +{ + u32 Cr; + + Cr = XAxiDma_ReadReg(RingPtr->ChanBase, XAXIDMA_CR_OFFSET); + + *CounterPtr = ((Cr & XAXIDMA_COALESCE_MASK) >> XAXIDMA_COALESCE_SHIFT); + *TimerPtr = ((Cr & XAXIDMA_DELAY_MASK) >> XAXIDMA_DELAY_SHIFT); +} + +/*****************************************************************************/ +/** + * Reserve locations in the BD ring. The set of returned BDs may be modified in + * preparation for future DMA transactions. Once the BDs are ready to be + * submitted to hardware, the application must call XAxiDma_BdRingToHw() in the + * same order which they were allocated here. Example: + * + *
+ *        NumBd = 2;
+ *        Status = XDsma_RingBdAlloc(MyRingPtr, NumBd, &MyBdSet);
+ *
+ *        if (Status != XST_SUCCESS)
+ *        {
+ *            // Not enough BDs available for the request
+ *        }
+ *
+ *        CurBd = MyBdSet;
+ *        for (i=0; i
+ *
+ * A more advanced use of this function may allocate multiple sets of BDs.
+ * They must be allocated and given to hardware in the correct sequence:
+ * 
+ *        // Legal
+ *        XAxiDma_BdRingAlloc(MyRingPtr, NumBd1, &MySet1);
+ *        XAxiDma_BdRingToHw(MyRingPtr, NumBd1, MySet1);
+ *
+ *        // Legal
+ *        XAxiDma_BdRingAlloc(MyRingPtr, NumBd1, &MySet1);
+ *        XAxiDma_BdRingAlloc(MyRingPtr, NumBd2, &MySet2);
+ *        XAxiDma_BdRingToHw(MyRingPtr, NumBd1, MySet1);
+ *        XAxiDma_BdRingToHw(MyRingPtr, NumBd2, MySet2);
+ *
+ *        // Not legal
+ *        XAxiDma_BdRingAlloc(MyRingPtr, NumBd1, &MySet1);
+ *        XAxiDma_BdRingAlloc(MyRingPtr, NumBd2, &MySet2);
+ *        XAxiDma_BdRingToHw(MyRingPtr, NumBd2, MySet2);
+ *        XAxiDma_BdRingToHw(MyRingPtr, NumBd1, MySet1);
+ * 
+ * + * Use the API defined in xaxidmabd.h to modify individual BDs. Traversal of + * the BD set can be done using XAxiDma_BdRingNext() and XAxiDma_BdRingPrev(). + * + * @param RingPtr is a pointer to the descriptor ring instance to be + * worked on. + * @param NumBd is the number of BDs to allocate + * @param BdSetPtr is an output parameter, it points to the first BD + * available for modification. + * + * @return + * - XST_SUCCESS if the requested number of BDs were returned in + * the BdSetPtr parameter. + * - XST_INVALID_PARAM if passed in NumBd is not positive + * - XST_FAILURE if there were not enough free BDs to satisfy + * the request. + * + * @note This function should not be preempted by another XAxiDma_BdRing + * function call that modifies the BD space. It is the caller's + * responsibility to provide a mutual exclusion mechanism. + * + * Do not modify more BDs than the number requested with the NumBd + * parameter. Doing so will lead to data corruption and system + * instability. + * + * This function can be used only when DMA is in SG mode + * + *****************************************************************************/ +int XAxiDma_BdRingAlloc(XAxiDma_BdRing * RingPtr, int NumBd, + XAxiDma_Bd ** BdSetPtr) +{ + if (NumBd <= 0) { + + xdbg_printf(XDBG_DEBUG_ERROR, "BdRingAlloc: negative BD " + "number %d\r\n", NumBd); + + return XST_INVALID_PARAM; + } + + /* Enough free BDs available for the request? */ + if (RingPtr->FreeCnt < NumBd) { + xdbg_printf(XDBG_DEBUG_ERROR, + "Not enough BDs to alloc %d/%d\r\n", NumBd, RingPtr->FreeCnt); + + return XST_FAILURE; + } + + /* Set the return argument and move FreeHead forward */ + *BdSetPtr = RingPtr->FreeHead; + XAXIDMA_RING_SEEKAHEAD(RingPtr, RingPtr->FreeHead, NumBd); + RingPtr->FreeCnt -= NumBd; + RingPtr->PreCnt += NumBd; + + return XST_SUCCESS; +} +/*****************************************************************************/ +/** + * Fully or partially undo an XAxiDma_BdRingAlloc() operation. Use this + * function if all the BDs allocated by XAxiDma_BdRingAlloc() could not be + * transferred to hardware with XAxiDma_BdRingToHw(). + * + * This function releases the BDs after they have been allocated but before + * they have been given to hardware. + * + * This function is not the same as XAxiDma_BdRingFree(). The Free function + * returns BDs to the free list after they have been processed by hardware, + * while UnAlloc returns them before being processed by hardware. + * + * There are two scenarios where this function can be used. Full UnAlloc or + * Partial UnAlloc. A Full UnAlloc means all the BDs Alloc'd will be returned: + * + *
+ *    Status = XAxiDma_BdRingAlloc(MyRingPtr, 10, &BdPtr);
+ *        ...
+ *        ...
+ *    if (Error)
+ *    {
+ *        Status = XAxiDma_BdRingUnAlloc(MyRingPtr, 10, &BdPtr);
+ *    }
+ * 
+ * + * A partial UnAlloc means some of the BDs Alloc'd will be returned: + * + *
+ *    Status = XAxiDma_BdRingAlloc(MyRingPtr, 10, &BdPtr);
+ *    BdsLeft = 10;
+ *    CurBdPtr = BdPtr;
+ *
+ *    while (BdsLeft)
+ *    {
+ *       if (Error)
+ *       {
+ *          Status = XAxiDma_BdRingUnAlloc(MyRingPtr, BdsLeft, CurBdPtr);
+ *       }
+ *
+ *       CurBdPtr = XAxiDma_BdRingNext(MyRingPtr, CurBdPtr);
+ *       BdsLeft--;
+ *    }
+ * 
+ * + * A partial UnAlloc must include the last BD in the list that was Alloc'd. + * + * @param RingPtr is a pointer to the descriptor ring instance to be + * worked on. + * @param NumBd is the number of BDs to unallocate + * @param BdSetPtr points to the first of the BDs to be returned. + * + * @return + * - XST_SUCCESS if the BDs were unallocated. + * - XST_INVALID_PARAM if passed in NumBd is negative + * - XST_FAILURE if NumBd parameter was greater that the number of + * BDs in the preprocessing state. + * + * @note This function should not be preempted by another XAxiDma ring + * function call that modifies the BD space. It is the caller's + * responsibility to provide a mutual exclusion mechanism. + * + * This function can be used only when DMA is in SG mode + * + *****************************************************************************/ +int XAxiDma_BdRingUnAlloc(XAxiDma_BdRing * RingPtr, int NumBd, + XAxiDma_Bd * BdSetPtr) +{ + XAxiDma_Bd *TmpBd; + + if (NumBd <= 0) { + + xdbg_printf(XDBG_DEBUG_ERROR, "BdRingUnAlloc: negative BD" + " number %d\r\n", NumBd); + + return XST_INVALID_PARAM; + } + + /* Enough BDs in the preprocessing state for the request? */ + if (RingPtr->PreCnt < NumBd) { + xdbg_printf(XDBG_DEBUG_ERROR, + "Pre-allocated BDs less than requested %d/%d\r\n", + RingPtr->PreCnt, NumBd); + + return XST_FAILURE; + } + + /* The last BD in the BD set must has the FreeHead as its next BD. + * Otherwise, this is not a valid operation. + */ + TmpBd = BdSetPtr; + XAXIDMA_RING_SEEKAHEAD(RingPtr, TmpBd, NumBd); + + if (TmpBd != RingPtr->FreeHead) { + xdbg_printf(XDBG_DEBUG_ERROR, + "Unalloc does not go back to free head\r\n"); + + return XST_FAILURE; + } + + /* Set the return argument and move FreeHead backward */ + XAXIDMA_RING_SEEKBACK(RingPtr, RingPtr->FreeHead, NumBd); + RingPtr->FreeCnt += NumBd; + RingPtr->PreCnt -= NumBd; + + return XST_SUCCESS; +} +/*****************************************************************************/ +/** + * Enqueue a set of BDs to hardware that were previously allocated by + * XAxiDma_BdRingAlloc(). Once this function returns, the argument BD set goes + * under hardware control. Changes to these BDs should be held until they are + * finished by hardware to avoid data corruption and system instability. + * + * For transmit, the set will be rejected if the last BD of the set does not + * mark the end of a packet or the first BD does not mark the start of a packet. + * + * @param RingPtr is a pointer to the descriptor ring instance to be + * worked on. + * @param NumBd is the number of BDs in the set. + * @param BdSetPtr is the first BD of the set to commit to hardware. + * + * @return + * - XST_SUCCESS if the set of BDs was accepted and enqueued to + * hardware + * - XST_INVALID_PARAM if passed in NumBd is negative + * - XST_FAILURE if the set of BDs was rejected because the first + * BD does not have its start-of-packet bit set, or the last BD + * does not have its end-of-packet bit set, or any one of the BDs + * has 0 length. + * - XST_DMA_SG_LIST_ERROR if this function was called out of + * sequence with XAxiDma_BdRingAlloc() + * + * @note This function should not be preempted by another XAxiDma ring + * function call that modifies the BD space. It is the caller's + * responsibility to provide a mutual exclusion mechanism. + * + * This function can be used only when DMA is in SG mode + * + *****************************************************************************/ +int XAxiDma_BdRingToHw(XAxiDma_BdRing * RingPtr, int NumBd, + XAxiDma_Bd * BdSetPtr) +{ + XAxiDma_Bd *CurBdPtr; + int i; + u32 BdCr; + u32 BdSts; + int RingIndex = RingPtr->RingIndex; + + if (NumBd < 0) { + + xdbg_printf(XDBG_DEBUG_ERROR, "BdRingToHw: negative BD number " + "%d\r\n", NumBd); + + return XST_INVALID_PARAM; + } + + /* If the commit set is empty, do nothing */ + if (NumBd == 0) { + return XST_SUCCESS; + } + + /* Make sure we are in sync with XAxiDma_BdRingAlloc() */ + if ((RingPtr->PreCnt < NumBd) || (RingPtr->PreHead != BdSetPtr)) { + + xdbg_printf(XDBG_DEBUG_ERROR, "Bd ring has problems\r\n"); + return XST_DMA_SG_LIST_ERROR; + } + + CurBdPtr = BdSetPtr; + BdCr = XAxiDma_BdGetCtrl(CurBdPtr); + BdSts = XAxiDma_BdGetSts(CurBdPtr); + + /* In case of Tx channel, the first BD should have been marked + * as start-of-frame + */ + if (!(RingPtr->IsRxChannel) && !(BdCr & XAXIDMA_BD_CTRL_TXSOF_MASK)) { + + xdbg_printf(XDBG_DEBUG_ERROR, "Tx first BD does not have " + "SOF\r\n"); + + return XST_FAILURE; + } + + /* Clear the completed status bit + */ + for (i = 0; i < NumBd - 1; i++) { + + /* Make sure the length value in the BD is non-zero. */ + if (XAxiDma_BdGetLength(CurBdPtr, + RingPtr->MaxTransferLen) == 0) { + + xdbg_printf(XDBG_DEBUG_ERROR, "0 length bd\r\n"); + + return XST_FAILURE; + } + + BdSts &= ~XAXIDMA_BD_STS_COMPLETE_MASK; + XAxiDma_BdWrite(CurBdPtr, XAXIDMA_BD_STS_OFFSET, BdSts); + + /* Flush the current BD so DMA core could see the updates */ + XAXIDMA_CACHE_FLUSH(CurBdPtr); + + CurBdPtr = (XAxiDma_Bd *)((void *)XAxiDma_BdRingNext(RingPtr, CurBdPtr)); + BdCr = XAxiDma_BdRead(CurBdPtr, XAXIDMA_BD_CTRL_LEN_OFFSET); + BdSts = XAxiDma_BdRead(CurBdPtr, XAXIDMA_BD_STS_OFFSET); + } + + /* In case of Tx channel, the last BD should have EOF bit set */ + if (!(RingPtr->IsRxChannel) && !(BdCr & XAXIDMA_BD_CTRL_TXEOF_MASK)) { + + xdbg_printf(XDBG_DEBUG_ERROR, "Tx last BD does not have " + "EOF\r\n"); + + return XST_FAILURE; + } + + /* Make sure the length value in the last BD is non-zero. */ + if (XAxiDma_BdGetLength(CurBdPtr, + RingPtr->MaxTransferLen) == 0) { + + xdbg_printf(XDBG_DEBUG_ERROR, "0 length bd\r\n"); + + return XST_FAILURE; + } + + /* The last BD should also have the completed status bit cleared + */ + BdSts &= ~XAXIDMA_BD_STS_COMPLETE_MASK; + XAxiDma_BdWrite(CurBdPtr, XAXIDMA_BD_STS_OFFSET, BdSts); + + /* Flush the last BD so DMA core could see the updates */ + XAXIDMA_CACHE_FLUSH(CurBdPtr); + DATA_SYNC; + + /* This set has completed pre-processing, adjust ring pointers and + * counters + */ + XAXIDMA_RING_SEEKAHEAD(RingPtr, RingPtr->PreHead, NumBd); + RingPtr->PreCnt -= NumBd; + RingPtr->HwTail = CurBdPtr; + RingPtr->HwCnt += NumBd; + + /* If it is running, signal the engine to begin processing */ + if (RingPtr->RunState == AXIDMA_CHANNEL_NOT_HALTED) { + if (RingPtr->Cyclic) { + XAxiDma_WriteReg(RingPtr->ChanBase, + XAXIDMA_TDESC_OFFSET, + (u32)XAXIDMA_VIRT_TO_PHYS(RingPtr->CyclicBd)); + if (RingPtr->Addr_ext) + XAxiDma_WriteReg(RingPtr->ChanBase, + XAXIDMA_TDESC_MSB_OFFSET, + UPPER_32_BITS(XAXIDMA_VIRT_TO_PHYS(RingPtr->CyclicBd))); + return XST_SUCCESS; + } + + if (RingPtr->IsRxChannel) { + if (!RingIndex) { + XAxiDma_WriteReg(RingPtr->ChanBase, + XAXIDMA_TDESC_OFFSET, (XAXIDMA_VIRT_TO_PHYS(RingPtr->HwTail) & XAXIDMA_DESC_LSB_MASK)); + if (RingPtr->Addr_ext) + XAxiDma_WriteReg(RingPtr->ChanBase, XAXIDMA_TDESC_MSB_OFFSET, + UPPER_32_BITS(XAXIDMA_VIRT_TO_PHYS(RingPtr->HwTail))); + } + else { + XAxiDma_WriteReg(RingPtr->ChanBase, + (XAXIDMA_RX_TDESC0_OFFSET + + (RingIndex - 1) * XAXIDMA_RX_NDESC_OFFSET), + (XAXIDMA_VIRT_TO_PHYS(RingPtr->HwTail) & XAXIDMA_DESC_LSB_MASK )); + if (RingPtr->Addr_ext) + XAxiDma_WriteReg(RingPtr->ChanBase, + (XAXIDMA_RX_TDESC0_MSB_OFFSET + + (RingIndex - 1) * XAXIDMA_RX_NDESC_OFFSET), + UPPER_32_BITS(XAXIDMA_VIRT_TO_PHYS(RingPtr->HwTail))); + } + } + else { + XAxiDma_WriteReg(RingPtr->ChanBase, + XAXIDMA_TDESC_OFFSET, (XAXIDMA_VIRT_TO_PHYS(RingPtr->HwTail) & XAXIDMA_DESC_LSB_MASK)); + if (RingPtr->Addr_ext) + XAxiDma_WriteReg(RingPtr->ChanBase, XAXIDMA_TDESC_MSB_OFFSET, + UPPER_32_BITS(XAXIDMA_VIRT_TO_PHYS(RingPtr->HwTail))); + } + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** + * Returns a set of BD(s) that have been processed by hardware. The returned + * BDs may be examined by the application to determine the outcome of the DMA + * transactions. Once the BDs have been examined, the application must call + * XAxiDma_BdRingFree() in the same order which they were retrieved here. + * + * Example: + * + *
+ *        NumBd = XAxiDma_BdRingFromHw(MyRingPtr, XAXIDMA_ALL_BDS, &MyBdSet);
+ *
+ *        if (NumBd == 0)
+ *        {
+ *           // hardware has nothing ready for us yet
+ *        }
+ *
+ *        CurBd = MyBdSet;
+ *        for (i=0; i
+ *
+ * A more advanced use of this function may allocate multiple sets of BDs.
+ * They must be retrieved from hardware and freed in the correct sequence:
+ * 
+ *        // Legal
+ *        XAxiDma_BdRingFromHw(MyRingPtr, NumBd1, &MySet1);
+ *        XAxiDma_BdRingFree(MyRingPtr, NumBd1, MySet1);
+ *
+ *        // Legal
+ *        XAxiDma_BdRingFromHw(MyRingPtr, NumBd1, &MySet1);
+ *        XAxiDma_BdRingFromHw(MyRingPtr, NumBd2, &MySet2);
+ *        XAxiDma_BdRingFree(MyRingPtr, NumBd1, MySet1);
+ *        XAxiDma_BdRingFree(MyRingPtr, NumBd2, MySet2);
+ *
+ *        // Not legal
+ *        XAxiDma_BdRingFromHw(MyRingPtr, NumBd1, &MySet1);
+ *        XAxiDma_BdRingFromHw(MyRingPtr, NumBd2, &MySet2);
+ *        XAxiDma_BdRingFree(MyRingPtr, NumBd2, MySet2);
+ *        XAxiDma_BdRingFree(MyRingPtr, NumBd1, MySet1);
+ * 
+ * + * If hardware has partially completed a packet spanning multiple BDs, then + * none of the BDs for that packet will be included in the results. + * + * @param RingPtr is a pointer to the descriptor ring instance to be + * worked on. + * @param BdLimit is the maximum number of BDs to return in the set. Use + * XAXIDMA_ALL_BDS to return all BDs that have been processed. + * @param BdSetPtr is an output parameter, it points to the first BD + * available for examination. + * + * @return The number of BDs processed by hardware. A value of 0 indicates + * that no data is available. No more than BdLimit BDs will be + * returned. + * + * @note Treat BDs returned by this function as read-only. + * + * This function should not be preempted by another XAxiDma ring + * function call that modifies the BD space. It is the caller's + * responsibility to provide a mutual exclusion mechanism. + * + * This function can be used only when DMA is in SG mode + * + *****************************************************************************/ +int XAxiDma_BdRingFromHw(XAxiDma_BdRing * RingPtr, int BdLimit, + XAxiDma_Bd ** BdSetPtr) +{ + XAxiDma_Bd *CurBdPtr; + int BdCount; + int BdPartialCount; + u32 BdSts; + u32 BdCr; + + CurBdPtr = RingPtr->HwHead; + BdCount = 0; + BdPartialCount = 0; + BdSts = 0; + BdCr = 0; + + /* If no BDs in work group, then there's nothing to search */ + if (RingPtr->HwCnt == 0) { + *BdSetPtr = (XAxiDma_Bd *)NULL; + + return 0; + } + + if (BdLimit > RingPtr->HwCnt) { + BdLimit = RingPtr->HwCnt; + } + + /* Starting at HwHead, keep moving forward in the list until: + * - A BD is encountered with its completed bit clear in the status + * word which means hardware has not completed processing of that + * BD. + * - RingPtr->HwTail is reached + * - The number of requested BDs has been processed + */ + + while (BdCount < BdLimit) { + /* Read the status */ + XAXIDMA_CACHE_INVALIDATE(CurBdPtr); + BdSts = XAxiDma_BdRead(CurBdPtr, XAXIDMA_BD_STS_OFFSET); + BdCr = XAxiDma_BdRead(CurBdPtr, XAXIDMA_BD_CTRL_LEN_OFFSET); + + /* If the hardware still hasn't processed this BD then we are + * done + */ + if (!(BdSts & XAXIDMA_BD_STS_COMPLETE_MASK)) { + break; + } + + BdCount++; + + /* Hardware has processed this BD so check the "last" bit. If + * it is clear, then there are more BDs for the current packet. + * Keep a count of these partial packet BDs. + * + * For tx BDs, EOF bit is in the control word + * For rx BDs, EOF bit is in the status word + */ + if (((!(RingPtr->IsRxChannel) && + (BdCr & XAXIDMA_BD_CTRL_TXEOF_MASK)) || + ((RingPtr->IsRxChannel) && (BdSts & + XAXIDMA_BD_STS_RXEOF_MASK)))) { + + BdPartialCount = 0; + } + else { + BdPartialCount++; + } + + if (RingPtr->Cyclic) { + BdSts = BdSts & ~XAXIDMA_BD_STS_COMPLETE_MASK; + XAxiDma_BdWrite(CurBdPtr, XAXIDMA_BD_STS_OFFSET, BdSts); + XAXIDMA_CACHE_FLUSH(CurBdPtr); + } + + /* Reached the end of the work group */ + if (CurBdPtr == RingPtr->HwTail) { + break; + } + + /* Move on to the next BD in work group */ + CurBdPtr = (XAxiDma_Bd *)((void *)XAxiDma_BdRingNext(RingPtr, CurBdPtr)); + } + + /* Subtract off any partial packet BDs found */ + BdCount -= BdPartialCount; + + /* If BdCount is non-zero then BDs were found to return. Set return + * parameters, update pointers and counters, return success + */ + if (BdCount) { + *BdSetPtr = RingPtr->HwHead; + if (!RingPtr->Cyclic) { + RingPtr->HwCnt -= BdCount; + RingPtr->PostCnt += BdCount; + } + XAXIDMA_RING_SEEKAHEAD(RingPtr, RingPtr->HwHead, BdCount); + + return BdCount; + } + else { + *BdSetPtr = (XAxiDma_Bd *)NULL; + + return 0; + } +} +/*****************************************************************************/ +/** + * Frees a set of BDs that had been previously retrieved with + * XAxiDma_BdRingFromHw(). + * + * @param RingPtr is a pointer to the descriptor ring instance to be + * worked on. + * @param NumBd is the number of BDs to free. + * @param BdSetPtr is the head of a list of BDs returned by + * XAxiDma_BdRingFromHw(). + * + * @return + * - XST_SUCCESS if the set of BDs was freed. + * - XST_INVALID_PARAM if NumBd is negative + * - XST_DMA_SG_LIST_ERROR if this function was called out of + * sequence with XAxiDma_BdRingFromHw(). + * + * @note This function should not be preempted by another XAxiDma + * function call that modifies the BD space. It is the caller's + * responsibility to ensure mutual exclusion. + * + * This function can be used only when DMA is in SG mode + * + *****************************************************************************/ +int XAxiDma_BdRingFree(XAxiDma_BdRing * RingPtr, int NumBd, + XAxiDma_Bd * BdSetPtr) +{ + if (NumBd < 0) { + + xdbg_printf(XDBG_DEBUG_ERROR, + "BdRingFree: negative BDs %d\r\n", NumBd); + + return XST_INVALID_PARAM; + } + + /* If the BD Set to free is empty, do nothing + */ + if (NumBd == 0) { + return XST_SUCCESS; + } + + /* Make sure we are in sync with XAxiDma_BdRingFromHw() */ + if ((RingPtr->PostCnt < NumBd) || (RingPtr->PostHead != BdSetPtr)) { + + xdbg_printf(XDBG_DEBUG_ERROR, "BdRingFree: Error free BDs: " + "post count %d to free %d, PostHead %x to free ptr %x\r\n", + RingPtr->PostCnt, NumBd, + (UINTPTR)RingPtr->PostHead, + (UINTPTR)BdSetPtr); + + return XST_DMA_SG_LIST_ERROR; + } + + /* Update pointers and counters */ + RingPtr->FreeCnt += NumBd; + RingPtr->PostCnt -= NumBd; + XAXIDMA_RING_SEEKAHEAD(RingPtr, RingPtr->PostHead, NumBd); + + return XST_SUCCESS; +} +/*****************************************************************************/ +/** + * Check the internal data structures of the BD ring for the provided channel. + * The following checks are made: + * + * - The BD ring is linked correctly in physical address space. + * - The internal pointers point to BDs in the ring. + * - The internal counters add up. + * + * The channel should be stopped (through XAxiDma_Pause() or XAxiDma_Reset()) + * prior to calling this function. + * + * @param RingPtr is a pointer to the descriptor ring to be worked on. + * + * @return + * - XST_SUCCESS if no errors were found. + * - XST_DMA_SG_NO_LIST if the ring has not been created. + * - XST_IS_STARTED if the channel is not stopped. + * - XST_DMA_SG_LIST_ERROR if a problem is found with the internal + * data structures. If this value is returned, the channel should + * be reset,and the BD ring should be recreated through + * XAxiDma_BdRingCreate() to avoid data corruption or system + * instability. + * + * @note This function can be used only when DMA is in SG mode + * + *****************************************************************************/ +int XAxiDma_BdRingCheck(XAxiDma_BdRing * RingPtr) +{ + u32 AddrV; + u32 AddrP; + int i; + + /* Is the list created */ + if (RingPtr->AllCnt == 0) { + + xdbg_printf(XDBG_DEBUG_ERROR, "BdRingCheck: no BDs\r\n"); + + return XST_DMA_SG_NO_LIST; + } + + /* Can't check if channel is running */ + if (RingPtr->RunState == AXIDMA_CHANNEL_NOT_HALTED) { + + xdbg_printf(XDBG_DEBUG_ERROR, "BdRingCheck: Bd ring is " + "running, cannot check it\r\n"); + + return XST_IS_STARTED; + } + + /* RunState doesn't make sense */ + else if (RingPtr->RunState != AXIDMA_CHANNEL_HALTED) { + + xdbg_printf(XDBG_DEBUG_ERROR, "BdRingCheck: unknown BD ring " + "state %d ", RingPtr->RunState); + + return XST_DMA_SG_LIST_ERROR; + } + + /* Verify internal pointers point to correct memory space */ + AddrV = (UINTPTR) RingPtr->FreeHead; + if ((AddrV < RingPtr->FirstBdAddr) || (AddrV > RingPtr->LastBdAddr)) { + + xdbg_printf(XDBG_DEBUG_ERROR, "BdRingCheck: FreeHead wrong " + "%x, should be in range of %x/%x\r\n", + (unsigned int)AddrV, + (unsigned int)RingPtr->FirstBdAddr, + (unsigned int)RingPtr->LastBdAddr); + + return XST_DMA_SG_LIST_ERROR; + } + + AddrV = (UINTPTR) RingPtr->PreHead; + if ((AddrV < RingPtr->FirstBdAddr) || (AddrV > RingPtr->LastBdAddr)) { + + xdbg_printf(XDBG_DEBUG_ERROR, "BdRingCheck: PreHead wrong %x, " + "should be in range of %x/%x\r\n", + (unsigned int)AddrV, + (unsigned int)RingPtr->FirstBdAddr, + (unsigned int)RingPtr->LastBdAddr); + + return XST_DMA_SG_LIST_ERROR; + } + + AddrV = (UINTPTR) RingPtr->HwHead; + if ((AddrV < RingPtr->FirstBdAddr) || (AddrV > RingPtr->LastBdAddr)) { + + xdbg_printf(XDBG_DEBUG_ERROR, "BdRingCheck: HwHead wrong %x, " + "should be in range of %x/%x\r\n", + (unsigned int)AddrV, + (unsigned int)RingPtr->FirstBdAddr, + (unsigned int)RingPtr->LastBdAddr); + + return XST_DMA_SG_LIST_ERROR; + } + + AddrV = (UINTPTR) RingPtr->HwTail; + if ((AddrV < RingPtr->FirstBdAddr) || (AddrV > RingPtr->LastBdAddr)) { + + xdbg_printf(XDBG_DEBUG_ERROR, "BdRingCheck: HwTail wrong %x, " + "should be in range of %x/%x\r\n", + (unsigned int)AddrV, + (unsigned int)RingPtr->FirstBdAddr, + (unsigned int)RingPtr->LastBdAddr); + + return XST_DMA_SG_LIST_ERROR; + } + + AddrV = (UINTPTR) RingPtr->PostHead; + if ((AddrV < RingPtr->FirstBdAddr) || (AddrV > RingPtr->LastBdAddr)) { + + xdbg_printf(XDBG_DEBUG_ERROR, "BdRingCheck: PostHead wrong " + "%x, should be in range of %x/%x\r\n", + (unsigned int)AddrV, + (unsigned int)RingPtr->FirstBdAddr, + (unsigned int)RingPtr->LastBdAddr); + + return XST_DMA_SG_LIST_ERROR; + } + + /* Verify internal counters add up */ + if ((RingPtr->HwCnt + RingPtr->PreCnt + RingPtr->FreeCnt + + RingPtr->PostCnt) != RingPtr->AllCnt) { + + xdbg_printf(XDBG_DEBUG_ERROR, "BdRingCheck: internal counter " + "error\r\n"); + + return XST_DMA_SG_LIST_ERROR; + } + + /* Verify BDs are linked correctly */ + AddrV = RingPtr->FirstBdAddr; + AddrP = RingPtr->FirstBdPhysAddr + RingPtr->Separation; + for (i = 1; i < RingPtr->AllCnt; i++) { + XAXIDMA_CACHE_INVALIDATE(AddrV); + /* Check next pointer for this BD. It should equal to the + * physical address of next BD + */ + if (XAxiDma_BdRead(AddrV, XAXIDMA_BD_NDESC_OFFSET) != AddrP) { + + xdbg_printf(XDBG_DEBUG_ERROR, "BdRingCheck: Next Bd " + "ptr %x wrong, expect %x\r\n", + (unsigned int)XAxiDma_BdRead(AddrV, + XAXIDMA_BD_NDESC_OFFSET), + (unsigned int)AddrP); + + return XST_DMA_SG_LIST_ERROR; + } + + /* Move on to next BD */ + AddrV += RingPtr->Separation; + AddrP += RingPtr->Separation; + } + + XAXIDMA_CACHE_INVALIDATE(AddrV); + /* Last BD should point back to the beginning of ring */ + if (XAxiDma_BdRead(AddrV, XAXIDMA_BD_NDESC_OFFSET) != + RingPtr->FirstBdPhysAddr) { + + xdbg_printf(XDBG_DEBUG_ERROR, "BdRingCheck: last Bd Next BD " + "ptr %x wrong, expect %x\r\n", + (unsigned int)XAxiDma_BdRead(AddrV, + XAXIDMA_BD_NDESC_OFFSET), + (unsigned int)RingPtr->FirstBdPhysAddr); + + return XST_DMA_SG_LIST_ERROR; + } + + /* No problems found */ + return XST_SUCCESS; +} +/*****************************************************************************/ +/** + * Dump the registers for a channel. + * + * @param RingPtr is a pointer to the descriptor ring to be worked on. + * + * @return None + * + * @note This function can be used only when DMA is in SG mode + * + *****************************************************************************/ +void XAxiDma_BdRingDumpRegs(XAxiDma_BdRing *RingPtr) { + UINTPTR RegBase = RingPtr->ChanBase; + int RingIndex = RingPtr->RingIndex; + + xil_printf("Dump registers %p:\r\n", (void *)RegBase); + xil_printf("Control REG: %08x\r\n", + (unsigned int)XAxiDma_ReadReg(RegBase, XAXIDMA_CR_OFFSET)); + xil_printf("Status REG: %08x\r\n", + (unsigned int)XAxiDma_ReadReg(RegBase, XAXIDMA_SR_OFFSET)); + + if (RingIndex) { + xil_printf("Cur BD REG: %08x\r\n", + (unsigned int)XAxiDma_ReadReg(RegBase, + XAXIDMA_RX_CDESC0_OFFSET + ((RingIndex - 1) * + XAXIDMA_RX_NDESC_OFFSET))); + xil_printf("Tail BD REG: %08x\r\n", + (unsigned int)XAxiDma_ReadReg(RegBase, + XAXIDMA_RX_TDESC0_OFFSET + ((RingIndex - 1) * + XAXIDMA_RX_NDESC_OFFSET))); + } + else { + xil_printf("Cur BD REG: %08x\r\n", + (unsigned int)XAxiDma_ReadReg(RegBase, XAXIDMA_CDESC_OFFSET)); + xil_printf("Tail BD REG: %08x\r\n", + (unsigned int)XAxiDma_ReadReg(RegBase, XAXIDMA_TDESC_OFFSET)); + } + + xil_printf("\r\n"); +} +/** @} */ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/axidma_v9_9/src/xaxidma_bdring.h b/datalink814_sp/bsp/microblaze_ps/libsrc/axidma_v9_9/src/xaxidma_bdring.h new file mode 100644 index 0000000..75cf96c --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/axidma_v9_9/src/xaxidma_bdring.h @@ -0,0 +1,542 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xaxidma_bdring.h +* @addtogroup axidma_v9_9 +* @{ +* +* This file contains DMA channel related structure and constant definition +* as well as function prototypes. Each DMA channel is managed by a Buffer +* Descriptor ring, and XAxiDma_BdRing is chosen as the symbol prefix used in +* this file. See xaxidma.h for more information on how a BD ring is managed. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a jz   05/18/10 First release
+* 2.00a jz   08/10/10 Second release, added in xaxidma_g.c, xaxidma_sinit.c,
+*                     updated tcl file, added xaxidma_porting_guide.h
+* 3.00a jz   11/22/10 Support IP core parameters change
+* 6.00a srt  01/24/12 Added support for Multi-Channel DMA.
+*		      - New API
+*			* XAxiDma_UpdateBdRingCDesc(XAxiDma_BdRing * RingPtr,
+*						int RingIndex)
+*		      - Changed APIs
+*			* XAxiDma_StartBdRingHw(XAxiDma_BdRing * RingPtr,
+*					int RingIndex)
+*			* XAxiDma_BdRingStart(XAxiDma_BdRing * RingPtr,
+*						 int RingIndex)
+*			* XAxiDma_BdRingToHw(XAxiDma_BdRing * RingPtr,
+*        			int NumBd, XAxiDma_Bd * BdSetPtr, int RingIndex)
+*			* XAxiDma_BdRingDumpRegs(XAxiDma_BdRing * RingPtr,
+*						 int RingIndex)
+*			* XAxiDma_BdRingSnapShotCurrBd(XAxiDma_BdRing * RingPtr,
+*						 int RingIndex)
+* 7.00a srt  06/18/12  All the APIs changed in v6_00_a are reverted back for
+*		       backward compatibility.
+* 9.2   vak  15/04/16  Fixed the compilation warnings in axidma driver
+* 9.7   rsp  01/11/18  Use UINTPTR instead of u32 for ChanBase CR#976392
+*
+* 
+* +******************************************************************************/ + +#ifndef XAXIDMA_BDRING_H_ /* prevent circular inclusions */ +#define XAXIDMA_BDRING_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xstatus.h" +#include "xaxidma_bd.h" +#include + +/************************** Constant Definitions *****************************/ +/* State of a DMA channel + */ +#define AXIDMA_CHANNEL_NOT_HALTED 1 +#define AXIDMA_CHANNEL_HALTED 2 + +/* Argument constant to simplify argument setting + */ +#define XAXIDMA_NO_CHANGE 0xFFFFFFFF +#define XAXIDMA_ALL_BDS 0x0FFFFFFF /* 268 Million */ + +/**************************** Type Definitions *******************************/ + +/** Container structure for descriptor storage control. If address translation + * is enabled, then all addresses and pointers excluding FirstBdPhysAddr are + * expressed in terms of the virtual address. + */ +typedef struct { + UINTPTR ChanBase; /**< physical base address*/ + + int IsRxChannel; /**< Is this a receive channel */ + volatile int RunState; /**< Whether channel is running */ + int HasStsCntrlStrm; /**< Whether has stscntrl stream */ + int HasDRE; + int DataWidth; + int Addr_ext; + u32 MaxTransferLen; + + UINTPTR FirstBdPhysAddr; /**< Physical address of 1st BD in list */ + UINTPTR FirstBdAddr; /**< Virtual address of 1st BD in list */ + UINTPTR LastBdAddr; /**< Virtual address of last BD in the list */ + u32 Length; /**< Total size of ring in bytes */ + UINTPTR Separation; /**< Number of bytes between the starting + address of adjacent BDs */ + XAxiDma_Bd *FreeHead; /**< First BD in the free group */ + XAxiDma_Bd *PreHead; /**< First BD in the pre-work group */ + XAxiDma_Bd *HwHead; /**< First BD in the work group */ + XAxiDma_Bd *HwTail; /**< Last BD in the work group */ + XAxiDma_Bd *PostHead; /**< First BD in the post-work group */ + XAxiDma_Bd *BdaRestart; /**< BD to load when channel is started */ + XAxiDma_Bd *CyclicBd; /**< Useful for Cyclic DMA operations */ + int FreeCnt; /**< Number of allocatable BDs in free group */ + int PreCnt; /**< Number of BDs in pre-work group */ + int HwCnt; /**< Number of BDs in work group */ + int PostCnt; /**< Number of BDs in post-work group */ + int AllCnt; /**< Total Number of BDs for channel */ + int RingIndex; /**< Ring Index */ + int Cyclic; /**< Check for cyclic DMA Mode */ +} XAxiDma_BdRing; + +/***************** Macros (Inline Functions) Definitions *********************/ + +/*****************************************************************************/ +/** +* Use this macro at initialization time to determine how many BDs will fit +* within the given memory constraints. +* +* The results of this macro can be provided to XAxiDma_BdRingCreate(). +* +* @param Alignment specifies what byte alignment the BDs must fall +* on and must be a power of 2 to get an accurate calculation +* (32, 64, 126,...) +* @param Bytes is the number of bytes to be used to store BDs. +* +* @return Number of BDs that can fit in the given memory area +* +* @note +* C-style signature: +* int XAxiDma_BdRingCntCalc(u32 Alignment, u32 Bytes) +* This function is used only when system is configured as SG mode +* +******************************************************************************/ +#define XAxiDma_BdRingCntCalc(Alignment, Bytes) \ + (uint32_t)((Bytes)/((sizeof(XAxiDma_Bd)+((Alignment)-1))&~((Alignment)-1))) + +/*****************************************************************************/ +/** +* Use this macro at initialization time to determine how many bytes of memory +* are required to contain a given number of BDs at a given alignment. +* +* @param Alignment specifies what byte alignment the BDs must fall on. +* This parameter must be a power of 2 to get an accurate +* calculation (32, 64,128,...) +* @param NumBd is the number of BDs to calculate memory size +* requirements +* +* @return The number of bytes of memory required to create a BD list +* with the given memory constraints. +* +* @note +* C-style signature: +* int XAxiDma_BdRingMemCalc(u32 Alignment, u32 NumBd) +* This function is used only when system is configured as SG mode +* +******************************************************************************/ +#define XAxiDma_BdRingMemCalc(Alignment, NumBd) \ + (int)((sizeof(XAxiDma_Bd)+((Alignment)-1)) & ~((Alignment)-1))*(NumBd) + +/****************************************************************************/ +/** +* Return the total number of BDs allocated by this channel with +* XAxiDma_BdRingCreate(). +* +* @param RingPtr is the BD ring to operate on. +* +* @return The total number of BDs allocated for this channel. +* +* @note +* C-style signature: +* int XAxiDma_BdRingGetCnt(XAxiDma_BdRing* RingPtr) +* This function is used only when system is configured as SG mode +* +*****************************************************************************/ +#define XAxiDma_BdRingGetCnt(RingPtr) ((RingPtr)->AllCnt) + +/****************************************************************************/ +/** +* Return the number of BDs allocatable with XAxiDma_BdRingAlloc() for pre- +* processing. +* +* @param RingPtr is the BD ring to operate on. +* +* @return The number of BDs currently allocatable. +* +* @note +* C-style signature: +* int XAxiDma_BdRingGetFreeCnt(XAxiDma_BdRing* RingPtr) +* This function is used only when system is configured as SG mode +* +*****************************************************************************/ +#define XAxiDma_BdRingGetFreeCnt(RingPtr) ((RingPtr)->FreeCnt) + + +/****************************************************************************/ +/** +* Snap shot the latest BD a BD ring is processing. +* +* @param RingPtr is the BD ring to operate on. +* +* @return None +* +* @note +* C-style signature: +* void XAxiDma_BdRingSnapShotCurrBd(XAxiDma_BdRing* RingPtr) +* This function is used only when system is configured as SG mode +* +*****************************************************************************/ +#define XAxiDma_BdRingSnapShotCurrBd(RingPtr) \ + { \ + if (!RingPtr->IsRxChannel) { \ + (RingPtr)->BdaRestart = \ + (XAxiDma_Bd *)(UINTPTR)XAxiDma_ReadReg( \ + (RingPtr)->ChanBase, \ + XAXIDMA_CDESC_OFFSET); \ + } else { \ + if (!RingPtr->RingIndex) { \ + (RingPtr)->BdaRestart = \ + (XAxiDma_Bd *)(UINTPTR)XAxiDma_ReadReg( \ + (RingPtr)->ChanBase, \ + XAXIDMA_CDESC_OFFSET); \ + } else { \ + (RingPtr)->BdaRestart = \ + (XAxiDma_Bd *)(UINTPTR)XAxiDma_ReadReg( \ + (RingPtr)->ChanBase, \ + (XAXIDMA_RX_CDESC0_OFFSET + \ + (RingPtr->RingIndex - 1) * \ + XAXIDMA_RX_NDESC_OFFSET)); \ + } \ + } \ + } + +/****************************************************************************/ +/** +* Get the BD a BD ring is processing. +* +* @param RingPtr is the BD ring to operate on. +* +* @return The current BD that the BD ring is working on +* +* @note +* C-style signature: +* XAxiDma_Bd * XAxiDma_BdRingGetCurrBd(XAxiDma_BdRing* RingPtr) +* This function is used only when system is configured as SG mode +* +*****************************************************************************/ +#define XAxiDma_BdRingGetCurrBd(RingPtr) \ + (XAxiDma_Bd *)XAxiDma_ReadReg((RingPtr)->ChanBase, \ + XAXIDMA_CDESC_OFFSET) \ + +/****************************************************************************/ +/** +* Return the next BD in the ring. +* +* @param RingPtr is the BD ring to operate on. +* @param BdPtr is the current BD. +* +* @return The next BD in the ring relative to the BdPtr parameter. +* +* @note +* C-style signature: +* XAxiDma_Bd *XAxiDma_BdRingNext(XAxiDma_BdRing* RingPtr, +* XAxiDma_Bd *BdPtr) +* This function is used only when system is configured as SG mode +* +*****************************************************************************/ +#define XAxiDma_BdRingNext(RingPtr, BdPtr) \ + (((UINTPTR)(BdPtr) >= (RingPtr)->LastBdAddr) ? \ + (UINTPTR)(RingPtr)->FirstBdAddr : \ + (UINTPTR)((UINTPTR)(BdPtr) + (RingPtr)->Separation)) + +/****************************************************************************/ +/** +* Return the previous BD in the ring. +* +* @param RingPtr is the DMA channel to operate on. +* @param BdPtr is the current BD. +* +* @return The previous BD in the ring relative to the BdPtr parameter. +* +* @note +* C-style signature: +* XAxiDma_Bd *XAxiDma_BdRingPrev(XAxiDma_BdRing* RingPtr, +* XAxiDma_Bd *BdPtr) +* This function is used only when system is configured as SG mode +* +*****************************************************************************/ +#define XAxiDma_BdRingPrev(RingPtr, BdPtr) \ + (((u32)(BdPtr) <= (RingPtr)->FirstBdAddr) ? \ + (XAxiDma_Bd*)(RingPtr)->LastBdAddr : \ + (XAxiDma_Bd*)((u32)(BdPtr) - (RingPtr)->Separation)) + +/****************************************************************************/ +/** +* Retrieve the contents of the channel status register +* +* @param RingPtr is the channel instance to operate on. +* +* @return Current contents of status register +* +* @note +* C-style signature: +* u32 XAxiDma_BdRingGetSr(XAxiDma_BdRing* RingPtr) +* This function is used only when system is configured as SG mode +* +*****************************************************************************/ +#define XAxiDma_BdRingGetSr(RingPtr) \ + XAxiDma_ReadReg((RingPtr)->ChanBase, XAXIDMA_SR_OFFSET) + +/****************************************************************************/ +/** +* Get error bits of a DMA channel +* +* @param RingPtr is the channel instance to operate on. +* +* @return Rrror bits in the status register, they should be interpreted +* with XAXIDMA_ERR_*_MASK defined in xaxidma_hw.h +* +* @note +* C-style signature: +* u32 XAxiDma_BdRingGetError(XAxiDma_BdRing* RingPtr) +* This function is used only when system is configured as SG mode +* +*****************************************************************************/ +#define XAxiDma_BdRingGetError(RingPtr) \ + (XAxiDma_ReadReg((RingPtr)->ChanBase, XAXIDMA_SR_OFFSET) \ + & XAXIDMA_ERR_ALL_MASK) + +/****************************************************************************/ +/** +* Check whether a DMA channel is started, meaning the channel is not halted. +* +* @param RingPtr is the channel instance to operate on. +* +* @return +* - 1 if channel is started +* - 0 otherwise +* +* @note +* C-style signature: +* int XAxiDma_BdRingHwIsStarted(XAxiDma_BdRing* RingPtr) +* +*****************************************************************************/ +#define XAxiDma_BdRingHwIsStarted(RingPtr) \ + ((XAxiDma_ReadReg((RingPtr)->ChanBase, XAXIDMA_SR_OFFSET) \ + & XAXIDMA_HALTED_MASK) ? FALSE : TRUE) + +/****************************************************************************/ +/** +* Check if the current DMA channel is busy with a DMA operation. +* +* @param RingPtr is the channel instance to operate on. +* +* @return +* - 1 if the DMA is busy. +* - 0 otherwise +* +* @note +* C-style signature: +* int XAxiDma_BdRingBusy(XAxiDma_BdRing* RingPtr) +* This function is used only when system is configured as SG mode +* +*****************************************************************************/ +#define XAxiDma_BdRingBusy(RingPtr) \ + (XAxiDma_BdRingHwIsStarted(RingPtr) && \ + ((XAxiDma_ReadReg((RingPtr)->ChanBase, XAXIDMA_SR_OFFSET) \ + & XAXIDMA_IDLE_MASK) ? FALSE : TRUE)) + +/****************************************************************************/ +/** +* Set interrupt enable bits for a channel. This operation will modify the +* XAXIDMA_CR_OFFSET register. +* +* @param RingPtr is the channel instance to operate on. +* @param Mask consists of the interrupt signals to enable.Bits not +* specified in the mask are not affected. +* +* @note +* C-style signature: +* void XAxiDma_BdRingIntEnable(XAxiDma_BdRing* RingPtr, u32 Mask) +* This function is used only when system is configured as SG mode +* +*****************************************************************************/ +#define XAxiDma_BdRingIntEnable(RingPtr, Mask) \ + (XAxiDma_WriteReg((RingPtr)->ChanBase, XAXIDMA_CR_OFFSET, \ + XAxiDma_ReadReg((RingPtr)->ChanBase, XAXIDMA_CR_OFFSET) \ + | ((Mask) & XAXIDMA_IRQ_ALL_MASK))) + +/****************************************************************************/ +/** +* Get enabled interrupts of a channel. It is in XAXIDMA_CR_OFFSET register. +* +* @param RingPtr is the channel instance to operate on. +* @return Enabled interrupts of a channel. Use XAXIDMA_IRQ_* defined in +* xaxidma_hw.h to interpret this returned value. +* +* @note +* C-style signature: +* u32 XAxiDma_BdRingIntGetEnabled(XAxiDma_BdRing* RingPtr) +* This function is used only when system is configured as SG mode +* +*****************************************************************************/ +#define XAxiDma_BdRingIntGetEnabled(RingPtr) \ + (XAxiDma_ReadReg((RingPtr)->ChanBase, XAXIDMA_CR_OFFSET) \ + & XAXIDMA_IRQ_ALL_MASK) + +/****************************************************************************/ +/** +* Clear interrupt enable bits for a channel. It modifies the +* XAXIDMA_CR_OFFSET register. +* +* @param RingPtr is the channel instance to operate on. +* @param Mask consists of the interrupt signals to disable.Bits not +* specified in the Mask are not affected. +* +* @note +* C-style signature: +* void XAxiDma_BdRingIntDisable(XAxiDma_BdRing* RingPtr, +* u32 Mask) +* This function is used only when system is configured as SG mode +* +*****************************************************************************/ +#define XAxiDma_BdRingIntDisable(RingPtr, Mask) \ + (XAxiDma_WriteReg((RingPtr)->ChanBase, XAXIDMA_CR_OFFSET, \ + XAxiDma_ReadReg((RingPtr)->ChanBase, XAXIDMA_CR_OFFSET) & \ + ~((Mask) & XAXIDMA_IRQ_ALL_MASK))) + +/****************************************************************************/ +/** +* Retrieve the contents of the channel's IRQ register XAXIDMA_SR_OFFSET. This +* operation can be used to see which interrupts are pending. +* +* @param RingPtr is the channel instance to operate on. +* +* @return Current contents of the IRQ_OFFSET register. Use +* XAXIDMA_IRQ_*** values defined in xaxidma_hw.h to interpret +* the returned value. +* +* @note +* C-style signature: +* u32 XAxiDma_BdRingGetIrq(XAxiDma_BdRing* RingPtr) +* This function is used only when system is configured as SG mode +* +*****************************************************************************/ +#define XAxiDma_BdRingGetIrq(RingPtr) \ + (XAxiDma_ReadReg((RingPtr)->ChanBase, XAXIDMA_SR_OFFSET) \ + & XAXIDMA_IRQ_ALL_MASK) + +/****************************************************************************/ +/** +* Acknowledge asserted interrupts. It modifies XAXIDMA_SR_OFFSET register. +* A mask bit set for an unasserted interrupt has no effect. +* +* @param RingPtr is the channel instance to operate on. +* @param Mask are the interrupt signals to acknowledge +* +* @note +* C-style signature: +* void XAxiDma_BdRingAckIrq(XAxiDma_BdRing* RingPtr) +* This function is used only when system is configured as SG mode +* +*****************************************************************************/ +#define XAxiDma_BdRingAckIrq(RingPtr, Mask) \ + XAxiDma_WriteReg((RingPtr)->ChanBase, XAXIDMA_SR_OFFSET,\ + (Mask) & XAXIDMA_IRQ_ALL_MASK) + +/****************************************************************************/ +/** +* Enable Cyclic DMA Mode. +* +* @param RingPtr is the channel instance to operate on. +* +* @note +* C-style signature: +* void XAxiDma_BdRingEnableCyclicDMA(XAxiDma_BdRing* RingPtr) +* This function is used only when system is configured as SG mode +* +*****************************************************************************/ +#define XAxiDma_BdRingEnableCyclicDMA(RingPtr) \ + (RingPtr->Cyclic = 1) + +/****************************************************************************/ + +/************************* Function Prototypes ******************************/ + +/* + * Descriptor ring functions xaxidma_bdring.c + */ +int XAxiDma_StartBdRingHw(XAxiDma_BdRing* RingPtr); +int XAxiDma_UpdateBdRingCDesc(XAxiDma_BdRing* RingPtr); +u32 XAxiDma_BdRingCreate(XAxiDma_BdRing * RingPtr, UINTPTR PhysAddr, + UINTPTR VirtAddr, u32 Alignment, int BdCount); +int XAxiDma_BdRingClone(XAxiDma_BdRing * RingPtr, XAxiDma_Bd * SrcBdPtr); +int XAxiDma_BdRingAlloc(XAxiDma_BdRing * RingPtr, int NumBd, + XAxiDma_Bd ** BdSetPtr); +int XAxiDma_BdRingUnAlloc(XAxiDma_BdRing * RingPtr, int NumBd, + XAxiDma_Bd * BdSetPtr); +int XAxiDma_BdRingToHw(XAxiDma_BdRing * RingPtr, int NumBd, + XAxiDma_Bd * BdSetPtr); +int XAxiDma_BdRingFromHw(XAxiDma_BdRing * RingPtr, int BdLimit, + XAxiDma_Bd ** BdSetPtr); +int XAxiDma_BdRingFree(XAxiDma_BdRing * RingPtr, int NumBd, + XAxiDma_Bd * BdSetPtr); +int XAxiDma_BdRingStart(XAxiDma_BdRing * RingPtr); +int XAxiDma_BdRingSetCoalesce(XAxiDma_BdRing * RingPtr, u32 Counter, u32 Timer); +void XAxiDma_BdRingGetCoalesce(XAxiDma_BdRing * RingPtr, + u32 *CounterPtr, u32 *TimerPtr); + +/* The following functions are for debug only + */ +int XAxiDma_BdRingCheck(XAxiDma_BdRing * RingPtr); +void XAxiDma_BdRingDumpRegs(XAxiDma_BdRing *RingPtr); +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/axidma_v9_9/src/xaxidma_g.c b/datalink814_sp/bsp/microblaze_ps/libsrc/axidma_v9_9/src/xaxidma_g.c new file mode 100644 index 0000000..ddcb1d0 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/axidma_v9_9/src/xaxidma_g.c @@ -0,0 +1,66 @@ + +/******************************************************************* +* +* CAUTION: This file is automatically generated by HSI. +* Version: 2019.1.3 +* DO NOT EDIT. +* +* Copyright (C) 2010-2023 Xilinx, Inc. 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 +*XILINX 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. +* +*Except as contained in this notice, the name of the Xilinx shall not be used +*in advertising or otherwise to promote the sale, use or other dealings in +*this Software without prior written authorization from Xilinx. +* + +* +* Description: Driver configuration +* +*******************************************************************/ + +#include "xparameters.h" +#include "xaxidma.h" + +/* +* The configuration table for devices +*/ + +XAxiDma_Config XAxiDma_ConfigTable[XPAR_XAXIDMA_NUM_INSTANCES] = +{ + { + XPAR_AXI_DMA_C2C_DEVICE_ID, + XPAR_AXI_DMA_C2C_BASEADDR, + XPAR_AXI_DMA_C2C_SG_INCLUDE_STSCNTRL_STRM, + XPAR_AXI_DMA_C2C_INCLUDE_MM2S, + XPAR_AXI_DMA_C2C_INCLUDE_MM2S_DRE, + XPAR_AXI_DMA_C2C_M_AXI_MM2S_DATA_WIDTH, + XPAR_AXI_DMA_C2C_INCLUDE_S2MM, + XPAR_AXI_DMA_C2C_INCLUDE_S2MM_DRE, + XPAR_AXI_DMA_C2C_M_AXI_S2MM_DATA_WIDTH, + XPAR_AXI_DMA_C2C_INCLUDE_SG, + XPAR_AXI_DMA_C2C_NUM_MM2S_CHANNELS, + XPAR_AXI_DMA_C2C_NUM_S2MM_CHANNELS, + XPAR_AXI_DMA_C2C_MM2S_BURST_SIZE, + XPAR_AXI_DMA_C2C_S2MM_BURST_SIZE, + XPAR_AXI_DMA_C2C_MICRO_DMA, + XPAR_AXI_DMA_C2C_ADDR_WIDTH, + XPAR_AXI_DMA_C2C_SG_LENGTH_WIDTH + } +}; + + diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/axidma_v9_9/src/xaxidma_hw.h b/datalink814_sp/bsp/microblaze_ps/libsrc/axidma_v9_9/src/xaxidma_hw.h new file mode 100644 index 0000000..171fca6 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/axidma_v9_9/src/xaxidma_hw.h @@ -0,0 +1,342 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** + * @file xaxidma_hw.h +* @addtogroup axidma_v9_9 +* @{ + * + * Hardware definition file. It defines the register interface and Buffer + * Descriptor (BD) definitions. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -------------------------------------------------------
+ * 1.00a jz   05/18/10 First release
+ * 2.00a jz   08/10/10 Second release, added in xaxidma_g.c, xaxidma_sinit.c,
+ *                     updated tcl file, added xaxidma_porting_guide.h
+ * 3.00a jz   11/22/10 Support IP core parameters change
+ * 4.00a rkv  02/22/11 Added support for simple DMA mode
+ * 6.00a srt  01/24/12 Added support for Multi-Channel DMA mode
+ * 8.0   srt  01/29/14 Added support for Micro DMA Mode and Cyclic mode of
+ *		       operations.
+ * 9.7   rsp  04/24/18 Added support for 64MB data transfer.Instead of #define
+ *                     read max buffer width from IP config.
+ *
+ * 
+ * + *****************************************************************************/ + +#ifndef XAXIDMA_HW_H_ /* prevent circular inclusions */ +#define XAXIDMA_HW_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "xil_types.h" +#include "xil_io.h" + +/************************** Constant Definitions *****************************/ + +/** @name DMA Transfer Direction + * @{ + */ +#define XAXIDMA_DMA_TO_DEVICE 0x00 +#define XAXIDMA_DEVICE_TO_DMA 0x01 + + +/** @name Buffer Descriptor Alignment + * @{ + */ +#define XAXIDMA_BD_MINIMUM_ALIGNMENT 0x40 /**< Minimum byte alignment + requirement for descriptors to + satisfy both hardware/software + needs */ +/*@}*/ + +/** @name Micro DMA Buffer Address Alignment + * @{ + */ +#define XAXIDMA_MICROMODE_MIN_BUF_ALIGN 0xFFF /**< Minimum byte alignment + requirement for buffer address + in Micro DMA mode */ +/*@}*/ + +/** @name Maximum transfer length + * This is determined by hardware + * @{ + */ +#define XAXIDMA_MCHAN_MAX_TRANSFER_LEN 0x00FFFF /* Max length MCDMA + hw supports */ +/*@}*/ + +/* Register offset definitions. Register accesses are 32-bit. + */ +/** @name Device registers + * Register sets on TX and RX channels are identical + * @{ + */ +#define XAXIDMA_TX_OFFSET 0x00000000 /**< TX channel registers base + * offset */ +#define XAXIDMA_RX_OFFSET 0x00000030 /**< RX channel registers base + * offset */ + +/* This set of registers are applicable for both channels. Add + * XAXIDMA_TX_OFFSET to get to TX channel, and XAXIDMA_RX_OFFSET to get to RX + * channel + */ +#define XAXIDMA_CR_OFFSET 0x00000000 /**< Channel control */ +#define XAXIDMA_SR_OFFSET 0x00000004 /**< Status */ +#define XAXIDMA_CDESC_OFFSET 0x00000008 /**< Current descriptor pointer */ +#define XAXIDMA_CDESC_MSB_OFFSET 0x0000000C /**< Current descriptor pointer */ +#define XAXIDMA_TDESC_OFFSET 0x00000010 /**< Tail descriptor pointer */ +#define XAXIDMA_TDESC_MSB_OFFSET 0x00000014 /**< Tail descriptor pointer */ +#define XAXIDMA_SRCADDR_OFFSET 0x00000018 /**< Simple mode source address + pointer */ +#define XAXIDMA_SRCADDR_MSB_OFFSET 0x0000001C /**< Simple mode source address + pointer */ +#define XAXIDMA_DESTADDR_OFFSET 0x00000018 /**< Simple mode destination address pointer */ +#define XAXIDMA_DESTADDR_MSB_OFFSET 0x0000001C /**< Simple mode destination address pointer */ +#define XAXIDMA_BUFFLEN_OFFSET 0x00000028 /**< Tail descriptor pointer */ +#define XAXIDMA_SGCTL_OFFSET 0x0000002c /**< SG Control Register */ + +/** Multi-Channel DMA Descriptor Offsets **/ +#define XAXIDMA_RX_CDESC0_OFFSET 0x00000040 /**< Rx Current Descriptor 0 */ +#define XAXIDMA_RX_CDESC0_MSB_OFFSET 0x00000044 /**< Rx Current Descriptor 0 */ +#define XAXIDMA_RX_TDESC0_OFFSET 0x00000048 /**< Rx Tail Descriptor 0 */ +#define XAXIDMA_RX_TDESC0_MSB_OFFSET 0x0000004C /**< Rx Tail Descriptor 0 */ +#define XAXIDMA_RX_NDESC_OFFSET 0x00000020 /**< Rx Next Descriptor Offset */ +/*@}*/ + +/** @name Bitmasks of XAXIDMA_CR_OFFSET register + * @{ + */ +#define XAXIDMA_CR_RUNSTOP_MASK 0x00000001 /**< Start/stop DMA channel */ +#define XAXIDMA_CR_RESET_MASK 0x00000004 /**< Reset DMA engine */ +#define XAXIDMA_CR_KEYHOLE_MASK 0x00000008 /**< Keyhole feature */ +#define XAXIDMA_CR_CYCLIC_MASK 0x00000010 /**< Cyclic Mode */ +/*@}*/ + +/** @name Bitmasks of XAXIDMA_SR_OFFSET register + * + * This register reports status of a DMA channel, including + * run/stop/idle state, errors, and interrupts (note that interrupt + * masks are shared with XAXIDMA_CR_OFFSET register, and are defined + * in the _IRQ_ section. + * + * The interrupt coalescing threshold value and delay counter value are + * also shared with XAXIDMA_CR_OFFSET register, and are defined in a + * later section. + * @{ + */ +#define XAXIDMA_HALTED_MASK 0x00000001 /**< DMA channel halted */ +#define XAXIDMA_IDLE_MASK 0x00000002 /**< DMA channel idle */ +#define XAXIDMA_ERR_INTERNAL_MASK 0x00000010 /**< Datamover internal + * err */ +#define XAXIDMA_ERR_SLAVE_MASK 0x00000020 /**< Datamover slave err */ +#define XAXIDMA_ERR_DECODE_MASK 0x00000040 /**< Datamover decode + * err */ +#define XAXIDMA_ERR_SG_INT_MASK 0x00000100 /**< SG internal err */ +#define XAXIDMA_ERR_SG_SLV_MASK 0x00000200 /**< SG slave err */ +#define XAXIDMA_ERR_SG_DEC_MASK 0x00000400 /**< SG decode err */ +#define XAXIDMA_ERR_ALL_MASK 0x00000770 /**< All errors */ + +/** @name Bitmask for interrupts + * These masks are shared by XAXIDMA_CR_OFFSET register and + * XAXIDMA_SR_OFFSET register + * @{ + */ +#define XAXIDMA_IRQ_IOC_MASK 0x00001000 /**< Completion intr */ +#define XAXIDMA_IRQ_DELAY_MASK 0x00002000 /**< Delay interrupt */ +#define XAXIDMA_IRQ_ERROR_MASK 0x00004000 /**< Error interrupt */ +#define XAXIDMA_IRQ_ALL_MASK 0x00007000 /**< All interrupts */ +/*@}*/ + +/** @name Bitmask and shift for delay and coalesce + * These masks are shared by XAXIDMA_CR_OFFSET register and + * XAXIDMA_SR_OFFSET register + * @{ + */ +#define XAXIDMA_DELAY_MASK 0xFF000000 /**< Delay timeout + * counter */ +#define XAXIDMA_COALESCE_MASK 0x00FF0000 /**< Coalesce counter */ + +#define XAXIDMA_DELAY_SHIFT 24 +#define XAXIDMA_COALESCE_SHIFT 16 +/*@}*/ + + +/* Buffer Descriptor (BD) definitions + */ + +/** @name Buffer Descriptor offsets + * USR* fields are defined by higher level IP. + * setup for EMAC type devices. The first 13 words are used by hardware. + * All words after the 13rd word are for software use only. + * @{ + */ +#define XAXIDMA_BD_NDESC_OFFSET 0x00 /**< Next descriptor pointer */ +#define XAXIDMA_BD_NDESC_MSB_OFFSET 0x04 /**< Next descriptor pointer */ +#define XAXIDMA_BD_BUFA_OFFSET 0x08 /**< Buffer address */ +#define XAXIDMA_BD_BUFA_MSB_OFFSET 0x0C /**< Buffer address */ +#define XAXIDMA_BD_MCCTL_OFFSET 0x10 /**< Multichannel Control Fields */ +#define XAXIDMA_BD_STRIDE_VSIZE_OFFSET 0x14 /**< 2D Transfer Sizes */ +#define XAXIDMA_BD_CTRL_LEN_OFFSET 0x18 /**< Control/buffer length */ +#define XAXIDMA_BD_STS_OFFSET 0x1C /**< Status */ + +#define XAXIDMA_BD_USR0_OFFSET 0x20 /**< User IP specific word0 */ +#define XAXIDMA_BD_USR1_OFFSET 0x24 /**< User IP specific word1 */ +#define XAXIDMA_BD_USR2_OFFSET 0x28 /**< User IP specific word2 */ +#define XAXIDMA_BD_USR3_OFFSET 0x2C /**< User IP specific word3 */ +#define XAXIDMA_BD_USR4_OFFSET 0x30 /**< User IP specific word4 */ + +#define XAXIDMA_BD_ID_OFFSET 0x34 /**< Sw ID */ +#define XAXIDMA_BD_HAS_STSCNTRL_OFFSET 0x38 /**< Whether has stscntrl strm */ +#define XAXIDMA_BD_HAS_DRE_OFFSET 0x3C /**< Whether has DRE */ + +#define XAXIDMA_BD_HAS_DRE_MASK 0xF00 /**< Whether has DRE mask */ +#define XAXIDMA_BD_WORDLEN_MASK 0xFF /**< Whether has DRE mask */ + +#define XAXIDMA_BD_HAS_DRE_SHIFT 8 /**< Whether has DRE shift */ +#define XAXIDMA_BD_WORDLEN_SHIFT 0 /**< Whether has DRE shift */ + +#define XAXIDMA_BD_START_CLEAR 8 /**< Offset to start clear */ +#define XAXIDMA_BD_BYTES_TO_CLEAR 48 /**< BD specific bytes to be + * cleared */ + +#define XAXIDMA_BD_NUM_WORDS 16U /**< Total number of words for + * one BD*/ +#define XAXIDMA_BD_HW_NUM_BYTES 52 /**< Number of bytes hw used */ + +/* The offset of the last app word. + */ +#define XAXIDMA_LAST_APPWORD 4 + +/*@}*/ +#define XAXIDMA_DESC_LSB_MASK (0xFFFFFFC0U) /**< LSB Address mask */ + +/** @name Bitmasks of XAXIDMA_BD_CTRL_OFFSET register + * @{ + */ +#define XAXIDMA_BD_CTRL_TXSOF_MASK 0x08000000 /**< First tx packet */ +#define XAXIDMA_BD_CTRL_TXEOF_MASK 0x04000000 /**< Last tx packet */ +#define XAXIDMA_BD_CTRL_ALL_MASK 0x0C000000 /**< All control bits */ +/*@}*/ + +/** @name Bitmasks of XAXIDMA_BD_STS_OFFSET register + * @{ + */ +#define XAXIDMA_BD_STS_COMPLETE_MASK 0x80000000 /**< Completed */ +#define XAXIDMA_BD_STS_DEC_ERR_MASK 0x40000000 /**< Decode error */ +#define XAXIDMA_BD_STS_SLV_ERR_MASK 0x20000000 /**< Slave error */ +#define XAXIDMA_BD_STS_INT_ERR_MASK 0x10000000 /**< Internal err */ +#define XAXIDMA_BD_STS_ALL_ERR_MASK 0x70000000 /**< All errors */ +#define XAXIDMA_BD_STS_RXSOF_MASK 0x08000000 /**< First rx pkt */ +#define XAXIDMA_BD_STS_RXEOF_MASK 0x04000000 /**< Last rx pkt */ +#define XAXIDMA_BD_STS_ALL_MASK 0xFC000000 /**< All status bits */ +/*@}*/ + +/** @name Bitmasks and shift values for XAXIDMA_BD_MCCTL_OFFSET register + * @{ + */ +#define XAXIDMA_BD_TDEST_FIELD_MASK 0x0000000F +#define XAXIDMA_BD_TID_FIELD_MASK 0x00000F00 +#define XAXIDMA_BD_TUSER_FIELD_MASK 0x000F0000 +#define XAXIDMA_BD_ARCACHE_FIELD_MASK 0x0F000000 +#define XAXIDMA_BD_ARUSER_FIELD_MASK 0xF0000000 + +#define XAXIDMA_BD_TDEST_FIELD_SHIFT 0 +#define XAXIDMA_BD_TID_FIELD_SHIFT 8 +#define XAXIDMA_BD_TUSER_FIELD_SHIFT 16 +#define XAXIDMA_BD_ARCACHE_FIELD_SHIFT 24 +#define XAXIDMA_BD_ARUSER_FIELD_SHIFT 28 +/*@}*/ + +/** @name Bitmasks and shift values for XAXIDMA_BD_STRIDE_VSIZE_OFFSET register + * @{ + */ +#define XAXIDMA_BD_STRIDE_FIELD_MASK 0x0000FFFF +#define XAXIDMA_BD_VSIZE_FIELD_MASK 0xFFF80000 + +#define XAXIDMA_BD_STRIDE_FIELD_SHIFT 0 +#define XAXIDMA_BD_VSIZE_FIELD_SHIFT 19 +/*@}*/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +#define XAxiDma_In32 Xil_In32 +#define XAxiDma_Out32 Xil_Out32 + +/*****************************************************************************/ +/** +* +* Read the given register. +* +* @param BaseAddress is the base address of the device +* @param RegOffset is the register offset to be read +* +* @return The 32-bit value of the register +* +* @note +* C-style signature: +* u32 XAxiDma_ReadReg(u32 BaseAddress, u32 RegOffset) +* +******************************************************************************/ +#define XAxiDma_ReadReg(BaseAddress, RegOffset) \ + XAxiDma_In32((BaseAddress) + (RegOffset)) + +/*****************************************************************************/ +/** +* +* Write the given register. +* +* @param BaseAddress is the base address of the device +* @param RegOffset is the register offset to be written +* @param Data is the 32-bit value to write to the register +* +* @return None. +* +* @note +* C-style signature: +* void XAxiDma_WriteReg(u32 BaseAddress, u32 RegOffset, u32 Data) +* +******************************************************************************/ +#define XAxiDma_WriteReg(BaseAddress, RegOffset, Data) \ + XAxiDma_Out32((BaseAddress) + (RegOffset), (Data)) + +#ifdef __cplusplus +} +#endif + +#endif +/** @} */ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/axidma_v9_9/src/xaxidma_porting_guide.h b/datalink814_sp/bsp/microblaze_ps/libsrc/axidma_v9_9/src/xaxidma_porting_guide.h new file mode 100644 index 0000000..84875b1 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/axidma_v9_9/src/xaxidma_porting_guide.h @@ -0,0 +1,250 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xaxidma_porting_guide.h +* @addtogroup axidma_v9_9 +* @{ +* +* This is a guide on how to move from using the xlldma driver to use xaxidma +* driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a jz   05/18/10 First release
+* 2.00a jz   08/10/10 Second release, added in xaxidma_g.c, xaxidma_sinit.c,
+*                     updated tcl file, added xaxidma_porting_guide.h
+* 4.00a rkv  02/22/11 Added support for simple DMA mode
+* 6.00a srt  03/27/12 Added support for MCDMA mode
+* 7.00a srt  06/18/12 API calls are reverted back for backward compatibility.
+*
+* 
+* +* Overview +* +* The API for xaxidma driver is similar to xlldma driver. The prefix for the +* API functions and structures is XAxiDma_ for the xaxidma driver. +* +* Due to hardware feature changes, signatures of some API functions are a +* little bit different from the xlldma API functions. +* +* We present API functions: +* - That only have prefix changes +* - That have different return type +* - That are new API functions +* - That have been removed +* +* Note that data structures have different prefix of XAxiDma_. Those API +* functions, that have data structures with prefix change, are considered as +* prefix change. +* +* API Functions That Only Have Prefix Changes +* +*
+*         xlldma driver              |         xaxidma driver (upto v5_00_a)
+* -----------------------------------------------------------------------
+*    XLlDma_Reset(...)               |  XAxiDma_Reset(...)
+*    XLlDma_BdRingSnapShotCurrBd(...)|  XAxiDma_BdRingSnapShotCurrBd(...)
+*    XLlDma_BdRingNext(...)          |  XAxiDma_BdRingNext(...)
+*    XLlDma_BdRingPrev(...)          |  XAxiDma_BdRingPrev(...)
+*    XLlDma_BdRingGetSr(...)         |  XAxiDma_BdRingGetSr(...)
+*    XLlDma_BdRingBusy(...)          |  XAxiDma_BdRingBusy(...)
+*    XLlDma_BdRingIntEnable(...)     |  XAxiDma_BdRingIntEnable(...)
+*    XLlDma_BdRingIntDisable(...)    |  XAxiDma_BdRingIntDisable(...)
+*    XLlDma_BdRingIntGetEnabled(...) |  XAxiDma_BdRingIntGetEnabled(...)
+*    XLlDma_BdRingGetIrq(...)        |  XAxiDma_BdRingGetIrq(...)
+*    XLlDma_BdRingAckIrq(...)        |  XAxiDma_BdRingAckIrq(...)
+*    XLlDma_BdRingCreate(...)        |  XAxiDma_BdRingCreate(...)
+*    XLlDma_BdRingClone(...)         |  XAxiDma_BdRingClone(...)
+*    XLlDma_BdRingAlloc(...)         |  XAxiDma_BdRingAlloc(...)
+*    XLlDma_BdRingUnAlloc(...)       |  XAxiDma_BdRingUnAlloc(...)
+*    XLlDma_BdRingToHw(...)          |  XAxiDma_BdRingToHw(...)
+*    XLlDma_BdRingFromHw(...)        |  XAxiDma_BdRingFromHw(...)
+*    XLlDma_BdRingFree(...)          |  XAxiDma_BdRingFree(...)
+*    XLlDma_BdRingStart(...)         |  XAxiDma_BdRingStart(...)
+*    XLlDma_BdRingCheck(...)         |  XAxiDma_BdRingCheck(...)
+*    XLlDma_BdRingSetCoalesce(...)   |  XAxiDma_BdRingSetCoalesce(...)
+*    XLlDma_BdRingGetCoalesce(...)   |  XAxiDma_BdRingGetCoalesce(...)
+*    XLlDma_BdRead(...)              |  XAxiDma_BdRead(...)
+*    XLlDma_BdWrite(...)             |  XAxiDma_BdWrite(...)
+*    XLlDma_BdClear(...)             |  XAxiDma_BdClear(...)
+*    XLlDma_BdSetId(...)             |  XAxiDma_BdSetId(...)
+*    XLlDma_BdGetId(...)             |  XAxiDma_BdGetId(...)
+*    XLlDma_BdGetLength(...)         |  XAxiDma_BdGetLength(...)
+*    XLlDma_BdGetBufAddr(...)        |  XAxiDma_BdGetBufAddr(...)
+*
+*
+* +* API Functions That Have Different Return Type +* +* Due to possible hardware failures, The caller should check the return value +* of the following functions. +* +*
+*         xlldma driver              |         xaxidma driver
+* -----------------------------------------------------------------------
+* void XLlDma_Pause(...)             | int XAxiDma_Pause(...)
+* void XLlDma_Resume(...)            | int XAxiDma_Resume(...)
+* 
+* +* The following functions have return type changed: +* +*
+*         xlldma driver              |         xaxidma driver
+* -----------------------------------------------------------------------
+* XLlDma_BdRing XLlDma_GetRxRing(...)| XAxiDma_BdRing * XAxiDma_GetRxRing(...)
+* XLlDma_BdRing XLlDma_GetTxRing(...)| XAxiDma_BdRing * XAxiDma_GetTxRing(...)
+* u32 XLlDma_BdRingMemCalc(...)      | int XAxiDma_BdRingMemCalc(...)
+* u32 XLlDma_BdRingCntCalc(...)      | int XAxiDma_BdRingCntCalc(...)
+* u32 XLlDma_BdRingGetCnt(...)       | int XAxiDma_BdRingGetCnt(...)
+* u32 XLlDma_BdRingGetFreeCnt(...)   | int XAxiDma_BdRingGetFreeCnt(...)
+* void XLlDma_BdSetLength(...)       | int XAxiDma_BdSetLength(...)
+* void XLlDma_BdSetBufAddr(...)      | int XAxiDma_BdSetBufAddr(...)
+*
+* +* API Functions That Are New API Functions +* +* Now that the AXI DMA core is a standalone core, some new API are intrduced. +* Some other functions are added due to hardware interface change, so to +* replace old API functions. +* +* - XAxiDma_Config *XAxiDma_LookupConfig(u32 DeviceId); +* - int XAxiDma_CfgInitialize(XAxiDma * InstancePtr, XAxiDma_Config *Config); +* - int XAxiDma_ResetIsDone(XAxiDma * InstancePtr); +* - XAxiDma_Bd * XAxiDma_BdRingGetCurrBd(XAxiDma_BdRing* RingPtr); +* - int XAxiDma_BdRingHwIsStarted(XAxiDma_BdRing* RingPtr); +* - void XAxiDma_BdRingDumpRegs(XAxiDma_BdRing *RingPtr); +* - int XAxiDma_StartBdRingHw(XAxiDma_BdRing* RingPtr); +* - void XAxiDma_BdSetCtrl(XAxiDma_Bd *BdPtr, u32 Data); +* - u32 XAxiDma_BdGetCtrl(XAxiDma_Bd* BdPtr); +* - u32 XAxiDma_BdGetSts(XAxiDma_Bd* BdPtr); +* - int XAxiDma_BdHwCompleted(XAxiDma_Bd* BdPtr); +* - int XAxiDma_BdGetActualLength(XAxiDma_Bd* BdPtr); +* - int XAxiDma_BdSetAppWord(XAxiDma_Bd * BdPtr, int Offset, u32 Word); +* - u32 XAxiDma_BdGetAppWord(XAxiDma_Bd * BdPtr, int Offset, int *Valid); +* +* API Functions That Have Been Removed +* +* Please see individual function comments for how to replace the removed API +* function with new API functions. +* +* - void XLlDma_Initialize(XLlDma * InstancePtr, u32 BaseAddress). +* This function is replaced by XAxiDma_LookupConfig()/XAxiDma_CfgInitialize() +* +* - u32 XLlDma_BdRingGetCr(XLlDma_BdRing* RingPtr). +* This is replaced by XAxiDma_BdRingGetError(XAxiDma_BdRing* RingPtr) +* +* - u32 XLlDma_BdRingSetCr(XLlDma_BdRing* RingPtr, u32 Data). +* This function is covered by other API functions: +* - void XAxiDma_BdRingIntEnable(XAxiDma_BdRing* RingPtr, u32 Mask) +* - void XAxiDma_BdRingIntDisable(XAxiDma_BdRing* RingPtr, u32 Mask) +* - int XAxiDma_BdRingSetCoalesce(XAxiDma_BdRing * RingPtr, u32 Counter, +* u32 Timer) +* +* - u32 XLlDma_BdSetStsCtrl(XLlDma_Bd* BdPtr, u32 Data). +* Replaced by XAxiDma_BdSetCtrl(XAxiDma_Bd *BdPtr, u32 Data); +* +* - u32 XLlDma_BdGetStsCtrl(XLlDma_Bd* BdPtr). +* Replaced by XAxiDma_BdGetCtrl(XAxiDma_Bd* BdPtr) and +* XAxiDma_BdGetSts(XAxiDma_Bd* BdPtr). +* +* API Functions That Have Been Added to support simple DMA mode +* +* - u32 XAxiDma_Busy(XAxiDma *InstancePtr,int Direction); +* - int XAxiDma_SimpleTransfer(XAxiDma *InstancePtr, u32 BuffAddr, int Length, +* int Direction); +* - XAxiDma_HasSg(InstancePtr); +* - XAxiDma_IntrEnable(InstancePtr,Mask,Direction); +* - XAxiDma_IntrGetEnabled(InstancePtr, Direction); +* - XAxiDma_IntrDisable(InstancePtr, Mask, Direction); +* - XAxiDma_IntrGetIrq(InstancePtr, Direction); +* - XAxiDma_IntrAckIrq(InstancePtr, Mask, Direction); +* +* For xaxidma driver v6_00_a Multiple Channel Support +* --------------------------------------------------- +* This driver supports Multi-channel mode and accordingly some APIs are +* changed to index multiple channels. Few new APIs are added. +* - Changed APIs +* * XAxiDma_GetRxRing(InstancePtr, RingIndex) +* * XAxiDma_Start(XAxiDma * InstancePtr, int RingIndex) +* * XAxiDma_Started(XAxiDma * InstancePtr, int RingIndex) +* * XAxiDma_Pause(XAxiDma * InstancePtr, int RingIndex) +* * XAxiDma_Resume(XAxiDma * InstancePtr, int RingIndex) +* * XAxiDma_SimpleTransfer(XAxiDma *InstancePtr, +* u32 BuffAddr, u32 Length, +* int Direction, int RingIndex) +* * XAxiDma_StartBdRingHw(XAxiDma_BdRing * RingPtr, +* int RingIndex) +* * XAxiDma_BdRingStart(XAxiDma_BdRing * RingPtr, +* int RingIndex) +* * XAxiDma_BdRingToHw(XAxiDma_BdRing * RingPtr, +* int NumBd, XAxiDma_Bd * BdSetPtr, int RingIndex) +* * XAxiDma_BdRingDumpRegs(XAxiDma_BdRing * RingPtr, +* int RingIndex) +* * XAxiDma_BdRingSnapShotCurrBd(XAxiDma_BdRing * RingPtr, +* int RingIndex) +* * XAxiDma_BdSetLength(XAxiDma_Bd *BdPtr, +* u32 LenBytes, u32 LengthMask) +* * XAxiDma_BdGetActualLength(BdPtr, LengthMask) +* * XAxiDma_BdGetLength(BdPtr, LengthMask) +* +* - New APIs +* * XAxiDma_SelectKeyHole(XAxiDma *InstancePtr, +* int Direction, int Select) +* * XAxiDma_UpdateBdRingCDesc(XAxiDma_BdRing * RingPtr, +* int RingIndex) +* * XAxiDma_BdSetTId() +* * XAxiDma_BdGetTId() +* * XAxiDma_BdSetTDest() +* * XAxiDma_BdGetTDest() +* * XAxiDma_BdSetTUser() +* * XAxiDma_BdGetTUser() +* * XAxiDma_BdSetARCache() +* * XAxiDma_BdGetARCache() +* * XAxiDma_BdSetARUser() +* * XAxiDma_BdGetARUser() +* * XAxiDma_BdSetStride() +* * XAxiDma_BdGetStride() +* * XAxiDma_BdSetVSize() +* * XAxiDma_BdGetVSize() +* For xaxidma driver v7_00_a +* --------------------------------------------------- +* - New API +* * XAxiDma_GetRxIndexRing(InstancePtr, RingIndex) +* +* - Changed APIs +* All the APIs changed in v6_00_a are reverted back for backward +* compatibility. +*
+* +******************************************************************************/ +/** @} */ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/axidma_v9_9/src/xaxidma_selftest.c b/datalink814_sp/bsp/microblaze_ps/libsrc/axidma_v9_9/src/xaxidma_selftest.c new file mode 100644 index 0000000..1a249c5 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/axidma_v9_9/src/xaxidma_selftest.c @@ -0,0 +1,111 @@ +/****************************************************************************** +* +* Copyright (C) 2015 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xaxidma_selftest.c +* @addtogroup axidma_v9_9 +* @{ +* +* Contains diagnostic/self-test functions for the XAxiDma component. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 8.1 	adk  29/01/15 First release
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xil_io.h" +#include "xaxidma.h" + + +/************************** Constant Definitions *****************************/ +#define XAXIDMA_RESET_TIMEOUT 500 + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + + +/************************** Variable Definitions *****************************/ + + +/*****************************************************************************/ +/** +* +* Runs a self-test on the driver/device. This test perform a +* reset of the DMA device and checks the device is coming out of reset or not +* +* @param InstancePtr is a pointer to the XAxiDma instance. +* +* @return +* - XST_SUCCESS if self-test was successful +* - XST_FAILURE if the device is not coming out of reset. +* +* @note +* None. +* +******************************************************************************/ +int XAxiDma_Selftest(XAxiDma * InstancePtr) +{ + int TimeOut; + + Xil_AssertNonvoid(InstancePtr != NULL); + + XAxiDma_Reset(InstancePtr); + + /* At the initialization time, hardware should finish reset quickly + */ + TimeOut = XAXIDMA_RESET_TIMEOUT; + + while (TimeOut) { + + if(XAxiDma_ResetIsDone(InstancePtr)) { + break; + } + + TimeOut -= 1; + + } + + if (!TimeOut) + return XST_FAILURE; + + return XST_SUCCESS; +} +/** @} */ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/axidma_v9_9/src/xaxidma_sinit.c b/datalink814_sp/bsp/microblaze_ps/libsrc/axidma_v9_9/src/xaxidma_sinit.c new file mode 100644 index 0000000..776989e --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/axidma_v9_9/src/xaxidma_sinit.c @@ -0,0 +1,126 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xaxidma_sinit.c +* @addtogroup axidma_v9_9 +* @{ +* +* Look up the hardware settings using device ID. The hardware setting is inside +* the configuration table in xaxidma_g.c, generated automatically by XPS or +* manually by the user. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a jz   08/16/10 First release
+* 2.00a jz   08/10/10 Second release, added in xaxidma_g.c, xaxidma_sinit.c,
+*                     updated tcl file, added xaxidma_porting_guide.h
+* 3.00a jz   11/22/10 Support IP core parameters change
+* 5.00a srt  08/29/11 Removed a compiler warning
+* 9.5   rsp  11/01/17 Add interface to do config lookup based on base address.
+* 9.6   rsp  01/11/18 In LookupConfig use UINTPTR for Baseaddr CR#976392
+*
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xparameters.h" +#include "xaxidma.h" + + +/*****************************************************************************/ +/** + * Look up the hardware configuration for a device instance + * + * @param DeviceId is the unique device ID of the device to lookup for + * + * @return + * The configuration structure for the device. If the device ID is + * not found,a NULL pointer is returned. + * + * @note None + * + ******************************************************************************/ +XAxiDma_Config *XAxiDma_LookupConfig(u32 DeviceId) +{ + extern XAxiDma_Config XAxiDma_ConfigTable[]; + XAxiDma_Config *CfgPtr; + u32 Index; + + CfgPtr = NULL; + + for (Index = 0; Index < XPAR_XAXIDMA_NUM_INSTANCES; Index++) { + if (XAxiDma_ConfigTable[Index].DeviceId == DeviceId) { + + CfgPtr = &XAxiDma_ConfigTable[Index]; + break; + } + } + + return CfgPtr; +} + +/*****************************************************************************/ +/** + * Look up the hardware configuration for a device instance based on base address + * + * @param Baseaddr is the base address of the device to lookup for + * + * @return + * The configuration structure for the device. If the device base + * address is not found,a NULL pointer is returned. + * + * @note None + * + ******************************************************************************/ +XAxiDma_Config *XAxiDma_LookupConfigBaseAddr(UINTPTR Baseaddr) +{ + extern XAxiDma_Config XAxiDma_ConfigTable[]; + XAxiDma_Config *CfgPtr; + u32 Index; + + CfgPtr = NULL; + + for (Index = 0; Index < XPAR_XAXIDMA_NUM_INSTANCES; Index++) { + if (XAxiDma_ConfigTable[Index].BaseAddr == Baseaddr) { + + CfgPtr = &XAxiDma_ConfigTable[Index]; + break; + } + } + + return CfgPtr; +} + +/** @} */ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/axidma_v9_9/src/xdebug.h b/datalink814_sp/bsp/microblaze_ps/libsrc/axidma_v9_9/src/xdebug.h new file mode 100644 index 0000000..9fc9a6e --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/axidma_v9_9/src/xdebug.h @@ -0,0 +1,89 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +#ifndef _XDEBUG_H +#define _XDEBUG_H + +#if defined(DEBUG) && !defined(NDEBUG) + +#include + +#ifndef XDEBUG_WARNING +#define XDEBUG_WARNING +#warning DEBUG is enabled +#endif + +#define XDBG_DEBUG_ERROR 0x00000001 /* error condition messages */ +#define XDBG_DEBUG_GENERAL 0x00000002 /* general debug messages */ +#define XDBG_DEBUG_ALL 0xFFFFFFFF /* all debugging data */ + +#define XDBG_DEBUG_FIFO_REG 0x00000100 /* display register reads/writes */ +#define XDBG_DEBUG_FIFO_RX 0x00000101 /* receive debug messages */ +#define XDBG_DEBUG_FIFO_TX 0x00000102 /* transmit debug messages */ +#define XDBG_DEBUG_FIFO_ALL 0x0000010F /* all fifo debug messages */ + +#define XDBG_DEBUG_TEMAC_REG 0x00000400 /* display register reads/writes */ +#define XDBG_DEBUG_TEMAC_RX 0x00000401 /* receive debug messages */ +#define XDBG_DEBUG_TEMAC_TX 0x00000402 /* transmit debug messages */ +#define XDBG_DEBUG_TEMAC_ALL 0x0000040F /* all temac debug messages */ + +#define XDBG_DEBUG_TEMAC_ADPT_RX 0x00000800 /* receive debug messages */ +#define XDBG_DEBUG_TEMAC_ADPT_TX 0x00000801 /* transmit debug messages */ +#define XDBG_DEBUG_TEMAC_ADPT_IOCTL 0x00000802 /* ioctl debug messages */ +#define XDBG_DEBUG_TEMAC_ADPT_MISC 0x00000803 /* debug msg for other routines */ +#define XDBG_DEBUG_TEMAC_ADPT_ALL 0x0000080F /* all temac adapter debug messages */ + +#define xdbg_current_types (XDBG_DEBUG_ERROR) + +#define xdbg_stmnt(x) x + +/* In VxWorks, if _WRS_GNU_VAR_MACROS is defined, special syntax is needed for + * macros that accept variable number of arguments + */ +#if defined(XENV_VXWORKS) && defined(_WRS_GNU_VAR_MACROS) +#define xdbg_printf(type, args...) (((type) & xdbg_current_types) ? printf (## args) : 0) + +#else /* ANSI Syntax */ + +#define xdbg_printf(type, ...) (((type) & xdbg_current_types) ? printf (__VA_ARGS__) : 0) + +#endif + +#else /* defined(DEBUG) && !defined(NDEBUG) */ + +#define xdbg_stmnt(x) + +/* See VxWorks comments above */ +#if defined(XENV_VXWORKS) && defined(_WRS_GNU_VAR_MACROS) +#define xdbg_printf(type, args...) +#else /* ANSI Syntax */ +#define xdbg_printf(...) +#endif + +#endif /* defined(DEBUG) && !defined(NDEBUG) */ + +#endif /* _XDEBUG_H */ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/bram_v4_3/src/Makefile b/datalink814_sp/bsp/microblaze_ps/libsrc/bram_v4_3/src/Makefile new file mode 100644 index 0000000..dce15aa --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/bram_v4_3/src/Makefile @@ -0,0 +1,28 @@ +COMPILER= +ARCHIVER= +CP=cp +COMPILER_FLAGS= +EXTRA_COMPILER_FLAGS= +LIB=libxil.a + +RELEASEDIR=../../../lib +INCLUDEDIR=../../../include +INCLUDES=-I./. -I${INCLUDEDIR} + +INCLUDEFILES=*.h + +LIBSOURCES=*.c +OUTS = *.o +OBJECTS = $(addsuffix .o, $(basename $(wildcard *.c))) + +libs: + echo "Compiling bram" + $(COMPILER) $(COMPILER_FLAGS) $(EXTRA_COMPILER_FLAGS) $(INCLUDES) $(LIBSOURCES) + $(ARCHIVER) -r ${RELEASEDIR}/${LIB} $(OBJECTS) + make clean + +include: + ${CP} ${INCLUDEFILES} ${INCLUDEDIR} + +clean: + rm -rf ${OBJECTS} diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/bram_v4_3/src/xbram.c b/datalink814_sp/bsp/microblaze_ps/libsrc/bram_v4_3/src/xbram.c new file mode 100644 index 0000000..0976b82 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/bram_v4_3/src/xbram.c @@ -0,0 +1,145 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +/** +* @file xbram.c +* @addtogroup bram_v4_2 +* @{ +* +* The implementation of the XBram driver's basic functionality. +* See xbram.h for more information about the driver. +* +* @note +* +* None +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a sa   05/11/10 First release
+* 3.01a sa   13/01/12 Added CorrectableFailingDataRegs and
+*                     UncorrectableFailingDataRegs in
+*					  XBram_CfgInitialize API.
+* 4.1   sk   11/10/15 Used UINTPTR instead of u32 for Baseaddress CR# 867425.
+*                     Changed the prototype of XBram_CfgInitialize API.
+*
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ + +#include "xbram.h" +#include "xstatus.h" + +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Variable Definitions ****************************/ + + +/************************** Function Prototypes *****************************/ + + +/****************************************************************************/ +/** +* Initialize the XBram instance provided by the caller based on the given +* configuration data. +* +* Nothing is done except to initialize the InstancePtr. +* +* @param InstancePtr is a pointer to an XBram instance. +* The memory the pointer references must be pre-allocated by +* the caller. Further calls to manipulate the driver through +* the XBram API must be made with this pointer. +* @param Config is a reference to a structure containing information +* about a specific BRAM device. This function +* initializes an InstancePtr object for a specific device +* specified by the contents of Config. This function can +* initialize multiple instance objects with the use of multiple +* calls giving different Config information on each call. +* @param EffectiveAddr is the device base address in the virtual memory +* address space. The caller is responsible for keeping the +* address mapping from EffectiveAddr to the device physical base +* address unchanged once this function is invoked. Unexpected +* errors may occur if the address mapping changes after this +* function is called. If address translation is not used, use +* Config->BaseAddress for this parameters, passing the physical +* address instead. +* +* @return +* - XST_SUCCESS Initialization was successful. +* +* @note None. +* +*****************************************************************************/ +int XBram_CfgInitialize(XBram *InstancePtr, + XBram_Config *Config, + UINTPTR EffectiveAddr) +{ + /* + * Assert arguments + */ + Xil_AssertNonvoid(InstancePtr != NULL); + + /* + * Set some default values. + */ + InstancePtr->Config.CtrlBaseAddress = EffectiveAddr; + InstancePtr->Config.MemBaseAddress = Config->MemBaseAddress; + InstancePtr->Config.MemHighAddress = Config->MemHighAddress; + InstancePtr->Config.DataWidth = Config->DataWidth; + InstancePtr->Config.EccPresent = Config->EccPresent; + InstancePtr->Config.FaultInjectionPresent = + Config->FaultInjectionPresent; + InstancePtr->Config.CorrectableFailingRegisters = + Config->CorrectableFailingRegisters; + InstancePtr->Config.CorrectableFailingDataRegs = + Config->CorrectableFailingDataRegs; + InstancePtr->Config.UncorrectableFailingRegisters = + Config->UncorrectableFailingRegisters; + InstancePtr->Config.UncorrectableFailingDataRegs = + Config->UncorrectableFailingDataRegs; + InstancePtr->Config.EccStatusInterruptPresent = + Config->EccStatusInterruptPresent; + InstancePtr->Config.CorrectableCounterBits = + Config->CorrectableCounterBits; + InstancePtr->Config.WriteAccess = Config->WriteAccess; + + /* + * Indicate the instance is now ready to use, initialized without error + */ + InstancePtr->IsReady = XIL_COMPONENT_IS_READY; + return (XST_SUCCESS); +} + +/** @} */ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/bram_v4_3/src/xbram.h b/datalink814_sp/bsp/microblaze_ps/libsrc/bram_v4_3/src/xbram.h new file mode 100644 index 0000000..246df6d --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/bram_v4_3/src/xbram.h @@ -0,0 +1,223 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file xbram.h +* @addtogroup bram_v4_2 +* @{ +* @details +* +* If ECC is not enabled, this driver exists only to allow the tools to +* create a memory test application and to populate xparameters.h with memory +* range constants. In this case there is no source code. +* +* If ECC is enabled, this file contains the software API definition of the +* Xilinx BRAM Interface Controller (XBram) device driver. +* +* The Xilinx BRAM controller is a soft IP core designed for Xilinx +* FPGAs and contains the following general features: +* - LMB v2.0 bus interfaces with byte enable support +* - Used in conjunction with bram_block peripheral to provide fast BRAM +* memory solution for MicroBlaze ILMB and DLMB ports +* - Supports byte, half-word, and word transfers +* - Supports optional BRAM error correction and detection. +* +* The driver provides interrupt management functions. Implementation of +* interrupt handlers is left to the user. Refer to the provided interrupt +* example in the examples directory for details. +* +* This driver is intended to be RTOS and processor independent. Any needs for +* dynamic memory management, threads or thread mutual exclusion, virtual +* memory, or cache control must be satisfied by the layer above this driver. +* +* Initialization & Configuration +* +* The XBram_Config structure is used by the driver to configure +* itself. This configuration structure is typically created by the tool-chain +* based on HW build properties. +* +* To support multiple runtime loading and initialization strategies employed +* by various operating systems, the driver instance can be initialized as +* follows: +* +* - XBram_CfgInitialize(InstancePtr, CfgPtr, EffectiveAddr) - +* Uses a configuration structure provided by the caller. If running in a +* system with address translation, the provided virtual memory base address +* replaces the physical address present in the configuration structure. +* +* @note +* +* This API utilizes 32 bit I/O to the BRAM registers. With less +* than 32 bits, the unused bits from registers are read as zero and written as +* don't cares. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 3.00a sa  05/11/10 Added ECC support
+* 3.01a sa  01/13/12  Changed Selftest API from
+*		      XBram_SelfTest(XBram *InstancePtr) to
+*		      XBram_SelfTest(XBram *InstancePtr, u8 IntMask) and
+*		      fixed a problem with interrupt generation for CR 639274
+*		      Modified Selftest example to return XST_SUCCESS when
+*		      ECC is not enabled and return XST_FAILURE when ECC is
+*		      enabled and Control Base Address is zero (CR 636581)
+*		      Modified Selftest to use correct CorrectableCounterBits
+*		      for CR 635655
+*		      Updated to check CorrectableFailingDataRegs in the case
+*		      of LMB BRAM.
+* 		      Added CorrectableFailingDataRegs and
+*		      UncorrectableFailingDataRegs to the config structure to
+*		      distinguish between AXI BRAM and LMB BRAM.
+*		      These registers are not present in the current version of
+*		      the AXI BRAM Controller.
+* 3.02a sa 04/16/12   Added test of byte and halfword read-modify-write
+* 3.02a sa 04/16/12   Modified driver tcl to sort the address parameters
+*  	       	      to support both xps and vivado designs.
+* 3.02a adk 24/4/13   Modified the tcl file to avoid warnings
+*	       	      when ecc is disabled cr:705002.
+* 3.03a bss 05/22/13  Added Xil_DCacheFlushRange in xbram_selftest.c to
+*		      flush the Cache after writing to BRAM in InjectErrors
+*		      API(CR #719011)
+* 4.0   adk  19/12/13 Updated as per the New Tcl API's
+* 4.1   sk   11/10/15 Used UINTPTR instead of u32 for Baseaddress CR# 867425.
+*                     Changed the prototype of XBram_CfgInitialize API.
+*       ms  01/23/17 Modified xil_printf statement in main function for all
+*                    examples to ensure that "Successfully ran" and "Failed"
+*                    strings are available in all examples. This is a fix
+*                    for CR-965028.
+*       ms  03/17/17 Added readme.txt file in examples folder for doxygen
+*                    generation.
+* 4.2   ms  04/18/17 Modified tcl file to add suffix U for all macro
+*                    definitions of bram in xparameters.h
+*       ms  08/07/17 Fixed compilation warnings in xbram_sinit.c
+* 4.3   aru 03/23/19 Used UINTPTR instead of u32 for MemBaseAddress and
+*                    MemHighAddress.
+* 
+*****************************************************************************/ +#ifndef XBRAM_H /* prevent circular inclusions */ +#define XBRAM_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files ********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xstatus.h" +#include "xbram_hw.h" + +/************************** Constant Definitions ****************************/ + + +/**************************** Type Definitions ******************************/ + +/** + * This typedef contains configuration information for the device. + */ +typedef struct { + u16 DeviceId; /**< Unique ID of device */ + u32 DataWidth; /**< BRAM data width */ + int EccPresent; /**< Is ECC supported in H/W */ + int FaultInjectionPresent; /**< Is Fault Injection + * supported in H/W */ + int CorrectableFailingRegisters; /**< Is Correctable Failing Registers + * supported in H/W */ + int CorrectableFailingDataRegs; /**< Is Correctable Failing Data + * Registers supported in H/W */ + int UncorrectableFailingRegisters; /**< Is Un-correctable Failing + * Registers supported in H/W */ + int UncorrectableFailingDataRegs; /**< Is Un-correctable Failing Data + * Registers supported in H/W */ + int EccStatusInterruptPresent; /**< Are ECC status and interrupts + * supported in H/W */ + int CorrectableCounterBits; /**< Number of bits in the + * Correctable Error Counter */ + int EccOnOffRegister; /**< Is ECC on/off register supported + * in h/w */ + int EccOnOffResetValue; /**< Reset value of the ECC on/off + * register in h/w */ + int WriteAccess; /**< Is write access enabled in + * h/w */ + UINTPTR MemBaseAddress; /**< Device memory base address */ + UINTPTR MemHighAddress; /**< Device memory high address */ + UINTPTR CtrlBaseAddress; /**< Device register base address.*/ + UINTPTR CtrlHighAddress; /**< Device register base address.*/ +} XBram_Config; + +/** + * The XBram driver instance data. The user is required to + * allocate a variable of this type for every BRAM device in the + * system. A pointer to a variable of this type is then passed to the driver + * API functions. + */ +typedef struct { + XBram_Config Config; /* BRAM config structure */ + u32 IsReady; /* Device is initialized and ready */ +} XBram; + +/***************** Macros (Inline Functions) Definitions ********************/ + + +/************************** Function Prototypes *****************************/ + +/* + * Functions in xbram_sinit.c + */ +XBram_Config *XBram_LookupConfig(u16 DeviceId); + +/* + * Functions implemented in xbram.c + */ +int XBram_CfgInitialize(XBram *InstancePtr, XBram_Config *Config, + UINTPTR EffectiveAddr); + +/* + * Functions implemented in xbram_selftest.c + */ +int XBram_SelfTest(XBram *InstancePtr, u8 IntMask); + +/* + * Functions implemented in xbram_intr.c + */ +void XBram_InterruptEnable(XBram *InstancePtr, u32 Mask); +void XBram_InterruptDisable(XBram *InstancePtr, u32 Mask); +void XBram_InterruptClear(XBram *InstancePtr, u32 Mask); +u32 XBram_InterruptGetEnabled(XBram *InstancePtr); +u32 XBram_InterruptGetStatus(XBram *InstancePtr); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/bram_v4_3/src/xbram_g.c b/datalink814_sp/bsp/microblaze_ps/libsrc/bram_v4_3/src/xbram_g.c new file mode 100644 index 0000000..5c6859a --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/bram_v4_3/src/xbram_g.c @@ -0,0 +1,180 @@ + +/******************************************************************* +* +* CAUTION: This file is automatically generated by HSI. +* Version: 2019.1.3 +* DO NOT EDIT. +* +* Copyright (C) 2010-2023 Xilinx, Inc. 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 +*XILINX 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. +* +*Except as contained in this notice, the name of the Xilinx shall not be used +*in advertising or otherwise to promote the sale, use or other dealings in +*this Software without prior written authorization from Xilinx. +* + +* +* Description: Driver configuration +* +*******************************************************************/ + +#include "xparameters.h" +#include "xbram.h" + +/* +* The configuration table for devices +*/ + +XBram_Config XBram_ConfigTable[] = +{ + { + XPAR_ANT_CONFIG_BRAM_CTRL_DEVICE_ID, + XPAR_ANT_CONFIG_BRAM_CTRL_DATA_WIDTH, + XPAR_ANT_CONFIG_BRAM_CTRL_ECC, + XPAR_ANT_CONFIG_BRAM_CTRL_FAULT_INJECT, + XPAR_ANT_CONFIG_BRAM_CTRL_CE_FAILING_REGISTERS, + 0, + XPAR_ANT_CONFIG_BRAM_CTRL_UE_FAILING_REGISTERS, + 0, + XPAR_ANT_CONFIG_BRAM_CTRL_ECC_STATUS_REGISTERS, + XPAR_ANT_CONFIG_BRAM_CTRL_CE_COUNTER_WIDTH, + XPAR_ANT_CONFIG_BRAM_CTRL_ECC_ONOFF_REGISTER, + XPAR_ANT_CONFIG_BRAM_CTRL_ECC_ONOFF_RESET_VALUE, + XPAR_ANT_CONFIG_BRAM_CTRL_WRITE_ACCESS, + XPAR_ANT_CONFIG_BRAM_CTRL_S_AXI_BASEADDR, + XPAR_ANT_CONFIG_BRAM_CTRL_S_AXI_HIGHADDR, + XPAR_ANT_CONFIG_BRAM_CTRL_S_AXI_CTRL_BASEADDR, + XPAR_ANT_CONFIG_BRAM_CTRL_S_AXI_CTRL_HIGHADDR + }, + { + XPAR_C2C_RX_AXI_BRAM_CTRL_DEVICE_ID, + XPAR_C2C_RX_AXI_BRAM_CTRL_DATA_WIDTH, + XPAR_C2C_RX_AXI_BRAM_CTRL_ECC, + XPAR_C2C_RX_AXI_BRAM_CTRL_FAULT_INJECT, + XPAR_C2C_RX_AXI_BRAM_CTRL_CE_FAILING_REGISTERS, + 0, + XPAR_C2C_RX_AXI_BRAM_CTRL_UE_FAILING_REGISTERS, + 0, + XPAR_C2C_RX_AXI_BRAM_CTRL_ECC_STATUS_REGISTERS, + XPAR_C2C_RX_AXI_BRAM_CTRL_CE_COUNTER_WIDTH, + XPAR_C2C_RX_AXI_BRAM_CTRL_ECC_ONOFF_REGISTER, + XPAR_C2C_RX_AXI_BRAM_CTRL_ECC_ONOFF_RESET_VALUE, + XPAR_C2C_RX_AXI_BRAM_CTRL_WRITE_ACCESS, + XPAR_C2C_RX_AXI_BRAM_CTRL_S_AXI_BASEADDR, + XPAR_C2C_RX_AXI_BRAM_CTRL_S_AXI_HIGHADDR, + XPAR_C2C_RX_AXI_BRAM_CTRL_S_AXI_CTRL_BASEADDR, + XPAR_C2C_RX_AXI_BRAM_CTRL_S_AXI_CTRL_HIGHADDR + }, + { + XPAR_C2C_TX_AXI_BRAM_CTRL_DEVICE_ID, + XPAR_C2C_TX_AXI_BRAM_CTRL_DATA_WIDTH, + XPAR_C2C_TX_AXI_BRAM_CTRL_ECC, + XPAR_C2C_TX_AXI_BRAM_CTRL_FAULT_INJECT, + XPAR_C2C_TX_AXI_BRAM_CTRL_CE_FAILING_REGISTERS, + 0, + XPAR_C2C_TX_AXI_BRAM_CTRL_UE_FAILING_REGISTERS, + 0, + XPAR_C2C_TX_AXI_BRAM_CTRL_ECC_STATUS_REGISTERS, + XPAR_C2C_TX_AXI_BRAM_CTRL_CE_COUNTER_WIDTH, + XPAR_C2C_TX_AXI_BRAM_CTRL_ECC_ONOFF_REGISTER, + XPAR_C2C_TX_AXI_BRAM_CTRL_ECC_ONOFF_RESET_VALUE, + XPAR_C2C_TX_AXI_BRAM_CTRL_WRITE_ACCESS, + XPAR_C2C_TX_AXI_BRAM_CTRL_S_AXI_BASEADDR, + XPAR_C2C_TX_AXI_BRAM_CTRL_S_AXI_HIGHADDR, + XPAR_C2C_TX_AXI_BRAM_CTRL_S_AXI_CTRL_BASEADDR, + XPAR_C2C_TX_AXI_BRAM_CTRL_S_AXI_CTRL_HIGHADDR + }, + { + XPAR_MICROBLAZE_PS_LOCAL_MEMORY_DLMB_BRAM_IF_CNTLR_DEVICE_ID, + XPAR_MICROBLAZE_PS_LOCAL_MEMORY_DLMB_BRAM_IF_CNTLR_DATA_WIDTH, + XPAR_MICROBLAZE_PS_LOCAL_MEMORY_DLMB_BRAM_IF_CNTLR_ECC, + XPAR_MICROBLAZE_PS_LOCAL_MEMORY_DLMB_BRAM_IF_CNTLR_FAULT_INJECT, + XPAR_MICROBLAZE_PS_LOCAL_MEMORY_DLMB_BRAM_IF_CNTLR_CE_FAILING_REGISTERS, + XPAR_MICROBLAZE_PS_LOCAL_MEMORY_DLMB_BRAM_IF_CNTLR_CE_FAILING_REGISTERS, + XPAR_MICROBLAZE_PS_LOCAL_MEMORY_DLMB_BRAM_IF_CNTLR_UE_FAILING_REGISTERS, + XPAR_MICROBLAZE_PS_LOCAL_MEMORY_DLMB_BRAM_IF_CNTLR_UE_FAILING_REGISTERS, + XPAR_MICROBLAZE_PS_LOCAL_MEMORY_DLMB_BRAM_IF_CNTLR_ECC_STATUS_REGISTERS, + XPAR_MICROBLAZE_PS_LOCAL_MEMORY_DLMB_BRAM_IF_CNTLR_CE_COUNTER_WIDTH, + XPAR_MICROBLAZE_PS_LOCAL_MEMORY_DLMB_BRAM_IF_CNTLR_ECC_ONOFF_REGISTER, + XPAR_MICROBLAZE_PS_LOCAL_MEMORY_DLMB_BRAM_IF_CNTLR_ECC_ONOFF_RESET_VALUE, + XPAR_MICROBLAZE_PS_LOCAL_MEMORY_DLMB_BRAM_IF_CNTLR_WRITE_ACCESS, + XPAR_MICROBLAZE_PS_LOCAL_MEMORY_DLMB_BRAM_IF_CNTLR_BASEADDR, + XPAR_MICROBLAZE_PS_LOCAL_MEMORY_DLMB_BRAM_IF_CNTLR_HIGHADDR, + XPAR_MICROBLAZE_PS_LOCAL_MEMORY_DLMB_BRAM_IF_CNTLR_S_AXI_CTRL_BASEADDR, + XPAR_MICROBLAZE_PS_LOCAL_MEMORY_DLMB_BRAM_IF_CNTLR_S_AXI_CTRL_HIGHADDR + }, + { + XPAR_MICROBLAZE_PS_LOCAL_MEMORY_ILMB_BRAM_IF_CNTLR_DEVICE_ID, + XPAR_MICROBLAZE_PS_LOCAL_MEMORY_ILMB_BRAM_IF_CNTLR_DATA_WIDTH, + XPAR_MICROBLAZE_PS_LOCAL_MEMORY_ILMB_BRAM_IF_CNTLR_ECC, + XPAR_MICROBLAZE_PS_LOCAL_MEMORY_ILMB_BRAM_IF_CNTLR_FAULT_INJECT, + XPAR_MICROBLAZE_PS_LOCAL_MEMORY_ILMB_BRAM_IF_CNTLR_CE_FAILING_REGISTERS, + XPAR_MICROBLAZE_PS_LOCAL_MEMORY_ILMB_BRAM_IF_CNTLR_CE_FAILING_REGISTERS, + XPAR_MICROBLAZE_PS_LOCAL_MEMORY_ILMB_BRAM_IF_CNTLR_UE_FAILING_REGISTERS, + XPAR_MICROBLAZE_PS_LOCAL_MEMORY_ILMB_BRAM_IF_CNTLR_UE_FAILING_REGISTERS, + XPAR_MICROBLAZE_PS_LOCAL_MEMORY_ILMB_BRAM_IF_CNTLR_ECC_STATUS_REGISTERS, + XPAR_MICROBLAZE_PS_LOCAL_MEMORY_ILMB_BRAM_IF_CNTLR_CE_COUNTER_WIDTH, + XPAR_MICROBLAZE_PS_LOCAL_MEMORY_ILMB_BRAM_IF_CNTLR_ECC_ONOFF_REGISTER, + XPAR_MICROBLAZE_PS_LOCAL_MEMORY_ILMB_BRAM_IF_CNTLR_ECC_ONOFF_RESET_VALUE, + XPAR_MICROBLAZE_PS_LOCAL_MEMORY_ILMB_BRAM_IF_CNTLR_WRITE_ACCESS, + XPAR_MICROBLAZE_PS_LOCAL_MEMORY_ILMB_BRAM_IF_CNTLR_BASEADDR, + XPAR_MICROBLAZE_PS_LOCAL_MEMORY_ILMB_BRAM_IF_CNTLR_HIGHADDR, + XPAR_MICROBLAZE_PS_LOCAL_MEMORY_ILMB_BRAM_IF_CNTLR_S_AXI_CTRL_BASEADDR, + XPAR_MICROBLAZE_PS_LOCAL_MEMORY_ILMB_BRAM_IF_CNTLR_S_AXI_CTRL_HIGHADDR + }, + { + XPAR_RX_FRAME_BRAM_CTRL_DEVICE_ID, + XPAR_RX_FRAME_BRAM_CTRL_DATA_WIDTH, + XPAR_RX_FRAME_BRAM_CTRL_ECC, + XPAR_RX_FRAME_BRAM_CTRL_FAULT_INJECT, + XPAR_RX_FRAME_BRAM_CTRL_CE_FAILING_REGISTERS, + 0, + XPAR_RX_FRAME_BRAM_CTRL_UE_FAILING_REGISTERS, + 0, + XPAR_RX_FRAME_BRAM_CTRL_ECC_STATUS_REGISTERS, + XPAR_RX_FRAME_BRAM_CTRL_CE_COUNTER_WIDTH, + XPAR_RX_FRAME_BRAM_CTRL_ECC_ONOFF_REGISTER, + XPAR_RX_FRAME_BRAM_CTRL_ECC_ONOFF_RESET_VALUE, + XPAR_RX_FRAME_BRAM_CTRL_WRITE_ACCESS, + XPAR_RX_FRAME_BRAM_CTRL_S_AXI_BASEADDR, + XPAR_RX_FRAME_BRAM_CTRL_S_AXI_HIGHADDR, + XPAR_RX_FRAME_BRAM_CTRL_S_AXI_CTRL_BASEADDR, + XPAR_RX_FRAME_BRAM_CTRL_S_AXI_CTRL_HIGHADDR + }, + { + XPAR_TX_FRAME_BRAM_CTRL_DEVICE_ID, + XPAR_TX_FRAME_BRAM_CTRL_DATA_WIDTH, + XPAR_TX_FRAME_BRAM_CTRL_ECC, + XPAR_TX_FRAME_BRAM_CTRL_FAULT_INJECT, + XPAR_TX_FRAME_BRAM_CTRL_CE_FAILING_REGISTERS, + 0, + XPAR_TX_FRAME_BRAM_CTRL_UE_FAILING_REGISTERS, + 0, + XPAR_TX_FRAME_BRAM_CTRL_ECC_STATUS_REGISTERS, + XPAR_TX_FRAME_BRAM_CTRL_CE_COUNTER_WIDTH, + XPAR_TX_FRAME_BRAM_CTRL_ECC_ONOFF_REGISTER, + XPAR_TX_FRAME_BRAM_CTRL_ECC_ONOFF_RESET_VALUE, + XPAR_TX_FRAME_BRAM_CTRL_WRITE_ACCESS, + XPAR_TX_FRAME_BRAM_CTRL_S_AXI_BASEADDR, + XPAR_TX_FRAME_BRAM_CTRL_S_AXI_HIGHADDR, + XPAR_TX_FRAME_BRAM_CTRL_S_AXI_CTRL_BASEADDR, + XPAR_TX_FRAME_BRAM_CTRL_S_AXI_CTRL_HIGHADDR + } +}; + + diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/bram_v4_3/src/xbram_hw.h b/datalink814_sp/bsp/microblaze_ps/libsrc/bram_v4_3/src/xbram_hw.h new file mode 100644 index 0000000..55a2505 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/bram_v4_3/src/xbram_hw.h @@ -0,0 +1,405 @@ +/****************************************************************************** +* +* Copyright (C) 2011 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xbram_hw.h +* @addtogroup bram_v4_2 +* @{ +* +* This header file contains identifiers and driver functions (or +* macros) that can be used to access the device. The user should refer to the +* hardware device specification for more details of the device operation. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a sa   24/11/10 First release
+* 
+* +******************************************************************************/ +#ifndef XBRAM_HW_H /* prevent circular inclusions */ +#define XBRAM_HW_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_io.h" + +/************************** Constant Definitions *****************************/ + +/** @name Registers + * + * Register offsets for this device. + * @{ + */ + +#define XBRAM_ECC_STATUS_OFFSET 0x0 /**< ECC status Register */ +#define XBRAM_ECC_EN_IRQ_OFFSET 0x4 /**< ECC interrupt enable Register */ +#define XBRAM_ECC_ON_OFF_OFFSET 0x8 /**< ECC on/off register */ +#define XBRAM_CE_CNT_OFFSET 0xC /**< Correctable error counter Register */ + +#define XBRAM_CE_FFD_0_OFFSET 0x100 /**< Correctable error first failing + * data Register, 31-0 */ +#define XBRAM_CE_FFD_1_OFFSET 0x104 /**< Correctable error first failing + * data Register, 63-32 */ +#define XBRAM_CE_FFD_2_OFFSET 0x108 /**< Correctable error first failing + * data Register, 95-64 */ +#define XBRAM_CE_FFD_3_OFFSET 0x10C /**< Correctable error first failing + * data Register, 127-96 */ +#define XBRAM_CE_FFD_4_OFFSET 0x110 /**< Correctable error first failing + * data Register, 159-128 */ +#define XBRAM_CE_FFD_5_OFFSET 0x114 /**< Correctable error first failing + * data Register, 191-160 */ +#define XBRAM_CE_FFD_6_OFFSET 0x118 /**< Correctable error first failing + * data Register, 223-192 */ +#define XBRAM_CE_FFD_7_OFFSET 0x11C /**< Correctable error first failing + * data Register, 255-224 */ +#define XBRAM_CE_FFD_8_OFFSET 0x120 /**< Correctable error first failing + * data Register, 287-256 */ +#define XBRAM_CE_FFD_9_OFFSET 0x124 /**< Correctable error first failing + * data Register, 319-288 */ +#define XBRAM_CE_FFD_10_OFFSET 0x128 /**< Correctable error first failing + * data Register, 351-320 */ +#define XBRAM_CE_FFD_11_OFFSET 0x12C /**< Correctable error first failing + * data Register, 383-352 */ +#define XBRAM_CE_FFD_12_OFFSET 0x130 /**< Correctable error first failing + * data Register, 415-384 */ +#define XBRAM_CE_FFD_13_OFFSET 0x134 /**< Correctable error first failing + * data Register, 447-416 */ +#define XBRAM_CE_FFD_14_OFFSET 0x138 /**< Correctable error first failing + * data Register, 479-448 */ +#define XBRAM_CE_FFD_15_OFFSET 0x13C /**< Correctable error first failing + * data Register, 511-480 */ +#define XBRAM_CE_FFD_16_OFFSET 0x140 /**< Correctable error first failing + * data Register, 543-512 */ +#define XBRAM_CE_FFD_17_OFFSET 0x144 /**< Correctable error first failing + * data Register, 575-544 */ +#define XBRAM_CE_FFD_18_OFFSET 0x148 /**< Correctable error first failing + * data Register, 607-576 */ +#define XBRAM_CE_FFD_19_OFFSET 0x14C /**< Correctable error first failing + * data Register, 639-608 */ +#define XBRAM_CE_FFD_20_OFFSET 0x150 /**< Correctable error first failing + * data Register, 671-640 */ +#define XBRAM_CE_FFD_21_OFFSET 0x154 /**< Correctable error first failing + * data Register, 703-672 */ +#define XBRAM_CE_FFD_22_OFFSET 0x158 /**< Correctable error first failing + * data Register, 735-704 */ +#define XBRAM_CE_FFD_23_OFFSET 0x15C /**< Correctable error first failing + * data Register, 767-736 */ +#define XBRAM_CE_FFD_24_OFFSET 0x160 /**< Correctable error first failing + * data Register, 799-768 */ +#define XBRAM_CE_FFD_25_OFFSET 0x164 /**< Correctable error first failing + * data Register, 831-800 */ +#define XBRAM_CE_FFD_26_OFFSET 0x168 /**< Correctable error first failing + * data Register, 863-832 */ +#define XBRAM_CE_FFD_27_OFFSET 0x16C /**< Correctable error first failing + * data Register, 895-864 */ +#define XBRAM_CE_FFD_28_OFFSET 0x170 /**< Correctable error first failing + * data Register, 927-896 */ +#define XBRAM_CE_FFD_29_OFFSET 0x174 /**< Correctable error first failing + * data Register, 959-928 */ +#define XBRAM_CE_FFD_30_OFFSET 0x178 /**< Correctable error first failing + * data Register, 991-960 */ +#define XBRAM_CE_FFD_31_OFFSET 0x17C /**< Correctable error first failing + * data Register, 1023-992 */ + +#define XBRAM_CE_FFE_0_OFFSET 0x180 /**< Correctable error first failing + * ECC Register, 31-0 */ +#define XBRAM_CE_FFE_1_OFFSET 0x184 /**< Correctable error first failing + * ECC Register, 63-32 */ +#define XBRAM_CE_FFE_2_OFFSET 0x188 /**< Correctable error first failing + * ECC Register, 95-64 */ +#define XBRAM_CE_FFE_3_OFFSET 0x18C /**< Correctable error first failing + * ECC Register, 127-96 */ +#define XBRAM_CE_FFE_4_OFFSET 0x190 /**< Correctable error first failing + * ECC Register, 159-128 */ +#define XBRAM_CE_FFE_5_OFFSET 0x194 /**< Correctable error first failing + * ECC Register, 191-160 */ +#define XBRAM_CE_FFE_6_OFFSET 0x198 /**< Correctable error first failing + * ECC Register, 223-192 */ +#define XBRAM_CE_FFE_7_OFFSET 0x19C /**< Correctable error first failing + * ECC Register, 255-224 */ + +#define XBRAM_CE_FFA_0_OFFSET 0x1C0 /**< Correctable error first failing + * address Register 31-0 */ +#define XBRAM_CE_FFA_1_OFFSET 0x1C4 /**< Correctable error first failing + * address Register 63-32 */ + +#define XBRAM_UE_FFD_0_OFFSET 0x200 /**< Uncorrectable error first failing + * data Register, 31-0 */ +#define XBRAM_UE_FFD_1_OFFSET 0x204 /**< Uncorrectable error first failing + * data Register, 63-32 */ +#define XBRAM_UE_FFD_2_OFFSET 0x208 /**< Uncorrectable error first failing + * data Register, 95-64 */ +#define XBRAM_UE_FFD_3_OFFSET 0x20C /**< Uncorrectable error first failing + * data Register, 127-96 */ +#define XBRAM_UE_FFD_4_OFFSET 0x210 /**< Uncorrectable error first failing + * data Register, 159-128 */ +#define XBRAM_UE_FFD_5_OFFSET 0x214 /**< Uncorrectable error first failing + * data Register, 191-160 */ +#define XBRAM_UE_FFD_6_OFFSET 0x218 /**< Uncorrectable error first failing + * data Register, 223-192 */ +#define XBRAM_UE_FFD_7_OFFSET 0x21C /**< Uncorrectable error first failing + * data Register, 255-224 */ +#define XBRAM_UE_FFD_8_OFFSET 0x220 /**< Uncorrectable error first failing + * data Register, 287-256 */ +#define XBRAM_UE_FFD_9_OFFSET 0x224 /**< Uncorrectable error first failing + * data Register, 319-288 */ +#define XBRAM_UE_FFD_10_OFFSET 0x228 /**< Uncorrectable error first failing + * data Register, 351-320 */ +#define XBRAM_UE_FFD_11_OFFSET 0x22C /**< Uncorrectable error first failing + * data Register, 383-352 */ +#define XBRAM_UE_FFD_12_OFFSET 0x230 /**< Uncorrectable error first failing + * data Register, 415-384 */ +#define XBRAM_UE_FFD_13_OFFSET 0x234 /**< Uncorrectable error first failing + * data Register, 447-416 */ +#define XBRAM_UE_FFD_14_OFFSET 0x238 /**< Uncorrectable error first failing + * data Register, 479-448 */ +#define XBRAM_UE_FFD_15_OFFSET 0x23C /**< Uncorrectable error first failing + * data Register, 511-480 */ +#define XBRAM_UE_FFD_16_OFFSET 0x240 /**< Uncorrectable error first failing + * data Register, 543-512 */ +#define XBRAM_UE_FFD_17_OFFSET 0x244 /**< Uncorrectable error first failing + * data Register, 575-544 */ +#define XBRAM_UE_FFD_18_OFFSET 0x248 /**< Uncorrectable error first failing + * data Register, 607-576 */ +#define XBRAM_UE_FFD_19_OFFSET 0x24C /**< Uncorrectable error first failing + * data Register, 639-608 */ +#define XBRAM_UE_FFD_20_OFFSET 0x250 /**< Uncorrectable error first failing + * data Register, 671-640 */ +#define XBRAM_UE_FFD_21_OFFSET 0x254 /**< Uncorrectable error first failing + * data Register, 703-672 */ +#define XBRAM_UE_FFD_22_OFFSET 0x258 /**< Uncorrectable error first failing + * data Register, 735-704 */ +#define XBRAM_UE_FFD_23_OFFSET 0x25C /**< Uncorrectable error first failing + * data Register, 767-736 */ +#define XBRAM_UE_FFD_24_OFFSET 0x260 /**< Uncorrectable error first failing + * data Register, 799-768 */ +#define XBRAM_UE_FFD_25_OFFSET 0x264 /**< Uncorrectable error first failing + * data Register, 831-800 */ +#define XBRAM_UE_FFD_26_OFFSET 0x268 /**< Uncorrectable error first failing + * data Register, 863-832 */ +#define XBRAM_UE_FFD_27_OFFSET 0x26C /**< Uncorrectable error first failing + * data Register, 895-864 */ +#define XBRAM_UE_FFD_28_OFFSET 0x270 /**< Uncorrectable error first failing + * data Register, 927-896 */ +#define XBRAM_UE_FFD_29_OFFSET 0x274 /**< Uncorrectable error first failing + * data Register, 959-928 */ +#define XBRAM_UE_FFD_30_OFFSET 0x278 /**< Uncorrectable error first failing + * data Register, 991-960 */ +#define XBRAM_UE_FFD_31_OFFSET 0x27C /**< Uncorrectable error first failing + * data Register, 1023-992 */ + +#define XBRAM_UE_FFE_0_OFFSET 0x280 /**< Uncorrectable error first failing + * ECC Register, 31-0 */ +#define XBRAM_UE_FFE_1_OFFSET 0x284 /**< Uncorrectable error first failing + * ECC Register, 63-32 */ +#define XBRAM_UE_FFE_2_OFFSET 0x288 /**< Uncorrectable error first failing + * ECC Register, 95-64 */ +#define XBRAM_UE_FFE_3_OFFSET 0x28C /**< Uncorrectable error first failing + * ECC Register, 127-96 */ +#define XBRAM_UE_FFE_4_OFFSET 0x290 /**< Uncorrectable error first failing + * ECC Register, 159-128 */ +#define XBRAM_UE_FFE_5_OFFSET 0x294 /**< Uncorrectable error first failing + * ECC Register, 191-160 */ +#define XBRAM_UE_FFE_6_OFFSET 0x298 /**< Uncorrectable error first failing + * ECC Register, 223-192 */ +#define XBRAM_UE_FFE_7_OFFSET 0x29C /**< Uncorrectable error first failing + * ECC Register, 255-224 */ + +#define XBRAM_UE_FFA_0_OFFSET 0x2C0 /**< Uncorrectable error first failing + * address Register 31-0 */ +#define XBRAM_UE_FFA_1_OFFSET 0x2C4 /**< Uncorrectable error first failing + * address Register 63-32 */ + +#define XBRAM_FI_D_0_OFFSET 0x300 /**< Fault injection Data Register, + * 31-0 */ +#define XBRAM_FI_D_1_OFFSET 0x304 /**< Fault injection Data Register, + * 63-32 */ +#define XBRAM_FI_D_2_OFFSET 0x308 /**< Fault injection Data Register, + * 95-64 */ +#define XBRAM_FI_D_3_OFFSET 0x30C /**< Fault injection Data Register, + * 127-96 */ +#define XBRAM_FI_D_4_OFFSET 0x310 /**< Fault injection Data Register, + * 159-128 */ +#define XBRAM_FI_D_5_OFFSET 0x314 /**< Fault injection Data Register, + * 191-160 */ +#define XBRAM_FI_D_6_OFFSET 0x318 /**< Fault injection Data Register, + * 223-192 */ +#define XBRAM_FI_D_7_OFFSET 0x31C /**< Fault injection Data Register, + * 255-224 */ +#define XBRAM_FI_D_8_OFFSET 0x320 /**< Fault injection Data Register, + * 287-256 */ +#define XBRAM_FI_D_9_OFFSET 0x324 /**< Fault injection Data Register, + * 319-288 */ +#define XBRAM_FI_D_10_OFFSET 0x328 /**< Fault injection Data Register, + * 351-320 */ +#define XBRAM_FI_D_11_OFFSET 0x32C /**< Fault injection Data Register, + * 383-352 */ +#define XBRAM_FI_D_12_OFFSET 0x330 /**< Fault injection Data Register, + * 415-384 */ +#define XBRAM_FI_D_13_OFFSET 0x334 /**< Fault injection Data Register, + * 447-416 */ +#define XBRAM_FI_D_14_OFFSET 0x338 /**< Fault injection Data Register, + * 479-448 */ +#define XBRAM_FI_D_15_OFFSET 0x33C /**< Fault injection Data Register, + * 511-480 */ +#define XBRAM_FI_D_16_OFFSET 0x340 /**< Fault injection Data Register, + * 543-512 */ +#define XBRAM_FI_D_17_OFFSET 0x344 /**< Fault injection Data Register, + * 575-544 */ +#define XBRAM_FI_D_18_OFFSET 0x348 /**< Fault injection Data Register, + * 607-576 */ +#define XBRAM_FI_D_19_OFFSET 0x34C /**< Fault injection Data Register, + * 639-608 */ +#define XBRAM_FI_D_20_OFFSET 0x350 /**< Fault injection Data Register, + * 671-640 */ +#define XBRAM_FI_D_21_OFFSET 0x354 /**< Fault injection Data Register, + * 703-672 */ +#define XBRAM_FI_D_22_OFFSET 0x358 /**< Fault injection Data Register, + * 735-704 */ +#define XBRAM_FI_D_23_OFFSET 0x35C /**< Fault injection Data Register, + * 767-736 */ +#define XBRAM_FI_D_24_OFFSET 0x360 /**< Fault injection Data Register, + * 799-768 */ +#define XBRAM_FI_D_25_OFFSET 0x364 /**< Fault injection Data Register, + * 831-800 */ +#define XBRAM_FI_D_26_OFFSET 0x368 /**< Fault injection Data Register, + * 863-832 */ +#define XBRAM_FI_D_27_OFFSET 0x36C /**< Fault injection Data Register, + * 895-864 */ +#define XBRAM_FI_D_28_OFFSET 0x370 /**< Fault injection Data Register, + * 927-896 */ +#define XBRAM_FI_D_29_OFFSET 0x374 /**< Fault injection Data Register, + * 959-928 */ +#define XBRAM_FI_D_30_OFFSET 0x378 /**< Fault injection Data Register, + * 991-960 */ +#define XBRAM_FI_D_31_OFFSET 0x37C /**< Fault injection Data Register, + * 1023-992 */ + +#define XBRAM_FI_ECC_0_OFFSET 0x380 /**< Fault injection ECC Register, + * 31-0 */ +#define XBRAM_FI_ECC_1_OFFSET 0x384 /**< Fault injection ECC Register, + * 63-32 */ +#define XBRAM_FI_ECC_2_OFFSET 0x388 /**< Fault injection ECC Register, + * 95-64 */ +#define XBRAM_FI_ECC_3_OFFSET 0x38C /**< Fault injection ECC Register, + * 127-96 */ +#define XBRAM_FI_ECC_4_OFFSET 0x390 /**< Fault injection ECC Register, + * 159-128 */ +#define XBRAM_FI_ECC_5_OFFSET 0x394 /**< Fault injection ECC Register, + * 191-160 */ +#define XBRAM_FI_ECC_6_OFFSET 0x398 /**< Fault injection ECC Register, + * 223-192 */ +#define XBRAM_FI_ECC_7_OFFSET 0x39C /**< Fault injection ECC Register, + * 255-224 */ + + +/* @} */ + +/** @name Interrupt Status and Enable Register bitmaps and masks + * + * Bit definitions for the ECC status register and ECC interrupt enable register. + * @{ + */ +#define XBRAM_IR_CE_MASK 0x2 /**< Mask for the correctable error */ +#define XBRAM_IR_UE_MASK 0x1 /**< Mask for the uncorrectable error */ +#define XBRAM_IR_ALL_MASK 0x3 /**< Mask of all bits */ +/*@}*/ + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + +#define XBram_In32 Xil_In32 +#define XBram_Out32 Xil_Out32 + +#define XBram_In16 Xil_In16 +#define XBram_Out16 Xil_Out16 + +#define XBram_In8 Xil_In8 +#define XBram_Out8 Xil_Out8 + + +/****************************************************************************/ +/** +* +* Write a value to a BRAM register. A 32 bit write is performed. +* +* @param BaseAddress is the base address of the BRAM device register. +* @param RegOffset is the register offset from the base to write to. +* @param Data is the data written to the register. +* +* @return None. +* +* @note C-style signature: +* void XBram_WriteReg(u32 BaseAddress, u32 RegOffset, u32 Data) +* +****************************************************************************/ +#define XBram_WriteReg(BaseAddress, RegOffset, Data) \ + XBram_Out32((BaseAddress) + (RegOffset), (u32)(Data)) + +/****************************************************************************/ +/** +* +* Read a value from a BRAM register. A 32 bit read is performed. +* +* @param BaseAddress is the base address of the BRAM device registers. +* @param RegOffset is the register offset from the base to read from. +* +* @return Data read from the register. +* +* @note C-style signature: +* u32 XBram_ReadReg(u32 BaseAddress, u32 RegOffset) +* +****************************************************************************/ +#define XBram_ReadReg(BaseAddress, RegOffset) \ + XBram_In32((BaseAddress) + (RegOffset)) + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + + + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/bram_v4_3/src/xbram_intr.c b/datalink814_sp/bsp/microblaze_ps/libsrc/bram_v4_3/src/xbram_intr.c new file mode 100644 index 0000000..50644aa --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/bram_v4_3/src/xbram_intr.c @@ -0,0 +1,234 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +/*****************************************************************************/ +/** +* @file xbram_intr.c +* @addtogroup bram_v4_2 +* @{ +* +* Implements BRAM interrupt processing functions for the +* XBram driver. See xbram.h for more information +* about the driver. +* +* The functions in this file require the hardware device to be built with +* interrupt capabilities. The functions will assert if called using hardware +* that does not have interrupt capabilities. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a sa   05/11/10 Initial release
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ +#include "xbram.h" + + +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Variable Definitions ****************************/ + +/************************** Function Prototypes *****************************/ + + +/****************************************************************************/ +/** +* Enable interrupts. This function will assert if the hardware device has not +* been built with interrupt capabilities. +* +* @param InstancePtr is the BRAM instance to operate on. +* @param Mask is the mask to enable. Bit positions of 1 are enabled. +* This mask is formed by OR'ing bits from XBRAM_IR* +* bits which are contained in xbram_hw.h. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XBram_InterruptEnable(XBram *InstancePtr, u32 Mask) +{ + u32 Register; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(InstancePtr->Config.CtrlBaseAddress != 0); + + /* + * Read the interrupt enable register and only enable the specified + * interrupts without disabling or enabling any others. + */ + Register = XBram_ReadReg(InstancePtr->Config.CtrlBaseAddress, + XBRAM_ECC_EN_IRQ_OFFSET); + XBram_WriteReg(InstancePtr->Config.CtrlBaseAddress, + XBRAM_ECC_EN_IRQ_OFFSET, + Register | Mask); +} + + +/****************************************************************************/ +/** +* Disable interrupts. This function allows each specific interrupt to be +* disabled. This function will assert if the hardware device has not been +* built with interrupt capabilities. +* +* @param InstancePtr is the BRAM instance to operate on. +* @param Mask is the mask to disable. Bits set to 1 are disabled. This +* mask is formed by OR'ing bits from XBRAM_IR* bits +* which are contained in xbram_hw.h. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XBram_InterruptDisable(XBram *InstancePtr, u32 Mask) +{ + u32 Register; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(InstancePtr->Config.CtrlBaseAddress != 0); + + /* + * Read the interrupt enable register and only disable the specified + * interrupts without enabling or disabling any others. + */ + Register = XBram_ReadReg(InstancePtr->Config.CtrlBaseAddress, + XBRAM_ECC_EN_IRQ_OFFSET); + XBram_WriteReg(InstancePtr->Config.CtrlBaseAddress, + XBRAM_ECC_EN_IRQ_OFFSET, + Register & (~Mask)); +} + +/****************************************************************************/ +/** +* Clear pending interrupts with the provided mask. This function should be +* called after the software has serviced the interrupts that are pending. +* This function will assert if the hardware device has not been built with +* interrupt capabilities. +* +* @param InstancePtr is the BRAM instance to operate on. +* @param Mask is the mask to clear pending interrupts for. Bit positions +* of 1 are cleared. This mask is formed by OR'ing bits from +* XBRAM_IR* bits which are contained in +* xbram_hw.h. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XBram_InterruptClear(XBram *InstancePtr, u32 Mask) +{ + u32 Register; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(InstancePtr->Config.CtrlBaseAddress != 0); + + /* + * Read the interrupt status register and only clear the interrupts + * that are specified without affecting any others. Since the register + * is a toggle on write, make sure any bits to be written are already + * set. + */ + Register = XBram_ReadReg(InstancePtr->Config.CtrlBaseAddress, + XBRAM_ECC_STATUS_OFFSET); + XBram_WriteReg(InstancePtr->Config.CtrlBaseAddress, + XBRAM_ECC_STATUS_OFFSET, + Register & Mask); + + +} + + +/****************************************************************************/ +/** +* Returns the interrupt enable mask. This function will assert if the +* hardware device has not been built with interrupt capabilities. +* +* @param InstancePtr is the BRAM instance to operate on. +* +* @return A mask of bits made from XBRAM_IR* bits which +* are contained in xbram_hw.h. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +u32 XBram_InterruptGetEnabled(XBram * InstancePtr) +{ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(InstancePtr->Config.CtrlBaseAddress != 0); + + return XBram_ReadReg(InstancePtr->Config.CtrlBaseAddress, + XBRAM_ECC_EN_IRQ_OFFSET); +} + + +/****************************************************************************/ +/** +* Returns the status of interrupt signals. Any bit in the mask set to 1 +* indicates that the channel associated with the bit has asserted an interrupt +* condition. This function will assert if the hardware device has not been +* built with interrupt capabilities. +* +* @param InstancePtr is the BRAM instance to operate on. +* +* @return A pointer to a mask of bits made from XBRAM_IR* +* bits which are contained in xbram_hw.h. +* +* @note +* +* The interrupt status indicates the status of the device irregardless if +* the interrupts from the devices have been enabled or not through +* XBram_InterruptEnable(). +* +*****************************************************************************/ +u32 XBram_InterruptGetStatus(XBram * InstancePtr) +{ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(InstancePtr->Config.CtrlBaseAddress != 0); + + return XBram_ReadReg(InstancePtr->Config.CtrlBaseAddress, + XBRAM_ECC_EN_IRQ_OFFSET); +} +/** @} */ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/bram_v4_3/src/xbram_selftest.c b/datalink814_sp/bsp/microblaze_ps/libsrc/bram_v4_3/src/xbram_selftest.c new file mode 100644 index 0000000..e57e09c --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/bram_v4_3/src/xbram_selftest.c @@ -0,0 +1,557 @@ +/****************************************************************************** +* +* Copyright (C) 2011 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file xbram_selftest.c +* @addtogroup bram_v4_2 +* @{ +* +* The implementation of the XBram driver's self test function. This SelfTest +* is only applicable if ECC is enabled. +* If ECC is not enabled then this function will return XST_SUCCESS. +* See xbram.h for more information about the driver. +* Temp change +* +* @note +* +* None +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a sa   11/24/10 First release
+* 3.01a sa   01/13/12  Changed Selftest API from
+*		       XBram_SelfTest(XBram *InstancePtr) to
+*		       XBram_SelfTest(XBram *InstancePtr, u8 IntMask) and
+*		       fixed a problem with interrupt generation for CR 639274
+*		       Modified Selftest example to return XST_SUCCESS when
+*		       ECC is not enabled and return XST_FAILURE when ECC is
+*		       enabled and Control Base Address is zero (CR 636581)
+*		       Modified Selftest to use correct CorrectableCounterBits
+*		       for CR 635655
+*		       Updated to check CorrectableFailingDataRegs in the case
+*		       of LMB BRAM.
+* 3.02a sa  04/16/12   Added test of byte and halfword read-modify-write
+* 3.03a bss 05/22/13   Added Xil_DCacheFlushRange in InjectErrors API to
+*		       flush the Cache after writing to BRAM (CR #719011)
+* 4.3   aru 04/09/19   Used UINTPTR instead of u32 for Addr in XBram_SelfTest()
+*
+* 
+*****************************************************************************/ + +/***************************** Include Files ********************************/ +#include "xbram.h" +#include "xil_cache.h" +/************************** Constant Definitions ****************************/ +#define TOTAL_BITS 39 + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ +#define RD(reg) XBram_ReadReg(InstancePtr->Config.CtrlBaseAddress, \ + XBRAM_ ## reg) +#define WR(reg, data) XBram_WriteReg(InstancePtr->Config.CtrlBaseAddress, \ + XBRAM_ ## reg, data) + +#define CHECK(reg, data, result) if (result!=XST_SUCCESS || RD(reg)!=data) \ + result = XST_FAILURE; + +/************************** Variable Definitions ****************************/ +static u32 PrngResult; + +/************************** Function Prototypes *****************************/ +static inline u32 PrngData(u32 *PrngResult); + +static inline u32 CalculateEcc(u32 Data); + +static void InjectErrors(XBram * InstancePtr, UINTPTR Addr, + int Index1, int Index2, int Width, + u32 *ActualData, u32 *ActualEcc); + + +/*****************************************************************************/ +/** +* Generate a pseudo random number. +* +* @param The PrngResult is the previous random number in the pseudo +* random sequence, also knwon as the seed. It is modified to +* the calculated pseudo random number by the function. +* +* @return The generated pseudo random number +* +* @note None. +* +******************************************************************************/ +static inline u32 PrngData(u32 *PrngResult) +{ + *PrngResult = *PrngResult * 0x77D15E25 + 0x3617C161; + return *PrngResult; +} + + +/*****************************************************************************/ +/** +* Calculate ECC from Data. +* +* @param The Data Value +* +* @return The calculated ECC +* +* @note None. +* +******************************************************************************/ +static inline u32 CalculateEcc(u32 Data) +{ + unsigned char c[7], d[32]; + u32 Result = 0; + int Index; + + for (Index = 0; Index < 32; Index++) { + d[31 - Index] = Data & 1; + Data = Data >> 1; + } + + c[0] = d[0] ^ d[1] ^ d[3] ^ d[4] ^ d[6] ^ d[8] ^ d[10] ^ d[11] ^ + d[13] ^ d[15] ^ d[17] ^ d[19] ^ d[21] ^ d[23] ^ d[25] ^ d[26] ^ + d[28] ^ d[30]; + + c[1] = d[0] ^ d[2] ^ d[3] ^ d[5] ^ d[6] ^ d[9] ^ d[10] ^ d[12] ^ + d[13] ^ d[16] ^ d[17] ^ d[20] ^ d[21] ^ d[24] ^ d[25] ^ d[27] ^ + d[28] ^ d[31]; + + c[2] = d[1] ^ d[2] ^ d[3] ^ d[7] ^ d[8] ^ d[9] ^ d[10] ^ d[14] ^ + d[15] ^ d[16] ^ d[17] ^ d[22] ^ d[23] ^ d[24] ^ d[25] ^ d[29] ^ + d[30] ^ d[31]; + + c[3] = d[4] ^ d[5] ^ d[6] ^ d[7] ^ d[8] ^ d[9] ^ d[10] ^ d[18] ^ + d[19] ^ d[20] ^ d[21] ^ d[22] ^ d[23] ^ d[24] ^ d[25]; + + c[4] = d[11] ^ d[12] ^ d[13] ^ d[14] ^ d[15] ^ d[16] ^ d[17] ^ d[18] ^ + d[19] ^ d[20] ^ d[21] ^ d[22] ^ d[23] ^ d[24] ^ d[25]; + + c[5] = d[26] ^ d[27] ^ d[28] ^ d[29] ^ d[30] ^ d[31]; + + c[6] = d[0] ^ d[1] ^ d[2] ^ d[3] ^ d[4] ^ d[5] ^ d[6] ^ d[7] ^ + d[8] ^ d[9] ^ d[10] ^ d[11] ^ d[12] ^ d[13] ^ d[14] ^ d[15] ^ + d[16] ^ d[17] ^ d[18] ^ d[19] ^ d[20] ^ d[21] ^ d[22] ^ d[23] ^ + d[24] ^ d[25] ^ d[26] ^ d[27] ^ d[28] ^ d[29] ^ d[30] ^ d[31] ^ + c[5] ^ c[4] ^ c[3] ^ c[2] ^ c[1] ^ c[0]; + + for (Index = 0; Index < 7; Index++) { + Result = Result << 1; + Result |= c[Index] & 1; + } + + return Result; +} + +/*****************************************************************************/ +/** +* Get the expected actual data read in case of uncorrectable errors. +* +* @param The injected data value including errors (if any) +* @param The syndrome (calculated ecc ^ actual ecc read) +* +* @return The actual data value read +* +* @note None. +* +******************************************************************************/ +static inline u32 UncorrectableData(u32 Data, u8 Syndrome) +{ + switch (Syndrome) { + case 0x03: return Data ^ 0x00000034; + case 0x05: return Data ^ 0x001a2000; + case 0x09: return Data ^ 0x0d000000; + case 0x0d: return Data ^ 0x00001a00; + + case 0x11: return Data ^ 0x60000000; + case 0x13: return Data ^ 0x00000003; + case 0x15: return Data ^ 0x00018000; + case 0x19: return Data ^ 0x00c00000; + case 0x1d: return Data ^ 0x00000180; + + case 0x21: return Data ^ 0x80000000; + case 0x23: return Data ^ 0x00000008; + case 0x25: return Data ^ 0x00040000; + case 0x29: return Data ^ 0x02000000; + case 0x2d: return Data ^ 0x00000400; + + case 0x31: return Data ^ 0x10000000; + case 0x35: return Data ^ 0x00004000; + case 0x39: return Data ^ 0x00200000; + case 0x3d: return Data ^ 0x00000040; + } + return Data; +} + +/*****************************************************************************/ +/** +* Inject errors using the hardware fault injection functionality, and write +* random data and read it back using the indicated location. +* +* @param InstancePtr is a pointer to the XBram instance to +* be worked on. +* @param The Addr is the indicated memory location to use +* @param The Index1 is the bit location of the first injected error +* @param The Index2 is the bit location of the second injected error +* @param The Width is the data byte width +* @param The ActualData is filled in with expected data for checking +* @param The ActualEcc is filled in with expected ECC for checking +* +* @return None +* +* @note None. +* +******************************************************************************/ +static void InjectErrors(XBram * InstancePtr, UINTPTR Addr, + int Index1, int Index2, int Width, + u32 *ActualData, u32 *ActualEcc) +{ + u32 InjectedData = 0; + u32 InjectedEcc = 0; + u32 RandomData = PrngData(&PrngResult); + + if (Index1 < 32) { + InjectedData = 1 << Index1; + } else { + InjectedEcc = 1 << (Index1 - 32); + } + + if (Index2 < 32) { + InjectedData |= (1 << Index2); + } else { + InjectedEcc |= 1 << (Index2 - 32); + } + + WR(FI_D_0_OFFSET, InjectedData); + WR(FI_ECC_0_OFFSET, InjectedEcc); + + XBram_Out32(Addr, RandomData); + Xil_DCacheFlushRange(Addr, 4); + switch (Width) { + case 1: /* Byte - Write to do Read-Modify-Write */ + XBram_Out8(Addr, PrngData(&PrngResult) & 0xFF); + break; + case 2: /* Halfword - Write to do Read-Modify-Write */ + XBram_Out16(Addr, PrngData(&PrngResult) & 0xFFFF); + break; + case 4: /* Word - Read */ + (void) XBram_In32(Addr); + break; + } + *ActualData = InjectedData ^ RandomData; + *ActualEcc = InjectedEcc ^ CalculateEcc(RandomData); +} + + +/*****************************************************************************/ +/** +* Run a self-test on the driver/device. Unless fault injection is implemented +* in hardware, this function only does a minimal test in which available +* registers (if any) are written and read. +* +* With fault injection, all possible single-bit and double-bit errors are +* injected, and checked to the extent possible, given the implemented hardware. +* +* @param InstancePtr is a pointer to the XBram instance. +* @param IntMask is the interrupt mask to use. When testing +* with interrupts, this should be set to allow interrupt +* generation, otherwise it should be 0. +* +* @return +* - XST_SUCCESS if fault injection/detection is working properly OR +* if ECC is Not Enabled in the HW. +* - XST_FAILURE if the injected fault is not correctly detected or +* the Control Base Address is Zero when ECC is enabled. +* . +* +* If the BRAM device is not present in the +* hardware a bus error could be generated. Other indicators of a +* bus error, such as registers in bridges or buses, may be +* necessary to determine if this function caused a bus error. +* +* @note None. +* +******************************************************************************/ +int XBram_SelfTest(XBram *InstancePtr, u8 IntMask) +{ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + + + if (InstancePtr->Config.EccPresent == 0) { + return (XST_SUCCESS); + } + + if (InstancePtr->Config.CtrlBaseAddress == 0) { + return (XST_SUCCESS); + } + + /* + * Only 32-bit data width is supported as of yet. 64-bit and 128-bit + * widths will be supported in future. + */ + if (InstancePtr->Config.DataWidth != 32) + return (XST_SUCCESS); + + /* + * Read from the implemented readable registers in the hardware device. + */ + if (InstancePtr->Config.CorrectableFailingRegisters) { + (void) RD(CE_FFA_0_OFFSET); + } + if (InstancePtr->Config.CorrectableFailingDataRegs) { + (void) RD(CE_FFD_0_OFFSET); + (void) RD(CE_FFE_0_OFFSET); + } + if (InstancePtr->Config.UncorrectableFailingRegisters) { + (void) RD(UE_FFA_0_OFFSET); + } + if (InstancePtr->Config.UncorrectableFailingDataRegs) { + (void) RD(UE_FFD_0_OFFSET); + (void) RD(UE_FFE_0_OFFSET); + } + + /* + * Write and read the implemented read/write registers in the hardware + * device. + */ + if (InstancePtr->Config.EccStatusInterruptPresent) { + WR(ECC_EN_IRQ_OFFSET, 0); + if (RD(ECC_EN_IRQ_OFFSET) != 0) { + return (XST_FAILURE); + } + } + + if (InstancePtr->Config.CorrectableCounterBits > 0) { + u32 Value; + + /* Calculate counter max value */ + if (InstancePtr->Config.CorrectableCounterBits == 32) { + Value = 0xFFFFFFFF; + } else { + Value = (1 << + InstancePtr->Config.CorrectableCounterBits) - 1; + } + + WR(CE_CNT_OFFSET, Value); + if (RD(CE_CNT_OFFSET) != Value) { + return (XST_FAILURE); + } + + WR(CE_CNT_OFFSET, 0); + if (RD(CE_CNT_OFFSET) != 0) { + return (XST_FAILURE); + } + } + + /* + * If fault injection is implemented, inject all possible single-bit + * and double-bit errors, and check all observable effects. + */ + if (InstancePtr->Config.FaultInjectionPresent && + InstancePtr->Config.WriteAccess != 0) { + + const UINTPTR Addr[2] = {InstancePtr->Config.MemBaseAddress & + (UINTPTR)0xfffffffffffffffc, + InstancePtr->Config.MemHighAddress & + (UINTPTR)0xfffffffffffffffc}; + u32 SavedWords[2]; + u32 ActualData; + u32 ActualEcc; + u32 CounterValue = 0; + u32 CounterMax; + int WordIndex = 0; + int Result = XST_SUCCESS; + int Index1; + int Index2; + int Width; + + PrngResult = 42; /* Random seed */ + + /* Save two words in BRAM used for test */ + SavedWords[0] = XBram_In32(Addr[0]); + SavedWords[1] = XBram_In32(Addr[1]); + + for (Width = 1; Width <= 4; Width <<= 1) { + /* Calculate counter max value */ + if (InstancePtr->Config.CorrectableCounterBits == 32) { + CounterMax = 0xFFFFFFFF; + } else { + CounterMax =(1 << + InstancePtr->Config.CorrectableCounterBits) - 1; + } + + /* Inject and check all single bit errors */ + for (Index1 = 0; Index1 < TOTAL_BITS; Index1++) { + /* Save counter value */ + if (InstancePtr->Config.CorrectableCounterBits > 0) { + CounterValue = RD(CE_CNT_OFFSET); + } + + /* Inject single bit error */ + InjectErrors(InstancePtr, Addr[WordIndex], Index1, + Index1, Width, &ActualData, &ActualEcc); + + /* Check that CE is set */ + if (InstancePtr->Config.EccStatusInterruptPresent) { + CHECK(ECC_STATUS_OFFSET, + XBRAM_IR_CE_MASK, Result); + } + + /* Check that address, data, ECC are correct */ + if (InstancePtr->Config.CorrectableFailingRegisters) { + CHECK(CE_FFA_0_OFFSET, Addr[WordIndex], Result); + } + /* Checks are only for LMB BRAM */ + if (InstancePtr->Config.CorrectableFailingDataRegs) { + CHECK(CE_FFD_0_OFFSET, ActualData, Result); + CHECK(CE_FFE_0_OFFSET, ActualEcc, Result); + } + + /* Check that counter has incremented */ + if (InstancePtr->Config.CorrectableCounterBits > 0 && + CounterValue < CounterMax) { + CHECK(CE_CNT_OFFSET, + CounterValue + 1, Result); + } + + /* Restore correct data in the used word */ + XBram_Out32(Addr[WordIndex], SavedWords[WordIndex]); + + /* Allow interrupts to occur */ + /* Clear status register */ + if (InstancePtr->Config.EccStatusInterruptPresent) { + WR(ECC_EN_IRQ_OFFSET, IntMask); + WR(ECC_STATUS_OFFSET, XBRAM_IR_ALL_MASK); + WR(ECC_EN_IRQ_OFFSET, 0); + } + + /* Switch to the other word */ + WordIndex = WordIndex ^ 1; + + if (Result != XST_SUCCESS) break; + + } + + if (Result != XST_SUCCESS) { + return XST_FAILURE; + } + + for (Index1 = 0; Index1 < TOTAL_BITS; Index1++) { + for (Index2 = 0; Index2 < TOTAL_BITS; Index2++) { + if (Index1 != Index2) { + /* Inject double bit error */ + InjectErrors(InstancePtr, + Addr[WordIndex], + Index1, Index2, Width, + &ActualData, + &ActualEcc); + + /* Check that UE is set */ + if (InstancePtr->Config. + EccStatusInterruptPresent) { + CHECK(ECC_STATUS_OFFSET, + XBRAM_IR_UE_MASK, + Result); + } + + /* Check that address, data, ECC are correct */ + if (InstancePtr->Config. + UncorrectableFailingRegisters) { + CHECK(UE_FFA_0_OFFSET, Addr[WordIndex], + Result); + CHECK(UE_FFD_0_OFFSET, + ActualData, Result); + CHECK(UE_FFE_0_OFFSET, ActualEcc, + Result); + } + + /* Restore correct data in the used word */ + XBram_Out32(Addr[WordIndex], + SavedWords[WordIndex]); + + /* Allow interrupts to occur */ + /* Clear status register */ + if (InstancePtr->Config. + EccStatusInterruptPresent) { + WR(ECC_EN_IRQ_OFFSET, IntMask); + WR(ECC_STATUS_OFFSET, + XBRAM_IR_ALL_MASK); + WR(ECC_EN_IRQ_OFFSET, 0); + } + + /* Switch to the other word */ + WordIndex = WordIndex ^ 1; + } + if (Result != XST_SUCCESS) break; + } + if (Result != XST_SUCCESS) break; + } + + /* Check saturation of correctable error counter */ + if (InstancePtr->Config.CorrectableCounterBits > 0 && + Result == XST_SUCCESS) { + + WR(CE_CNT_OFFSET, CounterMax); + + InjectErrors(InstancePtr, Addr[WordIndex], 0, 0, + 4, &ActualData, &ActualEcc); + + CHECK(CE_CNT_OFFSET, CounterMax, Result); + } + + /* Restore the two words used for test */ + XBram_Out32(Addr[0], SavedWords[0]); + XBram_Out32(Addr[1], SavedWords[1]); + + /* Clear the Status Register. */ + if (InstancePtr->Config.EccStatusInterruptPresent) { + WR(ECC_STATUS_OFFSET, XBRAM_IR_ALL_MASK); + } + + /* Set Correctable Counter to zero */ + if (InstancePtr->Config.CorrectableCounterBits > 0) { + WR(CE_CNT_OFFSET, 0); + } + + if (Result != XST_SUCCESS) break; + + } /* Width loop */ + + return (Result); + } + + return (XST_SUCCESS); +} + +/** @} */ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/bram_v4_3/src/xbram_sinit.c b/datalink814_sp/bsp/microblaze_ps/libsrc/bram_v4_3/src/xbram_sinit.c new file mode 100644 index 0000000..adc560e --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/bram_v4_3/src/xbram_sinit.c @@ -0,0 +1,101 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2017 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file xbram_sinit.c +* @addtogroup bram_v4_2 +* @{ +* +* The implementation of the XBram driver's static initialzation +* functionality. +* +* @note +* +* None +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 2.01a jvb  10/13/05 First release
+* 2.11a mta  03/21/07 Updated to new coding style
+* 4.2   ms   08/07/17 Fixed compilation warnings.
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ + +#include "xstatus.h" +#include "xparameters.h" +#include "xbram.h" + +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Variable Definitions ****************************/ +extern XBram_Config XBram_ConfigTable[]; + +/************************** Function Prototypes *****************************/ + + +/*****************************************************************************/ +/** +* Lookup the device configuration based on the unique device ID. The table +* ConfigTable contains the configuration info for each device in the system. +* +* @param DeviceId is the device identifier to lookup. +* +* @return +* - A pointer of data type XBram_Config which +* points to the device configuration if DeviceID is found. +* - NULL if DeviceID is not found. +* +* @note None. +* +******************************************************************************/ +XBram_Config *XBram_LookupConfig(u16 DeviceId) +{ + XBram_Config *CfgPtr = NULL; + + u32 Index; + + for (Index = 0U; Index < XPAR_XBRAM_NUM_INSTANCES; Index++) { + if (XBram_ConfigTable[Index].DeviceId == DeviceId) { + CfgPtr = &XBram_ConfigTable[Index]; + break; + } + } + + return CfgPtr; +} +/** @} */ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/cpu_v2_9/src/Makefile b/datalink814_sp/bsp/microblaze_ps/libsrc/cpu_v2_9/src/Makefile new file mode 100644 index 0000000..95744ee --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/cpu_v2_9/src/Makefile @@ -0,0 +1,27 @@ +COMPILER= +ARCHIVER= +CP=cp +COMPILER_FLAGS= +EXTRA_COMPILER_FLAGS= +LIB=libxil.a + +RELEASEDIR=../../../lib +INCLUDEDIR=../../../include +INCLUDES=-I${INCLUDEDIR} + +OUTS = *.o +OBJECTS = $(addsuffix .o, $(basename $(wildcard *.c))) +LIBSOURCES=*.c +INCLUDEFILES=xio.h + +libs: + echo "Compiling cpu" + $(COMPILER) $(COMPILER_FLAGS) $(EXTRA_COMPILER_FLAGS) $(INCLUDES) $(LIBSOURCES) + $(ARCHIVER) -r ${RELEASEDIR}/${LIB} $(OBJECTS) + make clean + +include: + ${CP} ${INCLUDEFILES} ${INCLUDEDIR} + +clean: + rm -rf ${OBJECTS} diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/cpu_v2_9/src/fsl.h b/datalink814_sp/bsp/microblaze_ps/libsrc/cpu_v2_9/src/fsl.h new file mode 100644 index 0000000..329b141 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/cpu_v2_9/src/fsl.h @@ -0,0 +1,168 @@ +/****************************************************************************** +* +* Copyright (C) 2007 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file fsl.h +* @addtogroup cpu_v2_9 +* @{ +* +* This file contains macros for interfacing to the Fast Simplex Link (FSL) +* interface.. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- ---------------------------------------------------
+* 1.00a ecm  06/20/07 Initial version, moved over from bsp area
+* 1.11c ecm  08/26/08 Fixed the missing 'FSL_DEFAULT' define that was causing
+*					  assembly errors.
+* 
+* +* @note +* +* None. +* +******************************************************************************/ + + +#ifndef _FSL_H +#define _FSL_H + +/***************************** Include Files *********************************/ + + +#ifdef __cplusplus +extern "C" { +#endif +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/* if these have not been defined already, define here */ +#ifndef stringify + +/* necessary for pre-processor */ +#define stringify(s) tostring(s) +#define tostring(s) #s + +#endif /* stringify */ + +/* Extended FSL macros. These now replace all of the previous FSL macros */ +#define FSL_DEFAULT +#define FSL_NONBLOCKING n +#define FSL_EXCEPTION e +#define FSL_CONTROL c +#define FSL_ATOMIC a + +#define FSL_NONBLOCKING_EXCEPTION ne +#define FSL_NONBLOCKING_CONTROL nc +#define FSL_NONBLOCKING_ATOMIC na +#define FSL_EXCEPTION_CONTROL ec +#define FSL_EXCEPTION_ATOMIC ea +#define FSL_CONTROL_ATOMIC ca + +#define FSL_NONBLOCKING_EXCEPTION_CONTROL nec +#define FSL_NONBLOCKING_EXCEPTION_ATOMIC nea +#define FSL_NONBLOCKING_CONTROL_ATOMIC nca +#define FSL_EXCEPTION_CONTROL_ATOMIC eca + +#define FSL_NONBLOCKING_EXCEPTION_CONTROL_ATOMIC neca + +#define getfslx(val, id, flags) asm volatile (stringify(flags) "get\t%0,rfsl" stringify(id) : "=d" (val)) +#define putfslx(val, id, flags) asm volatile (stringify(flags) "put\t%0,rfsl" stringify(id) :: "d" (val)) + +#define tgetfslx(val, id, flags) asm volatile ("t" stringify(flags) "get\t%0,rfsl" stringify(id) : "=d" (val)) +#define tputfslx(id, flags) asm volatile ("t" stringify(flags) "put\trfsl" stringify(id)) + +#define getdfslx(val, var, flags) asm volatile (stringify(flags) "getd\t%0,%1" : "=d" (val) : "d" (var)) +#define putdfslx(val, var, flags) asm volatile (stringify(flags) "putd\t%0,%1" :: "d" (val), "d" (var)) + +#define tgetdfslx(val, var, flags) asm volatile ("t" stringify(flags) "getd\t%0,%1" : "=d" (val) : "d" (var)) +#define tputdfslx(var, flags) asm volatile ("t" stringify(flags) "putd\t%0" :: "d" (var)) + +/* if the mb_interface.h file has been included already, the following are not needed and will not be defined */ + +/* Legacy FSL Access Macros */ + +#ifndef getfsl + +/* Blocking Data Read and Write to FSL no. id */ +#define getfsl(val, id) asm volatile ("get\t%0,rfsl" stringify(id) : "=d" (val)) +#define putfsl(val, id) asm volatile ("put\t%0,rfsl" stringify(id) :: "d" (val)) + +/* Non-blocking Data Read and Write to FSL no. id */ +#define ngetfsl(val, id) asm volatile ("nget\t%0,rfsl" stringify(id) : "=d" (val)) +#define nputfsl(val, id) asm volatile ("nput\t%0,rfsl" stringify(id) :: "d" (val)) + +/* Blocking Control Read and Write to FSL no. id */ +#define cgetfsl(val, id) asm volatile ("cget\t%0,rfsl" stringify(id) : "=d" (val)) +#define cputfsl(val, id) asm volatile ("cput\t%0,rfsl" stringify(id) :: "d" (val)) + +/* Non-blocking Control Read and Write to FSL no. id */ +#define ncgetfsl(val, id) asm volatile ("ncget\t%0,rfsl" stringify(id) : "=d" (val)) +#define ncputfsl(val, id) asm volatile ("ncput\t%0,rfsl" stringify(id) :: "d" (val)) + +/* Polling versions of FSL access macros. This makes the FSL access interruptible */ +#define getfsl_interruptible(val, id) asm volatile ("\n1:\n\tnget\t%0,rfsl" stringify(id) "\n\t" \ + "addic\tr18,r0,0\n\t" \ + "bnei\tr18,1b\n" \ + : "=d" (val) :: "r18") + +#define putfsl_interruptible(val, id) asm volatile ("\n1:\n\tnput\t%0,rfsl" stringify(id) "\n\t" \ + "addic\tr18,r0,0\n\t" \ + "bnei\tr18,1b\n" \ + :: "d" (val) : "r18") + +#define cgetfsl_interruptible(val, id) asm volatile ("\n1:\n\tncget\t%0,rfsl" stringify(id) "\n\t" \ + "addic\tr18,r0,0\n\t" \ + "bnei\tr18,1b\n" \ + : "=d" (val) :: "r18") + +#define cputfsl_interruptible(val, id) asm volatile ("\n1:\n\tncput\t%0,rfsl" stringify(id) "\n\t" \ + "addic\tr18,r0,0\n\t" \ + "bnei\tr18,1b\n" \ + :: "d" (val) : "r18") +/* FSL valid and error check macros. */ +#define fsl_isinvalid(result) asm volatile ("addic\t%0,r0,0" : "=d" (result)) +#define fsl_iserror(error) asm volatile ("mfs\t%0,rmsr\n\t" \ + "andi\t%0,%0,0x10" : "=d" (error)) + +#endif /* legacy FSL defines */ +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +#ifdef __cplusplus +} +#endif +#endif /* _FSL_H */ +/** @} */ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/cpu_v2_9/src/xio.c b/datalink814_sp/bsp/microblaze_ps/libsrc/cpu_v2_9/src/xio.c new file mode 100644 index 0000000..6e6f152 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/cpu_v2_9/src/xio.c @@ -0,0 +1,226 @@ +/****************************************************************************** +* +* Copyright (C) 2007 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xio.c +* @addtogroup cpu_v2_9 +* @{ +* +* Contains I/O functions for memory-mapped or non-memory-mapped I/O +* architectures. These functions encapsulate generic CPU I/O requirements. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date	 Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a rpm  11/07/03 Added InSwap/OutSwap routines for endian conversion
+* 1.01a ecm  02/24/06 CR225908 corrected the extra curly braces in macros
+*                     and bumped version to 1.01.a.
+* 2.11a mta  03/21/07 Updated to new coding style.
+*
+* 
+* +* @note +* +* This file may contain architecture-dependent code. +* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xio.h" +#include "xil_types.h" +#include "xil_assert.h" + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + + +/*****************************************************************************/ +/** +* +* Performs a 16-bit endian converion. +* +* @param Source contains the value to be converted. +* @param DestPtr contains a pointer to the location to put the +* converted value. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XIo_EndianSwap16(u16 Source, u16 *DestPtr) +{ + *DestPtr = (u16) (((Source & 0xFF00) >> 8) | ((Source & 0x00FF) << 8)); +} + +/*****************************************************************************/ +/** +* +* Performs a 32-bit endian converion. +* +* @param Source contains the value to be converted. +* @param DestPtr contains a pointer to the location to put the +* converted value. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XIo_EndianSwap32(u32 Source, u32 *DestPtr) +{ + /* get each of the half words from the 32 bit word */ + + u16 LoWord = (u16) (Source & 0x0000FFFF); + u16 HiWord = (u16) ((Source & 0xFFFF0000) >> 16); + + /* byte swap each of the 16 bit half words */ + + LoWord = (((LoWord & 0xFF00) >> 8) | ((LoWord & 0x00FF) << 8)); + HiWord = (((HiWord & 0xFF00) >> 8) | ((HiWord & 0x00FF) << 8)); + + /* swap the half words before returning the value */ + + *DestPtr = (u32) ((LoWord << 16) | HiWord); +} + +/*****************************************************************************/ +/** +* +* Performs an input operation for a 16-bit memory location by reading from the +* specified address and returning the byte-swapped value read from that +* address. +* +* @param InAddress contains the address to perform the input +* operation at. +* +* @return The byte-swapped value read from the specified input address. +* +* @note None. +* +******************************************************************************/ +u16 XIo_InSwap16(XIo_Address InAddress) +{ + u16 InData; + + /* get the data then swap it */ + InData = XIo_In16(InAddress); + + return (u16) (((InData & 0xFF00) >> 8) | ((InData & 0x00FF) << 8)); +} + +/*****************************************************************************/ +/** +* +* Performs an input operation for a 32-bit memory location by reading from the +* specified address and returning the byte-swapped value read from that +* address. +* +* @param InAddress contains the address to perform the input +* operation at. +* +* @return The byte-swapped value read from the specified input address. +* +* @note None. +* +******************************************************************************/ +u32 XIo_InSwap32(XIo_Address InAddress) +{ + u32 InData; + u32 SwapData; + + /* get the data then swap it */ + InData = XIo_In32(InAddress); + XIo_EndianSwap32(InData, &SwapData); + + return SwapData; +} + +/*****************************************************************************/ +/** +* +* Performs an output operation for a 16-bit memory location by writing the +* specified value to the the specified address. The value is byte-swapped +* before being written. +* +* @param OutAddress contains the address to perform the output +* operation at. +* @param Value contains the value to be output at the specified address. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XIo_OutSwap16(XIo_Address OutAddress, u16 Value) +{ + u16 OutData; + + /* swap the data then output it */ + OutData = (u16) (((Value & 0xFF00) >> 8) | ((Value & 0x00FF) << 8)); + + XIo_Out16(OutAddress, OutData); +} + +/*****************************************************************************/ +/** +* +* Performs an output operation for a 32-bit memory location by writing the +* specified value to the the specified address. The value is byte-swapped +* before being written. +* +* @param OutAddress contains the address at which the +* output operation has to be done. +* @param Value contains the value to be output at the specified address. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XIo_OutSwap32(XIo_Address OutAddress, u32 Value) +{ + u32 OutData; + + /* swap the data then output it */ + XIo_EndianSwap32(Value, &OutData); + XIo_Out32(OutAddress, OutData); +} +/** @} */ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/cpu_v2_9/src/xio.h b/datalink814_sp/bsp/microblaze_ps/libsrc/cpu_v2_9/src/xio.h new file mode 100644 index 0000000..a923a4d --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/cpu_v2_9/src/xio.h @@ -0,0 +1,269 @@ +/****************************************************************************** +* +* Copyright (C) 2007 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xio.h +* @addtogroup cpu_v2_9 +* @{ +* @details +* +* This file contains the interface for the XIo component, which encapsulates +* the Input/Output functions for processors that do not require any special +* I/O handling. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a rpm  11/07/03 Added InSwap/OutSwap routines for endian conversion
+* 1.00a xd   11/04/04 Improved support for doxygen
+* 1.01a ecm  02/24/06 CR225908 corrected the extra curly braces in macros
+*                     and bumped version to 1.01.a.
+* 1.11a mta  03/21/07 Updated to new coding style.
+* 1.11b va   04/17/08 Updated Tcl for better CORE_CLOCK_FREQ_HZ definition
+* 1.11a sdm  03/12/09 Updated Tcl to define correct value for CORE_CLOCK_FREQ_HZ
+*                     (CR  #502010)
+* 1.13a sdm  03/12/09 Updated the Tcl to pull appropriate libraries for Little
+*                     Endian Microblaze
+* 2.0   adk  19/12/13 Updated as per the New Tcl API's
+* 2.1   bss  04/14/14 Updated tcl to copy libgloss.a and libgcc.a libraries
+* 2.1   bss  04/29/14 Updated to copy libgloss.a if exists otherwise libxil.a
+*			CR#794205
+* 2.2   bss  08/04/14 Updated driver tcl to add protection macros for
+*		      xparameters.h (CR#802257).
+* 2.3	sk	 12/15/14 Updated mdd file to delete �ffunction-sections &
+*					  -fdata-sections flags from extra compiler flags CR#838648
+*					  Changed default os to latest version in mdd file.
+* 2.4   nsk  11/05/15 Updated generate and post_generate procs in driver tcl
+*                     not to generate cpu macros, when microblaze is connected
+*                     as one of the streaming slaves to itself. CR#876604
+*
+* 
+* +* @note +* +* This file may contain architecture-dependent items (memory-mapped or +* non-memory-mapped I/O). +* +******************************************************************************/ + +#ifndef XIO_H /* prevent circular inclusions */ +#define XIO_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + +/** + * Typedef for an I/O address. Typically correlates to the width of the + * address bus. + */ +typedef u32 XIo_Address; + +/***************** Macros (Inline Functions) Definitions *********************/ + +/* + * The following macros allow optimized I/O operations for memory mapped I/O. + * It should be noted that macros cannot be used if synchronization of the I/O + * operation is needed as it will likely break some code. + */ + +/*****************************************************************************/ +/** +* +* Performs an input operation for an 8-bit memory location by reading from the +* specified address and returning the value read from that address. +* +* @param InputPtr contains the address to perform the input operation at. +* +* @return The value read from the specified input address. +* +* @note None. +* +******************************************************************************/ +#define XIo_In8(InputPtr) (*(volatile u8 *)(InputPtr)) + +/*****************************************************************************/ +/** +* +* Performs an input operation for a 16-bit memory location by reading from the +* specified address and returning the value read from that address. +* +* @param InputPtr contains the address to perform the input operation at. +* +* @return The value read from the specified input address. +* +* @note None. +* +******************************************************************************/ +#define XIo_In16(InputPtr) (*(volatile u16 *)(InputPtr)) + +/*****************************************************************************/ +/** +* +* Performs an input operation for a 32-bit memory location by reading from the +* specified address and returning the value read from that address. +* +* @param InputPtr contains the address to perform the input operation at. +* +* @return The value read from the specified input address. +* +* @note None. +* +******************************************************************************/ +#define XIo_In32(InputPtr) (*(volatile u32 *)(InputPtr)) + + +/*****************************************************************************/ +/** +* +* Performs an output operation for an 8-bit memory location by writing the +* specified value to the the specified address. +* +* @param OutputPtr contains the address to perform the output operation +* at. +* @param Value contains the value to be output at the specified address. +* +* @return None +* +* @note None. +* +******************************************************************************/ +#define XIo_Out8(OutputPtr, Value) \ + (*(volatile u8 *)((OutputPtr)) = (Value)) + +/*****************************************************************************/ +/** +* +* Performs an output operation for a 16-bit memory location by writing the +* specified value to the the specified address. +* +* @param OutputPtr contains the address to perform the output operation +* at. +* @param Value contains the value to be output at the specified address. +* +* @return None +* +* @note None. +* +******************************************************************************/ +#define XIo_Out16(OutputPtr, Value) \ + (*(volatile u16 *)((OutputPtr)) = (Value)) + +/*****************************************************************************/ +/** +* +* Performs an output operation for a 32-bit memory location by writing the +* specified value to the the specified address. +* +* @param OutputPtr contains the address to perform the output operation +* at. +* @param Value contains the value to be output at the specified address. +* +* @return None +* +* @note None. +* +******************************************************************************/ +#define XIo_Out32(OutputPtr, Value) \ + (*(volatile u32 *)((OutputPtr)) = (Value)) + + +/* The following macros allow the software to be transportable across + * processors which use big or little endian memory models. + * + * Defined first is a no-op endian conversion macro. This macro is not to + * be used directly by software. Instead, the XIo_To/FromLittleEndianXX and + * XIo_To/FromBigEndianXX macros below are to be used to allow the endian + * conversion to only be performed when necessary + */ +#define XIo_EndianNoop(Source, DestPtr) (*DestPtr = Source) + +#ifdef XLITTLE_ENDIAN + +#define XIo_ToLittleEndian16 XIo_EndianNoop +#define XIo_ToLittleEndian32 XIo_EndianNoop +#define XIo_FromLittleEndian16 XIo_EndianNoop +#define XIo_FromLittleEndian32 XIo_EndianNoop + +#define XIo_ToBigEndian16(Source, DestPtr) XIo_EndianSwap16(Source, DestPtr) +#define XIo_ToBigEndian32(Source, DestPtr) XIo_EndianSwap32(Source, DestPtr) +#define XIo_FromBigEndian16 XIo_ToBigEndian16 +#define XIo_FromBigEndian32 XIo_ToBigEndian32 + +#else + +#define XIo_ToLittleEndian16(Source, DestPtr) XIo_EndianSwap16(Source, DestPtr) +#define XIo_ToLittleEndian32(Source, DestPtr) XIo_EndianSwap32(Source, DestPtr) +#define XIo_FromLittleEndian16 XIo_ToLittleEndian16 +#define XIo_FromLittleEndian32 XIo_ToLittleEndian32 + +#define XIo_ToBigEndian16 XIo_EndianNoop +#define XIo_ToBigEndian32 XIo_EndianNoop +#define XIo_FromBigEndian16 XIo_EndianNoop +#define XIo_FromBigEndian32 XIo_EndianNoop + +#endif + +/************************** Function Prototypes ******************************/ + +/* The following functions allow the software to be transportable across + * processors which use big or little endian memory models. These functions + * should not be directly called, but the macros XIo_To/FromLittleEndianXX and + * XIo_To/FromBigEndianXX should be used to allow the endian conversion to only + * be performed when necessary. + */ +void XIo_EndianSwap16(u16 Source, u16 *DestPtr); +void XIo_EndianSwap32(u32 Source, u32 *DestPtr); + +/* The following functions handle IO addresses where data must be swapped + * They cannot be implemented as macros + */ +u16 XIo_InSwap16(XIo_Address InAddress); +u32 XIo_InSwap32(XIo_Address InAddress); +void XIo_OutSwap16(XIo_Address OutAddress, u16 Value); +void XIo_OutSwap32(XIo_Address OutAddress, u32 Value); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/gpio_v4_4/src/Makefile b/datalink814_sp/bsp/microblaze_ps/libsrc/gpio_v4_4/src/Makefile new file mode 100644 index 0000000..a98e2a0 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/gpio_v4_4/src/Makefile @@ -0,0 +1,40 @@ +COMPILER= +ARCHIVER= +CP=cp +COMPILER_FLAGS= +EXTRA_COMPILER_FLAGS= +LIB=libxil.a + +CC_FLAGS = $(COMPILER_FLAGS) +ECC_FLAGS = $(EXTRA_COMPILER_FLAGS) + +RELEASEDIR=../../../lib +INCLUDEDIR=../../../include +INCLUDES=-I./. -I${INCLUDEDIR} + +OUTS = *.o + +LIBSOURCES:=*.c +INCLUDEFILES:=*.h + +OBJECTS = $(addsuffix .o, $(basename $(wildcard *.c))) + +libs: banner xgpio_libs clean + +%.o: %.c + ${COMPILER} $(CC_FLAGS) $(ECC_FLAGS) $(INCLUDES) -o $@ $< + +banner: + echo "Compiling gpio" + +xgpio_libs: ${OBJECTS} + $(ARCHIVER) -r ${RELEASEDIR}/${LIB} ${OBJECTS} + +.PHONY: include +include: xgpio_includes + +xgpio_includes: + ${CP} ${INCLUDEFILES} ${INCLUDEDIR} + +clean: + rm -rf ${OBJECTS} diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/gpio_v4_4/src/xgpio.c b/datalink814_sp/bsp/microblaze_ps/libsrc/gpio_v4_4/src/xgpio.c new file mode 100644 index 0000000..a07e914 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/gpio_v4_4/src/xgpio.c @@ -0,0 +1,251 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file xgpio.c +* @addtogroup gpio_v4_4 +* @{ +* +* The implementation of the XGpio driver's basic functionality. See xgpio.h +* for more information about the driver. +* +* @note +* +* None +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a rmm  02/04/02 First release
+* 2.00a jhl  12/16/02 Update for dual channel and interrupt support
+* 2.01a jvb  12/13/05 Changed Initialize() into CfgInitialize(), and made
+*                     CfgInitialize() take a pointer to a config structure
+*                     instead of a device id. Moved Initialize() into
+*                     xgpio_sinit.c, and had Initialize() call CfgInitialize()
+*                     after it retrieved the config structure using the device
+*                     id. Removed include of xparameters.h along with any
+*                     dependencies on xparameters.h and the _g.c config table.
+* 2.11a mta  03/21/07 Updated to new coding style, added GetDataDirection
+* 2.12a sv   11/21/07 Updated driver to support access through DCR bus
+* 3.00a sv   11/21/09 Updated to use HAL Processor APIs. Renamed the
+*		      macros to remove _m from the name.
+* 4.1   lks  11/18/15 Clean up of the comments in the code and
+*		      removed support for DCR bridge
+* 4.2   sk   08/16/16 Used UINTPTR instead of u32 for Baseaddress as part of
+*                     adding 64 bit support. CR# 867425.
+*                     Changed the prototype of XGpio_CfgInitialize API.
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ + +#include "xgpio.h" +#include "xstatus.h" + +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Variable Definitions ****************************/ + + +/************************** Function Prototypes *****************************/ + + +/****************************************************************************/ +/** +* Initialize the XGpio instance provided by the caller based on the +* given configuration data. +* +* Nothing is done except to initialize the InstancePtr. +* +* @param InstancePtr is a pointer to an XGpio instance. The memory the +* pointer references must be pre-allocated by the caller. Further +* calls to manipulate the driver through the XGpio API must be +* made with this pointer. +* @param Config is a reference to a structure containing information +* about a specific GPIO device. This function initializes an +* InstancePtr object for a specific device specified by the +* contents of Config. This function can initialize multiple +* instance objects with the use of multiple calls giving different +* Config information on each call. +* @param EffectiveAddr is the device base address in the virtual memory +* address space. The caller is responsible for keeping the address +* mapping from EffectiveAddr to the device physical base address +* unchanged once this function is invoked. Unexpected errors may +* occur if the address mapping changes after this function is +* called. If address translation is not used, use +* Config->BaseAddress for this parameters, passing the physical +* address instead. +* +* @return +* - XST_SUCCESS if the initialization is successfull. +* +* @note None. +* +*****************************************************************************/ +int XGpio_CfgInitialize(XGpio * InstancePtr, XGpio_Config * Config, + UINTPTR EffectiveAddr) +{ + /* Assert arguments */ + Xil_AssertNonvoid(InstancePtr != NULL); + + /* Set some default values. */ + InstancePtr->BaseAddress = EffectiveAddr; + + InstancePtr->InterruptPresent = Config->InterruptPresent; + InstancePtr->IsDual = Config->IsDual; + + /* + * Indicate the instance is now ready to use, initialized without error + */ + InstancePtr->IsReady = XIL_COMPONENT_IS_READY; + return (XST_SUCCESS); +} + + +/****************************************************************************/ +/** +* Set the input/output direction of all discrete signals for the specified +* GPIO channel. +* +* @param InstancePtr is a pointer to an XGpio instance to be worked on. +* @param Channel contains the channel of the GPIO (1 or 2) to operate on. +* @param DirectionMask is a bitmask specifying which discretes are input +* and which are output. Bits set to 0 are output and bits set to 1 +* are input. +* +* @return None. +* +* @note The hardware must be built for dual channels if this function +* is used with any channel other than 1. If it is not, this +* function will assert. +* +*****************************************************************************/ +void XGpio_SetDataDirection(XGpio *InstancePtr, unsigned Channel, + u32 DirectionMask) +{ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid((Channel == 1) || + ((Channel == 2) && (InstancePtr->IsDual == TRUE))); + + XGpio_WriteReg(InstancePtr->BaseAddress, + ((Channel - 1) * XGPIO_CHAN_OFFSET) + XGPIO_TRI_OFFSET, + DirectionMask); +} + +/****************************************************************************/ +/** +* Get the input/output direction of all discrete signals for the specified +* GPIO channel. +* +* @param InstancePtr is a pointer to an XGpio instance to be worked on. +* @param Channel contains the channel of the GPIO (1 or 2) to operate on. +* +* @return Bitmask specifying which discretes are input and +* which are output. Bits set to 0 are output and bits set to 1 are +* input. +* +* @note +* +* The hardware must be built for dual channels if this function is used +* with any channel other than 1. If it is not, this function will assert. +* +*****************************************************************************/ +u32 XGpio_GetDataDirection(XGpio *InstancePtr, unsigned Channel) +{ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid((Channel == 1) || + ((Channel == 2) && + (InstancePtr->IsDual == TRUE))); + + return XGpio_ReadReg(InstancePtr->BaseAddress, + ((Channel - 1) * XGPIO_CHAN_OFFSET) + XGPIO_TRI_OFFSET); +} + +/****************************************************************************/ +/** +* Read state of discretes for the specified GPIO channnel. +* +* @param InstancePtr is a pointer to an XGpio instance to be worked on. +* @param Channel contains the channel of the GPIO (1 or 2) to operate on. +* +* @return Current copy of the discretes register. +* +* @note The hardware must be built for dual channels if this function +* is used with any channel other than 1. If it is not, this +* function will assert. +* +*****************************************************************************/ +u32 XGpio_DiscreteRead(XGpio * InstancePtr, unsigned Channel) +{ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid((Channel == 1) || + ((Channel == 2) && (InstancePtr->IsDual == TRUE))); + + return XGpio_ReadReg(InstancePtr->BaseAddress, + ((Channel - 1) * XGPIO_CHAN_OFFSET) + + XGPIO_DATA_OFFSET); +} + +/****************************************************************************/ +/** +* Write to discretes register for the specified GPIO channel. +* +* @param InstancePtr is a pointer to an XGpio instance to be worked on. +* @param Channel contains the channel of the GPIO (1 or 2) to operate on. +* @param Data is the value to be written to the discretes register. +* +* @return None. +* +* @note The hardware must be built for dual channels if this function +* is used with any channel other than 1. If it is not, this +* function will assert. See also XGpio_DiscreteSet() and +* XGpio_DiscreteClear(). +* +*****************************************************************************/ +void XGpio_DiscreteWrite(XGpio * InstancePtr, unsigned Channel, u32 Data) +{ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid((Channel == 1) || + ((Channel == 2) && (InstancePtr->IsDual == TRUE))); + + XGpio_WriteReg(InstancePtr->BaseAddress, + ((Channel - 1) * XGPIO_CHAN_OFFSET) + XGPIO_DATA_OFFSET, + Data); +} +/** @} */ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/gpio_v4_4/src/xgpio.h b/datalink814_sp/bsp/microblaze_ps/libsrc/gpio_v4_4/src/xgpio.h new file mode 100644 index 0000000..b498fe0 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/gpio_v4_4/src/xgpio.h @@ -0,0 +1,211 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file xgpio.h +* @addtogroup gpio_v4_4 +* @{ +* @details +* +* This file contains the software API definition of the Xilinx General Purpose +* I/O (XGpio) device driver. +* +* The Xilinx GPIO controller is a soft IP core designed for Xilinx FPGAs and +* contains the following general features: +* - Support for up to 32 I/O discretes for each channel (64 bits total). +* - Each of the discretes can be configured for input or output. +* - Configurable support for dual channels and interrupt generation. +* +* The driver provides interrupt management functions. Implementation of +* interrupt handlers is left to the user. Refer to the provided interrupt +* example in the examples directory for details. +* +* This driver is intended to be RTOS and processor independent. Any needs for +* dynamic memory management, threads or thread mutual exclusion, virtual +* memory, or cache control must be satisfied by the layer above this driver. +* +* Initialization & Configuration +* +* The XGpio_Config structure is used by the driver to configure itself. This +* configuration structure is typically created by the tool-chain based on HW +* build properties. +* +* To support multiple runtime loading and initialization strategies employed +* by various operating systems, the driver instance can be initialized in one +* of the following ways: +* +* - XGpio_Initialize(InstancePtr, DeviceId) - The driver looks up its own +* configuration structure created by the tool-chain based on an ID provided +* by the tool-chain. +* +* - XGpio_CfgInitialize(InstancePtr, CfgPtr, EffectiveAddr) - Uses a +* configuration structure provided by the caller. If running in a system +* with address translation, the provided virtual memory base address +* replaces the physical address present in the configuration structure. +* +* @note +* +* This API utilizes 32 bit I/O to the GPIO registers. With less than 32 bits, +* the unused bits from registers are read as zero and written as don't cares. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a rmm  03/13/02 First release
+* 2.00a jhl  11/26/03 Added support for dual channels and interrupts
+* 2.01a jvb  12/14/05 I separated dependency on the static config table and
+*                     xparameters.h from the driver initialization by moving
+*                     _Initialize and _LookupConfig to _sinit.c. I also added
+*                     the new _CfgInitialize routine.
+* 2.11a mta  03/21/07 Updated to new coding style, added GetDataDirection
+* 2.12a sv   11/21/07 Updated driver to support access through DCR bus
+* 2.12a sv   06/05/08 Updated driver to fix the XGpio_InterruptDisable function
+*		      to properly update the Interrupt Enable register
+* 2.13a sdm  08/22/08 Removed support for static interrupt handlers from the MDD
+*		      file
+* 3.00a sv   11/21/09 Updated to use HAL Processor APIs.
+*		      Renamed the macros XGpio_mWriteReg to XGpio_WriteReg and
+*		      XGpio_mReadReg to XGpio_ReadReg. Removed the macros
+*		      XGpio_mSetDataDirection, XGpio_mGetDataReg and
+*		      XGpio_mSetDataReg. Users should use XGpio_WriteReg and
+*		      XGpio_ReadReg to achieve the same functionality.
+* 3.01a bss  04/18/13 Updated driver tcl to generate Canonical params in
+*		      xparameters.h. CR#698589
+* 4.0   adk  19/12/13 Updated as per the New Tcl API's
+* 4.1   lks  11/18/15 Updated to use cannonical xparameters in examples and
+*		      clean up of the comments, removed support for DCR bridge
+*		      and removed xgpio_intr_example for CR 900381
+* 4.2   sk   08/16/16 Used UINTPTR instead of u32 for Baseaddress as part of
+*                     adding 64 bit support. CR# 867425.
+*                     Changed the prototype of XGpio_CfgInitialize API.
+* 4.3   sk   09/29/16 Modified the example to make it work when LED_bits are
+*                     configured as an output. CR# 958644
+*       ms   01/23/17 Added xil_printf statement in main function for all
+*                     examples to ensure that "Successfully ran" and "Failed"
+*                     strings are available in all examples. This is a fix
+*                     for CR-965028.
+*       ms   03/17/17 Added readme.txt file in examples folder for doxygen
+*                     generation.
+* 4.4   sne  04/25/19 Updated Makefile for IAR compier (CR-1029421).
+*
+* 
+*****************************************************************************/ + +#ifndef XGPIO_H /* prevent circular inclusions */ +#define XGPIO_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files ********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xstatus.h" +#include "xgpio_l.h" + +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + +/** + * This typedef contains configuration information for the device. + */ +typedef struct { + u16 DeviceId; /* Unique ID of device */ + UINTPTR BaseAddress; /* Device base address */ + int InterruptPresent; /* Are interrupts supported in h/w */ + int IsDual; /* Are 2 channels supported in h/w */ +} XGpio_Config; + +/** + * The XGpio driver instance data. The user is required to allocate a + * variable of this type for every GPIO device in the system. A pointer + * to a variable of this type is then passed to the driver API functions. + */ +typedef struct { + UINTPTR BaseAddress; /* Device base address */ + u32 IsReady; /* Device is initialized and ready */ + int InterruptPresent; /* Are interrupts supported in h/w */ + int IsDual; /* Are 2 channels supported in h/w */ +} XGpio; + +/***************** Macros (Inline Functions) Definitions ********************/ + + +/************************** Function Prototypes *****************************/ + +/* + * Initialization functions in xgpio_sinit.c + */ +int XGpio_Initialize(XGpio *InstancePtr, u16 DeviceId); +XGpio_Config *XGpio_LookupConfig(u16 DeviceId); + +/* + * API Basic functions implemented in xgpio.c + */ +int XGpio_CfgInitialize(XGpio *InstancePtr, XGpio_Config * Config, + UINTPTR EffectiveAddr); +void XGpio_SetDataDirection(XGpio *InstancePtr, unsigned Channel, + u32 DirectionMask); +u32 XGpio_GetDataDirection(XGpio *InstancePtr, unsigned Channel); +u32 XGpio_DiscreteRead(XGpio *InstancePtr, unsigned Channel); +void XGpio_DiscreteWrite(XGpio *InstancePtr, unsigned Channel, u32 Mask); + + +/* + * API Functions implemented in xgpio_extra.c + */ +void XGpio_DiscreteSet(XGpio *InstancePtr, unsigned Channel, u32 Mask); +void XGpio_DiscreteClear(XGpio *InstancePtr, unsigned Channel, u32 Mask); + +/* + * API Functions implemented in xgpio_selftest.c + */ +int XGpio_SelfTest(XGpio *InstancePtr); + +/* + * API Functions implemented in xgpio_intr.c + */ +void XGpio_InterruptGlobalEnable(XGpio *InstancePtr); +void XGpio_InterruptGlobalDisable(XGpio *InstancePtr); +void XGpio_InterruptEnable(XGpio *InstancePtr, u32 Mask); +void XGpio_InterruptDisable(XGpio *InstancePtr, u32 Mask); +void XGpio_InterruptClear(XGpio *InstancePtr, u32 Mask); +u32 XGpio_InterruptGetEnabled(XGpio *InstancePtr); +u32 XGpio_InterruptGetStatus(XGpio *InstancePtr); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/gpio_v4_4/src/xgpio_extra.c b/datalink814_sp/bsp/microblaze_ps/libsrc/gpio_v4_4/src/xgpio_extra.c new file mode 100644 index 0000000..af9a44b --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/gpio_v4_4/src/xgpio_extra.c @@ -0,0 +1,160 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file xgpio_extra.c +* @addtogroup gpio_v4_4 +* @{ +* +* The implementation of the XGpio driver's advanced discrete functions. +* See xgpio.h for more information about the driver. +* +* @note +* +* These APIs can only be used if the GPIO_IO ports in the IP are used for +* connecting to the external output ports. +* +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a rmm  02/04/02 First release
+* 2.00a jhl  12/16/02 Update for dual channel and interrupt support
+* 2.11a mta  03/21/07 Updated to new coding style
+* 3.00a sv   11/21/09 Updated to use HAL Processor APIs. Renamed the macros
+*		      XGpio_mWriteReg to XGpio_WriteReg, and XGpio_mReadReg
+*		      to XGpio_ReadReg.
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ + +#include "xgpio.h" +#include "xgpio_i.h" + +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Variable Definitions ****************************/ + +/************************** Function Prototypes *****************************/ + + +/****************************************************************************/ +/** +* Set output discrete(s) to logic 1 for the specified GPIO channel. +* +* @param InstancePtr is a pointer to an XGpio instance to be worked on. +* @param Channel contains the channel of the GPIO (1 or 2) to operate on. +* @param Mask is the set of bits that will be set to 1 in the discrete +* data register. All other bits in the data register are +* unaffected. +* +* @return None. +* +* @note +* +* The hardware must be built for dual channels if this function is used +* with any channel other than 1. If it is not, this function will assert. +* +* This API can only be used if the GPIO_IO ports in the IP are used for +* connecting to the external output ports. +* +*****************************************************************************/ +void XGpio_DiscreteSet(XGpio * InstancePtr, unsigned Channel, u32 Mask) +{ + u32 Current; + unsigned DataOffset; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid((Channel == 1) || + ((Channel == 2) && (InstancePtr->IsDual == TRUE))); + + /* Calculate the offset to the data register of the GPIO */ + DataOffset = ((Channel - 1) * XGPIO_CHAN_OFFSET) + XGPIO_DATA_OFFSET; + + /* + * Read the contents of the data register, merge in Mask and write + * back results + */ + Current = XGpio_ReadReg(InstancePtr->BaseAddress, DataOffset); + Current |= Mask; + XGpio_WriteReg(InstancePtr->BaseAddress, DataOffset, Current); +} + + +/****************************************************************************/ +/** +* Set output discrete(s) to logic 0 for the specified GPIO channel. +* +* @param InstancePtr is a pointer to an XGpio instance to be worked on. +* @param Channel contains the channel of the GPIO (1 or 2) to operate on. +* @param Mask is the set of bits that will be set to 0 in the discrete +* data register. All other bits in the data register are +* unaffected. +* +* @return None. +* +* @note +* +* The hardware must be built for dual channels if this function is used +* with any channel other than 1. If it is not, this function will assert. +* +* This API can only be used if the GPIO_IO ports in the IP are used for +* connecting to the external output ports. +* +*****************************************************************************/ +void XGpio_DiscreteClear(XGpio * InstancePtr, unsigned Channel, u32 Mask) +{ + u32 Current; + unsigned DataOffset; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid((Channel == 1) || + ((Channel == 2) && (InstancePtr->IsDual == TRUE))); + + /* Calculate the offset to the data register of the GPIO */ + DataOffset = ((Channel - 1) * XGPIO_CHAN_OFFSET) + XGPIO_DATA_OFFSET; + + /* + * Read the contents of the data register, merge in Mask and write + * back results + */ + Current = XGpio_ReadReg(InstancePtr->BaseAddress, DataOffset); + Current &= ~Mask; + XGpio_WriteReg(InstancePtr->BaseAddress, DataOffset, Current); +} +/** @} */ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/gpio_v4_4/src/xgpio_g.c b/datalink814_sp/bsp/microblaze_ps/libsrc/gpio_v4_4/src/xgpio_g.c new file mode 100644 index 0000000..9dd0fd4 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/gpio_v4_4/src/xgpio_g.c @@ -0,0 +1,65 @@ + +/******************************************************************* +* +* CAUTION: This file is automatically generated by HSI. +* Version: 2019.1.3 +* DO NOT EDIT. +* +* Copyright (C) 2010-2023 Xilinx, Inc. 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 +*XILINX 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. +* +*Except as contained in this notice, the name of the Xilinx shall not be used +*in advertising or otherwise to promote the sale, use or other dealings in +*this Software without prior written authorization from Xilinx. +* + +* +* Description: Driver configuration +* +*******************************************************************/ + +#include "xparameters.h" +#include "xgpio.h" + +/* +* The configuration table for devices +*/ + +XGpio_Config XGpio_ConfigTable[XPAR_XGPIO_NUM_INSTANCES] = +{ + { + XPAR_AXI_GPIO_DEVICE_ID, + XPAR_AXI_GPIO_BASEADDR, + XPAR_AXI_GPIO_INTERRUPT_PRESENT, + XPAR_AXI_GPIO_IS_DUAL + }, + { + XPAR_STATUS_GPIO_I_DEVICE_ID, + XPAR_STATUS_GPIO_I_BASEADDR, + XPAR_STATUS_GPIO_I_INTERRUPT_PRESENT, + XPAR_STATUS_GPIO_I_IS_DUAL + }, + { + XPAR_STATUS_GPIO_O_DEVICE_ID, + XPAR_STATUS_GPIO_O_BASEADDR, + XPAR_STATUS_GPIO_O_INTERRUPT_PRESENT, + XPAR_STATUS_GPIO_O_IS_DUAL + } +}; + + diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/gpio_v4_4/src/xgpio_i.h b/datalink814_sp/bsp/microblaze_ps/libsrc/gpio_v4_4/src/xgpio_i.h new file mode 100644 index 0000000..7938b0f --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/gpio_v4_4/src/xgpio_i.h @@ -0,0 +1,83 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/******************************************************************************/ +/** +* @file xgpio_i.h +* @addtogroup gpio_v4_3 +* @{ +* +* This header file contains internal identifiers, which are those shared +* between the files of the driver. It is intended for internal use only. +* +* NOTES: +* +* None. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a rmm  03/13/02 First release
+* 2.11a mta  03/21/07 Updated to new coding style
+* 
+******************************************************************************/ + +#ifndef XGPIO_I_H /* prevent circular inclusions */ +#define XGPIO_I_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xgpio.h" + +/************************** Constant Definitions ****************************/ + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + + +/************************** Variable Definitions ****************************/ + +extern XGpio_Config XGpio_ConfigTable[]; + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/gpio_v4_4/src/xgpio_intr.c b/datalink814_sp/bsp/microblaze_ps/libsrc/gpio_v4_4/src/xgpio_intr.c new file mode 100644 index 0000000..acbb084 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/gpio_v4_4/src/xgpio_intr.c @@ -0,0 +1,290 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file xgpio_intr.c +* @addtogroup gpio_v4_4 +* @{ +* +* Implements GPIO interrupt processing functions for the XGpio driver. +* See xgpio.h for more information about the driver. +* +* The functions in this file require the hardware device to be built with +* interrupt capabilities. The functions will assert if called using hardware +* that does not have interrupt capabilities. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 2.00a jhl  11/26/03 Initial release
+* 2.11a mta  03/21/07 Updated to new coding style
+* 2.12a sv   06/05/08 Updated driver to fix the XGpio_InterruptDisable function
+*		      to properly update the Interrupt Enable register
+* 3.00a sv   11/21/09 Updated to use HAL Processor APIs. Renamed the macros
+*		      XGpio_mWriteReg to XGpio_WriteReg, and XGpio_mReadReg
+*		      to XGpio_ReadReg.
+
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ +#include "xgpio.h" + + +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Variable Definitions ****************************/ + +/************************** Function Prototypes *****************************/ + + +/****************************************************************************/ +/** +* Enable the interrupt output signal. Interrupts enabled through +* XGpio_InterruptEnable() will not be passed through until the global enable +* bit is set by this function. This function is designed to allow all +* interrupts (both channels) to be enabled easily for exiting a critical +* section. This function will assert if the hardware device has not been +* built with interrupt capabilities. +* +* @param InstancePtr is the GPIO instance to operate on. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XGpio_InterruptGlobalEnable(XGpio *InstancePtr) +{ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(InstancePtr->InterruptPresent == TRUE); + + XGpio_WriteReg(InstancePtr->BaseAddress, XGPIO_GIE_OFFSET, + XGPIO_GIE_GINTR_ENABLE_MASK); +} + + +/****************************************************************************/ +/** +* Disable the interrupt output signal. Interrupts enabled through +* XGpio_InterruptEnable() will no longer be passed through until the global +* enable bit is set by XGpio_InterruptGlobalEnable(). This function is +* designed to allow all interrupts (both channels) to be disabled easily for +* entering a critical section. This function will assert if the hardware +* device has not been built with interrupt capabilities. +* +* @param InstancePtr is the GPIO instance to operate on. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XGpio_InterruptGlobalDisable(XGpio *InstancePtr) +{ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(InstancePtr->InterruptPresent == TRUE); + + + XGpio_WriteReg(InstancePtr->BaseAddress, XGPIO_GIE_OFFSET, 0x0); + +} + + +/****************************************************************************/ +/** +* Enable interrupts. The global interrupt must also be enabled by calling +* XGpio_InterruptGlobalEnable() for interrupts to occur. This function will +* assert if the hardware device has not been built with interrupt capabilities. +* +* @param InstancePtr is the GPIO instance to operate on. +* @param Mask is the mask to enable. Bit positions of 1 are enabled. +* This mask is formed by OR'ing bits from XGPIO_IR* bits which +* are contained in xgpio_l.h. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XGpio_InterruptEnable(XGpio *InstancePtr, u32 Mask) +{ + u32 Register; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(InstancePtr->InterruptPresent == TRUE); + + /* + * Read the interrupt enable register and only enable the specified + * interrupts without disabling or enabling any others. + */ + + Register = XGpio_ReadReg(InstancePtr->BaseAddress, XGPIO_IER_OFFSET); + XGpio_WriteReg(InstancePtr->BaseAddress, XGPIO_IER_OFFSET, + Register | Mask); + +} + + +/****************************************************************************/ +/** +* Disable interrupts. This function allows specific interrupts for each +* channel to be disabled. This function will assert if the hardware device +* has not been built with interrupt capabilities. +* +* @param InstancePtr is the GPIO instance to operate on. +* @param Mask is the mask to disable. Bits set to 1 are disabled. This +* mask is formed by OR'ing bits from XGPIO_IR* bits which are +* contained in xgpio_l.h. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XGpio_InterruptDisable(XGpio *InstancePtr, u32 Mask) +{ + u32 Register; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(InstancePtr->InterruptPresent == TRUE); + + /* + * Read the interrupt enable register and only disable the specified + * interrupts without enabling or disabling any others. + */ + Register = XGpio_ReadReg(InstancePtr->BaseAddress, XGPIO_IER_OFFSET); + XGpio_WriteReg(InstancePtr->BaseAddress, XGPIO_IER_OFFSET, + Register & (~Mask)); + +} + +/****************************************************************************/ +/** +* Clear pending interrupts with the provided mask. This function should be +* called after the software has serviced the interrupts that are pending. +* This function will assert if the hardware device has not been built with +* interrupt capabilities. +* +* @param InstancePtr is the GPIO instance to operate on. +* @param Mask is the mask to clear pending interrupts for. Bit positions +* of 1 are cleared. This mask is formed by OR'ing bits from +* XGPIO_IR* bits which are contained in xgpio_l.h. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XGpio_InterruptClear(XGpio * InstancePtr, u32 Mask) +{ + u32 Register; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(InstancePtr->InterruptPresent == TRUE); + + /* + * Read the interrupt status register and only clear the interrupts + * that are specified without affecting any others. Since the register + * is a toggle on write, make sure any bits to be written are already + * set. + */ + Register = XGpio_ReadReg(InstancePtr->BaseAddress, XGPIO_ISR_OFFSET); + XGpio_WriteReg(InstancePtr->BaseAddress, XGPIO_ISR_OFFSET, + Register & Mask); + + +} + + +/****************************************************************************/ +/** +* Returns the interrupt enable mask. This function will assert if the +* hardware device has not been built with interrupt capabilities. +* +* @param InstancePtr is the GPIO instance to operate on. +* +* @return A mask of bits made from XGPIO_IR* bits which are contained in +* xgpio_l.h. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +u32 XGpio_InterruptGetEnabled(XGpio * InstancePtr) +{ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(InstancePtr->InterruptPresent == TRUE); + + return XGpio_ReadReg(InstancePtr->BaseAddress, XGPIO_IER_OFFSET); +} + + +/****************************************************************************/ +/** +* Returns the status of interrupt signals. Any bit in the mask set to 1 +* indicates that the channel associated with the bit has asserted an interrupt +* condition. This function will assert if the hardware device has not been +* built with interrupt capabilities. +* +* @param InstancePtr is the GPIO instance to operate on. +* +* @return A pointer to a mask of bits made from XGPIO_IR* bits which are +* contained in xgpio_l.h. +* +* @note +* +* The interrupt status indicates the status of the device irregardless if +* the interrupts from the devices have been enabled or not through +* XGpio_InterruptEnable(). +* +*****************************************************************************/ +u32 XGpio_InterruptGetStatus(XGpio * InstancePtr) +{ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(InstancePtr->InterruptPresent == TRUE); + + + return XGpio_ReadReg(InstancePtr->BaseAddress, XGPIO_ISR_OFFSET); +} +/** @} */ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/gpio_v4_4/src/xgpio_l.h b/datalink814_sp/bsp/microblaze_ps/libsrc/gpio_v4_4/src/xgpio_l.h new file mode 100644 index 0000000..be6d04a --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/gpio_v4_4/src/xgpio_l.h @@ -0,0 +1,189 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xgpio_l.h +* @addtogroup gpio_v4_4 +* @{ +* +* This header file contains identifiers and driver functions (or +* macros) that can be used to access the device. The user should refer to the +* hardware device specification for more details of the device operation. +* +* The macros that are available in this file use a multiply to calculate the +* addresses of registers. The user can control whether that multiply is done +* at run time or at compile time. A constant passed as the channel parameter +* will cause the multiply to be done at compile time. A variable passed as the +* channel parameter will cause it to occur at run time. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a jhl  04/24/02 First release of low level driver
+* 2.00a jhl  11/26/03 Added support for dual channels and interrupts. This
+*                     change required the functions to be changed such that
+*                     the interface is not compatible with previous versions.
+*                     See the examples in the example directory for macros
+*                     to help compile an application that was designed for
+*                     previous versions of the driver. The interrupt registers
+*                     are accessible using the ReadReg and WriteReg macros and
+*                     a channel parameter was added to the other macros.
+* 2.11a mta  03/21/07 Updated to new coding style
+* 2.12a sv   11/21/07 Updated driver to support access through DCR bus.
+* 3.00a sv   11/21/09 Renamed the macros XGpio_mWriteReg to XGpio_WriteReg
+*		      XGpio_mReadReg to XGpio_ReadReg.
+*		      Removed the macros XGpio_mSetDataDirection,
+*		      XGpio_mGetDataReg and XGpio_mSetDataReg. Users
+*		      should use XGpio_WriteReg/XGpio_ReadReg to achieve the
+*		      same functionality.
+* 4.1  lks   11/18/15 Removed support for DCR bridge
+* 
+* +******************************************************************************/ + +#ifndef XGPIO_L_H /* prevent circular inclusions */ +#define XGPIO_L_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_io.h" + + +/************************** Constant Definitions *****************************/ + +/** @name Registers + * + * Register offsets for this device. + * @{ + */ +#define XGPIO_DATA_OFFSET 0x0 /**< Data register for 1st channel */ +#define XGPIO_TRI_OFFSET 0x4 /**< I/O direction reg for 1st channel */ +#define XGPIO_DATA2_OFFSET 0x8 /**< Data register for 2nd channel */ +#define XGPIO_TRI2_OFFSET 0xC /**< I/O direction reg for 2nd channel */ + +#define XGPIO_GIE_OFFSET 0x11C /**< Glogal interrupt enable register */ +#define XGPIO_ISR_OFFSET 0x120 /**< Interrupt status register */ +#define XGPIO_IER_OFFSET 0x128 /**< Interrupt enable register */ + +/* @} */ + +/* The following constant describes the offset of each channels data and + * tristate register from the base address. + */ +#define XGPIO_CHAN_OFFSET 8 + +/** @name Interrupt Status and Enable Register bitmaps and masks + * + * Bit definitions for the interrupt status register and interrupt enable + * registers. + * @{ + */ +#define XGPIO_IR_MASK 0x3 /**< Mask of all bits */ +#define XGPIO_IR_CH1_MASK 0x1 /**< Mask for the 1st channel */ +#define XGPIO_IR_CH2_MASK 0x2 /**< Mask for the 2nd channel */ +/*@}*/ + + +/** @name Global Interrupt Enable Register bitmaps and masks + * + * Bit definitions for the Global Interrupt Enable register + * @{ + */ +#define XGPIO_GIE_GINTR_ENABLE_MASK 0x80000000 +/*@}*/ + + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + +#define XGpio_In32 Xil_In32 +#define XGpio_Out32 Xil_Out32 + + +/****************************************************************************/ +/** +* +* Write a value to a GPIO register. A 32 bit write is performed. If the +* GPIO core is implemented in a smaller width, only the least significant data +* is written. +* +* @param BaseAddress is the base address of the GPIO device. +* @param RegOffset is the register offset from the base to write to. +* @param Data is the data written to the register. +* +* @return None. +* +* @note C-style signature: +* void XGpio_WriteReg(u32 BaseAddress, u32 RegOffset, u32 Data) +* +****************************************************************************/ +#define XGpio_WriteReg(BaseAddress, RegOffset, Data) \ + XGpio_Out32((BaseAddress) + (RegOffset), (u32)(Data)) + +/****************************************************************************/ +/** +* +* Read a value from a GPIO register. A 32 bit read is performed. If the +* GPIO core is implemented in a smaller width, only the least +* significant data is read from the register. The most significant data +* will be read as 0. +* +* @param BaseAddress is the base address of the GPIO device. +* @param RegOffset is the register offset from the base to read from. +* +* @return Data read from the register. +* +* @note C-style signature: +* u32 XGpio_ReadReg(u32 BaseAddress, u32 RegOffset) +* +****************************************************************************/ +#define XGpio_ReadReg(BaseAddress, RegOffset) \ + XGpio_In32((BaseAddress) + (RegOffset)) + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/gpio_v4_4/src/xgpio_selftest.c b/datalink814_sp/bsp/microblaze_ps/libsrc/gpio_v4_4/src/xgpio_selftest.c new file mode 100644 index 0000000..50d8d4f --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/gpio_v4_4/src/xgpio_selftest.c @@ -0,0 +1,106 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file xgpio_selftest.c +* @addtogroup gpio_v4_4 +* @{ +* +* The implementation of the XGpio driver's self test function. +* See xgpio.h for more information about the driver. +* +* @note +* +* None +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a rmm  02/04/02 First release
+* 2.00a jhl  01/13/04 Addition of dual channels and interrupts.
+* 2.11a mta  03/21/07 Updated to new coding style
+* 3.00a sv   11/21/09 Updated to use HAL Processor APIs.
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ +#include "xgpio.h" + +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Variable Definitions ****************************/ + +/************************** Function Prototypes *****************************/ + + +/******************************************************************************/ +/** +* Run a self-test on the driver/device. This function does a minimal test +* in which the data register is read. It only does a read without any kind +* of test because the hardware has been parameterized such that it may be only +* an input such that the state of the inputs won't be known. +* +* All other hardware features of the device are not guaranteed to be in the +* hardware since they are parameterizable. +* +* +* @param InstancePtr is a pointer to the XGpio instance to be worked on. +* This parameter must have been previously initialized with +* XGpio_Initialize(). +* +* @return XST_SUCCESS always. If the GPIO device was not present in the +* hardware a bus error could be generated. Other indicators of a +* bus error, such as registers in bridges or buses, may be +* necessary to determine if this function caused a bus error. +* +* @note None. +* +******************************************************************************/ +int XGpio_SelfTest(XGpio * InstancePtr) +{ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read from the data register of channel 1 which is always guaranteed + * to be in the hardware device. Since the data may be configured as + * all inputs, there is not way to guarantee the value read so don't + * test it. + */ + (void) XGpio_DiscreteRead(InstancePtr, 1); + + return (XST_SUCCESS); +} +/** @} */ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/gpio_v4_4/src/xgpio_sinit.c b/datalink814_sp/bsp/microblaze_ps/libsrc/gpio_v4_4/src/xgpio_sinit.c new file mode 100644 index 0000000..0be44bd --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/gpio_v4_4/src/xgpio_sinit.c @@ -0,0 +1,155 @@ +/****************************************************************************** +* +* Copyright (C) 2003 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file xgpio_sinit.c +* @addtogroup gpio_v4_4 +* @{ +* +* The implementation of the XGpio driver's static initialzation +* functionality. +* +* @note +* +* None +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 2.01a jvb  10/13/05 First release
+* 2.11a mta  03/21/07 Updated to new coding style
+* 4.0   sha  07/15/15 Defined macro XPAR_XGPIO_NUM_INSTANCES if not
+*		      defined in xparameters.h
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ + +#include "xstatus.h" +#include "xparameters.h" +#include "xgpio_i.h" + +/************************** Constant Definitions ****************************/ + +#ifndef XPAR_XGPIO_NUM_INSTANCES +#define XPAR_XGPIO_NUM_INSTANCES 0 +#endif + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Variable Definitions ****************************/ + + +/************************** Function Prototypes *****************************/ + + +/******************************************************************************/ +/** +* Lookup the device configuration based on the unique device ID. The table +* ConfigTable contains the configuration info for each device in the system. +* +* @param DeviceId is the device identifier to lookup. +* +* @return +* - A pointer of data type XGpio_Config which points to the +* device configuration if DeviceID is found. +* - NULL if DeviceID is not found. +* +* @note None. +* +******************************************************************************/ +XGpio_Config *XGpio_LookupConfig(u16 DeviceId) +{ + XGpio_Config *CfgPtr = NULL; + + int Index; + + for (Index = 0; Index < XPAR_XGPIO_NUM_INSTANCES; Index++) { + if (XGpio_ConfigTable[Index].DeviceId == DeviceId) { + CfgPtr = &XGpio_ConfigTable[Index]; + break; + } + } + + return CfgPtr; +} + + +/****************************************************************************/ +/** +* Initialize the XGpio instance provided by the caller based on the +* given DeviceID. +* +* Nothing is done except to initialize the InstancePtr. +* +* @param InstancePtr is a pointer to an XGpio instance. The memory the +* pointer references must be pre-allocated by the caller. Further +* calls to manipulate the instance/driver through the XGpio API +* must be made with this pointer. +* @param DeviceId is the unique id of the device controlled by this XGpio +* instance. Passing in a device id associates the generic XGpio +* instance to a specific device, as chosen by the caller or +* application developer. +* +* @return +* - XST_SUCCESS if the initialization was successfull. +* - XST_DEVICE_NOT_FOUND if the device configuration data was not +* found for a device with the supplied device ID. +* +* @note None. +* +*****************************************************************************/ +int XGpio_Initialize(XGpio * InstancePtr, u16 DeviceId) +{ + XGpio_Config *ConfigPtr; + + /* + * Assert arguments + */ + Xil_AssertNonvoid(InstancePtr != NULL); + + /* + * Lookup configuration data in the device configuration table. + * Use this configuration info down below when initializing this + * driver. + */ + ConfigPtr = XGpio_LookupConfig(DeviceId); + if (ConfigPtr == (XGpio_Config *) NULL) { + InstancePtr->IsReady = 0; + return (XST_DEVICE_NOT_FOUND); + } + + return XGpio_CfgInitialize(InstancePtr, ConfigPtr, + ConfigPtr->BaseAddress); +} +/** @} */ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/intc_v3_9/src/Makefile b/datalink814_sp/bsp/microblaze_ps/libsrc/intc_v3_9/src/Makefile new file mode 100644 index 0000000..87c3db9 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/intc_v3_9/src/Makefile @@ -0,0 +1,28 @@ +COMPILER= +ARCHIVER= +CP=cp +COMPILER_FLAGS= +EXTRA_COMPILER_FLAGS= +LIB=libxil.a +LEVEL=0 + +RELEASEDIR=../../../lib +INCLUDEDIR=../../../include +INCLUDES=-I./. -I${INCLUDEDIR} + +INCLUDEFILES=*.h +LIBSOURCES=*.c + +OUTS = *.o +OBJECTS = $(addsuffix .o, $(basename $(wildcard *.c))) +libs: + echo "Compiling intc" + $(COMPILER) $(COMPILER_FLAGS) $(EXTRA_COMPILER_FLAGS) $(INCLUDES) $(LIBSOURCES) + $(ARCHIVER) -r ${RELEASEDIR}/${LIB} $(OBJECTS) + make clean + +include: + ${CP} $(INCLUDEFILES) $(INCLUDEDIR) + +clean: + rm -rf ${OBJECTS} diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/intc_v3_9/src/xintc.c b/datalink814_sp/bsp/microblaze_ps/libsrc/intc_v3_9/src/xintc.c new file mode 100644 index 0000000..96aa830 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/intc_v3_9/src/xintc.c @@ -0,0 +1,1166 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xintc.c +* @addtogroup intc_v3_9 +* @{ +* +* Contains required functions for the XIntc driver for the Xilinx Interrupt +* Controller. See xintc.h for a detailed description of the driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- --------------------------------------------------------
+* 1.00a ecm  08/16/01 First release
+* 1.00b jhl  02/21/02 Repartitioned the driver for smaller files
+* 1.00b jhl  04/24/02 Made LookupConfig global and compressed ack before table
+*                     in the configuration into a bit mask
+* 1.00c rpm  10/17/03 New release. Support the static vector table created
+*                     in the xintc_g.c configuration table.
+* 1.00c rpm  04/23/04 Removed check in XIntc_Connect for a previously connected
+*                     handler. Always overwrite the vector table handler with
+*                     the handler provided as an argument.
+* 1.10c mta  03/21/07 Updated to new coding style
+* 1.11a sv   11/21/07 Updated driver to support access through a DCR bridge
+* 2.00a ktn  10/20/09 Updated to use HAL Processor APIs.
+* 2.04a bss  01/13/12 Added XIntc_ConnectFastHandler API for Fast Interrupt
+*		      and XIntc_SetNormalIntrMode for setting to normal
+*		      interrupt mode.
+* 2.05a bss  08/16/12 Updated to support relocatable vectors in Microblaze,
+*		      updated XIntc_SetNormalIntrMode to use IntVectorAddr
+*		      which is the interrupt vector address
+* 2.06a bss  01/28/13 To support Cascade mode:
+*		      Modified XIntc_Initialize,XIntc_Start,XIntc_Connect
+*		      XIntc_Disconnect,XIntc_Enable,XIntc_Disable,
+*		      XIntc_Acknowledge,XIntc_ConnectFastHandler and
+*		      XIntc_SetNormalIntrMode APIs.
+*		      Added XIntc_InitializeSlaves API.
+* 3.0   bss  01/28/13 Modified to initialize IVAR register with
+*		      XPAR_MICROBLAZE_BASE_VECTORS + 0x10 to fix
+*		      CR#765931
+* 3.9  sa   03/18/19 Modified XIntc_ConnectFastHandler, XIntc_SetNormalIntrMode
+*		             and XIntc_InitializeSlaves APIs to support vector addresses
+*		             of width > 32 bits.
+*
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xintc.h" +#include "xintc_l.h" +#include "xintc_i.h" + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Variable Definitions *****************************/ + +/* + * Array of masks associated with the bit position, improves performance + * in the ISR and acknowledge functions, this table is shared between all + * instances of the driver. XIN_CONTROLLER_MAX_INTRS is the maximum number of + * sources of Interrupt controller + */ +u32 XIntc_BitPosMask[XIN_CONTROLLER_MAX_INTRS]; + +/************************** Function Prototypes ******************************/ + +static void StubHandler(void *CallBackRef); +static void XIntc_InitializeSlaves(XIntc * InstancePtr); + +/*****************************************************************************/ +/** +* +* Initialize a specific interrupt controller instance/driver. The +* initialization entails: +* +* - Initialize fields of the XIntc structure +* - Initial vector table with stub function calls +* - All interrupt sources are disabled +* - Interrupt output is disabled +* +* @param InstancePtr is a pointer to the XIntc instance to be worked on. +* @param DeviceId is the unique id of the device controlled by this XIntc +* instance. Passing in a device id associates the generic XIntc +* instance to a specific device, as chosen by the caller or +* application developer. +* +* @return +* - XST_SUCCESS if initialization was successful +* - XST_DEVICE_IS_STARTED if the device has already been started +* - XST_DEVICE_NOT_FOUND if device configuration information was +* not found for a device with the supplied device ID. +* +* @note In Cascade mode this function calls XIntc_InitializeSlaves to +* initialiaze Slave Interrupt controllers. +* +******************************************************************************/ +int XIntc_Initialize(XIntc * InstancePtr, u16 DeviceId) +{ + u8 Id; + XIntc_Config *CfgPtr; + u32 NextBitMask = 1; + + Xil_AssertNonvoid(InstancePtr != NULL); + + /* + * If the device is started, disallow the initialize and return a status + * indicating it is started. This allows the user to stop the device + * and reinitialize, but prevents a user from inadvertently initializing + */ + if (InstancePtr->IsStarted == XIL_COMPONENT_IS_STARTED) { + return XST_DEVICE_IS_STARTED; + } + + /* + * Lookup the device configuration in the CROM table. Use this + * configuration info down below when initializing this component. + */ + CfgPtr = XIntc_LookupConfig(DeviceId); + if (CfgPtr == NULL) { + return XST_DEVICE_NOT_FOUND; + } + + /* + * Set some default values + */ + InstancePtr->IsReady = 0; + InstancePtr->IsStarted = 0; /* not started */ + InstancePtr->CfgPtr = CfgPtr; + + InstancePtr->CfgPtr->Options = XIN_SVC_SGL_ISR_OPTION; + InstancePtr->CfgPtr->IntcType = CfgPtr->IntcType; + + /* + * Save the base address pointer such that the registers of the + * interrupt can be accessed + */ +#if (XPAR_XINTC_USE_DCR_BRIDGE != 0) + InstancePtr->BaseAddress = ((CfgPtr->BaseAddress >> 2)) & 0xFFF; +#else + InstancePtr->BaseAddress = CfgPtr->BaseAddress; +#endif + + /* + * Initialize all the data needed to perform interrupt processing for + * each interrupt ID up to the maximum used + */ + for (Id = 0; Id < CfgPtr->NumberofIntrs; Id++) { + + /* + * Initalize the handler to point to a stub to handle an + * interrupt which has not been connected to a handler. Only + * initialize it if the handler is 0 or XNullHandler, which + * means it was not initialized statically by the tools/user. + * Set the callback reference to this instance so that + * unhandled interrupts can be tracked. + */ + if ((InstancePtr->CfgPtr->HandlerTable[Id].Handler == 0) || + (InstancePtr->CfgPtr->HandlerTable[Id].Handler == + XNullHandler)) { + InstancePtr->CfgPtr->HandlerTable[Id].Handler = + StubHandler; + } + InstancePtr->CfgPtr->HandlerTable[Id].CallBackRef = InstancePtr; + + /* + * Initialize the bit position mask table such that bit + * positions are lookups only for each interrupt id, with 0 + * being a special case + * (XIntc_BitPosMask[] = { 1, 2, 4, 8, ... }) + */ + XIntc_BitPosMask[Id] = NextBitMask; + NextBitMask *= 2; + } + + /* + * Disable IRQ output signal + * Disable all interrupt sources + * Acknowledge all sources + */ + XIntc_Out32(InstancePtr->BaseAddress + XIN_MER_OFFSET, 0); + XIntc_Out32(InstancePtr->BaseAddress + XIN_IER_OFFSET, 0); + XIntc_Out32(InstancePtr->BaseAddress + XIN_IAR_OFFSET, 0xFFFFFFFF); + + /* + * If the fast Interrupt mode is enabled then set all the + * interrupts as normal mode. + */ + if(InstancePtr->CfgPtr->FastIntr == TRUE) { + XIntc_Out32(InstancePtr->BaseAddress + XIN_IMR_OFFSET, 0); + +#ifdef XPAR_MICROBLAZE_BASE_VECTORS + if (InstancePtr->CfgPtr->VectorAddrWidth > + XINTC_STANDARD_VECTOR_ADDRESS_WIDTH) { + for (Id = 0; Id < 32 ; Id++) { + XIntc_Out64(InstancePtr->BaseAddress + XIN_IVEAR_OFFSET + + (Id * 8), XPAR_MICROBLAZE_BASE_VECTORS + + 0x10); + } + } else { + for (Id = 0; Id < 32 ; Id++) { + XIntc_Out32(InstancePtr->BaseAddress + XIN_IVAR_OFFSET + + (Id * 4), XPAR_MICROBLAZE_BASE_VECTORS + + 0x10); + } + } +#else + if (InstancePtr->CfgPtr->VectorAddrWidth > + XINTC_STANDARD_VECTOR_ADDRESS_WIDTH) { + for (Id = 0; Id < 32 ; Id++) { + XIntc_Out64(InstancePtr->BaseAddress + XIN_IVEAR_OFFSET + + (Id * 8), 0x10); + } + } else { + for (Id = 0; Id < 32 ; Id++) { + XIntc_Out32(InstancePtr->BaseAddress + XIN_IVAR_OFFSET + + (Id * 4), 0x10); + } + } +#endif + } + + /* Initialize slaves in Cascade mode*/ + if (InstancePtr->CfgPtr->IntcType != XIN_INTC_NOCASCADE) { + XIntc_InitializeSlaves(InstancePtr); + } + + /* + * Indicate the instance is now ready to use, successfully initialized + */ + InstancePtr->IsReady = XIL_COMPONENT_IS_READY; + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* Starts the interrupt controller by enabling the output from the controller +* to the processor. Interrupts may be generated by the interrupt controller +* after this function is called. +* +* It is necessary for the caller to connect the interrupt handler of this +* component to the proper interrupt source. This function also starts Slave +* controllers in Cascade mode. +* +* @param InstancePtr is a pointer to the XIntc instance to be worked on. +* @param Mode determines if software is allowed to simulate interrupts or +* real interrupts are allowed to occur. Note that these modes are +* mutually exclusive. The interrupt controller hardware resets in +* a mode that allows software to simulate interrupts until this +* mode is exited. It cannot be reentered once it has been exited. +* +* One of the following values should be used for the mode. +* - XIN_SIMULATION_MODE enables simulation of interrupts only +* - XIN_REAL_MODE enables hardware interrupts only +* +* @return +* - XST_SUCCESS if the device was started successfully +* - XST_FAILURE if simulation mode was specified and it could not +* be set because real mode has already been entered. +* +* @note Must be called after XIntc initialization is completed. +* +******************************************************************************/ +int XIntc_Start(XIntc * InstancePtr, u8 Mode) +{ + u32 MasterEnable = XIN_INT_MASTER_ENABLE_MASK; + XIntc_Config *CfgPtr; + int Index; + + /* + * Assert the arguments + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid((Mode == XIN_SIMULATION_MODE) || + (Mode == XIN_REAL_MODE)) + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Check for simulation mode + */ + if (Mode == XIN_SIMULATION_MODE) { + if (MasterEnable & XIN_INT_HARDWARE_ENABLE_MASK) { + return XST_FAILURE; + } + } + else { + MasterEnable |= XIN_INT_HARDWARE_ENABLE_MASK; + } + + /* + * Indicate the instance is ready to be used and is started before we + * enable the device. + */ + InstancePtr->IsStarted = XIL_COMPONENT_IS_STARTED; + + /* Start the Slaves for Cascade Mode */ + if (InstancePtr->CfgPtr->IntcType != XIN_INTC_NOCASCADE) { + for (Index = 1; Index <= XPAR_XINTC_NUM_INSTANCES - 1; Index++) + { + CfgPtr = XIntc_LookupConfig(Index); + XIntc_Out32(CfgPtr->BaseAddress + XIN_MER_OFFSET, + MasterEnable); + } + } + + /* Start the master */ + XIntc_Out32(InstancePtr->BaseAddress + XIN_MER_OFFSET, MasterEnable); + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* Stops the interrupt controller by disabling the output from the controller +* so that no interrupts will be caused by the interrupt controller. +* +* @param InstancePtr is a pointer to the XIntc instance to be worked on. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XIntc_Stop(XIntc * InstancePtr) +{ + /* + * Assert the arguments + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Stop all interrupts from occurring thru the interrupt controller by + * disabling all interrupts in the MER register + */ + XIntc_Out32(InstancePtr->BaseAddress + XIN_MER_OFFSET, 0); + + InstancePtr->IsStarted = 0; +} + +/*****************************************************************************/ +/** +* +* Makes the connection between the Id of the interrupt source and the +* associated handler that is to run when the interrupt is recognized. The +* argument provided in this call as the Callbackref is used as the argument +* for the handler when it is called. In Cascade mode, connects handler to +* Slave controller handler table depending on the interrupt Id. +* +* @param InstancePtr is a pointer to the XIntc instance to be worked on. +* @param Id contains the ID of the interrupt source and should be in the +* range of 0 to XPAR_INTC_MAX_NUM_INTR_INPUTS - 1 with 0 being +* the highest priority interrupt. +* @param Handler to the handler for that interrupt. +* @param CallBackRef is the callback reference, usually the instance +* pointer of the connecting driver. +* +* @return +* +* - XST_SUCCESS if the handler was connected correctly. +* +* @note +* +* WARNING: The handler provided as an argument will overwrite any handler +* that was previously connected. +* +****************************************************************************/ +int XIntc_Connect(XIntc * InstancePtr, u8 Id, + XInterruptHandler Handler, void *CallBackRef) +{ + XIntc_Config *CfgPtr; + /* + * Assert the arguments + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(Id < XPAR_INTC_MAX_NUM_INTR_INPUTS); + Xil_AssertNonvoid(Handler != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* Connect Handlers for Slave controllers in Cascade Mode */ + if (Id > 31) { + + CfgPtr = XIntc_LookupConfig(Id/32); + + CfgPtr->HandlerTable[Id%32].Handler = Handler; + CfgPtr->HandlerTable[Id%32].CallBackRef = CallBackRef; + } + /* Connect Handlers for Master/primary controller */ + else { + /* + * The Id is used as an index into the table to select the + * proper handler + */ + InstancePtr->CfgPtr->HandlerTable[Id].Handler = Handler; + InstancePtr->CfgPtr->HandlerTable[Id].CallBackRef = + CallBackRef; + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* Updates the interrupt table with the Null Handler and NULL arguments at the +* location pointed at by the Id. This effectively disconnects that interrupt +* source from any handler. The interrupt is disabled also. In Cascade mode, +* disconnects handler from Slave controller handler table depending on the +* interrupt Id. +* +* @param InstancePtr is a pointer to the XIntc instance to be worked on. +* @param Id contains the ID of the interrupt source and should be in the +* range of 0 to XPAR_INTC_MAX_NUM_INTR_INPUTS - 1 with 0 being +* the highest priority interrupt. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void XIntc_Disconnect(XIntc * InstancePtr, u8 Id) +{ + u32 CurrentIER; + u32 Mask; + XIntc_Config *CfgPtr; + + /* + * Assert the arguments + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(Id < XPAR_INTC_MAX_NUM_INTR_INPUTS); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Disable the interrupt such that it won't occur while disconnecting + * the handler, only disable the specified interrupt id without + * modifying the other interrupt ids + */ + + /* Disconnect Handlers for Slave controllers in Cascade Mode */ + if (Id > 31) { + + CfgPtr = XIntc_LookupConfig(Id/32); + + CurrentIER = XIntc_In32(CfgPtr->BaseAddress + XIN_IER_OFFSET); + + /* Convert from integer id to bit mask */ + Mask = XIntc_BitPosMask[(Id%32)]; + + XIntc_Out32(CfgPtr->BaseAddress + XIN_IER_OFFSET, + (CurrentIER & ~Mask)); + /* + * Disconnect the handler and connect a stub, the callback + * reference must be set to this instance to allow unhandled + * interrupts to be tracked + */ + CfgPtr->HandlerTable[Id%32].Handler = StubHandler; + CfgPtr->HandlerTable[Id%32].CallBackRef = InstancePtr; + } + /* Disconnect Handlers for Master/primary controller */ + else { + CurrentIER = XIntc_In32(InstancePtr->BaseAddress + + XIN_IER_OFFSET); + + /* Convert from integer id to bit mask */ + Mask = XIntc_BitPosMask[Id]; + + XIntc_Out32(InstancePtr->BaseAddress + XIN_IER_OFFSET, + (CurrentIER & ~Mask)); + InstancePtr->CfgPtr->HandlerTable[Id%32].Handler = + StubHandler; + InstancePtr->CfgPtr->HandlerTable[Id%32].CallBackRef = + InstancePtr; + } + +} + +/*****************************************************************************/ +/** +* +* Enables the interrupt source provided as the argument Id. Any pending +* interrupt condition for the specified Id will occur after this function is +* called. In Cascade mode, enables corresponding interrupt of Slave controllers +* depending on the Id. +* +* @param InstancePtr is a pointer to the XIntc instance to be worked on. +* @param Id contains the ID of the interrupt source and should be in the +* range of 0 to XPAR_INTC_MAX_NUM_INTR_INPUTS - 1 with 0 being +* the highest priority interrupt. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void XIntc_Enable(XIntc * InstancePtr, u8 Id) +{ + u32 CurrentIER; + u32 Mask; + XIntc_Config *CfgPtr; + + /* + * Assert the arguments + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(Id < XPAR_INTC_MAX_NUM_INTR_INPUTS); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + if (Id > 31) { + + /* Enable user required Id in Slave controller */ + CfgPtr = XIntc_LookupConfig(Id/32); + + CurrentIER = XIntc_In32(CfgPtr->BaseAddress + XIN_IER_OFFSET); + + /* Convert from integer id to bit mask */ + Mask = XIntc_BitPosMask[(Id%32)]; + + XIntc_Out32(CfgPtr->BaseAddress + XIN_IER_OFFSET, + (CurrentIER | Mask)); + } + else { + /* + * The Id is used to create the appropriate mask for the + * desired bit position. + */ + Mask = XIntc_BitPosMask[Id]; + + /* + * Enable the selected interrupt source by reading the + * interrupt enable register and then modifying only the + * specified interrupt id enable + */ + CurrentIER = XIntc_In32(InstancePtr->BaseAddress + + XIN_IER_OFFSET); + XIntc_Out32(InstancePtr->BaseAddress + XIN_IER_OFFSET, + (CurrentIER | Mask)); + } +} + +/*****************************************************************************/ +/** +* +* Disables the interrupt source provided as the argument Id such that the +* interrupt controller will not cause interrupts for the specified Id. The +* interrupt controller will continue to hold an interrupt condition for the +* Id, but will not cause an interrupt.In Cascade mode, disables corresponding +* interrupt of Slave controllers depending on the Id. +* +* @param InstancePtr is a pointer to the XIntc instance to be worked on. +* @param Id contains the ID of the interrupt source and should be in the +* range of 0 to XPAR_INTC_MAX_NUM_INTR_INPUTS - 1 with 0 being the +* highest priority interrupt. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void XIntc_Disable(XIntc * InstancePtr, u8 Id) +{ + u32 CurrentIER; + u32 Mask; + XIntc_Config *CfgPtr; + + /* + * Assert the arguments + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(Id < XPAR_INTC_MAX_NUM_INTR_INPUTS); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + if (Id > 31) { + /* Enable user required Id in Slave controller */ + CfgPtr = XIntc_LookupConfig(Id/32); + + CurrentIER = XIntc_In32(CfgPtr->BaseAddress + XIN_IER_OFFSET); + + /* Convert from integer id to bit mask */ + Mask = XIntc_BitPosMask[(Id%32)]; + + XIntc_Out32(CfgPtr->BaseAddress + XIN_IER_OFFSET, + (CurrentIER & ~Mask)); + } else { + /* + * The Id is used to create the appropriate mask for the + * desired bit position. Id currently limited to 0 - 31 + */ + Mask = XIntc_BitPosMask[Id]; + + /* + * Disable the selected interrupt source by reading the + * interrupt enable register and then modifying only the + * specified interrupt id + */ + CurrentIER = XIntc_In32(InstancePtr->BaseAddress + + XIN_IER_OFFSET); + XIntc_Out32(InstancePtr->BaseAddress + XIN_IER_OFFSET, + (CurrentIER & ~Mask)); + } +} + +/*****************************************************************************/ +/** +* +* Acknowledges the interrupt source provided as the argument Id. When the +* interrupt is acknowledged, it causes the interrupt controller to clear its +* interrupt condition.In Cascade mode, acknowledges corresponding interrupt +* source of Slave controllers depending on the Id. +* +* @param InstancePtr is a pointer to the XIntc instance to be worked on. +* @param Id contains the ID of the interrupt source and should be in the +* range of 0 to XPAR_INTC_MAX_NUM_INTR_INPUTS - 1 with 0 being +* the highest priority interrupt. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void XIntc_Acknowledge(XIntc * InstancePtr, u8 Id) +{ + u32 Mask; + XIntc_Config *CfgPtr; + + /* + * Assert the arguments + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(Id < XPAR_INTC_MAX_NUM_INTR_INPUTS); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + if (Id > 31) { + /* Enable user required Id in Slave controller */ + CfgPtr = XIntc_LookupConfig(Id/32); + + /* Convert from integer id to bit mask */ + Mask = XIntc_BitPosMask[(Id%32)]; + + XIntc_Out32(CfgPtr->BaseAddress + XIN_IAR_OFFSET, Mask); + } else { + /* + * The Id is used to create the appropriate mask for the + * desired bit position. + */ + Mask = XIntc_BitPosMask[Id]; + + /* + * Acknowledge the selected interrupt source, no read of the + * acknowledge register is necessary since only the bits set + * in the mask will be affected by the write + */ + XIntc_Out32(InstancePtr->BaseAddress + XIN_IAR_OFFSET, Mask); + } +} + +/*****************************************************************************/ +/** +* +* A stub for the asynchronous callback. The stub is here in case the upper +* layers forget to set the handler. +* +* @param CallBackRef is a pointer to the upper layer callback reference +* +* @return None. +* +* @note None. +* +******************************************************************************/ +static void StubHandler(void *CallBackRef) +{ + /* + * Verify that the inputs are valid + */ + Xil_AssertVoid(CallBackRef != NULL); + + /* + * Indicate another unhandled interrupt for stats + */ + ((XIntc *) CallBackRef)->UnhandledInterrupts++; +} + +/*****************************************************************************/ +/** +* +* Looks up the device configuration based on the unique device ID. A table +* contains the configuration info for each device in the system. +* +* @param DeviceId is the unique identifier for a device. +* +* @return A pointer to the XIntc configuration structure for the specified +* device, or NULL if the device was not found. +* +* @note None. +* +******************************************************************************/ +XIntc_Config *XIntc_LookupConfig(u16 DeviceId) +{ + XIntc_Config *CfgPtr = NULL; + int Index; + + for (Index = 0; Index < XPAR_XINTC_NUM_INSTANCES; Index++) { + if (XIntc_ConfigTable[Index].DeviceId == DeviceId) { + CfgPtr = &XIntc_ConfigTable[Index]; + break; + } + } + + return CfgPtr; +} + +/*****************************************************************************/ +/** +* +* Makes the connection between the Id of the interrupt source and the +* associated handler that is to run when the interrupt is recognized.In Cascade +* mode, connects handler to corresponding Slave controller IVAR/IVEAR register +* depending on the Id and sets all interrupt sources of the Slave controller as +* fast interrupts. +* +* @param InstancePtr is a pointer to the XIntc instance to be worked on. +* @param Id contains the ID of the interrupt source and should be in the +* range of 0 to XPAR_INTC_MAX_NUM_INTR_INPUTS - 1 with 0 being +* the highest priority interrupt. +* @param Handler for specified interrupt id. It must be declared with +* "fast_interrupt" attribute. +* e.g. static void MyHandler(void) __attribute__ ((fast_interrupt)); +* +* @return +* - XST_SUCCESS +* +* @note +* Slave controllers in Cascade Mode should have all as Fast +* interrupts or Normal interrupts, mixed interrupts are not +* supported +* +* WARNING: The handler provided as an argument will overwrite any handler +* that was previously connected. +* +****************************************************************************/ +int XIntc_ConnectFastHandler(XIntc *InstancePtr, u8 Id, + XFastInterruptHandler Handler) +{ + u32 Imr; + u32 CurrentIER; + u32 Mask; + XIntc_Config *CfgPtr; + + /* + * Assert the arguments + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(Id < XPAR_INTC_MAX_NUM_INTR_INPUTS); + Xil_AssertNonvoid(Handler != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(InstancePtr->CfgPtr->FastIntr == TRUE); + + + if (Id > 31) { + /* Enable user required Id in Slave controller */ + CfgPtr = XIntc_LookupConfig(Id/32); + + if (CfgPtr->FastIntr != TRUE) { + /*Fast interrupts of slave controller are not enabled*/ + return XST_FAILURE; + } + + /* Get the Enabled Interrupts */ + CurrentIER = XIntc_In32(CfgPtr->BaseAddress + XIN_IER_OFFSET); + + /* Convert from integer id to bit mask */ + Mask = XIntc_BitPosMask[(Id%32)]; + + /* Disable the Interrupt if it was enabled before calling + * this function + */ + if (CurrentIER & Mask) { + XIntc_Disable(InstancePtr, Id); + } + + if (CfgPtr->VectorAddrWidth > + XINTC_STANDARD_VECTOR_ADDRESS_WIDTH) { + XIntc_Out64(CfgPtr->BaseAddress + XIN_IVEAR_OFFSET + + ((Id%32) * 8), (UINTPTR) Handler); + } else { + XIntc_Out32(CfgPtr->BaseAddress + XIN_IVAR_OFFSET + + ((Id%32) * 4), (u32) Handler); + } + + /* Slave controllers in Cascade Mode should have all as Fast + * interrupts or Normal interrupts, mixed interrupts are not + * supported + */ + XIntc_Out32(CfgPtr->BaseAddress + XIN_IMR_OFFSET, 0xFFFFFFFF); + + /* Enable the Interrupt if it was enabled before calling this + * function + */ + if (CurrentIER & Mask) { + XIntc_Enable(InstancePtr, Id); + } + } + else { + /* Get the Enabled Interrupts */ + CurrentIER = XIntc_In32(InstancePtr->BaseAddress + + XIN_IER_OFFSET); + /* Convert from integer id to bit mask */ + Mask = XIntc_BitPosMask[Id]; + + /* Disable the Interrupt if it was enabled before calling + * this function + */ + if (CurrentIER & Mask) { + XIntc_Disable(InstancePtr, Id); + } + + if (InstancePtr->CfgPtr->VectorAddrWidth > + XINTC_STANDARD_VECTOR_ADDRESS_WIDTH) { + XIntc_Out64(InstancePtr->BaseAddress + + XIN_IVEAR_OFFSET + (Id * 8), (UINTPTR) Handler); + } else { + XIntc_Out32(InstancePtr->BaseAddress + + XIN_IVAR_OFFSET + (Id * 4), (u32) Handler); + } + + Imr = XIntc_In32(InstancePtr->BaseAddress + XIN_IMR_OFFSET); + XIntc_Out32(InstancePtr->BaseAddress + XIN_IMR_OFFSET, + Imr | Mask); + + /* Enable the Interrupt if it was enabled before + * calling this function + */ + if (CurrentIER & Mask) { + XIntc_Enable(InstancePtr, Id); + } + + } + + return XST_SUCCESS; +} + + +/*****************************************************************************/ +/** +* +* Sets the normal interrupt mode for the specified interrupt in the Interrupt +* Mode Register. In Cascade mode disconnects handler from corresponding Slave +* controller IVAR/IVEAR register depending on the Id and sets all interrupt +* sources of the Slave controller as normal interrupts. +* +* @param InstancePtr is a pointer to the XIntc instance to be worked on. +* @param Id contains the ID of the interrupt source and should be in the +* range of 0 to XPAR_INTC_MAX_NUM_INTR_INPUTS - 1 with 0 being the +* highest priority interrupt. +* +* @return None. +* +* @note +* Slave controllers in Cascade Mode should have all as Fast +* interrupts or Normal interrupts, mixed interrupts are not +* supported +* +****************************************************************************/ +void XIntc_SetNormalIntrMode(XIntc *InstancePtr, u8 Id) +{ + u32 Imr; + u32 CurrentIER; + u32 Mask; + XIntc_Config *CfgPtr; + + /* + * Assert the arguments + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(Id < XPAR_INTC_MAX_NUM_INTR_INPUTS); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(InstancePtr->CfgPtr->FastIntr == TRUE); + + if (Id > 31) { + /* Enable user required Id in Slave controller */ + CfgPtr = XIntc_LookupConfig(Id/32); + + /* Get the Enabled Interrupts */ + CurrentIER = XIntc_In32(CfgPtr->BaseAddress + XIN_IER_OFFSET); + + /* Convert from integer id to bit mask */ + Mask = XIntc_BitPosMask[(Id%32)]; + + /* Disable the Interrupt if it was enabled before calling + * this function + */ + if (CurrentIER & Mask) { + XIntc_Disable(InstancePtr, Id); + } + + /* Slave controllers in Cascade Mode should have all as Fast + * interrupts or Normal interrupts, mixed interrupts are not + * supported + */ + XIntc_Out32(CfgPtr->BaseAddress + XIN_IMR_OFFSET, 0x0); + +#ifdef XPAR_MICROBLAZE_BASE_VECTORS + if (CfgPtr->VectorAddrWidth > + XINTC_STANDARD_VECTOR_ADDRESS_WIDTH) { + for (Id = 0; Id < 32 ; Id++) + { + XIntc_Out64(CfgPtr->BaseAddress + XIN_IVEAR_OFFSET + + (Id * 8), XPAR_MICROBLAZE_BASE_VECTORS + + 0x10); + } + } else { + for (Id = 0; Id < 32 ; Id++) + { + XIntc_Out32(CfgPtr->BaseAddress + XIN_IVAR_OFFSET + + (Id * 4), XPAR_MICROBLAZE_BASE_VECTORS + + 0x10); + } + } +#else + if (CfgPtr->VectorAddrWidth > + XINTC_STANDARD_VECTOR_ADDRESS_WIDTH) { + for (Id = 0; Id < 32 ; Id++) + { + XIntc_Out64(CfgPtr->BaseAddress + XIN_IVEAR_OFFSET + + (Id * 8), 0x10); + } + } else { + for (Id = 0; Id < 32 ; Id++) + { + XIntc_Out32(CfgPtr->BaseAddress + XIN_IVAR_OFFSET + + (Id * 4), 0x10); + } + } +#endif + + /* Enable the Interrupt if it was enabled before calling this + * function + */ + if (CurrentIER & Mask) { + XIntc_Enable(InstancePtr, Id); + } + + } + else { + + /* Get the Enabled Interrupts */ + CurrentIER = XIntc_In32(InstancePtr->BaseAddress + XIN_IER_OFFSET); + Mask = XIntc_BitPosMask[Id];/* Convert from integer id to bit mask */ + + + /* Disable the Interrupt if it was enabled before + * calling this function + */ + if (CurrentIER & Mask) { + XIntc_Disable(InstancePtr, Id); + } + + /* + * Disable the selected interrupt as Fast Interrupt by reading the + * interrupt mode register and then modifying only the + * specified interrupt id + */ + Imr = XIntc_In32(InstancePtr->BaseAddress + XIN_IMR_OFFSET); + XIntc_Out32(InstancePtr->BaseAddress + XIN_IMR_OFFSET, + Imr & ~Mask); + +#ifdef XPAR_MICROBLAZE_BASE_VECTORS + if (InstancePtr->CfgPtr->VectorAddrWidth > + XINTC_STANDARD_VECTOR_ADDRESS_WIDTH) { + for (Id = 0; Id < 32 ; Id++) + { + XIntc_Out64(InstancePtr->BaseAddress + XIN_IVEAR_OFFSET + + (Id * 8), XPAR_MICROBLAZE_BASE_VECTORS + + 0x10); + } + } else { + for (Id = 0; Id < 32 ; Id++) + { + XIntc_Out32(InstancePtr->BaseAddress + XIN_IVAR_OFFSET + + (Id * 4), XPAR_MICROBLAZE_BASE_VECTORS + + 0x10); + } + } +#else + if (InstancePtr->CfgPtr->VectorAddrWidth > + XINTC_STANDARD_VECTOR_ADDRESS_WIDTH) { + for (Id = 0; Id < 32 ; Id++) + { + XIntc_Out64(InstancePtr->BaseAddress + XIN_IVEAR_OFFSET + + (Id * 8), 0x10); + } + } else { + for (Id = 0; Id < 32 ; Id++) + { + XIntc_Out32(InstancePtr->BaseAddress + XIN_IVAR_OFFSET + + (Id * 4), 0x10); + } + } +#endif + /* Enable the Interrupt if it was enabled before + * calling this function + */ + if (CurrentIER & Mask) { + XIntc_Enable(InstancePtr, Id); + } + } +} + +/*****************************************************************************/ +/** +* +* Initializes Slave controllers in Cascade mode. The initialization entails: +* - Initial vector table with stub function calls +* - All interrupt sources are disabled for last controller. +* - All interrupt sources are disabled except sources to 31 pin of +* primary and secondary controllers +* - Interrupt outputs are disabled +* +* @param InstancePtr is a pointer to the XIntc instance to be worked on. +* +* @return None +* +* @note None. +* +******************************************************************************/ +static void XIntc_InitializeSlaves(XIntc * InstancePtr) +{ + int Index; + u32 Mask; + XIntc_Config *CfgPtr; + int Id; + + Mask = XIntc_BitPosMask[31]; /* Convert from integer id to bit mask */ + + /* Enable interrupt id with 31 for Master + * interrupt controller + */ + XIntc_Out32(InstancePtr->CfgPtr->BaseAddress + XIN_IER_OFFSET, Mask); + + for (Index = 1; Index <= XPAR_XINTC_NUM_INSTANCES - 1; Index++) { + CfgPtr = XIntc_LookupConfig(Index); + + XIntc_Out32(CfgPtr->BaseAddress + XIN_IAR_OFFSET, + 0xFFFFFFFF); + if (CfgPtr->IntcType != XIN_INTC_LAST) { + + /* Enable interrupt ids with 31 for secondary + * interrupt controllers + */ + XIntc_Out32(CfgPtr->BaseAddress + XIN_IER_OFFSET, + Mask); + } else { + XIntc_Out32(CfgPtr->BaseAddress + XIN_IER_OFFSET, 0x0); + } + + /* Disable Interrupt output */ + XIntc_Out32(CfgPtr->BaseAddress + XIN_MER_OFFSET, 0); + + /* Set all interrupts as normal mode if Fast Interrupts + * are enabled + */ + if(CfgPtr->FastIntr == TRUE) { + XIntc_Out32(CfgPtr->BaseAddress + XIN_IMR_OFFSET, 0); + +#ifdef XPAR_MICROBLAZE_BASE_VECTORS + if (CfgPtr->VectorAddrWidth > + XINTC_STANDARD_VECTOR_ADDRESS_WIDTH) { + for (Id = 0; Id < 32 ; Id++) + { + XIntc_Out64(CfgPtr->BaseAddress + + XIN_IVEAR_OFFSET + (Id * 8), + XPAR_MICROBLAZE_BASE_VECTORS + 0x10); + } + } else { + for (Id = 0; Id < 32 ; Id++) + { + XIntc_Out32(CfgPtr->BaseAddress + + XIN_IVAR_OFFSET + (Id * 4), + XPAR_MICROBLAZE_BASE_VECTORS + 0x10); + } + } +#else + if (CfgPtr->VectorAddrWidth > + XINTC_STANDARD_VECTOR_ADDRESS_WIDTH) { + for (Id = 0; Id < 32 ; Id++) + { + XIntc_Out64(CfgPtr->BaseAddress + + XIN_IVEAR_OFFSET + (Id * 8), 0x10); + } + } else { + for (Id = 0; Id < 32 ; Id++) + { + XIntc_Out32(CfgPtr->BaseAddress + + XIN_IVAR_OFFSET + (Id * 4), 0x10); + } + } +#endif + } + + /* + * Initialize all the data needed to perform interrupt + * processing for each interrupt ID up to the maximum used + */ + for (Id = 0; Id < CfgPtr->NumberofIntrs; Id++) { + + /* + * Initalize the handler to point to a stub to handle an + * interrupt which has not been connected to a handler. + * Only initialize it if the handler is 0 or + * XNullHandler, which means it was not initialized + * statically by the tools/user.Set the callback + * reference to this instance so that unhandled + * interrupts can be tracked. + */ + if ((CfgPtr->HandlerTable[Id].Handler == 0) || + (CfgPtr->HandlerTable[Id].Handler == + XNullHandler)) { + CfgPtr->HandlerTable[Id].Handler = StubHandler; + } + CfgPtr->HandlerTable[Id].CallBackRef = InstancePtr; + } + } +} +/** @} */ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/intc_v3_9/src/xintc.h b/datalink814_sp/bsp/microblaze_ps/libsrc/intc_v3_9/src/xintc.h new file mode 100644 index 0000000..34643e5 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/intc_v3_9/src/xintc.h @@ -0,0 +1,379 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xintc.h +* @addtogroup intc_v3_9 +* @{ +* @details +* +* The Xilinx interrupt controller driver component. This component supports the +* Xilinx interrupt controller. +* +* The interrupt controller driver uses the idea of priority for the various +* handlers. Priority is an integer within the range of 0 and 31 inclusive with +* 0 being the highest priority interrupt source. +* +* The Xilinx interrupt controller supports the following features: +* +* - specific individual interrupt enabling/disabling +* - specific individual interrupt acknowledging +* - attaching specific callback function to handle interrupt source +* - master enable/disable +* - single callback per interrupt or all pending interrupts handled for +* each interrupt of the processor +* +* The acknowledgement of the interrupt within the interrupt controller is +* selectable, either prior to the device's handler being called or after +* the handler is called. This is necessary to support interrupt signal inputs +* which are either edge or level signals. Edge driven interrupt signals +* require that the interrupt is acknowledged prior to the interrupt being +* serviced in order to prevent the loss of interrupts which are occurring +* extremely close together. A level driven interrupt input signal requires +* the interrupt to acknowledged after servicing the interrupt to ensure that +* the interrupt only generates a single interrupt condition. +* +* Details about connecting the interrupt handler of the driver are contained +* in the source file specific to interrupt processing, xintc_intr.c. +* +* This driver is intended to be RTOS and processor independent. It works with +* physical addresses only. Any needs for dynamic memory management, threads +* or thread mutual exclusion, virtual memory, or cache control must be +* satisfied by the layer above this driver. +* +* Interrupt Vector Tables +* +* The interrupt vector table for each interrupt controller device is declared +* statically in xintc_g.c within the configuration data for each instance. +* The device ID of the interrupt controller device is used by the driver as a +* direct index into the configuration data table - to retrieve the vector table +* for an instance of the interrupt controller. The user should populate the +* vector table with handlers and callbacks at run-time using the XIntc_Connect() +* and XIntc_Disconnect() functions. +* +* Each vector table entry corresponds to a device that can generate an +* interrupt. Each entry contains an interrupt handler function and an argument +* to be passed to the handler when an interrupt occurs. The tools default this +* argument to the base address of the interrupting device. Note that the +* device driver interrupt handlers given in this file do not take a base +* address as an argument, but instead take a pointer to the driver instance. +* This means that although the table is created statically, the user must still +* use XIntc_Connect() when the interrupt handler takes an argument other than +* the base address. This is only to say that the existence of the static vector +* tables should not mislead the user into thinking they no longer need to +* register/connect interrupt handlers with this driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a ecm  08/16/01 First release
+* 1.00a rpm  01/09/02 Removed the AckLocation argument from XIntc_Connect().
+*                     This information is now internal in xintc_g.c.
+* 1.00b jhl  02/13/02 Repartitioned the driver for smaller files
+* 1.00b jhl  04/24/02 Made LookupConfig function global and relocated config
+*                     data type
+* 1.00c rpm  10/17/03 New release. Support the static vector table created
+*                     in the xintc_g.c configuration table. Moved vector
+*                     table and options out of instance structure and into
+*                     the configuration table.
+* 1.10c mta  03/21/07 Updated to new coding style
+* 1.11a sv   11/21/07 Updated driver to support access through a DCR bridge
+* 2.00a ktn  10/20/09 Updated to use HAL Processor APIs and _m is removed from
+*		      all the macro names/definitions.
+* 2.01a sdm  04/27/10 Updated the tcl so that the defintions are generated in
+*		      the xparameters.h to know whether the optional registers
+*		      SIE, CIE and IVR are enabled in the HW - Refer CR 555392.
+*		      This driver doesnot make use of these definitions and does
+*		      not use the optional registers.
+* 2.03a hvm  05/24/11 Updated the tcl to generate vector Ids for external
+*		      interrupts. CR565336
+* 2.04a bss  01/13/12 Added XIntc_ConnectFastHandler API for Fast Interrupt
+*		      and XIntc_SetNormalIntrMode for setting to normal
+*		      interrupt mode.
+* 2.04a asa  03/19/12 Changed the XIntc_Config struct. The order of entries
+*		      declared in the structure now matches with the
+*		      XIntc_ConfigTable generated by the driver tcl.
+* 2.05a bss  08/16/12 Updated to support relocatable vectors in Microblaze,
+*		      added IntVectorAddr to XIntc_Config for this.
+*		      Added XIntc_RegisterFastHandler API to register fast
+*		      interrupt handlers using base address.
+* 2.06a bss  01/28/13 To support Cascade mode:
+* 		      Added XIN_INTC_NOCASCADE,XIN_INTC_PRIMARY,
+*		      XIN_INTC_SECONDARY,XIN_INTC_LAST and
+*		      XIN_CONTROLLER_MAX_INTRS  macros
+*		      Added NumberofIntrs and IntcType fields in XIntc_Config
+*		      structure.
+*		      Modified XIntc_Initialize,XIntc_Start,XIntc_Connect
+*		      XIntc_Disconnect,XIntc_Enable,XIntc_Disable,
+*		      XIntc_Acknowledge,XIntc_ConnectFastHandler and
+*		      XIntc_SetNormalIntrMode APIs.Added XIntc_InitializeSlaves
+*		      API in xintc.c
+*  		      Modified XIntc_DeviceInterruptHandler,
+*  		      XIntc_SetIntrSvcOption,XIntc_RegisterHandler and
+*		      XIntc_RegisterFastHandler APIs.Added XIntc_CascadeHandler
+*		      API in xintc_l.c.
+*		      Modified XIntc_SetOptions API in xintc_options.c.
+*		      Modified XIntc_SimulateIntr API in xintc_selftest.c.
+*		      Modified driver tcl:
+*			to check for Cascade mode and generate XPAR_INTC_TYPE
+*			for each controller.
+*			Generate XPAR_INTC_MAX_NUM_INTR_INPUTS by adding all
+*			interrupt sources of all Controllers in Cascade mode.
+* 2.07a bss  10/18/13 To support Nested interrupts:
+*		      Modified XIntc_DeviceInterruptHandler API.
+*		      Added XIN_ILR_OFFSET macro in xintc_l.h.
+*		      Modified driver tcl to generate HAS_ILR parameter in
+*		      xparameters.h
+* 3.0   bss  01/28/13 Modified xintc.c to initialize IVAR register with
+*		      XPAR_MICROBLAZE_BASE_VECTORS + 0x10 to fix
+*		      CR#765931.
+*		      Modified driver tcl to generate XPAR_AXI_INTC_0_TYPE
+*		      correctly(CR#764865).
+*
+* @note
+*		For Cascade mode, Interrupt IDs are generated in xparameters.h
+*		as shown below:
+*
+*	    Master/Primary INTC
+*		 ______
+*		|      |-0      Secondary INTC
+*		|      |-.         ______
+*		|      |-.        |      |-32        Last INTC
+*		|      |-.        |      |-.          ______
+*		|______|<-31------|      |-.         |      |-64
+*			          |      |-.         |      |-.
+*			          |______|<-63-------|      |-.
+*                                                    |      |-.
+*                                                    |______|-95
+*
+*		All driver functions has to be called using DeviceId/
+*		InstancePtr/BaseAddress of Primary/Master Controller and
+*		Interrupts IDs generated in xparameters.h only.
+*		Driver functions takes care of Slave Controllers based on
+*		Interrupt ID passed. User must not use Interrupt source/ID
+*		31 of Primary and Secondary controllers to call driver
+*		functions.
+*
+*		For nested interrupts, XIntc_DeviceInterruptHandler saves
+*		microblaze r14 register on entry and restores on exit. This is
+*		required since compiler does not support nesting. It enables
+*		Microblaze interrupts after blocking further interrupts from
+*		the current interrupt number and interrupts below current
+*		interrupt proirity by writing to Interrupt Level Register of
+*		INTC on entry. On exit, it disables microblaze interrupts and
+*		restores ILR register default value(0xFFFFFFFF)back. It is
+*		recommended to increase STACK_SIZE in linker script for nested
+*		interrupts.
+* 3.0     adk    12/10/13  Updated as per the New Tcl API's
+* 3.0 	  adk 	 17/02/14  Fixed the CR:771287 Changes are made in the intc
+* 		           driver tcl.
+* 3.1     adk    8/4/14    Fixed the CR:783248 Changes are made in
+*			   the test-app tcl
+* 3.2     bss    4/8/14    Fixed driver tcl to handle external interrupt pins
+*			   correctly (CR#799609).
+* 3.3     adk    11/3/14   added generation of C_HAS_ILR parameter to
+*			   xparameters.h.Changes are made in the driver tcl file
+*			   (CR#828046).
+* 3.5   sk   11/10/15 Used UINTPTR instead of u32 for Baseaddress CR# 867425.
+* 3.6   ms   01/23/17 Added xil_printf statement in main function for all
+*                     examples to ensure that "Successfully ran" and "Failed"
+*                     strings are available in all examples. This is a fix
+*                     for CR-965028.
+*       ms   03/17/17 Added readme.txt file in examples folder for doxygen
+*                     generation.
+* 3.7   ms   04/18/17 Modified tcl file to add suffix U for macro definitions
+*                     of intc in xparameters.h
+* 3.9   adk  19/12/18 If design contains unconnected interrupt pins
+*		      return proper error message(CR#1018878).
+* 
+* +******************************************************************************/ + +#ifndef XINTC_H /* prevent circular inclusions */ +#define XINTC_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xparameters.h" +#include "xstatus.h" +#include "xintc_l.h" + +/************************** Constant Definitions *****************************/ + +/** + * @name Configuration options + * These options are used in XIntc_SetOptions() to configure the device. + * @{ + */ +/** + *
+ * XIN_SVC_SGL_ISR_OPTION	Service the highest priority pending interrupt
+ *				and then return.
+ * XIN_SVC_ALL_ISRS_OPTION	Service all of the pending interrupts and then
+ *				return.
+ * 
+ */ +#define XIN_SVC_SGL_ISR_OPTION 1UL +#define XIN_SVC_ALL_ISRS_OPTION 2UL +/*@}*/ + +/** + * @name Start modes + * One of these values is passed to XIntc_Start() to start the device. + * @{ + */ +/** Simulation only mode, no hardware interrupts recognized */ +#define XIN_SIMULATION_MODE 0 +/** Real mode, no simulation allowed, hardware interrupts recognized */ +#define XIN_REAL_MODE 1 +/*@}*/ + +/** + * @name Masks to specify Interrupt Controller Mode + * @{ + */ +#define XIN_INTC_NOCASCADE 0 /* Normal - No Cascade Mode */ +#define XIN_INTC_PRIMARY 1 /* Master/Primary controller */ +#define XIN_INTC_SECONDARY 2 /* Secondary Slave Controllers */ +#define XIN_INTC_LAST 3 /* Last Slave Controller */ + +/*@}*/ + +/** + * @name Mask to specify maximum number of interrupt sources per controller + * @{ + */ +#define XIN_CONTROLLER_MAX_INTRS 32 /* Each Controller has 32 + interrupt pins */ + +#define XINTC_STANDARD_VECTOR_ADDRESS_WIDTH 32U +/*@}*/ + +/**************************** Type Definitions *******************************/ + +/** + * This typedef contains configuration information for the device. + */ +typedef struct { + u16 DeviceId; /**< Unique ID of device */ + UINTPTR BaseAddress; /**< Register base address */ + u32 AckBeforeService; /**< Ack location per interrupt */ + int FastIntr; /**< Fast Interrupt enabled */ + u32 IntVectorAddr; /**< Interrupt Vector Address */ + int NumberofIntrs; /**< Number of Interrupt sources */ + u8 VectorAddrWidth; /**< Width of vector address */ + u32 Options; /**< Device options */ + int IntcType; /**< Intc type 0 - No Cascade Mode + 1 - primary instance + 2 - secondary instance + 3 - last instance */ + +/** Static vector table of interrupt handlers */ +#if XPAR_INTC_0_INTC_TYPE != XIN_INTC_NOCASCADE + XIntc_VectorTableEntry HandlerTable[XIN_CONTROLLER_MAX_INTRS]; +#else + XIntc_VectorTableEntry HandlerTable[XPAR_INTC_MAX_NUM_INTR_INPUTS]; +#endif + +} XIntc_Config; + +/** + * The XIntc driver instance data. The user is required to allocate a + * variable of this type for every intc device in the system. A pointer + * to a variable of this type is then passed to the driver API functions. + */ +typedef struct { + UINTPTR BaseAddress; /**< Base address of registers */ + u32 IsReady; /**< Device is initialized and ready */ + u32 IsStarted; /**< Device has been started */ + u32 UnhandledInterrupts; /**< Intc Statistics */ + XIntc_Config *CfgPtr; /**< Pointer to instance config entry */ + +} XIntc; + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/* + * Required functions in xintc.c + */ +int XIntc_Initialize(XIntc * InstancePtr, u16 DeviceId); + +int XIntc_Start(XIntc * InstancePtr, u8 Mode); +void XIntc_Stop(XIntc * InstancePtr); + +int XIntc_Connect(XIntc * InstancePtr, u8 Id, + XInterruptHandler Handler, void *CallBackRef); +void XIntc_Disconnect(XIntc * InstancePtr, u8 Id); + +void XIntc_Enable(XIntc * InstancePtr, u8 Id); +void XIntc_Disable(XIntc * InstancePtr, u8 Id); + +void XIntc_Acknowledge(XIntc * InstancePtr, u8 Id); + +XIntc_Config *XIntc_LookupConfig(u16 DeviceId); + +int XIntc_ConnectFastHandler(XIntc *InstancePtr, u8 Id, + XFastInterruptHandler Handler); +void XIntc_SetNormalIntrMode(XIntc *InstancePtr, u8 Id); + +/* + * Interrupt functions in xintr_intr.c + */ +void XIntc_VoidInterruptHandler(void); +void XIntc_InterruptHandler(XIntc * InstancePtr); + +/* + * Options functions in xintc_options.c + */ +int XIntc_SetOptions(XIntc * InstancePtr, u32 Options); +u32 XIntc_GetOptions(XIntc * InstancePtr); + +/* + * Self-test functions in xintc_selftest.c + */ +int XIntc_SelfTest(XIntc * InstancePtr); +int XIntc_SimulateIntr(XIntc * InstancePtr, u8 Id); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/intc_v3_9/src/xintc_g.c b/datalink814_sp/bsp/microblaze_ps/libsrc/intc_v3_9/src/xintc_g.c new file mode 100644 index 0000000..438d597 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/intc_v3_9/src/xintc_g.c @@ -0,0 +1,87 @@ + +/******************************************************************* +* +* CAUTION: This file is automatically generated by HSI. +* Version: 2019.1.3 +* DO NOT EDIT. +* +* Copyright (C) 2010-2023 Xilinx, Inc. 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 +*XILINX 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. +* +*Except as contained in this notice, the name of the Xilinx shall not be used +*in advertising or otherwise to promote the sale, use or other dealings in +*this Software without prior written authorization from Xilinx. +* + +* +* Description: Driver configuration +* +*******************************************************************/ + +#include "xparameters.h" +#include "xintc.h" + + +extern void XNullHandler (void *); + +/* +* The configuration table for devices +*/ + +XIntc_Config XIntc_ConfigTable[] = +{ + { + XPAR_AXI_INTC_DEVICE_ID, + XPAR_AXI_INTC_BASEADDR, + XPAR_AXI_INTC_KIND_OF_INTR, + XPAR_AXI_INTC_HAS_FAST, + XPAR_AXI_INTC_IVAR_RESET_VALUE, + XPAR_AXI_INTC_NUM_INTR_INPUTS, + XPAR_AXI_INTC_ADDR_WIDTH, + XIN_SVC_SGL_ISR_OPTION, + XPAR_AXI_INTC_TYPE, + { + { + XNullHandler, + (void *) XNULL + }, + { + XNullHandler, + (void *) XNULL + }, + { + XNullHandler, + (void *) XNULL + }, + { + XNullHandler, + (void *) XNULL + }, + { + XNullHandler, + (void *) XNULL + }, + { + XNullHandler, + (void *) XNULL + } + } + + } +}; + diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/intc_v3_9/src/xintc_i.h b/datalink814_sp/bsp/microblaze_ps/libsrc/intc_v3_9/src/xintc_i.h new file mode 100644 index 0000000..6a09e43 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/intc_v3_9/src/xintc_i.h @@ -0,0 +1,89 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xintc_i.h +* @addtogroup intc_v3_9 +* @{ +* +* This file contains data which is shared between files and internal to the +* XIntc component. It is intended for internal use only. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00b jhl  02/06/02 First release
+* 1.00b jhl  04/24/02 Moved register definitions to xintc_l.h
+* 1.00c rpm  10/17/03 New release. Removed extern of global, single instance
+*                     pointer.
+* 1.10c mta  03/21/07 Updated to new coding style
+* 2.00a ktn  10/20/09 Updated to use HAL Processor APIs.
+* 
+* +******************************************************************************/ + +#ifndef XINTC_I_H /* prevent circular inclusions */ +#define XINTC_I_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xintc.h" + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + + +/************************** Variable Definitions *****************************/ + +extern u32 XIntc_BitPosMask[]; + +extern XIntc_Config XIntc_ConfigTable[]; + +#ifdef __cplusplus +} +#endif + +#endif +/** @} */ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/intc_v3_9/src/xintc_intr.c b/datalink814_sp/bsp/microblaze_ps/libsrc/intc_v3_9/src/xintc_intr.c new file mode 100644 index 0000000..5d03bff --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/intc_v3_9/src/xintc_intr.c @@ -0,0 +1,172 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xintc_intr.c +* @addtogroup intc_v3_9 +* @{ +* +* This file contains the interrupt processing for the XIntc component which +* is the driver for the Xilinx Interrupt Controller. The interrupt +* processing is partitioned seperately such that users are not required to +* use the provided interrupt processing. This file requires other files of +* the driver to be linked in also. +* +* Two different interrupt handlers are provided for this driver such that the +* user must select the appropriate handler for the application. The first +* interrupt handler, XIntc_VoidInterruptHandler, is provided for systems +* which use only a single interrupt controller or for systems that cannot +* otherwise provide an argument to the XIntc interrupt handler (e.g., the RTOS +* interrupt vector handler may not provide such a facility). The constant +* XPAR_INTC_SINGLE_DEVICE_ID must be defined for this handler to be included in +* the driver. The second interrupt handler, XIntc_InterruptHandler, uses an +* input argument which is an instance pointer to an interrupt controller driver +* such that multiple interrupt controllers can be supported. This handler +* requires the calling function to pass it the appropriate argument, so another +* level of indirection may be required. +* +* Note that both of these handlers are now only provided for backward +* compatibility. The handler defined in xintc_l.c is the recommended handler. +* +* The interrupt processing may be used by connecting one of the interrupt +* handlers to the interrupt system. These handlers do not save and restore +* the processor context but only handle the processing of the Interrupt +* Controller. The two handlers are provided as working examples. The user is +* encouraged to supply their own interrupt handler when performance tuning is +* deemed necessary. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- ---------------------------------------------------------
+* 1.00b jhl  02/13/02 First release
+* 1.00c rpm  10/17/03 New release. Support the static vector table created
+*                     in the xintc_g.c configuration table. Collapse handlers
+*                     to use the XIntc_DeviceInterruptHandler() in xintc_l.c.
+* 1.00c rpm  04/09/04 Added conditional compilation around the old handler
+*                     XIntc_VoidInterruptHandler(). This handler will only be
+*                     include/compiled if XPAR_INTC_SINGLE_DEVICE_ID is defined.
+* 1.10c mta  03/21/07 Updated to new coding style
+* 2.00a ktn  10/20/09 Updated to use HAL Processor APIs.
+*
+* 
+* +* @internal +* +* This driver assumes that the context of the processor has been saved prior to +* the calling of the Interrupt Controller interrupt handler and then restored +* after the handler returns. This requires either the running RTOS to save the +* state of the machine or that a wrapper be used as the destination of the +* interrupt vector to save the state of the processor and restore the state +* after the interrupt handler returns. +* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xparameters.h" +#include "xintc.h" + +/************************** Constant Definitions *****************************/ + + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + + +/************************** Variable Definitions *****************************/ + + +/*****************************************************************************/ +/** +* +* Interrupt handler for the driver used when there can be no argument passed +* to the handler. This function is provided mostly for backward compatibility. +* The user should use XIntc_DeviceInterruptHandler(), defined in xintc_l.c, +* if possible. +* +* The user must connect this function to the interrupt system such that it is +* called whenever the devices which are connected to it cause an interrupt. +* +* @return None. +* +* @note +* +* The constant XPAR_INTC_SINGLE_DEVICE_ID must be defined for this handler +* to be included in the driver compilation. +* +******************************************************************************/ +#ifdef XPAR_INTC_SINGLE_DEVICE_ID +void XIntc_VoidInterruptHandler(void) +{ + /* Use the single instance to call the main interrupt handler */ + XIntc_DeviceInterruptHandler((void *) XPAR_INTC_SINGLE_DEVICE_ID); +} +#endif + +/*****************************************************************************/ +/** +* +* The interrupt handler for the driver. This function is provided mostly for +* backward compatibility. The user should use XIntc_DeviceInterruptHandler(), +* defined in xintc_l.c when possible and pass the device ID of the interrupt +* controller device as its argument. +* +* The user must connect this function to the interrupt system such that it is +* called whenever the devices which are connected to it cause an interrupt. +* +* @param InstancePtr is a pointer to the XIntc instance to be worked on. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XIntc_InterruptHandler(XIntc * InstancePtr) +{ + /* Assert that the pointer to the instance is valid + */ + Xil_AssertVoid(InstancePtr != NULL); + + /* Use the instance's device ID to call the main interrupt handler. + * (the casts are to avoid a compiler warning) + */ + XIntc_DeviceInterruptHandler((void *) + ((u32) (InstancePtr->CfgPtr->DeviceId))); +} +/** @} */ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/intc_v3_9/src/xintc_l.c b/datalink814_sp/bsp/microblaze_ps/libsrc/intc_v3_9/src/xintc_l.c new file mode 100644 index 0000000..41df264 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/intc_v3_9/src/xintc_l.c @@ -0,0 +1,677 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xintc_l.c +* @addtogroup intc_v3_9 +* @{ +* +* This file contains low-level driver functions that can be used to access the +* device. The user should refer to the hardware device specification for more +* details of the device operation. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00b jhl  04/24/02 First release
+* 1.00c rpm  10/17/03 New release. Support the static vector table created
+*                     in the xintc_g.c configuration table.
+* 1.00c rpm  04/09/04 Added conditional compilation around the old handler
+*                     XIntc_LowLevelInterruptHandler(). This handler will only
+*                     be include/compiled if XPAR_INTC_SINGLE_DEVICE_ID is
+*                     defined.
+* 1.10c mta  03/21/07 Updated to new coding style
+* 1.10c ecm  07/09/07 Read the ISR after the Acknowledge in the interrupt
+*		      handler to support architectures with posted write bus
+*		      access issues.
+* 2.00a ktn  10/20/09 Updated to use HAL Processor APIs and  _m is removed
+*		      from all the macro definitions.
+* 2.04a bss  01/13/12 Removed the unused Register variable for warnings.
+* 2.05a bss  08/18/12 Added XIntc_RegisterFastHandler API to register fast
+*		      interrupt handlers using base address.
+* 2.06a bss  01/28/13 To support Cascade mode:
+*		      Modified XIntc_DeviceInterruptHandler,
+*		      XIntc_SetIntrSvcOption,XIntc_RegisterHandler and
+*		      XIntc_RegisterFastHandler APIs.
+*		      Added XIntc_CascadeHandler API.
+* 2.07a bss  10/18/13 Modified XIntc_DeviceInterruptHandler to support
+*		      nested interrupts.
+* 3.5   sk   11/10/15 Used UINTPTR instead of u32 for Baseaddress CR# 867425.
+*                     Changed the prototypes of LookupConfigByBaseAddress,
+*                     XIntc_SetIntrSvcOption, XIntc_RegisterHandler,
+*                     XIntc_RegisterFastHandler APIs.
+*
+* 
+* +******************************************************************************/ + + +/***************************** Include Files *********************************/ + +#include "xparameters.h" +#include "xil_types.h" +#include "xil_assert.h" +#include "xintc.h" +#include "xintc_i.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + +static XIntc_Config *LookupConfigByBaseAddress(UINTPTR BaseAddress); + +#if XPAR_INTC_0_INTC_TYPE != XIN_INTC_NOCASCADE +static void XIntc_CascadeHandler(void *DeviceId); +#endif + +/************************** Variable Definitions *****************************/ + +/*****************************************************************************/ +/** +* +* This is the interrupt handler for the driver interface provided in this file +* when there can be no argument passed to the handler. In this case, we just +* use the globally defined device ID for the interrupt controller. This function +* is provided mostly for backward compatibility. The user should use +* XIntc_DeviceInterruptHandler() if possible. +* +* This function does not support multiple interrupt controller instances to be +* handled. +* +* The user must connect this function to the interrupt system such that it is +* called whenever the devices which are connected to it cause an interrupt. +* +* @return None. +* +* @note +* +* The constant XPAR_INTC_SINGLE_DEVICE_ID must be defined for this handler +* to be included in the driver compilation. +* +******************************************************************************/ +#ifdef XPAR_INTC_SINGLE_DEVICE_ID +void XIntc_LowLevelInterruptHandler(void) +{ + /* + * A level of indirection here because the interrupt handler used with + * the driver interface given in this file needs to remain void - no + * arguments. So we need the globally defined device ID of THE + * interrupt controller. + */ + XIntc_DeviceInterruptHandler((void *) XPAR_INTC_SINGLE_DEVICE_ID); +} +#endif + +/*****************************************************************************/ +/** +* +* This function is the primary interrupt handler for the driver. It must be +* connected to the interrupt source such that is called when an interrupt of +* the interrupt controller is active. It will resolve which interrupts are +* active and enabled and call the appropriate interrupt handler. It uses +* the AckBeforeService flag in the configuration data to determine when to +* acknowledge the interrupt. Highest priority interrupts are serviced first. +* This function assumes that an interrupt vector table has been previously +* initialized.It does not verify that entries in the table are valid before +* calling an interrupt handler. In Cascade mode this function calls +* XIntc_CascadeHandler to handle interrupts of Master and Slave controllers. +* This functions also handles interrupts nesting by saving and restoring link +* register of Microblaze and Interrupt Level register of interrupt controller +* properly. + +* @param DeviceId is the zero-based device ID defined in xparameters.h +* of the interrupting interrupt controller. It is used as a direct +* index into the configuration data, which contains the vector +* table for the interrupt controller. Note that even though the +* argument is a void pointer, the value is not a pointer but the +* actual device ID. The void pointer type is necessary to meet +* the XInterruptHandler typedef for interrupt handlers. +* +* @return None. +* +* @note For nested interrupts, this function saves microblaze r14 +* register on entry and restores on exit. This is required since +* compiler does not support nesting. This function enables +* Microblaze interrupts after blocking further interrupts +* from the current interrupt number and interrupts below current +* interrupt proirity by writing to Interrupt Level Register of +* INTC on entry. On exit, it disables microblaze interrupts and +* restores ILR register default value(0xFFFFFFFF)back. It is +* recommended to increase STACK_SIZE in linker script for nested +* interrupts. +* +******************************************************************************/ +void XIntc_DeviceInterruptHandler(void *DeviceId) +{ + u32 IntrStatus; + u32 IntrMask = 1; + int IntrNumber; + XIntc_Config *CfgPtr; + u32 Imr; + + /* Get the configuration data using the device ID */ + CfgPtr = &XIntc_ConfigTable[(u32)DeviceId]; + +#if XPAR_INTC_0_INTC_TYPE != XIN_INTC_NOCASCADE + if (CfgPtr->IntcType != XIN_INTC_NOCASCADE) { + XIntc_CascadeHandler(DeviceId); + } + else +#endif + { /* This extra brace is required for compilation in Cascade Mode */ + +#if XPAR_XINTC_HAS_ILR == TRUE +#ifdef __MICROBLAZE__ + volatile u32 R14_register; + /* Save r14 register */ + R14_register = mfgpr(r14); +#endif + volatile u32 ILR_reg; + /* Save ILR register */ + ILR_reg = Xil_In32(CfgPtr->BaseAddress + XIN_ILR_OFFSET); +#endif + /* Get the interrupts that are waiting to be serviced */ + IntrStatus = XIntc_GetIntrStatus(CfgPtr->BaseAddress); + + /* Mask the Fast Interrupts */ + if (CfgPtr->FastIntr == TRUE) { + Imr = XIntc_In32(CfgPtr->BaseAddress + XIN_IMR_OFFSET); + IntrStatus &= ~Imr; + } + + /* Service each interrupt that is active and enabled by + * checking each bit in the register from LSB to MSB which + * corresponds to an interrupt input signal + */ + for (IntrNumber = 0; IntrNumber < CfgPtr->NumberofIntrs; + IntrNumber++) { + if (IntrStatus & 1) { + XIntc_VectorTableEntry *TablePtr; +#if XPAR_XINTC_HAS_ILR == TRUE + /* Write to ILR the current interrupt + * number + */ + Xil_Out32(CfgPtr->BaseAddress + + XIN_ILR_OFFSET, IntrNumber); + + /* Read back ILR to ensure the value + * has been updated and it is safe to + * enable interrupts + */ + + Xil_In32(CfgPtr->BaseAddress + + XIN_ILR_OFFSET); + + /* Enable interrupts */ + Xil_ExceptionEnable(); +#endif + /* If the interrupt has been setup to + * acknowledge it before servicing the + * interrupt, then ack it */ + if (CfgPtr->AckBeforeService & IntrMask) { + XIntc_AckIntr(CfgPtr->BaseAddress, + IntrMask); + } + + /* The interrupt is active and enabled, call + * the interrupt handler that was setup with + * the specified parameter + */ + TablePtr = &(CfgPtr->HandlerTable[IntrNumber]); + TablePtr->Handler(TablePtr->CallBackRef); + + /* If the interrupt has been setup to + * acknowledge it after it has been serviced + * then ack it + */ + if ((CfgPtr->AckBeforeService & + IntrMask) == 0) { + XIntc_AckIntr(CfgPtr->BaseAddress, + IntrMask); + } + +#if XPAR_XINTC_HAS_ILR == TRUE + /* Disable interrupts */ + Xil_ExceptionDisable(); + /* Restore ILR */ + Xil_Out32(CfgPtr->BaseAddress + XIN_ILR_OFFSET, + ILR_reg); +#endif + /* + * Read the ISR again to handle architectures + * with posted write bus access issues. + */ + (void) XIntc_GetIntrStatus(CfgPtr->BaseAddress); + + /* + * If only the highest priority interrupt is to + * be serviced, exit loop and return after + * servicing + * the interrupt + */ + if (CfgPtr->Options == XIN_SVC_SGL_ISR_OPTION) { + +#if XPAR_XINTC_HAS_ILR == TRUE +#ifdef __MICROBLAZE__ + /* Restore r14 */ + mtgpr(r14, R14_register); +#endif +#endif + return; + } + } + + /* Move to the next interrupt to check */ + IntrMask <<= 1; + IntrStatus >>= 1; + + /* If there are no other bits set indicating that all + * interrupts have been serviced, then exit the loop + */ + if (IntrStatus == 0) { + break; + } + } +#if XPAR_XINTC_HAS_ILR == TRUE +#ifdef __MICROBLAZE__ + /* Restore r14 */ + mtgpr(r14, R14_register); +#endif +#endif + } +} + +/*****************************************************************************/ +/** +* +* Set the interrupt service option, which can configure the driver so that it +* services only a single interrupt at a time when an interrupt occurs, or +* services all pending interrupts when an interrupt occurs. The default +* behavior when using the driver interface given in xintc.h file is to service +* only a single interrupt, whereas the default behavior when using the driver +* interface given in this file is to service all outstanding interrupts when an +* interrupt occurs. In Cascade mode same Option is set to Slave controllers. +* +* @param BaseAddress is the unique identifier for a device. +* @param Option is XIN_SVC_SGL_ISR_OPTION if you want only a single +* interrupt serviced when an interrupt occurs, or +* XIN_SVC_ALL_ISRS_OPTION if you want all pending interrupts +* serviced when an interrupt occurs. +* +* @return None. +* +* @note +* +* Note that this function has no effect if the input base address is invalid. +* +******************************************************************************/ +void XIntc_SetIntrSvcOption(UINTPTR BaseAddress, int Option) +{ + XIntc_Config *CfgPtr; + + CfgPtr = LookupConfigByBaseAddress(BaseAddress); + if (CfgPtr != NULL) { + CfgPtr->Options = Option; + /* If Cascade mode set the option for all Slaves */ + if (CfgPtr->IntcType != XIN_INTC_NOCASCADE) { + int Index; + for (Index = 1; Index <= XPAR_XINTC_NUM_INSTANCES - 1; + Index++) { + CfgPtr = XIntc_LookupConfig(Index); + CfgPtr->Options = Option; + } + } + } +} + +/*****************************************************************************/ +/** +* +* Register a handler function for a specific interrupt ID. The vector table +* of the interrupt controller is updated, overwriting any previous handler. +* The handler function will be called when an interrupt occurs for the given +* interrupt ID. +* +* This function can also be used to remove a handler from the vector table +* by passing in the XIntc_DefaultHandler() as the handler and NULL as the +* callback reference. +* In Cascade mode Interrupt Id is used to set Handler for corresponding Slave +* Controller +* +* @param BaseAddress is the base address of the interrupt controller +* whose vector table will be modified. +* @param InterruptId is the interrupt ID to be associated with the input +* handler. +* @param Handler is the function pointer that will be added to +* the vector table for the given interrupt ID. +* @param CallBackRef is the argument that will be passed to the new +* handler function when it is called. This is user-specific. +* +* @return None. +* +* @note +* +* Note that this function has no effect if the input base address is invalid. +* +******************************************************************************/ +void XIntc_RegisterHandler(UINTPTR BaseAddress, int InterruptId, + XInterruptHandler Handler, void *CallBackRef) +{ + XIntc_Config *CfgPtr; + + CfgPtr = LookupConfigByBaseAddress(BaseAddress); + + if (CfgPtr != NULL) { + + if (InterruptId > 31) { + CfgPtr = XIntc_LookupConfig(InterruptId/32); + CfgPtr->HandlerTable[InterruptId%32].Handler = Handler; + CfgPtr->HandlerTable[InterruptId%32].CallBackRef = + CallBackRef; + } + else { + CfgPtr->HandlerTable[InterruptId].Handler = Handler; + CfgPtr->HandlerTable[InterruptId].CallBackRef = + CallBackRef; + } + } +} + + +/*****************************************************************************/ +/** +* +* Looks up the device configuration based on the base address of the device. +* A table contains the configuration info for each device in the system. +* +* @param BaseAddress is the unique identifier for a device. +* +* @return +* +* A pointer to the configuration structure for the specified device, or +* NULL if the device was not found. +* +* @note None. +* +******************************************************************************/ +static XIntc_Config *LookupConfigByBaseAddress(UINTPTR BaseAddress) +{ + XIntc_Config *CfgPtr = NULL; + int Index; + + for (Index = 0; Index < XPAR_XINTC_NUM_INSTANCES; Index++) { + if (XIntc_ConfigTable[Index].BaseAddress == BaseAddress) { + CfgPtr = &XIntc_ConfigTable[Index]; + break; + } + } + + return CfgPtr; +} + +/*****************************************************************************/ +/** +* +* Register a fast handler function for a specific interrupt ID. The handler +* function will be called when an interrupt occurs for the given interrupt ID. +* In Cascade mode Interrupt Id is used to set Handler for corresponding Slave +* Controller +* +* @param BaseAddress is the base address of the interrupt controller +* whose vector table will be modified. +* @param InterruptId is the interrupt ID to be associated with the input +* handler. +* @param FastHandler is the function pointer that will be called when +* interrupt occurs +* +* @return None. +* +* @note +* +* Note that this function has no effect if the input base address is invalid. +* +******************************************************************************/ +void XIntc_RegisterFastHandler(UINTPTR BaseAddress, u8 Id, + XFastInterruptHandler FastHandler) +{ + u32 CurrentIER; + u32 Mask; + u32 Imr; + XIntc_Config *CfgPtr; + + + if (Id > 31) { + /* Enable user required Id in Slave controller */ + CfgPtr = XIntc_LookupConfig(Id/32); + + /* Get the Enabled Interrupts */ + CurrentIER = XIntc_In32(CfgPtr->BaseAddress + XIN_IER_OFFSET); + + /* Convert from integer id to bit mask */ + Mask = XIntc_BitPosMask[(Id%32)]; + + /* Disable the Interrupt if it was enabled before calling + * this function + */ + if (CurrentIER & Mask) { + XIntc_Out32(CfgPtr->BaseAddress + XIN_IER_OFFSET, + (CurrentIER & ~Mask)); + } + if (CfgPtr->VectorAddrWidth > + XINTC_STANDARD_VECTOR_ADDRESS_WIDTH) { + XIntc_Out64(CfgPtr->BaseAddress + XIN_IVEAR_OFFSET + + ((Id%32) * 8), (UINTPTR) FastHandler); + } else { + XIntc_Out32(CfgPtr->BaseAddress + XIN_IVAR_OFFSET + + ((Id%32) * 4), (u32) FastHandler); + } + + /* Slave controllers in Cascade Mode should have all as Fast + * interrupts or Normal interrupts, mixed interrupts are not + * supported + */ + XIntc_Out32(CfgPtr->BaseAddress + XIN_IMR_OFFSET, 0xFFFFFFFF); + + /* Enable the Interrupt if it was enabled before calling this + * function + */ + if (CurrentIER & Mask) { + XIntc_Out32(CfgPtr->BaseAddress + XIN_IER_OFFSET, + (CurrentIER | Mask)); + } + } + else { + + CurrentIER = XIntc_In32(BaseAddress + XIN_IER_OFFSET); + + /* Convert from integer id to bit mask */ + Mask = XIntc_BitPosMask[Id]; + + if (CurrentIER & Mask) { + /* Disable Interrupt if it was enabled */ + CurrentIER = XIntc_In32(BaseAddress + XIN_IER_OFFSET); + XIntc_Out32(BaseAddress + XIN_IER_OFFSET, + (CurrentIER & ~Mask)); + } + + CfgPtr = XIntc_LookupConfig(Id/32); + if (CfgPtr->VectorAddrWidth > + XINTC_STANDARD_VECTOR_ADDRESS_WIDTH) { + XIntc_Out64(BaseAddress + XIN_IVEAR_OFFSET + + (Id * 8), (UINTPTR) FastHandler); + } else { + XIntc_Out32(BaseAddress + XIN_IVAR_OFFSET + (Id * 4), + (u32) FastHandler); + } + + Imr = XIntc_In32(BaseAddress + XIN_IMR_OFFSET); + XIntc_Out32(BaseAddress + XIN_IMR_OFFSET, Imr | Mask); + + + /* Enable Interrupt if it was enabled before calling + * this function + */ + if (CurrentIER & Mask) { + CurrentIER = XIntc_In32(BaseAddress + XIN_IER_OFFSET); + XIntc_Out32(BaseAddress + XIN_IER_OFFSET, + (CurrentIER | Mask)); + } + } +} + +#if XPAR_INTC_0_INTC_TYPE != XIN_INTC_NOCASCADE +/*****************************************************************************/ +/** +* +* This function is called by primary interrupt handler for the driver to handle +* all Controllers in Cascade mode.It will resolve which interrupts are active +* and enabled and call the appropriate interrupt handler. It uses the +* AckBeforeService flag in the configuration data to determine when to +* acknowledge the interrupt. Highest priority interrupts are serviced first. +* This function assumes that an interrupt vector table has been previously +* initialized. It does not verify that entries in the table are valid before +* calling an interrupt handler.This function calls itself recursively to handle +* all interrupt controllers. +* +* @param DeviceId is the zero-based device ID defined in xparameters.h +* of the interrupting interrupt controller. It is used as a direct +* index into the configuration data, which contains the vector +* table for the interrupt controller. +* +* @return None. +* +* @note +* +******************************************************************************/ +static void XIntc_CascadeHandler(void *DeviceId) +{ + u32 IntrStatus; + u32 IntrMask = 1; + int IntrNumber; + u32 Imr; + XIntc_Config *CfgPtr; + static int Id = 0; + + /* Get the configuration data using the device ID */ + CfgPtr = &XIntc_ConfigTable[(u32)DeviceId]; + + /* Get the interrupts that are waiting to be serviced */ + IntrStatus = XIntc_GetIntrStatus(CfgPtr->BaseAddress); + + /* Mask the Fast Interrupts */ + if (CfgPtr->FastIntr == TRUE) { + Imr = XIntc_In32(CfgPtr->BaseAddress + XIN_IMR_OFFSET); + IntrStatus &= ~Imr; + } + + /* Service each interrupt that is active and enabled by + * checking each bit in the register from LSB to MSB which + * corresponds to an interrupt input signal + */ + for (IntrNumber = 0; IntrNumber < CfgPtr->NumberofIntrs; IntrNumber++) { + if (IntrStatus & 1) { + XIntc_VectorTableEntry *TablePtr; + + /* In Cascade mode call this function recursively + * for interrupt id 31 and until interrupts of last + * instance/controller are handled + */ + if ((IntrNumber == 31) && + (CfgPtr->IntcType != XIN_INTC_LAST) && + (CfgPtr->IntcType != XIN_INTC_NOCASCADE)) { + XIntc_CascadeHandler((void *)++Id); + Id--; + } + + /* If the interrupt has been setup to + * acknowledge it before servicing the + * interrupt, then ack it */ + if (CfgPtr->AckBeforeService & IntrMask) { + XIntc_AckIntr(CfgPtr->BaseAddress, IntrMask); + } + + /* Handler of 31 interrupt Id has to be called only + * for Last controller in cascade Mode + */ + if (!((IntrNumber == 31) && + (CfgPtr->IntcType != XIN_INTC_LAST) && + (CfgPtr->IntcType != XIN_INTC_NOCASCADE))) { + + /* The interrupt is active and enabled, call + * the interrupt handler that was setup with + * the specified parameter + */ + TablePtr = &(CfgPtr->HandlerTable[IntrNumber]); + TablePtr->Handler(TablePtr->CallBackRef); + } + /* If the interrupt has been setup to acknowledge it + * after it has been serviced then ack it + */ + if ((CfgPtr->AckBeforeService & IntrMask) == 0) { + XIntc_AckIntr(CfgPtr->BaseAddress, IntrMask); + } + + /* + * Read the ISR again to handle architectures with + * posted write bus access issues. + */ + XIntc_GetIntrStatus(CfgPtr->BaseAddress); + + /* + * If only the highest priority interrupt is to be + * serviced, exit loop and return after servicing + * the interrupt + */ + if (CfgPtr->Options == XIN_SVC_SGL_ISR_OPTION) { + return; + } + } + + /* Move to the next interrupt to check */ + IntrMask <<= 1; + IntrStatus >>= 1; + + /* If there are no other bits set indicating that all interrupts + * have been serviced, then exit the loop + */ + if (IntrStatus == 0) { + break; + } + } +} +#endif +/** @} */ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/intc_v3_9/src/xintc_l.h b/datalink814_sp/bsp/microblaze_ps/libsrc/intc_v3_9/src/xintc_l.h new file mode 100644 index 0000000..49b417e --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/intc_v3_9/src/xintc_l.h @@ -0,0 +1,331 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xintc_l.h +* @addtogroup intc_v3_9 +* @{ +* +* This header file contains identifiers and low-level driver functions (or +* macros) that can be used to access the device. The user should refer to the +* hardware device specification for more details of the device operation. +* +* +* Note that users of the driver interface given in this file can register +* an interrupt handler dynamically (at run-time) using the +* XIntc_RegisterHandler() function. +* User of the driver interface given in xintc.h should still use +* XIntc_Connect(), as always. +* Also see the discussion of the interrupt vector tables in xintc.h. +* +* There are currently two interrupt handlers specified in this interface. +* +* - XIntc_LowLevelInterruptHandler() is a handler without any arguments that +* is used in cases where there is a single interrupt controller device in +* the system and the handler cannot be passed an argument. This function is +* provided mostly for backward compatibility. +* +* - XIntc_DeviceInterruptHandler() is a handler that takes a device ID as an +* argument, indicating which interrupt controller device in the system is +* causing the interrupt - thereby supporting multiple interrupt controllers. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------------
+* 1.00b jhl  04/24/02 First release
+* 1.00c rpm  10/17/03 New release. Support the static vector table created
+*                     in the xintc_g.c configuration table.
+* 1.10c mta  03/21/07 Updated to new coding style
+* 1.11a sv   11/21/07 Updated driver to support access through a DCR bridge
+* 2.00a ktn  10/20/09 Updated to use HAL Processor APIs. _m is removed from all
+*		      the macro definitions.
+* 2.04a bss  01/13/12 Updated for adding defines for IMR and IVAR for
+*                     the FAST Interrupt
+* 2.05a bss  08/18/12 Added XIntc_RegisterFastHandler API to register fast
+*		      interrupt handlers using base address.
+* 2.07a bss  10/18/13 Added XIN_ILR_OFFSET macro for nested interrupts.
+* 3.5   sk   11/10/15 Used UINTPTR instead of u32 for Baseaddress CR# 867425.
+*                     Changed the prototypes of XIntc_RegisterFastHandler,
+*                     XIntc_SetIntrSvcOption, XIntc_RegisterHandler APIs.
+*
+* 
+* +******************************************************************************/ + +#ifndef XINTC_L_H /* prevent circular inclusions */ +#define XINTC_L_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xparameters.h" +#include "xil_io.h" + +/* + * XPAR_XINTC_USE_DCR_BRIDGE has to be set to 1 if the Intc device will be + * accessed through a DCR bus connected to a bridge. + */ +#define XPAR_XINTC_USE_DCR_BRIDGE 0 + +#if ((XPAR_XINTC_USE_DCR != 0) || (XPAR_XINTC_USE_DCR_BRIDGE != 0)) +#include "xio_dcr.h" +#endif + +/************************** Constant Definitions *****************************/ + +/* define the offsets from the base address for all the registers of the + * interrupt controller, some registers may be optional in the hardware device + */ +#if ((XPAR_XINTC_USE_DCR != 0) || (XPAR_XINTC_USE_DCR_BRIDGE != 0)) + +#define XIN_ISR_OFFSET 0 /* Interrupt Status Register */ +#define XIN_IPR_OFFSET 1 /* Interrupt Pending Register */ +#define XIN_IER_OFFSET 2 /* Interrupt Enable Register */ +#define XIN_IAR_OFFSET 3 /* Interrupt Acknowledge Register */ +#define XIN_SIE_OFFSET 4 /* Set Interrupt Enable Register */ +#define XIN_CIE_OFFSET 5 /* Clear Interrupt Enable Register */ +#define XIN_IVR_OFFSET 6 /* Interrupt Vector Register */ +#define XIN_MER_OFFSET 7 /* Master Enable Register */ +#define XIN_IMR_OFFSET 8 /* Interrupt Mode Register , this is present + * only for Fast Interrupt */ +#define XIN_IVAR_OFFSET 64 /* Interrupt Vector Address Register + * Interrupt 0 Offest, this is present + * only for Fast Interrupt */ + +#else /* ((XPAR_XINTC_USE_DCR != 0) || (XPAR_XINTC_USE_DCR_BRIDGE != 0)) */ + +#define XIN_ISR_OFFSET 0 /* Interrupt Status Register */ +#define XIN_IPR_OFFSET 4 /* Interrupt Pending Register */ +#define XIN_IER_OFFSET 8 /* Interrupt Enable Register */ +#define XIN_IAR_OFFSET 12 /* Interrupt Acknowledge Register */ +#define XIN_SIE_OFFSET 16 /* Set Interrupt Enable Register */ +#define XIN_CIE_OFFSET 20 /* Clear Interrupt Enable Register */ +#define XIN_IVR_OFFSET 24 /* Interrupt Vector Register */ +#define XIN_MER_OFFSET 28 /* Master Enable Register */ +#define XIN_IMR_OFFSET 32 /* Interrupt Mode Register , this is present + * only for Fast Interrupt */ +#define XIN_ILR_OFFSET 36 /* Interrupt level register */ +#define XIN_IVAR_OFFSET 0x100 /* Interrupt Vector Address Register + * Interrupt 0 Offest, this is present + * only for Fast Interrupt */ +#define XIN_IVEAR_OFFSET 0x200 /* Interrupt Vector Extended Address + Register */ + + +#endif /* ((XPAR_XINTC_USE_DCR != 0) || (XPAR_XINTC_USE_DCR_BRIDGE != 0)) */ + +/* Bit definitions for the bits of the MER register */ + +#define XIN_INT_MASTER_ENABLE_MASK 0x1UL +#define XIN_INT_HARDWARE_ENABLE_MASK 0x2UL /* once set cannot be cleared */ + +/**************************** Type Definitions *******************************/ + +/* The following data type defines each entry in an interrupt vector table. + * The callback reference is the base address of the interrupting device + * for the driver interface given in this file and an instance pointer for the + * driver interface given in xintc.h file. + */ +typedef struct { + XInterruptHandler Handler; + void *CallBackRef; +} XIntc_VectorTableEntry; + +typedef void (*XFastInterruptHandler) (void); + +/***************** Macros (Inline Functions) Definitions *********************/ + +/* + * Define the appropriate I/O access method to memory mapped I/O or DCR. + */ +#if ((XPAR_XINTC_USE_DCR != 0) || (XPAR_XINTC_USE_DCR_BRIDGE != 0)) + +#define XIntc_In32 XIo_DcrIn +#define XIntc_Out32 XIo_DcrOut + +#else + +#define XIntc_In32 Xil_In32 +#define XIntc_Out32 Xil_Out32 +#define XIntc_Out64 Xil_Out64 + +#endif + +/****************************************************************************/ +/** +* +* Enable all interrupts in the Master Enable register of the interrupt +* controller. The interrupt controller defaults to all interrupts disabled +* from reset such that this macro must be used to enable interrupts. +* +* @param BaseAddress is the base address of the device. +* +* @return None. +* +* @note C-style signature: +* void XIntc_MasterEnable(u32 BaseAddress); +* +*****************************************************************************/ +#define XIntc_MasterEnable(BaseAddress) \ + XIntc_Out32((BaseAddress) + XIN_MER_OFFSET, \ + XIN_INT_MASTER_ENABLE_MASK | XIN_INT_HARDWARE_ENABLE_MASK) + +/****************************************************************************/ +/** +* +* Disable all interrupts in the Master Enable register of the interrupt +* controller. +* +* @param BaseAddress is the base address of the device. +* +* @return None. +* +* @note C-style signature: +* void XIntc_MasterDisable(u32 BaseAddress); +* +*****************************************************************************/ +#define XIntc_MasterDisable(BaseAddress) \ + XIntc_Out32((BaseAddress) + XIN_MER_OFFSET, 0) + +/****************************************************************************/ +/** +* +* Enable specific interrupt(s) in the interrupt controller. +* +* @param BaseAddress is the base address of the device +* @param EnableMask is the 32-bit value to write to the enable register. +* Each bit of the mask corresponds to an interrupt input signal +* that is connected to the interrupt controller (INT0 = LSB). +* Only the bits which are set in the mask will enable interrupts. +* +* @return None. +* +* @note C-style signature: +* void XIntc_EnableIntr(u32 BaseAddress, u32 EnableMask); +* +*****************************************************************************/ +#define XIntc_EnableIntr(BaseAddress, EnableMask) \ + XIntc_Out32((BaseAddress) + XIN_IER_OFFSET, (EnableMask)) + +/****************************************************************************/ +/** +* +* Disable specific interrupt(s) in the interrupt controller. +* +* @param BaseAddress is the base address of the device +* @param DisableMask is the 32-bit value to write to the enable register. +* Each bit of the mask corresponds to an interrupt input signal +* that is connected to the interrupt controller (INT0 = LSB). +* Only the bits which are set in the mask will disable interrupts. +* +* @return None. +* +* @note C-style signature: +* void XIntc_DisableIntr(u32 BaseAddress, u32 DisableMask); +* +*****************************************************************************/ +#define XIntc_DisableIntr(BaseAddress, DisableMask) \ + XIntc_Out32((BaseAddress) + XIN_IER_OFFSET, ~(DisableMask)) + +/****************************************************************************/ +/** +* +* Acknowledge specific interrupt(s) in the interrupt controller. +* +* @param BaseAddress is the base address of the device +* @param AckMask is the 32-bit value to write to the acknowledge +* register. Each bit of the mask corresponds to an interrupt input +* signal that is connected to the interrupt controller (INT0 = +* LSB). Only the bits which are set in the mask will acknowledge +* interrupts. +* +* @return None. +* +* @note C-style signature: +* void XIntc_AckIntr(u32 BaseAddress, u32 AckMask); +* +*****************************************************************************/ +#define XIntc_AckIntr(BaseAddress, AckMask) \ + XIntc_Out32((BaseAddress) + XIN_IAR_OFFSET, (AckMask)) + +/****************************************************************************/ +/** +* +* Get the interrupt status from the interrupt controller which indicates +* which interrupts are active and enabled. +* +* @param BaseAddress is the base address of the device +* +* @return The 32-bit contents of the interrupt status register. Each bit +* corresponds to an interrupt input signal that is connected to +* the interrupt controller (INT0 = LSB). Bits which are set +* indicate an active interrupt which is also enabled. +* +* @note C-style signature: +* u32 XIntc_GetIntrStatus(u32 BaseAddress); +* +*****************************************************************************/ +#define XIntc_GetIntrStatus(BaseAddress) \ + (XIntc_In32((BaseAddress) + XIN_ISR_OFFSET) & \ + XIntc_In32((BaseAddress) + XIN_IER_OFFSET)) + +/************************** Function Prototypes ******************************/ + +/* + * Interrupt controller handlers, to be connected to processor exception + * handling code. + */ +void XIntc_LowLevelInterruptHandler(void); +void XIntc_DeviceInterruptHandler(void *DeviceId); + +/* Various configuration functions */ +void XIntc_SetIntrSvcOption(UINTPTR BaseAddress, int Option); + +void XIntc_RegisterHandler(UINTPTR BaseAddress, int InterruptId, + XInterruptHandler Handler, void *CallBackRef); + +void XIntc_RegisterFastHandler(UINTPTR BaseAddress, u8 Id, + XFastInterruptHandler FastHandler); + +/************************** Variable Definitions *****************************/ + + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/intc_v3_9/src/xintc_options.c b/datalink814_sp/bsp/microblaze_ps/libsrc/intc_v3_9/src/xintc_options.c new file mode 100644 index 0000000..3090d4c --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/intc_v3_9/src/xintc_options.c @@ -0,0 +1,145 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xintc_options.c +* @addtogroup intc_v3_9 +* @{ +* +* Contains option functions for the XIntc driver. These functions allow the +* user to configure an instance of the XIntc driver. This file requires other +* files of the component to be linked in also. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------------
+* 1.00b jhl  02/21/02 First release
+* 1.00c rpm  10/17/03 New release. Support the relocation of the options flag
+*                     from the instance structure to the xintc_g.c
+*                     configuration table.
+* 1.10c mta  03/21/07 Updated to new coding style
+* 2.00a ktn  10/20/09 Updated to use HAL Processor APIs
+* 2.06a bss  01/28/13 To support Cascade mode:
+*		      Modified XIntc_SetOptions API.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xintc.h" + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + + +/************************** Variable Definitions *****************************/ + + +/*****************************************************************************/ +/** +* +* Set the options for the interrupt controller driver. In Cascade mode same +* Option is set to Slave controllers. +* +* @param InstancePtr is a pointer to the XIntc instance to be worked on. +* @param Options to be set. The available options are described in +* xintc.h. +* +* @return +* - XST_SUCCESS if the options were set successfully +* - XST_INVALID_PARAM if the specified option was not valid +* +* @note None. +* +****************************************************************************/ +int XIntc_SetOptions(XIntc * InstancePtr, u32 Options) +{ + XIntc_Config *CfgPtr; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Make sure option request is valid + */ + if ((Options == XIN_SVC_SGL_ISR_OPTION) || + (Options == XIN_SVC_ALL_ISRS_OPTION)) { + InstancePtr->CfgPtr->Options = Options; + /* If Cascade mode set the option for all Slaves */ + if (InstancePtr->CfgPtr->IntcType != XIN_INTC_NOCASCADE) { + int Index; + for (Index = 1; Index <= XPAR_XINTC_NUM_INSTANCES - 1; + Index++) { + CfgPtr = XIntc_LookupConfig(Index); + CfgPtr->Options = Options; + } + } + return XST_SUCCESS; + } + else { + return XST_INVALID_PARAM; + } +} + +/*****************************************************************************/ +/** +* +* Return the currently set options. +* +* @param InstancePtr is a pointer to the XIntc instance to be worked on. +* +* @return The currently set options. The options are described in xintc.h. +* +* @note None. +* +****************************************************************************/ +u32 XIntc_GetOptions(XIntc * InstancePtr) +{ + /* + * Assert the arguments + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + return InstancePtr->CfgPtr->Options; +} +/** @} */ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/intc_v3_9/src/xintc_selftest.c b/datalink814_sp/bsp/microblaze_ps/libsrc/intc_v3_9/src/xintc_selftest.c new file mode 100644 index 0000000..2dc0f49 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/intc_v3_9/src/xintc_selftest.c @@ -0,0 +1,251 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xintc_selftest.c +* @addtogroup intc_v3_9 +* @{ +* +* Contains diagnostic self-test functions for the XIntc component. This file +* requires other files of the component to be linked in also. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00b jhl  02/21/02 First release
+* 1.10c mta  03/21/07 Updated to new coding style
+* 2.00a ktn  10/20/09 Updated to use HAL Processor APIs
+* 2.04a bss  01/16/12 Removed CurrentMIE variable and reading of the
+*                     MER register to remove warnings
+* 2.06a bss  01/28/13 To support Cascade mode:
+*		      Modified XIntc_SimulateIntr API.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xintc.h" +#include "xintc_i.h" + +/************************** Constant Definitions *****************************/ + +#define XIN_TEST_MASK 1 + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + + +/************************** Variable Definitions *****************************/ + + +/*****************************************************************************/ +/** +* +* Run a self-test on the driver/device. This is a destructive test. +* +* This involves forcing interrupts into the controller and verifying that they +* are recognized and can be acknowledged. This test will not succeed if the +* interrupt controller has been started in real mode such that interrupts +* cannot be forced. +* +* @param InstancePtr is a pointer to the XIntc instance to be worked on. +* +* @return +* - XST_SUCCESS if self-test is successful. +* - XST_INTC_FAIL_SELFTEST if the Interrupt controller fails the +* self-test. It will fail the self test if the device has +* previously been started in real mode. +* +* @note None. +* +******************************************************************************/ +int XIntc_SelfTest(XIntc * InstancePtr) +{ + u32 CurrentISR; + u32 Temp; + + /* + * Assert the arguments + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + + /* + * Acknowledge all pending interrupts by reading the interrupt status + * register and writing the value to the acknowledge register + */ + Temp = XIntc_In32(InstancePtr->BaseAddress + XIN_ISR_OFFSET); + + XIntc_Out32(InstancePtr->BaseAddress + XIN_IAR_OFFSET, Temp); + + /* + * Verify that there are no interrupts by reading the interrupt status + */ + CurrentISR = XIntc_In32(InstancePtr->BaseAddress + XIN_ISR_OFFSET); + + /* + * ISR should be zero after all interrupts are acknowledged + */ + if (CurrentISR != 0) { + return XST_INTC_FAIL_SELFTEST; + } + + /* + * Set a bit in the ISR which simulates an interrupt + */ + XIntc_Out32(InstancePtr->BaseAddress + XIN_ISR_OFFSET, XIN_TEST_MASK); + + /* + * Verify that it was set + */ + CurrentISR = XIntc_In32(InstancePtr->BaseAddress + XIN_ISR_OFFSET); + + if (CurrentISR != XIN_TEST_MASK) { + return XST_INTC_FAIL_SELFTEST; + } + + /* + * Acknowledge the interrupt + */ + XIntc_Out32(InstancePtr->BaseAddress + XIN_IAR_OFFSET, XIN_TEST_MASK); + + /* + * Read back the ISR to verify that the interrupt is gone + */ + CurrentISR = XIntc_In32(InstancePtr->BaseAddress + XIN_ISR_OFFSET); + + if (CurrentISR != 0) { + return XST_INTC_FAIL_SELFTEST; + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* Allows software to simulate an interrupt in the interrupt controller. This +* function will only be successful when the interrupt controller has been +* started in simulation mode. Once it has been started in real mode, +* interrupts cannot be simulated. A simulated interrupt allows the interrupt +* controller to be tested without any device to drive an interrupt input +* signal into it. In Cascade mode writes to ISR of appropraite Slave +* controller depending on Id. +* +* @param InstancePtr is a pointer to the XIntc instance to be worked on. +* @param Id is the interrupt ID for which to simulate an interrupt. +* +* @return +* - XST_SUCCESS if successful +* - XST_FAILURE if the interrupt could not be +* simulated because the interrupt controller is or +* has previously been in real mode. +* +* @note None. +* +******************************************************************************/ +int XIntc_SimulateIntr(XIntc * InstancePtr, u8 Id) +{ + u32 Mask; + u32 MasterEnable; + XIntc_Config *CfgPtr; + int Index; + int DeviceId; + + /* + * Assert the arguments + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(Id < XPAR_INTC_MAX_NUM_INTR_INPUTS); + + + /* Get the contents of the master enable register and determine if + * hardware interrupts have already been enabled, if so, this is a write + * once bit such that simulation can't be done at this point because + * the ISR register is no longer writable by software + */ + MasterEnable = XIntc_In32(InstancePtr->BaseAddress + XIN_MER_OFFSET); + if (MasterEnable & XIN_INT_HARDWARE_ENABLE_MASK) { + return XST_FAILURE; + } + + + if (Id > 31) { + + DeviceId = Id/32; + + CfgPtr = XIntc_LookupConfig(Id/32); + Mask = XIntc_BitPosMask[Id%32]; + XIntc_Out32(CfgPtr->BaseAddress + XIN_ISR_OFFSET, Mask); + + /* Generate interrupt for 31 by writing to Interrupt Status + * register of parent controllers. Primary controller ISR + * will be written last in the loop + */ + Mask = XIntc_BitPosMask[31]; + for (Index = DeviceId - 1; Index >= 0; Index--) + { + CfgPtr = XIntc_LookupConfig(Index); + + XIntc_Out32(CfgPtr->BaseAddress + XIN_ISR_OFFSET, + Mask); + } + } + else { + /* + * The Id is used to create the appropriate mask for the + * desired bit position. + */ + Mask = XIntc_BitPosMask[Id]; + + /* + * Enable the selected interrupt source by reading the interrupt + * enable register and then modifying only the specified + * interrupt id enable + */ + XIntc_Out32(InstancePtr->BaseAddress + XIN_ISR_OFFSET, Mask); + + } + /* indicate the interrupt was successfully simulated */ + + return XST_SUCCESS; +} +/** @} */ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/Makefile b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/Makefile new file mode 100644 index 0000000..9effba9 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/Makefile @@ -0,0 +1,75 @@ +############################################################################### +# +# Copyright (C) 2012 - 2014 Xilinx, Inc. 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 +# XILINX 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. +# +# Except as contained in this notice, the name of the Xilinx shall not be used +# in advertising or otherwise to promote the sale, use or other dealings in +# this Software without prior written authorization from Xilinx. +# +############################################################################### + +# The following are defined in config.make +# LIBSOURCES - Based on if MicroBlaze support Exceptions +# LIBS - Do Build Profile Libraries +include config.make + +AS=mb-as +CC=$(CC) +AR=mb-ar +CP=cp +COMPILER_FLAGS=-O2 -c +EXTRA_COMPILER_FLAGS= +LIB=libxil.a + +CC_FLAGS = $(subst -pg, , $(COMPILER_FLAGS)) +ECC_FLAGS = $(subst -pg, , $(EXTRA_COMPILER_FLAGS)) + +RELEASEDIR=../../../lib +INCLUDEDIR=../../../include +INCLUDES=-I./. -I${INCLUDEDIR} + +OUTS = *.o +OBJECTS = $(addsuffix .o, $(basename $(wildcard *.c))) +ASSEMBLY_OBJECTS = $(addsuffix .o, $(basename $(wildcard *.S))) +INCLUDEFILES=*.h + +libs: $(LIBS) + +standalone_libs: $(LIBSOURCES) + echo "Compiling standalone"; + $(CC) $(CC_FLAGS) $(ECC_FLAGS) $(INCLUDES) $^ + $(AR) -r ${RELEASEDIR}/${LIB} ${OBJECTS} ${ASSEMBLY_OBJECTS} + +profile_libs: + $(MAKE) -C profile COMPILER_FLAGS="$(COMPILER_FLAGS)" EXTRA_COMPILER_FLAGS="$(EXTRA_COMPILER_FLAGS)" COMPILER="$(CC)" ARCHIVER="$(AR)" AS="$(AS)" libs + +include: standalone_includes profile_includes + +standalone_includes: + ${CP} ${INCLUDEFILES} ${INCLUDEDIR} + +profile_includes: + $(MAKE) -C profile COMPILER_FLAGS="$(COMPILER_FLAGS)" EXTRA_COMPILER_FLAGS="$(EXTRA_COMPILER_FLAGS)" COMPILER="$(CC)" ARCHIVER="$(AR)" AS="$(AS)" include + +clean: + rm -rf ${OBJECTS} + rm -rf ${ASSEMBLY_OBJECTS} + $(MAKE) -C profile COMPILER_FLAGS="$(COMPILER_FLAGS)" EXTRA_COMPILER_FLAGS="$(EXTRA_COMPILER_FLAGS)" COMPILER="$(CC)" ARCHIVER="$(AR)" AS="$(AS)" clean diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/_exit.c b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/_exit.c new file mode 100644 index 0000000..8cea938 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/_exit.c @@ -0,0 +1,42 @@ +/****************************************************************************** +* +* Copyright (C) 2012 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +#include +#include "xil_types.h" +void _exit (sint32 status); + +/* _exit - Simple implementation. Does not return. +*/ +void _exit (sint32 status) +{ + (void) status; + while (1) + { + ; + } +} diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/bspconfig.h b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/bspconfig.h new file mode 100644 index 0000000..dfedab2 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/bspconfig.h @@ -0,0 +1,41 @@ + +/******************************************************************* +* +* CAUTION: This file is automatically generated by HSI. +* Version: 2019.1.3 +* DO NOT EDIT. +* +* Copyright (C) 2010-2023 Xilinx, Inc. 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 +*XILINX 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. +* +*Except as contained in this notice, the name of the Xilinx shall not be used +*in advertising or otherwise to promote the sale, use or other dealings in +*this Software without prior written authorization from Xilinx. +* + +* +* Description: Configurations for Standalone BSP +* +*******************************************************************/ + +#ifndef BSPCONFIG_H /* prevent circular inclusions */ +#define BSPCONFIG_H /* by using protection macros */ + +#define MICROBLAZE_PVR_NONE + +#endif /*end of __BSPCONFIG_H_*/ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/changelog.txt b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/changelog.txt new file mode 100644 index 0000000..cdefb9f --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/changelog.txt @@ -0,0 +1,593 @@ +/***************************************************************************** + * MODIFICATION HISTORY: + * + * Ver Who Date Changes + * ----- ---- -------- --------------------------------------------------- + * 3.02a sdm 05/30/11 Added Xuint64 typedef and XUINT64_MSW/XUINT64_LSW macros + * 3.02a sdm 06/27/11 Added INST_SYNC and DATA_SYNC macros for all the CPUs + * 3.02a sdm 07/07/11 Updated ppc440 boot.S to set guarded bit for all but + * cacheable regions + * Update ppc440/xil_cache.c to use CACHEABLE_REGION_MASK + * generated by the cpu driver, for enabling caches + * 3.02a sdm 07/08/11 Updated microblaze cache flush APIs based on write-back/ + * write-thru caches + * 3.03a sdm 08/20/11 Updated the tag/data RAM latency values for L2CC + * Updated the MMU table to mark OCM in high address space + * as inner cacheable and reserved space as Invalid + * 3.03a sdm 08/20/11 Changes to support FreeRTOS + * Updated the MMU table to mark upper half of the DDR as + * non-cacheable + * Setup supervisor and abort mode stacks + * Do not initialize/enable L2CC in case of AMP + * Initialize UART1 for 9600bps in case of AMP + * 3.03a sdm 08/27/11 Setup abort and supervisor mode stacks and don't init SMC + * in case of AMP + * 3.03a sdm 09/14/11 Added code for performance monitor and L2CC event + * counters + * 3.03a sdm 11/08/11 Updated microblaze xil_cache.h file to include + * xparameters.h file for CR630532 - Xil_DCacheFlush()/ + * Xil_DCacheFlushRange() functions in standalone BSP v3_02a + * for MicroBlaze will invalidate data in the cache instead + * of flushing it for writeback caches + * 3.04a sdm 11/21/11 Updated to initialize stdio device for 115200bps, for PS7 + * 3.04a sdm 01/02/12 Updated to clear cp15 regs with unknown reset values + * Remove redundant dsb/dmb instructions in cache maintenance + * APIs + * Remove redundant dsb in mcr instruction + * 3.04a sdm 01/13/12 Updated MMU table to mark DDR memory as Shareable + * 3.05a sdm 02/02/12 Removed some of the defines as they are being generated through + * driver tcl in xparameters.h. Update the gcc/translationtable.s + * for the QSPI complete address range - DT644567 + * Removed profile directory for armcc compiler and changed + * profiling setting to false in standalone_v2_1_0.tcl file + * Deleting boot.S file after preprocessing for armcc compiler + * 3.05a asa 03/11/12 Updated the function Xil_EnableMMU in file xil_mmu.c to + * invalidate the caches before enabling back the MMU and + * D cache. + * 3.05a asa 04/15/12 Updated the function Xil_SetTlbAttributes in file + * xil_mmu.c. Now we invalidate UTLB, Branch predictor + * array, flush the D-cache before changing the attributes + * in translation table. The user need not call Xil_DisableMMU + * before calling Xil_SetTlbAttributes. + * 3.06a asa/ 06/17/12 Removed the UART initialization for Zynq. For PEEP, the UART + * sgd initialization is present. Changes for this were done in + * uart.c and xil-crt0.s. + * Made changes in xil_io.c to use volatile pointers. + * Made changes in xil_mmu.c to correct the function + * Xil_SetTlbAttributes. + * Changes are made xil-crt0.s to initialize the static + * C++ constructors. + * Changes are made in boot.s, to fix the TTBR settings, + * correct the L2 Cache Auxiliary register settings, L2 cache + * latency settings. + * 3.07a asa/ 07/16/12 Made changes in cortexa9/xtime_l.c, xtime_l.h, sleep.c + * sgd usleep.c to use global timer intstead of CP15. + * Made changes in cortexa9/gcc/translation_table.s to map + * the peripheral devices as shareable device memory. + * Made changes in cortexa9/gcc/xil-crt0.s to initialize + * the global timer. + * Made changes in cortexa9/armcc/boot.S to initialize + * the global timer. + * Made changes in cortexa9/armcc/translation_table.s to + * map the peripheral devices as shareable device memory. + * Made changes in cortexa9/gcc/boot.S to optimize the + * L2 cache settings. Changes the section properties for + * ".mmu_tbl" and ".boot" sections in cortexa9/gcc/boot.S + * and cortexa9/gcc/translation_table.S. + * Made changes in cortexa9/xil_cache.c to change the + * cache invalidation order. + * 3.07a asa 08/17/12 Made changes across files for Cortexa9 to remove + * compilation/linking issues for C++ compiler. + * Made changes in mb_interface.h to remove compilation/ + * linking issues for C++ compiler. + * Added macros for swapb and swaph microblaze instructions + * mb_interface.h + * Remove barrier usage (SYNCHRONIZE_IO) from xil_io.c + * for CortexA9. + * 3.07a asa 08/30/12 Updated for CR 675636 to provide the L2 Base Address + * 3.07a asa 08/31/12 Added xil_printf.h include + * 3.07a sgd 09/18/12 Corrected the L2 cache enable settings + * Corrected L2 cache sequence disable sequence + * 3.07a sgd 10/19/12 SMC NOR and SRAM initialization with compiler option + * 3.09a asa 01/25/13 Updated to push and pop neon registers into stack for + * irq/fiq handling. + * Relocated COUNTS_PER_SECOND from sleep.c to xtime_l.h. This + * fixes the CR #692094. + * 3.09a sgd 02/14/13 Fix for CRs 697094 (SI#687034) and 675552. + * 3.10a srt 04/18/13 Implemented ARM Erratas. + * Cortex A9 Errata - 742230, 743622, 775420, 794073 + * L2Cache PL310 Errata - 588369, 727915, 759370 + * Please refer to file 'xil_errata.h' for errata + * description. + * 3.10a asa 05/04/13 Added support for L2 cache in MicroBlaze BSP. The older + * cache APIs were corresponding to only Layer 1 cache + * memories. New APIs were now added and the existing cache + * related APIs were changed to provide a uniform interface + * to flush/invalidate/enable/disable the complete cache + * system which includes both L1 and L2 caches. The changes + * for these were done in: + * src/microblaze/xil_cache.c and src/microblaze/xil_cache.h + * files. + * Four new files were added for supporting L2 cache. They are: + * microblaze_flush_cache_ext.S-> Flushes L2 cache + * microblaze_flush_cache_ext_range.S -> Flushes a range of + * memory in L2 cache. + * microblaze_invalidate_cache_ext.S-> Invalidates L2 cache + * microblaze_invalidate_cache_ext_range -> Invalidates a + * range of memory in L2 cache. + * These changes are done to implement PR #697214. + * 3.10a asa 05/13/13 Modified cache disable APIs at src/cortexa9/xil_cache.c to + * fix the CR #706464. L2 cache disabling happens independent + * of L1 data cache disable operation. Changes are done in the + * same file in cache handling APIs to do a L2 cache sync + * (poll reg7_?cache_?sync). This fixes CR #700542. + * 3.10a asa 05/20/13 Added API/Macros for enabling and disabling nested + * interrupts for ARM. These are done to fix the CR#699680. + * 3.10a srt 05/20/13 Made changes in cache maintenance APIs to do a proper cach + * sync operation. This fixes the CR# 716781. + * 3.11a asa 09/07/13 Updated armcc specific BSP files to have proper support + * for armcc toolchain. + * Modified asm_vectors.S (gcc) and asm_vectors.s (armcc) to + * fix issues related to NEON context saving. The assembly + * routines for IRQ and FIQ handling are modified. + * Deprecated the older BSP (3.10a). + * 3.11a asa 09/22/13 Fix for CR#732704. Cache APIs are modified to avoid + * various potential issues. Made changes in the function + * Xil_SetAttributes in file xil_mmu.c. + * 3.11a asa 09/23/13 Added files xil_misc_psreset_api.c and xil_misc_psreset_api.h + * in src\cortexa9 and src\microblaze folders. + * 3.11a asa 09/28/13 Modified the cache APIs (src\cortexa9) to fix handling of + * L2 cache sync operation and to fix issues around complete + * L2 cache flush/invalidation by ways. + * 3.12a asa 10/22/13 Modified the files xpseudo_asm_rvct.c and xpseudo_asm_rvct.h + * to fix linking issues with armcc/DS-5. Modified the armcc + * makefile to fix issues. + * 3.12a asa 11/15/13 Fix for CR#754800. It fixes issues around profiling for MB. + * 4.0 hk 12/13/13 Added check for STDOUT_BASEADDRESS where outbyte is used. + * 4.0 pkp 22/01/14 Modified return addresses for interrupt handlers (DataAbortHandler + * and SWIHandler) in asm_vector.S (src\cortexa9\gcc\ and + * src\cortexa9\armcc\) to fix CR#767251 + * 4.0 pkp 24/01/14 Modified cache APIs (Xil_DCacheInvalidateRange and + * Xil_L1DCacheInvalidate) in xil_cache.c (src\cortexa9) to fix the bugs. + * Few cache lines were missed to invalidate when unaligned address + * invalidation was accommodated in Xil_DCacheInvalidateRange. + * In Xil_L1DCacheInvalidate, while invalidating all L1D cache + * stack memory (which contains return address) was invalidated. So + * stack memory is flushed first and then L1D cache is invalidated. + * This is done to fix CR #763829 + * 4.0 adk 22/02/2014 Fixed the CR:775379 removed unnecessay _t(unit32_t etc) from + * mblaze_nt_types.h file and replace uint32_t with u32 in the + * profile_hist.c to fix the above CR. + * 4.1 bss 04/14/14 Updated driver tcl to remove _interrupt_handler.o from libgloss.a + * instead of libxil.a and added prototypes for + * microblaze_invalidate_cache_ext and microblaze_flush_cache_ext in + * mb_interface.h + * 4.1 hk 04/18/14 Add sleep function. + * 4.1 asa 04/21/14 Fix for CR#764881. Added support for msrset and msrclr. Renamed + * some of the *.s files inMB BSP source to *.S. + * 4.1 asa 04/28/14 Fix for CR#772280. Made changes in file cortexa9/gcc/read.c. + * 4.1 bss 04/29/14 Modified driver tcl to use libxil.a if libgloss.a does not exist + * CR#794205 + * 4.1 asa 05/09/14 Fix for CR#798230. Made changes in cortexa9/xil_cache.c and + * common/xil_testcache.c + * Fix for CR#764881. + * 4.1 srt 06/27/14 Remove '#undef DEBUG' from src/common/xdebug.h, which allows to + * output the DEBUG logs when -DDEBUG flag is enabled in BSP. + * 4.2 pkp 06/27/14 Added support for IAR compiler in src/cortexa9/iccarm. + * Also added explanatory notes in cortexa9/xil_cache.c for CR#785243. + * 4.2 pkp 06/19/14 Asynchronous abort has been enabled into cortexa9/gcc/boot.s and + * cortexa9/armcc/boot.s. Added default exception handlers for data + * abort and prefetch abort using handlers called + * DataAbortHandler and PrefetchAbortHandler respectively in + * cortexa9/xil_exception.c to fix CR#802862. + * 4.2 pkp 06/30/14 MakeFile for cortexa9/armcc has been changed to fixes the + * issue of improper linking of translation_table.s + * 4.2 pkp 07/04/14 added weak attribute for the function in BSP which are also present + * in tool chain to avoid conflicts into some special cases + * 4.2 pkp 07/21/14 Corrected reset value of event counter in function + * Xpm_ResetEventCounters in src/cortexa9/xpm_counter.c to fix CR#796275 + * 4.2 pkp 07/21/14 Included xil_types.h file in xil_mmu.h which had contained a function + * containing type def u32 defined in xil_types.g to resolve issue of + * CR#805869 + * 4.2 pkp 08/04/14 Removed unimplemented nanosleep routine from cortexa9/usleep.c as + * it is not possible to generate timer in nanosecond due to limited + * cpu frequency + * 4.2 pkp 08/04/14 Removed PEEP board related code which contained initialization of + * uart, smc nor and sram from cortexa9/gcc/xil-crt0.s and armcc/boot.s + * and iccarm/boot.s. Also uart.c and smc.c have been removed. Also + * removed function definition of XSmc_NorInit and XSmc_NorInit from + * cortexa9/smc.h + * 4.2 bss 08/11/14 Added microblaze_flush_cache_ext_range and microblaze_invalidate_ + * cache_ext_range declarations in mb_interface.h CR#783821. + * Modified profile_mcount_mb.S to fix CR#808412. + * 4.2 pkp 08/21/14 modified makefile of iccarm for proper linking of objectfiles in + * cortexa9/iccarm to fix CR#816701 + * 4.2 pkp 09/02/14 modified translation table entries in cortexa9/gcc/translation_table.s, + * armcc/translation_table.s and iccarm/translation_table.s + * to properly defined reserved entries according to address map for + * fixing CR#820146 + * 4.2 pkp 09/11/14 modified translation table entries in cortexa9/iccarm/translation_table.s + * and cortexa9/armcc/translation_table.s to resolve compilation + * error for solving CR#822897 + * 5.0 kvn 12/9/14 Support for Zync Ultrascale Mp.Also modified code for + * MISRA-C:2012 compliance. + * 5.0 pkp 12/15/14 Added APIs to get information about the platforms running the code by + * adding src/common/xplatform_info.*s + * 5.0 pkp 16/12/14 Modified boot code to enable scu after MMU is enabled and + * removed incorrect initialization of TLB lockdown register to fix + * CR#830580 in cortexa9/gcc/boot.S & cpu_init.S, armcc/boot.S + * and iccarm/boot.s + * 5.0 pkp 25/02/15 Modified floating point flag to vfpv3 from vfpv3_d16 in BSP MakeFile + * for iccarm and armcc compiler of cortexA9 + * 5.1 pkp 05/13/15 Changed the initialization order in cortexa9/gcc/boot.S, iccarm/boot.s + * and armcc/boot.s so to first invalidate caches and TLB, enable MMU and + * caches, then enable SMP bit in ACTLR. L2Cache invalidation and enabling + * of L2Cache is done later. + * 5.1 pkp 12/05/15 Modified cortexa9/xil_cache.c to modify Xil_DCacheInvalidateRange and + * Xil_DCacheFlushRange to remove unnecessary dsb which is unnecessarily + * taking long time to fix CR#853097. L2CacheSync is added into + * Xil_L2CacheInvalidateRange API. Xil_L1DCacheInvalidate and + * Xil_L2CacheInvalidate APIs are modified to flush the complete stack + * instead of just System Stack + * 5.1 pkp 14/05/15 Modified cortexa9/gcc/Makefile to keep a correct check of a compiler + * to update ECC_FLAGS and also take the compiler and archiver as specified + * in settings instead of hardcoding it. + * 5.2 pkp 06/08/15 Modified cortexa9/gcc/translation_table.S to put a check for + * XPAR_PS7_DDR_0_S_AXI_BASEADDR to confirm if DDR is present or not and + * accordingly generate the translation table + * 5.2 pkp 23/07/15 Modified cortexa9/gcc/Makefile to keep a correct check of a compiler + * to update ECC_FLAGS to fix a bug introduced during new version creation + * of BSP. + * 5.3 pkp 10/07/15 Modified cortexa9/xil_cache.c file to change cache API so that L2 Cache + * functionalities are avoided for the OpenAMP slave application(when + * USE_AMP flag is defined for BSP) as master CPU would be utilizing L2 + * cache for its operation. Also file operations such as read, write, + * close, open are also avoided for OpenAMP support(when USE_AMP flag is + * defined for BSP) because XilOpenAMP library contains own file operation. + * The xil-crt0.S file is modified for not initializing global timer for + * OpenAMP application as it might be already in use by master CPU + * 5.3 pkp 10/09/15 Modified cortexa9/iccarm/xpseudo_asm_iccarm.h file to change function + * definition for dsb, isb and dmb to fix the compilation error when used + * kvn 16/10/15 Encapsulated assembly code into macros for R5 xil_cache file. + * 5.4 pkp 09/11/15 Modified cortexr5/gcc/boot.S to disable ACTLR.DBWR bit to avoid potential + * R5 deadlock for errata 780125 + * 5.4 pkp 09/11/15 Modified cortexa53/32bit/gcc/boot.S to enable I-Cache and D-Cache for a53 + * 32 bit BSP in the initialization + * 5.4 pkp 09/11/15 Modified cortexa9/xil_misc_psreset_api.c file to change the description + * for XOcm_Remap function + * 5.4 pkp 16/11/15 Modified microblaze/xil_misc_psreset_api.c file to change the description + * for XOcm_Remap function + * kvn 21/11/15 Added volatile keyword for ADDR varibles in Xil_Out API + * kvn 21/11/15 Changed ADDR variable type from u32 to UINTPTR. This is + * required for MISRA-C:2012 Compliance. + * 5.4 pkp 23/11/15 Added attribute definitions for Xil_SetTlbAttributes API of Cortex-A9 + * in cortexa9/xil_mmu.h + * 5.4 pkp 23/11/15 Added default undefined exception handler for Cortex-A9 + * 5.4 pkp 11/12/15 Modified common/xplatform_info.h to add #defines for silicon for + * checking the current executing platform + * 5.4 pkp 18/12/15 Modified cortexa53/32bit/gcc/xil-crt0.S and 64bit/gcc/xil-crt0.S + * to initialize global constructor for C++ applications + * 5.4 pkp 18/12/15 Modified cortexr5/gcc/xil-crt0.S to initialize global constructor for + * C++ applications + * 5.4 pkp 18/12/15 Modified cortexa53/32bit/gcc/translation_table.S and 64bit/gcc/ + * translation_table.S to update the translation table according to proper + * address map + * 5.4 pkp 18/12/15 Modified cortexar5/mpu.c to initialize the MPU according to proper + * address map + * 5.4 pkp 05/01/16 Modified cortexa53/64bit/boot.S to set the reset vector register RVBAR + * equivalent to vector table base address + * 5.4 pkp 08/01/16 Modified cortexa9/gcc/Makefile to update the extra compiler flag + * as per the toolchain update + * 5.4 pkp 12/01/16 Changed common/xplatform_info.* to add platform information support + * for Cortex-A53 32bit mode + * 5.4 pkp 28/01/16 Modified cortexa53/32bit/sleep.c and usleep.c & cortexa53/64bit/sleep.c + * and usleep.c to correct routines to avoid hardcoding the timer frequency, + * instead take it from xparameters.h to properly configure the timestamp + * clock frequency + * 5.4 asa 29/01/16 Modified microblaze/mb_interface.h to add macros that support the + * new instructions for MB address extension feature + * 5.4 kvn 30/01/16 Modified xparameters_ps.h file to add interrupt ID number for + * system monitor. + * 5.4 pkp 04/02/16 Modified cortexr5/gcc/boot.S to enable fault log for lock-step mode + * 5.4 pkp 19/02/16 Modified cortexr5/xtime_l.c to add an API XTime_StartTimer and updated + * cortexr5/xil-crt0.S to configure the TTC3 timer when present. Modified + * cortexr5/sleep.c, cortexr5/usleep.c to use TTC3 when present otherwise + * use set of assembly instructions to provide required delay to fix + * CR#913249. + * 5.4 asa 25/02/16 Made changes in xil-crt0.S for R5, A53 64 and 32 bit BSPs, to replace + * _exit with exit. We should not be directly calling _exit and should + * always use the library exit. This fixes the CR#937036. + * 5.4 pkp 25/02/16 Made change to cortexr5/gcc/boot.S to initialize the floating point + * registers, banked registers for various modes and enabled + * the cache ECC check before enabling the fault log for lock step mode + * Also modified the cortexr5/gcc/Makefile to support floating point + * registers initialization in boot code. + * 5.4 pkp 03/01/16 Updated the exit function in cortexr5/gcc/_exit.c to enable the debug + * logic in case of lock-step mode when fault log is enabled to fix + * CR#938281 + * 5.4 pkp 03/02/16 Modified cortexa9/iccarm/xpseudo_asm_iccarm.h file to include + * header file instrinsics.h which contains assembly instructions + * definitions which can be used by C + * 5.4 asa 03/02/16 Added print.c in MB BSP. Made other cosmetic changes to have uniform + * proto for all print.c across the BSPs. This patch fixes CR#938738. + * 5.4 pkp 03/09/16 Modified cortexr5/sleep.c and usleep.c to avoid disabling the + * interrupts when sleep/usleep is being executed using assembly + * instructions to fix CR#913249. + * 5.4 pkp 03/11/16 Modified cortexr5/xtime_l.c to avoid enabling overflow interrupt, + * instead modified cortexr5/sleep.c and usleep.c to poll the counter + * value and compare it with previous value to detect the overflow + * to fix CR#940209. + * 5.4 pkp 03/24/16 Modified cortexr5/boot.S to reset the dbg_lpd_reset before enabling + * the fault log to avoid intervention for lock-step mode and cortexr5/ + * _exit.c to enable the dbg_lpd_reset once the fault log is disabled + * to fix CR#947335 + * 5.5 pkp 04/11/16 Modified cortexr5/boot.S to enable comparators for non-JTAG bootmode + * in lock-step to avoid resetting the debug logic which restricts the + * access for debugger and removed enabling back of debug modules in + * cortexr5/_exit.c + * 5.5 pkp 04/13/16 Modified cortexa9/gcc/read.c to return correct number of bytes when + * read buffer is filled and removed the redundant NULL checking for + * buffer to simplify the code + * 5.5 pkp 04/13/16 Modified cortexa53/64bit/gcc/read.c and cortexa53/32bit/gcc/read.c + * to return correct number of bytes when read buffer is filled and + * removed the redundant NULL checking for buffer to simplify the code + * 5.5 pkp 04/13/16 Modified cortexr5/gcc/read.c to return correct number of bytes when + * read buffer is filled and removed the redundant NULL checking for + * buffer to simplify the code + * 5.5 pkp 04/13/16 Modified cortexa53/64bit/xpseudo_asm_gcc.h to add volatile to asm + * instruction macros to disable certain optimizations which may move + * code out of loops if optimizers believe that the code will always + * return the same result or discard asm statements if optimizers + * determine there is no need for the output variables + * 5.5 pkp 04/13/16 Modified cortexa53/64bit/xtime_l.c to add XTime_StartTimer which + * starts the timer if it is disabled and modified XTime_GetTime to + * enable the timer if it is not enabled. Also modified cortexa53/64bit/ + * sleep.c and cortexa53/64bit/usleep.c to enable the timer if it is + * disabled and read the counter value directly from register instead + * of using XTime_GetTime for optimization + * 5.5 pkp 04/13/16 Modified cortexa53/32bit/xtime_l.c to add XTime_StartTimer which + * starts the timer if it is disabled and modified XTime_GetTime to + * enable the timer if it is not enabled. Also modified cortexa53/32bit/ + * sleep.c and cortexa53/32bit/usleep.c to enable the timer if it is + * disabled and read the counter value directly from register instead + * of using XTime_GetTime for optimization + * 5.5 pkp 04/13/16 Modified cortexa53/32bit/xil_cache.c and cortexa53/64bit/xil_cache.c + * to update the Xil_DCacheInvalidate, Xil_DCacheInvalidateLine and + * Xil_DCacheInvalidateRange functions description for proper + * explaination to fix CR#949801 + * 5.5 asa 04/20/16 Added missing macros for hibernate and suspend in Microblaze BSP + * file mb_interface.h. This fixes the CR#949503. + * 5.5 asa 04/29/16 Fix for CR#951080. Updated cache APIs for HW designs where cache + * memory is not included for MicroBlaze. + * 5.5 pkp 05/06/16 Modified the cortexa9/xil_exception.h to update the macros + * Xil_EnableNestedInterrupts and Xil_DisableNestedInterrupts for fixing + * the issue of lr being corrupted to resolve CR#950468 + * 5.5 pkp 05/06/16 Modified the cortexr5/xil_exception.h to update the macros + * Xil_EnableNestedInterrupts and Xil_DisableNestedInterrupts for fixing + * the issue of lr being corrupted to resolve CR#950468 + * 6.0 kvn 05/31/16 Make Xil_AsserWait a global variable + * 6.0 pkp 06/27/16 Updated cortexr5/mpu.c to move the code related to Init_MPU to .boot + * section since it is part of boot process to fix CR#949555 + * hk 07/12/16 Correct masks for IOU SLCR GEM registers + * 6.0 pkp 07/25/16 Program the counter frequency in boot code for CortexA53 + * 6.0 asa 08/03/16 Updated sleep_common function in microblaze_sleep.c to improve the + * the accuracy of MB sleep functionality. This fixes the CR#954191. + * 6.0 mus 08/03/16 Restructured the BSP to avoid code duplication across all BSPs. + * Source code directories specific to ARM processor's are moved to src/arm + * directory(i.e. src/cortexa53,src/cortexa9 and src/cortexr5 moved to src/arm/cortexa53, + * src/arm/cortexa9 and src/arm/cortexr5 respectively).Files xil_printf.c,xil_printf.h, + * print.c,xil_io.c and xil_io.h are consolidated across all BSPs into common file each and + * consolidated files are kept at src/common directory.Files putnum.c,vectors.c,vectors.h, + * xil_exception.c and xil_exception.h are consolidated across all ARM BSPs + * into common file each and consolidated files are kept at src/arm/common directory. + * GCC source files related to file operations are consolidated and kept + * at src/arm/common/gcc directory. + * All io interfacing functions (i.e. All variants of xil_out, xil_in ) + * are made as static inline and implementation is kept in consolidated common/xil_io.h, + * xil_io.h must be included as a header file to access io interfacing functions. + * Added undefined exception handler for A53 32 bit and R5 processor + * 6.0 mus 08/11/16 Updated xtime_l.c in R5 BSP to remove implementation of XTime_SetTime API, since + * TTC counter value register is read only. + * 6.0 asa 08/15/16 Modified the signatures for functions sleep and usleep. This fixes + * the CR#956899. + * 6.0 mus 08/18/16 Defined ARMA53_32 flag in cortexa53/32bit/xparameters_ps.h and ARMR5 flag + * in cortexr5/xparameters_ps.h + * 6.0 mus 08/18/16 Added support for the the Zynq 7000s devices + * 6.0 mus 08/18/16 Removed unused variables from xil_printf.c and xplatform_info.c + * 6.0 mus 08/19/16 Modified xil_io.h to remove __LITTLE_ENDIAN__ flag check for all ARM processors + * 6.1 mus 11/03/16 Added APIs handle_stdin_parameter and handle_stdout_parameter in standalone tcl. + * ::hsi::utils::handle_stdin and ::hsi::utils::handle_stdout are taken as a base for + * these APIs and modifications are done on top of it to handle stdout/stdin + * parameters for design which doesnt have UART.It fixes CR#953681 + * 6.1 nsk 11/07/16 Added two new files xil_mem.c and xil_mem.h for xil_memcpy + * 6.2 pkp 12/14/16 Updated cortexa53/64bit/translation_table.S for upper ps DDR. The 0x800000000 - + * 0xFFFFFFFFF range is marked normal memory for the DDR size defined in hdf + * and rest of the memory in that 32GB region is marked as reserved to avoid + * any speculative access + * 6.2 pkp 12/23/16 Added support for floating point operation to Cortex-A53 64bit mode. It modified + * asm_vectors.S to implement lazy floating point context saving i.e. floating point + * access is enabled if there is any floating point operation, it is disabled by + * default. Also FPU is initally disabled for IRQ and none of the floating point + * registers are saved during normal context saving. If IRQ handler does not require + * floating point operation, the floating point registers are untouched and no need + * for saving/restoring. If IRQ handler uses any floating point operation, then floating + * point registers are saved and FPU is enabled for IRQ handler. Then floating point + * registers are restored back after servicing IRQ during normal context restoring. + * 6.2 mus 01/01/17 Updated makefiles of R5 and a53 64 bit/32 bit processors to fix error in clean + * target.It fixes the CR#966900 + * 6.2 pkp 01/22/17 Added support for EL1 non-secure execution and Hypervisor Baremetal for Cortex-A53 + * 64bit Mode. If Hypervisor_guest is selected as true in BSP settings, BSP will be built + * for EL1 Non-secure, else BSP will be built for EL3. By default hypervisor_guest is + * as false i.e. default bsp is EL3. + * 6.2 pkp 01/24/17 Updated cortexa53/64bit/boot.S to clear FPUStatus variable to make sure that it + * contains initial status of FPU i.e. disabled. In case of a warm restart execution + * when bss sections are not cleared, it may contain previously updated value which + * does not hold true once processor resumes. This fixes CR#966826. + * 6.2 asa 01/31/17 The existing Xil_DCacheDisable API first flushes the + * D caches and then disables it. The problem with that is, + * potentially there will be a small window after the cache + * flush operation and before the we disable D caches where + * we might have valid data in cache lines. In such a + * scenario disabling the D cache can lead to unknown behavior. + * The ideal solution to this is to use assembly code for + * the complete API and avoid any memory accesses. But with + * that we will end up having a huge amount on assembly code + * which is not maintainable. Changes are done to use a mix + * of assembly and C code. All local variables are put in + * registers. Also function calls are avoided in the API to + * avoid using stack memory. + * 6.2 mus 02/13/17 A53 CPU cache system can pre-fetch catch lines.So there are + * scenarios when an invalidated cache line can get pre fetched to cache. + * If that happens, the coherency between cache and memory is lost + * resulting in lost data. To avoid this kind of issue either + * user has to use dsb() or disable pre-fetching for L1 cache + * or else reduce maximum number of outstanding data prefetches allowed. + * Using dsb() while comparing data costing more performance compared to + * disabling pre-fetching/reducing maximum number of outstanding data + * prefetches for L1 Cache.The new api Xil_ConfigureL1Prefetch is added + * to disable pre-fetching/configure maximum number of outstanding data + * prefetches allowed in L1 cache system.This fixes CR#967864. + * 6.2 pkp 02/16/17 Added xil_smc.c file to provide a C wrapper for smc calling which can be + * used by cortex-A53 64bit EL1 Non-secure application. + * 6.2 kvn 03/03/17 Added support thumb mode + * 6.2 mus 03/13/17 Fixed MISRA C mandatory standard violations in ARM cortexr5 and cortexa53 BSP. + * It fixes CR#970543 + * 6.2 asa 03/16/17 Fix for CR#970859. For Mcroblaze BSP, when we enable intrusive + * profiling we see a crash. That is because the the tcl uses invalid + * HSI command. This change fixes it. + * 6.2 mus 03/22/17 Updated standalone tcl to generate xparameter XPAR_FPD_IS_CACHE_COHERENT, if + * any FPD peripheral is configured to use CCI.It fixes CR#972638 + * 6.3 mus 03/20/17 Updated cortex-r5 BSP, to add hard floating point support. + * 6.3 mus 04/17/17 Updated Cortex-a53 32 bit BSP boot code to fix bug in + * the HW coherency enablement. It fixes the CR#973287 + * 6.3 mus 04/20/17 Updated Cortex-A53 64 bit BSP boot code, to remove redundant write to the + * L2CTLR_EL1 register. It fixes the CR#974698 + * 6.4 mus 06/08/17 Updated arm/common/xil_exception.c to fix warnings in C level exception handlers + * of ARM 32 bit processor's. + * 6.4 mus 06/14/17 Updated cortexa53/64bit/gcc/asm_vectors.S to fix bug in IRQInterruptHandler code + * snippet, which checks for the FPEN bit of CPACR_EL1 register. + * 6.4 ms 05/23/17 Added PSU_PMU macro in xplatform_info.c, xparameters.h to support + * XGetPSVersion_Info function for PMUFW. + * ms 06/13/17 Added PSU_PMU macro in xplatform_info.c to support XGetPlatform_Info + * function for PMUFW. + * 6.4 mus 07/05/17 Updated Xil_In32BE function in xil_io.h to fix bug.It fixes CR#979740. + * 6.4 mus 07/25/17 Updated a53 32 bit boot code and vectors to support hard floating point + * operations.Now,VFP is being enabled in FPEXC register, through boot code + * and FPU registers are being saved/restored when irq/fiq vector is invoked. + * 6.4 adk 08/01/17 Updated standalone tcl to generate xparameter XPAR_PL_IS_CACHE_COHERENT, + * if h/w design configured with HPC port. + * 6.4 mus 08/10/17 Updated a53 64 bit translation table to mark memory as a outer shareable for + * EL1 NS execution. This change has been done to support CCI enabled IP's. + * 6.4 mus 08/11/17 Updated a53 64 bit boot code to implement ARM erratum 855873.This fixes + * CR#982209. + * 6.4 asa 08/16/17 Made several changes in the R5 MPU handling logic. Added new APIs to + * make RPU MPU handling user-friendly. This also fixes the CR-981028. + * 6.4 mus 08/17/17 Updated XGet_Zynq_UltraMp_Platform_info and XGetPSVersion_Info APIs to read + * version register through SMC call, over EL1 NS mode. This change has been done to + * support these APIs over EL1 NS mode. + * 6.5 mus 10/20/17 Updated standalone.tcl to fix bug in mb_can_handle_exceptions_in_delay_slots proc, + * it fixes CR#987464. + * 6.6 mus 12/07/17 Updated cortexa9/xil_errata.h and cortexa9/xil_cache.c to remove Errata 753970. + * It fixes CR#989132. + * srm 10/18/17 Updated all the sleep routines in a9,a53,R5,microblaze. Now the sleep routines + * will use the timer specified by the user to provide delay. A9 and A53 can use + * Global timer or TTC. R5 can use TTC or the machine cycles. Microblaze can use + * machine cycles or Axi timer. Updated standalone.tcl and standalone.mld files + * to support the sleep configuration Added new API's for the Axi timer in + * microblaze and TTC in ARM. Added two new files, xil_sleeptimer.c and + * xil_sleeptimer.h in ARM for the common sleep routines and 1 new file, + * xil_sleepcommon.c in Standalone-common for sleep/usleep API's. + * 6.6 hk 12/15/17 Export platform macros to bspconfig.h based on the processor. + * 6.6 asa 1/16/18 Ensure C stack information for A9 are flushed out from L1 D cache + * or L2 cache only when the respective caches are enabled. This fixes CR-922023. + * 6.6 mus 01/19/18 Updated asm_vectors.S and boot.S in Cortexa53 64 bit BSP, to add isb + * after writing to cpacr_el1/cptr_el3 registers. It would ensure + * disabling/enabling of floating-point unit, before any subsequent + * instruction. + * 6.6 hk 12/15/17 Export platform macros to xparameters.h based on the processor. + * 6.6 asa 1/16/18 Ensure C stack information for A9 are flushed out from L1 D cache + * or L2 cache only when the respective caches are enabled.This fixes CR-922023. + * + * 6.6 mus 01/19/18 Updated asm_vectors.S and boot.S in Cortexa53 64 bit BSP, to add isb + * after writing to cpacr_el1/cptr_el3 registers. It would ensure + * disabling/enabling of floating-point unit, before any subsequent + * instruction. + * 6.6 mus 01/30/18 Updated hypervisor enabled Cortexa53 64 bit BSP, to add xen PV console + * support. Now, xil_printf would use PV console instead of UART in case of + * hypervisor enabled BSP. + * 6.6 mus 02/02/18 Updated get_connected_if proc in standalone tcl to detect the HPC port + * configured with smart interconnect.It fixes CR#990318. + * 6.6 srm 02/10/18 Updated csu_wdt interrupt to the correct value. Fixes CR#992229 + * 6.6 asa 02/12/18 Fix for heap handling for ARM platforms. CR#993932. + * 6.6 mus 02/19/18 Updated standalone.tcl to fix bug in handle_profile_opbtimer proc, + * CR#995014. + * 6.6 mus 02/23/18 Presently Cortex R5 BSP boot code is disabling the debug logic in + * non-JTAG boot mode, when processor is in lockstep configuration. + * This behavior is restricting application debugging in non-JTAG boot + * mode. To get rid of this restriction, added new mld parameter + * "lockstep_mode_debug", to enable/disable debug logic from BSP + * settings. Now, debug logic can be enabled through BSP settings, + * by modifying value of parameter "lockstep_mode_debug" as "true". + * It fixes CR#993896. + * 6.6.mus 02/27/18 Updated Xil_DCacheInvalidateRange and + * Xil_ICacheInvalidateRange APIs in Cortexa53 64 bit BSP, to fix bug + * in handling upper DDR addresses.It fixes CR#995581. + * 6.6 mus 03/12/18 Updated makefile of Cortexa53 32bit BSP to add includes_ps directory + * in the list of include paths. This change allows applications/BSP + * files to include .h files in include_ps directory. + * 6.6 mus 03/16/18 By default CPUACTLR_EL1 is accessible only from EL3, it + * results into abort if accessed from EL1 non secure privilege + * level. Updated Xil_ConfigureL1Prefetch function in Cortexa53 64 bit BSP + * to avoid CPUACTLR_EL1 access from privile levels other than EL3. + * 6.6 mus 03/16/18 Updated hypervisor enabled BSP to use PV console, based on the + * XEN_USE_PV_CONSOLE flag. By deafault hypervisor enabled BSP would + * use UART console, PV console can be enabled by appending + * "-DXEN_USE_PV_CONSOLE" to the BSP extra compiler flags. + * 6.7 asa 04/26/18 Added API Xil_GetExceptionRegisterHandler for obtaining information + * on an already registered exception vector. + * 6.7 asa 05/18/18 Fixed bugss in the API Xil_GetExceptionRegisterHandler. + * 6.8 mus 04/27/18 Removed __ARM_NEON__ flag definition. Now, saving/restoring of of HW + * floating point register would be done through newly introduced flag + * FPU_HARD_FLOAT_ABI_ENABLED. This new flag will be configured based on + * the -mfpu-abi option in extra compiler flags.. This change has + * been done to avoid saving/restoring of HW floating point registers, + * when BSP is not compiled with HW floating point configuration. + * 6.8 aru 06/15/18 Removed unused variable in xil_cache.c for A53-32. It + * fixes CR1005118. + * 6.8 aru 07/02/18 Returned the pointer instead of address of that pointer in xil_mpu.c + * for R5 processor.It Fixes CR#1005119. + * 6.8 mus 07/12/18 Updated Cortexa9 translation table to mark DDR memory as inner cacheable, + * if BSP is built with the USE_AMP flag. It fixes CR#1006745. + * + * 6.8 aru 07/04/18 Optimized the code to use a loop and to remove redundant code + * in Xil_DCacheFlush() and Xil_DCacheInvalidate() + * of xil_cache.c for A53-32. + * 6.8 aru 07/26/18 added support in xil_printf.c to print u64 variabbles + * correctly in 32 bit processor.It fixes CR#1007207. + * 6.8 aru 09/03/18 Optimized the code to use a single function and removed + * code redundancy in xil_printf.c . It Fixes CR#1009654. + * 6.8 aru 09/06/18 Removed the compiler warnings for ARMCC toolchain. + * It fixes CR#1008309. + * 6.8 mus 09/20/18 Updated CortexR5 boot code to initialize CortexR5 core with LOVEC + * on reset. It fixes CR#1010656. + * 6.8 mus 10/04/18 Updated microblaze sleep functinality to execute default method of + * sleep implementation, incase of FreeRTOS BSP. + * 6.8 mus 10/25/18 Updated assembly code for cache APIs and inline assemby macros to + * to support 64 bit addresses. + * 6.8 asa 10/11/18 Updated the A53 32 bit cache APIs for Xil_DCacheFlush and + * Xil_DCacheInvalidate to fix various issues. These issues were not + * present in the previous releases but got introduced as part of + * optimization patches that got applied for 6.8 BSP version. These + * changes fix the CR#1016012. + * 7.0 rp 10/25/18 Added XST_NO_ACCESS status macros for generic access error. + * 7.0 mus 02/01/19 Added support for Versal. Cortea53 BSP will be re-used by Cortexa72, + * re-named cortexa53 directory as ARMv8, since files are generic for + * ARMv8 based processors. Created "platform" directory to place + * SoC based files. + * 7.0 mus 02/05/19 Updated Xil_MemCpy API to copy two bytes at a time from source to + * destination if byte count is <= 2. + * 7.0 mus 02/28/19 Added armclang complier support to the Cortexa53 64 bit BSP. + * 7.0 mus 04/08/19 Fix microblaze_disable_dcache for 64 bit microblaze + * 7.0 mus 04/26/19 Added frequently used functions in common area in xil_utils.c, + * so that other modules can make use of it. + *****************************************************************************************/ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/config.make b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/config.make new file mode 100644 index 0000000..7803643 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/config.make @@ -0,0 +1,3 @@ +LIBSOURCES = *.c *.S +PROFILE_ARCH_OBJS = profile_mcount_mb.o +LIBS = standalone_libs diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/errno.c b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/errno.c new file mode 100644 index 0000000..3d6fb20 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/errno.c @@ -0,0 +1,14 @@ +/* The errno variable is stored in the reentrancy structure. This + function returns its address for use by the macro errno defined in + errno.h. */ + +#include +#include +#include "xil_types.h" +sint32 * __errno (void); + +sint32 * +__errno (void) +{ + return &_REENT->_errno; +} diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/fcntl.c b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/fcntl.c new file mode 100644 index 0000000..257cee5 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/fcntl.c @@ -0,0 +1,15 @@ +#include +#include "xil_types.h" +sint32 fcntl (sint32 fd, sint32 cmd, sint32 arg); + +/* + * fcntl -- Manipulate a file descriptor. + * We don't have a filesystem, so we do nothing. + */ +sint32 fcntl (sint32 fd, sint32 cmd, sint32 arg) +{ + (void) fd; + (void) cmd; + (void) arg; + return 0; +} diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/fsl.h b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/fsl.h new file mode 100644 index 0000000..8291414 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/fsl.h @@ -0,0 +1,113 @@ +#ifndef FSL_H +#define FSL_H +/*****************************************************************************/ +/** +* +* @file fsl.h +* +* @addtogroup microblaze_fsl_macro MicroBlaze Processor FSL Macros +* +* Microblaze BSP includes macros to provide convenient access to accelerators +* connected to the MicroBlaze Fast Simplex Link (FSL) Interfaces.To use these functions, +* include the header file fsl.h in your source code +* +* @{ +* +******************************************************************************/ +#include "mb_interface.h" /* Legacy reasons. We just have to include this guy who defines the FSL stuff */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Extended FSL macros. These now replace all of the previous FSL macros */ +#define FSL_DEFAULT +#define FSL_NONBLOCKING n +#define FSL_EXCEPTION e +#define FSL_CONTROL c +#define FSL_ATOMIC a + +#define FSL_NONBLOCKING_EXCEPTION ne +#define FSL_NONBLOCKING_CONTROL nc +#define FSL_NONBLOCKING_ATOMIC na +#define FSL_EXCEPTION_CONTROL ec +#define FSL_EXCEPTION_ATOMIC ea +#define FSL_CONTROL_ATOMIC ca + +#define FSL_NONBLOCKING_EXCEPTION_CONTROL nec +#define FSL_NONBLOCKING_EXCEPTION_ATOMIC nea +#define FSL_NONBLOCKING_CONTROL_ATOMIC nca +#define FSL_EXCEPTION_CONTROL_ATOMIC eca + +#define FSL_NONBLOCKING_EXCEPTION_CONTROL_ATOMIC neca + +/** +Performs a get function on an input FSL of the MicroBlaze processor +@param val variable to sink data from get function +@param id literal in the range of 0 to 7 (0 to 15 for MicroBlaze v7.00.a and later) +@param flags valid FSL macro flags +*/ +#define getfslx(val, id, flags) asm volatile (stringify(flags) "get\t%0,rfsl" stringify(id) : "=d" (val)) + +/** +Performs a put function on an input FSL of the MicroBlaze processor +@param val variable to source data to put function +@param id literal in the range of 0 to 7 (0 to 15 for MicroBlaze v7.00.a and later) +@param flags valid FSL macro flags +*/ +#define putfslx(val, id, flags) asm volatile (stringify(flags) "put\t%0,rfsl" stringify(id) :: "d" (val)) + +/** +Performs a test get function on an input FSL of the MicroBlaze processor +@param val variable to sink data from get function +@param id literal in the range of 0 to 7 (0 to 15 for MicroBlaze v7.00.a and later) +@param flags valid FSL macro flags +*/ +#define tgetfslx(val, id, flags) asm volatile ("t" stringify(flags) "get\t%0,rfsl" stringify(id) : "=d" (val)) + +/** +Performs a put function on an input FSL of the MicroBlaze processor +@param id FSL identifier +@param flags valid FSL macro flags +*/ +#define tputfslx(id, flags) asm volatile ("t" stringify(flags) "put\trfsl" stringify(id)) + +/** +Performs a getd function on an input FSL of the MicroBlaze processor +@param val variable to sink data from getd function +@param var literal in the range of 0 to 7 (0 to 15 for MicroBlaze v7.00.a and later) +@param flags valid FSL macro flags +*/ +#define getdfslx(val, var, flags) asm volatile (stringify(flags) "getd\t%0,%1" : "=d" (val) : "d" (var)) + +/** +Performs a putd function on an input FSL of the MicroBlaze processor +@param val variable to source data to putd function +@param var literal in the range of 0 to 7 (0 to 15 for MicroBlaze v7.00.a and later) +@param flags valid FSL macro flags +*/ +#define putdfslx(val, var, flags) asm volatile (stringify(flags) "putd\t%0,%1" :: "d" (val), "d" (var)) + +/** +Performs a test getd function on an input FSL of the MicroBlaze processor; +@param val variable to sink data from getd function +@param var literal in the range of 0 to 7 (0 to 15 for MicroBlaze v7.00.a and later) +@param flags valid FSL macro flags +*/ +#define tgetdfslx(val, var, flags) asm volatile ("t" stringify(flags) "getd\t%0,%1" : "=d" (val) : "d" (var)) + +/** +Performs a put function on an input FSL of the MicroBlaze processor +@param var FSL identifier +@param flags valid FSL macro flags +*/ +#define tputdfslx(var, flags) asm volatile ("t" stringify(flags) "putd\t%0" :: "d" (var)) + + +#ifdef __cplusplus +} +#endif +#endif /* FSL_H */ +/** +* @} End of "addtogroup microblaze_fsl_macro". +*/ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/hw_exception_handler.S b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/hw_exception_handler.S new file mode 100644 index 0000000..9b229a1 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/hw_exception_handler.S @@ -0,0 +1,672 @@ +/****************************************************************************** +* +* Copyright (C) 2004 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************** + * Microblaze HW Exception Handler + * - Non self-modifying exception handler for the following exception conditions + * - Unalignment + * - Instruction bus error + * - Data bus error + * - Illegal instruction opcode + * - Divide-by-zero + * - Stack protection violation + *******************************************************************************/ + +#include "microblaze_exceptions_g.h" +#include "xparameters.h" +#include "microblaze_instructions.h" + +/* 64-bit definitions */ +#if defined (__arch64__) +#define INTPTR_DATAITEM .quad +#define REGSIZE 8 +#define DATAALIGN 4 +#else +#define INTPTR_DATAITEM .long +#define REGSIZE 4 +#define DATAALIGN 2 +#endif /* 64-bit definitions */ + +/* Helpful Macros */ +#define EX_HANDLER_STACK_SIZ (REGSIZE*21) +#define RMSR_OFFSET (20 * REGSIZE) +#define R17_OFFSET (0) +#define REG_OFFSET(regnum) (REGSIZE * (regnum + 1)) +#define NUM_TO_REG(num) r ## num + +#define R3_TO_STACK(regnum) SI r3, r1, REG_OFFSET(regnum) +#define R3_FROM_STACK(regnum) LI r3, r1, REG_OFFSET(regnum) + +#define PUSH_REG(regnum) SI NUM_TO_REG(regnum), r1, REG_OFFSET(regnum) +#define POP_REG(regnum) LI NUM_TO_REG(regnum), r1, REG_OFFSET(regnum) + +/* Uses r5 */ +#define PUSH_MSR \ + mfs r5, rmsr; \ + swi r5, r1, RMSR_OFFSET; + +#define PUSH_MSR_AND_ENABLE_EXC \ + mfs r5, rmsr; \ + swi r5, r1, RMSR_OFFSET; \ + ori r5, r5, 0x100; /* Turn ON the EE bit*/ \ + mts rmsr, r5; + +/* Uses r5 */ +#define POP_MSR \ + lwi r5, r1, RMSR_OFFSET; \ + mts rmsr, r5; + +/* Push r17 */ +#define PUSH_R17 SI r17, r1, R17_OFFSET +/* Pop r17 */ +#define POP_R17 LI r17, r1, R17_OFFSET + +#define LWREG_NOP \ + BRI ex_handler_unhandled; \ + nop; + +#define SWREG_NOP \ + BRI ex_handler_unhandled; \ + nop; + +/* r3 is the source */ +#define R3_TO_LWREG_V(regnum) \ + R3_TO_STACK (regnum); \ + BRI ex_handler_done; + +/* r3 is the source */ +#define R3_TO_LWREG(regnum) \ + OR NUM_TO_REG (regnum), r0, r3; \ + BRI ex_handler_done; + +/* r3 is the target */ +#define SWREG_TO_R3_V(regnum) \ + R3_FROM_STACK (regnum); \ + BRI ex_sw_tail; + +/* r3 is the target */ +#define SWREG_TO_R3(regnum) \ + OR r3, r0, NUM_TO_REG (regnum); \ + BRI ex_sw_tail; + +/* regnum is the source */ +#define FP_EX_OPB_SAVE(regnum) \ + SI NUM_TO_REG (regnum), r0, mb_fpex_op_b; \ + nop; \ + BRI handle_fp_ex_opa; + +/* regnum is the source */ +#define FP_EX_OPB_SAVE_V(regnum) \ + R3_FROM_STACK (regnum); \ + SI r3, r0, mb_fpex_op_b; \ + BRI handle_fp_ex_opa; + +/* regnum is the source */ +#define FP_EX_OPA_SAVE(regnum) \ + SI NUM_TO_REG (regnum), r0, mb_fpex_op_a; \ + nop; \ + BRI handle_fp_ex_done; + +/* regnum is the source */ +#define FP_EX_OPA_SAVE_V(regnum) \ + R3_FROM_STACK (regnum); \ + SI r3, r0, mb_fpex_op_a; \ + BRI handle_fp_ex_done; + +#define FP_EX_UNHANDLED \ + BRI fp_ex_unhandled; \ + nop; \ + nop; + +/* ESR masks */ +#define ESR_EXC_MASK 0x0000001F +#define ESR_REG_MASK 0x000003E0 +#define ESR_LW_SW_MASK 0x00000400 +#define ESR_WORD_MASK 0x00000800 +#define ESR_DS_MASK 0x00001000 + +/* Extern declarations */ +.extern XNullHandler + + +#ifdef MICROBLAZE_EXCEPTIONS_ENABLED /* If exceptions are enabled in the processor */ + +/* + * hw_exception_handler - Handler for unaligned exceptions + * Exception handler notes: + * - Does not handle exceptions other than unaligned exceptions + * - Does not handle exceptions during load into r17, r1, r0. + * - Does not handle exceptions during store from r17 (cannot be done) and r1 (slows down common case) + * + * Relevant register structures + * + * EAR - |----|----|----|----|----|----|----|----| + * - < ## 32 or 64 bit faulting address ## > + * + * ESR - |----|----|----|----|----| - | - |-----|-----| + * - W S REG EXC + * + * + * STACK FRAME STRUCTURE + * --------------------- + * + * +-------------+ + 0 + * | r17 | + * +-------------+ + 4 (32-bit) + 8 (64-bit) + * | Args for | + * | next func | + * +-------------+ + 8 (32-bit) + 16 (64-bit) + * | r1 | + * | . | + * | . | + * | . | + * | . | + * | r18 | + * +-------------+ + 80 (32-bit) + 160 (64-bit) + * | MSR | + * +-------------+ + 84 (32-bit) + 168 (64-bit) + * | . | + * | . | + */ + + +.global _hw_exception_handler +.section .text +.align 2 +.ent _hw_exception_handler +.type _hw_exception_handler, @function +_hw_exception_handler: + +#if defined(XPAR_MICROBLAZE_USE_STACK_PROTECTION) && (XPAR_MICROBLAZE_USE_STACK_PROTECTION == 1) + /* Immediately halt for stack protection violation exception without using any stack */ + SI r3, r0, mb_sp_save_r3; /* Save temporary register */ + mfs r3, resr; /* Extract ESR[DS] */ + andi r3, r3, ESR_EXC_MASK; + xori r3, r3, 0x7; /* Check for stack protection violation */ + BNEI r3, ex_handler_not_sp_violation; +ex_handler_sp_violation: + bri 0; /* Halt here if stack protection violation */ +ex_handler_not_sp_violation: + LI r3, r0, mb_sp_save_r3; /* Restore temporary register */ +#endif /* defined(XPAR_MICROBLAZE_USE_STACK_PROTECTION) && (XPAR_MICROBLAZE_USE_STACK_PROTECTION == 1) */ + + ADDIK r1, r1, -(EX_HANDLER_STACK_SIZ); /* Create stack frame */ + PUSH_REG(3); + PUSH_REG(4); + PUSH_REG(5); + PUSH_REG(6); +#ifdef MICROBLAZE_CAN_HANDLE_EXCEPTIONS_IN_DELAY_SLOTS + mfs r6, resr; + andi r6, r6, ESR_DS_MASK; + BEQI r6, ex_handler_no_ds; + mfs r17, rbtr; +ex_handler_no_ds: +#endif + PUSH_R17; + PUSH_MSR_AND_ENABLE_EXC; /* Exceptions enabled here. This will allow nested exceptions */ + + mfs r3, resr; + andi r5, r3, ESR_EXC_MASK; /* Extract ESR[EXC] */ +#ifndef NO_UNALIGNED_EXCEPTIONS + xori r6, r5, 1; /* 00001 = Unaligned Exception */ + BNEI r6, handle_ex_regular; + + ADDIK r4, r0, MB_ExceptionVectorTable; /* Check if user has registered an unaligned exception handler */ + LI r4, r4, 8; + ADDIK r6, r0, XNullHandler; /* If exceptionvectortable entry is still XNullHandler, use */ + XOR r6, r4, r6; /* the default exception handler */ + BEQI r6, handle_unaligned_ex ; + +handle_ex_regular: +#endif /* ! NO_UNALIGNED_EXCEPTIONS */ + +#if defined (MICROBLAZE_FP_EXCEPTION_ENABLED) && defined (MICROBLAZE_FP_EXCEPTION_DECODE) + xori r6, r5, 6; /* 00110 = FPU exception */ + BEQI r6, handle_fp_ex; /* Go and decode the FP exception */ +#endif /* defined (MICROBLAZE_FP_EXCEPTION_ENABLED) && defined (MICROBLAZE_FP_EXCEPTION_DECODE) */ + +handle_other_ex: /* Handle Other exceptions here */ + ori r6, r0, 20; + cmp r6, r5, r6; /* >= 20 are exceptions we do not handle. */ + BLEI r6, ex_handler_unhandled; + + ori r6, r0, 7; + cmp r6, r5, r6; /* Convert MMU exception indices into an ordinal of 7 */ + BGTI r6, handle_other_ex_tail; + ori r5, r0, 0x7; + +handle_other_ex_tail: + PUSH_REG(7); /* Save other volatiles before we make procedure calls below */ + PUSH_REG(8); + PUSH_REG(9); + PUSH_REG(10); + PUSH_REG(11); + PUSH_REG(12); + PUSH_REG(15); + PUSH_REG(18); + + ADDIK r4, r0, MB_ExceptionVectorTable; /* Load the Exception vector table base address */ + ADDK r7, r5, r5; /* Calculate exception vector offset = r5 * 8 (32-bit) */ + ADDK r7, r7, r7; + ADDK r7, r7, r7; +#if defined (__arch64__) + ADDK r7, r7, r7; /* or r5 * 16 (64-bit) */ +#endif + ADDK r7, r7, r4; /* Get pointer to exception vector */ + LI r5, r7, REGSIZE; /* Load argument to exception handler from table */ + LOAD r7, r7, r0; /* Load vector itself here */ + + brald r15, r7; /* Branch to handler */ + nop; + + POP_REG(7); /* Restore other volatiles */ + POP_REG(8); + POP_REG(9); + POP_REG(10); + POP_REG(11); + POP_REG(12); + POP_REG(15); + POP_REG(18); + + BRI ex_handler_done; /* Complete exception handling */ + +#ifndef NO_UNALIGNED_EXCEPTIONS +handle_unaligned_ex: + andi r6, r3, ESR_REG_MASK; /* Mask and extract the register operand */ + srl r6, r6; /* r6 >> 5 */ + srl r6, r6; + srl r6, r6; + srl r6, r6; + srl r6, r6; + sbi r6, r0, ex_reg_op; /* Store the register operand in a temporary location */ + mfs r4, rear; + andi r6, r3, ESR_LW_SW_MASK; /* Extract ESR[S] */ + BNEI r6, ex_sw; +ex_lw: + andi r6, r3, ESR_WORD_MASK; /* Extract ESR[W] */ + BEQI r6, ex_lhw; + lbui r5, r4, 0; /* Exception address in r4 */ + sbi r5, r0, ex_tmp_data_loc_0; /* Load a word, byte-by-byte from destination address and save it in tmp space */ + lbui r5, r4, 1; + sbi r5, r0, ex_tmp_data_loc_1; + lbui r5, r4, 2; + sbi r5, r0, ex_tmp_data_loc_2; + lbui r5, r4, 3; + sbi r5, r0, ex_tmp_data_loc_3; + lwi r3, r0, ex_tmp_data_loc_0; /* Get the destination register value into r3 */ + BRI ex_lw_tail; +ex_lhw: + lbui r5, r4, 0; /* Exception address in r4 */ + sbi r5, r0, ex_tmp_data_loc_0; /* Load a half-word, byte-by-byte from destination address and save it in tmp space */ + lbui r5, r4, 1; + sbi r5, r0, ex_tmp_data_loc_1; + lhui r3, r0, ex_tmp_data_loc_0; /* Get the destination register value into r3 */ +ex_lw_tail: + lbui r5, r0, ex_reg_op; /* Get the destination register number into r5 */ + ADDIK r6, r0, lw_table; /* Form load_word jump table offset (lw_table + (8 * regnum)) */ + ADDK r5, r5, r5; + ADDK r5, r5, r5; + ADDK r5, r5, r5; + ADDK r5, r5, r6; + bra r5; +ex_lw_end: /* Exception handling of load word, ends */ +ex_sw: + lbui r5, r0, ex_reg_op; /* Get the destination register number into r5 */ + ADDIK r6, r0, sw_table; /* Form store_word jump table offset (sw_table + (8 * regnum)) */ + ADDK r5, r5, r5; + ADDK r5, r5, r5; + ADDK r5, r5, r5; + ADDK r5, r5, r6; + bra r5; +ex_sw_tail: + mfs r6, resr; + andi r6, r6, ESR_WORD_MASK; /* Extract ESR[W] */ + BEQI r6, ex_shw; + swi r3, r0, ex_tmp_data_loc_0; + lbui r3, r0, ex_tmp_data_loc_0; /* Store the word, byte-by-byte into destination address */ + sbi r3, r4, 0; + lbui r3, r0, ex_tmp_data_loc_1; + sbi r3, r4, 1; + lbui r3, r0, ex_tmp_data_loc_2; + sbi r3, r4, 2; + lbui r3, r0, ex_tmp_data_loc_3; + sbi r3, r4, 3; + BRI ex_handler_done; +ex_shw: + swi r3, r0, ex_tmp_data_loc_0; /* Store the lower half-word, byte-by-byte into destination address */ + +#ifdef __LITTLE_ENDIAN__ + lbui r3, r0, ex_tmp_data_loc_0; +#else + lbui r3, r0, ex_tmp_data_loc_2; +#endif + sbi r3, r4, 0; +#ifdef __LITTLE_ENDIAN__ + lbui r3, r0, ex_tmp_data_loc_1; +#else + lbui r3, r0, ex_tmp_data_loc_3; +#endif + sbi r3, r4, 1; +ex_sw_end: /* Exception handling of store word, ends. */ + BRI ex_handler_done; +#endif /* !NO_UNALIGNED_EXCEPTIONS */ + +#if defined (MICROBLAZE_FP_EXCEPTION_ENABLED) && defined (MICROBLAZE_FP_EXCEPTION_DECODE) +handle_fp_ex: + ADDIK r3, r17, -4; /* r17 contains (addr of exception causing FP instruction + 4) */ + lw r4, r0, r3; /* We might find ourselves in a spot here. Unguaranteed load */ + +handle_fp_ex_opb: + ADDIK r6, r0, fp_table_opb; /* Decode opB and store its value in mb_fpex_op_b */ + srl r4, r4; + srl r4, r4; + srl r4, r4; + srl r4, r4; + srl r4, r4; + srl r4, r4; + srl r4, r4; + srl r4, r4; + srl r4, r4; + srl r4, r4; + srl r4, r4; + andi r3, r4, 0x1F; + ADDK r3, r3, r3; /* Calculate (fp_table_opb + (regno * 12)) in r5 */ + ADDK r3, r3, r3; + ADDK r5, r3, r3; + ADDK r5, r5, r3; + ADDK r5, r5, r6; + bra r5; + +handle_fp_ex_opa: + ADDIK r6, r0, fp_table_opa; /* Decode opA and store its value in mb_fpex_op_a */ + srl r4, r4; + srl r4, r4; + srl r4, r4; + srl r4, r4; + srl r4, r4; + andi r3, r4, 0x1F; + ADDK r3, r3, r3; /* Calculate (fp_table_opb + (regno * 12)) in r5 */ + ADDK r3, r3, r3; + ADDK r5, r3, r3; + ADDK r5, r5, r3; + ADDK r5, r5, r6; + bra r5; + +handle_fp_ex_done: + ori r5, r0, 6; /* Set exception number back to 6 */ + BRI handle_other_ex_tail; + +fp_ex_unhandled: + bri 0; +#endif /* defined (MICROBLAZE_FP_EXCEPTION_ENABLED) && defined (MICROBLAZE_FP_EXCEPTION_DECODE) */ + +ex_handler_done: + POP_R17; + POP_MSR; + POP_REG(3); + POP_REG(4); + POP_REG(5); + POP_REG(6); + + ADDIK r1, r1, (EX_HANDLER_STACK_SIZ); /* Restore stack frame */ + rted r17, 0 + nop + +ex_handler_unhandled: + bri 0 /* UNHANDLED. TRAP HERE */ +.end _hw_exception_handler + +#ifndef NO_UNALIGNED_EXCEPTIONS + +/* + * hw_exception_handler Jump Table + * - Contains code snippets for each register that caused the unaligned exception. + * - Hence exception handler is NOT self-modifying + * - Separate table for load exceptions and store exceptions. + * - Each table is of size: (8 * 32) = 256 bytes + */ + +.section .text +.align 4 +lw_table: +lw_r0: R3_TO_LWREG (0); +lw_r1: LWREG_NOP; +lw_r2: R3_TO_LWREG (2); +lw_r3: R3_TO_LWREG_V (3); +lw_r4: R3_TO_LWREG_V (4); +lw_r5: R3_TO_LWREG_V (5); +lw_r6: R3_TO_LWREG_V (6); +lw_r7: R3_TO_LWREG (7); +lw_r8: R3_TO_LWREG (8); +lw_r9: R3_TO_LWREG (9); +lw_r10: R3_TO_LWREG (10); +lw_r11: R3_TO_LWREG (11); +lw_r12: R3_TO_LWREG (12); +lw_r13: R3_TO_LWREG (13); +lw_r14: R3_TO_LWREG (14); +lw_r15: R3_TO_LWREG (15); +lw_r16: R3_TO_LWREG (16); +lw_r17: LWREG_NOP; +lw_r18: R3_TO_LWREG (18); +lw_r19: R3_TO_LWREG (19); +lw_r20: R3_TO_LWREG (20); +lw_r21: R3_TO_LWREG (21); +lw_r22: R3_TO_LWREG (22); +lw_r23: R3_TO_LWREG (23); +lw_r24: R3_TO_LWREG (24); +lw_r25: R3_TO_LWREG (25); +lw_r26: R3_TO_LWREG (26); +lw_r27: R3_TO_LWREG (27); +lw_r28: R3_TO_LWREG (28); +lw_r29: R3_TO_LWREG (29); +lw_r30: R3_TO_LWREG (30); +lw_r31: R3_TO_LWREG (31); + +sw_table: +sw_r0: SWREG_TO_R3 (0); +sw_r1: SWREG_NOP; +sw_r2: SWREG_TO_R3 (2); +sw_r3: SWREG_TO_R3_V (3); +sw_r4: SWREG_TO_R3_V (4); +sw_r5: SWREG_TO_R3_V (5); +sw_r6: SWREG_TO_R3_V (6); +sw_r7: SWREG_TO_R3 (7); +sw_r8: SWREG_TO_R3 (8); +sw_r9: SWREG_TO_R3 (9); +sw_r10: SWREG_TO_R3 (10); +sw_r11: SWREG_TO_R3 (11); +sw_r12: SWREG_TO_R3 (12); +sw_r13: SWREG_TO_R3 (13); +sw_r14: SWREG_TO_R3 (14); +sw_r15: SWREG_TO_R3 (15); +sw_r16: SWREG_TO_R3 (16); +sw_r17: SWREG_NOP; +sw_r18: SWREG_TO_R3 (18); +sw_r19: SWREG_TO_R3 (19); +sw_r20: SWREG_TO_R3 (20); +sw_r21: SWREG_TO_R3 (21); +sw_r22: SWREG_TO_R3 (22); +sw_r23: SWREG_TO_R3 (23); +sw_r24: SWREG_TO_R3 (24); +sw_r25: SWREG_TO_R3 (25); +sw_r26: SWREG_TO_R3 (26); +sw_r27: SWREG_TO_R3 (27); +sw_r28: SWREG_TO_R3 (28); +sw_r29: SWREG_TO_R3 (29); +sw_r30: SWREG_TO_R3 (30); +sw_r31: SWREG_TO_R3 (31); + +/* Temporary data structures used in the handler */ +.section .data +.align DATAALIGN +ex_tmp_data_loc_0: + .byte 0 +ex_tmp_data_loc_1: + .byte 0 +ex_tmp_data_loc_2: + .byte 0 +ex_tmp_data_loc_3: + .byte 0 +ex_reg_op: + .byte 0 + +#endif /* ! NO_UNALIGNED_EXCEPTIONS */ + +#if defined (MICROBLAZE_FP_EXCEPTION_ENABLED) && defined (MICROBLAZE_FP_EXCEPTION_DECODE) +/* + * FP exception decode jump table. + * - Contains code snippets for each register that could have been a source operand for an excepting FP instruction + * - Hence exception handler is NOT self-modifying + * - Separate table for opA and opB + * - Each table is of size: (12 * 32) = 384 bytes + */ + +.section .text +.align 4 +fp_table_opa: +opa_r0: FP_EX_OPA_SAVE (0); +opa_r1: FP_EX_UNHANDLED; +opa_r2: FP_EX_OPA_SAVE (2); +opa_r3: FP_EX_OPA_SAVE_V (3); +opa_r4: FP_EX_OPA_SAVE_V (4); +opa_r5: FP_EX_OPA_SAVE_V (5); +opa_r6: FP_EX_OPA_SAVE_V (6); +opa_r7: FP_EX_OPA_SAVE (7); +opa_r8: FP_EX_OPA_SAVE (8); +opa_r9: FP_EX_OPA_SAVE (9); +opa_r10: FP_EX_OPA_SAVE (10); +opa_r11: FP_EX_OPA_SAVE (11); +opa_r12: FP_EX_OPA_SAVE (12); +opa_r13: FP_EX_OPA_SAVE (13); +opa_r14: FP_EX_UNHANDLED; +opa_r15: FP_EX_UNHANDLED; +opa_r16: FP_EX_UNHANDLED; +opa_r17: FP_EX_UNHANDLED; +opa_r18: FP_EX_OPA_SAVE (18); +opa_r19: FP_EX_OPA_SAVE (19); +opa_r20: FP_EX_OPA_SAVE (20); +opa_r21: FP_EX_OPA_SAVE (21); +opa_r22: FP_EX_OPA_SAVE (22); +opa_r23: FP_EX_OPA_SAVE (23); +opa_r24: FP_EX_OPA_SAVE (24); +opa_r25: FP_EX_OPA_SAVE (25); +opa_r26: FP_EX_OPA_SAVE (26); +opa_r27: FP_EX_OPA_SAVE (27); +opa_r28: FP_EX_OPA_SAVE (28); +opa_r29: FP_EX_OPA_SAVE (29); +opa_r30: FP_EX_OPA_SAVE (30); +opa_r31: FP_EX_OPA_SAVE (31); + +fp_table_opb: +opb_r0: FP_EX_OPB_SAVE (0); +opb_r1: FP_EX_UNHANDLED; +opb_r2: FP_EX_OPB_SAVE (2); +opb_r3: FP_EX_OPB_SAVE_V (3); +opb_r4: FP_EX_OPB_SAVE_V (4); +opb_r5: FP_EX_OPB_SAVE_V (5); +opb_r6: FP_EX_OPB_SAVE_V (6); +opb_r7: FP_EX_OPB_SAVE (7); +opb_r8: FP_EX_OPB_SAVE (8); +opb_r9: FP_EX_OPB_SAVE (9); +opb_r10: FP_EX_OPB_SAVE (10); +opb_r11: FP_EX_OPB_SAVE (11); +opb_r12: FP_EX_OPB_SAVE (12); +opb_r13: FP_EX_OPB_SAVE (13); +opb_r14: FP_EX_UNHANDLED; +opb_r15: FP_EX_UNHANDLED; +opb_r16: FP_EX_UNHANDLED; +opb_r17: FP_EX_UNHANDLED; +opb_r18: FP_EX_OPB_SAVE (18); +opb_r19: FP_EX_OPB_SAVE (19); +opb_r20: FP_EX_OPB_SAVE (20); +opb_r21: FP_EX_OPB_SAVE (21); +opb_r22: FP_EX_OPB_SAVE (22); +opb_r23: FP_EX_OPB_SAVE (23); +opb_r24: FP_EX_OPB_SAVE (24); +opb_r25: FP_EX_OPB_SAVE (25); +opb_r26: FP_EX_OPB_SAVE (26); +opb_r27: FP_EX_OPB_SAVE (27); +opb_r28: FP_EX_OPB_SAVE (28); +opb_r29: FP_EX_OPB_SAVE (29); +opb_r30: FP_EX_OPB_SAVE (30); +opb_r31: FP_EX_OPB_SAVE (31); + +#endif /* defined (MICROBLAZE_FP_EXCEPTION_ENABLED) && defined (MICROBLAZE_FP_EXCEPTION_DECODE) */ + +#if defined(MICROBLAZE_FP_EXCEPTION_ENABLED) && defined(MICROBLAZE_FP_EXCEPTION_DECODE) +/* This is where we store the opA and opB of the last excepting FP instruction */ +.section .data +.align DATAALIGN +.global mb_fpex_op_a +.global mb_fpex_op_b +mb_fpex_op_a: + INTPTR_DATAITEM 0 +mb_fpex_op_b: + INTPTR_DATAITEM 0 +#endif /* defined (MICROBLAZE_FP_EXCEPTION_ENABLED) && defined (MICROBLAZE_FP_EXCEPTION_DECODE) */ + +#if defined(XPAR_MICROBLAZE_USE_STACK_PROTECTION) && (XPAR_MICROBLAZE_USE_STACK_PROTECTION == 1) +/* This is where we store the register used to check which exception occurred */ + .section .data + .align DATAALIGN +mb_sp_save_r3: + INTPTR_DATAITEM 0 +#endif /* defined(XPAR_MICROBLAZE_USE_STACK_PROTECTION) && (XPAR_MICROBLAZE_USE_STACK_PROTECTION == 1) */ + +/* The exception vector table */ +.section .data +.align DATAALIGN +.global MB_ExceptionVectorTable +MB_ExceptionVectorTable: + INTPTR_DATAITEM XNullHandler + INTPTR_DATAITEM 0 /* -- FSL Exception -- */ + INTPTR_DATAITEM XNullHandler + INTPTR_DATAITEM 1 /* -- Unaligned Access Exception -- */ + INTPTR_DATAITEM XNullHandler + INTPTR_DATAITEM 2 /* -- Illegal Opcode Exception -- */ + INTPTR_DATAITEM XNullHandler + INTPTR_DATAITEM 3 /* -- Instruction Bus Exception -- */ + INTPTR_DATAITEM XNullHandler + INTPTR_DATAITEM 4 /* -- Data Bus Exception -- */ + INTPTR_DATAITEM XNullHandler + INTPTR_DATAITEM 5 /* -- Div-by-0 Exception -- */ + INTPTR_DATAITEM XNullHandler + INTPTR_DATAITEM 6 /* -- FPU Exception -- */ + INTPTR_DATAITEM XNullHandler + INTPTR_DATAITEM 7 /* -- MMU Exceptions -- */ + +#else /* Dummy exception handler, in case exceptions are not present in the processor */ + +.global _hw_exception_handler +.section .text +.align 2 +.ent _hw_exception_handler +_hw_exception_handler: + bri 0; +.end _hw_exception_handler + +#endif /* MICROBLAZE_EXCEPTIONS_ENABLED */ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/inbyte.c b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/inbyte.c new file mode 100644 index 0000000..2e27984 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/inbyte.c @@ -0,0 +1,11 @@ +#include "xparameters.h" +#ifdef __cplusplus +extern "C" { +#endif +char inbyte(void); +#ifdef __cplusplus +} +#endif + +char inbyte(void) { +} diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/mb_interface.h b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/mb_interface.h new file mode 100644 index 0000000..fc45555 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/mb_interface.h @@ -0,0 +1,470 @@ +/****************************************************************************** +* +* Copyright (C) 2004 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file mb_interface.h +* +* @addtogroup microblaze_pseudo_asm_macro Microblaze Pseudo-asm Macros and Interrupt Handling APIs +* +* Microblaze BSP includes macros to provide convenient access to various registers +* in the MicroBlaze processor. Some of these macros are very useful within +* exception handlers for retrieving information about the exception.Also, +* the interrupt handling functions help manage interrupt handling on MicroBlaze +* processor devices.To use these functions, include the header file +* mb_interface.h in your source code +* +* @{ +* +******************************************************************************/ +#ifndef _MICROBLAZE_INTERFACE_H_ +#define _MICROBLAZE_INTERFACE_H_ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_exception.h" + +#ifdef __cplusplus +extern "C" { +#endif +extern void microblaze_enable_interrupts(void); /* Enable Interrupts */ +extern void microblaze_disable_interrupts(void); /* Disable Interrupts */ +extern void microblaze_enable_icache(void); /* Enable Instruction Cache */ +extern void microblaze_disable_icache(void); /* Disable Instruction Cache */ +extern void microblaze_enable_dcache(void); /* Enable Instruction Cache */ +extern void microblaze_disable_dcache(void); /* Disable Instruction Cache */ +extern void microblaze_enable_exceptions(void); /* Enable hardware exceptions */ +extern void microblaze_disable_exceptions(void); /* Disable hardware exceptions */ +extern void microblaze_register_handler(XInterruptHandler Handler, void *DataPtr); /* Register top level interrupt handler */ +extern void microblaze_register_exception_handler(u32 ExceptionId, Xil_ExceptionHandler Handler, void *DataPtr); /* Register exception handler */ + +extern void microblaze_invalidate_icache(void); /* Invalidate the entire icache */ +extern void microblaze_invalidate_dcache(void); /* Invalidate the entire dcache */ +extern void microblaze_flush_dcache(void); /* Flush the whole dcache */ +extern void microblaze_invalidate_icache_range(UINTPTR cacheaddr, u32 len); /* Invalidate a part of the icache */ +extern void microblaze_invalidate_dcache_range(UINTPTR cacheaddr, u32 len); /* Invalidate a part of the dcache */ +extern void microblaze_flush_dcache_range(UINTPTR cacheaddr, u32 len); /* Flush a part of the dcache */ +extern void microblaze_scrub(void); /* Scrub LMB and internal BRAM */ +extern void microblaze_invalidate_cache_ext(void); /* Invalidate cache ext */ +extern void microblaze_flush_cache_ext(void); /* Flush cache ext */ +extern void microblaze_flush_cache_ext_range(UINTPTR cacheaddr, + u32 len); /* Flush cache ext range */ +extern void microblaze_invalidate_cache_ext_range(UINTPTR cacheaddr, + u32 len); /* Invalidate cache ext range */ + +/* Deprecated */ +extern void microblaze_update_icache (s32 , s32 , s32 ) __attribute__((deprecated)); +extern void microblaze_init_icache_range (s32 , s32 ) __attribute__((deprecated)); +extern void microblaze_update_dcache (s32 , s32 , s32 ) __attribute__((deprecated)); +extern void microblaze_init_dcache_range (s32 , s32 ) __attribute__((deprecated)); + +/* necessary for pre-processor */ +#define stringify(s) tostring(s) +#define tostring(s) #s + +/* FSL Access Macros */ + +/* Blocking Data Read and Write to FSL no. id */ +#define getfsl(val, id) asm volatile ("get\t%0,rfsl" stringify(id) : "=d" (val)) +#define putfsl(val, id) asm volatile ("put\t%0,rfsl" stringify(id) :: "d" (val)) + +/* Non-blocking Data Read and Write to FSL no. id */ +#define ngetfsl(val, id) asm volatile ("nget\t%0,rfsl" stringify(id) : "=d" (val)) +#define nputfsl(val, id) asm volatile ("nput\t%0,rfsl" stringify(id) :: "d" (val)) + +/* Blocking Control Read and Write to FSL no. id */ +#define cgetfsl(val, id) asm volatile ("cget\t%0,rfsl" stringify(id) : "=d" (val)) +#define cputfsl(val, id) asm volatile ("cput\t%0,rfsl" stringify(id) :: "d" (val)) + +/* Non-blocking Control Read and Write to FSL no. id */ +#define ncgetfsl(val, id) asm volatile ("ncget\t%0,rfsl" stringify(id) : "=d" (val)) +#define ncputfsl(val, id) asm volatile ("ncput\t%0,rfsl" stringify(id) :: "d" (val)) + +/* Polling versions of FSL access macros. This makes the FSL access interruptible */ +#define getfsl_interruptible(val, id) asm volatile ("\n1:\n\tnget\t%0,rfsl" stringify(id) "\n\t" \ + "addic\tr18,r0,0\n\t" \ + "bnei\tr18,1b\n" \ + : "=d" (val) :: "r18") + +#define putfsl_interruptible(val, id) asm volatile ("\n1:\n\tnput\t%0,rfsl" stringify(id) "\n\t" \ + "addic\tr18,r0,0\n\t" \ + "bnei\tr18,1b\n" \ + :: "d" (val) : "r18") + +#define cgetfsl_interruptible(val, id) asm volatile ("\n1:\n\tncget\t%0,rfsl" stringify(id) "\n\t" \ + "addic\tr18,r0,0\n\t" \ + "bnei\tr18,1b\n" \ + : "=d" (val) :: "r18") + +#define cputfsl_interruptible(val, id) asm volatile ("\n1:\n\tncput\t%0,rfsl" stringify(id) "\n\t" \ + "addic\tr18,r0,0\n\t" \ + "bnei\tr18,1b\n" \ + :: "d" (val) : "r18") +/* FSL valid and error check macros. */ +#define fsl_isinvalid(result) asm volatile ("addic\t%0,r0,0" : "=d" (result)) +#define fsl_iserror(error) asm volatile ("mfs\t%0,rmsr\n\t" \ + "andi\t%0,%0,0x10" : "=d" (error)) + +/* Pseudo assembler instructions */ +#define clz(v) ({ u32 _rval; \ + __asm__ __volatile__ ( \ + "clz\t%0,%1\n" : "=d"(_rval): "d" (v) \ + ); \ + _rval; \ + }) + +#define mbar(mask) ({ __asm__ __volatile__ ("mbar\t" stringify(mask) ); }) +#define mb_sleep() ({ __asm__ __volatile__ ("sleep\t"); }) +#define mb_hibernate() ({ __asm__ __volatile__ ("hibernate\t"); }) +#define mb_suspend() ({ __asm__ __volatile__ ("suspend\t"); }) +#define mb_swapb(v) ({ u32 _rval; \ + __asm__ __volatile__ ( \ + "swapb\t%0,%1\n" : "=d"(_rval) : "d" (v) \ + ); \ + _rval; \ + }) + +#define mb_swaph(v) ({ u32 _rval; \ + __asm__ __volatile__ ( \ + "swaph\t%0,%1\n" : "=d"(_rval) : "d" (v) \ + ); \ + _rval; \ + }) + +/** @name Microblaze pseudo-asm macros + * + * The following is a summary of the MicroBlaze processor pseudo-asm macros. + * @{ + */ + + /** + Return value from the general purpose register (GPR) rn. + @param rn General purpose register to be read. +*/ +#define mfgpr(rn) ({ UINTPTR _rval; \ + __asm__ __volatile__ ( \ + "or\t%0,r0," stringify(rn) "\n" : "=d"(_rval) \ + ); \ + _rval; \ + }) + + /** + Return the current value of the MSR. + @param None +*/ +#define mfmsr() ({ UINTPTR _rval; \ + __asm__ __volatile__ ( \ + "mfs\t%0,rmsr\n" : "=d"(_rval) \ + ); \ + _rval; \ + }) + + /** + Return the current value of the Exception Address Register (EAR). + @param None +*/ +#define mfear() ({ UINTPTR _rval; \ + __asm__ __volatile__ ( \ + "mfs\t%0,rear\n" : "=d"(_rval) \ + ); \ + _rval; \ + }) + +#define mfeare() ({ UINTPTR _rval; \ + __asm__ __volatile__ ( \ + "mfse\t%0,rear\n" : "=d"(_rval) \ + ); \ + _rval; \ + }) + /** + Return the current value of the Exception Status Register (ESR). + @param None +*/ +#define mfesr() ({ UINTPTR _rval; \ + __asm__ __volatile__ ( \ + "mfs\t%0,resr\n" : "=d"(_rval) \ + ); \ + _rval; \ + }) + + /** + Return the current value of the Floating Point Status (FPS). + @param None +*/ +#define mffsr() ({ UINTPTR _rval; \ + __asm__ __volatile__ ( \ + "mfs\t%0,rfsr\n" : "=d"(_rval) \ + ); \ + _rval; \ + }) +/*@}*/ +#define mfpvr(rn) ({ UINTPTR _rval; \ + __asm__ __volatile__ ( \ + "mfs\t%0,rpvr" stringify(rn) "\n" : "=d"(_rval) \ + ); \ + _rval; \ + }) + +#define mfpvre(rn) ({ UINTPTR _rval; \ + __asm__ __volatile__ ( \ + "mfse\t%0,rpvr" stringify(rn) "\n" : "=d"(_rval) \ + ); \ + _rval; \ + }) + +#define mfbtr() ({ UINTPTR _rval; \ + __asm__ __volatile__ ( \ + "mfs\t%0,rbtr\n" : "=d"(_rval) \ + ); \ + _rval; \ + }) + +#define mfedr() ({ UINTPTR _rval; \ + __asm__ __volatile__ ( \ + "mfs\t%0,redr\n" : "=d"(_rval) \ + ); \ + _rval; \ + }) + +#define mfpid() ({ UINTPTR _rval; \ + __asm__ __volatile__ ( \ + "mfs\t%0,rpid\n" : "=d"(_rval)\ + ); \ + _rval; \ + }) + +#define mfzpr() ({ UINTPTR _rval; \ + __asm__ __volatile__ ( \ + "mfs\t%0,rzpr\n" : "=d"(_rval) \ + ); \ + _rval; \ + }) + +#define mftlbx() ({ UINTPTR _rval; \ + __asm__ __volatile__ ( \ + "mfs\t%0,rtlbx\n" : "=d"(_rval) \ + ); \ + _rval; \ + }) + +#define mftlblo() ({ UINTPTR _rval; \ + __asm__ __volatile__ ( \ + "mfs\t%0,rtlblo\n" : "=d"(_rval) \ + ); \ + _rval; \ + }) + +#define mftlbhi() ({ UINTPTR _rval; \ + __asm__ __volatile__ ( \ + "mfs\t%0,rtlbhi\n" : "=d"(_rval) \ + ); \ + _rval; \ + }) + +#define mfslr() ({ UINTPTR _rval; \ + __asm__ __volatile__ ( \ + "mfs\t%0,rslr\n" : "=d"(_rval) \ + ); \ + _rval; \ + }) + +#define mfshr() ({ UINTPTR _rval; \ + __asm__ __volatile__ ( \ + "mfs\t%0,rshr\n" : "=d"(_rval) \ + ); \ + _rval; \ + }) + +#define mtgpr(rn, v) ({ __asm__ __volatile__ ( \ + "or\t" stringify(rn) ",r0,%0\n" :: "d" (v) \ + ); \ + }) + +#define mtmsr(v) ({ __asm__ __volatile__ ( \ + "mts\trmsr,%0\n\tnop\n" :: "d" (v) \ + ); \ + }) + + +#define mtfsr(v) ({ __asm__ __volatile__ ( \ + "mts\trfsr,%0\n\tnop\n" :: "d" (v) \ + ); \ + }) + +#define mtpid(v) ({ __asm__ __volatile__ ( \ + "mts\trpid,%0\n\tnop\n" :: "d" (v) \ + ); \ + }) + +#define mtzpr(v) ({ __asm__ __volatile__ ( \ + "mts\trzpr,%0\n\tnop\n" :: "d" (v) \ + ); \ + }) + +#define mttlbx(v) ({ __asm__ __volatile__ ( \ + "mts\trtlbx,%0\n\tnop\n" :: "d" (v) \ + ); \ + }) + +#define mttlblo(v) ({ __asm__ __volatile__ ( \ + "mts\trtlblo,%0\n\tnop\n" :: "d" (v) \ + ); \ + }) + +#define mttlbhi(v) ({ __asm__ __volatile__ ( \ + "mts\trtlbhi,%0\n\tnop\n" :: "d" (v) \ + ); \ + }) + +#define mttlbsx(v) ({ __asm__ __volatile__ ( \ + "mts\trtlbsx,%0\n\tnop\n" :: "d" (v) \ + ); \ + }) + +#define mtslr(v) ({ __asm__ __volatile__ ( \ + "mts\trslr,%0\n\tnop\n" :: "d" (v) \ + ); \ + }) + +#define mtshr(v) ({ __asm__ __volatile__ ( \ + "mts\trshr,%0\n\tnop\n" :: "d" (v) \ + ); \ + }) + +#define lwx(address) ({ u32 _rval; \ + __asm__ __volatile__ ( \ + "lwx\t%0,%1,r0\n" : "=d"(_rval) : "d" (address) \ + ); \ + _rval; \ + }) + +#define lwr(address) ({ u32 _rval; \ + __asm__ __volatile__ ( \ + "lwr\t%0,%1,r0\n" : "=d"(_rval) : "d" (address) \ + ); \ + _rval; \ + }) + + +#define lwea(lladdr) ({ u32 _rval; \ + __asm__ __volatile__ ( \ + "lwea\t%0,%M1,%L1\n" : "=d"(_rval) : "d" (lladdr) \ + ); \ + _rval; \ + }) + +#define lhur(address) ({ u32 _rval; \ + __asm__ __volatile__ ( \ + "lhur\t%0,%1,r0\n" : "=d"(_rval) : "d" (address) \ + ); \ + _rval; \ + }) + +#define lhuea(lladdr) ({ u32 _rval; \ + __asm__ __volatile__ ( \ + "lhuea\t%0,%M1,%L1\n" : "=d"(_rval) : "d" (lladdr) \ + ); \ + _rval; \ + }) + +#define lbur(address) ({ u32 _rval; \ + __asm__ __volatile__ ( \ + "lbur\t%0,%1,r0\n" : "=d"(_rval) : "d" (address) \ + ); \ + _rval; \ + }) + +#define lbuea(lladdr) ({ u32 _rval; \ + __asm__ __volatile__ ( \ + "lbuea\t%0,%M1,%L1\n" : "=d"(_rval) : "d" (lladdr) \ + ); \ + _rval; \ + }) + +#define swx(address, data) ({ __asm__ __volatile__ ( \ + "swx\t%0,%1,r0\n" :: "d" (data), "d" (address) \ + ); \ + }) + +#define swr(address, data) ({ __asm__ __volatile__ ( \ + "swr\t%0,%1,r0\n" :: "d" (data), "d" (address) \ + ); \ + }) + +#define swea(lladdr, data) ({ __asm__ __volatile__ ( \ + "swea\t%0,%M1,%L1\n" :: "d" (data), "d" (lladdr) \ + ); \ + }) + +#define shr(address, data) ({ __asm__ __volatile__ ( \ + "shr\t%0,%1,r0\n" :: "d" (data), "d" (address) \ + ); \ + }) + +#define shea(lladdr, data) ({ __asm__ __volatile__ ( \ + "shea\t%0,%M1,%L1\n" :: "d" (data), "d" (lladdr) \ + ); \ + }) + +#define sbr(address, data) ({ __asm__ __volatile__ ( \ + "sbr\t%0,%1,r0\n" :: "d" (data), "d" (address) \ + ); \ + }) + +#define sbea(lladdr, data) ({ __asm__ __volatile__ ( \ + "sbea\t%0,%M1,%L1\n" :: "d" (data), "d" (lladdr) \ + ); \ + }) + +#define microblaze_getfpex_operand_a() ({ \ + extern u32 mb_fpex_op_a; \ + mb_fpex_op_a; \ + }) + +#define microblaze_getfpex_operand_b() ({ \ + extern u32 mb_fpex_op_b; \ + mb_fpex_op_b; \ + }) + +/* Deprecated MicroBlaze FSL macros */ +#define microblaze_bread_datafsl(val, id) getfsl(val,id) +#define microblaze_bwrite_datafsl(val, id) putfsl(val,id) +#define microblaze_nbread_datafsl(val, id) ngetfsl(val,id) +#define microblaze_nbwrite_datafsl(val, id) nputfsl(val,id) +#define microblaze_bread_cntlfsl(val, id) cgetfsl(val,id) +#define microblaze_bwrite_cntlfsl(val, id) cputfsl(val,id) +#define microblaze_nbread_cntlfsl(val, id) ncgetfsl(val,id) +#define microblaze_nbwrite_cntlfsl(val, id) ncputfsl(val,id) + +#ifdef __cplusplus +} +#endif +#endif // _MICROBLAZE_INTERFACE_H_ +/** +* @} End of "addtogroup microblaze_pseudo_asm_macro". +*/ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_disable_dcache.S b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_disable_dcache.S new file mode 100644 index 0000000..a455b02 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_disable_dcache.S @@ -0,0 +1,82 @@ +/****************************************************************************** +* +* Copyright (C) 2008 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************** +* File : microblaze_disable_dcache.s +* Date : 2002, March 20. +* Company: Xilinx +* Group : Emerging Software Technologies +* +* Summary: +* Disable the L1 dcache on the microblaze. +* +*******************************************************************************/ + +#include "xparameters.h" +#include "microblaze_instructions.h" + + .text + .globl microblaze_disable_dcache + .ent microblaze_disable_dcache + .align 2 +microblaze_disable_dcache: +#if XPAR_MICROBLAZE_USE_MSR_INSTR == 1 + +#if XPAR_MICROBLAZE_DCACHE_USE_WRITEBACK != 0 + ADDIK r1, r1, -8 + SI r15, r1, 0 + BRLID r15, microblaze_flush_dcache /* microblaze_flush_dcache does not use r1*/ + nop + LI r15, r1, 0 + ADDIK r1, r1, 8 +#endif /* XPAR_MICROBLAZE_DCACHE_USE_WRITEBACK != 0 */ + rtsd r15, 8 + msrclr r0, 0x80 + +#else /* XPAR_MICROBLAZE_USE_MSR_INSTR == 1 */ + + ADDIK r1, r1, -8 + +#if XPAR_MICROBLAZE_DCACHE_USE_WRITEBACK != 0 + SI r15, r1, 0 + BRLID r15, microblaze_flush_dcache + nop +#endif /* XPAR_MICROBLAZE_DCACHE_USE_WRITEBACK != 0 */ + mfs r11, rmsr + andi r11, r11, ~(0x80) + mts rmsr, r11 + +#if XPAR_MICROBLAZE_DCACHE_USE_WRITEBACK != 0 + LI r15, r1, 0 +#endif /* XPAR_MICROBLAZE_DCACHE_USE_WRITEBACK != 0 */ + + ADDIK r1, r1, 8 + rtsd r15, 8 + nop + +#endif /*XPAR_MICROBLAZE_USE_MSR_INSTR == 1*/ + .end microblaze_disable_dcache diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_disable_exceptions.S b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_disable_exceptions.S new file mode 100644 index 0000000..f9909b9 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_disable_exceptions.S @@ -0,0 +1,52 @@ +/****************************************************************************** +* +* Copyright (C) 2004 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************** +* +* Disable exceptions on microblaze. +* +* +******************************************************************************/ + +#include "xparameters.h" + + .text + .globl microblaze_disable_exceptions + .ent microblaze_disable_exceptions + .align 2 +microblaze_disable_exceptions: +#if XPAR_MICROBLAZE_USE_MSR_INSTR == 1 + rtsd r15, 8 + msrclr r0, 0x100 +#else + mfs r4, rmsr; + andi r4, r4, ~(0x100); /* Turn OFF the EE bit */ + mts rmsr, r4; + rtsd r15, 8; + nop; +#endif +.end microblaze_disable_exceptions diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_disable_icache.S b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_disable_icache.S new file mode 100644 index 0000000..daf0cac --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_disable_icache.S @@ -0,0 +1,62 @@ +/****************************************************************************** +* +* Copyright (C) 2004 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************** +* +* File : microblaze_disable_icache.s +* Date : 2002, March 20. +* Company: Xilinx +* Group : Emerging Software Technologies +* +* Summary: +* Disable L1 icache on the microblaze. +* +* +******************************************************************************/ + +#include "xparameters.h" + + .text + .globl microblaze_disable_icache + .ent microblaze_disable_icache + .align 2 +microblaze_disable_icache: +#if XPAR_MICROBLAZE_USE_MSR_INSTR == 1 + rtsd r15, 8 + msrclr r0, 0x20 +#else /*XPAR_MICROBLAZE_USE_MSR_INSTR == 1*/ + #Read the MSR register + mfs r8, rmsr + #Clear the icache enable bit + andi r8, r8, ~(0x20) + #Save the MSR register + mts rmsr, r8 + #Return + rtsd r15, 8 + nop +#endif + .end microblaze_disable_icache diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_disable_interrupts.S b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_disable_interrupts.S new file mode 100644 index 0000000..0270414 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_disable_interrupts.S @@ -0,0 +1,76 @@ +/****************************************************************************** +* +* Copyright (C) 2004 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************** +* @file microblaze_disable_interrupts.S +* +* @addtogroup microblaze_pseudo_asm_macro +* @{ +*

microblaze_disable_interrupts.S

+* - API to disable Interrupts: void microblaze_disable_interrupts(void) +* +* This API Disables interrupts on the MicroBlaze processor. It can be +* called when entering a critical section of code where a context switch is +* undesirable. +* +*
+* File   : microblaze_disable_interrupts.s
+* Date   : 2002, March 20.
+* Company: Xilinx
+* Group  : Emerging Software Technologies
+*
+* Summary:
+* Disable interrupts on the microblaze.
+* 
+* +******************************************************************************/ + +#include "xparameters.h" + + .text + .globl microblaze_disable_interrupts + .ent microblaze_disable_interrupts + .align 2 +microblaze_disable_interrupts: +#if XPAR_MICROBLAZE_USE_MSR_INSTR == 1 + rtsd r15, 8 + msrclr r0, 0x2 +#else /*XPAR_MICROBLAZE_USE_MSR_INSTR == 1*/ + #Read the MSR register + mfs r12, rmsr + #Clear the interrupt enable bit + andi r12, r12, ~(0x2) + #Save the MSR register + mts rmsr, r12 + #Return + rtsd r15, 8 + nop +#endif /*XPAR_MICROBLAZE_USE_MSR_INSTR == 1*/ + .end microblaze_disable_interrupts +/** +* @} End of "addtogroup microblaze_pseudo_asm_macro". +*/ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_enable_dcache.S b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_enable_dcache.S new file mode 100644 index 0000000..4f944be --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_enable_dcache.S @@ -0,0 +1,63 @@ +/****************************************************************************** +* +* Copyright (C) 2004 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************** +* +* File : microblaze_enable_dcache.s +* Date : 2002, March 20. +* Company: Xilinx +* Group : Emerging Software Technologies +* +* Summary: +* Enable L1 dcache on the microblaze. +* +* +******************************************************************************/ + +#include "xparameters.h" + + .text + .globl microblaze_enable_dcache + .ent microblaze_enable_dcache + .align 2 +microblaze_enable_dcache: + +#if XPAR_MICROBLAZE_USE_MSR_INSTR == 1 + rtsd r15, 8 + msrset r0, 0x80 +#else /*XPAR_MICROBLAZE_USE_MSR_INSTR == 1*/ + #Read the MSR register + mfs r8, rmsr + #Set the interrupt enable bit + ori r8, r8, 0x80 + #Save the MSR register + mts rmsr, r8 + #Return + rtsd r15, 8 + nop +#endif /*XPAR_MICROBLAZE_USE_MSR_INSTR == 1*/ + .end microblaze_enable_dcache diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_enable_exceptions.S b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_enable_exceptions.S new file mode 100644 index 0000000..e990a3d --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_enable_exceptions.S @@ -0,0 +1,52 @@ +/****************************************************************************** +* +* Copyright (C) 2004 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************** +* +* Enable exceptions on microblaze. +* +* +******************************************************************************/ + +#include "xparameters.h" + + .text + .globl microblaze_enable_exceptions + .ent microblaze_enable_exceptions + .align 2 +microblaze_enable_exceptions: +#if XPAR_MICROBLAZE_USE_MSR_INSTR == 1 + rtsd r15, 8; + msrset r0, 0x100 +#else /*XPAR_MICROBLAZE_USE_MSR_INSTR == 1*/ + mfs r4, rmsr; + ori r4, r4, 0x100; /* Turn ON the EE bit */ + mts rmsr, r4; + rtsd r15, 8; + nop; +#endif /*XPAR_MICROBLAZE_USE_MSR_INSTR == 1*/ +.end microblaze_enable_exceptions diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_enable_icache.S b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_enable_icache.S new file mode 100644 index 0000000..aaed781 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_enable_icache.S @@ -0,0 +1,61 @@ +/****************************************************************************** +* +* Copyright (C) 2004 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************** +* +* File : microblaze_enable_icache.s +* Date : 2002, March 20. +* Company: Xilinx +* Group : Emerging Software Technologies +* +* Summary: +* Enable icache on the microblaze. +* +* +******************************************************************************/ +#include "xparameters.h" + + .text + .globl microblaze_enable_icache + .ent microblaze_enable_icache + .align 2 +microblaze_enable_icache: +#if XPAR_MICROBLAZE_USE_MSR_INSTR == 1 + rtsd r15, 8 + msrset r0, 0x20 +#else /*XPAR_MICROBLAZE_USE_MSR_INSTR == 1*/ + #Read the MSR register + mfs r8, rmsr + #Set the interrupt enable bit + ori r8, r8, 0x20 + #Save the MSR register + mts rmsr, r8 + #Return + rtsd r15, 8 + nop +#endif /*XPAR_MICROBLAZE_USE_MSR_INSTR == 1*/ + .end microblaze_enable_icache diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_enable_interrupts.S b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_enable_interrupts.S new file mode 100644 index 0000000..3b7a7c2 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_enable_interrupts.S @@ -0,0 +1,78 @@ +/****************************************************************************** +* +* Copyright (C) 2004 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************** +* @file microblaze_enable_interrupts.S +* +* @addtogroup microblaze_pseudo_asm_macro +* @{ +*

microblaze_enable_interrupts.S

+* - API to Enable Interrupts: void microblaze_enable_interrupts(void) +* +* This API Enables interrupts on the MicroBlaze processor. When the MicroBlaze +* processor starts up, interrupts are disabled. Interrupts must be explicitly +* turned on using this function. +* +*
+*
+* File   : microblaze_enable_interrupts.s
+* Date   : 2002, March 20.
+* Company: Xilinx
+* Group  : Emerging Software Technologies
+*
+* Summary:
+* Enable interrupts on the microblaze.
+* 
+* +******************************************************************************/ + +#include "xparameters.h" + + .text + .globl microblaze_enable_interrupts + .ent microblaze_enable_interrupts + .align 2 +microblaze_enable_interrupts: +#if XPAR_MICROBLAZE_USE_MSR_INSTR == 1 + rtsd r15, 8 + msrset r0, 0x2 + nop +#else /*XPAR_MICROBLAZE_USE_MSR_INSTR == 1*/ + #Read the MSR register + mfs r12, rmsr + #Set the interrupt enable bit + ori r12, r12, 0x2 + #Save the MSR register + mts rmsr, r12 + #Return + rtsd r15, 8 + nop +#endif /*XPAR_MICROBLAZE_USE_MSR_INSTR == 1*/ + .end microblaze_enable_interrupts +/** +* @} End of "addtogroup microblaze_pseudo_asm_macro". +*/ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_exception_handler.c b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_exception_handler.c new file mode 100644 index 0000000..2f3a289 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_exception_handler.c @@ -0,0 +1,93 @@ +/****************************************************************************** +* +* Copyright (C) 2004 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file microblaze_exception_handler.c +* +* This file contains exception handler registration routines for +* the MicroBlaze processor. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Date     Changes
+* ----- -------- -----------------------------------------------
+* 1.00b 06/24/04 First release
+* 
+* +******************************************************************************/ + + +/***************************** Include Files *********************************/ +#include "microblaze_exceptions_i.h" +#include "microblaze_exceptions_g.h" + +#ifdef MICROBLAZE_EXCEPTIONS_ENABLED /* If exceptions are enabled in the processor */ +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ +extern MB_ExceptionVectorTableEntry MB_ExceptionVectorTable[]; +/****************************************************************************/ + +/*****************************************************************************/ +/** +* +* Registers an exception handler for the MicroBlaze. The +* argument provided in this call as the DataPtr is used as the argument +* for the handler when it is called. +* +* @param ExceptionId is the id of the exception to register this handler +* for. +* @param Top level handler. +* @param DataPtr is a reference to data that will be passed to the handler +* when it gets called. +* @return None. +* +* @note +* +* None. +* +****************************************************************************/ +void microblaze_register_exception_handler(u32 ExceptionId, Xil_ExceptionHandler Handler, void *DataPtr) +{ + MB_ExceptionVectorTable[ExceptionId].Handler = Handler; + MB_ExceptionVectorTable[ExceptionId].CallBackRef = DataPtr; +} + +#endif /* MICROBLAZE_EXCEPTIONS_ENABLED */ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_exceptions_g.h b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_exceptions_g.h new file mode 100644 index 0000000..9d665a0 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_exceptions_g.h @@ -0,0 +1,39 @@ + +/******************************************************************* +* +* CAUTION: This file is automatically generated by HSI. +* Version: 2019.1.3 +* DO NOT EDIT. +* +* Copyright (C) 2010-2023 Xilinx, Inc. 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 +*XILINX 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. +* +*Except as contained in this notice, the name of the Xilinx shall not be used +*in advertising or otherwise to promote the sale, use or other dealings in +*this Software without prior written authorization from Xilinx. +* + +* +* Description: Exception Handling Header for MicroBlaze Processor +* +*******************************************************************/ + +#define MICROBLAZE_EXCEPTIONS_ENABLED 1 +#define MICROBLAZE_CAN_HANDLE_EXCEPTIONS_IN_DELAY_SLOTS + + diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_exceptions_i.h b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_exceptions_i.h new file mode 100644 index 0000000..b31b257 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_exceptions_i.h @@ -0,0 +1,83 @@ +/****************************************************************************** +* +* Copyright (C) 2012 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file microblaze_exceptions_i.h +* +* This header file contains defines for structures used by the microblaze +* hardware exception handler. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Date     Changes
+* ----- -------- -----------------------------------------------
+* 1.00a 06/24/04 First release
+* 
+* +******************************************************************************/ + +#ifndef MICROBLAZE_EXCEPTIONS_I_H /* prevent circular inclusions */ +#define MICROBLAZE_EXCEPTIONS_I_H /* by using protection macros */ + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_exception.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct +{ + Xil_ExceptionHandler Handler; + void *CallBackRef; +} MB_ExceptionVectorTableEntry; + +/* Exception IDs */ +#define XEXC_ID_FSL 0U +#define XEXC_ID_UNALIGNED_ACCESS 1U +#define XEXC_ID_ILLEGAL_OPCODE 2U +#define XEXC_ID_M_AXI_I_EXCEPTION 3U +#define XEXC_ID_IPLB_EXCEPTION 3U +#define XEXC_ID_M_AXI_D_EXCEPTION 4U +#define XEXC_ID_DPLB_EXCEPTION 4U +#define XEXC_ID_DIV_BY_ZERO 5U +#define XEXC_ID_FPU 6U +#define XEXC_ID_STACK_VIOLATION 7U +#define XEXC_ID_MMU 7U + +void microblaze_register_exception_handler(u32 ExceptionId, Xil_ExceptionHandler Handler, void *DataPtr); + +#ifdef __cplusplus +} +#endif +#endif /* end of protection macro */ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_flush_cache_ext.S b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_flush_cache_ext.S new file mode 100644 index 0000000..6e7ff22 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_flush_cache_ext.S @@ -0,0 +1,70 @@ +/****************************************************************************** +* +* Copyright (C) 2008 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************** +* +* microblaze_flush_cache_ext() +* +* Flush the entire L2 Cache +* +* +*******************************************************************************/ + +#include "xparameters.h" +#include "microblaze_instructions.h" + +#define XPAR_MICROBLAZE_EXT_CACHE_LINE_LEN 16 + +#define CACHEABLE_REGION_SIZE (XPAR_MICROBLAZE_DCACHE_HIGHADDR - XPAR_MICROBLAZE_DCACHE_BASEADDR) + + + .text + .globl microblaze_flush_cache_ext + .ent microblaze_flush_cache_ext + .align 2 + +microblaze_flush_cache_ext: + +#if ((XPAR_MICROBLAZE_INTERCONNECT==3) && (XPAR_MICROBLAZE_USE_DCACHE==1)) + ADDIK r5, r0, XPAR_MICROBLAZE_DCACHE_BASEADDR & (-(4 * XPAR_MICROBLAZE_DCACHE_LINE_LEN)) + + ADDIK r6, r0, CACHEABLE_REGION_SIZE-(4 * XPAR_MICROBLAZE_EXT_CACHE_LINE_LEN) + ANDI r6, r6, -(4 * XPAR_MICROBLAZE_EXT_CACHE_LINE_LEN) + +Loop_start: + wdc.ext.flush r5, r6 +#if defined (__arch64__) + addlik r6, r6,-(4 * XPAR_MICROBLAZE_EXT_CACHE_LINE_LEN) + beagei r6, Loop_start +#else + bgtid r6,Loop_start + addik r6, r6,-(4 * XPAR_MICROBLAZE_EXT_CACHE_LINE_LEN) +#endif +#endif + rtsd r15, 8 + nop + .end microblaze_flush_cache_ext diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_flush_cache_ext_range.S b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_flush_cache_ext_range.S new file mode 100644 index 0000000..23fbdc2 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_flush_cache_ext_range.S @@ -0,0 +1,76 @@ +/****************************************************************************** +* +* Copyright (C) 2008 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************** +* +* microblaze_flush_cache_ext_range (unsigned int cacheaddr, unsigned int len) +* +*Flush a L2 Cache range +* +*Parameters: +* 'cacheaddr' - address in the L2 cache where the flush begins +* 'len ' - length (in bytes) worth of L2 cache to be flushed +* +*******************************************************************************/ + +#include "xparameters.h" +#include "microblaze_instructions.h" + +#define XPAR_MICROBLAZE_EXT_CACHE_LINE_LEN 16 + + .text + .globl microblaze_flush_cache_ext_range + .ent microblaze_flush_cache_ext_range + .align 2 + +microblaze_flush_cache_ext_range: +#if ((XPAR_MICROBLAZE_INTERCONNECT==3) && (XPAR_MICROBLAZE_USE_DCACHE==1)) + beqi r6, Loop_done + + ADDIK r6, r6, -1 + ADD r6, r5, r6 + + ANDI r6, r6, -(4 * XPAR_MICROBLAZE_EXT_CACHE_LINE_LEN) + ANDI r5, r5, -(4 * XPAR_MICROBLAZE_EXT_CACHE_LINE_LEN) + + RSUBK r6, r5, r6 +Loop_start: + wdc.ext.flush r5, r6 +#if defined (__arch64__ ) + addlik r6, r6, -(4 * XPAR_MICROBLAZE_EXT_CACHE_LINE_LEN) + beagei r6, Loop_start +#else + bneid r6, Loop_start + addik r6, r6, -(4 * XPAR_MICROBLAZE_EXT_CACHE_LINE_LEN) +#endif + +Loop_done: +#endif + rtsd r15, 8 + nop + + .end microblaze_flush_cache_ext_range diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_flush_dcache.S b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_flush_dcache.S new file mode 100644 index 0000000..4426532 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_flush_dcache.S @@ -0,0 +1,74 @@ +/****************************************************************************** +* +* Copyright (C) 2008 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************** +* +* +* microblaze_flush_dcache() +* +* Flush the L1 DCache +* +*******************************************************************************/ + +#include "xparameters.h" +#include "microblaze_instructions.h" + +#define MICROBLAZE_MSR_DCACHE_ENABLE 0x00000080 +#define MICROBLAZE_MSR_INTR_ENABLE 0x00000002 + +#ifndef XPAR_MICROBLAZE_DCACHE_LINE_LEN +#define XPAR_MICROBLAZE_DCACHE_LINE_LEN 1 +#endif + + .text + .globl microblaze_flush_dcache + .ent microblaze_flush_dcache + .align 2 + +microblaze_flush_dcache: +#if (XPAR_MICROBLAZE_USE_DCACHE==1) && (XPAR_MICROBLAZE_ALLOW_DCACHE_WR==1) + ADDIK r5, r0, XPAR_MICROBLAZE_DCACHE_BASEADDR & (-(4 * XPAR_MICROBLAZE_DCACHE_LINE_LEN)) /* Align to cache line */ + ADDIK r6, r5, XPAR_MICROBLAZE_DCACHE_BYTE_SIZE & (-(4 * XPAR_MICROBLAZE_DCACHE_LINE_LEN)) /* Compute end */ + +L_start: + wdc.flush r5, r0 /* Flush the Cache */ + + CMPU r18, r5, r6 /* Are we at the end? */ + BLEI r18, L_done + +#if defined (__arch64__ ) + addlik r5, r5, (XPAR_MICROBLAZE_DCACHE_LINE_LEN * 4) /* Increment the address by 4 */ + BRI L_start +#else + brid L_start /* Branch to the beginning of the loop */ + addik r5, r5, (XPAR_MICROBLAZE_DCACHE_LINE_LEN * 4) /* Increment the addrees by 4 (delay slot) */ +#endif +L_done: +#endif + rtsd r15, 8 /* Return */ + nop + .end microblaze_flush_dcache diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_flush_dcache_range.S b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_flush_dcache_range.S new file mode 100644 index 0000000..0692607 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_flush_dcache_range.S @@ -0,0 +1,120 @@ +/****************************************************************************** +* +* Copyright (C) 2008 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************** +* +* microblaze_flush_dcache_range (unsigned int cacheaddr, unsigned int len) +* +* Flush a L1 DCache range +* +* Parameters: +* 'cacheaddr' - address in the Dcache where the flush begins +* 'len ' - length (in bytes) worth of Dcache to be flushed +* +*******************************************************************************/ + +#include "xparameters.h" +#include "microblaze_instructions.h" + +#define MICROBLAZE_MSR_DCACHE_ENABLE 0x00000080 +#define MICROBLAZE_MSR_INTR_ENABLE 0x00000002 + +#ifndef XPAR_MICROBLAZE_DCACHE_LINE_LEN +#define XPAR_MICROBLAZE_DCACHE_LINE_LEN 1 +#endif + +#ifndef XPAR_MICROBLAZE_DCACHE_USE_WRITEBACK +#define MB_VERSION_LT_v720 +#define MB_HAS_WRITEBACK_SET 0 +#else +#define MB_HAS_WRITEBACK_SET XPAR_MICROBLAZE_DCACHE_USE_WRITEBACK +#endif + + .text + .globl microblaze_flush_dcache_range + .ent microblaze_flush_dcache_range + .align 2 + +microblaze_flush_dcache_range: +#if (XPAR_MICROBLAZE_USE_DCACHE==1) && (XPAR_MICROBLAZE_ALLOW_DCACHE_WR==1) + +#ifdef MB_VERSION_LT_v720 /* Disable Dcache and interrupts before invalidating */ + mfs r9, rmsr + andi r10, r9, ~(MICROBLAZE_MSR_DCACHE_ENABLE | MICROBLAZE_MSR_INTR_ENABLE) + mts rmsr, r10 +#endif + + beqi r6, L_done /* Skip loop if size is zero */ + + ADD r6, r5, r6 /* Compute end address */ + ADDIK r6, r6, -1 + + ANDI r6, r6, -(4 * XPAR_MICROBLAZE_DCACHE_LINE_LEN) /* Align end down to cache line */ + ANDI r5, r5, -(4 * XPAR_MICROBLAZE_DCACHE_LINE_LEN) /* Align start down to cache line */ + +#if MB_HAS_WRITEBACK_SET == 0 /* Use a different scheme for MB version < v7.20 or when caches are write-through */ + +L_start: + CMPU r18, r5, r6 /* Are we at the end? */ + BLTI r18, L_done + + wdc r5, r0 /* Invalidate the cache line */ + +#if defined (__arch64__ ) + addlik r5, r5, (XPAR_MICROBLAZE_DCACHE_LINE_LEN * 4) /* Increment the address by 4 */ + breai L_start /* Branch to the beginning of the loop */ +#else + brid L_start /* Branch to the beginning of the loop */ + addik r5, r5, (XPAR_MICROBLAZE_DCACHE_LINE_LEN * 4) /* Increment the addrees by 4 (delay slot) */ +#endif +#else + RSUBK r6, r5, r6 + /* r6 will now contain (count of bytes - (4 * XPAR_MICROBLAZE_DCACHE_LINE_LEN)) */ +L_start: + wdc.flush r5, r6 /* Flush the cache line */ +#if defined (__arch64__ ) + addlik r6, r6, -(XPAR_MICROBLAZE_DCACHE_LINE_LEN * 4) + beagei r6, L_start +#else + bneid r6, L_start + addik r6, r6, -(XPAR_MICROBLAZE_DCACHE_LINE_LEN * 4) +#endif +#endif + +L_done: + rtsd r15, 8 +#ifdef MB_VERSION_LT_v720 /* restore MSR only for MB version < v7.20 */ + mts rmsr, r9 +#else + nop +#endif + +#else + rtsd r15, 8 /* Return */ + nop +#endif + .end microblaze_flush_dcache_range diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_init_dcache_range.S b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_init_dcache_range.S new file mode 100644 index 0000000..5c035d1 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_init_dcache_range.S @@ -0,0 +1,82 @@ +/****************************************************************************** +* +* Copyright (C) 2006 - 2016 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************** +* +* microblaze_init_dcache_range (unsigned int cache_start, unsigned int cache_len) +* +* Invalidate dcache on the microblaze +* +* Parameters: +* 'cache_start' - address in the Dcache where invalidation begins +* 'cache_len' - length (in bytes) worth of Dcache to be invalidated +* +* +*******************************************************************************/ + +#include "xparameters.h" + +#define MICROBLAZE_MSR_DCACHE_ENABLE 0x00000080 +#define MICROBLAZE_MSR_INTR_ENABLE 0x00000002 + +#ifndef XPAR_MICROBLAZE_DCACHE_LINE_LEN +#define XPAR_MICROBLAZE_DCACHE_LINE_LEN 1 +#endif + + .text + .globl microblaze_init_dcache_range + .ent microblaze_init_dcache_range + .align 2 + +microblaze_init_dcache_range: +#if (XPAR_MICROBLAZE_USE_DCACHE==1) && (XPAR_MICROBLAZE_ALLOW_DCACHE_WR==1) + mfs r9, rmsr /* Disable Dcache and interrupts before invalidating */ + andi r10, r9, ~(MICROBLAZE_MSR_DCACHE_ENABLE | MICROBLAZE_MSR_INTR_ENABLE) + mts rmsr, r10 + + andi r5, r5, -(4 * XPAR_MICROBLAZE_DCACHE_LINE_LEN) /* Align to cache line */ + + add r6, r5, r6 /* Compute end */ + andi r6, r6, -(4 * XPAR_MICROBLAZE_DCACHE_LINE_LEN) /* Align to cache line */ + +L_start: + wdc r5, r0 /* Invalidate the Cache (delay slot) */ + + cmpu r18, r5, r6 /* Are we at the end ? */ + blei r18, L_done + + brid L_start /* Branch to the beginning of the loop */ + addik r5, r5, (XPAR_MICROBLAZE_DCACHE_LINE_LEN * 4) /* Increment the addrees by 4 (delay slot) */ + +L_done: + rtsd r15, 8 /* Return */ + mts rmsr, r9 +#else + rtsd r15, 8 /* Return */ + nop +#endif + .end microblaze_init_dcache_range diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_init_icache_range.S b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_init_icache_range.S new file mode 100644 index 0000000..431b827 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_init_icache_range.S @@ -0,0 +1,83 @@ +/****************************************************************************** +* +* Copyright (C) 2006 - 2016 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************** +* +* +* microblaze_init_icache_range (unsigned int cache_start, unsigned int cache_len) +* +* Invalidate icache on the microblaze +* +* Parameters: +* 'cache_start' - address in the Icache where invalidation begins +* 'cache_len' - length (in bytes) worth of Icache to be invalidated +* +* +*******************************************************************************/ + +#include "xparameters.h" + +#define MICROBLAZE_MSR_ICACHE_ENABLE 0x00000020 +#define MICROBLAZE_MSR_INTR_ENABLE 0x00000002 + +#ifndef XPAR_MICROBLAZE_ICACHE_LINE_LEN +#define XPAR_MICROBLAZE_ICACHE_LINE_LEN 1 +#endif + + .text + .globl microblaze_init_icache_range + .ent microblaze_init_icache_range + .align 2 + +microblaze_init_icache_range: +#if (XPAR_MICROBLAZE_USE_ICACHE==1) && (XPAR_MICROBLAZE_ALLOW_ICACHE_WR==1) + mfs r9, rmsr /* Disable Icache and interrupts before invalidating */ + andi r10, r9, ~(MICROBLAZE_MSR_ICACHE_ENABLE | MICROBLAZE_MSR_INTR_ENABLE) + mts rmsr, r10 + + andi r5, r5, -(4 * XPAR_MICROBLAZE_ICACHE_LINE_LEN) /* Align to cache line */ + + add r6, r5, r6 /* Compute end */ + andi r6, r6, -(4 * XPAR_MICROBLAZE_ICACHE_LINE_LEN) /* Align to cache line */ + +L_start: + wic r5, r0 /* Invalidate the Cache (delay slot) */ + + cmpu r18, r5, r6 /* Are we at the end ? */ + blei r18, L_done + + brid L_start /* Branch to the beginning of the loop */ + addik r5, r5, (XPAR_MICROBLAZE_ICACHE_LINE_LEN * 4) /* Increment the addrees by 4 (delay slot) */ + +L_done: + rtsd r15, 8 /* Return */ + mts rmsr, r9 +#else + rtsd r15, 8 /* Return */ + nop +#endif + .end microblaze_init_icache_range diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_instructions.h b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_instructions.h new file mode 100644 index 0000000..fdaa508 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_instructions.h @@ -0,0 +1,118 @@ +/****************************************************************************** +* +* Copyright (C) 2018-2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file microblaze_instructions.h +* +* It provides wrapper macros to call 32/64 bit variant of specific +* arithmetic/logical instructions, based on the processor in execution. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 6.8 	mus  	 10/09/18 First release
+*
+*
+* 
+* +******************************************************************************/ +#ifndef MICROBLAZE_INSTRUCTIONS_H /* prevent circular inclusions */ +#define MICROBLAZE_INSTRUCTIONS_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined (__arch64__) +#define ADDIK addlik +#define ADDK addlk +#define ADDI addli +#define ADD addl +#define ANDI andli +#define SUBK sublk +#define RSUBK rsublk +#define ORI orli +#define LI lli +#define LOAD ll +#define SI sli +#define STORE sl +#define BRLID brealid +#define BGTID beageid +#define BGEI beagei +#define BNEID beaneid +#define BLTI bealti +#define CMPU cmplu +#define BRID breaid +#define BNEID beaneid +#define BLEI bealei +#define BEQI beaeqi +#define BRI breai +#define XORI xorli +#define BNEI beanei +#define OR orl +#define BRALID brealid +#define XOR xorl +#else +#define ADDIK addik +#define ADDK addk +#define ADDI addi +#define ADD add +#define ANDI andi +#define SUBK subk +#define RSUBK rsubk +#define ORI ori +#define LI lwi +#define LOAD lw +#define SI swi +#define STORE sw +#define BRLID brlid +#define BGTID bgtid +#define BGEI bgei +#define BNEID bneid +#define BLTI blti +#define CMPU cmpu +#define BRID brid +#define BNEID bneid +#define BLEI blei +#define BEQI beqi +#define BRI bri +#define XORI xori +#define BNEI bnei +#define OR or +#define BRALID bralid +#define XOR xor +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* MICROBLAZE_INSTRUCTIONS_H */ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_interrupt_handler.c b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_interrupt_handler.c new file mode 100644 index 0000000..b948e13 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_interrupt_handler.c @@ -0,0 +1,115 @@ +/****************************************************************************** +* +* Copyright (C) 2004 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file microblaze_interrupt_handler.c +* +* This file contains the standard interrupt handler for the MicroBlaze processor. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Date     Changes
+* ----- -------- -----------------------------------------------
+* 1.00b 10/03/03 First release
+* 
+* +******************************************************************************/ + + +/***************************** Include Files *********************************/ + +#include "xil_exception.h" +#include "microblaze_interrupts_i.h" + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + +void __interrupt_handler (void) __attribute__ ((interrupt_handler)); +void microblaze_register_handler(XInterruptHandler Handler, void *DataPtr); + +/************************** Variable Definitions *****************************/ + +extern MB_InterruptVectorTableEntry MB_InterruptVectorTable[MB_INTERRUPT_VECTOR_TABLE_ENTRIES]; +/*****************************************************************************/ +/** +* +* This function is the standard interrupt handler used by the MicroBlaze processor. +* It saves all volatile registers, calls the users top level interrupt handler. +* When this returns, it restores all registers, and returns using a rtid instruction. +* +* @param +* +* None +* +* @return +* +* None. +* +* @note +* +* None. +* +******************************************************************************/ +void __interrupt_handler(void) +{ + /* The compiler saves all volatiles and the MSR */ + (void)MB_InterruptVectorTable[0].Handler(MB_InterruptVectorTable[0].CallBackRef); + /* The compiler restores all volatiles and MSR, and returns from interrupt */ +} + + +/*****************************************************************************/ +/** +* +* Registers a top-level interrupt handler for the MicroBlaze. The +* argument provided in this call as the DataPtr is used as the argument +* for the handler when it is called. +* +* @param Handler: Top level handler. +* @param DataPtr: a reference to data that will be passed to the handler +* when it gets called. + +* @return None. +* +* +****************************************************************************/ +void microblaze_register_handler(XInterruptHandler Handler, void *DataPtr) +{ + MB_InterruptVectorTable[0].Handler = Handler; + MB_InterruptVectorTable[0].CallBackRef = DataPtr; +} diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_interrupts_g.c b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_interrupts_g.c new file mode 100644 index 0000000..07312aa --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_interrupts_g.c @@ -0,0 +1,51 @@ + +/******************************************************************* +* +* CAUTION: This file is automatically generated by HSI. +* Version: 2019.1.3 +* DO NOT EDIT. +* +* Copyright (C) 2010-2023 Xilinx, Inc. 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 +*XILINX 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. +* +*Except as contained in this notice, the name of the Xilinx shall not be used +*in advertising or otherwise to promote the sale, use or other dealings in +*this Software without prior written authorization from Xilinx. +* + +* +* Description: Interrupt Handler Table for MicroBlaze Processor +* +*******************************************************************/ + +#include "microblaze_interrupts_i.h" +#include "xparameters.h" + + +extern void XIntc_DeviceInterruptHandler (void *); + +/* +* The interrupt handler table for microblaze processor +*/ + +MB_InterruptVectorTableEntry MB_InterruptVectorTable[] = +{ +{ XIntc_DeviceInterruptHandler, + (void*) XPAR_AXI_INTC_DEVICE_ID} +}; + diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_interrupts_i.h b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_interrupts_i.h new file mode 100644 index 0000000..c5465ad --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_interrupts_i.h @@ -0,0 +1,73 @@ +/****************************************************************************** +* +* Copyright (C) 2008 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file microblaze_interrupts_i.h +* +* This header file contains identifiers and low-level driver functions (or +* macros) that can be used to access the device. The user should refer to the +* hardware device specification for more details of the device operation. +* High-level driver functions are defined in xintc.h. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Date     Changes
+* ----- -------- -----------------------------------------------
+* 1.00b 10/03/03 First release
+* 
+* +******************************************************************************/ + +#ifndef MICROBLAZE_INTERRUPTS_I_H /* prevent circular inclusions */ +#define MICROBLAZE_INTERRUPTS_I_H /* by using protection macros */ + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_exception.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct +{ + XInterruptHandler Handler; + void *CallBackRef; +} MB_InterruptVectorTableEntry; + +#define MB_INTERRUPT_VECTOR_TABLE_ENTRIES 1 + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_invalidate_cache_ext.S b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_invalidate_cache_ext.S new file mode 100644 index 0000000..573b054 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_invalidate_cache_ext.S @@ -0,0 +1,69 @@ +/****************************************************************************** +* +* Copyright (C) 2008 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************** +* +* microblaze_invalidate_cache_ext() +* +*Invalidate the entire L2 Cache +* +* +*******************************************************************************/ + +#include "xparameters.h" +#include "microblaze_instructions.h" + +#define XPAR_MICROBLAZE_EXT_CACHE_LINE_LEN 16 +#define CACHEABLE_REGION_SIZE (XPAR_MICROBLAZE_DCACHE_HIGHADDR - XPAR_MICROBLAZE_DCACHE_BASEADDR) + + .text + .globl microblaze_invalidate_cache_ext + .ent microblaze_invalidate_cache_ext + .align 2 + +microblaze_invalidate_cache_ext: + +#if ((XPAR_MICROBLAZE_INTERCONNECT==3) && (XPAR_MICROBLAZE_USE_DCACHE==1)) + ADDIK r5, r0, XPAR_MICROBLAZE_DCACHE_BASEADDR & (-(4 * XPAR_MICROBLAZE_EXT_CACHE_LINE_LEN)) + + ADDIK r6, r0, CACHEABLE_REGION_SIZE-(4 * XPAR_MICROBLAZE_EXT_CACHE_LINE_LEN) + ANDI r6, r6, -(4 * XPAR_MICROBLAZE_EXT_CACHE_LINE_LEN) + +Loop_start: + wdc.ext.clear r5, r6 +#if defined (__arch64__ ) + addlik r6, r6,-(4 * XPAR_MICROBLAZE_EXT_CACHE_LINE_LEN) + beagei r6, Loop_start +#else + bgtid r6,Loop_start + addik r6, r6,-(4 * XPAR_MICROBLAZE_EXT_CACHE_LINE_LEN) +#endif +#endif + rtsd r15, 8 + nop + + .end microblaze_invalidate_cache_ext diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_invalidate_cache_ext_range.S b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_invalidate_cache_ext_range.S new file mode 100644 index 0000000..e85af00 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_invalidate_cache_ext_range.S @@ -0,0 +1,77 @@ +/****************************************************************************** +* +* Copyright (C) 2008 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************** +* +* microblaze_invalidate_cache_ext_range (unsigned int cacheaddr, unsigned int len) +* +*Invalidate an L2 cache range +* +*Parameters: +* 'cacheaddr' - address in the L2 cache where invalidation begins +* 'len ' - length (in bytes) worth of Dcache to be invalidated +* +*******************************************************************************/ + +#include "xparameters.h" +#include "microblaze_instructions.h" + +#define XPAR_MICROBLAZE_EXT_CACHE_LINE_LEN 16 + + .text + .globl microblaze_invalidate_cache_ext_range + .ent microblaze_invalidate_cache_ext_range + .align 2 + +microblaze_invalidate_cache_ext_range: +#if ((XPAR_MICROBLAZE_INTERCONNECT==3) && (XPAR_MICROBLAZE_USE_DCACHE==1)) + beqi r6, Loop_done + + ADD r6, r5, r6 + ADDIK r6, r6, -1 + + ANDI r6, r6, -(4 * XPAR_MICROBLAZE_EXT_CACHE_LINE_LEN) + ANDI r5, r5, -(4 * XPAR_MICROBLAZE_EXT_CACHE_LINE_LEN) + + RSUBK r6, r5, r6 + +Loop_start: + wdc.ext.clear r5, r6 +#if defined (__arch64__ ) + addlik r6, r6, -(4 * XPAR_MICROBLAZE_EXT_CACHE_LINE_LEN) + beagei r6, Loop_start +#else + bneid r6, Loop_start + addik r6, r6, -(4 * XPAR_MICROBLAZE_EXT_CACHE_LINE_LEN) +#endif + +Loop_done: +#endif + rtsd r15, 8 + nop + + .end microblaze_invalidate_cache_ext_range diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_invalidate_dcache.S b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_invalidate_dcache.S new file mode 100644 index 0000000..5785b74 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_invalidate_dcache.S @@ -0,0 +1,92 @@ +/****************************************************************************** +* +* Copyright (C) 2008 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************** +* +* microblaze_invalidate_dcache() +* +* Invalidate the entire L1 DCache +* +* +*******************************************************************************/ + +#include "xparameters.h" +#include "microblaze_instructions.h" + +#define MICROBLAZE_MSR_DCACHE_ENABLE 0x00000080 +#define MICROBLAZE_MSR_INTR_ENABLE 0x00000002 + +#ifndef XPAR_MICROBLAZE_DCACHE_LINE_LEN +#define XPAR_MICROBLAZE_DCACHE_LINE_LEN 1 +#endif + +#ifndef XPAR_MICROBLAZE_DCACHE_USE_WRITEBACK +#define MB_VERSION_LT_v720 +#endif + + .text + .globl microblaze_invalidate_dcache + .ent microblaze_invalidate_dcache + .align 2 + +microblaze_invalidate_dcache: +#if (XPAR_MICROBLAZE_USE_DCACHE==1) && (XPAR_MICROBLAZE_ALLOW_DCACHE_WR==1) + +#ifdef MB_VERSION_LT_v720 /* Disable Dcache and interrupts before invalidating */ + mfs r9, rmsr + andi r10, r9, ~(MICROBLAZE_MSR_DCACHE_ENABLE | MICROBLAZE_MSR_INTR_ENABLE) + mts rmsr, r10 +#endif + ADDIK r5, r0, XPAR_MICROBLAZE_DCACHE_BASEADDR & (-(4 * XPAR_MICROBLAZE_DCACHE_LINE_LEN)) + ADDIK r6, r5, XPAR_MICROBLAZE_DCACHE_BYTE_SIZE & (-(4 * XPAR_MICROBLAZE_DCACHE_LINE_LEN)) /* Compute end */ + +L_start: + wdc r5, r0 /* Invalidate the Cache */ + + CMPU r18, r5, r6 /* Are we at the end? */ + BLEI r18, L_done + +#if defined (__arch64__ ) + addlik r5, r5, (XPAR_MICROBLAZE_DCACHE_LINE_LEN * 4) /* Increment the address by 4 */ + breai L_start +#else + brid L_start /* Branch to the beginning of the loop */ + addik r5, r5, (XPAR_MICROBLAZE_DCACHE_LINE_LEN * 4) /* Increment the addrees by 4 (delay slot) */ +#endif +L_done: + rtsd r15, 8 /* Return */ +#ifdef MB_VERSION_LT_v720 /* restore MSR only for MB version < v7.20 */ + mts rmsr, r9 +#else + nop +#endif + +#else + rtsd r15, 8 /* Return */ + nop +#endif + .end microblaze_invalidate_dcache diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_invalidate_dcache_range.S b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_invalidate_dcache_range.S new file mode 100644 index 0000000..804919e --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_invalidate_dcache_range.S @@ -0,0 +1,124 @@ +/****************************************************************************** +* +* Copyright (C) 2008 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************** +* +* +* microblaze_invalidate_dcache_range (unsigned int cacheaddr, unsigned int len) +* +* Invalidate a Dcache range +* +* Parameters: +* 'cacheaddr' - address in the Dcache where invalidation begins +* 'len ' - length (in bytes) worth of Dcache to be invalidated +* +* +*******************************************************************************/ + +#include "xparameters.h" +#include "microblaze_instructions.h" + +#define MICROBLAZE_MSR_DCACHE_ENABLE 0x00000080 +#define MICROBLAZE_MSR_INTR_ENABLE 0x00000002 + +#ifndef XPAR_MICROBLAZE_DCACHE_LINE_LEN +#define XPAR_MICROBLAZE_DCACHE_LINE_LEN 1 +#endif + +#ifndef XPAR_MICROBLAZE_DCACHE_USE_WRITEBACK +#define MB_VERSION_LT_v720 +#define MB_HAS_WRITEBACK_SET 0 +#else +#define MB_HAS_WRITEBACK_SET XPAR_MICROBLAZE_DCACHE_USE_WRITEBACK +#endif + + .text + .globl microblaze_invalidate_dcache_range + .ent microblaze_invalidate_dcache_range + .align 2 + +microblaze_invalidate_dcache_range: +#if (XPAR_MICROBLAZE_USE_DCACHE==1) && (XPAR_MICROBLAZE_ALLOW_DCACHE_WR==1) + +#ifdef MB_VERSION_LT_v720 /* Disable Dcache and interrupts before invalidating */ + mfs r9, rmsr + andi r10, r9, ~(MICROBLAZE_MSR_DCACHE_ENABLE | MICROBLAZE_MSR_INTR_ENABLE) + mts rmsr, r10 +#endif + + BEQI r6, L_done /* Skip loop if size is zero */ + + ADD r6, r5, r6 /* Compute end address */ + ADDIK r6, r6, -1 + + ANDI r6, r6, -(4 * XPAR_MICROBLAZE_DCACHE_LINE_LEN) /* Align end down to cache line */ + ANDI r5, r5, -(4 * XPAR_MICROBLAZE_DCACHE_LINE_LEN) /* Align start down to cache line */ + +#if MB_HAS_WRITEBACK_SET == 0 /* Use a different scheme for MB version < v7.20 or when caches are write-through */ + +L_start: + CMPU r18, r5, r6 /* Are we at the end? */ + BLTI r18, L_done + + wdc r5, r0 + +#if defined (__arch64__ ) + addlik r5, r5, (XPAR_MICROBLAZE_DCACHE_LINE_LEN * 4) /* Increment the address by 4 */ + breai L_start /* Branch to the beginning of the loop */ +#else + brid L_start /* Branch to the beginning of the loop */ + addik r5, r5, (XPAR_MICROBLAZE_DCACHE_LINE_LEN * 4) /* Increment the addrees by 4 (delay slot) */ +#endif +#else + + RSUBK r6, r5, r6 + /* r6 will now contain (count of bytes - (4 * XPAR_MICROBLAZE_DCACHE_LINE_LEN)) */ +L_start: + wdc.clear r5, r6 /* Invalidate the cache line only if the address matches */ +#if defined (__arch64__ ) + addlik r6, r6, -(XPAR_MICROBLAZE_DCACHE_LINE_LEN * 4) + beagei r6, L_start +#else + bneid r6, L_start + addik r6, r6, -(XPAR_MICROBLAZE_DCACHE_LINE_LEN * 4) +#endif + +#endif + +L_done: + rtsd r15, 8 +#ifdef MB_VERSION_LT_v720 /* restore MSR only for MB version < v7.20 */ + mts rmsr, r9 +#else + nop +#endif + +#else + rtsd r15, 8 + nop +#endif + .end microblaze_invalidate_dcache_range diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_invalidate_icache.S b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_invalidate_icache.S new file mode 100644 index 0000000..4ecaa1a --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_invalidate_icache.S @@ -0,0 +1,93 @@ +/****************************************************************************** +* +* Copyright (C) 2008 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************** +* +* +* microblaze_invalidate_icache() +* +* Invalidate the entire ICache +* +* +*******************************************************************************/ + +#include "xparameters.h" +#include "microblaze_instructions.h" + +#define MICROBLAZE_MSR_ICACHE_ENABLE 0x00000020 +#define MICROBLAZE_MSR_INTR_ENABLE 0x00000002 + +#ifndef XPAR_MICROBLAZE_ICACHE_LINE_LEN +#define XPAR_MICROBLAZE_ICACHE_LINE_LEN 1 +#endif + +#ifndef XPAR_MICROBLAZE_DCACHE_USE_WRITEBACK +#define MB_VERSION_LT_v720 +#endif + + .text + .globl microblaze_invalidate_icache + .ent microblaze_invalidate_icache + .align 2 + +microblaze_invalidate_icache: +#if (XPAR_MICROBLAZE_USE_ICACHE==1) && (XPAR_MICROBLAZE_ALLOW_ICACHE_WR==1) + +#ifdef MB_VERSION_LT_v720 /* Disable Icache and interrupts before invalidating */ + mfs r9, rmsr + andi r10, r9, ~(MICROBLAZE_MSR_ICACHE_ENABLE | MICROBLAZE_MSR_INTR_ENABLE) + mts rmsr, r10 +#endif + ADDIK r5, r0, XPAR_MICROBLAZE_ICACHE_BASEADDR & (-(4 * XPAR_MICROBLAZE_ICACHE_LINE_LEN)) /* Align to cache line */ + ADDIK r6, r5, XPAR_MICROBLAZE_CACHE_BYTE_SIZE & (-(4 * XPAR_MICROBLAZE_ICACHE_LINE_LEN)) /* Compute end */ +L_start: + wic r5, r0 /* Invalidate the Cache */ + + CMPU r18, r5, r6 /* Are we at the end? */ + BLEI r18, L_done + +#if defined (__arch64__ ) + addlik r5, r5, (XPAR_MICROBLAZE_ICACHE_LINE_LEN * 4) /* Increment the address by 4 */ + breai L_start +#else + brid L_start /* Branch to the beginning of the loop */ + addik r5, r5, (XPAR_MICROBLAZE_ICACHE_LINE_LEN * 4) /* Increment the addrees by 4 (delay slot) */ +#endif +L_done: + rtsd r15, 8 /* Return */ + +#ifdef MB_VERSION_LT_v720 /* restore MSR only for MB version < v7.20 */ + mts rmsr, r9 +#else + nop +#endif + +#else + rtsd r15, 8 /* Return */ + nop +#endif + .end microblaze_invalidate_icache diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_invalidate_icache_range.S b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_invalidate_icache_range.S new file mode 100644 index 0000000..5182ac6 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_invalidate_icache_range.S @@ -0,0 +1,103 @@ +/****************************************************************************** +* +* Copyright (C) 2008 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************** +* +* +* microblaze_invalidate_icache_range(unsigned int cacheaddr, unsigned int len) +* +* Invalidate an ICache range +* +* Parameters: +* 'cacheaddr' - address in the Icache where invalidation begins +* 'len' - length (in bytes) worth of Icache to be invalidated +* +* +*******************************************************************************/ + +#include "xparameters.h" +#include "microblaze_instructions.h" + +#define MICROBLAZE_MSR_ICACHE_ENABLE 0x00000020 +#define MICROBLAZE_MSR_INTR_ENABLE 0x00000002 + +#ifndef XPAR_MICROBLAZE_ICACHE_LINE_LEN +#define XPAR_MICROBLAZE_ICACHE_LINE_LEN 1 +#endif + +#ifndef XPAR_MICROBLAZE_DCACHE_USE_WRITEBACK +#define MB_VERSION_LT_v720 +#endif + + .text + .globl microblaze_invalidate_icache_range + .ent microblaze_invalidate_icache_range + .align 2 + +microblaze_invalidate_icache_range: +#if (XPAR_MICROBLAZE_USE_ICACHE==1) && (XPAR_MICROBLAZE_ALLOW_ICACHE_WR==1) + +#ifdef MB_VERSION_LT_v720 /* Disable Icache and interrupts before invalidating */ + mfs r9, rmsr + andi r10, r9, ~(MICROBLAZE_MSR_ICACHE_ENABLE | MICROBLAZE_MSR_INTR_ENABLE) + mts rmsr, r10 +#endif + + BEQI r6, L_done /* Skip loop if size is zero */ + + ADD r6, r5, r6 /* Compute end address */ + ADDIK r6, r6, -1 + + ANDI r6, r6, -(4 * XPAR_MICROBLAZE_ICACHE_LINE_LEN) /* Align end down to cache line */ + ANDI r5, r5, -(4 * XPAR_MICROBLAZE_ICACHE_LINE_LEN) /* Align start down to cache line */ + +L_start: + CMPU r18, r5, r6 /* Are we at the end? */ + BLTI r18, L_done + + wic r5, r0 /* Invalidate the cache line */ + +#if defined (__arch64__ ) + addlik r5, r5, (XPAR_MICROBLAZE_ICACHE_LINE_LEN * 4) /* Increment the address by 4 */ + breai L_start /* Branch to the beginning of the loop */ +#else + brid L_start /* Branch to the beginning of the loop */ + addik r5, r5, (XPAR_MICROBLAZE_ICACHE_LINE_LEN * 4) /* Increment the addrees by 4 (delay slot) */ +#endif +L_done: + rtsd r15, 8 /* Return */ +#ifdef MB_VERSION_LT_v720 /* restore MSR only for MB version < v7.20 */ + mts rmsr, r9 +#else + nop +#endif + +#else + rtsd r15, 8 /* Return */ + nop +#endif +.end microblaze_invalidate_icache_range diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_scrub.S b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_scrub.S new file mode 100644 index 0000000..a7b32e9 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_scrub.S @@ -0,0 +1,207 @@ +/****************************************************************************** +* +* Copyright (C) 2012 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************** +* +* microblaze_scrub () +* +* Scrub LMB memory and all internal BRAMs (data cache, instruction cache, +* MMU UTLB and branch target cache) in MicroBlaze to reduce the possibility +* of an uncorrectable error when fault tolerance support is enabled. +* +* This routine assumes that the processor is in privileged mode when it is +* called, if the MMU is enabled. +* +* Call this routine regularly from a timer interrupt. +* +* Parameters: +* None +* +* +*******************************************************************************/ + +#include "xparameters.h" + +/* Define if fault tolerance is used */ +#ifdef XPAR_MICROBLAZE_FAULT_TOLERANT + #if XPAR_MICROBLAZE_FAULT_TOLERANT > 0 + #define FAULT_TOLERANT + #endif +#endif + +/* Define if LMB is used and can be scrubbed */ +#if defined(XPAR_MICROBLAZE_D_LMB) && \ + defined(XPAR_DLMB_CNTLR_BASEADDR) && \ + defined(XPAR_DLMB_CNTLR_HIGHADDR) + #if XPAR_MICROBLAZE_D_LMB == 1 + #define HAS_SCRUBBABLE_LMB + #define DLMB_MASK (XPAR_DLMB_CNTLR_HIGHADDR - XPAR_DLMB_CNTLR_BASEADDR) + #endif +#endif + +/* Set default cache line lengths */ +#ifndef XPAR_MICROBLAZE_DCACHE_LINE_LEN + #define XPAR_MICROBLAZE_DCACHE_LINE_LEN 4 +#endif + +#ifndef XPAR_MICROBLAZE_ICACHE_LINE_LEN + #define XPAR_MICROBLAZE_ICACHE_LINE_LEN 4 +#endif + +/* Define if internal Data Cache BRAMs are used */ +#if defined(XPAR_MICROBLAZE_USE_DCACHE) && defined(XPAR_MICROBLAZE_DCACHE_BYTE_SIZE) + #if XPAR_MICROBLAZE_USE_DCACHE == 1 && XPAR_MICROBLAZE_DCACHE_BYTE_SIZE > 1024 + #define HAS_BRAM_DCACHE + #define DCACHE_INCREMENT (XPAR_MICROBLAZE_DCACHE_LINE_LEN * 4) + #define DCACHE_MASK (XPAR_MICROBLAZE_DCACHE_BYTE_SIZE - 1) + #endif +#endif + +/* Define if internal Instruction Cache BRAMs are used */ +#if defined(XPAR_MICROBLAZE_USE_ICACHE) && defined(XPAR_MICROBLAZE_CACHE_BYTE_SIZE) + #if XPAR_MICROBLAZE_USE_ICACHE == 1 && XPAR_MICROBLAZE_CACHE_BYTE_SIZE > 1024 + #define HAS_BRAM_ICACHE + #define ICACHE_INCREMENT (XPAR_MICROBLAZE_ICACHE_LINE_LEN * 4) + #define ICACHE_MASK (XPAR_MICROBLAZE_CACHE_BYTE_SIZE - 1) + #endif +#endif + +/* Define if internal MMU UTLB BRAM is used */ +#ifdef XPAR_MICROBLAZE_USE_MMU + #if XPAR_MICROBLAZE_USE_MMU > 1 + #define HAS_BRAM_MMU_UTLB + #endif +#endif + +/* Define if internal BTC BRAM is used, and match BTC clear to a complete cache scrub */ +#if defined(XPAR_MICROBLAZE_USE_BRANCH_TARGET_CACHE) && \ + defined(XPAR_MICROBLAZE_BRANCH_TARGET_CACHE_SIZE) + #if XPAR_MICROBLAZE_USE_BRANCH_TARGET_CACHE == 1 + #if XPAR_MICROBLAZE_BRANCH_TARGET_CACHE_SIZE == 0 || \ + XPAR_MICROBLAZE_BRANCH_TARGET_CACHE_SIZE > 4 + #define HAS_BRAM_BRANCH_TARGET_CACHE + #ifdef HAS_BRAM_DCACHE + #define BTC_MASK_D (XPAR_MICROBLAZE_DCACHE_BYTE_SIZE/DCACHE_INCREMENT-1) + #else + #define BTC_MASK_D 256 + #endif + #ifdef HAS_BRAM_ICACHE + #define BTC_MASK_I (XPAR_MICROBLAZE_CACHE_BYTE_SIZE/ICACHE_INCREMENT-1) + #else + #define BTC_MASK_I 256 + #endif + #if BTC_MASK_D > BTC_MASK_I + #define BTC_MASK BTC_MASK_D + #else + #define BTC_MASK BTC_MASK_I + #endif + #endif + #endif +#endif + +/* Define index offsets to persistent data used by this routine */ +#define DLMB_INDEX_OFFSET 0 +#define DCACHE_INDEX_OFFSET 4 +#define ICACHE_INDEX_OFFSET 8 +#define MMU_INDEX_OFFSET 12 +#define BTC_CALL_COUNT_OFFSET 16 + + .text + .globl microblaze_scrub + .ent microblaze_scrub + .align 2 + +microblaze_scrub: +#ifdef FAULT_TOLERANT + la r6, r0, L_persistent_data /* Get pointer to data */ + +#ifdef HAS_SCRUBBABLE_LMB +L_dlmb: + lwi r5, r6, DLMB_INDEX_OFFSET /* Get dlmb index */ + lw r7, r5, r0 /* Load and store */ + sw r7, r5, r0 + addik r5, r5, 4 /* Increment and save dlmb index */ + andi r5, r5, DLMB_MASK + swi r5, r6, DLMB_INDEX_OFFSET +#endif /* HAS_SCRUBBABLE_LMB */ + +#ifdef HAS_BRAM_DCACHE +L_dcache: + lwi r5, r6, DCACHE_INDEX_OFFSET /* Get dcache line index */ + wdc r5, r0 /* Invalidate data cache line */ + addik r5, r5, DCACHE_INCREMENT /* Increment and save entry index */ + andi r5, r5, DCACHE_MASK + swi r5, r6, DCACHE_INDEX_OFFSET +#endif /* HAS_BRAM_DCACHE */ + +#ifdef HAS_BRAM_ICACHE +L_icache: + lwi r5, r6, ICACHE_INDEX_OFFSET /* Get icache line index */ + wic r5, r0 /* Invalidate data cache line */ + addik r5, r5, ICACHE_INCREMENT /* Increment and save entry index */ + andi r5, r5, ICACHE_MASK + swi r5, r6, ICACHE_INDEX_OFFSET +#endif /* HAS_BRAM_ICACHE */ + +#ifdef HAS_BRAM_MMU_UTLB +L_mmu: + lwi r5, r6, MMU_INDEX_OFFSET /* Get UTLB entry index */ + mts rtlbx, r5 /* Access next entry in UTLB */ + mts rtlbhi, r0 /* Clear the UTLB entry */ + + addik r5, r5, 1 /* Increment and save entry index */ + andi r5, r5, 0x3F + swi r5, r6, MMU_INDEX_OFFSET +#endif /* HAS_BRAM_MMU_UTLB */ + +#ifdef HAS_BRAM_BRANCH_TARGET_CACHE +L_btc: + lwi r5, r6, BTC_CALL_COUNT_OFFSET /* Get BTC call count offset */ + addik r5, r5, 1 /* Increment and save call count */ + andi r5, r5, BTC_MASK + swi r5, r6, BTC_CALL_COUNT_OFFSET + + bnei r5, L_skip_btc_scrub /* Skip scrub unless count wrap */ + bri 4 /* Clear branch target cache */ +L_skip_btc_scrub: +#endif /* HAS_BRAM_BRANCH_TARGET_CACHE */ + +#endif /* FAULT_TOLERANT */ +L_done: + rtsd r15, 8 /* Return */ + nop + .end microblaze_scrub + + /* Persistent data used by this routine */ + .data + .align 2 +L_persistent_data: + .long 0 /* dlmb index */ + .long 0 /* dcache index */ + .long 0 /* icache index */ + .long 0 /* mmu entry index */ + .long 0 /* btc call count */ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_sleep.c b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_sleep.c new file mode 100644 index 0000000..9677796 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_sleep.c @@ -0,0 +1,241 @@ +/****************************************************************************** +* +* Copyright (C) 2014-2017 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file microblaze_sleep.c +* +* Contains implementation of microblaze sleep function. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date	 Changes
+* ----- ---- -------- -------------------------------------------------------
+* 4.1   hk   04/18/14 Add sleep function.
+* 6.0   asa  08/15/16 Updated the sleep/usleep signature. Fix for CR#956899.
+* 6.6   srm  10/18/17 Updated sleep routines to support user configurable
+*                     implementation. Now sleep routines will use Axi Timer
+*                     or machine cycles as specified by the user.
+* 6.8   mus  10/04/18 FreeRTOS BSP alway use default method for sleep
+*                     implementation, It does not have user configurable sleep
+*                     implementation support, that is why FreeRTOS tcl does not
+*                     export XSLEEP_TIMER_IS_DEFAULT_TIMER macro to
+*                     xparameters.h. Modified code to always use default timer
+*                     path for FreeRTOS BSP, based on the "FREERTOS_BSP" macro.
+*                     It fixes CR#1012363.
+*
+* 
+* +* @note +* +* This file may contain architecture-dependent code. +* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "microblaze_sleep.h" +#include "bspconfig.h" + +/***************** Macros (Inline Functions) Definitions *********************/ + +#if defined (XSLEEP_TIMER_IS_AXI_TIMER) +#define COUNTS_PER_SECOND (SLEEP_TIMER_FREQUENCY) +#define COUNTS_PER_MSECOND (COUNTS_PER_SECOND / 1000) +#define COUNTS_PER_USECOND (COUNTS_PER_SECOND / 1000000) +#warning "May wait for more than the specified delay" +#elif defined (XSLEEP_TIMER_IS_DEFAULT_TIMER) || defined (FREERTOS_BSP) +#define ITERS_PER_SEC (XPAR_CPU_CORE_CLOCK_FREQ_HZ / 4) +#define ITERS_PER_MSEC (ITERS_PER_SEC / 1000) +#define ITERS_PER_USEC (ITERS_PER_MSEC / 1000) +#pragma message ("For the sleep routines, assembly instructions are used") +#endif + +#if defined (XSLEEP_TIMER_IS_DEFAULT_TIMER) || defined (FREERTOS_BSP) +static void sleep_common(u32 n, u32 iters) +{ + asm volatile ( + "1: \n\t" + "addik %1, %1, -1 \n\t" + "add r7, r0, %0 \n\t" + "2: \n\t" + "addik r7, r7, -1 \n\t" + "bneid r7, 2b \n\t" + "or r0, r0, r0 \n\t" + "bneid %1, 1b \n\t" + "or r0, r0, r0 \n\t" + : + : "r"(iters), "r"(n) + : "r0", "r7" + ); +} +#endif + +/*****************************************************************************/ +/** +* @brief Provides delay for requested duration. +* @param useconds- time in useconds. +* @return 0 +* +* @note Instruction cache should be enabled for this to work. +* +******************************************************************************/ +int usleep_MB(unsigned long useconds) +{ +#if defined (XSLEEP_TIMER_IS_DEFAULT_TIMER) || defined (FREERTOS_BSP) + sleep_common((u32)useconds, ITERS_PER_USEC); +#elif defined (XSLEEP_TIMER_IS_AXI_TIMER) + /* Start Axi timer */ + XTime_StartAxiTimer(); + Xil_SleepAxiTimer(useconds, COUNTS_PER_USECOND); +#endif + + return 0; +} + +/*****************************************************************************/ +/** +* @brief Provides delay for requested duration. +* @param seconds- time in useconds. +* @return 0 +* +* @note Instruction cache should be enabled for this to work. +* +******************************************************************************/ +unsigned sleep_MB(unsigned int seconds) +{ +#if defined (XSLEEP_TIMER_IS_DEFAULT_TIMER) || defined (FREERTOS_BSP) + sleep_common(seconds, ITERS_PER_SEC); +#elif defined (XSLEEP_TIMER_IS_AXI_TIMER) + /* Start Axi timer */ + XTime_StartAxiTimer(); + Xil_SleepAxiTimer(seconds, COUNTS_PER_SECOND); +#endif + + return 0; +} + +/*****************************************************************************/ +/** +* +* @brief Provides delay for requested duration.. +* +* @param MilliSeconds- Delay time in milliseconds. +* +* @return None. +* +* @note Instruction cache should be enabled for this to work. +* +******************************************************************************/ +void MB_Sleep(u32 MilliSeconds) +{ +#if defined (XSLEEP_TIMER_IS_DEFAULT_TIMER) || defined (FREERTOS_BSP) + sleep_common(MilliSeconds, ITERS_PER_MSEC); + +#elif defined (XSLEEP_TIMER_IS_AXI_TIMER) + /* Start Axi timer */ + XTime_StartAxiTimer(); + Xil_SleepAxiTimer(MilliSeconds, COUNTS_PER_MSECOND); +#endif +} + +/*****************************************************************************/ +/** + * + * @brief Provides delay for requested duration by using Axi Timer. + * + * @param delay - delay time in seconds/milli seconds/micro seconds. + * frequency - Number of counts per + * second/milli second/micro second. + * + * @return None. + * + * + ******************************************************************************/ +#if defined (XSLEEP_TIMER_IS_AXI_TIMER) +static void Xil_SleepAxiTimer(u32 delay, u64 frequency) +{ + u64 tEnd = 0U; + u64 tCur = 0U; + u32 TimeHighVal = 0U; + u32 TimeLowVal1 = 0U; + u32 TimeLowVal2 = 0U; + + TimeLowVal1 = Xil_In32((SLEEP_TIMER_BASEADDR) + + (XSLEEP_TIMER_AXITIMER_TCR_OFFSET)); + tEnd = (u64)TimeLowVal1 + ((u64)(delay) * frequency); + do + { + TimeLowVal2 = Xil_In32((SLEEP_TIMER_BASEADDR) + + (XSLEEP_TIMER_AXITIMER_TCR_OFFSET)); + if (TimeLowVal2 < TimeLowVal1) { + TimeHighVal++; + } + TimeLowVal1 = TimeLowVal2; + tCur = (((u64) TimeHighVal) << 32U) | (u64)TimeLowVal2; + }while (tCur < tEnd); +} + +/*****************************************************************************/ +/** + * + * @brief This API starts the Axi Timer only when the timer is not enabled. + * + * @param None. + * + * @return None. + * + * @note Instruction cache should be enabled for this to work. + * + ******************************************************************************/ + static void XTime_StartAxiTimer() + { + u32 ControlStatusReg; + + /* Checking if the timer is enabled */ + if(Xil_In32(SLEEP_TIMER_BASEADDR + XSLEEP_TIMER_AXITIMER_TCSR0_OFFSET) && + XSLEEP_TIMER_AXITIMER_CSR_ENABLE_TMR_MASK) + { + return; + } + /* + * Read the current register contents such that only the necessary bits + * of the register are modified in the following operations + */ + ControlStatusReg = Xil_In32(SLEEP_TIMER_BASEADDR + + XSLEEP_TIMER_AXITIMER_TCSR0_OFFSET); + /* + * Remove the reset condition such that the timer counter starts running + * with the value loaded from the compare register + */ + Xil_Out32((SLEEP_TIMER_BASEADDR + XSLEEP_TIMER_AXITIMER_TCSR0_OFFSET), + (ControlStatusReg | XSLEEP_TIMER_AXITIMER_CSR_ENABLE_TMR_MASK | + XSLEEP_TIMER_AXITIMER_CSR_AUTO_RELOAD_MASK)); + } +#endif diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_sleep.h b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_sleep.h new file mode 100644 index 0000000..929f811 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_sleep.h @@ -0,0 +1,129 @@ +/****************************************************************************** +* +* Copyright (C) 2014-2017 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file microblaze_sleep.h +* +* @addtogroup microblaze_sleep_routines Sleep Routines for Microblaze +* +* The microblaze_sleep.h file contains microblaze sleep APIs. These APIs +* provides delay for requested duration. +* +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 4.1   asa  04/18/14 Add sleep function - first release.
+* 6.6   srm  10/18/17 Added the Register offset definitions and Control/Status
+*                     Register bit masks of the Axi timer.
+*
+* 
+* +* @note +* The microblaze_sleep.h file may contain architecture-dependent items. +* +******************************************************************************/ + +#ifndef MICROBLAZE_SLEEP_H /* prevent circular inclusions */ +#define MICROBLAZE_SLEEP_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "mb_interface.h" +#include "xparameters.h" +#include "sleep.h" + +/************************** Constant Definitions *****************************/ + +#if defined (XSLEEP_TIMER_IS_AXI_TIMER) + +/** @name Register Offset Definitions + * Register offsets within the Axi timer counter, there are multiple + * timer counters within a single device + * @{ + */ +#define XSLEEP_TIMER_AXITIMER_TCSR0_OFFSET 0U /**< Control/Status register */ +#define XSLEEP_TIMER_AXITIMER_TLR_OFFSET 4U /**< Load register */ +#define XSLEEP_TIMER_AXITIMER_TCR_OFFSET 8U /**< Timer counter register */ +/* @} */ + +/** @name Control Status Register Bit Definitions + * Control Status Register bit masks + * Used to configure the Axi timer counter device. + * @{ + */ +#define XSLEEP_TIMER_AXITIMER_CSR_ENABLE_TMR_MASK 0x00000080U + /**< Enables only the specific timer */ +#define XSLEEP_TIMER_AXITIMER_CSR_AUTO_RELOAD_MASK 0x00000010U + /**< In compare mode, configures the timer + * counter to reload from the Load Register. + * The default mode causes the timer counter + * to hold when the compare value is hit. In + * capture mode, configures the timer counter + * to not hold the previous capture value if + * a new event occurs. The default mode cause + * the timer counter to hold the capture value + * until recognized.*/ +#define XSLEEP_TIMER_AXITIMER_CSR_LOAD_MASK 0x00000020U + /**< Loads the timer using the load value + * provided earlier in the Load Register, + * XSLEEP_TIMER_AXITIMER_TLR_OFFSET. */ +#define XSLEEP_TIMER_AXITIMER_CSR_INT_OCCURED_MASK 0x00000100U + /**< If bit is set, an interrupt has occured. + * If set and '1' is written to this bit + * position, bit is cleared.*/ +#define XSLEEP_TIMER_AXITIMER_CSR_ENABLE_TMR_MASK 0x00000080U + /**< Enables only the specific timer */ +/* @} */ + +/**************************** Type Definitions *******************************/ + +/************************** Function Prototypes ******************************/ + +static void Xil_SleepAxiTimer(u32 delay, u64 frequency); +static void XTime_StartAxiTimer(); +#endif +void MB_Sleep(u32 MilliSeconds) __attribute__((__deprecated__)); + + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** +* @} End of "addtogroup microblaze_sleep_routines". +*/ \ No newline at end of file diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_update_dcache.S b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_update_dcache.S new file mode 100644 index 0000000..98e1754 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_update_dcache.S @@ -0,0 +1,107 @@ +/****************************************************************************** +* +* Copyright (C) 2006 - 2016 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************** +* +* +* File : microblaze_update_dcache.s +* Date : 2003, September 24 +* Company: Xilinx +* Group : Emerging Software Technologies +* +* Summary: +* Update dcache on the microblaze. +* Takes in three parameters +* r5 : Cache Tag Line +* r6 : Cache Data +* r7 : Lock/Valid information +* Bit 30 is Lock [ 1 indicates locked ] +* Bit 31 is Valid [ 1 indicates valid ] +* +* -------------------------------------------------------------- +* | Lock | Valid | Effect +* -------------------------------------------------------------- +* | 0 | 0 | Invalidate Cache +* | 0 | 1 | Valid, but unlocked cacheline +* | 1 | 0 | Invalidate Cache, No effect of lock +* | 1 | 1 | Valid cache. Locked to a +* | | | particular addrees +* -------------------------------------------------------------- +* +* +**********************************************************************************/ +#include "xparameters.h" + +#ifndef XPAR_MICROBLAZE_DCACHE_LINE_LEN +#define XPAR_MICROBLAZE_DCACHE_LINE_LEN 1 +#endif + + .text + .globl microblaze_update_dcache + .ent microblaze_update_dcache + .align 2 +microblaze_update_dcache: +#if (XPAR_MICROBLAZE_USE_DCACHE==1) && (XPAR_MICROBLAZE_ALLOW_DCACHE_WR==1) + +#if XPAR_MICROBLAZE_DCACHE_LINE_LEN == 1 + +/* Read the MSR register into a temp register */ + mfs r18, rmsr + +/* Clear the dcache enable bit to disable the cache + Register r10,r18 are volatile registers and hence do not need to be saved before use */ + andi r10, r18, ~128 + mts rmsr, r10 + +/* Update the lock and valid info */ + andi r5, r5, 0xfffffffc + or r5, r5, r7 + +/* Update dcache */ + wdc r5, r6 + +/* Return */ + rtsd r15, 8 + mts rmsr, r18 + +#else + + /* The only valid usage of this routine for larger cache line lengths is to invalidate a data cache line + So call microblaze_init_dcache_range appropriately to do the job */ + + brid microblaze_init_dcache_range + addik r6, r0, (XPAR_MICROBLAZE_DCACHE_LINE_LEN * 4) + + /* We don't have a return instruction here. This is tail call optimization :) */ + +#endif /* XPAR_MICROBLAZE_DCACHE_LINE_LEN == 1 */ + +#else + rtsd r15, 8 + nop +#endif + .end microblaze_update_dcache diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_update_icache.S b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_update_icache.S new file mode 100644 index 0000000..f2f03eb --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/microblaze_update_icache.S @@ -0,0 +1,106 @@ +/****************************************************************************** +* +* Copyright (C) 2006 - 2016 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************** +* +* File : microblaze_update_icache.s +* Date : 2003, September 24 +* Company: Xilinx +* Group : Emerging Software Technologies +* +* Summary: +* Update icache on the microblaze. +* Takes in three parameters +* r5 : Cache Tag Line +* r6 : Cache Data +* r7 : Lock/Valid information +* Bit 30 is Lock [ 1 indicates locked ] +* Bit 31 is Valid [ 1 indicates valid ] +* +* -------------------------------------------------------------- +* | Lock | Valid | Effect +* -------------------------------------------------------------- +* | 0 | 0 | Invalidate Cache +* | 0 | 1 | Valid, but unlocked cacheline +* | 1 | 0 | Invalidate Cache, No effect of lock +* | 1 | 1 | Valid cache. Locked to a +* | | | particular addrees +* -------------------------------------------------------------- +* +* +**********************************************************************************/ +#include "xparameters.h" + +#ifndef XPAR_MICROBLAZE_ICACHE_LINE_LEN +#define XPAR_MICROBLAZE_ICACHE_LINE_LEN 1 +#endif + + .text + .globl microblaze_update_icache + .ent microblaze_update_icache + .align 2 +microblaze_update_icache: +#if (XPAR_MICROBLAZE_USE_ICACHE==1) && (XPAR_MICROBLAZE_ALLOW_ICACHE_WR==1) + +#if XPAR_MICROBLAZE_ICACHE_LINE_LEN == 1 + +/* Read the MSR register into a temp register */ + mfs r18, rmsr + +/* Clear the icache enable bit to disable the cache + Register r10,r18 are volatile registers and hence do not need to be saved before use */ + andi r10, r18, ~32 + mts rmsr, r10 + +/* Update the lock and valid info */ + andi r5, r5, 0xfffffffc + or r5, r5, r7 + +/* Update icache */ + wic r5, r6 + +/* Return */ + rtsd r15, 8 + mts rmsr, r18 + +#else + + /* The only valid usage of this routine for larger cache line lengths is to invalidate an instruction cache line + So call microblaze_init_icache_range appropriately to do the job */ + + brid microblaze_init_icache_range + addik r6, r0, (XPAR_MICROBLAZE_ICACHE_LINE_LEN * 4) + + /* We don't have a return instruction here. This is tail call optimization :) */ + +#endif /* XPAR_MICROBLAZE_ICACHE_LINE_LEN == 1 */ + +#else + rtsd r15, 8 + nop +#endif + .end microblaze_update_icache diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/outbyte.c b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/outbyte.c new file mode 100644 index 0000000..7bb3ecd --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/outbyte.c @@ -0,0 +1,12 @@ +#include "xparameters.h" +#ifdef __cplusplus +extern "C" { +#endif +void outbyte(char c); + +#ifdef __cplusplus +} +#endif + +void outbyte(char c) { +} diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/print.c b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/print.c new file mode 100644 index 0000000..da7e768 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/print.c @@ -0,0 +1,36 @@ +/* print.c -- print a string on the output device. + * + * Copyright (c) 1995 Cygnus Support + * + * The authors hereby grant permission to use, copy, modify, distribute, + * and license this software and its documentation for any purpose, provided + * that existing copyright notices are retained in all copies and that this + * notice is included verbatim in any distributions. No written agreement, + * license, or royalty fee is required for any of the authorized uses. + * Modifications to this software may be copyrighted by their authors + * and need not follow the licensing terms described here, provided that + * the new terms are clearly indicated on the first page of each file where + * they apply. + * + */ + +/* + * print -- do a raw print of a string + */ +#include "xil_printf.h" + +void print(const char8 *ptr) +{ +#if HYP_GUEST && EL1_NONSECURE && XEN_USE_PV_CONSOLE + XPVXenConsole_Write(ptr); +#else +#ifdef STDOUT_BASEADDRESS + while (*ptr != (char8)0) { + outbyte (*ptr); + ptr++; + } +#else +(void)ptr; +#endif +#endif +} diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/profile/Makefile b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/profile/Makefile new file mode 100644 index 0000000..e46e976 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/profile/Makefile @@ -0,0 +1,74 @@ +############################################################################### +# +# Copyright (C) 2002 - 2014 Xilinx, Inc. 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 +# XILINX 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. +# +# Except as contained in this notice, the name of the Xilinx shall not be used +# in advertising or otherwise to promote the sale, use or other dealings in +# this Software without prior written authorization from Xilinx. +# +############################################################################### +# +# Makefile for profiler +# +####################################################################### + +# PROFILE_ARCH_OBJS - Processor Architecture Dependent files defined here +include ../config.make + +AS=mb-as +COMPILER = $(CC) +ARCHIVER = mb-ar +CP = cp +COMPILER_FLAGS=-O2 +EXTRA_COMPILER_FLAGS= +LIB = libxil.a +DUMMYLIB = libxilprofile.a + +CC_FLAGS = $(subst -pg, , $(COMPILER_FLAGS)) +ECC_FLAGS = $(subst -pg, , $(EXTRA_COMPILER_FLAGS)) + +RELEASEDIR = ../../../../lib +INCLUDEDIR = ../../../../include +INCLUDES = -I./. -I${INCLUDEDIR} + +OBJS = _profile_init.o _profile_clean.o _profile_timer_hw.o profile_hist.o profile_cg.o +DUMMYOBJ = dummy.o +INCLUDEFILES = profile.h mblaze_nt_types.h _profile_timer_hw.h + +libs : reallibs dummylibs + +reallibs : $(OBJS) $(PROFILE_ARCH_OBJS) + $(ARCHIVER) -r $(RELEASEDIR)/$(LIB) $(OBJS) $(PROFILE_ARCH_OBJS) + +dummylibs : $(DUMMYOBJ) + $(ARCHIVER) -r $(RELEASEDIR)/$(DUMMYLIB) $(DUMMYOBJ) + +%.o:%.c + $(COMPILER) $(CC_FLAGS) $(ECC_FLAGS) -c $< -o $@ $(INCLUDES) + +%.o:%.S + $(COMPILER) $(CC_FLAGS) $(ECC_FLAGS) -c $< -o $@ $(INCLUDES) + +include: + $(CP) -rf $(INCLUDEFILES) $(INCLUDEDIR) + +clean: + rm -f $(OBJS) $(PROFILE_ARCH_OBJS) $(LIB) diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/profile/_profile_clean.c b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/profile/_profile_clean.c new file mode 100644 index 0000000..b1c61f8 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/profile/_profile_clean.c @@ -0,0 +1,43 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +#include "profile.h" +#include "_profile_timer_hw.h" +#include "xil_exception.h" + +void _profile_clean( void ); + +/* + * This function is the exit routine and is called by the crtinit, when the + * program terminates. The name needs to be changed later.. + */ +void _profile_clean( void ) +{ + Xil_ExceptionDisable(); + disable_timer(); +} diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/profile/_profile_init.c b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/profile/_profile_init.c new file mode 100644 index 0000000..050b0a7 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/profile/_profile_init.c @@ -0,0 +1,86 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +****************************************************************************** +* +* _program_init.c: +* Initialize the Profiling Structures. +* +******************************************************************************/ + +#include "profile.h" + +/* XMD Initializes the following Global Variables Value during Program + * Download with appropriate values. */ + +#ifdef PROC_MICROBLAZE + +extern s32 microblaze_init(void); + +#elif defined PROC_PPC + +extern s32 powerpc405_init(void); + +#else + +extern s32 cortexa9_init(void); + +#endif + +s32 profile_version = 1; /* Version of S/W Intrusive Profiling library */ + +u32 binsize = (u32)BINSIZE; /* Histogram Bin Size */ +u32 cpu_clk_freq = (u32)CPU_FREQ_HZ ; /* CPU Clock Frequency */ +u32 sample_freq_hz = (u32)SAMPLE_FREQ_HZ ; /* Histogram Sampling Frequency */ +u32 timer_clk_ticks = (u32)TIMER_CLK_TICKS ;/* Timer Clock Ticks for the Timer */ + +/* Structure for Storing the Profiling Data */ +struct gmonparam *_gmonparam = (struct gmonparam *)(0xffffffffU); +s32 n_gmon_sections = 1; + +/* This is the initialization code, which is called from the crtinit. */ + +void _profile_init( void ) +{ +/* print("Gmon Init called....\r\n") */ +/* putnum(n_gmon_sections) , print("\r\n") */ +/* if( _gmonparam == 0xffffffff ) */ +/* printf("Gmonparam is NULL !!\r\n") */ +/* for( i = 0, i < n_gmon_sections, i++ )[ */ +/* putnum( _gmonparam[i].lowpc) , print("\t") */ +/* putnum( _gmonparam[i].highpc) , print("\r\n") */ +/* putnum( _gmonparam[i].textsize ), print("\r\n") */ +/* putnum( _gmonparam[i].kcountsize * sizeof(unsigned short)), print("\r\n") */ +/* ] */ + +#ifdef PROC_MICROBLAZE + (void)microblaze_init(); +#elif defined PROC_PPC + powerpc405_init(); +#else + (void)cortexa9_init(); +#endif +} diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/profile/_profile_timer_hw.c b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/profile/_profile_timer_hw.c new file mode 100644 index 0000000..c8243e5 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/profile/_profile_timer_hw.c @@ -0,0 +1,383 @@ +/****************************************************************************** +* +* Copyright (C) 2004 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +****************************************************************************** +* +* _program_timer_hw.c: +* Timer related functions +* +******************************************************************************/ + +#include "profile.h" +#include "_profile_timer_hw.h" + +#include "xil_exception.h" + +#ifdef PROC_PPC +#include "xtime_l.h" +#include "xpseudo_asm.h" +#endif + +#ifdef TIMER_CONNECT_INTC +#include "xintc_l.h" +#include "xintc.h" +#endif /* TIMER_CONNECT_INTC */ + +/* #ifndef PPC_PIT_INTERRUPT */ +#if (!defined PPC_PIT_INTERRUPT && !defined PROC_CORTEXA9) +#include "xtmrctr_l.h" +#endif + +/* extern u32 timer_clk_ticks, */ + +#ifdef PROC_PPC405 +#ifdef PPC_PIT_INTERRUPT +s32 ppc_pit_init( void ); +#endif +s32 powerpc405_init() +#endif /* PROC_CORTEXA9 */ + +#ifdef PROC_PPC440 +#ifdef PPC_PIT_INTERRUPT +s32 ppc_dec_init( void ); +#endif +s32 powerpc405_init(void); +#endif /* PROC_PPC440 */ + +#if (!defined PPC_PIT_INTERRUPT && !defined PROC_CORTEXA9) +s32 opb_timer_init( void ); +#endif + +#ifdef PROC_MICROBLAZE +s32 microblaze_init(void); +#endif /* PROC_MICROBLAZE */ + +#ifdef PROC_CORTEXA9 +s32 scu_timer_init( void ); +s32 cortexa9_init(void); +#endif /* PROC_CORTEXA9 */ + + +/*-------------------------------------------------------------------- + * PowerPC Target - Timer related functions + *-------------------------------------------------------------------- */ +#ifdef PROC_PPC405 + + +/*-------------------------------------------------------------------- +* PowerPC PIT Timer Init. +* Defined only if PIT Timer is used for Profiling +* +*-------------------------------------------------------------------- */ +#ifdef PPC_PIT_INTERRUPT +int ppc_pit_init( void ) +{ + /* 1. Register Profile_intr_handler as Interrupt handler */ + /* 2. Set PIT Timer Interrupt and Enable it. */ + Xil_ExceptionRegisterHandler( XIL_EXCEPTION_ID_PIT_INT, + (Xil_ExceptionHandler)profile_intr_handler,NULL); + XTime_PITSetInterval( timer_clk_ticks ) ; + XTime_PITEnableAutoReload() ; + return 0; +} +#endif + + +/* -------------------------------------------------------------------- +* PowerPC Timer Initialization functions. +* For PowerPC, PIT and opb_timer can be used for Profiling. This +* is selected by the user in standalone BSP +* +*-------------------------------------------------------------------- */ +s32 powerpc405_init() +{ + Xil_ExceptionInit() ; + Xil_ExceptionDisableMask( XIL_EXCEPTION_NON_CRITICAL ) ; + + /* Initialize the Timer. + * 1. If PowerPC PIT Timer has to be used, initialize PIT timer. + * 2. Else use opb_timer. It can be directly connected or thru intc to PowerPC */ +#ifdef PPC_PIT_INTERRUPT + ppc_pit_init(); +#else +#ifdef TIMER_CONNECT_INTC + Xil_ExceptionRegisterHandler( XIL_EXCEPTION_ID_NON_CRITICAL_INT, + (Xil_ExceptionHandler)XIntc_DeviceInterruptHandler,NULL); + XIntc_RegisterHandler( INTC_BASEADDR, PROFILE_TIMER_INTR_ID, + (XInterruptHandler)profile_intr_handler,NULL); +#else + Xil_ExceptionRegisterHandler( XIL_EXCEPTION_ID_NON_CRITICAL_INT, + (Xil_ExceptionHandler)profile_intr_handler,NULL); +#endif + /* Initialize the timer with Timer Ticks */ + opb_timer_init() ; +#endif + + /* Enable Interrupts in the System, if Profile Timer is the only Interrupt + * in the System. */ +#ifdef ENABLE_SYS_INTR +#ifdef PPC_PIT_INTERRUPT + XTime_PITEnableInterrupt() ; +#elif TIMER_CONNECT_INTC + XIntc_MasterEnable( INTC_BASEADDR ); + XIntc_SetIntrSvcOption( INTC_BASEADDR, XIN_SVC_ALL_ISRS_OPTION); + XIntc_EnableIntr( INTC_BASEADDR, PROFILE_TIMER_INTR_MASK ); +#endif + Xil_ExceptionEnableMask( XIL_EXCEPTION_NON_CRITICAL ) ; +#endif + return 0; +} + +#endif /* PROC_PPC */ + + + +/*-------------------------------------------------------------------- + * PowerPC440 Target - Timer related functions + * -------------------------------------------------------------------- */ +#ifdef PROC_PPC440 + + +/*-------------------------------------------------------------------- + * PowerPC DEC Timer Init. + * Defined only if DEC Timer is used for Profiling + * + *-------------------------------------------------------------------- */ +#ifdef PPC_PIT_INTERRUPT +s32 ppc_dec_init( void ) +{ + /* 1. Register Profile_intr_handler as Interrupt handler */ + /* 2. Set DEC Timer Interrupt and Enable it. */ + Xil_ExceptionRegisterHandler( XIL_EXCEPTION_ID_DEC_INT, + (Xil_ExceptionHandler)profile_intr_handler,NULL); + XTime_DECSetInterval( timer_clk_ticks ) ; + XTime_DECEnableAutoReload() ; + return 0; +} +#endif + + +/*-------------------------------------------------------------------- + * PowerPC Timer Initialization functions. + * For PowerPC, DEC and opb_timer can be used for Profiling. This + * is selected by the user in standalone BSP + * + *-------------------------------------------------------------------- */ +s32 powerpc405_init(void) +{ + Xil_ExceptionInit(); + Xil_ExceptionDisableMask( XIL_EXCEPTION_NON_CRITICAL ) ; + + /* Initialize the Timer. + * 1. If PowerPC DEC Timer has to be used, initialize DEC timer. + * 2. Else use opb_timer. It can be directly connected or thru intc to PowerPC */ +#ifdef PPC_PIT_INTERRUPT + ppc_dec_init(); +#else +#ifdef TIMER_CONNECT_INTC + Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_NON_CRITICAL_INT, + (Xil_ExceptionHandler)XIntc_DeviceInterruptHandler,NULL); + + XIntc_RegisterHandler( INTC_BASEADDR, PROFILE_TIMER_INTR_ID, + (XInterruptHandler)profile_intr_handler,NULL); +#else + Xil_ExceptionRegisterHandler( XIL_EXCEPTION_ID_NON_CRITICAL_INT, + (Xil_ExceptionHandler)profile_intr_handler,NULL); + Xil_ExceptionRegisterHandler( XIL_EXCEPTION_ID_NON_CRITICAL_INT, + (Xil_ExceptionHandler)profile_intr_handler,NULL); +#endif + /* Initialize the timer with Timer Ticks */ + opb_timer_init() ; +#endif + + /* Enable Interrupts in the System, if Profile Timer is the only Interrupt + * in the System. */ +#ifdef ENABLE_SYS_INTR +#ifdef PPC_PIT_INTERRUPT + XTime_DECEnableInterrupt() ; +#elif TIMER_CONNECT_INTC + XIntc_MasterEnable( INTC_BASEADDR ); + XIntc_SetIntrSvcOption( INTC_BASEADDR, XIN_SVC_ALL_ISRS_OPTION); + XIntc_EnableIntr( INTC_BASEADDR, PROFILE_TIMER_INTR_MASK ); +#endif + Xil_ExceptionEnableMask( XEXC_NON_CRITICAL ) ; +#endif + return 0; +} + +#endif /* PROC_PPC440 */ + +/* -------------------------------------------------------------------- + * opb_timer Initialization for PowerPC and MicroBlaze. This function + * is not needed if DEC timer is used in PowerPC + * + *-------------------------------------------------------------------- */ +/* #ifndef PPC_PIT_INTERRUPT */ +#if (!defined PPC_PIT_INTERRUPT && !defined PROC_CORTEXA9) +s32 opb_timer_init( void ) +{ + /* set the number of cycles the timer counts before interrupting */ + XTmrCtr_SetLoadReg((u32)PROFILE_TIMER_BASEADDR, (u16)0, (u32)timer_clk_ticks); + + /* reset the timers, and clear interrupts */ + XTmrCtr_SetControlStatusReg((u32)PROFILE_TIMER_BASEADDR, (u16)0, + (u32)XTC_CSR_INT_OCCURED_MASK | (u32)XTC_CSR_LOAD_MASK ); + + /* start the timers */ + XTmrCtr_SetControlStatusReg((u32)PROFILE_TIMER_BASEADDR, (u16)0, (u32)XTC_CSR_ENABLE_TMR_MASK + | (u32)XTC_CSR_ENABLE_INT_MASK | (u32)XTC_CSR_AUTO_RELOAD_MASK | (u32)XTC_CSR_DOWN_COUNT_MASK); + return 0; +} +#endif + + +/*-------------------------------------------------------------------- + * MicroBlaze Target - Timer related functions + *-------------------------------------------------------------------- */ +#ifdef PROC_MICROBLAZE + +/* -------------------------------------------------------------------- + * Initialize the Profile Timer for MicroBlaze Target. + * For MicroBlaze, opb_timer is used. The opb_timer can be directly + * connected to MicroBlaze or connected through Interrupt Controller. + * + *-------------------------------------------------------------------- */ +s32 microblaze_init(void) +{ + /* Register profile_intr_handler + * 1. If timer is connected to Interrupt Controller, register the handler + * to Interrupt Controllers vector table. + * 2. If timer is directly connected to MicroBlaze, register the handler + * as Interrupt handler */ + Xil_ExceptionInit(); + +#ifdef TIMER_CONNECT_INTC + XIntc_RegisterHandler( INTC_BASEADDR, PROFILE_TIMER_INTR_ID, + (XInterruptHandler)profile_intr_handler,NULL); +#else + Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, + (Xil_ExceptionHandler)profile_intr_handler, + NULL) ; +#endif + + /* Initialize the timer with Timer Ticks */ + (void)opb_timer_init() ; + + /* Enable Interrupts in the System, if Profile Timer is the only Interrupt + * in the System. */ +#ifdef ENABLE_SYS_INTR +#ifdef TIMER_CONNECT_INTC + XIntc_MasterEnable((u32)INTC_BASEADDR ); + XIntc_SetIntrSvcOption( INTC_BASEADDR, XIN_SVC_ALL_ISRS_OPTION); + XIntc_EnableIntr( (u32)INTC_BASEADDR, PROFILE_TIMER_INTR_MASK ); + Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, + (Xil_ExceptionHandler)XIntc_DeviceInterruptHandler,NULL); +#endif + +#endif + + Xil_ExceptionEnable(); + + return 0; + +} + +#endif /* PROC_MICROBLAZE */ + + + +/* -------------------------------------------------------------------- + * Cortex A9 Target - Timer related functions + *-------------------------------------------------------------------- */ +#ifdef PROC_CORTEXA9 + +/* -------------------------------------------------------------------- + * Initialize the Profile Timer for Cortex A9 Target. + * The scu private timer is connected to the Scu GIC controller. + * + *-------------------------------------------------------------------- */ +s32 scu_timer_init( void ) +{ + /* set the number of cycles the timer counts before interrupting + * scu timer runs at half the cpu clock */ + XScuTimer_SetLoadReg(PROFILE_TIMER_BASEADDR, timer_clk_ticks/2U); + + /* clear any pending interrupts */ + XScuTimer_SetIntrReg(PROFILE_TIMER_BASEADDR, 1U); + + /* enable interrupts, auto-reload mode and start the timer */ + XScuTimer_SetControlReg(PROFILE_TIMER_BASEADDR, XSCUTIMER_CONTROL_IRQ_ENABLE_MASK | + XSCUTIMER_CONTROL_AUTO_RELOAD_MASK | XSCUTIMER_CONTROL_ENABLE_MASK); + + return 0; +} + +s32 cortexa9_init(void) +{ + + Xil_ExceptionInit(); + + XScuGic_DeviceInitialize(0); + + /* + * Connect the interrupt controller interrupt handler to the hardware + * interrupt handling logic in the processor. + */ + Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_IRQ_INT, + (Xil_ExceptionHandler)XScuGic_DeviceInterruptHandler, + NULL); + + /* + * Connect the device driver handler that will be called when an + * interrupt for the device occurs, the handler defined above performs + * the specific interrupt processing for the device. + */ + XScuGic_RegisterHandler(SCUGIC_CPU_BASEADDR, + PROFILE_TIMER_INTR_ID, + (Xil_ExceptionHandler)profile_intr_handler, + NULL); + + /* + * Enable the interrupt for scu timer. + */ + XScuGic_EnableIntr(SCUGIC_DIST_BASEADDR, PROFILE_TIMER_INTR_ID); + + /* + * Enable interrupts in the Processor. + */ + Xil_ExceptionEnableMask(XIL_EXCEPTION_IRQ); + + /* + * Initialize the timer with Timer Ticks + */ + (void)scu_timer_init() ; + + Xil_ExceptionEnable(); + + return 0; +} + +#endif /* PROC_CORTEXA9 */ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/profile/_profile_timer_hw.h b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/profile/_profile_timer_hw.h new file mode 100644 index 0000000..1647600 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/profile/_profile_timer_hw.h @@ -0,0 +1,308 @@ +/****************************************************************************** +* +* Copyright (C) 2004 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +****************************************************************************** +* +* _program_timer_hw.h: +* Timer related functions +* +******************************************************************************/ + +#ifndef PROFILE_TIMER_HW_H +#define PROFILE_TIMER_HW_H + +#include "profile.h" + +#ifdef PROC_PPC +#if defined __GNUC__ +# define SYNCHRONIZE_IO __asm__ volatile ("eieio") +#elif defined __DCC__ +# define SYNCHRONIZE_IO __asm volatile(" eieio") +#else +# define SYNCHRONIZE_IO +#endif +#endif + +#ifdef PROC_PPC +#define ProfIo_In32(InputPtr) { (*(volatile u32 *)(InputPtr)); SYNCHRONIZE_IO; } +#define ProfIo_Out32(OutputPtr, Value) { (*(volatile u32 *)(OutputPtr) = Value); SYNCHRONIZE_IO; } +#else +#define ProfIo_In32(InputPtr) (*(volatile u32 *)(InputPtr)); +#define ProfIo_Out32(OutputPtr, Value) { (*(volatile u32 *)(OutputPtr) = (Value)); } +#endif + +#define ProfTmrCtr_mWriteReg(BaseAddress, TmrCtrNumber, RegOffset, ValueToWrite)\ + ProfIo_Out32(((u32)(BaseAddress) + (u32)XTmrCtr_Offsets[(TmrCtrNumber)] + \ + (u32)(RegOffset)), (u32)(ValueToWrite)) + +#define ProfTimerCtr_mReadReg(BaseAddress, TmrCtrNumber, RegOffset) \ + ProfIo_In32((u32)(BaseAddress) + (u32)XTmrCtr_Offsets[(TmrCtrNumber)] + (u32)(RegOffset)) + +#define ProfTmrCtr_mSetControlStatusReg(BaseAddress, TmrCtrNumber, RegisterValue)\ + ProfTmrCtr_mWriteReg((BaseAddress), (TmrCtrNumber), XTC_TCSR_OFFSET, \ + (RegisterValue)) + +#define ProfTmrCtr_mGetControlStatusReg(BaseAddress, TmrCtrNumber) \ + ProfTimerCtr_mReadReg((u32)(BaseAddress), (TmrCtrNumber), XTC_TCSR_OFFSET) + + + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef PROC_PPC +#include "xexception_l.h" +#include "xtime_l.h" +#include "xpseudo_asm.h" +#endif + +#ifdef TIMER_CONNECT_INTC +#include "xintc_l.h" +#include "xintc.h" +#endif /* TIMER_CONNECT_INTC */ + +#if (!defined PPC_PIT_INTERRUPT && !defined PROC_CORTEXA9) +#include "xtmrctr_l.h" +#endif + +#ifdef PROC_CORTEXA9 +#include "xscutimer_hw.h" +#include "xscugic.h" +#endif + +extern u32 timer_clk_ticks ; + +/*-------------------------------------------------------------------- + * PowerPC Target - Timer related functions + *-------------------------------------------------------------------- */ +#ifdef PROC_PPC + +#ifdef PPC_PIT_INTERRUPT +u32 timer_lo_clk_ticks ; /* Clk ticks when Timer is disabled in CG */ +#endif + +#ifdef PROC_PPC440 +#define XREG_TCR_PIT_INTERRUPT_ENABLE XREG_TCR_DEC_INTERRUPT_ENABLE +#define XREG_TSR_PIT_INTERRUPT_STATUS XREG_TSR_DEC_INTERRUPT_STATUS +#define XREG_SPR_PIT XREG_SPR_DEC +#define XEXC_ID_PIT_INT XEXC_ID_DEC_INT +#endif + +/* -------------------------------------------------------------------- + * Disable the Timer - During Profiling + * + * For PIT Timer - + * 1. XTime_PITDisableInterrupt() ; + * 2. Store the remaining timer clk tick + * 3. Stop the PIT Timer + *-------------------------------------------------------------------- */ + +#ifdef PPC_PIT_INTERRUPT +#define disable_timer() \ + { \ + u32 val; \ + val=mfspr(XREG_SPR_TCR); \ + mtspr(XREG_SPR_TCR, val & (~XREG_TCR_PIT_INTERRUPT_ENABLE)); \ + timer_lo_clk_ticks = mfspr(XREG_SPR_PIT); \ + mtspr(XREG_SPR_PIT, 0); \ + } +#else +#define disable_timer() \ + { \ + u32 addr = (PROFILE_TIMER_BASEADDR) + XTmrCtr_Offsets[(0)] + XTC_TCSR_OFFSET; \ + u32 tmp_v = ProfIo_In32(addr); \ + tmp_v = tmp_v & (~XTC_CSR_ENABLE_TMR_MASK); \ + ProfIo_Out32((PROFILE_TIMER_BASEADDR) + XTmrCtr_Offsets[(0)] + XTC_TCSR_OFFSET, tmp_v); \ + } +#endif + + + +/* -------------------------------------------------------------------- + * Enable the Timer + * + * For PIT Timer - + * 1. Load the remaining timer clk ticks + * 2. XTime_PITEnableInterrupt() ; + *-------------------------------------------------------------------- */ +#ifdef PPC_PIT_INTERRUPT +#define enable_timer() \ + { \ + u32 val; \ + val=mfspr(XREG_SPR_TCR); \ + mtspr(XREG_SPR_PIT, timer_lo_clk_ticks); \ + mtspr(XREG_SPR_TCR, val | XREG_TCR_PIT_INTERRUPT_ENABLE); \ + } +#else +#define enable_timer() \ + { \ + u32 addr = (PROFILE_TIMER_BASEADDR) + XTmrCtr_Offsets[(0)] + XTC_TCSR_OFFSET; \ + u32 tmp_v = ProfIo_In32(addr); \ + tmp_v = tmp_v | XTC_CSR_ENABLE_TMR_MASK; \ + ProfIo_Out32((PROFILE_TIMER_BASEADDR) + XTmrCtr_Offsets[(0)] + XTC_TCSR_OFFSET, tmp_v); \ + } +#endif + + + +/* -------------------------------------------------------------------- + * Send Ack to Timer Interrupt + * + * For PIT Timer - + * 1. Load the timer clk ticks + * 2. Enable AutoReload and Interrupt + * 3. Clear PIT Timer Status bits + *-------------------------------------------------------------------- */ +#ifdef PPC_PIT_INTERRUPT +#define timer_ack() \ + { \ + u32 val; \ + mtspr(XREG_SPR_PIT, timer_clk_ticks); \ + mtspr(XREG_SPR_TSR, XREG_TSR_PIT_INTERRUPT_STATUS); \ + val=mfspr(XREG_SPR_TCR); \ + mtspr(XREG_SPR_TCR, val| XREG_TCR_PIT_INTERRUPT_ENABLE| XREG_TCR_AUTORELOAD_ENABLE); \ + } +#else +#define timer_ack() \ + { \ + u32 csr; \ + csr = ProfTmrCtr_mGetControlStatusReg(PROFILE_TIMER_BASEADDR, 0); \ + ProfTmrCtr_mSetControlStatusReg(PROFILE_TIMER_BASEADDR, 0, csr); \ + } +#endif + +/*-------------------------------------------------------------------- */ +#endif /* PROC_PPC */ +/* -------------------------------------------------------------------- */ + + + + +/* -------------------------------------------------------------------- + * MicroBlaze Target - Timer related functions + *-------------------------------------------------------------------- */ +#ifdef PROC_MICROBLAZE + +/* -------------------------------------------------------------------- + * Disable the Timer during Call-Graph Data collection + * + *-------------------------------------------------------------------- */ +#define disable_timer() \ + { \ + u32 Addr = ((u32)PROFILE_TIMER_BASEADDR); \ + Addr += (u32)XTmrCtr_Offsets[(u16)(0)]; \ + Addr += (u32)XTC_TCSR_OFFSET; \ + u32 tmp_v = ProfIo_In32(Addr); \ + tmp_v = tmp_v & (u32)(~XTC_CSR_ENABLE_TMR_MASK); \ + u32 OutAddr = (u32)PROFILE_TIMER_BASEADDR; \ + OutAddr += (u32)XTmrCtr_Offsets[(u16)(0)]; \ + OutAddr += (u32)XTC_TCSR_OFFSET; \ + ProfIo_Out32(OutAddr, (u32)tmp_v); \ + } + + +/* -------------------------------------------------------------------- + * Enable the Timer after Call-Graph Data collection + * + *-------------------------------------------------------------------- */ +#define enable_timer() \ + { \ + u32 Addr = ((u32)PROFILE_TIMER_BASEADDR); \ + Addr += (u32)XTmrCtr_Offsets[(u16)(0)]; \ + Addr += (u32)XTC_TCSR_OFFSET; \ + u32 tmp_v = (u32)ProfIo_In32(Addr); \ + tmp_v = tmp_v | (u32)XTC_CSR_ENABLE_TMR_MASK; \ + ProfIo_Out32((u32)(PROFILE_TIMER_BASEADDR) + (u32)XTmrCtr_Offsets[(u16)(0)] + (u32)XTC_TCSR_OFFSET, (u32)tmp_v); \ + } + + +/* -------------------------------------------------------------------- + * Send Ack to Timer Interrupt + * + *-------------------------------------------------------------------- */ +#define timer_ack() \ + { \ + u32 csr; \ + csr = ProfTmrCtr_mGetControlStatusReg((u32)PROFILE_TIMER_BASEADDR, (u16)0); \ + ProfTmrCtr_mSetControlStatusReg((u32)PROFILE_TIMER_BASEADDR, (u16)0, (u32)csr); \ + } + +/*-------------------------------------------------------------------- */ +#endif /* PROC_MICROBLAZE */ +/*-------------------------------------------------------------------- */ + +/* -------------------------------------------------------------------- + * Cortex A9 Target - Timer related functions + *-------------------------------------------------------------------- */ +#ifdef PROC_CORTEXA9 + +/* -------------------------------------------------------------------- + * Disable the Timer during Call-Graph Data collection + * + *-------------------------------------------------------------------- */ +#define disable_timer() \ +{ \ + u32 Reg; \ + Reg = Xil_In32(PROFILE_TIMER_BASEADDR + XSCUTIMER_CONTROL_OFFSET); \ + Reg &= (~XSCUTIMER_CONTROL_ENABLE_MASK);\ + Xil_Out32(PROFILE_TIMER_BASEADDR + XSCUTIMER_CONTROL_OFFSET, Reg);\ +} + + +/* -------------------------------------------------------------------- + * Enable the Timer after Call-Graph Data collection + * + *-------------------------------------------------------------------- */ +#define enable_timer() \ +{ \ + u32 Reg; \ + Reg = Xil_In32(PROFILE_TIMER_BASEADDR + XSCUTIMER_CONTROL_OFFSET); \ + Reg |= XSCUTIMER_CONTROL_ENABLE_MASK; \ + Xil_Out32(PROFILE_TIMER_BASEADDR + XSCUTIMER_CONTROL_OFFSET, Reg);\ +} + + +/* -------------------------------------------------------------------- + * Send Ack to Timer Interrupt + * + *-------------------------------------------------------------------- */ +#define timer_ack() \ +{ \ + Xil_Out32((u32)PROFILE_TIMER_BASEADDR + (u32)XSCUTIMER_ISR_OFFSET, \ + (u32)XSCUTIMER_ISR_EVENT_FLAG_MASK);\ +} + +/*-------------------------------------------------------------------- */ +#endif /* PROC_CORTEXA9 */ +/*-------------------------------------------------------------------- */ + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/profile/dummy.S b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/profile/dummy.S new file mode 100644 index 0000000..f4ff406 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/profile/dummy.S @@ -0,0 +1,60 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + + .globl dummy_f + +#ifdef PROC_MICROBLAZE + .text + .align 2 + .ent dummy_f + +dummy_f: + nop + + .end dummy_f +#endif + +#ifdef PROC_PPC + .section .text + .align 2 + .type dummy_f@function + +dummy_f: + b dummy_f + +#endif + +#ifdef PROC_CORTEXA9 + .section .text + .align 2 + .type dummy_f, %function + +dummy_f: + b dummy_f + +#endif diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/profile/mblaze_nt_types.h b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/profile/mblaze_nt_types.h new file mode 100644 index 0000000..807dda3 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/profile/mblaze_nt_types.h @@ -0,0 +1,50 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + + +#ifndef _MBLAZE_NT_TYPES_H +#define _MBLAZE_NT_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef char byte; +typedef short half; +typedef int word; +typedef unsigned char ubyte; +typedef unsigned short uhalf; +typedef unsigned int uword; +typedef ubyte boolean; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/profile/profile.h b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/profile/profile.h new file mode 100644 index 0000000..63f503a --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/profile/profile.h @@ -0,0 +1,127 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +#ifndef PROFILE_H +#define PROFILE_H 1 + +#include +#include "xil_types.h" +#include "profile_config.h" + +#ifdef PROC_MICROBLAZE +#include "mblaze_nt_types.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +void _system_init( void ) ; +void _system_clean( void ) ; +void mcount(u32 frompc, u32 selfpc); +void profile_intr_handler( void ) ; +void _profile_init( void ); + + + +/**************************************************************************** + * Profiling on hardware - Hash table maintained on hardware and data sent + * to xmd for gmon.out generation. + ****************************************************************************/ +/* + * histogram counters are unsigned shorts (according to the kernel). + */ +#define HISTCOUNTER u16 + +struct tostruct { + u32 selfpc; + s32 count; + s16 link; + u16 pad; +}; + +struct fromstruct { + u32 frompc ; + s16 link ; + u16 pad ; +} ; + +/* + * general rounding functions. + */ +#define ROUNDDOWN(x,y) (((x)/(y))*(y)) +#define ROUNDUP(x,y) ((((x)+(y)-1)/(y))*(y)) + +/* + * The profiling data structures are housed in this structure. + */ +struct gmonparam { + s32 state; + + /* Histogram Information */ + u16 *kcount; /* No. of bins in histogram */ + u32 kcountsize; /* Histogram samples */ + + /* Call-graph Information */ + struct fromstruct *froms; + u32 fromssize; + struct tostruct *tos; + u32 tossize; + + /* Initialization I/Ps */ + u32 lowpc; + u32 highpc; + u32 textsize; + /* u32 cg_froms, */ + /* u32 cg_tos, */ +}; +extern struct gmonparam *_gmonparam; +extern s32 n_gmon_sections; + +/* + * Possible states of profiling. + */ +#define GMON_PROF_ON 0 +#define GMON_PROF_BUSY 1 +#define GMON_PROF_ERROR 2 +#define GMON_PROF_OFF 3 + +/* + * Sysctl definitions for extracting profiling information from the kernel. + */ +#define GPROF_STATE 0 /* int: profiling enabling variable */ +#define GPROF_COUNT 1 /* struct: profile tick count buffer */ +#define GPROF_FROMS 2 /* struct: from location hash bucket */ +#define GPROF_TOS 3 /* struct: destination/count structure */ +#define GPROF_GMONPARAM 4 /* struct: profiling parameters (see above) */ + +#ifdef __cplusplus +} +#endif + +#endif /* PROFILE_H */ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/profile/profile_cg.c b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/profile/profile_cg.c new file mode 100644 index 0000000..328e6fc --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/profile/profile_cg.c @@ -0,0 +1,167 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +#include "profile.h" +#include "_profile_timer_hw.h" +#ifdef PROC_MICROBLAZE +#include "mblaze_nt_types.h" +#endif + +/* + * The mcount fucntion is excluded from the library, if the user defines + * PROFILE_NO_GRAPH. + */ +#ifndef PROFILE_NO_GRAPH + +#include +#include +#include + +#ifdef PROFILE_NO_FUNCPTR +s32 searchpc(const struct fromto_struct *cgtable, s32 cgtable_size, u32 frompc ); +#else +s32 searchpc(const struct fromstruct *froms, s32 fromssize, u32 frompc ); +#endif + +/*extern struct gmonparam *_gmonparam, */ + +#ifdef PROFILE_NO_FUNCPTR +s32 searchpc(const struct fromto_struct *cgtable, s32 cgtable_size, u32 frompc ) +{ + s32 index = 0 ; + + while( (index < cgtable_size) && (cgtable[index].frompc != frompc) ){ + index++ ; + } + if( index == cgtable_size ) { + return -1 ; + } else { + return index ; + } +} +#else +s32 searchpc(const struct fromstruct *froms, s32 fromssize, u32 frompc ) +{ + s32 index = 0 ; + s32 Status; + + while( (index < fromssize) && (froms[index].frompc != frompc) ){ + index++ ; + } + if( index == fromssize ) { + Status = -1 ; + } else { + Status = index ; + } + return Status; +} +#endif /* PROFILE_NO_FUNCPTR */ + + +void mcount( u32 frompc, u32 selfpc ) +{ + register struct gmonparam *p = NULL; + register s32 toindex, fromindex; + s32 j; + + disable_timer(); + + /*print("CG: "), putnum(frompc), print("->"), putnum(selfpc), print("\r\n") , + * check that frompcindex is a reasonable pc value. + * for example: signal catchers get called from the stack, + * not from text space. too bad. + */ + for(j = 0; j < n_gmon_sections; j++ ){ + if((frompc >= _gmonparam[j].lowpc) && (frompc < _gmonparam[j].highpc)) { + p = &_gmonparam[j]; + break; + } + } + if( j == n_gmon_sections ) { + goto done; + } + +#ifdef PROFILE_NO_FUNCPTR + fromindex = searchpc( p->cgtable, p->cgtable_size, frompc ) ; + if( fromindex == -1 ) { + fromindex = p->cgtable_size ; + p->cgtable_size++ ; + p->cgtable[fromindex].frompc = frompc ; + p->cgtable[fromindex].selfpc = selfpc ; + p->cgtable[fromindex].count = 1 ; + goto done ; + } + p->cgtable[fromindex].count++ ; +#else + fromindex = (s32)searchpc( p->froms, ((s32)p->fromssize), frompc ) ; + if( fromindex == -1 ) { + fromindex = (s32)p->fromssize ; + p->fromssize++ ; + /*if( fromindex >= N_FROMS ) { + * print("Error : From PC table overflow\r\n") + * goto overflow + *}*/ + p->froms[fromindex].frompc = frompc ; + p->froms[fromindex].link = -1 ; + }else { + toindex = ((s32)(p->froms[fromindex].link)); + while(toindex != -1) { + toindex = (((s32)p->tossize) - toindex)-1 ; + if( p->tos[toindex].selfpc == selfpc ) { + p->tos[toindex].count++ ; + goto done ; + } + toindex = ((s32)(p->tos[toindex].link)) ; + } + } + + /*if( toindex == -1 ) { */ + p->tos-- ; + p->tossize++ ; + /* if( toindex >= N_TOS ) { + * print("Error : To PC table overflow\r\n") + * goto overflow + *} */ + p->tos[0].selfpc = selfpc ; + p->tos[0].count = 1 ; + p->tos[0].link = p->froms[fromindex].link ; + p->froms[fromindex].link = ((s32)(p->tossize))-((s32)1); +#endif + + done: + p->state = GMON_PROF_ON; + goto enable_timer_label ; + /* overflow: */ + /*p->state = GMON_PROF_ERROR */ + enable_timer_label: + enable_timer(); + return ; +} + + +#endif /* PROFILE_NO_GRAPH */ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/profile/profile_config.h b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/profile/profile_config.h new file mode 100644 index 0000000..5d66311 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/profile/profile_config.h @@ -0,0 +1,52 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + + +#ifndef _PROFILE_CONFIG_H +#define _PROFILE_CONFIG_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define BINSIZE 4U +#define SAMPLE_FREQ_HZ 100000U +#define TIMER_CLK_TICKS 1000U + +#define PROFILE_NO_FUNCPTR_FLAG 0 + +#define PROFILE_TIMER_BASEADDR 0x00608000U +#define PROFILE_TIMER_INTR_ID 0U + +#define TIMER_CONNECT_INTC + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/profile/profile_hist.c b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/profile/profile_hist.c new file mode 100644 index 0000000..b3e237b --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/profile/profile_hist.c @@ -0,0 +1,67 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +#include "profile.h" +#include "_profile_timer_hw.h" + +#ifdef PROC_MICROBLAZE +#include "mblaze_nt_types.h" +#endif + +#ifdef PROC_PPC +#include "xpseudo_asm.h" +#define SPR_SRR0 0x01A +#endif + +#include "xil_types.h" + +extern u32 binsize ; +u32 prof_pc ; + +void profile_intr_handler( void ) +{ + + s32 j; + +#ifdef PROC_MICROBLAZE + asm( "swi r14, r0, prof_pc" ) ; +#elif defined PROC_PPC + prof_pc = mfspr(SPR_SRR0); +#else + /* for cortexa9, lr is saved in asm interrupt handler */ +#endif + /* print("PC: "), putnum(prof_pc), print("\r\n"), */ + for(j = 0; j < n_gmon_sections; j++ ){ + if((prof_pc >= ((u32)_gmonparam[j].lowpc)) && (prof_pc < ((u32)_gmonparam[j].highpc))) { + _gmonparam[j].kcount[(prof_pc-_gmonparam[j].lowpc)/((u32)4 * binsize)]++; + break; + } + } + /* Ack the Timer Interrupt */ + timer_ack(); +} diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/profile/profile_mcount_arm.S b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/profile/profile_mcount_arm.S new file mode 100644 index 0000000..9a84363 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/profile/profile_mcount_arm.S @@ -0,0 +1,41 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +// based on "ARM Profiling Implementation" from Sourcery G++ Lite for ARM EABI + +.globl __gnu_mcount_nc +.type __gnu_mcount_nc, %function + +__gnu_mcount_nc: + push {r0, r1, r2, r3, lr} + subs r1, lr, #0 /* callee - current lr */ + ldr r0, [sp, #20] /* caller - at the top of the stack */ + bl mcount /* when __gnu_mcount_nc is called */ + pop {r0, r1, r2, r3, ip, lr} + bx ip + + .end __gnu_mcount_nc diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/profile/profile_mcount_mb.S b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/profile/profile_mcount_mb.S new file mode 100644 index 0000000..21ab5b4 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/profile/profile_mcount_mb.S @@ -0,0 +1,65 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + + .globl _mcount + .text + .align 2 + .ent _mcount + + #ifndef PROFILE_NO_GRAPH + +_mcount: + addi r1, r1, -48 + swi r11, r1, 44 + swi r12, r1, 40 + swi r5, r1, 36 + swi r6, r1, 32 + swi r7, r1, 28 + swi r8, r1, 24 + swi r9, r1, 20 + swi r10, r1, 16 + swi r15, r1, 12 + add r5, r0, r15 + brlid r15, mcount + add r6, r0, r16 + + lwi r11, r1, 44 + lwi r12, r1, 40 + lwi r5, r1, 36 + lwi r6, r1, 32 + lwi r7, r1, 28 + lwi r8, r1, 24 + lwi r9, r1, 20 + lwi r10, r1, 16 + lwi r15, r1, 12 + rtsd r15, 4 + addi r1, r1, 48 + + #endif /* PROFILE_NO_GRAPH */ + + .end _mcount diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/profile/profile_mcount_ppc.S b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/profile/profile_mcount_ppc.S new file mode 100644 index 0000000..230df08 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/profile/profile_mcount_ppc.S @@ -0,0 +1,67 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + + .globl _mcount + + #define _MCOUNT_STACK_FRAME 48 + .section .text + .align 2 + .type _mcount@function + + +_mcount: + stwu 1, -_MCOUNT_STACK_FRAME(1) + stw 3, 8(1) + stw 4, 12(1) + stw 5, 16(1) + stw 6, 20(1) + stw 7, 24(1) + stw 8, 28(1) + stw 9, 32(1) + stw 10, 36(1) + stw 11, 40(1) + stw 12, 44(1) + mflr 4 + stw 4, (_MCOUNT_STACK_FRAME+4)(1) + lwz 3, (_MCOUNT_STACK_FRAME)(1) + lwz 3, 4(3) + bl mcount + lwz 4, (_MCOUNT_STACK_FRAME+4)(1) + mtlr 4 + lwz 12, 44(1) + lwz 11, 40(1) + lwz 10, 36(1) + lwz 9, 32(1) + lwz 8, 28(1) + lwz 7, 24(1) + lwz 6, 20(1) + lwz 5, 16(1) + lwz 4, 12(1) + lwz 3, 8(1) + addi 1,1, _MCOUNT_STACK_FRAME + blr diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/pvr.c b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/pvr.c new file mode 100644 index 0000000..c6a728c --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/pvr.c @@ -0,0 +1,90 @@ +/****************************************************************************** +* +* Copyright (C) 2006 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file pvr.c +* +* This header file contains defines for structures used by the microblaze +* PVR routines +* +******************************************************************************/ +#include "xparameters.h" +#include "pvr.h" +#include + +/* Definitions */ + +/****************************************************************************/ +/** +* @brief Populate the PVR data structure to which pvr points, with the +* values of the hardware PVR registers. +* +* @param pvr- address of PVR data structure to be populated +* +* @return 0 - SUCCESS +* -1 - FAILURE +* +****************************************************************************/ +int microblaze_get_pvr (pvr_t *pvr) +{ + if (!pvr) + return -1; + + bzero ((void*)pvr, sizeof (pvr_t)); + +#ifdef MICROBLAZE_PVR_NONE + return -1; +#else + getpvr (0, pvr->pvr[0]); +#endif /* MICROBLAZE_PVR_NONE */ + +#ifdef MICROBLAZE_PVR_FULL + getpvr (1, pvr->pvr[1]); + getpvr (2, pvr->pvr[2]); + getpvr (3, pvr->pvr[3]); + + getpvr (4, pvr->pvr[4]); + getpvr (5, pvr->pvr[5]); + getpvr (6, pvr->pvr[6]); + getpvr (7, pvr->pvr[7]); + + getpvr (8, pvr->pvr[8]); + getpvr (9, pvr->pvr[9]); + getpvr (10, pvr->pvr[10]); + getpvr (11, pvr->pvr[11]); + +/* getpvr (12, pvr->pvr[12]); */ +/* getpvr (13, pvr->pvr[13]); */ +/* getpvr (14, pvr->pvr[14]); */ +/* getpvr (15, pvr->pvr[15]); */ + +#endif /* MICROBLAZE_PVR_FULL */ + + return 0; +} diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/pvr.h b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/pvr.h new file mode 100644 index 0000000..e413cfb --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/pvr.h @@ -0,0 +1,532 @@ +/****************************************************************************** +* +* Copyright (C) 2006 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file pvr.h +* +* @addtogroup microblaze_pvr_macros Microblaze PVR access routines and macros +* +* MicroBlaze processor v5.00.a and later versions have configurable +* Processor Version Registers (PVRs). The contents of the PVR are captured +* using the pvr_t data structure, which is defined as an array of 32-bit words, +* with each word corresponding to a PVR register on hardware. The number of PVR +* words is determined by the number of PVRs configured in the hardware. You should +* not attempt to access PVR registers that are not present in hardware, as the +* pvr_t data structure is resized to hold only as many PVRs as are present in +* hardware. +* To access information in the PVR: +* 1. Use the microblaze_get_pvr() function to populate the PVR data into a pvr_t +* data structure. +* 2. In subsequent steps, you can use any one of the PVR access macros list to +* get individual data stored in the PVR. +* 3. pvr.h header file must be included to source to use PVR macros. +* +* @{ +* +******************************************************************************/ + +#ifndef _PVR_H +#define _PVR_H + +#include "xil_types.h" +#include "xil_assert.h" +#include "xparameters.h" +#include "mb_interface.h" +#include "bspconfig.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Defs */ +typedef struct pvr_s { +#ifdef MICROBLAZE_PVR_FULL + unsigned int pvr[16]; +#else + unsigned int pvr[1]; +#endif +} pvr_t; + + +#define getpvr(pvrid, val) asm volatile ("mfs\t%0,rpvr" stringify(pvrid) "\n\t" : "=d" (val)) + +/* Basic PVR mask */ +#define MICROBLAZE_PVR0_PVR_FULL_MASK 0x80000000 +#define MICROBLAZE_PVR0_USE_BARREL_MASK 0x40000000 +#define MICROBLAZE_PVR0_USE_DIV_MASK 0x20000000 +#define MICROBLAZE_PVR0_USE_HW_MUL_MASK 0x10000000 +#define MICROBLAZE_PVR0_USE_FPU_MASK 0x08000000 +#define MICROBLAZE_PVR0_USE_EXCEPTION_MASK 0x04000000 +#define MICROBLAZE_PVR0_USE_ICACHE_MASK 0x02000000 +#define MICROBLAZE_PVR0_USE_DCACHE_MASK 0x01000000 +#define MICROBLAZE_PVR0_USE_MMU_MASK 0x00800000 +#define MICROBLAZE_PVR0_USE_BTC_MASK 0x00400000 +#define MICROBLAZE_PVR0_ENDIANNESS_MASK 0x00200000 +#define MICROBLAZE_PVR0_FAULT_TOLERANT_MASK 0x00100000 +#define MICROBLAZE_PVR0_STACK_PROTECTION_MASK 0x00080000 +#define MICROBLAZE_PVR0_MICROBLAZE_VERSION_MASK 0x0000FF00 +#define MICROBLAZE_PVR0_USER1_MASK 0x000000FF + +/* User 2 PVR mask */ +#define MICROBLAZE_PVR1_USER2_MASK 0xFFFFFFFF + +/* Configuration PVR masks */ +#define MICROBLAZE_PVR2_D_AXI_MASK 0x80000000 +#define MICROBLAZE_PVR2_D_LMB_MASK 0x40000000 +#define MICROBLAZE_PVR2_D_PLB_MASK 0x02000000 +#define MICROBLAZE_PVR2_I_AXI_MASK 0x20000000 +#define MICROBLAZE_PVR2_I_LMB_MASK 0x10000000 +#define MICROBLAZE_PVR2_I_PLB_MASK 0x01000000 +#define MICROBLAZE_PVR2_INTERRUPT_IS_EDGE_MASK 0x08000000 +#define MICROBLAZE_PVR2_EDGE_IS_POSITIVE_MASK 0x04000000 +#define MICROBLAZE_PVR2_INTERCONNECT_MASK 0x00800000 +#define MICROBLAZE_PVR2_STREAM_INTERCONNECT_MASK 0x00400000 +#define MICROBLAZE_PVR2_USE_EXTENDED_FSL_INSTR_MASK 0x00080000 +#define MICROBLAZE_PVR2_USE_MSR_INSTR_MASK 0x00020000 +#define MICROBLAZE_PVR2_USE_PCMP_INSTR_MASK 0x00010000 +#define MICROBLAZE_PVR2_AREA_OPTIMIZED_MASK 0x00008000 +#define MICROBLAZE_PVR2_USE_BARREL_MASK 0x00004000 +#define MICROBLAZE_PVR2_USE_DIV_MASK 0x00002000 +#define MICROBLAZE_PVR2_USE_HW_MUL_MASK 0x00001000 +#define MICROBLAZE_PVR2_USE_FPU_MASK 0x00000800 +#define MICROBLAZE_PVR2_USE_FPU2_MASK 0x00000200 +#define MICROBLAZE_PVR2_USE_MUL64_MASK 0x00000400 +#define MICROBLAZE_PVR2_OPCODE_0x0_ILLEGAL_MASK 0x00000040 +#define MICROBLAZE_PVR2_UNALIGNED_EXCEPTION_MASK 0x00000020 +#define MICROBLAZE_PVR2_ILL_OPCODE_EXCEPTION_MASK 0x00000010 +#define MICROBLAZE_PVR2_M_AXI_I_BUS_EXCEPTION_MASK 0x00000008 +#define MICROBLAZE_PVR2_M_AXI_D_BUS_EXCEPTION_MASK 0x00000004 +#define MICROBLAZE_PVR2_IPLB_BUS_EXCEPTION_MASK 0x00000100 +#define MICROBLAZE_PVR2_DPLB_BUS_EXCEPTION_MASK 0x00000080 +#define MICROBLAZE_PVR2_DIV_ZERO_EXCEPTION_MASK 0x00000002 +#define MICROBLAZE_PVR2_FPU_EXCEPTION_MASK 0x00000001 +#define MICROBLAZE_PVR2_FSL_EXCEPTION_MASK 0x00040000 + +/* Debug and exception PVR masks */ +#define MICROBLAZE_PVR3_DEBUG_ENABLED_MASK 0x80000000 +#define MICROBLAZE_PVR3_NUMBER_OF_PC_BRK_MASK 0x1E000000 +#define MICROBLAZE_PVR3_NUMBER_OF_RD_ADDR_BRK_MASK 0x00380000 +#define MICROBLAZE_PVR3_NUMBER_OF_WR_ADDR_BRK_MASK 0x0000E000 +#define MICROBLAZE_PVR3_FSL_LINKS_MASK 0x00000380 +#define MICROBLAZE_PVR3_BTC_SIZE_MASK 0x00000007 + +/* ICache config PVR masks */ +#define MICROBLAZE_PVR4_USE_ICACHE_MASK 0x80000000 +#define MICROBLAZE_PVR4_ICACHE_ADDR_TAG_BITS_MASK 0x7C000000 +#define MICROBLAZE_PVR4_ICACHE_ALLOW_WR_MASK 0x01000000 +#define MICROBLAZE_PVR4_ICACHE_LINE_LEN_MASK 0x00E00000 +#define MICROBLAZE_PVR4_ICACHE_BYTE_SIZE_MASK 0x001F0000 +#define MICROBLAZE_PVR4_ICACHE_ALWAYS_USED_MASK 0x00008000 +#define MICROBLAZE_PVR4_ICACHE_INTERFACE_MASK 0x00002000 +#define MICROBLAZE_PVR4_ICACHE_VICTIMS_MASK 0x00001C00 +#define MICROBLAZE_PVR4_ICACHE_STREAMS_MASK 0x00000300 +#define MICROBLAZE_PVR4_ICACHE_FORCE_TAG_LUTRAM_MASK 0x00000080 +#define MICROBLAZE_PVR4_ICACHE_DATA_WIDTH_MASK 0x00000040 + +/* DCache config PVR masks */ +#define MICROBLAZE_PVR5_USE_DCACHE_MASK 0x80000000 +#define MICROBLAZE_PVR5_DCACHE_ADDR_TAG_BITS_MASK 0x7C000000 +#define MICROBLAZE_PVR5_DCACHE_ALLOW_WR_MASK 0x01000000 +#define MICROBLAZE_PVR5_DCACHE_LINE_LEN_MASK 0x00E00000 +#define MICROBLAZE_PVR5_DCACHE_BYTE_SIZE_MASK 0x001F0000 +#define MICROBLAZE_PVR5_DCACHE_ALWAYS_USED_MASK 0x00008000 +#define MICROBLAZE_PVR5_DCACHE_USE_WRITEBACK_MASK 0x00004000 +#define MICROBLAZE_PVR5_DCACHE_INTERFACE_MASK 0x00002000 +#define MICROBLAZE_PVR5_DCACHE_VICTIMS_MASK 0x00001C00 +#define MICROBLAZE_PVR5_DCACHE_FORCE_TAG_LUTRAM_MASK 0x00000080 +#define MICROBLAZE_PVR5_DCACHE_DATA_WIDTH_MASK 0x00000040 + +#if defined(__arch64__) +/* ICache base address PVR mask */ +#define MICROBLAZE_PVR6_ICACHE_BASEADDR_MASK 0xFFFFFFFFFFFFFFFF + +/* ICache high address PVR mask */ +#define MICROBLAZE_PVR7_ICACHE_HIGHADDR_MASK 0xFFFFFFFFFFFFFFFF + +/* DCache base address PVR mask */ +#define MICROBLAZE_PVR8_DCACHE_BASEADDR_MASK 0xFFFFFFFFFFFFFFFF + +/* DCache high address PVR mask */ +#define MICROBLAZE_PVR9_DCACHE_HIGHADDR_MASK 0xFFFFFFFFFFFFFFFF + +#else +/* ICache base address PVR mask */ +#define MICROBLAZE_PVR6_ICACHE_BASEADDR_MASK 0xFFFFFFFF + +/* ICache high address PVR mask */ +#define MICROBLAZE_PVR7_ICACHE_HIGHADDR_MASK 0xFFFFFFFF + +/* DCache base address PVR mask */ +#define MICROBLAZE_PVR8_DCACHE_BASEADDR_MASK 0xFFFFFFFF + +/* DCache high address PVR mask */ +#define MICROBLAZE_PVR9_DCACHE_HIGHADDR_MASK 0xFFFFFFFF +#endif + +/* Target family PVR mask */ +#define MICROBLAZE_PVR10_TARGET_FAMILY_MASK 0xFF000000 + +/* MSR Reset value PVR mask */ +#define MICROBLAZE_PVR11_MSR_RESET_VALUE_MASK 0x000007FF + +/* MMU value PVR mask */ +#define MICROBLAZE_PVR11_MMU_MASK 0xC0000000 +#define MICROBLAZE_PVR11_MMU_ITLB_SIZE_MASK 0x38000000 +#define MICROBLAZE_PVR11_MMU_DTLB_SIZE_MASK 0x07000000 +#define MICROBLAZE_PVR11_MMU_TLB_ACCESS_MASK 0x00C00000 +#define MICROBLAZE_PVR11_MMU_ZONES_MASK 0x003E0000 +#define MICROBLAZE_PVR11_MMU_PRIVILEGED_INSTR_MASK 0x00010000 + +/* PVR access macros */ + +/** +Return non-zero integer if PVR is of type FULL, 0 if basic +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_IS_FULL(_pvr) (_pvr.pvr[0] & MICROBLAZE_PVR0_PVR_FULL_MASK) +/** +Return non-zero integer if hardware barrel shifter present. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_USE_BARREL(_pvr) (_pvr.pvr[0] & MICROBLAZE_PVR0_USE_BARREL_MASK) +/** +Return non-zero integer if hardware divider present. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_USE_DIV(_pvr) (_pvr.pvr[0] & MICROBLAZE_PVR0_USE_DIV_MASK) +/** +Return non-zero integer if hardware multiplier present. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_USE_HW_MUL(_pvr) (_pvr.pvr[0] & MICROBLAZE_PVR0_USE_HW_MUL_MASK) +/** +Return non-zero integer if hardware floating point unit (FPU) present. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_USE_FPU(_pvr) (_pvr.pvr[0] & MICROBLAZE_PVR0_USE_FPU_MASK) +/** +Return non-zero integer if I-cache present. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_USE_ICACHE(_pvr) (_pvr.pvr[0] & MICROBLAZE_PVR0_USE_ICACHE_MASK) +/** +Return non-zero integer if D-cache present. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_USE_DCACHE(_pvr) (_pvr.pvr[0] & MICROBLAZE_PVR0_USE_DCACHE_MASK) +#define MICROBLAZE_PVR_USE_MMU(_pvr) (_pvr.pvr[0] & MICROBLAZE_PVR0_USE_MMU_MASK) +#define MICROBLAZE_PVR_USE_BTC(_pvr) (_pvr.pvr[0] & MICROBLAZE_PVR0_USE_BTC_MASK) +#define MICROBLAZE_PVR_ENDIANNESS(_pvr) (_pvr.pvr[0] & MICROBLAZE_PVR0_ENDIANNESS_MASK) +#define MICROBLAZE_PVR_FAULT_TOLERANT(_pvr) (_pvr.pvr[0] & MICROBLAZE_PVR0_FAULT_TOLERANT_MASK) +#define MICROBLAZE_PVR_STACK_PROTECTION(_pvr) (_pvr.pvr[0] & MICROBLAZE_PVR0_STACK_PROTECTION_MASK) +/** +Return MicroBlaze processor version encoding. Refer to the MicroBlaze Processor +Reference Guide (UG081) for mappings from encodings to actual hardware versions. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_MICROBLAZE_VERSION(_pvr) ((_pvr.pvr[0] & MICROBLAZE_PVR0_MICROBLAZE_VERSION_MASK) >> 8) +/** +Return the USER1 field stored in the PVR. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_USER1(_pvr) (_pvr.pvr[0] & MICROBLAZE_PVR0_USER1_MASK) + +/** +Return the USER2 field stored in the PVR. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_USER2(_pvr) (_pvr.pvr[1] & MICROBLAZE_PVR1_USER2_MASK) + +#define MICROBLAZE_PVR_D_AXI(_pvr) (_pvr.pvr[2] & MICROBLAZE_PVR2_D_AXI_MASK) + +/** +Return non-zero integer if Data Side PLB +interface is present. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_D_LMB(_pvr) (_pvr.pvr[2] & MICROBLAZE_PVR2_D_LMB_MASK) + +/** +Return non-zero integer if Data Side PLB interface is present. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_D_PLB(_pvr) (_pvr.pvr[2] & MICROBLAZE_PVR2_D_PLB_MASK) + +#define MICROBLAZE_PVR_I_AXI(_pvr) (_pvr.pvr[2] & MICROBLAZE_PVR2_I_AXI_MASK) + +/** +Return non-zero integer if Instruction Side Local Memory Bus (LMB) interface present. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_I_LMB(_pvr) (_pvr.pvr[2] & MICROBLAZE_PVR2_I_LMB_MASK) + +/** +Return non-zero integer if Instruction Side PLB interface present. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_I_PLB(_pvr) (_pvr.pvr[2] & MICROBLAZE_PVR2_I_PLB_MASK) + +/** +Return non-zero integer if interrupts are configured as edge-triggered. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_INTERRUPT_IS_EDGE(_pvr) (_pvr.pvr[2] & MICROBLAZE_PVR2_INTERRUPT_IS_EDGE_MASK) + +/** +Return non-zero integer if interrupts are configured as positive edge triggered. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_EDGE_IS_POSITIVE(_pvr) (_pvr.pvr[2] & MICROBLAZE_PVR2_EDGE_IS_POSITIVE_MASK) + +/** +Return non-zero if MicroBlaze processor has PLB interconnect; otherwise return zero. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_INTERCONNECT(_pvr) (_pvr.pvr[2] & MICROBLAZE_PVR2_INTERCONNECT_MASK) + +#define MICROBLAZE_PVR_STREAM_INTERCONNECT(_pvr) (_pvr.pvr[2] & MICROBLAZE_PVR2_STREAM_INTERCONNECT_MASK) +#define MICROBLAZE_PVR_USE_EXTENDED_FSL_INSTR(_pvr) (_pvr.pvr[2] & MICROBLAZE_PVR2_USE_EXTENDED_FSL_INSTR_MASK) +#define MICROBLAZE_PVR_USE_MSR_INSTR(_pvr) (_pvr.pvr[2] & MICROBLAZE_PVR2_USE_MSR_INSTR_MASK) +#define MICROBLAZE_PVR_USE_PCMP_INSTR(_pvr) (_pvr.pvr[2] & MICROBLAZE_PVR2_USE_PCMP_INSTR_MASK) +#define MICROBLAZE_PVR_AREA_OPTIMIZED(_pvr) (_pvr.pvr[2] & MICROBLAZE_PVR2_AREA_OPTIMIZED_MASK) + +/** +Return non-zero integer if MicroBlaze processor supports 64-bit products for +multiplies. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_USE_MUL64(_pvr) (_pvr.pvr[2] & MICROBLAZE_PVR2_USE_MUL64_MASK) + +/** +Return non-zero integer if opcode 0x0 is treated as an illegal opcode. +multiplies. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_OPCODE_0x0_ILLEGAL(_pvr) (_pvr.pvr[2] & MICROBLAZE_PVR2_OPCODE_0x0_ILLEGAL_MASK) + +/** +Return non-zero integer if unaligned exceptions are supported. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_UNALIGNED_EXCEPTION(_pvr) (_pvr.pvr[2] & MICROBLAZE_PVR2_UNALIGNED_EXCEPTION_MASK) + +/** +Return non-zero integer if illegal opcode exceptions are supported. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_ILL_OPCODE_EXCEPTION(_pvr) (_pvr.pvr[2] & MICROBLAZE_PVR2_ILL_OPCODE_EXCEPTION_MASK) + +#define MICROBLAZE_PVR_M_AXI_I_BUS_EXCEPTION(_pvr) (_pvr.pvr[2] & MICROBLAZE_PVR2_M_AXI_I_BUS_EXCEPTION_MASK) + +/** +Return non-zero integer if I-PLB exceptions are supported. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_IPLB_BUS_EXCEPTION(_pvr) (_pvr.pvr[2] & MICROBLAZE_PVR2_IPLB_BUS_EXCEPTION_MASK) + +#define MICROBLAZE_PVR_M_AXI_D_BUS_EXCEPTION(_pvr) (_pvr.pvr[2] & MICROBLAZE_PVR2_M_AXI_D_BUS_EXCEPTION_MASK) + +/** +Return non-zero integer if I-PLB exceptions are supported. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_DPLB_BUS_EXCEPTION(_pvr) (_pvr.pvr[2] & MICROBLAZE_PVR2_DPLB_BUS_EXCEPTION_MASK) + +/** +Return non-zero integer if divide by zero exceptions are supported. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_DIV_ZERO_EXCEPTION(_pvr) (_pvr.pvr[2] & MICROBLAZE_PVR2_DIV_ZERO_EXCEPTION_MASK) + +/** +Return non-zero integer if FPU exceptions are supported. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_FPU_EXCEPTION(_pvr) (_pvr.pvr[2] & MICROBLAZE_PVR2_FPU_EXCEPTION_MASK) + +/** +Return non-zero integer if FSL exceptions are present. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_FSL_EXCEPTION(_pvr) (_pvr.pvr[2] & MICROBLAZE_PVR2_FSL_EXCEPTION_MASK) + +/** +Return non-zero integer if debug is enabled. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_DEBUG_ENABLED(_pvr) (_pvr.pvr[3] & MICROBLAZE_PVR3_DEBUG_ENABLED_MASK) + +/** +Return the number of hardware PC breakpoints available. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_NUMBER_OF_PC_BRK(_pvr) ((_pvr.pvr[3] & MICROBLAZE_PVR3_NUMBER_OF_PC_BRK_MASK) >> 25) + +/** +Return the number of read address hardware watchpoints supported. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_NUMBER_OF_RD_ADDR_BRK(_pvr) ((_pvr.pvr[3] & MICROBLAZE_PVR3_NUMBER_OF_RD_ADDR_BRK_MASK) >> 19) + +/** +Return the number of write address hardware watchpoints supported. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_NUMBER_OF_WR_ADDR_BRK(_pvr) ((_pvr.pvr[3] & MICROBLAZE_PVR3_NUMBER_OF_WR_ADDR_BRK_MASK) >> 13) + +/** +Return the number of FSL links present. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_FSL_LINKS(_pvr) ((_pvr.pvr[3] & MICROBLAZE_PVR3_FSL_LINKS_MASK) >> 7) +#define MICROBLAZE_PVR_BTC_SIZE(_pvr) (_pvr.pvr[3] & MICROBLAZE_PVR3_BTC_SIZE_MASK) + +/** +Return the number of address tag bits for the I-cache. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_ICACHE_ADDR_TAG_BITS(_pvr) ((_pvr.pvr[4] & MICROBLAZE_PVR4_ICACHE_ADDR_TAG_BITS_MASK) >> 26) + +/** +Return non-zero if writes to I-caches are allowed. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_ICACHE_ALLOW_WR(_pvr) (_pvr.pvr[4] & MICROBLAZE_PVR4_ICACHE_ALLOW_WR_MASK) + +/** +Return the length of each I-cache line in bytes. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_ICACHE_LINE_LEN(_pvr) (1 << ((_pvr.pvr[4] & MICROBLAZE_PVR4_ICACHE_LINE_LEN_MASK) >> 21)) + +/** +Return the size of the D-cache in bytes. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_ICACHE_BYTE_SIZE(_pvr) (1 << ((_pvr.pvr[4] & MICROBLAZE_PVR4_ICACHE_BYTE_SIZE_MASK) >> 16)) + +#define MICROBLAZE_PVR_ICACHE_ALWAYS_USED(_pvr) (_pvr.pvr[4] & MICROBLAZE_PVR4_ICACHE_ALWAYS_USED_MASK) +#define MICROBLAZE_PVR_ICACHE_INTERFACE(_pvr) (_pvr.pvr[4] & MICROBLAZE_PVR4_ICACHE_INTERFACE_MASK) +#define MICROBLAZE_PVR_ICACHE_VICTIMS(_pvr) ((_pvr.pvr[4] & MICROBLAZE_PVR4_ICACHE_VICTIMS_MASK) >> 10) +#define MICROBLAZE_PVR_ICACHE_STREAMS(_pvr) ((_pvr.pvr[4] & MICROBLAZE_PVR4_ICACHE_STREAMS_MASK) >> 8) +#define MICROBLAZE_PVR_ICACHE_FORCE_TAG_LUTRAM(_pvr) (_pvr.pvr[4] & MICROBLAZE_PVR4_ICACHE_FORCE_TAG_LUTRAM_MASK) +#define MICROBLAZE_PVR_ICACHE_DATA_WIDTH(_pvr) (_pvr.pvr[4] & MICROBLAZE_PVR4_ICACHE_DATA_WIDTH_MASK) + +/** +Return the number of address tag bits for the D-cache. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_DCACHE_ADDR_TAG_BITS(_pvr) ((_pvr.pvr[5] & MICROBLAZE_PVR5_DCACHE_ADDR_TAG_BITS_MASK) >> 26) + +/** +Return non-zero if writes to D-cache are allowed. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_DCACHE_ALLOW_WR(_pvr) (_pvr.pvr[5] & MICROBLAZE_PVR5_DCACHE_ALLOW_WR_MASK) + +/** +Return the length of each line in the D-cache in bytes. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_DCACHE_LINE_LEN(_pvr) (1 << ((_pvr.pvr[5] & MICROBLAZE_PVR5_DCACHE_LINE_LEN_MASK) >> 21)) + +/** +Return the size of the D-cache in bytes. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_DCACHE_BYTE_SIZE(_pvr) (1 << ((_pvr.pvr[5] & MICROBLAZE_PVR5_DCACHE_BYTE_SIZE_MASK) >> 16)) + + +#define MICROBLAZE_PVR_DCACHE_ALWAYS_USED(_pvr) (_pvr.pvr[5] & MICROBLAZE_PVR5_DCACHE_ALWAYS_USED_MASK) +#define MICROBLAZE_PVR_DCACHE_USE_WRITEBACK(_pvr) (_pvr.pvr[5] & MICROBLAZE_PVR5_DCACHE_USE_WRITEBACK_MASK) +#define MICROBLAZE_PVR_DCACHE_INTERFACE(_pvr) (_pvr.pvr[5] & MICROBLAZE_PVR5_DCACHE_INTERFACE_MASK) +#define MICROBLAZE_PVR_DCACHE_VICTIMS(_pvr) ((_pvr.pvr[5] & MICROBLAZE_PVR5_DCACHE_VICTIMS_MASK) >> 10) +#define MICROBLAZE_PVR_DCACHE_FORCE_TAG_LUTRAM(_pvr) (_pvr.pvr[5] & MICROBLAZE_PVR5_DCACHE_FORCE_TAG_LUTRAM_MASK) +#define MICROBLAZE_PVR_DCACHE_DATA_WIDTH(_pvr) (_pvr.pvr[5] & MICROBLAZE_PVR5_DCACHE_DATA_WIDTH_MASK) + +/** +Return the base address of the I-cache. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_ICACHE_BASEADDR(_pvr) (_pvr.pvr[6] & MICROBLAZE_PVR6_ICACHE_BASEADDR_MASK) + +/** +Return the high address of the I-cache. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_ICACHE_HIGHADDR(_pvr) (_pvr.pvr[7] & MICROBLAZE_PVR7_ICACHE_HIGHADDR_MASK) + +/** +Return the base address of the D-cache. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_DCACHE_BASEADDR(_pvr) (_pvr.pvr[8] & MICROBLAZE_PVR8_DCACHE_BASEADDR_MASK) + +/** +Return the high address of the D-cache. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_DCACHE_HIGHADDR(_pvr) (_pvr.pvr[9] & MICROBLAZE_PVR9_DCACHE_HIGHADDR_MASK) + +/** +Return the encoded target family identifier. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_TARGET_FAMILY(_pvr) ((_pvr.pvr[10] & MICROBLAZE_PVR10_TARGET_FAMILY_MASK) >> 24) + +/** +Refer to the MicroBlaze Processor Reference Guide (UG081) for mappings from encodings +to target family name strings. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_MSR_RESET_VALUE(_pvr) (_pvr.pvr[11] & MICROBLAZE_PVR11_MSR_RESET_VALUE_MASK) + +/** +Returns the value of C_USE_MMU. Refer to the MicroBlaze Processor Reference Guide +(UG081) for mappings from MMU type values to MMU function. +@param _pvr pvr data structure +*/ +#define MICROBLAZE_PVR_MMU_TYPE(_pvr) ((_pvr.pvr[11] & MICROBLAZE_PVR11_MMU_MASK) >> 30) +#define MICROBLAZE_PVR_MMU_ITLB_SIZE(_pvr) ((_pvr.pvr[11] & MICROBLAZE_PVR11_MMU_ITLB_SIZE_MASK) >> 27) +#define MICROBLAZE_PVR_MMU_DTLB_SIZE(_pvr) ((_pvr.pvr[11] & MICROBLAZE_PVR11_MMU_DTLB_SIZE_MASK) >> 24) +#define MICROBLAZE_PVR_MMU_TLB_ACCESS(_pvr) ((_pvr.pvr[11] & MICROBLAZE_PVR11_MMU_TLB_ACCESS_MASK) >> 22) +#define MICROBLAZE_PVR_MMU_ZONES(_pvr) ((_pvr.pvr[11] & MICROBLAZE_PVR11_MMU_ZONES_MASK) >> 17) +#define MICROBLAZE_PVR_MMU_PRIVILEGED_INSTR(_pvr) ((_pvr.pvr[11] & MICROBLAZE_PVR11_MMU_PRIVILEGED_INSTR_MASK) >> 16) + +/* Protos */ +int microblaze_get_pvr (pvr_t *pvr); + +#ifdef __cplusplus +} +#endif +#endif /* _PVR_H */ +/** +* @} End of "addtogroup microblaze_pvr_macros". +*/ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/sleep.h b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/sleep.h new file mode 100644 index 0000000..f3a632b --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/sleep.h @@ -0,0 +1,115 @@ +/****************************************************************************** +* +* Copyright (C) 2014 - 2017 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +/*****************************************************************************/ +/** +* @file sleep.h +* +* This header file contains ARM Cortex A53,A9,R5,Microblaze specific sleep +* related APIs. +* +*
+* MODIFICATION HISTORY :
+*
+* Ver   Who  Date	 Changes
+* ----- ---- -------- -------------------------------------------------------
+* 6.6   srm  11/02/17 Added processor specific sleep rountines
+*								 function prototypes.
+*
+* 
+* +******************************************************************************/ + +#ifndef SLEEP_H +#define SLEEP_H + +#include "xil_types.h" +#include "xil_io.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*****************************************************************************/ +/** +* +* This macro polls an address periodically until a condition is met or till the +* timeout occurs. +* The minimum timeout for calling this macro is 100us. If the timeout is less +* than 100us, it still waits for 100us. Also the unit for the timeout is 100us. +* If the timeout is not a multiple of 100us, it waits for a timeout of +* the next usec value which is a multiple of 100us. +* +* @param IO_func - accessor function to read the register contents. +* Depends on the register width. +* @param ADDR - Address to be polled +* @param VALUE - variable to read the value +* @param COND - Condition to checked (usually involves VALUE) +* @param TIMEOUT_US - timeout in micro seconds +* +* @return 0 - when the condition is met +* -1 - when the condition is not met till the timeout period +* +* @note none +* +*****************************************************************************/ +#define Xil_poll_timeout(IO_func, ADDR, VALUE, COND, TIMEOUT_US) \ + ( { \ + u64 timeout = TIMEOUT_US/100; \ + if(TIMEOUT_US%100!=0) \ + timeout++; \ + for(;;) { \ + VALUE = IO_func(ADDR); \ + if(COND) \ + break; \ + else { \ + usleep(100); \ + timeout--; \ + if(timeout==0) \ + break; \ + } \ + } \ + (timeout>0) ? 0 : -1; \ + } ) + +void usleep(unsigned long useconds); +void sleep(unsigned int seconds); +int usleep_R5(unsigned long useconds); +unsigned sleep_R5(unsigned int seconds); +int usleep_MB(unsigned long useconds); +unsigned sleep_MB(unsigned int seconds); +int usleep_A53(unsigned long useconds); +unsigned sleep_A53(unsigned int seconds); +int usleep_A9(unsigned long useconds); +unsigned sleep_A9(unsigned int seconds); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xbasic_types.h b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xbasic_types.h new file mode 100644 index 0000000..2d9b245 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xbasic_types.h @@ -0,0 +1,127 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xbasic_types.h +* +* +* @note Dummy File for backwards compatibility +* + +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date   Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a adk   1/31/14  Added in bsp common folder for backward compatibility
+* 7.0   aru   01/21/19 Modified the typedef of u32,u16,u8
+* 7.0 	aru   02/06/19 Included stdint.h and stddef.h
+* 
+* +******************************************************************************/ + +#ifndef XBASIC_TYPES_H /* prevent circular inclusions */ +#define XBASIC_TYPES_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +/** @name Legacy types + * Deprecated legacy types. + * @{ + */ +typedef uint8_t Xuint8; /**< unsigned 8-bit */ +typedef char Xint8; /**< signed 8-bit */ +typedef uint16_t Xuint16; /**< unsigned 16-bit */ +typedef short Xint16; /**< signed 16-bit */ +typedef uint32_t Xuint32; /**< unsigned 32-bit */ +typedef long Xint32; /**< signed 32-bit */ +typedef float Xfloat32; /**< 32-bit floating point */ +typedef double Xfloat64; /**< 64-bit double precision FP */ +typedef unsigned long Xboolean; /**< boolean (XTRUE or XFALSE) */ + +#if !defined __XUINT64__ +typedef struct +{ + Xuint32 Upper; + Xuint32 Lower; +} Xuint64; +#endif + +/** @name New types + * New simple types. + * @{ + */ +#ifndef __KERNEL__ +#ifndef XIL_TYPES_H +typedef Xuint32 u32; +typedef Xuint16 u16; +typedef Xuint8 u8; +#endif +#else +#include +#endif + +#ifndef TRUE +# define TRUE 1U +#endif + +#ifndef FALSE +# define FALSE 0U +#endif + +#ifndef NULL +#define NULL 0U +#endif + +/* + * Xilinx NULL, TRUE and FALSE legacy support. Deprecated. + * Please use NULL, TRUE and FALSE + */ +#define XNULL NULL +#define XTRUE TRUE +#define XFALSE FALSE + +/* + * This file is deprecated and users + * should use xil_types.h and xil_assert.h\n\r + */ +#warning The xbasics_type.h file is deprecated and users should use xil_types.h and xil_assert. +#warning Please refer the Standalone BSP UG647 for further details + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xdebug.h b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xdebug.h new file mode 100644 index 0000000..b09c02d --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xdebug.h @@ -0,0 +1,40 @@ +#ifndef XDEBUG /* prevent circular inclusions */ +#define XDEBUG /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(DEBUG) && !defined(NDEBUG) + +#ifndef XDEBUG_WARNING +#define XDEBUG_WARNING +#warning DEBUG is enabled +#endif + +int printf(const char *format, ...); + +#define XDBG_DEBUG_ERROR 0x00000001U /* error condition messages */ +#define XDBG_DEBUG_GENERAL 0x00000002U /* general debug messages */ +#define XDBG_DEBUG_ALL 0xFFFFFFFFU /* all debugging data */ + +#define xdbg_current_types (XDBG_DEBUG_GENERAL) + +#define xdbg_stmnt(x) x + +#define xdbg_printf(type, ...) (((type) & xdbg_current_types) ? printf (__VA_ARGS__) : 0) + + +#else /* defined(DEBUG) && !defined(NDEBUG) */ + +#define xdbg_stmnt(x) + +#define xdbg_printf(...) + +#endif /* defined(DEBUG) && !defined(NDEBUG) */ + +#ifdef __cplusplus +} +#endif + +#endif /* XDEBUG */ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xenv.h b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xenv.h new file mode 100644 index 0000000..9c7c4c3 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xenv.h @@ -0,0 +1,183 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xenv.h +* +* Defines common services that are typically found in a host operating. +* environment. This include file simply includes an OS specific file based +* on the compile-time constant BUILD_ENV_*, where * is the name of the target +* environment. +* +* All services are defined as macros. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00b ch   10/24/02 Added XENV_LINUX
+* 1.00a rmm  04/17/02 First release
+* 
+* +******************************************************************************/ + +#ifndef XENV_H /* prevent circular inclusions */ +#define XENV_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Select which target environment we are operating under + */ + +/* VxWorks target environment */ +#if defined XENV_VXWORKS +#include "xenv_vxworks.h" + +/* Linux target environment */ +#elif defined XENV_LINUX +#include "xenv_linux.h" + +/* Unit test environment */ +#elif defined XENV_UNITTEST +#include "ut_xenv.h" + +/* Integration test environment */ +#elif defined XENV_INTTEST +#include "int_xenv.h" + +/* Standalone environment selected */ +#else +#include "xenv_standalone.h" +#endif + + +/* + * The following comments specify the types and macro wrappers that are + * expected to be defined by the target specific header files + */ + +/**************************** Type Definitions *******************************/ + +/*****************************************************************************/ +/** + * + * XENV_TIME_STAMP + * + * A structure that contains a time stamp used by other time stamp macros + * defined below. This structure is processor dependent. + */ + + +/***************** Macros (Inline Functions) Definitions *********************/ + +/*****************************************************************************/ +/** + * + * XENV_MEM_COPY(void *DestPtr, void *SrcPtr, unsigned Bytes) + * + * Copies a non-overlapping block of memory. + * + * @param DestPtr is the destination address to copy data to. + * @param SrcPtr is the source address to copy data from. + * @param Bytes is the number of bytes to copy. + * + * @return None + */ + +/*****************************************************************************/ +/** + * + * XENV_MEM_FILL(void *DestPtr, char Data, unsigned Bytes) + * + * Fills an area of memory with constant data. + * + * @param DestPtr is the destination address to set. + * @param Data contains the value to set. + * @param Bytes is the number of bytes to set. + * + * @return None + */ +/*****************************************************************************/ +/** + * + * XENV_TIME_STAMP_GET(XTIME_STAMP *StampPtr) + * + * Samples the processor's or external timer's time base counter. + * + * @param StampPtr is the storage for the retrieved time stamp. + * + * @return None + */ + +/*****************************************************************************/ +/** + * + * XENV_TIME_STAMP_DELTA_US(XTIME_STAMP *Stamp1Ptr, XTIME_STAMP* Stamp2Ptr) + * + * Computes the delta between the two time stamps. + * + * @param Stamp1Ptr - First sampled time stamp. + * @param Stamp1Ptr - Sedond sampled time stamp. + * + * @return An unsigned int value with units of microseconds. + */ + +/*****************************************************************************/ +/** + * + * XENV_TIME_STAMP_DELTA_MS(XTIME_STAMP *Stamp1Ptr, XTIME_STAMP* Stamp2Ptr) + * + * Computes the delta between the two time stamps. + * + * @param Stamp1Ptr - First sampled time stamp. + * @param Stamp1Ptr - Sedond sampled time stamp. + * + * @return An unsigned int value with units of milliseconds. + */ + +/*****************************************************************************//** + * + * XENV_USLEEP(unsigned delay) + * + * Delay the specified number of microseconds. + * + * @param delay is the number of microseconds to delay. + * + * @return None + */ + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xenv_standalone.h b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xenv_standalone.h new file mode 100644 index 0000000..ef905af --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xenv_standalone.h @@ -0,0 +1,364 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xenv_standalone.h +* +* Defines common services specified by xenv.h. +* +* @note +* This file is not intended to be included directly by driver code. +* Instead, the generic xenv.h file is intended to be included by driver +* code. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a wgr  02/28/07 Added cache handling macros.
+* 1.00a wgr  02/27/07 Simplified code. Deprecated old-style macro names.
+* 1.00a rmm  01/24/06 Implemented XENV_USLEEP. Assume implementation is being
+*                     used under Xilinx standalone BSP.
+* 1.00a xd   11/03/04 Improved support for doxygen.
+* 1.00a rmm  03/21/02 First release
+* 1.00a wgr  03/22/07 Converted to new coding style.
+* 1.00a rpm  06/29/07 Added udelay macro for standalone
+* 1.00a xd   07/19/07 Included xparameters.h as XPAR_ constants are referred
+*                     to in MICROBLAZE section
+* 1.00a ecm  09/19/08 updated for v7.20 of Microblaze, new functionality
+*
+* 
+* +* +******************************************************************************/ + +#ifndef XENV_STANDALONE_H +#define XENV_STANDALONE_H + +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ +/****************************************************************************** + * + * Get the processor dependent includes + * + ******************************************************************************/ + +#include + +#if defined __MICROBLAZE__ +# include "mb_interface.h" +# include "xparameters.h" /* XPAR constants used below in MB section */ + +#elif defined __PPC__ +# include "sleep.h" +# include "xcache_l.h" /* also include xcache_l.h for caching macros */ +#endif + +/****************************************************************************** + * + * MEMCPY / MEMSET related macros. + * + * The following are straight forward implementations of memset and memcpy. + * + * NOTE: memcpy may not work if source and target memory area are overlapping. + * + ******************************************************************************/ +/*****************************************************************************/ +/** + * + * Copies a non-overlapping block of memory. + * + * @param DestPtr + * Destination address to copy data to. + * + * @param SrcPtr + * Source address to copy data from. + * + * @param Bytes + * Number of bytes to copy. + * + * @return None. + * + * @note + * The use of XENV_MEM_COPY is deprecated. Use memcpy() instead. + * + * @note + * This implemention MAY BREAK work if source and target memory + * area are overlapping. + * + *****************************************************************************/ + +#define XENV_MEM_COPY(DestPtr, SrcPtr, Bytes) \ + memcpy((void *) DestPtr, (const void *) SrcPtr, (size_t) Bytes) + + + +/*****************************************************************************/ +/** + * + * Fills an area of memory with constant data. + * + * @param DestPtr + * Destination address to copy data to. + * + * @param Data + * Value to set. + * + * @param Bytes + * Number of bytes to copy. + * + * @return None. + * + * @note + * The use of XENV_MEM_FILL is deprecated. Use memset() instead. + * + *****************************************************************************/ + +#define XENV_MEM_FILL(DestPtr, Data, Bytes) \ + memset((void *) DestPtr, (s32) Data, (size_t) Bytes) + + + +/****************************************************************************** + * + * TIME related macros + * + ******************************************************************************/ + +/** + * A structure that contains a time stamp used by other time stamp macros + * defined below. This structure is processor dependent. + */ +typedef s32 XENV_TIME_STAMP; + +/*****************************************************************************/ +/** + * + * Time is derived from the 64 bit PPC timebase register + * + * @param StampPtr is the storage for the retrieved time stamp. + * + * @return None. + * + * @note + * + * Signature: void XENV_TIME_STAMP_GET(XTIME_STAMP *StampPtr) + *

+ * This macro must be implemented by the user. + * + *****************************************************************************/ +#define XENV_TIME_STAMP_GET(StampPtr) + +/*****************************************************************************/ +/** + * + * This macro is not yet implemented and always returns 0. + * + * @param Stamp1Ptr is the first sampled time stamp. + * @param Stamp2Ptr is the second sampled time stamp. + * + * @return 0 + * + * @note + * + * This macro must be implemented by the user. + * + *****************************************************************************/ +#define XENV_TIME_STAMP_DELTA_US(Stamp1Ptr, Stamp2Ptr) (0) + +/*****************************************************************************/ +/** + * + * This macro is not yet implemented and always returns 0. + * + * @param Stamp1Ptr is the first sampled time stamp. + * @param Stamp2Ptr is the second sampled time stamp. + * + * @return 0 + * + * @note + * + * This macro must be implemented by the user. + * + *****************************************************************************/ +#define XENV_TIME_STAMP_DELTA_MS(Stamp1Ptr, Stamp2Ptr) (0) + +/*****************************************************************************/ +/** + * XENV_USLEEP(unsigned delay) + * + * Delay the specified number of microseconds. Not implemented without OS + * support. + * + * @param delay + * Number of microseconds to delay. + * + * @return None. + * + *****************************************************************************/ + +#ifdef __PPC__ +#define XENV_USLEEP(delay) usleep(delay) +#define udelay(delay) usleep(delay) +#else +#define XENV_USLEEP(delay) +#define udelay(delay) +#endif + + +/****************************************************************************** + * + * CACHE handling macros / mappings + * + ******************************************************************************/ +/****************************************************************************** + * + * Processor independent macros + * + ******************************************************************************/ + +#define XCACHE_ENABLE_CACHE() \ + { XCACHE_ENABLE_DCACHE(); XCACHE_ENABLE_ICACHE(); } + +#define XCACHE_DISABLE_CACHE() \ + { XCACHE_DISABLE_DCACHE(); XCACHE_DISABLE_ICACHE(); } + + +/****************************************************************************** + * + * MicroBlaze case + * + * NOTE: Currently the following macros will only work on systems that contain + * only ONE MicroBlaze processor. Also, the macros will only be enabled if the + * system is built using a xparameters.h file. + * + ******************************************************************************/ + +#if defined __MICROBLAZE__ + +/* Check if MicroBlaze data cache was built into the core. + */ +#if (XPAR_MICROBLAZE_USE_DCACHE == 1) +# define XCACHE_ENABLE_DCACHE() microblaze_enable_dcache() +# define XCACHE_DISABLE_DCACHE() microblaze_disable_dcache() +# define XCACHE_INVALIDATE_DCACHE() microblaze_invalidate_dcache() + +# define XCACHE_INVALIDATE_DCACHE_RANGE(Addr, Len) \ + microblaze_invalidate_dcache_range((s32)(Addr), (s32)(Len)) + +#if (XPAR_MICROBLAZE_DCACHE_USE_WRITEBACK == 1) +# define XCACHE_FLUSH_DCACHE() microblaze_flush_dcache() +# define XCACHE_FLUSH_DCACHE_RANGE(Addr, Len) \ + microblaze_flush_dcache_range((s32)(Addr), (s32)(Len)) +#else +# define XCACHE_FLUSH_DCACHE() microblaze_invalidate_dcache() +# define XCACHE_FLUSH_DCACHE_RANGE(Addr, Len) \ + microblaze_invalidate_dcache_range((s32)(Addr), (s32)(Len)) +#endif /*XPAR_MICROBLAZE_DCACHE_USE_WRITEBACK*/ + +#else +# define XCACHE_ENABLE_DCACHE() +# define XCACHE_DISABLE_DCACHE() +# define XCACHE_INVALIDATE_DCACHE_RANGE(Addr, Len) +# define XCACHE_FLUSH_DCACHE_RANGE(Addr, Len) +#endif /*XPAR_MICROBLAZE_USE_DCACHE*/ + + +/* Check if MicroBlaze instruction cache was built into the core. + */ +#if (XPAR_MICROBLAZE_USE_ICACHE == 1) +# define XCACHE_ENABLE_ICACHE() microblaze_enable_icache() +# define XCACHE_DISABLE_ICACHE() microblaze_disable_icache() + +# define XCACHE_INVALIDATE_ICACHE() microblaze_invalidate_icache() + +# define XCACHE_INVALIDATE_ICACHE_RANGE(Addr, Len) \ + microblaze_invalidate_icache_range((s32)(Addr), (s32)(Len)) + +#else +# define XCACHE_ENABLE_ICACHE() +# define XCACHE_DISABLE_ICACHE() +#endif /*XPAR_MICROBLAZE_USE_ICACHE*/ + + +/****************************************************************************** + * + * PowerPC case + * + * Note that the XCACHE_ENABLE_xxx functions are hardcoded to enable a + * specific memory region (0x80000001). Each bit (0-30) in the regions + * bitmask stands for 128MB of memory. Bit 31 stands for the upper 2GB + * range. + * + * regions --> cached address range + * ------------|-------------------------------------------------- + * 0x80000000 | [0, 0x7FFFFFF] + * 0x00000001 | [0xF8000000, 0xFFFFFFFF] + * 0x80000001 | [0, 0x7FFFFFF],[0xF8000000, 0xFFFFFFFF] + * + ******************************************************************************/ + +#elif defined __PPC__ + +#define XCACHE_ENABLE_DCACHE() XCache_EnableDCache(0x80000001) +#define XCACHE_DISABLE_DCACHE() XCache_DisableDCache() +#define XCACHE_ENABLE_ICACHE() XCache_EnableICache(0x80000001) +#define XCACHE_DISABLE_ICACHE() XCache_DisableICache() + +#define XCACHE_INVALIDATE_DCACHE_RANGE(Addr, Len) \ + XCache_InvalidateDCacheRange((u32)(Addr), (u32)(Len)) + +#define XCACHE_FLUSH_DCACHE_RANGE(Addr, Len) \ + XCache_FlushDCacheRange((u32)(Addr), (u32)(Len)) + +#define XCACHE_INVALIDATE_ICACHE() XCache_InvalidateICache() + + +/****************************************************************************** + * + * Unknown processor / architecture + * + ******************************************************************************/ + +#else +/* #error "Unknown processor / architecture. Must be MicroBlaze or PowerPC." */ +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* #ifndef XENV_STANDALONE_H */ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_assert.c b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_assert.c new file mode 100644 index 0000000..f6ec066 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_assert.c @@ -0,0 +1,143 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2016 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_assert.c +* +* This file contains basic assert related functions for Xilinx software IP. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date   Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a hbm  07/14/09 Initial release
+* 6.0   kvn  05/31/16 Make Xil_AsserWait a global variable
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Variable Definitions *****************************/ + +/** + * This variable allows testing to be done easier with asserts. An assert + * sets this variable such that a driver can evaluate this variable + * to determine if an assert occurred. + */ +u32 Xil_AssertStatus; + +/** + * This variable allows the assert functionality to be changed for testing + * such that it does not wait infinitely. Use the debugger to disable the + * waiting during testing of asserts. + */ +s32 Xil_AssertWait = 1; + +/* The callback function to be invoked when an assert is taken */ +static Xil_AssertCallback Xil_AssertCallbackRoutine = NULL; + +/************************** Function Prototypes ******************************/ + +/*****************************************************************************/ +/** +* +* @brief Implement assert. Currently, it calls a user-defined callback +* function if one has been set. Then, it potentially enters an +* infinite loop depending on the value of the Xil_AssertWait +* variable. +* +* @param file: filename of the source +* @param line: linenumber within File +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void Xil_Assert(const char8 *File, s32 Line) +{ + /* if the callback has been set then invoke it */ + if (Xil_AssertCallbackRoutine != 0) { + (*Xil_AssertCallbackRoutine)(File, Line); + } + + /* if specified, wait indefinitely such that the assert will show up + * in testing + */ + while (Xil_AssertWait != 0) { + } +} + +/*****************************************************************************/ +/** +* +* @brief Set up a callback function to be invoked when an assert occurs. +* If a callback is already installed, then it will be replaced. +* +* @param routine: callback to be invoked when an assert is taken +* +* @return None. +* +* @note This function has no effect if NDEBUG is set +* +******************************************************************************/ +void Xil_AssertSetCallback(Xil_AssertCallback Routine) +{ + Xil_AssertCallbackRoutine = Routine; +} + +/*****************************************************************************/ +/** +* +* @brief Null handler function. This follows the XInterruptHandler +* signature for interrupt handlers. It can be used to assign a null +* handler (a stub) to an interrupt controller vector table. +* +* @param NullParameter: arbitrary void pointer and not used. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XNullHandler(void *NullParameter) +{ + (void) NullParameter; +} diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_assert.h b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_assert.h new file mode 100644 index 0000000..917de31 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_assert.h @@ -0,0 +1,191 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_assert.h +* +* @addtogroup common_assert_apis Assert APIs and Macros +* +* The xil_assert.h file contains assert related functions and macros. +* Assert APIs/Macros specifies that a application program satisfies certain +* conditions at particular points in its execution. These function can be +* used by application programs to ensure that, application code is satisfying +* certain conditions. +* +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date   Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a hbm  07/14/09 First release
+* 6.0   kvn  05/31/16 Make Xil_AsserWait a global variable
+* 
+* +******************************************************************************/ + +#ifndef XIL_ASSERT_H /* prevent circular inclusions */ +#define XIL_ASSERT_H /* by using protection macros */ + +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/***************************** Include Files *********************************/ + + +/************************** Constant Definitions *****************************/ + +#define XIL_ASSERT_NONE 0U +#define XIL_ASSERT_OCCURRED 1U +#define XNULL NULL + +extern u32 Xil_AssertStatus; +extern s32 Xil_AssertWait; +extern void Xil_Assert(const char8 *File, s32 Line); +void XNullHandler(void *NullParameter); + +/** + * This data type defines a callback to be invoked when an + * assert occurs. The callback is invoked only when asserts are enabled + */ +typedef void (*Xil_AssertCallback) (const char8 *File, s32 Line); + +/***************** Macros (Inline Functions) Definitions *********************/ + +#ifndef NDEBUG + +/*****************************************************************************/ +/** +* @brief This assert macro is to be used for void functions. This in +* conjunction with the Xil_AssertWait boolean can be used to +* accomodate tests so that asserts which fail allow execution to +* continue. +* +* @param Expression: expression to be evaluated. If it evaluates to +* false, the assert occurs. +* +* @return Returns void unless the Xil_AssertWait variable is true, in which +* case no return is made and an infinite loop is entered. +* +******************************************************************************/ +#define Xil_AssertVoid(Expression) \ +{ \ + if (Expression) { \ + Xil_AssertStatus = XIL_ASSERT_NONE; \ + } else { \ + Xil_Assert(__FILE__, __LINE__); \ + Xil_AssertStatus = XIL_ASSERT_OCCURRED; \ + return; \ + } \ +} + +/*****************************************************************************/ +/** +* @brief This assert macro is to be used for functions that do return a +* value. This in conjunction with the Xil_AssertWait boolean can be +* used to accomodate tests so that asserts which fail allow execution +* to continue. +* +* @param Expression: expression to be evaluated. If it evaluates to false, +* the assert occurs. +* +* @return Returns 0 unless the Xil_AssertWait variable is true, in which +* case no return is made and an infinite loop is entered. +* +******************************************************************************/ +#define Xil_AssertNonvoid(Expression) \ +{ \ + if (Expression) { \ + Xil_AssertStatus = XIL_ASSERT_NONE; \ + } else { \ + Xil_Assert(__FILE__, __LINE__); \ + Xil_AssertStatus = XIL_ASSERT_OCCURRED; \ + return 0; \ + } \ +} + +/*****************************************************************************/ +/** +* @brief Always assert. This assert macro is to be used for void functions. +* Use for instances where an assert should always occur. +* +* @return Returns void unless the Xil_AssertWait variable is true, in which +* case no return is made and an infinite loop is entered. +* +******************************************************************************/ +#define Xil_AssertVoidAlways() \ +{ \ + Xil_Assert(__FILE__, __LINE__); \ + Xil_AssertStatus = XIL_ASSERT_OCCURRED; \ + return; \ +} + +/*****************************************************************************/ +/** +* @brief Always assert. This assert macro is to be used for functions that +* do return a value. Use for instances where an assert should always +* occur. +* +* @return Returns void unless the Xil_AssertWait variable is true, in which +* case no return is made and an infinite loop is entered. +* +******************************************************************************/ +#define Xil_AssertNonvoidAlways() \ +{ \ + Xil_Assert(__FILE__, __LINE__); \ + Xil_AssertStatus = XIL_ASSERT_OCCURRED; \ + return 0; \ +} + + +#else + +#define Xil_AssertVoid(Expression) +#define Xil_AssertVoidAlways() +#define Xil_AssertNonvoid(Expression) +#define Xil_AssertNonvoidAlways() + +#endif + +/************************** Function Prototypes ******************************/ + +void Xil_AssertSetCallback(Xil_AssertCallback Routine); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** +* @} End of "addtogroup common_assert_apis". +*/ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_cache.c b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_cache.c new file mode 100644 index 0000000..ea95ba7 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_cache.c @@ -0,0 +1,88 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_cache.c +* +* This contains implementation of cache related driver functions. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00  hbm  07/28/09 Initial release
+* 3.10  asa  05/04/13 This version of MicroBlaze BSP adds support for system
+*					  cache/L2 cache. Existing APIs in this file are modified
+*					  to add support for L2 cache.
+*					  These changes are done for implementing PR #697214.
+* 
+* +* @note +* +* None. +* +******************************************************************************/ + +#include "xil_cache.h" + + +/****************************************************************************/ +/** +* +* @brief Disable the data cache. +* +* @param None +* +* @return None. +* +****************************************************************************/ +void Xil_DCacheDisable(void) +{ + Xil_DCacheFlush(); + Xil_DCacheInvalidate(); + Xil_L1DCacheDisable(); +} + +/****************************************************************************/ +/** +* +* @brief Disable the instruction cache. +* +* @param None +* +* @return None. +* +* +****************************************************************************/ +void Xil_ICacheDisable(void) +{ + Xil_ICacheInvalidate(); + Xil_L1ICacheDisable(); +} diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_cache.h b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_cache.h new file mode 100644 index 0000000..c9ff61d --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_cache.h @@ -0,0 +1,433 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_cache.h +* +* The xil_cache.h file contains cache related driver functions (or macros) +* that can be used to access the device. The user should refer to the +* hardware device specification for more details of the device operation. +* The functions in this header file can be used across all Xilinx supported +* processors. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00  hbm  07/28/09 Initial release
+* 3.02a sdm  10/24/11 Updated the file to include xparameters.h so that
+*                     the correct cache flush routines are used based on
+*                     whether the write-back or write-through caches are
+*                     used (cr #630532).
+* 3.10a asa  05/04/13 This version of MicroBlaze BSP adds support for system
+*					  cache/L2 cache. The existing/old APIs/macros in this
+*					  file are renamed to imply that they deal with L1 cache.
+*					  New macros/APIs are added to address similar features for
+*					  L2 cache. Users can include this file in their application
+*					  to use the various cache related APIs. These changes are
+*					  done for implementing PR #697214.
+*
+* 
+* +* @note +* +******************************************************************************/ + +#ifndef XIL_CACHE_H +#define XIL_CACHE_H + +#if defined XENV_VXWORKS +/* VxWorks environment */ +#error "Unknown processor / architecture. Must be PPC for VxWorks." +#else +/* standalone environment */ + +#include "mb_interface.h" +#include "xil_types.h" +#include "xparameters.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/****************************************************************************/ +/** +* +* @brief Invalidate the entire L1 data cache. If the cacheline is modified +* (dirty), the modified contents are lost. +* +* @param None. +* +* @return None. +* +* @note +* +* Processor must be in real mode. +****************************************************************************/ +#define Xil_L1DCacheInvalidate() microblaze_invalidate_dcache() + +/****************************************************************************/ +/** +* +* @brief Invalidate the entire L2 data cache. If the cacheline is modified +* (dirty),the modified contents are lost. +* +* @param None. +* +* @return None. +* +* @note +* +* Processor must be in real mode. +****************************************************************************/ +#define Xil_L2CacheInvalidate() microblaze_invalidate_cache_ext() + +/****************************************************************************/ +/** +* +* @brief Invalidate the L1 data cache for the given address range. +* If the bytes specified by the address (Addr) are cached by the L1 +* data cache, the cacheline containing that byte is invalidated.If +* the cacheline is modified (dirty), the modified contents are lost. +* +* @param Addr is address of ragne to be invalidated. +* @param Len is the length in bytes to be invalidated. +* +* @return None. +* +* @note +* +* Processor must be in real mode. +****************************************************************************/ +#define Xil_L1DCacheInvalidateRange(Addr, Len) \ + microblaze_invalidate_dcache_range((Addr), (Len)) + +/****************************************************************************/ +/** +* +* @brief Invalidate the L1 data cache for the given address range. +* If the bytes specified by the address (Addr) are cached by the +* L1 data cache, the cacheline containing that byte is invalidated. +* If the cacheline is modified (dirty), the modified contents are lost. +* +* @param Addr: address of ragne to be invalidated. +* @param Len: length in bytes to be invalidated. +* +* @return None. +* +* @note +* Processor must be in real mode. +****************************************************************************/ +#define Xil_L2CacheInvalidateRange(Addr, Len) \ + microblaze_invalidate_cache_ext_range((Addr), (Len)) + +/****************************************************************************/ +/** +* @brief Flush the L1 data cache for the given address range. +* If the bytes specified by the address (Addr) are cached by the +* data cache, and is modified (dirty), the cacheline will be written +* to system memory.The cacheline will also be invalidated. +* +* @param Addr: the starting address of the range to be flushed. +* @param Len: length in byte to be flushed. +* +* @return None. +* +****************************************************************************/ +#if (XPAR_MICROBLAZE_DCACHE_USE_WRITEBACK == 1) +# define Xil_L1DCacheFlushRange(Addr, Len) \ + microblaze_flush_dcache_range((Addr), (Len)) +#else +# define Xil_L1DCacheFlushRange(Addr, Len) \ + microblaze_invalidate_dcache_range((Addr), (Len)) +#endif /* XPAR_MICROBLAZE_DCACHE_USE_WRITEBACK */ + +/****************************************************************************/ +/** +* @brief Flush the L2 data cache for the given address range. +* If the bytes specified by the address (Addr) are cached by the +* data cache, and is modified (dirty), the cacheline will be +* written to system memory. The cacheline will also be invalidated. +* +* @param Addr: the starting address of the range to be flushed. +* @param Len: length in byte to be flushed. +* +* @return None. +* +****************************************************************************/ +#define Xil_L2CacheFlushRange(Addr, Len) \ + microblaze_flush_cache_ext_range((Addr), (Len)) + +/****************************************************************************/ +/** +* @brief Flush the entire L1 data cache. If any cacheline is dirty, the +* cacheline will be written to system memory. The entire data cache +* will be invalidated. +* +* @return None. +* +****************************************************************************/ +#if (XPAR_MICROBLAZE_DCACHE_USE_WRITEBACK == 1) +# define Xil_L1DCacheFlush() microblaze_flush_dcache() +#else +# define Xil_L1DCacheFlush() microblaze_invalidate_dcache() +#endif /* XPAR_MICROBLAZE_DCACHE_USE_WRITEBACK */ + +/****************************************************************************/ +/** +* @brief Flush the entire L2 data cache. If any cacheline is dirty, the +* cacheline will be written to system memory. The entire data cache +* will be invalidated. +* +* @return None. +* +****************************************************************************/ +#define Xil_L2CacheFlush() microblaze_flush_cache_ext() + +/****************************************************************************/ +/** +* +* @brief Invalidate the instruction cache for the given address range. +* +* @param Addr is address of ragne to be invalidated. +* @param Len is the length in bytes to be invalidated. +* +* @return None. +* +****************************************************************************/ +#define Xil_L1ICacheInvalidateRange(Addr, Len) \ + microblaze_invalidate_icache_range((Addr), (Len)) + +/****************************************************************************/ +/** +* +* @brief Invalidate the entire instruction cache. +* +* @param None +* +* @return None. +* +****************************************************************************/ +#define Xil_L1ICacheInvalidate() \ + microblaze_invalidate_icache() + + +/****************************************************************************/ +/** +* +* @brief Enable the L1 data cache. +* +* @return None. +* +* @note This is processor specific. +* +****************************************************************************/ +#define Xil_L1DCacheEnable() \ + microblaze_enable_dcache() + +/****************************************************************************/ +/** +* +* @brief Disable the L1 data cache. +* +* @return None. +* +* @note This is processor specific. +* +****************************************************************************/ +#define Xil_L1DCacheDisable() \ + microblaze_disable_dcache() + +/****************************************************************************/ +/** +* +* @brief Enable the instruction cache. +* +* @return None. +* +* @note This is processor specific. +* +****************************************************************************/ +#define Xil_L1ICacheEnable() \ + microblaze_enable_icache() + +/****************************************************************************/ +/** +* +* @brief Disable the L1 Instruction cache. +* +* @return None. +* +* @note This is processor specific. +* +****************************************************************************/ +#define Xil_L1ICacheDisable() \ + microblaze_disable_icache() + +/****************************************************************************/ +/** +* +* @brief Enable the data cache. +* +* @param None +* +* @return None. +* +****************************************************************************/ +#define Xil_DCacheEnable() Xil_L1DCacheEnable() + +/****************************************************************************/ +/** +* +* @brief Enable the instruction cache. +* +* @param None +* +* @return None. +* +* @note +* +* +****************************************************************************/ +#define Xil_ICacheEnable() Xil_L1ICacheEnable() + +/**************************************************************************** +* +* @brief Invalidate the entire Data cache. +* +* @param None. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +#define Xil_DCacheInvalidate() \ + Xil_L2CacheInvalidate(); \ + Xil_L1DCacheInvalidate(); + + +/**************************************************************************** +* +* @brief Invalidate the Data cache for the given address range. +* If the bytes specified by the address (adr) are cached by the +* Data cache, the cacheline containing that byte is invalidated. +* If the cacheline is modified (dirty), the modified contents are +* lost and are NOT written to system memory before the line is +* invalidated. +* +* @param Addr: Start address of ragne to be invalidated. +* @param Len: Length of range to be invalidated in bytes. +* +* @return None. +* +****************************************************************************/ +#define Xil_DCacheInvalidateRange(Addr, Len) \ + Xil_L2CacheInvalidateRange((Addr), (Len)); \ + Xil_L1DCacheInvalidateRange((Addr), (Len)); + + +/**************************************************************************** +* +* @brief Flush the entire Data cache. +* +* @param None. +* +* @return None. +* +****************************************************************************/ +#define Xil_DCacheFlush() \ + Xil_L2CacheFlush(); \ + Xil_L1DCacheFlush(); + +/**************************************************************************** +* @brief Flush the Data cache for the given address range. +* If the bytes specified by the address (adr) are cached by the +* Data cache, the cacheline containing that byte is invalidated. +* If the cacheline is modified (dirty), the written to system +* memory first before the before the line is invalidated. +* +* @param Addr: Start address of range to be flushed. +* @param Len: Length of range to be flushed in bytes. +* +* @return None. +* +****************************************************************************/ +#define Xil_DCacheFlushRange(Addr, Len) \ + Xil_L2CacheFlushRange((Addr), (Len)); \ + Xil_L1DCacheFlushRange((Addr), (Len)); + + +/**************************************************************************** +* +* @brief Invalidate the entire instruction cache. +* +* @param None. +* +* @return None. +* +****************************************************************************/ +#define Xil_ICacheInvalidate() \ + Xil_L2CacheInvalidate(); \ + Xil_L1ICacheInvalidate(); + + +/**************************************************************************** +* +* @brief Invalidate the instruction cache for the given address range. +* If the bytes specified by the address (adr) are cached by the +* Data cache, the cacheline containing that byte is invalidated. +* If the cacheline is modified (dirty), the modified contents are +* lost and are NOT written to system memory before the line is +* invalidated. +* +* @param Addr: Start address of ragne to be invalidated. +* @param Len: Length of range to be invalidated in bytes. +* +* @return None. +* +****************************************************************************/ +#define Xil_ICacheInvalidateRange(Addr, Len) \ + Xil_L2CacheInvalidateRange((Addr), (Len)); \ + Xil_L1ICacheInvalidateRange((Addr), (Len)); + +void Xil_DCacheDisable(void); +void Xil_ICacheDisable(void); + +#ifdef __cplusplus +} +#endif + +#endif + +#endif +/** +* @} End of "addtogroup microblaze_cache_apis". +*/ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_cache_vxworks.h b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_cache_vxworks.h new file mode 100644 index 0000000..7e2a7d9 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_cache_vxworks.h @@ -0,0 +1,89 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_cache_vxworks.h +* +* Contains the cache related functions for VxWorks that is wrapped by +* xil_cache. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date	 Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a hbm  12/11/09 Initial release
+*
+* 
+* +* @note +* +******************************************************************************/ + +#ifndef XIL_CACHE_VXWORKS_H +#define XIL_CACHE_VXWORKS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "vxWorks.h" +#include "vxLib.h" +#include "sysLibExtra.h" +#include "cacheLib.h" + +#if (CPU_FAMILY==PPC) + +#define Xil_DCacheEnable() cacheEnable(DATA_CACHE) + +#define Xil_DCacheDisable() cacheDisable(DATA_CACHE) + +#define Xil_DCacheInvalidateRange(Addr, Len) \ + cacheInvalidate(DATA_CACHE, (void *)(Addr), (Len)) + +#define Xil_DCacheFlushRange(Addr, Len) \ + cacheFlush(DATA_CACHE, (void *)(Addr), (Len)) + +#define Xil_ICacheEnable() cacheEnable(INSTRUCTION_CACHE) + +#define Xil_ICacheDisable() cacheDisable(INSTRUCTION_CACHE) + +#define Xil_ICacheInvalidateRange(Addr, Len) \ + cacheInvalidate(INSTRUCTION_CACHE, (void *)(Addr), (Len)) + + +#else +#error "Unknown processor / architecture. Must be PPC for VxWorks." +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_exception.c b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_exception.c new file mode 100644 index 0000000..d56af82 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_exception.c @@ -0,0 +1,210 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_exception.c +* +* This file contains implementation of exception related driver functions. +* +* @addtogroup microblaze_exception_apis Microblaze exception APIs +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00  hbm  07/28/09 Initial release
+* 6.2   ms   02/20/17 Fixed compilation warning. This is a fix for CR-969126.
+*
+* 
+* +* @note +* +* None. +* +******************************************************************************/ + +#include "xil_types.h" +#include "xil_exception.h" + +#include "microblaze_exceptions_g.h" +#include "microblaze_interrupts_i.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern void microblaze_enable_exceptions(void); +extern void microblaze_disable_exceptions(void); +extern void microblaze_enable_interrupts(void); +extern void microblaze_disable_interrupts(void); + +/** +* Currently HAL is an augmented part of standalone BSP, so the old definition +* of MB_ExceptionVectorTableEntry is used here. +*/ + +typedef struct { + Xil_ExceptionHandler Handler; + void *CallBackRef; +} MB_ExceptionVectorTableEntry; + +#ifdef __cplusplus +} +#endif + + +/************************** Variable Definitions *****************************/ +extern MB_ExceptionVectorTableEntry MB_ExceptionVectorTable[XIL_EXCEPTION_ID_INT]; +extern MB_InterruptVectorTableEntry MB_InterruptVectorTable[MB_INTERRUPT_VECTOR_TABLE_ENTRIES]; + +/****************************************************************************/ +/** + * @brief This function is a stub handler that is the default handler that gets + * called if the application has not setup a handler for a specific + * exception. The function interface has to match the interface + * specified for a handler even though none of the arguments are used. + * + * @param Data: unused by this function. + * + *****************************************************************************/ +static void Xil_ExceptionNullHandler(void *Data) +{ + (void) Data; +} + +/****************************************************************************/ +/** +* @brief Initialize exception handling for the processor. The exception +* vector table is setup with the stub handler for all exceptions. +* +* @param None. +* +* @return None. +* +*****************************************************************************/ +void Xil_ExceptionInit(void) +{ + /* + * there is no need to setup the exception table here + */ + +} + +/****************************************************************************/ +/** +* @brief Enable Exceptions. +* +* @return None. +* +******************************************************************************/ +void Xil_ExceptionEnable(void) +{ +#ifdef MICROBLAZE_EXCEPTIONS_ENABLED + microblaze_enable_exceptions(); +#endif + microblaze_enable_interrupts(); +} + +/****************************************************************************/ +/** +* @brief Disable Exceptions. +* +* @param None. +* +* @return None. +* +******************************************************************************/ +void Xil_ExceptionDisable(void) +{ +#ifdef MICROBLAZE_EXCEPTIONS_ENABLED + microblaze_disable_exceptions(); +#endif + microblaze_disable_interrupts(); +} + +/*****************************************************************************/ +/** +*@brief Makes the connection between the Id of the exception source and the +* associated handler that is to run when the exception is recognized. +* The argument provided in this call as the DataPtr is used as the +* argument for the handler when it is called. +* +* @param Id: contains the 32 bit ID of the exception source and should +* be XIL_EXCEPTION_INT or be in the range of 0 to XIL_EXCEPTION_LAST. +* See xil_mach_exception.h for further information. +* @param Handler: handler function to be registered for exception +* @param Data: a reference to data that will be passed to the handler +* when it gets called. +* +****************************************************************************/ +void Xil_ExceptionRegisterHandler(u32 Id, Xil_ExceptionHandler Handler, + void *Data) +{ + if (Id == XIL_EXCEPTION_ID_INT) { + MB_InterruptVectorTable[0].Handler = Handler; + MB_InterruptVectorTable[0].CallBackRef = Data; + } + else { +#ifdef MICROBLAZE_EXCEPTIONS_ENABLED + MB_ExceptionVectorTable[Id].Handler = Handler; + MB_ExceptionVectorTable[Id].CallBackRef = Data; +#endif + } +} + + +/*****************************************************************************/ +/** +* @brief Removes the handler for a specific exception Id. The stub handler +* is then registered for this exception Id. +* +* @param Id: contains the 32 bit ID of the exception source and should +* be XIL_EXCEPTION_INT or in the range of 0 to XIL_EXCEPTION_LAST. +* See xexception_l.h for further information. +* +****************************************************************************/ +void Xil_ExceptionRemoveHandler(u32 Id) +{ + if (Id == XIL_EXCEPTION_ID_INT) { + MB_InterruptVectorTable[0].Handler = Xil_ExceptionNullHandler; + MB_InterruptVectorTable[0].CallBackRef = NULL; + } + else { + +#ifdef MICROBLAZE_EXCEPTIONS_ENABLED + MB_ExceptionVectorTable[Id].Handler = + Xil_ExceptionNullHandler; + MB_ExceptionVectorTable[Id].CallBackRef = NULL; +#endif + } +} +/** +* @} End of "addtogroup microblaze_exception_apis". +*/ \ No newline at end of file diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_exception.h b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_exception.h new file mode 100644 index 0000000..07c5357 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_exception.h @@ -0,0 +1,127 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_exception.h +* +* @addtogroup microblaze_exception_apis Microblaze Exception APIs +* +* The xil_exception.h file contains Microblaze specific exception +* related APIs and macros. Application programs can use these APIs/Macros +* for various exception related operations (i.e. enable exception, disable +* exception, register exception hander etc.) +* +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00  hbm  07/28/09 Initial release
+*
+* 
+* +* @note +* To use exception related functions, the xil_exception.h file must be added in +* source code +* +******************************************************************************/ + +#ifndef XIL_EXCEPTION_H /* prevent circular inclusions */ +#define XIL_EXCEPTION_H /* by using protection macros */ + +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************** Constant Definitions *****************************/ + +/* + * These constants are specific to Microblaze processor. + */ + +#define XIL_EXCEPTION_ID_FIRST 0U +#define XIL_EXCEPTION_ID_FSL 0U +#define XIL_EXCEPTION_ID_UNALIGNED_ACCESS 1U +#define XIL_EXCEPTION_ID_ILLEGAL_OPCODE 2U +#define XIL_EXCEPTION_ID_M_AXI_I_EXCEPTION 3U +#define XIL_EXCEPTION_ID_IPLB_EXCEPTION 3U +#define XIL_EXCEPTION_ID_M_AXI_D_EXCEPTION 4U +#define XIL_EXCEPTION_ID_DPLB_EXCEPTION 4U +#define XIL_EXCEPTION_ID_DIV_BY_ZERO 5U +#define XIL_EXCEPTION_ID_FPU 6U +#define XIL_EXCEPTION_ID_STACK_VIOLATION 7U +#define XIL_EXCEPTION_ID_MMU 7U +#define XIL_EXCEPTION_ID_LAST XIL_EXCEPTION_ID_MMU + +/* + * XIL_EXCEPTION_ID_INT is defined for all processors, but with different value. + */ +#define XIL_EXCEPTION_ID_INT 16U /** + * exception ID for interrupt + */ + +/**************************** Type Definitions *******************************/ + +/** + * This typedef is the exception handler function. + */ +typedef void (*Xil_ExceptionHandler)(void *Data); + +/** + * This data type defines an interrupt handler for a device. + * The argument points to the instance of the component + */ +typedef void (*XInterruptHandler) (void *InstancePtr); + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + +extern void Xil_ExceptionRegisterHandler(u32 Id, + Xil_ExceptionHandler Handler, + void *Data); + +extern void Xil_ExceptionRemoveHandler(u32 Id); + +extern void Xil_ExceptionInit(void); +extern void Xil_ExceptionEnable(void); +extern void Xil_ExceptionDisable(void); + +#ifdef __cplusplus +} +#endif + +#endif +/** +* @} End of "addtogroup microblaze_exception_apis". +*/ \ No newline at end of file diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_hal.h b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_hal.h new file mode 100644 index 0000000..e8971c9 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_hal.h @@ -0,0 +1,65 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_hal.h +* +* Contains all the HAL header files. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date	 Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a hbm  07/28/09 Initial release
+*
+* 
+* +* @note +* +******************************************************************************/ + +#ifndef XIL_HAL_H +#define XIL_HAL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "xil_cache.h" +#include "xil_io.h" +#include "xil_assert.h" +#include "xil_exception.h" +#include "xil_types.h" + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_io.c b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_io.c new file mode 100644 index 0000000..6ed1559 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_io.c @@ -0,0 +1,98 @@ +/****************************************************************************** +* +* Copyright (C) 2014 - 2016 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_io.c +* +* Contains I/O functions for memory-mapped or non-memory-mapped I/O +* architectures. +* +* @note +* +* This file contains architecture-dependent code. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 5.00 	pkp  	 05/29/14 First release
+* 
+******************************************************************************/ + + +/***************************** Include Files *********************************/ +#include "xil_io.h" +#include "xil_types.h" +#include "xil_assert.h" + +/*****************************************************************************/ +/** +* +* @brief Perform a 16-bit endian converion. +* +* @param Data: 16 bit value to be converted +* +* @return 16 bit Data with converted endianess +* +******************************************************************************/ +u16 Xil_EndianSwap16(u16 Data) +{ + return (u16) (((Data & 0xFF00U) >> 8U) | ((Data & 0x00FFU) << 8U)); +} + +/*****************************************************************************/ +/** +* +* @brief Perform a 32-bit endian converion. +* +* @param Data: 32 bit value to be converted +* +* @return 32 bit data with converted endianess +* +******************************************************************************/ +u32 Xil_EndianSwap32(u32 Data) +{ + u16 LoWord; + u16 HiWord; + + /* get each of the half words from the 32 bit word */ + + LoWord = (u16) (Data & 0x0000FFFFU); + HiWord = (u16) ((Data & 0xFFFF0000U) >> 16U); + + /* byte swap each of the 16 bit half words */ + + LoWord = (((LoWord & 0xFF00U) >> 8U) | ((LoWord & 0x00FFU) << 8U)); + HiWord = (((HiWord & 0xFF00U) >> 8U) | ((HiWord & 0x00FFU) << 8U)); + + /* swap the half words before returning the value */ + + return ((((u32)LoWord) << (u32)16U) | (u32)HiWord); +} diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_io.h b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_io.h new file mode 100644 index 0000000..00207cf --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_io.h @@ -0,0 +1,341 @@ +/****************************************************************************** +* +* Copyright (C) 2014 - 2016 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_io.h +* +* @addtogroup common_io_interfacing_apis Register IO interfacing APIs +* +* The xil_io.h file contains the interface for the general I/O component, which +* encapsulates the Input/Output functions for the processors that do not +* require any special I/O handling. +* +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 5.00 	pkp  	 05/29/14 First release
+* 6.00  mus      08/19/16 Remove checking of __LITTLE_ENDIAN__ flag for
+*                         ARM processors
+* 
+******************************************************************************/ + +#ifndef XIL_IO_H /* prevent circular inclusions */ +#define XIL_IO_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_printf.h" + +#if defined (__MICROBLAZE__) +#include "mb_interface.h" +#else +#include "xpseudo_asm.h" +#endif + +/************************** Function Prototypes ******************************/ +u16 Xil_EndianSwap16(u16 Data); +u32 Xil_EndianSwap32(u32 Data); +#ifdef ENABLE_SAFETY +extern u32 XStl_RegUpdate(u32 RegAddr, u32 RegVal); +#endif + +/***************** Macros (Inline Functions) Definitions *********************/ +#if defined __GNUC__ +#if defined (__MICROBLAZE__) +# define INST_SYNC mbar(0) +# define DATA_SYNC mbar(1) +# else +# define SYNCHRONIZE_IO dmb() +# define INST_SYNC isb() +# define DATA_SYNC dsb() +# endif +#else +# define SYNCHRONIZE_IO +# define INST_SYNC +# define DATA_SYNC +# define INST_SYNC +# define DATA_SYNC +#endif + +#if defined (__GNUC__) || defined (__ICCARM__) || defined (__MICROBLAZE__) +#define INLINE inline +#else +#define INLINE __inline +#endif + +/*****************************************************************************/ +/** +* +* @brief Performs an input operation for a memory location by reading +* from the specified address and returning the 8 bit Value read from +* that address. +* +* @param Addr: contains the address to perform the input operation +* +* @return The 8 bit Value read from the specified input address. + +* +******************************************************************************/ +static INLINE u8 Xil_In8(UINTPTR Addr) +{ + return *(volatile u8 *) Addr; +} + +/*****************************************************************************/ +/** +* +* @brief Performs an input operation for a memory location by reading from +* the specified address and returning the 16 bit Value read from that +* address. +* +* @param Addr: contains the address to perform the input operation +* +* @return The 16 bit Value read from the specified input address. +* +******************************************************************************/ +static INLINE u16 Xil_In16(UINTPTR Addr) +{ + return *(volatile u16 *) Addr; +} + +/*****************************************************************************/ +/** +* +* @brief Performs an input operation for a memory location by +* reading from the specified address and returning the 32 bit Value +* read from that address. +* +* @param Addr: contains the address to perform the input operation +* +* @return The 32 bit Value read from the specified input address. +* +******************************************************************************/ +static INLINE u32 Xil_In32(UINTPTR Addr) +{ + return *(volatile u32 *) Addr; +} + +/*****************************************************************************/ +/** +* +* @brief Performs an input operation for a memory location by reading the +* 64 bit Value read from that address. +* +* +* @param Addr: contains the address to perform the input operation +* +* @return The 64 bit Value read from the specified input address. +* +******************************************************************************/ +static INLINE u64 Xil_In64(UINTPTR Addr) +{ + return *(volatile u64 *) Addr; +} + +/*****************************************************************************/ +/** +* +* @brief Performs an output operation for an memory location by +* writing the 8 bit Value to the the specified address. +* +* @param Addr: contains the address to perform the output operation +* @param Value: contains the 8 bit Value to be written at the specified +* address. +* +* @return None. +* +******************************************************************************/ +static INLINE void Xil_Out8(UINTPTR Addr, u8 Value) +{ + volatile u8 *LocalAddr = (volatile u8 *)Addr; + *LocalAddr = Value; +} + +/*****************************************************************************/ +/** +* +* @brief Performs an output operation for a memory location by writing the +* 16 bit Value to the the specified address. +* +* @param Addr contains the address to perform the output operation +* @param Value contains the Value to be written at the specified address. +* +* @return None. +* +******************************************************************************/ +static INLINE void Xil_Out16(UINTPTR Addr, u16 Value) +{ + volatile u16 *LocalAddr = (volatile u16 *)Addr; + *LocalAddr = Value; +} + +/*****************************************************************************/ +/** +* +* @brief Performs an output operation for a memory location by writing the +* 32 bit Value to the the specified address. +* +* @param Addr contains the address to perform the output operation +* @param Value contains the 32 bit Value to be written at the specified +* address. +* +* @return None. +* +******************************************************************************/ +static INLINE void Xil_Out32(UINTPTR Addr, u32 Value) +{ +#ifndef ENABLE_SAFETY + volatile u32 *LocalAddr = (volatile u32 *)Addr; + *LocalAddr = Value; +#else + XStl_RegUpdate(Addr, Value); +#endif +} + +/*****************************************************************************/ +/** +* +* @brief Performs an output operation for a memory location by writing the +* 64 bit Value to the the specified address. +* +* @param Addr contains the address to perform the output operation +* @param Value contains 64 bit Value to be written at the specified address. +* +* @return None. +* +******************************************************************************/ +static INLINE void Xil_Out64(UINTPTR Addr, u64 Value) +{ + volatile u64 *LocalAddr = (volatile u64 *)Addr; + *LocalAddr = Value; +} + +#if defined (__MICROBLAZE__) +#ifdef __LITTLE_ENDIAN__ +# define Xil_In16LE Xil_In16 +# define Xil_In32LE Xil_In32 +# define Xil_Out16LE Xil_Out16 +# define Xil_Out32LE Xil_Out32 +# define Xil_Htons Xil_EndianSwap16 +# define Xil_Htonl Xil_EndianSwap32 +# define Xil_Ntohs Xil_EndianSwap16 +# define Xil_Ntohl Xil_EndianSwap32 +# else +# define Xil_In16BE Xil_In16 +# define Xil_In32BE Xil_In32 +# define Xil_Out16BE Xil_Out16 +# define Xil_Out32BE Xil_Out32 +# define Xil_Htons(Data) (Data) +# define Xil_Htonl(Data) (Data) +# define Xil_Ntohs(Data) (Data) +# define Xil_Ntohl(Data) (Data) +#endif +#else +# define Xil_In16LE Xil_In16 +# define Xil_In32LE Xil_In32 +# define Xil_Out16LE Xil_Out16 +# define Xil_Out32LE Xil_Out32 +# define Xil_Htons Xil_EndianSwap16 +# define Xil_Htonl Xil_EndianSwap32 +# define Xil_Ntohs Xil_EndianSwap16 +# define Xil_Ntohl Xil_EndianSwap32 +#endif + +#if defined (__MICROBLAZE__) +#ifdef __LITTLE_ENDIAN__ +static INLINE u16 Xil_In16BE(UINTPTR Addr) +#else +static INLINE u16 Xil_In16LE(UINTPTR Addr) +#endif +#else +static INLINE u16 Xil_In16BE(UINTPTR Addr) +#endif +{ + u16 value = Xil_In16(Addr); + return Xil_EndianSwap16(value); +} + +#if defined (__MICROBLAZE__) +#ifdef __LITTLE_ENDIAN__ +static INLINE u32 Xil_In32BE(UINTPTR Addr) +#else +static INLINE u32 Xil_In32LE(UINTPTR Addr) +#endif +#else +static INLINE u32 Xil_In32BE(UINTPTR Addr) +#endif +{ + u32 value = Xil_In32(Addr); + return Xil_EndianSwap32(value); +} + +#if defined (__MICROBLAZE__) +#ifdef __LITTLE_ENDIAN__ +static INLINE void Xil_Out16BE(UINTPTR Addr, u16 Value) +#else +static INLINE void Xil_Out16LE(UINTPTR Addr, u16 Value) +#endif +#else +static INLINE void Xil_Out16BE(UINTPTR Addr, u16 Value) +#endif +{ + Value = Xil_EndianSwap16(Value); + Xil_Out16(Addr, Value); +} + +#if defined (__MICROBLAZE__) +#ifdef __LITTLE_ENDIAN__ +static INLINE void Xil_Out32BE(UINTPTR Addr, u32 Value) +#else +static INLINE void Xil_Out32LE(UINTPTR Addr, u32 Value) +#endif +#else +static INLINE void Xil_Out32BE(UINTPTR Addr, u32 Value) +#endif +{ + Value = Xil_EndianSwap32(Value); + Xil_Out32(Addr, Value); +} + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** +* @} End of "addtogroup common_io_interfacing_apis". +*/ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_macroback.h b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_macroback.h new file mode 100644 index 0000000..b245c18 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_macroback.h @@ -0,0 +1,1056 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +/*********************************************************************/ +/** + * @file xil_macroback.h + * + * This header file is meant to bring back the removed _m macros. + * This header file must be included last. + * The following macros are not defined here due to the driver change: + * XGpio_mSetDataDirection + * XGpio_mGetDataReg + * XGpio_mSetDataReg + * XIIC_RESET + * XIIC_CLEAR_STATS + * XSpi_mReset + * XSysAce_mSetCfgAddr + * XSysAce_mIsCfgDone + * XTft_mSetPixel + * XTft_mGetPixel + * XWdtTb_mEnableWdt + * XWdtTb_mDisbleWdt + * XWdtTb_mRestartWdt + * XWdtTb_mGetTimebaseReg + * XWdtTb_mHasReset + * + * Please refer the corresonding driver document for replacement. + * + *********************************************************************/ + +#ifndef XIL_MACROBACK_H +#define XIL_MACROBACK_H + +#ifdef __cplusplus +extern "C" { +#endif + +/*********************************************************************/ +/** + * Macros for Driver XCan + * + *********************************************************************/ +#ifndef XCan_mReadReg +#define XCan_mReadReg XCan_ReadReg +#endif + +#ifndef XCan_mWriteReg +#define XCan_mWriteReg XCan_WriteReg +#endif + +#ifndef XCan_mIsTxDone +#define XCan_mIsTxDone XCan_IsTxDone +#endif + +#ifndef XCan_mIsTxFifoFull +#define XCan_mIsTxFifoFull XCan_IsTxFifoFull +#endif + +#ifndef XCan_mIsHighPriorityBufFull +#define XCan_mIsHighPriorityBufFull XCan_IsHighPriorityBufFull +#endif + +#ifndef XCan_mIsRxEmpty +#define XCan_mIsRxEmpty XCan_IsRxEmpty +#endif + +#ifndef XCan_mIsAcceptFilterBusy +#define XCan_mIsAcceptFilterBusy XCan_IsAcceptFilterBusy +#endif + +#ifndef XCan_mCreateIdValue +#define XCan_mCreateIdValue XCan_CreateIdValue +#endif + +#ifndef XCan_mCreateDlcValue +#define XCan_mCreateDlcValue XCan_CreateDlcValue +#endif + +/*********************************************************************/ +/** + * Macros for Driver XDmaCentral + * + *********************************************************************/ +#ifndef XDmaCentral_mWriteReg +#define XDmaCentral_mWriteReg XDmaCentral_WriteReg +#endif + +#ifndef XDmaCentral_mReadReg +#define XDmaCentral_mReadReg XDmaCentral_ReadReg +#endif + +/*********************************************************************/ +/** + * Macros for Driver XDsAdc + * + *********************************************************************/ +#ifndef XDsAdc_mWriteReg +#define XDsAdc_mWriteReg XDsAdc_WriteReg +#endif + +#ifndef XDsAdc_mReadReg +#define XDsAdc_mReadReg XDsAdc_ReadReg +#endif + +#ifndef XDsAdc_mIsEmpty +#define XDsAdc_mIsEmpty XDsAdc_IsEmpty +#endif + +#ifndef XDsAdc_mSetFstmReg +#define XDsAdc_mSetFstmReg XDsAdc_SetFstmReg +#endif + +#ifndef XDsAdc_mGetFstmReg +#define XDsAdc_mGetFstmReg XDsAdc_GetFstmReg +#endif + +#ifndef XDsAdc_mEnableConversion +#define XDsAdc_mEnableConversion XDsAdc_EnableConversion +#endif + +#ifndef XDsAdc_mDisableConversion +#define XDsAdc_mDisableConversion XDsAdc_DisableConversion +#endif + +#ifndef XDsAdc_mGetFifoOccyReg +#define XDsAdc_mGetFifoOccyReg XDsAdc_GetFifoOccyReg +#endif + +/*********************************************************************/ +/** + * Macros for Driver XDsDac + * + *********************************************************************/ +#ifndef XDsDac_mWriteReg +#define XDsDac_mWriteReg XDsDac_WriteReg +#endif + +#ifndef XDsDac_mReadReg +#define XDsDac_mReadReg XDsDac_ReadReg +#endif + +#ifndef XDsDac_mIsEmpty +#define XDsDac_mIsEmpty XDsDac_IsEmpty +#endif + +#ifndef XDsDac_mFifoIsFull +#define XDsDac_mFifoIsFull XDsDac_FifoIsFull +#endif + +#ifndef XDsDac_mGetVacancy +#define XDsDac_mGetVacancy XDsDac_GetVacancy +#endif + +/*********************************************************************/ +/** + * Macros for Driver XEmacLite + * + *********************************************************************/ +#ifndef XEmacLite_mReadReg +#define XEmacLite_mReadReg XEmacLite_ReadReg +#endif + +#ifndef XEmacLite_mWriteReg +#define XEmacLite_mWriteReg XEmacLite_WriteReg +#endif + +#ifndef XEmacLite_mGetTxStatus +#define XEmacLite_mGetTxStatus XEmacLite_GetTxStatus +#endif + +#ifndef XEmacLite_mSetTxStatus +#define XEmacLite_mSetTxStatus XEmacLite_SetTxStatus +#endif + +#ifndef XEmacLite_mGetRxStatus +#define XEmacLite_mGetRxStatus XEmacLite_GetRxStatus +#endif + +#ifndef XEmacLite_mSetRxStatus +#define XEmacLite_mSetRxStatus XEmacLite_SetRxStatus +#endif + +#ifndef XEmacLite_mIsTxDone +#define XEmacLite_mIsTxDone XEmacLite_IsTxDone +#endif + +#ifndef XEmacLite_mIsRxEmpty +#define XEmacLite_mIsRxEmpty XEmacLite_IsRxEmpty +#endif + +#ifndef XEmacLite_mNextTransmitAddr +#define XEmacLite_mNextTransmitAddr XEmacLite_NextTransmitAddr +#endif + +#ifndef XEmacLite_mNextReceiveAddr +#define XEmacLite_mNextReceiveAddr XEmacLite_NextReceiveAddr +#endif + +#ifndef XEmacLite_mIsMdioConfigured +#define XEmacLite_mIsMdioConfigured XEmacLite_IsMdioConfigured +#endif + +#ifndef XEmacLite_mIsLoopbackConfigured +#define XEmacLite_mIsLoopbackConfigured XEmacLite_IsLoopbackConfigured +#endif + +#ifndef XEmacLite_mGetReceiveDataLength +#define XEmacLite_mGetReceiveDataLength XEmacLite_GetReceiveDataLength +#endif + +#ifndef XEmacLite_mGetTxActive +#define XEmacLite_mGetTxActive XEmacLite_GetTxActive +#endif + +#ifndef XEmacLite_mSetTxActive +#define XEmacLite_mSetTxActive XEmacLite_SetTxActive +#endif + +/*********************************************************************/ +/** + * Macros for Driver XGpio + * + *********************************************************************/ +#ifndef XGpio_mWriteReg +#define XGpio_mWriteReg XGpio_WriteReg +#endif + +#ifndef XGpio_mReadReg +#define XGpio_mReadReg XGpio_ReadReg +#endif + +/*********************************************************************/ +/** + * Macros for Driver XHwIcap + * + *********************************************************************/ +#ifndef XHwIcap_mFifoWrite +#define XHwIcap_mFifoWrite XHwIcap_FifoWrite +#endif + +#ifndef XHwIcap_mFifoRead +#define XHwIcap_mFifoRead XHwIcap_FifoRead +#endif + +#ifndef XHwIcap_mSetSizeReg +#define XHwIcap_mSetSizeReg XHwIcap_SetSizeReg +#endif + +#ifndef XHwIcap_mGetControlReg +#define XHwIcap_mGetControlReg XHwIcap_GetControlReg +#endif + +#ifndef XHwIcap_mStartConfig +#define XHwIcap_mStartConfig XHwIcap_StartConfig +#endif + +#ifndef XHwIcap_mStartReadBack +#define XHwIcap_mStartReadBack XHwIcap_StartReadBack +#endif + +#ifndef XHwIcap_mGetStatusReg +#define XHwIcap_mGetStatusReg XHwIcap_GetStatusReg +#endif + +#ifndef XHwIcap_mIsTransferDone +#define XHwIcap_mIsTransferDone XHwIcap_IsTransferDone +#endif + +#ifndef XHwIcap_mIsDeviceBusy +#define XHwIcap_mIsDeviceBusy XHwIcap_IsDeviceBusy +#endif + +#ifndef XHwIcap_mIntrGlobalEnable +#define XHwIcap_mIntrGlobalEnable XHwIcap_IntrGlobalEnable +#endif + +#ifndef XHwIcap_mIntrGlobalDisable +#define XHwIcap_mIntrGlobalDisable XHwIcap_IntrGlobalDisable +#endif + +#ifndef XHwIcap_mIntrGetStatus +#define XHwIcap_mIntrGetStatus XHwIcap_IntrGetStatus +#endif + +#ifndef XHwIcap_mIntrDisable +#define XHwIcap_mIntrDisable XHwIcap_IntrDisable +#endif + +#ifndef XHwIcap_mIntrEnable +#define XHwIcap_mIntrEnable XHwIcap_IntrEnable +#endif + +#ifndef XHwIcap_mIntrGetEnabled +#define XHwIcap_mIntrGetEnabled XHwIcap_IntrGetEnabled +#endif + +#ifndef XHwIcap_mIntrClear +#define XHwIcap_mIntrClear XHwIcap_IntrClear +#endif + +#ifndef XHwIcap_mGetWrFifoVacancy +#define XHwIcap_mGetWrFifoVacancy XHwIcap_GetWrFifoVacancy +#endif + +#ifndef XHwIcap_mGetRdFifoOccupancy +#define XHwIcap_mGetRdFifoOccupancy XHwIcap_GetRdFifoOccupancy +#endif + +#ifndef XHwIcap_mSliceX2Col +#define XHwIcap_mSliceX2Col XHwIcap_SliceX2Col +#endif + +#ifndef XHwIcap_mSliceY2Row +#define XHwIcap_mSliceY2Row XHwIcap_SliceY2Row +#endif + +#ifndef XHwIcap_mSliceXY2Slice +#define XHwIcap_mSliceXY2Slice XHwIcap_SliceXY2Slice +#endif + +#ifndef XHwIcap_mReadReg +#define XHwIcap_mReadReg XHwIcap_ReadReg +#endif + +#ifndef XHwIcap_mWriteReg +#define XHwIcap_mWriteReg XHwIcap_WriteReg +#endif + +/*********************************************************************/ +/** + * Macros for Driver XIic + * + *********************************************************************/ +#ifndef XIic_mReadReg +#define XIic_mReadReg XIic_ReadReg +#endif + +#ifndef XIic_mWriteReg +#define XIic_mWriteReg XIic_WriteReg +#endif + +#ifndef XIic_mEnterCriticalRegion +#define XIic_mEnterCriticalRegion XIic_IntrGlobalDisable +#endif + +#ifndef XIic_mExitCriticalRegion +#define XIic_mExitCriticalRegion XIic_IntrGlobalEnable +#endif + +#ifndef XIIC_GINTR_DISABLE +#define XIIC_GINTR_DISABLE XIic_IntrGlobalDisable +#endif + +#ifndef XIIC_GINTR_ENABLE +#define XIIC_GINTR_ENABLE XIic_IntrGlobalEnable +#endif + +#ifndef XIIC_IS_GINTR_ENABLED +#define XIIC_IS_GINTR_ENABLED XIic_IsIntrGlobalEnabled +#endif + +#ifndef XIIC_WRITE_IISR +#define XIIC_WRITE_IISR XIic_WriteIisr +#endif + +#ifndef XIIC_READ_IISR +#define XIIC_READ_IISR XIic_ReadIisr +#endif + +#ifndef XIIC_WRITE_IIER +#define XIIC_WRITE_IIER XIic_WriteIier +#endif + +#ifndef XIic_mClearIisr +#define XIic_mClearIisr XIic_ClearIisr +#endif + +#ifndef XIic_mSend7BitAddress +#define XIic_mSend7BitAddress XIic_Send7BitAddress +#endif + +#ifndef XIic_mDynSend7BitAddress +#define XIic_mDynSend7BitAddress XIic_DynSend7BitAddress +#endif + +#ifndef XIic_mDynSendStartStopAddress +#define XIic_mDynSendStartStopAddress XIic_DynSendStartStopAddress +#endif + +#ifndef XIic_mDynSendStop +#define XIic_mDynSendStop XIic_DynSendStop +#endif + +#ifndef XIic_mSend10BitAddrByte1 +#define XIic_mSend10BitAddrByte1 XIic_Send10BitAddrByte1 +#endif + +#ifndef XIic_mSend10BitAddrByte2 +#define XIic_mSend10BitAddrByte2 XIic_Send10BitAddrByte2 +#endif + +#ifndef XIic_mSend7BitAddr +#define XIic_mSend7BitAddr XIic_Send7BitAddr +#endif + +#ifndef XIic_mDisableIntr +#define XIic_mDisableIntr XIic_DisableIntr +#endif + +#ifndef XIic_mEnableIntr +#define XIic_mEnableIntr XIic_EnableIntr +#endif + +#ifndef XIic_mClearIntr +#define XIic_mClearIntr XIic_ClearIntr +#endif + +#ifndef XIic_mClearEnableIntr +#define XIic_mClearEnableIntr XIic_ClearEnableIntr +#endif + +#ifndef XIic_mFlushRxFifo +#define XIic_mFlushRxFifo XIic_FlushRxFifo +#endif + +#ifndef XIic_mFlushTxFifo +#define XIic_mFlushTxFifo XIic_FlushTxFifo +#endif + +#ifndef XIic_mReadRecvByte +#define XIic_mReadRecvByte XIic_ReadRecvByte +#endif + +#ifndef XIic_mWriteSendByte +#define XIic_mWriteSendByte XIic_WriteSendByte +#endif + +#ifndef XIic_mSetControlRegister +#define XIic_mSetControlRegister XIic_SetControlRegister +#endif + +/*********************************************************************/ +/** + * Macros for Driver XIntc + * + *********************************************************************/ +#ifndef XIntc_mMasterEnable +#define XIntc_mMasterEnable XIntc_MasterEnable +#endif + +#ifndef XIntc_mMasterDisable +#define XIntc_mMasterDisable XIntc_MasterDisable +#endif + +#ifndef XIntc_mEnableIntr +#define XIntc_mEnableIntr XIntc_EnableIntr +#endif + +#ifndef XIntc_mDisableIntr +#define XIntc_mDisableIntr XIntc_DisableIntr +#endif + +#ifndef XIntc_mAckIntr +#define XIntc_mAckIntr XIntc_AckIntr +#endif + +#ifndef XIntc_mGetIntrStatus +#define XIntc_mGetIntrStatus XIntc_GetIntrStatus +#endif + +/*********************************************************************/ +/** + * Macros for Driver XLlDma + * + *********************************************************************/ +#ifndef XLlDma_mBdRead +#define XLlDma_mBdRead XLlDma_BdRead +#endif + +#ifndef XLlDma_mBdWrite +#define XLlDma_mBdWrite XLlDma_BdWrite +#endif + +#ifndef XLlDma_mWriteReg +#define XLlDma_mWriteReg XLlDma_WriteReg +#endif + +#ifndef XLlDma_mReadReg +#define XLlDma_mReadReg XLlDma_ReadReg +#endif + +#ifndef XLlDma_mBdClear +#define XLlDma_mBdClear XLlDma_BdClear +#endif + +#ifndef XLlDma_mBdSetStsCtrl +#define XLlDma_mBdSetStsCtrl XLlDma_BdSetStsCtrl +#endif + +#ifndef XLlDma_mBdGetStsCtrl +#define XLlDma_mBdGetStsCtrl XLlDma_BdGetStsCtrl +#endif + +#ifndef XLlDma_mBdSetLength +#define XLlDma_mBdSetLength XLlDma_BdSetLength +#endif + +#ifndef XLlDma_mBdGetLength +#define XLlDma_mBdGetLength XLlDma_BdGetLength +#endif + +#ifndef XLlDma_mBdSetId +#define XLlDma_mBdSetId XLlDma_BdSetId +#endif + +#ifndef XLlDma_mBdGetId +#define XLlDma_mBdGetId XLlDma_BdGetId +#endif + +#ifndef XLlDma_mBdSetBufAddr +#define XLlDma_mBdSetBufAddr XLlDma_BdSetBufAddr +#endif + +#ifndef XLlDma_mBdGetBufAddr +#define XLlDma_mBdGetBufAddr XLlDma_BdGetBufAddr +#endif + +#ifndef XLlDma_mBdGetLength +#define XLlDma_mBdGetLength XLlDma_BdGetLength +#endif + +#ifndef XLlDma_mGetTxRing +#define XLlDma_mGetTxRing XLlDma_GetTxRing +#endif + +#ifndef XLlDma_mGetRxRing +#define XLlDma_mGetRxRing XLlDma_GetRxRing +#endif + +#ifndef XLlDma_mGetCr +#define XLlDma_mGetCr XLlDma_GetCr +#endif + +#ifndef XLlDma_mSetCr +#define XLlDma_mSetCr XLlDma_SetCr +#endif + +#ifndef XLlDma_mBdRingCntCalc +#define XLlDma_mBdRingCntCalc XLlDma_BdRingCntCalc +#endif + +#ifndef XLlDma_mBdRingMemCalc +#define XLlDma_mBdRingMemCalc XLlDma_BdRingMemCalc +#endif + +#ifndef XLlDma_mBdRingGetCnt +#define XLlDma_mBdRingGetCnt XLlDma_BdRingGetCnt +#endif + +#ifndef XLlDma_mBdRingGetFreeCnt +#define XLlDma_mBdRingGetFreeCnt XLlDma_BdRingGetFreeCnt +#endif + +#ifndef XLlDma_mBdRingSnapShotCurrBd +#define XLlDma_mBdRingSnapShotCurrBd XLlDma_BdRingSnapShotCurrBd +#endif + +#ifndef XLlDma_mBdRingNext +#define XLlDma_mBdRingNext XLlDma_BdRingNext +#endif + +#ifndef XLlDma_mBdRingPrev +#define XLlDma_mBdRingPrev XLlDma_BdRingPrev +#endif + +#ifndef XLlDma_mBdRingGetSr +#define XLlDma_mBdRingGetSr XLlDma_BdRingGetSr +#endif + +#ifndef XLlDma_mBdRingSetSr +#define XLlDma_mBdRingSetSr XLlDma_BdRingSetSr +#endif + +#ifndef XLlDma_mBdRingGetCr +#define XLlDma_mBdRingGetCr XLlDma_BdRingGetCr +#endif + +#ifndef XLlDma_mBdRingSetCr +#define XLlDma_mBdRingSetCr XLlDma_BdRingSetCr +#endif + +#ifndef XLlDma_mBdRingBusy +#define XLlDma_mBdRingBusy XLlDma_BdRingBusy +#endif + +#ifndef XLlDma_mBdRingIntEnable +#define XLlDma_mBdRingIntEnable XLlDma_BdRingIntEnable +#endif + +#ifndef XLlDma_mBdRingIntDisable +#define XLlDma_mBdRingIntDisable XLlDma_BdRingIntDisable +#endif + +#ifndef XLlDma_mBdRingIntGetEnabled +#define XLlDma_mBdRingIntGetEnabled XLlDma_BdRingIntGetEnabled +#endif + +#ifndef XLlDma_mBdRingGetIrq +#define XLlDma_mBdRingGetIrq XLlDma_BdRingGetIrq +#endif + +#ifndef XLlDma_mBdRingAckIrq +#define XLlDma_mBdRingAckIrq XLlDma_BdRingAckIrq +#endif + +/*********************************************************************/ +/** + * Macros for Driver XMbox + * + *********************************************************************/ +#ifndef XMbox_mWriteReg +#define XMbox_mWriteReg XMbox_WriteReg +#endif + +#ifndef XMbox_mReadReg +#define XMbox_mReadReg XMbox_ReadReg +#endif + +#ifndef XMbox_mWriteMBox +#define XMbox_mWriteMBox XMbox_WriteMBox +#endif + +#ifndef XMbox_mReadMBox +#define XMbox_mReadMBox XMbox_ReadMBox +#endif + +#ifndef XMbox_mFSLReadMBox +#define XMbox_mFSLReadMBox XMbox_FSLReadMBox +#endif + +#ifndef XMbox_mFSLWriteMBox +#define XMbox_mFSLWriteMBox XMbox_FSLWriteMBox +#endif + +#ifndef XMbox_mFSLIsEmpty +#define XMbox_mFSLIsEmpty XMbox_FSLIsEmpty +#endif + +#ifndef XMbox_mFSLIsFull +#define XMbox_mFSLIsFull XMbox_FSLIsFull +#endif + +#ifndef XMbox_mIsEmpty +#define XMbox_mIsEmpty XMbox_IsEmptyHw +#endif + +#ifndef XMbox_mIsFull +#define XMbox_mIsFull XMbox_IsFullHw +#endif + +/*********************************************************************/ +/** + * Macros for Driver XMpmc + * + *********************************************************************/ +#ifndef XMpmc_mReadReg +#define XMpmc_mReadReg XMpmc_ReadReg +#endif + +#ifndef XMpmc_mWriteReg +#define XMpmc_mWriteReg XMpmc_WriteReg +#endif + +/*********************************************************************/ +/** + * Macros for Driver XMutex + * + *********************************************************************/ +#ifndef XMutex_mWriteReg +#define XMutex_mWriteReg XMutex_WriteReg +#endif + +#ifndef XMutex_mReadReg +#define XMutex_mReadReg XMutex_ReadReg +#endif + +/*********************************************************************/ +/** + * Macros for Driver XPcie + * + *********************************************************************/ +#ifndef XPcie_mReadReg +#define XPcie_mReadReg XPcie_ReadReg +#endif + +#ifndef XPcie_mWriteReg +#define XPcie_mWriteReg XPcie_WriteReg +#endif + +/*********************************************************************/ +/** + * Macros for Driver XSpi + * + *********************************************************************/ +#ifndef XSpi_mIntrGlobalEnable +#define XSpi_mIntrGlobalEnable XSpi_IntrGlobalEnable +#endif + +#ifndef XSpi_mIntrGlobalDisable +#define XSpi_mIntrGlobalDisable XSpi_IntrGlobalDisable +#endif + +#ifndef XSpi_mIsIntrGlobalEnabled +#define XSpi_mIsIntrGlobalEnabled XSpi_IsIntrGlobalEnabled +#endif + +#ifndef XSpi_mIntrGetStatus +#define XSpi_mIntrGetStatus XSpi_IntrGetStatus +#endif + +#ifndef XSpi_mIntrClear +#define XSpi_mIntrClear XSpi_IntrClear +#endif + +#ifndef XSpi_mIntrEnable +#define XSpi_mIntrEnable XSpi_IntrEnable +#endif + +#ifndef XSpi_mIntrDisable +#define XSpi_mIntrDisable XSpi_IntrDisable +#endif + +#ifndef XSpi_mIntrGetEnabled +#define XSpi_mIntrGetEnabled XSpi_IntrGetEnabled +#endif + +#ifndef XSpi_mSetControlReg +#define XSpi_mSetControlReg XSpi_SetControlReg +#endif + +#ifndef XSpi_mGetControlReg +#define XSpi_mGetControlReg XSpi_GetControlReg +#endif + +#ifndef XSpi_mGetStatusReg +#define XSpi_mGetStatusReg XSpi_GetStatusReg +#endif + +#ifndef XSpi_mSetSlaveSelectReg +#define XSpi_mSetSlaveSelectReg XSpi_SetSlaveSelectReg +#endif + +#ifndef XSpi_mGetSlaveSelectReg +#define XSpi_mGetSlaveSelectReg XSpi_GetSlaveSelectReg +#endif + +#ifndef XSpi_mEnable +#define XSpi_mEnable XSpi_Enable +#endif + +#ifndef XSpi_mDisable +#define XSpi_mDisable XSpi_Disable +#endif + +/*********************************************************************/ +/** + * Macros for Driver XSysAce + * + *********************************************************************/ +#ifndef XSysAce_mGetControlReg +#define XSysAce_mGetControlReg XSysAce_GetControlReg +#endif + +#ifndef XSysAce_mSetControlReg +#define XSysAce_mSetControlReg XSysAce_SetControlReg +#endif + +#ifndef XSysAce_mOrControlReg +#define XSysAce_mOrControlReg XSysAce_OrControlReg +#endif + +#ifndef XSysAce_mAndControlReg +#define XSysAce_mAndControlReg XSysAce_AndControlReg +#endif + +#ifndef XSysAce_mGetErrorReg +#define XSysAce_mGetErrorReg XSysAce_GetErrorReg +#endif + +#ifndef XSysAce_mGetStatusReg +#define XSysAce_mGetStatusReg XSysAce_GetStatusReg +#endif + +#ifndef XSysAce_mWaitForLock +#define XSysAce_mWaitForLock XSysAce_WaitForLock +#endif + +#ifndef XSysAce_mEnableIntr +#define XSysAce_mEnableIntr XSysAce_EnableIntr +#endif + +#ifndef XSysAce_mDisableIntr +#define XSysAce_mDisableIntr XSysAce_DisableIntr +#endif + +#ifndef XSysAce_mIsReadyForCmd +#define XSysAce_mIsReadyForCmd XSysAce_IsReadyForCmd +#endif + +#ifndef XSysAce_mIsMpuLocked +#define XSysAce_mIsMpuLocked XSysAce_IsMpuLocked +#endif + +#ifndef XSysAce_mIsIntrEnabled +#define XSysAce_mIsIntrEnabled XSysAce_IsIntrEnabled +#endif + +/*********************************************************************/ +/** + * Macros for Driver XSysMon + * + *********************************************************************/ +#ifndef XSysMon_mIsEventSamplingModeSet +#define XSysMon_mIsEventSamplingModeSet XSysMon_IsEventSamplingModeSet +#endif + +#ifndef XSysMon_mIsDrpBusy +#define XSysMon_mIsDrpBusy XSysMon_IsDrpBusy +#endif + +#ifndef XSysMon_mIsDrpLocked +#define XSysMon_mIsDrpLocked XSysMon_IsDrpLocked +#endif + +#ifndef XSysMon_mRawToTemperature +#define XSysMon_mRawToTemperature XSysMon_RawToTemperature +#endif + +#ifndef XSysMon_mRawToVoltage +#define XSysMon_mRawToVoltage XSysMon_RawToVoltage +#endif + +#ifndef XSysMon_mTemperatureToRaw +#define XSysMon_mTemperatureToRaw XSysMon_TemperatureToRaw +#endif + +#ifndef XSysMon_mVoltageToRaw +#define XSysMon_mVoltageToRaw XSysMon_VoltageToRaw +#endif + +#ifndef XSysMon_mReadReg +#define XSysMon_mReadReg XSysMon_ReadReg +#endif + +#ifndef XSysMon_mWriteReg +#define XSysMon_mWriteReg XSysMon_WriteReg +#endif + +/*********************************************************************/ +/** + * Macros for Driver XTmrCtr + * + *********************************************************************/ +#ifndef XTimerCtr_mReadReg +#define XTimerCtr_mReadReg XTimerCtr_ReadReg +#endif + +#ifndef XTmrCtr_mWriteReg +#define XTmrCtr_mWriteReg XTmrCtr_WriteReg +#endif + +#ifndef XTmrCtr_mSetControlStatusReg +#define XTmrCtr_mSetControlStatusReg XTmrCtr_SetControlStatusReg +#endif + +#ifndef XTmrCtr_mGetControlStatusReg +#define XTmrCtr_mGetControlStatusReg XTmrCtr_GetControlStatusReg +#endif + +#ifndef XTmrCtr_mGetTimerCounterReg +#define XTmrCtr_mGetTimerCounterReg XTmrCtr_GetTimerCounterReg +#endif + +#ifndef XTmrCtr_mSetLoadReg +#define XTmrCtr_mSetLoadReg XTmrCtr_SetLoadReg +#endif + +#ifndef XTmrCtr_mGetLoadReg +#define XTmrCtr_mGetLoadReg XTmrCtr_GetLoadReg +#endif + +#ifndef XTmrCtr_mEnable +#define XTmrCtr_mEnable XTmrCtr_Enable +#endif + +#ifndef XTmrCtr_mDisable +#define XTmrCtr_mDisable XTmrCtr_Disable +#endif + +#ifndef XTmrCtr_mEnableIntr +#define XTmrCtr_mEnableIntr XTmrCtr_EnableIntr +#endif + +#ifndef XTmrCtr_mDisableIntr +#define XTmrCtr_mDisableIntr XTmrCtr_DisableIntr +#endif + +#ifndef XTmrCtr_mLoadTimerCounterReg +#define XTmrCtr_mLoadTimerCounterReg XTmrCtr_LoadTimerCounterReg +#endif + +#ifndef XTmrCtr_mHasEventOccurred +#define XTmrCtr_mHasEventOccurred XTmrCtr_HasEventOccurred +#endif + +/*********************************************************************/ +/** + * Macros for Driver XUartLite + * + *********************************************************************/ +#ifndef XUartLite_mUpdateStats +#define XUartLite_mUpdateStats XUartLite_UpdateStats +#endif + +#ifndef XUartLite_mWriteReg +#define XUartLite_mWriteReg XUartLite_WriteReg +#endif + +#ifndef XUartLite_mReadReg +#define XUartLite_mReadReg XUartLite_ReadReg +#endif + +#ifndef XUartLite_mClearStats +#define XUartLite_mClearStats XUartLite_ClearStats +#endif + +#ifndef XUartLite_mSetControlReg +#define XUartLite_mSetControlReg XUartLite_SetControlReg +#endif + +#ifndef XUartLite_mGetStatusReg +#define XUartLite_mGetStatusReg XUartLite_GetStatusReg +#endif + +#ifndef XUartLite_mIsReceiveEmpty +#define XUartLite_mIsReceiveEmpty XUartLite_IsReceiveEmpty +#endif + +#ifndef XUartLite_mIsTransmitFull +#define XUartLite_mIsTransmitFull XUartLite_IsTransmitFull +#endif + +#ifndef XUartLite_mIsIntrEnabled +#define XUartLite_mIsIntrEnabled XUartLite_IsIntrEnabled +#endif + +#ifndef XUartLite_mEnableIntr +#define XUartLite_mEnableIntr XUartLite_EnableIntr +#endif + +#ifndef XUartLite_mDisableIntr +#define XUartLite_mDisableIntr XUartLite_DisableIntr +#endif + +/*********************************************************************/ +/** + * Macros for Driver XUartNs550 + * + *********************************************************************/ +#ifndef XUartNs550_mUpdateStats +#define XUartNs550_mUpdateStats XUartNs550_UpdateStats +#endif + +#ifndef XUartNs550_mReadReg +#define XUartNs550_mReadReg XUartNs550_ReadReg +#endif + +#ifndef XUartNs550_mWriteReg +#define XUartNs550_mWriteReg XUartNs550_WriteReg +#endif + +#ifndef XUartNs550_mClearStats +#define XUartNs550_mClearStats XUartNs550_ClearStats +#endif + +#ifndef XUartNs550_mGetLineStatusReg +#define XUartNs550_mGetLineStatusReg XUartNs550_GetLineStatusReg +#endif + +#ifndef XUartNs550_mGetLineControlReg +#define XUartNs550_mGetLineControlReg XUartNs550_GetLineControlReg +#endif + +#ifndef XUartNs550_mSetLineControlReg +#define XUartNs550_mSetLineControlReg XUartNs550_SetLineControlReg +#endif + +#ifndef XUartNs550_mEnableIntr +#define XUartNs550_mEnableIntr XUartNs550_EnableIntr +#endif + +#ifndef XUartNs550_mDisableIntr +#define XUartNs550_mDisableIntr XUartNs550_DisableIntr +#endif + +#ifndef XUartNs550_mIsReceiveData +#define XUartNs550_mIsReceiveData XUartNs550_IsReceiveData +#endif + +#ifndef XUartNs550_mIsTransmitEmpty +#define XUartNs550_mIsTransmitEmpty XUartNs550_IsTransmitEmpty +#endif + +/*********************************************************************/ +/** + * Macros for Driver XUsb + * + *********************************************************************/ +#ifndef XUsb_mReadReg +#define XUsb_mReadReg XUsb_ReadReg +#endif + +#ifndef XUsb_mWriteReg +#define XUsb_mWriteReg XUsb_WriteReg +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_mem.c b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_mem.c new file mode 100644 index 0000000..e089bb5 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_mem.c @@ -0,0 +1,85 @@ +/******************************************************************************/ +/** +* Copyright (C) 2015 - 2016 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* @file xil_mem.c +* +* This file contains xil mem copy function to use in case of word aligned +* data copies. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 6.1   nsk      11/07/16 First release.
+*
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ + +#include "xil_types.h" + +/***************** Inline Functions Definitions ********************/ +/*****************************************************************************/ +/** +* @brief This function copies memory from once location to other. +* +* @param dst: pointer pointing to destination memory +* +* @param src: pointer pointing to source memory +* +* @param cnt: 32 bit length of bytes to be copied +* +*****************************************************************************/ +void Xil_MemCpy(void* dst, const void* src, u32 cnt) +{ + char *d = (char*)(void *)dst; + const char *s = src; + + while (cnt >= sizeof (int)) { + *(int*)d = *(int*)s; + d += sizeof (int); + s += sizeof (int); + cnt -= sizeof (int); + } + while (cnt >= sizeof (u16)) { + *(u16*)d = *(u16*)s; + d += sizeof (u16); + s += sizeof (u16); + cnt -= sizeof (u16); + } + while ((cnt) > 0U){ + *d = *s; + d += 1U; + s += 1U; + cnt -= 1U; + } +} diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_mem.h b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_mem.h new file mode 100644 index 0000000..9aae942 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_mem.h @@ -0,0 +1,68 @@ +/******************************************************************************/ +/** +* Copyright (C) 2015 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* @file xil_mem.h +* +* @addtogroup common_mem_operation_api Customized APIs for Memory Operations +* +* The xil_mem.h file contains prototype for functions related +* to memory operations. These APIs are applicable for all processors supported +* by Xilinx. +* +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 6.1   nsk      11/07/16 First release.
+* 7.0   mus      01/07/19 Add cpp extern macro
+*
+* 
+* +*****************************************************************************/ +#ifndef XIL_MEM_H /* prevent circular inclusions */ +#define XIL_MEM_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/************************** Function Prototypes *****************************/ + +void Xil_MemCpy(void* dst, const void* src, u32 cnt); + +#ifdef __cplusplus +} +#endif + +#endif /* XIL_MEM_H */ +/** +* @} End of "addtogroup common_mem_operation_api". +*/ \ No newline at end of file diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_misc_psreset_api.c b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_misc_psreset_api.c new file mode 100644 index 0000000..fd44b8b --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_misc_psreset_api.c @@ -0,0 +1,520 @@ +/****************************************************************************** +* +* Copyright (C) 2013 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_misc_reset.c +* +* This file contains the implementation of the reset sequence for various +* zynq ps devices like DDR,OCM,Slcr,Ethernet,Usb.. controllers. The reset +* sequence provided to the interfaces is based on the provision in +* slcr reset functional blcok. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date   Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00b kpc   03/07/13 First release
+* 5.4	pkp	  16/11/15 Change the description for XOcm_Remap function
+* 
+* +******************************************************************************/ + + +/***************************** Include Files *********************************/ +#include "xil_misc_psreset_api.h" + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + + +/*****************************************************************************/ +/** +* This function contains the implementation for ddr reset. +* +* @param N/A. +* +* @return N/A. +* +* @note None. +* +******************************************************************************/ +void XDdr_ResetHw(void) +{ + u32 RegVal; + + /* Unlock the slcr register access lock */ + Xil_Out32(XSLCR_UNLOCK_ADDR, XSLCR_UNLOCK_CODE); + /* Assert and deassert the ddr softreset bit */ + RegVal = Xil_In32(XDDRC_CTRL_BASEADDR); + RegVal &= (u32)(~XDDRPS_CTRL_RESET_MASK); + Xil_Out32(XDDRC_CTRL_BASEADDR,RegVal); + RegVal |= XDDRPS_CTRL_RESET_MASK; + Xil_Out32(XDDRC_CTRL_BASEADDR,RegVal); + +} + +/*****************************************************************************/ +/** +* This function contains the implementation for remapping the ocm memory region +* to postbootrom state. +* +* @param N/A. +* +* @return N/A. +* +* @note None. +* +******************************************************************************/ +void XOcm_Remap(void) +{ + u32 RegVal; + + /* Unlock the slcr register access lock */ + Xil_Out32(XSLCR_UNLOCK_ADDR, XSLCR_UNLOCK_CODE); + /* Map the ocm region to postbootrom state */ + RegVal = Xil_In32(XSLCR_OCM_CFG_ADDR); + RegVal = (RegVal & (u32)(~XSLCR_OCM_CFG_HIADDR_MASK)) | (u32)XSLCR_OCM_CFG_RESETVAL; + Xil_Out32(XSLCR_OCM_CFG_ADDR, RegVal); +} + +/*****************************************************************************/ +/** +* This function contains the implementation for SMC reset sequence +* +* @param BaseAddress of the interface +* +* @return N/A. +* +* @note None. +* +******************************************************************************/ +void XSmc_ResetHw(u32 BaseAddress) +{ + u32 RegVal; + + /* Clear the interuupts */ + RegVal = Xil_In32(BaseAddress + XSMC_MEMC_CLR_CONFIG_OFFSET); + RegVal |= XSMC_MEMC_CLR_CONFIG_MASK; + Xil_Out32(BaseAddress + XSMC_MEMC_CLR_CONFIG_OFFSET, RegVal); + /* Clear the idle counter registers */ + Xil_Out32(BaseAddress + XSMC_REFRESH_PERIOD_0_OFFSET, 0x0U); + Xil_Out32(BaseAddress + XSMC_REFRESH_PERIOD_1_OFFSET, 0x0U); + /* Update the ecc registers with reset values */ + Xil_Out32(BaseAddress + XSMC_ECC_MEMCFG1_OFFSET, + XSMC_ECC_MEMCFG1_RESET_VAL); + Xil_Out32(BaseAddress + XSMC_ECC_MEMCMD1_OFFSET, + XSMC_ECC_MEMCMD1_RESET_VAL); + Xil_Out32(BaseAddress + XSMC_ECC_MEMCMD2_OFFSET, + XSMC_ECC_MEMCMD2_RESET_VAL); + +} + +/*****************************************************************************/ +/** +* This function contains the implementation for updating the slcr mio registers +* with reset values +* @param N/A. +* +* @return N/A. +* +* @note None. +* +******************************************************************************/ +void XSlcr_MioWriteResetValues(void) +{ + u32 i; + + /* Unlock the slcr register access lock */ + Xil_Out32(XSLCR_UNLOCK_ADDR, XSLCR_UNLOCK_CODE); + /* Update all the MIO registers with reset values */ + for (i=0U; i<=1U;i++) + { + Xil_Out32((XSLCR_MIO_PIN_00_ADDR + (i * 4U)), + XSLCR_MIO_PIN_00_RESET_VAL); + } + for (; i<=8U;i++) + { + Xil_Out32((XSLCR_MIO_PIN_00_ADDR + (i * 4U)), + XSLCR_MIO_PIN_02_RESET_VAL); + } + for (; i<=53U ;i++) + { + Xil_Out32((XSLCR_MIO_PIN_00_ADDR + (i * 4U)), + XSLCR_MIO_PIN_00_RESET_VAL); + } + + +} + +/*****************************************************************************/ +/** +* This function contains the implementation for updating the slcr pll registers +* with reset values +* @param N/A. +* +* @return N/A. +* +* @note None. +* +******************************************************************************/ +void XSlcr_PllWriteResetValues(void) +{ + + /* Unlock the slcr register access lock */ + Xil_Out32(XSLCR_UNLOCK_ADDR, XSLCR_UNLOCK_CODE); + + /* update the pll control registers with reset values */ + Xil_Out32(XSLCR_IO_PLL_CTRL_ADDR, XSLCR_IO_PLL_CTRL_RESET_VAL); + Xil_Out32(XSLCR_ARM_PLL_CTRL_ADDR, XSLCR_ARM_PLL_CTRL_RESET_VAL); + Xil_Out32(XSLCR_DDR_PLL_CTRL_ADDR, XSLCR_DDR_PLL_CTRL_RESET_VAL); + /* update the pll config registers with reset values */ + Xil_Out32(XSLCR_IO_PLL_CFG_ADDR, XSLCR_IO_PLL_CFG_RESET_VAL); + Xil_Out32(XSLCR_ARM_PLL_CFG_ADDR, XSLCR_ARM_PLL_CFG_RESET_VAL); + Xil_Out32(XSLCR_DDR_PLL_CFG_ADDR, XSLCR_DDR_PLL_CFG_RESET_VAL); + /* update the clock control registers with reset values */ + Xil_Out32(XSLCR_ARM_CLK_CTRL_ADDR, XSLCR_ARM_CLK_CTRL_RESET_VAL); + Xil_Out32(XSLCR_DDR_CLK_CTRL_ADDR, XSLCR_DDR_CLK_CTRL_RESET_VAL); +} + +/*****************************************************************************/ +/** +* This function contains the implementation for disabling the level shifters +* +* @param N/A. +* +* @return N/A. +* +* @note None. +* +******************************************************************************/ +void XSlcr_DisableLevelShifters(void) +{ + u32 RegVal; + /* Unlock the slcr register access lock */ + Xil_Out32(XSLCR_UNLOCK_ADDR, XSLCR_UNLOCK_CODE); + /* Disable the level shifters */ + RegVal = Xil_In32(XSLCR_LVL_SHFTR_EN_ADDR); + RegVal = RegVal & (u32)(~XSLCR_LVL_SHFTR_EN_MASK); + Xil_Out32(XSLCR_LVL_SHFTR_EN_ADDR, RegVal); + +} +/*****************************************************************************/ +/** +* This function contains the implementation for OCM software reset from the +* slcr +* +* @param N/A. +* +* @return N/A. +* +* @note None. +* +******************************************************************************/ +void XSlcr_OcmReset(void) +{ + u32 RegVal; + /* Unlock the slcr register access lock */ + Xil_Out32(XSLCR_UNLOCK_ADDR, XSLCR_UNLOCK_CODE); + /* Assert the reset */ + RegVal = Xil_In32(XSLCR_OCM_RST_CTRL_ADDR); + RegVal |= XSLCR_OCM_RST_CTRL_VAL; + Xil_Out32(XSLCR_OCM_RST_CTRL_ADDR, RegVal); + /* Release the reset */ + RegVal = Xil_In32(XSLCR_OCM_RST_CTRL_ADDR); + RegVal = RegVal & (u32)(~XSLCR_OCM_RST_CTRL_VAL); + Xil_Out32(XSLCR_OCM_RST_CTRL_ADDR, RegVal); +} + +/*****************************************************************************/ +/** +* This function contains the implementation for Ethernet software reset from +* the slcr +* @param N/A. +* +* @return N/A. +* +* @note None. +* +******************************************************************************/ +void XSlcr_EmacPsReset(void) +{ + u32 RegVal; + /* Unlock the slcr register access lock */ + Xil_Out32(XSLCR_UNLOCK_ADDR, XSLCR_UNLOCK_CODE); + /* Assert the reset */ + RegVal = Xil_In32(XSLCR_GEM_RST_CTRL_ADDR); + RegVal |= XSLCR_GEM_RST_CTRL_VAL; + Xil_Out32(XSLCR_GEM_RST_CTRL_ADDR, RegVal); + /* Release the reset */ + RegVal = Xil_In32(XSLCR_GEM_RST_CTRL_ADDR); + RegVal &= (u32)(~XSLCR_GEM_RST_CTRL_VAL); + Xil_Out32(XSLCR_GEM_RST_CTRL_ADDR, RegVal); +} + +/*****************************************************************************/ +/** +* This function contains the implementation for USB software reset from the +* slcr +* +* @param N/A. +* +* @return N/A. +* +* @note None. +* +******************************************************************************/ +void XSlcr_UsbPsReset(void) +{ + u32 RegVal; + /* Unlock the slcr register access lock */ + Xil_Out32(XSLCR_UNLOCK_ADDR, XSLCR_UNLOCK_CODE); + /* Assert the reset */ + RegVal = Xil_In32(XSLCR_USB_RST_CTRL_ADDR); + RegVal |= XSLCR_USB_RST_CTRL_VAL; + Xil_Out32(XSLCR_USB_RST_CTRL_ADDR, RegVal); + /* Release the reset */ + RegVal = Xil_In32(XSLCR_USB_RST_CTRL_ADDR); + RegVal = RegVal & (u32)(~XSLCR_USB_RST_CTRL_VAL); + Xil_Out32(XSLCR_USB_RST_CTRL_ADDR, RegVal); +} +/*****************************************************************************/ +/** +* This function contains the implementation for QSPI software reset from the +* slcr +* +* @param N/A. +* +* @return N/A. +* +* @note None. +* +******************************************************************************/ +void XSlcr_QspiPsReset(void) +{ + u32 RegVal; + /* Unlock the slcr register access lock */ + Xil_Out32(XSLCR_UNLOCK_ADDR, XSLCR_UNLOCK_CODE); + /* Assert the reset */ + RegVal = Xil_In32(XSLCR_LQSPI_RST_CTRL_ADDR); + RegVal |= XSLCR_QSPI_RST_CTRL_VAL; + Xil_Out32(XSLCR_LQSPI_RST_CTRL_ADDR, RegVal); + /* Release the reset */ + RegVal = Xil_In32(XSLCR_LQSPI_RST_CTRL_ADDR); + RegVal = RegVal & (u32)(~XSLCR_QSPI_RST_CTRL_VAL); + Xil_Out32(XSLCR_LQSPI_RST_CTRL_ADDR, RegVal); +} +/*****************************************************************************/ +/** +* This function contains the implementation for SPI software reset from the +* slcr +* +* @param N/A. +* +* @return N/A. +* +* @note None. +* +******************************************************************************/ +void XSlcr_SpiPsReset(void) +{ + u32 RegVal; + /* Unlock the slcr register access lock */ + Xil_Out32(XSLCR_UNLOCK_ADDR, XSLCR_UNLOCK_CODE); + /* Assert the reset */ + RegVal = Xil_In32(XSLCR_SPI_RST_CTRL_ADDR); + RegVal |= XSLCR_SPI_RST_CTRL_VAL; + Xil_Out32(XSLCR_SPI_RST_CTRL_ADDR, RegVal); + /* Release the reset */ + RegVal = Xil_In32(XSLCR_SPI_RST_CTRL_ADDR); + RegVal = RegVal & (u32)(~XSLCR_SPI_RST_CTRL_VAL); + Xil_Out32(XSLCR_SPI_RST_CTRL_ADDR, RegVal); +} +/*****************************************************************************/ +/** +* This function contains the implementation for i2c software reset from the slcr +* +* @param N/A. +* +* @return N/A. +* +* @note None. +* +******************************************************************************/ +void XSlcr_I2cPsReset(void) +{ + u32 RegVal; + /* Unlock the slcr register access lock */ + Xil_Out32(XSLCR_UNLOCK_ADDR, XSLCR_UNLOCK_CODE); + /* Assert the reset */ + RegVal = Xil_In32(XSLCR_I2C_RST_CTRL_ADDR); + RegVal |= XSLCR_I2C_RST_CTRL_VAL; + Xil_Out32(XSLCR_I2C_RST_CTRL_ADDR, RegVal); + /* Release the reset */ + RegVal = Xil_In32(XSLCR_I2C_RST_CTRL_ADDR); + RegVal = RegVal & (u32)(~XSLCR_I2C_RST_CTRL_VAL); + Xil_Out32(XSLCR_I2C_RST_CTRL_ADDR, RegVal); +} +/*****************************************************************************/ +/** +* This function contains the implementation for UART software reset from the +* slcr +* +* @param N/A. +* +* @return N/A. +* +* @note None. +* +******************************************************************************/ +void XSlcr_UartPsReset(void) +{ + u32 RegVal; + /* Unlock the slcr register access lock */ + Xil_Out32(XSLCR_UNLOCK_ADDR, XSLCR_UNLOCK_CODE); + /* Assert the reset */ + RegVal = Xil_In32(XSLCR_UART_RST_CTRL_ADDR); + RegVal |= XSLCR_UART_RST_CTRL_VAL; + Xil_Out32(XSLCR_UART_RST_CTRL_ADDR, RegVal); + /* Release the reset */ + RegVal = Xil_In32(XSLCR_UART_RST_CTRL_ADDR); + RegVal = RegVal & (u32)(~XSLCR_UART_RST_CTRL_VAL); + Xil_Out32(XSLCR_UART_RST_CTRL_ADDR, RegVal); +} +/*****************************************************************************/ +/** +* This function contains the implementation for CAN software reset from slcr +* registers +* +* @param N/A. +* +* @return N/A. +* +* @note None. +* +******************************************************************************/ +void XSlcr_CanPsReset(void) +{ + u32 RegVal; + /* Unlock the slcr register access lock */ + Xil_Out32(XSLCR_UNLOCK_ADDR, XSLCR_UNLOCK_CODE); + /* Assert the reset */ + RegVal = Xil_In32(XSLCR_CAN_RST_CTRL_ADDR); + RegVal |= XSLCR_CAN_RST_CTRL_VAL; + Xil_Out32(XSLCR_CAN_RST_CTRL_ADDR, RegVal); + /* Release the reset */ + RegVal = Xil_In32(XSLCR_CAN_RST_CTRL_ADDR); + RegVal = RegVal & (u32)(~XSLCR_CAN_RST_CTRL_VAL); + Xil_Out32(XSLCR_CAN_RST_CTRL_ADDR, RegVal); +} +/*****************************************************************************/ +/** +* This function contains the implementation for SMC software reset from the slcr +* +* @param N/A. +* +* @return N/A. +* +* @note None. +* +******************************************************************************/ +void XSlcr_SmcPsReset(void) +{ + u32 RegVal; + /* Unlock the slcr register access lock */ + Xil_Out32(XSLCR_UNLOCK_ADDR, XSLCR_UNLOCK_CODE); + /* Assert the reset */ + RegVal = Xil_In32(XSLCR_SMC_RST_CTRL_ADDR); + RegVal |= XSLCR_SMC_RST_CTRL_VAL; + Xil_Out32(XSLCR_SMC_RST_CTRL_ADDR, RegVal); + /* Release the reset */ + RegVal = Xil_In32(XSLCR_SMC_RST_CTRL_ADDR); + RegVal = RegVal & (u32)(~XSLCR_SMC_RST_CTRL_VAL); + Xil_Out32(XSLCR_SMC_RST_CTRL_ADDR, RegVal); +} +/*****************************************************************************/ +/** +* This function contains the implementation for DMA controller software reset +* from the slcr +* +* @param N/A. +* +* @return N/A. +* +* @note None. +* +******************************************************************************/ +void XSlcr_DmaPsReset(void) +{ + u32 RegVal; + /* Unlock the slcr register access lock */ + Xil_Out32(XSLCR_UNLOCK_ADDR, XSLCR_UNLOCK_CODE); + /* Assert the reset */ + RegVal = Xil_In32(XSLCR_DMAC_RST_CTRL_ADDR); + RegVal |= XSLCR_DMAC_RST_CTRL_VAL; + Xil_Out32(XSLCR_DMAC_RST_CTRL_ADDR, RegVal); + /* Release the reset */ + RegVal = Xil_In32(XSLCR_DMAC_RST_CTRL_ADDR); + RegVal = RegVal & (u32)(~XSLCR_DMAC_RST_CTRL_VAL); + Xil_Out32(XSLCR_DMAC_RST_CTRL_ADDR, RegVal); +} +/*****************************************************************************/ +/** +* This function contains the implementation for Gpio AMBA software reset from +* the slcr +* +* @param N/A. +* +* @return N/A. +* +* @note None. +* +******************************************************************************/ +void XSlcr_GpioPsReset(void) +{ + u32 RegVal; + /* Unlock the slcr register access lock */ + Xil_Out32(XSLCR_UNLOCK_ADDR, XSLCR_UNLOCK_CODE); + /* Assert the reset */ + RegVal = Xil_In32(XSLCR_GPIO_RST_CTRL_ADDR); + RegVal |= XSLCR_GPIO_RST_CTRL_VAL; + Xil_Out32(XSLCR_GPIO_RST_CTRL_ADDR, RegVal); + /* Release the reset */ + RegVal = Xil_In32(XSLCR_GPIO_RST_CTRL_ADDR); + RegVal = RegVal & (u32)(~XSLCR_GPIO_RST_CTRL_VAL); + Xil_Out32(XSLCR_GPIO_RST_CTRL_ADDR, RegVal); +} diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_misc_psreset_api.h b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_misc_psreset_api.h new file mode 100644 index 0000000..f795f2e --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_misc_psreset_api.h @@ -0,0 +1,273 @@ +/****************************************************************************** +* +* Copyright (C) 2013 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file xil_misc_psreset_api.h +* +* This file contains the various register defintions and function prototypes for +* implementing the reset functionality of zynq ps devices +* +* MODIFICATION HISTORY: +* +* Ver Who Date Changes +* ----- ---- -------- ------------------------------------------------------- +* 1.00b kpc 03/07/13 First release. +*
+* +******************************************************************************/ + +#ifndef XIL_MISC_RESET_H /* prevent circular inclusions */ +#define XIL_MISC_RESET_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + + +/***************************** Include Files *********************************/ +#include "xil_types.h" +#include "xil_io.h" + +/************************** Constant Definitions *****************************/ +#define XDDRC_CTRL_BASEADDR 0xF8006000U +#define XSLCR_BASEADDR 0xF8000000U +/**< OCM configuration register */ +#define XSLCR_OCM_CFG_ADDR (XSLCR_BASEADDR + 0x00000910U) +/**< SLCR unlock register */ +#define XSLCR_UNLOCK_ADDR (XSLCR_BASEADDR + 0x00000008U) +/**< SLCR GEM0 rx clock control register */ +#define XSLCR_GEM0_RCLK_CTRL_ADDR (XSLCR_BASEADDR + 0x00000138U) +/**< SLCR GEM1 rx clock control register */ +#define XSLCR_GEM1_RCLK_CTRL_ADDR (XSLCR_BASEADDR + 0x0000013CU) +/**< SLCR GEM0 clock control register */ +#define XSLCR_GEM0_CLK_CTRL_ADDR (XSLCR_BASEADDR + 0x00000140U) +/**< SLCR GEM1 clock control register */ +#define XSLCR_GEM1_CLK_CTRL_ADDR (XSLCR_BASEADDR + 0x00000144U) +/**< SLCR SMC clock control register */ +#define XSLCR_SMC_CLK_CTRL_ADDR (XSLCR_BASEADDR + 0x00000148U) +/**< SLCR GEM reset control register */ +#define XSLCR_GEM_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000214U) +/**< SLCR USB0 clock control register */ +#define XSLCR_USB0_CLK_CTRL_ADDR (XSLCR_BASEADDR + 0x00000130U) +/**< SLCR USB1 clock control register */ +#define XSLCR_USB1_CLK_CTRL_ADDR (XSLCR_BASEADDR + 0x00000134U) +/**< SLCR USB1 reset control register */ +#define XSLCR_USB_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000210U) +/**< SLCR SMC reset control register */ +#define XSLCR_SMC_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000234U) +/**< SLCR Level shifter enable register */ +#define XSLCR_LVL_SHFTR_EN_ADDR (XSLCR_BASEADDR + 0x00000900U) +/**< SLCR ARM pll control register */ +#define XSLCR_ARM_PLL_CTRL_ADDR (XSLCR_BASEADDR + 0x00000100U) +/**< SLCR DDR pll control register */ +#define XSLCR_DDR_PLL_CTRL_ADDR (XSLCR_BASEADDR + 0x00000104U) +/**< SLCR IO pll control register */ +#define XSLCR_IO_PLL_CTRL_ADDR (XSLCR_BASEADDR + 0x00000108U) +/**< SLCR ARM pll configuration register */ +#define XSLCR_ARM_PLL_CFG_ADDR (XSLCR_BASEADDR + 0x00000110U) +/**< SLCR DDR pll configuration register */ +#define XSLCR_DDR_PLL_CFG_ADDR (XSLCR_BASEADDR + 0x00000114U) +/**< SLCR IO pll configuration register */ +#define XSLCR_IO_PLL_CFG_ADDR (XSLCR_BASEADDR + 0x00000118U) +/**< SLCR ARM clock control register */ +#define XSLCR_ARM_CLK_CTRL_ADDR (XSLCR_BASEADDR + 0x00000120U) +/**< SLCR DDR clock control register */ +#define XSLCR_DDR_CLK_CTRL_ADDR (XSLCR_BASEADDR + 0x00000124U) +/**< SLCR MIO pin address register */ +#define XSLCR_MIO_PIN_00_ADDR (XSLCR_BASEADDR + 0x00000700U) +/**< SLCR DMAC reset control address register */ +#define XSLCR_DMAC_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x0000020CU) +/**< SLCR USB reset control address register */ +/*#define XSLCR_USB_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000210U)*/ +/**< SLCR GEM reset control address register */ +/*#define XSLCR_GEM_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000214U)*/ +/**< SLCR SDIO reset control address register */ +#define XSLCR_SDIO_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000218U) +/**< SLCR SPI reset control address register */ +#define XSLCR_SPI_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x0000021CU) +/**< SLCR CAN reset control address register */ +#define XSLCR_CAN_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000220U) +/**< SLCR I2C reset control address register */ +#define XSLCR_I2C_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000224U) +/**< SLCR UART reset control address register */ +#define XSLCR_UART_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000228U) +/**< SLCR GPIO reset control address register */ +#define XSLCR_GPIO_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x0000022CU) +/**< SLCR LQSPI reset control address register */ +#define XSLCR_LQSPI_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000230U) +/**< SLCR SMC reset control address register */ +/*#define XSLCR_SMC_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000234U)*/ +/**< SLCR OCM reset control address register */ +#define XSLCR_OCM_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000238U) + +/**< SMC mem controller clear config register */ +#define XSMC_MEMC_CLR_CONFIG_OFFSET 0x0000000CU +/**< SMC idlecount configuration register */ +#define XSMC_REFRESH_PERIOD_0_OFFSET 0x00000020U +#define XSMC_REFRESH_PERIOD_1_OFFSET 0x00000024U +/**< SMC ECC configuration register */ +#define XSMC_ECC_MEMCFG1_OFFSET 0x00000404U +/**< SMC ECC command 1 register */ +#define XSMC_ECC_MEMCMD1_OFFSET 0x00000404U +/**< SMC ECC command 2 register */ +#define XSMC_ECC_MEMCMD2_OFFSET 0x00000404U + +/**< SLCR unlock code */ +#define XSLCR_UNLOCK_CODE 0x0000DF0DU + +/**< SMC mem clear configuration mask */ +#define XSMC_MEMC_CLR_CONFIG_MASK 0x0000005FU +/**< SMC ECC memconfig 1 reset value */ +#define XSMC_ECC_MEMCFG1_RESET_VAL 0x00000043U +/**< SMC ECC memcommand 1 reset value */ +#define XSMC_ECC_MEMCMD1_RESET_VAL 0x01300080U +/**< SMC ECC memcommand 2 reset value */ +#define XSMC_ECC_MEMCMD2_RESET_VAL 0x01E00585U + +/**< DDR controller reset bit mask */ +#define XDDRPS_CTRL_RESET_MASK 0x00000001U +/**< SLCR OCM configuration reset value*/ +#define XSLCR_OCM_CFG_RESETVAL 0x00000008U +/**< SLCR OCM bank selection mask*/ +#define XSLCR_OCM_CFG_HIADDR_MASK 0x0000000FU +/**< SLCR level shifter enable mask*/ +#define XSLCR_LVL_SHFTR_EN_MASK 0x0000000FU + +/**< SLCR PLL register reset values */ +#define XSLCR_ARM_PLL_CTRL_RESET_VAL 0x0001A008U +#define XSLCR_DDR_PLL_CTRL_RESET_VAL 0x0001A008U +#define XSLCR_IO_PLL_CTRL_RESET_VAL 0x0001A008U +#define XSLCR_ARM_PLL_CFG_RESET_VAL 0x00177EA0U +#define XSLCR_DDR_PLL_CFG_RESET_VAL 0x00177EA0U +#define XSLCR_IO_PLL_CFG_RESET_VAL 0x00177EA0U +#define XSLCR_ARM_CLK_CTRL_RESET_VAL 0x1F000400U +#define XSLCR_DDR_CLK_CTRL_RESET_VAL 0x18400003U + +/**< SLCR MIO register default values */ +#define XSLCR_MIO_PIN_00_RESET_VAL 0x00001601U +#define XSLCR_MIO_PIN_02_RESET_VAL 0x00000601U + +/**< SLCR Reset control registers default values */ +#define XSLCR_DMAC_RST_CTRL_VAL 0x00000001U +#define XSLCR_GEM_RST_CTRL_VAL 0x000000F3U +#define XSLCR_USB_RST_CTRL_VAL 0x00000003U +#define XSLCR_I2C_RST_CTRL_VAL 0x00000003U +#define XSLCR_SPI_RST_CTRL_VAL 0x0000000FU +#define XSLCR_UART_RST_CTRL_VAL 0x0000000FU +#define XSLCR_QSPI_RST_CTRL_VAL 0x00000003U +#define XSLCR_GPIO_RST_CTRL_VAL 0x00000001U +#define XSLCR_SMC_RST_CTRL_VAL 0x00000003U +#define XSLCR_OCM_RST_CTRL_VAL 0x00000001U +#define XSLCR_SDIO_RST_CTRL_VAL 0x00000033U +#define XSLCR_CAN_RST_CTRL_VAL 0x00000003U +/**************************** Type Definitions *******************************/ + +/* the following data type is used to hold a null terminated version string + * consisting of the following format, "X.YYX" + */ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ +/* + * Performs reset operation to the ddr interface + */ +void XDdr_ResetHw(void); +/* + * Map the ocm region to post bootrom state + */ +void XOcm_Remap(void); +/* + * Performs the smc interface reset + */ +void XSmc_ResetHw(u32 BaseAddress); +/* + * updates the MIO registers with reset values + */ +void XSlcr_MioWriteResetValues(void); +/* + * updates the PLL and clock registers with reset values + */ +void XSlcr_PllWriteResetValues(void); +/* + * Disables the level shifters + */ +void XSlcr_DisableLevelShifters(void); +/* + * provides softreset to the GPIO interface + */ +void XSlcr_GpioPsReset(void); +/* + * provides softreset to the DMA interface + */ +void XSlcr_DmaPsReset(void); +/* + * provides softreset to the SMC interface + */ +void XSlcr_SmcPsReset(void); +/* + * provides softreset to the CAN interface + */ +void XSlcr_CanPsReset(void); +/* + * provides softreset to the Uart interface + */ +void XSlcr_UartPsReset(void); +/* + * provides softreset to the I2C interface + */ +void XSlcr_I2cPsReset(void); +/* + * provides softreset to the SPI interface + */ +void XSlcr_SpiPsReset(void); +/* + * provides softreset to the QSPI interface + */ +void XSlcr_QspiPsReset(void); +/* + * provides softreset to the USB interface + */ +void XSlcr_UsbPsReset(void); +/* + * provides softreset to the GEM interface + */ +void XSlcr_EmacPsReset(void); +/* + * provides softreset to the OCM interface + */ +void XSlcr_OcmReset(void); + + +#ifdef __cplusplus +} +#endif + +#endif /* XIL_MISC_RESET_H */ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_printf.c b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_printf.c new file mode 100644 index 0000000..3113269 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_printf.c @@ -0,0 +1,443 @@ +/*---------------------------------------------------*/ +/* Modified from : */ +/* Public Domain version of printf */ +/* Rud Merriam, Compsult, Inc. Houston, Tx. */ +/* For Embedded Systems Programming, 1991 */ +/* */ +/*---------------------------------------------------*/ +#include "xil_printf.h" +#include "xil_types.h" +#include "xil_assert.h" +#include +#include +#include + +static void padding( const s32 l_flag,const struct params_s *par); +static void outs(const charptr lp, struct params_s *par); +static s32 getnum( charptr* linep); + +typedef struct params_s { + s32 len; + s32 num1; + s32 num2; + char8 pad_character; + s32 do_padding; + s32 left_flag; + s32 unsigned_flag; +} params_t; + + +/*---------------------------------------------------*/ +/* The purpose of this routine is to output data the */ +/* same as the standard printf function without the */ +/* overhead most run-time libraries involve. Usually */ +/* the printf brings in many kilobytes of code and */ +/* that is unacceptable in most embedded systems. */ +/*---------------------------------------------------*/ + + +/*---------------------------------------------------*/ +/* */ +/* This routine puts pad characters into the output */ +/* buffer. */ +/* */ +static void padding( const s32 l_flag, const struct params_s *par) +{ + s32 i; + + if ((par->do_padding != 0) && (l_flag != 0) && (par->len < par->num1)) { + i=(par->len); + for (; i<(par->num1); i++) { +#ifdef STDOUT_BASEADDRESS + outbyte( par->pad_character); +#endif + } + } +} + +/*---------------------------------------------------*/ +/* */ +/* This routine moves a string to the output buffer */ +/* as directed by the padding and positioning flags. */ +/* */ +static void outs(const charptr lp, struct params_s *par) +{ + charptr LocalPtr; + LocalPtr = lp; + /* pad on left if needed */ + if(LocalPtr != NULL) { + par->len = (s32)strlen( LocalPtr); + } + padding( !(par->left_flag), par); + + /* Move string to the buffer */ + while (((*LocalPtr) != (char8)0) && ((par->num2) != 0)) { + (par->num2)--; +#ifdef STDOUT_BASEADDRESS + outbyte(*LocalPtr); +#endif + LocalPtr += 1; +} + + /* Pad on right if needed */ + /* CR 439175 - elided next stmt. Seemed bogus. */ + /* par->len = strlen( lp) */ + padding( par->left_flag, par); +} + +/*---------------------------------------------------*/ +/* */ +/* This routine moves a number to the output buffer */ +/* as directed by the padding and positioning flags. */ +/* */ + +static void outnum( const s32 n, const s32 base, struct params_s *par) +{ + s32 negative; + s32 i; + char8 outbuf[32]; + const char8 digits[] = "0123456789ABCDEF"; + u32 num; + for(i = 0; i<32; i++) { + outbuf[i] = '0'; + } + + /* Check if number is negative */ + if ((par->unsigned_flag == 0) && (base == 10) && (n < 0L)) { + negative = 1; + num =(-(n)); + } + else{ + num = n; + negative = 0; + } + + /* Build number (backwards) in outbuf */ + i = 0; + do { + outbuf[i] = digits[(num % base)]; + i++; + num /= base; + } while (num > 0); + + if (negative != 0) { + outbuf[i] = '-'; + i++; + } + + outbuf[i] = '\0'; + i--; + + /* Move the converted number to the buffer and */ + /* add in the padding where needed. */ + par->len = (s32)strlen(outbuf); + padding( !(par->left_flag), par); + while (&outbuf[i] >= outbuf) { +#ifdef STDOUT_BASEADDRESS + outbyte( outbuf[i] ); +#endif + i--; +} + padding( par->left_flag, par); +} +/*---------------------------------------------------*/ +/* */ +/* This routine moves a 64-bit number to the output */ +/* buffer as directed by the padding and positioning */ +/* flags. */ +/* */ +#if defined (__aarch64__) || defined (__arch64__) +static void outnum1( const s64 n, const s32 base, params_t *par) +{ + s32 negative; + s32 i; + char8 outbuf[64]; + const char8 digits[] = "0123456789ABCDEF"; + u64 num; + for(i = 0; i<64; i++) { + outbuf[i] = '0'; + } + + /* Check if number is negative */ + if ((par->unsigned_flag == 0) && (base == 10) && (n < 0L)) { + negative = 1; + num =(-(n)); + } + else{ + num = (n); + negative = 0; + } + + /* Build number (backwards) in outbuf */ + i = 0; + do { + outbuf[i] = digits[(num % base)]; + i++; + num /= base; + } while (num > 0); + + if (negative != 0) { + outbuf[i] = '-'; + i++; + } + + outbuf[i] = '\0'; + i--; + + /* Move the converted number to the buffer and */ + /* add in the padding where needed. */ + par->len = (s32)strlen(outbuf); + padding( !(par->left_flag), par); + while (&outbuf[i] >= outbuf) { + outbyte( outbuf[i] ); + i--; +} + padding( par->left_flag, par); +} +#endif +/*---------------------------------------------------*/ +/* */ +/* This routine gets a number from the format */ +/* string. */ +/* */ +static s32 getnum( charptr* linep) +{ + s32 n; + s32 ResultIsDigit = 0; + charptr cptr; + n = 0; + cptr = *linep; + if(cptr != NULL){ + ResultIsDigit = isdigit(((s32)*cptr)); + } + while (ResultIsDigit != 0) { + if(cptr != NULL){ + n = ((n*10) + (((s32)*cptr) - (s32)'0')); + cptr += 1; + if(cptr != NULL){ + ResultIsDigit = isdigit(((s32)*cptr)); + } + } + ResultIsDigit = isdigit(((s32)*cptr)); + } + *linep = ((charptr )(cptr)); + return(n); +} + +/*---------------------------------------------------*/ +/* */ +/* This routine operates just like a printf/sprintf */ +/* routine. It outputs a set of data under the */ +/* control of a formatting string. Not all of the */ +/* standard C format control are supported. The ones */ +/* provided are primarily those needed for embedded */ +/* systems work. Primarily the floating point */ +/* routines are omitted. Other formats could be */ +/* added easily by following the examples shown for */ +/* the supported formats. */ +/* */ + +/* void esp_printf( const func_ptr f_ptr, + const charptr ctrl1, ...) */ +#if defined (__aarch64__) && HYP_GUEST && EL1_NONSECURE && XEN_USE_PV_CONSOLE +void xil_printf( const char8 *ctrl1, ...){ + XPVXenConsole_Printf(ctrl1); +} +#else +void xil_printf( const char8 *ctrl1, ...) +{ + s32 Check; +#if defined (__aarch64__) || defined (__arch64__) + s32 long_flag; +#endif + s32 dot_flag; + + params_t par; + + char8 ch; + va_list argp; + char8 *ctrl = (char8 *)ctrl1; + + va_start( argp, ctrl1); + + while ((ctrl != NULL) && (*ctrl != (char8)0)) { + + /* move format string chars to buffer until a */ + /* format control is found. */ + if (*ctrl != '%') { +#ifdef STDOUT_BASEADDRESS + outbyte(*ctrl); +#endif + ctrl += 1; + continue; + } + + /* initialize all the flags for this format. */ + dot_flag = 0; +#if defined (__aarch64__) || defined (__arch64__) + long_flag = 0; +#endif + par.unsigned_flag = 0; + par.left_flag = 0; + par.do_padding = 0; + par.pad_character = ' '; + par.num2=32767; + par.num1=0; + par.len=0; + + try_next: + if(ctrl != NULL) { + ctrl += 1; + } + if(ctrl != NULL) { + ch = *ctrl; + } + else { + ch = *ctrl; + } + + if (isdigit((s32)ch) != 0) { + if (dot_flag != 0) { + par.num2 = getnum(&ctrl); + } + else { + if (ch == '0') { + par.pad_character = '0'; + } + if(ctrl != NULL) { + par.num1 = getnum(&ctrl); + } + par.do_padding = 1; + } + if(ctrl != NULL) { + ctrl -= 1; + } + goto try_next; + } + + switch (tolower((s32)ch)) { + case '%': +#ifdef STDOUT_BASEADDRESS + outbyte( '%'); +#endif + Check = 1; + break; + + case '-': + par.left_flag = 1; + Check = 0; + break; + + case '.': + dot_flag = 1; + Check = 0; + break; + + case 'l': + #if defined (__aarch64__) || defined (__arch64__) + long_flag = 1; + #endif + Check = 0; + break; + + case 'u': + par.unsigned_flag = 1; + /* fall through */ + case 'i': + case 'd': + #if defined (__aarch64__) || defined (__arch64__) + if (long_flag != 0){ + outnum1((s64)va_arg(argp, s64), 10L, &par); + } + else { + outnum( va_arg(argp, s32), 10L, &par); + } + #else + outnum( va_arg(argp, s32), 10L, &par); + #endif + Check = 1; + break; + case 'p': + #if defined (__aarch64__) || defined (__arch64__) + par.unsigned_flag = 1; + outnum1((s64)va_arg(argp, s64), 16L, &par); + Check = 1; + break; + #endif + case 'X': + case 'x': + par.unsigned_flag = 1; + #if defined (__aarch64__) || defined (__arch64__) + if (long_flag != 0) { + outnum1((s64)va_arg(argp, s64), 16L, &par); + } + else { + outnum((s32)va_arg(argp, s32), 16L, &par); + } + #else + outnum((s32)va_arg(argp, s32), 16L, &par); + #endif + Check = 1; + break; + + case 's': + outs( va_arg( argp, char *), &par); + Check = 1; + break; + + case 'c': +#ifdef STDOUT_BASEADDRESS + outbyte( va_arg( argp, s32)); +#endif + Check = 1; + break; + + case '\\': + switch (*ctrl) { + case 'a': +#ifdef STDOUT_BASEADDRESS + outbyte( ((char8)0x07)); +#endif + break; + case 'h': +#ifdef STDOUT_BASEADDRESS + outbyte( ((char8)0x08)); +#endif + break; + case 'r': +#ifdef STDOUT_BASEADDRESS + outbyte( ((char8)0x0D)); +#endif + break; + case 'n': +#ifdef STDOUT_BASEADDRESS + outbyte( ((char8)0x0D)); + outbyte( ((char8)0x0A)); +#endif + break; + default: +#ifdef STDOUT_BASEADDRESS + outbyte( *ctrl); +#endif + break; + } + ctrl += 1; + Check = 0; + break; + + default: + Check = 1; + break; + } + if(Check == 1) { + if(ctrl != NULL) { + ctrl += 1; + } + continue; + } + goto try_next; + } + va_end( argp); +} +#endif +/*---------------------------------------------------*/ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_printf.h b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_printf.h new file mode 100644 index 0000000..a0177fc --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_printf.h @@ -0,0 +1,48 @@ + #ifndef XIL_PRINTF_H + #define XIL_PRINTF_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include "xil_types.h" +#include "xparameters.h" +#include "bspconfig.h" +#if defined (__aarch64__) && HYP_GUEST && EL1_NONSECURE && XEN_USE_PV_CONSOLE +#include "xen_console.h" +#endif + +/*----------------------------------------------------*/ +/* Use the following parameter passing structure to */ +/* make xil_printf re-entrant. */ +/*----------------------------------------------------*/ + +struct params_s; + + +/*---------------------------------------------------*/ +/* The purpose of this routine is to output data the */ +/* same as the standard printf function without the */ +/* overhead most run-time libraries involve. Usually */ +/* the printf brings in many kilobytes of code and */ +/* that is unacceptable in most embedded systems. */ +/*---------------------------------------------------*/ + +typedef char8* charptr; +typedef s32 (*func_ptr)(int c); + +/* */ + +void xil_printf( const char8 *ctrl1, ...); +void print( const char8 *ptr); +extern void outbyte (char8 c); +extern char8 inbyte(void); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_sleepcommon.c b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_sleepcommon.c new file mode 100644 index 0000000..cb28204 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_sleepcommon.c @@ -0,0 +1,102 @@ +/****************************************************************************** +* +* Copyright (C) 2017 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +*@file xil_sleepcommon.c +* +* This file contains the sleep API's +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 6.6 	srm  	 11/02/17 First release
+* 
+******************************************************************************/ + + +/***************************** Include Files *********************************/ +#include "xil_io.h" +#include "sleep.h" + +/**************************** Constant Definitions *************************/ + + +/*****************************************************************************/ +/** +* +* This API gives delay in sec +* +* @param seconds - delay time in seconds +* +* @return none +* +* @note none +* +*****************************************************************************/ + void sleep(unsigned int seconds) + { +#if defined (ARMR5) + sleep_R5(seconds); +#elif defined (__aarch64__) || defined (ARMA53_32) + sleep_A53(seconds); +#elif defined (__MICROBLAZE__) + sleep_MB(seconds); +#else + sleep_A9(seconds); +#endif + + } + +/****************************************************************************/ +/** +* +* This API gives delay in usec +* +* @param useconds - delay time in useconds +* +* @return none +* +* @note none +* +*****************************************************************************/ + void usleep(unsigned long useconds) + { +#if defined (ARMR5) + usleep_R5(useconds); +#elif defined (__aarch64__) || defined (ARMA53_32) + usleep_A53(useconds); +#elif defined (__MICROBLAZE__) + usleep_MB(useconds); +#else + usleep_A9(useconds); +#endif + + } diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_testcache.c b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_testcache.c new file mode 100644 index 0000000..6ea52a8 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_testcache.c @@ -0,0 +1,367 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_testcache.c +* +* Contains utility functions to test cache. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date	 Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a hbm  07/28/09 Initial release
+* 4.1   asa  05/09/14 Ensured that the address uses for cache test is aligned
+*				      cache line.
+* 
+* +* @note +* This file contain functions that all operate on HAL. +* +******************************************************************************/ +#ifdef __ARM__ +#include "xil_cache.h" +#include "xil_testcache.h" +#include "xil_types.h" +#include "xpseudo_asm.h" +#ifdef __aarch64__ +#include "xreg_cortexa53.h" +#else +#include "xreg_cortexr5.h" +#endif + +#include "xil_types.h" + +extern void xil_printf(const char8 *ctrl1, ...); + +#define DATA_LENGTH 128 + +#ifdef __aarch64__ +static INTPTR Data[DATA_LENGTH] __attribute__ ((aligned(64))); +#else +static INTPTR Data[DATA_LENGTH] __attribute__ ((aligned(32))); +#endif + + +/*****************************************************************************/ +/** +* +* @brief Perform DCache range related API test such as Xil_DCacheFlushRange +* and Xil_DCacheInvalidateRange. This test function writes a constant +* value to the Data array, flushes the range, writes a new value, then +* invalidates the corresponding range. +* @param None +* +* @return +* - -1 is returned for a failure +* - 0 is returned for a pass +* +*****************************************************************************/ +s32 Xil_TestDCacheRange(void) +{ + s32 Index; + s32 Status = 0; + u32 CtrlReg; + INTPTR Value; + + xil_printf("-- Cache Range Test --\n\r"); + + for (Index = 0; Index < DATA_LENGTH; Index++) + Data[Index] = 0xA0A00505; + + xil_printf(" initialize Data done:\r\n"); + + Xil_DCacheFlushRange((INTPTR)Data, DATA_LENGTH * sizeof(INTPTR)); + + xil_printf(" flush range done\r\n"); + + dsb(); + #ifdef __aarch64__ + CtrlReg = mfcp(SCTLR_EL3); + CtrlReg &= ~(XREG_CONTROL_DCACHE_BIT); + mtcp(SCTLR_EL3,CtrlReg); + #else + CtrlReg = mfcp(XREG_CP15_SYS_CONTROL); + CtrlReg &= ~(XREG_CP15_CONTROL_C_BIT); + mtcp(XREG_CP15_SYS_CONTROL, CtrlReg); + #endif + dsb(); + + Status = 0; + + for (Index = 0; Index < DATA_LENGTH; Index++) { + Value = Data[Index]; + if (Value != 0xA0A00505) { + Status = -1; + xil_printf("Data[%d] = %x\r\n", Index, Value); + break; + } + } + + if (!Status) { + xil_printf(" Flush worked\r\n"); + } + else { + xil_printf("Error: flush dcache range not working\r\n"); + } + dsb(); + #ifdef __aarch64__ + CtrlReg = mfcp(SCTLR_EL3); + CtrlReg |= (XREG_CONTROL_DCACHE_BIT); + mtcp(SCTLR_EL3,CtrlReg); + #else + CtrlReg = mfcp(XREG_CP15_SYS_CONTROL); + CtrlReg |= (XREG_CP15_CONTROL_C_BIT); + mtcp(XREG_CP15_SYS_CONTROL, CtrlReg); + #endif + dsb(); + for (Index = 0; Index < DATA_LENGTH; Index++) + Data[Index] = 0xA0A0C505; + + + + Xil_DCacheFlushRange((INTPTR)Data, DATA_LENGTH * sizeof(INTPTR)); + + for (Index = 0; Index < DATA_LENGTH; Index++) + Data[Index] = Index + 3; + + Xil_DCacheInvalidateRange((INTPTR)Data, DATA_LENGTH * sizeof(INTPTR)); + + xil_printf(" invalidate dcache range done\r\n"); + dsb(); + #ifdef __aarch64__ + CtrlReg = mfcp(SCTLR_EL3); + CtrlReg &= ~(XREG_CONTROL_DCACHE_BIT); + mtcp(SCTLR_EL3,CtrlReg); + #else + CtrlReg = mfcp(XREG_CP15_SYS_CONTROL); + CtrlReg &= ~(XREG_CP15_CONTROL_C_BIT); + mtcp(XREG_CP15_SYS_CONTROL, CtrlReg); + #endif + dsb(); + for (Index = 0; Index < DATA_LENGTH; Index++) + Data[Index] = 0xA0A0A05; + dsb(); + #ifdef __aarch64__ + CtrlReg = mfcp(SCTLR_EL3); + CtrlReg |= (XREG_CONTROL_DCACHE_BIT); + mtcp(SCTLR_EL3,CtrlReg); + #else + CtrlReg = mfcp(XREG_CP15_SYS_CONTROL); + CtrlReg |= (XREG_CP15_CONTROL_C_BIT); + mtcp(XREG_CP15_SYS_CONTROL, CtrlReg); + #endif + dsb(); + + Status = 0; + + for (Index = 0; Index < DATA_LENGTH; Index++) { + Value = Data[Index]; + if (Value != 0xA0A0A05) { + Status = -1; + xil_printf("Data[%d] = %x\r\n", Index, Value); + break; + } + } + + + if (!Status) { + xil_printf(" Invalidate worked\r\n"); + } + else { + xil_printf("Error: Invalidate dcache range not working\r\n"); + } + xil_printf("-- Cache Range Test Complete --\r\n"); + return Status; + +} + +/*****************************************************************************/ +/** +* @brief Perform DCache all related API test such as Xil_DCacheFlush and +* Xil_DCacheInvalidate. This test function writes a constant value +* to the Data array, flushes the DCache, writes a new value, +* then invalidates the DCache. +* +* @return +* - 0 is returned for a pass +* - -1 is returned for a failure +*****************************************************************************/ +s32 Xil_TestDCacheAll(void) +{ + s32 Index; + s32 Status; + INTPTR Value; + u32 CtrlReg; + + xil_printf("-- Cache All Test --\n\r"); + + for (Index = 0; Index < DATA_LENGTH; Index++) + Data[Index] = 0x50500A0A; + xil_printf(" initialize Data done:\r\n"); + + Xil_DCacheFlush(); + xil_printf(" flush all done\r\n"); + dsb(); + #ifdef __aarch64__ + CtrlReg = mfcp(SCTLR_EL3); + CtrlReg &= ~(XREG_CONTROL_DCACHE_BIT); + mtcp(SCTLR_EL3,CtrlReg); + #else + CtrlReg = mfcp(XREG_CP15_SYS_CONTROL); + CtrlReg &= ~(XREG_CP15_CONTROL_C_BIT); + mtcp(XREG_CP15_SYS_CONTROL, CtrlReg); + #endif + dsb(); + Status = 0; + + for (Index = 0; Index < DATA_LENGTH; Index++) { + Value = Data[Index]; + + if (Value != 0x50500A0A) { + Status = -1; + xil_printf("Data[%d] = %x\r\n", Index, Value); + break; + } + } + + if (!Status) { + xil_printf(" Flush all worked\r\n"); + } + else { + xil_printf("Error: Flush dcache all not working\r\n"); + } + dsb(); + #ifdef __aarch64__ + CtrlReg = mfcp(SCTLR_EL3); + CtrlReg |= (XREG_CONTROL_DCACHE_BIT); + mtcp(SCTLR_EL3,CtrlReg); + #else + CtrlReg = mfcp(XREG_CP15_SYS_CONTROL); + CtrlReg |= (XREG_CP15_CONTROL_C_BIT); + mtcp(XREG_CP15_SYS_CONTROL, CtrlReg); + #endif + dsb(); + for (Index = 0; Index < DATA_LENGTH; Index++) + Data[Index] = 0x505FFA0A; + + Xil_DCacheFlush(); + + + for (Index = 0; Index < DATA_LENGTH; Index++) + Data[Index] = Index + 3; + + Xil_DCacheInvalidate(); + + xil_printf(" invalidate all done\r\n"); + dsb(); + #ifdef __aarch64__ + CtrlReg = mfcp(SCTLR_EL3); + CtrlReg &= ~(XREG_CONTROL_DCACHE_BIT); + mtcp(SCTLR_EL3,CtrlReg); + #else + CtrlReg = mfcp(XREG_CP15_SYS_CONTROL); + CtrlReg &= ~(XREG_CP15_CONTROL_C_BIT); + mtcp(XREG_CP15_SYS_CONTROL, CtrlReg); + #endif + dsb(); + for (Index = 0; Index < DATA_LENGTH; Index++) + Data[Index] = 0x50CFA0A; + dsb(); + #ifdef __aarch64__ + CtrlReg = mfcp(SCTLR_EL3); + CtrlReg |= (XREG_CONTROL_DCACHE_BIT); + mtcp(SCTLR_EL3,CtrlReg); + #else + CtrlReg = mfcp(XREG_CP15_SYS_CONTROL); + CtrlReg |= (XREG_CP15_CONTROL_C_BIT); + mtcp(XREG_CP15_SYS_CONTROL, CtrlReg); + #endif + dsb(); + Status = 0; + + for (Index = 0; Index < DATA_LENGTH; Index++) { + Value = Data[Index]; + if (Value != 0x50CFA0A) { + Status = -1; + xil_printf("Data[%d] = %x\r\n", Index, Value); + break; + } + } + + if (!Status) { + xil_printf(" Invalidate all worked\r\n"); + } + else { + xil_printf("Error: Invalidate dcache all not working\r\n"); + } + + xil_printf("-- DCache all Test Complete --\n\r"); + + return Status; +} + +/*****************************************************************************/ +/** +* @brief Perform Xil_ICacheInvalidateRange() on a few function pointers. +* +* @return +* - 0 is returned for a pass +* @note +* The function will hang if it fails. +*****************************************************************************/ +s32 Xil_TestICacheRange(void) +{ + + Xil_ICacheInvalidateRange((INTPTR)Xil_TestICacheRange, 1024); + Xil_ICacheInvalidateRange((INTPTR)Xil_TestDCacheRange, 1024); + Xil_ICacheInvalidateRange((INTPTR)Xil_TestDCacheAll, 1024); + + xil_printf("-- Invalidate icache range done --\r\n"); + + return 0; +} + +/*****************************************************************************/ +/** +* @brief Perform Xil_ICacheInvalidate() on a few function pointers. +* +* @return +* - 0 is returned for a pass +* @note +* The function will hang if it fails. +*****************************************************************************/ +s32 Xil_TestICacheAll(void) +{ + Xil_ICacheInvalidate(); + xil_printf("-- Invalidate icache all done --\r\n"); + return 0; +} +#endif diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_testcache.h b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_testcache.h new file mode 100644 index 0000000..8289ca9 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_testcache.h @@ -0,0 +1,67 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_testcache.h +* +* @addtogroup common_test_utils +*

Cache test

+* The xil_testcache.h file contains utility functions to test cache. +* +* @{ +*
+* Ver    Who    Date    Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a hbm  07/29/09 First release
+* 
+* +******************************************************************************/ + +#ifndef XIL_TESTCACHE_H /* prevent circular inclusions */ +#define XIL_TESTCACHE_H /* by using protection macros */ + +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern s32 Xil_TestDCacheRange(void); +extern s32 Xil_TestDCacheAll(void); +extern s32 Xil_TestICacheRange(void); +extern s32 Xil_TestICacheAll(void); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** +* @} End of "addtogroup common_test_utils". +*/ \ No newline at end of file diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_testio.c b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_testio.c new file mode 100644 index 0000000..9a13a64 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_testio.c @@ -0,0 +1,295 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_testio.c +* +* Contains the memory test utility functions. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver    Who    Date    Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a hbm  08/25/09 First release
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ +#include "xil_testio.h" +#include "xil_assert.h" +#include "xil_io.h" + +/************************** Constant Definitions ****************************/ +/************************** Function Prototypes *****************************/ + + + +/** + * + * Endian swap a 16-bit word. + * @param Data is the 16-bit word to be swapped. + * @return The endian swapped value. + * + */ +static u16 Swap16(u16 Data) +{ + return ((Data >> 8U) & 0x00FFU) | ((Data << 8U) & 0xFF00U); +} + +/** + * + * Endian swap a 32-bit word. + * @param Data is the 32-bit word to be swapped. + * @return The endian swapped value. + * + */ +static u32 Swap32(u32 Data) +{ + u16 Lo16; + u16 Hi16; + + u16 Swap16Lo; + u16 Swap16Hi; + + Hi16 = (u16)((Data >> 16U) & 0x0000FFFFU); + Lo16 = (u16)(Data & 0x0000FFFFU); + + Swap16Lo = Swap16(Lo16); + Swap16Hi = Swap16(Hi16); + + return (((u32)(Swap16Lo)) << 16U) | ((u32)Swap16Hi); +} + +/*****************************************************************************/ +/** +* +* @brief Perform a destructive 8-bit wide register IO test where the +* register is accessed using Xil_Out8 and Xil_In8, and comparing +* the written values by reading them back. +* +* @param Addr: a pointer to the region of memory to be tested. +* @param Length: Length of the block. +* @param Value: constant used for writting the memory. +* +* @return +* - -1 is returned for a failure +* - 0 is returned for a pass +* +*****************************************************************************/ + +s32 Xil_TestIO8(u8 *Addr, s32 Length, u8 Value) +{ + u8 ValueIn; + s32 Index; + s32 Status = 0; + + for (Index = 0; Index < Length; Index++) { + Xil_Out8((INTPTR)Addr, Value); + + ValueIn = Xil_In8((INTPTR)Addr); + + if ((Value != ValueIn) && (Status == 0)) { + Status = -1; + break; + } + } + return Status; + +} + +/*****************************************************************************/ +/** +* +* @brief Perform a destructive 16-bit wide register IO test. Each location +* is tested by sequentially writing a 16-bit wide register, reading +* the register, and comparing value. This function tests three kinds +* of register IO functions, normal register IO, little-endian register +* IO, and big-endian register IO. When testing little/big-endian IO, +* the function performs the following sequence, Xil_Out16LE/Xil_Out16BE, +* Xil_In16, Compare In-Out values, Xil_Out16, Xil_In16LE/Xil_In16BE, +* Compare In-Out values. Whether to swap the read-in value before +* comparing is controlled by the 5th argument. +* +* @param Addr: a pointer to the region of memory to be tested. +* @param Length: Length of the block. +* @param Value: constant used for writting the memory. +* @param Kind: Type of test. Acceptable values are: +* XIL_TESTIO_DEFAULT, XIL_TESTIO_LE, XIL_TESTIO_BE. +* @param Swap: indicates whether to byte swap the read-in value. +* +* @return +* - -1 is returned for a failure +* - 0 is returned for a pass +* +*****************************************************************************/ + +s32 Xil_TestIO16(u16 *Addr, s32 Length, u16 Value, s32 Kind, s32 Swap) +{ + u16 *TempAddr16; + u16 ValueIn = 0U; + s32 Index; + TempAddr16 = Addr; + Xil_AssertNonvoid(TempAddr16 != NULL); + + for (Index = 0; Index < Length; Index++) { + switch (Kind) { + case XIL_TESTIO_LE: + Xil_Out16LE((INTPTR)TempAddr16, Value); + break; + case XIL_TESTIO_BE: + Xil_Out16BE((INTPTR)TempAddr16, Value); + break; + default: + Xil_Out16((INTPTR)TempAddr16, Value); + break; + } + + ValueIn = Xil_In16((INTPTR)TempAddr16); + + if ((Kind != 0) && (Swap != 0)) { + ValueIn = Swap16(ValueIn); + } + + if (Value != ValueIn) { + return -1; + } + + /* second round */ + Xil_Out16((INTPTR)TempAddr16, Value); + + switch (Kind) { + case XIL_TESTIO_LE: + ValueIn = Xil_In16LE((INTPTR)TempAddr16); + break; + case XIL_TESTIO_BE: + ValueIn = Xil_In16BE((INTPTR)TempAddr16); + break; + default: + ValueIn = Xil_In16((INTPTR)TempAddr16); + break; + } + + + if ((Kind != 0) && (Swap != 0)) { + ValueIn = Swap16(ValueIn); + } + + if (Value != ValueIn) { + return -1; + } + TempAddr16 += sizeof(u16); + } + return 0; +} + + +/*****************************************************************************/ +/** +* +* @brief Perform a destructive 32-bit wide register IO test. Each location +* is tested by sequentially writing a 32-bit wide regsiter, reading +* the register, and comparing value. This function tests three kinds +* of register IO functions, normal register IO, little-endian register IO, +* and big-endian register IO. When testing little/big-endian IO, +* the function perform the following sequence, Xil_Out32LE/ +* Xil_Out32BE, Xil_In32, Compare, Xil_Out32, Xil_In32LE/Xil_In32BE, Compare. +* Whether to swap the read-in value *before comparing is controlled +* by the 5th argument. +* @param Addr: a pointer to the region of memory to be tested. +* @param Length: Length of the block. +* @param Value: constant used for writting the memory. +* @param Kind: type of test. Acceptable values are: +* XIL_TESTIO_DEFAULT, XIL_TESTIO_LE, XIL_TESTIO_BE. +* @param Swap: indicates whether to byte swap the read-in value. +* +* @return +* - -1 is returned for a failure +* - 0 is returned for a pass +* +*****************************************************************************/ +s32 Xil_TestIO32(u32 *Addr, s32 Length, u32 Value, s32 Kind, s32 Swap) +{ + u32 *TempAddr; + u32 ValueIn = 0U; + s32 Index; + TempAddr = Addr; + Xil_AssertNonvoid(TempAddr != NULL); + + for (Index = 0; Index < Length; Index++) { + switch (Kind) { + case XIL_TESTIO_LE: + Xil_Out32LE((INTPTR)TempAddr, Value); + break; + case XIL_TESTIO_BE: + Xil_Out32BE((INTPTR)TempAddr, Value); + break; + default: + Xil_Out32((INTPTR)TempAddr, Value); + break; + } + + ValueIn = Xil_In32((INTPTR)TempAddr); + + if ((Kind != 0) && (Swap != 0)) { + ValueIn = Swap32(ValueIn); + } + + if (Value != ValueIn) { + return -1; + } + + /* second round */ + Xil_Out32((INTPTR)TempAddr, Value); + + + switch (Kind) { + case XIL_TESTIO_LE: + ValueIn = Xil_In32LE((INTPTR)TempAddr); + break; + case XIL_TESTIO_BE: + ValueIn = Xil_In32BE((INTPTR)TempAddr); + break; + default: + ValueIn = Xil_In32((INTPTR)TempAddr); + break; + } + + if ((Kind != 0) && (Swap != 0)) { + ValueIn = Swap32(ValueIn); + } + + if (Value != ValueIn) { + return -1; + } + TempAddr += sizeof(u32); + } + return 0; +} diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_testio.h b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_testio.h new file mode 100644 index 0000000..6f0fc1c --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_testio.h @@ -0,0 +1,90 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_testio.h +* +* @addtogroup common_test_utils Test Utilities +*

I/O test

+* The xil_testio.h file contains utility functions to test endian related memory +* IO functions. +* +* A subset of the memory tests can be selected or all of the tests can be run +* in order. If there is an error detected by a subtest, the test stops and the +* failure code is returned. Further tests are not run even if all of the tests +* are selected. +* +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver    Who    Date    Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00 hbm  08/05/09 First release
+* 
+* +******************************************************************************/ + +#ifndef XIL_TESTIO_H /* prevent circular inclusions */ +#define XIL_TESTIO_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ +#include "xil_types.h" + +/************************** Constant Definitions *****************************/ + + +#define XIL_TESTIO_DEFAULT 0 +#define XIL_TESTIO_LE 1 +#define XIL_TESTIO_BE 2 + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + +extern s32 Xil_TestIO8(u8 *Addr, s32 Length, u8 Value); +extern s32 Xil_TestIO16(u16 *Addr, s32 Length, u16 Value, s32 Kind, s32 Swap); +extern s32 Xil_TestIO32(u32 *Addr, s32 Length, u32 Value, s32 Kind, s32 Swap); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** +* @} End of "addtogroup common_test_utils". +*/ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_testmem.c b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_testmem.c new file mode 100644 index 0000000..b7eb68b --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_testmem.c @@ -0,0 +1,864 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_testmem.c +* +* Contains the memory test utility functions. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver    Who    Date    Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a hbm  08/25/09 First release
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ +#include "xil_testmem.h" +#include "xil_io.h" +#include "xil_assert.h" + +/************************** Constant Definitions ****************************/ +/************************** Function Prototypes *****************************/ + +static u32 RotateLeft(u32 Input, u8 Width); + +/* define ROTATE_RIGHT to give access to this functionality */ +/* #define ROTATE_RIGHT */ +#ifdef ROTATE_RIGHT +static u32 RotateRight(u32 Input, u8 Width); +#endif /* ROTATE_RIGHT */ + + +/*****************************************************************************/ +/** +* +* @brief Perform a destructive 32-bit wide memory test. +* +* @param Addr: pointer to the region of memory to be tested. +* @param Words: length of the block. +* @param Pattern: constant used for the constant pattern test, if 0, +* 0xDEADBEEF is used. +* @param Subtest: test type selected. See xil_testmem.h for possible +* values. +* +* @return +* - 0 is returned for a pass +* - 1 is returned for a failure +* +* @note +* Used for spaces where the address range of the region is smaller than +* the data width. If the memory range is greater than 2 ** Width, +* the patterns used in XIL_TESTMEM_WALKONES and XIL_TESTMEM_WALKZEROS will +* repeat on a boundry of a power of two making it more difficult to detect +* addressing errors. The XIL_TESTMEM_INCREMENT and XIL_TESTMEM_INVERSEADDR +* tests suffer the same problem. Ideally, if large blocks of memory are to be +* tested, break them up into smaller regions of memory to allow the test +* patterns used not to repeat over the region tested. +* +*****************************************************************************/ +s32 Xil_TestMem32(u32 *Addr, u32 Words, u32 Pattern, u8 Subtest) +{ + u32 I; + u32 j; + u32 Val; + u32 FirtVal; + u32 WordMem32; + s32 Status = 0; + + Xil_AssertNonvoid(Words != (u32)0); + Xil_AssertNonvoid(Subtest <= (u8)XIL_TESTMEM_MAXTEST); + Xil_AssertNonvoid(Addr != NULL); + + /* + * variable initialization + */ + Val = XIL_TESTMEM_INIT_VALUE; + FirtVal = XIL_TESTMEM_INIT_VALUE; + + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_INCREMENT)) { + /* + * Fill the memory with incrementing + * values starting from 'FirtVal' + */ + for (I = 0U; I < Words; I++) { + *(Addr+I) = Val; + Val++; + } + + /* + * Restore the reference 'Val' to the + * initial value + */ + Val = FirtVal; + + /* + * Check every word within the words + * of tested memory and compare it + * with the incrementing reference + * Val + */ + + for (I = 0U; I < Words; I++) { + WordMem32 = *(Addr+I); + + if (WordMem32 != Val) { + Status = -1; + goto End_Label; + } + + Val++; + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_WALKONES)) { + /* + * set up to cycle through all possible initial + * test Patterns for walking ones test + */ + + for (j = 0U; j < (u32)32; j++) { + /* + * Generate an initial value for walking ones test + * to test for bad data bits + */ + + Val = (1U << j); + + /* + * START walking ones test + * Write a one to each data bit indifferent locations + */ + + for (I = 0U; I < (u32)32; I++) { + /* write memory location */ + *(Addr+I) = Val; + Val = (u32) RotateLeft(Val, 32U); + } + + /* + * Restore the reference 'val' to the + * initial value + */ + Val = 1U << j; + + /* Read the values from each location that was + * written */ + for (I = 0U; I < (u32)32; I++) { + /* read memory location */ + + WordMem32 = *(Addr+I); + + if (WordMem32 != Val) { + Status = -1; + goto End_Label; + } + + Val = (u32)RotateLeft(Val, 32U); + } + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_WALKZEROS)) { + /* + * set up to cycle through all possible + * initial test Patterns for walking zeros test + */ + + for (j = 0U; j < (u32)32; j++) { + + /* + * Generate an initial value for walking ones test + * to test for bad data bits + */ + + Val = ~(1U << j); + + /* + * START walking zeros test + * Write a one to each data bit indifferent locations + */ + + for (I = 0U; I < (u32)32; I++) { + /* write memory location */ + *(Addr+I) = Val; + Val = ~((u32)RotateLeft(~Val, 32U)); + } + + /* + * Restore the reference 'Val' to the + * initial value + */ + + Val = ~(1U << j); + + /* Read the values from each location that was + * written */ + for (I = 0U; I < (u32)32; I++) { + /* read memory location */ + WordMem32 = *(Addr+I); + if (WordMem32 != Val) { + Status = -1; + goto End_Label; + } + Val = ~((u32)RotateLeft(~Val, 32U)); + } + + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_INVERSEADDR)) { + /* Fill the memory with inverse of address */ + for (I = 0U; I < Words; I++) { + /* write memory location */ + Val = (u32) (~((INTPTR) (&Addr[I]))); + *(Addr+I) = Val; + } + + /* + * Check every word within the words + * of tested memory + */ + + for (I = 0U; I < Words; I++) { + /* Read the location */ + WordMem32 = *(Addr+I); + Val = (u32) (~((INTPTR) (&Addr[I]))); + + if ((WordMem32 ^ Val) != 0x00000000U) { + Status = -1; + goto End_Label; + } + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_FIXEDPATTERN)) { + /* + * Generate an initial value for + * memory testing + */ + + if (Pattern == (u32)0) { + Val = 0xDEADBEEFU; + } + else { + Val = Pattern; + } + + /* + * Fill the memory with fixed Pattern + */ + + for (I = 0U; I < Words; I++) { + /* write memory location */ + *(Addr+I) = Val; + } + + /* + * Check every word within the words + * of tested memory and compare it + * with the fixed Pattern + */ + + for (I = 0U; I < Words; I++) { + + /* read memory location */ + + WordMem32 = *(Addr+I); + if (WordMem32 != Val) { + Status = -1; + goto End_Label; + } + } + } + +End_Label: + return Status; +} + +/*****************************************************************************/ +/** +* +* @brief Perform a destructive 16-bit wide memory test. +* +* @param Addr: pointer to the region of memory to be tested. +* @param Words: length of the block. +* @param Pattern: constant used for the constant Pattern test, if 0, +* 0xDEADBEEF is used. +* @param Subtest: type of test selected. See xil_testmem.h for possible +* values. +* +* @return +* +* - -1 is returned for a failure +* - 0 is returned for a pass +* +* @note +* Used for spaces where the address range of the region is smaller than +* the data width. If the memory range is greater than 2 ** Width, +* the patterns used in XIL_TESTMEM_WALKONES and XIL_TESTMEM_WALKZEROS will +* repeat on a boundry of a power of two making it more difficult to detect +* addressing errors. The XIL_TESTMEM_INCREMENT and XIL_TESTMEM_INVERSEADDR +* tests suffer the same problem. Ideally, if large blocks of memory are to be +* tested, break them up into smaller regions of memory to allow the test +* patterns used not to repeat over the region tested. +* +*****************************************************************************/ +s32 Xil_TestMem16(u16 *Addr, u32 Words, u16 Pattern, u8 Subtest) +{ + u32 I; + u32 j; + u16 Val; + u16 FirtVal; + u16 WordMem16; + s32 Status = 0; + + Xil_AssertNonvoid(Words != (u32)0); + Xil_AssertNonvoid(Subtest <= XIL_TESTMEM_MAXTEST); + Xil_AssertNonvoid(Addr != NULL); + + /* + * variable initialization + */ + Val = XIL_TESTMEM_INIT_VALUE; + FirtVal = XIL_TESTMEM_INIT_VALUE; + + /* + * selectthe proper Subtest(s) + */ + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_INCREMENT)) { + /* + * Fill the memory with incrementing + * values starting from 'FirtVal' + */ + for (I = 0U; I < Words; I++) { + /* write memory location */ + *(Addr+I) = Val; + Val++; + } + /* + * Restore the reference 'Val' to the + * initial value + */ + Val = FirtVal; + + /* + * Check every word within the words + * of tested memory and compare it + * with the incrementing reference val + */ + + for (I = 0U; I < Words; I++) { + /* read memory location */ + WordMem16 = *(Addr+I); + if (WordMem16 != Val) { + Status = -1; + goto End_Label; + } + Val++; + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_WALKONES)) { + /* + * set up to cycle through all possible initial test + * Patterns for walking ones test + */ + + for (j = 0U; j < (u32)16; j++) { + /* + * Generate an initial value for walking ones test + * to test for bad data bits + */ + + Val = (u16)((u32)1 << j); + /* + * START walking ones test + * Write a one to each data bit indifferent locations + */ + + for (I = 0U; I < (u32)16; I++) { + /* write memory location */ + *(Addr+I) = Val; + Val = (u16)RotateLeft(Val, 16U); + } + /* + * Restore the reference 'Val' to the + * initial value + */ + Val = (u16)((u32)1 << j); + /* Read the values from each location that was written */ + for (I = 0U; I < (u32)16; I++) { + /* read memory location */ + WordMem16 = *(Addr+I); + if (WordMem16 != Val) { + Status = -1; + goto End_Label; + } + Val = (u16)RotateLeft(Val, 16U); + } + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_WALKZEROS)) { + /* + * set up to cycle through all possible initial + * test Patterns for walking zeros test + */ + + for (j = 0U; j < (u32)16; j++) { + /* + * Generate an initial value for walking ones + * test to test for bad + * data bits + */ + + Val = ~(1U << j); + /* + * START walking zeros test + * Write a one to each data bit indifferent locations + */ + + for (I = 0U; I < (u32)16; I++) { + /* write memory location */ + *(Addr+I) = Val; + Val = ~((u16)RotateLeft(~Val, 16U)); + } + /* + * Restore the reference 'Val' to the + * initial value + */ + Val = ~(1U << j); + /* Read the values from each location that was written */ + for (I = 0U; I < (u32)16; I++) { + /* read memory location */ + WordMem16 = *(Addr+I); + if (WordMem16 != Val) { + Status = -1; + goto End_Label; + } + Val = ~((u16)RotateLeft(~Val, 16U)); + } + + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_INVERSEADDR)) { + /* Fill the memory with inverse of address */ + for (I = 0U; I < Words; I++) { + /* write memory location */ + Val = (u16) (~((INTPTR)(&Addr[I]))); + *(Addr+I) = Val; + } + /* + * Check every word within the words + * of tested memory + */ + + for (I = 0U; I < Words; I++) { + /* read memory location */ + WordMem16 = *(Addr+I); + Val = (u16) (~((INTPTR) (&Addr[I]))); + if ((WordMem16 ^ Val) != 0x0000U) { + Status = -1; + goto End_Label; + } + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_FIXEDPATTERN)) { + /* + * Generate an initial value for + * memory testing + */ + if (Pattern == (u16)0) { + Val = 0xDEADU; + } + else { + Val = Pattern; + } + + /* + * Fill the memory with fixed pattern + */ + + for (I = 0U; I < Words; I++) { + /* write memory location */ + *(Addr+I) = Val; + } + + /* + * Check every word within the words + * of tested memory and compare it + * with the fixed pattern + */ + + for (I = 0U; I < Words; I++) { + /* read memory location */ + WordMem16 = *(Addr+I); + if (WordMem16 != Val) { + Status = -1; + goto End_Label; + } + } + } + +End_Label: + return Status; +} + + +/*****************************************************************************/ +/** +* +* @brief Perform a destructive 8-bit wide memory test. +* +* @param Addr: pointer to the region of memory to be tested. +* @param Words: length of the block. +* @param Pattern: constant used for the constant pattern test, if 0, +* 0xDEADBEEF is used. +* @param Subtest: type of test selected. See xil_testmem.h for possible +* values. +* +* @return +* - -1 is returned for a failure +* - 0 is returned for a pass +* +* @note +* Used for spaces where the address range of the region is smaller than +* the data width. If the memory range is greater than 2 ** Width, +* the patterns used in XIL_TESTMEM_WALKONES and XIL_TESTMEM_WALKZEROS will +* repeat on a boundry of a power of two making it more difficult to detect +* addressing errors. The XIL_TESTMEM_INCREMENT and XIL_TESTMEM_INVERSEADDR +* tests suffer the same problem. Ideally, if large blocks of memory are to be +* tested, break them up into smaller regions of memory to allow the test +* patterns used not to repeat over the region tested. +* +*****************************************************************************/ +s32 Xil_TestMem8(u8 *Addr, u32 Words, u8 Pattern, u8 Subtest) +{ + u32 I; + u32 j; + u8 Val; + u8 FirtVal; + u8 WordMem8; + s32 Status = 0; + + Xil_AssertNonvoid(Words != (u32)0); + Xil_AssertNonvoid(Subtest <= XIL_TESTMEM_MAXTEST); + Xil_AssertNonvoid(Addr != NULL); + + /* + * variable initialization + */ + Val = XIL_TESTMEM_INIT_VALUE; + FirtVal = XIL_TESTMEM_INIT_VALUE; + + /* + * select the proper Subtest(s) + */ + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_INCREMENT)) { + /* + * Fill the memory with incrementing + * values starting from 'FirtVal' + */ + for (I = 0U; I < Words; I++) { + /* write memory location */ + *(Addr+I) = Val; + Val++; + } + /* + * Restore the reference 'Val' to the + * initial value + */ + Val = FirtVal; + /* + * Check every word within the words + * of tested memory and compare it + * with the incrementing reference + * Val + */ + + for (I = 0U; I < Words; I++) { + /* read memory location */ + WordMem8 = *(Addr+I); + if (WordMem8 != Val) { + Status = -1; + goto End_Label; + } + Val++; + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_WALKONES)) { + /* + * set up to cycle through all possible initial + * test Patterns for walking ones test + */ + + for (j = 0U; j < (u32)8; j++) { + /* + * Generate an initial value for walking ones test + * to test for bad data bits + */ + Val = (u8)((u32)1 << j); + /* + * START walking ones test + * Write a one to each data bit indifferent locations + */ + for (I = 0U; I < (u32)8; I++) { + /* write memory location */ + *(Addr+I) = Val; + Val = (u8)RotateLeft(Val, 8U); + } + /* + * Restore the reference 'Val' to the + * initial value + */ + Val = (u8)((u32)1 << j); + /* Read the values from each location that was written */ + for (I = 0U; I < (u32)8; I++) { + /* read memory location */ + WordMem8 = *(Addr+I); + if (WordMem8 != Val) { + Status = -1; + goto End_Label; + } + Val = (u8)RotateLeft(Val, 8U); + } + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_WALKZEROS)) { + /* + * set up to cycle through all possible initial test + * Patterns for walking zeros test + */ + + for (j = 0U; j < (u32)8; j++) { + /* + * Generate an initial value for walking ones test to test + * for bad data bits + */ + Val = ~(1U << j); + /* + * START walking zeros test + * Write a one to each data bit indifferent locations + */ + for (I = 0U; I < (u32)8; I++) { + /* write memory location */ + *(Addr+I) = Val; + Val = ~((u8)RotateLeft(~Val, 8U)); + } + /* + * Restore the reference 'Val' to the + * initial value + */ + Val = ~(1U << j); + /* Read the values from each location that was written */ + for (I = 0U; I < (u32)8; I++) { + /* read memory location */ + WordMem8 = *(Addr+I); + if (WordMem8 != Val) { + Status = -1; + goto End_Label; + } + + Val = ~((u8)RotateLeft(~Val, 8U)); + } + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_INVERSEADDR)) { + /* Fill the memory with inverse of address */ + for (I = 0U; I < Words; I++) { + /* write memory location */ + Val = (u8) (~((INTPTR) (&Addr[I]))); + *(Addr+I) = Val; + } + + /* + * Check every word within the words + * of tested memory + */ + + for (I = 0U; I < Words; I++) { + /* read memory location */ + WordMem8 = *(Addr+I); + Val = (u8) (~((INTPTR) (&Addr[I]))); + if ((WordMem8 ^ Val) != 0x00U) { + Status = -1; + goto End_Label; + } + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_FIXEDPATTERN)) { + /* + * Generate an initial value for + * memory testing + */ + + if (Pattern == (u8)0) { + Val = 0xA5U; + } + else { + Val = Pattern; + } + /* + * Fill the memory with fixed Pattern + */ + for (I = 0U; I < Words; I++) { + /* write memory location */ + *(Addr+I) = Val; + } + /* + * Check every word within the words + * of tested memory and compare it + * with the fixed Pattern + */ + + for (I = 0U; I < Words; I++) { + /* read memory location */ + WordMem8 = *(Addr+I); + if (WordMem8 != Val) { + Status = -1; + goto End_Label; + } + } + } + +End_Label: + return Status; +} + + +/*****************************************************************************/ +/** +* +* @brief Rotates the provided value to the left one bit position +* +* @param Input is value to be rotated to the left +* @param Width is the number of bits in the input data +* +* @return +* The resulting unsigned long value of the rotate left +* +* +*****************************************************************************/ +static u32 RotateLeft(u32 Input, u8 Width) +{ + u32 Msb; + u32 ReturnVal; + u32 WidthMask; + u32 MsbMask; + u32 LocalInput = Input; + + /* + * set up the WidthMask and the MsbMask + */ + + MsbMask = 1U << (Width - 1U); + + WidthMask = (MsbMask << (u32)1) - (u32)1; + + /* + * set the Width of the Input to the correct width + */ + + LocalInput = LocalInput & WidthMask; + + Msb = LocalInput & MsbMask; + + ReturnVal = LocalInput << 1U; + + if (Msb != 0x00000000U) { + ReturnVal = ReturnVal | (u32)0x00000001; + } + + ReturnVal = ReturnVal & WidthMask; + + return ReturnVal; + +} + +#ifdef ROTATE_RIGHT +/*****************************************************************************/ +/** +* +* @brief Rotates the provided value to the right one bit position +* +* @param Input: value to be rotated to the right +* @param Width: number of bits in the input data +* +* @return +* The resulting u32 value of the rotate right +* +*****************************************************************************/ +static u32 RotateRight(u32 Input, u8 Width) +{ + u32 Lsb; + u32 ReturnVal; + u32 WidthMask; + u32 MsbMask; + u32 LocalInput = Input; + /* + * set up the WidthMask and the MsbMask + */ + + MsbMask = 1U << (Width - 1U); + + WidthMask = (MsbMask << 1U) - 1U; + + /* + * set the width of the input to the correct width + */ + + LocalInput = LocalInput & WidthMask; + + ReturnVal = LocalInput >> 1U; + + Lsb = LocalInput & 0x00000001U; + + if (Lsb != 0x00000000U) { + ReturnVal = ReturnVal | MsbMask; + } + + ReturnVal = ReturnVal & WidthMask; + + return ReturnVal; + +} +#endif /* ROTATE_RIGHT */ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_testmem.h b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_testmem.h new file mode 100644 index 0000000..ecce6b7 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_testmem.h @@ -0,0 +1,154 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_testmem.h +* @addtogroup common_test_utils +* +*

Memory test

+* +* The xil_testmem.h file contains utility functions to test memory. +* A subset of the memory tests can be selected or all of the tests can be run +* in order. If there is an error detected by a subtest, the test stops and the +* failure code is returned. Further tests are not run even if all of the tests +* are selected. +* Following list describes the supported memory tests: +* +* - XIL_TESTMEM_ALLMEMTESTS: This test runs all of the subtests. +* +* - XIL_TESTMEM_INCREMENT: This test +* starts at 'XIL_TESTMEM_INIT_VALUE' and uses the incrementing value as the +* test value for memory. +* +* - XIL_TESTMEM_WALKONES: Also known as the Walking ones test. This test +* uses a walking '1' as the test value for memory. +* @code +* location 1 = 0x00000001 +* location 2 = 0x00000002 +* ... +* @endcode +* +* - XIL_TESTMEM_WALKZEROS: Also known as the Walking zero's test. +* This test uses the inverse value of the walking ones test +* as the test value for memory. +* @code +* location 1 = 0xFFFFFFFE +* location 2 = 0xFFFFFFFD +* ... +*@endcode +* +* - XIL_TESTMEM_INVERSEADDR: Also known as the inverse address test. +* This test uses the inverse of the address of the location under test +* as the test value for memory. +* +* - XIL_TESTMEM_FIXEDPATTERN: Also known as the fixed pattern test. +* This test uses the provided patters as the test value for memory. +* If zero is provided as the pattern the test uses '0xDEADBEEF". +* +* @warning +* The tests are DESTRUCTIVE. Run before any initialized memory spaces +* have been set up. +* The address provided to the memory tests is not checked for +* validity except for the NULL case. It is possible to provide a code-space +* pointer for this test to start with and ultimately destroy executable code +* causing random failures. +* +* @note +* Used for spaces where the address range of the region is smaller than +* the data width. If the memory range is greater than 2 ** width, +* the patterns used in XIL_TESTMEM_WALKONES and XIL_TESTMEM_WALKZEROS will +* repeat on a boundry of a power of two making it more difficult to detect +* addressing errors. The XIL_TESTMEM_INCREMENT and XIL_TESTMEM_INVERSEADDR +* tests suffer the same problem. Ideally, if large blocks of memory are to be +* tested, break them up into smaller regions of memory to allow the test +* patterns used not to repeat over the region tested. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver    Who    Date    Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a hbm  08/25/09 First release
+* 
+* +******************************************************************************/ + +#ifndef XIL_TESTMEM_H /* prevent circular inclusions */ +#define XIL_TESTMEM_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ +#include "xil_types.h" + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + +/* xutil_memtest defines */ + +#define XIL_TESTMEM_INIT_VALUE 1U + +/** @name Memory subtests + * @{ + */ +/** + * See the detailed description of the subtests in the file description. + */ +#define XIL_TESTMEM_ALLMEMTESTS 0x00U +#define XIL_TESTMEM_INCREMENT 0x01U +#define XIL_TESTMEM_WALKONES 0x02U +#define XIL_TESTMEM_WALKZEROS 0x03U +#define XIL_TESTMEM_INVERSEADDR 0x04U +#define XIL_TESTMEM_FIXEDPATTERN 0x05U +#define XIL_TESTMEM_MAXTEST XIL_TESTMEM_FIXEDPATTERN +/* @} */ + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + +/* xutil_testmem prototypes */ + +extern s32 Xil_TestMem32(u32 *Addr, u32 Words, u32 Pattern, u8 Subtest); +extern s32 Xil_TestMem16(u16 *Addr, u32 Words, u16 Pattern, u8 Subtest); +extern s32 Xil_TestMem8(u8 *Addr, u32 Words, u8 Pattern, u8 Subtest); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** +* @} End of "addtogroup common_test_utils". +*/ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_types.h b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_types.h new file mode 100644 index 0000000..625ff8c --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_types.h @@ -0,0 +1,214 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_types.h +* +* @addtogroup common_types Basic Data types for Xilinx® Software IP +* +* The xil_types.h file contains basic types for Xilinx software IP. These data types +* are applicable for all processors supported by Xilinx. +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date   Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a hbm  07/14/09 First release
+* 3.03a sdm  05/30/11 Added Xuint64 typedef and XUINT64_MSW/XUINT64_LSW macros
+* 5.00 	pkp  05/29/14 Made changes for 64 bit architecture
+*	srt  07/14/14 Use standard definitions from stdint.h and stddef.h
+*		      Define LONG and ULONG datatypes and mask values
+* 7.00  mus  01/07/19 Add cpp extern macro
+* 
+* +******************************************************************************/ + +#ifndef XIL_TYPES_H /* prevent circular inclusions */ +#define XIL_TYPES_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +/************************** Constant Definitions *****************************/ + +#ifndef TRUE +# define TRUE 1U +#endif + +#ifndef FALSE +# define FALSE 0U +#endif + +#ifndef NULL +#define NULL 0U +#endif + +#define XIL_COMPONENT_IS_READY 0x11111111U /**< In device drivers, This macro will be + assigend to "IsReady" member of driver + instance to indicate that driver + instance is initialized and ready to use. */ +#define XIL_COMPONENT_IS_STARTED 0x22222222U /**< In device drivers, This macro will be assigend to + "IsStarted" member of driver instance + to indicate that driver instance is + started and it can be enabled. */ + +/* @name New types + * New simple types. + * @{ + */ +#ifndef __KERNEL__ +#ifndef XBASIC_TYPES_H +/* + * guarded against xbasic_types.h. + */ +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; +/** @}*/ +#define __XUINT64__ +typedef struct +{ + u32 Upper; + u32 Lower; +} Xuint64; + + +/*****************************************************************************/ +/** +* @brief Return the most significant half of the 64 bit data type. +* +* @param x is the 64 bit word. +* +* @return The upper 32 bits of the 64 bit word. +* +******************************************************************************/ +#define XUINT64_MSW(x) ((x).Upper) + +/*****************************************************************************/ +/** +* @brief Return the least significant half of the 64 bit data type. +* +* @param x is the 64 bit word. +* +* @return The lower 32 bits of the 64 bit word. +* +******************************************************************************/ +#define XUINT64_LSW(x) ((x).Lower) + +#endif /* XBASIC_TYPES_H */ + +/* + * xbasic_types.h does not typedef s* or u64 + */ +/** @{ */ +typedef char char8; +typedef int8_t s8; +typedef int16_t s16; +typedef int32_t s32; +typedef int64_t s64; +typedef uint64_t u64; +typedef int sint32; + +typedef intptr_t INTPTR; +typedef uintptr_t UINTPTR; +typedef ptrdiff_t PTRDIFF; +/** @}*/ +#if !defined(LONG) || !defined(ULONG) +typedef long LONG; +typedef unsigned long ULONG; +#endif + +#define ULONG64_HI_MASK 0xFFFFFFFF00000000U +#define ULONG64_LO_MASK ~ULONG64_HI_MASK + +#else +#include +#endif + +/** @{ */ +/** + * This data type defines an interrupt handler for a device. + * The argument points to the instance of the component + */ +typedef void (*XInterruptHandler) (void *InstancePtr); + +/** + * This data type defines an exception handler for a processor. + * The argument points to the instance of the component + */ +typedef void (*XExceptionHandler) (void *InstancePtr); + +/** + * @brief Returns 32-63 bits of a number. + * @param n : Number being accessed. + * @return Bits 32-63 of number. + * + * @note A basic shift-right of a 64- or 32-bit quantity. + * Use this to suppress the "right shift count >= width of type" + * warning when that quantity is 32-bits. + */ +#define UPPER_32_BITS(n) ((u32)(((n) >> 16) >> 16)) + +/** + * @brief Returns 0-31 bits of a number + * @param n : Number being accessed. + * @return Bits 0-31 of number + */ +#define LOWER_32_BITS(n) ((u32)(n)) + + + + +/************************** Constant Definitions *****************************/ + +#ifndef TRUE +#define TRUE 1U +#endif + +#ifndef FALSE +#define FALSE 0U +#endif + +#ifndef NULL +#define NULL 0U +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** +* @} End of "addtogroup common_types". +*/ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_util.c b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_util.c new file mode 100644 index 0000000..d9282ca --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_util.c @@ -0,0 +1,175 @@ +/******************************************************************************/ +/** +* Copyright (C) 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* @file xil_util.c +* +* This file contains xil utility functions +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 6.4   mmd      04/21/19 First release.
+*
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ +#include "xil_types.h" +#include "xil_io.h" +#include "xstatus.h" + +/************************** Constant Definitions ****************************/ +#define MAX_NIBBLES 8U + +/************************** Function Prototypes *****************************/ +/****************************************************************************/ +/** + * Converts the char into the equivalent nibble. + * Ex: 'a' -> 0xa, 'A' -> 0xa, '9'->0x9 + * + * @param InChar is input character. It has to be between 0-9,a-f,A-F + * @param Num is the output nibble. + * + * @return + * - XST_SUCCESS no errors occured. + * - ERROR when input parameters are not valid + * + * @note None. + * + *****************************************************************************/ + +u32 Xil_ConvertCharToNibble(u8 InChar, u8 *Num) +{ + u32 Status; + + /* Convert the char to nibble */ + if ((InChar >= (u8)'0') && (InChar <= (u8)'9')) { + *Num = InChar - (u8)'0'; + Status = XST_SUCCESS; + } + else if ((InChar >= (u8)'a') && (InChar <= (u8)'f')) { + *Num = InChar - (u8)'a' + 10U; + Status = XST_SUCCESS; + } + else if ((InChar >= (u8)'A') && (InChar <= (u8)'F')) { + *Num = InChar - (u8)'A' + 10U; + Status = XST_SUCCESS; + } + else { + Status = XST_FAILURE; + } + + return Status; +} + +/****************************************************************************/ +/* + * Converts the string into the equivalent Hex buffer. + * Ex: "abc123" -> {0xab, 0xc1, 0x23} + * + * @param Str is a Input String. Will support the lower and upper + * case values. Value should be between 0-9, a-f and A-F + * + * @param Buf is Output buffer. + * @param Len of the input string. Should have even values + * + * @return + * - XST_SUCCESS no errors occured. + * - ERROR when input parameters are not valid + * - an error when input buffer has invalid values + * + * @note None. + * + *****************************************************************************/ +u32 Xil_ConvertStringToHex(const char *Str, u32 *buf, u8 Len) +{ + u32 Status = XST_FAILURE; + u8 ConvertedLen = 0U, index = 0U; + u8 Nibble[MAX_NIBBLES] = {0U}; + u8 i; + + while (ConvertedLen < Len) { + /* Convert char to nibble */ + for (i = 0U; i < MAX_NIBBLES; i++) { + Status = Xil_ConvertCharToNibble( + Str[ConvertedLen], &Nibble[i]); + ConvertedLen = ConvertedLen +1U; + if (Status != XST_SUCCESS) { + /* Error converting char to nibble */ + goto END; + } + } + + buf[index] = ((Nibble[0] << (u8)28U )| (Nibble[1] << (u8)24U) | + (Nibble[2] << (u8)20U) | (Nibble[3] << (u8)16U) | + (Nibble[4] << (u8)12U) | (Nibble[5] << (u8)8U)| + (Nibble[6] << (u8)4U) | (u32)Nibble[7]); + index++; + } +END: + return Status; +} + +/****************************************************************************/ +/* + * Waits for the event + * + * @param RegAddr Address of register to be checked for event(s) occurance + * @param EventMask Mask indicating event(s) to be checked + * @param Event Specific event(s) value to be checked + * @param Timeout Free counter decremented on each event(s) check and + * declared timeout when reaches 0 + * + * @return + * - XST_SUCCESS On occurance of the event(s). + * - XST_FAILURE Event did not occur before counter reaches 0 + * + * @note None. + * + *****************************************************************************/ +u32 Xil_WaitForEvent(u32 RegAddr, u32 EventMask, u32 Event, u32 Timeout) +{ + u32 RegVal; + u32 PollCount = Timeout; + u32 Status = XST_FAILURE; + + while(PollCount > 0) { + RegVal = Xil_In32(RegAddr) & EventMask; + if (RegVal == Event) { + Status = XST_SUCCESS; + break; + } + PollCount--; + } + + return Status; +} diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_util.h b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_util.h new file mode 100644 index 0000000..194c425 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xil_util.h @@ -0,0 +1,57 @@ +/******************************************************************************/ +/** +* Copyright (C) 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* @file xil_util.h +* +* This file contains xil utility functions declaration +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 6.4   mmd      04/21/19 First release.
+*
+* 
+* +*****************************************************************************/ + +#ifndef XIL_UTIL_H_ +#define XIL_UTIL_H_ + +/* Converts input character to nibble */ +u32 Xil_ConvertCharToNibble(u8 InChar, u8 *Num); + +/* Conver input hex string to array of 32-bits integers */ +u32 Xil_ConvertStringToHex(const char *Str, u32 *buf, u8 Len); + +/* Waits for specified event */ +u32 Xil_WaitForEvent(u32 RegAddr, u32 EventMask, u32 Event, u32 Timeout); + +#endif /* XIL_UTIL_H_ */ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xplatform_info.c b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xplatform_info.c new file mode 100644 index 0000000..03b1742 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xplatform_info.c @@ -0,0 +1,162 @@ +/****************************************************************************** +* +* Copyright (C) 2014 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xplatform_info.c +* +* This file contains information about hardware for which the code is built +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date   Changes
+* ----- ---- -------- -------------------------------------------------------
+* 5.00  pkp  12/15/14 Initial release
+* 5.04  pkp  01/12/16 Added platform information support for Cortex-A53 32bit
+*					  mode
+* 6.00  mus  17/08/16 Removed unused variable from XGetPlatform_Info
+* 6.4   ms   05/23/17 Added PSU_PMU macro to support XGetPSVersion_Info
+*                     function for PMUFW.
+*       ms   06/13/17 Added PSU_PMU macro to provide support of
+*                     XGetPlatform_Info function for PMUFW.
+*       mus  08/17/17 Add EL1 NS mode support for
+*                     XGet_Zynq_UltraMp_Platform_info and XGetPSVersion_Info
+*                     APIs.
+* 7.0	aru 03/15/19  Check for versal before aarch64 and armr5
+*		      in XGetPlatform_Info()
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_io.h" +#include "xplatform_info.h" +#if defined (__aarch64__) +#include "bspconfig.h" +#include "xil_smc.h" +#endif +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Variable Definitions *****************************/ + + +/************************** Function Prototypes ******************************/ + +/*****************************************************************************/ +/** +* +* @brief This API is used to provide information about platform +* +* @param None. +* +* @return The information about platform defined in xplatform_info.h +* +******************************************************************************/ +u32 XGetPlatform_Info() +{ +#if defined (versal) + return XPLAT_versal; +#elif defined (ARMR5) || (__aarch64__) || (ARMA53_32) || (PSU_PMU) + return XPLAT_ZYNQ_ULTRA_MP; +#elif (__microblaze__) + return XPLAT_MICROBLAZE; +#else + return XPLAT_ZYNQ; +#endif +} + +/*****************************************************************************/ +/** +* +* @brief This API is used to provide information about zynq ultrascale MP platform +* +* @param None. +* +* @return The information about zynq ultrascale MP platform defined in +* xplatform_info.h +* +******************************************************************************/ +#if defined (ARMR5) || (__aarch64__) || (ARMA53_32) +u32 XGet_Zynq_UltraMp_Platform_info() +{ +#if EL1_NONSECURE + XSmc_OutVar reg; + /* + * This SMC call will return, + * idcode - upper 32 bits of reg.Arg0 + * version - lower 32 bits of reg.Arg1 + */ + reg = Xil_Smc(GET_CHIPID_SMC_FID,0,0, 0, 0, 0, 0, 0); + return (u32)((reg.Arg1 >> XPLAT_INFO_SHIFT) & XPLAT_INFO_MASK); +#else + u32 reg; + reg = ((Xil_In32(XPLAT_PS_VERSION_ADDRESS) >> XPLAT_INFO_SHIFT ) + & XPLAT_INFO_MASK); + return reg; +#endif +} +#endif + +/*****************************************************************************/ +/** +* +* @brief This API is used to provide information about PS Silicon version +* +* @param None. +* +* @return The information about PS Silicon version. +* +******************************************************************************/ +#if defined (ARMR5) || (__aarch64__) || (ARMA53_32) || (PSU_PMU) +u32 XGetPSVersion_Info() +{ +#if EL1_NONSECURE + /* + * This SMC call will return, + * idcode - upper 32 bits of reg.Arg0 + * version - lower 32 bits of reg.Arg1 + */ + XSmc_OutVar reg; + reg = Xil_Smc(GET_CHIPID_SMC_FID,0,0, 0, 0, 0, 0, 0); + return (u32)((reg.Arg1 & XPS_VERSION_INFO_MASK) >> + XPS_VERSION_INFO_SHIFT); +#else + u32 reg; + reg = (Xil_In32(XPLAT_PS_VERSION_ADDRESS) + & XPS_VERSION_INFO_MASK); + return (reg >> XPS_VERSION_INFO_SHIFT); +#endif +} +#endif diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xplatform_info.h b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xplatform_info.h new file mode 100644 index 0000000..88851bb --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xplatform_info.h @@ -0,0 +1,120 @@ +/****************************************************************************** +* +* Copyright (C) 2014 - 2017 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xplatform_info.h +* +* @addtogroup common_platform_info APIs to Get Platform Information +* +* The xplatform_info.h file contains definitions for various available Xilinx® +* platforms. Also, it contains prototype of APIs, which can be used to get the +* platform information. +* +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date    Changes
+* ----- ---- --------- -------------------------------------------------------
+* 6.4    ms   05/23/17 Added PSU_PMU macro to support XGetPSVersion_Info
+*                      function for PMUFW.
+* 
+* +******************************************************************************/ + +#ifndef XPLATFORM_INFO_H /* prevent circular inclusions */ +#define XPLATFORM_INFO_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" + +/************************** Constant Definitions *****************************/ +#if defined (versal) +#define XPAR_PMC_TAP_BASEADDR 0xF11A0000U +#define XPAR_PMC_TAP_VERSION_OFFSET 0x00000004U +#define XPLAT_PS_VERSION_ADDRESS (XPAR_PMC_TAP_BASEADDR + \ + XPAR_PMC_TAP_VERSION_OFFSET) +#else +#define XPAR_CSU_BASEADDR 0xFFCA0000U +#define XPAR_CSU_VER_OFFSET 0x00000044U +#define XPLAT_PS_VERSION_ADDRESS (XPAR_CSU_BASEADDR + \ + XPAR_CSU_VER_OFFSET) +#endif +#define XPLAT_ZYNQ_ULTRA_MP_SILICON 0x0 +#define XPLAT_ZYNQ_ULTRA_MP 0x1 +#define XPLAT_ZYNQ_ULTRA_MPVEL 0x2 +#define XPLAT_ZYNQ_ULTRA_MPQEMU 0x3 +#define XPLAT_ZYNQ 0x4 +#define XPLAT_MICROBLAZE 0x5 +#define XPLAT_versal 0x6U + +#define XPS_VERSION_1 0x0 +#define XPS_VERSION_2 0x1 +#define XPLAT_INFO_MASK (0xF) + +#if defined (versal) +#define XPS_VERSION_INFO_MASK 0xFF00U +#define XPS_VERSION_INFO_SHIFT 0x8U +#define XPLAT_INFO_SHIFT 0x18U +#else +#define XPS_VERSION_INFO_MASK (0xF) +#define XPS_VERSION_INFO_SHIFT 0x0U +#define XPLAT_INFO_SHIFT 0xCU +#endif + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + + +u32 XGetPlatform_Info(void); + +#if defined (ARMR5) || (__aarch64__) || (ARMA53_32) || (PSU_PMU) +u32 XGetPSVersion_Info(); +#endif + +#if defined (ARMR5) || (__aarch64__) || (ARMA53_32) +u32 XGet_Zynq_UltraMp_Platform_info(); +#endif +/************************** Function Prototypes ******************************/ + + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** +* @} End of "addtogroup common_platform_info". +*/ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xstatus.h b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xstatus.h new file mode 100644 index 0000000..1a212bf --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/standalone_v7_0/src/xstatus.h @@ -0,0 +1,533 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xstatus.h +* +* @addtogroup common_status_codes Xilinx® software status codes +* +* The xstatus.h file contains the Xilinx® software status codes.These codes are +* used throughout the Xilinx device drivers. +* +* @{ +******************************************************************************/ + +#ifndef XSTATUS_H /* prevent circular inclusions */ +#define XSTATUS_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" + +/************************** Constant Definitions *****************************/ + +/*********************** Common statuses 0 - 500 *****************************/ +/** +@name Common Status Codes for All Device Drivers +@{ +*/ +#define XST_SUCCESS 0L +#define XST_FAILURE 1L +#define XST_DEVICE_NOT_FOUND 2L +#define XST_DEVICE_BLOCK_NOT_FOUND 3L +#define XST_INVALID_VERSION 4L +#define XST_DEVICE_IS_STARTED 5L +#define XST_DEVICE_IS_STOPPED 6L +#define XST_FIFO_ERROR 7L /*!< An error occurred during an + operation with a FIFO such as + an underrun or overrun, this + error requires the device to + be reset */ +#define XST_RESET_ERROR 8L /*!< An error occurred which requires + the device to be reset */ +#define XST_DMA_ERROR 9L /*!< A DMA error occurred, this error + typically requires the device + using the DMA to be reset */ +#define XST_NOT_POLLED 10L /*!< The device is not configured for + polled mode operation */ +#define XST_FIFO_NO_ROOM 11L /*!< A FIFO did not have room to put + the specified data into */ +#define XST_BUFFER_TOO_SMALL 12L /*!< The buffer is not large enough + to hold the expected data */ +#define XST_NO_DATA 13L /*!< There was no data available */ +#define XST_REGISTER_ERROR 14L /*!< A register did not contain the + expected value */ +#define XST_INVALID_PARAM 15L /*!< An invalid parameter was passed + into the function */ +#define XST_NOT_SGDMA 16L /*!< The device is not configured for + scatter-gather DMA operation */ +#define XST_LOOPBACK_ERROR 17L /*!< A loopback test failed */ +#define XST_NO_CALLBACK 18L /*!< A callback has not yet been + registered */ +#define XST_NO_FEATURE 19L /*!< Device is not configured with + the requested feature */ +#define XST_NOT_INTERRUPT 20L /*!< Device is not configured for + interrupt mode operation */ +#define XST_DEVICE_BUSY 21L /*!< Device is busy */ +#define XST_ERROR_COUNT_MAX 22L /*!< The error counters of a device + have maxed out */ +#define XST_IS_STARTED 23L /*!< Used when part of device is + already started i.e. + sub channel */ +#define XST_IS_STOPPED 24L /*!< Used when part of device is + already stopped i.e. + sub channel */ +#define XST_DATA_LOST 26L /*!< Driver defined error */ +#define XST_RECV_ERROR 27L /*!< Generic receive error */ +#define XST_SEND_ERROR 28L /*!< Generic transmit error */ +#define XST_NOT_ENABLED 29L /*!< A requested service is not + available because it has not + been enabled */ +#define XST_NO_ACCESS 30L /* Generic access error */ +/** @} */ +/***************** Utility Component statuses 401 - 500 *********************/ +/** +@name Utility Component Status Codes 401 - 500 +@{ +*/ +#define XST_MEMTEST_FAILED 401L /*!< Memory test failed */ + +/** @} */ +/***************** Common Components statuses 501 - 1000 *********************/ +/** +@name Packet Fifo Status Codes 501 - 510 +@{ +*/ +/********************* Packet Fifo statuses 501 - 510 ************************/ + +#define XST_PFIFO_LACK_OF_DATA 501L /*!< Not enough data in FIFO */ +#define XST_PFIFO_NO_ROOM 502L /*!< Not enough room in FIFO */ +#define XST_PFIFO_BAD_REG_VALUE 503L /*!< Self test, a register value + was invalid after reset */ +#define XST_PFIFO_ERROR 504L /*!< Generic packet FIFO error */ +#define XST_PFIFO_DEADLOCK 505L /*!< Packet FIFO is reporting + * empty and full simultaneously + */ +/** @} */ +/** +@name DMA Status Codes 511 - 530 +@{ +*/ +/************************** DMA statuses 511 - 530 ***************************/ + +#define XST_DMA_TRANSFER_ERROR 511L /*!< Self test, DMA transfer + failed */ +#define XST_DMA_RESET_REGISTER_ERROR 512L /*!< Self test, a register value + was invalid after reset */ +#define XST_DMA_SG_LIST_EMPTY 513L /*!< Scatter gather list contains + no buffer descriptors ready + to be processed */ +#define XST_DMA_SG_IS_STARTED 514L /*!< Scatter gather not stopped */ +#define XST_DMA_SG_IS_STOPPED 515L /*!< Scatter gather not running */ +#define XST_DMA_SG_LIST_FULL 517L /*!< All the buffer desciptors of + the scatter gather list are + being used */ +#define XST_DMA_SG_BD_LOCKED 518L /*!< The scatter gather buffer + descriptor which is to be + copied over in the scatter + list is locked */ +#define XST_DMA_SG_NOTHING_TO_COMMIT 519L /*!< No buffer descriptors have been + put into the scatter gather + list to be commited */ +#define XST_DMA_SG_COUNT_EXCEEDED 521L /*!< The packet count threshold + specified was larger than the + total # of buffer descriptors + in the scatter gather list */ +#define XST_DMA_SG_LIST_EXISTS 522L /*!< The scatter gather list has + already been created */ +#define XST_DMA_SG_NO_LIST 523L /*!< No scatter gather list has + been created */ +#define XST_DMA_SG_BD_NOT_COMMITTED 524L /*!< The buffer descriptor which was + being started was not committed + to the list */ +#define XST_DMA_SG_NO_DATA 525L /*!< The buffer descriptor to start + has already been used by the + hardware so it can't be reused + */ +#define XST_DMA_SG_LIST_ERROR 526L /*!< General purpose list access + error */ +#define XST_DMA_BD_ERROR 527L /*!< General buffer descriptor + error */ +/** @} */ +/** +@name IPIF Status Codes Codes 531 - 550 +@{ +*/ +/************************** IPIF statuses 531 - 550 ***************************/ + +#define XST_IPIF_REG_WIDTH_ERROR 531L /*!< An invalid register width + was passed into the function */ +#define XST_IPIF_RESET_REGISTER_ERROR 532L /*!< The value of a register at + reset was not valid */ +#define XST_IPIF_DEVICE_STATUS_ERROR 533L /*!< A write to the device interrupt + status register did not read + back correctly */ +#define XST_IPIF_DEVICE_ACK_ERROR 534L /*!< The device interrupt status + register did not reset when + acked */ +#define XST_IPIF_DEVICE_ENABLE_ERROR 535L /*!< The device interrupt enable + register was not updated when + other registers changed */ +#define XST_IPIF_IP_STATUS_ERROR 536L /*!< A write to the IP interrupt + status register did not read + back correctly */ +#define XST_IPIF_IP_ACK_ERROR 537L /*!< The IP interrupt status register + did not reset when acked */ +#define XST_IPIF_IP_ENABLE_ERROR 538L /*!< IP interrupt enable register was + not updated correctly when other + registers changed */ +#define XST_IPIF_DEVICE_PENDING_ERROR 539L /*!< The device interrupt pending + register did not indicate the + expected value */ +#define XST_IPIF_DEVICE_ID_ERROR 540L /*!< The device interrupt ID register + did not indicate the expected + value */ +#define XST_IPIF_ERROR 541L /*!< Generic ipif error */ +/** @} */ + +/****************** Device specific statuses 1001 - 4095 *********************/ +/** +@name Ethernet Status Codes 1001 - 1050 +@{ +*/ +/********************* Ethernet statuses 1001 - 1050 *************************/ + +#define XST_EMAC_MEMORY_SIZE_ERROR 1001L /*!< Memory space is not big enough + * to hold the minimum number of + * buffers or descriptors */ +#define XST_EMAC_MEMORY_ALLOC_ERROR 1002L /*!< Memory allocation failed */ +#define XST_EMAC_MII_READ_ERROR 1003L /*!< MII read error */ +#define XST_EMAC_MII_BUSY 1004L /*!< An MII operation is in progress */ +#define XST_EMAC_OUT_OF_BUFFERS 1005L /*!< Driver is out of buffers */ +#define XST_EMAC_PARSE_ERROR 1006L /*!< Invalid driver init string */ +#define XST_EMAC_COLLISION_ERROR 1007L /*!< Excess deferral or late + * collision on polled send */ +/** @} */ +/** +@name UART Status Codes 1051 - 1075 +@{ +*/ +/*********************** UART statuses 1051 - 1075 ***************************/ +#define XST_UART + +#define XST_UART_INIT_ERROR 1051L +#define XST_UART_START_ERROR 1052L +#define XST_UART_CONFIG_ERROR 1053L +#define XST_UART_TEST_FAIL 1054L +#define XST_UART_BAUD_ERROR 1055L +#define XST_UART_BAUD_RANGE 1056L + +/** @} */ +/** +@name IIC Status Codes 1076 - 1100 +@{ +*/ +/************************ IIC statuses 1076 - 1100 ***************************/ + +#define XST_IIC_SELFTEST_FAILED 1076 /*!< self test failed */ +#define XST_IIC_BUS_BUSY 1077 /*!< bus found busy */ +#define XST_IIC_GENERAL_CALL_ADDRESS 1078 /*!< mastersend attempted with */ + /* general call address */ +#define XST_IIC_STAND_REG_RESET_ERROR 1079 /*!< A non parameterizable reg */ + /* value after reset not valid */ +#define XST_IIC_TX_FIFO_REG_RESET_ERROR 1080 /*!< Tx fifo included in design */ + /* value after reset not valid */ +#define XST_IIC_RX_FIFO_REG_RESET_ERROR 1081 /*!< Rx fifo included in design */ + /* value after reset not valid */ +#define XST_IIC_TBA_REG_RESET_ERROR 1082 /*!< 10 bit addr incl in design */ + /* value after reset not valid */ +#define XST_IIC_CR_READBACK_ERROR 1083 /*!< Read of the control register */ + /* didn't return value written */ +#define XST_IIC_DTR_READBACK_ERROR 1084 /*!< Read of the data Tx reg */ + /* didn't return value written */ +#define XST_IIC_DRR_READBACK_ERROR 1085 /*!< Read of the data Receive reg */ + /* didn't return value written */ +#define XST_IIC_ADR_READBACK_ERROR 1086 /*!< Read of the data Tx reg */ + /* didn't return value written */ +#define XST_IIC_TBA_READBACK_ERROR 1087 /*!< Read of the 10 bit addr reg */ + /* didn't return written value */ +#define XST_IIC_NOT_SLAVE 1088 /*!< The device isn't a slave */ +#define XST_IIC_ARB_LOST 1089 /*!< Arbitration lost for master */ +/** @} */ +/** +@name ATMC Status Codes 1101 - 1125 +@{ +*/ +/*********************** ATMC statuses 1101 - 1125 ***************************/ + +#define XST_ATMC_ERROR_COUNT_MAX 1101L /*!< the error counters in the ATM + controller hit the max value + which requires the statistics + to be cleared */ +/** @} */ +/** +@name Flash Status Codes 1126 - 1150 +@{ +*/ +/*********************** Flash statuses 1126 - 1150 **************************/ + +#define XST_FLASH_BUSY 1126L /*!< Flash is erasing or programming + */ +#define XST_FLASH_READY 1127L /*!< Flash is ready for commands */ +#define XST_FLASH_ERROR 1128L /*!< Flash had detected an internal + error. Use XFlash_DeviceControl + to retrieve device specific codes + */ +#define XST_FLASH_ERASE_SUSPENDED 1129L /*!< Flash is in suspended erase state + */ +#define XST_FLASH_WRITE_SUSPENDED 1130L /*!< Flash is in suspended write state + */ +#define XST_FLASH_PART_NOT_SUPPORTED 1131L /*!< Flash type not supported by + driver */ +#define XST_FLASH_NOT_SUPPORTED 1132L /*!< Operation not supported */ +#define XST_FLASH_TOO_MANY_REGIONS 1133L /*!< Too many erase regions */ +#define XST_FLASH_TIMEOUT_ERROR 1134L /*!< Programming or erase operation + aborted due to a timeout */ +#define XST_FLASH_ADDRESS_ERROR 1135L /*!< Accessed flash outside its + addressible range */ +#define XST_FLASH_ALIGNMENT_ERROR 1136L /*!< Write alignment error */ +#define XST_FLASH_BLOCKING_CALL_ERROR 1137L /*!< Couldn't return immediately from + write/erase function with + XFL_NON_BLOCKING_WRITE/ERASE + option cleared */ +#define XST_FLASH_CFI_QUERY_ERROR 1138L /*!< Failed to query the device */ +/** @} */ +/** +@name SPI Status Codes 1151 - 1175 +@{ +*/ +/*********************** SPI statuses 1151 - 1175 ****************************/ + +#define XST_SPI_MODE_FAULT 1151 /*!< master was selected as slave */ +#define XST_SPI_TRANSFER_DONE 1152 /*!< data transfer is complete */ +#define XST_SPI_TRANSMIT_UNDERRUN 1153 /*!< slave underruns transmit register */ +#define XST_SPI_RECEIVE_OVERRUN 1154 /*!< device overruns receive register */ +#define XST_SPI_NO_SLAVE 1155 /*!< no slave has been selected yet */ +#define XST_SPI_TOO_MANY_SLAVES 1156 /*!< more than one slave is being + * selected */ +#define XST_SPI_NOT_MASTER 1157 /*!< operation is valid only as master */ +#define XST_SPI_SLAVE_ONLY 1158 /*!< device is configured as slave-only + */ +#define XST_SPI_SLAVE_MODE_FAULT 1159 /*!< slave was selected while disabled */ +#define XST_SPI_SLAVE_MODE 1160 /*!< device has been addressed as slave */ +#define XST_SPI_RECEIVE_NOT_EMPTY 1161 /*!< device received data in slave mode */ + +#define XST_SPI_COMMAND_ERROR 1162 /*!< unrecognised command - qspi only */ +#define XST_SPI_POLL_DONE 1163 /*!< controller completed polling the + device for status */ +/** @} */ +/** +@name OPB Arbiter Status Codes 1176 - 1200 +@{ +*/ +/********************** OPB Arbiter statuses 1176 - 1200 *********************/ + +#define XST_OPBARB_INVALID_PRIORITY 1176 /*!< the priority registers have either + * one master assigned to two or more + * priorities, or one master not + * assigned to any priority + */ +#define XST_OPBARB_NOT_SUSPENDED 1177 /*!< an attempt was made to modify the + * priority levels without first + * suspending the use of priority + * levels + */ +#define XST_OPBARB_PARK_NOT_ENABLED 1178 /*!< bus parking by id was enabled but + * bus parking was not enabled + */ +#define XST_OPBARB_NOT_FIXED_PRIORITY 1179 /*!< the arbiter must be in fixed + * priority mode to allow the + * priorities to be changed + */ +/** @} */ +/** +@name INTC Status Codes 1201 - 1225 +@{ +*/ +/************************ Intc statuses 1201 - 1225 **************************/ + +#define XST_INTC_FAIL_SELFTEST 1201 /*!< self test failed */ +#define XST_INTC_CONNECT_ERROR 1202 /*!< interrupt already in use */ +/** @} */ +/** +@name TmrCtr Status Codes 1226 - 1250 +@{ +*/ +/********************** TmrCtr statuses 1226 - 1250 **************************/ + +#define XST_TMRCTR_TIMER_FAILED 1226 /*!< self test failed */ +/** @} */ +/** +@name WdtTb Status Codes 1251 - 1275 +@{ +*/ +/********************** WdtTb statuses 1251 - 1275 ***************************/ + +#define XST_WDTTB_TIMER_FAILED 1251L +/** @} */ +/** +@name PlbArb status Codes 1276 - 1300 +@{ +*/ +/********************** PlbArb statuses 1276 - 1300 **************************/ + +#define XST_PLBARB_FAIL_SELFTEST 1276L +/** @} */ +/** +@name Plb2Opb Status Codes 1301 - 1325 +@{ +*/ +/********************** Plb2Opb statuses 1301 - 1325 *************************/ + +#define XST_PLB2OPB_FAIL_SELFTEST 1301L +/** @} */ +/** +@name Opb2Plb Status 1326 - 1350 +@{ +*/ +/********************** Opb2Plb statuses 1326 - 1350 *************************/ + +#define XST_OPB2PLB_FAIL_SELFTEST 1326L +/** @} */ +/** +@name SysAce Status Codes 1351 - 1360 +@{ +*/ +/********************** SysAce statuses 1351 - 1360 **************************/ + +#define XST_SYSACE_NO_LOCK 1351L /*!< No MPU lock has been granted */ +/** @} */ +/** +@name PCI Bridge Status Codes 1361 - 1375 +@{ +*/ +/********************** PCI Bridge statuses 1361 - 1375 **********************/ + +#define XST_PCI_INVALID_ADDRESS 1361L +/** @} */ +/** +@name FlexRay Constants 1400 - 1409 +@{ +*/ +/********************** FlexRay constants 1400 - 1409 *************************/ + +#define XST_FR_TX_ERROR 1400 +#define XST_FR_TX_BUSY 1401 +#define XST_FR_BUF_LOCKED 1402 +#define XST_FR_NO_BUF 1403 +/** @} */ +/** +@name USB constants 1410 - 1420 +@{ +*/ +/****************** USB constants 1410 - 1420 *******************************/ + +#define XST_USB_ALREADY_CONFIGURED 1410 +#define XST_USB_BUF_ALIGN_ERROR 1411 +#define XST_USB_NO_DESC_AVAILABLE 1412 +#define XST_USB_BUF_TOO_BIG 1413 +#define XST_USB_NO_BUF 1414 +/** @} */ +/** +@name HWICAP constants 1421 - 1429 +@{ +*/ +/****************** HWICAP constants 1421 - 1429 *****************************/ + +#define XST_HWICAP_WRITE_DONE 1421 + +/** @} */ +/** +@name AXI VDMA constants 1430 - 1440 +@{ +*/ +/****************** AXI VDMA constants 1430 - 1440 *****************************/ + +#define XST_VDMA_MISMATCH_ERROR 1430 +/** @} */ +/** +@name NAND Flash Status Codes 1441 - 1459 +@{ +*/ +/*********************** NAND Flash statuses 1441 - 1459 *********************/ + +#define XST_NAND_BUSY 1441L /*!< Flash is erasing or + * programming + */ +#define XST_NAND_READY 1442L /*!< Flash is ready for commands + */ +#define XST_NAND_ERROR 1443L /*!< Flash had detected an + * internal error. + */ +#define XST_NAND_PART_NOT_SUPPORTED 1444L /*!< Flash type not supported by + * driver + */ +#define XST_NAND_OPT_NOT_SUPPORTED 1445L /*!< Operation not supported + */ +#define XST_NAND_TIMEOUT_ERROR 1446L /*!< Programming or erase + * operation aborted due to a + * timeout + */ +#define XST_NAND_ADDRESS_ERROR 1447L /*!< Accessed flash outside its + * addressible range + */ +#define XST_NAND_ALIGNMENT_ERROR 1448L /*!< Write alignment error + */ +#define XST_NAND_PARAM_PAGE_ERROR 1449L /*!< Failed to read parameter + * page of the device + */ +#define XST_NAND_CACHE_ERROR 1450L /*!< Flash page buffer error + */ + +#define XST_NAND_WRITE_PROTECTED 1451L /*!< Flash is write protected + */ +/** @} */ + +/**************************** Type Definitions *******************************/ + +typedef s32 XStatus; + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** +* @} End of "addtogroup common_status_codes". +*/ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/sysmon_v7_5/src/Makefile b/datalink814_sp/bsp/microblaze_ps/libsrc/sysmon_v7_5/src/Makefile new file mode 100644 index 0000000..1e3e53d --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/sysmon_v7_5/src/Makefile @@ -0,0 +1,27 @@ +COMPILER= +ARCHIVER= +CP=cp +COMPILER_FLAGS= +EXTRA_COMPILER_FLAGS= +LIB=libxil.a + +RELEASEDIR=../../../lib +INCLUDEDIR=../../../include +INCLUDES=-I./. -I${INCLUDEDIR} + +INCLUDEFILES=*.h +LIBSOURCES=*.c +OUTS = *.o +OBJECTS = $(addsuffix .o, $(basename $(wildcard *.c))) + +libs: + echo "Compiling sysmon" + $(COMPILER) $(COMPILER_FLAGS) $(EXTRA_COMPILER_FLAGS) $(INCLUDES) $(LIBSOURCES) + $(ARCHIVER) -r ${RELEASEDIR}/${LIB} $(OBJECTS) + make clean + +include: + ${CP} ${INCLUDEFILES} ${INCLUDEDIR} + +clean: + rm -rf ${OBJECTS} diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/sysmon_v7_5/src/xsysmon.c b/datalink814_sp/bsp/microblaze_ps/libsrc/sysmon_v7_5/src/xsysmon.c new file mode 100644 index 0000000..aae4ae9 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/sysmon_v7_5/src/xsysmon.c @@ -0,0 +1,1915 @@ +/****************************************************************************** +* +* Copyright (C) 2007 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xsysmon.c +* @addtogroup sysmon_v7_5 +* @{ +* +* This file contains the driver API functions that can be used to access +* the System Monitor/ADC device. +* +* Refer to the xsysmon.h header file for more information about this driver. +* +* @note None. +* +*
+*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- -----  -------- -----------------------------------------------------
+* 1.00a xd/sv  05/22/07 First release
+* 2.00a sv     07/07/08 Modified the ADC data functions to return 16 bits of
+*						data.
+* 3.00a sdm    09/02/09 Added APIs for V6 SysMon.
+* 4.00a ktn    10/22/09 Updated the file to use the HAL processor APIs/macros.
+*			The macros have been renamed to remove _m from the name
+*			of the macro.
+* 5.00a sdm    06/15/11 Added support for XADC (7 Series Families).
+* 5.01a bss    02/28/12 Added support for Zynq.
+* 5.02a bss    11/23/12 Added XSysMon_EnableTempUpdate,
+*			XSysMon_DisableTempUpdate and XSysMon_SetTempWaitCycles
+*			APIs (CR #679872)
+* 5.03a bss    04/25/13 Modified XSysMon_SetSeqChEnables,
+*			XSysMon_SetSeqAvgEnables, XSysMon_SetSeqInputMode
+*			and XSysMon_SetSeqAcqTime APIs to check for Safe Mode
+*			instead of Single Channel mode. CR #703729
+* 7.0	bss    7/25/14  Modified XSysMon_GetAdcData,
+*			XSysMon_GetMinMaxMeasurement,
+*			XSysMon_SetSingleChParams, XSysMon_SetAlarmEnables,
+*			XSysMon_GetAlarmEnables,XSysMon_SetSeqChEnables,
+*			XSysMon_GetSeqChEnables,XSysMon_SetSeqAvgEnables,
+*			XSysMon_GetSeqAvgEnables,XSysMon_SetAlarmThreshold
+*			and XSysMon_GetAlarmThreshold to support Ultrascale
+* 7.2   sk   11/10/15 Used UINTPTR instead of u32 for Baseaddress CR# 867425.
+*                     Changed the prototype of XSysMon_CfgInitialize API.
+* 7.2   asa Made changes to use XSM_CFR3_OFFSET (configuration register 3)
+*           only for Ultrascale. Changes were made in APIs XSysMon_SetAlarmEnables
+*           and XSysMon_GetAlarmEnables. This is to fix CR#910905.
+* 7.5	mn    07/06/18  Fixed Doxygen warnings
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ + +#include "xsysmon.h" + +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Function Prototypes *****************************/ + +/************************** Variable Definitions ****************************/ + +/*****************************************************************************/ +/** +* +* This function initializes a specific XSysMon device/instance. This function +* must be called prior to using the System Monitor/ADC device. +* +* @param InstancePtr is a pointer to the XSysMon instance. +* @param ConfigPtr points to the XSysMon device configuration structure. +* @param EffectiveAddr is the device base address in the virtual memory +* address space. If the address translation is not used then the +* physical address is passed. +* Unexpected errors may occur if the address mapping is changed +* after this function is invoked. +* +* @return +* - XST_SUCCESS if successful. +* +* @note The user needs to first call the XSysMon_LookupConfig() API +* which returns the Configuration structure pointer which is +* passed as a parameter to the XSysMon_CfgInitialize() API. +* +******************************************************************************/ +int XSysMon_CfgInitialize(XSysMon *InstancePtr, XSysMon_Config *ConfigPtr, + UINTPTR EffectiveAddr) +{ + /* + * Assert the input arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(ConfigPtr != NULL); + + /* + * Set the values read from the device config and the base address. + */ + InstancePtr->Config.DeviceId = ConfigPtr->DeviceId; + InstancePtr->Config.BaseAddress = EffectiveAddr; + InstancePtr->Config.IncludeInterrupt = ConfigPtr->IncludeInterrupt; + + /* Store the default Waitcycles value in Mask */ + InstancePtr->Mask = XSM_CONVST_WAITCYCLES_DEFAULT << + XSM_CONVST_WAITCYCLES_SHIFT; + + /* + * Indicate the instance is now ready to use, initialized without error + */ + InstancePtr->IsReady = XIL_COMPONENT_IS_READY; + + /* + * Reset the device such that it is in a known state. + */ + XSysMon_Reset(InstancePtr); + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function forces the software reset of the complete SystemMonitor/ADC +* Hard Macro and the SYSMON ADC Core Logic. +* +* +* @param InstancePtr is a pointer to the XSysMon instance. +* +* @return None. +* +* @note The Control registers in the SystemMonitor/ADC Hard Macro +* are not affected by this reset, only the Status registers +* are reset. +* Refer to the device data sheet for the device status and +* register values after the reset. +* Use the XSysMon_ResetAdc() to reset only the SystemMonitor/ADC +* Hard Macro. +* +******************************************************************************/ +void XSysMon_Reset(XSysMon *InstancePtr) +{ + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Write the reset value to the Software Reset Register (SRR) to + * Reset the device. + */ + XSysMon_WriteReg(InstancePtr->Config.BaseAddress, XSM_SRR_OFFSET, + XSM_SRR_IPRST_MASK); +} + +/****************************************************************************/ +/** +* +* The functions reads the contents of the Status Register. +* +* @param InstancePtr is a pointer to the XSysMon instance. +* +* @return A 32-bit value representing the contents of the Status Register. +* Use the XSM_SR_*_MASK constants defined in xsysmon_hw.h to +* interpret the returned value. +* +* @note None. +* +*****************************************************************************/ +u32 XSysMon_GetStatus(XSysMon *InstancePtr) +{ + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the Status Register and return the value. + */ + return XSysMon_ReadReg(InstancePtr->Config.BaseAddress, XSM_SR_OFFSET); +} + +/****************************************************************************/ +/** +* +* This function reads the contents of Alarm Output Register. +* +* @param InstancePtr is a pointer to the XSysMon instance. +* +* @return A 32-bit value read from the Alarm Output Register. +* Use the XSM_AOR_*_MASK constants defined in xsysmon_hw.h to +* interpret the value. +* +* @note None. +* +*****************************************************************************/ +u32 XSysMon_GetAlarmOutputStatus(XSysMon *InstancePtr) +{ + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the Alarm Output Register and return the value. + */ + return (XSysMon_ReadReg(InstancePtr->Config.BaseAddress, + XSM_AOR_OFFSET) & XSM_AOR_ALARM_ALL_MASK); +} + +/****************************************************************************/ +/** +* +* This function starts the ADC conversion in the Single Channel event driven +* sampling mode. The EOC bit in Status Register will be set once the conversion +* is finished. Refer to the device specification for more details. +* +* @param InstancePtr is a pointer to the XSysMon instance. +* +* @return None. +* +* @note The default state of the CONVST bit is a logic 0. The conversion +* is started when the CONVST bit is set to 1 from 0. +* This bit is cleared in this function so that the next conversion +* can be started by setting this bit. +* +*****************************************************************************/ +void XSysMon_StartAdcConversion(XSysMon *InstancePtr) +{ + u32 RegVal; + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* Modify only CONVST bit using the InstancePtr->Mask, which + stores previously written value in CONVST register */ + + RegVal = (InstancePtr->Mask) | XSM_CONVST_CONVST_MASK; + + /* + * Start the conversion by setting the CONVST bit to 1 and to 0. + */ + XSysMon_WriteReg(InstancePtr->Config.BaseAddress, + XSM_CONVST_OFFSET, RegVal); + + RegVal = (InstancePtr->Mask) & ~(XSM_CONVST_CONVST_MASK); + + XSysMon_WriteReg(InstancePtr->Config.BaseAddress, + XSM_CONVST_OFFSET, RegVal); +} + +/*****************************************************************************/ +/** +* +* This function resets the SystemMonitor/ADC Hard Macro in the device. +* +* @param InstancePtr is a pointer to the XSysMon instance. +* +* @return None. +* +* @note The Control registers in the SystemMonitor/ADC Hard Macro +* are not affected by this reset, only the Status registers +* are reset. +* This reset causes the ADC to begin with a new conversion. +* Refer to the device data sheet for the device status and +* register values after the reset. +* Use the XSysMon_Reset() API to reset both the SystemMonitor/ADC +* Hard Macro and the SYSMON ADC Core Logic. +* +******************************************************************************/ +void XSysMon_ResetAdc(XSysMon *InstancePtr) +{ + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Set the reset bit to the ADC Reset Register (ARR) to + * put the SystemMonitor/ADC Hard Macro in Reset. + */ + XSysMon_WriteReg(InstancePtr->Config.BaseAddress, XSM_ARR_OFFSET, + XSM_ARR_RST_MASK); + /* + * Clear the reset bit to the ADC Reset Register (ARR) to + * release the reset of SystemMonitor/ADC Hard Macro. + */ + XSysMon_WriteReg(InstancePtr->Config.BaseAddress, XSM_ARR_OFFSET, 0x0); +} + +/****************************************************************************/ +/** +* +* Get the ADC converted data for the specified channel. +* +* @param InstancePtr is a pointer to the XSysMon instance. +* @param Channel is the channel number. Use the XSM_CH_* defined in +* the file xsysmon.h. +* The valid channels are 0 to 5 and 16 to 31 for all the device +* families. Channel 6 is valid for 7 Series and Zynq. +* Channel 13, 14, 15 are valid for Zynq. 32 to 35 are valid for +* Ultrascale. +* +* @return A 16-bit value representing the ADC converted data for the +* specified channel. The System Monitor/ADC device guarantees +* a 10 bit resolution for the ADC converted data and data is the +* 10 MSB bits of the 16 data read from the device. +* +* @note The channels 7,8,9 are used for calibration of the device and +* hence there is no associated data with this channel. +* Please make sure that the proper channel number is passed. +* +*****************************************************************************/ +u16 XSysMon_GetAdcData(XSysMon *InstancePtr, u8 Channel) +{ + u16 AdcData; + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid((Channel <= XSM_CH_VBRAM) || + ((Channel >= XSM_CH_VCCPINT) && + (Channel <= XSM_CH_AUX_MAX)) || + ((Channel >= XSM_CH_VUSR0) && + (Channel <= XSM_CH_VUSR3))); + + /* + * Read the selected ADC converted data for the specified channel + * and return the value. + */ + if (Channel <= XSM_CH_AUX_MAX) { + AdcData = (u16) (XSysMon_ReadReg(InstancePtr-> + Config.BaseAddress, XSM_TEMP_OFFSET + + (Channel << 2))); + } else { + AdcData = (u16) (XSysMon_ReadReg(InstancePtr-> + Config.BaseAddress, XSM_VUSR0_OFFSET + + ((Channel - XSM_CH_VUSR0) << 2))); + } + + return AdcData; +} + +/****************************************************************************/ +/** +* +* This function gets the calibration coefficient data for the specified +* parameter. +* +* @param InstancePtr is a pointer to the XSysMon instance. +* @param CoeffType specifies the calibration coefficient +* to be read. Use XSM_CALIB_* constants defined in xsysmon.h to +* specify the calibration coefficient to be read. +* +* @return A 16-bit value representing the calibration coefficient. +* The System Monitor/ADC device guarantees a 10 bit resolution for +* the ADC converted data and data is the 10 MSB bits of the 16 +* data read from the device. +* +* @note None. +* +*****************************************************************************/ +u16 XSysMon_GetCalibCoefficient(XSysMon *InstancePtr, u8 CoeffType) +{ + u16 CalibData; + + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(CoeffType <= XSM_CALIB_GAIN_ERROR_COEFF); + + /* + * Read the selected calibration coefficient. + */ + CalibData = (u16) XSysMon_ReadReg(InstancePtr->Config.BaseAddress, + XSM_SUPPLY_CALIB_OFFSET + (CoeffType << 2)); + + return CalibData; +} + +/****************************************************************************/ +/** +* +* This function reads the Minimum/Maximum measurement for one of the +* following parameters : +* - Minimum Temperature (XSM_MIN_TEMP) - All families +* - Minimum VCCINT (XSM_MIN_VCCINT) - All families +* - Minimum VCCAUX (XSM_MIN_VCCAUX) - All families +* - Maximum Temperature (XSM_MAX_TEMP) - All families +* - Maximum VCCINT (XSM_MAX_VCCINT) - All families +* - Maximum VCCAUX (XSM_MAX_VCCAUX) - All families +* - Maximum VCCBRAM (XSM_MAX_VCCBRAM) - 7 series and Zynq only +* - Minimum VCCBRAM (XSM_MIN_VCCBRAM) - 7 series and Zynq only +* - Maximum VCCPINT (XSM_MAX_VCCPINT) - Zynq only +* - Maximum VCCPAUX (XSM_MAX_VCCPAUX) - Zynq only +* - Maximum VCCPDRO (XSM_MAX_VCCPDRO) - Zynq only +* - Minimum VCCPINT (XSM_MIN_VCCPINT) - Zynq only +* - Minimum VCCPAUX (XSM_MIN_VCCPAUX) - Zynq only +* - Minimum VCCPDRO (XSM_MIN_VCCPDRO) - Zynq only +* - Maximum VUSER0 (XSM_MAX_VUSR0) - Ultrascale +* - Maximum VUSER1 (XSM_MAX_VUSR1) - Ultrascale +* - Maximum VUSER2 (XSM_MAX_VUSR2) - Ultrascale +* - Maximum VUSER3 (XSM_MAX_VUSR3) - Ultrascale +* - Minimum VUSER0 (XSM_MIN_VUSR0) - Ultrascale +* - Minimum VUSER1 (XSM_MIN_VUSR1) - Ultrascale +* - Minimum VUSER2 (XSM_MIN_VUSR2) - Ultrascale +* - Minimum VUSER3 (XSM_MIN_VUSR3) - Ultrascale +* +* @param InstancePtr is a pointer to the XSysMon instance. +* @param MeasurementType specifies the parameter for which the +* Minimum/Maximum measurement has to be read. +* Use XSM_MAX_* and XSM_MIN_* constants defined in xsysmon.h to +* specify the data to be read. +* +* @return A 16-bit value representing the maximum/minimum measurement for +* specified parameter. +* The System Monitor/ADC device guarantees a 10 bit resolution for +* the ADC converted data and data is the 10 MSB bits of 16 bit +* data read from the device. +* +*****************************************************************************/ +u16 XSysMon_GetMinMaxMeasurement(XSysMon *InstancePtr, u8 MeasurementType) +{ + u16 MinMaxData; + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid((MeasurementType <= XSM_MAX_VCCPDRO) || + ((MeasurementType >= XSM_MIN_VCCPINT) && + (MeasurementType <= XSM_MIN_VCCPDRO)) || + ((MeasurementType >= XSM_MAX_VUSR0) && + (MeasurementType <= XSM_MAX_VUSR3)) || + ((MeasurementType >= XSM_MIN_VUSR0) && + (MeasurementType <= XSM_MIN_VUSR3))) + + + /* + * Read and return the specified Minimum/Maximum measurement. + */ + MinMaxData = (u16) (XSysMon_ReadReg(InstancePtr->Config.BaseAddress, + XSM_MAX_TEMP_OFFSET + (MeasurementType << 2))); + return MinMaxData; +} + +/****************************************************************************/ +/** +* +* This function sets the number of samples of averaging that is to be done for +* all the channels in both the single channel mode and sequence mode of +* operations. +* +* @param InstancePtr is a pointer to the XSysMon instance. +* @param Average is the number of samples of averaging programmed to the +* Configuration Register 0. Use the XSM_AVG_* definitions defined +* in xsysmon.h file : +* - XSM_AVG_0_SAMPLES for no averaging +* - XSM_AVG_16_SAMPLES for 16 samples of averaging +* - XSM_AVG_64_SAMPLES for 64 samples of averaging +* - XSM_AVG_256_SAMPLES for 256 samples of averaging +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XSysMon_SetAvg(XSysMon *InstancePtr, u8 Average) +{ + u32 RegValue; + + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Average <= XSM_AVG_256_SAMPLES); + + /* + * Write the averaging value into the Configuration Register 0. + */ + RegValue = XSysMon_ReadReg(InstancePtr->Config.BaseAddress, + XSM_CFR0_OFFSET) & + (~XSM_CFR0_AVG_VALID_MASK); + RegValue |= (((u32) Average << XSM_CFR0_AVG_SHIFT)); + XSysMon_WriteReg(InstancePtr->Config.BaseAddress, XSM_CFR0_OFFSET, + RegValue); +} + +/****************************************************************************/ +/** +* +* This function returns the number of samples of averaging configured for all +* the channels in the Configuration Register 0. +* +* @param InstancePtr is a pointer to the XSysMon instance. +* +* @return The averaging read from the Configuration Register 0 is +* returned. Use the XSM_AVG_* bit definitions defined in xsysmon.h +* file to interpret the returned value : +* - XSM_AVG_0_SAMPLES means no averaging +* - XSM_AVG_16_SAMPLES means 16 samples of averaging +* - XSM_AVG_64_SAMPLES means 64 samples of averaging +* - XSM_AVG_256_SAMPLES means 256 samples of averaging +* +* @note None. +* +*****************************************************************************/ +u8 XSysMon_GetAvg(XSysMon *InstancePtr) +{ + u32 Average; + + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the averaging value from the Configuration Register 0. + */ + Average = XSysMon_ReadReg(InstancePtr->Config.BaseAddress, + XSM_CFR0_OFFSET) & XSM_CFR0_AVG_VALID_MASK; + + return ((u8) (Average >> XSM_CFR0_AVG_SHIFT)); +} + +/****************************************************************************/ +/** +* +* The function sets the given parameters in the Configuration Register 0 in +* the single channel mode. +* +* @param InstancePtr is a pointer to the XSysMon instance. +* @param Channel is the channel number for conversion. The valid +* channels are 0 to 5, 8, and 16 to 31. Channel 6 is +* valid for 7 series and Zynq XADC. Channel 32 to 35 are valid +* for Ultrascale. +* @param IncreaseAcqCycles is a boolean parameter which specifies whether +* the Acquisition time for the external channels has to be +* increased to 10 ADCCLK cycles (specify TRUE) or remain at the +* default 4 ADCCLK cycles (specify FALSE). This parameter is +* only valid for the external channels. +* @param IsEventMode is a boolean parameter that specifies continuous +* sampling (specify FALSE) or event driven sampling mode (specify +* TRUE) for the given channel. +* @param IsDifferentialMode is a boolean parameter which specifies +* unipolar(specify FALSE) or differential mode (specify TRUE) for +* the analog inputs. The input mode is only valid for the +* external channels. +* @return +* - XST_SUCCESS if the given values were written successfully to +* the Configuration Register 0. +* - XST_FAILURE if the channel sequencer is enabled or the input +* parameters are not valid for the selected channel. +* +* @note +* - The number of samples for the averaging for all the channels +* is set by using the function XSysMon_SetAvg. +* - The calibration of the device is done by doing a ADC +* conversion on the calibration channel(channel 8). The input +* parameters IncreaseAcqCycles, IsDifferentialMode and +* IsEventMode are not valid for this channel. +* +*****************************************************************************/ +int XSysMon_SetSingleChParams(XSysMon *InstancePtr, u8 Channel, + int IncreaseAcqCycles, int IsEventMode, + int IsDifferentialMode) +{ + u32 RegValue; + + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid((Channel <= XSM_CH_VREFN) || + (Channel == XSM_CH_CALIBRATION) || + ((Channel >= XSM_CH_AUX_MIN) && + (Channel <= XSM_CH_AUX_MAX)) || + ((Channel >= XSM_CH_VUSR0) && + (Channel <= XSM_CH_VUSR3))); + Xil_AssertNonvoid((IncreaseAcqCycles == TRUE) || + (IncreaseAcqCycles == FALSE)); + Xil_AssertNonvoid((IsEventMode == TRUE) || (IsEventMode == FALSE)); + Xil_AssertNonvoid((IsDifferentialMode == TRUE) || + (IsDifferentialMode == FALSE)); + + /* + * Check if the device is in single channel mode else return failure + */ + if ((XSysMon_GetSequencerMode(InstancePtr) != XSM_SEQ_MODE_SINGCHAN)) { + return XST_FAILURE; + } + + /* + * Read the Configuration Register 0. + */ + RegValue = XSysMon_ReadReg(InstancePtr->Config.BaseAddress, + XSM_CFR0_OFFSET) & XSM_CFR0_AVG_VALID_MASK; + + /* + * Select the number of acquisition cycles. The acquisition cycles is + * only valid for the external channels. + */ + if (IncreaseAcqCycles == TRUE) { + if (((Channel >= XSM_CH_AUX_MIN) && (Channel <= XSM_CH_AUX_MAX)) + || (Channel == XSM_CH_VPVN)) { + RegValue |= XSM_CFR0_ACQ_MASK; + } else { + return XST_FAILURE; + } + } + + /* + * Select the input mode. The input mode is only valid for the + * external channels. + */ + if (IsDifferentialMode == TRUE) { + + if (((Channel >= XSM_CH_AUX_MIN) && (Channel <= XSM_CH_AUX_MAX)) + || (Channel == XSM_CH_VPVN)) { + RegValue |= XSM_CFR0_DU_MASK; + } else { + return XST_FAILURE; + } + } + + /* + * Select the ADC mode. + */ + if (IsEventMode == TRUE) { + RegValue |= XSM_CFR0_EC_MASK; + } + + /* + * Write the given values into the Configuration Register 0. + */ + RegValue |= (Channel & XSM_CFR0_CHANNEL_MASK); + XSysMon_WriteReg(InstancePtr->Config.BaseAddress, XSM_CFR0_OFFSET, + RegValue); + + return XST_SUCCESS; +} + +/****************************************************************************/ +/** +* +* This function enables the alarm outputs for the specified alarms in the +* Configuration Registers 1 and 3: +* +* - OT for Over Temperature (XSM_CFR_OT_MASK) +* - ALM0 for On board Temperature (XSM_CFR_ALM_TEMP_MASK) +* - ALM1 for VCCINT (XSM_CFR_ALM_VCCINT_MASK) +* - ALM2 for VCCAUX (XSM_CFR_ALM_VCCAUX_MASK) +* - ALM3 for VBRAM (XSM_CFR_ALM_VBRAM_MASK)for 7 Series and Zynq +* - ALM4 for VCCPINT (XSM_CFR_ALM_VCCPINT_MASK) for Zynq +* - ALM5 for VCCPAUX (XSM_CFR_ALM_VCCPAUX_MASK) for Zynq +* - ALM6 for VCCPDRO (XSM_CFR_ALM_VCCPDRO_MASK) for Zynq +* - ALM8 for VUSER0 (XSM_CFR_ALM_VUSR0_MASK) for Ultrascale +* - ALM9 for VUSER1 (XSM_CFR_ALM_VUSR1_MASK) for Ultrascale +* - ALM10 for VUSER2 (XSM_CFR_ALM_VUSR2_MASK) for Ultrascale +* - ALM11 for VUSER3 (XSM_CFR_ALM_VUSR3_MASK) for Ultrascale +* +* @param InstancePtr is a pointer to the XSysMon instance. +* @param AlmEnableMask is the bit-mask of the alarm outputs to be enabled +* in the Configuration Register 1. +* Bit positions of 1 will be enabled. Bit positions of 0 will be +* disabled. This mask is formed by OR'ing XSM_CFR_ALM_*_MASK, +* XSM_CFR_ALM_*_MASK and XSM_CFR_OT_MASK masks defined in +* xsysmon_hw.h. +* +* @return None. +* +* @note The implementation of the alarm enables in the Configuration +* register 1 is such that the alarms for bit positions of 1 will +* be disabled and alarms for bit positions of 0 will be enabled. +* The alarm outputs specified by the AlmEnableMask are negated +* before writing to the Configuration Register 1. +* +*****************************************************************************/ +void XSysMon_SetAlarmEnables(XSysMon *InstancePtr, u32 AlmEnableMask) +{ + u32 RegValue; + + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(AlmEnableMask <= XSM_CFR_ALM_ALL_MASK); + + RegValue = XSysMon_ReadReg(InstancePtr->Config.BaseAddress, + XSM_CFR1_OFFSET); + RegValue &= (u32)~XSM_CFR1_ALM_ALL_MASK; + RegValue |= (~AlmEnableMask & XSM_CFR1_ALM_ALL_MASK); + + /* + * Enable/disables the alarm enables for the specified alarm bits in the + * Configuration Register 1. + */ + XSysMon_WriteReg(InstancePtr->Config.BaseAddress, XSM_CFR1_OFFSET, + RegValue); + +#if XPAR_SYSMON_0_IP_TYPE == SYSTEM_MANAGEMENT + /* + * Enable/disables the alarm enables for the specified alarm bits in the + * Configuration Register 3. + */ + RegValue = XSysMon_ReadReg(InstancePtr->Config.BaseAddress, + XSM_CFR3_OFFSET); + RegValue &= (u32)~XSM_CFR3_ALM_ALL_MASK; + RegValue |= (~(AlmEnableMask >> 16) & XSM_CFR3_ALM_ALL_MASK); + + XSysMon_WriteReg(InstancePtr->Config.BaseAddress, XSM_CFR3_OFFSET, + RegValue); +#endif +} + +/****************************************************************************/ +/** +* +* This function gets the status of the alarm output enables in the +* Configuration Register 1. +* +* @param InstancePtr is a pointer to the XSysMon instance. +* +* @return This is the bit-mask of the enabled alarm outputs in the +* Configuration Register 1. Use the masks XSM_CFR_ALM_*, +* XSM_CFR_ALM*_* and XSM_CFR_OT_MASK defined in +* xsysmon_hw.h to interpret the returned value. +* +* Bit positions of 1 indicate that the alarm output is enabled. +* Bit positions of 0 indicate that the alarm output is disabled. +* +* +* @note The implementation of the alarm enables in the Configuration +* register 1 is such that alarms for the bit positions of 1 will +* be disabled and alarms for bit positions of 0 will be enabled. +* The enabled alarm outputs returned by this function is the +* negated value of the the data read from the Configuration +* Register 1. +* +*****************************************************************************/ +u32 XSysMon_GetAlarmEnables(XSysMon *InstancePtr) +{ + u32 RegValue1; +#if XPAR_SYSMON_0_IP_TYPE == SYSTEM_MANAGEMENT + u32 RegValue2; +#endif + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the status of alarm output enables from the Configuration + * Register 1. + */ + RegValue1 = XSysMon_ReadReg(InstancePtr->Config.BaseAddress, + XSM_CFR1_OFFSET) & XSM_CFR1_ALM_ALL_MASK; + RegValue1 = (~RegValue1 & XSM_CFR1_ALM_ALL_MASK); + +#if XPAR_SYSMON_0_IP_TYPE == SYSTEM_MANAGEMENT + /* + * Read the status of alarm output enables from the Configuration + * Register 3. + */ + RegValue2 = XSysMon_ReadReg(InstancePtr->Config.BaseAddress, + XSM_CFR3_OFFSET) & XSM_CFR3_ALM_ALL_MASK; + RegValue2 = (~RegValue2 & XSM_CFR3_ALM_ALL_MASK); + + return ((RegValue2 << 16) | RegValue1); +#else + return RegValue1; +#endif +} + +/****************************************************************************/ +/** +* +* This function enables the specified calibration in the Configuration +* Register 1 : +* +* - XSM_CFR1_CAL_ADC_OFFSET_MASK : Calibration 0 -ADC offset correction +* - XSM_CFR1_CAL_ADC_GAIN_OFFSET_MASK : Calibration 1 -ADC gain and offset +* correction +* - XSM_CFR1_CAL_PS_OFFSET_MASK : Calibration 2 -Power Supply sensor +* offset correction +* - XSM_CFR1_CAL_PS_GAIN_OFFSET_MASK : Calibration 3 -Power Supply sensor +* gain and offset correction +* - XSM_CFR1_CAL_DISABLE_MASK : No Calibration +* +* @param InstancePtr is a pointer to the XSysMon instance. +* @param Calibration is the Calibration to be applied. +* Use XSM_CFR1_CAL*_* bits defined in xsysmon_hw.h. +* Multiple calibrations can be enabled at a time by oring the +* XSM_CFR1_CAL_ADC_* and XSM_CFR1_CAL_PS_* bits. +* Calibration can be disabled by specifying +* XSM_CFR1_CAL_DISABLE_MASK; +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XSysMon_SetCalibEnables(XSysMon *InstancePtr, u16 Calibration) +{ + u32 RegValue; + + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(((Calibration >= XSM_CFR1_CAL_ADC_OFFSET_MASK) && + (Calibration <= XSM_CFR1_CAL_VALID_MASK)) || + (Calibration == XSM_CFR1_CAL_DISABLE_MASK)); + + /* + * Set the specified calibration in the Configuration Register 1. + */ + RegValue = XSysMon_ReadReg(InstancePtr->Config.BaseAddress, + XSM_CFR1_OFFSET); + + RegValue &= (~ XSM_CFR1_CAL_VALID_MASK); + RegValue |= (Calibration & XSM_CFR1_CAL_VALID_MASK); + XSysMon_WriteReg(InstancePtr->Config.BaseAddress, XSM_CFR1_OFFSET, + RegValue); +} + +/****************************************************************************/ +/** +* +* This function reads the value of the calibration enables from the +* Configuration Register 1. +* +* @param InstancePtr is a pointer to the XSysMon instance. +* +* @return The value of the calibration enables in the Configuration +* Register 1 : +* - XSM_CFR1_CAL_ADC_OFFSET_MASK : ADC offset correction +* - XSM_CFR1_CAL_ADC_GAIN_OFFSET_MASK : ADC gain and offset +* correction +* - XSM_CFR1_CAL_PS_OFFSET_MASK : Power Supply sensor offset +* correction +* - XSM_CFR1_CAL_PS_GAIN_OFFSET_MASK : Power Supply sensor gain +* and offset correction +* - XSM_CFR1_CAL_DISABLE_MASK : No Calibration +* +* @note None. +* +*****************************************************************************/ +u16 XSysMon_GetCalibEnables(XSysMon *InstancePtr) +{ + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the calibration enables from the Configuration Register 1. + */ + return (u16) XSysMon_ReadReg(InstancePtr->Config.BaseAddress, + XSM_CFR1_OFFSET) & XSM_CFR1_CAL_VALID_MASK; +} + +/****************************************************************************/ +/** +* +* This function sets the specified Channel Sequencer Mode in the Configuration +* Register 1 : +* - Default safe mode (XSM_SEQ_MODE_SAFE) +* - One pass through sequence (XSM_SEQ_MODE_ONEPASS) +* - Continuous channel sequencing (XSM_SEQ_MODE_CONTINPASS) +* - Single Channel/Sequencer off (XSM_SEQ_MODE_SINGCHAN) +* - Simulataneous sampling mode (XSM_SEQ_MODE_SIMUL) +* - Independent mode (XSM_SEQ_MODE_INDEPENDENT) +* +* @param InstancePtr is a pointer to the XSysMon instance. +* @param SequencerMode is the sequencer mode to be set. +* Use XSM_SEQ_MODE_* bits defined in xsysmon.h. +* +* @return None. +* +* @note Only one of the modes can be enabled at a time. +* +*****************************************************************************/ +void XSysMon_SetSequencerMode(XSysMon *InstancePtr, u8 SequencerMode) +{ + u32 RegValue; + + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid((SequencerMode <= XSM_SEQ_MODE_SIMUL) || + (SequencerMode == XSM_SEQ_MODE_INDEPENDENT)); + + /* + * Set the specified sequencer mode in the Configuration Register 1. + */ + RegValue = XSysMon_ReadReg(InstancePtr->Config.BaseAddress, + XSM_CFR1_OFFSET); + RegValue &= (~ XSM_CFR1_SEQ_VALID_MASK); + RegValue |= ((SequencerMode << XSM_CFR1_SEQ_SHIFT) & + XSM_CFR1_SEQ_VALID_MASK); + XSysMon_WriteReg(InstancePtr->Config.BaseAddress, XSM_CFR1_OFFSET, + RegValue); +} + +/****************************************************************************/ +/** +* +* This function gets the channel sequencer mode from the Configuration +* Register 1. +* +* @param InstancePtr is a pointer to the XSysMon instance. +* +* @return The channel sequencer mode : +* - XSM_SEQ_MODE_SAFE : Default safe mode +* - XSM_SEQ_MODE_ONEPASS : One pass through sequence +* - XSM_SEQ_MODE_CONTINPASS : Continuous channel sequencing +* - XSM_SEQ_MODE_SINGCHAN : Single channel/Sequencer off +* - XSM_SEQ_MODE_SIMUL : Simulataneous sampling mode +* - XSM_SEQ_MODE_INDEPENDENT : Independent mode +* +* @note None. +* +*****************************************************************************/ +u8 XSysMon_GetSequencerMode(XSysMon *InstancePtr) +{ + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the channel sequencer mode from the Configuration Register 1. + */ + return ((u8) ((XSysMon_ReadReg(InstancePtr->Config.BaseAddress, + XSM_CFR1_OFFSET) & XSM_CFR1_SEQ_VALID_MASK) >> + XSM_CFR1_SEQ_SHIFT)); +} + +/****************************************************************************/ +/** +* +* The function enables the Event mode or Continuous mode in the sequencer mode. +* +* @param InstancePtr is a pointer to the XSysMon instance. +* @param IsEventMode is a boolean parameter that specifies continuous +* sampling (specify FALSE) or event driven sampling mode (specify +* TRUE) for the given channel. +* +* @return None. +* +* @note The Event mode is only available in 7 Series XADC and Zynq. +* This API should be used only with 7 Series XADC and Zynq . +* +*****************************************************************************/ +void XSysMon_SetSequencerEvent(XSysMon *InstancePtr, int IsEventMode) +{ + u32 RegValue; + + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid((IsEventMode == TRUE) || (IsEventMode == FALSE)); + + /* + * Read the Configuration Register 0. + */ + RegValue = XSysMon_ReadReg(InstancePtr->Config.BaseAddress, + XSM_CFR0_OFFSET); + + /* + * Set the ADC mode. + */ + if (IsEventMode == TRUE) { + RegValue |= XSM_CFR0_EC_MASK; + } else { + RegValue &= ~XSM_CFR0_EC_MASK; + } + + XSysMon_WriteReg(InstancePtr->Config.BaseAddress, XSM_CFR0_OFFSET, + RegValue); +} + +/****************************************************************************/ +/** +* +* The function enables the external mux and connects a channel to the mux. +* +* @param InstancePtr is a pointer to the XSysMon instance. +* @param Channel is the channel number used to connect to the external +* Mux. The valid channels are 0 to 6, 8, and 16 to 31. +* +* @return +* - XST_SUCCESS if the given values were written successfully to +* the Configuration Register 0. +* - XST_FAILURE if the channel sequencer is enabled or the input +* parameters are not valid for the selected channel. +* +* @note The External Mux is only available in 7 Series and Zynq XADC. +* This API should be used only with 7 Series and Zynq XADC. +* +*****************************************************************************/ +void XSysMon_SetExtenalMux(XSysMon *InstancePtr, u8 Channel) +{ + u32 RegValue; + + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid((Channel <= XSM_CH_VREFN) || + (Channel == XSM_CH_CALIBRATION) || + ((Channel >= XSM_CH_AUX_MIN) && + (Channel <= XSM_CH_AUX_MAX))); + + /* + * Read the Configuration Register 0 and the clear the channel selection + * bits. + */ + RegValue = XSysMon_ReadReg(InstancePtr->Config.BaseAddress, + XSM_CFR0_OFFSET); + RegValue &= ~(XSM_CFR0_CHANNEL_MASK); + + /* + * Enable the External Mux and select the channel. + */ + RegValue |= (XSM_CFR0_MUX_MASK | Channel); + XSysMon_WriteReg(InstancePtr->Config.BaseAddress, XSM_CFR0_OFFSET, + RegValue); +} + +/****************************************************************************/ +/** +* +* The function sets the frequency of the ADCCLK by configuring the DCLK to +* ADCCLK ratio in the Configuration Register #2. +* +* @param InstancePtr is a pointer to the XSysMon instance. +* @param Divisor is clock divisor used to derive ADCCLK from DCLK. +* Valid values of the divisor are +* - 8 to 255 for V5 SysMon. +* - 0 to 255 for V6/7 Series and Zynq XADC. +* Values 0, 1, 2 are all mapped to 2. +* Refer to the device specification for more details. +* +* @return None. +* +* @note - The ADCCLK is an internal clock used by the ADC and is +* synchronized to the DCLK clock. The ADCCLK is equal to DCLK +* divided by the user selection in the Configuration Register 2. +* - There is no Assert on the minimum value of the Divisor. Users +* must take care such that the minimum value of Divisor used is +* 8, in case of V5 SysMon. +* +*****************************************************************************/ +void XSysMon_SetAdcClkDivisor(XSysMon *InstancePtr, u8 Divisor) +{ + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Write the divisor value into the Configuration Register #2. + */ + XSysMon_WriteReg(InstancePtr->Config.BaseAddress, XSM_CFR2_OFFSET, + Divisor << XSM_CFR2_CD_SHIFT); + +} + +/****************************************************************************/ +/** +* +* The function gets the ADCCLK divisor from the Configuration Register 2. +* +* @param InstancePtr is a pointer to the XSysMon instance. +* +* @return The divisor read from the Configuration Register 2. +* +* @note The ADCCLK is an internal clock used by the ADC and is +* synchronized to the DCLK clock. The ADCCLK is equal to DCLK +* divided by the user selection in the Configuration Register 2. +* +*****************************************************************************/ +u8 XSysMon_GetAdcClkDivisor(XSysMon *InstancePtr) +{ + u16 Divisor; + + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the divisor value from the Configuration Register 2. + */ + Divisor = (u16) XSysMon_ReadReg(InstancePtr->Config.BaseAddress, + XSM_CFR2_OFFSET); + + return (u8) (Divisor >> XSM_CFR2_CD_SHIFT); +} + +/****************************************************************************/ +/** +* +* This function enables the specified channels in the ADC Channel Selection +* Sequencer Registers. The sequencer must be in the Safe Mode before writing +* to these registers. +* +* @param InstancePtr is a pointer to the XSysMon instance. +* @param ChEnableMask is the bit mask of all the channels to be enabled. +* Use XSM_SEQ_CH_* defined in xsysmon_hw.h to specify the Channel +* numbers. Bit masks of 1 will be enabled and bit mask of 0 will +* be disabled. +* The ChEnableMask is a 64 bit mask that is written to the three +* 16 bit ADC Channel Selection Sequencer Registers. +* +* @return +* - XST_SUCCESS if the given values were written successfully to +* the ADC Channel Selection Sequencer Registers. +* - XST_FAILURE if the channel sequencer is enabled. +* +* @note None. +* +*****************************************************************************/ +int XSysMon_SetSeqChEnables(XSysMon *InstancePtr, u64 ChEnableMask) +{ + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * The sequencer must be in the Safe Mode before writing + * to these registers. Return XST_FAILURE if the channel sequencer + * is enabled. + */ + if ((XSysMon_GetSequencerMode(InstancePtr) != XSM_SEQ_MODE_SAFE)) { + return XST_FAILURE; + } + + /* + * Enable the specified channels in the ADC Channel Selection Sequencer + * Registers. + */ + XSysMon_WriteReg(InstancePtr->Config.BaseAddress, + XSM_SEQ00_OFFSET, + (ChEnableMask & XSM_SEQ00_CH_VALID_MASK)); + + XSysMon_WriteReg(InstancePtr->Config.BaseAddress, + XSM_SEQ01_OFFSET, + (ChEnableMask >> XSM_SEQ_CH_AUX_SHIFT) & + XSM_SEQ01_CH_VALID_MASK); + + XSysMon_WriteReg(InstancePtr->Config.BaseAddress, + XSM_SEQ08_OFFSET, + (ChEnableMask >> XSM_SEQ_CH_VUSR_SHIFT) & + XSM_SEQ08_CH_VALID_MASK); + + return XST_SUCCESS; +} + +/****************************************************************************/ +/** +* +* This function gets the channel enable bits status from the ADC Channel +* Selection Sequencer Registers. +* +* @param InstancePtr is a pointer to the XSysMon instance. +* +* @return Gets the channel enable bits. Use XSM_SEQ_CH_* defined in +* xsysmon_hw.h to interpret the Channel numbers. Bit masks of 1 +* are the channels that are enabled and bit mask of 0 are +* the channels that are disabled. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +u64 XSysMon_GetSeqChEnables(XSysMon *InstancePtr) +{ + u32 RegValEnable; + u32 RegValEnable1; + u64 RetVal = 0x0; + + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the channel enable bits for all the channels from the ADC + * Channel Selection Register. + */ + RegValEnable = XSysMon_ReadReg(InstancePtr->Config.BaseAddress, + XSM_SEQ00_OFFSET) & XSM_SEQ00_CH_VALID_MASK; + RegValEnable |= (XSysMon_ReadReg(InstancePtr->Config.BaseAddress, + XSM_SEQ01_OFFSET) & XSM_SEQ01_CH_VALID_MASK) << + XSM_SEQ_CH_AUX_SHIFT; + + RegValEnable1 = XSysMon_ReadReg(InstancePtr->Config.BaseAddress, + XSM_SEQ08_OFFSET) & XSM_SEQ08_CH_VALID_MASK; + + RetVal = RegValEnable1; + RetVal = (RetVal << XSM_SEQ_CH_VUSR_SHIFT); + RetVal = RetVal | RegValEnable; + + return RetVal; +} + +/****************************************************************************/ +/** +* +* This function enables the averaging for the specified channels in the ADC +* Channel Averaging Enable Sequencer Registers. The sequencer must be in +* the Safe Mode before writing to these registers. +* +* @param InstancePtr is a pointer to the XSysMon instance. +* @param AvgEnableChMask is the bit mask of all the channels for which +* averaging is to be enabled. Use XSM_SEQ_CH__* defined in +* xsysmon_hw.h to specify the Channel numbers. Averaging will be +* enabled for bit masks of 1 and disabled for bit mask of 0. +* The AvgEnableChMask is a 64 bit mask that is written to the +* three 16 bit ADC Channel Averaging Enable Sequencer Registers. +* +* @return +* - XST_SUCCESS if the given values were written successfully to +* the ADC Channel Averaging Enables Sequencer Registers. +* - XST_FAILURE if the channel sequencer is enabled. +* +* @note None. +* +*****************************************************************************/ +int XSysMon_SetSeqAvgEnables(XSysMon *InstancePtr, u64 AvgEnableChMask) +{ + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * The sequencer must be disabled for writing any of these registers. + * Return XST_FAILURE if the channel sequencer is enabled. + */ + if ((XSysMon_GetSequencerMode(InstancePtr) != XSM_SEQ_MODE_SAFE)) { + return XST_FAILURE; + } + + /* + * Enable/disable the averaging for the specified channels in the + * ADC Channel Averaging Enables Sequencer Registers. + */ + XSysMon_WriteReg(InstancePtr->Config.BaseAddress, + XSM_SEQ02_OFFSET, + (AvgEnableChMask & XSM_SEQ02_CH_VALID_MASK)); + + XSysMon_WriteReg(InstancePtr->Config.BaseAddress, + XSM_SEQ03_OFFSET, + (AvgEnableChMask >> XSM_SEQ_CH_AUX_SHIFT) & + XSM_SEQ03_CH_VALID_MASK); + + XSysMon_WriteReg(InstancePtr->Config.BaseAddress, + XSM_SEQ09_OFFSET, + (AvgEnableChMask >> XSM_SEQ_CH_VUSR_SHIFT) & + XSM_SEQ09_CH_VALID_MASK); + + return XST_SUCCESS; +} + +/****************************************************************************/ +/** +* +* This function returns the channels for which the averaging has been enabled +* in the ADC Channel Averaging Enables Sequencer Registers. +* +* @param InstancePtr is a pointer to the XSysMon instance. +* +* @returns The status of averaging (enabled/disabled) for all the channels. +* Use XSM_SEQ_CH__* defined in xsysmon_hw.h to interpret the +* Channel numbers. Bit masks of 1 are the channels for which +* averaging is enabled and bit mask of 0 are the channels for +* averaging is disabled. +* +* @note None. +* +*****************************************************************************/ +u64 XSysMon_GetSeqAvgEnables(XSysMon *InstancePtr) +{ + u32 RegValAvg; + u32 RegValAvg1; + u64 RetVal = 0x0; + + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the averaging enable status for all the channels from the + * ADC Channel Averaging Enables Sequencer Registers. + */ + RegValAvg = XSysMon_ReadReg(InstancePtr->Config.BaseAddress, + XSM_SEQ02_OFFSET) & XSM_SEQ02_CH_VALID_MASK; + RegValAvg |= (XSysMon_ReadReg(InstancePtr->Config.BaseAddress, + XSM_SEQ03_OFFSET) & XSM_SEQ03_CH_VALID_MASK) << + XSM_SEQ_CH_AUX_SHIFT; + + RegValAvg1 = XSysMon_ReadReg(InstancePtr->Config.BaseAddress, + XSM_SEQ09_OFFSET) & XSM_SEQ09_CH_VALID_MASK; + + RetVal = RegValAvg1; + RetVal = (RetVal << XSM_SEQ_CH_VUSR_SHIFT); + RetVal = RetVal | RegValAvg; + + return RetVal; +} + +/****************************************************************************/ +/** +* +* This function sets the Analog input mode for the specified channels in the +* ADC Channel Analog-Input Mode Sequencer Registers. The sequencer must be in +* the Safe Mode before writing to these registers. +* +* @param InstancePtr is a pointer to the XSysMon instance. +* @param InputModeChMask is the bit mask of all the channels for which +* the input mode is differential mode. Use XSM_SEQ_CH__* defined +* in xsysmon_hw.h to specify the channel numbers. Differential +* input mode will be set for bit masks of 1 and unipolar input +* mode for bit masks of 0. +* The InputModeChMask is a 32 bit mask that is written to the two +* 16 bit ADC Channel Analog-Input Mode Sequencer Registers. +* +* @return +* - XST_SUCCESS if the given values were written successfully to +* the ADC Channel Analog-Input Mode Sequencer Registers. +* - XST_FAILURE if the channel sequencer is enabled. +* +* @note None. +* +*****************************************************************************/ +int XSysMon_SetSeqInputMode(XSysMon *InstancePtr, u32 InputModeChMask) +{ + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * The sequencer must be in the Safe Mode before writing to + * these registers. Return XST_FAILURE if the channel sequencer + * is enabled. + */ + if ((XSysMon_GetSequencerMode(InstancePtr) != XSM_SEQ_MODE_SAFE)) { + return XST_FAILURE; + } + + /* + * Set the input mode for the specified channels in the ADC Channel + * Analog-Input Mode Sequencer Registers. + */ + XSysMon_WriteReg(InstancePtr->Config.BaseAddress, + XSM_SEQ04_OFFSET, + (InputModeChMask & XSM_SEQ04_CH_VALID_MASK)); + + XSysMon_WriteReg(InstancePtr->Config.BaseAddress, + XSM_SEQ05_OFFSET, + (InputModeChMask >> XSM_SEQ_CH_AUX_SHIFT) & + XSM_SEQ05_CH_VALID_MASK); + + return XST_SUCCESS; +} + +/****************************************************************************/ +/** +* +* This function gets the Analog input mode for all the channels from +* the ADC Channel Analog-Input Mode Sequencer Registers. +* +* @param InstancePtr is a pointer to the XSysMon instance. +* +* @returns The input mode for all the channels. +* Use XSM_SEQ_CH_* defined in xsysmon_hw.h to interpret the +* Channel numbers. Bit masks of 1 are the channels for which +* input mode is differential and bit mask of 0 are the channels +* for which input mode is unipolar. +* +* @note None. +* +*****************************************************************************/ +u32 XSysMon_GetSeqInputMode(XSysMon *InstancePtr) +{ + u32 InputMode; + + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Get the input mode for all the channels from the ADC Channel + * Analog-Input Mode Sequencer Registers. + */ + InputMode = XSysMon_ReadReg(InstancePtr->Config.BaseAddress, + XSM_SEQ04_OFFSET) & XSM_SEQ04_CH_VALID_MASK; + InputMode |= (XSysMon_ReadReg(InstancePtr->Config.BaseAddress, + XSM_SEQ05_OFFSET) & XSM_SEQ05_CH_VALID_MASK) << + XSM_SEQ_CH_AUX_SHIFT; + + return InputMode; +} + +/****************************************************************************/ +/** +* +* This function sets the number of Acquisition cycles in the ADC Channel +* Acquisition Time Sequencer Registers. The sequencer must be in the Safe Mode +* before writing to these registers. +* +* @param InstancePtr is a pointer to the XSysMon instance. +* @param AcqCyclesChMask is the bit mask of all the channels for which +* the number of acquisition cycles is to be extended. +* Use XSM_SEQ_CH__* defined in xsysmon_hw.h to specify the Channel +* numbers. Acquisition cycles will be extended to 10 ADCCLK cycles +* for bit masks of 1 and will be the default 4 ADCCLK cycles for +* bit masks of 0. +* The AcqCyclesChMask is a 32 bit mask that is written to the two +* 16 bit ADC Channel Acquisition Time Sequencer Registers. +* +* @return +* - XST_SUCCESS if the given values were written successfully to +* the Channel Sequencer Registers. +* - XST_FAILURE if the channel sequencer is enabled. +* +* @note None. +* +*****************************************************************************/ +int XSysMon_SetSeqAcqTime(XSysMon *InstancePtr, u32 AcqCyclesChMask) +{ + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * The sequencer must be in the Safe Mode before writing + * to these registers. Return XST_FAILURE if the channel + * sequencer is enabled. + */ + if ((XSysMon_GetSequencerMode(InstancePtr) != XSM_SEQ_MODE_SAFE)) { + return XST_FAILURE; + } + + /* + * Set the Acquisition time for the specified channels in the + * ADC Channel Acquisition Time Sequencer Registers. + */ + XSysMon_WriteReg(InstancePtr->Config.BaseAddress, + XSM_SEQ06_OFFSET, + (AcqCyclesChMask & XSM_SEQ06_CH_VALID_MASK)); + + XSysMon_WriteReg(InstancePtr->Config.BaseAddress, + XSM_SEQ07_OFFSET, + (AcqCyclesChMask >> XSM_SEQ_CH_AUX_SHIFT) & + XSM_SEQ07_CH_VALID_MASK); + + return XST_SUCCESS; +} + +/****************************************************************************/ +/** +* +* This function gets the status of acquisition from the ADC Channel Acquisition +* Time Sequencer Registers. +* +* @param InstancePtr is a pointer to the XSysMon instance. +* +* @returns The acquisition time for all the channels. +* Use XSM_SEQ_CH__* defined in xsysmon_hw.h to interpret the +* Channel numbers. Bit masks of 1 are the channels for which +* acquisition cycles are extended and bit mask of 0 are the +* channels for which acquisition cycles are not extended. +* +* @note None. +* +*****************************************************************************/ +u32 XSysMon_GetSeqAcqTime(XSysMon *InstancePtr) +{ + u32 RegValAcq; + + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Get the Acquisition cycles for the specified channels from the ADC + * Channel Acquisition Time Sequencer Registers. + */ + RegValAcq = XSysMon_ReadReg(InstancePtr->Config.BaseAddress, + XSM_SEQ06_OFFSET) & XSM_SEQ06_CH_VALID_MASK; + RegValAcq |= (XSysMon_ReadReg(InstancePtr->Config.BaseAddress, + XSM_SEQ07_OFFSET) & XSM_SEQ07_CH_VALID_MASK) << + XSM_SEQ_CH_AUX_SHIFT; + + return RegValAcq; +} + +/****************************************************************************/ +/** +* +* This functions sets the contents of the given Alarm Threshold Register. +* +* @param InstancePtr is a pointer to the XSysMon instance. +* @param AlarmThrReg is the index of an Alarm Threshold Register to +* be set. Use XSM_ATR_* constants defined in xsysmon.h to +* specify the index. +* @param Value is the 16-bit threshold value to write into the register. +* +* @return None. +* +* @note Over Temperature upper threshold is programmable only in V6, +* 7 Series/Zynq XADC and UltraScale. +* BRAM high and low voltage threshold registers are available only +* in 7 Series XADC and UltraScale. +* VUSER0 to VUSER3 threshold registers are available only in +* UltraScale. +* All the remaining Alarm Threshold registers specified by the +* constants XSM_ATR_*, are available in all the families of the +* Sysmon. +* +*****************************************************************************/ +void XSysMon_SetAlarmThreshold(XSysMon *InstancePtr, u8 AlarmThrReg, u16 Value) +{ + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid((AlarmThrReg <= XSM_ATR_VUSR3_UPPER) || + ((AlarmThrReg >= XSM_ATR_VUSR0_LOWER) && + (AlarmThrReg <= XSM_ATR_VUSR3_LOWER))); + + /* + * Write the value into the specified Alarm Threshold Register. + */ + XSysMon_WriteReg(InstancePtr->Config.BaseAddress, + XSM_ATR_TEMP_UPPER_OFFSET + (AlarmThrReg << 2), + Value); +} + +/****************************************************************************/ +/** +* +* This function returns the contents of the specified Alarm Threshold Register. +* +* @param InstancePtr is a pointer to the XSysMon instance. +* @param AlarmThrReg is the index of an Alarm Threshold Register +* to be read. Use XSM_ATR_* constants defined in xsysmon.h +* to specify the index. +* +* @return A 16-bit value representing the contents of the selected Alarm +* Threshold Register. +* +* @note Over Temperature upper threshold is programmable only in V6 and +* 7 Series XADC +* BRAM high and low voltage threshold registers are available only +* in 7 Series and Zynq XADC. +* All the remaining Alarm Threshold registers specified by the +* constants XSM_ATR_*, are available in all the families of the +* Sysmon. +* +*****************************************************************************/ +u16 XSysMon_GetAlarmThreshold(XSysMon *InstancePtr, u8 AlarmThrReg) +{ + u16 AlarmThreshold; + + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid((AlarmThrReg <= XSM_ATR_VUSR3_UPPER) || + ((AlarmThrReg >= XSM_ATR_VUSR0_LOWER) && + (AlarmThrReg <= XSM_ATR_VUSR3_LOWER))); + + /* + * Read the specified Alarm Threshold Register and return + * the value. + */ + AlarmThreshold = (u16) XSysMon_ReadReg(InstancePtr->Config.BaseAddress, + XSM_ATR_TEMP_UPPER_OFFSET + (AlarmThrReg << 2)); + + return AlarmThreshold; +} + +/****************************************************************************/ +/** +* +* This function sets the powerdown temperature for the OverTemp signal in the +* OT Powerdown register. +* +* @param InstancePtr is a pointer to the XSysMon instance. +* @param Value is the 16-bit OT Upper Alarm Register powerdown value. +* Valid values are 0 to 0x0FFF. +* +* @return None. +* +* @note This API has been deprecated. Use XSysMon_SetAlarmThreshold(), +* instead. +* This API should be used only with V6/7 Series since the +* upper threshold of OverTemp is programmable in in only V6 +* SysMon/7 Series and Zynq XADC. +* +*****************************************************************************/ +void XSysMon_SetOverTemp(XSysMon *InstancePtr, u16 Value) +{ + u16 OtUpper; + + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Value <= XSM_ATR_OT_UPPER_VAL_MAX); + + /* + * Read the OT Upper Alarm Threshold Register. + */ + OtUpper = (u16) XSysMon_ReadReg(InstancePtr->Config.BaseAddress, + XSM_ATR_OT_UPPER_OFFSET); + OtUpper &= ~(XSM_ATR_OT_UPPER_VAL_MASK); + + /* + * Preserve the OT enable value and write the powerdown value into the + * OT Upper Alarm Threshold Register. + */ + Value = (Value << XSM_ATR_OT_UPPER_VAL_SHIFT) | OtUpper; + XSysMon_WriteReg(InstancePtr->Config.BaseAddress, + XSM_ATR_OT_UPPER_OFFSET, Value); +} + +/****************************************************************************/ +/** +* +* This function returns the powerdown temperature of the OverTemp signal in +* the OT Powerdown register. +* +* @param InstancePtr is a pointer to the XSysMon instance. +* +* @return A 12-bit OT Upper Alarm Register powerdown value. +* +* @note This API has been deprecated. Use XSysMon_GetAlarmThreshold(), +* instead. +* This API should be used only with V6/7 Series since the +* upper threshold of OverTemp is programmable in only V6 +* SysMon/7 Series and Zynq XADC. +* +*****************************************************************************/ +u16 XSysMon_GetOverTemp(XSysMon *InstancePtr) +{ + u16 OtUpper; + + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the OT upper Alarm Threshold Register and return + * the value. + */ + OtUpper = (u16) XSysMon_ReadReg(InstancePtr->Config.BaseAddress, + XSM_ATR_OT_UPPER_OFFSET); + OtUpper >>= XSM_ATR_OT_UPPER_VAL_SHIFT; + + return OtUpper; +} + +/****************************************************************************/ +/** +* +* This function enables programming of the powerdown temperature for the +* OverTemp signal in the OT Powerdown register. +* +* @param InstancePtr is a pointer to the XSysMon instance. +* +* @return None. +* +* @note This API should be used only with V6/7 Series since the +* upper threshold of OverTemp is programmable in only V6 +* SysMon/7 Series and Zynq XADC. +* +*****************************************************************************/ +void XSysMon_EnableUserOverTemp(XSysMon *InstancePtr) +{ + u16 OtUpper; + + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the OT upper Alarm Threshold Register. + */ + OtUpper = XSysMon_ReadReg(InstancePtr->Config.BaseAddress, + XSM_ATR_OT_UPPER_OFFSET); + OtUpper &= ~(XSM_ATR_OT_UPPER_ENB_MASK); + + /* + * Preserve the powerdown value and write OT enable value the into the + * OT Upper Alarm Threshold Register. + */ + OtUpper |= XSM_ATR_OT_UPPER_ENB_VAL; + XSysMon_WriteReg(InstancePtr->Config.BaseAddress, + XSM_ATR_OT_UPPER_OFFSET, OtUpper); +} + +/****************************************************************************/ +/** +* +* This function disables programming of the powerdown temperature for the +* OverTemp signal in the OT Powerdown register. +* +* @param InstancePtr is a pointer to the XSysMon instance. +* +* @return None. +* +* @note This API should be used only with V6 SysMon/7 Series and Zynq +* XADC since the upper threshold of OverTemp is programmable +* in only V6 SysMon/7 Series and Zynq XADC. +* +*****************************************************************************/ +void XSysMon_DisableUserOverTemp(XSysMon *InstancePtr) +{ + u16 OtUpper; + + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the OT Upper Alarm Threshold Register. + */ + OtUpper = XSysMon_ReadReg(InstancePtr->Config.BaseAddress, + XSM_ATR_OT_UPPER_OFFSET); + OtUpper &= ~(XSM_ATR_OT_UPPER_ENB_MASK); + + XSysMon_WriteReg(InstancePtr->Config.BaseAddress, + XSM_ATR_OT_UPPER_OFFSET, OtUpper); +} + +/****************************************************************************/ +/** +* +* This function enables the Temperature updation logic so that temperature +* can be sent over TEMP_OUT port. +* +* @param InstancePtr is a pointer to the XSysMon instance. +* +* @return None. +* +* @note None +* +*****************************************************************************/ +void XSysMon_EnableTempUpdate(XSysMon *InstancePtr) +{ + u32 RegVal; + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + + RegVal = (InstancePtr->Mask) | XSM_CONVST_TEMPUPDT_MASK ; + + XSysMon_WriteReg(InstancePtr->Config.BaseAddress, + XSM_CONVST_OFFSET, RegVal); + + /* Store the written value in Mask */ + InstancePtr->Mask = RegVal; +} + +/****************************************************************************/ +/** +* +* This function disables the Temperature updation logic for TEMP_OUT port +* +* @param InstancePtr is a pointer to the XSysMon instance. +* +* @return None. +* +* @note None +* +*****************************************************************************/ +void XSysMon_DisableTempUpdate(XSysMon *InstancePtr) +{ + u32 RegVal; + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + RegVal = (InstancePtr->Mask) & ~(XSM_CONVST_TEMPUPDT_MASK) ; + + XSysMon_WriteReg(InstancePtr->Config.BaseAddress, + XSM_CONVST_OFFSET, RegVal); + + /* Store the written value in Mask */ + InstancePtr->Mask = RegVal; +} + +/****************************************************************************/ +/** +* +* This function sets the number of Wait Cycles for Temperature updation logic +* +* @param InstancePtr is a pointer to the XSysMon instance. +* @param WaitCycles is number of wait cycles +* +* @return None. +* +* @note The default number of wait cycles are 1000(0x3E8). +* +*****************************************************************************/ +void XSysMon_SetTempWaitCycles(XSysMon *InstancePtr, u16 WaitCycles) +{ + u32 RegVal; + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + + RegVal = ((InstancePtr->Mask) & ~(XSM_CONVST_WAITCYCLES_MASK)) ; + + RegVal = (WaitCycles << XSM_CONVST_WAITCYCLES_SHIFT) | RegVal; + + XSysMon_WriteReg(InstancePtr->Config.BaseAddress, + XSM_CONVST_OFFSET, RegVal); + + /* Store the written value in Mask */ + InstancePtr->Mask = RegVal; +} +/** @} */ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/sysmon_v7_5/src/xsysmon.h b/datalink814_sp/bsp/microblaze_ps/libsrc/sysmon_v7_5/src/xsysmon.h new file mode 100644 index 0000000..c01dddc --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/sysmon_v7_5/src/xsysmon.h @@ -0,0 +1,654 @@ +/****************************************************************************** +* +* Copyright (C) 2007 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xsysmon.h +* @addtogroup sysmon_v7_5 +* @{ +* @details +* +* The XSysMon driver supports the Xilinx System Monitor/ADC device. +* +* The System Monitor/ADC device has the following features: +* - 10-bit, 200-KSPS (kilo samples per second) +* Analog-to-Digital Converter (ADC) +* - Monitoring of on-chip supply voltages and temperature +* - 1 dedicated differential analog-input pair and +* 16 auxiliary differential analog-input pairs +* - Automatic alarms based on user defined limits for the on-chip +* supply voltages and temperature +* - Automatic Channel Sequencer, programmable averaging, programmable +* acquisition time for the external inputs, unipolar or differential +* input selection for the external inputs +* - Inbuilt Calibration +* - Optional interrupt request generation +* - External Mux (7 Series and Zynq XADC) +* +* +* The user should refer to the hardware device specification for detailed +* information about the device. +* +* This header file contains the prototypes of driver functions that can +* be used to access the System Monitor/ADC device. +* +* +* System Monitor Channel Sequencer Modes +* +* The System Monitor Channel Sequencer supports the following operating modes: +* +* - Default : This is the default mode after power up. +* In this mode of operation the System Monitor operates in +* a sequence mode, monitoring the on chip sensors: +* Temperature, VCCINT, and VCCAUX. +* - One pass through sequence : In this mode the System Monitor +* converts the channels enabled in the Sequencer Channel Enable +* registers for a single pass and then stops. +* - Continuous cycling of sequence : In this mode the System Monitor +* converts the channels enabled in the Sequencer Channel Enable +* registers continuously. +* - Single channel mode: In this mode the System Monitor Channel +* Sequencer is disabled and the System Monitor operates in a +* Single Channel Mode. +* The System Monitor can operate either in a Continuous or Event +* driven sampling mode in the single channel mode. +* - Simultaneous sampling mode: This mode is available only in +* 7 Series and Zynq XADC devices. In this mode both ADCs sample and +* digitizes two different analog input signals at the same time. +* - Independent ADC mode: This mode is available only in 7 Series and +* Zynq XADC devices. In this mode ADC A is used to implement a +* fixed monitoring mode which is similar to default mode, but the +* fixed alarm functions are enabled. ADC B is available to be used +* with the external analog input channels only. +* +* Initialization and Configuration +* +* The device driver enables higher layer software (e.g., an application) to +* communicate to the System Monitor/ADC device. +* +* XSysMon_CfgInitialize() API is used to initialize the System Monitor/ADC +* device. The user needs to first call the XSysMon_LookupConfig() API which +* returns the Configuration structure pointer which is passed as a parameter to +* the XSysMon_CfgInitialize() API. +* +* +* Interrupts +* +* The System Monitor/ADC device supports interrupt driven mode and the default +* operation mode is polling mode. +* +* The interrupt mode is available only if hardware is configured to support +* interrupts. +* +* This driver does not provide a Interrupt Service Routine (ISR) for the device. +* It is the responsibility of the application to provide one if needed. Refer to +* the interrupt example provided with this driver for details on using the +* device in interrupt mode. +* +* +* Virtual Memory +* +* This driver supports Virtual Memory. The RTOS is responsible for calculating +* the correct device base address in Virtual Memory space. +* +* +* Threads +* +* This driver is not thread safe. Any needs for threads or thread mutual +* exclusion must be satisfied by the layer above this driver. +* +* +* Asserts +* +* Asserts are used within all Xilinx drivers to enforce constraints on argument +* values. Asserts can be turned off on a system-wide basis by defining, at +* compile time, the NDEBUG identifier. By default, asserts are turned on and it +* is recommended that users leave asserts on during development. +* +* +* Building the driver +* +* The XSysMon driver is composed of several source files. This allows the user +* to build and link only those parts of the driver that are necessary. +* +* Limitations of the driver +* +* System Monitor/ADC device can be accessed through the JTAG port and the AXI +* interface. The driver implementation does not support the simultaneous access +* of the device by both these interfaces. The user has to care of this situation +* in the user application code. +* +* +* +*

+* +*
+*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- -----  -------- -----------------------------------------------------
+* 1.00a xd/sv  05/22/07 First release
+* 2.00a sv     07/07/08 Added bit definitions for new Alarm Interrupts in the
+*			Interrupt Registers. Changed the ADC data functions
+*			to return 16 bits of data. Added macros for conversion
+*			from Raw Data to Temperature/Voltage and vice-versa.
+* 3.00a sdm    02/09/09 Added APIs and bit definitions for V6 SysMon.
+* 4.00a ktn    10/22/09 Updated the driver to use the HAL Processor APIs/macros.
+*		        The macros have been renamed to remove _m from the name
+*		        in all the driver files.
+* 5.00a sdm    06/15/11 Added support for XADC 7 Series.
+* 5.01a bss    02/28/12 Added support for Zynq,
+*			renamed XSM_ATR_BRAM_UPPER to XSM_ATR_VBRAM_UPPER
+*			renamed XSM_ATR_BRAM_LOWER to XSM_ATR_VBRAM_LOWER
+* 5.02a bss    11/23/12 Added APIs and Macros to support Temperature Updation
+*			over TEMP_OUT port(CR #679872)
+* 5.03a bss    04/25/13 Modified XSysMon_SetSeqChEnables,
+*			XSysMon_SetSeqAvgEnables, XSysMon_SetSeqInputMode
+*			and XSysMon_SetSeqAcqTime APIs to check for Safe Mode
+*			instead of Single Channel mode(CR #703729) in xsysmon.c
+*			Modified examples: xsysmon_polled_example.c,
+*			xsysmon_low_level_example.c,
+*			xsysmon_intr_printf_example.c, xsysmon_intr_example.c
+*			xsysmon_extmux_example.c and
+*			xsysmon_polled_printf_example.c to set Sequencer Mode
+*			as Safe mode instead of Single channel mode before
+*			configuring Sequencer registers.
+* 6.0   adk  19/12/13   Updated as per the New Tcl API's
+* 7.0   bss  7/25/14    To support Ultrascale:
+*			Added XSM_CH_VUSR0 - XSMXSM_CH_VUSR3,XSM_MAX_VUSR0 -
+*			XSM_MIN_VUSR3,XSM_ATR_VUSR0_UPPER -
+*			XSM_ATR_VUSR3_LOWER macros.
+*			Added XSM_IP_OFFSET macro(since register
+*			offsets are different for Ultrascale comapared to
+*			earlier familes),Offsets,Masks for VUSER0 to
+*			VUSER3 channels, Configuration Register 3 and
+*			Sequence Registers 8 and 9 in xsysmon_hw.h.
+*			Modified XSysMon_GetAdcData,
+*			XSysMon_GetMinMaxMeasurement,
+*			XSysMon_SetSingleChParams, XSysMon_SetAlarmEnables,
+*			XSysMon_GetAlarmEnables,XSysMon_SetSeqChEnables,
+*			XSysMon_GetSeqChEnables,XSysMon_SetSeqAvgEnables,
+*			XSysMon_GetSeqAvgEnables,XSysMon_SetAlarmThreshold
+*			and XSysMon_GetAlarmThreshold in xsysmon.c.
+*			Modified driver tcl to generate XPAR_SYSMON_0_IP_TYPE
+*			parameter.
+* 7.1	bss  05/06/15 Modified temperature transfer function for
+* 					  for Ultrascale CR#859369
+* 7.2   sk   11/10/15 Used UINTPTR instead of u32 for Baseaddress CR# 867425.
+*                     Changed the prototype of XSysMon_CfgInitialize API.
+* 7.2  adk  29/02/16 Updated interrupt example to support Zynq and ZynqMP
+*                    CR#938326.
+* 7.2  asa  11/03/16  Made changes to use configuration register 3 only for
+*					  Ultrascale. This fixes the CR#910905.
+* 7.2  adk  14/03/16 Fix compilation issues when sysmon is configured
+*                    with streaming interface CR#940976.
+* 7.3  vns  15/04/16 Corrected Ultrascale conversion formulae CR#949949
+*      ms   01/23/17 Added xil_printf statement in main function for all
+*                    examples to ensure that "Successfully ran" and "Failed"
+*                    strings are available in all examples. This is a fix
+*                    for CR-965028.
+*      ms   03/17/17 Added readme.txt file in examples folder for doxygen
+*                    generation.
+*      ms   04/05/17 Modified Comment lines in functions of sysmon
+*                    examples to recognize it as documentation block
+*                    for doxygen generation.
+* 7.4  ms   04/18/17 Modified tcl file to add suffix U for all macros
+*                    definitions of sysmon in xparameters.h
+* 
+* +*****************************************************************************/ + +#ifndef XSYSMON_H /* Prevent circular inclusions */ +#define XSYSMON_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files ********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xstatus.h" +#include "xsysmon_hw.h" + +/************************** Constant Definitions ****************************/ + + +/** + * @name Indexes for the different channels. + * @{ + */ +#define XSM_CH_TEMP 0x0 /**< On Chip Temperature */ +#define XSM_CH_VCCINT 0x1 /**< VCCINT */ +#define XSM_CH_VCCAUX 0x2 /**< VCCAUX */ +#define XSM_CH_VPVN 0x3 /**< VP/VN Dedicated analog inputs */ +#define XSM_CH_VREFP 0x4 /**< VREFP */ +#define XSM_CH_VREFN 0x5 /**< VREFN */ +#define XSM_CH_VBRAM 0x6 /**< VBRAM - 7 Series and Zynq */ +#define XSM_CH_SUPPLY_CALIB 0x07 /**< Supply Calib Data Reg */ +#define XSM_CH_ADC_CALIB 0x08 /**< ADC Offset Channel Reg */ +#define XSM_CH_GAINERR_CALIB 0x09 /**< Gain Error Channel Reg */ +#define XSM_CH_VCCPINT 0x0D /**< On-chip PS VCCPINT Channel, Zynq */ +#define XSM_CH_VCCPAUX 0x0E /**< On-chip PS VCCPAUX Channel, Zynq */ +#define XSM_CH_VCCPDRO 0x0F /**< On-chip PS VCCPDRO Channel, Zynq */ +#define XSM_CH_AUX_MIN 16 /**< Channel number for 1st Aux Channel */ +#define XSM_CH_AUX_MAX 31 /**< Channel number for Last Aux channel */ +#define XSM_CH_VUSR0 32 /**< VUSER0 Supply - UltraScale */ +#define XSM_CH_VUSR1 33 /**< VUSER1 Supply - UltraScale */ +#define XSM_CH_VUSR2 34 /**< VUSER2 Supply - UltraScale */ +#define XSM_CH_VUSR3 35 /**< VUSER3 Supply - UltraScale */ + + +/*@}*/ + + +/** + * @name Indexes for reading the Calibration Coefficient Data. + * @{ + */ +#define XSM_CALIB_SUPPLY_OFFSET_COEFF 0 /**< Supply Offset Calib Coefficient */ +#define XSM_CALIB_ADC_OFFSET_COEFF 1 /**< ADC Offset Calib Coefficient */ +#define XSM_CALIB_GAIN_ERROR_COEFF 2 /**< Gain Error Calib Coefficient*/ + +/*@}*/ + + +/** + * @name Indexes for reading the Minimum/Maximum Measurement Data. + * @{ + */ +#define XSM_MAX_TEMP 0 /**< Maximum Temperature Data */ +#define XSM_MAX_VCCINT 1 /**< Maximum VCCINT Data */ +#define XSM_MAX_VCCAUX 2 /**< Maximum VCCAUX Data */ +#define XSM_MAX_VCCBRAM 3 /**< Maximum VCCBRAM Data, 7 Series/Zynq */ +#define XSM_MIN_TEMP 4 /**< Minimum Temperature Data */ +#define XSM_MIN_VCCINT 5 /**< Minimum VCCINT Data */ +#define XSM_MIN_VCCAUX 6 /**< Minimum VCCAUX Data */ +#define XSM_MIN_VCCBRAM 7 /**< Minimum VCCBRAM Data, 7 Series/Zynq */ +#define XSM_MAX_VCCPINT 8 /**< Maximum VCCPINT Data, Zynq */ +#define XSM_MAX_VCCPAUX 9 /**< Maximum VCCPAUX Data, Zynq */ +#define XSM_MAX_VCCPDRO 0xA /**< Maximum VCCPDRO Data, Zynq */ +#define XSM_MIN_VCCPINT 0xC /**< Minimum VCCPINT Data, Zynq */ +#define XSM_MIN_VCCPAUX 0xD /**< Minimum VCCPAUX Data, Zynq */ +#define XSM_MIN_VCCPDRO 0xE /**< Minimum VCCPDRO Data, Zynq */ +#define XSM_MAX_VUSR0 0x80 /**< Maximum VUSR0 Data, Ultrascale */ +#define XSM_MAX_VUSR1 0x81 /**< Maximum VUSR1 Data, Ultrascale */ +#define XSM_MAX_VUSR2 0x82 /**< Maximum VUSR2 Data, Ultrascale */ +#define XSM_MAX_VUSR3 0x83 /**< Maximum VUSR3 Data, Ultrascale */ +#define XSM_MIN_VUSR0 0x88 /**< Minimum VUSR0 Data, Ultrascale */ +#define XSM_MIN_VUSR1 0x89 /**< Minimum VUSR1 Data, Ultrascale */ +#define XSM_MIN_VUSR2 0x8A /**< Minimum VUSR2 Data, Ultrascale */ +#define XSM_MIN_VUSR3 0x8B /**< Minimum VUSR3 Data, Ultrascale */ + + +/*@}*/ + + +/** + * @name Alarm Threshold(Limit) Register (ATR) indexes. + * @{ + */ +#define XSM_ATR_TEMP_UPPER 0 /**< High user Temperature */ +#define XSM_ATR_VCCINT_UPPER 1 /**< VCCINT high voltage limit */ +#define XSM_ATR_VCCAUX_UPPER 2 /**< VCCAUX high voltage limit */ +#define XSM_ATR_OT_UPPER 3 /**< Lower Over Temperature limit */ +#define XSM_ATR_TEMP_LOWER 4 /**< Low user Temperature */ +#define XSM_ATR_VCCINT_LOWER 5 /**< VCCINT low voltage limit */ +#define XSM_ATR_VCCAUX_LOWER 6 /**< VCCAUX low voltage limit */ +#define XSM_ATR_OT_LOWER 7 /**< Lower Over Temperature limit */ +#define XSM_ATR_VBRAM_UPPER 8 /**< VBRAM high voltage limit */ +#define XSM_ATR_VCCPINT_UPPER 9 /**< VCCPINT Upper Alarm, Zynq */ +#define XSM_ATR_VCCPAUX_UPPER 0xA /**< VCCPAUX Upper Alarm, Zynq */ +#define XSM_ATR_VCCPDRO_UPPER 0xB /**< VCCPDRO Upper Alarm, Zynq */ +#define XSM_ATR_VBRAM_LOWER 0xC /**< VRBAM Lower Alarm, 7 Series and Zynq*/ +#define XSM_ATR_VCCPINT_LOWER 0xD /**< VCCPINT Lower Alarm, Zynq */ +#define XSM_ATR_VCCPAUX_LOWER 0xE /**< VCCPAUX Lower Alarm, Zynq */ +#define XSM_ATR_VCCPDRO_LOWER 0xF /**< VCCPDRO Lower Alarm, Zynq */ +#define XSM_ATR_VUSR0_UPPER 0x10 /**< VUSER0 Upper Alarm, Ultrascale */ +#define XSM_ATR_VUSR1_UPPER 0x11 /**< VUSER1 Upper Alarm, Ultrascale */ +#define XSM_ATR_VUSR2_UPPER 0x12 /**< VUSER2 Upper Alarm, Ultrascale */ +#define XSM_ATR_VUSR3_UPPER 0x13 /**< VUSER3 Upper Alarm, Ultrascale */ +#define XSM_ATR_VUSR0_LOWER 0x18 /**< VUSER0 Lower Alarm, Ultrascale */ +#define XSM_ATR_VUSR1_LOWER 0x19 /**< VUSER1 Lower Alarm, Ultrascale */ +#define XSM_ATR_VUSR2_LOWER 0x1A /**< VUSER2 Lower Alarm, Ultrascale */ +#define XSM_ATR_VUSR3_LOWER 0x1B /**< VUSER3 Lower Alarm, Ultrascale */ + +/*@}*/ + + +/** + * @name Averaging to be done for the channels. + * @{ + */ +#define XSM_AVG_0_SAMPLES 0 /**< No Averaging */ +#define XSM_AVG_16_SAMPLES 1 /**< Average 16 samples */ +#define XSM_AVG_64_SAMPLES 2 /**< Average 64 samples */ +#define XSM_AVG_256_SAMPLES 3 /**< Average 256 samples */ + +/*@}*/ + + +/** + * @name Channel Sequencer Modes of operation. + * @{ + */ +#define XSM_SEQ_MODE_SAFE 0 /**< Default Safe Mode */ +#define XSM_SEQ_MODE_ONEPASS 1 /**< Onepass through Sequencer */ +#define XSM_SEQ_MODE_CONTINPASS 2 /**< Continuous Cycling Seqquencer */ +#define XSM_SEQ_MODE_SINGCHAN 3 /**< Single channel - No Sequencing */ +#define XSM_SEQ_MODE_SIMUL 4 /**< Simultaneous Cycling Sequencer, + * 7 Series and Zynq XADC only */ +#define XSM_SEQ_MODE_INDEPENDENT 8 /**< Independent ADC Sequencer, + * 7 Series and Zynq XADC only */ + +/*@}*/ + +/* For backwards compatabilty */ +#define XSM_CH_CALIBRATION XSM_CH_ADC_CALIB +#define XSM_ATR_BRAM_UPPER XSM_ATR_VBRAM_UPPER +#define XSM_ATR_BRAM_LOWER XSM_ATR_VBRAM_LOWER + + +/**************************** Type Definitions ******************************/ + +/** + * This typedef contains configuration information for the System Monitor/ADC + * device. + */ +typedef struct { + u16 DeviceId; /**< Unique ID of device */ + UINTPTR BaseAddress; /**< Device base address */ + int IncludeInterrupt; /**< Supports Interrupt driven mode */ + u8 IpType; /**< 1 - System Management */ + /**< 0 - XADC/System Monoitor */ +} XSysMon_Config; + + +/** + * The driver's instance data. The user is required to allocate a variable + * of this type for every System Monitor/ADC device in the system. A pointer to + * a variable of this type is then passed to the driver API functions. + */ +typedef struct { + XSysMon_Config Config; /**< XSysMon_Config of current device */ + u32 IsReady; /**< Device is initialized and ready */ + u32 Mask; /**< Store the previously written value + in CONVST register */ +} XSysMon; + +/***************** Macros (Inline Functions) Definitions ********************/ + +/****************************************************************************/ +/** +* +* This macro checks if the SysMonitor/ADC device is in Event Sampling mode. +* +* @param InstancePtr is a pointer to the XSysMon instance. +* +* @return +* - TRUE if the device is in Event Sampling Mode. +* - FALSE if the device is in Continuous Sampling Mode. +* +* @note C-Style signature: +* int XSysMon_IsEventSamplingMode(XSysMon *InstancePtr); +* +*****************************************************************************/ +#define XSysMon_IsEventSamplingModeSet(InstancePtr) \ + (((XSysMon_ReadReg((InstancePtr)->Config.BaseAddress, \ + XSM_CFR0_OFFSET) & XSM_CFR0_EC_MASK) ? \ + TRUE : FALSE)) + +/****************************************************************************/ +/** +* +* This macro checks if the Dynamic Reconfiguration Port (DRP) transaction from +* the JTAG is in progress. +* +* @param InstancePtr is a pointer to the XSysMon instance. +* +* @return +* - TRUE if the DRP transaction from JTAG is in Progress. +* - FALSE if there is no DRP transaction from the JTAG. +* +* @note C-Style signature: +* int XSysMon_IsDrpBusy(XSysMon *InstancePtr); +* +*****************************************************************************/ +#define XSysMon_IsDrpBusy(InstancePtr) \ + ((XSysMon_ReadReg((InstancePtr)->Config.BaseAddress, \ + XSM_SR_OFFSET) & XSM_SR_JTAG_BUSY_MASK) ? \ + TRUE : FALSE) + +/****************************************************************************/ +/** +* +* This macro checks if the Dynamic Reconfiguration Port (DRP) is locked by the +* JTAG. +* +* @param InstancePtr is a pointer to the XSysMon instance. +* +* @return +* - TRUE if the DRP is locked by the JTAG. +* - FALSE if the DRP is not locked by the JTAG. +* +* @note C-Style signature: +* int XSysMon_IsDrpLocked(XSysMon *InstancePtr); +* +*****************************************************************************/ +#define XSysMon_IsDrpLocked(InstancePtr) \ + (((XSysMon_ReadReg((InstancePtr)->Config.BaseAddress, \ + XSM_SR_OFFSET) & XSM_SR_JTAG_LOCKED_MASK) ? \ + TRUE : FALSE)) + +/****************************************************************************/ +/** +* +* This macro converts System Monitor/ADC Raw Data to Temperature(centigrades). +* +* @param AdcData is the SysMon Raw ADC Data. +* +* @return The Temperature in centigrades. +* +* @note C-Style signature: +* float XSysMon_RawToTemperature(u32 AdcData); +* +*****************************************************************************/ +#if XPAR_SYSMON_0_IP_TYPE == SYSTEM_MANAGEMENT + +#define XSysMon_RawToTemperature(AdcData) \ + ((((float)(AdcData)/65536.0f)/0.00199451786f ) - 273.67f) + +#else + +#define XSysMon_RawToTemperature(AdcData) \ + ((((float)(AdcData)/65536.0f)/0.00198421639f ) - 273.15f) + +#endif +/****************************************************************************/ +/** +* +* This macro converts System Monitor/ADC Raw Data to Voltage(volts). +* +* @param AdcData is the System Monitor/ADC Raw Data. +* +* @return The Voltage in volts. +* +* @note C-Style signature: +* float XSysMon_RawToVoltage(u32 AdcData); +* +*****************************************************************************/ +#define XSysMon_RawToVoltage(AdcData) \ + ((((float)(AdcData))* (3.0f))/65536.0f) + +/****************************************************************************/ +/** +* +* This macro converts Temperature in centigrades to System Monitor/ADC Raw Data. +* +* @param Temperature is the Temperature in centigrades to be +* converted to System Monitor/ADC Raw Data. +* +* @return The System Monitor/ADC Raw Data. +* +* @note C-Style signature: +* int XSysMon_TemperatureToRaw(float Temperature); +* +*****************************************************************************/ +#if XPAR_SYSMON_0_IP_TYPE == SYSTEM_MANAGEMENT + +#define XSysMon_TemperatureToRaw(Temperature) \ + ((int)(((Temperature) + 273.67f)*65536.0f*0.00199451786f)) + +#else + +#define XSysMon_TemperatureToRaw(Temperature) \ + ((int)(((Temperature) + 273.15f)*65536.0f*0.00198421639f)) + +#endif +/****************************************************************************/ +/** +* +* This macro converts Voltage in Volts to System Monitor/ADC Raw Data. +* +* @param Voltage is the Voltage in volts to be converted to +* System Monitor/ADC Raw Data. +* +* @return The System Monitor/ADC Raw Data. +* +* @note C-Style signature: +* int XSysMon_VoltageToRaw(float Voltage); +* +*****************************************************************************/ +#define XSysMon_VoltageToRaw(Voltage) \ + ((int)((Voltage)*65536.0f/3.0f)) + + +/************************** Function Prototypes *****************************/ + +/** + * Functions in xsysmon_sinit.c + */ +XSysMon_Config *XSysMon_LookupConfig(u16 DeviceId); + +/** + * Functions in xsysmon.c + */ +int XSysMon_CfgInitialize(XSysMon *InstancePtr, + XSysMon_Config *ConfigPtr, UINTPTR EffectiveAddr); + +void XSysMon_Reset(XSysMon *InstancePtr); + +u32 XSysMon_GetStatus(XSysMon *InstancePtr); + +u32 XSysMon_GetAlarmOutputStatus(XSysMon *InstancePtr); + +void XSysMon_StartAdcConversion(XSysMon *InstancePtr); + +void XSysMon_ResetAdc(XSysMon *InstancePtr); + +u16 XSysMon_GetAdcData(XSysMon *InstancePtr, u8 Channel); + +u16 XSysMon_GetCalibCoefficient(XSysMon *InstancePtr, u8 CoeffType); + +u16 XSysMon_GetMinMaxMeasurement(XSysMon *InstancePtr, u8 MeasurementType); + +void XSysMon_SetAvg(XSysMon *InstancePtr, u8 Average); +u8 XSysMon_GetAvg(XSysMon *InstancePtr); + +int XSysMon_SetSingleChParams(XSysMon *InstancePtr, u8 Channel, + int IncreaseAcqCycles, int IsEventMode, + int IsDifferentialMode); + +void XSysMon_SetAlarmEnables(XSysMon *InstancePtr, u32 AlmEnableMask); +u32 XSysMon_GetAlarmEnables(XSysMon *InstancePtr); + +void XSysMon_SetCalibEnables(XSysMon *InstancePtr, u16 Calibration); +u16 XSysMon_GetCalibEnables(XSysMon *InstancePtr); + +void XSysMon_SetSequencerMode(XSysMon *InstancePtr, u8 SequencerMode); +u8 XSysMon_GetSequencerMode(XSysMon *InstancePtr); +void XSysMon_SetSequencerEvent(XSysMon *InstancePtr, int IsEventMode); + +void XSysMon_SetExtenalMux(XSysMon *InstancePtr, u8 Channel); + +void XSysMon_SetAdcClkDivisor(XSysMon *InstancePtr, u8 Divisor); +u8 XSysMon_GetAdcClkDivisor(XSysMon *InstancePtr); + +int XSysMon_SetSeqChEnables(XSysMon *InstancePtr, u64 ChEnableMask); +u64 XSysMon_GetSeqChEnables(XSysMon *InstancePtr); + +int XSysMon_SetSeqAvgEnables(XSysMon *InstancePtr, u64 AvgEnableChMask); +u64 XSysMon_GetSeqAvgEnables(XSysMon *InstancePtr); + +int XSysMon_SetSeqInputMode(XSysMon *InstancePtr, u32 InputModeChMask); +u32 XSysMon_GetSeqInputMode(XSysMon *InstancePtr); + +int XSysMon_SetSeqAcqTime(XSysMon *InstancePtr, u32 AcqCyclesChMask); +u32 XSysMon_GetSeqAcqTime(XSysMon *InstancePtr); + +void XSysMon_SetAlarmThreshold(XSysMon *InstancePtr, u8 AlarmThrReg, u16 Value); +u16 XSysMon_GetAlarmThreshold(XSysMon *InstancePtr, u8 AlarmThrReg); + +void XSysMon_SetOverTemp(XSysMon *InstancePtr, u16 Value); +u16 XSysMon_GetOverTemp(XSysMon *InstancePtr); + +void XSysMon_EnableUserOverTemp(XSysMon *InstancePtr); +void XSysMon_DisableUserOverTemp(XSysMon *InstancePtr); + +void XSysMon_EnableTempUpdate(XSysMon *InstancePtr); +void XSysMon_DisableTempUpdate(XSysMon *InstancePtr); +void XSysMon_SetTempWaitCycles(XSysMon *InstancePtr, u16 WaitCycles); + + +/** + * Functions in xsysmon_selftest.c + */ +int XSysMon_SelfTest(XSysMon *InstancePtr); + +/** + * Functions in xsysmon_intr.c + */ +void XSysMon_IntrGlobalEnable(XSysMon *InstancePtr); +void XSysMon_IntrGlobalDisable(XSysMon *InstancePtr); + +void XSysMon_IntrEnable(XSysMon *InstancePtr, u32 Mask); +void XSysMon_IntrDisable(XSysMon *InstancePtr, u32 Mask); +u32 XSysMon_IntrGetEnabled(XSysMon *InstancePtr); + +u32 XSysMon_IntrGetStatus(XSysMon *InstancePtr); +void XSysMon_IntrClear(XSysMon *InstancePtr, u32 Mask); + + +#ifdef __cplusplus +} +#endif + +#endif /* End of protection macro. */ +/** @} */ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/sysmon_v7_5/src/xsysmon_g.c b/datalink814_sp/bsp/microblaze_ps/libsrc/sysmon_v7_5/src/xsysmon_g.c new file mode 100644 index 0000000..14768b1 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/sysmon_v7_5/src/xsysmon_g.c @@ -0,0 +1,53 @@ + +/******************************************************************* +* +* CAUTION: This file is automatically generated by HSI. +* Version: 2019.1.3 +* DO NOT EDIT. +* +* Copyright (C) 2010-2023 Xilinx, Inc. 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 +*XILINX 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. +* +*Except as contained in this notice, the name of the Xilinx shall not be used +*in advertising or otherwise to promote the sale, use or other dealings in +*this Software without prior written authorization from Xilinx. +* + +* +* Description: Driver configuration +* +*******************************************************************/ + +#include "xparameters.h" +#include "xsysmon.h" + +/* + * The configuration table for devices + */ + +XSysMon_Config XSysMon_ConfigTable[] = +{ + { + XPAR_SYSMON_0_DEVICE_ID, + XPAR_SYSMON_0_BASEADDR, + XPAR_SYSMON_0_INCLUDE_INTR, + XPAR_SYSMON_0_IP_TYPE + } +}; + + diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/sysmon_v7_5/src/xsysmon_hw.h b/datalink814_sp/bsp/microblaze_ps/libsrc/sysmon_v7_5/src/xsysmon_hw.h new file mode 100644 index 0000000..9316273 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/sysmon_v7_5/src/xsysmon_hw.h @@ -0,0 +1,686 @@ +/****************************************************************************** +* +* Copyright (C) 2007 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xsysmon_hw.h +* @addtogroup sysmon_v7_5 +* @{ +* +* This header file contains identifiers and basic driver functions (or +* macros) that can be used to access the System Monitor/ADC device or XADC. +* +* Refer to the device specification for more information about this driver. +* +* @note None. +* +*
+*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- -----  -------- -----------------------------------------------------
+* 1.00a xd/sv  05/22/07 First release
+* 2.00a sv     07/07/08 Added bit definitions for new Alarm Interrupts in the
+*			Interrupt Registers.
+* 3.00a sdm    02/09/09 Added register and bit definitions for V6 SysMon.
+* 4.00a ktn    10/22/09 The macros have been renamed to remove _m from the name
+*		       	of the macro.
+* 5.00a sdm    06/15/11 Added new definitions for XADC.
+* 5.01a bss    02/15/12 Updated for Zynq.
+* 5.02a bss    11/23/12 Added macros XSM_CONVST_TEMPUPDT_MASK,
+*			XSM_CONVST_WAITCYCLES_MASK and
+*			XSM_CONVST_WAITCYCLES_SHIFT (CR #679872)
+* 7.0	bss    7/25/14	To support Ultrascale:
+*			Added XSM_IP_OFFSET macro.
+*			Added Offsets and Masks for VUSER0 to VUSER3 channels.
+*			Added Configuration Register 3 and Sequence Registers
+*			8 and 9.
+* 7.2   asa     03/11/16 Made changes so that XSM_CFR3_OFFSET is
+*             visible only for Ultrasacle. Fix for CR#910905.
+*
+* 
+* +*****************************************************************************/ + +#ifndef XSYSMON_HW_H /* Prevent circular inclusions */ +#define XSYSMON_HW_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files ********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_io.h" +#include "xparameters.h" + +/************************** Constant Definitions ****************************/ + +#define SYSTEM_MANAGEMENT 1 /* Ultrascale */ +#define XADC 0 /* 7 Series, Zynq */ + + +#if XPAR_SYSMON_0_IP_TYPE == SYSTEM_MANAGEMENT +#define XSM_IP_OFFSET 0x200 +#else +#define XSM_IP_OFFSET 0x00 +#endif + + +/**@name Register offsets + * + * The following constants provide access to each of the registers of the + * System Monitor/ADC device. + * @{ + */ + +/* + * System Monitor/ADC Local Registers + */ +#define XSM_SRR_OFFSET 0x00 /**< Software Reset Register */ +#define XSM_SR_OFFSET 0x04 /**< Status Register */ +#define XSM_AOR_OFFSET 0x08 /**< Alarm Output Register */ +#define XSM_CONVST_OFFSET 0x0C /**< ADC Convert Start Register */ +#define XSM_ARR_OFFSET 0x10 /**< ADC Reset Register */ + +/* + * System Monitor/ADC Interrupt Registers + */ +#define XSM_GIER_OFFSET 0x5C /**< Global Interrupt Enable */ +#define XSM_IPISR_OFFSET 0x60 /**< Interrupt Status Register */ +#define XSM_IPIER_OFFSET 0x68 /**< Interrupt Enable register */ + +/* + * System Monitor/ADC Internal Channel Registers + */ +#define XSM_TEMP_OFFSET (XSM_IP_OFFSET + 0x200) + /**< On-chip Temperature Reg */ +#define XSM_VCCINT_OFFSET (XSM_IP_OFFSET + 0x204) + /**< On-chip VCCINT Data Reg */ +#define XSM_VCCAUX_OFFSET (XSM_IP_OFFSET + 0x208) + /**< On-chip VCCAUX Data Reg */ +#define XSM_VPVN_OFFSET (XSM_IP_OFFSET + 0x20C) + /**< ADC out of VP/VN */ +#define XSM_VREFP_OFFSET (XSM_IP_OFFSET + 0x210) + /**< On-chip VREFP Data Reg */ +#define XSM_VREFN_OFFSET (XSM_IP_OFFSET + 0x214) + /**< On-chip VREFN Data Reg */ +#define XSM_VBRAM_OFFSET (XSM_IP_OFFSET + 0x218) + /**< On-chip VBRAM Data,7-series/Zynq */ +#define XSM_SUPPLY_CALIB_OFFSET (XSM_IP_OFFSET + 0x220) + /**< Supply Offset Data Reg */ +#define XSM_ADC_CALIB_OFFSET (XSM_IP_OFFSET + 0x224) + /**< ADC Offset Data Reg */ +#define XSM_GAINERR_CALIB_OFFSET (XSM_IP_OFFSET + 0x228) + /**< Gain Error Data Reg */ +#define XSM_VCCPINT_OFFSET (XSM_IP_OFFSET + 0x22C) + /**< PS VCCPINT Data Reg - Zynq */ +#define XSM_VCCPAUX_OFFSET (XSM_IP_OFFSET + 0x230) + /**< PS VCCPAUX Data Reg - Zynq */ +#define XSM_VCCPDRO_OFFSET (XSM_IP_OFFSET + 0x234) + /**< PS VCCPDRO Data Reg - Zynq */ +#define XSM_VUSR0_OFFSET (XSM_IP_OFFSET + 0x400) + /**< VUSER0 Supply - Ultrascale */ +#define XSM_VUSR1_OFFSET (XSM_IP_OFFSET + 0x404) + /**< VUSER0 Supply - Ultrascale */ +#define XSM_VUSR2_OFFSET (XSM_IP_OFFSET + 0x408) + /**< VUSER0 Supply - Ultrascale */ +#define XSM_VUSR3_OFFSET (XSM_IP_OFFSET + 0x40C) + /**< VUSER0 Supply - Ultrascale */ + +/* + * System Monitor/ADC External Channel Registers + */ +#define XSM_AUX00_OFFSET (XSM_IP_OFFSET + 0x240) + /**< ADC out of VAUXP0/VAUXN0 */ +#define XSM_AUX01_OFFSET (XSM_IP_OFFSET + 0x244) + /**< ADC out of VAUXP1/VAUXN1 */ +#define XSM_AUX02_OFFSET (XSM_IP_OFFSET + 0x248) + /**< ADC out of VAUXP2/VAUXN2 */ +#define XSM_AUX03_OFFSET (XSM_IP_OFFSET + 0x24C) + /**< ADC out of VAUXP3/VAUXN3 */ +#define XSM_AUX04_OFFSET (XSM_IP_OFFSET + 0x250) + /**< ADC out of VAUXP4/VAUXN4 */ +#define XSM_AUX05_OFFSET (XSM_IP_OFFSET + 0x254) + /**< ADC out of VAUXP5/VAUXN5 */ +#define XSM_AUX06_OFFSET (XSM_IP_OFFSET + 0x258) + /**< ADC out of VAUXP6/VAUXN6 */ +#define XSM_AUX07_OFFSET (XSM_IP_OFFSET + 0x25C) + /**< ADC out of VAUXP7/VAUXN7 */ +#define XSM_AUX08_OFFSET (XSM_IP_OFFSET + 0x260) + /**< ADC out of VAUXP8/VAUXN8 */ +#define XSM_AUX09_OFFSET (XSM_IP_OFFSET + 0x264) + /**< ADC out of VAUXP9/VAUXN9 */ +#define XSM_AUX10_OFFSET (XSM_IP_OFFSET + 0x268) + /**< ADC out of VAUXP10/VAUXN10 */ +#define XSM_AUX11_OFFSET (XSM_IP_OFFSET + 0x26C) + /**< ADC out of VAUXP11/VAUXN11 */ +#define XSM_AUX12_OFFSET (XSM_IP_OFFSET + 0x270) + /**< ADC out of VAUXP12/VAUXN12 */ +#define XSM_AUX13_OFFSET (XSM_IP_OFFSET + 0x274) + /**< ADC out of VAUXP13/VAUXN13 */ +#define XSM_AUX14_OFFSET (XSM_IP_OFFSET + 0x278) + /**< ADC out of VAUXP14/VAUXN14 */ +#define XSM_AUX15_OFFSET (XSM_IP_OFFSET + 0x27C) + /**< ADC out of VAUXP15/VAUXN15 */ + +/* + * System Monitor/ADC Registers for Maximum/Minimum data captured for the + * on chip Temperature/VCCINT/VCCAUX data. + */ +#define XSM_MAX_TEMP_OFFSET (XSM_IP_OFFSET + 0x280) + /**< Maximum Temperature Reg */ +#define XSM_MAX_VCCINT_OFFSET (XSM_IP_OFFSET + 0x284) + /**< Maximum VCCINT Register */ +#define XSM_MAX_VCCAUX_OFFSET (XSM_IP_OFFSET + 0x288) + /**< Maximum VCCAUX Register */ +#define XSM_MAX_VBRAM_OFFSET (XSM_IP_OFFSET + 0x28C) + /**< Maximum VBRAM Reg, 7 Series/Zynq */ +#define XSM_MIN_TEMP_OFFSET (XSM_IP_OFFSET + 0x290) + /**< Minimum Temperature Reg */ +#define XSM_MIN_VCCINT_OFFSET (XSM_IP_OFFSET + 0x294) + /**< Minimum VCCINT Register */ +#define XSM_MIN_VCCAUX_OFFSET (XSM_IP_OFFSET + 0x298) + /**< Minimum VCCAUX Register */ +#define XSM_MIN_VBRAM_OFFSET (XSM_IP_OFFSET + 0x29C) + /**< Maximum VBRAM Reg, 7 Series/Zynq */ +#define XSM_MAX_VCCPINT_OFFSET (XSM_IP_OFFSET + 0x2A0) + /**< Max VCCPINT Register, Zynq */ +#define XSM_MAX_VCCPAUX_OFFSET (XSM_IP_OFFSET + 0x2A4) + /**< Max VCCPAUX Register, Zynq */ +#define XSM_MAX_VCCPDRO_OFFSET (XSM_IP_OFFSET + 0x2A8) + /**< Max VCCPDRO Register, Zynq */ +#define XSM_MIN_VCCPINT_OFFSET (XSM_IP_OFFSET + 0x2AC) + /**< Min VCCPINT Register, Zynq */ +#define XSM_MIN_VCCPAUX_OFFSET (XSM_IP_OFFSET + 0x2B0) + /**< Min VCCPAUX Register, Zynq */ +#define XSM_MIN_VCCPDRO_OFFSET (XSM_IP_OFFSET + 0x2B4) + /**< Min VCCPDRO Register, Zynq */ +#define XSM_MAX_VUSR0_OFFSET (XSM_IP_OFFSET + 0x480) + /**< Maximum VUSER0 Supply Reg */ +#define XSM_MAX_VUSR1_OFFSET (XSM_IP_OFFSET + 0x484) + /**< Maximum VUSER1 Supply Reg */ +#define XSM_MAX_VUSR2_OFFSET (XSM_IP_OFFSET + 0x488) + /**< Maximum VUSER2 Supply Reg */ +#define XSM_MAX_VUSR3_OFFSET (XSM_IP_OFFSET + 0x48C) + /**< Maximum VUSER3 Supply Reg */ +#define XSM_MIN_VUSR0_OFFSET (XSM_IP_OFFSET + 0x4A0) + /**< Minimum VUSER0 Supply Reg */ +#define XSM_MIN_VUSR1_OFFSET (XSM_IP_OFFSET + 0x4A4) + /**< Minimum VUSER1 Supply Reg */ +#define XSM_MIN_VUSR2_OFFSET (XSM_IP_OFFSET + 0x4A8) + /**< Minimum VUSER2 Supply Reg */ +#define XSM_MIN_VUSR3_OFFSET (XSM_IP_OFFSET + 0x4AC) + /**< Minimum VUSER3 Supply Reg */ + + +#define XSM_FLAG_REG_OFFSET (XSM_IP_OFFSET + 0x2FC) /**< General Status */ + +/* + * System Monitor/ADC Configuration Registers + */ +#define XSM_CFR0_OFFSET (XSM_IP_OFFSET + 0x300) + /**< Configuration Register 0 */ +#define XSM_CFR1_OFFSET (XSM_IP_OFFSET + 0x304) + /**< Configuration Register 1 */ +#define XSM_CFR2_OFFSET (XSM_IP_OFFSET + 0x308) + /**< Configuration Register 2 */ + +#if XPAR_SYSMON_0_IP_TYPE == SYSTEM_MANAGEMENT +#define XSM_CFR3_OFFSET (XSM_IP_OFFSET + 0x30C) + /**< Configuration Register 3 */ +#endif +/* + * System Monitor/ADC Sequence Registers + */ +#define XSM_SEQ00_OFFSET (XSM_IP_OFFSET + 0x320) + /**< Seq Reg 00 Adc Channel Selection */ +#define XSM_SEQ01_OFFSET (XSM_IP_OFFSET + 0x324) + /**< Seq Reg 01 Adc Channel Selection */ +#define XSM_SEQ02_OFFSET (XSM_IP_OFFSET + 0x328) + /**< Seq Reg 02 Adc Average Enable */ +#define XSM_SEQ03_OFFSET (XSM_IP_OFFSET + 0x32C) + /**< Seq Reg 03 Adc Average Enable */ +#define XSM_SEQ04_OFFSET (XSM_IP_OFFSET + 0x330) + /**< Seq Reg 04 Adc Input Mode Select */ +#define XSM_SEQ05_OFFSET (XSM_IP_OFFSET + 0x334) + /**< Seq Reg 05 Adc Input Mode Select */ +#define XSM_SEQ06_OFFSET (XSM_IP_OFFSET + 0x338) + /**< Seq Reg 06 Adc Acquisition Select */ +#define XSM_SEQ07_OFFSET (XSM_IP_OFFSET + 0x33C) + /**< Seq Reg 07 Adc Acquisition Select */ +#define XSM_SEQ08_OFFSET (XSM_IP_OFFSET + 0x318) + /**< Seq Reg 08 Adc Channel Selection */ +#define XSM_SEQ09_OFFSET (XSM_IP_OFFSET + 0x31C) + /**< Seq Reg 09 Adc Average Enable */ + +/* + * System Monitor/ADC Alarm Threshold/Limit Registers (ATR) + */ +#define XSM_ATR_TEMP_UPPER_OFFSET (XSM_IP_OFFSET + 0x340) + /**< Temp Upper Alarm Register */ +#define XSM_ATR_VCCINT_UPPER_OFFSET (XSM_IP_OFFSET + 0x344) + /**< VCCINT Upper Alarm Reg */ +#define XSM_ATR_VCCAUX_UPPER_OFFSET (XSM_IP_OFFSET + 0x348) + /**< VCCAUX Upper Alarm Reg */ +#define XSM_ATR_OT_UPPER_OFFSET (XSM_IP_OFFSET + 0x34C) + /**< Over Temp Upper Alarm Reg */ +#define XSM_ATR_TEMP_LOWER_OFFSET (XSM_IP_OFFSET + 0x350) + /**< Temp Lower Alarm Register */ +#define XSM_ATR_VCCINT_LOWER_OFFSET (XSM_IP_OFFSET + 0x354) + /**< VCCINT Lower Alarm Reg */ +#define XSM_ATR_VCCAUX_LOWER_OFFSET (XSM_IP_OFFSET + 0x358) + /**< VCCAUX Lower Alarm Reg */ +#define XSM_ATR_OT_LOWER_OFFSET (XSM_IP_OFFSET + 0x35C) + /**< Over Temp Lower Alarm Reg */ +#define XSM_ATR_VBRAM_UPPER_OFFSET (XSM_IP_OFFSET + 0x360) + /**< VBBAM Upper Alarm,7 Series */ +#define XSM_ATR_VCCPINT_UPPER_OFFSET (XSM_IP_OFFSET + 0x364) + /**< VCCPINT Upper Alarm, Zynq */ +#define XSM_ATR_VCCPAUX_UPPER_OFFSET (XSM_IP_OFFSET + 0x368) + /**< VCCPAUX Upper Alarm, Zynq */ +#define XSM_ATR_VCCPDRO_UPPER_OFFSET (XSM_IP_OFFSET + 0x36C) + /**< VCCPDRO Upper Alarm, Zynq */ +#define XSM_ATR_VBRAM_LOWER_OFFSET (XSM_IP_OFFSET + 0x370) + /**< VRBAM Lower Alarm, 7 Series*/ +#define XSM_ATR_VCCPINT_LOWER_OFFSET (XSM_IP_OFFSET + 0x374) + /**< VCCPINT Lower Alarm, Zynq */ +#define XSM_ATR_VCCPAUX_LOWER_OFFSET (XSM_IP_OFFSET + 0x378) + /**< VCCPAUX Lower Alarm, Zynq */ +#define XSM_ATR_VCCPDRO_LOWER_OFFSET (XSM_IP_OFFSET + 0x37C) + /**< VCCPDRO Lower Alarm, Zynq */ +#define XSM_ATR_VUSR0_UPPER_OFFSET (XSM_IP_OFFSET + 0x380) + /**< VUSER0 Upper Alarm Reg */ +#define XSM_ATR_VUSR1_UPPER_OFFSET (XSM_IP_OFFSET + 0x384) + /**< VUSER1 Upper Alarm Reg */ +#define XSM_ATR_VUSR2_UPPER_OFFSET (XSM_IP_OFFSET + 0x388) + /**< VUSER2 Upper Alarm Reg */ +#define XSM_ATR_VUSR3_UPPER_OFFSET (XSM_IP_OFFSET + 0x38C) + /**< VUSER3 Upper Alarm Reg */ +#define XSM_ATR_VUSR0_LOWER_OFFSET (XSM_IP_OFFSET + 0x3A0) + /**< VUSER0 Lower Alarm Reg */ +#define XSM_ATR_VUSR1_LOWER_OFFSET (XSM_IP_OFFSET + 0x3A4) + /**< VUSER1 Lower Alarm Reg */ +#define XSM_ATR_VUSR2_LOWER_OFFSET (XSM_IP_OFFSET + 0x3A8) + /**< VUSER2 Lower Alarm Reg */ +#define XSM_ATR_VUSR3_LOWER_OFFSET (XSM_IP_OFFSET + 0x3AC) + /**< VUSER3 Lower Alarm Reg */ + +/*@}*/ + +/** + * @name System Monitor/ADC Software Reset Register (SRR) mask(s) + * @{ + */ +#define XSM_SRR_IPRST_MASK 0x0000000A /**< Device Reset Mask */ + +/*@}*/ + +/** + * @name System Monitor/ADC Status Register (SR) mask(s) + * @{ + */ +#define XSM_SR_JTAG_BUSY_MASK 0x00000400 /**< JTAG is busy */ +#define XSM_SR_JTAG_MODIFIED_MASK 0x00000200 /**< JTAG Write has occurred */ +#define XSM_SR_JTAG_LOCKED_MASK 0x00000100 /**< JTAG is locked */ +#define XSM_SR_BUSY_MASK 0x00000080 /**< ADC is busy in conversion */ +#define XSM_SR_EOS_MASK 0x00000040 /**< End of Sequence */ +#define XSM_SR_EOC_MASK 0x00000020 /**< End of Conversion */ +#define XSM_SR_CH_MASK 0x0000001F /**< Input ADC channel */ + +/*@}*/ + +/** + * @name System Monitor/ADC Alarm Output Register (AOR) mask(s) + * @{ + */ +#define XSM_AOR_ALARM_ALL_MASK 0x00001FFF /**< Mask for all Alarms */ +#define XSM_AOR_VUSR3_MASK 0x00001000 /**< ALM11 - VUSER3 Alarm Mask */ +#define XSM_AOR_VUSR2_MASK 0x00000800 /**< ALM10 - VUSER2 Alarm Mask */ +#define XSM_AOR_VUSR1_MASK 0x00000400 /**< ALM9 - VUSER1 Alarm Mask */ +#define XSM_AOR_VUSR0_MASK 0x00000200 /**< ALM8 - VUSER0 Alarm Mask */ +#define XSM_AOR_ALL_MASK 0x00000100 /**< ALM7 - All Alarms 0 to 6 */ +#define XSM_AOR_VCCPDRO_MASK 0x00000080 /**< ALM6 - VCCPDRO Mask, Zynq */ +#define XSM_AOR_VCCPAUX_MASK 0x00000040 /**< ALM5 - VCCPAUX Mask, Zynq */ +#define XSM_AOR_VCCPINT_MASK 0x00000020 /**< ALM4 - VCCPINT Mask, Zynq */ +#define XSM_AOR_VBRAM_MASK 0x00000010 /**< ALM3 - VBRAM Output Mask + * - 7 Series and Zynq */ +#define XSM_AOR_VCCAUX_MASK 0x00000008 /**< ALM2 - VCCAUX Output Mask */ +#define XSM_AOR_VCCINT_MASK 0x00000004 /**< ALM1 - VCCINT Alarm Mask */ +#define XSM_AOR_TEMP_MASK 0x00000002 /**< ALM0 - Temp sensor Alarm Mask */ +#define XSM_AOR_OT_MASK 0x00000001 /**< Over Temp Alarm Output */ + +/*@}*/ + +/** + * @name System Monitor/ADC CONVST Register (CONVST) mask(s) + * @{ + */ +#define XSM_CONVST_CONVST_MASK 0x00000001 + /**< Conversion Start Mask */ +#define XSM_CONVST_TEMPUPDT_MASK 0x00000002 + /**< Temperature Update + Enable Mask */ +#define XSM_CONVST_WAITCYCLES_SHIFT 2 /**< Wait Cycles Shift */ +#define XSM_CONVST_WAITCYCLES_MASK 0x0003FFFC /**< Wait Cycles Mask */ +#define XSM_CONVST_WAITCYCLES_DEFAULT 0x03E8 /**< Wait Cycles + default value */ +/*@}*/ + +/** + * @name System Monitor/ADC Reset Register (ARR) mask(s) + * @{ + */ +#define XSM_ARR_RST_MASK 0x00000001 /**< ADC Reset bit mask */ + +/*@}*/ + +/** + * @name Global Interrupt Enable Register (GIER) mask(s) + * @{ + */ +#define XSM_GIER_GIE_MASK 0x80000000 /**< Global interrupt enable */ +/*@}*/ + +/** + * @name System Monitor/ADC device Interrupt Status/Enable Registers + * + * Interrupt Status Register (IPISR) + * + * This register holds the interrupt status flags for the device. + * + * Interrupt Enable Register (IPIER) + * + * This register is used to enable interrupt sources for the device. + * Writing a '1' to a bit in this register enables the corresponding Interrupt. + * Writing a '0' to a bit in this register disables the corresponding Interrupt + * + * IPISR/IPIER registers have the same bit definitions and are only defined + * once. + * @{ + */ +#define XSM_IPIXR_VBRAM_MASK 0x00000400 /**< ALM3 - VBRAM Output Mask + * - 7 Series and Zynq */ +#define XSM_IPIXR_TEMP_DEACTIVE_MASK 0x00000200 /**< Alarm 0 DEACTIVE */ +#define XSM_IPIXR_OT_DEACTIVE_MASK 0x00000100 /**< Over Temp DEACTIVE */ +#define XSM_IPIXR_JTAG_MODIFIED_MASK 0x00000080 /**< JTAG Modified */ +#define XSM_IPIXR_JTAG_LOCKED_MASK 0x00000040 /**< JTAG Locked */ +#define XSM_IPIXR_EOC_MASK 0x00000020 /**< End Of Conversion */ +#define XSM_IPIXR_EOS_MASK 0x00000010 /**< End Of Sequence */ +#define XSM_IPIXR_VCCAUX_MASK 0x00000008 /**< Alarm 2 - VCCAUX */ +#define XSM_IPIXR_VCCINT_MASK 0x00000004 /**< Alarm 1 - VCCINT */ +#define XSM_IPIXR_TEMP_MASK 0x00000002 /**< Alarm 0 - Temp ACTIVE */ +#define XSM_IPIXR_OT_MASK 0x00000001 /**< Over Temperature ACTIVE */ +#define XSM_IPIXR_VUSR0_MASK 0x00004000 /**< Alarm 8 VUSER0 */ +#define XSM_IPIXR_VUSR1_MASK 0x00008000 /**< Alarm 9 VUSER1 */ +#define XSM_IPIXR_VUSR2_MASK 0x00010000 /**< Alarm 10 VUSER2 */ +#define XSM_IPIXR_VUSR3_MASK 0x00020000 /**< Alarm 11 VUSER3 */ +#define XSM_IPIXR_ALL_MASK 0x0003C7FF /**< Mask of all interrupts */ + + +/*@}*/ + +/** + * @name Mask for all ADC converted data including Minimum/Maximum Measurements + * and Threshold data. + * @{ + */ +#define XSM_ADCDATA_MAX_MASK 0x03FF + +/*@}*/ + +/** + * @name Configuration Register 0 (CFR0) mask(s) + * @{ + */ +#define XSM_CFR0_CAL_AVG_MASK 0x8000 /**< Averaging enable Mask */ +#define XSM_CFR0_AVG_VALID_MASK 0x3000 /**< Averaging bit Mask */ +#define XSM_CFR0_AVG1_MASK 0x0000 /**< No Averaging */ +#define XSM_CFR0_AVG16_MASK 0x1000 /**< Average 16 samples */ +#define XSM_CFR0_AVG64_MASK 0x2000 /**< Average 64 samples */ +#define XSM_CFR0_AVG256_MASK 0x3000 /**< Average 256 samples */ +#define XSM_CFR0_AVG_SHIFT 12 /**< Shift for the Averaging bits */ +#define XSM_CFR0_MUX_MASK 0x0800 /**< External Mux Mask Enable + * - 7 Series and Zynq */ +#define XSM_CFR0_DU_MASK 0x0400 /**< Bipolar/Unipolar mode */ +#define XSM_CFR0_EC_MASK 0x0200 /**< Event driven/Continuous mode */ +#define XSM_CFR0_ACQ_MASK 0x0100 /**< Add acquisition by 6 ADCCLK */ +#define XSM_CFR0_CHANNEL_MASK 0x003F /**< Channel number bit Mask */ + +/*@}*/ + +/** + * @name Configuration Register 1 (CFR1) mask(s) + * @{ + */ +#define XSM_CFR1_SEQ_VALID_MASK 0xF000 /**< Sequence bit Mask */ +#define XSM_CFR1_SEQ_SAFEMODE_MASK 0x0000 /**< Default Safe Mode */ +#define XSM_CFR1_SEQ_ONEPASS_MASK 0x1000 /**< Onepass through Seq */ +#define XSM_CFR1_SEQ_CONTINPASS_MASK 0x2000 /**< Continuous Cycling Seq */ +#define XSM_CFR1_SEQ_SINGCHAN_MASK 0x3000 /**< Single channel - No Seq */ +#define XSM_CFR1_SEQ_SIMUL_SAMPLING_MASK 0x4000 /**< Simulataneous Sampling + * Mask */ +#define XSM_CFR1_SEQ_INDEPENDENT_MASK 0x8000 /**< Independent Mode */ +#define XSM_CFR1_SEQ_SHIFT 12 /**< Sequence bit shift */ +#define XSM_CFR1_ALM_VCCPDRO_MASK 0x0800 /**< Alarm 6 - VCCPDRO, Zynq */ +#define XSM_CFR1_ALM_VCCPAUX_MASK 0x0400 /**< Alarm 5 - VCCPAUX, Zynq */ +#define XSM_CFR1_ALM_VCCPINT_MASK 0x0200 /**< Alarm 4 - VCCPINT, Zynq */ +#define XSM_CFR1_ALM_VBRAM_MASK 0x0100 /**< Alarm 3 - VBRAM Enable + * 7 Series and Zynq */ +#define XSM_CFR1_CAL_VALID_MASK 0x00F0 /**< Valid Calibration Mask */ +#define XSM_CFR1_CAL_PS_GAIN_OFFSET_MASK 0x0080 /**< Calibration 3 -Power + Supply Gain/Offset + Enable */ +#define XSM_CFR1_CAL_PS_OFFSET_MASK 0x0040 /**< Calibration 2 -Power + Supply Offset Enable */ +#define XSM_CFR1_CAL_ADC_GAIN_OFFSET_MASK 0x0020 /**< Calibration 1 -ADC Gain + Offset Enable */ +#define XSM_CFR1_CAL_ADC_OFFSET_MASK 0x0010 /**< Calibration 0 -ADC Offset + Enable */ +#define XSM_CFR1_CAL_DISABLE_MASK 0x0000 /**< No Calibration */ +#define XSM_CFR1_ALM_ALL_MASK 0x0F0F /**< Mask for all alarms */ +#define XSM_CFR1_ALM_VCCAUX_MASK 0x0008 /**< Alarm 2 - VCCAUX Enable */ +#define XSM_CFR1_ALM_VCCINT_MASK 0x0004 /**< Alarm 1 - VCCINT Enable */ +#define XSM_CFR1_ALM_TEMP_MASK 0x0002 /**< Alarm 0 - Temperature */ +#define XSM_CFR1_OT_MASK 0x0001 /**< Over Temperature Enable */ + +/*@}*/ + +/** + * @name Configuration Register 2 (CFR2) mask(s) + * @{ + */ +#define XSM_CFR2_CD_VALID_MASK 0xFF00 /** +* +* MODIFICATION HISTORY: +* +* Ver Who Date Changes +* ----- ----- -------- ----------------------------------------------------- +* 1.00a xd/sv 05/22/07 First release +* 4.00a ktn 10/22/09 Updated the file to use the HAL Processor APIs/macros. +* The macros have been renamed to remove _m from the name +* of the macro. +* +* +* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xsysmon.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +/*****************************************************************************/ +/** +* This function enables the global interrupt in the Global Interrupt Enable +* Register (GIER) so that the interrupt output from the System Monitor/ADC +* device is enabled. Interrupts enabled using XSysMon_IntrEnable() will not +* occur until the global interrupt enable bit is set by using this function. +* +* @param InstancePtr is a pointer to the XSysMon instance. +* +* @return None. +* +* @note The device must be configured at hardware build time to include +* interrupt component for this function to work. +* +******************************************************************************/ +void XSysMon_IntrGlobalEnable(XSysMon *InstancePtr) +{ + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(InstancePtr->Config.IncludeInterrupt == TRUE); + + /* + * Enable the Global Interrupt. + */ + XSysMon_WriteReg(InstancePtr->Config.BaseAddress, XSM_GIER_OFFSET, + XSM_GIER_GIE_MASK); +} + +/****************************************************************************/ +/** +* This function disables the global interrupt in the Global Interrupt Enable +* Register (GIER) so that the interrupt output from the System Monitor/ADC +* device is disabled. +* +* @param InstancePtr is a pointer to the XSysMon instance. +* +* @return None. +* +* @note The device must be configured at hardware build time to include +* interrupt component for this function to work. +* +*****************************************************************************/ +void XSysMon_IntrGlobalDisable(XSysMon *InstancePtr) +{ + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(InstancePtr->Config.IncludeInterrupt == TRUE); + + /* + * Disable the Global Interrupt. + */ + XSysMon_WriteReg(InstancePtr->Config.BaseAddress, XSM_GIER_OFFSET, 0); +} + +/****************************************************************************/ +/** +* +* This function enables the specified interrupts in the device. +* Interrupts enabled using this function will not occur until the global +* interrupt enable bit is set by using the XSysMon_IntrGlobalEnable()function. +* +* @param InstancePtr is a pointer to the XSysMon instance. +* @param Mask is the bit-mask of the interrupts to be enabled. +* Bit positions of 1 will be enabled. Bit positions of 0 will +* keep the previous setting. This mask is formed by OR'ing +* XSM_IPIXR_* bits defined in xsysmon_hw.h. +* +* @return None. +* +* @note The device must be configured at hardware build time to include +* interrupt component for this function to work. +* +*****************************************************************************/ +void XSysMon_IntrEnable(XSysMon *InstancePtr, u32 Mask) +{ + u32 RegValue; + + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(InstancePtr->Config.IncludeInterrupt == TRUE); + + /* + * Enable the specified interrupts in the IPIER. + */ + RegValue = XSysMon_ReadReg(InstancePtr->Config.BaseAddress, + XSM_IPIER_OFFSET); + RegValue |= (Mask & XSM_IPIXR_ALL_MASK); + XSysMon_WriteReg(InstancePtr->Config.BaseAddress, XSM_IPIER_OFFSET, + RegValue); +} + +/****************************************************************************/ +/** +* +* This function disables the specified interrupts in the device. +* +* @param InstancePtr is a pointer to the XSysMon instance. +* @param Mask is the bit-mask of the interrupts to be disabled. +* Bit positions of 1 will be disabled. Bit positions of 0 will +* keep the previous setting. This mask is formed by OR'ing +* XSM_IPIXR_* bits defined in xsysmon_hw.h. +* +* @return None. +* +* @note The device must be configured at hardware build time to include +* interrupt component for this function to work. +* +*****************************************************************************/ +void XSysMon_IntrDisable(XSysMon *InstancePtr, u32 Mask) +{ + u32 RegValue; + + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(InstancePtr->Config.IncludeInterrupt == TRUE); + + /* + * Disable the specified interrupts in the IPIER. + */ + RegValue = XSysMon_ReadReg(InstancePtr->Config.BaseAddress, + XSM_IPIER_OFFSET); + RegValue &= ~(Mask & XSM_IPIXR_ALL_MASK); + XSysMon_WriteReg(InstancePtr->Config.BaseAddress, XSM_IPIER_OFFSET, + RegValue); +} + +/****************************************************************************/ +/** +* +* This function returns the enabled interrupts read from the Interrupt Enable +* Register (IPIER). Use the XSM_IPIXR_* constants defined in xsysmon_hw.h to +* interpret the returned value. +* +* @param InstancePtr is a pointer to the XSysMon instance. +* +* @return A 32-bit value representing the contents of the IPIER. +* +* @note The device must be configured at hardware build time to include +* interrupt component for this function to work. +* +*****************************************************************************/ +u32 XSysMon_IntrGetEnabled(XSysMon *InstancePtr) +{ + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(InstancePtr->Config.IncludeInterrupt == TRUE); + + /* + * Return the value read from the Interrupt Enable Register. + */ + return XSysMon_ReadReg(InstancePtr->Config.BaseAddress, + XSM_IPIER_OFFSET) & XSM_IPIXR_ALL_MASK; +} + +/****************************************************************************/ +/** +* +* This function returns the interrupt status read from Interrupt Status +* Register(IPISR). Use the XSM_IPIXR_* constants defined in xsysmon_hw.h +* to interpret the returned value. +* +* @param InstancePtr is a pointer to the XSysMon instance. +* +* @return A 32-bit value representing the contents of the IPISR. +* +* @note The device must be configured at hardware build time to include +* interrupt component for this function to work. +* +*****************************************************************************/ +u32 XSysMon_IntrGetStatus(XSysMon *InstancePtr) +{ + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(InstancePtr->Config.IncludeInterrupt == TRUE); + + /* + * Return the value read from the Interrupt Status register. + */ + return XSysMon_ReadReg(InstancePtr->Config.BaseAddress, + XSM_IPISR_OFFSET) & XSM_IPIXR_ALL_MASK; +} + +/****************************************************************************/ +/** +* +* This function clears the specified interrupts in the Interrupt Status +* Register (IPISR). +* +* @param InstancePtr is a pointer to the XSysMon instance. +* @param Mask is the bit-mask of the interrupts to be cleared. +* Bit positions of 1 will be cleared. Bit positions of 0 will not +* change the previous interrupt status. This mask is formed by +* OR'ing XSM_IPIXR_* bits which are defined in xsysmon_hw.h. +* +* @return None. +* +* @note The device must be configured at hardware build time to include +* interrupt component for this function to work. +* +*****************************************************************************/ +void XSysMon_IntrClear(XSysMon *InstancePtr, u32 Mask) +{ + u32 RegValue; + + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(InstancePtr->Config.IncludeInterrupt == TRUE); + + /* + * Clear the specified interrupts in the Interrupt Status register. + */ + RegValue = XSysMon_ReadReg(InstancePtr->Config.BaseAddress, + XSM_IPISR_OFFSET); + RegValue &= (Mask & XSM_IPIXR_ALL_MASK); + XSysMon_WriteReg(InstancePtr->Config.BaseAddress, XSM_IPISR_OFFSET, + RegValue); + +} +/** @} */ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/sysmon_v7_5/src/xsysmon_selftest.c b/datalink814_sp/bsp/microblaze_ps/libsrc/sysmon_v7_5/src/xsysmon_selftest.c new file mode 100644 index 0000000..09be407 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/sysmon_v7_5/src/xsysmon_selftest.c @@ -0,0 +1,140 @@ +/****************************************************************************** +* +* Copyright (C) 2007 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xsysmon_selftest.c +* @addtogroup sysmon_v7_5 +* @{ +* +* This file contains a diagnostic self test function for the XSysMon driver. +* The self test function does a simple read/write test of the Alarm Threshold +* Register. +* +* See xsysmon.h for more information. +* +* @note None. +* +*
+*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- -----  -------- -----------------------------------------------------
+* 1.00a xd/sv  05/22/07 First release
+* 4.00a ktn    10/22/09 Updated the file to use the HAL APIs/macros.
+*
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ + +#include "xsysmon.h" + +/************************** Constant Definitions ****************************/ + +/* + * The following constant defines the test value to be written + * to the Alarm Threshold Register + */ +#define XSM_ATR_TEST_VALUE 0x55 + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Variable Definitions ****************************/ + +/************************** Function Prototypes *****************************/ + +/*****************************************************************************/ +/** +* +* Run a self-test on the driver/device. The test +* - Resets the device, +* - Writes a value into the Alarm Threshold register and reads it back +* for comparison. +* - Resets the device again. +* +* +* @param InstancePtr is a pointer to the XSysMon instance. +* +* @return +* - XST_SUCCESS if the value read from the Alarm Threshold +* register is the same as the value written. +* - XST_FAILURE Otherwise +* +* @note This is a destructive test in that resets of the device are +* performed. Refer to the device specification for the +* device status after the reset operation. +* +******************************************************************************/ +int XSysMon_SelfTest(XSysMon *InstancePtr) +{ + int Status; + u32 RegValue; + + /* + * Assert the argument + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + + /* + * Reset the device to get it back to its default state + */ + XSysMon_Reset(InstancePtr); + + /* + * Write a value into the Alarm Threshold registers, read it back, and + * do the comparison + */ + XSysMon_SetAlarmThreshold(InstancePtr, XSM_ATR_VCCINT_UPPER, + XSM_ATR_TEST_VALUE); + RegValue = XSysMon_GetAlarmThreshold(InstancePtr, XSM_ATR_VCCINT_UPPER); + + if (RegValue == XSM_ATR_TEST_VALUE) { + Status = XST_SUCCESS; + } else { + Status = XST_FAILURE; + } + + /* + * Reset the device again to its default state. + */ + XSysMon_Reset(InstancePtr); + + + /* + * Return the test result. + */ + return Status; +} +/** @} */ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/sysmon_v7_5/src/xsysmon_sinit.c b/datalink814_sp/bsp/microblaze_ps/libsrc/sysmon_v7_5/src/xsysmon_sinit.c new file mode 100644 index 0000000..47efeef --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/sysmon_v7_5/src/xsysmon_sinit.c @@ -0,0 +1,99 @@ +/****************************************************************************** +* +* Copyright (C) 2007 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xsysmon_sinit.c +* @addtogroup sysmon_v7_5 +* @{ +* +* This file contains the implementation of the XSysMon driver's static +* initialization functionality. +* +* @note None. +* +*
+*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- -----  -------- -----------------------------------------------------
+* 1.00a xd/sv  05/22/07 First release
+*
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xparameters.h" +#include "xsysmon.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ +extern XSysMon_Config XSysMon_ConfigTable[]; + +/*****************************************************************************/ +/** +* +* This function looks up the device configuration based on the unique device ID. +* The table XSysMon_ConfigTable contains the configuration info for each device +* in the system. +* +* @param DeviceId contains the ID of the device for which the +* device configuration pointer is to be returned. +* +* @return +* - A pointer to the configuration found. +* - NULL if the specified device ID was not found. +* +* @note None. +* +******************************************************************************/ +XSysMon_Config *XSysMon_LookupConfig(u16 DeviceId) +{ + XSysMon_Config *CfgPtr = NULL; + u32 Index; + + for (Index=0; Index < XPAR_XSYSMON_NUM_INSTANCES; Index++) { + if (XSysMon_ConfigTable[Index].DeviceId == DeviceId) { + CfgPtr = &XSysMon_ConfigTable[Index]; + break; + } + } + + return CfgPtr; +} +/** @} */ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/tmrctr_v4_5/src/Makefile b/datalink814_sp/bsp/microblaze_ps/libsrc/tmrctr_v4_5/src/Makefile new file mode 100644 index 0000000..e26ed30 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/tmrctr_v4_5/src/Makefile @@ -0,0 +1,28 @@ +COMPILER= +ARCHIVER= +CP=cp +COMPILER_FLAGS= +EXTRA_COMPILER_FLAGS= +LIB=libxil.a + +RELEASEDIR=../../../lib +INCLUDEDIR=../../../include +INCLUDES=-I./. -I${INCLUDEDIR} + +OUTS = *.o +OBJECTS = $(addsuffix .o, $(basename $(wildcard *.c))) +LIBSOURCES=*.c +INCLUDEFILES=*.h + +libs: + echo "Compiling tmrctr" + $(COMPILER) $(COMPILER_FLAGS) $(EXTRA_COMPILER_FLAGS) $(INCLUDES) $(LIBSOURCES) + $(ARCHIVER) -r ${RELEASEDIR}/${LIB} $(OBJECTS) + make clean + +include: + ${CP} $(INCLUDEFILES) $(INCLUDEDIR) + +clean: + rm -rf ${OBJECTS} + diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/tmrctr_v4_5/src/xtmrctr.c b/datalink814_sp/bsp/microblaze_ps/libsrc/tmrctr_v4_5/src/xtmrctr.c new file mode 100644 index 0000000..9e2a0ed --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/tmrctr_v4_5/src/xtmrctr.c @@ -0,0 +1,726 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xtmrctr.c +* @addtogroup tmrctr_v4_6 +* @{ +* +* Contains required functions for the XTmrCtr driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a ecm  08/16/01 First release
+* 1.00b jhl  02/21/02 Repartitioned the driver for smaller files
+* 1.10b mta  03/21/07 Updated to new coding style
+* 2.00a ktn  10/30/09 Updated to use HAL API's. _m is removed from all the macro
+*		      definitions.
+* 2.05a adk  15/05/13 Fixed the CR:693066
+*		      Added the IsStartedTmrCtr0/IsStartedTmrCtr1 members to the
+*		      XTmrCtr instance structure.
+*		      The IsStartedTmrCtrX will be assigned XIL_COMPONENT_IS_STARTED in
+*		      the XTmrCtr_Start function.
+*		      The IsStartedTmrCtrX will be cleared in the XTmrCtr_Stop function.
+*		      There will be no Initialization done in the
+*		      XTmrCtr_Initialize if both the timers have already started and
+*		      the XST_DEVICE_IS_STARTED Status is returned.
+*		      Removed the logic in the XTmrCtr_Initialize function
+*		      which was checking the Register Value to know whether
+*		      a timer has started or not.
+* 4.0   als  09/30/15 Updated initialization API.
+* 4.1   sk   11/10/15 Used UINTPTR instead of u32 for Baseaddress CR# 867425.
+*                     Changed the prototype of XTmrCtr_CfgInitialize API.
+* 4.5   cjp  03/22/18 Added APIs to support PWM feature. XTmrCtr_PwmConfigure
+*                     is used to configure PWM to operate for specific period
+*                     and high time. XTmrCtr_PwmEnable and XTmrCtr_PwmDisable
+*                     are used to enable/disable the PWM output.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xstatus.h" +#include "xparameters.h" +#include "xtmrctr.h" +#include "xtmrctr_i.h" + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + +static void XTmrCtr_StubCallback(void *CallBackRef, u8 TmrCtrNumber); + +/************************** Variable Definitions *****************************/ + +/*****************************************************************************/ +/** +* This function populates the timer counter's configuration structure and sets +* some configurations defaults. +* +* @param InstancePtr is a pointer to the XTmrCtr instance. +* @param ConfigPtr is a pointer to the configuration structure that will +* be used to copy the settings from. +* @param EffectiveAddr is the device base address in the virtual memory +* space. If the address translation is not used, then the physical +* address is passed. +* +* @return None. +* +* @note Unexpected errors may occur if the address mapping is changed +* after this function is invoked. +* +******************************************************************************/ +void XTmrCtr_CfgInitialize(XTmrCtr *InstancePtr, XTmrCtr_Config *ConfigPtr, + UINTPTR EffectiveAddr) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(ConfigPtr != NULL); + Xil_AssertVoid(EffectiveAddr != 0x0); + + InstancePtr->IsReady = 0; + InstancePtr->Config = *ConfigPtr; + + InstancePtr->Config.BaseAddress = EffectiveAddr; + InstancePtr->BaseAddress = EffectiveAddr; + + InstancePtr->Handler = XTmrCtr_StubCallback; + InstancePtr->CallBackRef = InstancePtr; + InstancePtr->Stats.Interrupts = 0; + + InstancePtr->IsReady = XIL_COMPONENT_IS_READY; +} + +/*****************************************************************************/ +/** +* (Re-)initialzes all timer counters which aren't started already. +* +* @param InstancePtr is a pointer to the XTmrCtr instance. +* +* @return +* - XST_SUCCESS if at least one timer counter is stopped. +* - XST_DEVICE_IS_STARTED otherwise. +* +* @note None. +* +******************************************************************************/ +int XTmrCtr_InitHw(XTmrCtr *InstancePtr) +{ + int Status = XST_DEVICE_IS_STARTED; + u8 TmrIndex; + u32 TmrCtrStarted[XTC_DEVICE_TIMER_COUNT]; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + TmrCtrStarted[0] = InstancePtr->IsStartedTmrCtr0; + TmrCtrStarted[1] = InstancePtr->IsStartedTmrCtr1; + + for (TmrIndex = 0; TmrIndex < XTC_DEVICE_TIMER_COUNT; TmrIndex++) { + /* Only initialize timers counters which aren't started. */ + if (TmrCtrStarted[TmrIndex] == XIL_COMPONENT_IS_STARTED) { + continue; + } + + /* Set the compare register to 0. */ + XTmrCtr_WriteReg(InstancePtr->BaseAddress, TmrIndex, + XTC_TLR_OFFSET, 0); + /* Reset the timer and the interrupt. */ + XTmrCtr_WriteReg(InstancePtr->BaseAddress, TmrIndex, + XTC_TCSR_OFFSET, + XTC_CSR_INT_OCCURED_MASK | XTC_CSR_LOAD_MASK); + /* Release the reset. */ + XTmrCtr_WriteReg(InstancePtr->BaseAddress, TmrIndex, + XTC_TCSR_OFFSET, 0); + + /* Indicate that at least one timer is not running and has been + * initialized. */ + Status = XST_SUCCESS; + } + + return Status; +} + +/*****************************************************************************/ +/** +* Initializes a specific timer/counter instance/driver. Initialize fields of +* the XTmrCtr structure, then reset the timer/counter.If a timer is already +* running then it is not initialized. +* +* +* @param InstancePtr is a pointer to the XTmrCtr instance. +* @param DeviceId is the unique id of the device controlled by this +* XTmrCtr component. Passing in a device id associates the +* generic XTmrCtr component to a specific device, as chosen by +* the caller or application developer. +* +* @return +* - XST_SUCCESS if initialization was successful +* - XST_DEVICE_IS_STARTED if the device has already been started +* - XST_DEVICE_NOT_FOUND if the device doesn't exist +* +* @note None. +* +******************************************************************************/ +int XTmrCtr_Initialize(XTmrCtr *InstancePtr, u16 DeviceId) +{ + XTmrCtr_Config *ConfigPtr; + + Xil_AssertNonvoid(InstancePtr != NULL); + + /* In case all timer counters are already started, don't proceed with + * re-initialization. */ + if ((InstancePtr->IsStartedTmrCtr0 == XIL_COMPONENT_IS_STARTED) && + (InstancePtr->IsStartedTmrCtr1 == XIL_COMPONENT_IS_STARTED)) { + return XST_DEVICE_IS_STARTED; + } + + /* Retrieve configuration of timer counter core with matching ID. */ + ConfigPtr = XTmrCtr_LookupConfig(DeviceId); + if (!ConfigPtr) { + return XST_DEVICE_NOT_FOUND; + } + + XTmrCtr_CfgInitialize(InstancePtr, ConfigPtr, ConfigPtr->BaseAddress); + + return XTmrCtr_InitHw(InstancePtr); +} + +/*****************************************************************************/ +/** +* +* Starts the specified timer counter of the device such that it starts running. +* The timer counter is reset before it is started and the reset value is +* loaded into the timer counter. +* +* If interrupt mode is specified in the options, it is necessary for the caller +* to connect the interrupt handler of the timer/counter to the interrupt source, +* typically an interrupt controller, and enable the interrupt within the +* interrupt controller. +* +* @param InstancePtr is a pointer to the XTmrCtr instance. +* @param TmrCtrNumber is the timer counter of the device to operate on. +* Each device may contain multiple timer counters. The timer +* number is a zero based number with a range of +* 0 - (XTC_DEVICE_TIMER_COUNT - 1). +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XTmrCtr_Start(XTmrCtr * InstancePtr, u8 TmrCtrNumber) +{ + u32 ControlStatusReg; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(TmrCtrNumber < XTC_DEVICE_TIMER_COUNT); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the current register contents such that only the necessary bits + * of the register are modified in the following operations + */ + ControlStatusReg = XTmrCtr_ReadReg(InstancePtr->BaseAddress, + TmrCtrNumber, XTC_TCSR_OFFSET); + /* + * Reset the timer counter such that it reloads from the compare + * register and the interrupt is cleared simultaneously, the interrupt + * can only be cleared after reset such that the interrupt condition is + * cleared + */ + XTmrCtr_WriteReg(InstancePtr->BaseAddress, TmrCtrNumber, + XTC_TCSR_OFFSET, + XTC_CSR_LOAD_MASK); + + + + /* + * Indicate that the timer is started before enabling it + */ + if (TmrCtrNumber == 0) { + InstancePtr->IsStartedTmrCtr0 = XIL_COMPONENT_IS_STARTED; + } else { + InstancePtr->IsStartedTmrCtr1 = XIL_COMPONENT_IS_STARTED; + } + + + /* + * Remove the reset condition such that the timer counter starts running + * with the value loaded from the compare register + */ + XTmrCtr_WriteReg(InstancePtr->BaseAddress, TmrCtrNumber, + XTC_TCSR_OFFSET, + ControlStatusReg | XTC_CSR_ENABLE_TMR_MASK); +} + +/*****************************************************************************/ +/** +* +* Stops the timer counter by disabling it. +* +* It is the callers' responsibility to disconnect the interrupt handler of the +* timer_counter from the interrupt source, typically an interrupt controller, +* and disable the interrupt within the interrupt controller. +* +* @param InstancePtr is a pointer to the XTmrCtr instance. +* @param TmrCtrNumber is the timer counter of the device to operate on. +* Each device may contain multiple timer counters. The timer +* number is a zero based number with a range of +* 0 - (XTC_DEVICE_TIMER_COUNT - 1). +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XTmrCtr_Stop(XTmrCtr * InstancePtr, u8 TmrCtrNumber) +{ + u32 ControlStatusReg; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(TmrCtrNumber < XTC_DEVICE_TIMER_COUNT); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the current register contents + */ + ControlStatusReg = XTmrCtr_ReadReg(InstancePtr->BaseAddress, + TmrCtrNumber, XTC_TCSR_OFFSET); + /* + * Disable the timer counter such that it's not running + */ + ControlStatusReg &= ~(XTC_CSR_ENABLE_TMR_MASK); + + /* + * Write out the updated value to the actual register. + */ + XTmrCtr_WriteReg(InstancePtr->BaseAddress, TmrCtrNumber, + XTC_TCSR_OFFSET, ControlStatusReg); + + /* + * Indicate that the timer is stopped + */ + if (TmrCtrNumber == 0) { + InstancePtr->IsStartedTmrCtr0 = 0; + } else { + InstancePtr->IsStartedTmrCtr1 = 0; + } +} + +/*****************************************************************************/ +/** +* +* Get the current value of the specified timer counter. The timer counter +* may be either incrementing or decrementing based upon the current mode of +* operation. +* +* @param InstancePtr is a pointer to the XTmrCtr instance. +* @param TmrCtrNumber is the timer counter of the device to operate on. +* Each device may contain multiple timer counters. The timer +* number is a zero based number with a range of +* 0 - (XTC_DEVICE_TIMER_COUNT - 1). +* +* @return The current value for the timer counter. +* +* @note None. +* +******************************************************************************/ +u32 XTmrCtr_GetValue(XTmrCtr * InstancePtr, u8 TmrCtrNumber) +{ + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(TmrCtrNumber < XTC_DEVICE_TIMER_COUNT); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + return XTmrCtr_ReadReg(InstancePtr->BaseAddress, + TmrCtrNumber, XTC_TCR_OFFSET); +} + +/*****************************************************************************/ +/** +* +* Set the reset value for the specified timer counter. This is the value +* that is loaded into the timer counter when it is reset. This value is also +* loaded when the timer counter is started. +* +* @param InstancePtr is a pointer to the XTmrCtr instance. +* @param TmrCtrNumber is the timer counter of the device to operate on. +* Each device may contain multiple timer counters. The timer +* number is a zero based number with a range of +* 0 - (XTC_DEVICE_TIMER_COUNT - 1). +* @param ResetValue contains the value to be used to reset the timer +* counter. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XTmrCtr_SetResetValue(XTmrCtr * InstancePtr, u8 TmrCtrNumber, + u32 ResetValue) +{ + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(TmrCtrNumber < XTC_DEVICE_TIMER_COUNT); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + XTmrCtr_WriteReg(InstancePtr->BaseAddress, TmrCtrNumber, + XTC_TLR_OFFSET, ResetValue); +} + +/*****************************************************************************/ +/** +* +* Returns the timer counter value that was captured the last time the external +* capture input was asserted. +* +* @param InstancePtr is a pointer to the XTmrCtr instance. +* @param TmrCtrNumber is the timer counter of the device to operate on. +* Each device may contain multiple timer counters. The timer +* number is a zero based number with a range of +* 0 - (XTC_DEVICE_TIMER_COUNT - 1). +* +* @return The current capture value for the indicated timer counter. +* +* @note None. +* +*******************************************************************************/ +u32 XTmrCtr_GetCaptureValue(XTmrCtr * InstancePtr, u8 TmrCtrNumber) +{ + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(TmrCtrNumber < XTC_DEVICE_TIMER_COUNT); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + return XTmrCtr_ReadReg(InstancePtr->BaseAddress, + TmrCtrNumber, XTC_TLR_OFFSET); +} + +/*****************************************************************************/ +/** +* +* Resets the specified timer counter of the device. A reset causes the timer +* counter to set it's value to the reset value. +* +* @param InstancePtr is a pointer to the XTmrCtr instance. +* @param TmrCtrNumber is the timer counter of the device to operate on. +* Each device may contain multiple timer counters. The timer +* number is a zero based number with a range of +* 0 - (XTC_DEVICE_TIMER_COUNT - 1). +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XTmrCtr_Reset(XTmrCtr * InstancePtr, u8 TmrCtrNumber) +{ + u32 CounterControlReg; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(TmrCtrNumber < XTC_DEVICE_TIMER_COUNT); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read current contents of the register so it won't be destroyed + */ + CounterControlReg = XTmrCtr_ReadReg(InstancePtr->BaseAddress, + TmrCtrNumber, XTC_TCSR_OFFSET); + /* + * Reset the timer by toggling the reset bit in the register + */ + XTmrCtr_WriteReg(InstancePtr->BaseAddress, TmrCtrNumber, + XTC_TCSR_OFFSET, + CounterControlReg | XTC_CSR_LOAD_MASK); + + XTmrCtr_WriteReg(InstancePtr->BaseAddress, TmrCtrNumber, + XTC_TCSR_OFFSET, CounterControlReg); +} + +/*****************************************************************************/ +/** +* +* Checks if the specified timer counter of the device has expired. In capture +* mode, expired is defined as a capture occurred. In compare mode, expired is +* defined as the timer counter rolled over/under for up/down counting. +* +* When interrupts are enabled, the expiration causes an interrupt. This function +* is typically used to poll a timer counter to determine when it has expired. +* +* @param InstancePtr is a pointer to the XTmrCtr instance. +* @param TmrCtrNumber is the timer counter of the device to operate on. +* Each device may contain multiple timer counters. The timer +* number is a zero based number with a range of +* 0 - (XTC_DEVICE_TIMER_COUNT - 1). +* +* @return TRUE if the timer has expired, and FALSE otherwise. +* +* @note None. +* +******************************************************************************/ +int XTmrCtr_IsExpired(XTmrCtr * InstancePtr, u8 TmrCtrNumber) +{ + u32 CounterControlReg; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(TmrCtrNumber < XTC_DEVICE_TIMER_COUNT); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Check if timer is expired + */ + CounterControlReg = XTmrCtr_ReadReg(InstancePtr->BaseAddress, + TmrCtrNumber, XTC_TCSR_OFFSET); + + return ((CounterControlReg & XTC_CSR_INT_OCCURED_MASK) == + XTC_CSR_INT_OCCURED_MASK); +} + +/*****************************************************************************/ +/** +* +* Configures timers to generate PWM output. +* +* @param InstancePtr is a pointer to the XTmrCtr instance. +* @param PwmPeriod is the period of pwm signal in nano seconds. +* @param PwmHighTime is the high time of pwm signal in nano seconds. +* +* @return the duty cycle that will possibly be achieved. +* +* @note This function needs to be called before enabling PWM otherwise +* the output of PWM may be indeterminate. Here Down count mode of +* timers are used for generating PWM output. +* +******************************************************************************/ +u8 XTmrCtr_PwmConfigure(XTmrCtr *InstancePtr, u32 PwmPeriod, u32 PwmHighTime) +{ + u32 CounterControlReg; + u32 SysClkPeriod; + u64 Period; + u64 High; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* Stop the timers if they are running */ + if (InstancePtr->IsStartedTmrCtr0 == XIL_COMPONENT_IS_STARTED) { + XTmrCtr_Stop(InstancePtr, XTC_TIMER_0); + } + if (InstancePtr->IsStartedTmrCtr1 == XIL_COMPONENT_IS_STARTED) { + XTmrCtr_Stop(InstancePtr, XTC_TIMER_1); + } + + /* Configure timers modes to be used for PWM */ + CounterControlReg = XTmrCtr_ReadReg(InstancePtr->BaseAddress, + XTC_TIMER_0, XTC_TCSR_OFFSET); + CounterControlReg |= + (XTC_CSR_DOWN_COUNT_MASK | XTC_CSR_AUTO_RELOAD_MASK); + CounterControlReg &= ~(XTC_CSR_CASC_MASK | XTC_CSR_EXT_GENERATE_MASK); + XTmrCtr_WriteReg(InstancePtr->BaseAddress, XTC_TIMER_0, + XTC_TCSR_OFFSET, CounterControlReg); + + CounterControlReg = XTmrCtr_ReadReg(InstancePtr->BaseAddress, + XTC_TIMER_1, XTC_TCSR_OFFSET); + CounterControlReg |= + (XTC_CSR_DOWN_COUNT_MASK | XTC_CSR_AUTO_RELOAD_MASK); + CounterControlReg &= ~(XTC_CSR_CASC_MASK | XTC_CSR_EXT_GENERATE_MASK); + XTmrCtr_WriteReg(InstancePtr->BaseAddress, XTC_TIMER_1, + XTC_TCSR_OFFSET, CounterControlReg); + + /* Set period and high time for PWM */ + SysClkPeriod = XTC_HZ_TO_NS(InstancePtr->Config.SysClockFreqHz); + if (PwmPeriod < PwmHighTime || + PwmPeriod < (2 * SysClkPeriod) || + PwmHighTime < (2 * SysClkPeriod)) { + return XST_INVALID_PARAM; + } + + Period = XTC_ROUND_DIV(PwmPeriod, SysClkPeriod) - 2; + High = XTC_ROUND_DIV(PwmHighTime, SysClkPeriod) - 2; + if (Period > XTC_MAX_LOAD_VALUE) { + return XST_INVALID_PARAM; + } + + XTmrCtr_WriteReg(InstancePtr->BaseAddress, XTC_TIMER_0, + XTC_TLR_OFFSET, (u32)Period); + XTmrCtr_WriteReg(InstancePtr->BaseAddress, XTC_TIMER_1, + XTC_TLR_OFFSET, (u32)High); + + /* Configure timers in generate mode */ + CounterControlReg = XTmrCtr_ReadReg(InstancePtr->BaseAddress, + XTC_TIMER_0, XTC_TCSR_OFFSET); + CounterControlReg &= ~(XTC_CSR_CAPTURE_MODE_MASK); + XTmrCtr_WriteReg(InstancePtr->BaseAddress, XTC_TIMER_0, + XTC_TCSR_OFFSET, CounterControlReg); + CounterControlReg = XTmrCtr_ReadReg(InstancePtr->BaseAddress, + XTC_TIMER_1, XTC_TCSR_OFFSET); + CounterControlReg &= ~(XTC_CSR_CAPTURE_MODE_MASK); + XTmrCtr_WriteReg(InstancePtr->BaseAddress, XTC_TIMER_1, + XTC_TCSR_OFFSET, CounterControlReg); + + return (((float)High / Period * 100)); +} + +/*****************************************************************************/ +/** +* +* Enables the PWM output as per configurations set by XTmrCtr_PwmConfigure. +* +* @param InstancePtr is a pointer to the XTmrCtr instance. +* +* @return none. +* +* @note none. +* +******************************************************************************/ +void XTmrCtr_PwmEnable(XTmrCtr *InstancePtr) +{ + u32 CounterControlReg; + + Xil_AssertVoid(InstancePtr != NULL); + + /* PWM already running */ + if (InstancePtr->IsPwmEnabled) { + return; + } + + /* Enable PWM, Generate Out */ + CounterControlReg = XTmrCtr_ReadReg(InstancePtr->BaseAddress, + XTC_TIMER_0, XTC_TCSR_OFFSET); + CounterControlReg |= + (XTC_CSR_ENABLE_PWM_MASK | XTC_CSR_EXT_GENERATE_MASK); + XTmrCtr_WriteReg(InstancePtr->BaseAddress, XTC_TIMER_0, + XTC_TCSR_OFFSET, CounterControlReg); + + CounterControlReg = XTmrCtr_ReadReg(InstancePtr->BaseAddress, + XTC_TIMER_1, XTC_TCSR_OFFSET); + CounterControlReg |= + (XTC_CSR_ENABLE_PWM_MASK | XTC_CSR_EXT_GENERATE_MASK); + XTmrCtr_WriteReg(InstancePtr->BaseAddress, XTC_TIMER_1, + XTC_TCSR_OFFSET, CounterControlReg); + + /* Reset Counters */ + XTmrCtr_Reset(InstancePtr, XTC_TIMER_0); + XTmrCtr_Reset(InstancePtr, XTC_TIMER_1); + + /* Enable all timers */ + CounterControlReg = XTmrCtr_ReadReg(InstancePtr->BaseAddress, + XTC_TIMER_0, XTC_TCSR_OFFSET); + CounterControlReg |= XTC_CSR_ENABLE_ALL_MASK; + XTmrCtr_WriteReg(InstancePtr->BaseAddress, XTC_TIMER_0, + XTC_TCSR_OFFSET, CounterControlReg); + + InstancePtr->IsPwmEnabled = TRUE; +} + +/*****************************************************************************/ +/** +* +* Disables the PWM output. +* +* @param InstancePtr is a pointer to the XTmrCtr instance. +* +* @return none. +* +* @note Call to this function disables only the PWM output and do not +* alter any configuration. PWM output can again be enabled by +* calling XTmrCtr_PwmEnable without the need of re-configuration. +* +******************************************************************************/ +void XTmrCtr_PwmDisable(XTmrCtr *InstancePtr) +{ + u32 CounterControlReg; + + Xil_AssertVoid(InstancePtr != NULL); + + /* PWM already disabled */ + if (!InstancePtr->IsPwmEnabled) { + return; + } + + /* Disable timers */ + XTmrCtr_Stop(InstancePtr, XTC_TIMER_0); + XTmrCtr_Stop(InstancePtr, XTC_TIMER_1); + + /* Reset Counters */ + XTmrCtr_Reset(InstancePtr, XTC_TIMER_0); + XTmrCtr_Reset(InstancePtr, XTC_TIMER_1); + + /* Disable PWM, Generate Out */ + CounterControlReg = XTmrCtr_ReadReg(InstancePtr->BaseAddress, + XTC_TIMER_0, XTC_TCSR_OFFSET); + CounterControlReg &= + ~(XTC_CSR_ENABLE_PWM_MASK | XTC_CSR_EXT_GENERATE_MASK); + XTmrCtr_WriteReg(InstancePtr->BaseAddress, XTC_TIMER_0, + XTC_TCSR_OFFSET, CounterControlReg); + + CounterControlReg = XTmrCtr_ReadReg(InstancePtr->BaseAddress, + XTC_TIMER_1, XTC_TCSR_OFFSET); + CounterControlReg &= + ~(XTC_CSR_ENABLE_PWM_MASK | XTC_CSR_EXT_GENERATE_MASK); + XTmrCtr_WriteReg(InstancePtr->BaseAddress, XTC_TIMER_1, + XTC_TCSR_OFFSET, CounterControlReg); + + InstancePtr->IsPwmEnabled = FALSE; +} + +/*****************************************************************************/ +/** +* Default callback for the driver does nothing. It matches the signature of the +* XTmrCtr_Handler type. +* +* @param CallBackRef is a pointer to the callback's data. +* @param TmrCtrNumber is the ID of the timer counter which a user-defined +* callback would normally operate on. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +static void XTmrCtr_StubCallback(void *CallBackRef, u8 TmrCtrNumber) +{ + Xil_AssertVoid(CallBackRef != NULL); + Xil_AssertVoid(TmrCtrNumber < XTC_DEVICE_TIMER_COUNT); +} + +/** @} */ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/tmrctr_v4_5/src/xtmrctr.h b/datalink814_sp/bsp/microblaze_ps/libsrc/tmrctr_v4_5/src/xtmrctr.h new file mode 100644 index 0000000..7fe108d --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/tmrctr_v4_5/src/xtmrctr.h @@ -0,0 +1,326 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xtmrctr.h +* @addtogroup tmrctr_v4_6 +* @{ +* @details +* +* The Xilinx timer/counter component. This component supports the Xilinx +* timer/counter. More detailed description of the driver operation can +* be found in the xtmrctr.c file. +* +* The Xilinx timer/counter supports the following features: +* - Polled mode. +* - Interrupt driven mode +* - enabling and disabling specific timers +* - PWM operation +* - Cascade Operation (This is to be used for getting a 64 bit timer and this +* feature is present in the latest versions of the axi_timer IP) +* +* The timer counter operates in 2 primary modes, compare and capture. In +* either mode, the timer counter may count up or down, with up being the +* default. +* +* Compare mode is typically used for creating a single time period or multiple +* repeating time periods in the auto reload mode, such as a periodic interrupt. +* When started, the timer counter loads an initial value, referred to as the +* compare value, into the timer counter and starts counting down or up. The +* timer counter expires when it rolls over/under depending upon the mode of +* counting. An external compare output signal may be configured such that a +* pulse is generated with this signal when it hits the compare value. +* +* Capture mode is typically used for measuring the time period between +* external events. This mode uses an external capture input signal to cause +* the value of the timer counter to be captured. When started, the timer +* counter loads an initial value, referred to as the compare value, + +* The timer can be configured to either cause an interrupt when the count +* reaches the compare value in compare mode or latch the current count +* value in the capture register when an external input is asserted +* in capture mode. The external capture input can be enabled/disabled using the +* XTmrCtr_SetOptions function. While in compare mode, it is also possible to +* drive an external output when the compare value is reached in the count +* register The external compare output can be enabled/disabled using the +* XTmrCtr_SetOptions function. +* +* Interrupts +* +* It is the responsibility of the application to connect the interrupt +* handler of the timer/counter to the interrupt source. The interrupt +* handler function, XTmrCtr_InterruptHandler, is visible such that the user +* can connect it to the interrupt source. Note that this interrupt handler +* does not provide interrupt context save and restore processing, the user +* must perform this processing. +* +* The driver services interrupts and passes timeouts to the upper layer +* software through callback functions. The upper layer software must register +* its callback functions during initialization. The driver requires callback +* functions for timers. +* +* @note +* The default settings for the timers are: +* - Interrupt generation disabled +* - Count up mode +* - Compare mode +* - Hold counter (will not reload the timer) +* - External compare output disabled +* - External capture input disabled +* - Pulse width modulation disabled +* - Timer disabled, waits for Start function to be called +*

+* A timer counter device may contain multiple timer counters. The symbol +* XTC_DEVICE_TIMER_COUNT defines the number of timer counters in the device. +* The device currently contains 2 timer counters. +*

+* This driver is intended to be RTOS and processor independent. It works with +* physical addresses only. Any needs for dynamic memory management, threads +* or thread mutual exclusion, virtual memory, or cache control must be +* satisfied by the layer above this driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a ecm  08/16/01 First release
+* 1.00b jhl  02/21/02 Repartitioned the driver for smaller files
+* 1.10b mta  03/21/07 Updated to new coding style.
+* 1.11a sdm  08/22/08 Removed support for static interrupt handlers from the MDD
+*		      file
+* 2.00a ktn  10/30/09 Updated to use HAL API's. _m is removed from all the macro
+*		      definitions.
+* 2.01a ktn  07/12/10 Renamed the macro XTimerCtr_ReadReg as XTmrCtr_ReadReg
+*		      for naming consistency (CR 559142).
+* 2.02a sdm  09/28/10 Updated the driver tcl to generate the xparameters
+*		      for the timer clock frequency (CR 572679).
+* 2.03a rvo  11/30/10 Added check to see if interrupt is enabled before further
+*		      processing for CR 584557.
+* 2.04a sdm  07/12/11 Added support for cascade mode operation.
+* 		      The cascade mode of operation is present in the latest
+*		      versions of the axi_timer IP. Please check the HW
+*		      Datasheet to see whether this feature is present in the
+*		      version of the IP that you are using.
+* 2.05a adk  15/05/13 Fixed the CR:693066
+*		      Added the IsStartedTmrCtr0/IsStartedTmrCtr1 members to the
+*		      XTmrCtr instance structure.
+*		      The IsStartedTmrCtrX will be assigned XIL_COMPONENT_IS_STARTED in
+*		      the XTmrCtr_Start function.
+*		      The IsStartedTmrCtrX will be cleared in the XTmrCtr_Stop function.
+*		      There will be no Initialization done in the
+*		      XTmrCtr_Initialize if both the timers have already started and
+*		      the XST_DEVICE_IS_STARTED Status is returned.
+*		      Removed the logic in the XTmrCtr_Initialize function
+*		      which was checking the Register Value to know whether
+*		      a timer has started or not.
+* 3.0   adk  19/12/13 Updated as per the New Tcl API's
+* 4.0   als  09/30/15 Updated initialization API.
+* 4.1   sk   11/10/15 Used UINTPTR instead of u32 for Baseaddress CR# 867425.
+*                     Changed the prototype of XTmrCtr_CfgInitialize API.
+* 4.2   nsk  15/09/16 Updated tcl, to get correct device id for canonical defines,
+*                     when there exist more than one timer perepheral
+*       ms   01/23/17 Added xil_printf statement in main function for all
+*                     examples to ensure that "Successfully ran" and "Failed"
+*                     strings are available in all examples. This is a fix
+*                     for CR-965028.
+*       ms   03/17/17 Added readme.txt file in examples folder for doxygen
+*                     generation.
+* 4.4   ms   04/18/17 Modified tcl file to add suffix U for all macros
+*                     definitions of tmrctr in xparameters.h
+* 4.5   cjp  03/22/18 Added APIs to support PWM feature. XTmrCtr_PwmConfigure
+*                     is used to configure PWM to operate for specific period
+*                     and high time. XTmrCtr_PwmEnable and XTmrCtr_PwmDisable
+*                     are used to enable/disable the PWM output.
+* 4.6   mus  03/13/19 tmrctr_tapp tcl is updated to support scenario where
+*                     AXI TIMER is interrupting ARM processor through more
+*                     than one interrupt pin. Fix for CR#1024699
+* 
+* +******************************************************************************/ + +#ifndef XTMRCTR_H /* prevent circular inclusions */ +#define XTMRCTR_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xstatus.h" +#include "xtmrctr_l.h" + +/************************** Constant Definitions *****************************/ + +/** + * @name Configuration options + * These options are used in XTmrCtr_SetOptions() and XTmrCtr_GetOptions() + * @{ + */ +/** + * Used to configure the timer counter device. + *
+ * XTC_CASCADE_MODE_OPTION	Enables the Cascade Mode only valid for TCSRO.
+ * XTC_ENABLE_ALL_OPTION	Enables all timer counters at once.
+ * XTC_DOWN_COUNT_OPTION	Configures the timer counter to count down from
+ *				start value, the default is to count up.
+ * XTC_CAPTURE_MODE_OPTION	Configures the timer to capture the timer
+ *				counter value when the external capture line is
+ *				asserted. The default mode is compare mode.
+ * XTC_INT_MODE_OPTION		Enables the timer counter interrupt output.
+ * XTC_AUTO_RELOAD_OPTION	In compare mode, configures the timer counter to
+ *				reload from the compare value. The default mode
+ *				causes the timer counter to hold when the
+ *				compare value is hit.
+ *				In capture mode, configures the timer counter to
+ *				not hold the previous capture value if a new
+ *				event occurs. The default mode cause the timer
+ *				counter to hold the capture value until
+ *				recognized.
+ * XTC_EXT_COMPARE_OPTION	Enables the external compare output signal.
+ * 
+ */ +#define XTC_CASCADE_MODE_OPTION 0x00000080UL +#define XTC_ENABLE_ALL_OPTION 0x00000040UL +#define XTC_DOWN_COUNT_OPTION 0x00000020UL +#define XTC_CAPTURE_MODE_OPTION 0x00000010UL +#define XTC_INT_MODE_OPTION 0x00000008UL +#define XTC_AUTO_RELOAD_OPTION 0x00000004UL +#define XTC_EXT_COMPARE_OPTION 0x00000002UL +/*@}*/ + +/* Round division */ +#define XTC_ROUND_DIV(a, b) ((a + (b / 2)) / b) + +/* Convert clock frequency in hertz to period in nano seconds */ +#define XTC_HZ_TO_NS(Hz) XTC_ROUND_DIV(1000000000, Hz) + +/**************************** Type Definitions *******************************/ + +/** + * This typedef contains configuration information for the device. + */ +typedef struct { + u16 DeviceId; /**< Unique ID of device */ + UINTPTR BaseAddress; /**< Register base address */ + u32 SysClockFreqHz; /**< The AXI bus clock frequency */ +} XTmrCtr_Config; + +/** + * Signature for the callback function. + * + * @param CallBackRef is a callback reference passed in by the upper layer + * when setting the callback functions, and passed back to the + * upper layer when the callback is invoked. Its type is + * unimportant to the driver, so it is a void pointer. + * @param TmrCtrNumber is the number of the timer/counter within the + * device. The device typically contains at least two + * timer/counters. The timer number is a zero based number with a + * range of 0 to (XTC_DEVICE_TIMER_COUNT - 1). + */ +typedef void (*XTmrCtr_Handler) (void *CallBackRef, u8 TmrCtrNumber); + + +/** + * Timer/Counter statistics + */ +typedef struct { + u32 Interrupts; /**< The number of interrupts that have occurred */ +} XTmrCtrStats; + +/** + * The XTmrCtr driver instance data. The user is required to allocate a + * variable of this type for every timer/counter device in the system. A + * pointer to a variable of this type is then passed to the driver API + * functions. + */ +typedef struct { + XTmrCtr_Config Config; /**< Core configuration. */ + XTmrCtrStats Stats; /**< Component Statistics */ + UINTPTR BaseAddress; /**< Base address of registers */ + u32 IsReady; /**< Device is initialized and ready */ + u32 IsStartedTmrCtr0; /**< Is Timer Counter 0 started */ + u32 IsStartedTmrCtr1; /**< Is Timer Counter 1 started */ + u32 IsPwmEnabled; /**< Is PWM Enabled */ + + XTmrCtr_Handler Handler; /**< Callback function */ + void *CallBackRef; /**< Callback reference for handler */ +} XTmrCtr; + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + +/* Required functions, in file xtmrctr.c */ +void XTmrCtr_CfgInitialize(XTmrCtr *InstancePtr, XTmrCtr_Config *ConfigPtr, + UINTPTR EffectiveAddr); +int XTmrCtr_InitHw(XTmrCtr *InstancePtr); +int XTmrCtr_Initialize(XTmrCtr * InstancePtr, u16 DeviceId); +void XTmrCtr_Start(XTmrCtr * InstancePtr, u8 TmrCtrNumber); +void XTmrCtr_Stop(XTmrCtr * InstancePtr, u8 TmrCtrNumber); +u32 XTmrCtr_GetValue(XTmrCtr * InstancePtr, u8 TmrCtrNumber); +void XTmrCtr_SetResetValue(XTmrCtr * InstancePtr, u8 TmrCtrNumber, + u32 ResetValue); +u32 XTmrCtr_GetCaptureValue(XTmrCtr * InstancePtr, u8 TmrCtrNumber); +int XTmrCtr_IsExpired(XTmrCtr * InstancePtr, u8 TmrCtrNumber); +void XTmrCtr_Reset(XTmrCtr * InstancePtr, u8 TmrCtrNumber); +u8 XTmrCtr_PwmConfigure(XTmrCtr *InstancePtr, u32 PwmPeriod, u32 PwmHighTime); +void XTmrCtr_PwmEnable(XTmrCtr *InstancePtr); +void XTmrCtr_PwmDisable(XTmrCtr *InstancePtr); + +/* Lookup configuration in xtmrctr_sinit.c */ +XTmrCtr_Config *XTmrCtr_LookupConfig(u16 DeviceId); + +/* Functions for options, in file xtmrctr_options.c */ +void XTmrCtr_SetOptions(XTmrCtr * InstancePtr, u8 TmrCtrNumber, u32 Options); +u32 XTmrCtr_GetOptions(XTmrCtr * InstancePtr, u8 TmrCtrNumber); + +/* Functions for statistics, in file xtmrctr_stats.c */ +void XTmrCtr_GetStats(XTmrCtr * InstancePtr, XTmrCtrStats * StatsPtr); +void XTmrCtr_ClearStats(XTmrCtr * InstancePtr); + +/* Functions for self-test, in file xtmrctr_selftest.c */ +int XTmrCtr_SelfTest(XTmrCtr * InstancePtr, u8 TmrCtrNumber); + +/* Functions for interrupts, in file xtmrctr_intr.c */ +void XTmrCtr_SetHandler(XTmrCtr * InstancePtr, XTmrCtr_Handler FuncPtr, + void *CallBackRef); +void XTmrCtr_InterruptHandler(void *InstancePtr); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/tmrctr_v4_5/src/xtmrctr_g.c b/datalink814_sp/bsp/microblaze_ps/libsrc/tmrctr_v4_5/src/xtmrctr_g.c new file mode 100644 index 0000000..30e9ccc --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/tmrctr_v4_5/src/xtmrctr_g.c @@ -0,0 +1,52 @@ + +/******************************************************************* +* +* CAUTION: This file is automatically generated by HSI. +* Version: 2019.1.3 +* DO NOT EDIT. +* +* Copyright (C) 2010-2023 Xilinx, Inc. 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 +*XILINX 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. +* +*Except as contained in this notice, the name of the Xilinx shall not be used +*in advertising or otherwise to promote the sale, use or other dealings in +*this Software without prior written authorization from Xilinx. +* + +* +* Description: Driver configuration +* +*******************************************************************/ + +#include "xparameters.h" +#include "xtmrctr.h" + +/* +* The configuration table for devices +*/ + +XTmrCtr_Config XTmrCtr_ConfigTable[XPAR_XTMRCTR_NUM_INSTANCES] = +{ + { + XPAR_AXI_TIMER_0_DEVICE_ID, + XPAR_AXI_TIMER_0_BASEADDR, + XPAR_AXI_TIMER_0_CLOCK_FREQ_HZ + } +}; + + diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/tmrctr_v4_5/src/xtmrctr_i.h b/datalink814_sp/bsp/microblaze_ps/libsrc/tmrctr_v4_5/src/xtmrctr_i.h new file mode 100644 index 0000000..6fc562d --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/tmrctr_v4_5/src/xtmrctr_i.h @@ -0,0 +1,76 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xtmrctr_i.h +* @addtogroup tmrctr_v4_6 +* @{ +* +* This file contains data which is shared between files internal to the +* XTmrCtr component. It is intended for internal use only. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00b jhl  02/06/02 First release
+* 1.10b mta  03/21/07 Updated to new coding style
+* 2.00a ktn  10/30/09 _m is removed from all the macro definitions.
+* 
+* +******************************************************************************/ + +#ifndef XTMRCTR_I_H /* prevent circular inclusions */ +#define XTMRCTR_I_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" + +/************************** Constant Definitions *****************************/ + + +/************************** Function Prototypes ******************************/ + + +/************************** Variable Definitions *****************************/ + +extern u8 XTmrCtr_Offsets[]; + +#ifdef __cplusplus +} +#endif + +#endif +/** @} */ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/tmrctr_v4_5/src/xtmrctr_intr.c b/datalink814_sp/bsp/microblaze_ps/libsrc/tmrctr_v4_5/src/xtmrctr_intr.c new file mode 100644 index 0000000..7b9a8fd --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/tmrctr_v4_5/src/xtmrctr_intr.c @@ -0,0 +1,229 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xtmrctr_intr.c +* @addtogroup tmrctr_v4_6 +* @{ +* +* Contains interrupt-related functions for the XTmrCtr component. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00b jhl  02/06/02 First release
+* 1.10b mta  03/21/07 Updated to new coding style
+* 2.00a ktn  10/30/09 Updated to use HAL API's. _m is removed from all the macro
+*		      definitions.
+* 2.03a rvo  11/30/10 Added check to see if interrupt is enabled before further
+*		      processing for CR 584557.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xtmrctr.h" + + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + + +/************************** Variable Definitions *****************************/ + + +/*****************************************************************************/ +/** +* +* Sets the timer callback function, which the driver calls when the specified +* timer times out. +* +* @param InstancePtr is a pointer to the XTmrCtr instance . +* @param CallBackRef is the upper layer callback reference passed back +* when the callback function is invoked. +* @param FuncPtr is the pointer to the callback function. +* +* @return None. +* +* @note +* +* The handler is called within interrupt context so the function that is +* called should either be short or pass the more extensive processing off +* to another task to allow the interrupt to return and normal processing +* to continue. +* +******************************************************************************/ +void XTmrCtr_SetHandler(XTmrCtr * InstancePtr, XTmrCtr_Handler FuncPtr, + void *CallBackRef) +{ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(FuncPtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + InstancePtr->Handler = FuncPtr; + InstancePtr->CallBackRef = CallBackRef; +} + +/*****************************************************************************/ +/** +* +* Interrupt Service Routine (ISR) for the driver. This function only performs +* processing for the device and does not save and restore the interrupt context. +* +* @param InstancePtr contains a pointer to the timer/counter instance for +* the interrupt. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XTmrCtr_InterruptHandler(void *InstancePtr) +{ + XTmrCtr *TmrCtrPtr = NULL; + u8 TmrCtrNumber; + u32 ControlStatusReg; + + /* + * Verify that each of the inputs are valid. + */ + Xil_AssertVoid(InstancePtr != NULL); + + /* + * Convert the non-typed pointer to an timer/counter instance pointer + * such that there is access to the timer/counter + */ + TmrCtrPtr = (XTmrCtr *) InstancePtr; + + /* + * Loop thru each timer counter in the device and call the callback + * function for each timer which has caused an interrupt + */ + for (TmrCtrNumber = 0; + TmrCtrNumber < XTC_DEVICE_TIMER_COUNT; TmrCtrNumber++) { + + ControlStatusReg = XTmrCtr_ReadReg(TmrCtrPtr->BaseAddress, + TmrCtrNumber, + XTC_TCSR_OFFSET); + /* + * Check if interrupt is enabled + */ + if (ControlStatusReg & XTC_CSR_ENABLE_INT_MASK) { + + /* + * Check if timer expired and interrupt occured + */ + if (ControlStatusReg & XTC_CSR_INT_OCCURED_MASK) { + /* + * Increment statistics for the number of + * interrupts and call the callback to handle + * any application specific processing + */ + TmrCtrPtr->Stats.Interrupts++; + TmrCtrPtr->Handler(TmrCtrPtr->CallBackRef, + TmrCtrNumber); + /* + * Read the new Control/Status Register content. + */ + ControlStatusReg = + XTmrCtr_ReadReg(TmrCtrPtr->BaseAddress, + TmrCtrNumber, + XTC_TCSR_OFFSET); + /* + * If in compare mode and a single shot rather + * than auto reload mode then disable the timer + * and reset it such so that the interrupt can + * be acknowledged, this should be only temporary + * till the hardware is fixed + */ + if (((ControlStatusReg & + XTC_CSR_AUTO_RELOAD_MASK) == 0) && + ((ControlStatusReg & + XTC_CSR_CAPTURE_MODE_MASK)== 0)) { + /* + * Disable the timer counter and + * reset it such that the timer + * counter is loaded with the + * reset value allowing the + * interrupt to be acknowledged + */ + ControlStatusReg &= + ~XTC_CSR_ENABLE_TMR_MASK; + + XTmrCtr_WriteReg( + TmrCtrPtr->BaseAddress, + TmrCtrNumber, + XTC_TCSR_OFFSET, + ControlStatusReg | + XTC_CSR_LOAD_MASK); + + /* + * Clear the reset condition, + * the reset bit must be + * manually cleared by a 2nd write + * to the register + */ + XTmrCtr_WriteReg( + TmrCtrPtr->BaseAddress, + TmrCtrNumber, + XTC_TCSR_OFFSET, + ControlStatusReg); + } + + /* + * Acknowledge the interrupt by clearing the + * interrupt bit in the timer control status + * register, this is done after calling the + * handler so the application could call + * IsExpired, the interrupt is cleared by + * writing a 1 to the interrupt bit of the + * register without changing any of the other + * bits + */ + XTmrCtr_WriteReg(TmrCtrPtr->BaseAddress, + TmrCtrNumber, + XTC_TCSR_OFFSET, + ControlStatusReg | + XTC_CSR_INT_OCCURED_MASK); + } + } + } +} +/** @} */ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/tmrctr_v4_5/src/xtmrctr_l.c b/datalink814_sp/bsp/microblaze_ps/libsrc/tmrctr_v4_5/src/xtmrctr_l.c new file mode 100644 index 0000000..5e2bcb9 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/tmrctr_v4_5/src/xtmrctr_l.c @@ -0,0 +1,75 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xtmrctr_l.c +* @addtogroup tmrctr_v4_6 +* @{ +* +* This file contains low-level driver functions that can be used to access the +* device. The user should refer to the hardware device specification for more +* details of the device operation. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00b jhl  04/24/02 First release
+* 1.10b mta  03/21/07 Updated to new coding style
+* 2.00a ktn  10/30/09 Updated to use HAL API's
+* 
+* +******************************************************************************/ + + +/***************************** Include Files *********************************/ + +#include "xtmrctr_l.h" + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + + +/************************** Variable Definitions *****************************/ + +/* The following table contains the offset from the base address of a timer + * counter device for each timer counter. A single device may contain multiple + * timer counters and the functions specify which one to operate on. + */ +u8 XTmrCtr_Offsets[] = { 0, XTC_TIMER_COUNTER_OFFSET }; +/** @} */ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/tmrctr_v4_5/src/xtmrctr_l.h b/datalink814_sp/bsp/microblaze_ps/libsrc/tmrctr_v4_5/src/xtmrctr_l.h new file mode 100644 index 0000000..976e601 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/tmrctr_v4_5/src/xtmrctr_l.h @@ -0,0 +1,437 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xtmrctr_l.h +* @addtogroup tmrctr_v4_6 +* @{ +* +* This header file contains identifiers and low-level driver functions (or +* macros) that can be used to access the device. The user should refer to the +* hardware device specification for more details of the device operation. +* High-level driver functions are defined in xtmrctr.h. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00b jhl  04/24/02 First release
+* 1.10b mta  03/21/07 Updated to new coding style
+* 2.00a ktn  10/30/09 Updated to use HAL API's. _m is removed from all the macro
+*		      definitions.
+* 2.01a ktn  07/12/10 Renamed the macro XTimerCtr_ReadReg as XTmrCtr_ReadReg
+*		      for naming consistency (CR 559142).
+* 2.04a sdm  07/12/11 Added the CASC mode bit in the TCSRO register for the
+*		      cascade mode operation.
+*		      The cascade mode of operation is present in the latest
+*		      versions of the axi_timer IP. Please check the HW
+*		      Datasheet to see whether this feature is present in the
+*		      version of the IP that you are using.
+* 4.4   mus  07/21/17 Updated XTmrCtr_DisableIntr macro to not to clear
+*             T0INT flag
+* 4.5   cjp  03/22/18 Added macros for timer/counter instance number and max
+*                     load value.
+* 
+* +******************************************************************************/ + +#ifndef XTMRCTR_L_H /* prevent circular inclusions */ +#define XTMRCTR_L_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_io.h" + +/************************** Constant Definitions *****************************/ + +/** + * Defines the number of timer counters within a single hardware device. This + * number is not currently parameterized in the hardware but may be in the + * future. + */ +#define XTC_DEVICE_TIMER_COUNT 2 + +/* Each timer counter consumes 16 bytes of address space */ + +#define XTC_TIMER_COUNTER_OFFSET 16 + +/* Timer counter instance number used for PWM */ +#define XTC_TIMER_0 0 +#define XTC_TIMER_1 1 + +/* Max supported load value for timer/counter */ +#define XTC_MAX_LOAD_VALUE 0xFFFFFFFF + +/** @name Register Offset Definitions + * Register offsets within a timer counter, there are multiple + * timer counters within a single device + * @{ + */ + +#define XTC_TCSR_OFFSET 0 /**< Control/Status register */ +#define XTC_TLR_OFFSET 4 /**< Load register */ +#define XTC_TCR_OFFSET 8 /**< Timer counter register */ + +/* @} */ + +/** @name Control Status Register Bit Definitions + * Control Status Register bit masks + * Used to configure the timer counter device. + * @{ + */ + +#define XTC_CSR_CASC_MASK 0x00000800 /**< Cascade Mode */ +#define XTC_CSR_ENABLE_ALL_MASK 0x00000400 /**< Enables all timer + counters */ +#define XTC_CSR_ENABLE_PWM_MASK 0x00000200 /**< Enables the Pulse Width + Modulation */ +#define XTC_CSR_INT_OCCURED_MASK 0x00000100 /**< If bit is set, an + interrupt has occured. + If set and '1' is + written to this bit + position, bit is + cleared. */ +#define XTC_CSR_ENABLE_TMR_MASK 0x00000080 /**< Enables only the + specific timer */ +#define XTC_CSR_ENABLE_INT_MASK 0x00000040 /**< Enables the interrupt + output. */ +#define XTC_CSR_LOAD_MASK 0x00000020 /**< Loads the timer using + the load value provided + earlier in the Load + Register, + XTC_TLR_OFFSET. */ +#define XTC_CSR_AUTO_RELOAD_MASK 0x00000010 /**< In compare mode, + configures + the timer counter to + reload from the + Load Register. The + default mode + causes the timer counter + to hold when the compare + value is hit. In capture + mode, configures the + timer counter to not + hold the previous + capture value if a new + event occurs. The + default mode cause the + timer counter to hold + the capture value until + recognized. */ +#define XTC_CSR_EXT_CAPTURE_MASK 0x00000008 /**< Enables the + external input + to the timer counter. */ +#define XTC_CSR_EXT_GENERATE_MASK 0x00000004 /**< Enables the + external generate output + for the timer. */ +#define XTC_CSR_DOWN_COUNT_MASK 0x00000002 /**< Configures the timer + counter to count down + from start value, the + default is to count + up.*/ +#define XTC_CSR_CAPTURE_MODE_MASK 0x00000001 /**< Enables the timer to + capture the timer + counter value when the + external capture line is + asserted. The default + mode is compare mode.*/ +/* @} */ + +/**************************** Type Definitions *******************************/ + +extern u8 XTmrCtr_Offsets[]; + +/***************** Macros (Inline Functions) Definitions *********************/ + +/*****************************************************************************/ +/** +* Read one of the timer counter registers. +* +* @param BaseAddress contains the base address of the timer counter +* device. +* @param TmrCtrNumber contains the specific timer counter within the +* device, a zero based number, 0 - (XTC_DEVICE_TIMER_COUNT - 1). +* @param RegOffset contains the offset from the 1st register of the timer +* counter to select the specific register of the timer counter. +* +* @return The value read from the register, a 32 bit value. +* +* @note C-Style signature: +* u32 XTmrCtr_ReadReg(u32 BaseAddress, u8 TimerNumber, + unsigned RegOffset); +******************************************************************************/ +#define XTmrCtr_ReadReg(BaseAddress, TmrCtrNumber, RegOffset) \ + Xil_In32((BaseAddress) + XTmrCtr_Offsets[(TmrCtrNumber)] + \ + (RegOffset)) + +#ifndef XTimerCtr_ReadReg +#define XTimerCtr_ReadReg XTmrCtr_ReadReg +#endif + +/*****************************************************************************/ +/** +* Write a specified value to a register of a timer counter. +* +* @param BaseAddress is the base address of the timer counter device. +* @param TmrCtrNumber is the specific timer counter within the device, a +* zero based number, 0 - (XTC_DEVICE_TIMER_COUNT - 1). +* @param RegOffset contain the offset from the 1st register of the timer +* counter to select the specific register of the timer counter. +* @param ValueToWrite is the 32 bit value to be written to the register. +* +* @note C-Style signature: +* void XTmrCtr_WriteReg(u32 BaseAddress, u8 TimerNumber, +* unsigned RegOffset, u32 ValueToWrite); +******************************************************************************/ +#define XTmrCtr_WriteReg(BaseAddress, TmrCtrNumber, RegOffset, ValueToWrite)\ + Xil_Out32(((BaseAddress) + XTmrCtr_Offsets[(TmrCtrNumber)] + \ + (RegOffset)), (ValueToWrite)) + +/****************************************************************************/ +/** +* +* Set the Control Status Register of a timer counter to the specified value. +* +* @param BaseAddress is the base address of the device. +* @param TmrCtrNumber is the specific timer counter within the device, a +* zero based number, 0 - (XTC_DEVICE_TIMER_COUNT - 1). +* @param RegisterValue is the 32 bit value to be written to the register. +* +* @return None. +* +* @note C-Style signature: +* void XTmrCtr_SetControlStatusReg(u32 BaseAddress, +* u8 TmrCtrNumber,u32 RegisterValue); +*****************************************************************************/ +#define XTmrCtr_SetControlStatusReg(BaseAddress, TmrCtrNumber, RegisterValue)\ + XTmrCtr_WriteReg((BaseAddress), (TmrCtrNumber), XTC_TCSR_OFFSET, \ + (RegisterValue)) + +/****************************************************************************/ +/** +* +* Get the Control Status Register of a timer counter. +* +* @param BaseAddress is the base address of the device. +* @param TmrCtrNumber is the specific timer counter within the device, +* a zero based number, 0 - (XTC_DEVICE_TIMER_COUNT - 1). +* +* @return The value read from the register, a 32 bit value. +* +* @note C-Style signature: +* u32 XTmrCtr_GetControlStatusReg(u32 BaseAddress, +* u8 TmrCtrNumber); +*****************************************************************************/ +#define XTmrCtr_GetControlStatusReg(BaseAddress, TmrCtrNumber) \ + XTmrCtr_ReadReg((BaseAddress), (TmrCtrNumber), XTC_TCSR_OFFSET) + +/****************************************************************************/ +/** +* +* Get the Timer Counter Register of a timer counter. +* +* @param BaseAddress is the base address of the device. +* @param TmrCtrNumber is the specific timer counter within the device, +* a zero based number, 0 - (XTC_DEVICE_TIMER_COUNT - 1). +* +* @return The value read from the register, a 32 bit value. +* +* @note C-Style signature: +* u32 XTmrCtr_GetTimerCounterReg(u32 BaseAddress, +* u8 TmrCtrNumber); +*****************************************************************************/ +#define XTmrCtr_GetTimerCounterReg(BaseAddress, TmrCtrNumber) \ + XTmrCtr_ReadReg((BaseAddress), (TmrCtrNumber), XTC_TCR_OFFSET) \ + +/****************************************************************************/ +/** +* +* Set the Load Register of a timer counter to the specified value. +* +* @param BaseAddress is the base address of the device. +* @param TmrCtrNumber is the specific timer counter within the device, a +* zero based number, 0 - (XTC_DEVICE_TIMER_COUNT - 1). +* @param RegisterValue is the 32 bit value to be written to the register. +* +* @return None. +* +* @note C-Style signature: +* void XTmrCtr_SetLoadReg(u32 BaseAddress, u8 TmrCtrNumber, +* u32 RegisterValue); +*****************************************************************************/ +#define XTmrCtr_SetLoadReg(BaseAddress, TmrCtrNumber, RegisterValue) \ + XTmrCtr_WriteReg((BaseAddress), (TmrCtrNumber), XTC_TLR_OFFSET, \ + (RegisterValue)) + +/****************************************************************************/ +/** +* +* Get the Load Register of a timer counter. +* +* @param BaseAddress is the base address of the device. +* @param TmrCtrNumber is the specific timer counter within the device, a +* zero based number, 0 - (XTC_DEVICE_TIMER_COUNT - 1). +* +* @return The value read from the register, a 32 bit value. +* +* @note C-Style signature: +* u32 XTmrCtr_GetLoadReg(u32 BaseAddress, u8 TmrCtrNumber); +*****************************************************************************/ +#define XTmrCtr_GetLoadReg(BaseAddress, TmrCtrNumber) \ +XTmrCtr_ReadReg((BaseAddress), (TmrCtrNumber), XTC_TLR_OFFSET) + +/****************************************************************************/ +/** +* +* Enable a timer counter such that it starts running. +* +* @param BaseAddress is the base address of the device. +* @param TmrCtrNumber is the specific timer counter within the device, a +* zero based number, 0 - (XTC_DEVICE_TIMER_COUNT - 1). +* +* @return None. +* +* @note C-Style signature: +* void XTmrCtr_Enable(u32 BaseAddress, u8 TmrCtrNumber); +*****************************************************************************/ +#define XTmrCtr_Enable(BaseAddress, TmrCtrNumber) \ + XTmrCtr_WriteReg((BaseAddress), (TmrCtrNumber), XTC_TCSR_OFFSET, \ + (XTmrCtr_ReadReg((BaseAddress), ( TmrCtrNumber), \ + XTC_TCSR_OFFSET) | XTC_CSR_ENABLE_TMR_MASK)) + +/****************************************************************************/ +/** +* +* Disable a timer counter such that it stops running. +* +* @param BaseAddress is the base address of the device. +* @param TmrCtrNumber is the specific timer counter within the device, +* a zero based number, 0 - (XTC_DEVICE_TIMER_COUNT - 1). +* +* @return None. +* +* @note C-Style signature: +* void XTmrCtr_Disable(u32 BaseAddress, u8 TmrCtrNumber); +*****************************************************************************/ +#define XTmrCtr_Disable(BaseAddress, TmrCtrNumber) \ + XTmrCtr_WriteReg((BaseAddress), (TmrCtrNumber), XTC_TCSR_OFFSET, \ + (XTmrCtr_ReadReg((BaseAddress), (TmrCtrNumber),\ + XTC_TCSR_OFFSET) & ~ XTC_CSR_ENABLE_TMR_MASK)) + +/****************************************************************************/ +/** +* +* Enable the interrupt for a timer counter. +* +* @param BaseAddress is the base address of the device. +* @param TmrCtrNumber is the specific timer counter within the device, a +* zero based number, 0 - (XTC_DEVICE_TIMER_COUNT - 1). +* +* @return None. +* +* @note C-Style signature: +* void XTmrCtr_EnableIntr(u32 BaseAddress, u8 TmrCtrNumber); +*****************************************************************************/ +#define XTmrCtr_EnableIntr(BaseAddress, TmrCtrNumber) \ + XTmrCtr_WriteReg((BaseAddress), (TmrCtrNumber), XTC_TCSR_OFFSET, \ + (XTmrCtr_ReadReg((BaseAddress), (TmrCtrNumber), \ + XTC_TCSR_OFFSET) | XTC_CSR_ENABLE_INT_MASK)) + +/****************************************************************************/ +/** +* +* Disable the interrupt for a timer counter. +* +* @param BaseAddress is the base address of the device. +* @param TmrCtrNumber is the specific timer counter within the device, a +* zero based number, 0 - (XTC_DEVICE_TIMER_COUNT - 1). +* +* @return None. +* +* @note C-Style signature: +* void XTmrCtr_DisableIntr(u32 BaseAddress, u8 TmrCtrNumber); +*****************************************************************************/ +#define XTmrCtr_DisableIntr(BaseAddress, TmrCtrNumber) \ + XTmrCtr_WriteReg((BaseAddress), (TmrCtrNumber), XTC_TCSR_OFFSET, \ + (XTmrCtr_ReadReg((BaseAddress), (TmrCtrNumber), \ + XTC_TCSR_OFFSET) & ~ (XTC_CSR_ENABLE_INT_MASK \ + | XTC_CSR_INT_OCCURED_MASK))) + +/****************************************************************************/ +/** +* +* Cause the timer counter to load it's Timer Counter Register with the value +* in the Load Register. +* +* @param BaseAddress is the base address of the device. +* @param TmrCtrNumber is the specific timer counter within the device, a +* zero based number, 0 - (XTC_DEVICE_TIMER_COUNT - 1). +* +* @return None. +* +* @note C-Style signature: +* void XTmrCtr_LoadTimerCounterReg(u32 BaseAddress, + u8 TmrCtrNumber); +*****************************************************************************/ +#define XTmrCtr_LoadTimerCounterReg(BaseAddress, TmrCtrNumber) \ + XTmrCtr_WriteReg((BaseAddress), (TmrCtrNumber), XTC_TCSR_OFFSET, \ + (XTmrCtr_ReadReg((BaseAddress), (TmrCtrNumber),\ + XTC_TCSR_OFFSET) | XTC_CSR_LOAD_MASK)) + +/****************************************************************************/ +/** +* +* Determine if a timer counter event has occurred. Events are defined to be +* when a capture has occurred or the counter has roller over. +* +* @param BaseAddress is the base address of the device. +* @param TmrCtrNumber is the specific timer counter within the device, a +* zero based number, 0 - (XTC_DEVICE_TIMER_COUNT - 1). +* +* @note C-Style signature: +* int XTmrCtr_HasEventOccurred(u32 BaseAddress, u8 TmrCtrNumber); +*****************************************************************************/ +#define XTmrCtr_HasEventOccurred(BaseAddress, TmrCtrNumber) \ + ((XTmrCtr_ReadReg((BaseAddress), (TmrCtrNumber), \ + XTC_TCSR_OFFSET) & XTC_CSR_INT_OCCURED_MASK) == \ + XTC_CSR_INT_OCCURED_MASK) + +/************************** Function Prototypes ******************************/ +/************************** Variable Definitions *****************************/ +#ifdef __cplusplus +} +#endif +#endif /* end of protection macro */ +/** @} */ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/tmrctr_v4_5/src/xtmrctr_options.c b/datalink814_sp/bsp/microblaze_ps/libsrc/tmrctr_v4_5/src/xtmrctr_options.c new file mode 100644 index 0000000..e4aa850 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/tmrctr_v4_5/src/xtmrctr_options.c @@ -0,0 +1,213 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xtmrctr_options.c +* @addtogroup tmrctr_v4_6 +* @{ +* +* Contains configuration options functions for the XTmrCtr component. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00b jhl  02/06/02 First release
+* 1.10b mta  03/21/07 Updated to new coding style
+* 2.00a ktn  10/30/09 Updated to use HAL API's. _m is removed from all the macro
+*		      definitions.
+* 2.04a sdm  07/12/11 Added support for the cascade mode operation.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xtmrctr.h" +#include "xtmrctr_i.h" + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + + +/************************** Variable Definitions *****************************/ + +/* + * The following data type maps an option to a register mask such that getting + * and setting the options may be table driven. + */ +typedef struct { + u32 Option; + u32 Mask; +} Mapping; + +/* + * Create the table which contains options which are to be processed to get/set + * the options. These options are table driven to allow easy maintenance and + * expansion of the options. + */ +static Mapping OptionsTable[] = { + {XTC_CASCADE_MODE_OPTION, XTC_CSR_CASC_MASK}, + {XTC_ENABLE_ALL_OPTION, XTC_CSR_ENABLE_ALL_MASK}, + {XTC_DOWN_COUNT_OPTION, XTC_CSR_DOWN_COUNT_MASK}, + {XTC_CAPTURE_MODE_OPTION, XTC_CSR_CAPTURE_MODE_MASK | + XTC_CSR_EXT_CAPTURE_MASK}, + {XTC_INT_MODE_OPTION, XTC_CSR_ENABLE_INT_MASK}, + {XTC_AUTO_RELOAD_OPTION, XTC_CSR_AUTO_RELOAD_MASK}, + {XTC_EXT_COMPARE_OPTION, XTC_CSR_EXT_GENERATE_MASK} +}; + +/* Create a constant for the number of entries in the table */ + +#define XTC_NUM_OPTIONS (sizeof(OptionsTable) / sizeof(Mapping)) + +/*****************************************************************************/ +/** +* +* Enables the specified options for the specified timer counter. This function +* sets the options without regard to the current options of the driver. To +* prevent a loss of the current options, the user should call +* XTmrCtr_GetOptions() prior to this function and modify the retrieved options +* to pass into this function to prevent loss of the current options. +* +* @param InstancePtr is a pointer to the XTmrCtr instance. +* @param TmrCtrNumber is the timer counter of the device to operate on. +* Each device may contain multiple timer counters. The timer +* number is a zero based number with a range of +* 0 - (XTC_DEVICE_TIMER_COUNT - 1). +* @param Options contains the desired options to be set or cleared. +* Setting the option to '1' enables the option, clearing the to +* '0' disables the option. The options are bit masks such that +* multiple options may be set or cleared. The options are +* described in xtmrctr.h. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XTmrCtr_SetOptions(XTmrCtr * InstancePtr, u8 TmrCtrNumber, u32 Options) +{ + u32 CounterControlReg = 0; + u32 Index; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(TmrCtrNumber < XTC_DEVICE_TIMER_COUNT); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Loop through the Options table, turning the enable on or off + * depending on whether the bit is set in the incoming Options flag. + */ + + for (Index = 0; Index < XTC_NUM_OPTIONS; Index++) { + if (Options & OptionsTable[Index].Option) { + + /* + * Turn the option on + */ + CounterControlReg |= OptionsTable[Index].Mask; + } + else { + /* + * Turn the option off + */ + CounterControlReg &= ~OptionsTable[Index].Mask; + } + } + + /* + * Write out the updated value to the actual register + */ + XTmrCtr_WriteReg(InstancePtr->BaseAddress, TmrCtrNumber, + XTC_TCSR_OFFSET, CounterControlReg); +} + +/*****************************************************************************/ +/** +* +* Get the options for the specified timer counter. +* +* @param InstancePtr is a pointer to the XTmrCtr instance. +* @param TmrCtrNumber is the timer counter of the device to operate on +* Each device may contain multiple timer counters. The timer +* number is a zero based number with a range of +* 0 - (XTC_DEVICE_TIMER_COUNT - 1). +* +* @return +* +* The currently set options. An option which is set to a '1' is enabled and +* set to a '0' is disabled. The options are bit masks such that multiple +* options may be set or cleared. The options are described in xtmrctr.h. +* +* @note None. +* +******************************************************************************/ +u32 XTmrCtr_GetOptions(XTmrCtr * InstancePtr, u8 TmrCtrNumber) +{ + + u32 Options = 0; + u32 CounterControlReg; + u32 Index; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(TmrCtrNumber < XTC_DEVICE_TIMER_COUNT); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the current contents of the control status register to allow + * the current options to be determined + */ + CounterControlReg = XTmrCtr_ReadReg(InstancePtr->BaseAddress, + TmrCtrNumber, XTC_TCSR_OFFSET); + /* + * Loop through the Options table, turning the enable on or off + * depending on whether the bit is set in the current register settings. + */ + for (Index = 0; Index < XTC_NUM_OPTIONS; Index++) { + if (CounterControlReg & OptionsTable[Index].Mask) { + Options |= OptionsTable[Index].Option; /* turn it on */ + } + else { + Options &= ~OptionsTable[Index].Option; /* turn it off */ + } + } + + return Options; +} +/** @} */ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/tmrctr_v4_5/src/xtmrctr_selftest.c b/datalink814_sp/bsp/microblaze_ps/libsrc/tmrctr_v4_5/src/xtmrctr_selftest.c new file mode 100644 index 0000000..a090426 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/tmrctr_v4_5/src/xtmrctr_selftest.c @@ -0,0 +1,162 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xtmrctr_selftest.c +* @addtogroup tmrctr_v4_6 +* @{ +* +* Contains diagnostic/self-test functions for the XTmrCtr component. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00b jhl  02/06/02 First release
+* 1.10b mta  03/21/07 Updated to new coding style
+* 2.00a ktn  10/30/09 Updated to use HAL API's. _m is removed from all the macro
+*		      definitions.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xil_io.h" +#include "xtmrctr.h" +#include "xtmrctr_i.h" + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + + +/************************** Variable Definitions *****************************/ + + +/*****************************************************************************/ +/** +* +* Runs a self-test on the driver/device. This test verifies that the specified +* timer counter of the device can be enabled and increments. +* +* @param InstancePtr is a pointer to the XTmrCtr instance. +* @param TmrCtrNumber is the timer counter of the device to operate on. +* Each device may contain multiple timer counters. The timer +* number is a zero based number with a range of +* 0 - (XTC_DEVICE_TIMER_COUNT - 1). +* +* @return +* - XST_SUCCESS if self-test was successful +* - XST_FAILURE if the timer is not incrementing. +* +* @note +* +* This is a destructive test using the provided timer. The current settings +* of the timer are returned to the initialized values and all settings at the +* time this function is called are overwritten. +* +******************************************************************************/ +int XTmrCtr_SelfTest(XTmrCtr * InstancePtr, u8 TmrCtrNumber) +{ + u32 TimerCount1 = 0; + u32 TimerCount2 = 0; + u16 Count = 0; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(TmrCtrNumber < XTC_DEVICE_TIMER_COUNT); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Set the Capture register to 0 + */ + XTmrCtr_WriteReg(InstancePtr->BaseAddress, TmrCtrNumber, + XTC_TLR_OFFSET, 0); + + /* + * Reset the timer and the interrupt + */ + XTmrCtr_WriteReg(InstancePtr->BaseAddress, TmrCtrNumber, + XTC_TCSR_OFFSET, + XTC_CSR_INT_OCCURED_MASK | XTC_CSR_LOAD_MASK); + + /* + * Set the control/status register to enable timer + */ + XTmrCtr_WriteReg(InstancePtr->BaseAddress, TmrCtrNumber, + XTC_TCSR_OFFSET, XTC_CSR_ENABLE_TMR_MASK); + + /* + * Read the timer + */ + TimerCount1 = XTmrCtr_ReadReg(InstancePtr->BaseAddress, + TmrCtrNumber, XTC_TCR_OFFSET); + /* + * Make sure timer is incrementing if the Count rolls over to zero + * and the timer still has not incremented an error is returned + */ + + do { + TimerCount2 = XTmrCtr_ReadReg(InstancePtr->BaseAddress, + TmrCtrNumber, XTC_TCR_OFFSET); + Count++; + } + while ((TimerCount1 == TimerCount2) && (Count != 0)); + + /* + * Reset the timer and the interrupt + */ + XTmrCtr_WriteReg(InstancePtr->BaseAddress, TmrCtrNumber, + XTC_TCSR_OFFSET, + XTC_CSR_INT_OCCURED_MASK | XTC_CSR_LOAD_MASK); + + /* + * Set the control/status register to 0 to complete initialization + * this disables the timer completely and allows it to be used again + */ + + XTmrCtr_WriteReg(InstancePtr->BaseAddress, TmrCtrNumber, + XTC_TCSR_OFFSET, 0); + + if (TimerCount1 == TimerCount2) { + return XST_FAILURE; + } + else { + return XST_SUCCESS; + } +} +/** @} */ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/tmrctr_v4_5/src/xtmrctr_sinit.c b/datalink814_sp/bsp/microblaze_ps/libsrc/tmrctr_v4_5/src/xtmrctr_sinit.c new file mode 100644 index 0000000..e699f70 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/tmrctr_v4_5/src/xtmrctr_sinit.c @@ -0,0 +1,99 @@ +/****************************************************************************** +* +* Copyright (C) 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xtmrctr_sinit.c +* @addtogroup tmrctr_v4_6 +* @{ +* +* This file contains static initialization methods for the XTmrCtr driver. +* +* @note None. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 4.0   als  09/30/15 Creation of this file. Moved LookupConfig from xtmrctr.c.
+* 4.4	mn   07/31/17 Resolve Compilation warning
+* 
+* +******************************************************************************/ + +/******************************* Include Files *******************************/ + +#include "xparameters.h" +#include "xtmrctr.h" + +/************************** Constant Definitions *****************************/ + +#ifndef XPAR_XTMRCTR_NUM_INSTANCES +#define XPAR_XTMRCTR_NUM_INSTANCES 0 +#endif + +/*************************** Variable Declarations ***************************/ + +/* A table of configuration structures containing the configuration information + * for each timer core in the system. */ +extern XTmrCtr_Config XTmrCtr_ConfigTable[XPAR_XTMRCTR_NUM_INSTANCES]; + +/**************************** Function Definitions ***************************/ + +/*****************************************************************************/ +/** +* Looks up the device configuration based on the unique device ID. The table +* TmrCtr_ConfigTable contains the configuration info for each device in the +* system. +* +* @param DeviceId is the unique device ID to search for in the config +* table. +* +* @return A pointer to the configuration that matches the given device +* ID, or NULL if no match is found. +* +* @note None. +* +******************************************************************************/ +XTmrCtr_Config *XTmrCtr_LookupConfig(u16 DeviceId) +{ + XTmrCtr_Config *CfgPtr = NULL; + u16 Index; + + for (Index = 0; Index < XPAR_XTMRCTR_NUM_INSTANCES; Index++) { + if (XTmrCtr_ConfigTable[Index].DeviceId == DeviceId) { + CfgPtr = &XTmrCtr_ConfigTable[Index]; + break; + } + } + + return CfgPtr; +} + +/** @} */ diff --git a/datalink814_sp/bsp/microblaze_ps/libsrc/tmrctr_v4_5/src/xtmrctr_stats.c b/datalink814_sp/bsp/microblaze_ps/libsrc/tmrctr_v4_5/src/xtmrctr_stats.c new file mode 100644 index 0000000..29cdba7 --- /dev/null +++ b/datalink814_sp/bsp/microblaze_ps/libsrc/tmrctr_v4_5/src/xtmrctr_stats.c @@ -0,0 +1,111 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xtmrctr_stats.c +* @addtogroup tmrctr_v4_6 +* @{ +* +* Contains function to get and clear statistics for the XTmrCtr component. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00b jhl  02/06/02 First release.
+* 1.10b mta  03/21/07 Updated for new coding style.
+* 2.00a ktn  10/30/09 Updated to use HAL API's.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xtmrctr.h" + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + + +/************************** Variable Definitions *****************************/ + + +/*****************************************************************************/ +/** +* +* Get a copy of the XTmrCtrStats structure, which contains the current +* statistics for this driver. +* +* @param InstancePtr is a pointer to the XTmrCtr instance. +* @param StatsPtr is a pointer to a XTmrCtrStats structure which will get +* a copy of current statistics. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XTmrCtr_GetStats(XTmrCtr * InstancePtr, XTmrCtrStats * StatsPtr) +{ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(StatsPtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + StatsPtr->Interrupts = InstancePtr->Stats.Interrupts; +} + +/*****************************************************************************/ +/** +* +* Clear the XTmrCtrStats structure for this driver. +* +* @param InstancePtr is a pointer to the XTmrCtr instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XTmrCtr_ClearStats(XTmrCtr * InstancePtr) +{ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + InstancePtr->Stats.Interrupts = 0; +} +/** @} */ diff --git a/datalink814_sp/bsp/system.mss b/datalink814_sp/bsp/system.mss new file mode 100644 index 0000000..9430db8 --- /dev/null +++ b/datalink814_sp/bsp/system.mss @@ -0,0 +1,110 @@ + + PARAMETER VERSION = 2.2.0 + + +BEGIN OS + PARAMETER OS_NAME = standalone + PARAMETER OS_VER = 7.0 + PARAMETER PROC_INSTANCE = microblaze_ps +END + + +BEGIN PROCESSOR + PARAMETER DRIVER_NAME = cpu + PARAMETER DRIVER_VER = 2.9 + PARAMETER HW_INSTANCE = microblaze_ps + PARAMETER compiler_flags = -mlittle-endian -mxl-barrel-shift -mxl-pattern-compare -mno-xl-soft-mul -mno-xl-soft-div -mcpu=v11.0 +END + + +BEGIN DRIVER + PARAMETER DRIVER_NAME = bram + PARAMETER DRIVER_VER = 4.3 + PARAMETER HW_INSTANCE = ant_config_bram_ctrl +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = axidma + PARAMETER DRIVER_VER = 9.9 + PARAMETER HW_INSTANCE = axi_dma_c2c +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = gpio + PARAMETER DRIVER_VER = 4.4 + PARAMETER HW_INSTANCE = axi_gpio +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = intc + PARAMETER DRIVER_VER = 3.9 + PARAMETER HW_INSTANCE = axi_intc +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = generic + PARAMETER DRIVER_VER = 2.0 + PARAMETER HW_INSTANCE = axi_spi_engine_axi_spi_engine +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = tmrctr + PARAMETER DRIVER_VER = 4.5 + PARAMETER HW_INSTANCE = axi_timer_0 +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = bram + PARAMETER DRIVER_VER = 4.3 + PARAMETER HW_INSTANCE = c2c_rx_axi_bram_ctrl +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = bram + PARAMETER DRIVER_VER = 4.3 + PARAMETER HW_INSTANCE = c2c_tx_axi_bram_ctrl +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = bram + PARAMETER DRIVER_VER = 4.3 + PARAMETER HW_INSTANCE = microblaze_ps_local_memory_dlmb_bram_if_cntlr +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = bram + PARAMETER DRIVER_VER = 4.3 + PARAMETER HW_INSTANCE = microblaze_ps_local_memory_ilmb_bram_if_cntlr +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = bram + PARAMETER DRIVER_VER = 4.3 + PARAMETER HW_INSTANCE = rx_frame_bram_ctrl +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = gpio + PARAMETER DRIVER_VER = 4.4 + PARAMETER HW_INSTANCE = status_gpio_i +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = gpio + PARAMETER DRIVER_VER = 4.4 + PARAMETER HW_INSTANCE = status_gpio_o +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = bram + PARAMETER DRIVER_VER = 4.3 + PARAMETER HW_INSTANCE = tx_frame_bram_ctrl +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = sysmon + PARAMETER DRIVER_VER = 7.5 + PARAMETER HW_INSTANCE = xadc_wiz_0 +END + + diff --git a/datalink814_sp/build/makefile b/datalink814_sp/build/makefile new file mode 100644 index 0000000..91c1179 --- /dev/null +++ b/datalink814_sp/build/makefile @@ -0,0 +1,74 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +-include ../makefile.init + +CC = /tools/Xilinx/SDK/2019.1/gnu/microblaze/lin/bin/mb-gcc + +RM := rm -rf + +# All of the sources participating in the build are defined here +-include sources.mk +-include src/util/subdir.mk +-include src/time_ctrl/subdir.mk +-include src/phy_ctrl/subdir.mk +-include src/inter_comm/subdir.mk +-include src/dev_profile/subdir.mk +-include src/circ_queue/subdir.mk +-include src/c2c_bridge/subdir.mk +-include src/axi_dma/subdir.mk +-include src/adi_noos/drivers/rf-transceiver/ad9361_reg/subdir.mk +-include src/adi_noos/drivers/platform/subdir.mk +-include src/adi_noos/drivers/frequency/ad9516/subdir.mk +-include src/adi_noos/drivers/axi_core/spi_engine/subdir.mk +-include src/adi_noos/drivers/axi_core/axi_dmac/subdir.mk +-include src/adi_noos/drivers/api/subdir.mk +-include src/subdir.mk +-include subdir.mk +-include objects.mk + +ifneq ($(MAKECMDGOALS),clean) +ifneq ($(strip $(S_UPPER_DEPS)),) +-include $(S_UPPER_DEPS) +endif +ifneq ($(strip $(C_DEPS)),) +-include $(C_DEPS) +endif +endif + +-include ../makefile.defs + +# Add inputs and outputs from these tool invocations to the build variables +ELFSIZE += \ +datalink814_sp.elf.size \ + + +# All Target +all: datalink814_sp.elf secondary-outputs + +# Tool invocations +datalink814_sp.elf: $(OBJS) ../src/lscript.ld $(USER_OBJS) + @echo 'Building target: $@' + @echo 'Invoking: MicroBlaze gcc linker' + $(CC) -Wl,-T -Wl,../src/lscript.ld -L../bsp/microblaze_ps/lib -mlittle-endian -mxl-barrel-shift -mxl-pattern-compare -mno-xl-soft-div -mcpu=v11.0 -mno-xl-soft-mul -Wl,--no-relax -Wl,--gc-sections -o "datalink814_sp.elf" $(OBJS) $(USER_OBJS) $(LIBS) + @echo 'Finished building target: $@' + @echo ' ' + +datalink814_sp.elf.size: datalink814_sp.elf + @echo 'Invoking: MicroBlaze Print Size' + mb-size datalink814_sp.elf |tee "datalink814_sp.elf.size" + @echo 'Finished building: $@' + @echo ' ' + +# Other Targets +clean: + -$(RM) $(EXECUTABLES)$(OBJS)$(S_UPPER_DEPS)$(C_DEPS)$(ELFSIZE) datalink814_sp.elf + -@echo ' ' + +secondary-outputs: $(ELFSIZE) + +.PHONY: all clean dependents +.SECONDARY: + +-include ../makefile.targets diff --git a/datalink814_sp/build/objects.mk b/datalink814_sp/build/objects.mk new file mode 100644 index 0000000..c45166f --- /dev/null +++ b/datalink814_sp/build/objects.mk @@ -0,0 +1,8 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +USER_OBJS := + +LIBS := -Wl,--start-group,-lxil,-lgcc,-lc,--end-group + diff --git a/datalink814_sp/build/sources.mk b/datalink814_sp/build/sources.mk new file mode 100644 index 0000000..394950a --- /dev/null +++ b/datalink814_sp/build/sources.mk @@ -0,0 +1,34 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +LD_SRCS := +OBJ_SRCS := +S_SRCS := +C_SRCS := +S_UPPER_SRCS := +O_SRCS := +EXECUTABLES := +OBJS := +S_UPPER_DEPS := +C_DEPS := +ELFSIZE := + +# Every subdirectory with source files must be described here +SUBDIRS := \ +src/adi_noos/drivers/api \ +src/adi_noos/drivers/axi_core/axi_dmac \ +src/adi_noos/drivers/axi_core/spi_engine \ +src/adi_noos/drivers/frequency/ad9516 \ +src/adi_noos/drivers/platform \ +src/adi_noos/drivers/rf-transceiver/ad9361_reg \ +src/axi_dma \ +src/c2c_bridge \ +src/circ_queue \ +src \ +src/dev_profile \ +src/inter_comm \ +src/phy_ctrl \ +src/time_ctrl \ +src/util \ + diff --git a/datalink814_sp/build/src/adi_noos/drivers/api/subdir.mk b/datalink814_sp/build/src/adi_noos/drivers/api/subdir.mk new file mode 100644 index 0000000..db59755 --- /dev/null +++ b/datalink814_sp/build/src/adi_noos/drivers/api/subdir.mk @@ -0,0 +1,30 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +# Add inputs and outputs from these tool invocations to the build variables +C_SRCS += \ +../src/adi_noos/drivers/api/gpio.c \ +../src/adi_noos/drivers/api/irq.c \ +../src/adi_noos/drivers/api/spi.c + +OBJS += \ +./src/adi_noos/drivers/api/gpio.o \ +./src/adi_noos/drivers/api/irq.o \ +./src/adi_noos/drivers/api/spi.o + +C_DEPS += \ +./src/adi_noos/drivers/api/gpio.d \ +./src/adi_noos/drivers/api/irq.d \ +./src/adi_noos/drivers/api/spi.d + + +# Each subdirectory must supply rules for building sources it contributes +src/adi_noos/drivers/api/%.o: ../src/adi_noos/drivers/api/%.c + @echo 'Building file: $<' + @echo 'Invoking: MicroBlaze gcc compiler' + $(CC) -Wall -Os -g3 -c -fmessage-length=0 -MT"$@" -I../bsp/microblaze_ps/include -mlittle-endian -mxl-barrel-shift -mxl-pattern-compare -mno-xl-soft-div -mcpu=v11.0 -mno-xl-soft-mul -Wl,--no-relax -ffunction-sections -fdata-sections -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + + diff --git a/datalink814_sp/build/src/adi_noos/drivers/axi_core/axi_dmac/subdir.mk b/datalink814_sp/build/src/adi_noos/drivers/axi_core/axi_dmac/subdir.mk new file mode 100644 index 0000000..96c382f --- /dev/null +++ b/datalink814_sp/build/src/adi_noos/drivers/axi_core/axi_dmac/subdir.mk @@ -0,0 +1,24 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +# Add inputs and outputs from these tool invocations to the build variables +C_SRCS += \ +../src/adi_noos/drivers/axi_core/axi_dmac/axi_dmac.c + +OBJS += \ +./src/adi_noos/drivers/axi_core/axi_dmac/axi_dmac.o + +C_DEPS += \ +./src/adi_noos/drivers/axi_core/axi_dmac/axi_dmac.d + + +# Each subdirectory must supply rules for building sources it contributes +src/adi_noos/drivers/axi_core/axi_dmac/%.o: ../src/adi_noos/drivers/axi_core/axi_dmac/%.c + @echo 'Building file: $<' + @echo 'Invoking: MicroBlaze gcc compiler' + $(CC) -Wall -Os -g3 -c -fmessage-length=0 -MT"$@" -I../bsp/microblaze_ps/include -mlittle-endian -mxl-barrel-shift -mxl-pattern-compare -mno-xl-soft-div -mcpu=v11.0 -mno-xl-soft-mul -Wl,--no-relax -ffunction-sections -fdata-sections -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + + diff --git a/datalink814_sp/build/src/adi_noos/drivers/axi_core/spi_engine/subdir.mk b/datalink814_sp/build/src/adi_noos/drivers/axi_core/spi_engine/subdir.mk new file mode 100644 index 0000000..ec50f17 --- /dev/null +++ b/datalink814_sp/build/src/adi_noos/drivers/axi_core/spi_engine/subdir.mk @@ -0,0 +1,24 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +# Add inputs and outputs from these tool invocations to the build variables +C_SRCS += \ +../src/adi_noos/drivers/axi_core/spi_engine/spi_engine.c + +OBJS += \ +./src/adi_noos/drivers/axi_core/spi_engine/spi_engine.o + +C_DEPS += \ +./src/adi_noos/drivers/axi_core/spi_engine/spi_engine.d + + +# Each subdirectory must supply rules for building sources it contributes +src/adi_noos/drivers/axi_core/spi_engine/%.o: ../src/adi_noos/drivers/axi_core/spi_engine/%.c + @echo 'Building file: $<' + @echo 'Invoking: MicroBlaze gcc compiler' + $(CC) -Wall -Os -g3 -c -fmessage-length=0 -MT"$@" -I../bsp/microblaze_ps/include -mlittle-endian -mxl-barrel-shift -mxl-pattern-compare -mno-xl-soft-div -mcpu=v11.0 -mno-xl-soft-mul -Wl,--no-relax -ffunction-sections -fdata-sections -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + + diff --git a/datalink814_sp/build/src/adi_noos/drivers/frequency/ad9516/subdir.mk b/datalink814_sp/build/src/adi_noos/drivers/frequency/ad9516/subdir.mk new file mode 100644 index 0000000..7db893f --- /dev/null +++ b/datalink814_sp/build/src/adi_noos/drivers/frequency/ad9516/subdir.mk @@ -0,0 +1,24 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +# Add inputs and outputs from these tool invocations to the build variables +C_SRCS += \ +../src/adi_noos/drivers/frequency/ad9516/ad9516.c + +OBJS += \ +./src/adi_noos/drivers/frequency/ad9516/ad9516.o + +C_DEPS += \ +./src/adi_noos/drivers/frequency/ad9516/ad9516.d + + +# Each subdirectory must supply rules for building sources it contributes +src/adi_noos/drivers/frequency/ad9516/%.o: ../src/adi_noos/drivers/frequency/ad9516/%.c + @echo 'Building file: $<' + @echo 'Invoking: MicroBlaze gcc compiler' + $(CC) -Wall -Os -g3 -c -fmessage-length=0 -MT"$@" -I../bsp/microblaze_ps/include -mlittle-endian -mxl-barrel-shift -mxl-pattern-compare -mno-xl-soft-div -mcpu=v11.0 -mno-xl-soft-mul -Wl,--no-relax -ffunction-sections -fdata-sections -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + + diff --git a/datalink814_sp/build/src/adi_noos/drivers/platform/subdir.mk b/datalink814_sp/build/src/adi_noos/drivers/platform/subdir.mk new file mode 100644 index 0000000..68588c7 --- /dev/null +++ b/datalink814_sp/build/src/adi_noos/drivers/platform/subdir.mk @@ -0,0 +1,39 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +# Add inputs and outputs from these tool invocations to the build variables +C_SRCS += \ +../src/adi_noos/drivers/platform/axi_io.c \ +../src/adi_noos/drivers/platform/delay.c \ +../src/adi_noos/drivers/platform/xilinx_gpio.c \ +../src/adi_noos/drivers/platform/xilinx_irq.c \ +../src/adi_noos/drivers/platform/xilinx_spi.c \ +../src/adi_noos/drivers/platform/xilinx_spi_pl.c + +OBJS += \ +./src/adi_noos/drivers/platform/axi_io.o \ +./src/adi_noos/drivers/platform/delay.o \ +./src/adi_noos/drivers/platform/xilinx_gpio.o \ +./src/adi_noos/drivers/platform/xilinx_irq.o \ +./src/adi_noos/drivers/platform/xilinx_spi.o \ +./src/adi_noos/drivers/platform/xilinx_spi_pl.o + +C_DEPS += \ +./src/adi_noos/drivers/platform/axi_io.d \ +./src/adi_noos/drivers/platform/delay.d \ +./src/adi_noos/drivers/platform/xilinx_gpio.d \ +./src/adi_noos/drivers/platform/xilinx_irq.d \ +./src/adi_noos/drivers/platform/xilinx_spi.d \ +./src/adi_noos/drivers/platform/xilinx_spi_pl.d + + +# Each subdirectory must supply rules for building sources it contributes +src/adi_noos/drivers/platform/%.o: ../src/adi_noos/drivers/platform/%.c + @echo 'Building file: $<' + @echo 'Invoking: MicroBlaze gcc compiler' + $(CC) -Wall -Os -g3 -c -fmessage-length=0 -MT"$@" -I../bsp/microblaze_ps/include -mlittle-endian -mxl-barrel-shift -mxl-pattern-compare -mno-xl-soft-div -mcpu=v11.0 -mno-xl-soft-mul -Wl,--no-relax -ffunction-sections -fdata-sections -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + + diff --git a/datalink814_sp/build/src/adi_noos/drivers/rf-transceiver/ad9361_reg/subdir.mk b/datalink814_sp/build/src/adi_noos/drivers/rf-transceiver/ad9361_reg/subdir.mk new file mode 100644 index 0000000..29890b8 --- /dev/null +++ b/datalink814_sp/build/src/adi_noos/drivers/rf-transceiver/ad9361_reg/subdir.mk @@ -0,0 +1,24 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +# Add inputs and outputs from these tool invocations to the build variables +C_SRCS += \ +../src/adi_noos/drivers/rf-transceiver/ad9361_reg/ad9361_reg.c + +OBJS += \ +./src/adi_noos/drivers/rf-transceiver/ad9361_reg/ad9361_reg.o + +C_DEPS += \ +./src/adi_noos/drivers/rf-transceiver/ad9361_reg/ad9361_reg.d + + +# Each subdirectory must supply rules for building sources it contributes +src/adi_noos/drivers/rf-transceiver/ad9361_reg/%.o: ../src/adi_noos/drivers/rf-transceiver/ad9361_reg/%.c + @echo 'Building file: $<' + @echo 'Invoking: MicroBlaze gcc compiler' + $(CC) -Wall -Os -g3 -c -fmessage-length=0 -MT"$@" -I../bsp/microblaze_ps/include -mlittle-endian -mxl-barrel-shift -mxl-pattern-compare -mno-xl-soft-div -mcpu=v11.0 -mno-xl-soft-mul -Wl,--no-relax -ffunction-sections -fdata-sections -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + + diff --git a/datalink814_sp/build/src/axi_dma/subdir.mk b/datalink814_sp/build/src/axi_dma/subdir.mk new file mode 100644 index 0000000..a9d7f0b --- /dev/null +++ b/datalink814_sp/build/src/axi_dma/subdir.mk @@ -0,0 +1,22 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +# Add inputs and outputs from these tool invocations to the build variables +C_SRCS += \ +../src/axi_dma/axi_dma.c + +OBJS += \ +./src/axi_dma/axi_dma.o + +C_DEPS += \ +./src/axi_dma/axi_dma.d + + +# Each subdirectory must supply rules for building sources it contributes +src/axi_dma/%.o: ../src/axi_dma/%.c + @echo 'Building file: $<' + @echo 'Invoking: MicroBlaze gcc compiler' + $(CC) -Wall -Os -g3 -c -fmessage-length=0 -MT"$@" -I../bsp/microblaze_ps/include -mlittle-endian -mxl-barrel-shift -mxl-pattern-compare -mno-xl-soft-div -mcpu=v11.0 -mno-xl-soft-mul -Wl,--no-relax -ffunction-sections -fdata-sections -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' \ No newline at end of file diff --git a/datalink814_sp/build/src/c2c_bridge/subdir.mk b/datalink814_sp/build/src/c2c_bridge/subdir.mk new file mode 100644 index 0000000..71b53f6 --- /dev/null +++ b/datalink814_sp/build/src/c2c_bridge/subdir.mk @@ -0,0 +1,24 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +# Add inputs and outputs from these tool invocations to the build variables +C_SRCS += \ +../src/c2c_bridge/c2c_bridge.c + +OBJS += \ +./src/c2c_bridge/c2c_bridge.o + +C_DEPS += \ +./src/c2c_bridge/c2c_bridge.d + + +# Each subdirectory must supply rules for building sources it contributes +src/c2c_bridge/%.o: ../src/c2c_bridge/%.c + @echo 'Building file: $<' + @echo 'Invoking: MicroBlaze gcc compiler' + $(CC) -Wall -Os -g3 -c -fmessage-length=0 -MT"$@" -I../bsp/microblaze_ps/include -mlittle-endian -mxl-barrel-shift -mxl-pattern-compare -mno-xl-soft-div -mcpu=v11.0 -mno-xl-soft-mul -Wl,--no-relax -ffunction-sections -fdata-sections -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + + diff --git a/datalink814_sp/build/src/circ_queue/subdir.mk b/datalink814_sp/build/src/circ_queue/subdir.mk new file mode 100644 index 0000000..eda70bd --- /dev/null +++ b/datalink814_sp/build/src/circ_queue/subdir.mk @@ -0,0 +1,24 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +# Add inputs and outputs from these tool invocations to the build variables +C_SRCS += \ +../src/circ_queue/circ_queue.c + +OBJS += \ +./src/circ_queue/circ_queue.o + +C_DEPS += \ +./src/circ_queue/circ_queue.d + + +# Each subdirectory must supply rules for building sources it contributes +src/circ_queue/%.o: ../src/circ_queue/%.c + @echo 'Building file: $<' + @echo 'Invoking: MicroBlaze gcc compiler' + $(CC) -Wall -Os -g3 -c -fmessage-length=0 -MT"$@" -I../bsp/microblaze_ps/include -mlittle-endian -mxl-barrel-shift -mxl-pattern-compare -mno-xl-soft-div -mcpu=v11.0 -mno-xl-soft-mul -Wl,--no-relax -ffunction-sections -fdata-sections -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + + diff --git a/datalink814_sp/build/src/dev_profile/subdir.mk b/datalink814_sp/build/src/dev_profile/subdir.mk new file mode 100644 index 0000000..72ef263 --- /dev/null +++ b/datalink814_sp/build/src/dev_profile/subdir.mk @@ -0,0 +1,27 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +# Add inputs and outputs from these tool invocations to the build variables +C_SRCS += \ +../src/dev_profile/ad9361_reg_profile.c \ +../src/dev_profile/ad9516_profile.c + +OBJS += \ +./src/dev_profile/ad9361_reg_profile.o \ +./src/dev_profile/ad9516_profile.o + +C_DEPS += \ +./src/dev_profile/ad9361_reg_profile.d \ +./src/dev_profile/ad9516_profile.d + + +# Each subdirectory must supply rules for building sources it contributes +src/dev_profile/%.o: ../src/dev_profile/%.c + @echo 'Building file: $<' + @echo 'Invoking: MicroBlaze gcc compiler' + $(CC) -Wall -Os -g3 -c -fmessage-length=0 -MT"$@" -I../bsp/microblaze_ps/include -mlittle-endian -mxl-barrel-shift -mxl-pattern-compare -mno-xl-soft-div -mcpu=v11.0 -mno-xl-soft-mul -Wl,--no-relax -ffunction-sections -fdata-sections -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + + diff --git a/datalink814_sp/build/src/inter_comm/subdir.mk b/datalink814_sp/build/src/inter_comm/subdir.mk new file mode 100644 index 0000000..af91b46 --- /dev/null +++ b/datalink814_sp/build/src/inter_comm/subdir.mk @@ -0,0 +1,24 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +# Add inputs and outputs from these tool invocations to the build variables +C_SRCS += \ +../src/inter_comm/inter_comm.c + +OBJS += \ +./src/inter_comm/inter_comm.o + +C_DEPS += \ +./src/inter_comm/inter_comm.d + + +# Each subdirectory must supply rules for building sources it contributes +src/inter_comm/%.o: ../src/inter_comm/%.c + @echo 'Building file: $<' + @echo 'Invoking: MicroBlaze gcc compiler' + $(CC) -Wall -Os -g3 -c -fmessage-length=0 -MT"$@" -I../bsp/microblaze_ps/include -mlittle-endian -mxl-barrel-shift -mxl-pattern-compare -mno-xl-soft-div -mcpu=v11.0 -mno-xl-soft-mul -Wl,--no-relax -ffunction-sections -fdata-sections -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + + diff --git a/datalink814_sp/build/src/phy_ctrl/subdir.mk b/datalink814_sp/build/src/phy_ctrl/subdir.mk new file mode 100644 index 0000000..a360670 --- /dev/null +++ b/datalink814_sp/build/src/phy_ctrl/subdir.mk @@ -0,0 +1,27 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +# Add inputs and outputs from these tool invocations to the build variables +C_SRCS += \ +../src/phy_ctrl/antenna.c \ +../src/phy_ctrl/phy_ctrl.c + +OBJS += \ +./src/phy_ctrl/antenna.o \ +./src/phy_ctrl/phy_ctrl.o + +C_DEPS += \ +./src/phy_ctrl/antenna.d \ +./src/phy_ctrl/phy_ctrl.d + + +# Each subdirectory must supply rules for building sources it contributes +src/phy_ctrl/%.o: ../src/phy_ctrl/%.c + @echo 'Building file: $<' + @echo 'Invoking: MicroBlaze gcc compiler' + $(CC) -Wall -Os -g3 -c -fmessage-length=0 -MT"$@" -I../bsp/microblaze_ps/include -mlittle-endian -mxl-barrel-shift -mxl-pattern-compare -mno-xl-soft-div -mcpu=v11.0 -mno-xl-soft-mul -Wl,--no-relax -ffunction-sections -fdata-sections -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + + diff --git a/datalink814_sp/build/src/subdir.mk b/datalink814_sp/build/src/subdir.mk new file mode 100644 index 0000000..a4c3be8 --- /dev/null +++ b/datalink814_sp/build/src/subdir.mk @@ -0,0 +1,30 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +# Add inputs and outputs from these tool invocations to the build variables +LD_SRCS += \ +../src/lscript.ld + +C_SRCS += \ +../src/common.c \ +../src/main.c + +OBJS += \ +./src/common.o \ +./src/main.o + +C_DEPS += \ +./src/common.d \ +./src/main.d + + +# Each subdirectory must supply rules for building sources it contributes +src/%.o: ../src/%.c + @echo 'Building file: $<' + @echo 'Invoking: MicroBlaze gcc compiler' + $(CC) -Wall -Os -g3 -c -fmessage-length=0 -MT"$@" -I../bsp/microblaze_ps/include -mlittle-endian -mxl-barrel-shift -mxl-pattern-compare -mno-xl-soft-div -mcpu=v11.0 -mno-xl-soft-mul -Wl,--no-relax -ffunction-sections -fdata-sections -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + + diff --git a/datalink814_sp/build/src/time_ctrl/subdir.mk b/datalink814_sp/build/src/time_ctrl/subdir.mk new file mode 100644 index 0000000..f07fc63 --- /dev/null +++ b/datalink814_sp/build/src/time_ctrl/subdir.mk @@ -0,0 +1,24 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +# Add inputs and outputs from these tool invocations to the build variables +C_SRCS += \ +../src/time_ctrl/time_ctrl.c + +OBJS += \ +./src/time_ctrl/time_ctrl.o + +C_DEPS += \ +./src/time_ctrl/time_ctrl.d + + +# Each subdirectory must supply rules for building sources it contributes +src/time_ctrl/%.o: ../src/time_ctrl/%.c + @echo 'Building file: $<' + @echo 'Invoking: MicroBlaze gcc compiler' + $(CC) -Wall -Os -g3 -c -fmessage-length=0 -MT"$@" -I../bsp/microblaze_ps/include -mlittle-endian -mxl-barrel-shift -mxl-pattern-compare -mno-xl-soft-div -mcpu=v11.0 -mno-xl-soft-mul -Wl,--no-relax -ffunction-sections -fdata-sections -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + + diff --git a/datalink814_sp/build/src/util/subdir.mk b/datalink814_sp/build/src/util/subdir.mk new file mode 100644 index 0000000..ffef95b --- /dev/null +++ b/datalink814_sp/build/src/util/subdir.mk @@ -0,0 +1,27 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +# Add inputs and outputs from these tool invocations to the build variables +C_SRCS += \ +../src/util/crc.c \ +../src/util/util.c + +OBJS += \ +./src/util/crc.o \ +./src/util/util.o + +C_DEPS += \ +./src/util/crc.d \ +./src/util/util.d + + +# Each subdirectory must supply rules for building sources it contributes +src/util/%.o: ../src/util/%.c + @echo 'Building file: $<' + @echo 'Invoking: MicroBlaze gcc compiler' + $(CC) -Wall -Os -g3 -c -fmessage-length=0 -MT"$@" -I../bsp/microblaze_ps/include -mlittle-endian -mxl-barrel-shift -mxl-pattern-compare -mno-xl-soft-div -mcpu=v11.0 -mno-xl-soft-mul -Wl,--no-relax -ffunction-sections -fdata-sections -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + + diff --git a/datalink814_sp/src/adi_noos/drivers/api/gpio.c b/datalink814_sp/src/adi_noos/drivers/api/gpio.c new file mode 100644 index 0000000..9742613 --- /dev/null +++ b/datalink814_sp/src/adi_noos/drivers/api/gpio.c @@ -0,0 +1,184 @@ +/***************************************************************************//** + * @file gpio.c + * @brief Implementation of the GPIO Interface + * @author Antoniu Miclaus (antoniu.miclaus@analog.com) +******************************************************************************** + * Copyright 2020(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#include +#include +#include "../../include/gpio.h" +#include "../../include/error.h" + +/******************************************************************************/ +/************************ Functions Definitions *******************************/ +/******************************************************************************/ + +/** + * @brief Obtain the GPIO decriptor. + * @param desc - The GPIO descriptor. + * @param param - GPIO Initialization parameters. + * @return SUCCESS in case of success, FAILURE otherwise. + */ +int32_t gpio_get(struct gpio_desc **desc, + const struct gpio_init_param *param) +{ + if (!param) + return FAILURE; + + if ((param->platform_ops->gpio_ops_get(desc, param))) + return FAILURE; + + (*desc)->platform_ops = param->platform_ops; + + return SUCCESS; +} + +/** + * @brief Get the value of an optional GPIO. + * @param desc - The GPIO descriptor. + * @param param - GPIO Initialization parameters. + * @return SUCCESS in case of success, FAILURE otherwise. + */ +int32_t gpio_get_optional(struct gpio_desc **desc, + const struct gpio_init_param *param) +{ + if (!param || (param->number == -1)) { + *desc = NULL; + return SUCCESS; + } + + if ((param->platform_ops->gpio_ops_get_optional(desc, param))) + return FAILURE; + + (*desc)->platform_ops = param->platform_ops; + + return SUCCESS; +} +/** + * @brief Free the resources allocated by gpio_get(). + * @param desc - The GPIO descriptor. + * @return SUCCESS in case of success, FAILURE otherwise. + */ +int32_t gpio_remove(struct gpio_desc *desc) +{ + if (desc) + return desc->platform_ops->gpio_ops_remove(desc); + else + return SUCCESS; +} + +/** + * @brief Enable the input direction of the specified GPIO. + * @param desc - The GPIO descriptor. + * @return SUCCESS in case of success, FAILURE otherwise. + */ +int32_t gpio_direction_input(struct gpio_desc *desc) +{ + if (desc) + return desc->platform_ops->gpio_ops_direction_input(desc); + else + return SUCCESS; +} + +/** + * @brief Enable the output direction of the specified GPIO. + * @param desc - The GPIO descriptor. + * @param value - The value. + * Example: GPIO_HIGH + * GPIO_LOW + * @return SUCCESS in case of success, FAILURE otherwise. + */ +int32_t gpio_direction_output(struct gpio_desc *desc, + uint8_t value) +{ + if (desc) + return desc->platform_ops-> + gpio_ops_direction_output(desc, value); + else + return SUCCESS; +} + +/** + * @brief Get the direction of the specified GPIO. + * @param desc - The GPIO descriptor. + * @param direction - The direction. + * Example: GPIO_OUT + * GPIO_IN + * @return SUCCESS in case of success, FAILURE otherwise. + */ +int32_t gpio_get_direction(struct gpio_desc *desc, + uint8_t *direction) +{ + if (desc) + return desc->platform_ops-> + gpio_ops_get_direction(desc, direction); + else + return SUCCESS; +} + +/** + * @brief Set the value of the specified GPIO. + * @param desc - The GPIO descriptor. + * @param value - The value. + * Example: GPIO_HIGH + * GPIO_LOW + * @return SUCCESS in case of success, FAILURE otherwise. + */ +int32_t gpio_set_value(struct gpio_desc *desc, + uint8_t value) +{ + if (desc) + return desc->platform_ops->gpio_ops_set_value(desc, value); + else + return SUCCESS; +} + +/** + * @brief Get the value of the specified GPIO. + * @param desc - The GPIO descriptor. + * @param value - The value. + * Example: GPIO_HIGH + * GPIO_LOW + * @return SUCCESS in case of success, FAILURE otherwise. + */ +int32_t gpio_get_value(struct gpio_desc *desc, + uint8_t *value) +{ + if (desc) + return desc->platform_ops->gpio_ops_get_value(desc, value); + else + return SUCCESS; +} diff --git a/datalink814_sp/src/adi_noos/drivers/api/irq.c b/datalink814_sp/src/adi_noos/drivers/api/irq.c new file mode 100644 index 0000000..937c57f --- /dev/null +++ b/datalink814_sp/src/adi_noos/drivers/api/irq.c @@ -0,0 +1,153 @@ +/***************************************************************************//** + * @file irq.c + * @brief Implementation of the IRQ Interface + * @author Andrei Porumb (andrei.porumb@analog.com) +******************************************************************************** + * Copyright 2021(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#include +#include +#include "../../include/irq.h" +#include "../../include/error.h" + +/** + * @brief Initialize the IRQ interrupts. + * @param desc - The IRQ descriptor. + * @param param - The structure that contains the IRQ parameters. + * @return SUCCESS in case of success, FAILURE otherwise. + */ +int32_t irq_ctrl_init(struct irq_ctrl_desc **desc, + const struct irq_init_param *param) +{ + if (!param) + return FAILURE; + + if ((param->platform_ops->init(desc, param))) + return FAILURE; + + (*desc)->platform_ops = param->platform_ops; + + return SUCCESS; +} + +/** + * @brief Free the resources allocated by irq_ctrl_init(). + * @param desc - The SPI descriptor. + * @return SUCCESS in case of success, FAILURE otherwise. + */ +int32_t irq_ctrl_remove(struct irq_ctrl_desc *desc) +{ + return desc->platform_ops->remove(desc); +} + +/** + * @brief Register a callback to handle the irq events. + * @param desc - The IRQ controller descriptor. + * @param irq_id - Interrupt identifier. + * @param callback_desc - Callback descriptor + * @return SUCCESS in case of success, FAILURE otherwise. + */ +int32_t irq_register_callback(struct irq_ctrl_desc *desc, uint32_t irq_id, + struct callback_desc *callback_desc) +{ + return desc->platform_ops->register_callback(desc, irq_id, callback_desc); +} + +/** + * @brief Unregisters a generic IRQ handling function. + * @param desc - The IRQ controller descriptor. + * @param irq_id - Interrupt identifier. + * @return SUCCESS in case of success, FAILURE otherwise. + */ +int32_t irq_unregister(struct irq_ctrl_desc *desc, uint32_t irq_id) +{ + return desc->platform_ops->unregister(desc, irq_id); +} + +/** + * @brief Enable global interrupts. + * @return SUCCESS in case of success, FAILURE otherwise. + */ +int32_t irq_global_enable(struct irq_ctrl_desc *desc) +{ + return desc->platform_ops->global_enable(desc); +} + +/** + * @brief Disable global interrupts. + * @return SUCCESS in case of success, FAILURE otherwise. + */ +int32_t irq_global_disable(struct irq_ctrl_desc *desc) +{ + return desc->platform_ops->global_disable(desc); +} + +/** + * @brief Set interrupt trigger level. + * @param desc - The IRQ controller descriptor. + * @param irq_id - Interrupt identifier. + * @param trig - New trigger level for the interrupt. + * @return SUCCESS in case of success, FAILURE otherwise. + */ +int32_t irq_trigger_level_set(struct irq_ctrl_desc *desc, uint32_t irq_id, + enum irq_trig_level trig) +{ + if(desc->platform_ops->trigger_level_set) + return desc->platform_ops->trigger_level_set(desc, irq_id, trig); + else + return ENOSYS; +} + +/** + * @brief Enable specific interrupt. + * @param desc - The IRQ controller descriptor. + * @param irq_id - Interrupt identifier. + * @return SUCCESS in case of success, FAILURE otherwise. + */ +int32_t irq_enable(struct irq_ctrl_desc *desc, uint32_t irq_id) +{ + return desc->platform_ops->enable(desc, irq_id); +} + +/** + * @brief Disable specific interrupt. + * @param desc - The IRQ controller descriptor. + * @param irq_id - Interrupt identifier. + * @return SUCCESS in case of success, FAILURE otherwise. + */ +int32_t irq_disable(struct irq_ctrl_desc *desc, uint32_t irq_id) +{ + return desc->platform_ops->disable(desc, irq_id); +} diff --git a/datalink814_sp/src/adi_noos/drivers/api/spi.c b/datalink814_sp/src/adi_noos/drivers/api/spi.c new file mode 100644 index 0000000..c114eda --- /dev/null +++ b/datalink814_sp/src/adi_noos/drivers/api/spi.c @@ -0,0 +1,144 @@ +/***************************************************************************//** + * @file spi.c + * @brief Implementation of the SPI Interface + * @author Antoniu Miclaus (antoniu.miclaus@analog.com) +******************************************************************************** + * Copyright 2020(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#include +#include +#include +#include "../../include/spi.h" +#include "../../include/error.h" + +/** + * @brief Initialize the SPI communication peripheral. + * @param desc - The SPI descriptor. + * @param param - The structure that contains the SPI parameters. + * @return SUCCESS in case of success, FAILURE otherwise. + */ +int32_t spi_init(struct spi_desc **desc, + const struct spi_init_param *param) +{ + if (!param) + return FAILURE; + + if ((param->platform_ops->init(desc, param))) + return FAILURE; + + (*desc)->platform_ops = param->platform_ops; + + return SUCCESS; +} + +/** + * @brief Free the resources allocated by spi_init(). + * @param desc - The SPI descriptor. + * @return SUCCESS in case of success, FAILURE otherwise. + */ +int32_t spi_remove(struct spi_desc *desc) +{ + return desc->platform_ops->remove(desc); +} + +/** + * @brief Write and read data to/from SPI. + * @param desc - The SPI descriptor. + * @param data - The buffer with the transmitted/received data. + * @param bytes_number - Number of bytes to write/read. + * @return SUCCESS in case of success, FAILURE otherwise. + */ +int32_t spi_write_and_read(struct spi_desc *desc, + uint8_t *data, + uint16_t bytes_number) +{ + return desc->platform_ops->write_and_read(desc, data, bytes_number); +} + +/** + * @brief Write and read data to/from SPI in 3 wire mode. + * @param desc - The SPI descriptor. + * @param write_data - The buffer with the transmitted data. + * @param read_data - The buffer with the received data. + * @param write_bytes_number - Number of bytes to write. + * @param read_bytes_number - Number of bytes to read. + * @return SUCCESS in case of success, FAILURE otherwise. + */ +int32_t spi_write_and_read_3wire(struct spi_desc *desc, + uint8_t *write_data, + uint8_t *read_data, + uint16_t write_bytes_number, + uint16_t read_bytes_number) +{ + int ret; + if(desc->platform_ops->write_and_read_3wire != NULL){ + return desc->platform_ops->write_and_read_3wire(desc, write_data, read_data, + write_bytes_number, read_bytes_number); + } + else{ + return FAILURE; + } +} + + +/** + * @brief Iterate over head list and send all spi messages + * @param desc - The SPI descriptor. + * @param msgs - Array of messages. + * @param len - Number of messages in the array. + * @return SUCCESS in case of success, negativ error code otherwise. + */ +int32_t spi_transfer(struct spi_desc *desc, struct spi_msg *msgs, uint32_t len) +{ + int32_t ret; + uint32_t i; + + if (!desc || !desc->platform_ops) + return -EINVAL; + + if (desc->platform_ops->transfer) + return desc->platform_ops->transfer(desc, msgs, len); + + for (i = 0; i < len; i++) { + if (msgs[i].rx_buff != msgs[i].tx_buff || !msgs[i].tx_buff) + return -EINVAL; + ret = spi_write_and_read(desc, msgs[i].rx_buff, + msgs[i].bytes_number); + if (IS_ERR_VALUE(ret)) + return ret; + } + + return SUCCESS; +} diff --git a/datalink814_sp/src/adi_noos/drivers/axi_core/axi_dmac/axi_dmac.c b/datalink814_sp/src/adi_noos/drivers/axi_core/axi_dmac/axi_dmac.c new file mode 100644 index 0000000..7964fbf --- /dev/null +++ b/datalink814_sp/src/adi_noos/drivers/axi_core/axi_dmac/axi_dmac.c @@ -0,0 +1,328 @@ +/***************************************************************************//** + * @file axi_dmac.c + * @brief Driver for the Analog Devices AXI-DMAC core. + * @author DBogdan (dragos.bogdan@analog.com) +******************************************************************************** + * Copyright 2018(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include +#include +#include +#include +#include "../../../include/axi_io.h" +#include "../../../include/error.h" +#include "../axi_dmac/axi_dmac.h" + +/***************************************************************************//** + * @brief dma_isr +*******************************************************************************/ +void axi_dmac_default_isr(void *instance) +{ + struct axi_dmac *dmac = (struct axi_dmac *)instance; + uint32_t remaining_size, burst_size; + uint32_t reg_val; + + /* Get interrupt sources and clear interrupts. */ + axi_dmac_read(dmac, AXI_DMAC_REG_IRQ_PENDING, ®_val); + axi_dmac_write(dmac, AXI_DMAC_REG_IRQ_PENDING, reg_val); + + if ((reg_val & AXI_DMAC_IRQ_SOT) && (dmac->big_transfer.size != 0)) { + remaining_size = dmac->big_transfer.size - + dmac->big_transfer.size_done; + burst_size = (remaining_size <= dmac->transfer_max_size) ? + remaining_size : dmac->transfer_max_size; + + dmac->big_transfer.size_done += burst_size; + dmac->big_transfer.address += burst_size; + switch (dmac->direction) { + case DMA_DEV_TO_MEM: + axi_dmac_write(dmac, AXI_DMAC_REG_DEST_ADDRESS, + dmac->big_transfer.address); + axi_dmac_write(dmac, AXI_DMAC_REG_DEST_STRIDE, 0x0); + break; + case DMA_MEM_TO_DEV: + axi_dmac_write(dmac, AXI_DMAC_REG_SRC_ADDRESS, + dmac->big_transfer.address); + axi_dmac_write(dmac, AXI_DMAC_REG_SRC_STRIDE, 0x0); + break; + default: + return; // Other directions are not supported yet + } + /* The current transfer was started and a new one is queued. */ + axi_dmac_write(dmac, AXI_DMAC_REG_X_LENGTH, + burst_size); + axi_dmac_write(dmac, AXI_DMAC_REG_Y_LENGTH, 0x0); + + axi_dmac_write(dmac, AXI_DMAC_REG_START_TRANSFER, 0x1); + } + if (reg_val & AXI_DMAC_IRQ_EOT) { + dmac->big_transfer.transfer_done = true; + dmac->big_transfer.address = 0; + dmac->big_transfer.size = 0; + dmac->big_transfer.size_done = 0; + } +} + +/***************************************************************************//** + * @brief axi_dmac_read + *******************************************************************************/ +int32_t axi_dmac_read(struct axi_dmac *dmac, + uint32_t reg_addr, + uint32_t *reg_data) +{ + axi_io_read(dmac->base, reg_addr, reg_data); + + return SUCCESS; +} + +/***************************************************************************//** + * @brief axi_dmac_write + *******************************************************************************/ +int32_t axi_dmac_write(struct axi_dmac *dmac, + uint32_t reg_addr, + uint32_t reg_data) +{ + axi_io_write(dmac->base, reg_addr, reg_data); + + return SUCCESS; +} + +/***************************************************************************//** + * @brief axi_dmac_transfer_nonblock + *******************************************************************************/ +int32_t axi_dmac_transfer_nonblocking(struct axi_dmac *dmac, + uint32_t address, uint32_t size) +{ + uint32_t reg_val; + + if (size == 0) + return SUCCESS; /* nothing to do */ + + axi_dmac_read(dmac, AXI_DMAC_REG_CTRL, ®_val); + if (!(reg_val & AXI_DMAC_CTRL_ENABLE)) { + axi_dmac_write(dmac, AXI_DMAC_REG_CTRL, 0x0); + axi_dmac_write(dmac, AXI_DMAC_REG_CTRL, AXI_DMAC_CTRL_ENABLE); + axi_dmac_write(dmac, AXI_DMAC_REG_IRQ_MASK, 0x0); + } + + axi_dmac_read(dmac, AXI_DMAC_REG_START_TRANSFER, ®_val); + if (!(reg_val & 1)) { + switch (dmac->direction) { + case DMA_DEV_TO_MEM: + axi_dmac_write(dmac, AXI_DMAC_REG_DEST_ADDRESS, address); + axi_dmac_write(dmac, AXI_DMAC_REG_DEST_STRIDE, 0x0); + break; + case DMA_MEM_TO_DEV: + axi_dmac_write(dmac, AXI_DMAC_REG_SRC_ADDRESS, address); + axi_dmac_write(dmac, AXI_DMAC_REG_SRC_STRIDE, 0x0); + break; + default: + return FAILURE; // Other directions are not supported yet + } + if ((size - 1) > dmac->transfer_max_size) { + dmac->big_transfer.address = address; + dmac->big_transfer.size = size - 1; + dmac->big_transfer.size_done = dmac->transfer_max_size; + + axi_dmac_write(dmac, AXI_DMAC_REG_X_LENGTH, + dmac->transfer_max_size); + axi_dmac_write(dmac, AXI_DMAC_REG_Y_LENGTH, 0x0); + + axi_dmac_write(dmac, AXI_DMAC_REG_FLAGS, dmac->flags); + + axi_dmac_write(dmac, AXI_DMAC_REG_START_TRANSFER, 0x1); + } else { + axi_dmac_write(dmac, AXI_DMAC_REG_X_LENGTH, + size - 1); + axi_dmac_write(dmac, AXI_DMAC_REG_Y_LENGTH, 0x0); + + axi_dmac_write(dmac, AXI_DMAC_REG_FLAGS, dmac->flags); + + axi_dmac_write(dmac, AXI_DMAC_REG_START_TRANSFER, 0x1); + } + } else { + return FAILURE; + } + + return SUCCESS; +} + +/***************************************************************************//** + * @brief axi_dmac_is_transfer_ready + *******************************************************************************/ +int32_t axi_dmac_is_transfer_ready(struct axi_dmac *dmac, bool *rdy) +{ + *rdy = dmac->big_transfer.transfer_done; + + return SUCCESS; +} + +/***************************************************************************//** + * @brief axi_dmac_transfer + *******************************************************************************/ +int32_t axi_dmac_transfer(struct axi_dmac *dmac, + uint32_t address, uint32_t size) +{ + uint32_t transfer_id; + uint32_t reg_val; + uint32_t timeout = 0; + + if (size == 0) + return SUCCESS; /* nothing to do */ + + axi_dmac_write(dmac, AXI_DMAC_REG_CTRL, 0x0); + axi_dmac_write(dmac, AXI_DMAC_REG_CTRL, AXI_DMAC_CTRL_ENABLE); + + axi_dmac_write(dmac, AXI_DMAC_REG_IRQ_MASK, 0x0); + + axi_dmac_read(dmac, AXI_DMAC_REG_TRANSFER_ID, &transfer_id); + axi_dmac_read(dmac, AXI_DMAC_REG_IRQ_PENDING, ®_val); + axi_dmac_write(dmac, AXI_DMAC_REG_IRQ_PENDING, reg_val); + + switch (dmac->direction) { + case DMA_DEV_TO_MEM: + axi_dmac_write(dmac, AXI_DMAC_REG_DEST_ADDRESS, address); + axi_dmac_write(dmac, AXI_DMAC_REG_DEST_STRIDE, 0x0); + break; + case DMA_MEM_TO_DEV: + axi_dmac_write(dmac, AXI_DMAC_REG_SRC_ADDRESS, address); + axi_dmac_write(dmac, AXI_DMAC_REG_SRC_STRIDE, 0x0); + break; + default: + return FAILURE; // Other directions are not supported yet + } + + if ((size - 1) > dmac->transfer_max_size) { + dmac->big_transfer.address = address; + dmac->big_transfer.size = size - 1; + dmac->big_transfer.size_done = dmac->transfer_max_size; + + axi_dmac_write(dmac, AXI_DMAC_REG_X_LENGTH, + dmac->transfer_max_size); + axi_dmac_write(dmac, AXI_DMAC_REG_Y_LENGTH, 0x0); + + axi_dmac_write(dmac, AXI_DMAC_REG_FLAGS, dmac->flags); + + axi_dmac_write(dmac, AXI_DMAC_REG_START_TRANSFER, 0x1); + + while(!dmac->big_transfer.transfer_done) { + timeout++; + if (timeout == UINT32_MAX) + return FAILURE; + } + + dmac->big_transfer.address = 0; + dmac->big_transfer.size = 0; + dmac->big_transfer.size_done = 0; + + return SUCCESS; + } + + axi_dmac_write(dmac, AXI_DMAC_REG_X_LENGTH, size - 1); + axi_dmac_write(dmac, AXI_DMAC_REG_Y_LENGTH, 0x0); + + axi_dmac_write(dmac, AXI_DMAC_REG_FLAGS, dmac->flags); + + axi_dmac_write(dmac, AXI_DMAC_REG_START_TRANSFER, 0x1); + + if (dmac->flags & DMA_CYCLIC) + return SUCCESS; + + /* Wait until the new transfer is queued. */ + do { + axi_dmac_read(dmac, AXI_DMAC_REG_START_TRANSFER, ®_val); + } while(reg_val == 1); + + /* Wait until the current transfer is completed. */ + do { + axi_dmac_read(dmac, AXI_DMAC_REG_IRQ_PENDING, ®_val); + if (reg_val == (AXI_DMAC_IRQ_SOT | AXI_DMAC_IRQ_EOT)) + break; + } while(!dmac->big_transfer.transfer_done); + if (reg_val != (AXI_DMAC_IRQ_SOT | AXI_DMAC_IRQ_EOT)) + axi_dmac_write(dmac, AXI_DMAC_REG_IRQ_PENDING, reg_val); + + /* Wait until the transfer with the ID transfer_id is completed. */ + do { + axi_dmac_read(dmac, AXI_DMAC_REG_TRANSFER_DONE, ®_val); + } while((reg_val & (1u << transfer_id)) != (1u << transfer_id)); + + return SUCCESS; +} + +/***************************************************************************//** + * @brief axi_dmac_init + *******************************************************************************/ +int32_t axi_dmac_init(struct axi_dmac **dmac_core, + const struct axi_dmac_init *init) +{ + struct axi_dmac *dmac; + + dmac = (struct axi_dmac *)malloc(sizeof(*dmac)); + if (!dmac) + return FAILURE; + + dmac->name = init->name; + dmac->base = init->base; + dmac->direction = init->direction; + dmac->flags = init->flags; + dmac->transfer_max_size = -1; + dmac->big_transfer.address = 0; + dmac->big_transfer.size = 0; + dmac->big_transfer.size_done = 0; + + axi_dmac_write(dmac, AXI_DMAC_REG_X_LENGTH, dmac->transfer_max_size); + axi_dmac_read(dmac, AXI_DMAC_REG_X_LENGTH, &dmac->transfer_max_size); + + *dmac_core = dmac; + + return SUCCESS; +} + +/***************************************************************************//** + * @brief axi_dmac_remove + *******************************************************************************/ +int32_t axi_dmac_remove(struct axi_dmac *dmac) +{ + if(!dmac) + return FAILURE; + + free(dmac); + + return SUCCESS; +} diff --git a/datalink814_sp/src/adi_noos/drivers/axi_core/axi_dmac/axi_dmac.h b/datalink814_sp/src/adi_noos/drivers/axi_core/axi_dmac/axi_dmac.h new file mode 100644 index 0000000..fc22223 --- /dev/null +++ b/datalink814_sp/src/adi_noos/drivers/axi_core/axi_dmac/axi_dmac.h @@ -0,0 +1,124 @@ +/***************************************************************************//** + * @file axi_dmac.h + * @brief Driver for the Analog Devices AXI-DMAC core. + * @author DBogdan (dragos.bogdan@analog.com) +******************************************************************************** + * Copyright 2018(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ +#ifndef AXI_DMAC_H_ +#define AXI_DMAC_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include +#include "../../../../util/util.h" + +/******************************************************************************/ +/********************** Macros and Constants Definitions **********************/ +/******************************************************************************/ +#define AXI_DMAC_REG_IRQ_MASK 0x80 +#define AXI_DMAC_REG_IRQ_PENDING 0x84 +#define AXI_DMAC_IRQ_SOT BIT(0) +#define AXI_DMAC_IRQ_EOT BIT(1) + +#define AXI_DMAC_REG_CTRL 0x400 +#define AXI_DMAC_CTRL_ENABLE BIT(0) +#define AXI_DMAC_CTRL_PAUSE BIT(1) + +#define AXI_DMAC_REG_TRANSFER_ID 0x404 +#define AXI_DMAC_REG_START_TRANSFER 0x408 +#define AXI_DMAC_REG_FLAGS 0x40c +#define AXI_DMAC_REG_DEST_ADDRESS 0x410 +#define AXI_DMAC_REG_SRC_ADDRESS 0x414 +#define AXI_DMAC_REG_X_LENGTH 0x418 +#define AXI_DMAC_REG_Y_LENGTH 0x41c +#define AXI_DMAC_REG_DEST_STRIDE 0x420 +#define AXI_DMAC_REG_SRC_STRIDE 0x424 +#define AXI_DMAC_REG_TRANSFER_DONE 0x428 + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ +enum dma_direction { + DMA_DEV_TO_MEM, + DMA_MEM_TO_DEV +}; + +enum dma_flags { + DMA_CYCLIC = 1, + DMA_LAST = 2 +}; + +struct axi_dma_transfer { + uint32_t size; + uint32_t address; + uint32_t size_done; + volatile bool transfer_done; +}; + +struct axi_dmac { + const char *name; + uint32_t base; + enum dma_direction direction; + uint32_t flags; + uint32_t transfer_max_size; + volatile struct axi_dma_transfer big_transfer; +}; + +struct axi_dmac_init { + const char *name; + uint32_t base; + enum dma_direction direction; + uint32_t flags; +}; + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ +void axi_dmac_default_isr(void *instance); +int32_t axi_dmac_read(struct axi_dmac *dmac, uint32_t reg_addr, + uint32_t *reg_data); +int32_t axi_dmac_write(struct axi_dmac *dmac, uint32_t reg_addr, + uint32_t reg_data); +int32_t axi_dmac_transfer_nonblocking(struct axi_dmac *dmac, + uint32_t address, uint32_t size); +int32_t axi_dmac_is_transfer_ready(struct axi_dmac *dmac, bool *rdy); +int32_t axi_dmac_transfer(struct axi_dmac *dmac, + uint32_t address, uint32_t size); +int32_t axi_dmac_init(struct axi_dmac **adc_core, + const struct axi_dmac_init *init); +int32_t axi_dmac_remove(struct axi_dmac *dmac); + +#endif diff --git a/datalink814_sp/src/adi_noos/drivers/axi_core/spi_engine/spi_engine.c b/datalink814_sp/src/adi_noos/drivers/axi_core/spi_engine/spi_engine.c new file mode 100644 index 0000000..702d97d --- /dev/null +++ b/datalink814_sp/src/adi_noos/drivers/axi_core/spi_engine/spi_engine.c @@ -0,0 +1,978 @@ +/******************************************************************************* + * @file spi_engine.c + * @brief Core implementation of the SPI Engine Driver. + * @author Sergiu Cuciurean (sergiu.cuciurean@analog.com) +******************************************************************************** + * Copyright 2019(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +/* In debug mode the printf function used in displaying the messages is causing +significant delays */ +//#define DEBUG_LEVEL 2 + +#include +#include +#include +#include +#include +#include + +#include "spi_engine.h" +#include "../axi_dmac/axi_dmac.h" +#include "../../../include/axi_io.h" +#include "../../../include/error.h" + +/** + * @brief Spi engine platform specific SPI platform ops structure + */ +const struct spi_platform_ops spi_eng_platform_ops = { + .init = &spi_engine_init, + .write_and_read = &spi_engine_spi_write_and_read, + .write_and_read_3wire = &spi_engine_spi_write_and_read_3wire, + .remove = &spi_engine_remove +}; + +/******************************************************************************/ +/***************************** Static variables *******************************/ +/******************************************************************************/ + +/** + * @brief Static variable used to sync transfers + * + */ +static uint8_t _sync_id = 0x01; + +/******************************************************************************/ +/************************** Functions Implementation **************************/ +/******************************************************************************/ + +/** + * @brief Write SPI Engine's axi registers + * + * @param desc Decriptor containing SPI Engine's parameters + * @param reg_addr The address of the SPI Engine's axi register where the data + * will be written + * @param reg_data Data that will be written + * @return int32_t This function allways returns SUCCESS + */ +int32_t spi_engine_write(struct spi_engine_desc *desc, + uint32_t reg_addr, + uint32_t reg_data) +{ + axi_io_write(desc->spi_engine_baseaddr, reg_addr, reg_data); + + return SUCCESS; +} + +/** + * @brief Read SPI Engine's axi registers + * + * @param desc Decriptor containing SPI Engine's parameters + * @param reg_addr The address of the SPI Engine's axi register from where the + * data where the data will be read + * @param reg_data Pointer where the read that will be stored + * @return int32_t This function allways returns SUCCESS + */ +int32_t spi_engine_read(struct spi_engine_desc *desc, + uint32_t reg_addr, + uint32_t *reg_data) +{ + axi_io_read(desc->spi_engine_baseaddr, reg_addr, reg_data); + return SUCCESS; +} + +/** + * @brief Set width of the transferred word over SPI + * + * @param desc Decriptor containing SPI interface parameters + * @param data_width The desired data width + * The supported values are: + * - 8 + * - 16 + * - 24 + * - 32 + */ +int32_t spi_engine_set_transfer_width(struct spi_desc *desc, + uint8_t data_width) +{ + struct spi_engine_desc *desc_extra; + + desc_extra = desc->extra; + + if (data_width > desc_extra->max_data_width) + desc_extra->data_width = desc_extra->max_data_width; + else + desc_extra->data_width = data_width; + + return SUCCESS; +} + +/** + * @brief Set SPI engine clock frequency + * + * @param desc Decriptor containing SPI Engine's parameters + * @param speed_hz SPI engine transfer speed + */ +void spi_engine_set_speed(struct spi_desc *desc, + uint32_t speed_hz) +{ + struct spi_engine_desc *desc_extra; + + desc_extra = desc->extra; + + desc_extra->clk_div = desc_extra->ref_clk_hz / + (2 * speed_hz) - 1; +} + +/** + * @brief Set the number of words transferred in a single transaction + * + * @param desc Decriptor containing SPI Engine's parameters + * @param bytes_number The number of bytes to be converted + * @return uint8_t A number of words in which bytes_number can be grouped + */ +static uint8_t spi_get_words_number(struct spi_engine_desc *desc, + uint8_t bytes_number) +{ + uint8_t xfer_word_len; + uint8_t words_number; + + xfer_word_len = desc->data_width / 8; + words_number = bytes_number / xfer_word_len; + + if ((bytes_number % xfer_word_len) != 0) + words_number++; + + return words_number; +} + +/** + * @brief Get the word length in bytes + * + * @param desc Decriptor containing SPI Engine's parameters + * @return uint8_t Number of bytes that fit in one word + */ +static uint8_t spi_get_word_length(struct spi_engine_desc *desc) +{ + uint8_t word_length; + + word_length = desc->data_width / 8; + + return word_length; +} + +/** + * @brief Compute the prescaler used to set the sleep period. + * + * @param desc Decriptor containing SPI interface parameters + * @param sleep_time_ns The amount of time where the transfer hangs + * @param sleep_div Clock prescaler + * @return int32_t This function allways returns SUCCESS + */ +static int32_t spi_get_sleep_div(struct spi_desc *desc, + uint32_t sleep_time_ns, + uint32_t *sleep_div) +{ + struct spi_engine_desc *eng_desc; + + eng_desc = desc->extra; + + /* + * Engine Wiki: + * + * The frequency of the SCLK signal is derived from the + * module clock frequency using the following formula: + * f_sclk = f_clk / ((div + 1) * 2) + */ + + *sleep_div = (desc->max_speed_hz / 1000000 * sleep_time_ns / 1000) / + ((eng_desc->clk_div + 1) * 2) - 1; + + return SUCCESS; +} + +/** + * @brief Create a new commands queue used in a spi transfer + * + * @param fifo Command buffer, usually used in fifo mode + * @param cmd Command with witch the buffer will be initiated + * @return int32_t Failure if the memory allocation failed + */ +static int32_t spi_engine_queue_new_cmd(struct spi_engine_cmd_queue **fifo, + uint32_t cmd) +{ + struct spi_engine_cmd_queue *local_fifo; + + local_fifo = (spi_engine_cmd_queue*)malloc(sizeof(*local_fifo)); + + if(!local_fifo) + return FAILURE; + + local_fifo->cmd = cmd; + local_fifo->next = NULL; + *fifo = local_fifo; + + return SUCCESS; +} + +/** + * @brief Add a command at the end of an existing queue + * + * @param fifo Command buffer, usually used in fifo mode + * @param cmd Command to be added + */ +static void spi_engine_queue_add_cmd(struct spi_engine_cmd_queue **fifo, + uint32_t cmd) +{ + struct spi_engine_cmd_queue *to_add = NULL; + struct spi_engine_cmd_queue *local_fifo; + + local_fifo = *fifo; + while (local_fifo->next != NULL) { + // Get the last element + local_fifo = local_fifo->next; + } + + // Create a new element + spi_engine_queue_new_cmd(&to_add, cmd); + // Add as the next element + local_fifo->next = to_add; +} + +/** + * @brief Add a command at the beginning of an existing queue + * + * @param fifo Command buffer, usually used in fifo mode + * @param cmd Command to be added + */ +static void spi_engine_queue_append_cmd(struct spi_engine_cmd_queue **fifo, + uint32_t cmd) +{ + struct spi_engine_cmd_queue *to_add = NULL; + + // Create a new element + spi_engine_queue_new_cmd(&to_add, cmd); + // Interchange the addresses + to_add->next = *fifo; + *fifo = to_add; +} + + +/** + * @brief Get the command from the beginning of the queue + * + * @param fifo Command buffer, usually used in fifo mode + * @param cmd Value of the command that was extracted + * @return int32_t Return FAILURE if the queue is empty + */ +static int32_t spi_engine_queue_get_cmd(struct spi_engine_cmd_queue **fifo, + uint32_t *cmd) +{ + struct spi_engine_cmd_queue *local_fifo; + + if (!*fifo) + return FAILURE; + + local_fifo = *fifo; + *cmd = local_fifo->cmd; + if ((*fifo)->next) { + *fifo = local_fifo->next; + free(local_fifo); + } else { + free(*fifo); + *fifo = NULL; + } + + return SUCCESS; +} + +/** + * @brief Free the memory allocated by a queue + * + * @param fifo The queue that needs it's memory freed + * @return int32_t This function allways return SUCCESS + */ +static int32_t spi_engine_queue_free(struct spi_engine_cmd_queue **fifo) +{ + if(*fifo && (*fifo)->next) + spi_engine_queue_free(&(*fifo)->next); + if((*fifo) != NULL) { + free(*fifo); + *fifo = NULL; + } + + return SUCCESS; +} + +/** + * @brief Write the SPI engine's command fifo + * + * @param desc Decriptor containing SPI Engine's parameters + * @param cmd The command that will be written + * @return int32_t Returns FAILURE if the the axi transfer failed + */ +static int32_t spi_engine_write_cmd_reg(struct spi_engine_desc *desc, + uint32_t cmd) +{ + int32_t ret; + + /* Check if offload is enabled */ + if(desc->offload_config & (OFFLOAD_TX_EN | OFFLOAD_RX_EN)) { + ret = spi_engine_write(desc, + SPI_ENGINE_REG_OFFLOAD_CMD_MEM(0), + cmd); + + } else { + ret = spi_engine_write(desc, + SPI_ENGINE_REG_CMD_FIFO, + cmd); + } + + return ret; +} + +/** + * @brief Write a transfer command to the SPI engine's command fifo + * + * @param desc Decriptor containing SPI Engine's parameters + * @param read_write Read/Write operation flag + * @param bytes_number Number of bytes to transfer + * @return int32_t This function allways returns SUCCESS + */ +static int32_t spi_engine_transfer(struct spi_engine_desc *desc, + uint8_t read_write, + uint8_t bytes_number) +{ + uint8_t words_number; + + words_number = spi_get_words_number(desc, bytes_number); + + desc->offload_tx_len += words_number; + + /* + * Engine Wiki: + * + * https://wiki.analog.com/resources/fpga/peripherals/spi_engine + * + * The words number is zero based + */ + + spi_engine_write_cmd_reg(desc, + SPI_ENGINE_CMD_TRANSFER(read_write, + words_number - 1)); + + return SUCCESS; +} + +/** + * @brief Change the state of the chip select port + * + * @param desc Decriptor containing SPI interface parameters + * @param assert Chip select state. + * The supported values are : + * -true (HIGH) + * -false (LOW) + */ +static void spi_engine_set_cs(struct spi_desc *desc, + bool assert) +{ + uint8_t mask; + struct spi_engine_desc *eng_desc; + + eng_desc = desc->extra; + + mask = 0xFF; + /* Switch the state only of the selected chip select */ + if (!assert) + mask ^= BIT(desc->chip_select); + + spi_engine_write_cmd_reg(eng_desc, + SPI_ENGINE_CMD_ASSERT(eng_desc->cs_delay, + mask)); +} + +/** + * @brief Add a delay between the engine commands + * + * @param desc Decriptor containing SPI interface parameters + * @param sleep_time_ns Number of nanoseconds to sleep between commands + */ +static void spi_gen_sleep_ns(struct spi_desc *desc, + uint32_t sleep_time_ns) +{ + uint32_t sleep_div; + struct spi_engine_desc *eng_desc; + + eng_desc = desc->extra; + + spi_get_sleep_div(desc, sleep_time_ns, &sleep_div); + + spi_engine_write_cmd_reg(eng_desc, SPI_ENGINE_CMD_SLEEP(sleep_div)); +} + +/** + * @brief Spi engine command interpreter + * + * @param desc Decriptor containing SPI interface parameters + * @param cmd Command to send to the engine + * @return int32_t - SUCCESS if the command is transferred + * - FAILURE if the command format is invalid + */ +static int32_t spi_engine_write_cmd(struct spi_desc *desc, + uint32_t cmd) +{ + uint8_t engine_command; + uint8_t parameter; + uint8_t modifier; + struct spi_engine_desc *desc_extra; + + desc_extra = desc->extra; + + engine_command = (cmd >> 12) & 0x0F; + modifier = (cmd >> 8) & 0x0F; + parameter = cmd & 0xFF; + + switch(engine_command) { + case SPI_ENGINE_INST_TRANSFER: + spi_engine_transfer(desc_extra, modifier, parameter); + break; + + case SPI_ENGINE_INST_ASSERT: + if(parameter == 0xFF) { + /* Set the CS HIGH */ + spi_engine_set_cs(desc, true); + } else if(parameter == 0x00) { + /* Set the CS LOW */ + spi_engine_set_cs(desc, false); + } + break; + + /* The SYNC and SLEEP commands got the same value but different + modifier */ + case SPI_ENGINE_INST_SYNC_SLEEP: + /* SYNC instruction */ + if(modifier == 0x00) { + spi_engine_write_cmd_reg(desc_extra, cmd); + } else if(modifier == 0x01) { + spi_gen_sleep_ns(desc, parameter); + } + break; + case SPI_ENGINE_INST_CONFIG: + spi_engine_write_cmd_reg(desc_extra, cmd); + + break; + + default: + + return FAILURE; + } + + return SUCCESS; +} + +/** + * @brief Prepare the command queue before sending it to the engine + * + * @param desc Decriptor containing SPI interface parameters + * @param msg Structure used to store the transfer messages + * @return int32_t This function allways returns SUCCESS + */ +static int32_t spi_engine_compile_message(struct spi_desc *desc, + struct spi_engine_msg *msg) +{ + struct spi_engine_desc *desc_extra; + + desc_extra = desc->extra; + + /* Configure the prescaler */ + spi_engine_queue_append_cmd(&msg->cmds, + SPI_ENGINE_CMD_CONFIG( + SPI_ENGINE_CMD_REG_CLK_DIV, + desc_extra->clk_div)); + + /* Set the data transfer length */ + spi_engine_queue_append_cmd(&msg->cmds, + SPI_ENGINE_CMD_CONFIG( + SPI_ENGINE_CMD_DATA_TRANSFER_LEN, + desc_extra->data_width)); + /* + * Configure the spi mode : + * - 3 wire + * - CPOL + * - CPHA + */ + spi_engine_queue_append_cmd(&msg->cmds, + SPI_ENGINE_CMD_CONFIG( + SPI_ENGINE_CMD_REG_CONFIG, + desc->mode)); + + /* Add a sync command to signal that the transfer has finished */ + spi_engine_queue_add_cmd(&msg->cmds, SPI_ENGINE_CMD_SYNC(_sync_id)); + + return SUCCESS; +} + +/** + * @brief Initiate a spi transfer (Blocking) + * + * @param desc Decriptor containing SPI interface parameters + * @param msg Structure used to store the transfer messages + * @return int32_t - SUCCESS if the transfer finished + * - FAILURE if the memory allocation failed + */ +static int32_t spi_engine_transfer_message(struct spi_desc *desc, + struct spi_engine_msg *msg) +{ + uint32_t i; + uint32_t data; + uint32_t sync_id; + bool offload_en; + struct spi_engine_desc *desc_extra; + + desc_extra = desc->extra; + + spi_engine_compile_message(desc, msg); + + offload_en = (desc_extra->offload_config & OFFLOAD_TX_EN) | + (desc_extra->offload_config & OFFLOAD_RX_EN); + + /* Write the command fifo buffer */ + while(msg->cmds != NULL) { + spi_engine_queue_get_cmd(&msg->cmds, &data); + spi_engine_write_cmd(desc, data); + } + + /* Write a number of tx_length WORDS on the SDO line */ + if(offload_en) { + for(i = 0; i < desc_extra->offload_tx_len; i++) + spi_engine_write(desc_extra, + SPI_ENGINE_REG_OFFLOAD_SDO_MEM(0), + msg->tx_buf[i]); + + } else { + if(msg->tx_buf != NULL){ + for(i = 0; i < msg->tx_length; i++) + spi_engine_write(desc_extra, + SPI_ENGINE_REG_SDO_DATA_FIFO, + msg->tx_buf[i]); + } + do { + spi_engine_read(desc_extra, + SPI_ENGINE_REG_SYNC_ID, + &sync_id); + } + /* Wait for the end sync signal */ + while(sync_id != _sync_id); + _sync_id++; + + /* Read a number of rx_length WORDS from the SDI line and store + them */ + for(i = 0; i < msg->rx_length; i++) { + spi_engine_read(desc_extra, + SPI_ENGINE_REG_SDI_DATA_FIFO, + &data); + /* Store the rx data if rx buffer valid, flush sdi_fifo if + rx buffer is invalid.*/ + if(msg->rx_buf != NULL){ + msg->rx_buf[i] = data; + } + } + } + + return SUCCESS; +} + +/** + * @brief Initialize the spi engine + * + * @param desc Decriptor containing SPI interface parameters + * @param param Structure containing the spi init parameters + * @return int32_t - SUCCESS if the transfer finished + * - FAILURE if the memory allocation failed + */ +int32_t spi_engine_init(struct spi_desc **desc, + const struct spi_init_param *param) +{ + uint32_t data_width = 0; + uint32_t spi_engine_version = 0; + struct spi_engine_desc *eng_desc; + struct spi_engine_init_param *spi_engine_init; + + if (!param) { + return FAILURE; + } + + *desc = malloc(sizeof(**desc)); + if(! *desc) { + free(*desc); + return FAILURE; + } + + eng_desc = (struct spi_engine_desc*)malloc(sizeof(*eng_desc)); + + if (!eng_desc) + return FAILURE; + + spi_engine_init = param->extra; + + (*desc)->max_speed_hz = param->max_speed_hz; + (*desc)->chip_select = param->chip_select; + (*desc)->mode = param->mode; + (*desc)->extra = eng_desc; + + eng_desc->offload_config = OFFLOAD_DISABLED; + eng_desc->spi_engine_baseaddr = spi_engine_init->spi_engine_baseaddr; + eng_desc->type = spi_engine_init->type; + eng_desc->cs_delay = spi_engine_init->cs_delay; + eng_desc->ref_clk_hz = spi_engine_init->ref_clk_hz; + eng_desc->clk_div = eng_desc->ref_clk_hz / + (2 * param->max_speed_hz) - 1; + + /* Perform a reset */ + spi_engine_write(eng_desc, SPI_ENGINE_REG_RESET, 0x01); + usleep(1000); + spi_engine_write(eng_desc, SPI_ENGINE_REG_RESET, 0x00); + + /* Get current data width */ + spi_engine_read(eng_desc, SPI_ENGINE_REG_DATA_WIDTH, &data_width); + eng_desc->max_data_width = data_width; + + spi_engine_set_transfer_width(*desc, spi_engine_init->data_width); + + /* Get spi engine version */ + spi_engine_read(eng_desc, SPI_ENGINE_REG_VERSION, &spi_engine_version); + + printf("Spi engine v%"PRIu32".%"PRIu32".%"PRIu32" successfully initialized.\n", + (spi_engine_version >> 16), + ((spi_engine_version >> 8) & 0xFF), + (spi_engine_version & 0xFF)); + + return SUCCESS; +} + +/** + * @brief Write and read on the spi interface in 4-wire mode (full-duplex) + * + * @param desc Decriptor containing SPI interface parameters + * @param data Pointer to data buffer + * @param bytes_number Number of bytes to transfer + * @return int32_t - SUCCESS if the transfer finished + * - FAILURE if the memory allocation or transfer failed + */ +int32_t spi_engine_spi_write_and_read(struct spi_desc *desc, + uint8_t *data, + uint16_t bytes_number) +{ + uint8_t word_len; + uint8_t words_number; + int32_t ret; + struct spi_engine_msg msg; + struct spi_engine_desc *desc_extra; + + desc_extra = desc->extra; + + /* If we want to access SPI interface and SPI engine offload module was + * activated, we need to disable it + * This is set in spi_engine_offload_init() */ + desc_extra->offload_config = OFFLOAD_DISABLED; + /* This is set in spi_engine_offload_transfer() */ + spi_engine_write(desc_extra, SPI_ENGINE_REG_OFFLOAD_CTRL(0), 0); + + words_number = spi_get_words_number(desc_extra, bytes_number); + + msg.cmds = (spi_engine_cmd_queue*)malloc(sizeof(*msg.cmds)); + if (!msg.cmds) + return FAILURE; + + msg.tx_buf =(uint32_t*)calloc(words_number, sizeof(msg.tx_buf[0])); + msg.rx_buf =(uint32_t*)calloc(words_number, sizeof(msg.rx_buf[0])); + msg.tx_length = words_number; + msg.rx_length = words_number; + + /* Get the length of transferred word */ + word_len = spi_get_word_length(desc_extra); + + /* Make sure the CS is HIGH before starting a transaction */ + msg.cmds->next = NULL; + msg.cmds->cmd = CS_HIGH; + // Assert select. + spi_engine_queue_add_cmd(&msg.cmds, CS_LOW); + // add read/write command + spi_engine_queue_add_cmd(&msg.cmds, WRITE_READ(bytes_number)); + // Disable select. + spi_engine_queue_add_cmd(&msg.cmds, CS_HIGH); + + /* Pack the bytes into engine WORDS */ + for (int i = 0; i < bytes_number; i++) + msg.tx_buf[i / word_len] |= data[i] << (desc_extra->data_width- + (i % word_len + 1) * 8); + + ret = spi_engine_transfer_message(desc, &msg); + + for (int i = 0; i < bytes_number; i++) + data[i] = msg.rx_buf[(i) / word_len] >> + (desc_extra->data_width - + ((i) % word_len + 1) * 8); + + spi_engine_queue_free(&msg.cmds); + free(msg.tx_buf); + free(msg.rx_buf); + + return ret; +} + +/** + * @brief Write and read on the spi interface in 3-wire mode (half-duplex) + * + * @param desc Decriptor containing SPI interface parameters + * @param data Pointer to data buffer + * @param bytes_number Number of bytes to transfer + * @return int32_t - SUCCESS if the transfer finished + * - FAILURE if the memory allocation or transfer failed + */ +int32_t spi_engine_spi_write_and_read_3wire(struct spi_desc *desc, + uint8_t *write_data, + uint8_t *read_data, + uint16_t write_bytes_number, + uint16_t read_bytes_number) +{ + uint8_t word_len; + uint8_t wr_words_number; + uint8_t rd_words_number; + int32_t ret; + struct spi_engine_msg msg; + struct spi_engine_desc *desc_extra; + + desc_extra = desc->extra; + + /* If we want to access SPI interface and SPI engine offload module was + * activated, we need to disable it + * This is set in spi_engine_offload_init() */ + desc_extra->offload_config = OFFLOAD_DISABLED; + /* This is set in spi_engine_offload_transfer() */ + spi_engine_write(desc_extra, SPI_ENGINE_REG_OFFLOAD_CTRL(0), 0); + + wr_words_number = spi_get_words_number(desc_extra, write_bytes_number); + rd_words_number = spi_get_words_number(desc_extra, read_bytes_number); + + msg.cmds = (spi_engine_cmd_queue*)malloc(sizeof(*msg.cmds)); + if (!msg.cmds) + return FAILURE; + + msg.tx_buf =(wr_words_number>0)?(uint32_t*)calloc(wr_words_number, sizeof(msg.tx_buf[0])):NULL; + msg.rx_buf =(rd_words_number>0)?(uint32_t*)calloc(rd_words_number, sizeof(msg.rx_buf[0])):NULL; + msg.tx_length = wr_words_number; + msg.rx_length = rd_words_number; + + /* Get the length of transferred word */ + word_len = spi_get_word_length(desc_extra); + + /* Make sure the CS is HIGH before starting a transaction */ + msg.cmds->next = NULL; + msg.cmds->cmd = CS_HIGH; + + // Assert select. + spi_engine_queue_add_cmd(&msg.cmds, CS_LOW); + + // add read/write command + if(write_bytes_number > 0) + spi_engine_queue_add_cmd(&msg.cmds, WRITE(write_bytes_number)); + if(read_bytes_number > 0) + spi_engine_queue_add_cmd(&msg.cmds, READ(read_bytes_number)); + + // Disable select. + spi_engine_queue_add_cmd(&msg.cmds, CS_HIGH); + + /* Pack the bytes into engine WORDS */ + for (int i = 0; i < write_bytes_number; i++) + msg.tx_buf[i / word_len] |= write_data[i] << (desc_extra->data_width- + (i % word_len + 1) * 8); + + ret = spi_engine_transfer_message(desc, &msg); + + for (int i = 0; i < read_bytes_number; i++) + read_data[i] = msg.rx_buf[(i) / word_len] >> + (desc_extra->data_width - + ((i) % word_len + 1) * 8); + + spi_engine_queue_free(&msg.cmds); + free(msg.tx_buf); + free(msg.rx_buf); + + return ret; +} + +/** + * @brief Initialize the SPI engine's offload module + * + * @param desc Decriptor containing SPI interface parameters + * @param param Structure containing the offload init parameters + * @return int32_t This function allways returns SUCCESS + */ +int32_t spi_engine_offload_init(struct spi_desc *desc, + const struct spi_engine_offload_init_param *param) +{ + struct spi_engine_desc *eng_desc; + struct axi_dmac_init dmac_init; + uint32_t dma_flags; + + eng_desc = desc->extra; + + eng_desc->offload_config = param->offload_config; + + if(!(param->dma_flags)) + dma_flags = DMA_CYCLIC; + else + dma_flags = *(param->dma_flags); + + if(param->offload_config & OFFLOAD_TX_EN) { + dmac_init.name = "DAC DMAC"; + dmac_init.base = param->tx_dma_baseaddr; + dmac_init.direction = DMA_MEM_TO_DEV; + dmac_init.flags = dma_flags; + axi_dmac_init(&eng_desc->offload_tx_dma, &dmac_init); + if(!eng_desc->offload_tx_dma) + return FAILURE; + } + if(param->offload_config & OFFLOAD_RX_EN) { + dmac_init.name = "ADC DMAC"; + dmac_init.base = param->rx_dma_baseaddr; + dmac_init.direction = DMA_DEV_TO_MEM; + dmac_init.flags = dma_flags; + axi_dmac_init(&eng_desc->offload_rx_dma, &dmac_init); + if(!eng_desc->offload_rx_dma) + return FAILURE; + } + + return SUCCESS; +} + +/** + * @brief Initiate a SPI transfer in offload mode + * + * @param desc Decriptor containing SPI interface parameters + * @param msg Offload message that get's to be transferred + * @param no_samples Number of time the messages will be transferred + * @return int32_t This function allways returns SUCCESS + */ +int32_t spi_engine_offload_transfer(struct spi_desc *desc, + struct spi_engine_offload_message msg, + uint32_t no_samples) +{ + struct spi_engine_msg transfer; + struct spi_engine_desc *eng_desc; + uint32_t i; + uint8_t word_length; + + eng_desc = desc->extra; + + /* Check if offload is disabled */ + if(!((eng_desc->offload_config & OFFLOAD_TX_EN) | + (eng_desc->offload_config & OFFLOAD_RX_EN))) + return FAILURE; + + spi_engine_write(eng_desc, SPI_ENGINE_REG_OFFLOAD_RESET(0), 1); + spi_engine_write(eng_desc, SPI_ENGINE_REG_OFFLOAD_RESET(0), 0); + + eng_desc->offload_tx_len = 0; + eng_desc->offload_rx_len = 0; + + transfer.cmds = (spi_engine_cmd_queue*)malloc(sizeof(*transfer.cmds)); + + if (!transfer.cmds) + return FAILURE; + + transfer.tx_buf = msg.commands_data; + + /* Load the commands into the message */ + transfer.cmds->next = NULL; + transfer.cmds->cmd = msg.commands[0]; + i = 1; + while(i < msg.no_commands) { + spi_engine_queue_add_cmd(&transfer.cmds, msg.commands[i++]); + + } + + spi_engine_transfer_message(desc, &transfer); + + /* Start transfer */ + spi_engine_write(eng_desc, SPI_ENGINE_REG_OFFLOAD_CTRL(0), 0x0001); + + word_length = spi_get_word_length(eng_desc); + if(eng_desc->offload_config & OFFLOAD_TX_EN) { + axi_dmac_transfer(eng_desc->offload_tx_dma, + msg.tx_addr, + word_length * eng_desc->offload_tx_len * + no_samples); + } + + if(eng_desc->offload_config & OFFLOAD_RX_EN) { + axi_dmac_transfer(eng_desc->offload_rx_dma, + msg.rx_addr, + word_length * eng_desc->offload_tx_len * + no_samples); + } + + usleep(1000); + + spi_engine_queue_free(&transfer.cmds); + + return SUCCESS; +} + +/** + * @brief Free the resources allocated by spi_init(). + * + * @param desc Decriptor containing SPI interface parameters + * @return int32_t This function allways returns SUCCESS + */ +int32_t spi_engine_remove(struct spi_desc *desc) +{ + struct spi_engine_desc *eng_desc; + + eng_desc = desc->extra; + + if(eng_desc->offload_config & OFFLOAD_TX_EN) + axi_dmac_remove(eng_desc->offload_tx_dma); + if(eng_desc->offload_config & OFFLOAD_RX_EN) + axi_dmac_remove(eng_desc->offload_rx_dma); + free(desc->extra); + free(desc); + + return SUCCESS; +} diff --git a/datalink814_sp/src/adi_noos/drivers/axi_core/spi_engine/spi_engine.h b/datalink814_sp/src/adi_noos/drivers/axi_core/spi_engine/spi_engine.h new file mode 100644 index 0000000..90dd18e --- /dev/null +++ b/datalink814_sp/src/adi_noos/drivers/axi_core/spi_engine/spi_engine.h @@ -0,0 +1,231 @@ +/******************************************************************************* + * @file spi_engine.h + * @brief Header file of SPI Engine core features. + * @author Sergiu Cuciurean (sergiu.cuciurean@analog.com) +******************************************************************************** + * Copyright 2019(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#ifndef SPI_ENGINE_H +#define SPI_ENGINE_H + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include + +#include "spi_engine_private.h" +#include "../../platform/spi_extra.h" + +/******************************************************************************/ +/********************** Macros and Constants Definitions **********************/ +/******************************************************************************/ + +#define OFFLOAD_DISABLED 0x00 +#define OFFLOAD_TX_EN BIT(0) +#define OFFLOAD_RX_EN BIT(1) +#define OFFLOAD_TX_RX_EN OFFLOAD_TX_EN | OFFLOAD_RX_EN + +#define SPI_ENGINE_MSG_QUEUE_END 0xFFFFFFFF + +/* Spi engine commands */ +#define WRITE_OR_READ(mode, no_bytes) ((SPI_ENGINE_INST_TRANSFER << 12) |\ +((mode) << 8) | (no_bytes)) + +#define WRITE(no_bytes) ((SPI_ENGINE_INST_TRANSFER << 12) |\ + (SPI_ENGINE_INSTRUCTION_TRANSFER_W << 8) | (no_bytes)) + +#define READ(no_bytes) ((SPI_ENGINE_INST_TRANSFER << 12) |\ + (SPI_ENGINE_INSTRUCTION_TRANSFER_R << 8) | (no_bytes)) + +#define WRITE_READ(no_bytes) ((SPI_ENGINE_INST_TRANSFER << 12) |\ + (SPI_ENGINE_INSTRUCTION_TRANSFER_RW << 8) | (no_bytes)) + + + +#define SLEEP(time) SPI_ENGINE_CMD_SLEEP(time & 0xF) + +/* The delay and chip select parmeters are passed over the engine descriptor +and will be used inside the function call */ +#define CS_HIGH SPI_ENGINE_CMD_ASSERT(0x00, 0xFF) +#define CS_LOW SPI_ENGINE_CMD_ASSERT(0x00, 0x00) + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ + +/** + * @struct spi_engine_init_param + * @brief Structure containing the init parameters needed by the SPI engine + */ +struct spi_engine_init_param { + /** SPI engine reference clock */ + uint32_t ref_clk_hz; + /** Type of implementation */ + enum xil_spi_type type; + /** Base address where the HDL core is situated */ + uint32_t spi_engine_baseaddr; + /** Delay between the CS toggle and the start of SCLK */ + uint32_t cs_delay; + /** Data with of one SPI transfer ( in bits ) */ + uint8_t data_width; +}; + + +/** + * @struct spi_engine_desc + * @brief Structure representing an SPI engine device + */ +struct spi_engine_desc { + /** SPI engine reference clock */ + uint32_t ref_clk_hz; + /** Type of implementation */ + enum xil_spi_type type; + /** Pointer to a DMAC used in transmission */ + struct axi_dmac *offload_tx_dma; + /** Pointer to a DMAC used in reception */ + struct axi_dmac *offload_rx_dma; + /** Offload's module transfer direction : TX, RX or both */ + uint8_t offload_config; + /** Number of words that the module has to send */ + uint8_t offload_tx_len; + /** Number of words that the module has to receive */ + uint8_t offload_rx_len; + /** Base address where the HDL core is situated */ + uint32_t spi_engine_baseaddr; + /** Base address where the RX DMAC core is situated */ + uint32_t rx_dma_baseaddr; + /** Base address where the TX DMAC core is situated */ + uint32_t tx_dma_baseaddr; + /** Delay between the CS toggle and the start of SCLK */ + uint8_t cs_delay; + /** Clock divider used in transmission delays */ + uint32_t clk_div; + /** Data with of one SPI transfer ( in bits ) */ + uint8_t data_width; + /** The maximum data width supported by the engine */ + uint8_t max_data_width; +}; + + +/** + * @struct spi_engine_offload_init_param + * @brief Structure containing the init parameters needed by the offload module + */ +struct spi_engine_offload_init_param { + /** Base address where the RX DMAC core is situated */ + uint32_t rx_dma_baseaddr; + /** Base address where the TX DMAC core is situated */ + uint32_t tx_dma_baseaddr; + /** DMAC flags - if not initialized, the default value is DMA_CYCLIC */ + uint32_t *dma_flags; + /** Offload's module transfer direction : TX, RX or both */ + uint8_t offload_config; +}; + +/** + * @struct spi_engine_offload_message + * @brief Structure representing an offload message + */ +struct spi_engine_offload_message { + /** Pointer to the SPI engine commands buffer that will be sent. + * The available commands can be found at: + * https://wiki.analog.com/resources/fpga/peripherals/spi_engine/ + */ + uint32_t *commands; + /** Length of the SPI engine commands buffer */ + uint32_t no_commands; + /** Pointer of the data that will be sent over spi */ + uint32_t *commands_data; + /** The address where the data that will be transmitted is situated */ + uint32_t tx_addr; + /** The address where the data that will be received is situated */ + uint32_t rx_addr; +}; + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ + +/** + * @brief Spi engine platform specific SPI platform ops structure + */ +extern const struct spi_platform_ops xil_spi_ops; + +/* Write SPI Engine's axi registers */ +int32_t spi_engine_write(struct spi_engine_desc *desc, + uint32_t reg_addr, + uint32_t reg_data); + +/* Read SPI Engine's axi registers */ +int32_t spi_engine_read(struct spi_engine_desc *desc, + uint32_t reg_addr, + uint32_t *reg_data); +/* Initialize the SPI engine device */ +int32_t spi_engine_init(struct spi_desc **desc, + const struct spi_init_param *param); + +/* Write and read data over SPI using the SPI engine */ +int32_t spi_engine_spi_write_and_read(struct spi_desc *desc, + uint8_t *data, + uint16_t bytes_number); + +/* Write and read data over SPI using the SPI engine in 3-wire mode */ +int32_t spi_engine_spi_write_and_read_3wire(struct spi_desc *desc, + uint8_t *write_data, + uint8_t *read_data, + uint16_t write_bytes_number, + uint16_t read_bytes_number); +/* Free the resources used by the SPI engine device */ +int32_t spi_engine_remove(struct spi_desc *desc); + +/* Initialize the SPI engine offload module */ +int32_t spi_engine_offload_init(struct spi_desc *desc, + const struct spi_engine_offload_init_param *param); + +/* Write and read data over SPI using the offload module */ +int32_t spi_engine_offload_transfer(struct spi_desc *desc, + struct spi_engine_offload_message msg, + uint32_t no_samples); + +/* Set SPI transfer width */ +int32_t spi_engine_set_transfer_width(struct spi_desc *desc, + uint8_t data_wdith); + +/* Set SPI transfer speed */ +void spi_engine_set_speed(struct spi_desc *desc, + uint32_t speed_hz); + +#endif // SPI_ENGINE_H diff --git a/datalink814_sp/src/adi_noos/drivers/axi_core/spi_engine/spi_engine_private.h b/datalink814_sp/src/adi_noos/drivers/axi_core/spi_engine/spi_engine_private.h new file mode 100644 index 0000000..e102bb9 --- /dev/null +++ b/datalink814_sp/src/adi_noos/drivers/axi_core/spi_engine/spi_engine_private.h @@ -0,0 +1,154 @@ +/******************************************************************************* + * @file spi_engine_private.h + * @brief Private definitions of the SPI Engine + * @author Sergiu Cuciurean (sergiu.cuciurean@analog.com) +******************************************************************************** + * Copyright 2019(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#ifndef SPI_ENGINE_PRIVATE_H +#define SPI_ENGINE_PRIVATE_H + +#include +#include + +#include "../../../include/spi.h" +#include "../../../../util/util.h" + +/******************************************************************************/ +/*************************** Spi Engine registers *****************************/ +/******************************************************************************/ + +#define SPI_ENGINE_REG_VERSION 0x00 +#define SPI_ENGINE_REG_DATA_WIDTH 0x0C +#define SPI_ENGINE_REG_RESET 0x40 +#define SPI_ENGINE_REG_INT_ENABLE 0x80 +#define SPI_ENGINE_REG_INT_PENDING 0x84 +#define SPI_ENGINE_REG_INT_SOURCE 0x88 +#define SPI_ENGINE_REG_SYNC_ID 0xC0 +#define SPI_ENGINE_REG_CMD_FIFO_ROOM 0xD0 +#define SPI_ENGINE_REG_SDO_FIFO_ROOM 0xD4 +#define SPI_ENGINE_REG_SDI_FIFO_LEVEL 0xD8 +#define SPI_ENGINE_REG_CMD_FIFO 0xE0 +#define SPI_ENGINE_REG_SDO_DATA_FIFO 0xE4 +#define SPI_ENGINE_REG_SDI_DATA_FIFO 0xE8 +#define SPI_ENGINE_REG_SDI_DATA_FIFO_PEEK 0xEC + +/******************************************************************************/ +/************************ Spi Engine register parameters **********************/ +/******************************************************************************/ + +#define SPI_ENGINE_INST_TRANSFER 0x00 +#define SPI_ENGINE_INST_ASSERT 0x01 +#define SPI_ENGINE_INST_CONFIG 0x02 +#define SPI_ENGINE_INST_SYNC_SLEEP 0x03 +#define SPI_ENGINE_INST_MISC 0x03 +#define SPI_ENGINE_CMD_REG_CLK_DIV 0x00 +#define SPI_ENGINE_CMD_REG_CONFIG 0x01 +#define SPI_ENGINE_CMD_DATA_TRANSFER_LEN 0x02 +#define SPI_ENGINE_MISC_SYNC 0x00 +#define SPI_ENGINE_MISC_SLEEP 0x01 +#define SPI_ENGINE_SYNC_TRANSFER_BEGIN BIT(1) +#define SPI_ENGINE_SYNC_TRANSFER_END BIT(2) +#define SPI_ENGINE_INT_CMD_ALMOST_EMPTY BIT(0) +#define SPI_ENGINE_INT_SDO_ALMOST_EMPTY BIT(1) +#define SPI_ENGINE_INT_SDI_ALMOST_FULL BIT(2) +#define SPI_ENGINE_INT_SYNC BIT(3) +#define SPI_ENGINE_OFFLOAD_CTRL_ENABLE BIT(0) +#define SPI_ENGINE_OFFLOAD_STATUS_ENABLED BIT(0) +#define SPI_ENGINE_CONFIG_CPHA BIT(0) +#define SPI_ENGINE_CONFIG_CPOL BIT(1) +#define SPI_ENGINE_CONFIG_3WIRE BIT(2) +#define SPI_ENGINE_VERSION_MAJOR(x) ((x >> 16) & 0xff) +#define SPI_ENGINE_VERSION_MINOR(x) ((x >> 8) & 0xff) +#define SPI_ENGINE_VERSION_PATCH(x) (x & 0xff) + +/******************************************************************************/ +/**************************** Spi Engine commands *****************************/ +/******************************************************************************/ + +#define SPI_ENGINE_INSTRUCTION_TRANSFER_W 0x01 +#define SPI_ENGINE_INSTRUCTION_TRANSFER_R 0x02 +#define SPI_ENGINE_INSTRUCTION_TRANSFER_RW 0x03 + +#define SPI_ENGINE_REG_OFFLOAD_CTRL(x) (0x100 + (0x20 * x)) +#define SPI_ENGINE_REG_OFFLOAD_STATUS(x) (0x104 + (0x20 * x)) +#define SPI_ENGINE_REG_OFFLOAD_RESET(x) (0x108 + (0x20 * x)) +#define SPI_ENGINE_REG_OFFLOAD_CMD_MEM(x) (0x110 + (0x20 * x)) +#define SPI_ENGINE_REG_OFFLOAD_SDO_MEM(x) (0x114 + (0x20 * x)) + +#define SPI_ENGINE_CMD(inst, arg1, arg2) \ + (((inst & 0x03) << 12) | \ + ((arg1 & 0x03) << 8) | arg2 ) + +#define SPI_ENGINE_CMD_TRANSFER(readwrite, n) \ + SPI_ENGINE_CMD(SPI_ENGINE_INST_TRANSFER, \ + (readwrite), (n)) + +#define SPI_ENGINE_CMD_ASSERT(delay, cs) \ + SPI_ENGINE_CMD(SPI_ENGINE_INST_ASSERT, \ + (delay), (cs)) + +#define SPI_ENGINE_CMD_CONFIG(reg, val) \ + SPI_ENGINE_CMD(SPI_ENGINE_INST_CONFIG, \ + (reg), (val)) + +#define SPI_ENGINE_CMD_SLEEP(delay) \ + SPI_ENGINE_CMD(SPI_ENGINE_INST_MISC, \ + SPI_ENGINE_MISC_SLEEP, \ + (delay)) + +#define SPI_ENGINE_CMD_SYNC(id) \ + SPI_ENGINE_CMD(SPI_ENGINE_INST_MISC, \ + SPI_ENGINE_MISC_SYNC, \ + (id)) + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ + +typedef struct spi_engine_cmd_queue { + uint32_t cmd; + struct spi_engine_cmd_queue *next; +} spi_engine_cmd_queue; + +typedef struct spi_engine_msg { + uint32_t *tx_buf; + uint32_t *rx_buf; + uint32_t tx_length; + uint32_t rx_length; + struct spi_engine_cmd_queue *cmds; +} spi_engine_msg; + +#endif // SPI_ENGINE_PRIVATE_H diff --git a/datalink814_sp/src/adi_noos/drivers/frequency/ad9516/ad9516.c b/datalink814_sp/src/adi_noos/drivers/frequency/ad9516/ad9516.c new file mode 100644 index 0000000..a78b10a --- /dev/null +++ b/datalink814_sp/src/adi_noos/drivers/frequency/ad9516/ad9516.c @@ -0,0 +1,129 @@ +/***************************************************************************//** + * @file ad9516.c + * @brief Implementation of AD9680 Driver. + * @author DBogdan (dragos.bogdan@analog.com) + ******************************************************************************** + * Copyright 2014-2016(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include "ad9516.h" + +#include +#include +#include "../../../include/error.h" + +/***************************************************************************//** + * @brief ad9516_read + *******************************************************************************/ +int32_t ad9516_read(struct ad9516_dev *dev, + uint16_t reg_addr, + uint8_t *reg_data) +{ + uint8_t tx_buf[2]; + uint8_t rx_buf[1]; + int32_t ret; + + tx_buf[0] = 0x80 | (reg_addr >> 8); + tx_buf[1] = reg_addr & 0xFF; + + + ret = spi_write_and_read_3wire(dev->spi_desc, + tx_buf, rx_buf, 2, 1); + + *reg_data = rx_buf[0]; + + return ret; +} + +/***************************************************************************//** + * @brief ad9516_write + *******************************************************************************/ +int32_t ad9516_write(struct ad9516_dev *dev, + uint16_t reg_addr, + uint8_t reg_data) +{ + uint8_t buf[3]; + + int32_t ret; + + buf[0] = reg_addr >> 8; + buf[1] = reg_addr & 0xFF; + buf[2] = reg_data; + + ret = spi_write_and_read_3wire(dev->spi_desc, + buf, NULL, 3, 0); + return ret; +} + +/***************************************************************************//** + * @brief ad9516_init + *******************************************************************************/ +int32_t ad9516_init(struct ad9516_dev **device, + const struct ad9516_init_param *init_param) +{ + int ret = SUCCESS; + struct ad9516_dev *dev; + + dev = (struct ad9516_dev *)malloc(sizeof(*dev)); + if (!dev) + return FAILURE; + + /* SPI */ + ret = spi_init(&dev->spi_desc, init_param->spi_init); + + *device = dev; + + return ret; +} + +/***************************************************************************//** + * @brief Free the resources allocated by ad9516_setup(). + * + * @param dev - The device structure. + * + * @return SUCCESS in case of success, negative error code otherwise. +*******************************************************************************/ +int32_t ad9516_remove(struct ad9516_dev *dev) +{ + int32_t ret; + + ret = spi_remove(dev->spi_desc); + + free(dev); + + return ret; +} diff --git a/datalink814_sp/src/adi_noos/drivers/frequency/ad9516/ad9516.h b/datalink814_sp/src/adi_noos/drivers/frequency/ad9516/ad9516.h new file mode 100644 index 0000000..0ab989a --- /dev/null +++ b/datalink814_sp/src/adi_noos/drivers/frequency/ad9516/ad9516.h @@ -0,0 +1,89 @@ +/***************************************************************************//** + * @file ad9516.h + * @brief Header file of ad9516 Driver. + * @author DBogdan (dragos.bogdan@analog.com) + ******************************************************************************** + * Copyright 2014-2016(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *******************************************************************************/ +#ifndef AD9516_H_ +#define AD9516_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include +#include "../../../include/delay.h" +#include "../../../include/spi.h" + +/******************************************************************************/ +/********************** Macros and Constants Definitions **********************/ +/******************************************************************************/ + + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ +struct ad9516_dev { + /* SPI */ + spi_desc *spi_desc; +}; + +struct ad9516_init_param { + /* SPI */ + spi_init_param *spi_init; +}; + +struct ad9516_config { + uint16_t addr; + uint8_t value; +}; + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ + +int32_t ad9516_read(struct ad9516_dev *dev, + uint16_t reg_addr, + uint8_t *reg_data); + +int32_t ad9516_write(struct ad9516_dev *dev, + uint16_t reg_addr, + uint8_t reg_data); + +int32_t ad9516_init(struct ad9516_dev **device, + const struct ad9516_init_param *init_param); + +int32_t ad9516_remove(struct ad9516_dev *dev); + +#endif diff --git a/datalink814_sp/src/adi_noos/drivers/platform/axi_io.c b/datalink814_sp/src/adi_noos/drivers/platform/axi_io.c new file mode 100644 index 0000000..d7b5a82 --- /dev/null +++ b/datalink814_sp/src/adi_noos/drivers/platform/axi_io.c @@ -0,0 +1,79 @@ +/***************************************************************************//** + * @file xilinx/axi_io.c + * @brief Implementation of Xilinx AXI IO. + * @author Antoniu Miclaus (antoniu.miclaus@analog.com) +******************************************************************************** + * Copyright 2019(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include +#include "../../include/error.h" +#include "../../include/axi_io.h" + +/******************************************************************************/ +/************************ Functions Definitions *******************************/ +/******************************************************************************/ + +/** + * @brief AXI IO Xilinx specific read function. + * @param base - Base address + * @param offset - Address offset + * @param data - variable where returned data is stored + * @return SUCCESS in case of success, FAILURE otherwise. + */ +int32_t axi_io_read(uint32_t base, uint32_t offset, uint32_t *data) +{ + *data = Xil_In32(base + offset); + + return SUCCESS; +} + +/** + * @brief AXI IO Xilinx specific write function. + * @param base - Base address + * @param offset - Address offset + * @param data - data to be written. + * @return SUCCESS in case of success, FAILURE otherwise. + */ +int32_t axi_io_write(uint32_t base, uint32_t offset, uint32_t data) +{ + Xil_Out32(base + offset, data); + + return SUCCESS; +} + diff --git a/datalink814_sp/src/adi_noos/drivers/platform/delay.c b/datalink814_sp/src/adi_noos/drivers/platform/delay.c new file mode 100644 index 0000000..ca06169 --- /dev/null +++ b/datalink814_sp/src/adi_noos/drivers/platform/delay.c @@ -0,0 +1,77 @@ +/***************************************************************************//** + * @file xilinx/delay.c + * @brief Implementation of Xilinx Delay Functions. + * @author Antoniu Miclaus (antoniu.miclaus@analog.com) +******************************************************************************** + * Copyright 2019(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include "../../include/delay.h" +#include + +/******************************************************************************/ +/************************ Functions Definitions *******************************/ +/******************************************************************************/ + +/** + * @brief Generate microseconds delay. + * @param usecs - Delay in microseconds. + * @return None. + */ +void udelay(uint32_t usecs) +{ +#ifdef _XPARAMETERS_PS_H_ + usleep(usecs); +#else + usleep(usecs / 20); // FIXME +#endif +} + +/** + * @brief Generate miliseconds delay. + * @param msecs - Delay in miliseconds. + * @return None. + */ +void mdelay(uint32_t msecs) +{ +#ifdef _XPARAMETERS_PS_H_ + usleep(msecs * 1000); +#else + usleep(msecs * 50); // FIXME +#endif +} diff --git a/datalink814_sp/src/adi_noos/drivers/platform/gpio_extra.h b/datalink814_sp/src/adi_noos/drivers/platform/gpio_extra.h new file mode 100644 index 0000000..dbc64b9 --- /dev/null +++ b/datalink814_sp/src/adi_noos/drivers/platform/gpio_extra.h @@ -0,0 +1,95 @@ +/******************************************************************************* + * @file xilinx/gpio_extra.h + * @brief Header containing extra types used in the gpio driver + * @author scuciurean (sergiu.cuciurean@analog.com) +******************************************************************************** + * Copyright 2019(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#ifndef GPIO_EXTRA_H_ +#define GPIO_EXTRA_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include +#include + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ + +/** + * @enum xil_gpio_type + * @brief Xilinx platform architecture sections + */ +typedef enum xil_gpio_type { + /** Programmable Logic */ + GPIO_PL, + /** Processing System */ + GPIO_PS +} xil_gpio_type; + +/** + * @struct xil_gpio_init_param + * @brief Structure holding the initialization parameters for Xilinx platform + * specific GPIO parameters. + */ +typedef struct xil_gpio_init_param { + /** Xilinx architecture */ + enum xil_gpio_type type; + /** Device ID */ + uint32_t device_id; +} xil_gpio_init_param; + +/** + * @struct xil_gpio_desc + * @brief Xilinx platform specific GPIO descriptor + */ +typedef struct xil_gpio_desc { + /** Xilinx architecture */ + enum xil_gpio_type type; + /** Xilinx GPIO configuration */ + void *config; + /** Xilinx GPIO Instance */ + void *instance; +} xil_gpio_desc; + +/** + * @brief Xilinx platform specific gpio platform ops structure + */ +extern const struct gpio_platform_ops xil_gpio_ops; + +#endif diff --git a/datalink814_sp/src/adi_noos/drivers/platform/irq_extra.h b/datalink814_sp/src/adi_noos/drivers/platform/irq_extra.h new file mode 100644 index 0000000..1c9b959 --- /dev/null +++ b/datalink814_sp/src/adi_noos/drivers/platform/irq_extra.h @@ -0,0 +1,91 @@ +/******************************************************************************* + * @file irq_extra.h + * @brief Header containing types used in the irq driver. + * @author Cristian Pop (cristian.pop@analog.com) +******************************************************************************** + * Copyright 2019(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#ifndef IRQ_EXTRA_H_ +#define IRQ_EXTRA_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include +#include "../../include/irq.h" + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ + +/** + * @enum xil_irq_type + * @brief Xilinx platform architecture sections + */ +enum xil_irq_type { + /** Programmable Logic */ + IRQ_PL, + /** Processing System */ + IRQ_PS +}; + +/** + * @struct xil_irq_init_param + * @brief Structure holding the initialization parameters for Xilinx platform + * specific IRQ parameters. + */ +struct xil_irq_init_param { + /** Xilinx architecture */ + enum xil_irq_type type; +}; + +/** + * @struct xil_irq_desc + * @brief Xilinx platform specific IRQ descriptor + */ +struct xil_irq_desc { + /** Xilinx architecture */ + enum xil_irq_type type; + /** Xilinx IRQ Instance */ + void *instance; +}; + +/** + * @brief Xilinx specific IRQ platform ops structure + */ +extern const struct irq_platform_ops xil_irq_ops; + +#endif diff --git a/datalink814_sp/src/adi_noos/drivers/platform/spi_extra.h b/datalink814_sp/src/adi_noos/drivers/platform/spi_extra.h new file mode 100644 index 0000000..2edb42c --- /dev/null +++ b/datalink814_sp/src/adi_noos/drivers/platform/spi_extra.h @@ -0,0 +1,115 @@ +/******************************************************************************* + * @file xilinx/spi_extra.h + * @brief Header containing extra types used in the spi driver. + * @author scuciurean (sergiu.cuciurean@analog.com) +******************************************************************************** + * Copyright 2019(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ +#ifndef SPI_EXTRA_H_ +#define SPI_EXTRA_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include +#include "../../include/spi.h" + +/******************************************************************************/ +/********************** Macros and Constants Definitions **********************/ +/******************************************************************************/ + +#define SPI_CS_DECODE 0x01 +#define SPI_DEASSERT_CURRENT_SS 0x0F + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ + +/** + * @enum xil_spi_type + * @brief Xilinx platform architecture sections + */ +enum xil_spi_type { + /** Programmable Logic */ + SPI_PL, + /** Processing System */ + SPI_PS, + /** SPI Engine */ + SPI_ENGINE +}; + +/** + * @struct xil_spi_init_param + * @brief Structure holding the initialization parameters for Xilinx platform + * specific SPI parameters when using xil_spi_ops. + */ +typedef struct xil_spi_init_param { + /** Xilinx architecture */ + enum xil_spi_type type; + /** SPI flags */ + uint32_t flags; +} xil_spi_init_param; + +/** + * @struct xil_spi_desc + * @brief Xilinx platform specific SPI descriptor + */ +typedef struct xil_spi_desc { + /** Xilinx architecture */ + enum xil_spi_type type; + /** SPI flags */ + uint32_t flags; + /** SPI configuration */ + void *config; + /** SPI instance */ + void *instance; +} xil_spi_desc; + +/** + * @brief SPI engine platform ops structure + */ +extern const struct spi_platform_ops spi_eng_platform_ops; + +/** + * @brief Xilinx specific SPI platform ops structure + */ +extern const struct spi_platform_ops xil_spi_ops; + +/** + * @brief Xilinx SPI PS register functions. No extra param needed + */ +extern const struct spi_platform_ops xil_spi_reg_ops_pl; + +#endif // SPI_EXTRA_H_ diff --git a/datalink814_sp/src/adi_noos/drivers/platform/uart_extra.h b/datalink814_sp/src/adi_noos/drivers/platform/uart_extra.h new file mode 100644 index 0000000..c877ebf --- /dev/null +++ b/datalink814_sp/src/adi_noos/drivers/platform/uart_extra.h @@ -0,0 +1,107 @@ +/******************************************************************************* + * @file xilinx/uart_extra.h + * @brief Header containing types used in the uart driver. + * @author Cristian Pop (cristian.pop@analog.com) +******************************************************************************** + * Copyright 2019(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#ifndef UART_EXTRA_H_ +#define UART_EXTRA_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +/******************************************************************************/ +/********************** Macros and Constants Definitions **********************/ +/******************************************************************************/ + +#define UART_BUFF_LENGTH 256 + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ + +/** + * @enum xil_uart_type + * @brief Xilinx platform architecture sections + */ +enum xil_uart_type { + /** Programmable Logic */ + UART_PL, + /** Processing System */ + UART_PS +}; + +/** + * @struct xil_uart_init_param + * @brief Structure holding the initialization parameters for Xilinx platform + * specific UART parameters. + */ +struct xil_uart_init_param { + /** Xilinx architecture */ + enum xil_uart_type type; + /** Interrupt Request ID */ + uint32_t irq_id; + /** Interrupt Request Descriptor */ + struct irq_ctrl_desc *irq_desc; +}; + +/** + * @struct xil_uart_desc + * @brief Xilinx platform specific UART descriptor + */ +struct xil_uart_desc { + /** Xilinx architecture */ + enum xil_uart_type type; + /** Interrupt Request ID */ + uint32_t irq_id; + /** Interrupt Request Descriptor */ + struct irq_ctrl_desc *irq_desc; + /** FIFO */ + struct fifo_element *fifo; + /** FIFO read offset */ + uint32_t fifo_read_offset; + /** UART Buffer */ + char buff[UART_BUFF_LENGTH]; + /** Number of bytes received */ + uint32_t bytes_received; + /** Total number of errors */ + uint32_t total_error_count; + /** UART Instance */ + void *instance; +}; + +#endif diff --git a/datalink814_sp/src/adi_noos/drivers/platform/xilinx_gpio.c b/datalink814_sp/src/adi_noos/drivers/platform/xilinx_gpio.c new file mode 100644 index 0000000..08ed15f --- /dev/null +++ b/datalink814_sp/src/adi_noos/drivers/platform/xilinx_gpio.c @@ -0,0 +1,464 @@ +/***************************************************************************//** + * @file xilinx/xilinx_gpio.c + * @brief Implementation of Xilinx GPIO Generic Driver. + * @author Antoniu Miclaus (antoniu.miclaus@analog.com) +******************************************************************************** + * Copyright 2019(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include + +#include +#ifdef XPAR_XGPIO_NUM_INSTANCES +#include +#endif +#ifdef XPAR_XGPIOPS_NUM_INSTANCES +#include +#endif + +#include "gpio_extra.h" +#include "../../include/error.h" +#include "../../include/gpio.h" + +/******************************************************************************/ +/************************ Functions Definitions *******************************/ +/******************************************************************************/ + +/** + * @brief Prepare the GPIO decriptor. + * @param desc - The GPIO descriptor. + * @param param - The structure that contains the GPIO parameters. + * @return SUCCESS in case of success, FAILURE otherwise. + */ +int32_t _gpio_init(struct gpio_desc *desc, + const struct gpio_init_param *param) +{ + int32_t ret; + struct xil_gpio_desc *xdesc; + struct xil_gpio_init_param *xinit; + + ret = FAILURE; + + xdesc = desc->extra; + xinit = param->extra; + + xdesc->type = xinit->type; + desc->number = param->number; + + switch (xinit->type) { + case GPIO_PL: +#ifdef XGPIO_H + xdesc->instance = (XGpio *)malloc(sizeof(XGpio)); + if(!xdesc->instance) + goto pl_error; + + xdesc->config = XGpio_LookupConfig(xinit->device_id); + if(xdesc->config == NULL) + goto pl_error; + + ret = XGpio_CfgInitialize(xdesc->instance, + xdesc->config, + ((XGpio_Config*)xdesc->config) + ->BaseAddress); + if(ret < 0) + goto pl_error; + + break; +pl_error: + free(xdesc->instance); +#endif + goto error; + case GPIO_PS: +#ifdef XGPIOPS_H + xdesc->instance = (XGpioPs *)malloc(sizeof(XGpioPs)); + if(!xdesc->instance) + goto ps_error; + + xdesc->config = XGpioPs_LookupConfig(xinit->device_id); + if(xdesc->config == NULL) + goto ps_error; + + ret = XGpioPs_CfgInitialize(xdesc->instance, + xdesc->config, + ((XGpioPs_Config*)xdesc->config)->BaseAddr); + if(ret < 0) + goto ps_error; + break; +ps_error: + free(xdesc->instance); +#endif + goto error; +error: + default: + return FAILURE; + } + + return SUCCESS; +} + +/** + * @brief Obtain the GPIO decriptor. + * @param desc - The GPIO descriptor. + * @param param - GPIO initialization parameters + * @return SUCCESS in case of success, FAILURE otherwise. + */ +int32_t xil_gpio_get(struct gpio_desc **desc, + const struct gpio_init_param *param) +{ + struct gpio_desc *descriptor; + struct xil_gpio_desc *extra; + int32_t ret; + + descriptor = (struct gpio_desc *)malloc(sizeof(*descriptor)); + extra = (struct xil_gpio_desc*)malloc(sizeof(*extra)); + + if (!descriptor || !extra) + return FAILURE; + + descriptor->extra = extra; + ret = _gpio_init(descriptor, param); + + if(ret != SUCCESS) + goto error; + + *desc = descriptor; + + return SUCCESS; +error: + free(extra); + free(descriptor); + + return FAILURE; +} + +/** + * @brief Get the value of an optional GPIO. + * @param desc - The GPIO descriptor. + * @param param - GPIO Initialization parameters. + * @return SUCCESS in case of success, FAILURE otherwise. + */ +int32_t xil_gpio_get_optional(struct gpio_desc **desc, + const struct gpio_init_param *param) +{ + if(param == NULL) { + *desc = NULL; + return SUCCESS; + } + + return xil_gpio_get(desc, param); +} + +/** + * @brief Free the resources allocated by gpio_get(). + * @param desc - The GPIO descriptor. + * @return SUCCESS in case of success, FAILURE otherwise. + */ +int32_t xil_gpio_remove(struct gpio_desc *desc) +{ + if (desc != NULL) { + free(((xil_gpio_desc *)(desc->extra))->instance); + free(desc->extra); + free(desc); + } + + return SUCCESS; +} + +/** + * @brief Enable the input direction of the specified GPIO. + * @param desc - The GPIO descriptor. + * @return SUCCESS in case of success, FAILURE otherwise. + */ +int32_t xil_gpio_direction_input(struct gpio_desc *desc) +{ + struct xil_gpio_desc *extra; +#ifdef XGPIO_H + uint8_t pin = desc->number; + uint32_t channel = 1; + uint32_t config = 0; +#endif + extra = desc->extra; + + switch (extra->type) { + case GPIO_PL: +#ifdef XGPIO_H + /* We assume that pin 32 is the first pin from channel 2 */ + if (pin >= 32) { + channel = 2; + pin -= 32; + } + + config = XGpio_GetDataDirection((XGpio *)extra->instance, + channel); + config |= (1 << pin); + XGpio_SetDataDirection((XGpio *)extra->instance, + channel, + config); +#endif + break; + case GPIO_PS: +#ifdef XGPIOPS_H + XGpioPs_SetDirectionPin(extra->instance, + desc->number, + GPIO_IN); +#endif + break; + default: + return FAILURE; + } + + return SUCCESS; +} + +/** + * @brief Enable the output direction of the specified GPIO. + * @param desc - The GPIO descriptor. + * @param value - The value. + * Example: GPIO_HIGH + * GPIO_LOW + * @return SUCCESS in case of success, FAILURE otherwise. + */ +int32_t xil_gpio_direction_output(struct gpio_desc *desc, + uint8_t value) +{ + struct xil_gpio_desc *extra; +#ifdef XGPIO_H + uint8_t pin = desc->number; + uint8_t channel; + uint32_t reg_val; +#endif + extra = desc->extra; + + switch (extra->type) { + case GPIO_PL: +#ifdef XGPIO_H + if (pin >= 32) { + channel = 2; + pin -= 32; + } else + channel = 1; + + reg_val = XGpio_GetDataDirection(extra->instance, + channel); + reg_val &= ~(1 << pin); + XGpio_SetDataDirection(extra->instance, + channel, + reg_val); + reg_val = XGpio_DiscreteRead(extra->instance, + channel); + if(value) + reg_val |= (1 << pin); + else + reg_val &= ~(1 << pin); + XGpio_DiscreteWrite(extra->instance, + channel, + reg_val); +#endif + break; + case GPIO_PS: +#ifdef XGPIOPS_H + XGpioPs_SetDirectionPin(extra->instance, + desc->number, + GPIO_OUT); + XGpioPs_SetOutputEnablePin(extra->instance, + desc->number, + GPIO_OUT); + XGpioPs_WritePin(extra->instance, + desc->number, + value); +#endif + break; + default: + return FAILURE; + } + + return SUCCESS; +} + +/** + * @brief Get the direction of the specified GPIO. + * @param desc - The GPIO descriptor. + * @param direction - The direction. + * Example: GPIO_OUT + * GPIO_IN + * @return SUCCESS in case of success, FAILURE otherwise. + */ +int32_t xil_gpio_get_direction(struct gpio_desc *desc, + uint8_t *direction) +{ + if (!desc) + return FAILURE; + + struct xil_gpio_desc *extra; + uint8_t pin = desc->number; + +#ifdef XGPIO_H + uint8_t channel; +#endif + extra = desc->extra; + + switch (extra->type) { + case GPIO_PL: +#ifdef XGPIO_H + if (pin >= 32) { + channel = 2; + pin -= 32; + } else + channel = 1; + *direction = ((XGpio_GetDataDirection(extra->instance, + channel) >> pin) & 0x1) ^ 0x1; +#endif + break; + case GPIO_PS: +#ifdef XGPIOPS_H + *direction = XGpioPs_GetDirectionPin(extra->instance, pin); +#endif + break; + default: + return FAILURE; + } + + return SUCCESS; +} + +/** + * @brief Set the value of the specified GPIO. + * @param desc - The GPIO descriptor. + * @param value - The value. + * Example: GPIO_HIGH + * GPIO_LOW + * @return SUCCESS in case of success, FAILURE otherwise. + */ +int32_t xil_gpio_set_value(struct gpio_desc *desc, + uint8_t value) +{ + struct xil_gpio_desc *extra; +#ifdef XGPIO_H + uint8_t pin = desc->number; + uint8_t channel; + uint32_t reg_val; +#endif + extra = desc->extra; + + switch (extra->type) { + case GPIO_PL: +#ifdef XGPIO_H + if (pin >= 32) { + channel = 2; + pin -= 32; + } else + channel = 1; + + reg_val = XGpio_DiscreteRead(extra->instance, channel); + if(value) + reg_val |= (1 << pin); + else + reg_val &= ~(1 << pin); + XGpio_DiscreteWrite(extra->instance, channel, reg_val); +#endif + break; + case GPIO_PS: +#ifdef XGPIOPS_H + XGpioPs_WritePin(extra->instance, desc->number, value); +#endif + break; + default: + return FAILURE; + } + + return SUCCESS; +} + +/** + * @brief Get the value of the specified GPIO. + * @param desc - The GPIO descriptor. + * @param value - The value. + * Example: GPIO_HIGH + * GPIO_LOW + * @return SUCCESS in case of success, FAILURE otherwise. + */ +int32_t xil_gpio_get_value(struct gpio_desc *desc, + uint8_t *value) +{ + if (!desc) + return FAILURE; + + struct xil_gpio_desc *extra; + uint8_t pin = desc->number; + +#ifdef XGPIO_H + uint8_t channel; +#endif + extra = desc->extra; + + switch (extra->type) { + case GPIO_PL: +#ifdef XGPIO_H + if (pin >= 32) { + channel = 2; + pin -= 32; + } else + channel = 1; + *value = (XGpio_DiscreteRead(extra->instance, channel) >> pin) & 0x01; +#endif + break; + case GPIO_PS: +#ifdef XGPIOPS_H + *value = XGpioPs_ReadPin(extra->instance, pin); +#endif + break; + default: + return FAILURE; + } + + return SUCCESS; +} + +/** + * @brief Xilinx platform specific GPIO platform ops structure + */ +const struct gpio_platform_ops xil_gpio_ops = { + .gpio_ops_get = &xil_gpio_get, + .gpio_ops_get_optional = &xil_gpio_get_optional, + .gpio_ops_remove = &xil_gpio_remove, + .gpio_ops_direction_input = &xil_gpio_direction_input, + .gpio_ops_direction_output = &xil_gpio_direction_output, + .gpio_ops_get_direction = &xil_gpio_get_direction, + .gpio_ops_set_value = &xil_gpio_set_value, + .gpio_ops_get_value = &xil_gpio_get_value, +}; diff --git a/datalink814_sp/src/adi_noos/drivers/platform/xilinx_irq.c b/datalink814_sp/src/adi_noos/drivers/platform/xilinx_irq.c new file mode 100644 index 0000000..f6dbcad --- /dev/null +++ b/datalink814_sp/src/adi_noos/drivers/platform/xilinx_irq.c @@ -0,0 +1,384 @@ +/***************************************************************************//** + * @file xilinx/xilinx_irq.c + * @brief Implementation of Xilinx IRQ Generic Driver. + * @author Cristian Pop (cristian.pop@analog.com) +******************************************************************************** + * Copyright 2019(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include +#include +#include "irq_extra.h" +#include "../../include/irq.h" +#include "../../include/error.h" +#ifdef XPAR_XSCUGIC_NUM_INSTANCES +#include +#endif +#ifdef XPAR_XINTC_NUM_INSTANCES +#include +#endif +#ifdef XPAR_XTMRCTR_NUM_INSTANCES +#include +#endif + +/******************************************************************************/ +/************************ Functions Definitions *******************************/ +/******************************************************************************/ + +/** + * @brief Initialize the IRQ interrupts. + * @param desc - The IRQ controller descriptor. + * @param param - The structure that contains the IRQ parameters. + * @return SUCCESS in case of success, FAILURE otherwise. + */ +int32_t xil_irq_ctrl_init(struct irq_ctrl_desc **desc, + const struct irq_init_param *param) +{ + int32_t status; + struct irq_ctrl_desc *descriptor; + struct xil_irq_desc *xil_dev; +#ifdef XSCUGIC_H + void *config; +#endif + + descriptor = (struct irq_ctrl_desc *)calloc(1, sizeof *descriptor); + if(!descriptor) + return FAILURE; + xil_dev = (struct xil_irq_desc *)calloc(1, sizeof *xil_dev); + if(!xil_dev) { + free(descriptor); + return FAILURE; + } + + Xil_ExceptionInit(); + + descriptor->irq_ctrl_id = param->irq_ctrl_id; + descriptor->extra = xil_dev; + xil_dev->type = ((struct xil_irq_init_param *)param->extra)->type; + + switch(xil_dev->type) { + case IRQ_PS: +#ifdef XSCUGIC_H + xil_dev->instance = calloc(1, sizeof(XScuGic)); + if(!xil_dev->instance) + goto error; + + config = XScuGic_LookupConfig(descriptor->irq_ctrl_id); + if(!config) + goto ps_error; + + status = XScuGic_CfgInitialize(xil_dev->instance, config, + ((XScuGic_Config *)config)->CpuBaseAddress); + if (status != SUCCESS) + goto ps_error; + + Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, + (Xil_ExceptionHandler)XScuGic_InterruptHandler, + xil_dev->instance); + + break; +ps_error: + free(xil_dev->instance); +#endif + goto error; + case IRQ_PL: +#ifdef XINTC_H + xil_dev->instance = calloc(1, sizeof(XIntc)); + if(!xil_dev->instance) + goto error; + + status = XIntc_Initialize(xil_dev->instance, descriptor->irq_ctrl_id); + if(status != SUCCESS) + goto pl_error; + + status = XIntc_Start(xil_dev->instance, XIN_REAL_MODE); + if(status != SUCCESS) + goto pl_error; + + break; +pl_error: + free(xil_dev->instance); +#endif + goto error; + default: + goto error; + + break; + } + + *desc = descriptor; + + return SUCCESS; + +error: + free(xil_dev); + free(descriptor); + + return FAILURE; +} + +/** + * @brief Enable global interrupts. + * @return SUCCESS in case of success, FAILURE otherwise. + */ +int32_t xil_irq_global_enable(struct irq_ctrl_desc *desc) +{ + /* Enable interrupts */ + Xil_ExceptionEnable(); + + return SUCCESS; +} + +/** + * @brief Disable global interrupts. + * @return SUCCESS in case of success, FAILURE otherwise. + */ +int32_t xil_irq_global_disable(struct irq_ctrl_desc *desc) +{ + /* Disable interrupts */ + Xil_ExceptionDisable(); + + return SUCCESS; +} + +/** + * @brief Enable specific interrupt. + * @param desc - The IRQ controller descriptor. + * @param irq_id - Interrupt identifier. + * @return SUCCESS in case of success, FAILURE otherwise. + */ +int32_t xil_irq_enable(struct irq_ctrl_desc *desc, uint32_t irq_id) +{ + struct xil_irq_desc *xil_dev = desc->extra; + + switch(xil_dev->type) { + case IRQ_PS: +#ifdef XSCUGIC_H + XScuGic_Enable(xil_dev->instance, irq_id); +#endif + break; + case IRQ_PL: +#ifdef XINTC_H + XIntc_Enable(xil_dev->instance, irq_id); +#endif + break; + default: + + return FAILURE; + } + + return SUCCESS; +} + +/** + * @brief Disable specific interrupt. + * @param desc - The IRQ controller descriptor. + * @param irq_id - Interrupt identifier. + * @return SUCCESS in case of success, FAILURE otherwise. + */ +int32_t xil_irq_disable(struct irq_ctrl_desc *desc, uint32_t irq_id) +{ + struct xil_irq_desc *xil_dev = desc->extra; + + switch(xil_dev->type) { + case IRQ_PS: +#ifdef XSCUGIC_H + XScuGic_Disable(xil_dev->instance, irq_id); +#endif + break; + case IRQ_PL: +#ifdef XINTC_H + XIntc_Disable(xil_dev->instance, irq_id); +#endif + break; + default: + + return FAILURE; + } + + return SUCCESS; +} + +/** + * @brief Register a callback to handle the irq events. + * @param desc - The IRQ controller descriptor. + * @param irq_id - Interrupt identifier. + * @param callback_desc - Callback descriptor + * @return SUCCESS in case of success, FAILURE otherwise. + */ +int32_t xil_irq_register_callback(struct irq_ctrl_desc *desc, uint32_t irq_id, + struct callback_desc *callback_desc) +{ + struct xil_irq_desc *xil_dev = desc->extra; + + switch(xil_dev->type) { + case IRQ_PS: +#ifdef XSCUGIC_H + return XScuGic_Connect(xil_dev->instance, irq_id, + (Xil_InterruptHandler) callback_desc->callback, + callback_desc->ctx); +#endif + break; +// case IRQ_PL: +//#ifdef XINTC_H +// if (irq_id == XPAR_AXI_INTC_AXI_TIMER_INTERRUPT_INTR) { +// int32_t ret; +// +// ret = XIntc_Connect(xil_dev->instance, irq_id, +// XTmrCtr_InterruptHandler, callback_desc->config); +// if (IS_ERR_VALUE(ret)) +// return FAILURE; +// XTmrCtr_SetHandler(callback_desc->config, +// (XTmrCtr_Handler)callback_desc->callback, +// callback_desc->ctx); +// +// return SUCCESS; +// } +// return XIntc_Connect(xil_dev->instance, irq_id, +// (XInterruptHandler) callback_desc->callback, +// callback_desc->ctx); +//#endif +// break; + default: + break; + } + + return FAILURE; +} + +/** + * @brief Set interrupt trigger level. + * @param desc - The IRQ controller descriptor. + * @param irq_id - Interrupt identifier. + * @param trig - New trigger level for the interrupt. + * @return SUCCESS in case of success, FAILURE otherwise. + */ +int32_t xil_irq_trigger_level_set(struct irq_ctrl_desc *desc, uint32_t irq_id, + enum irq_trig_level trig) +{ + struct xil_irq_desc *xil_dev = desc->extra; + + if(trig == IRQ_EDGE_BOTH) + return -EINVAL; + + switch(xil_dev->type) { + case IRQ_PS: +#ifdef XSCUGIC_H + ; + uint8_t priority, trigger; + + XScuGic_GetPriorityTriggerType(xil_dev->instance, irq_id, &priority, + &trigger); + trigger = trig; + XScuGic_SetPriorityTriggerType(xil_dev->instance, irq_id, priority, + trigger); + + return SUCCESS; +#endif + break; + case IRQ_PL: +#ifdef XINTC_H + /* Interrupt trigger determined in hardware. TODO: verify */ + return SUCCESS; +#endif + break; + default: + break; + } + + return FAILURE; +} + +/** + * @brief Unregisters a generic IRQ handling function. + * @param desc - The IRQ controller descriptor. + * @param irq_id - Interrupt identifier. + * @return SUCCESS in case of success, FAILURE otherwise. + */ +int32_t xil_irq_unregister(struct irq_ctrl_desc *desc, uint32_t irq_id) +{ + struct xil_irq_desc *xil_dev = desc->extra; + + switch(xil_dev->type) { + case IRQ_PS: +#ifdef XSCUGIC_H + XScuGic_Disconnect(xil_dev->instance, irq_id); +#endif + break; + case IRQ_PL: +#ifdef XINTC_H + XIntc_Disconnect(xil_dev->instance, irq_id); +#endif + break; + default: + + return FAILURE; + } + + return SUCCESS; +} + +/** + * @brief Free the resources allocated by irq_ctrl_init(). + * @param desc - The IRQ control descriptor. + * @return SUCCESS in case of success, FAILURE otherwise. + */ +int32_t xil_irq_ctrl_remove(struct irq_ctrl_desc *desc) +{ + struct xil_irq_desc *xil_dev = desc->extra; + free(xil_dev->instance); + free(desc->extra); + free(desc); + + return SUCCESS; +} + +/** + * @brief Xilinx platform specific IRQ platform ops structure + */ +const struct irq_platform_ops xil_irq_ops = { + .init = &xil_irq_ctrl_init, + .register_callback = &xil_irq_register_callback, + .unregister = &xil_irq_unregister, + .global_enable = &xil_irq_global_enable, + .global_disable = &xil_irq_global_disable, + .trigger_level_set = &xil_irq_trigger_level_set, + .enable = &xil_irq_enable, + .disable = &xil_irq_disable, + .remove = &xil_irq_ctrl_remove +}; diff --git a/datalink814_sp/src/adi_noos/drivers/platform/xilinx_spi.c b/datalink814_sp/src/adi_noos/drivers/platform/xilinx_spi.c new file mode 100644 index 0000000..adc3832 --- /dev/null +++ b/datalink814_sp/src/adi_noos/drivers/platform/xilinx_spi.c @@ -0,0 +1,461 @@ +/***************************************************************************//** + * @file xilinx/xilinx_spi.c + * @brief Implementation of Xilinx SPI Generic Driver. + * @author Antoniu Miclaus (antoniu.miclaus@analog.com) +******************************************************************************** + * Copyright 2019(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include + +#include +#ifdef XPAR_XSPI_NUM_INSTANCES +#include +#endif +#ifdef XPAR_XSPIPS_NUM_INSTANCES +#include +#endif + +#include "../../include/error.h" +#include "../../include/spi.h" +#include "spi_extra.h" + +#if defined(PLATFORM_ZYNQ) +#define SPI_CLK_FREQ_HZ(dev) (XPAR_PS7_SPI_ ## dev ## _SPI_CLK_FREQ_HZ) +#define SPI_NUM_INSTANCES XPAR_XSPIPS_NUM_INSTANCES +#elif defined(PLATFORM_ZYNQMP) +#define SPI_CLK_FREQ_HZ(dev) (XPAR_PSU_SPI_ ## dev ## _SPI_CLK_FREQ_HZ) +#define SPI_NUM_INSTANCES XPAR_XSPIPS_NUM_INSTANCES +#else +#define SPI_NUM_INSTANCES 0 +#endif + +/******************************************************************************/ +/************************ Functions Definitions *******************************/ +/******************************************************************************/ + +/** + * @brief Initialize the hardware SPI peripherial + * + * @param xdesc Platform specific SPI descriptor + * @param xinit Platform specific SPI init param + * @return int32_t FAILURE if the device couldn't be found or configured + */ +static int32_t spi_init_pl(struct spi_desc *desc, + const struct spi_init_param *param) +{ +#ifdef XSPI_H + int32_t ret; + struct xil_spi_desc *xdesc; + struct xil_spi_init_param *xinit; + + xdesc = (xil_spi_desc*)malloc(sizeof(xil_spi_desc)); + if(!xdesc) { + free(xdesc); + return FAILURE; + } + + desc->extra = xdesc; + xinit = param->extra; + xdesc->type = xinit->type; + xdesc->flags = xinit->flags; + + xdesc->instance = (XSpi*)calloc(1, sizeof(XSpi)); + if(!xdesc->instance) + goto pl_error; + + xdesc->config = XSpi_LookupConfig(param->device_id); + if(xdesc->config == NULL) + goto pl_error; + + ret = XSpi_CfgInitialize(xdesc->instance, + xdesc->config, + ((XSpi_Config*)xdesc->config) + ->BaseAddress); + if(ret != SUCCESS) + goto pl_error; + + ret = XSpi_Initialize(xdesc->instance, param->device_id); + if (ret != SUCCESS) + goto pl_error; + + ret = XSpi_SetOptions(xdesc->instance, + XSP_MASTER_OPTION | + ((desc->mode & SPI_CPOL) ? + XSP_CLK_ACTIVE_LOW_OPTION : 0) | + ((desc->mode & SPI_CPHA) ? + XSP_CLK_PHASE_1_OPTION : 0)); + if (ret != SUCCESS) + goto pl_error; + + ret = XSpi_Start(xdesc->instance); + if (ret != SUCCESS) + goto pl_error; + + XSpi_IntrGlobalDisable((XSpi *)(xdesc->instance)); + + return SUCCESS; + +pl_error: + free(xdesc->instance); + free(xdesc); +#endif + return FAILURE; +} + +/** + * @brief Initialize the hardware SPI peripherial + * + * @param xdesc Platform specific SPI descriptor + * @param xinit Platform specific SPI init param + * @return int32_t FAILURE if the device couldn't be found or configured + */ +static int32_t spi_init_ps(struct spi_desc *desc, + const struct spi_init_param *param) +{ +#ifdef XSPIPS_H + int32_t ret; + struct xil_spi_desc *xdesc; + struct xil_spi_init_param *xinit; + const uint32_t prescaler_default = XSPIPS_CLK_PRESCALE_64; + const uint32_t prescaler_min = XSPIPS_CLK_PRESCALE_4; + const uint32_t prescaler_max = XSPIPS_CLK_PRESCALE_256; + uint32_t prescaler = 0u; + uint32_t input_clock = 0u; + + xdesc = (xil_spi_desc*)malloc(sizeof(xil_spi_desc)); + if(!xdesc) { + free(xdesc); + return FAILURE; + } + + desc->extra = xdesc; + xinit = param->extra; + xdesc->type = xinit->type; + xdesc->flags = xinit->flags; + + xdesc->instance = (XSpiPs*)malloc(sizeof(XSpiPs)); + if(!xdesc->instance) + goto ps_error; + + xdesc->config = XSpiPs_LookupConfig(param->device_id); + if(xdesc->config == NULL) + goto ps_error; + + ret = XSpiPs_CfgInitialize(xdesc->instance, + xdesc->config, + ((XSpiPs_Config*)xdesc->config) + ->BaseAddress); + if(ret != SUCCESS) + goto ps_error; + + switch (param->device_id) { +#if (SPI_NUM_INSTANCES >= 1) + case 0: + input_clock = SPI_CLK_FREQ_HZ(0); + break; +#endif +#if (SPI_NUM_INSTANCES >= 2) + case 1: + input_clock = SPI_CLK_FREQ_HZ(1); + break; +#endif + default: + goto ps_error; + }; + + if (desc->max_speed_hz != 0u) { + uint32_t div = input_clock / desc->max_speed_hz; + uint32_t rem = input_clock % desc->max_speed_hz; + uint32_t po2 = !(div & (div - 1)) && !rem; + + // find the power of two just higher than div and + // store the exponent in prescaler + while(div) { + prescaler += 1; + div >>= 1u; + } + + // this exponent - 1 is needed because of the way + // xilinx stores it into registers + if (prescaler) + prescaler -= 1; + + // this exponent - 1 is needed when initial div was + // precisely a power of two + if (prescaler && po2) + prescaler -= 1; + + if (prescaler < prescaler_min) + prescaler = prescaler_min; + + if (prescaler > prescaler_max) + prescaler = prescaler_max; + } else + prescaler = prescaler_default; + + ret = XSpiPs_SetClkPrescaler(xdesc->instance, prescaler); + + if(ret != SUCCESS) + goto ps_error; + + return SUCCESS; + +ps_error: + free(xdesc->instance); + free(xdesc); +#endif + return FAILURE; +} + +/** + * @brief Initialize the SPI communication peripheral. + * @param desc - The SPI descriptor. + * @param param - The structure that contains the SPI parameters. + * @return SUCCESS in case of success, FAILURE otherwise. + */ +int32_t xil_spi_init(struct spi_desc **desc, + const struct spi_init_param *param) +{ + int32_t ret; + enum xil_spi_type *spi_type; + + if (!param) { + return FAILURE; + } + + *desc = malloc(sizeof(**desc)); + if(! *desc) { + free(*desc); + return FAILURE; + } + + spi_type = param->extra; + + if(!spi_type) + goto init_error; + + (*desc)->max_speed_hz = param->max_speed_hz; + (*desc)->mode = param->mode; + (*desc)->bit_order = param->bit_order; + (*desc)->chip_select = param->chip_select; + + switch (*spi_type) { + case SPI_PL: + ret = spi_init_pl(*desc, param); + break; + case SPI_PS: + ret = spi_init_ps(*desc, param); + break; + + default: + goto init_error; + break; + } + + if (ret != SUCCESS) { +init_error: + free(*desc); + + return FAILURE; + } + + return ret; +} + +/** + * @brief Free the resources allocated by spi_init(). + * @param desc - The SPI descriptor. + * @return SUCCESS in case of success, FAILURE otherwise. + */ +int32_t xil_spi_remove(struct spi_desc *desc) +{ +#ifdef XSPI_H + int32_t ret; +#endif + struct xil_spi_desc *xdesc = NULL; + enum xil_spi_type *spi_type; + + spi_type = desc->extra; + + if(!spi_type) + return FAILURE; + + switch (*spi_type ) { + case SPI_PL: +#ifdef XSPI_H + xdesc = desc->extra; + + if(!xdesc) + return FAILURE; + + ret = XSpi_Stop((XSpi *)(xdesc->instance)); + if(ret != SUCCESS) + goto error; +#endif + break; + case SPI_PS: +#ifdef XSPIPS_H + xdesc = desc->extra; + + if(!xdesc) + return FAILURE; +#endif + break; + + /* Intended fallthrough */ +#ifdef XSPI_H +error: +#endif + default: + return FAILURE; + } + + if(xdesc) + free(xdesc->instance); + free(desc->extra); + free(desc); + + return SUCCESS; +} + +/** + * @brief Write and read data to/from SPI. + * @param desc - The SPI descriptor. + * @param data - The buffer with the transmitted/received data. + * @param bytes_number - Number of bytes to write/read. + * @return SUCCESS in case of success, FAILURE otherwise. + */ +int32_t xil_spi_write_and_read(struct spi_desc *desc, + uint8_t *data, + uint16_t bytes_number) +{ + int32_t ret; +#ifdef XSPI_H + uint32_t ctrl_reg; +#endif + struct xil_spi_desc *xdesc; + enum xil_spi_type *spi_type; + + ret = FAILURE; + + spi_type = desc->extra; + + if(!spi_type) + return FAILURE; + + xdesc = desc->extra; + + switch (*spi_type) { + case SPI_PL: +#ifdef XSPI_H + ret = XSpi_SetOptions(xdesc->instance, + XSP_MASTER_OPTION | + ((desc->mode & SPI_CPOL) ? + XSP_CLK_ACTIVE_LOW_OPTION : 0) | + ((desc->mode & SPI_CPHA) ? + XSP_CLK_PHASE_1_OPTION : 0)); + if (ret != SUCCESS) + goto error; + + ctrl_reg = XSpi_GetControlReg(((XSpi*)xdesc->instance)); + if (desc->bit_order == SPI_BIT_ORDER_LSB_FIRST) + ctrl_reg |= XSP_CR_LSB_MSB_FIRST_MASK; + else + ctrl_reg &= ~ XSP_CR_LSB_MSB_FIRST_MASK; + XSpi_SetControlReg(((XSpi*)xdesc->instance), ctrl_reg); + + ret = XSpi_SetSlaveSelect(xdesc->instance, + 0x01 << desc->chip_select); + if (ret != SUCCESS) + goto error; + + ret = XSpi_Transfer(xdesc->instance, + data, + data, + bytes_number); + if (ret != SUCCESS) + goto error; +#endif + break; + case SPI_PS: +#ifdef XSPIPS_H + ret = XSpiPs_SetOptions(xdesc->instance, + XSPIPS_MASTER_OPTION | + ((xdesc->flags & SPI_CS_DECODE) ? + XSPIPS_DECODE_SSELECT_OPTION : 0) | + XSPIPS_FORCE_SSELECT_OPTION | + ((desc->mode & SPI_CPOL) ? + XSPIPS_CLK_ACTIVE_LOW_OPTION : 0) | + ((desc->mode & SPI_CPHA) ? + XSPIPS_CLK_PHASE_1_OPTION : 0)); + if (ret != SUCCESS) + goto error; + + ret = XSpiPs_SetSlaveSelect(xdesc->instance, + desc->chip_select); + if (ret != SUCCESS) + goto error; + ret = XSpiPs_PolledTransfer(xdesc->instance, + data, + data, + bytes_number); + if (ret != SUCCESS) + goto error; + ret = XSpiPs_SetSlaveSelect(xdesc->instance, SPI_DEASSERT_CURRENT_SS); + if (ret != SUCCESS) + goto error; +#endif + break; +error: + default: + return FAILURE; + } + + return ret; +} + +/** + * @brief Xilinx platform specific SPI platform ops structure + */ +const struct spi_platform_ops xil_spi_ops = { + .init = &xil_spi_init, + .write_and_read = &xil_spi_write_and_read, + .write_and_read_3wire = NULL, // Not support. + .remove = &xil_spi_remove +}; diff --git a/datalink814_sp/src/adi_noos/drivers/platform/xilinx_spi_pl.c b/datalink814_sp/src/adi_noos/drivers/platform/xilinx_spi_pl.c new file mode 100644 index 0000000..ed74cc8 --- /dev/null +++ b/datalink814_sp/src/adi_noos/drivers/platform/xilinx_spi_pl.c @@ -0,0 +1,531 @@ +/******************************************************************************* + * @file xilinx/xilinx_spi_pl.c + * @brief Driver for spi pl device using registers + * @author Mihail Chindris (mihail.chindris@analog.com) +******************************************************************************** + * Copyright 2021(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#include + +#ifdef XPAR_XSPI_NUM_INSTANCES + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include +#include +#include +#include "spi.h" +#include "error.h" +#include "delay.h" +#include "util.h" + +/******************************************************************************/ +/********************** Macros and Constants Definitions **********************/ +/******************************************************************************/ + +#define XPS_TYPE_WRITE 0x1 +#define XPS_TYPE_READ 0x2 +#define XSP_DEFAULT_SR_VALUE 0x25 +#define XSP_DUMMY_DATA 0xFF + +/* + * Used to store current spi device configuration in order to not update it for + * each spi transaction if not needed. + */ +static struct spi_desc g_spi_desc[XPAR_XSPI_NUM_INSTANCES]; + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ + +/* Xilinx PL spi specific data */ +struct xspi_desc { + uint32_t base_addr; + uint32_t disable_slaves_mask; + uint32_t fifo_depth; + uint8_t cs_asserted; +}; + +/* Structure used to iterate over SPI messages */ +struct msg_iter { + struct spi_msg *msgs; + uint32_t len; + uint32_t i; + uint32_t buff_i; + uint8_t is_wr; +}; + +/******************************************************************************/ +/************************ Functions Definitions *******************************/ +/******************************************************************************/ + +/* Read device register */ +static inline uint32_t _read(struct xspi_desc *xdesc, uint32_t reg) +{ + return Xil_In32(xdesc->base_addr + reg); +} + +/* Write device register */ +static inline void _write(struct xspi_desc *xdesc, uint32_t reg, uint32_t val) +{ + Xil_Out32(xdesc->base_addr + reg, val); +} + +/* Update device register. Only bits set to 1 in mask will be modified */ +static inline void _wr_mask(struct xspi_desc *xdesc, uint32_t reg, + uint32_t val, uint32_t mask) +{ + uint32_t tmp; + + tmp = _read(xdesc, reg); + tmp &= ~mask; + tmp |= val & mask; + _write(xdesc, reg, tmp); +} + +/* Update spi device configuration if needed */ +static void _update_mode(struct spi_desc *desc) +{ + uint32_t val; + uint32_t mask; + + if (desc->mode == g_spi_desc[desc->device_id].mode && + desc->bit_order == g_spi_desc[desc->device_id].bit_order) + return ; + + /* Update mode */ + val = desc->mode | SPI_CPOL ? XSP_CR_CLK_POLARITY_MASK : 0; + val |= desc->mode | SPI_CPHA ? XSP_CR_CLK_PHASE_MASK : 0; + mask = XSP_CR_CLK_POLARITY_MASK | XSP_CR_CLK_PHASE_MASK; + + val |= desc->bit_order == SPI_BIT_ORDER_LSB_FIRST ? + XSP_CR_LSB_MSB_FIRST_MASK : 0; + mask |= XSP_CR_LSB_MSB_FIRST_MASK; + + _wr_mask(desc->extra, XSP_CR_OFFSET, val, mask); + g_spi_desc[desc->device_id] = *desc; +} + +/* Configure SPI PL device */ +static int32_t _xil_spi_init_dev(struct xspi_desc *xdesc) +{ + uint32_t val; + + /* Software reset */ + _write(xdesc, XSP_SRR_OFFSET, XSP_SRR_RESET_MASK); + mdelay(1); + + /* Check if success reset */ + val = _read(xdesc, XSP_SR_OFFSET); + if (val != XSP_DEFAULT_SR_VALUE) + return -ENODEV; + + /* Disable interrupts. Drivers only works with pooled mode */ + _write(xdesc, XSP_IIER_OFFSET, 0); + + /* Deasert chip selects */ + _write(xdesc, XSP_SSR_OFFSET, 0xFFFFFFFF); + + /* Get fifo depth */ + while (!(_read(xdesc, XSP_SR_OFFSET) & XSP_SR_TX_FULL_MASK)) + _write(xdesc, XSP_DTR_OFFSET, XSP_DUMMY_DATA); + xdesc->fifo_depth = _read(xdesc, XSP_TFO_OFFSET) + 1; + + /* Configure spi device */ + val = XSP_CR_ENABLE_MASK | + XSP_CR_MANUAL_SS_MASK | + XSP_CR_TXFIFO_RESET_MASK | + XSP_CR_RXFIFO_RESET_MASK | + XSP_CR_MASTER_MODE_MASK | + XSP_CR_TRANS_INHIBIT_MASK; + + _write(xdesc, XSP_CR_OFFSET, val); + + return SUCCESS; +} + +/* Initialize spi_desc structure and device */ +static int32_t xil_spi_init_pl(struct spi_desc **desc, + const struct spi_init_param *param) +{ + struct spi_desc *ldesc; + struct xspi_desc *xdesc; + int32_t err; + XSpi_Config *cfg; + + if (!desc || !param || param->device_id >= XPAR_XSPI_NUM_INSTANCES) + return -EINVAL; + + cfg = XSpi_LookupConfig(param->device_id); + if (!cfg) + return -EINVAL; + + if (param->chip_select > cfg->NumSlaveBits) + return -EINVAL; + + ldesc = (struct spi_desc *)calloc(1, sizeof(*ldesc)); + if (!ldesc) + return -ENOMEM; + + xdesc = (struct xspi_desc *)calloc(1, sizeof(*xdesc)); + if (!xdesc) { + err = -ENOMEM; + goto error; + } + + ldesc->bit_order = param->bit_order; + ldesc->chip_select = param->chip_select; + ldesc->mode = param->mode; + xdesc->base_addr = cfg->BaseAddress; + xdesc->disable_slaves_mask = (1 << cfg->NumSlaveBits) - 1; + xdesc->cs_asserted = 0; + + err = _xil_spi_init_dev(xdesc); + if (IS_ERR_VALUE(err)) + goto error; + + ldesc->extra = xdesc; + *desc = ldesc; + + return SUCCESS; + +error: + free(xdesc); + free(ldesc); + + return err; +} + +/* Remove allocated resources */ +static int32_t xil_spi_remove_pl(struct spi_desc *desc) +{ + if (!desc) + return -EINVAL; + + free(desc->extra); + free(desc); + + return SUCCESS; +} + +/* + * Fill fifo until fifo is full or no more data available. + * Return the number of written bytes. + */ +static uint32_t _wr_fifo(struct xspi_desc *xdesc, uint8_t *data, + uint32_t len) +{ + uint32_t i; + uint32_t to_write; + uint32_t tx_available; + + tx_available = xdesc->fifo_depth - _read(xdesc, XSP_TFO_OFFSET); + to_write = min(tx_available, len); + for (i = 0; i < to_write; ++i) + if (data) + _write(xdesc, XSP_DTR_OFFSET, data[i]); + else + _write(xdesc, XSP_DTR_OFFSET, XSP_DUMMY_DATA); + + return to_write; +} + +/* + * Read fifo until fifo is empty or no more buffer available to read into + * Returns the number of read bytes + */ +static uint32_t _rd_fifo(struct xspi_desc *xdesc, uint8_t *data, + uint32_t len) +{ + uint32_t rx_available; + uint32_t to_read; + uint32_t tmp; + uint32_t i; + + tmp = _read(xdesc, XSP_SR_OFFSET); + if (tmp & XSP_SR_RX_EMPTY_MASK) + return 0; + + rx_available = _read(xdesc, XSP_RFO_OFFSET) + 1; + to_read = min(rx_available, len); + for (i = 0; i < to_read; ++i) { + tmp = _read(xdesc, XSP_DRR_OFFSET); + if (data) + data[i] = tmp; + } + + return to_read; +} + +/* If start is 0 stop transfer, else start it. + * CS will be asserted if needed. If different CS othere than the one needed + * is asserted. Deassert it and assert correct one */ +static void _xil_spi_start_transfer(struct spi_desc *desc, uint8_t start) +{ + struct xspi_desc *xdesc; + + xdesc = desc->extra; + if (start) { + if (xdesc->cs_asserted) { + if (desc->chip_select == + g_spi_desc[desc->device_id].chip_select) + return ; + else + /* Stop transfer to start again with new CS */ + _xil_spi_start_transfer(desc, 0); + } + _write(xdesc, XSP_SSR_OFFSET, ~(1 << desc->chip_select)); + _wr_mask(xdesc, XSP_CR_OFFSET, 0, XSP_CR_TRANS_INHIBIT_MASK); + } else { + _wr_mask(xdesc, XSP_CR_OFFSET, XSP_CR_TRANS_INHIBIT_MASK, + XSP_CR_TRANS_INHIBIT_MASK); + _write(xdesc, XSP_SSR_OFFSET, xdesc->disable_slaves_mask); + } + xdesc->cs_asserted = start; +} + + +/* SPI polled transfer */ +static int32_t xil_spi_write_and_read_pl(struct spi_desc *desc, uint8_t *data, + uint16_t bytes_number) +{ + struct xspi_desc *xdesc; + uint32_t rx; + uint32_t tx; + + if (!desc || !desc->extra) + return -EINVAL; + + xdesc = desc->extra; + _update_mode(desc); + + _xil_spi_start_transfer(desc, 1); + rx = 0; + tx = 0; + while (rx < bytes_number) { + if (tx < bytes_number) + tx += _wr_fifo(xdesc, data + tx, bytes_number - tx); + rx += _rd_fifo(xdesc, data + rx, bytes_number - rx); + } + _xil_spi_start_transfer(desc, 0); + + return SUCCESS; +} + +/* Get type of message. It can be READ, WRITE or both */ +static uint32_t _get_msg_type(struct spi_msg *msg) +{ + uint32_t type; + + type = 0; + if (msg->tx_buff) + type |= XPS_TYPE_WRITE; + if (msg->rx_buff) + type |= XPS_TYPE_READ; + + return type; +} + +/* Get information based on current iterator position */ +static void _get_data(struct msg_iter *it, uint8_t **buff, uint32_t *len, + uint32_t *type) +{ + struct spi_msg *msg; + + if (it->i == it->len) { + *len = 0; + return ; + } + + msg = it->msgs + it->i; + if (it->is_wr) + *buff = msg->tx_buff; + else + *buff = msg->rx_buff; + + if (*buff) + *buff += it->buff_i; + + *len = msg->bytes_number - it->buff_i; + if (type) + *type = _get_msg_type(msg); +} + +/* + * Increment iterator position with desired length. + * If the new position has a different message type, new_type will be set to 1 + * If a CS change is needed, cs_change is set + */ +static void _increment_iter(struct msg_iter *it, uint32_t len, + uint8_t *cs_change, uint8_t *new_type) +{ + struct spi_msg *msg; + uint32_t type; + uint32_t extra_len; + + if (!len) + return ; + + *cs_change = 0; + *new_type = 0; + msg = it->msgs + it->i; + if (it->buff_i + len > msg->bytes_number) + extra_len = it->buff_i + len - msg->bytes_number; + else + extra_len = 0; + len -= extra_len; + it->buff_i += len; + if (it->buff_i == msg->bytes_number) { + type = _get_msg_type(msg); + ++it->i; + it->buff_i = 0; + if (cs_change && msg->cs_change) + *cs_change = 1; + if (new_type) + if (it->i == it->len || + type != _get_msg_type(it->msgs + it->i)) + *new_type = 1; + } + if (extra_len) + _increment_iter(it, extra_len, cs_change, new_type); +} + +/* + * SPI polling transfer of multiple messages. + */ +static int32_t xil_spi_transfer_pl(struct spi_desc *desc, struct spi_msg *msgs, + uint32_t len) + +{ + struct xspi_desc *xdesc; + uint8_t cs_change; + uint8_t new_type; + struct msg_iter rx = {.msgs = msgs, .len = len, .is_wr = 0}; + struct msg_iter tx = {.msgs = msgs, .len = len, .is_wr = 1}; + uint8_t *buff; + uint32_t bytes; + uint32_t type; + /* Bytes to increment rx when only a write transaction is executed */ + uint32_t to_inc_rx; + /* Difference between rx and tx iterators in bytes */ + uint32_t tx_advance; + /* Save bytes sent during a write loop */ + uint32_t tx_sent; + /* Used to loop if need to empty the RX FIFO */ + uint32_t loop; + + if (!desc || !desc->extra) + return -EINVAL; + + xdesc = desc->extra; + _update_mode(desc); + + tx_advance = 0; + to_inc_rx = 0; + buff = NULL; + type = 0; + do { + _xil_spi_start_transfer(desc, 1); + + tx_sent = 0; + /* Writing loop */ + do { + _get_data(&tx, &buff, &bytes, &type); + if (type & XPS_TYPE_READ) + /* + * Do not write more bytes than fifo_depth if + * they haven't been read. + */ + bytes = min(bytes, + xdesc->fifo_depth - tx_advance); + bytes = _wr_fifo(xdesc, buff, bytes); + tx_sent += bytes; + _increment_iter(&tx, bytes, &cs_change, &new_type); + tx_advance += bytes; + } while (!cs_change && !new_type && bytes); + + if (type & XPS_TYPE_READ) { + loop = 1; + /* + * Loop only when no more data to write otherwise read + * only available data. + */ + while (loop) { + if (!new_type) + loop = 0; + _get_data(&rx, &buff, &bytes, NULL); + bytes = _rd_fifo(xdesc, buff, bytes); + _increment_iter(&rx, bytes, &cs_change, &new_type); + tx_advance -= bytes; + if (loop && new_type) + break; + } + } else { + /* Clean RX FIFO if it was only a WRITE message */ + to_inc_rx += tx_sent; + if (new_type) { + /* Wait for TX to be sent */ + while (!(_read(xdesc, XSP_SR_OFFSET) & + XSP_SR_TX_EMPTY_MASK)) + ; + /* Reset fifo. Only write was performed */ + _wr_mask(xdesc, XSP_CR_OFFSET, + XSP_CR_RXFIFO_RESET_MASK, + XSP_CR_RXFIFO_RESET_MASK); + + _increment_iter(&rx, to_inc_rx, NULL, NULL); + tx_advance -= to_inc_rx; + to_inc_rx = 0; + } + } + + if ((cs_change && rx.i != len) || (!cs_change && rx.i == len)) + _xil_spi_start_transfer(desc, 0); + } while (rx.i < len); + + return SUCCESS; +} + +const struct spi_platform_ops xil_spi_reg_ops_pl = { + .init = xil_spi_init_pl, + .remove = xil_spi_remove_pl, + .write_and_read = xil_spi_write_and_read_pl, + .write_and_read_3wire = NULL, // Not support. + .transfer = xil_spi_transfer_pl +}; + +#endif // XPAR_XSPI_NUM_INSTANCES diff --git a/datalink814_sp/src/adi_noos/drivers/rf-transceiver/ad9361_reg/ad9361_reg.c b/datalink814_sp/src/adi_noos/drivers/rf-transceiver/ad9361_reg/ad9361_reg.c new file mode 100644 index 0000000..5cf7d2d --- /dev/null +++ b/datalink814_sp/src/adi_noos/drivers/rf-transceiver/ad9361_reg/ad9361_reg.c @@ -0,0 +1,151 @@ +/***************************************************************************//** + * @file ad9361_reg.c + * @brief Implementation of AD9680 Driver. + * @author DBogdan (dragos.bogdan@analog.com) + ******************************************************************************** + * Copyright 2014-2016(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include "ad9361_reg.h" + +#include +#include +#include "../../../include/error.h" + +/***************************************************************************//** + * @brief ad9361_reg_read + *******************************************************************************/ +int32_t ad9361_reg_read(struct ad9361_reg_dev *dev, + uint16_t reg_addr, + uint8_t *reg_data) +{ + uint8_t tx_buf[2]; + uint8_t rx_buf[1]; + int32_t ret; + + tx_buf[0] = reg_addr >> 8; + tx_buf[1] = reg_addr & 0xFF; + + + ret = spi_write_and_read_3wire(dev->spi_desc, + tx_buf, rx_buf, 2, 1); + + *reg_data = rx_buf[0]; + + return ret; +} + +/***************************************************************************//** + * @brief ad9361_reg_write + *******************************************************************************/ +int32_t ad9361_reg_write(struct ad9361_reg_dev *dev, + uint16_t reg_addr, + uint8_t reg_data) +{ + uint8_t buf[3]; + + int32_t ret; + + buf[0] = 0x80 | reg_addr >> 8; + buf[1] = reg_addr & 0xFF; + buf[2] = reg_data; + + ret = spi_write_and_read_3wire(dev->spi_desc, + buf, NULL, 3, 0); + return ret; +} + +/***************************************************************************//** + * @brief ad9361_reg_init + *******************************************************************************/ +int32_t ad9361_reg_init(struct ad9361_reg_dev **device, + const struct ad9361_reg_init_param *init_param) +{ + int ret = SUCCESS; + struct ad9361_reg_dev *dev; + + dev = (struct ad9361_reg_dev *)malloc(sizeof(*dev)); + if (!dev) + return FAILURE; + + /* SPI */ + ret = spi_init(&dev->spi_desc, init_param->spi_init); + ret |= gpio_get(&dev->gpio_desc_resetb, init_param->gpio_resetb); + +// gpio_direction_output(dev->gpio_desc_resetb, 0); +// +// ad9361_reg_reset(dev); + + *device = dev; + + return ret; +} + +/** + * AD9361 Device Reset + * @param phy The AD9361 state structure. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_reg_reset(struct ad9361_reg_dev *dev) +{ + if (dev->gpio_desc_resetb) { + gpio_set_value(dev->gpio_desc_resetb, 0); + mdelay(10); + gpio_set_value(dev->gpio_desc_resetb, 1); + mdelay(10); + return 0; + } + return 0; +} + +/***************************************************************************//** + * @brief Free the resources allocated by ad9361_reg_setup(). + * + * @param dev - The device structure. + * + * @return SUCCESS in case of success, negative error code otherwise. +*******************************************************************************/ +int32_t ad9361_reg_remove(struct ad9361_reg_dev *dev) +{ + int32_t ret; + + ret = spi_remove(dev->spi_desc); + + free(dev); + + return ret; +} diff --git a/datalink814_sp/src/adi_noos/drivers/rf-transceiver/ad9361_reg/ad9361_reg.h b/datalink814_sp/src/adi_noos/drivers/rf-transceiver/ad9361_reg/ad9361_reg.h new file mode 100644 index 0000000..46c486b --- /dev/null +++ b/datalink814_sp/src/adi_noos/drivers/rf-transceiver/ad9361_reg/ad9361_reg.h @@ -0,0 +1,104 @@ +/***************************************************************************//** + * @file ad9361_reg.h + * @brief Header file of ad9361_reg Driver. + * @author DBogdan (dragos.bogdan@analog.com) + ******************************************************************************** + * Copyright 2014-2016(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *******************************************************************************/ +#ifndef ad9361_reg_H_ +#define ad9361_reg_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include +#include "../../../include/delay.h" +#include "../../../include/spi.h" +#include "../../../include/gpio.h" + +/******************************************************************************/ +/********************** Macros and Constants Definitions **********************/ +/******************************************************************************/ + + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ +struct ad9361_reg_dev { + /* SPI */ + spi_desc *spi_desc; + gpio_desc *gpio_desc_resetb; +}; + +struct ad9361_reg_init_param { + /* SPI */ + spi_init_param *spi_init; + gpio_init_param *gpio_resetb; +}; + +enum Operation_Type{ + AD9361_WRITE, + AD9361_READ, + AD9361_WAIT, + AD9361_WHEN +}; + +struct ad9361_reg_config { + int operation; + uint16_t val1; + uint16_t val2; +}; + + + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ + +int32_t ad9361_reg_read(struct ad9361_reg_dev *dev, + uint16_t reg_addr, + uint8_t *reg_data); + +int32_t ad9361_reg_write(struct ad9361_reg_dev *dev, + uint16_t reg_addr, + uint8_t reg_data); + +int32_t ad9361_reg_init(struct ad9361_reg_dev **device, + const struct ad9361_reg_init_param *init_param); + +int32_t ad9361_reg_reset(struct ad9361_reg_dev *dev); + +int32_t ad9361_reg_remove(struct ad9361_reg_dev *dev); + +#endif diff --git a/datalink814_sp/src/adi_noos/include/axi_io.h b/datalink814_sp/src/adi_noos/include/axi_io.h new file mode 100644 index 0000000..92b689a --- /dev/null +++ b/datalink814_sp/src/adi_noos/include/axi_io.h @@ -0,0 +1,59 @@ +/***************************************************************************//** + * @file axi_io.h + * @brief Header file of AXI IO. + * @author Antoniu Miclaus (antoniu.miclaus@analog.com) +******************************************************************************** + * Copyright 2019(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#ifndef AXI_IO_H_ +#define AXI_IO_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ + +/* AXI IO Read data */ +int32_t axi_io_read(uint32_t base, uint32_t offset, uint32_t *data); + +/* AXI IO Write data */ +int32_t axi_io_write(uint32_t base, uint32_t offset, uint32_t data); + +#endif // AXI_IO_H_ diff --git a/datalink814_sp/src/adi_noos/include/delay.h b/datalink814_sp/src/adi_noos/include/delay.h new file mode 100644 index 0000000..7937a9d --- /dev/null +++ b/datalink814_sp/src/adi_noos/include/delay.h @@ -0,0 +1,59 @@ +/***************************************************************************//** + * @file delay.h + * @brief Header file of Delay functions + * @author DBogdan (dragos.bogdan@analog.com) +******************************************************************************** + * Copyright 2019(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#ifndef DELAY_H_ +#define DELAY_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ + +/* Generate microseconds delay. */ +void udelay(uint32_t usecs); + +/* Generate miliseconds delay. */ +void mdelay(uint32_t msecs); + +#endif // DELAY_H_ diff --git a/datalink814_sp/src/adi_noos/include/error.h b/datalink814_sp/src/adi_noos/include/error.h new file mode 100644 index 0000000..275b126 --- /dev/null +++ b/datalink814_sp/src/adi_noos/include/error.h @@ -0,0 +1,67 @@ +/***************************************************************************//** + * @file error.h + * @brief Error codes definition + * @author DBogdan (dragos.bogdan@analog.com) +******************************************************************************** + * Copyright 2019(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#ifndef ERROR_H_ +#define ERROR_H_ + +#include + +/******************************************************************************/ +/********************** Macros and Constants Definitions **********************/ +/******************************************************************************/ + +#ifdef SUCCESS +#undef SUCCESS +#endif +#define SUCCESS 0 +#ifdef FAILURE +#undef FAILURE +#endif +#define FAILURE -1 + +#ifndef __ELASTERROR +#define __ELASTERROR 2000 +#endif + +#define EOVERRUN (__ELASTERROR + 1) /* Circular buffer overrun */ + + +#define IS_ERR_VALUE(x) ((x) < 0) + +#endif // ERROR_H_ diff --git a/datalink814_sp/src/adi_noos/include/gpio.h b/datalink814_sp/src/adi_noos/include/gpio.h new file mode 100644 index 0000000..5c057cb --- /dev/null +++ b/datalink814_sp/src/adi_noos/include/gpio.h @@ -0,0 +1,165 @@ +/***************************************************************************//** + * @file gpio.h + * @brief Header file of GPIO Interface + * @author DBogdan (dragos.bogdan@analog.com) +******************************************************************************** + * Copyright 2019(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#ifndef GPIO_H_ +#define GPIO_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include + +/******************************************************************************/ +/********************** Macros and Constants Definitions **********************/ +/******************************************************************************/ + +#define GPIO_OUT 0x01 +#define GPIO_IN 0x00 + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ + +/** + * @struct gpio_platform_ops + * @brief Structure holding gpio function pointers that point to the platform + * specific function + */ +struct gpio_platform_ops ; + +/** + * @struct gpio_init_param + * @brief Structure holding the parameters for GPIO initialization. + */ +typedef struct gpio_init_param { + /** GPIO number */ + int32_t number; + /** GPIO platform specific functions */ + const struct gpio_platform_ops *platform_ops; + /** GPIO extra parameters (device specific) */ + void *extra; +} gpio_init_param; + +/** + * @struct gpio_desc + * @brief Structure holding the GPIO descriptor. + */ +typedef struct gpio_desc { + /** GPIO number */ + int32_t number; + /** GPIO platform specific functions */ + const struct gpio_platform_ops *platform_ops; + /** GPIO extra parameters (device specific) */ + void *extra; +} gpio_desc; + +/** + * @enum gpio_values + * @brief Enum that holds the possible output states of a GPIO. + */ +enum gpio_values { + /** GPIO logic low */ + GPIO_LOW, + /** GPIO logic high */ + GPIO_HIGH, + /** GPIO high impedance */ + GPIO_HIGH_Z +}; + +/** + * @struct gpio_platform_ops + * @brief Structure holding gpio function pointers that point to the platform + * specific function + */ +struct gpio_platform_ops { + /** gpio initialization function pointer */ + int32_t (*gpio_ops_get)(struct gpio_desc **, const struct gpio_init_param *); + /** gpio optional descriptor function pointer */ + int32_t (*gpio_ops_get_optional)(struct gpio_desc **, + const struct gpio_init_param *); + /** gpio remove function pointer */ + int32_t (*gpio_ops_remove)(struct gpio_desc *); + /** gpio direction input function pointer */ + int32_t (*gpio_ops_direction_input)(struct gpio_desc *); + /** gpio direction output function pointer */ + int32_t (*gpio_ops_direction_output)(struct gpio_desc *, uint8_t); + /** gpio get direction function pointer */ + int32_t (*gpio_ops_get_direction)(struct gpio_desc *, uint8_t *); + /** gpio set value function pointer */ + int32_t (*gpio_ops_set_value)(struct gpio_desc *, uint8_t); + /** gpio get value function pointer */ + int32_t (*gpio_ops_get_value)(struct gpio_desc *, uint8_t *); +}; + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ + +/* Obtain the GPIO decriptor. */ +int32_t gpio_get(struct gpio_desc **desc, + const struct gpio_init_param *param); + +/* Obtain optional GPIO descriptor. */ +int32_t gpio_get_optional(struct gpio_desc **desc, + const struct gpio_init_param *param); + +/* Free the resources allocated by gpio_get() */ +int32_t gpio_remove(struct gpio_desc *desc); + +/* Enable the input direction of the specified GPIO. */ +int32_t gpio_direction_input(struct gpio_desc *desc); + +/* Enable the output direction of the specified GPIO. */ +int32_t gpio_direction_output(struct gpio_desc *desc, + uint8_t value); + +/* Get the direction of the specified GPIO. */ +int32_t gpio_get_direction(struct gpio_desc *desc, + uint8_t *direction); + +/* Set the value of the specified GPIO. */ +int32_t gpio_set_value(struct gpio_desc *desc, + uint8_t value); + +/* Get the value of the specified GPIO. */ +int32_t gpio_get_value(struct gpio_desc *desc, + uint8_t *value); + +#endif // GPIO_H_ diff --git a/datalink814_sp/src/adi_noos/include/irq.h b/datalink814_sp/src/adi_noos/include/irq.h new file mode 100644 index 0000000..7db97e9 --- /dev/null +++ b/datalink814_sp/src/adi_noos/include/irq.h @@ -0,0 +1,188 @@ +/***************************************************************************//** + * @file irq.h + * @brief Header file of IRQ interface. + * @author Cristian Pop (cristian.pop@analog.com) +******************************************************************************** + * Copyright 2019(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#ifndef IRQ_H_ +#define IRQ_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ + +/** + * @enum irq_uart_event_e + * @brief Possible events for uart interrupt + */ +enum irq_uart_event_e { + /** Write operation finalized */ + IRQ_WRITE_DONE, + /** Read operation finalized */ + IRQ_READ_DONE, + /** An error occurred */ + IRQ_ERROR +}; + +enum irq_trig_level { + IRQ_LEVEL_LOW, + IRQ_LEVEL_HIGH, + IRQ_EDGE_FALLING, + IRQ_EDGE_RISING, + IRQ_EDGE_BOTH +}; + +/** + * @struct irq_platform_ops + * @brief Structure holding IRQ function pointers that point to the platform + * specific function + */ +struct irq_platform_ops ; + +/** + * @struct irq_init_param + * @brief Structure holding the initial parameters for Interrupt Request. + */ +struct irq_init_param { + /** Interrupt request controller ID. */ + uint32_t irq_ctrl_id; + /** Platform specific IRQ platform ops structure. */ + const struct irq_platform_ops *platform_ops; + /** IRQ extra parameters (device specific) */ + void *extra; +}; + +/** + * @struct irq_desc + * @brief Structure for Interrupt Request descriptor. + */ +struct irq_ctrl_desc { + /** Interrupt request controller ID. */ + uint32_t irq_ctrl_id; + /** Platform specific IRQ platform ops structure. */ + const struct irq_platform_ops *platform_ops; + /** IRQ extra parameters (device specific) */ + void *extra; +}; + +/** + * @struct callback_desc + * @brief Structure describing a callback to be registered + */ +struct callback_desc { + /** + * Callback to be called when the event an event occurs + * @param ctx - Same as \ref callback_desc.ctx + * @param event - Event that generated the callback + * @param extra - Platform specific data + */ + void (*callback)(void *ctx, uint32_t event, void *extra); + /** Parameter to be passed when the callback is called */ + void *ctx; + /** Platform specific configuration for a callback */ + void *config; +}; + +/** + * @struct irq_platform_ops + * @brief Structure holding IRQ function pointers that point to the platform + * specific function + */ +struct irq_platform_ops { + /** Initialize a interrupt controller peripheral. */ + int32_t (*init)(struct irq_ctrl_desc **desc, + const struct irq_init_param *param); + /** Register a callback to handle the irq events */ + int32_t (*register_callback)(struct irq_ctrl_desc *desc, uint32_t irq_id, + struct callback_desc *callback_desc); + /** Unregisters a generic IRQ handling function */ + int32_t (*unregister)(struct irq_ctrl_desc *desc, uint32_t irq_id); + /** Global interrupt enable */ + int32_t (*global_enable)(struct irq_ctrl_desc *desc); + /** Global interrupt disable */ + int32_t (*global_disable)(struct irq_ctrl_desc *desc); + /** Set interrupt trigger level. */ + int32_t (*trigger_level_set)(struct irq_ctrl_desc *desc, uint32_t irq_id, + enum irq_trig_level trig); + /** Enable specific interrupt */ + int32_t (*enable)(struct irq_ctrl_desc *desc, uint32_t irq_id); + /** Disable specific interrupt */ + int32_t (*disable)(struct irq_ctrl_desc *desc, uint32_t irq_id); + /** IRQ remove function pointer */ + int32_t (*remove)(struct irq_ctrl_desc *desc); +}; + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ + +/* Initialize a interrupt controller peripheral. */ +int32_t irq_ctrl_init(struct irq_ctrl_desc **desc, + const struct irq_init_param *param); + +/* Free the resources allocated by irq_ctrl_init(). */ +int32_t irq_ctrl_remove(struct irq_ctrl_desc *desc); + +/* Register a callback to handle the irq events */ +int32_t irq_register_callback(struct irq_ctrl_desc *desc, uint32_t irq_id, + struct callback_desc *callback_desc); + +/* Unregisters a generic IRQ handling function */ +int32_t irq_unregister(struct irq_ctrl_desc *desc, uint32_t irq_id); + +/* Global interrupt enable */ +int32_t irq_global_enable(struct irq_ctrl_desc *desc); + +/* Global interrupt disable */ +int32_t irq_global_disable(struct irq_ctrl_desc *desc); + +/* Set interrupt trigger level. */ +int32_t irq_trigger_level_set(struct irq_ctrl_desc *desc, uint32_t irq_id, + enum irq_trig_level trig); + +/* Enable specific interrupt */ +int32_t irq_enable(struct irq_ctrl_desc *desc, uint32_t irq_id); + +/* Disable specific interrupt */ +int32_t irq_disable(struct irq_ctrl_desc *desc, uint32_t irq_id); + +#endif // IRQ_H_ diff --git a/datalink814_sp/src/adi_noos/include/spi.h b/datalink814_sp/src/adi_noos/include/spi.h new file mode 100644 index 0000000..0e9b8e0 --- /dev/null +++ b/datalink814_sp/src/adi_noos/include/spi.h @@ -0,0 +1,194 @@ +/***************************************************************************//** + * @file spi.h + * @brief Header file of SPI Interface + * @author DBogdan (dragos.bogdan@analog.com) +******************************************************************************** + * Copyright 2019(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#ifndef SPI_H_ +#define SPI_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include + +/******************************************************************************/ +/********************** Macros and Constants Definitions **********************/ +/******************************************************************************/ + +#define SPI_CPHA 0x01 +#define SPI_CPOL 0x02 +#define SPI_3WIRE 0x04 + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ + +/** + * @enum spi_mode + * @brief SPI configuration for clock phase and polarity. + */ +typedef enum spi_mode { + /** Data on rising, shift out on falling */ + SPI_MODE_0 = (0 | 0), + /** Data on falling, shift out on rising */ + SPI_MODE_1 = (0 | SPI_CPHA), + /** Data on falling, shift out on rising */ + SPI_MODE_2 = (SPI_CPOL | 0), + /** Data on rising, shift out on falling */ + SPI_MODE_3 = (SPI_CPOL | SPI_CPHA), + /** Data on rising, shift out on falling */ + SPI_MODE_4 = SPI_3WIRE +} spi_mode; + +/** + * @enum spi_bit_order + * @brief SPI configuration for bit order (MSB/LSB). + */ +typedef enum spi_bit_order { + /** Most-significant bit (MSB) first */ + SPI_BIT_ORDER_MSB_FIRST = 0, + /** Least-significant bit (LSB) first */ + SPI_BIT_ORDER_LSB_FIRST = 1, +} spi_bit_order; + +/** + * @struct spi_msg_list + * @brief List item describing a SPI transfer + */ +struct spi_msg { + /** Buffer with data to send. If NULL, 0x00 will be sent */ + uint8_t *tx_buff; + /** Buffer where to store data. If NULL, incoming data won't be saved */ + uint8_t *rx_buff; + /** Length of buffers. Must have equal size. */ + uint32_t bytes_number; + /** If set, CS will be deasserted after the transfer */ + uint8_t cs_change; +}; + +/** + * @struct spi_platform_ops + * @brief Structure holding SPI function pointers that point to the platform + * specific function + */ +struct spi_platform_ops ; + +/** + * @struct spi_init_param + * @brief Structure holding the parameters for SPI initialization + */ +typedef struct spi_init_param { + /** Device ID */ + uint32_t device_id; + /** maximum transfer speed */ + uint32_t max_speed_hz; + /** SPI chip select */ + uint8_t chip_select; + /** SPI mode */ + enum spi_mode mode; + /** SPI bit order */ + enum spi_bit_order bit_order; + const struct spi_platform_ops *platform_ops; + /** SPI extra parameters (device specific) */ + void *extra; +} spi_init_param; + +/** + * @struct spi_desc + * @brief Structure holding SPI descriptor. + */ +typedef struct spi_desc { + /** Device ID */ + uint32_t device_id; + /** maximum transfer speed */ + uint32_t max_speed_hz; + /** SPI chip select */ + uint8_t chip_select; + /** SPI mode */ + enum spi_mode mode; + /** SPI bit order */ + enum spi_bit_order bit_order; + const struct spi_platform_ops *platform_ops; + /** SPI extra parameters (device specific) */ + void *extra; +} spi_desc; + +/** + * @struct spi_platform_ops + * @brief Structure holding SPI function pointers that point to the platform + * specific function + */ +struct spi_platform_ops { + /** SPI initialization function pointer */ + int32_t (*init)(struct spi_desc **, const struct spi_init_param *); + /** SPI write/read function pointer */ + int32_t (*write_and_read)(struct spi_desc *, uint8_t *, uint16_t); + /** SPI write function pointer */ + int32_t (*write_and_read_3wire)(struct spi_desc *, uint8_t *,uint8_t *,uint16_t, uint16_t); + /** Iterate over the spi_msg array and send all messages at once */ + int32_t (*transfer)(struct spi_desc *, struct spi_msg *, uint32_t); + /** SPI remove function pointer */ + int32_t (*remove)(struct spi_desc *); +}; + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ + +/* Initialize the SPI communication peripheral. */ +int32_t spi_init(struct spi_desc **desc, + const struct spi_init_param *param); + +/* Free the resources allocated by spi_init(). */ +int32_t spi_remove(struct spi_desc *desc); + +/* Write and read data to/from SPI. */ +int32_t spi_write_and_read(struct spi_desc *desc, + uint8_t *data, + uint16_t bytes_number); +int32_t spi_write_and_read_3wire(struct spi_desc *desc, + uint8_t *write_data, + uint8_t *read_data, + uint16_t write_bytes_number, + uint16_t read_bytes_number); + +/* Iterate over the spi_msg array and send all messages at once */ +int32_t spi_transfer(struct spi_desc *desc, struct spi_msg *msgs, uint32_t len); + + +#endif // SPI_H_ diff --git a/datalink814_sp/src/axi_dma/axi_dma.c b/datalink814_sp/src/axi_dma/axi_dma.c new file mode 100644 index 0000000..db49401 --- /dev/null +++ b/datalink814_sp/src/axi_dma/axi_dma.c @@ -0,0 +1,452 @@ +/*****************************************************************************/ +/** + * Description: A simple AXI DMA api. + * + * Author: Fan Hao + * Date: 2022-06-18 16:37 + * LastEditors: Fan Hao + * LastEditTime: 2022-06-18 17:38 + * Revisions: Rev 0.0 + * History: + * [2022-06-18]: Initial version. + * + * Copyright(c) 2022 Beijing Institute of Technology. + * Lab of Communication and Networking + * +******************************************************************************/ +/***************************** Include Files *********************************/ +#include +#include +#include "xaxidma.h" +// #include "xtime_l.h" //Adjutment for microblaze +#include "xil_cache.h" + +#include "axi_dma.h" +#include "../error.h" +#include "../common.h" + +/************************** Constant Definitions *****************************/ +/***************** Macros (Inline Functions) Definitions *********************/ +/************************** Function Prototypes ******************************/ +/**************************** Type Definitions *******************************/ +/************************** Variable Definitions *****************************/ + +/*****************************************************************************/ +/** + * @brief Initialize the DMA descriptor instance, allocate space for + * descriptor. + * + * @param instPtr a second rank pointer to DMA descriptor instance + * @param configPtr a pointer to DMA descriptor instance configuration + * set. + * + * @return SUCCESS + * ENOMEM memory allocate failed. + * other error codes + * + ******************************************************************************/ +int32_t Dma_Init(DMA_DESC** instPtr, const DMA_CONFIG* configPtr){ + ASSERT(configPtr != NULL); + int32_t Status = SUCCESS; + + *instPtr = (DMA_DESC*) malloc(sizeof(DMA_DESC)); + if ((*instPtr) == NULL) { + goto err; + } + (*instPtr)->isTxDone = false; + (*instPtr)->isRxDone = false; + (*instPtr)->isError = false; + (*instPtr)->isListening = false; + memcpy(&((*instPtr)->configs), configPtr, sizeof(DMA_CONFIG)); + + (*instPtr)->axiDmaPtr = (XAxiDma*) malloc(sizeof(XAxiDma)); + if ((*instPtr)->axiDmaPtr == NULL) { + free((*instPtr)->axiDmaPtr); + goto err; + } + + XAxiDma_Config* damConfigPtr = NULL; + damConfigPtr = XAxiDma_LookupConfig(configPtr->devId); + if (damConfigPtr == NULL) { + DBG_PRINT("No config found for %d\r\n", configPtr->devId); + goto err; + } + + /* Initialize DMA engine */ + Status = XAxiDma_CfgInitialize((*instPtr)->axiDmaPtr, damConfigPtr); + if (Status != SUCCESS) { + DBG_ERROR("DMA initialize failed. device id: %d\r\n", configPtr->devId); + goto err; + } + + if(XAxiDma_HasSg((*instPtr)->axiDmaPtr)){ + DBG_ERROR("DMA Device configured as SG mode \r\n"); + goto err; + } + + /* Clear all interrupts before setup */ + XAxiDma_IntrAckIrq((*instPtr)->axiDmaPtr, XAXIDMA_IRQ_ALL_MASK, + XAXIDMA_DMA_TO_DEVICE); + XAxiDma_IntrAckIrq((*instPtr)->axiDmaPtr, XAXIDMA_IRQ_ALL_MASK, + XAXIDMA_DEVICE_TO_DMA); + + /* Disable all interrupts before setup */ + XAxiDma_IntrDisable((*instPtr)->axiDmaPtr, XAXIDMA_IRQ_ALL_MASK, + XAXIDMA_DMA_TO_DEVICE); + XAxiDma_IntrDisable((*instPtr)->axiDmaPtr, XAXIDMA_IRQ_ALL_MASK, + XAXIDMA_DEVICE_TO_DMA); + + (*instPtr)->isInitialized = true; + + return SUCCESS; +err: + free(*instPtr); + return Status; +} + + +/*****************************************************************************/ +/** + * @brief Enable DMA IRQs. + * + * @param instPtr a pointer to DMA descriptor instance. + * + * @return SUCCESS + * EDINVAL device not initialized. + * + ******************************************************************************/ +int32_t Dma_IrqEnable(DMA_DESC* instPtr){ + if(instPtr == NULL || instPtr->isInitialized == false){ + return EDINVAL; + } + /* Enable all interrupts */ + XAxiDma_IntrEnable(instPtr->axiDmaPtr, XAXIDMA_IRQ_ALL_MASK, XAXIDMA_DMA_TO_DEVICE); + XAxiDma_IntrEnable(instPtr->axiDmaPtr, XAXIDMA_IRQ_ALL_MASK, XAXIDMA_DEVICE_TO_DMA); + return SUCCESS; +} + + +/*****************************************************************************/ +/** + * @brief Enable DMA listening feature and start a receive procedure. + * + * @param instPtr a pointer to DMA descriptor instance. + * @param dataBuff a pointer to data buffer. + * + * @return SUCCESS + * EDINVAL device not initialized. + * + ******************************************************************************/ +int32_t Dma_ListenEnable(DMA_DESC* instPtr, uint8_t* dataBuff){ + if(instPtr == NULL || instPtr->isInitialized == false || dataBuff == NULL){ + return EDINVAL; + } + instPtr->isListening = true; + instPtr->listenBuff = dataBuff; + // if(XAxiDma_Busy(instPtr->axiDmaPtr, XAXIDMA_DEVICE_TO_DMA) == false){ + return XAxiDma_SimpleTransfer(instPtr->axiDmaPtr,(uintptr_t)instPtr->listenBuff, + instPtr->configs.defaultTransLen, XAXIDMA_DEVICE_TO_DMA); + // } + // else{ + // return SUCCESS; + // } +} + +/*****************************************************************************/ +/** + * @brief Disable DMA listening feature and start a receive procedure. + * + * @param instPtr a pointer to DMA descriptor instance. + * + * @return SUCCESS + * EDINVAL device not initialized. + * + ******************************************************************************/ +int32_t Dma_ListenDisable(DMA_DESC* instPtr){ + if(instPtr == NULL || instPtr->isInitialized == false){ + return EDINVAL; + } + instPtr->isListening = false; + instPtr->listenBuff = NULL; + if(XAxiDma_Busy(instPtr->axiDmaPtr, XAXIDMA_DEVICE_TO_DMA) == true){ + DBG_WARNING("an unfinished transfer is on going.\r\n"); + } + return SUCCESS; +} + +/*****************************************************************************/ +/** + * @brief Transfer a specific length of data (DMA->Device), none-blocking + * transfer. + * + * @param instPtr a pointer to DMA descriptor instance. + * @param dataBuff a pointer to data buffer. + * @param dataLen length of data need to be transfer. + * + * @return SUCCESS + * EDINVAL device not initialized. + * + ******************************************************************************/ +int32_t Dma_SendData(DMA_DESC* instPtr, uint8_t* dataBuff, int32_t dataLen){ + int32_t Status; + if(dataLen > instPtr->configs.transMax){ + return FAILURE; + } + + // Flush the SrcBuffer before the DMA transfer + // Xil_DCacheFlushRange((uintptr_t)dataBuff, dataLen); + + // Set txDone flage to false, before transmission + instPtr->isTxDone = false; + // Assert a send trigger + Status = XAxiDma_SimpleTransfer(instPtr->axiDmaPtr, (uintptr_t)dataBuff, + dataLen, XAXIDMA_DMA_TO_DEVICE); + if (Status != SUCCESS) { + return FAILURE; + } + return SUCCESS; +} + + +/*****************************************************************************/ +/** + * @brief Transfer a specific length of data (DMA->Device), blocking transfer. + * + * @param instPtr a pointer to DMA descriptor instance. + * @param dataBuff a pointer to data buffer. + * @param dataLen length of data need to be transfer. + * + * @return SUCCESS + * ETIMEOUT transfer timeout. + * other error codes. + * + ******************************************************************************/ +int32_t Dma_BlockingSendData(DMA_DESC* instPtr, uint8_t* dataBuff, int32_t dataLen){ + int32_t Status; + if(dataLen > instPtr->configs.transMax){ + return EINVAL; + } + + Status = Dma_SendData(instPtr, dataBuff, dataLen); + if(Status == SUCCESS){ + DBG_ERROR("Failed to setup a DMA transfer (DMA->Device).\r\n"); + return Status; + } + //Adjutment for microblaze +// XTime tCur = 0; +// XTime tTimeOut = 0; +// XTime_GetTime(&tCur); +// tTimeOut = tCur + instPtr->configs.timeoutTh; + + while(instPtr->isTxDone == false && instPtr->isError == false){ + //Adjutment for microblaze +// XTime_GetTime(&tCur); +// if(tCur >= tTimeOut){ +// return ETIMEOUT; +// } + } + if(instPtr->isError == true){ + return FAILURE; + } + // Set txDone flage to false, after transmission + instPtr->isTxDone = false; + return SUCCESS; +} + + +/*****************************************************************************/ +/** + * @brief Transfer a specific length of data (Device->DMA), none-blocking + * transfer. + * + * @param instPtr a pointer to DMA descriptor instance. + * @param dataBuff a pointer to data buffer. + * @param dataLen length of data need to be transfer. + * + * @return SUCCESS + * EDINVAL device not initialized. + * + ******************************************************************************/ +int32_t Dma_RecvData(DMA_DESC* instPtr, uint8_t* dataBuff, int32_t dataLen){ + int32_t Status; + if(dataLen > instPtr->configs.transMax){ + return FAILURE; + } + + // Set txDone flage to false, before transmission + instPtr->isRxDone = false; + // Assert a send trigger + Status = XAxiDma_SimpleTransfer(instPtr->axiDmaPtr,(uintptr_t)dataBuff, + dataLen, XAXIDMA_DEVICE_TO_DMA); + if (Status != SUCCESS) { + return FAILURE; + } + return SUCCESS; +} + +/*****************************************************************************/ +/** + * @brief Transfer a specific length of data (Device->DMA), blocking transfer. + * + * @param instPtr a pointer to DMA descriptor instance. + * @param dataBuff a pointer to data buffer. + * @param dataLen length of data need to be transfer. + * + * @return SUCCESS + * EDINVAL device not initialized. + * + ******************************************************************************/ +int32_t Dma_BlockingRecvData(DMA_DESC* instPtr, uint8_t* dataBuff, int32_t dataLen){ + int32_t Status; + if(dataLen > instPtr->configs.transMax){ + return FAILURE; + } + + Status = Dma_RecvData(instPtr, dataBuff, dataLen); + if(Status == SUCCESS){ + DBG_ERROR("Failed to setup a DMA transfer (Device->DMA).\r\n"); + return Status; + } + + //Adjutment for microblaze +// XTime tCur = 0; +// XTime tTimeOut = 0; +// XTime_GetTime(&tCur); +// tTimeOut = tCur + instPtr->configs.timeoutTh; + + while(instPtr->isTxDone == false && instPtr->isError == false){ + //Adjutment for microblaze +// XTime_GetTime(&tCur); +// if(tCur >= tTimeOut){ +// return ETIMEOUT; +// } + } + if(instPtr->isError == true){ + return FAILURE; + } + // Set txDone flage to false, after transmission + instPtr->isTxDone = false; + return SUCCESS; +} + + +/*****************************************************************************/ +/** + * @brief Handler for DMA->Device transfer. + * + * @param instPtr a pointer to DMA descriptor instance. + * + * @return SUCCESS + * error codes + * + ******************************************************************************/ +int32_t Dma_SendIrqHandler(DMA_DESC* instPtr){ + if(instPtr == NULL || instPtr->isInitialized == false){ + return FAILURE; + } + int32_t Status = SUCCESS; + uint32_t IrqStatus = 0; + /* Read pending interrupts */ + IrqStatus = XAxiDma_IntrGetIrq(instPtr->axiDmaPtr, XAXIDMA_DMA_TO_DEVICE); + + /* Acknowledge pending interrupts */ + XAxiDma_IntrAckIrq(instPtr->axiDmaPtr, IrqStatus, XAXIDMA_DMA_TO_DEVICE); + + /* If no interrupt is asserted, we do not do anything */ + if (!(IrqStatus & XAXIDMA_IRQ_ALL_MASK)) { + return EIGNORE; + } + + /* If error interrupt is asserted, raise error flag, reset the + * hardware to recover from the error, and return with no further + * processing. + */ + if ((IrqStatus & XAXIDMA_IRQ_ERROR_MASK)) { + + instPtr->isError = true; + + /* Reset should never fail for transmit channel */ + XAxiDma_Reset(instPtr->axiDmaPtr); + while (XAxiDma_ResetIsDone(instPtr->axiDmaPtr) == false) { + // FIXME: Add time out check + } + return EUNEXP; + } + + /* If Completion interrupt is asserted, then set the TxDone flag */ + if ((IrqStatus & XAXIDMA_IRQ_IOC_MASK)) { + instPtr->isTxDone = true; + } + return Status; +} + + +/*****************************************************************************/ +/** + * @brief Handler for Device->DMA transfer. + * + * @param instPtr a pointer to DMA descriptor instance. + * + * @return SUCCESS + * error codes + * + ******************************************************************************/ +int32_t Dma_RecvIrqHandler(DMA_DESC* instPtr){ + if(instPtr == NULL || instPtr->isInitialized == false){ + return FAILURE; + } + int32_t Status = SUCCESS; + uint32_t IrqStatus = 0; + + /* Read pending interrupts */ + IrqStatus = XAxiDma_IntrGetIrq(instPtr->axiDmaPtr, XAXIDMA_DEVICE_TO_DMA); + + /* Acknowledge pending interrupts */ + XAxiDma_IntrAckIrq(instPtr->axiDmaPtr, IrqStatus, XAXIDMA_DEVICE_TO_DMA); + + /* If no interrupt is asserted, we do not do anything */ + if (!(IrqStatus & XAXIDMA_IRQ_ALL_MASK)) { + return EIGNORE; + } + + /* If error interrupt is asserted, raise error flag, reset the + * hardware to recover from the error, and return with no further + * processing. + */ + if ((IrqStatus & XAXIDMA_IRQ_ERROR_MASK)) { + + instPtr->isError = true; + + /* Reset should never fail for transmit channel */ + XAxiDma_Reset(instPtr->axiDmaPtr); + while (XAxiDma_ResetIsDone(instPtr->axiDmaPtr)) { + // FIXME: Add time out check + } + return EUNEXP; + } + + /* If completion interrupt is asserted, then set RxDone flag */ + if ((IrqStatus & XAXIDMA_IRQ_IOC_MASK)) { + // // Invalid the DestBuffer after the DMA transfer + // int RingIndex = 0; + // uintptr_t dstAddr; + // uint32_t transLen; + // dstAddr = XAxiDma_ReadReg(instPtr->axiDmaPtr->RxBdRing[RingIndex].ChanBase, XAXIDMA_DESTADDR_OFFSET); + // if (instPtr->axiDmaPtr->AddrWidth > 32){ + // dstAddr |= ((uintptr_t)(XAxiDma_ReadReg(instPtr->axiDmaPtr->RxBdRing[RingIndex].ChanBase, + // XAXIDMA_DESTADDR_MSB_OFFSET))<<32); + // } + // transLen = XAxiDma_ReadReg(InstancePtr->RxBdRing[RingIndex].ChanBase, XAXIDMA_BUFFLEN_OFFSET) + // Xil_DCacheInvalidateRange(dstAddr, transLen); + instPtr->isRxDone = true; + } + if(instPtr->isListening == true){ + // Continuous receiving + Status = XAxiDma_SimpleTransfer(instPtr->axiDmaPtr,(uintptr_t)instPtr->listenBuff, + instPtr->configs.defaultTransLen, XAXIDMA_DEVICE_TO_DMA); + if(Status != SUCCESS){ + DBG_ERROR("Failed to start a new SimpleTransfer in XAXIDMA_DEVICE_TO_DMA channel.\r\n"); + } + } + return Status; +} diff --git a/datalink814_sp/src/axi_dma/axi_dma.h b/datalink814_sp/src/axi_dma/axi_dma.h new file mode 100644 index 0000000..2b1a7f1 --- /dev/null +++ b/datalink814_sp/src/axi_dma/axi_dma.h @@ -0,0 +1,62 @@ +/*****************************************************************************/ +/** + * Description: A simple AXI DMA api. + * prototypes. + * + * Author: Fan Hao + * Date: 2022-06-18 16:37 + * LastEditors: Fan Hao + * LastEditTime: 2022-06-18 17:40 + * Revisions: Rev 0.0 + * History: + * [2022-06-18]: Initial version. + * + * Copyright(c) 2022 Beijing Institute of Technology. + * Lab of Communication and Networking + * +******************************************************************************/ + +#ifndef AXI_DMA_H_ +#define AXI_DMA_H_ + + +/***************************** Include Files *********************************/ +#include +#include +#include "xaxidma.h" + +/************************** Constant Definitions *****************************/ +/***************** Macros (Inline Functions) Definitions *********************/ +/**************************** Type Definitions *******************************/ +typedef struct{ + uint32_t devId; + uint32_t transMax; + uint32_t defaultTransLen; + uint32_t timeoutTh; +}DMA_CONFIG; + +typedef struct{ + bool isTxDone; + bool isRxDone; + bool isError; + bool isListening; + bool isInitialized; + uint8_t* listenBuff; + XAxiDma* axiDmaPtr; + DMA_CONFIG configs; +}DMA_DESC; + +/************************** Variable Definitions *****************************/ + +/************************** Function Prototypes ******************************/ +int32_t Dma_Init(DMA_DESC** instPtr, const DMA_CONFIG* configPtr); +int32_t Dma_IrqEnable(DMA_DESC* instPtr); +int32_t Dma_ListenEnable(DMA_DESC* instPtr, uint8_t* dataBuff); +int32_t Dma_ListenDisable(DMA_DESC* instPtr); +int32_t Dma_SendData(DMA_DESC* instPtr, uint8_t* dataBuff, int32_t dataLen); +int32_t Dma_BlockingSendData(DMA_DESC* instPtr, uint8_t* dataBuff, int32_t dataLen); +int32_t Dma_RecvData(DMA_DESC* instPtr, uint8_t* dataBuff, int32_t dataLen); +int32_t Dma_BlockingRecvData(DMA_DESC* instPtr, uint8_t* dataBuff, int32_t dataLen); +int32_t Dma_SendIrqHandler(DMA_DESC* instPtr); +int32_t Dma_RecvIrqHandler(DMA_DESC* instPtr); +#endif //AXI_DMA_H_ diff --git a/datalink814_sp/src/c2c_bridge/c2c_bridge.c b/datalink814_sp/src/c2c_bridge/c2c_bridge.c new file mode 100644 index 0000000..172316a --- /dev/null +++ b/datalink814_sp/src/c2c_bridge/c2c_bridge.c @@ -0,0 +1,211 @@ +/*****************************************************************************/ +/** + * Description: Implementations of chip to chip data bridge. + * + * Author: Fan Hao + * Date: 2022-09-02 15:01 + * LastEditors: Fan Hao + * LastEditTime: 2022-09-02 15:49 + * Revisions: Rev 0.0 + * History: + * [2022-09-02]: Initial version + * + * Note: + * Branch from Analog Devices version (by DBogdan dragos.bogdan@analog.com). + * + * Copyright(c) 2022 Beijing Institute of Technology. + * Lab of Communication and Networking + * +******************************************************************************/ + +/***************************** Include Files **********************************/ +#include +#include +#include +#include + +#include "c2c_bridge.h" +#include "xgpio.h" +#include "../axi_dma/axi_dma.h" +#include "../util/util.h" +#include "../error.h" +#include "../common.h" + +/************************** Constant Definitions *****************************/ +// C2C Configs +#define C2C_GPIO_OUT_CH 1 +#define C2C_SEND_TRIGGER BIT(0) +#define C2C_RECV_TRIGGER BIT(1) + +/************************** Variable Definitions *****************************/ +C2C_DESC* c2cInstPtr = NULL; + +/************************** Function Prototypes ******************************/ + +inline bool C2c_IsSendBusy(C2C_DESC* instPtr){ + ASSERT(instPtr != NULL); + return (instPtr->txDone == false); +} + +inline bool C2c_IsRecvBusy(C2C_DESC* instPtr){ + ASSERT(instPtr != NULL); + return (instPtr->rxDone == false); +} + +/*****************************************************************************/ +/** + * @brief Initialize c2c bridge descriptor instance. + * + * @param instPtr second rank pointer to c2c instance. + * @param configPtr pointer to c2c instance configuration struct. + * + * @return NONE + * + ******************************************************************************/ +int32_t C2c_Init(C2C_DESC** instPtr, C2C_CONFIG* configPtr){ + ASSERT(configPtr != NULL); + int32_t Status; + (*instPtr) = (C2C_DESC*)malloc(sizeof(C2C_DESC)); + if((*instPtr) == NULL){ + return EALLOC; + } + memcpy(&(*instPtr)->c2cCofig, configPtr, sizeof(C2C_CONFIG)); + Status = Dma_Init(&((*instPtr)->axiDmaInst), &(*instPtr)->c2cCofig.dmaConfig); + if(Status != SUCCESS){ + DBG_ERROR("C2C axi DMA init failed, with error code: %d.\r\n", Status); + return Status; + } + (*instPtr)->isInit = true; + (*instPtr)->txDone = true; + (*instPtr)->rxDone = true; + (*instPtr)->lastRxBuff = (uintptr_t)NULL; + (*instPtr)->lastRxBuffSize = 0; + return SUCCESS; +} + +int32_t C2c_IrqEnable(C2C_DESC* instPtr){ + if(instPtr==NULL || instPtr->isInit == false){ + return FAILURE; + } + /* Enable all interrupts */ + return Dma_IrqEnable(instPtr->axiDmaInst); +} + +/*****************************************************************************/ +/** + * @brief Send data through c2c bridge. + * + * @param instPtr second rank pointer to c2c instance. + * @param buff data buffer stores the data needs to be sent + * @param dLen data length needs to be sent + * + * @return NONE + * + ******************************************************************************/ +int32_t C2c_SendData(C2C_DESC* instPtr, uint8_t* buff, uint32_t dLen){ + ASSERT(instPtr != NULL); + ASSERT(buff != NULL); + if(instPtr->isInit == false){ + return EDINVAL; + } + if(dLen > instPtr->c2cCofig.capacity){ + return EPARAM; + } + IO_Out32((uintptr_t)(buff + C2C_HEAD_OFFSET), C2C_HEADER); + IO_Out32((uintptr_t)(buff + C2C_DLEN_OFFSET), dLen + C2C_HEADER_LEN); + instPtr->txDone = false; + instPtr->lastTxBuff = (uintptr_t)buff; + instPtr->lastTxBuffSize = dLen; + if (SUCCESS == Dma_SendData(instPtr->axiDmaInst, buff, dLen + C2C_HEADER_LEN)){ + return SUCCESS; + } + else{ + return FAILURE; + } + return SUCCESS; +} + +int32_t C2c_BlockingSendData(C2C_DESC* instPtr, uint8_t* buff, uint32_t dLen) { + ASSERT(instPtr != NULL); + ASSERT(buff != NULL); + if(instPtr->isInit == false){ + return EDINVAL; + } + if(dLen > instPtr->c2cCofig.capacity){ + return EPARAM; + } + IO_Out32((uintptr_t)(buff + C2C_HEAD_OFFSET), C2C_HEADER); + IO_Out32((uintptr_t)(buff + C2C_DLEN_OFFSET), dLen + C2C_HEADER_LEN); + instPtr->txDone = false; + instPtr->lastTxBuff = (uintptr_t)buff; + instPtr->lastTxBuffSize = dLen; + if (SUCCESS == Dma_BlockingSendData(instPtr->axiDmaInst, buff, dLen + C2C_HEADER_LEN)){ + return SUCCESS; + } + else{ + return FAILURE; + } +} + +/*****************************************************************************/ +/** + * @brief Receive data from c2c bridge. + * + * @param instPtr second rank pointer to c2c instance. + * @param buff data buffer stores the received data. + * @param dLen data length that received + * + * @return NONE + * + ******************************************************************************/ +int32_t C2c_RecvData(C2C_DESC* instPtr, uint8_t* buff, uint32_t buffSize){ + ASSERT(instPtr != NULL); + ASSERT(buff != NULL); + if(instPtr->isInit == false){ + return EDINVAL; + } + instPtr->rxDone = false; + instPtr->lastRxBuff = (uintptr_t)buff; + instPtr->lastRxBuffSize = buffSize; + if (SUCCESS == Dma_RecvData(instPtr->axiDmaInst, buff, buffSize)){ + return SUCCESS; + } + else{ + return FAILURE; + } +} + +int32_t C2c_SendIrqHandler(C2C_DESC* instPtr){ + ASSERT(instPtr != NULL); + if(instPtr->isInit == false){ + return EDINVAL; + } + instPtr->txDone = true; + if (SUCCESS == Dma_SendIrqHandler(instPtr->axiDmaInst)){ + return SUCCESS; + } + else{ + return EUNEXP; + } +} + +int32_t C2c_RecvIrqHandler(C2C_DESC* instPtr){ + ASSERT(instPtr != NULL); + if(instPtr->isInit == false){ + return EDINVAL; + } + instPtr->rxDone = true; + if (SUCCESS == Dma_RecvIrqHandler(instPtr->axiDmaInst)){ + return SUCCESS; + } + else{ + return EUNEXP; + } + if(IO_In32(instPtr->lastRxBuff + C2C_HEAD_OFFSET) != C2C_HEADER){ + return EIGNORE; + } + if(IO_In32(instPtr->lastRxBuff + C2C_DLEN_OFFSET) > instPtr->lastRxBuffSize){ + return EIGNORE; + } + return SUCCESS; +} diff --git a/datalink814_sp/src/c2c_bridge/c2c_bridge.h b/datalink814_sp/src/c2c_bridge/c2c_bridge.h new file mode 100644 index 0000000..4cbebbf --- /dev/null +++ b/datalink814_sp/src/c2c_bridge/c2c_bridge.h @@ -0,0 +1,62 @@ +/*****************************************************************************/ +/** + * Description: Chip to chip data bridge. + * + * Author: Fan Hao + * Date: 2022-09-02 15:01 + * LastEditors: Fan Hao + * LastEditTime: 2022-09-02 15:49 + * Revisions: Rev 0.0 + * History: + * [2022-09-02]: Initial version + * [2023-02-23]: DMA version + * + * Note: + * Branch from Analog Devices version (by DBogdan dragos.bogdan@analog.com). + * + * Copyright(c) 2022 Beijing Institute of Technology. + * Lab of Communication and Networking + * +******************************************************************************/ +#include +#include +#include "../axi_dma/axi_dma.h" + +/************************** Constant Definitions *****************************/ +#define C2C_HEADER_LEN 8 //bytes +#define C2C_HEADER 0x7E7E7E7E +#define C2C_HEAD_OFFSET 0 +#define C2C_DLEN_OFFSET 4 +#define C2C_PLOAD_OFFSET 8 +#define C2C_BUFF_MAX 1024 +/**************************** Type Definitions *******************************/ +typedef struct { + uint32_t capacity; + DMA_CONFIG dmaConfig; +} C2C_CONFIG; + +typedef struct { + C2C_CONFIG c2cCofig; + DMA_DESC* axiDmaInst; + bool isInit; + bool txDone; + bool rxDone; + uintptr_t lastTxBuff; + uint32_t lastTxBuffSize; + uintptr_t lastRxBuff; + uint32_t lastRxBuffSize; +} C2C_DESC; + +/************************** Variable Definitions *****************************/ +extern C2C_DESC* c2cInstPtr; + +/************************** Function Prototypes ******************************/ +int32_t C2c_Init(C2C_DESC** instPtr, C2C_CONFIG* configPtr); +int32_t C2c_IrqEnable(C2C_DESC* instPtr); +int32_t C2c_SendData(C2C_DESC* instPtr, uint8_t* buff, uint32_t dLen); +int32_t C2c_RecvData(C2C_DESC* instPtr, uint8_t* buff, uint32_t buffSize); +int32_t C2c_BlockingSendData(C2C_DESC* instPtr, uint8_t* buff, uint32_t dLen); +bool C2c_IsSendBusy(C2C_DESC* instPtr); +bool C2c_IsRecvBusy(C2C_DESC* instPtr); +int32_t C2c_SendIrqHandler(C2C_DESC* instPtr); +int32_t C2c_RecvIrqHandler(C2C_DESC* instPtr); diff --git a/datalink814_sp/src/circ_queue/circ_queue.c b/datalink814_sp/src/circ_queue/circ_queue.c new file mode 100644 index 0000000..ee1db75 --- /dev/null +++ b/datalink814_sp/src/circ_queue/circ_queue.c @@ -0,0 +1,158 @@ +/*****************************************************************************/ +/** + * Description: A simple circular FIFO bounded queue + * + * Author: Fan Hao + * Date: 2023-02-23 10:29 + * LastEditors: Fan Hao + * LastEditTime: 2023-02-23 13:18 + * Revisions: Rev 0.0 + * History: + * [2023-02-23]: Initial Version. + * + * Copyright(c) 2023 Beijing Institute of Technology. + * Lab of Communication and Networking + * NOTE: Forked from https://github.com/chrismerck/rpa_queue.git + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +******************************************************************************/ + +#include "circ_queue.h" +#include +#include +#include +#include + +// uncomment to print debug messages +//#define QUEUE_DEBUG + +struct CIRC_QUEUE_S { + void **data; + volatile uint32_t nelts; /**< # elements */ + uint32_t in; /**< next empty location */ + uint32_t out; /**< next filled location */ + uint32_t bounds;/**< max size of queue */ + uint32_t full_waiters; + uint32_t empty_waiters; + pthread_mutex_t *one_big_mutex; + pthread_cond_t *not_empty; + pthread_cond_t *not_full; +}; + +#ifdef QUEUE_DEBUG +static void Q_DBG(const char*msg, CIRC_QUEUE *q) { + printf("#%d in %d out %d\t%s\n", + q->nelts, q->in, q->out, + msg + ); +} +#else +#define Q_DBG(x,y) +#endif + +void CircQueueFree(CIRC_QUEUE * queue) +{ + assert(queue != NULL); + if (queue->data) free(queue->data); + free(queue); +} + +/** + * Initialize the CIRC_QUEUE. + */ +bool CircQueueCreate(CIRC_QUEUE **q, uint32_t queueCapacity) +{ + assert(q != NULL); + CIRC_QUEUE *queue; + queue = malloc(sizeof(CIRC_QUEUE)); + if (!queue) { + return false; + } + *q = queue; + memset(queue, 0, sizeof(CIRC_QUEUE)); + + /* Set all the data in the queue to NULL */ + queue->data = malloc(queueCapacity * sizeof(void*)); + if(queue->data == NULL){ + goto error; + } + queue->bounds = queueCapacity; + queue->nelts = 0; + queue->in = 0; + queue->out = 0; + return true; +error: + free(queue); + return false; +} + +inline bool isCircQueueFull(CIRC_QUEUE *queue){ + assert(queue != NULL); + return ((queue)->nelts == (queue)->bounds); +} + +inline bool isCircQueueEmpty(CIRC_QUEUE *queue){ + assert(queue != NULL); + return ((queue)->nelts == 0); +} + +/** + * Push new data onto the queue. + */ +bool CircQueuePush(CIRC_QUEUE *queue, void *data) +{ + assert(queue != NULL); + + if (isCircQueueFull(queue)) { + return false; + } + + queue->data[queue->in] = data; + queue->in++; + if (queue->in >= queue->bounds) { + queue->in -= queue->bounds; + } + queue->nelts++; + + return true; +} + +/** + * Return current number of element in queue. + */ +inline uint32_t CircQueueSize(CIRC_QUEUE *queue) { + return queue->nelts; +} + +/** + * Retrieves the next item from the queue. + */ +bool CircQueuePop(CIRC_QUEUE *queue, void **data) +{ + assert(queue != NULL); + + if (isCircQueueEmpty(queue)) { + return false; + } + + *data = queue->data[queue->out]; + queue->nelts--; + + queue->out++; + if (queue->out >= queue->bounds) { + queue->out -= queue->bounds; + } + return true; +} diff --git a/datalink814_sp/src/circ_queue/circ_queue.h b/datalink814_sp/src/circ_queue/circ_queue.h new file mode 100644 index 0000000..8f20bb9 --- /dev/null +++ b/datalink814_sp/src/circ_queue/circ_queue.h @@ -0,0 +1,103 @@ +/*****************************************************************************/ +/** + * Description: A simple circular FIFO bounded queue + * + * Author: Fan Hao + * Date: 2023-02-23 10:29 + * LastEditors: Fan Hao + * LastEditTime: 2023-02-23 12:53 + * Revisions: Rev 0.0 + * History: + * [2023-02-23]: Initial Version. + * + * Copyright(c) 2023 Beijing Institute of Technology. + * Lab of Communication and Networking + * NOTE: Forked from https://github.com/chrismerck/rpa_queue.git + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +******************************************************************************/ + +#ifndef CIRC_QUEUE_H +#define CIRC_QUEUE_H + +#include +#include +#include + + +/** + * opaque structure + */ +typedef struct CIRC_QUEUE_S CIRC_QUEUE; + +/** + * create a FIFO queue + * @param queue The new queue + * @param queue_capacity maximum size of the queue + * @param a pool to allocate queue from + */ +bool CircQueueCreate(CIRC_QUEUE **queue, uint32_t queue_capacity); + +/** free queue memory -- call after destroy + * @note we do not free in destroy() to follow pthreads convention +*/ +void CircQueueFree(CIRC_QUEUE * queue); + +/** + * Detects when the CIRC_QUEUE is full. This utility function is expected + * to be called from within critical sections, and is not threadsafe. + */ +bool isCircQueueFull(CIRC_QUEUE *queue); + +/** + * Detects when the CIRC_QUEUE is empty. This utility function is expected + * to be called from within critical sections, and is not threadsafe. + */ +bool isCircQueueEmpty(CIRC_QUEUE *queue); + +/** + * push/add an object to the queue, blocking if the queue is already full + * + * @param queue the queue + * @param data the data + * @returns RPA_EINTR the blocking was interrupted (try again) + * @returns RPA_EOF the queue has been terminated + * @returns RPA_SUCCESS on a successful push + */ +bool CircQueuePush(CIRC_QUEUE *queue, void *data); + + +/** + * pop/get an object from the queue, blocking if the queue is already empty + * + * @param queue the queue + * @param data the data + * @returns RPA_EINTR the blocking was interrupted (try again) + * @returns RPA_EOF if the queue has been terminated + * @returns RPA_SUCCESS on a successful pop + */ +bool CircQueuePop(CIRC_QUEUE *queue, void **data); + +/** + * returns the size of the queue. + * + * @warning this is not threadsafe, and is intended for reporting/monitoring + * of the queue. + * @param queue the queue + * @returns the size of the queue + */ +uint32_t CircQueueSize(CIRC_QUEUE *queue); + +#endif /* CIRC_QUEUE_H */ diff --git a/datalink814_sp/src/common.c b/datalink814_sp/src/common.c new file mode 120000 index 0000000..dee4a89 --- /dev/null +++ b/datalink814_sp/src/common.c @@ -0,0 +1 @@ +../../datalink814_ge/src/common.c \ No newline at end of file diff --git a/datalink814_sp/src/common.h b/datalink814_sp/src/common.h new file mode 120000 index 0000000..1dc33b0 --- /dev/null +++ b/datalink814_sp/src/common.h @@ -0,0 +1 @@ +../../datalink814_ge/src/common.h \ No newline at end of file diff --git a/datalink814_sp/src/config/app_config.h b/datalink814_sp/src/config/app_config.h new file mode 100644 index 0000000..87a25b0 --- /dev/null +++ b/datalink814_sp/src/config/app_config.h @@ -0,0 +1,151 @@ +/*****************************************************************************/ +/** + * Description: Global configurations. + * + * Date: 2021-04-28 13:19 + * Last Edit Time: 2022-05-23 20:32 + * + * Revisions: Rev 0.0 + * History: + * [2021-04-28]: Initial edition. + * + * Copyright(c) 2021 Beijing Institute of Technology. + * Lab of Communication and Networking + * + ******************************************************************************/ + +#ifndef CONFIG_H_ +#define CONFIG_H_ + +#define XILINX_PLATFORM + +#include "xparameters.h" +#include "../util/util.h" + +/*********** Indoor Test Mode ************/ + +/************ Hardware Configs ************/ +#define CPU_CLK_HZ XPAR_MICROBLAZE_CORE_CLOCK_FREQ_HZ +#define FCLK_CLK0_HZ XPAR_MICROBLAZE_CORE_CLOCK_FREQ_HZ + +/********* Zynq Platform Configs **********/ + +// Check crc validation by computing crc value and comparing. +#define CRC_COMPARE + + +//Hardware Parameter +#define SPI_INTERFACE_SPI_ENGINE + +#define HAVE_SPLIT_GAIN_TABLE 1 /* only set to 0 in case split_gain_table_mode_enable = 0*/ +#define HAVE_TDD_SYNTH_TABLE 1 /* only set to 0 in case split_gain_table_mode_enable = 0*/ + +#define AD9361_DEVICE 1 /* set it 1 if AD9361 device is used, 0 otherwise */ +#define AD9364_DEVICE 0 /* set it 1 if AD9364 device is used, 0 otherwise */ +#define AD9363A_DEVICE 0 /* set it 1 if AD9363A device is used, 0 otherwise */ + +#define HAVE_VERBOSE_MESSAGES /* Recommended during development prints errors and warnings */ +//#define HAVE_DEBUG_MESSAGES /* For Debug purposes only */ + +#define GPIO_DEVICE_ID XPAR_AXI_GPIO_DEVICE_ID +#define GPIO_OFFSET 54 +#define GPIO_INPUT 0 +#define GPIO_OUTPUT 1 +#define GPIO_DISABLE 0 +#define GPIO_ENABLE 1 + +#define AD9516_POWEDOWN_B 0 +#define AD9516_RESET_B 1 +#define AD9516_SYNC_B 2 +#define AD9361_1_TXNRX 3 +#define AD9361_1_ENABLE 4 +#define AD9361_1_EN_AGC 5 +#define AD9361_1_RESET_B 6 +#define AD9361_1_CTRL_IN_0 7 +#define AD9361_1_CTRL_IN_1 8 +#define AD9361_1_CTRL_IN_2 9 +#define AD9361_1_CTRL_IN_3 10 +#define AD9361_2_TXNRX 11 +#define AD9361_2_ENABLE 12 +#define AD9361_2_EN_AGC 13 +#define AD9361_2_RESET_B 14 +#define AD9361_2_CTRL_IN_0 15 +#define AD9361_2_CTRL_IN_1 16 +#define AD9361_2_CTRL_IN_2 17 +#define AD9361_2_CTRL_IN_3 18 +#define AD9361_SYNC 19 +#define AD9361_RX_FIFO_RST 20 + +#define AD9361_1_CTRL_OUT_0 0 +#define AD9361_1_CTRL_OUT_1 1 +#define AD9361_1_CTRL_OUT_2 2 +#define AD9361_1_CTRL_OUT_3 3 +#define AD9361_1_CTRL_OUT_4 4 +#define AD9361_1_CTRL_OUT_5 5 +#define AD9361_1_CTRL_OUT_6 6 +#define AD9361_1_CTRL_OUT_7 7 +#define AD9361_2_CTRL_OUT_0 8 +#define AD9361_2_CTRL_OUT_1 9 +#define AD9361_2_CTRL_OUT_2 10 +#define AD9361_2_CTRL_OUT_3 11 +#define AD9361_2_CTRL_OUT_4 12 +#define AD9361_2_CTRL_OUT_5 13 +#define AD9361_2_CTRL_OUT_6 14 +#define AD9361_2_CTRL_OUT_7 15 +#define AD9516_REFMON 16 +#define AD9516_LOCKDETECT 17 +#define AD9516_STARUS 18 + +#define GPIO_BANK_OUT 1 +#define GPIO_BANK_IN 2 + +#define SPI_DEVICE_ID 0 +#define SPI_ENGINE_REF_CLK FCLK_CLK0_HZ +#define SPI_ENGINE_MAX_SPEED 5000000 +#define SPI_ENGINE_BASEADDR XPAR_AXI_SPI_ENGINE_AXI_SPI_ENGINE_BASEADDR +#define SPI_ENGINE_DATA_WIDTH 8 +#define SPI_ENGINE_CS_DELAY 3 +#define SPI_CS_AD9516 0x00 +#define SPI_CS_AD9361_1 0x01 +#define SPI_CS_AD9361_2 0x02 + +// Interrupt Configs +#define INTC_DEVICE_ID XPAR_AXI_INTC_DEVICE_ID +#define PHY_INTR_ID XPAR_AXI_INTC_SYSTEM_PHY_IRQ_INTR +#define C2C_TX_INTR_ID XPAR_AXI_INTC_AXI_DMA_C2C_MM2S_INTROUT_INTR +#define C2C_RX_INTR_ID XPAR_AXI_INTC_AXI_DMA_C2C_S2MM_INTROUT_INTR +#define SCUTIMER_INTR_ID XPAR_AXI_INTC_AXI_TIMER_0_INTERRUPT_INTR + +// C2C configure +#define C2C_AXI_DMA_DEVICE_ID XPAR_AXI_DMA_C2C_DEVICE_ID +#define C2C_RXBUFF_ADDR_BASE XPAR_C2C_RX_AXI_BRAM_CTRL_S_AXI_BASEADDR +#define C2C_TXBUFF_ADDR_BASE XPAR_C2C_TX_AXI_BRAM_CTRL_S_AXI_BASEADDR +#define C2C_BUFF_NUM 4 +#define C2C_BUFF_SIZE 1024 + +// Physical configure +#define PHY_CTRL_BASEADDR XPAR_PHYC_BASEADDR +#define PHY_RX_BRAM_BUFF_ID XPAR_RX_FRAME_BRAM_CTRL_DEVICE_ID +#define PHY_TX_BRAM_BUFF_ID XPAR_TX_FRAME_BRAM_CTRL_DEVICE_ID +#define PHY_ANT_CONFIG_BRAM_ID XPAR_ANT_CONFIG_BRAM_CTRL_DEVICE_ID +#define PHY_RX_BUFF_BASEADDR XPAR_RX_FRAME_BRAM_CTRL_S_AXI_BASEADDR +#define PHY_TX_BUFF_BASEADDR XPAR_TX_FRAME_BRAM_CTRL_S_AXI_BASEADDR + +//Remote Test +#define GLINK_REMOTE_TEST_ENABLE +#define TIMER_COUNT_MAX 150000000 +#define SCUTIMER_DEVICE_ID XPAR_AXI_TIMER_0_DEVICE_ID + +//ANT ID +#define ANT_DEVICE_ID 0x0000 + +#if defined(GLINK_REMOTE_TEST_ENABLE) && !defined(TIMER_COUNT_MAX) +#define TIMER_COUNT_MAX 150000000 +#warning Must set a remote test interval after enable remote test. +#warning Use default interval 150000000... +#endif + +//XADC ID +#define SYSMON_DEVICE_ID XPAR_XADC_WIZ_0_DEVICE_ID + +#endif diff --git a/datalink814_sp/src/dev_profile/ad9361_reg_profile.c b/datalink814_sp/src/dev_profile/ad9361_reg_profile.c new file mode 100644 index 0000000..9a37b4d --- /dev/null +++ b/datalink814_sp/src/dev_profile/ad9361_reg_profile.c @@ -0,0 +1,2423 @@ +#include "dev_profile.h" +#include "../config/app_config.h" +#include "../adi_noos/drivers/rf-transceiver/ad9361_reg/ad9361_reg.h" + +#define TIMEOUT_TH 2000 + +// ad9361-1 +static spi_init_param ad9361_1_reg_spi_init = { + .device_id = SPI_DEVICE_ID, + .max_speed_hz = SPI_ENGINE_MAX_SPEED, + .mode = SPI_MODE_1, + .chip_select = SPI_CS_AD9361_1, + .platform_ops = SPI_OPS, + .extra = SPI_PARAM +}; + +static gpio_init_param ad9361_1_reg_gpio_resetb_init = { + .number = AD9361_1_RESET_B, + .platform_ops = GPIO_OPS, + .extra = GPIO_PARAM +}; +struct ad9361_reg_init_param ad9361_1_reg_default_init_param = { + /* SPI */ + .spi_init = &ad9361_1_reg_spi_init, + .gpio_resetb = &ad9361_1_reg_gpio_resetb_init +}; + +// ad9361-2 +static spi_init_param ad9361_2_reg_spi_init = { + .device_id = SPI_DEVICE_ID, + .max_speed_hz = SPI_ENGINE_MAX_SPEED, + .mode = SPI_MODE_1, + .chip_select = SPI_CS_AD9361_2, + .platform_ops = SPI_OPS, + .extra = SPI_PARAM +}; + +static gpio_init_param ad9361_2_reg_gpio_resetb_init = { + .number = AD9361_2_RESET_B, + .platform_ops = GPIO_OPS, + .extra = GPIO_PARAM +}; +struct ad9361_reg_init_param ad9361_2_reg_default_init_param = { + /* SPI */ + .spi_init = &ad9361_2_reg_spi_init, + .gpio_resetb = &ad9361_2_reg_gpio_resetb_init +}; + +uint32_t ad9361_reg_config(struct ad9361_reg_dev *dev){ + int32_t status = 0; + uint8_t value = 0; + int32_t time_out_cnt = 0; +//************************************************************ +// AD9361 R2 Auto Generated Initialization Script: This script was +// generated using the AD9361 Customer software Version 2.1.3 +//************************************************************ +// Profile: Custom +// REFCLK_IN: 25.000 MHz + + status |= ad9361_reg_write(dev, 0x0001, 0x08); + status |= ad9361_reg_write(dev, 0x03DF, 0x01); + status |= ad9361_reg_write(dev, 0x02A6, 0x0E); + status |= ad9361_reg_write(dev, 0x02A8, 0x0E); + status |= ad9361_reg_write(dev, 0x02AB, 0x07); + status |= ad9361_reg_write(dev, 0x02AC, 0xFF); + status |= ad9361_reg_write(dev, 0x0009, 0x17); + mdelay(20); // Wait 20 ms + +//************************************************************ +// Set BBPLL Frequency: 1152.000000 +//************************************************************ + status |= ad9361_reg_write(dev, 0x0045, 0x03); + status |= ad9361_reg_write(dev, 0x0046, 0x03); + status |= ad9361_reg_write(dev, 0x0048, 0xE8); + status |= ad9361_reg_write(dev, 0x0049, 0x5B); + status |= ad9361_reg_write(dev, 0x004A, 0x35); + status |= ad9361_reg_write(dev, 0x004B, 0xE0); + status |= ad9361_reg_write(dev, 0x004E, 0x10); + status |= ad9361_reg_write(dev, 0x0043, 0x66); + status |= ad9361_reg_write(dev, 0x0042, 0x46); + status |= ad9361_reg_write(dev, 0x0041, 0x01); + status |= ad9361_reg_write(dev, 0x0044, 0x17); + status |= ad9361_reg_write(dev, 0x003F, 0x05); + status |= ad9361_reg_write(dev, 0x003F, 0x01); + status |= ad9361_reg_write(dev, 0x004C, 0x86); + status |= ad9361_reg_write(dev, 0x004D, 0x01); + status |= ad9361_reg_write(dev, 0x004D, 0x05); + time_out_cnt = 0; + do{ + status |= ad9361_reg_read(dev, 0x005E, &value); + mdelay(1);// Wait 1ms + time_out_cnt++; + } while((value & 0x80) != 0x80 && time_out_cnt <= TIMEOUT_TH); + + + + status |= ad9361_reg_write(dev, 0x0002, 0xA4); + status |= ad9361_reg_write(dev, 0x0003, 0xE4); + status |= ad9361_reg_write(dev, 0x0004, 0x03); + status |= ad9361_reg_write(dev, 0x000A, 0x12); + +//************************************************************ +// Setup the Parallel Port (Digital Data Interface) +//************************************************************ + status |= ad9361_reg_write(dev, 0x0010, 0xC8); + status |= ad9361_reg_write(dev, 0x0011, 0x00); + status |= ad9361_reg_write(dev, 0x0012, 0x02); + status |= ad9361_reg_write(dev, 0x0006, 0x00); + status |= ad9361_reg_write(dev, 0x0007, 0x0F); + +//************************************************************ +// Setup AuxDAC +//************************************************************ + status |= ad9361_reg_write(dev, 0x0018, 0x00); + status |= ad9361_reg_write(dev, 0x0019, 0x00); + status |= ad9361_reg_write(dev, 0x001A, 0x00); + status |= ad9361_reg_write(dev, 0x001B, 0x00); + status |= ad9361_reg_write(dev, 0x0023, 0xFF); + status |= ad9361_reg_write(dev, 0x0026, 0x00); + status |= ad9361_reg_write(dev, 0x0030, 0x00); + status |= ad9361_reg_write(dev, 0x0031, 0x00); + status |= ad9361_reg_write(dev, 0x0032, 0x00); + status |= ad9361_reg_write(dev, 0x0033, 0x00); + +//************************************************************ +// Setup AuxADC +//************************************************************ + status |= ad9361_reg_write(dev, 0x000B, 0x00); + status |= ad9361_reg_write(dev, 0x000C, 0x00); + status |= ad9361_reg_write(dev, 0x000D, 0x03); + status |= ad9361_reg_write(dev, 0x000F, 0x04); + status |= ad9361_reg_write(dev, 0x001C, 0x00); + status |= ad9361_reg_write(dev, 0x001D, 0x01); + +//************************************************************ +// Setup Control Outs +//************************************************************ + status |= ad9361_reg_write(dev, 0x0035, 0x00); + status |= ad9361_reg_write(dev, 0x0036, 0xFF); + +//************************************************************ +// Setup GPO +//************************************************************ + status |= ad9361_reg_write(dev, 0x003A, 0x18); + status |= ad9361_reg_write(dev, 0x0020, 0x00); + status |= ad9361_reg_write(dev, 0x0027, 0x00); + status |= ad9361_reg_write(dev, 0x0028, 0x00); + status |= ad9361_reg_write(dev, 0x0029, 0x00); + status |= ad9361_reg_write(dev, 0x002A, 0x00); + status |= ad9361_reg_write(dev, 0x002B, 0x00); + status |= ad9361_reg_write(dev, 0x002C, 0x00); + status |= ad9361_reg_write(dev, 0x002D, 0x00); + status |= ad9361_reg_write(dev, 0x002E, 0x00); + status |= ad9361_reg_write(dev, 0x002F, 0x00); + +//************************************************************ +// Setup RF PLL non-frequency-dependent registers +//************************************************************ + status |= ad9361_reg_write(dev, 0x0261, 0x00); + status |= ad9361_reg_write(dev, 0x02A1, 0x00); + status |= ad9361_reg_write(dev, 0x0248, 0x0B); + status |= ad9361_reg_write(dev, 0x0288, 0x0B); + status |= ad9361_reg_write(dev, 0x0246, 0x02); + status |= ad9361_reg_write(dev, 0x0286, 0x02); + status |= ad9361_reg_write(dev, 0x0249, 0x8E); + status |= ad9361_reg_write(dev, 0x0289, 0x8E); + status |= ad9361_reg_write(dev, 0x023B, 0x80); + status |= ad9361_reg_write(dev, 0x027B, 0x80); + status |= ad9361_reg_write(dev, 0x0243, 0x0D); + status |= ad9361_reg_write(dev, 0x0283, 0x0D); + status |= ad9361_reg_write(dev, 0x023D, 0x00); + status |= ad9361_reg_write(dev, 0x027D, 0x00); + + status |= ad9361_reg_write(dev, 0x0015, 0x0C); + status |= ad9361_reg_write(dev, 0x0014, 0x1D); + status |= ad9361_reg_write(dev, 0x0013, 0x01); + mdelay(1); // Wait 1 ms + + status |= ad9361_reg_write(dev, 0x023D, 0x04); + time_out_cnt = 0; + do{ + status |= ad9361_reg_read(dev, 0x0244, &value); + mdelay(1);// Wait 1ms + time_out_cnt++; + } while((value & 0x80) != 0x80 && time_out_cnt <= TIMEOUT_TH); + + + status |= ad9361_reg_write(dev, 0x027D, 0x04); + time_out_cnt = 0; + do{ + status |= ad9361_reg_read(dev, 0x0284, &value); + mdelay(1);// Wait 1ms + time_out_cnt++; + } while((value & 0x80) != 0x80 && time_out_cnt <= TIMEOUT_TH); + + + status |= ad9361_reg_write(dev, 0x023D, 0x00); + status |= ad9361_reg_write(dev, 0x027D, 0x00); +//************************************************************ +// FDD RX,TX Synth Frequency: 125.000000,4125.000000 MHz +//************************************************************ +//************************************************************ +// Setup Rx Frequency-Dependent Syntheisizer Registers +//************************************************************ + status |= ad9361_reg_write(dev, 0x023A, 0x4A); + status |= ad9361_reg_write(dev, 0x0239, 0xC1); + status |= ad9361_reg_write(dev, 0x0242, 0x0E); + status |= ad9361_reg_write(dev, 0x0238, 0x78); + status |= ad9361_reg_write(dev, 0x0245, 0x00); + status |= ad9361_reg_write(dev, 0x0251, 0x0B); + status |= ad9361_reg_write(dev, 0x0250, 0x70); + status |= ad9361_reg_write(dev, 0x023B, 0x94); + status |= ad9361_reg_write(dev, 0x023E, 0xF4); + status |= ad9361_reg_write(dev, 0x023F, 0xDF); + status |= ad9361_reg_write(dev, 0x0240, 0x0A); + +//************************************************************ +// Setup Tx Frequency-Dependent Syntheisizer Registers +//************************************************************ + status |= ad9361_reg_write(dev, 0x027A, 0x4A); + status |= ad9361_reg_write(dev, 0x0279, 0xC1); + status |= ad9361_reg_write(dev, 0x0282, 0x0E); + status |= ad9361_reg_write(dev, 0x0278, 0x78); + status |= ad9361_reg_write(dev, 0x0285, 0x00); + status |= ad9361_reg_write(dev, 0x0291, 0x0B); + status |= ad9361_reg_write(dev, 0x0290, 0x70); + status |= ad9361_reg_write(dev, 0x027B, 0x93); + status |= ad9361_reg_write(dev, 0x027E, 0xF4); + status |= ad9361_reg_write(dev, 0x027F, 0xDF); + status |= ad9361_reg_write(dev, 0x0280, 0x0A); + +//************************************************************ +// Write Rx and Tx Frequency Words +//************************************************************ + status |= ad9361_reg_write(dev, 0x0233, 0x00); + status |= ad9361_reg_write(dev, 0x0234, 0x00); + status |= ad9361_reg_write(dev, 0x0235, 0x00); + status |= ad9361_reg_write(dev, 0x0232, 0x00); + status |= ad9361_reg_write(dev, 0x0231, 0xA0); + status |= ad9361_reg_write(dev, 0x0005, 0x05); + status |= ad9361_reg_write(dev, 0x0273, 0x00); + status |= ad9361_reg_write(dev, 0x0274, 0x00); + status |= ad9361_reg_write(dev, 0x0275, 0x00); + status |= ad9361_reg_write(dev, 0x0272, 0x00); + status |= ad9361_reg_write(dev, 0x0271, 0xA5); + status |= ad9361_reg_write(dev, 0x0005, 0x05); + +//************************************************************ +// Program Mixer GM Sub-table +//************************************************************ + status |= ad9361_reg_write(dev, 0x013F, 0x02); + status |= ad9361_reg_write(dev, 0x0138, 0x0F); + status |= ad9361_reg_write(dev, 0x0139, 0x78); + status |= ad9361_reg_write(dev, 0x013A, 0x00); + status |= ad9361_reg_write(dev, 0x013B, 0x00); + status |= ad9361_reg_write(dev, 0x013F, 0x06); + status |= ad9361_reg_write(dev, 0x013C, 0x00); + status |= ad9361_reg_write(dev, 0x013C, 0x00); + status |= ad9361_reg_write(dev, 0x0138, 0x0E); + status |= ad9361_reg_write(dev, 0x0139, 0x74); + status |= ad9361_reg_write(dev, 0x013A, 0x00); + status |= ad9361_reg_write(dev, 0x013B, 0x0D); + status |= ad9361_reg_write(dev, 0x013F, 0x06); + status |= ad9361_reg_write(dev, 0x013C, 0x00); + status |= ad9361_reg_write(dev, 0x013C, 0x00); + status |= ad9361_reg_write(dev, 0x0138, 0x0D); + status |= ad9361_reg_write(dev, 0x0139, 0x70); + status |= ad9361_reg_write(dev, 0x013A, 0x00); + status |= ad9361_reg_write(dev, 0x013B, 0x15); + status |= ad9361_reg_write(dev, 0x013F, 0x06); + status |= ad9361_reg_write(dev, 0x013C, 0x00); + status |= ad9361_reg_write(dev, 0x013C, 0x00); + status |= ad9361_reg_write(dev, 0x0138, 0x0C); + status |= ad9361_reg_write(dev, 0x0139, 0x6C); + status |= ad9361_reg_write(dev, 0x013A, 0x00); + status |= ad9361_reg_write(dev, 0x013B, 0x1B); + status |= ad9361_reg_write(dev, 0x013F, 0x06); + status |= ad9361_reg_write(dev, 0x013C, 0x00); + status |= ad9361_reg_write(dev, 0x013C, 0x00); + status |= ad9361_reg_write(dev, 0x0138, 0x0B); + status |= ad9361_reg_write(dev, 0x0139, 0x68); + status |= ad9361_reg_write(dev, 0x013A, 0x00); + status |= ad9361_reg_write(dev, 0x013B, 0x21); + status |= ad9361_reg_write(dev, 0x013F, 0x06); + status |= ad9361_reg_write(dev, 0x013C, 0x00); + status |= ad9361_reg_write(dev, 0x013C, 0x00); + status |= ad9361_reg_write(dev, 0x0138, 0x0A); + status |= ad9361_reg_write(dev, 0x0139, 0x64); + status |= ad9361_reg_write(dev, 0x013A, 0x00); + status |= ad9361_reg_write(dev, 0x013B, 0x25); + status |= ad9361_reg_write(dev, 0x013F, 0x06); + status |= ad9361_reg_write(dev, 0x013C, 0x00); + status |= ad9361_reg_write(dev, 0x013C, 0x00); + status |= ad9361_reg_write(dev, 0x0138, 0x09); + status |= ad9361_reg_write(dev, 0x0139, 0x60); + status |= ad9361_reg_write(dev, 0x013A, 0x00); + status |= ad9361_reg_write(dev, 0x013B, 0x29); + status |= ad9361_reg_write(dev, 0x013F, 0x06); + status |= ad9361_reg_write(dev, 0x013C, 0x00); + status |= ad9361_reg_write(dev, 0x013C, 0x00); + status |= ad9361_reg_write(dev, 0x0138, 0x08); + status |= ad9361_reg_write(dev, 0x0139, 0x5C); + status |= ad9361_reg_write(dev, 0x013A, 0x00); + status |= ad9361_reg_write(dev, 0x013B, 0x2C); + status |= ad9361_reg_write(dev, 0x013F, 0x06); + status |= ad9361_reg_write(dev, 0x013C, 0x00); + status |= ad9361_reg_write(dev, 0x013C, 0x00); + status |= ad9361_reg_write(dev, 0x0138, 0x07); + status |= ad9361_reg_write(dev, 0x0139, 0x58); + status |= ad9361_reg_write(dev, 0x013A, 0x00); + status |= ad9361_reg_write(dev, 0x013B, 0x2F); + status |= ad9361_reg_write(dev, 0x013F, 0x06); + status |= ad9361_reg_write(dev, 0x013C, 0x00); + status |= ad9361_reg_write(dev, 0x013C, 0x00); + status |= ad9361_reg_write(dev, 0x0138, 0x06); + status |= ad9361_reg_write(dev, 0x0139, 0x54); + status |= ad9361_reg_write(dev, 0x013A, 0x00); + status |= ad9361_reg_write(dev, 0x013B, 0x31); + status |= ad9361_reg_write(dev, 0x013F, 0x06); + status |= ad9361_reg_write(dev, 0x013C, 0x00); + status |= ad9361_reg_write(dev, 0x013C, 0x00); + status |= ad9361_reg_write(dev, 0x0138, 0x05); + status |= ad9361_reg_write(dev, 0x0139, 0x50); + status |= ad9361_reg_write(dev, 0x013A, 0x00); + status |= ad9361_reg_write(dev, 0x013B, 0x33); + status |= ad9361_reg_write(dev, 0x013F, 0x06); + status |= ad9361_reg_write(dev, 0x013C, 0x00); + status |= ad9361_reg_write(dev, 0x013C, 0x00); + status |= ad9361_reg_write(dev, 0x0138, 0x04); + status |= ad9361_reg_write(dev, 0x0139, 0x4C); + status |= ad9361_reg_write(dev, 0x013A, 0x00); + status |= ad9361_reg_write(dev, 0x013B, 0x34); + status |= ad9361_reg_write(dev, 0x013F, 0x06); + status |= ad9361_reg_write(dev, 0x013C, 0x00); + status |= ad9361_reg_write(dev, 0x013C, 0x00); + status |= ad9361_reg_write(dev, 0x0138, 0x03); + status |= ad9361_reg_write(dev, 0x0139, 0x48); + status |= ad9361_reg_write(dev, 0x013A, 0x00); + status |= ad9361_reg_write(dev, 0x013B, 0x35); + status |= ad9361_reg_write(dev, 0x013F, 0x06); + status |= ad9361_reg_write(dev, 0x013C, 0x00); + status |= ad9361_reg_write(dev, 0x013C, 0x00); + status |= ad9361_reg_write(dev, 0x0138, 0x02); + status |= ad9361_reg_write(dev, 0x0139, 0x30); + status |= ad9361_reg_write(dev, 0x013A, 0x00); + status |= ad9361_reg_write(dev, 0x013B, 0x3A); + status |= ad9361_reg_write(dev, 0x013F, 0x06); + status |= ad9361_reg_write(dev, 0x013C, 0x00); + status |= ad9361_reg_write(dev, 0x013C, 0x00); + status |= ad9361_reg_write(dev, 0x0138, 0x01); + status |= ad9361_reg_write(dev, 0x0139, 0x18); + status |= ad9361_reg_write(dev, 0x013A, 0x00); + status |= ad9361_reg_write(dev, 0x013B, 0x3D); + status |= ad9361_reg_write(dev, 0x013F, 0x06); + status |= ad9361_reg_write(dev, 0x013C, 0x00); + status |= ad9361_reg_write(dev, 0x013C, 0x00); + status |= ad9361_reg_write(dev, 0x0138, 0x00); + status |= ad9361_reg_write(dev, 0x0139, 0x00); + status |= ad9361_reg_write(dev, 0x013A, 0x00); + status |= ad9361_reg_write(dev, 0x013B, 0x3E); + status |= ad9361_reg_write(dev, 0x013F, 0x06); + status |= ad9361_reg_write(dev, 0x013C, 0x00); + status |= ad9361_reg_write(dev, 0x013C, 0x00); + status |= ad9361_reg_write(dev, 0x013F, 0x02); + status |= ad9361_reg_write(dev, 0x013C, 0x00); + status |= ad9361_reg_write(dev, 0x013C, 0x00); + status |= ad9361_reg_write(dev, 0x013F, 0x00); + +//************************************************************ +// Program Rx Gain Tables with GainTable800MHz.csv +//************************************************************ + + status |= ad9361_reg_write(dev, 0x0137, 0x1A); + status |= ad9361_reg_write(dev, 0x0130, 0x00); + status |= ad9361_reg_write(dev, 0x0131, 0x00); + status |= ad9361_reg_write(dev, 0x0132, 0x00); + status |= ad9361_reg_write(dev, 0x0133, 0x20); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x01); + status |= ad9361_reg_write(dev, 0x0131, 0x00); + status |= ad9361_reg_write(dev, 0x0132, 0x00); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x02); + status |= ad9361_reg_write(dev, 0x0131, 0x00); + status |= ad9361_reg_write(dev, 0x0132, 0x00); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x03); + status |= ad9361_reg_write(dev, 0x0131, 0x00); + status |= ad9361_reg_write(dev, 0x0132, 0x01); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x04); + status |= ad9361_reg_write(dev, 0x0131, 0x00); + status |= ad9361_reg_write(dev, 0x0132, 0x02); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x05); + status |= ad9361_reg_write(dev, 0x0131, 0x00); + status |= ad9361_reg_write(dev, 0x0132, 0x03); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x06); + status |= ad9361_reg_write(dev, 0x0131, 0x00); + status |= ad9361_reg_write(dev, 0x0132, 0x04); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x07); + status |= ad9361_reg_write(dev, 0x0131, 0x00); + status |= ad9361_reg_write(dev, 0x0132, 0x05); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x08); + status |= ad9361_reg_write(dev, 0x0131, 0x01); + status |= ad9361_reg_write(dev, 0x0132, 0x03); + status |= ad9361_reg_write(dev, 0x0133, 0x20); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x09); + status |= ad9361_reg_write(dev, 0x0131, 0x01); + status |= ad9361_reg_write(dev, 0x0132, 0x04); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x0A); + status |= ad9361_reg_write(dev, 0x0131, 0x01); + status |= ad9361_reg_write(dev, 0x0132, 0x05); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x0B); + status |= ad9361_reg_write(dev, 0x0131, 0x01); + status |= ad9361_reg_write(dev, 0x0132, 0x06); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x0C); + status |= ad9361_reg_write(dev, 0x0131, 0x01); + status |= ad9361_reg_write(dev, 0x0132, 0x07); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x0D); + status |= ad9361_reg_write(dev, 0x0131, 0x01); + status |= ad9361_reg_write(dev, 0x0132, 0x08); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x0E); + status |= ad9361_reg_write(dev, 0x0131, 0x01); + status |= ad9361_reg_write(dev, 0x0132, 0x09); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x0F); + status |= ad9361_reg_write(dev, 0x0131, 0x01); + status |= ad9361_reg_write(dev, 0x0132, 0x0A); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x10); + status |= ad9361_reg_write(dev, 0x0131, 0x01); + status |= ad9361_reg_write(dev, 0x0132, 0x0B); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x11); + status |= ad9361_reg_write(dev, 0x0131, 0x01); + status |= ad9361_reg_write(dev, 0x0132, 0x0C); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x12); + status |= ad9361_reg_write(dev, 0x0131, 0x01); + status |= ad9361_reg_write(dev, 0x0132, 0x0D); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x13); + status |= ad9361_reg_write(dev, 0x0131, 0x01); + status |= ad9361_reg_write(dev, 0x0132, 0x0E); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x14); + status |= ad9361_reg_write(dev, 0x0131, 0x02); + status |= ad9361_reg_write(dev, 0x0132, 0x09); + status |= ad9361_reg_write(dev, 0x0133, 0x20); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x15); + status |= ad9361_reg_write(dev, 0x0131, 0x02); + status |= ad9361_reg_write(dev, 0x0132, 0x0A); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x16); + status |= ad9361_reg_write(dev, 0x0131, 0x02); + status |= ad9361_reg_write(dev, 0x0132, 0x0B); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x17); + status |= ad9361_reg_write(dev, 0x0131, 0x02); + status |= ad9361_reg_write(dev, 0x0132, 0x0C); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x18); + status |= ad9361_reg_write(dev, 0x0131, 0x02); + status |= ad9361_reg_write(dev, 0x0132, 0x0D); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x19); + status |= ad9361_reg_write(dev, 0x0131, 0x02); + status |= ad9361_reg_write(dev, 0x0132, 0x0E); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x1A); + status |= ad9361_reg_write(dev, 0x0131, 0x02); + status |= ad9361_reg_write(dev, 0x0132, 0x0F); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x1B); + status |= ad9361_reg_write(dev, 0x0131, 0x02); + status |= ad9361_reg_write(dev, 0x0132, 0x10); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x1C); + status |= ad9361_reg_write(dev, 0x0131, 0x02); + status |= ad9361_reg_write(dev, 0x0132, 0x2B); + status |= ad9361_reg_write(dev, 0x0133, 0x20); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x1D); + status |= ad9361_reg_write(dev, 0x0131, 0x02); + status |= ad9361_reg_write(dev, 0x0132, 0x2C); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x1E); + status |= ad9361_reg_write(dev, 0x0131, 0x04); + status |= ad9361_reg_write(dev, 0x0132, 0x28); + status |= ad9361_reg_write(dev, 0x0133, 0x20); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x1F); + status |= ad9361_reg_write(dev, 0x0131, 0x04); + status |= ad9361_reg_write(dev, 0x0132, 0x29); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x20); + status |= ad9361_reg_write(dev, 0x0131, 0x04); + status |= ad9361_reg_write(dev, 0x0132, 0x2A); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x21); + status |= ad9361_reg_write(dev, 0x0131, 0x04); + status |= ad9361_reg_write(dev, 0x0132, 0x2B); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x22); + status |= ad9361_reg_write(dev, 0x0131, 0x24); + status |= ad9361_reg_write(dev, 0x0132, 0x20); + status |= ad9361_reg_write(dev, 0x0133, 0x20); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x23); + status |= ad9361_reg_write(dev, 0x0131, 0x24); + status |= ad9361_reg_write(dev, 0x0132, 0x21); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x24); + status |= ad9361_reg_write(dev, 0x0131, 0x44); + status |= ad9361_reg_write(dev, 0x0132, 0x20); + status |= ad9361_reg_write(dev, 0x0133, 0x20); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x25); + status |= ad9361_reg_write(dev, 0x0131, 0x44); + status |= ad9361_reg_write(dev, 0x0132, 0x21); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x26); + status |= ad9361_reg_write(dev, 0x0131, 0x44); + status |= ad9361_reg_write(dev, 0x0132, 0x22); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x27); + status |= ad9361_reg_write(dev, 0x0131, 0x44); + status |= ad9361_reg_write(dev, 0x0132, 0x23); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x28); + status |= ad9361_reg_write(dev, 0x0131, 0x44); + status |= ad9361_reg_write(dev, 0x0132, 0x24); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x29); + status |= ad9361_reg_write(dev, 0x0131, 0x44); + status |= ad9361_reg_write(dev, 0x0132, 0x25); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x2A); + status |= ad9361_reg_write(dev, 0x0131, 0x44); + status |= ad9361_reg_write(dev, 0x0132, 0x26); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x2B); + status |= ad9361_reg_write(dev, 0x0131, 0x44); + status |= ad9361_reg_write(dev, 0x0132, 0x27); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x2C); + status |= ad9361_reg_write(dev, 0x0131, 0x44); + status |= ad9361_reg_write(dev, 0x0132, 0x28); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x2D); + status |= ad9361_reg_write(dev, 0x0131, 0x44); + status |= ad9361_reg_write(dev, 0x0132, 0x29); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x2E); + status |= ad9361_reg_write(dev, 0x0131, 0x44); + status |= ad9361_reg_write(dev, 0x0132, 0x2A); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x2F); + status |= ad9361_reg_write(dev, 0x0131, 0x44); + status |= ad9361_reg_write(dev, 0x0132, 0x2B); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x30); + status |= ad9361_reg_write(dev, 0x0131, 0x44); + status |= ad9361_reg_write(dev, 0x0132, 0x2C); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x31); + status |= ad9361_reg_write(dev, 0x0131, 0x44); + status |= ad9361_reg_write(dev, 0x0132, 0x2D); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x32); + status |= ad9361_reg_write(dev, 0x0131, 0x44); + status |= ad9361_reg_write(dev, 0x0132, 0x2E); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x33); + status |= ad9361_reg_write(dev, 0x0131, 0x44); + status |= ad9361_reg_write(dev, 0x0132, 0x2F); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x34); + status |= ad9361_reg_write(dev, 0x0131, 0x44); + status |= ad9361_reg_write(dev, 0x0132, 0x30); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x35); + status |= ad9361_reg_write(dev, 0x0131, 0x44); + status |= ad9361_reg_write(dev, 0x0132, 0x31); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x36); + status |= ad9361_reg_write(dev, 0x0131, 0x44); + status |= ad9361_reg_write(dev, 0x0132, 0x32); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x37); + status |= ad9361_reg_write(dev, 0x0131, 0x64); + status |= ad9361_reg_write(dev, 0x0132, 0x2E); + status |= ad9361_reg_write(dev, 0x0133, 0x20); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x38); + status |= ad9361_reg_write(dev, 0x0131, 0x64); + status |= ad9361_reg_write(dev, 0x0132, 0x2F); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x39); + status |= ad9361_reg_write(dev, 0x0131, 0x64); + status |= ad9361_reg_write(dev, 0x0132, 0x30); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x3A); + status |= ad9361_reg_write(dev, 0x0131, 0x64); + status |= ad9361_reg_write(dev, 0x0132, 0x31); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x3B); + status |= ad9361_reg_write(dev, 0x0131, 0x64); + status |= ad9361_reg_write(dev, 0x0132, 0x32); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x3C); + status |= ad9361_reg_write(dev, 0x0131, 0x64); + status |= ad9361_reg_write(dev, 0x0132, 0x33); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x3D); + status |= ad9361_reg_write(dev, 0x0131, 0x64); + status |= ad9361_reg_write(dev, 0x0132, 0x34); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x3E); + status |= ad9361_reg_write(dev, 0x0131, 0x64); + status |= ad9361_reg_write(dev, 0x0132, 0x35); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x3F); + status |= ad9361_reg_write(dev, 0x0131, 0x64); + status |= ad9361_reg_write(dev, 0x0132, 0x36); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x40); + status |= ad9361_reg_write(dev, 0x0131, 0x64); + status |= ad9361_reg_write(dev, 0x0132, 0x37); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x41); + status |= ad9361_reg_write(dev, 0x0131, 0x64); + status |= ad9361_reg_write(dev, 0x0132, 0x38); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x42); + status |= ad9361_reg_write(dev, 0x0131, 0x65); + status |= ad9361_reg_write(dev, 0x0132, 0x38); + status |= ad9361_reg_write(dev, 0x0133, 0x20); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x43); + status |= ad9361_reg_write(dev, 0x0131, 0x66); + status |= ad9361_reg_write(dev, 0x0132, 0x38); + status |= ad9361_reg_write(dev, 0x0133, 0x20); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x44); + status |= ad9361_reg_write(dev, 0x0131, 0x67); + status |= ad9361_reg_write(dev, 0x0132, 0x38); + status |= ad9361_reg_write(dev, 0x0133, 0x20); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x45); + status |= ad9361_reg_write(dev, 0x0131, 0x68); + status |= ad9361_reg_write(dev, 0x0132, 0x38); + status |= ad9361_reg_write(dev, 0x0133, 0x20); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x46); + status |= ad9361_reg_write(dev, 0x0131, 0x69); + status |= ad9361_reg_write(dev, 0x0132, 0x38); + status |= ad9361_reg_write(dev, 0x0133, 0x20); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x47); + status |= ad9361_reg_write(dev, 0x0131, 0x6A); + status |= ad9361_reg_write(dev, 0x0132, 0x38); + status |= ad9361_reg_write(dev, 0x0133, 0x20); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x48); + status |= ad9361_reg_write(dev, 0x0131, 0x6B); + status |= ad9361_reg_write(dev, 0x0132, 0x38); + status |= ad9361_reg_write(dev, 0x0133, 0x20); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x49); + status |= ad9361_reg_write(dev, 0x0131, 0x6C); + status |= ad9361_reg_write(dev, 0x0132, 0x38); + status |= ad9361_reg_write(dev, 0x0133, 0x20); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x4A); + status |= ad9361_reg_write(dev, 0x0131, 0x6D); + status |= ad9361_reg_write(dev, 0x0132, 0x38); + status |= ad9361_reg_write(dev, 0x0133, 0x20); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x4B); + status |= ad9361_reg_write(dev, 0x0131, 0x6E); + status |= ad9361_reg_write(dev, 0x0132, 0x38); + status |= ad9361_reg_write(dev, 0x0133, 0x20); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x4C); + status |= ad9361_reg_write(dev, 0x0131, 0x6F); + status |= ad9361_reg_write(dev, 0x0132, 0x38); + status |= ad9361_reg_write(dev, 0x0133, 0x20); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x4D); + status |= ad9361_reg_write(dev, 0x0131, 0x00); + status |= ad9361_reg_write(dev, 0x0132, 0x00); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x4E); + status |= ad9361_reg_write(dev, 0x0131, 0x00); + status |= ad9361_reg_write(dev, 0x0132, 0x00); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x4F); + status |= ad9361_reg_write(dev, 0x0131, 0x00); + status |= ad9361_reg_write(dev, 0x0132, 0x00); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x50); + status |= ad9361_reg_write(dev, 0x0131, 0x00); + status |= ad9361_reg_write(dev, 0x0132, 0x00); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x51); + status |= ad9361_reg_write(dev, 0x0131, 0x00); + status |= ad9361_reg_write(dev, 0x0132, 0x00); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x52); + status |= ad9361_reg_write(dev, 0x0131, 0x00); + status |= ad9361_reg_write(dev, 0x0132, 0x00); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x53); + status |= ad9361_reg_write(dev, 0x0131, 0x00); + status |= ad9361_reg_write(dev, 0x0132, 0x00); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x54); + status |= ad9361_reg_write(dev, 0x0131, 0x00); + status |= ad9361_reg_write(dev, 0x0132, 0x00); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x55); + status |= ad9361_reg_write(dev, 0x0131, 0x00); + status |= ad9361_reg_write(dev, 0x0132, 0x00); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x56); + status |= ad9361_reg_write(dev, 0x0131, 0x00); + status |= ad9361_reg_write(dev, 0x0132, 0x00); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x57); + status |= ad9361_reg_write(dev, 0x0131, 0x00); + status |= ad9361_reg_write(dev, 0x0132, 0x00); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x58); + status |= ad9361_reg_write(dev, 0x0131, 0x00); + status |= ad9361_reg_write(dev, 0x0132, 0x00); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x59); + status |= ad9361_reg_write(dev, 0x0131, 0x00); + status |= ad9361_reg_write(dev, 0x0132, 0x00); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0130, 0x5A); + status |= ad9361_reg_write(dev, 0x0131, 0x00); + status |= ad9361_reg_write(dev, 0x0132, 0x00); + status |= ad9361_reg_write(dev, 0x0133, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1E); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x1A); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0134, 0x00); + status |= ad9361_reg_write(dev, 0x0137, 0x00); +//************************************************************ +// Setup Rx Manual Gain Registers +//************************************************************ + status |= ad9361_reg_write(dev, 0x00FA, 0xE0); + status |= ad9361_reg_write(dev, 0x00FB, 0x08); + status |= ad9361_reg_write(dev, 0x00FC, 0x23); + status |= ad9361_reg_write(dev, 0x00FD, 0x4C); + status |= ad9361_reg_write(dev, 0x00FE, 0x44); + status |= ad9361_reg_write(dev, 0x0100, 0x6F); + status |= ad9361_reg_write(dev, 0x0104, 0x2F); + status |= ad9361_reg_write(dev, 0x0105, 0x3A); + status |= ad9361_reg_write(dev, 0x0107, 0x2B); + status |= ad9361_reg_write(dev, 0x0108, 0x31); + status |= ad9361_reg_write(dev, 0x0109, 0x00); + status |= ad9361_reg_write(dev, 0x010A, 0x58); + status |= ad9361_reg_write(dev, 0x010B, 0x00); + status |= ad9361_reg_write(dev, 0x010C, 0x00); + status |= ad9361_reg_write(dev, 0x010D, 0x18); + status |= ad9361_reg_write(dev, 0x010E, 0x00); + status |= ad9361_reg_write(dev, 0x0114, 0x30); + status |= ad9361_reg_write(dev, 0x011A, 0x27); + status |= ad9361_reg_write(dev, 0x0081, 0x00); +//************************************************************ +// RX Baseband Filter Tuning (Real BW: 20.000000 MHz) 3dB Filter +// Corner @ 28.000000 MHz) +//************************************************************ + status |= ad9361_reg_write(dev, 0x01FB, 0x14); + status |= ad9361_reg_write(dev, 0x01FC, 0x00); + status |= ad9361_reg_write(dev, 0x01F8, 0x05); + status |= ad9361_reg_write(dev, 0x01F9, 0x1E); + + status |= ad9361_reg_write(dev, 0x01D5, 0x3F); + status |= ad9361_reg_write(dev, 0x01C0, 0x03); + status |= ad9361_reg_write(dev, 0x01E2, 0x02); + status |= ad9361_reg_write(dev, 0x01E3, 0x02); + status |= ad9361_reg_write(dev, 0x0016, 0x80); + time_out_cnt = 0; + do{ + status |= ad9361_reg_read(dev, 0x0016, &value); + mdelay(1);// Wait 1ms + time_out_cnt++; + } while((value & 0x80) != 0x00 && time_out_cnt <= TIMEOUT_TH); + + + status |= ad9361_reg_write(dev, 0x01E2, 0x03); + status |= ad9361_reg_write(dev, 0x01E3, 0x03); +//************************************************************ +// TX Baseband Filter Tuning (Real BW: 20.000000 MHz) 3dB Filter +// Corner @ 32.000000 MHz) +//************************************************************ + status |= ad9361_reg_write(dev, 0x00D6, 0x04); + status |= ad9361_reg_write(dev, 0x00D7, 0x1E); + + status |= ad9361_reg_write(dev, 0x00CA, 0x22); + status |= ad9361_reg_write(dev, 0x0016, 0x40); + time_out_cnt = 0; + do{ + status |= ad9361_reg_read(dev, 0x0016, &value); + mdelay(1);// Wait 1ms + time_out_cnt++; + } while((value & 0x40) != 0x00 && time_out_cnt <= TIMEOUT_TH); + + + status |= ad9361_reg_write(dev, 0x00CA, 0x26); +//************************************************************ +// RX TIA Setup: Setup values scale based on RxBBF calibration +// results. See information in Calibration Guide. +//************************************************************ + status |= ad9361_reg_write(dev, 0x01DB, 0x20); + status |= ad9361_reg_write(dev, 0x01DD, 0x00); + status |= ad9361_reg_write(dev, 0x01DF, 0x00); + status |= ad9361_reg_write(dev, 0x01DC, 0x47); + status |= ad9361_reg_write(dev, 0x01DE, 0x47); + +//************************************************************ +// TX Secondary Filter Calibration Setup: Real Bandwidth +// 20.000000MHz, 3dB Corner @ 100.000000MHz +//************************************************************ + status |= ad9361_reg_write(dev, 0x00D2, 0x04); + status |= ad9361_reg_write(dev, 0x00D1, 0x0C); + status |= ad9361_reg_write(dev, 0x00D0, 0x57); + +//************************************************************ +// ADC Setup: Tune ADC Performance based on RX analog filter tune +// corner. Real Bandwidth: 18.155158 MHz, ADC Clock Frequency: +// 288.000000 MHz. The values in registers 0x200 - 0x227 need to be +// calculated using the equations in the Calibration Guide. +//************************************************************ + + status |= ad9361_reg_write(dev, 0x0200, 0x00); + status |= ad9361_reg_write(dev, 0x0201, 0x00); + status |= ad9361_reg_write(dev, 0x0202, 0x00); + status |= ad9361_reg_write(dev, 0x0203, 0x24); + status |= ad9361_reg_write(dev, 0x0204, 0x24); + status |= ad9361_reg_write(dev, 0x0205, 0x00); + status |= ad9361_reg_write(dev, 0x0206, 0x00); + status |= ad9361_reg_write(dev, 0x0207, 0x67); + status |= ad9361_reg_write(dev, 0x0208, 0x55); + status |= ad9361_reg_write(dev, 0x0209, 0x31); + status |= ad9361_reg_write(dev, 0x020A, 0x3E); + status |= ad9361_reg_write(dev, 0x020B, 0x35); + status |= ad9361_reg_write(dev, 0x020C, 0x41); + status |= ad9361_reg_write(dev, 0x020D, 0x34); + status |= ad9361_reg_write(dev, 0x020E, 0x00); + status |= ad9361_reg_write(dev, 0x020F, 0x6A); + status |= ad9361_reg_write(dev, 0x0210, 0x6A); + status |= ad9361_reg_write(dev, 0x0211, 0x6A); + status |= ad9361_reg_write(dev, 0x0212, 0x3C); + status |= ad9361_reg_write(dev, 0x0213, 0x3C); + status |= ad9361_reg_write(dev, 0x0214, 0x3C); + status |= ad9361_reg_write(dev, 0x0215, 0x3F); + status |= ad9361_reg_write(dev, 0x0216, 0x3F); + status |= ad9361_reg_write(dev, 0x0217, 0x3F); + status |= ad9361_reg_write(dev, 0x0218, 0x2E); + status |= ad9361_reg_write(dev, 0x0219, 0x9C); + status |= ad9361_reg_write(dev, 0x021A, 0x1F); + status |= ad9361_reg_write(dev, 0x021B, 0x15); + status |= ad9361_reg_write(dev, 0x021C, 0x9C); + status |= ad9361_reg_write(dev, 0x021D, 0x1F); + status |= ad9361_reg_write(dev, 0x021E, 0x15); + status |= ad9361_reg_write(dev, 0x021F, 0x9C); + status |= ad9361_reg_write(dev, 0x0220, 0x1F); + status |= ad9361_reg_write(dev, 0x0221, 0x2A); + status |= ad9361_reg_write(dev, 0x0222, 0x2A); + status |= ad9361_reg_write(dev, 0x0223, 0x40); + status |= ad9361_reg_write(dev, 0x0224, 0x40); + status |= ad9361_reg_write(dev, 0x0225, 0x2C); + status |= ad9361_reg_write(dev, 0x0226, 0x00); + status |= ad9361_reg_write(dev, 0x0227, 0x00); +//************************************************************ +// Setup and Run BB DC and RF DC Offset Calibrations +//************************************************************ + status |= ad9361_reg_write(dev, 0x0193, 0x3F); + status |= ad9361_reg_write(dev, 0x0190, 0x0F); + status |= ad9361_reg_write(dev, 0x0194, 0x01); + status |= ad9361_reg_write(dev, 0x0016, 0x01); + time_out_cnt = 0; + do{ + status |= ad9361_reg_read(dev, 0x0016, &value); + mdelay(1);// Wait 1ms + time_out_cnt++; + } while((value & 0x01) != 0x00 && time_out_cnt <= TIMEOUT_TH); + + + status |= ad9361_reg_write(dev, 0x0185, 0x20); + status |= ad9361_reg_write(dev, 0x0186, 0x32); + status |= ad9361_reg_write(dev, 0x0187, 0x24); + status |= ad9361_reg_write(dev, 0x018B, 0x83); + status |= ad9361_reg_write(dev, 0x0188, 0x05); + status |= ad9361_reg_write(dev, 0x0189, 0x30); + status |= ad9361_reg_write(dev, 0x0016, 0x02); + time_out_cnt = 0; + do{ + status |= ad9361_reg_read(dev, 0x0016, &value); + mdelay(1);// Wait 1ms + time_out_cnt++; + } while((value & 0x01) != 0x00 && time_out_cnt <= TIMEOUT_TH); + + +//************************************************************ +// Tx Quadrature Calibration Settings +//************************************************************ + status |= ad9361_reg_write(dev, 0x00A0, 0x5F); + status |= ad9361_reg_write(dev, 0x00A3, 0x80); + status |= ad9361_reg_write(dev, 0x00A1, 0x7B); + status |= ad9361_reg_write(dev, 0x00A9, 0xFF); + status |= ad9361_reg_write(dev, 0x00A2, 0x7F); + status |= ad9361_reg_write(dev, 0x00A5, 0x01); + status |= ad9361_reg_write(dev, 0x00A6, 0x01); + status |= ad9361_reg_write(dev, 0x00AA, 0x28); + status |= ad9361_reg_write(dev, 0x00A4, 0xF0); + status |= ad9361_reg_write(dev, 0x00AE, 0x04); + + status |= ad9361_reg_write(dev, 0x0169, 0xC0); + status |= ad9361_reg_write(dev, 0x0016, 0x10); + time_out_cnt = 0; + do{ + status |= ad9361_reg_read(dev, 0x0016, &value); + mdelay(1);// Wait 1ms + time_out_cnt++; + } while((value & 0x10) != 0x00 && time_out_cnt <= TIMEOUT_TH); + + + status |= ad9361_reg_write(dev, 0x016A, 0x75); + status |= ad9361_reg_write(dev, 0x016B, 0x95); + status |= ad9361_reg_write(dev, 0x0169, 0xCF); + status |= ad9361_reg_write(dev, 0x018B, 0xAD); + status |= ad9361_reg_write(dev, 0x0012, 0x02); + status |= ad9361_reg_write(dev, 0x0013, 0x01); + status |= ad9361_reg_write(dev, 0x0015, 0x0C); + +//************************************************************ +// Set Tx Attenuation: Tx1: 0.00 dB, Tx2: 0.00 dB +//************************************************************ + status |= ad9361_reg_write(dev, 0x0073, 0x00); + status |= ad9361_reg_write(dev, 0x0074, 0x00); + status |= ad9361_reg_write(dev, 0x0075, 0x00); + status |= ad9361_reg_write(dev, 0x0076, 0x00); +//************************************************************ +// Setup RSSI and Power Measurement Duration Registers +//************************************************************ + status |= ad9361_reg_write(dev, 0x0150, 0x0E); + status |= ad9361_reg_write(dev, 0x0151, 0x00); + status |= ad9361_reg_write(dev, 0x0152, 0xFF); + status |= ad9361_reg_write(dev, 0x0153, 0x00); + status |= ad9361_reg_write(dev, 0x0154, 0x00); + status |= ad9361_reg_write(dev, 0x0155, 0x00); + status |= ad9361_reg_write(dev, 0x0156, 0x00); + status |= ad9361_reg_write(dev, 0x0157, 0x00); + status |= ad9361_reg_write(dev, 0x0158, 0x0D); + status |= ad9361_reg_write(dev, 0x015C, 0x67); + +//************************************************************ +// Enable External LO & External VCO Buffer +//************************************************************ + status |= ad9361_reg_write(dev, 0x0005, 0x07); + status |= ad9361_reg_write(dev, 0x0057, 0x1C); + + return status; +} + + +//uint32_t ad9361_reg_config(struct ad9361_reg_dev *dev){ +// int32_t status = 0; +// uint8_t value = 0; +// int32_t time_out_cnt = 0; +////************************************************************ +//// AD9361 R2 Auto Generated Initialization Script: This script was +//// generated using the AD9361 Customer software Version 2.1.3 +////************************************************************ +//// Profile: Custom +//// REFCLK_IN: 25.000 MHz +// +// status |= ad9361_reg_write(dev, 0x0001, 0x08); +// status |= ad9361_reg_write(dev, 0x03DF, 0x01); +// status |= ad9361_reg_write(dev, 0x02A6, 0x0E); +// status |= ad9361_reg_write(dev, 0x02A8, 0x0E); +// status |= ad9361_reg_write(dev, 0x02AB, 0x07); +// status |= ad9361_reg_write(dev, 0x02AC, 0xFF); +// status |= ad9361_reg_write(dev, 0x0009, 0x17); +// mdelay(20); // Wait 20 ms +// +////************************************************************ +//// Set BBPLL Frequency: 768.000000 +////************************************************************ +// status |= ad9361_reg_write(dev, 0x0045, 0x03); +// status |= ad9361_reg_write(dev, 0x0046, 0x02); +// status |= ad9361_reg_write(dev, 0x0048, 0xE8); +// status |= ad9361_reg_write(dev, 0x0049, 0x5B); +// status |= ad9361_reg_write(dev, 0x004A, 0x35); +// status |= ad9361_reg_write(dev, 0x004B, 0xE0); +// status |= ad9361_reg_write(dev, 0x004E, 0x10); +// status |= ad9361_reg_write(dev, 0x0043, 0x9A); +// status |= ad9361_reg_write(dev, 0x0042, 0x79); +// status |= ad9361_reg_write(dev, 0x0041, 0x0B); +// status |= ad9361_reg_write(dev, 0x0044, 0x0F); +// status |= ad9361_reg_write(dev, 0x003F, 0x05); +// status |= ad9361_reg_write(dev, 0x003F, 0x01); +// status |= ad9361_reg_write(dev, 0x004C, 0x86); +// status |= ad9361_reg_write(dev, 0x004D, 0x01); +// status |= ad9361_reg_write(dev, 0x004D, 0x05); +// time_out_cnt = 0; +// do{ +// status |= ad9361_reg_read(dev, 0x005E, &value); +// mdelay(1);// Wait 1ms +// time_out_cnt++; +// } while((value & 0x80) != 0x80 && time_out_cnt <= TIMEOUT_TH); +// +// +// +// status |= ad9361_reg_write(dev, 0x0002, 0x9C); +// status |= ad9361_reg_write(dev, 0x0003, 0xDC); +// status |= ad9361_reg_write(dev, 0x0004, 0x03); +// status |= ad9361_reg_write(dev, 0x000A, 0x12); +// +////************************************************************ +//// Setup the Parallel Port (Digital Data Interface) +////************************************************************ +// status |= ad9361_reg_write(dev, 0x0010, 0xC8); +// status |= ad9361_reg_write(dev, 0x0011, 0x00); +// status |= ad9361_reg_write(dev, 0x0012, 0x02); +// status |= ad9361_reg_write(dev, 0x0006, 0x00); +// status |= ad9361_reg_write(dev, 0x0007, 0x0F); +// +////************************************************************ +//// Setup AuxDAC +////************************************************************ +// status |= ad9361_reg_write(dev, 0x0018, 0x00); +// status |= ad9361_reg_write(dev, 0x0019, 0x00); +// status |= ad9361_reg_write(dev, 0x001A, 0x00); +// status |= ad9361_reg_write(dev, 0x001B, 0x00); +// status |= ad9361_reg_write(dev, 0x0023, 0xFF); +// status |= ad9361_reg_write(dev, 0x0026, 0x00); +// status |= ad9361_reg_write(dev, 0x0030, 0x00); +// status |= ad9361_reg_write(dev, 0x0031, 0x00); +// status |= ad9361_reg_write(dev, 0x0032, 0x00); +// status |= ad9361_reg_write(dev, 0x0033, 0x00); +// +////************************************************************ +//// Setup AuxADC +////************************************************************ +// status |= ad9361_reg_write(dev, 0x000B, 0x00); +// status |= ad9361_reg_write(dev, 0x000C, 0x00); +// status |= ad9361_reg_write(dev, 0x000D, 0x03); +// status |= ad9361_reg_write(dev, 0x000F, 0x04); +// status |= ad9361_reg_write(dev, 0x001C, 0x00); +// status |= ad9361_reg_write(dev, 0x001D, 0x01); +// +////************************************************************ +//// Setup Control Outs +////************************************************************ +// status |= ad9361_reg_write(dev, 0x0035, 0x00); +// status |= ad9361_reg_write(dev, 0x0036, 0xFF); +// +////************************************************************ +//// Setup GPO +////************************************************************ +// status |= ad9361_reg_write(dev, 0x003A, 0x18); +// status |= ad9361_reg_write(dev, 0x0020, 0x00); +// status |= ad9361_reg_write(dev, 0x0027, 0x00); +// status |= ad9361_reg_write(dev, 0x0028, 0x00); +// status |= ad9361_reg_write(dev, 0x0029, 0x00); +// status |= ad9361_reg_write(dev, 0x002A, 0x00); +// status |= ad9361_reg_write(dev, 0x002B, 0x00); +// status |= ad9361_reg_write(dev, 0x002C, 0x00); +// status |= ad9361_reg_write(dev, 0x002D, 0x00); +// status |= ad9361_reg_write(dev, 0x002E, 0x00); +// status |= ad9361_reg_write(dev, 0x002F, 0x00); +// +////************************************************************ +//// Setup RF PLL non-frequency-dependent registers +////************************************************************ +// status |= ad9361_reg_write(dev, 0x0261, 0x00); +// status |= ad9361_reg_write(dev, 0x02A1, 0x00); +// status |= ad9361_reg_write(dev, 0x0248, 0x0B); +// status |= ad9361_reg_write(dev, 0x0288, 0x0B); +// status |= ad9361_reg_write(dev, 0x0246, 0x02); +// status |= ad9361_reg_write(dev, 0x0286, 0x02); +// status |= ad9361_reg_write(dev, 0x0249, 0x8E); +// status |= ad9361_reg_write(dev, 0x0289, 0x8E); +// status |= ad9361_reg_write(dev, 0x023B, 0x80); +// status |= ad9361_reg_write(dev, 0x027B, 0x80); +// status |= ad9361_reg_write(dev, 0x0243, 0x0D); +// status |= ad9361_reg_write(dev, 0x0283, 0x0D); +// status |= ad9361_reg_write(dev, 0x023D, 0x00); +// status |= ad9361_reg_write(dev, 0x027D, 0x00); +// +// status |= ad9361_reg_write(dev, 0x0015, 0x0C); +// status |= ad9361_reg_write(dev, 0x0014, 0x1D); +// status |= ad9361_reg_write(dev, 0x0013, 0x01); +// mdelay(1); // Wait 1 ms +// +// status |= ad9361_reg_write(dev, 0x023D, 0x04); +// time_out_cnt = 0; +// do{ +// status |= ad9361_reg_read(dev, 0x0244, &value); +// mdelay(1);// Wait 1ms +// time_out_cnt++; +// } while((value & 0x80) != 0x80 && time_out_cnt <= TIMEOUT_TH); +// +// +// status |= ad9361_reg_write(dev, 0x027D, 0x04); +// time_out_cnt = 0; +// do{ +// status |= ad9361_reg_read(dev, 0x0284, &value); +// mdelay(1);// Wait 1ms +// time_out_cnt++; +// } while((value & 0x80) != 0x80 && time_out_cnt <= TIMEOUT_TH); +// +// +// status |= ad9361_reg_write(dev, 0x023D, 0x00); +// status |= ad9361_reg_write(dev, 0x027D, 0x00); +////************************************************************ +//// FDD RX,TX Synth Frequency: 125.000000,4125.000000 MHz +////************************************************************ +////************************************************************ +//// Setup Rx Frequency-Dependent Syntheisizer Registers +////************************************************************ +// status |= ad9361_reg_write(dev, 0x023A, 0x4A); +// status |= ad9361_reg_write(dev, 0x0239, 0xC1); +// status |= ad9361_reg_write(dev, 0x0242, 0x0E); +// status |= ad9361_reg_write(dev, 0x0238, 0x78); +// status |= ad9361_reg_write(dev, 0x0245, 0x00); +// status |= ad9361_reg_write(dev, 0x0251, 0x0B); +// status |= ad9361_reg_write(dev, 0x0250, 0x70); +// status |= ad9361_reg_write(dev, 0x023B, 0x94); +// status |= ad9361_reg_write(dev, 0x023E, 0xF4); +// status |= ad9361_reg_write(dev, 0x023F, 0xDF); +// status |= ad9361_reg_write(dev, 0x0240, 0x0A); +// +////************************************************************ +//// Setup Tx Frequency-Dependent Syntheisizer Registers +////************************************************************ +// status |= ad9361_reg_write(dev, 0x027A, 0x4A); +// status |= ad9361_reg_write(dev, 0x0279, 0xC1); +// status |= ad9361_reg_write(dev, 0x0282, 0x0E); +// status |= ad9361_reg_write(dev, 0x0278, 0x78); +// status |= ad9361_reg_write(dev, 0x0285, 0x00); +// status |= ad9361_reg_write(dev, 0x0291, 0x0B); +// status |= ad9361_reg_write(dev, 0x0290, 0x70); +// status |= ad9361_reg_write(dev, 0x027B, 0x93); +// status |= ad9361_reg_write(dev, 0x027E, 0xF4); +// status |= ad9361_reg_write(dev, 0x027F, 0xDF); +// status |= ad9361_reg_write(dev, 0x0280, 0x0A); +// +////************************************************************ +//// Write Rx and Tx Frequency Words +////************************************************************ +// status |= ad9361_reg_write(dev, 0x0233, 0x00); +// status |= ad9361_reg_write(dev, 0x0234, 0x00); +// status |= ad9361_reg_write(dev, 0x0235, 0x00); +// status |= ad9361_reg_write(dev, 0x0232, 0x00); +// status |= ad9361_reg_write(dev, 0x0231, 0xA0); +// status |= ad9361_reg_write(dev, 0x0005, 0x05); +// status |= ad9361_reg_write(dev, 0x0273, 0x00); +// status |= ad9361_reg_write(dev, 0x0274, 0x00); +// status |= ad9361_reg_write(dev, 0x0275, 0x00); +// status |= ad9361_reg_write(dev, 0x0272, 0x00); +// status |= ad9361_reg_write(dev, 0x0271, 0xA5); +// status |= ad9361_reg_write(dev, 0x0005, 0x05); +// +////************************************************************ +//// Program Mixer GM Sub-table +////************************************************************ +// status |= ad9361_reg_write(dev, 0x013F, 0x02); +// status |= ad9361_reg_write(dev, 0x0138, 0x0F); +// status |= ad9361_reg_write(dev, 0x0139, 0x78); +// status |= ad9361_reg_write(dev, 0x013A, 0x00); +// status |= ad9361_reg_write(dev, 0x013B, 0x00); +// status |= ad9361_reg_write(dev, 0x013F, 0x06); +// status |= ad9361_reg_write(dev, 0x013C, 0x00); +// status |= ad9361_reg_write(dev, 0x013C, 0x00); +// status |= ad9361_reg_write(dev, 0x0138, 0x0E); +// status |= ad9361_reg_write(dev, 0x0139, 0x74); +// status |= ad9361_reg_write(dev, 0x013A, 0x00); +// status |= ad9361_reg_write(dev, 0x013B, 0x0D); +// status |= ad9361_reg_write(dev, 0x013F, 0x06); +// status |= ad9361_reg_write(dev, 0x013C, 0x00); +// status |= ad9361_reg_write(dev, 0x013C, 0x00); +// status |= ad9361_reg_write(dev, 0x0138, 0x0D); +// status |= ad9361_reg_write(dev, 0x0139, 0x70); +// status |= ad9361_reg_write(dev, 0x013A, 0x00); +// status |= ad9361_reg_write(dev, 0x013B, 0x15); +// status |= ad9361_reg_write(dev, 0x013F, 0x06); +// status |= ad9361_reg_write(dev, 0x013C, 0x00); +// status |= ad9361_reg_write(dev, 0x013C, 0x00); +// status |= ad9361_reg_write(dev, 0x0138, 0x0C); +// status |= ad9361_reg_write(dev, 0x0139, 0x6C); +// status |= ad9361_reg_write(dev, 0x013A, 0x00); +// status |= ad9361_reg_write(dev, 0x013B, 0x1B); +// status |= ad9361_reg_write(dev, 0x013F, 0x06); +// status |= ad9361_reg_write(dev, 0x013C, 0x00); +// status |= ad9361_reg_write(dev, 0x013C, 0x00); +// status |= ad9361_reg_write(dev, 0x0138, 0x0B); +// status |= ad9361_reg_write(dev, 0x0139, 0x68); +// status |= ad9361_reg_write(dev, 0x013A, 0x00); +// status |= ad9361_reg_write(dev, 0x013B, 0x21); +// status |= ad9361_reg_write(dev, 0x013F, 0x06); +// status |= ad9361_reg_write(dev, 0x013C, 0x00); +// status |= ad9361_reg_write(dev, 0x013C, 0x00); +// status |= ad9361_reg_write(dev, 0x0138, 0x0A); +// status |= ad9361_reg_write(dev, 0x0139, 0x64); +// status |= ad9361_reg_write(dev, 0x013A, 0x00); +// status |= ad9361_reg_write(dev, 0x013B, 0x25); +// status |= ad9361_reg_write(dev, 0x013F, 0x06); +// status |= ad9361_reg_write(dev, 0x013C, 0x00); +// status |= ad9361_reg_write(dev, 0x013C, 0x00); +// status |= ad9361_reg_write(dev, 0x0138, 0x09); +// status |= ad9361_reg_write(dev, 0x0139, 0x60); +// status |= ad9361_reg_write(dev, 0x013A, 0x00); +// status |= ad9361_reg_write(dev, 0x013B, 0x29); +// status |= ad9361_reg_write(dev, 0x013F, 0x06); +// status |= ad9361_reg_write(dev, 0x013C, 0x00); +// status |= ad9361_reg_write(dev, 0x013C, 0x00); +// status |= ad9361_reg_write(dev, 0x0138, 0x08); +// status |= ad9361_reg_write(dev, 0x0139, 0x5C); +// status |= ad9361_reg_write(dev, 0x013A, 0x00); +// status |= ad9361_reg_write(dev, 0x013B, 0x2C); +// status |= ad9361_reg_write(dev, 0x013F, 0x06); +// status |= ad9361_reg_write(dev, 0x013C, 0x00); +// status |= ad9361_reg_write(dev, 0x013C, 0x00); +// status |= ad9361_reg_write(dev, 0x0138, 0x07); +// status |= ad9361_reg_write(dev, 0x0139, 0x58); +// status |= ad9361_reg_write(dev, 0x013A, 0x00); +// status |= ad9361_reg_write(dev, 0x013B, 0x2F); +// status |= ad9361_reg_write(dev, 0x013F, 0x06); +// status |= ad9361_reg_write(dev, 0x013C, 0x00); +// status |= ad9361_reg_write(dev, 0x013C, 0x00); +// status |= ad9361_reg_write(dev, 0x0138, 0x06); +// status |= ad9361_reg_write(dev, 0x0139, 0x54); +// status |= ad9361_reg_write(dev, 0x013A, 0x00); +// status |= ad9361_reg_write(dev, 0x013B, 0x31); +// status |= ad9361_reg_write(dev, 0x013F, 0x06); +// status |= ad9361_reg_write(dev, 0x013C, 0x00); +// status |= ad9361_reg_write(dev, 0x013C, 0x00); +// status |= ad9361_reg_write(dev, 0x0138, 0x05); +// status |= ad9361_reg_write(dev, 0x0139, 0x50); +// status |= ad9361_reg_write(dev, 0x013A, 0x00); +// status |= ad9361_reg_write(dev, 0x013B, 0x33); +// status |= ad9361_reg_write(dev, 0x013F, 0x06); +// status |= ad9361_reg_write(dev, 0x013C, 0x00); +// status |= ad9361_reg_write(dev, 0x013C, 0x00); +// status |= ad9361_reg_write(dev, 0x0138, 0x04); +// status |= ad9361_reg_write(dev, 0x0139, 0x4C); +// status |= ad9361_reg_write(dev, 0x013A, 0x00); +// status |= ad9361_reg_write(dev, 0x013B, 0x34); +// status |= ad9361_reg_write(dev, 0x013F, 0x06); +// status |= ad9361_reg_write(dev, 0x013C, 0x00); +// status |= ad9361_reg_write(dev, 0x013C, 0x00); +// status |= ad9361_reg_write(dev, 0x0138, 0x03); +// status |= ad9361_reg_write(dev, 0x0139, 0x48); +// status |= ad9361_reg_write(dev, 0x013A, 0x00); +// status |= ad9361_reg_write(dev, 0x013B, 0x35); +// status |= ad9361_reg_write(dev, 0x013F, 0x06); +// status |= ad9361_reg_write(dev, 0x013C, 0x00); +// status |= ad9361_reg_write(dev, 0x013C, 0x00); +// status |= ad9361_reg_write(dev, 0x0138, 0x02); +// status |= ad9361_reg_write(dev, 0x0139, 0x30); +// status |= ad9361_reg_write(dev, 0x013A, 0x00); +// status |= ad9361_reg_write(dev, 0x013B, 0x3A); +// status |= ad9361_reg_write(dev, 0x013F, 0x06); +// status |= ad9361_reg_write(dev, 0x013C, 0x00); +// status |= ad9361_reg_write(dev, 0x013C, 0x00); +// status |= ad9361_reg_write(dev, 0x0138, 0x01); +// status |= ad9361_reg_write(dev, 0x0139, 0x18); +// status |= ad9361_reg_write(dev, 0x013A, 0x00); +// status |= ad9361_reg_write(dev, 0x013B, 0x3D); +// status |= ad9361_reg_write(dev, 0x013F, 0x06); +// status |= ad9361_reg_write(dev, 0x013C, 0x00); +// status |= ad9361_reg_write(dev, 0x013C, 0x00); +// status |= ad9361_reg_write(dev, 0x0138, 0x00); +// status |= ad9361_reg_write(dev, 0x0139, 0x00); +// status |= ad9361_reg_write(dev, 0x013A, 0x00); +// status |= ad9361_reg_write(dev, 0x013B, 0x3E); +// status |= ad9361_reg_write(dev, 0x013F, 0x06); +// status |= ad9361_reg_write(dev, 0x013C, 0x00); +// status |= ad9361_reg_write(dev, 0x013C, 0x00); +// status |= ad9361_reg_write(dev, 0x013F, 0x02); +// status |= ad9361_reg_write(dev, 0x013C, 0x00); +// status |= ad9361_reg_write(dev, 0x013C, 0x00); +// status |= ad9361_reg_write(dev, 0x013F, 0x00); +// +////************************************************************ +//// Program Rx Gain Tables with GainTable800MHz.csv +////************************************************************ +// +// status |= ad9361_reg_write(dev, 0x0137, 0x1A); +// status |= ad9361_reg_write(dev, 0x0130, 0x00); +// status |= ad9361_reg_write(dev, 0x0131, 0x00); +// status |= ad9361_reg_write(dev, 0x0132, 0x00); +// status |= ad9361_reg_write(dev, 0x0133, 0x20); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x01); +// status |= ad9361_reg_write(dev, 0x0131, 0x00); +// status |= ad9361_reg_write(dev, 0x0132, 0x00); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x02); +// status |= ad9361_reg_write(dev, 0x0131, 0x00); +// status |= ad9361_reg_write(dev, 0x0132, 0x00); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x03); +// status |= ad9361_reg_write(dev, 0x0131, 0x00); +// status |= ad9361_reg_write(dev, 0x0132, 0x01); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x04); +// status |= ad9361_reg_write(dev, 0x0131, 0x00); +// status |= ad9361_reg_write(dev, 0x0132, 0x02); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x05); +// status |= ad9361_reg_write(dev, 0x0131, 0x00); +// status |= ad9361_reg_write(dev, 0x0132, 0x03); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x06); +// status |= ad9361_reg_write(dev, 0x0131, 0x00); +// status |= ad9361_reg_write(dev, 0x0132, 0x04); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x07); +// status |= ad9361_reg_write(dev, 0x0131, 0x00); +// status |= ad9361_reg_write(dev, 0x0132, 0x05); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x08); +// status |= ad9361_reg_write(dev, 0x0131, 0x01); +// status |= ad9361_reg_write(dev, 0x0132, 0x03); +// status |= ad9361_reg_write(dev, 0x0133, 0x20); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x09); +// status |= ad9361_reg_write(dev, 0x0131, 0x01); +// status |= ad9361_reg_write(dev, 0x0132, 0x04); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x0A); +// status |= ad9361_reg_write(dev, 0x0131, 0x01); +// status |= ad9361_reg_write(dev, 0x0132, 0x05); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x0B); +// status |= ad9361_reg_write(dev, 0x0131, 0x01); +// status |= ad9361_reg_write(dev, 0x0132, 0x06); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x0C); +// status |= ad9361_reg_write(dev, 0x0131, 0x01); +// status |= ad9361_reg_write(dev, 0x0132, 0x07); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x0D); +// status |= ad9361_reg_write(dev, 0x0131, 0x01); +// status |= ad9361_reg_write(dev, 0x0132, 0x08); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x0E); +// status |= ad9361_reg_write(dev, 0x0131, 0x01); +// status |= ad9361_reg_write(dev, 0x0132, 0x09); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x0F); +// status |= ad9361_reg_write(dev, 0x0131, 0x01); +// status |= ad9361_reg_write(dev, 0x0132, 0x0A); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x10); +// status |= ad9361_reg_write(dev, 0x0131, 0x01); +// status |= ad9361_reg_write(dev, 0x0132, 0x0B); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x11); +// status |= ad9361_reg_write(dev, 0x0131, 0x01); +// status |= ad9361_reg_write(dev, 0x0132, 0x0C); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x12); +// status |= ad9361_reg_write(dev, 0x0131, 0x01); +// status |= ad9361_reg_write(dev, 0x0132, 0x0D); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x13); +// status |= ad9361_reg_write(dev, 0x0131, 0x01); +// status |= ad9361_reg_write(dev, 0x0132, 0x0E); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x14); +// status |= ad9361_reg_write(dev, 0x0131, 0x02); +// status |= ad9361_reg_write(dev, 0x0132, 0x09); +// status |= ad9361_reg_write(dev, 0x0133, 0x20); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x15); +// status |= ad9361_reg_write(dev, 0x0131, 0x02); +// status |= ad9361_reg_write(dev, 0x0132, 0x0A); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x16); +// status |= ad9361_reg_write(dev, 0x0131, 0x02); +// status |= ad9361_reg_write(dev, 0x0132, 0x0B); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x17); +// status |= ad9361_reg_write(dev, 0x0131, 0x02); +// status |= ad9361_reg_write(dev, 0x0132, 0x0C); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x18); +// status |= ad9361_reg_write(dev, 0x0131, 0x02); +// status |= ad9361_reg_write(dev, 0x0132, 0x0D); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x19); +// status |= ad9361_reg_write(dev, 0x0131, 0x02); +// status |= ad9361_reg_write(dev, 0x0132, 0x0E); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x1A); +// status |= ad9361_reg_write(dev, 0x0131, 0x02); +// status |= ad9361_reg_write(dev, 0x0132, 0x0F); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x1B); +// status |= ad9361_reg_write(dev, 0x0131, 0x02); +// status |= ad9361_reg_write(dev, 0x0132, 0x10); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x1C); +// status |= ad9361_reg_write(dev, 0x0131, 0x02); +// status |= ad9361_reg_write(dev, 0x0132, 0x2B); +// status |= ad9361_reg_write(dev, 0x0133, 0x20); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x1D); +// status |= ad9361_reg_write(dev, 0x0131, 0x02); +// status |= ad9361_reg_write(dev, 0x0132, 0x2C); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x1E); +// status |= ad9361_reg_write(dev, 0x0131, 0x04); +// status |= ad9361_reg_write(dev, 0x0132, 0x28); +// status |= ad9361_reg_write(dev, 0x0133, 0x20); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x1F); +// status |= ad9361_reg_write(dev, 0x0131, 0x04); +// status |= ad9361_reg_write(dev, 0x0132, 0x29); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x20); +// status |= ad9361_reg_write(dev, 0x0131, 0x04); +// status |= ad9361_reg_write(dev, 0x0132, 0x2A); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x21); +// status |= ad9361_reg_write(dev, 0x0131, 0x04); +// status |= ad9361_reg_write(dev, 0x0132, 0x2B); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x22); +// status |= ad9361_reg_write(dev, 0x0131, 0x24); +// status |= ad9361_reg_write(dev, 0x0132, 0x20); +// status |= ad9361_reg_write(dev, 0x0133, 0x20); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x23); +// status |= ad9361_reg_write(dev, 0x0131, 0x24); +// status |= ad9361_reg_write(dev, 0x0132, 0x21); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x24); +// status |= ad9361_reg_write(dev, 0x0131, 0x44); +// status |= ad9361_reg_write(dev, 0x0132, 0x20); +// status |= ad9361_reg_write(dev, 0x0133, 0x20); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x25); +// status |= ad9361_reg_write(dev, 0x0131, 0x44); +// status |= ad9361_reg_write(dev, 0x0132, 0x21); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x26); +// status |= ad9361_reg_write(dev, 0x0131, 0x44); +// status |= ad9361_reg_write(dev, 0x0132, 0x22); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x27); +// status |= ad9361_reg_write(dev, 0x0131, 0x44); +// status |= ad9361_reg_write(dev, 0x0132, 0x23); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x28); +// status |= ad9361_reg_write(dev, 0x0131, 0x44); +// status |= ad9361_reg_write(dev, 0x0132, 0x24); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x29); +// status |= ad9361_reg_write(dev, 0x0131, 0x44); +// status |= ad9361_reg_write(dev, 0x0132, 0x25); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x2A); +// status |= ad9361_reg_write(dev, 0x0131, 0x44); +// status |= ad9361_reg_write(dev, 0x0132, 0x26); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x2B); +// status |= ad9361_reg_write(dev, 0x0131, 0x44); +// status |= ad9361_reg_write(dev, 0x0132, 0x27); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x2C); +// status |= ad9361_reg_write(dev, 0x0131, 0x44); +// status |= ad9361_reg_write(dev, 0x0132, 0x28); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x2D); +// status |= ad9361_reg_write(dev, 0x0131, 0x44); +// status |= ad9361_reg_write(dev, 0x0132, 0x29); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x2E); +// status |= ad9361_reg_write(dev, 0x0131, 0x44); +// status |= ad9361_reg_write(dev, 0x0132, 0x2A); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x2F); +// status |= ad9361_reg_write(dev, 0x0131, 0x44); +// status |= ad9361_reg_write(dev, 0x0132, 0x2B); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x30); +// status |= ad9361_reg_write(dev, 0x0131, 0x44); +// status |= ad9361_reg_write(dev, 0x0132, 0x2C); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x31); +// status |= ad9361_reg_write(dev, 0x0131, 0x44); +// status |= ad9361_reg_write(dev, 0x0132, 0x2D); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x32); +// status |= ad9361_reg_write(dev, 0x0131, 0x44); +// status |= ad9361_reg_write(dev, 0x0132, 0x2E); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x33); +// status |= ad9361_reg_write(dev, 0x0131, 0x44); +// status |= ad9361_reg_write(dev, 0x0132, 0x2F); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x34); +// status |= ad9361_reg_write(dev, 0x0131, 0x44); +// status |= ad9361_reg_write(dev, 0x0132, 0x30); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x35); +// status |= ad9361_reg_write(dev, 0x0131, 0x44); +// status |= ad9361_reg_write(dev, 0x0132, 0x31); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x36); +// status |= ad9361_reg_write(dev, 0x0131, 0x44); +// status |= ad9361_reg_write(dev, 0x0132, 0x32); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x37); +// status |= ad9361_reg_write(dev, 0x0131, 0x64); +// status |= ad9361_reg_write(dev, 0x0132, 0x2E); +// status |= ad9361_reg_write(dev, 0x0133, 0x20); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x38); +// status |= ad9361_reg_write(dev, 0x0131, 0x64); +// status |= ad9361_reg_write(dev, 0x0132, 0x2F); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x39); +// status |= ad9361_reg_write(dev, 0x0131, 0x64); +// status |= ad9361_reg_write(dev, 0x0132, 0x30); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x3A); +// status |= ad9361_reg_write(dev, 0x0131, 0x64); +// status |= ad9361_reg_write(dev, 0x0132, 0x31); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x3B); +// status |= ad9361_reg_write(dev, 0x0131, 0x64); +// status |= ad9361_reg_write(dev, 0x0132, 0x32); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x3C); +// status |= ad9361_reg_write(dev, 0x0131, 0x64); +// status |= ad9361_reg_write(dev, 0x0132, 0x33); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x3D); +// status |= ad9361_reg_write(dev, 0x0131, 0x64); +// status |= ad9361_reg_write(dev, 0x0132, 0x34); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x3E); +// status |= ad9361_reg_write(dev, 0x0131, 0x64); +// status |= ad9361_reg_write(dev, 0x0132, 0x35); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x3F); +// status |= ad9361_reg_write(dev, 0x0131, 0x64); +// status |= ad9361_reg_write(dev, 0x0132, 0x36); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x40); +// status |= ad9361_reg_write(dev, 0x0131, 0x64); +// status |= ad9361_reg_write(dev, 0x0132, 0x37); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x41); +// status |= ad9361_reg_write(dev, 0x0131, 0x64); +// status |= ad9361_reg_write(dev, 0x0132, 0x38); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x42); +// status |= ad9361_reg_write(dev, 0x0131, 0x65); +// status |= ad9361_reg_write(dev, 0x0132, 0x38); +// status |= ad9361_reg_write(dev, 0x0133, 0x20); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x43); +// status |= ad9361_reg_write(dev, 0x0131, 0x66); +// status |= ad9361_reg_write(dev, 0x0132, 0x38); +// status |= ad9361_reg_write(dev, 0x0133, 0x20); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x44); +// status |= ad9361_reg_write(dev, 0x0131, 0x67); +// status |= ad9361_reg_write(dev, 0x0132, 0x38); +// status |= ad9361_reg_write(dev, 0x0133, 0x20); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x45); +// status |= ad9361_reg_write(dev, 0x0131, 0x68); +// status |= ad9361_reg_write(dev, 0x0132, 0x38); +// status |= ad9361_reg_write(dev, 0x0133, 0x20); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x46); +// status |= ad9361_reg_write(dev, 0x0131, 0x69); +// status |= ad9361_reg_write(dev, 0x0132, 0x38); +// status |= ad9361_reg_write(dev, 0x0133, 0x20); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x47); +// status |= ad9361_reg_write(dev, 0x0131, 0x6A); +// status |= ad9361_reg_write(dev, 0x0132, 0x38); +// status |= ad9361_reg_write(dev, 0x0133, 0x20); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x48); +// status |= ad9361_reg_write(dev, 0x0131, 0x6B); +// status |= ad9361_reg_write(dev, 0x0132, 0x38); +// status |= ad9361_reg_write(dev, 0x0133, 0x20); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x49); +// status |= ad9361_reg_write(dev, 0x0131, 0x6C); +// status |= ad9361_reg_write(dev, 0x0132, 0x38); +// status |= ad9361_reg_write(dev, 0x0133, 0x20); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x4A); +// status |= ad9361_reg_write(dev, 0x0131, 0x6D); +// status |= ad9361_reg_write(dev, 0x0132, 0x38); +// status |= ad9361_reg_write(dev, 0x0133, 0x20); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x4B); +// status |= ad9361_reg_write(dev, 0x0131, 0x6E); +// status |= ad9361_reg_write(dev, 0x0132, 0x38); +// status |= ad9361_reg_write(dev, 0x0133, 0x20); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x4C); +// status |= ad9361_reg_write(dev, 0x0131, 0x6F); +// status |= ad9361_reg_write(dev, 0x0132, 0x38); +// status |= ad9361_reg_write(dev, 0x0133, 0x20); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x4D); +// status |= ad9361_reg_write(dev, 0x0131, 0x00); +// status |= ad9361_reg_write(dev, 0x0132, 0x00); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x4E); +// status |= ad9361_reg_write(dev, 0x0131, 0x00); +// status |= ad9361_reg_write(dev, 0x0132, 0x00); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x4F); +// status |= ad9361_reg_write(dev, 0x0131, 0x00); +// status |= ad9361_reg_write(dev, 0x0132, 0x00); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x50); +// status |= ad9361_reg_write(dev, 0x0131, 0x00); +// status |= ad9361_reg_write(dev, 0x0132, 0x00); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x51); +// status |= ad9361_reg_write(dev, 0x0131, 0x00); +// status |= ad9361_reg_write(dev, 0x0132, 0x00); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x52); +// status |= ad9361_reg_write(dev, 0x0131, 0x00); +// status |= ad9361_reg_write(dev, 0x0132, 0x00); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x53); +// status |= ad9361_reg_write(dev, 0x0131, 0x00); +// status |= ad9361_reg_write(dev, 0x0132, 0x00); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x54); +// status |= ad9361_reg_write(dev, 0x0131, 0x00); +// status |= ad9361_reg_write(dev, 0x0132, 0x00); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x55); +// status |= ad9361_reg_write(dev, 0x0131, 0x00); +// status |= ad9361_reg_write(dev, 0x0132, 0x00); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x56); +// status |= ad9361_reg_write(dev, 0x0131, 0x00); +// status |= ad9361_reg_write(dev, 0x0132, 0x00); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x57); +// status |= ad9361_reg_write(dev, 0x0131, 0x00); +// status |= ad9361_reg_write(dev, 0x0132, 0x00); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x58); +// status |= ad9361_reg_write(dev, 0x0131, 0x00); +// status |= ad9361_reg_write(dev, 0x0132, 0x00); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x59); +// status |= ad9361_reg_write(dev, 0x0131, 0x00); +// status |= ad9361_reg_write(dev, 0x0132, 0x00); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0130, 0x5A); +// status |= ad9361_reg_write(dev, 0x0131, 0x00); +// status |= ad9361_reg_write(dev, 0x0132, 0x00); +// status |= ad9361_reg_write(dev, 0x0133, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1E); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x1A); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0134, 0x00); +// status |= ad9361_reg_write(dev, 0x0137, 0x00); +////************************************************************ +//// Setup Rx Manual Gain Registers +////************************************************************ +// status |= ad9361_reg_write(dev, 0x00FA, 0xE0); +// status |= ad9361_reg_write(dev, 0x00FB, 0x08); +// status |= ad9361_reg_write(dev, 0x00FC, 0x23); +// status |= ad9361_reg_write(dev, 0x00FD, 0x4C); +// status |= ad9361_reg_write(dev, 0x00FE, 0x44); +// status |= ad9361_reg_write(dev, 0x0100, 0x6F); +// status |= ad9361_reg_write(dev, 0x0104, 0x2F); +// status |= ad9361_reg_write(dev, 0x0105, 0x3A); +// status |= ad9361_reg_write(dev, 0x0107, 0x2B); +// status |= ad9361_reg_write(dev, 0x0108, 0x31); +// status |= ad9361_reg_write(dev, 0x0109, 0x00); +// status |= ad9361_reg_write(dev, 0x010A, 0x58); +// status |= ad9361_reg_write(dev, 0x010B, 0x00); +// status |= ad9361_reg_write(dev, 0x010C, 0x00); +// status |= ad9361_reg_write(dev, 0x010D, 0x18); +// status |= ad9361_reg_write(dev, 0x010E, 0x00); +// status |= ad9361_reg_write(dev, 0x0114, 0x30); +// status |= ad9361_reg_write(dev, 0x011A, 0x27); +// status |= ad9361_reg_write(dev, 0x0081, 0x00); +////************************************************************ +//// RX Baseband Filter Tuning (Real BW: 10.000000 MHz) 3dB Filter +//// Corner @ 14.000000 MHz) +////************************************************************ +// status |= ad9361_reg_write(dev, 0x01FB, 0x0A); +// status |= ad9361_reg_write(dev, 0x01FC, 0x00); +// status |= ad9361_reg_write(dev, 0x01F8, 0x07); +// status |= ad9361_reg_write(dev, 0x01F9, 0x1E); +// +// status |= ad9361_reg_write(dev, 0x01D5, 0x3F); +// status |= ad9361_reg_write(dev, 0x01C0, 0x03); +// status |= ad9361_reg_write(dev, 0x01E2, 0x02); +// status |= ad9361_reg_write(dev, 0x01E3, 0x02); +// status |= ad9361_reg_write(dev, 0x0016, 0x80); +// time_out_cnt = 0; +// do{ +// status |= ad9361_reg_read(dev, 0x0016, &value); +// mdelay(1);// Wait 1ms +// time_out_cnt++; +// } while((value & 0x80) != 0x00 && time_out_cnt <= TIMEOUT_TH); +// +// +// status |= ad9361_reg_write(dev, 0x01E2, 0x03); +// status |= ad9361_reg_write(dev, 0x01E3, 0x03); +////************************************************************ +//// TX Baseband Filter Tuning (Real BW: 10.000000 MHz) 3dB Filter +//// Corner @ 16.000000 MHz) +////************************************************************ +// status |= ad9361_reg_write(dev, 0x00D6, 0x06); +// status |= ad9361_reg_write(dev, 0x00D7, 0x1E); +// +// status |= ad9361_reg_write(dev, 0x00CA, 0x22); +// status |= ad9361_reg_write(dev, 0x0016, 0x40); +// time_out_cnt = 0; +// do{ +// status |= ad9361_reg_read(dev, 0x0016, &value); +// mdelay(1);// Wait 1ms +// time_out_cnt++; +// } while((value & 0x40) != 0x00 && time_out_cnt <= TIMEOUT_TH); +// +// +// status |= ad9361_reg_write(dev, 0x00CA, 0x26); +////************************************************************ +//// RX TIA Setup: Setup values scale based on RxBBF calibration +//// results. See information in Calibration Guide. +////************************************************************ +// status |= ad9361_reg_write(dev, 0x01DB, 0x20); +// status |= ad9361_reg_write(dev, 0x01DD, 0x00); +// status |= ad9361_reg_write(dev, 0x01DF, 0x00); +// status |= ad9361_reg_write(dev, 0x01DC, 0x63); +// status |= ad9361_reg_write(dev, 0x01DE, 0x63); +// +////************************************************************ +//// TX Secondary Filter Calibration Setup: Real Bandwidth +//// 10.000000MHz, 3dB Corner @ 50.000000MHz +////************************************************************ +// status |= ad9361_reg_write(dev, 0x00D2, 0x14); +// status |= ad9361_reg_write(dev, 0x00D1, 0x0C); +// status |= ad9361_reg_write(dev, 0x00D0, 0x56); +// +////************************************************************ +//// ADC Setup: Tune ADC Performance based on RX analog filter tune +//// corner. Real Bandwidth: 8.645313 MHz, ADC Clock Frequency: +//// 192.000000 MHz. The values in registers 0x200 - 0x227 need to be +//// calculated using the equations in the Calibration Guide. +////************************************************************ +// +// status |= ad9361_reg_write(dev, 0x0200, 0x00); +// status |= ad9361_reg_write(dev, 0x0201, 0x00); +// status |= ad9361_reg_write(dev, 0x0202, 0x00); +// status |= ad9361_reg_write(dev, 0x0203, 0x24); +// status |= ad9361_reg_write(dev, 0x0204, 0x24); +// status |= ad9361_reg_write(dev, 0x0205, 0x00); +// status |= ad9361_reg_write(dev, 0x0206, 0x00); +// status |= ad9361_reg_write(dev, 0x0207, 0x7B); +// status |= ad9361_reg_write(dev, 0x0208, 0x6B); +// status |= ad9361_reg_write(dev, 0x0209, 0x3B); +// status |= ad9361_reg_write(dev, 0x020A, 0x4A); +// status |= ad9361_reg_write(dev, 0x020B, 0x43); +// status |= ad9361_reg_write(dev, 0x020C, 0x4D); +// status |= ad9361_reg_write(dev, 0x020D, 0x41); +// status |= ad9361_reg_write(dev, 0x020E, 0x00); +// status |= ad9361_reg_write(dev, 0x020F, 0x7E); +// status |= ad9361_reg_write(dev, 0x0210, 0x7E); +// status |= ad9361_reg_write(dev, 0x0211, 0x7E); +// status |= ad9361_reg_write(dev, 0x0212, 0x48); +// status |= ad9361_reg_write(dev, 0x0213, 0x48); +// status |= ad9361_reg_write(dev, 0x0214, 0x48); +// status |= ad9361_reg_write(dev, 0x0215, 0x4B); +// status |= ad9361_reg_write(dev, 0x0216, 0x4B); +// status |= ad9361_reg_write(dev, 0x0217, 0x4B); +// status |= ad9361_reg_write(dev, 0x0218, 0x2E); +// status |= ad9361_reg_write(dev, 0x0219, 0x92); +// status |= ad9361_reg_write(dev, 0x021A, 0x16); +// status |= ad9361_reg_write(dev, 0x021B, 0x11); +// status |= ad9361_reg_write(dev, 0x021C, 0x92); +// status |= ad9361_reg_write(dev, 0x021D, 0x16); +// status |= ad9361_reg_write(dev, 0x021E, 0x11); +// status |= ad9361_reg_write(dev, 0x021F, 0x92); +// status |= ad9361_reg_write(dev, 0x0220, 0x16); +// status |= ad9361_reg_write(dev, 0x0221, 0x22); +// status |= ad9361_reg_write(dev, 0x0222, 0x23); +// status |= ad9361_reg_write(dev, 0x0223, 0x40); +// status |= ad9361_reg_write(dev, 0x0224, 0x40); +// status |= ad9361_reg_write(dev, 0x0225, 0x2C); +// status |= ad9361_reg_write(dev, 0x0226, 0x00); +// status |= ad9361_reg_write(dev, 0x0227, 0x00); +////************************************************************ +//// Setup and Run BB DC and RF DC Offset Calibrations +////************************************************************ +// status |= ad9361_reg_write(dev, 0x0193, 0x3F); +// status |= ad9361_reg_write(dev, 0x0190, 0x0F); +// status |= ad9361_reg_write(dev, 0x0194, 0x01); +// status |= ad9361_reg_write(dev, 0x0016, 0x01); +// time_out_cnt = 0; +// do{ +// status |= ad9361_reg_read(dev, 0x0016, &value); +// mdelay(1);// Wait 1ms +// time_out_cnt++; +// } while((value & 0x01) != 0x00 && time_out_cnt <= TIMEOUT_TH); +// +// +// status |= ad9361_reg_write(dev, 0x0185, 0x20); +// status |= ad9361_reg_write(dev, 0x0186, 0x32); +// status |= ad9361_reg_write(dev, 0x0187, 0x24); +// status |= ad9361_reg_write(dev, 0x018B, 0x83); +// status |= ad9361_reg_write(dev, 0x0188, 0x05); +// status |= ad9361_reg_write(dev, 0x0189, 0x30); +// status |= ad9361_reg_write(dev, 0x0016, 0x02); +// time_out_cnt = 0; +// do{ +// status |= ad9361_reg_read(dev, 0x0016, &value); +// mdelay(1);// Wait 1ms +// time_out_cnt++; +// } while((value & 0x01) != 0x00 && time_out_cnt <= TIMEOUT_TH); +// +// +////************************************************************ +//// Tx Quadrature Calibration Settings +////************************************************************ +// status |= ad9361_reg_write(dev, 0x00A0, 0x5F); +// status |= ad9361_reg_write(dev, 0x00A3, 0x80); +// status |= ad9361_reg_write(dev, 0x00A1, 0x7B); +// status |= ad9361_reg_write(dev, 0x00A9, 0xFF); +// status |= ad9361_reg_write(dev, 0x00A2, 0x7F); +// status |= ad9361_reg_write(dev, 0x00A5, 0x01); +// status |= ad9361_reg_write(dev, 0x00A6, 0x01); +// status |= ad9361_reg_write(dev, 0x00AA, 0x28); +// status |= ad9361_reg_write(dev, 0x00A4, 0xF0); +// status |= ad9361_reg_write(dev, 0x00AE, 0x04); +// +// status |= ad9361_reg_write(dev, 0x0169, 0xC0); +// status |= ad9361_reg_write(dev, 0x0016, 0x10); +// time_out_cnt = 0; +// do{ +// status |= ad9361_reg_read(dev, 0x0016, &value); +// mdelay(1);// Wait 1ms +// time_out_cnt++; +// } while((value & 0x10) != 0x00 && time_out_cnt <= TIMEOUT_TH); +// +// +// status |= ad9361_reg_write(dev, 0x016A, 0x75); +// status |= ad9361_reg_write(dev, 0x016B, 0x95); +// status |= ad9361_reg_write(dev, 0x0169, 0xCF); +// status |= ad9361_reg_write(dev, 0x018B, 0xAD); +// status |= ad9361_reg_write(dev, 0x0012, 0x02); +// status |= ad9361_reg_write(dev, 0x0013, 0x01); +// status |= ad9361_reg_write(dev, 0x0015, 0x0C); +// +////************************************************************ +//// Set Tx Attenuation: Tx1: 0.00 dB, Tx2: 0.00 dB +////************************************************************ +// status |= ad9361_reg_write(dev, 0x0073, 0x00); +// status |= ad9361_reg_write(dev, 0x0074, 0x00); +// status |= ad9361_reg_write(dev, 0x0075, 0x00); +// status |= ad9361_reg_write(dev, 0x0076, 0x00); +////************************************************************ +//// Setup RSSI and Power Measurement Duration Registers +////************************************************************ +// status |= ad9361_reg_write(dev, 0x0150, 0x0E); +// status |= ad9361_reg_write(dev, 0x0151, 0x00); +// status |= ad9361_reg_write(dev, 0x0152, 0xFF); +// status |= ad9361_reg_write(dev, 0x0153, 0x00); +// status |= ad9361_reg_write(dev, 0x0154, 0x00); +// status |= ad9361_reg_write(dev, 0x0155, 0x00); +// status |= ad9361_reg_write(dev, 0x0156, 0x00); +// status |= ad9361_reg_write(dev, 0x0157, 0x00); +// status |= ad9361_reg_write(dev, 0x0158, 0x0D); +// status |= ad9361_reg_write(dev, 0x015C, 0x67); +// +////************************************************************ +//// Enable External LO & External VCO Buffer +////************************************************************ +// status |= ad9361_reg_write(dev, 0x0005, 0x07); +// status |= ad9361_reg_write(dev, 0x0057, 0x1C); +// +// return status; +//} + diff --git a/datalink814_sp/src/dev_profile/ad9516_profile.c b/datalink814_sp/src/dev_profile/ad9516_profile.c new file mode 100644 index 0000000..7330455 --- /dev/null +++ b/datalink814_sp/src/dev_profile/ad9516_profile.c @@ -0,0 +1,89 @@ +#include "dev_profile.h" +#include "../config/app_config.h" +#include "../adi_noos/drivers/frequency/ad9516/ad9516.h" + + +static spi_init_param ad9516_spi_init = { + .device_id = SPI_DEVICE_ID, + .max_speed_hz = SPI_ENGINE_MAX_SPEED, + .mode = SPI_MODE_4, + .chip_select = SPI_CS_AD9516, + .platform_ops = SPI_OPS, + .extra = SPI_PARAM +}; + +struct ad9516_init_param ad9516_default_init_param = { + /* SPI */ + .spi_init = &ad9516_spi_init +}; + +const uint32_t ad9516_default_config_len = 66; +const struct ad9516_config ad9516_default_config[] = { + {0x0000,0x18}, // 16-bit instruction, MSB first, 3-wire SPI + {0x0004,0x00}, // reads back buffer registers + {0x0010,0x7C}, + {0x0011,0x04}, // R divider LSBs, R = 4 + {0x0012,0x00}, // R divider MSBs, R = 4 + {0x0013,0x08}, // A counter, A = 8 + {0x0014,0x09}, // B counter LSBs, B = 9 + {0x0015,0x00}, // B counter MSBs, B = 9 + {0x0016,0x04}, // Divide-by-8 (8/9 mode) + {0x0017,0x10}, // STATUS pin output: Prescaler output + {0x0018,0x06}, + {0x0019,0x80}, // R, A, B counters synchronous reset on SYNCB + {0x001A,0x00}, // LD pin output: Digital lock detect (high = lock, low = unlock) + {0x001B,0xA1}, // enables VCO, REF1 frequency monitor; REFMON pin output: REF1 clock + {0x001C,0x07}, // selects REF1; REF1, REF2 power on; differential reference mode + {0x001D,0x00}, + {0x001E,0x00}, + {0x00A0,0x01}, + {0x00A1,0x00}, + {0x00A2,0x00}, + {0x00A3,0x01}, + {0x00A4,0x00}, + {0x00A5,0x00}, + {0x00A6,0x01}, + {0x00A7,0x00}, + {0x00A8,0x00}, + {0x00A9,0x01}, + {0x00AA,0x00}, + {0x00AB,0x00}, + {0x00F0,0x08}, + {0x00F1,0x08}, + {0x00F2,0x08}, + {0x00F3,0x08}, + {0x00F4,0x08}, + {0x00F5,0x08}, + {0x0140,0x59}, + {0x0141,0x5A}, + {0x0142,0x5A}, + {0x0143,0x42}, + {0x0190,0x33}, + {0x0191,0x40}, + {0x0192,0x00}, + {0x0193,0x33}, + {0x0194,0x40}, + {0x0195,0x00}, + {0x0196,0x44}, + {0x0197,0x40}, + {0x0198,0x00}, + {0x0199,0x99}, // divider 3.1, Low Cycles = 10, High Cycles = 10 + {0x019A,0x00}, + {0x019B,0x00}, // divider 3.1, Low Cycles = 1, High Cycles = 1 + {0x019C,0x00}, + {0x019D,0x00}, +// {0x019E,0xFF}, + {0x019E,0x11}, + {0x019F,0x00}, + {0x01A0,0x11}, + {0x01A1,0x20}, + {0x01A2,0x00}, + {0x01A3,0x00}, + {0x01E0,0x00}, + {0x01E1,0x02}, + {0x0230,0x00}, + {0x0231,0x00}, + {0x0232,0x01}, // Update all registers + {0x0018,0x07}, // initiate the VCO calibration + {0x0232,0x01} // Update all registers +}; diff --git a/datalink814_sp/src/dev_profile/dev_profile.h b/datalink814_sp/src/dev_profile/dev_profile.h new file mode 100644 index 0000000..9da7bd2 --- /dev/null +++ b/datalink814_sp/src/dev_profile/dev_profile.h @@ -0,0 +1,42 @@ +#ifndef DEV_PROFILE_H_ +#define DEV_PROFILE_H_ + +#include +#include "../config/app_config.h" +#include "../adi_noos/include/spi.h" +#include "../adi_noos/include/gpio.h" +#include "../adi_noos/include/delay.h" +#include "../adi_noos/include/irq.h" +#include "../adi_noos/include/error.h" +#include "../adi_noos/drivers/rf-transceiver/ad9361_reg/ad9361_reg.h" +#include "../adi_noos/drivers/frequency/ad9516/ad9516.h" + +// Platform includes +#include "../adi_noos/drivers/platform/spi_extra.h" +#include "../adi_noos/drivers/platform/gpio_extra.h" +#include "../adi_noos/drivers/platform/irq_extra.h" + +// AXI-Cores includes +#include "../adi_noos/drivers/axi_core/spi_engine/spi_engine.h" + +// Declare in mian.c +extern struct spi_engine_init_param spi_engine_param; +extern struct xil_gpio_init_param xil_gpio_param; + +#define GPIO_PARAM &xil_gpio_param +#define SPI_PARAM &spi_engine_param +#define GPIO_OPS &xil_gpio_ops +#define SPI_OPS &spi_eng_platform_ops + +extern struct ad9516_init_param ad9516_default_init_param; +extern const struct ad9516_config ad9516_default_config[]; +extern const uint32_t ad9516_default_config_len; + +extern struct ad9361_reg_init_param ad9361_1_reg_default_init_param; +extern struct ad9361_reg_init_param ad9361_2_reg_default_init_param; + +uint32_t ad9361_reg_config(struct ad9361_reg_dev *dev); +uint32_t ad9361_1_reg_config(struct ad9361_reg_dev *dev); +uint32_t ad9361_2_reg_config(struct ad9361_reg_dev *dev); + +#endif /* SRC_DEV_PROFILE_H_ */ diff --git a/datalink814_sp/src/error.h b/datalink814_sp/src/error.h new file mode 120000 index 0000000..1c7de34 --- /dev/null +++ b/datalink814_sp/src/error.h @@ -0,0 +1 @@ +../../datalink814_ge/src/error.h \ No newline at end of file diff --git a/datalink814_sp/src/inter_comm/inter_comm.c b/datalink814_sp/src/inter_comm/inter_comm.c new file mode 100644 index 0000000..3739a33 --- /dev/null +++ b/datalink814_sp/src/inter_comm/inter_comm.c @@ -0,0 +1,850 @@ +/*****************************************************************************/ +/** + * Description: Inter-Communication protocol implementation. + * + * Date: 2022-06-18 16:37 + * LastEditTime: 2023-04-24 17:38 + * Revisions: Rev 0.1 + * History: + * [2022-06-18]: Initial version. + * [2023-04-24]: Bug fix: + * - Read frame type from PL status register. + * + * Copyright(c) 2022 Beijing Institute of Technology. + * Lab of Communication and Networking + * +******************************************************************************/ +/***************************** Include Files *********************************/ +#include +#include +#include +#include +#include "inter_comm.h" +#include "../error.h" +#include "../util/util.h" +#include "../phy_ctrl/phy_ctrl.h" + +/************************** Constant Definitions *****************************/ +/***************** Macros (Inline Functions) Definitions *********************/ +/************************** Function Prototypes ******************************/ +static uint64_t GetTimeWord(uint8_t* buffPtr); +static uint32_t GetMsgLen(uint8_t msgCode); +static int32_t EvalPhyConfig(INTER_COMM_INST* instPtr, uint8_t* msgPtr); +/**************************** Type Definitions *******************************/ +/************************** Variable Definitions *****************************/ + +/*****************************************************************************/ +/** + * @brief Get a 64 bit time word from specified buffer pointer. + * + * @param buffPtr + * + * @return 64bit unsigned timer word + * + ******************************************************************************/ +static uint64_t GetTimeWord(uint8_t* buffPtr){ + ASSERT(buffPtr != NULL); + uint64_t timeWord = 0; + timeWord |= (uint64_t)buffPtr[0]; + timeWord |= ((uint64_t)buffPtr[1])<<8; + timeWord |= ((uint64_t)buffPtr[2])<<16; + timeWord |= ((uint64_t)buffPtr[3])<<24; + timeWord |= ((uint64_t)buffPtr[4])<<32; + timeWord |= ((uint64_t)buffPtr[5])<<40; + timeWord |= ((uint64_t)buffPtr[6])<<48; + timeWord |= ((uint64_t)buffPtr[7])<<56; + return timeWord; +} + +/*****************************************************************************/ +/** + * @brief Invoke a glink message reception process, check data crc, test the + * validation of received data. + * + * @param instPtr a pointer to inter communication instance + * @param frameType + * + * @return SUCCESS + * ECRC crc check failed. + * + ******************************************************************************/ +static uint32_t GetMsgLen(uint8_t msgCode){ + switch(msgCode){ + case INTER_MSG_ST_REQ_CODE: + return INTER_MSG_ST_REQ_LEN; + case INTER_MSG_ST_RSP_CODE: + return INTER_MSG_ST_RSP_LEN; + case INTER_MSG_WAKE_REQ_CODE: + return INTER_MSG_WAKE_REQ_LEN; + case INTER_MSG_WAKE_RSP_CODE: + return INTER_MSG_WAKE_RSP_LEN; + case INTER_MSG_MODESW_CODE: + return INTER_MSG_MODESW_LEN; + case INTER_MSG_CTRL_CODE: + return INTER_MSG_CTRL_LEN; + case INTER_MSG_DSEGWR_CODE: + return INTER_MSG_DSEGWR_LEN; + case INTER_MSG_DSEGRD_CODE: + return INTER_MSG_DSEGRD_LEN; + case INTER_MSG_RT_CODE: + return INTER_MSG_RT_LEN; + default: + return INTER_MSG_LEN_NONE; + } +} + +/*****************************************************************************/ +/** + * @brief Evaluate glink command and get ready to receive/send the required + * frame. + * + * @param instPtr a pointer to inter communication instance + * @param msgPtr a pointer to message buffer + * + * @return SUCCESS + * EPARAM illegal command setting detected. + * EIGNORE unsupported command detected. + * + ******************************************************************************/ +static int32_t EvalPhyConfig(INTER_COMM_INST* instPtr, uint8_t* msgPtr){ + ASSERT(instPtr != NULL); + ASSERT(msgPtr != NULL); + int32_t Status; + PHY_INST* phyRef = instPtr->phyInstPtr; + L1_FRAME_TYPE frameType = L1_NONE_FRAME; + PHY_TOR_TYPE torState = PHY_TOR_SUSPEND; + PHY_ANT_BEAM_WIDTH beamWidth = ANT_BEAM_NONE; + uint32_t beamNo = 0; + + uint16_t msg_Recv = 0; + msg_Recv |= (uint16_t)msgPtr[TYPE_CODE_OFFSET]; + msg_Recv |= ((uint16_t)msgPtr[TYPE_CODE_OFFSET+1])<<8; + if(msg_Recv != INTER_MSG_CTRL_CODE){ + return EIGNORE; + } + + if(msgPtr[INTER_MSG_CTRL_TOR_OFFSET] == CTRL_TOR_TX){ + torState = PHY_TOR_TX; + } + else if(msgPtr[INTER_MSG_CTRL_TOR_OFFSET] == CTRL_TOR_RX){ + torState = PHY_TOR_RX; + } + else{ + DBG_ERROR("[PHY Control] Tx/Rx state cannot be recognized...\n\r"); + return EIGNORE; + } + instPtr->lastCtrlTimeTag = GetTimeWord(msgPtr+CTRL_TIME_OFFSET); + if(torState == PHY_TOR_TX){ + if(instPtr->lastCtrlTimeTag != instPtr->lastDataTimeTag){ + return EPARAM; + } + } + switch(msgPtr[CTRL_FRAME_TYPE_OFFSET]){ + case CTRL_FRAME_10K10MS: + frameType = L1_10KBPS_10MS_FRAME; + break; + case CTRL_FRAME_10K20MS: + frameType = L1_10KBPS_20MS_FRAME; + break; + case CTRL_FRAME_200K5MS: + frameType = L1_200KBPS_5MS_FRAME; + break; + case CTRL_FRAME_1M25MS: + frameType = L1_1M2BPS_5MS_FRAME; + break; + case CTRL_FRAME_2K20MS: + frameType = L1_2KBPS_20MS_FRAME; + break; + case CTRL_FRAME_2K100MS: + frameType = L1_2KBPS_100MS_FRAME; + break; + case CTRL_FRAME_40K10MS: + frameType = L1_40KBPS_10MS_FRAME; + break; + case CTRL_FRAME_40K20MS: + frameType = L1_40KBPS_20MS_FRAME; + break; + default: + DBG_ERROR("[PHY Control] Frame Type cannot be recognized...\n\r"); + return EIGNORE; + break; + } + // FIXME: no extra antenna in current stage + //////////////////////////////////// + // Antenna configurations + //////////////////////////////////// + // FIXME: no switch control in current stage + //////////////////////////////////// + // Switch configurations + //////////////////////////////////// + uint16_t hop_msg_Recv = 0; + hop_msg_Recv |= (uint16_t)msgPtr[INTER_MSG_CTRL_HOP_MODE_OFFSET]; + hop_msg_Recv |= ((uint16_t)msgPtr[INTER_MSG_CTRL_HOP_MODE_OFFSET+1])<<8; + if(hop_msg_Recv == CTRL_HOP_PRESET){ + phyRef->isPresetHop = true; + } + else if(hop_msg_Recv == CTRL_HOP_CONFIG){ + phyRef->isPresetHop = false; + } + else{ + DBG_ERROR("[PHY Control] Hopping Pattern Configure cannot be recognized...\n\r"); + DBG_WARNING("[PHY Control] Using default preset hopping pattern instead...\n\r"); + return EIGNORE; + } + if(phyRef->isPresetHop == false){ + Status = Phy_SetHopPattern(msgPtr+INTER_MSG_CTRL_HOP_PATTERN_OFFSET, + Phy_GetHopLength(frameType)); + if(Status != SUCCESS){ + return Status; + } + } + if(msgPtr[INTER_MSG_CTRL_BEAM_MODE_OFFSET] == BEAM_MODE_WIDE){ + beamWidth = ANT_BEAM_120; + } + else if(msgPtr[INTER_MSG_CTRL_BEAM_MODE_OFFSET] == BEAM_MODE_SUBNRW){ + beamWidth = ANT_BEAM_25; + } + else if(msgPtr[INTER_MSG_CTRL_BEAM_MODE_OFFSET] == BEAM_MODE_NRW){ + beamWidth = ANT_BEAM_8; + } + else{ + DBG_ERROR("[PHY Control] Beam Width Configure cannot be recognized...\n\r"); + DBG_WARNING("[PHY Control] Using default WILD beam (120 deg) instead...\n\r"); + return EIGNORE; + } + Status = Phy_SetBeamWidth(phyRef, beamWidth); + if(Status != SUCCESS){ + return Status; + } + beamNo = (uint32_t)msgPtr[INTER_MSG_CTRL_BEAM_NO_OFFSET]; + if((beamNolastCtrlTimeTag >> 32); + tmWord.frac_part = (uint32_t)(instPtr->lastCtrlTimeTag); + Status = Phy_SetTimeWord(phyRef, &tmWord, TIME_WORD_POLL); + Status = Phy_SetMode(phyRef, PHY_MODE_PULL); + Status = Phy_SetupNextSlot(phyRef, torState, frameType, instPtr->phySendBuff); + + if(Status != SUCCESS){ + return Status; + } + + instPtr->lastCtrlTimeTag = 0; + instPtr->lastDataTimeTag = 0; + return Status; +} + + +/*****************************************************************************/ +/** + * @brief Initialize the inter communication instance, allocate space for + * message buffers. + * + * @param instPtr a second rank pointer to inter communication instance + * @param configPtr a pointer to inter communication instance configuration + * set. + * + * @return SUCCESS + * EALLOC memory allocate failed. + * + ******************************************************************************/ +int32_t InterComm_Init(INTER_COMM_INST** instPtr, INTER_COMM_CONFIG* configPtr){ + int32_t Status; + if (configPtr == NULL) { + return EPARAM; + } + *instPtr = (INTER_COMM_INST*) malloc(sizeof(INTER_COMM_INST)); + if ((*instPtr) == NULL) { + return EALLOC; + } + memset(*instPtr, 0x00, sizeof(INTER_COMM_INST)); + (*instPtr)->rxRemain = 0; + (*instPtr)->txRemain = 0; + (*instPtr)->lastCtrlTimeTag = 0; + (*instPtr)->lastDataTimeTag = 0; + (*instPtr)->lastPhyTimeTag = 0; + (*instPtr)->phyInstPtr = configPtr->phyInstPtr; + (*instPtr)->data_send = configPtr->data_send; + (*instPtr)->data_recv = configPtr->data_recv; + (*instPtr)->isSleep = false; + + // Initial message buffer + (*instPtr)->recvBuff = calloc(INTER_MSG_LEN/sizeof(uint32_t), sizeof(uint32_t)); + if ((*instPtr)->recvBuff == NULL) { + Status = EALLOC; + goto init_failed; + } + (*instPtr)->sendBuff = calloc(INTER_MSG_LEN/sizeof(uint32_t), sizeof(uint32_t)); + if ((*instPtr)->sendBuff == NULL) { + Status = EALLOC; + goto init_failed; + } + + // Initial physical buffer + (*instPtr)->phyRecvBuff = calloc(TXRXDATA_MAX_LEN/sizeof(uint32_t), sizeof(uint32_t)); + if ((*instPtr)->phyRecvBuff == NULL) { + Status = EALLOC; + goto init_failed; + } + + (*instPtr)->phySendBuff = calloc(TXRXDATA_MAX_LEN/sizeof(uint32_t), sizeof(uint32_t)); + if ((*instPtr)->phySendBuff == NULL) { + Status = EALLOC; + goto init_failed; + } + return SUCCESS; +init_failed: + InterComm_Destroy(*instPtr); + return Status; +} + + +/*****************************************************************************/ +/** + * @brief Destroy the inter communication instance, free all allocated memory. + * + * @param instPtr a second rank pointer to inter communication instance + * + * @return NONE + * + ******************************************************************************/ +void InterComm_Destroy(INTER_COMM_INST* instPtr) { + if(instPtr == NULL) { + return; + } + free(instPtr->sendBuff); + free(instPtr->recvBuff); + free(instPtr->phySendBuff); + free(instPtr->phyRecvBuff); + free(instPtr); +} + +/*****************************************************************************/ +/** + * @brief Invoke a glink message reception process, check data crc, test the + * validation of received data. + * + * @param instPtr a pointer to inter communication instance + * @param frameType + * + * @return SUCCESS + * ECRC crc check failed. + * FAILURE command code cannot be recognized. + ******************************************************************************/ +int32_t InterComm_RecvMsg(INTER_COMM_INST* instPtr){ + bool ret; + int32_t Status; + uint32_t msgLen = 0; + uint8_t* msgRecvPtr = (uint8_t*)instPtr->recvBuff; + Status = instPtr->data_recv(msgRecvPtr, INTER_MSG_LEN); + msgLen = GetMsgLen(msgRecvPtr[TYPE_CODE_OFFSET]); + if(Status == SUCCESS){ + if(msgLen == INTER_MSG_LEN_NONE){ + return FAILURE; + } + ret = CrcCheck(msgRecvPtr, msgLen); + if(ret == true){ + return SUCCESS; + } + else{ + return ECRC; + } + } + return Status; +} + +/*****************************************************************************/ +/** + * @brief Invoke a data sending process, append crc check ro the send data. + * + * @param instPtr a pointer to inter communication instance + * @param dataLen length of the send data. + * + * @return SUCCESS + * FAILURE data too long, exceeded glink buffer length. + * + ******************************************************************************/ +int32_t InterComm_SendMsg(INTER_COMM_INST* instPtr, int32_t dataLen, uint16_t subAddr){ + int32_t Status; + if(dataLen > INTER_MSG_LEN){ + return FAILURE; + } + Status = AppendCrc((uint8_t*)instPtr->sendBuff, dataLen); + if(Status == SUCCESS){ + Status = instPtr->data_send((uint16_t*)instPtr->sendBuff, dataLen, subAddr); + } + return SUCCESS; +} + +/*****************************************************************************/ +/** + * @brief A full function of inter communication message handler, evaluate + * all the protocol command and response properly. + * + * @param instPtr a pointer to inter communication instance + * + * @return SUCCESS + * EDINVAL device in sleep mode, not functional. + * EIGNORE received a command not supported by current protocol. + * IGNORE_COMMAND_ERROR received a dummy command ignored by current protocol. + * + ******************************************************************************/ +int32_t InterComm_MsgHandler(INTER_COMM_INST* instPtr){ + ASSERT(instPtr != NULL); + int32_t Status = SUCCESS; + uint8_t* msgRecvPtr = (uint8_t*) instPtr->recvBuff; + uint8_t* msgSendPtr = (uint8_t*) instPtr->sendBuff; + uint16_t msg_Recv = 0; + msg_Recv |= (uint16_t)msgRecvPtr[TYPE_CODE_OFFSET]; + msg_Recv |= ((uint16_t)msgRecvPtr[TYPE_CODE_OFFSET+1])<<8; + + if(instPtr->isSleep == true){ + if(msg_Recv != INTER_MSG_WAKE_REQ_CODE){ + DBG_WARNING("Device is in sleep mode, ignore command..."); + return EDINVAL; + } + } + switch(msg_Recv){ + case INTER_MSG_ST_REQ_CODE:{ + uint16_t cmdCode = 0; + memset(msgSendPtr, 0x00, INTER_MSG_ST_RSP_LEN); + cmdCode |= (uint16_t)msgRecvPtr[ST_CMD_OFFSET]; + cmdCode |= ((uint16_t)msgRecvPtr[ST_CMD_OFFSET+1])<<8; + if(cmdCode == ST_CMD){ + //////////////////////// + // Run a self test... + ///////////////////////// + msgSendPtr[TYPE_CODE_OFFSET] = (uint8_t)INTER_MSG_ST_RSP_CODE; + msgSendPtr[TYPE_CODE_OFFSET+1] = (uint8_t)(INTER_MSG_ST_RSP_CODE>>8); + msgSendPtr[ST_RSP_STATE_OFFSET] = (uint8_t)ST_RSP_STATE_OK; + msgSendPtr[ST_RSP_STATE_OFFSET+1] = (uint8_t)(ST_RSP_STATE_OK>>8); + Status = InterComm_SendMsg(instPtr, INTER_MSG_ST_RSP_LEN, INTER_MSG_OTHER_ADDR); + } + else{ + return EIGNORE; + } + break; + } + case INTER_MSG_WAKE_REQ_CODE:{ + uint16_t cmdCode = 0; + memset(msgSendPtr, 0x00, INTER_MSG_WAKE_RSP_LEN); + cmdCode |= (uint16_t)msgRecvPtr[WAKE_CMD_OFFSET]; + cmdCode |= ((uint16_t)msgRecvPtr[WAKE_CMD_OFFSET+1])<<8; + if(cmdCode == WAKE_CMD_UP_LPW){ + if(instPtr->isSleep == true){ + DBG_WARNING("Device is already in sleep mode..."); + msgSendPtr[TYPE_CODE_OFFSET] = (uint8_t)INTER_MSG_WAKE_RSP_CODE; + msgSendPtr[TYPE_CODE_OFFSET+1] = (uint8_t)(INTER_MSG_WAKE_RSP_CODE>>8); + msgSendPtr[WAKE_CMD_OFFSET] = (uint8_t)WAKE_CMD_LPW_LPW; + msgSendPtr[WAKE_CMD_OFFSET+1] = (uint8_t)(WAKE_CMD_LPW_LPW>>8); + } + else{ + //////////////////////// + // Run a lowpower sleep routine... + ///////////////////////// + instPtr->isSleep = true; + msgSendPtr[TYPE_CODE_OFFSET] = (uint8_t)INTER_MSG_WAKE_RSP_CODE; + msgSendPtr[TYPE_CODE_OFFSET+1] = (uint8_t)(INTER_MSG_WAKE_RSP_CODE>>8); + msgSendPtr[WAKE_CMD_OFFSET] = (uint8_t)WAKE_CMD_UP_LPW; + msgSendPtr[WAKE_CMD_OFFSET+1] = (uint8_t)(WAKE_CMD_UP_LPW>>8); + } + } + else if(cmdCode == WAKE_CMD_LPW_UP){ + if(instPtr->isSleep == false){ + DBG_WARNING("Device is already in wake mode..."); + msgSendPtr[TYPE_CODE_OFFSET] = (uint8_t)INTER_MSG_WAKE_RSP_CODE; + msgSendPtr[TYPE_CODE_OFFSET+1] = (uint8_t)(INTER_MSG_WAKE_RSP_CODE>>8); + msgSendPtr[WAKE_CMD_OFFSET] = (uint8_t)WAKE_CMD_UP_UP; + msgSendPtr[WAKE_CMD_OFFSET+1] = (uint8_t)(WAKE_CMD_UP_UP>>8); + } + else{ + //////////////////////// + // Run a wake up routine... + ///////////////////////// + instPtr->isSleep = false; + msgSendPtr[TYPE_CODE_OFFSET] = (uint8_t)INTER_MSG_WAKE_RSP_CODE; + msgSendPtr[TYPE_CODE_OFFSET+1] = (uint8_t)(INTER_MSG_WAKE_RSP_CODE>>8); + msgSendPtr[WAKE_CMD_OFFSET] = (uint8_t)WAKE_CMD_LPW_UP; + msgSendPtr[WAKE_CMD_OFFSET+1] = (uint8_t)(WAKE_CMD_LPW_UP>>8); + } + } + else{ + return EIGNORE; + } + Status = InterComm_SendMsg(instPtr, INTER_MSG_WAKE_RSP_LEN,INTER_MSG_OTHER_ADDR); + break; + } + case INTER_MSG_MODESW_CODE:{ + if(msgRecvPtr[MODESW_MODE_OFFSET] == MODESW_MODE_NORMAL){ + Phy_SetMode(instPtr->phyInstPtr, PHY_MODE_PULL); + } + else if(msgRecvPtr[MODESW_MODE_OFFSET] == MODESW_MODE_NETSET){ + uint64_t timeTemp; + TIME_WORD tmWord; + timeTemp = GetTimeWord(msgRecvPtr + MODESW_START_TIME_OFFSET); + tmWord.int_part = (uint32_t)(timeTemp>>32);; + tmWord.frac_part = (uint32_t)(timeTemp); + Status = Phy_SetTimeWord(instPtr->phyInstPtr, &tmWord, TIME_WORD_POLL); + if(Status != SUCCESS){ + return EPARAM; + } + timeTemp = GetTimeWord(msgRecvPtr + MODESW_TIMEOUT_OFFSET); + if(timeTemp == 0){ + tmWord.frac_part = 0; + tmWord.int_part = 0; + Status = Phy_SetTimeWord(instPtr->phyInstPtr, &tmWord, TIME_WORD_LISTEN_TIMEOUT); + if(Status != SUCCESS){ + return EPARAM; + } + } + else{ + tmWord.frac_part += (uint32_t)(timeTemp); + tmWord.int_part += (uint32_t)(timeTemp>>32); + tmWord.int_part = (tmWord.frac_part >= TMWORD_FRAC_MAX) ? tmWord.int_part + 1:tmWord.int_part; + tmWord.frac_part %= TMWORD_FRAC_MAX; + Status = Phy_SetTimeWord(instPtr->phyInstPtr, &tmWord, TIME_WORD_LISTEN_TIMEOUT); + if(Status != SUCCESS){ + return EPARAM; + } + } + instPtr->phyInstPtr->isPresetHop = true ; + Status = Phy_SetMode(instPtr->phyInstPtr, PHY_MODE_LISTEN); + Status = Phy_SetupNextSlot(instPtr->phyInstPtr, PHY_TOR_RX, L1_10KBPS_20MS_FRAME, NULL); + } + else{ + return EPARAM; + } + break; + } + case INTER_MSG_CTRL_CODE:{ + Status = EvalPhyConfig(instPtr, msgRecvPtr); + break; + } + case INTER_MSG_DSEGWR_CODE:{ + uint16_t subPktLen; + uint8_t* phyTxBuff; + phyTxBuff= (uint8_t*)instPtr->phySendBuff; + subPktLen = (uint16_t)msgRecvPtr[DSEGWR_PDLEN_OFFSET]; + subPktLen |= ((uint16_t)msgRecvPtr[DSEGWR_PDLEN_OFFSET+1])<<8; + if(msgRecvPtr[DSEGWR_TYPE_OFFSET] == DSEGWR_TYPE_PKN){ + memcpy(phyTxBuff, msgRecvPtr+DSEGWR_PD_OFFSET, (size_t)subPktLen); + } + else if(msgRecvPtr[DSEGWR_TYPE_OFFSET] == DSEGWR_TYPE_PK1){ + memcpy(phyTxBuff, msgRecvPtr+DSEGWR_PD_OFFSET, (size_t)subPktLen); + } + else if(msgRecvPtr[DSEGWR_TYPE_OFFSET] == DSEGWR_TYPE_PK2){ + memcpy(phyTxBuff+DSEGWR_PD_LEN, msgRecvPtr+DSEGWR_PD_OFFSET, (size_t)subPktLen); + } + else if(msgRecvPtr[DSEGWR_TYPE_OFFSET] == DSEGWR_TYPE_PK3){ + memcpy(phyTxBuff+DSEGWR_PD_LEN*2, msgRecvPtr+DSEGWR_PD_OFFSET, (size_t)subPktLen); + } + else{ + return EPARAM; + } + // Store time tag last to prevent get a error command time tag + // e.g. if DSEGWR_TYPE not cannot be recognized, function will return + // in earlier stage, interComm instance won't get a time tag in a + // error command. + // FIXME: Check data integrity? + instPtr->lastDataTimeTag = GetTimeWord(msgRecvPtr+DSEGWR_TIME_OFFSET); + //////////////////////// + // Invoke a time sync process ... + ///////////////////////// + break; + } + default: + return FAILURE; + break; + } + return Status; +} + + +/*****************************************************************************/ +/** + * @brief Invoke a data sending process, append crc check ro the send data. + * + * @param instPtr a pointer to inter communication instance + * + * @return SUCCESS + * FAILURE data too long, exceeded glink buffer length. + * + ******************************************************************************/ +int32_t InterComm_SendRemotCheck(INTER_COMM_INST* instPtr, XSysMon* SysMonInstPtr, C2C_EXTRA* c2cExtraBuffPtr){ + ASSERT(instPtr != NULL); + ASSERT(SysMonInstPtr != NULL); + ASSERT(c2cExtraBuffPtr != NULL); + int32_t Status; + uint8_t* msgTxBuff = (uint8_t*) instPtr->sendBuff; + memset(msgTxBuff, 0x00, INTER_MSG_LEN); + + // Set message code + msgTxBuff[TYPE_CODE_OFFSET] = (uint8_t)(INTER_MSG_RT_CODE); + msgTxBuff[TYPE_CODE_OFFSET+1] = (uint8_t)(INTER_MSG_RT_CODE>>8); + + msgTxBuff[RT_PHY_OFFSET] = (uint8_t)(0x0003); + msgTxBuff[RT_PHY_OFFSET+1] = (uint8_t)(0x0003>>8); + + uint8_t* TimeBuff = (uint8_t*)(&(instPtr->lastPhyTimeTag)); + msgTxBuff[RT_TIME_OFFSET] = (uint8_t)(TimeBuff[0]); + msgTxBuff[RT_TIME_OFFSET+1] = (uint8_t)(TimeBuff[1]); + msgTxBuff[RT_TIME_OFFSET+2] = (uint8_t)(TimeBuff[2]); + msgTxBuff[RT_TIME_OFFSET+3] = (uint8_t)(TimeBuff[3]); + msgTxBuff[RT_TIME_OFFSET+4] = (uint8_t)(TimeBuff[4]); + msgTxBuff[RT_TIME_OFFSET+5] = (uint8_t)(TimeBuff[5]); + msgTxBuff[RT_TIME_OFFSET+6] = (uint8_t)(TimeBuff[6]); + msgTxBuff[RT_TIME_OFFSET+7] = (uint8_t)(TimeBuff[7]); + + uint32_t VccAuxRawData; + uint16_t VccAuxData; + VccAuxRawData = XSysMon_GetAdcData(SysMonInstPtr,XSM_CH_VCCINT ); + VccAuxData = (int16_t)(XSysMon_RawToVoltage(VccAuxRawData)*10); + msgTxBuff[RT_SP_VOLT_OFFSET] = (uint8_t)(VccAuxData); + msgTxBuff[RT_SP_VOLT_OFFSET+1] = (uint8_t)(VccAuxData>>8); + + uint32_t TempRawData; + int16_t TempData; + TempRawData = XSysMon_GetAdcData(SysMonInstPtr, XSM_CH_TEMP); + TempData = (int16_t)(XSysMon_RawToTemperature(TempRawData)*10); + msgTxBuff[RT_SP_TEMP_OFFSET] = (uint8_t)(TempData); + msgTxBuff[RT_SP_TEMP_OFFSET+1] = (uint8_t)(TempData>>8); + + msgTxBuff[RT_SP_CHIP_OFFSET] = (uint8_t)(0x0001); + msgTxBuff[RT_SP_CHIP_OFFSET+1] = (uint8_t)(0x0001>>8); + + uint8_t* ExtraBuff = (uint8_t*)(c2cExtraBuffPtr->extra); + + msgTxBuff[RT_ANT_VOLT_OFFSET] = (uint8_t)(ExtraBuff[0]); + msgTxBuff[RT_ANT_VOLT_OFFSET+1] = (uint8_t)(ExtraBuff[1]); + + msgTxBuff[RT_ANT_TEMP_OFFSET] = (uint8_t)(ExtraBuff[2]); + msgTxBuff[RT_ANT_TEMP_OFFSET+1] = (uint8_t)(ExtraBuff[3]); + + msgTxBuff[RT_ANT_LOCK_OFFSET] = (uint8_t)(0x0001); + msgTxBuff[RT_ANT_LOCK_OFFSET+1] = (uint8_t)(0x0001>>8); + + msgTxBuff[RT_ANT_MGC_OFFSET] = (uint8_t)(0x0000); + msgTxBuff[RT_ANT_MGC_OFFSET+1] = (uint8_t)(0x0000>>8); + + msgTxBuff[RT_ANT_STATE_OFFSET] = (uint8_t)(0x0001); + msgTxBuff[RT_ANT_STATE_OFFSET+1] = (uint8_t)(0x0001>>8); + + Status = InterComm_SendMsg(instPtr, (int32_t)INTER_MSG_RT_LEN, INTER_MSG_RT_ADDR); + + return Status; +} + +/*****************************************************************************/ +/** + * @brief Invoke a data frame upload process, split the received data frame + * to multiple subpackages if needed, and send the send them in a properly + * order defined by inter communication protocol. + * + * @param instPtr a pointer to inter communication instance + * + * @return SUCCESS + * FAILURE frame cannot be recognized. + * EIGNORE received a command not supported by current protocol. + * IGNORE_COMMAND_ERROR received a dummy command ignored by current protocol. + * + ******************************************************************************/ +// FIXME: only support ONE physical device now. +int32_t InterComm_PhyDataUpload(INTER_COMM_INST* instPtr){ + int32_t Status; + uint32_t remainDataLen, numPkt, subPktLen; + uint8_t *txMsgBuff, *phyRxBuff; + L1_FRAME_TYPE lastFrameType; + + txMsgBuff = (uint8_t*)instPtr->sendBuff; + phyRxBuff = (uint8_t*)instPtr->phyRecvBuff; + lastFrameType = Phy_GetLastRecvFrameType(instPtr->phyInstPtr); + remainDataLen = Phy_GetFrameLen(lastFrameType); + if(remainDataLen == L1_FRAME_NONE_LEN){ + return FAILURE; + } + numPkt = 1 + ((remainDataLen - 1) / DSEGRD_PD_LEN); // dived and round up equals to ceil(x/y) + + if(numPkt > MSG_DSEGRD_SUBPKG_MAX){ + return FAILURE; + } + + txMsgBuff[TYPE_CODE_OFFSET] = (uint8_t)(INTER_MSG_DSEGRD_CODE); + txMsgBuff[TYPE_CODE_OFFSET+1] = (uint8_t)(INTER_MSG_DSEGRD_CODE>>8); + + // Time Estimate + uint32_t fsTimeL, fsTimeH; + fsTimeL = PhyRead(instPtr->phyInstPtr, FSTIME_L); + fsTimeH = PhyRead(instPtr->phyInstPtr, FSTIME_H); + instPtr->lastPhyTimeTag = fsTimeL; + instPtr->lastPhyTimeTag |= ((uint64_t)fsTimeH)<<32; + uint32_t timeComp = Phy_GetTimeComp(lastFrameType); + if(timeComp == L1_FRAME_NONE_COMP){ + return FAILURE; + } + fsTimeH -= timeComp/TMWORD_FRAC_MAX; + timeComp %= TMWORD_FRAC_MAX; + fsTimeH = (fsTimeL < timeComp)?(fsTimeH - 1):fsTimeH; + fsTimeL = (fsTimeL < timeComp)?(TMWORD_FRAC_MAX + fsTimeL - timeComp) : (fsTimeL - timeComp); + memcpy(txMsgBuff+DSEGRD_TIME_OFFSET, &fsTimeL, DSEGRD_TIME_LEN/2); + memcpy(txMsgBuff+DSEGRD_TIME_OFFSET + DSEGRD_TIME_LEN/2, &fsTimeH, DSEGRD_TIME_LEN/2); + + // Doppler Estimate + double doppler = Phy_GetCoarseFreqEst(instPtr->phyInstPtr); + // LSB = 0.001Hz + int64_t dopplerQnt = doppler*1000; + memcpy(txMsgBuff+DSEGRD_DPL_OFFSET, &dopplerQnt, DSEGRD_DPL_LEN); + + // Check if last frame is a initial acquisition frame + // L1_2KBPS_20MS_FRAME and L1_10KBPS_10MS_FRAME is initial acquisition frame + // if acquisition frame was received successfully, mark it out. + // + // when physical layer acquisition synchronization procedure is done successfully in + // acquisition frame reception period, initial acquisition is considered as success. + if(lastFrameType == L1_2KBPS_20MS_FRAME || lastFrameType == L1_10KBPS_10MS_FRAME){ + txMsgBuff[DSEGRD_IACQ_OFFSET] = (Phy_IsFrameDetected(instPtr->phyInstPtr)) ? 0xAA : 0xFF; + txMsgBuff[DSEGRD_IACQ_BEAM_OFFSET] = (Phy_IsFrameDetected(instPtr->phyInstPtr)) ? (uint8_t)instPtr->phyInstPtr->beamNo.last : 0xFF; + } + else{ + txMsgBuff[DSEGRD_IACQ_OFFSET] = 0xFF; + txMsgBuff[DSEGRD_IACQ_BEAM_OFFSET] = 0xFF; + } + + if(numPkt == 1){ + // Initialize payload segment. + memset(txMsgBuff+DSEGRD_PD_OFFSET, 0x00, (size_t)DSEGRD_PD_LEN); + subPktLen = remainDataLen; + txMsgBuff[DSEGRD_TYPE_OFFSET] = (uint8_t)DSEGRD_TYPE_PKN; + txMsgBuff[DSEGRD_TYPE_OFFSET+1] = (uint8_t)(DSEGRD_TYPE_PKN>>8); + txMsgBuff[DSEGRD_PDLEN_OFFSET] = (uint8_t)subPktLen; + txMsgBuff[DSEGRD_PDLEN_OFFSET+1] = (uint8_t)(subPktLen>>8); + memcpy(txMsgBuff+DSEGRD_PD_OFFSET, phyRxBuff, (size_t)subPktLen); + Status = InterComm_SendMsg(instPtr, (int32_t)INTER_MSG_DSEGWR_LEN, INTER_MSG_DSEGRD_PKN_ADDR); + if(Status != SUCCESS){ + return Status; + } + } + else{ + for(int32_t i = 0; i < numPkt; i++){ + // Initialize payload segment. + memset(txMsgBuff+DSEGRD_PD_OFFSET, 0x00, (size_t)DSEGRD_PD_LEN); + subPktLen = (remainDataLen >= DSEGRD_PD_LEN) ? DSEGRD_PD_LEN : remainDataLen; + remainDataLen = remainDataLen - subPktLen; + txMsgBuff[DSEGRD_PDLEN_OFFSET] = (uint8_t)subPktLen; + txMsgBuff[DSEGRD_PDLEN_OFFSET+1] = (uint8_t)(subPktLen>>8); + if(i == 0){ + txMsgBuff[DSEGRD_TYPE_OFFSET] = (uint8_t)DSEGRD_TYPE_PK1; + txMsgBuff[DSEGRD_TYPE_OFFSET+1] = (uint8_t)(DSEGRD_TYPE_PK1>>8); + memcpy(txMsgBuff+DSEGRD_PD_OFFSET, phyRxBuff+i*DSEGRD_PD_LEN, (size_t)subPktLen); + Status = InterComm_SendMsg(instPtr, (int32_t) INTER_MSG_DSEGWR_LEN, INTER_MSG_DSEGRD_PK1_ADDR); + } + else if(i == 1){ + txMsgBuff[DSEGRD_TYPE_OFFSET] = (uint8_t)DSEGRD_TYPE_PK2; + txMsgBuff[DSEGRD_TYPE_OFFSET+1] = (uint8_t)(DSEGRD_TYPE_PK2>>8); + memcpy(txMsgBuff+DSEGRD_PD_OFFSET, phyRxBuff+i*DSEGRD_PD_LEN, (size_t)subPktLen); + Status = InterComm_SendMsg(instPtr, (int32_t) INTER_MSG_DSEGWR_LEN, INTER_MSG_DSEGRD_PK2_ADDR); + } + else if(i == 2){ + txMsgBuff[DSEGRD_TYPE_OFFSET] = (uint8_t)DSEGRD_TYPE_PK3; + txMsgBuff[DSEGRD_TYPE_OFFSET+1] = (uint8_t)(DSEGRD_TYPE_PK3>>8); + memcpy(txMsgBuff+DSEGRD_PD_OFFSET, phyRxBuff+i*DSEGRD_PD_LEN, (size_t)subPktLen); + Status = InterComm_SendMsg(instPtr, (int32_t) INTER_MSG_DSEGWR_LEN, INTER_MSG_DSEGRD_PK3_ADDR); + } + else{ // should never reached. + return EUNEXP; + } + if(Status != SUCCESS){ + return Status; + } + } + } + return SUCCESS; +} + +/*****************************************************************************/ +/** + * @brief Append frame CRC-16 result to frame data buffer. + * + * @param buffPtr + * @param dataLen + * + * @return SUCCESS append successfully + * Other frame cannot be recognized. + * + ******************************************************************************/ +int AppendCrc(uint8_t* buffPtr, uint32_t dataLen) { + ASSERT(buffPtr != NULL); + int32_t Status = SUCCESS; + if (dataLen == 0) { + return FAILURE; + } + uint16_t crc = 0; + Status = crc16_gen(buffPtr, dataLen - COMMON_CRC_LEN, 0x1021, &crc); + if(Status != SUCCESS){ + DBG_ERROR("C2C gernerate failed, error code: %d.\r\n", Status); + } + uint8_t* crcSegPtr = (buffPtr + dataLen - COMMON_CRC_LEN); + +#ifdef CRC_COMPARE + *crcSegPtr = (uint8_t) crc & 0x00FF; + *(crcSegPtr + 1) = (uint8_t)((crc & 0xFF00) >> 8); +#else + *crcSegPtr = (uint8_t)((crc & 0xFF00) >> 8); (uint8_t) crc & 0x00FF; + *(crcSegPtr + 1) = (uint8_t) crc & 0x00FF; +#endif + return SUCCESS; +} + +/*****************************************************************************/ +/** + * @brief Check the frame CRC-16, witch can infer the frame should be dump + * or not. + * + * @param frameBuffPtr + * @param frameType + * + * @return true CRC check passed, good frame. + * false CRC check failed, bad frame. + * + ******************************************************************************/ +bool CrcCheck(uint8_t* buffPtr, uint32_t dataLen){ + if (dataLen == 0) { + return false; + } + bool ret = false; +#ifdef CRC_COMPARE + ret = crc16_check(buffPtr, dataLen - COMMON_CRC_LEN, dataLen - COMMON_CRC_LEN, 0x1021); +#else + uint16_t crc = 0; + uint32_t Status = 0; + Status = crc16_gen(buffPtr, dataLen, 0x1021, &crc); + if(Status != SUCCESS){ + DBG_ERROR("C2C gernerate failed, error code: %d.\r\n", Status); + } + ret = (crc == 0); +#endif + return ret; +} \ No newline at end of file diff --git a/datalink814_sp/src/inter_comm/inter_comm.h b/datalink814_sp/src/inter_comm/inter_comm.h new file mode 100644 index 0000000..de8c2a8 --- /dev/null +++ b/datalink814_sp/src/inter_comm/inter_comm.h @@ -0,0 +1,309 @@ +/*****************************************************************************/ +/** + * Description: Inter-Communication protocol, definitions and function + * prototypes. + * + * Date: 2022-06-18 16:37 + * LastEditTime: 2023-04-24 17:38 + * Revisions: Rev 0.2 + * History: + * [2022-06-18]: Initial version. + * [2023-04-24]: Bug fix: + * - Read frame type from PL status register. + * + * Copyright(c) 2022 Beijing Institute of Technology. + * Lab of Communication and Networking + * +******************************************************************************/ +#ifndef INTER_COMM_H_ +#define INTER_COMM_H_ + +/***************************** Include Files *********************************/ +#include +#include "../phy_ctrl/phy_ctrl.h" +#include "xsysmon.h" +#include "../config/app_config.h" + +/************************** Constant Definitions *****************************/ +#define COMMON_CRC_LEN 2 + +#define INTER_MSG_LEN 512 //Byte +#define INTER_MSG_CRC_LEN 2 +#define INTER_MSG_LEN_NONE UINT32_MAX + +#define TYPE_CODE_OFFSET 0x0000 + +// self test request +#define INTER_MSG_ST_REQ_LEN 0x00006 +#define INTER_MSG_ST_REQ_CODE 0x0011 +#define ST_CMD_OFFSET 0x0002 +#define ST_CMD_LEN 0x0002 +#define ST_CMD 0x1111 + +// self test response +#define INTER_MSG_ST_RSP_LEN 0x0008 +#define INTER_MSG_ST_RSP_CODE 0x0021 +#define ST_RSP_STATE_OFFSET 0x0002 +#define ST_RSP_STATE_LEN 0x0002 +#define ST_RSP_STATE_OK 0xAAAA +#define ST_RSP_STATE_ERR 0x5555 +#define ST_RSP_MASK1_OFFSET 0x0004 +#define ST_RSP_MASK1_LEN 0x0002 +#define ST_RSP_MASK2_OFFSET 0x0006 +#define ST_RSP_MASK2_LEN 0x0002 + +// wake up requirement/response +#define INTER_MSG_WAKE_REQ_LEN 0x0006 +#define INTER_MSG_WAKE_REQ_CODE 0x0012 +#define INTER_MSG_WAKE_RSP_LEN 0x0006 +#define INTER_MSG_WAKE_RSP_CODE 0x0022 +#define WAKE_CMD_OFFSET 0x0002 +#define WAKE_CMD_LEN 0x0002 +#define WAKE_CMD_LPW_LPW 0xFFAA +#define WAKE_CMD_UP_LPW 0xAAAA +#define WAKE_CMD_UP_UP 0xFFCC +#define WAKE_CMD_LPW_UP 0xCCCC + +// mode swicth command +#define INTER_MSG_MODESW_LEN 0x0016 // 20byte + crc +#define INTER_MSG_MODESW_CODE 0x0041 +#define MODESW_START_TIME_OFFSET 0x0002 +#define MODESW_START_TIME_LEN 0x0008 +#define MODESW_TIMEOUT_OFFSET 0x000A +#define MODESW_TIMEOUT_LEN 0x0008 +#define MODESW_MODE_OFFSET 0x0012 +#define MODESW_MODE_LEN 0x0002 +#define MODESW_MODE_NORMAL 0x0001 +#define MODESW_MODE_NETSET 0x0002 + +// physical layer control +#define INTER_MSG_CTRL_LEN 0x00BC // 186byte + 2byte crc +#define INTER_MSG_CTRL_CODE 0x0013 +#define CTRL_TIME_OFFSET 0x0002 +#define CTRL_TIME_LEN 0x0008 + +#define CTRL_FRAME_TYPE_OFFSET 0x000A +#define CTRL_FRAME_TYPE_LEN 0x0001 +#define CTRL_FRAME_10K10MS 0x01 +#define CTRL_FRAME_10K20MS 0x02 +#define CTRL_FRAME_200K5MS 0x03 +#define CTRL_FRAME_1M25MS 0x04 +#define CTRL_FRAME_2K20MS 0x05 +#define CTRL_FRAME_2K100MS 0x06 +#define CTRL_FRAME_40K10MS 0x07 +#define CTRL_FRAME_40K20MS 0x08 + +#define INTER_MSG_CTRL_ANT_OFFSET 0x000B +#define INTER_MSG_CTRL_ANT_LEN 0x0001 +#define CTRL_ANT_ALL 0x3F +#define CTRL_ANT_FRONT 0x01 +#define CTRL_ANT_3QUAD2 0x02 +#define CTRL_ANT_3QUAD4 0x04 +#define CTRL_ANT_BOTT 0x08 +#define CTRL_ANT_RSV1 0x10 +#define CTRL_ANT_RSV2 0x20 + +#define INTER_MSG_CTRL_TOR_OFFSET 0x000C +#define INTER_MSG_CTRL_TOR_LEN 0x0001 +#define CTRL_TOR_TX 0xAA +#define CTRL_TOR_RX 0xCC + +#define INTER_MSG_CTRL_SW_OFFSET 0x000D +#define INTER_MSG_CTRL_SW_LEN 0x0001 +#define CTRL_SW_PW BIT(0) +#define CTRL_SW_TR BIT(1) +#define CTRL_SW_TOR BIT(2) + +#define INTER_MSG_CTRL_HOP_MODE_OFFSET 0x000E +#define INTER_MSG_CTRL_HOP_MODE_LEN 0x0002 +#define CTRL_HOP_PRESET 0x2222 +#define CTRL_HOP_CONFIG 0x5555 + +#define INTER_MSG_CTRL_HOP_PATTERN_OFFSET 0x0010 +#define INTER_MSG_CTRL_HOP_PATTERN_LEN 0x00A2 + +#define INTER_MSG_CTRL_BEAM_MODE_OFFSET 0x00B2 +#define INTER_MSG_CTRL_BEAM_MODE_LEN 0x0001 +#define BEAM_MODE_WIDE 0x51 +#define BEAM_MODE_NRW 0x52 +#define BEAM_MODE_SUBNRW 0x53 + + +#define INTER_MSG_CTRL_BEAM_NO_OFFSET 0x00B3 +#define INTER_MSG_CTRL_BEAM_NO_LEN 0x0001 + +#define INTER_MSG_CTRL_AMP_WT_OFFSET 0x00B4 +#define INTER_MSG_CTRL_AMP_WT_LEN 0x0002 + +#define INTER_MSG_CTRL_OFFAX_OFFSET 0x00B6 +#define INTER_MSG_CTRL_OFFAX_LEN 0x0002 +#define INTER_MSG_CTRL_RNDAX_OFFSET 0x00B8 +#define INTER_MSG_CTRL_RNDAX_LEN 0x0002 + +// data segment write +#define MSG_DSEGWR_SUBPKG_MAX 3 +#define INTER_MSG_DSEGWR_LEN 0x0200 //510 byte + 2byte crc +#define INTER_MSG_DSEGWR_CODE 0x0014 +#define DSEGWR_TYPE_OFFSET 0x0002 +#define DSEGWR_TYPE_LEN 0x0002 +#define DSEGWR_TYPE_PKN 0x0010 +#define DSEGWR_TYPE_PK1 0x0012 +#define DSEGWR_TYPE_PK2 0x0013 +#define DSEGWR_TYPE_PK3 0x0014 +#define DSEGWR_TIME_OFFSET 0x0004 +#define DSEGWR_TIME_LEN 0x0008 +#define DSEGWR_PDLEN_OFFSET 0x000C +#define DSEGWR_PDLEN_LEN 0x0002 +#define DSEGWR_PD_OFFSET 0x000E +#define DSEGWR_PD_LEN 0x01F0 + +// data segment read +#define MSG_DSEGRD_SUBPKG_MAX 3 +#define INTER_MSG_DSEGRD_LEN 0x0200 //510 byte + 2byte crc +#define INTER_MSG_DSEGRD_CODE 0x0023 +#define DSEGRD_TYPE_OFFSET 0x0002 +#define DSEGRD_TYPE_LEN 0x0001 +#define DSEGRD_TYPE_PKN 0x0010 +#define DSEGRD_TYPE_PK1 0x0012 +#define DSEGRD_TYPE_PK2 0x0013 +#define DSEGRD_TYPE_PK3 0x0014 +#define DSEGRD_TIME_OFFSET 0x0004 +#define DSEGRD_TIME_LEN 0x0008 +#define DSEGRD_DPL_OFFSET 0x000C +#define DSEGRD_DPL_LEN 0x0008 +#define DSEGRD_PDLEN_OFFSET 0x0016 +#define DSEGRD_PDLEN_LEN 0x0002 +#define DSEGRD_IACQ_OFFSET 0x0014 +#define DSEGRD_IACQ_LEN 0x0001 +#define DSEGRD_IACQ_BEAM_OFFSET 0x0015 +#define DSEGRD_IACQ_BEAM_LEN 0x0001 +#define DSEGRD_PD_OFFSET 0x0018 +#define DSEGRD_PD_LEN 0x01E6 + +// Remote state test. +#define INTER_MSG_RT_LEN 0x0022 // 32 bytes + 2byte crc +#define INTER_MSG_RT_CODE 0x0031 // remote test. +#define RT_PHY_OFFSET 0x0002 +#define RT_PHY_LEN 0x0002 +#define RT_TIME_OFFSET 0x0004 +#define RT_TIME_LEN 0x0008 +#define RT_BEAM_OFFSET 0x000C +#define RT_BEAM_LEN 0x0004 +#define RT_SP_VOLT_OFFSET 0x0010 +#define RT_SP_VOLT_LEN 0x0002 +#define RT_SP_TEMP_OFFSET 0x0012 +#define RT_SP_TEMP_LEN 0x0002 +#define RT_SP_CHIP_OFFSET 0x0014 +#define RT_SP_CHIP_LEN 0x0002 + +#define RT_ANT_VOLT_OFFSET 0x0016 +#define RT_ANT_VOLT_LEN 0x0002 +#define RT_ANT_TEMP_OFFSET 0x0018 +#define RT_ANT_TEMP_LEN 0x0002 +#define RT_ANT_LOCK_OFFSET 0x001A +#define RT_ANT_LOCK_LEN 0x0001 +#define RT_ANT_MGC_OFFSET 0x001C +#define RT_ANT_MGC_LEN 0x0002 +#define RT_ANT_STATE_OFFSET 0x001E +#define RT_ANT_STATE_LEN 0x0001 + +#ifdef ANT_DEVICE_ID +#if ANT_DEVICE_ID == 0x0000 +#define INTER_MSG_DSEGRD_PKN_ADDR 0x0001 +#define INTER_MSG_DSEGRD_PK1_ADDR 0x0001 +#define INTER_MSG_DSEGRD_PK2_ADDR 0x0002 +#define INTER_MSG_DSEGRD_PK3_ADDR 0x0003 +#define INTER_MSG_RT_ADDR 0x0004 +#define INTER_MSG_OTHER_ADDR 0x0005 +#elif ANT_DEVICE_ID == 0x0001 +#define INTER_MSG_DSEGRD_PKN_ADDR 0x0006 +#define INTER_MSG_DSEGRD_PK1_ADDR 0x0006 +#define INTER_MSG_DSEGRD_PK2_ADDR 0x0007 +#define INTER_MSG_DSEGRD_PK3_ADDR 0x0008 +#define INTER_MSG_RT_ADDR 0x0009 +#define INTER_MSG_OTHER_ADDR 0x000A +#elif ANT_DEVICE_ID == 0x0002 +#define INTER_MSG_DSEGRD_PKN_ADDR 0x000B +#define INTER_MSG_DSEGRD_PK1_ADDR 0x000B +#define INTER_MSG_DSEGRD_PK2_ADDR 0x000C +#define INTER_MSG_DSEGRD_PK3_ADDR 0x000D +#define INTER_MSG_RT_ADDR 0x000E +#define INTER_MSG_OTHER_ADDR 0x000F +#elif ANT_DEVICE_ID == 0x0003 +#define INTER_MSG_DSEGRD_PKN_ADDR 0x0010 +#define INTER_MSG_DSEGRD_PK1_ADDR 0x0010 +#define INTER_MSG_DSEGRD_PK2_ADDR 0x0011 +#define INTER_MSG_DSEGRD_PK3_ADDR 0x0012 +#define INTER_MSG_RT_ADDR 0x0013 +#define INTER_MSG_OTHER_ADDR 0x0014 +#elif ANT_DEVICE_ID == 0x0004 +#define INTER_MSG_DSEGRD_PKN_ADDR 0x0015 +#define INTER_MSG_DSEGRD_PK1_ADDR 0x0015 +#define INTER_MSG_DSEGRD_PK2_ADDR 0x0016 +#define INTER_MSG_DSEGRD_PK3_ADDR 0x0017 +#define INTER_MSG_RT_ADDR 0x0018 +#define INTER_MSG_OTHER_ADDR 0x0019 +#elif ANT_DEVICE_ID == 0x0005 +#define INTER_MSG_DSEGRD_PKN_ADDR 0x001A +#define INTER_MSG_DSEGRD_PK1_ADDR 0x001A +#define INTER_MSG_DSEGRD_PK2_ADDR 0x001B +#define INTER_MSG_DSEGRD_PK3_ADDR 0x001C +#define INTER_MSG_RT_ADDR 0x001D +#define INTER_MSG_OTHER_ADDR 0x001E +#elif ANT_DEVICE_ID == 0x0006 +#else + #error Cannot Eval Antenna ID... +#endif +#else + #error Antenna ID must be specified... +#endif + + +/***************** Macros (Inline Functions) Definitions *********************/ + +/**************************** Type Definitions *******************************/ +typedef struct{ + PHY_INST* phyInstPtr; + int32_t (*data_send) (void* buffPtr, int32_t dataLen, uint16_t subAddr); + int32_t (*data_recv) (void* buffPtr, int32_t dataLen); +}INTER_COMM_CONFIG; + +// FIXME: only support ONE physical device now. +typedef struct{ + uint8_t* recvBuff; + uint8_t* sendBuff; + bool isSleep; + uint32_t rxRemain; + uint32_t txRemain; + uint64_t lastCtrlTimeTag; + uint64_t lastDataTimeTag; + uint64_t lastPhyTimeTag; + PHY_INST* phyInstPtr; + uint8_t* phyRecvBuff; + uint8_t* phySendBuff; + int32_t (*data_send) (void* buffPtr, int32_t dataLen, uint16_t subAddr); + int32_t (*data_recv) (void* buffPtr, int32_t buffSize); +}INTER_COMM_INST; + +typedef struct { + uint16_t glinkSubAddr; + uint8_t extra[14]; +} C2C_EXTRA; + +/************************** Variable Definitions *****************************/ + +/************************** Function Prototypes ******************************/ +int32_t InterComm_Init(INTER_COMM_INST** instPtr, INTER_COMM_CONFIG* configPtr); +void InterComm_Destroy(INTER_COMM_INST* instPtr); + +int32_t InterComm_RecvMsg(INTER_COMM_INST* instPtr); +int32_t InterComm_SendMsg(INTER_COMM_INST* instPtr, int32_t dataLen, uint16_t subAddr); + +int32_t InterComm_MsgHandler(INTER_COMM_INST* instPtr); +int32_t InterComm_SendRemotCheck(INTER_COMM_INST* instPtr, XSysMon* SysMonInstPtr, C2C_EXTRA* c2cExtraBuffPtr); +int32_t InterComm_PhyDataUpload(INTER_COMM_INST* instPtr); + +// Helper functions +int AppendCrc(uint8_t* buffPtr, uint32_t dataLen); +bool CrcCheck(uint8_t* buffPtr, uint32_t dataLen); +#endif diff --git a/datalink814_sp/src/lscript.ld b/datalink814_sp/src/lscript.ld new file mode 100644 index 0000000..c922b21 --- /dev/null +++ b/datalink814_sp/src/lscript.ld @@ -0,0 +1,217 @@ +/*******************************************************************/ +/* */ +/* This file is automatically generated by linker script generator.*/ +/* */ +/* Version: 2019.1.3 */ +/* */ +/* Copyright (c) 2010-2016 Xilinx, Inc. All rights reserved. */ +/* */ +/* Description : MicroBlaze Linker Script */ +/* */ +/*******************************************************************/ + +_STACK_SIZE = DEFINED(_STACK_SIZE) ? _STACK_SIZE : 0x4000; +_HEAP_SIZE = DEFINED(_HEAP_SIZE) ? _HEAP_SIZE : 0x8000; + +/* Define Memories in the system */ + +MEMORY +{ + microblaze_ps_local_memory_ilmb_bram_if_cntlr_Mem_microblaze_ps_local_memory_dlmb_bram_if_cntlr_Mem : ORIGIN = 0x50, LENGTH = 0x3FFB0 + ant_config_bram_ctrl_Mem0 : ORIGIN = 0xC0000000, LENGTH = 0x2000 + tx_frame_bram_ctrl_Mem0 : ORIGIN = 0xC2000000, LENGTH = 0x1000 + rx_frame_bram_ctrl_Mem0 : ORIGIN = 0xC4000000, LENGTH = 0x1000 + c2c_rx_axi_bram_ctrl_Mem0 : ORIGIN = 0xC6000000, LENGTH = 0x2000 + c2c_tx_axi_bram_ctrl_Mem0 : ORIGIN = 0xC8000000, LENGTH = 0x2000 +} + +/* Specify the default entry point to the program */ + +ENTRY(_start) + +/* Define the sections, and where they are mapped in memory */ + +SECTIONS +{ +.vectors.reset 0x0 : { + KEEP (*(.vectors.reset)) +} + +.vectors.sw_exception 0x8 : { + KEEP (*(.vectors.sw_exception)) +} + +.vectors.interrupt 0x10 : { + KEEP (*(.vectors.interrupt)) +} + +.vectors.hw_exception 0x20 : { + KEEP (*(.vectors.hw_exception)) +} + +.text : { + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) +} > microblaze_ps_local_memory_ilmb_bram_if_cntlr_Mem_microblaze_ps_local_memory_dlmb_bram_if_cntlr_Mem + +.init : { + KEEP (*(.init)) +} > microblaze_ps_local_memory_ilmb_bram_if_cntlr_Mem_microblaze_ps_local_memory_dlmb_bram_if_cntlr_Mem + +.fini : { + KEEP (*(.fini)) +} > microblaze_ps_local_memory_ilmb_bram_if_cntlr_Mem_microblaze_ps_local_memory_dlmb_bram_if_cntlr_Mem + +.ctors : { + __CTOR_LIST__ = .; + ___CTORS_LIST___ = .; + KEEP (*crtbegin.o(.ctors)) + KEEP (*(EXCLUDE_FILE(*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + __CTOR_END__ = .; + ___CTORS_END___ = .; +} > microblaze_ps_local_memory_ilmb_bram_if_cntlr_Mem_microblaze_ps_local_memory_dlmb_bram_if_cntlr_Mem + +.dtors : { + __DTOR_LIST__ = .; + ___DTORS_LIST___ = .; + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE(*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + PROVIDE(__DTOR_END__ = .); + PROVIDE(___DTORS_END___ = .); +} > microblaze_ps_local_memory_ilmb_bram_if_cntlr_Mem_microblaze_ps_local_memory_dlmb_bram_if_cntlr_Mem + +.rodata : { + __rodata_start = .; + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + __rodata_end = .; +} > microblaze_ps_local_memory_ilmb_bram_if_cntlr_Mem_microblaze_ps_local_memory_dlmb_bram_if_cntlr_Mem + +.sdata2 : { + . = ALIGN(8); + __sdata2_start = .; + *(.sdata2) + *(.sdata2.*) + *(.gnu.linkonce.s2.*) + . = ALIGN(8); + __sdata2_end = .; +} > microblaze_ps_local_memory_ilmb_bram_if_cntlr_Mem_microblaze_ps_local_memory_dlmb_bram_if_cntlr_Mem + +.sbss2 : { + __sbss2_start = .; + *(.sbss2) + *(.sbss2.*) + *(.gnu.linkonce.sb2.*) + __sbss2_end = .; +} > microblaze_ps_local_memory_ilmb_bram_if_cntlr_Mem_microblaze_ps_local_memory_dlmb_bram_if_cntlr_Mem + +.data : { + . = ALIGN(4); + __data_start = .; + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + __data_end = .; +} > microblaze_ps_local_memory_ilmb_bram_if_cntlr_Mem_microblaze_ps_local_memory_dlmb_bram_if_cntlr_Mem + +.got : { + *(.got) +} > microblaze_ps_local_memory_ilmb_bram_if_cntlr_Mem_microblaze_ps_local_memory_dlmb_bram_if_cntlr_Mem + +.got1 : { + *(.got1) +} > microblaze_ps_local_memory_ilmb_bram_if_cntlr_Mem_microblaze_ps_local_memory_dlmb_bram_if_cntlr_Mem + +.got2 : { + *(.got2) +} > microblaze_ps_local_memory_ilmb_bram_if_cntlr_Mem_microblaze_ps_local_memory_dlmb_bram_if_cntlr_Mem + +.eh_frame : { + *(.eh_frame) +} > microblaze_ps_local_memory_ilmb_bram_if_cntlr_Mem_microblaze_ps_local_memory_dlmb_bram_if_cntlr_Mem + +.jcr : { + *(.jcr) +} > microblaze_ps_local_memory_ilmb_bram_if_cntlr_Mem_microblaze_ps_local_memory_dlmb_bram_if_cntlr_Mem + +.gcc_except_table : { + *(.gcc_except_table) +} > microblaze_ps_local_memory_ilmb_bram_if_cntlr_Mem_microblaze_ps_local_memory_dlmb_bram_if_cntlr_Mem + +.sdata : { + . = ALIGN(8); + __sdata_start = .; + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s.*) + __sdata_end = .; +} > microblaze_ps_local_memory_ilmb_bram_if_cntlr_Mem_microblaze_ps_local_memory_dlmb_bram_if_cntlr_Mem + +.sbss (NOLOAD) : { + . = ALIGN(4); + __sbss_start = .; + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.sb.*) + . = ALIGN(8); + __sbss_end = .; +} > microblaze_ps_local_memory_ilmb_bram_if_cntlr_Mem_microblaze_ps_local_memory_dlmb_bram_if_cntlr_Mem + +.tdata : { + __tdata_start = .; + *(.tdata) + *(.tdata.*) + *(.gnu.linkonce.td.*) + __tdata_end = .; +} > microblaze_ps_local_memory_ilmb_bram_if_cntlr_Mem_microblaze_ps_local_memory_dlmb_bram_if_cntlr_Mem + +.tbss : { + __tbss_start = .; + *(.tbss) + *(.tbss.*) + *(.gnu.linkonce.tb.*) + __tbss_end = .; +} > microblaze_ps_local_memory_ilmb_bram_if_cntlr_Mem_microblaze_ps_local_memory_dlmb_bram_if_cntlr_Mem + +.bss (NOLOAD) : { + . = ALIGN(4); + __bss_start = .; + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + __bss_end = .; +} > microblaze_ps_local_memory_ilmb_bram_if_cntlr_Mem_microblaze_ps_local_memory_dlmb_bram_if_cntlr_Mem + +_SDA_BASE_ = __sdata_start + ((__sbss_end - __sdata_start) / 2 ); + +_SDA2_BASE_ = __sdata2_start + ((__sbss2_end - __sdata2_start) / 2 ); + +/* Generate Stack and Heap definitions */ + +.heap (NOLOAD) : { + . = ALIGN(8); + _heap = .; + _heap_start = .; + . += _HEAP_SIZE; + _heap_end = .; +} > microblaze_ps_local_memory_ilmb_bram_if_cntlr_Mem_microblaze_ps_local_memory_dlmb_bram_if_cntlr_Mem + +.stack (NOLOAD) : { + _stack_end = .; + . += _STACK_SIZE; + . = ALIGN(8); + _stack = .; + __stack = _stack; +} > microblaze_ps_local_memory_ilmb_bram_if_cntlr_Mem_microblaze_ps_local_memory_dlmb_bram_if_cntlr_Mem + +_end = .; +} + diff --git a/datalink814_sp/src/main.c b/datalink814_sp/src/main.c new file mode 100644 index 0000000..a5b4170 --- /dev/null +++ b/datalink814_sp/src/main.c @@ -0,0 +1,779 @@ +/*****************************************************************************/ +/** + * Description: main.c + * + * Date: 2021-11-13 13:19 + * Last Edit Time: [2023-04-23 21:32] + * + * Revisions: Rev 0.0 + * History: + * [2021-11-13]: Initial edition. + * [2022-03-28]: Add bit error test mode. + * [2023-04-23]: Bug fixed, + * + * Copyright(c) 2021 Beijing Institute of Technology. + * Lab of Communication and Networking + * + ******************************************************************************/ + +/***************************** Include Files *********************************/ +// Standard +#include +#include +#include +// Xilinx +#include "xintc.h" // The generic interrupt controller driver component +#include "xil_exception.h" // ARM Cortex A9 specific exception related APIs +#include "sleep.h" // Sleep APIs for Cortex A9 +#include "xgpio.h" // GPIO APIs for Cortex A9 +#include "xbram.h" +#include "xtmrctr.h" +#include "xsysmon.h" + +// ADI Drivers +#include "dev_profile/dev_profile.h" +#include "adi_noos/drivers/axi_core/spi_engine/spi_engine.h" +#include "adi_noos/drivers/platform/gpio_extra.h" + +// User +#include "common.h" +#include "error.h" +#include "config/app_config.h" +#include "c2c_bridge/c2c_bridge.h" +#include "phy_ctrl/phy_ctrl.h" +#include "circ_queue/circ_queue.h" +#include "inter_comm/inter_comm.h" + +/************************** Function Prototypes ******************************/ +int32_t SetupInterruptSystem(XIntc* instPtr, uint32_t devId); +int32_t XADC_Init(XSysMon* instPtr, uint16_t devId); +int32_t ScuTimerInit(XTmrCtr* instPtr, uint16_t devId); + +// Utility functions +int32_t Intercom_C2cRecvData(void* buffPtr, int32_t dataLen); +int32_t Intercom_C2cSendData2Addr(void* buffPtr, int32_t dataLen, uint16_t subaddrId); + +// IRQ Handlers +void C2c_RxIntrHandler(void* callBackRef); +void C2c_TxIntrHandler(void* callBackRef); +void Timer_IntrHandler(void* CallBackRef); +void PhyIntr_Handler(void *callBackRef); +/************************** Constant Definitions *****************************/ +#define C2C_EXTRA_LEN (sizeof(C2C_EXTRA) + COMMON_CRC_LEN) + +C2C_CONFIG c2cConfig = { + .capacity = C2C_BUFF_MAX, + .dmaConfig = { + .devId = C2C_AXI_DMA_DEVICE_ID, + .transMax = C2C_BUFF_MAX, + .defaultTransLen = C2C_BUFF_MAX, + .timeoutTh = 500 + } +}; + +INTER_COMM_CONFIG intrCommConfig = { + .data_recv = Intercom_C2cRecvData, + .data_send = Intercom_C2cSendData2Addr, + .phyInstPtr = NULL +}; + +PHY_CONFIG phyConfig = { + .devId = 0, + .baseAddr = PHY_CTRL_BASEADDR, + .txBramId = PHY_TX_BRAM_BUFF_ID, + .rxBramId = PHY_RX_BRAM_BUFF_ID, + .antBramId = PHY_ANT_CONFIG_BRAM_ID + +}; + +struct spi_engine_init_param spi_engine_param = { + .ref_clk_hz = SPI_ENGINE_REF_CLK, + .type = SPI_ENGINE, + .spi_engine_baseaddr = SPI_ENGINE_BASEADDR, + .cs_delay = SPI_ENGINE_CS_DELAY, + .data_width = SPI_ENGINE_DATA_WIDTH +}; + +struct xil_gpio_init_param xil_gpio_param = { + .type = GPIO_PS, + .device_id = GPIO_DEVICE_ID +}; + +/*********************** Driver Instance Definitions **************************/ +static XIntc intcInst; // General interrupt controller instance +static XSysMon SysMonInst; +#ifdef GLINK_REMOTE_TEST_ENABLE +static XTmrCtr axiTimeInst; // PS scu timer +static bool isSendRemotCheckAsserted = false;//true when 1s comes +#endif +static bool isPhyUploadAsserted = false;//true when 1s comes +static CIRC_QUEUE *c2cRecvQueue; +static PHY_INST* phyInstPtr = NULL; +static INTER_COMM_INST* intrCommInstPtr = NULL; +static C2C_EXTRA* c2cExtraBuffPtr = NULL; + +// For AD9361 +struct ad9516_dev *ad9516_inst; +struct ad9361_reg_dev *ad9361_1_reg_inst; +struct ad9361_reg_dev *ad9361_2_reg_inst; +struct ad9361_rf_phy *ad9361_phy; + +/* Helper function for AD9361 IO control*/ +static int XGpio_WritePin(XGpio *InstPtr, uint32_t Channel, u32 Pin, uint8_t Value){ + ASSERT(Pin <= 31 && Pin >=0 ); + ASSERT(InstPtr != NULL); + ASSERT(InstPtr->IsReady == XIL_COMPONENT_IS_READY); + ASSERT((Channel == 1) || ((Channel == 2) && (InstPtr->IsDual == TRUE))); + u32 CurrValue = XGpio_DiscreteRead(InstPtr, Channel); + CurrValue = (Value == 0)? (CurrValue & (~(0x00000001 << Pin))) : (CurrValue | (0x00000001 << Pin)); + XGpio_DiscreteWrite(InstPtr, Channel, CurrValue); + return SUCCESS; +}// XGpio_WritePin + +/****************************************************************************/ +/** + * This function dose a hardware initialization. + * + * @param None + * + * @return SUCCESS if initialize successful. + * XST_FAILURE if initialization failed. + * + *****************************************************************************/ +static int Hardware_Initialize(void){ + int Status; + XGpio Gpio; + Status = XGpio_Initialize(&Gpio, GPIO_DEVICE_ID); + if (Status != SUCCESS) + { + return FAILURE; + } + XGpio_SetDataDirection(&Gpio, GPIO_BANK_OUT, 0x00000000); // Bank 1 output + XGpio_SetDataDirection(&Gpio, GPIO_BANK_IN, 0xFFFFFFFF); // Bank 0 inputT_FAILURE; + + /**********************************************************/ + /****************** AD9516 Configuration ******************/ + /**********************************************************/ + Status = ad9516_init(&ad9516_inst, &ad9516_default_init_param); + XGpio_WritePin(&Gpio, GPIO_BANK_OUT, AD9516_POWEDOWN_B, 1); + XGpio_WritePin(&Gpio, GPIO_BANK_OUT, AD9516_SYNC_B, 1); + XGpio_WritePin(&Gpio, GPIO_BANK_OUT, AD9516_RESET_B, 0); + mdelay(200); + XGpio_WritePin(&Gpio, GPIO_BANK_OUT, AD9516_RESET_B, 1); + for(int i = 0; i < ad9516_default_config_len; i++){ + Status = ad9516_write(ad9516_inst, ad9516_default_config[i].addr, ad9516_default_config[i].value); + if (ad9516_default_config[i].addr == 0x0000){ + mdelay(500); + } + } + + uint8_t rd_back; + Status = ad9516_read(ad9516_inst, 0x0003, &rd_back); + do + { + Status = ad9516_read(ad9516_inst, 0x001F, &rd_back); + } + while((rd_back & 0x01) != 0x01); + + /**********************************************************/ + /***************** AD9361-1 Configuration *****************/ + /**********************************************************/ + XGpio_WritePin(&Gpio, GPIO_BANK_OUT, AD9361_RX_FIFO_RST, 1); + XGpio_WritePin(&Gpio, GPIO_BANK_OUT, AD9361_SYNC, 0); + + ad9361_reg_init(&ad9361_1_reg_inst, &ad9361_1_reg_default_init_param); + + XGpio_WritePin(&Gpio, GPIO_BANK_OUT, AD9361_1_RESET_B, 0); + mdelay(200); + XGpio_WritePin(&Gpio, GPIO_BANK_OUT, AD9361_1_RESET_B, 1); + + XGpio_WritePin(&Gpio, GPIO_BANK_OUT, AD9361_1_ENABLE, 0); + ad9361_reg_config(ad9361_1_reg_inst); + XGpio_WritePin(&Gpio, GPIO_BANK_OUT, AD9361_1_ENABLE, 1); + + /**********************************************************/ + /***************** AD9361-2 Configuration *****************/ + /**********************************************************/ + ad9361_reg_init(&ad9361_2_reg_inst, &ad9361_2_reg_default_init_param); + + XGpio_WritePin(&Gpio, GPIO_BANK_OUT, AD9361_2_RESET_B, 0); + mdelay(200); + XGpio_WritePin(&Gpio, GPIO_BANK_OUT, AD9361_2_RESET_B, 1); + + XGpio_WritePin(&Gpio, GPIO_BANK_OUT, AD9361_2_ENABLE, 0); + ad9361_reg_config(ad9361_2_reg_inst); + XGpio_WritePin(&Gpio, GPIO_BANK_OUT, AD9361_2_ENABLE, 1); + + // sync clock output + XGpio_WritePin(&Gpio, GPIO_BANK_OUT, AD9516_SYNC_B, 0); + mdelay(500); + XGpio_WritePin(&Gpio, GPIO_BANK_OUT, AD9516_SYNC_B, 1); + + // SYNC BBPLL and DIGITAL SAMPLING CLOCKS + ad9361_reg_init(&ad9361_1_reg_inst, &ad9361_1_reg_default_init_param); + ad9361_reg_init(&ad9361_2_reg_inst, &ad9361_2_reg_default_init_param); + + ad9361_reg_write(ad9361_1_reg_inst, 0x0001, 0x0D); // MCS RF Enable; MCS BBPLL Enable; MCS BB Enable + ad9361_reg_write(ad9361_2_reg_inst, 0x0001, 0x0D); + ad9361_reg_write(ad9361_1_reg_inst, 0x0047, 0x80); // MCS refclk Scale Enable + ad9361_reg_write(ad9361_2_reg_inst, 0x0047, 0x80); + XGpio_WritePin(&Gpio, GPIO_BANK_OUT, AD9361_SYNC, 1); // Input a rising-edge pulse to the SYNC_IN pin + mdelay(500); + XGpio_WritePin(&Gpio, GPIO_BANK_OUT, AD9361_SYNC, 0); + mdelay(2000); + ad9361_reg_write(ad9361_1_reg_inst, 0x0001, 0x0B); // MCS RF Enable; MCS Digital CLK Enable ; MCS BB Enable + ad9361_reg_write(ad9361_2_reg_inst, 0x0001, 0x0B); + XGpio_WritePin(&Gpio, GPIO_BANK_OUT, AD9361_SYNC, 1); // Input another rising-edge pulse to the SYNC_IN pin + mdelay(500); + XGpio_WritePin(&Gpio, GPIO_BANK_OUT, AD9361_SYNC, 0); + ad9361_reg_write(ad9361_1_reg_inst, 0x0001, 0x08); // clear MCS bits + ad9361_reg_write(ad9361_2_reg_inst, 0x0001, 0x08); + + XGpio_WritePin(&Gpio, GPIO_BANK_OUT, AD9361_RX_FIFO_RST, 0); + + return SUCCESS; +}// Hardware_Initialize + +/*****************************************************************************/ +/** + * @brief Initialize ScuTimer instance. + * + * @param InstPtr A pointer to QSPI instance + * + * @param DevId ScuTimer instance device ID + * + * @return SUCCESS + * XST_FAILURE + * + ******************************************************************************/ +int32_t ScuTimerInit(XTmrCtr* instPtr, uint16_t devId) { + int Status = SUCCESS; + XTmrCtr_Config *configPtr; + /* + * Initialize the Scu Private Timer driver. + */ + configPtr = XTmrCtr_LookupConfig(devId); + /* + * This is where the virtual address would be used, this example + * uses physical address. + */ + Status = XTmrCtr_Initialize(instPtr, configPtr->DeviceId); + if (Status != SUCCESS) { + return Status; + } + /* + * Perform a self-test to ensure that the hardware was built correctly. + */ + Status = XTmrCtr_SelfTest(instPtr, XTC_TIMER_0); + + return Status; +}// ScuTimerInit + +/*****************************************************************************/ +/** + * @brief Initialize XADC instance. + * + * @param InstPtr A pointer to QSPI instance + * + * @param DevId ScuTimer instance device ID + * + * @return SUCCESS + * XST_FAILURE + * + ******************************************************************************/ +int32_t XADC_Init(XSysMon* instPtr, uint16_t devId) { + int Status = SUCCESS; + XSysMon_Config *configPtr; + + /* + * Initialize the Scu Private Timer driver. + */ + configPtr = XSysMon_LookupConfig(devId); + if (configPtr == NULL) { + return XST_FAILURE; + } + + XSysMon_CfgInitialize(instPtr, configPtr, configPtr->BaseAddress); + + //safe mode + XSysMon_SetSequencerMode(instPtr, XSM_SEQ_MODE_SAFE); + + //enable channels + XSysMon_SetSeqChEnables(instPtr, XSM_SEQ_CH_TEMP|XSM_SEQ_CH_VCCINT); + + /* Set the ADCCLK frequency equal to 1/32 of System clock for the System + * Monitor/ADC in the Configuration Register 2. + */ + XSysMon_SetAdcClkDivisor(instPtr, 32); + //mode + XSysMon_SetSequencerMode(instPtr, XSM_SEQ_MODE_CONTINPASS); + + /* + * Wait till the End of Sequence occurs + */ + XSysMon_GetStatus(instPtr); /* Clear the old status */ + while ((XSysMon_GetStatus(instPtr) & XSM_SR_EOS_MASK) != + XSM_SR_EOS_MASK); + + return Status; +}// XADC_Init + +/****************************************************************************/ +/** + * This function is responsible for initializing the SCUGIC instance, looking + * for the device configuration based on the unique device ID, initializing a + * SCUGIC instance, and initialize the interrupt at IRQ_F2P[0:0] + * + * @param deviceID is the XPAR__DEVICE_ID value from + * "xparameters.h". + * @param XIntc is a reference to the XScuGic driver Instance. + * + * @return SUCCESS if initialize successful. + * XST_FAILURE if initialization failed. + * + *****************************************************************************/ +int32_t SetupInterruptSystem(XIntc* instPtr, uint32_t devId){ + int Status = SUCCESS; + // Initialize the GIC instance. + Status = XIntc_Initialize(instPtr, devId); + if (Status != SUCCESS) { + return Status; + } + + // Perform a self-test to ensure that the hardware was built correctly. + Status = XIntc_SelfTest(instPtr); + if (Status != SUCCESS) { + return Status; + } + + /* Hook up interrupt service routine */ + Status = XIntc_Connect(instPtr, PHY_INTR_ID, + (XInterruptHandler) PhyIntr_Handler, (void *) instPtr); + if (Status != SUCCESS) { + return Status; + } + /* Enable the interrupt vector at the interrupt controller */ + XIntc_Enable(instPtr, PHY_INTR_ID); + + /* Hook up interrupt service routine */ + Status = XIntc_Connect(instPtr, C2C_TX_INTR_ID, + (XInterruptHandler) C2c_TxIntrHandler, (void *) instPtr); + if (Status != SUCCESS) { + return Status; + } + Status = XIntc_Connect(instPtr, C2C_RX_INTR_ID, + (XInterruptHandler) C2c_RxIntrHandler, (void *) instPtr); + if (Status != SUCCESS) { + return Status; + } + /* Enable the interrupt vector at the interrupt controller */ + XIntc_Enable(instPtr, C2C_TX_INTR_ID); + XIntc_Enable(instPtr, C2C_RX_INTR_ID); + +#ifdef GLINK_REMOTE_TEST_ENABLE + // ScuTimer interrupt + Status = XIntc_Connect(instPtr, SCUTIMER_INTR_ID, + (Xil_ExceptionHandler) Timer_IntrHandler, + (void *) &axiTimeInst); + if (Status != SUCCESS) { + return Status; + } + XIntc_Enable(instPtr, SCUTIMER_INTR_ID); +#endif + + /* Start the interrupt controller such that interrupts are recognized + * and handled by the processor + */ + Status = XIntc_Start(instPtr, XIN_REAL_MODE); + if (Status != SUCCESS) { + return Status; + } + + /* Initialize the exception table and register the interrupt controller + * handler with the exception table + */ + Xil_ExceptionInit(); + + Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, + (Xil_ExceptionHandler) XIntc_InterruptHandler, + (void *) instPtr); + + // Enable non-critical exceptions + Xil_ExceptionEnable(); + + return SUCCESS; +} // SetupInterruptSystem + +/****************************************************************************/ +/** + * This is a utility function to implement a C2C data transmission. + * + * @param buffPtr a pointer to data buffer, which need to be 2 byte aligned. + * @param dataLen length of data needs to be sent. + * + * @return None. + * + * @note None. + * + *****************************************************************************/ +int32_t Intercom_C2cRecvData(void* buffPtr, int32_t buffSize){ + int Status; + uint8_t* c2cRecvDataPtr; + + if(isCircQueueEmpty(c2cRecvQueue)){ + return EIGNORE; + } + else{ + Status = CircQueuePop(c2cRecvQueue, (void**)(&c2cRecvDataPtr)); + if(Status == false || c2cRecvDataPtr == NULL){ + return FAILURE; + } + } + + uint32_t recvLen = IO_In32((uintptr_t)(c2cRecvDataPtr + C2C_DLEN_OFFSET)) - C2C_HEADER_LEN; + memcpy(buffPtr, c2cRecvDataPtr + C2C_PLOAD_OFFSET, recvLen); + + // Check if buffer is big enough. + if(buffSize < recvLen - C2C_EXTRA_LEN){ + DBG_ERROR("Buffer too small.\r\n",); + return FAILURE; + } + + // Check CRC + if(CrcCheck(buffPtr + recvLen - C2C_EXTRA_LEN, C2C_EXTRA_LEN) == true){ + // Store received data + memcpy(c2cExtraBuffPtr, buffPtr + recvLen - C2C_EXTRA_LEN, sizeof(C2C_EXTRA)); + } + else{ + DBG_ERROR("C2C extra crc check failed.\r\n"); + return ECRC; + } + return SUCCESS; +} //Intercom_C2cRecvData + +/****************************************************************************/ +/** + * This is a utility function to implement a C2C data transmission. + * + * @param buffPtr a pointer to data buffer, which need to be 2 byte aligned. + * @param dataLen length of data needs to be sent. + * @param subaddrId taget subAddress + * + * @return None. + * + * @note None. + * + *****************************************************************************/ +int32_t Intercom_C2cSendData2Addr(void* buffPtr, int32_t dataLen, uint16_t subaddrId){ + int Status; + if(dataLen > (C2C_BUFF_MAX - (sizeof(C2C_EXTRA)+COMMON_CRC_LEN))){ + return FAILURE; + } + c2cExtraBuffPtr->glinkSubAddr = subaddrId; + memcpy((uint8_t *)(C2C_TXBUFF_ADDR_BASE + C2C_PLOAD_OFFSET), buffPtr, dataLen); + memcpy((uint8_t *)(C2C_TXBUFF_ADDR_BASE + C2C_PLOAD_OFFSET + dataLen), c2cExtraBuffPtr, sizeof(C2C_EXTRA)); + Status = AppendCrc((uint8_t *)(C2C_TXBUFF_ADDR_BASE + C2C_PLOAD_OFFSET + dataLen), C2C_EXTRA_LEN); + if(Status != SUCCESS){ + DBG_ERROR("C2C extra data crc append error, with error code: %d.\r\n", Status); + return Status; + } + Status = C2c_BlockingSendData(c2cInstPtr, (uint8_t *)C2C_TXBUFF_ADDR_BASE, dataLen + C2C_EXTRA_LEN); + // FIXME + usleep(1); + return Status; +}// Intercom_C2cSendData2Addr + +/****************************************************************************/ +/** + * This function is a interrupt service routine for IRQ_F2P[1:1], IRQ_F2P[1:1] + * tells CPU that the data in OCM is ready! + * + * @param callBackRef is the SCUGIC instance pointer. + * + * @return None. + * + * @note None. + * + *****************************************************************************/ +uint32_t c2cRecvCnt = 0; +void C2c_RxIntrHandler(void *callBackRef) { + int32_t Status; + Status = C2c_RecvIrqHandler(c2cInstPtr); + if(Status != SUCCESS){ + _nop_(); + } + CircQueuePush(c2cRecvQueue, (void *)c2cInstPtr->lastRxBuff); + uint8_t* nextRxBuff = (c2cInstPtr->lastRxBuff >= C2C_RXBUFF_ADDR_BASE + (C2C_BUFF_NUM-1)*C2C_BUFF_SIZE) ? + (uint8_t*)C2C_RXBUFF_ADDR_BASE : (uint8_t*)(c2cInstPtr->lastRxBuff + C2C_BUFF_SIZE); + C2c_RecvData(c2cInstPtr, nextRxBuff, C2C_BUFF_SIZE); + c2cRecvCnt ++; + return; +} // C2cRxIntr_Handler + +/****************************************************************************/ +/** + * This function is a interrupt service routine for IRQ_F2P[1:1], IRQ_F2P[1:1] + * tells CPU that the data in OCM is ready! + * + * @param callBackRef is the SCUGIC instance pointer. + * + * @return None. + * + * @note None. + * + *****************************************************************************/ +uint32_t c2cSendvCnt = 0; +void C2c_TxIntrHandler(void *callBackRef) { + int32_t Status; + Status = C2c_SendIrqHandler(c2cInstPtr); + if(Status != SUCCESS){ + _nop_(); + } + c2cSendvCnt ++; + return; +} // C2cTxIntr_Handler + +/****************************************************************************/ +/** + * This function is a interrupt service routine for IRQ_F2P[1:1], IRQ_F2P[1:1] + * tells CPU that the data in OCM is ready! + * + * @param callBackRef is the SCUGIC instance pointer. + * + * @return None. + * + * @note None. + * + *****************************************************************************/ +uint32_t phyIntrCnt = 0; +void PhyIntr_Handler(void *callBackRef) { + phyIntrCnt++; + Phy_UpdateState(phyInstPtr); + // Check last frame. + if (Phy_IsFrameValid(phyInstPtr) == true) { + Phy_RetrieveRecvData(phyInstPtr, intrCommInstPtr->phyRecvBuff); + isPhyUploadAsserted = true; + } + return; +} // PhyIntr_Handler + +/*****************************************************************************/ +/** + * @brief Handler of ScuTimer interrupt. + * + * @param CallBackRef A pointer to corresponding ScuTimer instance. + * + * @return None. + * + ******************************************************************************/ +#ifdef GLINK_REMOTE_TEST_ENABLE +void Timer_IntrHandler(void* CallBackRef) { + ASSERT(CallBackRef != NULL); + XTmrCtr *TimerInstPtr = (XTmrCtr *) CallBackRef; + XTmrCtr_InterruptHandler(TimerInstPtr); + isSendRemotCheckAsserted = true; + return; +} //Timer_IntrHandler +#endif + +/*****************************************************************************/ +/** + * @brief Main function, initialize all the device needed, initialize + * interrupt system, halt in while(1) wait for event interrupt. + * + * @param None. + * + * @return + * + ******************************************************************************/ +int main(void) { + int Status; + + /*** Initialize Hardware AD9361 AD9516 ***/ + Status = Hardware_Initialize(); + if (Status == SUCCESS) { + DBG_PRINT("Hardware Init SUCCESS! \r\n"); + } + else { + DBG_PRINT("Hardware Init FAILED! \r\n"); + return Status; + } + +#ifdef GLINK_REMOTE_TEST_ENABLE + /*** Initialize Remote Test Updater Module ***/ + //-- ScuTimer Initialization + Status = ScuTimerInit(&axiTimeInst, SCUTIMER_DEVICE_ID); + if (Status == SUCCESS) { + DBG_INFO("ScuTimer Init SUCCESS! \r\n"); + } + else { + DBG_ERROR("ScuTimer Init FAILED, ErrorCode: 0x%08X\r\n, Status"); + return Status; + } + XTmrCtr_InitHw(&axiTimeInst); + + //-- XADC Initialization + Status = XADC_Init(&SysMonInst, SYSMON_DEVICE_ID); + if (Status == SUCCESS) { + DBG_INFO("XADC Init SUCCESS! \r\n"); + } + else { + DBG_ERROR("XADC Init FAILED, ErrorCode: 0x%08X\r\n, Status"); + return Status; + } +#endif + + /*** Initialize C2C bridge ***/ + //-- Buffer Initialization + Status = CircQueueCreate(&c2cRecvQueue, C2C_BUFF_NUM); + if (Status == true) { + DBG_PRINT("CircQueue Creat SUCCESS! \r\n"); + } + else { + DBG_PRINT("CircQueue Creat FAILED! \r\n"); + return EUNEXP; + } + + c2cExtraBuffPtr = (C2C_EXTRA*) malloc(sizeof(C2C_EXTRA)); + if ((c2cExtraBuffPtr) == NULL) { + DBG_PRINT("c2cExtraBuffPtr allocate FAILED! \r\n"); + return EALLOC; + } + + //-- C2C Hardware Initialization + Status = C2c_Init(&c2cInstPtr, &c2cConfig); + if (Status == SUCCESS) { + DBG_INFO("C2C bridge Init SUCCESS! \r\n"); + } + else { + DBG_ERROR("C2C bridge Init FAILED, ErrorCode: %d\r\n, Status"); + return Status; + } + + //-- C2C Intercommunication Module Initialization + intrCommConfig.phyInstPtr = phyInstPtr; + Status = InterComm_Init(&intrCommInstPtr, &intrCommConfig); + if (Status == SUCCESS) { + DBG_INFO("nterComm Init SUCCESS! \r\n"); + } + else { + DBG_ERROR("nterComm Init FAILED, ErrorCode: %d\r\n, Status"); + return Status; + } + + //-- Start C2C Receiving Process + Status = C2c_RecvData(c2cInstPtr, (uint8_t*)C2C_RXBUFF_ADDR_BASE, C2C_BUFF_SIZE); + if (Status == SUCCESS) { + DBG_PRINT("C2C start listening SUCCESS! \r\n"); + } + else { + DBG_PRINT("C2C start listening FAILED! \r\n"); + return Status; + } + + //-- Enable C2C Interrupts + Status = C2c_IrqEnable(c2cInstPtr); + if (Status == SUCCESS) { + DBG_INFO("Glink interrupts enable SUCCESS!\r\n"); + } + else { + DBG_ERROR("Glink interrupts enable FAILED, with error code: %d.\r\n", Status); + return Status; + } + + /*** Initialize Physical Layer Control Module ***/ + //-- Physical Layer Hardware Initialization + Status = Phy_InstInit(&phyInstPtr, &phyConfig); + if (Status == SUCCESS) { + DBG_PRINT("PhyCtrl Init SUCCESS! \r\n"); + } + else { + DBG_PRINT("PhyCtrl Init FAILED! \r\n"); + return Status; + } + //-- Set Physical Layer Mode + Status = Phy_SetMode(phyInstPtr, PHY_MODE_PULL); + if (Status == SUCCESS) { + DBG_PRINT("Physical Mode %u Setup SUCCESS! \r\n", PHY_MODE_LISTEN); + } + else { + DBG_PRINT("Physical Mode %u Setup FAILED! \r\n", PHY_MODE_LISTEN); + return Status; + } + + /*** Initialize GIC ***/ + Status = SetupInterruptSystem(&intcInst, INTC_DEVICE_ID); + if (Status == SUCCESS) { + DBG_INFO("Intc Init SUCCESS! \r\n"); + } + else { + DBG_ERROR("Intc Init FAILED, ErrorCode: %d\r\n, Status"); + return Status; + } + + +#ifdef GLINK_REMOTE_TEST_ENABLE + // Start Remote Control Timer + XTmrCtr_SetLoadReg(axiTimeInst.BaseAddress, XTC_TIMER_0, TIMER_COUNT_MAX); + XTmrCtr_SetControlStatusReg(axiTimeInst.BaseAddress, XTC_TIMER_0, + XTC_CSR_ENABLE_TMR_MASK | XTC_CSR_ENABLE_INT_MASK | + XTC_CSR_AUTO_RELOAD_MASK | XTC_CSR_DOWN_COUNT_MASK); + XTmrCtr_Start(&axiTimeInst,XTC_TIMER_0); + XTmrCtr_Start(&axiTimeInst,XTC_TIMER_0); +#endif + + DBG_PRINT("Starting Physical Layer..."); + Phy_Start(phyInstPtr); + + /*** Main Routine - Handling C2C Handshake ***/ + while(true){ + // Upload physical frame data if new frame received. + if(isPhyUploadAsserted && !C2c_IsSendBusy(c2cInstPtr)){ + isPhyUploadAsserted = false; + Status = InterComm_PhyDataUpload(intrCommInstPtr); + if(Status != SUCCESS){ + DBG_PRINT("####\tInterComm L1 data upload finished with code: %d", Status); + continue; + } + } + + // Handle received intercom frame if received. + else if(isCircQueueEmpty(c2cRecvQueue) == false){ + Status = InterComm_RecvMsg(intrCommInstPtr); + if(Status != SUCCESS){ + DBG_PRINT("####\tInterComm L1 data upload finished with code: %d.\r\n", Status); + continue; + } + else{ + Status = InterComm_MsgHandler(intrCommInstPtr); + if(Status != SUCCESS){ + DBG_PRINT("####\tInterComm message handler finished with code: %d\n\r", Status); + continue; + } + } + } +#ifdef GLINK_REMOTE_TEST_ENABLE + // Update remote monitoring info if needed. + else if(isSendRemotCheckAsserted && !C2c_IsSendBusy(c2cInstPtr)){ + isSendRemotCheckAsserted = false; + Status = InterComm_SendRemotCheck(intrCommInstPtr, &SysMonInst, c2cExtraBuffPtr); + if(Status != SUCCESS){ + DBG_PRINT("####\tInterComm L1 data upload finished with code: %d", Status); + } + } +#endif + }// Waiting for interrupt + +// uint8_t * sendBuffPtr = (uint8_t *)C2C_TXBUFF_ADDR_BASE; +// uint32_t cnt = 0; +// while(cnt < 10240){ +// if(!C2c_IsSendBusy(c2cInstPtr)){ +// for(int i = 0; i < 512; i++){ +// sendBuffPtr[i] = i + cnt; +// } +// C2c_BlockingSendData(c2cInstPtr, sendBuffPtr, 512); +// cnt++; +// } +// } +// while(true); +} // main diff --git a/datalink814_sp/src/phy_ctrl b/datalink814_sp/src/phy_ctrl new file mode 120000 index 0000000..2e2ba2e --- /dev/null +++ b/datalink814_sp/src/phy_ctrl @@ -0,0 +1 @@ +../../datalink814_ge/src/phy_ctrl \ No newline at end of file diff --git a/datalink814_sp/src/time_ctrl b/datalink814_sp/src/time_ctrl new file mode 120000 index 0000000..848fc79 --- /dev/null +++ b/datalink814_sp/src/time_ctrl @@ -0,0 +1 @@ +../../datalink814_ge/src/time_ctrl \ No newline at end of file diff --git a/datalink814_sp/src/util b/datalink814_sp/src/util new file mode 120000 index 0000000..c684ffa --- /dev/null +++ b/datalink814_sp/src/util @@ -0,0 +1 @@ +../../datalink814_ge/src/util \ No newline at end of file diff --git a/df_datalink/bsp/Makefile b/df_datalink/bsp/Makefile new file mode 100644 index 0000000..5b2895d --- /dev/null +++ b/df_datalink/bsp/Makefile @@ -0,0 +1,35 @@ +# Makefile generated by Xilinx. + +PROCESSOR = ps7_cortexa9_0 +LIBRARIES = ${PROCESSOR}/lib/libxil.a +BSP_MAKEFILES := $(wildcard $(PROCESSOR)/libsrc/*/src/Makefile) +SUBDIRS := $(patsubst %/Makefile, %, $(BSP_MAKEFILES)) + +ifneq (,$(findstring win,$(RDI_PLATFORM))) + SHELL = CMD +endif + +all: libs + @echo 'Finished building libraries' + +include: $(addsuffix /make.include,$(SUBDIRS)) + +libs: $(addsuffix /make.libs,$(SUBDIRS)) + +clean: $(addsuffix /make.clean,$(SUBDIRS)) + +$(PROCESSOR)/lib/libxil.a: $(PROCESSOR)/lib/libxil_init.a + cp -f $< $@ + +%/make.include: $(if $(wildcard $(PROCESSOR)/lib/libxil_init.a),$(PROCESSOR)/lib/libxil.a,) + @echo "Running Make include in $(subst /make.include,,$@)" + $(MAKE) -C $(subst /make.include,,$@) -s include "SHELL=$(SHELL)" "COMPILER=$(CC)" "ARCHIVER=arm-none-eabi-ar" "COMPILER_FLAGS= -O2 -c" "EXTRA_COMPILER_FLAGS=-DDEBUG -mcpu=cortex-a9 -mfpu=vfpv3 -mfloat-abi=hard -nostartfiles -g -Wall -Wextra" + +%/make.libs: include + @echo "Running Make libs in $(subst /make.libs,,$@)" + $(MAKE) -C $(subst /make.libs,,$@) -s libs "SHELL=$(SHELL)" "COMPILER=$(CC)" "ARCHIVER=arm-none-eabi-ar" "COMPILER_FLAGS= -O2 -c" "EXTRA_COMPILER_FLAGS=-DDEBUG -mcpu=cortex-a9 -mfpu=vfpv3 -mfloat-abi=hard -nostartfiles -g -Wall -Wextra" + +%/make.clean: + $(MAKE) -C $(subst /make.clean,,$@) -s clean +clean: + rm -f ${PROCESSOR}/lib/libxil.a diff --git a/df_datalink/bsp/ps7_cortexa9_0/include/_profile_timer_hw.h b/df_datalink/bsp/ps7_cortexa9_0/include/_profile_timer_hw.h new file mode 100644 index 0000000..1647600 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/include/_profile_timer_hw.h @@ -0,0 +1,308 @@ +/****************************************************************************** +* +* Copyright (C) 2004 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +****************************************************************************** +* +* _program_timer_hw.h: +* Timer related functions +* +******************************************************************************/ + +#ifndef PROFILE_TIMER_HW_H +#define PROFILE_TIMER_HW_H + +#include "profile.h" + +#ifdef PROC_PPC +#if defined __GNUC__ +# define SYNCHRONIZE_IO __asm__ volatile ("eieio") +#elif defined __DCC__ +# define SYNCHRONIZE_IO __asm volatile(" eieio") +#else +# define SYNCHRONIZE_IO +#endif +#endif + +#ifdef PROC_PPC +#define ProfIo_In32(InputPtr) { (*(volatile u32 *)(InputPtr)); SYNCHRONIZE_IO; } +#define ProfIo_Out32(OutputPtr, Value) { (*(volatile u32 *)(OutputPtr) = Value); SYNCHRONIZE_IO; } +#else +#define ProfIo_In32(InputPtr) (*(volatile u32 *)(InputPtr)); +#define ProfIo_Out32(OutputPtr, Value) { (*(volatile u32 *)(OutputPtr) = (Value)); } +#endif + +#define ProfTmrCtr_mWriteReg(BaseAddress, TmrCtrNumber, RegOffset, ValueToWrite)\ + ProfIo_Out32(((u32)(BaseAddress) + (u32)XTmrCtr_Offsets[(TmrCtrNumber)] + \ + (u32)(RegOffset)), (u32)(ValueToWrite)) + +#define ProfTimerCtr_mReadReg(BaseAddress, TmrCtrNumber, RegOffset) \ + ProfIo_In32((u32)(BaseAddress) + (u32)XTmrCtr_Offsets[(TmrCtrNumber)] + (u32)(RegOffset)) + +#define ProfTmrCtr_mSetControlStatusReg(BaseAddress, TmrCtrNumber, RegisterValue)\ + ProfTmrCtr_mWriteReg((BaseAddress), (TmrCtrNumber), XTC_TCSR_OFFSET, \ + (RegisterValue)) + +#define ProfTmrCtr_mGetControlStatusReg(BaseAddress, TmrCtrNumber) \ + ProfTimerCtr_mReadReg((u32)(BaseAddress), (TmrCtrNumber), XTC_TCSR_OFFSET) + + + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef PROC_PPC +#include "xexception_l.h" +#include "xtime_l.h" +#include "xpseudo_asm.h" +#endif + +#ifdef TIMER_CONNECT_INTC +#include "xintc_l.h" +#include "xintc.h" +#endif /* TIMER_CONNECT_INTC */ + +#if (!defined PPC_PIT_INTERRUPT && !defined PROC_CORTEXA9) +#include "xtmrctr_l.h" +#endif + +#ifdef PROC_CORTEXA9 +#include "xscutimer_hw.h" +#include "xscugic.h" +#endif + +extern u32 timer_clk_ticks ; + +/*-------------------------------------------------------------------- + * PowerPC Target - Timer related functions + *-------------------------------------------------------------------- */ +#ifdef PROC_PPC + +#ifdef PPC_PIT_INTERRUPT +u32 timer_lo_clk_ticks ; /* Clk ticks when Timer is disabled in CG */ +#endif + +#ifdef PROC_PPC440 +#define XREG_TCR_PIT_INTERRUPT_ENABLE XREG_TCR_DEC_INTERRUPT_ENABLE +#define XREG_TSR_PIT_INTERRUPT_STATUS XREG_TSR_DEC_INTERRUPT_STATUS +#define XREG_SPR_PIT XREG_SPR_DEC +#define XEXC_ID_PIT_INT XEXC_ID_DEC_INT +#endif + +/* -------------------------------------------------------------------- + * Disable the Timer - During Profiling + * + * For PIT Timer - + * 1. XTime_PITDisableInterrupt() ; + * 2. Store the remaining timer clk tick + * 3. Stop the PIT Timer + *-------------------------------------------------------------------- */ + +#ifdef PPC_PIT_INTERRUPT +#define disable_timer() \ + { \ + u32 val; \ + val=mfspr(XREG_SPR_TCR); \ + mtspr(XREG_SPR_TCR, val & (~XREG_TCR_PIT_INTERRUPT_ENABLE)); \ + timer_lo_clk_ticks = mfspr(XREG_SPR_PIT); \ + mtspr(XREG_SPR_PIT, 0); \ + } +#else +#define disable_timer() \ + { \ + u32 addr = (PROFILE_TIMER_BASEADDR) + XTmrCtr_Offsets[(0)] + XTC_TCSR_OFFSET; \ + u32 tmp_v = ProfIo_In32(addr); \ + tmp_v = tmp_v & (~XTC_CSR_ENABLE_TMR_MASK); \ + ProfIo_Out32((PROFILE_TIMER_BASEADDR) + XTmrCtr_Offsets[(0)] + XTC_TCSR_OFFSET, tmp_v); \ + } +#endif + + + +/* -------------------------------------------------------------------- + * Enable the Timer + * + * For PIT Timer - + * 1. Load the remaining timer clk ticks + * 2. XTime_PITEnableInterrupt() ; + *-------------------------------------------------------------------- */ +#ifdef PPC_PIT_INTERRUPT +#define enable_timer() \ + { \ + u32 val; \ + val=mfspr(XREG_SPR_TCR); \ + mtspr(XREG_SPR_PIT, timer_lo_clk_ticks); \ + mtspr(XREG_SPR_TCR, val | XREG_TCR_PIT_INTERRUPT_ENABLE); \ + } +#else +#define enable_timer() \ + { \ + u32 addr = (PROFILE_TIMER_BASEADDR) + XTmrCtr_Offsets[(0)] + XTC_TCSR_OFFSET; \ + u32 tmp_v = ProfIo_In32(addr); \ + tmp_v = tmp_v | XTC_CSR_ENABLE_TMR_MASK; \ + ProfIo_Out32((PROFILE_TIMER_BASEADDR) + XTmrCtr_Offsets[(0)] + XTC_TCSR_OFFSET, tmp_v); \ + } +#endif + + + +/* -------------------------------------------------------------------- + * Send Ack to Timer Interrupt + * + * For PIT Timer - + * 1. Load the timer clk ticks + * 2. Enable AutoReload and Interrupt + * 3. Clear PIT Timer Status bits + *-------------------------------------------------------------------- */ +#ifdef PPC_PIT_INTERRUPT +#define timer_ack() \ + { \ + u32 val; \ + mtspr(XREG_SPR_PIT, timer_clk_ticks); \ + mtspr(XREG_SPR_TSR, XREG_TSR_PIT_INTERRUPT_STATUS); \ + val=mfspr(XREG_SPR_TCR); \ + mtspr(XREG_SPR_TCR, val| XREG_TCR_PIT_INTERRUPT_ENABLE| XREG_TCR_AUTORELOAD_ENABLE); \ + } +#else +#define timer_ack() \ + { \ + u32 csr; \ + csr = ProfTmrCtr_mGetControlStatusReg(PROFILE_TIMER_BASEADDR, 0); \ + ProfTmrCtr_mSetControlStatusReg(PROFILE_TIMER_BASEADDR, 0, csr); \ + } +#endif + +/*-------------------------------------------------------------------- */ +#endif /* PROC_PPC */ +/* -------------------------------------------------------------------- */ + + + + +/* -------------------------------------------------------------------- + * MicroBlaze Target - Timer related functions + *-------------------------------------------------------------------- */ +#ifdef PROC_MICROBLAZE + +/* -------------------------------------------------------------------- + * Disable the Timer during Call-Graph Data collection + * + *-------------------------------------------------------------------- */ +#define disable_timer() \ + { \ + u32 Addr = ((u32)PROFILE_TIMER_BASEADDR); \ + Addr += (u32)XTmrCtr_Offsets[(u16)(0)]; \ + Addr += (u32)XTC_TCSR_OFFSET; \ + u32 tmp_v = ProfIo_In32(Addr); \ + tmp_v = tmp_v & (u32)(~XTC_CSR_ENABLE_TMR_MASK); \ + u32 OutAddr = (u32)PROFILE_TIMER_BASEADDR; \ + OutAddr += (u32)XTmrCtr_Offsets[(u16)(0)]; \ + OutAddr += (u32)XTC_TCSR_OFFSET; \ + ProfIo_Out32(OutAddr, (u32)tmp_v); \ + } + + +/* -------------------------------------------------------------------- + * Enable the Timer after Call-Graph Data collection + * + *-------------------------------------------------------------------- */ +#define enable_timer() \ + { \ + u32 Addr = ((u32)PROFILE_TIMER_BASEADDR); \ + Addr += (u32)XTmrCtr_Offsets[(u16)(0)]; \ + Addr += (u32)XTC_TCSR_OFFSET; \ + u32 tmp_v = (u32)ProfIo_In32(Addr); \ + tmp_v = tmp_v | (u32)XTC_CSR_ENABLE_TMR_MASK; \ + ProfIo_Out32((u32)(PROFILE_TIMER_BASEADDR) + (u32)XTmrCtr_Offsets[(u16)(0)] + (u32)XTC_TCSR_OFFSET, (u32)tmp_v); \ + } + + +/* -------------------------------------------------------------------- + * Send Ack to Timer Interrupt + * + *-------------------------------------------------------------------- */ +#define timer_ack() \ + { \ + u32 csr; \ + csr = ProfTmrCtr_mGetControlStatusReg((u32)PROFILE_TIMER_BASEADDR, (u16)0); \ + ProfTmrCtr_mSetControlStatusReg((u32)PROFILE_TIMER_BASEADDR, (u16)0, (u32)csr); \ + } + +/*-------------------------------------------------------------------- */ +#endif /* PROC_MICROBLAZE */ +/*-------------------------------------------------------------------- */ + +/* -------------------------------------------------------------------- + * Cortex A9 Target - Timer related functions + *-------------------------------------------------------------------- */ +#ifdef PROC_CORTEXA9 + +/* -------------------------------------------------------------------- + * Disable the Timer during Call-Graph Data collection + * + *-------------------------------------------------------------------- */ +#define disable_timer() \ +{ \ + u32 Reg; \ + Reg = Xil_In32(PROFILE_TIMER_BASEADDR + XSCUTIMER_CONTROL_OFFSET); \ + Reg &= (~XSCUTIMER_CONTROL_ENABLE_MASK);\ + Xil_Out32(PROFILE_TIMER_BASEADDR + XSCUTIMER_CONTROL_OFFSET, Reg);\ +} + + +/* -------------------------------------------------------------------- + * Enable the Timer after Call-Graph Data collection + * + *-------------------------------------------------------------------- */ +#define enable_timer() \ +{ \ + u32 Reg; \ + Reg = Xil_In32(PROFILE_TIMER_BASEADDR + XSCUTIMER_CONTROL_OFFSET); \ + Reg |= XSCUTIMER_CONTROL_ENABLE_MASK; \ + Xil_Out32(PROFILE_TIMER_BASEADDR + XSCUTIMER_CONTROL_OFFSET, Reg);\ +} + + +/* -------------------------------------------------------------------- + * Send Ack to Timer Interrupt + * + *-------------------------------------------------------------------- */ +#define timer_ack() \ +{ \ + Xil_Out32((u32)PROFILE_TIMER_BASEADDR + (u32)XSCUTIMER_ISR_OFFSET, \ + (u32)XSCUTIMER_ISR_EVENT_FLAG_MASK);\ +} + +/*-------------------------------------------------------------------- */ +#endif /* PROC_CORTEXA9 */ +/*-------------------------------------------------------------------- */ + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/df_datalink/bsp/ps7_cortexa9_0/include/bspconfig.h b/df_datalink/bsp/ps7_cortexa9_0/include/bspconfig.h new file mode 100644 index 0000000..488641c --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/include/bspconfig.h @@ -0,0 +1,44 @@ + +/******************************************************************* +* +* CAUTION: This file is automatically generated by HSI. +* Version: 2019.1.3 +* DO NOT EDIT. +* +* Copyright (C) 2010-2023 Xilinx, Inc. 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 +*XILINX 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. +* +*Except as contained in this notice, the name of the Xilinx shall not be used +*in advertising or otherwise to promote the sale, use or other dealings in +*this Software without prior written authorization from Xilinx. +* + +* +* Description: Configurations for Standalone BSP +* +*******************************************************************/ + +#ifndef BSPCONFIG_H /* prevent circular inclusions */ +#define BSPCONFIG_H /* by using protection macros */ + +#define MICROBLAZE_PVR_NONE + +/* Definition for hard-float ABI */ +#define FPU_HARD_FLOAT_ABI_ENABLED 1 + +#endif /*end of __BSPCONFIG_H_*/ diff --git a/df_datalink/bsp/ps7_cortexa9_0/include/mblaze_nt_types.h b/df_datalink/bsp/ps7_cortexa9_0/include/mblaze_nt_types.h new file mode 100644 index 0000000..807dda3 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/include/mblaze_nt_types.h @@ -0,0 +1,50 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + + +#ifndef _MBLAZE_NT_TYPES_H +#define _MBLAZE_NT_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef char byte; +typedef short half; +typedef int word; +typedef unsigned char ubyte; +typedef unsigned short uhalf; +typedef unsigned int uword; +typedef ubyte boolean; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/df_datalink/bsp/ps7_cortexa9_0/include/profile.h b/df_datalink/bsp/ps7_cortexa9_0/include/profile.h new file mode 100644 index 0000000..63f503a --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/include/profile.h @@ -0,0 +1,127 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +#ifndef PROFILE_H +#define PROFILE_H 1 + +#include +#include "xil_types.h" +#include "profile_config.h" + +#ifdef PROC_MICROBLAZE +#include "mblaze_nt_types.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +void _system_init( void ) ; +void _system_clean( void ) ; +void mcount(u32 frompc, u32 selfpc); +void profile_intr_handler( void ) ; +void _profile_init( void ); + + + +/**************************************************************************** + * Profiling on hardware - Hash table maintained on hardware and data sent + * to xmd for gmon.out generation. + ****************************************************************************/ +/* + * histogram counters are unsigned shorts (according to the kernel). + */ +#define HISTCOUNTER u16 + +struct tostruct { + u32 selfpc; + s32 count; + s16 link; + u16 pad; +}; + +struct fromstruct { + u32 frompc ; + s16 link ; + u16 pad ; +} ; + +/* + * general rounding functions. + */ +#define ROUNDDOWN(x,y) (((x)/(y))*(y)) +#define ROUNDUP(x,y) ((((x)+(y)-1)/(y))*(y)) + +/* + * The profiling data structures are housed in this structure. + */ +struct gmonparam { + s32 state; + + /* Histogram Information */ + u16 *kcount; /* No. of bins in histogram */ + u32 kcountsize; /* Histogram samples */ + + /* Call-graph Information */ + struct fromstruct *froms; + u32 fromssize; + struct tostruct *tos; + u32 tossize; + + /* Initialization I/Ps */ + u32 lowpc; + u32 highpc; + u32 textsize; + /* u32 cg_froms, */ + /* u32 cg_tos, */ +}; +extern struct gmonparam *_gmonparam; +extern s32 n_gmon_sections; + +/* + * Possible states of profiling. + */ +#define GMON_PROF_ON 0 +#define GMON_PROF_BUSY 1 +#define GMON_PROF_ERROR 2 +#define GMON_PROF_OFF 3 + +/* + * Sysctl definitions for extracting profiling information from the kernel. + */ +#define GPROF_STATE 0 /* int: profiling enabling variable */ +#define GPROF_COUNT 1 /* struct: profile tick count buffer */ +#define GPROF_FROMS 2 /* struct: from location hash bucket */ +#define GPROF_TOS 3 /* struct: destination/count structure */ +#define GPROF_GMONPARAM 4 /* struct: profiling parameters (see above) */ + +#ifdef __cplusplus +} +#endif + +#endif /* PROFILE_H */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/include/sleep.h b/df_datalink/bsp/ps7_cortexa9_0/include/sleep.h new file mode 100644 index 0000000..f3a632b --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/include/sleep.h @@ -0,0 +1,115 @@ +/****************************************************************************** +* +* Copyright (C) 2014 - 2017 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +/*****************************************************************************/ +/** +* @file sleep.h +* +* This header file contains ARM Cortex A53,A9,R5,Microblaze specific sleep +* related APIs. +* +*
+* MODIFICATION HISTORY :
+*
+* Ver   Who  Date	 Changes
+* ----- ---- -------- -------------------------------------------------------
+* 6.6   srm  11/02/17 Added processor specific sleep rountines
+*								 function prototypes.
+*
+* 
+* +******************************************************************************/ + +#ifndef SLEEP_H +#define SLEEP_H + +#include "xil_types.h" +#include "xil_io.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*****************************************************************************/ +/** +* +* This macro polls an address periodically until a condition is met or till the +* timeout occurs. +* The minimum timeout for calling this macro is 100us. If the timeout is less +* than 100us, it still waits for 100us. Also the unit for the timeout is 100us. +* If the timeout is not a multiple of 100us, it waits for a timeout of +* the next usec value which is a multiple of 100us. +* +* @param IO_func - accessor function to read the register contents. +* Depends on the register width. +* @param ADDR - Address to be polled +* @param VALUE - variable to read the value +* @param COND - Condition to checked (usually involves VALUE) +* @param TIMEOUT_US - timeout in micro seconds +* +* @return 0 - when the condition is met +* -1 - when the condition is not met till the timeout period +* +* @note none +* +*****************************************************************************/ +#define Xil_poll_timeout(IO_func, ADDR, VALUE, COND, TIMEOUT_US) \ + ( { \ + u64 timeout = TIMEOUT_US/100; \ + if(TIMEOUT_US%100!=0) \ + timeout++; \ + for(;;) { \ + VALUE = IO_func(ADDR); \ + if(COND) \ + break; \ + else { \ + usleep(100); \ + timeout--; \ + if(timeout==0) \ + break; \ + } \ + } \ + (timeout>0) ? 0 : -1; \ + } ) + +void usleep(unsigned long useconds); +void sleep(unsigned int seconds); +int usleep_R5(unsigned long useconds); +unsigned sleep_R5(unsigned int seconds); +int usleep_MB(unsigned long useconds); +unsigned sleep_MB(unsigned int seconds); +int usleep_A53(unsigned long useconds); +unsigned sleep_A53(unsigned int seconds); +int usleep_A9(unsigned long useconds); +unsigned sleep_A9(unsigned int seconds); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/df_datalink/bsp/ps7_cortexa9_0/include/smc.h b/df_datalink/bsp/ps7_cortexa9_0/include/smc.h new file mode 100644 index 0000000..f7cc91c --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/include/smc.h @@ -0,0 +1,110 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file smc.h +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- ---------------------------------------------------
+* 1.00a sdm  11/03/09 Initial release.
+* 4.2	pkp	 08/04/14 Removed function definition of XSmc_NorInit and XSmc_NorInit
+*					  as smc.c is removed
+* 
+* +* @note None. +* +******************************************************************************/ + +#ifndef SMC_H /* prevent circular inclusions */ +#define SMC_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xparameters.h" +#include "xil_io.h" + +/***************** Macros (Inline Functions) Definitions *********************/ + +/**************************** Type Definitions *******************************/ + +/************************** Constant Definitions *****************************/ + +/* Memory controller configuration register offset */ +#define XSMCPSS_MC_STATUS 0x000U /* Controller status reg, RO */ +#define XSMCPSS_MC_INTERFACE_CONFIG 0x004U /* Interface config reg, RO */ +#define XSMCPSS_MC_SET_CONFIG 0x008U /* Set configuration reg, WO */ +#define XSMCPSS_MC_CLR_CONFIG 0x00CU /* Clear config reg, WO */ +#define XSMCPSS_MC_DIRECT_CMD 0x010U /* Direct command reg, WO */ +#define XSMCPSS_MC_SET_CYCLES 0x014U /* Set cycles register, WO */ +#define XSMCPSS_MC_SET_OPMODE 0x018U /* Set opmode register, WO */ +#define XSMCPSS_MC_REFRESH_PERIOD_0 0x020U /* Refresh period_0 reg, RW */ +#define XSMCPSS_MC_REFRESH_PERIOD_1 0x024U /* Refresh period_1 reg, RW */ + +/* Chip select configuration register offset */ +#define XSMCPSS_CS_IF0_CHIP_0_OFFSET 0x100U /* Interface 0 chip 0 config */ +#define XSMCPSS_CS_IF0_CHIP_1_OFFSET 0x120U /* Interface 0 chip 1 config */ +#define XSMCPSS_CS_IF0_CHIP_2_OFFSET 0x140U /* Interface 0 chip 2 config */ +#define XSMCPSS_CS_IF0_CHIP_3_OFFSET 0x160U /* Interface 0 chip 3 config */ +#define XSMCPSS_CS_IF1_CHIP_0_OFFSET 0x180U /* Interface 1 chip 0 config */ +#define XSMCPSS_CS_IF1_CHIP_1_OFFSET 0x1A0U /* Interface 1 chip 1 config */ +#define XSMCPSS_CS_IF1_CHIP_2_OFFSET 0x1C0U /* Interface 1 chip 2 config */ +#define XSMCPSS_CS_IF1_CHIP_3_OFFSET 0x1E0U /* Interface 1 chip 3 config */ + +/* User configuration register offset */ +#define XSMCPSS_UC_STATUS_OFFSET 0x200U /* User status reg, RO */ +#define XSMCPSS_UC_CONFIG_OFFSET 0x204U /* User config reg, WO */ + +/* Integration test register offset */ +#define XSMCPSS_IT_OFFSET 0xE00U + +/* ID configuration register offset */ +#define XSMCPSS_ID_PERIP_0_OFFSET 0xFE0U +#define XSMCPSS_ID_PERIP_1_OFFSET 0xFE4U +#define XSMCPSS_ID_PERIP_2_OFFSET 0xFE8U +#define XSMCPSS_ID_PERIP_3_OFFSET 0xFECU +#define XSMCPSS_ID_PCELL_0_OFFSET 0xFF0U +#define XSMCPSS_ID_PCELL_1_OFFSET 0xFF4U +#define XSMCPSS_ID_PCELL_2_OFFSET 0xFF8U +#define XSMCPSS_ID_PCELL_3_OFFSET 0xFFCU + +/************************** Variable Definitions *****************************/ + +/************************** Function Prototypes ******************************/ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* SMC_H */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/include/vectors.h b/df_datalink/bsp/ps7_cortexa9_0/include/vectors.h new file mode 100644 index 0000000..56bacbc --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/include/vectors.h @@ -0,0 +1,84 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2016 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file vectors.h +* +* This file contains the C level vector prototypes for the ARM Cortex A9 core. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- ---------------------------------------------------
+* 1.00a ecm  10/20/10 Initial version, moved over from bsp area
+* 6.0   mus  07/27/16 Consolidated vectors for a9,a53 and r5 processors
+* 
+* +* @note +* +* None. +* +******************************************************************************/ + +#ifndef _VECTORS_H_ +#define _VECTORS_H_ + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" + +#ifdef __cplusplus +extern "C" { +#endif +/***************** Macros (Inline Functions) Definitions *********************/ + +/**************************** Type Definitions *******************************/ + +/************************** Constant Definitions *****************************/ + +/************************** Function Prototypes ******************************/ + +void FIQInterrupt(void); +void IRQInterrupt(void); +#if !defined (__aarch64__) +void SWInterrupt(void); +void DataAbortInterrupt(void); +void PrefetchAbortInterrupt(void); +void UndefinedException(void); +#else +void SynchronousInterrupt(void); +void SErrorInterrupt(void); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* protection macro */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/include/xadcps.h b/df_datalink/bsp/ps7_cortexa9_0/include/xadcps.h new file mode 100644 index 0000000..900edf0 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/include/xadcps.h @@ -0,0 +1,589 @@ +/****************************************************************************** +* +* Copyright (C) 2011 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xadcps.h +* @addtogroup xadcps_v2_3 +* @{ +* @details +* +* The XAdcPs driver supports the Xilinx XADC/ADC device. +* +* The XADC/ADC device has the following features: +* - 10-bit, 200-KSPS (kilo samples per second) +* Analog-to-Digital Converter (ADC) +* - Monitoring of on-chip supply voltages and temperature +* - 1 dedicated differential analog-input pair and +* 16 auxiliary differential analog-input pairs +* - Automatic alarms based on user defined limits for the on-chip +* supply voltages and temperature +* - Automatic Channel Sequencer, programmable averaging, programmable +* acquisition time for the external inputs, unipolar or differential +* input selection for the external inputs +* - Inbuilt Calibration +* - Optional interrupt request generation +* +* +* The user should refer to the hardware device specification for detailed +* information about the device. +* +* This header file contains the prototypes of driver functions that can +* be used to access the XADC/ADC device. +* +* +* XADC Channel Sequencer Modes +* +* The XADC Channel Sequencer supports the following operating modes: +* +* - Default : This is the default mode after power up. +* In this mode of operation the XADC operates in +* a sequence mode, monitoring the on chip sensors: +* Temperature, VCCINT, and VCCAUX. +* - One pass through sequence : In this mode the XADC +* converts the channels enabled in the Sequencer Channel Enable +* registers for a single pass and then stops. +* - Continuous cycling of sequence : In this mode the XADC +* converts the channels enabled in the Sequencer Channel Enable +* registers continuously. +* - Single channel mode: In this mode the XADC Channel +* Sequencer is disabled and the XADC operates in a +* Single Channel Mode. +* The XADC can operate either in a Continuous or Event +* driven sampling mode in the single channel mode. +* - Simultaneous Sampling Mode: In this mode the XADC Channel +* Sequencer will automatically sequence through eight fixed pairs +* of auxiliary analog input channels for simulataneous conversion. +* - Independent ADC mode: In this mode the first ADC (A) is used to +* is used to implement a fixed monitoring mode similar to the +* default mode but the alarm fucntions ar eenabled. +* The second ADC (B) is available to be used with external analog +* input channels only. +* +* Read the XADC spec for more information about the sequencer modes. +* +* Initialization and Configuration +* +* The device driver enables higher layer software (e.g., an application) to +* communicate to the XADC/ADC device. +* +* XAdcPs_CfgInitialize() API is used to initialize the XADC/ADC +* device. The user needs to first call the XAdcPs_LookupConfig() API which +* returns the Configuration structure pointer which is passed as a parameter to +* the XAdcPs_CfgInitialize() API. +* +* +* Interrupts +* +* The XADC/ADC device supports interrupt driven mode and the default +* operation mode is polling mode. +* +* The interrupt mode is available only if hardware is configured to support +* interrupts. +* +* This driver does not provide a Interrupt Service Routine (ISR) for the device. +* It is the responsibility of the application to provide one if needed. Refer to +* the interrupt example provided with this driver for details on using the +* device in interrupt mode. +* +* +* Virtual Memory +* +* This driver supports Virtual Memory. The RTOS is responsible for calculating +* the correct device base address in Virtual Memory space. +* +* +* Threads +* +* This driver is not thread safe. Any needs for threads or thread mutual +* exclusion must be satisfied by the layer above this driver. +* +* +* Asserts +* +* Asserts are used within all Xilinx drivers to enforce constraints on argument +* values. Asserts can be turned off on a system-wide basis by defining, at +* compile time, the NDEBUG identifier. By default, asserts are turned on and it +* is recommended that users leave asserts on during development. +* +* +* Building the driver +* +* The XAdcPs driver is composed of several source files. This allows the user +* to build and link only those parts of the driver that are necessary. +* +* Limitations of the driver +* +* XADC/ADC device can be accessed through the JTAG port and the PLB +* interface. The driver implementation does not support the simultaneous access +* of the device by both these interfaces. The user has to care of this situation +* in the user application code. +* +*

+* +*
+*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- -----  -------- -----------------------------------------------------
+* 1.00a ssb    12/22/11 First release based on the XPS/AXI xadc driver
+* 1.01a bss    02/18/13	Modified XAdcPs_SetSeqChEnables,XAdcPs_SetSeqAvgEnables
+*			XAdcPs_SetSeqInputMode and XAdcPs_SetSeqAcqTime APIs
+*			in xadcps.c to fix CR #693371
+* 1.03a bss    11/01/13 Modified xadcps_hw.h to use correct Register offsets
+*			CR#749687
+* 2.1   bss    08/05/14 Added declarations for XAdcPs_SetSequencerEvent,
+*			XAdcPs_GetSamplingMode, XAdcPs_SetMuxMode,
+*			XAdcPs_SetPowerdownMode and XAdcPs_GetPowerdownMode
+*			functions.
+*			Modified Assert for XAdcPs_SetSingleChParams in
+*			xadcps.c to fix CR #807563.
+* 2.2   bss    04/27/14 Modified to use correct Device Config base address in
+*						xadcps.c (CR#854437).
+*       ms     01/23/17 Added xil_printf statement in main function for all
+*                       examples to ensure that "Successfully ran" and "Failed"
+*                       strings are available in all examples. This is a fix
+*                       for CR-965028.
+*       ms     03/17/17 Added readme.txt file in examples folder for doxygen
+*                       generation.
+*       ms     04/05/17 Modified Comment lines in functions of xadcps
+*                       examples to recognize it as documentation block
+*                       for doxygen generation.
+* 2.3   mn     07/09/18 Fix Doxygen warning
+*
+* 
+* +*****************************************************************************/ +#ifndef XADCPS_H /* Prevent circular inclusions */ +#define XADCPS_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files ********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xstatus.h" +#include "xadcps_hw.h" + +/************************** Constant Definitions ****************************/ + + +/** + * @name Indexes for the different channels. + * @{ + */ +#define XADCPS_CH_TEMP 0x0 /**< On Chip Temperature */ +#define XADCPS_CH_VCCINT 0x1 /**< VCCINT */ +#define XADCPS_CH_VCCAUX 0x2 /**< VCCAUX */ +#define XADCPS_CH_VPVN 0x3 /**< VP/VN Dedicated analog inputs */ +#define XADCPS_CH_VREFP 0x4 /**< VREFP */ +#define XADCPS_CH_VREFN 0x5 /**< VREFN */ +#define XADCPS_CH_VBRAM 0x6 /**< On-chip VBRAM Data Reg, 7 series */ +#define XADCPS_CH_SUPPLY_CALIB 0x07 /**< Supply Calib Data Reg */ +#define XADCPS_CH_ADC_CALIB 0x08 /**< ADC Offset Channel Reg */ +#define XADCPS_CH_GAINERR_CALIB 0x09 /**< Gain Error Channel Reg */ +#define XADCPS_CH_VCCPINT 0x0D /**< On-chip PS VCCPINT Channel , Zynq */ +#define XADCPS_CH_VCCPAUX 0x0E /**< On-chip PS VCCPAUX Channel , Zynq */ +#define XADCPS_CH_VCCPDRO 0x0F /**< On-chip PS VCCPDRO Channel , Zynq */ +#define XADCPS_CH_AUX_MIN 16 /**< Channel number for 1st Aux Channel */ +#define XADCPS_CH_AUX_MAX 31 /**< Channel number for Last Aux channel */ + +/*@}*/ + + +/** + * @name Indexes for reading the Calibration Coefficient Data. + * @{ + */ +#define XADCPS_CALIB_SUPPLY_COEFF 0 /**< Supply Offset Calib Coefficient */ +#define XADCPS_CALIB_ADC_COEFF 1 /**< ADC Offset Calib Coefficient */ +#define XADCPS_CALIB_GAIN_ERROR_COEFF 2 /**< Gain Error Calib Coefficient*/ +/*@}*/ + + +/** + * @name Indexes for reading the Minimum/Maximum Measurement Data. + * @{ + */ +#define XADCPS_MAX_TEMP 0 /**< Maximum Temperature Data */ +#define XADCPS_MAX_VCCINT 1 /**< Maximum VCCINT Data */ +#define XADCPS_MAX_VCCAUX 2 /**< Maximum VCCAUX Data */ +#define XADCPS_MAX_VBRAM 3 /**< Maximum VBRAM Data */ +#define XADCPS_MIN_TEMP 4 /**< Minimum Temperature Data */ +#define XADCPS_MIN_VCCINT 5 /**< Minimum VCCINT Data */ +#define XADCPS_MIN_VCCAUX 6 /**< Minimum VCCAUX Data */ +#define XADCPS_MIN_VBRAM 7 /**< Minimum VBRAM Data */ +#define XADCPS_MAX_VCCPINT 8 /**< Maximum VCCPINT Register , Zynq */ +#define XADCPS_MAX_VCCPAUX 9 /**< Maximum VCCPAUX Register , Zynq */ +#define XADCPS_MAX_VCCPDRO 0xA /**< Maximum VCCPDRO Register , Zynq */ +#define XADCPS_MIN_VCCPINT 0xC /**< Minimum VCCPINT Register , Zynq */ +#define XADCPS_MIN_VCCPAUX 0xD /**< Minimum VCCPAUX Register , Zynq */ +#define XADCPS_MIN_VCCPDRO 0xE /**< Minimum VCCPDRO Register , Zynq */ + +/*@}*/ + + +/** + * @name Alarm Threshold(Limit) Register (ATR) indexes. + * @{ + */ +#define XADCPS_ATR_TEMP_UPPER 0 /**< High user Temperature */ +#define XADCPS_ATR_VCCINT_UPPER 1 /**< VCCINT high voltage limit register */ +#define XADCPS_ATR_VCCAUX_UPPER 2 /**< VCCAUX high voltage limit register */ +#define XADCPS_ATR_OT_UPPER 3 /**< VCCAUX high voltage limit register */ +#define XADCPS_ATR_TEMP_LOWER 4 /**< Upper Over Temperature limit Reg */ +#define XADCPS_ATR_VCCINT_LOWER 5 /**< VCCINT high voltage limit register */ +#define XADCPS_ATR_VCCAUX_LOWER 6 /**< VCCAUX low voltage limit register */ +#define XADCPS_ATR_OT_LOWER 7 /**< Lower Over Temperature limit */ +#define XADCPS_ATR_VBRAM_UPPER_ 8 /**< VRBAM Upper Alarm Reg, 7 Series */ +#define XADCPS_ATR_VCCPINT_UPPER 9 /**< VCCPINT Upper Alarm Reg, Zynq */ +#define XADCPS_ATR_VCCPAUX_UPPER 0xA /**< VCCPAUX Upper Alarm Reg, Zynq */ +#define XADCPS_ATR_VCCPDRO_UPPER 0xB /**< VCCPDRO Upper Alarm Reg, Zynq */ +#define XADCPS_ATR_VBRAM_LOWER 0xC /**< VRBAM Lower Alarm Reg, 7 Series */ +#define XADCPS_ATR_VCCPINT_LOWER 0xD /**< VCCPINT Lower Alarm Reg , Zynq */ +#define XADCPS_ATR_VCCPAUX_LOWER 0xE /**< VCCPAUX Lower Alarm Reg , Zynq */ +#define XADCPS_ATR_VCCPDRO_LOWER 0xF /**< VCCPDRO Lower Alarm Reg , Zynq */ + +/*@}*/ + + +/** + * @name Averaging to be done for the channels. + * @{ + */ +#define XADCPS_AVG_0_SAMPLES 0 /**< No Averaging */ +#define XADCPS_AVG_16_SAMPLES 1 /**< Average 16 samples */ +#define XADCPS_AVG_64_SAMPLES 2 /**< Average 64 samples */ +#define XADCPS_AVG_256_SAMPLES 3 /**< Average 256 samples */ + +/*@}*/ + + +/** + * @name Channel Sequencer Modes of operation + * @{ + */ +#define XADCPS_SEQ_MODE_SAFE 0 /**< Default Safe Mode */ +#define XADCPS_SEQ_MODE_ONEPASS 1 /**< Onepass through Sequencer */ +#define XADCPS_SEQ_MODE_CONTINPASS 2 /**< Continuous Cycling Sequencer */ +#define XADCPS_SEQ_MODE_SINGCHAN 3 /**< Single channel -No Sequencing */ +#define XADCPS_SEQ_MODE_SIMUL_SAMPLING 4 /**< Simultaneous sampling */ +#define XADCPS_SEQ_MODE_INDEPENDENT 8 /**< Independent mode */ + +/*@}*/ + + + +/** + * @name Power Down Modes + * @{ + */ +#define XADCPS_PD_MODE_NONE 0 /**< No Power Down */ +#define XADCPS_PD_MODE_ADCB 1 /**< Power Down ADC B */ +#define XADCPS_PD_MODE_XADC 2 /**< Power Down ADC A and ADC B */ +/*@}*/ + +/**************************** Type Definitions ******************************/ + +/** + * This typedef contains configuration information for the XADC/ADC + * device. + */ +typedef struct { + u16 DeviceId; /**< Unique ID of device */ + u32 BaseAddress; /**< Device base address */ +} XAdcPs_Config; + + +/** + * The driver's instance data. The user is required to allocate a variable + * of this type for every XADC/ADC device in the system. A pointer to + * a variable of this type is then passed to the driver API functions. + */ +typedef struct { + XAdcPs_Config Config; /**< XAdcPs_Config of current device */ + u32 IsReady; /**< Device is initialized and ready */ + +} XAdcPs; + +/***************** Macros (Inline Functions) Definitions ********************/ + +/****************************************************************************/ +/** +* +* This macro checks if the XADC device is in Event Sampling mode. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @return +* - TRUE if the device is in Event Sampling Mode. +* - FALSE if the device is in Continuous Sampling Mode. +* +* @note C-Style signature: +* int XAdcPs_IsEventSamplingMode(XAdcPs *InstancePtr); +* +*****************************************************************************/ +#define XAdcPs_IsEventSamplingModeSet(InstancePtr) \ + (((XAdcPs_ReadInternalReg(InstancePtr, \ + XADCPS_CFR0_OFFSET) & XADCPS_CFR0_EC_MASK) ? \ + TRUE : FALSE)) + + +/****************************************************************************/ +/** +* +* This macro checks if the XADC device is in External Mux mode. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @return +* - TRUE if the device is in External Mux Mode. +* - FALSE if the device is NOT in External Mux Mode. +* +* @note C-Style signature: +* int XAdcPs_IsExternalMuxMode(XAdcPs *InstancePtr); +* +*****************************************************************************/ +#define XAdcPs_IsExternalMuxModeSet(InstancePtr) \ + (((XAdcPs_ReadInternalReg(InstancePtr, \ + XADCPS_CFR0_OFFSET) & XADCPS_CFR0_MUX_MASK) ? \ + TRUE : FALSE)) + +/****************************************************************************/ +/** +* +* This macro converts XADC Raw Data to Temperature(centigrades). +* +* @param AdcData is the Raw ADC Data from XADC. +* +* @return The Temperature in centigrades. +* +* @note C-Style signature: +* float XAdcPs_RawToTemperature(u32 AdcData); +* +*****************************************************************************/ +#define XAdcPs_RawToTemperature(AdcData) \ + ((((float)(AdcData)/65536.0f)/0.00198421639f ) - 273.15f) + +/****************************************************************************/ +/** +* +* This macro converts XADC/ADC Raw Data to Voltage(volts). +* +* @param AdcData is the XADC/ADC Raw Data. +* +* @return The Voltage in volts. +* +* @note C-Style signature: +* float XAdcPs_RawToVoltage(u32 AdcData); +* +*****************************************************************************/ +#define XAdcPs_RawToVoltage(AdcData) \ + ((((float)(AdcData))* (3.0f))/65536.0f) + +/****************************************************************************/ +/** +* +* This macro converts Temperature in centigrades to XADC/ADC Raw Data. +* +* @param Temperature is the Temperature in centigrades to be +* converted to XADC/ADC Raw Data. +* +* @return The XADC/ADC Raw Data. +* +* @note C-Style signature: +* int XAdcPs_TemperatureToRaw(float Temperature); +* +*****************************************************************************/ +#define XAdcPs_TemperatureToRaw(Temperature) \ + ((int)(((Temperature) + 273.15f)*65536.0f*0.00198421639f)) + +/****************************************************************************/ +/** +* +* This macro converts Voltage in Volts to XADC/ADC Raw Data. +* +* @param Voltage is the Voltage in volts to be converted to +* XADC/ADC Raw Data. +* +* @return The XADC/ADC Raw Data. +* +* @note C-Style signature: +* int XAdcPs_VoltageToRaw(float Voltage); +* +*****************************************************************************/ +#define XAdcPs_VoltageToRaw(Voltage) \ + ((int)((Voltage)*65536.0f/3.0f)) + + +/****************************************************************************/ +/** +* +* This macro is used for writing to the XADC Registers using the +* command FIFO. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param Data is the value to be written to XADC register. +* +* @return None. +* +* @note C-Style signature: +* void XAdcPs_WriteFifo(XAdcPs *InstancePtr, u32 Data); +* +*****************************************************************************/ +#define XAdcPs_WriteFifo(InstancePtr, Data) \ + XAdcPs_WriteReg((InstancePtr)->Config.BaseAddress, \ + XADCPS_CMDFIFO_OFFSET, Data); + + +/****************************************************************************/ +/** +* +* This macro is used for reading from the XADC Registers using the +* data FIFO. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @return Data read from the FIFO +* +* @note C-Style signature: +* u32 XAdcPs_ReadFifo(XAdcPs *InstancePtr); +* +*****************************************************************************/ +#define XAdcPs_ReadFifo(InstancePtr) \ + XAdcPs_ReadReg((InstancePtr)->Config.BaseAddress, \ + XADCPS_RDFIFO_OFFSET); + + +/************************** Function Prototypes *****************************/ + + + +/** + * Functions in xadcps_sinit.c + */ +XAdcPs_Config *XAdcPs_LookupConfig(u16 DeviceId); + +/** + * Functions in xadcps.c + */ +int XAdcPs_CfgInitialize(XAdcPs *InstancePtr, + XAdcPs_Config *ConfigPtr, + u32 EffectiveAddr); + + +u32 XAdcPs_GetStatus(XAdcPs *InstancePtr); + +u32 XAdcPs_GetAlarmOutputStatus(XAdcPs *InstancePtr); + +void XAdcPs_StartAdcConversion(XAdcPs *InstancePtr); + +void XAdcPs_Reset(XAdcPs *InstancePtr); + +u16 XAdcPs_GetAdcData(XAdcPs *InstancePtr, u8 Channel); + +u16 XAdcPs_GetCalibCoefficient(XAdcPs *InstancePtr, u8 CoeffType); + +u16 XAdcPs_GetMinMaxMeasurement(XAdcPs *InstancePtr, u8 MeasurementType); + +void XAdcPs_SetAvg(XAdcPs *InstancePtr, u8 Average); +u8 XAdcPs_GetAvg(XAdcPs *InstancePtr); + +int XAdcPs_SetSingleChParams(XAdcPs *InstancePtr, + u8 Channel, + int IncreaseAcqCycles, + int IsEventMode, + int IsDifferentialMode); + + +void XAdcPs_SetAlarmEnables(XAdcPs *InstancePtr, u16 AlmEnableMask); +u16 XAdcPs_GetAlarmEnables(XAdcPs *InstancePtr); + +void XAdcPs_SetCalibEnables(XAdcPs *InstancePtr, u16 Calibration); +u16 XAdcPs_GetCalibEnables(XAdcPs *InstancePtr); + +void XAdcPs_SetSequencerMode(XAdcPs *InstancePtr, u8 SequencerMode); +u8 XAdcPs_GetSequencerMode(XAdcPs *InstancePtr); + +void XAdcPs_SetAdcClkDivisor(XAdcPs *InstancePtr, u8 Divisor); +u8 XAdcPs_GetAdcClkDivisor(XAdcPs *InstancePtr); + +int XAdcPs_SetSeqChEnables(XAdcPs *InstancePtr, u32 ChEnableMask); +u32 XAdcPs_GetSeqChEnables(XAdcPs *InstancePtr); + +int XAdcPs_SetSeqAvgEnables(XAdcPs *InstancePtr, u32 AvgEnableChMask); +u32 XAdcPs_GetSeqAvgEnables(XAdcPs *InstancePtr); + +int XAdcPs_SetSeqInputMode(XAdcPs *InstancePtr, u32 InputModeChMask); +u32 XAdcPs_GetSeqInputMode(XAdcPs *InstancePtr); + +int XAdcPs_SetSeqAcqTime(XAdcPs *InstancePtr, u32 AcqCyclesChMask); +u32 XAdcPs_GetSeqAcqTime(XAdcPs *InstancePtr); + +void XAdcPs_SetAlarmThreshold(XAdcPs *InstancePtr, u8 AlarmThrReg, u16 Value); +u16 XAdcPs_GetAlarmThreshold(XAdcPs *InstancePtr, u8 AlarmThrReg); + +void XAdcPs_EnableUserOverTemp(XAdcPs *InstancePtr); +void XAdcPs_DisableUserOverTemp(XAdcPs *InstancePtr); + +void XAdcPs_SetSequencerEvent(XAdcPs *InstancePtr, int IsEventMode); + +int XAdcPs_GetSamplingMode(XAdcPs *InstancePtr); + +void XAdcPs_SetMuxMode(XAdcPs *InstancePtr, int MuxMode, u8 Channel); + +void XAdcPs_SetPowerdownMode(XAdcPs *InstancePtr, u32 Mode); + +u32 XAdcPs_GetPowerdownMode(XAdcPs *InstancePtr); + +/** + * Functions in xadcps_selftest.c + */ +int XAdcPs_SelfTest(XAdcPs *InstancePtr); + +/** + * Functions in xadcps_intr.c + */ +void XAdcPs_IntrEnable(XAdcPs *InstancePtr, u32 Mask); +void XAdcPs_IntrDisable(XAdcPs *InstancePtr, u32 Mask); +u32 XAdcPs_IntrGetEnabled(XAdcPs *InstancePtr); + +u32 XAdcPs_IntrGetStatus(XAdcPs *InstancePtr); +void XAdcPs_IntrClear(XAdcPs *InstancePtr, u32 Mask); + + +#ifdef __cplusplus +} +#endif + +#endif /* End of protection macro. */ +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/include/xadcps_hw.h b/df_datalink/bsp/ps7_cortexa9_0/include/xadcps_hw.h new file mode 100644 index 0000000..dd51473 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/include/xadcps_hw.h @@ -0,0 +1,498 @@ +/****************************************************************************** +* +* Copyright (C) 2011 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xadcps_hw.h +* @addtogroup xadcps_v2_3 +* @{ +* +* This header file contains identifiers and basic driver functions (or +* macros) that can be used to access the XADC device through the Device +* Config Interface of the Zynq. +* +* +* Refer to the device specification for more information about this driver. +* +* @note None. +* +* +*
+*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- -----  -------- -----------------------------------------------------
+* 1.00a bss    12/22/11 First release based on the XPS/AXI xadc driver
+* 1.03a bss    11/01/13 Modified macros to use correct Register offsets
+*			CR#749687
+*
+* 
+* +*****************************************************************************/ +#ifndef XADCPS_HW_H /* Prevent circular inclusions */ +#define XADCPS_HW_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files ********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_io.h" + +/************************** Constant Definitions ****************************/ + + +/**@name Register offsets of XADC in the Device Config + * + * The following constants provide access to each of the registers of the + * XADC device. + * @{ + */ + +#define XADCPS_CFG_OFFSET 0x00 /**< Configuration Register */ +#define XADCPS_INT_STS_OFFSET 0x04 /**< Interrupt Status Register */ +#define XADCPS_INT_MASK_OFFSET 0x08 /**< Interrupt Mask Register */ +#define XADCPS_MSTS_OFFSET 0x0C /**< Misc status register */ +#define XADCPS_CMDFIFO_OFFSET 0x10 /**< Command FIFO Register */ +#define XADCPS_RDFIFO_OFFSET 0x14 /**< Read FIFO Register */ +#define XADCPS_MCTL_OFFSET 0x18 /**< Misc control register */ + +/* @} */ + + + + + +/** @name XADC Config Register Bit definitions + * @{ + */ +#define XADCPS_CFG_ENABLE_MASK 0x80000000 /**< Enable access from PS mask */ +#define XADCPS_CFG_CFIFOTH_MASK 0x00F00000 /**< Command FIFO Threshold mask */ +#define XADCPS_CFG_DFIFOTH_MASK 0x000F0000 /**< Data FIFO Threshold mask */ +#define XADCPS_CFG_WEDGE_MASK 0x00002000 /**< Write Edge Mask */ +#define XADCPS_CFG_REDGE_MASK 0x00001000 /**< Read Edge Mask */ +#define XADCPS_CFG_TCKRATE_MASK 0x00000300 /**< Clock freq control */ +#define XADCPS_CFG_IGAP_MASK 0x0000001F /**< Idle Gap between + * successive commands */ +/* @} */ + + +/** @name XADC Interrupt Status/Mask Register Bit definitions + * + * The definitions are same for the Interrupt Status Register and + * Interrupt Mask Register. They are defined only once. + * @{ + */ +#define XADCPS_INTX_ALL_MASK 0x000003FF /**< Alarm Signals Mask */ +#define XADCPS_INTX_CFIFO_LTH_MASK 0x00000200 /**< CMD FIFO less than threshold */ +#define XADCPS_INTX_DFIFO_GTH_MASK 0x00000100 /**< Data FIFO greater than threshold */ +#define XADCPS_INTX_OT_MASK 0x00000080 /**< Over temperature Alarm Status */ +#define XADCPS_INTX_ALM_ALL_MASK 0x0000007F /**< Alarm Signals Mask */ +#define XADCPS_INTX_ALM6_MASK 0x00000040 /**< Alarm 6 Mask */ +#define XADCPS_INTX_ALM5_MASK 0x00000020 /**< Alarm 5 Mask */ +#define XADCPS_INTX_ALM4_MASK 0x00000010 /**< Alarm 4 Mask */ +#define XADCPS_INTX_ALM3_MASK 0x00000008 /**< Alarm 3 Mask */ +#define XADCPS_INTX_ALM2_MASK 0x00000004 /**< Alarm 2 Mask */ +#define XADCPS_INTX_ALM1_MASK 0x00000002 /**< Alarm 1 Mask */ +#define XADCPS_INTX_ALM0_MASK 0x00000001 /**< Alarm 0 Mask */ + +/* @} */ + + +/** @name XADC Miscellaneous Register Bit definitions + * @{ + */ +#define XADCPS_MSTS_CFIFO_LVL_MASK 0x000F0000 /**< Command FIFO Level mask */ +#define XADCPS_MSTS_DFIFO_LVL_MASK 0x0000F000 /**< Data FIFO Level Mask */ +#define XADCPS_MSTS_CFIFOF_MASK 0x00000800 /**< Command FIFO Full Mask */ +#define XADCPS_MSTS_CFIFOE_MASK 0x00000400 /**< Command FIFO Empty Mask */ +#define XADCPS_MSTS_DFIFOF_MASK 0x00000200 /**< Data FIFO Full Mask */ +#define XADCPS_MSTS_DFIFOE_MASK 0x00000100 /**< Data FIFO Empty Mask */ +#define XADCPS_MSTS_OT_MASK 0x00000080 /**< Over Temperature Mask */ +#define XADCPS_MSTS_ALM_MASK 0x0000007F /**< Alarms Mask */ +/* @} */ + + +/** @name XADC Miscellaneous Control Register Bit definitions + * @{ + */ +#define XADCPS_MCTL_RESET_MASK 0x00000010 /**< Reset XADC */ +#define XADCPS_MCTL_FLUSH_MASK 0x00000001 /**< Flush the FIFOs */ +/* @} */ + + +/**@name Internal Register offsets of the XADC + * + * The following constants provide access to each of the internal registers of + * the XADC device. + * @{ + */ + +/* + * XADC Internal Channel Registers + */ +#define XADCPS_TEMP_OFFSET 0x00 /**< On-chip Temperature Reg */ +#define XADCPS_VCCINT_OFFSET 0x01 /**< On-chip VCCINT Data Reg */ +#define XADCPS_VCCAUX_OFFSET 0x02 /**< On-chip VCCAUX Data Reg */ +#define XADCPS_VPVN_OFFSET 0x03 /**< ADC out of VP/VN */ +#define XADCPS_VREFP_OFFSET 0x04 /**< On-chip VREFP Data Reg */ +#define XADCPS_VREFN_OFFSET 0x05 /**< On-chip VREFN Data Reg */ +#define XADCPS_VBRAM_OFFSET 0x06 /**< On-chip VBRAM , 7 Series */ +#define XADCPS_ADC_A_SUPPLY_CALIB_OFFSET 0x08 /**< ADC A Supply Offset Reg */ +#define XADCPS_ADC_A_OFFSET_CALIB_OFFSET 0x09 /**< ADC A Offset Data Reg */ +#define XADCPS_ADC_A_GAINERR_CALIB_OFFSET 0x0A /**< ADC A Gain Error Reg */ +#define XADCPS_VCCPINT_OFFSET 0x0D /**< On-chip VCCPINT Reg, Zynq */ +#define XADCPS_VCCPAUX_OFFSET 0x0E /**< On-chip VCCPAUX Reg, Zynq */ +#define XADCPS_VCCPDRO_OFFSET 0x0F /**< On-chip VCCPDRO Reg, Zynq */ + +/* + * XADC External Channel Registers + */ +#define XADCPS_AUX00_OFFSET 0x10 /**< ADC out of VAUXP0/VAUXN0 */ +#define XADCPS_AUX01_OFFSET 0x11 /**< ADC out of VAUXP1/VAUXN1 */ +#define XADCPS_AUX02_OFFSET 0x12 /**< ADC out of VAUXP2/VAUXN2 */ +#define XADCPS_AUX03_OFFSET 0x13 /**< ADC out of VAUXP3/VAUXN3 */ +#define XADCPS_AUX04_OFFSET 0x14 /**< ADC out of VAUXP4/VAUXN4 */ +#define XADCPS_AUX05_OFFSET 0x15 /**< ADC out of VAUXP5/VAUXN5 */ +#define XADCPS_AUX06_OFFSET 0x16 /**< ADC out of VAUXP6/VAUXN6 */ +#define XADCPS_AUX07_OFFSET 0x17 /**< ADC out of VAUXP7/VAUXN7 */ +#define XADCPS_AUX08_OFFSET 0x18 /**< ADC out of VAUXP8/VAUXN8 */ +#define XADCPS_AUX09_OFFSET 0x19 /**< ADC out of VAUXP9/VAUXN9 */ +#define XADCPS_AUX10_OFFSET 0x1A /**< ADC out of VAUXP10/VAUXN10 */ +#define XADCPS_AUX11_OFFSET 0x1B /**< ADC out of VAUXP11/VAUXN11 */ +#define XADCPS_AUX12_OFFSET 0x1C /**< ADC out of VAUXP12/VAUXN12 */ +#define XADCPS_AUX13_OFFSET 0x1D /**< ADC out of VAUXP13/VAUXN13 */ +#define XADCPS_AUX14_OFFSET 0x1E /**< ADC out of VAUXP14/VAUXN14 */ +#define XADCPS_AUX15_OFFSET 0x1F /**< ADC out of VAUXP15/VAUXN15 */ + +/* + * XADC Registers for Maximum/Minimum data captured for the + * on chip Temperature/VCCINT/VCCAUX data. + */ +#define XADCPS_MAX_TEMP_OFFSET 0x20 /**< Max Temperature Reg */ +#define XADCPS_MAX_VCCINT_OFFSET 0x21 /**< Max VCCINT Register */ +#define XADCPS_MAX_VCCAUX_OFFSET 0x22 /**< Max VCCAUX Register */ +#define XADCPS_MAX_VCCBRAM_OFFSET 0x23 /**< Max BRAM Register, 7 series */ +#define XADCPS_MIN_TEMP_OFFSET 0x24 /**< Min Temperature Reg */ +#define XADCPS_MIN_VCCINT_OFFSET 0x25 /**< Min VCCINT Register */ +#define XADCPS_MIN_VCCAUX_OFFSET 0x26 /**< Min VCCAUX Register */ +#define XADCPS_MIN_VCCBRAM_OFFSET 0x27 /**< Min BRAM Register, 7 series */ +#define XADCPS_MAX_VCCPINT_OFFSET 0x28 /**< Max VCCPINT Register, Zynq */ +#define XADCPS_MAX_VCCPAUX_OFFSET 0x29 /**< Max VCCPAUX Register, Zynq */ +#define XADCPS_MAX_VCCPDRO_OFFSET 0x2A /**< Max VCCPDRO Register, Zynq */ +#define XADCPS_MIN_VCCPINT_OFFSET 0x2C /**< Min VCCPINT Register, Zynq */ +#define XADCPS_MIN_VCCPAUX_OFFSET 0x2D /**< Min VCCPAUX Register, Zynq */ +#define XADCPS_MIN_VCCPDRO_OFFSET 0x2E /**< Min VCCPDRO Register,Zynq */ + /* Undefined 0x2F to 0x3E */ +#define XADCPS_FLAG_OFFSET 0x3F /**< Flag Register */ + +/* + * XADC Configuration Registers + */ +#define XADCPS_CFR0_OFFSET 0x40 /**< Configuration Register 0 */ +#define XADCPS_CFR1_OFFSET 0x41 /**< Configuration Register 1 */ +#define XADCPS_CFR2_OFFSET 0x42 /**< Configuration Register 2 */ + +/* Test Registers 0x43 to 0x47 */ + +/* + * XADC Sequence Registers + */ +#define XADCPS_SEQ00_OFFSET 0x48 /**< Seq Reg 00 Adc Channel Selection */ +#define XADCPS_SEQ01_OFFSET 0x49 /**< Seq Reg 01 Adc Channel Selection */ +#define XADCPS_SEQ02_OFFSET 0x4A /**< Seq Reg 02 Adc Average Enable */ +#define XADCPS_SEQ03_OFFSET 0x4B /**< Seq Reg 03 Adc Average Enable */ +#define XADCPS_SEQ04_OFFSET 0x4C /**< Seq Reg 04 Adc Input Mode Select */ +#define XADCPS_SEQ05_OFFSET 0x4D /**< Seq Reg 05 Adc Input Mode Select */ +#define XADCPS_SEQ06_OFFSET 0x4E /**< Seq Reg 06 Adc Acquisition Select */ +#define XADCPS_SEQ07_OFFSET 0x4F /**< Seq Reg 07 Adc Acquisition Select */ + +/* + * XADC Alarm Threshold/Limit Registers (ATR) + */ +#define XADCPS_ATR_TEMP_UPPER_OFFSET 0x50 /**< Temp Upper Alarm Register */ +#define XADCPS_ATR_VCCINT_UPPER_OFFSET 0x51 /**< VCCINT Upper Alarm Reg */ +#define XADCPS_ATR_VCCAUX_UPPER_OFFSET 0x52 /**< VCCAUX Upper Alarm Reg */ +#define XADCPS_ATR_OT_UPPER_OFFSET 0x53 /**< Over Temp Upper Alarm Reg */ +#define XADCPS_ATR_TEMP_LOWER_OFFSET 0x54 /**< Temp Lower Alarm Register */ +#define XADCPS_ATR_VCCINT_LOWER_OFFSET 0x55 /**< VCCINT Lower Alarm Reg */ +#define XADCPS_ATR_VCCAUX_LOWER_OFFSET 0x56 /**< VCCAUX Lower Alarm Reg */ +#define XADCPS_ATR_OT_LOWER_OFFSET 0x57 /**< Over Temp Lower Alarm Reg */ +#define XADCPS_ATR_VBRAM_UPPER_OFFSET 0x58 /**< VBRAM Upper Alarm, 7 series */ +#define XADCPS_ATR_VCCPINT_UPPER_OFFSET 0x59 /**< VCCPINT Upper Alarm, Zynq */ +#define XADCPS_ATR_VCCPAUX_UPPER_OFFSET 0x5A /**< VCCPAUX Upper Alarm, Zynq */ +#define XADCPS_ATR_VCCPDRO_UPPER_OFFSET 0x5B /**< VCCPDRO Upper Alarm, Zynq */ +#define XADCPS_ATR_VBRAM_LOWER_OFFSET 0x5C /**< VRBAM Lower Alarm, 7 Series */ +#define XADCPS_ATR_VCCPINT_LOWER_OFFSET 0x5D /**< VCCPINT Lower Alarm, Zynq */ +#define XADCPS_ATR_VCCPAUX_LOWER_OFFSET 0x5E /**< VCCPAUX Lower Alarm, Zynq */ +#define XADCPS_ATR_VCCPDRO_LOWER_OFFSET 0x5F /**< VCCPDRO Lower Alarm, Zynq */ + +/* Undefined 0x60 to 0x7F */ + +/*@}*/ + + + +/** + * @name Configuration Register 0 (CFR0) mask(s) + * @{ + */ +#define XADCPS_CFR0_CAL_AVG_MASK 0x8000 /**< Averaging enable Mask */ +#define XADCPS_CFR0_AVG_VALID_MASK 0x3000 /**< Averaging bit Mask */ +#define XADCPS_CFR0_AVG1_MASK 0x0000 /**< No Averaging */ +#define XADCPS_CFR0_AVG16_MASK 0x1000 /**< Average 16 samples */ +#define XADCPS_CFR0_AVG64_MASK 0x2000 /**< Average 64 samples */ +#define XADCPS_CFR0_AVG256_MASK 0x3000 /**< Average 256 samples */ +#define XADCPS_CFR0_AVG_SHIFT 12 /**< Averaging bits shift */ +#define XADCPS_CFR0_MUX_MASK 0x0800 /**< External Mask Enable */ +#define XADCPS_CFR0_DU_MASK 0x0400 /**< Bipolar/Unipolar mode */ +#define XADCPS_CFR0_EC_MASK 0x0200 /**< Event driven/ + * Continuous mode selection + */ +#define XADCPS_CFR0_ACQ_MASK 0x0100 /**< Add acquisition by 6 ADCCLK */ +#define XADCPS_CFR0_CHANNEL_MASK 0x001F /**< Channel number bit Mask */ + +/*@}*/ + +/** + * @name Configuration Register 1 (CFR1) mask(s) + * @{ + */ +#define XADCPS_CFR1_SEQ_VALID_MASK 0xF000 /**< Sequence bit Mask */ +#define XADCPS_CFR1_SEQ_SAFEMODE_MASK 0x0000 /**< Default Safe Mode */ +#define XADCPS_CFR1_SEQ_ONEPASS_MASK 0x1000 /**< Onepass through Seq */ +#define XADCPS_CFR1_SEQ_CONTINPASS_MASK 0x2000 /**< Continuous Cycling Seq */ +#define XADCPS_CFR1_SEQ_SINGCHAN_MASK 0x3000 /**< Single channel - No Seq */ +#define XADCPS_CFR1_SEQ_SIMUL_SAMPLING_MASK 0x4000 /**< Simulataneous Sampling Mask */ +#define XADCPS_CFR1_SEQ_INDEPENDENT_MASK 0x8000 /**< Independent Mode */ +#define XADCPS_CFR1_SEQ_SHIFT 12 /**< Sequence bit shift */ +#define XADCPS_CFR1_ALM_VCCPDRO_MASK 0x0800 /**< Alm 6 - VCCPDRO, Zynq */ +#define XADCPS_CFR1_ALM_VCCPAUX_MASK 0x0400 /**< Alm 5 - VCCPAUX, Zynq */ +#define XADCPS_CFR1_ALM_VCCPINT_MASK 0x0200 /**< Alm 4 - VCCPINT, Zynq */ +#define XADCPS_CFR1_ALM_VBRAM_MASK 0x0100 /**< Alm 3 - VBRAM, 7 series */ +#define XADCPS_CFR1_CAL_VALID_MASK 0x00F0 /**< Valid Calibration Mask */ +#define XADCPS_CFR1_CAL_PS_GAIN_OFFSET_MASK 0x0080 /**< Calibration 3 -Power + Supply Gain/Offset + Enable */ +#define XADCPS_CFR1_CAL_PS_OFFSET_MASK 0x0040 /**< Calibration 2 -Power + Supply Offset Enable */ +#define XADCPS_CFR1_CAL_ADC_GAIN_OFFSET_MASK 0x0020 /**< Calibration 1 -ADC Gain + Offset Enable */ +#define XADCPS_CFR1_CAL_ADC_OFFSET_MASK 0x0010 /**< Calibration 0 -ADC Offset + Enable */ +#define XADCPS_CFR1_CAL_DISABLE_MASK 0x0000 /**< No Calibration */ +#define XADCPS_CFR1_ALM_ALL_MASK 0x0F0F /**< Mask for all alarms */ +#define XADCPS_CFR1_ALM_VCCAUX_MASK 0x0008 /**< Alarm 2 - VCCAUX Enable */ +#define XADCPS_CFR1_ALM_VCCINT_MASK 0x0004 /**< Alarm 1 - VCCINT Enable */ +#define XADCPS_CFR1_ALM_TEMP_MASK 0x0002 /**< Alarm 0 - Temperature */ +#define XADCPS_CFR1_OT_MASK 0x0001 /**< Over Temperature Enable */ + +/*@}*/ + +/** + * @name Configuration Register 2 (CFR2) mask(s) + * @{ + */ +#define XADCPS_CFR2_CD_VALID_MASK 0xFF00 /** +* MODIFICATION HISTORY: +* +* Ver Who Date Changes +* ----- ---- -------- ------------------------------------------------------- +* 1.00a adk 1/31/14 Added in bsp common folder for backward compatibility +* 7.0 aru 01/21/19 Modified the typedef of u32,u16,u8 +* 7.0 aru 02/06/19 Included stdint.h and stddef.h +* +* +******************************************************************************/ + +#ifndef XBASIC_TYPES_H /* prevent circular inclusions */ +#define XBASIC_TYPES_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +/** @name Legacy types + * Deprecated legacy types. + * @{ + */ +typedef uint8_t Xuint8; /**< unsigned 8-bit */ +typedef char Xint8; /**< signed 8-bit */ +typedef uint16_t Xuint16; /**< unsigned 16-bit */ +typedef short Xint16; /**< signed 16-bit */ +typedef uint32_t Xuint32; /**< unsigned 32-bit */ +typedef long Xint32; /**< signed 32-bit */ +typedef float Xfloat32; /**< 32-bit floating point */ +typedef double Xfloat64; /**< 64-bit double precision FP */ +typedef unsigned long Xboolean; /**< boolean (XTRUE or XFALSE) */ + +#if !defined __XUINT64__ +typedef struct +{ + Xuint32 Upper; + Xuint32 Lower; +} Xuint64; +#endif + +/** @name New types + * New simple types. + * @{ + */ +#ifndef __KERNEL__ +#ifndef XIL_TYPES_H +typedef Xuint32 u32; +typedef Xuint16 u16; +typedef Xuint8 u8; +#endif +#else +#include +#endif + +#ifndef TRUE +# define TRUE 1U +#endif + +#ifndef FALSE +# define FALSE 0U +#endif + +#ifndef NULL +#define NULL 0U +#endif + +/* + * Xilinx NULL, TRUE and FALSE legacy support. Deprecated. + * Please use NULL, TRUE and FALSE + */ +#define XNULL NULL +#define XTRUE TRUE +#define XFALSE FALSE + +/* + * This file is deprecated and users + * should use xil_types.h and xil_assert.h\n\r + */ +#warning The xbasics_type.h file is deprecated and users should use xil_types.h and xil_assert. +#warning Please refer the Standalone BSP UG647 for further details + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/include/xbram.h b/df_datalink/bsp/ps7_cortexa9_0/include/xbram.h new file mode 100644 index 0000000..246df6d --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/include/xbram.h @@ -0,0 +1,223 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file xbram.h +* @addtogroup bram_v4_2 +* @{ +* @details +* +* If ECC is not enabled, this driver exists only to allow the tools to +* create a memory test application and to populate xparameters.h with memory +* range constants. In this case there is no source code. +* +* If ECC is enabled, this file contains the software API definition of the +* Xilinx BRAM Interface Controller (XBram) device driver. +* +* The Xilinx BRAM controller is a soft IP core designed for Xilinx +* FPGAs and contains the following general features: +* - LMB v2.0 bus interfaces with byte enable support +* - Used in conjunction with bram_block peripheral to provide fast BRAM +* memory solution for MicroBlaze ILMB and DLMB ports +* - Supports byte, half-word, and word transfers +* - Supports optional BRAM error correction and detection. +* +* The driver provides interrupt management functions. Implementation of +* interrupt handlers is left to the user. Refer to the provided interrupt +* example in the examples directory for details. +* +* This driver is intended to be RTOS and processor independent. Any needs for +* dynamic memory management, threads or thread mutual exclusion, virtual +* memory, or cache control must be satisfied by the layer above this driver. +* +* Initialization & Configuration +* +* The XBram_Config structure is used by the driver to configure +* itself. This configuration structure is typically created by the tool-chain +* based on HW build properties. +* +* To support multiple runtime loading and initialization strategies employed +* by various operating systems, the driver instance can be initialized as +* follows: +* +* - XBram_CfgInitialize(InstancePtr, CfgPtr, EffectiveAddr) - +* Uses a configuration structure provided by the caller. If running in a +* system with address translation, the provided virtual memory base address +* replaces the physical address present in the configuration structure. +* +* @note +* +* This API utilizes 32 bit I/O to the BRAM registers. With less +* than 32 bits, the unused bits from registers are read as zero and written as +* don't cares. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 3.00a sa  05/11/10 Added ECC support
+* 3.01a sa  01/13/12  Changed Selftest API from
+*		      XBram_SelfTest(XBram *InstancePtr) to
+*		      XBram_SelfTest(XBram *InstancePtr, u8 IntMask) and
+*		      fixed a problem with interrupt generation for CR 639274
+*		      Modified Selftest example to return XST_SUCCESS when
+*		      ECC is not enabled and return XST_FAILURE when ECC is
+*		      enabled and Control Base Address is zero (CR 636581)
+*		      Modified Selftest to use correct CorrectableCounterBits
+*		      for CR 635655
+*		      Updated to check CorrectableFailingDataRegs in the case
+*		      of LMB BRAM.
+* 		      Added CorrectableFailingDataRegs and
+*		      UncorrectableFailingDataRegs to the config structure to
+*		      distinguish between AXI BRAM and LMB BRAM.
+*		      These registers are not present in the current version of
+*		      the AXI BRAM Controller.
+* 3.02a sa 04/16/12   Added test of byte and halfword read-modify-write
+* 3.02a sa 04/16/12   Modified driver tcl to sort the address parameters
+*  	       	      to support both xps and vivado designs.
+* 3.02a adk 24/4/13   Modified the tcl file to avoid warnings
+*	       	      when ecc is disabled cr:705002.
+* 3.03a bss 05/22/13  Added Xil_DCacheFlushRange in xbram_selftest.c to
+*		      flush the Cache after writing to BRAM in InjectErrors
+*		      API(CR #719011)
+* 4.0   adk  19/12/13 Updated as per the New Tcl API's
+* 4.1   sk   11/10/15 Used UINTPTR instead of u32 for Baseaddress CR# 867425.
+*                     Changed the prototype of XBram_CfgInitialize API.
+*       ms  01/23/17 Modified xil_printf statement in main function for all
+*                    examples to ensure that "Successfully ran" and "Failed"
+*                    strings are available in all examples. This is a fix
+*                    for CR-965028.
+*       ms  03/17/17 Added readme.txt file in examples folder for doxygen
+*                    generation.
+* 4.2   ms  04/18/17 Modified tcl file to add suffix U for all macro
+*                    definitions of bram in xparameters.h
+*       ms  08/07/17 Fixed compilation warnings in xbram_sinit.c
+* 4.3   aru 03/23/19 Used UINTPTR instead of u32 for MemBaseAddress and
+*                    MemHighAddress.
+* 
+*****************************************************************************/ +#ifndef XBRAM_H /* prevent circular inclusions */ +#define XBRAM_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files ********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xstatus.h" +#include "xbram_hw.h" + +/************************** Constant Definitions ****************************/ + + +/**************************** Type Definitions ******************************/ + +/** + * This typedef contains configuration information for the device. + */ +typedef struct { + u16 DeviceId; /**< Unique ID of device */ + u32 DataWidth; /**< BRAM data width */ + int EccPresent; /**< Is ECC supported in H/W */ + int FaultInjectionPresent; /**< Is Fault Injection + * supported in H/W */ + int CorrectableFailingRegisters; /**< Is Correctable Failing Registers + * supported in H/W */ + int CorrectableFailingDataRegs; /**< Is Correctable Failing Data + * Registers supported in H/W */ + int UncorrectableFailingRegisters; /**< Is Un-correctable Failing + * Registers supported in H/W */ + int UncorrectableFailingDataRegs; /**< Is Un-correctable Failing Data + * Registers supported in H/W */ + int EccStatusInterruptPresent; /**< Are ECC status and interrupts + * supported in H/W */ + int CorrectableCounterBits; /**< Number of bits in the + * Correctable Error Counter */ + int EccOnOffRegister; /**< Is ECC on/off register supported + * in h/w */ + int EccOnOffResetValue; /**< Reset value of the ECC on/off + * register in h/w */ + int WriteAccess; /**< Is write access enabled in + * h/w */ + UINTPTR MemBaseAddress; /**< Device memory base address */ + UINTPTR MemHighAddress; /**< Device memory high address */ + UINTPTR CtrlBaseAddress; /**< Device register base address.*/ + UINTPTR CtrlHighAddress; /**< Device register base address.*/ +} XBram_Config; + +/** + * The XBram driver instance data. The user is required to + * allocate a variable of this type for every BRAM device in the + * system. A pointer to a variable of this type is then passed to the driver + * API functions. + */ +typedef struct { + XBram_Config Config; /* BRAM config structure */ + u32 IsReady; /* Device is initialized and ready */ +} XBram; + +/***************** Macros (Inline Functions) Definitions ********************/ + + +/************************** Function Prototypes *****************************/ + +/* + * Functions in xbram_sinit.c + */ +XBram_Config *XBram_LookupConfig(u16 DeviceId); + +/* + * Functions implemented in xbram.c + */ +int XBram_CfgInitialize(XBram *InstancePtr, XBram_Config *Config, + UINTPTR EffectiveAddr); + +/* + * Functions implemented in xbram_selftest.c + */ +int XBram_SelfTest(XBram *InstancePtr, u8 IntMask); + +/* + * Functions implemented in xbram_intr.c + */ +void XBram_InterruptEnable(XBram *InstancePtr, u32 Mask); +void XBram_InterruptDisable(XBram *InstancePtr, u32 Mask); +void XBram_InterruptClear(XBram *InstancePtr, u32 Mask); +u32 XBram_InterruptGetEnabled(XBram *InstancePtr); +u32 XBram_InterruptGetStatus(XBram *InstancePtr); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/include/xbram_hw.h b/df_datalink/bsp/ps7_cortexa9_0/include/xbram_hw.h new file mode 100644 index 0000000..55a2505 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/include/xbram_hw.h @@ -0,0 +1,405 @@ +/****************************************************************************** +* +* Copyright (C) 2011 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xbram_hw.h +* @addtogroup bram_v4_2 +* @{ +* +* This header file contains identifiers and driver functions (or +* macros) that can be used to access the device. The user should refer to the +* hardware device specification for more details of the device operation. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a sa   24/11/10 First release
+* 
+* +******************************************************************************/ +#ifndef XBRAM_HW_H /* prevent circular inclusions */ +#define XBRAM_HW_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_io.h" + +/************************** Constant Definitions *****************************/ + +/** @name Registers + * + * Register offsets for this device. + * @{ + */ + +#define XBRAM_ECC_STATUS_OFFSET 0x0 /**< ECC status Register */ +#define XBRAM_ECC_EN_IRQ_OFFSET 0x4 /**< ECC interrupt enable Register */ +#define XBRAM_ECC_ON_OFF_OFFSET 0x8 /**< ECC on/off register */ +#define XBRAM_CE_CNT_OFFSET 0xC /**< Correctable error counter Register */ + +#define XBRAM_CE_FFD_0_OFFSET 0x100 /**< Correctable error first failing + * data Register, 31-0 */ +#define XBRAM_CE_FFD_1_OFFSET 0x104 /**< Correctable error first failing + * data Register, 63-32 */ +#define XBRAM_CE_FFD_2_OFFSET 0x108 /**< Correctable error first failing + * data Register, 95-64 */ +#define XBRAM_CE_FFD_3_OFFSET 0x10C /**< Correctable error first failing + * data Register, 127-96 */ +#define XBRAM_CE_FFD_4_OFFSET 0x110 /**< Correctable error first failing + * data Register, 159-128 */ +#define XBRAM_CE_FFD_5_OFFSET 0x114 /**< Correctable error first failing + * data Register, 191-160 */ +#define XBRAM_CE_FFD_6_OFFSET 0x118 /**< Correctable error first failing + * data Register, 223-192 */ +#define XBRAM_CE_FFD_7_OFFSET 0x11C /**< Correctable error first failing + * data Register, 255-224 */ +#define XBRAM_CE_FFD_8_OFFSET 0x120 /**< Correctable error first failing + * data Register, 287-256 */ +#define XBRAM_CE_FFD_9_OFFSET 0x124 /**< Correctable error first failing + * data Register, 319-288 */ +#define XBRAM_CE_FFD_10_OFFSET 0x128 /**< Correctable error first failing + * data Register, 351-320 */ +#define XBRAM_CE_FFD_11_OFFSET 0x12C /**< Correctable error first failing + * data Register, 383-352 */ +#define XBRAM_CE_FFD_12_OFFSET 0x130 /**< Correctable error first failing + * data Register, 415-384 */ +#define XBRAM_CE_FFD_13_OFFSET 0x134 /**< Correctable error first failing + * data Register, 447-416 */ +#define XBRAM_CE_FFD_14_OFFSET 0x138 /**< Correctable error first failing + * data Register, 479-448 */ +#define XBRAM_CE_FFD_15_OFFSET 0x13C /**< Correctable error first failing + * data Register, 511-480 */ +#define XBRAM_CE_FFD_16_OFFSET 0x140 /**< Correctable error first failing + * data Register, 543-512 */ +#define XBRAM_CE_FFD_17_OFFSET 0x144 /**< Correctable error first failing + * data Register, 575-544 */ +#define XBRAM_CE_FFD_18_OFFSET 0x148 /**< Correctable error first failing + * data Register, 607-576 */ +#define XBRAM_CE_FFD_19_OFFSET 0x14C /**< Correctable error first failing + * data Register, 639-608 */ +#define XBRAM_CE_FFD_20_OFFSET 0x150 /**< Correctable error first failing + * data Register, 671-640 */ +#define XBRAM_CE_FFD_21_OFFSET 0x154 /**< Correctable error first failing + * data Register, 703-672 */ +#define XBRAM_CE_FFD_22_OFFSET 0x158 /**< Correctable error first failing + * data Register, 735-704 */ +#define XBRAM_CE_FFD_23_OFFSET 0x15C /**< Correctable error first failing + * data Register, 767-736 */ +#define XBRAM_CE_FFD_24_OFFSET 0x160 /**< Correctable error first failing + * data Register, 799-768 */ +#define XBRAM_CE_FFD_25_OFFSET 0x164 /**< Correctable error first failing + * data Register, 831-800 */ +#define XBRAM_CE_FFD_26_OFFSET 0x168 /**< Correctable error first failing + * data Register, 863-832 */ +#define XBRAM_CE_FFD_27_OFFSET 0x16C /**< Correctable error first failing + * data Register, 895-864 */ +#define XBRAM_CE_FFD_28_OFFSET 0x170 /**< Correctable error first failing + * data Register, 927-896 */ +#define XBRAM_CE_FFD_29_OFFSET 0x174 /**< Correctable error first failing + * data Register, 959-928 */ +#define XBRAM_CE_FFD_30_OFFSET 0x178 /**< Correctable error first failing + * data Register, 991-960 */ +#define XBRAM_CE_FFD_31_OFFSET 0x17C /**< Correctable error first failing + * data Register, 1023-992 */ + +#define XBRAM_CE_FFE_0_OFFSET 0x180 /**< Correctable error first failing + * ECC Register, 31-0 */ +#define XBRAM_CE_FFE_1_OFFSET 0x184 /**< Correctable error first failing + * ECC Register, 63-32 */ +#define XBRAM_CE_FFE_2_OFFSET 0x188 /**< Correctable error first failing + * ECC Register, 95-64 */ +#define XBRAM_CE_FFE_3_OFFSET 0x18C /**< Correctable error first failing + * ECC Register, 127-96 */ +#define XBRAM_CE_FFE_4_OFFSET 0x190 /**< Correctable error first failing + * ECC Register, 159-128 */ +#define XBRAM_CE_FFE_5_OFFSET 0x194 /**< Correctable error first failing + * ECC Register, 191-160 */ +#define XBRAM_CE_FFE_6_OFFSET 0x198 /**< Correctable error first failing + * ECC Register, 223-192 */ +#define XBRAM_CE_FFE_7_OFFSET 0x19C /**< Correctable error first failing + * ECC Register, 255-224 */ + +#define XBRAM_CE_FFA_0_OFFSET 0x1C0 /**< Correctable error first failing + * address Register 31-0 */ +#define XBRAM_CE_FFA_1_OFFSET 0x1C4 /**< Correctable error first failing + * address Register 63-32 */ + +#define XBRAM_UE_FFD_0_OFFSET 0x200 /**< Uncorrectable error first failing + * data Register, 31-0 */ +#define XBRAM_UE_FFD_1_OFFSET 0x204 /**< Uncorrectable error first failing + * data Register, 63-32 */ +#define XBRAM_UE_FFD_2_OFFSET 0x208 /**< Uncorrectable error first failing + * data Register, 95-64 */ +#define XBRAM_UE_FFD_3_OFFSET 0x20C /**< Uncorrectable error first failing + * data Register, 127-96 */ +#define XBRAM_UE_FFD_4_OFFSET 0x210 /**< Uncorrectable error first failing + * data Register, 159-128 */ +#define XBRAM_UE_FFD_5_OFFSET 0x214 /**< Uncorrectable error first failing + * data Register, 191-160 */ +#define XBRAM_UE_FFD_6_OFFSET 0x218 /**< Uncorrectable error first failing + * data Register, 223-192 */ +#define XBRAM_UE_FFD_7_OFFSET 0x21C /**< Uncorrectable error first failing + * data Register, 255-224 */ +#define XBRAM_UE_FFD_8_OFFSET 0x220 /**< Uncorrectable error first failing + * data Register, 287-256 */ +#define XBRAM_UE_FFD_9_OFFSET 0x224 /**< Uncorrectable error first failing + * data Register, 319-288 */ +#define XBRAM_UE_FFD_10_OFFSET 0x228 /**< Uncorrectable error first failing + * data Register, 351-320 */ +#define XBRAM_UE_FFD_11_OFFSET 0x22C /**< Uncorrectable error first failing + * data Register, 383-352 */ +#define XBRAM_UE_FFD_12_OFFSET 0x230 /**< Uncorrectable error first failing + * data Register, 415-384 */ +#define XBRAM_UE_FFD_13_OFFSET 0x234 /**< Uncorrectable error first failing + * data Register, 447-416 */ +#define XBRAM_UE_FFD_14_OFFSET 0x238 /**< Uncorrectable error first failing + * data Register, 479-448 */ +#define XBRAM_UE_FFD_15_OFFSET 0x23C /**< Uncorrectable error first failing + * data Register, 511-480 */ +#define XBRAM_UE_FFD_16_OFFSET 0x240 /**< Uncorrectable error first failing + * data Register, 543-512 */ +#define XBRAM_UE_FFD_17_OFFSET 0x244 /**< Uncorrectable error first failing + * data Register, 575-544 */ +#define XBRAM_UE_FFD_18_OFFSET 0x248 /**< Uncorrectable error first failing + * data Register, 607-576 */ +#define XBRAM_UE_FFD_19_OFFSET 0x24C /**< Uncorrectable error first failing + * data Register, 639-608 */ +#define XBRAM_UE_FFD_20_OFFSET 0x250 /**< Uncorrectable error first failing + * data Register, 671-640 */ +#define XBRAM_UE_FFD_21_OFFSET 0x254 /**< Uncorrectable error first failing + * data Register, 703-672 */ +#define XBRAM_UE_FFD_22_OFFSET 0x258 /**< Uncorrectable error first failing + * data Register, 735-704 */ +#define XBRAM_UE_FFD_23_OFFSET 0x25C /**< Uncorrectable error first failing + * data Register, 767-736 */ +#define XBRAM_UE_FFD_24_OFFSET 0x260 /**< Uncorrectable error first failing + * data Register, 799-768 */ +#define XBRAM_UE_FFD_25_OFFSET 0x264 /**< Uncorrectable error first failing + * data Register, 831-800 */ +#define XBRAM_UE_FFD_26_OFFSET 0x268 /**< Uncorrectable error first failing + * data Register, 863-832 */ +#define XBRAM_UE_FFD_27_OFFSET 0x26C /**< Uncorrectable error first failing + * data Register, 895-864 */ +#define XBRAM_UE_FFD_28_OFFSET 0x270 /**< Uncorrectable error first failing + * data Register, 927-896 */ +#define XBRAM_UE_FFD_29_OFFSET 0x274 /**< Uncorrectable error first failing + * data Register, 959-928 */ +#define XBRAM_UE_FFD_30_OFFSET 0x278 /**< Uncorrectable error first failing + * data Register, 991-960 */ +#define XBRAM_UE_FFD_31_OFFSET 0x27C /**< Uncorrectable error first failing + * data Register, 1023-992 */ + +#define XBRAM_UE_FFE_0_OFFSET 0x280 /**< Uncorrectable error first failing + * ECC Register, 31-0 */ +#define XBRAM_UE_FFE_1_OFFSET 0x284 /**< Uncorrectable error first failing + * ECC Register, 63-32 */ +#define XBRAM_UE_FFE_2_OFFSET 0x288 /**< Uncorrectable error first failing + * ECC Register, 95-64 */ +#define XBRAM_UE_FFE_3_OFFSET 0x28C /**< Uncorrectable error first failing + * ECC Register, 127-96 */ +#define XBRAM_UE_FFE_4_OFFSET 0x290 /**< Uncorrectable error first failing + * ECC Register, 159-128 */ +#define XBRAM_UE_FFE_5_OFFSET 0x294 /**< Uncorrectable error first failing + * ECC Register, 191-160 */ +#define XBRAM_UE_FFE_6_OFFSET 0x298 /**< Uncorrectable error first failing + * ECC Register, 223-192 */ +#define XBRAM_UE_FFE_7_OFFSET 0x29C /**< Uncorrectable error first failing + * ECC Register, 255-224 */ + +#define XBRAM_UE_FFA_0_OFFSET 0x2C0 /**< Uncorrectable error first failing + * address Register 31-0 */ +#define XBRAM_UE_FFA_1_OFFSET 0x2C4 /**< Uncorrectable error first failing + * address Register 63-32 */ + +#define XBRAM_FI_D_0_OFFSET 0x300 /**< Fault injection Data Register, + * 31-0 */ +#define XBRAM_FI_D_1_OFFSET 0x304 /**< Fault injection Data Register, + * 63-32 */ +#define XBRAM_FI_D_2_OFFSET 0x308 /**< Fault injection Data Register, + * 95-64 */ +#define XBRAM_FI_D_3_OFFSET 0x30C /**< Fault injection Data Register, + * 127-96 */ +#define XBRAM_FI_D_4_OFFSET 0x310 /**< Fault injection Data Register, + * 159-128 */ +#define XBRAM_FI_D_5_OFFSET 0x314 /**< Fault injection Data Register, + * 191-160 */ +#define XBRAM_FI_D_6_OFFSET 0x318 /**< Fault injection Data Register, + * 223-192 */ +#define XBRAM_FI_D_7_OFFSET 0x31C /**< Fault injection Data Register, + * 255-224 */ +#define XBRAM_FI_D_8_OFFSET 0x320 /**< Fault injection Data Register, + * 287-256 */ +#define XBRAM_FI_D_9_OFFSET 0x324 /**< Fault injection Data Register, + * 319-288 */ +#define XBRAM_FI_D_10_OFFSET 0x328 /**< Fault injection Data Register, + * 351-320 */ +#define XBRAM_FI_D_11_OFFSET 0x32C /**< Fault injection Data Register, + * 383-352 */ +#define XBRAM_FI_D_12_OFFSET 0x330 /**< Fault injection Data Register, + * 415-384 */ +#define XBRAM_FI_D_13_OFFSET 0x334 /**< Fault injection Data Register, + * 447-416 */ +#define XBRAM_FI_D_14_OFFSET 0x338 /**< Fault injection Data Register, + * 479-448 */ +#define XBRAM_FI_D_15_OFFSET 0x33C /**< Fault injection Data Register, + * 511-480 */ +#define XBRAM_FI_D_16_OFFSET 0x340 /**< Fault injection Data Register, + * 543-512 */ +#define XBRAM_FI_D_17_OFFSET 0x344 /**< Fault injection Data Register, + * 575-544 */ +#define XBRAM_FI_D_18_OFFSET 0x348 /**< Fault injection Data Register, + * 607-576 */ +#define XBRAM_FI_D_19_OFFSET 0x34C /**< Fault injection Data Register, + * 639-608 */ +#define XBRAM_FI_D_20_OFFSET 0x350 /**< Fault injection Data Register, + * 671-640 */ +#define XBRAM_FI_D_21_OFFSET 0x354 /**< Fault injection Data Register, + * 703-672 */ +#define XBRAM_FI_D_22_OFFSET 0x358 /**< Fault injection Data Register, + * 735-704 */ +#define XBRAM_FI_D_23_OFFSET 0x35C /**< Fault injection Data Register, + * 767-736 */ +#define XBRAM_FI_D_24_OFFSET 0x360 /**< Fault injection Data Register, + * 799-768 */ +#define XBRAM_FI_D_25_OFFSET 0x364 /**< Fault injection Data Register, + * 831-800 */ +#define XBRAM_FI_D_26_OFFSET 0x368 /**< Fault injection Data Register, + * 863-832 */ +#define XBRAM_FI_D_27_OFFSET 0x36C /**< Fault injection Data Register, + * 895-864 */ +#define XBRAM_FI_D_28_OFFSET 0x370 /**< Fault injection Data Register, + * 927-896 */ +#define XBRAM_FI_D_29_OFFSET 0x374 /**< Fault injection Data Register, + * 959-928 */ +#define XBRAM_FI_D_30_OFFSET 0x378 /**< Fault injection Data Register, + * 991-960 */ +#define XBRAM_FI_D_31_OFFSET 0x37C /**< Fault injection Data Register, + * 1023-992 */ + +#define XBRAM_FI_ECC_0_OFFSET 0x380 /**< Fault injection ECC Register, + * 31-0 */ +#define XBRAM_FI_ECC_1_OFFSET 0x384 /**< Fault injection ECC Register, + * 63-32 */ +#define XBRAM_FI_ECC_2_OFFSET 0x388 /**< Fault injection ECC Register, + * 95-64 */ +#define XBRAM_FI_ECC_3_OFFSET 0x38C /**< Fault injection ECC Register, + * 127-96 */ +#define XBRAM_FI_ECC_4_OFFSET 0x390 /**< Fault injection ECC Register, + * 159-128 */ +#define XBRAM_FI_ECC_5_OFFSET 0x394 /**< Fault injection ECC Register, + * 191-160 */ +#define XBRAM_FI_ECC_6_OFFSET 0x398 /**< Fault injection ECC Register, + * 223-192 */ +#define XBRAM_FI_ECC_7_OFFSET 0x39C /**< Fault injection ECC Register, + * 255-224 */ + + +/* @} */ + +/** @name Interrupt Status and Enable Register bitmaps and masks + * + * Bit definitions for the ECC status register and ECC interrupt enable register. + * @{ + */ +#define XBRAM_IR_CE_MASK 0x2 /**< Mask for the correctable error */ +#define XBRAM_IR_UE_MASK 0x1 /**< Mask for the uncorrectable error */ +#define XBRAM_IR_ALL_MASK 0x3 /**< Mask of all bits */ +/*@}*/ + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + +#define XBram_In32 Xil_In32 +#define XBram_Out32 Xil_Out32 + +#define XBram_In16 Xil_In16 +#define XBram_Out16 Xil_Out16 + +#define XBram_In8 Xil_In8 +#define XBram_Out8 Xil_Out8 + + +/****************************************************************************/ +/** +* +* Write a value to a BRAM register. A 32 bit write is performed. +* +* @param BaseAddress is the base address of the BRAM device register. +* @param RegOffset is the register offset from the base to write to. +* @param Data is the data written to the register. +* +* @return None. +* +* @note C-style signature: +* void XBram_WriteReg(u32 BaseAddress, u32 RegOffset, u32 Data) +* +****************************************************************************/ +#define XBram_WriteReg(BaseAddress, RegOffset, Data) \ + XBram_Out32((BaseAddress) + (RegOffset), (u32)(Data)) + +/****************************************************************************/ +/** +* +* Read a value from a BRAM register. A 32 bit read is performed. +* +* @param BaseAddress is the base address of the BRAM device registers. +* @param RegOffset is the register offset from the base to read from. +* +* @return Data read from the register. +* +* @note C-style signature: +* u32 XBram_ReadReg(u32 BaseAddress, u32 RegOffset) +* +****************************************************************************/ +#define XBram_ReadReg(BaseAddress, RegOffset) \ + XBram_In32((BaseAddress) + (RegOffset)) + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + + + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/include/xcoresightpsdcc.h b/df_datalink/bsp/ps7_cortexa9_0/include/xcoresightpsdcc.h new file mode 100644 index 0000000..79bde0b --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/include/xcoresightpsdcc.h @@ -0,0 +1,74 @@ +/****************************************************************************** +* +* Copyright (C) 2015 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xcoresightpsdcc.h +* @addtogroup coresightps_dcc_v1_5 +* @{ +* @details +* +* CoreSight driver component. +* +* The coresight is a part of debug communication channel (DCC) group. Jtag UART +* for ARM uses DCC. Each ARM core has its own DCC, so one need to select an +* ARM target in XSDB console before running the jtag terminal command. Using the +* coresight driver component, the output stream can be directed to a log file. +* +* @note None. +* +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date		Changes
+* ----- -----  -------- -----------------------------------------------
+* 1.00  kvn    02/14/15 First release
+* 1.1   kvn    06/12/15 Add support for Zynq Ultrascale+ MP.
+*       kvn    08/18/15 Modified Makefile according to compiler changes.
+* 1.3   asa    07/01/16 Made changes to ensure that the file does not compile
+*                       for MB BSPs. Instead it throws up a warning. This
+*                       fixes the CR#953056.
+* 1.5   sne    01/19/19 Fixed MISRA-C Violations CR#1025101.
+*
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ +#ifndef XCORESIGHTPSDCC_H /* prevent circular inclusions */ +#define XCORESIGHTPSDCC_H /* by using protection macros */ +#ifndef __MICROBLAZE__ +#include + +void XCoresightPs_DccSendByte(u32 BaseAddress, u8 Data); + +u8 XCoresightPs_DccRecvByte(u32 BaseAddress); +#endif +#endif +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/include/xcpu_cortexa9.h b/df_datalink/bsp/ps7_cortexa9_0/include/xcpu_cortexa9.h new file mode 100644 index 0000000..e4a5e28 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/include/xcpu_cortexa9.h @@ -0,0 +1,47 @@ +/****************************************************************************** +* +* Copyright (C) 2011 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xcpu_cortexa9.h +* @addtogroup cpu_cortexa9_v2_7 +* @{ +* @details +* +* dummy file +* MODIFICATION HISTORY: +* +* Ver Who Date Changes +* ----- ---- -------- --------------------------------------------------------- +* 2.5 ms 04/18/17 Modified tcl file to add suffix U for XPAR_CPU_ID +* parameter of cpu_cortexa9 in xparameters.h +# 2.7 mus 07/03/18 Updated tcl to not to add default flags forcefully into +# extra compiler flags. Now, user can remove default flags +# from extra compiler flags. It fixes CR#998768. +******************************************************************************/ +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/include/xddrps.h b/df_datalink/bsp/ps7_cortexa9_0/include/xddrps.h new file mode 100644 index 0000000..b4d1f56 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/include/xddrps.h @@ -0,0 +1,62 @@ +/******************************************************************************* + * + * Copyright (C) 2015 Xilinx, Inc. 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 + * XILINX 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. + * + * Except as contained in this notice, the name of the Xilinx shall not be used + * in advertising or otherwise to promote the sale, use or other dealings in + * this Software without prior written authorization from Xilinx. + * +*******************************************************************************/ +/******************************************************************************/ +/** + * + * @file xddrps.h + * @addtogroup ddrps_v1_0 + * @{ + * @details + * + * The Xilinx DdrPs driver. This driver supports the Xilinx ddrps + * IP core. + * + * @note None. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -----------------------------------------------
+ * 1.0	 nsk  08/06/15 First Release
+ * 1.0	 nsk  08/20/15 Updated define_addr_params in ddrps.tcl
+ *		       to support PBD Designs (CR #876857)
+ *
+ * 
+ * +*******************************************************************************/ + +#ifndef XDDRPS_H_ +/* Prevent circular inclusions by using protection macros. */ +#define XDDRPS_H_ + +/******************************* Include Files ********************************/ + + +#endif /* XDDRPS_H_ */ +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/include/xdebug.h b/df_datalink/bsp/ps7_cortexa9_0/include/xdebug.h new file mode 100644 index 0000000..b09c02d --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/include/xdebug.h @@ -0,0 +1,40 @@ +#ifndef XDEBUG /* prevent circular inclusions */ +#define XDEBUG /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(DEBUG) && !defined(NDEBUG) + +#ifndef XDEBUG_WARNING +#define XDEBUG_WARNING +#warning DEBUG is enabled +#endif + +int printf(const char *format, ...); + +#define XDBG_DEBUG_ERROR 0x00000001U /* error condition messages */ +#define XDBG_DEBUG_GENERAL 0x00000002U /* general debug messages */ +#define XDBG_DEBUG_ALL 0xFFFFFFFFU /* all debugging data */ + +#define xdbg_current_types (XDBG_DEBUG_GENERAL) + +#define xdbg_stmnt(x) x + +#define xdbg_printf(type, ...) (((type) & xdbg_current_types) ? printf (__VA_ARGS__) : 0) + + +#else /* defined(DEBUG) && !defined(NDEBUG) */ + +#define xdbg_stmnt(x) + +#define xdbg_printf(...) + +#endif /* defined(DEBUG) && !defined(NDEBUG) */ + +#ifdef __cplusplus +} +#endif + +#endif /* XDEBUG */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/include/xdevcfg.h b/df_datalink/bsp/ps7_cortexa9_0/include/xdevcfg.h new file mode 100644 index 0000000..6586370 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/include/xdevcfg.h @@ -0,0 +1,399 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2017 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xdevcfg.h +* @addtogroup devcfg_v3_5 +* @{ +* @details +* +* The is the main header file for the Device Configuration Interface of the Zynq +* device. The device configuration interface has three main functionality. +* 1. AXI-PCAP +* 2. Security Policy +* 3. XADC +* This current version of the driver supports only the AXI-PCAP and Security +* Policy blocks. There is a separate driver for XADC. +* +* AXI-PCAP is used for download/upload an encrypted or decrypted bitstream. +* DMA embedded in the AXI PCAP provides the master interface to +* the Device configuration block for any DMA transfers. The data transfer can +* take place between the Tx/RxFIFOs of AXI-PCAP and memory (on chip +* RAM/DDR/peripheral memory). +* +* The current driver only supports the downloading the FPGA bitstream and +* readback of the decrypted image (sort of loopback). +* The driver does not know what information needs to be written to the FPGA to +* readback FPGA configuration register or memory data. The application above the +* driver should take care of creating the data that needs to be downloaded to +* the FPGA so that the bitstream can be readback. +* This driver also does not support the reading of the internal registers of the +* PCAP. The driver has no knowledge of the PCAP internals. +* +* Initialization and Configuration +* +* The device driver enables higher layer software (e.g., an application) to +* communicate with the Device Configuration device. +* +* XDcfg_CfgInitialize() API is used to initialize the Device Configuration +* Interface. The user needs to first call the XDcfg_LookupConfig() API which +* returns the Configuration structure pointer which is passed as a parameter to +* the XDcfg_CfgInitialize() API. +* +* Interrupts +* The Driver implements an interrupt handler to support the interrupts provided +* by this interface. +* +* Threads +* +* This driver is not thread safe. Any needs for threads or thread mutual +* exclusion must be satisfied by the layer above this driver. +* +* Asserts +* +* Asserts are used within all Xilinx drivers to enforce constraints on argument +* values. Asserts can be turned off on a system-wide basis by defining, at +* compile time, the NDEBUG identifier. By default, asserts are turned on and it +* is recommended that users leave asserts on during development. +* +* Building the driver +* +* The XDcfg driver is composed of several source files. This allows the user +* to build and link only those parts of the driver that are necessary. +* +*

+* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 1.00a hvm 02/07/11 First release
+* 2.00a nm  05/31/12 Updated the driver for CR 660835 so that input length for
+*		     source/destination to the XDcfg_InitiateDma, XDcfg_Transfer
+*		     APIs is words (32 bit) and not bytes.
+* 		     Updated the notes for XDcfg_InitiateDma/XDcfg_Transfer APIs
+*		     to add information that 2 LSBs of the Source/Destination
+*		     address when equal to 2�b01 indicate the last DMA command
+*		     of an overall transfer.
+*		     Destination Address passed to this API for secure transfers
+*		     instead of using 0xFFFFFFFF for CR 662197. This issue was
+*		     resulting in the failure of secure transfers of
+*		     non-bitstream images.
+* 2.01a nm  07/07/12 Updated the XDcfg_IntrClear function to directly
+*		     set the mask instead of oring it with the
+*		     value read from the interrupt status register
+* 		     Added defines for the PS Version bits,
+*	             removed the FIFO Flush bits from the
+*		     Miscellaneous Control Reg.
+*		     Added XDcfg_GetPsVersion, XDcfg_SelectIcapInterface
+*		     and XDcfg_SelectPcapInterface APIs for CR 643295
+*		     The user has to call the XDcfg_SelectIcapInterface API
+*		     for the PL reconfiguration using AXI HwIcap.
+*		     Updated the XDcfg_Transfer API to clear the
+*		     QUARTER_PCAP_RATE_EN bit in the control register for
+*		     non secure writes for CR 675543.
+* 2.02a nm  01/31/13 Fixed CR# 679335.
+* 		     Added Setting and Clearing the internal PCAP loopback.
+*		     Removed code for enabling/disabling AES engine as BootROM
+*		     locks down this setting.
+*		     Fixed CR# 681976.
+*		     Skip Checking the PCFG_INIT in case of non-secure DMA
+*		     loopback.
+*		     Fixed CR# 699558.
+*		     XDcfg_Transfer fails to transfer data in loopback mode.
+*		     Fixed CR# 701348.
+*                    Peripheral test fails with  Running
+* 		     DcfgSelfTestExample() in SECURE bootmode.
+* 2.03a nm  04/19/13 Fixed CR# 703728.
+*		     Updated the register definitions as per the latest TRM
+*		     version UG585 (v1.4) November 16, 2012.
+* 3.0   adk 10/12/13 Updated as per the New Tcl API's
+* 3.0   kpc 21/02/14 Added function prototype for XDcfg_ClearControlRegister
+* 3.2   sb  08/25/14 Fixed XDcfg_PcapReadback() function
+*		     updated driver code with != instead of ==,
+*		     while checking for Interrupt Status with DMA and
+*		     PCAP Done Mask
+*		     ((XDcfg_ReadReg(InstancePtr->Config.BaseAddr,
+*			XDCFG_INT_STS_OFFSET) &
+*			XDCFG_IXR_D_P_DONE_MASK) !=
+*			XDCFG_IXR_D_P_DONE_MASK);
+*		     A new example has been added to read back the
+*		     configuration registers from the PL region.
+*		     xdevcfg_reg_readback_example.c
+* 3.3   sk  04/06/15 Modified XDcfg_ReadMultiBootConfig Macro CR# 851335.
+*       ms  03/17/17 Added readme.txt file in examples folder for doxygen
+*                    generation.
+*       ms  04/10/17 Modified filename tag in interrupt and polled examples
+*                    to include them in doxygen examples.
+* 3.5   ms  04/18/17 Modified tcl file to add suffix U for all macros
+*                    definitions of devcfg in xparameters.h
+*       ms  08/07/17 Fixed compilation warnings in xdevcfg_sinit.c
+* 
+* +******************************************************************************/ +#ifndef XDCFG_H /* prevent circular inclusions */ +#define XDCFG_H /* by using protection macros */ + +/***************************** Include Files *********************************/ + +#include "xdevcfg_hw.h" +#include "xstatus.h" +#include "xil_assert.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************** Constant Definitions *****************************/ + +/* Types of PCAP transfers */ + +#define XDCFG_NON_SECURE_PCAP_WRITE 1 +#define XDCFG_SECURE_PCAP_WRITE 2 +#define XDCFG_PCAP_READBACK 3 +#define XDCFG_CONCURRENT_SECURE_READ_WRITE 4 +#define XDCFG_CONCURRENT_NONSEC_READ_WRITE 5 + + +/**************************** Type Definitions *******************************/ +/** +* The handler data type allows the user to define a callback function to +* respond to interrupt events in the system. This function is executed +* in interrupt context, so amount of processing should be minimized. +* +* @param CallBackRef is the callback reference passed in by the upper +* layer when setting the callback functions, and passed back to +* the upper layer when the callback is invoked. Its type is +* unimportant to the driver component, so it is a void pointer. +* @param Status is the Interrupt status of the XDcfg device. +*/ +typedef void (*XDcfg_IntrHandler) (void *CallBackRef, u32 Status); + +/** + * This typedef contains configuration information for the device. + */ +typedef struct { + u16 DeviceId; /**< Unique ID of device */ + u32 BaseAddr; /**< Base address of the device */ +} XDcfg_Config; + +/** + * The XDcfg driver instance data. + */ +typedef struct { + XDcfg_Config Config; /**< Hardware Configuration */ + u32 IsReady; /**< Device is initialized and ready */ + u32 IsStarted; /**< Device Configuration Interface + * is running + */ + XDcfg_IntrHandler StatusHandler; /* Event handler function */ + void *CallBackRef; /* Callback reference for event handler */ +} XDcfg; + +/****************************************************************************/ +/** +* +* Unlock the Device Config Interface block. +* +* @param InstancePtr is a pointer to the instance of XDcfg driver. +* +* @return None. +* +* @note C-style signature: +* void XDcfg_Unlock(XDcfg* InstancePtr) +* +*****************************************************************************/ +#define XDcfg_Unlock(InstancePtr) \ + XDcfg_WriteReg((InstancePtr)->Config.BaseAddr, \ + XDCFG_UNLOCK_OFFSET, XDCFG_UNLOCK_DATA) + + + +/****************************************************************************/ +/** +* +* Get the version number of the PS from the Miscellaneous Control Register. +* +* @param InstancePtr is a pointer to the instance of XDcfg driver. +* +* @return Version of the PS. +* +* @note C-style signature: +* void XDcfg_GetPsVersion(XDcfg* InstancePtr) +* +*****************************************************************************/ +#define XDcfg_GetPsVersion(InstancePtr) \ + ((XDcfg_ReadReg((InstancePtr)->Config.BaseAddr, \ + XDCFG_MCTRL_OFFSET)) & \ + XDCFG_MCTRL_PCAP_PS_VERSION_MASK) >> \ + XDCFG_MCTRL_PCAP_PS_VERSION_SHIFT + + + +/****************************************************************************/ +/** +* +* Read the multiboot config register value. +* +* @param InstancePtr is a pointer to the instance of XDcfg driver. +* +* @return None. +* +* @note C-style signature: +* u32 XDcfg_ReadMultiBootConfig(XDcfg* InstancePtr) +* +*****************************************************************************/ +#define XDcfg_ReadMultiBootConfig(InstancePtr) \ + XDcfg_ReadReg((InstancePtr)->Config.BaseAddr, \ + XDCFG_MULTIBOOT_ADDR_OFFSET) + + +/****************************************************************************/ +/** +* +* Selects ICAP interface for reconfiguration after the initial configuration +* of the PL. +* +* @param InstancePtr is a pointer to the instance of XDcfg driver. +* +* @return None. +* +* @note C-style signature: +* void XDcfg_SelectIcapInterface(XDcfg* InstancePtr) +* +*****************************************************************************/ +#define XDcfg_SelectIcapInterface(InstancePtr) \ + XDcfg_WriteReg((InstancePtr)->Config.BaseAddr, XDCFG_CTRL_OFFSET, \ + ((XDcfg_ReadReg((InstancePtr)->Config.BaseAddr, XDCFG_CTRL_OFFSET)) \ + & ( ~XDCFG_CTRL_PCAP_PR_MASK))) + +/****************************************************************************/ +/** +* +* Selects PCAP interface for reconfiguration after the initial configuration +* of the PL. +* +* @param InstancePtr is a pointer to the instance of XDcfg driver. +* +* @return None. +* +* @note C-style signature: +* void XDcfg_SelectPcapInterface(XDcfg* InstancePtr) +* +*****************************************************************************/ +#define XDcfg_SelectPcapInterface(InstancePtr) \ + XDcfg_WriteReg((InstancePtr)->Config.BaseAddr, XDCFG_CTRL_OFFSET, \ + ((XDcfg_ReadReg((InstancePtr)->Config.BaseAddr, XDCFG_CTRL_OFFSET)) \ + | XDCFG_CTRL_PCAP_PR_MASK)) + + + +/************************** Function Prototypes ******************************/ + +/* + * Lookup configuration in xdevcfg_sinit.c. + */ +XDcfg_Config *XDcfg_LookupConfig(u16 DeviceId); + +/* + * Selftest function in xdevcfg_selftest.c + */ +int XDcfg_SelfTest(XDcfg *InstancePtr); + +/* + * Interface functions in xdevcfg.c + */ +int XDcfg_CfgInitialize(XDcfg *InstancePtr, + XDcfg_Config *ConfigPtr, u32 EffectiveAddress); + +void XDcfg_EnablePCAP(XDcfg *InstancePtr); + +void XDcfg_DisablePCAP(XDcfg *InstancePtr); + +void XDcfg_SetControlRegister(XDcfg *InstancePtr, u32 Mask); + +void XDcfg_ClearControlRegister(XDcfg *InstancePtr, u32 Mask); + +u32 XDcfg_GetControlRegister(XDcfg *InstancePtr); + +void XDcfg_SetLockRegister(XDcfg *InstancePtr, u32 Data); + +u32 XDcfg_GetLockRegister(XDcfg *InstancePtr); + +void XDcfg_SetConfigRegister(XDcfg *InstancePtr, u32 Data); + +u32 XDcfg_GetConfigRegister(XDcfg *InstancePtr); + +void XDcfg_SetStatusRegister(XDcfg *InstancePtr, u32 Data); + +u32 XDcfg_GetStatusRegister(XDcfg *InstancePtr); + +void XDcfg_SetRomShadowRegister(XDcfg *InstancePtr, u32 Data); + +u32 XDcfg_GetSoftwareIdRegister(XDcfg *InstancePtr); + +void XDcfg_SetMiscControlRegister(XDcfg *InstancePtr, u32 Mask); + +u32 XDcfg_GetMiscControlRegister(XDcfg *InstancePtr); + +u32 XDcfg_IsDmaBusy(XDcfg *InstancePtr); + +void XDcfg_InitiateDma(XDcfg *InstancePtr, u32 SourcePtr, u32 DestPtr, + u32 SrcWordLength, u32 DestWordLength); + +u32 XDcfg_Transfer(XDcfg *InstancePtr, + void *SourcePtr, u32 SrcWordLength, + void *DestPtr, u32 DestWordLength, + u32 TransferType); + +/* + * Interrupt related function prototypes implemented in xdevcfg_intr.c + */ +void XDcfg_IntrEnable(XDcfg *InstancePtr, u32 Mask); + +void XDcfg_IntrDisable(XDcfg *InstancePtr, u32 Mask); + +u32 XDcfg_IntrGetEnabled(XDcfg *InstancePtr); + +u32 XDcfg_IntrGetStatus(XDcfg *InstancePtr); + +void XDcfg_IntrClear(XDcfg *InstancePtr, u32 Mask); + +void XDcfg_InterruptHandler(XDcfg *InstancePtr); + +void XDcfg_SetHandler(XDcfg *InstancePtr, void *CallBackFunc, + void *CallBackRef); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/include/xdevcfg_hw.h b/df_datalink/bsp/ps7_cortexa9_0/include/xdevcfg_hw.h new file mode 100644 index 0000000..80b6678 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/include/xdevcfg_hw.h @@ -0,0 +1,391 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xdevcfg_hw.h +* @addtogroup devcfg_v3_3 +* @{ +* +* This file contains the hardware interface to the Device Config Interface. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 1.00a hvm 02/07/11 First release
+* 2.01a nm  08/01/12 Added defines for the PS Version bits,
+*	             removed the FIFO Flush bits from the
+*		     Miscellaneous Control Reg
+* 2.03a nm  04/19/13 Fixed CR# 703728.
+*		     Updated the register definitions as per the latest TRM
+*		     version UG585 (v1.4) November 16, 2012.
+* 2.04a	kpc	10/07/13 Added function prototype.
+* 3.00a	kpc	25/02/14 Corrected the XDCFG_BASE_ADDRESS macro value.
+* 
+* +******************************************************************************/ +#ifndef XDCFG_HW_H /* prevent circular inclusions */ +#define XDCFG_HW_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_io.h" + +/************************** Constant Definitions *****************************/ + +/** @name Register Map + * Offsets of registers from the start of the device + * @{ + */ + +#define XDCFG_CTRL_OFFSET 0x00 /**< Control Register */ +#define XDCFG_LOCK_OFFSET 0x04 /**< Lock Register */ +#define XDCFG_CFG_OFFSET 0x08 /**< Configuration Register */ +#define XDCFG_INT_STS_OFFSET 0x0C /**< Interrupt Status Register */ +#define XDCFG_INT_MASK_OFFSET 0x10 /**< Interrupt Mask Register */ +#define XDCFG_STATUS_OFFSET 0x14 /**< Status Register */ +#define XDCFG_DMA_SRC_ADDR_OFFSET 0x18 /**< DMA Source Address Register */ +#define XDCFG_DMA_DEST_ADDR_OFFSET 0x1C /**< DMA Destination Address Reg */ +#define XDCFG_DMA_SRC_LEN_OFFSET 0x20 /**< DMA Source Transfer Length */ +#define XDCFG_DMA_DEST_LEN_OFFSET 0x24 /**< DMA Destination Transfer */ +#define XDCFG_ROM_SHADOW_OFFSET 0x28 /**< DMA ROM Shadow Register */ +#define XDCFG_MULTIBOOT_ADDR_OFFSET 0x2C /**< Multi BootAddress Pointer */ +#define XDCFG_SW_ID_OFFSET 0x30 /**< Software ID Register */ +#define XDCFG_UNLOCK_OFFSET 0x34 /**< Unlock Register */ +#define XDCFG_MCTRL_OFFSET 0x80 /**< Miscellaneous Control Reg */ + +/* @} */ + +/** @name Control Register Bit definitions + * @{ + */ + +#define XDCFG_CTRL_FORCE_RST_MASK 0x80000000 /**< Force into + * Secure Reset + */ +#define XDCFG_CTRL_PCFG_PROG_B_MASK 0x40000000 /**< Program signal to + * Reset FPGA + */ +#define XDCFG_CTRL_PCFG_POR_CNT_4K_MASK 0x20000000 /**< Control PL POR timer */ +#define XDCFG_CTRL_PCAP_PR_MASK 0x08000000 /**< Enable PCAP for PR */ +#define XDCFG_CTRL_PCAP_MODE_MASK 0x04000000 /**< Enable PCAP */ +#define XDCFG_CTRL_PCAP_RATE_EN_MASK 0x02000000 /**< Enable PCAP send data + * to FPGA every 4 PCAP + * cycles + */ +#define XDCFG_CTRL_MULTIBOOT_EN_MASK 0x01000000 /**< Multiboot Enable */ +#define XDCFG_CTRL_JTAG_CHAIN_DIS_MASK 0x00800000 /**< JTAG Chain Disable */ +#define XDCFG_CTRL_USER_MODE_MASK 0x00008000 /**< User Mode Mask */ +#define XDCFG_CTRL_PCFG_AES_FUSE_MASK 0x00001000 /**< AES key source */ +#define XDCFG_CTRL_PCFG_AES_EN_MASK 0x00000E00 /**< AES Enable Mask */ +#define XDCFG_CTRL_SEU_EN_MASK 0x00000100 /**< SEU Enable Mask */ +#define XDCFG_CTRL_SEC_EN_MASK 0x00000080 /**< Secure/Non Secure + * Status mask + */ +#define XDCFG_CTRL_SPNIDEN_MASK 0x00000040 /**< Secure Non Invasive + * Debug Enable + */ +#define XDCFG_CTRL_SPIDEN_MASK 0x00000020 /**< Secure Invasive + * Debug Enable + */ +#define XDCFG_CTRL_NIDEN_MASK 0x00000010 /**< Non-Invasive Debug + * Enable + */ +#define XDCFG_CTRL_DBGEN_MASK 0x00000008 /**< Invasive Debug + * Enable + */ +#define XDCFG_CTRL_DAP_EN_MASK 0x00000007 /**< DAP Enable Mask */ + +/* @} */ + +/** @name Lock register bit definitions + * @{ + */ + +#define XDCFG_LOCK_AES_EFUSE_MASK 0x00000010 /**< Lock AES Efuse bit */ +#define XDCFG_LOCK_AES_EN_MASK 0x00000008 /**< Lock AES_EN update */ +#define XDCFG_LOCK_SEU_MASK 0x00000004 /**< Lock SEU_En update */ +#define XDCFG_LOCK_SEC_MASK 0x00000002 /**< Lock SEC_EN and + * USER_MODE + */ +#define XDCFG_LOCK_DBG_MASK 0x00000001 /**< This bit locks + * security config + * including: DAP_En, + * DBGEN,, + * NIDEN, SPNIEN + */ +/*@}*/ + + + +/** @name Config Register Bit definitions + * @{ + */ +#define XDCFG_CFG_RFIFO_TH_MASK 0x00000C00 /**< Read FIFO + * Threshold Mask + */ +#define XDCFG_CFG_WFIFO_TH_MASK 0x00000300 /**< Write FIFO Threshold + * Mask + */ +#define XDCFG_CFG_RCLK_EDGE_MASK 0x00000080 /**< Read data active + * clock edge + */ +#define XDCFG_CFG_WCLK_EDGE_MASK 0x00000040 /**< Write data active + * clock edge + */ +#define XDCFG_CFG_DISABLE_SRC_INC_MASK 0x00000020 /**< Disable Source address + * increment mask + */ +#define XDCFG_CFG_DISABLE_DST_INC_MASK 0x00000010 /**< Disable Destination + * address increment + * mask + */ +/* @} */ + + +/** @name Interrupt Status/Mask Register Bit definitions + * @{ + */ +#define XDCFG_IXR_PSS_GTS_USR_B_MASK 0x80000000 /**< Tri-state IO during + * HIZ + */ +#define XDCFG_IXR_PSS_FST_CFG_B_MASK 0x40000000 /**< First configuration + * done + */ +#define XDCFG_IXR_PSS_GPWRDWN_B_MASK 0x20000000 /**< Global power down */ +#define XDCFG_IXR_PSS_GTS_CFG_B_MASK 0x10000000 /**< Tri-state IO during + * configuration + */ +#define XDCFG_IXR_PSS_CFG_RESET_B_MASK 0x08000000 /**< PL configuration + * reset + */ +#define XDCFG_IXR_AXI_WTO_MASK 0x00800000 /**< AXI Write Address + * or Data or response + * timeout + */ +#define XDCFG_IXR_AXI_WERR_MASK 0x00400000 /**< AXI Write response + * error + */ +#define XDCFG_IXR_AXI_RTO_MASK 0x00200000 /**< AXI Read Address or + * response timeout + */ +#define XDCFG_IXR_AXI_RERR_MASK 0x00100000 /**< AXI Read response + * error + */ +#define XDCFG_IXR_RX_FIFO_OV_MASK 0x00040000 /**< Rx FIFO Overflow */ +#define XDCFG_IXR_WR_FIFO_LVL_MASK 0x00020000 /**< Tx FIFO less than + * threshold */ +#define XDCFG_IXR_RD_FIFO_LVL_MASK 0x00010000 /**< Rx FIFO greater than + * threshold */ +#define XDCFG_IXR_DMA_CMD_ERR_MASK 0x00008000 /**< Illegal DMA command */ +#define XDCFG_IXR_DMA_Q_OV_MASK 0x00004000 /**< DMA command queue + * overflow + */ +#define XDCFG_IXR_DMA_DONE_MASK 0x00002000 /**< DMA Command Done */ +#define XDCFG_IXR_D_P_DONE_MASK 0x00001000 /**< DMA and PCAP + * transfers Done + */ +#define XDCFG_IXR_P2D_LEN_ERR_MASK 0x00000800 /**< PCAP to DMA transfer + * length error + */ +#define XDCFG_IXR_PCFG_HMAC_ERR_MASK 0x00000040 /**< HMAC error mask */ +#define XDCFG_IXR_PCFG_SEU_ERR_MASK 0x00000020 /**< SEU Error mask */ +#define XDCFG_IXR_PCFG_POR_B_MASK 0x00000010 /**< FPGA POR mask */ +#define XDCFG_IXR_PCFG_CFG_RST_MASK 0x00000008 /**< FPGA Reset mask */ +#define XDCFG_IXR_PCFG_DONE_MASK 0x00000004 /**< Done Signal Mask */ +#define XDCFG_IXR_PCFG_INIT_PE_MASK 0x00000002 /**< Detect Positive edge + * of Init Signal + */ +#define XDCFG_IXR_PCFG_INIT_NE_MASK 0x00000001 /**< Detect Negative edge + * of Init Signal + */ +#define XDCFG_IXR_ERROR_FLAGS_MASK (XDCFG_IXR_AXI_WTO_MASK | \ + XDCFG_IXR_AXI_WERR_MASK | \ + XDCFG_IXR_AXI_RTO_MASK | \ + XDCFG_IXR_AXI_RERR_MASK | \ + XDCFG_IXR_RX_FIFO_OV_MASK | \ + XDCFG_IXR_DMA_CMD_ERR_MASK |\ + XDCFG_IXR_DMA_Q_OV_MASK | \ + XDCFG_IXR_P2D_LEN_ERR_MASK |\ + XDCFG_IXR_PCFG_HMAC_ERR_MASK) + + +#define XDCFG_IXR_ALL_MASK 0x00F7F8EF + + + +/* @} */ + + +/** @name Status Register Bit definitions + * @{ + */ +#define XDCFG_STATUS_DMA_CMD_Q_F_MASK 0x80000000 /**< DMA command + * Queue full + */ +#define XDCFG_STATUS_DMA_CMD_Q_E_MASK 0x40000000 /**< DMA command + * Queue empty + */ +#define XDCFG_STATUS_DMA_DONE_CNT_MASK 0x30000000 /**< Number of + * completed DMA + * transfers + */ +#define XDCFG_STATUS_RX_FIFO_LVL_MASK 0x01F000000 /**< Rx FIFO level */ +#define XDCFG_STATUS_TX_FIFO_LVL_MASK 0x0007F000 /**< Tx FIFO level */ + +#define XDCFG_STATUS_PSS_GTS_USR_B 0x00000800 /**< Tri-state IO + * during HIZ + */ +#define XDCFG_STATUS_PSS_FST_CFG_B 0x00000400 /**< First PL config + * done + */ +#define XDCFG_STATUS_PSS_GPWRDWN_B 0x00000200 /**< Global power down */ +#define XDCFG_STATUS_PSS_GTS_CFG_B 0x00000100 /**< Tri-state IO during + * config + */ +#define XDCFG_STATUS_SECURE_RST_MASK 0x00000080 /**< Secure Reset + * POR Status + */ +#define XDCFG_STATUS_ILLEGAL_APB_ACCESS_MASK 0x00000040 /**< Illegal APB + * access + */ +#define XDCFG_STATUS_PSS_CFG_RESET_B 0x00000020 /**< PL config + * reset status + */ +#define XDCFG_STATUS_PCFG_INIT_MASK 0x00000010 /**< FPGA Init + * Status + */ +#define XDCFG_STATUS_EFUSE_BBRAM_KEY_DISABLE_MASK 0x00000008 + /**< BBRAM key + * disable + */ +#define XDCFG_STATUS_EFUSE_SEC_EN_MASK 0x00000004 /**< Efuse Security + * Enable Status + */ +#define XDCFG_STATUS_EFUSE_JTAG_DIS_MASK 0x00000002 /**< EFuse JTAG + * Disable + * status + */ +/* @} */ + + +/** @name DMA Source/Destination Transfer Length Register Bit definitions + * @{ + */ +#define XDCFG_DMA_LEN_MASK 0x7FFFFFF /**< Length Mask */ +/*@}*/ + + + + +/** @name Miscellaneous Control Register Bit definitions + * @{ + */ +#define XDCFG_MCTRL_PCAP_PS_VERSION_MASK 0xF0000000 /**< PS Version Mask */ +#define XDCFG_MCTRL_PCAP_PS_VERSION_SHIFT 28 /**< PS Version Shift */ +#define XDCFG_MCTRL_PCAP_LPBK_MASK 0x00000010 /**< PCAP loopback mask */ +/* @} */ + +/** @name FIFO Threshold Bit definitions + * @{ + */ + +#define XDCFG_CFG_FIFO_QUARTER 0x0 /**< Quarter empty */ +#define XDCFG_CFG_FIFO_HALF 0x1 /**< Half empty */ +#define XDCFG_CFG_FIFO_3QUARTER 0x2 /**< 3/4 empty */ +#define XDCFG_CFG_FIFO_EMPTY 0x4 /**< Empty */ +/* @}*/ + + +/* Miscellaneous constant values */ +#define XDCFG_DMA_INVALID_ADDRESS 0xFFFFFFFF /**< Invalid DMA address */ +#define XDCFG_UNLOCK_DATA 0x757BDF0D /**< First APB access data*/ +#define XDCFG_BASE_ADDRESS 0xF8007000 /**< Device Config base + * address + */ +#define XDCFG_CONFIG_RESET_VALUE 0x508 /**< Config reg reset value */ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/****************************************************************************/ +/** +* +* Read the given register. +* +* @param BaseAddr is the base address of the device +* @param RegOffset is the register offset to be read +* +* @return The 32-bit value of the register +* +* @note C-style signature: +* u32 XDcfg_ReadReg(u32 BaseAddr, u32 RegOffset) +* +*****************************************************************************/ +#define XDcfg_ReadReg(BaseAddr, RegOffset) \ + Xil_In32((BaseAddr) + (RegOffset)) + +/****************************************************************************/ +/** +* +* Write to the given register. +* +* @param BaseAddr is the base address of the device +* @param RegOffset is the register offset to be written +* @param Data is the 32-bit value to write to the register +* +* @return None. +* +* @note C-style signature: +* void XDcfg_WriteReg(u32 BaseAddr, u32 RegOffset, u32 Data) +* +*****************************************************************************/ +#define XDcfg_WriteReg(BaseAddr, RegOffset, Data) \ + Xil_Out32((BaseAddr) + (RegOffset), (Data)) + +/************************** Function Prototypes ******************************/ +/* + * Perform reset operation to the devcfg interface + */ +void XDcfg_ResetHw(u32 BaseAddr); +/************************** Variable Definitions *****************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/include/xdmaps.h b/df_datalink/bsp/ps7_cortexa9_0/include/xdmaps.h new file mode 100644 index 0000000..73e2b1e --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/include/xdmaps.h @@ -0,0 +1,349 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xdmaps.h +* @addtogroup dmaps_v2_4 +* @{ +* @details +* +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  	Date     Changes
+* ----- ------ -------- ----------------------------------------------
+* 1.00	hbm    08/19/10 First Release
+* 1.01a nm     12/20/12 Added definition XDMAPS_CHANNELS_PER_DEV which specifies
+*		        the maximum number of channels.
+*		        Replaced the usage of XPAR_XDMAPS_CHANNELS_PER_DEV
+*                       with XDMAPS_CHANNELS_PER_DEV defined in xdmaps_hw.h.
+*			Added the tcl file to automatically generate the
+*			xparameters.h
+* 1.02a sg     05/16/12 Made changes for doxygen and moved some function
+*			header from the xdmaps.h file to xdmaps.c file
+*			Other cleanup for coding guidelines and CR 657109
+*			and CR 657898
+*			The xdmaps_example_no_intr.c example is removed
+*			as it is using interrupts  and is similar to
+*			the interrupt example - CR 652477
+* 1.03a sg     07/16/2012 changed inline to __inline for CR665681
+* 1.04a nm     10/22/2012 Fixed CR# 681671.
+* 1.05a nm     04/15/2013 Fixed CR# 704396. Removed warnings when compiled
+*			  with -Wall and -Wextra option in bsp.
+*	       05/01/2013 Fixed CR# 700189. Changed XDmaPs_BuildDmaProg()
+*			  function description.
+*			  Fixed CR# 704396. Removed unused variables
+*			  UseM2MByte & MemBurstLen from XDmaPs_BuildDmaProg()
+*			  function.
+* 1.07a asa    11/02/13. Made changes to fix compilation issues for iarcc.
+*			   Removed the PDBG prints. By default they were always
+*			   defined out and never used. The PDBG is non-standard for
+*			   Xilinx drivers and no other driver does something similar.
+*			   Since there is no easy way to fix compilation issues with
+*			   the IARCC compiler around PDBG, it is better to remove it.
+*			   Users can always use xil_printfs if they want to debug.
+* 2.0   adk    10/12/13  Updated as per the New Tcl API's
+* 2.01  kpc    08/23/14  Fixed the IAR compiler reported errors
+* 2.2   mus    08/12/16  Declared all inline functions in xdmaps.c as extern, to avoid
+*                        linker error for IAR compiler
+* 2.3   ms     01/23/17 Modified xil_printf statement in main function for all
+*                       examples to ensure that "Successfully ran" and "Failed"
+*                       strings are available in all examples. This is a fix
+*                       for CR-965028.
+*       ms     03/17/17 Added readme.txt file in examples folder for doxygen
+*                       generation.
+* 2.4   adk    13/08/18 Fixed armcc compiler warnings in the driver CR-1008310.
+* 
+* +*****************************************************************************/ + +#ifndef XDMAPS_H /* prevent circular inclusions */ +#define XDMAPS_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files ********************************/ + +#include "xparameters.h" +#include "xil_types.h" +#include "xil_assert.h" +#include "xstatus.h" + +#include "xdmaps_hw.h" + +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + +/** + * This typedef contains configuration information for the device. + */ +typedef struct { + u16 DeviceId; /**< Unique ID of device */ + u32 BaseAddress; /**< Base address of device (IPIF) */ +} XDmaPs_Config; + + +/** DMA channle control structure. It's for AXI bus transaction. + * This struct will be translated into a 32-bit channel control register value. + */ +typedef struct { + unsigned int EndianSwapSize; /**< Endian swap size. */ + unsigned int DstCacheCtrl; /**< Destination cache control */ + unsigned int DstProtCtrl; /**< Destination protection control */ + unsigned int DstBurstLen; /**< Destination burst length */ + unsigned int DstBurstSize; /**< Destination burst size */ + unsigned int DstInc; /**< Destination incrementing or fixed + * address */ + unsigned int SrcCacheCtrl; /**< Source cache control */ + unsigned int SrcProtCtrl; /**< Source protection control */ + unsigned int SrcBurstLen; /**< Source burst length */ + unsigned int SrcBurstSize; /**< Source burst size */ + unsigned int SrcInc; /**< Source incrementing or fixed + * address */ +} XDmaPs_ChanCtrl; + +/** DMA block descriptor stucture. + */ +typedef struct { + u32 SrcAddr; /**< Source starting address */ + u32 DstAddr; /**< Destination starting address */ + unsigned int Length; /**< Number of bytes for the block */ +} XDmaPs_BD; + +/** + * A DMA command consisits of a channel control struct, a block descriptor, + * a user defined program, a pointer pointing to generated DMA program, and + * execution result. + * + */ +typedef struct { + XDmaPs_ChanCtrl ChanCtrl; /**< Channel Control Struct */ + XDmaPs_BD BD; /**< Together with SgLength field, + * it's a scatter-gather list. + */ + void *UserDmaProg; /**< If user wants the driver to + * execute their own DMA program, + * this field points to the DMA + * program. + */ + int UserDmaProgLength; /**< The length of user defined + * DMA program. + */ + + void *GeneratedDmaProg; /**< The DMA program genreated + * by the driver. This field will be + * set if a user invokes the DMA + * program generation function. Or + * the DMA command is finished and + * a user informs the driver not to + * release the program buffer. + * This field has two purposes, one + * is to ask the driver to generate + * a DMA program while the DMAC is + * performaning DMA transactions. The + * other purpose is to debug the + * driver. + */ + int GeneratedDmaProgLength; /**< The length of the DMA program + * generated by the driver + */ + int DmaStatus; /**< 0 on success, otherwise error code + */ + u32 ChanFaultType; /**< Channel fault type in case of fault + */ + u32 ChanFaultPCAddr; /**< Channel fault PC address + */ +} XDmaPs_Cmd; + +/** + * It's the done handler a user can set for a channel + */ +typedef void (*XDmaPsDoneHandler) (unsigned int Channel, + XDmaPs_Cmd *DmaCmd, + void *CallbackRef); + +/** + * It's the fault handler a user can set for a channel + */ +typedef void (*XDmaPsFaultHandler) (unsigned int Channel, + XDmaPs_Cmd *DmaCmd, + void *CallbackRef); + +#define XDMAPS_MAX_CHAN_BUFS 2 +#define XDMAPS_CHAN_BUF_LEN 128 + +/** + * The XDmaPs_ProgBuf is the struct for a DMA program buffer. + */ +typedef struct { + char Buf[XDMAPS_CHAN_BUF_LEN]; /**< The actual buffer the holds the + * content */ + unsigned Len; /**< The actual length of the DMA + * program in bytes. */ + int Allocated; /**< A tag indicating whether the + * buffer is allocated or not */ +} XDmaPs_ProgBuf; + +/** + * The XDmaPs_ChannelData is a struct to book keep individual channel of + * the DMAC. + */ +typedef struct { + unsigned DevId; /**< Device id indicating which DMAC */ + unsigned ChanId; /**< Channel number of the DMAC */ + XDmaPs_ProgBuf ProgBufPool[XDMAPS_MAX_CHAN_BUFS]; /**< A pool of + program buffers*/ + XDmaPsDoneHandler DoneHandler; /**< Done interrupt handler */ + void *DoneRef; /**< Done interrupt callback data */ + XDmaPs_Cmd *DmaCmdToHw; /**< DMA command being executed */ + XDmaPs_Cmd *DmaCmdFromHw; /**< DMA command that is finished. + * This field is for debugging purpose + */ + int HoldDmaProg; /**< A tag indicating whether to hold the + * DMA program after the DMA is done. + */ + +} XDmaPs_ChannelData; + +/** + * The XDmaPs driver instance data structure. A pointer to an instance data + * structure is passed around by functions to refer to a specific driver + * instance. + */ +typedef struct { + XDmaPs_Config Config; /**< Configuration data structure */ + int IsReady; /**< Device is Ready */ + int CacheLength; /**< icache length */ + XDmaPsFaultHandler FaultHandler; /**< fault interrupt handler */ + void *FaultRef; /**< fault call back data */ + XDmaPs_ChannelData Chans[XDMAPS_CHANNELS_PER_DEV]; + /**< + * channel data + */ +} XDmaPs; + +/* + * Functions implemented in xdmaps.c + */ +int XDmaPs_CfgInitialize(XDmaPs *InstPtr, + XDmaPs_Config *Config, + u32 EffectiveAddr); + +int XDmaPs_Start(XDmaPs *InstPtr, unsigned int Channel, + XDmaPs_Cmd *Cmd, + int HoldDmaProg); + +int XDmaPs_IsActive(XDmaPs *InstPtr, unsigned int Channel); +int XDmaPs_GenDmaProg(XDmaPs *InstPtr, unsigned int Channel, + XDmaPs_Cmd *Cmd); +int XDmaPs_FreeDmaProg(XDmaPs *InstPtr, unsigned int Channel, + XDmaPs_Cmd *Cmd); +void XDmaPs_Print_DmaProg(XDmaPs_Cmd *Cmd); + + +int XDmaPs_ResetManager(XDmaPs *InstPtr); +int XDmaPs_ResetChannel(XDmaPs *InstPtr, unsigned int Channel); + + +int XDmaPs_SetDoneHandler(XDmaPs *InstPtr, + unsigned Channel, + XDmaPsDoneHandler DoneHandler, + void *CallbackRef); + +int XDmaPs_SetFaultHandler(XDmaPs *InstPtr, + XDmaPsFaultHandler FaultHandler, + void *CallbackRef); + +void XDmaPs_Print_DmaProg(XDmaPs_Cmd *Cmd); +int XDmaPs_Instr_DMARMB(char *DmaProg); +int XDmaPs_Instr_DMAWMB(char *DmaProg); + +/** + * To avoid linking error,Declare all inline functions as extern for + * IAR compiler + */ +#ifdef __ICCARM__ +extern INLINE int XDmaPs_Instr_DMAEND(char *DmaProg); +extern INLINE void XDmaPs_Memcpy4(char *Dst, char *Src); +extern INLINE int XDmaPs_Instr_DMAGO(char *DmaProg, unsigned int Cn, + u32 Imm, unsigned int Ns); +extern INLINE int XDmaPs_Instr_DMALD(char *DmaProg); +extern INLINE int XDmaPs_Instr_DMALP(char *DmaProg, unsigned Lc, + unsigned LoopIterations); +extern INLINE int XDmaPs_Instr_DMALPEND(char *DmaProg, char *BodyStart, unsigned Lc); +extern INLINE int XDmaPs_Instr_DMAMOV(char *DmaProg, unsigned Rd, u32 Imm); +extern INLINE int XDmaPs_Instr_DMANOP(char *DmaProg); +extern INLINE int XDmaPs_Instr_DMASEV(char *DmaProg, unsigned int EventNumber); +extern INLINE int XDmaPs_Instr_DMAST(char *DmaProg); +extern INLINE unsigned XDmaPs_ToEndianSwapSizeBits(unsigned int EndianSwapSize); +extern INLINE unsigned XDmaPs_ToBurstSizeBits(unsigned BurstSize); +#endif + +/** + * Driver done interrupt service routines for the channels. + * We need this done ISR mainly because the driver needs to release the + * DMA program buffer. This is the one that connects the GIC + */ +void XDmaPs_DoneISR_0(XDmaPs *InstPtr); +void XDmaPs_DoneISR_1(XDmaPs *InstPtr); +void XDmaPs_DoneISR_2(XDmaPs *InstPtr); +void XDmaPs_DoneISR_3(XDmaPs *InstPtr); +void XDmaPs_DoneISR_4(XDmaPs *InstPtr); +void XDmaPs_DoneISR_5(XDmaPs *InstPtr); +void XDmaPs_DoneISR_6(XDmaPs *InstPtr); +void XDmaPs_DoneISR_7(XDmaPs *InstPtr); + +/** + * Driver fault interrupt service routine + */ +void XDmaPs_FaultISR(XDmaPs *InstPtr); + + +/* + * Static loopup function implemented in xdmaps_sinit.c + */ +XDmaPs_Config *XDmaPs_LookupConfig(u16 DeviceId); + + +/* + * self-test functions in xdmaps_selftest.c + */ +int XDmaPs_SelfTest(XDmaPs *InstPtr); + + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/include/xdmaps_hw.h b/df_datalink/bsp/ps7_cortexa9_0/include/xdmaps_hw.h new file mode 100644 index 0000000..42dfe69 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/include/xdmaps_hw.h @@ -0,0 +1,289 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xdmaps_hw.h +* @addtogroup dmaps_v2_4 +* @{ +* +* This header file contains the hardware interface of an XDmaPs device. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who   Date     Changes
+* ----- ----  -------- ----------------------------------------------
+* 1.00a	hbm   08/18/10 First Release
+* 1.01a nm    12/20/12 Added definition XDMAPS_CHANNELS_PER_DEV which specifies
+*		       the maximum number of channels.
+*		       Replaced the usage of XPAR_XDMAPS_CHANNELS_PER_DEV
+*                      with XDMAPS_CHANNELS_PER_DEV defined in xdmaps_hw.h
+* 1.02a sg    05/16/12 Made changes for doxygen
+* 1.06a kpc   07/10/13 Added function prototype
+* 
+* +******************************************************************************/ + +#ifndef XDMAPS_HW_H /* prevent circular inclusions */ +#define XDMAPS_HW_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_io.h" + +/************************** Constant Definitions *****************************/ + +/** @name Register Map + * + * Register offsets for the DMAC. + * @{ + */ + +#define XDMAPS_DS_OFFSET 0x000 /* DMA Status Register */ +#define XDMAPS_DPC_OFFSET 0x004 /* DMA Program Counter Rregister */ +#define XDMAPS_INTEN_OFFSET 0X020 /* DMA Interrupt Enable Register */ +#define XDMAPS_ES_OFFSET 0x024 /* DMA Event Status Register */ +#define XDMAPS_INTSTATUS_OFFSET 0x028 /* DMA Interrupt Status Register + */ +#define XDMAPS_INTCLR_OFFSET 0x02c /* DMA Interrupt Clear Register */ +#define XDMAPS_FSM_OFFSET 0x030 /* DMA Fault Status DMA Manager + * Register + */ +#define XDMAPS_FSC_OFFSET 0x034 /* DMA Fault Status DMA Chanel Register + */ +#define XDMAPS_FTM_OFFSET 0x038 /* DMA Fault Type DMA Manager Register */ + +#define XDMAPS_FTC0_OFFSET 0x040 /* DMA Fault Type for DMA Channel 0 */ +/* + * The offset for the rest of the FTC registers is calculated as + * FTC0 + dev_chan_num * 4 + */ +#define XDmaPs_FTCn_OFFSET(ch) (XDMAPS_FTC0_OFFSET + (ch) * 4) + +#define XDMAPS_CS0_OFFSET 0x100 /* Channel Status for DMA Channel 0 */ +/* + * The offset for the rest of the CS registers is calculated as + * CS0 + * dev_chan_num * 0x08 + */ +#define XDmaPs_CSn_OFFSET(ch) (XDMAPS_CS0_OFFSET + (ch) * 8) + +#define XDMAPS_CPC0_OFFSET 0x104 /* Channel Program Counter for DMA + * Channel 0 + */ +/* + * The offset for the rest of the CPC registers is calculated as + * CPC0 + dev_chan_num * 0x08 + */ +#define XDmaPs_CPCn_OFFSET(ch) (XDMAPS_CPC0_OFFSET + (ch) * 8) + +#define XDMAPS_SA_0_OFFSET 0x400 /* Source Address Register for DMA + * Channel 0 + */ +/* The offset for the rest of the SA registers is calculated as + * SA_0 + dev_chan_num * 0x20 + */ +#define XDmaPs_SA_n_OFFSET(ch) (XDMAPS_SA_0_OFFSET + (ch) * 0x20) + +#define XDMAPS_DA_0_OFFSET 0x404 /* Destination Address Register for + * DMA Channel 0 + */ +/* The offset for the rest of the DA registers is calculated as + * DA_0 + dev_chan_num * 0x20 + */ +#define XDmaPs_DA_n_OFFSET(ch) (XDMAPS_DA_0_OFFSET + (ch) * 0x20) + +#define XDMAPS_CC_0_OFFSET 0x408 /* Channel Control Register for + * DMA Channel 0 + */ +/* + * The offset for the rest of the CC registers is calculated as + * CC_0 + dev_chan_num * 0x20 + */ +#define XDmaPs_CC_n_OFFSET(ch) (XDMAPS_CC_0_OFFSET + (ch) * 0x20) + +#define XDMAPS_LC0_0_OFFSET 0x40C /* Loop Counter 0 for DMA Channel 0 */ +/* + * The offset for the rest of the LC0 registers is calculated as + * LC_0 + dev_chan_num * 0x20 + */ +#define XDmaPs_LC0_n_OFFSET(ch) (XDMAPS_LC0_0_OFFSET + (ch) * 0x20) +#define XDMAPS_LC1_0_OFFSET 0x410 /* Loop Counter 1 for DMA Channel 0 */ +/* + * The offset for the rest of the LC1 registers is calculated as + * LC_0 + dev_chan_num * 0x20 + */ +#define XDmaPs_LC1_n_OFFSET(ch) (XDMAPS_LC1_0_OFFSET + (ch) * 0x20) + +#define XDMAPS_DBGSTATUS_OFFSET 0xD00 /* Debug Status Register */ +#define XDMAPS_DBGCMD_OFFSET 0xD04 /* Debug Command Register */ +#define XDMAPS_DBGINST0_OFFSET 0xD08 /* Debug Instruction 0 Register */ +#define XDMAPS_DBGINST1_OFFSET 0xD0C /* Debug Instruction 1 Register */ + +#define XDMAPS_CR0_OFFSET 0xE00 /* Configuration Register 0 */ +#define XDMAPS_CR1_OFFSET 0xE04 /* Configuration Register 1 */ +#define XDMAPS_CR2_OFFSET 0xE08 /* Configuration Register 2 */ +#define XDMAPS_CR3_OFFSET 0xE0C /* Configuration Register 3 */ +#define XDMAPS_CR4_OFFSET 0xE10 /* Configuration Register 4 */ +#define XDMAPS_CRDN_OFFSET 0xE14 /* Configuration Register Dn */ + +#define XDMAPS_PERIPH_ID_0_OFFSET 0xFE0 /* Peripheral Identification + * Register 0 + */ +#define XDMAPS_PERIPH_ID_1_OFFSET 0xFE4 /* Peripheral Identification + * Register 1 + */ +#define XDMAPS_PERIPH_ID_2_OFFSET 0xFE8 /* Peripheral Identification + * Register 2 + */ +#define XDMAPS_PERIPH_ID_3_OFFSET 0xFEC /* Peripheral Identification + * Register 3 + */ +#define XDMAPS_PCELL_ID_0_OFFSET 0xFF0 /* PrimeCell Identification + * Register 0 + */ +#define XDMAPS_PCELL_ID_1_OFFSET 0xFF4 /* PrimeCell Identification + * Register 1 + */ +#define XDMAPS_PCELL_ID_2_OFFSET 0xFF8 /* PrimeCell Identification + * Register 2 + */ +#define XDMAPS_PCELL_ID_3_OFFSET 0xFFC /* PrimeCell Identification + * Register 3 + */ + +/* + * Some useful register masks + */ +#define XDMAPS_DS_DMA_STATUS 0x0F /* DMA status mask */ +#define XDMAPS_DS_DMA_STATUS_STOPPED 0x00 /* debug status busy mask */ + +#define XDMAPS_DBGSTATUS_BUSY 0x01 /* debug status busy mask */ + +#define XDMAPS_CS_ACTIVE_MASK 0x07 /* channel status active mask, + * llast 3 bits of CS register + */ + +#define XDMAPS_CR1_I_CACHE_LEN_MASK 0x07 /* i_cache_len mask */ + + +/* + * XDMAPS_DBGINST0 - constructs the word for the Debug Instruction-0 Register. + * @b1: Instruction byte 1 + * @b0: Instruction byte 0 + * @ch: Channel number + * @dbg_th: Debug thread encoding: 0 = DMA manager thread, 1 = DMA channel + */ +#define XDmaPs_DBGINST0(b1, b0, ch, dbg_th) \ + (((b1) << 24) | ((b0) << 16) | (((ch) & 0x7) << 8) | ((dbg_th & 0x1))) + +/* @} */ + +/** @name Control Register + * + * The Control register (CR) controls the major functions of the device. + * + * Control Register Bit Definition + */ + +/* @}*/ + + +#define XDMAPS_CHANNELS_PER_DEV 8 + + +/** @name Mode Register + * + * The mode register (MR) defines the mode of transfer as well as the data + * format. If this register is modified during transmission or reception, + * data validity cannot be guaranteed. + * + * Mode Register Bit Definition + * @{ + */ + +/* @} */ + + +/** @name Interrupt Registers + * + * Interrupt control logic uses the interrupt enable register (IER) and the + * interrupt disable register (IDR) to set the value of the bits in the + * interrupt mask register (IMR). The IMR determines whether to pass an + * interrupt to the interrupt status register (ISR). + * Writing a 1 to IER Enbables an interrupt, writing a 1 to IDR disables an + * interrupt. IMR and ISR are read only, and IER and IDR are write only. + * Reading either IER or IDR returns 0x00. + * + * All four registers have the same bit definitions. + * + * @{ + */ + +/* @} */ +#define XDMAPS_INTCLR_ALL_MASK 0xFF + +#define XDmaPs_ReadReg(BaseAddress, RegOffset) \ + Xil_In32((BaseAddress) + (RegOffset)) + +/***************************************************************************/ +/** +* Write a DMAC register. +* +* @param BaseAddress contains the base address of the device. +* @param RegOffset contains the offset from the base address of the device. +* @param RegisterValue is the value to be written to the register. +* +* @return None. +* +* @note +* C-Style signature: +* void XDmaPs_WriteReg(u32 BaseAddress, int RegOffset, +* u32 RegisterValue) +******************************************************************************/ +#define XDmaPs_WriteReg(BaseAddress, RegOffset, RegisterValue) \ + Xil_Out32((BaseAddress) + (RegOffset), (RegisterValue)) +/************************** Variable Definitions *****************************/ + +/************************** Function Prototypes *****************************/ +/* + * Perform reset operation to the dmaps interface + */ +void XDmaPs_ResetHw(u32 BaseAddr); +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/include/xenv.h b/df_datalink/bsp/ps7_cortexa9_0/include/xenv.h new file mode 100644 index 0000000..9c7c4c3 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/include/xenv.h @@ -0,0 +1,183 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xenv.h +* +* Defines common services that are typically found in a host operating. +* environment. This include file simply includes an OS specific file based +* on the compile-time constant BUILD_ENV_*, where * is the name of the target +* environment. +* +* All services are defined as macros. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00b ch   10/24/02 Added XENV_LINUX
+* 1.00a rmm  04/17/02 First release
+* 
+* +******************************************************************************/ + +#ifndef XENV_H /* prevent circular inclusions */ +#define XENV_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Select which target environment we are operating under + */ + +/* VxWorks target environment */ +#if defined XENV_VXWORKS +#include "xenv_vxworks.h" + +/* Linux target environment */ +#elif defined XENV_LINUX +#include "xenv_linux.h" + +/* Unit test environment */ +#elif defined XENV_UNITTEST +#include "ut_xenv.h" + +/* Integration test environment */ +#elif defined XENV_INTTEST +#include "int_xenv.h" + +/* Standalone environment selected */ +#else +#include "xenv_standalone.h" +#endif + + +/* + * The following comments specify the types and macro wrappers that are + * expected to be defined by the target specific header files + */ + +/**************************** Type Definitions *******************************/ + +/*****************************************************************************/ +/** + * + * XENV_TIME_STAMP + * + * A structure that contains a time stamp used by other time stamp macros + * defined below. This structure is processor dependent. + */ + + +/***************** Macros (Inline Functions) Definitions *********************/ + +/*****************************************************************************/ +/** + * + * XENV_MEM_COPY(void *DestPtr, void *SrcPtr, unsigned Bytes) + * + * Copies a non-overlapping block of memory. + * + * @param DestPtr is the destination address to copy data to. + * @param SrcPtr is the source address to copy data from. + * @param Bytes is the number of bytes to copy. + * + * @return None + */ + +/*****************************************************************************/ +/** + * + * XENV_MEM_FILL(void *DestPtr, char Data, unsigned Bytes) + * + * Fills an area of memory with constant data. + * + * @param DestPtr is the destination address to set. + * @param Data contains the value to set. + * @param Bytes is the number of bytes to set. + * + * @return None + */ +/*****************************************************************************/ +/** + * + * XENV_TIME_STAMP_GET(XTIME_STAMP *StampPtr) + * + * Samples the processor's or external timer's time base counter. + * + * @param StampPtr is the storage for the retrieved time stamp. + * + * @return None + */ + +/*****************************************************************************/ +/** + * + * XENV_TIME_STAMP_DELTA_US(XTIME_STAMP *Stamp1Ptr, XTIME_STAMP* Stamp2Ptr) + * + * Computes the delta between the two time stamps. + * + * @param Stamp1Ptr - First sampled time stamp. + * @param Stamp1Ptr - Sedond sampled time stamp. + * + * @return An unsigned int value with units of microseconds. + */ + +/*****************************************************************************/ +/** + * + * XENV_TIME_STAMP_DELTA_MS(XTIME_STAMP *Stamp1Ptr, XTIME_STAMP* Stamp2Ptr) + * + * Computes the delta between the two time stamps. + * + * @param Stamp1Ptr - First sampled time stamp. + * @param Stamp1Ptr - Sedond sampled time stamp. + * + * @return An unsigned int value with units of milliseconds. + */ + +/*****************************************************************************//** + * + * XENV_USLEEP(unsigned delay) + * + * Delay the specified number of microseconds. + * + * @param delay is the number of microseconds to delay. + * + * @return None + */ + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/include/xenv_standalone.h b/df_datalink/bsp/ps7_cortexa9_0/include/xenv_standalone.h new file mode 100644 index 0000000..ef905af --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/include/xenv_standalone.h @@ -0,0 +1,364 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xenv_standalone.h +* +* Defines common services specified by xenv.h. +* +* @note +* This file is not intended to be included directly by driver code. +* Instead, the generic xenv.h file is intended to be included by driver +* code. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a wgr  02/28/07 Added cache handling macros.
+* 1.00a wgr  02/27/07 Simplified code. Deprecated old-style macro names.
+* 1.00a rmm  01/24/06 Implemented XENV_USLEEP. Assume implementation is being
+*                     used under Xilinx standalone BSP.
+* 1.00a xd   11/03/04 Improved support for doxygen.
+* 1.00a rmm  03/21/02 First release
+* 1.00a wgr  03/22/07 Converted to new coding style.
+* 1.00a rpm  06/29/07 Added udelay macro for standalone
+* 1.00a xd   07/19/07 Included xparameters.h as XPAR_ constants are referred
+*                     to in MICROBLAZE section
+* 1.00a ecm  09/19/08 updated for v7.20 of Microblaze, new functionality
+*
+* 
+* +* +******************************************************************************/ + +#ifndef XENV_STANDALONE_H +#define XENV_STANDALONE_H + +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ +/****************************************************************************** + * + * Get the processor dependent includes + * + ******************************************************************************/ + +#include + +#if defined __MICROBLAZE__ +# include "mb_interface.h" +# include "xparameters.h" /* XPAR constants used below in MB section */ + +#elif defined __PPC__ +# include "sleep.h" +# include "xcache_l.h" /* also include xcache_l.h for caching macros */ +#endif + +/****************************************************************************** + * + * MEMCPY / MEMSET related macros. + * + * The following are straight forward implementations of memset and memcpy. + * + * NOTE: memcpy may not work if source and target memory area are overlapping. + * + ******************************************************************************/ +/*****************************************************************************/ +/** + * + * Copies a non-overlapping block of memory. + * + * @param DestPtr + * Destination address to copy data to. + * + * @param SrcPtr + * Source address to copy data from. + * + * @param Bytes + * Number of bytes to copy. + * + * @return None. + * + * @note + * The use of XENV_MEM_COPY is deprecated. Use memcpy() instead. + * + * @note + * This implemention MAY BREAK work if source and target memory + * area are overlapping. + * + *****************************************************************************/ + +#define XENV_MEM_COPY(DestPtr, SrcPtr, Bytes) \ + memcpy((void *) DestPtr, (const void *) SrcPtr, (size_t) Bytes) + + + +/*****************************************************************************/ +/** + * + * Fills an area of memory with constant data. + * + * @param DestPtr + * Destination address to copy data to. + * + * @param Data + * Value to set. + * + * @param Bytes + * Number of bytes to copy. + * + * @return None. + * + * @note + * The use of XENV_MEM_FILL is deprecated. Use memset() instead. + * + *****************************************************************************/ + +#define XENV_MEM_FILL(DestPtr, Data, Bytes) \ + memset((void *) DestPtr, (s32) Data, (size_t) Bytes) + + + +/****************************************************************************** + * + * TIME related macros + * + ******************************************************************************/ + +/** + * A structure that contains a time stamp used by other time stamp macros + * defined below. This structure is processor dependent. + */ +typedef s32 XENV_TIME_STAMP; + +/*****************************************************************************/ +/** + * + * Time is derived from the 64 bit PPC timebase register + * + * @param StampPtr is the storage for the retrieved time stamp. + * + * @return None. + * + * @note + * + * Signature: void XENV_TIME_STAMP_GET(XTIME_STAMP *StampPtr) + *

+ * This macro must be implemented by the user. + * + *****************************************************************************/ +#define XENV_TIME_STAMP_GET(StampPtr) + +/*****************************************************************************/ +/** + * + * This macro is not yet implemented and always returns 0. + * + * @param Stamp1Ptr is the first sampled time stamp. + * @param Stamp2Ptr is the second sampled time stamp. + * + * @return 0 + * + * @note + * + * This macro must be implemented by the user. + * + *****************************************************************************/ +#define XENV_TIME_STAMP_DELTA_US(Stamp1Ptr, Stamp2Ptr) (0) + +/*****************************************************************************/ +/** + * + * This macro is not yet implemented and always returns 0. + * + * @param Stamp1Ptr is the first sampled time stamp. + * @param Stamp2Ptr is the second sampled time stamp. + * + * @return 0 + * + * @note + * + * This macro must be implemented by the user. + * + *****************************************************************************/ +#define XENV_TIME_STAMP_DELTA_MS(Stamp1Ptr, Stamp2Ptr) (0) + +/*****************************************************************************/ +/** + * XENV_USLEEP(unsigned delay) + * + * Delay the specified number of microseconds. Not implemented without OS + * support. + * + * @param delay + * Number of microseconds to delay. + * + * @return None. + * + *****************************************************************************/ + +#ifdef __PPC__ +#define XENV_USLEEP(delay) usleep(delay) +#define udelay(delay) usleep(delay) +#else +#define XENV_USLEEP(delay) +#define udelay(delay) +#endif + + +/****************************************************************************** + * + * CACHE handling macros / mappings + * + ******************************************************************************/ +/****************************************************************************** + * + * Processor independent macros + * + ******************************************************************************/ + +#define XCACHE_ENABLE_CACHE() \ + { XCACHE_ENABLE_DCACHE(); XCACHE_ENABLE_ICACHE(); } + +#define XCACHE_DISABLE_CACHE() \ + { XCACHE_DISABLE_DCACHE(); XCACHE_DISABLE_ICACHE(); } + + +/****************************************************************************** + * + * MicroBlaze case + * + * NOTE: Currently the following macros will only work on systems that contain + * only ONE MicroBlaze processor. Also, the macros will only be enabled if the + * system is built using a xparameters.h file. + * + ******************************************************************************/ + +#if defined __MICROBLAZE__ + +/* Check if MicroBlaze data cache was built into the core. + */ +#if (XPAR_MICROBLAZE_USE_DCACHE == 1) +# define XCACHE_ENABLE_DCACHE() microblaze_enable_dcache() +# define XCACHE_DISABLE_DCACHE() microblaze_disable_dcache() +# define XCACHE_INVALIDATE_DCACHE() microblaze_invalidate_dcache() + +# define XCACHE_INVALIDATE_DCACHE_RANGE(Addr, Len) \ + microblaze_invalidate_dcache_range((s32)(Addr), (s32)(Len)) + +#if (XPAR_MICROBLAZE_DCACHE_USE_WRITEBACK == 1) +# define XCACHE_FLUSH_DCACHE() microblaze_flush_dcache() +# define XCACHE_FLUSH_DCACHE_RANGE(Addr, Len) \ + microblaze_flush_dcache_range((s32)(Addr), (s32)(Len)) +#else +# define XCACHE_FLUSH_DCACHE() microblaze_invalidate_dcache() +# define XCACHE_FLUSH_DCACHE_RANGE(Addr, Len) \ + microblaze_invalidate_dcache_range((s32)(Addr), (s32)(Len)) +#endif /*XPAR_MICROBLAZE_DCACHE_USE_WRITEBACK*/ + +#else +# define XCACHE_ENABLE_DCACHE() +# define XCACHE_DISABLE_DCACHE() +# define XCACHE_INVALIDATE_DCACHE_RANGE(Addr, Len) +# define XCACHE_FLUSH_DCACHE_RANGE(Addr, Len) +#endif /*XPAR_MICROBLAZE_USE_DCACHE*/ + + +/* Check if MicroBlaze instruction cache was built into the core. + */ +#if (XPAR_MICROBLAZE_USE_ICACHE == 1) +# define XCACHE_ENABLE_ICACHE() microblaze_enable_icache() +# define XCACHE_DISABLE_ICACHE() microblaze_disable_icache() + +# define XCACHE_INVALIDATE_ICACHE() microblaze_invalidate_icache() + +# define XCACHE_INVALIDATE_ICACHE_RANGE(Addr, Len) \ + microblaze_invalidate_icache_range((s32)(Addr), (s32)(Len)) + +#else +# define XCACHE_ENABLE_ICACHE() +# define XCACHE_DISABLE_ICACHE() +#endif /*XPAR_MICROBLAZE_USE_ICACHE*/ + + +/****************************************************************************** + * + * PowerPC case + * + * Note that the XCACHE_ENABLE_xxx functions are hardcoded to enable a + * specific memory region (0x80000001). Each bit (0-30) in the regions + * bitmask stands for 128MB of memory. Bit 31 stands for the upper 2GB + * range. + * + * regions --> cached address range + * ------------|-------------------------------------------------- + * 0x80000000 | [0, 0x7FFFFFF] + * 0x00000001 | [0xF8000000, 0xFFFFFFFF] + * 0x80000001 | [0, 0x7FFFFFF],[0xF8000000, 0xFFFFFFFF] + * + ******************************************************************************/ + +#elif defined __PPC__ + +#define XCACHE_ENABLE_DCACHE() XCache_EnableDCache(0x80000001) +#define XCACHE_DISABLE_DCACHE() XCache_DisableDCache() +#define XCACHE_ENABLE_ICACHE() XCache_EnableICache(0x80000001) +#define XCACHE_DISABLE_ICACHE() XCache_DisableICache() + +#define XCACHE_INVALIDATE_DCACHE_RANGE(Addr, Len) \ + XCache_InvalidateDCacheRange((u32)(Addr), (u32)(Len)) + +#define XCACHE_FLUSH_DCACHE_RANGE(Addr, Len) \ + XCache_FlushDCacheRange((u32)(Addr), (u32)(Len)) + +#define XCACHE_INVALIDATE_ICACHE() XCache_InvalidateICache() + + +/****************************************************************************** + * + * Unknown processor / architecture + * + ******************************************************************************/ + +#else +/* #error "Unknown processor / architecture. Must be MicroBlaze or PowerPC." */ +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* #ifndef XENV_STANDALONE_H */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/include/xgpiops.h b/df_datalink/bsp/ps7_cortexa9_0/include/xgpiops.h new file mode 100644 index 0000000..d0ff132 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/include/xgpiops.h @@ -0,0 +1,283 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xgpiops.h +* @addtogroup gpiops_v3_5 +* @{ +* @details +* +* The Xilinx PS GPIO driver. This driver supports the Xilinx PS GPIO +* Controller. +* +* The GPIO Controller supports the following features: +* - 4 banks +* - Masked writes (There are no masked reads) +* - Bypass mode +* - Configurable Interrupts (Level/Edge) +* +* This driver is intended to be RTOS and processor independent. Any needs for +* dynamic memory management, threads or thread mutual exclusion, virtual +* memory, or cache control must be satisfied by the layer above this driver. + +* This driver supports all the features listed above, if applicable. +* +* Driver Description +* +* The device driver enables higher layer software (e.g., an application) to +* communicate to the GPIO. +* +* Interrupts +* +* The driver provides interrupt management functions and an interrupt handler. +* Users of this driver need to provide callback functions. An interrupt handler +* example is available with the driver. +* +* Threads +* +* This driver is not thread safe. Any needs for threads or thread mutual +* exclusion must be satisfied by the layer above this driver. +* +* Asserts +* +* Asserts are used within all Xilinx drivers to enforce constraints on argument +* values. Asserts can be turned off on a system-wide basis by defining, at +* compile time, the NDEBUG identifier. By default, asserts are turned on and it +* is recommended that users leave asserts on during development. +* +* Building the driver +* +* The XGpioPs driver is composed of several source files. This allows the user +* to build and link only those parts of the driver that are necessary. +*

+* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a sv   01/15/10 First Release
+* 1.01a sv   04/15/12 Removed the APIs XGpioPs_SetMode, XGpioPs_SetModePin
+*                     XGpioPs_GetMode, XGpioPs_GetModePin as they are not
+*		      relevant to Zynq device.The interrupts are disabled
+*		      for output pins on all banks during initialization.
+* 1.02a hk   08/22/13 Added low level reset API
+* 2.1   hk   04/29/14 Use Input data register DATA_RO for read. CR# 771667.
+* 2.2	sk	 10/13/14 Used Pin number in Bank instead of pin number
+* 					  passed to APIs. CR# 822636
+* 3.00  kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.1	kvn  04/13/15 Add support for Zynq Ultrascale+ MP. CR# 856980.
+*       ms   03/17/17 Added readme.txt file in examples folder for doxygen
+*                     generation.
+*       ms   04/05/17 Added tabspace for return statements in functions of
+*                     gpiops examples for proper documentation while
+*                     generating doxygen.
+* 3.3   ms   04/17/17 Added notes about gpio input and output pin description
+*                     for zcu102 and zc702 boards in polled and interrupt
+*                     example, configured Interrupt pin to input pin for
+*                     proper functioning of interrupt example.
+* 3.4   aru  08/17/18 Resolved MISRA-C mandatory violations. CR# 1007751
+* 3.5   sne  03/01/19 Fixes violations according to MISRAC-2012
+*                     in saftey mode and modified the code such as
+*                     Use of mixed mode arithmetic,Declared the poiner param
+*                     as Pointer to const,Casting operation to a pointer,
+*                     Literal value requires a U suffix.
+* 3.5   sne  03/14/19 Added Versal support.
+* 
+* +******************************************************************************/ +#ifndef XGPIOPS_H /* prevent circular inclusions */ +#define XGPIOPS_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xstatus.h" +#include "xgpiops_hw.h" +#include "xplatform_info.h" + +/************************** Constant Definitions *****************************/ + +/** @name Interrupt types + * @{ + * The following constants define the interrupt types that can be set for each + * GPIO pin. + */ +#define XGPIOPS_IRQ_TYPE_EDGE_RISING 0x00U /**< Interrupt on Rising edge */ +#define XGPIOPS_IRQ_TYPE_EDGE_FALLING 0x01U /**< Interrupt Falling edge */ +#define XGPIOPS_IRQ_TYPE_EDGE_BOTH 0x02U /**< Interrupt on both edges */ +#define XGPIOPS_IRQ_TYPE_LEVEL_HIGH 0x03U /**< Interrupt on high level */ +#define XGPIOPS_IRQ_TYPE_LEVEL_LOW 0x04U /**< Interrupt on low level */ +/*@}*/ + +#define XGPIOPS_BANK_MAX_PINS (u32)32 /**< Max pins in a GPIO bank */ +#define XGPIOPS_BANK0 0x00U /**< GPIO Bank 0 */ +#define XGPIOPS_BANK1 0x01U /**< GPIO Bank 1 */ +#define XGPIOPS_BANK2 0x02U /**< GPIO Bank 2 */ +#define XGPIOPS_BANK3 0x03U /**< GPIO Bank 3 */ + +#ifdef XPAR_PSU_GPIO_0_BASEADDR +#define XGPIOPS_BANK4 0x04U /**< GPIO Bank 4 */ +#define XGPIOPS_BANK5 0x05U /**< GPIO Bank 5 */ +#endif + +#define XGPIOPS_MAX_BANKS_ZYNQMP 0x06U /**< Max banks in a + * Zynq Ultrascale+ MP GPIO device + */ +#define XGPIOPS_MAX_BANKS 0x04U /**< Max banks in a Zynq GPIO device */ + +#define XGPIOPS_DEVICE_MAX_PIN_NUM_ZYNQMP (u32)174 /**< Max pins in the + * Zynq Ultrascale+ MP GPIO device + * 0 - 25, Bank 0 + * 26 - 51, Bank 1 + * 52 - 77, Bank 2 + * 78 - 109, Bank 3 + * 110 - 141, Bank 4 + * 142 - 173, Bank 5 + */ +#define XGPIOPS_DEVICE_MAX_PIN_NUM (u32)118 /**< Max pins in the Zynq GPIO device + * 0 - 31, Bank 0 + * 32 - 53, Bank 1 + * 54 - 85, Bank 2 + * 86 - 117, Bank 3 + */ + +/**************************** Type Definitions *******************************/ + +/****************************************************************************/ +/** + * This handler data type allows the user to define a callback function to + * handle the interrupts for the GPIO device. The application using this + * driver is expected to define a handler of this type, to support interrupt + * driven mode. The handler executes in an interrupt context such that minimal + * processing should be performed. + * + * @param CallBackRef is a callback reference passed in by the upper layer + * when setting the callback functions for a GPIO bank. It is + * passed back to the upper layer when the callback is invoked. Its + * type is not important to the driver component, so it is a void + * pointer. + * @param Bank is the bank for which the interrupt status has changed. + * @param Status is the Interrupt status of the GPIO bank. + * + *****************************************************************************/ +typedef void (*XGpioPs_Handler) (void *CallBackRef, u32 Bank, u32 Status); + +/** + * This typedef contains configuration information for a device. + */ +typedef struct { + u16 DeviceId; /**< Unique ID of device */ + u32 BaseAddr; /**< Register base address */ +} XGpioPs_Config; + +/** + * The XGpioPs driver instance data. The user is required to allocate a + * variable of this type for the GPIO device in the system. A pointer + * to a variable of this type is then passed to the driver API functions. + */ +typedef struct { + XGpioPs_Config GpioConfig; /**< Device configuration */ + u32 IsReady; /**< Device is initialized and ready */ + XGpioPs_Handler Handler; /**< Status handlers for all banks */ + void *CallBackRef; /**< Callback ref for bank handlers */ + u32 Platform; /**< Platform data */ + u32 MaxPinNum; /**< Max pins in the GPIO device */ + u8 MaxBanks; /**< Max banks in a GPIO device */ + u32 PmcGpio; /**< Flag for accessing PS GPIO for versal*/ +} XGpioPs; + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/* Functions in xgpiops.c */ +s32 XGpioPs_CfgInitialize(XGpioPs *InstancePtr, const XGpioPs_Config *ConfigPtr, + u32 EffectiveAddr); + +/* Bank APIs in xgpiops.c */ +u32 XGpioPs_Read(const XGpioPs *InstancePtr, u8 Bank); +void XGpioPs_Write(const XGpioPs *InstancePtr, u8 Bank, u32 Data); +void XGpioPs_SetDirection(const XGpioPs *InstancePtr, u8 Bank, u32 Direction); +u32 XGpioPs_GetDirection(const XGpioPs *InstancePtr, u8 Bank); +void XGpioPs_SetOutputEnable(const XGpioPs *InstancePtr, u8 Bank, u32 OpEnable); +u32 XGpioPs_GetOutputEnable(const XGpioPs *InstancePtr, u8 Bank); +#ifdef versal +void XGpioPs_GetBankPin(const XGpioPs *InstancePtr,u8 PinNumber,u8 *BankNumber, u8 *PinNumberInBank); +#else +void XGpioPs_GetBankPin(u8 PinNumber,u8 *BankNumber, u8 *PinNumberInBank); +#endif + +/* Pin APIs in xgpiops.c */ +u32 XGpioPs_ReadPin(const XGpioPs *InstancePtr, u32 Pin); +void XGpioPs_WritePin(const XGpioPs *InstancePtr, u32 Pin, u32 Data); +void XGpioPs_SetDirectionPin(const XGpioPs *InstancePtr, u32 Pin, u32 Direction); +u32 XGpioPs_GetDirectionPin(const XGpioPs *InstancePtr, u32 Pin); +void XGpioPs_SetOutputEnablePin(const XGpioPs *InstancePtr, u32 Pin, u32 OpEnable); +u32 XGpioPs_GetOutputEnablePin(const XGpioPs *InstancePtr, u32 Pin); + +/* Diagnostic functions in xgpiops_selftest.c */ +s32 XGpioPs_SelfTest(const XGpioPs *InstancePtr); + +/* Functions in xgpiops_intr.c */ +/* Bank APIs in xgpiops_intr.c */ +void XGpioPs_IntrEnable(const XGpioPs *InstancePtr, u8 Bank, u32 Mask); +void XGpioPs_IntrDisable(const XGpioPs *InstancePtr, u8 Bank, u32 Mask); +u32 XGpioPs_IntrGetEnabled(const XGpioPs *InstancePtr, u8 Bank); +u32 XGpioPs_IntrGetStatus(const XGpioPs *InstancePtr, u8 Bank); +void XGpioPs_IntrClear(const XGpioPs *InstancePtr, u8 Bank, u32 Mask); +void XGpioPs_SetIntrType(const XGpioPs *InstancePtr, u8 Bank, u32 IntrType, + u32 IntrPolarity, u32 IntrOnAny); +void XGpioPs_GetIntrType(const XGpioPs *InstancePtr, u8 Bank, u32 *IntrType, + u32 *IntrPolarity, u32 *IntrOnAny); +void XGpioPs_SetCallbackHandler(XGpioPs *InstancePtr, void *CallBackRef, + XGpioPs_Handler FuncPointer); +void XGpioPs_IntrHandler(const XGpioPs *InstancePtr); + +/* Pin APIs in xgpiops_intr.c */ +void XGpioPs_SetIntrTypePin(const XGpioPs *InstancePtr, u32 Pin, u8 IrqType); +u8 XGpioPs_GetIntrTypePin(const XGpioPs *InstancePtr, u32 Pin); + +void XGpioPs_IntrEnablePin(const XGpioPs *InstancePtr, u32 Pin); +void XGpioPs_IntrDisablePin(const XGpioPs *InstancePtr, u32 Pin); +u32 XGpioPs_IntrGetEnabledPin(const XGpioPs *InstancePtr, u32 Pin); +u32 XGpioPs_IntrGetStatusPin(const XGpioPs *InstancePtr, u32 Pin); +void XGpioPs_IntrClearPin(const XGpioPs *InstancePtr, u32 Pin); + +/* Functions in xgpiops_sinit.c */ +XGpioPs_Config *XGpioPs_LookupConfig(u16 DeviceId); +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/include/xgpiops_hw.h b/df_datalink/bsp/ps7_cortexa9_0/include/xgpiops_hw.h new file mode 100644 index 0000000..599c7db --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/include/xgpiops_hw.h @@ -0,0 +1,168 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xgpiops_hw.h +* @addtogroup gpiops_v3_5 +* @{ +* +* This header file contains the identifiers and basic driver functions (or +* macros) that can be used to access the device. Other driver functions +* are defined in xgpiops.h. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------
+* 1.00a sv   01/15/10 First Release
+* 1.02a hk   08/22/13 Added low level reset API function prototype and
+*                     related constant definitions
+* 3.00  kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.1	kvn  04/13/15 Corrected reset values of banks.
+* 3.5   sne  03/14/19 Added versal support.
+* 
+* +******************************************************************************/ +#ifndef XGPIOPS_HW_H /* prevent circular inclusions */ +#define XGPIOPS_HW_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_io.h" + +/************************** Constant Definitions *****************************/ + +/** @name Register offsets for the GPIO. Each register is 32 bits. + * @{ + */ +#define XGPIOPS_DATA_LSW_OFFSET 0x00000000U /* Mask and Data Register LSW, WO */ +#define XGPIOPS_DATA_MSW_OFFSET 0x00000004U /* Mask and Data Register MSW, WO */ +#define XGPIOPS_DATA_OFFSET 0x00000040U /* Data Register, RW */ +#define XGPIOPS_DATA_RO_OFFSET 0x00000060U /* Data Register - Input, RO */ +#define XGPIOPS_DIRM_OFFSET 0x00000204U /* Direction Mode Register, RW */ +#define XGPIOPS_OUTEN_OFFSET 0x00000208U /* Output Enable Register, RW */ +#define XGPIOPS_INTMASK_OFFSET 0x0000020CU /* Interrupt Mask Register, RO */ +#define XGPIOPS_INTEN_OFFSET 0x00000210U /* Interrupt Enable Register, WO */ +#define XGPIOPS_INTDIS_OFFSET 0x00000214U /* Interrupt Disable Register, WO*/ +#define XGPIOPS_INTSTS_OFFSET 0x00000218U /* Interrupt Status Register, RO */ +#define XGPIOPS_INTTYPE_OFFSET 0x0000021CU /* Interrupt Type Register, RW */ +#define XGPIOPS_INTPOL_OFFSET 0x00000220U /* Interrupt Polarity Register, RW */ +#define XGPIOPS_INTANY_OFFSET 0x00000224U /* Interrupt On Any Register, RW */ +/* @} */ + +/** @name Register offsets for each Bank. + * @{ + */ +#define XGPIOPS_DATA_MASK_OFFSET 0x00000008U /* Data/Mask Registers offset */ +#define XGPIOPS_DATA_BANK_OFFSET 0x00000004U /* Data Registers offset */ +#define XGPIOPS_REG_MASK_OFFSET 0x00000040U /* Registers offset */ +/* @} */ + +/* For backwards compatibility */ +#define XGPIOPS_BYPM_MASK_OFFSET (u32)0x40 + +/** @name Interrupt type reset values for each bank + * @{ + */ +#ifdef XPAR_PSU_GPIO_0_BASEADDR +#define XGPIOPS_INTTYPE_BANK0_RESET 0x03FFFFFFU /* Resets specific to Zynq Ultrascale+ MP */ +#define XGPIOPS_INTTYPE_BANK1_RESET 0x03FFFFFFU +#define XGPIOPS_INTTYPE_BANK2_RESET 0x03FFFFFFU +#else +#define XGPIOPS_INTTYPE_BANK0_RESET 0xFFFFFFFFU /* Resets specific to Zynq */ +#define XGPIOPS_INTTYPE_BANK1_RESET 0x003FFFFFU +#define XGPIOPS_INTTYPE_BANK2_RESET 0xFFFFFFFFU +#endif + +#define XGPIOPS_INTTYPE_BANK3_RESET 0xFFFFFFFFU /* Reset common to both platforms */ +#define XGPIOPS_INTTYPE_BANK4_RESET 0xFFFFFFFFU /* Resets specific to Zynq Ultrascale+ MP */ +#define XGPIOPS_INTTYPE_BANK5_RESET 0xFFFFFFFFU +/* @} */ +#define XGPIOPS_PS_GPIO_BASEADDR 0xFF0B0000U /* Flag for Base Address for PS_GPIO in Versal */ +#define XGPIOPS_ZERO 0U /* Flag for 0 Value */ +#define XGPIOPS_ONE 1U /* Flag for 1 Value */ +#define XGPIOPS_TWO 2U /* Flag for 2 Value */ +#define XGPIOPS_THREE 3U /* Flag for 3 Value */ +#define XGPIOPS_FOUR 4U /* Flag for 4 Value */ +#define XGPIOPS_SIX 6U /* Flag for 6 Value */ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/****************************************************************************/ +/** +* +* This macro reads the given register. +* +* @param BaseAddr is the base address of the device. +* @param RegOffset is the register offset to be read. +* +* @return The 32-bit value of the register +* +* @note None. +* +*****************************************************************************/ +#define XGpioPs_ReadReg(BaseAddr, RegOffset) \ + Xil_In32((BaseAddr) + (u32)(RegOffset)) + +/****************************************************************************/ +/** +* +* This macro writes to the given register. +* +* @param BaseAddr is the base address of the device. +* @param RegOffset is the offset of the register to be written. +* @param Data is the 32-bit value to write to the register. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +#define XGpioPs_WriteReg(BaseAddr, RegOffset, Data) \ + Xil_Out32((BaseAddr) + (u32)(RegOffset), (u32)(Data)) + +/************************** Function Prototypes ******************************/ + +void XGpioPs_ResetHw(u32 BaseAddress); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* XGPIOPS_HW_H */ +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/include/xil_assert.h b/df_datalink/bsp/ps7_cortexa9_0/include/xil_assert.h new file mode 100644 index 0000000..917de31 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/include/xil_assert.h @@ -0,0 +1,191 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_assert.h +* +* @addtogroup common_assert_apis Assert APIs and Macros +* +* The xil_assert.h file contains assert related functions and macros. +* Assert APIs/Macros specifies that a application program satisfies certain +* conditions at particular points in its execution. These function can be +* used by application programs to ensure that, application code is satisfying +* certain conditions. +* +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date   Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a hbm  07/14/09 First release
+* 6.0   kvn  05/31/16 Make Xil_AsserWait a global variable
+* 
+* +******************************************************************************/ + +#ifndef XIL_ASSERT_H /* prevent circular inclusions */ +#define XIL_ASSERT_H /* by using protection macros */ + +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/***************************** Include Files *********************************/ + + +/************************** Constant Definitions *****************************/ + +#define XIL_ASSERT_NONE 0U +#define XIL_ASSERT_OCCURRED 1U +#define XNULL NULL + +extern u32 Xil_AssertStatus; +extern s32 Xil_AssertWait; +extern void Xil_Assert(const char8 *File, s32 Line); +void XNullHandler(void *NullParameter); + +/** + * This data type defines a callback to be invoked when an + * assert occurs. The callback is invoked only when asserts are enabled + */ +typedef void (*Xil_AssertCallback) (const char8 *File, s32 Line); + +/***************** Macros (Inline Functions) Definitions *********************/ + +#ifndef NDEBUG + +/*****************************************************************************/ +/** +* @brief This assert macro is to be used for void functions. This in +* conjunction with the Xil_AssertWait boolean can be used to +* accomodate tests so that asserts which fail allow execution to +* continue. +* +* @param Expression: expression to be evaluated. If it evaluates to +* false, the assert occurs. +* +* @return Returns void unless the Xil_AssertWait variable is true, in which +* case no return is made and an infinite loop is entered. +* +******************************************************************************/ +#define Xil_AssertVoid(Expression) \ +{ \ + if (Expression) { \ + Xil_AssertStatus = XIL_ASSERT_NONE; \ + } else { \ + Xil_Assert(__FILE__, __LINE__); \ + Xil_AssertStatus = XIL_ASSERT_OCCURRED; \ + return; \ + } \ +} + +/*****************************************************************************/ +/** +* @brief This assert macro is to be used for functions that do return a +* value. This in conjunction with the Xil_AssertWait boolean can be +* used to accomodate tests so that asserts which fail allow execution +* to continue. +* +* @param Expression: expression to be evaluated. If it evaluates to false, +* the assert occurs. +* +* @return Returns 0 unless the Xil_AssertWait variable is true, in which +* case no return is made and an infinite loop is entered. +* +******************************************************************************/ +#define Xil_AssertNonvoid(Expression) \ +{ \ + if (Expression) { \ + Xil_AssertStatus = XIL_ASSERT_NONE; \ + } else { \ + Xil_Assert(__FILE__, __LINE__); \ + Xil_AssertStatus = XIL_ASSERT_OCCURRED; \ + return 0; \ + } \ +} + +/*****************************************************************************/ +/** +* @brief Always assert. This assert macro is to be used for void functions. +* Use for instances where an assert should always occur. +* +* @return Returns void unless the Xil_AssertWait variable is true, in which +* case no return is made and an infinite loop is entered. +* +******************************************************************************/ +#define Xil_AssertVoidAlways() \ +{ \ + Xil_Assert(__FILE__, __LINE__); \ + Xil_AssertStatus = XIL_ASSERT_OCCURRED; \ + return; \ +} + +/*****************************************************************************/ +/** +* @brief Always assert. This assert macro is to be used for functions that +* do return a value. Use for instances where an assert should always +* occur. +* +* @return Returns void unless the Xil_AssertWait variable is true, in which +* case no return is made and an infinite loop is entered. +* +******************************************************************************/ +#define Xil_AssertNonvoidAlways() \ +{ \ + Xil_Assert(__FILE__, __LINE__); \ + Xil_AssertStatus = XIL_ASSERT_OCCURRED; \ + return 0; \ +} + + +#else + +#define Xil_AssertVoid(Expression) +#define Xil_AssertVoidAlways() +#define Xil_AssertNonvoid(Expression) +#define Xil_AssertNonvoidAlways() + +#endif + +/************************** Function Prototypes ******************************/ + +void Xil_AssertSetCallback(Xil_AssertCallback Routine); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** +* @} End of "addtogroup common_assert_apis". +*/ diff --git a/df_datalink/bsp/ps7_cortexa9_0/include/xil_cache.h b/df_datalink/bsp/ps7_cortexa9_0/include/xil_cache.h new file mode 100644 index 0000000..ce6fcf4 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/include/xil_cache.h @@ -0,0 +1,118 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_cache.h +* +* @addtogroup a9_cache_apis Cortex A9 Processor Cache Functions +* +* Cache functions provide access to cache related operations such as flush +* and invalidate for instruction and data caches. It gives option to perform +* the cache operations on a single cacheline, a range of memory and an entire +* cache. +* +* @{ +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a ecm  01/29/10 First release
+* 3.04a sdm  01/02/12 Remove redundant dsb/dmb instructions in cache maintenance
+*		      APIs.
+* 6.8   aru  09/06/18 Removed compilation warnings for ARMCC toolchain.
+* 
+* +******************************************************************************/ +#ifndef XIL_CACHE_H +#define XIL_CACHE_H + +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __GNUC__ + +#define asm_cp15_inval_dc_line_mva_poc(param) __asm__ __volatile__("mcr " \ + XREG_CP15_INVAL_DC_LINE_MVA_POC :: "r" (param)); + +#define asm_cp15_clean_inval_dc_line_mva_poc(param) __asm__ __volatile__("mcr " \ + XREG_CP15_CLEAN_INVAL_DC_LINE_MVA_POC :: "r" (param)); + +#define asm_cp15_inval_ic_line_mva_pou(param) __asm__ __volatile__("mcr " \ + XREG_CP15_INVAL_IC_LINE_MVA_POU :: "r" (param)); + +#define asm_cp15_inval_dc_line_sw(param) __asm__ __volatile__("mcr " \ + XREG_CP15_INVAL_DC_LINE_SW :: "r" (param)); + +#define asm_cp15_clean_inval_dc_line_sw(param) __asm__ __volatile__("mcr " \ + XREG_CP15_CLEAN_INVAL_DC_LINE_SW :: "r" (param)); + +#elif defined (__ICCARM__) + +#define asm_cp15_inval_dc_line_mva_poc(param) __asm volatile ("mcr " \ + XREG_CP15_INVAL_DC_LINE_MVA_POC :: "r" (param)); + +#define asm_cp15_clean_inval_dc_line_mva_poc(param) __asm volatile ("mcr " \ + XREG_CP15_CLEAN_INVAL_DC_LINE_MVA_POC :: "r" (param)); + +#define asm_cp15_inval_ic_line_mva_pou(param) __asm volatile ("mcr " \ + XREG_CP15_INVAL_IC_LINE_MVA_POU :: "r" (param)); + +#define asm_cp15_inval_dc_line_sw(param) __asm volatile ("mcr " \ + XREG_CP15_INVAL_DC_LINE_SW :: "r" (param)); + +#define asm_cp15_clean_inval_dc_line_sw(param) __asm volatile ("mcr " \ + XREG_CP15_CLEAN_INVAL_DC_LINE_SW :: "r" (param)); + +#endif + +void Xil_DCacheEnable(void); +void Xil_DCacheDisable(void); +void Xil_DCacheInvalidate(void); +void Xil_DCacheInvalidateRange(INTPTR adr, u32 len); +void Xil_DCacheFlush(void); +void Xil_DCacheFlushRange(INTPTR adr, u32 len); + +void Xil_ICacheEnable(void); +void Xil_ICacheDisable(void); +void Xil_ICacheInvalidate(void); +void Xil_ICacheInvalidateRange(INTPTR adr, u32 len); + +#ifdef __cplusplus +} +#endif + +#endif +/** +* @} End of "addtogroup a9_cache_apis". +*/ diff --git a/df_datalink/bsp/ps7_cortexa9_0/include/xil_cache_l.h b/df_datalink/bsp/ps7_cortexa9_0/include/xil_cache_l.h new file mode 100644 index 0000000..b6ff809 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/include/xil_cache_l.h @@ -0,0 +1,97 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_cache_l.h +* +* Contains L1 and L2 specific functions for the ARM cache functionality +* used by xcache.c. This functionality is being made available here for +* more sophisticated users. +* +* @addtogroup a9_cache_apis +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a ecm  01/24/10 First release
+* 6.8   aru  09/06/18 Removed compilation warnings for ARMCC toolchain.
+* 
+* +******************************************************************************/ +#ifndef XIL_CACHE_MACH_H +#define XIL_CACHE_MACH_H + +#include "xil_types.h" +#ifdef __cplusplus +extern "C" { +#endif + +/************************** Function Prototypes ******************************/ + +void Xil_DCacheInvalidateLine(u32 adr); +void Xil_DCacheFlushLine(u32 adr); +void Xil_DCacheStoreLine(u32 adr); +void Xil_ICacheInvalidateLine(u32 adr); + +void Xil_L1DCacheEnable(void); +void Xil_L1DCacheDisable(void); +void Xil_L1DCacheInvalidate(void); +void Xil_L1DCacheInvalidateLine(u32 adr); +void Xil_L1DCacheInvalidateRange(u32 adr, u32 len); +void Xil_L1DCacheFlush(void); +void Xil_L1DCacheFlushLine(u32 adr); +void Xil_L1DCacheFlushRange(u32 adr, u32 len); +void Xil_L1DCacheStoreLine(u32 adr); + +void Xil_L1ICacheEnable(void); +void Xil_L1ICacheDisable(void); +void Xil_L1ICacheInvalidate(void); +void Xil_L1ICacheInvalidateLine(u32 adr); +void Xil_L1ICacheInvalidateRange(u32 adr, u32 len); + +void Xil_L2CacheEnable(void); +void Xil_L2CacheDisable(void); +void Xil_L2CacheInvalidate(void); +void Xil_L2CacheInvalidateLine(u32 adr); +void Xil_L2CacheInvalidateRange(u32 adr, u32 len); +void Xil_L2CacheFlush(void); +void Xil_L2CacheFlushLine(u32 adr); +void Xil_L2CacheFlushRange(u32 adr, u32 len); +void Xil_L2CacheStoreLine(u32 adr); + +#ifdef __cplusplus +} +#endif + +#endif +/** +* @} End of "addtogroup a9_cache_apis". +*/ diff --git a/df_datalink/bsp/ps7_cortexa9_0/include/xil_cache_vxworks.h b/df_datalink/bsp/ps7_cortexa9_0/include/xil_cache_vxworks.h new file mode 100644 index 0000000..7e2a7d9 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/include/xil_cache_vxworks.h @@ -0,0 +1,89 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_cache_vxworks.h +* +* Contains the cache related functions for VxWorks that is wrapped by +* xil_cache. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date	 Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a hbm  12/11/09 Initial release
+*
+* 
+* +* @note +* +******************************************************************************/ + +#ifndef XIL_CACHE_VXWORKS_H +#define XIL_CACHE_VXWORKS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "vxWorks.h" +#include "vxLib.h" +#include "sysLibExtra.h" +#include "cacheLib.h" + +#if (CPU_FAMILY==PPC) + +#define Xil_DCacheEnable() cacheEnable(DATA_CACHE) + +#define Xil_DCacheDisable() cacheDisable(DATA_CACHE) + +#define Xil_DCacheInvalidateRange(Addr, Len) \ + cacheInvalidate(DATA_CACHE, (void *)(Addr), (Len)) + +#define Xil_DCacheFlushRange(Addr, Len) \ + cacheFlush(DATA_CACHE, (void *)(Addr), (Len)) + +#define Xil_ICacheEnable() cacheEnable(INSTRUCTION_CACHE) + +#define Xil_ICacheDisable() cacheDisable(INSTRUCTION_CACHE) + +#define Xil_ICacheInvalidateRange(Addr, Len) \ + cacheInvalidate(INSTRUCTION_CACHE, (void *)(Addr), (Len)) + + +#else +#error "Unknown processor / architecture. Must be PPC for VxWorks." +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/df_datalink/bsp/ps7_cortexa9_0/include/xil_errata.h b/df_datalink/bsp/ps7_cortexa9_0/include/xil_errata.h new file mode 100644 index 0000000..c839b63 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/include/xil_errata.h @@ -0,0 +1,127 @@ +/****************************************************************************** +* +* Copyright (C) 2013 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_errata.h +* +* @addtogroup a9_errata Cortex A9 Processor and pl310 Errata Support +* @{ +* Various ARM errata are handled in the standalone BSP. The implementation for +* errata handling follows ARM guidelines and is based on the open source Linux +* support for these errata. +* +* @note +* The errata handling is enabled by default. To disable handling of all the +* errata globally, un-define the macro ENABLE_ARM_ERRATA in xil_errata.h. To +* disable errata on a per-erratum basis, un-define relevant macros in +* xil_errata.h. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a srt  04/18/13 First release
+* 6.6   mus  12/07/17 Removed errata 753970, It fixes CR#989132.
+* 
+* +******************************************************************************/ +#ifndef XIL_ERRATA_H +#define XIL_ERRATA_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @name errata_definitions + * + * The errata conditions handled in the standalone BSP are listed below + * @{ + */ + +#define ENABLE_ARM_ERRATA 1 + +#ifdef ENABLE_ARM_ERRATA + +/** + * Errata No: 742230 + * Description: DMB operation may be faulty + */ +#define CONFIG_ARM_ERRATA_742230 1 + +/** + * Errata No: 743622 + * Description: Faulty hazard checking in the Store Buffer may lead + * to data corruption. + */ +#define CONFIG_ARM_ERRATA_743622 1 + +/** + * Errata No: 775420 + * Description: A data cache maintenance operation which aborts, + * might lead to deadlock + */ +#define CONFIG_ARM_ERRATA_775420 1 + +/** + * Errata No: 794073 + * Description: Speculative instruction fetches with MMU disabled + * might not comply with architectural requirements + */ +#define CONFIG_ARM_ERRATA_794073 1 + + +/** PL310 L2 Cache Errata */ + +/** + * Errata No: 588369 + * Description: Clean & Invalidate maintenance operations do not + * invalidate clean lines + */ +#define CONFIG_PL310_ERRATA_588369 1 + +/** + * Errata No: 727915 + * Description: Background Clean and Invalidate by Way operation + * can cause data corruption + */ +#define CONFIG_PL310_ERRATA_727915 1 + +/*@}*/ +#endif /* ENABLE_ARM_ERRATA */ + +#ifdef __cplusplus +} +#endif + +#endif /* XIL_ERRATA_H */ +/** +* @} End of "addtogroup a9_errata". +*/ diff --git a/df_datalink/bsp/ps7_cortexa9_0/include/xil_exception.h b/df_datalink/bsp/ps7_cortexa9_0/include/xil_exception.h new file mode 100644 index 0000000..807f310 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/include/xil_exception.h @@ -0,0 +1,285 @@ +/****************************************************************************** +* +* Copyright (C) 2015 - 2016 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_exception.h +* +* This header file contains ARM Cortex A53,A9,R5 specific exception related APIs. +* For exception related functions that can be used across all Xilinx supported +* processors, please use xil_exception.h. +* +* @addtogroup arm_exception_apis ARM Processor Exception Handling +* @{ +* ARM processors specific exception related APIs for cortex A53,A9 and R5 can +* utilized for enabling/disabling IRQ, registering/removing handler for +* exceptions or initializing exception vector table with null handler. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 5.2	pkp  	 28/05/15 First release
+* 6.0   mus      27/07/16 Consolidated file for a53,a9 and r5 processors
+* 6.7   mna      26/04/18 Add API Xil_GetExceptionRegisterHandler.
+* 6.7   asa      18/05/18 Update signature of API Xil_GetExceptionRegisterHandler.
+* 7.0   mus      01/03/19 Tweak Xil_ExceptionEnableMask and
+*                         Xil_ExceptionDisableMask macros to support legacy
+*                         examples for Cortexa72 EL3 exception level.
+* 
+* +******************************************************************************/ + +#ifndef XIL_EXCEPTION_H /* prevent circular inclusions */ +#define XIL_EXCEPTION_H /* by using protection macros */ + +/***************************** Include Files ********************************/ + +#include "xil_types.h" +#include "xpseudo_asm.h" +#include "bspconfig.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************** Constant Definitions ****************************/ + +#define XIL_EXCEPTION_FIQ XREG_CPSR_FIQ_ENABLE +#define XIL_EXCEPTION_IRQ XREG_CPSR_IRQ_ENABLE +#define XIL_EXCEPTION_ALL (XREG_CPSR_FIQ_ENABLE | XREG_CPSR_IRQ_ENABLE) + +#define XIL_EXCEPTION_ID_FIRST 0U +#if defined (__aarch64__) +#define XIL_EXCEPTION_ID_SYNC_INT 1U +#define XIL_EXCEPTION_ID_IRQ_INT 2U +#define XIL_EXCEPTION_ID_FIQ_INT 3U +#define XIL_EXCEPTION_ID_SERROR_ABORT_INT 4U +#define XIL_EXCEPTION_ID_LAST 5U +#else +#define XIL_EXCEPTION_ID_RESET 0U +#define XIL_EXCEPTION_ID_UNDEFINED_INT 1U +#define XIL_EXCEPTION_ID_SWI_INT 2U +#define XIL_EXCEPTION_ID_PREFETCH_ABORT_INT 3U +#define XIL_EXCEPTION_ID_DATA_ABORT_INT 4U +#define XIL_EXCEPTION_ID_IRQ_INT 5U +#define XIL_EXCEPTION_ID_FIQ_INT 6U +#define XIL_EXCEPTION_ID_LAST 6U +#endif + +/* + * XIL_EXCEPTION_ID_INT is defined for all Xilinx processors. + */ +#if defined (versal) && !defined(ARMR5) && EL3 +#define XIL_EXCEPTION_ID_INT XIL_EXCEPTION_ID_FIQ_INT +#else +#define XIL_EXCEPTION_ID_INT XIL_EXCEPTION_ID_IRQ_INT +#endif + +/**************************** Type Definitions ******************************/ + +/** + * This typedef is the exception handler function. + */ +typedef void (*Xil_ExceptionHandler)(void *data); +typedef void (*Xil_InterruptHandler)(void *data); + +/***************** Macros (Inline Functions) Definitions ********************/ + +/****************************************************************************/ +/** +* @brief Enable Exceptions. +* +* @param Mask: Value for enabling the exceptions. +* +* @return None. +* +* @note If bit is 0, exception is enabled. +* C-Style signature: void Xil_ExceptionEnableMask(Mask) +* +******************************************************************************/ +#if defined (versal) && !defined(ARMR5) && EL3 +/* + * Cortexa72 processor in versal is coupled with GIC-500, and GIC-500 supports + * only FIQ at EL3. Hence, tweaking this macro to always enable FIQ + * ignoring argument passed by user. + */ +#define Xil_ExceptionEnableMask(Mask) \ + mtcpsr(mfcpsr() & ~ ((XIL_EXCEPTION_FIQ) & XIL_EXCEPTION_ALL)) +#elif defined (__GNUC__) || defined (__ICCARM__) +#define Xil_ExceptionEnableMask(Mask) \ + mtcpsr(mfcpsr() & ~ ((Mask) & XIL_EXCEPTION_ALL)) +#else +#define Xil_ExceptionEnableMask(Mask) \ + { \ + register u32 Reg __asm("cpsr"); \ + mtcpsr((Reg) & (~((Mask) & XIL_EXCEPTION_ALL))); \ + } +#endif +/****************************************************************************/ +/** +* @brief Enable the IRQ exception. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +#if defined (versal) && !defined(ARMR5) && EL3 +#define Xil_ExceptionEnable() \ + Xil_ExceptionEnableMask(XIL_EXCEPTION_FIQ) +#else +#define Xil_ExceptionEnable() \ + Xil_ExceptionEnableMask(XIL_EXCEPTION_IRQ) +#endif + +/****************************************************************************/ +/** +* @brief Disable Exceptions. +* +* @param Mask: Value for disabling the exceptions. +* +* @return None. +* +* @note If bit is 1, exception is disabled. +* C-Style signature: Xil_ExceptionDisableMask(Mask) +* +******************************************************************************/ +#if defined (versal) && !defined(ARMR5) && EL3 +/* + * Cortexa72 processor in versal is coupled with GIC-500, and GIC-500 supports + * only FIQ at EL3. Hence, tweaking this macro to always disable FIQ + * ignoring argument passed by user. + */ +#define Xil_ExceptionDisableMask(Mask) \ + mtcpsr(mfcpsr() | ((XIL_EXCEPTION_FIQ) & XIL_EXCEPTION_ALL)) +#elif defined (__GNUC__) || defined (__ICCARM__) +#define Xil_ExceptionDisableMask(Mask) \ + mtcpsr(mfcpsr() | ((Mask) & XIL_EXCEPTION_ALL)) +#else +#define Xil_ExceptionDisableMask(Mask) \ + { \ + register u32 Reg __asm("cpsr"); \ + mtcpsr((Reg) | ((Mask) & XIL_EXCEPTION_ALL)); \ + } +#endif +/****************************************************************************/ +/** +* Disable the IRQ exception. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +#define Xil_ExceptionDisable() \ + Xil_ExceptionDisableMask(XIL_EXCEPTION_IRQ) + +#if !defined (__aarch64__) && !defined (ARMA53_32) +/****************************************************************************/ +/** +* @brief Enable nested interrupts by clearing the I and F bits in CPSR. This +* API is defined for cortex-a9 and cortex-r5. +* +* @return None. +* +* @note This macro is supposed to be used from interrupt handlers. In the +* interrupt handler the interrupts are disabled by default (I and F +* are 1). To allow nesting of interrupts, this macro should be +* used. It clears the I and F bits by changing the ARM mode to +* system mode. Once these bits are cleared and provided the +* preemption of interrupt conditions are met in the GIC, nesting of +* interrupts will start happening. +* Caution: This macro must be used with caution. Before calling this +* macro, the user must ensure that the source of the current IRQ +* is appropriately cleared. Otherwise, as soon as we clear the I and +* F bits, there can be an infinite loop of interrupts with an +* eventual crash (all the stack space getting consumed). +******************************************************************************/ +#define Xil_EnableNestedInterrupts() \ + __asm__ __volatile__ ("stmfd sp!, {lr}"); \ + __asm__ __volatile__ ("mrs lr, spsr"); \ + __asm__ __volatile__ ("stmfd sp!, {lr}"); \ + __asm__ __volatile__ ("msr cpsr_c, #0x1F"); \ + __asm__ __volatile__ ("stmfd sp!, {lr}"); + +/****************************************************************************/ +/** +* @brief Disable the nested interrupts by setting the I and F bits. This API +* is defined for cortex-a9 and cortex-r5. +* +* @return None. +* +* @note This macro is meant to be called in the interrupt service routines. +* This macro cannot be used independently. It can only be used when +* nesting of interrupts have been enabled by using the macro +* Xil_EnableNestedInterrupts(). In a typical flow, the user first +* calls the Xil_EnableNestedInterrupts in the ISR at the appropriate +* point. The user then must call this macro before exiting the interrupt +* service routine. This macro puts the ARM back in IRQ/FIQ mode and +* hence sets back the I and F bits. +******************************************************************************/ +#define Xil_DisableNestedInterrupts() \ + __asm__ __volatile__ ("ldmfd sp!, {lr}"); \ + __asm__ __volatile__ ("msr cpsr_c, #0x92"); \ + __asm__ __volatile__ ("ldmfd sp!, {lr}"); \ + __asm__ __volatile__ ("msr spsr_cxsf, lr"); \ + __asm__ __volatile__ ("ldmfd sp!, {lr}"); \ + +#endif +/************************** Variable Definitions ****************************/ + +/************************** Function Prototypes *****************************/ + +extern void Xil_ExceptionRegisterHandler(u32 Exception_id, + Xil_ExceptionHandler Handler, + void *Data); + +extern void Xil_ExceptionRemoveHandler(u32 Exception_id); +extern void Xil_GetExceptionRegisterHandler(u32 Exception_id, + Xil_ExceptionHandler *Handler, void **Data); + +extern void Xil_ExceptionInit(void); +#if defined (__aarch64__) +void Xil_SyncAbortHandler(void *CallBackRef); +void Xil_SErrorAbortHandler(void *CallBackRef); +#else +extern void Xil_DataAbortHandler(void *CallBackRef); +extern void Xil_PrefetchAbortHandler(void *CallBackRef); +extern void Xil_UndefinedExceptionHandler(void *CallBackRef); +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* XIL_EXCEPTION_H */ +/** +* @} End of "addtogroup arm_exception_apis". +*/ diff --git a/df_datalink/bsp/ps7_cortexa9_0/include/xil_hal.h b/df_datalink/bsp/ps7_cortexa9_0/include/xil_hal.h new file mode 100644 index 0000000..e8971c9 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/include/xil_hal.h @@ -0,0 +1,65 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_hal.h +* +* Contains all the HAL header files. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date	 Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a hbm  07/28/09 Initial release
+*
+* 
+* +* @note +* +******************************************************************************/ + +#ifndef XIL_HAL_H +#define XIL_HAL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "xil_cache.h" +#include "xil_io.h" +#include "xil_assert.h" +#include "xil_exception.h" +#include "xil_types.h" + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/df_datalink/bsp/ps7_cortexa9_0/include/xil_io.h b/df_datalink/bsp/ps7_cortexa9_0/include/xil_io.h new file mode 100644 index 0000000..00207cf --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/include/xil_io.h @@ -0,0 +1,341 @@ +/****************************************************************************** +* +* Copyright (C) 2014 - 2016 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_io.h +* +* @addtogroup common_io_interfacing_apis Register IO interfacing APIs +* +* The xil_io.h file contains the interface for the general I/O component, which +* encapsulates the Input/Output functions for the processors that do not +* require any special I/O handling. +* +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 5.00 	pkp  	 05/29/14 First release
+* 6.00  mus      08/19/16 Remove checking of __LITTLE_ENDIAN__ flag for
+*                         ARM processors
+* 
+******************************************************************************/ + +#ifndef XIL_IO_H /* prevent circular inclusions */ +#define XIL_IO_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_printf.h" + +#if defined (__MICROBLAZE__) +#include "mb_interface.h" +#else +#include "xpseudo_asm.h" +#endif + +/************************** Function Prototypes ******************************/ +u16 Xil_EndianSwap16(u16 Data); +u32 Xil_EndianSwap32(u32 Data); +#ifdef ENABLE_SAFETY +extern u32 XStl_RegUpdate(u32 RegAddr, u32 RegVal); +#endif + +/***************** Macros (Inline Functions) Definitions *********************/ +#if defined __GNUC__ +#if defined (__MICROBLAZE__) +# define INST_SYNC mbar(0) +# define DATA_SYNC mbar(1) +# else +# define SYNCHRONIZE_IO dmb() +# define INST_SYNC isb() +# define DATA_SYNC dsb() +# endif +#else +# define SYNCHRONIZE_IO +# define INST_SYNC +# define DATA_SYNC +# define INST_SYNC +# define DATA_SYNC +#endif + +#if defined (__GNUC__) || defined (__ICCARM__) || defined (__MICROBLAZE__) +#define INLINE inline +#else +#define INLINE __inline +#endif + +/*****************************************************************************/ +/** +* +* @brief Performs an input operation for a memory location by reading +* from the specified address and returning the 8 bit Value read from +* that address. +* +* @param Addr: contains the address to perform the input operation +* +* @return The 8 bit Value read from the specified input address. + +* +******************************************************************************/ +static INLINE u8 Xil_In8(UINTPTR Addr) +{ + return *(volatile u8 *) Addr; +} + +/*****************************************************************************/ +/** +* +* @brief Performs an input operation for a memory location by reading from +* the specified address and returning the 16 bit Value read from that +* address. +* +* @param Addr: contains the address to perform the input operation +* +* @return The 16 bit Value read from the specified input address. +* +******************************************************************************/ +static INLINE u16 Xil_In16(UINTPTR Addr) +{ + return *(volatile u16 *) Addr; +} + +/*****************************************************************************/ +/** +* +* @brief Performs an input operation for a memory location by +* reading from the specified address and returning the 32 bit Value +* read from that address. +* +* @param Addr: contains the address to perform the input operation +* +* @return The 32 bit Value read from the specified input address. +* +******************************************************************************/ +static INLINE u32 Xil_In32(UINTPTR Addr) +{ + return *(volatile u32 *) Addr; +} + +/*****************************************************************************/ +/** +* +* @brief Performs an input operation for a memory location by reading the +* 64 bit Value read from that address. +* +* +* @param Addr: contains the address to perform the input operation +* +* @return The 64 bit Value read from the specified input address. +* +******************************************************************************/ +static INLINE u64 Xil_In64(UINTPTR Addr) +{ + return *(volatile u64 *) Addr; +} + +/*****************************************************************************/ +/** +* +* @brief Performs an output operation for an memory location by +* writing the 8 bit Value to the the specified address. +* +* @param Addr: contains the address to perform the output operation +* @param Value: contains the 8 bit Value to be written at the specified +* address. +* +* @return None. +* +******************************************************************************/ +static INLINE void Xil_Out8(UINTPTR Addr, u8 Value) +{ + volatile u8 *LocalAddr = (volatile u8 *)Addr; + *LocalAddr = Value; +} + +/*****************************************************************************/ +/** +* +* @brief Performs an output operation for a memory location by writing the +* 16 bit Value to the the specified address. +* +* @param Addr contains the address to perform the output operation +* @param Value contains the Value to be written at the specified address. +* +* @return None. +* +******************************************************************************/ +static INLINE void Xil_Out16(UINTPTR Addr, u16 Value) +{ + volatile u16 *LocalAddr = (volatile u16 *)Addr; + *LocalAddr = Value; +} + +/*****************************************************************************/ +/** +* +* @brief Performs an output operation for a memory location by writing the +* 32 bit Value to the the specified address. +* +* @param Addr contains the address to perform the output operation +* @param Value contains the 32 bit Value to be written at the specified +* address. +* +* @return None. +* +******************************************************************************/ +static INLINE void Xil_Out32(UINTPTR Addr, u32 Value) +{ +#ifndef ENABLE_SAFETY + volatile u32 *LocalAddr = (volatile u32 *)Addr; + *LocalAddr = Value; +#else + XStl_RegUpdate(Addr, Value); +#endif +} + +/*****************************************************************************/ +/** +* +* @brief Performs an output operation for a memory location by writing the +* 64 bit Value to the the specified address. +* +* @param Addr contains the address to perform the output operation +* @param Value contains 64 bit Value to be written at the specified address. +* +* @return None. +* +******************************************************************************/ +static INLINE void Xil_Out64(UINTPTR Addr, u64 Value) +{ + volatile u64 *LocalAddr = (volatile u64 *)Addr; + *LocalAddr = Value; +} + +#if defined (__MICROBLAZE__) +#ifdef __LITTLE_ENDIAN__ +# define Xil_In16LE Xil_In16 +# define Xil_In32LE Xil_In32 +# define Xil_Out16LE Xil_Out16 +# define Xil_Out32LE Xil_Out32 +# define Xil_Htons Xil_EndianSwap16 +# define Xil_Htonl Xil_EndianSwap32 +# define Xil_Ntohs Xil_EndianSwap16 +# define Xil_Ntohl Xil_EndianSwap32 +# else +# define Xil_In16BE Xil_In16 +# define Xil_In32BE Xil_In32 +# define Xil_Out16BE Xil_Out16 +# define Xil_Out32BE Xil_Out32 +# define Xil_Htons(Data) (Data) +# define Xil_Htonl(Data) (Data) +# define Xil_Ntohs(Data) (Data) +# define Xil_Ntohl(Data) (Data) +#endif +#else +# define Xil_In16LE Xil_In16 +# define Xil_In32LE Xil_In32 +# define Xil_Out16LE Xil_Out16 +# define Xil_Out32LE Xil_Out32 +# define Xil_Htons Xil_EndianSwap16 +# define Xil_Htonl Xil_EndianSwap32 +# define Xil_Ntohs Xil_EndianSwap16 +# define Xil_Ntohl Xil_EndianSwap32 +#endif + +#if defined (__MICROBLAZE__) +#ifdef __LITTLE_ENDIAN__ +static INLINE u16 Xil_In16BE(UINTPTR Addr) +#else +static INLINE u16 Xil_In16LE(UINTPTR Addr) +#endif +#else +static INLINE u16 Xil_In16BE(UINTPTR Addr) +#endif +{ + u16 value = Xil_In16(Addr); + return Xil_EndianSwap16(value); +} + +#if defined (__MICROBLAZE__) +#ifdef __LITTLE_ENDIAN__ +static INLINE u32 Xil_In32BE(UINTPTR Addr) +#else +static INLINE u32 Xil_In32LE(UINTPTR Addr) +#endif +#else +static INLINE u32 Xil_In32BE(UINTPTR Addr) +#endif +{ + u32 value = Xil_In32(Addr); + return Xil_EndianSwap32(value); +} + +#if defined (__MICROBLAZE__) +#ifdef __LITTLE_ENDIAN__ +static INLINE void Xil_Out16BE(UINTPTR Addr, u16 Value) +#else +static INLINE void Xil_Out16LE(UINTPTR Addr, u16 Value) +#endif +#else +static INLINE void Xil_Out16BE(UINTPTR Addr, u16 Value) +#endif +{ + Value = Xil_EndianSwap16(Value); + Xil_Out16(Addr, Value); +} + +#if defined (__MICROBLAZE__) +#ifdef __LITTLE_ENDIAN__ +static INLINE void Xil_Out32BE(UINTPTR Addr, u32 Value) +#else +static INLINE void Xil_Out32LE(UINTPTR Addr, u32 Value) +#endif +#else +static INLINE void Xil_Out32BE(UINTPTR Addr, u32 Value) +#endif +{ + Value = Xil_EndianSwap32(Value); + Xil_Out32(Addr, Value); +} + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** +* @} End of "addtogroup common_io_interfacing_apis". +*/ diff --git a/df_datalink/bsp/ps7_cortexa9_0/include/xil_macroback.h b/df_datalink/bsp/ps7_cortexa9_0/include/xil_macroback.h new file mode 100644 index 0000000..b245c18 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/include/xil_macroback.h @@ -0,0 +1,1056 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +/*********************************************************************/ +/** + * @file xil_macroback.h + * + * This header file is meant to bring back the removed _m macros. + * This header file must be included last. + * The following macros are not defined here due to the driver change: + * XGpio_mSetDataDirection + * XGpio_mGetDataReg + * XGpio_mSetDataReg + * XIIC_RESET + * XIIC_CLEAR_STATS + * XSpi_mReset + * XSysAce_mSetCfgAddr + * XSysAce_mIsCfgDone + * XTft_mSetPixel + * XTft_mGetPixel + * XWdtTb_mEnableWdt + * XWdtTb_mDisbleWdt + * XWdtTb_mRestartWdt + * XWdtTb_mGetTimebaseReg + * XWdtTb_mHasReset + * + * Please refer the corresonding driver document for replacement. + * + *********************************************************************/ + +#ifndef XIL_MACROBACK_H +#define XIL_MACROBACK_H + +#ifdef __cplusplus +extern "C" { +#endif + +/*********************************************************************/ +/** + * Macros for Driver XCan + * + *********************************************************************/ +#ifndef XCan_mReadReg +#define XCan_mReadReg XCan_ReadReg +#endif + +#ifndef XCan_mWriteReg +#define XCan_mWriteReg XCan_WriteReg +#endif + +#ifndef XCan_mIsTxDone +#define XCan_mIsTxDone XCan_IsTxDone +#endif + +#ifndef XCan_mIsTxFifoFull +#define XCan_mIsTxFifoFull XCan_IsTxFifoFull +#endif + +#ifndef XCan_mIsHighPriorityBufFull +#define XCan_mIsHighPriorityBufFull XCan_IsHighPriorityBufFull +#endif + +#ifndef XCan_mIsRxEmpty +#define XCan_mIsRxEmpty XCan_IsRxEmpty +#endif + +#ifndef XCan_mIsAcceptFilterBusy +#define XCan_mIsAcceptFilterBusy XCan_IsAcceptFilterBusy +#endif + +#ifndef XCan_mCreateIdValue +#define XCan_mCreateIdValue XCan_CreateIdValue +#endif + +#ifndef XCan_mCreateDlcValue +#define XCan_mCreateDlcValue XCan_CreateDlcValue +#endif + +/*********************************************************************/ +/** + * Macros for Driver XDmaCentral + * + *********************************************************************/ +#ifndef XDmaCentral_mWriteReg +#define XDmaCentral_mWriteReg XDmaCentral_WriteReg +#endif + +#ifndef XDmaCentral_mReadReg +#define XDmaCentral_mReadReg XDmaCentral_ReadReg +#endif + +/*********************************************************************/ +/** + * Macros for Driver XDsAdc + * + *********************************************************************/ +#ifndef XDsAdc_mWriteReg +#define XDsAdc_mWriteReg XDsAdc_WriteReg +#endif + +#ifndef XDsAdc_mReadReg +#define XDsAdc_mReadReg XDsAdc_ReadReg +#endif + +#ifndef XDsAdc_mIsEmpty +#define XDsAdc_mIsEmpty XDsAdc_IsEmpty +#endif + +#ifndef XDsAdc_mSetFstmReg +#define XDsAdc_mSetFstmReg XDsAdc_SetFstmReg +#endif + +#ifndef XDsAdc_mGetFstmReg +#define XDsAdc_mGetFstmReg XDsAdc_GetFstmReg +#endif + +#ifndef XDsAdc_mEnableConversion +#define XDsAdc_mEnableConversion XDsAdc_EnableConversion +#endif + +#ifndef XDsAdc_mDisableConversion +#define XDsAdc_mDisableConversion XDsAdc_DisableConversion +#endif + +#ifndef XDsAdc_mGetFifoOccyReg +#define XDsAdc_mGetFifoOccyReg XDsAdc_GetFifoOccyReg +#endif + +/*********************************************************************/ +/** + * Macros for Driver XDsDac + * + *********************************************************************/ +#ifndef XDsDac_mWriteReg +#define XDsDac_mWriteReg XDsDac_WriteReg +#endif + +#ifndef XDsDac_mReadReg +#define XDsDac_mReadReg XDsDac_ReadReg +#endif + +#ifndef XDsDac_mIsEmpty +#define XDsDac_mIsEmpty XDsDac_IsEmpty +#endif + +#ifndef XDsDac_mFifoIsFull +#define XDsDac_mFifoIsFull XDsDac_FifoIsFull +#endif + +#ifndef XDsDac_mGetVacancy +#define XDsDac_mGetVacancy XDsDac_GetVacancy +#endif + +/*********************************************************************/ +/** + * Macros for Driver XEmacLite + * + *********************************************************************/ +#ifndef XEmacLite_mReadReg +#define XEmacLite_mReadReg XEmacLite_ReadReg +#endif + +#ifndef XEmacLite_mWriteReg +#define XEmacLite_mWriteReg XEmacLite_WriteReg +#endif + +#ifndef XEmacLite_mGetTxStatus +#define XEmacLite_mGetTxStatus XEmacLite_GetTxStatus +#endif + +#ifndef XEmacLite_mSetTxStatus +#define XEmacLite_mSetTxStatus XEmacLite_SetTxStatus +#endif + +#ifndef XEmacLite_mGetRxStatus +#define XEmacLite_mGetRxStatus XEmacLite_GetRxStatus +#endif + +#ifndef XEmacLite_mSetRxStatus +#define XEmacLite_mSetRxStatus XEmacLite_SetRxStatus +#endif + +#ifndef XEmacLite_mIsTxDone +#define XEmacLite_mIsTxDone XEmacLite_IsTxDone +#endif + +#ifndef XEmacLite_mIsRxEmpty +#define XEmacLite_mIsRxEmpty XEmacLite_IsRxEmpty +#endif + +#ifndef XEmacLite_mNextTransmitAddr +#define XEmacLite_mNextTransmitAddr XEmacLite_NextTransmitAddr +#endif + +#ifndef XEmacLite_mNextReceiveAddr +#define XEmacLite_mNextReceiveAddr XEmacLite_NextReceiveAddr +#endif + +#ifndef XEmacLite_mIsMdioConfigured +#define XEmacLite_mIsMdioConfigured XEmacLite_IsMdioConfigured +#endif + +#ifndef XEmacLite_mIsLoopbackConfigured +#define XEmacLite_mIsLoopbackConfigured XEmacLite_IsLoopbackConfigured +#endif + +#ifndef XEmacLite_mGetReceiveDataLength +#define XEmacLite_mGetReceiveDataLength XEmacLite_GetReceiveDataLength +#endif + +#ifndef XEmacLite_mGetTxActive +#define XEmacLite_mGetTxActive XEmacLite_GetTxActive +#endif + +#ifndef XEmacLite_mSetTxActive +#define XEmacLite_mSetTxActive XEmacLite_SetTxActive +#endif + +/*********************************************************************/ +/** + * Macros for Driver XGpio + * + *********************************************************************/ +#ifndef XGpio_mWriteReg +#define XGpio_mWriteReg XGpio_WriteReg +#endif + +#ifndef XGpio_mReadReg +#define XGpio_mReadReg XGpio_ReadReg +#endif + +/*********************************************************************/ +/** + * Macros for Driver XHwIcap + * + *********************************************************************/ +#ifndef XHwIcap_mFifoWrite +#define XHwIcap_mFifoWrite XHwIcap_FifoWrite +#endif + +#ifndef XHwIcap_mFifoRead +#define XHwIcap_mFifoRead XHwIcap_FifoRead +#endif + +#ifndef XHwIcap_mSetSizeReg +#define XHwIcap_mSetSizeReg XHwIcap_SetSizeReg +#endif + +#ifndef XHwIcap_mGetControlReg +#define XHwIcap_mGetControlReg XHwIcap_GetControlReg +#endif + +#ifndef XHwIcap_mStartConfig +#define XHwIcap_mStartConfig XHwIcap_StartConfig +#endif + +#ifndef XHwIcap_mStartReadBack +#define XHwIcap_mStartReadBack XHwIcap_StartReadBack +#endif + +#ifndef XHwIcap_mGetStatusReg +#define XHwIcap_mGetStatusReg XHwIcap_GetStatusReg +#endif + +#ifndef XHwIcap_mIsTransferDone +#define XHwIcap_mIsTransferDone XHwIcap_IsTransferDone +#endif + +#ifndef XHwIcap_mIsDeviceBusy +#define XHwIcap_mIsDeviceBusy XHwIcap_IsDeviceBusy +#endif + +#ifndef XHwIcap_mIntrGlobalEnable +#define XHwIcap_mIntrGlobalEnable XHwIcap_IntrGlobalEnable +#endif + +#ifndef XHwIcap_mIntrGlobalDisable +#define XHwIcap_mIntrGlobalDisable XHwIcap_IntrGlobalDisable +#endif + +#ifndef XHwIcap_mIntrGetStatus +#define XHwIcap_mIntrGetStatus XHwIcap_IntrGetStatus +#endif + +#ifndef XHwIcap_mIntrDisable +#define XHwIcap_mIntrDisable XHwIcap_IntrDisable +#endif + +#ifndef XHwIcap_mIntrEnable +#define XHwIcap_mIntrEnable XHwIcap_IntrEnable +#endif + +#ifndef XHwIcap_mIntrGetEnabled +#define XHwIcap_mIntrGetEnabled XHwIcap_IntrGetEnabled +#endif + +#ifndef XHwIcap_mIntrClear +#define XHwIcap_mIntrClear XHwIcap_IntrClear +#endif + +#ifndef XHwIcap_mGetWrFifoVacancy +#define XHwIcap_mGetWrFifoVacancy XHwIcap_GetWrFifoVacancy +#endif + +#ifndef XHwIcap_mGetRdFifoOccupancy +#define XHwIcap_mGetRdFifoOccupancy XHwIcap_GetRdFifoOccupancy +#endif + +#ifndef XHwIcap_mSliceX2Col +#define XHwIcap_mSliceX2Col XHwIcap_SliceX2Col +#endif + +#ifndef XHwIcap_mSliceY2Row +#define XHwIcap_mSliceY2Row XHwIcap_SliceY2Row +#endif + +#ifndef XHwIcap_mSliceXY2Slice +#define XHwIcap_mSliceXY2Slice XHwIcap_SliceXY2Slice +#endif + +#ifndef XHwIcap_mReadReg +#define XHwIcap_mReadReg XHwIcap_ReadReg +#endif + +#ifndef XHwIcap_mWriteReg +#define XHwIcap_mWriteReg XHwIcap_WriteReg +#endif + +/*********************************************************************/ +/** + * Macros for Driver XIic + * + *********************************************************************/ +#ifndef XIic_mReadReg +#define XIic_mReadReg XIic_ReadReg +#endif + +#ifndef XIic_mWriteReg +#define XIic_mWriteReg XIic_WriteReg +#endif + +#ifndef XIic_mEnterCriticalRegion +#define XIic_mEnterCriticalRegion XIic_IntrGlobalDisable +#endif + +#ifndef XIic_mExitCriticalRegion +#define XIic_mExitCriticalRegion XIic_IntrGlobalEnable +#endif + +#ifndef XIIC_GINTR_DISABLE +#define XIIC_GINTR_DISABLE XIic_IntrGlobalDisable +#endif + +#ifndef XIIC_GINTR_ENABLE +#define XIIC_GINTR_ENABLE XIic_IntrGlobalEnable +#endif + +#ifndef XIIC_IS_GINTR_ENABLED +#define XIIC_IS_GINTR_ENABLED XIic_IsIntrGlobalEnabled +#endif + +#ifndef XIIC_WRITE_IISR +#define XIIC_WRITE_IISR XIic_WriteIisr +#endif + +#ifndef XIIC_READ_IISR +#define XIIC_READ_IISR XIic_ReadIisr +#endif + +#ifndef XIIC_WRITE_IIER +#define XIIC_WRITE_IIER XIic_WriteIier +#endif + +#ifndef XIic_mClearIisr +#define XIic_mClearIisr XIic_ClearIisr +#endif + +#ifndef XIic_mSend7BitAddress +#define XIic_mSend7BitAddress XIic_Send7BitAddress +#endif + +#ifndef XIic_mDynSend7BitAddress +#define XIic_mDynSend7BitAddress XIic_DynSend7BitAddress +#endif + +#ifndef XIic_mDynSendStartStopAddress +#define XIic_mDynSendStartStopAddress XIic_DynSendStartStopAddress +#endif + +#ifndef XIic_mDynSendStop +#define XIic_mDynSendStop XIic_DynSendStop +#endif + +#ifndef XIic_mSend10BitAddrByte1 +#define XIic_mSend10BitAddrByte1 XIic_Send10BitAddrByte1 +#endif + +#ifndef XIic_mSend10BitAddrByte2 +#define XIic_mSend10BitAddrByte2 XIic_Send10BitAddrByte2 +#endif + +#ifndef XIic_mSend7BitAddr +#define XIic_mSend7BitAddr XIic_Send7BitAddr +#endif + +#ifndef XIic_mDisableIntr +#define XIic_mDisableIntr XIic_DisableIntr +#endif + +#ifndef XIic_mEnableIntr +#define XIic_mEnableIntr XIic_EnableIntr +#endif + +#ifndef XIic_mClearIntr +#define XIic_mClearIntr XIic_ClearIntr +#endif + +#ifndef XIic_mClearEnableIntr +#define XIic_mClearEnableIntr XIic_ClearEnableIntr +#endif + +#ifndef XIic_mFlushRxFifo +#define XIic_mFlushRxFifo XIic_FlushRxFifo +#endif + +#ifndef XIic_mFlushTxFifo +#define XIic_mFlushTxFifo XIic_FlushTxFifo +#endif + +#ifndef XIic_mReadRecvByte +#define XIic_mReadRecvByte XIic_ReadRecvByte +#endif + +#ifndef XIic_mWriteSendByte +#define XIic_mWriteSendByte XIic_WriteSendByte +#endif + +#ifndef XIic_mSetControlRegister +#define XIic_mSetControlRegister XIic_SetControlRegister +#endif + +/*********************************************************************/ +/** + * Macros for Driver XIntc + * + *********************************************************************/ +#ifndef XIntc_mMasterEnable +#define XIntc_mMasterEnable XIntc_MasterEnable +#endif + +#ifndef XIntc_mMasterDisable +#define XIntc_mMasterDisable XIntc_MasterDisable +#endif + +#ifndef XIntc_mEnableIntr +#define XIntc_mEnableIntr XIntc_EnableIntr +#endif + +#ifndef XIntc_mDisableIntr +#define XIntc_mDisableIntr XIntc_DisableIntr +#endif + +#ifndef XIntc_mAckIntr +#define XIntc_mAckIntr XIntc_AckIntr +#endif + +#ifndef XIntc_mGetIntrStatus +#define XIntc_mGetIntrStatus XIntc_GetIntrStatus +#endif + +/*********************************************************************/ +/** + * Macros for Driver XLlDma + * + *********************************************************************/ +#ifndef XLlDma_mBdRead +#define XLlDma_mBdRead XLlDma_BdRead +#endif + +#ifndef XLlDma_mBdWrite +#define XLlDma_mBdWrite XLlDma_BdWrite +#endif + +#ifndef XLlDma_mWriteReg +#define XLlDma_mWriteReg XLlDma_WriteReg +#endif + +#ifndef XLlDma_mReadReg +#define XLlDma_mReadReg XLlDma_ReadReg +#endif + +#ifndef XLlDma_mBdClear +#define XLlDma_mBdClear XLlDma_BdClear +#endif + +#ifndef XLlDma_mBdSetStsCtrl +#define XLlDma_mBdSetStsCtrl XLlDma_BdSetStsCtrl +#endif + +#ifndef XLlDma_mBdGetStsCtrl +#define XLlDma_mBdGetStsCtrl XLlDma_BdGetStsCtrl +#endif + +#ifndef XLlDma_mBdSetLength +#define XLlDma_mBdSetLength XLlDma_BdSetLength +#endif + +#ifndef XLlDma_mBdGetLength +#define XLlDma_mBdGetLength XLlDma_BdGetLength +#endif + +#ifndef XLlDma_mBdSetId +#define XLlDma_mBdSetId XLlDma_BdSetId +#endif + +#ifndef XLlDma_mBdGetId +#define XLlDma_mBdGetId XLlDma_BdGetId +#endif + +#ifndef XLlDma_mBdSetBufAddr +#define XLlDma_mBdSetBufAddr XLlDma_BdSetBufAddr +#endif + +#ifndef XLlDma_mBdGetBufAddr +#define XLlDma_mBdGetBufAddr XLlDma_BdGetBufAddr +#endif + +#ifndef XLlDma_mBdGetLength +#define XLlDma_mBdGetLength XLlDma_BdGetLength +#endif + +#ifndef XLlDma_mGetTxRing +#define XLlDma_mGetTxRing XLlDma_GetTxRing +#endif + +#ifndef XLlDma_mGetRxRing +#define XLlDma_mGetRxRing XLlDma_GetRxRing +#endif + +#ifndef XLlDma_mGetCr +#define XLlDma_mGetCr XLlDma_GetCr +#endif + +#ifndef XLlDma_mSetCr +#define XLlDma_mSetCr XLlDma_SetCr +#endif + +#ifndef XLlDma_mBdRingCntCalc +#define XLlDma_mBdRingCntCalc XLlDma_BdRingCntCalc +#endif + +#ifndef XLlDma_mBdRingMemCalc +#define XLlDma_mBdRingMemCalc XLlDma_BdRingMemCalc +#endif + +#ifndef XLlDma_mBdRingGetCnt +#define XLlDma_mBdRingGetCnt XLlDma_BdRingGetCnt +#endif + +#ifndef XLlDma_mBdRingGetFreeCnt +#define XLlDma_mBdRingGetFreeCnt XLlDma_BdRingGetFreeCnt +#endif + +#ifndef XLlDma_mBdRingSnapShotCurrBd +#define XLlDma_mBdRingSnapShotCurrBd XLlDma_BdRingSnapShotCurrBd +#endif + +#ifndef XLlDma_mBdRingNext +#define XLlDma_mBdRingNext XLlDma_BdRingNext +#endif + +#ifndef XLlDma_mBdRingPrev +#define XLlDma_mBdRingPrev XLlDma_BdRingPrev +#endif + +#ifndef XLlDma_mBdRingGetSr +#define XLlDma_mBdRingGetSr XLlDma_BdRingGetSr +#endif + +#ifndef XLlDma_mBdRingSetSr +#define XLlDma_mBdRingSetSr XLlDma_BdRingSetSr +#endif + +#ifndef XLlDma_mBdRingGetCr +#define XLlDma_mBdRingGetCr XLlDma_BdRingGetCr +#endif + +#ifndef XLlDma_mBdRingSetCr +#define XLlDma_mBdRingSetCr XLlDma_BdRingSetCr +#endif + +#ifndef XLlDma_mBdRingBusy +#define XLlDma_mBdRingBusy XLlDma_BdRingBusy +#endif + +#ifndef XLlDma_mBdRingIntEnable +#define XLlDma_mBdRingIntEnable XLlDma_BdRingIntEnable +#endif + +#ifndef XLlDma_mBdRingIntDisable +#define XLlDma_mBdRingIntDisable XLlDma_BdRingIntDisable +#endif + +#ifndef XLlDma_mBdRingIntGetEnabled +#define XLlDma_mBdRingIntGetEnabled XLlDma_BdRingIntGetEnabled +#endif + +#ifndef XLlDma_mBdRingGetIrq +#define XLlDma_mBdRingGetIrq XLlDma_BdRingGetIrq +#endif + +#ifndef XLlDma_mBdRingAckIrq +#define XLlDma_mBdRingAckIrq XLlDma_BdRingAckIrq +#endif + +/*********************************************************************/ +/** + * Macros for Driver XMbox + * + *********************************************************************/ +#ifndef XMbox_mWriteReg +#define XMbox_mWriteReg XMbox_WriteReg +#endif + +#ifndef XMbox_mReadReg +#define XMbox_mReadReg XMbox_ReadReg +#endif + +#ifndef XMbox_mWriteMBox +#define XMbox_mWriteMBox XMbox_WriteMBox +#endif + +#ifndef XMbox_mReadMBox +#define XMbox_mReadMBox XMbox_ReadMBox +#endif + +#ifndef XMbox_mFSLReadMBox +#define XMbox_mFSLReadMBox XMbox_FSLReadMBox +#endif + +#ifndef XMbox_mFSLWriteMBox +#define XMbox_mFSLWriteMBox XMbox_FSLWriteMBox +#endif + +#ifndef XMbox_mFSLIsEmpty +#define XMbox_mFSLIsEmpty XMbox_FSLIsEmpty +#endif + +#ifndef XMbox_mFSLIsFull +#define XMbox_mFSLIsFull XMbox_FSLIsFull +#endif + +#ifndef XMbox_mIsEmpty +#define XMbox_mIsEmpty XMbox_IsEmptyHw +#endif + +#ifndef XMbox_mIsFull +#define XMbox_mIsFull XMbox_IsFullHw +#endif + +/*********************************************************************/ +/** + * Macros for Driver XMpmc + * + *********************************************************************/ +#ifndef XMpmc_mReadReg +#define XMpmc_mReadReg XMpmc_ReadReg +#endif + +#ifndef XMpmc_mWriteReg +#define XMpmc_mWriteReg XMpmc_WriteReg +#endif + +/*********************************************************************/ +/** + * Macros for Driver XMutex + * + *********************************************************************/ +#ifndef XMutex_mWriteReg +#define XMutex_mWriteReg XMutex_WriteReg +#endif + +#ifndef XMutex_mReadReg +#define XMutex_mReadReg XMutex_ReadReg +#endif + +/*********************************************************************/ +/** + * Macros for Driver XPcie + * + *********************************************************************/ +#ifndef XPcie_mReadReg +#define XPcie_mReadReg XPcie_ReadReg +#endif + +#ifndef XPcie_mWriteReg +#define XPcie_mWriteReg XPcie_WriteReg +#endif + +/*********************************************************************/ +/** + * Macros for Driver XSpi + * + *********************************************************************/ +#ifndef XSpi_mIntrGlobalEnable +#define XSpi_mIntrGlobalEnable XSpi_IntrGlobalEnable +#endif + +#ifndef XSpi_mIntrGlobalDisable +#define XSpi_mIntrGlobalDisable XSpi_IntrGlobalDisable +#endif + +#ifndef XSpi_mIsIntrGlobalEnabled +#define XSpi_mIsIntrGlobalEnabled XSpi_IsIntrGlobalEnabled +#endif + +#ifndef XSpi_mIntrGetStatus +#define XSpi_mIntrGetStatus XSpi_IntrGetStatus +#endif + +#ifndef XSpi_mIntrClear +#define XSpi_mIntrClear XSpi_IntrClear +#endif + +#ifndef XSpi_mIntrEnable +#define XSpi_mIntrEnable XSpi_IntrEnable +#endif + +#ifndef XSpi_mIntrDisable +#define XSpi_mIntrDisable XSpi_IntrDisable +#endif + +#ifndef XSpi_mIntrGetEnabled +#define XSpi_mIntrGetEnabled XSpi_IntrGetEnabled +#endif + +#ifndef XSpi_mSetControlReg +#define XSpi_mSetControlReg XSpi_SetControlReg +#endif + +#ifndef XSpi_mGetControlReg +#define XSpi_mGetControlReg XSpi_GetControlReg +#endif + +#ifndef XSpi_mGetStatusReg +#define XSpi_mGetStatusReg XSpi_GetStatusReg +#endif + +#ifndef XSpi_mSetSlaveSelectReg +#define XSpi_mSetSlaveSelectReg XSpi_SetSlaveSelectReg +#endif + +#ifndef XSpi_mGetSlaveSelectReg +#define XSpi_mGetSlaveSelectReg XSpi_GetSlaveSelectReg +#endif + +#ifndef XSpi_mEnable +#define XSpi_mEnable XSpi_Enable +#endif + +#ifndef XSpi_mDisable +#define XSpi_mDisable XSpi_Disable +#endif + +/*********************************************************************/ +/** + * Macros for Driver XSysAce + * + *********************************************************************/ +#ifndef XSysAce_mGetControlReg +#define XSysAce_mGetControlReg XSysAce_GetControlReg +#endif + +#ifndef XSysAce_mSetControlReg +#define XSysAce_mSetControlReg XSysAce_SetControlReg +#endif + +#ifndef XSysAce_mOrControlReg +#define XSysAce_mOrControlReg XSysAce_OrControlReg +#endif + +#ifndef XSysAce_mAndControlReg +#define XSysAce_mAndControlReg XSysAce_AndControlReg +#endif + +#ifndef XSysAce_mGetErrorReg +#define XSysAce_mGetErrorReg XSysAce_GetErrorReg +#endif + +#ifndef XSysAce_mGetStatusReg +#define XSysAce_mGetStatusReg XSysAce_GetStatusReg +#endif + +#ifndef XSysAce_mWaitForLock +#define XSysAce_mWaitForLock XSysAce_WaitForLock +#endif + +#ifndef XSysAce_mEnableIntr +#define XSysAce_mEnableIntr XSysAce_EnableIntr +#endif + +#ifndef XSysAce_mDisableIntr +#define XSysAce_mDisableIntr XSysAce_DisableIntr +#endif + +#ifndef XSysAce_mIsReadyForCmd +#define XSysAce_mIsReadyForCmd XSysAce_IsReadyForCmd +#endif + +#ifndef XSysAce_mIsMpuLocked +#define XSysAce_mIsMpuLocked XSysAce_IsMpuLocked +#endif + +#ifndef XSysAce_mIsIntrEnabled +#define XSysAce_mIsIntrEnabled XSysAce_IsIntrEnabled +#endif + +/*********************************************************************/ +/** + * Macros for Driver XSysMon + * + *********************************************************************/ +#ifndef XSysMon_mIsEventSamplingModeSet +#define XSysMon_mIsEventSamplingModeSet XSysMon_IsEventSamplingModeSet +#endif + +#ifndef XSysMon_mIsDrpBusy +#define XSysMon_mIsDrpBusy XSysMon_IsDrpBusy +#endif + +#ifndef XSysMon_mIsDrpLocked +#define XSysMon_mIsDrpLocked XSysMon_IsDrpLocked +#endif + +#ifndef XSysMon_mRawToTemperature +#define XSysMon_mRawToTemperature XSysMon_RawToTemperature +#endif + +#ifndef XSysMon_mRawToVoltage +#define XSysMon_mRawToVoltage XSysMon_RawToVoltage +#endif + +#ifndef XSysMon_mTemperatureToRaw +#define XSysMon_mTemperatureToRaw XSysMon_TemperatureToRaw +#endif + +#ifndef XSysMon_mVoltageToRaw +#define XSysMon_mVoltageToRaw XSysMon_VoltageToRaw +#endif + +#ifndef XSysMon_mReadReg +#define XSysMon_mReadReg XSysMon_ReadReg +#endif + +#ifndef XSysMon_mWriteReg +#define XSysMon_mWriteReg XSysMon_WriteReg +#endif + +/*********************************************************************/ +/** + * Macros for Driver XTmrCtr + * + *********************************************************************/ +#ifndef XTimerCtr_mReadReg +#define XTimerCtr_mReadReg XTimerCtr_ReadReg +#endif + +#ifndef XTmrCtr_mWriteReg +#define XTmrCtr_mWriteReg XTmrCtr_WriteReg +#endif + +#ifndef XTmrCtr_mSetControlStatusReg +#define XTmrCtr_mSetControlStatusReg XTmrCtr_SetControlStatusReg +#endif + +#ifndef XTmrCtr_mGetControlStatusReg +#define XTmrCtr_mGetControlStatusReg XTmrCtr_GetControlStatusReg +#endif + +#ifndef XTmrCtr_mGetTimerCounterReg +#define XTmrCtr_mGetTimerCounterReg XTmrCtr_GetTimerCounterReg +#endif + +#ifndef XTmrCtr_mSetLoadReg +#define XTmrCtr_mSetLoadReg XTmrCtr_SetLoadReg +#endif + +#ifndef XTmrCtr_mGetLoadReg +#define XTmrCtr_mGetLoadReg XTmrCtr_GetLoadReg +#endif + +#ifndef XTmrCtr_mEnable +#define XTmrCtr_mEnable XTmrCtr_Enable +#endif + +#ifndef XTmrCtr_mDisable +#define XTmrCtr_mDisable XTmrCtr_Disable +#endif + +#ifndef XTmrCtr_mEnableIntr +#define XTmrCtr_mEnableIntr XTmrCtr_EnableIntr +#endif + +#ifndef XTmrCtr_mDisableIntr +#define XTmrCtr_mDisableIntr XTmrCtr_DisableIntr +#endif + +#ifndef XTmrCtr_mLoadTimerCounterReg +#define XTmrCtr_mLoadTimerCounterReg XTmrCtr_LoadTimerCounterReg +#endif + +#ifndef XTmrCtr_mHasEventOccurred +#define XTmrCtr_mHasEventOccurred XTmrCtr_HasEventOccurred +#endif + +/*********************************************************************/ +/** + * Macros for Driver XUartLite + * + *********************************************************************/ +#ifndef XUartLite_mUpdateStats +#define XUartLite_mUpdateStats XUartLite_UpdateStats +#endif + +#ifndef XUartLite_mWriteReg +#define XUartLite_mWriteReg XUartLite_WriteReg +#endif + +#ifndef XUartLite_mReadReg +#define XUartLite_mReadReg XUartLite_ReadReg +#endif + +#ifndef XUartLite_mClearStats +#define XUartLite_mClearStats XUartLite_ClearStats +#endif + +#ifndef XUartLite_mSetControlReg +#define XUartLite_mSetControlReg XUartLite_SetControlReg +#endif + +#ifndef XUartLite_mGetStatusReg +#define XUartLite_mGetStatusReg XUartLite_GetStatusReg +#endif + +#ifndef XUartLite_mIsReceiveEmpty +#define XUartLite_mIsReceiveEmpty XUartLite_IsReceiveEmpty +#endif + +#ifndef XUartLite_mIsTransmitFull +#define XUartLite_mIsTransmitFull XUartLite_IsTransmitFull +#endif + +#ifndef XUartLite_mIsIntrEnabled +#define XUartLite_mIsIntrEnabled XUartLite_IsIntrEnabled +#endif + +#ifndef XUartLite_mEnableIntr +#define XUartLite_mEnableIntr XUartLite_EnableIntr +#endif + +#ifndef XUartLite_mDisableIntr +#define XUartLite_mDisableIntr XUartLite_DisableIntr +#endif + +/*********************************************************************/ +/** + * Macros for Driver XUartNs550 + * + *********************************************************************/ +#ifndef XUartNs550_mUpdateStats +#define XUartNs550_mUpdateStats XUartNs550_UpdateStats +#endif + +#ifndef XUartNs550_mReadReg +#define XUartNs550_mReadReg XUartNs550_ReadReg +#endif + +#ifndef XUartNs550_mWriteReg +#define XUartNs550_mWriteReg XUartNs550_WriteReg +#endif + +#ifndef XUartNs550_mClearStats +#define XUartNs550_mClearStats XUartNs550_ClearStats +#endif + +#ifndef XUartNs550_mGetLineStatusReg +#define XUartNs550_mGetLineStatusReg XUartNs550_GetLineStatusReg +#endif + +#ifndef XUartNs550_mGetLineControlReg +#define XUartNs550_mGetLineControlReg XUartNs550_GetLineControlReg +#endif + +#ifndef XUartNs550_mSetLineControlReg +#define XUartNs550_mSetLineControlReg XUartNs550_SetLineControlReg +#endif + +#ifndef XUartNs550_mEnableIntr +#define XUartNs550_mEnableIntr XUartNs550_EnableIntr +#endif + +#ifndef XUartNs550_mDisableIntr +#define XUartNs550_mDisableIntr XUartNs550_DisableIntr +#endif + +#ifndef XUartNs550_mIsReceiveData +#define XUartNs550_mIsReceiveData XUartNs550_IsReceiveData +#endif + +#ifndef XUartNs550_mIsTransmitEmpty +#define XUartNs550_mIsTransmitEmpty XUartNs550_IsTransmitEmpty +#endif + +/*********************************************************************/ +/** + * Macros for Driver XUsb + * + *********************************************************************/ +#ifndef XUsb_mReadReg +#define XUsb_mReadReg XUsb_ReadReg +#endif + +#ifndef XUsb_mWriteReg +#define XUsb_mWriteReg XUsb_WriteReg +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/df_datalink/bsp/ps7_cortexa9_0/include/xil_mem.h b/df_datalink/bsp/ps7_cortexa9_0/include/xil_mem.h new file mode 100644 index 0000000..9aae942 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/include/xil_mem.h @@ -0,0 +1,68 @@ +/******************************************************************************/ +/** +* Copyright (C) 2015 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* @file xil_mem.h +* +* @addtogroup common_mem_operation_api Customized APIs for Memory Operations +* +* The xil_mem.h file contains prototype for functions related +* to memory operations. These APIs are applicable for all processors supported +* by Xilinx. +* +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 6.1   nsk      11/07/16 First release.
+* 7.0   mus      01/07/19 Add cpp extern macro
+*
+* 
+* +*****************************************************************************/ +#ifndef XIL_MEM_H /* prevent circular inclusions */ +#define XIL_MEM_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/************************** Function Prototypes *****************************/ + +void Xil_MemCpy(void* dst, const void* src, u32 cnt); + +#ifdef __cplusplus +} +#endif + +#endif /* XIL_MEM_H */ +/** +* @} End of "addtogroup common_mem_operation_api". +*/ \ No newline at end of file diff --git a/df_datalink/bsp/ps7_cortexa9_0/include/xil_misc_psreset_api.h b/df_datalink/bsp/ps7_cortexa9_0/include/xil_misc_psreset_api.h new file mode 100644 index 0000000..3a26175 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/include/xil_misc_psreset_api.h @@ -0,0 +1,273 @@ +/****************************************************************************** +* +* Copyright (C) 2013 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file xil_misc_psreset_api.h +* +* This file contains the various register defintions and function prototypes for +* implementing the reset functionality of zynq ps devices +* +* MODIFICATION HISTORY: +* +* Ver Who Date Changes +* ----- ---- -------- ------------------------------------------------------- +* 1.00b kpc 03/07/13 First release. +* +* +******************************************************************************/ + +#ifndef XIL_MISC_RESET_H /* prevent circular inclusions */ +#define XIL_MISC_RESET_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + + +/***************************** Include Files *********************************/ +#include "xil_types.h" +#include "xil_io.h" + +/************************** Constant Definitions *****************************/ +#define XDDRC_CTRL_BASEADDR 0xF8006000U +#define XSLCR_BASEADDR 0xF8000000U +/**< OCM configuration register */ +#define XSLCR_OCM_CFG_ADDR (XSLCR_BASEADDR + 0x00000910U) +/**< SLCR unlock register */ +#define XSLCR_UNLOCK_ADDR (XSLCR_BASEADDR + 0x00000008U) +/**< SLCR GEM0 rx clock control register */ +#define XSLCR_GEM0_RCLK_CTRL_ADDR (XSLCR_BASEADDR + 0x00000138U) +/**< SLCR GEM1 rx clock control register */ +#define XSLCR_GEM1_RCLK_CTRL_ADDR (XSLCR_BASEADDR + 0x0000013CU) +/**< SLCR GEM0 clock control register */ +#define XSLCR_GEM0_CLK_CTRL_ADDR (XSLCR_BASEADDR + 0x00000140U) +/**< SLCR GEM1 clock control register */ +#define XSLCR_GEM1_CLK_CTRL_ADDR (XSLCR_BASEADDR + 0x00000144U) +/**< SLCR SMC clock control register */ +#define XSLCR_SMC_CLK_CTRL_ADDR (XSLCR_BASEADDR + 0x00000148U) +/**< SLCR GEM reset control register */ +#define XSLCR_GEM_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000214U) +/**< SLCR USB0 clock control register */ +#define XSLCR_USB0_CLK_CTRL_ADDR (XSLCR_BASEADDR + 0x00000130U) +/**< SLCR USB1 clock control register */ +#define XSLCR_USB1_CLK_CTRL_ADDR (XSLCR_BASEADDR + 0x00000134U) +/**< SLCR USB1 reset control register */ +#define XSLCR_USB_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000210U) +/**< SLCR SMC reset control register */ +#define XSLCR_SMC_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000234U) +/**< SLCR Level shifter enable register */ +#define XSLCR_LVL_SHFTR_EN_ADDR (XSLCR_BASEADDR + 0x00000900U) +/**< SLCR ARM pll control register */ +#define XSLCR_ARM_PLL_CTRL_ADDR (XSLCR_BASEADDR + 0x00000100U) +/**< SLCR DDR pll control register */ +#define XSLCR_DDR_PLL_CTRL_ADDR (XSLCR_BASEADDR + 0x00000104U) +/**< SLCR IO pll control register */ +#define XSLCR_IO_PLL_CTRL_ADDR (XSLCR_BASEADDR + 0x00000108U) +/**< SLCR ARM pll configuration register */ +#define XSLCR_ARM_PLL_CFG_ADDR (XSLCR_BASEADDR + 0x00000110U) +/**< SLCR DDR pll configuration register */ +#define XSLCR_DDR_PLL_CFG_ADDR (XSLCR_BASEADDR + 0x00000114U) +/**< SLCR IO pll configuration register */ +#define XSLCR_IO_PLL_CFG_ADDR (XSLCR_BASEADDR + 0x00000118U) +/**< SLCR ARM clock control register */ +#define XSLCR_ARM_CLK_CTRL_ADDR (XSLCR_BASEADDR + 0x00000120U) +/**< SLCR DDR clock control register */ +#define XSLCR_DDR_CLK_CTRL_ADDR (XSLCR_BASEADDR + 0x00000124U) +/**< SLCR MIO pin address register */ +#define XSLCR_MIO_PIN_00_ADDR (XSLCR_BASEADDR + 0x00000700U) +/**< SLCR DMAC reset control address register */ +#define XSLCR_DMAC_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x0000020CU) +/**< SLCR USB reset control address register */ +/*#define XSLCR_USB_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000210U)*/ +/**< SLCR GEM reset control address register */ +/*#define XSLCR_GEM_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000214U)*/ +/**< SLCR SDIO reset control address register */ +#define XSLCR_SDIO_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000218U) +/**< SLCR SPI reset control address register */ +#define XSLCR_SPI_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x0000021CU) +/**< SLCR CAN reset control address register */ +#define XSLCR_CAN_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000220U) +/**< SLCR I2C reset control address register */ +#define XSLCR_I2C_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000224U) +/**< SLCR UART reset control address register */ +#define XSLCR_UART_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000228U) +/**< SLCR GPIO reset control address register */ +#define XSLCR_GPIO_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x0000022CU) +/**< SLCR LQSPI reset control address register */ +#define XSLCR_LQSPI_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000230U) +/**< SLCR SMC reset control address register */ +/*#define XSLCR_SMC_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000234U)*/ +/**< SLCR OCM reset control address register */ +#define XSLCR_OCM_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000238U) + +/**< SMC mem controller clear config register */ +#define XSMC_MEMC_CLR_CONFIG_OFFSET 0x0000000CU +/**< SMC idlecount configuration register */ +#define XSMC_REFRESH_PERIOD_0_OFFSET 0x00000020U +#define XSMC_REFRESH_PERIOD_1_OFFSET 0x00000024U +/**< SMC ECC configuration register */ +#define XSMC_ECC_MEMCFG1_OFFSET 0x00000404U +/**< SMC ECC command 1 register */ +#define XSMC_ECC_MEMCMD1_OFFSET 0x00000404U +/**< SMC ECC command 2 register */ +#define XSMC_ECC_MEMCMD2_OFFSET 0x00000404U + +/**< SLCR unlock code */ +#define XSLCR_UNLOCK_CODE 0x0000DF0DU + +/**< SMC mem clear configuration mask */ +#define XSMC_MEMC_CLR_CONFIG_MASK 0x000005FU +/**< SMC ECC memconfig 1 reset value */ +#define XSMC_ECC_MEMCFG1_RESET_VAL 0x0000043U +/**< SMC ECC memcommand 1 reset value */ +#define XSMC_ECC_MEMCMD1_RESET_VAL 0x01300080U +/**< SMC ECC memcommand 2 reset value */ +#define XSMC_ECC_MEMCMD2_RESET_VAL 0x01E00585U + +/**< DDR controller reset bit mask */ +#define XDDRPS_CTRL_RESET_MASK 0x00000001U +/**< SLCR OCM configuration reset value*/ +#define XSLCR_OCM_CFG_RESETVAL 0x00000008U +/**< SLCR OCM bank selection mask*/ +#define XSLCR_OCM_CFG_HIADDR_MASK 0x0000000FU +/**< SLCR level shifter enable mask*/ +#define XSLCR_LVL_SHFTR_EN_MASK 0x0000000FU + +/**< SLCR PLL register reset values */ +#define XSLCR_ARM_PLL_CTRL_RESET_VAL 0x0001A008U +#define XSLCR_DDR_PLL_CTRL_RESET_VAL 0x0001A008U +#define XSLCR_IO_PLL_CTRL_RESET_VAL 0x0001A008U +#define XSLCR_ARM_PLL_CFG_RESET_VAL 0x00177EA0U +#define XSLCR_DDR_PLL_CFG_RESET_VAL 0x00177EA0U +#define XSLCR_IO_PLL_CFG_RESET_VAL 0x00177EA0U +#define XSLCR_ARM_CLK_CTRL_RESET_VAL 0x1F000400U +#define XSLCR_DDR_CLK_CTRL_RESET_VAL 0x18400003U + +/**< SLCR MIO register default values */ +#define XSLCR_MIO_PIN_00_RESET_VAL 0x00001601U +#define XSLCR_MIO_PIN_02_RESET_VAL 0x00000601U + +/**< SLCR Reset control registers default values */ +#define XSLCR_DMAC_RST_CTRL_VAL 0x00000001U +#define XSLCR_GEM_RST_CTRL_VAL 0x000000F3U +#define XSLCR_USB_RST_CTRL_VAL 0x00000003U +#define XSLCR_I2C_RST_CTRL_VAL 0x00000003U +#define XSLCR_SPI_RST_CTRL_VAL 0x0000000FU +#define XSLCR_UART_RST_CTRL_VAL 0x0000000FU +#define XSLCR_QSPI_RST_CTRL_VAL 0x00000003U +#define XSLCR_GPIO_RST_CTRL_VAL 0x00000001U +#define XSLCR_SMC_RST_CTRL_VAL 0x00000003U +#define XSLCR_OCM_RST_CTRL_VAL 0x00000001U +#define XSLCR_SDIO_RST_CTRL_VAL 0x00000033U +#define XSLCR_CAN_RST_CTRL_VAL 0x00000003U +/**************************** Type Definitions *******************************/ + +/* the following data type is used to hold a null terminated version string + * consisting of the following format, "X.YYX" + */ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ +/* + * Performs reset operation to the ddr interface + */ +void XDdr_ResetHw(void); +/* + * Map the ocm region to post bootrom state + */ +void XOcm_Remap(void); +/* + * Performs the smc interface reset + */ +void XSmc_ResetHw(u32 BaseAddress); +/* + * updates the MIO registers with reset values + */ +void XSlcr_MioWriteResetValues(void); +/* + * updates the PLL and clock registers with reset values + */ +void XSlcr_PllWriteResetValues(void); +/* + * Disables the level shifters + */ +void XSlcr_DisableLevelShifters(void); +/* + * provides softreset to the GPIO interface + */ +void XSlcr_GpioPsReset(void); +/* + * provides softreset to the DMA interface + */ +void XSlcr_DmaPsReset(void); +/* + * provides softreset to the SMC interface + */ +void XSlcr_SmcPsReset(void); +/* + * provides softreset to the CAN interface + */ +void XSlcr_CanPsReset(void); +/* + * provides softreset to the Uart interface + */ +void XSlcr_UartPsReset(void); +/* + * provides softreset to the I2C interface + */ +void XSlcr_I2cPsReset(void); +/* + * provides softreset to the SPI interface + */ +void XSlcr_SpiPsReset(void); +/* + * provides softreset to the QSPI interface + */ +void XSlcr_QspiPsReset(void); +/* + * provides softreset to the USB interface + */ +void XSlcr_UsbPsReset(void); +/* + * provides softreset to the GEM interface + */ +void XSlcr_EmacPsReset(void); +/* + * provides softreset to the OCM interface + */ +void XSlcr_OcmReset(void); + + +#ifdef __cplusplus +} +#endif + +#endif /* XIL_MISC_RESET_H */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/include/xil_mmu.h b/df_datalink/bsp/ps7_cortexa9_0/include/xil_mmu.h new file mode 100644 index 0000000..3b63c0b --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/include/xil_mmu.h @@ -0,0 +1,106 @@ +/****************************************************************************** +* +* Copyright (C) 2012 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file xil_mmu.h +* +* @addtogroup a9_mmu_apis Cortex A9 Processor MMU Functions +* +* MMU functions equip users to enable MMU, disable MMU and modify default +* memory attributes of MMU table as per the need. +* +* @{ +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- ---------------------------------------------------
+* 1.00a sdm  01/12/12 Initial version
+* 4.2	pkp	 07/21/14 Included xil_types.h file which contains definition for
+*					  u32 which resolves issue of CR#805869
+* 5.4	pkp	 23/11/15 Added attribute definitions for Xil_SetTlbAttributes API
+* 6.8   aru  09/06/18 Removed compilation warnings for ARMCC toolchain.
+* 
+* +* +******************************************************************************/ + +#ifndef XIL_MMU_H +#define XIL_MMU_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/***************************** Include Files *********************************/ + +#include "xil_types.h" + +/***************** Macros (Inline Functions) Definitions *********************/ + +/**************************** Type Definitions *******************************/ + +/************************** Constant Definitions *****************************/ + +/* Memory type */ +#define NORM_NONCACHE 0x11DE2 /* Normal Non-cacheable */ +#define STRONG_ORDERED 0xC02 /* Strongly ordered */ +#define DEVICE_MEMORY 0xC06 /* Device memory */ +#define RESERVED 0x0 /* reserved memory */ + +/* Normal write-through cacheable shareable */ +#define NORM_WT_CACHE 0x16DEA + +/* Normal write back cacheable shareable */ +#define NORM_WB_CACHE 0x15DE6 + +/* shareability attribute */ +#define SHAREABLE (0x1 << 16) +#define NON_SHAREABLE (~(0x1 << 16)) + +/* Execution type */ +#define EXECUTE_NEVER ((0x1 << 4) | (0x1 << 0)) + +/************************** Variable Definitions *****************************/ + +/************************** Function Prototypes ******************************/ + +void Xil_SetTlbAttributes(INTPTR Addr, u32 attrib); +void Xil_EnableMMU(void); +void Xil_DisableMMU(void); +void* Xil_MemMap(UINTPTR PhysAddr, size_t size, u32 flags); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* XIL_MMU_H */ +/** +* @} End of "addtogroup a9_mmu_apis". +*/ diff --git a/df_datalink/bsp/ps7_cortexa9_0/include/xil_printf.h b/df_datalink/bsp/ps7_cortexa9_0/include/xil_printf.h new file mode 100644 index 0000000..a0177fc --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/include/xil_printf.h @@ -0,0 +1,48 @@ + #ifndef XIL_PRINTF_H + #define XIL_PRINTF_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include "xil_types.h" +#include "xparameters.h" +#include "bspconfig.h" +#if defined (__aarch64__) && HYP_GUEST && EL1_NONSECURE && XEN_USE_PV_CONSOLE +#include "xen_console.h" +#endif + +/*----------------------------------------------------*/ +/* Use the following parameter passing structure to */ +/* make xil_printf re-entrant. */ +/*----------------------------------------------------*/ + +struct params_s; + + +/*---------------------------------------------------*/ +/* The purpose of this routine is to output data the */ +/* same as the standard printf function without the */ +/* overhead most run-time libraries involve. Usually */ +/* the printf brings in many kilobytes of code and */ +/* that is unacceptable in most embedded systems. */ +/*---------------------------------------------------*/ + +typedef char8* charptr; +typedef s32 (*func_ptr)(int c); + +/* */ + +void xil_printf( const char8 *ctrl1, ...); +void print( const char8 *ptr); +extern void outbyte (char8 c); +extern char8 inbyte(void); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/include/xil_sleeptimer.h b/df_datalink/bsp/ps7_cortexa9_0/include/xil_sleeptimer.h new file mode 100644 index 0000000..08f64ba --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/include/xil_sleeptimer.h @@ -0,0 +1,128 @@ +/****************************************************************************** +* +* Copyright (C) 2017 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_sleeptimer.h +* +* This header file contains ARM Cortex A53,A9,R5 specific sleep related APIs. +* For sleep related functions that can be used across all Xilinx supported +* processors, please use xil_sleeptimer.h. +* +* +*
+* MODIFICATION HISTORY :
+*
+* Ver   Who  Date	 Changes
+* ----- ---- -------- -------------------------------------------------------
+* 6.6	srm  10/18/17 First Release.
+* 7.0   mus  01/07/19 Add cpp extern macro
+*
+* 
+*****************************************************************************/ + +#ifndef XIL_SLEEPTIMER_H /* prevent circular inclusions */ +#define XIL_SLEEPTIMER_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/**************************** Include Files ********************************/ + +#include "xil_io.h" +#include "xparameters.h" +#include "bspconfig.h" + +/************************** Constant Definitions *****************************/ + +#if defined (ARMR5) || (__aarch64__) || (ARMA53_32) +#define XSLEEP_TIMER_REG_SHIFT 32U +#define XSleep_ReadCounterVal Xil_In32 +#define XCntrVal u32 +#else +#define XSLEEP_TIMER_REG_SHIFT 16U +#define XSleep_ReadCounterVal Xil_In16 +#define XCntrVal u16 +#endif + +#if defined(ARMR5) || (defined (__aarch64__) && EL3==1) || defined (ARMA53_32) +#if defined (versal) +#define CRL_TTC_RST 0xFF5E0344U +#define CRL_TTC_BASE_RST_MASK 0x1U +#else +#define RST_LPD_IOU2 0xFF5E0238U +#define RST_LPD_IOU2_TTC_BASE_RESET_MASK 0x00000800U +#endif +#endif + +#if defined (SLEEP_TIMER_BASEADDR) +/** @name Register Map +* +* Register offsets from the base address of the TTC device +* +* @{ +*/ + #define XSLEEP_TIMER_TTC_CLK_CNTRL_OFFSET 0x00000000U + /**< Clock Control Register */ + #define XSLEEP_TIMER_TTC_CNT_CNTRL_OFFSET 0x0000000CU + /**< Counter Control Register*/ + #define XSLEEP_TIMER_TTC_COUNT_VALUE_OFFSET 0x00000018U + /**< Current Counter Value */ +/* @} */ +/** @name Clock Control Register +* Clock Control Register definitions of TTC +* @{ +*/ + #define XSLEEP_TIMER_TTC_CLK_CNTRL_PS_EN_MASK 0x00000001U + /**< Prescale enable */ +/* @} */ +/** @name Counter Control Register +* Counter Control Register definitions of TTC +* @{ +*/ +#define XSLEEP_TIMER_TTC_CNT_CNTRL_DIS_MASK 0x00000001U + /**< Disable the counter */ +#define XSLEEP_TIMER_TTC_CNT_CNTRL_RST_MASK 0x00000010U + /**< Reset counter */ +/* @} */ + +/**************************** Type Definitions *******************************/ + +/************************** Function Prototypes ******************************/ + +void Xil_SleepTTCCommon(u32 delay, u64 frequency); +void XTime_StartTTCTimer(); + +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* XIL_SLEEPTIMER_H */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/include/xil_testcache.h b/df_datalink/bsp/ps7_cortexa9_0/include/xil_testcache.h new file mode 100644 index 0000000..8289ca9 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/include/xil_testcache.h @@ -0,0 +1,67 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_testcache.h +* +* @addtogroup common_test_utils +*

Cache test

+* The xil_testcache.h file contains utility functions to test cache. +* +* @{ +*
+* Ver    Who    Date    Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a hbm  07/29/09 First release
+* 
+* +******************************************************************************/ + +#ifndef XIL_TESTCACHE_H /* prevent circular inclusions */ +#define XIL_TESTCACHE_H /* by using protection macros */ + +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern s32 Xil_TestDCacheRange(void); +extern s32 Xil_TestDCacheAll(void); +extern s32 Xil_TestICacheRange(void); +extern s32 Xil_TestICacheAll(void); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** +* @} End of "addtogroup common_test_utils". +*/ \ No newline at end of file diff --git a/df_datalink/bsp/ps7_cortexa9_0/include/xil_testio.h b/df_datalink/bsp/ps7_cortexa9_0/include/xil_testio.h new file mode 100644 index 0000000..6f0fc1c --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/include/xil_testio.h @@ -0,0 +1,90 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_testio.h +* +* @addtogroup common_test_utils Test Utilities +*

I/O test

+* The xil_testio.h file contains utility functions to test endian related memory +* IO functions. +* +* A subset of the memory tests can be selected or all of the tests can be run +* in order. If there is an error detected by a subtest, the test stops and the +* failure code is returned. Further tests are not run even if all of the tests +* are selected. +* +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver    Who    Date    Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00 hbm  08/05/09 First release
+* 
+* +******************************************************************************/ + +#ifndef XIL_TESTIO_H /* prevent circular inclusions */ +#define XIL_TESTIO_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ +#include "xil_types.h" + +/************************** Constant Definitions *****************************/ + + +#define XIL_TESTIO_DEFAULT 0 +#define XIL_TESTIO_LE 1 +#define XIL_TESTIO_BE 2 + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + +extern s32 Xil_TestIO8(u8 *Addr, s32 Length, u8 Value); +extern s32 Xil_TestIO16(u16 *Addr, s32 Length, u16 Value, s32 Kind, s32 Swap); +extern s32 Xil_TestIO32(u32 *Addr, s32 Length, u32 Value, s32 Kind, s32 Swap); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** +* @} End of "addtogroup common_test_utils". +*/ diff --git a/df_datalink/bsp/ps7_cortexa9_0/include/xil_testmem.h b/df_datalink/bsp/ps7_cortexa9_0/include/xil_testmem.h new file mode 100644 index 0000000..ecce6b7 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/include/xil_testmem.h @@ -0,0 +1,154 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_testmem.h +* @addtogroup common_test_utils +* +*

Memory test

+* +* The xil_testmem.h file contains utility functions to test memory. +* A subset of the memory tests can be selected or all of the tests can be run +* in order. If there is an error detected by a subtest, the test stops and the +* failure code is returned. Further tests are not run even if all of the tests +* are selected. +* Following list describes the supported memory tests: +* +* - XIL_TESTMEM_ALLMEMTESTS: This test runs all of the subtests. +* +* - XIL_TESTMEM_INCREMENT: This test +* starts at 'XIL_TESTMEM_INIT_VALUE' and uses the incrementing value as the +* test value for memory. +* +* - XIL_TESTMEM_WALKONES: Also known as the Walking ones test. This test +* uses a walking '1' as the test value for memory. +* @code +* location 1 = 0x00000001 +* location 2 = 0x00000002 +* ... +* @endcode +* +* - XIL_TESTMEM_WALKZEROS: Also known as the Walking zero's test. +* This test uses the inverse value of the walking ones test +* as the test value for memory. +* @code +* location 1 = 0xFFFFFFFE +* location 2 = 0xFFFFFFFD +* ... +*@endcode +* +* - XIL_TESTMEM_INVERSEADDR: Also known as the inverse address test. +* This test uses the inverse of the address of the location under test +* as the test value for memory. +* +* - XIL_TESTMEM_FIXEDPATTERN: Also known as the fixed pattern test. +* This test uses the provided patters as the test value for memory. +* If zero is provided as the pattern the test uses '0xDEADBEEF". +* +* @warning +* The tests are DESTRUCTIVE. Run before any initialized memory spaces +* have been set up. +* The address provided to the memory tests is not checked for +* validity except for the NULL case. It is possible to provide a code-space +* pointer for this test to start with and ultimately destroy executable code +* causing random failures. +* +* @note +* Used for spaces where the address range of the region is smaller than +* the data width. If the memory range is greater than 2 ** width, +* the patterns used in XIL_TESTMEM_WALKONES and XIL_TESTMEM_WALKZEROS will +* repeat on a boundry of a power of two making it more difficult to detect +* addressing errors. The XIL_TESTMEM_INCREMENT and XIL_TESTMEM_INVERSEADDR +* tests suffer the same problem. Ideally, if large blocks of memory are to be +* tested, break them up into smaller regions of memory to allow the test +* patterns used not to repeat over the region tested. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver    Who    Date    Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a hbm  08/25/09 First release
+* 
+* +******************************************************************************/ + +#ifndef XIL_TESTMEM_H /* prevent circular inclusions */ +#define XIL_TESTMEM_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ +#include "xil_types.h" + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + +/* xutil_memtest defines */ + +#define XIL_TESTMEM_INIT_VALUE 1U + +/** @name Memory subtests + * @{ + */ +/** + * See the detailed description of the subtests in the file description. + */ +#define XIL_TESTMEM_ALLMEMTESTS 0x00U +#define XIL_TESTMEM_INCREMENT 0x01U +#define XIL_TESTMEM_WALKONES 0x02U +#define XIL_TESTMEM_WALKZEROS 0x03U +#define XIL_TESTMEM_INVERSEADDR 0x04U +#define XIL_TESTMEM_FIXEDPATTERN 0x05U +#define XIL_TESTMEM_MAXTEST XIL_TESTMEM_FIXEDPATTERN +/* @} */ + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + +/* xutil_testmem prototypes */ + +extern s32 Xil_TestMem32(u32 *Addr, u32 Words, u32 Pattern, u8 Subtest); +extern s32 Xil_TestMem16(u16 *Addr, u32 Words, u16 Pattern, u8 Subtest); +extern s32 Xil_TestMem8(u8 *Addr, u32 Words, u8 Pattern, u8 Subtest); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** +* @} End of "addtogroup common_test_utils". +*/ diff --git a/df_datalink/bsp/ps7_cortexa9_0/include/xil_types.h b/df_datalink/bsp/ps7_cortexa9_0/include/xil_types.h new file mode 100644 index 0000000..625ff8c --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/include/xil_types.h @@ -0,0 +1,214 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_types.h +* +* @addtogroup common_types Basic Data types for Xilinx® Software IP +* +* The xil_types.h file contains basic types for Xilinx software IP. These data types +* are applicable for all processors supported by Xilinx. +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date   Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a hbm  07/14/09 First release
+* 3.03a sdm  05/30/11 Added Xuint64 typedef and XUINT64_MSW/XUINT64_LSW macros
+* 5.00 	pkp  05/29/14 Made changes for 64 bit architecture
+*	srt  07/14/14 Use standard definitions from stdint.h and stddef.h
+*		      Define LONG and ULONG datatypes and mask values
+* 7.00  mus  01/07/19 Add cpp extern macro
+* 
+* +******************************************************************************/ + +#ifndef XIL_TYPES_H /* prevent circular inclusions */ +#define XIL_TYPES_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +/************************** Constant Definitions *****************************/ + +#ifndef TRUE +# define TRUE 1U +#endif + +#ifndef FALSE +# define FALSE 0U +#endif + +#ifndef NULL +#define NULL 0U +#endif + +#define XIL_COMPONENT_IS_READY 0x11111111U /**< In device drivers, This macro will be + assigend to "IsReady" member of driver + instance to indicate that driver + instance is initialized and ready to use. */ +#define XIL_COMPONENT_IS_STARTED 0x22222222U /**< In device drivers, This macro will be assigend to + "IsStarted" member of driver instance + to indicate that driver instance is + started and it can be enabled. */ + +/* @name New types + * New simple types. + * @{ + */ +#ifndef __KERNEL__ +#ifndef XBASIC_TYPES_H +/* + * guarded against xbasic_types.h. + */ +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; +/** @}*/ +#define __XUINT64__ +typedef struct +{ + u32 Upper; + u32 Lower; +} Xuint64; + + +/*****************************************************************************/ +/** +* @brief Return the most significant half of the 64 bit data type. +* +* @param x is the 64 bit word. +* +* @return The upper 32 bits of the 64 bit word. +* +******************************************************************************/ +#define XUINT64_MSW(x) ((x).Upper) + +/*****************************************************************************/ +/** +* @brief Return the least significant half of the 64 bit data type. +* +* @param x is the 64 bit word. +* +* @return The lower 32 bits of the 64 bit word. +* +******************************************************************************/ +#define XUINT64_LSW(x) ((x).Lower) + +#endif /* XBASIC_TYPES_H */ + +/* + * xbasic_types.h does not typedef s* or u64 + */ +/** @{ */ +typedef char char8; +typedef int8_t s8; +typedef int16_t s16; +typedef int32_t s32; +typedef int64_t s64; +typedef uint64_t u64; +typedef int sint32; + +typedef intptr_t INTPTR; +typedef uintptr_t UINTPTR; +typedef ptrdiff_t PTRDIFF; +/** @}*/ +#if !defined(LONG) || !defined(ULONG) +typedef long LONG; +typedef unsigned long ULONG; +#endif + +#define ULONG64_HI_MASK 0xFFFFFFFF00000000U +#define ULONG64_LO_MASK ~ULONG64_HI_MASK + +#else +#include +#endif + +/** @{ */ +/** + * This data type defines an interrupt handler for a device. + * The argument points to the instance of the component + */ +typedef void (*XInterruptHandler) (void *InstancePtr); + +/** + * This data type defines an exception handler for a processor. + * The argument points to the instance of the component + */ +typedef void (*XExceptionHandler) (void *InstancePtr); + +/** + * @brief Returns 32-63 bits of a number. + * @param n : Number being accessed. + * @return Bits 32-63 of number. + * + * @note A basic shift-right of a 64- or 32-bit quantity. + * Use this to suppress the "right shift count >= width of type" + * warning when that quantity is 32-bits. + */ +#define UPPER_32_BITS(n) ((u32)(((n) >> 16) >> 16)) + +/** + * @brief Returns 0-31 bits of a number + * @param n : Number being accessed. + * @return Bits 0-31 of number + */ +#define LOWER_32_BITS(n) ((u32)(n)) + + + + +/************************** Constant Definitions *****************************/ + +#ifndef TRUE +#define TRUE 1U +#endif + +#ifndef FALSE +#define FALSE 0U +#endif + +#ifndef NULL +#define NULL 0U +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** +* @} End of "addtogroup common_types". +*/ diff --git a/df_datalink/bsp/ps7_cortexa9_0/include/xil_util.h b/df_datalink/bsp/ps7_cortexa9_0/include/xil_util.h new file mode 100644 index 0000000..194c425 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/include/xil_util.h @@ -0,0 +1,57 @@ +/******************************************************************************/ +/** +* Copyright (C) 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* @file xil_util.h +* +* This file contains xil utility functions declaration +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 6.4   mmd      04/21/19 First release.
+*
+* 
+* +*****************************************************************************/ + +#ifndef XIL_UTIL_H_ +#define XIL_UTIL_H_ + +/* Converts input character to nibble */ +u32 Xil_ConvertCharToNibble(u8 InChar, u8 *Num); + +/* Conver input hex string to array of 32-bits integers */ +u32 Xil_ConvertStringToHex(const char *Str, u32 *buf, u8 Len); + +/* Waits for specified event */ +u32 Xil_WaitForEvent(u32 RegAddr, u32 EventMask, u32 Event, u32 Timeout); + +#endif /* XIL_UTIL_H_ */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/include/xl2cc.h b/df_datalink/bsp/ps7_cortexa9_0/include/xl2cc.h new file mode 100644 index 0000000..22373c1 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/include/xl2cc.h @@ -0,0 +1,168 @@ +/****************************************************************************** +* +* Copyright (C) 2011 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file xl2cc.h +* +* This file contains the address definitions for the PL310 Level-2 Cache +* Controller. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- ---------------------------------------------------
+* 1.00a sdm  02/01/10 Initial version
+* 3.10a srt 04/18/13 Implemented ARM Erratas. Please refer to file
+*		      'xil_errata.h' for errata description
+* 
+* +* @note +* +* None. +* +******************************************************************************/ + +#ifndef _XL2CC_H_ +#define _XL2CC_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/************************** Constant Definitions *****************************/ +/* L2CC Register Offsets */ +#define XPS_L2CC_ID_OFFSET 0x0000U +#define XPS_L2CC_TYPE_OFFSET 0x0004U +#define XPS_L2CC_CNTRL_OFFSET 0x0100U +#define XPS_L2CC_AUX_CNTRL_OFFSET 0x0104U +#define XPS_L2CC_TAG_RAM_CNTRL_OFFSET 0x0108U +#define XPS_L2CC_DATA_RAM_CNTRL_OFFSET 0x010CU + +#define XPS_L2CC_EVNT_CNTRL_OFFSET 0x0200U +#define XPS_L2CC_EVNT_CNT1_CTRL_OFFSET 0x0204U +#define XPS_L2CC_EVNT_CNT0_CTRL_OFFSET 0x0208U +#define XPS_L2CC_EVNT_CNT1_VAL_OFFSET 0x020CU +#define XPS_L2CC_EVNT_CNT0_VAL_OFFSET 0x0210U + +#define XPS_L2CC_IER_OFFSET 0x0214U /* Interrupt Mask */ +#define XPS_L2CC_IPR_OFFSET 0x0218U /* Masked interrupt status */ +#define XPS_L2CC_ISR_OFFSET 0x021CU /* Raw Interrupt Status */ +#define XPS_L2CC_IAR_OFFSET 0x0220U /* Interrupt Clear */ + +#define XPS_L2CC_CACHE_SYNC_OFFSET 0x0730U /* Cache Sync */ +#define XPS_L2CC_DUMMY_CACHE_SYNC_OFFSET 0x0740U /* Dummy Register for Cache Sync */ +#define XPS_L2CC_CACHE_INVLD_PA_OFFSET 0x0770U /* Cache Invalid by PA */ +#define XPS_L2CC_CACHE_INVLD_WAY_OFFSET 0x077CU /* Cache Invalid by Way */ +#define XPS_L2CC_CACHE_CLEAN_PA_OFFSET 0x07B0U /* Cache Clean by PA */ +#define XPS_L2CC_CACHE_CLEAN_INDX_OFFSET 0x07B8U /* Cache Clean by Index */ +#define XPS_L2CC_CACHE_CLEAN_WAY_OFFSET 0x07BCU /* Cache Clean by Way */ +#define XPS_L2CC_CACHE_INV_CLN_PA_OFFSET 0x07F0U /* Cache Invalidate and Clean by PA */ +#define XPS_L2CC_CACHE_INV_CLN_INDX_OFFSET 0x07F8U /* Cache Invalidate and Clean by Index */ +#define XPS_L2CC_CACHE_INV_CLN_WAY_OFFSET 0x07FCU /* Cache Invalidate and Clean by Way */ + +#define XPS_L2CC_CACHE_DLCKDWN_0_WAY_OFFSET 0x0900U /* Cache Data Lockdown 0 by Way */ +#define XPS_L2CC_CACHE_ILCKDWN_0_WAY_OFFSET 0x0904U /* Cache Instruction Lockdown 0 by Way */ +#define XPS_L2CC_CACHE_DLCKDWN_1_WAY_OFFSET 0x0908U /* Cache Data Lockdown 1 by Way */ +#define XPS_L2CC_CACHE_ILCKDWN_1_WAY_OFFSET 0x090CU /* Cache Instruction Lockdown 1 by Way */ +#define XPS_L2CC_CACHE_DLCKDWN_2_WAY_OFFSET 0x0910U /* Cache Data Lockdown 2 by Way */ +#define XPS_L2CC_CACHE_ILCKDWN_2_WAY_OFFSET 0x0914U /* Cache Instruction Lockdown 2 by Way */ +#define XPS_L2CC_CACHE_DLCKDWN_3_WAY_OFFSET 0x0918U /* Cache Data Lockdown 3 by Way */ +#define XPS_L2CC_CACHE_ILCKDWN_3_WAY_OFFSET 0x091CU /* Cache Instruction Lockdown 3 by Way */ +#define XPS_L2CC_CACHE_DLCKDWN_4_WAY_OFFSET 0x0920U /* Cache Data Lockdown 4 by Way */ +#define XPS_L2CC_CACHE_ILCKDWN_4_WAY_OFFSET 0x0924U /* Cache Instruction Lockdown 4 by Way */ +#define XPS_L2CC_CACHE_DLCKDWN_5_WAY_OFFSET 0x0928U /* Cache Data Lockdown 5 by Way */ +#define XPS_L2CC_CACHE_ILCKDWN_5_WAY_OFFSET 0x092CU /* Cache Instruction Lockdown 5 by Way */ +#define XPS_L2CC_CACHE_DLCKDWN_6_WAY_OFFSET 0x0930U /* Cache Data Lockdown 6 by Way */ +#define XPS_L2CC_CACHE_ILCKDWN_6_WAY_OFFSET 0x0934U /* Cache Instruction Lockdown 6 by Way */ +#define XPS_L2CC_CACHE_DLCKDWN_7_WAY_OFFSET 0x0938U /* Cache Data Lockdown 7 by Way */ +#define XPS_L2CC_CACHE_ILCKDWN_7_WAY_OFFSET 0x093CU /* Cache Instruction Lockdown 7 by Way */ + +#define XPS_L2CC_CACHE_LCKDWN_LINE_ENABLE_OFFSET 0x0950U /* Cache Lockdown Line Enable */ +#define XPS_L2CC_CACHE_UUNLOCK_ALL_WAY_OFFSET 0x0954U /* Cache Unlock All Lines by Way */ + +#define XPS_L2CC_ADDR_FILTER_START_OFFSET 0x0C00U /* Start of address filtering */ +#define XPS_L2CC_ADDR_FILTER_END_OFFSET 0x0C04U /* Start of address filtering */ + +#define XPS_L2CC_DEBUG_CTRL_OFFSET 0x0F40U /* Debug Control Register */ + +/* XPS_L2CC_CNTRL_OFFSET bit masks */ +#define XPS_L2CC_ENABLE_MASK 0x00000001U /* enables the L2CC */ + +/* XPS_L2CC_AUX_CNTRL_OFFSET bit masks */ +#define XPS_L2CC_AUX_EBRESPE_MASK 0x40000000U /* Early BRESP Enable */ +#define XPS_L2CC_AUX_IPFE_MASK 0x20000000U /* Instruction Prefetch Enable */ +#define XPS_L2CC_AUX_DPFE_MASK 0x10000000U /* Data Prefetch Enable */ +#define XPS_L2CC_AUX_NSIC_MASK 0x08000000U /* Non-secure interrupt access control */ +#define XPS_L2CC_AUX_NSLE_MASK 0x04000000U /* Non-secure lockdown enable */ +#define XPS_L2CC_AUX_CRP_MASK 0x02000000U /* Cache replacement policy */ +#define XPS_L2CC_AUX_FWE_MASK 0x01800000U /* Force write allocate */ +#define XPS_L2CC_AUX_SAOE_MASK 0x00400000U /* Shared attribute override enable */ +#define XPS_L2CC_AUX_PE_MASK 0x00200000U /* Parity enable */ +#define XPS_L2CC_AUX_EMBE_MASK 0x00100000U /* Event monitor bus enable */ +#define XPS_L2CC_AUX_WAY_SIZE_MASK 0x000E0000U /* Way-size */ +#define XPS_L2CC_AUX_ASSOC_MASK 0x00010000U /* Associativity */ +#define XPS_L2CC_AUX_SAIE_MASK 0x00002000U /* Shared attribute invalidate enable */ +#define XPS_L2CC_AUX_EXCL_CACHE_MASK 0x00001000U /* Exclusive cache configuration */ +#define XPS_L2CC_AUX_SBDLE_MASK 0x00000800U /* Store buffer device limitation Enable */ +#define XPS_L2CC_AUX_HPSODRE_MASK 0x00000400U /* High Priority for SO and Dev Reads Enable */ +#define XPS_L2CC_AUX_FLZE_MASK 0x00000001U /* Full line of zero enable */ + +#define XPS_L2CC_AUX_REG_DEFAULT_MASK 0x72360000U /* Enable all prefetching, */ + /* Cache replacement policy, Parity enable, */ + /* Event monitor bus enable and Way Size (64 KB) */ +#define XPS_L2CC_AUX_REG_ZERO_MASK 0xFFF1FFFFU /* */ + +#define XPS_L2CC_TAG_RAM_DEFAULT_MASK 0x00000111U /* latency for TAG RAM */ +#define XPS_L2CC_DATA_RAM_DEFAULT_MASK 0x00000121U /* latency for DATA RAM */ + +/* Interrupt bit masks */ +#define XPS_L2CC_IXR_DECERR_MASK 0x00000100U /* DECERR from L3 */ +#define XPS_L2CC_IXR_SLVERR_MASK 0x00000080U /* SLVERR from L3 */ +#define XPS_L2CC_IXR_ERRRD_MASK 0x00000040U /* Error on L2 data RAM (Read) */ +#define XPS_L2CC_IXR_ERRRT_MASK 0x00000020U /* Error on L2 tag RAM (Read) */ +#define XPS_L2CC_IXR_ERRWD_MASK 0x00000010U /* Error on L2 data RAM (Write) */ +#define XPS_L2CC_IXR_ERRWT_MASK 0x00000008U /* Error on L2 tag RAM (Write) */ +#define XPS_L2CC_IXR_PARRD_MASK 0x00000004U /* Parity Error on L2 data RAM (Read) */ +#define XPS_L2CC_IXR_PARRT_MASK 0x00000002U /* Parity Error on L2 tag RAM (Read) */ +#define XPS_L2CC_IXR_ECNTR_MASK 0x00000001U /* Event Counter1/0 Overflow Increment */ + +/* Address filtering mask and enable bit */ +#define XPS_L2CC_ADDR_FILTER_VALID_MASK 0xFFF00000U /* Address filtering valid bits*/ +#define XPS_L2CC_ADDR_FILTER_ENABLE_MASK 0x00000001U /* Address filtering enable bit*/ + +/* Debug control bits */ +#define XPS_L2CC_DEBUG_SPIDEN_MASK 0x00000004U /* Debug SPIDEN bit */ +#define XPS_L2CC_DEBUG_DWB_MASK 0x00000002U /* Debug DWB bit, forces write through */ +#define XPS_L2CC_DEBUG_DCL_MASK 0x00000002U /* Debug DCL bit, disables cache line fill */ + +#ifdef __cplusplus +} +#endif + +#endif /* protection macro */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/include/xl2cc_counter.h b/df_datalink/bsp/ps7_cortexa9_0/include/xl2cc_counter.h new file mode 100644 index 0000000..b8d768f --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/include/xl2cc_counter.h @@ -0,0 +1,110 @@ +/****************************************************************************** +* +* Copyright (C) 2011 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xl2cc_counter.h +* +* @addtogroup l2_event_counter_apis PL310 L2 Event Counters Functions +* +* xl2cc_counter.h contains APIs for configuring and controlling the event +* counters in PL310 L2 cache controller. +* PL310 has two event counters which can be used to count variety of events +* like DRHIT, DRREQ, DWHIT, DWREQ, etc. xl2cc_counter.h contains definitions +* for different configurations which can be used for the event counters to +* count a set of events. +* +* +* @{ +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a sdm  07/11/11 First release
+* 3.07a asa  08/30/12 Updated for CR 675636 to provide the L2 Base Address
+*		      inside the APIs
+* 6.8   aru  09/06/18 Removed compilation warnings for ARMCC toolchain.
+* 
+* +******************************************************************************/ + +#ifndef L2CCCOUNTER_H /* prevent circular inclusions */ +#define L2CCCOUNTER_H /* by using protection macros */ + +/***************************** Include Files ********************************/ + +#include "xpseudo_asm.h" +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/************************** Constant Definitions ****************************/ + +/* + * The following constants define the event codes for the event counters. + */ +#define XL2CC_CO 0x1 +#define XL2CC_DRHIT 0x2 +#define XL2CC_DRREQ 0x3 +#define XL2CC_DWHIT 0x4 +#define XL2CC_DWREQ 0x5 +#define XL2CC_DWTREQ 0x6 +#define XL2CC_IRHIT 0x7 +#define XL2CC_IRREQ 0x8 +#define XL2CC_WA 0x9 +#define XL2CC_IPFALLOC 0xa +#define XL2CC_EPFHIT 0xb +#define XL2CC_EPFALLOC 0xc +#define XL2CC_SRRCVD 0xd +#define XL2CC_SRCONF 0xe +#define XL2CC_EPFRCVD 0xf + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Variable Definitions ****************************/ + +/************************** Function Prototypes *****************************/ + +void XL2cc_EventCtrInit(s32 Event0, s32 Event1); +void XL2cc_EventCtrStart(void); +void XL2cc_EventCtrStop(u32 *EveCtr0, u32 *EveCtr1); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* L2CCCOUNTER_H */ +/** +* @} End of "addtogroup l2_event_counter_apis". +*/ diff --git a/df_datalink/bsp/ps7_cortexa9_0/include/xparameters.h b/df_datalink/bsp/ps7_cortexa9_0/include/xparameters.h new file mode 100644 index 0000000..76605c7 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/include/xparameters.h @@ -0,0 +1,470 @@ +#ifndef XPARAMETERS_H /* prevent circular inclusions */ +#define XPARAMETERS_H /* by using protection macros */ + +/* Definition for CPU ID */ +#define XPAR_CPU_ID 0U + +/* Definitions for peripheral PS7_CORTEXA9_0 */ +#define XPAR_PS7_CORTEXA9_0_CPU_CLK_FREQ_HZ 666666687 + + +/******************************************************************/ + +/* Canonical definitions for peripheral PS7_CORTEXA9_0 */ +#define XPAR_CPU_CORTEXA9_0_CPU_CLK_FREQ_HZ 666666687 + + +/******************************************************************/ + + +/* Definitions for interface PHY */ +#define XPAR_PHY_BASEADDR 0x43C20000 +#define XPAR_PHY_HIGHADDR 0x43C20FFF + +#include "xparameters_ps.h" + +#define STDIN_BASEADDRESS 0xE0000000 +#define STDOUT_BASEADDRESS 0xE0000000 + +/******************************************************************/ + +/* Platform specific definitions */ +#define PLATFORM_ZYNQ + +/* Definitions for sleep timer configuration */ +#define XSLEEP_TIMER_IS_DEFAULT_TIMER + + +/******************************************************************/ +/* Definitions for driver BRAM */ +#define XPAR_XBRAM_NUM_INSTANCES 3U + +/* Definitions for peripheral PHY_DATA_INTERFACE_ANT_CONFIG_AXI_BRAM_CTRL */ +#define XPAR_PHY_DATA_INTERFACE_ANT_CONFIG_AXI_BRAM_CTRL_DEVICE_ID 0U +#define XPAR_PHY_DATA_INTERFACE_ANT_CONFIG_AXI_BRAM_CTRL_DATA_WIDTH 32U +#define XPAR_PHY_DATA_INTERFACE_ANT_CONFIG_AXI_BRAM_CTRL_ECC 0U +#define XPAR_PHY_DATA_INTERFACE_ANT_CONFIG_AXI_BRAM_CTRL_FAULT_INJECT 0U +#define XPAR_PHY_DATA_INTERFACE_ANT_CONFIG_AXI_BRAM_CTRL_CE_FAILING_REGISTERS 0U +#define XPAR_PHY_DATA_INTERFACE_ANT_CONFIG_AXI_BRAM_CTRL_UE_FAILING_REGISTERS 0U +#define XPAR_PHY_DATA_INTERFACE_ANT_CONFIG_AXI_BRAM_CTRL_ECC_STATUS_REGISTERS 0U +#define XPAR_PHY_DATA_INTERFACE_ANT_CONFIG_AXI_BRAM_CTRL_CE_COUNTER_WIDTH 0U +#define XPAR_PHY_DATA_INTERFACE_ANT_CONFIG_AXI_BRAM_CTRL_ECC_ONOFF_REGISTER 0U +#define XPAR_PHY_DATA_INTERFACE_ANT_CONFIG_AXI_BRAM_CTRL_ECC_ONOFF_RESET_VALUE 0U +#define XPAR_PHY_DATA_INTERFACE_ANT_CONFIG_AXI_BRAM_CTRL_WRITE_ACCESS 0U +#define XPAR_PHY_DATA_INTERFACE_ANT_CONFIG_AXI_BRAM_CTRL_S_AXI_BASEADDR 0x44000000U +#define XPAR_PHY_DATA_INTERFACE_ANT_CONFIG_AXI_BRAM_CTRL_S_AXI_HIGHADDR 0x44001FFFU +#define XPAR_PHY_DATA_INTERFACE_ANT_CONFIG_AXI_BRAM_CTRL_S_AXI_CTRL_BASEADDR 0xFFFFFFFFU +#define XPAR_PHY_DATA_INTERFACE_ANT_CONFIG_AXI_BRAM_CTRL_S_AXI_CTRL_HIGHADDR 0xFFFFFFFFU + + +/* Definitions for peripheral PHY_DATA_INTERFACE_PHY_RX_BUFF_AXI_BRAM_CTRL */ +#define XPAR_PHY_DATA_INTERFACE_PHY_RX_BUFF_AXI_BRAM_CTRL_DEVICE_ID 1U +#define XPAR_PHY_DATA_INTERFACE_PHY_RX_BUFF_AXI_BRAM_CTRL_DATA_WIDTH 32U +#define XPAR_PHY_DATA_INTERFACE_PHY_RX_BUFF_AXI_BRAM_CTRL_ECC 0U +#define XPAR_PHY_DATA_INTERFACE_PHY_RX_BUFF_AXI_BRAM_CTRL_FAULT_INJECT 0U +#define XPAR_PHY_DATA_INTERFACE_PHY_RX_BUFF_AXI_BRAM_CTRL_CE_FAILING_REGISTERS 0U +#define XPAR_PHY_DATA_INTERFACE_PHY_RX_BUFF_AXI_BRAM_CTRL_UE_FAILING_REGISTERS 0U +#define XPAR_PHY_DATA_INTERFACE_PHY_RX_BUFF_AXI_BRAM_CTRL_ECC_STATUS_REGISTERS 0U +#define XPAR_PHY_DATA_INTERFACE_PHY_RX_BUFF_AXI_BRAM_CTRL_CE_COUNTER_WIDTH 0U +#define XPAR_PHY_DATA_INTERFACE_PHY_RX_BUFF_AXI_BRAM_CTRL_ECC_ONOFF_REGISTER 0U +#define XPAR_PHY_DATA_INTERFACE_PHY_RX_BUFF_AXI_BRAM_CTRL_ECC_ONOFF_RESET_VALUE 0U +#define XPAR_PHY_DATA_INTERFACE_PHY_RX_BUFF_AXI_BRAM_CTRL_WRITE_ACCESS 0U +#define XPAR_PHY_DATA_INTERFACE_PHY_RX_BUFF_AXI_BRAM_CTRL_S_AXI_BASEADDR 0x40000000U +#define XPAR_PHY_DATA_INTERFACE_PHY_RX_BUFF_AXI_BRAM_CTRL_S_AXI_HIGHADDR 0x40000FFFU +#define XPAR_PHY_DATA_INTERFACE_PHY_RX_BUFF_AXI_BRAM_CTRL_S_AXI_CTRL_BASEADDR 0xFFFFFFFFU +#define XPAR_PHY_DATA_INTERFACE_PHY_RX_BUFF_AXI_BRAM_CTRL_S_AXI_CTRL_HIGHADDR 0xFFFFFFFFU + + +/* Definitions for peripheral PHY_DATA_INTERFACE_PHY_TX_BUFF_AXI_BRAM_CTRL */ +#define XPAR_PHY_DATA_INTERFACE_PHY_TX_BUFF_AXI_BRAM_CTRL_DEVICE_ID 2U +#define XPAR_PHY_DATA_INTERFACE_PHY_TX_BUFF_AXI_BRAM_CTRL_DATA_WIDTH 32U +#define XPAR_PHY_DATA_INTERFACE_PHY_TX_BUFF_AXI_BRAM_CTRL_ECC 0U +#define XPAR_PHY_DATA_INTERFACE_PHY_TX_BUFF_AXI_BRAM_CTRL_FAULT_INJECT 0U +#define XPAR_PHY_DATA_INTERFACE_PHY_TX_BUFF_AXI_BRAM_CTRL_CE_FAILING_REGISTERS 0U +#define XPAR_PHY_DATA_INTERFACE_PHY_TX_BUFF_AXI_BRAM_CTRL_UE_FAILING_REGISTERS 0U +#define XPAR_PHY_DATA_INTERFACE_PHY_TX_BUFF_AXI_BRAM_CTRL_ECC_STATUS_REGISTERS 0U +#define XPAR_PHY_DATA_INTERFACE_PHY_TX_BUFF_AXI_BRAM_CTRL_CE_COUNTER_WIDTH 0U +#define XPAR_PHY_DATA_INTERFACE_PHY_TX_BUFF_AXI_BRAM_CTRL_ECC_ONOFF_REGISTER 0U +#define XPAR_PHY_DATA_INTERFACE_PHY_TX_BUFF_AXI_BRAM_CTRL_ECC_ONOFF_RESET_VALUE 0U +#define XPAR_PHY_DATA_INTERFACE_PHY_TX_BUFF_AXI_BRAM_CTRL_WRITE_ACCESS 0U +#define XPAR_PHY_DATA_INTERFACE_PHY_TX_BUFF_AXI_BRAM_CTRL_S_AXI_BASEADDR 0x42000000U +#define XPAR_PHY_DATA_INTERFACE_PHY_TX_BUFF_AXI_BRAM_CTRL_S_AXI_HIGHADDR 0x42000FFFU +#define XPAR_PHY_DATA_INTERFACE_PHY_TX_BUFF_AXI_BRAM_CTRL_S_AXI_CTRL_BASEADDR 0xFFFFFFFFU +#define XPAR_PHY_DATA_INTERFACE_PHY_TX_BUFF_AXI_BRAM_CTRL_S_AXI_CTRL_HIGHADDR 0xFFFFFFFFU + + +/******************************************************************/ + +/* Canonical definitions for peripheral PHY_DATA_INTERFACE_ANT_CONFIG_AXI_BRAM_CTRL */ +#define XPAR_BRAM_0_DEVICE_ID XPAR_PHY_DATA_INTERFACE_ANT_CONFIG_AXI_BRAM_CTRL_DEVICE_ID +#define XPAR_BRAM_0_DATA_WIDTH 32U +#define XPAR_BRAM_0_ECC 0U +#define XPAR_BRAM_0_FAULT_INJECT 0U +#define XPAR_BRAM_0_CE_FAILING_REGISTERS 0U +#define XPAR_BRAM_0_UE_FAILING_REGISTERS 0U +#define XPAR_BRAM_0_ECC_STATUS_REGISTERS 0U +#define XPAR_BRAM_0_CE_COUNTER_WIDTH 0U +#define XPAR_BRAM_0_ECC_ONOFF_REGISTER 0U +#define XPAR_BRAM_0_ECC_ONOFF_RESET_VALUE 0U +#define XPAR_BRAM_0_WRITE_ACCESS 0U +#define XPAR_BRAM_0_BASEADDR 0x44000000U +#define XPAR_BRAM_0_HIGHADDR 0x44001FFFU +#define XPAR_BRAM_0_CTRL_BASEADDR 0xFFFFFFFFU +#define XPAR_BRAM_0_CTRL_HIGHADDR 0xFFFFFFFEU + +/* Canonical definitions for peripheral PHY_DATA_INTERFACE_PHY_RX_BUFF_AXI_BRAM_CTRL */ +#define XPAR_BRAM_1_DEVICE_ID XPAR_PHY_DATA_INTERFACE_PHY_RX_BUFF_AXI_BRAM_CTRL_DEVICE_ID +#define XPAR_BRAM_1_DATA_WIDTH 32U +#define XPAR_BRAM_1_ECC 0U +#define XPAR_BRAM_1_FAULT_INJECT 0U +#define XPAR_BRAM_1_CE_FAILING_REGISTERS 0U +#define XPAR_BRAM_1_UE_FAILING_REGISTERS 0U +#define XPAR_BRAM_1_ECC_STATUS_REGISTERS 0U +#define XPAR_BRAM_1_CE_COUNTER_WIDTH 0U +#define XPAR_BRAM_1_ECC_ONOFF_REGISTER 0U +#define XPAR_BRAM_1_ECC_ONOFF_RESET_VALUE 0U +#define XPAR_BRAM_1_WRITE_ACCESS 0U +#define XPAR_BRAM_1_BASEADDR 0x40000000U +#define XPAR_BRAM_1_HIGHADDR 0x40000FFFU +#define XPAR_BRAM_1_CTRL_BASEADDR 0xFFFFFFFFU +#define XPAR_BRAM_1_CTRL_HIGHADDR 0xFFFFFFFEU + +/* Canonical definitions for peripheral PHY_DATA_INTERFACE_PHY_TX_BUFF_AXI_BRAM_CTRL */ +#define XPAR_BRAM_2_DEVICE_ID XPAR_PHY_DATA_INTERFACE_PHY_TX_BUFF_AXI_BRAM_CTRL_DEVICE_ID +#define XPAR_BRAM_2_DATA_WIDTH 32U +#define XPAR_BRAM_2_ECC 0U +#define XPAR_BRAM_2_FAULT_INJECT 0U +#define XPAR_BRAM_2_CE_FAILING_REGISTERS 0U +#define XPAR_BRAM_2_UE_FAILING_REGISTERS 0U +#define XPAR_BRAM_2_ECC_STATUS_REGISTERS 0U +#define XPAR_BRAM_2_CE_COUNTER_WIDTH 0U +#define XPAR_BRAM_2_ECC_ONOFF_REGISTER 0U +#define XPAR_BRAM_2_ECC_ONOFF_RESET_VALUE 0U +#define XPAR_BRAM_2_WRITE_ACCESS 0U +#define XPAR_BRAM_2_BASEADDR 0x42000000U +#define XPAR_BRAM_2_HIGHADDR 0x42000FFFU +#define XPAR_BRAM_2_CTRL_BASEADDR 0xFFFFFFFFU +#define XPAR_BRAM_2_CTRL_HIGHADDR 0xFFFFFFFEU + + +/******************************************************************/ + + +/* Definitions for peripheral PS7_DDR_0 */ +#define XPAR_PS7_DDR_0_S_AXI_BASEADDR 0x00100000 +#define XPAR_PS7_DDR_0_S_AXI_HIGHADDR 0x1FFFFFFF + + +/******************************************************************/ + +/* Definitions for driver DEVCFG */ +#define XPAR_XDCFG_NUM_INSTANCES 1U + +/* Definitions for peripheral PS7_DEV_CFG_0 */ +#define XPAR_PS7_DEV_CFG_0_DEVICE_ID 0U +#define XPAR_PS7_DEV_CFG_0_BASEADDR 0xF8007000U +#define XPAR_PS7_DEV_CFG_0_HIGHADDR 0xF80070FFU + + +/******************************************************************/ + +/* Canonical definitions for peripheral PS7_DEV_CFG_0 */ +#define XPAR_XDCFG_0_DEVICE_ID XPAR_PS7_DEV_CFG_0_DEVICE_ID +#define XPAR_XDCFG_0_BASEADDR 0xF8007000U +#define XPAR_XDCFG_0_HIGHADDR 0xF80070FFU + + +/******************************************************************/ + +/* Definitions for driver DMAPS */ +#define XPAR_XDMAPS_NUM_INSTANCES 2 + +/* Definitions for peripheral PS7_DMA_NS */ +#define XPAR_PS7_DMA_NS_DEVICE_ID 0 +#define XPAR_PS7_DMA_NS_BASEADDR 0xF8004000 +#define XPAR_PS7_DMA_NS_HIGHADDR 0xF8004FFF + + +/* Definitions for peripheral PS7_DMA_S */ +#define XPAR_PS7_DMA_S_DEVICE_ID 1 +#define XPAR_PS7_DMA_S_BASEADDR 0xF8003000 +#define XPAR_PS7_DMA_S_HIGHADDR 0xF8003FFF + + +/******************************************************************/ + +/* Canonical definitions for peripheral PS7_DMA_NS */ +#define XPAR_XDMAPS_0_DEVICE_ID XPAR_PS7_DMA_NS_DEVICE_ID +#define XPAR_XDMAPS_0_BASEADDR 0xF8004000 +#define XPAR_XDMAPS_0_HIGHADDR 0xF8004FFF + +/* Canonical definitions for peripheral PS7_DMA_S */ +#define XPAR_XDMAPS_1_DEVICE_ID XPAR_PS7_DMA_S_DEVICE_ID +#define XPAR_XDMAPS_1_BASEADDR 0xF8003000 +#define XPAR_XDMAPS_1_HIGHADDR 0xF8003FFF + + +/******************************************************************/ + + +/* Definitions for peripheral AXI_SPI_ENGINE_AXI_SPI_ENGINE */ +#define XPAR_AXI_SPI_ENGINE_AXI_SPI_ENGINE_BASEADDR 0x43C00000 +#define XPAR_AXI_SPI_ENGINE_AXI_SPI_ENGINE_HIGHADDR 0x43C0FFFF + + +/* Definitions for peripheral PS7_AFI_0 */ +#define XPAR_PS7_AFI_0_S_AXI_BASEADDR 0xF8008000 +#define XPAR_PS7_AFI_0_S_AXI_HIGHADDR 0xF8008FFF + + +/* Definitions for peripheral PS7_AFI_1 */ +#define XPAR_PS7_AFI_1_S_AXI_BASEADDR 0xF8009000 +#define XPAR_PS7_AFI_1_S_AXI_HIGHADDR 0xF8009FFF + + +/* Definitions for peripheral PS7_AFI_2 */ +#define XPAR_PS7_AFI_2_S_AXI_BASEADDR 0xF800A000 +#define XPAR_PS7_AFI_2_S_AXI_HIGHADDR 0xF800AFFF + + +/* Definitions for peripheral PS7_AFI_3 */ +#define XPAR_PS7_AFI_3_S_AXI_BASEADDR 0xF800B000 +#define XPAR_PS7_AFI_3_S_AXI_HIGHADDR 0xF800BFFF + + +/* Definitions for peripheral PS7_DDRC_0 */ +#define XPAR_PS7_DDRC_0_S_AXI_BASEADDR 0xF8006000 +#define XPAR_PS7_DDRC_0_S_AXI_HIGHADDR 0xF8006FFF + + +/* Definitions for peripheral PS7_GLOBALTIMER_0 */ +#define XPAR_PS7_GLOBALTIMER_0_S_AXI_BASEADDR 0xF8F00200 +#define XPAR_PS7_GLOBALTIMER_0_S_AXI_HIGHADDR 0xF8F002FF + + +/* Definitions for peripheral PS7_GPV_0 */ +#define XPAR_PS7_GPV_0_S_AXI_BASEADDR 0xF8900000 +#define XPAR_PS7_GPV_0_S_AXI_HIGHADDR 0xF89FFFFF + + +/* Definitions for peripheral PS7_INTC_DIST_0 */ +#define XPAR_PS7_INTC_DIST_0_S_AXI_BASEADDR 0xF8F01000 +#define XPAR_PS7_INTC_DIST_0_S_AXI_HIGHADDR 0xF8F01FFF + + +/* Definitions for peripheral PS7_IOP_BUS_CONFIG_0 */ +#define XPAR_PS7_IOP_BUS_CONFIG_0_S_AXI_BASEADDR 0xE0200000 +#define XPAR_PS7_IOP_BUS_CONFIG_0_S_AXI_HIGHADDR 0xE0200FFF + + +/* Definitions for peripheral PS7_L2CACHEC_0 */ +#define XPAR_PS7_L2CACHEC_0_S_AXI_BASEADDR 0xF8F02000 +#define XPAR_PS7_L2CACHEC_0_S_AXI_HIGHADDR 0xF8F02FFF + + +/* Definitions for peripheral PS7_OCMC_0 */ +#define XPAR_PS7_OCMC_0_S_AXI_BASEADDR 0xF800C000 +#define XPAR_PS7_OCMC_0_S_AXI_HIGHADDR 0xF800CFFF + + +/* Definitions for peripheral PS7_PL310_0 */ +#define XPAR_PS7_PL310_0_S_AXI_BASEADDR 0xF8F02000 +#define XPAR_PS7_PL310_0_S_AXI_HIGHADDR 0xF8F02FFF + + +/* Definitions for peripheral PS7_PMU_0 */ +#define XPAR_PS7_PMU_0_S_AXI_BASEADDR 0xF8891000 +#define XPAR_PS7_PMU_0_S_AXI_HIGHADDR 0xF8891FFF +#define XPAR_PS7_PMU_0_PMU1_S_AXI_BASEADDR 0xF8893000 +#define XPAR_PS7_PMU_0_PMU1_S_AXI_HIGHADDR 0xF8893FFF + + +/* Definitions for peripheral PS7_QSPI_LINEAR_0 */ +#define XPAR_PS7_QSPI_LINEAR_0_S_AXI_BASEADDR 0xFC000000 +#define XPAR_PS7_QSPI_LINEAR_0_S_AXI_HIGHADDR 0xFCFFFFFF + + +/* Definitions for peripheral PS7_RAM_0 */ +#define XPAR_PS7_RAM_0_S_AXI_BASEADDR 0x00000000 +#define XPAR_PS7_RAM_0_S_AXI_HIGHADDR 0x0003FFFF + + +/* Definitions for peripheral PS7_RAM_1 */ +#define XPAR_PS7_RAM_1_S_AXI_BASEADDR 0xFFFC0000 +#define XPAR_PS7_RAM_1_S_AXI_HIGHADDR 0xFFFFFFFF + + +/* Definitions for peripheral PS7_SCUC_0 */ +#define XPAR_PS7_SCUC_0_S_AXI_BASEADDR 0xF8F00000 +#define XPAR_PS7_SCUC_0_S_AXI_HIGHADDR 0xF8F000FC + + +/* Definitions for peripheral PS7_SLCR_0 */ +#define XPAR_PS7_SLCR_0_S_AXI_BASEADDR 0xF8000000 +#define XPAR_PS7_SLCR_0_S_AXI_HIGHADDR 0xF8000FFF + + +/* Definitions for peripheral SYSTEMBUS */ +#define XPAR_SYSTEMBUS_BASEADDR 0x43C10000 +#define XPAR_SYSTEMBUS_HIGHADDR 0x43C11FFF + + +/******************************************************************/ + +/* Definitions for driver GPIOPS */ +#define XPAR_XGPIOPS_NUM_INSTANCES 1 + +/* Definitions for peripheral PS7_GPIO_0 */ +#define XPAR_PS7_GPIO_0_DEVICE_ID 0 +#define XPAR_PS7_GPIO_0_BASEADDR 0xE000A000 +#define XPAR_PS7_GPIO_0_HIGHADDR 0xE000AFFF + + +/******************************************************************/ + +/* Canonical definitions for peripheral PS7_GPIO_0 */ +#define XPAR_XGPIOPS_0_DEVICE_ID XPAR_PS7_GPIO_0_DEVICE_ID +#define XPAR_XGPIOPS_0_BASEADDR 0xE000A000 +#define XPAR_XGPIOPS_0_HIGHADDR 0xE000AFFF + + +/******************************************************************/ + +/* Definitions for driver QSPIPS */ +#define XPAR_XQSPIPS_NUM_INSTANCES 1 + +/* Definitions for peripheral PS7_QSPI_0 */ +#define XPAR_PS7_QSPI_0_DEVICE_ID 0 +#define XPAR_PS7_QSPI_0_BASEADDR 0xE000D000 +#define XPAR_PS7_QSPI_0_HIGHADDR 0xE000DFFF +#define XPAR_PS7_QSPI_0_QSPI_CLK_FREQ_HZ 200000000 +#define XPAR_PS7_QSPI_0_QSPI_MODE 0 +#define XPAR_PS7_QSPI_0_QSPI_BUS_WIDTH 2 + + +/******************************************************************/ + +/* Canonical definitions for peripheral PS7_QSPI_0 */ +#define XPAR_XQSPIPS_0_DEVICE_ID XPAR_PS7_QSPI_0_DEVICE_ID +#define XPAR_XQSPIPS_0_BASEADDR 0xE000D000 +#define XPAR_XQSPIPS_0_HIGHADDR 0xE000DFFF +#define XPAR_XQSPIPS_0_QSPI_CLK_FREQ_HZ 200000000 +#define XPAR_XQSPIPS_0_QSPI_MODE 0 +#define XPAR_XQSPIPS_0_QSPI_BUS_WIDTH 2 + + +/******************************************************************/ + +/* Definitions for Fabric interrupts connected to ps7_scugic_0 */ +#define XPAR_FABRIC_SYSTEMBUS_TX_DONE_INTR 62U +#define XPAR_FABRIC_SYSTEMBUS_RX_DONE_INTR 63U +#define XPAR_FABRIC_PHY_IRQ_INTR 64U + +/******************************************************************/ + +/* Canonical definitions for Fabric interrupts connected to ps7_scugic_0 */ + +/******************************************************************/ + +/* Definitions for driver SCUGIC */ +#define XPAR_XSCUGIC_NUM_INSTANCES 1U + +/* Definitions for peripheral PS7_SCUGIC_0 */ +#define XPAR_PS7_SCUGIC_0_DEVICE_ID 0U +#define XPAR_PS7_SCUGIC_0_BASEADDR 0xF8F00100U +#define XPAR_PS7_SCUGIC_0_HIGHADDR 0xF8F001FFU +#define XPAR_PS7_SCUGIC_0_DIST_BASEADDR 0xF8F01000U + + +/******************************************************************/ + +/* Canonical definitions for peripheral PS7_SCUGIC_0 */ +#define XPAR_SCUGIC_0_DEVICE_ID 0U +#define XPAR_SCUGIC_0_CPU_BASEADDR 0xF8F00100U +#define XPAR_SCUGIC_0_CPU_HIGHADDR 0xF8F001FFU +#define XPAR_SCUGIC_0_DIST_BASEADDR 0xF8F01000U + + +/******************************************************************/ + +/* Definitions for driver SCUTIMER */ +#define XPAR_XSCUTIMER_NUM_INSTANCES 1 + +/* Definitions for peripheral PS7_SCUTIMER_0 */ +#define XPAR_PS7_SCUTIMER_0_DEVICE_ID 0 +#define XPAR_PS7_SCUTIMER_0_BASEADDR 0xF8F00600 +#define XPAR_PS7_SCUTIMER_0_HIGHADDR 0xF8F0061F + + +/******************************************************************/ + +/* Canonical definitions for peripheral PS7_SCUTIMER_0 */ +#define XPAR_XSCUTIMER_0_DEVICE_ID XPAR_PS7_SCUTIMER_0_DEVICE_ID +#define XPAR_XSCUTIMER_0_BASEADDR 0xF8F00600 +#define XPAR_XSCUTIMER_0_HIGHADDR 0xF8F0061F + + +/******************************************************************/ + +/* Definitions for driver SCUWDT */ +#define XPAR_XSCUWDT_NUM_INSTANCES 1 + +/* Definitions for peripheral PS7_SCUWDT_0 */ +#define XPAR_PS7_SCUWDT_0_DEVICE_ID 0 +#define XPAR_PS7_SCUWDT_0_BASEADDR 0xF8F00620 +#define XPAR_PS7_SCUWDT_0_HIGHADDR 0xF8F006FF + + +/******************************************************************/ + +/* Canonical definitions for peripheral PS7_SCUWDT_0 */ +#define XPAR_SCUWDT_0_DEVICE_ID XPAR_PS7_SCUWDT_0_DEVICE_ID +#define XPAR_SCUWDT_0_BASEADDR 0xF8F00620 +#define XPAR_SCUWDT_0_HIGHADDR 0xF8F006FF + + +/******************************************************************/ + +/* Definitions for driver UARTPS */ +#define XPAR_XUARTPS_NUM_INSTANCES 1 + +/* Definitions for peripheral PS7_UART_0 */ +#define XPAR_PS7_UART_0_DEVICE_ID 0 +#define XPAR_PS7_UART_0_BASEADDR 0xE0000000 +#define XPAR_PS7_UART_0_HIGHADDR 0xE0000FFF +#define XPAR_PS7_UART_0_UART_CLK_FREQ_HZ 100000000 +#define XPAR_PS7_UART_0_HAS_MODEM 0 + + +/******************************************************************/ + +/* Canonical definitions for peripheral PS7_UART_0 */ +#define XPAR_XUARTPS_0_DEVICE_ID XPAR_PS7_UART_0_DEVICE_ID +#define XPAR_XUARTPS_0_BASEADDR 0xE0000000 +#define XPAR_XUARTPS_0_HIGHADDR 0xE0000FFF +#define XPAR_XUARTPS_0_UART_CLK_FREQ_HZ 100000000 +#define XPAR_XUARTPS_0_HAS_MODEM 0 + + +/******************************************************************/ + +/* Definitions for driver XADCPS */ +#define XPAR_XADCPS_NUM_INSTANCES 1 + +/* Definitions for peripheral PS7_XADC_0 */ +#define XPAR_PS7_XADC_0_DEVICE_ID 0 +#define XPAR_PS7_XADC_0_BASEADDR 0xF8007100 +#define XPAR_PS7_XADC_0_HIGHADDR 0xF8007120 + + +/******************************************************************/ + +/* Canonical definitions for peripheral PS7_XADC_0 */ +#define XPAR_XADCPS_0_DEVICE_ID XPAR_PS7_XADC_0_DEVICE_ID +#define XPAR_XADCPS_0_BASEADDR 0xF8007100 +#define XPAR_XADCPS_0_HIGHADDR 0xF8007120 + + +/******************************************************************/ + +#endif /* end of protection macro */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/include/xparameters_ps.h b/df_datalink/bsp/ps7_cortexa9_0/include/xparameters_ps.h new file mode 100644 index 0000000..2a6a0e0 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/include/xparameters_ps.h @@ -0,0 +1,334 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2017 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file xparameters_ps.h +* +* This file contains the address definitions for the hard peripherals +* attached to the ARM Cortex A9 core. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who     Date     Changes
+* ----- ------- -------- ---------------------------------------------------
+* 1.00a ecm/sdm 02/01/10 Initial version
+* 3.04a sdm     02/02/12 Removed some of the defines as they are being generated through
+*                        driver tcl
+* 5.0	pkp		01/16/15 Added interrupt ID definition of ttc for TEST APP
+* 6.6   srm     10/18/17 Added ARMA9 macro to identify CortexA9
+*
+* 
+* +* @note +* +* None. +* +******************************************************************************/ + +#ifndef _XPARAMETERS_PS_H_ +#define _XPARAMETERS_PS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/**************************** Include Files *******************************/ + + +/************************** Constant Definitions *****************************/ + +/* + * This block contains constant declarations for the peripherals + * within the hardblock + */ + +/* Canonical definitions for DDR MEMORY */ +#define XPAR_DDR_MEM_BASEADDR 0x00000000U +#define XPAR_DDR_MEM_HIGHADDR 0x3FFFFFFFU + +/* Canonical definitions for Interrupts */ +#define XPAR_XUARTPS_0_INTR XPS_UART0_INT_ID +#define XPAR_XUARTPS_1_INTR XPS_UART1_INT_ID +#define XPAR_XUSBPS_0_INTR XPS_USB0_INT_ID +#define XPAR_XUSBPS_1_INTR XPS_USB1_INT_ID +#define XPAR_XIICPS_0_INTR XPS_I2C0_INT_ID +#define XPAR_XIICPS_1_INTR XPS_I2C1_INT_ID +#define XPAR_XSPIPS_0_INTR XPS_SPI0_INT_ID +#define XPAR_XSPIPS_1_INTR XPS_SPI1_INT_ID +#define XPAR_XCANPS_0_INTR XPS_CAN0_INT_ID +#define XPAR_XCANPS_1_INTR XPS_CAN1_INT_ID +#define XPAR_XGPIOPS_0_INTR XPS_GPIO_INT_ID +#define XPAR_XEMACPS_0_INTR XPS_GEM0_INT_ID +#define XPAR_XEMACPS_0_WAKE_INTR XPS_GEM0_WAKE_INT_ID +#define XPAR_XEMACPS_1_INTR XPS_GEM1_INT_ID +#define XPAR_XEMACPS_1_WAKE_INTR XPS_GEM1_WAKE_INT_ID +#define XPAR_XSDIOPS_0_INTR XPS_SDIO0_INT_ID +#define XPAR_XQSPIPS_0_INTR XPS_QSPI_INT_ID +#define XPAR_XSDIOPS_1_INTR XPS_SDIO1_INT_ID +#define XPAR_XWDTPS_0_INTR XPS_WDT_INT_ID +#define XPAR_XDCFG_0_INTR XPS_DVC_INT_ID +#define XPAR_SCUTIMER_INTR XPS_SCU_TMR_INT_ID +#define XPAR_SCUWDT_INTR XPS_SCU_WDT_INT_ID +#define XPAR_XTTCPS_0_INTR XPS_TTC0_0_INT_ID +#define XPAR_XTTCPS_1_INTR XPS_TTC0_1_INT_ID +#define XPAR_XTTCPS_2_INTR XPS_TTC0_2_INT_ID +#define XPAR_XTTCPS_3_INTR XPS_TTC1_0_INT_ID +#define XPAR_XTTCPS_4_INTR XPS_TTC1_1_INT_ID +#define XPAR_XTTCPS_5_INTR XPS_TTC1_2_INT_ID +#define XPAR_XDMAPS_0_FAULT_INTR XPS_DMA0_ABORT_INT_ID +#define XPAR_XDMAPS_0_DONE_INTR_0 XPS_DMA0_INT_ID +#define XPAR_XDMAPS_0_DONE_INTR_1 XPS_DMA1_INT_ID +#define XPAR_XDMAPS_0_DONE_INTR_2 XPS_DMA2_INT_ID +#define XPAR_XDMAPS_0_DONE_INTR_3 XPS_DMA3_INT_ID +#define XPAR_XDMAPS_0_DONE_INTR_4 XPS_DMA4_INT_ID +#define XPAR_XDMAPS_0_DONE_INTR_5 XPS_DMA5_INT_ID +#define XPAR_XDMAPS_0_DONE_INTR_6 XPS_DMA6_INT_ID +#define XPAR_XDMAPS_0_DONE_INTR_7 XPS_DMA7_INT_ID + + +#define XPAR_XQSPIPS_0_LINEAR_BASEADDR XPS_QSPI_LINEAR_BASEADDR +#define XPAR_XPARPORTPS_CTRL_BASEADDR XPS_PARPORT_CRTL_BASEADDR + + + +/* Canonical definitions for DMAC */ + + +/* Canonical definitions for WDT */ + +/* Canonical definitions for SLCR */ +#define XPAR_XSLCR_NUM_INSTANCES 1U +#define XPAR_XSLCR_0_DEVICE_ID 0U +#define XPAR_XSLCR_0_BASEADDR XPS_SYS_CTRL_BASEADDR + +/* Canonical definitions for SCU GIC */ +#define XPAR_SCUGIC_NUM_INSTANCES 1U +#define XPAR_SCUGIC_SINGLE_DEVICE_ID 0U +#define XPAR_SCUGIC_CPU_BASEADDR (XPS_SCU_PERIPH_BASE + 0x00000100U) +#define XPAR_SCUGIC_DIST_BASEADDR (XPS_SCU_PERIPH_BASE + 0x00001000U) +#define XPAR_SCUGIC_ACK_BEFORE 0U + +/* Canonical definitions for Global Timer */ +#define XPAR_GLOBAL_TMR_NUM_INSTANCES 1U +#define XPAR_GLOBAL_TMR_DEVICE_ID 0U +#define XPAR_GLOBAL_TMR_BASEADDR (XPS_SCU_PERIPH_BASE + 0x00000200U) +#define XPAR_GLOBAL_TMR_INTR XPS_GLOBAL_TMR_INT_ID + + +/* Xilinx Parallel Flash Library (XilFlash) User Settings */ +#define XPAR_AXI_EMC + + +#define XPAR_CPU_CORTEXA9_CORE_CLOCK_FREQ_HZ XPAR_CPU_CORTEXA9_0_CPU_CLK_FREQ_HZ + + +/* + * This block contains constant declarations for the peripherals + * within the hardblock. These have been put for bacwards compatibilty + */ + +#define XPS_PERIPHERAL_BASEADDR 0xE0000000U +#define XPS_UART0_BASEADDR 0xE0000000U +#define XPS_UART1_BASEADDR 0xE0001000U +#define XPS_USB0_BASEADDR 0xE0002000U +#define XPS_USB1_BASEADDR 0xE0003000U +#define XPS_I2C0_BASEADDR 0xE0004000U +#define XPS_I2C1_BASEADDR 0xE0005000U +#define XPS_SPI0_BASEADDR 0xE0006000U +#define XPS_SPI1_BASEADDR 0xE0007000U +#define XPS_CAN0_BASEADDR 0xE0008000U +#define XPS_CAN1_BASEADDR 0xE0009000U +#define XPS_GPIO_BASEADDR 0xE000A000U +#define XPS_GEM0_BASEADDR 0xE000B000U +#define XPS_GEM1_BASEADDR 0xE000C000U +#define XPS_QSPI_BASEADDR 0xE000D000U +#define XPS_PARPORT_CRTL_BASEADDR 0xE000E000U +#define XPS_SDIO0_BASEADDR 0xE0100000U +#define XPS_SDIO1_BASEADDR 0xE0101000U +#define XPS_IOU_BUS_CFG_BASEADDR 0xE0200000U +#define XPS_NAND_BASEADDR 0xE1000000U +#define XPS_PARPORT0_BASEADDR 0xE2000000U +#define XPS_PARPORT1_BASEADDR 0xE4000000U +#define XPS_QSPI_LINEAR_BASEADDR 0xFC000000U +#define XPS_SYS_CTRL_BASEADDR 0xF8000000U /* AKA SLCR */ +#define XPS_TTC0_BASEADDR 0xF8001000U +#define XPS_TTC1_BASEADDR 0xF8002000U +#define XPS_DMAC0_SEC_BASEADDR 0xF8003000U +#define XPS_DMAC0_NON_SEC_BASEADDR 0xF8004000U +#define XPS_WDT_BASEADDR 0xF8005000U +#define XPS_DDR_CTRL_BASEADDR 0xF8006000U +#define XPS_DEV_CFG_APB_BASEADDR 0xF8007000U +#define XPS_AFI0_BASEADDR 0xF8008000U +#define XPS_AFI1_BASEADDR 0xF8009000U +#define XPS_AFI2_BASEADDR 0xF800A000U +#define XPS_AFI3_BASEADDR 0xF800B000U +#define XPS_OCM_BASEADDR 0xF800C000U +#define XPS_EFUSE_BASEADDR 0xF800D000U +#define XPS_CORESIGHT_BASEADDR 0xF8800000U +#define XPS_TOP_BUS_CFG_BASEADDR 0xF8900000U +#define XPS_SCU_PERIPH_BASE 0xF8F00000U +#define XPS_L2CC_BASEADDR 0xF8F02000U +#define XPS_SAM_RAM_BASEADDR 0xFFFC0000U +#define XPS_FPGA_AXI_S0_BASEADDR 0x40000000U +#define XPS_FPGA_AXI_S1_BASEADDR 0x80000000U +#define XPS_IOU_S_SWITCH_BASEADDR 0xE0000000U +#define XPS_PERIPH_APB_BASEADDR 0xF8000000U + +/* Shared Peripheral Interrupts (SPI) */ +#define XPS_CORE_PARITY0_INT_ID 32U +#define XPS_CORE_PARITY1_INT_ID 33U +#define XPS_L2CC_INT_ID 34U +#define XPS_OCMINTR_INT_ID 35U +#define XPS_ECC_INT_ID 36U +#define XPS_PMU0_INT_ID 37U +#define XPS_PMU1_INT_ID 38U +#define XPS_SYSMON_INT_ID 39U +#define XPS_DVC_INT_ID 40U +#define XPS_WDT_INT_ID 41U +#define XPS_TTC0_0_INT_ID 42U +#define XPS_TTC0_1_INT_ID 43U +#define XPS_TTC0_2_INT_ID 44U +#define XPS_DMA0_ABORT_INT_ID 45U +#define XPS_DMA0_INT_ID 46U +#define XPS_DMA1_INT_ID 47U +#define XPS_DMA2_INT_ID 48U +#define XPS_DMA3_INT_ID 49U +#define XPS_SMC_INT_ID 50U +#define XPS_QSPI_INT_ID 51U +#define XPS_GPIO_INT_ID 52U +#define XPS_USB0_INT_ID 53U +#define XPS_GEM0_INT_ID 54U +#define XPS_GEM0_WAKE_INT_ID 55U +#define XPS_SDIO0_INT_ID 56U +#define XPS_I2C0_INT_ID 57U +#define XPS_SPI0_INT_ID 58U +#define XPS_UART0_INT_ID 59U +#define XPS_CAN0_INT_ID 60U +#define XPS_FPGA0_INT_ID 61U +#define XPS_FPGA1_INT_ID 62U +#define XPS_FPGA2_INT_ID 63U +#define XPS_FPGA3_INT_ID 64U +#define XPS_FPGA4_INT_ID 65U +#define XPS_FPGA5_INT_ID 66U +#define XPS_FPGA6_INT_ID 67U +#define XPS_FPGA7_INT_ID 68U +#define XPS_TTC1_0_INT_ID 69U +#define XPS_TTC1_1_INT_ID 70U +#define XPS_TTC1_2_INT_ID 71U +#define XPS_DMA4_INT_ID 72U +#define XPS_DMA5_INT_ID 73U +#define XPS_DMA6_INT_ID 74U +#define XPS_DMA7_INT_ID 75U +#define XPS_USB1_INT_ID 76U +#define XPS_GEM1_INT_ID 77U +#define XPS_GEM1_WAKE_INT_ID 78U +#define XPS_SDIO1_INT_ID 79U +#define XPS_I2C1_INT_ID 80U +#define XPS_SPI1_INT_ID 81U +#define XPS_UART1_INT_ID 82U +#define XPS_CAN1_INT_ID 83U +#define XPS_FPGA8_INT_ID 84U +#define XPS_FPGA9_INT_ID 85U +#define XPS_FPGA10_INT_ID 86U +#define XPS_FPGA11_INT_ID 87U +#define XPS_FPGA12_INT_ID 88U +#define XPS_FPGA13_INT_ID 89U +#define XPS_FPGA14_INT_ID 90U +#define XPS_FPGA15_INT_ID 91U + +/* Private Peripheral Interrupts (PPI) */ +#define XPS_GLOBAL_TMR_INT_ID 27U /* SCU Global Timer interrupt */ +#define XPS_FIQ_INT_ID 28U /* FIQ from FPGA fabric */ +#define XPS_SCU_TMR_INT_ID 29U /* SCU Private Timer interrupt */ +#define XPS_SCU_WDT_INT_ID 30U /* SCU Private WDT interrupt */ +#define XPS_IRQ_INT_ID 31U /* IRQ from FPGA fabric */ + + +/* REDEFINES for TEST APP */ +/* Definitions for UART */ +#define XPAR_PS7_UART_0_INTR XPS_UART0_INT_ID +#define XPAR_PS7_UART_1_INTR XPS_UART1_INT_ID +#define XPAR_PS7_USB_0_INTR XPS_USB0_INT_ID +#define XPAR_PS7_USB_1_INTR XPS_USB1_INT_ID +#define XPAR_PS7_I2C_0_INTR XPS_I2C0_INT_ID +#define XPAR_PS7_I2C_1_INTR XPS_I2C1_INT_ID +#define XPAR_PS7_SPI_0_INTR XPS_SPI0_INT_ID +#define XPAR_PS7_SPI_1_INTR XPS_SPI1_INT_ID +#define XPAR_PS7_CAN_0_INTR XPS_CAN0_INT_ID +#define XPAR_PS7_CAN_1_INTR XPS_CAN1_INT_ID +#define XPAR_PS7_GPIO_0_INTR XPS_GPIO_INT_ID +#define XPAR_PS7_ETHERNET_0_INTR XPS_GEM0_INT_ID +#define XPAR_PS7_ETHERNET_0_WAKE_INTR XPS_GEM0_WAKE_INT_ID +#define XPAR_PS7_ETHERNET_1_INTR XPS_GEM1_INT_ID +#define XPAR_PS7_ETHERNET_1_WAKE_INTR XPS_GEM1_WAKE_INT_ID +#define XPAR_PS7_QSPI_0_INTR XPS_QSPI_INT_ID +#define XPAR_PS7_WDT_0_INTR XPS_WDT_INT_ID +#define XPAR_PS7_SCUWDT_0_INTR XPS_SCU_WDT_INT_ID +#define XPAR_PS7_SCUTIMER_0_INTR XPS_SCU_TMR_INT_ID +#define XPAR_PS7_XADC_0_INTR XPS_SYSMON_INT_ID +#define XPAR_PS7_TTC_0_INTR XPS_TTC0_0_INT_ID +#define XPAR_PS7_TTC_1_INTR XPS_TTC0_1_INT_ID +#define XPAR_PS7_TTC_2_INTR XPS_TTC0_2_INT_ID +#define XPAR_PS7_TTC_3_INTR XPS_TTC1_0_INT_ID +#define XPAR_PS7_TTC_4_INTR XPS_TTC1_1_INT_ID +#define XPAR_PS7_TTC_5_INTR XPS_TTC1_2_INT_ID + +#define XPAR_XADCPS_INT_ID XPS_SYSMON_INT_ID + +/* For backwards compatibilty */ +#define XPAR_XUARTPS_0_CLOCK_HZ XPAR_XUARTPS_0_UART_CLK_FREQ_HZ +#define XPAR_XUARTPS_1_CLOCK_HZ XPAR_XUARTPS_1_UART_CLK_FREQ_HZ +#define XPAR_XTTCPS_0_CLOCK_HZ XPAR_XTTCPS_0_TTC_CLK_FREQ_HZ +#define XPAR_XTTCPS_1_CLOCK_HZ XPAR_XTTCPS_1_TTC_CLK_FREQ_HZ +#define XPAR_XTTCPS_2_CLOCK_HZ XPAR_XTTCPS_2_TTC_CLK_FREQ_HZ +#define XPAR_XTTCPS_3_CLOCK_HZ XPAR_XTTCPS_3_TTC_CLK_FREQ_HZ +#define XPAR_XTTCPS_4_CLOCK_HZ XPAR_XTTCPS_4_TTC_CLK_FREQ_HZ +#define XPAR_XTTCPS_5_CLOCK_HZ XPAR_XTTCPS_5_TTC_CLK_FREQ_HZ +#define XPAR_XIICPS_0_CLOCK_HZ XPAR_XIICPS_0_I2C_CLK_FREQ_HZ +#define XPAR_XIICPS_1_CLOCK_HZ XPAR_XIICPS_1_I2C_CLK_FREQ_HZ + +#define XPAR_XQSPIPS_0_CLOCK_HZ XPAR_XQSPIPS_0_QSPI_CLK_FREQ_HZ + +#ifdef XPAR_CPU_CORTEXA9_0_CPU_CLK_FREQ_HZ +#define XPAR_CPU_CORTEXA9_CORE_CLOCK_FREQ_HZ XPAR_CPU_CORTEXA9_0_CPU_CLK_FREQ_HZ +#endif + +#ifdef XPAR_CPU_CORTEXA9_1_CPU_CLK_FREQ_HZ +#define XPAR_CPU_CORTEXA9_CORE_CLOCK_FREQ_HZ XPAR_CPU_CORTEXA9_1_CPU_CLK_FREQ_HZ +#endif + +#define XPAR_SCUTIMER_DEVICE_ID 0U +#define XPAR_SCUWDT_DEVICE_ID 0U + + +#ifdef __cplusplus +} +#endif + +#endif /* protection macro */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/include/xplatform_info.h b/df_datalink/bsp/ps7_cortexa9_0/include/xplatform_info.h new file mode 100644 index 0000000..88851bb --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/include/xplatform_info.h @@ -0,0 +1,120 @@ +/****************************************************************************** +* +* Copyright (C) 2014 - 2017 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xplatform_info.h +* +* @addtogroup common_platform_info APIs to Get Platform Information +* +* The xplatform_info.h file contains definitions for various available Xilinx® +* platforms. Also, it contains prototype of APIs, which can be used to get the +* platform information. +* +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date    Changes
+* ----- ---- --------- -------------------------------------------------------
+* 6.4    ms   05/23/17 Added PSU_PMU macro to support XGetPSVersion_Info
+*                      function for PMUFW.
+* 
+* +******************************************************************************/ + +#ifndef XPLATFORM_INFO_H /* prevent circular inclusions */ +#define XPLATFORM_INFO_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" + +/************************** Constant Definitions *****************************/ +#if defined (versal) +#define XPAR_PMC_TAP_BASEADDR 0xF11A0000U +#define XPAR_PMC_TAP_VERSION_OFFSET 0x00000004U +#define XPLAT_PS_VERSION_ADDRESS (XPAR_PMC_TAP_BASEADDR + \ + XPAR_PMC_TAP_VERSION_OFFSET) +#else +#define XPAR_CSU_BASEADDR 0xFFCA0000U +#define XPAR_CSU_VER_OFFSET 0x00000044U +#define XPLAT_PS_VERSION_ADDRESS (XPAR_CSU_BASEADDR + \ + XPAR_CSU_VER_OFFSET) +#endif +#define XPLAT_ZYNQ_ULTRA_MP_SILICON 0x0 +#define XPLAT_ZYNQ_ULTRA_MP 0x1 +#define XPLAT_ZYNQ_ULTRA_MPVEL 0x2 +#define XPLAT_ZYNQ_ULTRA_MPQEMU 0x3 +#define XPLAT_ZYNQ 0x4 +#define XPLAT_MICROBLAZE 0x5 +#define XPLAT_versal 0x6U + +#define XPS_VERSION_1 0x0 +#define XPS_VERSION_2 0x1 +#define XPLAT_INFO_MASK (0xF) + +#if defined (versal) +#define XPS_VERSION_INFO_MASK 0xFF00U +#define XPS_VERSION_INFO_SHIFT 0x8U +#define XPLAT_INFO_SHIFT 0x18U +#else +#define XPS_VERSION_INFO_MASK (0xF) +#define XPS_VERSION_INFO_SHIFT 0x0U +#define XPLAT_INFO_SHIFT 0xCU +#endif + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + + +u32 XGetPlatform_Info(void); + +#if defined (ARMR5) || (__aarch64__) || (ARMA53_32) || (PSU_PMU) +u32 XGetPSVersion_Info(); +#endif + +#if defined (ARMR5) || (__aarch64__) || (ARMA53_32) +u32 XGet_Zynq_UltraMp_Platform_info(); +#endif +/************************** Function Prototypes ******************************/ + + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** +* @} End of "addtogroup common_platform_info". +*/ diff --git a/df_datalink/bsp/ps7_cortexa9_0/include/xpm_counter.h b/df_datalink/bsp/ps7_cortexa9_0/include/xpm_counter.h new file mode 100644 index 0000000..39db7d8 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/include/xpm_counter.h @@ -0,0 +1,572 @@ +/****************************************************************************** +* +* Copyright (C) 2011 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xpm_counter.h +* +* @addtogroup a9_event_counter_apis Cortex A9 Event Counters Functions +* +* Cortex A9 event counter functions can be utilized to configure and control +* the Cortex-A9 performance monitor events. +* +* Cortex-A9 performance monitor has six event counters which can be used to +* count a variety of events described in Coretx-A9 TRM. xpm_counter.h defines +* configurations XPM_CNTRCFGx which can be used to program the event counters +* to count a set of events. +* +* @note +* It doesn't handle the Cortex-A9 cycle counter, as the cycle counter is +* being used for time keeping. +* +* @{ +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a sdm  07/11/11 First release
+* 6.8   aru  09/06/18 Removed compilation warnings for ARMCC toolchain.
+* 
+* +******************************************************************************/ + +#ifndef XPMCOUNTER_H /* prevent circular inclusions */ +#define XPMCOUNTER_H /* by using protection macros */ + +/***************************** Include Files ********************************/ + +#include +#include "xpseudo_asm.h" +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/************************** Constant Definitions ****************************/ + +/* Number of performance counters */ +#define XPM_CTRCOUNT 6U + +/* The following constants define the Cortex-A9 Performance Monitor Events */ + +/* + * Software increment. The register is incremented only on writes to the + * Software Increment Register + */ +#define XPM_EVENT_SOFTINCR 0x00U + +/* + * Instruction fetch that causes a refill at (at least) the lowest level(s) of + * instruction or unified cache. Includes the speculative linefills in the + * count + */ +#define XPM_EVENT_INSRFETCH_CACHEREFILL 0x01U + +/* + * Instruction fetch that causes a TLB refill at (at least) the lowest level of + * TLB. Includes the speculative requests in the count + */ +#define XPM_EVENT_INSTRFECT_TLBREFILL 0x02U + +/* + * Data read or write operation that causes a refill at (at least) the lowest + * level(s)of data or unified cache. Counts the number of allocations performed + * in the Data Cache due to a read or a write + */ +#define XPM_EVENT_DATA_CACHEREFILL 0x03U + +/* + * Data read or write operation that causes a cache access at (at least) the + * lowest level(s) of data or unified cache. This includes speculative reads + */ +#define XPM_EVENT_DATA_CACHEACCESS 0x04U + +/* + * Data read or write operation that causes a TLB refill at (at least) the + * lowest level of TLB. This does not include micro TLB misses due to PLD, PLI, + * CP15 Cache operation by MVA and CP15 VA to PA operations + */ +#define XPM_EVENT_DATA_TLBREFILL 0x05U + +/* + * Data read architecturally executed. Counts the number of data read + * instructions accepted by the Load Store Unit. This includes counting the + * speculative and aborted LDR/LDM, as well as the reads due to the SWP + * instructions + */ +#define XPM_EVENT_DATA_READS 0x06U + +/* + * Data write architecturally executed. Counts the number of data write + * instructions accepted by the Load Store Unit. This includes counting the + * speculative and aborted STR/STM, as well as the writes due to the SWP + * instructions + */ +#define XPM_EVENT_DATA_WRITE 0x07U + +/* Exception taken. Counts the number of exceptions architecturally taken.*/ +#define XPM_EVENT_EXCEPTION 0x09U + +/* Exception return architecturally executed.*/ +#define XPM_EVENT_EXCEPRETURN 0x0AU + +/* + * Change to ContextID retired. Counts the number of instructions + * architecturally executed writing into the ContextID Register + */ +#define XPM_EVENT_CHANGECONTEXT 0x0BU + +/* + * Software change of PC, except by an exception, architecturally executed. + * Count the number of PC changes architecturally executed, excluding the PC + * changes due to taken exceptions + */ +#define XPM_EVENT_SW_CHANGEPC 0x0CU + +/* + * Immediate branch architecturally executed (taken or not taken). This includes + * the branches which are flushed due to a previous load/store which aborts + * late + */ +#define XPM_EVENT_IMMEDBRANCH 0x0DU + +/* + * Unaligned access architecturally executed. Counts the number of aborted + * unaligned accessed architecturally executed, and the number of not-aborted + * unaligned accesses, including the speculative ones + */ +#define XPM_EVENT_UNALIGNEDACCESS 0x0FU + +/* + * Branch mispredicted/not predicted. Counts the number of mispredicted or + * not-predicted branches executed. This includes the branches which are flushed + * due to a previous load/store which aborts late + */ +#define XPM_EVENT_BRANCHMISS 0x10U + +/* + * Counts clock cycles when the Cortex-A9 processor is not in WFE/WFI. This + * event is not exported on the PMUEVENT bus + */ +#define XPM_EVENT_CLOCKCYCLES 0x11U + +/* + * Branches or other change in program flow that could have been predicted by + * the branch prediction resources of the processor. This includes the branches + * which are flushed due to a previous load/store which aborts late + */ +#define XPM_EVENT_BRANCHPREDICT 0x12U + +/* + * Java bytecode execute. Counts the number of Java bytecodes being decoded, + * including speculative ones + */ +#define XPM_EVENT_JAVABYTECODE 0x40U + +/* + * Software Java bytecode executed. Counts the number of software java bytecodes + * being decoded, including speculative ones + */ +#define XPM_EVENT_SWJAVABYTECODE 0x41U + +/* + * Jazelle backward branches executed. Counts the number of Jazelle taken + * branches being executed. This includes the branches which are flushed due + * to a previous load/store which aborts late + */ +#define XPM_EVENT_JAVABACKBRANCH 0x42U + +/* + * Coherent linefill miss Counts the number of coherent linefill requests + * performed by the Cortex-A9 processor which also miss in all the other + * Cortex-A9 processors, meaning that the request is sent to the external + * memory + */ +#define XPM_EVENT_COHERLINEMISS 0x50U + +/* + * Coherent linefill hit. Counts the number of coherent linefill requests + * performed by the Cortex-A9 processor which hit in another Cortex-A9 + * processor, meaning that the linefill data is fetched directly from the + * relevant Cortex-A9 cache + */ +#define XPM_EVENT_COHERLINEHIT 0x51U + +/* + * Instruction cache dependent stall cycles. Counts the number of cycles where + * the processor is ready to accept new instructions, but does not receive any + * due to the instruction side not being able to provide any and the + * instruction cache is currently performing at least one linefill + */ +#define XPM_EVENT_INSTRSTALL 0x60U + +/* + * Data cache dependent stall cycles. Counts the number of cycles where the core + * has some instructions that it cannot issue to any pipeline, and the Load + * Store unit has at least one pending linefill request, and no pending + */ +#define XPM_EVENT_DATASTALL 0x61U + +/* + * Main TLB miss stall cycles. Counts the number of cycles where the processor + * is stalled waiting for the completion of translation table walks from the + * main TLB. The processor stalls can be due to the instruction side not being + * able to provide the instructions, or to the data side not being able to + * provide the necessary data, due to them waiting for the main TLB translation + * table walk to complete + */ +#define XPM_EVENT_MAINTLBSTALL 0x62U + +/* + * Counts the number of STREX instructions architecturally executed and + * passed + */ +#define XPM_EVENT_STREXPASS 0x63U + +/* + * Counts the number of STREX instructions architecturally executed and + * failed + */ +#define XPM_EVENT_STREXFAIL 0x64U + +/* + * Data eviction. Counts the number of eviction requests due to a linefill in + * the data cache + */ +#define XPM_EVENT_DATAEVICT 0x65U + +/* + * Counts the number of cycles where the issue stage does not dispatch any + * instruction because it is empty or cannot dispatch any instructions + */ +#define XPM_EVENT_NODISPATCH 0x66U + +/* + * Counts the number of cycles where the issue stage is empty + */ +#define XPM_EVENT_ISSUEEMPTY 0x67U + +/* + * Counts the number of instructions going through the Register Renaming stage. + * This number is an approximate number of the total number of instructions + * speculatively executed, and even more approximate of the total number of + * instructions architecturally executed. The approximation depends mainly on + * the branch misprediction rate. + * The renaming stage can handle two instructions in the same cycle so the event + * is two bits long: + * - b00 no instructions renamed + * - b01 one instruction renamed + * - b10 two instructions renamed + */ +#define XPM_EVENT_INSTRRENAME 0x68U + +/* + * Counts the number of procedure returns whose condition codes do not fail, + * excluding all returns from exception. This count includes procedure returns + * which are flushed due to a previous load/store which aborts late. + * Only the following instructions are reported: + * - BX R14 + * - MOV PC LR + * - POP {..,pc} + * - LDR pc,[sp],#offset + * The following instructions are not reported: + * - LDMIA R9!,{..,PC} (ThumbEE state only) + * - LDR PC,[R9],#offset (ThumbEE state only) + * - BX R0 (Rm != R14) + * - MOV PC,R0 (Rm != R14) + * - LDM SP,{...,PC} (writeback not specified) + * - LDR PC,[SP,#offset] (wrong addressing mode) + */ +#define XPM_EVENT_PREDICTFUNCRET 0x6EU + +/* + * Counts the number of instructions being executed in the main execution + * pipeline of the processor, the multiply pipeline and arithmetic logic unit + * pipeline. The counted instructions are still speculative + */ +#define XPM_EVENT_MAINEXEC 0x70U + +/* + * Counts the number of instructions being executed in the processor second + * execution pipeline (ALU). The counted instructions are still speculative + */ +#define XPM_EVENT_SECEXEC 0x71U + +/* + * Counts the number of instructions being executed in the Load/Store unit. The + * counted instructions are still speculative + */ +#define XPM_EVENT_LDRSTR 0x72U + +/* + * Counts the number of Floating-point instructions going through the Register + * Rename stage. Instructions are still speculative in this stage. + *Two floating-point instructions can be renamed in the same cycle so the event + * is two bitslong: + *0b00 no floating-point instruction renamed + *0b01 one floating-point instruction renamed + *0b10 two floating-point instructions renamed + */ +#define XPM_EVENT_FLOATRENAME 0x73U + +/* + * Counts the number of Neon instructions going through the Register Rename + * stage.Instructions are still speculative in this stage. + * Two NEON instructions can be renamed in the same cycle so the event is two + * bits long: + *0b00 no NEON instruction renamed + *0b01 one NEON instruction renamed + *0b10 two NEON instructions renamed + */ +#define XPM_EVENT_NEONRENAME 0x74U + +/* + * Counts the number of cycles where the processor is stalled because PLD slots + * are all full + */ +#define XPM_EVENT_PLDSTALL 0x80U + +/* + * Counts the number of cycles when the processor is stalled and the data side + * is stalled too because it is full and executing writes to the external + * memory + */ +#define XPM_EVENT_WRITESTALL 0x81U + +/* + * Counts the number of stall cycles due to main TLB misses on requests issued + * by the instruction side + */ +#define XPM_EVENT_INSTRTLBSTALL 0x82U + +/* + * Counts the number of stall cycles due to main TLB misses on requests issued + * by the data side + */ +#define XPM_EVENT_DATATLBSTALL 0x83U + +/* + * Counts the number of stall cycles due to micro TLB misses on the instruction + * side. This event does not include main TLB miss stall cycles that are already + * counted in the corresponding main TLB event + */ +#define XPM_EVENT_INSTR_uTLBSTALL 0x84U + +/* + * Counts the number of stall cycles due to micro TLB misses on the data side. + * This event does not include main TLB miss stall cycles that are already + * counted in the corresponding main TLB event + */ +#define XPM_EVENT_DATA_uTLBSTALL 0x85U + +/* + * Counts the number of stall cycles because of the execution of a DMB memory + * barrier. This includes all DMB instructions being executed, even + * speculatively + */ +#define XPM_EVENT_DMB_STALL 0x86U + +/* + * Counts the number of cycles during which the integer core clock is enabled + */ +#define XPM_EVENT_INT_CLKEN 0x8AU + +/* + * Counts the number of cycles during which the Data Engine clock is enabled + */ +#define XPM_EVENT_DE_CLKEN 0x8BU + +/* + * Counts the number of ISB instructions architecturally executed + */ +#define XPM_EVENT_INSTRISB 0x90U + +/* + * Counts the number of DSB instructions architecturally executed + */ +#define XPM_EVENT_INSTRDSB 0x91U + +/* + * Counts the number of DMB instructions speculatively executed + */ +#define XPM_EVENT_INSTRDMB 0x92U + +/* + * Counts the number of external interrupts executed by the processor + */ +#define XPM_EVENT_EXTINT 0x93U + +/* + * PLE cache line request completed + */ +#define XPM_EVENT_PLE_LRC 0xA0U + +/* + * PLE cache line request skipped + */ +#define XPM_EVENT_PLE_LRS 0xA1U + +/* + * PLE FIFO flush + */ +#define XPM_EVENT_PLE_FLUSH 0xA2U + +/* + * PLE request complete + */ +#define XPM_EVENT_PLE_CMPL 0xA3U + +/* + * PLE FIFO overflow + */ +#define XPM_EVENT_PLE_OVFL 0xA4U + +/* + * PLE request programmed + */ +#define XPM_EVENT_PLE_PROG 0xA5U + +/* + * The following constants define the configurations for Cortex-A9 Performance + * Monitor Events. Each configuration configures the event counters for a set + * of events. + * ----------------------------------------------- + * Config PmCtr0... PmCtr5 + * ----------------------------------------------- + * XPM_CNTRCFG1 { XPM_EVENT_SOFTINCR, + * XPM_EVENT_INSRFETCH_CACHEREFILL, + * XPM_EVENT_INSTRFECT_TLBREFILL, + * XPM_EVENT_DATA_CACHEREFILL, + * XPM_EVENT_DATA_CACHEACCESS, + * XPM_EVENT_DATA_TLBREFILL } + * + * XPM_CNTRCFG2 { XPM_EVENT_DATA_READS, + * XPM_EVENT_DATA_WRITE, + * XPM_EVENT_EXCEPTION, + * XPM_EVENT_EXCEPRETURN, + * XPM_EVENT_CHANGECONTEXT, + * XPM_EVENT_SW_CHANGEPC } + * + * XPM_CNTRCFG3 { XPM_EVENT_IMMEDBRANCH, + * XPM_EVENT_UNALIGNEDACCESS, + * XPM_EVENT_BRANCHMISS, + * XPM_EVENT_CLOCKCYCLES, + * XPM_EVENT_BRANCHPREDICT, + * XPM_EVENT_JAVABYTECODE } + * + * XPM_CNTRCFG4 { XPM_EVENT_SWJAVABYTECODE, + * XPM_EVENT_JAVABACKBRANCH, + * XPM_EVENT_COHERLINEMISS, + * XPM_EVENT_COHERLINEHIT, + * XPM_EVENT_INSTRSTALL, + * XPM_EVENT_DATASTALL } + * + * XPM_CNTRCFG5 { XPM_EVENT_MAINTLBSTALL, + * XPM_EVENT_STREXPASS, + * XPM_EVENT_STREXFAIL, + * XPM_EVENT_DATAEVICT, + * XPM_EVENT_NODISPATCH, + * XPM_EVENT_ISSUEEMPTY } + * + * XPM_CNTRCFG6 { XPM_EVENT_INSTRRENAME, + * XPM_EVENT_PREDICTFUNCRET, + * XPM_EVENT_MAINEXEC, + * XPM_EVENT_SECEXEC, + * XPM_EVENT_LDRSTR, + * XPM_EVENT_FLOATRENAME } + * + * XPM_CNTRCFG7 { XPM_EVENT_NEONRENAME, + * XPM_EVENT_PLDSTALL, + * XPM_EVENT_WRITESTALL, + * XPM_EVENT_INSTRTLBSTALL, + * XPM_EVENT_DATATLBSTALL, + * XPM_EVENT_INSTR_uTLBSTALL } + * + * XPM_CNTRCFG8 { XPM_EVENT_DATA_uTLBSTALL, + * XPM_EVENT_DMB_STALL, + * XPM_EVENT_INT_CLKEN, + * XPM_EVENT_DE_CLKEN, + * XPM_EVENT_INSTRISB, + * XPM_EVENT_INSTRDSB } + * + * XPM_CNTRCFG9 { XPM_EVENT_INSTRDMB, + * XPM_EVENT_EXTINT, + * XPM_EVENT_PLE_LRC, + * XPM_EVENT_PLE_LRS, + * XPM_EVENT_PLE_FLUSH, + * XPM_EVENT_PLE_CMPL } + * + * XPM_CNTRCFG10 { XPM_EVENT_PLE_OVFL, + * XPM_EVENT_PLE_PROG, + * XPM_EVENT_PLE_LRC, + * XPM_EVENT_PLE_LRS, + * XPM_EVENT_PLE_FLUSH, + * XPM_EVENT_PLE_CMPL } + * + * XPM_CNTRCFG11 { XPM_EVENT_DATASTALL, + * XPM_EVENT_INSRFETCH_CACHEREFILL, + * XPM_EVENT_INSTRFECT_TLBREFILL, + * XPM_EVENT_DATA_CACHEREFILL, + * XPM_EVENT_DATA_CACHEACCESS, + * XPM_EVENT_DATA_TLBREFILL } + */ +#define XPM_CNTRCFG1 0 +#define XPM_CNTRCFG2 1 +#define XPM_CNTRCFG3 2 +#define XPM_CNTRCFG4 3 +#define XPM_CNTRCFG5 4 +#define XPM_CNTRCFG6 5 +#define XPM_CNTRCFG7 6 +#define XPM_CNTRCFG8 7 +#define XPM_CNTRCFG9 8 +#define XPM_CNTRCFG10 9 +#define XPM_CNTRCFG11 10 + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Variable Definitions ****************************/ + +/************************** Function Prototypes *****************************/ + +/* Interface fuctions to access perfromance counters from abstraction layer */ +void Xpm_SetEvents(s32 PmcrCfg); +void Xpm_GetEventCounters(u32 *PmCtrValue); + +#ifdef __cplusplus +} +#endif + +#endif +/** +* @} End of "addtogroup a9_event_counter_apis". +*/ diff --git a/df_datalink/bsp/ps7_cortexa9_0/include/xpseudo_asm.h b/df_datalink/bsp/ps7_cortexa9_0/include/xpseudo_asm.h new file mode 100644 index 0000000..c7123a0 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/include/xpseudo_asm.h @@ -0,0 +1,82 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xpseudo_asm.h +* +* @addtogroup a9_specific Cortex A9 Processor Specific Include Files +* +* The xpseudo_asm.h includes xreg_cortexa9.h and xpseudo_asm_gcc.h. +* +* The xreg_cortexa9.h file contains definitions for inline assembler code. +* It provides inline definitions for Cortex A9 GPRs, SPRs, MPE registers, +* co-processor registers and Debug registers. +* +* The xpseudo_asm_gcc.h contains the definitions for the most often used inline +* assembler instructions, available as macros. These can be very useful for +* tasks such as setting or getting special purpose registers, synchronization, +* or cache manipulation etc. These inline assembler instructions can be used +* from drivers and user applications written in C. +* +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a ecm  10/18/09 First release
+* 3.04a sdm  01/02/12 Remove redundant dsb in mcr instruction.
+* 6.8   aru  09/06/18 Removed compilation warnings for ARMCC toolchain.
+* 
+* +******************************************************************************/ +#ifndef XPSEUDO_ASM_H +#define XPSEUDO_ASM_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "xreg_cortexa9.h" +#ifdef __GNUC__ + #include "xpseudo_asm_gcc.h" +#elif defined (__ICCARM__) + #include "xpseudo_asm_iccarm.h" +#else + #include "xpseudo_asm_rvct.h" +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* XPSEUDO_ASM_H */ +/** +* @} End of "addtogroup a9_specific". +*/ diff --git a/df_datalink/bsp/ps7_cortexa9_0/include/xpseudo_asm_gcc.h b/df_datalink/bsp/ps7_cortexa9_0/include/xpseudo_asm_gcc.h new file mode 100644 index 0000000..85b067d --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/include/xpseudo_asm_gcc.h @@ -0,0 +1,252 @@ +/****************************************************************************** +* +* Copyright (C) 2014 - 2016 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xpseudo_asm_gcc.h +* +* This header file contains macros for using inline assembler code. It is +* written specifically for the GNU compiler. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 5.00 	pkp		 05/21/14 First release
+* 6.0   mus      07/27/16 Consolidated file for a53,a9 and r5 processors
+* 
+* +******************************************************************************/ + +#ifndef XPSEUDO_ASM_GCC_H /* prevent circular inclusions */ +#define XPSEUDO_ASM_GCC_H /* by using protection macros */ + +/***************************** Include Files ********************************/ + +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/* necessary for pre-processor */ +#define stringify(s) tostring(s) +#define tostring(s) #s + +#if defined (__aarch64__) +/* pseudo assembler instructions */ +#define mfcpsr() ({u32 rval = 0U; \ + asm volatile("mrs %0, DAIF" : "=r" (rval));\ + rval;\ + }) + +#define mtcpsr(v) __asm__ __volatile__ ("msr DAIF, %0" : : "r" (v)) + +#define cpsiei() //__asm__ __volatile__("cpsie i\n") +#define cpsidi() //__asm__ __volatile__("cpsid i\n") + +#define cpsief() //__asm__ __volatile__("cpsie f\n") +#define cpsidf() //__asm__ __volatile__("cpsid f\n") + + + +#define mtgpr(rn, v) /*__asm__ __volatile__(\ + "mov r" stringify(rn) ", %0 \n"\ + : : "r" (v)\ + )*/ + +#define mfgpr(rn) /*({u32 rval; \ + __asm__ __volatile__(\ + "mov %0,r" stringify(rn) "\n"\ + : "=r" (rval)\ + );\ + rval;\ + })*/ + +/* memory synchronization operations */ + +/* Instruction Synchronization Barrier */ +#define isb() __asm__ __volatile__ ("isb sy") + +/* Data Synchronization Barrier */ +#define dsb() __asm__ __volatile__("dsb sy") + +/* Data Memory Barrier */ +#define dmb() __asm__ __volatile__("dmb sy") + + +/* Memory Operations */ +#define ldr(adr) ({u64 rval; \ + __asm__ __volatile__(\ + "ldr %0,[%1]"\ + : "=r" (rval) : "r" (adr)\ + );\ + rval;\ + }) + +#define mfelrel3() ({u64 rval = 0U; \ + asm volatile("mrs %0, ELR_EL3" : "=r" (rval));\ + rval;\ + }) + +#define mtelrel3(v) __asm__ __volatile__ ("msr ELR_EL3, %0" : : "r" (v)) + +#else + +/* pseudo assembler instructions */ +#define mfcpsr() ({u32 rval = 0U; \ + __asm__ __volatile__(\ + "mrs %0, cpsr\n"\ + : "=r" (rval)\ + );\ + rval;\ + }) + +#define mtcpsr(v) __asm__ __volatile__(\ + "msr cpsr,%0\n"\ + : : "r" (v)\ + ) + +#define cpsiei() __asm__ __volatile__("cpsie i\n") +#define cpsidi() __asm__ __volatile__("cpsid i\n") + +#define cpsief() __asm__ __volatile__("cpsie f\n") +#define cpsidf() __asm__ __volatile__("cpsid f\n") + + + +#define mtgpr(rn, v) __asm__ __volatile__(\ + "mov r" stringify(rn) ", %0 \n"\ + : : "r" (v)\ + ) + +#define mfgpr(rn) ({u32 rval; \ + __asm__ __volatile__(\ + "mov %0,r" stringify(rn) "\n"\ + : "=r" (rval)\ + );\ + rval;\ + }) + +/* memory synchronization operations */ + +/* Instruction Synchronization Barrier */ +#define isb() __asm__ __volatile__ ("isb" : : : "memory") + +/* Data Synchronization Barrier */ +#define dsb() __asm__ __volatile__ ("dsb" : : : "memory") + +/* Data Memory Barrier */ +#define dmb() __asm__ __volatile__ ("dmb" : : : "memory") + + +/* Memory Operations */ +#define ldr(adr) ({u32 rval; \ + __asm__ __volatile__(\ + "ldr %0,[%1]"\ + : "=r" (rval) : "r" (adr)\ + );\ + rval;\ + }) + +#endif + +#define ldrb(adr) ({u8 rval; \ + __asm__ __volatile__(\ + "ldrb %0,[%1]"\ + : "=r" (rval) : "r" (adr)\ + );\ + rval;\ + }) + +#define str(adr, val) __asm__ __volatile__(\ + "str %0,[%1]\n"\ + : : "r" (val), "r" (adr)\ + ) + +#define strb(adr, val) __asm__ __volatile__(\ + "strb %0,[%1]\n"\ + : : "r" (val), "r" (adr)\ + ) + +/* Count leading zeroes (clz) */ +#define clz(arg) ({u8 rval; \ + __asm__ __volatile__(\ + "clz %0,%1"\ + : "=r" (rval) : "r" (arg)\ + );\ + rval;\ + }) + +#if defined (__aarch64__) +#define mtcpdc(reg,val) __asm__ __volatile__("dc " #reg ",%0" : : "r" (val)) +#define mtcpic(reg,val) __asm__ __volatile__("ic " #reg ",%0" : : "r" (val)) + +#define mtcpicall(reg) __asm__ __volatile__("ic " #reg) +#define mtcptlbi(reg) __asm__ __volatile__("tlbi " #reg) +#define mtcpat(reg,val) __asm__ __volatile__("at " #reg ",%0" : : "r" (val)) +/* CP15 operations */ +#define mfcp(reg) ({u64 rval = 0U;\ + __asm__ __volatile__("mrs %0, " #reg : "=r" (rval));\ + rval;\ + }) + +#define mtcp(reg,val) __asm__ __volatile__("msr " #reg ",%0" : : "r" (val)) + +#else +/* CP15 operations */ +#define mtcp(rn, v) __asm__ __volatile__(\ + "mcr " rn "\n"\ + : : "r" (v)\ + ); + +#define mfcp(rn) ({u32 rval = 0U; \ + __asm__ __volatile__(\ + "mrc " rn "\n"\ + : "=r" (rval)\ + );\ + rval;\ + }) +#endif + +/************************** Variable Definitions ****************************/ + +/************************** Function Prototypes *****************************/ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* XPSEUDO_ASM_GCC_H */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/include/xqspips.h b/df_datalink/bsp/ps7_cortexa9_0/include/xqspips.h new file mode 100644 index 0000000..0255bc2 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/include/xqspips.h @@ -0,0 +1,804 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xqspips.h +* @addtogroup qspips_v3_6 +* @{ +* @details +* +* This file contains the implementation of the XQspiPs driver. It supports only +* master mode. User documentation for the driver functions is contained in this +* file in the form of comment blocks at the front of each function. +* +* A QSPI device connects to an QSPI bus through a 4-wire serial interface. +* The QSPI bus is a full-duplex, synchronous bus that facilitates communication +* between one master and one slave. The device is always full-duplex, +* which means that for every byte sent, one is received, and vice-versa. +* The master controls the clock, so it can regulate when it wants to +* send or receive data. The slave is under control of the master, it must +* respond quickly since it has no control of the clock and must send/receive +* data as fast or as slow as the master does. +* +* Linear Mode +* The Linear Quad-SPI Controller extends the existing Quad-SPI Controller�s +* functionality by adding a linear addressing scheme that allows the SPI flash +* memory subsystem to behave like a typical ROM device. The new feature hides +* the normal SPI protocol from a master reading from the SPI flash memory. The +* feature improves both the user friendliness and the overall read memory +* throughput over that of the current Quad-SPI Controller by lessening the +* amount of software overheads required and by the use of the faster AXI +* interface. +* +* Initialization & Configuration +* +* The XQspiPs_Config structure is used by the driver to configure itself. This +* configuration structure is typically created by the tool-chain based on HW +* build properties. +* +* To support multiple runtime loading and initialization strategies employed by +* various operating systems, the driver instance can be initialized in the +* following way: +* - XQspiPs_LookupConfig(DeviceId) - Use the device identifier to find +* static configuration structure defined in xqspips_g.c. This is setup +* by the tools. For some operating systems the config structure will be +* initialized by the software and this call is not needed. +* - XQspiPs_CfgInitialize(InstancePtr, CfgPtr, EffectiveAddr) - Uses a +* configuration structure provided by the caller. If running in a system +* with address translation, the provided virtual memory base address +* replaces the physical address present in the configuration structure. +* +* Multiple Masters +* +* More than one master can exist, but arbitration is the responsibility of +* the higher layer software. The device driver does not perform any type of +* arbitration. +* +* Modes of Operation +* +* There are four modes to perform a data transfer and the selection of a mode +* is based on Chip Select(CS) and Start. These two options individually, can +* be controlled either by software(Manual) or hardware(Auto). +* - Auto CS: Chip select is automatically asserted as soon as the first word +* is written into the TXFIFO and de asserted when the TXFIFO becomes +* empty +* - Manual CS: Software must assert and de assert CS. +* - Auto Start: Data transmission starts as soon as there is data in the +* TXFIFO and stalls when the TXFIFO is empty +* - Manual Start: Software must start data transmission at the beginning of +* the transaction or whenever the TXFIFO has become empty +* +* The preferred combination is Manual CS and Auto Start. +* In this combination, the software asserts CS before loading any data into +* TXFIFO. In Auto Start mode, whenever data is in TXFIFO, controller sends it +* out until TXFIFO becomes empty. The software reads the RXFIFO whenever the +* data is available. If no further data, software disables CS. +* +* Risks/challenges of other combinations: +* - Manual CS and Manual Start: Manual Start bit should be set after each +* TXFIFO write otherwise there could be a race condition where the TXFIFO +* becomes empty before the new word is written. In that case the +* transmission stops. +* - Auto CS with Manual or Auto Start: It is very difficult for software to +* keep the TXFIFO filled. Whenever the TXFIFO runs empty, CS is de asserted. +* This results in a single transaction to be split into multiple pieces each +* with its own chip select. This will result in garbage data to be sent. +* +* Interrupts +* +* The user must connect the interrupt handler of the driver, +* XQspiPs_InterruptHandler, to an interrupt system such that it will be +* called when an interrupt occurs. This function does not save and restore +* the processor context such that the user must provide this processing. +* +* The driver handles the following interrupts: +* - Data Transmit Register/FIFO Underflow +* - Data Receive Register/FIFO Not Empty +* - Data Transmit Register/FIFO Overwater +* - Data Receive Register/FIFO Overrun +* +* The Data Transmit Register/FIFO Overwater interrupt -- indicates that the +* QSPI device has transmitted the data available to transmit, and now its data +* register and FIFO is ready to accept more data. The driver uses this +* interrupt to indicate progress while sending data. The driver may have +* more data to send, in which case the data transmit register and FIFO is +* filled for subsequent transmission. When this interrupt arrives and all +* the data has been sent, the driver invokes the status callback with a +* value of XST_SPI_TRANSFER_DONE to inform the upper layer software that +* all data has been sent. +* +* The Data Transmit Register/FIFO Underflow interrupt -- indicates that, +* as slave, the QSPI device was required to transmit but there was no data +* available to transmit in the transmit register (or FIFO). This may not +* be an error if the master is not expecting data. But in the case where +* the master is expecting data, this serves as a notification of such a +* condition. The driver reports this condition to the upper layer +* software through the status handler. +* +* The Data Receive Register/FIFO Overrun interrupt -- indicates that the QSPI +* device received data and subsequently dropped the data because the data +* receive register and FIFO was full. The driver reports this condition to the +* upper layer software through the status handler. This likely indicates a +* problem with the higher layer protocol, or a problem with the slave +* performance. +* +* +* Polled Operation +* +* Transfer in polled mode is supported through a separate interface function +* XQspiPs_PolledTransfer(). Unlike the transfer function in the interrupt mode, +* this function blocks until all data has been sent/received. +* +* Device Busy +* +* Some operations are disallowed when the device is busy. The driver tracks +* whether a device is busy. The device is considered busy when a data transfer +* request is outstanding, and is considered not busy only when that transfer +* completes (or is aborted with a mode fault error). +* +* Device Configuration +* +* The device can be configured in various ways during the FPGA implementation +* process. Configuration parameters are stored in the xqspips_g.c file or +* passed in via XQspiPs_CfgInitialize(). A table is defined where each entry +* contains configuration information for an QSPI device, including the base +* address for the device. +* +* RTOS Independence +* +* This driver is intended to be RTOS and processor independent. It works with +* physical addresses only. Any needs for dynamic memory management, threads or +* thread mutual exclusion, virtual memory, or cache control must be satisfied +* by the layer above this driver. +* +* NOTE: This driver was always tested with endianess set to little-endian. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- -----------------------------------------------
+* 1.00a sdm 11/25/10 First release, based on the PS SPI driver...
+* 1.01a sdm 11/22/11 Added TCL file for generating QSPI parameters
+*		     in xparameters.h
+* 2.00a kka 07/25/12 Added a few register defines for CR 670297
+* 		     Removed code related to mode fault for CR 671468
+*		     The XQspiPs_SetSlaveSelect has been modified to remove
+*		     the argument of the slave select as the QSPI controller
+*		     only supports one slave.
+* 		     XQspiPs_GetSlaveSelect API has been removed
+* 		     Added a flag ShiftReadData to the instance structure
+*.		     and is used in the XQspiPs_GetReadData API.
+*		     The ShiftReadData Flag indicates whether the data
+*		     read from the Rx FIFO needs to be shifted
+*		     in cases where the data is less than 4  bytes
+* 		     Removed the selection for the following options:
+*		     Master mode (XQSPIPS_MASTER_OPTION) and
+*		     Flash interface mode (XQSPIPS_FLASH_MODE_OPTION) option
+*		     as the QSPI driver supports the Master mode
+*		     and Flash Interface mode and doesnot support
+*		     Slave mode or the legacy mode.
+*		     Modified the XQspiPs_PolledTransfer and XQspiPs_Transfer
+*		     APIs so that the last argument (IsInst) specifying whether
+*		     it is instruction or data has been removed. The first byte
+*		     in the SendBufPtr argument of these APIs specify the
+*		     instruction to be sent to the Flash Device.
+*		     This version of the driver fixes CRs 670197/663787/
+*		     670297/671468.
+* 		     Added the option for setting the Holdb_dr bit in the
+*		     configuration options, XQSPIPS_HOLD_B_DRIVE_OPTION
+*		     is the option to be used for setting this bit in the
+*		     configuration register.
+*		     The XQspiPs_PolledTransfer function has been updated
+*		     to fill the data to fifo depth.
+* 2.01a sg  02/03/13 Added flash opcodes for DUAL_IO_READ,QUAD_IO_READ.
+*		     Added macros for Set/Get Rx Watermark. Changed QSPI
+*		     Enable/Disable macro argument from BaseAddress to
+*		     Instance Pointer. Added DelayNss argument to SetDelays
+*		     and GetDelays API's.
+*		     Created macros XQspiPs_IsManualStart and
+*		     XQspiPs_IsManualChipSelect.
+*		     Changed QSPI transfer logic for polled and interrupt
+*		     modes to be based on filled tx fifo count and receive
+*		     based on it. RXNEMPTY interrupt is not used.
+*		     Added assertions to XQspiPs_LqspiRead function.
+*		     SetDelays and GetDelays API's include DelayNss parameter.
+*		     Added defines for DelayNss,Rx Watermark,Interrupts
+*		     which need write to clear. Removed Read zeros mask from
+*		     LQSPI Config register. Renamed Fixed burst error to
+*		     data FSM error in  LQSPI Status register.
+*
+* 2.02a hk  05/07/13 Added ConnectionMode to config structure.
+*			 Corresponds to C_QSPI_MODE - 0:Single, 1:Stacked, 2:Parallel
+*			 Added enable and disable to the XQspiPs_LqspiRead() function
+*			 Removed XQspi_Reset() in Set_Options() function when
+*			 LQSPI_MODE_OPTION is set.
+*            Added instructions for bank selection, die erase and
+*            flag status register to the flash instruction table
+*            Handling for instructions not in flash instruction
+*			 table added. Checking for Tx FIFO empty when switching from
+*			 TXD1/2/3 to TXD0 added. If WRSR instruction is sent with
+*            byte count 3 (spansion), instruction size and TXD register
+*			 changed accordingly. CR# 712502 and 703869.
+*            Added prefix to constant definitions for ConnectionMode
+*            Added (#ifdef linear base address) in the Linear read function.
+*            Changed  XPAR_XQSPIPS_0_LINEAR_BASEADDR to
+*            XPAR_PS7_QSPI_LINEAR_0_S_AXI_BASEADDR in
+*            XQspiPs_LqspiRead function. Fix for CR#718141.
+*
+* 2.03a hk  09/17/13 Modified polled and interrupt transfers to make use of
+*                    thresholds. This is to improve performance.
+*                    Added API's for QSPI reset and
+*                    linear mode initialization for boot.
+*                    Added RX and TX threshold reset to one in XQspiPs_Abort.
+*                    Added RX threshold reset(1) after transfer in polled and
+*                    interrupt transfers. Made changes to make sure threshold
+*                    change is done only when no transfer is in progress.
+*                    Updated linear init API for parallel and stacked modes.
+*                    CR#737760.
+* 3.1   hk  08/13/14 When writing to the configuration register, set/reset
+*                    required bits leaving reserved bits untouched. CR# 796813.
+* 3.2	sk	02/05/15 Add SLCR reset in abort function as a workaround because
+* 					 controller does not update FIFO status flags as expected
+* 					 when thresholds are used.
+* 3.3   sk  11/07/15 Modified the API prototypes according to MISRAC standards
+*                    to remove compilation warnings. CR# 868893.
+*       ms  03/17/17 Added readme.txt file in examples folder for doxygen
+*                    generation.
+*       ms  04/05/17 Modified Comment lines in functions of qspips
+*                    examples to recognize it as documentation block
+*                    and modified filename tag in
+*                    xqspips_dual_flash_stack_lqspi_example.c to include it in
+*                    doxygen examples.
+* 3.4   nsk 31/07/17 Added QSPI_BUS_WIDTH parameter in xparameters.h file
+* 3.5	tjs 08/21/18 Fixed compilation warnings for the ARMCC.
+* 3.5	tjs 07/16/18 Added support for low density ISSI flash parts.
+* 3.6   akm 03/28/19 Fixed memory leak issue while reading from qspi.(CR#1016357)
+* 3.6   akm 04/15/19 Modified FlashQuadEnable, FlashWrie and FlashErase APIs,
+*                    to wait for the on going operation to complete before
+*                    performing the next operation.
+* 3.6   akm 04/15/19 Modified the mask in XQspiPs_GetReadData() API to retrieve
+*                    configuration register values of both the Flashes in dual
+*                    parellel connection.
+*
+* 
+* +******************************************************************************/ +#ifndef XQSPIPS_H /* prevent circular inclusions */ +#define XQSPIPS_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xstatus.h" +#include "xqspips_hw.h" +#include + +/************************** Constant Definitions *****************************/ + +/** @name Configuration options + * + * The following options are supported to enable/disable certain features of + * an QSPI device. Each of the options is a bit mask, so more than one may be + * specified. + * + * + * The Active Low Clock option configures the device's clock polarity. + * Setting this option means the clock is active low and the SCK signal idles + * high. By default, the clock is active high and SCK idles low. + * + * The Clock Phase option configures the QSPI device for one of two + * transfer formats. A clock phase of 0, the default, means data is valid on + * the first SCK edge (rising or falling) after the slave select (SS) signal + * has been asserted. A clock phase of 1 means data is valid on the second SCK + * edge (rising or falling) after SS has been asserted. + * + * + * The QSPI Force Slave Select option is used to enable manual control of + * the slave select signal. + * 0: The SPI_SS signal is controlled by the QSPI controller during + * transfers. (Default) + * 1: The SPI_SS signal is forced active (driven low) regardless of any + * transfers in progress. + * + * NOTE: The driver will handle setting and clearing the Slave Select when + * the user sets the "FORCE_SSELECT_OPTION". Using this option will allow the + * QSPI clock to be set to a faster speed. If the QSPI clock is too fast, the + * processor cannot empty and refill the FIFOs before the TX FIFO is empty + * When the QSPI hardware is controlling the Slave Select signals, this + * will cause slave to be de-selected and terminate the transfer. + * + * The Manual Start option is used to enable manual control of + * the Start command to perform data transfer. + * 0: The Start command is controlled by the QSPI controller during + * transfers(Default). Data transmission starts as soon as there is data in + * the TXFIFO and stalls when the TXFIFO is empty + * 1: The Start command must be issued by software to perform data transfer. + * Bit 15 of Configuration register is used to issue Start command. This bit + * must be set whenever TXFIFO is filled with new data. + * + * NOTE: The driver will set the Manual Start Enable bit in Configuration + * Register, if Manual Start option is selected. Software will issue + * Manual Start command whenever TXFIFO is filled with data. When there is + * no further data, driver will clear the Manual Start Enable bit. + * + * @{ + */ +#define XQSPIPS_CLK_ACTIVE_LOW_OPTION 0x2 /**< Active Low Clock option */ +#define XQSPIPS_CLK_PHASE_1_OPTION 0x4 /**< Clock Phase one option */ +#define XQSPIPS_FORCE_SSELECT_OPTION 0x10 /**< Force Slave Select */ +#define XQSPIPS_MANUAL_START_OPTION 0x20 /**< Manual Start enable */ +#define XQSPIPS_LQSPI_MODE_OPTION 0x80 /**< Linear QPSI mode */ +#define XQSPIPS_HOLD_B_DRIVE_OPTION 0x100 /**< Drive HOLD_B Pin */ +/*@}*/ + + +/** @name QSPI Clock Prescaler options + * The QSPI Clock Prescaler Configuration bits are used to program master mode + * bit rate. The bit rate can be programmed in divide-by-two decrements from + * pclk/2 to pclk/256. + * + * @{ + */ +#define XQSPIPS_CLK_PRESCALE_2 0x00 /**< PCLK/2 Prescaler */ +#define XQSPIPS_CLK_PRESCALE_4 0x01 /**< PCLK/4 Prescaler */ +#define XQSPIPS_CLK_PRESCALE_8 0x02 /**< PCLK/8 Prescaler */ +#define XQSPIPS_CLK_PRESCALE_16 0x03 /**< PCLK/16 Prescaler */ +#define XQSPIPS_CLK_PRESCALE_32 0x04 /**< PCLK/32 Prescaler */ +#define XQSPIPS_CLK_PRESCALE_64 0x05 /**< PCLK/64 Prescaler */ +#define XQSPIPS_CLK_PRESCALE_128 0x06 /**< PCLK/128 Prescaler */ +#define XQSPIPS_CLK_PRESCALE_256 0x07 /**< PCLK/256 Prescaler */ + +/*@}*/ + + +/** @name Callback events + * + * These constants specify the handler events that are passed to + * a handler from the driver. These constants are not bit masks such that + * only one will be passed at a time to the handler. + * + * @{ + */ +#define XQSPIPS_EVENT_TRANSFER_DONE 2 /**< Transfer done */ +#define XQSPIPS_EVENT_TRANSMIT_UNDERRUN 3 /**< TX FIFO empty */ +#define XQSPIPS_EVENT_RECEIVE_OVERRUN 4 /**< Receive data loss because + * RX FIFO full + */ +/*@}*/ + +/** @name Flash commands + * + * The following constants define most of the commands supported by flash + * devices. Users can add more commands supported by the flash devices + * + * @{ + */ +#define XQSPIPS_FLASH_OPCODE_WRSR 0x01 /* Write status register */ +#define XQSPIPS_FLASH_OPCODE_PP 0x02 /* Page program */ +#define XQSPIPS_FLASH_OPCODE_NORM_READ 0x03 /* Normal read data bytes */ +#define XQSPIPS_FLASH_OPCODE_WRDS 0x04 /* Write disable */ +#define XQSPIPS_FLASH_OPCODE_RDSR1 0x05 /* Read status register 1 */ +#define XQSPIPS_FLASH_OPCODE_WREN 0x06 /* Write enable */ +#define XQSPIPS_FLASH_OPCODE_FAST_READ 0x0B /* Fast read data bytes */ +#define XQSPIPS_FLASH_OPCODE_BE_4K 0x20 /* Erase 4KiB block */ +#define XQSPIPS_FLASH_OPCODE_RDSR2 0x35 /* Read status register 2 */ +#define XQSPIPS_FLASH_OPCODE_DUAL_READ 0x3B /* Dual read data bytes */ +#define XQSPIPS_FLASH_OPCODE_BE_32K 0x52 /* Erase 32KiB block */ +#define XQSPIPS_FLASH_OPCODE_QUAD_READ 0x6B /* Quad read data bytes */ +#define XQSPIPS_FLASH_OPCODE_ERASE_SUS 0x75 /* Erase suspend */ +#define XQSPIPS_FLASH_OPCODE_ERASE_RES 0x7A /* Erase resume */ +#define XQSPIPS_FLASH_OPCODE_RDID 0x9F /* Read JEDEC ID */ +#define XQSPIPS_FLASH_OPCODE_BE 0xC7 /* Erase whole flash block */ +#define XQSPIPS_FLASH_OPCODE_SE 0xD8 /* Sector erase (usually 64KB)*/ +#define XQSPIPS_FLASH_OPCODE_DUAL_IO_READ 0xBB /* Read data using Dual I/O */ +#define XQSPIPS_FLASH_OPCODE_QUAD_IO_READ 0xEB /* Read data using Quad I/O */ +#define XQSPIPS_FLASH_OPCODE_BRWR 0x17 /* Bank Register Write */ +#define XQSPIPS_FLASH_OPCODE_BRRD 0x16 /* Bank Register Read */ +/* Extende Address Register Write - Micron's equivalent of Bank Register */ +#define XQSPIPS_FLASH_OPCODE_EARWR 0xC5 +/* Extende Address Register Read - Micron's equivalent of Bank Register */ +#define XQSPIPS_FLASH_OPCODE_EARRD 0xC8 +#define XQSPIPS_FLASH_OPCODE_DIE_ERASE 0xC4 +#define XQSPIPS_FLASH_OPCODE_READ_FLAG_SR 0x70 +#define XQSPIPS_FLASH_OPCODE_CLEAR_FLAG_SR 0x50 +#define XQSPIPS_FLASH_OPCODE_READ_LOCK_REG 0xE8 /* Lock Reg Read */ +#define XQSPIPS_FLASH_OPCODE_WRITE_LOCK_REG 0xE5 /* Lock Reg Write */ + +/*@}*/ + +/** @name Instruction size + * + * The following constants define numbers 1 to 4. + * Used to identify whether TXD0,1,2 or 3 is to be used. + * + * @{ + */ +#define XQSPIPS_SIZE_ONE 1 +#define XQSPIPS_SIZE_TWO 2 +#define XQSPIPS_SIZE_THREE 3 +#define XQSPIPS_SIZE_FOUR 4 + +/*@}*/ + +/** @name ConnectionMode + * + * The following constants are the possible values of ConnectionMode in + * Config structure. + * + * @{ + */ +#define XQSPIPS_CONNECTION_MODE_SINGLE 0 +#define XQSPIPS_CONNECTION_MODE_STACKED 1 +#define XQSPIPS_CONNECTION_MODE_PARALLEL 2 + +/*@}*/ + +/** @name FIFO threshold value + * + * This is the Rx FIFO threshold (in words) that was found to be most + * optimal in terms of performance + * + * @{ + */ +#define XQSPIPS_RXFIFO_THRESHOLD_OPT 32 + +/*@}*/ + +/**************************** Type Definitions *******************************/ +/** + * The handler data type allows the user to define a callback function to + * handle the asynchronous processing for the QSPI device. The application + * using this driver is expected to define a handler of this type to support + * interrupt driven mode. The handler executes in an interrupt context, so + * only minimal processing should be performed. + * + * @param CallBackRef is the callback reference passed in by the upper + * layer when setting the callback functions, and passed back to + * the upper layer when the callback is invoked. Its type is + * not important to the driver, so it is a void pointer. + * @param StatusEvent holds one or more status events that have occurred. + * See the XQspiPs_SetStatusHandler() for details on the status + * events that can be passed in the callback. + * @param ByteCount indicates how many bytes of data were successfully + * transferred. This may be less than the number of bytes + * requested if the status event indicates an error. + */ +typedef void (*XQspiPs_StatusHandler) (void *CallBackRef, u32 StatusEvent, + unsigned ByteCount); + +/** + * This typedef contains configuration information for the device. + */ +typedef struct { + u16 DeviceId; /**< Unique ID of device */ + u32 BaseAddress; /**< Base address of the device */ + u32 InputClockHz; /**< Input clock frequency */ + u8 ConnectionMode; /**< Single, Stacked and Parallel mode */ +} XQspiPs_Config; + +/** + * The XQspiPs driver instance data. The user is required to allocate a + * variable of this type for every QSPI device in the system. A pointer + * to a variable of this type is then passed to the driver API functions. + */ +typedef struct { + XQspiPs_Config Config; /**< Configuration structure */ + u32 IsReady; /**< Device is initialized and ready */ + + u8 *SendBufferPtr; /**< Buffer to send (state) */ + u8 *RecvBufferPtr; /**< Buffer to receive (state) */ + int RequestedBytes; /**< Number of bytes to transfer (state) */ + int RemainingBytes; /**< Number of bytes left to transfer(state) */ + u32 IsBusy; /**< A transfer is in progress (state) */ + XQspiPs_StatusHandler StatusHandler; + void *StatusRef; /**< Callback reference for status handler */ + u32 ShiftReadData; /**< Flag to indicate whether the data + * read from the Rx FIFO needs to be shifted + * in cases where the data is less than 4 + * bytes + */ +} XQspiPs; + +/***************** Macros (Inline Functions) Definitions *********************/ + +/****************************************************************************/ +/* +* +* Check in OptionsTable if Manual Start Option is enabled or disabled. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* +* @return +* - TRUE if option is set +* - FALSE if option is not set +* +* @note C-Style signature: +* u8 XQspiPs_IsManualStart(XQspiPs *InstancePtr); +* +*****************************************************************************/ +#define XQspiPs_IsManualStart(InstancePtr) \ + ((XQspiPs_GetOptions(InstancePtr) & \ + XQSPIPS_MANUAL_START_OPTION) ? TRUE : FALSE) + +/****************************************************************************/ +/* +* +* Check in OptionsTable if Manual Chip Select Option is enabled or disabled. +* +* @param InstancePtr is a pointer to the XSpiPs instance. +* +* @return +* - TRUE if option is set +* - FALSE if option is not set +* +* @note C-Style signature: +* u8 XQspiPs_IsManualChipSelect(XQspiPs *InstancePtr); +* +*****************************************************************************/ +#define XQspiPs_IsManualChipSelect(InstancePtr) \ + ((XQspiPs_GetOptions(InstancePtr) & \ + XQSPIPS_FORCE_SSELECT_OPTION) ? TRUE : FALSE) + +/****************************************************************************/ +/** +* +* Set the contents of the slave idle count register. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* @param RegisterValue is the value to be written, valid values are +* 0-255. +* +* @return None +* +* @note C-Style signature: +* void XQspiPs_SetSlaveIdle(XQspiPs *InstancePtr, +* u32 RegisterValue) +* +*****************************************************************************/ +#define XQspiPs_SetSlaveIdle(InstancePtr, RegisterValue) \ + XQspiPs_Out32(((InstancePtr)->Config.BaseAddress) + \ + XQSPIPS_SICR_OFFSET, (RegisterValue)) + +/****************************************************************************/ +/** +* +* Get the contents of the slave idle count register. Use the XQSPIPS_SICR_* +* constants defined in xqspips_hw.h to interpret the bit-mask returned. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* +* @return An 8-bit value representing Slave Idle Count. +* +* @note C-Style signature: +* u32 XQspiPs_GetSlaveIdle(XQspiPs *InstancePtr) +* +*****************************************************************************/ +#define XQspiPs_GetSlaveIdle(InstancePtr) \ + XQspiPs_In32(((InstancePtr)->Config.BaseAddress) + \ + XQSPIPS_SICR_OFFSET) + +/****************************************************************************/ +/** +* +* Set the contents of the transmit FIFO watermark register. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* @param RegisterValue is the value to be written, valid values are 1-63. +* +* @return None. +* +* @note C-Style signature: +* void XQspiPs_SetTXWatermark(XQspiPs *InstancePtr, +* u32 RegisterValue) +* +*****************************************************************************/ +#define XQspiPs_SetTXWatermark(InstancePtr, RegisterValue) \ + XQspiPs_Out32(((InstancePtr)->Config.BaseAddress) + \ + XQSPIPS_TXWR_OFFSET, (RegisterValue)) + +/****************************************************************************/ +/** +* +* Get the contents of the transmit FIFO watermark register. +* Valid values are in the range 1-63. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* +* @return A 6-bit value representing Tx Watermark level. +* +* @note C-Style signature: +* u32 XQspiPs_GetTXWatermark(XQspiPs *InstancePtr) +* +*****************************************************************************/ +#define XQspiPs_GetTXWatermark(InstancePtr) \ + XQspiPs_In32((InstancePtr->Config.BaseAddress) + XQSPIPS_TXWR_OFFSET) + +/****************************************************************************/ +/** +* +* Set the contents of the receive FIFO watermark register. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* @param RegisterValue is the value to be written, valid values are 1-63. +* +* @return None. +* +* @note C-Style signature: +* void XQspiPs_SetRXWatermark(XQspiPs *InstancePtr, +* u32 RegisterValue) +* +*****************************************************************************/ +#define XQspiPs_SetRXWatermark(InstancePtr, RegisterValue) \ + XQspiPs_Out32(((InstancePtr)->Config.BaseAddress) + \ + XQSPIPS_RXWR_OFFSET, (RegisterValue)) + +/****************************************************************************/ +/** +* +* Get the contents of the receive FIFO watermark register. +* Valid values are in the range 1-63. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* +* @return A 6-bit value representing Rx Watermark level. +* +* @note C-Style signature: +* u32 XQspiPs_GetRXWatermark(XQspiPs *InstancePtr) +* +*****************************************************************************/ +#define XQspiPs_GetRXWatermark(InstancePtr) \ + XQspiPs_In32((InstancePtr->Config.BaseAddress) + XQSPIPS_RXWR_OFFSET) + +/****************************************************************************/ +/** +* +* Enable the device and uninhibit master transactions. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* +* @return None. +* +* @note C-Style signature: +* void XQspiPs_Enable(XQspiPs *InstancePtr) +* +*****************************************************************************/ +#define XQspiPs_Enable(InstancePtr) \ + XQspiPs_Out32((InstancePtr->Config.BaseAddress) + XQSPIPS_ER_OFFSET, \ + XQSPIPS_ER_ENABLE_MASK) + +/****************************************************************************/ +/** +* +* Disable the device. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* +* @return None. +* +* @note C-Style signature: +* void XQspiPs_Disable(XQspiPs *InstancePtr) +* +*****************************************************************************/ +#define XQspiPs_Disable(InstancePtr) \ + XQspiPs_Out32((InstancePtr->Config.BaseAddress) + XQSPIPS_ER_OFFSET, 0) + +/****************************************************************************/ +/** +* +* Set the contents of the Linear QSPI Configuration register. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* @param RegisterValue is the value to be written to the Linear QSPI +* configuration register. +* +* @return None. +* +* @note C-Style signature: +* void XQspiPs_SetLqspiConfigReg(XQspiPs *InstancePtr, +* u32 RegisterValue) +* +*****************************************************************************/ +#define XQspiPs_SetLqspiConfigReg(InstancePtr, RegisterValue) \ + XQspiPs_Out32(((InstancePtr)->Config.BaseAddress) + \ + XQSPIPS_LQSPI_CR_OFFSET, (RegisterValue)) + +/****************************************************************************/ +/** +* +* Get the contents of the Linear QSPI Configuration register. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* +* @return A 32-bit value representing the contents of the LQSPI Config +* register. +* +* @note C-Style signature: +* u32 XQspiPs_GetLqspiConfigReg(u32 *InstancePtr) +* +*****************************************************************************/ +#define XQspiPs_GetLqspiConfigReg(InstancePtr) \ + XQspiPs_In32((InstancePtr->Config.BaseAddress) + \ + XQSPIPS_LQSPI_CR_OFFSET) + +/************************** Function Prototypes ******************************/ + +/* + * Initialization function, implemented in xqspips_sinit.c + */ +XQspiPs_Config *XQspiPs_LookupConfig(u16 DeviceId); + +/* + * Functions implemented in xqspips.c + */ +int XQspiPs_CfgInitialize(XQspiPs *InstancePtr, XQspiPs_Config *Config, + u32 EffectiveAddr); +void XQspiPs_Reset(XQspiPs *InstancePtr); +void XQspiPs_Abort(XQspiPs *InstancePtr); + +s32 XQspiPs_Transfer(XQspiPs *InstancePtr, u8 *SendBufPtr, u8 *RecvBufPtr, + u32 ByteCount); +s32 XQspiPs_PolledTransfer(XQspiPs *InstancePtr, u8 *SendBufPtr, + u8 *RecvBufPtr, u32 ByteCount); +int XQspiPs_LqspiRead(XQspiPs *InstancePtr, u8 *RecvBufPtr, + u32 Address, unsigned ByteCount); + +int XQspiPs_SetSlaveSelect(XQspiPs *InstancePtr); + +void XQspiPs_SetStatusHandler(XQspiPs *InstancePtr, void *CallBackRef, + XQspiPs_StatusHandler FuncPtr); +void XQspiPs_InterruptHandler(void *InstancePtr); + +/* + * Functions for selftest, in xqspips_selftest.c + */ +int XQspiPs_SelfTest(XQspiPs *InstancePtr); + +/* + * Functions for options, in xqspips_options.c + */ +s32 XQspiPs_SetOptions(XQspiPs *InstancePtr, u32 Options); +u32 XQspiPs_GetOptions(XQspiPs *InstancePtr); + +s32 XQspiPs_SetClkPrescaler(XQspiPs *InstancePtr, u8 Prescaler); +u8 XQspiPs_GetClkPrescaler(XQspiPs *InstancePtr); + +int XQspiPs_SetDelays(XQspiPs *InstancePtr, u8 DelayNss, u8 DelayBtwn, + u8 DelayAfter, u8 DelayInit); +void XQspiPs_GetDelays(XQspiPs *InstancePtr, u8 *DelayNss, u8 *DelayBtwn, + u8 *DelayAfter, u8 *DelayInit); +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/include/xqspips_hw.h b/df_datalink/bsp/ps7_cortexa9_0/include/xqspips_hw.h new file mode 100644 index 0000000..88c232e --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/include/xqspips_hw.h @@ -0,0 +1,421 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xqspips_hw.h +* @addtogroup qspips_v3_6 +* @{ +* +* This header file contains the identifiers and basic HW access driver +* functions (or macros) that can be used to access the device. Other driver +* functions are defined in xqspips.h. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- -----------------------------------------------
+* 1.00  sdm 11/25/10 First release
+* 2.00a ka  07/25/12 Added a few register defines for CR 670297
+*		     and removed some defines of reserved fields for
+*		     CR 671468
+*		     Added define XQSPIPS_CR_HOLD_B_MASK for Holdb_dr
+*		     bit in Configuration register.
+* 2.01a sg  02/03/13 Added defines for DelayNss,Rx Watermark,Interrupts
+*		     which need write to clear. Removed Read zeros mask from
+*		     LQSPI Config register.
+* 2.03a hk  08/22/13 Added prototypes of API's for QSPI reset and
+*                    linear mode initialization for boot. Added related
+*                    constant definitions.
+* 3.1   hk  08/13/14 Changed definition of CR reset value masks to set/reset
+*                    required bits leaving reserved bits untouched. CR# 796813.
+* 3.2	sk	02/05/15 Add SLCR reset in abort function as a workaround because
+* 					 controller does not update FIFO status flags as expected
+* 					 when thresholds are used.
+* 3.6   akm 03/28/19 Fixed memory leak issue while reading from qspi.(CR#1016357)
+*
+* 
+* +******************************************************************************/ +#ifndef XQSPIPS_HW_H /* prevent circular inclusions */ +#define XQSPIPS_HW_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_io.h" +#include "xparameters.h" + +/************************** Constant Definitions *****************************/ + +/** @name Register Map + * + * Register offsets from the base address of an QSPI device. + * @{ + */ +#define XQSPIPS_CR_OFFSET 0x00 /**< Configuration Register */ +#define XQSPIPS_SR_OFFSET 0x04 /**< Interrupt Status */ +#define XQSPIPS_IER_OFFSET 0x08 /**< Interrupt Enable */ +#define XQSPIPS_IDR_OFFSET 0x0c /**< Interrupt Disable */ +#define XQSPIPS_IMR_OFFSET 0x10 /**< Interrupt Enabled Mask */ +#define XQSPIPS_ER_OFFSET 0x14 /**< Enable/Disable Register */ +#define XQSPIPS_DR_OFFSET 0x18 /**< Delay Register */ +#define XQSPIPS_TXD_00_OFFSET 0x1C /**< Transmit 4-byte inst/data */ +#define XQSPIPS_RXD_OFFSET 0x20 /**< Data Receive Register */ +#define XQSPIPS_SICR_OFFSET 0x24 /**< Slave Idle Count */ +#define XQSPIPS_TXWR_OFFSET 0x28 /**< Transmit FIFO Watermark */ +#define XQSPIPS_RXWR_OFFSET 0x2C /**< Receive FIFO Watermark */ +#define XQSPIPS_GPIO_OFFSET 0x30 /**< GPIO Register */ +#define XQSPIPS_LPBK_DLY_ADJ_OFFSET 0x38 /**< Loopback Delay Adjust Reg */ +#define XQSPIPS_TXD_01_OFFSET 0x80 /**< Transmit 1-byte inst */ +#define XQSPIPS_TXD_10_OFFSET 0x84 /**< Transmit 2-byte inst */ +#define XQSPIPS_TXD_11_OFFSET 0x88 /**< Transmit 3-byte inst */ +#define XQSPIPS_LQSPI_CR_OFFSET 0xA0 /**< Linear QSPI config register */ +#define XQSPIPS_LQSPI_SR_OFFSET 0xA4 /**< Linear QSPI status register */ +#define XQSPIPS_MOD_ID_OFFSET 0xFC /**< Module ID register */ + +/* @} */ + +/** @name Configuration Register + * + * This register contains various control bits that + * affect the operation of the QSPI device. Read/Write. + * @{ + */ + +#define XQSPIPS_CR_IFMODE_MASK 0x80000000 /**< Flash mem interface mode */ +#define XQSPIPS_CR_ENDIAN_MASK 0x04000000 /**< Tx/Rx FIFO endianness */ +#define XQSPIPS_CR_MANSTRT_MASK 0x00010000 /**< Manual Transmission Start */ +#define XQSPIPS_CR_MANSTRTEN_MASK 0x00008000 /**< Manual Transmission Start + Enable */ +#define XQSPIPS_CR_SSFORCE_MASK 0x00004000 /**< Force Slave Select */ +#define XQSPIPS_CR_SSCTRL_MASK 0x00000400 /**< Slave Select Decode */ +#define XQSPIPS_CR_SSCTRL_SHIFT 10 /**< Slave Select Decode shift */ +#define XQSPIPS_CR_DATA_SZ_MASK 0x000000C0 /**< Size of word to be + transferred */ +#define XQSPIPS_CR_PRESC_MASK 0x00000038 /**< Prescaler Setting */ +#define XQSPIPS_CR_PRESC_SHIFT 3 /**< Prescaler shift */ +#define XQSPIPS_CR_PRESC_MAXIMUM 0x07 /**< Prescaler maximum value */ + +#define XQSPIPS_CR_CPHA_MASK 0x00000004 /**< Phase Configuration */ +#define XQSPIPS_CR_CPOL_MASK 0x00000002 /**< Polarity Configuration */ + +#define XQSPIPS_CR_MSTREN_MASK 0x00000001 /**< Master Mode Enable */ + +#define XQSPIPS_CR_HOLD_B_MASK 0x00080000 /**< HOLD_B Pin Drive Enable */ + +#define XQSPIPS_CR_REF_CLK_MASK 0x00000100 /**< Ref clk bit - should be 0 */ + +/* Deselect the Slave select line and set the transfer size to 32 at reset */ +#define XQSPIPS_CR_RESET_MASK_SET XQSPIPS_CR_IFMODE_MASK | \ + XQSPIPS_CR_SSCTRL_MASK | \ + XQSPIPS_CR_DATA_SZ_MASK | \ + XQSPIPS_CR_MSTREN_MASK | \ + XQSPIPS_CR_SSFORCE_MASK | \ + XQSPIPS_CR_HOLD_B_MASK +#define XQSPIPS_CR_RESET_MASK_CLR XQSPIPS_CR_CPOL_MASK | \ + XQSPIPS_CR_CPHA_MASK | \ + XQSPIPS_CR_PRESC_MASK | \ + XQSPIPS_CR_MANSTRTEN_MASK | \ + XQSPIPS_CR_MANSTRT_MASK | \ + XQSPIPS_CR_ENDIAN_MASK | \ + XQSPIPS_CR_REF_CLK_MASK +/* @} */ + + +/** @name QSPI Interrupt Registers + * + * QSPI Status Register + * + * This register holds the interrupt status flags for an QSPI device. Some + * of the flags are level triggered, which means that they are set as long + * as the interrupt condition exists. Other flags are edge triggered, + * which means they are set once the interrupt condition occurs and remain + * set until they are cleared by software. The interrupts are cleared by + * writing a '1' to the interrupt bit position in the Status Register. + * Read/Write. + * + * QSPI Interrupt Enable Register + * + * This register is used to enable chosen interrupts for an QSPI device. + * Writing a '1' to a bit in this register sets the corresponding bit in the + * QSPI Interrupt Mask register. Write only. + * + * QSPI Interrupt Disable Register + * + * This register is used to disable chosen interrupts for an QSPI device. + * Writing a '1' to a bit in this register clears the corresponding bit in the + * QSPI Interrupt Mask register. Write only. + * + * QSPI Interrupt Mask Register + * + * This register shows the enabled/disabled interrupts of an QSPI device. + * Read only. + * + * All four registers have the same bit definitions. They are only defined once + * for each of the Interrupt Enable Register, Interrupt Disable Register, + * Interrupt Mask Register, and Channel Interrupt Status Register + * @{ + */ + +#define XQSPIPS_IXR_TXUF_MASK 0x00000040 /**< QSPI Tx FIFO Underflow */ +#define XQSPIPS_IXR_RXFULL_MASK 0x00000020 /**< QSPI Rx FIFO Full */ +#define XQSPIPS_IXR_RXNEMPTY_MASK 0x00000010 /**< QSPI Rx FIFO Not Empty */ +#define XQSPIPS_IXR_TXFULL_MASK 0x00000008 /**< QSPI Tx FIFO Full */ +#define XQSPIPS_IXR_TXOW_MASK 0x00000004 /**< QSPI Tx FIFO Overwater */ +#define XQSPIPS_IXR_RXOVR_MASK 0x00000001 /**< QSPI Rx FIFO Overrun */ +#define XQSPIPS_IXR_DFLT_MASK 0x00000025 /**< QSPI default interrupts + mask */ +#define XQSPIPS_IXR_WR_TO_CLR_MASK 0x00000041 /**< Interrupts which + need write to clear */ +#define XQSPIPS_ISR_RESET_STATE 0x00000004 /**< Default to tx/rx empty */ +#define XQSPIPS_IXR_DISABLE_ALL 0x0000007D /**< Disable all interrupts */ +/* @} */ + + +/** @name Enable Register + * + * This register is used to enable or disable an QSPI device. + * Read/Write + * @{ + */ +#define XQSPIPS_ER_ENABLE_MASK 0x00000001 /**< QSPI Enable Bit Mask */ +/* @} */ + + +/** @name Delay Register + * + * This register is used to program timing delays in + * slave mode. Read/Write + * @{ + */ +#define XQSPIPS_DR_NSS_MASK 0xFF000000 /**< Delay to de-assert slave select + between two words mask */ +#define XQSPIPS_DR_NSS_SHIFT 24 /**< Delay to de-assert slave select + between two words shift */ +#define XQSPIPS_DR_BTWN_MASK 0x00FF0000 /**< Delay Between Transfers + mask */ +#define XQSPIPS_DR_BTWN_SHIFT 16 /**< Delay Between Transfers shift */ +#define XQSPIPS_DR_AFTER_MASK 0x0000FF00 /**< Delay After Transfers mask */ +#define XQSPIPS_DR_AFTER_SHIFT 8 /**< Delay After Transfers shift */ +#define XQSPIPS_DR_INIT_MASK 0x000000FF /**< Delay Initially mask */ +/* @} */ + +/** @name Slave Idle Count Registers + * + * This register defines the number of pclk cycles the slave waits for a the + * QSPI clock to become stable in quiescent state before it can detect the start + * of the next transfer in CPHA = 1 mode. + * Read/Write + * + * @{ + */ +#define XQSPIPS_SICR_MASK 0x000000FF /**< Slave Idle Count Mask */ +/* @} */ + + +/** @name Transmit FIFO Watermark Register + * + * This register defines the watermark setting for the Transmit FIFO. + * + * @{ + */ +#define XQSPIPS_TXWR_MASK 0x0000003F /**< Transmit Watermark Mask */ +#define XQSPIPS_TXWR_RESET_VALUE 0x00000001 /**< Transmit Watermark + * register reset value */ + +/* @} */ + +/** @name Receive FIFO Watermark Register + * + * This register defines the watermark setting for the Receive FIFO. + * + * @{ + */ +#define XQSPIPS_RXWR_MASK 0x0000003F /**< Receive Watermark Mask */ +#define XQSPIPS_RXWR_RESET_VALUE 0x00000001 /**< Receive Watermark + * register reset value */ + +/* @} */ + +/** @name FIFO Depth + * + * This macro provides the depth of transmit FIFO and receive FIFO. + * + * @{ + */ +#define XQSPIPS_FIFO_DEPTH 63 /**< FIFO depth (words) */ +/* @} */ + + +/** @name Linear QSPI Configuration Register + * + * This register contains various control bits that + * affect the operation of the Linear QSPI controller. Read/Write. + * + * @{ + */ +#define XQSPIPS_LQSPI_CR_LINEAR_MASK 0x80000000 /**< LQSPI mode enable */ +#define XQSPIPS_LQSPI_CR_TWO_MEM_MASK 0x40000000 /**< Both memories or one */ +#define XQSPIPS_LQSPI_CR_SEP_BUS_MASK 0x20000000 /**< Seperate memory bus */ +#define XQSPIPS_LQSPI_CR_U_PAGE_MASK 0x10000000 /**< Upper memory page */ +#define XQSPIPS_LQSPI_CR_MODE_EN_MASK 0x02000000 /**< Enable mode bits */ +#define XQSPIPS_LQSPI_CR_MODE_ON_MASK 0x01000000 /**< Mode on */ +#define XQSPIPS_LQSPI_CR_MODE_BITS_MASK 0x00FF0000 /**< Mode value for dual I/O + or quad I/O */ +#define XQSPIPS_LQSPI_CR_DUMMY_MASK 0x00000700 /**< Number of dummy bytes + between addr and return + read data */ +#define XQSPIPS_LQSPI_CR_INST_MASK 0x000000FF /**< Read instr code */ +#define XQSPIPS_LQSPI_CR_RST_STATE 0x8000016B /**< Default CR value */ +/* @} */ + +/** @name Linear QSPI Status Register + * + * This register contains various status bits of the Linear QSPI controller. + * Read/Write. + * + * @{ + */ +#define XQSPIPS_LQSPI_SR_D_FSM_ERR_MASK 0x00000004 /**< AXI Data FSM Error + received */ +#define XQSPIPS_LQSPI_SR_WR_RECVD_MASK 0x00000002 /**< AXI write command + received */ +/* @} */ + + +/** @name Loopback Delay Adjust Register + * + * This register contains various bit masks of Loopback Delay Adjust Register. + * + * @{ + */ + +#define XQSPIPS_LPBK_DLY_ADJ_USE_LPBK_MASK 0x00000020 /**< Loopback Bit */ + +/* @} */ + + +/** @name SLCR Register + * + * Register offsets from SLCR base address. + * + * @{ + */ + +#define SLCR_LOCK 0x00000004 /**< SLCR Write Protection Lock */ +#define SLCR_UNLOCK 0x00000008 /**< SLCR Write Protection Unlock */ +#define LQSPI_RST_CTRL 0x00000230 /**< Quad SPI Software Reset Control */ +#define SLCR_LOCKSTA 0x0000000C /**< SLCR Write Protection status */ + +/* @} */ + + +/** @name SLCR Register + * + * Bit Masks of above SLCR Registers . + * + * @{ + */ + +#ifndef XPAR_XSLCR_0_BASEADDR +#define XPAR_XSLCR_0_BASEADDR 0xF8000000 +#endif +#define SLCR_LOCK_MASK 0x767B /**< Write Protection Lock mask*/ +#define SLCR_UNLOCK_MASK 0xDF0D /**< SLCR Write Protection Unlock */ +#define LQSPI_RST_CTRL_MASK 0x3 /**< Quad SPI Software Reset Control */ + +/* @} */ + + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +#define XQspiPs_In32 Xil_In32 +#define XQspiPs_Out32 Xil_Out32 +#define XQSPIPS_DUMMY_TX_DATA 0xFFFFFFFF + +/****************************************************************************/ +/** +* Read a register. +* +* @param BaseAddress contains the base address of the device. +* @param RegOffset contains the offset from the 1st register of the +* device to the target register. +* +* @return The value read from the register. +* +* @note C-Style signature: +* u32 XQspiPs_ReadReg(u32 BaseAddress. int RegOffset) +* +******************************************************************************/ +#define XQspiPs_ReadReg(BaseAddress, RegOffset) \ + XQspiPs_In32((BaseAddress) + (RegOffset)) + +/***************************************************************************/ +/** +* Write to a register. +* +* @param BaseAddress contains the base address of the device. +* @param RegOffset contains the offset from the 1st register of the +* device to target register. +* @param RegisterValue is the value to be written to the register. +* +* @return None. +* +* @note C-Style signature: +* void XQspiPs_WriteReg(u32 BaseAddress, int RegOffset, +* u32 RegisterValue) +* +******************************************************************************/ +#define XQspiPs_WriteReg(BaseAddress, RegOffset, RegisterValue) \ + XQspiPs_Out32((BaseAddress) + (RegOffset), (RegisterValue)) + +/************************** Function Prototypes ******************************/ + +/* + * Functions implemented in xqspips_hw.c + */ +void XQspiPs_ResetHw(u32 BaseAddress); +void XQspiPs_LinearInit(u32 BaseAddress); + +/************************** Variable Definitions *****************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/include/xreg_cortexa9.h b/df_datalink/bsp/ps7_cortexa9_0/include/xreg_cortexa9.h new file mode 100644 index 0000000..ad93665 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/include/xreg_cortexa9.h @@ -0,0 +1,587 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xreg_cortexa9.h +* +* This header file contains definitions for using inline assembler code. It is +* written specifically for the GNU, ARMCC compiler. +* +* All of the ARM Cortex A9 GPRs, SPRs, and Debug Registers are defined along +* with the positions of the bits within the registers. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 1.00a ecm/sdm  10/20/09 First release
+* 
+* +******************************************************************************/ +#ifndef XREG_CORTEXA9_H +#define XREG_CORTEXA9_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* GPRs */ +#define XREG_GPR0 r0 +#define XREG_GPR1 r1 +#define XREG_GPR2 r2 +#define XREG_GPR3 r3 +#define XREG_GPR4 r4 +#define XREG_GPR5 r5 +#define XREG_GPR6 r6 +#define XREG_GPR7 r7 +#define XREG_GPR8 r8 +#define XREG_GPR9 r9 +#define XREG_GPR10 r10 +#define XREG_GPR11 r11 +#define XREG_GPR12 r12 +#define XREG_GPR13 r13 +#define XREG_GPR14 r14 +#define XREG_GPR15 r15 +#define XREG_CPSR cpsr + +/* Coprocessor number defines */ +#define XREG_CP0 0 +#define XREG_CP1 1 +#define XREG_CP2 2 +#define XREG_CP3 3 +#define XREG_CP4 4 +#define XREG_CP5 5 +#define XREG_CP6 6 +#define XREG_CP7 7 +#define XREG_CP8 8 +#define XREG_CP9 9 +#define XREG_CP10 10 +#define XREG_CP11 11 +#define XREG_CP12 12 +#define XREG_CP13 13 +#define XREG_CP14 14 +#define XREG_CP15 15 + +/* Coprocessor control register defines */ +#define XREG_CR0 cr0 +#define XREG_CR1 cr1 +#define XREG_CR2 cr2 +#define XREG_CR3 cr3 +#define XREG_CR4 cr4 +#define XREG_CR5 cr5 +#define XREG_CR6 cr6 +#define XREG_CR7 cr7 +#define XREG_CR8 cr8 +#define XREG_CR9 cr9 +#define XREG_CR10 cr10 +#define XREG_CR11 cr11 +#define XREG_CR12 cr12 +#define XREG_CR13 cr13 +#define XREG_CR14 cr14 +#define XREG_CR15 cr15 + +/* Current Processor Status Register (CPSR) Bits */ +#define XREG_CPSR_THUMB_MODE 0x20 +#define XREG_CPSR_MODE_BITS 0x1F +#define XREG_CPSR_SYSTEM_MODE 0x1F +#define XREG_CPSR_UNDEFINED_MODE 0x1B +#define XREG_CPSR_DATA_ABORT_MODE 0x17 +#define XREG_CPSR_SVC_MODE 0x13 +#define XREG_CPSR_IRQ_MODE 0x12 +#define XREG_CPSR_FIQ_MODE 0x11 +#define XREG_CPSR_USER_MODE 0x10 + +#define XREG_CPSR_IRQ_ENABLE 0x80 +#define XREG_CPSR_FIQ_ENABLE 0x40 + +#define XREG_CPSR_N_BIT 0x80000000 +#define XREG_CPSR_Z_BIT 0x40000000 +#define XREG_CPSR_C_BIT 0x20000000 +#define XREG_CPSR_V_BIT 0x10000000 + + +/* CP15 defines */ +#if defined (__GNUC__) || defined (__ICCARM__) +/* C0 Register defines */ +#define XREG_CP15_MAIN_ID "p15, 0, %0, c0, c0, 0" +#define XREG_CP15_CACHE_TYPE "p15, 0, %0, c0, c0, 1" +#define XREG_CP15_TCM_TYPE "p15, 0, %0, c0, c0, 2" +#define XREG_CP15_TLB_TYPE "p15, 0, %0, c0, c0, 3" +#define XREG_CP15_MULTI_PROC_AFFINITY "p15, 0, %0, c0, c0, 5" + +#define XREG_CP15_PROC_FEATURE_0 "p15, 0, %0, c0, c1, 0" +#define XREG_CP15_PROC_FEATURE_1 "p15, 0, %0, c0, c1, 1" +#define XREG_CP15_DEBUG_FEATURE_0 "p15, 0, %0, c0, c1, 2" +#define XREG_CP15_MEMORY_FEATURE_0 "p15, 0, %0, c0, c1, 4" +#define XREG_CP15_MEMORY_FEATURE_1 "p15, 0, %0, c0, c1, 5" +#define XREG_CP15_MEMORY_FEATURE_2 "p15, 0, %0, c0, c1, 6" +#define XREG_CP15_MEMORY_FEATURE_3 "p15, 0, %0, c0, c1, 7" + +#define XREG_CP15_INST_FEATURE_0 "p15, 0, %0, c0, c2, 0" +#define XREG_CP15_INST_FEATURE_1 "p15, 0, %0, c0, c2, 1" +#define XREG_CP15_INST_FEATURE_2 "p15, 0, %0, c0, c2, 2" +#define XREG_CP15_INST_FEATURE_3 "p15, 0, %0, c0, c2, 3" +#define XREG_CP15_INST_FEATURE_4 "p15, 0, %0, c0, c2, 4" + +#define XREG_CP15_CACHE_SIZE_ID "p15, 1, %0, c0, c0, 0" +#define XREG_CP15_CACHE_LEVEL_ID "p15, 1, %0, c0, c0, 1" +#define XREG_CP15_AUXILARY_ID "p15, 1, %0, c0, c0, 7" + +#define XREG_CP15_CACHE_SIZE_SEL "p15, 2, %0, c0, c0, 0" + +/* C1 Register Defines */ +#define XREG_CP15_SYS_CONTROL "p15, 0, %0, c1, c0, 0" +#define XREG_CP15_AUX_CONTROL "p15, 0, %0, c1, c0, 1" +#define XREG_CP15_CP_ACCESS_CONTROL "p15, 0, %0, c1, c0, 2" + +#define XREG_CP15_SECURE_CONFIG "p15, 0, %0, c1, c1, 0" +#define XREG_CP15_SECURE_DEBUG_ENABLE "p15, 0, %0, c1, c1, 1" +#define XREG_CP15_NS_ACCESS_CONTROL "p15, 0, %0, c1, c1, 2" +#define XREG_CP15_VIRTUAL_CONTROL "p15, 0, %0, c1, c1, 3" + +#else /* RVCT */ +/* C0 Register defines */ +#define XREG_CP15_MAIN_ID "cp15:0:c0:c0:0" +#define XREG_CP15_CACHE_TYPE "cp15:0:c0:c0:1" +#define XREG_CP15_TCM_TYPE "cp15:0:c0:c0:2" +#define XREG_CP15_TLB_TYPE "cp15:0:c0:c0:3" +#define XREG_CP15_MULTI_PROC_AFFINITY "cp15:0:c0:c0:5" + +#define XREG_CP15_PROC_FEATURE_0 "cp15:0:c0:c1:0" +#define XREG_CP15_PROC_FEATURE_1 "cp15:0:c0:c1:1" +#define XREG_CP15_DEBUG_FEATURE_0 "cp15:0:c0:c1:2" +#define XREG_CP15_MEMORY_FEATURE_0 "cp15:0:c0:c1:4" +#define XREG_CP15_MEMORY_FEATURE_1 "cp15:0:c0:c1:5" +#define XREG_CP15_MEMORY_FEATURE_2 "cp15:0:c0:c1:6" +#define XREG_CP15_MEMORY_FEATURE_3 "cp15:0:c0:c1:7" + +#define XREG_CP15_INST_FEATURE_0 "cp15:0:c0:c2:0" +#define XREG_CP15_INST_FEATURE_1 "cp15:0:c0:c2:1" +#define XREG_CP15_INST_FEATURE_2 "cp15:0:c0:c2:2" +#define XREG_CP15_INST_FEATURE_3 "cp15:0:c0:c2:3" +#define XREG_CP15_INST_FEATURE_4 "cp15:0:c0:c2:4" + +#define XREG_CP15_CACHE_SIZE_ID "cp15:1:c0:c0:0" +#define XREG_CP15_CACHE_LEVEL_ID "cp15:1:c0:c0:1" +#define XREG_CP15_AUXILARY_ID "cp15:1:c0:c0:7" + +#define XREG_CP15_CACHE_SIZE_SEL "cp15:2:c0:c0:0" + +/* C1 Register Defines */ +#define XREG_CP15_SYS_CONTROL "cp15:0:c1:c0:0" +#define XREG_CP15_AUX_CONTROL "cp15:0:c1:c0:1" +#define XREG_CP15_CP_ACCESS_CONTROL "cp15:0:c1:c0:2" + +#define XREG_CP15_SECURE_CONFIG "cp15:0:c1:c1:0" +#define XREG_CP15_SECURE_DEBUG_ENABLE "cp15:0:c1:c1:1" +#define XREG_CP15_NS_ACCESS_CONTROL "cp15:0:c1:c1:2" +#define XREG_CP15_VIRTUAL_CONTROL "cp15:0:c1:c1:3" +#endif + +/* XREG_CP15_CONTROL bit defines */ +#define XREG_CP15_CONTROL_TE_BIT 0x40000000U +#define XREG_CP15_CONTROL_AFE_BIT 0x20000000U +#define XREG_CP15_CONTROL_TRE_BIT 0x10000000U +#define XREG_CP15_CONTROL_NMFI_BIT 0x08000000U +#define XREG_CP15_CONTROL_EE_BIT 0x02000000U +#define XREG_CP15_CONTROL_HA_BIT 0x00020000U +#define XREG_CP15_CONTROL_RR_BIT 0x00004000U +#define XREG_CP15_CONTROL_V_BIT 0x00002000U +#define XREG_CP15_CONTROL_I_BIT 0x00001000U +#define XREG_CP15_CONTROL_Z_BIT 0x00000800U +#define XREG_CP15_CONTROL_SW_BIT 0x00000400U +#define XREG_CP15_CONTROL_B_BIT 0x00000080U +#define XREG_CP15_CONTROL_C_BIT 0x00000004U +#define XREG_CP15_CONTROL_A_BIT 0x00000002U +#define XREG_CP15_CONTROL_M_BIT 0x00000001U + +#if defined (__GNUC__) || defined (__ICCARM__) +/* C2 Register Defines */ +#define XREG_CP15_TTBR0 "p15, 0, %0, c2, c0, 0" +#define XREG_CP15_TTBR1 "p15, 0, %0, c2, c0, 1" +#define XREG_CP15_TTB_CONTROL "p15, 0, %0, c2, c0, 2" + +/* C3 Register Defines */ +#define XREG_CP15_DOMAIN_ACCESS_CTRL "p15, 0, %0, c3, c0, 0" + +/* C4 Register Defines */ +/* Not Used */ + +/* C5 Register Defines */ +#define XREG_CP15_DATA_FAULT_STATUS "p15, 0, %0, c5, c0, 0" +#define XREG_CP15_INST_FAULT_STATUS "p15, 0, %0, c5, c0, 1" + +#define XREG_CP15_AUX_DATA_FAULT_STATUS "p15, 0, %0, c5, c1, 0" +#define XREG_CP15_AUX_INST_FAULT_STATUS "p15, 0, %0, c5, c1, 1" + +/* C6 Register Defines */ +#define XREG_CP15_DATA_FAULT_ADDRESS "p15, 0, %0, c6, c0, 0" +#define XREG_CP15_INST_FAULT_ADDRESS "p15, 0, %0, c6, c0, 2" + +/* C7 Register Defines */ +#define XREG_CP15_NOP "p15, 0, %0, c7, c0, 4" + +#define XREG_CP15_INVAL_IC_POU_IS "p15, 0, %0, c7, c1, 0" +#define XREG_CP15_INVAL_BRANCH_ARRAY_IS "p15, 0, %0, c7, c1, 6" + +#define XREG_CP15_PHYS_ADDR "p15, 0, %0, c7, c4, 0" + +#define XREG_CP15_INVAL_IC_POU "p15, 0, %0, c7, c5, 0" +#define XREG_CP15_INVAL_IC_LINE_MVA_POU "p15, 0, %0, c7, c5, 1" + +/* The CP15 register access below has been deprecated in favor of the new + * isb instruction in Cortex A9. + */ +#define XREG_CP15_INST_SYNC_BARRIER "p15, 0, %0, c7, c5, 4" +#define XREG_CP15_INVAL_BRANCH_ARRAY "p15, 0, %0, c7, c5, 6" + +#define XREG_CP15_INVAL_DC_LINE_MVA_POC "p15, 0, %0, c7, c6, 1" +#define XREG_CP15_INVAL_DC_LINE_SW "p15, 0, %0, c7, c6, 2" + +#define XREG_CP15_VA_TO_PA_CURRENT_0 "p15, 0, %0, c7, c8, 0" +#define XREG_CP15_VA_TO_PA_CURRENT_1 "p15, 0, %0, c7, c8, 1" +#define XREG_CP15_VA_TO_PA_CURRENT_2 "p15, 0, %0, c7, c8, 2" +#define XREG_CP15_VA_TO_PA_CURRENT_3 "p15, 0, %0, c7, c8, 3" + +#define XREG_CP15_VA_TO_PA_OTHER_0 "p15, 0, %0, c7, c8, 4" +#define XREG_CP15_VA_TO_PA_OTHER_1 "p15, 0, %0, c7, c8, 5" +#define XREG_CP15_VA_TO_PA_OTHER_2 "p15, 0, %0, c7, c8, 6" +#define XREG_CP15_VA_TO_PA_OTHER_3 "p15, 0, %0, c7, c8, 7" + +#define XREG_CP15_CLEAN_DC_LINE_MVA_POC "p15, 0, %0, c7, c10, 1" +#define XREG_CP15_CLEAN_DC_LINE_SW "p15, 0, %0, c7, c10, 2" + +/* The next two CP15 register accesses below have been deprecated in favor + * of the new dsb and dmb instructions in Cortex A9. + */ +#define XREG_CP15_DATA_SYNC_BARRIER "p15, 0, %0, c7, c10, 4" +#define XREG_CP15_DATA_MEMORY_BARRIER "p15, 0, %0, c7, c10, 5" + +#define XREG_CP15_CLEAN_DC_LINE_MVA_POU "p15, 0, %0, c7, c11, 1" + +#define XREG_CP15_NOP2 "p15, 0, %0, c7, c13, 1" + +#define XREG_CP15_CLEAN_INVAL_DC_LINE_MVA_POC "p15, 0, %0, c7, c14, 1" +#define XREG_CP15_CLEAN_INVAL_DC_LINE_SW "p15, 0, %0, c7, c14, 2" + +/* C8 Register Defines */ +#define XREG_CP15_INVAL_TLB_IS "p15, 0, %0, c8, c3, 0" +#define XREG_CP15_INVAL_TLB_MVA_IS "p15, 0, %0, c8, c3, 1" +#define XREG_CP15_INVAL_TLB_ASID_IS "p15, 0, %0, c8, c3, 2" +#define XREG_CP15_INVAL_TLB_MVA_ASID_IS "p15, 0, %0, c8, c3, 3" + +#define XREG_CP15_INVAL_ITLB_UNLOCKED "p15, 0, %0, c8, c5, 0" +#define XREG_CP15_INVAL_ITLB_MVA "p15, 0, %0, c8, c5, 1" +#define XREG_CP15_INVAL_ITLB_ASID "p15, 0, %0, c8, c5, 2" + +#define XREG_CP15_INVAL_DTLB_UNLOCKED "p15, 0, %0, c8, c6, 0" +#define XREG_CP15_INVAL_DTLB_MVA "p15, 0, %0, c8, c6, 1" +#define XREG_CP15_INVAL_DTLB_ASID "p15, 0, %0, c8, c6, 2" + +#define XREG_CP15_INVAL_UTLB_UNLOCKED "p15, 0, %0, c8, c7, 0" +#define XREG_CP15_INVAL_UTLB_MVA "p15, 0, %0, c8, c7, 1" +#define XREG_CP15_INVAL_UTLB_ASID "p15, 0, %0, c8, c7, 2" +#define XREG_CP15_INVAL_UTLB_MVA_ASID "p15, 0, %0, c8, c7, 3" + +/* C9 Register Defines */ +#define XREG_CP15_PERF_MONITOR_CTRL "p15, 0, %0, c9, c12, 0" +#define XREG_CP15_COUNT_ENABLE_SET "p15, 0, %0, c9, c12, 1" +#define XREG_CP15_COUNT_ENABLE_CLR "p15, 0, %0, c9, c12, 2" +#define XREG_CP15_V_FLAG_STATUS "p15, 0, %0, c9, c12, 3" +#define XREG_CP15_SW_INC "p15, 0, %0, c9, c12, 4" +#define XREG_CP15_EVENT_CNTR_SEL "p15, 0, %0, c9, c12, 5" + +#define XREG_CP15_PERF_CYCLE_COUNTER "p15, 0, %0, c9, c13, 0" +#define XREG_CP15_EVENT_TYPE_SEL "p15, 0, %0, c9, c13, 1" +#define XREG_CP15_PERF_MONITOR_COUNT "p15, 0, %0, c9, c13, 2" + +#define XREG_CP15_USER_ENABLE "p15, 0, %0, c9, c14, 0" +#define XREG_CP15_INTR_ENABLE_SET "p15, 0, %0, c9, c14, 1" +#define XREG_CP15_INTR_ENABLE_CLR "p15, 0, %0, c9, c14, 2" + +/* C10 Register Defines */ +#define XREG_CP15_TLB_LOCKDWN "p15, 0, %0, c10, c0, 0" + +#define XREG_CP15_PRI_MEM_REMAP "p15, 0, %0, c10, c2, 0" +#define XREG_CP15_NORM_MEM_REMAP "p15, 0, %0, c10, c2, 1" + +/* C11 Register Defines */ +/* Not used */ + +/* C12 Register Defines */ +#define XREG_CP15_VEC_BASE_ADDR "p15, 0, %0, c12, c0, 0" +#define XREG_CP15_MONITOR_VEC_BASE_ADDR "p15, 0, %0, c12, c0, 1" + +#define XREG_CP15_INTERRUPT_STATUS "p15, 0, %0, c12, c1, 0" +#define XREG_CP15_VIRTUALIZATION_INTR "p15, 0, %0, c12, c1, 1" + +/* C13 Register Defines */ +#define XREG_CP15_CONTEXT_ID "p15, 0, %0, c13, c0, 1" +#define USER_RW_THREAD_PID "p15, 0, %0, c13, c0, 2" +#define USER_RO_THREAD_PID "p15, 0, %0, c13, c0, 3" +#define USER_PRIV_THREAD_PID "p15, 0, %0, c13, c0, 4" + +/* C14 Register Defines */ +/* not used */ + +/* C15 Register Defines */ +#define XREG_CP15_POWER_CTRL "p15, 0, %0, c15, c0, 0" +#define XREG_CP15_CONFIG_BASE_ADDR "p15, 4, %0, c15, c0, 0" + +#define XREG_CP15_READ_TLB_ENTRY "p15, 5, %0, c15, c4, 2" +#define XREG_CP15_WRITE_TLB_ENTRY "p15, 5, %0, c15, c4, 4" + +#define XREG_CP15_MAIN_TLB_VA "p15, 5, %0, c15, c5, 2" + +#define XREG_CP15_MAIN_TLB_PA "p15, 5, %0, c15, c6, 2" + +#define XREG_CP15_MAIN_TLB_ATTR "p15, 5, %0, c15, c7, 2" + +#else +/* C2 Register Defines */ +#define XREG_CP15_TTBR0 "cp15:0:c2:c0:0" +#define XREG_CP15_TTBR1 "cp15:0:c2:c0:1" +#define XREG_CP15_TTB_CONTROL "cp15:0:c2:c0:2" + +/* C3 Register Defines */ +#define XREG_CP15_DOMAIN_ACCESS_CTRL "cp15:0:c3:c0:0" + +/* C4 Register Defines */ +/* Not Used */ + +/* C5 Register Defines */ +#define XREG_CP15_DATA_FAULT_STATUS "cp15:0:c5:c0:0" +#define XREG_CP15_INST_FAULT_STATUS "cp15:0:c5:c0:1" + +#define XREG_CP15_AUX_DATA_FAULT_STATUS "cp15:0:c5:c1:0" +#define XREG_CP15_AUX_INST_FAULT_STATUS "cp15:0:c5:c1:1" + +/* C6 Register Defines */ +#define XREG_CP15_DATA_FAULT_ADDRESS "cp15:0:c6:c0:0" +#define XREG_CP15_INST_FAULT_ADDRESS "cp15:0:c6:c0:2" + +/* C7 Register Defines */ +#define XREG_CP15_NOP "cp15:0:c7:c0:4" + +#define XREG_CP15_INVAL_IC_POU_IS "cp15:0:c7:c1:0" +#define XREG_CP15_INVAL_BRANCH_ARRAY_IS "cp15:0:c7:c1:6" + +#define XREG_CP15_PHYS_ADDR "cp15:0:c7:c4:0" + +#define XREG_CP15_INVAL_IC_POU "cp15:0:c7:c5:0" +#define XREG_CP15_INVAL_IC_LINE_MVA_POU "cp15:0:c7:c5:1" + +/* The CP15 register access below has been deprecated in favor of the new + * isb instruction in Cortex A9. + */ +#define XREG_CP15_INST_SYNC_BARRIER "cp15:0:c7:c5:4" +#define XREG_CP15_INVAL_BRANCH_ARRAY "cp15:0:c7:c5:6" + +#define XREG_CP15_INVAL_DC_LINE_MVA_POC "cp15:0:c7:c6:1" +#define XREG_CP15_INVAL_DC_LINE_SW "cp15:0:c7:c6:2" + +#define XREG_CP15_VA_TO_PA_CURRENT_0 "cp15:0:c7:c8:0" +#define XREG_CP15_VA_TO_PA_CURRENT_1 "cp15:0:c7:c8:1" +#define XREG_CP15_VA_TO_PA_CURRENT_2 "cp15:0:c7:c8:2" +#define XREG_CP15_VA_TO_PA_CURRENT_3 "cp15:0:c7:c8:3" + +#define XREG_CP15_VA_TO_PA_OTHER_0 "cp15:0:c7:c8:4" +#define XREG_CP15_VA_TO_PA_OTHER_1 "cp15:0:c7:c8:5" +#define XREG_CP15_VA_TO_PA_OTHER_2 "cp15:0:c7:c8:6" +#define XREG_CP15_VA_TO_PA_OTHER_3 "cp15:0:c7:c8:7" + +#define XREG_CP15_CLEAN_DC_LINE_MVA_POC "cp15:0:c7:c10:1" +#define XREG_CP15_CLEAN_DC_LINE_SW "cp15:0:c7:c10:2" + +/* The next two CP15 register accesses below have been deprecated in favor + * of the new dsb and dmb instructions in Cortex A9. + */ +#define XREG_CP15_DATA_SYNC_BARRIER "cp15:0:c7:c10:4" +#define XREG_CP15_DATA_MEMORY_BARRIER "cp15:0:c7:c10:5" + +#define XREG_CP15_CLEAN_DC_LINE_MVA_POU "cp15:0:c7:c11:1" + +#define XREG_CP15_NOP2 "cp15:0:c7:c13:1" + +#define XREG_CP15_CLEAN_INVAL_DC_LINE_MVA_POC "cp15:0:c7:c14:1" +#define XREG_CP15_CLEAN_INVAL_DC_LINE_SW "cp15:0:c7:c14:2" + +/* C8 Register Defines */ +#define XREG_CP15_INVAL_TLB_IS "cp15:0:c8:c3:0" +#define XREG_CP15_INVAL_TLB_MVA_IS "cp15:0:c8:c3:1" +#define XREG_CP15_INVAL_TLB_ASID_IS "cp15:0:c8:c3:2" +#define XREG_CP15_INVAL_TLB_MVA_ASID_IS "cp15:0:c8:c3:3" + +#define XREG_CP15_INVAL_ITLB_UNLOCKED "cp15:0:c8:c5:0" +#define XREG_CP15_INVAL_ITLB_MVA "cp15:0:c8:c5:1" +#define XREG_CP15_INVAL_ITLB_ASID "cp15:0:c8:c5:2" + +#define XREG_CP15_INVAL_DTLB_UNLOCKED "cp15:0:c8:c6:0" +#define XREG_CP15_INVAL_DTLB_MVA "cp15:0:c8:c6:1" +#define XREG_CP15_INVAL_DTLB_ASID "cp15:0:c8:c6:2" + +#define XREG_CP15_INVAL_UTLB_UNLOCKED "cp15:0:c8:c7:0" +#define XREG_CP15_INVAL_UTLB_MVA "cp15:0:c8:c7:1" +#define XREG_CP15_INVAL_UTLB_ASID "cp15:0:c8:c7:2" +#define XREG_CP15_INVAL_UTLB_MVA_ASID "cp15:0:c8:c7:3" + +/* C9 Register Defines */ +#define XREG_CP15_PERF_MONITOR_CTRL "cp15:0:c9:c12:0" +#define XREG_CP15_COUNT_ENABLE_SET "cp15:0:c9:c12:1" +#define XREG_CP15_COUNT_ENABLE_CLR "cp15:0:c9:c12:2" +#define XREG_CP15_V_FLAG_STATUS "cp15:0:c9:c12:3" +#define XREG_CP15_SW_INC "cp15:0:c9:c12:4" +#define XREG_CP15_EVENT_CNTR_SEL "cp15:0:c9:c12:5" + +#define XREG_CP15_PERF_CYCLE_COUNTER "cp15:0:c9:c13:0" +#define XREG_CP15_EVENT_TYPE_SEL "cp15:0:c9:c13:1" +#define XREG_CP15_PERF_MONITOR_COUNT "cp15:0:c9:c13:2" + +#define XREG_CP15_USER_ENABLE "cp15:0:c9:c14:0" +#define XREG_CP15_INTR_ENABLE_SET "cp15:0:c9:c14:1" +#define XREG_CP15_INTR_ENABLE_CLR "cp15:0:c9:c14:2" + +/* C10 Register Defines */ +#define XREG_CP15_TLB_LOCKDWN "cp15:0:c10:c0:0" + +#define XREG_CP15_PRI_MEM_REMAP "cp15:0:c10:c2:0" +#define XREG_CP15_NORM_MEM_REMAP "cp15:0:c10:c2:1" + +/* C11 Register Defines */ +/* Not used */ + +/* C12 Register Defines */ +#define XREG_CP15_VEC_BASE_ADDR "cp15:0:c12:c0:0" +#define XREG_CP15_MONITOR_VEC_BASE_ADDR "cp15:0:c12:c0:1" + +#define XREG_CP15_INTERRUPT_STATUS "cp15:0:c12:c1:0" +#define XREG_CP15_VIRTUALIZATION_INTR "cp15:0:c12:c1:1" + +/* C13 Register Defines */ +#define XREG_CP15_CONTEXT_ID "cp15:0:c13:c0:1" +#define USER_RW_THREAD_PID "cp15:0:c13:c0:2" +#define USER_RO_THREAD_PID "cp15:0:c13:c0:3" +#define USER_PRIV_THREAD_PID "cp15:0:c13:c0:4" + +/* C14 Register Defines */ +/* not used */ + +/* C15 Register Defines */ +#define XREG_CP15_POWER_CTRL "cp15:0:c15:c0:0" +#define XREG_CP15_CONFIG_BASE_ADDR "cp15:4:c15:c0:0" + +#define XREG_CP15_READ_TLB_ENTRY "cp15:5:c15:c4:2" +#define XREG_CP15_WRITE_TLB_ENTRY "cp15:5:c15:c4:4" + +#define XREG_CP15_MAIN_TLB_VA "cp15:5:c15:c5:2" + +#define XREG_CP15_MAIN_TLB_PA "cp15:5:c15:c6:2" + +#define XREG_CP15_MAIN_TLB_ATTR "cp15:5:c15:c7:2" +#endif + + +/* MPE register definitions */ +#define XREG_FPSID c0 +#define XREG_FPSCR c1 +#define XREG_MVFR1 c6 +#define XREG_MVFR0 c7 +#define XREG_FPEXC c8 +#define XREG_FPINST c9 +#define XREG_FPINST2 c10 + +/* FPSID bits */ +#define XREG_FPSID_IMPLEMENTER_BIT (24) +#define XREG_FPSID_IMPLEMENTER_MASK (0xFF << FPSID_IMPLEMENTER_BIT) +#define XREG_FPSID_SOFTWARE (1<<23) +#define XREG_FPSID_ARCH_BIT (16) +#define XREG_FPSID_ARCH_MASK (0xF << FPSID_ARCH_BIT) +#define XREG_FPSID_PART_BIT (8) +#define XREG_FPSID_PART_MASK (0xFF << FPSID_PART_BIT) +#define XREG_FPSID_VARIANT_BIT (4) +#define XREG_FPSID_VARIANT_MASK (0xF << FPSID_VARIANT_BIT) +#define XREG_FPSID_REV_BIT (0) +#define XREG_FPSID_REV_MASK (0xF << FPSID_REV_BIT) + +/* FPSCR bits */ +#define XREG_FPSCR_N_BIT (1 << 31) +#define XREG_FPSCR_Z_BIT (1 << 30) +#define XREG_FPSCR_C_BIT (1 << 29) +#define XREG_FPSCR_V_BIT (1 << 28) +#define XREG_FPSCR_QC (1 << 27) +#define XREG_FPSCR_AHP (1 << 26) +#define XREG_FPSCR_DEFAULT_NAN (1 << 25) +#define XREG_FPSCR_FLUSHTOZERO (1 << 24) +#define XREG_FPSCR_ROUND_NEAREST (0 << 22) +#define XREG_FPSCR_ROUND_PLUSINF (1 << 22) +#define XREG_FPSCR_ROUND_MINUSINF (2 << 22) +#define XREG_FPSCR_ROUND_TOZERO (3 << 22) +#define XREG_FPSCR_RMODE_BIT (22) +#define XREG_FPSCR_RMODE_MASK (3 << FPSCR_RMODE_BIT) +#define XREG_FPSCR_STRIDE_BIT (20) +#define XREG_FPSCR_STRIDE_MASK (3 << FPSCR_STRIDE_BIT) +#define XREG_FPSCR_LENGTH_BIT (16) +#define XREG_FPSCR_LENGTH_MASK (7 << FPSCR_LENGTH_BIT) +#define XREG_FPSCR_IDC (1 << 7) +#define XREG_FPSCR_IXC (1 << 4) +#define XREG_FPSCR_UFC (1 << 3) +#define XREG_FPSCR_OFC (1 << 2) +#define XREG_FPSCR_DZC (1 << 1) +#define XREG_FPSCR_IOC (1 << 0) + +/* MVFR0 bits */ +#define XREG_MVFR0_RMODE_BIT (28) +#define XREG_MVFR0_RMODE_MASK (0xF << XREG_MVFR0_RMODE_BIT) +#define XREG_MVFR0_SHORT_VEC_BIT (24) +#define XREG_MVFR0_SHORT_VEC_MASK (0xF << XREG_MVFR0_SHORT_VEC_BIT) +#define XREG_MVFR0_SQRT_BIT (20) +#define XREG_MVFR0_SQRT_MASK (0xF << XREG_MVFR0_SQRT_BIT) +#define XREG_MVFR0_DIVIDE_BIT (16) +#define XREG_MVFR0_DIVIDE_MASK (0xF << XREG_MVFR0_DIVIDE_BIT) +#define XREG_MVFR0_EXEC_TRAP_BIT (12) +#define XREG_MVFR0_EXEC_TRAP_MASK (0xF << XREG_MVFR0_EXEC_TRAP_BIT) +#define XREG_MVFR0_DP_BIT (8) +#define XREG_MVFR0_DP_MASK (0xF << XREG_MVFR0_DP_BIT) +#define XREG_MVFR0_SP_BIT (4) +#define XREG_MVFR0_SP_MASK (0xF << XREG_MVFR0_SP_BIT) +#define XREG_MVFR0_A_SIMD_BIT (0) +#define XREG_MVFR0_A_SIMD_MASK (0xF << MVFR0_A_SIMD_BIT) + +/* FPEXC bits */ +#define XREG_FPEXC_EX (1 << 31) +#define XREG_FPEXC_EN (1 << 30) +#define XREG_FPEXC_DEX (1 << 29) + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* XREG_CORTEXA9_H */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/include/xscugic.h b/df_datalink/bsp/ps7_cortexa9_0/include/xscugic.h new file mode 100644 index 0000000..5502a20 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/include/xscugic.h @@ -0,0 +1,598 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xscugic.h +* @addtogroup scugic_v4_0 +* @{ +* @details +* +* The generic interrupt controller driver component. +* +* The interrupt controller driver uses the idea of priority for the various +* handlers. Priority is an integer within the range of 1 and 31 inclusive with +* default of 1 being the highest priority interrupt source. The priorities +* of the various sources can be dynamically altered as needed through +* hardware configuration. +* +* The generic interrupt controller supports the following +* features: +* +* - specific individual interrupt enabling/disabling +* - specific individual interrupt acknowledging +* - attaching specific callback function to handle interrupt source +* - assigning desired priority to interrupt source if default is not +* acceptable. +* +* Details about connecting the interrupt handler of the driver are contained +* in the source file specific to interrupt processing, xscugic_intr.c. +* +* This driver is intended to be RTOS and processor independent. It works with +* physical addresses only. Any needs for dynamic memory management, threads +* or thread mutual exclusion, virtual memory, or cache control must be +* satisfied by the layer above this driver. +* +* Interrupt Vector Tables +* +* The device ID of the interrupt controller device is used by the driver as a +* direct index into the configuration data table. The user should populate the +* vector table with handlers and callbacks at run-time using the +* XScuGic_Connect() and XScuGic_Disconnect() functions. +* +* Each vector table entry corresponds to a device that can generate an +* interrupt. Each entry contains an interrupt handler function and an +* argument to be passed to the handler when an interrupt occurs. The +* user must use XScuGic_Connect() when the interrupt handler takes an +* argument other than the base address. +* +* Nested Interrupts Processing +* +* Nested interrupts are not supported by this driver. +* +* NOTE: +* The generic interrupt controller is not a part of the snoop control unit +* as indicated by the prefix "scu" in the name of the driver. +* It is an independent module in APU. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- ---------------------------------------------------------
+* 1.00a drg  01/19/00 First release
+* 1.01a sdm  11/09/11 The XScuGic and XScuGic_Config structures have changed.
+*		      The HandlerTable (of type XScuGic_VectorTableEntry) is
+*		      moved to XScuGic_Config structure from XScuGic structure.
+*
+*		      The "Config" entry in XScuGic structure is made as
+*		      pointer for better efficiency.
+*
+*		      A new file named as xscugic_hw.c is now added. It is
+*		      to implement low level driver routines without using
+*		      any xscugic instance pointer. They are useful when the
+*		      user wants to use xscugic through device id or
+*		      base address. The driver routines provided are explained
+*		      below.
+*		      XScuGic_DeviceInitialize that takes device id as
+*		      argument and initializes the device (without calling
+*		      XScuGic_CfgInitialize).
+*		      XScuGic_DeviceInterruptHandler that takes device id
+*		      as argument and calls appropriate handlers from the
+*		      HandlerTable.
+*		      XScuGic_RegisterHandler that registers a new handler
+*		      by taking xscugic hardware base address as argument.
+*		      LookupConfigByBaseAddress is used to return the
+*		      corresponding config structure from XScuGic_ConfigTable
+*		      based on the scugic base address passed.
+* 1.02a sdm  12/20/11 Removed AckBeforeService from the XScuGic_Config
+*		      structure.
+* 1.03a srt  02/27/13 Moved Offset calculation macros from *.c and *_hw.c to
+*		      *_hw.h
+*		      Added APIs
+*			- XScuGic_SetPriTrigTypeByDistAddr()
+*			- XScuGic_GetPriTrigTypeByDistAddr()
+*		      (CR 702687)
+*			Added support to direct interrupts to the appropriate CPU. Earlier
+*			  interrupts were directed to CPU1 (hard coded). Now depending
+*			  upon the CPU selected by the user (xparameters.h), interrupts
+*			  will be directed to the relevant CPU. This fixes CR 699688.
+* 1.04a hk   05/04/13 Assigned EffectiveAddr to CpuBaseAddress in
+*			  XScuGic_CfgInitialize. Fix for CR#704400 to remove warnings.
+*			  Moved functions XScuGic_SetPriTrigTypeByDistAddr and
+*             XScuGic_GetPriTrigTypeByDistAddr to xscugic_hw.c.
+*			  This is fix for CR#705621.
+* 1.05a hk   06/26/13 Modified tcl to export external interrupts correctly to
+*                     xparameters.h. Fix for CR's 690505, 708928 & 719359.
+* 2.0   adk  12/10/13 Updated as per the New Tcl API's
+* 2.1   adk  25/04/14 Fixed the CR:789373 changes are made in the driver tcl file.
+* 3.00  kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.2   asa  02/29/16 Modified DistributorInit function for Zynq AMP case. The
+*			  distributor is left uninitialized for Zynq AMP. It is assumed
+*             that the distributor will be initialized by Linux master. However
+*             for CortexR5 case, the earlier code is left unchanged where the
+*             the interrupt processor target registers in the distributor is
+*             initialized with the corresponding CPU ID on which the application
+*             built over the scugic driver runs.
+*             These changes fix CR#937243.
+*
+* 3.4   asa  04/07/16 Created a new static function DoDistributorInit to simplify
+*            the flow and avoid code duplication. Changes are made for
+*            USE_AMP use case for R5. In a scenario (in R5 split mode) when
+*            one R5 is operating with A53 in open amp config and other
+*            R5 running baremetal app, the existing code
+*            had the potential to stop the whole AMP solution to work (if
+*            for some reason the R5 running the baremetal app tasked to
+*            initialize the Distributor hangs or crashes before initializing).
+*            Changes are made so that the R5 under AMP first checks if
+*            the distributor is enabled or not and if not, it does the
+*            standard Distributor initialization.
+*            This fixes the CR#952962.
+* 3.6   ms   01/23/17 Modified xil_printf statement in main function for all
+*                     examples to ensure that "Successfully ran" and "Failed"
+*                     strings are available in all examples. This is a fix
+*                     for CR-965028.
+*       kvn  02/17/17 Add support for changing GIC CPU master at run time.
+*       kvn  02/28/17 Make the CpuId as static variable and Added new
+*                     XScugiC_GetCpuId to access CpuId.
+*       ms   03/17/17 Added readme.txt file in examples folder for doxygen
+*                     generation.
+* 3.7   ms   04/11/17 Modified tcl file to add suffix U for all macro
+*                     definitions of scugic in xparameters.h
+* 3.8   mus  07/05/17 Updated scugic.tcl to add support for intrrupts connected
+*                     through util_reduced_vector IP(OR gate)
+*       mus  07/05/17 Updated xdefine_zynq_canonical_xpars proc to initialize
+*                     the HandlerTable in XScuGic_ConfigTable to 0, it removes
+*                     the compilation warning in xscugic_g.c. Fix for CR#978736.
+*       mus  07/25/17 Updated xdefine_gic_params proc to export correct canonical
+*                     definitions for pl to ps interrupts.Fix for CR#980534
+* 3.9   mus  02/21/18 Added new API's XScuGic_UnmapAllInterruptsFromCpu and
+*                     XScuGic_InterruptUnmapFromCpu, These API's can be used
+*                     by applications to unmap specific/all interrupts from
+*                     target CPU.
+* 3.10  aru  08/23/18 Resolved MISRA-C:2012 compliance mandatory violations
+* 4.0   mus  11/22/18 Fixed bugs in software interrupt generation through 
+*                      XScuGic_SoftwareIntr API
+*
+* 
+* +******************************************************************************/ + +#ifndef XSCUGIC_H /* prevent circular inclusions */ +#define XSCUGIC_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + + +/***************************** Include Files *********************************/ + +#include "xstatus.h" +#include "xil_io.h" +#include "xscugic_hw.h" +#include "xil_exception.h" + +/************************** Constant Definitions *****************************/ + +#define EFUSE_STATUS_OFFSET 0x10 +#define EFUSE_STATUS_CPU_MASK 0x80 + +#if !defined (ARMR5) && !defined (__aarch64__) && !defined (ARMA53_32) +#define ARMA9 +#endif + +#define XSCUGIC500_DCTLR_ARE_NS_ENABLE 0x20 +#define XSCUGIC500_DCTLR_ARE_S_ENABLE 0x10 +/**************************** Type Definitions *******************************/ + +/* The following data type defines each entry in an interrupt vector table. + * The callback reference is the base address of the interrupting device + * for the low level driver and an instance pointer for the high level driver. + */ +typedef struct +{ + Xil_InterruptHandler Handler; + void *CallBackRef; +} XScuGic_VectorTableEntry; + +/** + * This typedef contains configuration information for the device. + */ +typedef struct +{ + u16 DeviceId; /**< Unique ID of device */ + u32 CpuBaseAddress; /**< CPU Interface Register base address */ + u32 DistBaseAddress; /**< Distributor Register base address */ + XScuGic_VectorTableEntry HandlerTable[XSCUGIC_MAX_NUM_INTR_INPUTS];/**< + Vector table of interrupt handlers */ +} XScuGic_Config; + +/** + * The XScuGic driver instance data. The user is required to allocate a + * variable of this type for every intc device in the system. A pointer + * to a variable of this type is then passed to the driver API functions. + */ +typedef struct +{ + XScuGic_Config *Config; /**< Configuration table entry */ + u32 IsReady; /**< Device is initialized and ready */ + u32 UnhandledInterrupts; /**< Intc Statistics */ +} XScuGic; + +/***************** Macros (Inline Functions) Definitions *********************/ + +/****************************************************************************/ +/** +* +* Write the given CPU Interface register +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param RegOffset is the register offset to be written +* @param Data is the 32-bit value to write to the register +* +* @return None. +* +* @note +* C-style signature: +* void XScuGic_CPUWriteReg(XScuGic *InstancePtr, u32 RegOffset, u32 Data) +* +*****************************************************************************/ +#define XScuGic_CPUWriteReg(InstancePtr, RegOffset, Data) \ +(XScuGic_WriteReg(((InstancePtr)->Config->CpuBaseAddress), (RegOffset), \ + ((u32)(Data)))) + +/****************************************************************************/ +/** +* +* Read the given CPU Interface register +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param RegOffset is the register offset to be read +* +* @return The 32-bit value of the register +* +* @note +* C-style signature: +* u32 XScuGic_CPUReadReg(XScuGic *InstancePtr, u32 RegOffset) +* +*****************************************************************************/ +#define XScuGic_CPUReadReg(InstancePtr, RegOffset) \ + (XScuGic_ReadReg(((InstancePtr)->Config->CpuBaseAddress), (RegOffset))) + +/****************************************************************************/ +/** +* +* Write the given Distributor Interface register +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param RegOffset is the register offset to be written +* @param Data is the 32-bit value to write to the register +* +* @return None. +* +* @note +* C-style signature: +* void XScuGic_DistWriteReg(XScuGic *InstancePtr, u32 RegOffset, u32 Data) +* +*****************************************************************************/ +#define XScuGic_DistWriteReg(InstancePtr, RegOffset, Data) \ +(XScuGic_WriteReg(((InstancePtr)->Config->DistBaseAddress), (RegOffset), \ + ((u32)(Data)))) + +/****************************************************************************/ +/** +* +* Read the given Distributor Interface register +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param RegOffset is the register offset to be read +* +* @return The 32-bit value of the register +* +* @note +* C-style signature: +* u32 XScuGic_DistReadReg(XScuGic *InstancePtr, u32 RegOffset) +* +*****************************************************************************/ +#define XScuGic_DistReadReg(InstancePtr, RegOffset) \ +(XScuGic_ReadReg(((InstancePtr)->Config->DistBaseAddress), (RegOffset))) + +/****************************************************************************/ +/** +* +* Write the given ReDistributor Interface register +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param RegOffset is the register offset to be written +* @param Data is the 32-bit value to write to the register +* +* @return None. +* +* @note +* C-style signature: +* void XScuGic_DistWriteReg(XScuGic *InstancePtr, u32 RegOffset, u32 Data) +* +*****************************************************************************/ +#define XScuGic_ReDistWriteReg(InstancePtr, RegOffset, Data) \ +(XScuGic_WriteReg(((InstancePtr)->Config->DistBaseAddress)+ \ + XSCUGIC_RDIST_OFFSET, (RegOffset), ((u32)(Data)))) + +/****************************************************************************/ +/** +* +* Read the given ReDistributor Interface register +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param RegOffset is the register offset to be read +* +* @return The 32-bit value of the register +* +* @note +* C-style signature: +* u32 XScuGic_DistReadReg(XScuGic *InstancePtr, u32 RegOffset) +* +*****************************************************************************/ +#define XScuGic_ReDistReadReg(InstancePtr, RegOffset) \ +(XScuGic_ReadReg((((InstancePtr)->Config->DistBaseAddress)+ \ +XSCUGIC_RDIST_OFFSET), (RegOffset))) + +/****************************************************************************/ +/** +* +* Write the given ReDistributor SGI PPI Interface register +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param RegOffset is the register offset to be written +* @param Data is the 32-bit value to write to the register +* +* @return None. +* +* @note +* C-style signature: +* void XScuGic_DistWriteReg(XScuGic *InstancePtr, u32 RegOffset, u32 Data) +* +*****************************************************************************/ +#define XScuGic_ReDistSGIPPIWriteReg(InstancePtr, RegOffset, Data) \ +(XScuGic_WriteReg(((InstancePtr)->Config->DistBaseAddress)+ \ + XSCUGIC_RDIST_SGI_PPI_OFFSET, (RegOffset), ((u32)(Data)))) + +/****************************************************************************/ +/** +* +* Read the given ReDistributor SGI PPI Interface register +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param RegOffset is the register offset to be read +* +* @return The 32-bit value of the register +* +* @note +* C-style signature: +* u32 XScuGic_DistReadReg(XScuGic *InstancePtr, u32 RegOffset) +* +*****************************************************************************/ +#define XScuGic_ReDistSGIPPIReadReg(InstancePtr, RegOffset) \ +(XScuGic_ReadReg((((InstancePtr)->Config->DistBaseAddress)+ \ + XSCUGIC_RDIST_SGI_PPI_OFFSET), (RegOffset))) + +/****************************************************************************/ +/** +* This function enables system register interface for GIC CPU Interface +* +* @param value to be written +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +#define XScuGic_Enable_SystemReg_CPU_Interface_EL3() mtcp(S3_6_C12_C12_5, 0xF); +#define XScuGic_Enable_SystemReg_CPU_Interface_EL1() mtcp(S3_0_C12_C12_5, 0xF); +/****************************************************************************/ +/** +* This function enables Grou0 interrupts +* +* @param None. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +#define XScuGic_Enable_Group0_Interrupts() mtcp(S3_0_C12_C12_6,0x1); +/****************************************************************************/ +/** +* This function enables Group1 interrupts +* +* @param None. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +#if defined (__aarch64__) +#if EL1_NONSECURE +#define XScuGic_Enable_Group1_Interrupts() \ + mtcp (S3_0_C12_C12_7, 0x1 | mfcp(S3_0_C12_C12_7) ); +#else +#define XScuGic_Enable_Group1_Interrupts() \ + mtcp (S3_6_C12_C12_7, 0x1 | mfcp(S3_6_C12_C12_7) ); +#endif +#endif +/****************************************************************************/ +/** +* This function writes to ICC_SGI0R_EL1 +* +* @param value to be written +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +#define XScuGic_WriteICC_SGI0R_EL1(val) mtcp(S3_0_C12_C11_7,val) + +/****************************************************************************/ +/** +* This function writes to ICC_SGI1R_EL1 +* +* @param value to be written +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +#define XScuGic_WriteICC_SGI1R_EL1(val) mtcp(S3_0_C12_C11_5,val) + +/****************************************************************************/ +/** +* This function reads ICC_SGI1R_EL1 register +* +* @param None +* +* @return Value of ICC_SGI1R_EL1 register +* +* @note None. +* +*****************************************************************************/ +#define XScuGic_ReadICC_SGI1R_EL1() mfcp(S3_0_C12_C11_5) +/****************************************************************************/ +/** +* This function sets interrupt priority filter +* +* @param None. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +#define XScuGic_set_priority_filter(val) __asm__ __volatile__("msr S3_0_C4_C6_0,%0" : : "r" (val)) +/****************************************************************************/ +/** +* This function returns interrupt id of highest priority pending interrupt +* +* @param None. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +#if defined (__aarch64__) +#if EL3 +#define XScuGic_get_IntID() mfcp(S3_0_C12_C8_0) +#else +#define XScuGic_get_IntID() mfcp(S3_0_C12_C12_0) +#endif +#endif +/****************************************************************************/ +/** +* This function acks the interrupt +* +* @param None. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +#if defined (__aarch64__) +#if EL3 +#define XScuGic_ack_Int(val) mtcp(S3_0_C12_C8_1,val) +#else +#define XScuGic_ack_Int(val) mtcp(S3_0_C12_C12_1,val) +#endif +#endif +/****************************************************************************/ +/** +* This macro returns bit position for the specific interrupt's trigger type +* configuration within GICR_ICFGR0/GICR_ICFGR1 register +* +* @param None. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +#define XScuGic_Get_Rdist_Int_Trigger_Index(IntrId) (((Int_Id%16) & 0x1f) << 2) +1 +/************************** Function Prototypes ******************************/ + +/* + * Required functions in xscugic.c + */ + +s32 XScuGic_Connect(XScuGic *InstancePtr, u32 Int_Id, + Xil_InterruptHandler Handler, void *CallBackRef); +void XScuGic_Disconnect(XScuGic *InstancePtr, u32 Int_Id); + +void XScuGic_Enable(XScuGic *InstancePtr, u32 Int_Id); +void XScuGic_Disable(XScuGic *InstancePtr, u32 Int_Id); + +s32 XScuGic_CfgInitialize(XScuGic *InstancePtr, XScuGic_Config *ConfigPtr, + u32 EffectiveAddr); + +s32 XScuGic_SoftwareIntr(XScuGic *InstancePtr, u32 Int_Id, u32 Cpu_Id); + +void XScuGic_GetPriorityTriggerType(XScuGic *InstancePtr, u32 Int_Id, + u8 *Priority, u8 *Trigger); +void XScuGic_SetPriorityTriggerType(XScuGic *InstancePtr, u32 Int_Id, + u8 Priority, u8 Trigger); +void XScuGic_InterruptMaptoCpu(XScuGic *InstancePtr, u8 Cpu_Id, u32 Int_Id); +void XScuGic_InterruptUnmapFromCpu(XScuGic *InstancePtr, u8 Cpu_Id, u32 Int_Id); +void XScuGic_UnmapAllInterruptsFromCpu(XScuGic *InstancePtr, u8 Cpu_Id); +void XScuGic_Stop(XScuGic *InstancePtr); +void XScuGic_SetCpuID(u32 CpuCoreId); +u32 XScuGic_GetCpuID(void); +/* + * Initialization functions in xscugic_sinit.c + */ +XScuGic_Config *XScuGic_LookupConfig(u16 DeviceId); + +/* + * Interrupt functions in xscugic_intr.c + */ +void XScuGic_InterruptHandler(XScuGic *InstancePtr); + +/* + * Self-test functions in xscugic_selftest.c + */ +s32 XScuGic_SelfTest(XScuGic *InstancePtr); + +void XScuGic_EnableSGI_PPI(XScuGic *InstancePtr,u32 ID); +void XScuGic_SetPPI_SGI_Priority(XScuGic *InstancePtr,u32 ID, u32 priority); +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/include/xscugic_hw.h b/df_datalink/bsp/ps7_cortexa9_0/include/xscugic_hw.h new file mode 100644 index 0000000..60d111f --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/include/xscugic_hw.h @@ -0,0 +1,753 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xscugic_hw.h +* @addtogroup scugic_v4_0 +* @{ +* +* This header file contains identifiers and HW access functions (or +* macros) that can be used to access the device. The user should refer to the +* hardware device specification for more details of the device operation. +* The driver functions/APIs are defined in xscugic.h. +* +* This GIC device has two parts, a distributor and CPU interface(s). Each part +* has separate register definition sections. +* +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------------
+* 1.00a drg  01/19/10 First release
+* 1.01a sdm  11/09/11 "xil_exception.h" added as include.
+*		      Macros XScuGic_EnableIntr and XScuGic_DisableIntr are
+*		      added to enable or disable interrupts based on
+*		      Distributor Register base address. Normally users use
+*		      XScuGic instance and call XScuGic_Enable or
+*		      XScuGic_Disable to enable/disable interrupts. These
+*		      new macros are provided when user does not want to
+*		      use an instance pointer but still wants to enable or
+*		      disable interrupts.
+*		      Function prototypes for functions (present in newly
+*		      added file xscugic_hw.c) are added.
+* 1.03a srt  02/27/13 Moved Offset calculation macros from *_hw.c (CR
+*		      702687).
+* 1.04a hk   05/04/13 Fix for CR#705621. Moved function prototypes
+*		      XScuGic_SetPriTrigTypeByDistAddr and
+*         	      XScuGic_GetPriTrigTypeByDistAddr here from xscugic.h
+* 3.0	pkp  12/09/14 changed XSCUGIC_MAX_NUM_INTR_INPUTS for
+*		      Zynq Ultrascale Mp
+* 3.0   kvn  02/13/14 Modified code for MISRA-C:2012 compliance.
+* 3.2	pkp  11/09/15 Corrected the interrupt processsor target mask value
+*					  for CPU interface 2 i.e. XSCUGIC_SPI_CPU2_MASK
+* 3.9   mus  02/21/18 Added new API's XScuGic_InterruptUnmapFromCpuByDistAddr
+*					  and XScuGic_UnmapAllInterruptsFromCpuByDistAddr, These
+*					  API's can be used by applications to unmap specific/all
+*					  interrupts from target CPU. It fixes CR#992490.
+* 3.10  aru  08/23/18 Resolved MISRA-C:2012 compliance mandatory violations
+*
+* 
+* +******************************************************************************/ + +#ifndef XSCUGIC_HW_H /* prevent circular inclusions */ +#define XSCUGIC_HW_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_io.h" +#include "xil_exception.h" +#include "bspconfig.h" + +/************************** Constant Definitions *****************************/ + +/* + * The maximum number of interrupts supported by the hardware. + */ +#ifdef PLATFORM_ZYNQ +#define XSCUGIC_MAX_NUM_INTR_INPUTS 95U /* Maximum number of interrupt defined by Zynq */ +#elif defined (versal) && !defined(ARMR5) +#define XSCUGIC_MAX_NUM_INTR_INPUTS 191U +#else +#define XSCUGIC_MAX_NUM_INTR_INPUTS 195U /* Maximum number of interrupt defined by Zynq Ultrascale Mp */ +#endif + +/* + * First Interrupt Id for SPI interrupts. + */ +#define XSCUGIC_SPI_INT_ID_START 0x20 +/* + * The maximum priority value that can be used in the GIC. + */ +#define XSCUGIC_MAX_INTR_PRIO_VAL 248U +#define XSCUGIC_INTR_PRIO_MASK 0x000000F8U + +/** @name Distributor Interface Register Map + * + * Define the offsets from the base address for all Distributor registers of + * the interrupt controller, some registers may be reserved in the hardware + * device. + * @{ + */ +#define XSCUGIC_DIST_EN_OFFSET 0x00000000U /**< Distributor Enable + Register */ +#define XSCUGIC_IC_TYPE_OFFSET 0x00000004U /**< Interrupt Controller + Type Register */ +#define XSCUGIC_DIST_IDENT_OFFSET 0x00000008U /**< Implementor ID + Register */ +#define XSCUGIC_SECURITY_OFFSET 0x00000080U /**< Interrupt Security + Register */ +#define XSCUGIC_ENABLE_SET_OFFSET 0x00000100U /**< Enable Set + Register */ +#define XSCUGIC_DISABLE_OFFSET 0x00000180U /**< Enable Clear Register */ +#define XSCUGIC_PENDING_SET_OFFSET 0x00000200U /**< Pending Set + Register */ +#define XSCUGIC_PENDING_CLR_OFFSET 0x00000280U /**< Pending Clear + Register */ +#define XSCUGIC_ACTIVE_OFFSET 0x00000300U /**< Active Status Register */ +#define XSCUGIC_PRIORITY_OFFSET 0x00000400U /**< Priority Level Register */ +#define XSCUGIC_SPI_TARGET_OFFSET 0x00000800U /**< SPI Target + Register 0x800-0x8FB */ +#define XSCUGIC_INT_CFG_OFFSET 0x00000C00U /**< Interrupt Configuration + Register 0xC00-0xCFC */ +#define XSCUGIC_PPI_STAT_OFFSET 0x00000D00U /**< PPI Status Register */ +#define XSCUGIC_SPI_STAT_OFFSET 0x00000D04U /**< SPI Status Register + 0xd04-0xd7C */ +#define XSCUGIC_AHB_CONFIG_OFFSET 0x00000D80U /**< AHB Configuration + Register */ +#define XSCUGIC_SFI_TRIG_OFFSET 0x00000F00U /**< Software Triggered + Interrupt Register */ +#define XSCUGIC_PERPHID_OFFSET 0x00000FD0U /**< Peripheral ID Reg */ +#if defined (versal) && !defined(ARMR5) +#define XSCUGIC_PCELLID_OFFSET 0x0000FFF0U /**< Pcell ID Register */ +#else +#define XSCUGIC_PCELLID_OFFSET 0x00000FF0U /**< Pcell ID Register */ +#endif +/* @} */ + +/** @name Distributor Enable Register + * Controls if the distributor response to external interrupt inputs. + * @{ + */ +#if defined (versal) && !defined(ARMR5) +#define XSCUGIC_EN_INT_MASK 0x00000003U /**< Interrupt In Enable */ +#else +#define XSCUGIC_EN_INT_MASK 0x00000001U /**< Interrupt In Enable */ +#endif +/* @} */ + +/** @name Interrupt Controller Type Register + * @{ + */ +#define XSCUGIC_LSPI_MASK 0x0000F800U /**< Number of Lockable + Shared Peripheral + Interrupts*/ +#define XSCUGIC_DOMAIN_MASK 0x00000400U /**< Number os Security domains*/ +#define XSCUGIC_CPU_NUM_MASK 0x000000E0U /**< Number of CPU Interfaces */ +#define XSCUGIC_NUM_INT_MASK 0x0000001FU /**< Number of Interrupt IDs */ +/* @} */ + +/** @name Implementor ID Register + * Implementor and revision information. + * @{ + */ +#define XSCUGIC_REV_MASK 0x00FFF000U /**< Revision Number */ +#define XSCUGIC_IMPL_MASK 0x00000FFFU /**< Implementor */ +/* @} */ + +/** @name Interrupt Security Registers + * Each bit controls the security level of an interrupt, either secure or non + * secure. These registers can only be accessed using secure read and write. + * There are registers for each of the CPU interfaces at offset 0x080. A + * register set for the SPI interrupts is available to all CPU interfaces. + * There are up to 32 of these registers staring at location 0x084. + * @{ + */ +#define XSCUGIC_INT_NS_MASK 0x00000001U /**< Each bit corresponds to an + INT_ID */ +/* @} */ + +/** @name Enable Set Register + * Each bit controls the enabling of an interrupt, a 0 is disabled, a 1 is + * enabled. Writing a 0 has no effect. Use the ENABLE_CLR register to set a + * bit to 0. + * There are registers for each of the CPU interfaces at offset 0x100. With up + * to 8 registers aliased to the same address. A register set for the SPI + * interrupts is available to all CPU interfaces. + * There are up to 32 of these registers staring at location 0x104. + * @{ + */ +#define XSCUGIC_INT_EN_MASK 0x00000001U /**< Each bit corresponds to an + INT_ID */ +/* @} */ + +/** @name Enable Clear Register + * Each bit controls the disabling of an interrupt, a 0 is disabled, a 1 is + * enabled. Writing a 0 has no effect. Writing a 1 disables an interrupt and + * sets the corresponding bit to 0. + * There are registers for each of the CPU interfaces at offset 0x180. With up + * to 8 registers aliased to the same address. + * A register set for the SPI interrupts is available to all CPU interfaces. + * There are up to 32 of these registers staring at location 0x184. + * @{ + */ +#define XSCUGIC_INT_CLR_MASK 0x00000001U /**< Each bit corresponds to an + INT_ID */ +/* @} */ + +/** @name Pending Set Register + * Each bit controls the Pending or Active and Pending state of an interrupt, a + * 0 is not pending, a 1 is pending. Writing a 0 has no effect. Writing a 1 sets + * an interrupt to the pending state. + * There are registers for each of the CPU interfaces at offset 0x200. With up + * to 8 registers aliased to the same address. + * A register set for the SPI interrupts is available to all CPU interfaces. + * There are up to 32 of these registers staring at location 0x204. + * @{ + */ +#define XSCUGIC_PEND_SET_MASK 0x00000001U /**< Each bit corresponds to an + INT_ID */ +/* @} */ + +/** @name Pending Clear Register + * Each bit can clear the Pending or Active and Pending state of an interrupt, a + * 0 is not pending, a 1 is pending. Writing a 0 has no effect. Writing a 1 + * clears the pending state of an interrupt. + * There are registers for each of the CPU interfaces at offset 0x280. With up + * to 8 registers aliased to the same address. + * A register set for the SPI interrupts is available to all CPU interfaces. + * There are up to 32 of these registers staring at location 0x284. + * @{ + */ +#define XSCUGIC_PEND_CLR_MASK 0x00000001U /**< Each bit corresponds to an + INT_ID */ +/* @} */ + +/** @name Active Status Register + * Each bit provides the Active status of an interrupt, a + * 0 is not Active, a 1 is Active. This is a read only register. + * There are registers for each of the CPU interfaces at offset 0x300. With up + * to 8 registers aliased to each address. + * A register set for the SPI interrupts is available to all CPU interfaces. + * There are up to 32 of these registers staring at location 0x380. + * @{ + */ +#define XSCUGIC_ACTIVE_MASK 0x00000001U /**< Each bit corresponds to an + INT_ID */ +/* @} */ + +/** @name Priority Level Register + * Each byte in a Priority Level Register sets the priority level of an + * interrupt. Reading the register provides the priority level of an interrupt. + * There are registers for each of the CPU interfaces at offset 0x400 through + * 0x41C. With up to 8 registers aliased to each address. + * 0 is highest priority, 0xFF is lowest. + * A register set for the SPI interrupts is available to all CPU interfaces. + * There are up to 255 of these registers staring at location 0x420. + * @{ + */ +#define XSCUGIC_PRIORITY_MASK 0x000000FFU /**< Each Byte corresponds to an + INT_ID */ +#define XSCUGIC_PRIORITY_MAX 0x000000FFU /**< Highest value of a priority + actually the lowest priority*/ +/* @} */ + +/** @name SPI Target Register 0x800-0x8FB + * Each byte references a separate SPI and programs which of the up to 8 CPU + * interfaces are sent a Pending interrupt. + * There are registers for each of the CPU interfaces at offset 0x800 through + * 0x81C. With up to 8 registers aliased to each address. + * A register set for the SPI interrupts is available to all CPU interfaces. + * There are up to 255 of these registers staring at location 0x820. + * + * This driver does not support multiple CPU interfaces. These are included + * for complete documentation. + * @{ + */ +#define XSCUGIC_SPI_CPU7_MASK 0x00000080U /**< CPU 7 Mask*/ +#define XSCUGIC_SPI_CPU6_MASK 0x00000040U /**< CPU 6 Mask*/ +#define XSCUGIC_SPI_CPU5_MASK 0x00000020U /**< CPU 5 Mask*/ +#define XSCUGIC_SPI_CPU4_MASK 0x00000010U /**< CPU 4 Mask*/ +#define XSCUGIC_SPI_CPU3_MASK 0x00000008U /**< CPU 3 Mask*/ +#define XSCUGIC_SPI_CPU2_MASK 0x00000004U /**< CPU 2 Mask*/ +#define XSCUGIC_SPI_CPU1_MASK 0x00000002U /**< CPU 1 Mask*/ +#define XSCUGIC_SPI_CPU0_MASK 0x00000001U /**< CPU 0 Mask*/ +/* @} */ + +/** @name Interrupt Configuration Register 0xC00-0xCFC + * The interrupt configuration registers program an SFI to be active HIGH level + * sensitive or rising edge sensitive. + * Each bit pair describes the configuration for an INT_ID. + * SFI Read Only b10 always + * PPI Read Only depending on how the PPIs are configured. + * b01 Active HIGH level sensitive + * b11 Rising edge sensitive + * SPI LSB is read only. + * b01 Active HIGH level sensitive + * b11 Rising edge sensitive/ + * There are registers for each of the CPU interfaces at offset 0xC00 through + * 0xC04. With up to 8 registers aliased to each address. + * A register set for the SPI interrupts is available to all CPU interfaces. + * There are up to 255 of these registers staring at location 0xC08. + * @{ + */ +#define XSCUGIC_INT_CFG_MASK 0x00000003U /**< */ +/* @} */ + +/** @name PPI Status Register + * Enables an external AMBA master to access the status of the PPI inputs. + * A CPU can only read the status of its local PPI signals and cannot read the + * status for other CPUs. + * This register is aliased for each CPU interface. + * @{ + */ +#define XSCUGIC_PPI_C15_MASK 0x00008000U /**< PPI Status */ +#define XSCUGIC_PPI_C14_MASK 0x00004000U /**< PPI Status */ +#define XSCUGIC_PPI_C13_MASK 0x00002000U /**< PPI Status */ +#define XSCUGIC_PPI_C12_MASK 0x00001000U /**< PPI Status */ +#define XSCUGIC_PPI_C11_MASK 0x00000800U /**< PPI Status */ +#define XSCUGIC_PPI_C10_MASK 0x00000400U /**< PPI Status */ +#define XSCUGIC_PPI_C09_MASK 0x00000200U /**< PPI Status */ +#define XSCUGIC_PPI_C08_MASK 0x00000100U /**< PPI Status */ +#define XSCUGIC_PPI_C07_MASK 0x00000080U /**< PPI Status */ +#define XSCUGIC_PPI_C06_MASK 0x00000040U /**< PPI Status */ +#define XSCUGIC_PPI_C05_MASK 0x00000020U /**< PPI Status */ +#define XSCUGIC_PPI_C04_MASK 0x00000010U /**< PPI Status */ +#define XSCUGIC_PPI_C03_MASK 0x00000008U /**< PPI Status */ +#define XSCUGIC_PPI_C02_MASK 0x00000004U /**< PPI Status */ +#define XSCUGIC_PPI_C01_MASK 0x00000002U /**< PPI Status */ +#define XSCUGIC_PPI_C00_MASK 0x00000001U /**< PPI Status */ +/* @} */ + +/** @name SPI Status Register 0xd04-0xd7C + * Enables an external AMBA master to access the status of the SPI inputs. + * There are up to 63 registers if the maximum number of SPI inputs are + * configured. + * @{ + */ +#define XSCUGIC_SPI_N_MASK 0x00000001U /**< Each bit corresponds to an SPI + input */ +/* @} */ + +/** @name AHB Configuration Register + * Provides the status of the CFGBIGEND input signal and allows the endianess + * of the GIC to be set. + * @{ + */ +#define XSCUGIC_AHB_END_MASK 0x00000004U /**< 0-GIC uses little Endian, + 1-GIC uses Big Endian */ +#define XSCUGIC_AHB_ENDOVR_MASK 0x00000002U /**< 0-Uses CFGBIGEND control, + 1-use the AHB_END bit */ +#define XSCUGIC_AHB_TIE_OFF_MASK 0x00000001U /**< State of CFGBIGEND */ + +/* @} */ + +/** @name Software Triggered Interrupt Register + * Controls issueing of software interrupts. + * @{ + */ +#define XSCUGIC_SFI_SELFTRIG_MASK 0x02010000U +#define XSCUGIC_SFI_TRIG_TRGFILT_MASK 0x03000000U /**< Target List filter + b00-Use the target List + b01-All CPUs except requester + b10-To Requester + b11-reserved */ +#define XSCUGIC_SFI_TRIG_CPU_MASK 0x00FF0000U /**< CPU Target list */ +#define XSCUGIC_SFI_TRIG_SATT_MASK 0x00008000U /**< 0= Use a secure interrupt */ +#define XSCUGIC_SFI_TRIG_INTID_MASK 0x0000000FU /**< Set to the INTID + signaled to the CPU*/ +/* @} */ + +/** @name CPU Interface Register Map + * + * Define the offsets from the base address for all CPU registers of the + * interrupt controller, some registers may be reserved in the hardware device. + * @{ + */ +#define XSCUGIC_CONTROL_OFFSET 0x00000000U /**< CPU Interface Control + Register */ +#define XSCUGIC_CPU_PRIOR_OFFSET 0x00000004U /**< Priority Mask Reg */ +#define XSCUGIC_BIN_PT_OFFSET 0x00000008U /**< Binary Point Register */ +#define XSCUGIC_INT_ACK_OFFSET 0x0000000CU /**< Interrupt ACK Reg */ +#define XSCUGIC_EOI_OFFSET 0x00000010U /**< End of Interrupt Reg */ +#define XSCUGIC_RUN_PRIOR_OFFSET 0x00000014U /**< Running Priority Reg */ +#define XSCUGIC_HI_PEND_OFFSET 0x00000018U /**< Highest Pending Interrupt + Register */ +#define XSCUGIC_ALIAS_BIN_PT_OFFSET 0x0000001CU /**< Aliased non-Secure + Binary Point Register */ + +/**< 0x00000020 to 0x00000FBC are reserved and should not be read or written + * to. */ +/* @} */ + + +/** @name Control Register + * CPU Interface Control register definitions + * All bits are defined here although some are not available in the non-secure + * mode. + * @{ + */ +#define XSCUGIC_CNTR_SBPR_MASK 0x00000010U /**< Secure Binary Pointer, + 0=separate registers, + 1=both use bin_pt_s */ +#define XSCUGIC_CNTR_FIQEN_MASK 0x00000008U /**< Use nFIQ_C for secure + interrupts, + 0= use IRQ for both, + 1=Use FIQ for secure, IRQ for non*/ +#define XSCUGIC_CNTR_ACKCTL_MASK 0x00000004U /**< Ack control for secure or non secure */ +#define XSCUGIC_CNTR_EN_NS_MASK 0x00000002U /**< Non Secure enable */ +#define XSCUGIC_CNTR_EN_S_MASK 0x00000001U /**< Secure enable, 0=Disabled, 1=Enabled */ +/* @} */ + +/** @name Priority Mask Register + * Priority Mask register definitions + * The CPU interface does not send interrupt if the level of the interrupt is + * lower than the level of the register. + * @{ + */ +/*#define XSCUGIC_PRIORITY_MASK 0x000000FFU*/ /**< All interrupts */ +/* @} */ + +/** @name Binary Point Register + * Binary Point register definitions + * @{ + */ + +#define XSCUGIC_BIN_PT_MASK 0x00000007U /**< Binary point mask value + Value Secure Non-secure + b000 0xFE 0xFF + b001 0xFC 0xFE + b010 0xF8 0xFC + b011 0xF0 0xF8 + b100 0xE0 0xF0 + b101 0xC0 0xE0 + b110 0x80 0xC0 + b111 0x00 0x80 + */ +/*@}*/ + +/** @name Interrupt Acknowledge Register + * Interrupt Acknowledge register definitions + * Identifies the current Pending interrupt, and the CPU ID for software + * interrupts. + */ +#define XSCUGIC_ACK_INTID_MASK 0x000003FFU /**< Interrupt ID */ +#define XSCUGIC_CPUID_MASK 0x00000C00U /**< CPU ID */ +/* @} */ + +/** @name End of Interrupt Register + * End of Interrupt register definitions + * Allows the CPU to signal the GIC when it completes an interrupt service + * routine. + */ +#define XSCUGIC_EOI_INTID_MASK 0x000003FFU /**< Interrupt ID */ + +/* @} */ + +/** @name Running Priority Register + * Running Priority register definitions + * Identifies the interrupt priority level of the highest priority active + * interrupt. + */ +#define XSCUGIC_RUN_PRIORITY_MASK 0x000000FFU /**< Interrupt Priority */ +/* @} */ + +#if defined (versal) && !defined(ARMR5) +#define XSCUGIC_IROUTER_BASE_OFFSET 0x6000U +#endif +/* + * Highest Pending Interrupt register definitions + * Identifies the interrupt priority of the highest priority pending interupt + */ +#define XSCUGIC_PEND_INTID_MASK 0x000003FFU /**< Pending Interrupt ID */ +/*#define XSCUGIC_CPUID_MASK 0x00000C00U */ /**< CPU ID */ +/* @} */ +#if defined (versal) && !defined(ARMR5) +/** @name ReDistributor Interface Register Map + * + * @{ + */ +#define XSCUGIC_RDIST_OFFSET 0x80000U +#define XSCUGIC_RDIST_BASE_ADDRESS (XPAR_SCUGIC_0_DIST_BASEADDR + XSCUGIC_RDIST_OFFSET) +#define XSCUGIC_RDIST_SGI_PPI_OFFSET 0x90000U +#define XSCUGIC_RDIST_SGI_PPI_BASE_ADDRESS (XPAR_SCUGIC_0_DIST_BASEADDR + XSCUGIC_RDIST_SGI_PPI_OFFSET) +#define XSCUGIC_RDIST_ISENABLE_OFFSET 0x100U +#define XSCUGIC_RDIST_IPRIORITYR_OFFSET 0x400U +#define XSCUGIC_RDIST_IGROUPR_OFFSET 0x80U +#define XSCUGIC_RDIST_GRPMODR_OFFSET 0xD00U +#define XSCUGIC_RDIST_INT_CONFIG_OFFSET 0xC00U +#define XSCUGIC_RDIST_WAKER_OFFSET 0x14U +#define XSCUGIC_SGIR_EL1_INITID_SHIFT 24U + +/* + * GICR_IGROUPR register definitions + */ +#if EL3 +#define XSCUGIC_DEFAULT_SECURITY 0x0U +#else +#define XSCUGIC_DEFAULT_SECURITY 0xFFFFFFFFU +#endif +/* + * GICR_WAKER register definitions + */ +#define XSCUGIC_RDIST_WAKER_LOW_POWER_STATE_MASK 0x7 +#endif +/***************** Macros (Inline Functions) Definitions *********************/ + +/****************************************************************************/ +/** +* +* Read the Interrupt Configuration Register offset for an interrupt id. +* +* @param InterruptID is the interrupt number. +* +* @return The 32-bit value of the offset +* +* @note +* +*****************************************************************************/ +#define XSCUGIC_INT_CFG_OFFSET_CALC(InterruptID) \ + ((u32)XSCUGIC_INT_CFG_OFFSET + (((InterruptID)/16U) * 4U)) + +/****************************************************************************/ +/** +* +* Read the Interrupt Priority Register offset for an interrupt id. +* +* @param InterruptID is the interrupt number. +* +* @return The 32-bit value of the offset +* +* @note +* +*****************************************************************************/ +#define XSCUGIC_PRIORITY_OFFSET_CALC(InterruptID) \ + ((u32)XSCUGIC_PRIORITY_OFFSET + (((InterruptID)/4U) * 4U)) + +/****************************************************************************/ +/** +* +* Read the Interrupt Routing Register offset for an interrupt id. +* +* @param InterruptID is the interrupt number. +* +* @return The 32-bit value of the offset +* +* @note +* +*****************************************************************************/ +#define XSCUGIC_IROUTER_OFFSET_CALC(InterruptID) \ + ((u32)XSCUGIC_IROUTER_BASE_OFFSET + (InterruptID * 8)) + +/****************************************************************************/ +/** +* +* Read the SPI Target Register offset for an interrupt id. +* +* @param InterruptID is the interrupt number. +* +* @return The 32-bit value of the offset +* +* @note +* +*****************************************************************************/ +#define XSCUGIC_SPI_TARGET_OFFSET_CALC(InterruptID) \ + ((u32)XSCUGIC_SPI_TARGET_OFFSET + (((InterruptID)/4U) * 4U)) +/****************************************************************************/ +/** +* +* Read the SPI Target Register offset for an interrupt id. +* +* @param InterruptID is the interrupt number. +* +* @return The 32-bit value of the offset +* +* @note +* +*****************************************************************************/ +#define XSCUGIC_SECURITY_TARGET_OFFSET_CALC(InterruptID) \ + ((u32)XSCUGIC_SECURITY_OFFSET + (((InterruptID)/32U)*4U)) + +/****************************************************************************/ +/** +* +* Read the Re-distributor Interrupt configuration register offset +* +* @param InterruptID is the interrupt number. +* +* @return The 32-bit value of the offset +* +* @note +* +*****************************************************************************/ +#define XSCUGIC_RDIST_INT_CONFIG_OFFSET_CALC(InterruptID) \ + ((u32)XSCUGIC_RDIST_INT_CONFIG_OFFSET + ((InterruptID /16)*4)) + +/****************************************************************************/ +/** +* +* Read the Re-distributor Interrupt Priority register offset +* +* @param InterruptID is the interrupt number. +* +* @return The 32-bit value of the offset +* +* @note +* +*****************************************************************************/ +#define XSCUGIC_RDIST_INT_PRIORITY_OFFSET_CALC(InterruptID) \ + ((u32)XSCUGIC_RDIST_IPRIORITYR_OFFSET + (InterruptID * 4)) +/****************************************************************************/ +/** +* +* Read the Interrupt Clear-Enable Register offset for an interrupt ID +* +* @param Register is the register offset for the clear/enable bank. +* @param InterruptID is the interrupt number. +* +* @return The 32-bit value of the offset +* +* @note +* +*****************************************************************************/ +#define XSCUGIC_EN_DIS_OFFSET_CALC(Register, InterruptID) \ + ((Register) + (((InterruptID)/32U) * 4U)) + +/****************************************************************************/ +/** +* +* Read the given Intc register. +* +* @param BaseAddress is the base address of the device. +* @param RegOffset is the register offset to be read +* +* @return The 32-bit value of the register +* +* @note +* C-style signature: +* u32 XScuGic_ReadReg(u32 BaseAddress, u32 RegOffset) +* +*****************************************************************************/ +#define XScuGic_ReadReg(BaseAddress, RegOffset) \ + (Xil_In32((BaseAddress) + (RegOffset))) + + +/****************************************************************************/ +/** +* +* Write the given Intc register. +* +* @param BaseAddress is the base address of the device. +* @param RegOffset is the register offset to be written +* @param Data is the 32-bit value to write to the register +* +* @return None. +* +* @note +* C-style signature: +* void XScuGic_WriteReg(u32 BaseAddress, u32 RegOffset, u32 Data) +* +*****************************************************************************/ +#define XScuGic_WriteReg(BaseAddress, RegOffset, Data) \ + (Xil_Out32(((BaseAddress) + (RegOffset)), ((u32)(Data)))) + + +/****************************************************************************/ +/** +* +* Enable specific interrupt(s) in the interrupt controller. +* +* @param DistBaseAddress is the Distributor Register base address of the +* device +* @param Int_Id is the ID of the interrupt source and should be in the +* range of 0 to XSCUGIC_MAX_NUM_INTR_INPUTS - 1 +* +* @return None. +* +* @note C-style signature: +* void XScuGic_EnableIntr(u32 DistBaseAddress, u32 Int_Id) +* +*****************************************************************************/ +#define XScuGic_EnableIntr(DistBaseAddress, Int_Id) \ + XScuGic_WriteReg((DistBaseAddress), \ + XSCUGIC_ENABLE_SET_OFFSET + (((Int_Id) / 32U) * 4U), \ + (0x00000001U << ((Int_Id) % 32U))) + +/****************************************************************************/ +/** +* +* Disable specific interrupt(s) in the interrupt controller. +* +* @param DistBaseAddress is the Distributor Register base address of the +* device +* @param Int_Id is the ID of the interrupt source and should be in the +* range of 0 to XSCUGIC_MAX_NUM_INTR_INPUTS - 1 +* +* +* @return None. +* +* @note C-style signature: +* void XScuGic_DisableIntr(u32 DistBaseAddress, u32 Int_Id) +* +*****************************************************************************/ +#define XScuGic_DisableIntr(DistBaseAddress, Int_Id) \ + XScuGic_WriteReg((DistBaseAddress), \ + XSCUGIC_DISABLE_OFFSET + (((Int_Id) / 32U) * 4U), \ + (0x00000001U << ((Int_Id) % 32U))) + + +/************************** Function Prototypes ******************************/ + +void XScuGic_DeviceInterruptHandler(void *DeviceId); +s32 XScuGic_DeviceInitialize(u32 DeviceId); +void XScuGic_RegisterHandler(u32 BaseAddress, s32 InterruptID, + Xil_InterruptHandler Handler, void *CallBackRef); +void XScuGic_SetPriTrigTypeByDistAddr(u32 DistBaseAddress, u32 Int_Id, + u8 Priority, u8 Trigger); +void XScuGic_GetPriTrigTypeByDistAddr(u32 DistBaseAddress, u32 Int_Id, + u8 *Priority, u8 *Trigger); +void XScuGic_InterruptUnmapFromCpuByDistAddr(u32 DistBaseAddress, + u8 Cpu_Id, u32 Int_Id); +void XScuGic_UnmapAllInterruptsFromCpuByDistAddr(u32 DistBaseAddress, + u8 Cpu_Id); +/************************** Variable Definitions *****************************/ +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/include/xscutimer.h b/df_datalink/bsp/ps7_cortexa9_0/include/xscutimer.h new file mode 100644 index 0000000..5434684 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/include/xscutimer.h @@ -0,0 +1,364 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xscutimer.h +* @addtogroup scutimer_v2_1 +* @{ +* @details +* +* The timer driver supports the Cortex A9 private timer. +* +* The timer driver supports the following features: +* - Normal mode and Auto reload mode +* - Interrupts (Interrupt handler is not provided in this driver. Application +* has to register it's own handler) +* +* Initialization and Configuration +* +* The device driver enables higher layer software (e.g., an application) to +* communicate with the Timer. +* +* XScuTimer_CfgInitialize() API is used to initialize the Timer. The +* user needs to first call the XScuTimer_LookupConfig() API which returns +* the Configuration structure pointer which is passed as a parameter to +* the XScuTimer_CfgInitialize() API. +* +* Interrupts +* +* The Timer hardware supports interrupts. +* +* This driver does not provide a Interrupt Service Routine (ISR) for the device. +* It is the responsibility of the application to provide one if needed. Refer to +* the interrupt example provided with this driver for details on using the +* Timer in interrupt mode. +* +* Virtual Memory +* +* This driver supports Virtual Memory. The RTOS is responsible for calculating +* the correct device base address in Virtual Memory space. +* +* Threads +* +* This driver is not thread safe. Any needs for threads or thread mutual +* exclusion must be satisfied by the layer above this driver. +* +* Asserts +* +* Asserts are used within all Xilinx drivers to enforce constraints on argument +* values. Asserts can be turned off on a system-wide basis by defining, at +* compile time, the NDEBUG identifier. By default, asserts are turned on and it +* is recommended that users leave asserts on during development. +* +* Building the driver +* +* The XScuTimer driver is composed of several source files. This allows the user +* to build and link only those parts of the driver that are necessary. +* +*

+* +* NOTE: +* The timer is not a part of the snoop control unit as indicated by the +* prefix "scu" in the name of the driver. +* It is an independent module in APU. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 1.00a nm  03/10/10 First release
+* 1.02a sg  07/17/12 Included xil_assert.h for CR 667947. This is an issue
+*		     when the xstatus.h in the common driver overwrites
+*		     the xstatus.h of the standalone BSP during the
+*		     libgen.
+* 2.1 	sk  02/26/15 Modified the code for MISRA-C:2012 compliance.
+*       ms  03/17/17 Added readme.txt file in examples folder for doxygen
+*                    generation.
+* 
+* +******************************************************************************/ +#ifndef XSCUTIMER_H /* prevent circular inclusions */ +#define XSCUTIMER_H /* by using protection macros */ + +/***************************** Include Files *********************************/ + +#include "xstatus.h" +#include "xscutimer_hw.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/** + * This typedef contains configuration information for the device. + */ +typedef struct { + u16 DeviceId; /**< Unique ID of device */ + u32 BaseAddr; /**< Base address of the device */ +} XScuTimer_Config; + +/** + * The XScuTimer driver instance data. The user is required to allocate a + * variable of this type for every timer device in the system. + * A pointer to a variable of this type is then passed to the driver API + * functions. + */ +typedef struct { + XScuTimer_Config Config; /**< Hardware Configuration */ + u32 IsReady; /**< Device is initialized and ready */ + u32 IsStarted; /**< Device timer is running */ +} XScuTimer; + +/***************** Macros (Inline Functions) Definitions *********************/ + +/****************************************************************************/ +/** +* +* Check if the timer has expired. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* +* @return +* - TRUE if the timer has expired. +* - FALSE if the timer has not expired. +* +* @note C-style signature: +* int XScuTimer_IsExpired(XScuTimer *InstancePtr) +* +******************************************************************************/ +#define XScuTimer_IsExpired(InstancePtr) \ + ((XScuTimer_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_ISR_OFFSET) & \ + XSCUTIMER_ISR_EVENT_FLAG_MASK) == \ + XSCUTIMER_ISR_EVENT_FLAG_MASK) + +/****************************************************************************/ +/** +* +* Re-start the timer. This macro will read the timer load register +* and writes the same value to load register to update the counter register. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_RestartTimer(XScuTimer *InstancePtr) +* +******************************************************************************/ +#define XScuTimer_RestartTimer(InstancePtr) \ + XScuTimer_LoadTimer((InstancePtr), \ + XScuTimer_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_LOAD_OFFSET)) + +/****************************************************************************/ +/** +* +* Write to the timer load register. This will also update the +* timer counter register with the new value. This macro can be used to +* change the time-out value. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* @param Value is the count to be loaded in to the load register. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_LoadTimer(XScuTimer *InstancePtr, u32 Value) +* +******************************************************************************/ +#define XScuTimer_LoadTimer(InstancePtr, Value) \ + XScuTimer_WriteReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_LOAD_OFFSET, (Value)) + +/****************************************************************************/ +/** +* +* Returns the current timer counter register value. It can be called at any +* time. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* +* @return Contents of the timer counter register. +* +* @note C-style signature: + u32 XScuTimer_GetCounterValue(XScuTimer *InstancePtr) +* +******************************************************************************/ +#define XScuTimer_GetCounterValue(InstancePtr) \ + XScuTimer_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_COUNTER_OFFSET) + +/****************************************************************************/ +/** +* +* Enable auto-reload mode. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_EnableAutoReload(XScuTimer *InstancePtr) +* +******************************************************************************/ +#define XScuTimer_EnableAutoReload(InstancePtr) \ + XScuTimer_WriteReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_CONTROL_OFFSET, \ + (XScuTimer_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_CONTROL_OFFSET) | \ + XSCUTIMER_CONTROL_AUTO_RELOAD_MASK)) + +/****************************************************************************/ +/** +* +* Disable auto-reload mode. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_DisableAutoReload(XScuTimer *InstancePtr) +* +******************************************************************************/ +#define XScuTimer_DisableAutoReload(InstancePtr) \ + XScuTimer_WriteReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_CONTROL_OFFSET, \ + (XScuTimer_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_CONTROL_OFFSET) & \ + ~(XSCUTIMER_CONTROL_AUTO_RELOAD_MASK))) + +/****************************************************************************/ +/** +* +* Enable the Timer interrupt. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_EnableInterrupt(XScuTimer *InstancePtr) +* +******************************************************************************/ +#define XScuTimer_EnableInterrupt(InstancePtr) \ + XScuTimer_WriteReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_CONTROL_OFFSET, \ + (XScuTimer_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_CONTROL_OFFSET) | \ + XSCUTIMER_CONTROL_IRQ_ENABLE_MASK)) + +/****************************************************************************/ +/** +* +* Disable the Timer interrupt. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_DisableInterrupt(XScuTimer *InstancePtr) +* +******************************************************************************/ +#define XScuTimer_DisableInterrupt(InstancePtr) \ + XScuTimer_WriteReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_CONTROL_OFFSET, \ + (XScuTimer_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_CONTROL_OFFSET) & \ + ~(XSCUTIMER_CONTROL_IRQ_ENABLE_MASK))) + +/*****************************************************************************/ +/** +* +* This function reads the interrupt status. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_GetInterruptStatus(XScuTimer *InstancePtr) +* +******************************************************************************/ +#define XScuTimer_GetInterruptStatus(InstancePtr) \ + XScuTimer_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_ISR_OFFSET) + +/*****************************************************************************/ +/** +* +* This function clears the interrupt status. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_ClearInterruptStatus(XScuTimer *InstancePtr) +* +******************************************************************************/ +#define XScuTimer_ClearInterruptStatus(InstancePtr) \ + XScuTimer_WriteReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_ISR_OFFSET, XSCUTIMER_ISR_EVENT_FLAG_MASK) + +/************************** Function Prototypes ******************************/ + +/* + * Lookup configuration in xscutimer_sinit.c + */ +XScuTimer_Config *XScuTimer_LookupConfig(u16 DeviceId); + +/* + * Selftest function in xscutimer_selftest.c + */ +s32 XScuTimer_SelfTest(XScuTimer *InstancePtr); + +/* + * Interface functions in xscutimer.c + */ +s32 XScuTimer_CfgInitialize(XScuTimer *InstancePtr, + XScuTimer_Config *ConfigPtr, u32 EffectiveAddress); +void XScuTimer_Start(XScuTimer *InstancePtr); +void XScuTimer_Stop(XScuTimer *InstancePtr); +void XScuTimer_SetPrescaler(XScuTimer *InstancePtr, u8 PrescalerValue); +u8 XScuTimer_GetPrescaler(XScuTimer *InstancePtr); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/include/xscutimer_hw.h b/df_datalink/bsp/ps7_cortexa9_0/include/xscutimer_hw.h new file mode 100644 index 0000000..d577784 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/include/xscutimer_hw.h @@ -0,0 +1,283 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xscutimer_hw.h +* @addtogroup scutimer_v2_1 +* @{ +* +* This file contains the hardware interface to the Timer. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 1.00a nm  03/10/10 First release
+* 1.01a sdm 02/02/12 Added low level macros to read/write load, counter, control
+*		     and interrupt registers
+* 1.02a  sg 07/17/12 Included xil_assert.h for CR 667947. This is an issue
+*		     when the xstatus.h in the common driver overwrites
+*		     the xstatus.h of the standalone BSP during the
+*		     libgen.
+* 2.1 	sk  02/26/15 Modified the code for MISRA-C:2012 compliance.
+* 
+* +******************************************************************************/ +#ifndef XSCUTIMER_HW_H /* prevent circular inclusions */ +#define XSCUTIMER_HW_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ +#include "xil_types.h" +#include "xil_io.h" +#include "xil_assert.h" +/************************** Constant Definitions *****************************/ + +/** @name Register Map + * Offsets of registers from the start of the device + * @{ + */ + +#define XSCUTIMER_LOAD_OFFSET 0x00U /**< Timer Load Register */ +#define XSCUTIMER_COUNTER_OFFSET 0x04U /**< Timer Counter Register */ +#define XSCUTIMER_CONTROL_OFFSET 0x08U /**< Timer Control Register */ +#define XSCUTIMER_ISR_OFFSET 0x0CU /**< Timer Interrupt + Status Register */ +/* @} */ + +/** @name Timer Control register + * This register bits control the prescaler, Intr enable, + * auto-reload and timer enable. + * @{ + */ + +#define XSCUTIMER_CONTROL_PRESCALER_MASK 0x0000FF00U /**< Prescaler */ +#define XSCUTIMER_CONTROL_PRESCALER_SHIFT 8U +#define XSCUTIMER_CONTROL_IRQ_ENABLE_MASK 0x00000004U /**< Intr enable */ +#define XSCUTIMER_CONTROL_AUTO_RELOAD_MASK 0x00000002U /**< Auto-reload */ +#define XSCUTIMER_CONTROL_ENABLE_MASK 0x00000001U /**< Timer enable */ +/* @} */ + +/** @name Interrupt Status register + * This register indicates the Timer counter register has reached zero. + * @{ + */ + +#define XSCUTIMER_ISR_EVENT_FLAG_MASK 0x00000001U /**< Event flag */ +/*@}*/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/****************************************************************************/ +/** +* +* Write to the timer load register. This will also update the +* timer counter register with the new value. This macro can be used to +* change the time-out value. +* +* @param BaseAddr is the base address of the scu timer. +* @param Value is the count to be loaded in to the load register. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_SetLoadReg(u32 BaseAddr, u32 Value) +* +******************************************************************************/ +#define XScuTimer_SetLoadReg(BaseAddr, Value) \ + XScuTimer_WriteReg(BaseAddr, XSCUTIMER_LOAD_OFFSET, (Value)) + +/****************************************************************************/ +/** +* +* Returns the current timer load register value. +* +* @param BaseAddr is the base address of the scu timer. +* +* @return Contents of the timer load register. +* +* @note C-style signature: +* u32 XScuTimer_GetLoadReg(u32 BaseAddr) +* +******************************************************************************/ +#define XScuTimer_GetLoadReg(BaseAddr) \ + XScuTimer_ReadReg(BaseAddr, XSCUTIMER_LOAD_OFFSET) + +/****************************************************************************/ +/** +* +* Write to the timer counter register. +* +* @param BaseAddr is the base address of the scu timer. +* @param Value is the count to be loaded in to the counter register. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_SetCounterReg(u32 BaseAddr, u32 Value) +* +******************************************************************************/ +#define XScuTimer_SetCounterReg(BaseAddr, Value) \ + XScuTimer_WriteReg(BaseAddr, XSCUTIMER_COUNTER_OFFSET, (Value)) + +/****************************************************************************/ +/** +* +* Returns the current timer counter register value. +* +* @param BaseAddr is the base address of the scu timer. +* +* @return Contents of the timer counter register. +* +* @note C-style signature: + u32 XScuTimer_GetCounterReg(u32 BaseAddr) +* +******************************************************************************/ +#define XScuTimer_GetCounterReg(BaseAddr) \ + XScuTimer_ReadReg(BaseAddr, XSCUTIMER_COUNTER_OFFSET) + +/****************************************************************************/ +/** +* +* Write to the timer load register. This will also update the +* timer counter register with the new value. This macro can be used to +* change the time-out value. +* +* @param BaseAddr is the base address of the scu timer. +* @param Value is the count to be loaded in to the load register. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_SetControlReg(u32 BaseAddr, u32 Value) +* +******************************************************************************/ +#define XScuTimer_SetControlReg(BaseAddr, Value) \ + XScuTimer_WriteReg(BaseAddr, XSCUTIMER_CONTROL_OFFSET, (Value)) + +/****************************************************************************/ +/** +* +* Returns the current timer load register value. +* +* @param BaseAddr is the base address of the scu timer. +* +* @return Contents of the timer load register. +* +* @note C-style signature: + u32 XScuTimer_GetControlReg(u32 BaseAddr) +* +******************************************************************************/ +#define XScuTimer_GetControlReg(BaseAddr) \ + XScuTimer_ReadReg(BaseAddr, XSCUTIMER_CONTROL_OFFSET) + +/****************************************************************************/ +/** +* +* Write to the timer counter register. +* +* @param BaseAddr is the base address of the scu timer. +* @param Value is the count to be loaded in to the counter register. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_SetIntrReg(u32 BaseAddr, u32 Value) +* +******************************************************************************/ +#define XScuTimer_SetIntrReg(BaseAddr, Value) \ + XScuTimer_WriteReg(BaseAddr, XSCUTIMER_ISR_OFFSET, (Value)) + +/****************************************************************************/ +/** +* +* Returns the current timer counter register value. +* +* @param BaseAddr is the base address of the scu timer. +* +* @return Contents of the timer counter register. +* +* @note C-style signature: + u32 XScuTimer_GetIntrReg(u32 BaseAddr) +* +******************************************************************************/ +#define XScuTimer_GetIntrReg(BaseAddr) \ + XScuTimer_ReadReg(BaseAddr, XSCUTIMER_ISR_OFFSET) + +/****************************************************************************/ +/** +* +* Read from the given Timer register. +* +* @param BaseAddr is the base address of the device +* @param RegOffset is the register offset to be read +* +* @return The 32-bit value of the register +* +* @note C-style signature: +* u32 XScuTimer_ReadReg(u32 BaseAddr, u32 RegOffset) +* +*****************************************************************************/ +#define XScuTimer_ReadReg(BaseAddr, RegOffset) \ + Xil_In32((BaseAddr) + (RegOffset)) + +/****************************************************************************/ +/** +* +* Write to the given Timer register. +* +* @param BaseAddr is the base address of the device +* @param RegOffset is the register offset to be written +* @param Data is the 32-bit value to write to the register +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_WriteReg(u32 BaseAddr, u32 RegOffset, u32 Data) +* +*****************************************************************************/ +#define XScuTimer_WriteReg(BaseAddr, RegOffset, Data) \ + Xil_Out32((BaseAddr) + (RegOffset), (Data)) + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/include/xscuwdt.h b/df_datalink/bsp/ps7_cortexa9_0/include/xscuwdt.h new file mode 100644 index 0000000..551eaf5 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/include/xscuwdt.h @@ -0,0 +1,379 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xscuwdt.h +* @addtogroup scuwdt_v2_1 +* @{ +* @details +* +* The Xilinx SCU watchdog timer driver (XScuWdt) supports the Xilinx SCU private +* watchdog timer hardware. +* +* The XScuWdt driver supports the following features: +* - Watchdog mode +* - Timer mode +* - Auto reload (timer mode only) +* +* The watchdog counter register is a down counter and starts decrementing when +* the watchdog is started. +* In watchdog mode, when the counter reaches 0, the Reset flag is set in the +* Reset status register and the WDRESETREQ pin is asserted, causing a system +* reset. The Reset flag is not reset by normal processor reset and is cleared +* when written with a value of 1. This enables the user to differentiate a +* normal reset and a reset caused by watchdog time-out. The user needs to call +* XScuWdt_RestartWdt() periodically, to avoid the watchdog from being timed-out. +* +* The IsWdtExpired function can be used to check if the watchdog was the cause +* of the last reset. In this situation, call Initialize then call IsWdtExpired. +* If the result is true, watchdog timeout caused the last system reset. The +* application then needs to clear the Reset flag. +* +* In timer mode, when the counter reaches 0, the Event flag is set in the +* Interrupt status register and if interrupts are enabled, interrupt ID 30 is +* set as pending in the interrupt distributor. The IsTimerExpired function +* is used to check if the watchdog counter has decremented to 0 in timer mode. +* If auto-reload mode is enabled, the Counter register is automatically reloaded +* from the Load register. +* +* Initialization and Configuration +* +* The device driver enables higher layer software (e.g., an application) to +* communicate with the Watchdog Timer. +* +* XScuWdt_CfgInitialize() API is used to initialize the Watchdog Timer. The +* user needs to first call the XScuWdt_LookupConfig() API which returns +* the Configuration structure pointer which is passed as a parameter to +* the XScuWdt_CfgInitialize() API. +* +* Interrupts +* +* The SCU Watchdog Timer supports interrupts in Timer mode. +* +* This driver does not provide a Interrupt Service Routine (ISR) for the device. +* It is the responsibility of the application to provide one if needed. Refer to +* the interrupt example provided with this driver for details on using the +* Timer in interrupt mode. +* +* Virtual Memory +* +* This driver supports Virtual Memory. The RTOS is responsible for calculating +* the correct device base address in Virtual Memory space. +* +* Threads +* +* This driver is not thread safe. Any needs for threads or thread mutual +* exclusion must be satisfied by the layer above this driver. +* +* Asserts +* +* Asserts are used within all Xilinx drivers to enforce constraints on argument +* values. Asserts can be turned off on a system-wide basis by defining, at +* compile time, the NDEBUG identifier. By default, asserts are turned on and it +* is recommended that users leave asserts on during development. +* +* Building the driver +* +* The XScuWdt driver is composed of several source files. This allows the user +* to build and link only those parts of the driver that are necessary. +* +*

+* +* NOTE: +* The watchdog timer is not a part of the snoop control unit as indicated +* by the prefix "scu" in the name of the driver. +* It is an independent module in APU. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 1.00a sdm 01/15/10 First release
+* 1.02a  sg 07/17/12 Included xil_assert.h for CR 667947. This is an issue
+*		     when the xstatus.h in the common driver overwrites
+*		     the xstatus.h of the standalone BSP during the
+*		     libgen.
+* 2.1 	sk  02/26/15 Modified the code for MISRA-C:2012 compliance.
+*       ms  03/17/17 Added readme.txt file in examples folder for doxygen
+*                    generation.
+* 
+* +******************************************************************************/ +#ifndef XSCUWDT_H /* prevent circular inclusions */ +#define XSCUWDT_H /* by using protection macros */ + +/***************************** Include Files *********************************/ + +#include "xstatus.h" +#include "xscuwdt_hw.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/** + * This typedef contains configuration information for the device. + */ +typedef struct { + u16 DeviceId; /**< Unique ID of device */ + u32 BaseAddr; /**< Base address of the device */ +} XScuWdt_Config; + +/** + * The XScuWdt driver instance data. The user is required to allocate a + * variable of this type for every watchdog/timer device in the system. + * A pointer to a variable of this type is then passed to the driver API + * functions. + */ +typedef struct { + XScuWdt_Config Config;/**< Hardware Configuration */ + u32 IsReady; /**< Device is initialized and ready */ + u32 IsStarted; /**< Device watchdog timer is running */ +} XScuWdt; + +/***************** Macros (Inline Functions) Definitions *********************/ +/****************************************************************************/ +/** +* +* This function is used to check if the watchdog has timed-out and the last +* reset was caused by the watchdog reset. +* +* @param InstancePtr is a pointer to the XScuWdt instance. +* +* @return +* - TRUE if the watchdog has expired. +* - FALSE if the watchdog has not expired. +* +* @note C-style signature: +* int XScuWdt_IsWdtExpired(XScuWdt *InstancePtr) +* +******************************************************************************/ +#define XScuWdt_IsWdtExpired(InstancePtr) \ + ((XScuWdt_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUWDT_RST_STS_OFFSET) & \ + XSCUWDT_RST_STS_RESET_FLAG_MASK) == XSCUWDT_RST_STS_RESET_FLAG_MASK) + +/****************************************************************************/ +/** +* +* This function is used to check if the watchdog counter has reached 0 in timer +* mode. +* +* @param InstancePtr is a pointer to the XScuWdt instance. +* +* @return +* - TRUE if the watchdog has expired. +* - FALSE if the watchdog has not expired. +* +* @note C-style signature: +* int XScuWdt_IsTimerExpired(XScuWdt *InstancePtr) +* +******************************************************************************/ +#define XScuWdt_IsTimerExpired(InstancePtr) \ + ((XScuWdt_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUWDT_ISR_OFFSET) & \ + XSCUWDT_ISR_EVENT_FLAG_MASK) == XSCUWDT_ISR_EVENT_FLAG_MASK) + +/****************************************************************************/ +/** +* +* Re-start the watchdog timer. This macro will read the watchdog load register +* and write the same value to load register to update the counter register. +* An application needs to call this function periodically to keep the watchdog +* from asserting the WDRESETREQ reset request output pin. +* +* @param InstancePtr is a pointer to the XScuWdt instance. +* +* @return None. +* +* @note C-style signature: +* void XScuWdt_RestartWdt(XScuWdt *InstancePtr) +* +******************************************************************************/ +#define XScuWdt_RestartWdt(InstancePtr) \ + XScuWdt_LoadWdt((InstancePtr), \ + (XScuWdt_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUWDT_LOAD_OFFSET))) + +/****************************************************************************/ +/** +* +* Write to the watchdog timer load register. This will also update the +* watchdog counter register with the new value. This macro can be used to +* change the time-out value. +* +* @param InstancePtr is a pointer to the XScuWdt instance. +* @param Value is the value to be written to the Watchdog Load register. +* +* @return None. +* +* @note C-style signature: +* void XScuWdt_LoadWdt(XScuWdt *InstancePtr, u32 Value) +* +******************************************************************************/ +#define XScuWdt_LoadWdt(InstancePtr, Value) \ + XScuWdt_WriteReg((InstancePtr)->Config.BaseAddr, \ + XSCUWDT_LOAD_OFFSET, (Value)) + +/****************************************************************************/ +/** +* +* Put the watchdog timer in Watchdog mode by setting the WD mode bit of the +* Watchdog control register. +* +* @param InstancePtr is a pointer to the XScuWdt instance. +* +* @return None. +* +* @note C-style signature: +* void XScuWdt_SetWdMode(XScuWdt *InstancePtr) +* +******************************************************************************/ +#define XScuWdt_SetWdMode(InstancePtr) \ + XScuWdt_WriteReg((InstancePtr)->Config.BaseAddr, \ + XSCUWDT_CONTROL_OFFSET, \ + (XScuWdt_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUWDT_CONTROL_OFFSET) | \ + (XSCUWDT_CONTROL_WD_MODE_MASK))) + +/****************************************************************************/ +/** +* +* Put the watchdog timer in Timer mode by writing 0x12345678 and 0x87654321 +* successively to the Watchdog Disable Register. +* The software must write 0x12345678 and 0x87654321 successively to the +* Watchdog Disable Register so that the watchdog mode bit in the Watchdog +* Control Register is set to zero. +* +* @param InstancePtr is a pointer to the XScuWdt instance. +* +* @return None. +* +* @note C-style signature: +* void XScuWdt_SetTimerMode(XScuWdt *InstancePtr) +* +******************************************************************************/ +#define XScuWdt_SetTimerMode(InstancePtr) \ +{ \ + XScuWdt_WriteReg((InstancePtr)->Config.BaseAddr, \ + XSCUWDT_DISABLE_OFFSET, \ + XSCUWDT_DISABLE_VALUE1); \ + XScuWdt_WriteReg((InstancePtr)->Config.BaseAddr, \ + XSCUWDT_DISABLE_OFFSET, \ + XSCUWDT_DISABLE_VALUE2); \ +} + +/****************************************************************************/ +/** +* +* Get the contents of the watchdog control register. +* +* @param InstancePtr is a pointer to the XScuWdt instance. +* +* @return Contents of the watchdog control register. +* +* @note C-style signature: + u32 XScuWdt_GetControlReg(XScuWdt *InstancePtr) +* +******************************************************************************/ +#define XScuWdt_GetControlReg(InstancePtr) \ + XScuWdt_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUWDT_CONTROL_OFFSET) + +/****************************************************************************/ +/** +* +* Write to the watchdog control register. +* +* @param InstancePtr is a pointer to the XScuWdt instance. +* @param ControlReg is the value to be written to the watchdog control +* register. +* +* @return None. +* +* @note C-style signature: + void XScuWdt_SetControlReg(XScuWdt *InstancePtr, u32 ControlReg) +* +******************************************************************************/ +#define XScuWdt_SetControlReg(InstancePtr, ControlReg) \ + XScuWdt_WriteReg((InstancePtr)->Config.BaseAddr, \ + XSCUWDT_CONTROL_OFFSET, (ControlReg)) + +/****************************************************************************/ +/** +* +* Enable auto-reload mode. +* +* @param InstancePtr is a pointer to the XScuWdt instance. +* +* @return None. +* +* @note C-style signature: +* void XScuWdt_EnableAutoReload(XScuWdt *InstancePtr) +* +******************************************************************************/ +#define XScuWdt_EnableAutoReload(InstancePtr) \ + XScuWdt_SetControlReg((InstancePtr), \ + (XScuWdt_GetControlReg(InstancePtr) | \ + XSCUWDT_CONTROL_AUTO_RELOAD_MASK)) + +/************************** Function Prototypes ******************************/ + +/* + * Lookup configuration in xscuwdt_sinit.c. + */ +XScuWdt_Config *XScuWdt_LookupConfig(u16 DeviceId); + +/* + * Selftest function in xscuwdt_selftest.c + */ +s32 XScuWdt_SelfTest(XScuWdt *InstancePtr); + +/* + * Interface functions in xscuwdt.c + */ +s32 XScuWdt_CfgInitialize(XScuWdt *InstancePtr, + XScuWdt_Config *ConfigPtr, u32 EffectiveAddress); + +void XScuWdt_Start(XScuWdt *InstancePtr); + +void XScuWdt_Stop(XScuWdt *InstancePtr); + + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/include/xscuwdt_hw.h b/df_datalink/bsp/ps7_cortexa9_0/include/xscuwdt_hw.h new file mode 100644 index 0000000..ad87a05 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/include/xscuwdt_hw.h @@ -0,0 +1,178 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xscuwdt_hw.h +* @addtogroup scuwdt_v2_1 +* @{ +* +* This file contains the hardware interface to the Xilinx SCU private Watch Dog +* Timer (XSCUWDT). +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 1.00a sdm 01/15/10 First release
+* 1.01a bss 02/27/12 Updated the register offsets to start at 0x0 instead
+*                    of 0x20 as the base address obtained from the tools
+*		     starts at 0x20.
+* 1.02a  sg 07/17/12 Included xil_assert.h for CR 667947. This is an issue
+*		     when the xstatus.h in the common driver overwrites
+*		     the xstatus.h of the standalone BSP during the
+*		     libgen.
+* 2.1 	sk  02/26/15 Modified the code for MISRA-C:2012 compliance.
+* 
+* +******************************************************************************/ +#ifndef XSCUWDT_HW_H /* prevent circular inclusions */ +#define XSCUWDT_HW_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_io.h" +#include "xil_assert.h" +/************************** Constant Definitions *****************************/ + +/** @name Register Map + * Offsets of registers from the start of the device. The WDT registers start at + * an offset 0x20 + * @{ + */ + +#define XSCUWDT_LOAD_OFFSET 0x00U /**< Watchdog Load Register */ +#define XSCUWDT_COUNTER_OFFSET 0x04U /**< Watchdog Counter Register */ +#define XSCUWDT_CONTROL_OFFSET 0x08U /**< Watchdog Control Register */ +#define XSCUWDT_ISR_OFFSET 0x0CU /**< Watchdog Interrupt Status Register */ +#define XSCUWDT_RST_STS_OFFSET 0x10U /**< Watchdog Reset Status Register */ +#define XSCUWDT_DISABLE_OFFSET 0x14U /**< Watchdog Disable Register */ +/* @} */ + +/** @name Watchdog Control register + * This register bits control the prescaler, WD/Timer mode, Intr enable, + * auto-reload, watchdog enable. + * @{ + */ + +#define XSCUWDT_CONTROL_PRESCALER_MASK 0x0000FF00U /**< Prescaler */ +#define XSCUWDT_CONTROL_PRESCALER_SHIFT 8U +#define XSCUWDT_CONTROL_WD_MODE_MASK 0x00000008U /**< Watchdog/Timer mode */ +#define XSCUWDT_CONTROL_IT_ENABLE_MASK 0x00000004U /**< Intr enable (in + timer mode) */ +#define XSCUWDT_CONTROL_AUTO_RELOAD_MASK 0x00000002U /**< Auto-reload (in + timer mode) */ +#define XSCUWDT_CONTROL_WD_ENABLE_MASK 0x00000001U /**< Watchdog enable */ +/* @} */ + +/** @name Interrupt Status register + * This register indicates the Counter register has reached zero in Counter + * mode. + * @{ + */ + +#define XSCUWDT_ISR_EVENT_FLAG_MASK 0x00000001U /**< Event flag */ +/*@}*/ + +/** @name Reset Status register + * This register indicates the Counter register has reached zero in Watchdog + * mode and a reset request is sent. + * @{ + */ + +#define XSCUWDT_RST_STS_RESET_FLAG_MASK 0x00000001U /**< Time out occured */ +/*@}*/ + +/** @name Disable register + * This register is used to switch from watchdog mode to timer mode. + * The software must write 0x12345678 and 0x87654321 successively to the + * Watchdog Disable Register so that the watchdog mode bit in the Watchdog + * Control Register is set to zero. + * @{ + */ +#define XSCUWDT_DISABLE_VALUE1 0x12345678U /**< Watchdog mode disable + value 1 */ +#define XSCUWDT_DISABLE_VALUE2 0x87654321U /**< Watchdog mode disable + value 2 */ +/*@}*/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/****************************************************************************/ +/** +* +* Read the given register. +* +* @param BaseAddr is the base address of the device +* @param RegOffset is the register offset to be read +* +* @return The 32-bit value of the register +* +* @note C-style signature: +* u32 XScuWdt_ReadReg(u32 BaseAddr, u32 RegOffset) +* +*****************************************************************************/ +#define XScuWdt_ReadReg(BaseAddr, RegOffset) \ + Xil_In32((BaseAddr) + ((u32)RegOffset)) + +/****************************************************************************/ +/** +* +* Write the given register. +* +* @param BaseAddr is the base address of the device +* @param RegOffset is the register offset to be written +* @param Data is the 32-bit value to write to the register +* +* @return None. +* +* @note C-style signature: +* void XScuWdt_WriteReg(u32 BaseAddr, u32 RegOffset, u32 Data) +* +*****************************************************************************/ +#define XScuWdt_WriteReg(BaseAddr, RegOffset, Data) \ + Xil_Out32((BaseAddr) + ((u32)RegOffset), ((u32)Data)) + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/include/xstatus.h b/df_datalink/bsp/ps7_cortexa9_0/include/xstatus.h new file mode 100644 index 0000000..1a212bf --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/include/xstatus.h @@ -0,0 +1,533 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xstatus.h +* +* @addtogroup common_status_codes Xilinx® software status codes +* +* The xstatus.h file contains the Xilinx® software status codes.These codes are +* used throughout the Xilinx device drivers. +* +* @{ +******************************************************************************/ + +#ifndef XSTATUS_H /* prevent circular inclusions */ +#define XSTATUS_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" + +/************************** Constant Definitions *****************************/ + +/*********************** Common statuses 0 - 500 *****************************/ +/** +@name Common Status Codes for All Device Drivers +@{ +*/ +#define XST_SUCCESS 0L +#define XST_FAILURE 1L +#define XST_DEVICE_NOT_FOUND 2L +#define XST_DEVICE_BLOCK_NOT_FOUND 3L +#define XST_INVALID_VERSION 4L +#define XST_DEVICE_IS_STARTED 5L +#define XST_DEVICE_IS_STOPPED 6L +#define XST_FIFO_ERROR 7L /*!< An error occurred during an + operation with a FIFO such as + an underrun or overrun, this + error requires the device to + be reset */ +#define XST_RESET_ERROR 8L /*!< An error occurred which requires + the device to be reset */ +#define XST_DMA_ERROR 9L /*!< A DMA error occurred, this error + typically requires the device + using the DMA to be reset */ +#define XST_NOT_POLLED 10L /*!< The device is not configured for + polled mode operation */ +#define XST_FIFO_NO_ROOM 11L /*!< A FIFO did not have room to put + the specified data into */ +#define XST_BUFFER_TOO_SMALL 12L /*!< The buffer is not large enough + to hold the expected data */ +#define XST_NO_DATA 13L /*!< There was no data available */ +#define XST_REGISTER_ERROR 14L /*!< A register did not contain the + expected value */ +#define XST_INVALID_PARAM 15L /*!< An invalid parameter was passed + into the function */ +#define XST_NOT_SGDMA 16L /*!< The device is not configured for + scatter-gather DMA operation */ +#define XST_LOOPBACK_ERROR 17L /*!< A loopback test failed */ +#define XST_NO_CALLBACK 18L /*!< A callback has not yet been + registered */ +#define XST_NO_FEATURE 19L /*!< Device is not configured with + the requested feature */ +#define XST_NOT_INTERRUPT 20L /*!< Device is not configured for + interrupt mode operation */ +#define XST_DEVICE_BUSY 21L /*!< Device is busy */ +#define XST_ERROR_COUNT_MAX 22L /*!< The error counters of a device + have maxed out */ +#define XST_IS_STARTED 23L /*!< Used when part of device is + already started i.e. + sub channel */ +#define XST_IS_STOPPED 24L /*!< Used when part of device is + already stopped i.e. + sub channel */ +#define XST_DATA_LOST 26L /*!< Driver defined error */ +#define XST_RECV_ERROR 27L /*!< Generic receive error */ +#define XST_SEND_ERROR 28L /*!< Generic transmit error */ +#define XST_NOT_ENABLED 29L /*!< A requested service is not + available because it has not + been enabled */ +#define XST_NO_ACCESS 30L /* Generic access error */ +/** @} */ +/***************** Utility Component statuses 401 - 500 *********************/ +/** +@name Utility Component Status Codes 401 - 500 +@{ +*/ +#define XST_MEMTEST_FAILED 401L /*!< Memory test failed */ + +/** @} */ +/***************** Common Components statuses 501 - 1000 *********************/ +/** +@name Packet Fifo Status Codes 501 - 510 +@{ +*/ +/********************* Packet Fifo statuses 501 - 510 ************************/ + +#define XST_PFIFO_LACK_OF_DATA 501L /*!< Not enough data in FIFO */ +#define XST_PFIFO_NO_ROOM 502L /*!< Not enough room in FIFO */ +#define XST_PFIFO_BAD_REG_VALUE 503L /*!< Self test, a register value + was invalid after reset */ +#define XST_PFIFO_ERROR 504L /*!< Generic packet FIFO error */ +#define XST_PFIFO_DEADLOCK 505L /*!< Packet FIFO is reporting + * empty and full simultaneously + */ +/** @} */ +/** +@name DMA Status Codes 511 - 530 +@{ +*/ +/************************** DMA statuses 511 - 530 ***************************/ + +#define XST_DMA_TRANSFER_ERROR 511L /*!< Self test, DMA transfer + failed */ +#define XST_DMA_RESET_REGISTER_ERROR 512L /*!< Self test, a register value + was invalid after reset */ +#define XST_DMA_SG_LIST_EMPTY 513L /*!< Scatter gather list contains + no buffer descriptors ready + to be processed */ +#define XST_DMA_SG_IS_STARTED 514L /*!< Scatter gather not stopped */ +#define XST_DMA_SG_IS_STOPPED 515L /*!< Scatter gather not running */ +#define XST_DMA_SG_LIST_FULL 517L /*!< All the buffer desciptors of + the scatter gather list are + being used */ +#define XST_DMA_SG_BD_LOCKED 518L /*!< The scatter gather buffer + descriptor which is to be + copied over in the scatter + list is locked */ +#define XST_DMA_SG_NOTHING_TO_COMMIT 519L /*!< No buffer descriptors have been + put into the scatter gather + list to be commited */ +#define XST_DMA_SG_COUNT_EXCEEDED 521L /*!< The packet count threshold + specified was larger than the + total # of buffer descriptors + in the scatter gather list */ +#define XST_DMA_SG_LIST_EXISTS 522L /*!< The scatter gather list has + already been created */ +#define XST_DMA_SG_NO_LIST 523L /*!< No scatter gather list has + been created */ +#define XST_DMA_SG_BD_NOT_COMMITTED 524L /*!< The buffer descriptor which was + being started was not committed + to the list */ +#define XST_DMA_SG_NO_DATA 525L /*!< The buffer descriptor to start + has already been used by the + hardware so it can't be reused + */ +#define XST_DMA_SG_LIST_ERROR 526L /*!< General purpose list access + error */ +#define XST_DMA_BD_ERROR 527L /*!< General buffer descriptor + error */ +/** @} */ +/** +@name IPIF Status Codes Codes 531 - 550 +@{ +*/ +/************************** IPIF statuses 531 - 550 ***************************/ + +#define XST_IPIF_REG_WIDTH_ERROR 531L /*!< An invalid register width + was passed into the function */ +#define XST_IPIF_RESET_REGISTER_ERROR 532L /*!< The value of a register at + reset was not valid */ +#define XST_IPIF_DEVICE_STATUS_ERROR 533L /*!< A write to the device interrupt + status register did not read + back correctly */ +#define XST_IPIF_DEVICE_ACK_ERROR 534L /*!< The device interrupt status + register did not reset when + acked */ +#define XST_IPIF_DEVICE_ENABLE_ERROR 535L /*!< The device interrupt enable + register was not updated when + other registers changed */ +#define XST_IPIF_IP_STATUS_ERROR 536L /*!< A write to the IP interrupt + status register did not read + back correctly */ +#define XST_IPIF_IP_ACK_ERROR 537L /*!< The IP interrupt status register + did not reset when acked */ +#define XST_IPIF_IP_ENABLE_ERROR 538L /*!< IP interrupt enable register was + not updated correctly when other + registers changed */ +#define XST_IPIF_DEVICE_PENDING_ERROR 539L /*!< The device interrupt pending + register did not indicate the + expected value */ +#define XST_IPIF_DEVICE_ID_ERROR 540L /*!< The device interrupt ID register + did not indicate the expected + value */ +#define XST_IPIF_ERROR 541L /*!< Generic ipif error */ +/** @} */ + +/****************** Device specific statuses 1001 - 4095 *********************/ +/** +@name Ethernet Status Codes 1001 - 1050 +@{ +*/ +/********************* Ethernet statuses 1001 - 1050 *************************/ + +#define XST_EMAC_MEMORY_SIZE_ERROR 1001L /*!< Memory space is not big enough + * to hold the minimum number of + * buffers or descriptors */ +#define XST_EMAC_MEMORY_ALLOC_ERROR 1002L /*!< Memory allocation failed */ +#define XST_EMAC_MII_READ_ERROR 1003L /*!< MII read error */ +#define XST_EMAC_MII_BUSY 1004L /*!< An MII operation is in progress */ +#define XST_EMAC_OUT_OF_BUFFERS 1005L /*!< Driver is out of buffers */ +#define XST_EMAC_PARSE_ERROR 1006L /*!< Invalid driver init string */ +#define XST_EMAC_COLLISION_ERROR 1007L /*!< Excess deferral or late + * collision on polled send */ +/** @} */ +/** +@name UART Status Codes 1051 - 1075 +@{ +*/ +/*********************** UART statuses 1051 - 1075 ***************************/ +#define XST_UART + +#define XST_UART_INIT_ERROR 1051L +#define XST_UART_START_ERROR 1052L +#define XST_UART_CONFIG_ERROR 1053L +#define XST_UART_TEST_FAIL 1054L +#define XST_UART_BAUD_ERROR 1055L +#define XST_UART_BAUD_RANGE 1056L + +/** @} */ +/** +@name IIC Status Codes 1076 - 1100 +@{ +*/ +/************************ IIC statuses 1076 - 1100 ***************************/ + +#define XST_IIC_SELFTEST_FAILED 1076 /*!< self test failed */ +#define XST_IIC_BUS_BUSY 1077 /*!< bus found busy */ +#define XST_IIC_GENERAL_CALL_ADDRESS 1078 /*!< mastersend attempted with */ + /* general call address */ +#define XST_IIC_STAND_REG_RESET_ERROR 1079 /*!< A non parameterizable reg */ + /* value after reset not valid */ +#define XST_IIC_TX_FIFO_REG_RESET_ERROR 1080 /*!< Tx fifo included in design */ + /* value after reset not valid */ +#define XST_IIC_RX_FIFO_REG_RESET_ERROR 1081 /*!< Rx fifo included in design */ + /* value after reset not valid */ +#define XST_IIC_TBA_REG_RESET_ERROR 1082 /*!< 10 bit addr incl in design */ + /* value after reset not valid */ +#define XST_IIC_CR_READBACK_ERROR 1083 /*!< Read of the control register */ + /* didn't return value written */ +#define XST_IIC_DTR_READBACK_ERROR 1084 /*!< Read of the data Tx reg */ + /* didn't return value written */ +#define XST_IIC_DRR_READBACK_ERROR 1085 /*!< Read of the data Receive reg */ + /* didn't return value written */ +#define XST_IIC_ADR_READBACK_ERROR 1086 /*!< Read of the data Tx reg */ + /* didn't return value written */ +#define XST_IIC_TBA_READBACK_ERROR 1087 /*!< Read of the 10 bit addr reg */ + /* didn't return written value */ +#define XST_IIC_NOT_SLAVE 1088 /*!< The device isn't a slave */ +#define XST_IIC_ARB_LOST 1089 /*!< Arbitration lost for master */ +/** @} */ +/** +@name ATMC Status Codes 1101 - 1125 +@{ +*/ +/*********************** ATMC statuses 1101 - 1125 ***************************/ + +#define XST_ATMC_ERROR_COUNT_MAX 1101L /*!< the error counters in the ATM + controller hit the max value + which requires the statistics + to be cleared */ +/** @} */ +/** +@name Flash Status Codes 1126 - 1150 +@{ +*/ +/*********************** Flash statuses 1126 - 1150 **************************/ + +#define XST_FLASH_BUSY 1126L /*!< Flash is erasing or programming + */ +#define XST_FLASH_READY 1127L /*!< Flash is ready for commands */ +#define XST_FLASH_ERROR 1128L /*!< Flash had detected an internal + error. Use XFlash_DeviceControl + to retrieve device specific codes + */ +#define XST_FLASH_ERASE_SUSPENDED 1129L /*!< Flash is in suspended erase state + */ +#define XST_FLASH_WRITE_SUSPENDED 1130L /*!< Flash is in suspended write state + */ +#define XST_FLASH_PART_NOT_SUPPORTED 1131L /*!< Flash type not supported by + driver */ +#define XST_FLASH_NOT_SUPPORTED 1132L /*!< Operation not supported */ +#define XST_FLASH_TOO_MANY_REGIONS 1133L /*!< Too many erase regions */ +#define XST_FLASH_TIMEOUT_ERROR 1134L /*!< Programming or erase operation + aborted due to a timeout */ +#define XST_FLASH_ADDRESS_ERROR 1135L /*!< Accessed flash outside its + addressible range */ +#define XST_FLASH_ALIGNMENT_ERROR 1136L /*!< Write alignment error */ +#define XST_FLASH_BLOCKING_CALL_ERROR 1137L /*!< Couldn't return immediately from + write/erase function with + XFL_NON_BLOCKING_WRITE/ERASE + option cleared */ +#define XST_FLASH_CFI_QUERY_ERROR 1138L /*!< Failed to query the device */ +/** @} */ +/** +@name SPI Status Codes 1151 - 1175 +@{ +*/ +/*********************** SPI statuses 1151 - 1175 ****************************/ + +#define XST_SPI_MODE_FAULT 1151 /*!< master was selected as slave */ +#define XST_SPI_TRANSFER_DONE 1152 /*!< data transfer is complete */ +#define XST_SPI_TRANSMIT_UNDERRUN 1153 /*!< slave underruns transmit register */ +#define XST_SPI_RECEIVE_OVERRUN 1154 /*!< device overruns receive register */ +#define XST_SPI_NO_SLAVE 1155 /*!< no slave has been selected yet */ +#define XST_SPI_TOO_MANY_SLAVES 1156 /*!< more than one slave is being + * selected */ +#define XST_SPI_NOT_MASTER 1157 /*!< operation is valid only as master */ +#define XST_SPI_SLAVE_ONLY 1158 /*!< device is configured as slave-only + */ +#define XST_SPI_SLAVE_MODE_FAULT 1159 /*!< slave was selected while disabled */ +#define XST_SPI_SLAVE_MODE 1160 /*!< device has been addressed as slave */ +#define XST_SPI_RECEIVE_NOT_EMPTY 1161 /*!< device received data in slave mode */ + +#define XST_SPI_COMMAND_ERROR 1162 /*!< unrecognised command - qspi only */ +#define XST_SPI_POLL_DONE 1163 /*!< controller completed polling the + device for status */ +/** @} */ +/** +@name OPB Arbiter Status Codes 1176 - 1200 +@{ +*/ +/********************** OPB Arbiter statuses 1176 - 1200 *********************/ + +#define XST_OPBARB_INVALID_PRIORITY 1176 /*!< the priority registers have either + * one master assigned to two or more + * priorities, or one master not + * assigned to any priority + */ +#define XST_OPBARB_NOT_SUSPENDED 1177 /*!< an attempt was made to modify the + * priority levels without first + * suspending the use of priority + * levels + */ +#define XST_OPBARB_PARK_NOT_ENABLED 1178 /*!< bus parking by id was enabled but + * bus parking was not enabled + */ +#define XST_OPBARB_NOT_FIXED_PRIORITY 1179 /*!< the arbiter must be in fixed + * priority mode to allow the + * priorities to be changed + */ +/** @} */ +/** +@name INTC Status Codes 1201 - 1225 +@{ +*/ +/************************ Intc statuses 1201 - 1225 **************************/ + +#define XST_INTC_FAIL_SELFTEST 1201 /*!< self test failed */ +#define XST_INTC_CONNECT_ERROR 1202 /*!< interrupt already in use */ +/** @} */ +/** +@name TmrCtr Status Codes 1226 - 1250 +@{ +*/ +/********************** TmrCtr statuses 1226 - 1250 **************************/ + +#define XST_TMRCTR_TIMER_FAILED 1226 /*!< self test failed */ +/** @} */ +/** +@name WdtTb Status Codes 1251 - 1275 +@{ +*/ +/********************** WdtTb statuses 1251 - 1275 ***************************/ + +#define XST_WDTTB_TIMER_FAILED 1251L +/** @} */ +/** +@name PlbArb status Codes 1276 - 1300 +@{ +*/ +/********************** PlbArb statuses 1276 - 1300 **************************/ + +#define XST_PLBARB_FAIL_SELFTEST 1276L +/** @} */ +/** +@name Plb2Opb Status Codes 1301 - 1325 +@{ +*/ +/********************** Plb2Opb statuses 1301 - 1325 *************************/ + +#define XST_PLB2OPB_FAIL_SELFTEST 1301L +/** @} */ +/** +@name Opb2Plb Status 1326 - 1350 +@{ +*/ +/********************** Opb2Plb statuses 1326 - 1350 *************************/ + +#define XST_OPB2PLB_FAIL_SELFTEST 1326L +/** @} */ +/** +@name SysAce Status Codes 1351 - 1360 +@{ +*/ +/********************** SysAce statuses 1351 - 1360 **************************/ + +#define XST_SYSACE_NO_LOCK 1351L /*!< No MPU lock has been granted */ +/** @} */ +/** +@name PCI Bridge Status Codes 1361 - 1375 +@{ +*/ +/********************** PCI Bridge statuses 1361 - 1375 **********************/ + +#define XST_PCI_INVALID_ADDRESS 1361L +/** @} */ +/** +@name FlexRay Constants 1400 - 1409 +@{ +*/ +/********************** FlexRay constants 1400 - 1409 *************************/ + +#define XST_FR_TX_ERROR 1400 +#define XST_FR_TX_BUSY 1401 +#define XST_FR_BUF_LOCKED 1402 +#define XST_FR_NO_BUF 1403 +/** @} */ +/** +@name USB constants 1410 - 1420 +@{ +*/ +/****************** USB constants 1410 - 1420 *******************************/ + +#define XST_USB_ALREADY_CONFIGURED 1410 +#define XST_USB_BUF_ALIGN_ERROR 1411 +#define XST_USB_NO_DESC_AVAILABLE 1412 +#define XST_USB_BUF_TOO_BIG 1413 +#define XST_USB_NO_BUF 1414 +/** @} */ +/** +@name HWICAP constants 1421 - 1429 +@{ +*/ +/****************** HWICAP constants 1421 - 1429 *****************************/ + +#define XST_HWICAP_WRITE_DONE 1421 + +/** @} */ +/** +@name AXI VDMA constants 1430 - 1440 +@{ +*/ +/****************** AXI VDMA constants 1430 - 1440 *****************************/ + +#define XST_VDMA_MISMATCH_ERROR 1430 +/** @} */ +/** +@name NAND Flash Status Codes 1441 - 1459 +@{ +*/ +/*********************** NAND Flash statuses 1441 - 1459 *********************/ + +#define XST_NAND_BUSY 1441L /*!< Flash is erasing or + * programming + */ +#define XST_NAND_READY 1442L /*!< Flash is ready for commands + */ +#define XST_NAND_ERROR 1443L /*!< Flash had detected an + * internal error. + */ +#define XST_NAND_PART_NOT_SUPPORTED 1444L /*!< Flash type not supported by + * driver + */ +#define XST_NAND_OPT_NOT_SUPPORTED 1445L /*!< Operation not supported + */ +#define XST_NAND_TIMEOUT_ERROR 1446L /*!< Programming or erase + * operation aborted due to a + * timeout + */ +#define XST_NAND_ADDRESS_ERROR 1447L /*!< Accessed flash outside its + * addressible range + */ +#define XST_NAND_ALIGNMENT_ERROR 1448L /*!< Write alignment error + */ +#define XST_NAND_PARAM_PAGE_ERROR 1449L /*!< Failed to read parameter + * page of the device + */ +#define XST_NAND_CACHE_ERROR 1450L /*!< Flash page buffer error + */ + +#define XST_NAND_WRITE_PROTECTED 1451L /*!< Flash is write protected + */ +/** @} */ + +/**************************** Type Definitions *******************************/ + +typedef s32 XStatus; + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** +* @} End of "addtogroup common_status_codes". +*/ diff --git a/df_datalink/bsp/ps7_cortexa9_0/include/xtime_l.h b/df_datalink/bsp/ps7_cortexa9_0/include/xtime_l.h new file mode 100644 index 0000000..12004e1 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/include/xtime_l.h @@ -0,0 +1,104 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file xtime_l.h +* @addtogroup a9_time_apis Cortex A9 Time Functions +* +* xtime_l.h provides access to the 64-bit Global Counter in the PMU. This +* counter increases by one at every two processor cycles. These functions can +* be used to get/set time in the global timer. +* +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ------ -------- ---------------------------------------------------
+* 1.00a rp/sdm 11/03/09 Initial release.
+* 3.06a sgd    05/15/12 Upadted get/set time functions to make use Global Timer
+* 3.06a asa    06/17/12 Reverted back the changes to make use Global Timer.
+* 3.07a sgd    07/05/12 Upadted get/set time functions to make use Global Timer
+* 6.6   srm    10/23/17 Updated the macros to support user configurable sleep
+*						implementation
+* 6.8   aru  09/06/18 Removed compilation warnings for ARMCC toolchain.
+* 
+* +******************************************************************************/ + +#ifndef XTIME_H /* prevent circular inclusions */ +#define XTIME_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xparameters.h" + +/***************** Macros (Inline Functions) Definitions *********************/ + +/**************************** Type Definitions *******************************/ + +typedef u64 XTime; + +/************************** Constant Definitions *****************************/ +#define GLOBAL_TMR_BASEADDR XPAR_GLOBAL_TMR_BASEADDR +#define GTIMER_COUNTER_LOWER_OFFSET 0x00U +#define GTIMER_COUNTER_UPPER_OFFSET 0x04U +#define GTIMER_CONTROL_OFFSET 0x08U + +#if defined (SLEEP_TIMER_BASEADDR) +#define COUNTS_PER_SECOND (SLEEP_TIMER_FREQUENCY) +#else +/* Global Timer is always clocked at half of the CPU frequency */ +#define COUNTS_PER_SECOND (XPAR_CPU_CORTEXA9_CORE_CLOCK_FREQ_HZ /2) +#endif + +#if defined (XSLEEP_TIMER_IS_DEFAULT_TIMER) +#ifdef __GNUC__ +#pragma message ("For the sleep routines, Global timer is being used") +#endif +#endif +/************************** Variable Definitions *****************************/ + +/************************** Function Prototypes ******************************/ + +void XTime_SetTime(XTime Xtime_Global); +void XTime_GetTime(XTime *Xtime_Global); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* XTIME_H */ +/** +* @} End of "addtogroup a9_time_apis". +*/ diff --git a/df_datalink/bsp/ps7_cortexa9_0/include/xuartps.h b/df_datalink/bsp/ps7_cortexa9_0/include/xuartps.h new file mode 100644 index 0000000..c6c2a0a --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/include/xuartps.h @@ -0,0 +1,517 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xuartps.h +* @addtogroup uartps_v3_5 +* @{ +* @details +* +* This driver supports the following features: +* +* - Dynamic data format (baud rate, data bits, stop bits, parity) +* - Polled mode +* - Interrupt driven mode +* - Transmit and receive FIFOs (32 byte FIFO depth) +* - Access to the external modem control lines +* +* Initialization & Configuration +* +* The XUartPs_Config structure is used by the driver to configure itself. +* Fields inside this structure are properties of XUartPs based on its hardware +* build. +* +* To support multiple runtime loading and initialization strategies employed +* by various operating systems, the driver instance can be initialized in the +* following way: +* +* - XUartPs_CfgInitialize(InstancePtr, CfgPtr, EffectiveAddr) - Uses a +* configuration structure provided by the caller. If running in a system +* with address translation, the parameter EffectiveAddr should be the +* virtual address. +* +* Baud Rate +* +* The UART has an internal baud rate generator, which furnishes the baud rate +* clock for both the receiver and the transmitter. Ther input clock frequency +* can be either the master clock or the master clock divided by 8, configured +* through the mode register. +* +* Accompanied with the baud rate divider register, the baud rate is determined +* by: +*
+*	baud_rate = input_clock / (bgen * (bdiv + 1)
+* 
+* where bgen is the value of the baud rate generator, and bdiv is the value of +* baud rate divider. +* +* Interrupts +* +* The FIFOs are not flushed when the driver is initialized, but a function is +* provided to allow the user to reset the FIFOs if desired. +* +* The driver defaults to no interrupts at initialization such that interrupts +* must be enabled if desired. An interrupt is generated for one of the +* following conditions. +* +* - A change in the modem signals +* - Data in the receive FIFO for a configuable time without receiver activity +* - A parity error +* - A framing error +* - An overrun error +* - Transmit FIFO is full +* - Transmit FIFO is empty +* - Receive FIFO is full +* - Receive FIFO is empty +* - Data in the receive FIFO equal to the receive threshold +* +* The application can control which interrupts are enabled using the +* XUartPs_SetInterruptMask() function. +* +* In order to use interrupts, it is necessary for the user to connect the +* driver interrupt handler, XUartPs_InterruptHandler(), to the interrupt +* system of the application. A separate handler should be provided by the +* application to communicate with the interrupt system, and conduct +* application specific interrupt handling. An application registers its own +* handler through the XUartPs_SetHandler() function. +* +* Data Transfer +* +* The functions, XUartPs_Send() and XUartPs_Recv(), are provided in the +* driver to allow data to be sent and received. They can be used in either +* polled or interrupt mode. +* +* @note +* +* The default configuration for the UART after initialization is: +* +* - 9,600 bps or XPAR_DFT_BAUDRATE if defined +* - 8 data bits +* - 1 stop bit +* - no parity +* - FIFO's are enabled with a receive threshold of 8 bytes +* - The RX timeout is enabled with a timeout of 1 (4 char times) +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date	Changes
+* ----- ------ -------- ----------------------------------------------
+* 1.00a	drg/jz 01/12/10 First Release
+* 1.00a sdm    09/27/11 Fixed compiler warnings and also a bug
+*		        in XUartPs_SetFlowDelay where the value was not
+*			being written to the register.
+* 1.01a sdm    12/20/11 Removed the InputClockHz parameter from the XUartPs
+*			instance structure and the driver is updated to use
+*			InputClockHz parameter from the XUartPs_Config config
+*			structure.
+*			Added a parameter to XUartPs_Config structure which
+*			specifies whether the user has selected Modem pins
+*			to be connected to MIO or FMIO.
+*			Added the tcl file to generate the xparameters.h
+* 1.02a sg     05/16/12	Changed XUARTPS_RXWM_MASK to 0x3F for CR 652540 fix.
+* 1.03a sg     07/16/12 Updated XUARTPS_FORMAT_7_BITS and XUARTPS_FORMAT_6_BITS
+*			with the correct values for CR 666724
+* 			Added defines for XUARTPS_IXR_TOVR,  XUARTPS_IXR_TNFUL
+*			and XUARTPS_IXR_TTRIG.
+*			Modified the name of these defines
+*			XUARTPS_MEDEMSR_DCDX to XUARTPS_MODEMSR_DDCD
+*			XUARTPS_MEDEMSR_RIX to XUARTPS_MODEMSR_TERI
+*			XUARTPS_MEDEMSR_DSRX to XUARTPS_MODEMSR_DDSR
+*			XUARTPS_MEDEMSR_CTSX to XUARTPS_MODEMSR_DCTS
+* 1.05a hk     08/22/13 Added API for uart reset and related
+*			constant definitions.
+* 2.0   hk      03/07/14 Version number revised.
+* 2.1   hk     04/16/14 Change XUARTPS_MAX_RATE to 921600. CR# 780625.
+* 2.2   hk     06/23/14 SW reset of RX and TX should be done when changing
+*                       baud rate. CR# 804281.
+* 3.0   vm     12/09/14 Modified source code according to misrac guideline.
+*			Support for Zynq Ultrascale Mp added.
+* 3.1	kvn    04/10/15 Modified code for latest RTL changes. Also added
+*						platform variable in driver instance structure.
+* 3.1   adk   14/03/16  Include interrupt examples in the peripheral test when
+*			uart is connected to a valid interrupt controller CR#946803.
+* 3.2   rk     07/20/16 Modified the logic for transmission break bit set
+* 3.4   ms     01/23/17 Added xil_printf statement in main function for all
+*                       examples to ensure that "Successfully ran" and "Failed"
+*                       strings are available in all examples. This is a fix
+*                       for CR-965028.
+*       ms     03/17/17 Added readme.txt file in examples folder for doxygen
+*                       generation.
+* 3.6   ms     02/16/18 Updates the flow control mode offset value in modem
+*                       control register.
+* 3.7   aru    08/17/18 Resolved MISRA-C:2012 compliance mandatory violations.
+*
+* 
+* +*****************************************************************************/ + +#ifndef XUARTPS_H /* prevent circular inclusions */ +#define XUARTPS_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files ********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xstatus.h" +#include "xuartps_hw.h" +#include "xplatform_info.h" + +/************************** Constant Definitions ****************************/ + +/* + * The following constants indicate the max and min baud rates and these + * numbers are based only on the testing that has been done. The hardware + * is capable of other baud rates. + */ +#define XUARTPS_MAX_RATE 921600U +#define XUARTPS_MIN_RATE 110U + +#define XUARTPS_DFT_BAUDRATE 115200U /* Default baud rate */ + +/** @name Configuration options + * @{ + */ +/** + * These constants specify the options that may be set or retrieved + * with the driver, each is a unique bit mask such that multiple options + * may be specified. These constants indicate the available options + * in active state. + * + */ + +#define XUARTPS_OPTION_SET_BREAK 0x0080U /**< Starts break transmission */ +#define XUARTPS_OPTION_STOP_BREAK 0x0040U /**< Stops break transmission */ +#define XUARTPS_OPTION_RESET_TMOUT 0x0020U /**< Reset the receive timeout */ +#define XUARTPS_OPTION_RESET_TX 0x0010U /**< Reset the transmitter */ +#define XUARTPS_OPTION_RESET_RX 0x0008U /**< Reset the receiver */ +#define XUARTPS_OPTION_ASSERT_RTS 0x0004U /**< Assert the RTS bit */ +#define XUARTPS_OPTION_ASSERT_DTR 0x0002U /**< Assert the DTR bit */ +#define XUARTPS_OPTION_SET_FCM 0x0001U /**< Turn on flow control mode */ +/*@}*/ + + +/** @name Channel Operational Mode + * + * The UART can operate in one of four modes: Normal, Local Loopback, Remote + * Loopback, or automatic echo. + * + * @{ + */ + +#define XUARTPS_OPER_MODE_NORMAL (u8)0x00U /**< Normal Mode */ +#define XUARTPS_OPER_MODE_AUTO_ECHO (u8)0x01U /**< Auto Echo Mode */ +#define XUARTPS_OPER_MODE_LOCAL_LOOP (u8)0x02U /**< Local Loopback Mode */ +#define XUARTPS_OPER_MODE_REMOTE_LOOP (u8)0x03U /**< Remote Loopback Mode */ + +/* @} */ + +/** @name Data format values + * + * These constants specify the data format that the driver supports. + * The data format includes the number of data bits, the number of stop + * bits and parity. + * + * @{ + */ +#define XUARTPS_FORMAT_8_BITS 0U /**< 8 data bits */ +#define XUARTPS_FORMAT_7_BITS 2U /**< 7 data bits */ +#define XUARTPS_FORMAT_6_BITS 3U /**< 6 data bits */ + +#define XUARTPS_FORMAT_NO_PARITY 4U /**< No parity */ +#define XUARTPS_FORMAT_MARK_PARITY 3U /**< Mark parity */ +#define XUARTPS_FORMAT_SPACE_PARITY 2U /**< parity */ +#define XUARTPS_FORMAT_ODD_PARITY 1U /**< Odd parity */ +#define XUARTPS_FORMAT_EVEN_PARITY 0U /**< Even parity */ + +#define XUARTPS_FORMAT_2_STOP_BIT 2U /**< 2 stop bits */ +#define XUARTPS_FORMAT_1_5_STOP_BIT 1U /**< 1.5 stop bits */ +#define XUARTPS_FORMAT_1_STOP_BIT 0U /**< 1 stop bit */ +/*@}*/ + +/** @name Callback events + * + * These constants specify the handler events that an application can handle + * using its specific handler function. Note that these constants are not bit + * mask, so only one event can be passed to an application at a time. + * + * @{ + */ +#define XUARTPS_EVENT_RECV_DATA 1U /**< Data receiving done */ +#define XUARTPS_EVENT_RECV_TOUT 2U /**< A receive timeout occurred */ +#define XUARTPS_EVENT_SENT_DATA 3U /**< Data transmission done */ +#define XUARTPS_EVENT_RECV_ERROR 4U /**< A receive error detected */ +#define XUARTPS_EVENT_MODEM 5U /**< Modem status changed */ +#define XUARTPS_EVENT_PARE_FRAME_BRKE 6U /**< A receive parity, frame, break + * error detected */ +#define XUARTPS_EVENT_RECV_ORERR 7U /**< A receive overrun error detected */ +/*@}*/ + + +/**************************** Type Definitions ******************************/ + +/** + * This typedef contains configuration information for the device. + */ +typedef struct { + u16 DeviceId; /**< Unique ID of device */ + u32 BaseAddress; /**< Base address of device (IPIF) */ + u32 InputClockHz;/**< Input clock frequency */ + s32 ModemPinsConnected; /** Specifies whether modem pins are connected + * to MIO or FMIO */ +} XUartPs_Config; + +/* Keep track of state information about a data buffer in the interrupt mode. */ +typedef struct { + u8 *NextBytePtr; + u32 RequestedBytes; + u32 RemainingBytes; +} XUartPsBuffer; + +/** + * Keep track of data format setting of a device. + */ +typedef struct { + u32 BaudRate; /**< In bps, ie 1200 */ + u32 DataBits; /**< Number of data bits */ + u32 Parity; /**< Parity */ + u8 StopBits; /**< Number of stop bits */ +} XUartPsFormat; + +/******************************************************************************/ +/** + * This data type defines a handler that an application defines to communicate + * with interrupt system to retrieve state information about an application. + * + * @param CallBackRef is a callback reference passed in by the upper layer + * when setting the handler, and is passed back to the upper layer + * when the handler is called. It is used to find the device driver + * instance. + * @param Event contains one of the event constants indicating events that + * have occurred. + * @param EventData contains the number of bytes sent or received at the + * time of the call for send and receive events and contains the + * modem status for modem events. + * + ******************************************************************************/ +typedef void (*XUartPs_Handler) (void *CallBackRef, u32 Event, + u32 EventData); + +/** + * The XUartPs driver instance data structure. A pointer to an instance data + * structure is passed around by functions to refer to a specific driver + * instance. + */ +typedef struct { + XUartPs_Config Config; /* Configuration data structure */ + u32 InputClockHz; /* Input clock frequency */ + u32 IsReady; /* Device is initialized and ready */ + u32 BaudRate; /* Current baud rate */ + + XUartPsBuffer SendBuffer; + XUartPsBuffer ReceiveBuffer; + + XUartPs_Handler Handler; + void *CallBackRef; /* Callback reference for event handler */ + u32 Platform; + u8 is_rxbs_error; +} XUartPs; + + +/***************** Macros (Inline Functions) Definitions ********************/ + +/****************************************************************************/ +/** +* Get the UART Channel Status Register. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* +* @return The value read from the register. +* +* @note C-Style signature: +* u16 XUartPs_GetChannelStatus(XUartPs *InstancePtr) +* +******************************************************************************/ +#define XUartPs_GetChannelStatus(InstancePtr) \ + Xil_In32(((InstancePtr)->Config.BaseAddress) + (u32)XUARTPS_SR_OFFSET) + +/****************************************************************************/ +/** +* Get the UART Mode Control Register. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* +* @return The value read from the register. +* +* @note C-Style signature: +* u32 XUartPs_GetControl(XUartPs *InstancePtr) +* +******************************************************************************/ +#define XUartPs_GetModeControl(InstancePtr) \ + Xil_In32(((InstancePtr)->Config.BaseAddress) + (u32)XUARTPS_CR_OFFSET) + +/****************************************************************************/ +/** +* Set the UART Mode Control Register. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* @param RegisterValue is the value to be written to the register. +* +* @return None. +* +* @note C-Style signature: +* void XUartPs_SetModeControl(XUartPs *InstancePtr, u16 RegisterValue) +* +******************************************************************************/ +#define XUartPs_SetModeControl(InstancePtr, RegisterValue) \ + Xil_Out32(((InstancePtr)->Config.BaseAddress) + (u32)XUARTPS_CR_OFFSET, \ + (u32)(RegisterValue)) + +/****************************************************************************/ +/** +* Enable the transmitter and receiver of the UART. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* +* @return None. +* +* @note C-Style signature: +* void XUartPs_EnableUart(XUartPs *InstancePtr) +* +******************************************************************************/ +#define XUartPs_EnableUart(InstancePtr) \ + Xil_Out32(((InstancePtr)->Config.BaseAddress + (u32)XUARTPS_CR_OFFSET), \ + ((Xil_In32((InstancePtr)->Config.BaseAddress + (u32)XUARTPS_CR_OFFSET) & \ + (u32)(~XUARTPS_CR_EN_DIS_MASK)) | ((u32)XUARTPS_CR_RX_EN | (u32)XUARTPS_CR_TX_EN))) + +/****************************************************************************/ +/** +* Disable the transmitter and receiver of the UART. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* +* @return None. +* +* @note C-Style signature: +* void XUartPs_DisableUart(XUartPs *InstancePtr) +* +******************************************************************************/ +#define XUartPs_DisableUart(InstancePtr) \ + Xil_Out32(((InstancePtr)->Config.BaseAddress + (u32)XUARTPS_CR_OFFSET), \ + (((Xil_In32((InstancePtr)->Config.BaseAddress + (u32)XUARTPS_CR_OFFSET)) & \ + (u32)(~XUARTPS_CR_EN_DIS_MASK)) | ((u32)XUARTPS_CR_RX_DIS | (u32)XUARTPS_CR_TX_DIS))) + +/****************************************************************************/ +/** +* Determine if the transmitter FIFO is empty. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* +* @return +* - TRUE if a byte can be sent +* - FALSE if the Transmitter Fifo is not empty +* +* @note C-Style signature: +* u32 XUartPs_IsTransmitEmpty(XUartPs InstancePtr) +* +******************************************************************************/ +#define XUartPs_IsTransmitEmpty(InstancePtr) \ + ((Xil_In32(((InstancePtr)->Config.BaseAddress) + (u32)XUARTPS_SR_OFFSET) & \ + (u32)XUARTPS_SR_TXEMPTY) == (u32)XUARTPS_SR_TXEMPTY) + + +/************************** Function Prototypes *****************************/ + +/* Static lookup function implemented in xuartps_sinit.c */ +XUartPs_Config *XUartPs_LookupConfig(u16 DeviceId); + +/* Interface functions implemented in xuartps.c */ +s32 XUartPs_CfgInitialize(XUartPs *InstancePtr, + XUartPs_Config * Config, u32 EffectiveAddr); + +u32 XUartPs_Send(XUartPs *InstancePtr,u8 *BufferPtr, + u32 NumBytes); + +u32 XUartPs_Recv(XUartPs *InstancePtr,u8 *BufferPtr, + u32 NumBytes); + +s32 XUartPs_SetBaudRate(XUartPs *InstancePtr, u32 BaudRate); + +/* Options functions in xuartps_options.c */ +void XUartPs_SetOptions(XUartPs *InstancePtr, u16 Options); + +u16 XUartPs_GetOptions(XUartPs *InstancePtr); + +void XUartPs_SetFifoThreshold(XUartPs *InstancePtr, u8 TriggerLevel); + +u8 XUartPs_GetFifoThreshold(XUartPs *InstancePtr); + +u16 XUartPs_GetModemStatus(XUartPs *InstancePtr); + +u32 XUartPs_IsSending(XUartPs *InstancePtr); + +u8 XUartPs_GetOperMode(XUartPs *InstancePtr); + +void XUartPs_SetOperMode(XUartPs *InstancePtr, u8 OperationMode); + +u8 XUartPs_GetFlowDelay(XUartPs *InstancePtr); + +void XUartPs_SetFlowDelay(XUartPs *InstancePtr, u8 FlowDelayValue); + +u8 XUartPs_GetRecvTimeout(XUartPs *InstancePtr); + +void XUartPs_SetRecvTimeout(XUartPs *InstancePtr, u8 RecvTimeout); + +s32 XUartPs_SetDataFormat(XUartPs *InstancePtr, XUartPsFormat * FormatPtr); + +void XUartPs_GetDataFormat(XUartPs *InstancePtr, XUartPsFormat * FormatPtr); + +/* interrupt functions in xuartps_intr.c */ +u32 XUartPs_GetInterruptMask(XUartPs *InstancePtr); + +void XUartPs_SetInterruptMask(XUartPs *InstancePtr, u32 Mask); + +void XUartPs_InterruptHandler(XUartPs *InstancePtr); + +void XUartPs_SetHandler(XUartPs *InstancePtr, XUartPs_Handler FuncPtr, + void *CallBackRef); + +/* self-test functions in xuartps_selftest.c */ +s32 XUartPs_SelfTest(XUartPs *InstancePtr); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/include/xuartps_hw.h b/df_datalink/bsp/ps7_cortexa9_0/include/xuartps_hw.h new file mode 100644 index 0000000..8c46ecf --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/include/xuartps_hw.h @@ -0,0 +1,447 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2017 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xuartps_hw.h +* @addtogroup uartps_v3_5 +* @{ +* +* This header file contains the hardware interface of an XUartPs device. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date	Changes
+* ----- ------ -------- ----------------------------------------------
+* 1.00	drg/jz 01/12/10 First Release
+* 1.03a sg     09/04/12 Added defines for XUARTPS_IXR_TOVR,  XUARTPS_IXR_TNFUL
+*			and XUARTPS_IXR_TTRIG.
+*			Modified the names of these defines
+*			XUARTPS_MEDEMSR_DCDX to XUARTPS_MODEMSR_DDCD
+*			XUARTPS_MEDEMSR_RIX to XUARTPS_MODEMSR_TERI
+*			XUARTPS_MEDEMSR_DSRX to XUARTPS_MODEMSR_DDSR
+*			XUARTPS_MEDEMSR_CTSX to XUARTPS_MODEMSR_DCTS
+* 1.05a hk     08/22/13 Added prototype for uart reset and related
+*			constant definitions.
+* 3.00  kvn    02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.1	kvn    04/10/15 Modified code for latest RTL changes.
+* 3.6   ms     02/16/18 Updates flow control mode offset value in
+*			modem control register.
+*
+* 
+* +******************************************************************************/ +#ifndef XUARTPS_HW_H /* prevent circular inclusions */ +#define XUARTPS_HW_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_io.h" + +/************************** Constant Definitions *****************************/ + +/** @name Register Map + * + * Register offsets for the UART. + * @{ + */ +#define XUARTPS_CR_OFFSET 0x0000U /**< Control Register [8:0] */ +#define XUARTPS_MR_OFFSET 0x0004U /**< Mode Register [9:0] */ +#define XUARTPS_IER_OFFSET 0x0008U /**< Interrupt Enable [12:0] */ +#define XUARTPS_IDR_OFFSET 0x000CU /**< Interrupt Disable [12:0] */ +#define XUARTPS_IMR_OFFSET 0x0010U /**< Interrupt Mask [12:0] */ +#define XUARTPS_ISR_OFFSET 0x0014U /**< Interrupt Status [12:0]*/ +#define XUARTPS_BAUDGEN_OFFSET 0x0018U /**< Baud Rate Generator [15:0] */ +#define XUARTPS_RXTOUT_OFFSET 0x001CU /**< RX Timeout [7:0] */ +#define XUARTPS_RXWM_OFFSET 0x0020U /**< RX FIFO Trigger Level [5:0] */ +#define XUARTPS_MODEMCR_OFFSET 0x0024U /**< Modem Control [5:0] */ +#define XUARTPS_MODEMSR_OFFSET 0x0028U /**< Modem Status [8:0] */ +#define XUARTPS_SR_OFFSET 0x002CU /**< Channel Status [14:0] */ +#define XUARTPS_FIFO_OFFSET 0x0030U /**< FIFO [7:0] */ +#define XUARTPS_BAUDDIV_OFFSET 0x0034U /**< Baud Rate Divider [7:0] */ +#define XUARTPS_FLOWDEL_OFFSET 0x0038U /**< Flow Delay [5:0] */ +#define XUARTPS_TXWM_OFFSET 0x0044U /**< TX FIFO Trigger Level [5:0] */ +#define XUARTPS_RXBS_OFFSET 0x0048U /**< RX FIFO Byte Status [11:0] */ +/* @} */ + +/** @name Control Register + * + * The Control register (CR) controls the major functions of the device. + * + * Control Register Bit Definition + */ + +#define XUARTPS_CR_STOPBRK 0x00000100U /**< Stop transmission of break */ +#define XUARTPS_CR_STARTBRK 0x00000080U /**< Set break */ +#define XUARTPS_CR_TORST 0x00000040U /**< RX timeout counter restart */ +#define XUARTPS_CR_TX_DIS 0x00000020U /**< TX disabled. */ +#define XUARTPS_CR_TX_EN 0x00000010U /**< TX enabled */ +#define XUARTPS_CR_RX_DIS 0x00000008U /**< RX disabled. */ +#define XUARTPS_CR_RX_EN 0x00000004U /**< RX enabled */ +#define XUARTPS_CR_EN_DIS_MASK 0x0000003CU /**< Enable/disable Mask */ +#define XUARTPS_CR_TXRST 0x00000002U /**< TX logic reset */ +#define XUARTPS_CR_RXRST 0x00000001U /**< RX logic reset */ +/* @}*/ + + +/** @name Mode Register + * + * The mode register (MR) defines the mode of transfer as well as the data + * format. If this register is modified during transmission or reception, + * data validity cannot be guaranteed. + * + * Mode Register Bit Definition + * @{ + */ +#define XUARTPS_MR_CCLK 0x00000400U /**< Input clock selection */ +#define XUARTPS_MR_CHMODE_R_LOOP 0x00000300U /**< Remote loopback mode */ +#define XUARTPS_MR_CHMODE_L_LOOP 0x00000200U /**< Local loopback mode */ +#define XUARTPS_MR_CHMODE_ECHO 0x00000100U /**< Auto echo mode */ +#define XUARTPS_MR_CHMODE_NORM 0x00000000U /**< Normal mode */ +#define XUARTPS_MR_CHMODE_SHIFT 8U /**< Mode shift */ +#define XUARTPS_MR_CHMODE_MASK 0x00000300U /**< Mode mask */ +#define XUARTPS_MR_STOPMODE_2_BIT 0x00000080U /**< 2 stop bits */ +#define XUARTPS_MR_STOPMODE_1_5_BIT 0x00000040U /**< 1.5 stop bits */ +#define XUARTPS_MR_STOPMODE_1_BIT 0x00000000U /**< 1 stop bit */ +#define XUARTPS_MR_STOPMODE_SHIFT 6U /**< Stop bits shift */ +#define XUARTPS_MR_STOPMODE_MASK 0x000000A0U /**< Stop bits mask */ +#define XUARTPS_MR_PARITY_NONE 0x00000020U /**< No parity mode */ +#define XUARTPS_MR_PARITY_MARK 0x00000018U /**< Mark parity mode */ +#define XUARTPS_MR_PARITY_SPACE 0x00000010U /**< Space parity mode */ +#define XUARTPS_MR_PARITY_ODD 0x00000008U /**< Odd parity mode */ +#define XUARTPS_MR_PARITY_EVEN 0x00000000U /**< Even parity mode */ +#define XUARTPS_MR_PARITY_SHIFT 3U /**< Parity setting shift */ +#define XUARTPS_MR_PARITY_MASK 0x00000038U /**< Parity mask */ +#define XUARTPS_MR_CHARLEN_6_BIT 0x00000006U /**< 6 bits data */ +#define XUARTPS_MR_CHARLEN_7_BIT 0x00000004U /**< 7 bits data */ +#define XUARTPS_MR_CHARLEN_8_BIT 0x00000000U /**< 8 bits data */ +#define XUARTPS_MR_CHARLEN_SHIFT 1U /**< Data Length shift */ +#define XUARTPS_MR_CHARLEN_MASK 0x00000006U /**< Data length mask */ +#define XUARTPS_MR_CLKSEL 0x00000001U /**< Input clock selection */ +/* @} */ + + +/** @name Interrupt Registers + * + * Interrupt control logic uses the interrupt enable register (IER) and the + * interrupt disable register (IDR) to set the value of the bits in the + * interrupt mask register (IMR). The IMR determines whether to pass an + * interrupt to the interrupt status register (ISR). + * Writing a 1 to IER Enbables an interrupt, writing a 1 to IDR disables an + * interrupt. IMR and ISR are read only, and IER and IDR are write only. + * Reading either IER or IDR returns 0x00. + * + * All four registers have the same bit definitions. + * + * @{ + */ +#define XUARTPS_IXR_RBRK 0x00002000U /**< Rx FIFO break detect interrupt */ +#define XUARTPS_IXR_TOVR 0x00001000U /**< Tx FIFO Overflow interrupt */ +#define XUARTPS_IXR_TNFUL 0x00000800U /**< Tx FIFO Nearly Full interrupt */ +#define XUARTPS_IXR_TTRIG 0x00000400U /**< Tx Trig interrupt */ +#define XUARTPS_IXR_DMS 0x00000200U /**< Modem status change interrupt */ +#define XUARTPS_IXR_TOUT 0x00000100U /**< Timeout error interrupt */ +#define XUARTPS_IXR_PARITY 0x00000080U /**< Parity error interrupt */ +#define XUARTPS_IXR_FRAMING 0x00000040U /**< Framing error interrupt */ +#define XUARTPS_IXR_OVER 0x00000020U /**< Overrun error interrupt */ +#define XUARTPS_IXR_TXFULL 0x00000010U /**< TX FIFO full interrupt. */ +#define XUARTPS_IXR_TXEMPTY 0x00000008U /**< TX FIFO empty interrupt. */ +#define XUARTPS_IXR_RXFULL 0x00000004U /**< RX FIFO full interrupt. */ +#define XUARTPS_IXR_RXEMPTY 0x00000002U /**< RX FIFO empty interrupt. */ +#define XUARTPS_IXR_RXOVR 0x00000001U /**< RX FIFO trigger interrupt. */ +#define XUARTPS_IXR_MASK 0x00003FFFU /**< Valid bit mask */ +/* @} */ + + +/** @name Baud Rate Generator Register + * + * The baud rate generator control register (BRGR) is a 16 bit register that + * controls the receiver bit sample clock and baud rate. + * Valid values are 1 - 65535. + * + * Bit Sample Rate = CCLK / BRGR, where the CCLK is selected by the MR_CCLK bit + * in the MR register. + * @{ + */ +#define XUARTPS_BAUDGEN_DISABLE 0x00000000U /**< Disable clock */ +#define XUARTPS_BAUDGEN_MASK 0x0000FFFFU /**< Valid bits mask */ +#define XUARTPS_BAUDGEN_RESET_VAL 0x0000028BU /**< Reset value */ + +/** @name Baud Divisor Rate register + * + * The baud rate divider register (BDIV) controls how much the bit sample + * rate is divided by. It sets the baud rate. + * Valid values are 0x04 to 0xFF. Writing a value less than 4 will be ignored. + * + * Baud rate = CCLK / ((BAUDDIV + 1) x BRGR), where the CCLK is selected by + * the MR_CCLK bit in the MR register. + * @{ + */ +#define XUARTPS_BAUDDIV_MASK 0x000000FFU /**< 8 bit baud divider mask */ +#define XUARTPS_BAUDDIV_RESET_VAL 0x0000000FU /**< Reset value */ +/* @} */ + + +/** @name Receiver Timeout Register + * + * Use the receiver timeout register (RTR) to detect an idle condition on + * the receiver data line. + * + * @{ + */ +#define XUARTPS_RXTOUT_DISABLE 0x00000000U /**< Disable time out */ +#define XUARTPS_RXTOUT_MASK 0x000000FFU /**< Valid bits mask */ + +/** @name Receiver FIFO Trigger Level Register + * + * Use the Receiver FIFO Trigger Level Register (RTRIG) to set the value at + * which the RX FIFO triggers an interrupt event. + * @{ + */ + +#define XUARTPS_RXWM_DISABLE 0x00000000U /**< Disable RX trigger interrupt */ +#define XUARTPS_RXWM_MASK 0x0000003FU /**< Valid bits mask */ +#define XUARTPS_RXWM_RESET_VAL 0x00000020U /**< Reset value */ +/* @} */ + +/** @name Transmit FIFO Trigger Level Register + * + * Use the Transmit FIFO Trigger Level Register (TTRIG) to set the value at + * which the TX FIFO triggers an interrupt event. + * @{ + */ + +#define XUARTPS_TXWM_MASK 0x0000003FU /**< Valid bits mask */ +#define XUARTPS_TXWM_RESET_VAL 0x00000020U /**< Reset value */ +/* @} */ + +/** @name Modem Control Register + * + * This register (MODEMCR) controls the interface with the modem or data set, + * or a peripheral device emulating a modem. + * + * @{ + */ +#define XUARTPS_MODEMCR_FCM 0x00000020U /**< Flow control mode */ +#define XUARTPS_MODEMCR_RTS 0x00000002U /**< Request to send */ +#define XUARTPS_MODEMCR_DTR 0x00000001U /**< Data terminal ready */ +/* @} */ + +/** @name Modem Status Register + * + * This register (MODEMSR) indicates the current state of the control lines + * from a modem, or another peripheral device, to the CPU. In addition, four + * bits of the modem status register provide change information. These bits + * are set to a logic 1 whenever a control input from the modem changes state. + * + * Note: Whenever the DCTS, DDSR, TERI, or DDCD bit is set to logic 1, a modem + * status interrupt is generated and this is reflected in the modem status + * register. + * + * @{ + */ +#define XUARTPS_MODEMSR_FCMS 0x00000100U /**< Flow control mode (FCMS) */ +#define XUARTPS_MODEMSR_DCD 0x00000080U /**< Complement of DCD input */ +#define XUARTPS_MODEMSR_RI 0x00000040U /**< Complement of RI input */ +#define XUARTPS_MODEMSR_DSR 0x00000020U /**< Complement of DSR input */ +#define XUARTPS_MODEMSR_CTS 0x00000010U /**< Complement of CTS input */ +#define XUARTPS_MODEMSR_DDCD 0x00000008U /**< Delta DCD indicator */ +#define XUARTPS_MODEMSR_TERI 0x00000004U /**< Trailing Edge Ring Indicator */ +#define XUARTPS_MODEMSR_DDSR 0x00000002U /**< Change of DSR */ +#define XUARTPS_MODEMSR_DCTS 0x00000001U /**< Change of CTS */ +/* @} */ + +/** @name Channel Status Register + * + * The channel status register (CSR) is provided to enable the control logic + * to monitor the status of bits in the channel interrupt status register, + * even if these are masked out by the interrupt mask register. + * + * @{ + */ +#define XUARTPS_SR_TNFUL 0x00004000U /**< TX FIFO Nearly Full Status */ +#define XUARTPS_SR_TTRIG 0x00002000U /**< TX FIFO Trigger Status */ +#define XUARTPS_SR_FLOWDEL 0x00001000U /**< RX FIFO fill over flow delay */ +#define XUARTPS_SR_TACTIVE 0x00000800U /**< TX active */ +#define XUARTPS_SR_RACTIVE 0x00000400U /**< RX active */ +#define XUARTPS_SR_TXFULL 0x00000010U /**< TX FIFO full */ +#define XUARTPS_SR_TXEMPTY 0x00000008U /**< TX FIFO empty */ +#define XUARTPS_SR_RXFULL 0x00000004U /**< RX FIFO full */ +#define XUARTPS_SR_RXEMPTY 0x00000002U /**< RX FIFO empty */ +#define XUARTPS_SR_RXOVR 0x00000001U /**< RX FIFO fill over trigger */ +/* @} */ + +/** @name Flow Delay Register + * + * Operation of the flow delay register (FLOWDEL) is very similar to the + * receive FIFO trigger register. An internal trigger signal activates when the + * FIFO is filled to the level set by this register. This trigger will not + * cause an interrupt, although it can be read through the channel status + * register. In hardware flow control mode, RTS is deactivated when the trigger + * becomes active. RTS only resets when the FIFO level is four less than the + * level of the flow delay trigger and the flow delay trigger is not activated. + * A value less than 4 disables the flow delay. + * @{ + */ +#define XUARTPS_FLOWDEL_MASK XUARTPS_RXWM_MASK /**< Valid bit mask */ +/* @} */ + +/** @name Receiver FIFO Byte Status Register + * + * The Receiver FIFO Status register is used to have a continuous + * monitoring of the raw unmasked byte status information. The register + * contains frame, parity and break status information for the top + * four bytes in the RX FIFO. + * + * Receiver FIFO Byte Status Register Bit Definition + * @{ + */ +#define XUARTPS_RXBS_BYTE3_BRKE 0x00000800U /**< Byte3 Break Error */ +#define XUARTPS_RXBS_BYTE3_FRME 0x00000400U /**< Byte3 Frame Error */ +#define XUARTPS_RXBS_BYTE3_PARE 0x00000200U /**< Byte3 Parity Error */ +#define XUARTPS_RXBS_BYTE2_BRKE 0x00000100U /**< Byte2 Break Error */ +#define XUARTPS_RXBS_BYTE2_FRME 0x00000080U /**< Byte2 Frame Error */ +#define XUARTPS_RXBS_BYTE2_PARE 0x00000040U /**< Byte2 Parity Error */ +#define XUARTPS_RXBS_BYTE1_BRKE 0x00000020U /**< Byte1 Break Error */ +#define XUARTPS_RXBS_BYTE1_FRME 0x00000010U /**< Byte1 Frame Error */ +#define XUARTPS_RXBS_BYTE1_PARE 0x00000008U /**< Byte1 Parity Error */ +#define XUARTPS_RXBS_BYTE0_BRKE 0x00000004U /**< Byte0 Break Error */ +#define XUARTPS_RXBS_BYTE0_FRME 0x00000002U /**< Byte0 Frame Error */ +#define XUARTPS_RXBS_BYTE0_PARE 0x00000001U /**< Byte0 Parity Error */ +#define XUARTPS_RXBS_MASK 0x00000007U /**< 3 bit RX byte status mask */ +/* @} */ + + +/* + * Defines for backwards compatabilty, will be removed + * in the next version of the driver + */ +#define XUARTPS_MEDEMSR_DCDX XUARTPS_MODEMSR_DDCD +#define XUARTPS_MEDEMSR_RIX XUARTPS_MODEMSR_TERI +#define XUARTPS_MEDEMSR_DSRX XUARTPS_MODEMSR_DDSR +#define XUARTPS_MEDEMSR_CTSX XUARTPS_MODEMSR_DCTS + + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + +/****************************************************************************/ +/** +* Read a UART register. +* +* @param BaseAddress contains the base address of the device. +* @param RegOffset contains the offset from the base address of the +* device. +* +* @return The value read from the register. +* +* @note C-Style signature: +* u32 XUartPs_ReadReg(u32 BaseAddress, int RegOffset) +* +******************************************************************************/ +#define XUartPs_ReadReg(BaseAddress, RegOffset) \ + Xil_In32((BaseAddress) + (u32)(RegOffset)) + +/***************************************************************************/ +/** +* Write a UART register. +* +* @param BaseAddress contains the base address of the device. +* @param RegOffset contains the offset from the base address of the +* device. +* @param RegisterValue is the value to be written to the register. +* +* @return None. +* +* @note C-Style signature: +* void XUartPs_WriteReg(u32 BaseAddress, int RegOffset, +* u16 RegisterValue) +* +******************************************************************************/ +#define XUartPs_WriteReg(BaseAddress, RegOffset, RegisterValue) \ + Xil_Out32((BaseAddress) + (u32)(RegOffset), (u32)(RegisterValue)) + +/****************************************************************************/ +/** +* Determine if there is receive data in the receiver and/or FIFO. +* +* @param BaseAddress contains the base address of the device. +* +* @return TRUE if there is receive data, FALSE otherwise. +* +* @note C-Style signature: +* u32 XUartPs_IsReceiveData(u32 BaseAddress) +* +******************************************************************************/ +#define XUartPs_IsReceiveData(BaseAddress) \ + !((Xil_In32((BaseAddress) + XUARTPS_SR_OFFSET) & \ + (u32)XUARTPS_SR_RXEMPTY) == (u32)XUARTPS_SR_RXEMPTY) + +/****************************************************************************/ +/** +* Determine if a byte of data can be sent with the transmitter. +* +* @param BaseAddress contains the base address of the device. +* +* @return TRUE if the TX FIFO is full, FALSE if a byte can be put in the +* FIFO. +* +* @note C-Style signature: +* u32 XUartPs_IsTransmitFull(u32 BaseAddress) +* +******************************************************************************/ +#define XUartPs_IsTransmitFull(BaseAddress) \ + ((Xil_In32((BaseAddress) + XUARTPS_SR_OFFSET) & \ + (u32)XUARTPS_SR_TXFULL) == (u32)XUARTPS_SR_TXFULL) + +/************************** Function Prototypes ******************************/ + +void XUartPs_SendByte(u32 BaseAddress, u8 Data); + +u8 XUartPs_RecvByte(u32 BaseAddress); + +void XUartPs_ResetHw(u32 BaseAddress); + +/************************** Variable Definitions *****************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/bram_v4_3/src/Makefile b/df_datalink/bsp/ps7_cortexa9_0/libsrc/bram_v4_3/src/Makefile new file mode 100644 index 0000000..dce15aa --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/bram_v4_3/src/Makefile @@ -0,0 +1,28 @@ +COMPILER= +ARCHIVER= +CP=cp +COMPILER_FLAGS= +EXTRA_COMPILER_FLAGS= +LIB=libxil.a + +RELEASEDIR=../../../lib +INCLUDEDIR=../../../include +INCLUDES=-I./. -I${INCLUDEDIR} + +INCLUDEFILES=*.h + +LIBSOURCES=*.c +OUTS = *.o +OBJECTS = $(addsuffix .o, $(basename $(wildcard *.c))) + +libs: + echo "Compiling bram" + $(COMPILER) $(COMPILER_FLAGS) $(EXTRA_COMPILER_FLAGS) $(INCLUDES) $(LIBSOURCES) + $(ARCHIVER) -r ${RELEASEDIR}/${LIB} $(OBJECTS) + make clean + +include: + ${CP} ${INCLUDEFILES} ${INCLUDEDIR} + +clean: + rm -rf ${OBJECTS} diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/bram_v4_3/src/xbram.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/bram_v4_3/src/xbram.c new file mode 100644 index 0000000..0976b82 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/bram_v4_3/src/xbram.c @@ -0,0 +1,145 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +/** +* @file xbram.c +* @addtogroup bram_v4_2 +* @{ +* +* The implementation of the XBram driver's basic functionality. +* See xbram.h for more information about the driver. +* +* @note +* +* None +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a sa   05/11/10 First release
+* 3.01a sa   13/01/12 Added CorrectableFailingDataRegs and
+*                     UncorrectableFailingDataRegs in
+*					  XBram_CfgInitialize API.
+* 4.1   sk   11/10/15 Used UINTPTR instead of u32 for Baseaddress CR# 867425.
+*                     Changed the prototype of XBram_CfgInitialize API.
+*
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ + +#include "xbram.h" +#include "xstatus.h" + +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Variable Definitions ****************************/ + + +/************************** Function Prototypes *****************************/ + + +/****************************************************************************/ +/** +* Initialize the XBram instance provided by the caller based on the given +* configuration data. +* +* Nothing is done except to initialize the InstancePtr. +* +* @param InstancePtr is a pointer to an XBram instance. +* The memory the pointer references must be pre-allocated by +* the caller. Further calls to manipulate the driver through +* the XBram API must be made with this pointer. +* @param Config is a reference to a structure containing information +* about a specific BRAM device. This function +* initializes an InstancePtr object for a specific device +* specified by the contents of Config. This function can +* initialize multiple instance objects with the use of multiple +* calls giving different Config information on each call. +* @param EffectiveAddr is the device base address in the virtual memory +* address space. The caller is responsible for keeping the +* address mapping from EffectiveAddr to the device physical base +* address unchanged once this function is invoked. Unexpected +* errors may occur if the address mapping changes after this +* function is called. If address translation is not used, use +* Config->BaseAddress for this parameters, passing the physical +* address instead. +* +* @return +* - XST_SUCCESS Initialization was successful. +* +* @note None. +* +*****************************************************************************/ +int XBram_CfgInitialize(XBram *InstancePtr, + XBram_Config *Config, + UINTPTR EffectiveAddr) +{ + /* + * Assert arguments + */ + Xil_AssertNonvoid(InstancePtr != NULL); + + /* + * Set some default values. + */ + InstancePtr->Config.CtrlBaseAddress = EffectiveAddr; + InstancePtr->Config.MemBaseAddress = Config->MemBaseAddress; + InstancePtr->Config.MemHighAddress = Config->MemHighAddress; + InstancePtr->Config.DataWidth = Config->DataWidth; + InstancePtr->Config.EccPresent = Config->EccPresent; + InstancePtr->Config.FaultInjectionPresent = + Config->FaultInjectionPresent; + InstancePtr->Config.CorrectableFailingRegisters = + Config->CorrectableFailingRegisters; + InstancePtr->Config.CorrectableFailingDataRegs = + Config->CorrectableFailingDataRegs; + InstancePtr->Config.UncorrectableFailingRegisters = + Config->UncorrectableFailingRegisters; + InstancePtr->Config.UncorrectableFailingDataRegs = + Config->UncorrectableFailingDataRegs; + InstancePtr->Config.EccStatusInterruptPresent = + Config->EccStatusInterruptPresent; + InstancePtr->Config.CorrectableCounterBits = + Config->CorrectableCounterBits; + InstancePtr->Config.WriteAccess = Config->WriteAccess; + + /* + * Indicate the instance is now ready to use, initialized without error + */ + InstancePtr->IsReady = XIL_COMPONENT_IS_READY; + return (XST_SUCCESS); +} + +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/bram_v4_3/src/xbram.h b/df_datalink/bsp/ps7_cortexa9_0/libsrc/bram_v4_3/src/xbram.h new file mode 100644 index 0000000..246df6d --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/bram_v4_3/src/xbram.h @@ -0,0 +1,223 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file xbram.h +* @addtogroup bram_v4_2 +* @{ +* @details +* +* If ECC is not enabled, this driver exists only to allow the tools to +* create a memory test application and to populate xparameters.h with memory +* range constants. In this case there is no source code. +* +* If ECC is enabled, this file contains the software API definition of the +* Xilinx BRAM Interface Controller (XBram) device driver. +* +* The Xilinx BRAM controller is a soft IP core designed for Xilinx +* FPGAs and contains the following general features: +* - LMB v2.0 bus interfaces with byte enable support +* - Used in conjunction with bram_block peripheral to provide fast BRAM +* memory solution for MicroBlaze ILMB and DLMB ports +* - Supports byte, half-word, and word transfers +* - Supports optional BRAM error correction and detection. +* +* The driver provides interrupt management functions. Implementation of +* interrupt handlers is left to the user. Refer to the provided interrupt +* example in the examples directory for details. +* +* This driver is intended to be RTOS and processor independent. Any needs for +* dynamic memory management, threads or thread mutual exclusion, virtual +* memory, or cache control must be satisfied by the layer above this driver. +* +* Initialization & Configuration +* +* The XBram_Config structure is used by the driver to configure +* itself. This configuration structure is typically created by the tool-chain +* based on HW build properties. +* +* To support multiple runtime loading and initialization strategies employed +* by various operating systems, the driver instance can be initialized as +* follows: +* +* - XBram_CfgInitialize(InstancePtr, CfgPtr, EffectiveAddr) - +* Uses a configuration structure provided by the caller. If running in a +* system with address translation, the provided virtual memory base address +* replaces the physical address present in the configuration structure. +* +* @note +* +* This API utilizes 32 bit I/O to the BRAM registers. With less +* than 32 bits, the unused bits from registers are read as zero and written as +* don't cares. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 3.00a sa  05/11/10 Added ECC support
+* 3.01a sa  01/13/12  Changed Selftest API from
+*		      XBram_SelfTest(XBram *InstancePtr) to
+*		      XBram_SelfTest(XBram *InstancePtr, u8 IntMask) and
+*		      fixed a problem with interrupt generation for CR 639274
+*		      Modified Selftest example to return XST_SUCCESS when
+*		      ECC is not enabled and return XST_FAILURE when ECC is
+*		      enabled and Control Base Address is zero (CR 636581)
+*		      Modified Selftest to use correct CorrectableCounterBits
+*		      for CR 635655
+*		      Updated to check CorrectableFailingDataRegs in the case
+*		      of LMB BRAM.
+* 		      Added CorrectableFailingDataRegs and
+*		      UncorrectableFailingDataRegs to the config structure to
+*		      distinguish between AXI BRAM and LMB BRAM.
+*		      These registers are not present in the current version of
+*		      the AXI BRAM Controller.
+* 3.02a sa 04/16/12   Added test of byte and halfword read-modify-write
+* 3.02a sa 04/16/12   Modified driver tcl to sort the address parameters
+*  	       	      to support both xps and vivado designs.
+* 3.02a adk 24/4/13   Modified the tcl file to avoid warnings
+*	       	      when ecc is disabled cr:705002.
+* 3.03a bss 05/22/13  Added Xil_DCacheFlushRange in xbram_selftest.c to
+*		      flush the Cache after writing to BRAM in InjectErrors
+*		      API(CR #719011)
+* 4.0   adk  19/12/13 Updated as per the New Tcl API's
+* 4.1   sk   11/10/15 Used UINTPTR instead of u32 for Baseaddress CR# 867425.
+*                     Changed the prototype of XBram_CfgInitialize API.
+*       ms  01/23/17 Modified xil_printf statement in main function for all
+*                    examples to ensure that "Successfully ran" and "Failed"
+*                    strings are available in all examples. This is a fix
+*                    for CR-965028.
+*       ms  03/17/17 Added readme.txt file in examples folder for doxygen
+*                    generation.
+* 4.2   ms  04/18/17 Modified tcl file to add suffix U for all macro
+*                    definitions of bram in xparameters.h
+*       ms  08/07/17 Fixed compilation warnings in xbram_sinit.c
+* 4.3   aru 03/23/19 Used UINTPTR instead of u32 for MemBaseAddress and
+*                    MemHighAddress.
+* 
+*****************************************************************************/ +#ifndef XBRAM_H /* prevent circular inclusions */ +#define XBRAM_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files ********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xstatus.h" +#include "xbram_hw.h" + +/************************** Constant Definitions ****************************/ + + +/**************************** Type Definitions ******************************/ + +/** + * This typedef contains configuration information for the device. + */ +typedef struct { + u16 DeviceId; /**< Unique ID of device */ + u32 DataWidth; /**< BRAM data width */ + int EccPresent; /**< Is ECC supported in H/W */ + int FaultInjectionPresent; /**< Is Fault Injection + * supported in H/W */ + int CorrectableFailingRegisters; /**< Is Correctable Failing Registers + * supported in H/W */ + int CorrectableFailingDataRegs; /**< Is Correctable Failing Data + * Registers supported in H/W */ + int UncorrectableFailingRegisters; /**< Is Un-correctable Failing + * Registers supported in H/W */ + int UncorrectableFailingDataRegs; /**< Is Un-correctable Failing Data + * Registers supported in H/W */ + int EccStatusInterruptPresent; /**< Are ECC status and interrupts + * supported in H/W */ + int CorrectableCounterBits; /**< Number of bits in the + * Correctable Error Counter */ + int EccOnOffRegister; /**< Is ECC on/off register supported + * in h/w */ + int EccOnOffResetValue; /**< Reset value of the ECC on/off + * register in h/w */ + int WriteAccess; /**< Is write access enabled in + * h/w */ + UINTPTR MemBaseAddress; /**< Device memory base address */ + UINTPTR MemHighAddress; /**< Device memory high address */ + UINTPTR CtrlBaseAddress; /**< Device register base address.*/ + UINTPTR CtrlHighAddress; /**< Device register base address.*/ +} XBram_Config; + +/** + * The XBram driver instance data. The user is required to + * allocate a variable of this type for every BRAM device in the + * system. A pointer to a variable of this type is then passed to the driver + * API functions. + */ +typedef struct { + XBram_Config Config; /* BRAM config structure */ + u32 IsReady; /* Device is initialized and ready */ +} XBram; + +/***************** Macros (Inline Functions) Definitions ********************/ + + +/************************** Function Prototypes *****************************/ + +/* + * Functions in xbram_sinit.c + */ +XBram_Config *XBram_LookupConfig(u16 DeviceId); + +/* + * Functions implemented in xbram.c + */ +int XBram_CfgInitialize(XBram *InstancePtr, XBram_Config *Config, + UINTPTR EffectiveAddr); + +/* + * Functions implemented in xbram_selftest.c + */ +int XBram_SelfTest(XBram *InstancePtr, u8 IntMask); + +/* + * Functions implemented in xbram_intr.c + */ +void XBram_InterruptEnable(XBram *InstancePtr, u32 Mask); +void XBram_InterruptDisable(XBram *InstancePtr, u32 Mask); +void XBram_InterruptClear(XBram *InstancePtr, u32 Mask); +u32 XBram_InterruptGetEnabled(XBram *InstancePtr); +u32 XBram_InterruptGetStatus(XBram *InstancePtr); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/bram_v4_3/src/xbram_g.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/bram_v4_3/src/xbram_g.c new file mode 100644 index 0000000..df2bd77 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/bram_v4_3/src/xbram_g.c @@ -0,0 +1,104 @@ + +/******************************************************************* +* +* CAUTION: This file is automatically generated by HSI. +* Version: 2019.1.3 +* DO NOT EDIT. +* +* Copyright (C) 2010-2023 Xilinx, Inc. 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 +*XILINX 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. +* +*Except as contained in this notice, the name of the Xilinx shall not be used +*in advertising or otherwise to promote the sale, use or other dealings in +*this Software without prior written authorization from Xilinx. +* + +* +* Description: Driver configuration +* +*******************************************************************/ + +#include "xparameters.h" +#include "xbram.h" + +/* +* The configuration table for devices +*/ + +XBram_Config XBram_ConfigTable[] = +{ + { + XPAR_PHY_DATA_INTERFACE_ANT_CONFIG_AXI_BRAM_CTRL_DEVICE_ID, + XPAR_PHY_DATA_INTERFACE_ANT_CONFIG_AXI_BRAM_CTRL_DATA_WIDTH, + XPAR_PHY_DATA_INTERFACE_ANT_CONFIG_AXI_BRAM_CTRL_ECC, + XPAR_PHY_DATA_INTERFACE_ANT_CONFIG_AXI_BRAM_CTRL_FAULT_INJECT, + XPAR_PHY_DATA_INTERFACE_ANT_CONFIG_AXI_BRAM_CTRL_CE_FAILING_REGISTERS, + 0, + XPAR_PHY_DATA_INTERFACE_ANT_CONFIG_AXI_BRAM_CTRL_UE_FAILING_REGISTERS, + 0, + XPAR_PHY_DATA_INTERFACE_ANT_CONFIG_AXI_BRAM_CTRL_ECC_STATUS_REGISTERS, + XPAR_PHY_DATA_INTERFACE_ANT_CONFIG_AXI_BRAM_CTRL_CE_COUNTER_WIDTH, + XPAR_PHY_DATA_INTERFACE_ANT_CONFIG_AXI_BRAM_CTRL_ECC_ONOFF_REGISTER, + XPAR_PHY_DATA_INTERFACE_ANT_CONFIG_AXI_BRAM_CTRL_ECC_ONOFF_RESET_VALUE, + XPAR_PHY_DATA_INTERFACE_ANT_CONFIG_AXI_BRAM_CTRL_WRITE_ACCESS, + XPAR_PHY_DATA_INTERFACE_ANT_CONFIG_AXI_BRAM_CTRL_S_AXI_BASEADDR, + XPAR_PHY_DATA_INTERFACE_ANT_CONFIG_AXI_BRAM_CTRL_S_AXI_HIGHADDR, + XPAR_PHY_DATA_INTERFACE_ANT_CONFIG_AXI_BRAM_CTRL_S_AXI_CTRL_BASEADDR, + XPAR_PHY_DATA_INTERFACE_ANT_CONFIG_AXI_BRAM_CTRL_S_AXI_CTRL_HIGHADDR + }, + { + XPAR_PHY_DATA_INTERFACE_PHY_RX_BUFF_AXI_BRAM_CTRL_DEVICE_ID, + XPAR_PHY_DATA_INTERFACE_PHY_RX_BUFF_AXI_BRAM_CTRL_DATA_WIDTH, + XPAR_PHY_DATA_INTERFACE_PHY_RX_BUFF_AXI_BRAM_CTRL_ECC, + XPAR_PHY_DATA_INTERFACE_PHY_RX_BUFF_AXI_BRAM_CTRL_FAULT_INJECT, + XPAR_PHY_DATA_INTERFACE_PHY_RX_BUFF_AXI_BRAM_CTRL_CE_FAILING_REGISTERS, + 0, + XPAR_PHY_DATA_INTERFACE_PHY_RX_BUFF_AXI_BRAM_CTRL_UE_FAILING_REGISTERS, + 0, + XPAR_PHY_DATA_INTERFACE_PHY_RX_BUFF_AXI_BRAM_CTRL_ECC_STATUS_REGISTERS, + XPAR_PHY_DATA_INTERFACE_PHY_RX_BUFF_AXI_BRAM_CTRL_CE_COUNTER_WIDTH, + XPAR_PHY_DATA_INTERFACE_PHY_RX_BUFF_AXI_BRAM_CTRL_ECC_ONOFF_REGISTER, + XPAR_PHY_DATA_INTERFACE_PHY_RX_BUFF_AXI_BRAM_CTRL_ECC_ONOFF_RESET_VALUE, + XPAR_PHY_DATA_INTERFACE_PHY_RX_BUFF_AXI_BRAM_CTRL_WRITE_ACCESS, + XPAR_PHY_DATA_INTERFACE_PHY_RX_BUFF_AXI_BRAM_CTRL_S_AXI_BASEADDR, + XPAR_PHY_DATA_INTERFACE_PHY_RX_BUFF_AXI_BRAM_CTRL_S_AXI_HIGHADDR, + XPAR_PHY_DATA_INTERFACE_PHY_RX_BUFF_AXI_BRAM_CTRL_S_AXI_CTRL_BASEADDR, + XPAR_PHY_DATA_INTERFACE_PHY_RX_BUFF_AXI_BRAM_CTRL_S_AXI_CTRL_HIGHADDR + }, + { + XPAR_PHY_DATA_INTERFACE_PHY_TX_BUFF_AXI_BRAM_CTRL_DEVICE_ID, + XPAR_PHY_DATA_INTERFACE_PHY_TX_BUFF_AXI_BRAM_CTRL_DATA_WIDTH, + XPAR_PHY_DATA_INTERFACE_PHY_TX_BUFF_AXI_BRAM_CTRL_ECC, + XPAR_PHY_DATA_INTERFACE_PHY_TX_BUFF_AXI_BRAM_CTRL_FAULT_INJECT, + XPAR_PHY_DATA_INTERFACE_PHY_TX_BUFF_AXI_BRAM_CTRL_CE_FAILING_REGISTERS, + 0, + XPAR_PHY_DATA_INTERFACE_PHY_TX_BUFF_AXI_BRAM_CTRL_UE_FAILING_REGISTERS, + 0, + XPAR_PHY_DATA_INTERFACE_PHY_TX_BUFF_AXI_BRAM_CTRL_ECC_STATUS_REGISTERS, + XPAR_PHY_DATA_INTERFACE_PHY_TX_BUFF_AXI_BRAM_CTRL_CE_COUNTER_WIDTH, + XPAR_PHY_DATA_INTERFACE_PHY_TX_BUFF_AXI_BRAM_CTRL_ECC_ONOFF_REGISTER, + XPAR_PHY_DATA_INTERFACE_PHY_TX_BUFF_AXI_BRAM_CTRL_ECC_ONOFF_RESET_VALUE, + XPAR_PHY_DATA_INTERFACE_PHY_TX_BUFF_AXI_BRAM_CTRL_WRITE_ACCESS, + XPAR_PHY_DATA_INTERFACE_PHY_TX_BUFF_AXI_BRAM_CTRL_S_AXI_BASEADDR, + XPAR_PHY_DATA_INTERFACE_PHY_TX_BUFF_AXI_BRAM_CTRL_S_AXI_HIGHADDR, + XPAR_PHY_DATA_INTERFACE_PHY_TX_BUFF_AXI_BRAM_CTRL_S_AXI_CTRL_BASEADDR, + XPAR_PHY_DATA_INTERFACE_PHY_TX_BUFF_AXI_BRAM_CTRL_S_AXI_CTRL_HIGHADDR + } +}; + + diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/bram_v4_3/src/xbram_hw.h b/df_datalink/bsp/ps7_cortexa9_0/libsrc/bram_v4_3/src/xbram_hw.h new file mode 100644 index 0000000..55a2505 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/bram_v4_3/src/xbram_hw.h @@ -0,0 +1,405 @@ +/****************************************************************************** +* +* Copyright (C) 2011 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xbram_hw.h +* @addtogroup bram_v4_2 +* @{ +* +* This header file contains identifiers and driver functions (or +* macros) that can be used to access the device. The user should refer to the +* hardware device specification for more details of the device operation. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a sa   24/11/10 First release
+* 
+* +******************************************************************************/ +#ifndef XBRAM_HW_H /* prevent circular inclusions */ +#define XBRAM_HW_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_io.h" + +/************************** Constant Definitions *****************************/ + +/** @name Registers + * + * Register offsets for this device. + * @{ + */ + +#define XBRAM_ECC_STATUS_OFFSET 0x0 /**< ECC status Register */ +#define XBRAM_ECC_EN_IRQ_OFFSET 0x4 /**< ECC interrupt enable Register */ +#define XBRAM_ECC_ON_OFF_OFFSET 0x8 /**< ECC on/off register */ +#define XBRAM_CE_CNT_OFFSET 0xC /**< Correctable error counter Register */ + +#define XBRAM_CE_FFD_0_OFFSET 0x100 /**< Correctable error first failing + * data Register, 31-0 */ +#define XBRAM_CE_FFD_1_OFFSET 0x104 /**< Correctable error first failing + * data Register, 63-32 */ +#define XBRAM_CE_FFD_2_OFFSET 0x108 /**< Correctable error first failing + * data Register, 95-64 */ +#define XBRAM_CE_FFD_3_OFFSET 0x10C /**< Correctable error first failing + * data Register, 127-96 */ +#define XBRAM_CE_FFD_4_OFFSET 0x110 /**< Correctable error first failing + * data Register, 159-128 */ +#define XBRAM_CE_FFD_5_OFFSET 0x114 /**< Correctable error first failing + * data Register, 191-160 */ +#define XBRAM_CE_FFD_6_OFFSET 0x118 /**< Correctable error first failing + * data Register, 223-192 */ +#define XBRAM_CE_FFD_7_OFFSET 0x11C /**< Correctable error first failing + * data Register, 255-224 */ +#define XBRAM_CE_FFD_8_OFFSET 0x120 /**< Correctable error first failing + * data Register, 287-256 */ +#define XBRAM_CE_FFD_9_OFFSET 0x124 /**< Correctable error first failing + * data Register, 319-288 */ +#define XBRAM_CE_FFD_10_OFFSET 0x128 /**< Correctable error first failing + * data Register, 351-320 */ +#define XBRAM_CE_FFD_11_OFFSET 0x12C /**< Correctable error first failing + * data Register, 383-352 */ +#define XBRAM_CE_FFD_12_OFFSET 0x130 /**< Correctable error first failing + * data Register, 415-384 */ +#define XBRAM_CE_FFD_13_OFFSET 0x134 /**< Correctable error first failing + * data Register, 447-416 */ +#define XBRAM_CE_FFD_14_OFFSET 0x138 /**< Correctable error first failing + * data Register, 479-448 */ +#define XBRAM_CE_FFD_15_OFFSET 0x13C /**< Correctable error first failing + * data Register, 511-480 */ +#define XBRAM_CE_FFD_16_OFFSET 0x140 /**< Correctable error first failing + * data Register, 543-512 */ +#define XBRAM_CE_FFD_17_OFFSET 0x144 /**< Correctable error first failing + * data Register, 575-544 */ +#define XBRAM_CE_FFD_18_OFFSET 0x148 /**< Correctable error first failing + * data Register, 607-576 */ +#define XBRAM_CE_FFD_19_OFFSET 0x14C /**< Correctable error first failing + * data Register, 639-608 */ +#define XBRAM_CE_FFD_20_OFFSET 0x150 /**< Correctable error first failing + * data Register, 671-640 */ +#define XBRAM_CE_FFD_21_OFFSET 0x154 /**< Correctable error first failing + * data Register, 703-672 */ +#define XBRAM_CE_FFD_22_OFFSET 0x158 /**< Correctable error first failing + * data Register, 735-704 */ +#define XBRAM_CE_FFD_23_OFFSET 0x15C /**< Correctable error first failing + * data Register, 767-736 */ +#define XBRAM_CE_FFD_24_OFFSET 0x160 /**< Correctable error first failing + * data Register, 799-768 */ +#define XBRAM_CE_FFD_25_OFFSET 0x164 /**< Correctable error first failing + * data Register, 831-800 */ +#define XBRAM_CE_FFD_26_OFFSET 0x168 /**< Correctable error first failing + * data Register, 863-832 */ +#define XBRAM_CE_FFD_27_OFFSET 0x16C /**< Correctable error first failing + * data Register, 895-864 */ +#define XBRAM_CE_FFD_28_OFFSET 0x170 /**< Correctable error first failing + * data Register, 927-896 */ +#define XBRAM_CE_FFD_29_OFFSET 0x174 /**< Correctable error first failing + * data Register, 959-928 */ +#define XBRAM_CE_FFD_30_OFFSET 0x178 /**< Correctable error first failing + * data Register, 991-960 */ +#define XBRAM_CE_FFD_31_OFFSET 0x17C /**< Correctable error first failing + * data Register, 1023-992 */ + +#define XBRAM_CE_FFE_0_OFFSET 0x180 /**< Correctable error first failing + * ECC Register, 31-0 */ +#define XBRAM_CE_FFE_1_OFFSET 0x184 /**< Correctable error first failing + * ECC Register, 63-32 */ +#define XBRAM_CE_FFE_2_OFFSET 0x188 /**< Correctable error first failing + * ECC Register, 95-64 */ +#define XBRAM_CE_FFE_3_OFFSET 0x18C /**< Correctable error first failing + * ECC Register, 127-96 */ +#define XBRAM_CE_FFE_4_OFFSET 0x190 /**< Correctable error first failing + * ECC Register, 159-128 */ +#define XBRAM_CE_FFE_5_OFFSET 0x194 /**< Correctable error first failing + * ECC Register, 191-160 */ +#define XBRAM_CE_FFE_6_OFFSET 0x198 /**< Correctable error first failing + * ECC Register, 223-192 */ +#define XBRAM_CE_FFE_7_OFFSET 0x19C /**< Correctable error first failing + * ECC Register, 255-224 */ + +#define XBRAM_CE_FFA_0_OFFSET 0x1C0 /**< Correctable error first failing + * address Register 31-0 */ +#define XBRAM_CE_FFA_1_OFFSET 0x1C4 /**< Correctable error first failing + * address Register 63-32 */ + +#define XBRAM_UE_FFD_0_OFFSET 0x200 /**< Uncorrectable error first failing + * data Register, 31-0 */ +#define XBRAM_UE_FFD_1_OFFSET 0x204 /**< Uncorrectable error first failing + * data Register, 63-32 */ +#define XBRAM_UE_FFD_2_OFFSET 0x208 /**< Uncorrectable error first failing + * data Register, 95-64 */ +#define XBRAM_UE_FFD_3_OFFSET 0x20C /**< Uncorrectable error first failing + * data Register, 127-96 */ +#define XBRAM_UE_FFD_4_OFFSET 0x210 /**< Uncorrectable error first failing + * data Register, 159-128 */ +#define XBRAM_UE_FFD_5_OFFSET 0x214 /**< Uncorrectable error first failing + * data Register, 191-160 */ +#define XBRAM_UE_FFD_6_OFFSET 0x218 /**< Uncorrectable error first failing + * data Register, 223-192 */ +#define XBRAM_UE_FFD_7_OFFSET 0x21C /**< Uncorrectable error first failing + * data Register, 255-224 */ +#define XBRAM_UE_FFD_8_OFFSET 0x220 /**< Uncorrectable error first failing + * data Register, 287-256 */ +#define XBRAM_UE_FFD_9_OFFSET 0x224 /**< Uncorrectable error first failing + * data Register, 319-288 */ +#define XBRAM_UE_FFD_10_OFFSET 0x228 /**< Uncorrectable error first failing + * data Register, 351-320 */ +#define XBRAM_UE_FFD_11_OFFSET 0x22C /**< Uncorrectable error first failing + * data Register, 383-352 */ +#define XBRAM_UE_FFD_12_OFFSET 0x230 /**< Uncorrectable error first failing + * data Register, 415-384 */ +#define XBRAM_UE_FFD_13_OFFSET 0x234 /**< Uncorrectable error first failing + * data Register, 447-416 */ +#define XBRAM_UE_FFD_14_OFFSET 0x238 /**< Uncorrectable error first failing + * data Register, 479-448 */ +#define XBRAM_UE_FFD_15_OFFSET 0x23C /**< Uncorrectable error first failing + * data Register, 511-480 */ +#define XBRAM_UE_FFD_16_OFFSET 0x240 /**< Uncorrectable error first failing + * data Register, 543-512 */ +#define XBRAM_UE_FFD_17_OFFSET 0x244 /**< Uncorrectable error first failing + * data Register, 575-544 */ +#define XBRAM_UE_FFD_18_OFFSET 0x248 /**< Uncorrectable error first failing + * data Register, 607-576 */ +#define XBRAM_UE_FFD_19_OFFSET 0x24C /**< Uncorrectable error first failing + * data Register, 639-608 */ +#define XBRAM_UE_FFD_20_OFFSET 0x250 /**< Uncorrectable error first failing + * data Register, 671-640 */ +#define XBRAM_UE_FFD_21_OFFSET 0x254 /**< Uncorrectable error first failing + * data Register, 703-672 */ +#define XBRAM_UE_FFD_22_OFFSET 0x258 /**< Uncorrectable error first failing + * data Register, 735-704 */ +#define XBRAM_UE_FFD_23_OFFSET 0x25C /**< Uncorrectable error first failing + * data Register, 767-736 */ +#define XBRAM_UE_FFD_24_OFFSET 0x260 /**< Uncorrectable error first failing + * data Register, 799-768 */ +#define XBRAM_UE_FFD_25_OFFSET 0x264 /**< Uncorrectable error first failing + * data Register, 831-800 */ +#define XBRAM_UE_FFD_26_OFFSET 0x268 /**< Uncorrectable error first failing + * data Register, 863-832 */ +#define XBRAM_UE_FFD_27_OFFSET 0x26C /**< Uncorrectable error first failing + * data Register, 895-864 */ +#define XBRAM_UE_FFD_28_OFFSET 0x270 /**< Uncorrectable error first failing + * data Register, 927-896 */ +#define XBRAM_UE_FFD_29_OFFSET 0x274 /**< Uncorrectable error first failing + * data Register, 959-928 */ +#define XBRAM_UE_FFD_30_OFFSET 0x278 /**< Uncorrectable error first failing + * data Register, 991-960 */ +#define XBRAM_UE_FFD_31_OFFSET 0x27C /**< Uncorrectable error first failing + * data Register, 1023-992 */ + +#define XBRAM_UE_FFE_0_OFFSET 0x280 /**< Uncorrectable error first failing + * ECC Register, 31-0 */ +#define XBRAM_UE_FFE_1_OFFSET 0x284 /**< Uncorrectable error first failing + * ECC Register, 63-32 */ +#define XBRAM_UE_FFE_2_OFFSET 0x288 /**< Uncorrectable error first failing + * ECC Register, 95-64 */ +#define XBRAM_UE_FFE_3_OFFSET 0x28C /**< Uncorrectable error first failing + * ECC Register, 127-96 */ +#define XBRAM_UE_FFE_4_OFFSET 0x290 /**< Uncorrectable error first failing + * ECC Register, 159-128 */ +#define XBRAM_UE_FFE_5_OFFSET 0x294 /**< Uncorrectable error first failing + * ECC Register, 191-160 */ +#define XBRAM_UE_FFE_6_OFFSET 0x298 /**< Uncorrectable error first failing + * ECC Register, 223-192 */ +#define XBRAM_UE_FFE_7_OFFSET 0x29C /**< Uncorrectable error first failing + * ECC Register, 255-224 */ + +#define XBRAM_UE_FFA_0_OFFSET 0x2C0 /**< Uncorrectable error first failing + * address Register 31-0 */ +#define XBRAM_UE_FFA_1_OFFSET 0x2C4 /**< Uncorrectable error first failing + * address Register 63-32 */ + +#define XBRAM_FI_D_0_OFFSET 0x300 /**< Fault injection Data Register, + * 31-0 */ +#define XBRAM_FI_D_1_OFFSET 0x304 /**< Fault injection Data Register, + * 63-32 */ +#define XBRAM_FI_D_2_OFFSET 0x308 /**< Fault injection Data Register, + * 95-64 */ +#define XBRAM_FI_D_3_OFFSET 0x30C /**< Fault injection Data Register, + * 127-96 */ +#define XBRAM_FI_D_4_OFFSET 0x310 /**< Fault injection Data Register, + * 159-128 */ +#define XBRAM_FI_D_5_OFFSET 0x314 /**< Fault injection Data Register, + * 191-160 */ +#define XBRAM_FI_D_6_OFFSET 0x318 /**< Fault injection Data Register, + * 223-192 */ +#define XBRAM_FI_D_7_OFFSET 0x31C /**< Fault injection Data Register, + * 255-224 */ +#define XBRAM_FI_D_8_OFFSET 0x320 /**< Fault injection Data Register, + * 287-256 */ +#define XBRAM_FI_D_9_OFFSET 0x324 /**< Fault injection Data Register, + * 319-288 */ +#define XBRAM_FI_D_10_OFFSET 0x328 /**< Fault injection Data Register, + * 351-320 */ +#define XBRAM_FI_D_11_OFFSET 0x32C /**< Fault injection Data Register, + * 383-352 */ +#define XBRAM_FI_D_12_OFFSET 0x330 /**< Fault injection Data Register, + * 415-384 */ +#define XBRAM_FI_D_13_OFFSET 0x334 /**< Fault injection Data Register, + * 447-416 */ +#define XBRAM_FI_D_14_OFFSET 0x338 /**< Fault injection Data Register, + * 479-448 */ +#define XBRAM_FI_D_15_OFFSET 0x33C /**< Fault injection Data Register, + * 511-480 */ +#define XBRAM_FI_D_16_OFFSET 0x340 /**< Fault injection Data Register, + * 543-512 */ +#define XBRAM_FI_D_17_OFFSET 0x344 /**< Fault injection Data Register, + * 575-544 */ +#define XBRAM_FI_D_18_OFFSET 0x348 /**< Fault injection Data Register, + * 607-576 */ +#define XBRAM_FI_D_19_OFFSET 0x34C /**< Fault injection Data Register, + * 639-608 */ +#define XBRAM_FI_D_20_OFFSET 0x350 /**< Fault injection Data Register, + * 671-640 */ +#define XBRAM_FI_D_21_OFFSET 0x354 /**< Fault injection Data Register, + * 703-672 */ +#define XBRAM_FI_D_22_OFFSET 0x358 /**< Fault injection Data Register, + * 735-704 */ +#define XBRAM_FI_D_23_OFFSET 0x35C /**< Fault injection Data Register, + * 767-736 */ +#define XBRAM_FI_D_24_OFFSET 0x360 /**< Fault injection Data Register, + * 799-768 */ +#define XBRAM_FI_D_25_OFFSET 0x364 /**< Fault injection Data Register, + * 831-800 */ +#define XBRAM_FI_D_26_OFFSET 0x368 /**< Fault injection Data Register, + * 863-832 */ +#define XBRAM_FI_D_27_OFFSET 0x36C /**< Fault injection Data Register, + * 895-864 */ +#define XBRAM_FI_D_28_OFFSET 0x370 /**< Fault injection Data Register, + * 927-896 */ +#define XBRAM_FI_D_29_OFFSET 0x374 /**< Fault injection Data Register, + * 959-928 */ +#define XBRAM_FI_D_30_OFFSET 0x378 /**< Fault injection Data Register, + * 991-960 */ +#define XBRAM_FI_D_31_OFFSET 0x37C /**< Fault injection Data Register, + * 1023-992 */ + +#define XBRAM_FI_ECC_0_OFFSET 0x380 /**< Fault injection ECC Register, + * 31-0 */ +#define XBRAM_FI_ECC_1_OFFSET 0x384 /**< Fault injection ECC Register, + * 63-32 */ +#define XBRAM_FI_ECC_2_OFFSET 0x388 /**< Fault injection ECC Register, + * 95-64 */ +#define XBRAM_FI_ECC_3_OFFSET 0x38C /**< Fault injection ECC Register, + * 127-96 */ +#define XBRAM_FI_ECC_4_OFFSET 0x390 /**< Fault injection ECC Register, + * 159-128 */ +#define XBRAM_FI_ECC_5_OFFSET 0x394 /**< Fault injection ECC Register, + * 191-160 */ +#define XBRAM_FI_ECC_6_OFFSET 0x398 /**< Fault injection ECC Register, + * 223-192 */ +#define XBRAM_FI_ECC_7_OFFSET 0x39C /**< Fault injection ECC Register, + * 255-224 */ + + +/* @} */ + +/** @name Interrupt Status and Enable Register bitmaps and masks + * + * Bit definitions for the ECC status register and ECC interrupt enable register. + * @{ + */ +#define XBRAM_IR_CE_MASK 0x2 /**< Mask for the correctable error */ +#define XBRAM_IR_UE_MASK 0x1 /**< Mask for the uncorrectable error */ +#define XBRAM_IR_ALL_MASK 0x3 /**< Mask of all bits */ +/*@}*/ + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + +#define XBram_In32 Xil_In32 +#define XBram_Out32 Xil_Out32 + +#define XBram_In16 Xil_In16 +#define XBram_Out16 Xil_Out16 + +#define XBram_In8 Xil_In8 +#define XBram_Out8 Xil_Out8 + + +/****************************************************************************/ +/** +* +* Write a value to a BRAM register. A 32 bit write is performed. +* +* @param BaseAddress is the base address of the BRAM device register. +* @param RegOffset is the register offset from the base to write to. +* @param Data is the data written to the register. +* +* @return None. +* +* @note C-style signature: +* void XBram_WriteReg(u32 BaseAddress, u32 RegOffset, u32 Data) +* +****************************************************************************/ +#define XBram_WriteReg(BaseAddress, RegOffset, Data) \ + XBram_Out32((BaseAddress) + (RegOffset), (u32)(Data)) + +/****************************************************************************/ +/** +* +* Read a value from a BRAM register. A 32 bit read is performed. +* +* @param BaseAddress is the base address of the BRAM device registers. +* @param RegOffset is the register offset from the base to read from. +* +* @return Data read from the register. +* +* @note C-style signature: +* u32 XBram_ReadReg(u32 BaseAddress, u32 RegOffset) +* +****************************************************************************/ +#define XBram_ReadReg(BaseAddress, RegOffset) \ + XBram_In32((BaseAddress) + (RegOffset)) + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + + + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/bram_v4_3/src/xbram_intr.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/bram_v4_3/src/xbram_intr.c new file mode 100644 index 0000000..50644aa --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/bram_v4_3/src/xbram_intr.c @@ -0,0 +1,234 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +/*****************************************************************************/ +/** +* @file xbram_intr.c +* @addtogroup bram_v4_2 +* @{ +* +* Implements BRAM interrupt processing functions for the +* XBram driver. See xbram.h for more information +* about the driver. +* +* The functions in this file require the hardware device to be built with +* interrupt capabilities. The functions will assert if called using hardware +* that does not have interrupt capabilities. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a sa   05/11/10 Initial release
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ +#include "xbram.h" + + +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Variable Definitions ****************************/ + +/************************** Function Prototypes *****************************/ + + +/****************************************************************************/ +/** +* Enable interrupts. This function will assert if the hardware device has not +* been built with interrupt capabilities. +* +* @param InstancePtr is the BRAM instance to operate on. +* @param Mask is the mask to enable. Bit positions of 1 are enabled. +* This mask is formed by OR'ing bits from XBRAM_IR* +* bits which are contained in xbram_hw.h. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XBram_InterruptEnable(XBram *InstancePtr, u32 Mask) +{ + u32 Register; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(InstancePtr->Config.CtrlBaseAddress != 0); + + /* + * Read the interrupt enable register and only enable the specified + * interrupts without disabling or enabling any others. + */ + Register = XBram_ReadReg(InstancePtr->Config.CtrlBaseAddress, + XBRAM_ECC_EN_IRQ_OFFSET); + XBram_WriteReg(InstancePtr->Config.CtrlBaseAddress, + XBRAM_ECC_EN_IRQ_OFFSET, + Register | Mask); +} + + +/****************************************************************************/ +/** +* Disable interrupts. This function allows each specific interrupt to be +* disabled. This function will assert if the hardware device has not been +* built with interrupt capabilities. +* +* @param InstancePtr is the BRAM instance to operate on. +* @param Mask is the mask to disable. Bits set to 1 are disabled. This +* mask is formed by OR'ing bits from XBRAM_IR* bits +* which are contained in xbram_hw.h. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XBram_InterruptDisable(XBram *InstancePtr, u32 Mask) +{ + u32 Register; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(InstancePtr->Config.CtrlBaseAddress != 0); + + /* + * Read the interrupt enable register and only disable the specified + * interrupts without enabling or disabling any others. + */ + Register = XBram_ReadReg(InstancePtr->Config.CtrlBaseAddress, + XBRAM_ECC_EN_IRQ_OFFSET); + XBram_WriteReg(InstancePtr->Config.CtrlBaseAddress, + XBRAM_ECC_EN_IRQ_OFFSET, + Register & (~Mask)); +} + +/****************************************************************************/ +/** +* Clear pending interrupts with the provided mask. This function should be +* called after the software has serviced the interrupts that are pending. +* This function will assert if the hardware device has not been built with +* interrupt capabilities. +* +* @param InstancePtr is the BRAM instance to operate on. +* @param Mask is the mask to clear pending interrupts for. Bit positions +* of 1 are cleared. This mask is formed by OR'ing bits from +* XBRAM_IR* bits which are contained in +* xbram_hw.h. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XBram_InterruptClear(XBram *InstancePtr, u32 Mask) +{ + u32 Register; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(InstancePtr->Config.CtrlBaseAddress != 0); + + /* + * Read the interrupt status register and only clear the interrupts + * that are specified without affecting any others. Since the register + * is a toggle on write, make sure any bits to be written are already + * set. + */ + Register = XBram_ReadReg(InstancePtr->Config.CtrlBaseAddress, + XBRAM_ECC_STATUS_OFFSET); + XBram_WriteReg(InstancePtr->Config.CtrlBaseAddress, + XBRAM_ECC_STATUS_OFFSET, + Register & Mask); + + +} + + +/****************************************************************************/ +/** +* Returns the interrupt enable mask. This function will assert if the +* hardware device has not been built with interrupt capabilities. +* +* @param InstancePtr is the BRAM instance to operate on. +* +* @return A mask of bits made from XBRAM_IR* bits which +* are contained in xbram_hw.h. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +u32 XBram_InterruptGetEnabled(XBram * InstancePtr) +{ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(InstancePtr->Config.CtrlBaseAddress != 0); + + return XBram_ReadReg(InstancePtr->Config.CtrlBaseAddress, + XBRAM_ECC_EN_IRQ_OFFSET); +} + + +/****************************************************************************/ +/** +* Returns the status of interrupt signals. Any bit in the mask set to 1 +* indicates that the channel associated with the bit has asserted an interrupt +* condition. This function will assert if the hardware device has not been +* built with interrupt capabilities. +* +* @param InstancePtr is the BRAM instance to operate on. +* +* @return A pointer to a mask of bits made from XBRAM_IR* +* bits which are contained in xbram_hw.h. +* +* @note +* +* The interrupt status indicates the status of the device irregardless if +* the interrupts from the devices have been enabled or not through +* XBram_InterruptEnable(). +* +*****************************************************************************/ +u32 XBram_InterruptGetStatus(XBram * InstancePtr) +{ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(InstancePtr->Config.CtrlBaseAddress != 0); + + return XBram_ReadReg(InstancePtr->Config.CtrlBaseAddress, + XBRAM_ECC_EN_IRQ_OFFSET); +} +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/bram_v4_3/src/xbram_selftest.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/bram_v4_3/src/xbram_selftest.c new file mode 100644 index 0000000..e57e09c --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/bram_v4_3/src/xbram_selftest.c @@ -0,0 +1,557 @@ +/****************************************************************************** +* +* Copyright (C) 2011 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file xbram_selftest.c +* @addtogroup bram_v4_2 +* @{ +* +* The implementation of the XBram driver's self test function. This SelfTest +* is only applicable if ECC is enabled. +* If ECC is not enabled then this function will return XST_SUCCESS. +* See xbram.h for more information about the driver. +* Temp change +* +* @note +* +* None +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a sa   11/24/10 First release
+* 3.01a sa   01/13/12  Changed Selftest API from
+*		       XBram_SelfTest(XBram *InstancePtr) to
+*		       XBram_SelfTest(XBram *InstancePtr, u8 IntMask) and
+*		       fixed a problem with interrupt generation for CR 639274
+*		       Modified Selftest example to return XST_SUCCESS when
+*		       ECC is not enabled and return XST_FAILURE when ECC is
+*		       enabled and Control Base Address is zero (CR 636581)
+*		       Modified Selftest to use correct CorrectableCounterBits
+*		       for CR 635655
+*		       Updated to check CorrectableFailingDataRegs in the case
+*		       of LMB BRAM.
+* 3.02a sa  04/16/12   Added test of byte and halfword read-modify-write
+* 3.03a bss 05/22/13   Added Xil_DCacheFlushRange in InjectErrors API to
+*		       flush the Cache after writing to BRAM (CR #719011)
+* 4.3   aru 04/09/19   Used UINTPTR instead of u32 for Addr in XBram_SelfTest()
+*
+* 
+*****************************************************************************/ + +/***************************** Include Files ********************************/ +#include "xbram.h" +#include "xil_cache.h" +/************************** Constant Definitions ****************************/ +#define TOTAL_BITS 39 + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ +#define RD(reg) XBram_ReadReg(InstancePtr->Config.CtrlBaseAddress, \ + XBRAM_ ## reg) +#define WR(reg, data) XBram_WriteReg(InstancePtr->Config.CtrlBaseAddress, \ + XBRAM_ ## reg, data) + +#define CHECK(reg, data, result) if (result!=XST_SUCCESS || RD(reg)!=data) \ + result = XST_FAILURE; + +/************************** Variable Definitions ****************************/ +static u32 PrngResult; + +/************************** Function Prototypes *****************************/ +static inline u32 PrngData(u32 *PrngResult); + +static inline u32 CalculateEcc(u32 Data); + +static void InjectErrors(XBram * InstancePtr, UINTPTR Addr, + int Index1, int Index2, int Width, + u32 *ActualData, u32 *ActualEcc); + + +/*****************************************************************************/ +/** +* Generate a pseudo random number. +* +* @param The PrngResult is the previous random number in the pseudo +* random sequence, also knwon as the seed. It is modified to +* the calculated pseudo random number by the function. +* +* @return The generated pseudo random number +* +* @note None. +* +******************************************************************************/ +static inline u32 PrngData(u32 *PrngResult) +{ + *PrngResult = *PrngResult * 0x77D15E25 + 0x3617C161; + return *PrngResult; +} + + +/*****************************************************************************/ +/** +* Calculate ECC from Data. +* +* @param The Data Value +* +* @return The calculated ECC +* +* @note None. +* +******************************************************************************/ +static inline u32 CalculateEcc(u32 Data) +{ + unsigned char c[7], d[32]; + u32 Result = 0; + int Index; + + for (Index = 0; Index < 32; Index++) { + d[31 - Index] = Data & 1; + Data = Data >> 1; + } + + c[0] = d[0] ^ d[1] ^ d[3] ^ d[4] ^ d[6] ^ d[8] ^ d[10] ^ d[11] ^ + d[13] ^ d[15] ^ d[17] ^ d[19] ^ d[21] ^ d[23] ^ d[25] ^ d[26] ^ + d[28] ^ d[30]; + + c[1] = d[0] ^ d[2] ^ d[3] ^ d[5] ^ d[6] ^ d[9] ^ d[10] ^ d[12] ^ + d[13] ^ d[16] ^ d[17] ^ d[20] ^ d[21] ^ d[24] ^ d[25] ^ d[27] ^ + d[28] ^ d[31]; + + c[2] = d[1] ^ d[2] ^ d[3] ^ d[7] ^ d[8] ^ d[9] ^ d[10] ^ d[14] ^ + d[15] ^ d[16] ^ d[17] ^ d[22] ^ d[23] ^ d[24] ^ d[25] ^ d[29] ^ + d[30] ^ d[31]; + + c[3] = d[4] ^ d[5] ^ d[6] ^ d[7] ^ d[8] ^ d[9] ^ d[10] ^ d[18] ^ + d[19] ^ d[20] ^ d[21] ^ d[22] ^ d[23] ^ d[24] ^ d[25]; + + c[4] = d[11] ^ d[12] ^ d[13] ^ d[14] ^ d[15] ^ d[16] ^ d[17] ^ d[18] ^ + d[19] ^ d[20] ^ d[21] ^ d[22] ^ d[23] ^ d[24] ^ d[25]; + + c[5] = d[26] ^ d[27] ^ d[28] ^ d[29] ^ d[30] ^ d[31]; + + c[6] = d[0] ^ d[1] ^ d[2] ^ d[3] ^ d[4] ^ d[5] ^ d[6] ^ d[7] ^ + d[8] ^ d[9] ^ d[10] ^ d[11] ^ d[12] ^ d[13] ^ d[14] ^ d[15] ^ + d[16] ^ d[17] ^ d[18] ^ d[19] ^ d[20] ^ d[21] ^ d[22] ^ d[23] ^ + d[24] ^ d[25] ^ d[26] ^ d[27] ^ d[28] ^ d[29] ^ d[30] ^ d[31] ^ + c[5] ^ c[4] ^ c[3] ^ c[2] ^ c[1] ^ c[0]; + + for (Index = 0; Index < 7; Index++) { + Result = Result << 1; + Result |= c[Index] & 1; + } + + return Result; +} + +/*****************************************************************************/ +/** +* Get the expected actual data read in case of uncorrectable errors. +* +* @param The injected data value including errors (if any) +* @param The syndrome (calculated ecc ^ actual ecc read) +* +* @return The actual data value read +* +* @note None. +* +******************************************************************************/ +static inline u32 UncorrectableData(u32 Data, u8 Syndrome) +{ + switch (Syndrome) { + case 0x03: return Data ^ 0x00000034; + case 0x05: return Data ^ 0x001a2000; + case 0x09: return Data ^ 0x0d000000; + case 0x0d: return Data ^ 0x00001a00; + + case 0x11: return Data ^ 0x60000000; + case 0x13: return Data ^ 0x00000003; + case 0x15: return Data ^ 0x00018000; + case 0x19: return Data ^ 0x00c00000; + case 0x1d: return Data ^ 0x00000180; + + case 0x21: return Data ^ 0x80000000; + case 0x23: return Data ^ 0x00000008; + case 0x25: return Data ^ 0x00040000; + case 0x29: return Data ^ 0x02000000; + case 0x2d: return Data ^ 0x00000400; + + case 0x31: return Data ^ 0x10000000; + case 0x35: return Data ^ 0x00004000; + case 0x39: return Data ^ 0x00200000; + case 0x3d: return Data ^ 0x00000040; + } + return Data; +} + +/*****************************************************************************/ +/** +* Inject errors using the hardware fault injection functionality, and write +* random data and read it back using the indicated location. +* +* @param InstancePtr is a pointer to the XBram instance to +* be worked on. +* @param The Addr is the indicated memory location to use +* @param The Index1 is the bit location of the first injected error +* @param The Index2 is the bit location of the second injected error +* @param The Width is the data byte width +* @param The ActualData is filled in with expected data for checking +* @param The ActualEcc is filled in with expected ECC for checking +* +* @return None +* +* @note None. +* +******************************************************************************/ +static void InjectErrors(XBram * InstancePtr, UINTPTR Addr, + int Index1, int Index2, int Width, + u32 *ActualData, u32 *ActualEcc) +{ + u32 InjectedData = 0; + u32 InjectedEcc = 0; + u32 RandomData = PrngData(&PrngResult); + + if (Index1 < 32) { + InjectedData = 1 << Index1; + } else { + InjectedEcc = 1 << (Index1 - 32); + } + + if (Index2 < 32) { + InjectedData |= (1 << Index2); + } else { + InjectedEcc |= 1 << (Index2 - 32); + } + + WR(FI_D_0_OFFSET, InjectedData); + WR(FI_ECC_0_OFFSET, InjectedEcc); + + XBram_Out32(Addr, RandomData); + Xil_DCacheFlushRange(Addr, 4); + switch (Width) { + case 1: /* Byte - Write to do Read-Modify-Write */ + XBram_Out8(Addr, PrngData(&PrngResult) & 0xFF); + break; + case 2: /* Halfword - Write to do Read-Modify-Write */ + XBram_Out16(Addr, PrngData(&PrngResult) & 0xFFFF); + break; + case 4: /* Word - Read */ + (void) XBram_In32(Addr); + break; + } + *ActualData = InjectedData ^ RandomData; + *ActualEcc = InjectedEcc ^ CalculateEcc(RandomData); +} + + +/*****************************************************************************/ +/** +* Run a self-test on the driver/device. Unless fault injection is implemented +* in hardware, this function only does a minimal test in which available +* registers (if any) are written and read. +* +* With fault injection, all possible single-bit and double-bit errors are +* injected, and checked to the extent possible, given the implemented hardware. +* +* @param InstancePtr is a pointer to the XBram instance. +* @param IntMask is the interrupt mask to use. When testing +* with interrupts, this should be set to allow interrupt +* generation, otherwise it should be 0. +* +* @return +* - XST_SUCCESS if fault injection/detection is working properly OR +* if ECC is Not Enabled in the HW. +* - XST_FAILURE if the injected fault is not correctly detected or +* the Control Base Address is Zero when ECC is enabled. +* . +* +* If the BRAM device is not present in the +* hardware a bus error could be generated. Other indicators of a +* bus error, such as registers in bridges or buses, may be +* necessary to determine if this function caused a bus error. +* +* @note None. +* +******************************************************************************/ +int XBram_SelfTest(XBram *InstancePtr, u8 IntMask) +{ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + + + if (InstancePtr->Config.EccPresent == 0) { + return (XST_SUCCESS); + } + + if (InstancePtr->Config.CtrlBaseAddress == 0) { + return (XST_SUCCESS); + } + + /* + * Only 32-bit data width is supported as of yet. 64-bit and 128-bit + * widths will be supported in future. + */ + if (InstancePtr->Config.DataWidth != 32) + return (XST_SUCCESS); + + /* + * Read from the implemented readable registers in the hardware device. + */ + if (InstancePtr->Config.CorrectableFailingRegisters) { + (void) RD(CE_FFA_0_OFFSET); + } + if (InstancePtr->Config.CorrectableFailingDataRegs) { + (void) RD(CE_FFD_0_OFFSET); + (void) RD(CE_FFE_0_OFFSET); + } + if (InstancePtr->Config.UncorrectableFailingRegisters) { + (void) RD(UE_FFA_0_OFFSET); + } + if (InstancePtr->Config.UncorrectableFailingDataRegs) { + (void) RD(UE_FFD_0_OFFSET); + (void) RD(UE_FFE_0_OFFSET); + } + + /* + * Write and read the implemented read/write registers in the hardware + * device. + */ + if (InstancePtr->Config.EccStatusInterruptPresent) { + WR(ECC_EN_IRQ_OFFSET, 0); + if (RD(ECC_EN_IRQ_OFFSET) != 0) { + return (XST_FAILURE); + } + } + + if (InstancePtr->Config.CorrectableCounterBits > 0) { + u32 Value; + + /* Calculate counter max value */ + if (InstancePtr->Config.CorrectableCounterBits == 32) { + Value = 0xFFFFFFFF; + } else { + Value = (1 << + InstancePtr->Config.CorrectableCounterBits) - 1; + } + + WR(CE_CNT_OFFSET, Value); + if (RD(CE_CNT_OFFSET) != Value) { + return (XST_FAILURE); + } + + WR(CE_CNT_OFFSET, 0); + if (RD(CE_CNT_OFFSET) != 0) { + return (XST_FAILURE); + } + } + + /* + * If fault injection is implemented, inject all possible single-bit + * and double-bit errors, and check all observable effects. + */ + if (InstancePtr->Config.FaultInjectionPresent && + InstancePtr->Config.WriteAccess != 0) { + + const UINTPTR Addr[2] = {InstancePtr->Config.MemBaseAddress & + (UINTPTR)0xfffffffffffffffc, + InstancePtr->Config.MemHighAddress & + (UINTPTR)0xfffffffffffffffc}; + u32 SavedWords[2]; + u32 ActualData; + u32 ActualEcc; + u32 CounterValue = 0; + u32 CounterMax; + int WordIndex = 0; + int Result = XST_SUCCESS; + int Index1; + int Index2; + int Width; + + PrngResult = 42; /* Random seed */ + + /* Save two words in BRAM used for test */ + SavedWords[0] = XBram_In32(Addr[0]); + SavedWords[1] = XBram_In32(Addr[1]); + + for (Width = 1; Width <= 4; Width <<= 1) { + /* Calculate counter max value */ + if (InstancePtr->Config.CorrectableCounterBits == 32) { + CounterMax = 0xFFFFFFFF; + } else { + CounterMax =(1 << + InstancePtr->Config.CorrectableCounterBits) - 1; + } + + /* Inject and check all single bit errors */ + for (Index1 = 0; Index1 < TOTAL_BITS; Index1++) { + /* Save counter value */ + if (InstancePtr->Config.CorrectableCounterBits > 0) { + CounterValue = RD(CE_CNT_OFFSET); + } + + /* Inject single bit error */ + InjectErrors(InstancePtr, Addr[WordIndex], Index1, + Index1, Width, &ActualData, &ActualEcc); + + /* Check that CE is set */ + if (InstancePtr->Config.EccStatusInterruptPresent) { + CHECK(ECC_STATUS_OFFSET, + XBRAM_IR_CE_MASK, Result); + } + + /* Check that address, data, ECC are correct */ + if (InstancePtr->Config.CorrectableFailingRegisters) { + CHECK(CE_FFA_0_OFFSET, Addr[WordIndex], Result); + } + /* Checks are only for LMB BRAM */ + if (InstancePtr->Config.CorrectableFailingDataRegs) { + CHECK(CE_FFD_0_OFFSET, ActualData, Result); + CHECK(CE_FFE_0_OFFSET, ActualEcc, Result); + } + + /* Check that counter has incremented */ + if (InstancePtr->Config.CorrectableCounterBits > 0 && + CounterValue < CounterMax) { + CHECK(CE_CNT_OFFSET, + CounterValue + 1, Result); + } + + /* Restore correct data in the used word */ + XBram_Out32(Addr[WordIndex], SavedWords[WordIndex]); + + /* Allow interrupts to occur */ + /* Clear status register */ + if (InstancePtr->Config.EccStatusInterruptPresent) { + WR(ECC_EN_IRQ_OFFSET, IntMask); + WR(ECC_STATUS_OFFSET, XBRAM_IR_ALL_MASK); + WR(ECC_EN_IRQ_OFFSET, 0); + } + + /* Switch to the other word */ + WordIndex = WordIndex ^ 1; + + if (Result != XST_SUCCESS) break; + + } + + if (Result != XST_SUCCESS) { + return XST_FAILURE; + } + + for (Index1 = 0; Index1 < TOTAL_BITS; Index1++) { + for (Index2 = 0; Index2 < TOTAL_BITS; Index2++) { + if (Index1 != Index2) { + /* Inject double bit error */ + InjectErrors(InstancePtr, + Addr[WordIndex], + Index1, Index2, Width, + &ActualData, + &ActualEcc); + + /* Check that UE is set */ + if (InstancePtr->Config. + EccStatusInterruptPresent) { + CHECK(ECC_STATUS_OFFSET, + XBRAM_IR_UE_MASK, + Result); + } + + /* Check that address, data, ECC are correct */ + if (InstancePtr->Config. + UncorrectableFailingRegisters) { + CHECK(UE_FFA_0_OFFSET, Addr[WordIndex], + Result); + CHECK(UE_FFD_0_OFFSET, + ActualData, Result); + CHECK(UE_FFE_0_OFFSET, ActualEcc, + Result); + } + + /* Restore correct data in the used word */ + XBram_Out32(Addr[WordIndex], + SavedWords[WordIndex]); + + /* Allow interrupts to occur */ + /* Clear status register */ + if (InstancePtr->Config. + EccStatusInterruptPresent) { + WR(ECC_EN_IRQ_OFFSET, IntMask); + WR(ECC_STATUS_OFFSET, + XBRAM_IR_ALL_MASK); + WR(ECC_EN_IRQ_OFFSET, 0); + } + + /* Switch to the other word */ + WordIndex = WordIndex ^ 1; + } + if (Result != XST_SUCCESS) break; + } + if (Result != XST_SUCCESS) break; + } + + /* Check saturation of correctable error counter */ + if (InstancePtr->Config.CorrectableCounterBits > 0 && + Result == XST_SUCCESS) { + + WR(CE_CNT_OFFSET, CounterMax); + + InjectErrors(InstancePtr, Addr[WordIndex], 0, 0, + 4, &ActualData, &ActualEcc); + + CHECK(CE_CNT_OFFSET, CounterMax, Result); + } + + /* Restore the two words used for test */ + XBram_Out32(Addr[0], SavedWords[0]); + XBram_Out32(Addr[1], SavedWords[1]); + + /* Clear the Status Register. */ + if (InstancePtr->Config.EccStatusInterruptPresent) { + WR(ECC_STATUS_OFFSET, XBRAM_IR_ALL_MASK); + } + + /* Set Correctable Counter to zero */ + if (InstancePtr->Config.CorrectableCounterBits > 0) { + WR(CE_CNT_OFFSET, 0); + } + + if (Result != XST_SUCCESS) break; + + } /* Width loop */ + + return (Result); + } + + return (XST_SUCCESS); +} + +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/bram_v4_3/src/xbram_sinit.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/bram_v4_3/src/xbram_sinit.c new file mode 100644 index 0000000..adc560e --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/bram_v4_3/src/xbram_sinit.c @@ -0,0 +1,101 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2017 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file xbram_sinit.c +* @addtogroup bram_v4_2 +* @{ +* +* The implementation of the XBram driver's static initialzation +* functionality. +* +* @note +* +* None +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 2.01a jvb  10/13/05 First release
+* 2.11a mta  03/21/07 Updated to new coding style
+* 4.2   ms   08/07/17 Fixed compilation warnings.
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ + +#include "xstatus.h" +#include "xparameters.h" +#include "xbram.h" + +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Variable Definitions ****************************/ +extern XBram_Config XBram_ConfigTable[]; + +/************************** Function Prototypes *****************************/ + + +/*****************************************************************************/ +/** +* Lookup the device configuration based on the unique device ID. The table +* ConfigTable contains the configuration info for each device in the system. +* +* @param DeviceId is the device identifier to lookup. +* +* @return +* - A pointer of data type XBram_Config which +* points to the device configuration if DeviceID is found. +* - NULL if DeviceID is not found. +* +* @note None. +* +******************************************************************************/ +XBram_Config *XBram_LookupConfig(u16 DeviceId) +{ + XBram_Config *CfgPtr = NULL; + + u32 Index; + + for (Index = 0U; Index < XPAR_XBRAM_NUM_INSTANCES; Index++) { + if (XBram_ConfigTable[Index].DeviceId == DeviceId) { + CfgPtr = &XBram_ConfigTable[Index]; + break; + } + } + + return CfgPtr; +} +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/coresightps_dcc_v1_5/src/Makefile b/df_datalink/bsp/ps7_cortexa9_0/libsrc/coresightps_dcc_v1_5/src/Makefile new file mode 100644 index 0000000..007162d --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/coresightps_dcc_v1_5/src/Makefile @@ -0,0 +1,40 @@ +COMPILER= +ARCHIVER= +CP=cp +COMPILER_FLAGS= +EXTRA_COMPILER_FLAGS= +LIB=libxil.a + +CC_FLAGS = $(COMPILER_FLAGS) +ECC_FLAGS = $(EXTRA_COMPILER_FLAGS) + +RELEASEDIR=../../../lib +INCLUDEDIR=../../../include +INCLUDES=-I./. -I${INCLUDEDIR} + +OUTS = *.o + +LIBSOURCES:=*.c +INCLUDEFILES:=*.h + +OBJECTS = $(addsuffix .o, $(basename $(wildcard *.c))) + +libs: banner coresightps_dcc_comp_libs clean + +%.o: %.c + ${COMPILER} $(CC_FLAGS) $(ECC_FLAGS) $(INCLUDES) -o $@ $< + +banner: + echo "Compiling coresightps_dcc" + +coresightps_dcc_comp_libs: ${OBJECTS} + $(ARCHIVER) -r ${RELEASEDIR}/${LIB} ${OBJECTS} + +.PHONY: include +include: coresightps_dcc_includes + +coresightps_dcc_includes: + ${CP} ${INCLUDEFILES} ${INCLUDEDIR} + +clean: + rm -rf ${OBJECTS} diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/coresightps_dcc_v1_5/src/xcoresightpsdcc.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/coresightps_dcc_v1_5/src/xcoresightpsdcc.c new file mode 100644 index 0000000..235eb8e --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/coresightps_dcc_v1_5/src/xcoresightpsdcc.c @@ -0,0 +1,186 @@ +/****************************************************************************** +* +* Copyright (C) 2015-2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xcoresightpsdcc.c +* @addtogroup coresightps_dcc_v1_5 +* @{ +* +* Functions in this file are the minimum required functions for the +* XCoreSightPs driver. +* +* @note None. +* +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date		Changes
+* ----- -----  -------- -----------------------------------------------
+* 1.00  kvn    02/14/15 First release
+* 1.1   kvn    06/12/15 Add support for Zynq Ultrascale+ MP.
+*       kvn    08/18/15 Modified Makefile according to compiler changes.
+* 1.2   kvn    10/09/15 Add support for IAR Compiler.
+* 1.3   asa    07/01/16 Made changes to ensure that the file does not compile
+*                       for MB BSPs. Instead it throws up a warning. This
+*                       fixes the CR#953056.
+* 1.5   sne    01/19/19 Fixed MISRA-C Violations CR#1025101.
+*
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ +#ifdef __MICROBLAZE__ +#warning "The driver is supported only for ARM architecture" +#else + +#include "xil_types.h" +#include "xpseudo_asm.h" +#include "xcoresightpsdcc.h" + +#ifdef __ICCARM__ +#define INLINE +#else +#define INLINE __inline +#endif + +/* DCC Status Bits */ +#define XCORESIGHTPS_DCC_STATUS_RX (1 << 30) +#define XCORESIGHTPS_DCC_STATUS_TX (1 << 29) + +static INLINE u32 XCoresightPs_DccGetStatus(void); + +/****************************************************************************/ +/** +* +* This functions sends a single byte using the DCC. It is blocking in that it +* waits for the transmitter to become non-full before it writes the byte to +* the transmit register. +* +* @param BaseAddress is a dummy parameter to match the function proto +* of functions for other stdio devices. +* @param Data is the byte of data to send +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XCoresightPs_DccSendByte(u32 BaseAddress, u8 Data) +{ + (void) BaseAddress; + while (XCoresightPs_DccGetStatus() & XCORESIGHTPS_DCC_STATUS_TX) + {dsb();} +#ifdef __aarch64__ + asm volatile ("msr dbgdtrtx_el0, %0" : : "r" (Data)); +#elif defined (__GNUC__) || defined (__ICCARM__) + asm volatile("mcr p14, 0, %0, c0, c5, 0" + : : "r" (Data)); +#else + { + volatile register u32 Reg __asm("cp14:0:c0:c5:0"); + Reg = Data; + } +#endif + isb(); + +} + +/****************************************************************************/ +/** +* +* This functions receives a single byte using the DCC. It is blocking in that +* it waits for the receiver to become non-empty before it reads from the +* receive register. +* +* @param BaseAddress is a dummy parameter to match the function proto +* of functions for other stdio devices. +* +* @return The byte of data received. +* +* @note None. +* +******************************************************************************/ +u8 XCoresightPs_DccRecvByte(u32 BaseAddress) +{ + u8 Data = 0U; + (void) BaseAddress; + + while (!(XCoresightPs_DccGetStatus() & XCORESIGHTPS_DCC_STATUS_RX)) + {dsb();} + +#ifdef __aarch64__ + asm volatile ("mrs %0, dbgdtrrx_el0" : "=r" (Data)); +#elif defined (__GNUC__) || defined (__ICCARM__) + asm volatile("mrc p14, 0, %0, c0, c5, 0" + : "=r" (Data)); +#else + { + volatile register u32 Reg __asm("cp14:0:c0:c5:0"); + Data = Reg; + } +#endif + isb(); + + return Data; +} + + +/****************************************************************************/ +/**INLINE +* +* This functions read the status register of the DCC. +* +* @param BaseAddress is the base address of the device +* +* @return The contents of the Status Register. +* +* @note None. +* +******************************************************************************/ +static INLINE u32 XCoresightPs_DccGetStatus(void) +{ + u32 Status = 0U; + +#ifdef __aarch64__ + asm volatile ("mrs %0, mdccsr_el0" : "=r" (Status)); +#elif defined (__GNUC__) || defined (__ICCARM__) + asm volatile("mrc p14, 0, %0, c0, c1, 0" + : "=r" (Status) : : "cc"); +#else + { + volatile register u32 Reg __asm("cp14:0:c0:c1:0"); + Status = Reg; + } +#endif + return Status; +#endif +} +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/coresightps_dcc_v1_5/src/xcoresightpsdcc.h b/df_datalink/bsp/ps7_cortexa9_0/libsrc/coresightps_dcc_v1_5/src/xcoresightpsdcc.h new file mode 100644 index 0000000..79bde0b --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/coresightps_dcc_v1_5/src/xcoresightpsdcc.h @@ -0,0 +1,74 @@ +/****************************************************************************** +* +* Copyright (C) 2015 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xcoresightpsdcc.h +* @addtogroup coresightps_dcc_v1_5 +* @{ +* @details +* +* CoreSight driver component. +* +* The coresight is a part of debug communication channel (DCC) group. Jtag UART +* for ARM uses DCC. Each ARM core has its own DCC, so one need to select an +* ARM target in XSDB console before running the jtag terminal command. Using the +* coresight driver component, the output stream can be directed to a log file. +* +* @note None. +* +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date		Changes
+* ----- -----  -------- -----------------------------------------------
+* 1.00  kvn    02/14/15 First release
+* 1.1   kvn    06/12/15 Add support for Zynq Ultrascale+ MP.
+*       kvn    08/18/15 Modified Makefile according to compiler changes.
+* 1.3   asa    07/01/16 Made changes to ensure that the file does not compile
+*                       for MB BSPs. Instead it throws up a warning. This
+*                       fixes the CR#953056.
+* 1.5   sne    01/19/19 Fixed MISRA-C Violations CR#1025101.
+*
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ +#ifndef XCORESIGHTPSDCC_H /* prevent circular inclusions */ +#define XCORESIGHTPSDCC_H /* by using protection macros */ +#ifndef __MICROBLAZE__ +#include + +void XCoresightPs_DccSendByte(u32 BaseAddress, u8 Data); + +u8 XCoresightPs_DccRecvByte(u32 BaseAddress); +#endif +#endif +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/cpu_cortexa9_v2_7/src/Makefile b/df_datalink/bsp/ps7_cortexa9_0/libsrc/cpu_cortexa9_v2_7/src/Makefile new file mode 100644 index 0000000..7ea505c --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/cpu_cortexa9_v2_7/src/Makefile @@ -0,0 +1,25 @@ +COMPILER= +ARCHIVER= +CP=cp +COMPILER_FLAGS= +EXTRA_COMPILER_FLAGS= +LIB=libxil.a + +RELEASEDIR=../../../lib +INCLUDEDIR=../../../include +INCLUDES=-I${INCLUDEDIR} + +OUTS = *.o +OBJECTS = $(addsuffix .o, $(basename $(wildcard *.c))) +LIBSOURCES=*.c +INCLUDEFILES=*.h + +libs: + echo "Compiling cpu_cortexa9" + +.PHONY: include +include: + ${CP} $(INCLUDEFILES) $(INCLUDEDIR) + +clean: + rm -rf ${OBJECTS} diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/cpu_cortexa9_v2_7/src/xcpu_cortexa9.h b/df_datalink/bsp/ps7_cortexa9_0/libsrc/cpu_cortexa9_v2_7/src/xcpu_cortexa9.h new file mode 100644 index 0000000..e4a5e28 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/cpu_cortexa9_v2_7/src/xcpu_cortexa9.h @@ -0,0 +1,47 @@ +/****************************************************************************** +* +* Copyright (C) 2011 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xcpu_cortexa9.h +* @addtogroup cpu_cortexa9_v2_7 +* @{ +* @details +* +* dummy file +* MODIFICATION HISTORY: +* +* Ver Who Date Changes +* ----- ---- -------- --------------------------------------------------------- +* 2.5 ms 04/18/17 Modified tcl file to add suffix U for XPAR_CPU_ID +* parameter of cpu_cortexa9 in xparameters.h +# 2.7 mus 07/03/18 Updated tcl to not to add default flags forcefully into +# extra compiler flags. Now, user can remove default flags +# from extra compiler flags. It fixes CR#998768. +******************************************************************************/ +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/ddrps_v1_0/src/Makefile b/df_datalink/bsp/ps7_cortexa9_0/libsrc/ddrps_v1_0/src/Makefile new file mode 100644 index 0000000..7b191dd --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/ddrps_v1_0/src/Makefile @@ -0,0 +1,40 @@ +COMPILER= +ARCHIVER= +CP=cp +COMPILER_FLAGS= +EXTRA_COMPILER_FLAGS= +LIB=libxil.a + +CC_FLAGS = $(COMPILER_FLAGS) +ECC_FLAGS = $(EXTRA_COMPILER_FLAGS) + +RELEASEDIR=../../../lib +INCLUDEDIR=../../../include +INCLUDES=-I./. -I${INCLUDEDIR} + +OUTS = *.o + +LIBSOURCES:=*.c +INCLUDEFILES:=*.h + +OBJECTS = $(addsuffix .o, $(basename $(wildcard *.c))) + +libs: banner xddrps_libs clean + +%.o: %.c + ${COMPILER} $(CC_FLAGS) $(ECC_FLAGS) $(INCLUDES) -o $@ $< + +banner: + echo "Compiling ddrps" + +xddrps_libs: ${OBJECTS} + $(ARCHIVER) -r ${RELEASEDIR}/${LIB} ${OBJECTS} + +.PHONY: include +include: xddrps_includes + +xddrps_includes: + ${CP} ${INCLUDEFILES} ${INCLUDEDIR} + +clean: + rm -rf ${OBJECTS} diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/ddrps_v1_0/src/xddrps.h b/df_datalink/bsp/ps7_cortexa9_0/libsrc/ddrps_v1_0/src/xddrps.h new file mode 100644 index 0000000..b4d1f56 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/ddrps_v1_0/src/xddrps.h @@ -0,0 +1,62 @@ +/******************************************************************************* + * + * Copyright (C) 2015 Xilinx, Inc. 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 + * XILINX 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. + * + * Except as contained in this notice, the name of the Xilinx shall not be used + * in advertising or otherwise to promote the sale, use or other dealings in + * this Software without prior written authorization from Xilinx. + * +*******************************************************************************/ +/******************************************************************************/ +/** + * + * @file xddrps.h + * @addtogroup ddrps_v1_0 + * @{ + * @details + * + * The Xilinx DdrPs driver. This driver supports the Xilinx ddrps + * IP core. + * + * @note None. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -----------------------------------------------
+ * 1.0	 nsk  08/06/15 First Release
+ * 1.0	 nsk  08/20/15 Updated define_addr_params in ddrps.tcl
+ *		       to support PBD Designs (CR #876857)
+ *
+ * 
+ * +*******************************************************************************/ + +#ifndef XDDRPS_H_ +/* Prevent circular inclusions by using protection macros. */ +#define XDDRPS_H_ + +/******************************* Include Files ********************************/ + + +#endif /* XDDRPS_H_ */ +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/devcfg_v3_5/src/Makefile b/df_datalink/bsp/ps7_cortexa9_0/libsrc/devcfg_v3_5/src/Makefile new file mode 100644 index 0000000..25ff740 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/devcfg_v3_5/src/Makefile @@ -0,0 +1,40 @@ +COMPILER= +ARCHIVER= +CP=cp +COMPILER_FLAGS= +EXTRA_COMPILER_FLAGS= +LIB=libxil.a + +CC_FLAGS = $(COMPILER_FLAGS) +ECC_FLAGS = $(EXTRA_COMPILER_FLAGS) + +RELEASEDIR=../../../lib +INCLUDEDIR=../../../include +INCLUDES=-I./. -I${INCLUDEDIR} + +OUTS = *.o + +LIBSOURCES:=*.c +INCLUDEFILES:=*.h + +OBJECTS = $(addsuffix .o, $(basename $(wildcard *.c))) + +libs: banner xdevcfg_libs clean + +%.o: %.c + ${COMPILER} $(CC_FLAGS) $(ECC_FLAGS) $(INCLUDES) -o $@ $< + +banner: + echo "Compiling devcfg" + +xdevcfg_libs: ${OBJECTS} + $(ARCHIVER) -r ${RELEASEDIR}/${LIB} ${OBJECTS} + +.PHONY: include +include: xdevcfg_includes + +xdevcfg_includes: + ${CP} ${INCLUDEFILES} ${INCLUDEDIR} + +clean: + rm -rf ${OBJECTS} diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/devcfg_v3_5/src/xdevcfg.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/devcfg_v3_5/src/xdevcfg.c new file mode 100644 index 0000000..74e1d59 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/devcfg_v3_5/src/xdevcfg.c @@ -0,0 +1,941 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xdevcfg.c +* @addtogroup devcfg_v3_5 +* @{ +* +* This file contains the implementation of the interface functions for XDcfg +* driver. Refer to the header file xdevcfg.h for more detailed information. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 1.00a hvm 02/07/11 First release
+* 2.00a nm  05/31/12 Updated the driver for CR 660835 so that input length for
+*		     source/destination to the XDcfg_InitiateDma, XDcfg_Transfer
+*		     APIs is words (32 bit) and not bytes.
+* 		     Updated the notes for XDcfg_InitiateDma/XDcfg_Transfer APIs
+*		     to add information that 2 LSBs of the Source/Destination
+*		     address when equal to 2�b01 indicate the last DMA command
+*		     of an overall transfer.
+*		     Updated the XDcfg_Transfer function to use the
+*		     Destination Address passed to this API for secure transfers
+*		     instead of using 0xFFFFFFFF for CR 662197. This issue was
+*		     resulting in the failure of secure transfers of
+*		     non-bitstream images.
+* 2.01a nm  08/27/12 Updated the XDcfg_Transfer API to clear the
+*		     QUARTER_PCAP_RATE_EN bit in the control register for
+*		     non secure writes for CR 675543.
+* 2.02a nm  01/31/13 Fixed CR# 679335.
+* 		     Added Setting and Clearing the internal PCAP loopback.
+*		     Removed code for enabling/disabling AES engine as BootROM
+*		     locks down this setting.
+*		     Fixed CR# 681976.
+*		     Skip Checking the PCFG_INIT in case of non-secure DMA
+*		     loopback.
+*		     Fixed CR# 699558.
+*		     XDcfg_Transfer fails to transfer data in loopback mode.
+* 2.03a nm  04/19/13 Fixed CR# 703728.
+*		     Updated the register definitions as per the latest TRM
+*		     version UG585 (v1.4) November 16, 2012.
+* 3.0   kpc 21/02/14 Implemented new function XDcfg_ClearControlRegister
+* 3.2   sb  08/25/14 Fixed XDcfg_PcapReadback() function
+*		     updated driver code with != instead of ==,
+*		     while checking for Interrupt Status with DMA and
+*		     PCAP Done Mask
+*		     ((XDcfg_ReadReg(InstancePtr->Config.BaseAddr,
+*			XDCFG_INT_STS_OFFSET) &
+*			XDCFG_IXR_D_P_DONE_MASK) !=
+*			XDCFG_IXR_D_P_DONE_MASK);
+*
+*
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xdevcfg.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +/****************************************************************************/ +/** +* +* Initialize the Device Config Interface driver. This function +* must be called before other functions of the driver are called. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* @param ConfigPtr is the config structure. +* @param EffectiveAddress is the base address for the device. It could be +* a virtual address if address translation is supported in the +* system, otherwise it is the physical address. +* +* @return +* - XST_SUCCESS if initialization was successful. +* - XST_DEVICE_IS_STARTED if the device has already been started. +* +* @note The very first APB access to the Device Configuration Interface +* block needs to be a write to the UNLOCK register with the value +* of 0x757BDF0D. This step is to be done once after reset, any +* other APB access has to come after this. The APB access is +* considered illegal if the step is not done or if it is done +* incorrectly. Furthermore, if any of efuse_sec_cfg[5:0] is high, +* the following additional actions would be carried out. +* In other words, if all bits are low, the following steps are not +* done. +* 1. AES is disabled +* 2. All APB writes disabled +* 3. SoC debug fully enabled +* +******************************************************************************/ +int XDcfg_CfgInitialize(XDcfg *InstancePtr, + XDcfg_Config *ConfigPtr, u32 EffectiveAddress) +{ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(ConfigPtr != NULL); + + /* + * If the device is started, disallow the initialize and return a + * status indicating it is started. This allows the user to stop the + * device and reinitialize, but prevents a user from inadvertently + * initializing. + */ + if (InstancePtr->IsStarted == XIL_COMPONENT_IS_STARTED) { + return XST_DEVICE_IS_STARTED; + } + + /* + * Copy configuration into instance. + */ + InstancePtr->Config.DeviceId = ConfigPtr->DeviceId; + + /* + * Save the base address pointer such that the registers of the block + * can be accessed and indicate it has not been started yet. + */ + InstancePtr->Config.BaseAddr = EffectiveAddress; + InstancePtr->IsStarted = 0; + + + /* Unlock the Device Configuration Interface */ + XDcfg_Unlock(InstancePtr); + + /* + * Indicate the instance is ready to use, successfully initialized. + */ + InstancePtr->IsReady = XIL_COMPONENT_IS_READY; + + return XST_SUCCESS; +} + +/****************************************************************************/ +/** +* +* The functions enables the PCAP interface by setting the PCAP mode bit in the +* control register. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* +* @return None. +* +* @note Enable FPGA programming from PCAP interface. Enabling this bit +* disables all the external interfaces from programming of FPGA +* except for ICAP. The user needs to ensure that the FPGA is +* programmed through either PCAP or ICAP. +* +*****************************************************************************/ +void XDcfg_EnablePCAP(XDcfg *InstancePtr) +{ + u32 CtrlReg; + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + + CtrlReg = XDcfg_ReadReg(InstancePtr->Config.BaseAddr, + XDCFG_CTRL_OFFSET); + + XDcfg_WriteReg(InstancePtr->Config.BaseAddr, XDCFG_CTRL_OFFSET, + (CtrlReg | XDCFG_CTRL_PCAP_MODE_MASK)); + +} + +/****************************************************************************/ +/** +* +* The functions disables the PCAP interface by clearing the PCAP mode bit in +* the control register. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XDcfg_DisablePCAP(XDcfg *InstancePtr) +{ + u32 CtrlReg; + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + + CtrlReg = XDcfg_ReadReg(InstancePtr->Config.BaseAddr, + XDCFG_CTRL_OFFSET); + + XDcfg_WriteReg(InstancePtr->Config.BaseAddr, XDCFG_CTRL_OFFSET, + (CtrlReg & ( ~XDCFG_CTRL_PCAP_MODE_MASK))); + +} + +/****************************************************************************/ +/** +* +* The function sets the contents of the Control Register. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* @param Mask is the 32 bit mask data to be written to the Register. +* The mask definitions are defined in the xdevcfg_hw.h file. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XDcfg_SetControlRegister(XDcfg *InstancePtr, u32 Mask) +{ + u32 CtrlReg; + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + + CtrlReg = XDcfg_ReadReg(InstancePtr->Config.BaseAddr, + XDCFG_CTRL_OFFSET); + + XDcfg_WriteReg(InstancePtr->Config.BaseAddr, XDCFG_CTRL_OFFSET, + (CtrlReg | Mask)); + +} + +/****************************************************************************/ +/** +* +* The function Clears the specified bit positions of the Control Register. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* @param Mask is the 32 bit value which holds the bit positions to be cleared. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XDcfg_ClearControlRegister(XDcfg *InstancePtr, u32 Mask) +{ + u32 CtrlReg; + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + + CtrlReg = XDcfg_ReadReg(InstancePtr->Config.BaseAddr, + XDCFG_CTRL_OFFSET); + + XDcfg_WriteReg(InstancePtr->Config.BaseAddr, XDCFG_CTRL_OFFSET, + (CtrlReg & ~Mask)); + +} + +/****************************************************************************/ +/** +* +* The function reads the contents of the Control Register. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* +* @return A 32-bit value representing the contents of the Control +* Register. +* Use the XDCFG_CTRL_*_MASK constants defined in xdevcfg_hw.h to +* interpret the returned value. +* +* @note None. +* +*****************************************************************************/ +u32 XDcfg_GetControlRegister(XDcfg *InstancePtr) +{ + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the Control Register and return the value. + */ + return XDcfg_ReadReg(InstancePtr->Config.BaseAddr, XDCFG_CTRL_OFFSET); +} + +/****************************************************************************/ +/** +* +* The function sets the contents of the Lock Register. These bits +* can only be set to a 1. They will be cleared after a Power On Reset. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* @param Data is the 32 bit data to be written to the Register. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XDcfg_SetLockRegister(XDcfg *InstancePtr, u32 Data) +{ + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + XDcfg_WriteReg(InstancePtr->Config.BaseAddr, XDCFG_LOCK_OFFSET, Data); + +} + +/****************************************************************************/ +/** +* +* The function reads the contents of the Lock Register. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* +* @return A 32-bit value representing the contents of the Lock +* Register. +* Use the XDCFG_CR_*_MASK constants defined in xdevcfg_hw.h to +* interpret the returned value. +* +* @note None. +* +*****************************************************************************/ +u32 XDcfg_GetLockRegister(XDcfg *InstancePtr) +{ + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the Lock Register and return the value. + */ + return XDcfg_ReadReg(InstancePtr->Config.BaseAddr, XDCFG_LOCK_OFFSET); +} + +/****************************************************************************/ +/** +* +* The function sets the contents of the Configuration Register with the +* given value. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* @param Data is the 32 bit data to be written to the Register. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XDcfg_SetConfigRegister(XDcfg *InstancePtr, u32 Data) +{ + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + XDcfg_WriteReg(InstancePtr->Config.BaseAddr, XDCFG_CFG_OFFSET, Data); + +} + +/****************************************************************************/ +/** +* +* The function reads the contents of the Configuration Register with the +* given value. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* +* @return A 32-bit value representing the contents of the Config +* Register. +* Use the XDCFG_CFG_*_MASK constants defined in xdevcfg_hw.h to +* interpret the returned value. +* +* @note None. +* +*****************************************************************************/ +u32 XDcfg_GetConfigRegister(XDcfg *InstancePtr) +{ + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + return XDcfg_ReadReg(InstancePtr->Config.BaseAddr, XDCFG_CFG_OFFSET); + +} + +/****************************************************************************/ +/** +* +* The function sets the contents of the Status Register. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* @param Data is the 32 bit data to be written to the Register. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XDcfg_SetStatusRegister(XDcfg *InstancePtr, u32 Data) +{ + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + XDcfg_WriteReg(InstancePtr->Config.BaseAddr, XDCFG_STATUS_OFFSET, Data); + +} + +/****************************************************************************/ +/** +* +* The function reads the contents of the Status Register. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* +* @return A 32-bit value representing the contents of the Status +* Register. +* Use the XDCFG_STATUS_*_MASK constants defined in +* xdevcfg_hw.h to interpret the returned value. +* +* @note None. +* +*****************************************************************************/ +u32 XDcfg_GetStatusRegister(XDcfg *InstancePtr) +{ + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the Status Register and return the value. + */ + return XDcfg_ReadReg(InstancePtr->Config.BaseAddr, XDCFG_STATUS_OFFSET); +} + +/****************************************************************************/ +/** +* +* The function sets the contents of the ROM Shadow Control Register. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* @param Data is the 32 bit data to be written to the Register. +* +* @return None. +* +* @note This register is can only be written and is used to control the +* RAM shadow of 32 bit 4K page ROM pages in user mode +* +*****************************************************************************/ +void XDcfg_SetRomShadowRegister(XDcfg *InstancePtr, u32 Data) +{ + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + XDcfg_WriteReg(InstancePtr->Config.BaseAddr, XDCFG_ROM_SHADOW_OFFSET, + Data); + +} + +/****************************************************************************/ +/** +* +* The function reads the contents of the Software ID Register. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* +* @return 32 Bit boot software ID. +* +* @note This register is locked for write once the system enters +* usermode. Hence API for reading the register only is provided. +* +*****************************************************************************/ +u32 XDcfg_GetSoftwareIdRegister(XDcfg *InstancePtr) +{ + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the Software ID Register and return the value. + */ + return XDcfg_ReadReg(InstancePtr->Config.BaseAddr, XDCFG_SW_ID_OFFSET); +} + +/****************************************************************************/ +/** +* +* The function sets the bit mask for the feature in Miscellaneous Control +* Register. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* @param Mask is the bit-mask of the feature to be set. +* +* @return None. +* +* @note None +* +*****************************************************************************/ +void XDcfg_SetMiscControlRegister(XDcfg *InstancePtr, u32 Mask) +{ + u32 RegData; + + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + + RegData = XDcfg_ReadReg(InstancePtr->Config.BaseAddr, + XDCFG_MCTRL_OFFSET); + + XDcfg_WriteReg(InstancePtr->Config.BaseAddr, XDCFG_MCTRL_OFFSET, + (RegData | Mask)); +} + +/****************************************************************************/ +/** +* +* The function reads the contents of the Miscellaneous Control Register. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* +* @return 32 Bit boot software ID. +* +* @note This register is locked for write once the system enters +* usermode. Hence API to reading the register only is provided. +* +*****************************************************************************/ +u32 XDcfg_GetMiscControlRegister(XDcfg *InstancePtr) +{ + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the Miscellaneous Control Register and return the value. + */ + return XDcfg_ReadReg(InstancePtr->Config.BaseAddr, XDCFG_MCTRL_OFFSET); +} + +/******************************************************************************/ +/** +* +* This function checks if DMA command queue is full. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* +* @return XST_SUCCESS is the DMA is busy +* XST_FAILURE if the DMA is idle +* +* @note The DMA queue has a depth of two. +* +****************************************************************************/ +u32 XDcfg_IsDmaBusy(XDcfg *InstancePtr) +{ + + u32 RegData; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* Read the PCAP status register for DMA status */ + RegData = XDcfg_ReadReg(InstancePtr->Config.BaseAddr, + XDCFG_STATUS_OFFSET); + + if ((RegData & XDCFG_STATUS_DMA_CMD_Q_F_MASK) == + XDCFG_STATUS_DMA_CMD_Q_F_MASK){ + return XST_SUCCESS; + } + + return XST_FAILURE; +} + +/******************************************************************************/ +/** +* +* This function initiates the DMA transfer. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* @param SourcePtr contains a pointer to the source memory where the data +* is to be transferred from. +* @param SrcWordLength is the number of words (32 bit) to be transferred +* for the source transfer. +* @param DestPtr contains a pointer to the destination memory +* where the data is to be transferred to. +* @param DestWordLength is the number of words (32 bit) to be transferred +* for the Destination transfer. +* +* @return None. +* +* @note It is the responsibility of the caller function to ensure that +* correct values are passed to this function. +* +* The 2 LSBs of the SourcePtr (Source)/ DestPtr (Destination) +* address when equal to 2�b01 indicates the last DMA command of +* an overall transfer. +* +****************************************************************************/ +void XDcfg_InitiateDma(XDcfg *InstancePtr, u32 SourcePtr, u32 DestPtr, + u32 SrcWordLength, u32 DestWordLength) +{ + + XDcfg_WriteReg(InstancePtr->Config.BaseAddr, + XDCFG_DMA_SRC_ADDR_OFFSET, + SourcePtr); + + XDcfg_WriteReg(InstancePtr->Config.BaseAddr, + XDCFG_DMA_DEST_ADDR_OFFSET, + DestPtr); + + XDcfg_WriteReg(InstancePtr->Config.BaseAddr, + XDCFG_DMA_SRC_LEN_OFFSET, + SrcWordLength); + + XDcfg_WriteReg(InstancePtr->Config.BaseAddr, + XDCFG_DMA_DEST_LEN_OFFSET, + DestWordLength); +} + +/******************************************************************************/ +/** +* +* This function Implements the DMA Read Command. This command is used to +* transfer the image data from FPGA to the external memory. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* @param SourcePtr contains a pointer to the source memory where the data +* is to be transferred from. +* @param SrcWordLength is the number of words (32 bit) to be transferred +* for the source transfer. +* @param DestPtr contains a pointer to the destination memory +* where the data is to be transferred to. +* @param DestWordLength is the number of words (32 bit) to be transferred +* for the Destination transfer. +* +* @return - XST_INVALID_PARAM if source address/length is invalid. +* - XST_SUCCESS if DMA transfer initiated properly. +* +* @note None. +* +****************************************************************************/ +static u32 XDcfg_PcapReadback(XDcfg *InstancePtr, u32 SourcePtr, + u32 SrcWordLength, u32 DestPtr, + u32 DestWordLength) +{ + u32 IntrReg; + + /* + * Send READ Frame command to FPGA + */ + XDcfg_InitiateDma(InstancePtr, SourcePtr, XDCFG_DMA_INVALID_ADDRESS, + SrcWordLength, 0); + + /* + * Store the enabled interrupts to enable before the actual read + * transfer is initiated and Disable all the interrupts temporarily. + */ + IntrReg = XDcfg_IntrGetEnabled(InstancePtr); + XDcfg_IntrDisable(InstancePtr, XDCFG_IXR_ALL_MASK); + + /* + * Wait till you get the DMA done for the read command sent + */ + while ((XDcfg_ReadReg(InstancePtr->Config.BaseAddr, + XDCFG_INT_STS_OFFSET) & + XDCFG_IXR_D_P_DONE_MASK) != + XDCFG_IXR_D_P_DONE_MASK); + /* + * Enable the previously stored Interrupts . + */ + XDcfg_IntrEnable(InstancePtr, IntrReg); + + /* + * Initiate the DMA write command. + */ + XDcfg_InitiateDma(InstancePtr, XDCFG_DMA_INVALID_ADDRESS, (u32)DestPtr, + 0, DestWordLength); + + return XST_SUCCESS; +} + + +/****************************************************************************/ +/** +* +* This function starts the DMA transfer. This function only starts the +* operation and returns before the operation may be completed. +* If the interrupt is enabled, an interrupt will be generated when the +* operation is completed, otherwise it is necessary to poll the Status register +* to determine when it is completed. It is the responsibility of the caller to +* determine when the operation is completed by handling the generated interrupt +* or polling the Status Register. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* @param SourcePtr contains a pointer to the source memory where the data +* is to be transferred from. +* @param SrcWordLength is the number of words (32 bit) to be transferred +* for the source transfer. +* @param DestPtr contains a pointer to the destination memory +* where the data is to be transferred to. +* @param DestWordLength is the number of words (32 bit) to be transferred +* for the Destination transfer. +* @param TransferType contains the type of PCAP transfer being requested. +* The definitions can be found in the xdevcfg.h file. +* @return +* - XST_SUCCESS.if DMA transfer initiated successfully +* - XST_DEVICE_BUSY if DMA is busy +* - XST_INVALID_PARAM if invalid Source / Destination address +* is sent or an invalid Source / Destination length is +* sent +* +* @note It is the responsibility of the caller to ensure that the cache +* is flushed and invalidated both before the DMA operation is +* started and after the DMA operation completes if the memory +* pointed to is cached. The caller must also ensure that the +* pointers contain physical address rather than a virtual address +* if address translation is being used. +* +* The 2 LSBs of the SourcePtr (Source)/ DestPtr (Destination) +* address when equal to 2�b01 indicates the last DMA command of +* an overall transfer. +* +*****************************************************************************/ +u32 XDcfg_Transfer(XDcfg *InstancePtr, + void *SourcePtr, u32 SrcWordLength, + void *DestPtr, u32 DestWordLength, + u32 TransferType) +{ + + u32 CtrlReg; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + + if (XDcfg_IsDmaBusy(InstancePtr) == XST_SUCCESS) { + return XST_DEVICE_BUSY; + } + + /* + * Check whether the fabric is in initialized state + */ + if ((XDcfg_ReadReg(InstancePtr->Config.BaseAddr, XDCFG_STATUS_OFFSET) + & XDCFG_STATUS_PCFG_INIT_MASK) == 0) { + /* + * We don't need to check PCFG_INIT to be high for + * non-encrypted loopback transfers. + */ + if (TransferType != XDCFG_CONCURRENT_NONSEC_READ_WRITE) { + return XST_FAILURE; + } + } + + if ((TransferType == XDCFG_SECURE_PCAP_WRITE) || + (TransferType == XDCFG_NON_SECURE_PCAP_WRITE)) { + + /* Check for valid source pointer and length */ + if ((!SourcePtr) || (SrcWordLength == 0)) { + return XST_INVALID_PARAM; + } + + /* Clear internal PCAP loopback */ + CtrlReg = XDcfg_ReadReg(InstancePtr->Config.BaseAddr, + XDCFG_MCTRL_OFFSET); + XDcfg_WriteReg(InstancePtr->Config.BaseAddr, + XDCFG_MCTRL_OFFSET, (CtrlReg & + ~(XDCFG_MCTRL_PCAP_LPBK_MASK))); + + if (TransferType == XDCFG_NON_SECURE_PCAP_WRITE) { + /* + * Clear QUARTER_PCAP_RATE_EN bit + * so that the PCAP data is transmitted every clock + */ + CtrlReg = XDcfg_ReadReg(InstancePtr->Config.BaseAddr, + XDCFG_CTRL_OFFSET); + + XDcfg_WriteReg(InstancePtr->Config.BaseAddr, + XDCFG_CTRL_OFFSET, (CtrlReg & + ~XDCFG_CTRL_PCAP_RATE_EN_MASK)); + + } + if (TransferType == XDCFG_SECURE_PCAP_WRITE) { + /* + * AES engine handles only 8 bit data every clock cycle. + * Hence, Encrypted PCAP data which is 32 bit data can + * only be sent in every 4 clock cycles. Set the control + * register QUARTER_PCAP_RATE_EN bit to achieve this + * operation. + */ + XDcfg_SetControlRegister(InstancePtr, + XDCFG_CTRL_PCAP_RATE_EN_MASK); + } + + XDcfg_InitiateDma(InstancePtr, (u32)SourcePtr, + (u32)DestPtr, SrcWordLength, DestWordLength); + + } + + if (TransferType == XDCFG_PCAP_READBACK) { + + if ((!DestPtr) || (DestWordLength == 0)) { + + return XST_INVALID_PARAM; + } + + /* Clear internal PCAP loopback */ + CtrlReg = XDcfg_ReadReg(InstancePtr->Config.BaseAddr, + XDCFG_MCTRL_OFFSET); + XDcfg_WriteReg(InstancePtr->Config.BaseAddr, + XDCFG_MCTRL_OFFSET, (CtrlReg & + ~(XDCFG_MCTRL_PCAP_LPBK_MASK))); + + /* + * For PCAP readback of FPGA configuration register or memory, + * the read command is first sent (written) to the FPGA fabric + * which responds by returning the required read data. Read data + * from the FPGA is captured if pcap_radata_v is active.A DMA + * read transfer is required to obtain the readback command, + * which is then sent to the FPGA, followed by a DMA write + * transfer to support this mode of operation. + */ + return XDcfg_PcapReadback(InstancePtr, + (u32)SourcePtr, SrcWordLength, + (u32)DestPtr, DestWordLength); + } + + + if ((TransferType == XDCFG_CONCURRENT_SECURE_READ_WRITE) || + (TransferType == XDCFG_CONCURRENT_NONSEC_READ_WRITE)) { + + if ((!SourcePtr) || (SrcWordLength == 0) || + (!DestPtr) || (DestWordLength == 0)) { + return XST_INVALID_PARAM; + } + + if (TransferType == XDCFG_CONCURRENT_NONSEC_READ_WRITE) { + /* Enable internal PCAP loopback */ + CtrlReg = XDcfg_ReadReg(InstancePtr->Config.BaseAddr, + XDCFG_MCTRL_OFFSET); + XDcfg_WriteReg(InstancePtr->Config.BaseAddr, + XDCFG_MCTRL_OFFSET, (CtrlReg | + XDCFG_MCTRL_PCAP_LPBK_MASK)); + + /* + * Clear QUARTER_PCAP_RATE_EN bit + * so that the PCAP data is transmitted every clock + */ + CtrlReg = XDcfg_ReadReg(InstancePtr->Config.BaseAddr, + XDCFG_CTRL_OFFSET); + + XDcfg_WriteReg(InstancePtr->Config.BaseAddr, + XDCFG_CTRL_OFFSET, (CtrlReg & + ~XDCFG_CTRL_PCAP_RATE_EN_MASK)); + + } + if (TransferType == XDCFG_CONCURRENT_SECURE_READ_WRITE) { + /* Clear internal PCAP loopback */ + CtrlReg = XDcfg_ReadReg(InstancePtr->Config.BaseAddr, + XDCFG_MCTRL_OFFSET); + XDcfg_WriteReg(InstancePtr->Config.BaseAddr, + XDCFG_MCTRL_OFFSET, (CtrlReg & + ~(XDCFG_MCTRL_PCAP_LPBK_MASK))); + + /* + * Set the QUARTER_PCAP_RATE_EN bit + * so that the PCAP data is transmitted every 4 clock + * cycles, this is required for encrypted data. + */ + XDcfg_SetControlRegister(InstancePtr, + XDCFG_CTRL_PCAP_RATE_EN_MASK); + } + + XDcfg_InitiateDma(InstancePtr, (u32)SourcePtr, + (u32)DestPtr, SrcWordLength, DestWordLength); + } + + return XST_SUCCESS; +} +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/devcfg_v3_5/src/xdevcfg.h b/df_datalink/bsp/ps7_cortexa9_0/libsrc/devcfg_v3_5/src/xdevcfg.h new file mode 100644 index 0000000..6586370 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/devcfg_v3_5/src/xdevcfg.h @@ -0,0 +1,399 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2017 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xdevcfg.h +* @addtogroup devcfg_v3_5 +* @{ +* @details +* +* The is the main header file for the Device Configuration Interface of the Zynq +* device. The device configuration interface has three main functionality. +* 1. AXI-PCAP +* 2. Security Policy +* 3. XADC +* This current version of the driver supports only the AXI-PCAP and Security +* Policy blocks. There is a separate driver for XADC. +* +* AXI-PCAP is used for download/upload an encrypted or decrypted bitstream. +* DMA embedded in the AXI PCAP provides the master interface to +* the Device configuration block for any DMA transfers. The data transfer can +* take place between the Tx/RxFIFOs of AXI-PCAP and memory (on chip +* RAM/DDR/peripheral memory). +* +* The current driver only supports the downloading the FPGA bitstream and +* readback of the decrypted image (sort of loopback). +* The driver does not know what information needs to be written to the FPGA to +* readback FPGA configuration register or memory data. The application above the +* driver should take care of creating the data that needs to be downloaded to +* the FPGA so that the bitstream can be readback. +* This driver also does not support the reading of the internal registers of the +* PCAP. The driver has no knowledge of the PCAP internals. +* +* Initialization and Configuration +* +* The device driver enables higher layer software (e.g., an application) to +* communicate with the Device Configuration device. +* +* XDcfg_CfgInitialize() API is used to initialize the Device Configuration +* Interface. The user needs to first call the XDcfg_LookupConfig() API which +* returns the Configuration structure pointer which is passed as a parameter to +* the XDcfg_CfgInitialize() API. +* +* Interrupts +* The Driver implements an interrupt handler to support the interrupts provided +* by this interface. +* +* Threads +* +* This driver is not thread safe. Any needs for threads or thread mutual +* exclusion must be satisfied by the layer above this driver. +* +* Asserts +* +* Asserts are used within all Xilinx drivers to enforce constraints on argument +* values. Asserts can be turned off on a system-wide basis by defining, at +* compile time, the NDEBUG identifier. By default, asserts are turned on and it +* is recommended that users leave asserts on during development. +* +* Building the driver +* +* The XDcfg driver is composed of several source files. This allows the user +* to build and link only those parts of the driver that are necessary. +* +*

+* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 1.00a hvm 02/07/11 First release
+* 2.00a nm  05/31/12 Updated the driver for CR 660835 so that input length for
+*		     source/destination to the XDcfg_InitiateDma, XDcfg_Transfer
+*		     APIs is words (32 bit) and not bytes.
+* 		     Updated the notes for XDcfg_InitiateDma/XDcfg_Transfer APIs
+*		     to add information that 2 LSBs of the Source/Destination
+*		     address when equal to 2�b01 indicate the last DMA command
+*		     of an overall transfer.
+*		     Destination Address passed to this API for secure transfers
+*		     instead of using 0xFFFFFFFF for CR 662197. This issue was
+*		     resulting in the failure of secure transfers of
+*		     non-bitstream images.
+* 2.01a nm  07/07/12 Updated the XDcfg_IntrClear function to directly
+*		     set the mask instead of oring it with the
+*		     value read from the interrupt status register
+* 		     Added defines for the PS Version bits,
+*	             removed the FIFO Flush bits from the
+*		     Miscellaneous Control Reg.
+*		     Added XDcfg_GetPsVersion, XDcfg_SelectIcapInterface
+*		     and XDcfg_SelectPcapInterface APIs for CR 643295
+*		     The user has to call the XDcfg_SelectIcapInterface API
+*		     for the PL reconfiguration using AXI HwIcap.
+*		     Updated the XDcfg_Transfer API to clear the
+*		     QUARTER_PCAP_RATE_EN bit in the control register for
+*		     non secure writes for CR 675543.
+* 2.02a nm  01/31/13 Fixed CR# 679335.
+* 		     Added Setting and Clearing the internal PCAP loopback.
+*		     Removed code for enabling/disabling AES engine as BootROM
+*		     locks down this setting.
+*		     Fixed CR# 681976.
+*		     Skip Checking the PCFG_INIT in case of non-secure DMA
+*		     loopback.
+*		     Fixed CR# 699558.
+*		     XDcfg_Transfer fails to transfer data in loopback mode.
+*		     Fixed CR# 701348.
+*                    Peripheral test fails with  Running
+* 		     DcfgSelfTestExample() in SECURE bootmode.
+* 2.03a nm  04/19/13 Fixed CR# 703728.
+*		     Updated the register definitions as per the latest TRM
+*		     version UG585 (v1.4) November 16, 2012.
+* 3.0   adk 10/12/13 Updated as per the New Tcl API's
+* 3.0   kpc 21/02/14 Added function prototype for XDcfg_ClearControlRegister
+* 3.2   sb  08/25/14 Fixed XDcfg_PcapReadback() function
+*		     updated driver code with != instead of ==,
+*		     while checking for Interrupt Status with DMA and
+*		     PCAP Done Mask
+*		     ((XDcfg_ReadReg(InstancePtr->Config.BaseAddr,
+*			XDCFG_INT_STS_OFFSET) &
+*			XDCFG_IXR_D_P_DONE_MASK) !=
+*			XDCFG_IXR_D_P_DONE_MASK);
+*		     A new example has been added to read back the
+*		     configuration registers from the PL region.
+*		     xdevcfg_reg_readback_example.c
+* 3.3   sk  04/06/15 Modified XDcfg_ReadMultiBootConfig Macro CR# 851335.
+*       ms  03/17/17 Added readme.txt file in examples folder for doxygen
+*                    generation.
+*       ms  04/10/17 Modified filename tag in interrupt and polled examples
+*                    to include them in doxygen examples.
+* 3.5   ms  04/18/17 Modified tcl file to add suffix U for all macros
+*                    definitions of devcfg in xparameters.h
+*       ms  08/07/17 Fixed compilation warnings in xdevcfg_sinit.c
+* 
+* +******************************************************************************/ +#ifndef XDCFG_H /* prevent circular inclusions */ +#define XDCFG_H /* by using protection macros */ + +/***************************** Include Files *********************************/ + +#include "xdevcfg_hw.h" +#include "xstatus.h" +#include "xil_assert.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************** Constant Definitions *****************************/ + +/* Types of PCAP transfers */ + +#define XDCFG_NON_SECURE_PCAP_WRITE 1 +#define XDCFG_SECURE_PCAP_WRITE 2 +#define XDCFG_PCAP_READBACK 3 +#define XDCFG_CONCURRENT_SECURE_READ_WRITE 4 +#define XDCFG_CONCURRENT_NONSEC_READ_WRITE 5 + + +/**************************** Type Definitions *******************************/ +/** +* The handler data type allows the user to define a callback function to +* respond to interrupt events in the system. This function is executed +* in interrupt context, so amount of processing should be minimized. +* +* @param CallBackRef is the callback reference passed in by the upper +* layer when setting the callback functions, and passed back to +* the upper layer when the callback is invoked. Its type is +* unimportant to the driver component, so it is a void pointer. +* @param Status is the Interrupt status of the XDcfg device. +*/ +typedef void (*XDcfg_IntrHandler) (void *CallBackRef, u32 Status); + +/** + * This typedef contains configuration information for the device. + */ +typedef struct { + u16 DeviceId; /**< Unique ID of device */ + u32 BaseAddr; /**< Base address of the device */ +} XDcfg_Config; + +/** + * The XDcfg driver instance data. + */ +typedef struct { + XDcfg_Config Config; /**< Hardware Configuration */ + u32 IsReady; /**< Device is initialized and ready */ + u32 IsStarted; /**< Device Configuration Interface + * is running + */ + XDcfg_IntrHandler StatusHandler; /* Event handler function */ + void *CallBackRef; /* Callback reference for event handler */ +} XDcfg; + +/****************************************************************************/ +/** +* +* Unlock the Device Config Interface block. +* +* @param InstancePtr is a pointer to the instance of XDcfg driver. +* +* @return None. +* +* @note C-style signature: +* void XDcfg_Unlock(XDcfg* InstancePtr) +* +*****************************************************************************/ +#define XDcfg_Unlock(InstancePtr) \ + XDcfg_WriteReg((InstancePtr)->Config.BaseAddr, \ + XDCFG_UNLOCK_OFFSET, XDCFG_UNLOCK_DATA) + + + +/****************************************************************************/ +/** +* +* Get the version number of the PS from the Miscellaneous Control Register. +* +* @param InstancePtr is a pointer to the instance of XDcfg driver. +* +* @return Version of the PS. +* +* @note C-style signature: +* void XDcfg_GetPsVersion(XDcfg* InstancePtr) +* +*****************************************************************************/ +#define XDcfg_GetPsVersion(InstancePtr) \ + ((XDcfg_ReadReg((InstancePtr)->Config.BaseAddr, \ + XDCFG_MCTRL_OFFSET)) & \ + XDCFG_MCTRL_PCAP_PS_VERSION_MASK) >> \ + XDCFG_MCTRL_PCAP_PS_VERSION_SHIFT + + + +/****************************************************************************/ +/** +* +* Read the multiboot config register value. +* +* @param InstancePtr is a pointer to the instance of XDcfg driver. +* +* @return None. +* +* @note C-style signature: +* u32 XDcfg_ReadMultiBootConfig(XDcfg* InstancePtr) +* +*****************************************************************************/ +#define XDcfg_ReadMultiBootConfig(InstancePtr) \ + XDcfg_ReadReg((InstancePtr)->Config.BaseAddr, \ + XDCFG_MULTIBOOT_ADDR_OFFSET) + + +/****************************************************************************/ +/** +* +* Selects ICAP interface for reconfiguration after the initial configuration +* of the PL. +* +* @param InstancePtr is a pointer to the instance of XDcfg driver. +* +* @return None. +* +* @note C-style signature: +* void XDcfg_SelectIcapInterface(XDcfg* InstancePtr) +* +*****************************************************************************/ +#define XDcfg_SelectIcapInterface(InstancePtr) \ + XDcfg_WriteReg((InstancePtr)->Config.BaseAddr, XDCFG_CTRL_OFFSET, \ + ((XDcfg_ReadReg((InstancePtr)->Config.BaseAddr, XDCFG_CTRL_OFFSET)) \ + & ( ~XDCFG_CTRL_PCAP_PR_MASK))) + +/****************************************************************************/ +/** +* +* Selects PCAP interface for reconfiguration after the initial configuration +* of the PL. +* +* @param InstancePtr is a pointer to the instance of XDcfg driver. +* +* @return None. +* +* @note C-style signature: +* void XDcfg_SelectPcapInterface(XDcfg* InstancePtr) +* +*****************************************************************************/ +#define XDcfg_SelectPcapInterface(InstancePtr) \ + XDcfg_WriteReg((InstancePtr)->Config.BaseAddr, XDCFG_CTRL_OFFSET, \ + ((XDcfg_ReadReg((InstancePtr)->Config.BaseAddr, XDCFG_CTRL_OFFSET)) \ + | XDCFG_CTRL_PCAP_PR_MASK)) + + + +/************************** Function Prototypes ******************************/ + +/* + * Lookup configuration in xdevcfg_sinit.c. + */ +XDcfg_Config *XDcfg_LookupConfig(u16 DeviceId); + +/* + * Selftest function in xdevcfg_selftest.c + */ +int XDcfg_SelfTest(XDcfg *InstancePtr); + +/* + * Interface functions in xdevcfg.c + */ +int XDcfg_CfgInitialize(XDcfg *InstancePtr, + XDcfg_Config *ConfigPtr, u32 EffectiveAddress); + +void XDcfg_EnablePCAP(XDcfg *InstancePtr); + +void XDcfg_DisablePCAP(XDcfg *InstancePtr); + +void XDcfg_SetControlRegister(XDcfg *InstancePtr, u32 Mask); + +void XDcfg_ClearControlRegister(XDcfg *InstancePtr, u32 Mask); + +u32 XDcfg_GetControlRegister(XDcfg *InstancePtr); + +void XDcfg_SetLockRegister(XDcfg *InstancePtr, u32 Data); + +u32 XDcfg_GetLockRegister(XDcfg *InstancePtr); + +void XDcfg_SetConfigRegister(XDcfg *InstancePtr, u32 Data); + +u32 XDcfg_GetConfigRegister(XDcfg *InstancePtr); + +void XDcfg_SetStatusRegister(XDcfg *InstancePtr, u32 Data); + +u32 XDcfg_GetStatusRegister(XDcfg *InstancePtr); + +void XDcfg_SetRomShadowRegister(XDcfg *InstancePtr, u32 Data); + +u32 XDcfg_GetSoftwareIdRegister(XDcfg *InstancePtr); + +void XDcfg_SetMiscControlRegister(XDcfg *InstancePtr, u32 Mask); + +u32 XDcfg_GetMiscControlRegister(XDcfg *InstancePtr); + +u32 XDcfg_IsDmaBusy(XDcfg *InstancePtr); + +void XDcfg_InitiateDma(XDcfg *InstancePtr, u32 SourcePtr, u32 DestPtr, + u32 SrcWordLength, u32 DestWordLength); + +u32 XDcfg_Transfer(XDcfg *InstancePtr, + void *SourcePtr, u32 SrcWordLength, + void *DestPtr, u32 DestWordLength, + u32 TransferType); + +/* + * Interrupt related function prototypes implemented in xdevcfg_intr.c + */ +void XDcfg_IntrEnable(XDcfg *InstancePtr, u32 Mask); + +void XDcfg_IntrDisable(XDcfg *InstancePtr, u32 Mask); + +u32 XDcfg_IntrGetEnabled(XDcfg *InstancePtr); + +u32 XDcfg_IntrGetStatus(XDcfg *InstancePtr); + +void XDcfg_IntrClear(XDcfg *InstancePtr, u32 Mask); + +void XDcfg_InterruptHandler(XDcfg *InstancePtr); + +void XDcfg_SetHandler(XDcfg *InstancePtr, void *CallBackFunc, + void *CallBackRef); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/devcfg_v3_5/src/xdevcfg_g.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/devcfg_v3_5/src/xdevcfg_g.c new file mode 100644 index 0000000..62b8d43 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/devcfg_v3_5/src/xdevcfg_g.c @@ -0,0 +1,51 @@ + +/******************************************************************* +* +* CAUTION: This file is automatically generated by HSI. +* Version: 2019.1.3 +* DO NOT EDIT. +* +* Copyright (C) 2010-2023 Xilinx, Inc. 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 +*XILINX 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. +* +*Except as contained in this notice, the name of the Xilinx shall not be used +*in advertising or otherwise to promote the sale, use or other dealings in +*this Software without prior written authorization from Xilinx. +* + +* +* Description: Driver configuration +* +*******************************************************************/ + +#include "xparameters.h" +#include "xdevcfg.h" + +/* +* The configuration table for devices +*/ + +XDcfg_Config XDcfg_ConfigTable[] = +{ + { + XPAR_PS7_DEV_CFG_0_DEVICE_ID, + XPAR_PS7_DEV_CFG_0_BASEADDR + } +}; + + diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/devcfg_v3_5/src/xdevcfg_hw.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/devcfg_v3_5/src/xdevcfg_hw.c new file mode 100644 index 0000000..8a1379a --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/devcfg_v3_5/src/xdevcfg_hw.c @@ -0,0 +1,109 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xdevcfg_hw.c +* @addtogroup devcfg_v3_5 +* @{ +* +* This file contains the implementation of the interface reset functionality +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 2.04a kpc 10/07/13 First release
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xdevcfg_hw.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +/*****************************************************************************/ +/** +* This function perform the reset sequence to the given devcfg interface by +* configuring the appropriate control bits in the devcfg specifc registers +* the devcfg reset squence involves the following steps +* Disable all the interuupts +* Clear the status +* Update relevant config registers with reset values +* Disbale the looopback mode and pcap rate enable +* +* @param BaseAddress of the interface +* +* @return N/A +* +* @note +* This function will not modify the slcr registers that are relavant for +* devcfg controller +******************************************************************************/ +void XDcfg_ResetHw(u32 BaseAddr) +{ + u32 Regval = 0; + + /* Mask the interrupts */ + XDcfg_WriteReg(BaseAddr, XDCFG_INT_MASK_OFFSET, + XDCFG_IXR_ALL_MASK); + /* Clear the interuupt status */ + Regval = XDcfg_ReadReg(BaseAddr, XDCFG_INT_STS_OFFSET); + XDcfg_WriteReg(BaseAddr, XDCFG_INT_STS_OFFSET, Regval); + /* Clear the source address register */ + XDcfg_WriteReg(BaseAddr, XDCFG_DMA_SRC_ADDR_OFFSET, 0x0); + /* Clear the destination address register */ + XDcfg_WriteReg(BaseAddr, XDCFG_DMA_DEST_ADDR_OFFSET, 0x0); + /* Clear the source length register */ + XDcfg_WriteReg(BaseAddr, XDCFG_DMA_SRC_LEN_OFFSET, 0x0); + /* Clear the destination length register */ + XDcfg_WriteReg(BaseAddr, XDCFG_DMA_DEST_LEN_OFFSET, 0x0); + /* Clear the loopback enable bit */ + Regval = XDcfg_ReadReg(BaseAddr, XDCFG_MCTRL_OFFSET); + Regval = Regval & ~XDCFG_MCTRL_PCAP_LPBK_MASK; + XDcfg_WriteReg(BaseAddr, XDCFG_MCTRL_OFFSET, Regval); + /*Reset the configuration register to reset value */ + XDcfg_WriteReg(BaseAddr, XDCFG_CFG_OFFSET, + XDCFG_CONFIG_RESET_VALUE); + /*Disable the PCAP rate enable bit */ + Regval = XDcfg_ReadReg(BaseAddr, XDCFG_CTRL_OFFSET); + Regval = Regval & ~XDCFG_CTRL_PCAP_RATE_EN_MASK; + XDcfg_WriteReg(BaseAddr, XDCFG_CTRL_OFFSET, Regval); + +} +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/devcfg_v3_5/src/xdevcfg_hw.h b/df_datalink/bsp/ps7_cortexa9_0/libsrc/devcfg_v3_5/src/xdevcfg_hw.h new file mode 100644 index 0000000..80b6678 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/devcfg_v3_5/src/xdevcfg_hw.h @@ -0,0 +1,391 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xdevcfg_hw.h +* @addtogroup devcfg_v3_3 +* @{ +* +* This file contains the hardware interface to the Device Config Interface. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 1.00a hvm 02/07/11 First release
+* 2.01a nm  08/01/12 Added defines for the PS Version bits,
+*	             removed the FIFO Flush bits from the
+*		     Miscellaneous Control Reg
+* 2.03a nm  04/19/13 Fixed CR# 703728.
+*		     Updated the register definitions as per the latest TRM
+*		     version UG585 (v1.4) November 16, 2012.
+* 2.04a	kpc	10/07/13 Added function prototype.
+* 3.00a	kpc	25/02/14 Corrected the XDCFG_BASE_ADDRESS macro value.
+* 
+* +******************************************************************************/ +#ifndef XDCFG_HW_H /* prevent circular inclusions */ +#define XDCFG_HW_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_io.h" + +/************************** Constant Definitions *****************************/ + +/** @name Register Map + * Offsets of registers from the start of the device + * @{ + */ + +#define XDCFG_CTRL_OFFSET 0x00 /**< Control Register */ +#define XDCFG_LOCK_OFFSET 0x04 /**< Lock Register */ +#define XDCFG_CFG_OFFSET 0x08 /**< Configuration Register */ +#define XDCFG_INT_STS_OFFSET 0x0C /**< Interrupt Status Register */ +#define XDCFG_INT_MASK_OFFSET 0x10 /**< Interrupt Mask Register */ +#define XDCFG_STATUS_OFFSET 0x14 /**< Status Register */ +#define XDCFG_DMA_SRC_ADDR_OFFSET 0x18 /**< DMA Source Address Register */ +#define XDCFG_DMA_DEST_ADDR_OFFSET 0x1C /**< DMA Destination Address Reg */ +#define XDCFG_DMA_SRC_LEN_OFFSET 0x20 /**< DMA Source Transfer Length */ +#define XDCFG_DMA_DEST_LEN_OFFSET 0x24 /**< DMA Destination Transfer */ +#define XDCFG_ROM_SHADOW_OFFSET 0x28 /**< DMA ROM Shadow Register */ +#define XDCFG_MULTIBOOT_ADDR_OFFSET 0x2C /**< Multi BootAddress Pointer */ +#define XDCFG_SW_ID_OFFSET 0x30 /**< Software ID Register */ +#define XDCFG_UNLOCK_OFFSET 0x34 /**< Unlock Register */ +#define XDCFG_MCTRL_OFFSET 0x80 /**< Miscellaneous Control Reg */ + +/* @} */ + +/** @name Control Register Bit definitions + * @{ + */ + +#define XDCFG_CTRL_FORCE_RST_MASK 0x80000000 /**< Force into + * Secure Reset + */ +#define XDCFG_CTRL_PCFG_PROG_B_MASK 0x40000000 /**< Program signal to + * Reset FPGA + */ +#define XDCFG_CTRL_PCFG_POR_CNT_4K_MASK 0x20000000 /**< Control PL POR timer */ +#define XDCFG_CTRL_PCAP_PR_MASK 0x08000000 /**< Enable PCAP for PR */ +#define XDCFG_CTRL_PCAP_MODE_MASK 0x04000000 /**< Enable PCAP */ +#define XDCFG_CTRL_PCAP_RATE_EN_MASK 0x02000000 /**< Enable PCAP send data + * to FPGA every 4 PCAP + * cycles + */ +#define XDCFG_CTRL_MULTIBOOT_EN_MASK 0x01000000 /**< Multiboot Enable */ +#define XDCFG_CTRL_JTAG_CHAIN_DIS_MASK 0x00800000 /**< JTAG Chain Disable */ +#define XDCFG_CTRL_USER_MODE_MASK 0x00008000 /**< User Mode Mask */ +#define XDCFG_CTRL_PCFG_AES_FUSE_MASK 0x00001000 /**< AES key source */ +#define XDCFG_CTRL_PCFG_AES_EN_MASK 0x00000E00 /**< AES Enable Mask */ +#define XDCFG_CTRL_SEU_EN_MASK 0x00000100 /**< SEU Enable Mask */ +#define XDCFG_CTRL_SEC_EN_MASK 0x00000080 /**< Secure/Non Secure + * Status mask + */ +#define XDCFG_CTRL_SPNIDEN_MASK 0x00000040 /**< Secure Non Invasive + * Debug Enable + */ +#define XDCFG_CTRL_SPIDEN_MASK 0x00000020 /**< Secure Invasive + * Debug Enable + */ +#define XDCFG_CTRL_NIDEN_MASK 0x00000010 /**< Non-Invasive Debug + * Enable + */ +#define XDCFG_CTRL_DBGEN_MASK 0x00000008 /**< Invasive Debug + * Enable + */ +#define XDCFG_CTRL_DAP_EN_MASK 0x00000007 /**< DAP Enable Mask */ + +/* @} */ + +/** @name Lock register bit definitions + * @{ + */ + +#define XDCFG_LOCK_AES_EFUSE_MASK 0x00000010 /**< Lock AES Efuse bit */ +#define XDCFG_LOCK_AES_EN_MASK 0x00000008 /**< Lock AES_EN update */ +#define XDCFG_LOCK_SEU_MASK 0x00000004 /**< Lock SEU_En update */ +#define XDCFG_LOCK_SEC_MASK 0x00000002 /**< Lock SEC_EN and + * USER_MODE + */ +#define XDCFG_LOCK_DBG_MASK 0x00000001 /**< This bit locks + * security config + * including: DAP_En, + * DBGEN,, + * NIDEN, SPNIEN + */ +/*@}*/ + + + +/** @name Config Register Bit definitions + * @{ + */ +#define XDCFG_CFG_RFIFO_TH_MASK 0x00000C00 /**< Read FIFO + * Threshold Mask + */ +#define XDCFG_CFG_WFIFO_TH_MASK 0x00000300 /**< Write FIFO Threshold + * Mask + */ +#define XDCFG_CFG_RCLK_EDGE_MASK 0x00000080 /**< Read data active + * clock edge + */ +#define XDCFG_CFG_WCLK_EDGE_MASK 0x00000040 /**< Write data active + * clock edge + */ +#define XDCFG_CFG_DISABLE_SRC_INC_MASK 0x00000020 /**< Disable Source address + * increment mask + */ +#define XDCFG_CFG_DISABLE_DST_INC_MASK 0x00000010 /**< Disable Destination + * address increment + * mask + */ +/* @} */ + + +/** @name Interrupt Status/Mask Register Bit definitions + * @{ + */ +#define XDCFG_IXR_PSS_GTS_USR_B_MASK 0x80000000 /**< Tri-state IO during + * HIZ + */ +#define XDCFG_IXR_PSS_FST_CFG_B_MASK 0x40000000 /**< First configuration + * done + */ +#define XDCFG_IXR_PSS_GPWRDWN_B_MASK 0x20000000 /**< Global power down */ +#define XDCFG_IXR_PSS_GTS_CFG_B_MASK 0x10000000 /**< Tri-state IO during + * configuration + */ +#define XDCFG_IXR_PSS_CFG_RESET_B_MASK 0x08000000 /**< PL configuration + * reset + */ +#define XDCFG_IXR_AXI_WTO_MASK 0x00800000 /**< AXI Write Address + * or Data or response + * timeout + */ +#define XDCFG_IXR_AXI_WERR_MASK 0x00400000 /**< AXI Write response + * error + */ +#define XDCFG_IXR_AXI_RTO_MASK 0x00200000 /**< AXI Read Address or + * response timeout + */ +#define XDCFG_IXR_AXI_RERR_MASK 0x00100000 /**< AXI Read response + * error + */ +#define XDCFG_IXR_RX_FIFO_OV_MASK 0x00040000 /**< Rx FIFO Overflow */ +#define XDCFG_IXR_WR_FIFO_LVL_MASK 0x00020000 /**< Tx FIFO less than + * threshold */ +#define XDCFG_IXR_RD_FIFO_LVL_MASK 0x00010000 /**< Rx FIFO greater than + * threshold */ +#define XDCFG_IXR_DMA_CMD_ERR_MASK 0x00008000 /**< Illegal DMA command */ +#define XDCFG_IXR_DMA_Q_OV_MASK 0x00004000 /**< DMA command queue + * overflow + */ +#define XDCFG_IXR_DMA_DONE_MASK 0x00002000 /**< DMA Command Done */ +#define XDCFG_IXR_D_P_DONE_MASK 0x00001000 /**< DMA and PCAP + * transfers Done + */ +#define XDCFG_IXR_P2D_LEN_ERR_MASK 0x00000800 /**< PCAP to DMA transfer + * length error + */ +#define XDCFG_IXR_PCFG_HMAC_ERR_MASK 0x00000040 /**< HMAC error mask */ +#define XDCFG_IXR_PCFG_SEU_ERR_MASK 0x00000020 /**< SEU Error mask */ +#define XDCFG_IXR_PCFG_POR_B_MASK 0x00000010 /**< FPGA POR mask */ +#define XDCFG_IXR_PCFG_CFG_RST_MASK 0x00000008 /**< FPGA Reset mask */ +#define XDCFG_IXR_PCFG_DONE_MASK 0x00000004 /**< Done Signal Mask */ +#define XDCFG_IXR_PCFG_INIT_PE_MASK 0x00000002 /**< Detect Positive edge + * of Init Signal + */ +#define XDCFG_IXR_PCFG_INIT_NE_MASK 0x00000001 /**< Detect Negative edge + * of Init Signal + */ +#define XDCFG_IXR_ERROR_FLAGS_MASK (XDCFG_IXR_AXI_WTO_MASK | \ + XDCFG_IXR_AXI_WERR_MASK | \ + XDCFG_IXR_AXI_RTO_MASK | \ + XDCFG_IXR_AXI_RERR_MASK | \ + XDCFG_IXR_RX_FIFO_OV_MASK | \ + XDCFG_IXR_DMA_CMD_ERR_MASK |\ + XDCFG_IXR_DMA_Q_OV_MASK | \ + XDCFG_IXR_P2D_LEN_ERR_MASK |\ + XDCFG_IXR_PCFG_HMAC_ERR_MASK) + + +#define XDCFG_IXR_ALL_MASK 0x00F7F8EF + + + +/* @} */ + + +/** @name Status Register Bit definitions + * @{ + */ +#define XDCFG_STATUS_DMA_CMD_Q_F_MASK 0x80000000 /**< DMA command + * Queue full + */ +#define XDCFG_STATUS_DMA_CMD_Q_E_MASK 0x40000000 /**< DMA command + * Queue empty + */ +#define XDCFG_STATUS_DMA_DONE_CNT_MASK 0x30000000 /**< Number of + * completed DMA + * transfers + */ +#define XDCFG_STATUS_RX_FIFO_LVL_MASK 0x01F000000 /**< Rx FIFO level */ +#define XDCFG_STATUS_TX_FIFO_LVL_MASK 0x0007F000 /**< Tx FIFO level */ + +#define XDCFG_STATUS_PSS_GTS_USR_B 0x00000800 /**< Tri-state IO + * during HIZ + */ +#define XDCFG_STATUS_PSS_FST_CFG_B 0x00000400 /**< First PL config + * done + */ +#define XDCFG_STATUS_PSS_GPWRDWN_B 0x00000200 /**< Global power down */ +#define XDCFG_STATUS_PSS_GTS_CFG_B 0x00000100 /**< Tri-state IO during + * config + */ +#define XDCFG_STATUS_SECURE_RST_MASK 0x00000080 /**< Secure Reset + * POR Status + */ +#define XDCFG_STATUS_ILLEGAL_APB_ACCESS_MASK 0x00000040 /**< Illegal APB + * access + */ +#define XDCFG_STATUS_PSS_CFG_RESET_B 0x00000020 /**< PL config + * reset status + */ +#define XDCFG_STATUS_PCFG_INIT_MASK 0x00000010 /**< FPGA Init + * Status + */ +#define XDCFG_STATUS_EFUSE_BBRAM_KEY_DISABLE_MASK 0x00000008 + /**< BBRAM key + * disable + */ +#define XDCFG_STATUS_EFUSE_SEC_EN_MASK 0x00000004 /**< Efuse Security + * Enable Status + */ +#define XDCFG_STATUS_EFUSE_JTAG_DIS_MASK 0x00000002 /**< EFuse JTAG + * Disable + * status + */ +/* @} */ + + +/** @name DMA Source/Destination Transfer Length Register Bit definitions + * @{ + */ +#define XDCFG_DMA_LEN_MASK 0x7FFFFFF /**< Length Mask */ +/*@}*/ + + + + +/** @name Miscellaneous Control Register Bit definitions + * @{ + */ +#define XDCFG_MCTRL_PCAP_PS_VERSION_MASK 0xF0000000 /**< PS Version Mask */ +#define XDCFG_MCTRL_PCAP_PS_VERSION_SHIFT 28 /**< PS Version Shift */ +#define XDCFG_MCTRL_PCAP_LPBK_MASK 0x00000010 /**< PCAP loopback mask */ +/* @} */ + +/** @name FIFO Threshold Bit definitions + * @{ + */ + +#define XDCFG_CFG_FIFO_QUARTER 0x0 /**< Quarter empty */ +#define XDCFG_CFG_FIFO_HALF 0x1 /**< Half empty */ +#define XDCFG_CFG_FIFO_3QUARTER 0x2 /**< 3/4 empty */ +#define XDCFG_CFG_FIFO_EMPTY 0x4 /**< Empty */ +/* @}*/ + + +/* Miscellaneous constant values */ +#define XDCFG_DMA_INVALID_ADDRESS 0xFFFFFFFF /**< Invalid DMA address */ +#define XDCFG_UNLOCK_DATA 0x757BDF0D /**< First APB access data*/ +#define XDCFG_BASE_ADDRESS 0xF8007000 /**< Device Config base + * address + */ +#define XDCFG_CONFIG_RESET_VALUE 0x508 /**< Config reg reset value */ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/****************************************************************************/ +/** +* +* Read the given register. +* +* @param BaseAddr is the base address of the device +* @param RegOffset is the register offset to be read +* +* @return The 32-bit value of the register +* +* @note C-style signature: +* u32 XDcfg_ReadReg(u32 BaseAddr, u32 RegOffset) +* +*****************************************************************************/ +#define XDcfg_ReadReg(BaseAddr, RegOffset) \ + Xil_In32((BaseAddr) + (RegOffset)) + +/****************************************************************************/ +/** +* +* Write to the given register. +* +* @param BaseAddr is the base address of the device +* @param RegOffset is the register offset to be written +* @param Data is the 32-bit value to write to the register +* +* @return None. +* +* @note C-style signature: +* void XDcfg_WriteReg(u32 BaseAddr, u32 RegOffset, u32 Data) +* +*****************************************************************************/ +#define XDcfg_WriteReg(BaseAddr, RegOffset, Data) \ + Xil_Out32((BaseAddr) + (RegOffset), (Data)) + +/************************** Function Prototypes ******************************/ +/* + * Perform reset operation to the devcfg interface + */ +void XDcfg_ResetHw(u32 BaseAddr); +/************************** Variable Definitions *****************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/devcfg_v3_5/src/xdevcfg_intr.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/devcfg_v3_5/src/xdevcfg_intr.c new file mode 100644 index 0000000..f0e5044 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/devcfg_v3_5/src/xdevcfg_intr.c @@ -0,0 +1,306 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xdevcfg_intr.c +* @addtogroup devcfg_v3_5 +* @{ +* +* Contains the implementation of interrupt related functions of the XDcfg +* driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 1.00a hvm 02/07/11 First release
+* 2.01a nm  07/07/12 Updated the XDcfg_IntrClear function to directly
+*		     set the mask instead of oring it with the
+*		     value read from the interrupt status register
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xdevcfg.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +/****************************************************************************/ +/** +* +* This function enables the specified interrupts in the device. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* @param Mask is the bit-mask of the interrupts to be enabled. +* Bit positions of 1 will be enabled. Bit positions of 0 will +* keep the previous setting. This mask is formed by OR'ing +* XDCFG_INT_* bits defined in xdevcfg_hw.h. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XDcfg_IntrEnable(XDcfg *InstancePtr, u32 Mask) +{ + u32 RegValue; + + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Enable the specified interrupts in the Interrupt Mask Register. + */ + RegValue = XDcfg_ReadReg(InstancePtr->Config.BaseAddr, + XDCFG_INT_MASK_OFFSET); + RegValue &= ~(Mask & XDCFG_IXR_ALL_MASK); + XDcfg_WriteReg(InstancePtr->Config.BaseAddr, + XDCFG_INT_MASK_OFFSET, + RegValue); +} + + +/****************************************************************************/ +/** +* +* This function disables the specified interrupts in the device. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* @param Mask is the bit-mask of the interrupts to be disabled. +* Bit positions of 1 will be disabled. Bit positions of 0 will +* keep the previous setting. This mask is formed by OR'ing +* XDCFG_INT_* bits defined in xdevcfg_hw.h. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XDcfg_IntrDisable(XDcfg *InstancePtr, u32 Mask) +{ + u32 RegValue; + + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Disable the specified interrupts in the Interrupt Mask Register. + */ + RegValue = XDcfg_ReadReg(InstancePtr->Config.BaseAddr, + XDCFG_INT_MASK_OFFSET); + RegValue |= (Mask & XDCFG_IXR_ALL_MASK); + XDcfg_WriteReg(InstancePtr->Config.BaseAddr, + XDCFG_INT_MASK_OFFSET, + RegValue); +} +/****************************************************************************/ +/** +* +* This function returns the enabled interrupts read from the Interrupt Mask +* Register. Use the XDCFG_INT_* constants defined in xdevcfg_hw.h +* to interpret the returned value. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* +* @return A 32-bit value representing the contents of the IMR. +* +* @note None. +* +*****************************************************************************/ +u32 XDcfg_IntrGetEnabled(XDcfg *InstancePtr) +{ + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Return the value read from the Interrupt Mask Register. + */ + return (~ XDcfg_ReadReg(InstancePtr->Config.BaseAddr, + XDCFG_INT_MASK_OFFSET)); +} + +/****************************************************************************/ +/** +* +* This function returns the interrupt status read from Interrupt Status +* Register. Use the XDCFG_INT_* constants defined in xdevcfg_hw.h +* to interpret the returned value. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* +* @return A 32-bit value representing the contents of the Interrupt +* Status register. +* +* @note None. +* +*****************************************************************************/ +u32 XDcfg_IntrGetStatus(XDcfg *InstancePtr) +{ + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Return the value read from the Interrupt Status register. + */ + return XDcfg_ReadReg(InstancePtr->Config.BaseAddr, + XDCFG_INT_STS_OFFSET); +} + +/****************************************************************************/ +/** +* +* This function clears the specified interrupts in the Interrupt Status +* Register. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* @param Mask is the bit-mask of the interrupts to be cleared. +* Bit positions of 1 will be cleared. Bit positions of 0 will not +* change the previous interrupt status. This mask is formed by +* OR'ing XDCFG_INT_* bits which are defined in xdevcfg_hw.h. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XDcfg_IntrClear(XDcfg *InstancePtr, u32 Mask) +{ + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + XDcfg_WriteReg(InstancePtr->Config.BaseAddr, + XDCFG_INT_STS_OFFSET, + Mask); + +} + +/*****************************************************************************/ +/** +* The interrupt handler for the Device Config Interface. +* +* Events are signaled to upper layer for proper handling. +* +* +* @param InstancePtr is a pointer to the XDcfg instance. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void XDcfg_InterruptHandler(XDcfg *InstancePtr) +{ + u32 IntrStatusReg; + + /* + * Assert validates the input arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the Interrupt status register. + */ + IntrStatusReg = XDcfg_ReadReg(InstancePtr->Config.BaseAddr, + XDCFG_INT_STS_OFFSET); + + /* + * Write the status back to clear the interrupts so that no + * subsequent interrupts are missed while processing this interrupt. + * This also does the DMA acknowledgment automatically. + */ + XDcfg_WriteReg(InstancePtr->Config.BaseAddr, + XDCFG_INT_STS_OFFSET, IntrStatusReg); + + /* + * Signal application that there are events to handle. + */ + InstancePtr->StatusHandler(InstancePtr->CallBackRef, + IntrStatusReg); + +} + +/****************************************************************************/ +/** +* +* This function sets the handler that will be called when an event (interrupt) +* occurs that needs application's attention. +* +* @param InstancePtr is a pointer to the XDcfg instance +* @param CallBackFunc is the address of the callback function. +* @param CallBackRef is a user data item that will be passed to the +* callback function when it is invoked. +* +* @return None. +* +* @note None. +* +* +*****************************************************************************/ +void XDcfg_SetHandler(XDcfg *InstancePtr, void *CallBackFunc, + void *CallBackRef) +{ + /* + * Asserts validate the input arguments + * CallBackRef not checked, no way to know what is valid + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(CallBackFunc != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + InstancePtr->StatusHandler = (XDcfg_IntrHandler) CallBackFunc; + InstancePtr->CallBackRef = CallBackRef; +} +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/devcfg_v3_5/src/xdevcfg_selftest.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/devcfg_v3_5/src/xdevcfg_selftest.c new file mode 100644 index 0000000..e8fc663 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/devcfg_v3_5/src/xdevcfg_selftest.c @@ -0,0 +1,110 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xdevcfg_selftest.c +* @addtogroup devcfg_v3_5 +* @{ +* +* Contains diagnostic self-test functions for the XDcfg driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 1.00a hvm 02/07/11 First release
+* 2.02a nm  02/27/13 Fixed CR# 701348.
+*                    Peripheral test fails with  Running
+* 		     DcfgSelfTestExample() in SECURE bootmode.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xdevcfg.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +/****************************************************************************/ +/** +* +* Run a self-test on the Device Configuration Interface. This test does a +* control register write and reads back the same value. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* +* @return +* - XST_SUCCESS if self-test was successful. +* - XST_FAILURE if fails. +* +* @note None. +* +******************************************************************************/ +int XDcfg_SelfTest(XDcfg *InstancePtr) +{ + u32 OldCfgReg; + u32 CfgReg; + int Status = XST_SUCCESS; + + /* + * Assert to ensure the inputs are valid and the instance has been + * initialized. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + OldCfgReg = XDcfg_GetControlRegister(InstancePtr); + + XDcfg_SetControlRegister(InstancePtr, XDCFG_CTRL_NIDEN_MASK); + + CfgReg = XDcfg_GetControlRegister(InstancePtr); + + if ((CfgReg & XDCFG_CTRL_NIDEN_MASK) != XDCFG_CTRL_NIDEN_MASK) { + + Status = XST_FAILURE; + } + + /* + * Restore the original values of the register + */ + XDcfg_SetControlRegister(InstancePtr, OldCfgReg); + + return Status; +} +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/devcfg_v3_5/src/xdevcfg_sinit.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/devcfg_v3_5/src/xdevcfg_sinit.c new file mode 100644 index 0000000..838db3a --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/devcfg_v3_5/src/xdevcfg_sinit.c @@ -0,0 +1,90 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2017 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xdevcfg_sinit.c +* @addtogroup devcfg_v3_5 +* @{ +* +* This file contains method for static initialization (compile-time) of the +* driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 1.00a hvm 02/07/11 First release
+* 3.5   ms  08/07/17 Fixed compilation warnings.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xdevcfg.h" +#include "xparameters.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/*****************************************************************************/ +/** +* Lookup the device configuration based on the unique device ID. The table +* contains the configuration info for each device in the system. +* +* @param DeviceId is the unique device ID of the device being looked up. +* +* @return A pointer to the configuration table entry corresponding to the +* given device ID, or NULL if no match is found. +* +* @note None. +* +******************************************************************************/ +XDcfg_Config *XDcfg_LookupConfig(u16 DeviceId) +{ + extern XDcfg_Config XDcfg_ConfigTable[]; + XDcfg_Config *CfgPtr = NULL; + u32 Index; + + for (Index = 0U; Index < XPAR_XDCFG_NUM_INSTANCES; Index++) { + if (XDcfg_ConfigTable[Index].DeviceId == DeviceId) { + CfgPtr = &XDcfg_ConfigTable[Index]; + break; + } + } + + return (CfgPtr); +} +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/dmaps_v2_4/src/Makefile b/df_datalink/bsp/ps7_cortexa9_0/libsrc/dmaps_v2_4/src/Makefile new file mode 100644 index 0000000..d1240c5 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/dmaps_v2_4/src/Makefile @@ -0,0 +1,41 @@ +COMPILER= +ARCHIVER= +CP=cp +COMPILER_FLAGS= +EXTRA_COMPILER_FLAGS= +LIB=libxil.a + +CC_FLAGS = $(COMPILER_FLAGS) +ECC_FLAGS = $(EXTRA_COMPILER_FLAGS) + +RELEASEDIR=../../../lib +INCLUDEDIR=../../../include +INCLUDES=-I./. -I${INCLUDEDIR} + +OUTS = *.o + +LIBSOURCES:=*.c +INCLUDEFILES:=*.h + +OBJECTS = $(addsuffix .o, $(basename $(wildcard *.c))) + +libs: banner xdmaps_libs clean + +%.o: %.c + ${COMPILER} $(CC_FLAGS) $(ECC_FLAGS) $(INCLUDES) -o $@ $< + +banner: + echo "Compiling dmaps" + +xdmaps_libs: ${OBJECTS} + $(ARCHIVER) -r ${RELEASEDIR}/${LIB} ${OBJECTS} + +.PHONY: include +include: xdmaps_includes + +xdmaps_includes: + ${CP} ${INCLUDEFILES} ${INCLUDEDIR} + +clean: + rm -rf ${OBJECTS} + diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/dmaps_v2_4/src/xdmaps.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/dmaps_v2_4/src/xdmaps.c new file mode 100644 index 0000000..b30a66f --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/dmaps_v2_4/src/xdmaps.c @@ -0,0 +1,1978 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xdmaps.c +* @addtogroup dmaps_v2_4 +* @{ +* +* This file contains the implementation of the interface functions for XDmaPs +* driver. Refer to the header file xdmaps.h for more detailed information. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  	Date     Changes
+* ----- ------ -------- ----------------------------------------------
+* 1.00	hbm    08/19/2010 First Release
+* 1.00  nm     05/25/2011 Updated for minor doxygen corrections
+* 1.02a sg     05/16/2012 Made changes for doxygen and moved some function
+*			  header from the xdmaps.h file to xdmaps.c file
+*			  Other cleanup for coding guidelines and CR 657109
+*			  and CR 657898
+* 1.03a sg     07/16/2012 changed inline to __inline for CR665681
+* 1.04a nm     10/22/2012 Fixed CR# 681671.
+* 1.05a nm     04/15/2013 Fixed CR# 704396. Removed warnings when compiled
+*			  with -Wall and -Wextra option in bsp.
+*	       05/01/2013 Fixed CR# 700189. Changed XDmaPs_BuildDmaProg()
+*			  function description.
+*			  Fixed CR# 704396. Removed unused variables
+*			  UseM2MByte & MemBurstLen from XDmaPs_BuildDmaProg()
+*			  function.
+* 1.07a asa    11/02/13. Made changes to fix compilation issues for iarcc.
+*			   Removed the PDBG prints. By default they were always
+*			   defined out and never used. The PDBG is non-standard for
+*			   Xilinx drivers and no other driver does something similar.
+*			   Since there is no easy way to fix compilation issues with
+*			   the IARCC compiler around PDBG, it is better to remove it.
+*			   Users can always use xil_printfs if they want to debug.
+* 2.01 kpc    08/23/14   Fixed the IAR compiler reported errors
+* 2.2  mus    12/08/16   Remove definition of INLINE macro to avoid re-definition,
+*                         since it is being defined in xil_io.h
+* 2.3 kpc     14/10/16   Fixed the compiler error when optimization O0 is used.
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ + +#include + +#include "xstatus.h" +#include "xdmaps.h" +#include "xil_io.h" +#include "xil_cache.h" + +#include "xil_printf.h" + + +/************************** Constant Definitions ****************************/ + +/* The following constant defines the amount of error that is allowed for + * a specified baud rate. This error is the difference between the actual + * baud rate that will be generated using the specified clock and the + * desired baud rate. + */ + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + + +/************************** Function Prototypes *****************************/ +static int XDmaPs_Exec_DMAKILL(u32 BaseAddr, + unsigned int Channel, + unsigned int Thread); + +static void XDmaPs_BufPool_Free(XDmaPs_ProgBuf *Pool, void *Buf); + +static int XDmaPs_Exec_DMAGO(u32 BaseAddr, unsigned int Channel, u32 DmaProg); + +static void XDmaPs_DoneISR_n(XDmaPs *InstPtr, unsigned Channel); +static void *XDmaPs_BufPool_Allocate(XDmaPs_ProgBuf *Pool); +static int XDmaPs_BuildDmaProg(unsigned Channel, XDmaPs_Cmd *Cmd, + unsigned CacheLength); + +static void XDmaPs_Print_DmaProgBuf(char *Buf, int Length); + + + +/************************** Variable Definitions ****************************/ + +/****************************************************************************/ +/** +* +* Initializes a specific XDmaPs instance such that it is ready to be used. +* The data format of the device is setup for 8 data bits, 1 stop bit, and no +* parity by default. The baud rate is set to a default value specified by +* Config->DefaultBaudRate if set, otherwise it is set to 19.2K baud. The +* receive FIFO threshold is set for 8 bytes. The default operating mode of the +* driver is polled mode. +* +* @param InstPtr is a pointer to the XDmaPs instance. +* @param Config is a reference to a structure containing information +* about a specific XDmaPs driver. +* @param EffectiveAddr is the device base address in the virtual memory +* address space. The caller is responsible for keeping the +* address mapping from EffectiveAddr to the device physical base +* address unchanged once this function is invoked. Unexpected +* errors may occur if the address mapping changes after this +* function is called. If address translation is not used, pass in +* the physical address instead. +* +* @return +* +* - XST_SUCCESS on initialization completion +* +* @note None. +* +*****************************************************************************/ +int XDmaPs_CfgInitialize(XDmaPs *InstPtr, + XDmaPs_Config *Config, + u32 EffectiveAddr) +{ + int Status = XST_SUCCESS; + unsigned int CacheLength = 0; + u32 CfgReg; + unsigned Channel; + XDmaPs_ChannelData *ChanData; + + /* + * Assert validates the input arguments + */ + Xil_AssertNonvoid(InstPtr != NULL); + Xil_AssertNonvoid(Config != NULL); + + /* + * Setup the driver instance using passed in parameters + */ + InstPtr->Config.DeviceId = Config->DeviceId; + InstPtr->Config.BaseAddress = EffectiveAddr; + + CfgReg = XDmaPs_ReadReg(EffectiveAddr, XDMAPS_CR1_OFFSET); + CacheLength = CfgReg & XDMAPS_CR1_I_CACHE_LEN_MASK; + if (CacheLength < 2 || CacheLength > 5) + CacheLength = 0; + else + CacheLength = 1 << CacheLength; + + InstPtr->CacheLength = CacheLength; + + memset(InstPtr->Chans, 0, + sizeof(XDmaPs_ChannelData[XDMAPS_CHANNELS_PER_DEV])); + + for (Channel = 0; Channel < XDMAPS_CHANNELS_PER_DEV; Channel++) { + ChanData = InstPtr->Chans + Channel; + ChanData->ChanId = Channel; + ChanData->DevId = Config->DeviceId; + } + + InstPtr->IsReady = 1; + + return Status; +} + +/****************************************************************************/ +/** +* +* Reset the DMA Manager. +* +* @param InstPtr is the DMA instance. +* +* @return 0 on success, -1 on time out +* +* @note None. +* +*****************************************************************************/ +int XDmaPs_ResetManager(XDmaPs *InstPtr) +{ + int Status; + Status = XDmaPs_Exec_DMAKILL(InstPtr->Config.BaseAddress, + 0, 0); + + return Status; +} + +/****************************************************************************/ +/** +* +* Reset the specified DMA Channel. +* +* @param InstPtr is the DMA instance. +* @param Channel is the channel to be reset. +* +* @return 0 on success, -1 on time out +* +* @note None. +* +*****************************************************************************/ +int XDmaPs_ResetChannel(XDmaPs *InstPtr, unsigned int Channel) +{ + int Status; + Status = XDmaPs_Exec_DMAKILL(InstPtr->Config.BaseAddress, + Channel, 1); + + return Status; + +} + +/*****************************************************************************/ +/** +* +* Driver fault interrupt service routine +* This is the one that connects the GIC +* +* @param InstPtr is the DMA instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XDmaPs_FaultISR(XDmaPs *InstPtr) +{ + + void *DmaProgBuf; + u32 Fsm; /* Fault status DMA manager register value */ + u32 Fsc; /* Fault status DMA channel register value */ + u32 FaultType; /* Fault type DMA manager register value */ + + u32 BaseAddr = InstPtr->Config.BaseAddress; + + u32 Pc; /* DMA Pc or channel Pc */ + XDmaPs_ChannelData *ChanData; + + unsigned Chan; + unsigned DevId; + + XDmaPs_Cmd *DmaCmd; + + Fsm = XDmaPs_ReadReg(BaseAddr, XDMAPS_FSM_OFFSET) & 0x01; + Fsc = XDmaPs_ReadReg(BaseAddr, XDMAPS_FSC_OFFSET) & 0xFF; + + + DevId = InstPtr->Config.DeviceId; + + if (Fsm) { + /* + * if DMA manager is fault + */ + FaultType = XDmaPs_ReadReg(BaseAddr, XDMAPS_FTM_OFFSET); + Pc = XDmaPs_ReadReg(BaseAddr, XDMAPS_DPC_OFFSET); + + xil_printf("PL330 device %d fault with type: %x at Pc %x\n", + DevId, + FaultType, Pc); + + /* kill the DMA manager thread */ + /* Should we disable interrupt?*/ + XDmaPs_Exec_DMAKILL(BaseAddr, 0, 0); + } + + /* + * check which channel faults and kill the channel thread + */ + for (Chan = 0; + Chan < XDMAPS_CHANNELS_PER_DEV; + Chan++) { + if (Fsc & (0x01 << Chan)) { + FaultType = + XDmaPs_ReadReg(BaseAddr, + XDmaPs_FTCn_OFFSET(Chan)); + Pc = XDmaPs_ReadReg(BaseAddr, + XDmaPs_CPCn_OFFSET(Chan)); + + /* kill the channel thread */ + /* Should we disable interrupt? */ + XDmaPs_Exec_DMAKILL(BaseAddr, Chan, 1); + + /* + * get the fault type and fault Pc and invoke the + * fault callback. + */ + ChanData = InstPtr->Chans + Chan; + + DmaCmd = ChanData->DmaCmdToHw; + + /* Should we check DmaCmd is not null */ + DmaCmd->DmaStatus = -1; + DmaCmd->ChanFaultType = FaultType; + DmaCmd->ChanFaultPCAddr = Pc; + ChanData->DmaCmdFromHw = DmaCmd; + ChanData->DmaCmdToHw = NULL; + + if (!ChanData->HoldDmaProg) { + DmaProgBuf = (void *)DmaCmd->GeneratedDmaProg; + if (DmaProgBuf) + XDmaPs_BufPool_Free(ChanData->ProgBufPool, + DmaProgBuf); + DmaCmd->GeneratedDmaProg = NULL; + } + + if (InstPtr->FaultHandler) + InstPtr->FaultHandler(Chan, + DmaCmd, + InstPtr->FaultRef); + + } + } + +} + +/*****************************************************************************/ +/** +* +* Set the done handler for a channel. +* +* @param InstPtr is the DMA instance. +* @param Channel is the channel number. +* @param DoneHandler is the done interrupt handler. +* @param CallbackRef is the callback reference data. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +int XDmaPs_SetDoneHandler(XDmaPs *InstPtr, + unsigned Channel, + XDmaPsDoneHandler DoneHandler, + void *CallbackRef) +{ + XDmaPs_ChannelData *ChanData; + + Xil_AssertNonvoid(InstPtr != NULL); + + if (Channel >= XDMAPS_CHANNELS_PER_DEV) + return XST_FAILURE; + + + ChanData = InstPtr->Chans + Channel; + + ChanData->DoneHandler = DoneHandler; + ChanData->DoneRef = CallbackRef; + + return 0; +} + +/*****************************************************************************/ +/** +* +* Set the fault handler for a channel. +* +* @param InstPtr is the DMA instance. +* @param FaultHandler is the fault interrupt handler. +* @param CallbackRef is the callback reference data. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +int XDmaPs_SetFaultHandler(XDmaPs *InstPtr, + XDmaPsFaultHandler FaultHandler, + void *CallbackRef) +{ + Xil_AssertNonvoid(InstPtr != NULL); + + InstPtr->FaultHandler = FaultHandler; + InstPtr->FaultRef = CallbackRef; + + return XST_SUCCESS; +} + + + +/****************************************************************************/ +/** +* Construction function for DMAEND instruction. This function fills the program +* buffer with the constructed instruction. +* +* @param DmaProg the DMA program buffer, it's the starting address for +* the instruction being constructed +* +* @return The number of bytes for this instruction which is 1. +* +* @note None. +* +*****************************************************************************/ +static INLINE int XDmaPs_Instr_DMAEND(char *DmaProg) +{ + /* + * DMAEND encoding: + * 7 6 5 4 3 2 1 0 + * 0 0 0 0 0 0 0 0 + */ + *DmaProg = 0x0; + + return 1; +} + +static INLINE void XDmaPs_Memcpy4(char *Dst, char *Src) +{ + *Dst = *Src; + *(Dst + 1) = *(Src + 1); + *(Dst + 2) = *(Src + 2); + *(Dst + 3) = *(Src + 3); +} + +/****************************************************************************/ +/** +* +* Construction function for DMAGO instruction. This function fills the program +* buffer with the constructed instruction. +* +* @param DmaProg is the DMA program buffer, it's the starting address +* for the instruction being constructed +* @param Cn is the Channel number, 0 - 7 +* @param Imm is 32-bit immediate number written to the Channel Program +* Counter. +* @param Ns is Non-secure flag. If Ns is 1, the DMA channel operates in +* the Non-secure state. If Ns is 0, the execution depends on the +* security state of the DMA manager: +* DMA manager is in the Secure state, DMA channel operates in the +* Secure state. +* DMA manager is in the Non-secure state, DMAC aborts. +* +* @return The number of bytes for this instruction which is 6. +* +* @note None +* +*****************************************************************************/ +static INLINE int XDmaPs_Instr_DMAGO(char *DmaProg, unsigned int Cn, + u32 Imm, unsigned int Ns) +{ + /* + * DMAGO encoding: + * 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 + * 0 0 0 0 0 |cn[2:0]| 1 0 1 0 0 0 ns 0 + * + * 47 ... 16 + * imm[32:0] + */ + *DmaProg = 0xA0 | ((Ns << 1) & 0x02); + + *(DmaProg + 1) = (u8)(Cn & 0x07); + + // *((u32 *)(DmaProg + 2)) = Imm; + XDmaPs_Memcpy4(DmaProg + 2, (char *)&Imm); + + /* success */ + return 6; +} + +/****************************************************************************/ +/** +* +* Construction function for DMALD instruction. This function fills the program +* buffer with the constructed instruction. +* +* @param DmaProg the DMA program buffer, it's the starting address for the +* instruction being constructed +* +* @return The number of bytes for this instruction which is 1. +* +* @note None. +* +*****************************************************************************/ +static INLINE int XDmaPs_Instr_DMALD(char *DmaProg) +{ + /* + * DMALD encoding + * 7 6 5 4 3 2 1 0 + * 0 0 0 0 0 1 bs x + * + * Note: this driver doesn't support conditional load or store, + * so the bs bit is 0 and x bit is 0. + */ + *DmaProg = 0x04; + return 1; +} + +/****************************************************************************/ +/** +* +* Construction function for DMALP instruction. This function fills the program +* buffer with the constructed instruction. +* +* @param DmaProg is the DMA program buffer, it's the starting address +* for the instruction being constructed +* @param Lc is the Loop counter register, can either be 0 or 1. +* @param LoopIterations: the number of interations, LoopInterations - 1 +* will be encoded in the DMALP instruction. +* +* @return The number of bytes for this instruction which is 2. +* +* @note None. +* +*****************************************************************************/ +static INLINE int XDmaPs_Instr_DMALP(char *DmaProg, unsigned Lc, + unsigned LoopIterations) +{ + /* + * DMALP encoding + * 15 ... 8 7 6 5 4 3 2 1 0 + * | iter[7:0] |0 0 1 0 0 0 lc 0 + */ + *DmaProg = (u8)(0x20 | ((Lc & 1) << 1)); + *(DmaProg + 1) = (u8)(LoopIterations - 1); + return 2; +} + +/****************************************************************************/ +/** +* +* Construction function for DMALPEND instruction. This function fills the +* program buffer with the constructed instruction. +* +* @param DmaProg is the DMA program buffer, it's the starting address +* for the instruction being constructed +* @param BodyStart is the starting address of the loop body. It is used +* to calculate the bytes of backward jump. +* @param Lc is the Loop counter register, can either be 0 or 1. +* +* @return The number of bytes for this instruction which is 2. +* +* @note None. +* +*****************************************************************************/ +static INLINE int XDmaPs_Instr_DMALPEND(char *DmaProg, char *BodyStart, unsigned Lc) +{ + /* + * DMALPEND encoding + * 15 ... 8 7 6 5 4 3 2 1 0 + * | backward_jump[7:0] |0 0 1 nf 1 lc bs x + * + * lc: loop counter + * nf is for loop forever. The driver does not support loop forever, + * so nf is 1. + * The driver does not support conditional LPEND, so bs is 0, x is 0. + */ + *DmaProg = 0x38 | ((Lc & 1) << 2); + *(DmaProg + 1) = (u8)(DmaProg - BodyStart); + + return 2; +} + +/* + * Register number for the DMAMOV instruction + */ +#define XDMAPS_MOV_SAR 0x0 +#define XDMAPS_MOV_CCR 0x1 +#define XDMAPS_MOV_DAR 0x2 + +/****************************************************************************/ +/** +* +* Construction function for DMAMOV instruction. This function fills the +* program buffer with the constructed instruction. +* +* @param DmaProg is the DMA program buffer, it's the starting address +* for the instruction being constructed +* @param Rd is the register id, 0 for SAR, 1 for CCR, and 2 for DAR +* @param Imm is the 32-bit immediate number +* +* @return The number of bytes for this instruction which is 6. +* +* @note None. +* +*****************************************************************************/ +static INLINE int XDmaPs_Instr_DMAMOV(char *DmaProg, unsigned Rd, u32 Imm) +{ + /* + * DMAMOV encoding + * 15 4 3 2 1 10 ... 8 7 6 5 4 3 2 1 0 + * 0 0 0 0 0 |rd[2:0]|1 0 1 1 1 1 0 0 + * + * 47 ... 16 + * imm[32:0] + * + * rd: b000 for SAR, b001 CCR, b010 DAR + */ + *DmaProg = 0xBC; + *(DmaProg + 1) = Rd & 0x7; + // *((u32 *)(DmaProg + 2)) = Imm; + XDmaPs_Memcpy4(DmaProg + 2, (char *)&Imm); + + return 6; +} + +/****************************************************************************/ +/** +* +* Construction function for DMANOP instruction. This function fills the +* program buffer with the constructed instruction. +* +* @param DmaProg is the DMA program buffer, it's the starting address +* for the instruction being constructed +* @return The number of bytes for this instruction which is 1. +* +* @note None. +* +*****************************************************************************/ +static INLINE int XDmaPs_Instr_DMANOP(char *DmaProg) +{ + /* + * DMANOP encoding + * 7 6 5 4 3 2 1 0 + * 0 0 0 1 1 0 0 0 + */ + *DmaProg = 0x18; + return 1; +} + +/****************************************************************************/ +/** +* +* Construction function for DMARMB instruction. This function fills the +* program buffer with the constructed instruction. +* +* @param DmaProg is the DMA program buffer, it's the starting address +* for the instruction being constructed +* +* @return The number of bytes for this instruction which is 1. +* +* @note None. +* +*****************************************************************************/ +int XDmaPs_Instr_DMARMB(char *DmaProg) +{ + /* + * DMARMB encoding + * 7 6 5 4 3 2 1 0 + * 0 0 0 1 0 0 1 0 + */ + *DmaProg = 0x12; + return 1; +} + +/****************************************************************************/ +/** +* +* Construction function for DMASEV instruction. This function fills the +* program buffer with the constructed instruction. +* +* @param DmaProg is the DMA program buffer, it's the starting address +* for the instruction being constructed +* @param EventNumber is the Event number to signal. +* +* @return The number of bytes for this instruction which is 2. +* +* @note None. +* +*****************************************************************************/ +static INLINE int XDmaPs_Instr_DMASEV(char *DmaProg, unsigned int EventNumber) +{ + /* + * DMASEV encoding + * 15 4 3 2 1 10 9 8 7 6 5 4 3 2 1 0 + * |event[4:0]| 0 0 0 0 0 1 1 0 1 0 0 + */ + *DmaProg = 0x34; + *(DmaProg + 1) = (u8)(EventNumber << 3); + + return 2; +} + + +/****************************************************************************/ +/** +* +* Construction function for DMAST instruction. This function fills the +* program buffer with the constructed instruction. +* +* @param DmaProg is the DMA program buffer, it's the starting address +* for the instruction being constructed +* +* @return The number of bytes for this instruction which is 1. +* +* @note None. +* +*****************************************************************************/ +static INLINE int XDmaPs_Instr_DMAST(char *DmaProg) +{ + /* + * DMAST encoding + * 7 6 5 4 3 2 1 0 + * 0 0 0 0 1 0 bs x + * + * Note: this driver doesn't support conditional load or store, + * so the bs bit is 0 and x bit is 0. + */ + *DmaProg = 0x08; + return 1; +} + + +/****************************************************************************/ +/** +* +* Construction function for DMAWMB instruction. This function fills the +* program buffer with the constructed instruction. +* +* @param DmaProg is the DMA program buffer, it's the starting address +* for the instruction being constructed +* +* @return The number of bytes for this instruction which is 1. +* +* @note None. +* +*****************************************************************************/ +int XDmaPs_Instr_DMAWMB(char *DmaProg) +{ + /* + * DMAWMB encoding + * 7 6 5 4 3 2 1 0 + * 0 0 0 1 0 0 1 0 + */ + *DmaProg = 0x13; + return 1; +} + +/****************************************************************************/ +/** +* +* Conversion function from the endian swap size to the bit encoding of the CCR +* +* @param EndianSwapSize is the endian swap size, in terms of bits, it +* could be 8, 16, 32, 64, or 128(We are using DMA assembly syntax) +* +* @return The endian swap size bit encoding for the CCR. +* +* @note None. +* +*****************************************************************************/ +static INLINE unsigned XDmaPs_ToEndianSwapSizeBits(unsigned int EndianSwapSize) +{ + switch (EndianSwapSize) { + case 0: + case 8: + return 0; + case 16: + return 1; + case 32: + return 2; + case 64: + return 3; + case 128: + return 4; + default: + return 0; + } + +} + +/****************************************************************************/ +/** +* +* Conversion function from the burst size to the bit encoding of the CCR +* +* @param BurstSize is the burst size. It's the data width. +* In terms of bytes, it could be 1, 2, 4, 8, 16, 32, 64, or 128. +* It must be no larger than the bus width. +* (We are using DMA assembly syntax.) +* +* @note None. +* +*****************************************************************************/ +static INLINE unsigned XDmaPs_ToBurstSizeBits(unsigned BurstSize) +{ + switch (BurstSize) { + case 1: + return 0; + case 2: + return 1; + case 4: + return 2; + case 8: + return 3; + case 16: + return 4; + case 32: + return 5; + case 64: + return 6; + case 128: + return 7; + default: + return 0; + } +} + + +/****************************************************************************/ +/** +* +* Conversion function from PL330 bus transfer descriptors to CCR value. All the +* values passed to the functions are in terms of assembly languages, not in +* terms of the register bit encoding. +* +* @param ChanCtrl is the Instance of XDmaPs_ChanCtrl. +* +* @return The 32-bit CCR value. +* +* @note None. +* +*****************************************************************************/ +u32 XDmaPs_ToCCRValue(XDmaPs_ChanCtrl *ChanCtrl) +{ + /* + * Channel Control Register encoding + * [31:28] - endian_swap_size + * [27:25] - dst_cache_ctrl + * [24:22] - dst_prot_ctrl + * [21:18] - dst_burst_len + * [17:15] - dst_burst_size + * [14] - dst_inc + * [13:11] - src_cache_ctrl + * [10:8] - src_prot_ctrl + * [7:4] - src_burst_len + * [3:1] - src_burst_size + * [0] - src_inc + */ + + unsigned es = + XDmaPs_ToEndianSwapSizeBits(ChanCtrl->EndianSwapSize); + + unsigned dst_burst_size = + XDmaPs_ToBurstSizeBits(ChanCtrl->DstBurstSize); + unsigned dst_burst_len = (ChanCtrl->DstBurstLen - 1) & 0x0F; + unsigned dst_cache_ctrl = (ChanCtrl->DstCacheCtrl & 0x03) + | ((ChanCtrl->DstCacheCtrl & 0x08) >> 1); + unsigned dst_prot_ctrl = ChanCtrl->DstProtCtrl & 0x07; + unsigned dst_inc_bit = ChanCtrl->DstInc & 1; + + unsigned src_burst_size = + XDmaPs_ToBurstSizeBits(ChanCtrl->SrcBurstSize); + unsigned src_burst_len = (ChanCtrl->SrcBurstLen - 1) & 0x0F; + unsigned src_cache_ctrl = (ChanCtrl->SrcCacheCtrl & 0x03) + | ((ChanCtrl->SrcCacheCtrl & 0x08) >> 1); + unsigned src_prot_ctrl = ChanCtrl->SrcProtCtrl & 0x07; + unsigned src_inc_bit = ChanCtrl->SrcInc & 1; + + u32 ccr_value = (es << 28) + | (dst_cache_ctrl << 25) + | (dst_prot_ctrl << 22) + | (dst_burst_len << 18) + | (dst_burst_size << 15) + | (dst_inc_bit << 14) + | (src_cache_ctrl << 11) + | (src_prot_ctrl << 8) + | (src_burst_len << 4) + | (src_burst_size << 1) + | (src_inc_bit); + + return ccr_value; +} + +/****************************************************************************/ +/** +* Construct a loop with only DMALD and DMAST as the body using loop counter 0. +* The function also makes sure the loop body and the lpend is in the same +* cache line. +* +* @param DmaProgStart is the very start address of the DMA program. +* This is used to calculate whether the loop is in a cache line. +* @param CacheLength is the icache line length, in terms of bytes. +* If it's zero, the performance enhancement feature will be +* turned off. +* @param DmaProgLoopStart The starting address of the loop (DMALP). +* @param LoopCount The inner loop count. Loop count - 1 will be used to +* initialize the loop counter. +* +* @return The number of bytes the loop has. +* +* @note None. +* +*****************************************************************************/ +int XDmaPs_ConstructSingleLoop(char *DmaProgStart, + int CacheLength, + char *DmaProgLoopStart, + int LoopCount) +{ + int CacheStartOffset; + int CacheEndOffset; + int NumNops; + char *DmaProgBuf = DmaProgLoopStart; + + DmaProgBuf += XDmaPs_Instr_DMALP(DmaProgBuf, 0, LoopCount); + + if (CacheLength > 0) { + /* + * the CacheLength > 0 switch is ued to turn on/off nop + * insertion + */ + CacheStartOffset = DmaProgBuf - DmaProgStart; + CacheEndOffset = CacheStartOffset + 3; + + /* + * check whether the body and lpend fit in one cache line + */ + if (CacheStartOffset / CacheLength + != CacheEndOffset / CacheLength) { + /* insert the nops */ + NumNops = CacheLength + - CacheStartOffset % CacheLength; + while (NumNops--) { + DmaProgBuf += + XDmaPs_Instr_DMANOP(DmaProgBuf); + } + } + } + + DmaProgBuf += XDmaPs_Instr_DMALD(DmaProgBuf); + DmaProgBuf += XDmaPs_Instr_DMAST(DmaProgBuf); + DmaProgBuf += XDmaPs_Instr_DMALPEND(DmaProgBuf, + DmaProgBuf - 2, 0); + + return DmaProgBuf - DmaProgLoopStart; +} + +/****************************************************************************/ +/** +* Construct a nested loop with only DMALD and DMAST in the inner loop body. +* It uses loop counter 1 for the outer loop and loop counter 0 for the +* inner loop. +* +* @param DmaProgStart is the very start address of the DMA program. +* This is used to calculate whether the loop is in a cache line. +* @param CacheLength is the icache line length, in terms of bytes. +* If it's zero, the performance enhancement feature will be +* turned off. +* @param DmaProgLoopStart The starting address of the loop (DMALP). +* @param LoopCountOuter The outer loop count. Loop count - 1 will be +* used to initialize the loop counter. +* @param LoopCountInner The inner loop count. Loop count - 1 will be +* used to initialize the loop counter. +* +* @return The number byes the nested loop program has. +* +* @note None. +* +*****************************************************************************/ +int XDmaPs_ConstructNestedLoop(char *DmaProgStart, + int CacheLength, + char *DmaProgLoopStart, + unsigned int LoopCountOuter, + unsigned int LoopCountInner) +{ + int CacheStartOffset; + int CacheEndOffset; + int NumNops; + char *InnerLoopStart; + char *DmaProgBuf = DmaProgLoopStart; + + DmaProgBuf += XDmaPs_Instr_DMALP(DmaProgBuf, 1, LoopCountOuter); + InnerLoopStart = DmaProgBuf; + + if (CacheLength > 0) { + /* + * the CacheLength > 0 switch is ued to turn on/off nop + * insertion + */ + if (CacheLength < 8) { + /* + * if the cache line is too small to fit both loops + * just align the inner loop + */ + DmaProgBuf += + XDmaPs_ConstructSingleLoop(DmaProgStart, + CacheLength, + DmaProgBuf, + LoopCountInner); + /* outer loop end */ + DmaProgBuf += + XDmaPs_Instr_DMALPEND(DmaProgBuf, + InnerLoopStart, + 1); + + /* + * the nested loop is constructed for + * smaller cache line + */ + return DmaProgBuf - DmaProgLoopStart; + } + + /* + * Now let's handle the case where a cache line can + * fit the nested loops. + */ + CacheStartOffset = DmaProgBuf - DmaProgStart; + CacheEndOffset = CacheStartOffset + 7; + + /* + * check whether the body and lpend fit in one cache line + */ + if (CacheStartOffset / CacheLength + != CacheEndOffset / CacheLength) { + /* insert the nops */ + NumNops = CacheLength + - CacheStartOffset % CacheLength; + while (NumNops--) { + DmaProgBuf += + XDmaPs_Instr_DMANOP(DmaProgBuf); + } + } + } + + /* insert the inner DMALP */ + DmaProgBuf += XDmaPs_Instr_DMALP(DmaProgBuf, 0, LoopCountInner); + + /* DMALD and DMAST instructions */ + DmaProgBuf += XDmaPs_Instr_DMALD(DmaProgBuf); + DmaProgBuf += XDmaPs_Instr_DMAST(DmaProgBuf); + + /* inner DMALPEND */ + DmaProgBuf += XDmaPs_Instr_DMALPEND(DmaProgBuf, + DmaProgBuf - 2, 0); + /* outer DMALPEND */ + DmaProgBuf += XDmaPs_Instr_DMALPEND(DmaProgBuf, + InnerLoopStart, 1); + + /* return the number of bytes */ + return DmaProgBuf - DmaProgLoopStart; +} + +/* + * [31:28] endian_swap_size b0000 + * [27:25] dst_cache_ctrl b000 + * [24:22] dst_prot_ctrl b000 + * [21:18] dst_burst_len b0000 + * [17:15] dst_burst_size b000 + * [14] dst_inc b0 + * [27:25] src_cache_ctrl b000 + * [24:22] src_prot_ctrl b000 + * [21:18] src_burst_len b0000 + * [17:15] src_burst_size b000 + * [14] src_inc b0 + */ +#define XDMAPS_CCR_SINGLE_BYTE (0x0) +#define XDMAPS_CCR_M2M_SINGLE_BYTE ((0x1 << 14) | 0x1) + + +/****************************************************************************/ +/** +* +* Construct the DMA program based on the descriptions of the DMA transfer. +* The function handles memory to memory DMA transfers. +* It also handles unalgined head and small amount of residue tail. +* +* @param Channel DMA channel number +* @param Cmd is the DMA command. +* @param CacheLength is the icache line length, in terms of bytes. +* If it's zero, the performance enhancement feature will be +* turned off. +* +* @returns The number of bytes for the program. +* +* @note None. +* +*****************************************************************************/ +static int XDmaPs_BuildDmaProg(unsigned Channel, XDmaPs_Cmd *Cmd, + unsigned CacheLength) +{ + /* + * unpack arguments + */ + char *DmaProgBuf = (char *)Cmd->GeneratedDmaProg; + unsigned DevChan = Channel; + unsigned long DmaLength = Cmd->BD.Length; + u32 SrcAddr = Cmd->BD.SrcAddr; + + unsigned SrcInc = Cmd->ChanCtrl.SrcInc; + u32 DstAddr = Cmd->BD.DstAddr; + unsigned DstInc = Cmd->ChanCtrl.DstInc; + + char *DmaProgStart = DmaProgBuf; + + unsigned int BurstBytes; + unsigned int LoopCount; + unsigned int LoopCount1 = 0; + unsigned int LoopResidue = 0; + unsigned int TailBytes; + unsigned int TailWords; + int DmaProgBytes; + u32 CCRValue; + unsigned int Unaligned; + unsigned int UnalignedCount; + unsigned int MemBurstSize = 1; + u32 MemAddr = 0; + unsigned int Index; + unsigned int SrcUnaligned = 0; + unsigned int DstUnaligned = 0; + + XDmaPs_ChanCtrl *ChanCtrl; + XDmaPs_ChanCtrl WordChanCtrl; + static XDmaPs_ChanCtrl Mem2MemByteCC; + + Mem2MemByteCC.EndianSwapSize = 0; + Mem2MemByteCC.DstCacheCtrl = 0; + Mem2MemByteCC.DstProtCtrl = 0; + Mem2MemByteCC.DstBurstLen = 1; + Mem2MemByteCC.DstBurstSize = 1; + Mem2MemByteCC.DstInc = 1; + Mem2MemByteCC.SrcCacheCtrl = 0; + Mem2MemByteCC.SrcProtCtrl = 0; + Mem2MemByteCC.SrcBurstLen = 1; + Mem2MemByteCC.SrcBurstSize = 1; + Mem2MemByteCC.SrcInc = 1; + + ChanCtrl = &Cmd->ChanCtrl; + + /* insert DMAMOV for SAR and DAR */ + DmaProgBuf += XDmaPs_Instr_DMAMOV(DmaProgBuf, + XDMAPS_MOV_SAR, + SrcAddr); + DmaProgBuf += XDmaPs_Instr_DMAMOV(DmaProgBuf, + XDMAPS_MOV_DAR, + DstAddr); + + + if (ChanCtrl->SrcInc) + SrcUnaligned = SrcAddr % ChanCtrl->SrcBurstSize; + + if (ChanCtrl->DstInc) + DstUnaligned = DstAddr % ChanCtrl->DstBurstSize; + + if ((SrcUnaligned && DstInc) || (DstUnaligned && SrcInc)) { + ChanCtrl = &Mem2MemByteCC; + } + + if (ChanCtrl->SrcInc) { + MemBurstSize = ChanCtrl->SrcBurstSize; + MemAddr = SrcAddr; + + } else if (ChanCtrl->DstInc) { + MemBurstSize = ChanCtrl->DstBurstSize; + MemAddr = DstAddr; + } + + /* check whether the head is aligned or not */ + Unaligned = MemAddr % MemBurstSize; + + if (Unaligned) { + /* if head is unaligned, transfer head in bytes */ + UnalignedCount = MemBurstSize - Unaligned; + CCRValue = XDMAPS_CCR_SINGLE_BYTE + | (SrcInc & 1) + | ((DstInc & 1) << 14); + + DmaProgBuf += XDmaPs_Instr_DMAMOV(DmaProgBuf, + XDMAPS_MOV_CCR, + CCRValue); + + for (Index = 0; Index < UnalignedCount; Index++) { + DmaProgBuf += XDmaPs_Instr_DMALD(DmaProgBuf); + DmaProgBuf += XDmaPs_Instr_DMAST(DmaProgBuf); + } + + DmaLength -= UnalignedCount; + } + + /* now the burst transfer part */ + CCRValue = XDmaPs_ToCCRValue(ChanCtrl); + DmaProgBuf += XDmaPs_Instr_DMAMOV(DmaProgBuf, + XDMAPS_MOV_CCR, + CCRValue); + + BurstBytes = ChanCtrl->SrcBurstSize * ChanCtrl->SrcBurstLen; + + LoopCount = DmaLength / BurstBytes; + TailBytes = DmaLength % BurstBytes; + + /* + * the loop count register is 8-bit wide, so if we need + * a larger loop, we need to have nested loops + */ + if (LoopCount > 256) { + LoopCount1 = LoopCount / 256; + if (LoopCount1 > 256) { + xil_printf("DMA operation cannot fit in a 2-level " + "loop for channel %d, please reduce the " + "DMA length or increase the burst size or " + "length", + Channel); + return 0; + } + LoopResidue = LoopCount % 256; + + if (LoopCount1 > 1) + DmaProgBuf += + XDmaPs_ConstructNestedLoop(DmaProgStart, + CacheLength, + DmaProgBuf, + LoopCount1, + 256); + else + DmaProgBuf += + XDmaPs_ConstructSingleLoop(DmaProgStart, + CacheLength, + DmaProgBuf, + 256); + + /* there will be some that cannot be covered by + * nested loops + */ + LoopCount = LoopResidue; + } + + if (LoopCount > 0) { + DmaProgBuf += XDmaPs_ConstructSingleLoop(DmaProgStart, + CacheLength, + DmaProgBuf, + LoopCount); + } + + if (TailBytes) { + /* handle the tail */ + TailWords = TailBytes / MemBurstSize; + TailBytes = TailBytes % MemBurstSize; + + if (TailWords) { + WordChanCtrl = *ChanCtrl; + /* + * if we can transfer the tail in words, we will + * transfer words as much as possible + */ + WordChanCtrl.SrcBurstSize = MemBurstSize; + WordChanCtrl.SrcBurstLen = 1; + WordChanCtrl.DstBurstSize = MemBurstSize; + WordChanCtrl.DstBurstLen = 1; + + + /* + * the burst length is 1 + */ + CCRValue = XDmaPs_ToCCRValue(&WordChanCtrl); + + DmaProgBuf += + XDmaPs_Instr_DMAMOV(DmaProgBuf, + XDMAPS_MOV_CCR, + CCRValue); + DmaProgBuf += + XDmaPs_ConstructSingleLoop(DmaProgStart, + CacheLength, + DmaProgBuf, + TailWords); + + } + + if (TailBytes) { + /* + * for the rest, we'll tranfer in bytes + */ + /* + * So far just to be safe, the tail bytes + * are transfered in a loop. We can optimize a little + * to perform a burst. + */ + CCRValue = XDMAPS_CCR_SINGLE_BYTE + | (SrcInc & 1) + | ((DstInc & 1) << 14); + + DmaProgBuf += + XDmaPs_Instr_DMAMOV(DmaProgBuf, + XDMAPS_MOV_CCR, + CCRValue); + + DmaProgBuf += + XDmaPs_ConstructSingleLoop(DmaProgStart, + CacheLength, + DmaProgBuf, + TailBytes); + + } + } + + DmaProgBuf += XDmaPs_Instr_DMASEV(DmaProgBuf, DevChan); + DmaProgBuf += XDmaPs_Instr_DMAEND(DmaProgBuf); + + DmaProgBytes = DmaProgBuf - DmaProgStart; + + Xil_DCacheFlushRange((u32)DmaProgStart, DmaProgBytes); + + return DmaProgBytes; + +} + + +/****************************************************************************/ +/** +* +* Generate a DMA program based for the DMA command, the buffer will be pointed +* by the GeneratedDmaProg field of the command. +* +* @param InstPtr is then DMA instance. +* @param Channel is the DMA channel number. +* @param Cmd is the DMA command. +* +* @return - XST_SUCCESS on success. +* - XST_FAILURE if it fails +* +* @note None. +* +*****************************************************************************/ +int XDmaPs_GenDmaProg(XDmaPs *InstPtr, unsigned int Channel, XDmaPs_Cmd *Cmd) +{ + void *Buf; + int ProgLen; + XDmaPs_ChannelData *ChanData; + XDmaPs_ChanCtrl *ChanCtrl; + + Xil_AssertNonvoid(InstPtr != NULL); + Xil_AssertNonvoid(Cmd != NULL); + + + if (Channel > XDMAPS_CHANNELS_PER_DEV) + return XST_FAILURE; + + ChanData = InstPtr->Chans + Channel; + ChanCtrl = &Cmd->ChanCtrl; + + if (ChanCtrl->SrcBurstSize * ChanCtrl->SrcBurstLen + != ChanCtrl->DstBurstSize * ChanCtrl->DstBurstLen) { + return XST_FAILURE; + } + + + /* + * unaligned fixed address is not supported + */ + if (!ChanCtrl->SrcInc && Cmd->BD.SrcAddr % ChanCtrl->SrcBurstSize) { + return XST_FAILURE; + } + + if (!ChanCtrl->DstInc && Cmd->BD.DstAddr % ChanCtrl->DstBurstSize) { + return XST_FAILURE; + } + + Buf = XDmaPs_BufPool_Allocate(ChanData->ProgBufPool); + if (Buf == NULL) { + return XST_FAILURE; + } + + Cmd->GeneratedDmaProg = Buf; + ProgLen = XDmaPs_BuildDmaProg(Channel, Cmd, + InstPtr->CacheLength); + Cmd->GeneratedDmaProgLength = ProgLen; + + +#ifdef XDMAPS_DEBUG + XDmaPs_Print_DmaProg(Cmd); +#endif + + if (ProgLen <= 0) { + /* something wrong, release the buffer */ + XDmaPs_BufPool_Free(ChanData->ProgBufPool, Buf); + Cmd->GeneratedDmaProgLength = 0; + Cmd->GeneratedDmaProg = NULL; + return XST_FAILURE; + } + + return XST_SUCCESS; +} + + +/****************************************************************************/ +/** + * Free the DMA program buffer that is pointed by the GeneratedDmaProg field + * of the command. + * + * @param InstPtr is then DMA instance. + * @param Channel is the DMA channel number. + * @param Cmd is the DMA command. + * + * @return XST_SUCCESS on success. + * XST_FAILURE if there is any error. + * + * @note None. + * + ****************************************************************************/ +int XDmaPs_FreeDmaProg(XDmaPs *InstPtr, unsigned int Channel, XDmaPs_Cmd *Cmd) +{ + + void *Buf; + XDmaPs_ChannelData *ChanData; + + Xil_AssertNonvoid(InstPtr != NULL); + Xil_AssertNonvoid(Cmd != NULL); + + if (Channel > XDMAPS_CHANNELS_PER_DEV) + return XST_FAILURE; + + Buf = (void *)Cmd->GeneratedDmaProg; + ChanData = InstPtr->Chans + Channel; + + if (Buf) { + XDmaPs_BufPool_Free(ChanData->ProgBufPool, Buf); + Cmd->GeneratedDmaProg = 0; + Cmd->GeneratedDmaProgLength = 0; + } + + return XST_SUCCESS; +} + + +/****************************************************************************/ +/** +* +* Start a DMA command. The command can only be invoked when the channel +* is idle. The driver takes the command, generates DMA program if needed, +* then pass the program to DMAC to execute. +* +* @param InstPtr is then DMA instance. +* @param Channel is the DMA channel number. +* @param Cmd is the DMA command. +* @param HoldDmaProg is tag indicating whether the driver can release +* the allocated DMA buffer or not. If a user wants to examine the +* generated DMA program, the flag should be set to 1. After the +* DMA program is finished, a user needs to explicity free the +* buffer. +* +* @return +* - XST_SUCCESS on success +* - XST_DEVICE_BUSY if DMA is busy +* - XST_FAILURE on other failures +* +* @note None. +* +****************************************************************************/ +int XDmaPs_Start(XDmaPs *InstPtr, unsigned int Channel, + XDmaPs_Cmd *Cmd, + int HoldDmaProg) +{ + int Status; + u32 DmaProg = 0; + u32 Inten; + + Xil_AssertNonvoid(InstPtr != NULL); + Xil_AssertNonvoid(Cmd != NULL); + + + Cmd->DmaStatus = XST_FAILURE; + + if (XDmaPs_IsActive(InstPtr, Channel)) + return XST_DEVICE_BUSY; + + if (!Cmd->UserDmaProg && !Cmd->GeneratedDmaProg) { + Status = XDmaPs_GenDmaProg(InstPtr, Channel, Cmd); + if (Status) + return XST_FAILURE; + } + + InstPtr->Chans[Channel].HoldDmaProg = HoldDmaProg; + + if (Cmd->UserDmaProg) + DmaProg = (u32)Cmd->UserDmaProg; + else if (Cmd->GeneratedDmaProg) + DmaProg = (u32)Cmd->GeneratedDmaProg; + + if (DmaProg) { + /* enable the interrupt */ + Inten = XDmaPs_ReadReg(InstPtr->Config.BaseAddress, + XDMAPS_INTEN_OFFSET); + Inten |= 0x01 << Channel; /* set the correpsonding bit */ + XDmaPs_WriteReg(InstPtr->Config.BaseAddress, + XDMAPS_INTEN_OFFSET, + Inten); + Inten = XDmaPs_ReadReg(InstPtr->Config.BaseAddress, + XDMAPS_INTEN_OFFSET); + + InstPtr->Chans[Channel].DmaCmdToHw = Cmd; + + if (Cmd->ChanCtrl.SrcInc) { + Xil_DCacheFlushRange(Cmd->BD.SrcAddr, Cmd->BD.Length); + } + if (Cmd->ChanCtrl.DstInc) { + Xil_DCacheInvalidateRange(Cmd->BD.DstAddr, + Cmd->BD.Length); + } + + Status = XDmaPs_Exec_DMAGO(InstPtr->Config.BaseAddress, + Channel, DmaProg); + } + else { + InstPtr->Chans[Channel].DmaCmdToHw = NULL; + Status = XST_FAILURE; + } + + return Status; +} + +/****************************************************************************/ +/** +* +* Checks whether the DMA channel is active or idle. +* +* @param InstPtr is the DMA instance. +* @param Channel is the DMA channel number. +* +* @return 0: if the channel is idle +* 1: otherwise +* +* @note None. +* +*****************************************************************************/ +int XDmaPs_IsActive(XDmaPs *InstPtr, unsigned int Channel) +{ + Xil_AssertNonvoid(InstPtr != NULL); + + /* Need to assert Channel is in range */ + if (Channel > XDMAPS_CHANNELS_PER_DEV) + return 0; + + return InstPtr->Chans[Channel].DmaCmdToHw != NULL; +} + + + +/****************************************************************************/ +/** +* +* Allocate a buffer of the DMA program buffer from the pool. +* +* @param Pool the DMA program pool. +* +* @return The allocated buffer, NULL if there is any error. +* +* @note None. +* +*****************************************************************************/ +static void *XDmaPs_BufPool_Allocate(XDmaPs_ProgBuf *Pool) +{ + int Index; + + Xil_AssertNonvoid(Pool != NULL); + + for (Index = 0; Index < XDMAPS_MAX_CHAN_BUFS; Index++) { + if (!Pool[Index].Allocated) { + Pool[Index].Allocated = 1; + return Pool[Index].Buf; + } + } + + return NULL; + +} + +/*****************************************************************************/ +/** +* +* Driver done interrupt service routine for channel 0. We need this done ISR +* mainly because the driver needs to release the DMA program buffer. +* This is the one that connects the GIC +* +* @param InstPtr is the DMA instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XDmaPs_DoneISR_0(XDmaPs *InstPtr) +{ + XDmaPs_DoneISR_n(InstPtr, 0); +} + +/*****************************************************************************/ +/** +* +* Driver done interrupt service routine for channel 1. We need this done ISR +* mainly because the driver needs to release the DMA program buffer. +* This is the one that connects the GIC +* +* @param InstPtr is the DMA instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XDmaPs_DoneISR_1(XDmaPs *InstPtr) +{ + XDmaPs_DoneISR_n(InstPtr, 1); +} + +/*****************************************************************************/ +/** +* +* Driver done interrupt service routine for channel 2. We need this done ISR +* mainly because the driver needs to release the DMA program buffer. +* This is the one that connects the GIC +* +* @param InstPtr is the DMA instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XDmaPs_DoneISR_2(XDmaPs *InstPtr) +{ + XDmaPs_DoneISR_n(InstPtr, 2); +} + +/*****************************************************************************/ +/** +* +* Driver done interrupt service routine for channel 3. We need this done ISR +* mainly because the driver needs to release the DMA program buffer. +* This is the one that connects the GIC +* +* @param InstPtr is the DMA instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XDmaPs_DoneISR_3(XDmaPs *InstPtr) +{ + XDmaPs_DoneISR_n(InstPtr, 3); +} + +/*****************************************************************************/ +/** +* +* Driver done interrupt service routine for channel 4. We need this done ISR +* mainly because the driver needs to release the DMA program buffer. +* This is the one that connects the GIC +* +* @param InstPtr is the DMA instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XDmaPs_DoneISR_4(XDmaPs *InstPtr) +{ + XDmaPs_DoneISR_n(InstPtr, 4); +} + +/*****************************************************************************/ +/** +* +* Driver done interrupt service routine for channel 5. We need this done ISR +* mainly because the driver needs to release the DMA program buffer. +* This is the one that connects the GIC +* +* @param InstPtr is the DMA instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XDmaPs_DoneISR_5(XDmaPs *InstPtr) +{ + XDmaPs_DoneISR_n(InstPtr, 5); +} + +/*****************************************************************************/ +/** +* +* Driver done interrupt service routine for channel 6. We need this done ISR +* mainly because the driver needs to release the DMA program buffer. +* This is the one that connects the GIC +* +* @param InstPtr is the DMA instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XDmaPs_DoneISR_6(XDmaPs *InstPtr) +{ + XDmaPs_DoneISR_n(InstPtr, 6); +} + +/*****************************************************************************/ +/** +* +* Driver done interrupt service routine for channel 7. We need this done ISR +* mainly because the driver needs to release the DMA program buffer. +* This is the one that connects the GIC +* +* @param InstPtr is the DMA instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XDmaPs_DoneISR_7(XDmaPs *InstPtr) +{ + XDmaPs_DoneISR_n(InstPtr, 7); +} + +#ifndef XDMAPS_MAX_WAIT +#define XDMAPS_MAX_WAIT 4000 +#endif + +/****************************************************************************/ +/** +* Use the debug registers to kill the DMA thread. +* +* @param BaseAddr is DMA device base address. +* @param Channel is the DMA channel number. +* @param Thread is Debug thread encoding. +* 0: DMA manager thread, 1: DMA channel. +* +* @return 0 on success, -1 on time out +* +* @note None. +* +*****************************************************************************/ +static int XDmaPs_Exec_DMAKILL(u32 BaseAddr, + unsigned int Channel, + unsigned int Thread) +{ + u32 DbgInst0; + int WaitCount; + + DbgInst0 = XDmaPs_DBGINST0(0, 0x01, Channel, Thread); + + /* wait while debug status is busy */ + WaitCount = 0; + while ((XDmaPs_ReadReg(BaseAddr, XDMAPS_DBGSTATUS_OFFSET) + & XDMAPS_DBGSTATUS_BUSY) + && (WaitCount < XDMAPS_MAX_WAIT)) + WaitCount++; + + if (WaitCount >= XDMAPS_MAX_WAIT) { + /* wait time out */ + xil_printf("PL330 device at %x debug status busy time out\n", + BaseAddr); + + return -1; + } + + /* write debug instruction 0 */ + XDmaPs_WriteReg(BaseAddr, XDMAPS_DBGINST0_OFFSET, DbgInst0); + + XDmaPs_WriteReg(BaseAddr, XDMAPS_DBGINST1_OFFSET, 0); + + + /* run the command in DbgInst0 and DbgInst1 */ + XDmaPs_WriteReg(BaseAddr, XDMAPS_DBGCMD_OFFSET, 0); + + return 0; +} + +/****************************************************************************/ +/** +* +* +* Free a buffer of the DMA program buffer. +* @param Pool the DMA program pool. +* @param Buf the DMA program buffer to be release. +* +* @return None +* +* @note None. +* +*****************************************************************************/ +static void XDmaPs_BufPool_Free(XDmaPs_ProgBuf *Pool, void *Buf) +{ + int Index; + Xil_AssertVoid(Pool != NULL); + + for (Index = 0; Index < XDMAPS_MAX_CHAN_BUFS; Index++) { + if (Pool[Index].Buf == Buf) { + if (Pool[Index].Allocated) { + Pool[Index].Allocated = 0; + } + } + } +} + +/*****************************************************************************/ +/** +* XDmaPs_Exec_DMAGO - Execute the DMAGO to start a channel. +* +* @param BaseAddr PL330 device base address +* @param Channel Channel number for the device +* @param DmaProg DMA program starting address, this should be DMA address +* +* @return 0 on success, -1 on time out +* +* @note None. +* +****************************************************************************/ +static int XDmaPs_Exec_DMAGO(u32 BaseAddr, unsigned int Channel, u32 DmaProg) +{ + char DmaGoProg[8]; + u32 DbgInst0; + u32 DbgInst1; + + int WaitCount; + + XDmaPs_Instr_DMAGO(DmaGoProg, Channel, DmaProg, 0); + + DbgInst0 = XDmaPs_DBGINST0(*(DmaGoProg + 1), *DmaGoProg, 0, 0); + DbgInst1 = (u32)DmaProg; + + /* wait while debug status is busy */ + WaitCount = 0; + while ((XDmaPs_ReadReg(BaseAddr, XDMAPS_DBGSTATUS_OFFSET) + & XDMAPS_DBGSTATUS_BUSY) + && (WaitCount < XDMAPS_MAX_WAIT)) { + + WaitCount++; + } + + if (WaitCount >= XDMAPS_MAX_WAIT) { + xil_printf("PL330 device at %x debug status busy time out\r\n", + BaseAddr); + return -1; + } + + /* write debug instruction 0 */ + XDmaPs_WriteReg(BaseAddr, XDMAPS_DBGINST0_OFFSET, DbgInst0); + /* write debug instruction 1 */ + XDmaPs_WriteReg(BaseAddr, XDMAPS_DBGINST1_OFFSET, DbgInst1); + + + /* wait while the DMA Manager is busy */ + WaitCount = 0; + while ((XDmaPs_ReadReg(BaseAddr, + XDMAPS_DS_OFFSET) & XDMAPS_DS_DMA_STATUS) + != XDMAPS_DS_DMA_STATUS_STOPPED + && WaitCount <= XDMAPS_MAX_WAIT) { + WaitCount++; + } + + if (WaitCount >= XDMAPS_MAX_WAIT) { + xil_printf("PL330 device at %x debug status busy time out\r\n", + BaseAddr); + return -1; + } + + /* run the command in DbgInst0 and DbgInst1 */ + XDmaPs_WriteReg(BaseAddr, XDMAPS_DBGCMD_OFFSET, 0); + + return 0; +} + + +/****************************************************************************/ +/** +* +* It's the generic Done ISR. +* @param InstPtr is the DMA instance. +* @param Channel is the DMA channel numer. +* +* @return None.* +* +* @note None. +* +*****************************************************************************/ +static void XDmaPs_DoneISR_n(XDmaPs *InstPtr, unsigned Channel) +{ + + void *DmaProgBuf; + XDmaPs_ChannelData *ChanData; + XDmaPs_Cmd *DmaCmd; + //u32 Value; + + ChanData = InstPtr->Chans + Channel; + + /*Value = XDmaPs_ReadReg(InstPtr->Config.BaseAddress, + XDMAPS_INTSTATUS_OFFSET);*/ + + /* clear the interrupt status */ + XDmaPs_WriteReg(InstPtr->Config.BaseAddress, + XDMAPS_INTCLR_OFFSET, + 1 << ChanData->ChanId); + + /*Value = XDmaPs_ReadReg(InstPtr->Config.BaseAddress, + XDMAPS_INTSTATUS_OFFSET);*/ + + + DmaCmd = ChanData->DmaCmdToHw; + if (DmaCmd) { + if (!ChanData->HoldDmaProg) { + DmaProgBuf = (void *)DmaCmd->GeneratedDmaProg; + if (DmaProgBuf) + XDmaPs_BufPool_Free(ChanData->ProgBufPool, + DmaProgBuf); + DmaCmd->GeneratedDmaProg = NULL; + } + + DmaCmd->DmaStatus = 0; + ChanData->DmaCmdToHw = NULL; + ChanData->DmaCmdFromHw = DmaCmd; + + if (ChanData->DoneHandler) + ChanData->DoneHandler(Channel, DmaCmd, + ChanData->DoneRef); + } + +} + + +/****************************************************************************/ +/** +* Prints the content of the buffer in bytes +* @param Buf is the buffer. +* @param Length is the length of the DMA program. +* +* @return None. +* +* @note None. +****************************************************************************/ +static void XDmaPs_Print_DmaProgBuf(char *Buf, int Length) +{ + int Index; + for (Index = 0; Index < Length; Index++) + xil_printf("[%x] %x\r\n", Index, Buf[Index]); + +} +/****************************************************************************/ +/** +* Print the Dma Prog Contents. +* +* @param Cmd is the command buffer. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ + void XDmaPs_Print_DmaProg(XDmaPs_Cmd *Cmd) +{ + if (Cmd->GeneratedDmaProg && Cmd->GeneratedDmaProgLength) { + xil_printf("Generated DMA program (%d):\r\n", + Cmd->GeneratedDmaProgLength); + XDmaPs_Print_DmaProgBuf((char *)Cmd->GeneratedDmaProg, + Cmd->GeneratedDmaProgLength); + } + + if (Cmd->UserDmaProg && Cmd->UserDmaProgLength) { + xil_printf("User defined DMA program (%d):\r\n", + Cmd->UserDmaProgLength); + XDmaPs_Print_DmaProgBuf((char *)Cmd->UserDmaProg, + Cmd->UserDmaProgLength); + } +} + + +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/dmaps_v2_4/src/xdmaps.h b/df_datalink/bsp/ps7_cortexa9_0/libsrc/dmaps_v2_4/src/xdmaps.h new file mode 100644 index 0000000..73e2b1e --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/dmaps_v2_4/src/xdmaps.h @@ -0,0 +1,349 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xdmaps.h +* @addtogroup dmaps_v2_4 +* @{ +* @details +* +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  	Date     Changes
+* ----- ------ -------- ----------------------------------------------
+* 1.00	hbm    08/19/10 First Release
+* 1.01a nm     12/20/12 Added definition XDMAPS_CHANNELS_PER_DEV which specifies
+*		        the maximum number of channels.
+*		        Replaced the usage of XPAR_XDMAPS_CHANNELS_PER_DEV
+*                       with XDMAPS_CHANNELS_PER_DEV defined in xdmaps_hw.h.
+*			Added the tcl file to automatically generate the
+*			xparameters.h
+* 1.02a sg     05/16/12 Made changes for doxygen and moved some function
+*			header from the xdmaps.h file to xdmaps.c file
+*			Other cleanup for coding guidelines and CR 657109
+*			and CR 657898
+*			The xdmaps_example_no_intr.c example is removed
+*			as it is using interrupts  and is similar to
+*			the interrupt example - CR 652477
+* 1.03a sg     07/16/2012 changed inline to __inline for CR665681
+* 1.04a nm     10/22/2012 Fixed CR# 681671.
+* 1.05a nm     04/15/2013 Fixed CR# 704396. Removed warnings when compiled
+*			  with -Wall and -Wextra option in bsp.
+*	       05/01/2013 Fixed CR# 700189. Changed XDmaPs_BuildDmaProg()
+*			  function description.
+*			  Fixed CR# 704396. Removed unused variables
+*			  UseM2MByte & MemBurstLen from XDmaPs_BuildDmaProg()
+*			  function.
+* 1.07a asa    11/02/13. Made changes to fix compilation issues for iarcc.
+*			   Removed the PDBG prints. By default they were always
+*			   defined out and never used. The PDBG is non-standard for
+*			   Xilinx drivers and no other driver does something similar.
+*			   Since there is no easy way to fix compilation issues with
+*			   the IARCC compiler around PDBG, it is better to remove it.
+*			   Users can always use xil_printfs if they want to debug.
+* 2.0   adk    10/12/13  Updated as per the New Tcl API's
+* 2.01  kpc    08/23/14  Fixed the IAR compiler reported errors
+* 2.2   mus    08/12/16  Declared all inline functions in xdmaps.c as extern, to avoid
+*                        linker error for IAR compiler
+* 2.3   ms     01/23/17 Modified xil_printf statement in main function for all
+*                       examples to ensure that "Successfully ran" and "Failed"
+*                       strings are available in all examples. This is a fix
+*                       for CR-965028.
+*       ms     03/17/17 Added readme.txt file in examples folder for doxygen
+*                       generation.
+* 2.4   adk    13/08/18 Fixed armcc compiler warnings in the driver CR-1008310.
+* 
+* +*****************************************************************************/ + +#ifndef XDMAPS_H /* prevent circular inclusions */ +#define XDMAPS_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files ********************************/ + +#include "xparameters.h" +#include "xil_types.h" +#include "xil_assert.h" +#include "xstatus.h" + +#include "xdmaps_hw.h" + +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + +/** + * This typedef contains configuration information for the device. + */ +typedef struct { + u16 DeviceId; /**< Unique ID of device */ + u32 BaseAddress; /**< Base address of device (IPIF) */ +} XDmaPs_Config; + + +/** DMA channle control structure. It's for AXI bus transaction. + * This struct will be translated into a 32-bit channel control register value. + */ +typedef struct { + unsigned int EndianSwapSize; /**< Endian swap size. */ + unsigned int DstCacheCtrl; /**< Destination cache control */ + unsigned int DstProtCtrl; /**< Destination protection control */ + unsigned int DstBurstLen; /**< Destination burst length */ + unsigned int DstBurstSize; /**< Destination burst size */ + unsigned int DstInc; /**< Destination incrementing or fixed + * address */ + unsigned int SrcCacheCtrl; /**< Source cache control */ + unsigned int SrcProtCtrl; /**< Source protection control */ + unsigned int SrcBurstLen; /**< Source burst length */ + unsigned int SrcBurstSize; /**< Source burst size */ + unsigned int SrcInc; /**< Source incrementing or fixed + * address */ +} XDmaPs_ChanCtrl; + +/** DMA block descriptor stucture. + */ +typedef struct { + u32 SrcAddr; /**< Source starting address */ + u32 DstAddr; /**< Destination starting address */ + unsigned int Length; /**< Number of bytes for the block */ +} XDmaPs_BD; + +/** + * A DMA command consisits of a channel control struct, a block descriptor, + * a user defined program, a pointer pointing to generated DMA program, and + * execution result. + * + */ +typedef struct { + XDmaPs_ChanCtrl ChanCtrl; /**< Channel Control Struct */ + XDmaPs_BD BD; /**< Together with SgLength field, + * it's a scatter-gather list. + */ + void *UserDmaProg; /**< If user wants the driver to + * execute their own DMA program, + * this field points to the DMA + * program. + */ + int UserDmaProgLength; /**< The length of user defined + * DMA program. + */ + + void *GeneratedDmaProg; /**< The DMA program genreated + * by the driver. This field will be + * set if a user invokes the DMA + * program generation function. Or + * the DMA command is finished and + * a user informs the driver not to + * release the program buffer. + * This field has two purposes, one + * is to ask the driver to generate + * a DMA program while the DMAC is + * performaning DMA transactions. The + * other purpose is to debug the + * driver. + */ + int GeneratedDmaProgLength; /**< The length of the DMA program + * generated by the driver + */ + int DmaStatus; /**< 0 on success, otherwise error code + */ + u32 ChanFaultType; /**< Channel fault type in case of fault + */ + u32 ChanFaultPCAddr; /**< Channel fault PC address + */ +} XDmaPs_Cmd; + +/** + * It's the done handler a user can set for a channel + */ +typedef void (*XDmaPsDoneHandler) (unsigned int Channel, + XDmaPs_Cmd *DmaCmd, + void *CallbackRef); + +/** + * It's the fault handler a user can set for a channel + */ +typedef void (*XDmaPsFaultHandler) (unsigned int Channel, + XDmaPs_Cmd *DmaCmd, + void *CallbackRef); + +#define XDMAPS_MAX_CHAN_BUFS 2 +#define XDMAPS_CHAN_BUF_LEN 128 + +/** + * The XDmaPs_ProgBuf is the struct for a DMA program buffer. + */ +typedef struct { + char Buf[XDMAPS_CHAN_BUF_LEN]; /**< The actual buffer the holds the + * content */ + unsigned Len; /**< The actual length of the DMA + * program in bytes. */ + int Allocated; /**< A tag indicating whether the + * buffer is allocated or not */ +} XDmaPs_ProgBuf; + +/** + * The XDmaPs_ChannelData is a struct to book keep individual channel of + * the DMAC. + */ +typedef struct { + unsigned DevId; /**< Device id indicating which DMAC */ + unsigned ChanId; /**< Channel number of the DMAC */ + XDmaPs_ProgBuf ProgBufPool[XDMAPS_MAX_CHAN_BUFS]; /**< A pool of + program buffers*/ + XDmaPsDoneHandler DoneHandler; /**< Done interrupt handler */ + void *DoneRef; /**< Done interrupt callback data */ + XDmaPs_Cmd *DmaCmdToHw; /**< DMA command being executed */ + XDmaPs_Cmd *DmaCmdFromHw; /**< DMA command that is finished. + * This field is for debugging purpose + */ + int HoldDmaProg; /**< A tag indicating whether to hold the + * DMA program after the DMA is done. + */ + +} XDmaPs_ChannelData; + +/** + * The XDmaPs driver instance data structure. A pointer to an instance data + * structure is passed around by functions to refer to a specific driver + * instance. + */ +typedef struct { + XDmaPs_Config Config; /**< Configuration data structure */ + int IsReady; /**< Device is Ready */ + int CacheLength; /**< icache length */ + XDmaPsFaultHandler FaultHandler; /**< fault interrupt handler */ + void *FaultRef; /**< fault call back data */ + XDmaPs_ChannelData Chans[XDMAPS_CHANNELS_PER_DEV]; + /**< + * channel data + */ +} XDmaPs; + +/* + * Functions implemented in xdmaps.c + */ +int XDmaPs_CfgInitialize(XDmaPs *InstPtr, + XDmaPs_Config *Config, + u32 EffectiveAddr); + +int XDmaPs_Start(XDmaPs *InstPtr, unsigned int Channel, + XDmaPs_Cmd *Cmd, + int HoldDmaProg); + +int XDmaPs_IsActive(XDmaPs *InstPtr, unsigned int Channel); +int XDmaPs_GenDmaProg(XDmaPs *InstPtr, unsigned int Channel, + XDmaPs_Cmd *Cmd); +int XDmaPs_FreeDmaProg(XDmaPs *InstPtr, unsigned int Channel, + XDmaPs_Cmd *Cmd); +void XDmaPs_Print_DmaProg(XDmaPs_Cmd *Cmd); + + +int XDmaPs_ResetManager(XDmaPs *InstPtr); +int XDmaPs_ResetChannel(XDmaPs *InstPtr, unsigned int Channel); + + +int XDmaPs_SetDoneHandler(XDmaPs *InstPtr, + unsigned Channel, + XDmaPsDoneHandler DoneHandler, + void *CallbackRef); + +int XDmaPs_SetFaultHandler(XDmaPs *InstPtr, + XDmaPsFaultHandler FaultHandler, + void *CallbackRef); + +void XDmaPs_Print_DmaProg(XDmaPs_Cmd *Cmd); +int XDmaPs_Instr_DMARMB(char *DmaProg); +int XDmaPs_Instr_DMAWMB(char *DmaProg); + +/** + * To avoid linking error,Declare all inline functions as extern for + * IAR compiler + */ +#ifdef __ICCARM__ +extern INLINE int XDmaPs_Instr_DMAEND(char *DmaProg); +extern INLINE void XDmaPs_Memcpy4(char *Dst, char *Src); +extern INLINE int XDmaPs_Instr_DMAGO(char *DmaProg, unsigned int Cn, + u32 Imm, unsigned int Ns); +extern INLINE int XDmaPs_Instr_DMALD(char *DmaProg); +extern INLINE int XDmaPs_Instr_DMALP(char *DmaProg, unsigned Lc, + unsigned LoopIterations); +extern INLINE int XDmaPs_Instr_DMALPEND(char *DmaProg, char *BodyStart, unsigned Lc); +extern INLINE int XDmaPs_Instr_DMAMOV(char *DmaProg, unsigned Rd, u32 Imm); +extern INLINE int XDmaPs_Instr_DMANOP(char *DmaProg); +extern INLINE int XDmaPs_Instr_DMASEV(char *DmaProg, unsigned int EventNumber); +extern INLINE int XDmaPs_Instr_DMAST(char *DmaProg); +extern INLINE unsigned XDmaPs_ToEndianSwapSizeBits(unsigned int EndianSwapSize); +extern INLINE unsigned XDmaPs_ToBurstSizeBits(unsigned BurstSize); +#endif + +/** + * Driver done interrupt service routines for the channels. + * We need this done ISR mainly because the driver needs to release the + * DMA program buffer. This is the one that connects the GIC + */ +void XDmaPs_DoneISR_0(XDmaPs *InstPtr); +void XDmaPs_DoneISR_1(XDmaPs *InstPtr); +void XDmaPs_DoneISR_2(XDmaPs *InstPtr); +void XDmaPs_DoneISR_3(XDmaPs *InstPtr); +void XDmaPs_DoneISR_4(XDmaPs *InstPtr); +void XDmaPs_DoneISR_5(XDmaPs *InstPtr); +void XDmaPs_DoneISR_6(XDmaPs *InstPtr); +void XDmaPs_DoneISR_7(XDmaPs *InstPtr); + +/** + * Driver fault interrupt service routine + */ +void XDmaPs_FaultISR(XDmaPs *InstPtr); + + +/* + * Static loopup function implemented in xdmaps_sinit.c + */ +XDmaPs_Config *XDmaPs_LookupConfig(u16 DeviceId); + + +/* + * self-test functions in xdmaps_selftest.c + */ +int XDmaPs_SelfTest(XDmaPs *InstPtr); + + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/dmaps_v2_4/src/xdmaps_g.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/dmaps_v2_4/src/xdmaps_g.c new file mode 100644 index 0000000..d9275e8 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/dmaps_v2_4/src/xdmaps_g.c @@ -0,0 +1,55 @@ + +/******************************************************************* +* +* CAUTION: This file is automatically generated by HSI. +* Version: 2019.1.3 +* DO NOT EDIT. +* +* Copyright (C) 2010-2023 Xilinx, Inc. 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 +*XILINX 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. +* +*Except as contained in this notice, the name of the Xilinx shall not be used +*in advertising or otherwise to promote the sale, use or other dealings in +*this Software without prior written authorization from Xilinx. +* + +* +* Description: Driver configuration +* +*******************************************************************/ + +#include "xparameters.h" +#include "xdmaps.h" + +/* +* The configuration table for devices +*/ + +XDmaPs_Config XDmaPs_ConfigTable[XPAR_XDMAPS_NUM_INSTANCES] = +{ + { + XPAR_PS7_DMA_NS_DEVICE_ID, + XPAR_PS7_DMA_NS_BASEADDR + }, + { + XPAR_PS7_DMA_S_DEVICE_ID, + XPAR_PS7_DMA_S_BASEADDR + } +}; + + diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/dmaps_v2_4/src/xdmaps_hw.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/dmaps_v2_4/src/xdmaps_hw.c new file mode 100644 index 0000000..5fbe4ca --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/dmaps_v2_4/src/xdmaps_hw.c @@ -0,0 +1,112 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xdmaps_hw.c +* @addtogroup dmaps_v2_4 +* @{ +* +* This file contains the implementation of the interface reset functionality +* for XDmaPs driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  	Date     Changes
+* ----- ------ -------- ----------------------------------------------
+* 1.06a kpc 10/07/13 First release
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ +#include "xdmaps_hw.h" + +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ +#ifndef XDMAPS_MAX_WAIT +#define XDMAPS_MAX_WAIT 4000 +#endif +/************************** Function Prototypes *****************************/ + +/************************** Variable Definitions ****************************/ + +/*****************************************************************************/ +/** +* This function perform the reset sequence to the given dmaps interface by +* configuring the appropriate control bits in the dmaps specifc registers +* the dmaps reset squence involves the following steps +* Disable all the interuupts +* Clear the pending interrupts +* Kill all the active channel threads +* Kill the manager thread +* +* @param BaseAddress of the interface +* +* @return N/A +* +* @note +* This function will not modify the slcr registers that are relavant for +* dmaps controller +******************************************************************************/ +void XDmaPs_ResetHw(u32 BaseAddress) +{ + u32 DbgInst; + u32 WaitCount = 0; + u32 ChanIndex; + + /* Disable all the interrupts */ + XDmaPs_WriteReg(BaseAddress, XDMAPS_INTEN_OFFSET, 0x00); + /* Clear the interrupts */ + XDmaPs_WriteReg(BaseAddress, XDMAPS_INTCLR_OFFSET, XDMAPS_INTCLR_ALL_MASK); + /* Kill the dma channel threads */ + for (ChanIndex=0; ChanIndex < XDMAPS_CHANNELS_PER_DEV; ChanIndex++) { + while ((XDmaPs_ReadReg(BaseAddress, XDMAPS_DBGSTATUS_OFFSET) + & XDMAPS_DBGSTATUS_BUSY) + && (WaitCount < XDMAPS_MAX_WAIT)) + WaitCount++; + + DbgInst = XDmaPs_DBGINST0(0, 0x01, ChanIndex, 1); + XDmaPs_WriteReg(BaseAddress, XDMAPS_DBGINST0_OFFSET, DbgInst); + XDmaPs_WriteReg(BaseAddress, XDMAPS_DBGINST1_OFFSET, 0x0); + XDmaPs_WriteReg(BaseAddress, XDMAPS_DBGCMD_OFFSET, 0x0); + } + /* Kill the manager thread */ + DbgInst = XDmaPs_DBGINST0(0, 0x01, 0, 0); + XDmaPs_WriteReg(BaseAddress, XDMAPS_DBGINST0_OFFSET, DbgInst); + XDmaPs_WriteReg(BaseAddress, XDMAPS_DBGINST1_OFFSET, 0x0); + XDmaPs_WriteReg(BaseAddress, XDMAPS_DBGCMD_OFFSET, 0x0); +} + + + +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/dmaps_v2_4/src/xdmaps_hw.h b/df_datalink/bsp/ps7_cortexa9_0/libsrc/dmaps_v2_4/src/xdmaps_hw.h new file mode 100644 index 0000000..42dfe69 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/dmaps_v2_4/src/xdmaps_hw.h @@ -0,0 +1,289 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xdmaps_hw.h +* @addtogroup dmaps_v2_4 +* @{ +* +* This header file contains the hardware interface of an XDmaPs device. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who   Date     Changes
+* ----- ----  -------- ----------------------------------------------
+* 1.00a	hbm   08/18/10 First Release
+* 1.01a nm    12/20/12 Added definition XDMAPS_CHANNELS_PER_DEV which specifies
+*		       the maximum number of channels.
+*		       Replaced the usage of XPAR_XDMAPS_CHANNELS_PER_DEV
+*                      with XDMAPS_CHANNELS_PER_DEV defined in xdmaps_hw.h
+* 1.02a sg    05/16/12 Made changes for doxygen
+* 1.06a kpc   07/10/13 Added function prototype
+* 
+* +******************************************************************************/ + +#ifndef XDMAPS_HW_H /* prevent circular inclusions */ +#define XDMAPS_HW_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_io.h" + +/************************** Constant Definitions *****************************/ + +/** @name Register Map + * + * Register offsets for the DMAC. + * @{ + */ + +#define XDMAPS_DS_OFFSET 0x000 /* DMA Status Register */ +#define XDMAPS_DPC_OFFSET 0x004 /* DMA Program Counter Rregister */ +#define XDMAPS_INTEN_OFFSET 0X020 /* DMA Interrupt Enable Register */ +#define XDMAPS_ES_OFFSET 0x024 /* DMA Event Status Register */ +#define XDMAPS_INTSTATUS_OFFSET 0x028 /* DMA Interrupt Status Register + */ +#define XDMAPS_INTCLR_OFFSET 0x02c /* DMA Interrupt Clear Register */ +#define XDMAPS_FSM_OFFSET 0x030 /* DMA Fault Status DMA Manager + * Register + */ +#define XDMAPS_FSC_OFFSET 0x034 /* DMA Fault Status DMA Chanel Register + */ +#define XDMAPS_FTM_OFFSET 0x038 /* DMA Fault Type DMA Manager Register */ + +#define XDMAPS_FTC0_OFFSET 0x040 /* DMA Fault Type for DMA Channel 0 */ +/* + * The offset for the rest of the FTC registers is calculated as + * FTC0 + dev_chan_num * 4 + */ +#define XDmaPs_FTCn_OFFSET(ch) (XDMAPS_FTC0_OFFSET + (ch) * 4) + +#define XDMAPS_CS0_OFFSET 0x100 /* Channel Status for DMA Channel 0 */ +/* + * The offset for the rest of the CS registers is calculated as + * CS0 + * dev_chan_num * 0x08 + */ +#define XDmaPs_CSn_OFFSET(ch) (XDMAPS_CS0_OFFSET + (ch) * 8) + +#define XDMAPS_CPC0_OFFSET 0x104 /* Channel Program Counter for DMA + * Channel 0 + */ +/* + * The offset for the rest of the CPC registers is calculated as + * CPC0 + dev_chan_num * 0x08 + */ +#define XDmaPs_CPCn_OFFSET(ch) (XDMAPS_CPC0_OFFSET + (ch) * 8) + +#define XDMAPS_SA_0_OFFSET 0x400 /* Source Address Register for DMA + * Channel 0 + */ +/* The offset for the rest of the SA registers is calculated as + * SA_0 + dev_chan_num * 0x20 + */ +#define XDmaPs_SA_n_OFFSET(ch) (XDMAPS_SA_0_OFFSET + (ch) * 0x20) + +#define XDMAPS_DA_0_OFFSET 0x404 /* Destination Address Register for + * DMA Channel 0 + */ +/* The offset for the rest of the DA registers is calculated as + * DA_0 + dev_chan_num * 0x20 + */ +#define XDmaPs_DA_n_OFFSET(ch) (XDMAPS_DA_0_OFFSET + (ch) * 0x20) + +#define XDMAPS_CC_0_OFFSET 0x408 /* Channel Control Register for + * DMA Channel 0 + */ +/* + * The offset for the rest of the CC registers is calculated as + * CC_0 + dev_chan_num * 0x20 + */ +#define XDmaPs_CC_n_OFFSET(ch) (XDMAPS_CC_0_OFFSET + (ch) * 0x20) + +#define XDMAPS_LC0_0_OFFSET 0x40C /* Loop Counter 0 for DMA Channel 0 */ +/* + * The offset for the rest of the LC0 registers is calculated as + * LC_0 + dev_chan_num * 0x20 + */ +#define XDmaPs_LC0_n_OFFSET(ch) (XDMAPS_LC0_0_OFFSET + (ch) * 0x20) +#define XDMAPS_LC1_0_OFFSET 0x410 /* Loop Counter 1 for DMA Channel 0 */ +/* + * The offset for the rest of the LC1 registers is calculated as + * LC_0 + dev_chan_num * 0x20 + */ +#define XDmaPs_LC1_n_OFFSET(ch) (XDMAPS_LC1_0_OFFSET + (ch) * 0x20) + +#define XDMAPS_DBGSTATUS_OFFSET 0xD00 /* Debug Status Register */ +#define XDMAPS_DBGCMD_OFFSET 0xD04 /* Debug Command Register */ +#define XDMAPS_DBGINST0_OFFSET 0xD08 /* Debug Instruction 0 Register */ +#define XDMAPS_DBGINST1_OFFSET 0xD0C /* Debug Instruction 1 Register */ + +#define XDMAPS_CR0_OFFSET 0xE00 /* Configuration Register 0 */ +#define XDMAPS_CR1_OFFSET 0xE04 /* Configuration Register 1 */ +#define XDMAPS_CR2_OFFSET 0xE08 /* Configuration Register 2 */ +#define XDMAPS_CR3_OFFSET 0xE0C /* Configuration Register 3 */ +#define XDMAPS_CR4_OFFSET 0xE10 /* Configuration Register 4 */ +#define XDMAPS_CRDN_OFFSET 0xE14 /* Configuration Register Dn */ + +#define XDMAPS_PERIPH_ID_0_OFFSET 0xFE0 /* Peripheral Identification + * Register 0 + */ +#define XDMAPS_PERIPH_ID_1_OFFSET 0xFE4 /* Peripheral Identification + * Register 1 + */ +#define XDMAPS_PERIPH_ID_2_OFFSET 0xFE8 /* Peripheral Identification + * Register 2 + */ +#define XDMAPS_PERIPH_ID_3_OFFSET 0xFEC /* Peripheral Identification + * Register 3 + */ +#define XDMAPS_PCELL_ID_0_OFFSET 0xFF0 /* PrimeCell Identification + * Register 0 + */ +#define XDMAPS_PCELL_ID_1_OFFSET 0xFF4 /* PrimeCell Identification + * Register 1 + */ +#define XDMAPS_PCELL_ID_2_OFFSET 0xFF8 /* PrimeCell Identification + * Register 2 + */ +#define XDMAPS_PCELL_ID_3_OFFSET 0xFFC /* PrimeCell Identification + * Register 3 + */ + +/* + * Some useful register masks + */ +#define XDMAPS_DS_DMA_STATUS 0x0F /* DMA status mask */ +#define XDMAPS_DS_DMA_STATUS_STOPPED 0x00 /* debug status busy mask */ + +#define XDMAPS_DBGSTATUS_BUSY 0x01 /* debug status busy mask */ + +#define XDMAPS_CS_ACTIVE_MASK 0x07 /* channel status active mask, + * llast 3 bits of CS register + */ + +#define XDMAPS_CR1_I_CACHE_LEN_MASK 0x07 /* i_cache_len mask */ + + +/* + * XDMAPS_DBGINST0 - constructs the word for the Debug Instruction-0 Register. + * @b1: Instruction byte 1 + * @b0: Instruction byte 0 + * @ch: Channel number + * @dbg_th: Debug thread encoding: 0 = DMA manager thread, 1 = DMA channel + */ +#define XDmaPs_DBGINST0(b1, b0, ch, dbg_th) \ + (((b1) << 24) | ((b0) << 16) | (((ch) & 0x7) << 8) | ((dbg_th & 0x1))) + +/* @} */ + +/** @name Control Register + * + * The Control register (CR) controls the major functions of the device. + * + * Control Register Bit Definition + */ + +/* @}*/ + + +#define XDMAPS_CHANNELS_PER_DEV 8 + + +/** @name Mode Register + * + * The mode register (MR) defines the mode of transfer as well as the data + * format. If this register is modified during transmission or reception, + * data validity cannot be guaranteed. + * + * Mode Register Bit Definition + * @{ + */ + +/* @} */ + + +/** @name Interrupt Registers + * + * Interrupt control logic uses the interrupt enable register (IER) and the + * interrupt disable register (IDR) to set the value of the bits in the + * interrupt mask register (IMR). The IMR determines whether to pass an + * interrupt to the interrupt status register (ISR). + * Writing a 1 to IER Enbables an interrupt, writing a 1 to IDR disables an + * interrupt. IMR and ISR are read only, and IER and IDR are write only. + * Reading either IER or IDR returns 0x00. + * + * All four registers have the same bit definitions. + * + * @{ + */ + +/* @} */ +#define XDMAPS_INTCLR_ALL_MASK 0xFF + +#define XDmaPs_ReadReg(BaseAddress, RegOffset) \ + Xil_In32((BaseAddress) + (RegOffset)) + +/***************************************************************************/ +/** +* Write a DMAC register. +* +* @param BaseAddress contains the base address of the device. +* @param RegOffset contains the offset from the base address of the device. +* @param RegisterValue is the value to be written to the register. +* +* @return None. +* +* @note +* C-Style signature: +* void XDmaPs_WriteReg(u32 BaseAddress, int RegOffset, +* u32 RegisterValue) +******************************************************************************/ +#define XDmaPs_WriteReg(BaseAddress, RegOffset, RegisterValue) \ + Xil_Out32((BaseAddress) + (RegOffset), (RegisterValue)) +/************************** Variable Definitions *****************************/ + +/************************** Function Prototypes *****************************/ +/* + * Perform reset operation to the dmaps interface + */ +void XDmaPs_ResetHw(u32 BaseAddr); +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/dmaps_v2_4/src/xdmaps_selftest.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/dmaps_v2_4/src/xdmaps_selftest.c new file mode 100644 index 0000000..37e70f8 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/dmaps_v2_4/src/xdmaps_selftest.c @@ -0,0 +1,106 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xdmaps_selftest.c +* @addtogroup dmaps_v2_4 +* @{ +* +* This file contains the self-test functions for the XDmaPs driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who     Date     Changes
+* ----- ------ -------- -----------------------------------------------
+* 1.00	hbm 	03/29/2010 First Release
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xstatus.h" +#include "xdmaps.h" + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Variable Definitions *****************************/ + + +/************************** Function Prototypes ******************************/ + + +/****************************************************************************/ +/** +* +* This function runs a self-test on the driver and hardware device. This self +* test performs a local loopback and verifies data can be sent and received. +* +* The time for this test is proportional to the baud rate that has been set +* prior to calling this function. +* +* The mode and control registers are restored before return. +* +* @param InstPtr is a pointer to the XDmaPs instance +* +* @return +* +* - XST_SUCCESS if the test was successful +* - XST_FAILURE if the test failed +* +* @note +* +* This function can hang if the hardware is not functioning properly. +* +******************************************************************************/ +int XDmaPs_SelfTest(XDmaPs *InstPtr) +{ + u32 BaseAddr = InstPtr->Config.BaseAddress; + int i; + + if (XDmaPs_ReadReg(BaseAddr, XDMAPS_DBGSTATUS_OFFSET) + & XDMAPS_DBGSTATUS_BUSY) + return XST_FAILURE; + + for (i = 0; i < XDMAPS_CHANNELS_PER_DEV; i++) { + if (XDmaPs_ReadReg(BaseAddr, + XDmaPs_CSn_OFFSET(i))) + return XST_FAILURE; + } + return XST_SUCCESS; +} +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/dmaps_v2_4/src/xdmaps_sinit.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/dmaps_v2_4/src/xdmaps_sinit.c new file mode 100644 index 0000000..e0b6fae --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/dmaps_v2_4/src/xdmaps_sinit.c @@ -0,0 +1,100 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xdmaps_sinit.c +* @addtogroup dmaps_v2_4 +* @{ +* +* The implementation of the XDmaPs driver's static initialzation +* functionality. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00  hbm  08/13/10 First Release
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ + +#include "xstatus.h" +#include "xparameters.h" +#include "xdmaps.h" + +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + + +/***************** Macros (Inline Functions) Definitions ********************/ + + +/************************** Variable Definitions ****************************/ +extern XDmaPs_Config XDmaPs_ConfigTable[]; + +/************************** Function Prototypes *****************************/ + +/****************************************************************************/ +/** +* +* Looks up the device configuration based on the unique device ID. The table +* contains the configuration info for each device in the system. +* +* @param DeviceId contains the ID of the device +* +* @return +* +* A pointer to the configuration structure or NULL if the specified device +* is not in the system. +* +* @note +* +* None. +* +******************************************************************************/ +XDmaPs_Config *XDmaPs_LookupConfig(u16 DeviceId) +{ + XDmaPs_Config *CfgPtr = NULL; + + int i; + + for (i = 0; i < XPAR_XDMAPS_NUM_INSTANCES; i++) { + if (XDmaPs_ConfigTable[i].DeviceId == DeviceId) { + CfgPtr = &XDmaPs_ConfigTable[i]; + break; + } + } + + return CfgPtr; +} +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/gpiops_v3_5/src/Makefile b/df_datalink/bsp/ps7_cortexa9_0/libsrc/gpiops_v3_5/src/Makefile new file mode 100644 index 0000000..8601ce4 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/gpiops_v3_5/src/Makefile @@ -0,0 +1,40 @@ +COMPILER= +ARCHIVER= +CP=cp +COMPILER_FLAGS= +EXTRA_COMPILER_FLAGS= +LIB=libxil.a + +CC_FLAGS = $(COMPILER_FLAGS) +ECC_FLAGS = $(EXTRA_COMPILER_FLAGS) + +RELEASEDIR=../../../lib +INCLUDEDIR=../../../include +INCLUDES=-I./. -I${INCLUDEDIR} + +OUTS = *.o + +LIBSOURCES:=*.c +INCLUDEFILES:=*.h + +OBJECTS = $(addsuffix .o, $(basename $(wildcard *.c))) + +libs: banner xgpiops_libs clean + +%.o: %.c + ${COMPILER} $(CC_FLAGS) $(ECC_FLAGS) $(INCLUDES) -o $@ $< + +banner: + echo "Compiling gpiops" + +xgpiops_libs: ${OBJECTS} + $(ARCHIVER) -r ${RELEASEDIR}/${LIB} ${OBJECTS} + +.PHONY: include +include: xgpiops_includes + +xgpiops_includes: + ${CP} ${INCLUDEFILES} ${INCLUDEDIR} + +clean: + rm -rf ${OBJECTS} diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/gpiops_v3_5/src/xgpiops.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/gpiops_v3_5/src/xgpiops.c new file mode 100644 index 0000000..39bcc94 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/gpiops_v3_5/src/xgpiops.c @@ -0,0 +1,830 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xgpiops.c +* @addtogroup gpiops_v3_5 +* @{ +* +* The XGpioPs driver. Functions in this file are the minimum required functions +* for this driver. See xgpiops.h for a detailed description of the driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a sv   01/15/10 First Release
+* 1.01a sv   04/15/12 Removed the APIs XGpioPs_SetMode, XGpioPs_SetModePin
+*                     XGpioPs_GetMode, XGpioPs_GetModePin as they are not
+*		      relevant to Zynq device. The interrupts are disabled
+*		      for output pins on all banks during initialization.
+* 2.1   hk   04/29/14 Use Input data register DATA_RO for read. CR# 771667.
+* 3.00  kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.1	kvn  04/13/15 Add support for Zynq Ultrascale+ MP. CR# 856980.
+* 3.1   aru  07/13/18 Resolved doxygen reported warnings. CR# 1006331.
+* 3.4   aru  08/17/18 Resolved MISRA-C mandatory violations. CR# 1007751
+* 3.5   sne  03/01/19 Fixes violations according to MISRAC-2012
+*                     in saftey mode and modified the code such as
+*                     Use of mixed mode arithmetic,Declared the poiner param
+*                     as Pointer to const,Casting operation to a pointer,
+*                     Literal value requires a U suffix.
+* 3.5   sne  03/13/19 Added Versal support.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xgpiops.h" + +/************************** Constant Definitions *****************************/ +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Variable Definitions *****************************/ + + +/************************** Function Prototypes ******************************/ + +extern void StubHandler(void *CallBackRef, u32 Bank, u32 Status); + +/*****************************************************************************/ +/* +* +* This function initializes a XGpioPs instance/driver. +* All members of the XGpioPs instance structure are initialized and +* StubHandlers are assigned to the Bank Status Handlers. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param ConfigPtr points to the XGpioPs device configuration structure. +* @param EffectiveAddr is the device base address in the virtual memory +* address space. If the address translation is not used then the +* physical address should be passed. +* Unexpected errors may occur if the address mapping is changed +* after this function is invoked. +* +* @return XST_SUCCESS always. +* +* @note None. +* +******************************************************************************/ +s32 XGpioPs_CfgInitialize(XGpioPs *InstancePtr, const XGpioPs_Config *ConfigPtr, + u32 EffectiveAddr) +{ + s32 Status = XST_SUCCESS; + u8 i; + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(ConfigPtr != NULL); + Xil_AssertNonvoid(EffectiveAddr != (u32)0); + /* + * Set some default values for instance data, don't indicate the device + * is ready to use until everything has been initialized successfully. + */ + InstancePtr->IsReady = 0U; + InstancePtr->GpioConfig.BaseAddr = EffectiveAddr; + InstancePtr->GpioConfig.DeviceId = ConfigPtr->DeviceId; + InstancePtr->Handler = (XGpioPs_Handler)StubHandler; + InstancePtr->Platform = XGetPlatform_Info(); + + /* Initialize the Bank data based on platform */ + if (InstancePtr->Platform == (u32)XPLAT_ZYNQ_ULTRA_MP) { + /* + * Max pins in the ZynqMP GPIO device + * 0 - 25, Bank 0 + * 26 - 51, Bank 1 + * 52 - 77, Bank 2 + * 78 - 109, Bank 3 + * 110 - 141, Bank 4 + * 142 - 173, Bank 5 + */ + InstancePtr->MaxPinNum = (u32)174; + InstancePtr->MaxBanks = (u8)6; + } + else if (InstancePtr->Platform == (u32)XPLAT_versal) + { + if(InstancePtr->PmcGpio == (u32)FALSE) + { + /* Max pins in the PS_GPIO devices + * 0 -25, Bank 0 + * 26-57, Bank 3 + */ + InstancePtr->MaxPinNum = (u32)58; + InstancePtr->MaxBanks = (u8)4; + } + else + { + /* Max pins in the PMC_GPIO devices + * 0 - 25,Bank 0 + * 26 - 51,Bank 1 + * 52 - 83,Bank 3 + * 84 - 115, Bank 4 + */ + InstancePtr->MaxPinNum = (u32)116; + InstancePtr->MaxBanks = (u8)5; + } + } + else { + /* + * Max pins in the GPIO device + * 0 - 31, Bank 0 + * 32 - 53, Bank 1 + * 54 - 85, Bank 2 + * 86 - 117, Bank 3 + */ + InstancePtr->MaxPinNum = (u32)118; + InstancePtr->MaxBanks = (u8)4; + } + + /* + * By default, interrupts are not masked in GPIO. Disable + * interrupts for all pins in all the 4 banks. + */ + for (i=(u8)0U;iMaxBanks;i++) { + if (InstancePtr->Platform == XPLAT_versal){ + if(InstancePtr->PmcGpio == (u32)FALSE) + { + if((i== (u8)XGPIOPS_ONE)||(i== (u8)XGPIOPS_TWO)) + { + continue; + } + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(i) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTDIS_OFFSET, 0xFFFFFFFFU); + } + else + { + if(i==(u32)XGPIOPS_TWO) + { + continue; + } + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(i) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTDIS_OFFSET, 0xFFFFFFFFU); + + } + } + else + { + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(i) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTDIS_OFFSET, 0xFFFFFFFFU); + } + } + + /* Indicate the component is now ready to use. */ + InstancePtr->IsReady = XIL_COMPONENT_IS_READY; + + return Status; +} + +/****************************************************************************/ +/** +* +* Read the Data register of the specified GPIO bank. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Bank is the bank number of the GPIO to operate on. +* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. +* +* @return Current value of the Data register. +* +* @note This function is used for reading the state of all the GPIO pins +* of specified bank. +* +*****************************************************************************/ +u32 XGpioPs_Read(const XGpioPs *InstancePtr, u8 Bank) +{ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(Bank < InstancePtr->MaxBanks); +#ifdef versal + if(InstancePtr->PmcGpio == TRUE) { + Xil_AssertNonvoid(Bank != XGPIOPS_TWO); + } else { + Xil_AssertNonvoid((Bank !=XGPIOPS_ONE) && (Bank !=XGPIOPS_TWO)); + } +#endif + + return XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_DATA_BANK_OFFSET) + + XGPIOPS_DATA_RO_OFFSET); +} + +/****************************************************************************/ +/** +* +* Read Data from the specified pin. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Pin is the pin number for which the data has to be read. +* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. +* See xgpiops.h for the mapping of the pin numbers in the banks. +* +* @return Current value of the Pin (0 or 1). +* +* @note This function is used for reading the state of the specified +* GPIO pin. +* +*****************************************************************************/ +u32 XGpioPs_ReadPin(const XGpioPs *InstancePtr, u32 Pin) +{ + u8 Bank; + u8 PinNumber; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(Pin < InstancePtr->MaxPinNum); + + /* Get the Bank number and Pin number within the bank. */ +#ifdef versal + XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); +#else + XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber); +#endif + return (XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_DATA_BANK_OFFSET) + + XGPIOPS_DATA_RO_OFFSET) >> (u32)PinNumber) & (u32)1; + +} + +/****************************************************************************/ +/** +* +* Write to the Data register of the specified GPIO bank. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Bank is the bank number of the GPIO to operate on. +* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. +* @param Data is the value to be written to the Data register. +* +* @return None. +* +* @note This function is used for writing to all the GPIO pins of +* the bank. The previous state of the pins is not maintained. +* +*****************************************************************************/ +void XGpioPs_Write(const XGpioPs *InstancePtr, u8 Bank, u32 Data) +{ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Bank < InstancePtr->MaxBanks); +#ifdef versal + if(InstancePtr->PmcGpio == TRUE) { + Xil_AssertVoid(Bank != XGPIOPS_TWO); + } else { + Xil_AssertVoid((Bank !=XGPIOPS_ONE) && (Bank !=XGPIOPS_TWO)); + } +#endif + + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_DATA_BANK_OFFSET) + + XGPIOPS_DATA_OFFSET, Data); +} + +/****************************************************************************/ +/** +* +* Write data to the specified pin. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Pin is the pin number to which the Data is to be written. +* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. +* @param Data is the data to be written to the specified pin (0 or 1). +* +* @return None. +* +* @note This function does a masked write to the specified pin of +* the specified GPIO bank. The previous state of other pins +* is maintained. +* +*****************************************************************************/ +void XGpioPs_WritePin(const XGpioPs *InstancePtr, u32 Pin, u32 Data) +{ + u32 RegOffset; + u32 Value; + u8 Bank; + u8 PinNumber; + u32 DataVar = Data; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Pin < InstancePtr->MaxPinNum); + + /* Get the Bank number and Pin number within the bank. */ +#ifdef versal + XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); +#else + XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber); +#endif + + if (PinNumber > 15U) { + /* There are only 16 data bits in bit maskable register. */ + PinNumber -= (u8)16; + RegOffset = XGPIOPS_DATA_MSW_OFFSET; + } else { + RegOffset = XGPIOPS_DATA_LSW_OFFSET; + } + + /* + * Get the 32 bit value to be written to the Mask/Data register where + * the upper 16 bits is the mask and lower 16 bits is the data. + */ + DataVar &= (u32)0x01; + Value = ~((u32)1 << (PinNumber + 16U)) & ((DataVar << PinNumber) | 0xFFFF0000U); + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_DATA_MASK_OFFSET) + + RegOffset, Value); + +} + + + +/****************************************************************************/ +/** +* +* Set the Direction of the pins of the specified GPIO Bank. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Bank is the bank number of the GPIO to operate on. +* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. +* @param Direction is the 32 bit mask of the Pin direction to be set for +* all the pins in the Bank. Bits with 0 are set to Input mode, +* bits with 1 are set to Output Mode. +* +* @return None. +* +* @note This function is used for setting the direction of all the pins +* in the specified bank. The previous state of the pins is +* not maintained. +* +*****************************************************************************/ +void XGpioPs_SetDirection(const XGpioPs *InstancePtr, u8 Bank, u32 Direction) +{ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Bank < InstancePtr->MaxBanks); +#ifdef versal + if(InstancePtr->PmcGpio == TRUE) { + Xil_AssertVoid(Bank != XGPIOPS_TWO); + } else { + Xil_AssertVoid((Bank !=XGPIOPS_ONE) && (Bank !=XGPIOPS_TWO)); + } +#endif + + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_DIRM_OFFSET, Direction); +} + +/****************************************************************************/ +/** +* +* Set the Direction of the specified pin. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Pin is the pin number to which the Data is to be written. +* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. +* @param Direction is the direction to be set for the specified pin. +* Valid values are 0 for Input Direction, 1 for Output Direction. +* +* @return None. +* +*****************************************************************************/ +void XGpioPs_SetDirectionPin(const XGpioPs *InstancePtr, u32 Pin, u32 Direction) +{ + u8 Bank; + u8 PinNumber; + u32 DirModeReg; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Pin < InstancePtr->MaxPinNum); + Xil_AssertVoid(Direction <= (u32)1); + + /* Get the Bank number and Pin number within the bank. */ +#ifdef versal + XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); +#else + XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber); +#endif + DirModeReg = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_DIRM_OFFSET); + + if (Direction!=(u32)0) { /* Output Direction */ + DirModeReg |= ((u32)1 << (u32)PinNumber); + } else { /* Input Direction */ + DirModeReg &= ~ ((u32)1 << (u32)PinNumber); + } + + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_DIRM_OFFSET, DirModeReg); +} + +/****************************************************************************/ +/** +* +* Get the Direction of the pins of the specified GPIO Bank. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Bank is the bank number of the GPIO to operate on. +* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. +* +* @return Returns a 32 bit mask of the Direction register. Bits with 0 are +* in Input mode, bits with 1 are in Output Mode. +* +* @note None. +* +*****************************************************************************/ +u32 XGpioPs_GetDirection(const XGpioPs *InstancePtr, u8 Bank) +{ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(Bank < InstancePtr->MaxBanks); +#ifdef versal + if(InstancePtr->PmcGpio == TRUE) { + Xil_AssertNonvoid(Bank != XGPIOPS_TWO); + } else { + Xil_AssertNonvoid((Bank !=XGPIOPS_ONE) && (Bank !=XGPIOPS_TWO)); + } +#endif + + return XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_DIRM_OFFSET); +} + +/****************************************************************************/ +/** +* +* Get the Direction of the specified pin. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Pin is the pin number for which the Direction is to be +* retrieved. +* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. +* +* @return Direction of the specified pin. +* - 0 for Input Direction +* - 1 for Output Direction +* +* @note None. +* +*****************************************************************************/ +u32 XGpioPs_GetDirectionPin(const XGpioPs *InstancePtr, u32 Pin) +{ + u8 Bank; + u8 PinNumber; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(Pin < InstancePtr->MaxPinNum); + + /* Get the Bank number and Pin number within the bank. */ +#ifdef versal + XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); +#else + XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber); +#endif + + return (XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_DIRM_OFFSET) >> (u32)PinNumber) & (u32)1; +} + +/****************************************************************************/ +/** +* +* Set the Output Enable of the pins of the specified GPIO Bank. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Bank is the bank number of the GPIO to operate on. +* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. +* @param OpEnable is the 32 bit mask of the Output Enables to be set for +* all the pins in the Bank. The Output Enable of bits with 0 are +* disabled, the Output Enable of bits with 1 are enabled. +* +* @return None. +* +* @note This function is used for setting the Output Enables of all the +* pins in the specified bank. The previous state of the Output +* Enables is not maintained. +* +*****************************************************************************/ +void XGpioPs_SetOutputEnable(const XGpioPs *InstancePtr, u8 Bank, u32 OpEnable) +{ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Bank < InstancePtr->MaxBanks); +#ifdef versal + if(InstancePtr->PmcGpio == TRUE) { + Xil_AssertVoid(Bank != XGPIOPS_TWO); + } else { + Xil_AssertVoid((Bank !=XGPIOPS_ONE) && (Bank !=XGPIOPS_TWO)); + } +#endif + + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_OUTEN_OFFSET, OpEnable); +} + +/****************************************************************************/ +/** +* +* Set the Output Enable of the specified pin. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Pin is the pin number to which the Data is to be written. +* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. +* @param OpEnable specifies whether the Output Enable for the specified +* pin should be enabled. +* Valid values are 0 for Disabling Output Enable, +* 1 for Enabling Output Enable. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XGpioPs_SetOutputEnablePin(const XGpioPs *InstancePtr, u32 Pin, u32 OpEnable) +{ + u8 Bank; + u8 PinNumber; + u32 OpEnableReg; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Pin < InstancePtr->MaxPinNum); + Xil_AssertVoid(OpEnable <= (u32)1); + + /* Get the Bank number and Pin number within the bank. */ +#ifdef versal + XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); +#else + XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber); +#endif + + OpEnableReg = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_OUTEN_OFFSET); + + if (OpEnable != (u32)0) { /* Enable Output Enable */ + OpEnableReg |= ((u32)1 << (u32)PinNumber); + } else { /* Disable Output Enable */ + OpEnableReg &= ~ ((u32)1 << (u32)PinNumber); + } + + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_OUTEN_OFFSET, OpEnableReg); +} +/****************************************************************************/ +/** +* +* Get the Output Enable status of the pins of the specified GPIO Bank. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Bank is the bank number of the GPIO to operate on. +* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. +* +* @return Returns a a 32 bit mask of the Output Enable register. +* Bits with 0 are in Disabled state, bits with 1 are in +* Enabled State. +* +* @note None. +* +*****************************************************************************/ +u32 XGpioPs_GetOutputEnable(const XGpioPs *InstancePtr, u8 Bank) +{ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(Bank < InstancePtr->MaxBanks); +#ifdef versal + if(InstancePtr->PmcGpio == TRUE) { + Xil_AssertNonvoid(Bank != XGPIOPS_TWO); + } else { + Xil_AssertNonvoid((Bank !=XGPIOPS_ONE) && (Bank !=XGPIOPS_TWO)); + } +#endif + + return XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_OUTEN_OFFSET); +} + +/****************************************************************************/ +/** +* +* Get the Output Enable status of the specified pin. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Pin is the pin number for which the Output Enable status is to +* be retrieved. +* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. +* +* @return Output Enable of the specified pin. +* - 0 if Output Enable is disabled for this pin +* - 1 if Output Enable is enabled for this pin +* +* @note None. +* +*****************************************************************************/ +u32 XGpioPs_GetOutputEnablePin(const XGpioPs *InstancePtr, u32 Pin) +{ + u8 Bank; + u8 PinNumber; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(Pin < InstancePtr->MaxPinNum); + + /* Get the Bank number and Pin number within the bank. */ +#ifdef versal + XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); +#else + XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber); +#endif + + return (XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_OUTEN_OFFSET) >> (u32)PinNumber) & (u32)1; +} + +/****************************************************************************/ +/* +* +* Get the Bank number and the Pin number in the Bank, for the given PinNumber +* in the GPIO device. +* +* @param PinNumber is the Pin number in the GPIO device. +* @param BankNumber returns the Bank in which this GPIO pin is present. +* Valid values are 0 to XGPIOPS_MAX_BANKS - 1. +* @param PinNumberInBank returns the Pin Number within the Bank. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +#ifdef versal +void XGpioPs_GetBankPin(const XGpioPs *InstancePtr,u8 PinNumber, u8 *BankNumber, u8 *PinNumberInBank) +#else +void XGpioPs_GetBankPin(u8 PinNumber, u8 *BankNumber, u8 *PinNumberInBank) +#endif +{ + u32 XGpioPsPinTable[6] = {0}; +#ifdef versal + u8 i=(u8)0; +#endif + u32 Platform = XGetPlatform_Info(); + + if (Platform == (u32)XPLAT_ZYNQ_ULTRA_MP) { + /* + * This structure defines the mapping of the pin numbers to the banks when + * the driver APIs are used for working on the individual pins. + */ + + XGpioPsPinTable[0] = (u32)25; /* 0 - 25, Bank 0 */ + XGpioPsPinTable[1] = (u32)51; /* 26 - 51, Bank 1 */ + XGpioPsPinTable[2] = (u32)77; /* 52 - 77, Bank 2 */ + XGpioPsPinTable[3] = (u32)109; /* 78 - 109, Bank 3 */ + XGpioPsPinTable[4] = (u32)141; /* 110 - 141, Bank 4 */ + XGpioPsPinTable[5] = (u32)173; /* 142 - 173 Bank 5 */ + + *BankNumber = 0U; + while (*BankNumber < XGPIOPS_SIX) { + if (PinNumber <= XGpioPsPinTable[*BankNumber]) { + break; + } + (*BankNumber)++; + } + } +#ifdef versal + else if(Platform == XPLAT_versal) + { + if(InstancePtr->PmcGpio == (u32)(FALSE)) + { + XGpioPsPinTable[0] = (u32)25; /* 0 - 25, Bank 0 */ + XGpioPsPinTable[1] = (u32)57; /* 26 - 57, Bank 3 */ + *BankNumber =0U; + if(PinNumber <= XGpioPsPinTable[*BankNumber]) + { + *BankNumber = (u8)XGPIOPS_ZERO; + } + else + { + *BankNumber = (u8)XGPIOPS_THREE; + } + + } + else + { + XGpioPsPinTable[0] = (u32)25; /* 0 - 25, Bank 0 */ + XGpioPsPinTable[1] = (u32)51; /* 26 - 51, Bank 1 */ + XGpioPsPinTable[2] = (u32)83; /* 52 - 83, Bank 3 */ + XGpioPsPinTable[3] = (u32)115; /*84 - 115, Bank 4 */ + + *BankNumber =0U; + while(i < XGPIOPS_FOUR) + { + if(i <= (u8)XGPIOPS_ONE) + { + if (PinNumber <= XGpioPsPinTable[i]) + { + *BankNumber = (u8)i; + break; + } + i++; + } + else + { + if (PinNumber <= XGpioPsPinTable[i]) + { + *BankNumber = (u8)i+1U; + break; + } + i++; + } + + } + } + + } +#endif + else { + XGpioPsPinTable[0] = (u32)31; /* 0 - 31, Bank 0 */ + XGpioPsPinTable[1] = (u32)53; /* 32 - 53, Bank 1 */ + XGpioPsPinTable[2] = (u32)85; /* 54 - 85, Bank 2 */ + XGpioPsPinTable[3] = (u32)117; /* 86 - 117 Bank 3 */ + + *BankNumber = 0U; + while (*BankNumber < XGPIOPS_FOUR) { + if (PinNumber <= XGpioPsPinTable[*BankNumber]) { + break; + } + (*BankNumber)++; + } + } + if (*BankNumber == (u8)0) { + *PinNumberInBank = PinNumber; + } + +#ifdef versal + else if(Platform == XPLAT_versal) + { + if(InstancePtr->PmcGpio == (u32)(FALSE)) + { + *PinNumberInBank = (u8)((u32)PinNumber - (XGpioPsPinTable[0] + (u32)1)); + } + else { + if((*BankNumber ==(u8)XGPIOPS_THREE) || (*BankNumber ==(u8)XGPIOPS_FOUR)) + { + *PinNumberInBank = (u8)((u32)PinNumber % + (XGpioPsPinTable[*BankNumber - (u8)XGPIOPS_TWO] + (u32)1)); + } + else + { + *PinNumberInBank = (u8)((u32)PinNumber % + (XGpioPsPinTable[*BankNumber - (u8)1] + (u32)1)); + } + } + + } +#endif + + else { + *PinNumberInBank = (u8)((u32)PinNumber % + (XGpioPsPinTable[*BankNumber - (u8)1] + (u32)1)); + } +} +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/gpiops_v3_5/src/xgpiops.h b/df_datalink/bsp/ps7_cortexa9_0/libsrc/gpiops_v3_5/src/xgpiops.h new file mode 100644 index 0000000..d0ff132 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/gpiops_v3_5/src/xgpiops.h @@ -0,0 +1,283 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xgpiops.h +* @addtogroup gpiops_v3_5 +* @{ +* @details +* +* The Xilinx PS GPIO driver. This driver supports the Xilinx PS GPIO +* Controller. +* +* The GPIO Controller supports the following features: +* - 4 banks +* - Masked writes (There are no masked reads) +* - Bypass mode +* - Configurable Interrupts (Level/Edge) +* +* This driver is intended to be RTOS and processor independent. Any needs for +* dynamic memory management, threads or thread mutual exclusion, virtual +* memory, or cache control must be satisfied by the layer above this driver. + +* This driver supports all the features listed above, if applicable. +* +* Driver Description +* +* The device driver enables higher layer software (e.g., an application) to +* communicate to the GPIO. +* +* Interrupts +* +* The driver provides interrupt management functions and an interrupt handler. +* Users of this driver need to provide callback functions. An interrupt handler +* example is available with the driver. +* +* Threads +* +* This driver is not thread safe. Any needs for threads or thread mutual +* exclusion must be satisfied by the layer above this driver. +* +* Asserts +* +* Asserts are used within all Xilinx drivers to enforce constraints on argument +* values. Asserts can be turned off on a system-wide basis by defining, at +* compile time, the NDEBUG identifier. By default, asserts are turned on and it +* is recommended that users leave asserts on during development. +* +* Building the driver +* +* The XGpioPs driver is composed of several source files. This allows the user +* to build and link only those parts of the driver that are necessary. +*

+* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a sv   01/15/10 First Release
+* 1.01a sv   04/15/12 Removed the APIs XGpioPs_SetMode, XGpioPs_SetModePin
+*                     XGpioPs_GetMode, XGpioPs_GetModePin as they are not
+*		      relevant to Zynq device.The interrupts are disabled
+*		      for output pins on all banks during initialization.
+* 1.02a hk   08/22/13 Added low level reset API
+* 2.1   hk   04/29/14 Use Input data register DATA_RO for read. CR# 771667.
+* 2.2	sk	 10/13/14 Used Pin number in Bank instead of pin number
+* 					  passed to APIs. CR# 822636
+* 3.00  kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.1	kvn  04/13/15 Add support for Zynq Ultrascale+ MP. CR# 856980.
+*       ms   03/17/17 Added readme.txt file in examples folder for doxygen
+*                     generation.
+*       ms   04/05/17 Added tabspace for return statements in functions of
+*                     gpiops examples for proper documentation while
+*                     generating doxygen.
+* 3.3   ms   04/17/17 Added notes about gpio input and output pin description
+*                     for zcu102 and zc702 boards in polled and interrupt
+*                     example, configured Interrupt pin to input pin for
+*                     proper functioning of interrupt example.
+* 3.4   aru  08/17/18 Resolved MISRA-C mandatory violations. CR# 1007751
+* 3.5   sne  03/01/19 Fixes violations according to MISRAC-2012
+*                     in saftey mode and modified the code such as
+*                     Use of mixed mode arithmetic,Declared the poiner param
+*                     as Pointer to const,Casting operation to a pointer,
+*                     Literal value requires a U suffix.
+* 3.5   sne  03/14/19 Added Versal support.
+* 
+* +******************************************************************************/ +#ifndef XGPIOPS_H /* prevent circular inclusions */ +#define XGPIOPS_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xstatus.h" +#include "xgpiops_hw.h" +#include "xplatform_info.h" + +/************************** Constant Definitions *****************************/ + +/** @name Interrupt types + * @{ + * The following constants define the interrupt types that can be set for each + * GPIO pin. + */ +#define XGPIOPS_IRQ_TYPE_EDGE_RISING 0x00U /**< Interrupt on Rising edge */ +#define XGPIOPS_IRQ_TYPE_EDGE_FALLING 0x01U /**< Interrupt Falling edge */ +#define XGPIOPS_IRQ_TYPE_EDGE_BOTH 0x02U /**< Interrupt on both edges */ +#define XGPIOPS_IRQ_TYPE_LEVEL_HIGH 0x03U /**< Interrupt on high level */ +#define XGPIOPS_IRQ_TYPE_LEVEL_LOW 0x04U /**< Interrupt on low level */ +/*@}*/ + +#define XGPIOPS_BANK_MAX_PINS (u32)32 /**< Max pins in a GPIO bank */ +#define XGPIOPS_BANK0 0x00U /**< GPIO Bank 0 */ +#define XGPIOPS_BANK1 0x01U /**< GPIO Bank 1 */ +#define XGPIOPS_BANK2 0x02U /**< GPIO Bank 2 */ +#define XGPIOPS_BANK3 0x03U /**< GPIO Bank 3 */ + +#ifdef XPAR_PSU_GPIO_0_BASEADDR +#define XGPIOPS_BANK4 0x04U /**< GPIO Bank 4 */ +#define XGPIOPS_BANK5 0x05U /**< GPIO Bank 5 */ +#endif + +#define XGPIOPS_MAX_BANKS_ZYNQMP 0x06U /**< Max banks in a + * Zynq Ultrascale+ MP GPIO device + */ +#define XGPIOPS_MAX_BANKS 0x04U /**< Max banks in a Zynq GPIO device */ + +#define XGPIOPS_DEVICE_MAX_PIN_NUM_ZYNQMP (u32)174 /**< Max pins in the + * Zynq Ultrascale+ MP GPIO device + * 0 - 25, Bank 0 + * 26 - 51, Bank 1 + * 52 - 77, Bank 2 + * 78 - 109, Bank 3 + * 110 - 141, Bank 4 + * 142 - 173, Bank 5 + */ +#define XGPIOPS_DEVICE_MAX_PIN_NUM (u32)118 /**< Max pins in the Zynq GPIO device + * 0 - 31, Bank 0 + * 32 - 53, Bank 1 + * 54 - 85, Bank 2 + * 86 - 117, Bank 3 + */ + +/**************************** Type Definitions *******************************/ + +/****************************************************************************/ +/** + * This handler data type allows the user to define a callback function to + * handle the interrupts for the GPIO device. The application using this + * driver is expected to define a handler of this type, to support interrupt + * driven mode. The handler executes in an interrupt context such that minimal + * processing should be performed. + * + * @param CallBackRef is a callback reference passed in by the upper layer + * when setting the callback functions for a GPIO bank. It is + * passed back to the upper layer when the callback is invoked. Its + * type is not important to the driver component, so it is a void + * pointer. + * @param Bank is the bank for which the interrupt status has changed. + * @param Status is the Interrupt status of the GPIO bank. + * + *****************************************************************************/ +typedef void (*XGpioPs_Handler) (void *CallBackRef, u32 Bank, u32 Status); + +/** + * This typedef contains configuration information for a device. + */ +typedef struct { + u16 DeviceId; /**< Unique ID of device */ + u32 BaseAddr; /**< Register base address */ +} XGpioPs_Config; + +/** + * The XGpioPs driver instance data. The user is required to allocate a + * variable of this type for the GPIO device in the system. A pointer + * to a variable of this type is then passed to the driver API functions. + */ +typedef struct { + XGpioPs_Config GpioConfig; /**< Device configuration */ + u32 IsReady; /**< Device is initialized and ready */ + XGpioPs_Handler Handler; /**< Status handlers for all banks */ + void *CallBackRef; /**< Callback ref for bank handlers */ + u32 Platform; /**< Platform data */ + u32 MaxPinNum; /**< Max pins in the GPIO device */ + u8 MaxBanks; /**< Max banks in a GPIO device */ + u32 PmcGpio; /**< Flag for accessing PS GPIO for versal*/ +} XGpioPs; + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/* Functions in xgpiops.c */ +s32 XGpioPs_CfgInitialize(XGpioPs *InstancePtr, const XGpioPs_Config *ConfigPtr, + u32 EffectiveAddr); + +/* Bank APIs in xgpiops.c */ +u32 XGpioPs_Read(const XGpioPs *InstancePtr, u8 Bank); +void XGpioPs_Write(const XGpioPs *InstancePtr, u8 Bank, u32 Data); +void XGpioPs_SetDirection(const XGpioPs *InstancePtr, u8 Bank, u32 Direction); +u32 XGpioPs_GetDirection(const XGpioPs *InstancePtr, u8 Bank); +void XGpioPs_SetOutputEnable(const XGpioPs *InstancePtr, u8 Bank, u32 OpEnable); +u32 XGpioPs_GetOutputEnable(const XGpioPs *InstancePtr, u8 Bank); +#ifdef versal +void XGpioPs_GetBankPin(const XGpioPs *InstancePtr,u8 PinNumber,u8 *BankNumber, u8 *PinNumberInBank); +#else +void XGpioPs_GetBankPin(u8 PinNumber,u8 *BankNumber, u8 *PinNumberInBank); +#endif + +/* Pin APIs in xgpiops.c */ +u32 XGpioPs_ReadPin(const XGpioPs *InstancePtr, u32 Pin); +void XGpioPs_WritePin(const XGpioPs *InstancePtr, u32 Pin, u32 Data); +void XGpioPs_SetDirectionPin(const XGpioPs *InstancePtr, u32 Pin, u32 Direction); +u32 XGpioPs_GetDirectionPin(const XGpioPs *InstancePtr, u32 Pin); +void XGpioPs_SetOutputEnablePin(const XGpioPs *InstancePtr, u32 Pin, u32 OpEnable); +u32 XGpioPs_GetOutputEnablePin(const XGpioPs *InstancePtr, u32 Pin); + +/* Diagnostic functions in xgpiops_selftest.c */ +s32 XGpioPs_SelfTest(const XGpioPs *InstancePtr); + +/* Functions in xgpiops_intr.c */ +/* Bank APIs in xgpiops_intr.c */ +void XGpioPs_IntrEnable(const XGpioPs *InstancePtr, u8 Bank, u32 Mask); +void XGpioPs_IntrDisable(const XGpioPs *InstancePtr, u8 Bank, u32 Mask); +u32 XGpioPs_IntrGetEnabled(const XGpioPs *InstancePtr, u8 Bank); +u32 XGpioPs_IntrGetStatus(const XGpioPs *InstancePtr, u8 Bank); +void XGpioPs_IntrClear(const XGpioPs *InstancePtr, u8 Bank, u32 Mask); +void XGpioPs_SetIntrType(const XGpioPs *InstancePtr, u8 Bank, u32 IntrType, + u32 IntrPolarity, u32 IntrOnAny); +void XGpioPs_GetIntrType(const XGpioPs *InstancePtr, u8 Bank, u32 *IntrType, + u32 *IntrPolarity, u32 *IntrOnAny); +void XGpioPs_SetCallbackHandler(XGpioPs *InstancePtr, void *CallBackRef, + XGpioPs_Handler FuncPointer); +void XGpioPs_IntrHandler(const XGpioPs *InstancePtr); + +/* Pin APIs in xgpiops_intr.c */ +void XGpioPs_SetIntrTypePin(const XGpioPs *InstancePtr, u32 Pin, u8 IrqType); +u8 XGpioPs_GetIntrTypePin(const XGpioPs *InstancePtr, u32 Pin); + +void XGpioPs_IntrEnablePin(const XGpioPs *InstancePtr, u32 Pin); +void XGpioPs_IntrDisablePin(const XGpioPs *InstancePtr, u32 Pin); +u32 XGpioPs_IntrGetEnabledPin(const XGpioPs *InstancePtr, u32 Pin); +u32 XGpioPs_IntrGetStatusPin(const XGpioPs *InstancePtr, u32 Pin); +void XGpioPs_IntrClearPin(const XGpioPs *InstancePtr, u32 Pin); + +/* Functions in xgpiops_sinit.c */ +XGpioPs_Config *XGpioPs_LookupConfig(u16 DeviceId); +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/gpiops_v3_5/src/xgpiops_g.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/gpiops_v3_5/src/xgpiops_g.c new file mode 100644 index 0000000..ee60dd2 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/gpiops_v3_5/src/xgpiops_g.c @@ -0,0 +1,51 @@ + +/******************************************************************* +* +* CAUTION: This file is automatically generated by HSI. +* Version: 2019.1.3 +* DO NOT EDIT. +* +* Copyright (C) 2010-2023 Xilinx, Inc. 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 +*XILINX 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. +* +*Except as contained in this notice, the name of the Xilinx shall not be used +*in advertising or otherwise to promote the sale, use or other dealings in +*this Software without prior written authorization from Xilinx. +* + +* +* Description: Driver configuration +* +*******************************************************************/ + +#include "xparameters.h" +#include "xgpiops.h" + +/* +* The configuration table for devices +*/ + +XGpioPs_Config XGpioPs_ConfigTable[XPAR_XGPIOPS_NUM_INSTANCES] = +{ + { + XPAR_PS7_GPIO_0_DEVICE_ID, + XPAR_PS7_GPIO_0_BASEADDR + } +}; + + diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/gpiops_v3_5/src/xgpiops_hw.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/gpiops_v3_5/src/xgpiops_hw.c new file mode 100644 index 0000000..4885c29 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/gpiops_v3_5/src/xgpiops_hw.c @@ -0,0 +1,262 @@ +/****************************************************************************** +* +* Copyright (C) 2013 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xgpiops_hw.c +* @addtogroup gpiops_v3_5 +* @{ +* +* This file contains low level GPIO functions. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.02a hk   08/22/13 First Release
+* 3.00  kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.1	kvn  04/13/15 Add support for Zynq Ultrascale+ MP. CR# 856980.
+* 3.5   sne  03/01/19 Fixes violations according to MISRAC-2012
+*                     in saftey mode and modified the code such as
+*                     Use of mixed mode arithmetic,Declared the poiner param
+*                     as Pointer to const,Casting operation to a pointer,
+*                     Literal value requires a U suffix.
+* 3.5   sne  03/14/19 Added versal support.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xgpiops_hw.h" +#include "xgpiops.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Variable Definitions *****************************/ + +/************************** Function Prototypes ******************************/ + + +/*****************************************************************************/ +/* +* +* This function resets the GPIO module by writing reset values to +* all registers +* +* @param Base address of GPIO module +* +* @return None +* +* @note None. +* +******************************************************************************/ +void XGpioPs_ResetHw(u32 BaseAddress) +{ + u32 BankCount; + u32 Platform,MaxBanks; + + Platform = XGetPlatform_Info(); + if (Platform == (u32)XPLAT_ZYNQ_ULTRA_MP) { + MaxBanks = (u32)6; + } + else if(Platform == (u32)XPLAT_versal) + { + if (BaseAddress == (u32)XGPIOPS_PS_GPIO_BASEADDR) + { + MaxBanks = (u32)4; + } + else + { + MaxBanks = (u32)5; + } + } + else { + MaxBanks = (u32)4; + } + + if (Platform == (u32)XPLAT_versal) + { + /* Write reset values to all mask data registers */ + for(BankCount = 3U; BankCount < (u32)MaxBanks; BankCount++) { + + XGpioPs_WriteReg(BaseAddress, + ((BankCount * XGPIOPS_DATA_MASK_OFFSET) + + XGPIOPS_DATA_LSW_OFFSET), 0x0U); + XGpioPs_WriteReg(BaseAddress, + ((BankCount * XGPIOPS_DATA_MASK_OFFSET) + + XGPIOPS_DATA_MSW_OFFSET), 0x0U); + } + /* Write reset values to all output data registers */ + for(BankCount = 3U; BankCount < (u32)MaxBanks; BankCount++) { + + XGpioPs_WriteReg(BaseAddress, + ((BankCount * XGPIOPS_DATA_BANK_OFFSET) + + XGPIOPS_DATA_OFFSET), 0x0U); + } + + /* Reset all registers of all GPIO banks */ + for(BankCount = 0U; BankCount < (u32)MaxBanks; BankCount++) { + + + if((BaseAddress == (u32)XGPIOPS_PS_GPIO_BASEADDR) && ((BankCount == (u32)XGPIOPS_ONE) ||(BankCount == (u32)XGPIOPS_TWO))) + { + continue; + } + else + { + if((BaseAddress != (u32)XGPIOPS_PS_GPIO_BASEADDR) && (BankCount == (u32)XGPIOPS_ONE)) + { + continue; + } + } + XGpioPs_WriteReg(BaseAddress, + ((BankCount * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_DIRM_OFFSET), 0x0U); + XGpioPs_WriteReg(BaseAddress, + ((BankCount * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_OUTEN_OFFSET), 0x0U); + XGpioPs_WriteReg(BaseAddress, + ((BankCount * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTMASK_OFFSET), 0x0U); + XGpioPs_WriteReg(BaseAddress, + ((BankCount * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTEN_OFFSET), 0x0U); + XGpioPs_WriteReg(BaseAddress, + ((BankCount * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTDIS_OFFSET), 0x0U); + XGpioPs_WriteReg(BaseAddress, + ((BankCount * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTSTS_OFFSET), 0x0U); + XGpioPs_WriteReg(BaseAddress, + ((BankCount * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTPOL_OFFSET), 0x0U); + XGpioPs_WriteReg(BaseAddress, + ((BankCount * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTANY_OFFSET), 0x0U); + + } + + /* Bank 0 Int type */ + XGpioPs_WriteReg(BaseAddress, XGPIOPS_INTTYPE_OFFSET, + XGPIOPS_INTTYPE_BANK0_RESET); + /* Bank 1 Int type */ + XGpioPs_WriteReg(BaseAddress, + ((u32)XGPIOPS_REG_MASK_OFFSET + (u32)XGPIOPS_INTTYPE_OFFSET), + XGPIOPS_INTTYPE_BANK1_RESET); + /* Bank 3 Int type */ + XGpioPs_WriteReg(BaseAddress, + (((u32)3 * XGPIOPS_REG_MASK_OFFSET) + XGPIOPS_INTTYPE_OFFSET), + XGPIOPS_INTTYPE_BANK3_RESET); + /* Bank 4 Int type */ + XGpioPs_WriteReg(BaseAddress, + (((u32)4 * XGPIOPS_REG_MASK_OFFSET) + XGPIOPS_INTTYPE_OFFSET), + XGPIOPS_INTTYPE_BANK4_RESET); + } + else + { + /* Write reset values to all mask data registers */ + for(BankCount = 2U; BankCount < (u32)MaxBanks; BankCount++) { + + XGpioPs_WriteReg(BaseAddress, + ((BankCount * XGPIOPS_DATA_MASK_OFFSET) + + XGPIOPS_DATA_LSW_OFFSET), 0x0U); + XGpioPs_WriteReg(BaseAddress, + ((BankCount * XGPIOPS_DATA_MASK_OFFSET) + + XGPIOPS_DATA_MSW_OFFSET), 0x0U); + } + /* Write reset values to all output data registers */ + for(BankCount = 2U; BankCount < (u32)MaxBanks; BankCount++) { + + XGpioPs_WriteReg(BaseAddress, + ((BankCount * XGPIOPS_DATA_BANK_OFFSET) + + XGPIOPS_DATA_OFFSET), 0x0U); + } + /* Reset all registers of all GPIO banks */ + for(BankCount = 0U; BankCount < (u32)MaxBanks; BankCount++) { + + XGpioPs_WriteReg(BaseAddress, + ((BankCount * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_DIRM_OFFSET), 0x0U); + XGpioPs_WriteReg(BaseAddress, + ((BankCount * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_OUTEN_OFFSET), 0x0U); + XGpioPs_WriteReg(BaseAddress, + ((BankCount * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTMASK_OFFSET), 0x0U); + XGpioPs_WriteReg(BaseAddress, + ((BankCount * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTEN_OFFSET), 0x0U); + XGpioPs_WriteReg(BaseAddress, + ((BankCount * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTDIS_OFFSET), 0x0U); + XGpioPs_WriteReg(BaseAddress, + ((BankCount * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTSTS_OFFSET), 0x0U); + XGpioPs_WriteReg(BaseAddress, + ((BankCount * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTPOL_OFFSET), 0x0U); + XGpioPs_WriteReg(BaseAddress, + ((BankCount * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTANY_OFFSET), 0x0U); + } + /* Bank 0 Int type */ + XGpioPs_WriteReg(BaseAddress, XGPIOPS_INTTYPE_OFFSET, + XGPIOPS_INTTYPE_BANK0_RESET); + /* Bank 1 Int type */ + XGpioPs_WriteReg(BaseAddress, + ((u32)XGPIOPS_REG_MASK_OFFSET + (u32)XGPIOPS_INTTYPE_OFFSET), + XGPIOPS_INTTYPE_BANK1_RESET); + /* Bank 2 Int type */ + XGpioPs_WriteReg(BaseAddress, + (((u32)2 * XGPIOPS_REG_MASK_OFFSET) + XGPIOPS_INTTYPE_OFFSET), + XGPIOPS_INTTYPE_BANK2_RESET); + /* Bank 3 Int type */ + XGpioPs_WriteReg(BaseAddress, + (((u32)3 * XGPIOPS_REG_MASK_OFFSET) + XGPIOPS_INTTYPE_OFFSET), + XGPIOPS_INTTYPE_BANK3_RESET); + + if (Platform == (u32)XPLAT_ZYNQ_ULTRA_MP) { + /* Bank 4 Int type */ + XGpioPs_WriteReg(BaseAddress, + (((u32)4 * XGPIOPS_REG_MASK_OFFSET) + XGPIOPS_INTTYPE_OFFSET), + XGPIOPS_INTTYPE_BANK4_RESET); + /* Bank 5 Int type */ + XGpioPs_WriteReg(BaseAddress, + (((u32)5 * XGPIOPS_REG_MASK_OFFSET) + XGPIOPS_INTTYPE_OFFSET), + XGPIOPS_INTTYPE_BANK5_RESET); + } + } + +} +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/gpiops_v3_5/src/xgpiops_hw.h b/df_datalink/bsp/ps7_cortexa9_0/libsrc/gpiops_v3_5/src/xgpiops_hw.h new file mode 100644 index 0000000..599c7db --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/gpiops_v3_5/src/xgpiops_hw.h @@ -0,0 +1,168 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xgpiops_hw.h +* @addtogroup gpiops_v3_5 +* @{ +* +* This header file contains the identifiers and basic driver functions (or +* macros) that can be used to access the device. Other driver functions +* are defined in xgpiops.h. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------
+* 1.00a sv   01/15/10 First Release
+* 1.02a hk   08/22/13 Added low level reset API function prototype and
+*                     related constant definitions
+* 3.00  kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.1	kvn  04/13/15 Corrected reset values of banks.
+* 3.5   sne  03/14/19 Added versal support.
+* 
+* +******************************************************************************/ +#ifndef XGPIOPS_HW_H /* prevent circular inclusions */ +#define XGPIOPS_HW_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_io.h" + +/************************** Constant Definitions *****************************/ + +/** @name Register offsets for the GPIO. Each register is 32 bits. + * @{ + */ +#define XGPIOPS_DATA_LSW_OFFSET 0x00000000U /* Mask and Data Register LSW, WO */ +#define XGPIOPS_DATA_MSW_OFFSET 0x00000004U /* Mask and Data Register MSW, WO */ +#define XGPIOPS_DATA_OFFSET 0x00000040U /* Data Register, RW */ +#define XGPIOPS_DATA_RO_OFFSET 0x00000060U /* Data Register - Input, RO */ +#define XGPIOPS_DIRM_OFFSET 0x00000204U /* Direction Mode Register, RW */ +#define XGPIOPS_OUTEN_OFFSET 0x00000208U /* Output Enable Register, RW */ +#define XGPIOPS_INTMASK_OFFSET 0x0000020CU /* Interrupt Mask Register, RO */ +#define XGPIOPS_INTEN_OFFSET 0x00000210U /* Interrupt Enable Register, WO */ +#define XGPIOPS_INTDIS_OFFSET 0x00000214U /* Interrupt Disable Register, WO*/ +#define XGPIOPS_INTSTS_OFFSET 0x00000218U /* Interrupt Status Register, RO */ +#define XGPIOPS_INTTYPE_OFFSET 0x0000021CU /* Interrupt Type Register, RW */ +#define XGPIOPS_INTPOL_OFFSET 0x00000220U /* Interrupt Polarity Register, RW */ +#define XGPIOPS_INTANY_OFFSET 0x00000224U /* Interrupt On Any Register, RW */ +/* @} */ + +/** @name Register offsets for each Bank. + * @{ + */ +#define XGPIOPS_DATA_MASK_OFFSET 0x00000008U /* Data/Mask Registers offset */ +#define XGPIOPS_DATA_BANK_OFFSET 0x00000004U /* Data Registers offset */ +#define XGPIOPS_REG_MASK_OFFSET 0x00000040U /* Registers offset */ +/* @} */ + +/* For backwards compatibility */ +#define XGPIOPS_BYPM_MASK_OFFSET (u32)0x40 + +/** @name Interrupt type reset values for each bank + * @{ + */ +#ifdef XPAR_PSU_GPIO_0_BASEADDR +#define XGPIOPS_INTTYPE_BANK0_RESET 0x03FFFFFFU /* Resets specific to Zynq Ultrascale+ MP */ +#define XGPIOPS_INTTYPE_BANK1_RESET 0x03FFFFFFU +#define XGPIOPS_INTTYPE_BANK2_RESET 0x03FFFFFFU +#else +#define XGPIOPS_INTTYPE_BANK0_RESET 0xFFFFFFFFU /* Resets specific to Zynq */ +#define XGPIOPS_INTTYPE_BANK1_RESET 0x003FFFFFU +#define XGPIOPS_INTTYPE_BANK2_RESET 0xFFFFFFFFU +#endif + +#define XGPIOPS_INTTYPE_BANK3_RESET 0xFFFFFFFFU /* Reset common to both platforms */ +#define XGPIOPS_INTTYPE_BANK4_RESET 0xFFFFFFFFU /* Resets specific to Zynq Ultrascale+ MP */ +#define XGPIOPS_INTTYPE_BANK5_RESET 0xFFFFFFFFU +/* @} */ +#define XGPIOPS_PS_GPIO_BASEADDR 0xFF0B0000U /* Flag for Base Address for PS_GPIO in Versal */ +#define XGPIOPS_ZERO 0U /* Flag for 0 Value */ +#define XGPIOPS_ONE 1U /* Flag for 1 Value */ +#define XGPIOPS_TWO 2U /* Flag for 2 Value */ +#define XGPIOPS_THREE 3U /* Flag for 3 Value */ +#define XGPIOPS_FOUR 4U /* Flag for 4 Value */ +#define XGPIOPS_SIX 6U /* Flag for 6 Value */ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/****************************************************************************/ +/** +* +* This macro reads the given register. +* +* @param BaseAddr is the base address of the device. +* @param RegOffset is the register offset to be read. +* +* @return The 32-bit value of the register +* +* @note None. +* +*****************************************************************************/ +#define XGpioPs_ReadReg(BaseAddr, RegOffset) \ + Xil_In32((BaseAddr) + (u32)(RegOffset)) + +/****************************************************************************/ +/** +* +* This macro writes to the given register. +* +* @param BaseAddr is the base address of the device. +* @param RegOffset is the offset of the register to be written. +* @param Data is the 32-bit value to write to the register. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +#define XGpioPs_WriteReg(BaseAddr, RegOffset, Data) \ + Xil_Out32((BaseAddr) + (u32)(RegOffset), (u32)(Data)) + +/************************** Function Prototypes ******************************/ + +void XGpioPs_ResetHw(u32 BaseAddress); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* XGPIOPS_HW_H */ +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/gpiops_v3_5/src/xgpiops_intr.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/gpiops_v3_5/src/xgpiops_intr.c new file mode 100644 index 0000000..0730c91 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/gpiops_v3_5/src/xgpiops_intr.c @@ -0,0 +1,813 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xgpiops_intr.c +* @addtogroup gpiops_v3_5 +* @{ +* +* This file contains functions related to GPIO interrupt handling. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a sv   01/18/10 First Release
+* 2.2	sk	 10/13/14 Used Pin number in Bank instead of pin number
+* 					  passed to API's. CR# 822636
+* 3.00  kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.1	kvn  04/13/15 Add support for Zynq Ultrascale+ MP. CR# 856980.
+* 3.1   aru  07/13/18 Ressolved doxygen reported warnings. CR# 1006331.
+* 3.4   aru  08/09/18 Ressolved cppcheck warnings.
+* 3.4   aru  08/17/18 Resolved MISRA-C mandatory violations. CR# 1007751
+* 3.5   sne  03/01/19 Fixes violations according to MISRAC-2012
+*                     in saftey mode and modified the code such as
+*                     Use of mixed mode arithmetic,Declared the poiner param
+*                     as Pointer to const,Casting operation to a pointer,
+*                     Literal value requires a U suffix.
+* 3.5   sne  03/14/19 Added Versal support.
+* 3.5   sne  03/20/19 Fixed multiple interrupts problem CR#1024556.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xgpiops.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Variable Definitions *****************************/ + +/************************** Function Prototypes ******************************/ + +void StubHandler(const void *CallBackRef, u32 Bank, u32 Status); + +/****************************************************************************/ +/** +* +* This function enables the interrupts for the specified pins in the specified +* bank. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Bank is the bank number of the GPIO to operate on. +* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. +* @param Mask is the bit mask of the pins for which interrupts are to +* be enabled. Bit positions of 1 will be enabled. Bit positions +* of 0 will keep the previous setting. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XGpioPs_IntrEnable(const XGpioPs *InstancePtr, u8 Bank, u32 Mask) +{ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Bank < InstancePtr->MaxBanks); +#ifdef versal + if(InstancePtr->PmcGpio == TRUE) { + Xil_AssertVoid(Bank != XGPIOPS_TWO); + } else { + Xil_AssertVoid((Bank !=XGPIOPS_ONE) && (Bank !=XGPIOPS_TWO)); + } +#endif + + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTEN_OFFSET, Mask); +} + +/****************************************************************************/ +/** +* +* This function enables the interrupt for the specified pin. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Pin is the pin number for which the interrupt is to be enabled. +* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XGpioPs_IntrEnablePin(const XGpioPs *InstancePtr, u32 Pin) +{ + u8 Bank; + u8 PinNumber; + u32 IntrReg; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Pin < InstancePtr->MaxPinNum); + + /* Get the Bank number and Pin number within the bank. */ +#ifdef versal + XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); +#else + XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber); +#endif + + IntrReg = ((u32)1 << (u32)PinNumber); + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTEN_OFFSET, IntrReg); +} + +/****************************************************************************/ +/** +* +* This function disables the interrupts for the specified pins in the specified +* bank. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Bank is the bank number of the GPIO to operate on. +* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. +* @param Mask is the bit mask of the pins for which interrupts are +* to be disabled. Bit positions of 1 will be disabled. Bit +* positions of 0 will keep the previous setting. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XGpioPs_IntrDisable(const XGpioPs *InstancePtr, u8 Bank, u32 Mask) +{ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Bank < InstancePtr->MaxBanks); +#ifdef versal + if(InstancePtr->PmcGpio == TRUE) { + Xil_AssertVoid(Bank != XGPIOPS_TWO); + } else { + Xil_AssertVoid((Bank !=XGPIOPS_ONE) && (Bank !=XGPIOPS_TWO)); + } +#endif + + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTDIS_OFFSET, Mask); +} + +/****************************************************************************/ +/** +* +* This function disables the interrupts for the specified pin. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Pin is the pin number for which the interrupt is to be disabled. +* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XGpioPs_IntrDisablePin(const XGpioPs *InstancePtr, u32 Pin) +{ + u8 Bank; + u8 PinNumber; + u32 IntrReg; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Pin < InstancePtr->MaxPinNum); + + /* Get the Bank number and Pin number within the bank. */ +#ifdef versal + XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); +#else + XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber); +#endif + + IntrReg = ((u32)1 << (u32)PinNumber); + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTDIS_OFFSET, IntrReg); +} + +/****************************************************************************/ +/** +* +* This function returns the interrupt enable status for a bank. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Bank is the bank number of the GPIO to operate on. +* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. +* +* @return Enabled interrupt(s) in a 32-bit format. Bit positions with 1 +* indicate that the interrupt for that pin is enabled, bit +* positions with 0 indicate that the interrupt for that pin is +* disabled. +* +* @note None. +* +*****************************************************************************/ +u32 XGpioPs_IntrGetEnabled(const XGpioPs *InstancePtr, u8 Bank) +{ + u32 IntrMask; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(Bank < InstancePtr->MaxBanks); +#ifdef versal + if(InstancePtr->PmcGpio == TRUE) { + Xil_AssertNonvoid(Bank != XGPIOPS_TWO); + } else { + Xil_AssertNonvoid((Bank !=XGPIOPS_ONE) && (Bank !=XGPIOPS_TWO)); + } +#endif + + IntrMask = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTMASK_OFFSET); + return (~IntrMask); +} + +/****************************************************************************/ +/** +* +* This function returns whether interrupts are enabled for the specified pin. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Pin is the pin number for which the interrupt enable status +* is to be known. +* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. +* +* @return +* - TRUE if the interrupt is enabled. +* - FALSE if the interrupt is disabled. +* +* @note None. +* +*****************************************************************************/ +u32 XGpioPs_IntrGetEnabledPin(const XGpioPs *InstancePtr, u32 Pin) +{ + u8 Bank; + u8 PinNumber; + u32 IntrReg; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(Pin < InstancePtr->MaxPinNum); + + /* Get the Bank number and Pin number within the bank. */ +#ifdef versal + XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); +#else + XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber); +#endif + + IntrReg = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTMASK_OFFSET); + + return (((IntrReg & ((u32)1 << PinNumber)) != (u32)0)? FALSE : TRUE); +} + +/****************************************************************************/ +/** +* +* This function returns interrupt status read from Interrupt Status Register. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Bank is the bank number of the GPIO to operate on. +* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. +* +* @return The value read from Interrupt Status Register. +* +* @note None. +* +*****************************************************************************/ +u32 XGpioPs_IntrGetStatus(const XGpioPs *InstancePtr, u8 Bank) +{ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(Bank < InstancePtr->MaxBanks); +#ifdef versal + if(InstancePtr->PmcGpio == TRUE) { + Xil_AssertNonvoid(Bank != XGPIOPS_TWO); + } else { + Xil_AssertNonvoid((Bank !=XGPIOPS_ONE) && (Bank !=XGPIOPS_TWO)); + } +#endif + + return XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTSTS_OFFSET); +} + +/****************************************************************************/ +/** +* +* This function returns interrupt enable status of the specified pin. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Pin is the pin number for which the interrupt enable status +* is to be known. +* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. +* +* @return +* - TRUE if the interrupt has occurred. +* - FALSE if the interrupt has not occurred. +* +* @note None. +* +*****************************************************************************/ +u32 XGpioPs_IntrGetStatusPin(const XGpioPs *InstancePtr, u32 Pin) +{ + u8 Bank; + u8 PinNumber; + u32 IntrReg; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(Pin < InstancePtr->MaxPinNum); + + /* Get the Bank number and Pin number within the bank. */ +#ifdef versal + XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); +#else + XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber); +#endif + + IntrReg = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTSTS_OFFSET); + + return (((IntrReg & ((u32)1 << PinNumber)) != (u32)0)? TRUE : FALSE); +} + +/****************************************************************************/ +/** +* +* This function clears pending interrupt(s) with the provided mask. This +* function should be called after the software has serviced the interrupts +* that are pending. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Bank is the bank number of the GPIO to operate on. +* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. +* @param Mask is the mask of the interrupts to be cleared. Bit positions +* of 1 will be cleared. Bit positions of 0 will not change the +* previous interrupt status. +* +* @note None. +* +*****************************************************************************/ +void XGpioPs_IntrClear(const XGpioPs *InstancePtr, u8 Bank, u32 Mask) +{ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Bank < InstancePtr->MaxBanks); +#ifdef versal + if(InstancePtr->PmcGpio == TRUE) { + Xil_AssertVoid(Bank != XGPIOPS_TWO); + } else { + Xil_AssertVoid((Bank !=XGPIOPS_ONE) && (Bank !=XGPIOPS_TWO)); + } +#endif + + /* Clear the currently pending interrupts. */ + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTSTS_OFFSET, Mask); +} + +/****************************************************************************/ +/** +* +* This function clears the specified pending interrupt. This function should be +* called after the software has serviced the interrupts that are pending. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Pin is the pin number for which the interrupt status is to be +* cleared. Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. +* +* @note None. +* +*****************************************************************************/ +void XGpioPs_IntrClearPin(const XGpioPs *InstancePtr, u32 Pin) +{ + u8 Bank; + u8 PinNumber; + u32 IntrReg; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Pin < InstancePtr->MaxPinNum); + + /* Get the Bank number and Pin number within the bank. */ +#ifdef versal + XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); +#else + XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber); +#endif + + /* Clear the specified pending interrupts. */ + IntrReg = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTSTS_OFFSET); + + IntrReg &= ((u32)1 << PinNumber); + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTSTS_OFFSET, IntrReg); +} + +/****************************************************************************/ +/** +* +* This function is used for setting the Interrupt Type, Interrupt Polarity and +* Interrupt On Any for the specified GPIO Bank pins. +* +* @param InstancePtr is a pointer to an XGpioPs instance. +* @param Bank is the bank number of the GPIO to operate on. +* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. +* @param IntrType is the 32 bit mask of the interrupt type. +* 0 means Level Sensitive and 1 means Edge Sensitive. +* @param IntrPolarity is the 32 bit mask of the interrupt polarity. +* 0 means Active Low or Falling Edge and 1 means Active High or +* Rising Edge. +* @param IntrOnAny is the 32 bit mask of the interrupt trigger for +* edge triggered interrupts. 0 means trigger on single edge using +* the configured interrupt polarity and 1 means trigger on both +* edges. +* +* @return None. +* +* @note This function is used for setting the interrupt related +* properties of all the pins in the specified bank. The previous +* state of the pins is not maintained. +* To change the Interrupt properties of a single GPIO pin, use the +* function XGpioPs_SetPinIntrType(). +* +*****************************************************************************/ +void XGpioPs_SetIntrType(const XGpioPs *InstancePtr, u8 Bank, u32 IntrType, + u32 IntrPolarity, u32 IntrOnAny) +{ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Bank < InstancePtr->MaxBanks); +#ifdef versal + if(InstancePtr->PmcGpio == TRUE) { + Xil_AssertVoid(Bank != XGPIOPS_TWO); + } else { + Xil_AssertVoid((Bank !=XGPIOPS_ONE) && (Bank !=XGPIOPS_TWO)); + } +#endif + + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTTYPE_OFFSET, IntrType); + + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTPOL_OFFSET, IntrPolarity); + + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTANY_OFFSET, IntrOnAny); +} + +/****************************************************************************/ +/** +* +* This function is used for getting the Interrupt Type, Interrupt Polarity and +* Interrupt On Any for the specified GPIO Bank pins. +* +* @param InstancePtr is a pointer to an XGpioPs instance. +* @param Bank is the bank number of the GPIO to operate on. +* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. +* @param IntrType returns the 32 bit mask of the interrupt type. +* 0 means Level Sensitive and 1 means Edge Sensitive. +* @param IntrPolarity returns the 32 bit mask of the interrupt +* polarity. 0 means Active Low or Falling Edge and 1 means +* Active High or Rising Edge. +* @param IntrOnAny returns the 32 bit mask of the interrupt trigger for +* edge triggered interrupts. 0 means trigger on single edge using +* the configured interrupt polarity and 1 means trigger on both +* edges. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XGpioPs_GetIntrType(const XGpioPs *InstancePtr, u8 Bank, u32 *IntrType, + u32 *IntrPolarity, u32 *IntrOnAny) + +{ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Bank < InstancePtr->MaxBanks); +#ifdef versal + if(InstancePtr->PmcGpio == TRUE) { + Xil_AssertVoid(Bank != XGPIOPS_TWO); + } else { + Xil_AssertVoid((Bank !=XGPIOPS_ONE) && (Bank !=XGPIOPS_TWO)); + } +#endif + + *IntrType = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTTYPE_OFFSET); + + *IntrPolarity = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTPOL_OFFSET); + + *IntrOnAny = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTANY_OFFSET); +} + +/****************************************************************************/ +/** +* +* This function is used for setting the IRQ Type of a single GPIO pin. +* +* @param InstancePtr is a pointer to an XGpioPs instance. +* @param Pin is the pin number whose IRQ type is to be set. +* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. +* @param IrqType is the IRQ type for GPIO Pin. Use XGPIOPS_IRQ_TYPE_* +* defined in xgpiops.h to specify the IRQ type. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XGpioPs_SetIntrTypePin(const XGpioPs *InstancePtr, u32 Pin, u8 IrqType) +{ + u32 IntrTypeReg; + u32 IntrPolReg; + u32 IntrOnAnyReg; + u8 Bank; + u8 PinNumber; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Pin < InstancePtr->MaxPinNum); + Xil_AssertVoid(IrqType <= XGPIOPS_IRQ_TYPE_LEVEL_LOW); + + /* Get the Bank number and Pin number within the bank. */ +#ifdef versal + XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); +#else + XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber); +#endif + + IntrTypeReg = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTTYPE_OFFSET); + + IntrPolReg = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTPOL_OFFSET); + + IntrOnAnyReg = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTANY_OFFSET); + + switch (IrqType) { + case XGPIOPS_IRQ_TYPE_EDGE_RISING: + IntrTypeReg |= ((u32)1 << (u32)PinNumber); + IntrPolReg |= ((u32)1 << (u32)PinNumber); + IntrOnAnyReg &= ~((u32)1 << (u32)PinNumber); + break; + case XGPIOPS_IRQ_TYPE_EDGE_FALLING: + IntrTypeReg |= ((u32)1 << (u32)PinNumber); + IntrPolReg &= ~((u32)1 << (u32)PinNumber); + IntrOnAnyReg &= ~((u32)1 << (u32)PinNumber); + break; + case XGPIOPS_IRQ_TYPE_EDGE_BOTH: + IntrTypeReg |= ((u32)1 << (u32)PinNumber); + IntrOnAnyReg |= ((u32)1 << (u32)PinNumber); + break; + case XGPIOPS_IRQ_TYPE_LEVEL_HIGH: + IntrTypeReg &= ~((u32)1 << (u32)PinNumber); + IntrPolReg |= ((u32)1 << (u32)PinNumber); + break; + case XGPIOPS_IRQ_TYPE_LEVEL_LOW: + IntrTypeReg &= ~((u32)1 << (u32)PinNumber); + IntrPolReg &= ~((u32)1 << (u32)PinNumber); + break; + default: + /**< Default statement is added for MISRA C compliance. */ + break; + } + + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTTYPE_OFFSET, IntrTypeReg); + + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTPOL_OFFSET, IntrPolReg); + + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTANY_OFFSET, IntrOnAnyReg); +} + +/****************************************************************************/ +/** +* +* This function returns the IRQ Type of a given GPIO pin. +* +* @param InstancePtr is a pointer to an XGpioPs instance. +* @param Pin is the pin number whose IRQ type is to be obtained. +* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. +* +* @return None. +* +* @note Use XGPIOPS_IRQ_TYPE_* defined in xgpiops.h for the IRQ type +* returned by this function. +* +*****************************************************************************/ +u8 XGpioPs_GetIntrTypePin(const XGpioPs *InstancePtr, u32 Pin) +{ + u32 IntrType; + u32 IntrPol; + u32 IntrOnAny; + u8 Bank; + u8 PinNumber; + u8 IrqType; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(Pin < InstancePtr->MaxPinNum); + + /* Get the Bank number and Pin number within the bank. */ +#ifdef versal + XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); +#else + XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber); +#endif + + IntrType = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTTYPE_OFFSET) & ((u32)1 << PinNumber); + + if (IntrType == ((u32)1 << PinNumber)) { + + IntrOnAny = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTANY_OFFSET) & ((u32)1 << PinNumber); + + IntrPol = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTPOL_OFFSET) & ((u32)1 << PinNumber); + + + if (IntrOnAny == ((u32)1 << PinNumber)) { + IrqType = XGPIOPS_IRQ_TYPE_EDGE_BOTH; + } else if (IntrPol == ((u32)1 << PinNumber)) { + IrqType = XGPIOPS_IRQ_TYPE_EDGE_RISING; + } else { + IrqType = XGPIOPS_IRQ_TYPE_EDGE_FALLING; + } + } else { + + IntrPol = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTPOL_OFFSET) & ((u32)1 << PinNumber); + + if (IntrPol == ((u32)1 << PinNumber)) { + IrqType = XGPIOPS_IRQ_TYPE_LEVEL_HIGH; + } else { + IrqType = XGPIOPS_IRQ_TYPE_LEVEL_LOW; + } + } + + return IrqType; +} + +/*****************************************************************************/ +/** +* +* This function sets the status callback function. The callback function is +* called by the XGpioPs_IntrHandler when an interrupt occurs. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param CallBackRef is the upper layer callback reference passed back +* when the callback function is invoked. +* @param FuncPointer is the pointer to the callback function. +* +* +* @return None. +* +* @note The handler is called within interrupt context, so it should do +* its work quickly and queue potentially time-consuming work to a +* task-level thread. +* +******************************************************************************/ +void XGpioPs_SetCallbackHandler(XGpioPs *InstancePtr, void *CallBackRef, + XGpioPs_Handler FuncPointer) +{ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(FuncPointer != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + InstancePtr->Handler = FuncPointer; + InstancePtr->CallBackRef = CallBackRef; +} + +/*****************************************************************************/ +/** +* +* This function is the interrupt handler for GPIO interrupts.It checks the +* interrupt status registers of all the banks to determine the actual bank in +* which an interrupt has been triggered. It then calls the upper layer callback +* handler set by the function XGpioPs_SetBankHandler(). The callback is called +* when an interrupt +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* +* @return None. +* +* @note This function does not save and restore the processor context +* such that the user must provide this processing. +* +******************************************************************************/ +void XGpioPs_IntrHandler(const XGpioPs *InstancePtr) +{ + u8 Bank; + u32 IntrStatus; + u32 IntrEnabled; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + for (Bank = 0U; Bank < InstancePtr->MaxBanks; Bank++) { + IntrStatus = XGpioPs_IntrGetStatus(InstancePtr, Bank); + IntrEnabled = XGpioPs_IntrGetEnabled(InstancePtr,Bank); + if ((IntrStatus & IntrEnabled) != (u32)0) { + XGpioPs_IntrClear(InstancePtr, Bank, + (IntrStatus & IntrEnabled)); + InstancePtr->Handler(InstancePtr-> + CallBackRef, Bank, + (IntrStatus & IntrEnabled)); + } + } +} + +/*****************************************************************************/ +/** +* +* This is a stub for the status callback. The stub is here in case the upper +* layers do not set the handler. +* +* @param CallBackRef is a pointer to the upper layer callback reference +* @param Bank is the GPIO Bank in which an interrupt occurred. +* @param Status is the Interrupt status of the GPIO bank. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void StubHandler(const void *CallBackRef, u32 Bank, u32 Status) +{ + (const void) CallBackRef; + (void) Bank; + (void) Status; + + Xil_AssertVoidAlways(); +} +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/gpiops_v3_5/src/xgpiops_selftest.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/gpiops_v3_5/src/xgpiops_selftest.c new file mode 100644 index 0000000..322ca74 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/gpiops_v3_5/src/xgpiops_selftest.c @@ -0,0 +1,134 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xgpiops_selftest.c +* @addtogroup gpiops_v3_5 +* @{ +* +* This file contains a diagnostic self-test function for the XGpioPs driver. +* +* Read xgpiops.h file for more information. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a sv   01/18/10 First Release
+* 3.00  kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.5   sne  03/01/19 Fixes violations according to MISRAC-2012
+*                     in saftey mode and modified the code such as
+*                     Use of mixed mode arithmetic,Declared the poiner param
+*                     as Pointer to const,Casting operation to a pointer,
+*                     Literal value requires a U suffix.
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ + +#include "xstatus.h" +#include "xgpiops.h" + +/************************** Constant Definitions ****************************/ + + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Variable Definitions ****************************/ + +/************************** Function Prototypes *****************************/ + +/*****************************************************************************/ +/** +* +* This function runs a self-test on the GPIO driver/device. This function +* does a register read/write test on some of the Interrupt Registers. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* +* @return +* - XST_SUCCESS if the self-test passed. +* - XST_FAILURE otherwise. +* +* +******************************************************************************/ +s32 XGpioPs_SelfTest(const XGpioPs *InstancePtr) +{ + s32 Status = XST_SUCCESS; + u32 IntrEnabled; + u32 CurrentIntrType = 0U; + u32 CurrentIntrPolarity = 0U; + u32 CurrentIntrOnAny = 0U; + u32 IntrType = 0U; + u32 IntrPolarity = 0U; + u32 IntrOnAny = 0U; + u32 IntrTestValue = 0x22U; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* Disable the Interrupts for Bank 0 . */ + IntrEnabled = XGpioPs_IntrGetEnabled(InstancePtr, XGPIOPS_BANK0); + XGpioPs_IntrDisable(InstancePtr, XGPIOPS_BANK0, IntrEnabled); + + /* + * Get the Current Interrupt properties for Bank 0. + * Set them to a known value, read it back and compare. + */ + XGpioPs_GetIntrType(InstancePtr, XGPIOPS_BANK0, &CurrentIntrType, + &CurrentIntrPolarity, &CurrentIntrOnAny); + + XGpioPs_SetIntrType(InstancePtr, XGPIOPS_BANK0, IntrTestValue, + IntrTestValue, IntrTestValue); + + XGpioPs_GetIntrType(InstancePtr, XGPIOPS_BANK0, &IntrType, + &IntrPolarity, &IntrOnAny); + + if ((IntrType != IntrTestValue) && (IntrPolarity != IntrTestValue) && + (IntrOnAny != IntrTestValue)) { + + Status = XST_FAILURE; + } + + /* + * Restore the contents of all the interrupt registers modified in this + * test. + */ + XGpioPs_SetIntrType(InstancePtr, XGPIOPS_BANK0, CurrentIntrType, + CurrentIntrPolarity, CurrentIntrOnAny); + + XGpioPs_IntrEnable(InstancePtr, XGPIOPS_BANK0, IntrEnabled); + + return Status; +} +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/gpiops_v3_5/src/xgpiops_sinit.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/gpiops_v3_5/src/xgpiops_sinit.c new file mode 100644 index 0000000..58ce55e --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/gpiops_v3_5/src/xgpiops_sinit.c @@ -0,0 +1,97 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xgpiops_sinit.c +* @addtogroup gpiops_v3_5 +* @{ +* +* This file contains the implementation of the XGpioPs driver's static +* initialization functionality. +* +* @note None. +* +*
+*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a sv   01/15/10 First Release
+* 3.00  kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xgpiops.h" +#include "xparameters.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ +extern XGpioPs_Config XGpioPs_ConfigTable[XPAR_XGPIOPS_NUM_INSTANCES]; + +/*****************************************************************************/ +/** +* +* This function looks for the device configuration based on the unique device +* ID. The table XGpioPs_ConfigTable[] contains the configuration information +* for each device in the system. +* +* @param DeviceId is the unique device ID of the device being looked up. +* +* @return A pointer to the configuration table entry corresponding to the +* given device ID, or NULL if no match is found. +* +* @note None. +* +******************************************************************************/ +XGpioPs_Config *XGpioPs_LookupConfig(u16 DeviceId) +{ + XGpioPs_Config *CfgPtr = NULL; + u32 Index; + + for (Index = 0U; Index < (u32)XPAR_XGPIOPS_NUM_INSTANCES; Index++) { + if (XGpioPs_ConfigTable[Index].DeviceId == DeviceId) { + CfgPtr = &XGpioPs_ConfigTable[Index]; + break; + } + } + + return (XGpioPs_Config *)CfgPtr; +} +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/qspips_v3_6/src/Makefile b/df_datalink/bsp/ps7_cortexa9_0/libsrc/qspips_v3_6/src/Makefile new file mode 100644 index 0000000..3600928 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/qspips_v3_6/src/Makefile @@ -0,0 +1,40 @@ +COMPILER= +ARCHIVER= +CP=cp +COMPILER_FLAGS= +EXTRA_COMPILER_FLAGS= +LIB=libxil.a + +CC_FLAGS = $(COMPILER_FLAGS) +ECC_FLAGS = $(EXTRA_COMPILER_FLAGS) + +RELEASEDIR=../../../lib +INCLUDEDIR=../../../include +INCLUDES=-I./. -I${INCLUDEDIR} + +OUTS = *.o + +LIBSOURCES:=*.c +INCLUDEFILES:=*.h + +OBJECTS = $(addsuffix .o, $(basename $(wildcard *.c))) + +libs: banner xqspips_libs clean + +%.o: %.c + ${COMPILER} $(CC_FLAGS) $(ECC_FLAGS) $(INCLUDES) -o $@ $< + +banner: + echo "Compiling qspips" + +xqspips_libs: ${OBJECTS} + $(ARCHIVER) -r ${RELEASEDIR}/${LIB} ${OBJECTS} + +.PHONY: include +include: xqspips_includes + +xqspips_includes: + ${CP} ${INCLUDEFILES} ${INCLUDEDIR} + +clean: + rm -rf ${OBJECTS} diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/qspips_v3_6/src/xqspips.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/qspips_v3_6/src/xqspips.c new file mode 100644 index 0000000..e82cab6 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/qspips_v3_6/src/xqspips.c @@ -0,0 +1,1611 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xqspips.c +* @addtogroup qspips_v3_6 +* @{ +* +* Contains implements the interface functions of the XQspiPs driver. +* See xqspips.h for a detailed description of the device and driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- -----------------------------------------------
+* 1.00  sdm 11/25/10 First release
+* 2.00a kka 07/25/12 Removed XQspiPs_GetWriteData API.
+*		     The XQspiPs_SetSlaveSelect has been modified to remove
+*		     the argument of the slave select as the QSPI controller
+*		     only supports one slave.
+* 		     XQspiPs_GetSlaveSelect API has been removed
+* 		     Added logic to XQspiPs_GetReadData to handle data
+*		     shift for normal data reads and instruction/status
+*		     reads differently based on the ShiftReadData flag.
+* 		     Removed the selection for the following options:
+*		     Master mode (XQSPIPS_MASTER_OPTION) and
+*		     Flash interface mode (XQSPIPS_FLASH_MODE_OPTION) option
+*		     as the QSPI driver supports the Master mode
+*		     and Flash Interface mode and doesnot support
+*		     Slave mode or the legacy mode.
+*		     Modified the XQspiPs_PolledTransfer and XQspiPs_Transfer
+*		     APIs so that the last argument (IsInst) specifying whether
+*		     it is instruction or data has been removed. The first byte
+*		     in the SendBufPtr argument of these APIs specify the
+*		     instruction to be sent to the Flash Device.
+*		     The XQspiPs_PolledTransfer function has been updated
+*		     to fill the data to fifo depth.
+*		     This version of the driver fixes CRs 670197/663787.
+* 2.01a sg  02/03/13 Added flash opcodes for DUAL_IO_READ,QUAD_IO_READ.
+*		     Created macros XQspiPs_IsManualStart and
+*		     XQspiPs_IsManualChipSelect.
+*		     Changed QSPI transfer logic for polled and interrupt
+*		     modes to be based on filled tx fifo count and receive
+*		     based on it. RXNEMPTY interrupt is not used.
+*		     Added assertions to XQspiPs_LqspiRead function.
+*
+* 2.02a hk  05/14/13 Added enable and disable to the XQspiPs_LqspiRead()
+*			 function
+*            Added instructions for bank selection, die erase and
+*            flag status register to the flash instruction table
+*            Handling for instructions not in flash instruction
+*			 table added. Checking for Tx FIFO empty when switching from
+*			 TXD1/2/3 to TXD0 added. If WRSR instruction is sent with
+*            byte count 3 (spansion), instruction size and TXD register
+*			 changed accordingly. CR# 712502 and 703869.
+*            Added (#ifdef linear base address) in the Linear read function.
+*            Changed  XPAR_XQSPIPS_0_LINEAR_BASEADDR to
+*            XPAR_PS7_QSPI_LINEAR_0_S_AXI_BASEADDR in
+*            XQspiPs_LqspiRead function. Fix for CR#718141
+*
+* 2.03a hk  09/05/13 Modified polled and interrupt transfers to make use of
+*                    thresholds. This is to improve performance.
+*                    Added RX and TX threshold reset to one in XQspiPs_Abort.
+*                    Added RX threshold reset(1) after transfer in polled and
+*                    interrupt transfers. Made changes to make sure threshold
+*                    change is done only when no transfer is in progress.
+* 3.1   hk  08/13/14 When writing to the configuration register, set/reset
+*                    required bits leaving reserved bits untouched. CR# 796813.
+* 3.2	sk	02/05/15 Add SLCR reset in abort function as a workaround because
+* 					 controller does not update FIFO status flags as expected
+* 					 when thresholds are used.
+* 3.3   sk  11/07/15 Modified the API prototypes according to MISRAC standards
+*                    to remove compilation warnings. CR# 868893.
+* 3.5	tjs 13/08/18 Fixed compilation warnings for ARMCC.
+* 3.6	akm 03/28/19 Fixed memory leak issue while reading from qspi.(CR#1016357)
+* 3.6 	akm 04/15/19 Modified the mask in XQspiPs_GetReadData() API to retrieve
+*		     configuration register values of both the Flashes in dual
+*		     parellel connection.
+*
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xqspips.h" + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + +/** + * This typedef defines qspi flash instruction format + */ +typedef struct { + u8 OpCode; /**< Operational code of the instruction */ + u8 InstSize; /**< Size of the instruction including address bytes */ + u8 TxOffset; /**< Register address where instruction has to be + written */ +} XQspiPsInstFormat; + +/***************** Macros (Inline Functions) Definitions *********************/ + +#define ARRAY_SIZE(Array) (sizeof(Array) / sizeof((Array)[0])) + +/************************** Function Prototypes ******************************/ +static void XQspiPs_GetReadData(XQspiPs *InstancePtr, u32 Data, u8 Size); +static void StubStatusHandler(void *CallBackRef, u32 StatusEvent, + unsigned ByteCount); + +/************************** Variable Definitions *****************************/ + +/* + * List of all the QSPI instructions and its format + */ +static XQspiPsInstFormat FlashInst[] = { + { XQSPIPS_FLASH_OPCODE_WREN, 1, XQSPIPS_TXD_01_OFFSET }, + { XQSPIPS_FLASH_OPCODE_WRDS, 1, XQSPIPS_TXD_01_OFFSET }, + { XQSPIPS_FLASH_OPCODE_RDSR1, 2, XQSPIPS_TXD_10_OFFSET }, + { XQSPIPS_FLASH_OPCODE_RDSR2, 2, XQSPIPS_TXD_10_OFFSET }, + { XQSPIPS_FLASH_OPCODE_WRSR, 2, XQSPIPS_TXD_10_OFFSET }, + { XQSPIPS_FLASH_OPCODE_PP, 4, XQSPIPS_TXD_00_OFFSET }, + { XQSPIPS_FLASH_OPCODE_SE, 4, XQSPIPS_TXD_00_OFFSET }, + { XQSPIPS_FLASH_OPCODE_BE_32K, 4, XQSPIPS_TXD_00_OFFSET }, + { XQSPIPS_FLASH_OPCODE_BE_4K, 4, XQSPIPS_TXD_00_OFFSET }, + { XQSPIPS_FLASH_OPCODE_BE, 1, XQSPIPS_TXD_01_OFFSET }, + { XQSPIPS_FLASH_OPCODE_ERASE_SUS, 1, XQSPIPS_TXD_01_OFFSET }, + { XQSPIPS_FLASH_OPCODE_ERASE_RES, 1, XQSPIPS_TXD_01_OFFSET }, + { XQSPIPS_FLASH_OPCODE_RDID, 4, XQSPIPS_TXD_00_OFFSET }, + { XQSPIPS_FLASH_OPCODE_NORM_READ, 4, XQSPIPS_TXD_00_OFFSET }, + { XQSPIPS_FLASH_OPCODE_FAST_READ, 4, XQSPIPS_TXD_00_OFFSET }, + { XQSPIPS_FLASH_OPCODE_DUAL_READ, 4, XQSPIPS_TXD_00_OFFSET }, + { XQSPIPS_FLASH_OPCODE_QUAD_READ, 4, XQSPIPS_TXD_00_OFFSET }, + { XQSPIPS_FLASH_OPCODE_DUAL_IO_READ, 4, XQSPIPS_TXD_00_OFFSET }, + { XQSPIPS_FLASH_OPCODE_QUAD_IO_READ, 4, XQSPIPS_TXD_00_OFFSET }, + { XQSPIPS_FLASH_OPCODE_BRWR, 2, XQSPIPS_TXD_10_OFFSET }, + { XQSPIPS_FLASH_OPCODE_BRRD, 2, XQSPIPS_TXD_10_OFFSET }, + { XQSPIPS_FLASH_OPCODE_EARWR, 2, XQSPIPS_TXD_10_OFFSET }, + { XQSPIPS_FLASH_OPCODE_EARRD, 2, XQSPIPS_TXD_10_OFFSET }, + { XQSPIPS_FLASH_OPCODE_DIE_ERASE, 4, XQSPIPS_TXD_00_OFFSET }, + { XQSPIPS_FLASH_OPCODE_READ_FLAG_SR, 2, XQSPIPS_TXD_10_OFFSET }, + { XQSPIPS_FLASH_OPCODE_CLEAR_FLAG_SR, 1, XQSPIPS_TXD_01_OFFSET }, + /* Add all the instructions supported by the flash device */ +}; + +/*****************************************************************************/ +/** +* +* Initializes a specific XQspiPs instance such that the driver is ready to use. +* +* The state of the device after initialization is: +* - Master mode +* - Active high clock polarity +* - Clock phase 0 +* - Baud rate divisor 2 +* - Transfer width 32 +* - Master reference clock = pclk +* - No chip select active +* - Manual CS and Manual Start disabled +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* @param ConfigPtr is a reference to a structure containing information +* about a specific QSPI device. This function initializes an +* InstancePtr object for a specific device specified by the +* contents of Config. +* @param EffectiveAddr is the device base address in the virtual memory +* address space. The caller is responsible for keeping the address +* mapping from EffectiveAddr to the device physical base address +* unchanged once this function is invoked. Unexpected errors may +* occur if the address mapping changes after this function is +* called. If address translation is not used, use +* ConfigPtr->Config.BaseAddress for this device. +* +* @return +* - XST_SUCCESS if successful. +* - XST_DEVICE_IS_STARTED if the device is already started. +* It must be stopped to re-initialize. +* +* @note None. +* +******************************************************************************/ +int XQspiPs_CfgInitialize(XQspiPs *InstancePtr, XQspiPs_Config *ConfigPtr, + u32 EffectiveAddr) +{ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(ConfigPtr != NULL); + + /* + * If the device is busy, disallow the initialize and return a status + * indicating it is already started. This allows the user to stop the + * device and re-initialize, but prevents a user from inadvertently + * initializing. This assumes the busy flag is cleared at startup. + */ + if (InstancePtr->IsBusy == TRUE) { + return XST_DEVICE_IS_STARTED; + } + + /* + * Set some default values. + */ + InstancePtr->IsBusy = FALSE; + + InstancePtr->Config.BaseAddress = EffectiveAddr; + InstancePtr->StatusHandler = StubStatusHandler; + + InstancePtr->SendBufferPtr = NULL; + InstancePtr->RecvBufferPtr = NULL; + InstancePtr->RequestedBytes = 0; + InstancePtr->RemainingBytes = 0; + InstancePtr->IsReady = XIL_COMPONENT_IS_READY; + + InstancePtr->Config.ConnectionMode = ConfigPtr->ConnectionMode; + + /* + * Reset the QSPI device to get it into its initial state. It is + * expected that device configuration will take place after this + * initialization is done, but before the device is started. + */ + XQspiPs_Reset(InstancePtr); + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* Resets the QSPI device. Reset must only be called after the driver has been +* initialized. Any data transfer that is in progress is aborted. +* +* The upper layer software is responsible for re-configuring (if necessary) +* and restarting the QSPI device after the reset. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XQspiPs_Reset(XQspiPs *InstancePtr) +{ + u32 ConfigReg; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Abort any transfer that is in progress + */ + XQspiPs_Abort(InstancePtr); + + /* + * Write default value to configuration register. + * Do not modify reserved bits. + */ + ConfigReg = XQspiPs_ReadReg(InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET); + ConfigReg |= XQSPIPS_CR_RESET_MASK_SET; + ConfigReg &= ~XQSPIPS_CR_RESET_MASK_CLR; + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPS_CR_OFFSET, + ConfigReg); +} + +/*****************************************************************************/ +/** +* +* Aborts a transfer in progress by disabling the device and flush the RxFIFO. +* The byte counts are cleared, the busy flag is cleared. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* +* @return None. +* +* @note +* +* This function does a read/modify/write of the config register. The user of +* this function needs to take care of critical sections. +* +******************************************************************************/ +void XQspiPs_Abort(XQspiPs *InstancePtr) +{ + u32 ConfigReg; + u32 IsLock; + + XQspiPs_Disable(InstancePtr); + + /* + * De-assert slave select lines. + */ + ConfigReg = XQspiPs_ReadReg(InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET); + ConfigReg |= (XQSPIPS_CR_SSCTRL_MASK | XQSPIPS_CR_SSFORCE_MASK); + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET, ConfigReg); + + /* + * QSPI Software Reset + */ + IsLock = XQspiPs_ReadReg(XPAR_XSLCR_0_BASEADDR, SLCR_LOCKSTA); + if (IsLock) { + XQspiPs_WriteReg(XPAR_XSLCR_0_BASEADDR, SLCR_UNLOCK, + SLCR_UNLOCK_MASK); + } + XQspiPs_WriteReg(XPAR_XSLCR_0_BASEADDR, LQSPI_RST_CTRL, + LQSPI_RST_CTRL_MASK); + XQspiPs_WriteReg(XPAR_XSLCR_0_BASEADDR, LQSPI_RST_CTRL, 0x0); + if (IsLock) { + XQspiPs_WriteReg(XPAR_XSLCR_0_BASEADDR, SLCR_LOCK, + SLCR_LOCK_MASK); + } + + /* + * Set the RX and TX FIFO threshold to reset value (one) + */ + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_RXWR_OFFSET, XQSPIPS_RXWR_RESET_VALUE); + + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_TXWR_OFFSET, XQSPIPS_TXWR_RESET_VALUE); + + InstancePtr->RemainingBytes = 0; + InstancePtr->RequestedBytes = 0; + InstancePtr->IsBusy = FALSE; +} + +/*****************************************************************************/ +/** +* +* Transfers specified data on the QSPI bus. Initiates bus communication and +* sends/receives data to/from the selected QSPI slave. For every byte sent, +* a byte is received. +* +* The caller has the option of providing two different buffers for send and +* receive, or one buffer for both send and receive, or no buffer for receive. +* The receive buffer must be at least as big as the send buffer to prevent +* unwanted memory writes. This implies that the byte count passed in as an +* argument must be the smaller of the two buffers if they differ in size. +* Here are some sample usages: +*
+*   XQspiPs_Transfer(InstancePtr, SendBuf, RecvBuf, ByteCount)
+*	The caller wishes to send and receive, and provides two different
+*	buffers for send and receive.
+*
+*   XQspiPs_Transfer(InstancePtr, SendBuf, NULL, ByteCount)
+*	The caller wishes only to send and does not care about the received
+*	data. The driver ignores the received data in this case.
+*
+*   XQspiPs_Transfer(InstancePtr, SendBuf, SendBuf, ByteCount)
+*	The caller wishes to send and receive, but provides the same buffer
+*	for doing both. The driver sends the data and overwrites the send
+*	buffer with received data as it transfers the data.
+*
+*   XQspiPs_Transfer(InstancePtr, RecvBuf, RecvBuf, ByteCount)
+*	The caller wishes to only receive and does not care about sending
+*	data.  In this case, the caller must still provide a send buffer, but
+*	it can be the same as the receive buffer if the caller does not care
+*	what it sends.  The device must send N bytes of data if it wishes to
+*	receive N bytes of data.
+* 
+* Although this function takes entire buffers as arguments, the driver can only +* transfer a limited number of bytes at a time, limited by the size of the +* FIFO. A call to this function only starts the transfer, then subsequent +* transfers of the data is performed by the interrupt service routine until +* the entire buffer has been transferred. The status callback function is +* called when the entire buffer has been sent/received. +* +* This function is non-blocking. The SetSlaveSelect function must be called +* prior to this function. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* @param SendBufPtr is a pointer to a data buffer that needs to be +* transmitted. This buffer must not be NULL. +* @param RecvBufPtr is a pointer to a buffer for received data. +* This argument can be NULL if do not care about receiving. +* @param ByteCount contains the number of bytes to send/receive. +* The number of bytes received always equals the number of bytes +* sent. +* +* @return +* - XST_SUCCESS if the buffers are successfully handed off to the +* device for transfer. +* - XST_DEVICE_BUSY indicates that a data transfer is already in +* progress. This is determined by the driver. +* +* @note +* +* This function is not thread-safe. The higher layer software must ensure that +* no two threads are transferring data on the QSPI bus at the same time. +* +******************************************************************************/ +s32 XQspiPs_Transfer(XQspiPs *InstancePtr, u8 *SendBufPtr, u8 *RecvBufPtr, + u32 ByteCount) +{ + u32 StatusReg; + u32 ConfigReg; + u8 Instruction; + u32 Data; + unsigned int Index; + u8 TransCount = 0; + XQspiPsInstFormat *CurrInst; + XQspiPsInstFormat NewInst[2]; + u8 SwitchFlag = 0; + + CurrInst = &NewInst[0]; + + /* + * The RecvBufPtr argument can be null + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(SendBufPtr != NULL); + Xil_AssertNonvoid(ByteCount > 0); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Check whether there is another transfer in progress. Not thread-safe. + */ + if (InstancePtr->IsBusy) { + return XST_DEVICE_BUSY; + } + + /* + * Set the busy flag, which will be cleared in the ISR when the + * transfer is entirely done. + */ + InstancePtr->IsBusy = TRUE; + + /* + * Set up buffer pointers. + */ + InstancePtr->SendBufferPtr = SendBufPtr; + InstancePtr->RecvBufferPtr = RecvBufPtr; + + InstancePtr->RequestedBytes = ByteCount; + InstancePtr->RemainingBytes = ByteCount; + + /* + * The first byte with every chip-select assertion is always + * expected to be an instruction for flash interface mode + */ + Instruction = *InstancePtr->SendBufferPtr; + + for (Index = 0 ; Index < ARRAY_SIZE(FlashInst); Index++) { + if (Instruction == FlashInst[Index].OpCode) { + break; + } + } + + /* + * Set the RX FIFO threshold + */ + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_RXWR_OFFSET, XQSPIPS_RXFIFO_THRESHOLD_OPT); + + /* + * If the slave select is "Forced" or under manual control, + * set the slave select now, before beginning the transfer. + */ + if (XQspiPs_IsManualChipSelect(InstancePtr)) { + ConfigReg = XQspiPs_ReadReg(InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET); + ConfigReg &= ~XQSPIPS_CR_SSCTRL_MASK; + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET, + ConfigReg); + } + + /* + * Enable the device. + */ + XQspiPs_Enable(InstancePtr); + + /* + * Clear all the interrrupts. + */ + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPS_SR_OFFSET, + XQSPIPS_IXR_WR_TO_CLR_MASK); + + if (Index < ARRAY_SIZE(FlashInst)) { + CurrInst = &FlashInst[Index]; + /* + * Check for WRSR instruction which has different size for + * Spansion (3 bytes) and Micron (2 bytes) + */ + if ((CurrInst->OpCode == XQSPIPS_FLASH_OPCODE_WRSR) && + (ByteCount == 3)) { + CurrInst->InstSize = 3; + CurrInst->TxOffset = XQSPIPS_TXD_11_OFFSET; + } + } + + /* + * If instruction not present in table + */ + if (Index == ARRAY_SIZE(FlashInst)) { + /* + * Assign current instruction, size and TXD register to be used + * The InstSize mentioned in case of instructions greater than + * 4 bytes is not the actual size, but is indicative of + * the TXD register used. + * The remaining bytes of the instruction will be transmitted + * through TXD0 below. + */ + switch (ByteCount%4) { + case XQSPIPS_SIZE_ONE: + CurrInst->OpCode = Instruction; + CurrInst->InstSize = XQSPIPS_SIZE_ONE; + CurrInst->TxOffset = XQSPIPS_TXD_01_OFFSET; + if (ByteCount > 4) { + SwitchFlag = 1; + } + break; + case XQSPIPS_SIZE_TWO: + CurrInst->OpCode = Instruction; + CurrInst->InstSize = XQSPIPS_SIZE_TWO; + CurrInst->TxOffset = XQSPIPS_TXD_10_OFFSET; + if (ByteCount > 4) { + SwitchFlag = 1; + } + break; + case XQSPIPS_SIZE_THREE: + CurrInst->OpCode = Instruction; + CurrInst->InstSize = XQSPIPS_SIZE_THREE; + CurrInst->TxOffset = XQSPIPS_TXD_11_OFFSET; + if (ByteCount > 4) { + SwitchFlag = 1; + } + break; + default: + CurrInst->OpCode = Instruction; + CurrInst->InstSize = XQSPIPS_SIZE_FOUR; + CurrInst->TxOffset = XQSPIPS_TXD_00_OFFSET; + break; + } + } + + /* + * If the instruction size in not 4 bytes then the data received needs + * to be shifted + */ + if (CurrInst->InstSize != 4) { + InstancePtr->ShiftReadData = 1; + } else { + InstancePtr->ShiftReadData = 0; + } + + /* Get the complete command (flash inst + address/data) */ + Data = *((u32 *)InstancePtr->SendBufferPtr); + InstancePtr->SendBufferPtr += CurrInst->InstSize; + InstancePtr->RemainingBytes -= CurrInst->InstSize; + if (InstancePtr->RemainingBytes < 0) { + InstancePtr->RemainingBytes = 0; + } + + /* Write the command to the FIFO */ + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + CurrInst->TxOffset, Data); + TransCount++; + + /* + * If switching from TXD1/2/3 to TXD0, then start transfer and + * check for FIFO empty + */ + if (SwitchFlag == 1) { + SwitchFlag = 0; + /* + * If, in Manual Start mode, start the transfer. + */ + if (XQspiPs_IsManualStart(InstancePtr)) { + ConfigReg = XQspiPs_ReadReg( + InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET); + ConfigReg |= XQSPIPS_CR_MANSTRT_MASK; + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET, ConfigReg); + } + /* + * Wait for the transfer to finish by polling Tx fifo status. + */ + do { + StatusReg = XQspiPs_ReadReg( + InstancePtr->Config.BaseAddress, + XQSPIPS_SR_OFFSET); + } while ((StatusReg & XQSPIPS_IXR_TXOW_MASK) == 0); + + } + + /* + * Fill the Tx FIFO with as many bytes as it takes (or as many as + * we have to send). + */ + while ((InstancePtr->RemainingBytes > 0) && + (TransCount < XQSPIPS_FIFO_DEPTH)) { + /* + * In case of Write fill the Tx FIFO with data to be transmitted. + * In case of Read fill the Tx FIFO with DUMMY bytes. + */ + if (!InstancePtr->RecvBufferPtr) { + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_TXD_00_OFFSET, + *((u32 *)InstancePtr->SendBufferPtr)); + InstancePtr->SendBufferPtr += 4; + } else { + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_TXD_00_OFFSET, + XQSPIPS_DUMMY_TX_DATA); + } + InstancePtr->RemainingBytes -= 4; + if (InstancePtr->RemainingBytes < 0) { + InstancePtr->RemainingBytes = 0; + } + TransCount++; + } + + /* + * Enable QSPI interrupts (connecting to the interrupt controller and + * enabling interrupts should have been done by the caller). + */ + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_IER_OFFSET, XQSPIPS_IXR_RXNEMPTY_MASK | + XQSPIPS_IXR_TXOW_MASK | XQSPIPS_IXR_RXOVR_MASK | + XQSPIPS_IXR_TXUF_MASK); + + /* + * If, in Manual Start mode, Start the transfer. + */ + if (XQspiPs_IsManualStart(InstancePtr)) { + ConfigReg = XQspiPs_ReadReg(InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET); + ConfigReg |= XQSPIPS_CR_MANSTRT_MASK; + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET, ConfigReg); + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* Transfers specified data on the QSPI bus in polled mode. +* +* The caller has the option of providing two different buffers for send and +* receive, or one buffer for both send and receive, or no buffer for receive. +* The receive buffer must be at least as big as the send buffer to prevent +* unwanted memory writes. This implies that the byte count passed in as an +* argument must be the smaller of the two buffers if they differ in size. +* Here are some sample usages: +*
+*   XQspiPs_PolledTransfer(InstancePtr, SendBuf, RecvBuf, ByteCount)
+*	The caller wishes to send and receive, and provides two different
+*	buffers for send and receive.
+*
+*   XQspiPs_PolledTransfer(InstancePtr, SendBuf, NULL, ByteCount)
+*	The caller wishes only to send and does not care about the received
+*	data. The driver ignores the received data in this case.
+*
+*   XQspiPs_PolledTransfer(InstancePtr, SendBuf, SendBuf, ByteCount)
+*	The caller wishes to send and receive, but provides the same buffer
+*	for doing both. The driver sends the data and overwrites the send
+*	buffer with received data as it transfers the data.
+*
+*   XQspiPs_PolledTransfer(InstancePtr, RecvBuf, RecvBuf, ByteCount)
+*	The caller wishes to only receive and does not care about sending
+*	data.  In this case, the caller must still provide a send buffer, but
+*	it can be the same as the receive buffer if the caller does not care
+*	what it sends.  The device must send N bytes of data if it wishes to
+*	receive N bytes of data.
+*
+* 
+* +* @param InstancePtr is a pointer to the XQspiPs instance. +* @param SendBufPtr is a pointer to a data buffer that needs to be +* transmitted. This buffer must not be NULL. +* @param RecvBufPtr is a pointer to a buffer for received data. +* This argument can be NULL if do not care about receiving. +* @param ByteCount contains the number of bytes to send/receive. +* The number of bytes received always equals the number of bytes +* sent. +* @return +* - XST_SUCCESS if the buffers are successfully handed off to the +* device for transfer. +* - XST_DEVICE_BUSY indicates that a data transfer is already in +* progress. This is determined by the driver. +* +* @note +* +* This function is not thread-safe. The higher layer software must ensure that +* no two threads are transferring data on the QSPI bus at the same time. +* +******************************************************************************/ +s32 XQspiPs_PolledTransfer(XQspiPs *InstancePtr, u8 *SendBufPtr, + u8 *RecvBufPtr, u32 ByteCount) +{ + u32 StatusReg; + u32 ConfigReg; + u8 Instruction; + u32 Data; + u8 TransCount; + unsigned int Index; + XQspiPsInstFormat *CurrInst; + XQspiPsInstFormat NewInst[2]; + u8 SwitchFlag = 0; + u8 IsManualStart = FALSE; + u32 RxCount = 0; + + CurrInst = &NewInst[0]; + /* + * The RecvBufPtr argument can be NULL. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(SendBufPtr != NULL); + Xil_AssertNonvoid(ByteCount > 0); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Check whether there is another transfer in progress. Not thread-safe. + */ + if (InstancePtr->IsBusy) { + return XST_DEVICE_BUSY; + } + + /* + * Set the busy flag, which will be cleared when the transfer is + * entirely done. + */ + InstancePtr->IsBusy = TRUE; + + /* + * Set up buffer pointers. + */ + InstancePtr->SendBufferPtr = SendBufPtr; + InstancePtr->RecvBufferPtr = RecvBufPtr; + + InstancePtr->RequestedBytes = ByteCount; + InstancePtr->RemainingBytes = ByteCount; + + /* + * The first byte with every chip-select assertion is always + * expected to be an instruction for flash interface mode + */ + Instruction = *InstancePtr->SendBufferPtr; + + for (Index = 0 ; Index < ARRAY_SIZE(FlashInst); Index++) { + if (Instruction == FlashInst[Index].OpCode) { + break; + } + } + + /* + * Set the RX FIFO threshold + */ + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_RXWR_OFFSET, XQSPIPS_RXFIFO_THRESHOLD_OPT); + + /* + * If the slave select is "Forced" or under manual control, + * set the slave select now, before beginning the transfer. + */ + if (XQspiPs_IsManualChipSelect(InstancePtr)) { + ConfigReg = XQspiPs_ReadReg(InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET); + ConfigReg &= ~XQSPIPS_CR_SSCTRL_MASK; + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET, + ConfigReg); + } + + /* + * Enable the device. + */ + XQspiPs_Enable(InstancePtr); + + if (Index < ARRAY_SIZE(FlashInst)) { + + CurrInst = &FlashInst[Index]; + /* + * Check for WRSR instruction which has different size for + * Spansion (3 bytes) and Micron (2 bytes) + */ + if ((CurrInst->OpCode == XQSPIPS_FLASH_OPCODE_WRSR) && + (ByteCount == 3)) { + CurrInst->InstSize = 3; + CurrInst->TxOffset = XQSPIPS_TXD_11_OFFSET; + } + } + + /* + * If instruction not present in table + */ + if (Index == ARRAY_SIZE(FlashInst)) { + /* + * Assign current instruction, size and TXD register to be used. + * The InstSize mentioned in case of instructions greater than 4 bytes + * is not the actual size, but is indicative of the TXD register used. + * The remaining bytes of the instruction will be transmitted + * through TXD0 below. + */ + switch (ByteCount % 4) { + case XQSPIPS_SIZE_ONE: + CurrInst->OpCode = Instruction; + CurrInst->InstSize = XQSPIPS_SIZE_ONE; + CurrInst->TxOffset = XQSPIPS_TXD_01_OFFSET; + if (ByteCount > 4) { + SwitchFlag = 1; + } + break; + case XQSPIPS_SIZE_TWO: + CurrInst->OpCode = Instruction; + CurrInst->InstSize = XQSPIPS_SIZE_TWO; + CurrInst->TxOffset = XQSPIPS_TXD_10_OFFSET; + if (ByteCount > 4) { + SwitchFlag = 1; + } + break; + case XQSPIPS_SIZE_THREE: + CurrInst->OpCode = Instruction; + CurrInst->InstSize = XQSPIPS_SIZE_THREE; + CurrInst->TxOffset = XQSPIPS_TXD_11_OFFSET; + if (ByteCount > 4) { + SwitchFlag = 1; + } + break; + default: + CurrInst->OpCode = Instruction; + CurrInst->InstSize = XQSPIPS_SIZE_FOUR; + CurrInst->TxOffset = XQSPIPS_TXD_00_OFFSET; + break; + } + } + + /* + * If the instruction size in not 4 bytes then the data received needs + * to be shifted + */ + if (CurrInst->InstSize != 4) { + InstancePtr->ShiftReadData = 1; + } else { + InstancePtr->ShiftReadData = 0; + } + TransCount = 0; + /* Get the complete command (flash inst + address/data) */ + Data = *((u32 *)InstancePtr->SendBufferPtr); + InstancePtr->SendBufferPtr += CurrInst->InstSize; + InstancePtr->RemainingBytes -= CurrInst->InstSize; + if (InstancePtr->RemainingBytes < 0) { + InstancePtr->RemainingBytes = 0; + } + + /* Write the command to the FIFO */ + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + CurrInst->TxOffset, Data); + ++TransCount; + + /* + * If switching from TXD1/2/3 to TXD0, then start transfer and + * check for FIFO empty + */ + if (SwitchFlag == 1) { + SwitchFlag = 0; + /* + * If, in Manual Start mode, start the transfer. + */ + if (XQspiPs_IsManualStart(InstancePtr)) { + ConfigReg = XQspiPs_ReadReg( + InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET); + ConfigReg |= XQSPIPS_CR_MANSTRT_MASK; + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET, ConfigReg); + } + /* + * Wait for the transfer to finish by polling Tx fifo status. + */ + do { + StatusReg = XQspiPs_ReadReg( + InstancePtr->Config.BaseAddress, + XQSPIPS_SR_OFFSET); + } while ((StatusReg & XQSPIPS_IXR_TXOW_MASK) == 0); + + } + + /* + * Check if manual start is selected and store it in a + * local varibale for reference. This is to avoid reading + * the config register everytime. + */ + IsManualStart = XQspiPs_IsManualStart(InstancePtr); + + /* + * Fill the DTR/FIFO with as many bytes as it will take (or as + * many as we have to send). + */ + while ((InstancePtr->RemainingBytes > 0) && + (TransCount < XQSPIPS_FIFO_DEPTH)) { + /* + * In case of Write fill the Tx FIFO with data to be transmitted. + * In case of Read fill the Tx FIFO with DUMMY bytes. + */ + if (!InstancePtr->RecvBufferPtr) { + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_TXD_00_OFFSET, + *((u32 *)InstancePtr->SendBufferPtr)); + InstancePtr->SendBufferPtr += 4; + } else { + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_TXD_00_OFFSET, + XQSPIPS_DUMMY_TX_DATA); + } + InstancePtr->RemainingBytes -= 4; + if (InstancePtr->RemainingBytes < 0) { + InstancePtr->RemainingBytes = 0; + } + ++TransCount; + } + + while ((InstancePtr->RemainingBytes > 0) || + (InstancePtr->RequestedBytes > 0)) { + + /* + * Fill the TX FIFO with RX threshold no. of entries (or as + * many as we have to send, in case that's less). + */ + while ((InstancePtr->RemainingBytes > 0) && + (TransCount < XQSPIPS_RXFIFO_THRESHOLD_OPT)) { + /* + * In case of Write fill the Tx FIFO with data to be transmitted. + * In case of Read fill the Tx FIFO with DUMMY bytes. + */ + if (!InstancePtr->RecvBufferPtr) { + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_TXD_00_OFFSET, + *((u32 *)InstancePtr->SendBufferPtr)); + InstancePtr->SendBufferPtr += 4; + } else { + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_TXD_00_OFFSET, + XQSPIPS_DUMMY_TX_DATA); + } + InstancePtr->RemainingBytes -= 4; + if (InstancePtr->RemainingBytes < 0) { + InstancePtr->RemainingBytes = 0; + } + ++TransCount; + } + + /* + * If, in Manual Start mode, start the transfer. + */ + if (IsManualStart == TRUE) { + ConfigReg = XQspiPs_ReadReg( + InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET); + ConfigReg |= XQSPIPS_CR_MANSTRT_MASK; + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET, ConfigReg); + } + + /* + * Reset TransCount - this is only used to fill TX FIFO + * in the above loop; + * RxCount is used to keep track of data received + */ + TransCount = 0; + + /* + * Wait for RX FIFO to reach threshold (or) + * TX FIFO to become empty. + * The latter check is required for + * small transfers (<32 words) and + * when the last chunk in a large data transfer is < 32 words. + */ + + do { + StatusReg = XQspiPs_ReadReg( + InstancePtr->Config.BaseAddress, + XQSPIPS_SR_OFFSET); + } while (((StatusReg & XQSPIPS_IXR_TXOW_MASK) == 0) && + ((StatusReg & XQSPIPS_IXR_RXNEMPTY_MASK) == 0)); + + /* + * A transmit has just completed. Process received data + * and check for more data to transmit. + * First get the data received as a result of the + * transmit that just completed. Receive data based on the + * count obtained while filling tx fifo. Always get + * the received data, but only fill the receive + * buffer if it points to something (the upper layer + * software may not care to receive data). + */ + while ((InstancePtr->RequestedBytes > 0) && + (RxCount < XQSPIPS_RXFIFO_THRESHOLD_OPT)) { + u32 Data; + + RxCount++; + + if (InstancePtr->RecvBufferPtr != NULL) { + if (InstancePtr->RequestedBytes < 4) { + Data = XQspiPs_ReadReg(InstancePtr->Config.BaseAddress, + XQSPIPS_RXD_OFFSET); + XQspiPs_GetReadData(InstancePtr, Data, + InstancePtr->RequestedBytes); + } else { + (*(u32 *)InstancePtr->RecvBufferPtr) = + XQspiPs_ReadReg(InstancePtr->Config.BaseAddress, + XQSPIPS_RXD_OFFSET); + InstancePtr->RecvBufferPtr += 4; + InstancePtr->RequestedBytes -= 4; + if (InstancePtr->RequestedBytes < 0) { + InstancePtr->RequestedBytes = 0; + } + } + } else { + Data = XQspiPs_ReadReg(InstancePtr->Config.BaseAddress, + XQSPIPS_RXD_OFFSET); + InstancePtr->RequestedBytes -= 4; + } + } + RxCount = 0; + } + + /* + * If the Slave select lines are being manually controlled, disable + * them because the transfer is complete. + */ + if (XQspiPs_IsManualChipSelect(InstancePtr)) { + ConfigReg = XQspiPs_ReadReg(InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET); + ConfigReg |= XQSPIPS_CR_SSCTRL_MASK; + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET, ConfigReg); + } + + /* + * Clear the busy flag. + */ + InstancePtr->IsBusy = FALSE; + + /* + * Disable the device. + */ + XQspiPs_Disable(InstancePtr); + + /* + * Reset the RX FIFO threshold to one + */ + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_RXWR_OFFSET, XQSPIPS_RXWR_RESET_VALUE); + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* Read the flash in Linear QSPI mode. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* @param RecvBufPtr is a pointer to a buffer for received data. +* @param Address is the starting address within the flash from +* from where data needs to be read. +* @param ByteCount contains the number of bytes to receive. +* +* @return +* - XST_SUCCESS if read is performed +* - XST_FAILURE if Linear mode is not set +* +* @note None. +* +* +******************************************************************************/ +int XQspiPs_LqspiRead(XQspiPs *InstancePtr, u8 *RecvBufPtr, + u32 Address, unsigned ByteCount) +{ + int Status = (int)XST_SUCCESS; + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(RecvBufPtr != NULL); + Xil_AssertNonvoid(ByteCount > 0); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + +#ifndef XPAR_PS7_QSPI_LINEAR_0_S_AXI_BASEADDR +#define XPAR_PS7_QSPI_LINEAR_0_S_AXI_BASEADDR 0xFC000000 +#endif + /* + * Enable the controller + */ + XQspiPs_Enable(InstancePtr); + + if (XQspiPs_GetLqspiConfigReg(InstancePtr) & + XQSPIPS_LQSPI_CR_LINEAR_MASK) { + memcpy((void *)RecvBufPtr, + (const void *)(XPAR_PS7_QSPI_LINEAR_0_S_AXI_BASEADDR + + Address), + (size_t)ByteCount); + Status = (int)XST_SUCCESS; + } else { + Status = (int)XST_FAILURE; + } + + /* + * Disable the controller + */ + XQspiPs_Disable(InstancePtr); + + return Status; +} + +/*****************************************************************************/ +/** +* +* Selects the slave with which the master communicates. +* +* The user is not allowed to select the slave while a transfer is in progress. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* +* @return +* - XST_SUCCESS if the slave is selected or deselected +* successfully. +* - XST_DEVICE_BUSY if a transfer is in progress, slave cannot be +* changed. +* +* @note +* +* This function only sets the slave which will be selected when a transfer +* occurs. The slave is not selected when the QSPI is idle. +* +******************************************************************************/ +int XQspiPs_SetSlaveSelect(XQspiPs *InstancePtr) +{ + u32 ConfigReg; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Do not allow the slave select to change while a transfer is in + * progress. Not thread-safe. + */ + if (InstancePtr->IsBusy) { + return XST_DEVICE_BUSY; + } + + /* + * Select the slave + */ + ConfigReg = XQspiPs_ReadReg(InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET); + ConfigReg &= ~XQSPIPS_CR_SSCTRL_MASK; + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET, ConfigReg); + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* Sets the status callback function, the status handler, which the driver +* calls when it encounters conditions that should be reported to upper +* layer software. The handler executes in an interrupt context, so it must +* minimize the amount of processing performed. One of the following status +* events is passed to the status handler. +* +*
+*
+* XST_SPI_TRANSFER_DONE		The requested data transfer is done
+*
+* XST_SPI_TRANSMIT_UNDERRUN	As a slave device, the master clocked data
+*				but there were none available in the transmit
+*				register/FIFO. This typically means the slave
+*				application did not issue a transfer request
+*				fast enough, or the processor/driver could not
+*				fill the transmit register/FIFO fast enough.
+*
+* XST_SPI_RECEIVE_OVERRUN	The QSPI device lost data. Data was received
+*				but the receive data register/FIFO was full.
+*
+* 
+* @param InstancePtr is a pointer to the XQspiPs instance. +* @param CallBackRef is the upper layer callback reference passed back +* when the callback function is invoked. +* @param FuncPtr is the pointer to the callback function. +* +* @return None. +* +* @note +* +* The handler is called within interrupt context, so it should do its work +* quickly and queue potentially time-consuming work to a task-level thread. +* +******************************************************************************/ +void XQspiPs_SetStatusHandler(XQspiPs *InstancePtr, void *CallBackRef, + XQspiPs_StatusHandler FuncPtr) +{ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(FuncPtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + InstancePtr->StatusHandler = FuncPtr; + InstancePtr->StatusRef = CallBackRef; +} + +/*****************************************************************************/ +/** +* +* This is a stub for the status callback. The stub is here in case the upper +* layers forget to set the handler. +* +* @param CallBackRef is a pointer to the upper layer callback reference +* @param StatusEvent is the event that just occurred. +* @param ByteCount is the number of bytes transferred up until the event +* occurred. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +static void StubStatusHandler(void *CallBackRef, u32 StatusEvent, + unsigned ByteCount) +{ + (void) CallBackRef; + (void) StatusEvent; + (void) ByteCount; + + Xil_AssertVoidAlways(); +} + +/*****************************************************************************/ +/** +* +* The interrupt handler for QSPI interrupts. This function must be connected +* by the user to an interrupt controller. +* +* The interrupts that are handled are: +* +* +* - Data Transmit Register (FIFO) Empty. This interrupt is generated when the +* transmit register or FIFO is empty. The driver uses this interrupt during a +* transmission to continually send/receive data until the transfer is done. +* +* - Data Transmit Register (FIFO) Underflow. This interrupt is generated when +* the QSPI device, when configured as a slave, attempts to read an empty +* DTR/FIFO. An empty DTR/FIFO usually means that software is not giving the +* device data in a timely manner. No action is taken by the driver other than +* to inform the upper layer software of the error. +* +* - Data Receive Register (FIFO) Overflow. This interrupt is generated when the +* QSPI device attempts to write a received byte to an already full DRR/FIFO. +* A full DRR/FIFO usually means software is not emptying the data in a timely +* manner. No action is taken by the driver other than to inform the upper +* layer software of the error. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* +* @return None. +* +* @note +* +* The slave select register is being set to deselect the slave when a transfer +* is complete. +* +******************************************************************************/ +void XQspiPs_InterruptHandler(void *InstancePtr) +{ + XQspiPs *QspiPtr = (XQspiPs *)InstancePtr; + u32 IntrStatus; + u32 ConfigReg; + u32 Data; + u32 TransCount; + u32 Count = 0; + unsigned BytesDone; /* Number of bytes done so far. */ + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(QspiPtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Immediately clear the interrupts in case the ISR causes another + * interrupt to be generated. If we clear at the end of the ISR, + * we may miss newly generated interrupts. This occurs because we + * transmit from within the ISR, which could potentially cause another + * TX_EMPTY interrupt. + */ + IntrStatus = XQspiPs_ReadReg(QspiPtr->Config.BaseAddress, + XQSPIPS_SR_OFFSET); + XQspiPs_WriteReg(QspiPtr->Config.BaseAddress, XQSPIPS_SR_OFFSET, + (IntrStatus & XQSPIPS_IXR_WR_TO_CLR_MASK)); + XQspiPs_WriteReg(QspiPtr->Config.BaseAddress, XQSPIPS_IDR_OFFSET, + XQSPIPS_IXR_TXOW_MASK | XQSPIPS_IXR_RXNEMPTY_MASK | + XQSPIPS_IXR_RXOVR_MASK | XQSPIPS_IXR_TXUF_MASK); + + if ((IntrStatus & XQSPIPS_IXR_TXOW_MASK) || + (IntrStatus & XQSPIPS_IXR_RXNEMPTY_MASK)) { + + /* + * Rx FIFO has just reached threshold no. of entries. + * Read threshold no. of entries from RX FIFO + * Another possiblity of entering this loop is when + * the last byte has been transmitted and TX FIFO is empty, + * in which case, read all the data from RX FIFO. + * Always get the received data, but only fill the + * receive buffer if it is not null (it can be null when + * the device does not care to receive data). + */ + TransCount = QspiPtr->RequestedBytes - QspiPtr->RemainingBytes; + if (TransCount % 4) { + TransCount = TransCount/4 + 1; + } else { + TransCount = TransCount/4; + } + + while ((Count < TransCount) && + (Count < XQSPIPS_RXFIFO_THRESHOLD_OPT)) { + + if (QspiPtr->RecvBufferPtr != NULL) { + if (QspiPtr->RequestedBytes < 4) { + Data = XQspiPs_ReadReg(QspiPtr->Config.BaseAddress, + XQSPIPS_RXD_OFFSET); + XQspiPs_GetReadData(QspiPtr, Data, + QspiPtr->RequestedBytes); + } else { + (*(u32 *)QspiPtr->RecvBufferPtr) = + XQspiPs_ReadReg(QspiPtr->Config.BaseAddress, + XQSPIPS_RXD_OFFSET); + QspiPtr->RecvBufferPtr += 4; + QspiPtr->RequestedBytes -= 4; + if (QspiPtr->RequestedBytes < 0) { + QspiPtr->RequestedBytes = 0; + } + } + } else { + XQspiPs_ReadReg(QspiPtr->Config.BaseAddress, + XQSPIPS_RXD_OFFSET); + QspiPtr->RequestedBytes -= 4; + if (QspiPtr->RequestedBytes < 0) { + QspiPtr->RequestedBytes = 0; + } + + } + Count++; + } + Count = 0; + /* + * Interrupt asserted as TX_OW got asserted + * See if there is more data to send. + * Fill TX FIFO with RX threshold no. of entries or + * remaining entries (in case that is less than threshold) + */ + while ((QspiPtr->RemainingBytes > 0) && + (Count < XQSPIPS_RXFIFO_THRESHOLD_OPT)) { + /* + * Send more data. + * In case of Write fill the Tx FIFO with data to be transmitted. + * In case of Read fill the Tx FIFO with DUMMY bytes. + */ + if (!QspiPtr->RecvBufferPtr) { + XQspiPs_WriteReg(QspiPtr->Config.BaseAddress, + XQSPIPS_TXD_00_OFFSET, + *((u32 *)QspiPtr->SendBufferPtr)); + QspiPtr->SendBufferPtr += 4; + } else { + XQspiPs_WriteReg(QspiPtr->Config.BaseAddress, + XQSPIPS_TXD_00_OFFSET, + XQSPIPS_DUMMY_TX_DATA); + } + QspiPtr->RemainingBytes -= 4; + if (QspiPtr->RemainingBytes < 0) { + QspiPtr->RemainingBytes = 0; + } + + Count++; + } + + if ((QspiPtr->RemainingBytes == 0) && + (QspiPtr->RequestedBytes == 0)) { + /* + * No more data to send. Disable the interrupt + * and inform the upper layer software that the + * transfer is done. The interrupt will be re-enabled + * when another transfer is initiated. + */ + XQspiPs_WriteReg(QspiPtr->Config.BaseAddress, + XQSPIPS_IDR_OFFSET, + XQSPIPS_IXR_RXNEMPTY_MASK | + XQSPIPS_IXR_TXOW_MASK | + XQSPIPS_IXR_RXOVR_MASK | + XQSPIPS_IXR_TXUF_MASK); + + /* + * If the Slave select is being manually controlled, + * disable it because the transfer is complete. + */ + if (XQspiPs_IsManualChipSelect(InstancePtr)) { + ConfigReg = XQspiPs_ReadReg( + QspiPtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET); + ConfigReg |= XQSPIPS_CR_SSCTRL_MASK; + XQspiPs_WriteReg(QspiPtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET, + ConfigReg); + } + + /* + * Clear the busy flag. + */ + QspiPtr->IsBusy = FALSE; + + /* + * Disable the device. + */ + XQspiPs_Disable(QspiPtr); + + /* + * Reset the RX FIFO threshold to one + */ + XQspiPs_WriteReg(QspiPtr->Config.BaseAddress, + XQSPIPS_RXWR_OFFSET, XQSPIPS_RXWR_RESET_VALUE); + + QspiPtr->StatusHandler(QspiPtr->StatusRef, + XST_SPI_TRANSFER_DONE, + QspiPtr->RequestedBytes); + } else { + /* + * Enable the TXOW interrupt. + */ + XQspiPs_WriteReg(QspiPtr->Config.BaseAddress, + XQSPIPS_IER_OFFSET, + XQSPIPS_IXR_RXNEMPTY_MASK | + XQSPIPS_IXR_TXOW_MASK | + XQSPIPS_IXR_RXOVR_MASK | + XQSPIPS_IXR_TXUF_MASK); + /* + * If, in Manual Start mode, start the transfer. + */ + if (XQspiPs_IsManualStart(QspiPtr)) { + ConfigReg = XQspiPs_ReadReg( + QspiPtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET); + ConfigReg |= XQSPIPS_CR_MANSTRT_MASK; + XQspiPs_WriteReg( + QspiPtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET, ConfigReg); + } + } + } + + /* + * Check for overflow and underflow errors. + */ + if (IntrStatus & XQSPIPS_IXR_RXOVR_MASK) { + BytesDone = QspiPtr->RequestedBytes - QspiPtr->RemainingBytes; + QspiPtr->IsBusy = FALSE; + + /* + * If the Slave select lines is being manually controlled, + * disable it because the transfer is complete. + */ + if (XQspiPs_IsManualChipSelect(InstancePtr)) { + ConfigReg = XQspiPs_ReadReg( + QspiPtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET); + ConfigReg |= XQSPIPS_CR_SSCTRL_MASK; + XQspiPs_WriteReg(QspiPtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET, ConfigReg); + } + + /* + * Disable the device. + */ + XQspiPs_Disable(QspiPtr); + + /* + * Reset the RX FIFO threshold to one + */ + XQspiPs_WriteReg(QspiPtr->Config.BaseAddress, + XQSPIPS_RXWR_OFFSET, XQSPIPS_RXWR_RESET_VALUE); + + QspiPtr->StatusHandler(QspiPtr->StatusRef, + XST_SPI_RECEIVE_OVERRUN, BytesDone); + } + + if (IntrStatus & XQSPIPS_IXR_TXUF_MASK) { + BytesDone = QspiPtr->RequestedBytes - QspiPtr->RemainingBytes; + + QspiPtr->IsBusy = FALSE; + /* + * If the Slave select lines is being manually controlled, + * disable it because the transfer is complete. + */ + if (XQspiPs_IsManualChipSelect(InstancePtr)) { + ConfigReg = XQspiPs_ReadReg( + QspiPtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET); + ConfigReg |= XQSPIPS_CR_SSCTRL_MASK; + XQspiPs_WriteReg(QspiPtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET, ConfigReg); + } + + /* + * Disable the device. + */ + XQspiPs_Disable(QspiPtr); + + /* + * Reset the RX FIFO threshold to one + */ + XQspiPs_WriteReg(QspiPtr->Config.BaseAddress, + XQSPIPS_RXWR_OFFSET, XQSPIPS_RXWR_RESET_VALUE); + + QspiPtr->StatusHandler(QspiPtr->StatusRef, + XST_SPI_TRANSMIT_UNDERRUN, BytesDone); + } +} + + +/*****************************************************************************/ +/** +* +* Copies data from Data to the Receive buffer. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* @param Data is the data which needs to be copied to the Rx buffer. +* @param Size is the number of bytes to be copied to the Receive buffer. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +static void XQspiPs_GetReadData(XQspiPs *InstancePtr, u32 Data, u8 Size) +{ + u8 DataByte3; + + if (InstancePtr->RecvBufferPtr) { + switch (Size) { + case 1: + if (InstancePtr->ShiftReadData == 1) { + *((u8 *)InstancePtr->RecvBufferPtr) = + ((Data & 0xFF000000) >> 24); + } else { + *((u8 *)InstancePtr->RecvBufferPtr) = + (Data & 0xFF); + } + InstancePtr->RecvBufferPtr += 1; + break; + case 2: + if (InstancePtr->ShiftReadData == 1) { + *((u16 *)InstancePtr->RecvBufferPtr) = + ((Data >> 16) & 0xFF00) | + ((Data >> 8) & 0xFF); + } else { + *((u16 *)InstancePtr->RecvBufferPtr) = + (Data & 0xFFFF); + } + InstancePtr->RecvBufferPtr += 2; + break; + case 3: + if (InstancePtr->ShiftReadData == 1) { + *((u16 *)InstancePtr->RecvBufferPtr) = + ((Data & 0x00FFFF00) >> 8); + InstancePtr->RecvBufferPtr += 2; + DataByte3 = ((Data & 0xFF000000) >> 24); + *((u8 *)InstancePtr->RecvBufferPtr) = DataByte3; + } else { + *((u16 *)InstancePtr->RecvBufferPtr) = + (Data & 0xFFFF); + InstancePtr->RecvBufferPtr += 2; + DataByte3 = ((Data & 0x00FF0000) >> 16); + *((u8 *)InstancePtr->RecvBufferPtr) = DataByte3; + } + InstancePtr->RecvBufferPtr += 1; + break; + default: + /* This will never execute */ + break; + } + } + InstancePtr->ShiftReadData = 0; + InstancePtr->RequestedBytes -= Size; + if (InstancePtr->RequestedBytes < 0) { + InstancePtr->RequestedBytes = 0; + } +} +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/qspips_v3_6/src/xqspips.h b/df_datalink/bsp/ps7_cortexa9_0/libsrc/qspips_v3_6/src/xqspips.h new file mode 100644 index 0000000..0255bc2 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/qspips_v3_6/src/xqspips.h @@ -0,0 +1,804 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xqspips.h +* @addtogroup qspips_v3_6 +* @{ +* @details +* +* This file contains the implementation of the XQspiPs driver. It supports only +* master mode. User documentation for the driver functions is contained in this +* file in the form of comment blocks at the front of each function. +* +* A QSPI device connects to an QSPI bus through a 4-wire serial interface. +* The QSPI bus is a full-duplex, synchronous bus that facilitates communication +* between one master and one slave. The device is always full-duplex, +* which means that for every byte sent, one is received, and vice-versa. +* The master controls the clock, so it can regulate when it wants to +* send or receive data. The slave is under control of the master, it must +* respond quickly since it has no control of the clock and must send/receive +* data as fast or as slow as the master does. +* +* Linear Mode +* The Linear Quad-SPI Controller extends the existing Quad-SPI Controller�s +* functionality by adding a linear addressing scheme that allows the SPI flash +* memory subsystem to behave like a typical ROM device. The new feature hides +* the normal SPI protocol from a master reading from the SPI flash memory. The +* feature improves both the user friendliness and the overall read memory +* throughput over that of the current Quad-SPI Controller by lessening the +* amount of software overheads required and by the use of the faster AXI +* interface. +* +* Initialization & Configuration +* +* The XQspiPs_Config structure is used by the driver to configure itself. This +* configuration structure is typically created by the tool-chain based on HW +* build properties. +* +* To support multiple runtime loading and initialization strategies employed by +* various operating systems, the driver instance can be initialized in the +* following way: +* - XQspiPs_LookupConfig(DeviceId) - Use the device identifier to find +* static configuration structure defined in xqspips_g.c. This is setup +* by the tools. For some operating systems the config structure will be +* initialized by the software and this call is not needed. +* - XQspiPs_CfgInitialize(InstancePtr, CfgPtr, EffectiveAddr) - Uses a +* configuration structure provided by the caller. If running in a system +* with address translation, the provided virtual memory base address +* replaces the physical address present in the configuration structure. +* +* Multiple Masters +* +* More than one master can exist, but arbitration is the responsibility of +* the higher layer software. The device driver does not perform any type of +* arbitration. +* +* Modes of Operation +* +* There are four modes to perform a data transfer and the selection of a mode +* is based on Chip Select(CS) and Start. These two options individually, can +* be controlled either by software(Manual) or hardware(Auto). +* - Auto CS: Chip select is automatically asserted as soon as the first word +* is written into the TXFIFO and de asserted when the TXFIFO becomes +* empty +* - Manual CS: Software must assert and de assert CS. +* - Auto Start: Data transmission starts as soon as there is data in the +* TXFIFO and stalls when the TXFIFO is empty +* - Manual Start: Software must start data transmission at the beginning of +* the transaction or whenever the TXFIFO has become empty +* +* The preferred combination is Manual CS and Auto Start. +* In this combination, the software asserts CS before loading any data into +* TXFIFO. In Auto Start mode, whenever data is in TXFIFO, controller sends it +* out until TXFIFO becomes empty. The software reads the RXFIFO whenever the +* data is available. If no further data, software disables CS. +* +* Risks/challenges of other combinations: +* - Manual CS and Manual Start: Manual Start bit should be set after each +* TXFIFO write otherwise there could be a race condition where the TXFIFO +* becomes empty before the new word is written. In that case the +* transmission stops. +* - Auto CS with Manual or Auto Start: It is very difficult for software to +* keep the TXFIFO filled. Whenever the TXFIFO runs empty, CS is de asserted. +* This results in a single transaction to be split into multiple pieces each +* with its own chip select. This will result in garbage data to be sent. +* +* Interrupts +* +* The user must connect the interrupt handler of the driver, +* XQspiPs_InterruptHandler, to an interrupt system such that it will be +* called when an interrupt occurs. This function does not save and restore +* the processor context such that the user must provide this processing. +* +* The driver handles the following interrupts: +* - Data Transmit Register/FIFO Underflow +* - Data Receive Register/FIFO Not Empty +* - Data Transmit Register/FIFO Overwater +* - Data Receive Register/FIFO Overrun +* +* The Data Transmit Register/FIFO Overwater interrupt -- indicates that the +* QSPI device has transmitted the data available to transmit, and now its data +* register and FIFO is ready to accept more data. The driver uses this +* interrupt to indicate progress while sending data. The driver may have +* more data to send, in which case the data transmit register and FIFO is +* filled for subsequent transmission. When this interrupt arrives and all +* the data has been sent, the driver invokes the status callback with a +* value of XST_SPI_TRANSFER_DONE to inform the upper layer software that +* all data has been sent. +* +* The Data Transmit Register/FIFO Underflow interrupt -- indicates that, +* as slave, the QSPI device was required to transmit but there was no data +* available to transmit in the transmit register (or FIFO). This may not +* be an error if the master is not expecting data. But in the case where +* the master is expecting data, this serves as a notification of such a +* condition. The driver reports this condition to the upper layer +* software through the status handler. +* +* The Data Receive Register/FIFO Overrun interrupt -- indicates that the QSPI +* device received data and subsequently dropped the data because the data +* receive register and FIFO was full. The driver reports this condition to the +* upper layer software through the status handler. This likely indicates a +* problem with the higher layer protocol, or a problem with the slave +* performance. +* +* +* Polled Operation +* +* Transfer in polled mode is supported through a separate interface function +* XQspiPs_PolledTransfer(). Unlike the transfer function in the interrupt mode, +* this function blocks until all data has been sent/received. +* +* Device Busy +* +* Some operations are disallowed when the device is busy. The driver tracks +* whether a device is busy. The device is considered busy when a data transfer +* request is outstanding, and is considered not busy only when that transfer +* completes (or is aborted with a mode fault error). +* +* Device Configuration +* +* The device can be configured in various ways during the FPGA implementation +* process. Configuration parameters are stored in the xqspips_g.c file or +* passed in via XQspiPs_CfgInitialize(). A table is defined where each entry +* contains configuration information for an QSPI device, including the base +* address for the device. +* +* RTOS Independence +* +* This driver is intended to be RTOS and processor independent. It works with +* physical addresses only. Any needs for dynamic memory management, threads or +* thread mutual exclusion, virtual memory, or cache control must be satisfied +* by the layer above this driver. +* +* NOTE: This driver was always tested with endianess set to little-endian. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- -----------------------------------------------
+* 1.00a sdm 11/25/10 First release, based on the PS SPI driver...
+* 1.01a sdm 11/22/11 Added TCL file for generating QSPI parameters
+*		     in xparameters.h
+* 2.00a kka 07/25/12 Added a few register defines for CR 670297
+* 		     Removed code related to mode fault for CR 671468
+*		     The XQspiPs_SetSlaveSelect has been modified to remove
+*		     the argument of the slave select as the QSPI controller
+*		     only supports one slave.
+* 		     XQspiPs_GetSlaveSelect API has been removed
+* 		     Added a flag ShiftReadData to the instance structure
+*.		     and is used in the XQspiPs_GetReadData API.
+*		     The ShiftReadData Flag indicates whether the data
+*		     read from the Rx FIFO needs to be shifted
+*		     in cases where the data is less than 4  bytes
+* 		     Removed the selection for the following options:
+*		     Master mode (XQSPIPS_MASTER_OPTION) and
+*		     Flash interface mode (XQSPIPS_FLASH_MODE_OPTION) option
+*		     as the QSPI driver supports the Master mode
+*		     and Flash Interface mode and doesnot support
+*		     Slave mode or the legacy mode.
+*		     Modified the XQspiPs_PolledTransfer and XQspiPs_Transfer
+*		     APIs so that the last argument (IsInst) specifying whether
+*		     it is instruction or data has been removed. The first byte
+*		     in the SendBufPtr argument of these APIs specify the
+*		     instruction to be sent to the Flash Device.
+*		     This version of the driver fixes CRs 670197/663787/
+*		     670297/671468.
+* 		     Added the option for setting the Holdb_dr bit in the
+*		     configuration options, XQSPIPS_HOLD_B_DRIVE_OPTION
+*		     is the option to be used for setting this bit in the
+*		     configuration register.
+*		     The XQspiPs_PolledTransfer function has been updated
+*		     to fill the data to fifo depth.
+* 2.01a sg  02/03/13 Added flash opcodes for DUAL_IO_READ,QUAD_IO_READ.
+*		     Added macros for Set/Get Rx Watermark. Changed QSPI
+*		     Enable/Disable macro argument from BaseAddress to
+*		     Instance Pointer. Added DelayNss argument to SetDelays
+*		     and GetDelays API's.
+*		     Created macros XQspiPs_IsManualStart and
+*		     XQspiPs_IsManualChipSelect.
+*		     Changed QSPI transfer logic for polled and interrupt
+*		     modes to be based on filled tx fifo count and receive
+*		     based on it. RXNEMPTY interrupt is not used.
+*		     Added assertions to XQspiPs_LqspiRead function.
+*		     SetDelays and GetDelays API's include DelayNss parameter.
+*		     Added defines for DelayNss,Rx Watermark,Interrupts
+*		     which need write to clear. Removed Read zeros mask from
+*		     LQSPI Config register. Renamed Fixed burst error to
+*		     data FSM error in  LQSPI Status register.
+*
+* 2.02a hk  05/07/13 Added ConnectionMode to config structure.
+*			 Corresponds to C_QSPI_MODE - 0:Single, 1:Stacked, 2:Parallel
+*			 Added enable and disable to the XQspiPs_LqspiRead() function
+*			 Removed XQspi_Reset() in Set_Options() function when
+*			 LQSPI_MODE_OPTION is set.
+*            Added instructions for bank selection, die erase and
+*            flag status register to the flash instruction table
+*            Handling for instructions not in flash instruction
+*			 table added. Checking for Tx FIFO empty when switching from
+*			 TXD1/2/3 to TXD0 added. If WRSR instruction is sent with
+*            byte count 3 (spansion), instruction size and TXD register
+*			 changed accordingly. CR# 712502 and 703869.
+*            Added prefix to constant definitions for ConnectionMode
+*            Added (#ifdef linear base address) in the Linear read function.
+*            Changed  XPAR_XQSPIPS_0_LINEAR_BASEADDR to
+*            XPAR_PS7_QSPI_LINEAR_0_S_AXI_BASEADDR in
+*            XQspiPs_LqspiRead function. Fix for CR#718141.
+*
+* 2.03a hk  09/17/13 Modified polled and interrupt transfers to make use of
+*                    thresholds. This is to improve performance.
+*                    Added API's for QSPI reset and
+*                    linear mode initialization for boot.
+*                    Added RX and TX threshold reset to one in XQspiPs_Abort.
+*                    Added RX threshold reset(1) after transfer in polled and
+*                    interrupt transfers. Made changes to make sure threshold
+*                    change is done only when no transfer is in progress.
+*                    Updated linear init API for parallel and stacked modes.
+*                    CR#737760.
+* 3.1   hk  08/13/14 When writing to the configuration register, set/reset
+*                    required bits leaving reserved bits untouched. CR# 796813.
+* 3.2	sk	02/05/15 Add SLCR reset in abort function as a workaround because
+* 					 controller does not update FIFO status flags as expected
+* 					 when thresholds are used.
+* 3.3   sk  11/07/15 Modified the API prototypes according to MISRAC standards
+*                    to remove compilation warnings. CR# 868893.
+*       ms  03/17/17 Added readme.txt file in examples folder for doxygen
+*                    generation.
+*       ms  04/05/17 Modified Comment lines in functions of qspips
+*                    examples to recognize it as documentation block
+*                    and modified filename tag in
+*                    xqspips_dual_flash_stack_lqspi_example.c to include it in
+*                    doxygen examples.
+* 3.4   nsk 31/07/17 Added QSPI_BUS_WIDTH parameter in xparameters.h file
+* 3.5	tjs 08/21/18 Fixed compilation warnings for the ARMCC.
+* 3.5	tjs 07/16/18 Added support for low density ISSI flash parts.
+* 3.6   akm 03/28/19 Fixed memory leak issue while reading from qspi.(CR#1016357)
+* 3.6   akm 04/15/19 Modified FlashQuadEnable, FlashWrie and FlashErase APIs,
+*                    to wait for the on going operation to complete before
+*                    performing the next operation.
+* 3.6   akm 04/15/19 Modified the mask in XQspiPs_GetReadData() API to retrieve
+*                    configuration register values of both the Flashes in dual
+*                    parellel connection.
+*
+* 
+* +******************************************************************************/ +#ifndef XQSPIPS_H /* prevent circular inclusions */ +#define XQSPIPS_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xstatus.h" +#include "xqspips_hw.h" +#include + +/************************** Constant Definitions *****************************/ + +/** @name Configuration options + * + * The following options are supported to enable/disable certain features of + * an QSPI device. Each of the options is a bit mask, so more than one may be + * specified. + * + * + * The Active Low Clock option configures the device's clock polarity. + * Setting this option means the clock is active low and the SCK signal idles + * high. By default, the clock is active high and SCK idles low. + * + * The Clock Phase option configures the QSPI device for one of two + * transfer formats. A clock phase of 0, the default, means data is valid on + * the first SCK edge (rising or falling) after the slave select (SS) signal + * has been asserted. A clock phase of 1 means data is valid on the second SCK + * edge (rising or falling) after SS has been asserted. + * + * + * The QSPI Force Slave Select option is used to enable manual control of + * the slave select signal. + * 0: The SPI_SS signal is controlled by the QSPI controller during + * transfers. (Default) + * 1: The SPI_SS signal is forced active (driven low) regardless of any + * transfers in progress. + * + * NOTE: The driver will handle setting and clearing the Slave Select when + * the user sets the "FORCE_SSELECT_OPTION". Using this option will allow the + * QSPI clock to be set to a faster speed. If the QSPI clock is too fast, the + * processor cannot empty and refill the FIFOs before the TX FIFO is empty + * When the QSPI hardware is controlling the Slave Select signals, this + * will cause slave to be de-selected and terminate the transfer. + * + * The Manual Start option is used to enable manual control of + * the Start command to perform data transfer. + * 0: The Start command is controlled by the QSPI controller during + * transfers(Default). Data transmission starts as soon as there is data in + * the TXFIFO and stalls when the TXFIFO is empty + * 1: The Start command must be issued by software to perform data transfer. + * Bit 15 of Configuration register is used to issue Start command. This bit + * must be set whenever TXFIFO is filled with new data. + * + * NOTE: The driver will set the Manual Start Enable bit in Configuration + * Register, if Manual Start option is selected. Software will issue + * Manual Start command whenever TXFIFO is filled with data. When there is + * no further data, driver will clear the Manual Start Enable bit. + * + * @{ + */ +#define XQSPIPS_CLK_ACTIVE_LOW_OPTION 0x2 /**< Active Low Clock option */ +#define XQSPIPS_CLK_PHASE_1_OPTION 0x4 /**< Clock Phase one option */ +#define XQSPIPS_FORCE_SSELECT_OPTION 0x10 /**< Force Slave Select */ +#define XQSPIPS_MANUAL_START_OPTION 0x20 /**< Manual Start enable */ +#define XQSPIPS_LQSPI_MODE_OPTION 0x80 /**< Linear QPSI mode */ +#define XQSPIPS_HOLD_B_DRIVE_OPTION 0x100 /**< Drive HOLD_B Pin */ +/*@}*/ + + +/** @name QSPI Clock Prescaler options + * The QSPI Clock Prescaler Configuration bits are used to program master mode + * bit rate. The bit rate can be programmed in divide-by-two decrements from + * pclk/2 to pclk/256. + * + * @{ + */ +#define XQSPIPS_CLK_PRESCALE_2 0x00 /**< PCLK/2 Prescaler */ +#define XQSPIPS_CLK_PRESCALE_4 0x01 /**< PCLK/4 Prescaler */ +#define XQSPIPS_CLK_PRESCALE_8 0x02 /**< PCLK/8 Prescaler */ +#define XQSPIPS_CLK_PRESCALE_16 0x03 /**< PCLK/16 Prescaler */ +#define XQSPIPS_CLK_PRESCALE_32 0x04 /**< PCLK/32 Prescaler */ +#define XQSPIPS_CLK_PRESCALE_64 0x05 /**< PCLK/64 Prescaler */ +#define XQSPIPS_CLK_PRESCALE_128 0x06 /**< PCLK/128 Prescaler */ +#define XQSPIPS_CLK_PRESCALE_256 0x07 /**< PCLK/256 Prescaler */ + +/*@}*/ + + +/** @name Callback events + * + * These constants specify the handler events that are passed to + * a handler from the driver. These constants are not bit masks such that + * only one will be passed at a time to the handler. + * + * @{ + */ +#define XQSPIPS_EVENT_TRANSFER_DONE 2 /**< Transfer done */ +#define XQSPIPS_EVENT_TRANSMIT_UNDERRUN 3 /**< TX FIFO empty */ +#define XQSPIPS_EVENT_RECEIVE_OVERRUN 4 /**< Receive data loss because + * RX FIFO full + */ +/*@}*/ + +/** @name Flash commands + * + * The following constants define most of the commands supported by flash + * devices. Users can add more commands supported by the flash devices + * + * @{ + */ +#define XQSPIPS_FLASH_OPCODE_WRSR 0x01 /* Write status register */ +#define XQSPIPS_FLASH_OPCODE_PP 0x02 /* Page program */ +#define XQSPIPS_FLASH_OPCODE_NORM_READ 0x03 /* Normal read data bytes */ +#define XQSPIPS_FLASH_OPCODE_WRDS 0x04 /* Write disable */ +#define XQSPIPS_FLASH_OPCODE_RDSR1 0x05 /* Read status register 1 */ +#define XQSPIPS_FLASH_OPCODE_WREN 0x06 /* Write enable */ +#define XQSPIPS_FLASH_OPCODE_FAST_READ 0x0B /* Fast read data bytes */ +#define XQSPIPS_FLASH_OPCODE_BE_4K 0x20 /* Erase 4KiB block */ +#define XQSPIPS_FLASH_OPCODE_RDSR2 0x35 /* Read status register 2 */ +#define XQSPIPS_FLASH_OPCODE_DUAL_READ 0x3B /* Dual read data bytes */ +#define XQSPIPS_FLASH_OPCODE_BE_32K 0x52 /* Erase 32KiB block */ +#define XQSPIPS_FLASH_OPCODE_QUAD_READ 0x6B /* Quad read data bytes */ +#define XQSPIPS_FLASH_OPCODE_ERASE_SUS 0x75 /* Erase suspend */ +#define XQSPIPS_FLASH_OPCODE_ERASE_RES 0x7A /* Erase resume */ +#define XQSPIPS_FLASH_OPCODE_RDID 0x9F /* Read JEDEC ID */ +#define XQSPIPS_FLASH_OPCODE_BE 0xC7 /* Erase whole flash block */ +#define XQSPIPS_FLASH_OPCODE_SE 0xD8 /* Sector erase (usually 64KB)*/ +#define XQSPIPS_FLASH_OPCODE_DUAL_IO_READ 0xBB /* Read data using Dual I/O */ +#define XQSPIPS_FLASH_OPCODE_QUAD_IO_READ 0xEB /* Read data using Quad I/O */ +#define XQSPIPS_FLASH_OPCODE_BRWR 0x17 /* Bank Register Write */ +#define XQSPIPS_FLASH_OPCODE_BRRD 0x16 /* Bank Register Read */ +/* Extende Address Register Write - Micron's equivalent of Bank Register */ +#define XQSPIPS_FLASH_OPCODE_EARWR 0xC5 +/* Extende Address Register Read - Micron's equivalent of Bank Register */ +#define XQSPIPS_FLASH_OPCODE_EARRD 0xC8 +#define XQSPIPS_FLASH_OPCODE_DIE_ERASE 0xC4 +#define XQSPIPS_FLASH_OPCODE_READ_FLAG_SR 0x70 +#define XQSPIPS_FLASH_OPCODE_CLEAR_FLAG_SR 0x50 +#define XQSPIPS_FLASH_OPCODE_READ_LOCK_REG 0xE8 /* Lock Reg Read */ +#define XQSPIPS_FLASH_OPCODE_WRITE_LOCK_REG 0xE5 /* Lock Reg Write */ + +/*@}*/ + +/** @name Instruction size + * + * The following constants define numbers 1 to 4. + * Used to identify whether TXD0,1,2 or 3 is to be used. + * + * @{ + */ +#define XQSPIPS_SIZE_ONE 1 +#define XQSPIPS_SIZE_TWO 2 +#define XQSPIPS_SIZE_THREE 3 +#define XQSPIPS_SIZE_FOUR 4 + +/*@}*/ + +/** @name ConnectionMode + * + * The following constants are the possible values of ConnectionMode in + * Config structure. + * + * @{ + */ +#define XQSPIPS_CONNECTION_MODE_SINGLE 0 +#define XQSPIPS_CONNECTION_MODE_STACKED 1 +#define XQSPIPS_CONNECTION_MODE_PARALLEL 2 + +/*@}*/ + +/** @name FIFO threshold value + * + * This is the Rx FIFO threshold (in words) that was found to be most + * optimal in terms of performance + * + * @{ + */ +#define XQSPIPS_RXFIFO_THRESHOLD_OPT 32 + +/*@}*/ + +/**************************** Type Definitions *******************************/ +/** + * The handler data type allows the user to define a callback function to + * handle the asynchronous processing for the QSPI device. The application + * using this driver is expected to define a handler of this type to support + * interrupt driven mode. The handler executes in an interrupt context, so + * only minimal processing should be performed. + * + * @param CallBackRef is the callback reference passed in by the upper + * layer when setting the callback functions, and passed back to + * the upper layer when the callback is invoked. Its type is + * not important to the driver, so it is a void pointer. + * @param StatusEvent holds one or more status events that have occurred. + * See the XQspiPs_SetStatusHandler() for details on the status + * events that can be passed in the callback. + * @param ByteCount indicates how many bytes of data were successfully + * transferred. This may be less than the number of bytes + * requested if the status event indicates an error. + */ +typedef void (*XQspiPs_StatusHandler) (void *CallBackRef, u32 StatusEvent, + unsigned ByteCount); + +/** + * This typedef contains configuration information for the device. + */ +typedef struct { + u16 DeviceId; /**< Unique ID of device */ + u32 BaseAddress; /**< Base address of the device */ + u32 InputClockHz; /**< Input clock frequency */ + u8 ConnectionMode; /**< Single, Stacked and Parallel mode */ +} XQspiPs_Config; + +/** + * The XQspiPs driver instance data. The user is required to allocate a + * variable of this type for every QSPI device in the system. A pointer + * to a variable of this type is then passed to the driver API functions. + */ +typedef struct { + XQspiPs_Config Config; /**< Configuration structure */ + u32 IsReady; /**< Device is initialized and ready */ + + u8 *SendBufferPtr; /**< Buffer to send (state) */ + u8 *RecvBufferPtr; /**< Buffer to receive (state) */ + int RequestedBytes; /**< Number of bytes to transfer (state) */ + int RemainingBytes; /**< Number of bytes left to transfer(state) */ + u32 IsBusy; /**< A transfer is in progress (state) */ + XQspiPs_StatusHandler StatusHandler; + void *StatusRef; /**< Callback reference for status handler */ + u32 ShiftReadData; /**< Flag to indicate whether the data + * read from the Rx FIFO needs to be shifted + * in cases where the data is less than 4 + * bytes + */ +} XQspiPs; + +/***************** Macros (Inline Functions) Definitions *********************/ + +/****************************************************************************/ +/* +* +* Check in OptionsTable if Manual Start Option is enabled or disabled. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* +* @return +* - TRUE if option is set +* - FALSE if option is not set +* +* @note C-Style signature: +* u8 XQspiPs_IsManualStart(XQspiPs *InstancePtr); +* +*****************************************************************************/ +#define XQspiPs_IsManualStart(InstancePtr) \ + ((XQspiPs_GetOptions(InstancePtr) & \ + XQSPIPS_MANUAL_START_OPTION) ? TRUE : FALSE) + +/****************************************************************************/ +/* +* +* Check in OptionsTable if Manual Chip Select Option is enabled or disabled. +* +* @param InstancePtr is a pointer to the XSpiPs instance. +* +* @return +* - TRUE if option is set +* - FALSE if option is not set +* +* @note C-Style signature: +* u8 XQspiPs_IsManualChipSelect(XQspiPs *InstancePtr); +* +*****************************************************************************/ +#define XQspiPs_IsManualChipSelect(InstancePtr) \ + ((XQspiPs_GetOptions(InstancePtr) & \ + XQSPIPS_FORCE_SSELECT_OPTION) ? TRUE : FALSE) + +/****************************************************************************/ +/** +* +* Set the contents of the slave idle count register. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* @param RegisterValue is the value to be written, valid values are +* 0-255. +* +* @return None +* +* @note C-Style signature: +* void XQspiPs_SetSlaveIdle(XQspiPs *InstancePtr, +* u32 RegisterValue) +* +*****************************************************************************/ +#define XQspiPs_SetSlaveIdle(InstancePtr, RegisterValue) \ + XQspiPs_Out32(((InstancePtr)->Config.BaseAddress) + \ + XQSPIPS_SICR_OFFSET, (RegisterValue)) + +/****************************************************************************/ +/** +* +* Get the contents of the slave idle count register. Use the XQSPIPS_SICR_* +* constants defined in xqspips_hw.h to interpret the bit-mask returned. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* +* @return An 8-bit value representing Slave Idle Count. +* +* @note C-Style signature: +* u32 XQspiPs_GetSlaveIdle(XQspiPs *InstancePtr) +* +*****************************************************************************/ +#define XQspiPs_GetSlaveIdle(InstancePtr) \ + XQspiPs_In32(((InstancePtr)->Config.BaseAddress) + \ + XQSPIPS_SICR_OFFSET) + +/****************************************************************************/ +/** +* +* Set the contents of the transmit FIFO watermark register. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* @param RegisterValue is the value to be written, valid values are 1-63. +* +* @return None. +* +* @note C-Style signature: +* void XQspiPs_SetTXWatermark(XQspiPs *InstancePtr, +* u32 RegisterValue) +* +*****************************************************************************/ +#define XQspiPs_SetTXWatermark(InstancePtr, RegisterValue) \ + XQspiPs_Out32(((InstancePtr)->Config.BaseAddress) + \ + XQSPIPS_TXWR_OFFSET, (RegisterValue)) + +/****************************************************************************/ +/** +* +* Get the contents of the transmit FIFO watermark register. +* Valid values are in the range 1-63. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* +* @return A 6-bit value representing Tx Watermark level. +* +* @note C-Style signature: +* u32 XQspiPs_GetTXWatermark(XQspiPs *InstancePtr) +* +*****************************************************************************/ +#define XQspiPs_GetTXWatermark(InstancePtr) \ + XQspiPs_In32((InstancePtr->Config.BaseAddress) + XQSPIPS_TXWR_OFFSET) + +/****************************************************************************/ +/** +* +* Set the contents of the receive FIFO watermark register. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* @param RegisterValue is the value to be written, valid values are 1-63. +* +* @return None. +* +* @note C-Style signature: +* void XQspiPs_SetRXWatermark(XQspiPs *InstancePtr, +* u32 RegisterValue) +* +*****************************************************************************/ +#define XQspiPs_SetRXWatermark(InstancePtr, RegisterValue) \ + XQspiPs_Out32(((InstancePtr)->Config.BaseAddress) + \ + XQSPIPS_RXWR_OFFSET, (RegisterValue)) + +/****************************************************************************/ +/** +* +* Get the contents of the receive FIFO watermark register. +* Valid values are in the range 1-63. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* +* @return A 6-bit value representing Rx Watermark level. +* +* @note C-Style signature: +* u32 XQspiPs_GetRXWatermark(XQspiPs *InstancePtr) +* +*****************************************************************************/ +#define XQspiPs_GetRXWatermark(InstancePtr) \ + XQspiPs_In32((InstancePtr->Config.BaseAddress) + XQSPIPS_RXWR_OFFSET) + +/****************************************************************************/ +/** +* +* Enable the device and uninhibit master transactions. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* +* @return None. +* +* @note C-Style signature: +* void XQspiPs_Enable(XQspiPs *InstancePtr) +* +*****************************************************************************/ +#define XQspiPs_Enable(InstancePtr) \ + XQspiPs_Out32((InstancePtr->Config.BaseAddress) + XQSPIPS_ER_OFFSET, \ + XQSPIPS_ER_ENABLE_MASK) + +/****************************************************************************/ +/** +* +* Disable the device. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* +* @return None. +* +* @note C-Style signature: +* void XQspiPs_Disable(XQspiPs *InstancePtr) +* +*****************************************************************************/ +#define XQspiPs_Disable(InstancePtr) \ + XQspiPs_Out32((InstancePtr->Config.BaseAddress) + XQSPIPS_ER_OFFSET, 0) + +/****************************************************************************/ +/** +* +* Set the contents of the Linear QSPI Configuration register. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* @param RegisterValue is the value to be written to the Linear QSPI +* configuration register. +* +* @return None. +* +* @note C-Style signature: +* void XQspiPs_SetLqspiConfigReg(XQspiPs *InstancePtr, +* u32 RegisterValue) +* +*****************************************************************************/ +#define XQspiPs_SetLqspiConfigReg(InstancePtr, RegisterValue) \ + XQspiPs_Out32(((InstancePtr)->Config.BaseAddress) + \ + XQSPIPS_LQSPI_CR_OFFSET, (RegisterValue)) + +/****************************************************************************/ +/** +* +* Get the contents of the Linear QSPI Configuration register. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* +* @return A 32-bit value representing the contents of the LQSPI Config +* register. +* +* @note C-Style signature: +* u32 XQspiPs_GetLqspiConfigReg(u32 *InstancePtr) +* +*****************************************************************************/ +#define XQspiPs_GetLqspiConfigReg(InstancePtr) \ + XQspiPs_In32((InstancePtr->Config.BaseAddress) + \ + XQSPIPS_LQSPI_CR_OFFSET) + +/************************** Function Prototypes ******************************/ + +/* + * Initialization function, implemented in xqspips_sinit.c + */ +XQspiPs_Config *XQspiPs_LookupConfig(u16 DeviceId); + +/* + * Functions implemented in xqspips.c + */ +int XQspiPs_CfgInitialize(XQspiPs *InstancePtr, XQspiPs_Config *Config, + u32 EffectiveAddr); +void XQspiPs_Reset(XQspiPs *InstancePtr); +void XQspiPs_Abort(XQspiPs *InstancePtr); + +s32 XQspiPs_Transfer(XQspiPs *InstancePtr, u8 *SendBufPtr, u8 *RecvBufPtr, + u32 ByteCount); +s32 XQspiPs_PolledTransfer(XQspiPs *InstancePtr, u8 *SendBufPtr, + u8 *RecvBufPtr, u32 ByteCount); +int XQspiPs_LqspiRead(XQspiPs *InstancePtr, u8 *RecvBufPtr, + u32 Address, unsigned ByteCount); + +int XQspiPs_SetSlaveSelect(XQspiPs *InstancePtr); + +void XQspiPs_SetStatusHandler(XQspiPs *InstancePtr, void *CallBackRef, + XQspiPs_StatusHandler FuncPtr); +void XQspiPs_InterruptHandler(void *InstancePtr); + +/* + * Functions for selftest, in xqspips_selftest.c + */ +int XQspiPs_SelfTest(XQspiPs *InstancePtr); + +/* + * Functions for options, in xqspips_options.c + */ +s32 XQspiPs_SetOptions(XQspiPs *InstancePtr, u32 Options); +u32 XQspiPs_GetOptions(XQspiPs *InstancePtr); + +s32 XQspiPs_SetClkPrescaler(XQspiPs *InstancePtr, u8 Prescaler); +u8 XQspiPs_GetClkPrescaler(XQspiPs *InstancePtr); + +int XQspiPs_SetDelays(XQspiPs *InstancePtr, u8 DelayNss, u8 DelayBtwn, + u8 DelayAfter, u8 DelayInit); +void XQspiPs_GetDelays(XQspiPs *InstancePtr, u8 *DelayNss, u8 *DelayBtwn, + u8 *DelayAfter, u8 *DelayInit); +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/qspips_v3_6/src/xqspips_g.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/qspips_v3_6/src/xqspips_g.c new file mode 100644 index 0000000..479135c --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/qspips_v3_6/src/xqspips_g.c @@ -0,0 +1,53 @@ + +/******************************************************************* +* +* CAUTION: This file is automatically generated by HSI. +* Version: 2019.1.3 +* DO NOT EDIT. +* +* Copyright (C) 2010-2023 Xilinx, Inc. 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 +*XILINX 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. +* +*Except as contained in this notice, the name of the Xilinx shall not be used +*in advertising or otherwise to promote the sale, use or other dealings in +*this Software without prior written authorization from Xilinx. +* + +* +* Description: Driver configuration +* +*******************************************************************/ + +#include "xparameters.h" +#include "xqspips.h" + +/* +* The configuration table for devices +*/ + +XQspiPs_Config XQspiPs_ConfigTable[XPAR_XQSPIPS_NUM_INSTANCES] = +{ + { + XPAR_PS7_QSPI_0_DEVICE_ID, + XPAR_PS7_QSPI_0_BASEADDR, + XPAR_PS7_QSPI_0_QSPI_CLK_FREQ_HZ, + XPAR_PS7_QSPI_0_QSPI_MODE + } +}; + + diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/qspips_v3_6/src/xqspips_hw.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/qspips_v3_6/src/xqspips_hw.c new file mode 100644 index 0000000..d5e0789 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/qspips_v3_6/src/xqspips_hw.c @@ -0,0 +1,220 @@ +/****************************************************************************** +* +* Copyright (C) 2013 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xqspips_hw.c +* @addtogroup qspips_v3_6 +* @{ +* +* Contains low level functions, primarily reset related. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- -----------------------------------------------
+* 2.03a hk  09/17/13 First release
+* 3.1   hk  06/19/14 When writing to the configuration register, set/reset
+*                    required bits leaving reserved bits untouched. CR# 796813.
+*
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xqspips_hw.h" +#include "xqspips.h" + +/************************** Constant Definitions *****************************/ + +/** @name Pre-scaler value for divided by 4 + * + * Pre-scaler value for divided by 4 + * + * @{ + */ +#define XQSPIPS_CR_PRESC_DIV_BY_4 0x01 +/* @} */ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + + +/*****************************************************************************/ +/** +* +* Resets QSPI by disabling the device and bringing it to reset state through +* register writes. +* +* @param None +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XQspiPs_ResetHw(u32 BaseAddress) +{ + u32 ConfigReg; + + /* + * Disable interrupts + */ + XQspiPs_WriteReg(BaseAddress, XQSPIPS_IDR_OFFSET, + XQSPIPS_IXR_DISABLE_ALL); + + /* + * Disable device + */ + XQspiPs_WriteReg(BaseAddress, XQSPIPS_ER_OFFSET, + 0); + + /* + * De-assert slave select lines. + */ + ConfigReg = XQspiPs_ReadReg(BaseAddress, XQSPIPS_CR_OFFSET); + ConfigReg |= (XQSPIPS_CR_SSCTRL_MASK | XQSPIPS_CR_SSFORCE_MASK); + XQspiPs_WriteReg(BaseAddress, XQSPIPS_CR_OFFSET, ConfigReg); + + /* + * Write default value to RX and TX threshold registers + * RX threshold should be set to 1 here because the corresponding + * status bit is used next to clear the RXFIFO + */ + XQspiPs_WriteReg(BaseAddress, XQSPIPS_TXWR_OFFSET, + (XQSPIPS_TXWR_RESET_VALUE & XQSPIPS_TXWR_MASK)); + XQspiPs_WriteReg(BaseAddress, XQSPIPS_RXWR_OFFSET, + (XQSPIPS_RXWR_RESET_VALUE & XQSPIPS_RXWR_MASK)); + + /* + * Clear RXFIFO + */ + while ((XQspiPs_ReadReg(BaseAddress,XQSPIPS_SR_OFFSET) & + XQSPIPS_IXR_RXNEMPTY_MASK) != 0) { + XQspiPs_ReadReg(BaseAddress, XQSPIPS_RXD_OFFSET); + } + + /* + * Clear status register by reading register and + * writing 1 to clear the write to clear bits + */ + XQspiPs_ReadReg(BaseAddress, XQSPIPS_SR_OFFSET); + XQspiPs_WriteReg(BaseAddress, XQSPIPS_SR_OFFSET, + XQSPIPS_IXR_WR_TO_CLR_MASK); + + /* + * Write default value to configuration register + */ + ConfigReg = XQspiPs_ReadReg(BaseAddress, XQSPIPS_CR_OFFSET); + ConfigReg |= XQSPIPS_CR_RESET_MASK_SET; + ConfigReg &= ~XQSPIPS_CR_RESET_MASK_CLR; + XQspiPs_WriteReg(BaseAddress, XQSPIPS_CR_OFFSET, ConfigReg); + + /* + * De-select linear mode + */ + XQspiPs_WriteReg(BaseAddress, XQSPIPS_LQSPI_CR_OFFSET, + 0x0); + +} + +/*****************************************************************************/ +/** +* +* Initializes QSPI to Linear mode with default QSPI boot settings. +* +* @param None +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XQspiPs_LinearInit(u32 BaseAddress) +{ + u32 BaudRateDiv; + u32 LinearCfg; + u32 ConfigReg; + + /* + * Baud rate divisor for dividing by 4. Value of CR bits [5:3] + * should be set to 0x001; hence shift the value and use the mask. + */ + BaudRateDiv = ( (XQSPIPS_CR_PRESC_DIV_BY_4) << + XQSPIPS_CR_PRESC_SHIFT) & XQSPIPS_CR_PRESC_MASK; + /* + * Write configuration register with default values, slave selected & + * pre-scaler value for divide by 4 + */ + ConfigReg = XQspiPs_ReadReg(BaseAddress, XQSPIPS_CR_OFFSET); + ConfigReg |= (XQSPIPS_CR_RESET_MASK_SET | BaudRateDiv); + ConfigReg &= ~(XQSPIPS_CR_RESET_MASK_CLR | XQSPIPS_CR_SSCTRL_MASK); + XQspiPs_WriteReg(BaseAddress, XQSPIPS_CR_OFFSET, ConfigReg); + + /* + * Write linear configuration register with default value - + * enable linear mode and use fast read. + */ + + if(XPAR_XQSPIPS_0_QSPI_MODE == XQSPIPS_CONNECTION_MODE_SINGLE){ + + LinearCfg = XQSPIPS_LQSPI_CR_RST_STATE; + + }else if(XPAR_XQSPIPS_0_QSPI_MODE == + XQSPIPS_CONNECTION_MODE_STACKED){ + + LinearCfg = XQSPIPS_LQSPI_CR_RST_STATE | + XQSPIPS_LQSPI_CR_TWO_MEM_MASK; + + }else if(XPAR_XQSPIPS_0_QSPI_MODE == + XQSPIPS_CONNECTION_MODE_PARALLEL){ + + LinearCfg = XQSPIPS_LQSPI_CR_RST_STATE | + XQSPIPS_LQSPI_CR_TWO_MEM_MASK | + XQSPIPS_LQSPI_CR_SEP_BUS_MASK; + + } + + XQspiPs_WriteReg(BaseAddress, XQSPIPS_LQSPI_CR_OFFSET, + LinearCfg); + + /* + * Enable device + */ + XQspiPs_WriteReg(BaseAddress, XQSPIPS_ER_OFFSET, + XQSPIPS_ER_ENABLE_MASK); + +} +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/qspips_v3_6/src/xqspips_hw.h b/df_datalink/bsp/ps7_cortexa9_0/libsrc/qspips_v3_6/src/xqspips_hw.h new file mode 100644 index 0000000..88c232e --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/qspips_v3_6/src/xqspips_hw.h @@ -0,0 +1,421 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xqspips_hw.h +* @addtogroup qspips_v3_6 +* @{ +* +* This header file contains the identifiers and basic HW access driver +* functions (or macros) that can be used to access the device. Other driver +* functions are defined in xqspips.h. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- -----------------------------------------------
+* 1.00  sdm 11/25/10 First release
+* 2.00a ka  07/25/12 Added a few register defines for CR 670297
+*		     and removed some defines of reserved fields for
+*		     CR 671468
+*		     Added define XQSPIPS_CR_HOLD_B_MASK for Holdb_dr
+*		     bit in Configuration register.
+* 2.01a sg  02/03/13 Added defines for DelayNss,Rx Watermark,Interrupts
+*		     which need write to clear. Removed Read zeros mask from
+*		     LQSPI Config register.
+* 2.03a hk  08/22/13 Added prototypes of API's for QSPI reset and
+*                    linear mode initialization for boot. Added related
+*                    constant definitions.
+* 3.1   hk  08/13/14 Changed definition of CR reset value masks to set/reset
+*                    required bits leaving reserved bits untouched. CR# 796813.
+* 3.2	sk	02/05/15 Add SLCR reset in abort function as a workaround because
+* 					 controller does not update FIFO status flags as expected
+* 					 when thresholds are used.
+* 3.6   akm 03/28/19 Fixed memory leak issue while reading from qspi.(CR#1016357)
+*
+* 
+* +******************************************************************************/ +#ifndef XQSPIPS_HW_H /* prevent circular inclusions */ +#define XQSPIPS_HW_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_io.h" +#include "xparameters.h" + +/************************** Constant Definitions *****************************/ + +/** @name Register Map + * + * Register offsets from the base address of an QSPI device. + * @{ + */ +#define XQSPIPS_CR_OFFSET 0x00 /**< Configuration Register */ +#define XQSPIPS_SR_OFFSET 0x04 /**< Interrupt Status */ +#define XQSPIPS_IER_OFFSET 0x08 /**< Interrupt Enable */ +#define XQSPIPS_IDR_OFFSET 0x0c /**< Interrupt Disable */ +#define XQSPIPS_IMR_OFFSET 0x10 /**< Interrupt Enabled Mask */ +#define XQSPIPS_ER_OFFSET 0x14 /**< Enable/Disable Register */ +#define XQSPIPS_DR_OFFSET 0x18 /**< Delay Register */ +#define XQSPIPS_TXD_00_OFFSET 0x1C /**< Transmit 4-byte inst/data */ +#define XQSPIPS_RXD_OFFSET 0x20 /**< Data Receive Register */ +#define XQSPIPS_SICR_OFFSET 0x24 /**< Slave Idle Count */ +#define XQSPIPS_TXWR_OFFSET 0x28 /**< Transmit FIFO Watermark */ +#define XQSPIPS_RXWR_OFFSET 0x2C /**< Receive FIFO Watermark */ +#define XQSPIPS_GPIO_OFFSET 0x30 /**< GPIO Register */ +#define XQSPIPS_LPBK_DLY_ADJ_OFFSET 0x38 /**< Loopback Delay Adjust Reg */ +#define XQSPIPS_TXD_01_OFFSET 0x80 /**< Transmit 1-byte inst */ +#define XQSPIPS_TXD_10_OFFSET 0x84 /**< Transmit 2-byte inst */ +#define XQSPIPS_TXD_11_OFFSET 0x88 /**< Transmit 3-byte inst */ +#define XQSPIPS_LQSPI_CR_OFFSET 0xA0 /**< Linear QSPI config register */ +#define XQSPIPS_LQSPI_SR_OFFSET 0xA4 /**< Linear QSPI status register */ +#define XQSPIPS_MOD_ID_OFFSET 0xFC /**< Module ID register */ + +/* @} */ + +/** @name Configuration Register + * + * This register contains various control bits that + * affect the operation of the QSPI device. Read/Write. + * @{ + */ + +#define XQSPIPS_CR_IFMODE_MASK 0x80000000 /**< Flash mem interface mode */ +#define XQSPIPS_CR_ENDIAN_MASK 0x04000000 /**< Tx/Rx FIFO endianness */ +#define XQSPIPS_CR_MANSTRT_MASK 0x00010000 /**< Manual Transmission Start */ +#define XQSPIPS_CR_MANSTRTEN_MASK 0x00008000 /**< Manual Transmission Start + Enable */ +#define XQSPIPS_CR_SSFORCE_MASK 0x00004000 /**< Force Slave Select */ +#define XQSPIPS_CR_SSCTRL_MASK 0x00000400 /**< Slave Select Decode */ +#define XQSPIPS_CR_SSCTRL_SHIFT 10 /**< Slave Select Decode shift */ +#define XQSPIPS_CR_DATA_SZ_MASK 0x000000C0 /**< Size of word to be + transferred */ +#define XQSPIPS_CR_PRESC_MASK 0x00000038 /**< Prescaler Setting */ +#define XQSPIPS_CR_PRESC_SHIFT 3 /**< Prescaler shift */ +#define XQSPIPS_CR_PRESC_MAXIMUM 0x07 /**< Prescaler maximum value */ + +#define XQSPIPS_CR_CPHA_MASK 0x00000004 /**< Phase Configuration */ +#define XQSPIPS_CR_CPOL_MASK 0x00000002 /**< Polarity Configuration */ + +#define XQSPIPS_CR_MSTREN_MASK 0x00000001 /**< Master Mode Enable */ + +#define XQSPIPS_CR_HOLD_B_MASK 0x00080000 /**< HOLD_B Pin Drive Enable */ + +#define XQSPIPS_CR_REF_CLK_MASK 0x00000100 /**< Ref clk bit - should be 0 */ + +/* Deselect the Slave select line and set the transfer size to 32 at reset */ +#define XQSPIPS_CR_RESET_MASK_SET XQSPIPS_CR_IFMODE_MASK | \ + XQSPIPS_CR_SSCTRL_MASK | \ + XQSPIPS_CR_DATA_SZ_MASK | \ + XQSPIPS_CR_MSTREN_MASK | \ + XQSPIPS_CR_SSFORCE_MASK | \ + XQSPIPS_CR_HOLD_B_MASK +#define XQSPIPS_CR_RESET_MASK_CLR XQSPIPS_CR_CPOL_MASK | \ + XQSPIPS_CR_CPHA_MASK | \ + XQSPIPS_CR_PRESC_MASK | \ + XQSPIPS_CR_MANSTRTEN_MASK | \ + XQSPIPS_CR_MANSTRT_MASK | \ + XQSPIPS_CR_ENDIAN_MASK | \ + XQSPIPS_CR_REF_CLK_MASK +/* @} */ + + +/** @name QSPI Interrupt Registers + * + * QSPI Status Register + * + * This register holds the interrupt status flags for an QSPI device. Some + * of the flags are level triggered, which means that they are set as long + * as the interrupt condition exists. Other flags are edge triggered, + * which means they are set once the interrupt condition occurs and remain + * set until they are cleared by software. The interrupts are cleared by + * writing a '1' to the interrupt bit position in the Status Register. + * Read/Write. + * + * QSPI Interrupt Enable Register + * + * This register is used to enable chosen interrupts for an QSPI device. + * Writing a '1' to a bit in this register sets the corresponding bit in the + * QSPI Interrupt Mask register. Write only. + * + * QSPI Interrupt Disable Register + * + * This register is used to disable chosen interrupts for an QSPI device. + * Writing a '1' to a bit in this register clears the corresponding bit in the + * QSPI Interrupt Mask register. Write only. + * + * QSPI Interrupt Mask Register + * + * This register shows the enabled/disabled interrupts of an QSPI device. + * Read only. + * + * All four registers have the same bit definitions. They are only defined once + * for each of the Interrupt Enable Register, Interrupt Disable Register, + * Interrupt Mask Register, and Channel Interrupt Status Register + * @{ + */ + +#define XQSPIPS_IXR_TXUF_MASK 0x00000040 /**< QSPI Tx FIFO Underflow */ +#define XQSPIPS_IXR_RXFULL_MASK 0x00000020 /**< QSPI Rx FIFO Full */ +#define XQSPIPS_IXR_RXNEMPTY_MASK 0x00000010 /**< QSPI Rx FIFO Not Empty */ +#define XQSPIPS_IXR_TXFULL_MASK 0x00000008 /**< QSPI Tx FIFO Full */ +#define XQSPIPS_IXR_TXOW_MASK 0x00000004 /**< QSPI Tx FIFO Overwater */ +#define XQSPIPS_IXR_RXOVR_MASK 0x00000001 /**< QSPI Rx FIFO Overrun */ +#define XQSPIPS_IXR_DFLT_MASK 0x00000025 /**< QSPI default interrupts + mask */ +#define XQSPIPS_IXR_WR_TO_CLR_MASK 0x00000041 /**< Interrupts which + need write to clear */ +#define XQSPIPS_ISR_RESET_STATE 0x00000004 /**< Default to tx/rx empty */ +#define XQSPIPS_IXR_DISABLE_ALL 0x0000007D /**< Disable all interrupts */ +/* @} */ + + +/** @name Enable Register + * + * This register is used to enable or disable an QSPI device. + * Read/Write + * @{ + */ +#define XQSPIPS_ER_ENABLE_MASK 0x00000001 /**< QSPI Enable Bit Mask */ +/* @} */ + + +/** @name Delay Register + * + * This register is used to program timing delays in + * slave mode. Read/Write + * @{ + */ +#define XQSPIPS_DR_NSS_MASK 0xFF000000 /**< Delay to de-assert slave select + between two words mask */ +#define XQSPIPS_DR_NSS_SHIFT 24 /**< Delay to de-assert slave select + between two words shift */ +#define XQSPIPS_DR_BTWN_MASK 0x00FF0000 /**< Delay Between Transfers + mask */ +#define XQSPIPS_DR_BTWN_SHIFT 16 /**< Delay Between Transfers shift */ +#define XQSPIPS_DR_AFTER_MASK 0x0000FF00 /**< Delay After Transfers mask */ +#define XQSPIPS_DR_AFTER_SHIFT 8 /**< Delay After Transfers shift */ +#define XQSPIPS_DR_INIT_MASK 0x000000FF /**< Delay Initially mask */ +/* @} */ + +/** @name Slave Idle Count Registers + * + * This register defines the number of pclk cycles the slave waits for a the + * QSPI clock to become stable in quiescent state before it can detect the start + * of the next transfer in CPHA = 1 mode. + * Read/Write + * + * @{ + */ +#define XQSPIPS_SICR_MASK 0x000000FF /**< Slave Idle Count Mask */ +/* @} */ + + +/** @name Transmit FIFO Watermark Register + * + * This register defines the watermark setting for the Transmit FIFO. + * + * @{ + */ +#define XQSPIPS_TXWR_MASK 0x0000003F /**< Transmit Watermark Mask */ +#define XQSPIPS_TXWR_RESET_VALUE 0x00000001 /**< Transmit Watermark + * register reset value */ + +/* @} */ + +/** @name Receive FIFO Watermark Register + * + * This register defines the watermark setting for the Receive FIFO. + * + * @{ + */ +#define XQSPIPS_RXWR_MASK 0x0000003F /**< Receive Watermark Mask */ +#define XQSPIPS_RXWR_RESET_VALUE 0x00000001 /**< Receive Watermark + * register reset value */ + +/* @} */ + +/** @name FIFO Depth + * + * This macro provides the depth of transmit FIFO and receive FIFO. + * + * @{ + */ +#define XQSPIPS_FIFO_DEPTH 63 /**< FIFO depth (words) */ +/* @} */ + + +/** @name Linear QSPI Configuration Register + * + * This register contains various control bits that + * affect the operation of the Linear QSPI controller. Read/Write. + * + * @{ + */ +#define XQSPIPS_LQSPI_CR_LINEAR_MASK 0x80000000 /**< LQSPI mode enable */ +#define XQSPIPS_LQSPI_CR_TWO_MEM_MASK 0x40000000 /**< Both memories or one */ +#define XQSPIPS_LQSPI_CR_SEP_BUS_MASK 0x20000000 /**< Seperate memory bus */ +#define XQSPIPS_LQSPI_CR_U_PAGE_MASK 0x10000000 /**< Upper memory page */ +#define XQSPIPS_LQSPI_CR_MODE_EN_MASK 0x02000000 /**< Enable mode bits */ +#define XQSPIPS_LQSPI_CR_MODE_ON_MASK 0x01000000 /**< Mode on */ +#define XQSPIPS_LQSPI_CR_MODE_BITS_MASK 0x00FF0000 /**< Mode value for dual I/O + or quad I/O */ +#define XQSPIPS_LQSPI_CR_DUMMY_MASK 0x00000700 /**< Number of dummy bytes + between addr and return + read data */ +#define XQSPIPS_LQSPI_CR_INST_MASK 0x000000FF /**< Read instr code */ +#define XQSPIPS_LQSPI_CR_RST_STATE 0x8000016B /**< Default CR value */ +/* @} */ + +/** @name Linear QSPI Status Register + * + * This register contains various status bits of the Linear QSPI controller. + * Read/Write. + * + * @{ + */ +#define XQSPIPS_LQSPI_SR_D_FSM_ERR_MASK 0x00000004 /**< AXI Data FSM Error + received */ +#define XQSPIPS_LQSPI_SR_WR_RECVD_MASK 0x00000002 /**< AXI write command + received */ +/* @} */ + + +/** @name Loopback Delay Adjust Register + * + * This register contains various bit masks of Loopback Delay Adjust Register. + * + * @{ + */ + +#define XQSPIPS_LPBK_DLY_ADJ_USE_LPBK_MASK 0x00000020 /**< Loopback Bit */ + +/* @} */ + + +/** @name SLCR Register + * + * Register offsets from SLCR base address. + * + * @{ + */ + +#define SLCR_LOCK 0x00000004 /**< SLCR Write Protection Lock */ +#define SLCR_UNLOCK 0x00000008 /**< SLCR Write Protection Unlock */ +#define LQSPI_RST_CTRL 0x00000230 /**< Quad SPI Software Reset Control */ +#define SLCR_LOCKSTA 0x0000000C /**< SLCR Write Protection status */ + +/* @} */ + + +/** @name SLCR Register + * + * Bit Masks of above SLCR Registers . + * + * @{ + */ + +#ifndef XPAR_XSLCR_0_BASEADDR +#define XPAR_XSLCR_0_BASEADDR 0xF8000000 +#endif +#define SLCR_LOCK_MASK 0x767B /**< Write Protection Lock mask*/ +#define SLCR_UNLOCK_MASK 0xDF0D /**< SLCR Write Protection Unlock */ +#define LQSPI_RST_CTRL_MASK 0x3 /**< Quad SPI Software Reset Control */ + +/* @} */ + + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +#define XQspiPs_In32 Xil_In32 +#define XQspiPs_Out32 Xil_Out32 +#define XQSPIPS_DUMMY_TX_DATA 0xFFFFFFFF + +/****************************************************************************/ +/** +* Read a register. +* +* @param BaseAddress contains the base address of the device. +* @param RegOffset contains the offset from the 1st register of the +* device to the target register. +* +* @return The value read from the register. +* +* @note C-Style signature: +* u32 XQspiPs_ReadReg(u32 BaseAddress. int RegOffset) +* +******************************************************************************/ +#define XQspiPs_ReadReg(BaseAddress, RegOffset) \ + XQspiPs_In32((BaseAddress) + (RegOffset)) + +/***************************************************************************/ +/** +* Write to a register. +* +* @param BaseAddress contains the base address of the device. +* @param RegOffset contains the offset from the 1st register of the +* device to target register. +* @param RegisterValue is the value to be written to the register. +* +* @return None. +* +* @note C-Style signature: +* void XQspiPs_WriteReg(u32 BaseAddress, int RegOffset, +* u32 RegisterValue) +* +******************************************************************************/ +#define XQspiPs_WriteReg(BaseAddress, RegOffset, RegisterValue) \ + XQspiPs_Out32((BaseAddress) + (RegOffset), (RegisterValue)) + +/************************** Function Prototypes ******************************/ + +/* + * Functions implemented in xqspips_hw.c + */ +void XQspiPs_ResetHw(u32 BaseAddress); +void XQspiPs_LinearInit(u32 BaseAddress); + +/************************** Variable Definitions *****************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/qspips_v3_6/src/xqspips_options.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/qspips_v3_6/src/xqspips_options.c new file mode 100644 index 0000000..14d0ca0 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/qspips_v3_6/src/xqspips_options.c @@ -0,0 +1,426 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xqspips_options.c +* @addtogroup qspips_v3_6 +* @{ +* +* Contains functions for the configuration of the XQspiPs driver component. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- -----------------------------------------------
+* 1.00  sdm 11/25/10 First release
+* 2.00a kka 07/25/12 Removed the selection for the following options:
+*		     Master mode (XQSPIPS_MASTER_OPTION) and
+*		     Flash interface mode (XQSPIPS_FLASH_MODE_OPTION) option
+*		     as the QSPI driver supports the Master mode
+*		     and Flash Interface mode. The driver doesnot support
+*		     Slave mode or the legacy mode.
+* 		     Added the option for setting the Holdb_dr bit in the
+*		     configuration options, XQSPIPS_HOLD_B_DRIVE_OPTION
+*		     is the option to be used for setting this bit in the
+*		     configuration register.
+* 2.01a sg  02/03/13 SetDelays and GetDelays API's include DelayNss parameter.
+*
+* 2.02a hk  26/03/13 Removed XQspi_Reset() in Set_Options() function when
+*			 LQSPI_MODE_OPTION is set. Moved Enable() to XQpsiPs_LqspiRead().
+* 3.3   sk  11/07/15 Modified the API prototypes according to MISRAC standards
+*                    to remove compilation warnings. CR# 868893.
+*
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xqspips.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +/* + * Create the table of options which are processed to get/set the device + * options. These options are table driven to allow easy maintenance and + * expansion of the options. + */ +typedef struct { + u32 Option; + u32 Mask; +} OptionsMap; + +static OptionsMap OptionsTable[] = { + {XQSPIPS_CLK_ACTIVE_LOW_OPTION, XQSPIPS_CR_CPOL_MASK}, + {XQSPIPS_CLK_PHASE_1_OPTION, XQSPIPS_CR_CPHA_MASK}, + {XQSPIPS_FORCE_SSELECT_OPTION, XQSPIPS_CR_SSFORCE_MASK}, + {XQSPIPS_MANUAL_START_OPTION, XQSPIPS_CR_MANSTRTEN_MASK}, + {XQSPIPS_HOLD_B_DRIVE_OPTION, XQSPIPS_CR_HOLD_B_MASK}, +}; + +#define XQSPIPS_NUM_OPTIONS (sizeof(OptionsTable) / sizeof(OptionsMap)) + +/*****************************************************************************/ +/** +* +* This function sets the options for the QSPI device driver. The options control +* how the device behaves relative to the QSPI bus. The device must be idle +* rather than busy transferring data before setting these device options. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* @param Options contains the specified options to be set. This is a bit +* mask where a 1 means to turn the option on, and a 0 means to +* turn the option off. One or more bit values may be contained in +* the mask. See the bit definitions named XQSPIPS_*_OPTIONS in +* the file xqspips.h. +* +* @return +* - XST_SUCCESS if options are successfully set. +* - XST_DEVICE_BUSY if the device is currently transferring data. +* The transfer must complete or be aborted before setting options. +* +* @note +* This function is not thread-safe. +* +******************************************************************************/ +s32 XQspiPs_SetOptions(XQspiPs *InstancePtr, u32 Options) +{ + u32 ConfigReg; + unsigned int Index; + u32 QspiOptions; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Do not allow to modify the Control Register while a transfer is in + * progress. Not thread-safe. + */ + if (InstancePtr->IsBusy) { + return XST_DEVICE_BUSY; + } + + QspiOptions = Options & XQSPIPS_LQSPI_MODE_OPTION; + Options &= ~XQSPIPS_LQSPI_MODE_OPTION; + + ConfigReg = XQspiPs_ReadReg(InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET); + + /* + * Loop through the options table, turning the option on or off + * depending on whether the bit is set in the incoming options flag. + */ + for (Index = 0; Index < XQSPIPS_NUM_OPTIONS; Index++) { + if (Options & OptionsTable[Index].Option) { + /* Turn it on */ + ConfigReg |= OptionsTable[Index].Mask; + } else { + /* Turn it off */ + ConfigReg &= ~(OptionsTable[Index].Mask); + } + } + + /* + * Now write the control register. Leave it to the upper layers + * to restart the device. + */ + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPS_CR_OFFSET, + ConfigReg); + + /* + * Check for the LQSPI configuration options. + */ + ConfigReg = XQspiPs_ReadReg(InstancePtr->Config.BaseAddress, + XQSPIPS_LQSPI_CR_OFFSET); + + + if (QspiOptions & XQSPIPS_LQSPI_MODE_OPTION) { + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_LQSPI_CR_OFFSET, + XQSPIPS_LQSPI_CR_RST_STATE); + XQspiPs_SetSlaveSelect(InstancePtr); + } else { + ConfigReg &= ~XQSPIPS_LQSPI_CR_LINEAR_MASK; + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_LQSPI_CR_OFFSET, ConfigReg); + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function gets the options for the QSPI device. The options control how +* the device behaves relative to the QSPI bus. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* +* @return +* +* Options contains the specified options currently set. This is a bit value +* where a 1 means the option is on, and a 0 means the option is off. +* See the bit definitions named XQSPIPS_*_OPTIONS in file xqspips.h. +* +* @note None. +* +******************************************************************************/ +u32 XQspiPs_GetOptions(XQspiPs *InstancePtr) +{ + u32 OptionsFlag = 0; + u32 ConfigReg; + unsigned int Index; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Get the current options from QSPI configuration register. + */ + ConfigReg = XQspiPs_ReadReg(InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET); + + /* + * Loop through the options table to grab options + */ + for (Index = 0; Index < XQSPIPS_NUM_OPTIONS; Index++) { + if (ConfigReg & OptionsTable[Index].Mask) { + OptionsFlag |= OptionsTable[Index].Option; + } + } + + /* + * Check for the LQSPI configuration options. + */ + ConfigReg = XQspiPs_ReadReg(InstancePtr->Config.BaseAddress, + XQSPIPS_LQSPI_CR_OFFSET); + + if ((ConfigReg & XQSPIPS_LQSPI_CR_LINEAR_MASK) != 0) { + OptionsFlag |= XQSPIPS_LQSPI_MODE_OPTION; + } + + return OptionsFlag; +} + +/*****************************************************************************/ +/** +* +* This function sets the clock prescaler for an QSPI device. The device +* must be idle rather than busy transferring data before setting these device +* options. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* @param Prescaler is the value that determine how much the clock should +* be divided by. Use the XQSPIPS_CLK_PRESCALE_* constants defined +* in xqspips.h for this setting. +* +* @return +* - XST_SUCCESS if options are successfully set. +* - XST_DEVICE_BUSY if the device is currently transferring data. +* The transfer must complete or be aborted before setting options. +* +* @note +* This function is not thread-safe. +* +******************************************************************************/ +s32 XQspiPs_SetClkPrescaler(XQspiPs *InstancePtr, u8 Prescaler) +{ + u32 ConfigReg; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(Prescaler <= XQSPIPS_CR_PRESC_MAXIMUM); + + /* + * Do not allow the slave select to change while a transfer is in + * progress. Not thread-safe. + */ + if (InstancePtr->IsBusy) { + return XST_DEVICE_BUSY; + } + + /* + * Read the configuration register, mask out the interesting bits, and set + * them with the shifted value passed into the function. Write the + * results back to the configuration register. + */ + ConfigReg = XQspiPs_ReadReg(InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET); + + ConfigReg &= ~XQSPIPS_CR_PRESC_MASK; + ConfigReg |= (u32) (Prescaler & XQSPIPS_CR_PRESC_MAXIMUM) << + XQSPIPS_CR_PRESC_SHIFT; + + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET, + ConfigReg); + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function gets the clock prescaler of an QSPI device. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* +* @return The prescaler value. +* +* @note None. +* +* +******************************************************************************/ +u8 XQspiPs_GetClkPrescaler(XQspiPs *InstancePtr) +{ + u32 ConfigReg; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + ConfigReg = XQspiPs_ReadReg(InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET); + + ConfigReg &= XQSPIPS_CR_PRESC_MASK; + + return (u8)(ConfigReg >> XQSPIPS_CR_PRESC_SHIFT); +} + +/*****************************************************************************/ +/** +* +* This function sets the delay register for the QSPI device driver. +* The delay register controls the Delay Between Transfers, Delay After +* Transfers, and the Delay Initially. The default value is 0x0. The range of +* each delay value is 0-255. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* @param DelayNss is the delay to de-assert slave select between +* two word transfers. +* @param DelayBtwn is the delay between one Slave Select being +* de-activated and the activation of another slave. The delay is +* the number of master clock periods given by DelayBtwn + 2. +* @param DelayAfter define the delay between the last bit of the current +* byte transfer and the first bit of the next byte transfer. +* The delay in number of master clock periods is given as: +* CHPA=0:DelayInit+DelayAfter+3 +* CHPA=1:DelayAfter+1 +* @param DelayInit is the delay between asserting the slave select signal +* and the first bit transfer. The delay int number of master clock +* periods is DelayInit+1. +* +* @return +* - XST_SUCCESS if delays are successfully set. +* - XST_DEVICE_BUSY if the device is currently transferring data. +* The transfer must complete or be aborted before setting options. +* +* @note None. +* +******************************************************************************/ +int XQspiPs_SetDelays(XQspiPs *InstancePtr, u8 DelayNss, u8 DelayBtwn, + u8 DelayAfter, u8 DelayInit) +{ + u32 DelayRegister; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Do not allow the delays to change while a transfer is in + * progress. Not thread-safe. + */ + if (InstancePtr->IsBusy) { + return XST_DEVICE_BUSY; + } + + /* Shift, Mask and OR the values to build the register settings */ + DelayRegister = (u32) DelayNss << XQSPIPS_DR_NSS_SHIFT; + DelayRegister |= (u32) DelayBtwn << XQSPIPS_DR_BTWN_SHIFT; + DelayRegister |= (u32) DelayAfter << XQSPIPS_DR_AFTER_SHIFT; + DelayRegister |= (u32) DelayInit; + + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_DR_OFFSET, DelayRegister); + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function gets the delay settings for an QSPI device. +* The delay register controls the Delay Between Transfers, Delay After +* Transfers, and the Delay Initially. The default value is 0x0. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* @param DelayNss is a pointer to the Delay to de-assert slave select +* between two word transfers. +* @param DelayBtwn is a pointer to the Delay Between transfers value. +* This is a return parameter. +* @param DelayAfter is a pointer to the Delay After transfer value. +* This is a return parameter. +* @param DelayInit is a pointer to the Delay Initially value. This is +* a return parameter. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XQspiPs_GetDelays(XQspiPs *InstancePtr, u8 *DelayNss, u8 *DelayBtwn, + u8 *DelayAfter, u8 *DelayInit) +{ + u32 DelayRegister; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + DelayRegister = XQspiPs_ReadReg(InstancePtr->Config.BaseAddress, + XQSPIPS_DR_OFFSET); + + *DelayInit = (u8)(DelayRegister & XQSPIPS_DR_INIT_MASK); + + *DelayAfter = (u8)((DelayRegister & XQSPIPS_DR_AFTER_MASK) >> + XQSPIPS_DR_AFTER_SHIFT); + + *DelayBtwn = (u8)((DelayRegister & XQSPIPS_DR_BTWN_MASK) >> + XQSPIPS_DR_BTWN_SHIFT); + + *DelayNss = (u8)((DelayRegister & XQSPIPS_DR_NSS_MASK) >> + XQSPIPS_DR_NSS_SHIFT); +} +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/qspips_v3_6/src/xqspips_selftest.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/qspips_v3_6/src/xqspips_selftest.c new file mode 100644 index 0000000..c72e952 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/qspips_v3_6/src/xqspips_selftest.c @@ -0,0 +1,135 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xqspips_selftest.c +* @addtogroup qspips_v3_6 +* @{ +* +* This file contains the implementation of selftest function for the QSPI +* device. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- -----------------------------------------------
+* 1.00  sdm 11/25/10 First release
+* 2.01a sg  02/03/13 Delay Register test is added with DelayNss parameter.
+* 3.1   hk  06/19/14 Remove checks for CR and ISR register values as they are
+*                    reset in the previous step.
+*
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xqspips.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +/*****************************************************************************/ +/** +* +* Runs a self-test on the driver/device. The self-test is destructive in that +* a reset of the device is performed in order to check the reset values of +* the registers and to get the device into a known state. +* +* Upon successful return from the self-test, the device is reset. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* +* @return +* - XST_SUCCESS if successful +* - XST_REGISTER_ERROR indicates a register did not read or write +* correctly. +* +* @note None. +* +******************************************************************************/ +int XQspiPs_SelfTest(XQspiPs *InstancePtr) +{ + int Status; + u8 DelayTestNss; + u8 DelayTestBtwn; + u8 DelayTestAfter; + u8 DelayTestInit; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Reset the QSPI device to leave it in a known good state + */ + XQspiPs_Reset(InstancePtr); + + DelayTestNss = 0x5A; + DelayTestBtwn = 0xA5; + DelayTestAfter = 0xAA; + DelayTestInit = 0x55; + + /* + * Write and read the delay register, just to be sure there is some + * hardware out there. + */ + Status = XQspiPs_SetDelays(InstancePtr, DelayTestNss, DelayTestBtwn, + DelayTestAfter, DelayTestInit); + if (Status != XST_SUCCESS) { + return Status; + } + + XQspiPs_GetDelays(InstancePtr, &DelayTestNss, &DelayTestBtwn, + &DelayTestAfter, &DelayTestInit); + if ((0x5A != DelayTestNss) || (0xA5 != DelayTestBtwn) || + (0xAA != DelayTestAfter) || (0x55 != DelayTestInit)) { + return XST_REGISTER_ERROR; + } + + Status = XQspiPs_SetDelays(InstancePtr, 0, 0, 0, 0); + if (Status != XST_SUCCESS) { + return Status; + } + + /* + * Reset the QSPI device to leave it in a known good state + */ + XQspiPs_Reset(InstancePtr); + + return XST_SUCCESS; +} +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/qspips_v3_6/src/xqspips_sinit.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/qspips_v3_6/src/xqspips_sinit.c new file mode 100644 index 0000000..da2dc1e --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/qspips_v3_6/src/xqspips_sinit.c @@ -0,0 +1,96 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xqspips_sinit.c +* @addtogroup qspips_v3_6 +* @{ +* +* The implementation of the XQspiPs component's static initialization +* functionality. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- -----------------------------------------------
+* 1.00  sdm 11/25/10 First release
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xstatus.h" +#include "xqspips.h" +#include "xparameters.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +extern XQspiPs_Config XQspiPs_ConfigTable[]; + +/*****************************************************************************/ +/** +* +* Looks up the device configuration based on the unique device ID. A table +* contains the configuration info for each device in the system. +* +* @param DeviceId contains the ID of the device to look up the +* configuration for. +* +* @return +* +* A pointer to the configuration found or NULL if the specified device ID was +* not found. See xqspips.h for the definition of XQspiPs_Config. +* +* @note None. +* +******************************************************************************/ +XQspiPs_Config *XQspiPs_LookupConfig(u16 DeviceId) +{ + XQspiPs_Config *CfgPtr = NULL; + int Index; + + for (Index = 0; Index < XPAR_XQSPIPS_NUM_INSTANCES; Index++) { + if (XQspiPs_ConfigTable[Index].DeviceId == DeviceId) { + CfgPtr = &XQspiPs_ConfigTable[Index]; + break; + } + } + return CfgPtr; +} +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/scugic_v4_0/src/Makefile b/df_datalink/bsp/ps7_cortexa9_0/libsrc/scugic_v4_0/src/Makefile new file mode 100644 index 0000000..04867a4 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/scugic_v4_0/src/Makefile @@ -0,0 +1,40 @@ +COMPILER= +ARCHIVER= +CP=cp +COMPILER_FLAGS= +EXTRA_COMPILER_FLAGS= +LIB=libxil.a + +CC_FLAGS = $(COMPILER_FLAGS) +ECC_FLAGS = $(EXTRA_COMPILER_FLAGS) + +RELEASEDIR=../../../lib +INCLUDEDIR=../../../include +INCLUDES=-I./. -I${INCLUDEDIR} + +OUTS = *.o + +LIBSOURCES:=*.c +INCLUDEFILES:=*.h + +OBJECTS = $(addsuffix .o, $(basename $(wildcard *.c))) + +libs: banner scugic_libs clean + +%.o: %.c + ${COMPILER} $(CC_FLAGS) $(ECC_FLAGS) $(INCLUDES) -o $@ $< + +banner: + echo "Compiling scugic" + +scugic_libs: ${OBJECTS} + $(ARCHIVER) -r ${RELEASEDIR}/${LIB} ${OBJECTS} + +.PHONY: include +include: scugic_includes + +scugic_includes: + ${CP} ${INCLUDEFILES} ${INCLUDEDIR} + +clean: + rm -rf ${OBJECTS} diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/scugic_v4_0/src/xscugic.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/scugic_v4_0/src/xscugic.c new file mode 100644 index 0000000..8a73638 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/scugic_v4_0/src/xscugic.c @@ -0,0 +1,1133 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xscugic.c +* @addtogroup scugic_v4_0 +* @{ +* +* Contains required functions for the XScuGic driver for the Interrupt +* Controller. See xscugic.h for a detailed description of the driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- --------------------------------------------------------
+* 1.00a drg  01/19/10 First release
+* 1.01a sdm  11/09/11 Changes are made in function XScuGic_CfgInitialize
+*                     Since entry is now made as pointer in the XScuGic
+*                     structure, necessary changes are made.
+*                     The HandlerTable can now be populated through the low
+*                     level routine XScuGic_RegisterHandler added in this
+*                     release. Hence necessary checks are added not to
+*                     overwrite the HandlerTable entriesin function
+*                     XScuGic_CfgInitialize.
+* 1.03a srt  02/27/13 Added APIs
+*                       -XScuGic_SetPriTrigTypeByDistAddr()
+*                       -XScuGic_GetPriTrigTypeByDistAddr()
+*                     Removed Offset calculation macros, defined in _hw.h
+*                     (CR 702687)
+*                     added support to direct interrupts  to the appropriate
+*                     CPU Earlier interrupts were directed to CPU1
+*                     (hard coded).Now depending upon the CPU selected by the
+*                     user(xparameters.h), interrupts will be directed to
+*                     the  relevant CPU. This fixes CR 699688.
+*
+* 1.04a hk   05/04/13 Assigned EffectiveAddr to CpuBaseAddress in
+*                     XScuGic_CfgInitialize. Fix for CR#704400 to remove
+*                     warnings.
+*                     Moved functions XScuGic_SetPriTrigTypeByDistAddr and
+*                    XScuGic_GetPriTrigTypeByDistAddr to xscugic_hw.c.
+*                    This is fix for CR#705621.
+* 1.06a asa  16/11/13 Fix for CR#749178. Assignment for EffectiveAddr
+*                     in function XScuGic_CfgInitialize is removed as it was
+*                     a bug.
+* 3.00  kvn  02/13/14 Modified code for MISRA-C:2012 compliance.
+* 3.01  pkp  06/19/15 Added XScuGic_InterruptMaptoCpu API for an interrupt
+*                     target CPU mapping
+* 3.02  pkp  11/09/15 Modified DistributorInit function for AMP case to add
+*                     the current cpu to interrupt processor targets registers
+* 3.2   asa  02/29/16 Modified DistributorInit function for Zynq AMP case. The
+*                     distributor is left uninitialized for Zynq AMP. It is
+*                     assumed that the distributor will be initialized by
+*                     Linux master. However for CortexR5 case, the earlier code
+*                     is left unchanged where the the interrupt processor target
+*                     registers in the distributor is initialized with the
+*                     corresponding CPU ID on which the application built over
+*                     the scugic driver runs. These changes fix CR#937243.
+* 3.3   pkp  05/12/16 Modified XScuGic_InterruptMaptoCpu to write proper value
+*                     to interrupt target register to fix CR#951848
+*
+* 3.4   asa  04/07/16 Created a new static function DoDistributorInit to
+*                     simplify the flow and avoid code duplication. Changes are
+*                     made for USE_AMP use case for R5. In a scenario
+*                     (in R5 split mode) when one R5 is operating with A53 in
+*                     open amp config and other R5 running baremetal app, the
+*                     existing code had the potential to stop the whole AMP
+*                     solution to work(if for some reason the R5 running the
+*                     baremetal app tasked to initialize the Distributor hangs
+*                     or crashes before initializing).Changes are made so that
+*                     the R5 under AMP first checks if the distributor is
+*                     enabled or not and if not, it does the standard
+*                     Distributor initialization.This fixes the CR#952962.
+* 3.4   mus  09/08/16 Added assert to avoid invalid access of GIC from CPUID 1
+*                     for single core zynq-7000s
+* 3.5   mus  10/05/16 Modified DistributorInit function to avoid
+*                     re-initialization of distributor, If it is already
+*                     initialized by other CPU.
+* 3.5   pkp  10/17/16 Modified XScuGic_InterruptMaptoCpu to correct the CPU Id
+*                     value and properly mask interrupt target processor value
+*                     to modify interrupt target processor register for a given
+*                     interrupt ID and cpu ID
+* 3.6   pkp  20/01/17 Added new API XScuGic_Stop to Disable distributor and
+*                     interrupts in case they are being used only by current
+*                     cpu. It also removes current cpu from interrupt target
+*                     registers for all interrupts.
+*       kvn  02/17/17 Add support for changing GIC CPU master at run time.
+*       kvn  02/28/17 Make the CpuId as static variable and Added new
+*                     XScugiC_GetCpuId to access CpuId.
+* 3.9   mus  02/21/18 Added new API's XScuGic_UnmapAllInterruptsFromCpu and
+*                     XScuGic_InterruptUnmapFromCpu, These API's can be used
+*                     by applications to unmap specific/all interrupts from
+*                     target CPU. It fixes CR#992490.
+* 3.10  mus  07/17/18 Updated file to fix the various coding style issues
+*                     reported by checkpatch. It fixes CR#1006344.
+* 3.10  aru  08/23/18 Resolved MISRA-C:2012 compliance mandatory violations
+*                     It fixes CR#1007753.
+* 3.10  mus  09/19/18 Fix cppcheck warnings
+* 4.0   mus  11/22/18 Fixed bugs in software interrupt generation through 
+*                      XScuGic_SoftwareIntr API
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ +#include "xil_types.h" +#include "xil_assert.h" +#include "xscugic.h" + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Variable Definitions *****************************/ +static u32 CpuId = XPAR_CPU_ID; /**< CPU Core identifier */ + +/************************** Function Prototypes ******************************/ + +static void StubHandler(void *CallBackRef); + +/*****************************************************************************/ +/** +* +* DoDistributorInit initializes the distributor of the GIC. The +* initialization entails: +* +* - Write the trigger mode, priority and target CPU +* - All interrupt sources are disabled +* - Enable the distributor +* +* @param InstancePtr is a pointer to the XScuGic instance. +* @param CpuID is the Cpu ID to be initialized. +* +* @return None +* +* @note None. +* +******************************************************************************/ +static void DoDistributorInit(XScuGic *InstancePtr, u32 CpuID) +{ + u32 Int_Id; +#if !defined (versal) || defined (ARMR5) + u32 LocalCpuID = CpuID; +#endif + +#if defined (versal) && !defined(ARMR5) + u32 temp; + + temp = XScuGic_DistReadReg(InstancePtr, XSCUGIC_DIST_EN_OFFSET); + temp = (XSCUGIC500_DCTLR_ARE_NS_ENABLE | XSCUGIC500_DCTLR_ARE_S_ENABLE); + temp &= ~(XSCUGIC_EN_INT_MASK); + XScuGic_DistWriteReg(InstancePtr, XSCUGIC_DIST_EN_OFFSET, temp); +#else + XScuGic_DistWriteReg(InstancePtr, XSCUGIC_DIST_EN_OFFSET, 0U); +#endif + + /* + * Set the security domains in the int_security registers for + * non-secure interrupts + * All are secure, so leave at the default. Set to 1 for non-secure + * interrupts. + */ + + /* + * For the Shared Peripheral Interrupts INT_ID[MAX..32], set: + */ + + /* + * 1. The trigger mode in the int_config register + * Only write to the SPI interrupts, so start at 32 + */ + for (Int_Id = 32U; Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS; + Int_Id = Int_Id+16U) { + /* + * Each INT_ID uses two bits, or 16 INT_ID per register + * Set them all to be level sensitive, active HIGH. + */ + XScuGic_DistWriteReg(InstancePtr, + XSCUGIC_INT_CFG_OFFSET_CALC(Int_Id), + 0U); + } + + +#define DEFAULT_PRIORITY 0xa0a0a0a0U + for (Int_Id = 0U; Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS; + Int_Id = Int_Id+4U) { + /* + * 2. The priority using int the priority_level register + * The priority_level and spi_target registers use one byte per + * INT_ID. + * Write a default value that can be changed elsewhere. + */ + XScuGic_DistWriteReg(InstancePtr, + XSCUGIC_PRIORITY_OFFSET_CALC(Int_Id), + DEFAULT_PRIORITY); + } + +#if defined (versal) && !defined(ARMR5) +for (Int_Id = 32U; Int_IdBaseAddress for this parameters, passing the physical +* address instead. +* +* @return +* - XST_SUCCESS if initialization was successful +* +* @note None. +* +******************************************************************************/ +s32 XScuGic_CfgInitialize(XScuGic *InstancePtr, + XScuGic_Config *ConfigPtr, + u32 EffectiveAddr) +{ + u32 Int_Id; + u32 Cpu_Id = CpuId + (u32)1; + (void) EffectiveAddr; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(ConfigPtr != NULL); + /* + * Detect Zynq-7000 base silicon configuration,Dual or Single CPU. + * If it is single CPU cnfiguration then invoke assert for CPU ID=1 + */ +#ifdef ARMA9 + if (XPAR_CPU_ID == 0x01) { + Xil_AssertNonvoid((Xil_In32(XPS_EFUSE_BASEADDR + + EFUSE_STATUS_OFFSET) & EFUSE_STATUS_CPU_MASK) == 0); + } +#endif + + if(InstancePtr->IsReady != XIL_COMPONENT_IS_READY) { + + InstancePtr->IsReady = 0U; + InstancePtr->Config = ConfigPtr; + + + for (Int_Id = 0U; Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS; + Int_Id++) { + /* + * Initalize the handler to point to a stub to handle an + * interrupt which has not been connected to a handler + * Only initialize it if the handler is 0 which means it + * was not initialized statically by the tools/user. Set + * the callback reference to this instance so that + * unhandled interrupts can be tracked. + */ + if ((InstancePtr->Config->HandlerTable[Int_Id].Handler + == (Xil_InterruptHandler)NULL)) { + InstancePtr->Config->HandlerTable[Int_Id].Handler + = (Xil_InterruptHandler)StubHandler; + } + InstancePtr->Config->HandlerTable[Int_Id].CallBackRef = + InstancePtr; + } +#if defined (versal) && !defined(ARMR5) + u32 Waker_State; + xil_printf("Execuing on the a72\n"); + Waker_State = XScuGic_ReDistReadReg(InstancePtr,XSCUGIC_RDIST_WAKER_OFFSET); + XScuGic_ReDistWriteReg(InstancePtr,XSCUGIC_RDIST_WAKER_OFFSET, + Waker_State & (~ XSCUGIC_RDIST_WAKER_LOW_POWER_STATE_MASK)); + /* Enable system reg interface through ICC_SRE_EL1 */ + #if EL3 + XScuGic_Enable_SystemReg_CPU_Interface_EL3(); + #endif + XScuGic_Enable_SystemReg_CPU_Interface_EL1(); + isb(); +#endif + XScuGic_Stop(InstancePtr); + DistributorInit(InstancePtr, Cpu_Id); +#if defined (versal) && !defined(ARMR5) + XScuGic_set_priority_filter(0xff); +#else + CPUInitialize(InstancePtr); +#endif + + InstancePtr->IsReady = XIL_COMPONENT_IS_READY; + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* Makes the connection between the Int_Id of the interrupt source and the +* associated handler that is to run when the interrupt is recognized. The +* argument provided in this call as the Callbackref is used as the argument +* for the handler when it is called. +* +* @param InstancePtr is a pointer to the XScuGic instance. +* @param Int_Id contains the ID of the interrupt source and should be +* in the range of 0 to XSCUGIC_MAX_NUM_INTR_INPUTS - 1 +* @param Handler to the handler for that interrupt. +* @param CallBackRef is the callback reference, usually the instance +* pointer of the connecting driver. +* +* @return +* +* - XST_SUCCESS if the handler was connected correctly. +* +* @note +* +* WARNING: The handler provided as an argument will overwrite any handler +* that was previously connected. +* +****************************************************************************/ +s32 XScuGic_Connect(XScuGic *InstancePtr, u32 Int_Id, + Xil_InterruptHandler Handler, void *CallBackRef) +{ + /* + * Assert the arguments + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS); + Xil_AssertNonvoid(Handler != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * The Int_Id is used as an index into the table to select the proper + * handler + */ + InstancePtr->Config->HandlerTable[Int_Id].Handler = (Xil_InterruptHandler)Handler; + InstancePtr->Config->HandlerTable[Int_Id].CallBackRef = CallBackRef; + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* Updates the interrupt table with the Null Handler and NULL arguments at the +* location pointed at by the Int_Id. This effectively disconnects that interrupt +* source from any handler. The interrupt is disabled also. +* +* @param InstancePtr is a pointer to the XScuGic instance to be worked on. +* @param Int_Id contains the ID of the interrupt source and should +* be in the range of 0 to XSCUGIC_MAX_NUM_INTR_INPUTS - 1 +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void XScuGic_Disconnect(XScuGic *InstancePtr, u32 Int_Id) +{ + u32 Mask; + + /* + * Assert the arguments + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * The Int_Id is used to create the appropriate mask for the + * desired bit position. Int_Id currently limited to 0 - 31 + */ + Mask = 0x00000001U << (Int_Id % 32U); + + /* + * Disable the interrupt such that it won't occur while disconnecting + * the handler, only disable the specified interrupt id without + * modifying the other interrupt ids + */ + XScuGic_DistWriteReg(InstancePtr, (u32)XSCUGIC_DISABLE_OFFSET + + ((Int_Id / 32U) * 4U), Mask); + + /* + * Disconnect the handler and connect a stub, the callback reference + * must be set to this instance to allow unhandled interrupts to be + * tracked + */ + InstancePtr->Config->HandlerTable[Int_Id].Handler = (Xil_InterruptHandler)StubHandler; + InstancePtr->Config->HandlerTable[Int_Id].CallBackRef = InstancePtr; +} + +/*****************************************************************************/ +/** +* +* Enables the interrupt source provided as the argument Int_Id. Any pending +* interrupt condition for the specified Int_Id will occur after this function is +* called. +* +* @param InstancePtr is a pointer to the XScuGic instance. +* @param Int_Id contains the ID of the interrupt source and should be +* in the range of 0 to XSCUGIC_MAX_NUM_INTR_INPUTS - 1 +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void XScuGic_Enable(XScuGic *InstancePtr, u32 Int_Id) +{ + u32 Mask; +#if defined (versal) && !defined(ARMR5) + u32 temp; +#endif + /* + * Assert the arguments + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + +#if defined (versal) && !defined(ARMR5) + if (Int_Id < XSCUGIC_SPI_INT_ID_START) + { + + Int_Id &= 0x1f; + Int_Id = 1 << Int_Id; + + temp = XScuGic_ReDistSGIPPIReadReg(InstancePtr,XSCUGIC_RDIST_ISENABLE_OFFSET); + temp |= Int_Id; + XScuGic_ReDistSGIPPIWriteReg(InstancePtr,XSCUGIC_RDIST_ISENABLE_OFFSET,temp); + return; + } +#endif + /* + * The Int_Id is used to create the appropriate mask for the + * desired bit position. Int_Id currently limited to 0 - 31 + */ + Mask = 0x00000001U << (Int_Id % 32U); + + /* + * Enable the selected interrupt source by setting the + * corresponding bit in the Enable Set register. + */ + XScuGic_DistWriteReg(InstancePtr, (u32)XSCUGIC_ENABLE_SET_OFFSET + + ((Int_Id / 32U) * 4U), Mask); +} + +/*****************************************************************************/ +/** +* +* Disables the interrupt source provided as the argument Int_Id such that the +* interrupt controller will not cause interrupts for the specified Int_Id. The +* interrupt controller will continue to hold an interrupt condition for the +* Int_Id, but will not cause an interrupt. +* +* @param InstancePtr is a pointer to the XScuGic instance. +* @param Int_Id contains the ID of the interrupt source and should be +* in the range of 0 to XSCUGIC_MAX_NUM_INTR_INPUTS - 1 +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void XScuGic_Disable(XScuGic *InstancePtr, u32 Int_Id) +{ + u32 Mask; + + /* + * Assert the arguments + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * The Int_Id is used to create the appropriate mask for the + * desired bit position. Int_Id currently limited to 0 - 31 + */ + Mask = 0x00000001U << (Int_Id % 32U); + + /* + * Disable the selected interrupt source by setting the + * corresponding bit in the IDR. + */ + XScuGic_DistWriteReg(InstancePtr, (u32)XSCUGIC_DISABLE_OFFSET + + ((Int_Id / 32U) * 4U), Mask); +} + +/*****************************************************************************/ +/** +* +* Allows software to simulate an interrupt in the interrupt controller. This +* function will only be successful when the interrupt controller has been +* started in simulation mode. A simulated interrupt allows the interrupt +* controller to be tested without any device to drive an interrupt input +* signal into it. +* +* @param InstancePtr is a pointer to the XScuGic instance. +* @param Int_Id is the software interrupt ID to simulate an interrupt. +* @param Cpu_Id is the list of CPUs to send the interrupt. +* +* @return +* +* XST_SUCCESS if successful, or XST_FAILURE if the interrupt could not be +* simulated +* +* @note None. +* +******************************************************************************/ +s32 XScuGic_SoftwareIntr(XScuGic *InstancePtr, u32 Int_Id, u32 Cpu_Id) +{ + u32 Mask; + + /* + * Assert the arguments + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(Int_Id <= 15U); + Xil_AssertNonvoid(Cpu_Id <= 255U); + +#if defined (versal) && !defined(ARMR5) + Mask = (Cpu_Id | (Int_Id << XSCUGIC_SGIR_EL1_INITID_SHIFT)); +#if EL3 + XScuGic_WriteICC_SGI0R_EL1(Mask); +#else + XScuGic_WriteICC_SGI1R_EL1(Mask); +#endif +#else + + /* + * The Int_Id is used to create the appropriate mask for the + * desired interrupt. Int_Id currently limited to 0 - 15 + * Use the target list for the Cpu ID. + */ + Mask = ((Cpu_Id << 16U) | Int_Id) & + (XSCUGIC_SFI_TRIG_CPU_MASK | XSCUGIC_SFI_TRIG_INTID_MASK); + + /* + * Write to the Software interrupt trigger register. Use the appropriate + * CPU Int_Id. + */ + XScuGic_DistWriteReg(InstancePtr, XSCUGIC_SFI_TRIG_OFFSET, Mask); + + /* Indicate the interrupt was successfully simulated */ +#endif + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* A stub for the asynchronous callback. The stub is here in case the upper +* layers forget to set the handler. +* +* @param CallBackRef is a pointer to the upper layer callback reference +* +* @return None. +* +* @note None. +* +******************************************************************************/ +static void StubHandler(void *CallBackRef) +{ + /* + * verify that the inputs are valid + */ + Xil_AssertVoid(CallBackRef != NULL); + + /* + * Indicate another unhandled interrupt for stats + */ + ((XScuGic *)((void *)CallBackRef))->UnhandledInterrupts++; +} + +/****************************************************************************/ +/** +* Sets the interrupt priority and trigger type for the specificd IRQ source. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param Int_Id is the IRQ source number to modify +* @param Priority is the new priority for the IRQ source. 0 is highest +* priority, 0xF8(248) is lowest. There are 32 priority levels +* supported with a step of 8. Hence the supported priorities are +* 0, 8, 16, 32, 40 ..., 248. +* @param Trigger is the new trigger type for the IRQ source. +* Each bit pair describes the configuration for an INT_ID. +* SFI Read Only b10 always +* PPI Read Only depending on how the PPIs are configured. +* b01 Active HIGH level sensitive +* b11 Rising edge sensitive +* SPI LSB is read only. +* b01 Active HIGH level sensitive +* b11 Rising edge sensitive/ +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XScuGic_SetPriorityTriggerType(XScuGic *InstancePtr, u32 Int_Id, + u8 Priority, u8 Trigger) +{ + u32 RegValue; +#if defined (versal) && !defined(ARMR5) + u32 temp,Index; +#endif + u8 LocalPriority; + LocalPriority = Priority; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS); + Xil_AssertVoid(Trigger <= (u8)XSCUGIC_INT_CFG_MASK); + Xil_AssertVoid(LocalPriority <= (u8)XSCUGIC_MAX_INTR_PRIO_VAL); +#if defined (versal) && !defined(ARMR5) + if (Int_Id < XSCUGIC_SPI_INT_ID_START ) + { + XScuGic_ReDistSGIPPIWriteReg(InstancePtr,XSCUGIC_RDIST_INT_PRIORITY_OFFSET_CALC(Int_Id),Priority); + temp = XScuGic_ReDistSGIPPIReadReg(InstancePtr,XSCUGIC_RDIST_INT_CONFIG_OFFSET_CALC(Int_Id)); + Index = XScuGic_Get_Rdist_Int_Trigger_Index(Int_Id); + temp |= (Trigger << Index); + XScuGic_ReDistSGIPPIWriteReg(InstancePtr,XSCUGIC_RDIST_INT_CONFIG_OFFSET_CALC(Int_Id),temp); + return; + } +#endif + + /* + * Determine the register to write to using the Int_Id. + */ + RegValue = XScuGic_DistReadReg(InstancePtr, + XSCUGIC_PRIORITY_OFFSET_CALC(Int_Id)); + + /* + * The priority bits are Bits 7 to 3 in GIC Priority Register. This + * means the number of priority levels supported are 32 and they are + * in steps of 8. The priorities can be 0, 8, 16, 32, 48, ... etc. + * The lower order 3 bits are masked before putting it in the register. + */ + LocalPriority = LocalPriority & (u8)XSCUGIC_INTR_PRIO_MASK; + /* + * Shift and Mask the correct bits for the priority and trigger in the + * register + */ + RegValue &= ~(XSCUGIC_PRIORITY_MASK << ((Int_Id%4U)*8U)); + RegValue |= (u32)LocalPriority << ((Int_Id%4U)*8U); + + /* + * Write the value back to the register. + */ + XScuGic_DistWriteReg(InstancePtr, XSCUGIC_PRIORITY_OFFSET_CALC(Int_Id), + RegValue); + + /* + * Determine the register to write to using the Int_Id. + */ + RegValue = XScuGic_DistReadReg(InstancePtr, + XSCUGIC_INT_CFG_OFFSET_CALC(Int_Id)); + + /* + * Shift and Mask the correct bits for the priority and trigger in the + * register + */ + RegValue &= ~(XSCUGIC_INT_CFG_MASK << ((Int_Id%16U)*2U)); + RegValue |= (u32)Trigger << ((Int_Id%16U)*2U); + + /* + * Write the value back to the register. + */ + XScuGic_DistWriteReg(InstancePtr, XSCUGIC_INT_CFG_OFFSET_CALC(Int_Id), + RegValue); + +} + +/****************************************************************************/ +/** +* Gets the interrupt priority and trigger type for the specificd IRQ source. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param Int_Id is the IRQ source number to modify +* @param Priority is a pointer to the value of the priority of the IRQ +* source. This is a return value. +* @param Trigger is pointer to the value of the trigger of the IRQ +* source. This is a return value. +* +* @return None. +* +* @note None +* +*****************************************************************************/ +void XScuGic_GetPriorityTriggerType(XScuGic *InstancePtr, u32 Int_Id, + u8 *Priority, u8 *Trigger) +{ + u32 RegValue; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS); + Xil_AssertVoid(Priority != NULL); + Xil_AssertVoid(Trigger != NULL); + + /* + * Determine the register to read to using the Int_Id. + */ + RegValue = XScuGic_DistReadReg(InstancePtr, + XSCUGIC_PRIORITY_OFFSET_CALC(Int_Id)); + + /* + * Shift and Mask the correct bits for the priority and trigger in the + * register + */ + RegValue = RegValue >> ((Int_Id%4U)*8U); + *Priority = (u8)(RegValue & XSCUGIC_PRIORITY_MASK); + + /* + * Determine the register to read to using the Int_Id. + */ + RegValue = XScuGic_DistReadReg(InstancePtr, + XSCUGIC_INT_CFG_OFFSET_CALC(Int_Id)); + + /* + * Shift and Mask the correct bits for the priority and trigger in the + * register + */ + RegValue = RegValue >> ((Int_Id%16U)*2U); + + *Trigger = (u8)(RegValue & XSCUGIC_INT_CFG_MASK); +} +/****************************************************************************/ +/** +* Sets the target CPU for the interrupt of a peripheral +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param Cpu_Id is a CPU number for which the interrupt has to be targeted +* @param Int_Id is the IRQ source number to modify +* +* @return None. +* +* @note None +* +*****************************************************************************/ +void XScuGic_InterruptMaptoCpu(XScuGic *InstancePtr, u8 Cpu_Id, u32 Int_Id) +{ + u32 RegValue; + u32 Offset; + RegValue = XScuGic_DistReadReg(InstancePtr, + XSCUGIC_SPI_TARGET_OFFSET_CALC(Int_Id)); + + Offset = (Int_Id & 0x3U); + Cpu_Id = (0x1U << Cpu_Id); + + RegValue = (RegValue & (~(0xFFU << (Offset*8U)))); + RegValue |= ((Cpu_Id) << (Offset*8U)); + + XScuGic_DistWriteReg(InstancePtr, + XSCUGIC_SPI_TARGET_OFFSET_CALC(Int_Id), + RegValue); +} +/****************************************************************************/ +/** +* Unmaps specific SPI interrupt from the target CPU +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param Cpu_Id is a CPU number from which the interrupt has to be +* unmapped +* @param Int_Id is the IRQ source number to modify +* +* @return None. +* +* @note None +* +*****************************************************************************/ +void XScuGic_InterruptUnmapFromCpu(XScuGic *InstancePtr, u8 Cpu_Id, u32 Int_Id) +{ + u32 RegValue; + u8 BitPos; + + Xil_AssertVoid(InstancePtr != NULL); + + RegValue = XScuGic_DistReadReg(InstancePtr, + XSCUGIC_SPI_TARGET_OFFSET_CALC(Int_Id)); + + /* + * Identify bit position corresponding to Int_Id and Cpu_Id, + * in interrupt target register and clear it + */ + BitPos = ((Int_Id % 4U) * 8U) + Cpu_Id; + RegValue &= (~(1U << BitPos)); + XScuGic_DistWriteReg(InstancePtr, + XSCUGIC_SPI_TARGET_OFFSET_CALC(Int_Id), + RegValue); +} +/****************************************************************************/ +/** +* Unmaps all SPI interrupts from the target CPU +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param Cpu_Id is a CPU number from which the interrupts has to be +* unmapped +* +* @return None. +* +* @note None +* +*****************************************************************************/ +void XScuGic_UnmapAllInterruptsFromCpu(XScuGic *InstancePtr, u8 Cpu_Id) +{ + u32 Int_Id; + u32 Target_Cpu; + u32 LocalCpuID = (1U << Cpu_Id); + + Xil_AssertVoid(InstancePtr != NULL); + + LocalCpuID |= LocalCpuID << 8U; + LocalCpuID |= LocalCpuID << 16U; + + for (Int_Id = 32U; Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS; + Int_Id = Int_Id+4U) { + + Target_Cpu = XScuGic_DistReadReg(InstancePtr, + XSCUGIC_SPI_TARGET_OFFSET_CALC(Int_Id)); + /* Remove LocalCpuID from interrupt target register */ + Target_Cpu &= (~LocalCpuID); + XScuGic_DistWriteReg(InstancePtr, + XSCUGIC_SPI_TARGET_OFFSET_CALC(Int_Id), Target_Cpu); + + } +} +/****************************************************************************/ +/** +* It checks if the interrupt target register contains all interrupts to be +* targeted for current CPU. If they are programmed to be forwarded to current +* cpu, this API disable all interrupts and disable GIC distributor. +* This API also removes current CPU from interrupt target registers for all +* interrupt. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* +* @return None. +* +* @note None +* +*****************************************************************************/ +void XScuGic_Stop(XScuGic *InstancePtr) +{ + u32 Int_Id; + u32 RegValue; + u32 Target_Cpu; + u32 DistDisable = 1; /* Track distributor status*/ + u32 LocalCpuID = ((u32)0x1 << CpuId); + + Xil_AssertVoid(InstancePtr != NULL); + + /* If distributor is already disabled, no need to do anything */ + RegValue = XScuGic_DistReadReg(InstancePtr, XSCUGIC_DIST_EN_OFFSET); + if ((RegValue & XSCUGIC_EN_INT_MASK) == 0U) { + return; + } + + LocalCpuID |= LocalCpuID << 8U; + LocalCpuID |= LocalCpuID << 16U; + + /* + * Check if the interrupt are targeted to current cpu only or not. + * Also remove current cpu from interrupt target register for all + * interrupts. + */ + for (Int_Id = 32U; Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS; + Int_Id = Int_Id+4U) { + + Target_Cpu = XScuGic_DistReadReg(InstancePtr, + XSCUGIC_SPI_TARGET_OFFSET_CALC(Int_Id)); + if ((Target_Cpu != LocalCpuID) && (Target_Cpu != 0)) { + /* + * If any other CPU is also programmed to target + * register, GIC distributor can not be disabled. + */ + DistDisable = 0; + } + + /* Remove current CPU from interrupt target register */ + Target_Cpu &= (~LocalCpuID); + XScuGic_DistWriteReg(InstancePtr, + XSCUGIC_SPI_TARGET_OFFSET_CALC(Int_Id), Target_Cpu); + + } + + /* + * If GIC distributor is safe to be disabled, disable all the interrupt + * and then disable distributor. + */ + if (DistDisable == 1) { + for (Int_Id = 0U; Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS; + Int_Id = Int_Id+32U) { + /* + * Disable all the interrupts + */ + XScuGic_DistWriteReg(InstancePtr, + XSCUGIC_EN_DIS_OFFSET_CALC(XSCUGIC_DISABLE_OFFSET, + Int_Id), + 0xFFFFFFFFU); + } + XScuGic_DistWriteReg(InstancePtr, XSCUGIC_DIST_EN_OFFSET, 0U); + } +} + +/****************************************************************************/ +/** +* This updates the CpuId global variable. +* +* @param CpuCoreId is the CPU core number. +* +* @return None. +* +* @note None +* +*****************************************************************************/ +void XScuGic_SetCpuID(u32 CpuCoreId) +{ + Xil_AssertVoid(CpuCoreId <= 1U); + + CpuId = CpuCoreId; +} + +/****************************************************************************/ +/** +* This function returns the CpuId variable. +* +* @return The CPU core number. +* +* @note None. +* +*****************************************************************************/ +u32 XScuGic_GetCpuID(void) +{ + return CpuId; +} +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/scugic_v4_0/src/xscugic.h b/df_datalink/bsp/ps7_cortexa9_0/libsrc/scugic_v4_0/src/xscugic.h new file mode 100644 index 0000000..5502a20 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/scugic_v4_0/src/xscugic.h @@ -0,0 +1,598 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xscugic.h +* @addtogroup scugic_v4_0 +* @{ +* @details +* +* The generic interrupt controller driver component. +* +* The interrupt controller driver uses the idea of priority for the various +* handlers. Priority is an integer within the range of 1 and 31 inclusive with +* default of 1 being the highest priority interrupt source. The priorities +* of the various sources can be dynamically altered as needed through +* hardware configuration. +* +* The generic interrupt controller supports the following +* features: +* +* - specific individual interrupt enabling/disabling +* - specific individual interrupt acknowledging +* - attaching specific callback function to handle interrupt source +* - assigning desired priority to interrupt source if default is not +* acceptable. +* +* Details about connecting the interrupt handler of the driver are contained +* in the source file specific to interrupt processing, xscugic_intr.c. +* +* This driver is intended to be RTOS and processor independent. It works with +* physical addresses only. Any needs for dynamic memory management, threads +* or thread mutual exclusion, virtual memory, or cache control must be +* satisfied by the layer above this driver. +* +* Interrupt Vector Tables +* +* The device ID of the interrupt controller device is used by the driver as a +* direct index into the configuration data table. The user should populate the +* vector table with handlers and callbacks at run-time using the +* XScuGic_Connect() and XScuGic_Disconnect() functions. +* +* Each vector table entry corresponds to a device that can generate an +* interrupt. Each entry contains an interrupt handler function and an +* argument to be passed to the handler when an interrupt occurs. The +* user must use XScuGic_Connect() when the interrupt handler takes an +* argument other than the base address. +* +* Nested Interrupts Processing +* +* Nested interrupts are not supported by this driver. +* +* NOTE: +* The generic interrupt controller is not a part of the snoop control unit +* as indicated by the prefix "scu" in the name of the driver. +* It is an independent module in APU. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- ---------------------------------------------------------
+* 1.00a drg  01/19/00 First release
+* 1.01a sdm  11/09/11 The XScuGic and XScuGic_Config structures have changed.
+*		      The HandlerTable (of type XScuGic_VectorTableEntry) is
+*		      moved to XScuGic_Config structure from XScuGic structure.
+*
+*		      The "Config" entry in XScuGic structure is made as
+*		      pointer for better efficiency.
+*
+*		      A new file named as xscugic_hw.c is now added. It is
+*		      to implement low level driver routines without using
+*		      any xscugic instance pointer. They are useful when the
+*		      user wants to use xscugic through device id or
+*		      base address. The driver routines provided are explained
+*		      below.
+*		      XScuGic_DeviceInitialize that takes device id as
+*		      argument and initializes the device (without calling
+*		      XScuGic_CfgInitialize).
+*		      XScuGic_DeviceInterruptHandler that takes device id
+*		      as argument and calls appropriate handlers from the
+*		      HandlerTable.
+*		      XScuGic_RegisterHandler that registers a new handler
+*		      by taking xscugic hardware base address as argument.
+*		      LookupConfigByBaseAddress is used to return the
+*		      corresponding config structure from XScuGic_ConfigTable
+*		      based on the scugic base address passed.
+* 1.02a sdm  12/20/11 Removed AckBeforeService from the XScuGic_Config
+*		      structure.
+* 1.03a srt  02/27/13 Moved Offset calculation macros from *.c and *_hw.c to
+*		      *_hw.h
+*		      Added APIs
+*			- XScuGic_SetPriTrigTypeByDistAddr()
+*			- XScuGic_GetPriTrigTypeByDistAddr()
+*		      (CR 702687)
+*			Added support to direct interrupts to the appropriate CPU. Earlier
+*			  interrupts were directed to CPU1 (hard coded). Now depending
+*			  upon the CPU selected by the user (xparameters.h), interrupts
+*			  will be directed to the relevant CPU. This fixes CR 699688.
+* 1.04a hk   05/04/13 Assigned EffectiveAddr to CpuBaseAddress in
+*			  XScuGic_CfgInitialize. Fix for CR#704400 to remove warnings.
+*			  Moved functions XScuGic_SetPriTrigTypeByDistAddr and
+*             XScuGic_GetPriTrigTypeByDistAddr to xscugic_hw.c.
+*			  This is fix for CR#705621.
+* 1.05a hk   06/26/13 Modified tcl to export external interrupts correctly to
+*                     xparameters.h. Fix for CR's 690505, 708928 & 719359.
+* 2.0   adk  12/10/13 Updated as per the New Tcl API's
+* 2.1   adk  25/04/14 Fixed the CR:789373 changes are made in the driver tcl file.
+* 3.00  kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.2   asa  02/29/16 Modified DistributorInit function for Zynq AMP case. The
+*			  distributor is left uninitialized for Zynq AMP. It is assumed
+*             that the distributor will be initialized by Linux master. However
+*             for CortexR5 case, the earlier code is left unchanged where the
+*             the interrupt processor target registers in the distributor is
+*             initialized with the corresponding CPU ID on which the application
+*             built over the scugic driver runs.
+*             These changes fix CR#937243.
+*
+* 3.4   asa  04/07/16 Created a new static function DoDistributorInit to simplify
+*            the flow and avoid code duplication. Changes are made for
+*            USE_AMP use case for R5. In a scenario (in R5 split mode) when
+*            one R5 is operating with A53 in open amp config and other
+*            R5 running baremetal app, the existing code
+*            had the potential to stop the whole AMP solution to work (if
+*            for some reason the R5 running the baremetal app tasked to
+*            initialize the Distributor hangs or crashes before initializing).
+*            Changes are made so that the R5 under AMP first checks if
+*            the distributor is enabled or not and if not, it does the
+*            standard Distributor initialization.
+*            This fixes the CR#952962.
+* 3.6   ms   01/23/17 Modified xil_printf statement in main function for all
+*                     examples to ensure that "Successfully ran" and "Failed"
+*                     strings are available in all examples. This is a fix
+*                     for CR-965028.
+*       kvn  02/17/17 Add support for changing GIC CPU master at run time.
+*       kvn  02/28/17 Make the CpuId as static variable and Added new
+*                     XScugiC_GetCpuId to access CpuId.
+*       ms   03/17/17 Added readme.txt file in examples folder for doxygen
+*                     generation.
+* 3.7   ms   04/11/17 Modified tcl file to add suffix U for all macro
+*                     definitions of scugic in xparameters.h
+* 3.8   mus  07/05/17 Updated scugic.tcl to add support for intrrupts connected
+*                     through util_reduced_vector IP(OR gate)
+*       mus  07/05/17 Updated xdefine_zynq_canonical_xpars proc to initialize
+*                     the HandlerTable in XScuGic_ConfigTable to 0, it removes
+*                     the compilation warning in xscugic_g.c. Fix for CR#978736.
+*       mus  07/25/17 Updated xdefine_gic_params proc to export correct canonical
+*                     definitions for pl to ps interrupts.Fix for CR#980534
+* 3.9   mus  02/21/18 Added new API's XScuGic_UnmapAllInterruptsFromCpu and
+*                     XScuGic_InterruptUnmapFromCpu, These API's can be used
+*                     by applications to unmap specific/all interrupts from
+*                     target CPU.
+* 3.10  aru  08/23/18 Resolved MISRA-C:2012 compliance mandatory violations
+* 4.0   mus  11/22/18 Fixed bugs in software interrupt generation through 
+*                      XScuGic_SoftwareIntr API
+*
+* 
+* +******************************************************************************/ + +#ifndef XSCUGIC_H /* prevent circular inclusions */ +#define XSCUGIC_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + + +/***************************** Include Files *********************************/ + +#include "xstatus.h" +#include "xil_io.h" +#include "xscugic_hw.h" +#include "xil_exception.h" + +/************************** Constant Definitions *****************************/ + +#define EFUSE_STATUS_OFFSET 0x10 +#define EFUSE_STATUS_CPU_MASK 0x80 + +#if !defined (ARMR5) && !defined (__aarch64__) && !defined (ARMA53_32) +#define ARMA9 +#endif + +#define XSCUGIC500_DCTLR_ARE_NS_ENABLE 0x20 +#define XSCUGIC500_DCTLR_ARE_S_ENABLE 0x10 +/**************************** Type Definitions *******************************/ + +/* The following data type defines each entry in an interrupt vector table. + * The callback reference is the base address of the interrupting device + * for the low level driver and an instance pointer for the high level driver. + */ +typedef struct +{ + Xil_InterruptHandler Handler; + void *CallBackRef; +} XScuGic_VectorTableEntry; + +/** + * This typedef contains configuration information for the device. + */ +typedef struct +{ + u16 DeviceId; /**< Unique ID of device */ + u32 CpuBaseAddress; /**< CPU Interface Register base address */ + u32 DistBaseAddress; /**< Distributor Register base address */ + XScuGic_VectorTableEntry HandlerTable[XSCUGIC_MAX_NUM_INTR_INPUTS];/**< + Vector table of interrupt handlers */ +} XScuGic_Config; + +/** + * The XScuGic driver instance data. The user is required to allocate a + * variable of this type for every intc device in the system. A pointer + * to a variable of this type is then passed to the driver API functions. + */ +typedef struct +{ + XScuGic_Config *Config; /**< Configuration table entry */ + u32 IsReady; /**< Device is initialized and ready */ + u32 UnhandledInterrupts; /**< Intc Statistics */ +} XScuGic; + +/***************** Macros (Inline Functions) Definitions *********************/ + +/****************************************************************************/ +/** +* +* Write the given CPU Interface register +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param RegOffset is the register offset to be written +* @param Data is the 32-bit value to write to the register +* +* @return None. +* +* @note +* C-style signature: +* void XScuGic_CPUWriteReg(XScuGic *InstancePtr, u32 RegOffset, u32 Data) +* +*****************************************************************************/ +#define XScuGic_CPUWriteReg(InstancePtr, RegOffset, Data) \ +(XScuGic_WriteReg(((InstancePtr)->Config->CpuBaseAddress), (RegOffset), \ + ((u32)(Data)))) + +/****************************************************************************/ +/** +* +* Read the given CPU Interface register +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param RegOffset is the register offset to be read +* +* @return The 32-bit value of the register +* +* @note +* C-style signature: +* u32 XScuGic_CPUReadReg(XScuGic *InstancePtr, u32 RegOffset) +* +*****************************************************************************/ +#define XScuGic_CPUReadReg(InstancePtr, RegOffset) \ + (XScuGic_ReadReg(((InstancePtr)->Config->CpuBaseAddress), (RegOffset))) + +/****************************************************************************/ +/** +* +* Write the given Distributor Interface register +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param RegOffset is the register offset to be written +* @param Data is the 32-bit value to write to the register +* +* @return None. +* +* @note +* C-style signature: +* void XScuGic_DistWriteReg(XScuGic *InstancePtr, u32 RegOffset, u32 Data) +* +*****************************************************************************/ +#define XScuGic_DistWriteReg(InstancePtr, RegOffset, Data) \ +(XScuGic_WriteReg(((InstancePtr)->Config->DistBaseAddress), (RegOffset), \ + ((u32)(Data)))) + +/****************************************************************************/ +/** +* +* Read the given Distributor Interface register +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param RegOffset is the register offset to be read +* +* @return The 32-bit value of the register +* +* @note +* C-style signature: +* u32 XScuGic_DistReadReg(XScuGic *InstancePtr, u32 RegOffset) +* +*****************************************************************************/ +#define XScuGic_DistReadReg(InstancePtr, RegOffset) \ +(XScuGic_ReadReg(((InstancePtr)->Config->DistBaseAddress), (RegOffset))) + +/****************************************************************************/ +/** +* +* Write the given ReDistributor Interface register +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param RegOffset is the register offset to be written +* @param Data is the 32-bit value to write to the register +* +* @return None. +* +* @note +* C-style signature: +* void XScuGic_DistWriteReg(XScuGic *InstancePtr, u32 RegOffset, u32 Data) +* +*****************************************************************************/ +#define XScuGic_ReDistWriteReg(InstancePtr, RegOffset, Data) \ +(XScuGic_WriteReg(((InstancePtr)->Config->DistBaseAddress)+ \ + XSCUGIC_RDIST_OFFSET, (RegOffset), ((u32)(Data)))) + +/****************************************************************************/ +/** +* +* Read the given ReDistributor Interface register +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param RegOffset is the register offset to be read +* +* @return The 32-bit value of the register +* +* @note +* C-style signature: +* u32 XScuGic_DistReadReg(XScuGic *InstancePtr, u32 RegOffset) +* +*****************************************************************************/ +#define XScuGic_ReDistReadReg(InstancePtr, RegOffset) \ +(XScuGic_ReadReg((((InstancePtr)->Config->DistBaseAddress)+ \ +XSCUGIC_RDIST_OFFSET), (RegOffset))) + +/****************************************************************************/ +/** +* +* Write the given ReDistributor SGI PPI Interface register +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param RegOffset is the register offset to be written +* @param Data is the 32-bit value to write to the register +* +* @return None. +* +* @note +* C-style signature: +* void XScuGic_DistWriteReg(XScuGic *InstancePtr, u32 RegOffset, u32 Data) +* +*****************************************************************************/ +#define XScuGic_ReDistSGIPPIWriteReg(InstancePtr, RegOffset, Data) \ +(XScuGic_WriteReg(((InstancePtr)->Config->DistBaseAddress)+ \ + XSCUGIC_RDIST_SGI_PPI_OFFSET, (RegOffset), ((u32)(Data)))) + +/****************************************************************************/ +/** +* +* Read the given ReDistributor SGI PPI Interface register +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param RegOffset is the register offset to be read +* +* @return The 32-bit value of the register +* +* @note +* C-style signature: +* u32 XScuGic_DistReadReg(XScuGic *InstancePtr, u32 RegOffset) +* +*****************************************************************************/ +#define XScuGic_ReDistSGIPPIReadReg(InstancePtr, RegOffset) \ +(XScuGic_ReadReg((((InstancePtr)->Config->DistBaseAddress)+ \ + XSCUGIC_RDIST_SGI_PPI_OFFSET), (RegOffset))) + +/****************************************************************************/ +/** +* This function enables system register interface for GIC CPU Interface +* +* @param value to be written +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +#define XScuGic_Enable_SystemReg_CPU_Interface_EL3() mtcp(S3_6_C12_C12_5, 0xF); +#define XScuGic_Enable_SystemReg_CPU_Interface_EL1() mtcp(S3_0_C12_C12_5, 0xF); +/****************************************************************************/ +/** +* This function enables Grou0 interrupts +* +* @param None. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +#define XScuGic_Enable_Group0_Interrupts() mtcp(S3_0_C12_C12_6,0x1); +/****************************************************************************/ +/** +* This function enables Group1 interrupts +* +* @param None. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +#if defined (__aarch64__) +#if EL1_NONSECURE +#define XScuGic_Enable_Group1_Interrupts() \ + mtcp (S3_0_C12_C12_7, 0x1 | mfcp(S3_0_C12_C12_7) ); +#else +#define XScuGic_Enable_Group1_Interrupts() \ + mtcp (S3_6_C12_C12_7, 0x1 | mfcp(S3_6_C12_C12_7) ); +#endif +#endif +/****************************************************************************/ +/** +* This function writes to ICC_SGI0R_EL1 +* +* @param value to be written +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +#define XScuGic_WriteICC_SGI0R_EL1(val) mtcp(S3_0_C12_C11_7,val) + +/****************************************************************************/ +/** +* This function writes to ICC_SGI1R_EL1 +* +* @param value to be written +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +#define XScuGic_WriteICC_SGI1R_EL1(val) mtcp(S3_0_C12_C11_5,val) + +/****************************************************************************/ +/** +* This function reads ICC_SGI1R_EL1 register +* +* @param None +* +* @return Value of ICC_SGI1R_EL1 register +* +* @note None. +* +*****************************************************************************/ +#define XScuGic_ReadICC_SGI1R_EL1() mfcp(S3_0_C12_C11_5) +/****************************************************************************/ +/** +* This function sets interrupt priority filter +* +* @param None. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +#define XScuGic_set_priority_filter(val) __asm__ __volatile__("msr S3_0_C4_C6_0,%0" : : "r" (val)) +/****************************************************************************/ +/** +* This function returns interrupt id of highest priority pending interrupt +* +* @param None. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +#if defined (__aarch64__) +#if EL3 +#define XScuGic_get_IntID() mfcp(S3_0_C12_C8_0) +#else +#define XScuGic_get_IntID() mfcp(S3_0_C12_C12_0) +#endif +#endif +/****************************************************************************/ +/** +* This function acks the interrupt +* +* @param None. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +#if defined (__aarch64__) +#if EL3 +#define XScuGic_ack_Int(val) mtcp(S3_0_C12_C8_1,val) +#else +#define XScuGic_ack_Int(val) mtcp(S3_0_C12_C12_1,val) +#endif +#endif +/****************************************************************************/ +/** +* This macro returns bit position for the specific interrupt's trigger type +* configuration within GICR_ICFGR0/GICR_ICFGR1 register +* +* @param None. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +#define XScuGic_Get_Rdist_Int_Trigger_Index(IntrId) (((Int_Id%16) & 0x1f) << 2) +1 +/************************** Function Prototypes ******************************/ + +/* + * Required functions in xscugic.c + */ + +s32 XScuGic_Connect(XScuGic *InstancePtr, u32 Int_Id, + Xil_InterruptHandler Handler, void *CallBackRef); +void XScuGic_Disconnect(XScuGic *InstancePtr, u32 Int_Id); + +void XScuGic_Enable(XScuGic *InstancePtr, u32 Int_Id); +void XScuGic_Disable(XScuGic *InstancePtr, u32 Int_Id); + +s32 XScuGic_CfgInitialize(XScuGic *InstancePtr, XScuGic_Config *ConfigPtr, + u32 EffectiveAddr); + +s32 XScuGic_SoftwareIntr(XScuGic *InstancePtr, u32 Int_Id, u32 Cpu_Id); + +void XScuGic_GetPriorityTriggerType(XScuGic *InstancePtr, u32 Int_Id, + u8 *Priority, u8 *Trigger); +void XScuGic_SetPriorityTriggerType(XScuGic *InstancePtr, u32 Int_Id, + u8 Priority, u8 Trigger); +void XScuGic_InterruptMaptoCpu(XScuGic *InstancePtr, u8 Cpu_Id, u32 Int_Id); +void XScuGic_InterruptUnmapFromCpu(XScuGic *InstancePtr, u8 Cpu_Id, u32 Int_Id); +void XScuGic_UnmapAllInterruptsFromCpu(XScuGic *InstancePtr, u8 Cpu_Id); +void XScuGic_Stop(XScuGic *InstancePtr); +void XScuGic_SetCpuID(u32 CpuCoreId); +u32 XScuGic_GetCpuID(void); +/* + * Initialization functions in xscugic_sinit.c + */ +XScuGic_Config *XScuGic_LookupConfig(u16 DeviceId); + +/* + * Interrupt functions in xscugic_intr.c + */ +void XScuGic_InterruptHandler(XScuGic *InstancePtr); + +/* + * Self-test functions in xscugic_selftest.c + */ +s32 XScuGic_SelfTest(XScuGic *InstancePtr); + +void XScuGic_EnableSGI_PPI(XScuGic *InstancePtr,u32 ID); +void XScuGic_SetPPI_SGI_Priority(XScuGic *InstancePtr,u32 ID, u32 priority); +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/scugic_v4_0/src/xscugic_g.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/scugic_v4_0/src/xscugic_g.c new file mode 100644 index 0000000..7363203 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/scugic_v4_0/src/xscugic_g.c @@ -0,0 +1,53 @@ + +/******************************************************************* +* +* CAUTION: This file is automatically generated by HSI. +* Version: 2019.1.3 +* DO NOT EDIT. +* +* Copyright (C) 2010-2023 Xilinx, Inc. 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 +*XILINX 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. +* +*Except as contained in this notice, the name of the Xilinx shall not be used +*in advertising or otherwise to promote the sale, use or other dealings in +*this Software without prior written authorization from Xilinx. +* + +* +* Description: Driver configuration +* +*******************************************************************/ + +#include "xparameters.h" +#include "xscugic.h" + +/* +* The configuration table for devices +*/ + +XScuGic_Config XScuGic_ConfigTable[XPAR_XSCUGIC_NUM_INSTANCES] = +{ + { + XPAR_PS7_SCUGIC_0_DEVICE_ID, + XPAR_PS7_SCUGIC_0_BASEADDR, + XPAR_PS7_SCUGIC_0_DIST_BASEADDR, + {{0}} /**< Initialize the HandlerTable to 0 */ + } +}; + + diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/scugic_v4_0/src/xscugic_hw.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/scugic_v4_0/src/xscugic_hw.c new file mode 100644 index 0000000..4193e80 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/scugic_v4_0/src/xscugic_hw.c @@ -0,0 +1,652 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xscugic_hw.c +* @addtogroup scugic_v4_0 +* @{ +* +* This file contains low-level driver functions that can be used to access the +* device. The user should refer to the hardware device specification for more +* details of the device operation. +* These routines are used when the user does not want to create an instance of +* XScuGic structure but still wants to use the ScuGic device. Hence the +* routines provided here take device id or scugic base address as arguments. +* Separate static versions of DistInit and CPUInit are provided to implement +* the low level driver routines. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.01a sdm  07/18/11 First release
+* 1.03a srt  02/27/13 Moved Offset calculation macros from *_hw.c (CR
+*                     702687).
+*                     Added support to direct interrupts to the appropriate
+*                     CPU. Earlier interrupts were directed to CPU1
+*                     (hard coded). Now depending upon the CPU selected by
+*                     the user (xparameters.h), interrupts will be directed
+*                     to the relevant CPU.This fixes CR 699688.
+* 1.04a hk   05/04/13 Fix for CR#705621. Moved functions
+*                     XScuGic_SetPriTrigTypeByDistAddr and
+*                     XScuGic_GetPriTrigTypeByDistAddr here from xscugic.c
+* 3.00  kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.6   kvn  02/17/17 Add support for changing GIC CPU master at run time.
+*       kvn  02/28/17 Make the CpuId as static variable and Added new
+*                     XScugiC_GetCpuId to access CpuId.
+* 3.9   mus  02/21/18 Added new API's
+*                     XScuGic_InterruptUnmapFromCpuByDistAddr and
+*                     XScuGic_UnmapAllInterruptsFromCpuByDistAddr, These
+*                     API's can be used by applications to unmap
+*                     specific/all interrupts from target CPU. It fixes
+*                     CR#992490.
+* 3.10  mus  07/17/18 Updated XScuGic_DeviceInterruptHandler to fix array
+*                     overrun reported by coverity tool. It fixes
+*                     CR#1006344.
+* 3.10  mus  07/17/18 Updated file to fix the various coding style issues
+*                     reported by checkpatch. It fixes CR#1006344.
+* 3.10  aru  08/23/18 Resolved MISRA-C:2012 compliance mandatory violations
+*                     It fixes CR#1007753
+* 3.10  mus  09/19/18 Update documentation for XScuGic_RegisterHandler to
+*                     fix doxygen warnings.
+* 
+* +******************************************************************************/ + + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xscugic.h" +#include "xparameters.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +static void DistInit(XScuGic_Config *Config, u32 CpuID); +static void CPUInit(XScuGic_Config *Config); +static XScuGic_Config *LookupConfigByBaseAddress(u32 CpuBaseAddress); + +/************************** Variable Definitions *****************************/ + +extern XScuGic_Config XScuGic_ConfigTable[XPAR_XSCUGIC_NUM_INSTANCES]; +extern u32 CpuId; + +/*****************************************************************************/ +/** +* +* DistInit initializes the distributor of the GIC. The +* initialization entails: +* +* - Write the trigger mode, priority and target CPU +* - All interrupt sources are disabled +* - Enable the distributor +* +* @param InstancePtr is a pointer to the XScuGic instance. +* @param CpuID is the Cpu ID to be initialized. +* +* @return None +* +* @note None. +* +******************************************************************************/ +static void DistInit(XScuGic_Config *Config, u32 CpuID) +{ + u32 Int_Id; + u32 LocalCpuID = CpuID; + +#if USE_AMP == 1 + #warning "Building GIC for AMP" + + /* + * The distrubutor should not be initialized by FreeRTOS in the case of + * AMP -- it is assumed that Linux is the master of this device in that + * case. + */ + return; +#endif + + XScuGic_WriteReg(Config->DistBaseAddress, XSCUGIC_DIST_EN_OFFSET, 0U); + + /* + * Set the security domains in the int_security registers for non-secure + * interrupts. All are secure, so leave at the default. Set to 1 for + * non-secure interrupts. + */ + + + /* + * For the Shared Peripheral Interrupts INT_ID[MAX..32], set: + */ + + /* + * 1. The trigger mode in the int_config register + * Only write to the SPI interrupts, so start at 32 + */ + for (Int_Id = 32U; Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS; + Int_Id = Int_Id+16U) { + /* + * Each INT_ID uses two bits, or 16 INT_ID per register + * Set them all to be level sensitive, active HIGH. + */ + XScuGic_WriteReg(Config->DistBaseAddress, + XSCUGIC_INT_CFG_OFFSET_CALC(Int_Id), 0U); + } + + +#define DEFAULT_PRIORITY 0xa0a0a0a0U + for (Int_Id = 0U; Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS; + Int_Id = Int_Id+4U) { + /* + * 2. The priority using int the priority_level register + * The priority_level and spi_target registers use one byte per + * INT_ID. + * Write a default value that can be changed elsewhere. + */ + XScuGic_WriteReg(Config->DistBaseAddress, + XSCUGIC_PRIORITY_OFFSET_CALC(Int_Id), + DEFAULT_PRIORITY); + } + + for (Int_Id = 32U; Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS; + Int_Id = Int_Id+4U) { + /* + * 3. The CPU interface in the spi_target register + * Only write to the SPI interrupts, so start at 32 + */ + LocalCpuID |= LocalCpuID << 8U; + LocalCpuID |= LocalCpuID << 16U; + + XScuGic_WriteReg(Config->DistBaseAddress, + XSCUGIC_SPI_TARGET_OFFSET_CALC(Int_Id), LocalCpuID); + } + + for (Int_Id = 0U; Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS; + Int_Id = Int_Id+32U) { + /* + * 4. Enable the SPI using the enable_set register. + * Leave all disabled for now. + */ + XScuGic_WriteReg(Config->DistBaseAddress, + XSCUGIC_EN_DIS_OFFSET_CALC(XSCUGIC_DISABLE_OFFSET, + Int_Id), + 0xFFFFFFFFU); + + } + + XScuGic_WriteReg(Config->DistBaseAddress, XSCUGIC_DIST_EN_OFFSET, + XSCUGIC_EN_INT_MASK); + +} + +/*****************************************************************************/ +/** +* +* CPUInit initializes the CPU Interface of the GIC. The initialization entails: +* +* - Set the priority of the CPU. +* - Enable the CPU interface +* +* @param ConfigPtr is a pointer to a config table for the particular +* device this driver is associated with. +* +* @return None +* +* @note None. +* +******************************************************************************/ +static void CPUInit(XScuGic_Config *Config) +{ + /* + * Program the priority mask of the CPU using the Priority mask + * register + */ + XScuGic_WriteReg(Config->CpuBaseAddress, XSCUGIC_CPU_PRIOR_OFFSET, + 0xF0U); + + /* + * If the CPU operates in both security domains, set parameters in the + * control_s register. + * 1. Set FIQen=1 to use FIQ for secure interrupts, + * 2. Program the AckCtl bit + * 3. Program the SBPR bit to select the binary pointer behavior + * 4. Set EnableS = 1 to enable secure interrupts + * 5. Set EnbleNS = 1 to enable non secure interrupts + */ + + /* + * If the CPU operates only in the secure domain, setup the + * control_s register. + * 1. Set FIQen=1, + * 2. Set EnableS=1, to enable the CPU interface to signal secure . + * interrupts Only enable the IRQ output unless secure interrupts + * are needed. + */ + XScuGic_WriteReg(Config->CpuBaseAddress, XSCUGIC_CONTROL_OFFSET, 0x07U); + +} + +/*****************************************************************************/ +/** +* +* Initialize the GIC based on the device id. The +* initialization entails: +* +* - Initialize distributor interface +* - Initialize cpu interface +* +* @param DeviceId is device id to be worked on. +* +* @return +* +* - XST_SUCCESS if initialization was successful +* +* @note +* +* None. +* +******************************************************************************/ +s32 XScuGic_DeviceInitialize(u32 DeviceId) +{ + XScuGic_Config *Config; + u32 Cpu_Id = XScuGic_GetCpuID() + (u32)1; + + Config = &XScuGic_ConfigTable[(u32)DeviceId]; + + DistInit(Config, Cpu_Id); + + CPUInit(Config); + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* This function is the primary interrupt handler for the driver. It must be +* connected to the interrupt source such that it is called when an interrupt of +* the interrupt controller is active. It will resolve which interrupts are +* active and enabled and call the appropriate interrupt handler. It uses +* the Interrupt Type information to determine when to acknowledge the +* interrupt.Highest priority interrupts are serviced first. +* +* This function assumes that an interrupt vector table has been previously +* initialized. It does not verify that entries in the table are valid before +* calling an interrupt handler. +* +* @param DeviceId is the unique identifier for the ScuGic device. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XScuGic_DeviceInterruptHandler(void *DeviceId) +{ + + u32 InterruptID; + u32 IntIDFull; + XScuGic_VectorTableEntry *TablePtr; + XScuGic_Config *CfgPtr; + + CfgPtr = &XScuGic_ConfigTable[(INTPTR)DeviceId]; + + /* + * Read the int_ack register to identify the highest priority + * interrupt ID and make sure it is valid. Reading Int_Ack will + * clear the interrupt in the GIC. + */ + IntIDFull = XScuGic_ReadReg(CfgPtr->CpuBaseAddress, + XSCUGIC_INT_ACK_OFFSET); + InterruptID = IntIDFull & XSCUGIC_ACK_INTID_MASK; + if (XSCUGIC_MAX_NUM_INTR_INPUTS <= InterruptID) { + goto IntrExit; + } + + /* + * If the interrupt is shared, do some locking here if there are + * multiple processors. + */ + /* + * If pre-eption is required: + * Re-enable pre-emption by setting the CPSR I bit for non-secure , + * interrupts or the F bit for secure interrupts + */ + + /* + * If we need to change security domains, issue a SMC instruction here. + */ + + /* + * Execute the ISR. Jump into the Interrupt service routine based on + * the IRQSource. A software trigger is cleared by the ACK. + */ + TablePtr = &(CfgPtr->HandlerTable[InterruptID]); + if (TablePtr != NULL) { + TablePtr->Handler(TablePtr->CallBackRef); + } + +IntrExit: + /* + * Write to the EOI register, we are all done here. + * Let this function return, the boot code will restore the stack. + */ + XScuGic_WriteReg(CfgPtr->CpuBaseAddress, XSCUGIC_EOI_OFFSET, IntIDFull); + + /* + * Return from the interrupt. Change security domains could happen + * here. + */ +} + +/*****************************************************************************/ +/** +* +* Register a handler function for a specific interrupt ID. The vector table +* of the interrupt controller is updated, overwriting any previous handler. +* The handler function will be called when an interrupt occurs for the given +* interrupt ID. +* +* @param BaseAddress is the CPU Interface Register base address of the +* interrupt controller whose vector table will be modified. +* @param InterruptID is the interrupt ID to be associated with the input +* handler. +* @param IntrHandler is the function pointer that will be added to +* the vector table for the given interrupt ID. +* @param CallBackRef is the argument that will be passed to the new +* handler function when it is called. This is user-specific. +* +* @return None. +* +* @note +* +* Note that this function has no effect if the input base address is invalid. +* +******************************************************************************/ +void XScuGic_RegisterHandler(u32 BaseAddress, s32 InterruptID, + Xil_InterruptHandler IntrHandler, void *CallBackRef) +{ + XScuGic_Config *CfgPtr; + CfgPtr = LookupConfigByBaseAddress(BaseAddress); + + if (CfgPtr != NULL) { + if (IntrHandler != NULL) { + CfgPtr->HandlerTable[InterruptID].Handler = + (Xil_InterruptHandler)IntrHandler; + } + if (CallBackRef != NULL) { + CfgPtr->HandlerTable[InterruptID].CallBackRef = + CallBackRef; + } + } +} + +/*****************************************************************************/ +/** +* +* Looks up the device configuration based on the CPU interface base address of +* the device. A table contains the configuration info for each device in the +* system. +* +* @param CpuBaseAddress is the CPU Interface Register base address. +* +* @return A pointer to the configuration structure for the specified +* device, or NULL if the device was not found. +* +* @note None. +* +******************************************************************************/ +static XScuGic_Config *LookupConfigByBaseAddress(u32 CpuBaseAddress) +{ + XScuGic_Config *CfgPtr = NULL; + u32 Index; + + for (Index = 0U; Index < XPAR_SCUGIC_NUM_INSTANCES; Index++) { + if (XScuGic_ConfigTable[Index].CpuBaseAddress == + CpuBaseAddress) { + CfgPtr = &XScuGic_ConfigTable[Index]; + break; + } + } + + return (XScuGic_Config *)CfgPtr; +} + +/****************************************************************************/ +/** +* Sets the interrupt priority and trigger type for the specificd IRQ source. +* +* @param DistBaseAddress is the distributor base address +* @param Int_Id is the IRQ source number to modify +* @param Priority is the new priority for the IRQ source. 0 is highest +* priority, 0xF8(248) is lowest. There are 32 priority +* levels supported with a step of 8. Hence the supported +* priorities are 0, 8, 16, 32, 40 ..., 248. +* @param Trigger is the new trigger type for the IRQ source. +* Each bit pair describes the configuration for an INT_ID. +* SFI Read Only b10 always +* PPI Read Only depending on how the PPIs are configured. +* b01 Active HIGH level sensitive +* b11 Rising edge sensitive +* SPI LSB is read only. +* b01 Active HIGH level sensitive +* b11 Rising edge sensitive/ +* +* @return None. +* +* @note This API has the similar functionality of XScuGic_SetPriority +* TriggerType() and should be used when there is no InstancePtr. +* +*****************************************************************************/ +void XScuGic_SetPriTrigTypeByDistAddr(u32 DistBaseAddress, u32 Int_Id, + u8 Priority, u8 Trigger) +{ + u32 RegValue; + u8 LocalPriority = Priority; + + Xil_AssertVoid(Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS); + Xil_AssertVoid(Trigger <= XSCUGIC_INT_CFG_MASK); + Xil_AssertVoid(LocalPriority <= XSCUGIC_MAX_INTR_PRIO_VAL); + + /* + * Determine the register to write to using the Int_Id. + */ + RegValue = XScuGic_ReadReg(DistBaseAddress, + XSCUGIC_PRIORITY_OFFSET_CALC(Int_Id)); + + /* + * The priority bits are Bits 7 to 3 in GIC Priority Register. This + * means the number of priority levels supported are 32 and they are + * in steps of 8. The priorities can be 0, 8, 16, 32, 48, ... etc. + * The lower order 3 bits are masked before putting it in the register. + */ + LocalPriority = LocalPriority & XSCUGIC_INTR_PRIO_MASK; + /* + * Shift and Mask the correct bits for the priority and trigger in the + * register + */ + RegValue &= ~(XSCUGIC_PRIORITY_MASK << ((Int_Id%4U)*8U)); + RegValue |= (u32)LocalPriority << ((Int_Id%4U)*8U); + + /* + * Write the value back to the register. + */ + XScuGic_WriteReg(DistBaseAddress, XSCUGIC_PRIORITY_OFFSET_CALC(Int_Id), + RegValue); + /* + * Determine the register to write to using the Int_Id. + */ + RegValue = XScuGic_ReadReg(DistBaseAddress, + XSCUGIC_INT_CFG_OFFSET_CALC(Int_Id)); + + /* + * Shift and Mask the correct bits for the priority and trigger in the + * register + */ + RegValue &= ~(XSCUGIC_INT_CFG_MASK << ((Int_Id%16U)*2U)); + RegValue |= (u32)Trigger << ((Int_Id%16U)*2U); + + /* + * Write the value back to the register. + */ + XScuGic_WriteReg(DistBaseAddress, XSCUGIC_INT_CFG_OFFSET_CALC(Int_Id), + RegValue); +} + +/****************************************************************************/ +/** +* Gets the interrupt priority and trigger type for the specificd IRQ source. +* +* @param DistBaseAddress is the distributor base address +* @param Int_Id is the IRQ source number to modify +* @param Priority is a pointer to the value of the priority of the IRQ +* source. This is a return value. +* @param Trigger is pointer to the value of the trigger of the IRQ +* source. This is a return value. +* +* @return None. +* +* @note This API has the similar functionality of XScuGic_GetPriority +* TriggerType() and should be used when there is no InstancePtr. +* +*****************************************************************************/ +void XScuGic_GetPriTrigTypeByDistAddr(u32 DistBaseAddress, u32 Int_Id, + u8 *Priority, u8 *Trigger) +{ + u32 RegValue; + + Xil_AssertVoid(Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS); + Xil_AssertVoid(Priority != NULL); + Xil_AssertVoid(Trigger != NULL); + + /* + * Determine the register to read to using the Int_Id. + */ + RegValue = XScuGic_ReadReg(DistBaseAddress, + XSCUGIC_PRIORITY_OFFSET_CALC(Int_Id)); + + /* + * Shift and Mask the correct bits for the priority and trigger in the + * register + */ + RegValue = RegValue >> ((Int_Id%4U)*8U); + *Priority = (u8)(RegValue & XSCUGIC_PRIORITY_MASK); + + /* + * Determine the register to read to using the Int_Id. + */ + RegValue = XScuGic_ReadReg(DistBaseAddress, + XSCUGIC_INT_CFG_OFFSET_CALC(Int_Id)); + + /* + * Shift and Mask the correct bits for the priority and trigger in the + * register + */ + RegValue = RegValue >> ((Int_Id%16U)*2U); + + *Trigger = (u8)(RegValue & XSCUGIC_INT_CFG_MASK); +} + +/****************************************************************************/ +/** +* Unmaps specific SPI interrupt from the target CPU +* +* @param DistBaseAddress is the device base address +* @param Cpu_Id is a CPU number from which the interrupt has to be +* unmapped +* @param Int_Id is the IRQ source number to modify +* +* @return None. +* +* @note None +* +*****************************************************************************/ +void XScuGic_InterruptUnmapFromCpuByDistAddr(u32 DistBaseAddress, + u8 Cpu_Id, u32 Int_Id) +{ + u32 RegValue; + u8 BitPos; + + Xil_AssertVoid(Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS); + + RegValue = XScuGic_ReadReg(DistBaseAddress, + XSCUGIC_SPI_TARGET_OFFSET_CALC(Int_Id)); + + /* + * Identify bit position corresponding to Int_Id and Cpu_Id, + * in interrupt target register and clear it + */ + BitPos = ((Int_Id % 4U) * 8U) + Cpu_Id; + RegValue &= (~(1U << BitPos)); + XScuGic_WriteReg(DistBaseAddress, + XSCUGIC_SPI_TARGET_OFFSET_CALC(Int_Id), RegValue); +} + +/****************************************************************************/ +/** +* Unmaps all SPI interrupts from the target CPU +* +* @param DistBaseAddress is the device base address +* @param Cpu_Id is a CPU number from which the interrupts has to be +* unmapped +* +* @return None. +* +* @note None +* +*****************************************************************************/ +void XScuGic_UnmapAllInterruptsFromCpuByDistAddr(u32 DistBaseAddress, + u8 Cpu_Id) +{ + u32 Int_Id; + u32 Target_Cpu; + u32 LocalCpuID = (1U << Cpu_Id); + + LocalCpuID |= LocalCpuID << 8U; + LocalCpuID |= LocalCpuID << 16U; + + for (Int_Id = 32U; Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS; + Int_Id = Int_Id+4U) { + + Target_Cpu = XScuGic_ReadReg(DistBaseAddress, + XSCUGIC_SPI_TARGET_OFFSET_CALC(Int_Id)); + /* Remove LocalCpuID from interrupt target register */ + Target_Cpu &= (~LocalCpuID); + XScuGic_WriteReg(DistBaseAddress, + XSCUGIC_SPI_TARGET_OFFSET_CALC(Int_Id), Target_Cpu); + + } +} +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/scugic_v4_0/src/xscugic_hw.h b/df_datalink/bsp/ps7_cortexa9_0/libsrc/scugic_v4_0/src/xscugic_hw.h new file mode 100644 index 0000000..60d111f --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/scugic_v4_0/src/xscugic_hw.h @@ -0,0 +1,753 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xscugic_hw.h +* @addtogroup scugic_v4_0 +* @{ +* +* This header file contains identifiers and HW access functions (or +* macros) that can be used to access the device. The user should refer to the +* hardware device specification for more details of the device operation. +* The driver functions/APIs are defined in xscugic.h. +* +* This GIC device has two parts, a distributor and CPU interface(s). Each part +* has separate register definition sections. +* +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------------
+* 1.00a drg  01/19/10 First release
+* 1.01a sdm  11/09/11 "xil_exception.h" added as include.
+*		      Macros XScuGic_EnableIntr and XScuGic_DisableIntr are
+*		      added to enable or disable interrupts based on
+*		      Distributor Register base address. Normally users use
+*		      XScuGic instance and call XScuGic_Enable or
+*		      XScuGic_Disable to enable/disable interrupts. These
+*		      new macros are provided when user does not want to
+*		      use an instance pointer but still wants to enable or
+*		      disable interrupts.
+*		      Function prototypes for functions (present in newly
+*		      added file xscugic_hw.c) are added.
+* 1.03a srt  02/27/13 Moved Offset calculation macros from *_hw.c (CR
+*		      702687).
+* 1.04a hk   05/04/13 Fix for CR#705621. Moved function prototypes
+*		      XScuGic_SetPriTrigTypeByDistAddr and
+*         	      XScuGic_GetPriTrigTypeByDistAddr here from xscugic.h
+* 3.0	pkp  12/09/14 changed XSCUGIC_MAX_NUM_INTR_INPUTS for
+*		      Zynq Ultrascale Mp
+* 3.0   kvn  02/13/14 Modified code for MISRA-C:2012 compliance.
+* 3.2	pkp  11/09/15 Corrected the interrupt processsor target mask value
+*					  for CPU interface 2 i.e. XSCUGIC_SPI_CPU2_MASK
+* 3.9   mus  02/21/18 Added new API's XScuGic_InterruptUnmapFromCpuByDistAddr
+*					  and XScuGic_UnmapAllInterruptsFromCpuByDistAddr, These
+*					  API's can be used by applications to unmap specific/all
+*					  interrupts from target CPU. It fixes CR#992490.
+* 3.10  aru  08/23/18 Resolved MISRA-C:2012 compliance mandatory violations
+*
+* 
+* +******************************************************************************/ + +#ifndef XSCUGIC_HW_H /* prevent circular inclusions */ +#define XSCUGIC_HW_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_io.h" +#include "xil_exception.h" +#include "bspconfig.h" + +/************************** Constant Definitions *****************************/ + +/* + * The maximum number of interrupts supported by the hardware. + */ +#ifdef PLATFORM_ZYNQ +#define XSCUGIC_MAX_NUM_INTR_INPUTS 95U /* Maximum number of interrupt defined by Zynq */ +#elif defined (versal) && !defined(ARMR5) +#define XSCUGIC_MAX_NUM_INTR_INPUTS 191U +#else +#define XSCUGIC_MAX_NUM_INTR_INPUTS 195U /* Maximum number of interrupt defined by Zynq Ultrascale Mp */ +#endif + +/* + * First Interrupt Id for SPI interrupts. + */ +#define XSCUGIC_SPI_INT_ID_START 0x20 +/* + * The maximum priority value that can be used in the GIC. + */ +#define XSCUGIC_MAX_INTR_PRIO_VAL 248U +#define XSCUGIC_INTR_PRIO_MASK 0x000000F8U + +/** @name Distributor Interface Register Map + * + * Define the offsets from the base address for all Distributor registers of + * the interrupt controller, some registers may be reserved in the hardware + * device. + * @{ + */ +#define XSCUGIC_DIST_EN_OFFSET 0x00000000U /**< Distributor Enable + Register */ +#define XSCUGIC_IC_TYPE_OFFSET 0x00000004U /**< Interrupt Controller + Type Register */ +#define XSCUGIC_DIST_IDENT_OFFSET 0x00000008U /**< Implementor ID + Register */ +#define XSCUGIC_SECURITY_OFFSET 0x00000080U /**< Interrupt Security + Register */ +#define XSCUGIC_ENABLE_SET_OFFSET 0x00000100U /**< Enable Set + Register */ +#define XSCUGIC_DISABLE_OFFSET 0x00000180U /**< Enable Clear Register */ +#define XSCUGIC_PENDING_SET_OFFSET 0x00000200U /**< Pending Set + Register */ +#define XSCUGIC_PENDING_CLR_OFFSET 0x00000280U /**< Pending Clear + Register */ +#define XSCUGIC_ACTIVE_OFFSET 0x00000300U /**< Active Status Register */ +#define XSCUGIC_PRIORITY_OFFSET 0x00000400U /**< Priority Level Register */ +#define XSCUGIC_SPI_TARGET_OFFSET 0x00000800U /**< SPI Target + Register 0x800-0x8FB */ +#define XSCUGIC_INT_CFG_OFFSET 0x00000C00U /**< Interrupt Configuration + Register 0xC00-0xCFC */ +#define XSCUGIC_PPI_STAT_OFFSET 0x00000D00U /**< PPI Status Register */ +#define XSCUGIC_SPI_STAT_OFFSET 0x00000D04U /**< SPI Status Register + 0xd04-0xd7C */ +#define XSCUGIC_AHB_CONFIG_OFFSET 0x00000D80U /**< AHB Configuration + Register */ +#define XSCUGIC_SFI_TRIG_OFFSET 0x00000F00U /**< Software Triggered + Interrupt Register */ +#define XSCUGIC_PERPHID_OFFSET 0x00000FD0U /**< Peripheral ID Reg */ +#if defined (versal) && !defined(ARMR5) +#define XSCUGIC_PCELLID_OFFSET 0x0000FFF0U /**< Pcell ID Register */ +#else +#define XSCUGIC_PCELLID_OFFSET 0x00000FF0U /**< Pcell ID Register */ +#endif +/* @} */ + +/** @name Distributor Enable Register + * Controls if the distributor response to external interrupt inputs. + * @{ + */ +#if defined (versal) && !defined(ARMR5) +#define XSCUGIC_EN_INT_MASK 0x00000003U /**< Interrupt In Enable */ +#else +#define XSCUGIC_EN_INT_MASK 0x00000001U /**< Interrupt In Enable */ +#endif +/* @} */ + +/** @name Interrupt Controller Type Register + * @{ + */ +#define XSCUGIC_LSPI_MASK 0x0000F800U /**< Number of Lockable + Shared Peripheral + Interrupts*/ +#define XSCUGIC_DOMAIN_MASK 0x00000400U /**< Number os Security domains*/ +#define XSCUGIC_CPU_NUM_MASK 0x000000E0U /**< Number of CPU Interfaces */ +#define XSCUGIC_NUM_INT_MASK 0x0000001FU /**< Number of Interrupt IDs */ +/* @} */ + +/** @name Implementor ID Register + * Implementor and revision information. + * @{ + */ +#define XSCUGIC_REV_MASK 0x00FFF000U /**< Revision Number */ +#define XSCUGIC_IMPL_MASK 0x00000FFFU /**< Implementor */ +/* @} */ + +/** @name Interrupt Security Registers + * Each bit controls the security level of an interrupt, either secure or non + * secure. These registers can only be accessed using secure read and write. + * There are registers for each of the CPU interfaces at offset 0x080. A + * register set for the SPI interrupts is available to all CPU interfaces. + * There are up to 32 of these registers staring at location 0x084. + * @{ + */ +#define XSCUGIC_INT_NS_MASK 0x00000001U /**< Each bit corresponds to an + INT_ID */ +/* @} */ + +/** @name Enable Set Register + * Each bit controls the enabling of an interrupt, a 0 is disabled, a 1 is + * enabled. Writing a 0 has no effect. Use the ENABLE_CLR register to set a + * bit to 0. + * There are registers for each of the CPU interfaces at offset 0x100. With up + * to 8 registers aliased to the same address. A register set for the SPI + * interrupts is available to all CPU interfaces. + * There are up to 32 of these registers staring at location 0x104. + * @{ + */ +#define XSCUGIC_INT_EN_MASK 0x00000001U /**< Each bit corresponds to an + INT_ID */ +/* @} */ + +/** @name Enable Clear Register + * Each bit controls the disabling of an interrupt, a 0 is disabled, a 1 is + * enabled. Writing a 0 has no effect. Writing a 1 disables an interrupt and + * sets the corresponding bit to 0. + * There are registers for each of the CPU interfaces at offset 0x180. With up + * to 8 registers aliased to the same address. + * A register set for the SPI interrupts is available to all CPU interfaces. + * There are up to 32 of these registers staring at location 0x184. + * @{ + */ +#define XSCUGIC_INT_CLR_MASK 0x00000001U /**< Each bit corresponds to an + INT_ID */ +/* @} */ + +/** @name Pending Set Register + * Each bit controls the Pending or Active and Pending state of an interrupt, a + * 0 is not pending, a 1 is pending. Writing a 0 has no effect. Writing a 1 sets + * an interrupt to the pending state. + * There are registers for each of the CPU interfaces at offset 0x200. With up + * to 8 registers aliased to the same address. + * A register set for the SPI interrupts is available to all CPU interfaces. + * There are up to 32 of these registers staring at location 0x204. + * @{ + */ +#define XSCUGIC_PEND_SET_MASK 0x00000001U /**< Each bit corresponds to an + INT_ID */ +/* @} */ + +/** @name Pending Clear Register + * Each bit can clear the Pending or Active and Pending state of an interrupt, a + * 0 is not pending, a 1 is pending. Writing a 0 has no effect. Writing a 1 + * clears the pending state of an interrupt. + * There are registers for each of the CPU interfaces at offset 0x280. With up + * to 8 registers aliased to the same address. + * A register set for the SPI interrupts is available to all CPU interfaces. + * There are up to 32 of these registers staring at location 0x284. + * @{ + */ +#define XSCUGIC_PEND_CLR_MASK 0x00000001U /**< Each bit corresponds to an + INT_ID */ +/* @} */ + +/** @name Active Status Register + * Each bit provides the Active status of an interrupt, a + * 0 is not Active, a 1 is Active. This is a read only register. + * There are registers for each of the CPU interfaces at offset 0x300. With up + * to 8 registers aliased to each address. + * A register set for the SPI interrupts is available to all CPU interfaces. + * There are up to 32 of these registers staring at location 0x380. + * @{ + */ +#define XSCUGIC_ACTIVE_MASK 0x00000001U /**< Each bit corresponds to an + INT_ID */ +/* @} */ + +/** @name Priority Level Register + * Each byte in a Priority Level Register sets the priority level of an + * interrupt. Reading the register provides the priority level of an interrupt. + * There are registers for each of the CPU interfaces at offset 0x400 through + * 0x41C. With up to 8 registers aliased to each address. + * 0 is highest priority, 0xFF is lowest. + * A register set for the SPI interrupts is available to all CPU interfaces. + * There are up to 255 of these registers staring at location 0x420. + * @{ + */ +#define XSCUGIC_PRIORITY_MASK 0x000000FFU /**< Each Byte corresponds to an + INT_ID */ +#define XSCUGIC_PRIORITY_MAX 0x000000FFU /**< Highest value of a priority + actually the lowest priority*/ +/* @} */ + +/** @name SPI Target Register 0x800-0x8FB + * Each byte references a separate SPI and programs which of the up to 8 CPU + * interfaces are sent a Pending interrupt. + * There are registers for each of the CPU interfaces at offset 0x800 through + * 0x81C. With up to 8 registers aliased to each address. + * A register set for the SPI interrupts is available to all CPU interfaces. + * There are up to 255 of these registers staring at location 0x820. + * + * This driver does not support multiple CPU interfaces. These are included + * for complete documentation. + * @{ + */ +#define XSCUGIC_SPI_CPU7_MASK 0x00000080U /**< CPU 7 Mask*/ +#define XSCUGIC_SPI_CPU6_MASK 0x00000040U /**< CPU 6 Mask*/ +#define XSCUGIC_SPI_CPU5_MASK 0x00000020U /**< CPU 5 Mask*/ +#define XSCUGIC_SPI_CPU4_MASK 0x00000010U /**< CPU 4 Mask*/ +#define XSCUGIC_SPI_CPU3_MASK 0x00000008U /**< CPU 3 Mask*/ +#define XSCUGIC_SPI_CPU2_MASK 0x00000004U /**< CPU 2 Mask*/ +#define XSCUGIC_SPI_CPU1_MASK 0x00000002U /**< CPU 1 Mask*/ +#define XSCUGIC_SPI_CPU0_MASK 0x00000001U /**< CPU 0 Mask*/ +/* @} */ + +/** @name Interrupt Configuration Register 0xC00-0xCFC + * The interrupt configuration registers program an SFI to be active HIGH level + * sensitive or rising edge sensitive. + * Each bit pair describes the configuration for an INT_ID. + * SFI Read Only b10 always + * PPI Read Only depending on how the PPIs are configured. + * b01 Active HIGH level sensitive + * b11 Rising edge sensitive + * SPI LSB is read only. + * b01 Active HIGH level sensitive + * b11 Rising edge sensitive/ + * There are registers for each of the CPU interfaces at offset 0xC00 through + * 0xC04. With up to 8 registers aliased to each address. + * A register set for the SPI interrupts is available to all CPU interfaces. + * There are up to 255 of these registers staring at location 0xC08. + * @{ + */ +#define XSCUGIC_INT_CFG_MASK 0x00000003U /**< */ +/* @} */ + +/** @name PPI Status Register + * Enables an external AMBA master to access the status of the PPI inputs. + * A CPU can only read the status of its local PPI signals and cannot read the + * status for other CPUs. + * This register is aliased for each CPU interface. + * @{ + */ +#define XSCUGIC_PPI_C15_MASK 0x00008000U /**< PPI Status */ +#define XSCUGIC_PPI_C14_MASK 0x00004000U /**< PPI Status */ +#define XSCUGIC_PPI_C13_MASK 0x00002000U /**< PPI Status */ +#define XSCUGIC_PPI_C12_MASK 0x00001000U /**< PPI Status */ +#define XSCUGIC_PPI_C11_MASK 0x00000800U /**< PPI Status */ +#define XSCUGIC_PPI_C10_MASK 0x00000400U /**< PPI Status */ +#define XSCUGIC_PPI_C09_MASK 0x00000200U /**< PPI Status */ +#define XSCUGIC_PPI_C08_MASK 0x00000100U /**< PPI Status */ +#define XSCUGIC_PPI_C07_MASK 0x00000080U /**< PPI Status */ +#define XSCUGIC_PPI_C06_MASK 0x00000040U /**< PPI Status */ +#define XSCUGIC_PPI_C05_MASK 0x00000020U /**< PPI Status */ +#define XSCUGIC_PPI_C04_MASK 0x00000010U /**< PPI Status */ +#define XSCUGIC_PPI_C03_MASK 0x00000008U /**< PPI Status */ +#define XSCUGIC_PPI_C02_MASK 0x00000004U /**< PPI Status */ +#define XSCUGIC_PPI_C01_MASK 0x00000002U /**< PPI Status */ +#define XSCUGIC_PPI_C00_MASK 0x00000001U /**< PPI Status */ +/* @} */ + +/** @name SPI Status Register 0xd04-0xd7C + * Enables an external AMBA master to access the status of the SPI inputs. + * There are up to 63 registers if the maximum number of SPI inputs are + * configured. + * @{ + */ +#define XSCUGIC_SPI_N_MASK 0x00000001U /**< Each bit corresponds to an SPI + input */ +/* @} */ + +/** @name AHB Configuration Register + * Provides the status of the CFGBIGEND input signal and allows the endianess + * of the GIC to be set. + * @{ + */ +#define XSCUGIC_AHB_END_MASK 0x00000004U /**< 0-GIC uses little Endian, + 1-GIC uses Big Endian */ +#define XSCUGIC_AHB_ENDOVR_MASK 0x00000002U /**< 0-Uses CFGBIGEND control, + 1-use the AHB_END bit */ +#define XSCUGIC_AHB_TIE_OFF_MASK 0x00000001U /**< State of CFGBIGEND */ + +/* @} */ + +/** @name Software Triggered Interrupt Register + * Controls issueing of software interrupts. + * @{ + */ +#define XSCUGIC_SFI_SELFTRIG_MASK 0x02010000U +#define XSCUGIC_SFI_TRIG_TRGFILT_MASK 0x03000000U /**< Target List filter + b00-Use the target List + b01-All CPUs except requester + b10-To Requester + b11-reserved */ +#define XSCUGIC_SFI_TRIG_CPU_MASK 0x00FF0000U /**< CPU Target list */ +#define XSCUGIC_SFI_TRIG_SATT_MASK 0x00008000U /**< 0= Use a secure interrupt */ +#define XSCUGIC_SFI_TRIG_INTID_MASK 0x0000000FU /**< Set to the INTID + signaled to the CPU*/ +/* @} */ + +/** @name CPU Interface Register Map + * + * Define the offsets from the base address for all CPU registers of the + * interrupt controller, some registers may be reserved in the hardware device. + * @{ + */ +#define XSCUGIC_CONTROL_OFFSET 0x00000000U /**< CPU Interface Control + Register */ +#define XSCUGIC_CPU_PRIOR_OFFSET 0x00000004U /**< Priority Mask Reg */ +#define XSCUGIC_BIN_PT_OFFSET 0x00000008U /**< Binary Point Register */ +#define XSCUGIC_INT_ACK_OFFSET 0x0000000CU /**< Interrupt ACK Reg */ +#define XSCUGIC_EOI_OFFSET 0x00000010U /**< End of Interrupt Reg */ +#define XSCUGIC_RUN_PRIOR_OFFSET 0x00000014U /**< Running Priority Reg */ +#define XSCUGIC_HI_PEND_OFFSET 0x00000018U /**< Highest Pending Interrupt + Register */ +#define XSCUGIC_ALIAS_BIN_PT_OFFSET 0x0000001CU /**< Aliased non-Secure + Binary Point Register */ + +/**< 0x00000020 to 0x00000FBC are reserved and should not be read or written + * to. */ +/* @} */ + + +/** @name Control Register + * CPU Interface Control register definitions + * All bits are defined here although some are not available in the non-secure + * mode. + * @{ + */ +#define XSCUGIC_CNTR_SBPR_MASK 0x00000010U /**< Secure Binary Pointer, + 0=separate registers, + 1=both use bin_pt_s */ +#define XSCUGIC_CNTR_FIQEN_MASK 0x00000008U /**< Use nFIQ_C for secure + interrupts, + 0= use IRQ for both, + 1=Use FIQ for secure, IRQ for non*/ +#define XSCUGIC_CNTR_ACKCTL_MASK 0x00000004U /**< Ack control for secure or non secure */ +#define XSCUGIC_CNTR_EN_NS_MASK 0x00000002U /**< Non Secure enable */ +#define XSCUGIC_CNTR_EN_S_MASK 0x00000001U /**< Secure enable, 0=Disabled, 1=Enabled */ +/* @} */ + +/** @name Priority Mask Register + * Priority Mask register definitions + * The CPU interface does not send interrupt if the level of the interrupt is + * lower than the level of the register. + * @{ + */ +/*#define XSCUGIC_PRIORITY_MASK 0x000000FFU*/ /**< All interrupts */ +/* @} */ + +/** @name Binary Point Register + * Binary Point register definitions + * @{ + */ + +#define XSCUGIC_BIN_PT_MASK 0x00000007U /**< Binary point mask value + Value Secure Non-secure + b000 0xFE 0xFF + b001 0xFC 0xFE + b010 0xF8 0xFC + b011 0xF0 0xF8 + b100 0xE0 0xF0 + b101 0xC0 0xE0 + b110 0x80 0xC0 + b111 0x00 0x80 + */ +/*@}*/ + +/** @name Interrupt Acknowledge Register + * Interrupt Acknowledge register definitions + * Identifies the current Pending interrupt, and the CPU ID for software + * interrupts. + */ +#define XSCUGIC_ACK_INTID_MASK 0x000003FFU /**< Interrupt ID */ +#define XSCUGIC_CPUID_MASK 0x00000C00U /**< CPU ID */ +/* @} */ + +/** @name End of Interrupt Register + * End of Interrupt register definitions + * Allows the CPU to signal the GIC when it completes an interrupt service + * routine. + */ +#define XSCUGIC_EOI_INTID_MASK 0x000003FFU /**< Interrupt ID */ + +/* @} */ + +/** @name Running Priority Register + * Running Priority register definitions + * Identifies the interrupt priority level of the highest priority active + * interrupt. + */ +#define XSCUGIC_RUN_PRIORITY_MASK 0x000000FFU /**< Interrupt Priority */ +/* @} */ + +#if defined (versal) && !defined(ARMR5) +#define XSCUGIC_IROUTER_BASE_OFFSET 0x6000U +#endif +/* + * Highest Pending Interrupt register definitions + * Identifies the interrupt priority of the highest priority pending interupt + */ +#define XSCUGIC_PEND_INTID_MASK 0x000003FFU /**< Pending Interrupt ID */ +/*#define XSCUGIC_CPUID_MASK 0x00000C00U */ /**< CPU ID */ +/* @} */ +#if defined (versal) && !defined(ARMR5) +/** @name ReDistributor Interface Register Map + * + * @{ + */ +#define XSCUGIC_RDIST_OFFSET 0x80000U +#define XSCUGIC_RDIST_BASE_ADDRESS (XPAR_SCUGIC_0_DIST_BASEADDR + XSCUGIC_RDIST_OFFSET) +#define XSCUGIC_RDIST_SGI_PPI_OFFSET 0x90000U +#define XSCUGIC_RDIST_SGI_PPI_BASE_ADDRESS (XPAR_SCUGIC_0_DIST_BASEADDR + XSCUGIC_RDIST_SGI_PPI_OFFSET) +#define XSCUGIC_RDIST_ISENABLE_OFFSET 0x100U +#define XSCUGIC_RDIST_IPRIORITYR_OFFSET 0x400U +#define XSCUGIC_RDIST_IGROUPR_OFFSET 0x80U +#define XSCUGIC_RDIST_GRPMODR_OFFSET 0xD00U +#define XSCUGIC_RDIST_INT_CONFIG_OFFSET 0xC00U +#define XSCUGIC_RDIST_WAKER_OFFSET 0x14U +#define XSCUGIC_SGIR_EL1_INITID_SHIFT 24U + +/* + * GICR_IGROUPR register definitions + */ +#if EL3 +#define XSCUGIC_DEFAULT_SECURITY 0x0U +#else +#define XSCUGIC_DEFAULT_SECURITY 0xFFFFFFFFU +#endif +/* + * GICR_WAKER register definitions + */ +#define XSCUGIC_RDIST_WAKER_LOW_POWER_STATE_MASK 0x7 +#endif +/***************** Macros (Inline Functions) Definitions *********************/ + +/****************************************************************************/ +/** +* +* Read the Interrupt Configuration Register offset for an interrupt id. +* +* @param InterruptID is the interrupt number. +* +* @return The 32-bit value of the offset +* +* @note +* +*****************************************************************************/ +#define XSCUGIC_INT_CFG_OFFSET_CALC(InterruptID) \ + ((u32)XSCUGIC_INT_CFG_OFFSET + (((InterruptID)/16U) * 4U)) + +/****************************************************************************/ +/** +* +* Read the Interrupt Priority Register offset for an interrupt id. +* +* @param InterruptID is the interrupt number. +* +* @return The 32-bit value of the offset +* +* @note +* +*****************************************************************************/ +#define XSCUGIC_PRIORITY_OFFSET_CALC(InterruptID) \ + ((u32)XSCUGIC_PRIORITY_OFFSET + (((InterruptID)/4U) * 4U)) + +/****************************************************************************/ +/** +* +* Read the Interrupt Routing Register offset for an interrupt id. +* +* @param InterruptID is the interrupt number. +* +* @return The 32-bit value of the offset +* +* @note +* +*****************************************************************************/ +#define XSCUGIC_IROUTER_OFFSET_CALC(InterruptID) \ + ((u32)XSCUGIC_IROUTER_BASE_OFFSET + (InterruptID * 8)) + +/****************************************************************************/ +/** +* +* Read the SPI Target Register offset for an interrupt id. +* +* @param InterruptID is the interrupt number. +* +* @return The 32-bit value of the offset +* +* @note +* +*****************************************************************************/ +#define XSCUGIC_SPI_TARGET_OFFSET_CALC(InterruptID) \ + ((u32)XSCUGIC_SPI_TARGET_OFFSET + (((InterruptID)/4U) * 4U)) +/****************************************************************************/ +/** +* +* Read the SPI Target Register offset for an interrupt id. +* +* @param InterruptID is the interrupt number. +* +* @return The 32-bit value of the offset +* +* @note +* +*****************************************************************************/ +#define XSCUGIC_SECURITY_TARGET_OFFSET_CALC(InterruptID) \ + ((u32)XSCUGIC_SECURITY_OFFSET + (((InterruptID)/32U)*4U)) + +/****************************************************************************/ +/** +* +* Read the Re-distributor Interrupt configuration register offset +* +* @param InterruptID is the interrupt number. +* +* @return The 32-bit value of the offset +* +* @note +* +*****************************************************************************/ +#define XSCUGIC_RDIST_INT_CONFIG_OFFSET_CALC(InterruptID) \ + ((u32)XSCUGIC_RDIST_INT_CONFIG_OFFSET + ((InterruptID /16)*4)) + +/****************************************************************************/ +/** +* +* Read the Re-distributor Interrupt Priority register offset +* +* @param InterruptID is the interrupt number. +* +* @return The 32-bit value of the offset +* +* @note +* +*****************************************************************************/ +#define XSCUGIC_RDIST_INT_PRIORITY_OFFSET_CALC(InterruptID) \ + ((u32)XSCUGIC_RDIST_IPRIORITYR_OFFSET + (InterruptID * 4)) +/****************************************************************************/ +/** +* +* Read the Interrupt Clear-Enable Register offset for an interrupt ID +* +* @param Register is the register offset for the clear/enable bank. +* @param InterruptID is the interrupt number. +* +* @return The 32-bit value of the offset +* +* @note +* +*****************************************************************************/ +#define XSCUGIC_EN_DIS_OFFSET_CALC(Register, InterruptID) \ + ((Register) + (((InterruptID)/32U) * 4U)) + +/****************************************************************************/ +/** +* +* Read the given Intc register. +* +* @param BaseAddress is the base address of the device. +* @param RegOffset is the register offset to be read +* +* @return The 32-bit value of the register +* +* @note +* C-style signature: +* u32 XScuGic_ReadReg(u32 BaseAddress, u32 RegOffset) +* +*****************************************************************************/ +#define XScuGic_ReadReg(BaseAddress, RegOffset) \ + (Xil_In32((BaseAddress) + (RegOffset))) + + +/****************************************************************************/ +/** +* +* Write the given Intc register. +* +* @param BaseAddress is the base address of the device. +* @param RegOffset is the register offset to be written +* @param Data is the 32-bit value to write to the register +* +* @return None. +* +* @note +* C-style signature: +* void XScuGic_WriteReg(u32 BaseAddress, u32 RegOffset, u32 Data) +* +*****************************************************************************/ +#define XScuGic_WriteReg(BaseAddress, RegOffset, Data) \ + (Xil_Out32(((BaseAddress) + (RegOffset)), ((u32)(Data)))) + + +/****************************************************************************/ +/** +* +* Enable specific interrupt(s) in the interrupt controller. +* +* @param DistBaseAddress is the Distributor Register base address of the +* device +* @param Int_Id is the ID of the interrupt source and should be in the +* range of 0 to XSCUGIC_MAX_NUM_INTR_INPUTS - 1 +* +* @return None. +* +* @note C-style signature: +* void XScuGic_EnableIntr(u32 DistBaseAddress, u32 Int_Id) +* +*****************************************************************************/ +#define XScuGic_EnableIntr(DistBaseAddress, Int_Id) \ + XScuGic_WriteReg((DistBaseAddress), \ + XSCUGIC_ENABLE_SET_OFFSET + (((Int_Id) / 32U) * 4U), \ + (0x00000001U << ((Int_Id) % 32U))) + +/****************************************************************************/ +/** +* +* Disable specific interrupt(s) in the interrupt controller. +* +* @param DistBaseAddress is the Distributor Register base address of the +* device +* @param Int_Id is the ID of the interrupt source and should be in the +* range of 0 to XSCUGIC_MAX_NUM_INTR_INPUTS - 1 +* +* +* @return None. +* +* @note C-style signature: +* void XScuGic_DisableIntr(u32 DistBaseAddress, u32 Int_Id) +* +*****************************************************************************/ +#define XScuGic_DisableIntr(DistBaseAddress, Int_Id) \ + XScuGic_WriteReg((DistBaseAddress), \ + XSCUGIC_DISABLE_OFFSET + (((Int_Id) / 32U) * 4U), \ + (0x00000001U << ((Int_Id) % 32U))) + + +/************************** Function Prototypes ******************************/ + +void XScuGic_DeviceInterruptHandler(void *DeviceId); +s32 XScuGic_DeviceInitialize(u32 DeviceId); +void XScuGic_RegisterHandler(u32 BaseAddress, s32 InterruptID, + Xil_InterruptHandler Handler, void *CallBackRef); +void XScuGic_SetPriTrigTypeByDistAddr(u32 DistBaseAddress, u32 Int_Id, + u8 Priority, u8 Trigger); +void XScuGic_GetPriTrigTypeByDistAddr(u32 DistBaseAddress, u32 Int_Id, + u8 *Priority, u8 *Trigger); +void XScuGic_InterruptUnmapFromCpuByDistAddr(u32 DistBaseAddress, + u8 Cpu_Id, u32 Int_Id); +void XScuGic_UnmapAllInterruptsFromCpuByDistAddr(u32 DistBaseAddress, + u8 Cpu_Id); +/************************** Variable Definitions *****************************/ +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/scugic_v4_0/src/xscugic_intr.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/scugic_v4_0/src/xscugic_intr.c new file mode 100644 index 0000000..2157b4f --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/scugic_v4_0/src/xscugic_intr.c @@ -0,0 +1,185 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xscugic_intr.c +* @addtogroup scugic_v4_0 +* @{ +* +* This file contains the interrupt processing for the driver for the Xilinx +* Interrupt Controller. The interrupt processing is partitioned separately such +* that users are not required to use the provided interrupt processing. This +* file requires other files of the driver to be linked in also. +* +* The interrupt handler, XScuGic_InterruptHandler, uses an input argument which +* is an instance pointer to an interrupt controller driver such that multiple +* interrupt controllers can be supported. This handler requires the calling +* function to pass it the appropriate argument, so another level of indirection +* may be required. +* +* The interrupt processing may be used by connecting the interrupt handler to +* the interrupt system. The handler does not save and restore the processor +* context but only handles the processing of the Interrupt Controller. The user +* is encouraged to supply their own interrupt handler when performance tuning is +* deemed necessary. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- ---------------------------------------------------------
+* 1.00a drg  01/19/10 First release
+* 1.01a sdm  11/09/11 XScuGic_InterruptHandler has changed correspondingly
+*		      since the HandlerTable has now moved to XScuGic_Config.
+* 3.00  kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.10  mus  07/17/18 Updated XScuGic_InterruptHandler to fix array overrun
+*                     reported by coverity tool. It fixes CR#1006344.
+* 3.10  mus  07/17/18 Updated file to fix the various coding style issues
+*                     reported by checkpatch. It fixes CR#1006344.
+*
+* 
+* +* @internal +* +* This driver assumes that the context of the processor has been saved prior to +* the calling of the Interrupt Controller interrupt handler and then restored +* after the handler returns. This requires either the running RTOS to save the +* state of the machine or that a wrapper be used as the destination of the +* interrupt vector to save the state of the processor and restore the state +* after the interrupt handler returns. +* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xscugic.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +/*****************************************************************************/ +/** +* This function is the primary interrupt handler for the driver. It must be +* connected to the interrupt source such that it is called when an interrupt of +* the interrupt controller is active. It will resolve which interrupts are +* active and enabled and call the appropriate interrupt handler. It uses +* the Interrupt Type information to determine when to acknowledge the interrupt. +* Highest priority interrupts are serviced first. +* +* This function assumes that an interrupt vector table has been previously +* initialized. It does not verify that entries in the table are valid before +* calling an interrupt handler. +* +* +* @param InstancePtr is a pointer to the XScuGic instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XScuGic_InterruptHandler(XScuGic *InstancePtr) +{ + + u32 InterruptID; +#if !defined (versal) || defined (ARMR5) + u32 IntIDFull; +#endif + XScuGic_VectorTableEntry *TablePtr; + + /* Assert that the pointer to the instance is valid + */ + Xil_AssertVoid(InstancePtr != NULL); + + /* + * Read the int_ack register to identify the highest priority + * interrupt ID and make sure it is valid. Reading Int_Ack will + * clear the interrupt in the GIC. + */ +#if defined (versal) && !defined(ARMR5) + InterruptID = XScuGic_get_IntID(); +#else + IntIDFull = XScuGic_CPUReadReg(InstancePtr, XSCUGIC_INT_ACK_OFFSET); + InterruptID = IntIDFull & XSCUGIC_ACK_INTID_MASK; +#endif + if (XSCUGIC_MAX_NUM_INTR_INPUTS <= InterruptID) { + goto IntrExit; + } + + /* + * If the interrupt is shared, do some locking here if + * there are multiple processors. + */ + /* + * If pre-eption is required: + * Re-enable pre-emption by setting the CPSR I bit for non-secure , + * interrupts or the F bit for secure interrupts + */ + + /* + * If we need to change security domains, issue a SMC + * instruction here. + */ + + /* + * Execute the ISR. Jump into the Interrupt service routine + * based on the IRQSource. A software trigger is cleared by + *.the ACK. + */ + TablePtr = &(InstancePtr->Config->HandlerTable[InterruptID]); + if (TablePtr != NULL) { + TablePtr->Handler(TablePtr->CallBackRef); + } + +IntrExit: + /* + * Write to the EOI register, we are all done here. + * Let this function return, the boot code will restore the stack. + */ +#if defined (versal) && !defined(ARMR5) + XScuGic_ack_Int(InterruptID); + +#else + XScuGic_CPUWriteReg(InstancePtr, XSCUGIC_EOI_OFFSET, IntIDFull); +#endif + /* + * Return from the interrupt. Change security domains + * could happen here. + */ +} +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/scugic_v4_0/src/xscugic_selftest.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/scugic_v4_0/src/xscugic_selftest.c new file mode 100644 index 0000000..052ef43 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/scugic_v4_0/src/xscugic_selftest.c @@ -0,0 +1,114 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xscugic_selftest.c +* @addtogroup scugic_v4_0 +* @{ +* +* Contains diagnostic self-test functions for the XScuGic driver. +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a drg  01/19/10 First release
+* 3.00  kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.10  mus  07/17/18 Updated file to fix the various coding style issues
+*                     reported by checkpatch. It fixes CR#1006344.
+*
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xscugic.h" + +/************************** Constant Definitions *****************************/ + +#define XSCUGIC_PCELL_ID 0xB105F00DU + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +/*****************************************************************************/ +/** +* +* Run a self-test on the driver/device. This test reads the ID registers and +* compares them. +* +* @param InstancePtr is a pointer to the XScuGic instance. +* +* @return +* +* -XST_SUCCESS if self-test is successful. +* -XST_FAILURE if the self-test is not successful. +* +* @note None. +* +******************************************************************************/ +s32 XScuGic_SelfTest(XScuGic *InstancePtr) +{ + u32 RegValue1 = 0U; + u32 Index; + s32 Status; + + /* + * Assert the arguments + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the ID registers. + */ + for (Index = 0U; Index <= 3U; Index++) { + RegValue1 |= XScuGic_DistReadReg(InstancePtr, + ((u32)XSCUGIC_PCELLID_OFFSET + (Index * 4U))) << + (Index * 8U); + } + + if (XSCUGIC_PCELL_ID != RegValue1) { + Status = XST_FAILURE; + } else { + Status = XST_SUCCESS; + } + return Status; +} +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/scugic_v4_0/src/xscugic_sinit.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/scugic_v4_0/src/xscugic_sinit.c new file mode 100644 index 0000000..3a3d710 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/scugic_v4_0/src/xscugic_sinit.c @@ -0,0 +1,101 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xscugic_sinit.c +* @addtogroup scugic_v4_0 +* @{ +* +* Contains static init functions for the XScuGic driver for the Interrupt +* Controller. See xscugic.h for a detailed description of the driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- --------------------------------------------------------
+* 1.00a drg  01/19/10 First release
+* 3.00  kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.10  mus  07/17/18 Updated file to fix the various coding style issues
+*                     reported by checkpatch. It fixes CR#1006344.
+*
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xparameters.h" +#include "xscugic.h" + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Variable Definitions *****************************/ + +extern XScuGic_Config XScuGic_ConfigTable[XPAR_SCUGIC_NUM_INSTANCES]; + +/************************** Function Prototypes ******************************/ + +/*****************************************************************************/ +/** +* +* Looks up the device configuration based on the unique device ID. A table +* contains the configuration info for each device in the system. +* +* @param DeviceId is the unique identifier for a device. +* +* @return A pointer to the XScuGic configuration structure for the +* specified device, or NULL if the device was not found. +* +* @note None. +* +******************************************************************************/ +XScuGic_Config *XScuGic_LookupConfig(u16 DeviceId) +{ + XScuGic_Config *CfgPtr = NULL; + u32 Index; + + for (Index = 0U; Index < (u32)XPAR_SCUGIC_NUM_INSTANCES; Index++) { + if (XScuGic_ConfigTable[Index].DeviceId == DeviceId) { + CfgPtr = &XScuGic_ConfigTable[Index]; + break; + } + } + + return (XScuGic_Config *)CfgPtr; +} +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/scutimer_v2_1/src/Makefile b/df_datalink/bsp/ps7_cortexa9_0/libsrc/scutimer_v2_1/src/Makefile new file mode 100644 index 0000000..7c673d4 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/scutimer_v2_1/src/Makefile @@ -0,0 +1,40 @@ +COMPILER= +ARCHIVER= +CP=cp +COMPILER_FLAGS= +EXTRA_COMPILER_FLAGS= +LIB=libxil.a + +CC_FLAGS = $(COMPILER_FLAGS) +ECC_FLAGS = $(EXTRA_COMPILER_FLAGS) + +RELEASEDIR=../../../lib +INCLUDEDIR=../../../include +INCLUDES=-I./. -I${INCLUDEDIR} + +OUTS = *.o + +LIBSOURCES:=*.c +INCLUDEFILES:=*.h + +OBJECTS = $(addsuffix .o, $(basename $(wildcard *.c))) + +libs: banner scutimer_libs clean + +%.o: %.c + ${COMPILER} $(CC_FLAGS) $(ECC_FLAGS) $(INCLUDES) -o $@ $< + +banner: + echo "Compiling scutimer" + +scutimer_libs: ${OBJECTS} + $(ARCHIVER) -r ${RELEASEDIR}/${LIB} ${OBJECTS} + +.PHONY: include +include: scutimer_includes + +scutimer_includes: + ${CP} ${INCLUDEFILES} ${INCLUDEDIR} + +clean: + rm -rf ${OBJECTS} diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/scutimer_v2_1/src/xscutimer.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/scutimer_v2_1/src/xscutimer.c new file mode 100644 index 0000000..d7f6348 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/scutimer_v2_1/src/xscutimer.c @@ -0,0 +1,282 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xscutimer.c +* @addtogroup scutimer_v2_1 +* @{ +* +* Contains the implementation of interface functions of the SCU Timer driver. +* See xscutimer.h for a description of the driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 1.00a nm  03/10/10 First release
+* 2.1 	sk  02/26/15 Modified the code for MISRA-C:2012 compliance.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xscutimer.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +/****************************************************************************/ +/** +* +* Initialize a specific timer instance/driver. This function must be called +* before other functions of the driver are called. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* @param ConfigPtr points to the XScuTimer configuration structure. +* @param EffectiveAddress is the base address for the device. It could be +* a virtual address if address translation is supported in the +* system, otherwise it is the physical address. +* +* @return +* - XST_SUCCESS if initialization was successful. +* - XST_DEVICE_IS_STARTED if the device has already been started. +* +* @note None. +* +******************************************************************************/ +s32 XScuTimer_CfgInitialize(XScuTimer *InstancePtr, + XScuTimer_Config *ConfigPtr, u32 EffectiveAddress) +{ + s32 Status; + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(ConfigPtr != NULL); + + /* + * If the device is started, disallow the initialize and return a + * status indicating it is started. This allows the user to stop the + * device and reinitialize, but prevents a user from inadvertently + * initializing. + */ + if (InstancePtr->IsStarted != XIL_COMPONENT_IS_STARTED) { + /* + * Copy configuration into the instance structure. + */ + InstancePtr->Config.DeviceId = ConfigPtr->DeviceId; + + /* + * Save the base address pointer such that the registers of the block + * can be accessed and indicate it has not been started yet. + */ + InstancePtr->Config.BaseAddr = EffectiveAddress; + + InstancePtr->IsStarted = (u32)0; + + /* + * Indicate the instance is ready to use, successfully initialized. + */ + InstancePtr->IsReady = XIL_COMPONENT_IS_READY; + + Status =(s32)XST_SUCCESS; + } + else { + Status = (s32)XST_DEVICE_IS_STARTED; + } + return Status; +} + +/****************************************************************************/ +/** +* +* Start the timer. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XScuTimer_Start(XScuTimer *InstancePtr) +{ + u32 Register; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the contents of the Control register. + */ + Register = XScuTimer_ReadReg(InstancePtr->Config.BaseAddr, + XSCUTIMER_CONTROL_OFFSET); + + /* + * Set the 'timer enable' bit in the register. + */ + Register |= XSCUTIMER_CONTROL_ENABLE_MASK; + + /* + * Update the Control register with the new value. + */ + XScuTimer_WriteReg(InstancePtr->Config.BaseAddr, + XSCUTIMER_CONTROL_OFFSET, Register); + + /* + * Indicate that the device is started. + */ + InstancePtr->IsStarted = XIL_COMPONENT_IS_STARTED; +} + +/****************************************************************************/ +/** +* +* Stop the timer. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XScuTimer_Stop(XScuTimer *InstancePtr) +{ + u32 Register; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the contents of the Control register. + */ + Register = XScuTimer_ReadReg(InstancePtr->Config.BaseAddr, + XSCUTIMER_CONTROL_OFFSET); + + /* + * Clear the 'timer enable' bit in the register. + */ + Register &= (u32)(~XSCUTIMER_CONTROL_ENABLE_MASK); + + /* + * Update the Control register with the new value. + */ + XScuTimer_WriteReg(InstancePtr->Config.BaseAddr, + XSCUTIMER_CONTROL_OFFSET, Register); + + /* + * Indicate that the device is stopped. + */ + InstancePtr->IsStarted = (u32)0; +} + +/*****************************************************************************/ +/** +* +* This function sets the prescaler bits in the timer control register. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* @param PrescalerValue is a 8 bit value that sets the prescaler to use. +* +* @return None +* +* @note None +* +****************************************************************************/ +void XScuTimer_SetPrescaler(XScuTimer *InstancePtr, u8 PrescalerValue) +{ + u32 ControlReg; + + /* + * Assert to validate input arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + /* + * Read the Timer control register. + */ + ControlReg = XScuTimer_ReadReg(InstancePtr->Config.BaseAddr, + XSCUTIMER_CONTROL_OFFSET); + + /* + * Clear all of the prescaler control bits in the register. + */ + ControlReg &= (u32)(~XSCUTIMER_CONTROL_PRESCALER_MASK); + + /* + * Set the prescaler value. + */ + ControlReg |= (((u32)PrescalerValue) << XSCUTIMER_CONTROL_PRESCALER_SHIFT); + + /* + * Write the register with the new values. + */ + XScuTimer_WriteReg(InstancePtr->Config.BaseAddr, + XSCUTIMER_CONTROL_OFFSET, ControlReg); +} + +/*****************************************************************************/ +/** +* +* This function returns the current prescaler value. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* +* @return The prescaler value. +* +* @note None. +* +****************************************************************************/ +u8 XScuTimer_GetPrescaler(XScuTimer *InstancePtr) +{ + u32 ControlReg; + + /* + * Assert to validate input arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the Timer control register. + */ + ControlReg = XScuTimer_ReadReg(InstancePtr->Config.BaseAddr, + XSCUTIMER_CONTROL_OFFSET); + ControlReg &= XSCUTIMER_CONTROL_PRESCALER_MASK; + + return (u8)(ControlReg >> XSCUTIMER_CONTROL_PRESCALER_SHIFT); +} +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/scutimer_v2_1/src/xscutimer.h b/df_datalink/bsp/ps7_cortexa9_0/libsrc/scutimer_v2_1/src/xscutimer.h new file mode 100644 index 0000000..5434684 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/scutimer_v2_1/src/xscutimer.h @@ -0,0 +1,364 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xscutimer.h +* @addtogroup scutimer_v2_1 +* @{ +* @details +* +* The timer driver supports the Cortex A9 private timer. +* +* The timer driver supports the following features: +* - Normal mode and Auto reload mode +* - Interrupts (Interrupt handler is not provided in this driver. Application +* has to register it's own handler) +* +* Initialization and Configuration +* +* The device driver enables higher layer software (e.g., an application) to +* communicate with the Timer. +* +* XScuTimer_CfgInitialize() API is used to initialize the Timer. The +* user needs to first call the XScuTimer_LookupConfig() API which returns +* the Configuration structure pointer which is passed as a parameter to +* the XScuTimer_CfgInitialize() API. +* +* Interrupts +* +* The Timer hardware supports interrupts. +* +* This driver does not provide a Interrupt Service Routine (ISR) for the device. +* It is the responsibility of the application to provide one if needed. Refer to +* the interrupt example provided with this driver for details on using the +* Timer in interrupt mode. +* +* Virtual Memory +* +* This driver supports Virtual Memory. The RTOS is responsible for calculating +* the correct device base address in Virtual Memory space. +* +* Threads +* +* This driver is not thread safe. Any needs for threads or thread mutual +* exclusion must be satisfied by the layer above this driver. +* +* Asserts +* +* Asserts are used within all Xilinx drivers to enforce constraints on argument +* values. Asserts can be turned off on a system-wide basis by defining, at +* compile time, the NDEBUG identifier. By default, asserts are turned on and it +* is recommended that users leave asserts on during development. +* +* Building the driver +* +* The XScuTimer driver is composed of several source files. This allows the user +* to build and link only those parts of the driver that are necessary. +* +*

+* +* NOTE: +* The timer is not a part of the snoop control unit as indicated by the +* prefix "scu" in the name of the driver. +* It is an independent module in APU. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 1.00a nm  03/10/10 First release
+* 1.02a sg  07/17/12 Included xil_assert.h for CR 667947. This is an issue
+*		     when the xstatus.h in the common driver overwrites
+*		     the xstatus.h of the standalone BSP during the
+*		     libgen.
+* 2.1 	sk  02/26/15 Modified the code for MISRA-C:2012 compliance.
+*       ms  03/17/17 Added readme.txt file in examples folder for doxygen
+*                    generation.
+* 
+* +******************************************************************************/ +#ifndef XSCUTIMER_H /* prevent circular inclusions */ +#define XSCUTIMER_H /* by using protection macros */ + +/***************************** Include Files *********************************/ + +#include "xstatus.h" +#include "xscutimer_hw.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/** + * This typedef contains configuration information for the device. + */ +typedef struct { + u16 DeviceId; /**< Unique ID of device */ + u32 BaseAddr; /**< Base address of the device */ +} XScuTimer_Config; + +/** + * The XScuTimer driver instance data. The user is required to allocate a + * variable of this type for every timer device in the system. + * A pointer to a variable of this type is then passed to the driver API + * functions. + */ +typedef struct { + XScuTimer_Config Config; /**< Hardware Configuration */ + u32 IsReady; /**< Device is initialized and ready */ + u32 IsStarted; /**< Device timer is running */ +} XScuTimer; + +/***************** Macros (Inline Functions) Definitions *********************/ + +/****************************************************************************/ +/** +* +* Check if the timer has expired. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* +* @return +* - TRUE if the timer has expired. +* - FALSE if the timer has not expired. +* +* @note C-style signature: +* int XScuTimer_IsExpired(XScuTimer *InstancePtr) +* +******************************************************************************/ +#define XScuTimer_IsExpired(InstancePtr) \ + ((XScuTimer_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_ISR_OFFSET) & \ + XSCUTIMER_ISR_EVENT_FLAG_MASK) == \ + XSCUTIMER_ISR_EVENT_FLAG_MASK) + +/****************************************************************************/ +/** +* +* Re-start the timer. This macro will read the timer load register +* and writes the same value to load register to update the counter register. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_RestartTimer(XScuTimer *InstancePtr) +* +******************************************************************************/ +#define XScuTimer_RestartTimer(InstancePtr) \ + XScuTimer_LoadTimer((InstancePtr), \ + XScuTimer_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_LOAD_OFFSET)) + +/****************************************************************************/ +/** +* +* Write to the timer load register. This will also update the +* timer counter register with the new value. This macro can be used to +* change the time-out value. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* @param Value is the count to be loaded in to the load register. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_LoadTimer(XScuTimer *InstancePtr, u32 Value) +* +******************************************************************************/ +#define XScuTimer_LoadTimer(InstancePtr, Value) \ + XScuTimer_WriteReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_LOAD_OFFSET, (Value)) + +/****************************************************************************/ +/** +* +* Returns the current timer counter register value. It can be called at any +* time. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* +* @return Contents of the timer counter register. +* +* @note C-style signature: + u32 XScuTimer_GetCounterValue(XScuTimer *InstancePtr) +* +******************************************************************************/ +#define XScuTimer_GetCounterValue(InstancePtr) \ + XScuTimer_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_COUNTER_OFFSET) + +/****************************************************************************/ +/** +* +* Enable auto-reload mode. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_EnableAutoReload(XScuTimer *InstancePtr) +* +******************************************************************************/ +#define XScuTimer_EnableAutoReload(InstancePtr) \ + XScuTimer_WriteReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_CONTROL_OFFSET, \ + (XScuTimer_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_CONTROL_OFFSET) | \ + XSCUTIMER_CONTROL_AUTO_RELOAD_MASK)) + +/****************************************************************************/ +/** +* +* Disable auto-reload mode. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_DisableAutoReload(XScuTimer *InstancePtr) +* +******************************************************************************/ +#define XScuTimer_DisableAutoReload(InstancePtr) \ + XScuTimer_WriteReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_CONTROL_OFFSET, \ + (XScuTimer_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_CONTROL_OFFSET) & \ + ~(XSCUTIMER_CONTROL_AUTO_RELOAD_MASK))) + +/****************************************************************************/ +/** +* +* Enable the Timer interrupt. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_EnableInterrupt(XScuTimer *InstancePtr) +* +******************************************************************************/ +#define XScuTimer_EnableInterrupt(InstancePtr) \ + XScuTimer_WriteReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_CONTROL_OFFSET, \ + (XScuTimer_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_CONTROL_OFFSET) | \ + XSCUTIMER_CONTROL_IRQ_ENABLE_MASK)) + +/****************************************************************************/ +/** +* +* Disable the Timer interrupt. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_DisableInterrupt(XScuTimer *InstancePtr) +* +******************************************************************************/ +#define XScuTimer_DisableInterrupt(InstancePtr) \ + XScuTimer_WriteReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_CONTROL_OFFSET, \ + (XScuTimer_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_CONTROL_OFFSET) & \ + ~(XSCUTIMER_CONTROL_IRQ_ENABLE_MASK))) + +/*****************************************************************************/ +/** +* +* This function reads the interrupt status. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_GetInterruptStatus(XScuTimer *InstancePtr) +* +******************************************************************************/ +#define XScuTimer_GetInterruptStatus(InstancePtr) \ + XScuTimer_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_ISR_OFFSET) + +/*****************************************************************************/ +/** +* +* This function clears the interrupt status. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_ClearInterruptStatus(XScuTimer *InstancePtr) +* +******************************************************************************/ +#define XScuTimer_ClearInterruptStatus(InstancePtr) \ + XScuTimer_WriteReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_ISR_OFFSET, XSCUTIMER_ISR_EVENT_FLAG_MASK) + +/************************** Function Prototypes ******************************/ + +/* + * Lookup configuration in xscutimer_sinit.c + */ +XScuTimer_Config *XScuTimer_LookupConfig(u16 DeviceId); + +/* + * Selftest function in xscutimer_selftest.c + */ +s32 XScuTimer_SelfTest(XScuTimer *InstancePtr); + +/* + * Interface functions in xscutimer.c + */ +s32 XScuTimer_CfgInitialize(XScuTimer *InstancePtr, + XScuTimer_Config *ConfigPtr, u32 EffectiveAddress); +void XScuTimer_Start(XScuTimer *InstancePtr); +void XScuTimer_Stop(XScuTimer *InstancePtr); +void XScuTimer_SetPrescaler(XScuTimer *InstancePtr, u8 PrescalerValue); +u8 XScuTimer_GetPrescaler(XScuTimer *InstancePtr); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/scutimer_v2_1/src/xscutimer_g.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/scutimer_v2_1/src/xscutimer_g.c new file mode 100644 index 0000000..d1e3c24 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/scutimer_v2_1/src/xscutimer_g.c @@ -0,0 +1,51 @@ + +/******************************************************************* +* +* CAUTION: This file is automatically generated by HSI. +* Version: 2019.1.3 +* DO NOT EDIT. +* +* Copyright (C) 2010-2023 Xilinx, Inc. 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 +*XILINX 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. +* +*Except as contained in this notice, the name of the Xilinx shall not be used +*in advertising or otherwise to promote the sale, use or other dealings in +*this Software without prior written authorization from Xilinx. +* + +* +* Description: Driver configuration +* +*******************************************************************/ + +#include "xparameters.h" +#include "xscutimer.h" + +/* +* The configuration table for devices +*/ + +XScuTimer_Config XScuTimer_ConfigTable[XPAR_XSCUTIMER_NUM_INSTANCES] = +{ + { + XPAR_PS7_SCUTIMER_0_DEVICE_ID, + XPAR_PS7_SCUTIMER_0_BASEADDR + } +}; + + diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/scutimer_v2_1/src/xscutimer_hw.h b/df_datalink/bsp/ps7_cortexa9_0/libsrc/scutimer_v2_1/src/xscutimer_hw.h new file mode 100644 index 0000000..d577784 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/scutimer_v2_1/src/xscutimer_hw.h @@ -0,0 +1,283 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xscutimer_hw.h +* @addtogroup scutimer_v2_1 +* @{ +* +* This file contains the hardware interface to the Timer. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 1.00a nm  03/10/10 First release
+* 1.01a sdm 02/02/12 Added low level macros to read/write load, counter, control
+*		     and interrupt registers
+* 1.02a  sg 07/17/12 Included xil_assert.h for CR 667947. This is an issue
+*		     when the xstatus.h in the common driver overwrites
+*		     the xstatus.h of the standalone BSP during the
+*		     libgen.
+* 2.1 	sk  02/26/15 Modified the code for MISRA-C:2012 compliance.
+* 
+* +******************************************************************************/ +#ifndef XSCUTIMER_HW_H /* prevent circular inclusions */ +#define XSCUTIMER_HW_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ +#include "xil_types.h" +#include "xil_io.h" +#include "xil_assert.h" +/************************** Constant Definitions *****************************/ + +/** @name Register Map + * Offsets of registers from the start of the device + * @{ + */ + +#define XSCUTIMER_LOAD_OFFSET 0x00U /**< Timer Load Register */ +#define XSCUTIMER_COUNTER_OFFSET 0x04U /**< Timer Counter Register */ +#define XSCUTIMER_CONTROL_OFFSET 0x08U /**< Timer Control Register */ +#define XSCUTIMER_ISR_OFFSET 0x0CU /**< Timer Interrupt + Status Register */ +/* @} */ + +/** @name Timer Control register + * This register bits control the prescaler, Intr enable, + * auto-reload and timer enable. + * @{ + */ + +#define XSCUTIMER_CONTROL_PRESCALER_MASK 0x0000FF00U /**< Prescaler */ +#define XSCUTIMER_CONTROL_PRESCALER_SHIFT 8U +#define XSCUTIMER_CONTROL_IRQ_ENABLE_MASK 0x00000004U /**< Intr enable */ +#define XSCUTIMER_CONTROL_AUTO_RELOAD_MASK 0x00000002U /**< Auto-reload */ +#define XSCUTIMER_CONTROL_ENABLE_MASK 0x00000001U /**< Timer enable */ +/* @} */ + +/** @name Interrupt Status register + * This register indicates the Timer counter register has reached zero. + * @{ + */ + +#define XSCUTIMER_ISR_EVENT_FLAG_MASK 0x00000001U /**< Event flag */ +/*@}*/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/****************************************************************************/ +/** +* +* Write to the timer load register. This will also update the +* timer counter register with the new value. This macro can be used to +* change the time-out value. +* +* @param BaseAddr is the base address of the scu timer. +* @param Value is the count to be loaded in to the load register. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_SetLoadReg(u32 BaseAddr, u32 Value) +* +******************************************************************************/ +#define XScuTimer_SetLoadReg(BaseAddr, Value) \ + XScuTimer_WriteReg(BaseAddr, XSCUTIMER_LOAD_OFFSET, (Value)) + +/****************************************************************************/ +/** +* +* Returns the current timer load register value. +* +* @param BaseAddr is the base address of the scu timer. +* +* @return Contents of the timer load register. +* +* @note C-style signature: +* u32 XScuTimer_GetLoadReg(u32 BaseAddr) +* +******************************************************************************/ +#define XScuTimer_GetLoadReg(BaseAddr) \ + XScuTimer_ReadReg(BaseAddr, XSCUTIMER_LOAD_OFFSET) + +/****************************************************************************/ +/** +* +* Write to the timer counter register. +* +* @param BaseAddr is the base address of the scu timer. +* @param Value is the count to be loaded in to the counter register. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_SetCounterReg(u32 BaseAddr, u32 Value) +* +******************************************************************************/ +#define XScuTimer_SetCounterReg(BaseAddr, Value) \ + XScuTimer_WriteReg(BaseAddr, XSCUTIMER_COUNTER_OFFSET, (Value)) + +/****************************************************************************/ +/** +* +* Returns the current timer counter register value. +* +* @param BaseAddr is the base address of the scu timer. +* +* @return Contents of the timer counter register. +* +* @note C-style signature: + u32 XScuTimer_GetCounterReg(u32 BaseAddr) +* +******************************************************************************/ +#define XScuTimer_GetCounterReg(BaseAddr) \ + XScuTimer_ReadReg(BaseAddr, XSCUTIMER_COUNTER_OFFSET) + +/****************************************************************************/ +/** +* +* Write to the timer load register. This will also update the +* timer counter register with the new value. This macro can be used to +* change the time-out value. +* +* @param BaseAddr is the base address of the scu timer. +* @param Value is the count to be loaded in to the load register. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_SetControlReg(u32 BaseAddr, u32 Value) +* +******************************************************************************/ +#define XScuTimer_SetControlReg(BaseAddr, Value) \ + XScuTimer_WriteReg(BaseAddr, XSCUTIMER_CONTROL_OFFSET, (Value)) + +/****************************************************************************/ +/** +* +* Returns the current timer load register value. +* +* @param BaseAddr is the base address of the scu timer. +* +* @return Contents of the timer load register. +* +* @note C-style signature: + u32 XScuTimer_GetControlReg(u32 BaseAddr) +* +******************************************************************************/ +#define XScuTimer_GetControlReg(BaseAddr) \ + XScuTimer_ReadReg(BaseAddr, XSCUTIMER_CONTROL_OFFSET) + +/****************************************************************************/ +/** +* +* Write to the timer counter register. +* +* @param BaseAddr is the base address of the scu timer. +* @param Value is the count to be loaded in to the counter register. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_SetIntrReg(u32 BaseAddr, u32 Value) +* +******************************************************************************/ +#define XScuTimer_SetIntrReg(BaseAddr, Value) \ + XScuTimer_WriteReg(BaseAddr, XSCUTIMER_ISR_OFFSET, (Value)) + +/****************************************************************************/ +/** +* +* Returns the current timer counter register value. +* +* @param BaseAddr is the base address of the scu timer. +* +* @return Contents of the timer counter register. +* +* @note C-style signature: + u32 XScuTimer_GetIntrReg(u32 BaseAddr) +* +******************************************************************************/ +#define XScuTimer_GetIntrReg(BaseAddr) \ + XScuTimer_ReadReg(BaseAddr, XSCUTIMER_ISR_OFFSET) + +/****************************************************************************/ +/** +* +* Read from the given Timer register. +* +* @param BaseAddr is the base address of the device +* @param RegOffset is the register offset to be read +* +* @return The 32-bit value of the register +* +* @note C-style signature: +* u32 XScuTimer_ReadReg(u32 BaseAddr, u32 RegOffset) +* +*****************************************************************************/ +#define XScuTimer_ReadReg(BaseAddr, RegOffset) \ + Xil_In32((BaseAddr) + (RegOffset)) + +/****************************************************************************/ +/** +* +* Write to the given Timer register. +* +* @param BaseAddr is the base address of the device +* @param RegOffset is the register offset to be written +* @param Data is the 32-bit value to write to the register +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_WriteReg(u32 BaseAddr, u32 RegOffset, u32 Data) +* +*****************************************************************************/ +#define XScuTimer_WriteReg(BaseAddr, RegOffset, Data) \ + Xil_Out32((BaseAddr) + (RegOffset), (Data)) + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/scutimer_v2_1/src/xscutimer_selftest.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/scutimer_v2_1/src/xscutimer_selftest.c new file mode 100644 index 0000000..b3464b6 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/scutimer_v2_1/src/xscutimer_selftest.c @@ -0,0 +1,135 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xscutimer_selftest.c +* @addtogroup scutimer_v2_1 +* @{ +* +* Contains diagnostic self-test functions for the XScuTimer driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 1.00a nm  03/10/10 First release
+* 2.1 	sk  02/26/15 Modified the code for MISRA-C:2012 compliance.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xscutimer.h" + +/************************** Constant Definitions *****************************/ + +#define XSCUTIMER_SELFTEST_VALUE 0xA55AF00FU + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +/****************************************************************************/ +/** +* +* Run a self-test on the timer. This test clears the timer enable bit in +* the control register, writes to the timer load register and verifies the +* value read back matches the value written and restores the control register +* and the timer load register. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* +* @return +* - XST_SUCCESS if self-test was successful. +* - XST_FAILURE if self test was not successful. +* +* @note None. +* +******************************************************************************/ +s32 XScuTimer_SelfTest(XScuTimer *InstancePtr) +{ + u32 Register; + u32 CtrlOrig; + u32 LoadOrig; + s32 Status; + + /* + * Assert to ensure the inputs are valid and the instance has been + * initialized. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Save the contents of the Control Register and stop the timer. + */ + CtrlOrig = XScuTimer_ReadReg(InstancePtr->Config.BaseAddr, + XSCUTIMER_CONTROL_OFFSET); + Register = CtrlOrig & (u32)(~XSCUTIMER_CONTROL_ENABLE_MASK); + XScuTimer_WriteReg(InstancePtr->Config.BaseAddr, + XSCUTIMER_CONTROL_OFFSET, Register); + + /* + * Save the contents of the Load Register. + * Load a new test value in the Load Register, read it back and + * compare it with the written value. + */ + LoadOrig = XScuTimer_ReadReg((InstancePtr)->Config.BaseAddr, + XSCUTIMER_LOAD_OFFSET); + XScuTimer_LoadTimer(InstancePtr, XSCUTIMER_SELFTEST_VALUE); + Register = XScuTimer_ReadReg((InstancePtr)->Config.BaseAddr, + XSCUTIMER_LOAD_OFFSET); + + /* + * Restore the contents of the Load Register and Control Register. + */ + XScuTimer_LoadTimer(InstancePtr, LoadOrig); + XScuTimer_WriteReg(InstancePtr->Config.BaseAddr, + XSCUTIMER_CONTROL_OFFSET, CtrlOrig); + + /* + * Return a Failure if the contents of the Load Register do not + * match with the value written to it. + */ + if (Register != XSCUTIMER_SELFTEST_VALUE) { + Status = (s32)XST_FAILURE; + } + else { + Status = (s32)XST_SUCCESS; + } + + return Status; +} +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/scutimer_v2_1/src/xscutimer_sinit.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/scutimer_v2_1/src/xscutimer_sinit.c new file mode 100644 index 0000000..0c5f671 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/scutimer_v2_1/src/xscutimer_sinit.c @@ -0,0 +1,92 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xscutimer_sinit.c +* @addtogroup scutimer_v2_1 +* @{ +* +* This file contains method for static initialization (compile-time) of the +* driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 1.00a nm  03/10/10 First release
+* 2.1 	sk  02/26/15 Modified the code for MISRA-C:2012 compliance.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xscutimer.h" +#include "xparameters.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Variable Definitions ****************************/ +extern XScuTimer_Config XScuTimer_ConfigTable[XPAR_XSCUTIMER_NUM_INSTANCES]; + +/************************** Function Prototypes ******************************/ + +/*****************************************************************************/ +/** +* Lookup the device configuration based on the unique device ID. The table +* contains the configuration info for each device in the system. +* +* @param DeviceId is the unique device ID of the device being looked up. +* +* @return A pointer to the configuration table entry corresponding to the +* given device ID, or NULL if no match is found. +* +* @note None. +* +******************************************************************************/ +XScuTimer_Config *XScuTimer_LookupConfig(u16 DeviceId) +{ + XScuTimer_Config *CfgPtr = NULL; + u32 Index; + + for (Index = 0U; Index < XPAR_XSCUTIMER_NUM_INSTANCES; Index++) { + if (XScuTimer_ConfigTable[Index].DeviceId == DeviceId) { + CfgPtr = &XScuTimer_ConfigTable[Index]; + break; + } + } + + return (XScuTimer_Config *)CfgPtr; +} +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/scuwdt_v2_1/src/Makefile b/df_datalink/bsp/ps7_cortexa9_0/libsrc/scuwdt_v2_1/src/Makefile new file mode 100644 index 0000000..493ad9a --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/scuwdt_v2_1/src/Makefile @@ -0,0 +1,40 @@ +COMPILER= +ARCHIVER= +CP=cp +COMPILER_FLAGS= +EXTRA_COMPILER_FLAGS= +LIB=libxil.a + +CC_FLAGS = $(COMPILER_FLAGS) +ECC_FLAGS = $(EXTRA_COMPILER_FLAGS) + +RELEASEDIR=../../../lib +INCLUDEDIR=../../../include +INCLUDES=-I./. -I${INCLUDEDIR} + +OUTS = *.o + +LIBSOURCES:=*.c +INCLUDEFILES:=*.h + +OBJECTS = $(addsuffix .o, $(basename $(wildcard *.c))) + +libs: banner scuwdt_libs clean + +%.o: %.c + ${COMPILER} $(CC_FLAGS) $(ECC_FLAGS) $(INCLUDES) -o $@ $< + +banner: + echo "Compiling scuwdt" + +scuwdt_libs: ${OBJECTS} + $(ARCHIVER) -r ${RELEASEDIR}/${LIB} ${OBJECTS} + +.PHONY: include +include: scuwdt_includes + +scuwdt_includes: + ${CP} ${INCLUDEFILES} ${INCLUDEDIR} + +clean: + rm -rf ${OBJECTS} diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/scuwdt_v2_1/src/xscuwdt.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/scuwdt_v2_1/src/xscuwdt.c new file mode 100644 index 0000000..85f0507 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/scuwdt_v2_1/src/xscuwdt.c @@ -0,0 +1,213 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xscuwdt.c +* @addtogroup scuwdt_v2_1 +* @{ +* +* Contains the implementation of interface functions of the XScuWdt driver. +* See xscuwdt.h for a description of the driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 1.00a sdm 01/15/10 First release
+* 2.1 	sk  02/26/15 Modified the code for MISRA-C:2012 compliance.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xscuwdt.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +/****************************************************************************/ +/** +* +* Initialize a specific watchdog timer instance/driver. This function +* must be called before other functions of the driver are called. +* +* @param InstancePtr is a pointer to the XScuWdt instance. +* @param ConfigPtr is the config structure. +* @param EffectiveAddress is the base address for the device. It could be +* a virtual address if address translation is supported in the +* system, otherwise it is the physical address. +* +* @return +* - XST_SUCCESS if initialization was successful. +* - XST_DEVICE_IS_STARTED if the device has already been started. +* +* @note This function enables the watchdog mode. +* +******************************************************************************/ +s32 XScuWdt_CfgInitialize(XScuWdt *InstancePtr, + XScuWdt_Config *ConfigPtr, u32 EffectiveAddress) +{ + s32 CfgStatus; + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(ConfigPtr != NULL); + Xil_AssertNonvoid(EffectiveAddress != 0x00U); + + /* + * If the device is started, disallow the initialize and return a + * status indicating it is started. This allows the user to stop the + * device and reinitialize, but prevents a user from inadvertently + * initializing. + */ + if (InstancePtr->IsStarted == XIL_COMPONENT_IS_STARTED) { + CfgStatus = (s32)XST_DEVICE_IS_STARTED; + } + else { + /* + * Copy configuration into instance. + */ + InstancePtr->Config.DeviceId = ConfigPtr->DeviceId; + + /* + * Save the base address pointer such that the registers of the block + * can be accessed and indicate it has not been started yet. + */ + InstancePtr->Config.BaseAddr = EffectiveAddress; + InstancePtr->IsStarted = 0U; + + /* + * Put the watchdog timer in Watchdog mode. + */ + XScuWdt_SetWdMode(InstancePtr); + + /* + * Indicate the instance is ready to use, successfully initialized. + */ + InstancePtr->IsReady = XIL_COMPONENT_IS_READY; + + CfgStatus =(s32)XST_SUCCESS; + } + return CfgStatus; +} + +/****************************************************************************/ +/** +* +* Start the watchdog counter of the device. +* +* @param InstancePtr is a pointer to the XScuWdt instance. +* +* @return None. +* +* @note User needs to select the appropriate mode (watchdog/timer) +* before using this API. +* See XScuWdt_SetWdMode/XScuWdt_SetTimerMode macros in +* xscuwdt.h. +* +******************************************************************************/ +void XScuWdt_Start(XScuWdt *InstancePtr) +{ + u32 Register; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the contents of the Control register. + */ + Register = XScuWdt_ReadReg(InstancePtr->Config.BaseAddr, + XSCUWDT_CONTROL_OFFSET); + + /* + * Set the 'watchdog enable' bit in the register. + */ + Register |= XSCUWDT_CONTROL_WD_ENABLE_MASK; + + /* + * Update the Control register with the new value. + */ + XScuWdt_WriteReg(InstancePtr->Config.BaseAddr, + XSCUWDT_CONTROL_OFFSET, Register); + + /* + * Indicate that the device is started. + */ + InstancePtr->IsStarted = XIL_COMPONENT_IS_STARTED; +} + +/****************************************************************************/ +/** +* +* Stop the watchdog timer. +* +* @param InstancePtr is a pointer to the XScuWdt instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XScuWdt_Stop(XScuWdt *InstancePtr) +{ + u32 Register; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the contents of the Control register. + */ + Register = XScuWdt_ReadReg(InstancePtr->Config.BaseAddr, + XSCUWDT_CONTROL_OFFSET); + + /* + * Clear the 'watchdog enable' bit in the register. + */ + Register &= (u32)(~XSCUWDT_CONTROL_WD_ENABLE_MASK); + + /* + * Update the Control register with the new value. + */ + XScuWdt_WriteReg(InstancePtr->Config.BaseAddr, + XSCUWDT_CONTROL_OFFSET, Register); + + /* + * Indicate that the device is stopped. + */ + InstancePtr->IsStarted = 0U; +} +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/scuwdt_v2_1/src/xscuwdt.h b/df_datalink/bsp/ps7_cortexa9_0/libsrc/scuwdt_v2_1/src/xscuwdt.h new file mode 100644 index 0000000..551eaf5 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/scuwdt_v2_1/src/xscuwdt.h @@ -0,0 +1,379 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xscuwdt.h +* @addtogroup scuwdt_v2_1 +* @{ +* @details +* +* The Xilinx SCU watchdog timer driver (XScuWdt) supports the Xilinx SCU private +* watchdog timer hardware. +* +* The XScuWdt driver supports the following features: +* - Watchdog mode +* - Timer mode +* - Auto reload (timer mode only) +* +* The watchdog counter register is a down counter and starts decrementing when +* the watchdog is started. +* In watchdog mode, when the counter reaches 0, the Reset flag is set in the +* Reset status register and the WDRESETREQ pin is asserted, causing a system +* reset. The Reset flag is not reset by normal processor reset and is cleared +* when written with a value of 1. This enables the user to differentiate a +* normal reset and a reset caused by watchdog time-out. The user needs to call +* XScuWdt_RestartWdt() periodically, to avoid the watchdog from being timed-out. +* +* The IsWdtExpired function can be used to check if the watchdog was the cause +* of the last reset. In this situation, call Initialize then call IsWdtExpired. +* If the result is true, watchdog timeout caused the last system reset. The +* application then needs to clear the Reset flag. +* +* In timer mode, when the counter reaches 0, the Event flag is set in the +* Interrupt status register and if interrupts are enabled, interrupt ID 30 is +* set as pending in the interrupt distributor. The IsTimerExpired function +* is used to check if the watchdog counter has decremented to 0 in timer mode. +* If auto-reload mode is enabled, the Counter register is automatically reloaded +* from the Load register. +* +* Initialization and Configuration +* +* The device driver enables higher layer software (e.g., an application) to +* communicate with the Watchdog Timer. +* +* XScuWdt_CfgInitialize() API is used to initialize the Watchdog Timer. The +* user needs to first call the XScuWdt_LookupConfig() API which returns +* the Configuration structure pointer which is passed as a parameter to +* the XScuWdt_CfgInitialize() API. +* +* Interrupts +* +* The SCU Watchdog Timer supports interrupts in Timer mode. +* +* This driver does not provide a Interrupt Service Routine (ISR) for the device. +* It is the responsibility of the application to provide one if needed. Refer to +* the interrupt example provided with this driver for details on using the +* Timer in interrupt mode. +* +* Virtual Memory +* +* This driver supports Virtual Memory. The RTOS is responsible for calculating +* the correct device base address in Virtual Memory space. +* +* Threads +* +* This driver is not thread safe. Any needs for threads or thread mutual +* exclusion must be satisfied by the layer above this driver. +* +* Asserts +* +* Asserts are used within all Xilinx drivers to enforce constraints on argument +* values. Asserts can be turned off on a system-wide basis by defining, at +* compile time, the NDEBUG identifier. By default, asserts are turned on and it +* is recommended that users leave asserts on during development. +* +* Building the driver +* +* The XScuWdt driver is composed of several source files. This allows the user +* to build and link only those parts of the driver that are necessary. +* +*

+* +* NOTE: +* The watchdog timer is not a part of the snoop control unit as indicated +* by the prefix "scu" in the name of the driver. +* It is an independent module in APU. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 1.00a sdm 01/15/10 First release
+* 1.02a  sg 07/17/12 Included xil_assert.h for CR 667947. This is an issue
+*		     when the xstatus.h in the common driver overwrites
+*		     the xstatus.h of the standalone BSP during the
+*		     libgen.
+* 2.1 	sk  02/26/15 Modified the code for MISRA-C:2012 compliance.
+*       ms  03/17/17 Added readme.txt file in examples folder for doxygen
+*                    generation.
+* 
+* +******************************************************************************/ +#ifndef XSCUWDT_H /* prevent circular inclusions */ +#define XSCUWDT_H /* by using protection macros */ + +/***************************** Include Files *********************************/ + +#include "xstatus.h" +#include "xscuwdt_hw.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/** + * This typedef contains configuration information for the device. + */ +typedef struct { + u16 DeviceId; /**< Unique ID of device */ + u32 BaseAddr; /**< Base address of the device */ +} XScuWdt_Config; + +/** + * The XScuWdt driver instance data. The user is required to allocate a + * variable of this type for every watchdog/timer device in the system. + * A pointer to a variable of this type is then passed to the driver API + * functions. + */ +typedef struct { + XScuWdt_Config Config;/**< Hardware Configuration */ + u32 IsReady; /**< Device is initialized and ready */ + u32 IsStarted; /**< Device watchdog timer is running */ +} XScuWdt; + +/***************** Macros (Inline Functions) Definitions *********************/ +/****************************************************************************/ +/** +* +* This function is used to check if the watchdog has timed-out and the last +* reset was caused by the watchdog reset. +* +* @param InstancePtr is a pointer to the XScuWdt instance. +* +* @return +* - TRUE if the watchdog has expired. +* - FALSE if the watchdog has not expired. +* +* @note C-style signature: +* int XScuWdt_IsWdtExpired(XScuWdt *InstancePtr) +* +******************************************************************************/ +#define XScuWdt_IsWdtExpired(InstancePtr) \ + ((XScuWdt_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUWDT_RST_STS_OFFSET) & \ + XSCUWDT_RST_STS_RESET_FLAG_MASK) == XSCUWDT_RST_STS_RESET_FLAG_MASK) + +/****************************************************************************/ +/** +* +* This function is used to check if the watchdog counter has reached 0 in timer +* mode. +* +* @param InstancePtr is a pointer to the XScuWdt instance. +* +* @return +* - TRUE if the watchdog has expired. +* - FALSE if the watchdog has not expired. +* +* @note C-style signature: +* int XScuWdt_IsTimerExpired(XScuWdt *InstancePtr) +* +******************************************************************************/ +#define XScuWdt_IsTimerExpired(InstancePtr) \ + ((XScuWdt_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUWDT_ISR_OFFSET) & \ + XSCUWDT_ISR_EVENT_FLAG_MASK) == XSCUWDT_ISR_EVENT_FLAG_MASK) + +/****************************************************************************/ +/** +* +* Re-start the watchdog timer. This macro will read the watchdog load register +* and write the same value to load register to update the counter register. +* An application needs to call this function periodically to keep the watchdog +* from asserting the WDRESETREQ reset request output pin. +* +* @param InstancePtr is a pointer to the XScuWdt instance. +* +* @return None. +* +* @note C-style signature: +* void XScuWdt_RestartWdt(XScuWdt *InstancePtr) +* +******************************************************************************/ +#define XScuWdt_RestartWdt(InstancePtr) \ + XScuWdt_LoadWdt((InstancePtr), \ + (XScuWdt_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUWDT_LOAD_OFFSET))) + +/****************************************************************************/ +/** +* +* Write to the watchdog timer load register. This will also update the +* watchdog counter register with the new value. This macro can be used to +* change the time-out value. +* +* @param InstancePtr is a pointer to the XScuWdt instance. +* @param Value is the value to be written to the Watchdog Load register. +* +* @return None. +* +* @note C-style signature: +* void XScuWdt_LoadWdt(XScuWdt *InstancePtr, u32 Value) +* +******************************************************************************/ +#define XScuWdt_LoadWdt(InstancePtr, Value) \ + XScuWdt_WriteReg((InstancePtr)->Config.BaseAddr, \ + XSCUWDT_LOAD_OFFSET, (Value)) + +/****************************************************************************/ +/** +* +* Put the watchdog timer in Watchdog mode by setting the WD mode bit of the +* Watchdog control register. +* +* @param InstancePtr is a pointer to the XScuWdt instance. +* +* @return None. +* +* @note C-style signature: +* void XScuWdt_SetWdMode(XScuWdt *InstancePtr) +* +******************************************************************************/ +#define XScuWdt_SetWdMode(InstancePtr) \ + XScuWdt_WriteReg((InstancePtr)->Config.BaseAddr, \ + XSCUWDT_CONTROL_OFFSET, \ + (XScuWdt_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUWDT_CONTROL_OFFSET) | \ + (XSCUWDT_CONTROL_WD_MODE_MASK))) + +/****************************************************************************/ +/** +* +* Put the watchdog timer in Timer mode by writing 0x12345678 and 0x87654321 +* successively to the Watchdog Disable Register. +* The software must write 0x12345678 and 0x87654321 successively to the +* Watchdog Disable Register so that the watchdog mode bit in the Watchdog +* Control Register is set to zero. +* +* @param InstancePtr is a pointer to the XScuWdt instance. +* +* @return None. +* +* @note C-style signature: +* void XScuWdt_SetTimerMode(XScuWdt *InstancePtr) +* +******************************************************************************/ +#define XScuWdt_SetTimerMode(InstancePtr) \ +{ \ + XScuWdt_WriteReg((InstancePtr)->Config.BaseAddr, \ + XSCUWDT_DISABLE_OFFSET, \ + XSCUWDT_DISABLE_VALUE1); \ + XScuWdt_WriteReg((InstancePtr)->Config.BaseAddr, \ + XSCUWDT_DISABLE_OFFSET, \ + XSCUWDT_DISABLE_VALUE2); \ +} + +/****************************************************************************/ +/** +* +* Get the contents of the watchdog control register. +* +* @param InstancePtr is a pointer to the XScuWdt instance. +* +* @return Contents of the watchdog control register. +* +* @note C-style signature: + u32 XScuWdt_GetControlReg(XScuWdt *InstancePtr) +* +******************************************************************************/ +#define XScuWdt_GetControlReg(InstancePtr) \ + XScuWdt_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUWDT_CONTROL_OFFSET) + +/****************************************************************************/ +/** +* +* Write to the watchdog control register. +* +* @param InstancePtr is a pointer to the XScuWdt instance. +* @param ControlReg is the value to be written to the watchdog control +* register. +* +* @return None. +* +* @note C-style signature: + void XScuWdt_SetControlReg(XScuWdt *InstancePtr, u32 ControlReg) +* +******************************************************************************/ +#define XScuWdt_SetControlReg(InstancePtr, ControlReg) \ + XScuWdt_WriteReg((InstancePtr)->Config.BaseAddr, \ + XSCUWDT_CONTROL_OFFSET, (ControlReg)) + +/****************************************************************************/ +/** +* +* Enable auto-reload mode. +* +* @param InstancePtr is a pointer to the XScuWdt instance. +* +* @return None. +* +* @note C-style signature: +* void XScuWdt_EnableAutoReload(XScuWdt *InstancePtr) +* +******************************************************************************/ +#define XScuWdt_EnableAutoReload(InstancePtr) \ + XScuWdt_SetControlReg((InstancePtr), \ + (XScuWdt_GetControlReg(InstancePtr) | \ + XSCUWDT_CONTROL_AUTO_RELOAD_MASK)) + +/************************** Function Prototypes ******************************/ + +/* + * Lookup configuration in xscuwdt_sinit.c. + */ +XScuWdt_Config *XScuWdt_LookupConfig(u16 DeviceId); + +/* + * Selftest function in xscuwdt_selftest.c + */ +s32 XScuWdt_SelfTest(XScuWdt *InstancePtr); + +/* + * Interface functions in xscuwdt.c + */ +s32 XScuWdt_CfgInitialize(XScuWdt *InstancePtr, + XScuWdt_Config *ConfigPtr, u32 EffectiveAddress); + +void XScuWdt_Start(XScuWdt *InstancePtr); + +void XScuWdt_Stop(XScuWdt *InstancePtr); + + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/scuwdt_v2_1/src/xscuwdt_g.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/scuwdt_v2_1/src/xscuwdt_g.c new file mode 100644 index 0000000..0097f71 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/scuwdt_v2_1/src/xscuwdt_g.c @@ -0,0 +1,51 @@ + +/******************************************************************* +* +* CAUTION: This file is automatically generated by HSI. +* Version: 2019.1.3 +* DO NOT EDIT. +* +* Copyright (C) 2010-2023 Xilinx, Inc. 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 +*XILINX 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. +* +*Except as contained in this notice, the name of the Xilinx shall not be used +*in advertising or otherwise to promote the sale, use or other dealings in +*this Software without prior written authorization from Xilinx. +* + +* +* Description: Driver configuration +* +*******************************************************************/ + +#include "xparameters.h" +#include "xscuwdt.h" + +/* +* The configuration table for devices +*/ + +XScuWdt_Config XScuWdt_ConfigTable[XPAR_XSCUWDT_NUM_INSTANCES] = +{ + { + XPAR_PS7_SCUWDT_0_DEVICE_ID, + XPAR_PS7_SCUWDT_0_BASEADDR + } +}; + + diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/scuwdt_v2_1/src/xscuwdt_hw.h b/df_datalink/bsp/ps7_cortexa9_0/libsrc/scuwdt_v2_1/src/xscuwdt_hw.h new file mode 100644 index 0000000..ad87a05 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/scuwdt_v2_1/src/xscuwdt_hw.h @@ -0,0 +1,178 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xscuwdt_hw.h +* @addtogroup scuwdt_v2_1 +* @{ +* +* This file contains the hardware interface to the Xilinx SCU private Watch Dog +* Timer (XSCUWDT). +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 1.00a sdm 01/15/10 First release
+* 1.01a bss 02/27/12 Updated the register offsets to start at 0x0 instead
+*                    of 0x20 as the base address obtained from the tools
+*		     starts at 0x20.
+* 1.02a  sg 07/17/12 Included xil_assert.h for CR 667947. This is an issue
+*		     when the xstatus.h in the common driver overwrites
+*		     the xstatus.h of the standalone BSP during the
+*		     libgen.
+* 2.1 	sk  02/26/15 Modified the code for MISRA-C:2012 compliance.
+* 
+* +******************************************************************************/ +#ifndef XSCUWDT_HW_H /* prevent circular inclusions */ +#define XSCUWDT_HW_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_io.h" +#include "xil_assert.h" +/************************** Constant Definitions *****************************/ + +/** @name Register Map + * Offsets of registers from the start of the device. The WDT registers start at + * an offset 0x20 + * @{ + */ + +#define XSCUWDT_LOAD_OFFSET 0x00U /**< Watchdog Load Register */ +#define XSCUWDT_COUNTER_OFFSET 0x04U /**< Watchdog Counter Register */ +#define XSCUWDT_CONTROL_OFFSET 0x08U /**< Watchdog Control Register */ +#define XSCUWDT_ISR_OFFSET 0x0CU /**< Watchdog Interrupt Status Register */ +#define XSCUWDT_RST_STS_OFFSET 0x10U /**< Watchdog Reset Status Register */ +#define XSCUWDT_DISABLE_OFFSET 0x14U /**< Watchdog Disable Register */ +/* @} */ + +/** @name Watchdog Control register + * This register bits control the prescaler, WD/Timer mode, Intr enable, + * auto-reload, watchdog enable. + * @{ + */ + +#define XSCUWDT_CONTROL_PRESCALER_MASK 0x0000FF00U /**< Prescaler */ +#define XSCUWDT_CONTROL_PRESCALER_SHIFT 8U +#define XSCUWDT_CONTROL_WD_MODE_MASK 0x00000008U /**< Watchdog/Timer mode */ +#define XSCUWDT_CONTROL_IT_ENABLE_MASK 0x00000004U /**< Intr enable (in + timer mode) */ +#define XSCUWDT_CONTROL_AUTO_RELOAD_MASK 0x00000002U /**< Auto-reload (in + timer mode) */ +#define XSCUWDT_CONTROL_WD_ENABLE_MASK 0x00000001U /**< Watchdog enable */ +/* @} */ + +/** @name Interrupt Status register + * This register indicates the Counter register has reached zero in Counter + * mode. + * @{ + */ + +#define XSCUWDT_ISR_EVENT_FLAG_MASK 0x00000001U /**< Event flag */ +/*@}*/ + +/** @name Reset Status register + * This register indicates the Counter register has reached zero in Watchdog + * mode and a reset request is sent. + * @{ + */ + +#define XSCUWDT_RST_STS_RESET_FLAG_MASK 0x00000001U /**< Time out occured */ +/*@}*/ + +/** @name Disable register + * This register is used to switch from watchdog mode to timer mode. + * The software must write 0x12345678 and 0x87654321 successively to the + * Watchdog Disable Register so that the watchdog mode bit in the Watchdog + * Control Register is set to zero. + * @{ + */ +#define XSCUWDT_DISABLE_VALUE1 0x12345678U /**< Watchdog mode disable + value 1 */ +#define XSCUWDT_DISABLE_VALUE2 0x87654321U /**< Watchdog mode disable + value 2 */ +/*@}*/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/****************************************************************************/ +/** +* +* Read the given register. +* +* @param BaseAddr is the base address of the device +* @param RegOffset is the register offset to be read +* +* @return The 32-bit value of the register +* +* @note C-style signature: +* u32 XScuWdt_ReadReg(u32 BaseAddr, u32 RegOffset) +* +*****************************************************************************/ +#define XScuWdt_ReadReg(BaseAddr, RegOffset) \ + Xil_In32((BaseAddr) + ((u32)RegOffset)) + +/****************************************************************************/ +/** +* +* Write the given register. +* +* @param BaseAddr is the base address of the device +* @param RegOffset is the register offset to be written +* @param Data is the 32-bit value to write to the register +* +* @return None. +* +* @note C-style signature: +* void XScuWdt_WriteReg(u32 BaseAddr, u32 RegOffset, u32 Data) +* +*****************************************************************************/ +#define XScuWdt_WriteReg(BaseAddr, RegOffset, Data) \ + Xil_Out32((BaseAddr) + ((u32)RegOffset), ((u32)Data)) + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/scuwdt_v2_1/src/xscuwdt_selftest.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/scuwdt_v2_1/src/xscuwdt_selftest.c new file mode 100644 index 0000000..aa0cd39 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/scuwdt_v2_1/src/xscuwdt_selftest.c @@ -0,0 +1,127 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xscuwdt_selftest.c +* @addtogroup scuwdt_v2_1 +* @{ +* +* Contains diagnostic self-test functions for the XScuWdt driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 1.00a sdm 01/15/10 First release
+* 2.1 	sk  02/26/15 Modified the code for MISRA-C:2012 compliance.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xscuwdt.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +/****************************************************************************/ +/** +* +* Run a self-test on the WDT. This test stops the watchdog, writes a value to +* the watchdog load register, starts the watchdog and verifies that the value +* read from the counter register is less that the value written to the load +* register. It then restores the control register and the watchdog load +* register. +* +* @param InstancePtr is a pointer to the XScuWdt instance. +* +* @return +* - XST_SUCCESS if self-test was successful. +* - XST_FAILURE if the WDT is not decrementing. +* +* @note None. +* +******************************************************************************/ +s32 XScuWdt_SelfTest(XScuWdt *InstancePtr) +{ + s32 SelfTestStatus; + u32 Register; + u32 CtrlOrig; + u32 LoadOrig; + + /* + * Assert to ensure the inputs are valid and the instance has been + * initialized. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Stop the watchdog timer. + */ + CtrlOrig = XScuWdt_GetControlReg(InstancePtr); + XScuWdt_SetControlReg(InstancePtr, + CtrlOrig & (u32)(~XSCUWDT_CONTROL_WD_ENABLE_MASK)); + + LoadOrig = XScuWdt_ReadReg((InstancePtr)->Config.BaseAddr, + XSCUWDT_LOAD_OFFSET); + XScuWdt_LoadWdt(InstancePtr, 0xFFFFFFFFU); + + /* + * Start the watchdog timer and check if the watchdog counter is + * decrementing. + */ + XScuWdt_SetControlReg(InstancePtr, + CtrlOrig | (u32)XSCUWDT_CONTROL_WD_ENABLE_MASK); + + Register = XScuWdt_ReadReg((InstancePtr)->Config.BaseAddr, + XSCUWDT_COUNTER_OFFSET); + + XScuWdt_LoadWdt(InstancePtr, LoadOrig); + XScuWdt_SetControlReg(InstancePtr, CtrlOrig); + + if (Register == 0xFFFFFFFFU) { + SelfTestStatus = (s32)XST_FAILURE; + } + else { + SelfTestStatus = (s32)XST_SUCCESS; + } + + return SelfTestStatus; +} +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/scuwdt_v2_1/src/xscuwdt_sinit.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/scuwdt_v2_1/src/xscuwdt_sinit.c new file mode 100644 index 0000000..e311a04 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/scuwdt_v2_1/src/xscuwdt_sinit.c @@ -0,0 +1,92 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xscuwdt_sinit.c +* @addtogroup scuwdt_v2_1 +* @{ +* +* This file contains method for static initialization (compile-time) of the +* driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 1.00a sdm 01/15/10 First release
+* 2.1 	sk  02/26/15 Modified the code for MISRA-C:2012 compliance.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xscuwdt.h" +#include "xparameters.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ +extern XScuWdt_Config XScuWdt_ConfigTable[XPAR_XSCUWDT_NUM_INSTANCES]; + +/*****************************************************************************/ +/** +* Lookup the device configuration based on the unique device ID. The table +* contains the configuration info for each device in the system. +* +* @param DeviceId is the unique device ID of the device being looked up. +* +* @return A pointer to the configuration table entry corresponding to the +* given device ID, or NULL if no match is found. +* +* @note None. +* +******************************************************************************/ +XScuWdt_Config *XScuWdt_LookupConfig(u16 DeviceId) +{ + XScuWdt_Config *CfgPtr = NULL; + u32 Index; + + for (Index = 0U; Index < XPAR_XSCUWDT_NUM_INSTANCES; Index++) { + if (XScuWdt_ConfigTable[Index].DeviceId == DeviceId) { + CfgPtr = &XScuWdt_ConfigTable[Index]; + break; + } + } + + return (XScuWdt_Config *)CfgPtr; +} +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/Makefile b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/Makefile new file mode 100644 index 0000000..186606f --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/Makefile @@ -0,0 +1,83 @@ +############################################################################### +# +# Copyright (C) 2011 - 2015 Xilinx, Inc. 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 +# XILINX 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. +# +# Except as contained in this notice, the name of the Xilinx shall not be used +# in advertising or otherwise to promote the sale, use or other dealings in +# this Software without prior written authorization from Xilinx. +# +############################################################################### + +include config.make + +CC=$(COMPILER) +AR=$(ARCHIVER) +CP=cp +COMPILER_FLAGS= +EXTRA_COMPILER_FLAGS= +LIB=libxil.a + +CC_FLAGS = $(subst -pg, -DPROFILING, $(COMPILER_FLAGS)) +ECC_FLAGS = $(subst -pg, -DPROFILING, $(EXTRA_COMPILER_FLAGS)) + +ifeq (($(notdir $(CC))) , arm-xilinx-eabi-gcc) +ECC_FLAGS += -nostartfiles\ + -march=armv7-a \ + -mfloat-abi=soft \ + -mfpu=neon +endif + +ifeq (($(notdir $(CC))) , $(CC)) +ECC_FLAGS += -nostartfiles +endif + +RELEASEDIR=../../../lib +INCLUDEDIR=../../../include +INCLUDES=-I./. -I${INCLUDEDIR} + +OUTS = *.o +OBJECTS = $(addsuffix .o, $(basename $(wildcard *.c))) +ASSEMBLY_OBJECTS = $(addsuffix .o, $(basename $(wildcard *.S))) +INCLUDEFILES=*.h + +libs: $(LIBS) + +standalone_libs: $(LIBSOURCES) + echo "Compiling standalone" + $(CC) $(CC_FLAGS) $(ECC_FLAGS) $(INCLUDES) $^ + $(AR) -r ${RELEASEDIR}/${LIB} ${OBJECTS} ${ASSEMBLY_OBJECTS} + +profile_libs: + $(MAKE) -C profile COMPILER_FLAGS="$(COMPILER_FLAGS)" EXTRA_COMPILER_FLAGS="$(EXTRA_COMPILER_FLAGS)" COMPILER="$(CC)" ARCHIVER="$(AR)" libs + +.PHONY: include +include: standalone_includes profile_includes + +standalone_includes: + ${CP} ${INCLUDEFILES} ${INCLUDEDIR} + +profile_includes: + $(MAKE) -C profile COMPILER_FLAGS="$(COMPILER_FLAGS)" EXTRA_COMPILER_FLAGS="$(EXTRA_COMPILER_FLAGS)" COMPILER="$(CC)" ARCHIVER="$(AR)" include + +clean: + rm -rf ${OBJECTS} + rm -rf ${ASSEMBLY_OBJECTS} + $(MAKE) -C profile COMPILER_FLAGS="$(COMPILER_FLAGS)" EXTRA_COMPILER_FLAGS="$(EXTRA_COMPILER_FLAGS)" COMPILER="$(CC)" ARCHIVER="$(AR)" clean diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/_exit.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/_exit.c new file mode 100644 index 0000000..87271ae --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/_exit.c @@ -0,0 +1,40 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +#include +#include "xil_types.h" + +/* _exit - Simple implementation. Does not return. +*/ +__attribute__((weak)) void _exit (sint32 status) +{ + (void)status; + while (1) { + ; + } +} diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/_open.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/_open.c new file mode 100644 index 0000000..4ef7441 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/_open.c @@ -0,0 +1,50 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +#ifndef UNDEFINE_FILE_OPS +#include +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { + __attribute__((weak)) s32 _open(const char8 *buf, s32 flags, s32 mode); +} +#endif + +/* + * _open -- open a file descriptor. We don't have a filesystem, so + * we return an error. + */ +__attribute__((weak)) s32 _open(const char8 *buf, s32 flags, s32 mode) +{ + (void)buf; + (void)flags; + (void)mode; + errno = EIO; + return (-1); +} +#endif diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/_sbrk.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/_sbrk.c new file mode 100644 index 0000000..1c39e3a --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/_sbrk.c @@ -0,0 +1,61 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +#include +#include "xil_types.h" + +extern u8 _heap_start[]; +extern u8 _heap_end[]; + +#ifdef __cplusplus +extern "C" { + __attribute__((weak)) caddr_t _sbrk ( s32 incr ); +} +#endif + +__attribute__((weak)) caddr_t _sbrk ( s32 incr ) +{ + static u8 *heap = NULL; + u8 *prev_heap; + static u8 *HeapEndPtr = (u8 *)&_heap_end; + caddr_t Status; + + if (heap == NULL) { + heap = (u8 *)&_heap_start; + } + prev_heap = heap; + + if (((heap + incr) <= HeapEndPtr) && (prev_heap != NULL)) { + heap += incr; + Status = (caddr_t) ((void *)prev_heap); + } else { + Status = (caddr_t) -1; + } + + return Status; +} diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/abort.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/abort.c new file mode 100644 index 0000000..78d3839 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/abort.c @@ -0,0 +1,38 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +#include +#include + +/* + * abort -- go out via exit... + */ +__attribute__((weak)) void abort(void) +{ + _exit(1); +} diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/asm_vectors.S b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/asm_vectors.S new file mode 100644 index 0000000..4fbfa2d --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/asm_vectors.S @@ -0,0 +1,199 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file asm_vectors.s +* +* This file contains the initial vector table for the Cortex A9 processor +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who     Date     Changes
+* ----- ------- -------- ---------------------------------------------------
+* 1.00a ecm/sdm 10/20/09 Initial version
+* 3.05a sdm	02/02/12 Save lr when profiling is enabled
+* 3.10a srt     04/18/13 Implemented ARM Erratas. Please refer to file
+*			 'xil_errata.h' for errata description
+* 4.00a pkp	22/01/14 Modified return addresses for interrupt
+*			 handlers (DataAbortHandler and SVCHandler)
+*			 to fix CR#767251
+* 5.1	pkp	05/13/15 Saved the addresses of instruction causing data
+*			 abort and prefetch abort into DataAbortAddr and
+*			 PrefetchAbortAddr for further use to fix CR#854523
+* 5.4	pkp	12/03/15 Added handler for undefined exception
+* 6.8	mus	04/27/18 Removed __ARM_NEON__ flag definition. Now,
+*			 saving/restoring of of HW floating point register
+*			 would be done through newly introduced flag
+*			 FPU_HARD_FLOAT_ABI_ENABLED. This new flag will be
+*			 configured based on the -mfpu-abi option in extra
+*			 compiler flags.
+* 
+* +* @note +* +* None. +* +******************************************************************************/ +#include "xil_errata.h" +#include "bspconfig.h" + +.org 0 +.text + +.globl _vector_table + +.section .vectors +_vector_table: + B _boot + B Undefined + B SVCHandler + B PrefetchAbortHandler + B DataAbortHandler + NOP /* Placeholder for address exception vector*/ + B IRQHandler + B FIQHandler + + +IRQHandler: /* IRQ vector handler */ + + stmdb sp!,{r0-r3,r12,lr} /* state save from compiled code*/ +#if FPU_HARD_FLOAT_ABI_ENABLED + vpush {d0-d7} + vpush {d16-d31} + vmrs r1, FPSCR + push {r1} + vmrs r1, FPEXC + push {r1} +#endif + +#ifdef PROFILING + ldr r2, =prof_pc + subs r3, lr, #0 + str r3, [r2] +#endif + + bl IRQInterrupt /* IRQ vector */ + +#if FPU_HARD_FLOAT_ABI_ENABLED + pop {r1} + vmsr FPEXC, r1 + pop {r1} + vmsr FPSCR, r1 + vpop {d16-d31} + vpop {d0-d7} +#endif + ldmia sp!,{r0-r3,r12,lr} /* state restore from compiled code */ + + + subs pc, lr, #4 /* adjust return */ + + +FIQHandler: /* FIQ vector handler */ + stmdb sp!,{r0-r3,r12,lr} /* state save from compiled code */ +#if FPU_HARD_FLOAT_ABI_ENABLED + vpush {d0-d7} + vpush {d16-d31} + vmrs r1, FPSCR + push {r1} + vmrs r1, FPEXC + push {r1} +#endif + +FIQLoop: + bl FIQInterrupt /* FIQ vector */ + +#if FPU_HARD_FLOAT_ABI_ENABLED + pop {r1} + vmsr FPEXC, r1 + pop {r1} + vmsr FPSCR, r1 + vpop {d16-d31} + vpop {d0-d7} +#endif + ldmia sp!,{r0-r3,r12,lr} /* state restore from compiled code */ + subs pc, lr, #4 /* adjust return */ + + +Undefined: /* Undefined handler */ + stmdb sp!,{r0-r3,r12,lr} /* state save from compiled code */ + ldr r0, =UndefinedExceptionAddr + sub r1, lr, #4 + str r1, [r0] /* Store address of instruction causing undefined exception */ + + bl UndefinedException /* UndefinedException: call C function here */ + ldmia sp!,{r0-r3,r12,lr} /* state restore from compiled code */ + movs pc, lr + +SVCHandler: /* SWI handler */ + stmdb sp!,{r0-r3,r12,lr} /* state save from compiled code */ + + tst r0, #0x20 /* check the T bit */ + ldrneh r0, [lr,#-2] /* Thumb mode */ + bicne r0, r0, #0xff00 /* Thumb mode */ + ldreq r0, [lr,#-4] /* ARM mode */ + biceq r0, r0, #0xff000000 /* ARM mode */ + + bl SWInterrupt /* SWInterrupt: call C function here */ + + ldmia sp!,{r0-r3,r12,lr} /* state restore from compiled code */ + + movs pc, lr /*return to the next instruction after the SWI instruction */ + + +DataAbortHandler: /* Data Abort handler */ +#ifdef CONFIG_ARM_ERRATA_775420 + dsb +#endif + stmdb sp!,{r0-r3,r12,lr} /* state save from compiled code */ + ldr r0, =DataAbortAddr + sub r1, lr, #8 + str r1, [r0] /* Stores instruction causing data abort */ + + bl DataAbortInterrupt /*DataAbortInterrupt :call C function here */ + + ldmia sp!,{r0-r3,r12,lr} /* state restore from compiled code */ + + subs pc, lr, #8 /* points to the instruction that caused the Data Abort exception */ + +PrefetchAbortHandler: /* Prefetch Abort handler */ +#ifdef CONFIG_ARM_ERRATA_775420 + dsb +#endif + stmdb sp!,{r0-r3,r12,lr} /* state save from compiled code */ + ldr r0, =PrefetchAbortAddr + sub r1, lr, #4 + str r1, [r0] /* Stores instruction causing prefetch abort */ + + bl PrefetchAbortInterrupt /* PrefetchAbortInterrupt: call C function here */ + + ldmia sp!,{r0-r3,r12,lr} /* state restore from compiled code */ + + subs pc, lr, #4 /* points to the instruction that caused the Prefetch Abort exception */ + +.end diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/boot.S b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/boot.S new file mode 100644 index 0000000..c8ebfd1 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/boot.S @@ -0,0 +1,492 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2016 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file boot.S +* +* @addtogroup a9_boot_code Cortex A9 Processor Boot Code +* @{ +*

boot.S

+* The boot code performs minimum configuration which is required for an +* application to run starting from processor's reset state. Below is a +* sequence illustrating what all configuration is performed before control +* reaches to main function. +* +* 1. Program vector table base for exception handling +* 2. Invalidate instruction cache, data cache and TLBs +* 3. Program stack pointer for various modes (IRQ, FIQ, supervisor, undefine, +* abort, system) +* 4. Configure MMU with short descriptor translation table format and program +* base address of translation table +* 5. Enable data cache, instruction cache and MMU +* 6. Enable Floating point unit +* 7. Transfer control to _start which clears BSS sections, initializes +* global timer and runs global constructor before jumping to main +* application +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who     Date     Changes
+* ----- ------- -------- ---------------------------------------------------
+* 1.00a ecm/sdm 10/20/09 Initial version
+* 3.06a sgd     05/15/12 Updated L2CC Auxiliary and Tag RAM Latency control
+*			 register settings.
+* 3.06a asa 	06/17/12 Modified the TTBR settings and L2 Cache auxiliary
+*		         register settings.
+* 3.07a asa     07/16/12 Modified the L2 Cache controller settings to improve
+*			 performance. Changed the property of the ".boot"
+*			 section.
+* 3.07a sgd     08/21/12 Modified the L2 Cache controller and cp15 Aux Control
+*               Register settings
+* 3.09a sgd     02/06/13 Updated SLCR l2c Ram Control register to a
+*               value of 0x00020202. Fix for CR 697094 (SI#687034).
+* 3.10a srt     04/18/13 Implemented ARM Erratas. Please refer to file
+*			 'xil_errata.h' for errata description
+* 4.2   pkp	06/19/14 Enabled asynchronous abort exception
+* 5.0	pkp	16/15/14 Modified initialization code to enable scu after
+*			 MMU is enabled
+* 5.1   pkp	05/13/15 Changed the initialization order so to first invalidate
+*			 caches and TLB, enable MMU and caches, then enable SMP
+*			 bit in ACTLR. L2Cache invalidation and enabling of L2Cache
+*			 is done later.
+* 5.4   asa     12/6/15  Added code to initialize SPSR for all relevant modes.
+* 6.0   mus     08/04/16 Added code to detect zynq-7000 base silicon configuration and
+*                        attempt to enable dual core behavior on single cpu zynq-7000s
+*                        devices is prevented from corrupting system behavior.
+* 6.0   mus     08/24/16 Check CPU core before putting cpu1 to reset for single core
+*                        zynq-7000s devices
+*
+* 
+* +* @note +* +* None. +* +******************************************************************************/ + +#include "xparameters.h" +#include "xil_errata.h" + +.globl MMUTable +.global _prestart +.global _boot +.global __stack +.global __irq_stack +.global __supervisor_stack +.global __abort_stack +.global __fiq_stack +.global __undef_stack +.global _vector_table + +.set PSS_L2CC_BASE_ADDR, 0xF8F02000 +.set PSS_SLCR_BASE_ADDR, 0xF8000000 + +.set RESERVED, 0x0fffff00 +.set TblBase , MMUTable +.set LRemap, 0xFE00000F /* set the base address of the peripheral block as not shared */ +.set L2CCWay, (PSS_L2CC_BASE_ADDR + 0x077C) /*(PSS_L2CC_BASE_ADDR + PSS_L2CC_CACHE_INVLD_WAY_OFFSET)*/ +.set L2CCSync, (PSS_L2CC_BASE_ADDR + 0x0730) /*(PSS_L2CC_BASE_ADDR + PSS_L2CC_CACHE_SYNC_OFFSET)*/ +.set L2CCCrtl, (PSS_L2CC_BASE_ADDR + 0x0100) /*(PSS_L2CC_BASE_ADDR + PSS_L2CC_CNTRL_OFFSET)*/ +.set L2CCAuxCrtl, (PSS_L2CC_BASE_ADDR + 0x0104) /*(PSS_L2CC_BASE_ADDR + XPSS_L2CC_AUX_CNTRL_OFFSET)*/ +.set L2CCTAGLatReg, (PSS_L2CC_BASE_ADDR + 0x0108) /*(PSS_L2CC_BASE_ADDR + XPSS_L2CC_TAG_RAM_CNTRL_OFFSET)*/ +.set L2CCDataLatReg, (PSS_L2CC_BASE_ADDR + 0x010C) /*(PSS_L2CC_BASE_ADDR + XPSS_L2CC_DATA_RAM_CNTRL_OFFSET)*/ +.set L2CCIntClear, (PSS_L2CC_BASE_ADDR + 0x0220) /*(PSS_L2CC_BASE_ADDR + XPSS_L2CC_IAR_OFFSET)*/ +.set L2CCIntRaw, (PSS_L2CC_BASE_ADDR + 0x021C) /*(PSS_L2CC_BASE_ADDR + XPSS_L2CC_ISR_OFFSET)*/ + +.set SLCRlockReg, (PSS_SLCR_BASE_ADDR + 0x04) /*(PSS_SLCR_BASE_ADDR + XPSS_SLCR_LOCK_OFFSET)*/ +.set SLCRUnlockReg, (PSS_SLCR_BASE_ADDR + 0x08) /*(PSS_SLCR_BASE_ADDR + XPSS_SLCR_UNLOCK_OFFSET)*/ +.set SLCRL2cRamReg, (PSS_SLCR_BASE_ADDR + 0xA1C) /*(PSS_SLCR_BASE_ADDR + XPSS_SLCR_L2C_RAM_OFFSET)*/ +.set SLCRCPURSTReg, (0xF8000000 + 0x244) /*(XPS_SYS_CTRL_BASEADDR + A9_CPU_RST_CTRL_OFFSET)*/ +.set EFUSEStaus, (0xF800D000 + 0x10) /*(XPS_EFUSE_BASEADDR + EFUSE_STATUS_OFFSET)*/ + +/* workaround for simulation not working when L1 D and I caches,MMU and L2 cache enabled - DT568997 */ +.if SIM_MODE == 1 +.set CRValMmuCac, 0b00000000000000 /* Disable IDC, and MMU */ +.else +.set CRValMmuCac, 0b01000000000101 /* Enable IDC, and MMU */ +.endif + +.set CRValHiVectorAddr, 0b10000000000000 /* Set the Vector address to high, 0xFFFF0000 */ + +.set L2CCAuxControl, 0x72360000 /* Enable all prefetching, Cache replacement policy, Parity enable, + Event monitor bus enable and Way Size (64 KB) */ +.set L2CCControl, 0x01 /* Enable L2CC */ +.set L2CCTAGLatency, 0x0111 /* latency for TAG RAM */ +.set L2CCDataLatency, 0x0121 /* latency for DATA RAM */ + +.set SLCRlockKey, 0x767B /* SLCR lock key */ +.set SLCRUnlockKey, 0xDF0D /* SLCR unlock key */ +.set SLCRL2cRamConfig, 0x00020202 /* SLCR L2C ram configuration */ + +/* Stack Pointer locations for boot code */ +.set Undef_stack, __undef_stack +.set FIQ_stack, __fiq_stack +.set Abort_stack, __abort_stack +.set SPV_stack, __supervisor_stack +.set IRQ_stack, __irq_stack +.set SYS_stack, __stack + +.set vector_base, _vector_table + +.set FPEXC_EN, 0x40000000 /* FPU enable bit, (1 << 30) */ + +.section .boot,"ax" + + +/* this initializes the various processor modes */ + +_prestart: +_boot: + +#if XPAR_CPU_ID==0 + /* only allow cpu0 through */ + mrc p15,0,r1,c0,c0,5 + and r1, r1, #0xf + cmp r1, #0 + beq CheckEFUSE + EndlessLoop0: + wfe + b EndlessLoop0 + +CheckEFUSE: + ldr r0,=EFUSEStaus + ldr r1,[r0] /* Read eFuse setting */ + ands r1,r1,#0x80 /* Check whether device is having single core */ + beq OKToRun + + /* single core device, reset cpu1 */ + ldr r0,=SLCRUnlockReg /* Load SLCR base address base + unlock register */ + ldr r1,=SLCRUnlockKey /* set unlock key */ + str r1, [r0] /* Unlock SLCR */ + + ldr r0,=SLCRCPURSTReg + ldr r1,[r0] /* Read CPU Software Reset Control register */ + orr r1,r1,#0x22 + str r1,[r0] /* Reset CPU1 */ + + ldr r0,=SLCRlockReg /* Load SLCR base address base + lock register */ + ldr r1,=SLCRlockKey /* set lock key */ + str r1, [r0] /* lock SLCR */ + +#elif XPAR_CPU_ID==1 + /* only allow cpu1 through */ + mrc p15,0,r1,c0,c0,5 + and r1, r1, #0xf + cmp r1, #1 + beq CheckEFUSE1 + b EndlessLoop1 + +CheckEFUSE1: + ldr r0,=EFUSEStaus + ldr r1,[r0] /* Read eFuse setting */ + ands r1,r1,#0x80 /* Check whether device is having single core */ + beq OKToRun + EndlessLoop1: + wfe + b EndlessLoop1 +#endif + +OKToRun: + mrc p15, 0, r0, c0, c0, 0 /* Get the revision */ + and r5, r0, #0x00f00000 + and r6, r0, #0x0000000f + orr r6, r6, r5, lsr #20-4 + +#ifdef CONFIG_ARM_ERRATA_742230 + cmp r6, #0x22 /* only present up to r2p2 */ + mrcle p15, 0, r10, c15, c0, 1 /* read diagnostic register */ + orrle r10, r10, #1 << 4 /* set bit #4 */ + mcrle p15, 0, r10, c15, c0, 1 /* write diagnostic register */ +#endif + +#ifdef CONFIG_ARM_ERRATA_743622 + teq r5, #0x00200000 /* only present in r2p* */ + mrceq p15, 0, r10, c15, c0, 1 /* read diagnostic register */ + orreq r10, r10, #1 << 6 /* set bit #6 */ + mcreq p15, 0, r10, c15, c0, 1 /* write diagnostic register */ +#endif + + /* set VBAR to the _vector_table address in linker script */ + ldr r0, =vector_base + mcr p15, 0, r0, c12, c0, 0 + + /*invalidate scu*/ + ldr r7, =0xf8f0000c + ldr r6, =0xffff + str r6, [r7] + + /* Invalidate caches and TLBs */ + mov r0,#0 /* r0 = 0 */ + mcr p15, 0, r0, c8, c7, 0 /* invalidate TLBs */ + mcr p15, 0, r0, c7, c5, 0 /* invalidate icache */ + mcr p15, 0, r0, c7, c5, 6 /* Invalidate branch predictor array */ + bl invalidate_dcache /* invalidate dcache */ + + /* Disable MMU, if enabled */ + mrc p15, 0, r0, c1, c0, 0 /* read CP15 register 1 */ + bic r0, r0, #0x1 /* clear bit 0 */ + mcr p15, 0, r0, c1, c0, 0 /* write value back */ + +#ifdef SHAREABLE_DDR + /* Mark the entire DDR memory as shareable */ + ldr r3, =0x3ff /* 1024 entries to cover 1G DDR */ + ldr r0, =TblBase /* MMU Table address in memory */ + ldr r2, =0x15de6 /* S=b1 TEX=b101 AP=b11, Domain=b1111, C=b0, B=b1 */ +shareable_loop: + str r2, [r0] /* write the entry to MMU table */ + add r0, r0, #0x4 /* next entry in the table */ + add r2, r2, #0x100000 /* next section */ + subs r3, r3, #1 + bge shareable_loop /* loop till 1G is covered */ +#endif + + mrs r0, cpsr /* get the current PSR */ + mvn r1, #0x1f /* set up the irq stack pointer */ + and r2, r1, r0 + orr r2, r2, #0x12 /* IRQ mode */ + msr cpsr, r2 + ldr r13,=IRQ_stack /* IRQ stack pointer */ + bic r2, r2, #(0x1 << 9) /* Set EE bit to little-endian */ + msr spsr_fsxc,r2 + + mrs r0, cpsr /* get the current PSR */ + mvn r1, #0x1f /* set up the supervisor stack pointer */ + and r2, r1, r0 + orr r2, r2, #0x13 /* supervisor mode */ + msr cpsr, r2 + ldr r13,=SPV_stack /* Supervisor stack pointer */ + bic r2, r2, #(0x1 << 9) /* Set EE bit to little-endian */ + msr spsr_fsxc,r2 + + mrs r0, cpsr /* get the current PSR */ + mvn r1, #0x1f /* set up the Abort stack pointer */ + and r2, r1, r0 + orr r2, r2, #0x17 /* Abort mode */ + msr cpsr, r2 + ldr r13,=Abort_stack /* Abort stack pointer */ + bic r2, r2, #(0x1 << 9) /* Set EE bit to little-endian */ + msr spsr_fsxc,r2 + + mrs r0, cpsr /* get the current PSR */ + mvn r1, #0x1f /* set up the FIQ stack pointer */ + and r2, r1, r0 + orr r2, r2, #0x11 /* FIQ mode */ + msr cpsr, r2 + ldr r13,=FIQ_stack /* FIQ stack pointer */ + bic r2, r2, #(0x1 << 9) /* Set EE bit to little-endian */ + msr spsr_fsxc,r2 + + mrs r0, cpsr /* get the current PSR */ + mvn r1, #0x1f /* set up the Undefine stack pointer */ + and r2, r1, r0 + orr r2, r2, #0x1b /* Undefine mode */ + msr cpsr, r2 + ldr r13,=Undef_stack /* Undefine stack pointer */ + bic r2, r2, #(0x1 << 9) /* Set EE bit to little-endian */ + msr spsr_fsxc,r2 + + mrs r0, cpsr /* get the current PSR */ + mvn r1, #0x1f /* set up the system stack pointer */ + and r2, r1, r0 + orr r2, r2, #0x1F /* SYS mode */ + msr cpsr, r2 + ldr r13,=SYS_stack /* SYS stack pointer */ + + /*set scu enable bit in scu*/ + ldr r7, =0xf8f00000 + ldr r0, [r7] + orr r0, r0, #0x1 + str r0, [r7] + + /* enable MMU and cache */ + + ldr r0,=TblBase /* Load MMU translation table base */ + orr r0, r0, #0x5B /* Outer-cacheable, WB */ + mcr 15, 0, r0, c2, c0, 0 /* TTB0 */ + + mvn r0,#0 /* Load MMU domains -- all ones=manager */ + mcr p15,0,r0,c3,c0,0 + + /* Enable mmu, icahce and dcache */ + ldr r0,=CRValMmuCac + mcr p15,0,r0,c1,c0,0 /* Enable cache and MMU */ + dsb /* dsb allow the MMU to start up */ + isb /* isb flush prefetch buffer */ + + /* Write to ACTLR */ + mrc p15, 0, r0, c1, c0, 1 /* Read ACTLR*/ + orr r0, r0, #(0x01 << 6) /* set SMP bit */ + orr r0, r0, #(0x01 ) /* Cache/TLB maintenance broadcast */ + mcr p15, 0, r0, c1, c0, 1 /* Write ACTLR*/ + +/* Invalidate L2 Cache and enable L2 Cache*/ +/* For AMP, assume running on CPU1. Don't initialize L2 Cache (up to Linux) */ +#if USE_AMP!=1 + ldr r0,=L2CCCrtl /* Load L2CC base address base + control register */ + mov r1, #0 /* force the disable bit */ + str r1, [r0] /* disable the L2 Caches */ + + ldr r0,=L2CCAuxCrtl /* Load L2CC base address base + Aux control register */ + ldr r1,[r0] /* read the register */ + ldr r2,=L2CCAuxControl /* set the default bits */ + orr r1,r1,r2 + str r1, [r0] /* store the Aux Control Register */ + + ldr r0,=L2CCTAGLatReg /* Load L2CC base address base + TAG Latency address */ + ldr r1,=L2CCTAGLatency /* set the latencies for the TAG*/ + str r1, [r0] /* store the TAG Latency register Register */ + + ldr r0,=L2CCDataLatReg /* Load L2CC base address base + Data Latency address */ + ldr r1,=L2CCDataLatency /* set the latencies for the Data*/ + str r1, [r0] /* store the Data Latency register Register */ + + ldr r0,=L2CCWay /* Load L2CC base address base + way register*/ + ldr r2, =0xFFFF + str r2, [r0] /* force invalidate */ + + ldr r0,=L2CCSync /* need to poll 0x730, PSS_L2CC_CACHE_SYNC_OFFSET */ + /* Load L2CC base address base + sync register*/ + /* poll for completion */ +Sync: ldr r1, [r0] + cmp r1, #0 + bne Sync + + ldr r0,=L2CCIntRaw /* clear pending interrupts */ + ldr r1,[r0] + ldr r0,=L2CCIntClear + str r1,[r0] + + ldr r0,=SLCRUnlockReg /* Load SLCR base address base + unlock register */ + ldr r1,=SLCRUnlockKey /* set unlock key */ + str r1, [r0] /* Unlock SLCR */ + + ldr r0,=SLCRL2cRamReg /* Load SLCR base address base + l2c Ram Control register */ + ldr r1,=SLCRL2cRamConfig /* set the configuration value */ + str r1, [r0] /* store the L2c Ram Control Register */ + + ldr r0,=SLCRlockReg /* Load SLCR base address base + lock register */ + ldr r1,=SLCRlockKey /* set lock key */ + str r1, [r0] /* lock SLCR */ + + ldr r0,=L2CCCrtl /* Load L2CC base address base + control register */ + ldr r1,[r0] /* read the register */ + mov r2, #L2CCControl /* set the enable bit */ + orr r1,r1,r2 + str r1, [r0] /* enable the L2 Caches */ +#endif + + mov r0, r0 + mrc p15, 0, r1, c1, c0, 2 /* read cp access control register (CACR) into r1 */ + orr r1, r1, #(0xf << 20) /* enable full access for p10 & p11 */ + mcr p15, 0, r1, c1, c0, 2 /* write back into CACR */ + + /* enable vfp */ + fmrx r1, FPEXC /* read the exception register */ + orr r1,r1, #FPEXC_EN /* set VFP enable bit, leave the others in orig state */ + fmxr FPEXC, r1 /* write back the exception register */ + + mrc p15,0,r0,c1,c0,0 /* flow prediction enable */ + orr r0, r0, #(0x01 << 11) /* #0x8000 */ + mcr p15,0,r0,c1,c0,0 + + mrc p15,0,r0,c1,c0,1 /* read Auxiliary Control Register */ + orr r0, r0, #(0x1 << 2) /* enable Dside prefetch */ + orr r0, r0, #(0x1 << 1) /* enable L2 Prefetch hint */ + mcr p15,0,r0,c1,c0,1 /* write Auxiliary Control Register */ + + mrs r0, cpsr /* get the current PSR */ + bic r0, r0, #0x100 /* enable asynchronous abort exception */ + msr cpsr_xsf, r0 + + + b _start /* jump to C startup code */ + and r0, r0, r0 /* no op */ + +.Ldone: b .Ldone /* Paranoia: we should never get here */ + + +/* + ************************************************************************* + * + * invalidate_dcache - invalidate the entire d-cache by set/way + * + * Note: for Cortex-A9, there is no cp instruction for invalidating + * the whole D-cache. Need to invalidate each line. + * + ************************************************************************* + */ +invalidate_dcache: + mrc p15, 1, r0, c0, c0, 1 /* read CLIDR */ + ands r3, r0, #0x7000000 + mov r3, r3, lsr #23 /* cache level value (naturally aligned) */ + beq finished + mov r10, #0 /* start with level 0 */ +loop1: + add r2, r10, r10, lsr #1 /* work out 3xcachelevel */ + mov r1, r0, lsr r2 /* bottom 3 bits are the Cache type for this level */ + and r1, r1, #7 /* get those 3 bits alone */ + cmp r1, #2 + blt skip /* no cache or only instruction cache at this level */ + mcr p15, 2, r10, c0, c0, 0 /* write the Cache Size selection register */ + isb /* isb to sync the change to the CacheSizeID reg */ + mrc p15, 1, r1, c0, c0, 0 /* reads current Cache Size ID register */ + and r2, r1, #7 /* extract the line length field */ + add r2, r2, #4 /* add 4 for the line length offset (log2 16 bytes) */ + ldr r4, =0x3ff + ands r4, r4, r1, lsr #3 /* r4 is the max number on the way size (right aligned) */ + clz r5, r4 /* r5 is the bit position of the way size increment */ + ldr r7, =0x7fff + ands r7, r7, r1, lsr #13 /* r7 is the max number of the index size (right aligned) */ +loop2: + mov r9, r4 /* r9 working copy of the max way size (right aligned) */ +loop3: + orr r11, r10, r9, lsl r5 /* factor in the way number and cache number into r11 */ + orr r11, r11, r7, lsl r2 /* factor in the index number */ + mcr p15, 0, r11, c7, c6, 2 /* invalidate by set/way */ + subs r9, r9, #1 /* decrement the way number */ + bge loop3 + subs r7, r7, #1 /* decrement the index */ + bge loop2 +skip: + add r10, r10, #2 /* increment the cache number */ + cmp r3, r10 + bgt loop1 + +finished: + mov r10, #0 /* swith back to cache level 0 */ + mcr p15, 2, r10, c0, c0, 0 /* select current cache level in cssr */ + dsb + isb + + bx lr + +.end +/** +* @} End of "addtogroup a9_boot_code". +*/ \ No newline at end of file diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/bspconfig.h b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/bspconfig.h new file mode 100644 index 0000000..488641c --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/bspconfig.h @@ -0,0 +1,44 @@ + +/******************************************************************* +* +* CAUTION: This file is automatically generated by HSI. +* Version: 2019.1.3 +* DO NOT EDIT. +* +* Copyright (C) 2010-2023 Xilinx, Inc. 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 +*XILINX 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. +* +*Except as contained in this notice, the name of the Xilinx shall not be used +*in advertising or otherwise to promote the sale, use or other dealings in +*this Software without prior written authorization from Xilinx. +* + +* +* Description: Configurations for Standalone BSP +* +*******************************************************************/ + +#ifndef BSPCONFIG_H /* prevent circular inclusions */ +#define BSPCONFIG_H /* by using protection macros */ + +#define MICROBLAZE_PVR_NONE + +/* Definition for hard-float ABI */ +#define FPU_HARD_FLOAT_ABI_ENABLED 1 + +#endif /*end of __BSPCONFIG_H_*/ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/changelog.txt b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/changelog.txt new file mode 100644 index 0000000..cdefb9f --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/changelog.txt @@ -0,0 +1,593 @@ +/***************************************************************************** + * MODIFICATION HISTORY: + * + * Ver Who Date Changes + * ----- ---- -------- --------------------------------------------------- + * 3.02a sdm 05/30/11 Added Xuint64 typedef and XUINT64_MSW/XUINT64_LSW macros + * 3.02a sdm 06/27/11 Added INST_SYNC and DATA_SYNC macros for all the CPUs + * 3.02a sdm 07/07/11 Updated ppc440 boot.S to set guarded bit for all but + * cacheable regions + * Update ppc440/xil_cache.c to use CACHEABLE_REGION_MASK + * generated by the cpu driver, for enabling caches + * 3.02a sdm 07/08/11 Updated microblaze cache flush APIs based on write-back/ + * write-thru caches + * 3.03a sdm 08/20/11 Updated the tag/data RAM latency values for L2CC + * Updated the MMU table to mark OCM in high address space + * as inner cacheable and reserved space as Invalid + * 3.03a sdm 08/20/11 Changes to support FreeRTOS + * Updated the MMU table to mark upper half of the DDR as + * non-cacheable + * Setup supervisor and abort mode stacks + * Do not initialize/enable L2CC in case of AMP + * Initialize UART1 for 9600bps in case of AMP + * 3.03a sdm 08/27/11 Setup abort and supervisor mode stacks and don't init SMC + * in case of AMP + * 3.03a sdm 09/14/11 Added code for performance monitor and L2CC event + * counters + * 3.03a sdm 11/08/11 Updated microblaze xil_cache.h file to include + * xparameters.h file for CR630532 - Xil_DCacheFlush()/ + * Xil_DCacheFlushRange() functions in standalone BSP v3_02a + * for MicroBlaze will invalidate data in the cache instead + * of flushing it for writeback caches + * 3.04a sdm 11/21/11 Updated to initialize stdio device for 115200bps, for PS7 + * 3.04a sdm 01/02/12 Updated to clear cp15 regs with unknown reset values + * Remove redundant dsb/dmb instructions in cache maintenance + * APIs + * Remove redundant dsb in mcr instruction + * 3.04a sdm 01/13/12 Updated MMU table to mark DDR memory as Shareable + * 3.05a sdm 02/02/12 Removed some of the defines as they are being generated through + * driver tcl in xparameters.h. Update the gcc/translationtable.s + * for the QSPI complete address range - DT644567 + * Removed profile directory for armcc compiler and changed + * profiling setting to false in standalone_v2_1_0.tcl file + * Deleting boot.S file after preprocessing for armcc compiler + * 3.05a asa 03/11/12 Updated the function Xil_EnableMMU in file xil_mmu.c to + * invalidate the caches before enabling back the MMU and + * D cache. + * 3.05a asa 04/15/12 Updated the function Xil_SetTlbAttributes in file + * xil_mmu.c. Now we invalidate UTLB, Branch predictor + * array, flush the D-cache before changing the attributes + * in translation table. The user need not call Xil_DisableMMU + * before calling Xil_SetTlbAttributes. + * 3.06a asa/ 06/17/12 Removed the UART initialization for Zynq. For PEEP, the UART + * sgd initialization is present. Changes for this were done in + * uart.c and xil-crt0.s. + * Made changes in xil_io.c to use volatile pointers. + * Made changes in xil_mmu.c to correct the function + * Xil_SetTlbAttributes. + * Changes are made xil-crt0.s to initialize the static + * C++ constructors. + * Changes are made in boot.s, to fix the TTBR settings, + * correct the L2 Cache Auxiliary register settings, L2 cache + * latency settings. + * 3.07a asa/ 07/16/12 Made changes in cortexa9/xtime_l.c, xtime_l.h, sleep.c + * sgd usleep.c to use global timer intstead of CP15. + * Made changes in cortexa9/gcc/translation_table.s to map + * the peripheral devices as shareable device memory. + * Made changes in cortexa9/gcc/xil-crt0.s to initialize + * the global timer. + * Made changes in cortexa9/armcc/boot.S to initialize + * the global timer. + * Made changes in cortexa9/armcc/translation_table.s to + * map the peripheral devices as shareable device memory. + * Made changes in cortexa9/gcc/boot.S to optimize the + * L2 cache settings. Changes the section properties for + * ".mmu_tbl" and ".boot" sections in cortexa9/gcc/boot.S + * and cortexa9/gcc/translation_table.S. + * Made changes in cortexa9/xil_cache.c to change the + * cache invalidation order. + * 3.07a asa 08/17/12 Made changes across files for Cortexa9 to remove + * compilation/linking issues for C++ compiler. + * Made changes in mb_interface.h to remove compilation/ + * linking issues for C++ compiler. + * Added macros for swapb and swaph microblaze instructions + * mb_interface.h + * Remove barrier usage (SYNCHRONIZE_IO) from xil_io.c + * for CortexA9. + * 3.07a asa 08/30/12 Updated for CR 675636 to provide the L2 Base Address + * 3.07a asa 08/31/12 Added xil_printf.h include + * 3.07a sgd 09/18/12 Corrected the L2 cache enable settings + * Corrected L2 cache sequence disable sequence + * 3.07a sgd 10/19/12 SMC NOR and SRAM initialization with compiler option + * 3.09a asa 01/25/13 Updated to push and pop neon registers into stack for + * irq/fiq handling. + * Relocated COUNTS_PER_SECOND from sleep.c to xtime_l.h. This + * fixes the CR #692094. + * 3.09a sgd 02/14/13 Fix for CRs 697094 (SI#687034) and 675552. + * 3.10a srt 04/18/13 Implemented ARM Erratas. + * Cortex A9 Errata - 742230, 743622, 775420, 794073 + * L2Cache PL310 Errata - 588369, 727915, 759370 + * Please refer to file 'xil_errata.h' for errata + * description. + * 3.10a asa 05/04/13 Added support for L2 cache in MicroBlaze BSP. The older + * cache APIs were corresponding to only Layer 1 cache + * memories. New APIs were now added and the existing cache + * related APIs were changed to provide a uniform interface + * to flush/invalidate/enable/disable the complete cache + * system which includes both L1 and L2 caches. The changes + * for these were done in: + * src/microblaze/xil_cache.c and src/microblaze/xil_cache.h + * files. + * Four new files were added for supporting L2 cache. They are: + * microblaze_flush_cache_ext.S-> Flushes L2 cache + * microblaze_flush_cache_ext_range.S -> Flushes a range of + * memory in L2 cache. + * microblaze_invalidate_cache_ext.S-> Invalidates L2 cache + * microblaze_invalidate_cache_ext_range -> Invalidates a + * range of memory in L2 cache. + * These changes are done to implement PR #697214. + * 3.10a asa 05/13/13 Modified cache disable APIs at src/cortexa9/xil_cache.c to + * fix the CR #706464. L2 cache disabling happens independent + * of L1 data cache disable operation. Changes are done in the + * same file in cache handling APIs to do a L2 cache sync + * (poll reg7_?cache_?sync). This fixes CR #700542. + * 3.10a asa 05/20/13 Added API/Macros for enabling and disabling nested + * interrupts for ARM. These are done to fix the CR#699680. + * 3.10a srt 05/20/13 Made changes in cache maintenance APIs to do a proper cach + * sync operation. This fixes the CR# 716781. + * 3.11a asa 09/07/13 Updated armcc specific BSP files to have proper support + * for armcc toolchain. + * Modified asm_vectors.S (gcc) and asm_vectors.s (armcc) to + * fix issues related to NEON context saving. The assembly + * routines for IRQ and FIQ handling are modified. + * Deprecated the older BSP (3.10a). + * 3.11a asa 09/22/13 Fix for CR#732704. Cache APIs are modified to avoid + * various potential issues. Made changes in the function + * Xil_SetAttributes in file xil_mmu.c. + * 3.11a asa 09/23/13 Added files xil_misc_psreset_api.c and xil_misc_psreset_api.h + * in src\cortexa9 and src\microblaze folders. + * 3.11a asa 09/28/13 Modified the cache APIs (src\cortexa9) to fix handling of + * L2 cache sync operation and to fix issues around complete + * L2 cache flush/invalidation by ways. + * 3.12a asa 10/22/13 Modified the files xpseudo_asm_rvct.c and xpseudo_asm_rvct.h + * to fix linking issues with armcc/DS-5. Modified the armcc + * makefile to fix issues. + * 3.12a asa 11/15/13 Fix for CR#754800. It fixes issues around profiling for MB. + * 4.0 hk 12/13/13 Added check for STDOUT_BASEADDRESS where outbyte is used. + * 4.0 pkp 22/01/14 Modified return addresses for interrupt handlers (DataAbortHandler + * and SWIHandler) in asm_vector.S (src\cortexa9\gcc\ and + * src\cortexa9\armcc\) to fix CR#767251 + * 4.0 pkp 24/01/14 Modified cache APIs (Xil_DCacheInvalidateRange and + * Xil_L1DCacheInvalidate) in xil_cache.c (src\cortexa9) to fix the bugs. + * Few cache lines were missed to invalidate when unaligned address + * invalidation was accommodated in Xil_DCacheInvalidateRange. + * In Xil_L1DCacheInvalidate, while invalidating all L1D cache + * stack memory (which contains return address) was invalidated. So + * stack memory is flushed first and then L1D cache is invalidated. + * This is done to fix CR #763829 + * 4.0 adk 22/02/2014 Fixed the CR:775379 removed unnecessay _t(unit32_t etc) from + * mblaze_nt_types.h file and replace uint32_t with u32 in the + * profile_hist.c to fix the above CR. + * 4.1 bss 04/14/14 Updated driver tcl to remove _interrupt_handler.o from libgloss.a + * instead of libxil.a and added prototypes for + * microblaze_invalidate_cache_ext and microblaze_flush_cache_ext in + * mb_interface.h + * 4.1 hk 04/18/14 Add sleep function. + * 4.1 asa 04/21/14 Fix for CR#764881. Added support for msrset and msrclr. Renamed + * some of the *.s files inMB BSP source to *.S. + * 4.1 asa 04/28/14 Fix for CR#772280. Made changes in file cortexa9/gcc/read.c. + * 4.1 bss 04/29/14 Modified driver tcl to use libxil.a if libgloss.a does not exist + * CR#794205 + * 4.1 asa 05/09/14 Fix for CR#798230. Made changes in cortexa9/xil_cache.c and + * common/xil_testcache.c + * Fix for CR#764881. + * 4.1 srt 06/27/14 Remove '#undef DEBUG' from src/common/xdebug.h, which allows to + * output the DEBUG logs when -DDEBUG flag is enabled in BSP. + * 4.2 pkp 06/27/14 Added support for IAR compiler in src/cortexa9/iccarm. + * Also added explanatory notes in cortexa9/xil_cache.c for CR#785243. + * 4.2 pkp 06/19/14 Asynchronous abort has been enabled into cortexa9/gcc/boot.s and + * cortexa9/armcc/boot.s. Added default exception handlers for data + * abort and prefetch abort using handlers called + * DataAbortHandler and PrefetchAbortHandler respectively in + * cortexa9/xil_exception.c to fix CR#802862. + * 4.2 pkp 06/30/14 MakeFile for cortexa9/armcc has been changed to fixes the + * issue of improper linking of translation_table.s + * 4.2 pkp 07/04/14 added weak attribute for the function in BSP which are also present + * in tool chain to avoid conflicts into some special cases + * 4.2 pkp 07/21/14 Corrected reset value of event counter in function + * Xpm_ResetEventCounters in src/cortexa9/xpm_counter.c to fix CR#796275 + * 4.2 pkp 07/21/14 Included xil_types.h file in xil_mmu.h which had contained a function + * containing type def u32 defined in xil_types.g to resolve issue of + * CR#805869 + * 4.2 pkp 08/04/14 Removed unimplemented nanosleep routine from cortexa9/usleep.c as + * it is not possible to generate timer in nanosecond due to limited + * cpu frequency + * 4.2 pkp 08/04/14 Removed PEEP board related code which contained initialization of + * uart, smc nor and sram from cortexa9/gcc/xil-crt0.s and armcc/boot.s + * and iccarm/boot.s. Also uart.c and smc.c have been removed. Also + * removed function definition of XSmc_NorInit and XSmc_NorInit from + * cortexa9/smc.h + * 4.2 bss 08/11/14 Added microblaze_flush_cache_ext_range and microblaze_invalidate_ + * cache_ext_range declarations in mb_interface.h CR#783821. + * Modified profile_mcount_mb.S to fix CR#808412. + * 4.2 pkp 08/21/14 modified makefile of iccarm for proper linking of objectfiles in + * cortexa9/iccarm to fix CR#816701 + * 4.2 pkp 09/02/14 modified translation table entries in cortexa9/gcc/translation_table.s, + * armcc/translation_table.s and iccarm/translation_table.s + * to properly defined reserved entries according to address map for + * fixing CR#820146 + * 4.2 pkp 09/11/14 modified translation table entries in cortexa9/iccarm/translation_table.s + * and cortexa9/armcc/translation_table.s to resolve compilation + * error for solving CR#822897 + * 5.0 kvn 12/9/14 Support for Zync Ultrascale Mp.Also modified code for + * MISRA-C:2012 compliance. + * 5.0 pkp 12/15/14 Added APIs to get information about the platforms running the code by + * adding src/common/xplatform_info.*s + * 5.0 pkp 16/12/14 Modified boot code to enable scu after MMU is enabled and + * removed incorrect initialization of TLB lockdown register to fix + * CR#830580 in cortexa9/gcc/boot.S & cpu_init.S, armcc/boot.S + * and iccarm/boot.s + * 5.0 pkp 25/02/15 Modified floating point flag to vfpv3 from vfpv3_d16 in BSP MakeFile + * for iccarm and armcc compiler of cortexA9 + * 5.1 pkp 05/13/15 Changed the initialization order in cortexa9/gcc/boot.S, iccarm/boot.s + * and armcc/boot.s so to first invalidate caches and TLB, enable MMU and + * caches, then enable SMP bit in ACTLR. L2Cache invalidation and enabling + * of L2Cache is done later. + * 5.1 pkp 12/05/15 Modified cortexa9/xil_cache.c to modify Xil_DCacheInvalidateRange and + * Xil_DCacheFlushRange to remove unnecessary dsb which is unnecessarily + * taking long time to fix CR#853097. L2CacheSync is added into + * Xil_L2CacheInvalidateRange API. Xil_L1DCacheInvalidate and + * Xil_L2CacheInvalidate APIs are modified to flush the complete stack + * instead of just System Stack + * 5.1 pkp 14/05/15 Modified cortexa9/gcc/Makefile to keep a correct check of a compiler + * to update ECC_FLAGS and also take the compiler and archiver as specified + * in settings instead of hardcoding it. + * 5.2 pkp 06/08/15 Modified cortexa9/gcc/translation_table.S to put a check for + * XPAR_PS7_DDR_0_S_AXI_BASEADDR to confirm if DDR is present or not and + * accordingly generate the translation table + * 5.2 pkp 23/07/15 Modified cortexa9/gcc/Makefile to keep a correct check of a compiler + * to update ECC_FLAGS to fix a bug introduced during new version creation + * of BSP. + * 5.3 pkp 10/07/15 Modified cortexa9/xil_cache.c file to change cache API so that L2 Cache + * functionalities are avoided for the OpenAMP slave application(when + * USE_AMP flag is defined for BSP) as master CPU would be utilizing L2 + * cache for its operation. Also file operations such as read, write, + * close, open are also avoided for OpenAMP support(when USE_AMP flag is + * defined for BSP) because XilOpenAMP library contains own file operation. + * The xil-crt0.S file is modified for not initializing global timer for + * OpenAMP application as it might be already in use by master CPU + * 5.3 pkp 10/09/15 Modified cortexa9/iccarm/xpseudo_asm_iccarm.h file to change function + * definition for dsb, isb and dmb to fix the compilation error when used + * kvn 16/10/15 Encapsulated assembly code into macros for R5 xil_cache file. + * 5.4 pkp 09/11/15 Modified cortexr5/gcc/boot.S to disable ACTLR.DBWR bit to avoid potential + * R5 deadlock for errata 780125 + * 5.4 pkp 09/11/15 Modified cortexa53/32bit/gcc/boot.S to enable I-Cache and D-Cache for a53 + * 32 bit BSP in the initialization + * 5.4 pkp 09/11/15 Modified cortexa9/xil_misc_psreset_api.c file to change the description + * for XOcm_Remap function + * 5.4 pkp 16/11/15 Modified microblaze/xil_misc_psreset_api.c file to change the description + * for XOcm_Remap function + * kvn 21/11/15 Added volatile keyword for ADDR varibles in Xil_Out API + * kvn 21/11/15 Changed ADDR variable type from u32 to UINTPTR. This is + * required for MISRA-C:2012 Compliance. + * 5.4 pkp 23/11/15 Added attribute definitions for Xil_SetTlbAttributes API of Cortex-A9 + * in cortexa9/xil_mmu.h + * 5.4 pkp 23/11/15 Added default undefined exception handler for Cortex-A9 + * 5.4 pkp 11/12/15 Modified common/xplatform_info.h to add #defines for silicon for + * checking the current executing platform + * 5.4 pkp 18/12/15 Modified cortexa53/32bit/gcc/xil-crt0.S and 64bit/gcc/xil-crt0.S + * to initialize global constructor for C++ applications + * 5.4 pkp 18/12/15 Modified cortexr5/gcc/xil-crt0.S to initialize global constructor for + * C++ applications + * 5.4 pkp 18/12/15 Modified cortexa53/32bit/gcc/translation_table.S and 64bit/gcc/ + * translation_table.S to update the translation table according to proper + * address map + * 5.4 pkp 18/12/15 Modified cortexar5/mpu.c to initialize the MPU according to proper + * address map + * 5.4 pkp 05/01/16 Modified cortexa53/64bit/boot.S to set the reset vector register RVBAR + * equivalent to vector table base address + * 5.4 pkp 08/01/16 Modified cortexa9/gcc/Makefile to update the extra compiler flag + * as per the toolchain update + * 5.4 pkp 12/01/16 Changed common/xplatform_info.* to add platform information support + * for Cortex-A53 32bit mode + * 5.4 pkp 28/01/16 Modified cortexa53/32bit/sleep.c and usleep.c & cortexa53/64bit/sleep.c + * and usleep.c to correct routines to avoid hardcoding the timer frequency, + * instead take it from xparameters.h to properly configure the timestamp + * clock frequency + * 5.4 asa 29/01/16 Modified microblaze/mb_interface.h to add macros that support the + * new instructions for MB address extension feature + * 5.4 kvn 30/01/16 Modified xparameters_ps.h file to add interrupt ID number for + * system monitor. + * 5.4 pkp 04/02/16 Modified cortexr5/gcc/boot.S to enable fault log for lock-step mode + * 5.4 pkp 19/02/16 Modified cortexr5/xtime_l.c to add an API XTime_StartTimer and updated + * cortexr5/xil-crt0.S to configure the TTC3 timer when present. Modified + * cortexr5/sleep.c, cortexr5/usleep.c to use TTC3 when present otherwise + * use set of assembly instructions to provide required delay to fix + * CR#913249. + * 5.4 asa 25/02/16 Made changes in xil-crt0.S for R5, A53 64 and 32 bit BSPs, to replace + * _exit with exit. We should not be directly calling _exit and should + * always use the library exit. This fixes the CR#937036. + * 5.4 pkp 25/02/16 Made change to cortexr5/gcc/boot.S to initialize the floating point + * registers, banked registers for various modes and enabled + * the cache ECC check before enabling the fault log for lock step mode + * Also modified the cortexr5/gcc/Makefile to support floating point + * registers initialization in boot code. + * 5.4 pkp 03/01/16 Updated the exit function in cortexr5/gcc/_exit.c to enable the debug + * logic in case of lock-step mode when fault log is enabled to fix + * CR#938281 + * 5.4 pkp 03/02/16 Modified cortexa9/iccarm/xpseudo_asm_iccarm.h file to include + * header file instrinsics.h which contains assembly instructions + * definitions which can be used by C + * 5.4 asa 03/02/16 Added print.c in MB BSP. Made other cosmetic changes to have uniform + * proto for all print.c across the BSPs. This patch fixes CR#938738. + * 5.4 pkp 03/09/16 Modified cortexr5/sleep.c and usleep.c to avoid disabling the + * interrupts when sleep/usleep is being executed using assembly + * instructions to fix CR#913249. + * 5.4 pkp 03/11/16 Modified cortexr5/xtime_l.c to avoid enabling overflow interrupt, + * instead modified cortexr5/sleep.c and usleep.c to poll the counter + * value and compare it with previous value to detect the overflow + * to fix CR#940209. + * 5.4 pkp 03/24/16 Modified cortexr5/boot.S to reset the dbg_lpd_reset before enabling + * the fault log to avoid intervention for lock-step mode and cortexr5/ + * _exit.c to enable the dbg_lpd_reset once the fault log is disabled + * to fix CR#947335 + * 5.5 pkp 04/11/16 Modified cortexr5/boot.S to enable comparators for non-JTAG bootmode + * in lock-step to avoid resetting the debug logic which restricts the + * access for debugger and removed enabling back of debug modules in + * cortexr5/_exit.c + * 5.5 pkp 04/13/16 Modified cortexa9/gcc/read.c to return correct number of bytes when + * read buffer is filled and removed the redundant NULL checking for + * buffer to simplify the code + * 5.5 pkp 04/13/16 Modified cortexa53/64bit/gcc/read.c and cortexa53/32bit/gcc/read.c + * to return correct number of bytes when read buffer is filled and + * removed the redundant NULL checking for buffer to simplify the code + * 5.5 pkp 04/13/16 Modified cortexr5/gcc/read.c to return correct number of bytes when + * read buffer is filled and removed the redundant NULL checking for + * buffer to simplify the code + * 5.5 pkp 04/13/16 Modified cortexa53/64bit/xpseudo_asm_gcc.h to add volatile to asm + * instruction macros to disable certain optimizations which may move + * code out of loops if optimizers believe that the code will always + * return the same result or discard asm statements if optimizers + * determine there is no need for the output variables + * 5.5 pkp 04/13/16 Modified cortexa53/64bit/xtime_l.c to add XTime_StartTimer which + * starts the timer if it is disabled and modified XTime_GetTime to + * enable the timer if it is not enabled. Also modified cortexa53/64bit/ + * sleep.c and cortexa53/64bit/usleep.c to enable the timer if it is + * disabled and read the counter value directly from register instead + * of using XTime_GetTime for optimization + * 5.5 pkp 04/13/16 Modified cortexa53/32bit/xtime_l.c to add XTime_StartTimer which + * starts the timer if it is disabled and modified XTime_GetTime to + * enable the timer if it is not enabled. Also modified cortexa53/32bit/ + * sleep.c and cortexa53/32bit/usleep.c to enable the timer if it is + * disabled and read the counter value directly from register instead + * of using XTime_GetTime for optimization + * 5.5 pkp 04/13/16 Modified cortexa53/32bit/xil_cache.c and cortexa53/64bit/xil_cache.c + * to update the Xil_DCacheInvalidate, Xil_DCacheInvalidateLine and + * Xil_DCacheInvalidateRange functions description for proper + * explaination to fix CR#949801 + * 5.5 asa 04/20/16 Added missing macros for hibernate and suspend in Microblaze BSP + * file mb_interface.h. This fixes the CR#949503. + * 5.5 asa 04/29/16 Fix for CR#951080. Updated cache APIs for HW designs where cache + * memory is not included for MicroBlaze. + * 5.5 pkp 05/06/16 Modified the cortexa9/xil_exception.h to update the macros + * Xil_EnableNestedInterrupts and Xil_DisableNestedInterrupts for fixing + * the issue of lr being corrupted to resolve CR#950468 + * 5.5 pkp 05/06/16 Modified the cortexr5/xil_exception.h to update the macros + * Xil_EnableNestedInterrupts and Xil_DisableNestedInterrupts for fixing + * the issue of lr being corrupted to resolve CR#950468 + * 6.0 kvn 05/31/16 Make Xil_AsserWait a global variable + * 6.0 pkp 06/27/16 Updated cortexr5/mpu.c to move the code related to Init_MPU to .boot + * section since it is part of boot process to fix CR#949555 + * hk 07/12/16 Correct masks for IOU SLCR GEM registers + * 6.0 pkp 07/25/16 Program the counter frequency in boot code for CortexA53 + * 6.0 asa 08/03/16 Updated sleep_common function in microblaze_sleep.c to improve the + * the accuracy of MB sleep functionality. This fixes the CR#954191. + * 6.0 mus 08/03/16 Restructured the BSP to avoid code duplication across all BSPs. + * Source code directories specific to ARM processor's are moved to src/arm + * directory(i.e. src/cortexa53,src/cortexa9 and src/cortexr5 moved to src/arm/cortexa53, + * src/arm/cortexa9 and src/arm/cortexr5 respectively).Files xil_printf.c,xil_printf.h, + * print.c,xil_io.c and xil_io.h are consolidated across all BSPs into common file each and + * consolidated files are kept at src/common directory.Files putnum.c,vectors.c,vectors.h, + * xil_exception.c and xil_exception.h are consolidated across all ARM BSPs + * into common file each and consolidated files are kept at src/arm/common directory. + * GCC source files related to file operations are consolidated and kept + * at src/arm/common/gcc directory. + * All io interfacing functions (i.e. All variants of xil_out, xil_in ) + * are made as static inline and implementation is kept in consolidated common/xil_io.h, + * xil_io.h must be included as a header file to access io interfacing functions. + * Added undefined exception handler for A53 32 bit and R5 processor + * 6.0 mus 08/11/16 Updated xtime_l.c in R5 BSP to remove implementation of XTime_SetTime API, since + * TTC counter value register is read only. + * 6.0 asa 08/15/16 Modified the signatures for functions sleep and usleep. This fixes + * the CR#956899. + * 6.0 mus 08/18/16 Defined ARMA53_32 flag in cortexa53/32bit/xparameters_ps.h and ARMR5 flag + * in cortexr5/xparameters_ps.h + * 6.0 mus 08/18/16 Added support for the the Zynq 7000s devices + * 6.0 mus 08/18/16 Removed unused variables from xil_printf.c and xplatform_info.c + * 6.0 mus 08/19/16 Modified xil_io.h to remove __LITTLE_ENDIAN__ flag check for all ARM processors + * 6.1 mus 11/03/16 Added APIs handle_stdin_parameter and handle_stdout_parameter in standalone tcl. + * ::hsi::utils::handle_stdin and ::hsi::utils::handle_stdout are taken as a base for + * these APIs and modifications are done on top of it to handle stdout/stdin + * parameters for design which doesnt have UART.It fixes CR#953681 + * 6.1 nsk 11/07/16 Added two new files xil_mem.c and xil_mem.h for xil_memcpy + * 6.2 pkp 12/14/16 Updated cortexa53/64bit/translation_table.S for upper ps DDR. The 0x800000000 - + * 0xFFFFFFFFF range is marked normal memory for the DDR size defined in hdf + * and rest of the memory in that 32GB region is marked as reserved to avoid + * any speculative access + * 6.2 pkp 12/23/16 Added support for floating point operation to Cortex-A53 64bit mode. It modified + * asm_vectors.S to implement lazy floating point context saving i.e. floating point + * access is enabled if there is any floating point operation, it is disabled by + * default. Also FPU is initally disabled for IRQ and none of the floating point + * registers are saved during normal context saving. If IRQ handler does not require + * floating point operation, the floating point registers are untouched and no need + * for saving/restoring. If IRQ handler uses any floating point operation, then floating + * point registers are saved and FPU is enabled for IRQ handler. Then floating point + * registers are restored back after servicing IRQ during normal context restoring. + * 6.2 mus 01/01/17 Updated makefiles of R5 and a53 64 bit/32 bit processors to fix error in clean + * target.It fixes the CR#966900 + * 6.2 pkp 01/22/17 Added support for EL1 non-secure execution and Hypervisor Baremetal for Cortex-A53 + * 64bit Mode. If Hypervisor_guest is selected as true in BSP settings, BSP will be built + * for EL1 Non-secure, else BSP will be built for EL3. By default hypervisor_guest is + * as false i.e. default bsp is EL3. + * 6.2 pkp 01/24/17 Updated cortexa53/64bit/boot.S to clear FPUStatus variable to make sure that it + * contains initial status of FPU i.e. disabled. In case of a warm restart execution + * when bss sections are not cleared, it may contain previously updated value which + * does not hold true once processor resumes. This fixes CR#966826. + * 6.2 asa 01/31/17 The existing Xil_DCacheDisable API first flushes the + * D caches and then disables it. The problem with that is, + * potentially there will be a small window after the cache + * flush operation and before the we disable D caches where + * we might have valid data in cache lines. In such a + * scenario disabling the D cache can lead to unknown behavior. + * The ideal solution to this is to use assembly code for + * the complete API and avoid any memory accesses. But with + * that we will end up having a huge amount on assembly code + * which is not maintainable. Changes are done to use a mix + * of assembly and C code. All local variables are put in + * registers. Also function calls are avoided in the API to + * avoid using stack memory. + * 6.2 mus 02/13/17 A53 CPU cache system can pre-fetch catch lines.So there are + * scenarios when an invalidated cache line can get pre fetched to cache. + * If that happens, the coherency between cache and memory is lost + * resulting in lost data. To avoid this kind of issue either + * user has to use dsb() or disable pre-fetching for L1 cache + * or else reduce maximum number of outstanding data prefetches allowed. + * Using dsb() while comparing data costing more performance compared to + * disabling pre-fetching/reducing maximum number of outstanding data + * prefetches for L1 Cache.The new api Xil_ConfigureL1Prefetch is added + * to disable pre-fetching/configure maximum number of outstanding data + * prefetches allowed in L1 cache system.This fixes CR#967864. + * 6.2 pkp 02/16/17 Added xil_smc.c file to provide a C wrapper for smc calling which can be + * used by cortex-A53 64bit EL1 Non-secure application. + * 6.2 kvn 03/03/17 Added support thumb mode + * 6.2 mus 03/13/17 Fixed MISRA C mandatory standard violations in ARM cortexr5 and cortexa53 BSP. + * It fixes CR#970543 + * 6.2 asa 03/16/17 Fix for CR#970859. For Mcroblaze BSP, when we enable intrusive + * profiling we see a crash. That is because the the tcl uses invalid + * HSI command. This change fixes it. + * 6.2 mus 03/22/17 Updated standalone tcl to generate xparameter XPAR_FPD_IS_CACHE_COHERENT, if + * any FPD peripheral is configured to use CCI.It fixes CR#972638 + * 6.3 mus 03/20/17 Updated cortex-r5 BSP, to add hard floating point support. + * 6.3 mus 04/17/17 Updated Cortex-a53 32 bit BSP boot code to fix bug in + * the HW coherency enablement. It fixes the CR#973287 + * 6.3 mus 04/20/17 Updated Cortex-A53 64 bit BSP boot code, to remove redundant write to the + * L2CTLR_EL1 register. It fixes the CR#974698 + * 6.4 mus 06/08/17 Updated arm/common/xil_exception.c to fix warnings in C level exception handlers + * of ARM 32 bit processor's. + * 6.4 mus 06/14/17 Updated cortexa53/64bit/gcc/asm_vectors.S to fix bug in IRQInterruptHandler code + * snippet, which checks for the FPEN bit of CPACR_EL1 register. + * 6.4 ms 05/23/17 Added PSU_PMU macro in xplatform_info.c, xparameters.h to support + * XGetPSVersion_Info function for PMUFW. + * ms 06/13/17 Added PSU_PMU macro in xplatform_info.c to support XGetPlatform_Info + * function for PMUFW. + * 6.4 mus 07/05/17 Updated Xil_In32BE function in xil_io.h to fix bug.It fixes CR#979740. + * 6.4 mus 07/25/17 Updated a53 32 bit boot code and vectors to support hard floating point + * operations.Now,VFP is being enabled in FPEXC register, through boot code + * and FPU registers are being saved/restored when irq/fiq vector is invoked. + * 6.4 adk 08/01/17 Updated standalone tcl to generate xparameter XPAR_PL_IS_CACHE_COHERENT, + * if h/w design configured with HPC port. + * 6.4 mus 08/10/17 Updated a53 64 bit translation table to mark memory as a outer shareable for + * EL1 NS execution. This change has been done to support CCI enabled IP's. + * 6.4 mus 08/11/17 Updated a53 64 bit boot code to implement ARM erratum 855873.This fixes + * CR#982209. + * 6.4 asa 08/16/17 Made several changes in the R5 MPU handling logic. Added new APIs to + * make RPU MPU handling user-friendly. This also fixes the CR-981028. + * 6.4 mus 08/17/17 Updated XGet_Zynq_UltraMp_Platform_info and XGetPSVersion_Info APIs to read + * version register through SMC call, over EL1 NS mode. This change has been done to + * support these APIs over EL1 NS mode. + * 6.5 mus 10/20/17 Updated standalone.tcl to fix bug in mb_can_handle_exceptions_in_delay_slots proc, + * it fixes CR#987464. + * 6.6 mus 12/07/17 Updated cortexa9/xil_errata.h and cortexa9/xil_cache.c to remove Errata 753970. + * It fixes CR#989132. + * srm 10/18/17 Updated all the sleep routines in a9,a53,R5,microblaze. Now the sleep routines + * will use the timer specified by the user to provide delay. A9 and A53 can use + * Global timer or TTC. R5 can use TTC or the machine cycles. Microblaze can use + * machine cycles or Axi timer. Updated standalone.tcl and standalone.mld files + * to support the sleep configuration Added new API's for the Axi timer in + * microblaze and TTC in ARM. Added two new files, xil_sleeptimer.c and + * xil_sleeptimer.h in ARM for the common sleep routines and 1 new file, + * xil_sleepcommon.c in Standalone-common for sleep/usleep API's. + * 6.6 hk 12/15/17 Export platform macros to bspconfig.h based on the processor. + * 6.6 asa 1/16/18 Ensure C stack information for A9 are flushed out from L1 D cache + * or L2 cache only when the respective caches are enabled. This fixes CR-922023. + * 6.6 mus 01/19/18 Updated asm_vectors.S and boot.S in Cortexa53 64 bit BSP, to add isb + * after writing to cpacr_el1/cptr_el3 registers. It would ensure + * disabling/enabling of floating-point unit, before any subsequent + * instruction. + * 6.6 hk 12/15/17 Export platform macros to xparameters.h based on the processor. + * 6.6 asa 1/16/18 Ensure C stack information for A9 are flushed out from L1 D cache + * or L2 cache only when the respective caches are enabled.This fixes CR-922023. + * + * 6.6 mus 01/19/18 Updated asm_vectors.S and boot.S in Cortexa53 64 bit BSP, to add isb + * after writing to cpacr_el1/cptr_el3 registers. It would ensure + * disabling/enabling of floating-point unit, before any subsequent + * instruction. + * 6.6 mus 01/30/18 Updated hypervisor enabled Cortexa53 64 bit BSP, to add xen PV console + * support. Now, xil_printf would use PV console instead of UART in case of + * hypervisor enabled BSP. + * 6.6 mus 02/02/18 Updated get_connected_if proc in standalone tcl to detect the HPC port + * configured with smart interconnect.It fixes CR#990318. + * 6.6 srm 02/10/18 Updated csu_wdt interrupt to the correct value. Fixes CR#992229 + * 6.6 asa 02/12/18 Fix for heap handling for ARM platforms. CR#993932. + * 6.6 mus 02/19/18 Updated standalone.tcl to fix bug in handle_profile_opbtimer proc, + * CR#995014. + * 6.6 mus 02/23/18 Presently Cortex R5 BSP boot code is disabling the debug logic in + * non-JTAG boot mode, when processor is in lockstep configuration. + * This behavior is restricting application debugging in non-JTAG boot + * mode. To get rid of this restriction, added new mld parameter + * "lockstep_mode_debug", to enable/disable debug logic from BSP + * settings. Now, debug logic can be enabled through BSP settings, + * by modifying value of parameter "lockstep_mode_debug" as "true". + * It fixes CR#993896. + * 6.6.mus 02/27/18 Updated Xil_DCacheInvalidateRange and + * Xil_ICacheInvalidateRange APIs in Cortexa53 64 bit BSP, to fix bug + * in handling upper DDR addresses.It fixes CR#995581. + * 6.6 mus 03/12/18 Updated makefile of Cortexa53 32bit BSP to add includes_ps directory + * in the list of include paths. This change allows applications/BSP + * files to include .h files in include_ps directory. + * 6.6 mus 03/16/18 By default CPUACTLR_EL1 is accessible only from EL3, it + * results into abort if accessed from EL1 non secure privilege + * level. Updated Xil_ConfigureL1Prefetch function in Cortexa53 64 bit BSP + * to avoid CPUACTLR_EL1 access from privile levels other than EL3. + * 6.6 mus 03/16/18 Updated hypervisor enabled BSP to use PV console, based on the + * XEN_USE_PV_CONSOLE flag. By deafault hypervisor enabled BSP would + * use UART console, PV console can be enabled by appending + * "-DXEN_USE_PV_CONSOLE" to the BSP extra compiler flags. + * 6.7 asa 04/26/18 Added API Xil_GetExceptionRegisterHandler for obtaining information + * on an already registered exception vector. + * 6.7 asa 05/18/18 Fixed bugss in the API Xil_GetExceptionRegisterHandler. + * 6.8 mus 04/27/18 Removed __ARM_NEON__ flag definition. Now, saving/restoring of of HW + * floating point register would be done through newly introduced flag + * FPU_HARD_FLOAT_ABI_ENABLED. This new flag will be configured based on + * the -mfpu-abi option in extra compiler flags.. This change has + * been done to avoid saving/restoring of HW floating point registers, + * when BSP is not compiled with HW floating point configuration. + * 6.8 aru 06/15/18 Removed unused variable in xil_cache.c for A53-32. It + * fixes CR1005118. + * 6.8 aru 07/02/18 Returned the pointer instead of address of that pointer in xil_mpu.c + * for R5 processor.It Fixes CR#1005119. + * 6.8 mus 07/12/18 Updated Cortexa9 translation table to mark DDR memory as inner cacheable, + * if BSP is built with the USE_AMP flag. It fixes CR#1006745. + * + * 6.8 aru 07/04/18 Optimized the code to use a loop and to remove redundant code + * in Xil_DCacheFlush() and Xil_DCacheInvalidate() + * of xil_cache.c for A53-32. + * 6.8 aru 07/26/18 added support in xil_printf.c to print u64 variabbles + * correctly in 32 bit processor.It fixes CR#1007207. + * 6.8 aru 09/03/18 Optimized the code to use a single function and removed + * code redundancy in xil_printf.c . It Fixes CR#1009654. + * 6.8 aru 09/06/18 Removed the compiler warnings for ARMCC toolchain. + * It fixes CR#1008309. + * 6.8 mus 09/20/18 Updated CortexR5 boot code to initialize CortexR5 core with LOVEC + * on reset. It fixes CR#1010656. + * 6.8 mus 10/04/18 Updated microblaze sleep functinality to execute default method of + * sleep implementation, incase of FreeRTOS BSP. + * 6.8 mus 10/25/18 Updated assembly code for cache APIs and inline assemby macros to + * to support 64 bit addresses. + * 6.8 asa 10/11/18 Updated the A53 32 bit cache APIs for Xil_DCacheFlush and + * Xil_DCacheInvalidate to fix various issues. These issues were not + * present in the previous releases but got introduced as part of + * optimization patches that got applied for 6.8 BSP version. These + * changes fix the CR#1016012. + * 7.0 rp 10/25/18 Added XST_NO_ACCESS status macros for generic access error. + * 7.0 mus 02/01/19 Added support for Versal. Cortea53 BSP will be re-used by Cortexa72, + * re-named cortexa53 directory as ARMv8, since files are generic for + * ARMv8 based processors. Created "platform" directory to place + * SoC based files. + * 7.0 mus 02/05/19 Updated Xil_MemCpy API to copy two bytes at a time from source to + * destination if byte count is <= 2. + * 7.0 mus 02/28/19 Added armclang complier support to the Cortexa53 64 bit BSP. + * 7.0 mus 04/08/19 Fix microblaze_disable_dcache for 64 bit microblaze + * 7.0 mus 04/26/19 Added frequently used functions in common area in xil_utils.c, + * so that other modules can make use of it. + *****************************************************************************************/ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/close.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/close.c new file mode 100644 index 0000000..64f7f49 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/close.c @@ -0,0 +1,45 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +#ifndef UNDEFINE_FILE_OPS +#include "xil_types.h" +#ifdef __cplusplus +extern "C" { + __attribute__((weak)) s32 _close(s32 fd); +} +#endif + +/* + * close -- We don't need to do anything, but pretend we did. + */ + +__attribute__((weak)) s32 _close(s32 fd) +{ + (void)fd; + return (0); +} +#endif diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/config.make b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/config.make new file mode 100644 index 0000000..2668199 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/config.make @@ -0,0 +1,3 @@ +LIBSOURCES = *.c *.S +PROFILE_ARCH_OBJS = profile_mcount_arm.o +LIBS = standalone_libs diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/cpu_init.S b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/cpu_init.S new file mode 100644 index 0000000..5b597be --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/cpu_init.S @@ -0,0 +1,76 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file cpu_init.s +* +* This file contains CPU specific initialization. Invoked from main CRT +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who     Date     Changes
+* ----- ------- -------- ---------------------------------------------------
+* 1.00a ecm/sdm 10/20/09 Initial version
+* 3.04a sdm	01/02/12 Updated to clear cp15 regs with unknown reset values
+* 5.0   pkp	12/16/14 removed incorrect initialization of TLB lockdown
+*			 register to fix CR#830580
+* 
+* +* @note +* +* None. +* +******************************************************************************/ + + .text + .global __cpu_init + .align 2 +__cpu_init: + +/* Clear cp15 regs with unknown reset values */ + mov r0, #0x0 + mcr p15, 0, r0, c5, c0, 0 /* DFSR */ + mcr p15, 0, r0, c5, c0, 1 /* IFSR */ + mcr p15, 0, r0, c6, c0, 0 /* DFAR */ + mcr p15, 0, r0, c6, c0, 2 /* IFAR */ + mcr p15, 0, r0, c9, c13, 2 /* PMXEVCNTR */ + mcr p15, 0, r0, c13, c0, 2 /* TPIDRURW */ + mcr p15, 0, r0, c13, c0, 3 /* TPIDRURO */ + +/* Reset and start Cycle Counter */ + mov r2, #0x80000000 /* clear overflow */ + mcr p15, 0, r2, c9, c12, 3 + mov r2, #0xd /* D, C, E */ + mcr p15, 0, r2, c9, c12, 0 + mov r2, #0x80000000 /* enable cycle counter */ + mcr p15, 0, r2, c9, c12, 1 + + bx lr + +.end diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/errno.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/errno.c new file mode 100644 index 0000000..3cdb751 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/errno.c @@ -0,0 +1,47 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +/* The errno variable is stored in the reentrancy structure. This + function returns its address for use by the macro errno defined in + errno.h. */ + +#include +#include +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { + __attribute__((weak)) sint32 * __errno (void); +} +#endif + +__attribute__((weak)) sint32 * +__errno (void) +{ + return &_REENT->_errno; +} diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/fcntl.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/fcntl.c new file mode 100644 index 0000000..42c2bff --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/fcntl.c @@ -0,0 +1,42 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +#include +#include "xil_types.h" + +/* + * fcntl -- Manipulate a file descriptor. + * We don't have a filesystem, so we do nothing. + */ +__attribute__((weak)) sint32 fcntl (sint32 fd, sint32 cmd, long arg) +{ + (void)fd; + (void)cmd; + (void)arg; + return 0; +} diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/fstat.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/fstat.c new file mode 100644 index 0000000..92a3ebf --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/fstat.c @@ -0,0 +1,46 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +#include +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { + __attribute__((weak)) s32 _fstat(s32 fd, struct stat *buf); +} +#endif +/* + * fstat -- Since we have no file system, we just return an error. + */ +__attribute__((weak)) s32 _fstat(s32 fd, struct stat *buf) +{ + (void)fd; + buf->st_mode = S_IFCHR; /* Always pretend to be a tty */ + + return (0); +} diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/getpid.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/getpid.c new file mode 100644 index 0000000..36c8769 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/getpid.c @@ -0,0 +1,47 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +#include "xil_types.h" +/* + * getpid -- only one process, so just return 1. + */ +#ifdef __cplusplus +extern "C" { + __attribute__((weak)) s32 _getpid(void); +} +#endif + +__attribute__((weak)) s32 getpid(void) +{ + return 1; +} + +__attribute__((weak)) s32 _getpid(void) +{ + return 1; +} diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/inbyte.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/inbyte.c new file mode 100644 index 0000000..0036459 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/inbyte.c @@ -0,0 +1,14 @@ +#include "xparameters.h" +#include "xuartps_hw.h" + +#ifdef __cplusplus +extern "C" { +#endif +char inbyte(void); +#ifdef __cplusplus +} +#endif + +char inbyte(void) { + return XUartPs_RecvByte(STDIN_BASEADDRESS); +} diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/isatty.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/isatty.c new file mode 100644 index 0000000..d1ef081 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/isatty.c @@ -0,0 +1,52 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +#include +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { + __attribute__((weak)) sint32 _isatty(sint32 fd); +} +#endif + +/* + * isatty -- returns 1 if connected to a terminal device, + * returns 0 if not. Since we're hooked up to a + * serial port, we'll say yes _AND return a 1. + */ +__attribute__((weak)) sint32 isatty(sint32 fd) +{ + (void)fd; + return (1); +} + +__attribute__((weak)) sint32 _isatty(sint32 fd) +{ + (void)fd; + return (1); +} diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/kill.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/kill.c new file mode 100644 index 0000000..22b66a2 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/kill.c @@ -0,0 +1,56 @@ +/****************************************************************************** +* +* Copyright (C) 2014 - 2016 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +#include +#include +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { + __attribute__((weak)) int _kill(pid_t pid, int sig); +} +#endif + +/* + * kill -- go out via exit... + */ + +__attribute__((weak)) int kill(pid_t pid, int sig) +{ + if(pid == 1) { + _exit(sig); + } + return 0; +} + +__attribute__((weak)) int _kill(pid_t pid, int sig) +{ + if(pid == 1) { + _exit(sig); + } + return 0; +} diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/lseek.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/lseek.c new file mode 100644 index 0000000..400d4cc --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/lseek.c @@ -0,0 +1,57 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +#include +#include +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { + __attribute__((weak)) off_t _lseek(s32 fd, off_t offset, s32 whence); +} +#endif +/* + * lseek -- Since a serial port is non-seekable, we return an error. + */ +__attribute__((weak)) off_t lseek(s32 fd, off_t offset, s32 whence) +{ + (void)fd; + (void)offset; + (void)whence; + errno = ESPIPE; + return ((off_t)-1); +} + +__attribute__((weak)) off_t _lseek(s32 fd, off_t offset, s32 whence) +{ + (void)fd; + (void)offset; + (void)whence; + errno = ESPIPE; + return ((off_t)-1); +} diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/open.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/open.c new file mode 100644 index 0000000..4c46b67 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/open.c @@ -0,0 +1,49 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +#ifndef UNDEFINE_FILE_OPS +#include +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { + __attribute__((weak)) s32 open(char8 *buf, s32 flags, s32 mode); +} +#endif +/* + * open -- open a file descriptor. We don't have a filesystem, so + * we return an error. + */ +__attribute__((weak)) s32 open(char8 *buf, s32 flags, s32 mode) +{ + (void)buf; + (void)flags; + (void)mode; + errno = EIO; + return (-1); +} +#endif diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/outbyte.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/outbyte.c new file mode 100644 index 0000000..8b56036 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/outbyte.c @@ -0,0 +1,15 @@ +#include "xparameters.h" +#include "xuartps_hw.h" + +#ifdef __cplusplus +extern "C" { +#endif +void outbyte(char c); + +#ifdef __cplusplus +} +#endif + +void outbyte(char c) { + XUartPs_SendByte(STDOUT_BASEADDRESS, c); +} diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/print.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/print.c new file mode 100644 index 0000000..da7e768 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/print.c @@ -0,0 +1,36 @@ +/* print.c -- print a string on the output device. + * + * Copyright (c) 1995 Cygnus Support + * + * The authors hereby grant permission to use, copy, modify, distribute, + * and license this software and its documentation for any purpose, provided + * that existing copyright notices are retained in all copies and that this + * notice is included verbatim in any distributions. No written agreement, + * license, or royalty fee is required for any of the authorized uses. + * Modifications to this software may be copyrighted by their authors + * and need not follow the licensing terms described here, provided that + * the new terms are clearly indicated on the first page of each file where + * they apply. + * + */ + +/* + * print -- do a raw print of a string + */ +#include "xil_printf.h" + +void print(const char8 *ptr) +{ +#if HYP_GUEST && EL1_NONSECURE && XEN_USE_PV_CONSOLE + XPVXenConsole_Write(ptr); +#else +#ifdef STDOUT_BASEADDRESS + while (*ptr != (char8)0) { + outbyte (*ptr); + ptr++; + } +#else +(void)ptr; +#endif +#endif +} diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/Makefile b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/Makefile new file mode 100644 index 0000000..53a288e --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/Makefile @@ -0,0 +1,74 @@ +############################################################################### +# +# Copyright (C) 2002 - 2014 Xilinx, Inc. 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 +# XILINX 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. +# +# Except as contained in this notice, the name of the Xilinx shall not be used +# in advertising or otherwise to promote the sale, use or other dealings in +# this Software without prior written authorization from Xilinx. +# +############################################################################### +# +# Makefile for profiler +# +####################################################################### + +# PROFILE_ARCH_OBJS - Processor Architecture Dependent files defined here +include ../config.make + +AS=mb-as +COMPILER = mb-gcc +ARCHIVER = mb-ar +CP = cp +COMPILER_FLAGS=-O2 +EXTRA_COMPILER_FLAGS= +LIB = libxil.a +DUMMYLIB = libxilprofile.a + +CC_FLAGS = $(subst -pg, , $(COMPILER_FLAGS)) +ECC_FLAGS = $(subst -pg, , $(EXTRA_COMPILER_FLAGS)) + +RELEASEDIR = ../../../../lib +INCLUDEDIR = ../../../../include +INCLUDES = -I./. -I${INCLUDEDIR} + +OBJS = _profile_init.o _profile_clean.o _profile_timer_hw.o profile_hist.o profile_cg.o +DUMMYOBJ = dummy.o +INCLUDEFILES = profile.h mblaze_nt_types.h _profile_timer_hw.h + +libs : reallibs dummylibs + +reallibs : $(OBJS) $(PROFILE_ARCH_OBJS) + $(ARCHIVER) -r $(RELEASEDIR)/$(LIB) $(OBJS) $(PROFILE_ARCH_OBJS) + +dummylibs : $(DUMMYOBJ) + $(ARCHIVER) -r $(RELEASEDIR)/$(DUMMYLIB) $(DUMMYOBJ) + +%.o:%.c + $(COMPILER) $(CC_FLAGS) $(ECC_FLAGS) -c $< -o $@ $(INCLUDES) + +%.o:%.S + $(COMPILER) $(CC_FLAGS) $(ECC_FLAGS) -c $< -o $@ $(INCLUDES) + +include: + $(CP) -rf $(INCLUDEFILES) $(INCLUDEDIR) + +clean: + rm -f $(OBJS) $(PROFILE_ARCH_OBJS) $(LIB) diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/_profile_clean.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/_profile_clean.c new file mode 100644 index 0000000..b1c61f8 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/_profile_clean.c @@ -0,0 +1,43 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +#include "profile.h" +#include "_profile_timer_hw.h" +#include "xil_exception.h" + +void _profile_clean( void ); + +/* + * This function is the exit routine and is called by the crtinit, when the + * program terminates. The name needs to be changed later.. + */ +void _profile_clean( void ) +{ + Xil_ExceptionDisable(); + disable_timer(); +} diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/_profile_init.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/_profile_init.c new file mode 100644 index 0000000..050b0a7 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/_profile_init.c @@ -0,0 +1,86 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +****************************************************************************** +* +* _program_init.c: +* Initialize the Profiling Structures. +* +******************************************************************************/ + +#include "profile.h" + +/* XMD Initializes the following Global Variables Value during Program + * Download with appropriate values. */ + +#ifdef PROC_MICROBLAZE + +extern s32 microblaze_init(void); + +#elif defined PROC_PPC + +extern s32 powerpc405_init(void); + +#else + +extern s32 cortexa9_init(void); + +#endif + +s32 profile_version = 1; /* Version of S/W Intrusive Profiling library */ + +u32 binsize = (u32)BINSIZE; /* Histogram Bin Size */ +u32 cpu_clk_freq = (u32)CPU_FREQ_HZ ; /* CPU Clock Frequency */ +u32 sample_freq_hz = (u32)SAMPLE_FREQ_HZ ; /* Histogram Sampling Frequency */ +u32 timer_clk_ticks = (u32)TIMER_CLK_TICKS ;/* Timer Clock Ticks for the Timer */ + +/* Structure for Storing the Profiling Data */ +struct gmonparam *_gmonparam = (struct gmonparam *)(0xffffffffU); +s32 n_gmon_sections = 1; + +/* This is the initialization code, which is called from the crtinit. */ + +void _profile_init( void ) +{ +/* print("Gmon Init called....\r\n") */ +/* putnum(n_gmon_sections) , print("\r\n") */ +/* if( _gmonparam == 0xffffffff ) */ +/* printf("Gmonparam is NULL !!\r\n") */ +/* for( i = 0, i < n_gmon_sections, i++ )[ */ +/* putnum( _gmonparam[i].lowpc) , print("\t") */ +/* putnum( _gmonparam[i].highpc) , print("\r\n") */ +/* putnum( _gmonparam[i].textsize ), print("\r\n") */ +/* putnum( _gmonparam[i].kcountsize * sizeof(unsigned short)), print("\r\n") */ +/* ] */ + +#ifdef PROC_MICROBLAZE + (void)microblaze_init(); +#elif defined PROC_PPC + powerpc405_init(); +#else + (void)cortexa9_init(); +#endif +} diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/_profile_timer_hw.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/_profile_timer_hw.c new file mode 100644 index 0000000..c8243e5 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/_profile_timer_hw.c @@ -0,0 +1,383 @@ +/****************************************************************************** +* +* Copyright (C) 2004 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +****************************************************************************** +* +* _program_timer_hw.c: +* Timer related functions +* +******************************************************************************/ + +#include "profile.h" +#include "_profile_timer_hw.h" + +#include "xil_exception.h" + +#ifdef PROC_PPC +#include "xtime_l.h" +#include "xpseudo_asm.h" +#endif + +#ifdef TIMER_CONNECT_INTC +#include "xintc_l.h" +#include "xintc.h" +#endif /* TIMER_CONNECT_INTC */ + +/* #ifndef PPC_PIT_INTERRUPT */ +#if (!defined PPC_PIT_INTERRUPT && !defined PROC_CORTEXA9) +#include "xtmrctr_l.h" +#endif + +/* extern u32 timer_clk_ticks, */ + +#ifdef PROC_PPC405 +#ifdef PPC_PIT_INTERRUPT +s32 ppc_pit_init( void ); +#endif +s32 powerpc405_init() +#endif /* PROC_CORTEXA9 */ + +#ifdef PROC_PPC440 +#ifdef PPC_PIT_INTERRUPT +s32 ppc_dec_init( void ); +#endif +s32 powerpc405_init(void); +#endif /* PROC_PPC440 */ + +#if (!defined PPC_PIT_INTERRUPT && !defined PROC_CORTEXA9) +s32 opb_timer_init( void ); +#endif + +#ifdef PROC_MICROBLAZE +s32 microblaze_init(void); +#endif /* PROC_MICROBLAZE */ + +#ifdef PROC_CORTEXA9 +s32 scu_timer_init( void ); +s32 cortexa9_init(void); +#endif /* PROC_CORTEXA9 */ + + +/*-------------------------------------------------------------------- + * PowerPC Target - Timer related functions + *-------------------------------------------------------------------- */ +#ifdef PROC_PPC405 + + +/*-------------------------------------------------------------------- +* PowerPC PIT Timer Init. +* Defined only if PIT Timer is used for Profiling +* +*-------------------------------------------------------------------- */ +#ifdef PPC_PIT_INTERRUPT +int ppc_pit_init( void ) +{ + /* 1. Register Profile_intr_handler as Interrupt handler */ + /* 2. Set PIT Timer Interrupt and Enable it. */ + Xil_ExceptionRegisterHandler( XIL_EXCEPTION_ID_PIT_INT, + (Xil_ExceptionHandler)profile_intr_handler,NULL); + XTime_PITSetInterval( timer_clk_ticks ) ; + XTime_PITEnableAutoReload() ; + return 0; +} +#endif + + +/* -------------------------------------------------------------------- +* PowerPC Timer Initialization functions. +* For PowerPC, PIT and opb_timer can be used for Profiling. This +* is selected by the user in standalone BSP +* +*-------------------------------------------------------------------- */ +s32 powerpc405_init() +{ + Xil_ExceptionInit() ; + Xil_ExceptionDisableMask( XIL_EXCEPTION_NON_CRITICAL ) ; + + /* Initialize the Timer. + * 1. If PowerPC PIT Timer has to be used, initialize PIT timer. + * 2. Else use opb_timer. It can be directly connected or thru intc to PowerPC */ +#ifdef PPC_PIT_INTERRUPT + ppc_pit_init(); +#else +#ifdef TIMER_CONNECT_INTC + Xil_ExceptionRegisterHandler( XIL_EXCEPTION_ID_NON_CRITICAL_INT, + (Xil_ExceptionHandler)XIntc_DeviceInterruptHandler,NULL); + XIntc_RegisterHandler( INTC_BASEADDR, PROFILE_TIMER_INTR_ID, + (XInterruptHandler)profile_intr_handler,NULL); +#else + Xil_ExceptionRegisterHandler( XIL_EXCEPTION_ID_NON_CRITICAL_INT, + (Xil_ExceptionHandler)profile_intr_handler,NULL); +#endif + /* Initialize the timer with Timer Ticks */ + opb_timer_init() ; +#endif + + /* Enable Interrupts in the System, if Profile Timer is the only Interrupt + * in the System. */ +#ifdef ENABLE_SYS_INTR +#ifdef PPC_PIT_INTERRUPT + XTime_PITEnableInterrupt() ; +#elif TIMER_CONNECT_INTC + XIntc_MasterEnable( INTC_BASEADDR ); + XIntc_SetIntrSvcOption( INTC_BASEADDR, XIN_SVC_ALL_ISRS_OPTION); + XIntc_EnableIntr( INTC_BASEADDR, PROFILE_TIMER_INTR_MASK ); +#endif + Xil_ExceptionEnableMask( XIL_EXCEPTION_NON_CRITICAL ) ; +#endif + return 0; +} + +#endif /* PROC_PPC */ + + + +/*-------------------------------------------------------------------- + * PowerPC440 Target - Timer related functions + * -------------------------------------------------------------------- */ +#ifdef PROC_PPC440 + + +/*-------------------------------------------------------------------- + * PowerPC DEC Timer Init. + * Defined only if DEC Timer is used for Profiling + * + *-------------------------------------------------------------------- */ +#ifdef PPC_PIT_INTERRUPT +s32 ppc_dec_init( void ) +{ + /* 1. Register Profile_intr_handler as Interrupt handler */ + /* 2. Set DEC Timer Interrupt and Enable it. */ + Xil_ExceptionRegisterHandler( XIL_EXCEPTION_ID_DEC_INT, + (Xil_ExceptionHandler)profile_intr_handler,NULL); + XTime_DECSetInterval( timer_clk_ticks ) ; + XTime_DECEnableAutoReload() ; + return 0; +} +#endif + + +/*-------------------------------------------------------------------- + * PowerPC Timer Initialization functions. + * For PowerPC, DEC and opb_timer can be used for Profiling. This + * is selected by the user in standalone BSP + * + *-------------------------------------------------------------------- */ +s32 powerpc405_init(void) +{ + Xil_ExceptionInit(); + Xil_ExceptionDisableMask( XIL_EXCEPTION_NON_CRITICAL ) ; + + /* Initialize the Timer. + * 1. If PowerPC DEC Timer has to be used, initialize DEC timer. + * 2. Else use opb_timer. It can be directly connected or thru intc to PowerPC */ +#ifdef PPC_PIT_INTERRUPT + ppc_dec_init(); +#else +#ifdef TIMER_CONNECT_INTC + Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_NON_CRITICAL_INT, + (Xil_ExceptionHandler)XIntc_DeviceInterruptHandler,NULL); + + XIntc_RegisterHandler( INTC_BASEADDR, PROFILE_TIMER_INTR_ID, + (XInterruptHandler)profile_intr_handler,NULL); +#else + Xil_ExceptionRegisterHandler( XIL_EXCEPTION_ID_NON_CRITICAL_INT, + (Xil_ExceptionHandler)profile_intr_handler,NULL); + Xil_ExceptionRegisterHandler( XIL_EXCEPTION_ID_NON_CRITICAL_INT, + (Xil_ExceptionHandler)profile_intr_handler,NULL); +#endif + /* Initialize the timer with Timer Ticks */ + opb_timer_init() ; +#endif + + /* Enable Interrupts in the System, if Profile Timer is the only Interrupt + * in the System. */ +#ifdef ENABLE_SYS_INTR +#ifdef PPC_PIT_INTERRUPT + XTime_DECEnableInterrupt() ; +#elif TIMER_CONNECT_INTC + XIntc_MasterEnable( INTC_BASEADDR ); + XIntc_SetIntrSvcOption( INTC_BASEADDR, XIN_SVC_ALL_ISRS_OPTION); + XIntc_EnableIntr( INTC_BASEADDR, PROFILE_TIMER_INTR_MASK ); +#endif + Xil_ExceptionEnableMask( XEXC_NON_CRITICAL ) ; +#endif + return 0; +} + +#endif /* PROC_PPC440 */ + +/* -------------------------------------------------------------------- + * opb_timer Initialization for PowerPC and MicroBlaze. This function + * is not needed if DEC timer is used in PowerPC + * + *-------------------------------------------------------------------- */ +/* #ifndef PPC_PIT_INTERRUPT */ +#if (!defined PPC_PIT_INTERRUPT && !defined PROC_CORTEXA9) +s32 opb_timer_init( void ) +{ + /* set the number of cycles the timer counts before interrupting */ + XTmrCtr_SetLoadReg((u32)PROFILE_TIMER_BASEADDR, (u16)0, (u32)timer_clk_ticks); + + /* reset the timers, and clear interrupts */ + XTmrCtr_SetControlStatusReg((u32)PROFILE_TIMER_BASEADDR, (u16)0, + (u32)XTC_CSR_INT_OCCURED_MASK | (u32)XTC_CSR_LOAD_MASK ); + + /* start the timers */ + XTmrCtr_SetControlStatusReg((u32)PROFILE_TIMER_BASEADDR, (u16)0, (u32)XTC_CSR_ENABLE_TMR_MASK + | (u32)XTC_CSR_ENABLE_INT_MASK | (u32)XTC_CSR_AUTO_RELOAD_MASK | (u32)XTC_CSR_DOWN_COUNT_MASK); + return 0; +} +#endif + + +/*-------------------------------------------------------------------- + * MicroBlaze Target - Timer related functions + *-------------------------------------------------------------------- */ +#ifdef PROC_MICROBLAZE + +/* -------------------------------------------------------------------- + * Initialize the Profile Timer for MicroBlaze Target. + * For MicroBlaze, opb_timer is used. The opb_timer can be directly + * connected to MicroBlaze or connected through Interrupt Controller. + * + *-------------------------------------------------------------------- */ +s32 microblaze_init(void) +{ + /* Register profile_intr_handler + * 1. If timer is connected to Interrupt Controller, register the handler + * to Interrupt Controllers vector table. + * 2. If timer is directly connected to MicroBlaze, register the handler + * as Interrupt handler */ + Xil_ExceptionInit(); + +#ifdef TIMER_CONNECT_INTC + XIntc_RegisterHandler( INTC_BASEADDR, PROFILE_TIMER_INTR_ID, + (XInterruptHandler)profile_intr_handler,NULL); +#else + Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, + (Xil_ExceptionHandler)profile_intr_handler, + NULL) ; +#endif + + /* Initialize the timer with Timer Ticks */ + (void)opb_timer_init() ; + + /* Enable Interrupts in the System, if Profile Timer is the only Interrupt + * in the System. */ +#ifdef ENABLE_SYS_INTR +#ifdef TIMER_CONNECT_INTC + XIntc_MasterEnable((u32)INTC_BASEADDR ); + XIntc_SetIntrSvcOption( INTC_BASEADDR, XIN_SVC_ALL_ISRS_OPTION); + XIntc_EnableIntr( (u32)INTC_BASEADDR, PROFILE_TIMER_INTR_MASK ); + Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, + (Xil_ExceptionHandler)XIntc_DeviceInterruptHandler,NULL); +#endif + +#endif + + Xil_ExceptionEnable(); + + return 0; + +} + +#endif /* PROC_MICROBLAZE */ + + + +/* -------------------------------------------------------------------- + * Cortex A9 Target - Timer related functions + *-------------------------------------------------------------------- */ +#ifdef PROC_CORTEXA9 + +/* -------------------------------------------------------------------- + * Initialize the Profile Timer for Cortex A9 Target. + * The scu private timer is connected to the Scu GIC controller. + * + *-------------------------------------------------------------------- */ +s32 scu_timer_init( void ) +{ + /* set the number of cycles the timer counts before interrupting + * scu timer runs at half the cpu clock */ + XScuTimer_SetLoadReg(PROFILE_TIMER_BASEADDR, timer_clk_ticks/2U); + + /* clear any pending interrupts */ + XScuTimer_SetIntrReg(PROFILE_TIMER_BASEADDR, 1U); + + /* enable interrupts, auto-reload mode and start the timer */ + XScuTimer_SetControlReg(PROFILE_TIMER_BASEADDR, XSCUTIMER_CONTROL_IRQ_ENABLE_MASK | + XSCUTIMER_CONTROL_AUTO_RELOAD_MASK | XSCUTIMER_CONTROL_ENABLE_MASK); + + return 0; +} + +s32 cortexa9_init(void) +{ + + Xil_ExceptionInit(); + + XScuGic_DeviceInitialize(0); + + /* + * Connect the interrupt controller interrupt handler to the hardware + * interrupt handling logic in the processor. + */ + Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_IRQ_INT, + (Xil_ExceptionHandler)XScuGic_DeviceInterruptHandler, + NULL); + + /* + * Connect the device driver handler that will be called when an + * interrupt for the device occurs, the handler defined above performs + * the specific interrupt processing for the device. + */ + XScuGic_RegisterHandler(SCUGIC_CPU_BASEADDR, + PROFILE_TIMER_INTR_ID, + (Xil_ExceptionHandler)profile_intr_handler, + NULL); + + /* + * Enable the interrupt for scu timer. + */ + XScuGic_EnableIntr(SCUGIC_DIST_BASEADDR, PROFILE_TIMER_INTR_ID); + + /* + * Enable interrupts in the Processor. + */ + Xil_ExceptionEnableMask(XIL_EXCEPTION_IRQ); + + /* + * Initialize the timer with Timer Ticks + */ + (void)scu_timer_init() ; + + Xil_ExceptionEnable(); + + return 0; +} + +#endif /* PROC_CORTEXA9 */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/_profile_timer_hw.h b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/_profile_timer_hw.h new file mode 100644 index 0000000..1647600 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/_profile_timer_hw.h @@ -0,0 +1,308 @@ +/****************************************************************************** +* +* Copyright (C) 2004 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +****************************************************************************** +* +* _program_timer_hw.h: +* Timer related functions +* +******************************************************************************/ + +#ifndef PROFILE_TIMER_HW_H +#define PROFILE_TIMER_HW_H + +#include "profile.h" + +#ifdef PROC_PPC +#if defined __GNUC__ +# define SYNCHRONIZE_IO __asm__ volatile ("eieio") +#elif defined __DCC__ +# define SYNCHRONIZE_IO __asm volatile(" eieio") +#else +# define SYNCHRONIZE_IO +#endif +#endif + +#ifdef PROC_PPC +#define ProfIo_In32(InputPtr) { (*(volatile u32 *)(InputPtr)); SYNCHRONIZE_IO; } +#define ProfIo_Out32(OutputPtr, Value) { (*(volatile u32 *)(OutputPtr) = Value); SYNCHRONIZE_IO; } +#else +#define ProfIo_In32(InputPtr) (*(volatile u32 *)(InputPtr)); +#define ProfIo_Out32(OutputPtr, Value) { (*(volatile u32 *)(OutputPtr) = (Value)); } +#endif + +#define ProfTmrCtr_mWriteReg(BaseAddress, TmrCtrNumber, RegOffset, ValueToWrite)\ + ProfIo_Out32(((u32)(BaseAddress) + (u32)XTmrCtr_Offsets[(TmrCtrNumber)] + \ + (u32)(RegOffset)), (u32)(ValueToWrite)) + +#define ProfTimerCtr_mReadReg(BaseAddress, TmrCtrNumber, RegOffset) \ + ProfIo_In32((u32)(BaseAddress) + (u32)XTmrCtr_Offsets[(TmrCtrNumber)] + (u32)(RegOffset)) + +#define ProfTmrCtr_mSetControlStatusReg(BaseAddress, TmrCtrNumber, RegisterValue)\ + ProfTmrCtr_mWriteReg((BaseAddress), (TmrCtrNumber), XTC_TCSR_OFFSET, \ + (RegisterValue)) + +#define ProfTmrCtr_mGetControlStatusReg(BaseAddress, TmrCtrNumber) \ + ProfTimerCtr_mReadReg((u32)(BaseAddress), (TmrCtrNumber), XTC_TCSR_OFFSET) + + + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef PROC_PPC +#include "xexception_l.h" +#include "xtime_l.h" +#include "xpseudo_asm.h" +#endif + +#ifdef TIMER_CONNECT_INTC +#include "xintc_l.h" +#include "xintc.h" +#endif /* TIMER_CONNECT_INTC */ + +#if (!defined PPC_PIT_INTERRUPT && !defined PROC_CORTEXA9) +#include "xtmrctr_l.h" +#endif + +#ifdef PROC_CORTEXA9 +#include "xscutimer_hw.h" +#include "xscugic.h" +#endif + +extern u32 timer_clk_ticks ; + +/*-------------------------------------------------------------------- + * PowerPC Target - Timer related functions + *-------------------------------------------------------------------- */ +#ifdef PROC_PPC + +#ifdef PPC_PIT_INTERRUPT +u32 timer_lo_clk_ticks ; /* Clk ticks when Timer is disabled in CG */ +#endif + +#ifdef PROC_PPC440 +#define XREG_TCR_PIT_INTERRUPT_ENABLE XREG_TCR_DEC_INTERRUPT_ENABLE +#define XREG_TSR_PIT_INTERRUPT_STATUS XREG_TSR_DEC_INTERRUPT_STATUS +#define XREG_SPR_PIT XREG_SPR_DEC +#define XEXC_ID_PIT_INT XEXC_ID_DEC_INT +#endif + +/* -------------------------------------------------------------------- + * Disable the Timer - During Profiling + * + * For PIT Timer - + * 1. XTime_PITDisableInterrupt() ; + * 2. Store the remaining timer clk tick + * 3. Stop the PIT Timer + *-------------------------------------------------------------------- */ + +#ifdef PPC_PIT_INTERRUPT +#define disable_timer() \ + { \ + u32 val; \ + val=mfspr(XREG_SPR_TCR); \ + mtspr(XREG_SPR_TCR, val & (~XREG_TCR_PIT_INTERRUPT_ENABLE)); \ + timer_lo_clk_ticks = mfspr(XREG_SPR_PIT); \ + mtspr(XREG_SPR_PIT, 0); \ + } +#else +#define disable_timer() \ + { \ + u32 addr = (PROFILE_TIMER_BASEADDR) + XTmrCtr_Offsets[(0)] + XTC_TCSR_OFFSET; \ + u32 tmp_v = ProfIo_In32(addr); \ + tmp_v = tmp_v & (~XTC_CSR_ENABLE_TMR_MASK); \ + ProfIo_Out32((PROFILE_TIMER_BASEADDR) + XTmrCtr_Offsets[(0)] + XTC_TCSR_OFFSET, tmp_v); \ + } +#endif + + + +/* -------------------------------------------------------------------- + * Enable the Timer + * + * For PIT Timer - + * 1. Load the remaining timer clk ticks + * 2. XTime_PITEnableInterrupt() ; + *-------------------------------------------------------------------- */ +#ifdef PPC_PIT_INTERRUPT +#define enable_timer() \ + { \ + u32 val; \ + val=mfspr(XREG_SPR_TCR); \ + mtspr(XREG_SPR_PIT, timer_lo_clk_ticks); \ + mtspr(XREG_SPR_TCR, val | XREG_TCR_PIT_INTERRUPT_ENABLE); \ + } +#else +#define enable_timer() \ + { \ + u32 addr = (PROFILE_TIMER_BASEADDR) + XTmrCtr_Offsets[(0)] + XTC_TCSR_OFFSET; \ + u32 tmp_v = ProfIo_In32(addr); \ + tmp_v = tmp_v | XTC_CSR_ENABLE_TMR_MASK; \ + ProfIo_Out32((PROFILE_TIMER_BASEADDR) + XTmrCtr_Offsets[(0)] + XTC_TCSR_OFFSET, tmp_v); \ + } +#endif + + + +/* -------------------------------------------------------------------- + * Send Ack to Timer Interrupt + * + * For PIT Timer - + * 1. Load the timer clk ticks + * 2. Enable AutoReload and Interrupt + * 3. Clear PIT Timer Status bits + *-------------------------------------------------------------------- */ +#ifdef PPC_PIT_INTERRUPT +#define timer_ack() \ + { \ + u32 val; \ + mtspr(XREG_SPR_PIT, timer_clk_ticks); \ + mtspr(XREG_SPR_TSR, XREG_TSR_PIT_INTERRUPT_STATUS); \ + val=mfspr(XREG_SPR_TCR); \ + mtspr(XREG_SPR_TCR, val| XREG_TCR_PIT_INTERRUPT_ENABLE| XREG_TCR_AUTORELOAD_ENABLE); \ + } +#else +#define timer_ack() \ + { \ + u32 csr; \ + csr = ProfTmrCtr_mGetControlStatusReg(PROFILE_TIMER_BASEADDR, 0); \ + ProfTmrCtr_mSetControlStatusReg(PROFILE_TIMER_BASEADDR, 0, csr); \ + } +#endif + +/*-------------------------------------------------------------------- */ +#endif /* PROC_PPC */ +/* -------------------------------------------------------------------- */ + + + + +/* -------------------------------------------------------------------- + * MicroBlaze Target - Timer related functions + *-------------------------------------------------------------------- */ +#ifdef PROC_MICROBLAZE + +/* -------------------------------------------------------------------- + * Disable the Timer during Call-Graph Data collection + * + *-------------------------------------------------------------------- */ +#define disable_timer() \ + { \ + u32 Addr = ((u32)PROFILE_TIMER_BASEADDR); \ + Addr += (u32)XTmrCtr_Offsets[(u16)(0)]; \ + Addr += (u32)XTC_TCSR_OFFSET; \ + u32 tmp_v = ProfIo_In32(Addr); \ + tmp_v = tmp_v & (u32)(~XTC_CSR_ENABLE_TMR_MASK); \ + u32 OutAddr = (u32)PROFILE_TIMER_BASEADDR; \ + OutAddr += (u32)XTmrCtr_Offsets[(u16)(0)]; \ + OutAddr += (u32)XTC_TCSR_OFFSET; \ + ProfIo_Out32(OutAddr, (u32)tmp_v); \ + } + + +/* -------------------------------------------------------------------- + * Enable the Timer after Call-Graph Data collection + * + *-------------------------------------------------------------------- */ +#define enable_timer() \ + { \ + u32 Addr = ((u32)PROFILE_TIMER_BASEADDR); \ + Addr += (u32)XTmrCtr_Offsets[(u16)(0)]; \ + Addr += (u32)XTC_TCSR_OFFSET; \ + u32 tmp_v = (u32)ProfIo_In32(Addr); \ + tmp_v = tmp_v | (u32)XTC_CSR_ENABLE_TMR_MASK; \ + ProfIo_Out32((u32)(PROFILE_TIMER_BASEADDR) + (u32)XTmrCtr_Offsets[(u16)(0)] + (u32)XTC_TCSR_OFFSET, (u32)tmp_v); \ + } + + +/* -------------------------------------------------------------------- + * Send Ack to Timer Interrupt + * + *-------------------------------------------------------------------- */ +#define timer_ack() \ + { \ + u32 csr; \ + csr = ProfTmrCtr_mGetControlStatusReg((u32)PROFILE_TIMER_BASEADDR, (u16)0); \ + ProfTmrCtr_mSetControlStatusReg((u32)PROFILE_TIMER_BASEADDR, (u16)0, (u32)csr); \ + } + +/*-------------------------------------------------------------------- */ +#endif /* PROC_MICROBLAZE */ +/*-------------------------------------------------------------------- */ + +/* -------------------------------------------------------------------- + * Cortex A9 Target - Timer related functions + *-------------------------------------------------------------------- */ +#ifdef PROC_CORTEXA9 + +/* -------------------------------------------------------------------- + * Disable the Timer during Call-Graph Data collection + * + *-------------------------------------------------------------------- */ +#define disable_timer() \ +{ \ + u32 Reg; \ + Reg = Xil_In32(PROFILE_TIMER_BASEADDR + XSCUTIMER_CONTROL_OFFSET); \ + Reg &= (~XSCUTIMER_CONTROL_ENABLE_MASK);\ + Xil_Out32(PROFILE_TIMER_BASEADDR + XSCUTIMER_CONTROL_OFFSET, Reg);\ +} + + +/* -------------------------------------------------------------------- + * Enable the Timer after Call-Graph Data collection + * + *-------------------------------------------------------------------- */ +#define enable_timer() \ +{ \ + u32 Reg; \ + Reg = Xil_In32(PROFILE_TIMER_BASEADDR + XSCUTIMER_CONTROL_OFFSET); \ + Reg |= XSCUTIMER_CONTROL_ENABLE_MASK; \ + Xil_Out32(PROFILE_TIMER_BASEADDR + XSCUTIMER_CONTROL_OFFSET, Reg);\ +} + + +/* -------------------------------------------------------------------- + * Send Ack to Timer Interrupt + * + *-------------------------------------------------------------------- */ +#define timer_ack() \ +{ \ + Xil_Out32((u32)PROFILE_TIMER_BASEADDR + (u32)XSCUTIMER_ISR_OFFSET, \ + (u32)XSCUTIMER_ISR_EVENT_FLAG_MASK);\ +} + +/*-------------------------------------------------------------------- */ +#endif /* PROC_CORTEXA9 */ +/*-------------------------------------------------------------------- */ + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/dummy.S b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/dummy.S new file mode 100644 index 0000000..f4ff406 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/dummy.S @@ -0,0 +1,60 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + + .globl dummy_f + +#ifdef PROC_MICROBLAZE + .text + .align 2 + .ent dummy_f + +dummy_f: + nop + + .end dummy_f +#endif + +#ifdef PROC_PPC + .section .text + .align 2 + .type dummy_f@function + +dummy_f: + b dummy_f + +#endif + +#ifdef PROC_CORTEXA9 + .section .text + .align 2 + .type dummy_f, %function + +dummy_f: + b dummy_f + +#endif diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/mblaze_nt_types.h b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/mblaze_nt_types.h new file mode 100644 index 0000000..807dda3 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/mblaze_nt_types.h @@ -0,0 +1,50 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + + +#ifndef _MBLAZE_NT_TYPES_H +#define _MBLAZE_NT_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef char byte; +typedef short half; +typedef int word; +typedef unsigned char ubyte; +typedef unsigned short uhalf; +typedef unsigned int uword; +typedef ubyte boolean; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/profile.h b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/profile.h new file mode 100644 index 0000000..63f503a --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/profile.h @@ -0,0 +1,127 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +#ifndef PROFILE_H +#define PROFILE_H 1 + +#include +#include "xil_types.h" +#include "profile_config.h" + +#ifdef PROC_MICROBLAZE +#include "mblaze_nt_types.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +void _system_init( void ) ; +void _system_clean( void ) ; +void mcount(u32 frompc, u32 selfpc); +void profile_intr_handler( void ) ; +void _profile_init( void ); + + + +/**************************************************************************** + * Profiling on hardware - Hash table maintained on hardware and data sent + * to xmd for gmon.out generation. + ****************************************************************************/ +/* + * histogram counters are unsigned shorts (according to the kernel). + */ +#define HISTCOUNTER u16 + +struct tostruct { + u32 selfpc; + s32 count; + s16 link; + u16 pad; +}; + +struct fromstruct { + u32 frompc ; + s16 link ; + u16 pad ; +} ; + +/* + * general rounding functions. + */ +#define ROUNDDOWN(x,y) (((x)/(y))*(y)) +#define ROUNDUP(x,y) ((((x)+(y)-1)/(y))*(y)) + +/* + * The profiling data structures are housed in this structure. + */ +struct gmonparam { + s32 state; + + /* Histogram Information */ + u16 *kcount; /* No. of bins in histogram */ + u32 kcountsize; /* Histogram samples */ + + /* Call-graph Information */ + struct fromstruct *froms; + u32 fromssize; + struct tostruct *tos; + u32 tossize; + + /* Initialization I/Ps */ + u32 lowpc; + u32 highpc; + u32 textsize; + /* u32 cg_froms, */ + /* u32 cg_tos, */ +}; +extern struct gmonparam *_gmonparam; +extern s32 n_gmon_sections; + +/* + * Possible states of profiling. + */ +#define GMON_PROF_ON 0 +#define GMON_PROF_BUSY 1 +#define GMON_PROF_ERROR 2 +#define GMON_PROF_OFF 3 + +/* + * Sysctl definitions for extracting profiling information from the kernel. + */ +#define GPROF_STATE 0 /* int: profiling enabling variable */ +#define GPROF_COUNT 1 /* struct: profile tick count buffer */ +#define GPROF_FROMS 2 /* struct: from location hash bucket */ +#define GPROF_TOS 3 /* struct: destination/count structure */ +#define GPROF_GMONPARAM 4 /* struct: profiling parameters (see above) */ + +#ifdef __cplusplus +} +#endif + +#endif /* PROFILE_H */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/profile_cg.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/profile_cg.c new file mode 100644 index 0000000..328e6fc --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/profile_cg.c @@ -0,0 +1,167 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +#include "profile.h" +#include "_profile_timer_hw.h" +#ifdef PROC_MICROBLAZE +#include "mblaze_nt_types.h" +#endif + +/* + * The mcount fucntion is excluded from the library, if the user defines + * PROFILE_NO_GRAPH. + */ +#ifndef PROFILE_NO_GRAPH + +#include +#include +#include + +#ifdef PROFILE_NO_FUNCPTR +s32 searchpc(const struct fromto_struct *cgtable, s32 cgtable_size, u32 frompc ); +#else +s32 searchpc(const struct fromstruct *froms, s32 fromssize, u32 frompc ); +#endif + +/*extern struct gmonparam *_gmonparam, */ + +#ifdef PROFILE_NO_FUNCPTR +s32 searchpc(const struct fromto_struct *cgtable, s32 cgtable_size, u32 frompc ) +{ + s32 index = 0 ; + + while( (index < cgtable_size) && (cgtable[index].frompc != frompc) ){ + index++ ; + } + if( index == cgtable_size ) { + return -1 ; + } else { + return index ; + } +} +#else +s32 searchpc(const struct fromstruct *froms, s32 fromssize, u32 frompc ) +{ + s32 index = 0 ; + s32 Status; + + while( (index < fromssize) && (froms[index].frompc != frompc) ){ + index++ ; + } + if( index == fromssize ) { + Status = -1 ; + } else { + Status = index ; + } + return Status; +} +#endif /* PROFILE_NO_FUNCPTR */ + + +void mcount( u32 frompc, u32 selfpc ) +{ + register struct gmonparam *p = NULL; + register s32 toindex, fromindex; + s32 j; + + disable_timer(); + + /*print("CG: "), putnum(frompc), print("->"), putnum(selfpc), print("\r\n") , + * check that frompcindex is a reasonable pc value. + * for example: signal catchers get called from the stack, + * not from text space. too bad. + */ + for(j = 0; j < n_gmon_sections; j++ ){ + if((frompc >= _gmonparam[j].lowpc) && (frompc < _gmonparam[j].highpc)) { + p = &_gmonparam[j]; + break; + } + } + if( j == n_gmon_sections ) { + goto done; + } + +#ifdef PROFILE_NO_FUNCPTR + fromindex = searchpc( p->cgtable, p->cgtable_size, frompc ) ; + if( fromindex == -1 ) { + fromindex = p->cgtable_size ; + p->cgtable_size++ ; + p->cgtable[fromindex].frompc = frompc ; + p->cgtable[fromindex].selfpc = selfpc ; + p->cgtable[fromindex].count = 1 ; + goto done ; + } + p->cgtable[fromindex].count++ ; +#else + fromindex = (s32)searchpc( p->froms, ((s32)p->fromssize), frompc ) ; + if( fromindex == -1 ) { + fromindex = (s32)p->fromssize ; + p->fromssize++ ; + /*if( fromindex >= N_FROMS ) { + * print("Error : From PC table overflow\r\n") + * goto overflow + *}*/ + p->froms[fromindex].frompc = frompc ; + p->froms[fromindex].link = -1 ; + }else { + toindex = ((s32)(p->froms[fromindex].link)); + while(toindex != -1) { + toindex = (((s32)p->tossize) - toindex)-1 ; + if( p->tos[toindex].selfpc == selfpc ) { + p->tos[toindex].count++ ; + goto done ; + } + toindex = ((s32)(p->tos[toindex].link)) ; + } + } + + /*if( toindex == -1 ) { */ + p->tos-- ; + p->tossize++ ; + /* if( toindex >= N_TOS ) { + * print("Error : To PC table overflow\r\n") + * goto overflow + *} */ + p->tos[0].selfpc = selfpc ; + p->tos[0].count = 1 ; + p->tos[0].link = p->froms[fromindex].link ; + p->froms[fromindex].link = ((s32)(p->tossize))-((s32)1); +#endif + + done: + p->state = GMON_PROF_ON; + goto enable_timer_label ; + /* overflow: */ + /*p->state = GMON_PROF_ERROR */ + enable_timer_label: + enable_timer(); + return ; +} + + +#endif /* PROFILE_NO_GRAPH */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/profile_config.h b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/profile_config.h new file mode 100644 index 0000000..5d66311 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/profile_config.h @@ -0,0 +1,52 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + + +#ifndef _PROFILE_CONFIG_H +#define _PROFILE_CONFIG_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define BINSIZE 4U +#define SAMPLE_FREQ_HZ 100000U +#define TIMER_CLK_TICKS 1000U + +#define PROFILE_NO_FUNCPTR_FLAG 0 + +#define PROFILE_TIMER_BASEADDR 0x00608000U +#define PROFILE_TIMER_INTR_ID 0U + +#define TIMER_CONNECT_INTC + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/profile_hist.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/profile_hist.c new file mode 100644 index 0000000..b3e237b --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/profile_hist.c @@ -0,0 +1,67 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +#include "profile.h" +#include "_profile_timer_hw.h" + +#ifdef PROC_MICROBLAZE +#include "mblaze_nt_types.h" +#endif + +#ifdef PROC_PPC +#include "xpseudo_asm.h" +#define SPR_SRR0 0x01A +#endif + +#include "xil_types.h" + +extern u32 binsize ; +u32 prof_pc ; + +void profile_intr_handler( void ) +{ + + s32 j; + +#ifdef PROC_MICROBLAZE + asm( "swi r14, r0, prof_pc" ) ; +#elif defined PROC_PPC + prof_pc = mfspr(SPR_SRR0); +#else + /* for cortexa9, lr is saved in asm interrupt handler */ +#endif + /* print("PC: "), putnum(prof_pc), print("\r\n"), */ + for(j = 0; j < n_gmon_sections; j++ ){ + if((prof_pc >= ((u32)_gmonparam[j].lowpc)) && (prof_pc < ((u32)_gmonparam[j].highpc))) { + _gmonparam[j].kcount[(prof_pc-_gmonparam[j].lowpc)/((u32)4 * binsize)]++; + break; + } + } + /* Ack the Timer Interrupt */ + timer_ack(); +} diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/profile_mcount_arm.S b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/profile_mcount_arm.S new file mode 100644 index 0000000..9a84363 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/profile_mcount_arm.S @@ -0,0 +1,41 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +// based on "ARM Profiling Implementation" from Sourcery G++ Lite for ARM EABI + +.globl __gnu_mcount_nc +.type __gnu_mcount_nc, %function + +__gnu_mcount_nc: + push {r0, r1, r2, r3, lr} + subs r1, lr, #0 /* callee - current lr */ + ldr r0, [sp, #20] /* caller - at the top of the stack */ + bl mcount /* when __gnu_mcount_nc is called */ + pop {r0, r1, r2, r3, ip, lr} + bx ip + + .end __gnu_mcount_nc diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/profile_mcount_mb.S b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/profile_mcount_mb.S new file mode 100644 index 0000000..21ab5b4 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/profile_mcount_mb.S @@ -0,0 +1,65 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + + .globl _mcount + .text + .align 2 + .ent _mcount + + #ifndef PROFILE_NO_GRAPH + +_mcount: + addi r1, r1, -48 + swi r11, r1, 44 + swi r12, r1, 40 + swi r5, r1, 36 + swi r6, r1, 32 + swi r7, r1, 28 + swi r8, r1, 24 + swi r9, r1, 20 + swi r10, r1, 16 + swi r15, r1, 12 + add r5, r0, r15 + brlid r15, mcount + add r6, r0, r16 + + lwi r11, r1, 44 + lwi r12, r1, 40 + lwi r5, r1, 36 + lwi r6, r1, 32 + lwi r7, r1, 28 + lwi r8, r1, 24 + lwi r9, r1, 20 + lwi r10, r1, 16 + lwi r15, r1, 12 + rtsd r15, 4 + addi r1, r1, 48 + + #endif /* PROFILE_NO_GRAPH */ + + .end _mcount diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/profile_mcount_ppc.S b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/profile_mcount_ppc.S new file mode 100644 index 0000000..230df08 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/profile/profile_mcount_ppc.S @@ -0,0 +1,67 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + + .globl _mcount + + #define _MCOUNT_STACK_FRAME 48 + .section .text + .align 2 + .type _mcount@function + + +_mcount: + stwu 1, -_MCOUNT_STACK_FRAME(1) + stw 3, 8(1) + stw 4, 12(1) + stw 5, 16(1) + stw 6, 20(1) + stw 7, 24(1) + stw 8, 28(1) + stw 9, 32(1) + stw 10, 36(1) + stw 11, 40(1) + stw 12, 44(1) + mflr 4 + stw 4, (_MCOUNT_STACK_FRAME+4)(1) + lwz 3, (_MCOUNT_STACK_FRAME)(1) + lwz 3, 4(3) + bl mcount + lwz 4, (_MCOUNT_STACK_FRAME+4)(1) + mtlr 4 + lwz 12, 44(1) + lwz 11, 40(1) + lwz 10, 36(1) + lwz 9, 32(1) + lwz 8, 28(1) + lwz 7, 24(1) + lwz 6, 20(1) + lwz 5, 16(1) + lwz 4, 12(1) + lwz 3, 8(1) + addi 1,1, _MCOUNT_STACK_FRAME + blr diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/putnum.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/putnum.c new file mode 100644 index 0000000..aaf9ede --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/putnum.c @@ -0,0 +1,59 @@ +/* putnum.c -- put a hex number on the output device. + * + * Copyright (c) 1995 Cygnus Support + * + * The authors hereby grant permission to use, copy, modify, distribute, + * and license this software and its documentation for any purpose, provided + * that existing copyright notices are retained in all copies and that this + * notice is included verbatim in any distributions. No written agreement, + * license, or royalty fee is required for any of the authorized uses. + * Modifications to this software may be copyrighted by their authors + * and need not follow the licensing terms described here, provided that + * the new terms are clearly indicated on the first page of each file where + * they apply. + */ + +/* + * putnum -- print a 32 bit number in hex + */ + +/***************************** Include Files *********************************/ +#include "xil_types.h" + +/************************** Function Prototypes ******************************/ +extern void print (const char8 *ptr); +void putnum(u32 num); + +void putnum(u32 num) +{ + char8 buf[9]; + s32 cnt; + s32 i; + char8 *ptr; + u32 digit; + for(i = 0; i<9; i++) { + buf[i] = '0'; + } + + ptr = buf; + for (cnt = 7 ; cnt >= 0 ; cnt--) { + digit = (num >> (cnt * 4U)) & 0x0000000fU; + + if ((digit <= 9U) && (ptr != NULL)) { + digit += (u32)'0'; + *ptr = ((char8) digit); + ptr += 1; + } else if (ptr != NULL) { + digit += ((u32)'a' - (u32)10); + *ptr = ((char8)digit); + ptr += 1; + } else { + /*Made for MisraC Compliance*/; + } + } + + if(ptr != NULL) { + *ptr = (char8) 0; + } + print (buf); +} diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/read.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/read.c new file mode 100644 index 0000000..9900842 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/read.c @@ -0,0 +1,100 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +/* read.c -- read bytes from a input device. + */ +#ifndef UNDEFINE_FILE_OPS +#include "xil_printf.h" +#include "xparameters.h" + +#ifdef __cplusplus +extern "C" { + __attribute__((weak)) s32 _read (s32 fd, char8* buf, s32 nbytes); +} +#endif + +/* + * read -- read bytes from the serial port. Ignore fd, since + * we only have stdin. + */ +__attribute__((weak)) s32 +read (s32 fd, char8* buf, s32 nbytes) +{ +#ifdef STDIN_BASEADDRESS + s32 i; + s32 numbytes = 0; + char8* LocalBuf = buf; + + (void)fd; + if(LocalBuf != NULL) { + for (i = 0; i < nbytes; i++) { + numbytes++; + *(LocalBuf + i) = inbyte(); + if ((*(LocalBuf + i) == '\n' )|| (*(LocalBuf + i) == '\r')) { + break; + } + } + } + + return numbytes; +#else + (void)fd; + (void)buf; + (void)nbytes; + return 0; +#endif +} + +__attribute__((weak)) s32 +_read (s32 fd, char8* buf, s32 nbytes) +{ +#ifdef STDIN_BASEADDRESS + s32 i; + s32 numbytes = 0; + char8* LocalBuf = buf; + + (void)fd; + if(LocalBuf != NULL) { + for (i = 0; i < nbytes; i++) { + numbytes++; + *(LocalBuf + i) = inbyte(); + if ((*(LocalBuf + i) == '\n' )|| (*(LocalBuf + i) == '\r')) { + break; + } + } + } + + return numbytes; +#else + (void)fd; + (void)buf; + (void)nbytes; + return 0; +#endif +} +#endif diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/sbrk.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/sbrk.c new file mode 100644 index 0000000..7f91b9c --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/sbrk.c @@ -0,0 +1,57 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +#include +#include "xil_types.h" +#ifdef __cplusplus +extern "C" { + __attribute__((weak)) char8 *sbrk (s32 nbytes); +} +#endif + +extern u8 _heap_start[]; +extern u8 _heap_end[]; +extern char8 HeapBase[]; +extern char8 HeapLimit[]; + + + +__attribute__((weak)) char8 *sbrk (s32 nbytes) +{ + char8 *base; + static char8 *heap_ptr = HeapBase; + + base = heap_ptr; + if((heap_ptr != NULL) && (heap_ptr + nbytes <= (char8 *)&HeapLimit + 1)) { + heap_ptr += nbytes; + return base; + } else { + errno = ENOMEM; + return ((char8 *)-1); + } +} diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/sleep.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/sleep.c new file mode 100644 index 0000000..659c21b --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/sleep.c @@ -0,0 +1,88 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2017 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/***************************************************************************** +* +* @file sleep.c +* +* This function provides a second delay using the Global Timer register in +* the ARM Cortex A9 MP core. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 1.00a ecm/sdm  11/11/09 First release
+* 3.07a sgd      07/05/12 Updated sleep function to make use Global
+* 6.0   asa      08/15/16 Updated the sleep signature. Fix for CR#956899.
+* 6.6	srm      10/18/17 Updated sleep routines to support user configurable
+*			  implementation. Now sleep routines will use Timer
+*                         specified by the user (i.e. Global timer/TTC timer)
+*
+* 
+* +******************************************************************************/ +/***************************** Include Files *********************************/ + +#include "sleep.h" +#include "xtime_l.h" +#include "xparameters.h" + +#if defined (SLEEP_TIMER_BASEADDR) +#include "xil_sleeptimer.h" +#endif + +/*****************************************************************************/ +/* +* +* This API is used to provide delays in seconds +* +* @param seconds requested +* +* @return 0 always +* +* @note None. +* +****************************************************************************/ +unsigned sleep_A9(unsigned int seconds) +{ +#if defined (SLEEP_TIMER_BASEADDR) + Xil_SleepTTCCommon(seconds, COUNTS_PER_SECOND); +#else + XTime tEnd, tCur; + + XTime_GetTime(&tCur); + tEnd = tCur + (((XTime) seconds) * COUNTS_PER_SECOND); + do + { + XTime_GetTime(&tCur); + } while (tCur < tEnd); +#endif + + return 0; +} diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/sleep.h b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/sleep.h new file mode 100644 index 0000000..f3a632b --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/sleep.h @@ -0,0 +1,115 @@ +/****************************************************************************** +* +* Copyright (C) 2014 - 2017 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +/*****************************************************************************/ +/** +* @file sleep.h +* +* This header file contains ARM Cortex A53,A9,R5,Microblaze specific sleep +* related APIs. +* +*
+* MODIFICATION HISTORY :
+*
+* Ver   Who  Date	 Changes
+* ----- ---- -------- -------------------------------------------------------
+* 6.6   srm  11/02/17 Added processor specific sleep rountines
+*								 function prototypes.
+*
+* 
+* +******************************************************************************/ + +#ifndef SLEEP_H +#define SLEEP_H + +#include "xil_types.h" +#include "xil_io.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*****************************************************************************/ +/** +* +* This macro polls an address periodically until a condition is met or till the +* timeout occurs. +* The minimum timeout for calling this macro is 100us. If the timeout is less +* than 100us, it still waits for 100us. Also the unit for the timeout is 100us. +* If the timeout is not a multiple of 100us, it waits for a timeout of +* the next usec value which is a multiple of 100us. +* +* @param IO_func - accessor function to read the register contents. +* Depends on the register width. +* @param ADDR - Address to be polled +* @param VALUE - variable to read the value +* @param COND - Condition to checked (usually involves VALUE) +* @param TIMEOUT_US - timeout in micro seconds +* +* @return 0 - when the condition is met +* -1 - when the condition is not met till the timeout period +* +* @note none +* +*****************************************************************************/ +#define Xil_poll_timeout(IO_func, ADDR, VALUE, COND, TIMEOUT_US) \ + ( { \ + u64 timeout = TIMEOUT_US/100; \ + if(TIMEOUT_US%100!=0) \ + timeout++; \ + for(;;) { \ + VALUE = IO_func(ADDR); \ + if(COND) \ + break; \ + else { \ + usleep(100); \ + timeout--; \ + if(timeout==0) \ + break; \ + } \ + } \ + (timeout>0) ? 0 : -1; \ + } ) + +void usleep(unsigned long useconds); +void sleep(unsigned int seconds); +int usleep_R5(unsigned long useconds); +unsigned sleep_R5(unsigned int seconds); +int usleep_MB(unsigned long useconds); +unsigned sleep_MB(unsigned int seconds); +int usleep_A53(unsigned long useconds); +unsigned sleep_A53(unsigned int seconds); +int usleep_A9(unsigned long useconds); +unsigned sleep_A9(unsigned int seconds); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/smc.h b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/smc.h new file mode 100644 index 0000000..f7cc91c --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/smc.h @@ -0,0 +1,110 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file smc.h +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- ---------------------------------------------------
+* 1.00a sdm  11/03/09 Initial release.
+* 4.2	pkp	 08/04/14 Removed function definition of XSmc_NorInit and XSmc_NorInit
+*					  as smc.c is removed
+* 
+* +* @note None. +* +******************************************************************************/ + +#ifndef SMC_H /* prevent circular inclusions */ +#define SMC_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xparameters.h" +#include "xil_io.h" + +/***************** Macros (Inline Functions) Definitions *********************/ + +/**************************** Type Definitions *******************************/ + +/************************** Constant Definitions *****************************/ + +/* Memory controller configuration register offset */ +#define XSMCPSS_MC_STATUS 0x000U /* Controller status reg, RO */ +#define XSMCPSS_MC_INTERFACE_CONFIG 0x004U /* Interface config reg, RO */ +#define XSMCPSS_MC_SET_CONFIG 0x008U /* Set configuration reg, WO */ +#define XSMCPSS_MC_CLR_CONFIG 0x00CU /* Clear config reg, WO */ +#define XSMCPSS_MC_DIRECT_CMD 0x010U /* Direct command reg, WO */ +#define XSMCPSS_MC_SET_CYCLES 0x014U /* Set cycles register, WO */ +#define XSMCPSS_MC_SET_OPMODE 0x018U /* Set opmode register, WO */ +#define XSMCPSS_MC_REFRESH_PERIOD_0 0x020U /* Refresh period_0 reg, RW */ +#define XSMCPSS_MC_REFRESH_PERIOD_1 0x024U /* Refresh period_1 reg, RW */ + +/* Chip select configuration register offset */ +#define XSMCPSS_CS_IF0_CHIP_0_OFFSET 0x100U /* Interface 0 chip 0 config */ +#define XSMCPSS_CS_IF0_CHIP_1_OFFSET 0x120U /* Interface 0 chip 1 config */ +#define XSMCPSS_CS_IF0_CHIP_2_OFFSET 0x140U /* Interface 0 chip 2 config */ +#define XSMCPSS_CS_IF0_CHIP_3_OFFSET 0x160U /* Interface 0 chip 3 config */ +#define XSMCPSS_CS_IF1_CHIP_0_OFFSET 0x180U /* Interface 1 chip 0 config */ +#define XSMCPSS_CS_IF1_CHIP_1_OFFSET 0x1A0U /* Interface 1 chip 1 config */ +#define XSMCPSS_CS_IF1_CHIP_2_OFFSET 0x1C0U /* Interface 1 chip 2 config */ +#define XSMCPSS_CS_IF1_CHIP_3_OFFSET 0x1E0U /* Interface 1 chip 3 config */ + +/* User configuration register offset */ +#define XSMCPSS_UC_STATUS_OFFSET 0x200U /* User status reg, RO */ +#define XSMCPSS_UC_CONFIG_OFFSET 0x204U /* User config reg, WO */ + +/* Integration test register offset */ +#define XSMCPSS_IT_OFFSET 0xE00U + +/* ID configuration register offset */ +#define XSMCPSS_ID_PERIP_0_OFFSET 0xFE0U +#define XSMCPSS_ID_PERIP_1_OFFSET 0xFE4U +#define XSMCPSS_ID_PERIP_2_OFFSET 0xFE8U +#define XSMCPSS_ID_PERIP_3_OFFSET 0xFECU +#define XSMCPSS_ID_PCELL_0_OFFSET 0xFF0U +#define XSMCPSS_ID_PCELL_1_OFFSET 0xFF4U +#define XSMCPSS_ID_PCELL_2_OFFSET 0xFF8U +#define XSMCPSS_ID_PCELL_3_OFFSET 0xFFCU + +/************************** Variable Definitions *****************************/ + +/************************** Function Prototypes ******************************/ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* SMC_H */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/translation_table.S b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/translation_table.S new file mode 100644 index 0000000..418ded8 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/translation_table.S @@ -0,0 +1,226 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file translation_table.s +* +* @addtogroup a9_boot_code +* @{ +*

translation_table.S

+* translation_table.S contains a static page table required by MMU for +* cortex-A9. This translation table is flat mapped (input address = output +* address) with default memory attributes defined for zynq architecture. It +* utilizes short descriptor translation table format with each section defining +* 1MB of memory. +* +* The overview of translation table memory attributes is described below. +* +*| | Memory Range | Definition in Translation Table | +*|-----------------------|-------------------------|-----------------------------------| +*| DDR | 0x00000000 - 0x3FFFFFFF | Normal write-back Cacheable | +*| PL | 0x40000000 - 0xBFFFFFFF | Strongly Ordered | +*| Reserved | 0xC0000000 - 0xDFFFFFFF | Unassigned | +*| Memory mapped devices | 0xE0000000 - 0xE02FFFFF | Device Memory | +*| Reserved | 0xE0300000 - 0xE0FFFFFF | Unassigned | +*| NAND, NOR | 0xE1000000 - 0xE3FFFFFF | Device memory | +*| SRAM | 0xE4000000 - 0xE5FFFFFF | Normal write-back Cacheable | +*| Reserved | 0xE6000000 - 0xF7FFFFFF | Unassigned | +*| AMBA APB Peripherals | 0xF8000000 - 0xF8FFFFFF | Device Memory | +*| Reserved | 0xF9000000 - 0xFBFFFFFF | Unassigned | +*| Linear QSPI - XIP | 0xFC000000 - 0xFDFFFFFF | Normal write-through cacheable | +*| Reserved | 0xFE000000 - 0xFFEFFFFF | Unassigned | +*| OCM | 0xFFF00000 - 0xFFFFFFFF | Normal inner write-back cacheable | +* +* @note +* +* For region 0x00000000 - 0x3FFFFFFF, a system where DDR is less than 1GB, +* region after DDR and before PL is marked as undefined/reserved in translation +* table. In 0xF8000000 - 0xF8FFFFFF, 0xF8000C00 - 0xF8000FFF, 0xF8010000 - +* 0xF88FFFFF and 0xF8F03000 to 0xF8FFFFFF are reserved but due to granual size +* of 1MB, it is not possible to define separate regions for them. For region +* 0xFFF00000 - 0xFFFFFFFF, 0xFFF00000 to 0xFFFB0000 is reserved but due to 1MB +* granual size, it is not possible to define separate region for it +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- ---------------------------------------------------
+* 1.00a ecm  10/20/09 Initial version
+* 3.04a sdm  01/13/12 Updated MMU table to mark DDR memory as Shareable
+* 3.07a sgd  07/05/2012 Configuring device address spaces as shareable device
+*		       instead of strongly-ordered.
+* 3.07a asa  07/17/2012 Changed the property of the ".mmu_tbl" section.
+* 4.2	pkp  09/02/2014 added entries for 0xfe000000 to 0xffefffff as reserved
+*			and  0xe0000000 - 0xe1ffffff is broken down into
+*			0xe0000000 - 0xe02fffff (memory mapped devides)
+*			0xe0300000 - 0xe0ffffff (reserved) and
+*			0xe1000000 - 0xe1ffffff (NAND)
+* 5.2	pkp  06/08/2015 put a check for XPAR_PS7_DDR_0_S_AXI_BASEADDR to confirm
+*			if DDR is present or not and accordingly generate the
+*			translation table
+* 6.1	pkp  07/11/2016 Corrected comments for memory attributes
+* 6.8   mus  07/12/2018 Mark DDR memory as inner cacheable, if BSP is built
+*			with the USE_AMP flag.
+* 
+* +* +******************************************************************************/ +#include "xparameters.h" + .globl MMUTable + + .section .mmu_tbl,"a" + +MMUTable: + /* Each table entry occupies one 32-bit word and there are + * 4096 entries, so the entire table takes up 16KB. + * Each entry covers a 1MB section. + */ +.set SECT, 0 + +#ifdef XPAR_PS7_DDR_0_S_AXI_BASEADDR +.set DDR_START, XPAR_PS7_DDR_0_S_AXI_BASEADDR +.set DDR_END, XPAR_PS7_DDR_0_S_AXI_HIGHADDR +.set DDR_SIZE, (DDR_END - DDR_START)+1 +.set DDR_REG, DDR_SIZE/0x100000 +#else +.set DDR_REG, 0 +#endif + +.set UNDEF_REG, 0x3FF - DDR_REG + +#ifndef USE_AMP + /*0x00000000 - 0x00100000 (inner and outer cacheable )*/ +.word SECT + 0x15de6 /* S=b1 TEX=b101 AP=b11, Domain=b1111, C=b0, B=b1 */ +#else + /*0x00000000 - 0x00100000 (inner cacheable )*/ +.word SECT + 0x14de6 /* S=b1 TEX=b100 AP=b11, Domain=b1111, C=b0, B=b1 */ +#endif +.set SECT, SECT+0x100000 + +.rept DDR_REG /* (DDR Cacheable) */ +.word SECT + 0x15de6 /* S=b1 TEX=b101 AP=b11, Domain=b1111, C=b0, B=b1 */ +.set SECT, SECT+0x100000 +.endr + +.rept UNDEF_REG /* (unassigned/reserved). + * Generates a translation fault if accessed */ +.word SECT + 0x0 /* S=b0 TEX=b000 AP=b00, Domain=b0, C=b0, B=b0 */ +.set SECT, SECT+0x100000 +.endr + + +.rept 0x0400 /* 0x40000000 - 0x7fffffff (FPGA slave0) */ +.word SECT + 0xc02 /* S=b0 TEX=b000 AP=b11, Domain=b0, C=b0, B=b0 */ +.set SECT, SECT+0x100000 +.endr + +.rept 0x0400 /* 0x80000000 - 0xbfffffff (FPGA slave1) */ +.word SECT + 0xc02 /* S=b0 TEX=b000 AP=b11, Domain=b0, C=b0, B=b0 */ +.set SECT, SECT+0x100000 +.endr + +.rept 0x0200 /* 0xc0000000 - 0xdfffffff (unassigned/reserved). + * Generates a translation fault if accessed */ +.word SECT + 0x0 /* S=b0 TEX=b000 AP=b00, Domain=b0, C=b0, B=b0 */ +.set SECT, SECT+0x100000 +.endr + +.rept 0x003 /* 0xe0000000 - 0xe02fffff (Memory mapped devices) + * UART/USB/IIC/SPI/CAN/GEM/GPIO/QSPI/SD/NAND */ +.word SECT + 0xc06 /* S=b0 TEX=b000 AP=b11, Domain=b0, C=b0, B=b1 */ +.set SECT, SECT+0x100000 +.endr + +.rept 0x0D /* 0xe0300000 - 0xe0ffffff (unassigned/reserved). + * Generates a translation fault if accessed */ +.word SECT + 0x0 /* S=b0 TEX=b000 AP=b00, Domain=b0, C=b0, B=b0 */ +.set SECT, SECT+0x100000 +.endr + +.rept 0x0010 /* 0xe1000000 - 0xe1ffffff (NAND) */ +.word SECT + 0xc06 /* S=b0 TEX=b000 AP=b11, Domain=b0, C=b0, B=b1 */ +.set SECT, SECT+0x100000 +.endr + +.rept 0x0020 /* 0xe2000000 - 0xe3ffffff (NOR) */ +.word SECT + 0xc06 /* S=b0 TEX=b000 AP=b11, Domain=b0, C=b0, B=b1 */ +.set SECT, SECT+0x100000 +.endr + +.rept 0x0020 /* 0xe4000000 - 0xe5ffffff (SRAM) */ +.word SECT + 0xc0e /* S=b0 TEX=b000 AP=b11, Domain=b0, C=b1, B=b1 */ +.set SECT, SECT+0x100000 +.endr + +.rept 0x0120 /* 0xe6000000 - 0xf7ffffff (unassigned/reserved). + * Generates a translation fault if accessed */ +.word SECT + 0x0 /* S=b0 TEX=b000 AP=b00, Domain=b0, C=b0, B=b0 */ +.set SECT, SECT+0x100000 +.endr + +/* 0xf8000c00 to 0xf8000fff, 0xf8010000 to 0xf88fffff and + 0xf8f03000 to 0xf8ffffff are reserved but due to granual size of + 1MB, it is not possible to define separate regions for them */ + +.rept 0x0010 /* 0xf8000000 - 0xf8ffffff (AMBA APB Peripherals) */ + +.word SECT + 0xc06 /* S=b0 TEX=b000 AP=b11, Domain=b0, C=b0, B=b1 */ +.set SECT, SECT+0x100000 +.endr + +.rept 0x0030 /* 0xf9000000 - 0xfbffffff (unassigned/reserved). + * Generates a translation fault if accessed */ +.word SECT + 0x0 /* S=b0 TEX=b000 AP=b00, Domain=b0, C=b0, B=b0 */ +.set SECT, SECT+0x100000 +.endr + +.rept 0x0020 /* 0xfc000000 - 0xfdffffff (Linear QSPI - XIP) */ +.word SECT + 0xc0a /* S=b0 TEX=b000 AP=b11, Domain=b0, C=b1, B=b0 */ +.set SECT, SECT+0x100000 +.endr + +.rept 0x001F /* 0xfe000000 - 0xffefffff (unassigned/reserved). + * Generates a translation fault if accessed */ +.word SECT + 0x0 /* S=b0 TEX=b000 AP=b00, Domain=b0, C=b0, B=b0 */ +.set SECT, SECT+0x100000 +.endr + +/* 0xfff00000 to 0xfffb0000 is reserved but due to granual size of + 1MB, it is not possible to define separate region for it + + 0xfff00000 - 0xffffffff + 256K OCM when mapped to high address space + inner-cacheable */ +.word SECT + 0x4c0e /* S=b0 TEX=b100 AP=b11, Domain=b0, C=b1, B=b1 */ +.set SECT, SECT+0x100000 + +.end +/** +* @} End of "addtogroup a9_boot_code". +*/ \ No newline at end of file diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/unlink.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/unlink.c new file mode 100644 index 0000000..abd0d87 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/unlink.c @@ -0,0 +1,46 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +#include +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { + __attribute__((weak)) sint32 unlink(char8 *path); +} +#endif +/* + * unlink -- since we have no file system, + * we just return an error. + */ +__attribute__((weak)) sint32 unlink(char8 *path) +{ + (void) path; + errno = EIO; + return (-1); +} diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/usleep.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/usleep.c new file mode 100644 index 0000000..0965233 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/usleep.c @@ -0,0 +1,103 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2017 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file usleep.c +* +* This function provides a microsecond delay using the Global Timer register in +* the ARM Cortex A9 MP core. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 1.00a ecm/sdm  11/11/09 First release
+* 3.07a sgd      07/05/12 Upadted micro sleep function to make use Global Timer
+* 4.2	pkp		 08/04/14 Removed unimplemented nanosleep routine as it is not
+*						  possible to generate timer in nanosecond due to
+*						  limited cpu frequency
+* 6.0   asa      08/15/16 Updated the usleep signature. Fix for CR#956899.
+* 6.6	srm	 10/18/17 Updated sleep routines to support user configurable
+*			  implementation. Now sleep routines will use Timer
+*                         specified by the user (i.e. Global timer/TTC timer)
+* 
+* +******************************************************************************/ +/***************************** Include Files *********************************/ + +#include "sleep.h" +#include "xtime_l.h" +#include "xparameters.h" +#include "xil_types.h" +#include "xpseudo_asm.h" +#include "xreg_cortexa9.h" + +#if defined (SLEEP_TIMER_BASEADDR) +#include "xil_sleeptimer.h" +#endif + +/**************************** Constant Definitions ************************/ +#if defined (SLEEP_TIMER_BASEADDR) +#define COUNTS_PER_USECOND (SLEEP_TIMER_FREQUENCY / 1000000) +#else +/* Global Timer is always clocked at half of the CPU frequency */ +#define COUNTS_PER_USECOND (XPAR_CPU_CORTEXA9_CORE_CLOCK_FREQ_HZ / (2U*1000000U)) +#endif + +/*****************************************************************************/ +/** +* +* This API gives a delay in microseconds +* +* @param useconds requested +* +* @return 0 if the delay can be achieved, -1 if the requested delay +* is out of range +* +* @note None. +* +****************************************************************************/ +int usleep_A9(unsigned long useconds) +{ +#if defined (SLEEP_TIMER_BASEADDR) + Xil_SleepTTCCommon(useconds, COUNTS_PER_USECOND); +#else + XTime tEnd, tCur; + + XTime_GetTime(&tCur); + tEnd = tCur + (((XTime) useconds) * COUNTS_PER_USECOND); + do + { + XTime_GetTime(&tCur); + } while (tCur < tEnd); +#endif + + return 0; +} diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/vectors.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/vectors.c new file mode 100644 index 0000000..2e23fc9 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/vectors.c @@ -0,0 +1,227 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2016 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file vectors.c +* +* This file contains the C level vectors for the ARM Cortex A9 core. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- ---------------------------------------------------
+* 1.00a ecm  10/20/09 Initial version, moved over from bsp area
+* 6.0   mus  27/07/16 Consolidated vectors for a53,a9 and r5 processor
+*                     and added UndefinedException for a53 32 bit and r5
+*                     processor
+* 
+* +* @note +* +* None. +* +******************************************************************************/ +/***************************** Include Files *********************************/ + +#include "xil_exception.h" +#include "vectors.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +typedef struct { + Xil_ExceptionHandler Handler; + void *Data; +} XExc_VectorTableEntry; + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Variable Definitions *****************************/ + +extern XExc_VectorTableEntry XExc_VectorTable[]; + +/************************** Function Prototypes ******************************/ + + +/*****************************************************************************/ +/** +* +* This is the C level wrapper for the FIQ interrupt called from the vectors.s +* file. +* +* @param None. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void FIQInterrupt(void) +{ + XExc_VectorTable[XIL_EXCEPTION_ID_FIQ_INT].Handler(XExc_VectorTable[ + XIL_EXCEPTION_ID_FIQ_INT].Data); +} + +/*****************************************************************************/ +/** +* +* This is the C level wrapper for the IRQ interrupt called from the vectors.s +* file. +* +* @param None. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void IRQInterrupt(void) +{ + XExc_VectorTable[XIL_EXCEPTION_ID_IRQ_INT].Handler(XExc_VectorTable[ + XIL_EXCEPTION_ID_IRQ_INT].Data); +} + +#if !defined (__aarch64__) +/*****************************************************************************/ +/** +* +* This is the C level wrapper for the Undefined exception called from the +* vectors.s file. +* +* @param None. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void UndefinedException(void) +{ + XExc_VectorTable[XIL_EXCEPTION_ID_UNDEFINED_INT].Handler(XExc_VectorTable[ + XIL_EXCEPTION_ID_UNDEFINED_INT].Data); +} + +/*****************************************************************************/ +/** +* +* This is the C level wrapper for the SW Interrupt called from the vectors.s +* file. +* +* @param None. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void SWInterrupt(void) +{ + XExc_VectorTable[XIL_EXCEPTION_ID_SWI_INT].Handler(XExc_VectorTable[ + XIL_EXCEPTION_ID_SWI_INT].Data); +} + +/*****************************************************************************/ +/** +* +* This is the C level wrapper for the DataAbort Interrupt called from the +* vectors.s file. +* +* @param None. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void DataAbortInterrupt(void) +{ + XExc_VectorTable[XIL_EXCEPTION_ID_DATA_ABORT_INT].Handler( + XExc_VectorTable[XIL_EXCEPTION_ID_DATA_ABORT_INT].Data); +} + +/*****************************************************************************/ +/** +* +* This is the C level wrapper for the PrefetchAbort Interrupt called from the +* vectors.s file. +* +* @param None. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void PrefetchAbortInterrupt(void) +{ + XExc_VectorTable[XIL_EXCEPTION_ID_PREFETCH_ABORT_INT].Handler( + XExc_VectorTable[XIL_EXCEPTION_ID_PREFETCH_ABORT_INT].Data); +} +#else + +/*****************************************************************************/ +/** +* +* This is the C level wrapper for the Synchronous Interrupt called from the vectors.s +* file. +* +* @param None. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void SynchronousInterrupt(void) +{ + XExc_VectorTable[XIL_EXCEPTION_ID_SYNC_INT].Handler(XExc_VectorTable[ + XIL_EXCEPTION_ID_SYNC_INT].Data); +} + +/*****************************************************************************/ +/** +* +* This is the C level wrapper for the SError Interrupt called from the +* vectors.s file. +* +* @param None. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void SErrorInterrupt(void) +{ + XExc_VectorTable[XIL_EXCEPTION_ID_SERROR_ABORT_INT].Handler( + XExc_VectorTable[XIL_EXCEPTION_ID_SERROR_ABORT_INT].Data); +} + +#endif diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/vectors.h b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/vectors.h new file mode 100644 index 0000000..56bacbc --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/vectors.h @@ -0,0 +1,84 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2016 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file vectors.h +* +* This file contains the C level vector prototypes for the ARM Cortex A9 core. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- ---------------------------------------------------
+* 1.00a ecm  10/20/10 Initial version, moved over from bsp area
+* 6.0   mus  07/27/16 Consolidated vectors for a9,a53 and r5 processors
+* 
+* +* @note +* +* None. +* +******************************************************************************/ + +#ifndef _VECTORS_H_ +#define _VECTORS_H_ + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" + +#ifdef __cplusplus +extern "C" { +#endif +/***************** Macros (Inline Functions) Definitions *********************/ + +/**************************** Type Definitions *******************************/ + +/************************** Constant Definitions *****************************/ + +/************************** Function Prototypes ******************************/ + +void FIQInterrupt(void); +void IRQInterrupt(void); +#if !defined (__aarch64__) +void SWInterrupt(void); +void DataAbortInterrupt(void); +void PrefetchAbortInterrupt(void); +void UndefinedException(void); +#else +void SynchronousInterrupt(void); +void SErrorInterrupt(void); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* protection macro */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/write.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/write.c new file mode 100644 index 0000000..dc10ed7 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/write.c @@ -0,0 +1,117 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +/* write.c -- write bytes to an output device. + */ +#ifndef UNDEFINE_FILE_OPS +#include "xil_printf.h" +#include "xparameters.h" + +#ifdef __cplusplus +extern "C" { + __attribute__((weak)) sint32 _write (sint32 fd, char8* buf, sint32 nbytes); +} +#endif + +/* + * write -- write bytes to the serial port. Ignore fd, since + * stdout and stderr are the same. Since we have no filesystem, + * open will only return an error. + */ +__attribute__((weak)) sint32 +write (sint32 fd, char8* buf, sint32 nbytes) + +{ +#ifdef STDOUT_BASEADDRESS + s32 i; + char8* LocalBuf = buf; + + (void)fd; + for (i = 0; i < nbytes; i++) { + if(LocalBuf != NULL) { + LocalBuf += i; + } + if(LocalBuf != NULL) { + if (*LocalBuf == '\n') { + outbyte ('\r'); + } + outbyte (*LocalBuf); + } + if(LocalBuf != NULL) { + LocalBuf -= i; + } + } + return (nbytes); +#else + (void)fd; + (void)buf; + (void)nbytes; + return 0; +#endif +} + +__attribute__((weak)) sint32 +_write (sint32 fd, char8* buf, sint32 nbytes) +{ +#if HYP_GUEST && EL1_NONSECURE && XEN_USE_PV_CONSOLE + sint32 length; + + (void)fd; + (void)nbytes; + length = XPVXenConsole_Write(buf); + return length; +#else +#ifdef STDOUT_BASEADDRESS + s32 i; + char8* LocalBuf = buf; + + (void)fd; + for (i = 0; i < nbytes; i++) { + if(LocalBuf != NULL) { + LocalBuf += i; + } + if(LocalBuf != NULL) { + if (*LocalBuf == '\n') { + outbyte ('\r'); + } + outbyte (*LocalBuf); + } + if(LocalBuf != NULL) { + LocalBuf -= i; + } + } + return (nbytes); +#else + (void)fd; + (void)buf; + (void)nbytes; + return 0; +#endif +#endif +} +#endif diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xbasic_types.h b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xbasic_types.h new file mode 100644 index 0000000..2d9b245 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xbasic_types.h @@ -0,0 +1,127 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xbasic_types.h +* +* +* @note Dummy File for backwards compatibility +* + +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date   Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a adk   1/31/14  Added in bsp common folder for backward compatibility
+* 7.0   aru   01/21/19 Modified the typedef of u32,u16,u8
+* 7.0 	aru   02/06/19 Included stdint.h and stddef.h
+* 
+* +******************************************************************************/ + +#ifndef XBASIC_TYPES_H /* prevent circular inclusions */ +#define XBASIC_TYPES_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +/** @name Legacy types + * Deprecated legacy types. + * @{ + */ +typedef uint8_t Xuint8; /**< unsigned 8-bit */ +typedef char Xint8; /**< signed 8-bit */ +typedef uint16_t Xuint16; /**< unsigned 16-bit */ +typedef short Xint16; /**< signed 16-bit */ +typedef uint32_t Xuint32; /**< unsigned 32-bit */ +typedef long Xint32; /**< signed 32-bit */ +typedef float Xfloat32; /**< 32-bit floating point */ +typedef double Xfloat64; /**< 64-bit double precision FP */ +typedef unsigned long Xboolean; /**< boolean (XTRUE or XFALSE) */ + +#if !defined __XUINT64__ +typedef struct +{ + Xuint32 Upper; + Xuint32 Lower; +} Xuint64; +#endif + +/** @name New types + * New simple types. + * @{ + */ +#ifndef __KERNEL__ +#ifndef XIL_TYPES_H +typedef Xuint32 u32; +typedef Xuint16 u16; +typedef Xuint8 u8; +#endif +#else +#include +#endif + +#ifndef TRUE +# define TRUE 1U +#endif + +#ifndef FALSE +# define FALSE 0U +#endif + +#ifndef NULL +#define NULL 0U +#endif + +/* + * Xilinx NULL, TRUE and FALSE legacy support. Deprecated. + * Please use NULL, TRUE and FALSE + */ +#define XNULL NULL +#define XTRUE TRUE +#define XFALSE FALSE + +/* + * This file is deprecated and users + * should use xil_types.h and xil_assert.h\n\r + */ +#warning The xbasics_type.h file is deprecated and users should use xil_types.h and xil_assert. +#warning Please refer the Standalone BSP UG647 for further details + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xdebug.h b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xdebug.h new file mode 100644 index 0000000..b09c02d --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xdebug.h @@ -0,0 +1,40 @@ +#ifndef XDEBUG /* prevent circular inclusions */ +#define XDEBUG /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(DEBUG) && !defined(NDEBUG) + +#ifndef XDEBUG_WARNING +#define XDEBUG_WARNING +#warning DEBUG is enabled +#endif + +int printf(const char *format, ...); + +#define XDBG_DEBUG_ERROR 0x00000001U /* error condition messages */ +#define XDBG_DEBUG_GENERAL 0x00000002U /* general debug messages */ +#define XDBG_DEBUG_ALL 0xFFFFFFFFU /* all debugging data */ + +#define xdbg_current_types (XDBG_DEBUG_GENERAL) + +#define xdbg_stmnt(x) x + +#define xdbg_printf(type, ...) (((type) & xdbg_current_types) ? printf (__VA_ARGS__) : 0) + + +#else /* defined(DEBUG) && !defined(NDEBUG) */ + +#define xdbg_stmnt(x) + +#define xdbg_printf(...) + +#endif /* defined(DEBUG) && !defined(NDEBUG) */ + +#ifdef __cplusplus +} +#endif + +#endif /* XDEBUG */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xenv.h b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xenv.h new file mode 100644 index 0000000..9c7c4c3 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xenv.h @@ -0,0 +1,183 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xenv.h +* +* Defines common services that are typically found in a host operating. +* environment. This include file simply includes an OS specific file based +* on the compile-time constant BUILD_ENV_*, where * is the name of the target +* environment. +* +* All services are defined as macros. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00b ch   10/24/02 Added XENV_LINUX
+* 1.00a rmm  04/17/02 First release
+* 
+* +******************************************************************************/ + +#ifndef XENV_H /* prevent circular inclusions */ +#define XENV_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Select which target environment we are operating under + */ + +/* VxWorks target environment */ +#if defined XENV_VXWORKS +#include "xenv_vxworks.h" + +/* Linux target environment */ +#elif defined XENV_LINUX +#include "xenv_linux.h" + +/* Unit test environment */ +#elif defined XENV_UNITTEST +#include "ut_xenv.h" + +/* Integration test environment */ +#elif defined XENV_INTTEST +#include "int_xenv.h" + +/* Standalone environment selected */ +#else +#include "xenv_standalone.h" +#endif + + +/* + * The following comments specify the types and macro wrappers that are + * expected to be defined by the target specific header files + */ + +/**************************** Type Definitions *******************************/ + +/*****************************************************************************/ +/** + * + * XENV_TIME_STAMP + * + * A structure that contains a time stamp used by other time stamp macros + * defined below. This structure is processor dependent. + */ + + +/***************** Macros (Inline Functions) Definitions *********************/ + +/*****************************************************************************/ +/** + * + * XENV_MEM_COPY(void *DestPtr, void *SrcPtr, unsigned Bytes) + * + * Copies a non-overlapping block of memory. + * + * @param DestPtr is the destination address to copy data to. + * @param SrcPtr is the source address to copy data from. + * @param Bytes is the number of bytes to copy. + * + * @return None + */ + +/*****************************************************************************/ +/** + * + * XENV_MEM_FILL(void *DestPtr, char Data, unsigned Bytes) + * + * Fills an area of memory with constant data. + * + * @param DestPtr is the destination address to set. + * @param Data contains the value to set. + * @param Bytes is the number of bytes to set. + * + * @return None + */ +/*****************************************************************************/ +/** + * + * XENV_TIME_STAMP_GET(XTIME_STAMP *StampPtr) + * + * Samples the processor's or external timer's time base counter. + * + * @param StampPtr is the storage for the retrieved time stamp. + * + * @return None + */ + +/*****************************************************************************/ +/** + * + * XENV_TIME_STAMP_DELTA_US(XTIME_STAMP *Stamp1Ptr, XTIME_STAMP* Stamp2Ptr) + * + * Computes the delta between the two time stamps. + * + * @param Stamp1Ptr - First sampled time stamp. + * @param Stamp1Ptr - Sedond sampled time stamp. + * + * @return An unsigned int value with units of microseconds. + */ + +/*****************************************************************************/ +/** + * + * XENV_TIME_STAMP_DELTA_MS(XTIME_STAMP *Stamp1Ptr, XTIME_STAMP* Stamp2Ptr) + * + * Computes the delta between the two time stamps. + * + * @param Stamp1Ptr - First sampled time stamp. + * @param Stamp1Ptr - Sedond sampled time stamp. + * + * @return An unsigned int value with units of milliseconds. + */ + +/*****************************************************************************//** + * + * XENV_USLEEP(unsigned delay) + * + * Delay the specified number of microseconds. + * + * @param delay is the number of microseconds to delay. + * + * @return None + */ + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xenv_standalone.h b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xenv_standalone.h new file mode 100644 index 0000000..ef905af --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xenv_standalone.h @@ -0,0 +1,364 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xenv_standalone.h +* +* Defines common services specified by xenv.h. +* +* @note +* This file is not intended to be included directly by driver code. +* Instead, the generic xenv.h file is intended to be included by driver +* code. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a wgr  02/28/07 Added cache handling macros.
+* 1.00a wgr  02/27/07 Simplified code. Deprecated old-style macro names.
+* 1.00a rmm  01/24/06 Implemented XENV_USLEEP. Assume implementation is being
+*                     used under Xilinx standalone BSP.
+* 1.00a xd   11/03/04 Improved support for doxygen.
+* 1.00a rmm  03/21/02 First release
+* 1.00a wgr  03/22/07 Converted to new coding style.
+* 1.00a rpm  06/29/07 Added udelay macro for standalone
+* 1.00a xd   07/19/07 Included xparameters.h as XPAR_ constants are referred
+*                     to in MICROBLAZE section
+* 1.00a ecm  09/19/08 updated for v7.20 of Microblaze, new functionality
+*
+* 
+* +* +******************************************************************************/ + +#ifndef XENV_STANDALONE_H +#define XENV_STANDALONE_H + +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ +/****************************************************************************** + * + * Get the processor dependent includes + * + ******************************************************************************/ + +#include + +#if defined __MICROBLAZE__ +# include "mb_interface.h" +# include "xparameters.h" /* XPAR constants used below in MB section */ + +#elif defined __PPC__ +# include "sleep.h" +# include "xcache_l.h" /* also include xcache_l.h for caching macros */ +#endif + +/****************************************************************************** + * + * MEMCPY / MEMSET related macros. + * + * The following are straight forward implementations of memset and memcpy. + * + * NOTE: memcpy may not work if source and target memory area are overlapping. + * + ******************************************************************************/ +/*****************************************************************************/ +/** + * + * Copies a non-overlapping block of memory. + * + * @param DestPtr + * Destination address to copy data to. + * + * @param SrcPtr + * Source address to copy data from. + * + * @param Bytes + * Number of bytes to copy. + * + * @return None. + * + * @note + * The use of XENV_MEM_COPY is deprecated. Use memcpy() instead. + * + * @note + * This implemention MAY BREAK work if source and target memory + * area are overlapping. + * + *****************************************************************************/ + +#define XENV_MEM_COPY(DestPtr, SrcPtr, Bytes) \ + memcpy((void *) DestPtr, (const void *) SrcPtr, (size_t) Bytes) + + + +/*****************************************************************************/ +/** + * + * Fills an area of memory with constant data. + * + * @param DestPtr + * Destination address to copy data to. + * + * @param Data + * Value to set. + * + * @param Bytes + * Number of bytes to copy. + * + * @return None. + * + * @note + * The use of XENV_MEM_FILL is deprecated. Use memset() instead. + * + *****************************************************************************/ + +#define XENV_MEM_FILL(DestPtr, Data, Bytes) \ + memset((void *) DestPtr, (s32) Data, (size_t) Bytes) + + + +/****************************************************************************** + * + * TIME related macros + * + ******************************************************************************/ + +/** + * A structure that contains a time stamp used by other time stamp macros + * defined below. This structure is processor dependent. + */ +typedef s32 XENV_TIME_STAMP; + +/*****************************************************************************/ +/** + * + * Time is derived from the 64 bit PPC timebase register + * + * @param StampPtr is the storage for the retrieved time stamp. + * + * @return None. + * + * @note + * + * Signature: void XENV_TIME_STAMP_GET(XTIME_STAMP *StampPtr) + *

+ * This macro must be implemented by the user. + * + *****************************************************************************/ +#define XENV_TIME_STAMP_GET(StampPtr) + +/*****************************************************************************/ +/** + * + * This macro is not yet implemented and always returns 0. + * + * @param Stamp1Ptr is the first sampled time stamp. + * @param Stamp2Ptr is the second sampled time stamp. + * + * @return 0 + * + * @note + * + * This macro must be implemented by the user. + * + *****************************************************************************/ +#define XENV_TIME_STAMP_DELTA_US(Stamp1Ptr, Stamp2Ptr) (0) + +/*****************************************************************************/ +/** + * + * This macro is not yet implemented and always returns 0. + * + * @param Stamp1Ptr is the first sampled time stamp. + * @param Stamp2Ptr is the second sampled time stamp. + * + * @return 0 + * + * @note + * + * This macro must be implemented by the user. + * + *****************************************************************************/ +#define XENV_TIME_STAMP_DELTA_MS(Stamp1Ptr, Stamp2Ptr) (0) + +/*****************************************************************************/ +/** + * XENV_USLEEP(unsigned delay) + * + * Delay the specified number of microseconds. Not implemented without OS + * support. + * + * @param delay + * Number of microseconds to delay. + * + * @return None. + * + *****************************************************************************/ + +#ifdef __PPC__ +#define XENV_USLEEP(delay) usleep(delay) +#define udelay(delay) usleep(delay) +#else +#define XENV_USLEEP(delay) +#define udelay(delay) +#endif + + +/****************************************************************************** + * + * CACHE handling macros / mappings + * + ******************************************************************************/ +/****************************************************************************** + * + * Processor independent macros + * + ******************************************************************************/ + +#define XCACHE_ENABLE_CACHE() \ + { XCACHE_ENABLE_DCACHE(); XCACHE_ENABLE_ICACHE(); } + +#define XCACHE_DISABLE_CACHE() \ + { XCACHE_DISABLE_DCACHE(); XCACHE_DISABLE_ICACHE(); } + + +/****************************************************************************** + * + * MicroBlaze case + * + * NOTE: Currently the following macros will only work on systems that contain + * only ONE MicroBlaze processor. Also, the macros will only be enabled if the + * system is built using a xparameters.h file. + * + ******************************************************************************/ + +#if defined __MICROBLAZE__ + +/* Check if MicroBlaze data cache was built into the core. + */ +#if (XPAR_MICROBLAZE_USE_DCACHE == 1) +# define XCACHE_ENABLE_DCACHE() microblaze_enable_dcache() +# define XCACHE_DISABLE_DCACHE() microblaze_disable_dcache() +# define XCACHE_INVALIDATE_DCACHE() microblaze_invalidate_dcache() + +# define XCACHE_INVALIDATE_DCACHE_RANGE(Addr, Len) \ + microblaze_invalidate_dcache_range((s32)(Addr), (s32)(Len)) + +#if (XPAR_MICROBLAZE_DCACHE_USE_WRITEBACK == 1) +# define XCACHE_FLUSH_DCACHE() microblaze_flush_dcache() +# define XCACHE_FLUSH_DCACHE_RANGE(Addr, Len) \ + microblaze_flush_dcache_range((s32)(Addr), (s32)(Len)) +#else +# define XCACHE_FLUSH_DCACHE() microblaze_invalidate_dcache() +# define XCACHE_FLUSH_DCACHE_RANGE(Addr, Len) \ + microblaze_invalidate_dcache_range((s32)(Addr), (s32)(Len)) +#endif /*XPAR_MICROBLAZE_DCACHE_USE_WRITEBACK*/ + +#else +# define XCACHE_ENABLE_DCACHE() +# define XCACHE_DISABLE_DCACHE() +# define XCACHE_INVALIDATE_DCACHE_RANGE(Addr, Len) +# define XCACHE_FLUSH_DCACHE_RANGE(Addr, Len) +#endif /*XPAR_MICROBLAZE_USE_DCACHE*/ + + +/* Check if MicroBlaze instruction cache was built into the core. + */ +#if (XPAR_MICROBLAZE_USE_ICACHE == 1) +# define XCACHE_ENABLE_ICACHE() microblaze_enable_icache() +# define XCACHE_DISABLE_ICACHE() microblaze_disable_icache() + +# define XCACHE_INVALIDATE_ICACHE() microblaze_invalidate_icache() + +# define XCACHE_INVALIDATE_ICACHE_RANGE(Addr, Len) \ + microblaze_invalidate_icache_range((s32)(Addr), (s32)(Len)) + +#else +# define XCACHE_ENABLE_ICACHE() +# define XCACHE_DISABLE_ICACHE() +#endif /*XPAR_MICROBLAZE_USE_ICACHE*/ + + +/****************************************************************************** + * + * PowerPC case + * + * Note that the XCACHE_ENABLE_xxx functions are hardcoded to enable a + * specific memory region (0x80000001). Each bit (0-30) in the regions + * bitmask stands for 128MB of memory. Bit 31 stands for the upper 2GB + * range. + * + * regions --> cached address range + * ------------|-------------------------------------------------- + * 0x80000000 | [0, 0x7FFFFFF] + * 0x00000001 | [0xF8000000, 0xFFFFFFFF] + * 0x80000001 | [0, 0x7FFFFFF],[0xF8000000, 0xFFFFFFFF] + * + ******************************************************************************/ + +#elif defined __PPC__ + +#define XCACHE_ENABLE_DCACHE() XCache_EnableDCache(0x80000001) +#define XCACHE_DISABLE_DCACHE() XCache_DisableDCache() +#define XCACHE_ENABLE_ICACHE() XCache_EnableICache(0x80000001) +#define XCACHE_DISABLE_ICACHE() XCache_DisableICache() + +#define XCACHE_INVALIDATE_DCACHE_RANGE(Addr, Len) \ + XCache_InvalidateDCacheRange((u32)(Addr), (u32)(Len)) + +#define XCACHE_FLUSH_DCACHE_RANGE(Addr, Len) \ + XCache_FlushDCacheRange((u32)(Addr), (u32)(Len)) + +#define XCACHE_INVALIDATE_ICACHE() XCache_InvalidateICache() + + +/****************************************************************************** + * + * Unknown processor / architecture + * + ******************************************************************************/ + +#else +/* #error "Unknown processor / architecture. Must be MicroBlaze or PowerPC." */ +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* #ifndef XENV_STANDALONE_H */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil-crt0.S b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil-crt0.S new file mode 100644 index 0000000..8ea3a09 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil-crt0.S @@ -0,0 +1,155 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2017 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file xil-crt0.S +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- ---------------------------------------------------
+* 1.00a ecm  10/20/09 Initial version
+* 3.05a sdm  02/02/12 Added code for profiling
+* 3.06a sgd  05/16/12 Added global constructors and cleanup code
+*                     Uart initialization based on compiler flag
+* 3.07a sgd  07/05/12 Updated with reset and start Global Timer
+* 3.07a sgd  10/19/12 SMC NOR and SRAM initialization with build option
+* 4.2	pkp  08/04/14 Removed PEEP board related code which contained
+*		      initialization of uart smc nor and sram
+* 5.3	pkp  10/07/15 Added support for OpenAMP by not initializing global
+*		      timer when USE_AMP flag is defined
+* 6.6   srm  10/18/17 Added timer configuration using XTime_StartTTCTimer API.
+*		      Now the TTC instance as specified by the user will be
+*		      started.
+* 
+* +* @note +* +* None. +* +******************************************************************************/ +#include "bspconfig.h" + + .file "xil-crt0.S" + .section ".got2","aw" + .align 2 + + .text +.Lsbss_start: + .long __sbss_start + +.Lsbss_end: + .long __sbss_end + +.Lbss_start: + .long __bss_start + +.Lbss_end: + .long __bss_end + +.Lstack: + .long __stack + + + .globl _start +_start: + bl __cpu_init /* Initialize the CPU first (BSP provides this) */ + + mov r0, #0 + + /* clear sbss */ + ldr r1,.Lsbss_start /* calculate beginning of the SBSS */ + ldr r2,.Lsbss_end /* calculate end of the SBSS */ + +.Lloop_sbss: + cmp r1,r2 + bge .Lenclsbss /* If no SBSS, no clearing required */ + str r0, [r1], #4 + b .Lloop_sbss + +.Lenclsbss: + /* clear bss */ + ldr r1,.Lbss_start /* calculate beginning of the BSS */ + ldr r2,.Lbss_end /* calculate end of the BSS */ + +.Lloop_bss: + cmp r1,r2 + bge .Lenclbss /* If no BSS, no clearing required */ + str r0, [r1], #4 + b .Lloop_bss + +.Lenclbss: + + /* set stack pointer */ + ldr r13,.Lstack /* stack address */ + + /* Reset and start Global Timer */ + mov r0, #0x0 + mov r1, #0x0 + + /* Reset and start Triple Timer Counter */ + #if defined SLEEP_TIMER_BASEADDR + bl XTime_StartTTCTimer + #endif + +#if USE_AMP != 1 + bl XTime_SetTime +#endif + +#ifdef PROFILING /* defined in Makefile */ + /* Setup profiling stuff */ + bl _profile_init +#endif /* PROFILING */ + + /* run global constructors */ + bl __libc_init_array + + /* make sure argc and argv are valid */ + mov r0, #0 + mov r1, #0 + + /* Let her rip */ + bl main + + /* Cleanup global constructors */ + bl __libc_fini_array + +#ifdef PROFILING + /* Cleanup profiling stuff */ + bl _profile_clean +#endif /* PROFILING */ + + /* All done */ + bl exit + +.Lexit: /* should never get here */ + b .Lexit + +.Lstart: + .size _start,.Lstart-_start diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_assert.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_assert.c new file mode 100644 index 0000000..f6ec066 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_assert.c @@ -0,0 +1,143 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2016 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_assert.c +* +* This file contains basic assert related functions for Xilinx software IP. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date   Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a hbm  07/14/09 Initial release
+* 6.0   kvn  05/31/16 Make Xil_AsserWait a global variable
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Variable Definitions *****************************/ + +/** + * This variable allows testing to be done easier with asserts. An assert + * sets this variable such that a driver can evaluate this variable + * to determine if an assert occurred. + */ +u32 Xil_AssertStatus; + +/** + * This variable allows the assert functionality to be changed for testing + * such that it does not wait infinitely. Use the debugger to disable the + * waiting during testing of asserts. + */ +s32 Xil_AssertWait = 1; + +/* The callback function to be invoked when an assert is taken */ +static Xil_AssertCallback Xil_AssertCallbackRoutine = NULL; + +/************************** Function Prototypes ******************************/ + +/*****************************************************************************/ +/** +* +* @brief Implement assert. Currently, it calls a user-defined callback +* function if one has been set. Then, it potentially enters an +* infinite loop depending on the value of the Xil_AssertWait +* variable. +* +* @param file: filename of the source +* @param line: linenumber within File +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void Xil_Assert(const char8 *File, s32 Line) +{ + /* if the callback has been set then invoke it */ + if (Xil_AssertCallbackRoutine != 0) { + (*Xil_AssertCallbackRoutine)(File, Line); + } + + /* if specified, wait indefinitely such that the assert will show up + * in testing + */ + while (Xil_AssertWait != 0) { + } +} + +/*****************************************************************************/ +/** +* +* @brief Set up a callback function to be invoked when an assert occurs. +* If a callback is already installed, then it will be replaced. +* +* @param routine: callback to be invoked when an assert is taken +* +* @return None. +* +* @note This function has no effect if NDEBUG is set +* +******************************************************************************/ +void Xil_AssertSetCallback(Xil_AssertCallback Routine) +{ + Xil_AssertCallbackRoutine = Routine; +} + +/*****************************************************************************/ +/** +* +* @brief Null handler function. This follows the XInterruptHandler +* signature for interrupt handlers. It can be used to assign a null +* handler (a stub) to an interrupt controller vector table. +* +* @param NullParameter: arbitrary void pointer and not used. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XNullHandler(void *NullParameter) +{ + (void) NullParameter; +} diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_assert.h b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_assert.h new file mode 100644 index 0000000..917de31 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_assert.h @@ -0,0 +1,191 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_assert.h +* +* @addtogroup common_assert_apis Assert APIs and Macros +* +* The xil_assert.h file contains assert related functions and macros. +* Assert APIs/Macros specifies that a application program satisfies certain +* conditions at particular points in its execution. These function can be +* used by application programs to ensure that, application code is satisfying +* certain conditions. +* +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date   Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a hbm  07/14/09 First release
+* 6.0   kvn  05/31/16 Make Xil_AsserWait a global variable
+* 
+* +******************************************************************************/ + +#ifndef XIL_ASSERT_H /* prevent circular inclusions */ +#define XIL_ASSERT_H /* by using protection macros */ + +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/***************************** Include Files *********************************/ + + +/************************** Constant Definitions *****************************/ + +#define XIL_ASSERT_NONE 0U +#define XIL_ASSERT_OCCURRED 1U +#define XNULL NULL + +extern u32 Xil_AssertStatus; +extern s32 Xil_AssertWait; +extern void Xil_Assert(const char8 *File, s32 Line); +void XNullHandler(void *NullParameter); + +/** + * This data type defines a callback to be invoked when an + * assert occurs. The callback is invoked only when asserts are enabled + */ +typedef void (*Xil_AssertCallback) (const char8 *File, s32 Line); + +/***************** Macros (Inline Functions) Definitions *********************/ + +#ifndef NDEBUG + +/*****************************************************************************/ +/** +* @brief This assert macro is to be used for void functions. This in +* conjunction with the Xil_AssertWait boolean can be used to +* accomodate tests so that asserts which fail allow execution to +* continue. +* +* @param Expression: expression to be evaluated. If it evaluates to +* false, the assert occurs. +* +* @return Returns void unless the Xil_AssertWait variable is true, in which +* case no return is made and an infinite loop is entered. +* +******************************************************************************/ +#define Xil_AssertVoid(Expression) \ +{ \ + if (Expression) { \ + Xil_AssertStatus = XIL_ASSERT_NONE; \ + } else { \ + Xil_Assert(__FILE__, __LINE__); \ + Xil_AssertStatus = XIL_ASSERT_OCCURRED; \ + return; \ + } \ +} + +/*****************************************************************************/ +/** +* @brief This assert macro is to be used for functions that do return a +* value. This in conjunction with the Xil_AssertWait boolean can be +* used to accomodate tests so that asserts which fail allow execution +* to continue. +* +* @param Expression: expression to be evaluated. If it evaluates to false, +* the assert occurs. +* +* @return Returns 0 unless the Xil_AssertWait variable is true, in which +* case no return is made and an infinite loop is entered. +* +******************************************************************************/ +#define Xil_AssertNonvoid(Expression) \ +{ \ + if (Expression) { \ + Xil_AssertStatus = XIL_ASSERT_NONE; \ + } else { \ + Xil_Assert(__FILE__, __LINE__); \ + Xil_AssertStatus = XIL_ASSERT_OCCURRED; \ + return 0; \ + } \ +} + +/*****************************************************************************/ +/** +* @brief Always assert. This assert macro is to be used for void functions. +* Use for instances where an assert should always occur. +* +* @return Returns void unless the Xil_AssertWait variable is true, in which +* case no return is made and an infinite loop is entered. +* +******************************************************************************/ +#define Xil_AssertVoidAlways() \ +{ \ + Xil_Assert(__FILE__, __LINE__); \ + Xil_AssertStatus = XIL_ASSERT_OCCURRED; \ + return; \ +} + +/*****************************************************************************/ +/** +* @brief Always assert. This assert macro is to be used for functions that +* do return a value. Use for instances where an assert should always +* occur. +* +* @return Returns void unless the Xil_AssertWait variable is true, in which +* case no return is made and an infinite loop is entered. +* +******************************************************************************/ +#define Xil_AssertNonvoidAlways() \ +{ \ + Xil_Assert(__FILE__, __LINE__); \ + Xil_AssertStatus = XIL_ASSERT_OCCURRED; \ + return 0; \ +} + + +#else + +#define Xil_AssertVoid(Expression) +#define Xil_AssertVoidAlways() +#define Xil_AssertNonvoid(Expression) +#define Xil_AssertNonvoidAlways() + +#endif + +/************************** Function Prototypes ******************************/ + +void Xil_AssertSetCallback(Xil_AssertCallback Routine); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** +* @} End of "addtogroup common_assert_apis". +*/ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_cache.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_cache.c new file mode 100644 index 0000000..536800f --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_cache.c @@ -0,0 +1,1637 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_cache.c +* +* Contains required functions for the ARM cache functionality. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver    Who Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a  ecm 01/29/10 First release
+* 1.00a  ecm 06/24/10 Moved the L1 and L2 specific function prototypes
+*		      		  to xil_cache_mach.h to give access to sophisticated users
+* 3.02a  sdm 04/07/11 Updated Flush/InvalidateRange APIs to flush/invalidate
+*		      		  L1 and L2 caches in a single loop and used dsb, L2 sync
+*		      		  at the end of the loop.
+* 3.04a  sdm 01/02/12 Remove redundant dsb/dmb instructions in cache maintenance
+*		      		  APIs.
+* 3.07a  asa 07/16/12 Corrected the L1 and L2 cache invalidation order.
+* 3.07a  sgd 09/18/12 Corrected the L2 cache enable and disable sequence.
+* 3.10a  srt 04/18/13 Implemented ARM Erratas. Please refer to file
+*		      		  'xil_errata.h' for errata description
+* 3.10a  asa 05/13/13 Modified cache disable APIs. The L2 cache disable
+*			  		  operation was being done with L1 Data cache disabled. This is
+*			  		  fixed so that L2 cache disable operation happens independent of
+*			  		  L1 cache disable operation. This fixes CR #706464.
+*			  		  Changes are done to do a L2 cache sync (poll reg7_?cache_?sync).
+*			  		  This is done to fix the CR #700542.
+* 3.11a  asa 09/23/13 Modified the Xil_DCacheFlushRange and
+*			 		  Xil_DCacheInvalidateRange to fix potential issues. Fixed other
+*			 		  relevant cache APIs to disable and enable back the interrupts.
+*			 		  This fixes CR #663885.
+* 3.11a  asa 09/28/13 Made changes for L2 cache sync operation. It is found
+*			 		  out that for L2 cache flush/clean/invalidation by cache lines
+*			 		  does not need a cache sync as these are atomic nature. Similarly
+*			 		  figured out that for complete L2 cache flush/invalidation by way
+*			 		  we need to wait for some more time in a loop till the status
+*			 		  shows that the cache operation is completed.
+* 4.00	 pkp 24/01/14 Modified Xil_DCacheInvalidateRange to fix the bug. Few
+*			 		  cache lines were missed to invalidate when unaligned address
+*			 		  invalidation was accommodated. That fixes CR #766768.
+*			 		  Also in Xil_L1DCacheInvalidate, while invalidating all L1D cache
+*			 		  stack memory which contains return address was invalidated. So
+*			 		  stack memory was flushed first and then L1D cache is invalidated.
+*			 		  This is done to fix CR #763829
+* 4.01   asa 05/09/14 Made changes in cortexa9/xil_cache.c to fix CR# 798230.
+* 4.02	 pkp 06/27/14 Added notes to Xil_L1DCacheInvalidateRange function for
+*					  explanation of CR#785243
+* 5.00   kvn 12/15/14 Xil_L2CacheInvalidate was modified to fix CR# 838835. L2 Cache
+*					  has stack memory which has return address. Before invalidating
+*					  cache, stack memory was flushed first and L2 Cache is invalidated.
+* 5.01	 pkp 05/12/15 Xil_DCacheInvalidateRange and Xil_DCacheFlushRange is modified
+*					  to remove unnecessary dsb in the APIs. Instead of using dsb
+*					  for L2 Cache, L2CacheSync has been used for each L2 cache line
+*					  and single dsb has been used for L1 cache. Also L2CacheSync is
+*					  added into Xil_L2CacheInvalidateRange API. Xil_L1DCacheInvalidate
+*					  and Xil_L2CacheInvalidate APIs are modified to flush the complete
+*					  stack instead of just System Stack
+* 5.03	 pkp 10/07/15 L2 Cache functionalities are avoided for the OpenAMP slave
+*					  application(when USE_AMP flag is defined for BSP) as master CPU
+*					  would be utilizing L2 cache for its operation
+* 6.6    mus 12/07/17 Errata 753970 is not applicable for the PL130 cache controller
+*                     version r0p2, which is present in zynq. So,removed the handling
+*                     related to same.It fixes CR#989132.
+* 6.6    asa 16/01/18 Changes made in Xil_L1DCacheInvalidate and Xil_L2CacheInvalidate
+*					  routines to ensure the stack data flushed only when the respective
+*					  caches are enabled. This fixes CR-992023.
+*
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xil_cache.h" +#include "xil_cache_l.h" +#include "xil_io.h" +#include "xpseudo_asm.h" +#include "xparameters.h" +#include "xreg_cortexa9.h" +#include "xl2cc.h" +#include "xil_errata.h" +#include "xil_exception.h" + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +#define IRQ_FIQ_MASK 0xC0U /* Mask IRQ and FIQ interrupts in cpsr */ + +#ifdef __GNUC__ + extern s32 _stack_end; + extern s32 __undef_stack; +#endif + +#ifndef USE_AMP +/**************************************************************************** +* +* Access L2 Debug Control Register. +* +* @param Value, value to be written to Debug Control Register. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +#ifdef __GNUC__ +static inline void Xil_L2WriteDebugCtrl(u32 Value) +#else +static void Xil_L2WriteDebugCtrl(u32 Value) +#endif +{ +#if defined(CONFIG_PL310_ERRATA_588369) || defined(CONFIG_PL310_ERRATA_727915) + Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_DEBUG_CTRL_OFFSET, Value); +#else + (void)(Value); +#endif +} + +/**************************************************************************** +* +* Perform L2 Cache Sync Operation. +* +* @param None. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +#ifdef __GNUC__ +static inline void Xil_L2CacheSync(void) +#else +static void Xil_L2CacheSync(void) +#endif +{ + Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_CACHE_SYNC_OFFSET, 0x0U); +} +#endif +/****************************************************************************/ +/** +* @brief Enable the Data cache. +* +* @param None. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void Xil_DCacheEnable(void) +{ + Xil_L1DCacheEnable(); +#ifndef USE_AMP + Xil_L2CacheEnable(); +#endif +} + +/****************************************************************************/ +/** +* @brief Disable the Data cache. +* +* @param None. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void Xil_DCacheDisable(void) +{ +#ifndef USE_AMP + Xil_L2CacheDisable(); +#endif + Xil_L1DCacheDisable(); +} + +/****************************************************************************/ +/** +* @brief Invalidate the entire Data cache. +* +* @param None. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void Xil_DCacheInvalidate(void) +{ + u32 currmask; + + currmask = mfcpsr(); + mtcpsr(currmask | IRQ_FIQ_MASK); +#ifndef USE_AMP + Xil_L2CacheInvalidate(); +#endif + Xil_L1DCacheInvalidate(); + + mtcpsr(currmask); +} + +/*****************************************************************************/ +/** +* @brief Invalidate a Data cache line. If the byte specified by the address +* (adr) is cached by the Data cache, the cacheline containing that +* byte is invalidated. If the cacheline is modified (dirty), the +* modified contents are lost and are NOT written to the system memory +* before the line is invalidated. +* +* @param adr: 32bit address of the data to be flushed. +* +* @return None. +* +* @note The bottom 4 bits are set to 0, forced by architecture. +* +****************************************************************************/ +void Xil_DCacheInvalidateLine(u32 adr) +{ + u32 currmask; + + currmask = mfcpsr(); + mtcpsr(currmask | IRQ_FIQ_MASK); +#ifndef USE_AMP + Xil_L2CacheInvalidateLine(adr); +#endif + Xil_L1DCacheInvalidateLine(adr); + + mtcpsr(currmask); +} + + +/*****************************************************************************/ +/** +* @brief Invalidate the Data cache for the given address range. +* If the bytes specified by the address range are cached by the Data +* cache, the cachelines containing those bytes are invalidated. If +* the cachelines are modified (dirty), the modified contents are lost +* and NOT written to the system memory before the lines are +* invalidated. +* +* In this function, if start address or end address is not aligned to +* cache-line, particular cache-line containing unaligned start or end +* address is flush first and then invalidated the others as +* invalidating the same unaligned cache line may result into loss of +* data. This issue raises few possibilities. +* +* If the address to be invalidated is not cache-line aligned, the +* following choices are available: +* 1. Invalidate the cache line when required and do not bother much +* for the side effects. Though it sounds good, it can result in +* hard-to-debug issues. The problem is, if some other variable are +* allocated in the same cache line and had been recently updated +* (in cache), the invalidation would result in loss of data. +* 2. Flush the cache line first. This will ensure that if any other +* variable present in the same cache line and updated recently are +* flushed out to memory. Then it can safely be invalidated. Again it +* sounds good, but this can result in issues. For example, when the +* invalidation happens in a typical ISR (after a DMA transfer has +* updated the memory), then flushing the cache line means, loosing +* data that were updated recently before the ISR got invoked. +* +* Linux prefers the second one. To have uniform implementation +* (across standalone and Linux), the second option is implemented. +* This being the case, follwoing needs to be taken care of: +* 1. Whenever possible, the addresses must be cache line aligned. +* Please nore that, not just start address, even the end address must +* be cache line aligned. If that is taken care of, this will always +* work. +* 2. Avoid situations where invalidation has to be done after the +* data is updated by peripheral/DMA directly into the memory. It is +* not tough to achieve (may be a bit risky). The common use case to +* do invalidation is when a DMA happens. Generally for such use +* cases, buffers can be allocated first and then start the DMA. The +* practice that needs to be followed here is, immediately after +* buffer allocation and before starting the DMA, do the invalidation. +* With this approach, invalidation need not to be done after the DMA +* transfer is over. +* +* This is going to always work if done carefully. +* However, the concern is, there is no guarantee that invalidate has +* not needed to be done after DMA is complete. For example, because +* of some reasons if the first cache line or last cache line +* (assuming the buffer in question comprises of multiple cache lines) +* are brought into cache (between the time it is invalidated and DMA +* completes) because of some speculative prefetching or reading data +* for a variable present in the same cache line, then we will have to +* invalidate the cache after DMA is complete. +* +* +* @param adr: 32bit start address of the range to be invalidated. +* @param len: Length of the range to be invalidated in bytes. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void Xil_DCacheInvalidateRange(INTPTR adr, u32 len) +{ + const u32 cacheline = 32U; + u32 end; + u32 tempadr = adr; + u32 tempend; + u32 currmask; + volatile u32 *L2CCOffset = (volatile u32 *)(XPS_L2CC_BASEADDR + + XPS_L2CC_CACHE_INVLD_PA_OFFSET); + + currmask = mfcpsr(); + mtcpsr(currmask | IRQ_FIQ_MASK); + + if (len != 0U) { + end = tempadr + len; + tempend = end; + /* Select L1 Data cache in CSSR */ + mtcp(XREG_CP15_CACHE_SIZE_SEL, 0U); + + if ((tempadr & (cacheline-1U)) != 0U) { + tempadr &= (~(cacheline - 1U)); + + Xil_L1DCacheFlushLine(tempadr); +#ifndef USE_AMP + /* Disable Write-back and line fills */ + Xil_L2WriteDebugCtrl(0x3U); + Xil_L2CacheFlushLine(tempadr); + /* Enable Write-back and line fills */ + Xil_L2WriteDebugCtrl(0x0U); + Xil_L2CacheSync(); +#endif + tempadr += cacheline; + } + if ((tempend & (cacheline-1U)) != 0U) { + tempend &= (~(cacheline - 1U)); + + Xil_L1DCacheFlushLine(tempend); +#ifndef USE_AMP + /* Disable Write-back and line fills */ + Xil_L2WriteDebugCtrl(0x3U); + Xil_L2CacheFlushLine(tempend); + /* Enable Write-back and line fills */ + Xil_L2WriteDebugCtrl(0x0U); + Xil_L2CacheSync(); +#endif + } + + while (tempadr < tempend) { +#ifndef USE_AMP + /* Invalidate L2 cache line */ + *L2CCOffset = tempadr; + Xil_L2CacheSync(); +#endif + + /* Invalidate L1 Data cache line */ +#if defined (__GNUC__) || defined (__ICCARM__) + asm_cp15_inval_dc_line_mva_poc(tempadr); +#else + { volatile register u32 Reg + __asm(XREG_CP15_INVAL_DC_LINE_MVA_POC); + Reg = tempadr; } +#endif + tempadr += cacheline; + } + } + + dsb(); + mtcpsr(currmask); +} + +/****************************************************************************/ +/** +* @brief Flush the entire Data cache. +* +* @param None. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void Xil_DCacheFlush(void) +{ + u32 currmask; + + currmask = mfcpsr(); + mtcpsr(currmask | IRQ_FIQ_MASK); + Xil_L1DCacheFlush(); +#ifndef USE_AMP + Xil_L2CacheFlush(); +#endif + mtcpsr(currmask); +} + + +/****************************************************************************/ +/** +* @brief Flush a Data cache line. If the byte specified by the address (adr) +* is cached by the Data cache, the cacheline containing that byte is +* invalidated. If the cacheline is modified (dirty), the entire +* contents of the cacheline are written to system memory before the +* line is invalidated. +* +* @param adr: 32bit address of the data to be flushed. +* +* @return None. +* +* @note The bottom 4 bits are set to 0, forced by architecture. +* +****************************************************************************/ +void Xil_DCacheFlushLine(u32 adr) +{ + u32 currmask; + + currmask = mfcpsr(); + mtcpsr(currmask | IRQ_FIQ_MASK); + Xil_L1DCacheFlushLine(adr); +#ifndef USE_AMP + /* Disable Write-back and line fills */ + Xil_L2WriteDebugCtrl(0x3U); + + Xil_L2CacheFlushLine(adr); + + /* Enable Write-back and line fills */ + Xil_L2WriteDebugCtrl(0x0U); + Xil_L2CacheSync(); +#endif + mtcpsr(currmask); +} + +/****************************************************************************/ +/** +* @brief Flush the Data cache for the given address range. +* If the bytes specified by the address range are cached by the +* data cache, the cachelines containing those bytes are invalidated. +* If the cachelines are modified (dirty), they are written to the +* system memory before the lines are invalidated. +* +* @param adr: 32bit start address of the range to be flushed. +* @param len: Length of the range to be flushed in bytes. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void Xil_DCacheFlushRange(INTPTR adr, u32 len) +{ + u32 LocalAddr = adr; + const u32 cacheline = 32U; + u32 end; + u32 currmask; + volatile u32 *L2CCOffset = (volatile u32 *)(XPS_L2CC_BASEADDR + + XPS_L2CC_CACHE_INV_CLN_PA_OFFSET); + + currmask = mfcpsr(); + mtcpsr(currmask | IRQ_FIQ_MASK); + + if (len != 0U) { + /* Back the starting address up to the start of a cache line + * perform cache operations until adr+len + */ + end = LocalAddr + len; + LocalAddr &= ~(cacheline - 1U); + + while (LocalAddr < end) { + + /* Flush L1 Data cache line */ +#if defined (__GNUC__) || defined (__ICCARM__) + asm_cp15_clean_inval_dc_line_mva_poc(LocalAddr); +#else + { volatile register u32 Reg + __asm(XREG_CP15_CLEAN_INVAL_DC_LINE_MVA_POC); + Reg = LocalAddr; } +#endif +#ifndef USE_AMP + /* Flush L2 cache line */ + *L2CCOffset = LocalAddr; + Xil_L2CacheSync(); +#endif + LocalAddr += cacheline; + } + } + dsb(); + mtcpsr(currmask); +} +/****************************************************************************/ +/** +* @brief Store a Data cache line. If the byte specified by the address (adr) +* is cached by the Data cache and the cacheline is modified (dirty), +* the entire contents of the cacheline are written to system memory. +* After the store completes, the cacheline is marked as unmodified +* (not dirty). +* +* @param adr: 32bit address of the data to be stored. +* +* @return None. +* +* @note The bottom 4 bits are set to 0, forced by architecture. +* +****************************************************************************/ +void Xil_DCacheStoreLine(u32 adr) +{ + u32 currmask; + + currmask = mfcpsr(); + mtcpsr(currmask | IRQ_FIQ_MASK); + + Xil_L1DCacheStoreLine(adr); +#ifndef USE_AMP + Xil_L2CacheStoreLine(adr); +#endif + mtcpsr(currmask); +} + +/***************************************************************************/ +/** +* @brief Enable the instruction cache. +* +* @param None. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void Xil_ICacheEnable(void) +{ + Xil_L1ICacheEnable(); +#ifndef USE_AMP + Xil_L2CacheEnable(); +#endif +} + +/***************************************************************************/ +/** +* @brief Disable the instruction cache. +* +* @param None. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void Xil_ICacheDisable(void) +{ +#ifndef USE_AMP + Xil_L2CacheDisable(); +#endif + Xil_L1ICacheDisable(); +} + + +/****************************************************************************/ +/** +* @brief Invalidate the entire instruction cache. +* +* @param None. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void Xil_ICacheInvalidate(void) +{ + u32 currmask; + + currmask = mfcpsr(); + mtcpsr(currmask | IRQ_FIQ_MASK); +#ifndef USE_AMP + Xil_L2CacheInvalidate(); +#endif + Xil_L1ICacheInvalidate(); + + mtcpsr(currmask); +} + +/****************************************************************************/ +/** +* @brief Invalidate an instruction cache line. If the instruction specified +* by the address is cached by the instruction cache, the cacheline +* containing that instruction is invalidated. +* +* @param adr: 32bit address of the instruction to be invalidated. +* +* @return None. +* +* @note The bottom 4 bits are set to 0, forced by architecture. +* +****************************************************************************/ +void Xil_ICacheInvalidateLine(u32 adr) +{ + u32 currmask; + + currmask = mfcpsr(); + mtcpsr(currmask | IRQ_FIQ_MASK); +#ifndef USE_AMP + Xil_L2CacheInvalidateLine(adr); +#endif + Xil_L1ICacheInvalidateLine(adr); + mtcpsr(currmask); +} + +/****************************************************************************/ +/** +* @brief Invalidate the instruction cache for the given address range. +* If the instructions specified by the address range are cached by +* the instrunction cache, the cachelines containing those +* instructions are invalidated. +* +* @param adr: 32bit start address of the range to be invalidated. +* @param len: Length of the range to be invalidated in bytes. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void Xil_ICacheInvalidateRange(INTPTR adr, u32 len) +{ + u32 LocalAddr = adr; + const u32 cacheline = 32U; + u32 end; + volatile u32 *L2CCOffset = (volatile u32 *)(XPS_L2CC_BASEADDR + + XPS_L2CC_CACHE_INVLD_PA_OFFSET); + + u32 currmask; + + currmask = mfcpsr(); + mtcpsr(currmask | IRQ_FIQ_MASK); + if (len != 0U) { + /* Back the starting address up to the start of a cache line + * perform cache operations until adr+len + */ + end = LocalAddr + len; + LocalAddr = LocalAddr & ~(cacheline - 1U); + + /* Select cache L0 I-cache in CSSR */ + mtcp(XREG_CP15_CACHE_SIZE_SEL, 1U); + + while (LocalAddr < end) { +#ifndef USE_AMP + /* Invalidate L2 cache line */ + *L2CCOffset = LocalAddr; + dsb(); +#endif + + /* Invalidate L1 I-cache line */ +#if defined (__GNUC__) || defined (__ICCARM__) + asm_cp15_inval_ic_line_mva_pou(LocalAddr); +#else + { volatile register u32 Reg + __asm(XREG_CP15_INVAL_IC_LINE_MVA_POU); + Reg = LocalAddr; } +#endif + + LocalAddr += cacheline; + } + } + + /* Wait for L1 and L2 invalidate to complete */ + dsb(); + mtcpsr(currmask); +} + +/****************************************************************************/ +/** +* @brief Enable the level 1 Data cache. +* +* @param None. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void Xil_L1DCacheEnable(void) +{ + register u32 CtrlReg; + + /* enable caches only if they are disabled */ +#ifdef __GNUC__ + CtrlReg = mfcp(XREG_CP15_SYS_CONTROL); +#elif defined (__ICCARM__) + mfcp(XREG_CP15_SYS_CONTROL, CtrlReg); +#else + { volatile register u32 Reg __asm(XREG_CP15_SYS_CONTROL); + CtrlReg = Reg; } +#endif + if ((CtrlReg & (XREG_CP15_CONTROL_C_BIT)) != 0U) { + return; + } + + /* clean and invalidate the Data cache */ + Xil_L1DCacheInvalidate(); + + /* enable the Data cache */ + CtrlReg |= (XREG_CP15_CONTROL_C_BIT); + + mtcp(XREG_CP15_SYS_CONTROL, CtrlReg); +} + +/***************************************************************************/ +/** +* @brief Disable the level 1 Data cache. +* +* @param None. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void Xil_L1DCacheDisable(void) +{ + register u32 CtrlReg; + + /* clean and invalidate the Data cache */ + Xil_L1DCacheFlush(); + +#ifdef __GNUC__ + /* disable the Data cache */ + CtrlReg = mfcp(XREG_CP15_SYS_CONTROL); +#elif defined (__ICCARM__) + mfcp(XREG_CP15_SYS_CONTROL, CtrlReg); +#else + { volatile register u32 Reg __asm(XREG_CP15_SYS_CONTROL); + CtrlReg = Reg; } +#endif + + CtrlReg &= ~(XREG_CP15_CONTROL_C_BIT); + + mtcp(XREG_CP15_SYS_CONTROL, CtrlReg); +} + +/****************************************************************************/ +/** +* @brief Invalidate the level 1 Data cache. +* +* @param None. +* +* @return None. +* +* @note In Cortex A9, there is no cp instruction for invalidating +* the whole D-cache. This function invalidates each line by +* set/way. +* +****************************************************************************/ +void Xil_L1DCacheInvalidate(void) +{ + register u32 CsidReg, C7Reg; + u32 CacheSize, LineSize, NumWays; + u32 Way, WayIndex, Set, SetIndex, NumSet; + u32 currmask; + +#ifdef __GNUC__ + u32 stack_start,stack_end,stack_size; + register u32 CtrlReg; +#endif + + currmask = mfcpsr(); + mtcpsr(currmask | IRQ_FIQ_MASK); + +#ifdef __GNUC__ + stack_end = (u32)&_stack_end; + stack_start = (u32)&__undef_stack; + stack_size=stack_start-stack_end; + + /* Check for the cache status. If cache is enabled, then only + * flush stack memory to save return address. If cache is disabled, + * dont flush anything as it might result in flushing stale date into + * memory which is undesirable. + * */ + CtrlReg = mfcp(XREG_CP15_SYS_CONTROL); + if ((CtrlReg & (XREG_CP15_CONTROL_C_BIT)) != 0U) { + Xil_DCacheFlushRange(stack_end, stack_size); + } +#endif + + /* Select cache level 0 and D cache in CSSR */ + mtcp(XREG_CP15_CACHE_SIZE_SEL, 0U); + +#ifdef __GNUC__ + CsidReg = mfcp(XREG_CP15_CACHE_SIZE_ID); +#elif defined (__ICCARM__) + mfcp(XREG_CP15_CACHE_SIZE_ID, CsidReg); +#else + { volatile register u32 Reg __asm(XREG_CP15_CACHE_SIZE_ID); + CsidReg = Reg; } +#endif + /* Determine Cache Size */ + CacheSize = (CsidReg >> 13U) & 0x1FFU; + CacheSize +=1U; + CacheSize *=128U; /* to get number of bytes */ + + /* Number of Ways */ + NumWays = (CsidReg & 0x3ffU) >> 3U; + NumWays += 1U; + + /* Get the cacheline size, way size, index size from csidr */ + LineSize = (CsidReg & 0x07U) + 4U; + + NumSet = CacheSize/NumWays; + NumSet /= (0x00000001U << LineSize); + + Way = 0U; + Set = 0U; + + /* Invalidate all the cachelines */ + for (WayIndex =0U; WayIndex < NumWays; WayIndex++) { + for (SetIndex =0U; SetIndex < NumSet; SetIndex++) { + C7Reg = Way | Set; + + /* Invalidate by Set/Way */ +#if defined (__GNUC__) || defined (__ICCARM__) + asm_cp15_inval_dc_line_sw(C7Reg); +#else + /*mtcp(XREG_CP15_INVAL_DC_LINE_SW, C7Reg), */ + { volatile register u32 Reg + __asm(XREG_CP15_INVAL_DC_LINE_SW); + Reg = C7Reg; } +#endif + Set += (0x00000001U << LineSize); + } + Set=0U; + Way += 0x40000000U; + } + + /* Wait for L1 invalidate to complete */ + dsb(); + mtcpsr(currmask); +} + +/****************************************************************************/ +/** +* @brief Invalidate a level 1 Data cache line. If the byte specified by the +* address (Addr) is cached by the Data cache, the cacheline +* containing that byte is invalidated. If the cacheline is modified +* (dirty), the modified contents are lost and are NOT written to +* system memory before the line is invalidated. +* +* @param adr: 32bit address of the data to be invalidated. +* +* @return None. +* +* @note The bottom 5 bits are set to 0, forced by architecture. +* +****************************************************************************/ +void Xil_L1DCacheInvalidateLine(u32 adr) +{ + mtcp(XREG_CP15_CACHE_SIZE_SEL, 0U); + mtcp(XREG_CP15_INVAL_DC_LINE_MVA_POC, (adr & (~0x1FU))); + + /* Wait for L1 invalidate to complete */ + dsb(); +} + +/****************************************************************************/ +/** +* @brief Invalidate the level 1 Data cache for the given address range. +* If the bytes specified by the address range are cached by the Data +* cache, the cachelines containing those bytes are invalidated. If the +* cachelines are modified (dirty), the modified contents are lost and +* NOT written to the system memory before the lines are invalidated. +* +* @param adr: 32bit start address of the range to be invalidated. +* @param len: Length of the range to be invalidated in bytes. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void Xil_L1DCacheInvalidateRange(u32 adr, u32 len) +{ + u32 LocalAddr = adr; + const u32 cacheline = 32U; + u32 end; + u32 currmask; + + currmask = mfcpsr(); + mtcpsr(currmask | IRQ_FIQ_MASK); + + if (len != 0U) { + /* Back the starting address up to the start of a cache line + * perform cache operations until adr+len + */ + end = LocalAddr + len; + LocalAddr = LocalAddr & ~(cacheline - 1U); + + /* Select cache L0 D-cache in CSSR */ + mtcp(XREG_CP15_CACHE_SIZE_SEL, 0); + + while (LocalAddr < end) { + +#if defined (__GNUC__) || defined (__ICCARM__) + asm_cp15_inval_dc_line_mva_poc(LocalAddr); +#else + { volatile register u32 Reg + __asm(XREG_CP15_INVAL_DC_LINE_MVA_POC); + Reg = LocalAddr; } +#endif + LocalAddr += cacheline; + } + } + + /* Wait for L1 invalidate to complete */ + dsb(); + mtcpsr(currmask); +} + +/****************************************************************************/ +/** +* @brief Flush the level 1 Data cache. +* +* @param None. +* +* @return None. +* +* @note In Cortex A9, there is no cp instruction for flushing +* the whole D-cache. Need to flush each line. +* +****************************************************************************/ +void Xil_L1DCacheFlush(void) +{ + register u32 CsidReg, C7Reg; + u32 CacheSize, LineSize, NumWays; + u32 Way; + u32 WayIndex, Set, SetIndex, NumSet; + u32 currmask; + + currmask = mfcpsr(); + mtcpsr(currmask | IRQ_FIQ_MASK); + + /* Select cache level 0 and D cache in CSSR */ + mtcp(XREG_CP15_CACHE_SIZE_SEL, 0); + +#ifdef __GNUC__ + CsidReg = mfcp(XREG_CP15_CACHE_SIZE_ID); +#elif defined (__ICCARM__) + mfcp(XREG_CP15_CACHE_SIZE_ID, CsidReg); +#else + { volatile register u32 Reg __asm(XREG_CP15_CACHE_SIZE_ID); + CsidReg = Reg; } +#endif + + /* Determine Cache Size */ + + CacheSize = (CsidReg >> 13U) & 0x1FFU; + CacheSize +=1U; + CacheSize *=128U; /* to get number of bytes */ + + /* Number of Ways */ + NumWays = (CsidReg & 0x3ffU) >> 3U; + NumWays += 1U; + + /* Get the cacheline size, way size, index size from csidr */ + LineSize = (CsidReg & 0x07U) + 4U; + + NumSet = CacheSize/NumWays; + NumSet /= (0x00000001U << LineSize); + + Way = 0U; + Set = 0U; + + /* Invalidate all the cachelines */ + for (WayIndex =0U; WayIndex < NumWays; WayIndex++) { + for (SetIndex =0U; SetIndex < NumSet; SetIndex++) { + C7Reg = Way | Set; + /* Flush by Set/Way */ + +#if defined (__GNUC__) || defined (__ICCARM__) + asm_cp15_clean_inval_dc_line_sw(C7Reg); +#else + { volatile register u32 Reg + __asm(XREG_CP15_CLEAN_INVAL_DC_LINE_SW); + Reg = C7Reg; } +#endif + Set += (0x00000001U << LineSize); + } + Set = 0U; + Way += 0x40000000U; + } + + /* Wait for L1 flush to complete */ + dsb(); + mtcpsr(currmask); +} + +/****************************************************************************/ +/** +* @brief Flush a level 1 Data cache line. If the byte specified by the +* address (adr) is cached by the Data cache, the cacheline containing +* that byte is invalidated. If the cacheline is modified (dirty), the +* entire contents of the cacheline are written to system memory +* before the line is invalidated. +* +* @param adr: 32bit address of the data to be flushed. +* +* @return None. +* +* @note The bottom 5 bits are set to 0, forced by architecture. +* +****************************************************************************/ +void Xil_L1DCacheFlushLine(u32 adr) +{ + mtcp(XREG_CP15_CACHE_SIZE_SEL, 0U); + mtcp(XREG_CP15_CLEAN_INVAL_DC_LINE_MVA_POC, (adr & (~0x1FU))); + + /* Wait for L1 flush to complete */ + dsb(); +} + +/****************************************************************************/ +/** +* @brief Flush the level 1 Data cache for the given address range. +* If the bytes specified by the address range are cached by the Data +* cache, the cacheline containing those bytes are invalidated. If the +* cachelines are modified (dirty), they are written to system memory +* before the lines are invalidated. +* +* @param adr: 32bit start address of the range to be flushed. +* @param len: Length of the range to be flushed in bytes. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void Xil_L1DCacheFlushRange(u32 adr, u32 len) +{ + u32 LocalAddr = adr; + const u32 cacheline = 32U; + u32 end; + u32 currmask; + + currmask = mfcpsr(); + mtcpsr(currmask | IRQ_FIQ_MASK); + + if (len != 0U) { + /* Back the starting address up to the start of a cache line + * perform cache operations until adr+len + */ + end = LocalAddr + len; + LocalAddr = LocalAddr & ~(cacheline - 1U); + + /* Select cache L0 D-cache in CSSR */ + mtcp(XREG_CP15_CACHE_SIZE_SEL, 0U); + + while (LocalAddr < end) { + +#if defined (__GNUC__) || defined (__ICCARM__) + asm_cp15_clean_inval_dc_line_mva_poc(LocalAddr); +#else + { volatile register u32 Reg + __asm(XREG_CP15_CLEAN_INVAL_DC_LINE_MVA_POC); + Reg = LocalAddr; } +#endif + LocalAddr += cacheline; + } + } + + /* Wait for L1 flush to complete */ + dsb(); + mtcpsr(currmask); +} + +/****************************************************************************/ +/** +* @brief Store a level 1 Data cache line. If the byte specified by the +* address (adr) is cached by the Data cache and the cacheline is +* modified (dirty), the entire contents of the cacheline are written +* to system memory. After the store completes, the cacheline is +* marked as unmodified (not dirty). +* +* @param Address to be stored. +* +* @return None. +* +* @note The bottom 5 bits are set to 0, forced by architecture. +* +****************************************************************************/ +void Xil_L1DCacheStoreLine(u32 adr) +{ + mtcp(XREG_CP15_CACHE_SIZE_SEL, 0U); + mtcp(XREG_CP15_CLEAN_DC_LINE_MVA_POC, (adr & (~0x1FU))); + + /* Wait for L1 store to complete */ + dsb(); +} + + +/****************************************************************************/ +/** +* @brief Enable the level 1 instruction cache. +* +* @param None. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void Xil_L1ICacheEnable(void) +{ + register u32 CtrlReg; + + /* enable caches only if they are disabled */ +#ifdef __GNUC__ + CtrlReg = mfcp(XREG_CP15_SYS_CONTROL); +#elif defined (__ICCARM__) + mfcp(XREG_CP15_SYS_CONTROL, CtrlReg); +#else + { volatile register u32 Reg __asm(XREG_CP15_SYS_CONTROL); + CtrlReg = Reg; } +#endif + if ((CtrlReg & (XREG_CP15_CONTROL_I_BIT)) != 0U) { + return; + } + + /* invalidate the instruction cache */ + mtcp(XREG_CP15_INVAL_IC_POU, 0U); + + /* enable the instruction cache */ + CtrlReg |= (XREG_CP15_CONTROL_I_BIT); + + mtcp(XREG_CP15_SYS_CONTROL, CtrlReg); +} + +/****************************************************************************/ +/** +* @brief Disable level 1 the instruction cache. +* +* @param None. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void Xil_L1ICacheDisable(void) +{ + register u32 CtrlReg; + + dsb(); + + /* invalidate the instruction cache */ + mtcp(XREG_CP15_INVAL_IC_POU, 0U); + + /* disable the instruction cache */ +#ifdef __GNUC__ + CtrlReg = mfcp(XREG_CP15_SYS_CONTROL); +#elif defined (__ICCARM__) + mfcp(XREG_CP15_SYS_CONTROL, CtrlReg); +#else + { volatile register u32 Reg __asm(XREG_CP15_SYS_CONTROL); + CtrlReg = Reg; } +#endif + CtrlReg &= ~(XREG_CP15_CONTROL_I_BIT); + + mtcp(XREG_CP15_SYS_CONTROL, CtrlReg); +} + +/****************************************************************************/ +/** +* @brief Invalidate the entire level 1 instruction cache. +* +* @param None. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void Xil_L1ICacheInvalidate(void) +{ + mtcp(XREG_CP15_CACHE_SIZE_SEL, 1U); + /* invalidate the instruction cache */ + mtcp(XREG_CP15_INVAL_IC_POU, 0U); + + /* Wait for L1 invalidate to complete */ + dsb(); +} + +/****************************************************************************/ +/** +* @brief Invalidate a level 1 instruction cache line. If the instruction +* specified by the address is cached by the instruction cache, the +* cacheline containing that instruction is invalidated. +* +* @param adr: 32bit address of the instruction to be invalidated. +* +* @return None. +* +* @note The bottom 5 bits are set to 0, forced by architecture. +* +****************************************************************************/ +void Xil_L1ICacheInvalidateLine(u32 adr) +{ + mtcp(XREG_CP15_CACHE_SIZE_SEL, 1U); + mtcp(XREG_CP15_INVAL_IC_LINE_MVA_POU, (adr & (~0x1FU))); + + /* Wait for L1 invalidate to complete */ + dsb(); +} + +/****************************************************************************/ +/** +* @brief Invalidate the level 1 instruction cache for the given address +* range. If the instrucions specified by the address range are cached +* by the instruction cache, the cacheline containing those bytes are +* invalidated. +* +* @param adr: 32bit start address of the range to be invalidated. +* @param len: Length of the range to be invalidated in bytes. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void Xil_L1ICacheInvalidateRange(u32 adr, u32 len) +{ + u32 LocalAddr = adr; + const u32 cacheline = 32U; + u32 end; + u32 currmask; + + currmask = mfcpsr(); + mtcpsr(currmask | IRQ_FIQ_MASK); + + if (len != 0U) { + /* Back the starting address up to the start of a cache line + * perform cache operations until adr+len + */ + end = LocalAddr + len; + LocalAddr = LocalAddr & ~(cacheline - 1U); + + /* Select cache L0 I-cache in CSSR */ + mtcp(XREG_CP15_CACHE_SIZE_SEL, 1U); + + while (LocalAddr < end) { + +#if defined (__GNUC__) || defined (__ICCARM__) + asm_cp15_inval_ic_line_mva_pou(LocalAddr); +#else + { volatile register u32 Reg + __asm(XREG_CP15_INVAL_IC_LINE_MVA_POU); + Reg = LocalAddr; } +#endif + LocalAddr += cacheline; + } + } + + /* Wait for L1 invalidate to complete */ + dsb(); + mtcpsr(currmask); +} + +#ifndef USE_AMP +/****************************************************************************/ +/** +* @brief Enable the L2 cache. +* +* @param None. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void Xil_L2CacheEnable(void) +{ + register u32 L2CCReg; + + L2CCReg = Xil_In32(XPS_L2CC_BASEADDR + XPS_L2CC_CNTRL_OFFSET); + + /* only enable if L2CC is currently disabled */ + if ((L2CCReg & 0x01U) == 0U) { + /* set up the way size and latencies */ + L2CCReg = Xil_In32(XPS_L2CC_BASEADDR + + XPS_L2CC_AUX_CNTRL_OFFSET); + L2CCReg &= XPS_L2CC_AUX_REG_ZERO_MASK; + L2CCReg |= XPS_L2CC_AUX_REG_DEFAULT_MASK; + Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_AUX_CNTRL_OFFSET, + L2CCReg); + Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_TAG_RAM_CNTRL_OFFSET, + XPS_L2CC_TAG_RAM_DEFAULT_MASK); + Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_DATA_RAM_CNTRL_OFFSET, + XPS_L2CC_DATA_RAM_DEFAULT_MASK); + + /* Clear the pending interrupts */ + L2CCReg = Xil_In32(XPS_L2CC_BASEADDR + + XPS_L2CC_ISR_OFFSET); + Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_IAR_OFFSET, L2CCReg); + + Xil_L2CacheInvalidate(); + /* Enable the L2CC */ + L2CCReg = Xil_In32(XPS_L2CC_BASEADDR + + XPS_L2CC_CNTRL_OFFSET); + Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_CNTRL_OFFSET, + (L2CCReg | (0x01U))); + + Xil_L2CacheSync(); + /* synchronize the processor */ + dsb(); + + } +} + +/****************************************************************************/ +/** +* @brief Disable the L2 cache. +* +* @param None. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void Xil_L2CacheDisable(void) +{ + register u32 L2CCReg; + + L2CCReg = Xil_In32(XPS_L2CC_BASEADDR + XPS_L2CC_CNTRL_OFFSET); + + if((L2CCReg & 0x1U) != 0U) { + + /* Clean and Invalidate L2 Cache */ + Xil_L2CacheFlush(); + + /* Disable the L2CC */ + L2CCReg = Xil_In32(XPS_L2CC_BASEADDR + XPS_L2CC_CNTRL_OFFSET); + Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_CNTRL_OFFSET, + (L2CCReg & (~0x01U))); + /* Wait for the cache operations to complete */ + + dsb(); + } +} + +/*****************************************************************************/ +/** +* @brief Invalidate the entire level 2 cache. +* +* @param None. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void Xil_L2CacheInvalidate(void) +{ + #ifdef __GNUC__ + u32 stack_start,stack_end,stack_size; + register u32 L2CCReg; + stack_end = (u32)&_stack_end; + stack_start = (u32)&__undef_stack; + stack_size=stack_start-stack_end; + + /* Check for the cache status. If cache is enabled, then only + * flush stack memory to save return address. If cache is disabled, + * dont flush anything as it might result in flushing stale date into + * memory which is undesirable. + */ + L2CCReg = Xil_In32(XPS_L2CC_BASEADDR + XPS_L2CC_CNTRL_OFFSET); + if ((L2CCReg & 0x01U) != 0U) { + /*Flush stack memory to save return address*/ + Xil_DCacheFlushRange(stack_end, stack_size); + } + + #endif + u32 ResultDCache; + /* Invalidate the caches */ + Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_CACHE_INVLD_WAY_OFFSET, + 0x0000FFFFU); + ResultDCache = Xil_In32(XPS_L2CC_BASEADDR + XPS_L2CC_CACHE_INVLD_WAY_OFFSET) + & 0x0000FFFFU; + while(ResultDCache != (u32)0U) { + ResultDCache = Xil_In32(XPS_L2CC_BASEADDR + XPS_L2CC_CACHE_INVLD_WAY_OFFSET) + & 0x0000FFFFU; + } + + /* Wait for the invalidate to complete */ + Xil_L2CacheSync(); + + /* synchronize the processor */ + dsb(); +} + +/*****************************************************************************/ +/** +* @brief Invalidate a level 2 cache line. If the byte specified by the +* address (adr) is cached by the Data cache, the cacheline containing +* that byte is invalidated. If the cacheline is modified (dirty), +* the modified contents are lost and are NOT written to system memory +* before the line is invalidated. +* +* @param adr: 32bit address of the data/instruction to be invalidated. +* +* @return None. +* +* @note The bottom 4 bits are set to 0, forced by architecture. +* +****************************************************************************/ +void Xil_L2CacheInvalidateLine(u32 adr) +{ + Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_CACHE_INVLD_PA_OFFSET, (u32)adr); + /* synchronize the processor */ + dsb(); +} + +/****************************************************************************/ +/** +* @brief Invalidate the level 2 cache for the given address range. +* If the bytes specified by the address range are cached by the L2 +* cache, the cacheline containing those bytes are invalidated. If the +* cachelines are modified (dirty), the modified contents are lost and +* are NOT written to system memory before the lines are invalidated. +* +* @param adr: 32bit start address of the range to be invalidated. +* @param len: Length of the range to be invalidated in bytes. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void Xil_L2CacheInvalidateRange(u32 adr, u32 len) +{ + u32 LocalAddr = adr; + const u32 cacheline = 32U; + u32 end; + volatile u32 *L2CCOffset = (volatile u32 *)(XPS_L2CC_BASEADDR + + XPS_L2CC_CACHE_INVLD_PA_OFFSET); + + u32 currmask; + + currmask = mfcpsr(); + mtcpsr(currmask | IRQ_FIQ_MASK); + + if (len != 0U) { + /* Back the starting address up to the start of a cache line + * perform cache operations until adr+len + */ + end = LocalAddr + len; + LocalAddr = LocalAddr & ~(cacheline - 1U); + + /* Disable Write-back and line fills */ + Xil_L2WriteDebugCtrl(0x3U); + + while (LocalAddr < end) { + *L2CCOffset = LocalAddr; + Xil_L2CacheSync(); + LocalAddr += cacheline; + } + + /* Enable Write-back and line fills */ + Xil_L2WriteDebugCtrl(0x0U); + } + + /* synchronize the processor */ + dsb(); + mtcpsr(currmask); +} + +/****************************************************************************/ +/** +* @brief Flush the entire level 2 cache. +* +* @param None. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void Xil_L2CacheFlush(void) +{ + u32 ResultL2Cache; + + /* Flush the caches */ + + /* Disable Write-back and line fills */ + Xil_L2WriteDebugCtrl(0x3U); + + Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_CACHE_INV_CLN_WAY_OFFSET, + 0x0000FFFFU); + ResultL2Cache = Xil_In32(XPS_L2CC_BASEADDR + XPS_L2CC_CACHE_INV_CLN_WAY_OFFSET) + & 0x0000FFFFU; + + while(ResultL2Cache != (u32)0U) { + ResultL2Cache = Xil_In32(XPS_L2CC_BASEADDR + XPS_L2CC_CACHE_INV_CLN_WAY_OFFSET) + & 0x0000FFFFU; + } + + Xil_L2CacheSync(); + /* Enable Write-back and line fills */ + Xil_L2WriteDebugCtrl(0x0U); + + /* synchronize the processor */ + dsb(); +} + +/****************************************************************************/ +/** +* @brief Flush a level 2 cache line. If the byte specified by the address +* (adr) is cached by the L2 cache, the cacheline containing that +* byte is invalidated. If the cacheline is modified (dirty), the +* entire contents of the cacheline are written to system memory +* before the line is invalidated. +* +* @param adr: 32bit address of the data/instruction to be flushed. +* +* @return None. +* +* @note The bottom 4 bits are set to 0, forced by architecture. +* +****************************************************************************/ +void Xil_L2CacheFlushLine(u32 adr) +{ +#ifdef CONFIG_PL310_ERRATA_588369 + Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_CACHE_CLEAN_PA_OFFSET, adr); + Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_CACHE_INVLD_PA_OFFSET, adr); +#else + Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_CACHE_INV_CLN_PA_OFFSET, adr); +#endif + /* synchronize the processor */ + dsb(); +} + +/****************************************************************************/ +/** +* @brief Flush the level 2 cache for the given address range. +* If the bytes specified by the address range are cached by the L2 +* cache, the cacheline containing those bytes are invalidated. If the +* cachelines are modified (dirty), they are written to the system +* memory before the lines are invalidated. +* +* @param adr: 32bit start address of the range to be flushed. +* @param len: Length of the range to be flushed in bytes. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void Xil_L2CacheFlushRange(u32 adr, u32 len) +{ + u32 LocalAddr = adr; + const u32 cacheline = 32U; + u32 end; + volatile u32 *L2CCOffset = (volatile u32 *)(XPS_L2CC_BASEADDR + + XPS_L2CC_CACHE_INV_CLN_PA_OFFSET); + + u32 currmask; + + currmask = mfcpsr(); + mtcpsr(currmask | IRQ_FIQ_MASK); + if (len != 0U) { + /* Back the starting address up to the start of a cache line + * perform cache operations until adr+len + */ + end = LocalAddr + len; + LocalAddr = LocalAddr & ~(cacheline - 1U); + + /* Disable Write-back and line fills */ + Xil_L2WriteDebugCtrl(0x3U); + + while (LocalAddr < end) { + *L2CCOffset = LocalAddr; + Xil_L2CacheSync(); + LocalAddr += cacheline; + } + + /* Enable Write-back and line fills */ + Xil_L2WriteDebugCtrl(0x0U); + } + /* synchronize the processor */ + dsb(); + mtcpsr(currmask); +} + +/****************************************************************************/ +/** +* @brief Store a level 2 cache line. If the byte specified by the address +* (adr) is cached by the L2 cache and the cacheline is modified +* (dirty), the entire contents of the cacheline are written to +* system memory. After the store completes, the cacheline is marked +* as unmodified (not dirty). +* +* @param adr: 32bit address of the data/instruction to be stored. +* +* @return None. +* +* @note The bottom 4 bits are set to 0, forced by architecture. +* +****************************************************************************/ +void Xil_L2CacheStoreLine(u32 adr) +{ + Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_CACHE_CLEAN_PA_OFFSET, adr); + /* synchronize the processor */ + dsb(); +} +#endif diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_cache.h b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_cache.h new file mode 100644 index 0000000..ce6fcf4 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_cache.h @@ -0,0 +1,118 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_cache.h +* +* @addtogroup a9_cache_apis Cortex A9 Processor Cache Functions +* +* Cache functions provide access to cache related operations such as flush +* and invalidate for instruction and data caches. It gives option to perform +* the cache operations on a single cacheline, a range of memory and an entire +* cache. +* +* @{ +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a ecm  01/29/10 First release
+* 3.04a sdm  01/02/12 Remove redundant dsb/dmb instructions in cache maintenance
+*		      APIs.
+* 6.8   aru  09/06/18 Removed compilation warnings for ARMCC toolchain.
+* 
+* +******************************************************************************/ +#ifndef XIL_CACHE_H +#define XIL_CACHE_H + +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __GNUC__ + +#define asm_cp15_inval_dc_line_mva_poc(param) __asm__ __volatile__("mcr " \ + XREG_CP15_INVAL_DC_LINE_MVA_POC :: "r" (param)); + +#define asm_cp15_clean_inval_dc_line_mva_poc(param) __asm__ __volatile__("mcr " \ + XREG_CP15_CLEAN_INVAL_DC_LINE_MVA_POC :: "r" (param)); + +#define asm_cp15_inval_ic_line_mva_pou(param) __asm__ __volatile__("mcr " \ + XREG_CP15_INVAL_IC_LINE_MVA_POU :: "r" (param)); + +#define asm_cp15_inval_dc_line_sw(param) __asm__ __volatile__("mcr " \ + XREG_CP15_INVAL_DC_LINE_SW :: "r" (param)); + +#define asm_cp15_clean_inval_dc_line_sw(param) __asm__ __volatile__("mcr " \ + XREG_CP15_CLEAN_INVAL_DC_LINE_SW :: "r" (param)); + +#elif defined (__ICCARM__) + +#define asm_cp15_inval_dc_line_mva_poc(param) __asm volatile ("mcr " \ + XREG_CP15_INVAL_DC_LINE_MVA_POC :: "r" (param)); + +#define asm_cp15_clean_inval_dc_line_mva_poc(param) __asm volatile ("mcr " \ + XREG_CP15_CLEAN_INVAL_DC_LINE_MVA_POC :: "r" (param)); + +#define asm_cp15_inval_ic_line_mva_pou(param) __asm volatile ("mcr " \ + XREG_CP15_INVAL_IC_LINE_MVA_POU :: "r" (param)); + +#define asm_cp15_inval_dc_line_sw(param) __asm volatile ("mcr " \ + XREG_CP15_INVAL_DC_LINE_SW :: "r" (param)); + +#define asm_cp15_clean_inval_dc_line_sw(param) __asm volatile ("mcr " \ + XREG_CP15_CLEAN_INVAL_DC_LINE_SW :: "r" (param)); + +#endif + +void Xil_DCacheEnable(void); +void Xil_DCacheDisable(void); +void Xil_DCacheInvalidate(void); +void Xil_DCacheInvalidateRange(INTPTR adr, u32 len); +void Xil_DCacheFlush(void); +void Xil_DCacheFlushRange(INTPTR adr, u32 len); + +void Xil_ICacheEnable(void); +void Xil_ICacheDisable(void); +void Xil_ICacheInvalidate(void); +void Xil_ICacheInvalidateRange(INTPTR adr, u32 len); + +#ifdef __cplusplus +} +#endif + +#endif +/** +* @} End of "addtogroup a9_cache_apis". +*/ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_cache_l.h b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_cache_l.h new file mode 100644 index 0000000..b6ff809 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_cache_l.h @@ -0,0 +1,97 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_cache_l.h +* +* Contains L1 and L2 specific functions for the ARM cache functionality +* used by xcache.c. This functionality is being made available here for +* more sophisticated users. +* +* @addtogroup a9_cache_apis +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a ecm  01/24/10 First release
+* 6.8   aru  09/06/18 Removed compilation warnings for ARMCC toolchain.
+* 
+* +******************************************************************************/ +#ifndef XIL_CACHE_MACH_H +#define XIL_CACHE_MACH_H + +#include "xil_types.h" +#ifdef __cplusplus +extern "C" { +#endif + +/************************** Function Prototypes ******************************/ + +void Xil_DCacheInvalidateLine(u32 adr); +void Xil_DCacheFlushLine(u32 adr); +void Xil_DCacheStoreLine(u32 adr); +void Xil_ICacheInvalidateLine(u32 adr); + +void Xil_L1DCacheEnable(void); +void Xil_L1DCacheDisable(void); +void Xil_L1DCacheInvalidate(void); +void Xil_L1DCacheInvalidateLine(u32 adr); +void Xil_L1DCacheInvalidateRange(u32 adr, u32 len); +void Xil_L1DCacheFlush(void); +void Xil_L1DCacheFlushLine(u32 adr); +void Xil_L1DCacheFlushRange(u32 adr, u32 len); +void Xil_L1DCacheStoreLine(u32 adr); + +void Xil_L1ICacheEnable(void); +void Xil_L1ICacheDisable(void); +void Xil_L1ICacheInvalidate(void); +void Xil_L1ICacheInvalidateLine(u32 adr); +void Xil_L1ICacheInvalidateRange(u32 adr, u32 len); + +void Xil_L2CacheEnable(void); +void Xil_L2CacheDisable(void); +void Xil_L2CacheInvalidate(void); +void Xil_L2CacheInvalidateLine(u32 adr); +void Xil_L2CacheInvalidateRange(u32 adr, u32 len); +void Xil_L2CacheFlush(void); +void Xil_L2CacheFlushLine(u32 adr); +void Xil_L2CacheFlushRange(u32 adr, u32 len); +void Xil_L2CacheStoreLine(u32 adr); + +#ifdef __cplusplus +} +#endif + +#endif +/** +* @} End of "addtogroup a9_cache_apis". +*/ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_cache_vxworks.h b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_cache_vxworks.h new file mode 100644 index 0000000..7e2a7d9 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_cache_vxworks.h @@ -0,0 +1,89 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_cache_vxworks.h +* +* Contains the cache related functions for VxWorks that is wrapped by +* xil_cache. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date	 Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a hbm  12/11/09 Initial release
+*
+* 
+* +* @note +* +******************************************************************************/ + +#ifndef XIL_CACHE_VXWORKS_H +#define XIL_CACHE_VXWORKS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "vxWorks.h" +#include "vxLib.h" +#include "sysLibExtra.h" +#include "cacheLib.h" + +#if (CPU_FAMILY==PPC) + +#define Xil_DCacheEnable() cacheEnable(DATA_CACHE) + +#define Xil_DCacheDisable() cacheDisable(DATA_CACHE) + +#define Xil_DCacheInvalidateRange(Addr, Len) \ + cacheInvalidate(DATA_CACHE, (void *)(Addr), (Len)) + +#define Xil_DCacheFlushRange(Addr, Len) \ + cacheFlush(DATA_CACHE, (void *)(Addr), (Len)) + +#define Xil_ICacheEnable() cacheEnable(INSTRUCTION_CACHE) + +#define Xil_ICacheDisable() cacheDisable(INSTRUCTION_CACHE) + +#define Xil_ICacheInvalidateRange(Addr, Len) \ + cacheInvalidate(INSTRUCTION_CACHE, (void *)(Addr), (Len)) + + +#else +#error "Unknown processor / architecture. Must be PPC for VxWorks." +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_errata.h b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_errata.h new file mode 100644 index 0000000..c839b63 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_errata.h @@ -0,0 +1,127 @@ +/****************************************************************************** +* +* Copyright (C) 2013 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_errata.h +* +* @addtogroup a9_errata Cortex A9 Processor and pl310 Errata Support +* @{ +* Various ARM errata are handled in the standalone BSP. The implementation for +* errata handling follows ARM guidelines and is based on the open source Linux +* support for these errata. +* +* @note +* The errata handling is enabled by default. To disable handling of all the +* errata globally, un-define the macro ENABLE_ARM_ERRATA in xil_errata.h. To +* disable errata on a per-erratum basis, un-define relevant macros in +* xil_errata.h. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a srt  04/18/13 First release
+* 6.6   mus  12/07/17 Removed errata 753970, It fixes CR#989132.
+* 
+* +******************************************************************************/ +#ifndef XIL_ERRATA_H +#define XIL_ERRATA_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @name errata_definitions + * + * The errata conditions handled in the standalone BSP are listed below + * @{ + */ + +#define ENABLE_ARM_ERRATA 1 + +#ifdef ENABLE_ARM_ERRATA + +/** + * Errata No: 742230 + * Description: DMB operation may be faulty + */ +#define CONFIG_ARM_ERRATA_742230 1 + +/** + * Errata No: 743622 + * Description: Faulty hazard checking in the Store Buffer may lead + * to data corruption. + */ +#define CONFIG_ARM_ERRATA_743622 1 + +/** + * Errata No: 775420 + * Description: A data cache maintenance operation which aborts, + * might lead to deadlock + */ +#define CONFIG_ARM_ERRATA_775420 1 + +/** + * Errata No: 794073 + * Description: Speculative instruction fetches with MMU disabled + * might not comply with architectural requirements + */ +#define CONFIG_ARM_ERRATA_794073 1 + + +/** PL310 L2 Cache Errata */ + +/** + * Errata No: 588369 + * Description: Clean & Invalidate maintenance operations do not + * invalidate clean lines + */ +#define CONFIG_PL310_ERRATA_588369 1 + +/** + * Errata No: 727915 + * Description: Background Clean and Invalidate by Way operation + * can cause data corruption + */ +#define CONFIG_PL310_ERRATA_727915 1 + +/*@}*/ +#endif /* ENABLE_ARM_ERRATA */ + +#ifdef __cplusplus +} +#endif + +#endif /* XIL_ERRATA_H */ +/** +* @} End of "addtogroup a9_errata". +*/ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_exception.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_exception.c new file mode 100644 index 0000000..16facac --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_exception.c @@ -0,0 +1,379 @@ +/****************************************************************************** +* +* Copyright (C) 2015 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xil_exception.c +* +* This file contains low-level driver functions for the Cortex A53,A9,R5 exception +* Handler. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 5.2	pkp  	 28/05/15 First release
+* 6.0   mus      27/07/16 Consolidated exceptions for a53,a9 and r5
+*                         processors and added Xil_UndefinedExceptionHandler
+*                         for a53 32 bit and r5 as well.
+* 6.4   mus      08/06/17 Updated debug prints to replace %x with the %lx, to
+*                         fix the warnings.
+* 6.7   mna      26/04/18 Add an API to obtain a corresponding
+*                         Xil_ExceptionHandler entry from XExc_VectorTable.
+* 6.7  asa       18/05/18 Fix bugs in the API Xil_GetExceptionRegisterHandler.
+* 7.0  mus       07/03/19 Tweak Xil_ExceptionRegisterHandler and
+*                         Xil_GetExceptionRegisterHandler to support legacy
+*                         examples for Cortexa72 EL3 exception level.
+*
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_exception.h" +#include "xpseudo_asm.h" +#include "xdebug.h" +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + +typedef struct { + Xil_ExceptionHandler Handler; + void *Data; +} XExc_VectorTableEntry; + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Function Prototypes *****************************/ +static void Xil_ExceptionNullHandler(void *Data); +/************************** Variable Definitions *****************************/ +/* + * Exception vector table to store handlers for each exception vector. + */ +#if defined (__aarch64__) +XExc_VectorTableEntry XExc_VectorTable[XIL_EXCEPTION_ID_LAST + 1] = +{ + {Xil_ExceptionNullHandler, NULL}, + {Xil_SyncAbortHandler, NULL}, + {Xil_ExceptionNullHandler, NULL}, + {Xil_ExceptionNullHandler, NULL}, + {Xil_SErrorAbortHandler, NULL}, + +}; +#else +XExc_VectorTableEntry XExc_VectorTable[XIL_EXCEPTION_ID_LAST + 1] = +{ + {Xil_ExceptionNullHandler, NULL}, + {Xil_UndefinedExceptionHandler, NULL}, + {Xil_ExceptionNullHandler, NULL}, + {Xil_PrefetchAbortHandler, NULL}, + {Xil_DataAbortHandler, NULL}, + {Xil_ExceptionNullHandler, NULL}, + {Xil_ExceptionNullHandler, NULL}, +}; +#endif +#if !defined (__aarch64__) +u32 DataAbortAddr; /* Address of instruction causing data abort */ +u32 PrefetchAbortAddr; /* Address of instruction causing prefetch abort */ +u32 UndefinedExceptionAddr; /* Address of instruction causing Undefined + exception */ +#endif + +/*****************************************************************************/ + +/****************************************************************************/ +/** +* +* This function is a stub Handler that is the default Handler that gets called +* if the application has not setup a Handler for a specific exception. The +* function interface has to match the interface specified for a Handler even +* though none of the arguments are used. +* +* @param Data is unused by this function. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +static void Xil_ExceptionNullHandler(void *Data) +{ + (void) Data; +DieLoop: goto DieLoop; +} + +/****************************************************************************/ +/** +* @brief The function is a common API used to initialize exception handlers +* across all supported arm processors. For ARM Cortex-A53, Cortex-R5, +* and Cortex-A9, the exception handlers are being initialized +* statically and this function does not do anything. +* However, it is still present to take care of backward compatibility +* issues (in earlier versions of BSPs, this API was being used to +* initialize exception handlers). +* +* @param None. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void Xil_ExceptionInit(void) +{ + return; +} + +/*****************************************************************************/ +/** +* @brief Register a handler for a specific exception. This handler is being +* called when the processor encounters the specified exception. +* +* @param exception_id contains the ID of the exception source and should +* be in the range of 0 to XIL_EXCEPTION_ID_LAST. +* See xil_exception.h for further information. +* @param Handler to the Handler for that exception. +* @param Data is a reference to Data that will be passed to the +* Handler when it gets called. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void Xil_ExceptionRegisterHandler(u32 Exception_id, + Xil_ExceptionHandler Handler, + void *Data) +{ +#if defined (versal) && !defined(ARMR5) && EL3 +/* + * Cortexa72 processor in versal is coupled with GIC-500, and GIC-500 supports + * only FIQ at EL3. Hence, tweaking this API to always act on FIQ, + * ignoring argument passed by user. + */ + Exception_id = XIL_EXCEPTION_ID_FIQ_INT; +#endif + XExc_VectorTable[Exception_id].Handler = Handler; + XExc_VectorTable[Exception_id].Data = Data; +} + +/*****************************************************************************/ +/** +* @brief Get a handler for a specific exception. This handler is being +* called when the processor encounters the specified exception. +* +* @param exception_id contains the ID of the exception source and should +* be in the range of 0 to XIL_EXCEPTION_ID_LAST. +* See xil_exception.h for further information. +* @param Handler to the Handler for that exception. +* @param Data is a reference to Data that will be passed to the +* Handler when it gets called. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void Xil_GetExceptionRegisterHandler(u32 Exception_id, + Xil_ExceptionHandler *Handler, + void **Data) +{ +#if defined (versal) && !defined(ARMR5) && EL3 +/* + * Cortexa72 processor in versal is coupled with GIC-500, and GIC-500 supports + * only FIQ at EL3. Hence, tweaking this API to always act on FIQ, + * ignoring argument passed by user. + */ + Exception_id = XIL_EXCEPTION_ID_FIQ_INT; +#endif + + *Handler = XExc_VectorTable[Exception_id].Handler; + *Data = XExc_VectorTable[Exception_id].Data; +} + +/*****************************************************************************/ +/** +* +* @brief Removes the Handler for a specific exception Id. The stub Handler +* is then registered for this exception Id. +* +* @param exception_id contains the ID of the exception source and should +* be in the range of 0 to XIL_EXCEPTION_ID_LAST. +* See xil_exception.h for further information. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void Xil_ExceptionRemoveHandler(u32 Exception_id) +{ + Xil_ExceptionRegisterHandler(Exception_id, + Xil_ExceptionNullHandler, + NULL); +} + +#if defined (__aarch64__) +/*****************************************************************************/ +/** +* +* Default Synchronous abort handler which prints a debug message on console if +* Debug flag is enabled +* +* @param None +* +* @return None. +* +* @note None. +* +****************************************************************************/ + +void Xil_SyncAbortHandler(void *CallBackRef){ + (void) CallBackRef; + xdbg_printf(XDBG_DEBUG_ERROR, "Synchronous abort \n"); + while(1) { + ; + } +} + +/*****************************************************************************/ +/** +* +* Default SError abort handler which prints a debug message on console if +* Debug flag is enabled +* +* @param None +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void Xil_SErrorAbortHandler(void *CallBackRef){ + (void) CallBackRef; + xdbg_printf(XDBG_DEBUG_ERROR, "Synchronous abort \n"); + while(1) { + ; + } +} +#else +/*****************************************************************************/ +/* +* +* Default Data abort handler which prints data fault status register through +* which information about data fault can be acquired +* +* @param None +* +* @return None. +* +* @note None. +* +****************************************************************************/ + +void Xil_DataAbortHandler(void *CallBackRef){ + (void) CallBackRef; +#ifdef DEBUG + u32 FaultStatus; + + xdbg_printf(XDBG_DEBUG_ERROR, "Data abort \n"); + #ifdef __GNUC__ + FaultStatus = mfcp(XREG_CP15_DATA_FAULT_STATUS); + #elif defined (__ICCARM__) + mfcp(XREG_CP15_DATA_FAULT_STATUS,FaultStatus); + #else + { volatile register u32 Reg __asm(XREG_CP15_DATA_FAULT_STATUS); + FaultStatus = Reg; } + #endif + xdbg_printf(XDBG_DEBUG_GENERAL, "Data abort with Data Fault Status Register %lx\n",FaultStatus); + xdbg_printf(XDBG_DEBUG_GENERAL, "Address of Instruction causing Data abort %lx\n",DataAbortAddr); +#endif + while(1) { + ; + } +} + +/*****************************************************************************/ +/* +* +* Default Prefetch abort handler which prints prefetch fault status register through +* which information about instruction prefetch fault can be acquired +* +* @param None +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void Xil_PrefetchAbortHandler(void *CallBackRef){ + (void) CallBackRef; +#ifdef DEBUG + u32 FaultStatus; + + xdbg_printf(XDBG_DEBUG_ERROR, "Prefetch abort \n"); + #ifdef __GNUC__ + FaultStatus = mfcp(XREG_CP15_INST_FAULT_STATUS); + #elif defined (__ICCARM__) + mfcp(XREG_CP15_INST_FAULT_STATUS,FaultStatus); + #else + { volatile register u32 Reg __asm(XREG_CP15_INST_FAULT_STATUS); + FaultStatus = Reg; } + #endif + xdbg_printf(XDBG_DEBUG_GENERAL, "Prefetch abort with Instruction Fault Status Register %lx\n",FaultStatus); + xdbg_printf(XDBG_DEBUG_GENERAL, "Address of Instruction causing Prefetch abort %lx\n",PrefetchAbortAddr); +#endif + while(1) { + ; + } +} +/*****************************************************************************/ +/* +* +* Default undefined exception handler which prints address of the undefined +* instruction if debug prints are enabled +* +* @param None +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void Xil_UndefinedExceptionHandler(void *CallBackRef){ + (void) CallBackRef; + xdbg_printf(XDBG_DEBUG_GENERAL, "Address of the undefined instruction %lx\n",UndefinedExceptionAddr); + while(1) { + ; + } +} +#endif diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_exception.h b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_exception.h new file mode 100644 index 0000000..807f310 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_exception.h @@ -0,0 +1,285 @@ +/****************************************************************************** +* +* Copyright (C) 2015 - 2016 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_exception.h +* +* This header file contains ARM Cortex A53,A9,R5 specific exception related APIs. +* For exception related functions that can be used across all Xilinx supported +* processors, please use xil_exception.h. +* +* @addtogroup arm_exception_apis ARM Processor Exception Handling +* @{ +* ARM processors specific exception related APIs for cortex A53,A9 and R5 can +* utilized for enabling/disabling IRQ, registering/removing handler for +* exceptions or initializing exception vector table with null handler. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 5.2	pkp  	 28/05/15 First release
+* 6.0   mus      27/07/16 Consolidated file for a53,a9 and r5 processors
+* 6.7   mna      26/04/18 Add API Xil_GetExceptionRegisterHandler.
+* 6.7   asa      18/05/18 Update signature of API Xil_GetExceptionRegisterHandler.
+* 7.0   mus      01/03/19 Tweak Xil_ExceptionEnableMask and
+*                         Xil_ExceptionDisableMask macros to support legacy
+*                         examples for Cortexa72 EL3 exception level.
+* 
+* +******************************************************************************/ + +#ifndef XIL_EXCEPTION_H /* prevent circular inclusions */ +#define XIL_EXCEPTION_H /* by using protection macros */ + +/***************************** Include Files ********************************/ + +#include "xil_types.h" +#include "xpseudo_asm.h" +#include "bspconfig.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************** Constant Definitions ****************************/ + +#define XIL_EXCEPTION_FIQ XREG_CPSR_FIQ_ENABLE +#define XIL_EXCEPTION_IRQ XREG_CPSR_IRQ_ENABLE +#define XIL_EXCEPTION_ALL (XREG_CPSR_FIQ_ENABLE | XREG_CPSR_IRQ_ENABLE) + +#define XIL_EXCEPTION_ID_FIRST 0U +#if defined (__aarch64__) +#define XIL_EXCEPTION_ID_SYNC_INT 1U +#define XIL_EXCEPTION_ID_IRQ_INT 2U +#define XIL_EXCEPTION_ID_FIQ_INT 3U +#define XIL_EXCEPTION_ID_SERROR_ABORT_INT 4U +#define XIL_EXCEPTION_ID_LAST 5U +#else +#define XIL_EXCEPTION_ID_RESET 0U +#define XIL_EXCEPTION_ID_UNDEFINED_INT 1U +#define XIL_EXCEPTION_ID_SWI_INT 2U +#define XIL_EXCEPTION_ID_PREFETCH_ABORT_INT 3U +#define XIL_EXCEPTION_ID_DATA_ABORT_INT 4U +#define XIL_EXCEPTION_ID_IRQ_INT 5U +#define XIL_EXCEPTION_ID_FIQ_INT 6U +#define XIL_EXCEPTION_ID_LAST 6U +#endif + +/* + * XIL_EXCEPTION_ID_INT is defined for all Xilinx processors. + */ +#if defined (versal) && !defined(ARMR5) && EL3 +#define XIL_EXCEPTION_ID_INT XIL_EXCEPTION_ID_FIQ_INT +#else +#define XIL_EXCEPTION_ID_INT XIL_EXCEPTION_ID_IRQ_INT +#endif + +/**************************** Type Definitions ******************************/ + +/** + * This typedef is the exception handler function. + */ +typedef void (*Xil_ExceptionHandler)(void *data); +typedef void (*Xil_InterruptHandler)(void *data); + +/***************** Macros (Inline Functions) Definitions ********************/ + +/****************************************************************************/ +/** +* @brief Enable Exceptions. +* +* @param Mask: Value for enabling the exceptions. +* +* @return None. +* +* @note If bit is 0, exception is enabled. +* C-Style signature: void Xil_ExceptionEnableMask(Mask) +* +******************************************************************************/ +#if defined (versal) && !defined(ARMR5) && EL3 +/* + * Cortexa72 processor in versal is coupled with GIC-500, and GIC-500 supports + * only FIQ at EL3. Hence, tweaking this macro to always enable FIQ + * ignoring argument passed by user. + */ +#define Xil_ExceptionEnableMask(Mask) \ + mtcpsr(mfcpsr() & ~ ((XIL_EXCEPTION_FIQ) & XIL_EXCEPTION_ALL)) +#elif defined (__GNUC__) || defined (__ICCARM__) +#define Xil_ExceptionEnableMask(Mask) \ + mtcpsr(mfcpsr() & ~ ((Mask) & XIL_EXCEPTION_ALL)) +#else +#define Xil_ExceptionEnableMask(Mask) \ + { \ + register u32 Reg __asm("cpsr"); \ + mtcpsr((Reg) & (~((Mask) & XIL_EXCEPTION_ALL))); \ + } +#endif +/****************************************************************************/ +/** +* @brief Enable the IRQ exception. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +#if defined (versal) && !defined(ARMR5) && EL3 +#define Xil_ExceptionEnable() \ + Xil_ExceptionEnableMask(XIL_EXCEPTION_FIQ) +#else +#define Xil_ExceptionEnable() \ + Xil_ExceptionEnableMask(XIL_EXCEPTION_IRQ) +#endif + +/****************************************************************************/ +/** +* @brief Disable Exceptions. +* +* @param Mask: Value for disabling the exceptions. +* +* @return None. +* +* @note If bit is 1, exception is disabled. +* C-Style signature: Xil_ExceptionDisableMask(Mask) +* +******************************************************************************/ +#if defined (versal) && !defined(ARMR5) && EL3 +/* + * Cortexa72 processor in versal is coupled with GIC-500, and GIC-500 supports + * only FIQ at EL3. Hence, tweaking this macro to always disable FIQ + * ignoring argument passed by user. + */ +#define Xil_ExceptionDisableMask(Mask) \ + mtcpsr(mfcpsr() | ((XIL_EXCEPTION_FIQ) & XIL_EXCEPTION_ALL)) +#elif defined (__GNUC__) || defined (__ICCARM__) +#define Xil_ExceptionDisableMask(Mask) \ + mtcpsr(mfcpsr() | ((Mask) & XIL_EXCEPTION_ALL)) +#else +#define Xil_ExceptionDisableMask(Mask) \ + { \ + register u32 Reg __asm("cpsr"); \ + mtcpsr((Reg) | ((Mask) & XIL_EXCEPTION_ALL)); \ + } +#endif +/****************************************************************************/ +/** +* Disable the IRQ exception. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +#define Xil_ExceptionDisable() \ + Xil_ExceptionDisableMask(XIL_EXCEPTION_IRQ) + +#if !defined (__aarch64__) && !defined (ARMA53_32) +/****************************************************************************/ +/** +* @brief Enable nested interrupts by clearing the I and F bits in CPSR. This +* API is defined for cortex-a9 and cortex-r5. +* +* @return None. +* +* @note This macro is supposed to be used from interrupt handlers. In the +* interrupt handler the interrupts are disabled by default (I and F +* are 1). To allow nesting of interrupts, this macro should be +* used. It clears the I and F bits by changing the ARM mode to +* system mode. Once these bits are cleared and provided the +* preemption of interrupt conditions are met in the GIC, nesting of +* interrupts will start happening. +* Caution: This macro must be used with caution. Before calling this +* macro, the user must ensure that the source of the current IRQ +* is appropriately cleared. Otherwise, as soon as we clear the I and +* F bits, there can be an infinite loop of interrupts with an +* eventual crash (all the stack space getting consumed). +******************************************************************************/ +#define Xil_EnableNestedInterrupts() \ + __asm__ __volatile__ ("stmfd sp!, {lr}"); \ + __asm__ __volatile__ ("mrs lr, spsr"); \ + __asm__ __volatile__ ("stmfd sp!, {lr}"); \ + __asm__ __volatile__ ("msr cpsr_c, #0x1F"); \ + __asm__ __volatile__ ("stmfd sp!, {lr}"); + +/****************************************************************************/ +/** +* @brief Disable the nested interrupts by setting the I and F bits. This API +* is defined for cortex-a9 and cortex-r5. +* +* @return None. +* +* @note This macro is meant to be called in the interrupt service routines. +* This macro cannot be used independently. It can only be used when +* nesting of interrupts have been enabled by using the macro +* Xil_EnableNestedInterrupts(). In a typical flow, the user first +* calls the Xil_EnableNestedInterrupts in the ISR at the appropriate +* point. The user then must call this macro before exiting the interrupt +* service routine. This macro puts the ARM back in IRQ/FIQ mode and +* hence sets back the I and F bits. +******************************************************************************/ +#define Xil_DisableNestedInterrupts() \ + __asm__ __volatile__ ("ldmfd sp!, {lr}"); \ + __asm__ __volatile__ ("msr cpsr_c, #0x92"); \ + __asm__ __volatile__ ("ldmfd sp!, {lr}"); \ + __asm__ __volatile__ ("msr spsr_cxsf, lr"); \ + __asm__ __volatile__ ("ldmfd sp!, {lr}"); \ + +#endif +/************************** Variable Definitions ****************************/ + +/************************** Function Prototypes *****************************/ + +extern void Xil_ExceptionRegisterHandler(u32 Exception_id, + Xil_ExceptionHandler Handler, + void *Data); + +extern void Xil_ExceptionRemoveHandler(u32 Exception_id); +extern void Xil_GetExceptionRegisterHandler(u32 Exception_id, + Xil_ExceptionHandler *Handler, void **Data); + +extern void Xil_ExceptionInit(void); +#if defined (__aarch64__) +void Xil_SyncAbortHandler(void *CallBackRef); +void Xil_SErrorAbortHandler(void *CallBackRef); +#else +extern void Xil_DataAbortHandler(void *CallBackRef); +extern void Xil_PrefetchAbortHandler(void *CallBackRef); +extern void Xil_UndefinedExceptionHandler(void *CallBackRef); +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* XIL_EXCEPTION_H */ +/** +* @} End of "addtogroup arm_exception_apis". +*/ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_hal.h b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_hal.h new file mode 100644 index 0000000..e8971c9 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_hal.h @@ -0,0 +1,65 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_hal.h +* +* Contains all the HAL header files. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date	 Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a hbm  07/28/09 Initial release
+*
+* 
+* +* @note +* +******************************************************************************/ + +#ifndef XIL_HAL_H +#define XIL_HAL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "xil_cache.h" +#include "xil_io.h" +#include "xil_assert.h" +#include "xil_exception.h" +#include "xil_types.h" + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_io.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_io.c new file mode 100644 index 0000000..6ed1559 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_io.c @@ -0,0 +1,98 @@ +/****************************************************************************** +* +* Copyright (C) 2014 - 2016 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_io.c +* +* Contains I/O functions for memory-mapped or non-memory-mapped I/O +* architectures. +* +* @note +* +* This file contains architecture-dependent code. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 5.00 	pkp  	 05/29/14 First release
+* 
+******************************************************************************/ + + +/***************************** Include Files *********************************/ +#include "xil_io.h" +#include "xil_types.h" +#include "xil_assert.h" + +/*****************************************************************************/ +/** +* +* @brief Perform a 16-bit endian converion. +* +* @param Data: 16 bit value to be converted +* +* @return 16 bit Data with converted endianess +* +******************************************************************************/ +u16 Xil_EndianSwap16(u16 Data) +{ + return (u16) (((Data & 0xFF00U) >> 8U) | ((Data & 0x00FFU) << 8U)); +} + +/*****************************************************************************/ +/** +* +* @brief Perform a 32-bit endian converion. +* +* @param Data: 32 bit value to be converted +* +* @return 32 bit data with converted endianess +* +******************************************************************************/ +u32 Xil_EndianSwap32(u32 Data) +{ + u16 LoWord; + u16 HiWord; + + /* get each of the half words from the 32 bit word */ + + LoWord = (u16) (Data & 0x0000FFFFU); + HiWord = (u16) ((Data & 0xFFFF0000U) >> 16U); + + /* byte swap each of the 16 bit half words */ + + LoWord = (((LoWord & 0xFF00U) >> 8U) | ((LoWord & 0x00FFU) << 8U)); + HiWord = (((HiWord & 0xFF00U) >> 8U) | ((HiWord & 0x00FFU) << 8U)); + + /* swap the half words before returning the value */ + + return ((((u32)LoWord) << (u32)16U) | (u32)HiWord); +} diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_io.h b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_io.h new file mode 100644 index 0000000..00207cf --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_io.h @@ -0,0 +1,341 @@ +/****************************************************************************** +* +* Copyright (C) 2014 - 2016 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_io.h +* +* @addtogroup common_io_interfacing_apis Register IO interfacing APIs +* +* The xil_io.h file contains the interface for the general I/O component, which +* encapsulates the Input/Output functions for the processors that do not +* require any special I/O handling. +* +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 5.00 	pkp  	 05/29/14 First release
+* 6.00  mus      08/19/16 Remove checking of __LITTLE_ENDIAN__ flag for
+*                         ARM processors
+* 
+******************************************************************************/ + +#ifndef XIL_IO_H /* prevent circular inclusions */ +#define XIL_IO_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_printf.h" + +#if defined (__MICROBLAZE__) +#include "mb_interface.h" +#else +#include "xpseudo_asm.h" +#endif + +/************************** Function Prototypes ******************************/ +u16 Xil_EndianSwap16(u16 Data); +u32 Xil_EndianSwap32(u32 Data); +#ifdef ENABLE_SAFETY +extern u32 XStl_RegUpdate(u32 RegAddr, u32 RegVal); +#endif + +/***************** Macros (Inline Functions) Definitions *********************/ +#if defined __GNUC__ +#if defined (__MICROBLAZE__) +# define INST_SYNC mbar(0) +# define DATA_SYNC mbar(1) +# else +# define SYNCHRONIZE_IO dmb() +# define INST_SYNC isb() +# define DATA_SYNC dsb() +# endif +#else +# define SYNCHRONIZE_IO +# define INST_SYNC +# define DATA_SYNC +# define INST_SYNC +# define DATA_SYNC +#endif + +#if defined (__GNUC__) || defined (__ICCARM__) || defined (__MICROBLAZE__) +#define INLINE inline +#else +#define INLINE __inline +#endif + +/*****************************************************************************/ +/** +* +* @brief Performs an input operation for a memory location by reading +* from the specified address and returning the 8 bit Value read from +* that address. +* +* @param Addr: contains the address to perform the input operation +* +* @return The 8 bit Value read from the specified input address. + +* +******************************************************************************/ +static INLINE u8 Xil_In8(UINTPTR Addr) +{ + return *(volatile u8 *) Addr; +} + +/*****************************************************************************/ +/** +* +* @brief Performs an input operation for a memory location by reading from +* the specified address and returning the 16 bit Value read from that +* address. +* +* @param Addr: contains the address to perform the input operation +* +* @return The 16 bit Value read from the specified input address. +* +******************************************************************************/ +static INLINE u16 Xil_In16(UINTPTR Addr) +{ + return *(volatile u16 *) Addr; +} + +/*****************************************************************************/ +/** +* +* @brief Performs an input operation for a memory location by +* reading from the specified address and returning the 32 bit Value +* read from that address. +* +* @param Addr: contains the address to perform the input operation +* +* @return The 32 bit Value read from the specified input address. +* +******************************************************************************/ +static INLINE u32 Xil_In32(UINTPTR Addr) +{ + return *(volatile u32 *) Addr; +} + +/*****************************************************************************/ +/** +* +* @brief Performs an input operation for a memory location by reading the +* 64 bit Value read from that address. +* +* +* @param Addr: contains the address to perform the input operation +* +* @return The 64 bit Value read from the specified input address. +* +******************************************************************************/ +static INLINE u64 Xil_In64(UINTPTR Addr) +{ + return *(volatile u64 *) Addr; +} + +/*****************************************************************************/ +/** +* +* @brief Performs an output operation for an memory location by +* writing the 8 bit Value to the the specified address. +* +* @param Addr: contains the address to perform the output operation +* @param Value: contains the 8 bit Value to be written at the specified +* address. +* +* @return None. +* +******************************************************************************/ +static INLINE void Xil_Out8(UINTPTR Addr, u8 Value) +{ + volatile u8 *LocalAddr = (volatile u8 *)Addr; + *LocalAddr = Value; +} + +/*****************************************************************************/ +/** +* +* @brief Performs an output operation for a memory location by writing the +* 16 bit Value to the the specified address. +* +* @param Addr contains the address to perform the output operation +* @param Value contains the Value to be written at the specified address. +* +* @return None. +* +******************************************************************************/ +static INLINE void Xil_Out16(UINTPTR Addr, u16 Value) +{ + volatile u16 *LocalAddr = (volatile u16 *)Addr; + *LocalAddr = Value; +} + +/*****************************************************************************/ +/** +* +* @brief Performs an output operation for a memory location by writing the +* 32 bit Value to the the specified address. +* +* @param Addr contains the address to perform the output operation +* @param Value contains the 32 bit Value to be written at the specified +* address. +* +* @return None. +* +******************************************************************************/ +static INLINE void Xil_Out32(UINTPTR Addr, u32 Value) +{ +#ifndef ENABLE_SAFETY + volatile u32 *LocalAddr = (volatile u32 *)Addr; + *LocalAddr = Value; +#else + XStl_RegUpdate(Addr, Value); +#endif +} + +/*****************************************************************************/ +/** +* +* @brief Performs an output operation for a memory location by writing the +* 64 bit Value to the the specified address. +* +* @param Addr contains the address to perform the output operation +* @param Value contains 64 bit Value to be written at the specified address. +* +* @return None. +* +******************************************************************************/ +static INLINE void Xil_Out64(UINTPTR Addr, u64 Value) +{ + volatile u64 *LocalAddr = (volatile u64 *)Addr; + *LocalAddr = Value; +} + +#if defined (__MICROBLAZE__) +#ifdef __LITTLE_ENDIAN__ +# define Xil_In16LE Xil_In16 +# define Xil_In32LE Xil_In32 +# define Xil_Out16LE Xil_Out16 +# define Xil_Out32LE Xil_Out32 +# define Xil_Htons Xil_EndianSwap16 +# define Xil_Htonl Xil_EndianSwap32 +# define Xil_Ntohs Xil_EndianSwap16 +# define Xil_Ntohl Xil_EndianSwap32 +# else +# define Xil_In16BE Xil_In16 +# define Xil_In32BE Xil_In32 +# define Xil_Out16BE Xil_Out16 +# define Xil_Out32BE Xil_Out32 +# define Xil_Htons(Data) (Data) +# define Xil_Htonl(Data) (Data) +# define Xil_Ntohs(Data) (Data) +# define Xil_Ntohl(Data) (Data) +#endif +#else +# define Xil_In16LE Xil_In16 +# define Xil_In32LE Xil_In32 +# define Xil_Out16LE Xil_Out16 +# define Xil_Out32LE Xil_Out32 +# define Xil_Htons Xil_EndianSwap16 +# define Xil_Htonl Xil_EndianSwap32 +# define Xil_Ntohs Xil_EndianSwap16 +# define Xil_Ntohl Xil_EndianSwap32 +#endif + +#if defined (__MICROBLAZE__) +#ifdef __LITTLE_ENDIAN__ +static INLINE u16 Xil_In16BE(UINTPTR Addr) +#else +static INLINE u16 Xil_In16LE(UINTPTR Addr) +#endif +#else +static INLINE u16 Xil_In16BE(UINTPTR Addr) +#endif +{ + u16 value = Xil_In16(Addr); + return Xil_EndianSwap16(value); +} + +#if defined (__MICROBLAZE__) +#ifdef __LITTLE_ENDIAN__ +static INLINE u32 Xil_In32BE(UINTPTR Addr) +#else +static INLINE u32 Xil_In32LE(UINTPTR Addr) +#endif +#else +static INLINE u32 Xil_In32BE(UINTPTR Addr) +#endif +{ + u32 value = Xil_In32(Addr); + return Xil_EndianSwap32(value); +} + +#if defined (__MICROBLAZE__) +#ifdef __LITTLE_ENDIAN__ +static INLINE void Xil_Out16BE(UINTPTR Addr, u16 Value) +#else +static INLINE void Xil_Out16LE(UINTPTR Addr, u16 Value) +#endif +#else +static INLINE void Xil_Out16BE(UINTPTR Addr, u16 Value) +#endif +{ + Value = Xil_EndianSwap16(Value); + Xil_Out16(Addr, Value); +} + +#if defined (__MICROBLAZE__) +#ifdef __LITTLE_ENDIAN__ +static INLINE void Xil_Out32BE(UINTPTR Addr, u32 Value) +#else +static INLINE void Xil_Out32LE(UINTPTR Addr, u32 Value) +#endif +#else +static INLINE void Xil_Out32BE(UINTPTR Addr, u32 Value) +#endif +{ + Value = Xil_EndianSwap32(Value); + Xil_Out32(Addr, Value); +} + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** +* @} End of "addtogroup common_io_interfacing_apis". +*/ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_macroback.h b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_macroback.h new file mode 100644 index 0000000..b245c18 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_macroback.h @@ -0,0 +1,1056 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +/*********************************************************************/ +/** + * @file xil_macroback.h + * + * This header file is meant to bring back the removed _m macros. + * This header file must be included last. + * The following macros are not defined here due to the driver change: + * XGpio_mSetDataDirection + * XGpio_mGetDataReg + * XGpio_mSetDataReg + * XIIC_RESET + * XIIC_CLEAR_STATS + * XSpi_mReset + * XSysAce_mSetCfgAddr + * XSysAce_mIsCfgDone + * XTft_mSetPixel + * XTft_mGetPixel + * XWdtTb_mEnableWdt + * XWdtTb_mDisbleWdt + * XWdtTb_mRestartWdt + * XWdtTb_mGetTimebaseReg + * XWdtTb_mHasReset + * + * Please refer the corresonding driver document for replacement. + * + *********************************************************************/ + +#ifndef XIL_MACROBACK_H +#define XIL_MACROBACK_H + +#ifdef __cplusplus +extern "C" { +#endif + +/*********************************************************************/ +/** + * Macros for Driver XCan + * + *********************************************************************/ +#ifndef XCan_mReadReg +#define XCan_mReadReg XCan_ReadReg +#endif + +#ifndef XCan_mWriteReg +#define XCan_mWriteReg XCan_WriteReg +#endif + +#ifndef XCan_mIsTxDone +#define XCan_mIsTxDone XCan_IsTxDone +#endif + +#ifndef XCan_mIsTxFifoFull +#define XCan_mIsTxFifoFull XCan_IsTxFifoFull +#endif + +#ifndef XCan_mIsHighPriorityBufFull +#define XCan_mIsHighPriorityBufFull XCan_IsHighPriorityBufFull +#endif + +#ifndef XCan_mIsRxEmpty +#define XCan_mIsRxEmpty XCan_IsRxEmpty +#endif + +#ifndef XCan_mIsAcceptFilterBusy +#define XCan_mIsAcceptFilterBusy XCan_IsAcceptFilterBusy +#endif + +#ifndef XCan_mCreateIdValue +#define XCan_mCreateIdValue XCan_CreateIdValue +#endif + +#ifndef XCan_mCreateDlcValue +#define XCan_mCreateDlcValue XCan_CreateDlcValue +#endif + +/*********************************************************************/ +/** + * Macros for Driver XDmaCentral + * + *********************************************************************/ +#ifndef XDmaCentral_mWriteReg +#define XDmaCentral_mWriteReg XDmaCentral_WriteReg +#endif + +#ifndef XDmaCentral_mReadReg +#define XDmaCentral_mReadReg XDmaCentral_ReadReg +#endif + +/*********************************************************************/ +/** + * Macros for Driver XDsAdc + * + *********************************************************************/ +#ifndef XDsAdc_mWriteReg +#define XDsAdc_mWriteReg XDsAdc_WriteReg +#endif + +#ifndef XDsAdc_mReadReg +#define XDsAdc_mReadReg XDsAdc_ReadReg +#endif + +#ifndef XDsAdc_mIsEmpty +#define XDsAdc_mIsEmpty XDsAdc_IsEmpty +#endif + +#ifndef XDsAdc_mSetFstmReg +#define XDsAdc_mSetFstmReg XDsAdc_SetFstmReg +#endif + +#ifndef XDsAdc_mGetFstmReg +#define XDsAdc_mGetFstmReg XDsAdc_GetFstmReg +#endif + +#ifndef XDsAdc_mEnableConversion +#define XDsAdc_mEnableConversion XDsAdc_EnableConversion +#endif + +#ifndef XDsAdc_mDisableConversion +#define XDsAdc_mDisableConversion XDsAdc_DisableConversion +#endif + +#ifndef XDsAdc_mGetFifoOccyReg +#define XDsAdc_mGetFifoOccyReg XDsAdc_GetFifoOccyReg +#endif + +/*********************************************************************/ +/** + * Macros for Driver XDsDac + * + *********************************************************************/ +#ifndef XDsDac_mWriteReg +#define XDsDac_mWriteReg XDsDac_WriteReg +#endif + +#ifndef XDsDac_mReadReg +#define XDsDac_mReadReg XDsDac_ReadReg +#endif + +#ifndef XDsDac_mIsEmpty +#define XDsDac_mIsEmpty XDsDac_IsEmpty +#endif + +#ifndef XDsDac_mFifoIsFull +#define XDsDac_mFifoIsFull XDsDac_FifoIsFull +#endif + +#ifndef XDsDac_mGetVacancy +#define XDsDac_mGetVacancy XDsDac_GetVacancy +#endif + +/*********************************************************************/ +/** + * Macros for Driver XEmacLite + * + *********************************************************************/ +#ifndef XEmacLite_mReadReg +#define XEmacLite_mReadReg XEmacLite_ReadReg +#endif + +#ifndef XEmacLite_mWriteReg +#define XEmacLite_mWriteReg XEmacLite_WriteReg +#endif + +#ifndef XEmacLite_mGetTxStatus +#define XEmacLite_mGetTxStatus XEmacLite_GetTxStatus +#endif + +#ifndef XEmacLite_mSetTxStatus +#define XEmacLite_mSetTxStatus XEmacLite_SetTxStatus +#endif + +#ifndef XEmacLite_mGetRxStatus +#define XEmacLite_mGetRxStatus XEmacLite_GetRxStatus +#endif + +#ifndef XEmacLite_mSetRxStatus +#define XEmacLite_mSetRxStatus XEmacLite_SetRxStatus +#endif + +#ifndef XEmacLite_mIsTxDone +#define XEmacLite_mIsTxDone XEmacLite_IsTxDone +#endif + +#ifndef XEmacLite_mIsRxEmpty +#define XEmacLite_mIsRxEmpty XEmacLite_IsRxEmpty +#endif + +#ifndef XEmacLite_mNextTransmitAddr +#define XEmacLite_mNextTransmitAddr XEmacLite_NextTransmitAddr +#endif + +#ifndef XEmacLite_mNextReceiveAddr +#define XEmacLite_mNextReceiveAddr XEmacLite_NextReceiveAddr +#endif + +#ifndef XEmacLite_mIsMdioConfigured +#define XEmacLite_mIsMdioConfigured XEmacLite_IsMdioConfigured +#endif + +#ifndef XEmacLite_mIsLoopbackConfigured +#define XEmacLite_mIsLoopbackConfigured XEmacLite_IsLoopbackConfigured +#endif + +#ifndef XEmacLite_mGetReceiveDataLength +#define XEmacLite_mGetReceiveDataLength XEmacLite_GetReceiveDataLength +#endif + +#ifndef XEmacLite_mGetTxActive +#define XEmacLite_mGetTxActive XEmacLite_GetTxActive +#endif + +#ifndef XEmacLite_mSetTxActive +#define XEmacLite_mSetTxActive XEmacLite_SetTxActive +#endif + +/*********************************************************************/ +/** + * Macros for Driver XGpio + * + *********************************************************************/ +#ifndef XGpio_mWriteReg +#define XGpio_mWriteReg XGpio_WriteReg +#endif + +#ifndef XGpio_mReadReg +#define XGpio_mReadReg XGpio_ReadReg +#endif + +/*********************************************************************/ +/** + * Macros for Driver XHwIcap + * + *********************************************************************/ +#ifndef XHwIcap_mFifoWrite +#define XHwIcap_mFifoWrite XHwIcap_FifoWrite +#endif + +#ifndef XHwIcap_mFifoRead +#define XHwIcap_mFifoRead XHwIcap_FifoRead +#endif + +#ifndef XHwIcap_mSetSizeReg +#define XHwIcap_mSetSizeReg XHwIcap_SetSizeReg +#endif + +#ifndef XHwIcap_mGetControlReg +#define XHwIcap_mGetControlReg XHwIcap_GetControlReg +#endif + +#ifndef XHwIcap_mStartConfig +#define XHwIcap_mStartConfig XHwIcap_StartConfig +#endif + +#ifndef XHwIcap_mStartReadBack +#define XHwIcap_mStartReadBack XHwIcap_StartReadBack +#endif + +#ifndef XHwIcap_mGetStatusReg +#define XHwIcap_mGetStatusReg XHwIcap_GetStatusReg +#endif + +#ifndef XHwIcap_mIsTransferDone +#define XHwIcap_mIsTransferDone XHwIcap_IsTransferDone +#endif + +#ifndef XHwIcap_mIsDeviceBusy +#define XHwIcap_mIsDeviceBusy XHwIcap_IsDeviceBusy +#endif + +#ifndef XHwIcap_mIntrGlobalEnable +#define XHwIcap_mIntrGlobalEnable XHwIcap_IntrGlobalEnable +#endif + +#ifndef XHwIcap_mIntrGlobalDisable +#define XHwIcap_mIntrGlobalDisable XHwIcap_IntrGlobalDisable +#endif + +#ifndef XHwIcap_mIntrGetStatus +#define XHwIcap_mIntrGetStatus XHwIcap_IntrGetStatus +#endif + +#ifndef XHwIcap_mIntrDisable +#define XHwIcap_mIntrDisable XHwIcap_IntrDisable +#endif + +#ifndef XHwIcap_mIntrEnable +#define XHwIcap_mIntrEnable XHwIcap_IntrEnable +#endif + +#ifndef XHwIcap_mIntrGetEnabled +#define XHwIcap_mIntrGetEnabled XHwIcap_IntrGetEnabled +#endif + +#ifndef XHwIcap_mIntrClear +#define XHwIcap_mIntrClear XHwIcap_IntrClear +#endif + +#ifndef XHwIcap_mGetWrFifoVacancy +#define XHwIcap_mGetWrFifoVacancy XHwIcap_GetWrFifoVacancy +#endif + +#ifndef XHwIcap_mGetRdFifoOccupancy +#define XHwIcap_mGetRdFifoOccupancy XHwIcap_GetRdFifoOccupancy +#endif + +#ifndef XHwIcap_mSliceX2Col +#define XHwIcap_mSliceX2Col XHwIcap_SliceX2Col +#endif + +#ifndef XHwIcap_mSliceY2Row +#define XHwIcap_mSliceY2Row XHwIcap_SliceY2Row +#endif + +#ifndef XHwIcap_mSliceXY2Slice +#define XHwIcap_mSliceXY2Slice XHwIcap_SliceXY2Slice +#endif + +#ifndef XHwIcap_mReadReg +#define XHwIcap_mReadReg XHwIcap_ReadReg +#endif + +#ifndef XHwIcap_mWriteReg +#define XHwIcap_mWriteReg XHwIcap_WriteReg +#endif + +/*********************************************************************/ +/** + * Macros for Driver XIic + * + *********************************************************************/ +#ifndef XIic_mReadReg +#define XIic_mReadReg XIic_ReadReg +#endif + +#ifndef XIic_mWriteReg +#define XIic_mWriteReg XIic_WriteReg +#endif + +#ifndef XIic_mEnterCriticalRegion +#define XIic_mEnterCriticalRegion XIic_IntrGlobalDisable +#endif + +#ifndef XIic_mExitCriticalRegion +#define XIic_mExitCriticalRegion XIic_IntrGlobalEnable +#endif + +#ifndef XIIC_GINTR_DISABLE +#define XIIC_GINTR_DISABLE XIic_IntrGlobalDisable +#endif + +#ifndef XIIC_GINTR_ENABLE +#define XIIC_GINTR_ENABLE XIic_IntrGlobalEnable +#endif + +#ifndef XIIC_IS_GINTR_ENABLED +#define XIIC_IS_GINTR_ENABLED XIic_IsIntrGlobalEnabled +#endif + +#ifndef XIIC_WRITE_IISR +#define XIIC_WRITE_IISR XIic_WriteIisr +#endif + +#ifndef XIIC_READ_IISR +#define XIIC_READ_IISR XIic_ReadIisr +#endif + +#ifndef XIIC_WRITE_IIER +#define XIIC_WRITE_IIER XIic_WriteIier +#endif + +#ifndef XIic_mClearIisr +#define XIic_mClearIisr XIic_ClearIisr +#endif + +#ifndef XIic_mSend7BitAddress +#define XIic_mSend7BitAddress XIic_Send7BitAddress +#endif + +#ifndef XIic_mDynSend7BitAddress +#define XIic_mDynSend7BitAddress XIic_DynSend7BitAddress +#endif + +#ifndef XIic_mDynSendStartStopAddress +#define XIic_mDynSendStartStopAddress XIic_DynSendStartStopAddress +#endif + +#ifndef XIic_mDynSendStop +#define XIic_mDynSendStop XIic_DynSendStop +#endif + +#ifndef XIic_mSend10BitAddrByte1 +#define XIic_mSend10BitAddrByte1 XIic_Send10BitAddrByte1 +#endif + +#ifndef XIic_mSend10BitAddrByte2 +#define XIic_mSend10BitAddrByte2 XIic_Send10BitAddrByte2 +#endif + +#ifndef XIic_mSend7BitAddr +#define XIic_mSend7BitAddr XIic_Send7BitAddr +#endif + +#ifndef XIic_mDisableIntr +#define XIic_mDisableIntr XIic_DisableIntr +#endif + +#ifndef XIic_mEnableIntr +#define XIic_mEnableIntr XIic_EnableIntr +#endif + +#ifndef XIic_mClearIntr +#define XIic_mClearIntr XIic_ClearIntr +#endif + +#ifndef XIic_mClearEnableIntr +#define XIic_mClearEnableIntr XIic_ClearEnableIntr +#endif + +#ifndef XIic_mFlushRxFifo +#define XIic_mFlushRxFifo XIic_FlushRxFifo +#endif + +#ifndef XIic_mFlushTxFifo +#define XIic_mFlushTxFifo XIic_FlushTxFifo +#endif + +#ifndef XIic_mReadRecvByte +#define XIic_mReadRecvByte XIic_ReadRecvByte +#endif + +#ifndef XIic_mWriteSendByte +#define XIic_mWriteSendByte XIic_WriteSendByte +#endif + +#ifndef XIic_mSetControlRegister +#define XIic_mSetControlRegister XIic_SetControlRegister +#endif + +/*********************************************************************/ +/** + * Macros for Driver XIntc + * + *********************************************************************/ +#ifndef XIntc_mMasterEnable +#define XIntc_mMasterEnable XIntc_MasterEnable +#endif + +#ifndef XIntc_mMasterDisable +#define XIntc_mMasterDisable XIntc_MasterDisable +#endif + +#ifndef XIntc_mEnableIntr +#define XIntc_mEnableIntr XIntc_EnableIntr +#endif + +#ifndef XIntc_mDisableIntr +#define XIntc_mDisableIntr XIntc_DisableIntr +#endif + +#ifndef XIntc_mAckIntr +#define XIntc_mAckIntr XIntc_AckIntr +#endif + +#ifndef XIntc_mGetIntrStatus +#define XIntc_mGetIntrStatus XIntc_GetIntrStatus +#endif + +/*********************************************************************/ +/** + * Macros for Driver XLlDma + * + *********************************************************************/ +#ifndef XLlDma_mBdRead +#define XLlDma_mBdRead XLlDma_BdRead +#endif + +#ifndef XLlDma_mBdWrite +#define XLlDma_mBdWrite XLlDma_BdWrite +#endif + +#ifndef XLlDma_mWriteReg +#define XLlDma_mWriteReg XLlDma_WriteReg +#endif + +#ifndef XLlDma_mReadReg +#define XLlDma_mReadReg XLlDma_ReadReg +#endif + +#ifndef XLlDma_mBdClear +#define XLlDma_mBdClear XLlDma_BdClear +#endif + +#ifndef XLlDma_mBdSetStsCtrl +#define XLlDma_mBdSetStsCtrl XLlDma_BdSetStsCtrl +#endif + +#ifndef XLlDma_mBdGetStsCtrl +#define XLlDma_mBdGetStsCtrl XLlDma_BdGetStsCtrl +#endif + +#ifndef XLlDma_mBdSetLength +#define XLlDma_mBdSetLength XLlDma_BdSetLength +#endif + +#ifndef XLlDma_mBdGetLength +#define XLlDma_mBdGetLength XLlDma_BdGetLength +#endif + +#ifndef XLlDma_mBdSetId +#define XLlDma_mBdSetId XLlDma_BdSetId +#endif + +#ifndef XLlDma_mBdGetId +#define XLlDma_mBdGetId XLlDma_BdGetId +#endif + +#ifndef XLlDma_mBdSetBufAddr +#define XLlDma_mBdSetBufAddr XLlDma_BdSetBufAddr +#endif + +#ifndef XLlDma_mBdGetBufAddr +#define XLlDma_mBdGetBufAddr XLlDma_BdGetBufAddr +#endif + +#ifndef XLlDma_mBdGetLength +#define XLlDma_mBdGetLength XLlDma_BdGetLength +#endif + +#ifndef XLlDma_mGetTxRing +#define XLlDma_mGetTxRing XLlDma_GetTxRing +#endif + +#ifndef XLlDma_mGetRxRing +#define XLlDma_mGetRxRing XLlDma_GetRxRing +#endif + +#ifndef XLlDma_mGetCr +#define XLlDma_mGetCr XLlDma_GetCr +#endif + +#ifndef XLlDma_mSetCr +#define XLlDma_mSetCr XLlDma_SetCr +#endif + +#ifndef XLlDma_mBdRingCntCalc +#define XLlDma_mBdRingCntCalc XLlDma_BdRingCntCalc +#endif + +#ifndef XLlDma_mBdRingMemCalc +#define XLlDma_mBdRingMemCalc XLlDma_BdRingMemCalc +#endif + +#ifndef XLlDma_mBdRingGetCnt +#define XLlDma_mBdRingGetCnt XLlDma_BdRingGetCnt +#endif + +#ifndef XLlDma_mBdRingGetFreeCnt +#define XLlDma_mBdRingGetFreeCnt XLlDma_BdRingGetFreeCnt +#endif + +#ifndef XLlDma_mBdRingSnapShotCurrBd +#define XLlDma_mBdRingSnapShotCurrBd XLlDma_BdRingSnapShotCurrBd +#endif + +#ifndef XLlDma_mBdRingNext +#define XLlDma_mBdRingNext XLlDma_BdRingNext +#endif + +#ifndef XLlDma_mBdRingPrev +#define XLlDma_mBdRingPrev XLlDma_BdRingPrev +#endif + +#ifndef XLlDma_mBdRingGetSr +#define XLlDma_mBdRingGetSr XLlDma_BdRingGetSr +#endif + +#ifndef XLlDma_mBdRingSetSr +#define XLlDma_mBdRingSetSr XLlDma_BdRingSetSr +#endif + +#ifndef XLlDma_mBdRingGetCr +#define XLlDma_mBdRingGetCr XLlDma_BdRingGetCr +#endif + +#ifndef XLlDma_mBdRingSetCr +#define XLlDma_mBdRingSetCr XLlDma_BdRingSetCr +#endif + +#ifndef XLlDma_mBdRingBusy +#define XLlDma_mBdRingBusy XLlDma_BdRingBusy +#endif + +#ifndef XLlDma_mBdRingIntEnable +#define XLlDma_mBdRingIntEnable XLlDma_BdRingIntEnable +#endif + +#ifndef XLlDma_mBdRingIntDisable +#define XLlDma_mBdRingIntDisable XLlDma_BdRingIntDisable +#endif + +#ifndef XLlDma_mBdRingIntGetEnabled +#define XLlDma_mBdRingIntGetEnabled XLlDma_BdRingIntGetEnabled +#endif + +#ifndef XLlDma_mBdRingGetIrq +#define XLlDma_mBdRingGetIrq XLlDma_BdRingGetIrq +#endif + +#ifndef XLlDma_mBdRingAckIrq +#define XLlDma_mBdRingAckIrq XLlDma_BdRingAckIrq +#endif + +/*********************************************************************/ +/** + * Macros for Driver XMbox + * + *********************************************************************/ +#ifndef XMbox_mWriteReg +#define XMbox_mWriteReg XMbox_WriteReg +#endif + +#ifndef XMbox_mReadReg +#define XMbox_mReadReg XMbox_ReadReg +#endif + +#ifndef XMbox_mWriteMBox +#define XMbox_mWriteMBox XMbox_WriteMBox +#endif + +#ifndef XMbox_mReadMBox +#define XMbox_mReadMBox XMbox_ReadMBox +#endif + +#ifndef XMbox_mFSLReadMBox +#define XMbox_mFSLReadMBox XMbox_FSLReadMBox +#endif + +#ifndef XMbox_mFSLWriteMBox +#define XMbox_mFSLWriteMBox XMbox_FSLWriteMBox +#endif + +#ifndef XMbox_mFSLIsEmpty +#define XMbox_mFSLIsEmpty XMbox_FSLIsEmpty +#endif + +#ifndef XMbox_mFSLIsFull +#define XMbox_mFSLIsFull XMbox_FSLIsFull +#endif + +#ifndef XMbox_mIsEmpty +#define XMbox_mIsEmpty XMbox_IsEmptyHw +#endif + +#ifndef XMbox_mIsFull +#define XMbox_mIsFull XMbox_IsFullHw +#endif + +/*********************************************************************/ +/** + * Macros for Driver XMpmc + * + *********************************************************************/ +#ifndef XMpmc_mReadReg +#define XMpmc_mReadReg XMpmc_ReadReg +#endif + +#ifndef XMpmc_mWriteReg +#define XMpmc_mWriteReg XMpmc_WriteReg +#endif + +/*********************************************************************/ +/** + * Macros for Driver XMutex + * + *********************************************************************/ +#ifndef XMutex_mWriteReg +#define XMutex_mWriteReg XMutex_WriteReg +#endif + +#ifndef XMutex_mReadReg +#define XMutex_mReadReg XMutex_ReadReg +#endif + +/*********************************************************************/ +/** + * Macros for Driver XPcie + * + *********************************************************************/ +#ifndef XPcie_mReadReg +#define XPcie_mReadReg XPcie_ReadReg +#endif + +#ifndef XPcie_mWriteReg +#define XPcie_mWriteReg XPcie_WriteReg +#endif + +/*********************************************************************/ +/** + * Macros for Driver XSpi + * + *********************************************************************/ +#ifndef XSpi_mIntrGlobalEnable +#define XSpi_mIntrGlobalEnable XSpi_IntrGlobalEnable +#endif + +#ifndef XSpi_mIntrGlobalDisable +#define XSpi_mIntrGlobalDisable XSpi_IntrGlobalDisable +#endif + +#ifndef XSpi_mIsIntrGlobalEnabled +#define XSpi_mIsIntrGlobalEnabled XSpi_IsIntrGlobalEnabled +#endif + +#ifndef XSpi_mIntrGetStatus +#define XSpi_mIntrGetStatus XSpi_IntrGetStatus +#endif + +#ifndef XSpi_mIntrClear +#define XSpi_mIntrClear XSpi_IntrClear +#endif + +#ifndef XSpi_mIntrEnable +#define XSpi_mIntrEnable XSpi_IntrEnable +#endif + +#ifndef XSpi_mIntrDisable +#define XSpi_mIntrDisable XSpi_IntrDisable +#endif + +#ifndef XSpi_mIntrGetEnabled +#define XSpi_mIntrGetEnabled XSpi_IntrGetEnabled +#endif + +#ifndef XSpi_mSetControlReg +#define XSpi_mSetControlReg XSpi_SetControlReg +#endif + +#ifndef XSpi_mGetControlReg +#define XSpi_mGetControlReg XSpi_GetControlReg +#endif + +#ifndef XSpi_mGetStatusReg +#define XSpi_mGetStatusReg XSpi_GetStatusReg +#endif + +#ifndef XSpi_mSetSlaveSelectReg +#define XSpi_mSetSlaveSelectReg XSpi_SetSlaveSelectReg +#endif + +#ifndef XSpi_mGetSlaveSelectReg +#define XSpi_mGetSlaveSelectReg XSpi_GetSlaveSelectReg +#endif + +#ifndef XSpi_mEnable +#define XSpi_mEnable XSpi_Enable +#endif + +#ifndef XSpi_mDisable +#define XSpi_mDisable XSpi_Disable +#endif + +/*********************************************************************/ +/** + * Macros for Driver XSysAce + * + *********************************************************************/ +#ifndef XSysAce_mGetControlReg +#define XSysAce_mGetControlReg XSysAce_GetControlReg +#endif + +#ifndef XSysAce_mSetControlReg +#define XSysAce_mSetControlReg XSysAce_SetControlReg +#endif + +#ifndef XSysAce_mOrControlReg +#define XSysAce_mOrControlReg XSysAce_OrControlReg +#endif + +#ifndef XSysAce_mAndControlReg +#define XSysAce_mAndControlReg XSysAce_AndControlReg +#endif + +#ifndef XSysAce_mGetErrorReg +#define XSysAce_mGetErrorReg XSysAce_GetErrorReg +#endif + +#ifndef XSysAce_mGetStatusReg +#define XSysAce_mGetStatusReg XSysAce_GetStatusReg +#endif + +#ifndef XSysAce_mWaitForLock +#define XSysAce_mWaitForLock XSysAce_WaitForLock +#endif + +#ifndef XSysAce_mEnableIntr +#define XSysAce_mEnableIntr XSysAce_EnableIntr +#endif + +#ifndef XSysAce_mDisableIntr +#define XSysAce_mDisableIntr XSysAce_DisableIntr +#endif + +#ifndef XSysAce_mIsReadyForCmd +#define XSysAce_mIsReadyForCmd XSysAce_IsReadyForCmd +#endif + +#ifndef XSysAce_mIsMpuLocked +#define XSysAce_mIsMpuLocked XSysAce_IsMpuLocked +#endif + +#ifndef XSysAce_mIsIntrEnabled +#define XSysAce_mIsIntrEnabled XSysAce_IsIntrEnabled +#endif + +/*********************************************************************/ +/** + * Macros for Driver XSysMon + * + *********************************************************************/ +#ifndef XSysMon_mIsEventSamplingModeSet +#define XSysMon_mIsEventSamplingModeSet XSysMon_IsEventSamplingModeSet +#endif + +#ifndef XSysMon_mIsDrpBusy +#define XSysMon_mIsDrpBusy XSysMon_IsDrpBusy +#endif + +#ifndef XSysMon_mIsDrpLocked +#define XSysMon_mIsDrpLocked XSysMon_IsDrpLocked +#endif + +#ifndef XSysMon_mRawToTemperature +#define XSysMon_mRawToTemperature XSysMon_RawToTemperature +#endif + +#ifndef XSysMon_mRawToVoltage +#define XSysMon_mRawToVoltage XSysMon_RawToVoltage +#endif + +#ifndef XSysMon_mTemperatureToRaw +#define XSysMon_mTemperatureToRaw XSysMon_TemperatureToRaw +#endif + +#ifndef XSysMon_mVoltageToRaw +#define XSysMon_mVoltageToRaw XSysMon_VoltageToRaw +#endif + +#ifndef XSysMon_mReadReg +#define XSysMon_mReadReg XSysMon_ReadReg +#endif + +#ifndef XSysMon_mWriteReg +#define XSysMon_mWriteReg XSysMon_WriteReg +#endif + +/*********************************************************************/ +/** + * Macros for Driver XTmrCtr + * + *********************************************************************/ +#ifndef XTimerCtr_mReadReg +#define XTimerCtr_mReadReg XTimerCtr_ReadReg +#endif + +#ifndef XTmrCtr_mWriteReg +#define XTmrCtr_mWriteReg XTmrCtr_WriteReg +#endif + +#ifndef XTmrCtr_mSetControlStatusReg +#define XTmrCtr_mSetControlStatusReg XTmrCtr_SetControlStatusReg +#endif + +#ifndef XTmrCtr_mGetControlStatusReg +#define XTmrCtr_mGetControlStatusReg XTmrCtr_GetControlStatusReg +#endif + +#ifndef XTmrCtr_mGetTimerCounterReg +#define XTmrCtr_mGetTimerCounterReg XTmrCtr_GetTimerCounterReg +#endif + +#ifndef XTmrCtr_mSetLoadReg +#define XTmrCtr_mSetLoadReg XTmrCtr_SetLoadReg +#endif + +#ifndef XTmrCtr_mGetLoadReg +#define XTmrCtr_mGetLoadReg XTmrCtr_GetLoadReg +#endif + +#ifndef XTmrCtr_mEnable +#define XTmrCtr_mEnable XTmrCtr_Enable +#endif + +#ifndef XTmrCtr_mDisable +#define XTmrCtr_mDisable XTmrCtr_Disable +#endif + +#ifndef XTmrCtr_mEnableIntr +#define XTmrCtr_mEnableIntr XTmrCtr_EnableIntr +#endif + +#ifndef XTmrCtr_mDisableIntr +#define XTmrCtr_mDisableIntr XTmrCtr_DisableIntr +#endif + +#ifndef XTmrCtr_mLoadTimerCounterReg +#define XTmrCtr_mLoadTimerCounterReg XTmrCtr_LoadTimerCounterReg +#endif + +#ifndef XTmrCtr_mHasEventOccurred +#define XTmrCtr_mHasEventOccurred XTmrCtr_HasEventOccurred +#endif + +/*********************************************************************/ +/** + * Macros for Driver XUartLite + * + *********************************************************************/ +#ifndef XUartLite_mUpdateStats +#define XUartLite_mUpdateStats XUartLite_UpdateStats +#endif + +#ifndef XUartLite_mWriteReg +#define XUartLite_mWriteReg XUartLite_WriteReg +#endif + +#ifndef XUartLite_mReadReg +#define XUartLite_mReadReg XUartLite_ReadReg +#endif + +#ifndef XUartLite_mClearStats +#define XUartLite_mClearStats XUartLite_ClearStats +#endif + +#ifndef XUartLite_mSetControlReg +#define XUartLite_mSetControlReg XUartLite_SetControlReg +#endif + +#ifndef XUartLite_mGetStatusReg +#define XUartLite_mGetStatusReg XUartLite_GetStatusReg +#endif + +#ifndef XUartLite_mIsReceiveEmpty +#define XUartLite_mIsReceiveEmpty XUartLite_IsReceiveEmpty +#endif + +#ifndef XUartLite_mIsTransmitFull +#define XUartLite_mIsTransmitFull XUartLite_IsTransmitFull +#endif + +#ifndef XUartLite_mIsIntrEnabled +#define XUartLite_mIsIntrEnabled XUartLite_IsIntrEnabled +#endif + +#ifndef XUartLite_mEnableIntr +#define XUartLite_mEnableIntr XUartLite_EnableIntr +#endif + +#ifndef XUartLite_mDisableIntr +#define XUartLite_mDisableIntr XUartLite_DisableIntr +#endif + +/*********************************************************************/ +/** + * Macros for Driver XUartNs550 + * + *********************************************************************/ +#ifndef XUartNs550_mUpdateStats +#define XUartNs550_mUpdateStats XUartNs550_UpdateStats +#endif + +#ifndef XUartNs550_mReadReg +#define XUartNs550_mReadReg XUartNs550_ReadReg +#endif + +#ifndef XUartNs550_mWriteReg +#define XUartNs550_mWriteReg XUartNs550_WriteReg +#endif + +#ifndef XUartNs550_mClearStats +#define XUartNs550_mClearStats XUartNs550_ClearStats +#endif + +#ifndef XUartNs550_mGetLineStatusReg +#define XUartNs550_mGetLineStatusReg XUartNs550_GetLineStatusReg +#endif + +#ifndef XUartNs550_mGetLineControlReg +#define XUartNs550_mGetLineControlReg XUartNs550_GetLineControlReg +#endif + +#ifndef XUartNs550_mSetLineControlReg +#define XUartNs550_mSetLineControlReg XUartNs550_SetLineControlReg +#endif + +#ifndef XUartNs550_mEnableIntr +#define XUartNs550_mEnableIntr XUartNs550_EnableIntr +#endif + +#ifndef XUartNs550_mDisableIntr +#define XUartNs550_mDisableIntr XUartNs550_DisableIntr +#endif + +#ifndef XUartNs550_mIsReceiveData +#define XUartNs550_mIsReceiveData XUartNs550_IsReceiveData +#endif + +#ifndef XUartNs550_mIsTransmitEmpty +#define XUartNs550_mIsTransmitEmpty XUartNs550_IsTransmitEmpty +#endif + +/*********************************************************************/ +/** + * Macros for Driver XUsb + * + *********************************************************************/ +#ifndef XUsb_mReadReg +#define XUsb_mReadReg XUsb_ReadReg +#endif + +#ifndef XUsb_mWriteReg +#define XUsb_mWriteReg XUsb_WriteReg +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_mem.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_mem.c new file mode 100644 index 0000000..e089bb5 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_mem.c @@ -0,0 +1,85 @@ +/******************************************************************************/ +/** +* Copyright (C) 2015 - 2016 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* @file xil_mem.c +* +* This file contains xil mem copy function to use in case of word aligned +* data copies. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 6.1   nsk      11/07/16 First release.
+*
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ + +#include "xil_types.h" + +/***************** Inline Functions Definitions ********************/ +/*****************************************************************************/ +/** +* @brief This function copies memory from once location to other. +* +* @param dst: pointer pointing to destination memory +* +* @param src: pointer pointing to source memory +* +* @param cnt: 32 bit length of bytes to be copied +* +*****************************************************************************/ +void Xil_MemCpy(void* dst, const void* src, u32 cnt) +{ + char *d = (char*)(void *)dst; + const char *s = src; + + while (cnt >= sizeof (int)) { + *(int*)d = *(int*)s; + d += sizeof (int); + s += sizeof (int); + cnt -= sizeof (int); + } + while (cnt >= sizeof (u16)) { + *(u16*)d = *(u16*)s; + d += sizeof (u16); + s += sizeof (u16); + cnt -= sizeof (u16); + } + while ((cnt) > 0U){ + *d = *s; + d += 1U; + s += 1U; + cnt -= 1U; + } +} diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_mem.h b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_mem.h new file mode 100644 index 0000000..9aae942 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_mem.h @@ -0,0 +1,68 @@ +/******************************************************************************/ +/** +* Copyright (C) 2015 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* @file xil_mem.h +* +* @addtogroup common_mem_operation_api Customized APIs for Memory Operations +* +* The xil_mem.h file contains prototype for functions related +* to memory operations. These APIs are applicable for all processors supported +* by Xilinx. +* +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 6.1   nsk      11/07/16 First release.
+* 7.0   mus      01/07/19 Add cpp extern macro
+*
+* 
+* +*****************************************************************************/ +#ifndef XIL_MEM_H /* prevent circular inclusions */ +#define XIL_MEM_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/************************** Function Prototypes *****************************/ + +void Xil_MemCpy(void* dst, const void* src, u32 cnt); + +#ifdef __cplusplus +} +#endif + +#endif /* XIL_MEM_H */ +/** +* @} End of "addtogroup common_mem_operation_api". +*/ \ No newline at end of file diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_misc_psreset_api.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_misc_psreset_api.c new file mode 100644 index 0000000..77d6fc1 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_misc_psreset_api.c @@ -0,0 +1,520 @@ +/****************************************************************************** +* +* Copyright (C) 2013 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_misc_reset.c +* +* This file contains the implementation of the reset sequence for various +* zynq ps devices like DDR,OCM,Slcr,Ethernet,Usb.. controllers. The reset +* sequence provided to the interfaces is based on the provision in +* slcr reset functional blcok. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date   Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00b kpc   03/07/13 First release
+* 5.4	pkp	  09/11/15 Change the description for XOcm_Remap function
+* 
+* +******************************************************************************/ + + +/***************************** Include Files *********************************/ +#include "xil_misc_psreset_api.h" + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + + +/*****************************************************************************/ +/** +* This function contains the implementation for ddr reset. +* +* @param N/A. +* +* @return N/A. +* +* @note None. +* +******************************************************************************/ +void XDdr_ResetHw(void) +{ + u32 RegVal; + + /* Unlock the slcr register access lock */ + Xil_Out32(XSLCR_UNLOCK_ADDR, XSLCR_UNLOCK_CODE); + /* Assert and deassert the ddr softreset bit */ + RegVal = Xil_In32(XDDRC_CTRL_BASEADDR); + RegVal &= (u32)(~XDDRPS_CTRL_RESET_MASK); + Xil_Out32(XDDRC_CTRL_BASEADDR,RegVal); + RegVal |= ((u32)XDDRPS_CTRL_RESET_MASK); + Xil_Out32(XDDRC_CTRL_BASEADDR,RegVal); + +} + +/*****************************************************************************/ +/** +* This function contains the implementation for remapping the ocm memory region +* to postbootrom state. +* +* @param N/A. +* +* @return N/A. +* +* @note None. +* +******************************************************************************/ +void XOcm_Remap(void) +{ + u32 RegVal; + + /* Unlock the slcr register access lock */ + Xil_Out32(XSLCR_UNLOCK_ADDR, XSLCR_UNLOCK_CODE); + /* Map the ocm region to postbootrom state */ + RegVal = Xil_In32(XSLCR_OCM_CFG_ADDR); + RegVal = (RegVal & (u32)(~XSLCR_OCM_CFG_HIADDR_MASK)) | (u32)XSLCR_OCM_CFG_RESETVAL; + Xil_Out32(XSLCR_OCM_CFG_ADDR, RegVal); +} + +/*****************************************************************************/ +/** +* This function contains the implementation for SMC reset sequence +* +* @param BaseAddress of the interface +* +* @return N/A. +* +* @note None. +* +******************************************************************************/ +void XSmc_ResetHw(u32 BaseAddress) +{ + u32 RegVal; + + /* Clear the interuupts */ + RegVal = Xil_In32(BaseAddress + XSMC_MEMC_CLR_CONFIG_OFFSET); + RegVal = RegVal | (u32)XSMC_MEMC_CLR_CONFIG_MASK; + Xil_Out32(BaseAddress + XSMC_MEMC_CLR_CONFIG_OFFSET, RegVal); + /* Clear the idle counter registers */ + Xil_Out32(BaseAddress + XSMC_REFRESH_PERIOD_0_OFFSET, 0x0U); + Xil_Out32(BaseAddress + XSMC_REFRESH_PERIOD_1_OFFSET, 0x0U); + /* Update the ecc registers with reset values */ + Xil_Out32(BaseAddress + XSMC_ECC_MEMCFG1_OFFSET, + XSMC_ECC_MEMCFG1_RESET_VAL); + Xil_Out32(BaseAddress + XSMC_ECC_MEMCMD1_OFFSET, + XSMC_ECC_MEMCMD1_RESET_VAL); + Xil_Out32(BaseAddress + XSMC_ECC_MEMCMD2_OFFSET, + XSMC_ECC_MEMCMD2_RESET_VAL); + +} + +/*****************************************************************************/ +/** +* This function contains the implementation for updating the slcr mio registers +* with reset values +* @param N/A. +* +* @return N/A. +* +* @note None. +* +******************************************************************************/ +void XSlcr_MioWriteResetValues(void) +{ + u32 i; + + /* Unlock the slcr register access lock */ + Xil_Out32(XSLCR_UNLOCK_ADDR, XSLCR_UNLOCK_CODE); + /* Update all the MIO registers with reset values */ + for (i=0U; i<=1U;i++) + { + Xil_Out32((XSLCR_MIO_PIN_00_ADDR + (i * 4U)), + XSLCR_MIO_PIN_00_RESET_VAL); + } + for (; i<=8U;i++) + { + Xil_Out32((XSLCR_MIO_PIN_00_ADDR + (i * 4U)), + XSLCR_MIO_PIN_02_RESET_VAL); + } + for (; i<=53U ;i++) + { + Xil_Out32((XSLCR_MIO_PIN_00_ADDR + (i * 4U)), + XSLCR_MIO_PIN_00_RESET_VAL); + } + + +} + +/*****************************************************************************/ +/** +* This function contains the implementation for updating the slcr pll registers +* with reset values +* @param N/A. +* +* @return N/A. +* +* @note None. +* +******************************************************************************/ +void XSlcr_PllWriteResetValues(void) +{ + + /* Unlock the slcr register access lock */ + Xil_Out32(XSLCR_UNLOCK_ADDR, XSLCR_UNLOCK_CODE); + + /* update the pll control registers with reset values */ + Xil_Out32(XSLCR_IO_PLL_CTRL_ADDR, XSLCR_IO_PLL_CTRL_RESET_VAL); + Xil_Out32(XSLCR_ARM_PLL_CTRL_ADDR, XSLCR_ARM_PLL_CTRL_RESET_VAL); + Xil_Out32(XSLCR_DDR_PLL_CTRL_ADDR, XSLCR_DDR_PLL_CTRL_RESET_VAL); + /* update the pll config registers with reset values */ + Xil_Out32(XSLCR_IO_PLL_CFG_ADDR, XSLCR_IO_PLL_CFG_RESET_VAL); + Xil_Out32(XSLCR_ARM_PLL_CFG_ADDR, XSLCR_ARM_PLL_CFG_RESET_VAL); + Xil_Out32(XSLCR_DDR_PLL_CFG_ADDR, XSLCR_DDR_PLL_CFG_RESET_VAL); + /* update the clock control registers with reset values */ + Xil_Out32(XSLCR_ARM_CLK_CTRL_ADDR, XSLCR_ARM_CLK_CTRL_RESET_VAL); + Xil_Out32(XSLCR_DDR_CLK_CTRL_ADDR, XSLCR_DDR_CLK_CTRL_RESET_VAL); +} + +/*****************************************************************************/ +/** +* This function contains the implementation for disabling the level shifters +* +* @param N/A. +* +* @return N/A. +* +* @note None. +* +******************************************************************************/ +void XSlcr_DisableLevelShifters(void) +{ + u32 RegVal; + /* Unlock the slcr register access lock */ + Xil_Out32(XSLCR_UNLOCK_ADDR, XSLCR_UNLOCK_CODE); + /* Disable the level shifters */ + RegVal = Xil_In32(XSLCR_LVL_SHFTR_EN_ADDR); + RegVal = RegVal & (u32)(~XSLCR_LVL_SHFTR_EN_MASK); + Xil_Out32(XSLCR_LVL_SHFTR_EN_ADDR, RegVal); + +} +/*****************************************************************************/ +/** +* This function contains the implementation for OCM software reset from the +* slcr +* +* @param N/A. +* +* @return N/A. +* +* @note None. +* +******************************************************************************/ +void XSlcr_OcmReset(void) +{ + u32 RegVal; + /* Unlock the slcr register access lock */ + Xil_Out32(XSLCR_UNLOCK_ADDR, XSLCR_UNLOCK_CODE); + /* Assert the reset */ + RegVal = Xil_In32(XSLCR_OCM_RST_CTRL_ADDR); + RegVal = RegVal | ((u32)XSLCR_OCM_RST_CTRL_VAL); + Xil_Out32(XSLCR_OCM_RST_CTRL_ADDR, RegVal); + /* Release the reset */ + RegVal = Xil_In32(XSLCR_OCM_RST_CTRL_ADDR); + RegVal = RegVal & (u32)(~XSLCR_OCM_RST_CTRL_VAL); + Xil_Out32(XSLCR_OCM_RST_CTRL_ADDR, RegVal); +} + +/*****************************************************************************/ +/** +* This function contains the implementation for Ethernet software reset from +* the slcr +* @param N/A. +* +* @return N/A. +* +* @note None. +* +******************************************************************************/ +void XSlcr_EmacPsReset(void) +{ + u32 RegVal; + /* Unlock the slcr register access lock */ + Xil_Out32(XSLCR_UNLOCK_ADDR, XSLCR_UNLOCK_CODE); + /* Assert the reset */ + RegVal = Xil_In32(XSLCR_GEM_RST_CTRL_ADDR); + RegVal = RegVal | ((u32)XSLCR_GEM_RST_CTRL_VAL); + Xil_Out32(XSLCR_GEM_RST_CTRL_ADDR, RegVal); + /* Release the reset */ + RegVal = Xil_In32(XSLCR_GEM_RST_CTRL_ADDR); + RegVal = RegVal & (u32)(~XSLCR_GEM_RST_CTRL_VAL); + Xil_Out32(XSLCR_GEM_RST_CTRL_ADDR, RegVal); +} + +/*****************************************************************************/ +/** +* This function contains the implementation for USB software reset from the +* slcr +* +* @param N/A. +* +* @return N/A. +* +* @note None. +* +******************************************************************************/ +void XSlcr_UsbPsReset(void) +{ + u32 RegVal; + /* Unlock the slcr register access lock */ + Xil_Out32(XSLCR_UNLOCK_ADDR, XSLCR_UNLOCK_CODE); + /* Assert the reset */ + RegVal = Xil_In32(XSLCR_USB_RST_CTRL_ADDR); + RegVal = RegVal | ((u32)XSLCR_USB_RST_CTRL_VAL); + Xil_Out32(XSLCR_USB_RST_CTRL_ADDR, RegVal); + /* Release the reset */ + RegVal = Xil_In32(XSLCR_USB_RST_CTRL_ADDR); + RegVal = RegVal & (u32)(~XSLCR_USB_RST_CTRL_VAL); + Xil_Out32(XSLCR_USB_RST_CTRL_ADDR, RegVal); +} +/*****************************************************************************/ +/** +* This function contains the implementation for QSPI software reset from the +* slcr +* +* @param N/A. +* +* @return N/A. +* +* @note None. +* +******************************************************************************/ +void XSlcr_QspiPsReset(void) +{ + u32 RegVal; + /* Unlock the slcr register access lock */ + Xil_Out32(XSLCR_UNLOCK_ADDR, XSLCR_UNLOCK_CODE); + /* Assert the reset */ + RegVal = Xil_In32(XSLCR_LQSPI_RST_CTRL_ADDR); + RegVal = RegVal | ((u32)XSLCR_QSPI_RST_CTRL_VAL); + Xil_Out32(XSLCR_LQSPI_RST_CTRL_ADDR, RegVal); + /* Release the reset */ + RegVal = Xil_In32(XSLCR_LQSPI_RST_CTRL_ADDR); + RegVal = RegVal & (u32)(~XSLCR_QSPI_RST_CTRL_VAL); + Xil_Out32(XSLCR_LQSPI_RST_CTRL_ADDR, RegVal); +} +/*****************************************************************************/ +/** +* This function contains the implementation for SPI software reset from the +* slcr +* +* @param N/A. +* +* @return N/A. +* +* @note None. +* +******************************************************************************/ +void XSlcr_SpiPsReset(void) +{ + u32 RegVal; + /* Unlock the slcr register access lock */ + Xil_Out32(XSLCR_UNLOCK_ADDR, XSLCR_UNLOCK_CODE); + /* Assert the reset */ + RegVal = Xil_In32(XSLCR_SPI_RST_CTRL_ADDR); + RegVal = RegVal | ((u32)XSLCR_SPI_RST_CTRL_VAL); + Xil_Out32(XSLCR_SPI_RST_CTRL_ADDR, RegVal); + /* Release the reset */ + RegVal = Xil_In32(XSLCR_SPI_RST_CTRL_ADDR); + RegVal = RegVal & (u32)(~XSLCR_SPI_RST_CTRL_VAL); + Xil_Out32(XSLCR_SPI_RST_CTRL_ADDR, RegVal); +} +/*****************************************************************************/ +/** +* This function contains the implementation for i2c software reset from the slcr +* +* @param N/A. +* +* @return N/A. +* +* @note None. +* +******************************************************************************/ +void XSlcr_I2cPsReset(void) +{ + u32 RegVal; + /* Unlock the slcr register access lock */ + Xil_Out32(XSLCR_UNLOCK_ADDR, XSLCR_UNLOCK_CODE); + /* Assert the reset */ + RegVal = Xil_In32(XSLCR_I2C_RST_CTRL_ADDR); + RegVal = RegVal | ((u32)XSLCR_I2C_RST_CTRL_VAL); + Xil_Out32(XSLCR_I2C_RST_CTRL_ADDR, RegVal); + /* Release the reset */ + RegVal = Xil_In32(XSLCR_I2C_RST_CTRL_ADDR); + RegVal = RegVal & (u32)(~XSLCR_I2C_RST_CTRL_VAL); + Xil_Out32(XSLCR_I2C_RST_CTRL_ADDR, RegVal); +} +/*****************************************************************************/ +/** +* This function contains the implementation for UART software reset from the +* slcr +* +* @param N/A. +* +* @return N/A. +* +* @note None. +* +******************************************************************************/ +void XSlcr_UartPsReset(void) +{ + u32 RegVal; + /* Unlock the slcr register access lock */ + Xil_Out32(XSLCR_UNLOCK_ADDR, XSLCR_UNLOCK_CODE); + /* Assert the reset */ + RegVal = Xil_In32(XSLCR_UART_RST_CTRL_ADDR); + RegVal = RegVal | ((u32)XSLCR_UART_RST_CTRL_VAL); + Xil_Out32(XSLCR_UART_RST_CTRL_ADDR, RegVal); + /* Release the reset */ + RegVal = Xil_In32(XSLCR_UART_RST_CTRL_ADDR); + RegVal = RegVal & (u32)(~XSLCR_UART_RST_CTRL_VAL); + Xil_Out32(XSLCR_UART_RST_CTRL_ADDR, RegVal); +} +/*****************************************************************************/ +/** +* This function contains the implementation for CAN software reset from slcr +* registers +* +* @param N/A. +* +* @return N/A. +* +* @note None. +* +******************************************************************************/ +void XSlcr_CanPsReset(void) +{ + u32 RegVal; + /* Unlock the slcr register access lock */ + Xil_Out32(XSLCR_UNLOCK_ADDR, XSLCR_UNLOCK_CODE); + /* Assert the reset */ + RegVal = Xil_In32(XSLCR_CAN_RST_CTRL_ADDR); + RegVal = RegVal | ((u32)XSLCR_CAN_RST_CTRL_VAL); + Xil_Out32(XSLCR_CAN_RST_CTRL_ADDR, RegVal); + /* Release the reset */ + RegVal = Xil_In32(XSLCR_CAN_RST_CTRL_ADDR); + RegVal = RegVal & (u32)(~XSLCR_CAN_RST_CTRL_VAL); + Xil_Out32(XSLCR_CAN_RST_CTRL_ADDR, RegVal); +} +/*****************************************************************************/ +/** +* This function contains the implementation for SMC software reset from the slcr +* +* @param N/A. +* +* @return N/A. +* +* @note None. +* +******************************************************************************/ +void XSlcr_SmcPsReset(void) +{ + u32 RegVal; + /* Unlock the slcr register access lock */ + Xil_Out32(XSLCR_UNLOCK_ADDR, XSLCR_UNLOCK_CODE); + /* Assert the reset */ + RegVal = Xil_In32(XSLCR_SMC_RST_CTRL_ADDR); + RegVal = RegVal | ((u32)XSLCR_SMC_RST_CTRL_VAL); + Xil_Out32(XSLCR_SMC_RST_CTRL_ADDR, RegVal); + /* Release the reset */ + RegVal = Xil_In32(XSLCR_SMC_RST_CTRL_ADDR); + RegVal = RegVal & (u32)(~XSLCR_SMC_RST_CTRL_VAL); + Xil_Out32(XSLCR_SMC_RST_CTRL_ADDR, RegVal); +} +/*****************************************************************************/ +/** +* This function contains the implementation for DMA controller software reset +* from the slcr +* +* @param N/A. +* +* @return N/A. +* +* @note None. +* +******************************************************************************/ +void XSlcr_DmaPsReset(void) +{ + u32 RegVal; + /* Unlock the slcr register access lock */ + Xil_Out32(XSLCR_UNLOCK_ADDR, XSLCR_UNLOCK_CODE); + /* Assert the reset */ + RegVal = Xil_In32(XSLCR_DMAC_RST_CTRL_ADDR); + RegVal = RegVal | ((u32)XSLCR_DMAC_RST_CTRL_VAL); + Xil_Out32(XSLCR_DMAC_RST_CTRL_ADDR, RegVal); + /* Release the reset */ + RegVal = Xil_In32(XSLCR_DMAC_RST_CTRL_ADDR); + RegVal = RegVal & (u32)(~XSLCR_DMAC_RST_CTRL_VAL); + Xil_Out32(XSLCR_DMAC_RST_CTRL_ADDR, RegVal); +} +/*****************************************************************************/ +/** +* This function contains the implementation for Gpio AMBA software reset from +* the slcr +* +* @param N/A. +* +* @return N/A. +* +* @note None. +* +******************************************************************************/ +void XSlcr_GpioPsReset(void) +{ + u32 RegVal; + /* Unlock the slcr register access lock */ + Xil_Out32(XSLCR_UNLOCK_ADDR, XSLCR_UNLOCK_CODE); + /* Assert the reset */ + RegVal = Xil_In32(XSLCR_GPIO_RST_CTRL_ADDR); + RegVal = RegVal | ((u32)XSLCR_GPIO_RST_CTRL_VAL); + Xil_Out32(XSLCR_GPIO_RST_CTRL_ADDR, RegVal); + /* Release the reset */ + RegVal = Xil_In32(XSLCR_GPIO_RST_CTRL_ADDR); + RegVal = RegVal & (u32)(~XSLCR_GPIO_RST_CTRL_VAL); + Xil_Out32(XSLCR_GPIO_RST_CTRL_ADDR, RegVal); +} diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_misc_psreset_api.h b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_misc_psreset_api.h new file mode 100644 index 0000000..3a26175 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_misc_psreset_api.h @@ -0,0 +1,273 @@ +/****************************************************************************** +* +* Copyright (C) 2013 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file xil_misc_psreset_api.h +* +* This file contains the various register defintions and function prototypes for +* implementing the reset functionality of zynq ps devices +* +* MODIFICATION HISTORY: +* +* Ver Who Date Changes +* ----- ---- -------- ------------------------------------------------------- +* 1.00b kpc 03/07/13 First release. +* +* +******************************************************************************/ + +#ifndef XIL_MISC_RESET_H /* prevent circular inclusions */ +#define XIL_MISC_RESET_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + + +/***************************** Include Files *********************************/ +#include "xil_types.h" +#include "xil_io.h" + +/************************** Constant Definitions *****************************/ +#define XDDRC_CTRL_BASEADDR 0xF8006000U +#define XSLCR_BASEADDR 0xF8000000U +/**< OCM configuration register */ +#define XSLCR_OCM_CFG_ADDR (XSLCR_BASEADDR + 0x00000910U) +/**< SLCR unlock register */ +#define XSLCR_UNLOCK_ADDR (XSLCR_BASEADDR + 0x00000008U) +/**< SLCR GEM0 rx clock control register */ +#define XSLCR_GEM0_RCLK_CTRL_ADDR (XSLCR_BASEADDR + 0x00000138U) +/**< SLCR GEM1 rx clock control register */ +#define XSLCR_GEM1_RCLK_CTRL_ADDR (XSLCR_BASEADDR + 0x0000013CU) +/**< SLCR GEM0 clock control register */ +#define XSLCR_GEM0_CLK_CTRL_ADDR (XSLCR_BASEADDR + 0x00000140U) +/**< SLCR GEM1 clock control register */ +#define XSLCR_GEM1_CLK_CTRL_ADDR (XSLCR_BASEADDR + 0x00000144U) +/**< SLCR SMC clock control register */ +#define XSLCR_SMC_CLK_CTRL_ADDR (XSLCR_BASEADDR + 0x00000148U) +/**< SLCR GEM reset control register */ +#define XSLCR_GEM_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000214U) +/**< SLCR USB0 clock control register */ +#define XSLCR_USB0_CLK_CTRL_ADDR (XSLCR_BASEADDR + 0x00000130U) +/**< SLCR USB1 clock control register */ +#define XSLCR_USB1_CLK_CTRL_ADDR (XSLCR_BASEADDR + 0x00000134U) +/**< SLCR USB1 reset control register */ +#define XSLCR_USB_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000210U) +/**< SLCR SMC reset control register */ +#define XSLCR_SMC_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000234U) +/**< SLCR Level shifter enable register */ +#define XSLCR_LVL_SHFTR_EN_ADDR (XSLCR_BASEADDR + 0x00000900U) +/**< SLCR ARM pll control register */ +#define XSLCR_ARM_PLL_CTRL_ADDR (XSLCR_BASEADDR + 0x00000100U) +/**< SLCR DDR pll control register */ +#define XSLCR_DDR_PLL_CTRL_ADDR (XSLCR_BASEADDR + 0x00000104U) +/**< SLCR IO pll control register */ +#define XSLCR_IO_PLL_CTRL_ADDR (XSLCR_BASEADDR + 0x00000108U) +/**< SLCR ARM pll configuration register */ +#define XSLCR_ARM_PLL_CFG_ADDR (XSLCR_BASEADDR + 0x00000110U) +/**< SLCR DDR pll configuration register */ +#define XSLCR_DDR_PLL_CFG_ADDR (XSLCR_BASEADDR + 0x00000114U) +/**< SLCR IO pll configuration register */ +#define XSLCR_IO_PLL_CFG_ADDR (XSLCR_BASEADDR + 0x00000118U) +/**< SLCR ARM clock control register */ +#define XSLCR_ARM_CLK_CTRL_ADDR (XSLCR_BASEADDR + 0x00000120U) +/**< SLCR DDR clock control register */ +#define XSLCR_DDR_CLK_CTRL_ADDR (XSLCR_BASEADDR + 0x00000124U) +/**< SLCR MIO pin address register */ +#define XSLCR_MIO_PIN_00_ADDR (XSLCR_BASEADDR + 0x00000700U) +/**< SLCR DMAC reset control address register */ +#define XSLCR_DMAC_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x0000020CU) +/**< SLCR USB reset control address register */ +/*#define XSLCR_USB_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000210U)*/ +/**< SLCR GEM reset control address register */ +/*#define XSLCR_GEM_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000214U)*/ +/**< SLCR SDIO reset control address register */ +#define XSLCR_SDIO_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000218U) +/**< SLCR SPI reset control address register */ +#define XSLCR_SPI_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x0000021CU) +/**< SLCR CAN reset control address register */ +#define XSLCR_CAN_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000220U) +/**< SLCR I2C reset control address register */ +#define XSLCR_I2C_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000224U) +/**< SLCR UART reset control address register */ +#define XSLCR_UART_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000228U) +/**< SLCR GPIO reset control address register */ +#define XSLCR_GPIO_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x0000022CU) +/**< SLCR LQSPI reset control address register */ +#define XSLCR_LQSPI_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000230U) +/**< SLCR SMC reset control address register */ +/*#define XSLCR_SMC_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000234U)*/ +/**< SLCR OCM reset control address register */ +#define XSLCR_OCM_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000238U) + +/**< SMC mem controller clear config register */ +#define XSMC_MEMC_CLR_CONFIG_OFFSET 0x0000000CU +/**< SMC idlecount configuration register */ +#define XSMC_REFRESH_PERIOD_0_OFFSET 0x00000020U +#define XSMC_REFRESH_PERIOD_1_OFFSET 0x00000024U +/**< SMC ECC configuration register */ +#define XSMC_ECC_MEMCFG1_OFFSET 0x00000404U +/**< SMC ECC command 1 register */ +#define XSMC_ECC_MEMCMD1_OFFSET 0x00000404U +/**< SMC ECC command 2 register */ +#define XSMC_ECC_MEMCMD2_OFFSET 0x00000404U + +/**< SLCR unlock code */ +#define XSLCR_UNLOCK_CODE 0x0000DF0DU + +/**< SMC mem clear configuration mask */ +#define XSMC_MEMC_CLR_CONFIG_MASK 0x000005FU +/**< SMC ECC memconfig 1 reset value */ +#define XSMC_ECC_MEMCFG1_RESET_VAL 0x0000043U +/**< SMC ECC memcommand 1 reset value */ +#define XSMC_ECC_MEMCMD1_RESET_VAL 0x01300080U +/**< SMC ECC memcommand 2 reset value */ +#define XSMC_ECC_MEMCMD2_RESET_VAL 0x01E00585U + +/**< DDR controller reset bit mask */ +#define XDDRPS_CTRL_RESET_MASK 0x00000001U +/**< SLCR OCM configuration reset value*/ +#define XSLCR_OCM_CFG_RESETVAL 0x00000008U +/**< SLCR OCM bank selection mask*/ +#define XSLCR_OCM_CFG_HIADDR_MASK 0x0000000FU +/**< SLCR level shifter enable mask*/ +#define XSLCR_LVL_SHFTR_EN_MASK 0x0000000FU + +/**< SLCR PLL register reset values */ +#define XSLCR_ARM_PLL_CTRL_RESET_VAL 0x0001A008U +#define XSLCR_DDR_PLL_CTRL_RESET_VAL 0x0001A008U +#define XSLCR_IO_PLL_CTRL_RESET_VAL 0x0001A008U +#define XSLCR_ARM_PLL_CFG_RESET_VAL 0x00177EA0U +#define XSLCR_DDR_PLL_CFG_RESET_VAL 0x00177EA0U +#define XSLCR_IO_PLL_CFG_RESET_VAL 0x00177EA0U +#define XSLCR_ARM_CLK_CTRL_RESET_VAL 0x1F000400U +#define XSLCR_DDR_CLK_CTRL_RESET_VAL 0x18400003U + +/**< SLCR MIO register default values */ +#define XSLCR_MIO_PIN_00_RESET_VAL 0x00001601U +#define XSLCR_MIO_PIN_02_RESET_VAL 0x00000601U + +/**< SLCR Reset control registers default values */ +#define XSLCR_DMAC_RST_CTRL_VAL 0x00000001U +#define XSLCR_GEM_RST_CTRL_VAL 0x000000F3U +#define XSLCR_USB_RST_CTRL_VAL 0x00000003U +#define XSLCR_I2C_RST_CTRL_VAL 0x00000003U +#define XSLCR_SPI_RST_CTRL_VAL 0x0000000FU +#define XSLCR_UART_RST_CTRL_VAL 0x0000000FU +#define XSLCR_QSPI_RST_CTRL_VAL 0x00000003U +#define XSLCR_GPIO_RST_CTRL_VAL 0x00000001U +#define XSLCR_SMC_RST_CTRL_VAL 0x00000003U +#define XSLCR_OCM_RST_CTRL_VAL 0x00000001U +#define XSLCR_SDIO_RST_CTRL_VAL 0x00000033U +#define XSLCR_CAN_RST_CTRL_VAL 0x00000003U +/**************************** Type Definitions *******************************/ + +/* the following data type is used to hold a null terminated version string + * consisting of the following format, "X.YYX" + */ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ +/* + * Performs reset operation to the ddr interface + */ +void XDdr_ResetHw(void); +/* + * Map the ocm region to post bootrom state + */ +void XOcm_Remap(void); +/* + * Performs the smc interface reset + */ +void XSmc_ResetHw(u32 BaseAddress); +/* + * updates the MIO registers with reset values + */ +void XSlcr_MioWriteResetValues(void); +/* + * updates the PLL and clock registers with reset values + */ +void XSlcr_PllWriteResetValues(void); +/* + * Disables the level shifters + */ +void XSlcr_DisableLevelShifters(void); +/* + * provides softreset to the GPIO interface + */ +void XSlcr_GpioPsReset(void); +/* + * provides softreset to the DMA interface + */ +void XSlcr_DmaPsReset(void); +/* + * provides softreset to the SMC interface + */ +void XSlcr_SmcPsReset(void); +/* + * provides softreset to the CAN interface + */ +void XSlcr_CanPsReset(void); +/* + * provides softreset to the Uart interface + */ +void XSlcr_UartPsReset(void); +/* + * provides softreset to the I2C interface + */ +void XSlcr_I2cPsReset(void); +/* + * provides softreset to the SPI interface + */ +void XSlcr_SpiPsReset(void); +/* + * provides softreset to the QSPI interface + */ +void XSlcr_QspiPsReset(void); +/* + * provides softreset to the USB interface + */ +void XSlcr_UsbPsReset(void); +/* + * provides softreset to the GEM interface + */ +void XSlcr_EmacPsReset(void); +/* + * provides softreset to the OCM interface + */ +void XSlcr_OcmReset(void); + + +#ifdef __cplusplus +} +#endif + +#endif /* XIL_MISC_RESET_H */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_mmu.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_mmu.c new file mode 100644 index 0000000..ef5bbfe --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_mmu.c @@ -0,0 +1,227 @@ +/****************************************************************************** +* +* Copyright (C) 2012 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file xil_mmu.c +* +* This file provides APIs for enabling/disabling MMU and setting the memory +* attributes for sections, in the MMU translation table. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- ---------------------------------------------------
+* 1.00a sdm  01/12/12 Initial version
+* 3.05a asa  03/10/12 Modified the Xil_EnableMMU to invalidate the caches
+*		      before enabling back.
+* 3.05a asa  04/15/12 Modified the Xil_SetTlbAttributes routine so that
+*		      translation table and branch predictor arrays are
+*		      invalidated, D-cache flushed before the attribute
+*		      change is applied. This is done so that the user
+*		      need not call Xil_DisableMMU before calling
+*		      Xil_SetTlbAttributes.
+* 3.10a  srt 04/18/13 Implemented ARM Erratas. Please refer to file
+*		      'xil_errata.h' for errata description
+* 3.11a  asa 09/23/13 Modified Xil_SetTlbAttributes to flush the complete
+*			 D cache after the translation table update. Removed the
+*			 redundant TLB invalidation in the same API at the beginning.
+* 6.8   aru  09/06/18 Removed compilation warnings for ARMCC toolchain.
+*                     It fixes CR#1008309.
+* 
+* +* @note +* +* None. +* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xil_cache.h" +#include "xpseudo_asm.h" +#include "xil_types.h" +#include "xil_mmu.h" +#include "xil_errata.h" + +/***************** Macros (Inline Functions) Definitions *********************/ + +/**************************** Type Definitions *******************************/ + +/************************** Constant Definitions *****************************/ +#define ARM_AR_MEM_TTB_SECT_SIZE 1024*1024 +#define ARM_AR_MEM_TTB_SECT_SIZE_MASK (~(ARM_AR_MEM_TTB_SECT_SIZE-1UL)) +/************************** Variable Definitions *****************************/ + +extern u32 MMUTable; + +/************************** Function Prototypes ******************************/ + +/*****************************************************************************/ +/** +* @brief This function sets the memory attributes for a section covering 1MB +* of memory in the translation table. +* +* @param Addr: 32-bit address for which memory attributes need to be set. +* @param attrib: Attribute for the given memory region. xil_mmu.h contains +* definitions of commonly used memory attributes which can be +* utilized for this function. +* +* +* @return None. +* +* @note The MMU or D-cache does not need to be disabled before changing a +* translation table entry. +* +******************************************************************************/ +void Xil_SetTlbAttributes(INTPTR Addr, u32 attrib) +{ + u32 *ptr; + u32 section; + + section = Addr / 0x100000U; + ptr = &MMUTable; + ptr += section; + if(ptr != NULL) { + *ptr = (Addr & 0xFFF00000U) | attrib; + } + + Xil_DCacheFlush(); + + mtcp(XREG_CP15_INVAL_UTLB_UNLOCKED, 0U); + /* Invalidate all branch predictors */ + mtcp(XREG_CP15_INVAL_BRANCH_ARRAY, 0U); + + dsb(); /* ensure completion of the BP and TLB invalidation */ + isb(); /* synchronize context on this processor */ +} + +/*****************************************************************************/ +/** +* @brief Enable MMU for cortex A9 processor. This function invalidates the +* instruction and data caches, and then enables MMU. +* +* @param None. +* @return None. +* +******************************************************************************/ +void Xil_EnableMMU(void) +{ + u32 Reg; + Xil_DCacheInvalidate(); + Xil_ICacheInvalidate(); + +#ifdef __GNUC__ + Reg = mfcp(XREG_CP15_SYS_CONTROL); +#elif defined (__ICCARM__) + mfcp(XREG_CP15_SYS_CONTROL, Reg); +#else + { volatile register u32 Cp15Reg __asm(XREG_CP15_SYS_CONTROL); + Reg = Cp15Reg; } +#endif + Reg |= (u32)0x05U; + mtcp(XREG_CP15_SYS_CONTROL, Reg); + + dsb(); + isb(); +} + +/*****************************************************************************/ +/** +* @brief Disable MMU for Cortex A9 processors. This function invalidates +* the TLBs, Branch Predictor Array and flushed the D Caches before +* disabling the MMU. +* +* @param None. +* +* @return None. +* +* @note When the MMU is disabled, all the memory accesses are treated as +* strongly ordered. +******************************************************************************/ +void Xil_DisableMMU(void) +{ + u32 Reg; + + mtcp(XREG_CP15_INVAL_UTLB_UNLOCKED, 0U); + mtcp(XREG_CP15_INVAL_BRANCH_ARRAY, 0U); + Xil_DCacheFlush(); + +#ifdef __GNUC__ + Reg = mfcp(XREG_CP15_SYS_CONTROL); +#elif defined (__ICCARM__) + mfcp(XREG_CP15_SYS_CONTROL, Reg); +#else + { volatile register u32 Cp15Reg __asm(XREG_CP15_SYS_CONTROL); + Reg = Cp15Reg; } +#endif + Reg &= (u32)(~0x05U); +#ifdef CONFIG_ARM_ERRATA_794073 + /* Disable Branch Prediction */ + Reg &= (u32)(~0x800U); +#endif + mtcp(XREG_CP15_SYS_CONTROL, Reg); +} + +/*****************************************************************************/ +/** +* @brief Memory mapping for Cortex A9 processor. +* +* @param PhysAddr is physical address. +* @param size is size of region. +* @param flags is flags used to set translation table. +* +* @return Pointer to virtual address. +* +* @note: Previously this was implemented in libmetal. Move to embeddedsw as this +* functionality is specific to A9 processor. +* +******************************************************************************/ +void* Xil_MemMap(UINTPTR PhysAddr, size_t size, u32 flags) +{ + u32 Sectionoffset; + u32 Ttbaddr; + + if (!flags) + return (void*)PhysAddr; + + /* Ensure alignement on a section boundary */ + PhysAddr &= ARM_AR_MEM_TTB_SECT_SIZE_MASK; + + /* Loop through entire region of memory (one MMU section at a time). + Each section requires a TTB entry. */ + for (Sectionoffset = 0; Sectionoffset < size; + Sectionoffset += ARM_AR_MEM_TTB_SECT_SIZE) { + /* Calculate translation table entry for this memory section */ + Ttbaddr = (PhysAddr + Sectionoffset); + + /* Write translation table entry value to entry address */ + Xil_SetTlbAttributes(Ttbaddr, flags); + } + return (void*)PhysAddr; +} diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_mmu.h b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_mmu.h new file mode 100644 index 0000000..3b63c0b --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_mmu.h @@ -0,0 +1,106 @@ +/****************************************************************************** +* +* Copyright (C) 2012 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file xil_mmu.h +* +* @addtogroup a9_mmu_apis Cortex A9 Processor MMU Functions +* +* MMU functions equip users to enable MMU, disable MMU and modify default +* memory attributes of MMU table as per the need. +* +* @{ +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- ---------------------------------------------------
+* 1.00a sdm  01/12/12 Initial version
+* 4.2	pkp	 07/21/14 Included xil_types.h file which contains definition for
+*					  u32 which resolves issue of CR#805869
+* 5.4	pkp	 23/11/15 Added attribute definitions for Xil_SetTlbAttributes API
+* 6.8   aru  09/06/18 Removed compilation warnings for ARMCC toolchain.
+* 
+* +* +******************************************************************************/ + +#ifndef XIL_MMU_H +#define XIL_MMU_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/***************************** Include Files *********************************/ + +#include "xil_types.h" + +/***************** Macros (Inline Functions) Definitions *********************/ + +/**************************** Type Definitions *******************************/ + +/************************** Constant Definitions *****************************/ + +/* Memory type */ +#define NORM_NONCACHE 0x11DE2 /* Normal Non-cacheable */ +#define STRONG_ORDERED 0xC02 /* Strongly ordered */ +#define DEVICE_MEMORY 0xC06 /* Device memory */ +#define RESERVED 0x0 /* reserved memory */ + +/* Normal write-through cacheable shareable */ +#define NORM_WT_CACHE 0x16DEA + +/* Normal write back cacheable shareable */ +#define NORM_WB_CACHE 0x15DE6 + +/* shareability attribute */ +#define SHAREABLE (0x1 << 16) +#define NON_SHAREABLE (~(0x1 << 16)) + +/* Execution type */ +#define EXECUTE_NEVER ((0x1 << 4) | (0x1 << 0)) + +/************************** Variable Definitions *****************************/ + +/************************** Function Prototypes ******************************/ + +void Xil_SetTlbAttributes(INTPTR Addr, u32 attrib); +void Xil_EnableMMU(void); +void Xil_DisableMMU(void); +void* Xil_MemMap(UINTPTR PhysAddr, size_t size, u32 flags); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* XIL_MMU_H */ +/** +* @} End of "addtogroup a9_mmu_apis". +*/ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_printf.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_printf.c new file mode 100644 index 0000000..3113269 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_printf.c @@ -0,0 +1,443 @@ +/*---------------------------------------------------*/ +/* Modified from : */ +/* Public Domain version of printf */ +/* Rud Merriam, Compsult, Inc. Houston, Tx. */ +/* For Embedded Systems Programming, 1991 */ +/* */ +/*---------------------------------------------------*/ +#include "xil_printf.h" +#include "xil_types.h" +#include "xil_assert.h" +#include +#include +#include + +static void padding( const s32 l_flag,const struct params_s *par); +static void outs(const charptr lp, struct params_s *par); +static s32 getnum( charptr* linep); + +typedef struct params_s { + s32 len; + s32 num1; + s32 num2; + char8 pad_character; + s32 do_padding; + s32 left_flag; + s32 unsigned_flag; +} params_t; + + +/*---------------------------------------------------*/ +/* The purpose of this routine is to output data the */ +/* same as the standard printf function without the */ +/* overhead most run-time libraries involve. Usually */ +/* the printf brings in many kilobytes of code and */ +/* that is unacceptable in most embedded systems. */ +/*---------------------------------------------------*/ + + +/*---------------------------------------------------*/ +/* */ +/* This routine puts pad characters into the output */ +/* buffer. */ +/* */ +static void padding( const s32 l_flag, const struct params_s *par) +{ + s32 i; + + if ((par->do_padding != 0) && (l_flag != 0) && (par->len < par->num1)) { + i=(par->len); + for (; i<(par->num1); i++) { +#ifdef STDOUT_BASEADDRESS + outbyte( par->pad_character); +#endif + } + } +} + +/*---------------------------------------------------*/ +/* */ +/* This routine moves a string to the output buffer */ +/* as directed by the padding and positioning flags. */ +/* */ +static void outs(const charptr lp, struct params_s *par) +{ + charptr LocalPtr; + LocalPtr = lp; + /* pad on left if needed */ + if(LocalPtr != NULL) { + par->len = (s32)strlen( LocalPtr); + } + padding( !(par->left_flag), par); + + /* Move string to the buffer */ + while (((*LocalPtr) != (char8)0) && ((par->num2) != 0)) { + (par->num2)--; +#ifdef STDOUT_BASEADDRESS + outbyte(*LocalPtr); +#endif + LocalPtr += 1; +} + + /* Pad on right if needed */ + /* CR 439175 - elided next stmt. Seemed bogus. */ + /* par->len = strlen( lp) */ + padding( par->left_flag, par); +} + +/*---------------------------------------------------*/ +/* */ +/* This routine moves a number to the output buffer */ +/* as directed by the padding and positioning flags. */ +/* */ + +static void outnum( const s32 n, const s32 base, struct params_s *par) +{ + s32 negative; + s32 i; + char8 outbuf[32]; + const char8 digits[] = "0123456789ABCDEF"; + u32 num; + for(i = 0; i<32; i++) { + outbuf[i] = '0'; + } + + /* Check if number is negative */ + if ((par->unsigned_flag == 0) && (base == 10) && (n < 0L)) { + negative = 1; + num =(-(n)); + } + else{ + num = n; + negative = 0; + } + + /* Build number (backwards) in outbuf */ + i = 0; + do { + outbuf[i] = digits[(num % base)]; + i++; + num /= base; + } while (num > 0); + + if (negative != 0) { + outbuf[i] = '-'; + i++; + } + + outbuf[i] = '\0'; + i--; + + /* Move the converted number to the buffer and */ + /* add in the padding where needed. */ + par->len = (s32)strlen(outbuf); + padding( !(par->left_flag), par); + while (&outbuf[i] >= outbuf) { +#ifdef STDOUT_BASEADDRESS + outbyte( outbuf[i] ); +#endif + i--; +} + padding( par->left_flag, par); +} +/*---------------------------------------------------*/ +/* */ +/* This routine moves a 64-bit number to the output */ +/* buffer as directed by the padding and positioning */ +/* flags. */ +/* */ +#if defined (__aarch64__) || defined (__arch64__) +static void outnum1( const s64 n, const s32 base, params_t *par) +{ + s32 negative; + s32 i; + char8 outbuf[64]; + const char8 digits[] = "0123456789ABCDEF"; + u64 num; + for(i = 0; i<64; i++) { + outbuf[i] = '0'; + } + + /* Check if number is negative */ + if ((par->unsigned_flag == 0) && (base == 10) && (n < 0L)) { + negative = 1; + num =(-(n)); + } + else{ + num = (n); + negative = 0; + } + + /* Build number (backwards) in outbuf */ + i = 0; + do { + outbuf[i] = digits[(num % base)]; + i++; + num /= base; + } while (num > 0); + + if (negative != 0) { + outbuf[i] = '-'; + i++; + } + + outbuf[i] = '\0'; + i--; + + /* Move the converted number to the buffer and */ + /* add in the padding where needed. */ + par->len = (s32)strlen(outbuf); + padding( !(par->left_flag), par); + while (&outbuf[i] >= outbuf) { + outbyte( outbuf[i] ); + i--; +} + padding( par->left_flag, par); +} +#endif +/*---------------------------------------------------*/ +/* */ +/* This routine gets a number from the format */ +/* string. */ +/* */ +static s32 getnum( charptr* linep) +{ + s32 n; + s32 ResultIsDigit = 0; + charptr cptr; + n = 0; + cptr = *linep; + if(cptr != NULL){ + ResultIsDigit = isdigit(((s32)*cptr)); + } + while (ResultIsDigit != 0) { + if(cptr != NULL){ + n = ((n*10) + (((s32)*cptr) - (s32)'0')); + cptr += 1; + if(cptr != NULL){ + ResultIsDigit = isdigit(((s32)*cptr)); + } + } + ResultIsDigit = isdigit(((s32)*cptr)); + } + *linep = ((charptr )(cptr)); + return(n); +} + +/*---------------------------------------------------*/ +/* */ +/* This routine operates just like a printf/sprintf */ +/* routine. It outputs a set of data under the */ +/* control of a formatting string. Not all of the */ +/* standard C format control are supported. The ones */ +/* provided are primarily those needed for embedded */ +/* systems work. Primarily the floating point */ +/* routines are omitted. Other formats could be */ +/* added easily by following the examples shown for */ +/* the supported formats. */ +/* */ + +/* void esp_printf( const func_ptr f_ptr, + const charptr ctrl1, ...) */ +#if defined (__aarch64__) && HYP_GUEST && EL1_NONSECURE && XEN_USE_PV_CONSOLE +void xil_printf( const char8 *ctrl1, ...){ + XPVXenConsole_Printf(ctrl1); +} +#else +void xil_printf( const char8 *ctrl1, ...) +{ + s32 Check; +#if defined (__aarch64__) || defined (__arch64__) + s32 long_flag; +#endif + s32 dot_flag; + + params_t par; + + char8 ch; + va_list argp; + char8 *ctrl = (char8 *)ctrl1; + + va_start( argp, ctrl1); + + while ((ctrl != NULL) && (*ctrl != (char8)0)) { + + /* move format string chars to buffer until a */ + /* format control is found. */ + if (*ctrl != '%') { +#ifdef STDOUT_BASEADDRESS + outbyte(*ctrl); +#endif + ctrl += 1; + continue; + } + + /* initialize all the flags for this format. */ + dot_flag = 0; +#if defined (__aarch64__) || defined (__arch64__) + long_flag = 0; +#endif + par.unsigned_flag = 0; + par.left_flag = 0; + par.do_padding = 0; + par.pad_character = ' '; + par.num2=32767; + par.num1=0; + par.len=0; + + try_next: + if(ctrl != NULL) { + ctrl += 1; + } + if(ctrl != NULL) { + ch = *ctrl; + } + else { + ch = *ctrl; + } + + if (isdigit((s32)ch) != 0) { + if (dot_flag != 0) { + par.num2 = getnum(&ctrl); + } + else { + if (ch == '0') { + par.pad_character = '0'; + } + if(ctrl != NULL) { + par.num1 = getnum(&ctrl); + } + par.do_padding = 1; + } + if(ctrl != NULL) { + ctrl -= 1; + } + goto try_next; + } + + switch (tolower((s32)ch)) { + case '%': +#ifdef STDOUT_BASEADDRESS + outbyte( '%'); +#endif + Check = 1; + break; + + case '-': + par.left_flag = 1; + Check = 0; + break; + + case '.': + dot_flag = 1; + Check = 0; + break; + + case 'l': + #if defined (__aarch64__) || defined (__arch64__) + long_flag = 1; + #endif + Check = 0; + break; + + case 'u': + par.unsigned_flag = 1; + /* fall through */ + case 'i': + case 'd': + #if defined (__aarch64__) || defined (__arch64__) + if (long_flag != 0){ + outnum1((s64)va_arg(argp, s64), 10L, &par); + } + else { + outnum( va_arg(argp, s32), 10L, &par); + } + #else + outnum( va_arg(argp, s32), 10L, &par); + #endif + Check = 1; + break; + case 'p': + #if defined (__aarch64__) || defined (__arch64__) + par.unsigned_flag = 1; + outnum1((s64)va_arg(argp, s64), 16L, &par); + Check = 1; + break; + #endif + case 'X': + case 'x': + par.unsigned_flag = 1; + #if defined (__aarch64__) || defined (__arch64__) + if (long_flag != 0) { + outnum1((s64)va_arg(argp, s64), 16L, &par); + } + else { + outnum((s32)va_arg(argp, s32), 16L, &par); + } + #else + outnum((s32)va_arg(argp, s32), 16L, &par); + #endif + Check = 1; + break; + + case 's': + outs( va_arg( argp, char *), &par); + Check = 1; + break; + + case 'c': +#ifdef STDOUT_BASEADDRESS + outbyte( va_arg( argp, s32)); +#endif + Check = 1; + break; + + case '\\': + switch (*ctrl) { + case 'a': +#ifdef STDOUT_BASEADDRESS + outbyte( ((char8)0x07)); +#endif + break; + case 'h': +#ifdef STDOUT_BASEADDRESS + outbyte( ((char8)0x08)); +#endif + break; + case 'r': +#ifdef STDOUT_BASEADDRESS + outbyte( ((char8)0x0D)); +#endif + break; + case 'n': +#ifdef STDOUT_BASEADDRESS + outbyte( ((char8)0x0D)); + outbyte( ((char8)0x0A)); +#endif + break; + default: +#ifdef STDOUT_BASEADDRESS + outbyte( *ctrl); +#endif + break; + } + ctrl += 1; + Check = 0; + break; + + default: + Check = 1; + break; + } + if(Check == 1) { + if(ctrl != NULL) { + ctrl += 1; + } + continue; + } + goto try_next; + } + va_end( argp); +} +#endif +/*---------------------------------------------------*/ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_printf.h b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_printf.h new file mode 100644 index 0000000..a0177fc --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_printf.h @@ -0,0 +1,48 @@ + #ifndef XIL_PRINTF_H + #define XIL_PRINTF_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include "xil_types.h" +#include "xparameters.h" +#include "bspconfig.h" +#if defined (__aarch64__) && HYP_GUEST && EL1_NONSECURE && XEN_USE_PV_CONSOLE +#include "xen_console.h" +#endif + +/*----------------------------------------------------*/ +/* Use the following parameter passing structure to */ +/* make xil_printf re-entrant. */ +/*----------------------------------------------------*/ + +struct params_s; + + +/*---------------------------------------------------*/ +/* The purpose of this routine is to output data the */ +/* same as the standard printf function without the */ +/* overhead most run-time libraries involve. Usually */ +/* the printf brings in many kilobytes of code and */ +/* that is unacceptable in most embedded systems. */ +/*---------------------------------------------------*/ + +typedef char8* charptr; +typedef s32 (*func_ptr)(int c); + +/* */ + +void xil_printf( const char8 *ctrl1, ...); +void print( const char8 *ptr); +extern void outbyte (char8 c); +extern char8 inbyte(void); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_sleepcommon.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_sleepcommon.c new file mode 100644 index 0000000..cb28204 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_sleepcommon.c @@ -0,0 +1,102 @@ +/****************************************************************************** +* +* Copyright (C) 2017 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +*@file xil_sleepcommon.c +* +* This file contains the sleep API's +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 6.6 	srm  	 11/02/17 First release
+* 
+******************************************************************************/ + + +/***************************** Include Files *********************************/ +#include "xil_io.h" +#include "sleep.h" + +/**************************** Constant Definitions *************************/ + + +/*****************************************************************************/ +/** +* +* This API gives delay in sec +* +* @param seconds - delay time in seconds +* +* @return none +* +* @note none +* +*****************************************************************************/ + void sleep(unsigned int seconds) + { +#if defined (ARMR5) + sleep_R5(seconds); +#elif defined (__aarch64__) || defined (ARMA53_32) + sleep_A53(seconds); +#elif defined (__MICROBLAZE__) + sleep_MB(seconds); +#else + sleep_A9(seconds); +#endif + + } + +/****************************************************************************/ +/** +* +* This API gives delay in usec +* +* @param useconds - delay time in useconds +* +* @return none +* +* @note none +* +*****************************************************************************/ + void usleep(unsigned long useconds) + { +#if defined (ARMR5) + usleep_R5(useconds); +#elif defined (__aarch64__) || defined (ARMA53_32) + usleep_A53(useconds); +#elif defined (__MICROBLAZE__) + usleep_MB(useconds); +#else + usleep_A9(useconds); +#endif + + } diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_sleeptimer.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_sleeptimer.c new file mode 100644 index 0000000..316efd5 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_sleeptimer.c @@ -0,0 +1,162 @@ +/****************************************************************************** +* +* Copyright (C) 2017 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xil_sleeptimer.c +* +* This file provides the common helper routines for the sleep API's +* +*
+* MODIFICATION HISTORY :
+*
+* Ver   Who  Date	 Changes
+* ----- ---- -------- -------------------------------------------------------
+* 6.6	srm  10/18/17 First Release.
+* 6.6   srm  04/20/18 Fixed compilation warning in Xil_SleepTTCCommon API
+*
+* 
+*****************************************************************************/ + +/**************************** Include Files ********************************/ + +#include "xil_io.h" +#include "xil_sleeptimer.h" +#include "xtime_l.h" + +/**************************** Constant Definitions *************************/ + + +/* Function definitions are applicable only when TTC3 is present*/ +#if defined (SLEEP_TIMER_BASEADDR) +/****************************************************************************/ +/** +* +* This is a helper function used by sleep/usleep APIs to +* have delay in sec/usec +* +* @param delay - delay time in seconds/micro seconds +* +* @param frequency - Number of counts per second/micro second +* +* @return none +* +* @note none +* +*****************************************************************************/ +void Xil_SleepTTCCommon(u32 delay, u64 frequency) +{ + u64 tEnd = 0U; + u64 tCur = 0U; + XCntrVal TimeHighVal = 0U; + XCntrVal TimeLowVal1 = 0U; + XCntrVal TimeLowVal2 = 0U; + + TimeLowVal1 = XSleep_ReadCounterVal(SLEEP_TIMER_BASEADDR + + XSLEEP_TIMER_TTC_COUNT_VALUE_OFFSET); + tEnd = (u64)TimeLowVal1 + ((u64)(delay) * frequency); + do + { + TimeLowVal2 = XSleep_ReadCounterVal(SLEEP_TIMER_BASEADDR + + XSLEEP_TIMER_TTC_COUNT_VALUE_OFFSET); + if (TimeLowVal2 < TimeLowVal1) { + TimeHighVal++; + } + TimeLowVal1 = TimeLowVal2; + tCur = (((u64) TimeHighVal) << XSLEEP_TIMER_REG_SHIFT) | + (u64)TimeLowVal2; + }while (tCur < tEnd); +} + + +/*****************************************************************************/ +/** +* +* This API starts the Triple Timer Counter +* +* @param none +* +* @return none +* +* @note none +* +*****************************************************************************/ +void XTime_StartTTCTimer() +{ + u32 TimerPrescalar; + u32 TimerCntrl; + +#if (defined (__aarch64__) && EL3==1) || defined (ARMR5) || defined (ARMA53_32) + u32 LpdRst; + +#if defined (versal) + u32 RstAddr = CRL_TTC_RST; + u32 RstMask = CRL_TTC_BASE_RST_MASK << XSLEEP_TTC_INSTANCE; +#else + u32 RstAddr = RST_LPD_IOU2; + u32 RstMask = RST_LPD_IOU2_TTC_BASE_RESET_MASK << XSLEEP_TTC_INSTANCE; +#endif + /* check if the timer is reset */ + LpdRst = XSleep_ReadCounterVal(RstAddr); + if ((LpdRst & RstMask) != 0 ) { + LpdRst = LpdRst & (~RstMask); + Xil_Out32(RstAddr, LpdRst); + } else { +#endif + TimerCntrl = XSleep_ReadCounterVal(SLEEP_TIMER_BASEADDR + + XSLEEP_TIMER_TTC_CNT_CNTRL_OFFSET); + /* check if Timer is disabled */ + if ((TimerCntrl & XSLEEP_TIMER_TTC_CNT_CNTRL_DIS_MASK) == 0) { + TimerPrescalar = XSleep_ReadCounterVal(SLEEP_TIMER_BASEADDR + + XSLEEP_TIMER_TTC_CLK_CNTRL_OFFSET); + /* check if Timer is configured with proper functionalty for sleep */ + if ((TimerPrescalar & XSLEEP_TIMER_TTC_CLK_CNTRL_PS_EN_MASK) == 0) + return; + } +#if (defined (__aarch64__) && EL3==1) || defined (ARMR5) || defined (ARMA53_32) + } +#endif + /* Disable the timer to configure */ + TimerCntrl = XSleep_ReadCounterVal(SLEEP_TIMER_BASEADDR + + XSLEEP_TIMER_TTC_CNT_CNTRL_OFFSET); + TimerCntrl = TimerCntrl | XSLEEP_TIMER_TTC_CNT_CNTRL_DIS_MASK; + Xil_Out32(SLEEP_TIMER_BASEADDR + XSLEEP_TIMER_TTC_CNT_CNTRL_OFFSET, + TimerCntrl); + /* Disable the prescalar */ + TimerPrescalar = XSleep_ReadCounterVal(SLEEP_TIMER_BASEADDR + + XSLEEP_TIMER_TTC_CLK_CNTRL_OFFSET); + TimerPrescalar = TimerPrescalar & (~XSLEEP_TIMER_TTC_CLK_CNTRL_PS_EN_MASK); + Xil_Out32(SLEEP_TIMER_BASEADDR + XSLEEP_TIMER_TTC_CLK_CNTRL_OFFSET, + TimerPrescalar); + /* Enable the Timer */ + TimerCntrl = TimerCntrl & (~XSLEEP_TIMER_TTC_CNT_CNTRL_DIS_MASK); + Xil_Out32(SLEEP_TIMER_BASEADDR + XSLEEP_TIMER_TTC_CNT_CNTRL_OFFSET, + TimerCntrl); +} +#endif diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_sleeptimer.h b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_sleeptimer.h new file mode 100644 index 0000000..08f64ba --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_sleeptimer.h @@ -0,0 +1,128 @@ +/****************************************************************************** +* +* Copyright (C) 2017 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_sleeptimer.h +* +* This header file contains ARM Cortex A53,A9,R5 specific sleep related APIs. +* For sleep related functions that can be used across all Xilinx supported +* processors, please use xil_sleeptimer.h. +* +* +*
+* MODIFICATION HISTORY :
+*
+* Ver   Who  Date	 Changes
+* ----- ---- -------- -------------------------------------------------------
+* 6.6	srm  10/18/17 First Release.
+* 7.0   mus  01/07/19 Add cpp extern macro
+*
+* 
+*****************************************************************************/ + +#ifndef XIL_SLEEPTIMER_H /* prevent circular inclusions */ +#define XIL_SLEEPTIMER_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/**************************** Include Files ********************************/ + +#include "xil_io.h" +#include "xparameters.h" +#include "bspconfig.h" + +/************************** Constant Definitions *****************************/ + +#if defined (ARMR5) || (__aarch64__) || (ARMA53_32) +#define XSLEEP_TIMER_REG_SHIFT 32U +#define XSleep_ReadCounterVal Xil_In32 +#define XCntrVal u32 +#else +#define XSLEEP_TIMER_REG_SHIFT 16U +#define XSleep_ReadCounterVal Xil_In16 +#define XCntrVal u16 +#endif + +#if defined(ARMR5) || (defined (__aarch64__) && EL3==1) || defined (ARMA53_32) +#if defined (versal) +#define CRL_TTC_RST 0xFF5E0344U +#define CRL_TTC_BASE_RST_MASK 0x1U +#else +#define RST_LPD_IOU2 0xFF5E0238U +#define RST_LPD_IOU2_TTC_BASE_RESET_MASK 0x00000800U +#endif +#endif + +#if defined (SLEEP_TIMER_BASEADDR) +/** @name Register Map +* +* Register offsets from the base address of the TTC device +* +* @{ +*/ + #define XSLEEP_TIMER_TTC_CLK_CNTRL_OFFSET 0x00000000U + /**< Clock Control Register */ + #define XSLEEP_TIMER_TTC_CNT_CNTRL_OFFSET 0x0000000CU + /**< Counter Control Register*/ + #define XSLEEP_TIMER_TTC_COUNT_VALUE_OFFSET 0x00000018U + /**< Current Counter Value */ +/* @} */ +/** @name Clock Control Register +* Clock Control Register definitions of TTC +* @{ +*/ + #define XSLEEP_TIMER_TTC_CLK_CNTRL_PS_EN_MASK 0x00000001U + /**< Prescale enable */ +/* @} */ +/** @name Counter Control Register +* Counter Control Register definitions of TTC +* @{ +*/ +#define XSLEEP_TIMER_TTC_CNT_CNTRL_DIS_MASK 0x00000001U + /**< Disable the counter */ +#define XSLEEP_TIMER_TTC_CNT_CNTRL_RST_MASK 0x00000010U + /**< Reset counter */ +/* @} */ + +/**************************** Type Definitions *******************************/ + +/************************** Function Prototypes ******************************/ + +void Xil_SleepTTCCommon(u32 delay, u64 frequency); +void XTime_StartTTCTimer(); + +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* XIL_SLEEPTIMER_H */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_testcache.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_testcache.c new file mode 100644 index 0000000..6ea52a8 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_testcache.c @@ -0,0 +1,367 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_testcache.c +* +* Contains utility functions to test cache. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date	 Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a hbm  07/28/09 Initial release
+* 4.1   asa  05/09/14 Ensured that the address uses for cache test is aligned
+*				      cache line.
+* 
+* +* @note +* This file contain functions that all operate on HAL. +* +******************************************************************************/ +#ifdef __ARM__ +#include "xil_cache.h" +#include "xil_testcache.h" +#include "xil_types.h" +#include "xpseudo_asm.h" +#ifdef __aarch64__ +#include "xreg_cortexa53.h" +#else +#include "xreg_cortexr5.h" +#endif + +#include "xil_types.h" + +extern void xil_printf(const char8 *ctrl1, ...); + +#define DATA_LENGTH 128 + +#ifdef __aarch64__ +static INTPTR Data[DATA_LENGTH] __attribute__ ((aligned(64))); +#else +static INTPTR Data[DATA_LENGTH] __attribute__ ((aligned(32))); +#endif + + +/*****************************************************************************/ +/** +* +* @brief Perform DCache range related API test such as Xil_DCacheFlushRange +* and Xil_DCacheInvalidateRange. This test function writes a constant +* value to the Data array, flushes the range, writes a new value, then +* invalidates the corresponding range. +* @param None +* +* @return +* - -1 is returned for a failure +* - 0 is returned for a pass +* +*****************************************************************************/ +s32 Xil_TestDCacheRange(void) +{ + s32 Index; + s32 Status = 0; + u32 CtrlReg; + INTPTR Value; + + xil_printf("-- Cache Range Test --\n\r"); + + for (Index = 0; Index < DATA_LENGTH; Index++) + Data[Index] = 0xA0A00505; + + xil_printf(" initialize Data done:\r\n"); + + Xil_DCacheFlushRange((INTPTR)Data, DATA_LENGTH * sizeof(INTPTR)); + + xil_printf(" flush range done\r\n"); + + dsb(); + #ifdef __aarch64__ + CtrlReg = mfcp(SCTLR_EL3); + CtrlReg &= ~(XREG_CONTROL_DCACHE_BIT); + mtcp(SCTLR_EL3,CtrlReg); + #else + CtrlReg = mfcp(XREG_CP15_SYS_CONTROL); + CtrlReg &= ~(XREG_CP15_CONTROL_C_BIT); + mtcp(XREG_CP15_SYS_CONTROL, CtrlReg); + #endif + dsb(); + + Status = 0; + + for (Index = 0; Index < DATA_LENGTH; Index++) { + Value = Data[Index]; + if (Value != 0xA0A00505) { + Status = -1; + xil_printf("Data[%d] = %x\r\n", Index, Value); + break; + } + } + + if (!Status) { + xil_printf(" Flush worked\r\n"); + } + else { + xil_printf("Error: flush dcache range not working\r\n"); + } + dsb(); + #ifdef __aarch64__ + CtrlReg = mfcp(SCTLR_EL3); + CtrlReg |= (XREG_CONTROL_DCACHE_BIT); + mtcp(SCTLR_EL3,CtrlReg); + #else + CtrlReg = mfcp(XREG_CP15_SYS_CONTROL); + CtrlReg |= (XREG_CP15_CONTROL_C_BIT); + mtcp(XREG_CP15_SYS_CONTROL, CtrlReg); + #endif + dsb(); + for (Index = 0; Index < DATA_LENGTH; Index++) + Data[Index] = 0xA0A0C505; + + + + Xil_DCacheFlushRange((INTPTR)Data, DATA_LENGTH * sizeof(INTPTR)); + + for (Index = 0; Index < DATA_LENGTH; Index++) + Data[Index] = Index + 3; + + Xil_DCacheInvalidateRange((INTPTR)Data, DATA_LENGTH * sizeof(INTPTR)); + + xil_printf(" invalidate dcache range done\r\n"); + dsb(); + #ifdef __aarch64__ + CtrlReg = mfcp(SCTLR_EL3); + CtrlReg &= ~(XREG_CONTROL_DCACHE_BIT); + mtcp(SCTLR_EL3,CtrlReg); + #else + CtrlReg = mfcp(XREG_CP15_SYS_CONTROL); + CtrlReg &= ~(XREG_CP15_CONTROL_C_BIT); + mtcp(XREG_CP15_SYS_CONTROL, CtrlReg); + #endif + dsb(); + for (Index = 0; Index < DATA_LENGTH; Index++) + Data[Index] = 0xA0A0A05; + dsb(); + #ifdef __aarch64__ + CtrlReg = mfcp(SCTLR_EL3); + CtrlReg |= (XREG_CONTROL_DCACHE_BIT); + mtcp(SCTLR_EL3,CtrlReg); + #else + CtrlReg = mfcp(XREG_CP15_SYS_CONTROL); + CtrlReg |= (XREG_CP15_CONTROL_C_BIT); + mtcp(XREG_CP15_SYS_CONTROL, CtrlReg); + #endif + dsb(); + + Status = 0; + + for (Index = 0; Index < DATA_LENGTH; Index++) { + Value = Data[Index]; + if (Value != 0xA0A0A05) { + Status = -1; + xil_printf("Data[%d] = %x\r\n", Index, Value); + break; + } + } + + + if (!Status) { + xil_printf(" Invalidate worked\r\n"); + } + else { + xil_printf("Error: Invalidate dcache range not working\r\n"); + } + xil_printf("-- Cache Range Test Complete --\r\n"); + return Status; + +} + +/*****************************************************************************/ +/** +* @brief Perform DCache all related API test such as Xil_DCacheFlush and +* Xil_DCacheInvalidate. This test function writes a constant value +* to the Data array, flushes the DCache, writes a new value, +* then invalidates the DCache. +* +* @return +* - 0 is returned for a pass +* - -1 is returned for a failure +*****************************************************************************/ +s32 Xil_TestDCacheAll(void) +{ + s32 Index; + s32 Status; + INTPTR Value; + u32 CtrlReg; + + xil_printf("-- Cache All Test --\n\r"); + + for (Index = 0; Index < DATA_LENGTH; Index++) + Data[Index] = 0x50500A0A; + xil_printf(" initialize Data done:\r\n"); + + Xil_DCacheFlush(); + xil_printf(" flush all done\r\n"); + dsb(); + #ifdef __aarch64__ + CtrlReg = mfcp(SCTLR_EL3); + CtrlReg &= ~(XREG_CONTROL_DCACHE_BIT); + mtcp(SCTLR_EL3,CtrlReg); + #else + CtrlReg = mfcp(XREG_CP15_SYS_CONTROL); + CtrlReg &= ~(XREG_CP15_CONTROL_C_BIT); + mtcp(XREG_CP15_SYS_CONTROL, CtrlReg); + #endif + dsb(); + Status = 0; + + for (Index = 0; Index < DATA_LENGTH; Index++) { + Value = Data[Index]; + + if (Value != 0x50500A0A) { + Status = -1; + xil_printf("Data[%d] = %x\r\n", Index, Value); + break; + } + } + + if (!Status) { + xil_printf(" Flush all worked\r\n"); + } + else { + xil_printf("Error: Flush dcache all not working\r\n"); + } + dsb(); + #ifdef __aarch64__ + CtrlReg = mfcp(SCTLR_EL3); + CtrlReg |= (XREG_CONTROL_DCACHE_BIT); + mtcp(SCTLR_EL3,CtrlReg); + #else + CtrlReg = mfcp(XREG_CP15_SYS_CONTROL); + CtrlReg |= (XREG_CP15_CONTROL_C_BIT); + mtcp(XREG_CP15_SYS_CONTROL, CtrlReg); + #endif + dsb(); + for (Index = 0; Index < DATA_LENGTH; Index++) + Data[Index] = 0x505FFA0A; + + Xil_DCacheFlush(); + + + for (Index = 0; Index < DATA_LENGTH; Index++) + Data[Index] = Index + 3; + + Xil_DCacheInvalidate(); + + xil_printf(" invalidate all done\r\n"); + dsb(); + #ifdef __aarch64__ + CtrlReg = mfcp(SCTLR_EL3); + CtrlReg &= ~(XREG_CONTROL_DCACHE_BIT); + mtcp(SCTLR_EL3,CtrlReg); + #else + CtrlReg = mfcp(XREG_CP15_SYS_CONTROL); + CtrlReg &= ~(XREG_CP15_CONTROL_C_BIT); + mtcp(XREG_CP15_SYS_CONTROL, CtrlReg); + #endif + dsb(); + for (Index = 0; Index < DATA_LENGTH; Index++) + Data[Index] = 0x50CFA0A; + dsb(); + #ifdef __aarch64__ + CtrlReg = mfcp(SCTLR_EL3); + CtrlReg |= (XREG_CONTROL_DCACHE_BIT); + mtcp(SCTLR_EL3,CtrlReg); + #else + CtrlReg = mfcp(XREG_CP15_SYS_CONTROL); + CtrlReg |= (XREG_CP15_CONTROL_C_BIT); + mtcp(XREG_CP15_SYS_CONTROL, CtrlReg); + #endif + dsb(); + Status = 0; + + for (Index = 0; Index < DATA_LENGTH; Index++) { + Value = Data[Index]; + if (Value != 0x50CFA0A) { + Status = -1; + xil_printf("Data[%d] = %x\r\n", Index, Value); + break; + } + } + + if (!Status) { + xil_printf(" Invalidate all worked\r\n"); + } + else { + xil_printf("Error: Invalidate dcache all not working\r\n"); + } + + xil_printf("-- DCache all Test Complete --\n\r"); + + return Status; +} + +/*****************************************************************************/ +/** +* @brief Perform Xil_ICacheInvalidateRange() on a few function pointers. +* +* @return +* - 0 is returned for a pass +* @note +* The function will hang if it fails. +*****************************************************************************/ +s32 Xil_TestICacheRange(void) +{ + + Xil_ICacheInvalidateRange((INTPTR)Xil_TestICacheRange, 1024); + Xil_ICacheInvalidateRange((INTPTR)Xil_TestDCacheRange, 1024); + Xil_ICacheInvalidateRange((INTPTR)Xil_TestDCacheAll, 1024); + + xil_printf("-- Invalidate icache range done --\r\n"); + + return 0; +} + +/*****************************************************************************/ +/** +* @brief Perform Xil_ICacheInvalidate() on a few function pointers. +* +* @return +* - 0 is returned for a pass +* @note +* The function will hang if it fails. +*****************************************************************************/ +s32 Xil_TestICacheAll(void) +{ + Xil_ICacheInvalidate(); + xil_printf("-- Invalidate icache all done --\r\n"); + return 0; +} +#endif diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_testcache.h b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_testcache.h new file mode 100644 index 0000000..8289ca9 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_testcache.h @@ -0,0 +1,67 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_testcache.h +* +* @addtogroup common_test_utils +*

Cache test

+* The xil_testcache.h file contains utility functions to test cache. +* +* @{ +*
+* Ver    Who    Date    Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a hbm  07/29/09 First release
+* 
+* +******************************************************************************/ + +#ifndef XIL_TESTCACHE_H /* prevent circular inclusions */ +#define XIL_TESTCACHE_H /* by using protection macros */ + +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern s32 Xil_TestDCacheRange(void); +extern s32 Xil_TestDCacheAll(void); +extern s32 Xil_TestICacheRange(void); +extern s32 Xil_TestICacheAll(void); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** +* @} End of "addtogroup common_test_utils". +*/ \ No newline at end of file diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_testio.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_testio.c new file mode 100644 index 0000000..9a13a64 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_testio.c @@ -0,0 +1,295 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_testio.c +* +* Contains the memory test utility functions. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver    Who    Date    Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a hbm  08/25/09 First release
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ +#include "xil_testio.h" +#include "xil_assert.h" +#include "xil_io.h" + +/************************** Constant Definitions ****************************/ +/************************** Function Prototypes *****************************/ + + + +/** + * + * Endian swap a 16-bit word. + * @param Data is the 16-bit word to be swapped. + * @return The endian swapped value. + * + */ +static u16 Swap16(u16 Data) +{ + return ((Data >> 8U) & 0x00FFU) | ((Data << 8U) & 0xFF00U); +} + +/** + * + * Endian swap a 32-bit word. + * @param Data is the 32-bit word to be swapped. + * @return The endian swapped value. + * + */ +static u32 Swap32(u32 Data) +{ + u16 Lo16; + u16 Hi16; + + u16 Swap16Lo; + u16 Swap16Hi; + + Hi16 = (u16)((Data >> 16U) & 0x0000FFFFU); + Lo16 = (u16)(Data & 0x0000FFFFU); + + Swap16Lo = Swap16(Lo16); + Swap16Hi = Swap16(Hi16); + + return (((u32)(Swap16Lo)) << 16U) | ((u32)Swap16Hi); +} + +/*****************************************************************************/ +/** +* +* @brief Perform a destructive 8-bit wide register IO test where the +* register is accessed using Xil_Out8 and Xil_In8, and comparing +* the written values by reading them back. +* +* @param Addr: a pointer to the region of memory to be tested. +* @param Length: Length of the block. +* @param Value: constant used for writting the memory. +* +* @return +* - -1 is returned for a failure +* - 0 is returned for a pass +* +*****************************************************************************/ + +s32 Xil_TestIO8(u8 *Addr, s32 Length, u8 Value) +{ + u8 ValueIn; + s32 Index; + s32 Status = 0; + + for (Index = 0; Index < Length; Index++) { + Xil_Out8((INTPTR)Addr, Value); + + ValueIn = Xil_In8((INTPTR)Addr); + + if ((Value != ValueIn) && (Status == 0)) { + Status = -1; + break; + } + } + return Status; + +} + +/*****************************************************************************/ +/** +* +* @brief Perform a destructive 16-bit wide register IO test. Each location +* is tested by sequentially writing a 16-bit wide register, reading +* the register, and comparing value. This function tests three kinds +* of register IO functions, normal register IO, little-endian register +* IO, and big-endian register IO. When testing little/big-endian IO, +* the function performs the following sequence, Xil_Out16LE/Xil_Out16BE, +* Xil_In16, Compare In-Out values, Xil_Out16, Xil_In16LE/Xil_In16BE, +* Compare In-Out values. Whether to swap the read-in value before +* comparing is controlled by the 5th argument. +* +* @param Addr: a pointer to the region of memory to be tested. +* @param Length: Length of the block. +* @param Value: constant used for writting the memory. +* @param Kind: Type of test. Acceptable values are: +* XIL_TESTIO_DEFAULT, XIL_TESTIO_LE, XIL_TESTIO_BE. +* @param Swap: indicates whether to byte swap the read-in value. +* +* @return +* - -1 is returned for a failure +* - 0 is returned for a pass +* +*****************************************************************************/ + +s32 Xil_TestIO16(u16 *Addr, s32 Length, u16 Value, s32 Kind, s32 Swap) +{ + u16 *TempAddr16; + u16 ValueIn = 0U; + s32 Index; + TempAddr16 = Addr; + Xil_AssertNonvoid(TempAddr16 != NULL); + + for (Index = 0; Index < Length; Index++) { + switch (Kind) { + case XIL_TESTIO_LE: + Xil_Out16LE((INTPTR)TempAddr16, Value); + break; + case XIL_TESTIO_BE: + Xil_Out16BE((INTPTR)TempAddr16, Value); + break; + default: + Xil_Out16((INTPTR)TempAddr16, Value); + break; + } + + ValueIn = Xil_In16((INTPTR)TempAddr16); + + if ((Kind != 0) && (Swap != 0)) { + ValueIn = Swap16(ValueIn); + } + + if (Value != ValueIn) { + return -1; + } + + /* second round */ + Xil_Out16((INTPTR)TempAddr16, Value); + + switch (Kind) { + case XIL_TESTIO_LE: + ValueIn = Xil_In16LE((INTPTR)TempAddr16); + break; + case XIL_TESTIO_BE: + ValueIn = Xil_In16BE((INTPTR)TempAddr16); + break; + default: + ValueIn = Xil_In16((INTPTR)TempAddr16); + break; + } + + + if ((Kind != 0) && (Swap != 0)) { + ValueIn = Swap16(ValueIn); + } + + if (Value != ValueIn) { + return -1; + } + TempAddr16 += sizeof(u16); + } + return 0; +} + + +/*****************************************************************************/ +/** +* +* @brief Perform a destructive 32-bit wide register IO test. Each location +* is tested by sequentially writing a 32-bit wide regsiter, reading +* the register, and comparing value. This function tests three kinds +* of register IO functions, normal register IO, little-endian register IO, +* and big-endian register IO. When testing little/big-endian IO, +* the function perform the following sequence, Xil_Out32LE/ +* Xil_Out32BE, Xil_In32, Compare, Xil_Out32, Xil_In32LE/Xil_In32BE, Compare. +* Whether to swap the read-in value *before comparing is controlled +* by the 5th argument. +* @param Addr: a pointer to the region of memory to be tested. +* @param Length: Length of the block. +* @param Value: constant used for writting the memory. +* @param Kind: type of test. Acceptable values are: +* XIL_TESTIO_DEFAULT, XIL_TESTIO_LE, XIL_TESTIO_BE. +* @param Swap: indicates whether to byte swap the read-in value. +* +* @return +* - -1 is returned for a failure +* - 0 is returned for a pass +* +*****************************************************************************/ +s32 Xil_TestIO32(u32 *Addr, s32 Length, u32 Value, s32 Kind, s32 Swap) +{ + u32 *TempAddr; + u32 ValueIn = 0U; + s32 Index; + TempAddr = Addr; + Xil_AssertNonvoid(TempAddr != NULL); + + for (Index = 0; Index < Length; Index++) { + switch (Kind) { + case XIL_TESTIO_LE: + Xil_Out32LE((INTPTR)TempAddr, Value); + break; + case XIL_TESTIO_BE: + Xil_Out32BE((INTPTR)TempAddr, Value); + break; + default: + Xil_Out32((INTPTR)TempAddr, Value); + break; + } + + ValueIn = Xil_In32((INTPTR)TempAddr); + + if ((Kind != 0) && (Swap != 0)) { + ValueIn = Swap32(ValueIn); + } + + if (Value != ValueIn) { + return -1; + } + + /* second round */ + Xil_Out32((INTPTR)TempAddr, Value); + + + switch (Kind) { + case XIL_TESTIO_LE: + ValueIn = Xil_In32LE((INTPTR)TempAddr); + break; + case XIL_TESTIO_BE: + ValueIn = Xil_In32BE((INTPTR)TempAddr); + break; + default: + ValueIn = Xil_In32((INTPTR)TempAddr); + break; + } + + if ((Kind != 0) && (Swap != 0)) { + ValueIn = Swap32(ValueIn); + } + + if (Value != ValueIn) { + return -1; + } + TempAddr += sizeof(u32); + } + return 0; +} diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_testio.h b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_testio.h new file mode 100644 index 0000000..6f0fc1c --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_testio.h @@ -0,0 +1,90 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_testio.h +* +* @addtogroup common_test_utils Test Utilities +*

I/O test

+* The xil_testio.h file contains utility functions to test endian related memory +* IO functions. +* +* A subset of the memory tests can be selected or all of the tests can be run +* in order. If there is an error detected by a subtest, the test stops and the +* failure code is returned. Further tests are not run even if all of the tests +* are selected. +* +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver    Who    Date    Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00 hbm  08/05/09 First release
+* 
+* +******************************************************************************/ + +#ifndef XIL_TESTIO_H /* prevent circular inclusions */ +#define XIL_TESTIO_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ +#include "xil_types.h" + +/************************** Constant Definitions *****************************/ + + +#define XIL_TESTIO_DEFAULT 0 +#define XIL_TESTIO_LE 1 +#define XIL_TESTIO_BE 2 + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + +extern s32 Xil_TestIO8(u8 *Addr, s32 Length, u8 Value); +extern s32 Xil_TestIO16(u16 *Addr, s32 Length, u16 Value, s32 Kind, s32 Swap); +extern s32 Xil_TestIO32(u32 *Addr, s32 Length, u32 Value, s32 Kind, s32 Swap); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** +* @} End of "addtogroup common_test_utils". +*/ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_testmem.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_testmem.c new file mode 100644 index 0000000..b7eb68b --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_testmem.c @@ -0,0 +1,864 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_testmem.c +* +* Contains the memory test utility functions. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver    Who    Date    Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a hbm  08/25/09 First release
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ +#include "xil_testmem.h" +#include "xil_io.h" +#include "xil_assert.h" + +/************************** Constant Definitions ****************************/ +/************************** Function Prototypes *****************************/ + +static u32 RotateLeft(u32 Input, u8 Width); + +/* define ROTATE_RIGHT to give access to this functionality */ +/* #define ROTATE_RIGHT */ +#ifdef ROTATE_RIGHT +static u32 RotateRight(u32 Input, u8 Width); +#endif /* ROTATE_RIGHT */ + + +/*****************************************************************************/ +/** +* +* @brief Perform a destructive 32-bit wide memory test. +* +* @param Addr: pointer to the region of memory to be tested. +* @param Words: length of the block. +* @param Pattern: constant used for the constant pattern test, if 0, +* 0xDEADBEEF is used. +* @param Subtest: test type selected. See xil_testmem.h for possible +* values. +* +* @return +* - 0 is returned for a pass +* - 1 is returned for a failure +* +* @note +* Used for spaces where the address range of the region is smaller than +* the data width. If the memory range is greater than 2 ** Width, +* the patterns used in XIL_TESTMEM_WALKONES and XIL_TESTMEM_WALKZEROS will +* repeat on a boundry of a power of two making it more difficult to detect +* addressing errors. The XIL_TESTMEM_INCREMENT and XIL_TESTMEM_INVERSEADDR +* tests suffer the same problem. Ideally, if large blocks of memory are to be +* tested, break them up into smaller regions of memory to allow the test +* patterns used not to repeat over the region tested. +* +*****************************************************************************/ +s32 Xil_TestMem32(u32 *Addr, u32 Words, u32 Pattern, u8 Subtest) +{ + u32 I; + u32 j; + u32 Val; + u32 FirtVal; + u32 WordMem32; + s32 Status = 0; + + Xil_AssertNonvoid(Words != (u32)0); + Xil_AssertNonvoid(Subtest <= (u8)XIL_TESTMEM_MAXTEST); + Xil_AssertNonvoid(Addr != NULL); + + /* + * variable initialization + */ + Val = XIL_TESTMEM_INIT_VALUE; + FirtVal = XIL_TESTMEM_INIT_VALUE; + + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_INCREMENT)) { + /* + * Fill the memory with incrementing + * values starting from 'FirtVal' + */ + for (I = 0U; I < Words; I++) { + *(Addr+I) = Val; + Val++; + } + + /* + * Restore the reference 'Val' to the + * initial value + */ + Val = FirtVal; + + /* + * Check every word within the words + * of tested memory and compare it + * with the incrementing reference + * Val + */ + + for (I = 0U; I < Words; I++) { + WordMem32 = *(Addr+I); + + if (WordMem32 != Val) { + Status = -1; + goto End_Label; + } + + Val++; + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_WALKONES)) { + /* + * set up to cycle through all possible initial + * test Patterns for walking ones test + */ + + for (j = 0U; j < (u32)32; j++) { + /* + * Generate an initial value for walking ones test + * to test for bad data bits + */ + + Val = (1U << j); + + /* + * START walking ones test + * Write a one to each data bit indifferent locations + */ + + for (I = 0U; I < (u32)32; I++) { + /* write memory location */ + *(Addr+I) = Val; + Val = (u32) RotateLeft(Val, 32U); + } + + /* + * Restore the reference 'val' to the + * initial value + */ + Val = 1U << j; + + /* Read the values from each location that was + * written */ + for (I = 0U; I < (u32)32; I++) { + /* read memory location */ + + WordMem32 = *(Addr+I); + + if (WordMem32 != Val) { + Status = -1; + goto End_Label; + } + + Val = (u32)RotateLeft(Val, 32U); + } + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_WALKZEROS)) { + /* + * set up to cycle through all possible + * initial test Patterns for walking zeros test + */ + + for (j = 0U; j < (u32)32; j++) { + + /* + * Generate an initial value for walking ones test + * to test for bad data bits + */ + + Val = ~(1U << j); + + /* + * START walking zeros test + * Write a one to each data bit indifferent locations + */ + + for (I = 0U; I < (u32)32; I++) { + /* write memory location */ + *(Addr+I) = Val; + Val = ~((u32)RotateLeft(~Val, 32U)); + } + + /* + * Restore the reference 'Val' to the + * initial value + */ + + Val = ~(1U << j); + + /* Read the values from each location that was + * written */ + for (I = 0U; I < (u32)32; I++) { + /* read memory location */ + WordMem32 = *(Addr+I); + if (WordMem32 != Val) { + Status = -1; + goto End_Label; + } + Val = ~((u32)RotateLeft(~Val, 32U)); + } + + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_INVERSEADDR)) { + /* Fill the memory with inverse of address */ + for (I = 0U; I < Words; I++) { + /* write memory location */ + Val = (u32) (~((INTPTR) (&Addr[I]))); + *(Addr+I) = Val; + } + + /* + * Check every word within the words + * of tested memory + */ + + for (I = 0U; I < Words; I++) { + /* Read the location */ + WordMem32 = *(Addr+I); + Val = (u32) (~((INTPTR) (&Addr[I]))); + + if ((WordMem32 ^ Val) != 0x00000000U) { + Status = -1; + goto End_Label; + } + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_FIXEDPATTERN)) { + /* + * Generate an initial value for + * memory testing + */ + + if (Pattern == (u32)0) { + Val = 0xDEADBEEFU; + } + else { + Val = Pattern; + } + + /* + * Fill the memory with fixed Pattern + */ + + for (I = 0U; I < Words; I++) { + /* write memory location */ + *(Addr+I) = Val; + } + + /* + * Check every word within the words + * of tested memory and compare it + * with the fixed Pattern + */ + + for (I = 0U; I < Words; I++) { + + /* read memory location */ + + WordMem32 = *(Addr+I); + if (WordMem32 != Val) { + Status = -1; + goto End_Label; + } + } + } + +End_Label: + return Status; +} + +/*****************************************************************************/ +/** +* +* @brief Perform a destructive 16-bit wide memory test. +* +* @param Addr: pointer to the region of memory to be tested. +* @param Words: length of the block. +* @param Pattern: constant used for the constant Pattern test, if 0, +* 0xDEADBEEF is used. +* @param Subtest: type of test selected. See xil_testmem.h for possible +* values. +* +* @return +* +* - -1 is returned for a failure +* - 0 is returned for a pass +* +* @note +* Used for spaces where the address range of the region is smaller than +* the data width. If the memory range is greater than 2 ** Width, +* the patterns used in XIL_TESTMEM_WALKONES and XIL_TESTMEM_WALKZEROS will +* repeat on a boundry of a power of two making it more difficult to detect +* addressing errors. The XIL_TESTMEM_INCREMENT and XIL_TESTMEM_INVERSEADDR +* tests suffer the same problem. Ideally, if large blocks of memory are to be +* tested, break them up into smaller regions of memory to allow the test +* patterns used not to repeat over the region tested. +* +*****************************************************************************/ +s32 Xil_TestMem16(u16 *Addr, u32 Words, u16 Pattern, u8 Subtest) +{ + u32 I; + u32 j; + u16 Val; + u16 FirtVal; + u16 WordMem16; + s32 Status = 0; + + Xil_AssertNonvoid(Words != (u32)0); + Xil_AssertNonvoid(Subtest <= XIL_TESTMEM_MAXTEST); + Xil_AssertNonvoid(Addr != NULL); + + /* + * variable initialization + */ + Val = XIL_TESTMEM_INIT_VALUE; + FirtVal = XIL_TESTMEM_INIT_VALUE; + + /* + * selectthe proper Subtest(s) + */ + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_INCREMENT)) { + /* + * Fill the memory with incrementing + * values starting from 'FirtVal' + */ + for (I = 0U; I < Words; I++) { + /* write memory location */ + *(Addr+I) = Val; + Val++; + } + /* + * Restore the reference 'Val' to the + * initial value + */ + Val = FirtVal; + + /* + * Check every word within the words + * of tested memory and compare it + * with the incrementing reference val + */ + + for (I = 0U; I < Words; I++) { + /* read memory location */ + WordMem16 = *(Addr+I); + if (WordMem16 != Val) { + Status = -1; + goto End_Label; + } + Val++; + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_WALKONES)) { + /* + * set up to cycle through all possible initial test + * Patterns for walking ones test + */ + + for (j = 0U; j < (u32)16; j++) { + /* + * Generate an initial value for walking ones test + * to test for bad data bits + */ + + Val = (u16)((u32)1 << j); + /* + * START walking ones test + * Write a one to each data bit indifferent locations + */ + + for (I = 0U; I < (u32)16; I++) { + /* write memory location */ + *(Addr+I) = Val; + Val = (u16)RotateLeft(Val, 16U); + } + /* + * Restore the reference 'Val' to the + * initial value + */ + Val = (u16)((u32)1 << j); + /* Read the values from each location that was written */ + for (I = 0U; I < (u32)16; I++) { + /* read memory location */ + WordMem16 = *(Addr+I); + if (WordMem16 != Val) { + Status = -1; + goto End_Label; + } + Val = (u16)RotateLeft(Val, 16U); + } + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_WALKZEROS)) { + /* + * set up to cycle through all possible initial + * test Patterns for walking zeros test + */ + + for (j = 0U; j < (u32)16; j++) { + /* + * Generate an initial value for walking ones + * test to test for bad + * data bits + */ + + Val = ~(1U << j); + /* + * START walking zeros test + * Write a one to each data bit indifferent locations + */ + + for (I = 0U; I < (u32)16; I++) { + /* write memory location */ + *(Addr+I) = Val; + Val = ~((u16)RotateLeft(~Val, 16U)); + } + /* + * Restore the reference 'Val' to the + * initial value + */ + Val = ~(1U << j); + /* Read the values from each location that was written */ + for (I = 0U; I < (u32)16; I++) { + /* read memory location */ + WordMem16 = *(Addr+I); + if (WordMem16 != Val) { + Status = -1; + goto End_Label; + } + Val = ~((u16)RotateLeft(~Val, 16U)); + } + + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_INVERSEADDR)) { + /* Fill the memory with inverse of address */ + for (I = 0U; I < Words; I++) { + /* write memory location */ + Val = (u16) (~((INTPTR)(&Addr[I]))); + *(Addr+I) = Val; + } + /* + * Check every word within the words + * of tested memory + */ + + for (I = 0U; I < Words; I++) { + /* read memory location */ + WordMem16 = *(Addr+I); + Val = (u16) (~((INTPTR) (&Addr[I]))); + if ((WordMem16 ^ Val) != 0x0000U) { + Status = -1; + goto End_Label; + } + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_FIXEDPATTERN)) { + /* + * Generate an initial value for + * memory testing + */ + if (Pattern == (u16)0) { + Val = 0xDEADU; + } + else { + Val = Pattern; + } + + /* + * Fill the memory with fixed pattern + */ + + for (I = 0U; I < Words; I++) { + /* write memory location */ + *(Addr+I) = Val; + } + + /* + * Check every word within the words + * of tested memory and compare it + * with the fixed pattern + */ + + for (I = 0U; I < Words; I++) { + /* read memory location */ + WordMem16 = *(Addr+I); + if (WordMem16 != Val) { + Status = -1; + goto End_Label; + } + } + } + +End_Label: + return Status; +} + + +/*****************************************************************************/ +/** +* +* @brief Perform a destructive 8-bit wide memory test. +* +* @param Addr: pointer to the region of memory to be tested. +* @param Words: length of the block. +* @param Pattern: constant used for the constant pattern test, if 0, +* 0xDEADBEEF is used. +* @param Subtest: type of test selected. See xil_testmem.h for possible +* values. +* +* @return +* - -1 is returned for a failure +* - 0 is returned for a pass +* +* @note +* Used for spaces where the address range of the region is smaller than +* the data width. If the memory range is greater than 2 ** Width, +* the patterns used in XIL_TESTMEM_WALKONES and XIL_TESTMEM_WALKZEROS will +* repeat on a boundry of a power of two making it more difficult to detect +* addressing errors. The XIL_TESTMEM_INCREMENT and XIL_TESTMEM_INVERSEADDR +* tests suffer the same problem. Ideally, if large blocks of memory are to be +* tested, break them up into smaller regions of memory to allow the test +* patterns used not to repeat over the region tested. +* +*****************************************************************************/ +s32 Xil_TestMem8(u8 *Addr, u32 Words, u8 Pattern, u8 Subtest) +{ + u32 I; + u32 j; + u8 Val; + u8 FirtVal; + u8 WordMem8; + s32 Status = 0; + + Xil_AssertNonvoid(Words != (u32)0); + Xil_AssertNonvoid(Subtest <= XIL_TESTMEM_MAXTEST); + Xil_AssertNonvoid(Addr != NULL); + + /* + * variable initialization + */ + Val = XIL_TESTMEM_INIT_VALUE; + FirtVal = XIL_TESTMEM_INIT_VALUE; + + /* + * select the proper Subtest(s) + */ + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_INCREMENT)) { + /* + * Fill the memory with incrementing + * values starting from 'FirtVal' + */ + for (I = 0U; I < Words; I++) { + /* write memory location */ + *(Addr+I) = Val; + Val++; + } + /* + * Restore the reference 'Val' to the + * initial value + */ + Val = FirtVal; + /* + * Check every word within the words + * of tested memory and compare it + * with the incrementing reference + * Val + */ + + for (I = 0U; I < Words; I++) { + /* read memory location */ + WordMem8 = *(Addr+I); + if (WordMem8 != Val) { + Status = -1; + goto End_Label; + } + Val++; + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_WALKONES)) { + /* + * set up to cycle through all possible initial + * test Patterns for walking ones test + */ + + for (j = 0U; j < (u32)8; j++) { + /* + * Generate an initial value for walking ones test + * to test for bad data bits + */ + Val = (u8)((u32)1 << j); + /* + * START walking ones test + * Write a one to each data bit indifferent locations + */ + for (I = 0U; I < (u32)8; I++) { + /* write memory location */ + *(Addr+I) = Val; + Val = (u8)RotateLeft(Val, 8U); + } + /* + * Restore the reference 'Val' to the + * initial value + */ + Val = (u8)((u32)1 << j); + /* Read the values from each location that was written */ + for (I = 0U; I < (u32)8; I++) { + /* read memory location */ + WordMem8 = *(Addr+I); + if (WordMem8 != Val) { + Status = -1; + goto End_Label; + } + Val = (u8)RotateLeft(Val, 8U); + } + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_WALKZEROS)) { + /* + * set up to cycle through all possible initial test + * Patterns for walking zeros test + */ + + for (j = 0U; j < (u32)8; j++) { + /* + * Generate an initial value for walking ones test to test + * for bad data bits + */ + Val = ~(1U << j); + /* + * START walking zeros test + * Write a one to each data bit indifferent locations + */ + for (I = 0U; I < (u32)8; I++) { + /* write memory location */ + *(Addr+I) = Val; + Val = ~((u8)RotateLeft(~Val, 8U)); + } + /* + * Restore the reference 'Val' to the + * initial value + */ + Val = ~(1U << j); + /* Read the values from each location that was written */ + for (I = 0U; I < (u32)8; I++) { + /* read memory location */ + WordMem8 = *(Addr+I); + if (WordMem8 != Val) { + Status = -1; + goto End_Label; + } + + Val = ~((u8)RotateLeft(~Val, 8U)); + } + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_INVERSEADDR)) { + /* Fill the memory with inverse of address */ + for (I = 0U; I < Words; I++) { + /* write memory location */ + Val = (u8) (~((INTPTR) (&Addr[I]))); + *(Addr+I) = Val; + } + + /* + * Check every word within the words + * of tested memory + */ + + for (I = 0U; I < Words; I++) { + /* read memory location */ + WordMem8 = *(Addr+I); + Val = (u8) (~((INTPTR) (&Addr[I]))); + if ((WordMem8 ^ Val) != 0x00U) { + Status = -1; + goto End_Label; + } + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_FIXEDPATTERN)) { + /* + * Generate an initial value for + * memory testing + */ + + if (Pattern == (u8)0) { + Val = 0xA5U; + } + else { + Val = Pattern; + } + /* + * Fill the memory with fixed Pattern + */ + for (I = 0U; I < Words; I++) { + /* write memory location */ + *(Addr+I) = Val; + } + /* + * Check every word within the words + * of tested memory and compare it + * with the fixed Pattern + */ + + for (I = 0U; I < Words; I++) { + /* read memory location */ + WordMem8 = *(Addr+I); + if (WordMem8 != Val) { + Status = -1; + goto End_Label; + } + } + } + +End_Label: + return Status; +} + + +/*****************************************************************************/ +/** +* +* @brief Rotates the provided value to the left one bit position +* +* @param Input is value to be rotated to the left +* @param Width is the number of bits in the input data +* +* @return +* The resulting unsigned long value of the rotate left +* +* +*****************************************************************************/ +static u32 RotateLeft(u32 Input, u8 Width) +{ + u32 Msb; + u32 ReturnVal; + u32 WidthMask; + u32 MsbMask; + u32 LocalInput = Input; + + /* + * set up the WidthMask and the MsbMask + */ + + MsbMask = 1U << (Width - 1U); + + WidthMask = (MsbMask << (u32)1) - (u32)1; + + /* + * set the Width of the Input to the correct width + */ + + LocalInput = LocalInput & WidthMask; + + Msb = LocalInput & MsbMask; + + ReturnVal = LocalInput << 1U; + + if (Msb != 0x00000000U) { + ReturnVal = ReturnVal | (u32)0x00000001; + } + + ReturnVal = ReturnVal & WidthMask; + + return ReturnVal; + +} + +#ifdef ROTATE_RIGHT +/*****************************************************************************/ +/** +* +* @brief Rotates the provided value to the right one bit position +* +* @param Input: value to be rotated to the right +* @param Width: number of bits in the input data +* +* @return +* The resulting u32 value of the rotate right +* +*****************************************************************************/ +static u32 RotateRight(u32 Input, u8 Width) +{ + u32 Lsb; + u32 ReturnVal; + u32 WidthMask; + u32 MsbMask; + u32 LocalInput = Input; + /* + * set up the WidthMask and the MsbMask + */ + + MsbMask = 1U << (Width - 1U); + + WidthMask = (MsbMask << 1U) - 1U; + + /* + * set the width of the input to the correct width + */ + + LocalInput = LocalInput & WidthMask; + + ReturnVal = LocalInput >> 1U; + + Lsb = LocalInput & 0x00000001U; + + if (Lsb != 0x00000000U) { + ReturnVal = ReturnVal | MsbMask; + } + + ReturnVal = ReturnVal & WidthMask; + + return ReturnVal; + +} +#endif /* ROTATE_RIGHT */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_testmem.h b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_testmem.h new file mode 100644 index 0000000..ecce6b7 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_testmem.h @@ -0,0 +1,154 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_testmem.h +* @addtogroup common_test_utils +* +*

Memory test

+* +* The xil_testmem.h file contains utility functions to test memory. +* A subset of the memory tests can be selected or all of the tests can be run +* in order. If there is an error detected by a subtest, the test stops and the +* failure code is returned. Further tests are not run even if all of the tests +* are selected. +* Following list describes the supported memory tests: +* +* - XIL_TESTMEM_ALLMEMTESTS: This test runs all of the subtests. +* +* - XIL_TESTMEM_INCREMENT: This test +* starts at 'XIL_TESTMEM_INIT_VALUE' and uses the incrementing value as the +* test value for memory. +* +* - XIL_TESTMEM_WALKONES: Also known as the Walking ones test. This test +* uses a walking '1' as the test value for memory. +* @code +* location 1 = 0x00000001 +* location 2 = 0x00000002 +* ... +* @endcode +* +* - XIL_TESTMEM_WALKZEROS: Also known as the Walking zero's test. +* This test uses the inverse value of the walking ones test +* as the test value for memory. +* @code +* location 1 = 0xFFFFFFFE +* location 2 = 0xFFFFFFFD +* ... +*@endcode +* +* - XIL_TESTMEM_INVERSEADDR: Also known as the inverse address test. +* This test uses the inverse of the address of the location under test +* as the test value for memory. +* +* - XIL_TESTMEM_FIXEDPATTERN: Also known as the fixed pattern test. +* This test uses the provided patters as the test value for memory. +* If zero is provided as the pattern the test uses '0xDEADBEEF". +* +* @warning +* The tests are DESTRUCTIVE. Run before any initialized memory spaces +* have been set up. +* The address provided to the memory tests is not checked for +* validity except for the NULL case. It is possible to provide a code-space +* pointer for this test to start with and ultimately destroy executable code +* causing random failures. +* +* @note +* Used for spaces where the address range of the region is smaller than +* the data width. If the memory range is greater than 2 ** width, +* the patterns used in XIL_TESTMEM_WALKONES and XIL_TESTMEM_WALKZEROS will +* repeat on a boundry of a power of two making it more difficult to detect +* addressing errors. The XIL_TESTMEM_INCREMENT and XIL_TESTMEM_INVERSEADDR +* tests suffer the same problem. Ideally, if large blocks of memory are to be +* tested, break them up into smaller regions of memory to allow the test +* patterns used not to repeat over the region tested. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver    Who    Date    Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a hbm  08/25/09 First release
+* 
+* +******************************************************************************/ + +#ifndef XIL_TESTMEM_H /* prevent circular inclusions */ +#define XIL_TESTMEM_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ +#include "xil_types.h" + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + +/* xutil_memtest defines */ + +#define XIL_TESTMEM_INIT_VALUE 1U + +/** @name Memory subtests + * @{ + */ +/** + * See the detailed description of the subtests in the file description. + */ +#define XIL_TESTMEM_ALLMEMTESTS 0x00U +#define XIL_TESTMEM_INCREMENT 0x01U +#define XIL_TESTMEM_WALKONES 0x02U +#define XIL_TESTMEM_WALKZEROS 0x03U +#define XIL_TESTMEM_INVERSEADDR 0x04U +#define XIL_TESTMEM_FIXEDPATTERN 0x05U +#define XIL_TESTMEM_MAXTEST XIL_TESTMEM_FIXEDPATTERN +/* @} */ + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + +/* xutil_testmem prototypes */ + +extern s32 Xil_TestMem32(u32 *Addr, u32 Words, u32 Pattern, u8 Subtest); +extern s32 Xil_TestMem16(u16 *Addr, u32 Words, u16 Pattern, u8 Subtest); +extern s32 Xil_TestMem8(u8 *Addr, u32 Words, u8 Pattern, u8 Subtest); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** +* @} End of "addtogroup common_test_utils". +*/ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_types.h b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_types.h new file mode 100644 index 0000000..625ff8c --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_types.h @@ -0,0 +1,214 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_types.h +* +* @addtogroup common_types Basic Data types for Xilinx® Software IP +* +* The xil_types.h file contains basic types for Xilinx software IP. These data types +* are applicable for all processors supported by Xilinx. +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date   Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a hbm  07/14/09 First release
+* 3.03a sdm  05/30/11 Added Xuint64 typedef and XUINT64_MSW/XUINT64_LSW macros
+* 5.00 	pkp  05/29/14 Made changes for 64 bit architecture
+*	srt  07/14/14 Use standard definitions from stdint.h and stddef.h
+*		      Define LONG and ULONG datatypes and mask values
+* 7.00  mus  01/07/19 Add cpp extern macro
+* 
+* +******************************************************************************/ + +#ifndef XIL_TYPES_H /* prevent circular inclusions */ +#define XIL_TYPES_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +/************************** Constant Definitions *****************************/ + +#ifndef TRUE +# define TRUE 1U +#endif + +#ifndef FALSE +# define FALSE 0U +#endif + +#ifndef NULL +#define NULL 0U +#endif + +#define XIL_COMPONENT_IS_READY 0x11111111U /**< In device drivers, This macro will be + assigend to "IsReady" member of driver + instance to indicate that driver + instance is initialized and ready to use. */ +#define XIL_COMPONENT_IS_STARTED 0x22222222U /**< In device drivers, This macro will be assigend to + "IsStarted" member of driver instance + to indicate that driver instance is + started and it can be enabled. */ + +/* @name New types + * New simple types. + * @{ + */ +#ifndef __KERNEL__ +#ifndef XBASIC_TYPES_H +/* + * guarded against xbasic_types.h. + */ +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; +/** @}*/ +#define __XUINT64__ +typedef struct +{ + u32 Upper; + u32 Lower; +} Xuint64; + + +/*****************************************************************************/ +/** +* @brief Return the most significant half of the 64 bit data type. +* +* @param x is the 64 bit word. +* +* @return The upper 32 bits of the 64 bit word. +* +******************************************************************************/ +#define XUINT64_MSW(x) ((x).Upper) + +/*****************************************************************************/ +/** +* @brief Return the least significant half of the 64 bit data type. +* +* @param x is the 64 bit word. +* +* @return The lower 32 bits of the 64 bit word. +* +******************************************************************************/ +#define XUINT64_LSW(x) ((x).Lower) + +#endif /* XBASIC_TYPES_H */ + +/* + * xbasic_types.h does not typedef s* or u64 + */ +/** @{ */ +typedef char char8; +typedef int8_t s8; +typedef int16_t s16; +typedef int32_t s32; +typedef int64_t s64; +typedef uint64_t u64; +typedef int sint32; + +typedef intptr_t INTPTR; +typedef uintptr_t UINTPTR; +typedef ptrdiff_t PTRDIFF; +/** @}*/ +#if !defined(LONG) || !defined(ULONG) +typedef long LONG; +typedef unsigned long ULONG; +#endif + +#define ULONG64_HI_MASK 0xFFFFFFFF00000000U +#define ULONG64_LO_MASK ~ULONG64_HI_MASK + +#else +#include +#endif + +/** @{ */ +/** + * This data type defines an interrupt handler for a device. + * The argument points to the instance of the component + */ +typedef void (*XInterruptHandler) (void *InstancePtr); + +/** + * This data type defines an exception handler for a processor. + * The argument points to the instance of the component + */ +typedef void (*XExceptionHandler) (void *InstancePtr); + +/** + * @brief Returns 32-63 bits of a number. + * @param n : Number being accessed. + * @return Bits 32-63 of number. + * + * @note A basic shift-right of a 64- or 32-bit quantity. + * Use this to suppress the "right shift count >= width of type" + * warning when that quantity is 32-bits. + */ +#define UPPER_32_BITS(n) ((u32)(((n) >> 16) >> 16)) + +/** + * @brief Returns 0-31 bits of a number + * @param n : Number being accessed. + * @return Bits 0-31 of number + */ +#define LOWER_32_BITS(n) ((u32)(n)) + + + + +/************************** Constant Definitions *****************************/ + +#ifndef TRUE +#define TRUE 1U +#endif + +#ifndef FALSE +#define FALSE 0U +#endif + +#ifndef NULL +#define NULL 0U +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** +* @} End of "addtogroup common_types". +*/ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_util.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_util.c new file mode 100644 index 0000000..d9282ca --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_util.c @@ -0,0 +1,175 @@ +/******************************************************************************/ +/** +* Copyright (C) 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* @file xil_util.c +* +* This file contains xil utility functions +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 6.4   mmd      04/21/19 First release.
+*
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ +#include "xil_types.h" +#include "xil_io.h" +#include "xstatus.h" + +/************************** Constant Definitions ****************************/ +#define MAX_NIBBLES 8U + +/************************** Function Prototypes *****************************/ +/****************************************************************************/ +/** + * Converts the char into the equivalent nibble. + * Ex: 'a' -> 0xa, 'A' -> 0xa, '9'->0x9 + * + * @param InChar is input character. It has to be between 0-9,a-f,A-F + * @param Num is the output nibble. + * + * @return + * - XST_SUCCESS no errors occured. + * - ERROR when input parameters are not valid + * + * @note None. + * + *****************************************************************************/ + +u32 Xil_ConvertCharToNibble(u8 InChar, u8 *Num) +{ + u32 Status; + + /* Convert the char to nibble */ + if ((InChar >= (u8)'0') && (InChar <= (u8)'9')) { + *Num = InChar - (u8)'0'; + Status = XST_SUCCESS; + } + else if ((InChar >= (u8)'a') && (InChar <= (u8)'f')) { + *Num = InChar - (u8)'a' + 10U; + Status = XST_SUCCESS; + } + else if ((InChar >= (u8)'A') && (InChar <= (u8)'F')) { + *Num = InChar - (u8)'A' + 10U; + Status = XST_SUCCESS; + } + else { + Status = XST_FAILURE; + } + + return Status; +} + +/****************************************************************************/ +/* + * Converts the string into the equivalent Hex buffer. + * Ex: "abc123" -> {0xab, 0xc1, 0x23} + * + * @param Str is a Input String. Will support the lower and upper + * case values. Value should be between 0-9, a-f and A-F + * + * @param Buf is Output buffer. + * @param Len of the input string. Should have even values + * + * @return + * - XST_SUCCESS no errors occured. + * - ERROR when input parameters are not valid + * - an error when input buffer has invalid values + * + * @note None. + * + *****************************************************************************/ +u32 Xil_ConvertStringToHex(const char *Str, u32 *buf, u8 Len) +{ + u32 Status = XST_FAILURE; + u8 ConvertedLen = 0U, index = 0U; + u8 Nibble[MAX_NIBBLES] = {0U}; + u8 i; + + while (ConvertedLen < Len) { + /* Convert char to nibble */ + for (i = 0U; i < MAX_NIBBLES; i++) { + Status = Xil_ConvertCharToNibble( + Str[ConvertedLen], &Nibble[i]); + ConvertedLen = ConvertedLen +1U; + if (Status != XST_SUCCESS) { + /* Error converting char to nibble */ + goto END; + } + } + + buf[index] = ((Nibble[0] << (u8)28U )| (Nibble[1] << (u8)24U) | + (Nibble[2] << (u8)20U) | (Nibble[3] << (u8)16U) | + (Nibble[4] << (u8)12U) | (Nibble[5] << (u8)8U)| + (Nibble[6] << (u8)4U) | (u32)Nibble[7]); + index++; + } +END: + return Status; +} + +/****************************************************************************/ +/* + * Waits for the event + * + * @param RegAddr Address of register to be checked for event(s) occurance + * @param EventMask Mask indicating event(s) to be checked + * @param Event Specific event(s) value to be checked + * @param Timeout Free counter decremented on each event(s) check and + * declared timeout when reaches 0 + * + * @return + * - XST_SUCCESS On occurance of the event(s). + * - XST_FAILURE Event did not occur before counter reaches 0 + * + * @note None. + * + *****************************************************************************/ +u32 Xil_WaitForEvent(u32 RegAddr, u32 EventMask, u32 Event, u32 Timeout) +{ + u32 RegVal; + u32 PollCount = Timeout; + u32 Status = XST_FAILURE; + + while(PollCount > 0) { + RegVal = Xil_In32(RegAddr) & EventMask; + if (RegVal == Event) { + Status = XST_SUCCESS; + break; + } + PollCount--; + } + + return Status; +} diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_util.h b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_util.h new file mode 100644 index 0000000..194c425 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xil_util.h @@ -0,0 +1,57 @@ +/******************************************************************************/ +/** +* Copyright (C) 2019 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* @file xil_util.h +* +* This file contains xil utility functions declaration +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 6.4   mmd      04/21/19 First release.
+*
+* 
+* +*****************************************************************************/ + +#ifndef XIL_UTIL_H_ +#define XIL_UTIL_H_ + +/* Converts input character to nibble */ +u32 Xil_ConvertCharToNibble(u8 InChar, u8 *Num); + +/* Conver input hex string to array of 32-bits integers */ +u32 Xil_ConvertStringToHex(const char *Str, u32 *buf, u8 Len); + +/* Waits for specified event */ +u32 Xil_WaitForEvent(u32 RegAddr, u32 EventMask, u32 Event, u32 Timeout); + +#endif /* XIL_UTIL_H_ */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xl2cc.h b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xl2cc.h new file mode 100644 index 0000000..22373c1 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xl2cc.h @@ -0,0 +1,168 @@ +/****************************************************************************** +* +* Copyright (C) 2011 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file xl2cc.h +* +* This file contains the address definitions for the PL310 Level-2 Cache +* Controller. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- ---------------------------------------------------
+* 1.00a sdm  02/01/10 Initial version
+* 3.10a srt 04/18/13 Implemented ARM Erratas. Please refer to file
+*		      'xil_errata.h' for errata description
+* 
+* +* @note +* +* None. +* +******************************************************************************/ + +#ifndef _XL2CC_H_ +#define _XL2CC_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/************************** Constant Definitions *****************************/ +/* L2CC Register Offsets */ +#define XPS_L2CC_ID_OFFSET 0x0000U +#define XPS_L2CC_TYPE_OFFSET 0x0004U +#define XPS_L2CC_CNTRL_OFFSET 0x0100U +#define XPS_L2CC_AUX_CNTRL_OFFSET 0x0104U +#define XPS_L2CC_TAG_RAM_CNTRL_OFFSET 0x0108U +#define XPS_L2CC_DATA_RAM_CNTRL_OFFSET 0x010CU + +#define XPS_L2CC_EVNT_CNTRL_OFFSET 0x0200U +#define XPS_L2CC_EVNT_CNT1_CTRL_OFFSET 0x0204U +#define XPS_L2CC_EVNT_CNT0_CTRL_OFFSET 0x0208U +#define XPS_L2CC_EVNT_CNT1_VAL_OFFSET 0x020CU +#define XPS_L2CC_EVNT_CNT0_VAL_OFFSET 0x0210U + +#define XPS_L2CC_IER_OFFSET 0x0214U /* Interrupt Mask */ +#define XPS_L2CC_IPR_OFFSET 0x0218U /* Masked interrupt status */ +#define XPS_L2CC_ISR_OFFSET 0x021CU /* Raw Interrupt Status */ +#define XPS_L2CC_IAR_OFFSET 0x0220U /* Interrupt Clear */ + +#define XPS_L2CC_CACHE_SYNC_OFFSET 0x0730U /* Cache Sync */ +#define XPS_L2CC_DUMMY_CACHE_SYNC_OFFSET 0x0740U /* Dummy Register for Cache Sync */ +#define XPS_L2CC_CACHE_INVLD_PA_OFFSET 0x0770U /* Cache Invalid by PA */ +#define XPS_L2CC_CACHE_INVLD_WAY_OFFSET 0x077CU /* Cache Invalid by Way */ +#define XPS_L2CC_CACHE_CLEAN_PA_OFFSET 0x07B0U /* Cache Clean by PA */ +#define XPS_L2CC_CACHE_CLEAN_INDX_OFFSET 0x07B8U /* Cache Clean by Index */ +#define XPS_L2CC_CACHE_CLEAN_WAY_OFFSET 0x07BCU /* Cache Clean by Way */ +#define XPS_L2CC_CACHE_INV_CLN_PA_OFFSET 0x07F0U /* Cache Invalidate and Clean by PA */ +#define XPS_L2CC_CACHE_INV_CLN_INDX_OFFSET 0x07F8U /* Cache Invalidate and Clean by Index */ +#define XPS_L2CC_CACHE_INV_CLN_WAY_OFFSET 0x07FCU /* Cache Invalidate and Clean by Way */ + +#define XPS_L2CC_CACHE_DLCKDWN_0_WAY_OFFSET 0x0900U /* Cache Data Lockdown 0 by Way */ +#define XPS_L2CC_CACHE_ILCKDWN_0_WAY_OFFSET 0x0904U /* Cache Instruction Lockdown 0 by Way */ +#define XPS_L2CC_CACHE_DLCKDWN_1_WAY_OFFSET 0x0908U /* Cache Data Lockdown 1 by Way */ +#define XPS_L2CC_CACHE_ILCKDWN_1_WAY_OFFSET 0x090CU /* Cache Instruction Lockdown 1 by Way */ +#define XPS_L2CC_CACHE_DLCKDWN_2_WAY_OFFSET 0x0910U /* Cache Data Lockdown 2 by Way */ +#define XPS_L2CC_CACHE_ILCKDWN_2_WAY_OFFSET 0x0914U /* Cache Instruction Lockdown 2 by Way */ +#define XPS_L2CC_CACHE_DLCKDWN_3_WAY_OFFSET 0x0918U /* Cache Data Lockdown 3 by Way */ +#define XPS_L2CC_CACHE_ILCKDWN_3_WAY_OFFSET 0x091CU /* Cache Instruction Lockdown 3 by Way */ +#define XPS_L2CC_CACHE_DLCKDWN_4_WAY_OFFSET 0x0920U /* Cache Data Lockdown 4 by Way */ +#define XPS_L2CC_CACHE_ILCKDWN_4_WAY_OFFSET 0x0924U /* Cache Instruction Lockdown 4 by Way */ +#define XPS_L2CC_CACHE_DLCKDWN_5_WAY_OFFSET 0x0928U /* Cache Data Lockdown 5 by Way */ +#define XPS_L2CC_CACHE_ILCKDWN_5_WAY_OFFSET 0x092CU /* Cache Instruction Lockdown 5 by Way */ +#define XPS_L2CC_CACHE_DLCKDWN_6_WAY_OFFSET 0x0930U /* Cache Data Lockdown 6 by Way */ +#define XPS_L2CC_CACHE_ILCKDWN_6_WAY_OFFSET 0x0934U /* Cache Instruction Lockdown 6 by Way */ +#define XPS_L2CC_CACHE_DLCKDWN_7_WAY_OFFSET 0x0938U /* Cache Data Lockdown 7 by Way */ +#define XPS_L2CC_CACHE_ILCKDWN_7_WAY_OFFSET 0x093CU /* Cache Instruction Lockdown 7 by Way */ + +#define XPS_L2CC_CACHE_LCKDWN_LINE_ENABLE_OFFSET 0x0950U /* Cache Lockdown Line Enable */ +#define XPS_L2CC_CACHE_UUNLOCK_ALL_WAY_OFFSET 0x0954U /* Cache Unlock All Lines by Way */ + +#define XPS_L2CC_ADDR_FILTER_START_OFFSET 0x0C00U /* Start of address filtering */ +#define XPS_L2CC_ADDR_FILTER_END_OFFSET 0x0C04U /* Start of address filtering */ + +#define XPS_L2CC_DEBUG_CTRL_OFFSET 0x0F40U /* Debug Control Register */ + +/* XPS_L2CC_CNTRL_OFFSET bit masks */ +#define XPS_L2CC_ENABLE_MASK 0x00000001U /* enables the L2CC */ + +/* XPS_L2CC_AUX_CNTRL_OFFSET bit masks */ +#define XPS_L2CC_AUX_EBRESPE_MASK 0x40000000U /* Early BRESP Enable */ +#define XPS_L2CC_AUX_IPFE_MASK 0x20000000U /* Instruction Prefetch Enable */ +#define XPS_L2CC_AUX_DPFE_MASK 0x10000000U /* Data Prefetch Enable */ +#define XPS_L2CC_AUX_NSIC_MASK 0x08000000U /* Non-secure interrupt access control */ +#define XPS_L2CC_AUX_NSLE_MASK 0x04000000U /* Non-secure lockdown enable */ +#define XPS_L2CC_AUX_CRP_MASK 0x02000000U /* Cache replacement policy */ +#define XPS_L2CC_AUX_FWE_MASK 0x01800000U /* Force write allocate */ +#define XPS_L2CC_AUX_SAOE_MASK 0x00400000U /* Shared attribute override enable */ +#define XPS_L2CC_AUX_PE_MASK 0x00200000U /* Parity enable */ +#define XPS_L2CC_AUX_EMBE_MASK 0x00100000U /* Event monitor bus enable */ +#define XPS_L2CC_AUX_WAY_SIZE_MASK 0x000E0000U /* Way-size */ +#define XPS_L2CC_AUX_ASSOC_MASK 0x00010000U /* Associativity */ +#define XPS_L2CC_AUX_SAIE_MASK 0x00002000U /* Shared attribute invalidate enable */ +#define XPS_L2CC_AUX_EXCL_CACHE_MASK 0x00001000U /* Exclusive cache configuration */ +#define XPS_L2CC_AUX_SBDLE_MASK 0x00000800U /* Store buffer device limitation Enable */ +#define XPS_L2CC_AUX_HPSODRE_MASK 0x00000400U /* High Priority for SO and Dev Reads Enable */ +#define XPS_L2CC_AUX_FLZE_MASK 0x00000001U /* Full line of zero enable */ + +#define XPS_L2CC_AUX_REG_DEFAULT_MASK 0x72360000U /* Enable all prefetching, */ + /* Cache replacement policy, Parity enable, */ + /* Event monitor bus enable and Way Size (64 KB) */ +#define XPS_L2CC_AUX_REG_ZERO_MASK 0xFFF1FFFFU /* */ + +#define XPS_L2CC_TAG_RAM_DEFAULT_MASK 0x00000111U /* latency for TAG RAM */ +#define XPS_L2CC_DATA_RAM_DEFAULT_MASK 0x00000121U /* latency for DATA RAM */ + +/* Interrupt bit masks */ +#define XPS_L2CC_IXR_DECERR_MASK 0x00000100U /* DECERR from L3 */ +#define XPS_L2CC_IXR_SLVERR_MASK 0x00000080U /* SLVERR from L3 */ +#define XPS_L2CC_IXR_ERRRD_MASK 0x00000040U /* Error on L2 data RAM (Read) */ +#define XPS_L2CC_IXR_ERRRT_MASK 0x00000020U /* Error on L2 tag RAM (Read) */ +#define XPS_L2CC_IXR_ERRWD_MASK 0x00000010U /* Error on L2 data RAM (Write) */ +#define XPS_L2CC_IXR_ERRWT_MASK 0x00000008U /* Error on L2 tag RAM (Write) */ +#define XPS_L2CC_IXR_PARRD_MASK 0x00000004U /* Parity Error on L2 data RAM (Read) */ +#define XPS_L2CC_IXR_PARRT_MASK 0x00000002U /* Parity Error on L2 tag RAM (Read) */ +#define XPS_L2CC_IXR_ECNTR_MASK 0x00000001U /* Event Counter1/0 Overflow Increment */ + +/* Address filtering mask and enable bit */ +#define XPS_L2CC_ADDR_FILTER_VALID_MASK 0xFFF00000U /* Address filtering valid bits*/ +#define XPS_L2CC_ADDR_FILTER_ENABLE_MASK 0x00000001U /* Address filtering enable bit*/ + +/* Debug control bits */ +#define XPS_L2CC_DEBUG_SPIDEN_MASK 0x00000004U /* Debug SPIDEN bit */ +#define XPS_L2CC_DEBUG_DWB_MASK 0x00000002U /* Debug DWB bit, forces write through */ +#define XPS_L2CC_DEBUG_DCL_MASK 0x00000002U /* Debug DCL bit, disables cache line fill */ + +#ifdef __cplusplus +} +#endif + +#endif /* protection macro */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xl2cc_counter.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xl2cc_counter.c new file mode 100644 index 0000000..465be05 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xl2cc_counter.c @@ -0,0 +1,165 @@ +/****************************************************************************** +* +* Copyright (C) 2011 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xl2cc_counter.c +* +* This file contains APIs for configuring and controlling the event counters +* in PL310 L2 cache controller. For more information about the event counters, +* see xl2cc_counter.h. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a sdm  07/11/11 First release
+* 3.07a asa  08/30/12 Updated for CR 675636 to provide the L2 Base Address
+*		      inside the APIs
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include +#include "xparameters_ps.h" +#include "xl2cc_counter.h" +#include "xl2cc.h" + +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Variable Definitions *****************************/ + +/************************** Function Prototypes ******************************/ + +void XL2cc_EventCtrReset(void); + +/******************************************************************************/ + +/****************************************************************************/ +/** +* +* @brief This function initializes the event counters in L2 Cache controller +* with a set of event codes specified by the user. +* +* @param Event0: Event code for counter 0. +* @param Event1: Event code for counter 1. +* +* @return None. +* +* @note The definitions for event codes XL2CC_* can be found in +* xl2cc_counter.h. +* +*****************************************************************************/ +void XL2cc_EventCtrInit(s32 Event0, s32 Event1) +{ + + /* Write event code into cnt1 cfg reg */ + *((volatile u32*)(XPS_L2CC_BASEADDR + XPS_L2CC_EVNT_CNT1_CTRL_OFFSET)) = (((u32)Event1) << 2); + + /* Write event code into cnt0 cfg reg */ + *((volatile u32*)(XPS_L2CC_BASEADDR + XPS_L2CC_EVNT_CNT0_CTRL_OFFSET)) = (((u32)Event0) << 2); + + /* Reset counters */ + XL2cc_EventCtrReset(); +} + + +/****************************************************************************/ +/** +* +* @brief This function starts the event counters in L2 Cache controller. +* +* @param None. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XL2cc_EventCtrStart(void) +{ + u32 *LocalPtr; + LocalPtr = (u32 *)(XPS_L2CC_BASEADDR + XPS_L2CC_EVNT_CNTRL_OFFSET); + XL2cc_EventCtrReset(); + + /* Enable counter */ + /* *((volatile u32*)((void *)(XPS_L2CC_BASEADDR + XPS_L2CC_EVNT_CNTRL_OFFSET))) = 1 */ + *LocalPtr = (u32)1; +} + +/****************************************************************************/ +/** +* +* @brief This function disables the event counters in L2 Cache controller, +* saves the counter values and resets the counters. +* +* @param EveCtr0: Output parameter which is used to return the value +* in event counter 0. +* EveCtr1: Output parameter which is used to return the value +* in event counter 1. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XL2cc_EventCtrStop(u32 *EveCtr0, u32 *EveCtr1) +{ + /* Disable counter */ + *((volatile u32*) (XPS_L2CC_BASEADDR + XPS_L2CC_EVNT_CNTRL_OFFSET)) = 0U; + + /* Save counter values */ + *EveCtr1 = *((volatile u32*)(XPS_L2CC_BASEADDR + XPS_L2CC_EVNT_CNT1_VAL_OFFSET)); + *EveCtr0 = *((volatile u32*)(XPS_L2CC_BASEADDR + XPS_L2CC_EVNT_CNT0_VAL_OFFSET)); + + XL2cc_EventCtrReset(); +} + +/****************************************************************************/ +/** +* +* @brief This function resets the event counters in L2 Cache controller. +* +* @param None. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XL2cc_EventCtrReset(void) +{ + *((volatile u32*)(XPS_L2CC_BASEADDR + XPS_L2CC_EVNT_CNTRL_OFFSET)) = 0x6U; +} diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xl2cc_counter.h b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xl2cc_counter.h new file mode 100644 index 0000000..b8d768f --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xl2cc_counter.h @@ -0,0 +1,110 @@ +/****************************************************************************** +* +* Copyright (C) 2011 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xl2cc_counter.h +* +* @addtogroup l2_event_counter_apis PL310 L2 Event Counters Functions +* +* xl2cc_counter.h contains APIs for configuring and controlling the event +* counters in PL310 L2 cache controller. +* PL310 has two event counters which can be used to count variety of events +* like DRHIT, DRREQ, DWHIT, DWREQ, etc. xl2cc_counter.h contains definitions +* for different configurations which can be used for the event counters to +* count a set of events. +* +* +* @{ +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a sdm  07/11/11 First release
+* 3.07a asa  08/30/12 Updated for CR 675636 to provide the L2 Base Address
+*		      inside the APIs
+* 6.8   aru  09/06/18 Removed compilation warnings for ARMCC toolchain.
+* 
+* +******************************************************************************/ + +#ifndef L2CCCOUNTER_H /* prevent circular inclusions */ +#define L2CCCOUNTER_H /* by using protection macros */ + +/***************************** Include Files ********************************/ + +#include "xpseudo_asm.h" +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/************************** Constant Definitions ****************************/ + +/* + * The following constants define the event codes for the event counters. + */ +#define XL2CC_CO 0x1 +#define XL2CC_DRHIT 0x2 +#define XL2CC_DRREQ 0x3 +#define XL2CC_DWHIT 0x4 +#define XL2CC_DWREQ 0x5 +#define XL2CC_DWTREQ 0x6 +#define XL2CC_IRHIT 0x7 +#define XL2CC_IRREQ 0x8 +#define XL2CC_WA 0x9 +#define XL2CC_IPFALLOC 0xa +#define XL2CC_EPFHIT 0xb +#define XL2CC_EPFALLOC 0xc +#define XL2CC_SRRCVD 0xd +#define XL2CC_SRCONF 0xe +#define XL2CC_EPFRCVD 0xf + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Variable Definitions ****************************/ + +/************************** Function Prototypes *****************************/ + +void XL2cc_EventCtrInit(s32 Event0, s32 Event1); +void XL2cc_EventCtrStart(void); +void XL2cc_EventCtrStop(u32 *EveCtr0, u32 *EveCtr1); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* L2CCCOUNTER_H */ +/** +* @} End of "addtogroup l2_event_counter_apis". +*/ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xparameters_ps.h b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xparameters_ps.h new file mode 100644 index 0000000..2a6a0e0 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xparameters_ps.h @@ -0,0 +1,334 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2017 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file xparameters_ps.h +* +* This file contains the address definitions for the hard peripherals +* attached to the ARM Cortex A9 core. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who     Date     Changes
+* ----- ------- -------- ---------------------------------------------------
+* 1.00a ecm/sdm 02/01/10 Initial version
+* 3.04a sdm     02/02/12 Removed some of the defines as they are being generated through
+*                        driver tcl
+* 5.0	pkp		01/16/15 Added interrupt ID definition of ttc for TEST APP
+* 6.6   srm     10/18/17 Added ARMA9 macro to identify CortexA9
+*
+* 
+* +* @note +* +* None. +* +******************************************************************************/ + +#ifndef _XPARAMETERS_PS_H_ +#define _XPARAMETERS_PS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/**************************** Include Files *******************************/ + + +/************************** Constant Definitions *****************************/ + +/* + * This block contains constant declarations for the peripherals + * within the hardblock + */ + +/* Canonical definitions for DDR MEMORY */ +#define XPAR_DDR_MEM_BASEADDR 0x00000000U +#define XPAR_DDR_MEM_HIGHADDR 0x3FFFFFFFU + +/* Canonical definitions for Interrupts */ +#define XPAR_XUARTPS_0_INTR XPS_UART0_INT_ID +#define XPAR_XUARTPS_1_INTR XPS_UART1_INT_ID +#define XPAR_XUSBPS_0_INTR XPS_USB0_INT_ID +#define XPAR_XUSBPS_1_INTR XPS_USB1_INT_ID +#define XPAR_XIICPS_0_INTR XPS_I2C0_INT_ID +#define XPAR_XIICPS_1_INTR XPS_I2C1_INT_ID +#define XPAR_XSPIPS_0_INTR XPS_SPI0_INT_ID +#define XPAR_XSPIPS_1_INTR XPS_SPI1_INT_ID +#define XPAR_XCANPS_0_INTR XPS_CAN0_INT_ID +#define XPAR_XCANPS_1_INTR XPS_CAN1_INT_ID +#define XPAR_XGPIOPS_0_INTR XPS_GPIO_INT_ID +#define XPAR_XEMACPS_0_INTR XPS_GEM0_INT_ID +#define XPAR_XEMACPS_0_WAKE_INTR XPS_GEM0_WAKE_INT_ID +#define XPAR_XEMACPS_1_INTR XPS_GEM1_INT_ID +#define XPAR_XEMACPS_1_WAKE_INTR XPS_GEM1_WAKE_INT_ID +#define XPAR_XSDIOPS_0_INTR XPS_SDIO0_INT_ID +#define XPAR_XQSPIPS_0_INTR XPS_QSPI_INT_ID +#define XPAR_XSDIOPS_1_INTR XPS_SDIO1_INT_ID +#define XPAR_XWDTPS_0_INTR XPS_WDT_INT_ID +#define XPAR_XDCFG_0_INTR XPS_DVC_INT_ID +#define XPAR_SCUTIMER_INTR XPS_SCU_TMR_INT_ID +#define XPAR_SCUWDT_INTR XPS_SCU_WDT_INT_ID +#define XPAR_XTTCPS_0_INTR XPS_TTC0_0_INT_ID +#define XPAR_XTTCPS_1_INTR XPS_TTC0_1_INT_ID +#define XPAR_XTTCPS_2_INTR XPS_TTC0_2_INT_ID +#define XPAR_XTTCPS_3_INTR XPS_TTC1_0_INT_ID +#define XPAR_XTTCPS_4_INTR XPS_TTC1_1_INT_ID +#define XPAR_XTTCPS_5_INTR XPS_TTC1_2_INT_ID +#define XPAR_XDMAPS_0_FAULT_INTR XPS_DMA0_ABORT_INT_ID +#define XPAR_XDMAPS_0_DONE_INTR_0 XPS_DMA0_INT_ID +#define XPAR_XDMAPS_0_DONE_INTR_1 XPS_DMA1_INT_ID +#define XPAR_XDMAPS_0_DONE_INTR_2 XPS_DMA2_INT_ID +#define XPAR_XDMAPS_0_DONE_INTR_3 XPS_DMA3_INT_ID +#define XPAR_XDMAPS_0_DONE_INTR_4 XPS_DMA4_INT_ID +#define XPAR_XDMAPS_0_DONE_INTR_5 XPS_DMA5_INT_ID +#define XPAR_XDMAPS_0_DONE_INTR_6 XPS_DMA6_INT_ID +#define XPAR_XDMAPS_0_DONE_INTR_7 XPS_DMA7_INT_ID + + +#define XPAR_XQSPIPS_0_LINEAR_BASEADDR XPS_QSPI_LINEAR_BASEADDR +#define XPAR_XPARPORTPS_CTRL_BASEADDR XPS_PARPORT_CRTL_BASEADDR + + + +/* Canonical definitions for DMAC */ + + +/* Canonical definitions for WDT */ + +/* Canonical definitions for SLCR */ +#define XPAR_XSLCR_NUM_INSTANCES 1U +#define XPAR_XSLCR_0_DEVICE_ID 0U +#define XPAR_XSLCR_0_BASEADDR XPS_SYS_CTRL_BASEADDR + +/* Canonical definitions for SCU GIC */ +#define XPAR_SCUGIC_NUM_INSTANCES 1U +#define XPAR_SCUGIC_SINGLE_DEVICE_ID 0U +#define XPAR_SCUGIC_CPU_BASEADDR (XPS_SCU_PERIPH_BASE + 0x00000100U) +#define XPAR_SCUGIC_DIST_BASEADDR (XPS_SCU_PERIPH_BASE + 0x00001000U) +#define XPAR_SCUGIC_ACK_BEFORE 0U + +/* Canonical definitions for Global Timer */ +#define XPAR_GLOBAL_TMR_NUM_INSTANCES 1U +#define XPAR_GLOBAL_TMR_DEVICE_ID 0U +#define XPAR_GLOBAL_TMR_BASEADDR (XPS_SCU_PERIPH_BASE + 0x00000200U) +#define XPAR_GLOBAL_TMR_INTR XPS_GLOBAL_TMR_INT_ID + + +/* Xilinx Parallel Flash Library (XilFlash) User Settings */ +#define XPAR_AXI_EMC + + +#define XPAR_CPU_CORTEXA9_CORE_CLOCK_FREQ_HZ XPAR_CPU_CORTEXA9_0_CPU_CLK_FREQ_HZ + + +/* + * This block contains constant declarations for the peripherals + * within the hardblock. These have been put for bacwards compatibilty + */ + +#define XPS_PERIPHERAL_BASEADDR 0xE0000000U +#define XPS_UART0_BASEADDR 0xE0000000U +#define XPS_UART1_BASEADDR 0xE0001000U +#define XPS_USB0_BASEADDR 0xE0002000U +#define XPS_USB1_BASEADDR 0xE0003000U +#define XPS_I2C0_BASEADDR 0xE0004000U +#define XPS_I2C1_BASEADDR 0xE0005000U +#define XPS_SPI0_BASEADDR 0xE0006000U +#define XPS_SPI1_BASEADDR 0xE0007000U +#define XPS_CAN0_BASEADDR 0xE0008000U +#define XPS_CAN1_BASEADDR 0xE0009000U +#define XPS_GPIO_BASEADDR 0xE000A000U +#define XPS_GEM0_BASEADDR 0xE000B000U +#define XPS_GEM1_BASEADDR 0xE000C000U +#define XPS_QSPI_BASEADDR 0xE000D000U +#define XPS_PARPORT_CRTL_BASEADDR 0xE000E000U +#define XPS_SDIO0_BASEADDR 0xE0100000U +#define XPS_SDIO1_BASEADDR 0xE0101000U +#define XPS_IOU_BUS_CFG_BASEADDR 0xE0200000U +#define XPS_NAND_BASEADDR 0xE1000000U +#define XPS_PARPORT0_BASEADDR 0xE2000000U +#define XPS_PARPORT1_BASEADDR 0xE4000000U +#define XPS_QSPI_LINEAR_BASEADDR 0xFC000000U +#define XPS_SYS_CTRL_BASEADDR 0xF8000000U /* AKA SLCR */ +#define XPS_TTC0_BASEADDR 0xF8001000U +#define XPS_TTC1_BASEADDR 0xF8002000U +#define XPS_DMAC0_SEC_BASEADDR 0xF8003000U +#define XPS_DMAC0_NON_SEC_BASEADDR 0xF8004000U +#define XPS_WDT_BASEADDR 0xF8005000U +#define XPS_DDR_CTRL_BASEADDR 0xF8006000U +#define XPS_DEV_CFG_APB_BASEADDR 0xF8007000U +#define XPS_AFI0_BASEADDR 0xF8008000U +#define XPS_AFI1_BASEADDR 0xF8009000U +#define XPS_AFI2_BASEADDR 0xF800A000U +#define XPS_AFI3_BASEADDR 0xF800B000U +#define XPS_OCM_BASEADDR 0xF800C000U +#define XPS_EFUSE_BASEADDR 0xF800D000U +#define XPS_CORESIGHT_BASEADDR 0xF8800000U +#define XPS_TOP_BUS_CFG_BASEADDR 0xF8900000U +#define XPS_SCU_PERIPH_BASE 0xF8F00000U +#define XPS_L2CC_BASEADDR 0xF8F02000U +#define XPS_SAM_RAM_BASEADDR 0xFFFC0000U +#define XPS_FPGA_AXI_S0_BASEADDR 0x40000000U +#define XPS_FPGA_AXI_S1_BASEADDR 0x80000000U +#define XPS_IOU_S_SWITCH_BASEADDR 0xE0000000U +#define XPS_PERIPH_APB_BASEADDR 0xF8000000U + +/* Shared Peripheral Interrupts (SPI) */ +#define XPS_CORE_PARITY0_INT_ID 32U +#define XPS_CORE_PARITY1_INT_ID 33U +#define XPS_L2CC_INT_ID 34U +#define XPS_OCMINTR_INT_ID 35U +#define XPS_ECC_INT_ID 36U +#define XPS_PMU0_INT_ID 37U +#define XPS_PMU1_INT_ID 38U +#define XPS_SYSMON_INT_ID 39U +#define XPS_DVC_INT_ID 40U +#define XPS_WDT_INT_ID 41U +#define XPS_TTC0_0_INT_ID 42U +#define XPS_TTC0_1_INT_ID 43U +#define XPS_TTC0_2_INT_ID 44U +#define XPS_DMA0_ABORT_INT_ID 45U +#define XPS_DMA0_INT_ID 46U +#define XPS_DMA1_INT_ID 47U +#define XPS_DMA2_INT_ID 48U +#define XPS_DMA3_INT_ID 49U +#define XPS_SMC_INT_ID 50U +#define XPS_QSPI_INT_ID 51U +#define XPS_GPIO_INT_ID 52U +#define XPS_USB0_INT_ID 53U +#define XPS_GEM0_INT_ID 54U +#define XPS_GEM0_WAKE_INT_ID 55U +#define XPS_SDIO0_INT_ID 56U +#define XPS_I2C0_INT_ID 57U +#define XPS_SPI0_INT_ID 58U +#define XPS_UART0_INT_ID 59U +#define XPS_CAN0_INT_ID 60U +#define XPS_FPGA0_INT_ID 61U +#define XPS_FPGA1_INT_ID 62U +#define XPS_FPGA2_INT_ID 63U +#define XPS_FPGA3_INT_ID 64U +#define XPS_FPGA4_INT_ID 65U +#define XPS_FPGA5_INT_ID 66U +#define XPS_FPGA6_INT_ID 67U +#define XPS_FPGA7_INT_ID 68U +#define XPS_TTC1_0_INT_ID 69U +#define XPS_TTC1_1_INT_ID 70U +#define XPS_TTC1_2_INT_ID 71U +#define XPS_DMA4_INT_ID 72U +#define XPS_DMA5_INT_ID 73U +#define XPS_DMA6_INT_ID 74U +#define XPS_DMA7_INT_ID 75U +#define XPS_USB1_INT_ID 76U +#define XPS_GEM1_INT_ID 77U +#define XPS_GEM1_WAKE_INT_ID 78U +#define XPS_SDIO1_INT_ID 79U +#define XPS_I2C1_INT_ID 80U +#define XPS_SPI1_INT_ID 81U +#define XPS_UART1_INT_ID 82U +#define XPS_CAN1_INT_ID 83U +#define XPS_FPGA8_INT_ID 84U +#define XPS_FPGA9_INT_ID 85U +#define XPS_FPGA10_INT_ID 86U +#define XPS_FPGA11_INT_ID 87U +#define XPS_FPGA12_INT_ID 88U +#define XPS_FPGA13_INT_ID 89U +#define XPS_FPGA14_INT_ID 90U +#define XPS_FPGA15_INT_ID 91U + +/* Private Peripheral Interrupts (PPI) */ +#define XPS_GLOBAL_TMR_INT_ID 27U /* SCU Global Timer interrupt */ +#define XPS_FIQ_INT_ID 28U /* FIQ from FPGA fabric */ +#define XPS_SCU_TMR_INT_ID 29U /* SCU Private Timer interrupt */ +#define XPS_SCU_WDT_INT_ID 30U /* SCU Private WDT interrupt */ +#define XPS_IRQ_INT_ID 31U /* IRQ from FPGA fabric */ + + +/* REDEFINES for TEST APP */ +/* Definitions for UART */ +#define XPAR_PS7_UART_0_INTR XPS_UART0_INT_ID +#define XPAR_PS7_UART_1_INTR XPS_UART1_INT_ID +#define XPAR_PS7_USB_0_INTR XPS_USB0_INT_ID +#define XPAR_PS7_USB_1_INTR XPS_USB1_INT_ID +#define XPAR_PS7_I2C_0_INTR XPS_I2C0_INT_ID +#define XPAR_PS7_I2C_1_INTR XPS_I2C1_INT_ID +#define XPAR_PS7_SPI_0_INTR XPS_SPI0_INT_ID +#define XPAR_PS7_SPI_1_INTR XPS_SPI1_INT_ID +#define XPAR_PS7_CAN_0_INTR XPS_CAN0_INT_ID +#define XPAR_PS7_CAN_1_INTR XPS_CAN1_INT_ID +#define XPAR_PS7_GPIO_0_INTR XPS_GPIO_INT_ID +#define XPAR_PS7_ETHERNET_0_INTR XPS_GEM0_INT_ID +#define XPAR_PS7_ETHERNET_0_WAKE_INTR XPS_GEM0_WAKE_INT_ID +#define XPAR_PS7_ETHERNET_1_INTR XPS_GEM1_INT_ID +#define XPAR_PS7_ETHERNET_1_WAKE_INTR XPS_GEM1_WAKE_INT_ID +#define XPAR_PS7_QSPI_0_INTR XPS_QSPI_INT_ID +#define XPAR_PS7_WDT_0_INTR XPS_WDT_INT_ID +#define XPAR_PS7_SCUWDT_0_INTR XPS_SCU_WDT_INT_ID +#define XPAR_PS7_SCUTIMER_0_INTR XPS_SCU_TMR_INT_ID +#define XPAR_PS7_XADC_0_INTR XPS_SYSMON_INT_ID +#define XPAR_PS7_TTC_0_INTR XPS_TTC0_0_INT_ID +#define XPAR_PS7_TTC_1_INTR XPS_TTC0_1_INT_ID +#define XPAR_PS7_TTC_2_INTR XPS_TTC0_2_INT_ID +#define XPAR_PS7_TTC_3_INTR XPS_TTC1_0_INT_ID +#define XPAR_PS7_TTC_4_INTR XPS_TTC1_1_INT_ID +#define XPAR_PS7_TTC_5_INTR XPS_TTC1_2_INT_ID + +#define XPAR_XADCPS_INT_ID XPS_SYSMON_INT_ID + +/* For backwards compatibilty */ +#define XPAR_XUARTPS_0_CLOCK_HZ XPAR_XUARTPS_0_UART_CLK_FREQ_HZ +#define XPAR_XUARTPS_1_CLOCK_HZ XPAR_XUARTPS_1_UART_CLK_FREQ_HZ +#define XPAR_XTTCPS_0_CLOCK_HZ XPAR_XTTCPS_0_TTC_CLK_FREQ_HZ +#define XPAR_XTTCPS_1_CLOCK_HZ XPAR_XTTCPS_1_TTC_CLK_FREQ_HZ +#define XPAR_XTTCPS_2_CLOCK_HZ XPAR_XTTCPS_2_TTC_CLK_FREQ_HZ +#define XPAR_XTTCPS_3_CLOCK_HZ XPAR_XTTCPS_3_TTC_CLK_FREQ_HZ +#define XPAR_XTTCPS_4_CLOCK_HZ XPAR_XTTCPS_4_TTC_CLK_FREQ_HZ +#define XPAR_XTTCPS_5_CLOCK_HZ XPAR_XTTCPS_5_TTC_CLK_FREQ_HZ +#define XPAR_XIICPS_0_CLOCK_HZ XPAR_XIICPS_0_I2C_CLK_FREQ_HZ +#define XPAR_XIICPS_1_CLOCK_HZ XPAR_XIICPS_1_I2C_CLK_FREQ_HZ + +#define XPAR_XQSPIPS_0_CLOCK_HZ XPAR_XQSPIPS_0_QSPI_CLK_FREQ_HZ + +#ifdef XPAR_CPU_CORTEXA9_0_CPU_CLK_FREQ_HZ +#define XPAR_CPU_CORTEXA9_CORE_CLOCK_FREQ_HZ XPAR_CPU_CORTEXA9_0_CPU_CLK_FREQ_HZ +#endif + +#ifdef XPAR_CPU_CORTEXA9_1_CPU_CLK_FREQ_HZ +#define XPAR_CPU_CORTEXA9_CORE_CLOCK_FREQ_HZ XPAR_CPU_CORTEXA9_1_CPU_CLK_FREQ_HZ +#endif + +#define XPAR_SCUTIMER_DEVICE_ID 0U +#define XPAR_SCUWDT_DEVICE_ID 0U + + +#ifdef __cplusplus +} +#endif + +#endif /* protection macro */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xplatform_info.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xplatform_info.c new file mode 100644 index 0000000..03b1742 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xplatform_info.c @@ -0,0 +1,162 @@ +/****************************************************************************** +* +* Copyright (C) 2014 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xplatform_info.c +* +* This file contains information about hardware for which the code is built +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date   Changes
+* ----- ---- -------- -------------------------------------------------------
+* 5.00  pkp  12/15/14 Initial release
+* 5.04  pkp  01/12/16 Added platform information support for Cortex-A53 32bit
+*					  mode
+* 6.00  mus  17/08/16 Removed unused variable from XGetPlatform_Info
+* 6.4   ms   05/23/17 Added PSU_PMU macro to support XGetPSVersion_Info
+*                     function for PMUFW.
+*       ms   06/13/17 Added PSU_PMU macro to provide support of
+*                     XGetPlatform_Info function for PMUFW.
+*       mus  08/17/17 Add EL1 NS mode support for
+*                     XGet_Zynq_UltraMp_Platform_info and XGetPSVersion_Info
+*                     APIs.
+* 7.0	aru 03/15/19  Check for versal before aarch64 and armr5
+*		      in XGetPlatform_Info()
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_io.h" +#include "xplatform_info.h" +#if defined (__aarch64__) +#include "bspconfig.h" +#include "xil_smc.h" +#endif +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Variable Definitions *****************************/ + + +/************************** Function Prototypes ******************************/ + +/*****************************************************************************/ +/** +* +* @brief This API is used to provide information about platform +* +* @param None. +* +* @return The information about platform defined in xplatform_info.h +* +******************************************************************************/ +u32 XGetPlatform_Info() +{ +#if defined (versal) + return XPLAT_versal; +#elif defined (ARMR5) || (__aarch64__) || (ARMA53_32) || (PSU_PMU) + return XPLAT_ZYNQ_ULTRA_MP; +#elif (__microblaze__) + return XPLAT_MICROBLAZE; +#else + return XPLAT_ZYNQ; +#endif +} + +/*****************************************************************************/ +/** +* +* @brief This API is used to provide information about zynq ultrascale MP platform +* +* @param None. +* +* @return The information about zynq ultrascale MP platform defined in +* xplatform_info.h +* +******************************************************************************/ +#if defined (ARMR5) || (__aarch64__) || (ARMA53_32) +u32 XGet_Zynq_UltraMp_Platform_info() +{ +#if EL1_NONSECURE + XSmc_OutVar reg; + /* + * This SMC call will return, + * idcode - upper 32 bits of reg.Arg0 + * version - lower 32 bits of reg.Arg1 + */ + reg = Xil_Smc(GET_CHIPID_SMC_FID,0,0, 0, 0, 0, 0, 0); + return (u32)((reg.Arg1 >> XPLAT_INFO_SHIFT) & XPLAT_INFO_MASK); +#else + u32 reg; + reg = ((Xil_In32(XPLAT_PS_VERSION_ADDRESS) >> XPLAT_INFO_SHIFT ) + & XPLAT_INFO_MASK); + return reg; +#endif +} +#endif + +/*****************************************************************************/ +/** +* +* @brief This API is used to provide information about PS Silicon version +* +* @param None. +* +* @return The information about PS Silicon version. +* +******************************************************************************/ +#if defined (ARMR5) || (__aarch64__) || (ARMA53_32) || (PSU_PMU) +u32 XGetPSVersion_Info() +{ +#if EL1_NONSECURE + /* + * This SMC call will return, + * idcode - upper 32 bits of reg.Arg0 + * version - lower 32 bits of reg.Arg1 + */ + XSmc_OutVar reg; + reg = Xil_Smc(GET_CHIPID_SMC_FID,0,0, 0, 0, 0, 0, 0); + return (u32)((reg.Arg1 & XPS_VERSION_INFO_MASK) >> + XPS_VERSION_INFO_SHIFT); +#else + u32 reg; + reg = (Xil_In32(XPLAT_PS_VERSION_ADDRESS) + & XPS_VERSION_INFO_MASK); + return (reg >> XPS_VERSION_INFO_SHIFT); +#endif +} +#endif diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xplatform_info.h b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xplatform_info.h new file mode 100644 index 0000000..88851bb --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xplatform_info.h @@ -0,0 +1,120 @@ +/****************************************************************************** +* +* Copyright (C) 2014 - 2017 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xplatform_info.h +* +* @addtogroup common_platform_info APIs to Get Platform Information +* +* The xplatform_info.h file contains definitions for various available Xilinx® +* platforms. Also, it contains prototype of APIs, which can be used to get the +* platform information. +* +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date    Changes
+* ----- ---- --------- -------------------------------------------------------
+* 6.4    ms   05/23/17 Added PSU_PMU macro to support XGetPSVersion_Info
+*                      function for PMUFW.
+* 
+* +******************************************************************************/ + +#ifndef XPLATFORM_INFO_H /* prevent circular inclusions */ +#define XPLATFORM_INFO_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" + +/************************** Constant Definitions *****************************/ +#if defined (versal) +#define XPAR_PMC_TAP_BASEADDR 0xF11A0000U +#define XPAR_PMC_TAP_VERSION_OFFSET 0x00000004U +#define XPLAT_PS_VERSION_ADDRESS (XPAR_PMC_TAP_BASEADDR + \ + XPAR_PMC_TAP_VERSION_OFFSET) +#else +#define XPAR_CSU_BASEADDR 0xFFCA0000U +#define XPAR_CSU_VER_OFFSET 0x00000044U +#define XPLAT_PS_VERSION_ADDRESS (XPAR_CSU_BASEADDR + \ + XPAR_CSU_VER_OFFSET) +#endif +#define XPLAT_ZYNQ_ULTRA_MP_SILICON 0x0 +#define XPLAT_ZYNQ_ULTRA_MP 0x1 +#define XPLAT_ZYNQ_ULTRA_MPVEL 0x2 +#define XPLAT_ZYNQ_ULTRA_MPQEMU 0x3 +#define XPLAT_ZYNQ 0x4 +#define XPLAT_MICROBLAZE 0x5 +#define XPLAT_versal 0x6U + +#define XPS_VERSION_1 0x0 +#define XPS_VERSION_2 0x1 +#define XPLAT_INFO_MASK (0xF) + +#if defined (versal) +#define XPS_VERSION_INFO_MASK 0xFF00U +#define XPS_VERSION_INFO_SHIFT 0x8U +#define XPLAT_INFO_SHIFT 0x18U +#else +#define XPS_VERSION_INFO_MASK (0xF) +#define XPS_VERSION_INFO_SHIFT 0x0U +#define XPLAT_INFO_SHIFT 0xCU +#endif + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + + +u32 XGetPlatform_Info(void); + +#if defined (ARMR5) || (__aarch64__) || (ARMA53_32) || (PSU_PMU) +u32 XGetPSVersion_Info(); +#endif + +#if defined (ARMR5) || (__aarch64__) || (ARMA53_32) +u32 XGet_Zynq_UltraMp_Platform_info(); +#endif +/************************** Function Prototypes ******************************/ + + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** +* @} End of "addtogroup common_platform_info". +*/ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xpm_counter.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xpm_counter.c new file mode 100644 index 0000000..482671e --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xpm_counter.c @@ -0,0 +1,293 @@ +/****************************************************************************** +* +* Copyright (C) 2011 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xpm_counter.c +* +* This file contains APIs for configuring and controlling the Cortex-A9 +* Performance Monitor Events. For more information about the event counters, +* see xpm_counter.h. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a sdm  07/11/11 First release
+* 4.2	pkp	 07/21/14 Corrected reset value of event counter in function
+*					  Xpm_ResetEventCounters to fix CR#796275
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xpm_counter.h" + +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + +typedef const u32 PmcrEventCfg32[XPM_CTRCOUNT]; + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Variable Definitions *****************************/ + +/************************** Function Prototypes ******************************/ + +void Xpm_DisableEventCounters(void); +void Xpm_EnableEventCounters (void); +void Xpm_ResetEventCounters (void); + +/******************************************************************************/ + +/****************************************************************************/ +/** +* +* @brief This function disables the Cortex A9 event counters. +* +* @param None. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void Xpm_DisableEventCounters(void) +{ + /* Disable the event counters */ + mtcp(XREG_CP15_COUNT_ENABLE_CLR, 0x3f); +} + +/****************************************************************************/ +/** +* +* @brief This function enables the Cortex A9 event counters. +* +* @param None. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void Xpm_EnableEventCounters(void) +{ + /* Enable the event counters */ + mtcp(XREG_CP15_COUNT_ENABLE_SET, 0x3f); +} + +/****************************************************************************/ +/** +* +* @brief This function resets the Cortex A9 event counters. +* +* @param None. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void Xpm_ResetEventCounters(void) +{ + u32 Reg; +#ifdef __GNUC__ + Reg = mfcp(XREG_CP15_PERF_MONITOR_CTRL); +#elif defined (__ICCARM__) + mfcp(XREG_CP15_PERF_MONITOR_CTRL, Reg); +#else + { register u32 C15Reg __asm(XREG_CP15_PERF_MONITOR_CTRL); + Reg = C15Reg; } +#endif + Reg |= (1U << 1U); /* reset event counters */ + mtcp(XREG_CP15_PERF_MONITOR_CTRL, Reg); + +} + +/****************************************************************************/ +/** +* @brief This function configures the Cortex A9 event counters controller, +* with the event codes, in a configuration selected by the user and +* enables the counters. +* +* @param PmcrCfg: Configuration value based on which the event counters +* are configured. XPM_CNTRCFG* values defined in xpm_counter.h can +* be utilized for setting configuration. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void Xpm_SetEvents(s32 PmcrCfg) +{ + u32 Counter; + static PmcrEventCfg32 PmcrEvents[] = { + { + XPM_EVENT_SOFTINCR, + XPM_EVENT_INSRFETCH_CACHEREFILL, + XPM_EVENT_INSTRFECT_TLBREFILL, + XPM_EVENT_DATA_CACHEREFILL, + XPM_EVENT_DATA_CACHEACCESS, + XPM_EVENT_DATA_TLBREFILL + }, + { + XPM_EVENT_DATA_READS, + XPM_EVENT_DATA_WRITE, + XPM_EVENT_EXCEPTION, + XPM_EVENT_EXCEPRETURN, + XPM_EVENT_CHANGECONTEXT, + XPM_EVENT_SW_CHANGEPC + }, + { + XPM_EVENT_IMMEDBRANCH, + XPM_EVENT_UNALIGNEDACCESS, + XPM_EVENT_BRANCHMISS, + XPM_EVENT_CLOCKCYCLES, + XPM_EVENT_BRANCHPREDICT, + XPM_EVENT_JAVABYTECODE + }, + { + XPM_EVENT_SWJAVABYTECODE, + XPM_EVENT_JAVABACKBRANCH, + XPM_EVENT_COHERLINEMISS, + XPM_EVENT_COHERLINEHIT, + XPM_EVENT_INSTRSTALL, + XPM_EVENT_DATASTALL + }, + { + XPM_EVENT_MAINTLBSTALL, + XPM_EVENT_STREXPASS, + XPM_EVENT_STREXFAIL, + XPM_EVENT_DATAEVICT, + XPM_EVENT_NODISPATCH, + XPM_EVENT_ISSUEEMPTY + }, + { + XPM_EVENT_INSTRRENAME, + XPM_EVENT_PREDICTFUNCRET, + XPM_EVENT_MAINEXEC, + XPM_EVENT_SECEXEC, + XPM_EVENT_LDRSTR, + XPM_EVENT_FLOATRENAME + }, + { + XPM_EVENT_NEONRENAME, + XPM_EVENT_PLDSTALL, + XPM_EVENT_WRITESTALL, + XPM_EVENT_INSTRTLBSTALL, + XPM_EVENT_DATATLBSTALL, + XPM_EVENT_INSTR_uTLBSTALL + }, + { + XPM_EVENT_DATA_uTLBSTALL, + XPM_EVENT_DMB_STALL, + XPM_EVENT_INT_CLKEN, + XPM_EVENT_DE_CLKEN, + XPM_EVENT_INSTRISB, + XPM_EVENT_INSTRDSB + }, + { + XPM_EVENT_INSTRDMB, + XPM_EVENT_EXTINT, + XPM_EVENT_PLE_LRC, + XPM_EVENT_PLE_LRS, + XPM_EVENT_PLE_FLUSH, + XPM_EVENT_PLE_CMPL + }, + { + XPM_EVENT_PLE_OVFL, + XPM_EVENT_PLE_PROG, + XPM_EVENT_PLE_LRC, + XPM_EVENT_PLE_LRS, + XPM_EVENT_PLE_FLUSH, + XPM_EVENT_PLE_CMPL + }, + { + XPM_EVENT_DATASTALL, + XPM_EVENT_INSRFETCH_CACHEREFILL, + XPM_EVENT_INSTRFECT_TLBREFILL, + XPM_EVENT_DATA_CACHEREFILL, + XPM_EVENT_DATA_CACHEACCESS, + XPM_EVENT_DATA_TLBREFILL + }, + }; + const u32 *ptr = PmcrEvents[PmcrCfg]; + + Xpm_DisableEventCounters(); + + for(Counter = 0U; Counter < XPM_CTRCOUNT; Counter++) { + + /* Selecet event counter */ + mtcp(XREG_CP15_EVENT_CNTR_SEL, Counter); + + /* Set the event */ + mtcp(XREG_CP15_EVENT_TYPE_SEL, ptr[Counter]); + } + + Xpm_ResetEventCounters(); + Xpm_EnableEventCounters(); +} + +/****************************************************************************/ +/** +* +* @brief This function disables the event counters and returns the counter +* values. +* +* @param PmCtrValue: Pointer to an array of type u32 PmCtrValue[6]. +* It is an output parameter which is used to return the PM +* counter values. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void Xpm_GetEventCounters(u32 *PmCtrValue) +{ + u32 Counter; + + Xpm_DisableEventCounters(); + + for(Counter = 0U; Counter < XPM_CTRCOUNT; Counter++) { + + mtcp(XREG_CP15_EVENT_CNTR_SEL, Counter); +#ifdef __GNUC__ + PmCtrValue[Counter] = mfcp(XREG_CP15_PERF_MONITOR_COUNT); +#elif defined (__ICCARM__) + mfcp(XREG_CP15_PERF_MONITOR_COUNT, PmCtrValue[Counter]); +#else + { register u32 Cp15Reg __asm(XREG_CP15_PERF_MONITOR_COUNT); + PmCtrValue[Counter] = Cp15Reg; } +#endif + } +} diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xpm_counter.h b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xpm_counter.h new file mode 100644 index 0000000..39db7d8 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xpm_counter.h @@ -0,0 +1,572 @@ +/****************************************************************************** +* +* Copyright (C) 2011 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xpm_counter.h +* +* @addtogroup a9_event_counter_apis Cortex A9 Event Counters Functions +* +* Cortex A9 event counter functions can be utilized to configure and control +* the Cortex-A9 performance monitor events. +* +* Cortex-A9 performance monitor has six event counters which can be used to +* count a variety of events described in Coretx-A9 TRM. xpm_counter.h defines +* configurations XPM_CNTRCFGx which can be used to program the event counters +* to count a set of events. +* +* @note +* It doesn't handle the Cortex-A9 cycle counter, as the cycle counter is +* being used for time keeping. +* +* @{ +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a sdm  07/11/11 First release
+* 6.8   aru  09/06/18 Removed compilation warnings for ARMCC toolchain.
+* 
+* +******************************************************************************/ + +#ifndef XPMCOUNTER_H /* prevent circular inclusions */ +#define XPMCOUNTER_H /* by using protection macros */ + +/***************************** Include Files ********************************/ + +#include +#include "xpseudo_asm.h" +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/************************** Constant Definitions ****************************/ + +/* Number of performance counters */ +#define XPM_CTRCOUNT 6U + +/* The following constants define the Cortex-A9 Performance Monitor Events */ + +/* + * Software increment. The register is incremented only on writes to the + * Software Increment Register + */ +#define XPM_EVENT_SOFTINCR 0x00U + +/* + * Instruction fetch that causes a refill at (at least) the lowest level(s) of + * instruction or unified cache. Includes the speculative linefills in the + * count + */ +#define XPM_EVENT_INSRFETCH_CACHEREFILL 0x01U + +/* + * Instruction fetch that causes a TLB refill at (at least) the lowest level of + * TLB. Includes the speculative requests in the count + */ +#define XPM_EVENT_INSTRFECT_TLBREFILL 0x02U + +/* + * Data read or write operation that causes a refill at (at least) the lowest + * level(s)of data or unified cache. Counts the number of allocations performed + * in the Data Cache due to a read or a write + */ +#define XPM_EVENT_DATA_CACHEREFILL 0x03U + +/* + * Data read or write operation that causes a cache access at (at least) the + * lowest level(s) of data or unified cache. This includes speculative reads + */ +#define XPM_EVENT_DATA_CACHEACCESS 0x04U + +/* + * Data read or write operation that causes a TLB refill at (at least) the + * lowest level of TLB. This does not include micro TLB misses due to PLD, PLI, + * CP15 Cache operation by MVA and CP15 VA to PA operations + */ +#define XPM_EVENT_DATA_TLBREFILL 0x05U + +/* + * Data read architecturally executed. Counts the number of data read + * instructions accepted by the Load Store Unit. This includes counting the + * speculative and aborted LDR/LDM, as well as the reads due to the SWP + * instructions + */ +#define XPM_EVENT_DATA_READS 0x06U + +/* + * Data write architecturally executed. Counts the number of data write + * instructions accepted by the Load Store Unit. This includes counting the + * speculative and aborted STR/STM, as well as the writes due to the SWP + * instructions + */ +#define XPM_EVENT_DATA_WRITE 0x07U + +/* Exception taken. Counts the number of exceptions architecturally taken.*/ +#define XPM_EVENT_EXCEPTION 0x09U + +/* Exception return architecturally executed.*/ +#define XPM_EVENT_EXCEPRETURN 0x0AU + +/* + * Change to ContextID retired. Counts the number of instructions + * architecturally executed writing into the ContextID Register + */ +#define XPM_EVENT_CHANGECONTEXT 0x0BU + +/* + * Software change of PC, except by an exception, architecturally executed. + * Count the number of PC changes architecturally executed, excluding the PC + * changes due to taken exceptions + */ +#define XPM_EVENT_SW_CHANGEPC 0x0CU + +/* + * Immediate branch architecturally executed (taken or not taken). This includes + * the branches which are flushed due to a previous load/store which aborts + * late + */ +#define XPM_EVENT_IMMEDBRANCH 0x0DU + +/* + * Unaligned access architecturally executed. Counts the number of aborted + * unaligned accessed architecturally executed, and the number of not-aborted + * unaligned accesses, including the speculative ones + */ +#define XPM_EVENT_UNALIGNEDACCESS 0x0FU + +/* + * Branch mispredicted/not predicted. Counts the number of mispredicted or + * not-predicted branches executed. This includes the branches which are flushed + * due to a previous load/store which aborts late + */ +#define XPM_EVENT_BRANCHMISS 0x10U + +/* + * Counts clock cycles when the Cortex-A9 processor is not in WFE/WFI. This + * event is not exported on the PMUEVENT bus + */ +#define XPM_EVENT_CLOCKCYCLES 0x11U + +/* + * Branches or other change in program flow that could have been predicted by + * the branch prediction resources of the processor. This includes the branches + * which are flushed due to a previous load/store which aborts late + */ +#define XPM_EVENT_BRANCHPREDICT 0x12U + +/* + * Java bytecode execute. Counts the number of Java bytecodes being decoded, + * including speculative ones + */ +#define XPM_EVENT_JAVABYTECODE 0x40U + +/* + * Software Java bytecode executed. Counts the number of software java bytecodes + * being decoded, including speculative ones + */ +#define XPM_EVENT_SWJAVABYTECODE 0x41U + +/* + * Jazelle backward branches executed. Counts the number of Jazelle taken + * branches being executed. This includes the branches which are flushed due + * to a previous load/store which aborts late + */ +#define XPM_EVENT_JAVABACKBRANCH 0x42U + +/* + * Coherent linefill miss Counts the number of coherent linefill requests + * performed by the Cortex-A9 processor which also miss in all the other + * Cortex-A9 processors, meaning that the request is sent to the external + * memory + */ +#define XPM_EVENT_COHERLINEMISS 0x50U + +/* + * Coherent linefill hit. Counts the number of coherent linefill requests + * performed by the Cortex-A9 processor which hit in another Cortex-A9 + * processor, meaning that the linefill data is fetched directly from the + * relevant Cortex-A9 cache + */ +#define XPM_EVENT_COHERLINEHIT 0x51U + +/* + * Instruction cache dependent stall cycles. Counts the number of cycles where + * the processor is ready to accept new instructions, but does not receive any + * due to the instruction side not being able to provide any and the + * instruction cache is currently performing at least one linefill + */ +#define XPM_EVENT_INSTRSTALL 0x60U + +/* + * Data cache dependent stall cycles. Counts the number of cycles where the core + * has some instructions that it cannot issue to any pipeline, and the Load + * Store unit has at least one pending linefill request, and no pending + */ +#define XPM_EVENT_DATASTALL 0x61U + +/* + * Main TLB miss stall cycles. Counts the number of cycles where the processor + * is stalled waiting for the completion of translation table walks from the + * main TLB. The processor stalls can be due to the instruction side not being + * able to provide the instructions, or to the data side not being able to + * provide the necessary data, due to them waiting for the main TLB translation + * table walk to complete + */ +#define XPM_EVENT_MAINTLBSTALL 0x62U + +/* + * Counts the number of STREX instructions architecturally executed and + * passed + */ +#define XPM_EVENT_STREXPASS 0x63U + +/* + * Counts the number of STREX instructions architecturally executed and + * failed + */ +#define XPM_EVENT_STREXFAIL 0x64U + +/* + * Data eviction. Counts the number of eviction requests due to a linefill in + * the data cache + */ +#define XPM_EVENT_DATAEVICT 0x65U + +/* + * Counts the number of cycles where the issue stage does not dispatch any + * instruction because it is empty or cannot dispatch any instructions + */ +#define XPM_EVENT_NODISPATCH 0x66U + +/* + * Counts the number of cycles where the issue stage is empty + */ +#define XPM_EVENT_ISSUEEMPTY 0x67U + +/* + * Counts the number of instructions going through the Register Renaming stage. + * This number is an approximate number of the total number of instructions + * speculatively executed, and even more approximate of the total number of + * instructions architecturally executed. The approximation depends mainly on + * the branch misprediction rate. + * The renaming stage can handle two instructions in the same cycle so the event + * is two bits long: + * - b00 no instructions renamed + * - b01 one instruction renamed + * - b10 two instructions renamed + */ +#define XPM_EVENT_INSTRRENAME 0x68U + +/* + * Counts the number of procedure returns whose condition codes do not fail, + * excluding all returns from exception. This count includes procedure returns + * which are flushed due to a previous load/store which aborts late. + * Only the following instructions are reported: + * - BX R14 + * - MOV PC LR + * - POP {..,pc} + * - LDR pc,[sp],#offset + * The following instructions are not reported: + * - LDMIA R9!,{..,PC} (ThumbEE state only) + * - LDR PC,[R9],#offset (ThumbEE state only) + * - BX R0 (Rm != R14) + * - MOV PC,R0 (Rm != R14) + * - LDM SP,{...,PC} (writeback not specified) + * - LDR PC,[SP,#offset] (wrong addressing mode) + */ +#define XPM_EVENT_PREDICTFUNCRET 0x6EU + +/* + * Counts the number of instructions being executed in the main execution + * pipeline of the processor, the multiply pipeline and arithmetic logic unit + * pipeline. The counted instructions are still speculative + */ +#define XPM_EVENT_MAINEXEC 0x70U + +/* + * Counts the number of instructions being executed in the processor second + * execution pipeline (ALU). The counted instructions are still speculative + */ +#define XPM_EVENT_SECEXEC 0x71U + +/* + * Counts the number of instructions being executed in the Load/Store unit. The + * counted instructions are still speculative + */ +#define XPM_EVENT_LDRSTR 0x72U + +/* + * Counts the number of Floating-point instructions going through the Register + * Rename stage. Instructions are still speculative in this stage. + *Two floating-point instructions can be renamed in the same cycle so the event + * is two bitslong: + *0b00 no floating-point instruction renamed + *0b01 one floating-point instruction renamed + *0b10 two floating-point instructions renamed + */ +#define XPM_EVENT_FLOATRENAME 0x73U + +/* + * Counts the number of Neon instructions going through the Register Rename + * stage.Instructions are still speculative in this stage. + * Two NEON instructions can be renamed in the same cycle so the event is two + * bits long: + *0b00 no NEON instruction renamed + *0b01 one NEON instruction renamed + *0b10 two NEON instructions renamed + */ +#define XPM_EVENT_NEONRENAME 0x74U + +/* + * Counts the number of cycles where the processor is stalled because PLD slots + * are all full + */ +#define XPM_EVENT_PLDSTALL 0x80U + +/* + * Counts the number of cycles when the processor is stalled and the data side + * is stalled too because it is full and executing writes to the external + * memory + */ +#define XPM_EVENT_WRITESTALL 0x81U + +/* + * Counts the number of stall cycles due to main TLB misses on requests issued + * by the instruction side + */ +#define XPM_EVENT_INSTRTLBSTALL 0x82U + +/* + * Counts the number of stall cycles due to main TLB misses on requests issued + * by the data side + */ +#define XPM_EVENT_DATATLBSTALL 0x83U + +/* + * Counts the number of stall cycles due to micro TLB misses on the instruction + * side. This event does not include main TLB miss stall cycles that are already + * counted in the corresponding main TLB event + */ +#define XPM_EVENT_INSTR_uTLBSTALL 0x84U + +/* + * Counts the number of stall cycles due to micro TLB misses on the data side. + * This event does not include main TLB miss stall cycles that are already + * counted in the corresponding main TLB event + */ +#define XPM_EVENT_DATA_uTLBSTALL 0x85U + +/* + * Counts the number of stall cycles because of the execution of a DMB memory + * barrier. This includes all DMB instructions being executed, even + * speculatively + */ +#define XPM_EVENT_DMB_STALL 0x86U + +/* + * Counts the number of cycles during which the integer core clock is enabled + */ +#define XPM_EVENT_INT_CLKEN 0x8AU + +/* + * Counts the number of cycles during which the Data Engine clock is enabled + */ +#define XPM_EVENT_DE_CLKEN 0x8BU + +/* + * Counts the number of ISB instructions architecturally executed + */ +#define XPM_EVENT_INSTRISB 0x90U + +/* + * Counts the number of DSB instructions architecturally executed + */ +#define XPM_EVENT_INSTRDSB 0x91U + +/* + * Counts the number of DMB instructions speculatively executed + */ +#define XPM_EVENT_INSTRDMB 0x92U + +/* + * Counts the number of external interrupts executed by the processor + */ +#define XPM_EVENT_EXTINT 0x93U + +/* + * PLE cache line request completed + */ +#define XPM_EVENT_PLE_LRC 0xA0U + +/* + * PLE cache line request skipped + */ +#define XPM_EVENT_PLE_LRS 0xA1U + +/* + * PLE FIFO flush + */ +#define XPM_EVENT_PLE_FLUSH 0xA2U + +/* + * PLE request complete + */ +#define XPM_EVENT_PLE_CMPL 0xA3U + +/* + * PLE FIFO overflow + */ +#define XPM_EVENT_PLE_OVFL 0xA4U + +/* + * PLE request programmed + */ +#define XPM_EVENT_PLE_PROG 0xA5U + +/* + * The following constants define the configurations for Cortex-A9 Performance + * Monitor Events. Each configuration configures the event counters for a set + * of events. + * ----------------------------------------------- + * Config PmCtr0... PmCtr5 + * ----------------------------------------------- + * XPM_CNTRCFG1 { XPM_EVENT_SOFTINCR, + * XPM_EVENT_INSRFETCH_CACHEREFILL, + * XPM_EVENT_INSTRFECT_TLBREFILL, + * XPM_EVENT_DATA_CACHEREFILL, + * XPM_EVENT_DATA_CACHEACCESS, + * XPM_EVENT_DATA_TLBREFILL } + * + * XPM_CNTRCFG2 { XPM_EVENT_DATA_READS, + * XPM_EVENT_DATA_WRITE, + * XPM_EVENT_EXCEPTION, + * XPM_EVENT_EXCEPRETURN, + * XPM_EVENT_CHANGECONTEXT, + * XPM_EVENT_SW_CHANGEPC } + * + * XPM_CNTRCFG3 { XPM_EVENT_IMMEDBRANCH, + * XPM_EVENT_UNALIGNEDACCESS, + * XPM_EVENT_BRANCHMISS, + * XPM_EVENT_CLOCKCYCLES, + * XPM_EVENT_BRANCHPREDICT, + * XPM_EVENT_JAVABYTECODE } + * + * XPM_CNTRCFG4 { XPM_EVENT_SWJAVABYTECODE, + * XPM_EVENT_JAVABACKBRANCH, + * XPM_EVENT_COHERLINEMISS, + * XPM_EVENT_COHERLINEHIT, + * XPM_EVENT_INSTRSTALL, + * XPM_EVENT_DATASTALL } + * + * XPM_CNTRCFG5 { XPM_EVENT_MAINTLBSTALL, + * XPM_EVENT_STREXPASS, + * XPM_EVENT_STREXFAIL, + * XPM_EVENT_DATAEVICT, + * XPM_EVENT_NODISPATCH, + * XPM_EVENT_ISSUEEMPTY } + * + * XPM_CNTRCFG6 { XPM_EVENT_INSTRRENAME, + * XPM_EVENT_PREDICTFUNCRET, + * XPM_EVENT_MAINEXEC, + * XPM_EVENT_SECEXEC, + * XPM_EVENT_LDRSTR, + * XPM_EVENT_FLOATRENAME } + * + * XPM_CNTRCFG7 { XPM_EVENT_NEONRENAME, + * XPM_EVENT_PLDSTALL, + * XPM_EVENT_WRITESTALL, + * XPM_EVENT_INSTRTLBSTALL, + * XPM_EVENT_DATATLBSTALL, + * XPM_EVENT_INSTR_uTLBSTALL } + * + * XPM_CNTRCFG8 { XPM_EVENT_DATA_uTLBSTALL, + * XPM_EVENT_DMB_STALL, + * XPM_EVENT_INT_CLKEN, + * XPM_EVENT_DE_CLKEN, + * XPM_EVENT_INSTRISB, + * XPM_EVENT_INSTRDSB } + * + * XPM_CNTRCFG9 { XPM_EVENT_INSTRDMB, + * XPM_EVENT_EXTINT, + * XPM_EVENT_PLE_LRC, + * XPM_EVENT_PLE_LRS, + * XPM_EVENT_PLE_FLUSH, + * XPM_EVENT_PLE_CMPL } + * + * XPM_CNTRCFG10 { XPM_EVENT_PLE_OVFL, + * XPM_EVENT_PLE_PROG, + * XPM_EVENT_PLE_LRC, + * XPM_EVENT_PLE_LRS, + * XPM_EVENT_PLE_FLUSH, + * XPM_EVENT_PLE_CMPL } + * + * XPM_CNTRCFG11 { XPM_EVENT_DATASTALL, + * XPM_EVENT_INSRFETCH_CACHEREFILL, + * XPM_EVENT_INSTRFECT_TLBREFILL, + * XPM_EVENT_DATA_CACHEREFILL, + * XPM_EVENT_DATA_CACHEACCESS, + * XPM_EVENT_DATA_TLBREFILL } + */ +#define XPM_CNTRCFG1 0 +#define XPM_CNTRCFG2 1 +#define XPM_CNTRCFG3 2 +#define XPM_CNTRCFG4 3 +#define XPM_CNTRCFG5 4 +#define XPM_CNTRCFG6 5 +#define XPM_CNTRCFG7 6 +#define XPM_CNTRCFG8 7 +#define XPM_CNTRCFG9 8 +#define XPM_CNTRCFG10 9 +#define XPM_CNTRCFG11 10 + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Variable Definitions ****************************/ + +/************************** Function Prototypes *****************************/ + +/* Interface fuctions to access perfromance counters from abstraction layer */ +void Xpm_SetEvents(s32 PmcrCfg); +void Xpm_GetEventCounters(u32 *PmCtrValue); + +#ifdef __cplusplus +} +#endif + +#endif +/** +* @} End of "addtogroup a9_event_counter_apis". +*/ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xpseudo_asm.h b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xpseudo_asm.h new file mode 100644 index 0000000..c7123a0 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xpseudo_asm.h @@ -0,0 +1,82 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xpseudo_asm.h +* +* @addtogroup a9_specific Cortex A9 Processor Specific Include Files +* +* The xpseudo_asm.h includes xreg_cortexa9.h and xpseudo_asm_gcc.h. +* +* The xreg_cortexa9.h file contains definitions for inline assembler code. +* It provides inline definitions for Cortex A9 GPRs, SPRs, MPE registers, +* co-processor registers and Debug registers. +* +* The xpseudo_asm_gcc.h contains the definitions for the most often used inline +* assembler instructions, available as macros. These can be very useful for +* tasks such as setting or getting special purpose registers, synchronization, +* or cache manipulation etc. These inline assembler instructions can be used +* from drivers and user applications written in C. +* +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a ecm  10/18/09 First release
+* 3.04a sdm  01/02/12 Remove redundant dsb in mcr instruction.
+* 6.8   aru  09/06/18 Removed compilation warnings for ARMCC toolchain.
+* 
+* +******************************************************************************/ +#ifndef XPSEUDO_ASM_H +#define XPSEUDO_ASM_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "xreg_cortexa9.h" +#ifdef __GNUC__ + #include "xpseudo_asm_gcc.h" +#elif defined (__ICCARM__) + #include "xpseudo_asm_iccarm.h" +#else + #include "xpseudo_asm_rvct.h" +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* XPSEUDO_ASM_H */ +/** +* @} End of "addtogroup a9_specific". +*/ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xpseudo_asm_gcc.h b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xpseudo_asm_gcc.h new file mode 100644 index 0000000..85b067d --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xpseudo_asm_gcc.h @@ -0,0 +1,252 @@ +/****************************************************************************** +* +* Copyright (C) 2014 - 2016 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xpseudo_asm_gcc.h +* +* This header file contains macros for using inline assembler code. It is +* written specifically for the GNU compiler. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 5.00 	pkp		 05/21/14 First release
+* 6.0   mus      07/27/16 Consolidated file for a53,a9 and r5 processors
+* 
+* +******************************************************************************/ + +#ifndef XPSEUDO_ASM_GCC_H /* prevent circular inclusions */ +#define XPSEUDO_ASM_GCC_H /* by using protection macros */ + +/***************************** Include Files ********************************/ + +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/* necessary for pre-processor */ +#define stringify(s) tostring(s) +#define tostring(s) #s + +#if defined (__aarch64__) +/* pseudo assembler instructions */ +#define mfcpsr() ({u32 rval = 0U; \ + asm volatile("mrs %0, DAIF" : "=r" (rval));\ + rval;\ + }) + +#define mtcpsr(v) __asm__ __volatile__ ("msr DAIF, %0" : : "r" (v)) + +#define cpsiei() //__asm__ __volatile__("cpsie i\n") +#define cpsidi() //__asm__ __volatile__("cpsid i\n") + +#define cpsief() //__asm__ __volatile__("cpsie f\n") +#define cpsidf() //__asm__ __volatile__("cpsid f\n") + + + +#define mtgpr(rn, v) /*__asm__ __volatile__(\ + "mov r" stringify(rn) ", %0 \n"\ + : : "r" (v)\ + )*/ + +#define mfgpr(rn) /*({u32 rval; \ + __asm__ __volatile__(\ + "mov %0,r" stringify(rn) "\n"\ + : "=r" (rval)\ + );\ + rval;\ + })*/ + +/* memory synchronization operations */ + +/* Instruction Synchronization Barrier */ +#define isb() __asm__ __volatile__ ("isb sy") + +/* Data Synchronization Barrier */ +#define dsb() __asm__ __volatile__("dsb sy") + +/* Data Memory Barrier */ +#define dmb() __asm__ __volatile__("dmb sy") + + +/* Memory Operations */ +#define ldr(adr) ({u64 rval; \ + __asm__ __volatile__(\ + "ldr %0,[%1]"\ + : "=r" (rval) : "r" (adr)\ + );\ + rval;\ + }) + +#define mfelrel3() ({u64 rval = 0U; \ + asm volatile("mrs %0, ELR_EL3" : "=r" (rval));\ + rval;\ + }) + +#define mtelrel3(v) __asm__ __volatile__ ("msr ELR_EL3, %0" : : "r" (v)) + +#else + +/* pseudo assembler instructions */ +#define mfcpsr() ({u32 rval = 0U; \ + __asm__ __volatile__(\ + "mrs %0, cpsr\n"\ + : "=r" (rval)\ + );\ + rval;\ + }) + +#define mtcpsr(v) __asm__ __volatile__(\ + "msr cpsr,%0\n"\ + : : "r" (v)\ + ) + +#define cpsiei() __asm__ __volatile__("cpsie i\n") +#define cpsidi() __asm__ __volatile__("cpsid i\n") + +#define cpsief() __asm__ __volatile__("cpsie f\n") +#define cpsidf() __asm__ __volatile__("cpsid f\n") + + + +#define mtgpr(rn, v) __asm__ __volatile__(\ + "mov r" stringify(rn) ", %0 \n"\ + : : "r" (v)\ + ) + +#define mfgpr(rn) ({u32 rval; \ + __asm__ __volatile__(\ + "mov %0,r" stringify(rn) "\n"\ + : "=r" (rval)\ + );\ + rval;\ + }) + +/* memory synchronization operations */ + +/* Instruction Synchronization Barrier */ +#define isb() __asm__ __volatile__ ("isb" : : : "memory") + +/* Data Synchronization Barrier */ +#define dsb() __asm__ __volatile__ ("dsb" : : : "memory") + +/* Data Memory Barrier */ +#define dmb() __asm__ __volatile__ ("dmb" : : : "memory") + + +/* Memory Operations */ +#define ldr(adr) ({u32 rval; \ + __asm__ __volatile__(\ + "ldr %0,[%1]"\ + : "=r" (rval) : "r" (adr)\ + );\ + rval;\ + }) + +#endif + +#define ldrb(adr) ({u8 rval; \ + __asm__ __volatile__(\ + "ldrb %0,[%1]"\ + : "=r" (rval) : "r" (adr)\ + );\ + rval;\ + }) + +#define str(adr, val) __asm__ __volatile__(\ + "str %0,[%1]\n"\ + : : "r" (val), "r" (adr)\ + ) + +#define strb(adr, val) __asm__ __volatile__(\ + "strb %0,[%1]\n"\ + : : "r" (val), "r" (adr)\ + ) + +/* Count leading zeroes (clz) */ +#define clz(arg) ({u8 rval; \ + __asm__ __volatile__(\ + "clz %0,%1"\ + : "=r" (rval) : "r" (arg)\ + );\ + rval;\ + }) + +#if defined (__aarch64__) +#define mtcpdc(reg,val) __asm__ __volatile__("dc " #reg ",%0" : : "r" (val)) +#define mtcpic(reg,val) __asm__ __volatile__("ic " #reg ",%0" : : "r" (val)) + +#define mtcpicall(reg) __asm__ __volatile__("ic " #reg) +#define mtcptlbi(reg) __asm__ __volatile__("tlbi " #reg) +#define mtcpat(reg,val) __asm__ __volatile__("at " #reg ",%0" : : "r" (val)) +/* CP15 operations */ +#define mfcp(reg) ({u64 rval = 0U;\ + __asm__ __volatile__("mrs %0, " #reg : "=r" (rval));\ + rval;\ + }) + +#define mtcp(reg,val) __asm__ __volatile__("msr " #reg ",%0" : : "r" (val)) + +#else +/* CP15 operations */ +#define mtcp(rn, v) __asm__ __volatile__(\ + "mcr " rn "\n"\ + : : "r" (v)\ + ); + +#define mfcp(rn) ({u32 rval = 0U; \ + __asm__ __volatile__(\ + "mrc " rn "\n"\ + : "=r" (rval)\ + );\ + rval;\ + }) +#endif + +/************************** Variable Definitions ****************************/ + +/************************** Function Prototypes *****************************/ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* XPSEUDO_ASM_GCC_H */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xreg_cortexa9.h b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xreg_cortexa9.h new file mode 100644 index 0000000..ad93665 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xreg_cortexa9.h @@ -0,0 +1,587 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xreg_cortexa9.h +* +* This header file contains definitions for using inline assembler code. It is +* written specifically for the GNU, ARMCC compiler. +* +* All of the ARM Cortex A9 GPRs, SPRs, and Debug Registers are defined along +* with the positions of the bits within the registers. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 1.00a ecm/sdm  10/20/09 First release
+* 
+* +******************************************************************************/ +#ifndef XREG_CORTEXA9_H +#define XREG_CORTEXA9_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* GPRs */ +#define XREG_GPR0 r0 +#define XREG_GPR1 r1 +#define XREG_GPR2 r2 +#define XREG_GPR3 r3 +#define XREG_GPR4 r4 +#define XREG_GPR5 r5 +#define XREG_GPR6 r6 +#define XREG_GPR7 r7 +#define XREG_GPR8 r8 +#define XREG_GPR9 r9 +#define XREG_GPR10 r10 +#define XREG_GPR11 r11 +#define XREG_GPR12 r12 +#define XREG_GPR13 r13 +#define XREG_GPR14 r14 +#define XREG_GPR15 r15 +#define XREG_CPSR cpsr + +/* Coprocessor number defines */ +#define XREG_CP0 0 +#define XREG_CP1 1 +#define XREG_CP2 2 +#define XREG_CP3 3 +#define XREG_CP4 4 +#define XREG_CP5 5 +#define XREG_CP6 6 +#define XREG_CP7 7 +#define XREG_CP8 8 +#define XREG_CP9 9 +#define XREG_CP10 10 +#define XREG_CP11 11 +#define XREG_CP12 12 +#define XREG_CP13 13 +#define XREG_CP14 14 +#define XREG_CP15 15 + +/* Coprocessor control register defines */ +#define XREG_CR0 cr0 +#define XREG_CR1 cr1 +#define XREG_CR2 cr2 +#define XREG_CR3 cr3 +#define XREG_CR4 cr4 +#define XREG_CR5 cr5 +#define XREG_CR6 cr6 +#define XREG_CR7 cr7 +#define XREG_CR8 cr8 +#define XREG_CR9 cr9 +#define XREG_CR10 cr10 +#define XREG_CR11 cr11 +#define XREG_CR12 cr12 +#define XREG_CR13 cr13 +#define XREG_CR14 cr14 +#define XREG_CR15 cr15 + +/* Current Processor Status Register (CPSR) Bits */ +#define XREG_CPSR_THUMB_MODE 0x20 +#define XREG_CPSR_MODE_BITS 0x1F +#define XREG_CPSR_SYSTEM_MODE 0x1F +#define XREG_CPSR_UNDEFINED_MODE 0x1B +#define XREG_CPSR_DATA_ABORT_MODE 0x17 +#define XREG_CPSR_SVC_MODE 0x13 +#define XREG_CPSR_IRQ_MODE 0x12 +#define XREG_CPSR_FIQ_MODE 0x11 +#define XREG_CPSR_USER_MODE 0x10 + +#define XREG_CPSR_IRQ_ENABLE 0x80 +#define XREG_CPSR_FIQ_ENABLE 0x40 + +#define XREG_CPSR_N_BIT 0x80000000 +#define XREG_CPSR_Z_BIT 0x40000000 +#define XREG_CPSR_C_BIT 0x20000000 +#define XREG_CPSR_V_BIT 0x10000000 + + +/* CP15 defines */ +#if defined (__GNUC__) || defined (__ICCARM__) +/* C0 Register defines */ +#define XREG_CP15_MAIN_ID "p15, 0, %0, c0, c0, 0" +#define XREG_CP15_CACHE_TYPE "p15, 0, %0, c0, c0, 1" +#define XREG_CP15_TCM_TYPE "p15, 0, %0, c0, c0, 2" +#define XREG_CP15_TLB_TYPE "p15, 0, %0, c0, c0, 3" +#define XREG_CP15_MULTI_PROC_AFFINITY "p15, 0, %0, c0, c0, 5" + +#define XREG_CP15_PROC_FEATURE_0 "p15, 0, %0, c0, c1, 0" +#define XREG_CP15_PROC_FEATURE_1 "p15, 0, %0, c0, c1, 1" +#define XREG_CP15_DEBUG_FEATURE_0 "p15, 0, %0, c0, c1, 2" +#define XREG_CP15_MEMORY_FEATURE_0 "p15, 0, %0, c0, c1, 4" +#define XREG_CP15_MEMORY_FEATURE_1 "p15, 0, %0, c0, c1, 5" +#define XREG_CP15_MEMORY_FEATURE_2 "p15, 0, %0, c0, c1, 6" +#define XREG_CP15_MEMORY_FEATURE_3 "p15, 0, %0, c0, c1, 7" + +#define XREG_CP15_INST_FEATURE_0 "p15, 0, %0, c0, c2, 0" +#define XREG_CP15_INST_FEATURE_1 "p15, 0, %0, c0, c2, 1" +#define XREG_CP15_INST_FEATURE_2 "p15, 0, %0, c0, c2, 2" +#define XREG_CP15_INST_FEATURE_3 "p15, 0, %0, c0, c2, 3" +#define XREG_CP15_INST_FEATURE_4 "p15, 0, %0, c0, c2, 4" + +#define XREG_CP15_CACHE_SIZE_ID "p15, 1, %0, c0, c0, 0" +#define XREG_CP15_CACHE_LEVEL_ID "p15, 1, %0, c0, c0, 1" +#define XREG_CP15_AUXILARY_ID "p15, 1, %0, c0, c0, 7" + +#define XREG_CP15_CACHE_SIZE_SEL "p15, 2, %0, c0, c0, 0" + +/* C1 Register Defines */ +#define XREG_CP15_SYS_CONTROL "p15, 0, %0, c1, c0, 0" +#define XREG_CP15_AUX_CONTROL "p15, 0, %0, c1, c0, 1" +#define XREG_CP15_CP_ACCESS_CONTROL "p15, 0, %0, c1, c0, 2" + +#define XREG_CP15_SECURE_CONFIG "p15, 0, %0, c1, c1, 0" +#define XREG_CP15_SECURE_DEBUG_ENABLE "p15, 0, %0, c1, c1, 1" +#define XREG_CP15_NS_ACCESS_CONTROL "p15, 0, %0, c1, c1, 2" +#define XREG_CP15_VIRTUAL_CONTROL "p15, 0, %0, c1, c1, 3" + +#else /* RVCT */ +/* C0 Register defines */ +#define XREG_CP15_MAIN_ID "cp15:0:c0:c0:0" +#define XREG_CP15_CACHE_TYPE "cp15:0:c0:c0:1" +#define XREG_CP15_TCM_TYPE "cp15:0:c0:c0:2" +#define XREG_CP15_TLB_TYPE "cp15:0:c0:c0:3" +#define XREG_CP15_MULTI_PROC_AFFINITY "cp15:0:c0:c0:5" + +#define XREG_CP15_PROC_FEATURE_0 "cp15:0:c0:c1:0" +#define XREG_CP15_PROC_FEATURE_1 "cp15:0:c0:c1:1" +#define XREG_CP15_DEBUG_FEATURE_0 "cp15:0:c0:c1:2" +#define XREG_CP15_MEMORY_FEATURE_0 "cp15:0:c0:c1:4" +#define XREG_CP15_MEMORY_FEATURE_1 "cp15:0:c0:c1:5" +#define XREG_CP15_MEMORY_FEATURE_2 "cp15:0:c0:c1:6" +#define XREG_CP15_MEMORY_FEATURE_3 "cp15:0:c0:c1:7" + +#define XREG_CP15_INST_FEATURE_0 "cp15:0:c0:c2:0" +#define XREG_CP15_INST_FEATURE_1 "cp15:0:c0:c2:1" +#define XREG_CP15_INST_FEATURE_2 "cp15:0:c0:c2:2" +#define XREG_CP15_INST_FEATURE_3 "cp15:0:c0:c2:3" +#define XREG_CP15_INST_FEATURE_4 "cp15:0:c0:c2:4" + +#define XREG_CP15_CACHE_SIZE_ID "cp15:1:c0:c0:0" +#define XREG_CP15_CACHE_LEVEL_ID "cp15:1:c0:c0:1" +#define XREG_CP15_AUXILARY_ID "cp15:1:c0:c0:7" + +#define XREG_CP15_CACHE_SIZE_SEL "cp15:2:c0:c0:0" + +/* C1 Register Defines */ +#define XREG_CP15_SYS_CONTROL "cp15:0:c1:c0:0" +#define XREG_CP15_AUX_CONTROL "cp15:0:c1:c0:1" +#define XREG_CP15_CP_ACCESS_CONTROL "cp15:0:c1:c0:2" + +#define XREG_CP15_SECURE_CONFIG "cp15:0:c1:c1:0" +#define XREG_CP15_SECURE_DEBUG_ENABLE "cp15:0:c1:c1:1" +#define XREG_CP15_NS_ACCESS_CONTROL "cp15:0:c1:c1:2" +#define XREG_CP15_VIRTUAL_CONTROL "cp15:0:c1:c1:3" +#endif + +/* XREG_CP15_CONTROL bit defines */ +#define XREG_CP15_CONTROL_TE_BIT 0x40000000U +#define XREG_CP15_CONTROL_AFE_BIT 0x20000000U +#define XREG_CP15_CONTROL_TRE_BIT 0x10000000U +#define XREG_CP15_CONTROL_NMFI_BIT 0x08000000U +#define XREG_CP15_CONTROL_EE_BIT 0x02000000U +#define XREG_CP15_CONTROL_HA_BIT 0x00020000U +#define XREG_CP15_CONTROL_RR_BIT 0x00004000U +#define XREG_CP15_CONTROL_V_BIT 0x00002000U +#define XREG_CP15_CONTROL_I_BIT 0x00001000U +#define XREG_CP15_CONTROL_Z_BIT 0x00000800U +#define XREG_CP15_CONTROL_SW_BIT 0x00000400U +#define XREG_CP15_CONTROL_B_BIT 0x00000080U +#define XREG_CP15_CONTROL_C_BIT 0x00000004U +#define XREG_CP15_CONTROL_A_BIT 0x00000002U +#define XREG_CP15_CONTROL_M_BIT 0x00000001U + +#if defined (__GNUC__) || defined (__ICCARM__) +/* C2 Register Defines */ +#define XREG_CP15_TTBR0 "p15, 0, %0, c2, c0, 0" +#define XREG_CP15_TTBR1 "p15, 0, %0, c2, c0, 1" +#define XREG_CP15_TTB_CONTROL "p15, 0, %0, c2, c0, 2" + +/* C3 Register Defines */ +#define XREG_CP15_DOMAIN_ACCESS_CTRL "p15, 0, %0, c3, c0, 0" + +/* C4 Register Defines */ +/* Not Used */ + +/* C5 Register Defines */ +#define XREG_CP15_DATA_FAULT_STATUS "p15, 0, %0, c5, c0, 0" +#define XREG_CP15_INST_FAULT_STATUS "p15, 0, %0, c5, c0, 1" + +#define XREG_CP15_AUX_DATA_FAULT_STATUS "p15, 0, %0, c5, c1, 0" +#define XREG_CP15_AUX_INST_FAULT_STATUS "p15, 0, %0, c5, c1, 1" + +/* C6 Register Defines */ +#define XREG_CP15_DATA_FAULT_ADDRESS "p15, 0, %0, c6, c0, 0" +#define XREG_CP15_INST_FAULT_ADDRESS "p15, 0, %0, c6, c0, 2" + +/* C7 Register Defines */ +#define XREG_CP15_NOP "p15, 0, %0, c7, c0, 4" + +#define XREG_CP15_INVAL_IC_POU_IS "p15, 0, %0, c7, c1, 0" +#define XREG_CP15_INVAL_BRANCH_ARRAY_IS "p15, 0, %0, c7, c1, 6" + +#define XREG_CP15_PHYS_ADDR "p15, 0, %0, c7, c4, 0" + +#define XREG_CP15_INVAL_IC_POU "p15, 0, %0, c7, c5, 0" +#define XREG_CP15_INVAL_IC_LINE_MVA_POU "p15, 0, %0, c7, c5, 1" + +/* The CP15 register access below has been deprecated in favor of the new + * isb instruction in Cortex A9. + */ +#define XREG_CP15_INST_SYNC_BARRIER "p15, 0, %0, c7, c5, 4" +#define XREG_CP15_INVAL_BRANCH_ARRAY "p15, 0, %0, c7, c5, 6" + +#define XREG_CP15_INVAL_DC_LINE_MVA_POC "p15, 0, %0, c7, c6, 1" +#define XREG_CP15_INVAL_DC_LINE_SW "p15, 0, %0, c7, c6, 2" + +#define XREG_CP15_VA_TO_PA_CURRENT_0 "p15, 0, %0, c7, c8, 0" +#define XREG_CP15_VA_TO_PA_CURRENT_1 "p15, 0, %0, c7, c8, 1" +#define XREG_CP15_VA_TO_PA_CURRENT_2 "p15, 0, %0, c7, c8, 2" +#define XREG_CP15_VA_TO_PA_CURRENT_3 "p15, 0, %0, c7, c8, 3" + +#define XREG_CP15_VA_TO_PA_OTHER_0 "p15, 0, %0, c7, c8, 4" +#define XREG_CP15_VA_TO_PA_OTHER_1 "p15, 0, %0, c7, c8, 5" +#define XREG_CP15_VA_TO_PA_OTHER_2 "p15, 0, %0, c7, c8, 6" +#define XREG_CP15_VA_TO_PA_OTHER_3 "p15, 0, %0, c7, c8, 7" + +#define XREG_CP15_CLEAN_DC_LINE_MVA_POC "p15, 0, %0, c7, c10, 1" +#define XREG_CP15_CLEAN_DC_LINE_SW "p15, 0, %0, c7, c10, 2" + +/* The next two CP15 register accesses below have been deprecated in favor + * of the new dsb and dmb instructions in Cortex A9. + */ +#define XREG_CP15_DATA_SYNC_BARRIER "p15, 0, %0, c7, c10, 4" +#define XREG_CP15_DATA_MEMORY_BARRIER "p15, 0, %0, c7, c10, 5" + +#define XREG_CP15_CLEAN_DC_LINE_MVA_POU "p15, 0, %0, c7, c11, 1" + +#define XREG_CP15_NOP2 "p15, 0, %0, c7, c13, 1" + +#define XREG_CP15_CLEAN_INVAL_DC_LINE_MVA_POC "p15, 0, %0, c7, c14, 1" +#define XREG_CP15_CLEAN_INVAL_DC_LINE_SW "p15, 0, %0, c7, c14, 2" + +/* C8 Register Defines */ +#define XREG_CP15_INVAL_TLB_IS "p15, 0, %0, c8, c3, 0" +#define XREG_CP15_INVAL_TLB_MVA_IS "p15, 0, %0, c8, c3, 1" +#define XREG_CP15_INVAL_TLB_ASID_IS "p15, 0, %0, c8, c3, 2" +#define XREG_CP15_INVAL_TLB_MVA_ASID_IS "p15, 0, %0, c8, c3, 3" + +#define XREG_CP15_INVAL_ITLB_UNLOCKED "p15, 0, %0, c8, c5, 0" +#define XREG_CP15_INVAL_ITLB_MVA "p15, 0, %0, c8, c5, 1" +#define XREG_CP15_INVAL_ITLB_ASID "p15, 0, %0, c8, c5, 2" + +#define XREG_CP15_INVAL_DTLB_UNLOCKED "p15, 0, %0, c8, c6, 0" +#define XREG_CP15_INVAL_DTLB_MVA "p15, 0, %0, c8, c6, 1" +#define XREG_CP15_INVAL_DTLB_ASID "p15, 0, %0, c8, c6, 2" + +#define XREG_CP15_INVAL_UTLB_UNLOCKED "p15, 0, %0, c8, c7, 0" +#define XREG_CP15_INVAL_UTLB_MVA "p15, 0, %0, c8, c7, 1" +#define XREG_CP15_INVAL_UTLB_ASID "p15, 0, %0, c8, c7, 2" +#define XREG_CP15_INVAL_UTLB_MVA_ASID "p15, 0, %0, c8, c7, 3" + +/* C9 Register Defines */ +#define XREG_CP15_PERF_MONITOR_CTRL "p15, 0, %0, c9, c12, 0" +#define XREG_CP15_COUNT_ENABLE_SET "p15, 0, %0, c9, c12, 1" +#define XREG_CP15_COUNT_ENABLE_CLR "p15, 0, %0, c9, c12, 2" +#define XREG_CP15_V_FLAG_STATUS "p15, 0, %0, c9, c12, 3" +#define XREG_CP15_SW_INC "p15, 0, %0, c9, c12, 4" +#define XREG_CP15_EVENT_CNTR_SEL "p15, 0, %0, c9, c12, 5" + +#define XREG_CP15_PERF_CYCLE_COUNTER "p15, 0, %0, c9, c13, 0" +#define XREG_CP15_EVENT_TYPE_SEL "p15, 0, %0, c9, c13, 1" +#define XREG_CP15_PERF_MONITOR_COUNT "p15, 0, %0, c9, c13, 2" + +#define XREG_CP15_USER_ENABLE "p15, 0, %0, c9, c14, 0" +#define XREG_CP15_INTR_ENABLE_SET "p15, 0, %0, c9, c14, 1" +#define XREG_CP15_INTR_ENABLE_CLR "p15, 0, %0, c9, c14, 2" + +/* C10 Register Defines */ +#define XREG_CP15_TLB_LOCKDWN "p15, 0, %0, c10, c0, 0" + +#define XREG_CP15_PRI_MEM_REMAP "p15, 0, %0, c10, c2, 0" +#define XREG_CP15_NORM_MEM_REMAP "p15, 0, %0, c10, c2, 1" + +/* C11 Register Defines */ +/* Not used */ + +/* C12 Register Defines */ +#define XREG_CP15_VEC_BASE_ADDR "p15, 0, %0, c12, c0, 0" +#define XREG_CP15_MONITOR_VEC_BASE_ADDR "p15, 0, %0, c12, c0, 1" + +#define XREG_CP15_INTERRUPT_STATUS "p15, 0, %0, c12, c1, 0" +#define XREG_CP15_VIRTUALIZATION_INTR "p15, 0, %0, c12, c1, 1" + +/* C13 Register Defines */ +#define XREG_CP15_CONTEXT_ID "p15, 0, %0, c13, c0, 1" +#define USER_RW_THREAD_PID "p15, 0, %0, c13, c0, 2" +#define USER_RO_THREAD_PID "p15, 0, %0, c13, c0, 3" +#define USER_PRIV_THREAD_PID "p15, 0, %0, c13, c0, 4" + +/* C14 Register Defines */ +/* not used */ + +/* C15 Register Defines */ +#define XREG_CP15_POWER_CTRL "p15, 0, %0, c15, c0, 0" +#define XREG_CP15_CONFIG_BASE_ADDR "p15, 4, %0, c15, c0, 0" + +#define XREG_CP15_READ_TLB_ENTRY "p15, 5, %0, c15, c4, 2" +#define XREG_CP15_WRITE_TLB_ENTRY "p15, 5, %0, c15, c4, 4" + +#define XREG_CP15_MAIN_TLB_VA "p15, 5, %0, c15, c5, 2" + +#define XREG_CP15_MAIN_TLB_PA "p15, 5, %0, c15, c6, 2" + +#define XREG_CP15_MAIN_TLB_ATTR "p15, 5, %0, c15, c7, 2" + +#else +/* C2 Register Defines */ +#define XREG_CP15_TTBR0 "cp15:0:c2:c0:0" +#define XREG_CP15_TTBR1 "cp15:0:c2:c0:1" +#define XREG_CP15_TTB_CONTROL "cp15:0:c2:c0:2" + +/* C3 Register Defines */ +#define XREG_CP15_DOMAIN_ACCESS_CTRL "cp15:0:c3:c0:0" + +/* C4 Register Defines */ +/* Not Used */ + +/* C5 Register Defines */ +#define XREG_CP15_DATA_FAULT_STATUS "cp15:0:c5:c0:0" +#define XREG_CP15_INST_FAULT_STATUS "cp15:0:c5:c0:1" + +#define XREG_CP15_AUX_DATA_FAULT_STATUS "cp15:0:c5:c1:0" +#define XREG_CP15_AUX_INST_FAULT_STATUS "cp15:0:c5:c1:1" + +/* C6 Register Defines */ +#define XREG_CP15_DATA_FAULT_ADDRESS "cp15:0:c6:c0:0" +#define XREG_CP15_INST_FAULT_ADDRESS "cp15:0:c6:c0:2" + +/* C7 Register Defines */ +#define XREG_CP15_NOP "cp15:0:c7:c0:4" + +#define XREG_CP15_INVAL_IC_POU_IS "cp15:0:c7:c1:0" +#define XREG_CP15_INVAL_BRANCH_ARRAY_IS "cp15:0:c7:c1:6" + +#define XREG_CP15_PHYS_ADDR "cp15:0:c7:c4:0" + +#define XREG_CP15_INVAL_IC_POU "cp15:0:c7:c5:0" +#define XREG_CP15_INVAL_IC_LINE_MVA_POU "cp15:0:c7:c5:1" + +/* The CP15 register access below has been deprecated in favor of the new + * isb instruction in Cortex A9. + */ +#define XREG_CP15_INST_SYNC_BARRIER "cp15:0:c7:c5:4" +#define XREG_CP15_INVAL_BRANCH_ARRAY "cp15:0:c7:c5:6" + +#define XREG_CP15_INVAL_DC_LINE_MVA_POC "cp15:0:c7:c6:1" +#define XREG_CP15_INVAL_DC_LINE_SW "cp15:0:c7:c6:2" + +#define XREG_CP15_VA_TO_PA_CURRENT_0 "cp15:0:c7:c8:0" +#define XREG_CP15_VA_TO_PA_CURRENT_1 "cp15:0:c7:c8:1" +#define XREG_CP15_VA_TO_PA_CURRENT_2 "cp15:0:c7:c8:2" +#define XREG_CP15_VA_TO_PA_CURRENT_3 "cp15:0:c7:c8:3" + +#define XREG_CP15_VA_TO_PA_OTHER_0 "cp15:0:c7:c8:4" +#define XREG_CP15_VA_TO_PA_OTHER_1 "cp15:0:c7:c8:5" +#define XREG_CP15_VA_TO_PA_OTHER_2 "cp15:0:c7:c8:6" +#define XREG_CP15_VA_TO_PA_OTHER_3 "cp15:0:c7:c8:7" + +#define XREG_CP15_CLEAN_DC_LINE_MVA_POC "cp15:0:c7:c10:1" +#define XREG_CP15_CLEAN_DC_LINE_SW "cp15:0:c7:c10:2" + +/* The next two CP15 register accesses below have been deprecated in favor + * of the new dsb and dmb instructions in Cortex A9. + */ +#define XREG_CP15_DATA_SYNC_BARRIER "cp15:0:c7:c10:4" +#define XREG_CP15_DATA_MEMORY_BARRIER "cp15:0:c7:c10:5" + +#define XREG_CP15_CLEAN_DC_LINE_MVA_POU "cp15:0:c7:c11:1" + +#define XREG_CP15_NOP2 "cp15:0:c7:c13:1" + +#define XREG_CP15_CLEAN_INVAL_DC_LINE_MVA_POC "cp15:0:c7:c14:1" +#define XREG_CP15_CLEAN_INVAL_DC_LINE_SW "cp15:0:c7:c14:2" + +/* C8 Register Defines */ +#define XREG_CP15_INVAL_TLB_IS "cp15:0:c8:c3:0" +#define XREG_CP15_INVAL_TLB_MVA_IS "cp15:0:c8:c3:1" +#define XREG_CP15_INVAL_TLB_ASID_IS "cp15:0:c8:c3:2" +#define XREG_CP15_INVAL_TLB_MVA_ASID_IS "cp15:0:c8:c3:3" + +#define XREG_CP15_INVAL_ITLB_UNLOCKED "cp15:0:c8:c5:0" +#define XREG_CP15_INVAL_ITLB_MVA "cp15:0:c8:c5:1" +#define XREG_CP15_INVAL_ITLB_ASID "cp15:0:c8:c5:2" + +#define XREG_CP15_INVAL_DTLB_UNLOCKED "cp15:0:c8:c6:0" +#define XREG_CP15_INVAL_DTLB_MVA "cp15:0:c8:c6:1" +#define XREG_CP15_INVAL_DTLB_ASID "cp15:0:c8:c6:2" + +#define XREG_CP15_INVAL_UTLB_UNLOCKED "cp15:0:c8:c7:0" +#define XREG_CP15_INVAL_UTLB_MVA "cp15:0:c8:c7:1" +#define XREG_CP15_INVAL_UTLB_ASID "cp15:0:c8:c7:2" +#define XREG_CP15_INVAL_UTLB_MVA_ASID "cp15:0:c8:c7:3" + +/* C9 Register Defines */ +#define XREG_CP15_PERF_MONITOR_CTRL "cp15:0:c9:c12:0" +#define XREG_CP15_COUNT_ENABLE_SET "cp15:0:c9:c12:1" +#define XREG_CP15_COUNT_ENABLE_CLR "cp15:0:c9:c12:2" +#define XREG_CP15_V_FLAG_STATUS "cp15:0:c9:c12:3" +#define XREG_CP15_SW_INC "cp15:0:c9:c12:4" +#define XREG_CP15_EVENT_CNTR_SEL "cp15:0:c9:c12:5" + +#define XREG_CP15_PERF_CYCLE_COUNTER "cp15:0:c9:c13:0" +#define XREG_CP15_EVENT_TYPE_SEL "cp15:0:c9:c13:1" +#define XREG_CP15_PERF_MONITOR_COUNT "cp15:0:c9:c13:2" + +#define XREG_CP15_USER_ENABLE "cp15:0:c9:c14:0" +#define XREG_CP15_INTR_ENABLE_SET "cp15:0:c9:c14:1" +#define XREG_CP15_INTR_ENABLE_CLR "cp15:0:c9:c14:2" + +/* C10 Register Defines */ +#define XREG_CP15_TLB_LOCKDWN "cp15:0:c10:c0:0" + +#define XREG_CP15_PRI_MEM_REMAP "cp15:0:c10:c2:0" +#define XREG_CP15_NORM_MEM_REMAP "cp15:0:c10:c2:1" + +/* C11 Register Defines */ +/* Not used */ + +/* C12 Register Defines */ +#define XREG_CP15_VEC_BASE_ADDR "cp15:0:c12:c0:0" +#define XREG_CP15_MONITOR_VEC_BASE_ADDR "cp15:0:c12:c0:1" + +#define XREG_CP15_INTERRUPT_STATUS "cp15:0:c12:c1:0" +#define XREG_CP15_VIRTUALIZATION_INTR "cp15:0:c12:c1:1" + +/* C13 Register Defines */ +#define XREG_CP15_CONTEXT_ID "cp15:0:c13:c0:1" +#define USER_RW_THREAD_PID "cp15:0:c13:c0:2" +#define USER_RO_THREAD_PID "cp15:0:c13:c0:3" +#define USER_PRIV_THREAD_PID "cp15:0:c13:c0:4" + +/* C14 Register Defines */ +/* not used */ + +/* C15 Register Defines */ +#define XREG_CP15_POWER_CTRL "cp15:0:c15:c0:0" +#define XREG_CP15_CONFIG_BASE_ADDR "cp15:4:c15:c0:0" + +#define XREG_CP15_READ_TLB_ENTRY "cp15:5:c15:c4:2" +#define XREG_CP15_WRITE_TLB_ENTRY "cp15:5:c15:c4:4" + +#define XREG_CP15_MAIN_TLB_VA "cp15:5:c15:c5:2" + +#define XREG_CP15_MAIN_TLB_PA "cp15:5:c15:c6:2" + +#define XREG_CP15_MAIN_TLB_ATTR "cp15:5:c15:c7:2" +#endif + + +/* MPE register definitions */ +#define XREG_FPSID c0 +#define XREG_FPSCR c1 +#define XREG_MVFR1 c6 +#define XREG_MVFR0 c7 +#define XREG_FPEXC c8 +#define XREG_FPINST c9 +#define XREG_FPINST2 c10 + +/* FPSID bits */ +#define XREG_FPSID_IMPLEMENTER_BIT (24) +#define XREG_FPSID_IMPLEMENTER_MASK (0xFF << FPSID_IMPLEMENTER_BIT) +#define XREG_FPSID_SOFTWARE (1<<23) +#define XREG_FPSID_ARCH_BIT (16) +#define XREG_FPSID_ARCH_MASK (0xF << FPSID_ARCH_BIT) +#define XREG_FPSID_PART_BIT (8) +#define XREG_FPSID_PART_MASK (0xFF << FPSID_PART_BIT) +#define XREG_FPSID_VARIANT_BIT (4) +#define XREG_FPSID_VARIANT_MASK (0xF << FPSID_VARIANT_BIT) +#define XREG_FPSID_REV_BIT (0) +#define XREG_FPSID_REV_MASK (0xF << FPSID_REV_BIT) + +/* FPSCR bits */ +#define XREG_FPSCR_N_BIT (1 << 31) +#define XREG_FPSCR_Z_BIT (1 << 30) +#define XREG_FPSCR_C_BIT (1 << 29) +#define XREG_FPSCR_V_BIT (1 << 28) +#define XREG_FPSCR_QC (1 << 27) +#define XREG_FPSCR_AHP (1 << 26) +#define XREG_FPSCR_DEFAULT_NAN (1 << 25) +#define XREG_FPSCR_FLUSHTOZERO (1 << 24) +#define XREG_FPSCR_ROUND_NEAREST (0 << 22) +#define XREG_FPSCR_ROUND_PLUSINF (1 << 22) +#define XREG_FPSCR_ROUND_MINUSINF (2 << 22) +#define XREG_FPSCR_ROUND_TOZERO (3 << 22) +#define XREG_FPSCR_RMODE_BIT (22) +#define XREG_FPSCR_RMODE_MASK (3 << FPSCR_RMODE_BIT) +#define XREG_FPSCR_STRIDE_BIT (20) +#define XREG_FPSCR_STRIDE_MASK (3 << FPSCR_STRIDE_BIT) +#define XREG_FPSCR_LENGTH_BIT (16) +#define XREG_FPSCR_LENGTH_MASK (7 << FPSCR_LENGTH_BIT) +#define XREG_FPSCR_IDC (1 << 7) +#define XREG_FPSCR_IXC (1 << 4) +#define XREG_FPSCR_UFC (1 << 3) +#define XREG_FPSCR_OFC (1 << 2) +#define XREG_FPSCR_DZC (1 << 1) +#define XREG_FPSCR_IOC (1 << 0) + +/* MVFR0 bits */ +#define XREG_MVFR0_RMODE_BIT (28) +#define XREG_MVFR0_RMODE_MASK (0xF << XREG_MVFR0_RMODE_BIT) +#define XREG_MVFR0_SHORT_VEC_BIT (24) +#define XREG_MVFR0_SHORT_VEC_MASK (0xF << XREG_MVFR0_SHORT_VEC_BIT) +#define XREG_MVFR0_SQRT_BIT (20) +#define XREG_MVFR0_SQRT_MASK (0xF << XREG_MVFR0_SQRT_BIT) +#define XREG_MVFR0_DIVIDE_BIT (16) +#define XREG_MVFR0_DIVIDE_MASK (0xF << XREG_MVFR0_DIVIDE_BIT) +#define XREG_MVFR0_EXEC_TRAP_BIT (12) +#define XREG_MVFR0_EXEC_TRAP_MASK (0xF << XREG_MVFR0_EXEC_TRAP_BIT) +#define XREG_MVFR0_DP_BIT (8) +#define XREG_MVFR0_DP_MASK (0xF << XREG_MVFR0_DP_BIT) +#define XREG_MVFR0_SP_BIT (4) +#define XREG_MVFR0_SP_MASK (0xF << XREG_MVFR0_SP_BIT) +#define XREG_MVFR0_A_SIMD_BIT (0) +#define XREG_MVFR0_A_SIMD_MASK (0xF << MVFR0_A_SIMD_BIT) + +/* FPEXC bits */ +#define XREG_FPEXC_EX (1 << 31) +#define XREG_FPEXC_EN (1 << 30) +#define XREG_FPEXC_DEX (1 << 29) + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* XREG_CORTEXA9_H */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xstatus.h b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xstatus.h new file mode 100644 index 0000000..1a212bf --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xstatus.h @@ -0,0 +1,533 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xstatus.h +* +* @addtogroup common_status_codes Xilinx® software status codes +* +* The xstatus.h file contains the Xilinx® software status codes.These codes are +* used throughout the Xilinx device drivers. +* +* @{ +******************************************************************************/ + +#ifndef XSTATUS_H /* prevent circular inclusions */ +#define XSTATUS_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" + +/************************** Constant Definitions *****************************/ + +/*********************** Common statuses 0 - 500 *****************************/ +/** +@name Common Status Codes for All Device Drivers +@{ +*/ +#define XST_SUCCESS 0L +#define XST_FAILURE 1L +#define XST_DEVICE_NOT_FOUND 2L +#define XST_DEVICE_BLOCK_NOT_FOUND 3L +#define XST_INVALID_VERSION 4L +#define XST_DEVICE_IS_STARTED 5L +#define XST_DEVICE_IS_STOPPED 6L +#define XST_FIFO_ERROR 7L /*!< An error occurred during an + operation with a FIFO such as + an underrun or overrun, this + error requires the device to + be reset */ +#define XST_RESET_ERROR 8L /*!< An error occurred which requires + the device to be reset */ +#define XST_DMA_ERROR 9L /*!< A DMA error occurred, this error + typically requires the device + using the DMA to be reset */ +#define XST_NOT_POLLED 10L /*!< The device is not configured for + polled mode operation */ +#define XST_FIFO_NO_ROOM 11L /*!< A FIFO did not have room to put + the specified data into */ +#define XST_BUFFER_TOO_SMALL 12L /*!< The buffer is not large enough + to hold the expected data */ +#define XST_NO_DATA 13L /*!< There was no data available */ +#define XST_REGISTER_ERROR 14L /*!< A register did not contain the + expected value */ +#define XST_INVALID_PARAM 15L /*!< An invalid parameter was passed + into the function */ +#define XST_NOT_SGDMA 16L /*!< The device is not configured for + scatter-gather DMA operation */ +#define XST_LOOPBACK_ERROR 17L /*!< A loopback test failed */ +#define XST_NO_CALLBACK 18L /*!< A callback has not yet been + registered */ +#define XST_NO_FEATURE 19L /*!< Device is not configured with + the requested feature */ +#define XST_NOT_INTERRUPT 20L /*!< Device is not configured for + interrupt mode operation */ +#define XST_DEVICE_BUSY 21L /*!< Device is busy */ +#define XST_ERROR_COUNT_MAX 22L /*!< The error counters of a device + have maxed out */ +#define XST_IS_STARTED 23L /*!< Used when part of device is + already started i.e. + sub channel */ +#define XST_IS_STOPPED 24L /*!< Used when part of device is + already stopped i.e. + sub channel */ +#define XST_DATA_LOST 26L /*!< Driver defined error */ +#define XST_RECV_ERROR 27L /*!< Generic receive error */ +#define XST_SEND_ERROR 28L /*!< Generic transmit error */ +#define XST_NOT_ENABLED 29L /*!< A requested service is not + available because it has not + been enabled */ +#define XST_NO_ACCESS 30L /* Generic access error */ +/** @} */ +/***************** Utility Component statuses 401 - 500 *********************/ +/** +@name Utility Component Status Codes 401 - 500 +@{ +*/ +#define XST_MEMTEST_FAILED 401L /*!< Memory test failed */ + +/** @} */ +/***************** Common Components statuses 501 - 1000 *********************/ +/** +@name Packet Fifo Status Codes 501 - 510 +@{ +*/ +/********************* Packet Fifo statuses 501 - 510 ************************/ + +#define XST_PFIFO_LACK_OF_DATA 501L /*!< Not enough data in FIFO */ +#define XST_PFIFO_NO_ROOM 502L /*!< Not enough room in FIFO */ +#define XST_PFIFO_BAD_REG_VALUE 503L /*!< Self test, a register value + was invalid after reset */ +#define XST_PFIFO_ERROR 504L /*!< Generic packet FIFO error */ +#define XST_PFIFO_DEADLOCK 505L /*!< Packet FIFO is reporting + * empty and full simultaneously + */ +/** @} */ +/** +@name DMA Status Codes 511 - 530 +@{ +*/ +/************************** DMA statuses 511 - 530 ***************************/ + +#define XST_DMA_TRANSFER_ERROR 511L /*!< Self test, DMA transfer + failed */ +#define XST_DMA_RESET_REGISTER_ERROR 512L /*!< Self test, a register value + was invalid after reset */ +#define XST_DMA_SG_LIST_EMPTY 513L /*!< Scatter gather list contains + no buffer descriptors ready + to be processed */ +#define XST_DMA_SG_IS_STARTED 514L /*!< Scatter gather not stopped */ +#define XST_DMA_SG_IS_STOPPED 515L /*!< Scatter gather not running */ +#define XST_DMA_SG_LIST_FULL 517L /*!< All the buffer desciptors of + the scatter gather list are + being used */ +#define XST_DMA_SG_BD_LOCKED 518L /*!< The scatter gather buffer + descriptor which is to be + copied over in the scatter + list is locked */ +#define XST_DMA_SG_NOTHING_TO_COMMIT 519L /*!< No buffer descriptors have been + put into the scatter gather + list to be commited */ +#define XST_DMA_SG_COUNT_EXCEEDED 521L /*!< The packet count threshold + specified was larger than the + total # of buffer descriptors + in the scatter gather list */ +#define XST_DMA_SG_LIST_EXISTS 522L /*!< The scatter gather list has + already been created */ +#define XST_DMA_SG_NO_LIST 523L /*!< No scatter gather list has + been created */ +#define XST_DMA_SG_BD_NOT_COMMITTED 524L /*!< The buffer descriptor which was + being started was not committed + to the list */ +#define XST_DMA_SG_NO_DATA 525L /*!< The buffer descriptor to start + has already been used by the + hardware so it can't be reused + */ +#define XST_DMA_SG_LIST_ERROR 526L /*!< General purpose list access + error */ +#define XST_DMA_BD_ERROR 527L /*!< General buffer descriptor + error */ +/** @} */ +/** +@name IPIF Status Codes Codes 531 - 550 +@{ +*/ +/************************** IPIF statuses 531 - 550 ***************************/ + +#define XST_IPIF_REG_WIDTH_ERROR 531L /*!< An invalid register width + was passed into the function */ +#define XST_IPIF_RESET_REGISTER_ERROR 532L /*!< The value of a register at + reset was not valid */ +#define XST_IPIF_DEVICE_STATUS_ERROR 533L /*!< A write to the device interrupt + status register did not read + back correctly */ +#define XST_IPIF_DEVICE_ACK_ERROR 534L /*!< The device interrupt status + register did not reset when + acked */ +#define XST_IPIF_DEVICE_ENABLE_ERROR 535L /*!< The device interrupt enable + register was not updated when + other registers changed */ +#define XST_IPIF_IP_STATUS_ERROR 536L /*!< A write to the IP interrupt + status register did not read + back correctly */ +#define XST_IPIF_IP_ACK_ERROR 537L /*!< The IP interrupt status register + did not reset when acked */ +#define XST_IPIF_IP_ENABLE_ERROR 538L /*!< IP interrupt enable register was + not updated correctly when other + registers changed */ +#define XST_IPIF_DEVICE_PENDING_ERROR 539L /*!< The device interrupt pending + register did not indicate the + expected value */ +#define XST_IPIF_DEVICE_ID_ERROR 540L /*!< The device interrupt ID register + did not indicate the expected + value */ +#define XST_IPIF_ERROR 541L /*!< Generic ipif error */ +/** @} */ + +/****************** Device specific statuses 1001 - 4095 *********************/ +/** +@name Ethernet Status Codes 1001 - 1050 +@{ +*/ +/********************* Ethernet statuses 1001 - 1050 *************************/ + +#define XST_EMAC_MEMORY_SIZE_ERROR 1001L /*!< Memory space is not big enough + * to hold the minimum number of + * buffers or descriptors */ +#define XST_EMAC_MEMORY_ALLOC_ERROR 1002L /*!< Memory allocation failed */ +#define XST_EMAC_MII_READ_ERROR 1003L /*!< MII read error */ +#define XST_EMAC_MII_BUSY 1004L /*!< An MII operation is in progress */ +#define XST_EMAC_OUT_OF_BUFFERS 1005L /*!< Driver is out of buffers */ +#define XST_EMAC_PARSE_ERROR 1006L /*!< Invalid driver init string */ +#define XST_EMAC_COLLISION_ERROR 1007L /*!< Excess deferral or late + * collision on polled send */ +/** @} */ +/** +@name UART Status Codes 1051 - 1075 +@{ +*/ +/*********************** UART statuses 1051 - 1075 ***************************/ +#define XST_UART + +#define XST_UART_INIT_ERROR 1051L +#define XST_UART_START_ERROR 1052L +#define XST_UART_CONFIG_ERROR 1053L +#define XST_UART_TEST_FAIL 1054L +#define XST_UART_BAUD_ERROR 1055L +#define XST_UART_BAUD_RANGE 1056L + +/** @} */ +/** +@name IIC Status Codes 1076 - 1100 +@{ +*/ +/************************ IIC statuses 1076 - 1100 ***************************/ + +#define XST_IIC_SELFTEST_FAILED 1076 /*!< self test failed */ +#define XST_IIC_BUS_BUSY 1077 /*!< bus found busy */ +#define XST_IIC_GENERAL_CALL_ADDRESS 1078 /*!< mastersend attempted with */ + /* general call address */ +#define XST_IIC_STAND_REG_RESET_ERROR 1079 /*!< A non parameterizable reg */ + /* value after reset not valid */ +#define XST_IIC_TX_FIFO_REG_RESET_ERROR 1080 /*!< Tx fifo included in design */ + /* value after reset not valid */ +#define XST_IIC_RX_FIFO_REG_RESET_ERROR 1081 /*!< Rx fifo included in design */ + /* value after reset not valid */ +#define XST_IIC_TBA_REG_RESET_ERROR 1082 /*!< 10 bit addr incl in design */ + /* value after reset not valid */ +#define XST_IIC_CR_READBACK_ERROR 1083 /*!< Read of the control register */ + /* didn't return value written */ +#define XST_IIC_DTR_READBACK_ERROR 1084 /*!< Read of the data Tx reg */ + /* didn't return value written */ +#define XST_IIC_DRR_READBACK_ERROR 1085 /*!< Read of the data Receive reg */ + /* didn't return value written */ +#define XST_IIC_ADR_READBACK_ERROR 1086 /*!< Read of the data Tx reg */ + /* didn't return value written */ +#define XST_IIC_TBA_READBACK_ERROR 1087 /*!< Read of the 10 bit addr reg */ + /* didn't return written value */ +#define XST_IIC_NOT_SLAVE 1088 /*!< The device isn't a slave */ +#define XST_IIC_ARB_LOST 1089 /*!< Arbitration lost for master */ +/** @} */ +/** +@name ATMC Status Codes 1101 - 1125 +@{ +*/ +/*********************** ATMC statuses 1101 - 1125 ***************************/ + +#define XST_ATMC_ERROR_COUNT_MAX 1101L /*!< the error counters in the ATM + controller hit the max value + which requires the statistics + to be cleared */ +/** @} */ +/** +@name Flash Status Codes 1126 - 1150 +@{ +*/ +/*********************** Flash statuses 1126 - 1150 **************************/ + +#define XST_FLASH_BUSY 1126L /*!< Flash is erasing or programming + */ +#define XST_FLASH_READY 1127L /*!< Flash is ready for commands */ +#define XST_FLASH_ERROR 1128L /*!< Flash had detected an internal + error. Use XFlash_DeviceControl + to retrieve device specific codes + */ +#define XST_FLASH_ERASE_SUSPENDED 1129L /*!< Flash is in suspended erase state + */ +#define XST_FLASH_WRITE_SUSPENDED 1130L /*!< Flash is in suspended write state + */ +#define XST_FLASH_PART_NOT_SUPPORTED 1131L /*!< Flash type not supported by + driver */ +#define XST_FLASH_NOT_SUPPORTED 1132L /*!< Operation not supported */ +#define XST_FLASH_TOO_MANY_REGIONS 1133L /*!< Too many erase regions */ +#define XST_FLASH_TIMEOUT_ERROR 1134L /*!< Programming or erase operation + aborted due to a timeout */ +#define XST_FLASH_ADDRESS_ERROR 1135L /*!< Accessed flash outside its + addressible range */ +#define XST_FLASH_ALIGNMENT_ERROR 1136L /*!< Write alignment error */ +#define XST_FLASH_BLOCKING_CALL_ERROR 1137L /*!< Couldn't return immediately from + write/erase function with + XFL_NON_BLOCKING_WRITE/ERASE + option cleared */ +#define XST_FLASH_CFI_QUERY_ERROR 1138L /*!< Failed to query the device */ +/** @} */ +/** +@name SPI Status Codes 1151 - 1175 +@{ +*/ +/*********************** SPI statuses 1151 - 1175 ****************************/ + +#define XST_SPI_MODE_FAULT 1151 /*!< master was selected as slave */ +#define XST_SPI_TRANSFER_DONE 1152 /*!< data transfer is complete */ +#define XST_SPI_TRANSMIT_UNDERRUN 1153 /*!< slave underruns transmit register */ +#define XST_SPI_RECEIVE_OVERRUN 1154 /*!< device overruns receive register */ +#define XST_SPI_NO_SLAVE 1155 /*!< no slave has been selected yet */ +#define XST_SPI_TOO_MANY_SLAVES 1156 /*!< more than one slave is being + * selected */ +#define XST_SPI_NOT_MASTER 1157 /*!< operation is valid only as master */ +#define XST_SPI_SLAVE_ONLY 1158 /*!< device is configured as slave-only + */ +#define XST_SPI_SLAVE_MODE_FAULT 1159 /*!< slave was selected while disabled */ +#define XST_SPI_SLAVE_MODE 1160 /*!< device has been addressed as slave */ +#define XST_SPI_RECEIVE_NOT_EMPTY 1161 /*!< device received data in slave mode */ + +#define XST_SPI_COMMAND_ERROR 1162 /*!< unrecognised command - qspi only */ +#define XST_SPI_POLL_DONE 1163 /*!< controller completed polling the + device for status */ +/** @} */ +/** +@name OPB Arbiter Status Codes 1176 - 1200 +@{ +*/ +/********************** OPB Arbiter statuses 1176 - 1200 *********************/ + +#define XST_OPBARB_INVALID_PRIORITY 1176 /*!< the priority registers have either + * one master assigned to two or more + * priorities, or one master not + * assigned to any priority + */ +#define XST_OPBARB_NOT_SUSPENDED 1177 /*!< an attempt was made to modify the + * priority levels without first + * suspending the use of priority + * levels + */ +#define XST_OPBARB_PARK_NOT_ENABLED 1178 /*!< bus parking by id was enabled but + * bus parking was not enabled + */ +#define XST_OPBARB_NOT_FIXED_PRIORITY 1179 /*!< the arbiter must be in fixed + * priority mode to allow the + * priorities to be changed + */ +/** @} */ +/** +@name INTC Status Codes 1201 - 1225 +@{ +*/ +/************************ Intc statuses 1201 - 1225 **************************/ + +#define XST_INTC_FAIL_SELFTEST 1201 /*!< self test failed */ +#define XST_INTC_CONNECT_ERROR 1202 /*!< interrupt already in use */ +/** @} */ +/** +@name TmrCtr Status Codes 1226 - 1250 +@{ +*/ +/********************** TmrCtr statuses 1226 - 1250 **************************/ + +#define XST_TMRCTR_TIMER_FAILED 1226 /*!< self test failed */ +/** @} */ +/** +@name WdtTb Status Codes 1251 - 1275 +@{ +*/ +/********************** WdtTb statuses 1251 - 1275 ***************************/ + +#define XST_WDTTB_TIMER_FAILED 1251L +/** @} */ +/** +@name PlbArb status Codes 1276 - 1300 +@{ +*/ +/********************** PlbArb statuses 1276 - 1300 **************************/ + +#define XST_PLBARB_FAIL_SELFTEST 1276L +/** @} */ +/** +@name Plb2Opb Status Codes 1301 - 1325 +@{ +*/ +/********************** Plb2Opb statuses 1301 - 1325 *************************/ + +#define XST_PLB2OPB_FAIL_SELFTEST 1301L +/** @} */ +/** +@name Opb2Plb Status 1326 - 1350 +@{ +*/ +/********************** Opb2Plb statuses 1326 - 1350 *************************/ + +#define XST_OPB2PLB_FAIL_SELFTEST 1326L +/** @} */ +/** +@name SysAce Status Codes 1351 - 1360 +@{ +*/ +/********************** SysAce statuses 1351 - 1360 **************************/ + +#define XST_SYSACE_NO_LOCK 1351L /*!< No MPU lock has been granted */ +/** @} */ +/** +@name PCI Bridge Status Codes 1361 - 1375 +@{ +*/ +/********************** PCI Bridge statuses 1361 - 1375 **********************/ + +#define XST_PCI_INVALID_ADDRESS 1361L +/** @} */ +/** +@name FlexRay Constants 1400 - 1409 +@{ +*/ +/********************** FlexRay constants 1400 - 1409 *************************/ + +#define XST_FR_TX_ERROR 1400 +#define XST_FR_TX_BUSY 1401 +#define XST_FR_BUF_LOCKED 1402 +#define XST_FR_NO_BUF 1403 +/** @} */ +/** +@name USB constants 1410 - 1420 +@{ +*/ +/****************** USB constants 1410 - 1420 *******************************/ + +#define XST_USB_ALREADY_CONFIGURED 1410 +#define XST_USB_BUF_ALIGN_ERROR 1411 +#define XST_USB_NO_DESC_AVAILABLE 1412 +#define XST_USB_BUF_TOO_BIG 1413 +#define XST_USB_NO_BUF 1414 +/** @} */ +/** +@name HWICAP constants 1421 - 1429 +@{ +*/ +/****************** HWICAP constants 1421 - 1429 *****************************/ + +#define XST_HWICAP_WRITE_DONE 1421 + +/** @} */ +/** +@name AXI VDMA constants 1430 - 1440 +@{ +*/ +/****************** AXI VDMA constants 1430 - 1440 *****************************/ + +#define XST_VDMA_MISMATCH_ERROR 1430 +/** @} */ +/** +@name NAND Flash Status Codes 1441 - 1459 +@{ +*/ +/*********************** NAND Flash statuses 1441 - 1459 *********************/ + +#define XST_NAND_BUSY 1441L /*!< Flash is erasing or + * programming + */ +#define XST_NAND_READY 1442L /*!< Flash is ready for commands + */ +#define XST_NAND_ERROR 1443L /*!< Flash had detected an + * internal error. + */ +#define XST_NAND_PART_NOT_SUPPORTED 1444L /*!< Flash type not supported by + * driver + */ +#define XST_NAND_OPT_NOT_SUPPORTED 1445L /*!< Operation not supported + */ +#define XST_NAND_TIMEOUT_ERROR 1446L /*!< Programming or erase + * operation aborted due to a + * timeout + */ +#define XST_NAND_ADDRESS_ERROR 1447L /*!< Accessed flash outside its + * addressible range + */ +#define XST_NAND_ALIGNMENT_ERROR 1448L /*!< Write alignment error + */ +#define XST_NAND_PARAM_PAGE_ERROR 1449L /*!< Failed to read parameter + * page of the device + */ +#define XST_NAND_CACHE_ERROR 1450L /*!< Flash page buffer error + */ + +#define XST_NAND_WRITE_PROTECTED 1451L /*!< Flash is write protected + */ +/** @} */ + +/**************************** Type Definitions *******************************/ + +typedef s32 XStatus; + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** +* @} End of "addtogroup common_status_codes". +*/ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xtime_l.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xtime_l.c new file mode 100644 index 0000000..a687473 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xtime_l.c @@ -0,0 +1,118 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file xtime_l.c +* +* This file contains low level functions to get/set time from the Global Timer +* register in the ARM Cortex A9 MP core. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ------ -------- ---------------------------------------------------
+* 1.00a rp/sdm 11/03/09 Initial release.
+* 3.07a sgd    07/05/12 Upadted get/set time functions to make use Global Timer
+* 
+* +* @note None. +* +******************************************************************************/ +/***************************** Include Files *********************************/ + +#include "xtime_l.h" +#include "xpseudo_asm.h" +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_io.h" + +/***************** Macros (Inline Functions) Definitions *********************/ + +/**************************** Type Definitions *******************************/ + +/************************** Constant Definitions *****************************/ + +/************************** Variable Definitions *****************************/ + +/************************** Function Prototypes ******************************/ + +/****************************************************************************/ +/** +* @brief Set the time in the Global Timer Counter Register. +* +* @param Xtime_Global: 64-bit Value to be written to the Global Timer +* Counter Register. +* +* @return None. +* +* @note When this function is called by any one processor in a multi- +* processor environment, reference time will reset/lost for all +* processors. +* +****************************************************************************/ +void XTime_SetTime(XTime Xtime_Global) +{ + /* Disable Global Timer */ + Xil_Out32((u32)GLOBAL_TMR_BASEADDR + (u32)GTIMER_CONTROL_OFFSET, (u32)0x0); + + /* Updating Global Timer Counter Register */ + Xil_Out32((u32)GLOBAL_TMR_BASEADDR + (u32)GTIMER_COUNTER_LOWER_OFFSET, (u32)Xtime_Global); + Xil_Out32((u32)GLOBAL_TMR_BASEADDR + (u32)GTIMER_COUNTER_UPPER_OFFSET, + (u32)((u32)(Xtime_Global>>32U))); + + /* Enable Global Timer */ + Xil_Out32((u32)GLOBAL_TMR_BASEADDR + (u32)GTIMER_CONTROL_OFFSET, (u32)0x1); +} + +/****************************************************************************/ +/** +* @brief Get the time from the Global Timer Counter Register. +* +* @param Xtime_Global: Pointer to the 64-bit location which will be +* updated with the current timer value. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void XTime_GetTime(XTime *Xtime_Global) +{ + u32 low; + u32 high; + + /* Reading Global Timer Counter Register */ + do + { + high = Xil_In32(GLOBAL_TMR_BASEADDR + GTIMER_COUNTER_UPPER_OFFSET); + low = Xil_In32(GLOBAL_TMR_BASEADDR + GTIMER_COUNTER_LOWER_OFFSET); + } while(Xil_In32(GLOBAL_TMR_BASEADDR + GTIMER_COUNTER_UPPER_OFFSET) != high); + + *Xtime_Global = (((XTime) high) << 32U) | (XTime) low; +} diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xtime_l.h b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xtime_l.h new file mode 100644 index 0000000..12004e1 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/standalone_v7_0/src/xtime_l.h @@ -0,0 +1,104 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file xtime_l.h +* @addtogroup a9_time_apis Cortex A9 Time Functions +* +* xtime_l.h provides access to the 64-bit Global Counter in the PMU. This +* counter increases by one at every two processor cycles. These functions can +* be used to get/set time in the global timer. +* +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ------ -------- ---------------------------------------------------
+* 1.00a rp/sdm 11/03/09 Initial release.
+* 3.06a sgd    05/15/12 Upadted get/set time functions to make use Global Timer
+* 3.06a asa    06/17/12 Reverted back the changes to make use Global Timer.
+* 3.07a sgd    07/05/12 Upadted get/set time functions to make use Global Timer
+* 6.6   srm    10/23/17 Updated the macros to support user configurable sleep
+*						implementation
+* 6.8   aru  09/06/18 Removed compilation warnings for ARMCC toolchain.
+* 
+* +******************************************************************************/ + +#ifndef XTIME_H /* prevent circular inclusions */ +#define XTIME_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xparameters.h" + +/***************** Macros (Inline Functions) Definitions *********************/ + +/**************************** Type Definitions *******************************/ + +typedef u64 XTime; + +/************************** Constant Definitions *****************************/ +#define GLOBAL_TMR_BASEADDR XPAR_GLOBAL_TMR_BASEADDR +#define GTIMER_COUNTER_LOWER_OFFSET 0x00U +#define GTIMER_COUNTER_UPPER_OFFSET 0x04U +#define GTIMER_CONTROL_OFFSET 0x08U + +#if defined (SLEEP_TIMER_BASEADDR) +#define COUNTS_PER_SECOND (SLEEP_TIMER_FREQUENCY) +#else +/* Global Timer is always clocked at half of the CPU frequency */ +#define COUNTS_PER_SECOND (XPAR_CPU_CORTEXA9_CORE_CLOCK_FREQ_HZ /2) +#endif + +#if defined (XSLEEP_TIMER_IS_DEFAULT_TIMER) +#ifdef __GNUC__ +#pragma message ("For the sleep routines, Global timer is being used") +#endif +#endif +/************************** Variable Definitions *****************************/ + +/************************** Function Prototypes ******************************/ + +void XTime_SetTime(XTime Xtime_Global); +void XTime_GetTime(XTime *Xtime_Global); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* XTIME_H */ +/** +* @} End of "addtogroup a9_time_apis". +*/ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/uartps_v3_7/src/Makefile b/df_datalink/bsp/ps7_cortexa9_0/libsrc/uartps_v3_7/src/Makefile new file mode 100644 index 0000000..88b1e62 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/uartps_v3_7/src/Makefile @@ -0,0 +1,40 @@ +COMPILER= +ARCHIVER= +CP=cp +COMPILER_FLAGS= +EXTRA_COMPILER_FLAGS= +LIB=libxil.a + +CC_FLAGS = $(COMPILER_FLAGS) +ECC_FLAGS = $(EXTRA_COMPILER_FLAGS) + +RELEASEDIR=../../../lib +INCLUDEDIR=../../../include +INCLUDES=-I./. -I${INCLUDEDIR} + +OUTS = *.o + +LIBSOURCES:=*.c +INCLUDEFILES:=*.h + +OBJECTS = $(addsuffix .o, $(basename $(wildcard *.c))) + +libs: banner xuartps_libs clean + +%.o: %.c + ${COMPILER} $(CC_FLAGS) $(ECC_FLAGS) $(INCLUDES) -o $@ $< + +banner: + echo "Compiling uartps" + +xuartps_libs: ${OBJECTS} + $(ARCHIVER) -r ${RELEASEDIR}/${LIB} ${OBJECTS} + +.PHONY: include +include: xuartps_includes + +xuartps_includes: + ${CP} ${INCLUDEFILES} ${INCLUDEDIR} + +clean: + rm -rf ${OBJECTS} diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/uartps_v3_7/src/xuartps.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/uartps_v3_7/src/xuartps.c new file mode 100644 index 0000000..944afa1 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/uartps_v3_7/src/xuartps.c @@ -0,0 +1,642 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xuartps.c +* @addtogroup uartps_v3_5 +* @{ +* +* This file contains the implementation of the interface functions for XUartPs +* driver. Refer to the header file xuartps.h for more detailed information. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date	 Changes
+* ----- ------ -------- ----------------------------------------------
+* 1.00	drg/jz 01/13/10 First Release
+* 2.2   hk     06/23/14 SW reset of RX and TX should be done when changing
+*                       baud rate. CR# 804281.
+* 3.00  kvn    02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.1	kvn    04/10/15 Modified code for latest RTL changes.
+* 3.5	NK     09/26/17 Fix the RX Buffer Overflow issue.
+* 3.7   aru    08/17/18 Resolved MISRA-C mandatory violations.(CR#1007755)
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ + +#include "xstatus.h" +#include "xuartps.h" +#include "xil_io.h" + +/************************** Constant Definitions ****************************/ + +/* The following constant defines the amount of error that is allowed for + * a specified baud rate. This error is the difference between the actual + * baud rate that will be generated using the specified clock and the + * desired baud rate. + */ +#define XUARTPS_MAX_BAUD_ERROR_RATE 3U /* max % error allowed */ + +/**************************** Type Definitions ******************************/ + + +/***************** Macros (Inline Functions) Definitions ********************/ + + +/************************** Function Prototypes *****************************/ + +static void XUartPs_StubHandler(void *CallBackRef, u32 Event, + u32 ByteCount); + +u32 XUartPs_SendBuffer(XUartPs *InstancePtr); + +u32 XUartPs_ReceiveBuffer(XUartPs *InstancePtr); + +/************************** Variable Definitions ****************************/ + +/****************************************************************************/ +/** +* +* Initializes a specific XUartPs instance such that it is ready to be used. +* The data format of the device is setup for 8 data bits, 1 stop bit, and no +* parity by default. The baud rate is set to a default value specified by +* Config->DefaultBaudRate if set, otherwise it is set to 19.2K baud. The +* receive FIFO threshold is set for 8 bytes. The default operating mode of the +* driver is polled mode. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* @param Config is a reference to a structure containing information +* about a specific XUartPs driver. +* @param EffectiveAddr is the device base address in the virtual memory +* address space. The caller is responsible for keeping the address +* mapping from EffectiveAddr to the device physical base address +* unchanged once this function is invoked. Unexpected errors may +* occur if the address mapping changes after this function is +* called. If address translation is not used, pass in the physical +* address instead. +* +* @return +* +* - XST_SUCCESS if initialization was successful +* - XST_UART_BAUD_ERROR if the baud rate is not possible because +* the inputclock frequency is not divisible with an acceptable +* amount of error +* +* @note +* +* The default configuration for the UART after initialization is: +* +* - 19,200 bps or XPAR_DFT_BAUDRATE if defined +* - 8 data bits +* - 1 stop bit +* - no parity +* - FIFO's are enabled with a receive threshold of 8 bytes +* - The RX timeout is enabled with a timeout of 1 (4 char times) +* +* All interrupts are disabled. +* +*****************************************************************************/ +s32 XUartPs_CfgInitialize(XUartPs *InstancePtr, + XUartPs_Config * Config, u32 EffectiveAddr) +{ + s32 Status; + u32 ModeRegister; + u32 BaudRate; + + /* Assert validates the input arguments */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(Config != NULL); + + /* Setup the driver instance using passed in parameters */ + InstancePtr->Config.BaseAddress = EffectiveAddr; + InstancePtr->Config.InputClockHz = Config->InputClockHz; + InstancePtr->Config.ModemPinsConnected = Config->ModemPinsConnected; + + /* Initialize other instance data to default values */ + InstancePtr->Handler = (XUartPs_Handler)XUartPs_StubHandler; + + InstancePtr->SendBuffer.NextBytePtr = NULL; + InstancePtr->SendBuffer.RemainingBytes = 0U; + InstancePtr->SendBuffer.RequestedBytes = 0U; + + InstancePtr->ReceiveBuffer.NextBytePtr = NULL; + InstancePtr->ReceiveBuffer.RemainingBytes = 0U; + InstancePtr->ReceiveBuffer.RequestedBytes = 0U; + + /* Initialize the platform data */ + InstancePtr->Platform = XGetPlatform_Info(); + + InstancePtr->is_rxbs_error = 0U; + + /* Flag that the driver instance is ready to use */ + InstancePtr->IsReady = XIL_COMPONENT_IS_READY; + + /* + * Set the default baud rate here, can be changed prior to + * starting the device + */ + BaudRate = (u32)XUARTPS_DFT_BAUDRATE; + Status = XUartPs_SetBaudRate(InstancePtr, BaudRate); + if (Status != (s32)XST_SUCCESS) { + InstancePtr->IsReady = 0U; + } else { + + /* + * Set up the default data format: 8 bit data, 1 stop bit, no + * parity + */ + ModeRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress, + XUARTPS_MR_OFFSET); + + /* Mask off what's already there */ + ModeRegister &= (~((u32)XUARTPS_MR_CHARLEN_MASK | + (u32)XUARTPS_MR_STOPMODE_MASK | + (u32)XUARTPS_MR_PARITY_MASK)); + + /* Set the register value to the desired data format */ + ModeRegister |= ((u32)XUARTPS_MR_CHARLEN_8_BIT | + (u32)XUARTPS_MR_STOPMODE_1_BIT | + (u32)XUARTPS_MR_PARITY_NONE); + + /* Write the mode register out */ + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_MR_OFFSET, + ModeRegister); + + /* Set the RX FIFO trigger at 8 data bytes. */ + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, + XUARTPS_RXWM_OFFSET, 0x08U); + + /* Set the RX timeout to 1, which will be 4 character time */ + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, + XUARTPS_RXTOUT_OFFSET, 0x01U); + + /* Disable all interrupts, polled mode is the default */ + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_IDR_OFFSET, + XUARTPS_IXR_MASK); + + Status = XST_SUCCESS; + } + return Status; +} + +/****************************************************************************/ +/** +* +* This functions sends the specified buffer using the device in either +* polled or interrupt driven mode. This function is non-blocking, if the device +* is busy sending data, it will return and indicate zero bytes were sent. +* Otherwise, it fills the TX FIFO as much as it can, and return the number of +* bytes sent. +* +* In a polled mode, this function will only send as much data as TX FIFO can +* buffer. The application may need to call it repeatedly to send the entire +* buffer. +* +* In interrupt mode, this function will start sending the specified buffer, +* then the interrupt handler will continue sending data until the entire +* buffer has been sent. A callback function, as specified by the application, +* will be called to indicate the completion of sending. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* @param BufferPtr is pointer to a buffer of data to be sent. +* @param NumBytes contains the number of bytes to be sent. A value of +* zero will stop a previous send operation that is in progress +* in interrupt mode. Any data that was already put into the +* transmit FIFO will be sent. +* +* @return The number of bytes actually sent. +* +* @note +* +* The number of bytes is not asserted so that this function may be called with +* a value of zero to stop an operation that is already in progress. +*

+* +*****************************************************************************/ +u32 XUartPs_Send(XUartPs *InstancePtr, u8 *BufferPtr, + u32 NumBytes) +{ + u32 BytesSent; + + /* Asserts validate the input arguments */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(BufferPtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Disable the UART transmit interrupts to allow this call to stop a + * previous operation that may be interrupt driven. + */ + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_IDR_OFFSET, + (XUARTPS_IXR_TXEMPTY | XUARTPS_IXR_TXFULL)); + + /* Setup the buffer parameters */ + InstancePtr->SendBuffer.RequestedBytes = NumBytes; + InstancePtr->SendBuffer.RemainingBytes = NumBytes; + InstancePtr->SendBuffer.NextBytePtr = BufferPtr; + + /* + * Transmit interrupts will be enabled in XUartPs_SendBuffer(), after + * filling the TX FIFO. + */ + BytesSent = XUartPs_SendBuffer(InstancePtr); + + return BytesSent; +} + +/****************************************************************************/ +/** +* +* This function attempts to receive a specified number of bytes of data +* from the device and store it into the specified buffer. This function works +* for both polled or interrupt driven modes. It is non-blocking. +* +* In a polled mode, this function will only receive the data already in the +* RX FIFO. The application may need to call it repeatedly to receive the +* entire buffer. Polled mode is the default mode of operation for the device. +* +* In interrupt mode, this function will start the receiving, if not the entire +* buffer has been received, the interrupt handler will continue receiving data +* until the entire buffer has been received. A callback function, as specified +* by the application, will be called to indicate the completion of the +* receiving or error conditions. +* +* @param InstancePtr is a pointer to the XUartPs instance +* @param BufferPtr is pointer to buffer for data to be received into +* @param NumBytes is the number of bytes to be received. A value of zero +* will stop a previous receive operation that is in progress in +* interrupt mode. +* +* @return The number of bytes received. +* +* @note +* +* The number of bytes is not asserted so that this function may be called +* with a value of zero to stop an operation that is already in progress. +* +*****************************************************************************/ +u32 XUartPs_Recv(XUartPs *InstancePtr, + u8 *BufferPtr, u32 NumBytes) +{ + u32 ReceivedCount; + u32 ImrRegister; + + /* Assert validates the input arguments */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(BufferPtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Disable all the interrupts. + * This stops a previous operation that may be interrupt driven + */ + ImrRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress, + XUARTPS_IMR_OFFSET); + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_IDR_OFFSET, + XUARTPS_IXR_MASK); + + /* Setup the buffer parameters */ + InstancePtr->ReceiveBuffer.RequestedBytes = NumBytes; + InstancePtr->ReceiveBuffer.RemainingBytes = NumBytes; + InstancePtr->ReceiveBuffer.NextBytePtr = BufferPtr; + + /* Receive the data from the device */ + ReceivedCount = XUartPs_ReceiveBuffer(InstancePtr); + + /* Restore the interrupt state */ + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_IER_OFFSET, + ImrRegister); + + return ReceivedCount; +} + +/****************************************************************************/ +/* +* +* This function sends a buffer that has been previously specified by setting +* up the instance variables of the instance. This function is an internal +* function for the XUartPs driver such that it may be called from a shell +* function that sets up the buffer or from an interrupt handler. +* +* This function sends the specified buffer in either polled or interrupt +* driven modes. This function is non-blocking. +* +* In a polled mode, this function only sends as much data as the TX FIFO +* can buffer. The application may need to call it repeatedly to send the +* entire buffer. +* +* In interrupt mode, this function starts the sending of the buffer, if not +* the entire buffer has been sent, then the interrupt handler continues the +* sending until the entire buffer has been sent. A callback function, as +* specified by the application, will be called to indicate the completion of +* sending. +* +* @param InstancePtr is a pointer to the XUartPs instance +* +* @return The number of bytes actually sent +* +* @note None. +* +*****************************************************************************/ +u32 XUartPs_SendBuffer(XUartPs *InstancePtr) +{ + u32 SentCount = 0U; + u32 ImrRegister; + + /* + * If the TX FIFO is full, send nothing. + * Otherwise put bytes into the TX FIFO unil it is full, or all of the + * data has been put into the FIFO. + */ + while ((!XUartPs_IsTransmitFull(InstancePtr->Config.BaseAddress)) && + (InstancePtr->SendBuffer.RemainingBytes > SentCount)) { + + /* Fill the FIFO from the buffer */ + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, + XUARTPS_FIFO_OFFSET, + ((u32)InstancePtr->SendBuffer. + NextBytePtr[SentCount])); + + /* Increment the send count. */ + SentCount++; + } + + /* Update the buffer to reflect the bytes that were sent from it */ + InstancePtr->SendBuffer.NextBytePtr += SentCount; + InstancePtr->SendBuffer.RemainingBytes -= SentCount; + + /* + * If interrupts are enabled as indicated by the receive interrupt, then + * enable the TX FIFO empty interrupt, so further action can be taken + * for this sending. + */ + ImrRegister = + XUartPs_ReadReg(InstancePtr->Config.BaseAddress, + XUARTPS_IMR_OFFSET); + if (((ImrRegister & XUARTPS_IXR_RXFULL) != (u32)0) || + ((ImrRegister & XUARTPS_IXR_RXEMPTY) != (u32)0)|| + ((ImrRegister & XUARTPS_IXR_RXOVR) != (u32)0)) { + + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, + XUARTPS_IER_OFFSET, + ImrRegister | (u32)XUARTPS_IXR_TXEMPTY); + } + + return SentCount; +} + +/****************************************************************************/ +/* +* +* This function receives a buffer that has been previously specified by setting +* up the instance variables of the instance. This function is an internal +* function, and it may be called from a shell function that sets up the buffer +* or from an interrupt handler. +* +* This function attempts to receive a specified number of bytes from the +* device and store it into the specified buffer. This function works for +* either polled or interrupt driven modes. It is non-blocking. +* +* In polled mode, this function only receives as much data as in the RX FIFO. +* The application may need to call it repeatedly to receive the entire buffer. +* Polled mode is the default mode for the driver. +* +* In interrupt mode, this function starts the receiving, if not the entire +* buffer has been received, the interrupt handler will continue until the +* entire buffer has been received. A callback function, as specified by the +* application, will be called to indicate the completion of the receiving or +* error conditions. +* +* @param InstancePtr is a pointer to the XUartPs instance +* +* @return The number of bytes received. +* +* @note None. +* +*****************************************************************************/ +u32 XUartPs_ReceiveBuffer(XUartPs *InstancePtr) +{ + u32 CsrRegister; + u32 ReceivedCount = 0U; + u32 ByteStatusValue, EventData; + u32 Event; + + /* + * Read the Channel Status Register to determine if there is any data in + * the RX FIFO + */ + CsrRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress, + XUARTPS_SR_OFFSET); + + /* + * Loop until there is no more data in RX FIFO or the specified + * number of bytes has been received + */ + while((ReceivedCount < InstancePtr->ReceiveBuffer.RemainingBytes)&& + (((CsrRegister & XUARTPS_SR_RXEMPTY) == (u32)0))){ + + if (InstancePtr->is_rxbs_error) { + ByteStatusValue = XUartPs_ReadReg( + InstancePtr->Config.BaseAddress, + XUARTPS_RXBS_OFFSET); + if((ByteStatusValue & XUARTPS_RXBS_MASK)!= (u32)0) { + EventData = ByteStatusValue; + Event = XUARTPS_EVENT_PARE_FRAME_BRKE; + /* + * Call the application handler to indicate that there is a receive + * error or a break interrupt, if the application cares about the + * error it call a function to get the last errors. + */ + InstancePtr->Handler(InstancePtr->CallBackRef, + Event, EventData); + } + } + + InstancePtr->ReceiveBuffer.NextBytePtr[ReceivedCount] = + XUartPs_ReadReg(InstancePtr->Config. + BaseAddress, + XUARTPS_FIFO_OFFSET); + + ReceivedCount++; + + CsrRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress, + XUARTPS_SR_OFFSET); + } + InstancePtr->is_rxbs_error = 0; + /* + * Update the receive buffer to reflect the number of bytes just + * received + */ + if(InstancePtr->ReceiveBuffer.NextBytePtr != NULL){ + InstancePtr->ReceiveBuffer.NextBytePtr += ReceivedCount; + } + InstancePtr->ReceiveBuffer.RemainingBytes -= ReceivedCount; + + return ReceivedCount; +} + +/*****************************************************************************/ +/** +* +* Sets the baud rate for the device. Checks the input value for +* validity and also verifies that the requested rate can be configured to +* within the maximum error range specified by XUARTPS_MAX_BAUD_ERROR_RATE. +* If the provided rate is not possible, the current setting is unchanged. +* +* @param InstancePtr is a pointer to the XUartPs instance +* @param BaudRate to be set +* +* @return +* - XST_SUCCESS if everything configured as expected +* - XST_UART_BAUD_ERROR if the requested rate is not available +* because there was too much error +* +* @note None. +* +*****************************************************************************/ +s32 XUartPs_SetBaudRate(XUartPs *InstancePtr, u32 BaudRate) +{ + u32 IterBAUDDIV; /* Iterator for available baud divisor values */ + u32 BRGR_Value; /* Calculated value for baud rate generator */ + u32 CalcBaudRate; /* Calculated baud rate */ + u32 BaudError; /* Diff between calculated and requested baud rate */ + u32 Best_BRGR = 0U; /* Best value for baud rate generator */ + u8 Best_BAUDDIV = 0U; /* Best value for baud divisor */ + u32 Best_Error = 0xFFFFFFFFU; + u32 PercentError; + u32 ModeReg; + u32 InputClk; + + /* Asserts validate the input arguments */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(BaudRate <= (u32)XUARTPS_MAX_RATE); + Xil_AssertNonvoid(BaudRate >= (u32)XUARTPS_MIN_RATE); + + /* + * Make sure the baud rate is not impossilby large. + * Fastest possible baud rate is Input Clock / 2. + */ + if ((BaudRate * 2) > InstancePtr->Config.InputClockHz) { + return XST_UART_BAUD_ERROR; + } + /* Check whether the input clock is divided by 8 */ + ModeReg = XUartPs_ReadReg( InstancePtr->Config.BaseAddress, + XUARTPS_MR_OFFSET); + + InputClk = InstancePtr->Config.InputClockHz; + if(ModeReg & XUARTPS_MR_CLKSEL) { + InputClk = InstancePtr->Config.InputClockHz / 8; + } + + /* + * Determine the Baud divider. It can be 4to 254. + * Loop through all possible combinations + */ + for (IterBAUDDIV = 4; IterBAUDDIV < 255; IterBAUDDIV++) { + + /* Calculate the value for BRGR register */ + BRGR_Value = InputClk / (BaudRate * (IterBAUDDIV + 1)); + + /* Calculate the baud rate from the BRGR value */ + CalcBaudRate = InputClk/ (BRGR_Value * (IterBAUDDIV + 1)); + + /* Avoid unsigned integer underflow */ + if (BaudRate > CalcBaudRate) { + BaudError = BaudRate - CalcBaudRate; + } + else { + BaudError = CalcBaudRate - BaudRate; + } + + /* Find the calculated baud rate closest to requested baud rate. */ + if (Best_Error > BaudError) { + + Best_BRGR = BRGR_Value; + Best_BAUDDIV = IterBAUDDIV; + Best_Error = BaudError; + } + } + + /* Make sure the best error is not too large. */ + PercentError = (Best_Error * 100) / BaudRate; + if (XUARTPS_MAX_BAUD_ERROR_RATE < PercentError) { + return XST_UART_BAUD_ERROR; + } + + /* Disable TX and RX to avoid glitches when setting the baud rate. */ + XUartPs_DisableUart(InstancePtr); + + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, + XUARTPS_BAUDGEN_OFFSET, Best_BRGR); + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, + XUARTPS_BAUDDIV_OFFSET, Best_BAUDDIV); + + /* RX and TX SW reset */ + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_CR_OFFSET, + XUARTPS_CR_TXRST | XUARTPS_CR_RXRST); + + /* Enable device */ + XUartPs_EnableUart(InstancePtr); + + InstancePtr->BaudRate = BaudRate; + + return XST_SUCCESS; + +} + +/****************************************************************************/ +/** +* +* This function is a stub handler that is the default handler such that if the +* application has not set the handler when interrupts are enabled, this +* function will be called. +* +* @param CallBackRef is unused by this function. +* @param Event is unused by this function. +* @param ByteCount is unused by this function. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +static void XUartPs_StubHandler(void *CallBackRef, u32 Event, + u32 ByteCount) +{ + (void) CallBackRef; + (void) Event; + (void) ByteCount; + /* Assert occurs always since this is a stub and should never be called */ + Xil_AssertVoidAlways(); +} +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/uartps_v3_7/src/xuartps.h b/df_datalink/bsp/ps7_cortexa9_0/libsrc/uartps_v3_7/src/xuartps.h new file mode 100644 index 0000000..c6c2a0a --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/uartps_v3_7/src/xuartps.h @@ -0,0 +1,517 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xuartps.h +* @addtogroup uartps_v3_5 +* @{ +* @details +* +* This driver supports the following features: +* +* - Dynamic data format (baud rate, data bits, stop bits, parity) +* - Polled mode +* - Interrupt driven mode +* - Transmit and receive FIFOs (32 byte FIFO depth) +* - Access to the external modem control lines +* +* Initialization & Configuration +* +* The XUartPs_Config structure is used by the driver to configure itself. +* Fields inside this structure are properties of XUartPs based on its hardware +* build. +* +* To support multiple runtime loading and initialization strategies employed +* by various operating systems, the driver instance can be initialized in the +* following way: +* +* - XUartPs_CfgInitialize(InstancePtr, CfgPtr, EffectiveAddr) - Uses a +* configuration structure provided by the caller. If running in a system +* with address translation, the parameter EffectiveAddr should be the +* virtual address. +* +* Baud Rate +* +* The UART has an internal baud rate generator, which furnishes the baud rate +* clock for both the receiver and the transmitter. Ther input clock frequency +* can be either the master clock or the master clock divided by 8, configured +* through the mode register. +* +* Accompanied with the baud rate divider register, the baud rate is determined +* by: +*
+*	baud_rate = input_clock / (bgen * (bdiv + 1)
+* 
+* where bgen is the value of the baud rate generator, and bdiv is the value of +* baud rate divider. +* +* Interrupts +* +* The FIFOs are not flushed when the driver is initialized, but a function is +* provided to allow the user to reset the FIFOs if desired. +* +* The driver defaults to no interrupts at initialization such that interrupts +* must be enabled if desired. An interrupt is generated for one of the +* following conditions. +* +* - A change in the modem signals +* - Data in the receive FIFO for a configuable time without receiver activity +* - A parity error +* - A framing error +* - An overrun error +* - Transmit FIFO is full +* - Transmit FIFO is empty +* - Receive FIFO is full +* - Receive FIFO is empty +* - Data in the receive FIFO equal to the receive threshold +* +* The application can control which interrupts are enabled using the +* XUartPs_SetInterruptMask() function. +* +* In order to use interrupts, it is necessary for the user to connect the +* driver interrupt handler, XUartPs_InterruptHandler(), to the interrupt +* system of the application. A separate handler should be provided by the +* application to communicate with the interrupt system, and conduct +* application specific interrupt handling. An application registers its own +* handler through the XUartPs_SetHandler() function. +* +* Data Transfer +* +* The functions, XUartPs_Send() and XUartPs_Recv(), are provided in the +* driver to allow data to be sent and received. They can be used in either +* polled or interrupt mode. +* +* @note +* +* The default configuration for the UART after initialization is: +* +* - 9,600 bps or XPAR_DFT_BAUDRATE if defined +* - 8 data bits +* - 1 stop bit +* - no parity +* - FIFO's are enabled with a receive threshold of 8 bytes +* - The RX timeout is enabled with a timeout of 1 (4 char times) +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date	Changes
+* ----- ------ -------- ----------------------------------------------
+* 1.00a	drg/jz 01/12/10 First Release
+* 1.00a sdm    09/27/11 Fixed compiler warnings and also a bug
+*		        in XUartPs_SetFlowDelay where the value was not
+*			being written to the register.
+* 1.01a sdm    12/20/11 Removed the InputClockHz parameter from the XUartPs
+*			instance structure and the driver is updated to use
+*			InputClockHz parameter from the XUartPs_Config config
+*			structure.
+*			Added a parameter to XUartPs_Config structure which
+*			specifies whether the user has selected Modem pins
+*			to be connected to MIO or FMIO.
+*			Added the tcl file to generate the xparameters.h
+* 1.02a sg     05/16/12	Changed XUARTPS_RXWM_MASK to 0x3F for CR 652540 fix.
+* 1.03a sg     07/16/12 Updated XUARTPS_FORMAT_7_BITS and XUARTPS_FORMAT_6_BITS
+*			with the correct values for CR 666724
+* 			Added defines for XUARTPS_IXR_TOVR,  XUARTPS_IXR_TNFUL
+*			and XUARTPS_IXR_TTRIG.
+*			Modified the name of these defines
+*			XUARTPS_MEDEMSR_DCDX to XUARTPS_MODEMSR_DDCD
+*			XUARTPS_MEDEMSR_RIX to XUARTPS_MODEMSR_TERI
+*			XUARTPS_MEDEMSR_DSRX to XUARTPS_MODEMSR_DDSR
+*			XUARTPS_MEDEMSR_CTSX to XUARTPS_MODEMSR_DCTS
+* 1.05a hk     08/22/13 Added API for uart reset and related
+*			constant definitions.
+* 2.0   hk      03/07/14 Version number revised.
+* 2.1   hk     04/16/14 Change XUARTPS_MAX_RATE to 921600. CR# 780625.
+* 2.2   hk     06/23/14 SW reset of RX and TX should be done when changing
+*                       baud rate. CR# 804281.
+* 3.0   vm     12/09/14 Modified source code according to misrac guideline.
+*			Support for Zynq Ultrascale Mp added.
+* 3.1	kvn    04/10/15 Modified code for latest RTL changes. Also added
+*						platform variable in driver instance structure.
+* 3.1   adk   14/03/16  Include interrupt examples in the peripheral test when
+*			uart is connected to a valid interrupt controller CR#946803.
+* 3.2   rk     07/20/16 Modified the logic for transmission break bit set
+* 3.4   ms     01/23/17 Added xil_printf statement in main function for all
+*                       examples to ensure that "Successfully ran" and "Failed"
+*                       strings are available in all examples. This is a fix
+*                       for CR-965028.
+*       ms     03/17/17 Added readme.txt file in examples folder for doxygen
+*                       generation.
+* 3.6   ms     02/16/18 Updates the flow control mode offset value in modem
+*                       control register.
+* 3.7   aru    08/17/18 Resolved MISRA-C:2012 compliance mandatory violations.
+*
+* 
+* +*****************************************************************************/ + +#ifndef XUARTPS_H /* prevent circular inclusions */ +#define XUARTPS_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files ********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xstatus.h" +#include "xuartps_hw.h" +#include "xplatform_info.h" + +/************************** Constant Definitions ****************************/ + +/* + * The following constants indicate the max and min baud rates and these + * numbers are based only on the testing that has been done. The hardware + * is capable of other baud rates. + */ +#define XUARTPS_MAX_RATE 921600U +#define XUARTPS_MIN_RATE 110U + +#define XUARTPS_DFT_BAUDRATE 115200U /* Default baud rate */ + +/** @name Configuration options + * @{ + */ +/** + * These constants specify the options that may be set or retrieved + * with the driver, each is a unique bit mask such that multiple options + * may be specified. These constants indicate the available options + * in active state. + * + */ + +#define XUARTPS_OPTION_SET_BREAK 0x0080U /**< Starts break transmission */ +#define XUARTPS_OPTION_STOP_BREAK 0x0040U /**< Stops break transmission */ +#define XUARTPS_OPTION_RESET_TMOUT 0x0020U /**< Reset the receive timeout */ +#define XUARTPS_OPTION_RESET_TX 0x0010U /**< Reset the transmitter */ +#define XUARTPS_OPTION_RESET_RX 0x0008U /**< Reset the receiver */ +#define XUARTPS_OPTION_ASSERT_RTS 0x0004U /**< Assert the RTS bit */ +#define XUARTPS_OPTION_ASSERT_DTR 0x0002U /**< Assert the DTR bit */ +#define XUARTPS_OPTION_SET_FCM 0x0001U /**< Turn on flow control mode */ +/*@}*/ + + +/** @name Channel Operational Mode + * + * The UART can operate in one of four modes: Normal, Local Loopback, Remote + * Loopback, or automatic echo. + * + * @{ + */ + +#define XUARTPS_OPER_MODE_NORMAL (u8)0x00U /**< Normal Mode */ +#define XUARTPS_OPER_MODE_AUTO_ECHO (u8)0x01U /**< Auto Echo Mode */ +#define XUARTPS_OPER_MODE_LOCAL_LOOP (u8)0x02U /**< Local Loopback Mode */ +#define XUARTPS_OPER_MODE_REMOTE_LOOP (u8)0x03U /**< Remote Loopback Mode */ + +/* @} */ + +/** @name Data format values + * + * These constants specify the data format that the driver supports. + * The data format includes the number of data bits, the number of stop + * bits and parity. + * + * @{ + */ +#define XUARTPS_FORMAT_8_BITS 0U /**< 8 data bits */ +#define XUARTPS_FORMAT_7_BITS 2U /**< 7 data bits */ +#define XUARTPS_FORMAT_6_BITS 3U /**< 6 data bits */ + +#define XUARTPS_FORMAT_NO_PARITY 4U /**< No parity */ +#define XUARTPS_FORMAT_MARK_PARITY 3U /**< Mark parity */ +#define XUARTPS_FORMAT_SPACE_PARITY 2U /**< parity */ +#define XUARTPS_FORMAT_ODD_PARITY 1U /**< Odd parity */ +#define XUARTPS_FORMAT_EVEN_PARITY 0U /**< Even parity */ + +#define XUARTPS_FORMAT_2_STOP_BIT 2U /**< 2 stop bits */ +#define XUARTPS_FORMAT_1_5_STOP_BIT 1U /**< 1.5 stop bits */ +#define XUARTPS_FORMAT_1_STOP_BIT 0U /**< 1 stop bit */ +/*@}*/ + +/** @name Callback events + * + * These constants specify the handler events that an application can handle + * using its specific handler function. Note that these constants are not bit + * mask, so only one event can be passed to an application at a time. + * + * @{ + */ +#define XUARTPS_EVENT_RECV_DATA 1U /**< Data receiving done */ +#define XUARTPS_EVENT_RECV_TOUT 2U /**< A receive timeout occurred */ +#define XUARTPS_EVENT_SENT_DATA 3U /**< Data transmission done */ +#define XUARTPS_EVENT_RECV_ERROR 4U /**< A receive error detected */ +#define XUARTPS_EVENT_MODEM 5U /**< Modem status changed */ +#define XUARTPS_EVENT_PARE_FRAME_BRKE 6U /**< A receive parity, frame, break + * error detected */ +#define XUARTPS_EVENT_RECV_ORERR 7U /**< A receive overrun error detected */ +/*@}*/ + + +/**************************** Type Definitions ******************************/ + +/** + * This typedef contains configuration information for the device. + */ +typedef struct { + u16 DeviceId; /**< Unique ID of device */ + u32 BaseAddress; /**< Base address of device (IPIF) */ + u32 InputClockHz;/**< Input clock frequency */ + s32 ModemPinsConnected; /** Specifies whether modem pins are connected + * to MIO or FMIO */ +} XUartPs_Config; + +/* Keep track of state information about a data buffer in the interrupt mode. */ +typedef struct { + u8 *NextBytePtr; + u32 RequestedBytes; + u32 RemainingBytes; +} XUartPsBuffer; + +/** + * Keep track of data format setting of a device. + */ +typedef struct { + u32 BaudRate; /**< In bps, ie 1200 */ + u32 DataBits; /**< Number of data bits */ + u32 Parity; /**< Parity */ + u8 StopBits; /**< Number of stop bits */ +} XUartPsFormat; + +/******************************************************************************/ +/** + * This data type defines a handler that an application defines to communicate + * with interrupt system to retrieve state information about an application. + * + * @param CallBackRef is a callback reference passed in by the upper layer + * when setting the handler, and is passed back to the upper layer + * when the handler is called. It is used to find the device driver + * instance. + * @param Event contains one of the event constants indicating events that + * have occurred. + * @param EventData contains the number of bytes sent or received at the + * time of the call for send and receive events and contains the + * modem status for modem events. + * + ******************************************************************************/ +typedef void (*XUartPs_Handler) (void *CallBackRef, u32 Event, + u32 EventData); + +/** + * The XUartPs driver instance data structure. A pointer to an instance data + * structure is passed around by functions to refer to a specific driver + * instance. + */ +typedef struct { + XUartPs_Config Config; /* Configuration data structure */ + u32 InputClockHz; /* Input clock frequency */ + u32 IsReady; /* Device is initialized and ready */ + u32 BaudRate; /* Current baud rate */ + + XUartPsBuffer SendBuffer; + XUartPsBuffer ReceiveBuffer; + + XUartPs_Handler Handler; + void *CallBackRef; /* Callback reference for event handler */ + u32 Platform; + u8 is_rxbs_error; +} XUartPs; + + +/***************** Macros (Inline Functions) Definitions ********************/ + +/****************************************************************************/ +/** +* Get the UART Channel Status Register. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* +* @return The value read from the register. +* +* @note C-Style signature: +* u16 XUartPs_GetChannelStatus(XUartPs *InstancePtr) +* +******************************************************************************/ +#define XUartPs_GetChannelStatus(InstancePtr) \ + Xil_In32(((InstancePtr)->Config.BaseAddress) + (u32)XUARTPS_SR_OFFSET) + +/****************************************************************************/ +/** +* Get the UART Mode Control Register. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* +* @return The value read from the register. +* +* @note C-Style signature: +* u32 XUartPs_GetControl(XUartPs *InstancePtr) +* +******************************************************************************/ +#define XUartPs_GetModeControl(InstancePtr) \ + Xil_In32(((InstancePtr)->Config.BaseAddress) + (u32)XUARTPS_CR_OFFSET) + +/****************************************************************************/ +/** +* Set the UART Mode Control Register. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* @param RegisterValue is the value to be written to the register. +* +* @return None. +* +* @note C-Style signature: +* void XUartPs_SetModeControl(XUartPs *InstancePtr, u16 RegisterValue) +* +******************************************************************************/ +#define XUartPs_SetModeControl(InstancePtr, RegisterValue) \ + Xil_Out32(((InstancePtr)->Config.BaseAddress) + (u32)XUARTPS_CR_OFFSET, \ + (u32)(RegisterValue)) + +/****************************************************************************/ +/** +* Enable the transmitter and receiver of the UART. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* +* @return None. +* +* @note C-Style signature: +* void XUartPs_EnableUart(XUartPs *InstancePtr) +* +******************************************************************************/ +#define XUartPs_EnableUart(InstancePtr) \ + Xil_Out32(((InstancePtr)->Config.BaseAddress + (u32)XUARTPS_CR_OFFSET), \ + ((Xil_In32((InstancePtr)->Config.BaseAddress + (u32)XUARTPS_CR_OFFSET) & \ + (u32)(~XUARTPS_CR_EN_DIS_MASK)) | ((u32)XUARTPS_CR_RX_EN | (u32)XUARTPS_CR_TX_EN))) + +/****************************************************************************/ +/** +* Disable the transmitter and receiver of the UART. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* +* @return None. +* +* @note C-Style signature: +* void XUartPs_DisableUart(XUartPs *InstancePtr) +* +******************************************************************************/ +#define XUartPs_DisableUart(InstancePtr) \ + Xil_Out32(((InstancePtr)->Config.BaseAddress + (u32)XUARTPS_CR_OFFSET), \ + (((Xil_In32((InstancePtr)->Config.BaseAddress + (u32)XUARTPS_CR_OFFSET)) & \ + (u32)(~XUARTPS_CR_EN_DIS_MASK)) | ((u32)XUARTPS_CR_RX_DIS | (u32)XUARTPS_CR_TX_DIS))) + +/****************************************************************************/ +/** +* Determine if the transmitter FIFO is empty. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* +* @return +* - TRUE if a byte can be sent +* - FALSE if the Transmitter Fifo is not empty +* +* @note C-Style signature: +* u32 XUartPs_IsTransmitEmpty(XUartPs InstancePtr) +* +******************************************************************************/ +#define XUartPs_IsTransmitEmpty(InstancePtr) \ + ((Xil_In32(((InstancePtr)->Config.BaseAddress) + (u32)XUARTPS_SR_OFFSET) & \ + (u32)XUARTPS_SR_TXEMPTY) == (u32)XUARTPS_SR_TXEMPTY) + + +/************************** Function Prototypes *****************************/ + +/* Static lookup function implemented in xuartps_sinit.c */ +XUartPs_Config *XUartPs_LookupConfig(u16 DeviceId); + +/* Interface functions implemented in xuartps.c */ +s32 XUartPs_CfgInitialize(XUartPs *InstancePtr, + XUartPs_Config * Config, u32 EffectiveAddr); + +u32 XUartPs_Send(XUartPs *InstancePtr,u8 *BufferPtr, + u32 NumBytes); + +u32 XUartPs_Recv(XUartPs *InstancePtr,u8 *BufferPtr, + u32 NumBytes); + +s32 XUartPs_SetBaudRate(XUartPs *InstancePtr, u32 BaudRate); + +/* Options functions in xuartps_options.c */ +void XUartPs_SetOptions(XUartPs *InstancePtr, u16 Options); + +u16 XUartPs_GetOptions(XUartPs *InstancePtr); + +void XUartPs_SetFifoThreshold(XUartPs *InstancePtr, u8 TriggerLevel); + +u8 XUartPs_GetFifoThreshold(XUartPs *InstancePtr); + +u16 XUartPs_GetModemStatus(XUartPs *InstancePtr); + +u32 XUartPs_IsSending(XUartPs *InstancePtr); + +u8 XUartPs_GetOperMode(XUartPs *InstancePtr); + +void XUartPs_SetOperMode(XUartPs *InstancePtr, u8 OperationMode); + +u8 XUartPs_GetFlowDelay(XUartPs *InstancePtr); + +void XUartPs_SetFlowDelay(XUartPs *InstancePtr, u8 FlowDelayValue); + +u8 XUartPs_GetRecvTimeout(XUartPs *InstancePtr); + +void XUartPs_SetRecvTimeout(XUartPs *InstancePtr, u8 RecvTimeout); + +s32 XUartPs_SetDataFormat(XUartPs *InstancePtr, XUartPsFormat * FormatPtr); + +void XUartPs_GetDataFormat(XUartPs *InstancePtr, XUartPsFormat * FormatPtr); + +/* interrupt functions in xuartps_intr.c */ +u32 XUartPs_GetInterruptMask(XUartPs *InstancePtr); + +void XUartPs_SetInterruptMask(XUartPs *InstancePtr, u32 Mask); + +void XUartPs_InterruptHandler(XUartPs *InstancePtr); + +void XUartPs_SetHandler(XUartPs *InstancePtr, XUartPs_Handler FuncPtr, + void *CallBackRef); + +/* self-test functions in xuartps_selftest.c */ +s32 XUartPs_SelfTest(XUartPs *InstancePtr); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/uartps_v3_7/src/xuartps_g.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/uartps_v3_7/src/xuartps_g.c new file mode 100644 index 0000000..023fcde --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/uartps_v3_7/src/xuartps_g.c @@ -0,0 +1,53 @@ + +/******************************************************************* +* +* CAUTION: This file is automatically generated by HSI. +* Version: 2019.1.3 +* DO NOT EDIT. +* +* Copyright (C) 2010-2023 Xilinx, Inc. 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 +*XILINX 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. +* +*Except as contained in this notice, the name of the Xilinx shall not be used +*in advertising or otherwise to promote the sale, use or other dealings in +*this Software without prior written authorization from Xilinx. +* + +* +* Description: Driver configuration +* +*******************************************************************/ + +#include "xparameters.h" +#include "xuartps.h" + +/* +* The configuration table for devices +*/ + +XUartPs_Config XUartPs_ConfigTable[XPAR_XUARTPS_NUM_INSTANCES] = +{ + { + XPAR_PS7_UART_0_DEVICE_ID, + XPAR_PS7_UART_0_BASEADDR, + XPAR_PS7_UART_0_UART_CLK_FREQ_HZ, + XPAR_PS7_UART_0_HAS_MODEM + } +}; + + diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/uartps_v3_7/src/xuartps_hw.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/uartps_v3_7/src/xuartps_hw.c new file mode 100644 index 0000000..11462ba --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/uartps_v3_7/src/xuartps_hw.c @@ -0,0 +1,176 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xuartps_hw.c +* @addtogroup uartps_v3_5 +* @{ +* +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date	Changes
+* ----- ------ -------- ----------------------------------------------
+* 1.00	drg/jz 01/12/10 First Release
+* 1.05a hk     08/22/13 Added reset function
+* 3.00  kvn    02/13/15 Modified code for MISRA-C:2012 compliance.
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ +#include "xuartps_hw.h" + +/************************** Constant Definitions ****************************/ + + +/***************** Macros (Inline Functions) Definitions ********************/ + + +/************************** Function Prototypes ******************************/ + + +/************************** Variable Definitions *****************************/ + +/****************************************************************************/ +/** +* +* This function sends one byte using the device. This function operates in +* polled mode and blocks until the data has been put into the TX FIFO register. +* +* @param BaseAddress contains the base address of the device. +* @param Data contains the byte to be sent. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XUartPs_SendByte(u32 BaseAddress, u8 Data) +{ + /* Wait until there is space in TX FIFO */ + while (XUartPs_IsTransmitFull(BaseAddress)) { + ; + } + + /* Write the byte into the TX FIFO */ + XUartPs_WriteReg(BaseAddress, XUARTPS_FIFO_OFFSET, (u32)Data); +} + +/****************************************************************************/ +/** +* +* This function receives a byte from the device. It operates in polled mode +* and blocks until a byte has received. +* +* @param BaseAddress contains the base address of the device. +* +* @return The data byte received. +* +* @note None. +* +*****************************************************************************/ +u8 XUartPs_RecvByte(u32 BaseAddress) +{ + u32 RecievedByte; + /* Wait until there is data */ + while (!XUartPs_IsReceiveData(BaseAddress)) { + ; + } + RecievedByte = XUartPs_ReadReg(BaseAddress, XUARTPS_FIFO_OFFSET); + /* Return the byte received */ + return (u8)RecievedByte; +} + +/****************************************************************************/ +/** +* +* This function resets UART +* +* @param BaseAddress contains the base address of the device. +* +* @return None +* +* @note None. +* +*****************************************************************************/ +void XUartPs_ResetHw(u32 BaseAddress) +{ + + /* Disable interrupts */ + XUartPs_WriteReg(BaseAddress, XUARTPS_IDR_OFFSET, XUARTPS_IXR_MASK); + + /* Disable receive and transmit */ + XUartPs_WriteReg(BaseAddress, XUARTPS_CR_OFFSET, + ((u32)XUARTPS_CR_RX_DIS | (u32)XUARTPS_CR_TX_DIS)); + + /* + * Software reset of receive and transmit + * This clears the FIFO. + */ + XUartPs_WriteReg(BaseAddress, XUARTPS_CR_OFFSET, + ((u32)XUARTPS_CR_TXRST | (u32)XUARTPS_CR_RXRST)); + + /* Clear status flags - SW reset wont clear sticky flags. */ + XUartPs_WriteReg(BaseAddress, XUARTPS_ISR_OFFSET, XUARTPS_IXR_MASK); + + /* + * Mode register reset value : All zeroes + * Normal mode, even parity, 1 stop bit + */ + XUartPs_WriteReg(BaseAddress, XUARTPS_MR_OFFSET, + XUARTPS_MR_CHMODE_NORM); + + /* Rx and TX trigger register reset values */ + XUartPs_WriteReg(BaseAddress, XUARTPS_RXWM_OFFSET, + XUARTPS_RXWM_RESET_VAL); + XUartPs_WriteReg(BaseAddress, XUARTPS_TXWM_OFFSET, + XUARTPS_TXWM_RESET_VAL); + + /* Rx timeout disabled by default */ + XUartPs_WriteReg(BaseAddress, XUARTPS_RXTOUT_OFFSET, + XUARTPS_RXTOUT_DISABLE); + + /* Baud rate generator and dividor reset values */ + XUartPs_WriteReg(BaseAddress, XUARTPS_BAUDGEN_OFFSET, + XUARTPS_BAUDGEN_RESET_VAL); + XUartPs_WriteReg(BaseAddress, XUARTPS_BAUDDIV_OFFSET, + XUARTPS_BAUDDIV_RESET_VAL); + + /* + * Control register reset value - + * RX and TX are disable by default + */ + XUartPs_WriteReg(BaseAddress, XUARTPS_CR_OFFSET, + ((u32)XUARTPS_CR_RX_DIS | (u32)XUARTPS_CR_TX_DIS | + (u32)XUARTPS_CR_STOPBRK)); + +} +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/uartps_v3_7/src/xuartps_hw.h b/df_datalink/bsp/ps7_cortexa9_0/libsrc/uartps_v3_7/src/xuartps_hw.h new file mode 100644 index 0000000..8c46ecf --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/uartps_v3_7/src/xuartps_hw.h @@ -0,0 +1,447 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2017 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xuartps_hw.h +* @addtogroup uartps_v3_5 +* @{ +* +* This header file contains the hardware interface of an XUartPs device. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date	Changes
+* ----- ------ -------- ----------------------------------------------
+* 1.00	drg/jz 01/12/10 First Release
+* 1.03a sg     09/04/12 Added defines for XUARTPS_IXR_TOVR,  XUARTPS_IXR_TNFUL
+*			and XUARTPS_IXR_TTRIG.
+*			Modified the names of these defines
+*			XUARTPS_MEDEMSR_DCDX to XUARTPS_MODEMSR_DDCD
+*			XUARTPS_MEDEMSR_RIX to XUARTPS_MODEMSR_TERI
+*			XUARTPS_MEDEMSR_DSRX to XUARTPS_MODEMSR_DDSR
+*			XUARTPS_MEDEMSR_CTSX to XUARTPS_MODEMSR_DCTS
+* 1.05a hk     08/22/13 Added prototype for uart reset and related
+*			constant definitions.
+* 3.00  kvn    02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.1	kvn    04/10/15 Modified code for latest RTL changes.
+* 3.6   ms     02/16/18 Updates flow control mode offset value in
+*			modem control register.
+*
+* 
+* +******************************************************************************/ +#ifndef XUARTPS_HW_H /* prevent circular inclusions */ +#define XUARTPS_HW_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_io.h" + +/************************** Constant Definitions *****************************/ + +/** @name Register Map + * + * Register offsets for the UART. + * @{ + */ +#define XUARTPS_CR_OFFSET 0x0000U /**< Control Register [8:0] */ +#define XUARTPS_MR_OFFSET 0x0004U /**< Mode Register [9:0] */ +#define XUARTPS_IER_OFFSET 0x0008U /**< Interrupt Enable [12:0] */ +#define XUARTPS_IDR_OFFSET 0x000CU /**< Interrupt Disable [12:0] */ +#define XUARTPS_IMR_OFFSET 0x0010U /**< Interrupt Mask [12:0] */ +#define XUARTPS_ISR_OFFSET 0x0014U /**< Interrupt Status [12:0]*/ +#define XUARTPS_BAUDGEN_OFFSET 0x0018U /**< Baud Rate Generator [15:0] */ +#define XUARTPS_RXTOUT_OFFSET 0x001CU /**< RX Timeout [7:0] */ +#define XUARTPS_RXWM_OFFSET 0x0020U /**< RX FIFO Trigger Level [5:0] */ +#define XUARTPS_MODEMCR_OFFSET 0x0024U /**< Modem Control [5:0] */ +#define XUARTPS_MODEMSR_OFFSET 0x0028U /**< Modem Status [8:0] */ +#define XUARTPS_SR_OFFSET 0x002CU /**< Channel Status [14:0] */ +#define XUARTPS_FIFO_OFFSET 0x0030U /**< FIFO [7:0] */ +#define XUARTPS_BAUDDIV_OFFSET 0x0034U /**< Baud Rate Divider [7:0] */ +#define XUARTPS_FLOWDEL_OFFSET 0x0038U /**< Flow Delay [5:0] */ +#define XUARTPS_TXWM_OFFSET 0x0044U /**< TX FIFO Trigger Level [5:0] */ +#define XUARTPS_RXBS_OFFSET 0x0048U /**< RX FIFO Byte Status [11:0] */ +/* @} */ + +/** @name Control Register + * + * The Control register (CR) controls the major functions of the device. + * + * Control Register Bit Definition + */ + +#define XUARTPS_CR_STOPBRK 0x00000100U /**< Stop transmission of break */ +#define XUARTPS_CR_STARTBRK 0x00000080U /**< Set break */ +#define XUARTPS_CR_TORST 0x00000040U /**< RX timeout counter restart */ +#define XUARTPS_CR_TX_DIS 0x00000020U /**< TX disabled. */ +#define XUARTPS_CR_TX_EN 0x00000010U /**< TX enabled */ +#define XUARTPS_CR_RX_DIS 0x00000008U /**< RX disabled. */ +#define XUARTPS_CR_RX_EN 0x00000004U /**< RX enabled */ +#define XUARTPS_CR_EN_DIS_MASK 0x0000003CU /**< Enable/disable Mask */ +#define XUARTPS_CR_TXRST 0x00000002U /**< TX logic reset */ +#define XUARTPS_CR_RXRST 0x00000001U /**< RX logic reset */ +/* @}*/ + + +/** @name Mode Register + * + * The mode register (MR) defines the mode of transfer as well as the data + * format. If this register is modified during transmission or reception, + * data validity cannot be guaranteed. + * + * Mode Register Bit Definition + * @{ + */ +#define XUARTPS_MR_CCLK 0x00000400U /**< Input clock selection */ +#define XUARTPS_MR_CHMODE_R_LOOP 0x00000300U /**< Remote loopback mode */ +#define XUARTPS_MR_CHMODE_L_LOOP 0x00000200U /**< Local loopback mode */ +#define XUARTPS_MR_CHMODE_ECHO 0x00000100U /**< Auto echo mode */ +#define XUARTPS_MR_CHMODE_NORM 0x00000000U /**< Normal mode */ +#define XUARTPS_MR_CHMODE_SHIFT 8U /**< Mode shift */ +#define XUARTPS_MR_CHMODE_MASK 0x00000300U /**< Mode mask */ +#define XUARTPS_MR_STOPMODE_2_BIT 0x00000080U /**< 2 stop bits */ +#define XUARTPS_MR_STOPMODE_1_5_BIT 0x00000040U /**< 1.5 stop bits */ +#define XUARTPS_MR_STOPMODE_1_BIT 0x00000000U /**< 1 stop bit */ +#define XUARTPS_MR_STOPMODE_SHIFT 6U /**< Stop bits shift */ +#define XUARTPS_MR_STOPMODE_MASK 0x000000A0U /**< Stop bits mask */ +#define XUARTPS_MR_PARITY_NONE 0x00000020U /**< No parity mode */ +#define XUARTPS_MR_PARITY_MARK 0x00000018U /**< Mark parity mode */ +#define XUARTPS_MR_PARITY_SPACE 0x00000010U /**< Space parity mode */ +#define XUARTPS_MR_PARITY_ODD 0x00000008U /**< Odd parity mode */ +#define XUARTPS_MR_PARITY_EVEN 0x00000000U /**< Even parity mode */ +#define XUARTPS_MR_PARITY_SHIFT 3U /**< Parity setting shift */ +#define XUARTPS_MR_PARITY_MASK 0x00000038U /**< Parity mask */ +#define XUARTPS_MR_CHARLEN_6_BIT 0x00000006U /**< 6 bits data */ +#define XUARTPS_MR_CHARLEN_7_BIT 0x00000004U /**< 7 bits data */ +#define XUARTPS_MR_CHARLEN_8_BIT 0x00000000U /**< 8 bits data */ +#define XUARTPS_MR_CHARLEN_SHIFT 1U /**< Data Length shift */ +#define XUARTPS_MR_CHARLEN_MASK 0x00000006U /**< Data length mask */ +#define XUARTPS_MR_CLKSEL 0x00000001U /**< Input clock selection */ +/* @} */ + + +/** @name Interrupt Registers + * + * Interrupt control logic uses the interrupt enable register (IER) and the + * interrupt disable register (IDR) to set the value of the bits in the + * interrupt mask register (IMR). The IMR determines whether to pass an + * interrupt to the interrupt status register (ISR). + * Writing a 1 to IER Enbables an interrupt, writing a 1 to IDR disables an + * interrupt. IMR and ISR are read only, and IER and IDR are write only. + * Reading either IER or IDR returns 0x00. + * + * All four registers have the same bit definitions. + * + * @{ + */ +#define XUARTPS_IXR_RBRK 0x00002000U /**< Rx FIFO break detect interrupt */ +#define XUARTPS_IXR_TOVR 0x00001000U /**< Tx FIFO Overflow interrupt */ +#define XUARTPS_IXR_TNFUL 0x00000800U /**< Tx FIFO Nearly Full interrupt */ +#define XUARTPS_IXR_TTRIG 0x00000400U /**< Tx Trig interrupt */ +#define XUARTPS_IXR_DMS 0x00000200U /**< Modem status change interrupt */ +#define XUARTPS_IXR_TOUT 0x00000100U /**< Timeout error interrupt */ +#define XUARTPS_IXR_PARITY 0x00000080U /**< Parity error interrupt */ +#define XUARTPS_IXR_FRAMING 0x00000040U /**< Framing error interrupt */ +#define XUARTPS_IXR_OVER 0x00000020U /**< Overrun error interrupt */ +#define XUARTPS_IXR_TXFULL 0x00000010U /**< TX FIFO full interrupt. */ +#define XUARTPS_IXR_TXEMPTY 0x00000008U /**< TX FIFO empty interrupt. */ +#define XUARTPS_IXR_RXFULL 0x00000004U /**< RX FIFO full interrupt. */ +#define XUARTPS_IXR_RXEMPTY 0x00000002U /**< RX FIFO empty interrupt. */ +#define XUARTPS_IXR_RXOVR 0x00000001U /**< RX FIFO trigger interrupt. */ +#define XUARTPS_IXR_MASK 0x00003FFFU /**< Valid bit mask */ +/* @} */ + + +/** @name Baud Rate Generator Register + * + * The baud rate generator control register (BRGR) is a 16 bit register that + * controls the receiver bit sample clock and baud rate. + * Valid values are 1 - 65535. + * + * Bit Sample Rate = CCLK / BRGR, where the CCLK is selected by the MR_CCLK bit + * in the MR register. + * @{ + */ +#define XUARTPS_BAUDGEN_DISABLE 0x00000000U /**< Disable clock */ +#define XUARTPS_BAUDGEN_MASK 0x0000FFFFU /**< Valid bits mask */ +#define XUARTPS_BAUDGEN_RESET_VAL 0x0000028BU /**< Reset value */ + +/** @name Baud Divisor Rate register + * + * The baud rate divider register (BDIV) controls how much the bit sample + * rate is divided by. It sets the baud rate. + * Valid values are 0x04 to 0xFF. Writing a value less than 4 will be ignored. + * + * Baud rate = CCLK / ((BAUDDIV + 1) x BRGR), where the CCLK is selected by + * the MR_CCLK bit in the MR register. + * @{ + */ +#define XUARTPS_BAUDDIV_MASK 0x000000FFU /**< 8 bit baud divider mask */ +#define XUARTPS_BAUDDIV_RESET_VAL 0x0000000FU /**< Reset value */ +/* @} */ + + +/** @name Receiver Timeout Register + * + * Use the receiver timeout register (RTR) to detect an idle condition on + * the receiver data line. + * + * @{ + */ +#define XUARTPS_RXTOUT_DISABLE 0x00000000U /**< Disable time out */ +#define XUARTPS_RXTOUT_MASK 0x000000FFU /**< Valid bits mask */ + +/** @name Receiver FIFO Trigger Level Register + * + * Use the Receiver FIFO Trigger Level Register (RTRIG) to set the value at + * which the RX FIFO triggers an interrupt event. + * @{ + */ + +#define XUARTPS_RXWM_DISABLE 0x00000000U /**< Disable RX trigger interrupt */ +#define XUARTPS_RXWM_MASK 0x0000003FU /**< Valid bits mask */ +#define XUARTPS_RXWM_RESET_VAL 0x00000020U /**< Reset value */ +/* @} */ + +/** @name Transmit FIFO Trigger Level Register + * + * Use the Transmit FIFO Trigger Level Register (TTRIG) to set the value at + * which the TX FIFO triggers an interrupt event. + * @{ + */ + +#define XUARTPS_TXWM_MASK 0x0000003FU /**< Valid bits mask */ +#define XUARTPS_TXWM_RESET_VAL 0x00000020U /**< Reset value */ +/* @} */ + +/** @name Modem Control Register + * + * This register (MODEMCR) controls the interface with the modem or data set, + * or a peripheral device emulating a modem. + * + * @{ + */ +#define XUARTPS_MODEMCR_FCM 0x00000020U /**< Flow control mode */ +#define XUARTPS_MODEMCR_RTS 0x00000002U /**< Request to send */ +#define XUARTPS_MODEMCR_DTR 0x00000001U /**< Data terminal ready */ +/* @} */ + +/** @name Modem Status Register + * + * This register (MODEMSR) indicates the current state of the control lines + * from a modem, or another peripheral device, to the CPU. In addition, four + * bits of the modem status register provide change information. These bits + * are set to a logic 1 whenever a control input from the modem changes state. + * + * Note: Whenever the DCTS, DDSR, TERI, or DDCD bit is set to logic 1, a modem + * status interrupt is generated and this is reflected in the modem status + * register. + * + * @{ + */ +#define XUARTPS_MODEMSR_FCMS 0x00000100U /**< Flow control mode (FCMS) */ +#define XUARTPS_MODEMSR_DCD 0x00000080U /**< Complement of DCD input */ +#define XUARTPS_MODEMSR_RI 0x00000040U /**< Complement of RI input */ +#define XUARTPS_MODEMSR_DSR 0x00000020U /**< Complement of DSR input */ +#define XUARTPS_MODEMSR_CTS 0x00000010U /**< Complement of CTS input */ +#define XUARTPS_MODEMSR_DDCD 0x00000008U /**< Delta DCD indicator */ +#define XUARTPS_MODEMSR_TERI 0x00000004U /**< Trailing Edge Ring Indicator */ +#define XUARTPS_MODEMSR_DDSR 0x00000002U /**< Change of DSR */ +#define XUARTPS_MODEMSR_DCTS 0x00000001U /**< Change of CTS */ +/* @} */ + +/** @name Channel Status Register + * + * The channel status register (CSR) is provided to enable the control logic + * to monitor the status of bits in the channel interrupt status register, + * even if these are masked out by the interrupt mask register. + * + * @{ + */ +#define XUARTPS_SR_TNFUL 0x00004000U /**< TX FIFO Nearly Full Status */ +#define XUARTPS_SR_TTRIG 0x00002000U /**< TX FIFO Trigger Status */ +#define XUARTPS_SR_FLOWDEL 0x00001000U /**< RX FIFO fill over flow delay */ +#define XUARTPS_SR_TACTIVE 0x00000800U /**< TX active */ +#define XUARTPS_SR_RACTIVE 0x00000400U /**< RX active */ +#define XUARTPS_SR_TXFULL 0x00000010U /**< TX FIFO full */ +#define XUARTPS_SR_TXEMPTY 0x00000008U /**< TX FIFO empty */ +#define XUARTPS_SR_RXFULL 0x00000004U /**< RX FIFO full */ +#define XUARTPS_SR_RXEMPTY 0x00000002U /**< RX FIFO empty */ +#define XUARTPS_SR_RXOVR 0x00000001U /**< RX FIFO fill over trigger */ +/* @} */ + +/** @name Flow Delay Register + * + * Operation of the flow delay register (FLOWDEL) is very similar to the + * receive FIFO trigger register. An internal trigger signal activates when the + * FIFO is filled to the level set by this register. This trigger will not + * cause an interrupt, although it can be read through the channel status + * register. In hardware flow control mode, RTS is deactivated when the trigger + * becomes active. RTS only resets when the FIFO level is four less than the + * level of the flow delay trigger and the flow delay trigger is not activated. + * A value less than 4 disables the flow delay. + * @{ + */ +#define XUARTPS_FLOWDEL_MASK XUARTPS_RXWM_MASK /**< Valid bit mask */ +/* @} */ + +/** @name Receiver FIFO Byte Status Register + * + * The Receiver FIFO Status register is used to have a continuous + * monitoring of the raw unmasked byte status information. The register + * contains frame, parity and break status information for the top + * four bytes in the RX FIFO. + * + * Receiver FIFO Byte Status Register Bit Definition + * @{ + */ +#define XUARTPS_RXBS_BYTE3_BRKE 0x00000800U /**< Byte3 Break Error */ +#define XUARTPS_RXBS_BYTE3_FRME 0x00000400U /**< Byte3 Frame Error */ +#define XUARTPS_RXBS_BYTE3_PARE 0x00000200U /**< Byte3 Parity Error */ +#define XUARTPS_RXBS_BYTE2_BRKE 0x00000100U /**< Byte2 Break Error */ +#define XUARTPS_RXBS_BYTE2_FRME 0x00000080U /**< Byte2 Frame Error */ +#define XUARTPS_RXBS_BYTE2_PARE 0x00000040U /**< Byte2 Parity Error */ +#define XUARTPS_RXBS_BYTE1_BRKE 0x00000020U /**< Byte1 Break Error */ +#define XUARTPS_RXBS_BYTE1_FRME 0x00000010U /**< Byte1 Frame Error */ +#define XUARTPS_RXBS_BYTE1_PARE 0x00000008U /**< Byte1 Parity Error */ +#define XUARTPS_RXBS_BYTE0_BRKE 0x00000004U /**< Byte0 Break Error */ +#define XUARTPS_RXBS_BYTE0_FRME 0x00000002U /**< Byte0 Frame Error */ +#define XUARTPS_RXBS_BYTE0_PARE 0x00000001U /**< Byte0 Parity Error */ +#define XUARTPS_RXBS_MASK 0x00000007U /**< 3 bit RX byte status mask */ +/* @} */ + + +/* + * Defines for backwards compatabilty, will be removed + * in the next version of the driver + */ +#define XUARTPS_MEDEMSR_DCDX XUARTPS_MODEMSR_DDCD +#define XUARTPS_MEDEMSR_RIX XUARTPS_MODEMSR_TERI +#define XUARTPS_MEDEMSR_DSRX XUARTPS_MODEMSR_DDSR +#define XUARTPS_MEDEMSR_CTSX XUARTPS_MODEMSR_DCTS + + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + +/****************************************************************************/ +/** +* Read a UART register. +* +* @param BaseAddress contains the base address of the device. +* @param RegOffset contains the offset from the base address of the +* device. +* +* @return The value read from the register. +* +* @note C-Style signature: +* u32 XUartPs_ReadReg(u32 BaseAddress, int RegOffset) +* +******************************************************************************/ +#define XUartPs_ReadReg(BaseAddress, RegOffset) \ + Xil_In32((BaseAddress) + (u32)(RegOffset)) + +/***************************************************************************/ +/** +* Write a UART register. +* +* @param BaseAddress contains the base address of the device. +* @param RegOffset contains the offset from the base address of the +* device. +* @param RegisterValue is the value to be written to the register. +* +* @return None. +* +* @note C-Style signature: +* void XUartPs_WriteReg(u32 BaseAddress, int RegOffset, +* u16 RegisterValue) +* +******************************************************************************/ +#define XUartPs_WriteReg(BaseAddress, RegOffset, RegisterValue) \ + Xil_Out32((BaseAddress) + (u32)(RegOffset), (u32)(RegisterValue)) + +/****************************************************************************/ +/** +* Determine if there is receive data in the receiver and/or FIFO. +* +* @param BaseAddress contains the base address of the device. +* +* @return TRUE if there is receive data, FALSE otherwise. +* +* @note C-Style signature: +* u32 XUartPs_IsReceiveData(u32 BaseAddress) +* +******************************************************************************/ +#define XUartPs_IsReceiveData(BaseAddress) \ + !((Xil_In32((BaseAddress) + XUARTPS_SR_OFFSET) & \ + (u32)XUARTPS_SR_RXEMPTY) == (u32)XUARTPS_SR_RXEMPTY) + +/****************************************************************************/ +/** +* Determine if a byte of data can be sent with the transmitter. +* +* @param BaseAddress contains the base address of the device. +* +* @return TRUE if the TX FIFO is full, FALSE if a byte can be put in the +* FIFO. +* +* @note C-Style signature: +* u32 XUartPs_IsTransmitFull(u32 BaseAddress) +* +******************************************************************************/ +#define XUartPs_IsTransmitFull(BaseAddress) \ + ((Xil_In32((BaseAddress) + XUARTPS_SR_OFFSET) & \ + (u32)XUARTPS_SR_TXFULL) == (u32)XUARTPS_SR_TXFULL) + +/************************** Function Prototypes ******************************/ + +void XUartPs_SendByte(u32 BaseAddress, u8 Data); + +u8 XUartPs_RecvByte(u32 BaseAddress); + +void XUartPs_ResetHw(u32 BaseAddress); + +/************************** Variable Definitions *****************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/uartps_v3_7/src/xuartps_intr.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/uartps_v3_7/src/xuartps_intr.c new file mode 100644 index 0000000..88eed1e --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/uartps_v3_7/src/xuartps_intr.c @@ -0,0 +1,447 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2018 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xuartps_intr.c +* @addtogroup uartps_v3_5 +* @{ +* +* This file contains the functions for interrupt handling +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date	Changes
+* ----- ------ -------- -----------------------------------------------
+* 1.00  drg/jz 01/13/10 First Release
+* 3.00  kvn    02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.1	kvn    04/10/15 Modified code for latest RTL changes.
+* 3.7   aru    08/17/18 Resolved MISRA-C mandatory violations.(CR#1007755)
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ + +#include "xuartps.h" + +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Function Prototypes *****************************/ + +static void ReceiveDataHandler(XUartPs *InstancePtr); +static void SendDataHandler(XUartPs *InstancePtr, u32 IsrStatus); +static void ReceiveErrorHandler(XUartPs *InstancePtr, u32 IsrStatus); +static void ReceiveTimeoutHandler(XUartPs *InstancePtr); +static void ModemHandler(XUartPs *InstancePtr); + + +/* Internal function prototypes implemented in xuartps.c */ +extern u32 XUartPs_ReceiveBuffer(XUartPs *InstancePtr); +extern u32 XUartPs_SendBuffer(XUartPs *InstancePtr); + +/************************** Variable Definitions ****************************/ + +typedef void (*Handler)(XUartPs *InstancePtr); + +/****************************************************************************/ +/** +* +* This function gets the interrupt mask +* +* @param InstancePtr is a pointer to the XUartPs instance. +* +* @return +* The current interrupt mask. The mask indicates which interupts +* are enabled. +* +* @note None. +* +*****************************************************************************/ +u32 XUartPs_GetInterruptMask(XUartPs *InstancePtr) +{ + /* Assert validates the input argument */ + Xil_AssertNonvoid(InstancePtr != NULL); + + /* Read the Interrupt Mask register */ + return (XUartPs_ReadReg(InstancePtr->Config.BaseAddress, + XUARTPS_IMR_OFFSET)); +} + +/****************************************************************************/ +/** +* +* This function sets the interrupt mask. +* +* @param InstancePtr is a pointer to the XUartPs instance +* @param Mask contains the interrupts to be enabled or disabled. +* A '1' enables an interupt, and a '0' disables. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XUartPs_SetInterruptMask(XUartPs *InstancePtr, u32 Mask) +{ + u32 TempMask = Mask; + /* Assert validates the input arguments */ + Xil_AssertVoid(InstancePtr != NULL); + + TempMask &= (u32)XUARTPS_IXR_MASK; + + /* Write the mask to the IER Register */ + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, + XUARTPS_IER_OFFSET, TempMask); + + /* Write the inverse of the Mask to the IDR register */ + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, + XUARTPS_IDR_OFFSET, (~TempMask)); + +} + +/****************************************************************************/ +/** +* +* This function sets the handler that will be called when an event (interrupt) +* occurs that needs application's attention. +* +* @param InstancePtr is a pointer to the XUartPs instance +* @param FuncPtr is the pointer to the callback function. +* @param CallBackRef is the upper layer callback reference passed back +* when the callback function is invoked. +* +* @return None. +* +* @note +* +* There is no assert on the CallBackRef since the driver doesn't know what it +* is (nor should it) +* +*****************************************************************************/ +void XUartPs_SetHandler(XUartPs *InstancePtr, XUartPs_Handler FuncPtr, + void *CallBackRef) +{ + /* + * Asserts validate the input arguments + * CallBackRef not checked, no way to know what is valid + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(FuncPtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + InstancePtr->Handler = (XUartPs_Handler)FuncPtr; + InstancePtr->CallBackRef = CallBackRef; +} + +/****************************************************************************/ +/** +* +* This function is the interrupt handler for the driver. +* It must be connected to an interrupt system by the application such that it +* can be called when an interrupt occurs. +* +* @param InstancePtr contains a pointer to the driver instance +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XUartPs_InterruptHandler(XUartPs *InstancePtr) +{ + u32 IsrStatus; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the interrupt ID register to determine which + * interrupt is active + */ + IsrStatus = XUartPs_ReadReg(InstancePtr->Config.BaseAddress, + XUARTPS_IMR_OFFSET); + + IsrStatus &= XUartPs_ReadReg(InstancePtr->Config.BaseAddress, + XUARTPS_ISR_OFFSET); + + /* Dispatch an appropriate handler. */ + if((IsrStatus & ((u32)XUARTPS_IXR_RXOVR | (u32)XUARTPS_IXR_RXEMPTY | + (u32)XUARTPS_IXR_RXFULL)) != (u32)0) { + /* Received data interrupt */ + ReceiveDataHandler(InstancePtr); + } + + if((IsrStatus & ((u32)XUARTPS_IXR_TXEMPTY | (u32)XUARTPS_IXR_TXFULL)) + != (u32)0) { + /* Transmit data interrupt */ + SendDataHandler(InstancePtr, IsrStatus); + } + + /* XUARTPS_IXR_RBRK is applicable only for Zynq Ultrascale+ MP */ + if ((IsrStatus & ((u32)XUARTPS_IXR_OVER | (u32)XUARTPS_IXR_FRAMING | + (u32)XUARTPS_IXR_PARITY | (u32)XUARTPS_IXR_RBRK)) != (u32)0) { + /* Received Error Status interrupt */ + ReceiveErrorHandler(InstancePtr, IsrStatus); + } + + if((IsrStatus & ((u32)XUARTPS_IXR_TOUT)) != (u32)0) { + /* Received Timeout interrupt */ + ReceiveTimeoutHandler(InstancePtr); + } + + if((IsrStatus & ((u32)XUARTPS_IXR_DMS)) != (u32)0) { + /* Modem status interrupt */ + ModemHandler(InstancePtr); + } + + /* Clear the interrupt status. */ + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_ISR_OFFSET, + IsrStatus); + +} + +/****************************************************************************/ +/* +* +* This function handles interrupts for receive errors which include +* overrun errors, framing errors, parity errors, and the break interrupt. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +static void ReceiveErrorHandler(XUartPs *InstancePtr, u32 IsrStatus) +{ + u32 EventData; + u32 Event; + + InstancePtr->is_rxbs_error = 0; + + if ((InstancePtr->Platform == XPLAT_ZYNQ_ULTRA_MP) && + (IsrStatus & ((u32)XUARTPS_IXR_PARITY | (u32)XUARTPS_IXR_RBRK + | (u32)XUARTPS_IXR_FRAMING))) { + InstancePtr->is_rxbs_error = 1; + } + /* + * If there are bytes still to be received in the specified buffer + * go ahead and receive them. Removing bytes from the RX FIFO will + * clear the interrupt. + */ + + (void)XUartPs_ReceiveBuffer(InstancePtr); + + if (!(InstancePtr->is_rxbs_error)) { + Event = XUARTPS_EVENT_RECV_ERROR; + EventData = InstancePtr->ReceiveBuffer.RequestedBytes - + InstancePtr->ReceiveBuffer.RemainingBytes; + + /* + * Call the application handler to indicate that there is a receive + * error or a break interrupt, if the application cares about the + * error it call a function to get the last errors. + */ + InstancePtr->Handler(InstancePtr->CallBackRef, + Event, + EventData); + } +} + +/****************************************************************************/ +/** +* +* This function handles the receive timeout interrupt. This interrupt occurs +* whenever a number of bytes have been present in the RX FIFO and the receive +* data line has been idle for at lease 4 or more character times, (the timeout +* is set using XUartPs_SetrecvTimeout() function). +* +* @param InstancePtr is a pointer to the XUartPs instance +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +static void ReceiveTimeoutHandler(XUartPs *InstancePtr) +{ + u32 Event; + + /* + * If there are bytes still to be received in the specified buffer + * go ahead and receive them. Removing bytes from the RX FIFO will + * clear the interrupt. + */ + if (InstancePtr->ReceiveBuffer.RemainingBytes != (u32)0) { + (void)XUartPs_ReceiveBuffer(InstancePtr); + } + + /* + * If there are no more bytes to receive then indicate that this is + * not a receive timeout but the end of the buffer reached, a timeout + * normally occurs if # of bytes is not divisible by FIFO threshold, + * don't rely on previous test of remaining bytes since receive + * function updates it + */ + if (InstancePtr->ReceiveBuffer.RemainingBytes != (u32)0) { + Event = XUARTPS_EVENT_RECV_TOUT; + } else { + Event = XUARTPS_EVENT_RECV_DATA; + } + + /* + * Call the application handler to indicate that there is a receive + * timeout or data event + */ + InstancePtr->Handler(InstancePtr->CallBackRef, Event, + InstancePtr->ReceiveBuffer.RequestedBytes - + InstancePtr->ReceiveBuffer.RemainingBytes); + +} +/****************************************************************************/ +/** +* +* This function handles the interrupt when data is in RX FIFO. +* +* @param InstancePtr is a pointer to the XUartPs instance +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +static void ReceiveDataHandler(XUartPs *InstancePtr) +{ + /* + * If there are bytes still to be received in the specified buffer + * go ahead and receive them. Removing bytes from the RX FIFO will + * clear the interrupt. + */ + if (InstancePtr->ReceiveBuffer.RemainingBytes != (u32)0) { + (void)XUartPs_ReceiveBuffer(InstancePtr); + } + + /* If the last byte of a message was received then call the application + * handler, this code should not use an else from the previous check of + * the number of bytes to receive because the call to receive the buffer + * updates the bytes ramained + */ + if (InstancePtr->ReceiveBuffer.RemainingBytes == (u32)0) { + InstancePtr->Handler(InstancePtr->CallBackRef, + XUARTPS_EVENT_RECV_DATA, + (InstancePtr->ReceiveBuffer.RequestedBytes - + InstancePtr->ReceiveBuffer.RemainingBytes)); + } + +} + +/****************************************************************************/ +/** +* +* This function handles the interrupt when data has been sent, the transmit +* FIFO is empty (transmitter holding register). +* +* @param InstancePtr is a pointer to the XUartPs instance +* @param IsrStatus is the register value for channel status register +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +static void SendDataHandler(XUartPs *InstancePtr, u32 IsrStatus) +{ + + /* + * If there are not bytes to be sent from the specified buffer then disable + * the transmit interrupt so it will stop interrupting as it interrupts + * any time the FIFO is empty + */ + if (InstancePtr->SendBuffer.RemainingBytes == (u32)0) { + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, + XUARTPS_IDR_OFFSET, + ((u32)XUARTPS_IXR_TXEMPTY | (u32)XUARTPS_IXR_TXFULL)); + + /* Call the application handler to indicate the sending is done */ + InstancePtr->Handler(InstancePtr->CallBackRef, + XUARTPS_EVENT_SENT_DATA, + InstancePtr->SendBuffer.RequestedBytes - + InstancePtr->SendBuffer.RemainingBytes); + } + + /* If TX FIFO is empty, send more. */ + else if((IsrStatus & ((u32)XUARTPS_IXR_TXEMPTY)) != (u32)0) { + (void)XUartPs_SendBuffer(InstancePtr); + } + else { + /* Else with dummy entry for MISRA-C Compliance.*/ + ; + } +} + +/****************************************************************************/ +/** +* +* This function handles modem interrupts. It does not do any processing +* except to call the application handler to indicate a modem event. +* +* @param InstancePtr is a pointer to the XUartPs instance +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +static void ModemHandler(XUartPs *InstancePtr) +{ + u32 MsrRegister; + + /* + * Read the modem status register so that the interrupt is acknowledged + * and it can be passed to the callback handler with the event + */ + MsrRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress, + XUARTPS_MODEMSR_OFFSET); + + /* + * Call the application handler to indicate the modem status changed, + * passing the modem status and the event data in the call + */ + InstancePtr->Handler(InstancePtr->CallBackRef, + XUARTPS_EVENT_MODEM, + MsrRegister); + +} +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/uartps_v3_7/src/xuartps_options.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/uartps_v3_7/src/xuartps_options.c new file mode 100644 index 0000000..ee0db5f --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/uartps_v3_7/src/xuartps_options.c @@ -0,0 +1,760 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xuartps_options.c +* @addtogroup uartps_v3_5 +* @{ +* +* The implementation of the options functions for the XUartPs driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date	Changes
+* ----- ------ -------- -----------------------------------------------
+* 1.00  drg/jz 01/13/10 First Release
+* 1.00  sdm    09/27/11 Fixed a bug in XUartPs_SetFlowDelay where the input
+*			value was not being written to the register.
+* 3.00  kvn    02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.2   rk     07/20/16 Modified the logic for transmission break bit set
+*
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ + +#include "xuartps.h" + +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Variable Definitions ****************************/ +/* + * The following data type is a map from an option to the offset in the + * register to which it belongs as well as its bit mask in that register. + */ +typedef struct { + u16 Option; + u16 RegisterOffset; + u32 Mask; +} Mapping; + +/* + * Create the table which contains options which are to be processed to get/set + * the options. These options are table driven to allow easy maintenance and + * expansion of the options. + */ + +static Mapping OptionsTable[] = { + {XUARTPS_OPTION_SET_BREAK, XUARTPS_CR_OFFSET, XUARTPS_CR_STARTBRK}, + {XUARTPS_OPTION_STOP_BREAK, XUARTPS_CR_OFFSET, XUARTPS_CR_STOPBRK}, + {XUARTPS_OPTION_RESET_TMOUT, XUARTPS_CR_OFFSET, XUARTPS_CR_TORST}, + {XUARTPS_OPTION_RESET_TX, XUARTPS_CR_OFFSET, XUARTPS_CR_TXRST}, + {XUARTPS_OPTION_RESET_RX, XUARTPS_CR_OFFSET, XUARTPS_CR_RXRST}, + {XUARTPS_OPTION_ASSERT_RTS, XUARTPS_MODEMCR_OFFSET, + XUARTPS_MODEMCR_RTS}, + {XUARTPS_OPTION_ASSERT_DTR, XUARTPS_MODEMCR_OFFSET, + XUARTPS_MODEMCR_DTR}, + {XUARTPS_OPTION_SET_FCM, XUARTPS_MODEMCR_OFFSET, XUARTPS_MODEMCR_FCM} +}; + +/* Create a constant for the number of entries in the table */ + +#define XUARTPS_NUM_OPTIONS (sizeof(OptionsTable) / sizeof(Mapping)) + +/************************** Function Prototypes *****************************/ + +/****************************************************************************/ +/** +* +* Gets the options for the specified driver instance. The options are +* implemented as bit masks such that multiple options may be enabled or +* disabled simulataneously. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* +* @return +* +* The current options for the UART. The optionss are bit masks that are +* contained in the file xuartps.h and named XUARTPS_OPTION_*. +* +* @note None. +* +*****************************************************************************/ +u16 XUartPs_GetOptions(XUartPs *InstancePtr) +{ + u16 Options = 0U; + u32 Register; + u32 Index; + + /* Assert validates the input arguments */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Loop thru the options table to map the physical options in the + * registers of the UART to the logical options to be returned + */ + for (Index = 0U; Index < XUARTPS_NUM_OPTIONS; Index++) { + Register = XUartPs_ReadReg(InstancePtr->Config.BaseAddress, + OptionsTable[Index]. + RegisterOffset); + + /* + * If the bit in the register which correlates to the option + * is set, then set the corresponding bit in the options, + * ignoring any bits which are zero since the options variable + * is initialized to zero + */ + if ((Register & OptionsTable[Index].Mask) != (u32)0) { + Options |= OptionsTable[Index].Option; + } + } + + return Options; +} + +/****************************************************************************/ +/** +* +* Sets the options for the specified driver instance. The options are +* implemented as bit masks such that multiple options may be enabled or +* disabled simultaneously. +* +* The GetOptions function may be called to retrieve the currently enabled +* options. The result is ORed in the desired new settings to be enabled and +* ANDed with the inverse to clear the settings to be disabled. The resulting +* value is then used as the options for the SetOption function call. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* @param Options contains the options to be set which are bit masks +* contained in the file xuartps.h and named XUARTPS_OPTION_*. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XUartPs_SetOptions(XUartPs *InstancePtr, u16 Options) +{ + u32 Index; + u32 Register; + + /* Assert validates the input arguments */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Loop thru the options table to map the logical options to the + * physical options in the registers of the UART. + */ + for (Index = 0U; Index < XUARTPS_NUM_OPTIONS; Index++) { + + /* + * Read the register which contains option so that the register + * can be changed without destoying any other bits of the + * register. + */ + Register = XUartPs_ReadReg(InstancePtr->Config.BaseAddress, + OptionsTable[Index]. + RegisterOffset); + + /* + * If the option is set in the input, then set the corresponding + * bit in the specified register, otherwise clear the bit in + * the register. + */ + if ((Options & OptionsTable[Index].Option) != (u16)0) { + if(OptionsTable[Index].Option == XUARTPS_OPTION_SET_BREAK) + Register &= ~XUARTPS_CR_STOPBRK; + Register |= OptionsTable[Index].Mask; + } + else { + Register &= ~OptionsTable[Index].Mask; + } + + /* Write the new value to the register to set the option */ + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, + OptionsTable[Index].RegisterOffset, + Register); + } + +} + +/****************************************************************************/ +/** +* +* This function gets the receive FIFO trigger level. The receive trigger +* level indicates the number of bytes in the receive FIFO that cause a receive +* data event (interrupt) to be generated. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* +* @return The current receive FIFO trigger level. This is a value +* from 0-31. +* +* @note None. +* +*****************************************************************************/ +u8 XUartPs_GetFifoThreshold(XUartPs *InstancePtr) +{ + u8 RtrigRegister; + + /* Assert validates the input arguments */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the value of the FIFO control register so that the threshold + * can be retrieved, this read takes special register processing + */ + RtrigRegister = (u8) XUartPs_ReadReg(InstancePtr->Config.BaseAddress, + XUARTPS_RXWM_OFFSET); + + /* Return only the trigger level from the register value */ + + RtrigRegister &= (u8)XUARTPS_RXWM_MASK; + return RtrigRegister; +} + +/****************************************************************************/ +/** +* +* This functions sets the receive FIFO trigger level. The receive trigger +* level specifies the number of bytes in the receive FIFO that cause a receive +* data event (interrupt) to be generated. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* @param TriggerLevel contains the trigger level to set. +* +* @return None +* +* @note None. +* +*****************************************************************************/ +void XUartPs_SetFifoThreshold(XUartPs *InstancePtr, u8 TriggerLevel) +{ + u32 RtrigRegister; + + /* Assert validates the input arguments */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(TriggerLevel <= (u8)XUARTPS_RXWM_MASK); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + RtrigRegister = ((u32)TriggerLevel) & (u32)XUARTPS_RXWM_MASK; + + /* + * Write the new value for the FIFO control register to it such that the + * threshold is changed + */ + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, + XUARTPS_RXWM_OFFSET, RtrigRegister); + +} + +/****************************************************************************/ +/** +* +* This function gets the modem status from the specified UART. The modem +* status indicates any changes of the modem signals. This function allows +* the modem status to be read in a polled mode. The modem status is updated +* whenever it is read such that reading it twice may not yield the same +* results. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* +* @return +* +* The modem status which are bit masks that are contained in the file +* xuartps.h and named XUARTPS_MODEM_*. +* +* @note +* +* The bit masks used for the modem status are the exact bits of the modem +* status register with no abstraction. +* +*****************************************************************************/ +u16 XUartPs_GetModemStatus(XUartPs *InstancePtr) +{ + u32 ModemStatusRegister; + u16 TmpRegister; + /* Assert validates the input arguments */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* Read the modem status register to return + */ + ModemStatusRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress, + XUARTPS_MODEMSR_OFFSET); + TmpRegister = (u16)ModemStatusRegister; + return TmpRegister; +} + +/****************************************************************************/ +/** +* +* This function determines if the specified UART is sending data. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* +* @return +* - TRUE if the UART is sending data +* - FALSE if UART is not sending data +* +* @note None. +* +*****************************************************************************/ +u32 XUartPs_IsSending(XUartPs *InstancePtr) +{ + u32 ChanStatRegister; + u32 ChanTmpSRegister; + u32 ActiveResult; + u32 EmptyResult; + + /* Assert validates the input arguments */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the channel status register to determine if the transmitter is + * active + */ + ChanStatRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress, + XUARTPS_SR_OFFSET); + + /* + * If the transmitter is active, or the TX FIFO is not empty, then indicate + * that the UART is still sending some data + */ + ActiveResult = ChanStatRegister & ((u32)XUARTPS_SR_TACTIVE); + EmptyResult = ChanStatRegister & ((u32)XUARTPS_SR_TXEMPTY); + ChanTmpSRegister = (((u32)XUARTPS_SR_TACTIVE) == ActiveResult) || + (((u32)XUARTPS_SR_TXEMPTY) != EmptyResult); + + return ChanTmpSRegister; +} + +/****************************************************************************/ +/** +* +* This function gets the operational mode of the UART. The UART can operate +* in one of four modes: Normal, Local Loopback, Remote Loopback, or automatic +* echo. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* +* @return +* +* The operational mode is specified by constants defined in xuartps.h. The +* constants are named XUARTPS_OPER_MODE_* +* +* @note None. +* +*****************************************************************************/ +u8 XUartPs_GetOperMode(XUartPs *InstancePtr) +{ + u32 ModeRegister; + u8 OperMode; + + /* Assert validates the input arguments */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* Read the Mode register. */ + ModeRegister = + XUartPs_ReadReg(InstancePtr->Config.BaseAddress, + XUARTPS_MR_OFFSET); + + ModeRegister &= (u32)XUARTPS_MR_CHMODE_MASK; + /* Return the constant */ + switch (ModeRegister) { + case XUARTPS_MR_CHMODE_NORM: + OperMode = XUARTPS_OPER_MODE_NORMAL; + break; + case XUARTPS_MR_CHMODE_ECHO: + OperMode = XUARTPS_OPER_MODE_AUTO_ECHO; + break; + case XUARTPS_MR_CHMODE_L_LOOP: + OperMode = XUARTPS_OPER_MODE_LOCAL_LOOP; + break; + case XUARTPS_MR_CHMODE_R_LOOP: + OperMode = XUARTPS_OPER_MODE_REMOTE_LOOP; + break; + default: + OperMode = (u8) ((ModeRegister & (u32)XUARTPS_MR_CHMODE_MASK) >> + XUARTPS_MR_CHMODE_SHIFT); + break; + } + + return OperMode; +} + +/****************************************************************************/ +/** +* +* This function sets the operational mode of the UART. The UART can operate +* in one of four modes: Normal, Local Loopback, Remote Loopback, or automatic +* echo. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* @param OperationMode is the mode of the UART. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XUartPs_SetOperMode(XUartPs *InstancePtr, u8 OperationMode) +{ + u32 ModeRegister; + + /* Assert validates the input arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(OperationMode <= XUARTPS_OPER_MODE_REMOTE_LOOP); + + /* Read the Mode register. */ + ModeRegister = + XUartPs_ReadReg(InstancePtr->Config.BaseAddress, + XUARTPS_MR_OFFSET); + + /* Set the correct value by masking the bits, then ORing the const. */ + ModeRegister &= (u32)(~XUARTPS_MR_CHMODE_MASK); + + switch (OperationMode) { + case XUARTPS_OPER_MODE_NORMAL: + ModeRegister |= (u32)XUARTPS_MR_CHMODE_NORM; + break; + case XUARTPS_OPER_MODE_AUTO_ECHO: + ModeRegister |= (u32)XUARTPS_MR_CHMODE_ECHO; + break; + case XUARTPS_OPER_MODE_LOCAL_LOOP: + ModeRegister |= (u32)XUARTPS_MR_CHMODE_L_LOOP; + break; + case XUARTPS_OPER_MODE_REMOTE_LOOP: + ModeRegister |= (u32)XUARTPS_MR_CHMODE_R_LOOP; + break; + default: + /* Default case made for MISRA-C Compliance. */ + break; + } + + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_MR_OFFSET, + ModeRegister); + +} + +/****************************************************************************/ +/** +* +* This function sets the Flow Delay. +* 0 - 3: Flow delay inactive +* 4 - 32: If Flow Control mode is enabled, UART_rtsN is deactivated when the +* receive FIFO fills to this level. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* +* @return +* +* The Flow Delay is specified by constants defined in xuartps_hw.h. The +* constants are named XUARTPS_FLOWDEL* +* +* @note None. +* +*****************************************************************************/ +u8 XUartPs_GetFlowDelay(XUartPs *InstancePtr) +{ + u32 FdelTmpRegister; + + /* Assert validates the input arguments */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* Read the Mode register. */ + FdelTmpRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress, + XUARTPS_FLOWDEL_OFFSET); + + /* Return the contents of the flow delay register */ + FdelTmpRegister = (u8)(FdelTmpRegister & (u32)XUARTPS_FLOWDEL_MASK); + return FdelTmpRegister; +} + +/****************************************************************************/ +/** +* +* This function sets the Flow Delay. +* 0 - 3: Flow delay inactive +* 4 - 63: If Flow Control mode is enabled, UART_rtsN is deactivated when the +* receive FIFO fills to this level. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* @param FlowDelayValue is the Setting for the flow delay. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XUartPs_SetFlowDelay(XUartPs *InstancePtr, u8 FlowDelayValue) +{ + u32 FdelRegister; + + /* Assert validates the input arguments */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(FlowDelayValue > (u8)XUARTPS_FLOWDEL_MASK); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Set the correct value by shifting the input constant, then masking + * the bits + */ + FdelRegister = ((u32)FlowDelayValue) & (u32)XUARTPS_FLOWDEL_MASK; + + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, + XUARTPS_FLOWDEL_OFFSET, FdelRegister); + +} + +/****************************************************************************/ +/** +* +* This function gets the Receive Timeout of the UART. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* +* @return The current setting for receive time out. +* +* @note None. +* +*****************************************************************************/ +u8 XUartPs_GetRecvTimeout(XUartPs *InstancePtr) +{ + u32 RtoRegister; + u8 RtoRTmpRegister; + + /* Assert validates the input arguments */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* Read the Receive Timeout register. */ + RtoRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress, + XUARTPS_RXTOUT_OFFSET); + + /* Return the contents of the mode register shifted appropriately */ + RtoRTmpRegister = (u8)(RtoRegister & (u32)XUARTPS_RXTOUT_MASK); + return RtoRTmpRegister; +} + +/****************************************************************************/ +/** +* +* This function sets the Receive Timeout of the UART. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* @param RecvTimeout setting allows the UART to detect an idle connection +* on the reciever data line. +* Timeout duration = RecvTimeout x 4 x Bit Period. 0 disables the +* timeout function. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XUartPs_SetRecvTimeout(XUartPs *InstancePtr, u8 RecvTimeout) +{ + u32 RtoRegister; + + /* Assert validates the input arguments */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* Set the correct value by masking the bits */ + RtoRegister = ((u32)RecvTimeout & (u32)XUARTPS_RXTOUT_MASK); + + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, + XUARTPS_RXTOUT_OFFSET, RtoRegister); + + /* Configure CR to restart the receiver timeout counter */ + RtoRegister = + XUartPs_ReadReg(InstancePtr->Config.BaseAddress, + XUARTPS_CR_OFFSET); + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_CR_OFFSET, + (RtoRegister | XUARTPS_CR_TORST)); + +} +/****************************************************************************/ +/** +* +* Sets the data format for the device. The data format includes the +* baud rate, number of data bits, number of stop bits, and parity. It is the +* caller's responsibility to ensure that the UART is not sending or receiving +* data when this function is called. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* @param FormatPtr is a pointer to a format structure containing the data +* format to be set. +* +* @return +* - XST_SUCCESS if the data format was successfully set. +* - XST_UART_BAUD_ERROR indicates the baud rate could not be +* set because of the amount of error with the baud rate and +* the input clock frequency. +* - XST_INVALID_PARAM if one of the parameters was not valid. +* +* @note +* +* The data types in the format type, data bits and parity, are 32 bit fields +* to prevent a compiler warning. +* The asserts in this function will cause a warning if these fields are +* bytes. +*

+* +*****************************************************************************/ +s32 XUartPs_SetDataFormat(XUartPs *InstancePtr, + XUartPsFormat * FormatPtr) +{ + s32 Status; + u32 ModeRegister; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(FormatPtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* Verify the inputs specified are valid */ + if ((FormatPtr->DataBits > ((u32)XUARTPS_FORMAT_6_BITS)) || + (FormatPtr->StopBits > ((u8)XUARTPS_FORMAT_2_STOP_BIT)) || + (FormatPtr->Parity > ((u32)XUARTPS_FORMAT_NO_PARITY))) { + Status = XST_INVALID_PARAM; + } else { + + /* + * Try to set the baud rate and if it's not successful then don't + * continue altering the data format, this is done first to avoid the + * format from being altered when an error occurs + */ + Status = XUartPs_SetBaudRate(InstancePtr, FormatPtr->BaudRate); + if (Status != (s32)XST_SUCCESS) { + ; + } else { + + ModeRegister = + XUartPs_ReadReg(InstancePtr->Config.BaseAddress, + XUARTPS_MR_OFFSET); + + /* + * Set the length of data (8,7,6) by first clearing out the bits + * that control it in the register, then set the length in the register + */ + ModeRegister &= (u32)(~XUARTPS_MR_CHARLEN_MASK); + ModeRegister |= (FormatPtr->DataBits << XUARTPS_MR_CHARLEN_SHIFT); + + /* + * Set the number of stop bits in the mode register by first clearing + * out the bits that control it in the register, then set the number + * of stop bits in the register. + */ + ModeRegister &= (u32)(~XUARTPS_MR_STOPMODE_MASK); + ModeRegister |= (((u32)FormatPtr->StopBits) << XUARTPS_MR_STOPMODE_SHIFT); + + /* + * Set the parity by first clearing out the bits that control it in the + * register, then set the bits in the register, the default is no parity + * after clearing the register bits + */ + ModeRegister &= (u32)(~XUARTPS_MR_PARITY_MASK); + ModeRegister |= (FormatPtr->Parity << XUARTPS_MR_PARITY_SHIFT); + + /* Update the mode register */ + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_MR_OFFSET, + ModeRegister); + + Status = XST_SUCCESS; + } + } + return Status; +} + +/****************************************************************************/ +/** +* +* Gets the data format for the specified UART. The data format includes the +* baud rate, number of data bits, number of stop bits, and parity. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* @param FormatPtr is a pointer to a format structure that will contain +* the data format after this call completes. +* +* @return None. +* +* @note None. +* +* +*****************************************************************************/ +void XUartPs_GetDataFormat(XUartPs *InstancePtr, XUartPsFormat * FormatPtr) +{ + u32 ModeRegister; + + + /* Assert validates the input arguments */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(FormatPtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Get the baud rate from the instance, this is not retrieved from the + * hardware because it is only kept as a divisor such that it is more + * difficult to get back to the baud rate + */ + FormatPtr->BaudRate = InstancePtr->BaudRate; + + ModeRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress, + XUARTPS_MR_OFFSET); + + /* Get the length of data (8,7,6,5) */ + FormatPtr->DataBits = + ((ModeRegister & (u32)XUARTPS_MR_CHARLEN_MASK) >> + XUARTPS_MR_CHARLEN_SHIFT); + + /* Get the number of stop bits */ + FormatPtr->StopBits = + (u8)((ModeRegister & (u32)XUARTPS_MR_STOPMODE_MASK) >> + XUARTPS_MR_STOPMODE_SHIFT); + + /* Determine what parity is */ + FormatPtr->Parity = + (u32)((ModeRegister & (u32)XUARTPS_MR_PARITY_MASK) >> + XUARTPS_MR_PARITY_SHIFT); +} +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/uartps_v3_7/src/xuartps_selftest.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/uartps_v3_7/src/xuartps_selftest.c new file mode 100644 index 0000000..f26176a --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/uartps_v3_7/src/xuartps_selftest.c @@ -0,0 +1,162 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xuartps_selftest.c +* @addtogroup uartps_v3_5 +* @{ +* +* This file contains the self-test functions for the XUartPs driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date	Changes
+* ----- ------ -------- -----------------------------------------------
+* 1.00	drg/jz 01/13/10 First Release
+* 3.00  kvn    02/13/15 Modified code for MISRA-C:2012 compliance.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xstatus.h" +#include "xuartps.h" + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + +#define XUARTPS_TOTAL_BYTES (u8)32 + +/************************** Variable Definitions *****************************/ + +static u8 TestString[XUARTPS_TOTAL_BYTES]="abcdefghABCDEFGH012345677654321"; +static u8 ReturnString[XUARTPS_TOTAL_BYTES]; + +/************************** Function Prototypes ******************************/ + + +/****************************************************************************/ +/** +* +* This function runs a self-test on the driver and hardware device. This self +* test performs a local loopback and verifies data can be sent and received. +* +* The time for this test is proportional to the baud rate that has been set +* prior to calling this function. +* +* The mode and control registers are restored before return. +* +* @param InstancePtr is a pointer to the XUartPs instance +* +* @return +* - XST_SUCCESS if the test was successful +* - XST_UART_TEST_FAIL if the test failed looping back the data +* +* @note +* +* This function can hang if the hardware is not functioning properly. +* +******************************************************************************/ +s32 XUartPs_SelfTest(XUartPs *InstancePtr) +{ + s32 Status = XST_SUCCESS; + u32 IntrRegister; + u32 ModeRegister; + u8 Index; + u32 ReceiveDataResult; + + /* Assert validates the input arguments */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* Disable all interrupts in the interrupt disable register */ + IntrRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress, + XUARTPS_IMR_OFFSET); + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_IDR_OFFSET, + XUARTPS_IXR_MASK); + + /* Setup for local loopback */ + ModeRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress, + XUARTPS_MR_OFFSET); + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_MR_OFFSET, + ((ModeRegister & (u32)(~XUARTPS_MR_CHMODE_MASK)) | + (u32)XUARTPS_MR_CHMODE_L_LOOP)); + + /* Send a number of bytes and receive them, one at a time. */ + for (Index = 0U; Index < XUARTPS_TOTAL_BYTES; Index++) { + /* + * Send out the byte and if it was not sent then the failure + * will be caught in the comparison at the end + */ + (void)XUartPs_Send(InstancePtr, &TestString[Index], 1U); + + /* + * Wait until the byte is received. This can hang if the HW + * is broken. Watch for the FIFO empty flag to be false. + */ + ReceiveDataResult = Xil_In32((InstancePtr->Config.BaseAddress) + XUARTPS_SR_OFFSET) & + XUARTPS_SR_RXEMPTY; + while (ReceiveDataResult == XUARTPS_SR_RXEMPTY ) { + ReceiveDataResult = Xil_In32((InstancePtr->Config.BaseAddress) + XUARTPS_SR_OFFSET) & + XUARTPS_SR_RXEMPTY; + } + + /* Receive the byte */ + (void)XUartPs_Recv(InstancePtr, &ReturnString[Index], 1U); + } + + /* + * Compare the bytes received to the bytes sent to verify the exact data + * was received + */ + for (Index = 0U; Index < XUARTPS_TOTAL_BYTES; Index++) { + if (TestString[Index] != ReturnString[Index]) { + Status = XST_UART_TEST_FAIL; + } + } + + /* + * Restore the registers which were altered to put into polling and + * loopback modes so that this test is not destructive + */ + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_IER_OFFSET, + IntrRegister); + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_MR_OFFSET, + ModeRegister); + + return Status; +} +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/uartps_v3_7/src/xuartps_sinit.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/uartps_v3_7/src/xuartps_sinit.c new file mode 100644 index 0000000..c3e809b --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/uartps_v3_7/src/xuartps_sinit.c @@ -0,0 +1,95 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2015 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xuartps_sinit.c +* @addtogroup uartps_v3_5 +* @{ +* +* The implementation of the XUartPs driver's static initialzation +* functionality. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date	Changes
+* ----- ------ -------- -----------------------------------------------
+* 1.00  drg/jz 01/13/10 First Release
+* 3.00  kvn    02/13/15 Modified code for MISRA-C:2012 compliance.
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ + +#include "xstatus.h" +#include "xparameters.h" +#include "xuartps.h" + +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Variable Definitions ****************************/ +extern XUartPs_Config XUartPs_ConfigTable[XPAR_XUARTPS_NUM_INSTANCES]; + +/************************** Function Prototypes *****************************/ + +/****************************************************************************/ +/** +* +* Looks up the device configuration based on the unique device ID. The table +* contains the configuration info for each device in the system. +* +* @param DeviceId contains the ID of the device +* +* @return A pointer to the configuration structure or NULL if the +* specified device is not in the system. +* +* @note None. +* +******************************************************************************/ +XUartPs_Config *XUartPs_LookupConfig(u16 DeviceId) +{ + XUartPs_Config *CfgPtr = NULL; + + u32 Index; + + for (Index = 0U; Index < (u32)XPAR_XUARTPS_NUM_INSTANCES; Index++) { + if (XUartPs_ConfigTable[Index].DeviceId == DeviceId) { + CfgPtr = &XUartPs_ConfigTable[Index]; + break; + } + } + + return (XUartPs_Config *)CfgPtr; +} +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/xadcps_v2_3/src/Makefile b/df_datalink/bsp/ps7_cortexa9_0/libsrc/xadcps_v2_3/src/Makefile new file mode 100644 index 0000000..837ca13 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/xadcps_v2_3/src/Makefile @@ -0,0 +1,40 @@ +COMPILER= +ARCHIVER= +CP=cp +COMPILER_FLAGS= +EXTRA_COMPILER_FLAGS= +LIB=libxil.a + +CC_FLAGS = $(COMPILER_FLAGS) +ECC_FLAGS = $(EXTRA_COMPILER_FLAGS) + +RELEASEDIR=../../../lib +INCLUDEDIR=../../../include +INCLUDES=-I./. -I${INCLUDEDIR} + +OUTS = *.o + +LIBSOURCES:=*.c +INCLUDEFILES:=*.h + +OBJECTS = $(addsuffix .o, $(basename $(wildcard *.c))) + +libs: banner xadcps_libs clean + +%.o: %.c + ${COMPILER} $(CC_FLAGS) $(ECC_FLAGS) $(INCLUDES) -o $@ $< + +banner: + echo "Compiling xadcps" + +xadcps_libs: ${OBJECTS} + $(ARCHIVER) -r ${RELEASEDIR}/${LIB} ${OBJECTS} + +.PHONY: include +include: xadcps_includes + +xadcps_includes: + ${CP} ${INCLUDEFILES} ${INCLUDEDIR} + +clean: + rm -rf ${OBJECTS} diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/xadcps_v2_3/src/xadcps.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/xadcps_v2_3/src/xadcps.c new file mode 100644 index 0000000..5ec5a93 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/xadcps_v2_3/src/xadcps.c @@ -0,0 +1,1830 @@ +/****************************************************************************** +* +* Copyright (C) 2011 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xadcps.c +* @addtogroup xadcps_v2_3 +* @{ +* +* This file contains the driver API functions that can be used to access +* the XADC device. +* +* Refer to the xadcps.h header file for more information about this driver. +* +* @note None. +* +*
+*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- -----  -------- -----------------------------------------------------
+* 1.00a ssb    12/22/11 First release based on the XPS/AXI xadc driver
+* 1.01a bss    02/18/13	Modified XAdcPs_SetSeqChEnables,XAdcPs_SetSeqAvgEnables
+*			XAdcPs_SetSeqInputMode and XAdcPs_SetSeqAcqTime APIs
+*			to fix CR #693371
+* 2.1   bss    08/05/14	Modified Assert for XAdcPs_SetSingleChParams to fix
+*			CR #807563.
+* 2.2	bss	   04/27/14 Modified to use correct Device Config base address
+*						(CR#854437).
+* 2.3   mn     07/09/18 Fix Doxygen warning
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ + +#include "xadcps.h" + +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Function Prototypes *****************************/ + +void XAdcPs_WriteInternalReg(XAdcPs *InstancePtr, u32 RegOffset, u32 Data); +u32 XAdcPs_ReadInternalReg(XAdcPs *InstancePtr, u32 RegOffset); + + +/************************** Variable Definitions ****************************/ + + +/*****************************************************************************/ +/** +* +* This function initializes a specific XAdcPs device/instance. This function +* must be called prior to using the XADC device. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param ConfigPtr points to the XAdcPs device configuration structure. +* @param EffectiveAddr is the device base address in the virtual memory +* address space. If the address translation is not used then the +* physical address is passed. +* Unexpected errors may occur if the address mapping is changed +* after this function is invoked. +* +* @return +* - XST_SUCCESS if successful. +* +* @note The user needs to first call the XAdcPs_LookupConfig() API +* which returns the Configuration structure pointer which is +* passed as a parameter to the XAdcPs_CfgInitialize() API. +* +******************************************************************************/ +int XAdcPs_CfgInitialize(XAdcPs *InstancePtr, XAdcPs_Config *ConfigPtr, + u32 EffectiveAddr) +{ + + u32 RegValue; + /* + * Assert the input arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(ConfigPtr != NULL); + + + /* + * Set the values read from the device config and the base address. + */ + InstancePtr->Config.DeviceId = ConfigPtr->DeviceId; + InstancePtr->Config.BaseAddress = EffectiveAddr; + + /* Write Unlock value to Device Config Unlock register */ + XAdcPs_WriteReg(XPAR_XDCFG_0_BASEADDR, + XADCPS_UNLK_OFFSET, XADCPS_UNLK_VALUE); + + /* Enable the PS access of xadc and set FIFO thresholds */ + + RegValue = XAdcPs_ReadReg((InstancePtr)->Config.BaseAddress, + XADCPS_CFG_OFFSET); + + RegValue = RegValue | XADCPS_CFG_ENABLE_MASK | + XADCPS_CFG_CFIFOTH_MASK | XADCPS_CFG_DFIFOTH_MASK; + + XAdcPs_WriteReg((InstancePtr)->Config.BaseAddress, + XADCPS_CFG_OFFSET, RegValue); + + /* Release xadc from reset */ + + XAdcPs_WriteReg((InstancePtr)->Config.BaseAddress, + XADCPS_MCTL_OFFSET, 0x00); + + /* + * Indicate the instance is now ready to use and + * initialized without error. + */ + InstancePtr->IsReady = XIL_COMPONENT_IS_READY; + + return XST_SUCCESS; +} + + +/****************************************************************************/ +/** +* +* The functions sets the contents of the Config Register. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param Data is the 32 bit data to be written to the Register. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XAdcPs_SetConfigRegister(XAdcPs *InstancePtr, u32 Data) +{ + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + XAdcPs_WriteReg((InstancePtr)->Config.BaseAddress, + XADCPS_CFG_OFFSET, Data); + +} + + +/****************************************************************************/ +/** +* +* The functions reads the contents of the Config Register. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @return A 32-bit value representing the contents of the Config Register. +* Use the XADCPS_SR_*_MASK constants defined in xadcps_hw.h to +* interpret the returned value. +* +* @note None. +* +*****************************************************************************/ +u32 XAdcPs_GetConfigRegister(XAdcPs *InstancePtr) +{ + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the Config Register and return the value. + */ + return XAdcPs_ReadReg((InstancePtr)->Config.BaseAddress, + XADCPS_CFG_OFFSET); +} + + +/****************************************************************************/ +/** +* +* The functions reads the contents of the Miscellaneous Status Register. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @return A 32-bit value representing the contents of the Miscellaneous +* Status Register. Use the XADCPS_MSTS_*_MASK constants defined +* in xadcps_hw.h to interpret the returned value. +* +* @note None. +* +*****************************************************************************/ +u32 XAdcPs_GetMiscStatus(XAdcPs *InstancePtr) +{ + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the Miscellaneous Status Register and return the value. + */ + return XAdcPs_ReadReg((InstancePtr)->Config.BaseAddress, + XADCPS_MSTS_OFFSET); +} + + +/****************************************************************************/ +/** +* +* The functions sets the contents of the Miscellaneous Control register. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param Data is the 32 bit data to be written to the Register. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XAdcPs_SetMiscCtrlRegister(XAdcPs *InstancePtr, u32 Data) +{ + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Write to the Miscellaneous control register Register. + */ + XAdcPs_WriteReg((InstancePtr)->Config.BaseAddress, + XADCPS_MCTL_OFFSET, Data); +} + + +/****************************************************************************/ +/** +* +* The functions reads the contents of the Miscellaneous control register. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @return A 32-bit value representing the contents of the Config Register. +* Use the XADCPS_SR_*_MASK constants defined in xadcps_hw.h to +* interpret the returned value. +* +* @note None. +* +*****************************************************************************/ +u32 XAdcPs_GetMiscCtrlRegister(XAdcPs *InstancePtr) +{ + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the Miscellaneous control register and return the value. + */ + return XAdcPs_ReadReg((InstancePtr)->Config.BaseAddress, + XADCPS_MCTL_OFFSET); +} + + +/*****************************************************************************/ +/** +* +* This function resets the XADC Hard Macro in the device. +* +* @param InstancePtr is a pointer to the Xxadc instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XAdcPs_Reset(XAdcPs *InstancePtr) +{ + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Generate the reset by Control + * register and release from reset + */ + XAdcPs_WriteReg((InstancePtr)->Config.BaseAddress, + XADCPS_MCTL_OFFSET, 0x10); + XAdcPs_WriteReg((InstancePtr)->Config.BaseAddress, + XADCPS_MCTL_OFFSET, 0x00); +} + + +/****************************************************************************/ +/** +* +* Get the ADC converted data for the specified channel. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param Channel is the channel number. Use the XADCPS_CH_* defined in +* the file xadcps.h. +* The valid channels are +* - 0 to 6 +* - 13 to 31 +* +* @return A 16-bit value representing the ADC converted data for the +* specified channel. The XADC Monitor/ADC device guarantees +* a 10 bit resolution for the ADC converted data and data is the +* 10 MSB bits of the 16 data read from the device. +* +* @note The channels 7,8,9 are used for calibration of the device and +* hence there is no associated data with this channel. +* +*****************************************************************************/ +u16 XAdcPs_GetAdcData(XAdcPs *InstancePtr, u8 Channel) +{ + + u32 RegData; + + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid((Channel <= XADCPS_CH_VBRAM) || + ((Channel >= XADCPS_CH_VCCPINT) && + (Channel <= XADCPS_CH_AUX_MAX))); + + RegData = XAdcPs_ReadInternalReg(InstancePtr, + (XADCPS_TEMP_OFFSET + + Channel)); + return (u16) RegData; +} + +/****************************************************************************/ +/** +* +* This function gets the calibration coefficient data for the specified +* parameter. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param CoeffType specifies the calibration coefficient +* to be read. Use XADCPS_CALIB_* constants defined in xadcps.h to +* specify the calibration coefficient to be read. +* +* @return A 16-bit value representing the calibration coefficient. +* The XADC device guarantees a 10 bit resolution for +* the ADC converted data and data is the 10 MSB bits of the 16 +* data read from the device. +* +* @note None. +* +*****************************************************************************/ +u16 XAdcPs_GetCalibCoefficient(XAdcPs *InstancePtr, u8 CoeffType) +{ + u32 RegData; + + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(CoeffType <= XADCPS_CALIB_GAIN_ERROR_COEFF); + + /* + * Read the selected calibration coefficient. + */ + RegData = XAdcPs_ReadInternalReg(InstancePtr, + (XADCPS_ADC_A_SUPPLY_CALIB_OFFSET + + CoeffType)); + return (u16) RegData; +} + +/****************************************************************************/ +/** +* +* This function reads the Minimum/Maximum measurement for one of the +* specified parameters. Use XADCPS_MAX_* and XADCPS_MIN_* constants defined in +* xadcps.h to specify the parameters (Temperature, VccInt, VccAux, VBram, +* VccPInt, VccPAux and VccPDro). +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param MeasurementType specifies the parameter for which the +* Minimum/Maximum measurement has to be read. +* Use XADCPS_MAX_* and XADCPS_MIN_* constants defined in xadcps.h to +* specify the data to be read. +* +* @return A 16-bit value representing the maximum/minimum measurement for +* specified parameter. +* The XADC device guarantees a 10 bit resolution for +* the ADC converted data and data is the 10 MSB bits of the 16 +* data read from the device. +* +* @note None. +* +*****************************************************************************/ +u16 XAdcPs_GetMinMaxMeasurement(XAdcPs *InstancePtr, u8 MeasurementType) +{ + u32 RegData; + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid((MeasurementType <= XADCPS_MAX_VCCPDRO) || + ((MeasurementType >= XADCPS_MIN_VCCPINT) && + (MeasurementType <= XADCPS_MIN_VCCPDRO))) + + /* + * Read and return the specified Minimum/Maximum measurement. + */ + RegData = XAdcPs_ReadInternalReg(InstancePtr, + (XADCPS_MAX_TEMP_OFFSET + + MeasurementType)); + return (u16) RegData; +} + +/****************************************************************************/ +/** +* +* This function sets the number of samples of averaging that is to be done for +* all the channels in both the single channel mode and sequence mode of +* operations. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param Average is the number of samples of averaging programmed to the +* Configuration Register 0. Use the XADCPS_AVG_* definitions defined +* in xadcps.h file : +* - XADCPS_AVG_0_SAMPLES for no averaging +* - XADCPS_AVG_16_SAMPLES for 16 samples of averaging +* - XADCPS_AVG_64_SAMPLES for 64 samples of averaging +* - XADCPS_AVG_256_SAMPLES for 256 samples of averaging +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XAdcPs_SetAvg(XAdcPs *InstancePtr, u8 Average) +{ + u32 RegData; + + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Average <= XADCPS_AVG_256_SAMPLES); + + /* + * Write the averaging value into the Configuration Register 0. + */ + RegData = XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_CFR0_OFFSET) & + (~XADCPS_CFR0_AVG_VALID_MASK); + + RegData |= (((u32) Average << XADCPS_CFR0_AVG_SHIFT)); + XAdcPs_WriteInternalReg(InstancePtr, XADCPS_CFR0_OFFSET, + RegData); + +} + +/****************************************************************************/ +/** +* +* This function returns the number of samples of averaging configured for all +* the channels in the Configuration Register 0. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @return The averaging read from the Configuration Register 0 is +* returned. Use the XADCPS_AVG_* bit definitions defined in +* xadcps.h file to interpret the returned value : +* - XADCPS_AVG_0_SAMPLES means no averaging +* - XADCPS_AVG_16_SAMPLES means 16 samples of averaging +* - XADCPS_AVG_64_SAMPLES means 64 samples of averaging +* - XADCPS_AVG_256_SAMPLES means 256 samples of averaging +* +* @note None. +* +*****************************************************************************/ +u8 XAdcPs_GetAvg(XAdcPs *InstancePtr) +{ + u32 Average; + + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the averaging value from the Configuration Register 0. + */ + Average = XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_CFR0_OFFSET) & XADCPS_CFR0_AVG_VALID_MASK; + + + return ((u8) (Average >> XADCPS_CFR0_AVG_SHIFT)); +} + +/****************************************************************************/ +/** +* +* The function sets the given parameters in the Configuration Register 0 in +* the single channel mode. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param Channel is the channel number for the singel channel mode. +* The valid channels are 0 to 6, 8, and 13 to 31. +* If the external Mux is used then this specifies the channel +* oonnected to the external Mux. Please read the Device Spec +* to know which channels are valid. +* @param IncreaseAcqCycles is a boolean parameter which specifies whether +* the Acquisition time for the external channels has to be +* increased to 10 ADCCLK cycles (specify TRUE) or remain at the +* default 4 ADCCLK cycles (specify FALSE). This parameter is +* only valid for the external channels. +* @param IsEventMode specifies whether the operation of the ADC is Event +* driven or Continuous mode. +* @param IsDifferentialMode is a boolean parameter which specifies +* unipolar(specify FALSE) or differential mode (specify TRUE) for +* the analog inputs. The input mode is only valid for the +* external channels. +* +* @return +* - XST_SUCCESS if the given values were written successfully to +* the Configuration Register 0. +* - XST_FAILURE if the channel sequencer is enabled or the input +* parameters are not valid for the selected channel. +* +* @note +* - The number of samples for the averaging for all the channels +* is set by using the function XAdcPs_SetAvg. +* - The calibration of the device is done by doing a ADC +* conversion on the calibration channel(channel 8). The input +* parameters IncreaseAcqCycles, IsDifferentialMode and +* IsEventMode are not valid for this channel +* +* +*****************************************************************************/ +int XAdcPs_SetSingleChParams(XAdcPs *InstancePtr, + u8 Channel, + int IncreaseAcqCycles, + int IsEventMode, + int IsDifferentialMode) +{ + u32 RegValue; + + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid((Channel <= XADCPS_CH_VBRAM) || + (Channel == XADCPS_CH_ADC_CALIB) || + ((Channel >= XADCPS_CH_VCCPINT) && + (Channel <= XADCPS_CH_AUX_MAX))); + Xil_AssertNonvoid((IncreaseAcqCycles == TRUE) || + (IncreaseAcqCycles == FALSE)); + Xil_AssertNonvoid((IsEventMode == TRUE) || (IsEventMode == FALSE)); + Xil_AssertNonvoid((IsDifferentialMode == TRUE) || + (IsDifferentialMode == FALSE)); + + /* + * Check if the device is in single channel mode else return failure + */ + if ((XAdcPs_GetSequencerMode(InstancePtr) != + XADCPS_SEQ_MODE_SINGCHAN)) { + return XST_FAILURE; + } + + /* + * Read the Configuration Register 0. + */ + RegValue = XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_CFR0_OFFSET) & + XADCPS_CFR0_AVG_VALID_MASK; + + /* + * Select the number of acquisition cycles. The acquisition cycles is + * only valid for the external channels. + */ + if (IncreaseAcqCycles == TRUE) { + if (((Channel >= XADCPS_CH_AUX_MIN) && + (Channel <= XADCPS_CH_AUX_MAX)) || + (Channel == XADCPS_CH_VPVN)){ + RegValue |= XADCPS_CFR0_ACQ_MASK; + } else { + return XST_FAILURE; + } + + } + + /* + * Select the input mode. The input mode is only valid for the + * external channels. + */ + if (IsDifferentialMode == TRUE) { + + if (((Channel >= XADCPS_CH_AUX_MIN) && + (Channel <= XADCPS_CH_AUX_MAX)) || + (Channel == XADCPS_CH_VPVN)){ + RegValue |= XADCPS_CFR0_DU_MASK; + } else { + return XST_FAILURE; + } + } + + /* + * Select the ADC mode. + */ + if (IsEventMode == TRUE) { + RegValue |= XADCPS_CFR0_EC_MASK; + } + + /* + * Write the given values into the Configuration Register 0. + */ + RegValue |= (Channel & XADCPS_CFR0_CHANNEL_MASK); + XAdcPs_WriteInternalReg(InstancePtr, XADCPS_CFR0_OFFSET, + RegValue); + + return XST_SUCCESS; +} + +/****************************************************************************/ +/** +* +* This function enables the alarm outputs for the specified alarms in the +* Configuration Register 1. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param AlmEnableMask is the bit-mask of the alarm outputs to be enabled +* in the Configuration Register 1. +* Bit positions of 1 will be enabled. Bit positions of 0 will be +* disabled. This mask is formed by OR'ing XADCPS_CFR1_ALM_*_MASK and +* XADCPS_CFR1_OT_MASK masks defined in xadcps_hw.h. +* +* @return None. +* +* @note The implementation of the alarm enables in the Configuration +* register 1 is such that the alarms for bit positions of 1 will +* be disabled and alarms for bit positions of 0 will be enabled. +* The alarm outputs specified by the AlmEnableMask are negated +* before writing to the Configuration Register 1. +* +* +*****************************************************************************/ +void XAdcPs_SetAlarmEnables(XAdcPs *InstancePtr, u16 AlmEnableMask) +{ + u32 RegValue; + + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + + RegValue = XAdcPs_ReadInternalReg(InstancePtr, XADCPS_CFR1_OFFSET); + + RegValue &= (u32)~XADCPS_CFR1_ALM_ALL_MASK; + RegValue |= (~AlmEnableMask & XADCPS_CFR1_ALM_ALL_MASK); + + /* + * Enable/disables the alarm enables for the specified alarm bits in the + * Configuration Register 1. + */ + XAdcPs_WriteInternalReg(InstancePtr, XADCPS_CFR1_OFFSET, + RegValue); +} + +/****************************************************************************/ +/** +* +* This function gets the status of the alarm output enables in the +* Configuration Register 1. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @return This is the bit-mask of the enabled alarm outputs in the +* Configuration Register 1. Use the masks XADCPS_CFR1_ALM*_* and +* XADCPS_CFR1_OT_MASK defined in xadcps_hw.h to interpret the +* returned value. +* Bit positions of 1 indicate that the alarm output is enabled. +* Bit positions of 0 indicate that the alarm output is disabled. +* +* +* @note The implementation of the alarm enables in the Configuration +* register 1 is such that alarms for the bit positions of 1 will +* be disabled and alarms for bit positions of 0 will be enabled. +* The enabled alarm outputs returned by this function is the +* negated value of the the data read from the Configuration +* Register 1. +* +*****************************************************************************/ +u16 XAdcPs_GetAlarmEnables(XAdcPs *InstancePtr) +{ + u32 RegValue; + + /* + * Assert the arguments + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the status of alarm output enables from the Configuration + * Register 1. + */ + RegValue = XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_CFR1_OFFSET) & XADCPS_CFR1_ALM_ALL_MASK; + return (u16) (~RegValue & XADCPS_CFR1_ALM_ALL_MASK); +} + +/****************************************************************************/ +/** +* +* This function enables the specified calibration in the Configuration +* Register 1 : +* +* - XADCPS_CFR1_CAL_ADC_OFFSET_MASK : Calibration 0 -ADC offset correction +* - XADCPS_CFR1_CAL_ADC_GAIN_OFFSET_MASK : Calibration 1 -ADC gain and offset +* correction +* - XADCPS_CFR1_CAL_PS_OFFSET_MASK : Calibration 2 -Power Supply sensor +* offset correction +* - XADCPS_CFR1_CAL_PS_GAIN_OFFSET_MASK : Calibration 3 -Power Supply sensor +* gain and offset correction +* - XADCPS_CFR1_CAL_DISABLE_MASK : No Calibration +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param Calibration is the Calibration to be applied. +* Use XADCPS_CFR1_CAL*_* bits defined in xadcps_hw.h. +* Multiple calibrations can be enabled at a time by oring the +* XADCPS_CFR1_CAL_ADC_* and XADCPS_CFR1_CAL_PS_* bits. +* Calibration can be disabled by specifying + XADCPS_CFR1_CAL_DISABLE_MASK; +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XAdcPs_SetCalibEnables(XAdcPs *InstancePtr, u16 Calibration) +{ + u32 RegValue; + + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(((Calibration >= XADCPS_CFR1_CAL_ADC_OFFSET_MASK) && + (Calibration <= XADCPS_CFR1_CAL_VALID_MASK)) || + (Calibration == XADCPS_CFR1_CAL_DISABLE_MASK)); + + /* + * Set the specified calibration in the Configuration Register 1. + */ + RegValue = XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_CFR1_OFFSET); + + RegValue &= (~ XADCPS_CFR1_CAL_VALID_MASK); + RegValue |= (Calibration & XADCPS_CFR1_CAL_VALID_MASK); + XAdcPs_WriteInternalReg(InstancePtr, XADCPS_CFR1_OFFSET, + RegValue); + +} + +/****************************************************************************/ +/** +* +* This function reads the value of the calibration enables from the +* Configuration Register 1. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @return The value of the calibration enables in the Configuration +* Register 1 : +* - XADCPS_CFR1_CAL_ADC_OFFSET_MASK : ADC offset correction +* - XADCPS_CFR1_CAL_ADC_GAIN_OFFSET_MASK : ADC gain and offset +* correction +* - XADCPS_CFR1_CAL_PS_OFFSET_MASK : Power Supply sensor offset +* correction +* - XADCPS_CFR1_CAL_PS_GAIN_OFFSET_MASK : Power Supply sensor +* gain and offset correction +* - XADCPS_CFR1_CAL_DISABLE_MASK : No Calibration +* +* @note None. +* +*****************************************************************************/ +u16 XAdcPs_GetCalibEnables(XAdcPs *InstancePtr) +{ + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the calibration enables from the Configuration Register 1. + */ + return (u16) XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_CFR1_OFFSET) & XADCPS_CFR1_CAL_VALID_MASK; + +} + +/****************************************************************************/ +/** +* +* This function sets the specified Channel Sequencer Mode in the Configuration +* Register 1 : +* - Default safe mode (XADCPS_SEQ_MODE_SAFE) +* - One pass through sequence (XADCPS_SEQ_MODE_ONEPASS) +* - Continuous channel sequencing (XADCPS_SEQ_MODE_CONTINPASS) +* - Single Channel/Sequencer off (XADCPS_SEQ_MODE_SINGCHAN) +* - Simulataneous sampling mode (XADCPS_SEQ_MODE_SIMUL_SAMPLING) +* - Independent mode (XADCPS_SEQ_MODE_INDEPENDENT) +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param SequencerMode is the sequencer mode to be set. +* Use XADCPS_SEQ_MODE_* bits defined in xadcps.h. +* @return None. +* +* @note Only one of the modes can be enabled at a time. Please +* read the Spec of the XADC for further information about the +* sequencer modes. +* +* +*****************************************************************************/ +void XAdcPs_SetSequencerMode(XAdcPs *InstancePtr, u8 SequencerMode) +{ + u32 RegValue; + + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid((SequencerMode <= XADCPS_SEQ_MODE_SIMUL_SAMPLING) || + (SequencerMode == XADCPS_SEQ_MODE_INDEPENDENT)); + + /* + * Set the specified sequencer mode in the Configuration Register 1. + */ + RegValue = XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_CFR1_OFFSET); + RegValue &= (~ XADCPS_CFR1_SEQ_VALID_MASK); + RegValue |= ((SequencerMode << XADCPS_CFR1_SEQ_SHIFT) & + XADCPS_CFR1_SEQ_VALID_MASK); + XAdcPs_WriteInternalReg(InstancePtr, XADCPS_CFR1_OFFSET, + RegValue); + +} + +/****************************************************************************/ +/** +* +* This function gets the channel sequencer mode from the Configuration +* Register 1. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @return The channel sequencer mode : +* - XADCPS_SEQ_MODE_SAFE : Default safe mode +* - XADCPS_SEQ_MODE_ONEPASS : One pass through sequence +* - XADCPS_SEQ_MODE_CONTINPASS : Continuous channel sequencing +* - XADCPS_SEQ_MODE_SINGCHAN : Single channel/Sequencer off +* - XADCPS_SEQ_MODE_SIMUL_SAMPLING : Simulataneous sampling mode +* - XADCPS_SEQ_MODE_INDEPENDENT : Independent mode +* +* +* @note None. +* +*****************************************************************************/ +u8 XAdcPs_GetSequencerMode(XAdcPs *InstancePtr) +{ + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the channel sequencer mode from the Configuration Register 1. + */ + return ((u8) ((XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_CFR1_OFFSET) & XADCPS_CFR1_SEQ_VALID_MASK) >> + XADCPS_CFR1_SEQ_SHIFT)); + +} + +/****************************************************************************/ +/** +* +* The function sets the frequency of the ADCCLK by configuring the DCLK to +* ADCCLK ratio in the Configuration Register #2 +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param Divisor is clock divisor used to derive ADCCLK from DCLK. +* Valid values of the divisor are +* - 0 to 255. Values 0, 1, 2 are all mapped to 2. +* Refer to the device specification for more details +* +* @return None. +* +* @note - The ADCCLK is an internal clock used by the ADC and is +* synchronized to the DCLK clock. The ADCCLK is equal to DCLK +* divided by the user selection in the Configuration Register 2. +* - There is no Assert on the minimum value of the Divisor. +* +*****************************************************************************/ +void XAdcPs_SetAdcClkDivisor(XAdcPs *InstancePtr, u8 Divisor) +{ + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Write the divisor value into the Configuration Register #2. + */ + XAdcPs_WriteInternalReg(InstancePtr, XADCPS_CFR2_OFFSET, + Divisor << XADCPS_CFR2_CD_SHIFT); + +} + +/****************************************************************************/ +/** +* +* The function gets the ADCCLK divisor from the Configuration Register 2. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @return The divisor read from the Configuration Register 2. +* +* @note The ADCCLK is an internal clock used by the ADC and is +* synchronized to the DCLK clock. The ADCCLK is equal to DCLK +* divided by the user selection in the Configuration Register 2. +* +*****************************************************************************/ +u8 XAdcPs_GetAdcClkDivisor(XAdcPs *InstancePtr) +{ + u16 Divisor; + + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the divisor value from the Configuration Register 2. + */ + Divisor = (u16) XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_CFR2_OFFSET); + + return (u8) (Divisor >> XADCPS_CFR2_CD_SHIFT); +} + +/****************************************************************************/ +/** +* +* This function enables the specified channels in the ADC Channel Selection +* Sequencer Registers. The sequencer must be disabled before writing to these +* regsiters. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param ChEnableMask is the bit mask of all the channels to be enabled. +* Use XADCPS_SEQ_CH__* defined in xadcps_hw.h to specify the Channel +* numbers. Bit masks of 1 will be enabled and bit mask of 0 will +* be disabled. +* The ChEnableMask is a 32 bit mask that is written to the two +* 16 bit ADC Channel Selection Sequencer Registers. +* +* @return +* - XST_SUCCESS if the given values were written successfully to +* the ADC Channel Selection Sequencer Registers. +* - XST_FAILURE if the channel sequencer is enabled. +* +* @note None +* +*****************************************************************************/ +int XAdcPs_SetSeqChEnables(XAdcPs *InstancePtr, u32 ChEnableMask) +{ + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * The sequencer must be disabled for writing any of these registers + * Return XST_FAILURE if the channel sequencer is enabled. + */ + if ((XAdcPs_GetSequencerMode(InstancePtr) != XADCPS_SEQ_MODE_SAFE)) { + return XST_FAILURE; + } + + /* + * Enable the specified channels in the ADC Channel Selection Sequencer + * Registers. + */ + XAdcPs_WriteInternalReg(InstancePtr, + XADCPS_SEQ00_OFFSET, + (ChEnableMask & XADCPS_SEQ00_CH_VALID_MASK)); + + XAdcPs_WriteInternalReg(InstancePtr, + XADCPS_SEQ01_OFFSET, + (ChEnableMask >> XADCPS_SEQ_CH_AUX_SHIFT) & + XADCPS_SEQ01_CH_VALID_MASK); + + return XST_SUCCESS; +} + +/****************************************************************************/ +/** +* +* This function gets the channel enable bits status from the ADC Channel +* Selection Sequencer Registers. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @return Gets the channel enable bits. Use XADCPS_SEQ_CH__* defined in +* xadcps_hw.h to interpret the Channel numbers. Bit masks of 1 +* are the channels that are enabled and bit mask of 0 are +* the channels that are disabled. +* +* @return None +* +* @note None +* +*****************************************************************************/ +u32 XAdcPs_GetSeqChEnables(XAdcPs *InstancePtr) +{ + u32 RegValEnable; + + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the channel enable bits for all the channels from the ADC + * Channel Selection Register. + */ + RegValEnable = XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_SEQ00_OFFSET) & + XADCPS_SEQ00_CH_VALID_MASK; + RegValEnable |= (XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_SEQ01_OFFSET) & + XADCPS_SEQ01_CH_VALID_MASK) << + XADCPS_SEQ_CH_AUX_SHIFT; + + + return RegValEnable; +} + +/****************************************************************************/ +/** +* +* This function enables the averaging for the specified channels in the ADC +* Channel Averaging Enable Sequencer Registers. The sequencer must be disabled +* before writing to these regsiters. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param AvgEnableChMask is the bit mask of all the channels for which +* averaging is to be enabled. Use XADCPS_SEQ_CH__* defined in +* xadcps_hw.h to specify the Channel numbers. Averaging will be +* enabled for bit masks of 1 and disabled for bit mask of 0. +* The AvgEnableChMask is a 32 bit mask that is written to the two +* 16 bit ADC Channel Averaging Enable Sequencer Registers. +* +* @return +* - XST_SUCCESS if the given values were written successfully to +* the ADC Channel Averaging Enables Sequencer Registers. +* - XST_FAILURE if the channel sequencer is enabled. +* +* @note None +* +*****************************************************************************/ +int XAdcPs_SetSeqAvgEnables(XAdcPs *InstancePtr, u32 AvgEnableChMask) +{ + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * The sequencer must be disabled for writing any of these registers + * Return XST_FAILURE if the channel sequencer is enabled. + */ + if ((XAdcPs_GetSequencerMode(InstancePtr) != XADCPS_SEQ_MODE_SAFE)) { + return XST_FAILURE; + } + + /* + * Enable/disable the averaging for the specified channels in the + * ADC Channel Averaging Enables Sequencer Registers. + */ + XAdcPs_WriteInternalReg(InstancePtr, + XADCPS_SEQ02_OFFSET, + (AvgEnableChMask & XADCPS_SEQ02_CH_VALID_MASK)); + + XAdcPs_WriteInternalReg(InstancePtr, + XADCPS_SEQ03_OFFSET, + (AvgEnableChMask >> XADCPS_SEQ_CH_AUX_SHIFT) & + XADCPS_SEQ03_CH_VALID_MASK); + + return XST_SUCCESS; +} + +/****************************************************************************/ +/** +* +* This function returns the channels for which the averaging has been enabled +* in the ADC Channel Averaging Enables Sequencer Registers. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @returns The status of averaging (enabled/disabled) for all the channels. +* Use XADCPS_SEQ_CH__* defined in xadcps_hw.h to interpret the +* Channel numbers. Bit masks of 1 are the channels for which +* averaging is enabled and bit mask of 0 are the channels for +* averaging is disabled +* +* @note None +* +*****************************************************************************/ +u32 XAdcPs_GetSeqAvgEnables(XAdcPs *InstancePtr) +{ + u32 RegValAvg; + + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the averaging enable status for all the channels from the + * ADC Channel Averaging Enables Sequencer Registers. + */ + RegValAvg = XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_SEQ02_OFFSET) & XADCPS_SEQ02_CH_VALID_MASK; + RegValAvg |= (XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_SEQ03_OFFSET) & XADCPS_SEQ03_CH_VALID_MASK) << + XADCPS_SEQ_CH_AUX_SHIFT; + + return RegValAvg; +} + +/****************************************************************************/ +/** +* +* This function sets the Analog input mode for the specified channels in the ADC +* Channel Analog-Input Mode Sequencer Registers. The sequencer must be disabled +* before writing to these regsiters. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param InputModeChMask is the bit mask of all the channels for which +* the input mode is differential mode. Use XADCPS_SEQ_CH__* defined +* in xadcps_hw.h to specify the channel numbers. Differential +* input mode will be set for bit masks of 1 and unipolar input +* mode for bit masks of 0. +* The InputModeChMask is a 32 bit mask that is written to the two +* 16 bit ADC Channel Analog-Input Mode Sequencer Registers. +* +* @return +* - XST_SUCCESS if the given values were written successfully to +* the ADC Channel Analog-Input Mode Sequencer Registers. +* - XST_FAILURE if the channel sequencer is enabled. +* +* @note None +* +*****************************************************************************/ +int XAdcPs_SetSeqInputMode(XAdcPs *InstancePtr, u32 InputModeChMask) +{ + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * The sequencer must be disabled for writing any of these registers + * Return XST_FAILURE if the channel sequencer is enabled. + */ + if ((XAdcPs_GetSequencerMode(InstancePtr) != XADCPS_SEQ_MODE_SAFE)) { + return XST_FAILURE; + } + + /* + * Set the input mode for the specified channels in the ADC Channel + * Analog-Input Mode Sequencer Registers. + */ + XAdcPs_WriteInternalReg(InstancePtr, + XADCPS_SEQ04_OFFSET, + (InputModeChMask & XADCPS_SEQ04_CH_VALID_MASK)); + + XAdcPs_WriteInternalReg(InstancePtr, + XADCPS_SEQ05_OFFSET, + (InputModeChMask >> XADCPS_SEQ_CH_AUX_SHIFT) & + XADCPS_SEQ05_CH_VALID_MASK); + + return XST_SUCCESS; +} + +/****************************************************************************/ +/** +* +* This function gets the Analog input mode for all the channels from +* the ADC Channel Analog-Input Mode Sequencer Registers. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @returns The input mode for all the channels. +* Use XADCPS_SEQ_CH_* defined in xadcps_hw.h to interpret the +* Channel numbers. Bit masks of 1 are the channels for which +* input mode is differential and bit mask of 0 are the channels +* for which input mode is unipolar. +* +* @note None. +* +*****************************************************************************/ +u32 XAdcPs_GetSeqInputMode(XAdcPs *InstancePtr) +{ + u32 InputMode; + + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Get the input mode for all the channels from the ADC Channel + * Analog-Input Mode Sequencer Registers. + */ + InputMode = XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_SEQ04_OFFSET) & + XADCPS_SEQ04_CH_VALID_MASK; + InputMode |= (XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_SEQ05_OFFSET) & + XADCPS_SEQ05_CH_VALID_MASK) << + XADCPS_SEQ_CH_AUX_SHIFT; + + return InputMode; +} + +/****************************************************************************/ +/** +* +* This function sets the number of Acquisition cycles in the ADC Channel +* Acquisition Time Sequencer Registers. The sequencer must be disabled +* before writing to these regsiters. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param AcqCyclesChMask is the bit mask of all the channels for which +* the number of acquisition cycles is to be extended. +* Use XADCPS_SEQ_CH__* defined in xadcps_hw.h to specify the Channel +* numbers. Acquisition cycles will be extended to 10 ADCCLK cycles +* for bit masks of 1 and will be the default 4 ADCCLK cycles for +* bit masks of 0. +* The AcqCyclesChMask is a 32 bit mask that is written to the two +* 16 bit ADC Channel Acquisition Time Sequencer Registers. +* +* @return +* - XST_SUCCESS if the given values were written successfully to +* the Channel Sequencer Registers. +* - XST_FAILURE if the channel sequencer is enabled. +* +* @note None. +* +*****************************************************************************/ +int XAdcPs_SetSeqAcqTime(XAdcPs *InstancePtr, u32 AcqCyclesChMask) +{ + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * The sequencer must be disabled for writing any of these registers + * Return XST_FAILURE if the channel sequencer is enabled. + */ + if ((XAdcPs_GetSequencerMode(InstancePtr) != + XADCPS_SEQ_MODE_SAFE)) { + return XST_FAILURE; + } + + /* + * Set the Acquisition time for the specified channels in the + * ADC Channel Acquisition Time Sequencer Registers. + */ + XAdcPs_WriteInternalReg(InstancePtr, + XADCPS_SEQ06_OFFSET, + (AcqCyclesChMask & XADCPS_SEQ06_CH_VALID_MASK)); + + XAdcPs_WriteInternalReg(InstancePtr, + XADCPS_SEQ07_OFFSET, + (AcqCyclesChMask >> XADCPS_SEQ_CH_AUX_SHIFT) & + XADCPS_SEQ07_CH_VALID_MASK); + + return XST_SUCCESS; +} + +/****************************************************************************/ +/** +* +* This function gets the status of acquisition from the ADC Channel Acquisition +* Time Sequencer Registers. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @returns The acquisition time for all the channels. +* Use XADCPS_SEQ_CH__* defined in xadcps_hw.h to interpret the +* Channel numbers. Bit masks of 1 are the channels for which +* acquisition cycles are extended and bit mask of 0 are the +* channels for which acquisition cycles are not extended. +* +* @note None +* +*****************************************************************************/ +u32 XAdcPs_GetSeqAcqTime(XAdcPs *InstancePtr) +{ + u32 RegValAcq; + + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Get the Acquisition cycles for the specified channels from the ADC + * Channel Acquisition Time Sequencer Registers. + */ + RegValAcq = XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_SEQ06_OFFSET) & + XADCPS_SEQ06_CH_VALID_MASK; + RegValAcq |= (XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_SEQ07_OFFSET) & + XADCPS_SEQ07_CH_VALID_MASK) << + XADCPS_SEQ_CH_AUX_SHIFT; + + return RegValAcq; +} + +/****************************************************************************/ +/** +* +* This functions sets the contents of the given Alarm Threshold Register. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param AlarmThrReg is the index of an Alarm Threshold Register to +* be set. Use XADCPS_ATR_* constants defined in xadcps.h to +* specify the index. +* @param Value is the 16-bit threshold value to write into the register. +* +* @return None. +* +* @note Use XAdcPs_SetOverTemp() to set the Over Temperature upper +* threshold value. +* +*****************************************************************************/ +void XAdcPs_SetAlarmThreshold(XAdcPs *InstancePtr, u8 AlarmThrReg, u16 Value) +{ + + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(AlarmThrReg <= XADCPS_ATR_VCCPDRO_LOWER); + + /* + * Write the value into the specified Alarm Threshold Register. + */ + XAdcPs_WriteInternalReg(InstancePtr, XADCPS_ATR_TEMP_UPPER_OFFSET + + AlarmThrReg,Value); + +} + +/****************************************************************************/ +/** +* +* This function returns the contents of the specified Alarm Threshold Register. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param AlarmThrReg is the index of an Alarm Threshold Register +* to be read. Use XADCPS_ATR_* constants defined in xadcps_hw.h +* to specify the index. +* +* @return A 16-bit value representing the contents of the selected Alarm +* Threshold Register. +* +* @note None. +* +*****************************************************************************/ +u16 XAdcPs_GetAlarmThreshold(XAdcPs *InstancePtr, u8 AlarmThrReg) +{ + u32 RegData; + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(AlarmThrReg <= XADCPS_ATR_VCCPDRO_LOWER); + + /* + * Read the specified Alarm Threshold Register and return + * the value + */ + RegData = XAdcPs_ReadInternalReg(InstancePtr, + (XADCPS_ATR_TEMP_UPPER_OFFSET + AlarmThrReg)); + + return (u16) RegData; +} + + +/****************************************************************************/ +/** +* +* This function enables programming of the powerdown temperature for the +* OverTemp signal in the OT Powerdown register. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XAdcPs_EnableUserOverTemp(XAdcPs *InstancePtr) +{ + u16 OtUpper; + + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the OT upper Alarm Threshold Register. + */ + OtUpper = XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_ATR_OT_UPPER_OFFSET); + OtUpper &= ~(XADCPS_ATR_OT_UPPER_ENB_MASK); + + /* + * Preserve the powerdown value and write OT enable value the into the + * OT Upper Alarm Threshold Register. + */ + OtUpper |= XADCPS_ATR_OT_UPPER_ENB_VAL; + XAdcPs_WriteInternalReg(InstancePtr, + XADCPS_ATR_OT_UPPER_OFFSET, OtUpper); +} + +/****************************************************************************/ +/** +* +* This function disables programming of the powerdown temperature for the +* OverTemp signal in the OT Powerdown register. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @return None. +* +* @note None. +* +* +*****************************************************************************/ +void XAdcPs_DisableUserOverTemp(XAdcPs *InstancePtr) +{ + u16 OtUpper; + + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the OT Upper Alarm Threshold Register. + */ + OtUpper = XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_ATR_OT_UPPER_OFFSET); + OtUpper &= ~(XADCPS_ATR_OT_UPPER_ENB_MASK); + + XAdcPs_WriteInternalReg(InstancePtr, + XADCPS_ATR_OT_UPPER_OFFSET, OtUpper); +} + + +/****************************************************************************/ +/** +* +* The function enables the Event mode or Continuous mode in the sequencer mode. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param IsEventMode is a boolean parameter that specifies continuous +* sampling (specify FALSE) or event driven sampling mode (specify +* TRUE) for the given channel. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XAdcPs_SetSequencerEvent(XAdcPs *InstancePtr, int IsEventMode) +{ + u32 RegValue; + + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid((IsEventMode == TRUE) || (IsEventMode == FALSE)); + + /* + * Read the Configuration Register 0. + */ + RegValue = XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_CFR0_OFFSET) & + (~XADCPS_CFR0_EC_MASK); + + /* + * Set the ADC mode. + */ + if (IsEventMode == TRUE) { + RegValue |= XADCPS_CFR0_EC_MASK; + } else { + RegValue &= ~XADCPS_CFR0_EC_MASK; + } + + XAdcPs_WriteInternalReg(InstancePtr, XADCPS_CFR0_OFFSET, + RegValue); +} + + +/****************************************************************************/ +/** +* +* This function returns the sampling mode. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @return The sampling mode +* - 0 specifies continuous sampling +* - 1 specifies event driven sampling mode +* +* @note None. +* +*****************************************************************************/ +int XAdcPs_GetSamplingMode(XAdcPs *InstancePtr) +{ + u32 Mode; + + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the sampling mode from the Configuration Register 0. + */ + Mode = XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_CFR0_OFFSET) & + XADCPS_CFR0_EC_MASK; + if (Mode) { + + return 1; + } + + return (0); +} + + +/****************************************************************************/ +/** +* +* This function sets the External Mux mode. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param MuxMode specifies whether External Mux is used +* - FALSE specifies NO external MUX +* - TRUE specifies External Mux is used +* @param Channel specifies the channel to be used for the +* external Mux. Please read the Device Spec for which +* channels are valid for which mode. +* +* @return None. +* +* @note There is no Assert in this function for checking the channel +* number if the external Mux is used. The user should provide a +* valid channel number. +* +*****************************************************************************/ +void XAdcPs_SetMuxMode(XAdcPs *InstancePtr, int MuxMode, u8 Channel) +{ + u32 RegValue; + + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid((MuxMode == TRUE) || (MuxMode == FALSE)); + + /* + * Read the Configuration Register 0. + */ + RegValue = XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_CFR0_OFFSET) & + (~XADCPS_CFR0_MUX_MASK); + /* + * Select the Mux mode and the channel to be used. + */ + if (MuxMode == TRUE) { + RegValue |= XADCPS_CFR0_MUX_MASK; + RegValue |= (Channel & XADCPS_CFR0_CHANNEL_MASK); + + } + + /* + * Write the mux mode into the Configuration Register 0. + */ + XAdcPs_WriteInternalReg(InstancePtr, XADCPS_CFR0_OFFSET, + RegValue); +} + + +/****************************************************************************/ +/** +* +* This function sets the Power Down mode. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param Mode specifies the Power Down Mode +* - XADCPS_PD_MODE_NONE specifies NO Power Down (Both ADC A and +* ADC B are enabled) +* - XADCPS_PD_MODE_ADCB specfies the Power Down of ADC B +* - XADCPS_PD_MODE_XADC specifies the Power Down of +* both ADC A and ADC B. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XAdcPs_SetPowerdownMode(XAdcPs *InstancePtr, u32 Mode) +{ + u32 RegValue; + + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Mode < XADCPS_PD_MODE_XADC); + + + /* + * Read the Configuration Register 2. + */ + RegValue = XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_CFR2_OFFSET) & + (~XADCPS_CFR2_PD_MASK); + /* + * Select the Power Down mode. + */ + RegValue |= (Mode << XADCPS_CFR2_PD_SHIFT); + + XAdcPs_WriteInternalReg(InstancePtr, XADCPS_CFR2_OFFSET, + RegValue); +} + +/****************************************************************************/ +/** +* +* This function gets the Power Down mode. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @return Mode specifies the Power Down Mode +* - XADCPS_PD_MODE_NONE specifies NO Power Down (Both ADC A and +* ADC B are enabled) +* - XADCPS_PD_MODE_ADCB specfies the Power Down of ADC B +* - XADCPS_PD_MODE_XADC specifies the Power Down of +* both ADC A and ADC B. +* +* @note None. +* +*****************************************************************************/ +u32 XAdcPs_GetPowerdownMode(XAdcPs *InstancePtr) +{ + u32 RegValue; + + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the Power Down Mode. + */ + RegValue = XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_CFR2_OFFSET) & + (~XADCPS_CFR2_PD_MASK); + /* + * Return the Power Down mode. + */ + return (RegValue >> XADCPS_CFR2_PD_SHIFT); + +} + +/****************************************************************************/ +/** +* +* This function is used for writing to XADC Registers using the command FIFO. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param RegOffset is the offset of the XADC register to be written. +* @param Data is the data to be written. +* +* @return None. +* +* @note None. +* +* +*****************************************************************************/ +void XAdcPs_WriteInternalReg(XAdcPs *InstancePtr, u32 RegOffset, u32 Data) +{ + u32 RegData; + + /* + * Write the Data into the FIFO Register. + */ + RegData = XAdcPs_FormatWriteData(RegOffset, Data, TRUE); + + XAdcPs_WriteFifo(InstancePtr, RegData); + + /* Read the Read FIFO after any write since for each write + * one location of Read FIFO gets updated + */ + XAdcPs_ReadFifo(InstancePtr); + +} + + +/****************************************************************************/ +/** +* +* This function is used for reading from the XADC Registers using the Data FIFO. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param RegOffset is the offset of the XADC register to be read. +* +* @return Data read from the FIFO +* +* @note None. +* +* +*****************************************************************************/ +u32 XAdcPs_ReadInternalReg(XAdcPs *InstancePtr, u32 RegOffset) +{ + + u32 RegData; + + RegData = XAdcPs_FormatWriteData(RegOffset, 0x0, FALSE); + + /* Read cmd to FIFO*/ + XAdcPs_WriteFifo(InstancePtr, RegData); + + /* Do a Dummy read */ + RegData = XAdcPs_ReadFifo(InstancePtr); + + /* Do a Dummy write to get the actual read */ + XAdcPs_WriteFifo(InstancePtr, RegData); + + /* Do the Actual read */ + RegData = XAdcPs_ReadFifo(InstancePtr); + + return RegData; + +} +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/xadcps_v2_3/src/xadcps.h b/df_datalink/bsp/ps7_cortexa9_0/libsrc/xadcps_v2_3/src/xadcps.h new file mode 100644 index 0000000..900edf0 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/xadcps_v2_3/src/xadcps.h @@ -0,0 +1,589 @@ +/****************************************************************************** +* +* Copyright (C) 2011 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xadcps.h +* @addtogroup xadcps_v2_3 +* @{ +* @details +* +* The XAdcPs driver supports the Xilinx XADC/ADC device. +* +* The XADC/ADC device has the following features: +* - 10-bit, 200-KSPS (kilo samples per second) +* Analog-to-Digital Converter (ADC) +* - Monitoring of on-chip supply voltages and temperature +* - 1 dedicated differential analog-input pair and +* 16 auxiliary differential analog-input pairs +* - Automatic alarms based on user defined limits for the on-chip +* supply voltages and temperature +* - Automatic Channel Sequencer, programmable averaging, programmable +* acquisition time for the external inputs, unipolar or differential +* input selection for the external inputs +* - Inbuilt Calibration +* - Optional interrupt request generation +* +* +* The user should refer to the hardware device specification for detailed +* information about the device. +* +* This header file contains the prototypes of driver functions that can +* be used to access the XADC/ADC device. +* +* +* XADC Channel Sequencer Modes +* +* The XADC Channel Sequencer supports the following operating modes: +* +* - Default : This is the default mode after power up. +* In this mode of operation the XADC operates in +* a sequence mode, monitoring the on chip sensors: +* Temperature, VCCINT, and VCCAUX. +* - One pass through sequence : In this mode the XADC +* converts the channels enabled in the Sequencer Channel Enable +* registers for a single pass and then stops. +* - Continuous cycling of sequence : In this mode the XADC +* converts the channels enabled in the Sequencer Channel Enable +* registers continuously. +* - Single channel mode: In this mode the XADC Channel +* Sequencer is disabled and the XADC operates in a +* Single Channel Mode. +* The XADC can operate either in a Continuous or Event +* driven sampling mode in the single channel mode. +* - Simultaneous Sampling Mode: In this mode the XADC Channel +* Sequencer will automatically sequence through eight fixed pairs +* of auxiliary analog input channels for simulataneous conversion. +* - Independent ADC mode: In this mode the first ADC (A) is used to +* is used to implement a fixed monitoring mode similar to the +* default mode but the alarm fucntions ar eenabled. +* The second ADC (B) is available to be used with external analog +* input channels only. +* +* Read the XADC spec for more information about the sequencer modes. +* +* Initialization and Configuration +* +* The device driver enables higher layer software (e.g., an application) to +* communicate to the XADC/ADC device. +* +* XAdcPs_CfgInitialize() API is used to initialize the XADC/ADC +* device. The user needs to first call the XAdcPs_LookupConfig() API which +* returns the Configuration structure pointer which is passed as a parameter to +* the XAdcPs_CfgInitialize() API. +* +* +* Interrupts +* +* The XADC/ADC device supports interrupt driven mode and the default +* operation mode is polling mode. +* +* The interrupt mode is available only if hardware is configured to support +* interrupts. +* +* This driver does not provide a Interrupt Service Routine (ISR) for the device. +* It is the responsibility of the application to provide one if needed. Refer to +* the interrupt example provided with this driver for details on using the +* device in interrupt mode. +* +* +* Virtual Memory +* +* This driver supports Virtual Memory. The RTOS is responsible for calculating +* the correct device base address in Virtual Memory space. +* +* +* Threads +* +* This driver is not thread safe. Any needs for threads or thread mutual +* exclusion must be satisfied by the layer above this driver. +* +* +* Asserts +* +* Asserts are used within all Xilinx drivers to enforce constraints on argument +* values. Asserts can be turned off on a system-wide basis by defining, at +* compile time, the NDEBUG identifier. By default, asserts are turned on and it +* is recommended that users leave asserts on during development. +* +* +* Building the driver +* +* The XAdcPs driver is composed of several source files. This allows the user +* to build and link only those parts of the driver that are necessary. +* +* Limitations of the driver +* +* XADC/ADC device can be accessed through the JTAG port and the PLB +* interface. The driver implementation does not support the simultaneous access +* of the device by both these interfaces. The user has to care of this situation +* in the user application code. +* +*

+* +*
+*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- -----  -------- -----------------------------------------------------
+* 1.00a ssb    12/22/11 First release based on the XPS/AXI xadc driver
+* 1.01a bss    02/18/13	Modified XAdcPs_SetSeqChEnables,XAdcPs_SetSeqAvgEnables
+*			XAdcPs_SetSeqInputMode and XAdcPs_SetSeqAcqTime APIs
+*			in xadcps.c to fix CR #693371
+* 1.03a bss    11/01/13 Modified xadcps_hw.h to use correct Register offsets
+*			CR#749687
+* 2.1   bss    08/05/14 Added declarations for XAdcPs_SetSequencerEvent,
+*			XAdcPs_GetSamplingMode, XAdcPs_SetMuxMode,
+*			XAdcPs_SetPowerdownMode and XAdcPs_GetPowerdownMode
+*			functions.
+*			Modified Assert for XAdcPs_SetSingleChParams in
+*			xadcps.c to fix CR #807563.
+* 2.2   bss    04/27/14 Modified to use correct Device Config base address in
+*						xadcps.c (CR#854437).
+*       ms     01/23/17 Added xil_printf statement in main function for all
+*                       examples to ensure that "Successfully ran" and "Failed"
+*                       strings are available in all examples. This is a fix
+*                       for CR-965028.
+*       ms     03/17/17 Added readme.txt file in examples folder for doxygen
+*                       generation.
+*       ms     04/05/17 Modified Comment lines in functions of xadcps
+*                       examples to recognize it as documentation block
+*                       for doxygen generation.
+* 2.3   mn     07/09/18 Fix Doxygen warning
+*
+* 
+* +*****************************************************************************/ +#ifndef XADCPS_H /* Prevent circular inclusions */ +#define XADCPS_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files ********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xstatus.h" +#include "xadcps_hw.h" + +/************************** Constant Definitions ****************************/ + + +/** + * @name Indexes for the different channels. + * @{ + */ +#define XADCPS_CH_TEMP 0x0 /**< On Chip Temperature */ +#define XADCPS_CH_VCCINT 0x1 /**< VCCINT */ +#define XADCPS_CH_VCCAUX 0x2 /**< VCCAUX */ +#define XADCPS_CH_VPVN 0x3 /**< VP/VN Dedicated analog inputs */ +#define XADCPS_CH_VREFP 0x4 /**< VREFP */ +#define XADCPS_CH_VREFN 0x5 /**< VREFN */ +#define XADCPS_CH_VBRAM 0x6 /**< On-chip VBRAM Data Reg, 7 series */ +#define XADCPS_CH_SUPPLY_CALIB 0x07 /**< Supply Calib Data Reg */ +#define XADCPS_CH_ADC_CALIB 0x08 /**< ADC Offset Channel Reg */ +#define XADCPS_CH_GAINERR_CALIB 0x09 /**< Gain Error Channel Reg */ +#define XADCPS_CH_VCCPINT 0x0D /**< On-chip PS VCCPINT Channel , Zynq */ +#define XADCPS_CH_VCCPAUX 0x0E /**< On-chip PS VCCPAUX Channel , Zynq */ +#define XADCPS_CH_VCCPDRO 0x0F /**< On-chip PS VCCPDRO Channel , Zynq */ +#define XADCPS_CH_AUX_MIN 16 /**< Channel number for 1st Aux Channel */ +#define XADCPS_CH_AUX_MAX 31 /**< Channel number for Last Aux channel */ + +/*@}*/ + + +/** + * @name Indexes for reading the Calibration Coefficient Data. + * @{ + */ +#define XADCPS_CALIB_SUPPLY_COEFF 0 /**< Supply Offset Calib Coefficient */ +#define XADCPS_CALIB_ADC_COEFF 1 /**< ADC Offset Calib Coefficient */ +#define XADCPS_CALIB_GAIN_ERROR_COEFF 2 /**< Gain Error Calib Coefficient*/ +/*@}*/ + + +/** + * @name Indexes for reading the Minimum/Maximum Measurement Data. + * @{ + */ +#define XADCPS_MAX_TEMP 0 /**< Maximum Temperature Data */ +#define XADCPS_MAX_VCCINT 1 /**< Maximum VCCINT Data */ +#define XADCPS_MAX_VCCAUX 2 /**< Maximum VCCAUX Data */ +#define XADCPS_MAX_VBRAM 3 /**< Maximum VBRAM Data */ +#define XADCPS_MIN_TEMP 4 /**< Minimum Temperature Data */ +#define XADCPS_MIN_VCCINT 5 /**< Minimum VCCINT Data */ +#define XADCPS_MIN_VCCAUX 6 /**< Minimum VCCAUX Data */ +#define XADCPS_MIN_VBRAM 7 /**< Minimum VBRAM Data */ +#define XADCPS_MAX_VCCPINT 8 /**< Maximum VCCPINT Register , Zynq */ +#define XADCPS_MAX_VCCPAUX 9 /**< Maximum VCCPAUX Register , Zynq */ +#define XADCPS_MAX_VCCPDRO 0xA /**< Maximum VCCPDRO Register , Zynq */ +#define XADCPS_MIN_VCCPINT 0xC /**< Minimum VCCPINT Register , Zynq */ +#define XADCPS_MIN_VCCPAUX 0xD /**< Minimum VCCPAUX Register , Zynq */ +#define XADCPS_MIN_VCCPDRO 0xE /**< Minimum VCCPDRO Register , Zynq */ + +/*@}*/ + + +/** + * @name Alarm Threshold(Limit) Register (ATR) indexes. + * @{ + */ +#define XADCPS_ATR_TEMP_UPPER 0 /**< High user Temperature */ +#define XADCPS_ATR_VCCINT_UPPER 1 /**< VCCINT high voltage limit register */ +#define XADCPS_ATR_VCCAUX_UPPER 2 /**< VCCAUX high voltage limit register */ +#define XADCPS_ATR_OT_UPPER 3 /**< VCCAUX high voltage limit register */ +#define XADCPS_ATR_TEMP_LOWER 4 /**< Upper Over Temperature limit Reg */ +#define XADCPS_ATR_VCCINT_LOWER 5 /**< VCCINT high voltage limit register */ +#define XADCPS_ATR_VCCAUX_LOWER 6 /**< VCCAUX low voltage limit register */ +#define XADCPS_ATR_OT_LOWER 7 /**< Lower Over Temperature limit */ +#define XADCPS_ATR_VBRAM_UPPER_ 8 /**< VRBAM Upper Alarm Reg, 7 Series */ +#define XADCPS_ATR_VCCPINT_UPPER 9 /**< VCCPINT Upper Alarm Reg, Zynq */ +#define XADCPS_ATR_VCCPAUX_UPPER 0xA /**< VCCPAUX Upper Alarm Reg, Zynq */ +#define XADCPS_ATR_VCCPDRO_UPPER 0xB /**< VCCPDRO Upper Alarm Reg, Zynq */ +#define XADCPS_ATR_VBRAM_LOWER 0xC /**< VRBAM Lower Alarm Reg, 7 Series */ +#define XADCPS_ATR_VCCPINT_LOWER 0xD /**< VCCPINT Lower Alarm Reg , Zynq */ +#define XADCPS_ATR_VCCPAUX_LOWER 0xE /**< VCCPAUX Lower Alarm Reg , Zynq */ +#define XADCPS_ATR_VCCPDRO_LOWER 0xF /**< VCCPDRO Lower Alarm Reg , Zynq */ + +/*@}*/ + + +/** + * @name Averaging to be done for the channels. + * @{ + */ +#define XADCPS_AVG_0_SAMPLES 0 /**< No Averaging */ +#define XADCPS_AVG_16_SAMPLES 1 /**< Average 16 samples */ +#define XADCPS_AVG_64_SAMPLES 2 /**< Average 64 samples */ +#define XADCPS_AVG_256_SAMPLES 3 /**< Average 256 samples */ + +/*@}*/ + + +/** + * @name Channel Sequencer Modes of operation + * @{ + */ +#define XADCPS_SEQ_MODE_SAFE 0 /**< Default Safe Mode */ +#define XADCPS_SEQ_MODE_ONEPASS 1 /**< Onepass through Sequencer */ +#define XADCPS_SEQ_MODE_CONTINPASS 2 /**< Continuous Cycling Sequencer */ +#define XADCPS_SEQ_MODE_SINGCHAN 3 /**< Single channel -No Sequencing */ +#define XADCPS_SEQ_MODE_SIMUL_SAMPLING 4 /**< Simultaneous sampling */ +#define XADCPS_SEQ_MODE_INDEPENDENT 8 /**< Independent mode */ + +/*@}*/ + + + +/** + * @name Power Down Modes + * @{ + */ +#define XADCPS_PD_MODE_NONE 0 /**< No Power Down */ +#define XADCPS_PD_MODE_ADCB 1 /**< Power Down ADC B */ +#define XADCPS_PD_MODE_XADC 2 /**< Power Down ADC A and ADC B */ +/*@}*/ + +/**************************** Type Definitions ******************************/ + +/** + * This typedef contains configuration information for the XADC/ADC + * device. + */ +typedef struct { + u16 DeviceId; /**< Unique ID of device */ + u32 BaseAddress; /**< Device base address */ +} XAdcPs_Config; + + +/** + * The driver's instance data. The user is required to allocate a variable + * of this type for every XADC/ADC device in the system. A pointer to + * a variable of this type is then passed to the driver API functions. + */ +typedef struct { + XAdcPs_Config Config; /**< XAdcPs_Config of current device */ + u32 IsReady; /**< Device is initialized and ready */ + +} XAdcPs; + +/***************** Macros (Inline Functions) Definitions ********************/ + +/****************************************************************************/ +/** +* +* This macro checks if the XADC device is in Event Sampling mode. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @return +* - TRUE if the device is in Event Sampling Mode. +* - FALSE if the device is in Continuous Sampling Mode. +* +* @note C-Style signature: +* int XAdcPs_IsEventSamplingMode(XAdcPs *InstancePtr); +* +*****************************************************************************/ +#define XAdcPs_IsEventSamplingModeSet(InstancePtr) \ + (((XAdcPs_ReadInternalReg(InstancePtr, \ + XADCPS_CFR0_OFFSET) & XADCPS_CFR0_EC_MASK) ? \ + TRUE : FALSE)) + + +/****************************************************************************/ +/** +* +* This macro checks if the XADC device is in External Mux mode. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @return +* - TRUE if the device is in External Mux Mode. +* - FALSE if the device is NOT in External Mux Mode. +* +* @note C-Style signature: +* int XAdcPs_IsExternalMuxMode(XAdcPs *InstancePtr); +* +*****************************************************************************/ +#define XAdcPs_IsExternalMuxModeSet(InstancePtr) \ + (((XAdcPs_ReadInternalReg(InstancePtr, \ + XADCPS_CFR0_OFFSET) & XADCPS_CFR0_MUX_MASK) ? \ + TRUE : FALSE)) + +/****************************************************************************/ +/** +* +* This macro converts XADC Raw Data to Temperature(centigrades). +* +* @param AdcData is the Raw ADC Data from XADC. +* +* @return The Temperature in centigrades. +* +* @note C-Style signature: +* float XAdcPs_RawToTemperature(u32 AdcData); +* +*****************************************************************************/ +#define XAdcPs_RawToTemperature(AdcData) \ + ((((float)(AdcData)/65536.0f)/0.00198421639f ) - 273.15f) + +/****************************************************************************/ +/** +* +* This macro converts XADC/ADC Raw Data to Voltage(volts). +* +* @param AdcData is the XADC/ADC Raw Data. +* +* @return The Voltage in volts. +* +* @note C-Style signature: +* float XAdcPs_RawToVoltage(u32 AdcData); +* +*****************************************************************************/ +#define XAdcPs_RawToVoltage(AdcData) \ + ((((float)(AdcData))* (3.0f))/65536.0f) + +/****************************************************************************/ +/** +* +* This macro converts Temperature in centigrades to XADC/ADC Raw Data. +* +* @param Temperature is the Temperature in centigrades to be +* converted to XADC/ADC Raw Data. +* +* @return The XADC/ADC Raw Data. +* +* @note C-Style signature: +* int XAdcPs_TemperatureToRaw(float Temperature); +* +*****************************************************************************/ +#define XAdcPs_TemperatureToRaw(Temperature) \ + ((int)(((Temperature) + 273.15f)*65536.0f*0.00198421639f)) + +/****************************************************************************/ +/** +* +* This macro converts Voltage in Volts to XADC/ADC Raw Data. +* +* @param Voltage is the Voltage in volts to be converted to +* XADC/ADC Raw Data. +* +* @return The XADC/ADC Raw Data. +* +* @note C-Style signature: +* int XAdcPs_VoltageToRaw(float Voltage); +* +*****************************************************************************/ +#define XAdcPs_VoltageToRaw(Voltage) \ + ((int)((Voltage)*65536.0f/3.0f)) + + +/****************************************************************************/ +/** +* +* This macro is used for writing to the XADC Registers using the +* command FIFO. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param Data is the value to be written to XADC register. +* +* @return None. +* +* @note C-Style signature: +* void XAdcPs_WriteFifo(XAdcPs *InstancePtr, u32 Data); +* +*****************************************************************************/ +#define XAdcPs_WriteFifo(InstancePtr, Data) \ + XAdcPs_WriteReg((InstancePtr)->Config.BaseAddress, \ + XADCPS_CMDFIFO_OFFSET, Data); + + +/****************************************************************************/ +/** +* +* This macro is used for reading from the XADC Registers using the +* data FIFO. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @return Data read from the FIFO +* +* @note C-Style signature: +* u32 XAdcPs_ReadFifo(XAdcPs *InstancePtr); +* +*****************************************************************************/ +#define XAdcPs_ReadFifo(InstancePtr) \ + XAdcPs_ReadReg((InstancePtr)->Config.BaseAddress, \ + XADCPS_RDFIFO_OFFSET); + + +/************************** Function Prototypes *****************************/ + + + +/** + * Functions in xadcps_sinit.c + */ +XAdcPs_Config *XAdcPs_LookupConfig(u16 DeviceId); + +/** + * Functions in xadcps.c + */ +int XAdcPs_CfgInitialize(XAdcPs *InstancePtr, + XAdcPs_Config *ConfigPtr, + u32 EffectiveAddr); + + +u32 XAdcPs_GetStatus(XAdcPs *InstancePtr); + +u32 XAdcPs_GetAlarmOutputStatus(XAdcPs *InstancePtr); + +void XAdcPs_StartAdcConversion(XAdcPs *InstancePtr); + +void XAdcPs_Reset(XAdcPs *InstancePtr); + +u16 XAdcPs_GetAdcData(XAdcPs *InstancePtr, u8 Channel); + +u16 XAdcPs_GetCalibCoefficient(XAdcPs *InstancePtr, u8 CoeffType); + +u16 XAdcPs_GetMinMaxMeasurement(XAdcPs *InstancePtr, u8 MeasurementType); + +void XAdcPs_SetAvg(XAdcPs *InstancePtr, u8 Average); +u8 XAdcPs_GetAvg(XAdcPs *InstancePtr); + +int XAdcPs_SetSingleChParams(XAdcPs *InstancePtr, + u8 Channel, + int IncreaseAcqCycles, + int IsEventMode, + int IsDifferentialMode); + + +void XAdcPs_SetAlarmEnables(XAdcPs *InstancePtr, u16 AlmEnableMask); +u16 XAdcPs_GetAlarmEnables(XAdcPs *InstancePtr); + +void XAdcPs_SetCalibEnables(XAdcPs *InstancePtr, u16 Calibration); +u16 XAdcPs_GetCalibEnables(XAdcPs *InstancePtr); + +void XAdcPs_SetSequencerMode(XAdcPs *InstancePtr, u8 SequencerMode); +u8 XAdcPs_GetSequencerMode(XAdcPs *InstancePtr); + +void XAdcPs_SetAdcClkDivisor(XAdcPs *InstancePtr, u8 Divisor); +u8 XAdcPs_GetAdcClkDivisor(XAdcPs *InstancePtr); + +int XAdcPs_SetSeqChEnables(XAdcPs *InstancePtr, u32 ChEnableMask); +u32 XAdcPs_GetSeqChEnables(XAdcPs *InstancePtr); + +int XAdcPs_SetSeqAvgEnables(XAdcPs *InstancePtr, u32 AvgEnableChMask); +u32 XAdcPs_GetSeqAvgEnables(XAdcPs *InstancePtr); + +int XAdcPs_SetSeqInputMode(XAdcPs *InstancePtr, u32 InputModeChMask); +u32 XAdcPs_GetSeqInputMode(XAdcPs *InstancePtr); + +int XAdcPs_SetSeqAcqTime(XAdcPs *InstancePtr, u32 AcqCyclesChMask); +u32 XAdcPs_GetSeqAcqTime(XAdcPs *InstancePtr); + +void XAdcPs_SetAlarmThreshold(XAdcPs *InstancePtr, u8 AlarmThrReg, u16 Value); +u16 XAdcPs_GetAlarmThreshold(XAdcPs *InstancePtr, u8 AlarmThrReg); + +void XAdcPs_EnableUserOverTemp(XAdcPs *InstancePtr); +void XAdcPs_DisableUserOverTemp(XAdcPs *InstancePtr); + +void XAdcPs_SetSequencerEvent(XAdcPs *InstancePtr, int IsEventMode); + +int XAdcPs_GetSamplingMode(XAdcPs *InstancePtr); + +void XAdcPs_SetMuxMode(XAdcPs *InstancePtr, int MuxMode, u8 Channel); + +void XAdcPs_SetPowerdownMode(XAdcPs *InstancePtr, u32 Mode); + +u32 XAdcPs_GetPowerdownMode(XAdcPs *InstancePtr); + +/** + * Functions in xadcps_selftest.c + */ +int XAdcPs_SelfTest(XAdcPs *InstancePtr); + +/** + * Functions in xadcps_intr.c + */ +void XAdcPs_IntrEnable(XAdcPs *InstancePtr, u32 Mask); +void XAdcPs_IntrDisable(XAdcPs *InstancePtr, u32 Mask); +u32 XAdcPs_IntrGetEnabled(XAdcPs *InstancePtr); + +u32 XAdcPs_IntrGetStatus(XAdcPs *InstancePtr); +void XAdcPs_IntrClear(XAdcPs *InstancePtr, u32 Mask); + + +#ifdef __cplusplus +} +#endif + +#endif /* End of protection macro. */ +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/xadcps_v2_3/src/xadcps_g.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/xadcps_v2_3/src/xadcps_g.c new file mode 100644 index 0000000..abcd1ec --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/xadcps_v2_3/src/xadcps_g.c @@ -0,0 +1,51 @@ + +/******************************************************************* +* +* CAUTION: This file is automatically generated by HSI. +* Version: 2019.1.3 +* DO NOT EDIT. +* +* Copyright (C) 2010-2023 Xilinx, Inc. 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 +*XILINX 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. +* +*Except as contained in this notice, the name of the Xilinx shall not be used +*in advertising or otherwise to promote the sale, use or other dealings in +*this Software without prior written authorization from Xilinx. +* + +* +* Description: Driver configuration +* +*******************************************************************/ + +#include "xparameters.h" +#include "xadcps.h" + +/* +* The configuration table for devices +*/ + +XAdcPs_Config XAdcPs_ConfigTable[XPAR_XADCPS_NUM_INSTANCES] = +{ + { + XPAR_PS7_XADC_0_DEVICE_ID, + XPAR_PS7_XADC_0_BASEADDR + } +}; + + diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/xadcps_v2_3/src/xadcps_hw.h b/df_datalink/bsp/ps7_cortexa9_0/libsrc/xadcps_v2_3/src/xadcps_hw.h new file mode 100644 index 0000000..dd51473 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/xadcps_v2_3/src/xadcps_hw.h @@ -0,0 +1,498 @@ +/****************************************************************************** +* +* Copyright (C) 2011 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file xadcps_hw.h +* @addtogroup xadcps_v2_3 +* @{ +* +* This header file contains identifiers and basic driver functions (or +* macros) that can be used to access the XADC device through the Device +* Config Interface of the Zynq. +* +* +* Refer to the device specification for more information about this driver. +* +* @note None. +* +* +*
+*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- -----  -------- -----------------------------------------------------
+* 1.00a bss    12/22/11 First release based on the XPS/AXI xadc driver
+* 1.03a bss    11/01/13 Modified macros to use correct Register offsets
+*			CR#749687
+*
+* 
+* +*****************************************************************************/ +#ifndef XADCPS_HW_H /* Prevent circular inclusions */ +#define XADCPS_HW_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files ********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_io.h" + +/************************** Constant Definitions ****************************/ + + +/**@name Register offsets of XADC in the Device Config + * + * The following constants provide access to each of the registers of the + * XADC device. + * @{ + */ + +#define XADCPS_CFG_OFFSET 0x00 /**< Configuration Register */ +#define XADCPS_INT_STS_OFFSET 0x04 /**< Interrupt Status Register */ +#define XADCPS_INT_MASK_OFFSET 0x08 /**< Interrupt Mask Register */ +#define XADCPS_MSTS_OFFSET 0x0C /**< Misc status register */ +#define XADCPS_CMDFIFO_OFFSET 0x10 /**< Command FIFO Register */ +#define XADCPS_RDFIFO_OFFSET 0x14 /**< Read FIFO Register */ +#define XADCPS_MCTL_OFFSET 0x18 /**< Misc control register */ + +/* @} */ + + + + + +/** @name XADC Config Register Bit definitions + * @{ + */ +#define XADCPS_CFG_ENABLE_MASK 0x80000000 /**< Enable access from PS mask */ +#define XADCPS_CFG_CFIFOTH_MASK 0x00F00000 /**< Command FIFO Threshold mask */ +#define XADCPS_CFG_DFIFOTH_MASK 0x000F0000 /**< Data FIFO Threshold mask */ +#define XADCPS_CFG_WEDGE_MASK 0x00002000 /**< Write Edge Mask */ +#define XADCPS_CFG_REDGE_MASK 0x00001000 /**< Read Edge Mask */ +#define XADCPS_CFG_TCKRATE_MASK 0x00000300 /**< Clock freq control */ +#define XADCPS_CFG_IGAP_MASK 0x0000001F /**< Idle Gap between + * successive commands */ +/* @} */ + + +/** @name XADC Interrupt Status/Mask Register Bit definitions + * + * The definitions are same for the Interrupt Status Register and + * Interrupt Mask Register. They are defined only once. + * @{ + */ +#define XADCPS_INTX_ALL_MASK 0x000003FF /**< Alarm Signals Mask */ +#define XADCPS_INTX_CFIFO_LTH_MASK 0x00000200 /**< CMD FIFO less than threshold */ +#define XADCPS_INTX_DFIFO_GTH_MASK 0x00000100 /**< Data FIFO greater than threshold */ +#define XADCPS_INTX_OT_MASK 0x00000080 /**< Over temperature Alarm Status */ +#define XADCPS_INTX_ALM_ALL_MASK 0x0000007F /**< Alarm Signals Mask */ +#define XADCPS_INTX_ALM6_MASK 0x00000040 /**< Alarm 6 Mask */ +#define XADCPS_INTX_ALM5_MASK 0x00000020 /**< Alarm 5 Mask */ +#define XADCPS_INTX_ALM4_MASK 0x00000010 /**< Alarm 4 Mask */ +#define XADCPS_INTX_ALM3_MASK 0x00000008 /**< Alarm 3 Mask */ +#define XADCPS_INTX_ALM2_MASK 0x00000004 /**< Alarm 2 Mask */ +#define XADCPS_INTX_ALM1_MASK 0x00000002 /**< Alarm 1 Mask */ +#define XADCPS_INTX_ALM0_MASK 0x00000001 /**< Alarm 0 Mask */ + +/* @} */ + + +/** @name XADC Miscellaneous Register Bit definitions + * @{ + */ +#define XADCPS_MSTS_CFIFO_LVL_MASK 0x000F0000 /**< Command FIFO Level mask */ +#define XADCPS_MSTS_DFIFO_LVL_MASK 0x0000F000 /**< Data FIFO Level Mask */ +#define XADCPS_MSTS_CFIFOF_MASK 0x00000800 /**< Command FIFO Full Mask */ +#define XADCPS_MSTS_CFIFOE_MASK 0x00000400 /**< Command FIFO Empty Mask */ +#define XADCPS_MSTS_DFIFOF_MASK 0x00000200 /**< Data FIFO Full Mask */ +#define XADCPS_MSTS_DFIFOE_MASK 0x00000100 /**< Data FIFO Empty Mask */ +#define XADCPS_MSTS_OT_MASK 0x00000080 /**< Over Temperature Mask */ +#define XADCPS_MSTS_ALM_MASK 0x0000007F /**< Alarms Mask */ +/* @} */ + + +/** @name XADC Miscellaneous Control Register Bit definitions + * @{ + */ +#define XADCPS_MCTL_RESET_MASK 0x00000010 /**< Reset XADC */ +#define XADCPS_MCTL_FLUSH_MASK 0x00000001 /**< Flush the FIFOs */ +/* @} */ + + +/**@name Internal Register offsets of the XADC + * + * The following constants provide access to each of the internal registers of + * the XADC device. + * @{ + */ + +/* + * XADC Internal Channel Registers + */ +#define XADCPS_TEMP_OFFSET 0x00 /**< On-chip Temperature Reg */ +#define XADCPS_VCCINT_OFFSET 0x01 /**< On-chip VCCINT Data Reg */ +#define XADCPS_VCCAUX_OFFSET 0x02 /**< On-chip VCCAUX Data Reg */ +#define XADCPS_VPVN_OFFSET 0x03 /**< ADC out of VP/VN */ +#define XADCPS_VREFP_OFFSET 0x04 /**< On-chip VREFP Data Reg */ +#define XADCPS_VREFN_OFFSET 0x05 /**< On-chip VREFN Data Reg */ +#define XADCPS_VBRAM_OFFSET 0x06 /**< On-chip VBRAM , 7 Series */ +#define XADCPS_ADC_A_SUPPLY_CALIB_OFFSET 0x08 /**< ADC A Supply Offset Reg */ +#define XADCPS_ADC_A_OFFSET_CALIB_OFFSET 0x09 /**< ADC A Offset Data Reg */ +#define XADCPS_ADC_A_GAINERR_CALIB_OFFSET 0x0A /**< ADC A Gain Error Reg */ +#define XADCPS_VCCPINT_OFFSET 0x0D /**< On-chip VCCPINT Reg, Zynq */ +#define XADCPS_VCCPAUX_OFFSET 0x0E /**< On-chip VCCPAUX Reg, Zynq */ +#define XADCPS_VCCPDRO_OFFSET 0x0F /**< On-chip VCCPDRO Reg, Zynq */ + +/* + * XADC External Channel Registers + */ +#define XADCPS_AUX00_OFFSET 0x10 /**< ADC out of VAUXP0/VAUXN0 */ +#define XADCPS_AUX01_OFFSET 0x11 /**< ADC out of VAUXP1/VAUXN1 */ +#define XADCPS_AUX02_OFFSET 0x12 /**< ADC out of VAUXP2/VAUXN2 */ +#define XADCPS_AUX03_OFFSET 0x13 /**< ADC out of VAUXP3/VAUXN3 */ +#define XADCPS_AUX04_OFFSET 0x14 /**< ADC out of VAUXP4/VAUXN4 */ +#define XADCPS_AUX05_OFFSET 0x15 /**< ADC out of VAUXP5/VAUXN5 */ +#define XADCPS_AUX06_OFFSET 0x16 /**< ADC out of VAUXP6/VAUXN6 */ +#define XADCPS_AUX07_OFFSET 0x17 /**< ADC out of VAUXP7/VAUXN7 */ +#define XADCPS_AUX08_OFFSET 0x18 /**< ADC out of VAUXP8/VAUXN8 */ +#define XADCPS_AUX09_OFFSET 0x19 /**< ADC out of VAUXP9/VAUXN9 */ +#define XADCPS_AUX10_OFFSET 0x1A /**< ADC out of VAUXP10/VAUXN10 */ +#define XADCPS_AUX11_OFFSET 0x1B /**< ADC out of VAUXP11/VAUXN11 */ +#define XADCPS_AUX12_OFFSET 0x1C /**< ADC out of VAUXP12/VAUXN12 */ +#define XADCPS_AUX13_OFFSET 0x1D /**< ADC out of VAUXP13/VAUXN13 */ +#define XADCPS_AUX14_OFFSET 0x1E /**< ADC out of VAUXP14/VAUXN14 */ +#define XADCPS_AUX15_OFFSET 0x1F /**< ADC out of VAUXP15/VAUXN15 */ + +/* + * XADC Registers for Maximum/Minimum data captured for the + * on chip Temperature/VCCINT/VCCAUX data. + */ +#define XADCPS_MAX_TEMP_OFFSET 0x20 /**< Max Temperature Reg */ +#define XADCPS_MAX_VCCINT_OFFSET 0x21 /**< Max VCCINT Register */ +#define XADCPS_MAX_VCCAUX_OFFSET 0x22 /**< Max VCCAUX Register */ +#define XADCPS_MAX_VCCBRAM_OFFSET 0x23 /**< Max BRAM Register, 7 series */ +#define XADCPS_MIN_TEMP_OFFSET 0x24 /**< Min Temperature Reg */ +#define XADCPS_MIN_VCCINT_OFFSET 0x25 /**< Min VCCINT Register */ +#define XADCPS_MIN_VCCAUX_OFFSET 0x26 /**< Min VCCAUX Register */ +#define XADCPS_MIN_VCCBRAM_OFFSET 0x27 /**< Min BRAM Register, 7 series */ +#define XADCPS_MAX_VCCPINT_OFFSET 0x28 /**< Max VCCPINT Register, Zynq */ +#define XADCPS_MAX_VCCPAUX_OFFSET 0x29 /**< Max VCCPAUX Register, Zynq */ +#define XADCPS_MAX_VCCPDRO_OFFSET 0x2A /**< Max VCCPDRO Register, Zynq */ +#define XADCPS_MIN_VCCPINT_OFFSET 0x2C /**< Min VCCPINT Register, Zynq */ +#define XADCPS_MIN_VCCPAUX_OFFSET 0x2D /**< Min VCCPAUX Register, Zynq */ +#define XADCPS_MIN_VCCPDRO_OFFSET 0x2E /**< Min VCCPDRO Register,Zynq */ + /* Undefined 0x2F to 0x3E */ +#define XADCPS_FLAG_OFFSET 0x3F /**< Flag Register */ + +/* + * XADC Configuration Registers + */ +#define XADCPS_CFR0_OFFSET 0x40 /**< Configuration Register 0 */ +#define XADCPS_CFR1_OFFSET 0x41 /**< Configuration Register 1 */ +#define XADCPS_CFR2_OFFSET 0x42 /**< Configuration Register 2 */ + +/* Test Registers 0x43 to 0x47 */ + +/* + * XADC Sequence Registers + */ +#define XADCPS_SEQ00_OFFSET 0x48 /**< Seq Reg 00 Adc Channel Selection */ +#define XADCPS_SEQ01_OFFSET 0x49 /**< Seq Reg 01 Adc Channel Selection */ +#define XADCPS_SEQ02_OFFSET 0x4A /**< Seq Reg 02 Adc Average Enable */ +#define XADCPS_SEQ03_OFFSET 0x4B /**< Seq Reg 03 Adc Average Enable */ +#define XADCPS_SEQ04_OFFSET 0x4C /**< Seq Reg 04 Adc Input Mode Select */ +#define XADCPS_SEQ05_OFFSET 0x4D /**< Seq Reg 05 Adc Input Mode Select */ +#define XADCPS_SEQ06_OFFSET 0x4E /**< Seq Reg 06 Adc Acquisition Select */ +#define XADCPS_SEQ07_OFFSET 0x4F /**< Seq Reg 07 Adc Acquisition Select */ + +/* + * XADC Alarm Threshold/Limit Registers (ATR) + */ +#define XADCPS_ATR_TEMP_UPPER_OFFSET 0x50 /**< Temp Upper Alarm Register */ +#define XADCPS_ATR_VCCINT_UPPER_OFFSET 0x51 /**< VCCINT Upper Alarm Reg */ +#define XADCPS_ATR_VCCAUX_UPPER_OFFSET 0x52 /**< VCCAUX Upper Alarm Reg */ +#define XADCPS_ATR_OT_UPPER_OFFSET 0x53 /**< Over Temp Upper Alarm Reg */ +#define XADCPS_ATR_TEMP_LOWER_OFFSET 0x54 /**< Temp Lower Alarm Register */ +#define XADCPS_ATR_VCCINT_LOWER_OFFSET 0x55 /**< VCCINT Lower Alarm Reg */ +#define XADCPS_ATR_VCCAUX_LOWER_OFFSET 0x56 /**< VCCAUX Lower Alarm Reg */ +#define XADCPS_ATR_OT_LOWER_OFFSET 0x57 /**< Over Temp Lower Alarm Reg */ +#define XADCPS_ATR_VBRAM_UPPER_OFFSET 0x58 /**< VBRAM Upper Alarm, 7 series */ +#define XADCPS_ATR_VCCPINT_UPPER_OFFSET 0x59 /**< VCCPINT Upper Alarm, Zynq */ +#define XADCPS_ATR_VCCPAUX_UPPER_OFFSET 0x5A /**< VCCPAUX Upper Alarm, Zynq */ +#define XADCPS_ATR_VCCPDRO_UPPER_OFFSET 0x5B /**< VCCPDRO Upper Alarm, Zynq */ +#define XADCPS_ATR_VBRAM_LOWER_OFFSET 0x5C /**< VRBAM Lower Alarm, 7 Series */ +#define XADCPS_ATR_VCCPINT_LOWER_OFFSET 0x5D /**< VCCPINT Lower Alarm, Zynq */ +#define XADCPS_ATR_VCCPAUX_LOWER_OFFSET 0x5E /**< VCCPAUX Lower Alarm, Zynq */ +#define XADCPS_ATR_VCCPDRO_LOWER_OFFSET 0x5F /**< VCCPDRO Lower Alarm, Zynq */ + +/* Undefined 0x60 to 0x7F */ + +/*@}*/ + + + +/** + * @name Configuration Register 0 (CFR0) mask(s) + * @{ + */ +#define XADCPS_CFR0_CAL_AVG_MASK 0x8000 /**< Averaging enable Mask */ +#define XADCPS_CFR0_AVG_VALID_MASK 0x3000 /**< Averaging bit Mask */ +#define XADCPS_CFR0_AVG1_MASK 0x0000 /**< No Averaging */ +#define XADCPS_CFR0_AVG16_MASK 0x1000 /**< Average 16 samples */ +#define XADCPS_CFR0_AVG64_MASK 0x2000 /**< Average 64 samples */ +#define XADCPS_CFR0_AVG256_MASK 0x3000 /**< Average 256 samples */ +#define XADCPS_CFR0_AVG_SHIFT 12 /**< Averaging bits shift */ +#define XADCPS_CFR0_MUX_MASK 0x0800 /**< External Mask Enable */ +#define XADCPS_CFR0_DU_MASK 0x0400 /**< Bipolar/Unipolar mode */ +#define XADCPS_CFR0_EC_MASK 0x0200 /**< Event driven/ + * Continuous mode selection + */ +#define XADCPS_CFR0_ACQ_MASK 0x0100 /**< Add acquisition by 6 ADCCLK */ +#define XADCPS_CFR0_CHANNEL_MASK 0x001F /**< Channel number bit Mask */ + +/*@}*/ + +/** + * @name Configuration Register 1 (CFR1) mask(s) + * @{ + */ +#define XADCPS_CFR1_SEQ_VALID_MASK 0xF000 /**< Sequence bit Mask */ +#define XADCPS_CFR1_SEQ_SAFEMODE_MASK 0x0000 /**< Default Safe Mode */ +#define XADCPS_CFR1_SEQ_ONEPASS_MASK 0x1000 /**< Onepass through Seq */ +#define XADCPS_CFR1_SEQ_CONTINPASS_MASK 0x2000 /**< Continuous Cycling Seq */ +#define XADCPS_CFR1_SEQ_SINGCHAN_MASK 0x3000 /**< Single channel - No Seq */ +#define XADCPS_CFR1_SEQ_SIMUL_SAMPLING_MASK 0x4000 /**< Simulataneous Sampling Mask */ +#define XADCPS_CFR1_SEQ_INDEPENDENT_MASK 0x8000 /**< Independent Mode */ +#define XADCPS_CFR1_SEQ_SHIFT 12 /**< Sequence bit shift */ +#define XADCPS_CFR1_ALM_VCCPDRO_MASK 0x0800 /**< Alm 6 - VCCPDRO, Zynq */ +#define XADCPS_CFR1_ALM_VCCPAUX_MASK 0x0400 /**< Alm 5 - VCCPAUX, Zynq */ +#define XADCPS_CFR1_ALM_VCCPINT_MASK 0x0200 /**< Alm 4 - VCCPINT, Zynq */ +#define XADCPS_CFR1_ALM_VBRAM_MASK 0x0100 /**< Alm 3 - VBRAM, 7 series */ +#define XADCPS_CFR1_CAL_VALID_MASK 0x00F0 /**< Valid Calibration Mask */ +#define XADCPS_CFR1_CAL_PS_GAIN_OFFSET_MASK 0x0080 /**< Calibration 3 -Power + Supply Gain/Offset + Enable */ +#define XADCPS_CFR1_CAL_PS_OFFSET_MASK 0x0040 /**< Calibration 2 -Power + Supply Offset Enable */ +#define XADCPS_CFR1_CAL_ADC_GAIN_OFFSET_MASK 0x0020 /**< Calibration 1 -ADC Gain + Offset Enable */ +#define XADCPS_CFR1_CAL_ADC_OFFSET_MASK 0x0010 /**< Calibration 0 -ADC Offset + Enable */ +#define XADCPS_CFR1_CAL_DISABLE_MASK 0x0000 /**< No Calibration */ +#define XADCPS_CFR1_ALM_ALL_MASK 0x0F0F /**< Mask for all alarms */ +#define XADCPS_CFR1_ALM_VCCAUX_MASK 0x0008 /**< Alarm 2 - VCCAUX Enable */ +#define XADCPS_CFR1_ALM_VCCINT_MASK 0x0004 /**< Alarm 1 - VCCINT Enable */ +#define XADCPS_CFR1_ALM_TEMP_MASK 0x0002 /**< Alarm 0 - Temperature */ +#define XADCPS_CFR1_OT_MASK 0x0001 /**< Over Temperature Enable */ + +/*@}*/ + +/** + * @name Configuration Register 2 (CFR2) mask(s) + * @{ + */ +#define XADCPS_CFR2_CD_VALID_MASK 0xFF00 /** +* +* MODIFICATION HISTORY: +* +* Ver Who Date Changes +* ----- ----- -------- ----------------------------------------------------- +* 1.00a ssb 12/22/11 First release based on the XPS/AXI xadc driver +* +* +* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xadcps.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + + +/****************************************************************************/ +/** +* +* This function enables the specified interrupts in the device. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param Mask is the bit-mask of the interrupts to be enabled. +* Bit positions of 1 will be enabled. Bit positions of 0 will +* keep the previous setting. This mask is formed by OR'ing +* XADCPS_INTX_* bits defined in xadcps_hw.h. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XAdcPs_IntrEnable(XAdcPs *InstancePtr, u32 Mask) +{ + u32 RegValue; + + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Disable the specified interrupts in the IPIER. + */ + RegValue = XAdcPs_ReadReg(InstancePtr->Config.BaseAddress, + XADCPS_INT_MASK_OFFSET); + RegValue &= ~(Mask & XADCPS_INTX_ALL_MASK); + XAdcPs_WriteReg(InstancePtr->Config.BaseAddress, + XADCPS_INT_MASK_OFFSET, + RegValue); +} + + +/****************************************************************************/ +/** +* +* This function disables the specified interrupts in the device. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param Mask is the bit-mask of the interrupts to be disabled. +* Bit positions of 1 will be disabled. Bit positions of 0 will +* keep the previous setting. This mask is formed by OR'ing +* XADCPS_INTX_* bits defined in xadcps_hw.h. +* +* @return None. +* +* @note None +* +*****************************************************************************/ +void XAdcPs_IntrDisable(XAdcPs *InstancePtr, u32 Mask) +{ + u32 RegValue; + + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Enable the specified interrupts in the IPIER. + */ + RegValue = XAdcPs_ReadReg(InstancePtr->Config.BaseAddress, + XADCPS_INT_MASK_OFFSET); + RegValue |= (Mask & XADCPS_INTX_ALL_MASK); + XAdcPs_WriteReg(InstancePtr->Config.BaseAddress, + XADCPS_INT_MASK_OFFSET, + RegValue); +} +/****************************************************************************/ +/** +* +* This function returns the enabled interrupts read from the Interrupt Mask +* Register (IPIER). Use the XADCPS_IPIXR_* constants defined in xadcps_hw.h to +* interpret the returned value. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @return A 32-bit value representing the contents of the I. +* +* @note None. +* +*****************************************************************************/ +u32 XAdcPs_IntrGetEnabled(XAdcPs *InstancePtr) +{ + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Return the value read from the Interrupt Enable Register. + */ + return (~ XAdcPs_ReadReg(InstancePtr->Config.BaseAddress, + XADCPS_INT_MASK_OFFSET) & XADCPS_INTX_ALL_MASK); +} + +/****************************************************************************/ +/** +* +* This function returns the interrupt status read from Interrupt Status +* Register(IPISR). Use the XADCPS_IPIXR_* constants defined in xadcps_hw.h +* to interpret the returned value. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @return A 32-bit value representing the contents of the IPISR. +* +* @note The device must be configured at hardware build time to include +* interrupt component for this function to work. +* +*****************************************************************************/ +u32 XAdcPs_IntrGetStatus(XAdcPs *InstancePtr) +{ + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Return the value read from the Interrupt Status register. + */ + return XAdcPs_ReadReg(InstancePtr->Config.BaseAddress, + XADCPS_INT_STS_OFFSET) & XADCPS_INTX_ALL_MASK; +} + +/****************************************************************************/ +/** +* +* This function clears the specified interrupts in the Interrupt Status +* Register (IPISR). +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param Mask is the bit-mask of the interrupts to be cleared. +* Bit positions of 1 will be cleared. Bit positions of 0 will not +* change the previous interrupt status. This mask is formed by +* OR'ing XADCPS_IPIXR_* bits which are defined in xadcps_hw.h. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XAdcPs_IntrClear(XAdcPs *InstancePtr, u32 Mask) +{ + u32 RegValue; + + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Clear the specified interrupts in the Interrupt Status register. + */ + RegValue = XAdcPs_ReadReg(InstancePtr->Config.BaseAddress, + XADCPS_INT_STS_OFFSET); + RegValue &= (Mask & XADCPS_INTX_ALL_MASK); + XAdcPs_WriteReg(InstancePtr->Config.BaseAddress, XADCPS_INT_STS_OFFSET, + RegValue); + +} +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/xadcps_v2_3/src/xadcps_selftest.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/xadcps_v2_3/src/xadcps_selftest.c new file mode 100644 index 0000000..2d2a7f2 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/xadcps_v2_3/src/xadcps_selftest.c @@ -0,0 +1,137 @@ +/****************************************************************************** +* +* Copyright (C) 2011 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xadcps_selftest.c +* @addtogroup xadcps_v2_3 +* @{ +* +* This file contains a diagnostic self test function for the XAdcPs driver. +* The self test function does a simple read/write test of the Alarm Threshold +* Register. +* +* See xadcps.h for more information. +* +* @note None. +* +*
+*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- -----  -------- -----------------------------------------------------
+* 1.00a ssb    12/22/11 First release based on the XPS/AXI xadc driver
+*
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ + +#include "xadcps.h" + +/************************** Constant Definitions ****************************/ + +/* + * The following constant defines the test value to be written + * to the Alarm Threshold Register + */ +#define XADCPS_ATR_TEST_VALUE 0x55 + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Variable Definitions ****************************/ + +/************************** Function Prototypes *****************************/ + +/*****************************************************************************/ +/** +* +* Run a self-test on the driver/device. The test +* - Resets the device, +* - Writes a value into the Alarm Threshold register and reads it back +* for comparison. +* - Resets the device again. +* +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @return +* - XST_SUCCESS if the value read from the Alarm Threshold +* register is the same as the value written. +* - XST_FAILURE Otherwise +* +* @note This is a destructive test in that resets of the device are +* performed. Refer to the device specification for the +* device status after the reset operation. +* +******************************************************************************/ +int XAdcPs_SelfTest(XAdcPs *InstancePtr) +{ + int Status; + u32 RegValue; + + /* + * Assert the argument + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + + /* + * Reset the device to get it back to its default state + */ + XAdcPs_Reset(InstancePtr); + + /* + * Write a value into the Alarm Threshold registers, read it back, and + * do the comparison + */ + XAdcPs_SetAlarmThreshold(InstancePtr, XADCPS_ATR_VCCINT_UPPER, + XADCPS_ATR_TEST_VALUE); + RegValue = XAdcPs_GetAlarmThreshold(InstancePtr, XADCPS_ATR_VCCINT_UPPER); + + if (RegValue == XADCPS_ATR_TEST_VALUE) { + Status = XST_SUCCESS; + } else { + Status = XST_FAILURE; + } + + /* + * Reset the device again to its default state. + */ + XAdcPs_Reset(InstancePtr); + /* + * Return the test result. + */ + return Status; +} +/** @} */ diff --git a/df_datalink/bsp/ps7_cortexa9_0/libsrc/xadcps_v2_3/src/xadcps_sinit.c b/df_datalink/bsp/ps7_cortexa9_0/libsrc/xadcps_v2_3/src/xadcps_sinit.c new file mode 100644 index 0000000..5572976 --- /dev/null +++ b/df_datalink/bsp/ps7_cortexa9_0/libsrc/xadcps_v2_3/src/xadcps_sinit.c @@ -0,0 +1,99 @@ +/****************************************************************************** +* +* Copyright (C) 2011 - 2014 Xilinx, Inc. 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 +* XILINX 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xadcps_sinit.c +* @addtogroup xadcps_v2_3 +* @{ +* +* This file contains the implementation of the XAdcPs driver's static +* initialization functionality. +* +* @note None. +* +*
+*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- -----  -------- -----------------------------------------------------
+* 1.00a ssb    12/22/11 First release based on the XPS/AXI XADC driver
+*
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xparameters.h" +#include "xadcps.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ +extern XAdcPs_Config XAdcPs_ConfigTable[]; + +/*****************************************************************************/ +/** +* +* This function looks up the device configuration based on the unique device ID. +* The table XAdcPs_ConfigTable contains the configuration info for each device +* in the system. +* +* @param DeviceId contains the ID of the device for which the +* device configuration pointer is to be returned. +* +* @return +* - A pointer to the configuration found. +* - NULL if the specified device ID was not found. +* +* @note None. +* +******************************************************************************/ +XAdcPs_Config *XAdcPs_LookupConfig(u16 DeviceId) +{ + XAdcPs_Config *CfgPtr = NULL; + u32 Index; + + for (Index=0; Index < 1; Index++) { + if (XAdcPs_ConfigTable[Index].DeviceId == DeviceId) { + CfgPtr = &XAdcPs_ConfigTable[Index]; + break; + } + } + + return CfgPtr; +} +/** @} */ diff --git a/df_datalink/bsp/system.mss b/df_datalink/bsp/system.mss new file mode 100644 index 0000000..685d2ad --- /dev/null +++ b/df_datalink/bsp/system.mss @@ -0,0 +1,232 @@ + + PARAMETER VERSION = 2.2.0 + + +BEGIN OS + PARAMETER OS_NAME = standalone + PARAMETER OS_VER = 7.0 + PARAMETER PROC_INSTANCE = ps7_cortexa9_0 + PARAMETER stdin = ps7_uart_0 + PARAMETER stdout = ps7_uart_0 +END + + +BEGIN PROCESSOR + PARAMETER DRIVER_NAME = cpu_cortexa9 + PARAMETER DRIVER_VER = 2.7 + PARAMETER HW_INSTANCE = ps7_cortexa9_0 + PARAMETER extra_compiler_flags = -DDEBUG -mcpu=cortex-a9 -mfpu=vfpv3 -mfloat-abi=hard -nostartfiles -g -Wall -Wextra +END + + +BEGIN DRIVER + PARAMETER DRIVER_NAME = generic + PARAMETER DRIVER_VER = 2.0 + PARAMETER HW_INSTANCE = axi_spi_engine_axi_spi_engine +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = bram + PARAMETER DRIVER_VER = 4.3 + PARAMETER HW_INSTANCE = phy_data_interface_ant_config_axi_bram_ctrl +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = bram + PARAMETER DRIVER_VER = 4.3 + PARAMETER HW_INSTANCE = phy_data_interface_phy_rx_buff_axi_bram_ctrl +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = bram + PARAMETER DRIVER_VER = 4.3 + PARAMETER HW_INSTANCE = phy_data_interface_phy_tx_buff_axi_bram_ctrl +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = generic + PARAMETER DRIVER_VER = 2.0 + PARAMETER HW_INSTANCE = ps7_afi_0 +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = generic + PARAMETER DRIVER_VER = 2.0 + PARAMETER HW_INSTANCE = ps7_afi_1 +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = generic + PARAMETER DRIVER_VER = 2.0 + PARAMETER HW_INSTANCE = ps7_afi_2 +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = generic + PARAMETER DRIVER_VER = 2.0 + PARAMETER HW_INSTANCE = ps7_afi_3 +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = coresightps_dcc + PARAMETER DRIVER_VER = 1.5 + PARAMETER HW_INSTANCE = ps7_coresight_comp_0 +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = ddrps + PARAMETER DRIVER_VER = 1.0 + PARAMETER HW_INSTANCE = ps7_ddr_0 +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = generic + PARAMETER DRIVER_VER = 2.0 + PARAMETER HW_INSTANCE = ps7_ddrc_0 +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = devcfg + PARAMETER DRIVER_VER = 3.5 + PARAMETER HW_INSTANCE = ps7_dev_cfg_0 +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = dmaps + PARAMETER DRIVER_VER = 2.4 + PARAMETER HW_INSTANCE = ps7_dma_ns +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = dmaps + PARAMETER DRIVER_VER = 2.4 + PARAMETER HW_INSTANCE = ps7_dma_s +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = generic + PARAMETER DRIVER_VER = 2.0 + PARAMETER HW_INSTANCE = ps7_globaltimer_0 +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = gpiops + PARAMETER DRIVER_VER = 3.5 + PARAMETER HW_INSTANCE = ps7_gpio_0 +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = generic + PARAMETER DRIVER_VER = 2.0 + PARAMETER HW_INSTANCE = ps7_gpv_0 +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = generic + PARAMETER DRIVER_VER = 2.0 + PARAMETER HW_INSTANCE = ps7_intc_dist_0 +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = generic + PARAMETER DRIVER_VER = 2.0 + PARAMETER HW_INSTANCE = ps7_iop_bus_config_0 +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = generic + PARAMETER DRIVER_VER = 2.0 + PARAMETER HW_INSTANCE = ps7_l2cachec_0 +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = generic + PARAMETER DRIVER_VER = 2.0 + PARAMETER HW_INSTANCE = ps7_ocmc_0 +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = generic + PARAMETER DRIVER_VER = 2.0 + PARAMETER HW_INSTANCE = ps7_pl310_0 +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = generic + PARAMETER DRIVER_VER = 2.0 + PARAMETER HW_INSTANCE = ps7_pmu_0 +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = qspips + PARAMETER DRIVER_VER = 3.6 + PARAMETER HW_INSTANCE = ps7_qspi_0 +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = generic + PARAMETER DRIVER_VER = 2.0 + PARAMETER HW_INSTANCE = ps7_qspi_linear_0 +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = generic + PARAMETER DRIVER_VER = 2.0 + PARAMETER HW_INSTANCE = ps7_ram_0 +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = generic + PARAMETER DRIVER_VER = 2.0 + PARAMETER HW_INSTANCE = ps7_ram_1 +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = generic + PARAMETER DRIVER_VER = 2.0 + PARAMETER HW_INSTANCE = ps7_scuc_0 +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = scugic + PARAMETER DRIVER_VER = 4.0 + PARAMETER HW_INSTANCE = ps7_scugic_0 +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = scutimer + PARAMETER DRIVER_VER = 2.1 + PARAMETER HW_INSTANCE = ps7_scutimer_0 +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = scuwdt + PARAMETER DRIVER_VER = 2.1 + PARAMETER HW_INSTANCE = ps7_scuwdt_0 +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = generic + PARAMETER DRIVER_VER = 2.0 + PARAMETER HW_INSTANCE = ps7_slcr_0 +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = uartps + PARAMETER DRIVER_VER = 3.7 + PARAMETER HW_INSTANCE = ps7_uart_0 +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = xadcps + PARAMETER DRIVER_VER = 2.3 + PARAMETER HW_INSTANCE = ps7_xadc_0 +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = generic + PARAMETER DRIVER_VER = 2.0 + PARAMETER HW_INSTANCE = systembus +END + + diff --git a/df_datalink/build/Xilinx.spec b/df_datalink/build/Xilinx.spec new file mode 100644 index 0000000..8eea377 --- /dev/null +++ b/df_datalink/build/Xilinx.spec @@ -0,0 +1,2 @@ +*startfile: +crti%O%s crtbegin%O%s diff --git a/df_datalink/build/makefile b/df_datalink/build/makefile new file mode 100644 index 0000000..62f8c14 --- /dev/null +++ b/df_datalink/build/makefile @@ -0,0 +1,82 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +-include ../makefile.init + +CC = /tools/Xilinx/SDK/2019.1/gnu/aarch32/lin/gcc-arm-none-eabi/bin/arm-none-eabi-gcc +XILIN_A9_PRE := /tools/Xilinx/SDK/2019.1/bin/a9-linaro-pre-build-step + +RM := rm -rf + +# All of the sources participating in the build are defined here +-include sources.mk +-include src/util/subdir.mk +-include src/systembus/subdir.mk +-include src/networking/phy_layer/subdir.mk +-include src/networking/link_layer/geometry/subdir.mk +-include src/networking/link_layer/subdir.mk +-include src/drivers/rf-transceiver/ad9361_reg/subdir.mk +-include src/drivers/rf-transceiver/ad9361/subdir.mk +-include src/drivers/platform/subdir.mk +-include src/drivers/frequency/hmc7044/subdir.mk +-include src/drivers/axi_core/spi_engine/subdir.mk +-include src/drivers/axi_core/axi_dmac/subdir.mk +-include src/drivers/api/subdir.mk +-include src/drivers/adc/ad9694/subdir.mk +-include src/dev_profile/subdir.mk +-include src/subdir.mk +-include subdir.mk +-include objects.mk + +ifneq ($(MAKECMDGOALS),clean) +ifneq ($(strip $(S_UPPER_DEPS)),) +-include $(S_UPPER_DEPS) +endif +ifneq ($(strip $(C_DEPS)),) +-include $(C_DEPS) +endif +endif + +-include ../makefile.defs + +# Add inputs and outputs from these tool invocations to the build variables +ELFSIZE += \ +df_datalink.elf.size \ + + +# All Target +all: pre-build main-build + +# Main-build Target +main-build: df_datalink.elf secondary-outputs + +# Tool invocations +df_datalink.elf: $(OBJS) ../src/lscript.ld $(USER_OBJS) + @echo 'Building target: $@' + @echo 'Invoking: ARM v7 gcc linker' + $(CC) -mcpu=cortex-a9 -mfpu=vfpv3 -mfloat-abi=hard -Wl,-build-id=none -specs=Xilinx.spec -Wl,-T -Wl,../src/lscript.ld -L../bsp/ps7_cortexa9_0/lib -o "df_datalink.elf" $(OBJS) $(USER_OBJS) $(LIBS) + @echo 'Finished building target: $@' + @echo ' ' + +df_datalink.elf.size: df_datalink.elf + @echo 'Invoking: ARM v7 Print Size' + arm-none-eabi-size df_datalink.elf |tee "df_datalink.elf.size" + @echo 'Finished building: $@' + @echo ' ' + +# Other Targets +clean: + -$(RM) $(EXECUTABLES)$(OBJS)$(S_UPPER_DEPS)$(C_DEPS)$(ELFSIZE) df_datalink.elf + -@echo ' ' + +pre-build: + -$(XILIN_A9_PRE) + -@echo ' ' + +secondary-outputs: $(ELFSIZE) + +.PHONY: all clean dependents +.SECONDARY: main-build pre-build + +-include ../makefile.targets diff --git a/df_datalink/build/objects.mk b/df_datalink/build/objects.mk new file mode 100644 index 0000000..24a8ef2 --- /dev/null +++ b/df_datalink/build/objects.mk @@ -0,0 +1,8 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +USER_OBJS := + +LIBS := -lm -Wl,--start-group,-lxil,-lgcc,-lc,--end-group + diff --git a/df_datalink/build/sources.mk b/df_datalink/build/sources.mk new file mode 100644 index 0000000..215a5fc --- /dev/null +++ b/df_datalink/build/sources.mk @@ -0,0 +1,34 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +LD_SRCS := +OBJ_SRCS := +S_SRCS := +C_SRCS := +S_UPPER_SRCS := +O_SRCS := +EXECUTABLES := +OBJS := +S_UPPER_DEPS := +C_DEPS := +ELFSIZE := + +# Every subdirectory with source files must be described here +SUBDIRS := \ +src/dev_profile \ +src/drivers/adc/ad9694 \ +src/drivers/api \ +src/drivers/axi_core/axi_dmac \ +src/drivers/axi_core/spi_engine \ +src/drivers/frequency/hmc7044 \ +src/drivers/platform \ +src/drivers/rf-transceiver/ad9361 \ +src/drivers/rf-transceiver/ad9361_reg \ +src \ +src/networking/link_layer \ +src/networking/link_layer/geometry \ +src/networking/phy_layer \ +src/systembus \ +src/util \ + diff --git a/df_datalink/build/src/dev_profile/subdir.mk b/df_datalink/build/src/dev_profile/subdir.mk new file mode 100644 index 0000000..2e09ea1 --- /dev/null +++ b/df_datalink/build/src/dev_profile/subdir.mk @@ -0,0 +1,39 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +# Add inputs and outputs from these tool invocations to the build variables +C_SRCS += \ +../src/dev_profile/ad9361_profile.c \ +../src/dev_profile/ad9361_reg_profile.c \ +../src/dev_profile/global_timer_profile.c \ +../src/dev_profile/hmc7044_profile.c \ +../src/dev_profile/intc_profile.c \ +../src/dev_profile/timer_profile.c + +OBJS += \ +./src/dev_profile/ad9361_profile.o \ +./src/dev_profile/ad9361_reg_profile.o \ +./src/dev_profile/global_timer_profile.o \ +./src/dev_profile/hmc7044_profile.o \ +./src/dev_profile/intc_profile.o \ +./src/dev_profile/timer_profile.o + +C_DEPS += \ +./src/dev_profile/ad9361_profile.d \ +./src/dev_profile/ad9361_reg_profile.d \ +./src/dev_profile/global_timer_profile.d \ +./src/dev_profile/hmc7044_profile.d \ +./src/dev_profile/intc_profile.d \ +./src/dev_profile/timer_profile.d + + +# Each subdirectory must supply rules for building sources it contributes +src/dev_profile/%.o: ../src/dev_profile/%.c + @echo 'Building file: $<' + @echo 'Invoking: ARM v7 gcc compiler' + $(CC) -Wall -O0 -g3 -I../bsp/ps7_cortexa9_0/include -I../src/include -c -fmessage-length=0 -MT"$@" -mcpu=cortex-a9 -mfpu=vfpv3 -mfloat-abi=hard -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + + diff --git a/df_datalink/build/src/drivers/adc/ad9694/subdir.mk b/df_datalink/build/src/drivers/adc/ad9694/subdir.mk new file mode 100644 index 0000000..ddb2fce --- /dev/null +++ b/df_datalink/build/src/drivers/adc/ad9694/subdir.mk @@ -0,0 +1,24 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +# Add inputs and outputs from these tool invocations to the build variables +C_SRCS += \ +../src/drivers/adc/ad9694/ad9694.c + +OBJS += \ +./src/drivers/adc/ad9694/ad9694.o + +C_DEPS += \ +./src/drivers/adc/ad9694/ad9694.d + + +# Each subdirectory must supply rules for building sources it contributes +src/drivers/adc/ad9694/%.o: ../src/drivers/adc/ad9694/%.c + @echo 'Building file: $<' + @echo 'Invoking: ARM v7 gcc compiler' + $(CC) -Wall -O0 -g3 -I../bsp/ps7_cortexa9_0/include -I../src/include -c -fmessage-length=0 -MT"$@" -mcpu=cortex-a9 -mfpu=vfpv3 -mfloat-abi=hard -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + + diff --git a/df_datalink/build/src/drivers/api/subdir.mk b/df_datalink/build/src/drivers/api/subdir.mk new file mode 100644 index 0000000..12e3d6a --- /dev/null +++ b/df_datalink/build/src/drivers/api/subdir.mk @@ -0,0 +1,39 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +# Add inputs and outputs from these tool invocations to the build variables +C_SRCS += \ +../src/drivers/api/gpio.c \ +../src/drivers/api/i2c.c \ +../src/drivers/api/irq.c \ +../src/drivers/api/spi.c \ +../src/drivers/api/timer.c \ +../src/drivers/api/trng.c + +OBJS += \ +./src/drivers/api/gpio.o \ +./src/drivers/api/i2c.o \ +./src/drivers/api/irq.o \ +./src/drivers/api/spi.o \ +./src/drivers/api/timer.o \ +./src/drivers/api/trng.o + +C_DEPS += \ +./src/drivers/api/gpio.d \ +./src/drivers/api/i2c.d \ +./src/drivers/api/irq.d \ +./src/drivers/api/spi.d \ +./src/drivers/api/timer.d \ +./src/drivers/api/trng.d + + +# Each subdirectory must supply rules for building sources it contributes +src/drivers/api/%.o: ../src/drivers/api/%.c + @echo 'Building file: $<' + @echo 'Invoking: ARM v7 gcc compiler' + $(CC) -Wall -O0 -g3 -I../bsp/ps7_cortexa9_0/include -I../src/include -c -fmessage-length=0 -MT"$@" -mcpu=cortex-a9 -mfpu=vfpv3 -mfloat-abi=hard -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + + diff --git a/df_datalink/build/src/drivers/axi_core/axi_dmac/subdir.mk b/df_datalink/build/src/drivers/axi_core/axi_dmac/subdir.mk new file mode 100644 index 0000000..fae6143 --- /dev/null +++ b/df_datalink/build/src/drivers/axi_core/axi_dmac/subdir.mk @@ -0,0 +1,24 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +# Add inputs and outputs from these tool invocations to the build variables +C_SRCS += \ +../src/drivers/axi_core/axi_dmac/axi_dmac.c + +OBJS += \ +./src/drivers/axi_core/axi_dmac/axi_dmac.o + +C_DEPS += \ +./src/drivers/axi_core/axi_dmac/axi_dmac.d + + +# Each subdirectory must supply rules for building sources it contributes +src/drivers/axi_core/axi_dmac/%.o: ../src/drivers/axi_core/axi_dmac/%.c + @echo 'Building file: $<' + @echo 'Invoking: ARM v7 gcc compiler' + $(CC) -Wall -O0 -g3 -I../bsp/ps7_cortexa9_0/include -I../src/include -c -fmessage-length=0 -MT"$@" -mcpu=cortex-a9 -mfpu=vfpv3 -mfloat-abi=hard -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + + diff --git a/df_datalink/build/src/drivers/axi_core/spi_engine/subdir.mk b/df_datalink/build/src/drivers/axi_core/spi_engine/subdir.mk new file mode 100644 index 0000000..41571fd --- /dev/null +++ b/df_datalink/build/src/drivers/axi_core/spi_engine/subdir.mk @@ -0,0 +1,24 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +# Add inputs and outputs from these tool invocations to the build variables +C_SRCS += \ +../src/drivers/axi_core/spi_engine/spi_engine.c + +OBJS += \ +./src/drivers/axi_core/spi_engine/spi_engine.o + +C_DEPS += \ +./src/drivers/axi_core/spi_engine/spi_engine.d + + +# Each subdirectory must supply rules for building sources it contributes +src/drivers/axi_core/spi_engine/%.o: ../src/drivers/axi_core/spi_engine/%.c + @echo 'Building file: $<' + @echo 'Invoking: ARM v7 gcc compiler' + $(CC) -Wall -O0 -g3 -I../bsp/ps7_cortexa9_0/include -I../src/include -c -fmessage-length=0 -MT"$@" -mcpu=cortex-a9 -mfpu=vfpv3 -mfloat-abi=hard -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + + diff --git a/df_datalink/build/src/drivers/frequency/hmc7044/subdir.mk b/df_datalink/build/src/drivers/frequency/hmc7044/subdir.mk new file mode 100644 index 0000000..f9ddfb7 --- /dev/null +++ b/df_datalink/build/src/drivers/frequency/hmc7044/subdir.mk @@ -0,0 +1,24 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +# Add inputs and outputs from these tool invocations to the build variables +C_SRCS += \ +../src/drivers/frequency/hmc7044/hmc7044.c + +OBJS += \ +./src/drivers/frequency/hmc7044/hmc7044.o + +C_DEPS += \ +./src/drivers/frequency/hmc7044/hmc7044.d + + +# Each subdirectory must supply rules for building sources it contributes +src/drivers/frequency/hmc7044/%.o: ../src/drivers/frequency/hmc7044/%.c + @echo 'Building file: $<' + @echo 'Invoking: ARM v7 gcc compiler' + $(CC) -Wall -O0 -g3 -I../bsp/ps7_cortexa9_0/include -I../src/include -c -fmessage-length=0 -MT"$@" -mcpu=cortex-a9 -mfpu=vfpv3 -mfloat-abi=hard -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + + diff --git a/df_datalink/build/src/drivers/platform/subdir.mk b/df_datalink/build/src/drivers/platform/subdir.mk new file mode 100644 index 0000000..b52ef54 --- /dev/null +++ b/df_datalink/build/src/drivers/platform/subdir.mk @@ -0,0 +1,48 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +# Add inputs and outputs from these tool invocations to the build variables +C_SRCS += \ +../src/drivers/platform/xilinx_axi_io.c \ +../src/drivers/platform/xilinx_delay.c \ +../src/drivers/platform/xilinx_gpio.c \ +../src/drivers/platform/xilinx_gpio_irq.c \ +../src/drivers/platform/xilinx_i2c.c \ +../src/drivers/platform/xilinx_irq.c \ +../src/drivers/platform/xilinx_spi.c \ +../src/drivers/platform/xilinx_spi_pl.c \ +../src/drivers/platform/xilinx_timer.c + +OBJS += \ +./src/drivers/platform/xilinx_axi_io.o \ +./src/drivers/platform/xilinx_delay.o \ +./src/drivers/platform/xilinx_gpio.o \ +./src/drivers/platform/xilinx_gpio_irq.o \ +./src/drivers/platform/xilinx_i2c.o \ +./src/drivers/platform/xilinx_irq.o \ +./src/drivers/platform/xilinx_spi.o \ +./src/drivers/platform/xilinx_spi_pl.o \ +./src/drivers/platform/xilinx_timer.o + +C_DEPS += \ +./src/drivers/platform/xilinx_axi_io.d \ +./src/drivers/platform/xilinx_delay.d \ +./src/drivers/platform/xilinx_gpio.d \ +./src/drivers/platform/xilinx_gpio_irq.d \ +./src/drivers/platform/xilinx_i2c.d \ +./src/drivers/platform/xilinx_irq.d \ +./src/drivers/platform/xilinx_spi.d \ +./src/drivers/platform/xilinx_spi_pl.d \ +./src/drivers/platform/xilinx_timer.d + + +# Each subdirectory must supply rules for building sources it contributes +src/drivers/platform/%.o: ../src/drivers/platform/%.c + @echo 'Building file: $<' + @echo 'Invoking: ARM v7 gcc compiler' + $(CC) -Wall -O0 -g3 -I../bsp/ps7_cortexa9_0/include -I../src/include -c -fmessage-length=0 -MT"$@" -mcpu=cortex-a9 -mfpu=vfpv3 -mfloat-abi=hard -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + + diff --git a/df_datalink/build/src/drivers/rf-transceiver/ad9361/subdir.mk b/df_datalink/build/src/drivers/rf-transceiver/ad9361/subdir.mk new file mode 100644 index 0000000..c250ef4 --- /dev/null +++ b/df_datalink/build/src/drivers/rf-transceiver/ad9361/subdir.mk @@ -0,0 +1,33 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +# Add inputs and outputs from these tool invocations to the build variables +C_SRCS += \ +../src/drivers/rf-transceiver/ad9361/ad9361.c \ +../src/drivers/rf-transceiver/ad9361/ad9361_api.c \ +../src/drivers/rf-transceiver/ad9361/ad9361_conv.c \ +../src/drivers/rf-transceiver/ad9361/ad9361_util.c + +OBJS += \ +./src/drivers/rf-transceiver/ad9361/ad9361.o \ +./src/drivers/rf-transceiver/ad9361/ad9361_api.o \ +./src/drivers/rf-transceiver/ad9361/ad9361_conv.o \ +./src/drivers/rf-transceiver/ad9361/ad9361_util.o + +C_DEPS += \ +./src/drivers/rf-transceiver/ad9361/ad9361.d \ +./src/drivers/rf-transceiver/ad9361/ad9361_api.d \ +./src/drivers/rf-transceiver/ad9361/ad9361_conv.d \ +./src/drivers/rf-transceiver/ad9361/ad9361_util.d + + +# Each subdirectory must supply rules for building sources it contributes +src/drivers/rf-transceiver/ad9361/%.o: ../src/drivers/rf-transceiver/ad9361/%.c + @echo 'Building file: $<' + @echo 'Invoking: ARM v7 gcc compiler' + $(CC) -Wall -O0 -g3 -I../bsp/ps7_cortexa9_0/include -I../src/include -c -fmessage-length=0 -MT"$@" -mcpu=cortex-a9 -mfpu=vfpv3 -mfloat-abi=hard -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + + diff --git a/df_datalink/build/src/drivers/rf-transceiver/ad9361_reg/subdir.mk b/df_datalink/build/src/drivers/rf-transceiver/ad9361_reg/subdir.mk new file mode 100644 index 0000000..993fe65 --- /dev/null +++ b/df_datalink/build/src/drivers/rf-transceiver/ad9361_reg/subdir.mk @@ -0,0 +1,24 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +# Add inputs and outputs from these tool invocations to the build variables +C_SRCS += \ +../src/drivers/rf-transceiver/ad9361_reg/ad9361_reg.c + +OBJS += \ +./src/drivers/rf-transceiver/ad9361_reg/ad9361_reg.o + +C_DEPS += \ +./src/drivers/rf-transceiver/ad9361_reg/ad9361_reg.d + + +# Each subdirectory must supply rules for building sources it contributes +src/drivers/rf-transceiver/ad9361_reg/%.o: ../src/drivers/rf-transceiver/ad9361_reg/%.c + @echo 'Building file: $<' + @echo 'Invoking: ARM v7 gcc compiler' + $(CC) -Wall -O0 -g3 -I../bsp/ps7_cortexa9_0/include -I../src/include -c -fmessage-length=0 -MT"$@" -mcpu=cortex-a9 -mfpu=vfpv3 -mfloat-abi=hard -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + + diff --git a/df_datalink/build/src/networking/link_layer/geometry/subdir.mk b/df_datalink/build/src/networking/link_layer/geometry/subdir.mk new file mode 100644 index 0000000..bb27a61 --- /dev/null +++ b/df_datalink/build/src/networking/link_layer/geometry/subdir.mk @@ -0,0 +1,30 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +# Add inputs and outputs from these tool invocations to the build variables +C_SRCS += \ +../src/networking/link_layer/geometry/coord.c \ +../src/networking/link_layer/geometry/eulerangles.c \ +../src/networking/link_layer/geometry/quaternion.c + +OBJS += \ +./src/networking/link_layer/geometry/coord.o \ +./src/networking/link_layer/geometry/eulerangles.o \ +./src/networking/link_layer/geometry/quaternion.o + +C_DEPS += \ +./src/networking/link_layer/geometry/coord.d \ +./src/networking/link_layer/geometry/eulerangles.d \ +./src/networking/link_layer/geometry/quaternion.d + + +# Each subdirectory must supply rules for building sources it contributes +src/networking/link_layer/geometry/%.o: ../src/networking/link_layer/geometry/%.c + @echo 'Building file: $<' + @echo 'Invoking: ARM v7 gcc compiler' + $(CC) -Wall -O0 -g3 -I../bsp/ps7_cortexa9_0/include -I../src/include -c -fmessage-length=0 -MT"$@" -mcpu=cortex-a9 -mfpu=vfpv3 -mfloat-abi=hard -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + + diff --git a/df_datalink/build/src/networking/link_layer/subdir.mk b/df_datalink/build/src/networking/link_layer/subdir.mk new file mode 100644 index 0000000..b5fed5f --- /dev/null +++ b/df_datalink/build/src/networking/link_layer/subdir.mk @@ -0,0 +1,42 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +# Add inputs and outputs from these tool invocations to the build variables +C_SRCS += \ +../src/networking/link_layer/framing.c \ +../src/networking/link_layer/link_layer.c \ +../src/networking/link_layer/node_list.c \ +../src/networking/link_layer/routine_table.c \ +../src/networking/link_layer/scan.c \ +../src/networking/link_layer/service.c \ +../src/networking/link_layer/time_sync.c + +OBJS += \ +./src/networking/link_layer/framing.o \ +./src/networking/link_layer/link_layer.o \ +./src/networking/link_layer/node_list.o \ +./src/networking/link_layer/routine_table.o \ +./src/networking/link_layer/scan.o \ +./src/networking/link_layer/service.o \ +./src/networking/link_layer/time_sync.o + +C_DEPS += \ +./src/networking/link_layer/framing.d \ +./src/networking/link_layer/link_layer.d \ +./src/networking/link_layer/node_list.d \ +./src/networking/link_layer/routine_table.d \ +./src/networking/link_layer/scan.d \ +./src/networking/link_layer/service.d \ +./src/networking/link_layer/time_sync.d + + +# Each subdirectory must supply rules for building sources it contributes +src/networking/link_layer/%.o: ../src/networking/link_layer/%.c + @echo 'Building file: $<' + @echo 'Invoking: ARM v7 gcc compiler' + $(CC) -Wall -O0 -g3 -I../bsp/ps7_cortexa9_0/include -I../src/include -c -fmessage-length=0 -MT"$@" -mcpu=cortex-a9 -mfpu=vfpv3 -mfloat-abi=hard -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + + diff --git a/df_datalink/build/src/networking/phy_layer/subdir.mk b/df_datalink/build/src/networking/phy_layer/subdir.mk new file mode 100644 index 0000000..65d68d5 --- /dev/null +++ b/df_datalink/build/src/networking/phy_layer/subdir.mk @@ -0,0 +1,27 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +# Add inputs and outputs from these tool invocations to the build variables +C_SRCS += \ +../src/networking/phy_layer/phy_antenna.c \ +../src/networking/phy_layer/phy_layer.c + +OBJS += \ +./src/networking/phy_layer/phy_antenna.o \ +./src/networking/phy_layer/phy_layer.o + +C_DEPS += \ +./src/networking/phy_layer/phy_antenna.d \ +./src/networking/phy_layer/phy_layer.d + + +# Each subdirectory must supply rules for building sources it contributes +src/networking/phy_layer/%.o: ../src/networking/phy_layer/%.c + @echo 'Building file: $<' + @echo 'Invoking: ARM v7 gcc compiler' + $(CC) -Wall -O0 -g3 -I../bsp/ps7_cortexa9_0/include -I../src/include -c -fmessage-length=0 -MT"$@" -mcpu=cortex-a9 -mfpu=vfpv3 -mfloat-abi=hard -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + + diff --git a/df_datalink/build/src/subdir.mk b/df_datalink/build/src/subdir.mk new file mode 100644 index 0000000..1583c87 --- /dev/null +++ b/df_datalink/build/src/subdir.mk @@ -0,0 +1,30 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +# Add inputs and outputs from these tool invocations to the build variables +LD_SRCS += \ +../src/lscript.ld + +C_SRCS += \ +../src/main.c \ +../src/system_monitor.c + +OBJS += \ +./src/main.o \ +./src/system_monitor.o + +C_DEPS += \ +./src/main.d \ +./src/system_monitor.d + + +# Each subdirectory must supply rules for building sources it contributes +src/%.o: ../src/%.c + @echo 'Building file: $<' + @echo 'Invoking: ARM v7 gcc compiler' + $(CC) -Wall -O0 -g3 -I../bsp/ps7_cortexa9_0/include -I../src/include -c -fmessage-length=0 -MT"$@" -mcpu=cortex-a9 -mfpu=vfpv3 -mfloat-abi=hard -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + + diff --git a/df_datalink/build/src/systembus/subdir.mk b/df_datalink/build/src/systembus/subdir.mk new file mode 100644 index 0000000..fd7331d --- /dev/null +++ b/df_datalink/build/src/systembus/subdir.mk @@ -0,0 +1,27 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +# Add inputs and outputs from these tool invocations to the build variables +C_SRCS += \ +../src/systembus/systembus.c \ +../src/systembus/systembus_uart.c + +OBJS += \ +./src/systembus/systembus.o \ +./src/systembus/systembus_uart.o + +C_DEPS += \ +./src/systembus/systembus.d \ +./src/systembus/systembus_uart.d + + +# Each subdirectory must supply rules for building sources it contributes +src/systembus/%.o: ../src/systembus/%.c + @echo 'Building file: $<' + @echo 'Invoking: ARM v7 gcc compiler' + $(CC) -Wall -O0 -g3 -I../bsp/ps7_cortexa9_0/include -I../src/include -c -fmessage-length=0 -MT"$@" -mcpu=cortex-a9 -mfpu=vfpv3 -mfloat-abi=hard -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + + diff --git a/df_datalink/build/src/util/subdir.mk b/df_datalink/build/src/util/subdir.mk new file mode 100644 index 0000000..0112f6f --- /dev/null +++ b/df_datalink/build/src/util/subdir.mk @@ -0,0 +1,36 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +# Add inputs and outputs from these tool invocations to the build variables +C_SRCS += \ +../src/util/circ_queue.c \ +../src/util/common.c \ +../src/util/crc.c \ +../src/util/list.c \ +../src/util/util.c + +OBJS += \ +./src/util/circ_queue.o \ +./src/util/common.o \ +./src/util/crc.o \ +./src/util/list.o \ +./src/util/util.o + +C_DEPS += \ +./src/util/circ_queue.d \ +./src/util/common.d \ +./src/util/crc.d \ +./src/util/list.d \ +./src/util/util.d + + +# Each subdirectory must supply rules for building sources it contributes +src/util/%.o: ../src/util/%.c + @echo 'Building file: $<' + @echo 'Invoking: ARM v7 gcc compiler' + $(CC) -Wall -O0 -g3 -I../bsp/ps7_cortexa9_0/include -I../src/include -c -fmessage-length=0 -MT"$@" -mcpu=cortex-a9 -mfpu=vfpv3 -mfloat-abi=hard -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + + diff --git a/df_datalink/src/Xilinx.spec b/df_datalink/src/Xilinx.spec new file mode 100644 index 0000000..8eea377 --- /dev/null +++ b/df_datalink/src/Xilinx.spec @@ -0,0 +1,2 @@ +*startfile: +crti%O%s crtbegin%O%s diff --git a/df_datalink/src/config/app_config.h b/df_datalink/src/config/app_config.h new file mode 100644 index 0000000..2fdb43b --- /dev/null +++ b/df_datalink/src/config/app_config.h @@ -0,0 +1,194 @@ +/*****************************************************************************/ +/** + * Description: Global configurations. + * + * Date: 2021-04-28 13:19 + * Last Editors: Fan Hao + * Last Edit Time: [2022-05-23 20:32] + * + * Revisions: Rev 0.0 + * History: + * [2021-04-28]: Initial edition. + * + * Copyright(c) 2021 Beijing Institute of Technology. + * Lab of Communication and Networking + * + ******************************************************************************/ + +#ifndef __APP_CONFIG_H_ +#define __APP_CONFIG_H_ + +#define XILINX_PLATFORM + +#include "xparameters.h" + +/******** Software Version ********/ +#define _APP_VER 0x00010008 + +#define _APP_VER_MAIN ((_APP_VER & 0xFF000000) >> 24) +#define _APP_VER_MINOR ((_APP_VER & 0x00FF0000) >> 16) +#define _APP_VER_PATCH (_APP_VER & 0x0000FFFF) + +/*********** Debug Info Level ************/ + #define _DEBUG_LEVEL 1 +// 3 - print all debug info +// 2 - print warnings and errors +// 1 - print only errors +// other - print nothing + +//#define DATALINK_ENABLE_AUTORECONNECT +#define DATALINK_ENABLE_AUTOTIMESYNC +//#define DATALINK_ENABLE_BERTEST + +/************ Hardware Configs ************/ +#define CPU_CLK_HZ XPAR_CPU_CORTEXA9_0_CPU_CLK_FREQ_HZ +#define GLOBAL_TIMER_CLK_HZ (CPU_CLK_HZ/2) +#define SCU_TIMER_CLK_HZ (CPU_CLK_HZ/2) +#define FCLK_CLK0_HZ 100000000 + +/********* Zynq Platform Configs **********/ +// SCU Timer (for logging) +#define SCUTIMER_DEVICE_ID XPAR_PS7_SCUTIMER_0_DEVICE_ID +#define SCUTIMER_INTR_ID XPAR_SCUTIMER_INTR + +// Physical Layer Configs +#define PHY_DEVICE_ID 0 +#define PHY_BASEADDR XPAR_PHY_BASEADDR +#define PHY_BEAM_SET_PRESET +#define PHY_BEAM_FORMING_ENABLE +// -- Antenna Bram Configs +#define PHY_ANTCONFIG_BRAM_DEVICE_ID XPAR_PHY_DATA_INTERFACE_ANT_CONFIG_AXI_BRAM_CTRL_DEVICE_ID +// -- Buffers +#define PHY_TXBUFF_BRAM_DEVICE_ID XPAR_PHY_DATA_INTERFACE_PHY_TX_BUFF_AXI_BRAM_CTRL_DEVICE_ID +#define PHY_RXBUFF_BRAM_DEVICE_ID XPAR_PHY_DATA_INTERFACE_PHY_RX_BUFF_AXI_BRAM_CTRL_DEVICE_ID +// -- Xadc +#define PHY_HW_XADC_DEVICE_ID XPAR_PS7_XADC_0_DEVICE_ID +// -- Interrupt id +#define PHY_INTR_ID XPAR_FABRIC_PHY_IRQ_INTR + +// System Bus Configs +#define SYSBUS_BASE_ADDR XPAR_SYSTEMBUS_BASEADDR +#define SYSBUS_TX_INTR_ID XPAR_FABRIC_SYSTEMBUS_TX_DONE_INTR +#define SYSBUS_RX_INTR_ID XPAR_FABRIC_SYSTEMBUS_RX_DONE_INTR + +// Global Timer config +#define GLOBAL_TIMER_DEVICE_ID XPAR_GLOBAL_TMR_DEVICE_ID +#define GLOBAL_TIMER_BASEADDR XPAR_GLOBAL_TMR_BASEADDR +#define GLOBAL_TIMER_INTR_ID XPAR_GLOBAL_TMR_INTR + +// INTC configis +#define INTC_DEVICE_ID XPAR_SCUGIC_0_DEVICE_ID + +// AD9361 Configuration +#define SPI_INTERFACE_SPI_ENGINE +#define HAVE_SPLIT_GAIN_TABLE 1 /* only set to 0 in case split_gain_table_mode_enable = 0*/ +#define HAVE_TDD_SYNTH_TABLE 1 /* only set to 0 in case split_gain_table_mode_enable = 0*/ +#define AD9361_DEVICE 1 /* set it 1 if AD9361 device is used, 0 otherwise */ +#define AD9364_DEVICE 0 /* set it 1 if AD9364 device is used, 0 otherwise */ +#define AD9363A_DEVICE 0 /* set it 1 if AD9363A device is used, 0 otherwise */ +#define HAVE_VERBOSE_MESSAGES /* Recommended during development prints errors and warnings */ +//#define HAVE_DEBUG_MESSAGES /* For Debug purposes only */ +// -- AD9361 SPI Engine Configuration +#define AD9361_SPI_DEVICE_ID 0 +#define AD9361_SPI_ENGINE_REF_CLK FCLK_CLK0_HZ +#define AD9361_SPI_ENGINE_MAX_SPEED 5000000 +#define AD9361_SPI_ENGINE_BASEADDR XPAR_AXI_SPI_ENGINE_AXI_SPI_ENGINE_BASEADDR +#define AD9361_SPI_ENGINE_DATA_WIDTH 8 +#define AD9361_SPI_ENGINE_CS_DELAY 3 +#define AD9361_SPI_CS_AD9361_1 0x01 +#define AD9361_SPI_CS_AD9361_2 0x02 +#define AD9361_TIMEOUT_TH 2000 +// AD9361 GPIO Configurations +#define AD9361_GPIO_DEVICE_ID 0 +#define AD9361_GPIO_OFFSET 54 +#define AD9361_GPIO_INPUT 0 +#define AD9361_GPIO_OUTPUT 1 +#define AD9361_GPIO_DISABLE 0 +#define AD9361_GPIO_ENABLE 1 +// -- AD9361-1 +#define AD9361_1_TXNRX (AD9361_GPIO_OFFSET+6) +#define AD9361_1_ENABLE (AD9361_GPIO_OFFSET+7) +#define AD9361_1_EN_AGC (AD9361_GPIO_OFFSET+8) +#define AD9361_1_RESET_B (AD9361_GPIO_OFFSET+9) +#define AD9361_1_CTRL_OUT0 (AD9361_GPIO_OFFSET+10) +#define AD9361_1_CTRL_OUT1 (AD9361_GPIO_OFFSET+11) +#define AD9361_1_CTRL_OUT2 (AD9361_GPIO_OFFSET+12) +#define AD9361_1_CTRL_OUT3 (AD9361_GPIO_OFFSET+13) +#define AD9361_1_CTRL_OUT4 (AD9361_GPIO_OFFSET+14) +#define AD9361_1_CTRL_OUT5 (AD9361_GPIO_OFFSET+15) +#define AD9361_1_CTRL_OUT6 (AD9361_GPIO_OFFSET+16) +#define AD9361_1_CTRL_OUT7 (AD9361_GPIO_OFFSET+17) +#define AD9361_1_CTRL_IN0 (AD9361_GPIO_OFFSET+18) +#define AD9361_1_CTRL_IN1 (AD9361_GPIO_OFFSET+19) +#define AD9361_1_CTRL_IN2 (AD9361_GPIO_OFFSET+20) +#define AD9361_1_CTRL_IN3 (AD9361_GPIO_OFFSET+21) +// AD9361-2 +#define AD9361_2_TXNRX (AD9361_GPIO_OFFSET+22) +#define AD9361_2_ENABLE (AD9361_GPIO_OFFSET+23) +#define AD9361_2_EN_AGC (AD9361_GPIO_OFFSET+24) +#define AD9361_2_RESET_B (AD9361_GPIO_OFFSET+25) +#define AD9361_2_CTRL_OUT0 (AD9361_GPIO_OFFSET+26) +#define AD9361_2_CTRL_OUT1 (AD9361_GPIO_OFFSET+27) +#define AD9361_2_CTRL_OUT2 (AD9361_GPIO_OFFSET+28) +#define AD9361_2_CTRL_OUT3 (AD9361_GPIO_OFFSET+29) +#define AD9361_2_CTRL_OUT4 (AD9361_GPIO_OFFSET+30) +#define AD9361_2_CTRL_OUT5 (AD9361_GPIO_OFFSET+31) +#define AD9361_2_CTRL_OUT6 (AD9361_GPIO_OFFSET+32) +#define AD9361_2_CTRL_OUT7 (AD9361_GPIO_OFFSET+33) +#define AD9361_2_CTRL_IN0 (AD9361_GPIO_OFFSET+34) +#define AD9361_2_CTRL_IN1 (AD9361_GPIO_OFFSET+35) +#define AD9361_2_CTRL_IN2 (AD9361_GPIO_OFFSET+36) +#define AD9361_2_CTRL_IN3 (AD9361_GPIO_OFFSET+37) +// AD9361-Status Code +#define AD9361_SYNC (AD9361_GPIO_OFFSET+38) +#define AD9361_RX_FIFO_RST (AD9361_GPIO_OFFSET+39) +#define AD9361_1_CAL_START (AD9361_GPIO_OFFSET+40) +#define AD9361_2_CAL_START (AD9361_GPIO_OFFSET+41) +#define AD9361_RECAL (AD9361_GPIO_OFFSET+42) +#define AD9361_TX_SWITCH (AD9361_GPIO_OFFSET+43) +#define AD9361_1_CAL_DONE (AD9361_GPIO_OFFSET+44) +#define AD9361_2_CAL_DONE (AD9361_GPIO_OFFSET+45) +#define AD9361_CAL_RESULT (AD9361_GPIO_OFFSET+46) + +typedef enum +{ + TX_FREQ_125, + TX_FREQ_126, + TX_FREQ_4125 +} ad9361TxFreq; + +// HMC7044 Configurations +#define HMC7044_GPIO_DEVICE_ID 0 +#define HMC7044_GPIO_OFFSET 54 +#define HMC7044_RESET (HMC7044_GPIO_OFFSET+0) +#define HMC7044_SYNC (HMC7044_GPIO_OFFSET+1) +#define HMC7044_GPIO_0 (HMC7044_GPIO_OFFSET+2) +#define HMC7044_GPIO_1 (HMC7044_GPIO_OFFSET+3) +#define HMC7044_GPIO_2 (HMC7044_GPIO_OFFSET+4) +#define HMC7044_GPIO_3 (HMC7044_GPIO_OFFSET+5) +// -- HMC7044 SPI Engine Configuration +#define HMC7044_SPI_DEVICE_ID 0 +#define HMC7044_SPI_ENGINE_REF_CLK FCLK_CLK0_HZ +#define HMC7044_SPI_ENGINE_MAX_SPEED 5000000 +#define HMC7044_SPI_ENGINE_BASEADDR XPAR_AXI_SPI_ENGINE_AXI_SPI_ENGINE_BASEADDR +#define HMC7044_SPI_ENGINE_DATA_WIDTH 8 +#define HMC7044_SPI_ENGINE_CS_DELAY 3 +#define HMC7044_SPI_CS_HMC7044 0x00 + + +// Configuration Check +#if defined(PHY_BEAM_SET_PRESET) && !defined(PHY_BEAM_FORMING_ENABLE) +#define PHY_BEAM_FORMING_ENABLE +#warning To impliment beam scan must enable beam forming... +#endif + +#if defined(DATALINK_ENABLE_BERTEST) +#if !defined(DATALINK_ENABLE_AUTOTIMESYNC) + #warning To enbale bit error rate test, auto time-sync should be enabled... +#endif +#if defined(DATALINK_ENABLE_AUTORECONNECT) + #error Do not support auto reconnnect in bit error rate test mode... +#endif +#endif + +#endif //__APP_CONFIG_H_ diff --git a/df_datalink/src/dev_profile/ad9361_profile.c b/df_datalink/src/dev_profile/ad9361_profile.c new file mode 100644 index 0000000..90de27b --- /dev/null +++ b/df_datalink/src/dev_profile/ad9361_profile.c @@ -0,0 +1,340 @@ +#include "dev_profile.h" +#include "../config/app_config.h" +#include "../drivers/rf-transceiver/ad9361/ad9361_api.h" +#include "../drivers/axi_core/spi_engine/spi_engine.h" +#include "../drivers/platform/xilinx_gpio.h" + +struct spi_engine_init_param spi_engine_param = { + .ref_clk_hz = AD9361_SPI_ENGINE_REF_CLK, + .type = SPI_ENGINE, + .spi_engine_baseaddr = AD9361_SPI_ENGINE_BASEADDR, + .cs_delay = AD9361_SPI_ENGINE_CS_DELAY, + .data_width = AD9361_SPI_ENGINE_DATA_WIDTH +}; + +struct xil_gpio_init_param xil_gpio_param = { + .type = GPIO_PS, + .device_id = AD9361_GPIO_DEVICE_ID +}; + +AD9361_InitParam ad9361_default_init_param = { + /* Device selection */ + ID_AD9361, // dev_sel + /* Reference Clock */ + 48000000UL, //reference_clk_rate + /* Base Configuration */ + 1, //two_rx_two_tx_mode_enable *** adi,2rx-2tx-mode-enable + 1, //one_rx_one_tx_mode_use_rx_num *** adi,1rx-1tx-mode-use-rx-num + 1, //one_rx_one_tx_mode_use_tx_num *** adi,1rx-1tx-mode-use-tx-num + 1, //frequency_division_duplex_mode_enable *** adi,frequency-division-duplex-mode-enable + 0, //frequency_division_duplex_independent_mode_enable *** adi,frequency-division-duplex-independent-mode-enable + 0, //tdd_use_dual_synth_mode_enable *** adi,tdd-use-dual-synth-mode-enable + 0, //tdd_skip_vco_cal_enable *** adi,tdd-skip-vco-cal-enable + 0, //tx_fastlock_delay_ns *** adi,tx-fastlock-delay-ns + 0, //rx_fastlock_delay_ns *** adi,rx-fastlock-delay-ns + 0, //rx_fastlock_pincontrol_enable *** adi,rx-fastlock-pincontrol-enable + 0, //tx_fastlock_pincontrol_enable *** adi,tx-fastlock-pincontrol-enable + 0, //external_rx_lo_enable *** adi,external-rx-lo-enable + 0, //external_tx_lo_enable *** adi,external-tx-lo-enable + 5, //dc_offset_tracking_update_event_mask *** adi,dc-offset-tracking-update-event-mask + 6, //dc_offset_attenuation_high_range *** adi,dc-offset-attenuation-high-range + 5, //dc_offset_attenuation_low_range *** adi,dc-offset-attenuation-low-range + 0x28, //dc_offset_count_high_range *** adi,dc-offset-count-high-range + 0x32, //dc_offset_count_low_range *** adi,dc-offset-count-low-range + 0, //split_gain_table_mode_enable *** adi,split-gain-table-mode-enable + MAX_SYNTH_FREF, //trx_synthesizer_target_fref_overwrite_hz *** adi,trx-synthesizer-target-fref-overwrite-hz + 0, // qec_tracking_slow_mode_enable *** adi,qec-tracking-slow-mode-enable + /* ENSM Control */ + 0, //ensm_enable_pin_pulse_mode_enable *** adi,ensm-enable-pin-pulse-mode-enable + 0, //ensm_enable_txnrx_control_enable *** adi,ensm-enable-txnrx-control-enable + /* LO Control */ + 4125000000UL, //rx_synthesizer_frequency_hz *** adi,rx-synthesizer-frequency-hz + 4126000000UL, //tx_synthesizer_frequency_hz *** adi,tx-synthesizer-frequency-hz + 1, //tx_lo_powerdown_managed_enable *** adi,tx-lo-powerdown-managed-enable + /* Rate & BW Control */ + {768000000, 192000000, 96000000, 48000000, 24000000, 24000000},// rx_path_clock_frequencies[6] *** adi,rx-path-clock-frequencies + {768000000, 192000000, 96000000, 48000000, 24000000, 24000000},// tx_path_clock_frequencies[6] *** adi,tx-path-clock-frequencies + 18000000,//rf_rx_bandwidth_hz *** adi,rf-rx-bandwidth-hz + 18000000,//rf_tx_bandwidth_hz *** adi,rf-tx-bandwidth-hz + /* RF Port Control */ + 0, //rx_rf_port_input_select *** adi,rx-rf-port-input-select + 0, //tx_rf_port_input_select *** adi,tx-rf-port-input-select + /* TX Attenuation Control */ + 10000, //tx_attenuation_mdB *** adi,tx-attenuation-mdB + 0, //update_tx_gain_in_alert_enable *** adi,update-tx-gain-in-alert-enable + /* Reference Clock Control */ + 0, //xo_disable_use_ext_refclk_enable *** adi,xo-disable-use-ext-refclk-enable + {8, 5920}, //dcxo_coarse_and_fine_tune[2] *** adi,dcxo-coarse-and-fine-tune + CLKOUT_DISABLE, //clk_output_mode_select *** adi,clk-output-mode-select + /* Gain Control */ + 2, //gc_rx1_mode *** adi,gc-rx1-mode + 2, //gc_rx2_mode *** adi,gc-rx2-mode + 58, //gc_adc_large_overload_thresh *** adi,gc-adc-large-overload-thresh + 4, //gc_adc_ovr_sample_size *** adi,gc-adc-ovr-sample-size + 47, //gc_adc_small_overload_thresh *** adi,gc-adc-small-overload-thresh + 8192, //gc_dec_pow_measurement_duration *** adi,gc-dec-pow-measurement-duration + 0, //gc_dig_gain_enable *** adi,gc-dig-gain-enable + 800, //gc_lmt_overload_high_thresh *** adi,gc-lmt-overload-high-thresh + 704, //gc_lmt_overload_low_thresh *** adi,gc-lmt-overload-low-thresh + 24, //gc_low_power_thresh *** adi,gc-low-power-thresh + 15, //gc_max_dig_gain *** adi,gc-max-dig-gain + 0, //gc_use_rx_fir_out_for_dec_pwr_meas_enable *** adi,gc-use-rx-fir-out-for-dec-pwr-meas-enable + /* Gain MGC Control */ + 2, //mgc_dec_gain_step *** adi,mgc-dec-gain-step + 2, //mgc_inc_gain_step *** adi,mgc-inc-gain-step + 0, //mgc_rx1_ctrl_inp_enable *** adi,mgc-rx1-ctrl-inp-enable + 0, //mgc_rx2_ctrl_inp_enable *** adi,mgc-rx2-ctrl-inp-enable + 0, //mgc_split_table_ctrl_inp_gain_mode *** adi,mgc-split-table-ctrl-inp-gain-mode + /* Gain AGC Control */ + 10, //agc_adc_large_overload_exceed_counter *** adi,agc-adc-large-overload-exceed-counter + 2, //agc_adc_large_overload_inc_steps *** adi,agc-adc-large-overload-inc-steps + 0, //agc_adc_lmt_small_overload_prevent_gain_inc_enable *** adi,agc-adc-lmt-small-overload-prevent-gain-inc-enable + 10, //agc_adc_small_overload_exceed_counter *** adi,agc-adc-small-overload-exceed-counter + 4, //agc_dig_gain_step_size *** adi,agc-dig-gain-step-size + 3, //agc_dig_saturation_exceed_counter *** adi,agc-dig-saturation-exceed-counter + 1000, // agc_gain_update_interval_us *** adi,agc-gain-update-interval-us + 0, //agc_immed_gain_change_if_large_adc_overload_enable *** adi,agc-immed-gain-change-if-large-adc-overload-enable + 0, //agc_immed_gain_change_if_large_lmt_overload_enable *** adi,agc-immed-gain-change-if-large-lmt-overload-enable + 10, //agc_inner_thresh_high *** adi,agc-inner-thresh-high + 1, //agc_inner_thresh_high_dec_steps *** adi,agc-inner-thresh-high-dec-steps + 12, //agc_inner_thresh_low *** adi,agc-inner-thresh-low + 1, //agc_inner_thresh_low_inc_steps *** adi,agc-inner-thresh-low-inc-steps + 10, //agc_lmt_overload_large_exceed_counter *** adi,agc-lmt-overload-large-exceed-counter + 2, //agc_lmt_overload_large_inc_steps *** adi,agc-lmt-overload-large-inc-steps + 10, //agc_lmt_overload_small_exceed_counter *** adi,agc-lmt-overload-small-exceed-counter + 5, //agc_outer_thresh_high *** adi,agc-outer-thresh-high + 2, //agc_outer_thresh_high_dec_steps *** adi,agc-outer-thresh-high-dec-steps + 18, //agc_outer_thresh_low *** adi,agc-outer-thresh-low + 2, //agc_outer_thresh_low_inc_steps *** adi,agc-outer-thresh-low-inc-steps + 1, //agc_attack_delay_extra_margin_us; *** adi,agc-attack-delay-extra-margin-us + 0, //agc_sync_for_gain_counter_enable *** adi,agc-sync-for-gain-counter-enable + /* Fast AGC */ + 64, //fagc_dec_pow_measuremnt_duration *** adi,fagc-dec-pow-measurement-duration + 260, //fagc_state_wait_time_ns *** adi,fagc-state-wait-time-ns + /* Fast AGC - Low Power */ + 0, //fagc_allow_agc_gain_increase *** adi,fagc-allow-agc-gain-increase-enable + 5, //fagc_lp_thresh_increment_time *** adi,fagc-lp-thresh-increment-time + 1, //fagc_lp_thresh_increment_steps *** adi,fagc-lp-thresh-increment-steps + /* Fast AGC - Lock Level (Lock Level is set via slow AGC inner high threshold) */ + 1, //fagc_lock_level_lmt_gain_increase_en *** adi,fagc-lock-level-lmt-gain-increase-enable + 5, //fagc_lock_level_gain_increase_upper_limit *** adi,fagc-lock-level-gain-increase-upper-limit + /* Fast AGC - Peak Detectors and Final Settling */ + 1, //fagc_lpf_final_settling_steps *** adi,fagc-lpf-final-settling-steps + 1, //fagc_lmt_final_settling_steps *** adi,fagc-lmt-final-settling-steps + 3, //fagc_final_overrange_count *** adi,fagc-final-overrange-count + /* Fast AGC - Final Power Test */ + 0, //fagc_gain_increase_after_gain_lock_en *** adi,fagc-gain-increase-after-gain-lock-enable + /* Fast AGC - Unlocking the Gain */ + 0, //fagc_gain_index_type_after_exit_rx_mode *** adi,fagc-gain-index-type-after-exit-rx-mode + 1, //fagc_use_last_lock_level_for_set_gain_en *** adi,fagc-use-last-lock-level-for-set-gain-enable + 1, //fagc_rst_gla_stronger_sig_thresh_exceeded_en *** adi,fagc-rst-gla-stronger-sig-thresh-exceeded-enable + 5, //fagc_optimized_gain_offset *** adi,fagc-optimized-gain-offset + 10, //fagc_rst_gla_stronger_sig_thresh_above_ll *** adi,fagc-rst-gla-stronger-sig-thresh-above-ll + 1, //fagc_rst_gla_engergy_lost_sig_thresh_exceeded_en *** adi,fagc-rst-gla-engergy-lost-sig-thresh-exceeded-enable + 1, //fagc_rst_gla_engergy_lost_goto_optim_gain_en *** adi,fagc-rst-gla-engergy-lost-goto-optim-gain-enable + 10, //fagc_rst_gla_engergy_lost_sig_thresh_below_ll *** adi,fagc-rst-gla-engergy-lost-sig-thresh-below-ll + 8, //fagc_energy_lost_stronger_sig_gain_lock_exit_cnt *** adi,fagc-energy-lost-stronger-sig-gain-lock-exit-cnt + 1, //fagc_rst_gla_large_adc_overload_en *** adi,fagc-rst-gla-large-adc-overload-enable + 1, //fagc_rst_gla_large_lmt_overload_en *** adi,fagc-rst-gla-large-lmt-overload-enable + 0, //fagc_rst_gla_en_agc_pulled_high_en *** adi,fagc-rst-gla-en-agc-pulled-high-enable + 0, //fagc_rst_gla_if_en_agc_pulled_high_mode *** adi,fagc-rst-gla-if-en-agc-pulled-high-mode + 64, //fagc_power_measurement_duration_in_state5 *** adi,fagc-power-measurement-duration-in-state5 + 2, //fagc_large_overload_inc_steps *** adi,fagc-adc-large-overload-inc-steps + /* RSSI Control */ + 1, //rssi_delay *** adi,rssi-delay + 1000, //rssi_duration *** adi,rssi-duration + 3, //rssi_restart_mode *** adi,rssi-restart-mode + 0, //rssi_unit_is_rx_samples_enable *** adi,rssi-unit-is-rx-samples-enable + 1, //rssi_wait *** adi,rssi-wait + /* Aux ADC Control */ + 256, //aux_adc_decimation *** adi,aux-adc-decimation + 48000000UL, //aux_adc_rate *** adi,aux-adc-rate + /* AuxDAC Control */ + 1, //aux_dac_manual_mode_enable *** adi,aux-dac-manual-mode-enable + 0, //aux_dac1_default_value_mV *** adi,aux-dac1-default-value-mV + 0, //aux_dac1_active_in_rx_enable *** adi,aux-dac1-active-in-rx-enable + 0, //aux_dac1_active_in_tx_enable *** adi,aux-dac1-active-in-tx-enable + 0, //aux_dac1_active_in_alert_enable *** adi,aux-dac1-active-in-alert-enable + 0, //aux_dac1_rx_delay_us *** adi,aux-dac1-rx-delay-us + 0, //aux_dac1_tx_delay_us *** adi,aux-dac1-tx-delay-us + 0, //aux_dac2_default_value_mV *** adi,aux-dac2-default-value-mV + 0, //aux_dac2_active_in_rx_enable *** adi,aux-dac2-active-in-rx-enable + 0, //aux_dac2_active_in_tx_enable *** adi,aux-dac2-active-in-tx-enable + 0, //aux_dac2_active_in_alert_enable *** adi,aux-dac2-active-in-alert-enable + 0, //aux_dac2_rx_delay_us *** adi,aux-dac2-rx-delay-us + 0, //aux_dac2_tx_delay_us *** adi,aux-dac2-tx-delay-us + /* Temperature Sensor Control */ + 256, //temp_sense_decimation *** adi,temp-sense-decimation + 1000, //temp_sense_measurement_interval_ms *** adi,temp-sense-measurement-interval-ms + 0xCE, //temp_sense_offset_signed *** adi,temp-sense-offset-signed + 1, //temp_sense_periodic_measurement_enable *** adi,temp-sense-periodic-measurement-enable + /* Control Out Setup */ + 0xFF, //ctrl_outs_enable_mask *** adi,ctrl-outs-enable-mask + 0, //ctrl_outs_index *** adi,ctrl-outs-index + /* External LNA Control */ + 0, //elna_settling_delay_ns *** adi,elna-settling-delay-ns + 0, //elna_gain_mdB *** adi,elna-gain-mdB + 0, //elna_bypass_loss_mdB *** adi,elna-bypass-loss-mdB + 0, //elna_rx1_gpo0_control_enable *** adi,elna-rx1-gpo0-control-enable + 0, //elna_rx2_gpo1_control_enable *** adi,elna-rx2-gpo1-control-enable + 0, //elna_gaintable_all_index_enable *** adi,elna-gaintable-all-index-enable + /* Digital Interface Control */ + 0, //digital_interface_tune_skip_mode *** adi,digital-interface-tune-skip-mode + 0, //digital_interface_tune_fir_disable *** adi,digital-interface-tune-fir-disable + 1, //pp_tx_swap_enable *** adi,pp-tx-swap-enable + 1, //pp_rx_swap_enable *** adi,pp-rx-swap-enable + 0, //tx_channel_swap_enable *** adi,tx-channel-swap-enable + 0, //rx_channel_swap_enable *** adi,rx-channel-swap-enable + 1, //rx_frame_pulse_mode_enable *** adi,rx-frame-pulse-mode-enable + 0, //two_t_two_r_timing_enable *** adi,2t2r-timing-enable + 0, //invert_data_bus_enable *** adi,invert-data-bus-enable + 0, //invert_data_clk_enable *** adi,invert-data-clk-enable + 0, //fdd_alt_word_order_enable *** adi,fdd-alt-word-order-enable + 0, //invert_rx_frame_enable *** adi,invert-rx-frame-enable + 0, //fdd_rx_rate_2tx_enable *** adi,fdd-rx-rate-2tx-enable + 0, //swap_ports_enable *** adi,swap-ports-enable + 0, //single_data_rate_enable *** adi,single-data-rate-enable + 1, //lvds_mode_enable *** adi,lvds-mode-enable + 0, //half_duplex_mode_enable *** adi,half-duplex-mode-enable + 0, //single_port_mode_enable *** adi,single-port-mode-enable + 0, //full_port_enable *** adi,full-port-enable + 0, //full_duplex_swap_bits_enable *** adi,full-duplex-swap-bits-enable + 0, //delay_rx_data *** adi,delay-rx-data + 0, //rx_data_clock_delay *** adi,rx-data-clock-delay + 4, //rx_data_delay *** adi,rx-data-delay + 7, //tx_fb_clock_delay *** adi,tx-fb-clock-delay + 0, //tx_data_delay *** adi,tx-data-delay + 150, //lvds_bias_mV *** adi,lvds-bias-mV + 1, //lvds_rx_onchip_termination_enable *** adi,lvds-rx-onchip-termination-enable + 0, //rx1rx2_phase_inversion_en *** adi,rx1-rx2-phase-inversion-enable + 0xFF, //lvds_invert1_control *** adi,lvds-invert1-control + 0x0F, //lvds_invert2_control *** adi,lvds-invert2-control + /* GPO Control */ + 0, //gpo_manual_mode_enable *** adi,gpo-manual-mode-enable + 0, //gpo_manual_mode_enable_mask *** adi,gpo-manual-mode-enable-mask + 0, //gpo0_inactive_state_high_enable *** adi,gpo0-inactive-state-high-enable + 0, //gpo1_inactive_state_high_enable *** adi,gpo1-inactive-state-high-enable + 0, //gpo2_inactive_state_high_enable *** adi,gpo2-inactive-state-high-enable + 0, //gpo3_inactive_state_high_enable *** adi,gpo3-inactive-state-high-enable + 0, //gpo0_slave_rx_enable *** adi,gpo0-slave-rx-enable + 0, //gpo0_slave_tx_enable *** adi,gpo0-slave-tx-enable + 0, //gpo1_slave_rx_enable *** adi,gpo1-slave-rx-enable + 0, //gpo1_slave_tx_enable *** adi,gpo1-slave-tx-enable + 0, //gpo2_slave_rx_enable *** adi,gpo2-slave-rx-enable + 0, //gpo2_slave_tx_enable *** adi,gpo2-slave-tx-enable + 0, //gpo3_slave_rx_enable *** adi,gpo3-slave-rx-enable + 0, //gpo3_slave_tx_enable *** adi,gpo3-slave-tx-enable + 0, //gpo0_rx_delay_us *** adi,gpo0-rx-delay-us + 0, //gpo0_tx_delay_us *** adi,gpo0-tx-delay-us + 0, //gpo1_rx_delay_us *** adi,gpo1-rx-delay-us + 0, //gpo1_tx_delay_us *** adi,gpo1-tx-delay-us + 0, //gpo2_rx_delay_us *** adi,gpo2-rx-delay-us + 0, //gpo2_tx_delay_us *** adi,gpo2-tx-delay-us + 0, //gpo3_rx_delay_us *** adi,gpo3-rx-delay-us + 0, //gpo3_tx_delay_us *** adi,gpo3-tx-delay-us + /* Tx Monitor Control */ + 37000, //low_high_gain_threshold_mdB *** adi,txmon-low-high-thresh + 0, //low_gain_dB *** adi,txmon-low-gain + 24, //high_gain_dB *** adi,txmon-high-gain + 0, //tx_mon_track_en *** adi,txmon-dc-tracking-enable + 0, //one_shot_mode_en *** adi,txmon-one-shot-mode-enable + 511, //tx_mon_delay *** adi,txmon-delay + 8192, //tx_mon_duration *** adi,txmon-duration + 2, //tx1_mon_front_end_gain *** adi,txmon-1-front-end-gain + 2, //tx2_mon_front_end_gain *** adi,txmon-2-front-end-gain + 48, //tx1_mon_lo_cm *** adi,txmon-1-lo-cm + 48, //tx2_mon_lo_cm *** adi,txmon-2-lo-cm + /* GPIO definitions */ + /* Reset_b */ + { + .number = AD9361_1_RESET_B, + .platform_ops = &xil_gpio_ops, + .extra = &xil_gpio_param + }, //gpio_resetb *** reset-gpios + /* MCS Sync */ + { + .number = -1, + .platform_ops = &xil_gpio_ops, + .extra = &xil_gpio_param + }, //gpio_sync *** sync-gpios + /* Cal-SW1 */ + { + .number = -1, + .platform_ops = &xil_gpio_ops, + .extra = &xil_gpio_param + }, //gpio_cal_sw1 *** cal-sw1-gpios + /* Cal-SW2 */ + { + .number = -1, + .platform_ops = &xil_gpio_ops, + .extra = &xil_gpio_param + }, //gpio_cal_sw2 *** cal-sw2-gpios + + { + .device_id = AD9361_SPI_DEVICE_ID, + .mode = SPI_MODE_1, + .chip_select = AD9361_SPI_CS_AD9361_1, + .platform_ops = &spi_eng_platform_ops, + .extra = &spi_engine_param + }, + + /* External LO clocks */ + NULL, //(*ad9361_rfpll_ext_recalc_rate)() + NULL, //(*ad9361_rfpll_ext_round_rate)() + NULL, //(*ad9361_rfpll_ext_set_rate)() +}; + +AD9361_RXFIRConfig rx_fir_config = { // BPF PASSBAND 3/20 fs to 1/4 fs + 3, // rx + 0, // rx_gain + 1, // rx_dec + { + -4, -6, -37, 35, 186, 86, -284, -315, + 107, 219, -4, 271, 558, -307, -1182, -356, + 658, 157, 207, 1648, 790, -2525, -2553, 748, + 865, -476, 3737, 6560, -3583, -14731, -5278, 14819, + 14819, -5278, -14731, -3583, 6560, 3737, -476, 865, + 748, -2553, -2525, 790, 1648, 207, 157, 658, + -356, -1182, -307, 558, 271, -4, 219, 107, + -315, -284, 86, 186, 35, -37, -6, -4, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 + }, // rx_coef[128] + 64, // rx_coef_size + {0, 0, 0, 0, 0, 0}, //rx_path_clks[6] + 0 // rx_bandwidth +}; + +AD9361_TXFIRConfig tx_fir_config = { // BPF PASSBAND 3/20 fs to 1/4 fs + 3, // tx + -6, // tx_gain + 1, // tx_int + { + -4, -6, -37, 35, 186, 86, -284, -315, + 107, 219, -4, 271, 558, -307, -1182, -356, + 658, 157, 207, 1648, 790, -2525, -2553, 748, + 865, -476, 3737, 6560, -3583, -14731, -5278, 14819, + 14819, -5278, -14731, -3583, 6560, 3737, -476, 865, + 748, -2553, -2525, 790, 1648, 207, 157, 658, + -356, -1182, -307, 558, 271, -4, 219, 107, + -315, -284, 86, 186, 35, -37, -6, -4, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 + }, // tx_coef[128] + 64, // tx_coef_size + {0, 0, 0, 0, 0, 0}, // tx_path_clks[6] + 0 // tx_bandwidth +}; + diff --git a/df_datalink/src/dev_profile/ad9361_reg_profile.c b/df_datalink/src/dev_profile/ad9361_reg_profile.c new file mode 100644 index 0000000..ce57c82 --- /dev/null +++ b/df_datalink/src/dev_profile/ad9361_reg_profile.c @@ -0,0 +1,1746 @@ +#include "dev_profile.h" +#include "spi.h" +#include "../config/app_config.h" +#include "../drivers/rf-transceiver/ad9361_reg/ad9361_reg.h" +#include "../drivers/axi_core/spi_engine/spi_engine.h" +#include "../drivers/platform/xilinx_gpio.h" + +#define TIMEOUT_TH AD9361_TIMEOUT_TH + +static struct spi_engine_init_param spi_engine_param = { + .ref_clk_hz = AD9361_SPI_ENGINE_REF_CLK, + .type = SPI_ENGINE, + .spi_engine_baseaddr = AD9361_SPI_ENGINE_BASEADDR, + .cs_delay = AD9361_SPI_ENGINE_CS_DELAY, + .data_width = AD9361_SPI_ENGINE_DATA_WIDTH +}; + +static struct xil_gpio_init_param xil_gpio_param = { + .type = GPIO_PS, + .device_id = AD9361_GPIO_DEVICE_ID +}; + +// ad9361-1 +static struct spi_init_param ad9361_1_reg_spi_init = { + .device_id = AD9361_SPI_DEVICE_ID, + .max_speed_hz = AD9361_SPI_ENGINE_MAX_SPEED, + .mode = SPI_MODE_1, + .chip_select = AD9361_SPI_CS_AD9361_1, + .platform_ops = &spi_eng_platform_ops, + .extra = &spi_engine_param +}; + +static struct gpio_init_param ad9361_1_reg_gpio_resetb_init = { + .number = AD9361_1_RESET_B, + .platform_ops = &xil_gpio_ops, + .extra = &xil_gpio_param +}; +struct ad9361_reg_init_param ad9361_1_reg_default_init_param = { + /* SPI */ + .spi_init = &ad9361_1_reg_spi_init, + .gpio_resetb = &ad9361_1_reg_gpio_resetb_init +}; + +// ad9361-2 +static struct spi_init_param ad9361_2_reg_spi_init = { + .device_id = AD9361_SPI_DEVICE_ID, + .max_speed_hz = AD9361_SPI_ENGINE_MAX_SPEED, + .mode = SPI_MODE_1, + .chip_select = AD9361_SPI_CS_AD9361_2, + .platform_ops = &spi_eng_platform_ops, + .extra = &spi_engine_param +}; + +static struct gpio_init_param ad9361_2_reg_gpio_resetb_init = { + .number = AD9361_2_RESET_B, + .platform_ops = &xil_gpio_ops, + .extra = &xil_gpio_param +}; +struct ad9361_reg_init_param ad9361_2_reg_default_init_param = { + /* SPI */ + .spi_init = &ad9361_2_reg_spi_init, + .gpio_resetb = &ad9361_2_reg_gpio_resetb_init +}; + +uint32_t ad9361_reg_config(struct ad9361_reg_dev *dev){ + int32_t status = 0; + uint8_t value = 0; + int32_t time_out_cnt = 0; + +//************************************************************ +// AD9361 R2 Auto Generated Initialization Script: This script was +// generated using the AD9361 Customer software Version 2.1.3 +//************************************************************ +// Profile: Custom +// REFCLK_IN: 25.000 MHz + + + status = ad9361_reg_write(dev, 0x03DF, 0x01); // Required for proper operation + status = ad9361_reg_write(dev, 0x02A6, 0x0E); // Enable Master Bias + status = ad9361_reg_write(dev, 0x02A8, 0x0E); // Set Bandgap Trim + status = ad9361_reg_write(dev, 0x02AB, 0x07); // Set RF PLL reflclk scale to REFCLK * 2 + status = ad9361_reg_write(dev, 0x02AC, 0xFF); // Set RF PLL reflclk scale to REFCLK * 2 + status = ad9361_reg_write(dev, 0x0009, 0x17); // Enable Clocks + mdelay(20) ;// waits 20 ms + +//************************************************************ +// Set BBPLL Frequency: 1152.000000 +//************************************************************ + status = ad9361_reg_write(dev, 0x0045, 0x03); // Set BBPLL reflclk scale to REFCLK * 2 + status = ad9361_reg_write(dev, 0x0046, 0x03); // Set BBPLL Loop Filter Charge Pump current + status = ad9361_reg_write(dev, 0x0048, 0xE8); // Set BBPLL Loop Filter C1, R1 + status = ad9361_reg_write(dev, 0x0049, 0x5B); // Set BBPLL Loop Filter R2, C2, C1 + status = ad9361_reg_write(dev, 0x004A, 0x35); // Set BBPLL Loop Filter C3,R2 + status = ad9361_reg_write(dev, 0x004B, 0xE0); // Allow calibration to occur and set cal count to 1024 for max accuracy + status = ad9361_reg_write(dev, 0x004E, 0x10); // Set calibration clock to REFCLK/4 for more accuracy + status = ad9361_reg_write(dev, 0x0043, 0x66); // BBPLL Freq Word (Fractional[7:0]) + status = ad9361_reg_write(dev, 0x0042, 0x46); // BBPLL Freq Word (Fractional[15:8]) + status = ad9361_reg_write(dev, 0x0041, 0x01); // BBPLL Freq Word (Fractional[23:16]) + status = ad9361_reg_write(dev, 0x0044, 0x17); // BBPLL Freq Word (Integer[7:0]) + status = ad9361_reg_write(dev, 0x003F, 0x05); // Start BBPLL Calibration + status = ad9361_reg_write(dev, 0x003F, 0x01); // Clear BBPLL start calibration bit + status = ad9361_reg_write(dev, 0x004C, 0x86); // Increase BBPLL KV and phase margin + status = ad9361_reg_write(dev, 0x004D, 0x01); // Increase BBPLL KV and phase margin + status = ad9361_reg_write(dev, 0x004D, 0x05); // Increase BBPLL KV and phase margin + + // Wait for BBPLL to lock, Timeout 2sec, Max BBPLL VCO Cal Time: 276.480 us (Done when 0x05E[7]==1) + time_out_cnt = 0; + do{ + status |= ad9361_reg_read(dev, 0x005E, &value); + mdelay(1);// Wait 1ms + time_out_cnt++; + } while((value & 0x80) != 0x80 && time_out_cnt <= AD9361_TIMEOUT_TH); + + + status = ad9361_reg_write(dev, 0x0002, 0xA4); // Setup Tx Digital Filters/ Channels + status = ad9361_reg_write(dev, 0x0003, 0xE5); // Setup Rx Digital Filters/ Channels + status = ad9361_reg_write(dev, 0x0004, 0x03); // Select Rx input pin(A,B,C)/ Tx out pin (A,B) + status = ad9361_reg_write(dev, 0x000A, 0x12); // Set BBPLL post divide rate + +//************************************************************ +// Program Rx FIR: C:\Users\josh\Desktop\Config\rx64.txt +//************************************************************ + status = ad9361_reg_write(dev, 0x00F5, 0x9A); // Enable clock to Rx FIR Filter + status = ad9361_reg_write(dev, 0x00F6, 0x02); // Write Filter Gain setting + status = ad9361_reg_write(dev, 0x00F0, 0x00); // Write FIR coefficient address + status = ad9361_reg_write(dev, 0x00F1, 0x00); // Write FIR coefficient data[7:0] + status = ad9361_reg_write(dev, 0x00F2, 0x00); // Write FIR coefficient data[15:8] + status = ad9361_reg_write(dev, 0x00F5, 0x9E); // Set Write EN to push data into FIR filter register map + status = ad9361_reg_write(dev, 0x00F4, 0x00); // Dummy Write to Read only register to delay ~1us + status = ad9361_reg_write(dev, 0x00F4, 0x00); // Dummy Write to Read only register to delay ~1us + status = ad9361_reg_write(dev, 0x00F0, 0x01); + status = ad9361_reg_write(dev, 0x00F1, 0xB6); + status = ad9361_reg_write(dev, 0x00F2, 0xFF); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x02); + status = ad9361_reg_write(dev, 0x00F1, 0xA5); + status = ad9361_reg_write(dev, 0x00F2, 0xFF); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x03); + status = ad9361_reg_write(dev, 0x00F1, 0xEA); + status = ad9361_reg_write(dev, 0x00F2, 0xFF); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x04); + status = ad9361_reg_write(dev, 0x00F1, 0x61); + status = ad9361_reg_write(dev, 0x00F2, 0x00); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x05); + status = ad9361_reg_write(dev, 0x00F1, 0xA3); + status = ad9361_reg_write(dev, 0x00F2, 0x00); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x06); + status = ad9361_reg_write(dev, 0x00F1, 0x4D); + status = ad9361_reg_write(dev, 0x00F2, 0x00); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x07); + status = ad9361_reg_write(dev, 0x00F1, 0x77); + status = ad9361_reg_write(dev, 0x00F2, 0xFF); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x08); + status = ad9361_reg_write(dev, 0x00F1, 0xD5); + status = ad9361_reg_write(dev, 0x00F2, 0xFE); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x09); + status = ad9361_reg_write(dev, 0x00F1, 0x38); + status = ad9361_reg_write(dev, 0x00F2, 0xFF); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x0A); + status = ad9361_reg_write(dev, 0x00F1, 0xA5); + status = ad9361_reg_write(dev, 0x00F2, 0x00); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x0B); + status = ad9361_reg_write(dev, 0x00F1, 0xF8); + status = ad9361_reg_write(dev, 0x00F2, 0x01); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x0C); + status = ad9361_reg_write(dev, 0x00F1, 0xAD); + status = ad9361_reg_write(dev, 0x00F2, 0x01); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x0D); + status = ad9361_reg_write(dev, 0x00F1, 0x75); + status = ad9361_reg_write(dev, 0x00F2, 0xFF); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x0E); + status = ad9361_reg_write(dev, 0x00F1, 0xFD); + status = ad9361_reg_write(dev, 0x00F2, 0xFC); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x0F); + status = ad9361_reg_write(dev, 0x00F1, 0xD8); + status = ad9361_reg_write(dev, 0x00F2, 0xFC); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x10); + status = ad9361_reg_write(dev, 0x00F1, 0x00); + status = ad9361_reg_write(dev, 0x00F2, 0x00); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x11); + status = ad9361_reg_write(dev, 0x00F1, 0x3A); + status = ad9361_reg_write(dev, 0x00F2, 0x04); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x12); + status = ad9361_reg_write(dev, 0x00F1, 0x6B); + status = ad9361_reg_write(dev, 0x00F2, 0x05); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x13); + status = ad9361_reg_write(dev, 0x00F1, 0x51); + status = ad9361_reg_write(dev, 0x00F2, 0x01); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x14); + status = ad9361_reg_write(dev, 0x00F1, 0x80); + status = ad9361_reg_write(dev, 0x00F2, 0xFA); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x15); + status = ad9361_reg_write(dev, 0x00F1, 0x34); + status = ad9361_reg_write(dev, 0x00F2, 0xF7); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x16); + status = ad9361_reg_write(dev, 0x00F1, 0x08); + status = ad9361_reg_write(dev, 0x00F2, 0xFC); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x17); + status = ad9361_reg_write(dev, 0x00F1, 0xB2); + status = ad9361_reg_write(dev, 0x00F2, 0x06); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x18); + status = ad9361_reg_write(dev, 0x00F1, 0x1A); + status = ad9361_reg_write(dev, 0x00F2, 0x0E); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x19); + status = ad9361_reg_write(dev, 0x00F1, 0x44); + status = ad9361_reg_write(dev, 0x00F2, 0x09); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x1A); + status = ad9361_reg_write(dev, 0x00F1, 0x54); + status = ad9361_reg_write(dev, 0x00F2, 0xF8); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x1B); + status = ad9361_reg_write(dev, 0x00F1, 0xD1); + status = ad9361_reg_write(dev, 0x00F2, 0xE7); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x1C); + status = ad9361_reg_write(dev, 0x00F1, 0xC2); + status = ad9361_reg_write(dev, 0x00F2, 0xE9); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x1D); + status = ad9361_reg_write(dev, 0x00F1, 0x4F); + status = ad9361_reg_write(dev, 0x00F2, 0x08); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x1E); + status = ad9361_reg_write(dev, 0x00F1, 0xB2); + status = ad9361_reg_write(dev, 0x00F2, 0x3B); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x1F); + status = ad9361_reg_write(dev, 0x00F1, 0x2A); + status = ad9361_reg_write(dev, 0x00F2, 0x6C); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x20); + status = ad9361_reg_write(dev, 0x00F1, 0xFF); + status = ad9361_reg_write(dev, 0x00F2, 0x7F); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x21); + status = ad9361_reg_write(dev, 0x00F1, 0x2A); + status = ad9361_reg_write(dev, 0x00F2, 0x6C); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x22); + status = ad9361_reg_write(dev, 0x00F1, 0xB2); + status = ad9361_reg_write(dev, 0x00F2, 0x3B); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x23); + status = ad9361_reg_write(dev, 0x00F1, 0x4F); + status = ad9361_reg_write(dev, 0x00F2, 0x08); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x24); + status = ad9361_reg_write(dev, 0x00F1, 0xC2); + status = ad9361_reg_write(dev, 0x00F2, 0xE9); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x25); + status = ad9361_reg_write(dev, 0x00F1, 0xD1); + status = ad9361_reg_write(dev, 0x00F2, 0xE7); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x26); + status = ad9361_reg_write(dev, 0x00F1, 0x54); + status = ad9361_reg_write(dev, 0x00F2, 0xF8); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x27); + status = ad9361_reg_write(dev, 0x00F1, 0x44); + status = ad9361_reg_write(dev, 0x00F2, 0x09); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x28); + status = ad9361_reg_write(dev, 0x00F1, 0x1A); + status = ad9361_reg_write(dev, 0x00F2, 0x0E); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x29); + status = ad9361_reg_write(dev, 0x00F1, 0xB2); + status = ad9361_reg_write(dev, 0x00F2, 0x06); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x2A); + status = ad9361_reg_write(dev, 0x00F1, 0x08); + status = ad9361_reg_write(dev, 0x00F2, 0xFC); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x2B); + status = ad9361_reg_write(dev, 0x00F1, 0x34); + status = ad9361_reg_write(dev, 0x00F2, 0xF7); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x2C); + status = ad9361_reg_write(dev, 0x00F1, 0x80); + status = ad9361_reg_write(dev, 0x00F2, 0xFA); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x2D); + status = ad9361_reg_write(dev, 0x00F1, 0x51); + status = ad9361_reg_write(dev, 0x00F2, 0x01); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x2E); + status = ad9361_reg_write(dev, 0x00F1, 0x6B); + status = ad9361_reg_write(dev, 0x00F2, 0x05); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x2F); + status = ad9361_reg_write(dev, 0x00F1, 0x3A); + status = ad9361_reg_write(dev, 0x00F2, 0x04); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x30); + status = ad9361_reg_write(dev, 0x00F1, 0x00); + status = ad9361_reg_write(dev, 0x00F2, 0x00); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x31); + status = ad9361_reg_write(dev, 0x00F1, 0xD8); + status = ad9361_reg_write(dev, 0x00F2, 0xFC); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x32); + status = ad9361_reg_write(dev, 0x00F1, 0xFD); + status = ad9361_reg_write(dev, 0x00F2, 0xFC); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x33); + status = ad9361_reg_write(dev, 0x00F1, 0x75); + status = ad9361_reg_write(dev, 0x00F2, 0xFF); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x34); + status = ad9361_reg_write(dev, 0x00F1, 0xAD); + status = ad9361_reg_write(dev, 0x00F2, 0x01); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x35); + status = ad9361_reg_write(dev, 0x00F1, 0xF8); + status = ad9361_reg_write(dev, 0x00F2, 0x01); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x36); + status = ad9361_reg_write(dev, 0x00F1, 0xA5); + status = ad9361_reg_write(dev, 0x00F2, 0x00); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x37); + status = ad9361_reg_write(dev, 0x00F1, 0x38); + status = ad9361_reg_write(dev, 0x00F2, 0xFF); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x38); + status = ad9361_reg_write(dev, 0x00F1, 0xD5); + status = ad9361_reg_write(dev, 0x00F2, 0xFE); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x39); + status = ad9361_reg_write(dev, 0x00F1, 0x77); + status = ad9361_reg_write(dev, 0x00F2, 0xFF); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x3A); + status = ad9361_reg_write(dev, 0x00F1, 0x4D); + status = ad9361_reg_write(dev, 0x00F2, 0x00); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x3B); + status = ad9361_reg_write(dev, 0x00F1, 0xA3); + status = ad9361_reg_write(dev, 0x00F2, 0x00); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x3C); + status = ad9361_reg_write(dev, 0x00F1, 0x61); + status = ad9361_reg_write(dev, 0x00F2, 0x00); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x3D); + status = ad9361_reg_write(dev, 0x00F1, 0xEA); + status = ad9361_reg_write(dev, 0x00F2, 0xFF); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x3E); + status = ad9361_reg_write(dev, 0x00F1, 0xA5); + status = ad9361_reg_write(dev, 0x00F2, 0xFF); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x3F); + status = ad9361_reg_write(dev, 0x00F1, 0xB6); + status = ad9361_reg_write(dev, 0x00F2, 0xFF); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x40); + status = ad9361_reg_write(dev, 0x00F1, 0x00); + status = ad9361_reg_write(dev, 0x00F2, 0x00); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x41); + status = ad9361_reg_write(dev, 0x00F1, 0x00); + status = ad9361_reg_write(dev, 0x00F2, 0x00); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x42); + status = ad9361_reg_write(dev, 0x00F1, 0x00); + status = ad9361_reg_write(dev, 0x00F2, 0x00); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x43); + status = ad9361_reg_write(dev, 0x00F1, 0x00); + status = ad9361_reg_write(dev, 0x00F2, 0x00); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x44); + status = ad9361_reg_write(dev, 0x00F1, 0x00); + status = ad9361_reg_write(dev, 0x00F2, 0x00); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x45); + status = ad9361_reg_write(dev, 0x00F1, 0x00); + status = ad9361_reg_write(dev, 0x00F2, 0x00); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x46); + status = ad9361_reg_write(dev, 0x00F1, 0x00); + status = ad9361_reg_write(dev, 0x00F2, 0x00); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x47); + status = ad9361_reg_write(dev, 0x00F1, 0x00); + status = ad9361_reg_write(dev, 0x00F2, 0x00); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x48); + status = ad9361_reg_write(dev, 0x00F1, 0x00); + status = ad9361_reg_write(dev, 0x00F2, 0x00); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x49); + status = ad9361_reg_write(dev, 0x00F1, 0x00); + status = ad9361_reg_write(dev, 0x00F2, 0x00); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x4A); + status = ad9361_reg_write(dev, 0x00F1, 0x00); + status = ad9361_reg_write(dev, 0x00F2, 0x00); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x4B); + status = ad9361_reg_write(dev, 0x00F1, 0x00); + status = ad9361_reg_write(dev, 0x00F2, 0x00); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x4C); + status = ad9361_reg_write(dev, 0x00F1, 0x00); + status = ad9361_reg_write(dev, 0x00F2, 0x00); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x4D); + status = ad9361_reg_write(dev, 0x00F1, 0x00); + status = ad9361_reg_write(dev, 0x00F2, 0x00); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x4E); + status = ad9361_reg_write(dev, 0x00F1, 0x00); + status = ad9361_reg_write(dev, 0x00F2, 0x00); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x4F); + status = ad9361_reg_write(dev, 0x00F1, 0x00); + status = ad9361_reg_write(dev, 0x00F2, 0x00); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F5, 0x98); // Disable clock to Rx Filter + +//************************************************************ +// Setup the Parallel Port (Digital Data Interface) +//************************************************************ + status = ad9361_reg_write(dev, 0x0010, 0xC8); // I/O Config. Tx Swap IQ; Rx Swap IQ; Tx CH Swap, Rx CH Swap; Rx Frame Mode; 2R2T bit; Invert data bus; Invert DATA_CLK + status = ad9361_reg_write(dev, 0x0011, 0x00); // I/O Config. Alt Word Order; -Rx1; -Rx2; -Tx1; -Tx2; Invert Rx Frame; Delay Rx Data + status = ad9361_reg_write(dev, 0x0012, 0x02); // I/O Config. Rx=2*Tx; Swap Ports; SDR; LVDS; Half Duplex; Single Port; Full Port; Swap Bits + status = ad9361_reg_write(dev, 0x0006, 0x00); // PPORT Rx Delay (adjusts Tco Dataclk->Data) + status = ad9361_reg_write(dev, 0x0007, 0x0F); // PPORT TX Delay (adjusts setup/hold FBCLK->Data) + +//************************************************************ +// Setup AuxDAC +//************************************************************ + status = ad9361_reg_write(dev, 0x0018, 0x00); // AuxDAC1 Word[9:2] + status = ad9361_reg_write(dev, 0x0019, 0x00); // AuxDAC2 Word[9:2] + status = ad9361_reg_write(dev, 0x001A, 0x00); // AuxDAC1 Config and Word[1:0] + status = ad9361_reg_write(dev, 0x001B, 0x00); // AuxDAC2 Config and Word[1:0] + status = ad9361_reg_write(dev, 0x0023, 0xFF); // AuxDAC Manaul/Auto Control + status = ad9361_reg_write(dev, 0x0026, 0x00); // AuxDAC Manual Select Bit/GPO Manual Select + status = ad9361_reg_write(dev, 0x0030, 0x00); // AuxDAC1 Rx Delay + status = ad9361_reg_write(dev, 0x0031, 0x00); // AuxDAC1 Tx Delay + status = ad9361_reg_write(dev, 0x0032, 0x00); // AuxDAC2 Rx Delay + status = ad9361_reg_write(dev, 0x0033, 0x00); // AuxDAC2 Tx Delay + +//************************************************************ +// Setup AuxADC +//************************************************************ + status = ad9361_reg_write(dev, 0x000B, 0x00); // Temp Sensor Setup (Offset) + status = ad9361_reg_write(dev, 0x000C, 0x00); // Temp Sensor Setup (Temp Window) + status = ad9361_reg_write(dev, 0x000D, 0x03); // Temp Sensor Setup (Periodic Measure) + status = ad9361_reg_write(dev, 0x000F, 0x04); // Temp Sensor Setup (Decimation) + status = ad9361_reg_write(dev, 0x001C, 0x00); // AuxADC Setup (Clock Div) + status = ad9361_reg_write(dev, 0x001D, 0x01); // AuxADC Setup (Decimation/Enable) + +//************************************************************ +// Setup Control Outs +//************************************************************ + status = ad9361_reg_write(dev, 0x0035, 0x00); // Ctrl Out index + status = ad9361_reg_write(dev, 0x0036, 0xFF); // Ctrl Out [7:0] output enable + +//************************************************************ +// Setup GPO +//************************************************************ + status = ad9361_reg_write(dev, 0x003A, 0x18); // Set number of REFCLK cycles for 1us delay timer + status = ad9361_reg_write(dev, 0x0020, 0x00); // GPO Auto Enable Setup in RX and TX + status = ad9361_reg_write(dev, 0x0027, 0x00); // GPO Manual and GPO auto value in ALERT + status = ad9361_reg_write(dev, 0x0028, 0x00); // GPO_0 RX Delay + status = ad9361_reg_write(dev, 0x0029, 0x00); // GPO_1 RX Delay + status = ad9361_reg_write(dev, 0x002A, 0x00); // GPO_2 RX Delay + status = ad9361_reg_write(dev, 0x002B, 0x00); // GPO_3 RX Delay + status = ad9361_reg_write(dev, 0x002C, 0x00); // GPO_0 TX Delay + status = ad9361_reg_write(dev, 0x002D, 0x00); // GPO_1 TX Delay + status = ad9361_reg_write(dev, 0x002E, 0x00); // GPO_2 TX Delay + status = ad9361_reg_write(dev, 0x002F, 0x00); // GPO_3 TX Delay + +//************************************************************ +// Setup RF PLL non-frequency-dependent registers +//************************************************************ + status = ad9361_reg_write(dev, 0x0261, 0x00); // Set Rx LO Power mode + status = ad9361_reg_write(dev, 0x02A1, 0x00); // Set Tx LO Power mode + status = ad9361_reg_write(dev, 0x0248, 0x0B); // Enable Rx VCO LDO + status = ad9361_reg_write(dev, 0x0288, 0x0B); // Enable Tx VCO LDO + status = ad9361_reg_write(dev, 0x0246, 0x02); // Set VCO Power down TCF bits + status = ad9361_reg_write(dev, 0x0286, 0x02); // Set VCO Power down TCF bits + status = ad9361_reg_write(dev, 0x0249, 0x8E); // Set VCO cal length + status = ad9361_reg_write(dev, 0x0289, 0x8E); // Set VCO cal length + status = ad9361_reg_write(dev, 0x023B, 0x80); // Enable Rx VCO cal + status = ad9361_reg_write(dev, 0x027B, 0x80); // Enable Tx VCO cal + status = ad9361_reg_write(dev, 0x0243, 0x0D); // Set Rx prescaler bias + status = ad9361_reg_write(dev, 0x0283, 0x0D); // Set Tx prescaler bias + status = ad9361_reg_write(dev, 0x023D, 0x00); // Clear Half VCO cal clock setting + status = ad9361_reg_write(dev, 0x027D, 0x00); // Clear Half VCO cal clock setting + + status = ad9361_reg_write(dev, 0x0015, 0x0C); // Set Dual Synth mode bit + status = ad9361_reg_write(dev, 0x0014, 0x1D); // Set Force ALERT State bit + status = ad9361_reg_write(dev, 0x0013, 0x01); // Set ENSM FDD mode + mdelay(1); // waits 1 ms + + status = ad9361_reg_write(dev, 0x023D, 0x04); // Start RX CP cal + + // Wait for CP cal to complete, Max RXCP Cal time: 737.280 (us)(Done when 0x244[7]==1) + time_out_cnt = 0; + do{ + status |= ad9361_reg_read(dev, 0x0244, &value); + mdelay(1);// Wait 1ms + time_out_cnt++; + } while((value & 0x80) != 0x80 && time_out_cnt <= AD9361_TIMEOUT_TH); + + status = ad9361_reg_write(dev, 0x027D, 0x04); // Start TX CP cal + + // Wait for CP cal to complete, Max TXCP Cal time: 737.280 (us)(Done when 0x284[7]==1) + time_out_cnt = 0; + do{ + status |= ad9361_reg_read(dev, 0x0284, &value); + mdelay(1);// Wait 1ms + time_out_cnt++; + } while((value & 0x80) != 0x80 && time_out_cnt <= AD9361_TIMEOUT_TH); + + status = ad9361_reg_write(dev, 0x023D, 0x00); // Disable RX CP Calibration since the CP Cal start bit is not self-clearing. Only important if the script is run again without restting the DUT + status = ad9361_reg_write(dev, 0x027D, 0x00); // Disable TX CP Calibration since the CP Cal start bit is not self-clearing. Only important if the script is run again without restting the DUT +//************************************************************ +// FDD RX,TX Synth Frequency: 125.000000,4125.000000 MHz +//************************************************************ +//************************************************************ +// Setup Rx Frequency-Dependent Syntheisizer Registers +//************************************************************ + status = ad9361_reg_write(dev, 0x023A, 0x4A); // Set VCO Output level[3:0] + status = ad9361_reg_write(dev, 0x0239, 0xC1); // Set Init ALC Value[3:0] and VCO Varactor[3:0] + status = ad9361_reg_write(dev, 0x0242, 0x0E); // Set VCO Bias Tcf[1:0] and VCO Bias Ref[2:0] + status = ad9361_reg_write(dev, 0x0238, 0x78); // Set VCO Cal Offset[3:0] + status = ad9361_reg_write(dev, 0x0245, 0x00); // Set VCO Cal Ref Tcf[2:0] + status = ad9361_reg_write(dev, 0x0251, 0x0B); // Set VCO Varactor Reference[3:0] + status = ad9361_reg_write(dev, 0x0250, 0x70); // Set VCO Varactor Ref Tcf[2:0] and VCO Varactor Offset[3:0] + status = ad9361_reg_write(dev, 0x023B, 0x94); // Set Synth Loop Filter charge pump current (Icp) + status = ad9361_reg_write(dev, 0x023E, 0xF4); // Set Synth Loop Filter C2 and C1 + status = ad9361_reg_write(dev, 0x023F, 0xDF); // Set Synth Loop Filter R1 and C3 + status = ad9361_reg_write(dev, 0x0240, 0x0A); // Set Synth Loop Filter R3 + +//************************************************************ +// Setup Tx Frequency-Dependent Syntheisizer Registers +//************************************************************ + status = ad9361_reg_write(dev, 0x027A, 0x4A); // Set VCO Output level[3:0] + status = ad9361_reg_write(dev, 0x0279, 0xC1); // Set Init ALC Value[3:0] and VCO Varactor[3:0] + status = ad9361_reg_write(dev, 0x0282, 0x0E); // Set VCO Bias Tcf[1:0] and VCO Bias Ref[2:0] + status = ad9361_reg_write(dev, 0x0278, 0x78); // Set VCO Cal Offset[3:0] + status = ad9361_reg_write(dev, 0x0285, 0x00); // Set VCO Cal Ref Tcf[2:0] + status = ad9361_reg_write(dev, 0x0291, 0x0B); // Set VCO Varactor Reference[3:0] + status = ad9361_reg_write(dev, 0x0290, 0x70); // Set VCO Varactor Ref Tcf[2:0] and VCO Varactor Offset[3:0] + status = ad9361_reg_write(dev, 0x027B, 0x93); // Set Synth Loop Filter charge pump current (Icp) + status = ad9361_reg_write(dev, 0x027E, 0xF4); // Set Synth Loop Filter C2 and C1 + status = ad9361_reg_write(dev, 0x027F, 0xDF); // Set Synth Loop Filter R1 and C3 + status = ad9361_reg_write(dev, 0x0280, 0x0A); // Set Synth Loop Filter R3 + +//************************************************************ +// Write Rx and Tx Frequency Words +//************************************************************ + status = ad9361_reg_write(dev, 0x0233, 0x00); // Write Rx Synth Fractional Freq Word[7:0] + status = ad9361_reg_write(dev, 0x0234, 0x00); // Write Rx Synth Fractional Freq Word[15:8] + status = ad9361_reg_write(dev, 0x0235, 0x00); // Write Rx Synth Fractional Freq Word[22:16] + status = ad9361_reg_write(dev, 0x0232, 0x00); // Write Rx Synth Integer Freq Word[10:8] + status = ad9361_reg_write(dev, 0x0231, 0xA0); // Write Rx Synth Integer Freq Word[7:0] + status = ad9361_reg_write(dev, 0x0005, 0x05); // Set LO divider setting + status = ad9361_reg_write(dev, 0x0273, 0x00); // Write Tx Synth Fractional Freq Word[7:0] + status = ad9361_reg_write(dev, 0x0274, 0x00); // Write Tx Synth Fractional Freq Word[15:8] + status = ad9361_reg_write(dev, 0x0275, 0x00); // Write Tx Synth Fractional Freq Word[22:16] + status = ad9361_reg_write(dev, 0x0272, 0x00); // Write Tx Synth Integer Freq Word[10:8] + status = ad9361_reg_write(dev, 0x0271, 0xA5); // Write Tx Synth Integer Freq Word[7:0] (starts VCO cal) + status = ad9361_reg_write(dev, 0x0005, 0x05); // Set LO divider setting + +//************************************************************ +// Program Mixer GM Sub-table +//************************************************************ + status = ad9361_reg_write(dev, 0x013F, 0x02); // Start Clock + status = ad9361_reg_write(dev, 0x0138, 0x0F); // Addr Table Index + status = ad9361_reg_write(dev, 0x0139, 0x78); // Gain + status = ad9361_reg_write(dev, 0x013A, 0x00); // Bias + status = ad9361_reg_write(dev, 0x013B, 0x00); // GM + status = ad9361_reg_write(dev, 0x013F, 0x06); // Write Words + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay for 3 ADCCLK/16 clock cycles (Dummy Write) + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay ~1us (Dummy Write) + status = ad9361_reg_write(dev, 0x0138, 0x0E); // Addr Table Index + status = ad9361_reg_write(dev, 0x0139, 0x74); // Gain + status = ad9361_reg_write(dev, 0x013A, 0x00); // Bias + status = ad9361_reg_write(dev, 0x013B, 0x0D); // GM + status = ad9361_reg_write(dev, 0x013F, 0x06); // Write Words + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay for 3 ADCCLK/16 clock cycles (Dummy Write) + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay ~1us (Dummy Write) + status = ad9361_reg_write(dev, 0x0138, 0x0D); // Addr Table Index + status = ad9361_reg_write(dev, 0x0139, 0x70); // Gain + status = ad9361_reg_write(dev, 0x013A, 0x00); // Bias + status = ad9361_reg_write(dev, 0x013B, 0x15); // GM + status = ad9361_reg_write(dev, 0x013F, 0x06); // Write Words + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay for 3 ADCCLK/16 clock cycles (Dummy Write) + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay ~1us (Dummy Write) + status = ad9361_reg_write(dev, 0x0138, 0x0C); // Addr Table Index + status = ad9361_reg_write(dev, 0x0139, 0x6C); // Gain + status = ad9361_reg_write(dev, 0x013A, 0x00); // Bias + status = ad9361_reg_write(dev, 0x013B, 0x1B); // GM + status = ad9361_reg_write(dev, 0x013F, 0x06); // Write Words + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay for 3 ADCCLK/16 clock cycles (Dummy Write) + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay ~1us (Dummy Write) + status = ad9361_reg_write(dev, 0x0138, 0x0B); // Addr Table Index + status = ad9361_reg_write(dev, 0x0139, 0x68); // Gain + status = ad9361_reg_write(dev, 0x013A, 0x00); // Bias + status = ad9361_reg_write(dev, 0x013B, 0x21); // GM + status = ad9361_reg_write(dev, 0x013F, 0x06); // Write Words + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay for 3 ADCCLK/16 clock cycles (Dummy Write) + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay ~1us (Dummy Write) + status = ad9361_reg_write(dev, 0x0138, 0x0A); // Addr Table Index + status = ad9361_reg_write(dev, 0x0139, 0x64); // Gain + status = ad9361_reg_write(dev, 0x013A, 0x00); // Bias + status = ad9361_reg_write(dev, 0x013B, 0x25); // GM + status = ad9361_reg_write(dev, 0x013F, 0x06); // Write Words + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay for 3 ADCCLK/16 clock cycles (Dummy Write) + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay ~1us (Dummy Write) + status = ad9361_reg_write(dev, 0x0138, 0x09); // Addr Table Index + status = ad9361_reg_write(dev, 0x0139, 0x60); // Gain + status = ad9361_reg_write(dev, 0x013A, 0x00); // Bias + status = ad9361_reg_write(dev, 0x013B, 0x29); // GM + status = ad9361_reg_write(dev, 0x013F, 0x06); // Write Words + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay for 3 ADCCLK/16 clock cycles (Dummy Write) + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay ~1us (Dummy Write) + status = ad9361_reg_write(dev, 0x0138, 0x08); // Addr Table Index + status = ad9361_reg_write(dev, 0x0139, 0x5C); // Gain + status = ad9361_reg_write(dev, 0x013A, 0x00); // Bias + status = ad9361_reg_write(dev, 0x013B, 0x2C); // GM + status = ad9361_reg_write(dev, 0x013F, 0x06); // Write Words + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay for 3 ADCCLK/16 clock cycles (Dummy Write) + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay ~1us (Dummy Write) + status = ad9361_reg_write(dev, 0x0138, 0x07); // Addr Table Index + status = ad9361_reg_write(dev, 0x0139, 0x58); // Gain + status = ad9361_reg_write(dev, 0x013A, 0x00); // Bias + status = ad9361_reg_write(dev, 0x013B, 0x2F); // GM + status = ad9361_reg_write(dev, 0x013F, 0x06); // Write Words + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay for 3 ADCCLK/16 clock cycles (Dummy Write) + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay ~1us (Dummy Write) + status = ad9361_reg_write(dev, 0x0138, 0x06); // Addr Table Index + status = ad9361_reg_write(dev, 0x0139, 0x54); // Gain + status = ad9361_reg_write(dev, 0x013A, 0x00); // Bias + status = ad9361_reg_write(dev, 0x013B, 0x31); // GM + status = ad9361_reg_write(dev, 0x013F, 0x06); // Write Words + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay for 3 ADCCLK/16 clock cycles (Dummy Write) + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay ~1us (Dummy Write) + status = ad9361_reg_write(dev, 0x0138, 0x05); // Addr Table Index + status = ad9361_reg_write(dev, 0x0139, 0x50); // Gain + status = ad9361_reg_write(dev, 0x013A, 0x00); // Bias + status = ad9361_reg_write(dev, 0x013B, 0x33); // GM + status = ad9361_reg_write(dev, 0x013F, 0x06); // Write Words + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay for 3 ADCCLK/16 clock cycles (Dummy Write) + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay ~1us (Dummy Write) + status = ad9361_reg_write(dev, 0x0138, 0x04); // Addr Table Index + status = ad9361_reg_write(dev, 0x0139, 0x4C); // Gain + status = ad9361_reg_write(dev, 0x013A, 0x00); // Bias + status = ad9361_reg_write(dev, 0x013B, 0x34); // GM + status = ad9361_reg_write(dev, 0x013F, 0x06); // Write Words + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay for 3 ADCCLK/16 clock cycles (Dummy Write) + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay ~1us (Dummy Write) + status = ad9361_reg_write(dev, 0x0138, 0x03); // Addr Table Index + status = ad9361_reg_write(dev, 0x0139, 0x48); // Gain + status = ad9361_reg_write(dev, 0x013A, 0x00); // Bias + status = ad9361_reg_write(dev, 0x013B, 0x35); // GM + status = ad9361_reg_write(dev, 0x013F, 0x06); // Write Words + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay for 3 ADCCLK/16 clock cycles (Dummy Write) + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay ~1us (Dummy Write) + status = ad9361_reg_write(dev, 0x0138, 0x02); // Addr Table Index + status = ad9361_reg_write(dev, 0x0139, 0x30); // Gain + status = ad9361_reg_write(dev, 0x013A, 0x00); // Bias + status = ad9361_reg_write(dev, 0x013B, 0x3A); // GM + status = ad9361_reg_write(dev, 0x013F, 0x06); // Write Words + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay for 3 ADCCLK/16 clock cycles (Dummy Write) + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay ~1us (Dummy Write) + status = ad9361_reg_write(dev, 0x0138, 0x01); // Addr Table Index + status = ad9361_reg_write(dev, 0x0139, 0x18); // Gain + status = ad9361_reg_write(dev, 0x013A, 0x00); // Bias + status = ad9361_reg_write(dev, 0x013B, 0x3D); // GM + status = ad9361_reg_write(dev, 0x013F, 0x06); // Write Words + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay for 3 ADCCLK/16 clock cycles (Dummy Write) + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay ~1us (Dummy Write) + status = ad9361_reg_write(dev, 0x0138, 0x00); // Addr Table Index + status = ad9361_reg_write(dev, 0x0139, 0x00); // Gain + status = ad9361_reg_write(dev, 0x013A, 0x00); // Bias + status = ad9361_reg_write(dev, 0x013B, 0x3E); // GM + status = ad9361_reg_write(dev, 0x013F, 0x06); // Write Words + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay for 3 ADCCLK/16 clock cycles (Dummy Write) + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay ~1us (Dummy Write) + status = ad9361_reg_write(dev, 0x013F, 0x02); // Clear Write Bit + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay for 3 ADCCLK/16 clock cycles (Dummy Write) + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay ~1us (Dummy Write) + status = ad9361_reg_write(dev, 0x013F, 0x00); // Stop Clock + +//************************************************************ +// Program Rx Gain Tables with GainTable800MHz.csv +//************************************************************ + + status = ad9361_reg_write(dev, 0x0137, 0x1A); // Start Gain Table Clock + status = ad9361_reg_write(dev, 0x0130, 0x00); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x00); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x01); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x00); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x02); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x00); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x03); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x01); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x04); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x02); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x05); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x03); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x06); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x04); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x07); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x05); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x08); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x01); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x03); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x09); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x01); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x04); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x0A); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x01); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x05); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x0B); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x01); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x06); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x0C); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x01); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x07); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x0D); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x01); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x08); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x0E); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x01); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x09); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x0F); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x01); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x0A); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x10); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x01); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x0B); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x11); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x01); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x0C); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x12); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x01); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x0D); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x13); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x01); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x0E); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x14); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x02); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x09); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x15); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x02); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x0A); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x16); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x02); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x0B); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x17); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x02); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x0C); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x18); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x02); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x0D); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x19); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x02); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x0E); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x1A); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x02); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x0F); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x1B); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x02); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x10); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x1C); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x02); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x2B); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x1D); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x02); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x2C); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x1E); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x04); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x28); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x1F); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x04); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x29); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x20); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x04); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x2A); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x21); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x04); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x2B); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x22); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x24); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x20); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x23); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x24); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x21); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x24); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x20); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x25); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x21); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x26); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x22); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x27); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x23); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x28); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x24); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x29); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x25); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x2A); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x26); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x2B); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x27); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x2C); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x28); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x2D); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x29); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x2E); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x2A); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x2F); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x2B); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x30); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x2C); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x31); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x2D); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x32); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x2E); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x33); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x2F); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x34); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x30); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x35); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x31); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x36); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x32); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x37); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x64); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x2E); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x38); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x64); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x2F); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x39); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x64); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x30); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x3A); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x64); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x31); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x3B); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x64); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x32); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x3C); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x64); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x33); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x3D); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x64); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x34); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x3E); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x64); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x35); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x3F); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x64); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x36); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x40); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x64); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x37); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x41); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x64); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x38); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x42); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x65); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x38); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x43); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x66); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x38); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x44); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x67); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x38); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x45); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x68); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x38); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x46); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x69); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x38); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x47); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x6A); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x38); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x48); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x6B); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x38); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x49); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x6C); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x38); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x4A); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x6D); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x38); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x4B); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x6E); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x38); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x4C); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x6F); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x38); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x4D); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x00); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x4E); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x00); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x4F); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x00); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x50); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x00); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x51); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x00); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x52); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x00); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x53); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x00); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x54); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x00); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x55); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x00); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x56); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x00); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x57); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x00); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x58); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x00); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x59); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x00); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x5A); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x00); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0137, 0x1A); // Clear Write Bit + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0137, 0x00); // Stop Gain Table Clock +//************************************************************ +// Setup Rx Manual Gain Registers +//************************************************************ + status = ad9361_reg_write(dev, 0x00FA, 0xE0); // Gain Control Mode Select + status = ad9361_reg_write(dev, 0x00FB, 0x08); // Table, Digital Gain, Man Gain Ctrl + status = ad9361_reg_write(dev, 0x00FC, 0x23); // Incr Step Size, ADC Overrange Size + status = ad9361_reg_write(dev, 0x00FD, 0x4C); // Max Full/LMT Gain Table Index + status = ad9361_reg_write(dev, 0x00FE, 0x44); // Decr Step Size, Peak Overload Time + status = ad9361_reg_write(dev, 0x0100, 0x6F); // Max Digital Gain + status = ad9361_reg_write(dev, 0x0104, 0x2F); // ADC Small Overload Threshold + status = ad9361_reg_write(dev, 0x0105, 0x3A); // ADC Large Overload Threshold + status = ad9361_reg_write(dev, 0x0107, 0x2B); // Small LMT Overload Threshold + status = ad9361_reg_write(dev, 0x0108, 0x31); // Large LMT Overload Threshold + status = ad9361_reg_write(dev, 0x0109, 0x00); // Rx1 Full/LMT Gain Index + status = ad9361_reg_write(dev, 0x010A, 0x58); // Rx1 LPF Gain Index + status = ad9361_reg_write(dev, 0x010B, 0x00); // Rx1 Digital Gain Index + status = ad9361_reg_write(dev, 0x010C, 0x00); // Rx2 Full/LMT Gain Index + status = ad9361_reg_write(dev, 0x010D, 0x18); // Rx2 LPF Gain Index + status = ad9361_reg_write(dev, 0x010E, 0x00); // Rx2 Digital Gain Index + status = ad9361_reg_write(dev, 0x0114, 0x30); // Low Power Threshold + status = ad9361_reg_write(dev, 0x011A, 0x27); // Initial LMT Gain Limit + status = ad9361_reg_write(dev, 0x0081, 0x00); // Tx Symbol Gain Control +//************************************************************ +// RX Baseband Filter Tuning (Real BW: 7.500000 MHz) 3dB Filter +// Corner @ 10.500000 MHz) +//************************************************************ + status = ad9361_reg_write(dev, 0x01FB, 0x07); // RX Freq Corner (MHz) + status = ad9361_reg_write(dev, 0x01FC, 0x40); // RX Freq Corner (Khz) + status = ad9361_reg_write(dev, 0x01F8, 0x0D); // Rx BBF Tune Divider[7:0] + status = ad9361_reg_write(dev, 0x01F9, 0x1E); // RX BBF Tune Divider[8] + + status = ad9361_reg_write(dev, 0x01D5, 0x3F); // Set Rx Mix LO CM + status = ad9361_reg_write(dev, 0x01C0, 0x03); // Set GM common mode + status = ad9361_reg_write(dev, 0x01E2, 0x02); // Enable Rx1 Filter Tuner + status = ad9361_reg_write(dev, 0x01E3, 0x02); // Enable Rx2 Filter Tuner + status = ad9361_reg_write(dev, 0x0016, 0x80); // Start RX Filter Tune + + // Wait for RX filter to tune, Max Cal Time: 6.884 us (Done when 0x016[7]==0) + time_out_cnt = 0; + do{ + status |= ad9361_reg_read(dev, 0x0016, &value); + mdelay(1);// Wait 1ms + time_out_cnt++; + } while((value & 0x80) != 0x00 && time_out_cnt <= AD9361_TIMEOUT_TH); + + status = ad9361_reg_write(dev, 0x01E2, 0x03); // Disable Rx Filter Tuner (Rx1) + status = ad9361_reg_write(dev, 0x01E3, 0x03); // Disable Rx Filter Tuner (Rx2) +//************************************************************ +// TX Baseband Filter Tuning (Real BW: 7.500000 MHz) 3dB Filter +// Corner @ 12.000000 MHz) +//************************************************************ + status = ad9361_reg_write(dev, 0x00D6, 0x0B); // TX BBF Tune Divider[7:0] + status = ad9361_reg_write(dev, 0x00D7, 0x1E); // TX BBF Tune Divider[8] + + status = ad9361_reg_write(dev, 0x00CA, 0x22); // Enable Tx Filter Tuner + status = ad9361_reg_write(dev, 0x0016, 0x40); // Start Tx Filter Tune + + // Wait for TX filter to tune, Max Cal Time: 3.390 us (Done when 0x016[6]==0) + time_out_cnt = 0; + do{ + status |= ad9361_reg_read(dev, 0x0016, &value); + mdelay(1);// Wait 1ms + time_out_cnt++; + } while((value & 0x40) != 0x00 && time_out_cnt <= AD9361_TIMEOUT_TH); + + status = ad9361_reg_write(dev, 0x00CA, 0x26); // Disable Tx Filter Tuner (Both Channels) +//************************************************************ +// RX TIA Setup: Setup values scale based on RxBBF calibration +// results. See information in Calibration Guide. +//************************************************************ + status = ad9361_reg_write(dev, 0x01DB, 0x60); // Set TIA selcc[2:0] + status = ad9361_reg_write(dev, 0x01DD, 0x00); // Set RX TIA1 C MSB[6:0] + status = ad9361_reg_write(dev, 0x01DF, 0x00); // Set RX TIA2 C MSB[6:0] + status = ad9361_reg_write(dev, 0x01DC, 0x72); // Set RX TIA1 C LSB[5:0] + status = ad9361_reg_write(dev, 0x01DE, 0x72); // Set RX TIA2 C LSB[5:0] + +//************************************************************ +// TX Secondary Filter Calibration Setup: Real Bandwidth +// 7.500000MHz, 3dB Corner @ 37.500000MHz +//************************************************************ + status = ad9361_reg_write(dev, 0x00D2, 0x1E); // TX Secondary Filter PDF Cap cal[5:0] + status = ad9361_reg_write(dev, 0x00D1, 0x0C); // TX Secondary Filter PDF Res cal[3:0] + status = ad9361_reg_write(dev, 0x00D0, 0x56); // Pdampbias + +//************************************************************ +// ADC Setup: Tune ADC Performance based on RX analog filter tune +// corner. Real Bandwidth: 6.982753 MHz, ADC Clock Frequency: +// 288.000000 MHz. The values in registers 0x200 - 0x227 need to be +// calculated using the equations in the Calibration Guide. +//************************************************************ + + status = ad9361_reg_write(dev, 0x0200, 0x00); + status = ad9361_reg_write(dev, 0x0201, 0x00); + status = ad9361_reg_write(dev, 0x0202, 0x00); + status = ad9361_reg_write(dev, 0x0203, 0x24); + status = ad9361_reg_write(dev, 0x0204, 0x24); + status = ad9361_reg_write(dev, 0x0205, 0x00); + status = ad9361_reg_write(dev, 0x0206, 0x00); + status = ad9361_reg_write(dev, 0x0207, 0x7C); + status = ad9361_reg_write(dev, 0x0208, 0x46); + status = ad9361_reg_write(dev, 0x0209, 0x3C); + status = ad9361_reg_write(dev, 0x020A, 0x4C); + status = ad9361_reg_write(dev, 0x020B, 0x2C); + status = ad9361_reg_write(dev, 0x020C, 0x4F); + status = ad9361_reg_write(dev, 0x020D, 0x2A); + status = ad9361_reg_write(dev, 0x020E, 0x00); + status = ad9361_reg_write(dev, 0x020F, 0x7F); + status = ad9361_reg_write(dev, 0x0210, 0x7F); + status = ad9361_reg_write(dev, 0x0211, 0x7F); + status = ad9361_reg_write(dev, 0x0212, 0x4A); + status = ad9361_reg_write(dev, 0x0213, 0x4A); + status = ad9361_reg_write(dev, 0x0214, 0x4A); + status = ad9361_reg_write(dev, 0x0215, 0x4D); + status = ad9361_reg_write(dev, 0x0216, 0x4D); + status = ad9361_reg_write(dev, 0x0217, 0x4D); + status = ad9361_reg_write(dev, 0x0218, 0x2E); + status = ad9361_reg_write(dev, 0x0219, 0x9C); + status = ad9361_reg_write(dev, 0x021A, 0x1F); + status = ad9361_reg_write(dev, 0x021B, 0x15); + status = ad9361_reg_write(dev, 0x021C, 0x9C); + status = ad9361_reg_write(dev, 0x021D, 0x1F); + status = ad9361_reg_write(dev, 0x021E, 0x15); + status = ad9361_reg_write(dev, 0x021F, 0x9C); + status = ad9361_reg_write(dev, 0x0220, 0x1F); + status = ad9361_reg_write(dev, 0x0221, 0x2A); + status = ad9361_reg_write(dev, 0x0222, 0x2A); + status = ad9361_reg_write(dev, 0x0223, 0x40); + status = ad9361_reg_write(dev, 0x0224, 0x40); + status = ad9361_reg_write(dev, 0x0225, 0x2C); + status = ad9361_reg_write(dev, 0x0226, 0x00); + status = ad9361_reg_write(dev, 0x0227, 0x00); +//************************************************************ +// Setup and Run BB DC and RF DC Offset Calibrations +//************************************************************ + status = ad9361_reg_write(dev, 0x0193, 0x3F); + status = ad9361_reg_write(dev, 0x0190, 0x0F); // Set BBDC tracking shift M value, only applies when BB DC tracking enabled + status = ad9361_reg_write(dev, 0x0194, 0x01); // BBDC Cal setting + status = ad9361_reg_write(dev, 0x0016, 0x01); // Start BBDC offset cal + + // BBDC Max Cal Time: 8416.667 us. Cal done when 0x016[0]==0 + time_out_cnt = 0; + do{ + status |= ad9361_reg_read(dev, 0x0016, &value); + mdelay(1);// Wait 1ms + time_out_cnt++; + } while((value & 0x01) != 0x00 && time_out_cnt <= AD9361_TIMEOUT_TH); + + status = ad9361_reg_write(dev, 0x0185, 0x20); // Set RF DC offset Wait Count + status = ad9361_reg_write(dev, 0x0186, 0x32); // Set RF DC Offset Count[7:0] + status = ad9361_reg_write(dev, 0x0187, 0x24); // Settings for RF DC cal + status = ad9361_reg_write(dev, 0x018B, 0x83); // Settings for RF DC cal + status = ad9361_reg_write(dev, 0x0188, 0x05); // Settings for RF DC cal + status = ad9361_reg_write(dev, 0x0189, 0x30); // Settings for RF DC cal + status = ad9361_reg_write(dev, 0x0016, 0x02); // Start RFDC offset cal + + // RFDC Max Cal Time: 114511.250 us + time_out_cnt = 0; + do{ + status |= ad9361_reg_read(dev, 0x0016, &value); + mdelay(1);// Wait 1ms + time_out_cnt++; + } while((value & 0x01) != 0x00 && time_out_cnt <= AD9361_TIMEOUT_TH); + +//************************************************************ +// Tx Quadrature Calibration Settings +//************************************************************ + status = ad9361_reg_write(dev, 0x00A0, 0x15); // Set TxQuadcal NCO frequency + status = ad9361_reg_write(dev, 0x00A3, 0x00); // Set TxQuadcal NCO frequency (Only update bits [7:6]) + status = ad9361_reg_write(dev, 0x00A1, 0x7B); // Tx Quad Cal Configuration, Phase and Gain Cal Enable + status = ad9361_reg_write(dev, 0x00A9, 0xFF); // Set Tx Quad Cal Count + status = ad9361_reg_write(dev, 0x00A2, 0x7F); // Set Tx Quad Cal Kexp + status = ad9361_reg_write(dev, 0x00A5, 0x01); // Set Tx Quad Cal Magnitude Threshhold + status = ad9361_reg_write(dev, 0x00A6, 0x01); // Set Tx Quad Cal Magnitude Threshhold + status = ad9361_reg_write(dev, 0x00AA, 0x28); // Set Tx Quad Cal Gain Table index + status = ad9361_reg_write(dev, 0x00A4, 0xF0); // Set Tx Quad Cal Settle Count + status = ad9361_reg_write(dev, 0x00AE, 0x04); // Set Tx Quad Cal LPF Gain index incase Split table mode used + + status = ad9361_reg_write(dev, 0x0169, 0xC0); // Disable Rx Quadrature Calibration before Running Tx Quadrature Calibration + status = ad9361_reg_write(dev, 0x0016, 0x10); // Start Tx Quad cal + + // Wait for cal to complete (Done when 0x016[4]==0) + time_out_cnt = 0; + do{ + status |= ad9361_reg_read(dev, 0x0016, &value); + mdelay(1);// Wait 1ms + time_out_cnt++; + } while((value & 0x10) != 0x00 && time_out_cnt <= AD9361_TIMEOUT_TH); + + status = ad9361_reg_write(dev, 0x016A, 0x75); // Set Kexp Phase + status = ad9361_reg_write(dev, 0x016B, 0x95); // Set Kexp Amplitude & Prevent Positive Gain Bit + status = ad9361_reg_write(dev, 0x0169, 0xCF); // Enable Rx Quadrature Calibration Tracking + status = ad9361_reg_write(dev, 0x018B, 0xAD); // Enable BB and RF DC Tracking Calibrations + status = ad9361_reg_write(dev, 0x0012, 0x02); // Cals done, Set PPORT Config + status = ad9361_reg_write(dev, 0x0013, 0x01); // Set ENSM FDD/TDD bit + status = ad9361_reg_write(dev, 0x0015, 0x0C); // Set Dual Synth Mode, FDD External Control bits properly + +//************************************************************ +// Set Tx Attenuation: Tx1: 0.00 dB, Tx2: 0.00 dB +//************************************************************ + status = ad9361_reg_write(dev, 0x0073, 0x00); + status = ad9361_reg_write(dev, 0x0074, 0x00); + status = ad9361_reg_write(dev, 0x0075, 0x00); + status = ad9361_reg_write(dev, 0x0076, 0x00); +//************************************************************ +// Setup RSSI and Power Measurement Duration Registers +//************************************************************ + status = ad9361_reg_write(dev, 0x0150, 0x0E); // RSSI Measurement Duration 0, 1 + status = ad9361_reg_write(dev, 0x0151, 0x00); // RSSI Measurement Duration 2, 3 + status = ad9361_reg_write(dev, 0x0152, 0xFF); // RSSI Weighted Multiplier 0 + status = ad9361_reg_write(dev, 0x0153, 0x00); // RSSI Weighted Multiplier 1 + status = ad9361_reg_write(dev, 0x0154, 0x00); // RSSI Weighted Multiplier 2 + status = ad9361_reg_write(dev, 0x0155, 0x00); // RSSI Weighted Multiplier 3 + status = ad9361_reg_write(dev, 0x0156, 0x00); // RSSI Delay + status = ad9361_reg_write(dev, 0x0157, 0x00); // RSSI Wait + status = ad9361_reg_write(dev, 0x0158, 0x0D); // RSSI Mode Select + status = ad9361_reg_write(dev, 0x015C, 0x67); // Power Measurement Duration + +//************************************************************ +// Enable External LO & External VCO Buffer +//************************************************************ + status |= ad9361_reg_write(dev, 0x0005, 0x07); + status |= ad9361_reg_write(dev, 0x0057, 0x1C); + + return status; +} diff --git a/df_datalink/src/dev_profile/dev_profile.h b/df_datalink/src/dev_profile/dev_profile.h new file mode 100644 index 0000000..38684fb --- /dev/null +++ b/df_datalink/src/dev_profile/dev_profile.h @@ -0,0 +1,30 @@ +#ifndef _DEV_PROFILE_H_ +#define _DEV_PROFILE_H_ + +#include "spi.h" +#include "i2c.h" +#include "delay.h" +#include "irq.h" +#include "error.h" +#include "../drivers/rf-transceiver/ad9361/ad9361_api.h" +#include "../drivers/rf-transceiver/ad9361_reg/ad9361_reg.h" +#include "../drivers/frequency/hmc7044/hmc7044.h" +#include "../drivers/adc/ad9694/ad9694.h" +#include "../config/app_config.h" + +// device parameters +extern struct irq_init_param intc_init_param; +extern struct timer_init_param scutimer_init_param; +extern struct global_timer_init_param globaltimer_init_param; + +// HMC7044 +extern struct hmc7044_init_param hmc7044_default_init_param; + +// AD9361 +extern AD9361_InitParam ad9361_default_init_param; +extern AD9361_RXFIRConfig rx_fir_config; +extern AD9361_TXFIRConfig tx_fir_config; +extern struct ad9361_reg_init_param ad9361_1_reg_default_init_param; +extern struct ad9361_reg_init_param ad9361_2_reg_default_init_param; +uint32_t ad9361_reg_config(struct ad9361_reg_dev *dev); +#endif /* SRC_DEV_PROFILE_H_ */ diff --git a/df_datalink/src/dev_profile/global_timer_profile.c b/df_datalink/src/dev_profile/global_timer_profile.c new file mode 100644 index 0000000..78fab27 --- /dev/null +++ b/df_datalink/src/dev_profile/global_timer_profile.c @@ -0,0 +1,11 @@ +#include "dev_profile.h" +#include "global_timer.h" +#include "../config/app_config.h" + +struct global_timer_init_param globaltimer_init_param = { + .base_addr = GLOBAL_TIMER_BASEADDR, + .id = GLOBAL_TIMER_DEVICE_ID, + .freq_hz = GLOBAL_TIMER_CLK_HZ, + .load_value = 0x0000000000000000 +}; + diff --git a/df_datalink/src/dev_profile/hmc7044_profile.c b/df_datalink/src/dev_profile/hmc7044_profile.c new file mode 100644 index 0000000..2d24d46 --- /dev/null +++ b/df_datalink/src/dev_profile/hmc7044_profile.c @@ -0,0 +1,132 @@ +#include "dev_profile.h" +#include "../config/app_config.h" +#include "../drivers/platform/xilinx_gpio.h" +#include "../drivers/axi_core/spi_engine/spi_engine.h" +#include "../drivers/frequency/hmc7044/hmc7044.h" + + +static struct spi_engine_init_param spi_engine_param = { + .ref_clk_hz = HMC7044_SPI_ENGINE_REF_CLK, + .type = SPI_ENGINE, + .spi_engine_baseaddr = HMC7044_SPI_ENGINE_BASEADDR, + .cs_delay = HMC7044_SPI_ENGINE_CS_DELAY, + .data_width = HMC7044_SPI_ENGINE_DATA_WIDTH +}; + +//static struct xil_gpio_init_param xil_gpio_param = { +// .type = GPIO_PS, +// .device_id = AD9361_GPIO_DEVICE_ID +//}; + +// hmc7044 spi settings +static struct spi_init_param hmc7044_spi_init_param = { + .device_id = HMC7044_SPI_DEVICE_ID, + .max_speed_hz = HMC7044_SPI_ENGINE_MAX_SPEED, + .mode = SPI_MODE_4, + .chip_select = HMC7044_SPI_CS_HMC7044, + .platform_ops = &spi_eng_platform_ops, + .extra = &spi_engine_param +}; + +// hmc7044 channel specifications +struct hmc7044_chan_spec hmc7044_chan_spec[4] = { + /* AD9361_XTAL */ + { + .disable = 0, + .num = 3, + .divider = 100, + .coarse_delay = 0, + .fine_delay = 0, + .high_performance_mode_dis = true, + .start_up_mode_dynamic_enable = false, + .dynamic_driver_enable = false, + .output_control0_rb4_enable = true, + .force_mute_enable = false, + .driver_mode = CML, + .driver_impedance = INTERNAL_100OHM_PER_PIN, + .out_mux_mode = CHANNEL_DIV + }, + /* FPGA_DAC_LOGIC_CLK */ + { + .disable = 0, + .num = 4, + .divider = 10, + .coarse_delay = 0, + .fine_delay = 0, + .high_performance_mode_dis = true, + .start_up_mode_dynamic_enable = false, + .dynamic_driver_enable = false, + .output_control0_rb4_enable = true, + .force_mute_enable = false, + .driver_mode = CML, + .driver_impedance = INTERNAL_100OHM_PER_PIN, + .out_mux_mode = CHANNEL_DIV + }, + /* B_AD9361_XTAL */ + { + .disable = 0, + .num = 12, + .divider = 100, + .coarse_delay = 0, + .fine_delay = 0, + .high_performance_mode_dis = false, + .start_up_mode_dynamic_enable = false, + .dynamic_driver_enable = false, + .output_control0_rb4_enable = true, + .force_mute_enable = false, + .driver_mode = CML, + .driver_impedance = INTERNAL_100OHM_PER_PIN, + .out_mux_mode = CHANNEL_DIV + }, + /* AD9361_RX_EXT_LO */ + { + .disable = 0, + .num = 13, + .divider = 10, + .coarse_delay = 0, + .fine_delay = 0, + .high_performance_mode_dis = false, + .start_up_mode_dynamic_enable = false, + .dynamic_driver_enable = false, + .output_control0_rb4_enable = true, + .force_mute_enable = false, + .driver_mode = CML, + .driver_impedance = INTERNAL_100OHM_PER_PIN, + .out_mux_mode = CHANNEL_DIV + }, +}; + +// hmc7044 default configurations +struct hmc7044_init_param hmc7044_default_init_param = { + .spi_init = &hmc7044_spi_init_param, + .clkin_freq = {0, 100000000, 0, 0}, + .vcxo_freq = 100000000, + .pll2_freq = 2500000000, + .pll1_loop_bw = 200, + .sysref_timer_div = 1536, + .in_buf_mode = { + BUFFER_DISABLE, + ENABLE_AC_COUPLE | ENABLE_INTERNAL_TERM | BUFFER_ENABLE, + BUFFER_DISABLE, + BUFFER_DISABLE, + ENABLE_AC_COUPLE | ENABLE_INTERNAL_TERM | BUFFER_ENABLE + }, + .gpi_ctrl = { + GPI_DISABLE, + GPI_DISABLE, + CHIP_SLEEP_MODE, + PULSE_GEN_REQUSET + }, + .gpo_ctrl = { + PLL1_LOCK_DETECT | GPO_CMOS_MODE, + PLL2_LOCK_DETECT | GPO_CMOS_MODE, + GPO_DISABLE, + GPO_DISABLE + }, + .num_channels = 4, + .pll1_ref_prio_ctrl = 0xE4, + .sync_pin_mode = SYNC_MULTICHIP, + .high_performance_mode_clock_dist_en = false, + .pulse_gen_mode = PULSE_ONE, + .channels = hmc7044_chan_spec +}; diff --git a/df_datalink/src/dev_profile/intc_profile.c b/df_datalink/src/dev_profile/intc_profile.c new file mode 100644 index 0000000..47dc70a --- /dev/null +++ b/df_datalink/src/dev_profile/intc_profile.c @@ -0,0 +1,13 @@ +#include "dev_profile.h" +#include "irq.h" +#include "../config/app_config.h" +#include "../drivers/platform/xilinx_irq.h" +struct xil_irq_init_param xil_intc_init_param = { + .type = IRQ_PS +}; + +struct irq_init_param intc_init_param = { + .irq_ctrl_id = INTC_DEVICE_ID, + .platform_ops = &xil_irq_ops, + .extra = &xil_intc_init_param +}; diff --git a/df_datalink/src/dev_profile/timer_profile.c b/df_datalink/src/dev_profile/timer_profile.c new file mode 100644 index 0000000..53aac51 --- /dev/null +++ b/df_datalink/src/dev_profile/timer_profile.c @@ -0,0 +1,17 @@ +#include "dev_profile.h" +#include "timer.h" +#include "../config/app_config.h" +#include "../drivers/platform/xilinx_timer.h" + +struct xil_timer_init_param xil_scutimer_init_param = { + .active_tmr = 0, + .type = TIMER_PS +}; + +struct timer_init_param scutimer_init_param = { + .id = SCUTIMER_DEVICE_ID, + .freq_hz = SCU_TIMER_CLK_HZ, + .ticks_count = (SCU_TIMER_CLK_HZ/10), //update log every 100ms + .platform_ops = &xil_timer_ops, + .extra = &xil_scutimer_init_param +}; diff --git a/df_datalink/src/drivers/adc/ad9694/ad9694.c b/df_datalink/src/drivers/adc/ad9694/ad9694.c new file mode 100644 index 0000000..336ea4b --- /dev/null +++ b/df_datalink/src/drivers/adc/ad9694/ad9694.c @@ -0,0 +1,128 @@ +/***************************************************************************//** + * @file ad9694.c + * @brief Implementation of AD9680 Driver. + * @author DBogdan (dragos.bogdan@analog.com) + ******************************************************************************** + * Copyright 2014-2016(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include +#include +#include "ad9694.h" +#include "../../../include/error.h" + +/***************************************************************************//** + * @brief ad9694_read + *******************************************************************************/ +int32_t ad9694_read(struct ad9694_dev *dev, + uint16_t reg_addr, + uint8_t *reg_data) +{ + uint8_t tx_buf[2]; + uint8_t rx_buf[1]; + int32_t ret; + + tx_buf[0] = 0x80 | (reg_addr >> 8); + tx_buf[1] = reg_addr & 0xFF; + + + ret = spi_write_and_read_3wire(dev->spi_desc, + tx_buf, rx_buf, 2, 1); + + *reg_data = rx_buf[0]; + + return ret; +} + +/***************************************************************************//** + * @brief ad9694_write + *******************************************************************************/ +int32_t ad9694_write(struct ad9694_dev *dev, + uint16_t reg_addr, + uint8_t reg_data) +{ + uint8_t buf[3]; + + int32_t ret; + + buf[0] = reg_addr >> 8; + buf[1] = reg_addr & 0xFF; + buf[2] = reg_data; + + ret = spi_write_and_read_3wire(dev->spi_desc, + buf, NULL, 3, 0); + return ret; +} + +/***************************************************************************//** + * @brief ad9694_init + *******************************************************************************/ +int32_t ad9694_init(struct ad9694_dev **device, + const struct ad9694_init_param *init_param) +{ + int ret = SUCCESS; + struct ad9694_dev *dev; + + dev = (struct ad9694_dev *)malloc(sizeof(*dev)); + if (!dev) + return FAILURE; + + /* SPI */ + ret = spi_init(&dev->spi_desc, init_param->spi_init); + + *device = dev; + + return ret; +} + +/***************************************************************************//** + * @brief Free the resources allocated by ad9694_setup(). + * + * @param dev - The device structure. + * + * @return SUCCESS in case of success, negative error code otherwise. +*******************************************************************************/ +int32_t ad9694_remove(struct ad9694_dev *dev) +{ + int32_t ret; + + ret = spi_remove(dev->spi_desc); + + free(dev); + + return ret; +} diff --git a/df_datalink/src/drivers/adc/ad9694/ad9694.h b/df_datalink/src/drivers/adc/ad9694/ad9694.h new file mode 100644 index 0000000..3c4446a --- /dev/null +++ b/df_datalink/src/drivers/adc/ad9694/ad9694.h @@ -0,0 +1,231 @@ +/***************************************************************************//** + * @file ad9694.h + * @brief Header file of AD9694 Driver. + * @author DBogdan (dragos.bogdan@analog.com) + ******************************************************************************** + * Copyright 2014-2016(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *******************************************************************************/ +#ifndef AD9694_H_ +#define AD9694_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include +#include "delay.h" +#include "spi.h" + +/******************************************************************************/ +/********************** Macros and Constants Definitions **********************/ +/******************************************************************************/ +#define AD9694_REG_GLOBAL_MAP_SPI_CONF_A 0x0000 +#define AD9694_REG_GLOBAL_MAP_SPI_CONF_B 0x0001 +#define AD9694_REG_CH_MAP_CHIP_CONF 0x0002 +#define AD9694_REG_PAIR_MAP_CHIP_TYPE 0x0003 +#define AD9694_REG_PAIR_MAP_CHIP_ID_LSB 0x0004 +#define AD9694_REG_PAIR_MAP_CHIP_GRADE 0x0006 +#define AD9694_REG_PAIR_MAP_DEV_INDEX 0x0008 +#define AD9694_REG_GLOBAL_MAP_PAIR_INDEX 0x0009 +#define AD9694_REG_PAIR_MAP_SCRATCH_PAD 0x000A +#define AD9694_REG_PAIR_MAP_SPI_REVISION 0x000B +#define AD9694_REG_PAIR_MAP_VENDOR_ID_LSB 0x000C +#define AD9694_REG_PAIR_MAP_VENDOR_ID_MSB 0x000D +#define AD9694_REG_CH_MAP_CHIP_PD_PIN 0x003F +#define AD9694_REG_PAIR_MAP_CHIP_PIN_CTRL_1 0x0040 +#define AD9694_REG_PAIR_MAP_CLK_DIV_CTRL 0x0108 +#define AD9694_REG_CH_MAP_CLK_DIV_PHASE 0x0109 +#define AD9694_REG_PAIR_MAP_CLK_DIV_SYSREF_CTRL 0x010A +#define AD9694_REG_PAIR_MAP_CLK_DELAY_CTRL 0x0110 +#define AD9694_REG_CH_MAP_CLK_SUPER_FINE_DELAY 0x0111 +#define AD9694_REG_CH_MAP_CLK_FINE_DELAY 0x0112 +#define AD9694_REG_CLK_DETN_CTRL 0x011A +#define AD9694_REG_PAIR_MAP_CLK_STAT 0x011B +#define AD9694_REG_CLK_DCS_CTRL_1 0x011C +#define AD9694_REG_CLK_DCS_CTRL_2 0x011E +#define AD9694_REG_CLK_DCS_CTRL_3 0x011F +#define AD9694_REG_PAIR_MAP_SYSREF_CTRL_1 0x0120 +#define AD9694_REG_PAIR_MAP_SYSREF_CTRL_2 0x0121 +#define AD9694_REG_PAIR_MAP_SYSREF_CTRL_4 0x0123 +#define AD9694_REG_PAIR_MAP_SYSREF_STAT_1 0x0128 +#define AD9694_REG_PAIR_MAP_SYSREF_STAT_2 0x0129 +#define AD9694_REG_PAIR_MAP_SYSREF_STAT_3 0x012A +#define AD9694_REG_PAIR_MAP_CHIP_SYNC 0x01FF +#define AD9694_REG_PAIR_MAP_CHIP_MODE 0x0200 +#define AD9694_REG_PAIR_MAP_CHIP_DEC_RATIO 0x0201 +#define AD9694_REG_CH_MAP_CUSTOM_OFFSET 0x0228 +#define AD9694_REG_CH_MAP_FD_CTRL 0x0245 +#define AD9694_REG_CH_MAP_FD_UT_LSB 0x0247 +#define AD9694_REG_CH_MAP_FD_UT_MSB 0x0248 +#define AD9694_REG_CH_MAP_FD_LT_LSB 0x0249 +#define AD9694_REG_CH_MAP_FD_LT_MSB 0x024A +#define AD9694_REG_CH_MAP_FD_DWELL_TIME_LSB 0x024B +#define AD9694_REG_CH_MAP_FD_DWELL_TIME_MSB 0x024C +#define AD9694_REG_PAIR_MAP_SIG_MON_SYNC_CTRL 0x026F +#define AD9694_REG_CH_MAP_SIG_MON_CTRL 0x0270 +#define AD9694_REG_CH_MAP_SIG_MON_PERIOD_0 0x0271 +#define AD9694_REG_CH_MAP_SIG_MON_PERIOD_1 0x0272 +#define AD9694_REG_CH_MAP_SIG_MON_PERIOD_2 0x0273 +#define AD9694_REG_CH_MAP_SIG_MON_STAT_CTRL 0x0274 +#define AD9694_REG_CH_MAP_SIG_MON_STAT_0 0x0275 +#define AD9694_REG_CH_MAP_SIG_MON_STAT_1 0x0276 +#define AD9694_REG_CH_MAP_SIG_MON_STAT_2 0x0277 +#define AD9694_REG_CH_MAP_SIG_MON_STAT_FRAME_CNT 0x0278 +#define AD9694_REG_CH_MAP_SIG_MON_SERIAL_FRAMER_CTRL 0x0279 +#define AD9694_REG_SPORT_OVER_JESD204B_INPUT_SEL 0x027A +#define AD9694_REG_PAIR_MAP_DDC_SYNC_CTRL 0x0300 +#define AD9694_REG_PAIR_MAP_DDC_0_CTRL 0x0310 +#define AD9694_REG_PAIR_MAP_DDC_0_INPUT_SEL 0x0311 +#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_INC_0 0x0314 +#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_INC_1 0x0315 +#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_INC_2 0x0316 +#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_INC_3 0x0317 +#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_INC_4 0x0318 +#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_INC_5 0x031A +#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_OFFSET_0 0x031D +#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_OFFSET_1 0x031E +#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_OFFSET_2 0x031F +#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_OFFSET_3 0x0320 +#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_OFFSET_4 0x0321 +#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_OFFSET_5 0x0322 +#define AD9694_REG_PAIR_MAP_DDC_0_TEST_ENABLE 0x0327 +#define AD9694_REG_PAIR_MAP_DDC_1_CTRL 0x0330 +#define AD9694_REG_PAIR_MAP_DDC_1_INPUT_SEL 0x0331 +#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_INC_0 0x0334 +#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_INC_1 0x0335 +#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_INC_2 0x0336 +#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_INC_3 0x0337 +#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_INC_4 0x0338 +#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_INC_5 0x033A +#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_OFFSET_0 0x033D +#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_OFFSET_1 0x033E +#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_OFFSET_2 0x033F +#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_OFFSET_3 0x0340 +#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_OFFSET_4 0x0341 +#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_OFFSET_5 0x0342 +#define AD9694_REG_PAIR_MAP_DDC_1_TEST_ENABLE 0x0347 +#define AD9694_REG_CH_MAP_TEST_MODE_CTRL 0x0550 +#define AD9694_REG_PAIR_MAP_USER_PATTERN_1_LSB 0x0551 +#define AD9694_REG_PAIR_MAP_USER_PATTERN_1_MSB 0x0552 +#define AD9694_REG_PAIR_MAP_USER_PATTERN_2_LSB 0x0553 +#define AD9694_REG_PAIR_MAP_USER_PATTERN_2_MSB 0x0554 +#define AD9694_REG_PAIR_MAP_USER_PATTERN_3_LSB 0x0555 +#define AD9694_REG_PAIR_MAP_USER_PATTERN_3_MSB 0x0556 +#define AD9694_REG_PAIR_MAP_USER_PATTERN_4_LSB 0x0557 +#define AD9694_REG_PAIR_MAP_USER_PATTERN_4_MSB 0x0558 +#define AD9694_REG_PAIR_MAP_OUTPUT_CTRL_MODE_0 0x0559 +#define AD9694_REG_PAIR_MAP_OUTPUT_CTRL_MODE_1 0x055A +#define AD9694_REG_PAIR_MAP_OUTPUT_SAMPLE_MODE 0x0561 +#define AD9694_REG_PAIR_MAP_OUTPUT_CH_SEL 0x0564 +#define AD9694_REG_JESD204B_MAP_PLL_CTRL 0x056E +#define AD9694_REG_JESD204B_MAP_PLL_STAT 0x056F +#define AD9694_REG_JESD204B_MAP_JTX_QUICK_CONF 0x0570 +#define AD9694_REG_JESD204B_MAP_JTX_LINK_CTRL_1 0x0571 +#define AD9694_REG_JESD204B_MAP_JTX_LINK_CTRL_2 0x0572 +#define AD9694_REG_JESD204B_MAP_JTX_LINK_CTRL_3 0x0573 +#define AD9694_REG_JESD204B_MAP_JTX_LINK_CTRL_4 0x0574 +#define AD9694_REG_JESD204B_MAP_JTX_LMFC_OFFSET 0x0578 +#define AD9694_REG_JESD204B_MAP_JTX_DID_CONF 0x0580 +#define AD9694_REG_JESD204B_MAP_JTX_BID_CONF 0x0581 +#define AD9694_REG_JESD204B_MAP_JTX_LID_0_CONF 0x0583 +#define AD9694_REG_JESD204B_MAP_JTX_LID_1_CONF 0x0585 +#define AD9694_REG_JESD204B_MAP_JTX_SCR_L_CONF 0x058B +#define AD9694_REG_JESD204B_MAP_JTX_F_CONF 0x058C +#define AD9694_REG_JESD204B_MAP_JTX_K_CONF 0x058D +#define AD9694_REG_JESD204B_MAP_JTX_M_CONF 0x058E +#define AD9694_REG_JESD204B_MAP_JTX_CS_N_CONF 0x058F +#define AD9694_REG_JESD204B_MAP_JTX_SUBCLASS_CONF 0x0590 +#define AD9694_REG_JESD204B_MAP_JTX_S_CONF 0x0591 +#define AD9694_REG_JESD204B_MAP_JTX_HD_CF_CONF 0x0592 +#define AD9694_REG_JESD204B_MAP_JTX_CHECKSUM_0_CONF 0x05A0 +#define AD9694_REG_JESD204B_MAP_JTX_CHECKSUM_1_CONF 0x05A1 +#define AD9694_REG_SERDOUTX0_SERDOUTX1_LANE_PD 0x05B0 +#define AD9694_REG_JESD204B_MAP_JTX_LANE_ASSIGN_1 0x05B2 +#define AD9694_REG_JESD204B_MAP_JTX_LANE_ASSIGN_2 0x05B3 +#define AD9694_REG_JESD204B_MAP_SERD_ADJUST_0 0x05C0 +#define AD9694_REG_JESD204B_MAP_SERD_ADJUST_1 0x05C1 +#define AD9694_REG_JESD204B_SER_PE_SEL_LANE_0 0x05C4 +#define AD9694_REG_JESD204B_SER_PE_SEL_LANE_1 0x05C6 +#define AD9694_REG_LARGE_DITHER_CTRL 0x0922 +#define AD9694_REG_PLL_CAL 0x1222 +#define AD9694_REG_JESD204B_STARTUP_CIRCUIT_RST 0x1228 +#define AD9694_REG_PLL_LOSS_OF_LOCK_CTRL 0x1262 +#define AD9694_REG_DC_OFFSET_CAL_CTRL 0x0701 +#define AD9694_REG_DC_OFFSET_CAL_CTRL_2 0x073B +#define AD9694_REG_PAIR_MAP_VREF_CTRL 0x18A6 +#define AD9694_REG_EXT_VCM_BUF_CTRL_1 0x18E0 +#define AD9694_REG_EXT_VCM_BUF_CTRL_2 0x18E1 +#define AD9694_REG_EXT_VCM_BUF_CTRL_3 0x18E2 +#define AD9694_REG_EXT_VCM_BUF_CTRL 0x18E3 +#define AD9694_REG_TEMP_DIODE_EXPORT 0x18E6 +#define AD9694_REG_CH_MAP_ANALOG_INPUT_CTRL 0x1908 +#define AD9694_REG_CH_MAP_INPUT_FULLSCALE_RANGE 0x1910 +#define AD9694_REG_CH_MAP_BUF_CTRL_1 0x1A4C +#define AD9694_REG_CH_MAP_BUF_CTRL_2 0x1A4D + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ +struct ad9694_dev { + /* SPI */ + struct spi_desc *spi_desc; +}; + +struct ad9694_init_param { + /* SPI */ + struct spi_init_param *spi_init; +}; + +struct ad9694_config { + uint16_t addr; + uint8_t value; +}; + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ + +int32_t ad9694_read(struct ad9694_dev *dev, + uint16_t reg_addr, + uint8_t *reg_data); + +int32_t ad9694_write(struct ad9694_dev *dev, + uint16_t reg_addr, + uint8_t reg_data); + +int32_t ad9694_init(struct ad9694_dev **device, + const struct ad9694_init_param *init_param); + +int32_t ad9694_remove(struct ad9694_dev *dev); + +#endif diff --git a/df_datalink/src/drivers/api/gpio.c b/df_datalink/src/drivers/api/gpio.c new file mode 100644 index 0000000..5b37137 --- /dev/null +++ b/df_datalink/src/drivers/api/gpio.c @@ -0,0 +1,241 @@ +/***************************************************************************//** + * @file gpio.c + * @brief Implementation of the GPIO Interface + * @author Antoniu Miclaus (antoniu.miclaus@analog.com) +******************************************************************************** + * Copyright 2020(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#include +#include "gpio.h" +#include +#include "error.h" + +/******************************************************************************/ +/************************ Functions Definitions *******************************/ +/******************************************************************************/ + +/** + * @brief Obtain the GPIO decriptor. + * @param desc - The GPIO descriptor. + * @param param - GPIO Initialization parameters. + * @return 0 in case of success, -1 otherwise. + */ +int32_t gpio_get(struct gpio_desc **desc, + const struct gpio_init_param *param) +{ + int32_t ret; + + if (!param || !param->platform_ops) + return -EINVAL; + + if (!param->platform_ops->gpio_ops_get) + return -ENOSYS; + + ret = param->platform_ops->gpio_ops_get(desc, param); + if (ret) + return ret; + + (*desc)->platform_ops = param->platform_ops; + + return 0; +} + +/** + * @brief Get the value of an optional GPIO. + * @param desc - The GPIO descriptor. + * @param param - GPIO Initialization parameters. + * @return 0 in case of success, -1 otherwise. + */ +int32_t gpio_get_optional(struct gpio_desc **desc, + const struct gpio_init_param *param) +{ + int32_t ret; + + if (!param || (param->number == -1)) { + *desc = NULL; + return 0; + } + + if (!param->platform_ops) + return -EINVAL; + + if (!param->platform_ops->gpio_ops_get_optional) + return -ENOSYS; + + ret = param->platform_ops->gpio_ops_get_optional(desc, param); + if (ret) + return ret; + + (*desc)->platform_ops = param->platform_ops; + + return 0; +} +/** + * @brief Free the resources allocated by gpio_get(). + * @param desc - The GPIO descriptor. + * @return 0 in case of success, -1 otherwise. + */ +int32_t gpio_remove(struct gpio_desc *desc) +{ + if (desc) { + if (!desc->platform_ops) + return -EINVAL; + + if (!desc->platform_ops->gpio_ops_remove) + return -ENOSYS; + + return desc->platform_ops->gpio_ops_remove(desc); + } + + return 0; +} + +/** + * @brief Enable the input direction of the specified GPIO. + * @param desc - The GPIO descriptor. + * @return 0 in case of success, -1 otherwise. + */ +int32_t gpio_direction_input(struct gpio_desc *desc) +{ + if (desc) { + if (!desc->platform_ops) + return -EINVAL; + + if (!desc->platform_ops->gpio_ops_direction_input) + return -ENOSYS; + + return desc->platform_ops->gpio_ops_direction_input(desc); + } + + return 0; +} + +/** + * @brief Enable the output direction of the specified GPIO. + * @param desc - The GPIO descriptor. + * @param value - The value. + * Example: GPIO_HIGH + * GPIO_LOW + * @return 0 in case of success, -1 otherwise. + */ +int32_t gpio_direction_output(struct gpio_desc *desc, + uint8_t value) +{ + if (desc) { + if (!desc->platform_ops) + return -EINVAL; + + if (!desc->platform_ops->gpio_ops_direction_output) + return -ENOSYS; + + return desc->platform_ops-> + gpio_ops_direction_output(desc, value); + } + + return 0; +} + +/** + * @brief Get the direction of the specified GPIO. + * @param desc - The GPIO descriptor. + * @param direction - The direction. + * Example: GPIO_OUT + * GPIO_IN + * @return 0 in case of success, -1 otherwise. + */ +int32_t gpio_get_direction(struct gpio_desc *desc, + uint8_t *direction) +{ + if (desc) { + if (!desc->platform_ops) + return -EINVAL; + + if (!desc->platform_ops->gpio_ops_get_direction) + return -ENOSYS; + + return desc->platform_ops-> + gpio_ops_get_direction(desc, direction); + } + + return 0; +} + +/** + * @brief Set the value of the specified GPIO. + * @param desc - The GPIO descriptor. + * @param value - The value. + * Example: GPIO_HIGH + * GPIO_LOW + * @return 0 in case of success, -1 otherwise. + */ +int32_t gpio_set_value(struct gpio_desc *desc, + uint8_t value) +{ + if (desc) { + if (!desc->platform_ops) + return -EINVAL; + + if (!desc->platform_ops->gpio_ops_set_value) + return -ENOSYS; + + return desc->platform_ops->gpio_ops_set_value(desc, value); + } + + return 0; +} + +/** + * @brief Get the value of the specified GPIO. + * @param desc - The GPIO descriptor. + * @param value - The value. + * Example: GPIO_HIGH + * GPIO_LOW + * @return 0 in case of success, -1 otherwise. + */ +int32_t gpio_get_value(struct gpio_desc *desc, + uint8_t *value) +{ + if (desc) { + if (!desc->platform_ops) + return -EINVAL; + + if (!desc->platform_ops->gpio_ops_set_value) + return -ENOSYS; + + return desc->platform_ops->gpio_ops_get_value(desc, value); + } + + return 0; +} diff --git a/df_datalink/src/drivers/api/i2c.c b/df_datalink/src/drivers/api/i2c.c new file mode 100644 index 0000000..149e7cd --- /dev/null +++ b/df_datalink/src/drivers/api/i2c.c @@ -0,0 +1,135 @@ +/***************************************************************************//** + * @file i2c.c + * @brief Implementation of the I2C Interface + * @author Antoniu Miclaus (antoniu.miclaus@analog.com) +******************************************************************************** + * Copyright 2020(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#include +#include "i2c.h" +#include +#include "error.h" + +/** + * @brief Initialize the I2C communication peripheral. + * @param desc - The I2C descriptor. + * @param param - The structure that contains the I2C parameters. + * @return 0 in case of success, -1 otherwise. + */ +int32_t i2c_init(struct i2c_desc **desc, + const struct i2c_init_param *param) +{ + int32_t ret; + + if (!param || !param->platform_ops) + return -EINVAL; + + if (!param->platform_ops->i2c_ops_init) + return -ENOSYS; + + ret = param->platform_ops->i2c_ops_init(desc, param); + if (ret) + return ret; + + (*desc)->platform_ops = param->platform_ops; + + return 0; +} + +/** + * @brief Free the resources allocated by i2c_init(). + * @param desc - The I2C descriptor. + * @return 0 in case of success, -1 otherwise. + */ +int32_t i2c_remove(struct i2c_desc *desc) +{ + if (!desc || !desc->platform_ops) + return -EINVAL; + + if (!desc->platform_ops->i2c_ops_remove) + return -ENOSYS; + + return desc->platform_ops->i2c_ops_remove(desc); +} + +/** + * @brief I2C Write data to slave device. + * @param desc - The I2C descriptor. + * @param data - The buffer with the transmitted/received data. + * @param bytes_number - Number of bytes to write. + * @param stop_bit - Stop conditional control. + * Example: 0 - A stop condition will not be generated. + * 1 - A stop condition will be generated. + * @return 0 in case of success, -1 otherwise. + */ +int32_t i2c_write(struct i2c_desc *desc, + uint8_t *data, + uint8_t bytes_number, + uint8_t stop_bit) +{ + if (!desc || !desc->platform_ops) + return -EINVAL; + + if (!desc->platform_ops->i2c_ops_write) + return -ENOSYS; + + return desc->platform_ops->i2c_ops_write(desc, data, bytes_number, + stop_bit); +} + +/** + * @brief I2C Read data from slave device. + * @param desc - The i2c descriptor. + * @param data - The buffer with the transmitted/received data. + * @param bytes_number - Number of bytes to read. + * @param stop_bit - Stop conditional control. + * Example: 0 - A stop condition will not be generated. + * 1 - A stop condition will be generated. + * @return 0 in case of success, -1 otherwise. + */ +int32_t i2c_read(struct i2c_desc *desc, + uint8_t *data, + uint8_t bytes_number, + uint8_t stop_bit) +{ + if (!desc || !desc->platform_ops) + return -EINVAL; + + if (!desc->platform_ops->i2c_ops_read) + return -ENOSYS; + + return desc->platform_ops->i2c_ops_read(desc, data, bytes_number, + stop_bit); +} diff --git a/df_datalink/src/drivers/api/irq.c b/df_datalink/src/drivers/api/irq.c new file mode 100644 index 0000000..9162366 --- /dev/null +++ b/df_datalink/src/drivers/api/irq.c @@ -0,0 +1,229 @@ +/***************************************************************************//** + * @file irq.c + * @brief Implementation of the IRQ Interface + * @author Andrei Porumb (andrei.porumb@analog.com) +******************************************************************************** + * Copyright 2021(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#include +#include +#include "irq.h" +#include "error.h" + +/** + * @brief Initialize the IRQ interrupts. + * @param desc - The IRQ descriptor. + * @param param - The structure that contains the IRQ parameters. + * @return 0 in case of success, -1 otherwise. + */ +int32_t irq_ctrl_init(struct irq_ctrl_desc **desc, + const struct irq_init_param *param) +{ + int32_t ret; + + if (!param || !param->platform_ops) + return -EINVAL; + + if (!param->platform_ops->init) + return -ENOSYS; + + ret = param->platform_ops->init(desc, param); + if (ret) + return ret; + + (*desc)->platform_ops = param->platform_ops; + + return 0; +} + +/** + * @brief Free the resources allocated by irq_ctrl_init(). + * @param desc - The SPI descriptor. + * @return 0 in case of success, -1 otherwise. + */ +int32_t irq_ctrl_remove(struct irq_ctrl_desc *desc) +{ + if (!desc || !desc->platform_ops) + return -EINVAL; + + if (!desc->platform_ops->remove) + return -ENOSYS; + + return desc->platform_ops->remove(desc); +} + +/** + * @brief Register a callback to handle the irq events. + * @param desc - The IRQ controller descriptor. + * @param irq_id - Interrupt identifier. + * @param callback - Callback descriptor - platform specific type. + * @return SUCCESS in case of success, FAILURE otherwise. + */ +int32_t irq_register_callback(struct irq_ctrl_desc *desc, + uint32_t irq_id, + struct callback_desc *callback) +{ + if (!desc || !desc->platform_ops) + return -EINVAL; + + if (!desc->platform_ops->register_callback) + return -ENOSYS; + + return desc->platform_ops->register_callback(desc, irq_id, callback); +} + +/** + * @brief Unregisters a generic IRQ handling function. + * @param desc - The IRQ controller descriptor. + * @param irq_id - Interrupt identifier. + * @param callback - Callback descriptor - platform specific type. + * @return SUCCESS in case of success, FAILURE otherwise. + */ +int32_t irq_unregister_callback(struct irq_ctrl_desc *desc, + uint32_t irq_id, + struct callback_desc *callback) +{ + if (!desc || !desc->platform_ops) + return -EINVAL; + + if (!desc->platform_ops->unregister_callback) + return -ENOSYS; + + return desc->platform_ops->unregister_callback(desc, irq_id, callback); +} + +/** + * @brief Enable global interrupts. + * @return 0 in case of success, -1 otherwise. + */ +int32_t irq_global_enable(struct irq_ctrl_desc *desc) +{ + if (!desc || !desc->platform_ops) + return -EINVAL; + + if (!desc->platform_ops->global_enable) + return -ENOSYS; + + return desc->platform_ops->global_enable(desc); +} + +/** + * @brief Disable global interrupts. + * @return 0 in case of success, -1 otherwise. + */ +int32_t irq_global_disable(struct irq_ctrl_desc *desc) +{ + if (!desc || !desc->platform_ops) + return -EINVAL; + + if (!desc->platform_ops->global_disable) + return -ENOSYS; + + return desc->platform_ops->global_disable(desc); +} + +/** + * @brief Set interrupt trigger level. + * @param desc - The IRQ controller descriptor. + * @param irq_id - Interrupt identifier. + * @param trig - New trigger level for the interrupt. + * @return 0 in case of success, -1 otherwise. + */ +int32_t irq_trigger_level_set(struct irq_ctrl_desc *desc, + uint32_t irq_id, + enum irq_trig_level trig) +{ + if (!desc || !desc->platform_ops) + return -EINVAL; + + if(!desc->platform_ops->trigger_level_set) + return -ENOSYS; + + return desc->platform_ops->trigger_level_set(desc, irq_id, trig); +} + +/** + * @brief Enable specific interrupt. + * @param desc - The IRQ controller descriptor. + * @param irq_id - Interrupt identifier. + * @return 0 in case of success, -1 otherwise. + */ +int32_t irq_enable(struct irq_ctrl_desc *desc, uint32_t irq_id) +{ + if (!desc || !desc->platform_ops) + return -EINVAL; + + if (!desc->platform_ops->enable) + return -ENOSYS; + + return desc->platform_ops->enable(desc, irq_id); +} + +/** + * @brief Disable specific interrupt. + * @param desc - The IRQ controller descriptor. + * @param irq_id - Interrupt identifier. + * @return 0 in case of success, -1 otherwise. + */ +int32_t irq_disable(struct irq_ctrl_desc *desc, uint32_t irq_id) +{ + if (!desc || !desc->platform_ops) + return -EINVAL; + + if (!desc->platform_ops->disable) + return -ENOSYS; + + return desc->platform_ops->disable(desc, irq_id); +} + +/** + * @brief Set the priority for an interrupt. + * @param desc - The IRQ controller descriptor. + * @param irq_id - Interrupt identifier. + * @param priority_level - The priority level of the interrupt. + * @return 0 in case of success, negative errno error codes. + */ +int32_t irq_set_priority(struct irq_ctrl_desc *desc, + uint32_t irq_id, + uint32_t priority_level) +{ + if (!desc || !desc->platform_ops) + return -EINVAL; + + if (!desc->platform_ops->set_priority) + return -ENOSYS; + + return desc->platform_ops->set_priority(desc, irq_id, priority_level); +} diff --git a/df_datalink/src/drivers/api/spi.c b/df_datalink/src/drivers/api/spi.c new file mode 100644 index 0000000..954f669 --- /dev/null +++ b/df_datalink/src/drivers/api/spi.c @@ -0,0 +1,161 @@ +/***************************************************************************//** + * @file spi.c + * @brief Implementation of the SPI Interface + * @author Antoniu Miclaus (antoniu.miclaus@analog.com) +******************************************************************************** + * Copyright 2020(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#include +#include "spi.h" +#include +#include "error.h" + +/** + * @brief Initialize the SPI communication peripheral. + * @param desc - The SPI descriptor. + * @param param - The structure that contains the SPI parameters. + * @return 0 in case of success, -1 otherwise. + */ +int32_t spi_init(struct spi_desc **desc, + const struct spi_init_param *param) +{ + int32_t ret; + + if (!param || !param->platform_ops) + return -EINVAL; + + if (!param->platform_ops->init) + return -ENOSYS; + + ret = param->platform_ops->init(desc, param); + if (ret) + return ret; + + (*desc)->platform_ops = param->platform_ops; + (*desc)->parent = param->parent; + + return 0; +} + +/** + * @brief Free the resources allocated by spi_init(). + * @param desc - The SPI descriptor. + * @return 0 in case of success, -1 otherwise. + */ +int32_t spi_remove(struct spi_desc *desc) +{ + if (!desc || !desc->platform_ops) + return -EINVAL; + + if (!desc->platform_ops->remove) + return -ENOSYS; + + return desc->platform_ops->remove(desc); +} + +/** + * @brief Write and read data to/from SPI. + * @param desc - The SPI descriptor. + * @param data - The buffer with the transmitted/received data. + * @param bytes_number - Number of bytes to write/read. + * @return 0 in case of success, -1 otherwise. + */ +int32_t spi_write_and_read(struct spi_desc *desc, + uint8_t *data, + uint16_t bytes_number) +{ + if (!desc || !desc->platform_ops) + return -EINVAL; + + if (!desc->platform_ops->write_and_read) + return -ENOSYS; + + return desc->platform_ops->write_and_read(desc, data, bytes_number); +} + +/** + * @brief Write and read data to/from SPI in 3 wire mode. + * @param desc - The SPI descriptor. + * @param write_data - The buffer with the transmitted data. + * @param read_data - The buffer with the received data. + * @param write_bytes_number - Number of bytes to write. + * @param read_bytes_number - Number of bytes to read. + * @return SUCCESS in case of success, FAILURE otherwise. + */ +int32_t spi_write_and_read_3wire(struct spi_desc *desc, + uint8_t *write_data, + uint8_t *read_data, + uint16_t write_bytes_number, + uint16_t read_bytes_number) +{ + if (!desc || !desc->platform_ops) + return -EINVAL; + + if (!desc->platform_ops->write_and_read_3wire) + return -ENOSYS; + return desc->platform_ops->write_and_read_3wire(desc, write_data, read_data, + write_bytes_number, read_bytes_number); +} +/** + * @brief Iterate over head list and send all spi messages + * @param desc - The SPI descriptor. + * @param msgs - Array of messages. + * @param len - Number of messages in the array. + * @return 0 in case of success, negativ error code otherwise. + */ +int32_t spi_transfer(struct spi_desc *desc, + struct spi_msg *msgs, + uint32_t len) +{ + int32_t ret; + uint32_t i; + + if (!desc || !desc->platform_ops) + return -EINVAL; + + if (desc->platform_ops->transfer) + return desc->platform_ops->transfer(desc, msgs, len); + + for (i = 0; i < len; i++) { + if (msgs[i].rx_buff != msgs[i].tx_buff || !msgs[i].tx_buff) + return -EINVAL; + ret = spi_write_and_read(desc, msgs[i].rx_buff, + msgs[i].bytes_number); + if (IS_ERR_VALUE(ret)) + return ret; + } + + return 0; +} diff --git a/df_datalink/src/drivers/api/timer.c b/df_datalink/src/drivers/api/timer.c new file mode 100644 index 0000000..c9aae42 --- /dev/null +++ b/df_datalink/src/drivers/api/timer.c @@ -0,0 +1,211 @@ +/***************************************************************************//** +* @file timer.c +* @brief Implementation of the timer Interface +* @author RBolboac (ramona.bolboaca@analog.com) +******************************************************************************** +* Copyright 2022(c) Analog Devices, Inc. +* +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* - Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* - Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* - Neither the name of Analog Devices, Inc. nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* - The use of this software may or may not infringe the patent rights +* of one or more patent holders. This license does not release you +* from the requirement that you obtain separate licenses from these +* patent holders to use this software. +* - Use of the software either in source or binary form, must be run +* on or directly connected to an Analog Devices Inc. component. +* +* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, MERCHANTABILITY +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include "error.h" +#include "timer.h" + +/******************************************************************************/ +/************************ Functions Definitions *******************************/ +/******************************************************************************/ +/** + * @brief Initialize hardware timer and the handler structure associated with + * it. + * @param [out] desc - Pointer to the reference of the device handler. + * @param [in] param - Initialization structure. + * @return 0 in case of success, negative error code otherwise + */ +int32_t timer_init(struct timer_desc **desc, + struct timer_init_param *param) +{ + int32_t ret; + + if (!param || !param->platform_ops) + return -EINVAL; + + if (!param->platform_ops->init) + return -ENOSYS; + + ret = param->platform_ops->init(desc, param); + if (ret) + return ret; + + (*desc)->platform_ops = param->platform_ops; + + return 0; +} + +/** + * @brief Free the memory allocated by timer_init(). + * @param [in] desc - Pointer to the device handler. + * @return 0 in case of success, negative error code otherwise + */ +int32_t timer_remove(struct timer_desc *desc) +{ + if (!desc || !desc->platform_ops) + return -EINVAL; + + if (!desc->platform_ops->remove) + return -ENOSYS; + + return desc->platform_ops->remove(desc); +} + +/** + * @brief Start a timer. + * @param [in] desc - Pointer to the device handler. + * @return 0 in case of success, negative error code otherwise + */ +int32_t timer_start(struct timer_desc *desc) +{ + if (!desc || !desc->platform_ops) + return -EINVAL; + + if (!desc->platform_ops->start) + return -ENOSYS; + + return desc->platform_ops->start(desc); +} + +/** + * @brief Stop a timer from counting. + * @param [in] desc - Pointer to the device handler. + * @return 0 in case of success, negative error code otherwise + */ +int32_t timer_stop(struct timer_desc *desc) +{ + if (!desc || !desc->platform_ops) + return -EINVAL; + + if (!desc->platform_ops->stop) + return -ENOSYS; + + return desc->platform_ops->stop(desc); +} + +/** + * @brief Get the value of the counter register for the timer. + * @param [in] desc - Pointer to the device handler. + * @param [out] counter - Pointer to the counter value. + * @return 0 in case of success, error code otherwise. + */ +int32_t timer_counter_get(struct timer_desc *desc, + uint32_t *counter) +{ + if (!desc || !desc->platform_ops || !counter) + return -EINVAL; + + if (!desc->platform_ops->counter_get) + return -ENOSYS; + + return desc->platform_ops->counter_get(desc, counter); +} + +/** + * @brief Set the timer counter register value. + * @param [in] desc - Pointer to the device handler. + * @param [in] new_val - The new value of the counter register. + * @return 0 in case of success, error code otherwise. + */ +int32_t timer_counter_set(struct timer_desc *desc, uint32_t new_val) +{ + if (!desc || !desc->platform_ops) + return -EINVAL; + + if (!desc->platform_ops->counter_set) + return -ENOSYS; + + return desc->platform_ops->counter_set(desc, new_val); +} + +/** + * @brief Get the timer clock frequency. + * @param [in] desc - Pointer to the device handler. + * @param [out] freq_hz - The value in Hz of the timer clock. + * @return 0 in case of success, error code otherwise. + */ +int32_t timer_count_clk_get(struct timer_desc *desc, + uint32_t *freq_hz) +{ + if (!desc || !desc->platform_ops || !freq_hz) + return -EINVAL; + + if (!desc->platform_ops->count_clk_get) + return -ENOSYS; + + return desc->platform_ops->count_clk_get(desc, freq_hz); +} + +/** + * @brief Set the timer clock frequency. + * @param [in] desc - Pointer to the device handler. + * @param [in] freq_hz - The value in Hz of the new timer clock. + * @return 0 in case of success, error code otherwise. + */ +int32_t timer_count_clk_set(struct timer_desc *desc, + uint32_t freq_hz) +{ + if (!desc || !desc->platform_ops) + return -EINVAL; + + if (!desc->platform_ops->count_clk_set) + return -ENOSYS; + + return desc->platform_ops->count_clk_set(desc, freq_hz); +} + +/** + * @brief Get the elapsed time in nsec for the timer. + * @param [in] desc - Pointer to the device handler. + * @param [in] elapsed_time - The elapsed time in nsec. + * @return 0 in case of success, error code otherwise. + */ +int32_t timer_get_elapsed_time_nsec(struct timer_desc *desc, + uint64_t *elapsed_time) +{ + if (!desc || !desc->platform_ops) + return -EINVAL; + + if (!desc->platform_ops->get_elapsed_time_nsec) + return -ENOSYS; + + return desc->platform_ops->get_elapsed_time_nsec(desc, elapsed_time); +} diff --git a/df_datalink/src/drivers/api/trng.c b/df_datalink/src/drivers/api/trng.c new file mode 100644 index 0000000..1f3827a --- /dev/null +++ b/df_datalink/src/drivers/api/trng.c @@ -0,0 +1,111 @@ +/***************************************************************************//** + * @file trng.c + * @brief Implementation of the TRNG Interface + * @author Antoniu Miclaus (antoniu.miclaus@analog.com) +******************************************************************************** + * Copyright 2023(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include +#include "trng.h" +#include +#include "error.h" + +/******************************************************************************/ +/************************ Functions Definitions *******************************/ +/******************************************************************************/ + +/** + * @brief Initialize the TRNG. + * @param desc - The TRNG descriptor. + * @param param - The structure that contains the TRNG parameters. + * @return 0 in case of success, -1 otherwise. + */ +int trng_init(struct trng_desc **desc, + const struct trng_init_param *param) +{ + int ret; + + if (!param || !param->platform_ops) + return -EINVAL; + + if (!param->platform_ops->init) + return -ENOSYS; + + ret = param->platform_ops->init(desc, param); + if (ret) + return ret; + + (*desc)->platform_ops = param->platform_ops; + + return 0; +} + +/** + * @brief Free the resources allocated by trng_init(). + * @param desc - The TRNG descriptor. + * @return 0 in case of success, -1 otherwise. + */ +int trng_remove(struct trng_desc *desc) +{ + if (!desc || !desc->platform_ops) + return -EINVAL; + + if (!desc->platform_ops->remove) + return -ENOSYS; + + return desc->platform_ops->remove(desc); +} + +/** + * @brief Fill buffer with rng data. + * @param desc - The TRNG descriptor. + * @param buff - Buffer to be filled + * @param len - Size of the buffer + * @return 0 in case of success, -1 otherwise. + */ +int trng_fill_buffer(struct trng_desc *desc, uint8_t *buff, + uint32_t len) +{ + if (!desc || !desc->platform_ops) + return -EINVAL; + + if (!desc->platform_ops->fill_buffer) + return -ENOSYS; + + return desc->platform_ops->fill_buffer(desc, buff, len); +} diff --git a/df_datalink/src/drivers/axi_core/axi_dmac/axi_dmac.c b/df_datalink/src/drivers/axi_core/axi_dmac/axi_dmac.c new file mode 100644 index 0000000..885fc74 --- /dev/null +++ b/df_datalink/src/drivers/axi_core/axi_dmac/axi_dmac.c @@ -0,0 +1,547 @@ +/******************************************************************************* + * @file axi_dmac.c + * @brief Driver for the Analog Devices AXI-DMAC core. + * @author DBogdan (dragos.bogdan@analog.com) +******************************************************************************** + * Copyright 2018(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include +#include +#include +#include +#include "axi_io.h" +#include "error.h" +#include "delay.h" +#include "axi_dmac.h" + +/******************************************************************************* + * @brief ISR for dev to mem DMA transfer. It computes the next transfer params, + * if any, and sets the transfer structure fields accordingly. + * + * @param instance - the instance that triggered the ISR. + * + * @return None. +*******************************************************************************/ +void axi_dmac_dev_to_mem_isr(void *instance) +{ + struct axi_dmac *dmac = (struct axi_dmac *)instance; + uint32_t burst_size; + uint32_t reg_val; + + /* Get interrupt sources and clear interrupts. */ + axi_dmac_read(dmac, AXI_DMAC_REG_IRQ_PENDING, ®_val); + axi_dmac_write(dmac, AXI_DMAC_REG_IRQ_PENDING, reg_val); + + if (reg_val & AXI_DMAC_IRQ_SOT) { + if (dmac->remaining_size) { + /* See if remaining size is bigger than max transfer size and + * set burst size. */ + if (dmac->remaining_size > dmac->max_length) { + burst_size = dmac->max_length; + } else { + burst_size = dmac->remaining_size - 1; + } + + /* The current transfer was started; set up the new one. */ + axi_dmac_write(dmac, AXI_DMAC_REG_DEST_ADDRESS, dmac->next_dest_addr); + axi_dmac_write(dmac, AXI_DMAC_REG_DEST_STRIDE, 0x0); + axi_dmac_write(dmac, AXI_DMAC_REG_X_LENGTH, burst_size); + axi_dmac_write(dmac, AXI_DMAC_REG_Y_LENGTH, 0x0); + + /* Compute size of the next transfer. */ + dmac->remaining_size = dmac->remaining_size - (burst_size + 1); + /* Address must advance with +1 since the DMAC writes X_LENGTH+1. */ + dmac->next_dest_addr = dmac->next_dest_addr + (burst_size + 1); + + /* Trigger the next transfer. */ + axi_dmac_write(dmac, AXI_DMAC_REG_TRANSFER_SUBMIT, AXI_DMAC_TRANSFER_SUBMIT); + } + } + if (reg_val & AXI_DMAC_IRQ_EOT) { + if (!dmac->remaining_size) { + dmac->transfer.transfer_done = true; + dmac->next_dest_addr = 0; + } + } +} + +/******************************************************************************* + * @brief ISR for mem DMA to dev transfer. It computes the next transfer params, + * if any, and sets the transfer structure fields accordingly. + * + * @param instance - the instance that triggered the ISR. + * + * @return None. +*******************************************************************************/ +void axi_dmac_mem_to_dev_isr(void *instance) +{ + struct axi_dmac *dmac = (struct axi_dmac *)instance; + uint32_t burst_size; + uint32_t reg_val; + + /* Get interrupt sources and clear interrupts. */ + axi_dmac_read(dmac, AXI_DMAC_REG_IRQ_PENDING, ®_val); + axi_dmac_write(dmac, AXI_DMAC_REG_IRQ_PENDING, reg_val); + + if (reg_val & AXI_DMAC_IRQ_SOT) { + if ((dmac->transfer.cyclic == CYCLIC) && + (dmac->next_src_addr >= (dmac->init_addr + dmac->transfer.size - 1))) { + dmac->remaining_size = dmac->transfer.size; + dmac->next_src_addr = dmac->init_addr; + } + + if (dmac->remaining_size) { + /** See if remaining size is bigger than max transfer size and + * set burst size. */ + if (dmac->remaining_size > dmac->max_length) { + burst_size = dmac->max_length; + } else { + burst_size = dmac->remaining_size - 1; + } + + /* The current transfer was started; set up the new one. */ + axi_dmac_write(dmac, AXI_DMAC_REG_SRC_ADDRESS, dmac->next_src_addr); + axi_dmac_write(dmac, AXI_DMAC_REG_SRC_STRIDE, 0x0); + axi_dmac_write(dmac, AXI_DMAC_REG_X_LENGTH, burst_size); + axi_dmac_write(dmac, AXI_DMAC_REG_Y_LENGTH, 0x0); + + /* Compute parameters for the next transfer. */ + dmac->remaining_size = dmac->remaining_size - (burst_size + 1); + /* Address must advance with +1 since the DMAC writes X_LENGTH+1. */ + dmac->next_src_addr = dmac->next_src_addr + (burst_size + 1); + + /* Trigger the current transfer */ + axi_dmac_write(dmac, AXI_DMAC_REG_TRANSFER_SUBMIT, AXI_DMAC_TRANSFER_SUBMIT); + } + } + if (reg_val & AXI_DMAC_IRQ_EOT) { + if ((!dmac->remaining_size) && (dmac->transfer.cyclic != CYCLIC)) { + dmac->transfer.transfer_done = true; + dmac->next_src_addr = 0; + } + } +} + +/******************************************************************************* + * @brief ISR for mem DMA to mem DMA transfer. It computes the next transfer + * params, if any, and sets the transfer structure fields accordingly. + * + * @param instance - the instance that triggered the ISR. + * + * @return None. +*******************************************************************************/ +void axi_dmac_mem_to_mem_isr(void *instance) +{ + struct axi_dmac *dmac = (struct axi_dmac *)instance; + uint32_t burst_size; + uint32_t reg_val; + + /* Get interrupt sources and clear interrupts. */ + axi_dmac_read(dmac, AXI_DMAC_REG_IRQ_PENDING, ®_val); + axi_dmac_write(dmac, AXI_DMAC_REG_IRQ_PENDING, reg_val); + + if (reg_val & AXI_DMAC_IRQ_SOT) { + if (dmac->remaining_size) { + /** See if remaining size is bigger than max transfer size and + * set burst size. */ + if (dmac->remaining_size > dmac->max_length) { + burst_size = dmac->max_length; + } else { + burst_size = dmac->remaining_size - 1; + } + + /* The current transfer was started; set up the new one. */ + axi_dmac_write(dmac, AXI_DMAC_REG_SRC_ADDRESS, dmac->next_src_addr); + axi_dmac_write(dmac, AXI_DMAC_REG_SRC_STRIDE, 0x0); + axi_dmac_write(dmac, AXI_DMAC_REG_DEST_ADDRESS, dmac->next_dest_addr); + axi_dmac_write(dmac, AXI_DMAC_REG_DEST_STRIDE, 0x0); + axi_dmac_write(dmac, AXI_DMAC_REG_X_LENGTH, burst_size); + axi_dmac_write(dmac, AXI_DMAC_REG_Y_LENGTH, 0x0); + + /* Compute parameters for the next transfer. */ + dmac->remaining_size = dmac->remaining_size - (burst_size + 1); + /* Address must advance with +1 since the DMAC writes X_LENGTH+1. */ + dmac->next_src_addr = dmac->next_src_addr + (burst_size + 1); + dmac->next_dest_addr = dmac->next_dest_addr + (burst_size + 1); + + /* If transfer finished advance src address so that transfer_done can be set*/ + if (!dmac->remaining_size) { + dmac->next_src_addr = dmac->next_src_addr + (burst_size + 1); + } + + /* Trigger the current transfer */ + axi_dmac_write(dmac, AXI_DMAC_REG_TRANSFER_SUBMIT, AXI_DMAC_TRANSFER_SUBMIT); + } + } + if (reg_val & AXI_DMAC_IRQ_EOT) { + if (!dmac->remaining_size) { + if(dmac->next_src_addr > (dmac->init_addr + dmac->transfer.size)) { + dmac->transfer.transfer_done = true; + dmac->next_src_addr = 0; + dmac->next_dest_addr = 0; + } + } + } +} + +/******************************************************************************* + * @brief Wrapper for AXI IO through UIO/devmem read function. + * + * @param dmac - DMAC istance containing UIO index (/dev/uioX)/base address. + * @param reg_addr - Address to read from. + * @param reg_data - Location where read data will be stored. + * + * @return 0 - success. +*******************************************************************************/ +int32_t axi_dmac_read(struct axi_dmac *dmac, + uint32_t reg_addr, + uint32_t *reg_data) +{ + axi_io_read(dmac->base, reg_addr, reg_data); + + return 0; +} + +/******************************************************************************* + * @brief Wrapper for AXI IO through UIO/devmem wrrite function. + * + * @param dmac - DMAC istance containing UIO index (/dev/uioX)/base address. + * @param reg_addr - Address to write to. + * @param reg_data - Data to be written. + * + * @return 0 - success. +*******************************************************************************/ +int32_t axi_dmac_write(struct axi_dmac *dmac, + uint32_t reg_addr, + uint32_t reg_data) +{ + axi_io_write(dmac->base, reg_addr, reg_data); + + return 0; +} + +/******************************************************************************* + * @brief Get transfer status (value of dmac->transfer.transfer_done flag). + * + * @note This function should not be used if DMA IRQ is not used. + * + * @param dmac - DMAC istance. + * @param rdy - Transfer status (0 - not ready, 1 - ready). + * + * @return 0 - success. +*******************************************************************************/ +int32_t axi_dmac_is_transfer_ready(struct axi_dmac *dmac, bool *rdy) +{ + *rdy = dmac->transfer.transfer_done; + + return 0; +} + +/******************************************************************************* + * @brief Get DMAC capabilities. + * + * @param dmac - DMAC istance. + * + * @return 0 for success, -1 in case of failure. +*******************************************************************************/ +static int32_t axi_dmac_detect_caps(struct axi_dmac *dmac) +{ + uint32_t reg_val, initial_reg_val = 0; + uint32_t src_mem_mapped = 0; + uint32_t dest_mem_mapped = 0; + + dmac->max_length = -1; + dmac->direction = INVALID_DIR; + + /* Check if HW cyclic possible */ + axi_dmac_read(dmac, AXI_DMAC_REG_FLAGS, &initial_reg_val); + axi_dmac_write(dmac, AXI_DMAC_REG_FLAGS, DMA_CYCLIC); + axi_dmac_read(dmac, AXI_DMAC_REG_FLAGS, ®_val); + if (reg_val == DMA_CYCLIC) + dmac->hw_cyclic = true; + /* Restore initial value for AXI_DMAC_REG_FLAGS register */ + axi_dmac_write(dmac, AXI_DMAC_REG_FLAGS, initial_reg_val); + + /* Get maximum burst size and set value. */ + axi_dmac_write(dmac, AXI_DMAC_REG_X_LENGTH, dmac->max_length); + axi_dmac_read(dmac, AXI_DMAC_REG_X_LENGTH, &dmac->max_length); + + /* Get transfer direction and set value. */ + axi_dmac_write(dmac, AXI_DMAC_REG_DEST_ADDRESS, 0xffffffff); + axi_dmac_read(dmac, AXI_DMAC_REG_DEST_ADDRESS, &dest_mem_mapped); + axi_dmac_write(dmac, AXI_DMAC_REG_SRC_ADDRESS, 0xffffffff); + axi_dmac_read(dmac, AXI_DMAC_REG_SRC_ADDRESS, &src_mem_mapped); + + if (dest_mem_mapped && !src_mem_mapped) { + dmac->direction = DMA_DEV_TO_MEM; + } else if (!dest_mem_mapped && src_mem_mapped) { + dmac->direction = DMA_MEM_TO_DEV; + } else if (dest_mem_mapped && src_mem_mapped) { + dmac->direction = DMA_MEM_TO_MEM; + } else { + printf("Destination and source memory-mapped interfaces not supported.\n"); + return -1; + } + return 0; +} + +/******************************************************************************* + * @brief Get transfer status (value of dmac->transfer.transfer_done flag). + * + * @param dmac_core - DMAC istance. + * @param init - Structure containing initializing data. + * + * @return 0 for success, -1 in case of failure. +*******************************************************************************/ +int32_t axi_dmac_init(struct axi_dmac **dmac_core, + const struct axi_dmac_init *init) +{ + struct axi_dmac *dmac; + + dmac = (struct axi_dmac *)calloc(1, sizeof(*dmac)); + if (!dmac) + return -1; + + dmac->name = init->name; + dmac->base = init->base; + dmac->irq_option = init->irq_option; + + *dmac_core = dmac; + + int32_t status = axi_dmac_detect_caps(*dmac_core); + if (status < 0) + return -1; + + return 0; +} + +/******************************************************************************* + * @brief Remove the DMAC instance. + * + * @param dmac - DMAC istance. + * + * @return 0 for success, -1 in case of failure. +*******************************************************************************/ +int32_t axi_dmac_remove(struct axi_dmac *dmac) +{ + if (!dmac) + return -1; + + free(dmac); + + return 0; +} + +/******************************************************************************* + * @brief Start a DMA transfer. + * + * @param dmac - DMAC istance. + * @param dma_transfer - Structure containing transfer details. + * + * @return 0 for success, -1 in case of failure. +*******************************************************************************/ +int32_t axi_dmac_transfer_start(struct axi_dmac *dmac, + struct axi_dma_transfer *dma_transfer) +{ + uint32_t reg_val, burst_size; + + if (dma_transfer->size == 0) + return 0; /* Nothing to do. */ + + /* Set current transfer parameters. */ + dmac->transfer.size = dma_transfer->size; + dmac->transfer.cyclic = dma_transfer->cyclic; + dmac->transfer.dest_addr = dma_transfer->dest_addr; + dmac->transfer.src_addr = dma_transfer->src_addr; + + dmac->remaining_size = dma_transfer->size; + dmac->next_dest_addr = dma_transfer->dest_addr; + dmac->next_src_addr = dma_transfer->src_addr; + + /* If HW cyclic transfer selected and not available, show error */ + /* HW cyclic transfer available only for MEM to DEV transfers. */ + if ((!dmac->hw_cyclic) && (dma_transfer->cyclic == CYCLIC)) { + printf("Transfer mode not supported!\n"); + return -1; + } + + /* Cyclic transfers not possible for DEV_TO_MEM and MEM_TO_MEM transmissions. */ + if ((dmac->direction == DMA_DEV_TO_MEM) + || (dmac->direction == DMA_MEM_TO_MEM)) { + if (dma_transfer->cyclic == CYCLIC) { + printf("Transfer mode not supported!\n"); + return -1; + } + } + + /* Cyclic transfers set to HW or SW depending on size for MEM to DEV. */ + if ((dmac->direction == DMA_MEM_TO_DEV) && (dmac->transfer.cyclic == CYCLIC)) { + if ((dmac->remaining_size - 1) <= dmac->max_length) { + if (dmac->hw_cyclic) { + axi_dmac_read(dmac, AXI_DMAC_REG_FLAGS, ®_val); + reg_val = reg_val | DMA_CYCLIC; + axi_dmac_write(dmac, AXI_DMAC_REG_FLAGS, reg_val); + } + } else { + axi_dmac_read(dmac, AXI_DMAC_REG_FLAGS, ®_val); + reg_val = reg_val & ~DMA_CYCLIC; + axi_dmac_write(dmac, AXI_DMAC_REG_FLAGS, reg_val); + } + } + + /* Enable DMA if not already enabled. */ + axi_dmac_read(dmac, AXI_DMAC_REG_CTRL, ®_val); + if (!(reg_val & AXI_DMAC_CTRL_ENABLE)) { + axi_dmac_write(dmac, AXI_DMAC_REG_CTRL, 0x0); + axi_dmac_write(dmac, AXI_DMAC_REG_CTRL, AXI_DMAC_CTRL_ENABLE); + axi_dmac_write(dmac, AXI_DMAC_REG_IRQ_MASK, 0x0); + } + + axi_dmac_read(dmac, AXI_DMAC_REG_TRANSFER_SUBMIT, ®_val); + /* If we don't have a start of transfer then start compute + * values and trigger next transfer. */ + if (!(reg_val & AXI_DMAC_QUEUE_FULL)) { + switch (dmac->direction) { + case DMA_DEV_TO_MEM: + dmac->init_addr = dmac->next_dest_addr; + axi_dmac_write(dmac, AXI_DMAC_REG_DEST_ADDRESS, dmac->next_dest_addr); + axi_dmac_write(dmac, AXI_DMAC_REG_DEST_STRIDE, 0x0); + break; + case DMA_MEM_TO_DEV: + dmac->init_addr = dmac->next_src_addr; + axi_dmac_write(dmac, AXI_DMAC_REG_SRC_ADDRESS, dmac->next_src_addr); + axi_dmac_write(dmac, AXI_DMAC_REG_SRC_STRIDE, 0x0); + break; + case DMA_MEM_TO_MEM: + dmac->init_addr = dmac->next_src_addr; + axi_dmac_write(dmac, AXI_DMAC_REG_DEST_ADDRESS, dmac->next_dest_addr); + axi_dmac_write(dmac, AXI_DMAC_REG_DEST_STRIDE, 0x0); + axi_dmac_write(dmac, AXI_DMAC_REG_SRC_ADDRESS, dmac->next_src_addr); + axi_dmac_write(dmac, AXI_DMAC_REG_SRC_STRIDE, 0x0); + break; + default: + return -1; /* Other directions are not supported yet. */ + } + + /* Compute the burst size. */ + if (dmac->remaining_size > dmac->max_length) { + burst_size = dmac->max_length; + } else { + burst_size = dmac->remaining_size - 1; + } + + /* Compute next address (src or dest, or both, depending on type of transfer). */ + switch (dmac->direction) { + case DMA_DEV_TO_MEM: + dmac->next_dest_addr = dmac->next_dest_addr + (burst_size + 1); + break; + case DMA_MEM_TO_DEV: + dmac->next_src_addr = dmac->next_src_addr + (burst_size + 1); + break; + case DMA_MEM_TO_MEM: + dmac->next_dest_addr = dmac->next_dest_addr + (burst_size + 1); + dmac->next_src_addr = dmac->next_src_addr + (burst_size + 1); + break; + default: + return -1; + } + + /* Compute remaining size. */ + dmac->remaining_size = dmac->remaining_size - (burst_size + 1); + + /* Specify the length of the transfer and trigger transfer. */ + axi_dmac_write(dmac, AXI_DMAC_REG_X_LENGTH, burst_size); + axi_dmac_write(dmac, AXI_DMAC_REG_Y_LENGTH, 0x0); + axi_dmac_write(dmac, AXI_DMAC_REG_TRANSFER_SUBMIT, AXI_DMAC_TRANSFER_SUBMIT); + } else { + return -1; + } + + return 0; +} + +/******************************************************************************* + * @brief Wait for DMA transfer to be completed. + * + * @param dmac - DMAC istance. + * @param timeout_ms - Number of ms to wait for completion of transfer. + * + * @return 0 for success, -1 in case trasnfer not completed in specified time. +*******************************************************************************/ +int32_t axi_dmac_transfer_wait_completion(struct axi_dmac *dmac, + uint32_t timeout_ms) +{ + uint32_t timeout = 0; + uint32_t reg_val = 0; + + if (dmac->irq_option == IRQ_ENABLED) { + while (!dmac->transfer.transfer_done) { + timeout++; + mdelay(1); + if (timeout == timeout_ms) { + printf("Error transferring data using DMA.\n"); + return -1; + } + } + } else if (dmac->irq_option == IRQ_DISABLED) { + axi_dmac_read(dmac, AXI_DMAC_REG_IRQ_PENDING, ®_val); + while (reg_val != (AXI_DMAC_IRQ_SOT | AXI_DMAC_IRQ_EOT)) { + timeout++; + mdelay(1); + if (timeout == timeout_ms) { + printf("Error transferring data using DMA.\n"); + return -1; + } + axi_dmac_read(dmac, AXI_DMAC_REG_IRQ_PENDING, ®_val); + } + } + + return 0; +} + +/******************************************************************************* + * @brief Stop a DMA transfer. + * + * @param dmac - DMAC istance. + * + * @return None +*******************************************************************************/ +void axi_dmac_transfer_stop(struct axi_dmac *dmac) +{ + axi_dmac_write(dmac, AXI_DMAC_REG_CTRL, AXI_DMAC_CTRL_DISABLE); +} diff --git a/df_datalink/src/drivers/axi_core/axi_dmac/axi_dmac.h b/df_datalink/src/drivers/axi_core/axi_dmac/axi_dmac.h new file mode 100644 index 0000000..6092a5b --- /dev/null +++ b/df_datalink/src/drivers/axi_core/axi_dmac/axi_dmac.h @@ -0,0 +1,156 @@ +/***************************************************************************//** + * @file axi_dmac.h + * @brief Driver for the Analog Devices AXI-DMAC core. + * @author DBogdan (dragos.bogdan@analog.com) +******************************************************************************** + * Copyright 2018(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ +#ifndef AXI_DMAC_H_ +#define AXI_DMAC_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include +#include "util.h" + +/******************************************************************************/ +/********************** Macros and Constants Definitions **********************/ +/******************************************************************************/ +#define AXI_DMAC_REG_IRQ_MASK 0x80 +#define AXI_DMAC_REG_IRQ_PENDING 0x84 +#define AXI_DMAC_IRQ_SOT BIT(0) +#define AXI_DMAC_IRQ_EOT BIT(1) + +#define AXI_DMAC_REG_INTF_DESC 0x010 +#define AXI_DMAC_DMA_TYPE_DEST GENMASK(5,4) +#define AXI_DMAC_DMA_TYPE_SRC GENMASK(13,12) +//Define macro for src and dest + +#define AXI_DMAC_REG_CTRL 0x400 +#define AXI_DMAC_CTRL_ENABLE BIT(0) +#define AXI_DMAC_CTRL_DISABLE 0u +#define AXI_DMAC_CTRL_PAUSE BIT(1) + +#define AXI_DMAC_REG_TRANSFER_ID 0x404 +#define AXI_DMAC_REG_TRANSFER_SUBMIT 0x408 +#define AXI_DMAC_TRANSFER_SUBMIT BIT(0) +#define AXI_DMAC_QUEUE_FULL BIT(0) +#define AXI_DMAC_REG_FLAGS 0x40c +#define AXI_DMAC_REG_DEST_ADDRESS 0x410 +#define AXI_DMAC_REG_SRC_ADDRESS 0x414 +#define AXI_DMAC_REG_X_LENGTH 0x418 +#define AXI_DMAC_REG_Y_LENGTH 0x41c +#define AXI_DMAC_REG_DEST_STRIDE 0x420 +#define AXI_DMAC_REG_SRC_STRIDE 0x424 +#define AXI_DMAC_REG_TRANSFER_DONE 0x428 + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ +enum use_irq { + IRQ_DISABLED = 0, + IRQ_ENABLED = 1 +}; + +enum dma_direction { + INVALID_DIR = 0, + DMA_DEV_TO_MEM = 1, + DMA_MEM_TO_DEV = 2, + DMA_MEM_TO_MEM = 3 +}; + +enum dma_flags { + DMA_CYCLIC = 1, + DMA_LAST = 2, + DMA_PARTIAL_REPORTING_EN = 4 +}; + +// Could be transformed to a bool +enum cyclic_transfer { + NO = 0, + CYCLIC = 1 +}; + +struct axi_dma_transfer { + uint32_t size; + volatile bool transfer_done; + enum cyclic_transfer cyclic; + uint32_t src_addr; + uint32_t dest_addr; +}; + +struct axi_dmac { + const char *name; + uint32_t base; + enum use_irq irq_option; + enum dma_direction direction; + bool hw_cyclic; + uint32_t max_length; + volatile struct axi_dma_transfer transfer; + //Current sub-transfer properties + uint32_t init_addr; + uint32_t remaining_size; + uint32_t next_src_addr; + uint32_t next_dest_addr; +}; + +struct axi_dmac_init { + const char *name; + uint32_t base; + enum use_irq irq_option; +}; + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ +void axi_dmac_dev_to_mem_isr(void *instance); +void axi_dmac_mem_to_dev_isr(void *instance); +void axi_dmac_mem_to_mem_isr(void *instance); +void axi_dmac_write_isr(void *instance); +int32_t axi_dmac_read(struct axi_dmac *dmac, uint32_t reg_addr, + uint32_t *reg_data); +int32_t axi_dmac_write(struct axi_dmac *dmac, uint32_t reg_addr, + uint32_t reg_data); +int32_t axi_dmac_is_transfer_ready(struct axi_dmac *dmac, bool *rdy); +int32_t axi_dmac_init(struct axi_dmac **adc_core, + const struct axi_dmac_init *init); +int32_t axi_dmac_remove(struct axi_dmac *dmac); +int32_t axi_dmac_transfer_start(struct axi_dmac *dmac, + struct axi_dma_transfer *dma_transfer); +int32_t axi_dmac_transfer_wait_completion(struct axi_dmac *dmac, + uint32_t timeout_ms); +void axi_dmac_transfer_stop(struct axi_dmac *dmac); + +#endif diff --git a/df_datalink/src/drivers/axi_core/spi_engine/spi_engine.c b/df_datalink/src/drivers/axi_core/spi_engine/spi_engine.c new file mode 100644 index 0000000..7e299c3 --- /dev/null +++ b/df_datalink/src/drivers/axi_core/spi_engine/spi_engine.c @@ -0,0 +1,997 @@ +/******************************************************************************* + * @file spi_engine.c + * @brief Core implementation of the SPI Engine Driver. + * @author Sergiu Cuciurean (sergiu.cuciurean@analog.com) +******************************************************************************** + * Copyright 2019(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +/* In debug mode the printf function used in displaying the messages is causing +significant delays */ +//#define DEBUG_LEVEL 2 + +#include +#include +#include +#include +#include +#include + +#include "axi_io.h" +#include "error.h" +#include "spi_engine.h" + +/** + * @brief Spi engine platform specific SPI platform ops structure + */ +const struct spi_platform_ops spi_eng_platform_ops = { + .init = &spi_engine_init, + .write_and_read = &spi_engine_write_and_read, + .write_and_read_3wire = &spi_engine_write_and_read_3wire, + .remove = &spi_engine_remove +}; + +/******************************************************************************/ +/***************************** Static variables *******************************/ +/******************************************************************************/ + +/** + * @brief Static variable used to sync transfers + * + */ +static uint8_t _sync_id = 0x01; + +/******************************************************************************/ +/************************** Functions Implementation **************************/ +/******************************************************************************/ + +/** + * @brief Write SPI Engine's axi registers + * + * @param desc Decriptor containing SPI Engine's parameters + * @param reg_addr The address of the SPI Engine's axi register where the data + * will be written + * @param reg_data Data that will be written + * @return int32_t This function allways returns SUCCESS + */ +int32_t spi_engine_write(struct spi_engine_desc *desc, + uint32_t reg_addr, + uint32_t reg_data) +{ + axi_io_write(desc->spi_engine_baseaddr, reg_addr, reg_data); + + return SUCCESS; +} + +/** + * @brief Read SPI Engine's axi registers + * + * @param desc Decriptor containing SPI Engine's parameters + * @param reg_addr The address of the SPI Engine's axi register from where the + * data where the data will be read + * @param reg_data Pointer where the read that will be stored + * @return int32_t This function allways returns SUCCESS + */ +int32_t spi_engine_read(struct spi_engine_desc *desc, + uint32_t reg_addr, + uint32_t *reg_data) +{ + axi_io_read(desc->spi_engine_baseaddr, reg_addr, reg_data); + return SUCCESS; +} + +/** + * @brief Set width of the transferred word over SPI + * + * @param desc Decriptor containing SPI interface parameters + * @param data_width The desired data width + * The supported values are: + * - 8 + * - 16 + * - 24 + * - 32 + */ +int32_t spi_engine_set_transfer_width(struct spi_desc *desc, + uint8_t data_width) +{ + struct spi_engine_desc *desc_extra; + + desc_extra = desc->extra; + + if (data_width > desc_extra->max_data_width) + desc_extra->data_width = desc_extra->max_data_width; + else + desc_extra->data_width = data_width; + + return SUCCESS; +} + +/** + * @brief Set SPI engine clock frequency + * + * @param desc Decriptor containing SPI Engine's parameters + * @param speed_hz SPI engine transfer speed + */ +void spi_engine_set_speed(struct spi_desc *desc, + uint32_t speed_hz) +{ + struct spi_engine_desc *desc_extra; + + desc_extra = desc->extra; + + desc_extra->clk_div = desc_extra->ref_clk_hz / + (2 * speed_hz) - 1; +} + +/** + * @brief Set the number of words transferred in a single transaction + * + * @param desc Decriptor containing SPI Engine's parameters + * @param bytes_number The number of bytes to be converted + * @return uint8_t A number of words in which bytes_number can be grouped + */ +static uint8_t spi_get_words_number(struct spi_engine_desc *desc, + uint8_t bytes_number) +{ + uint8_t xfer_word_len; + uint8_t words_number; + + xfer_word_len = desc->data_width / 8; + words_number = bytes_number / xfer_word_len; + + if ((bytes_number % xfer_word_len) != 0) + words_number++; + + return words_number; +} + +/** + * @brief Get the word length in bytes + * + * @param desc Decriptor containing SPI Engine's parameters + * @return uint8_t Number of bytes that fit in one word + */ +static uint8_t spi_get_word_length(struct spi_engine_desc *desc) +{ + uint8_t word_length; + + word_length = desc->data_width / 8; + + return word_length; +} + +/** + * @brief Compute the prescaler used to set the sleep period. + * + * @param desc Decriptor containing SPI interface parameters + * @param sleep_time_ns The amount of time where the transfer hangs + * @param sleep_div Clock prescaler + * @return int32_t This function allways returns SUCCESS + */ +static int32_t spi_get_sleep_div(struct spi_desc *desc, + uint32_t sleep_time_ns, + uint32_t *sleep_div) +{ + struct spi_engine_desc *eng_desc; + + eng_desc = desc->extra; + + /* + * Engine Wiki: + * + * The frequency of the SCLK signal is derived from the + * module clock frequency using the following formula: + * f_sclk = f_clk / ((div + 1) * 2) + */ + + *sleep_div = (desc->max_speed_hz / 1000000 * sleep_time_ns / 1000) / + ((eng_desc->clk_div + 1) * 2) - 1; + + return SUCCESS; +} + +/** + * @brief Create a new commands queue used in a spi transfer + * + * @param fifo Command buffer, usually used in fifo mode + * @param cmd Command with which the buffer will be initiated + * @return int32_t Failure if the memory allocation failed + */ +static int32_t spi_engine_queue_new_cmd(struct spi_engine_cmd_queue **fifo, + uint32_t cmd) +{ + struct spi_engine_cmd_queue *local_fifo; + + local_fifo = (spi_engine_cmd_queue*)malloc(sizeof(*local_fifo)); + + if(!local_fifo) + return FAILURE; + + local_fifo->cmd = cmd; + local_fifo->next = NULL; + *fifo = local_fifo; + + return SUCCESS; +} + +/** + * @brief Add a command at the end of an existing queue + * + * @param fifo Command buffer, usually used in fifo mode + * @param cmd Command to be added + */ +static void spi_engine_queue_add_cmd(struct spi_engine_cmd_queue **fifo, + uint32_t cmd) +{ + struct spi_engine_cmd_queue *to_add = NULL; + struct spi_engine_cmd_queue *local_fifo; + + local_fifo = *fifo; + while (local_fifo->next != NULL) { + // Get the last element + local_fifo = local_fifo->next; + } + + // Create a new element + spi_engine_queue_new_cmd(&to_add, cmd); + // Add as the next element + local_fifo->next = to_add; +} + +/** + * @brief Add a command at the beginning of an existing queue + * + * @param fifo Command buffer, usually used in fifo mode + * @param cmd Command to be added + */ +static void spi_engine_queue_append_cmd(struct spi_engine_cmd_queue **fifo, + uint32_t cmd) +{ + struct spi_engine_cmd_queue *to_add = NULL; + + // Create a new element + spi_engine_queue_new_cmd(&to_add, cmd); + // Interchange the addresses + to_add->next = *fifo; + *fifo = to_add; +} + + +/** + * @brief Get the command from the beginning of the queue + * + * @param fifo Command buffer, usually used in fifo mode + * @param cmd Value of the command that was extracted + * @return int32_t Return FAILURE if the queue is empty + */ +static int32_t spi_engine_queue_get_cmd(struct spi_engine_cmd_queue **fifo, + uint32_t *cmd) +{ + struct spi_engine_cmd_queue *local_fifo; + + if (!*fifo) + return FAILURE; + + local_fifo = *fifo; + *cmd = local_fifo->cmd; + if ((*fifo)->next) { + *fifo = local_fifo->next; + free(local_fifo); + } else { + free(*fifo); + *fifo = NULL; + } + + return SUCCESS; +} + +/** + * @brief Free the memory allocated by a queue + * + * @param fifo The queue that needs it's memory freed + * @return int32_t This function always returns SUCCESS + */ +static int32_t spi_engine_queue_free(struct spi_engine_cmd_queue **fifo) +{ + if(*fifo && (*fifo)->next) + spi_engine_queue_free(&(*fifo)->next); + if((*fifo) != NULL) { + free(*fifo); + *fifo = NULL; + } + + return SUCCESS; +} + +/** + * @brief Write the SPI engine's command fifo + * + * @param desc Decriptor containing SPI Engine's parameters + * @param cmd The command that will be written + * @return int32_t Returns FAILURE if the the axi transfer failed + */ +static int32_t spi_engine_write_cmd_reg(struct spi_engine_desc *desc, + uint32_t cmd) +{ + int32_t ret; + + /* Check if offload is enabled */ + if(desc->offload_config & (OFFLOAD_TX_EN | OFFLOAD_RX_EN)) { + ret = spi_engine_write(desc, + SPI_ENGINE_REG_OFFLOAD_CMD_MEM(0), + cmd); + + } else { + ret = spi_engine_write(desc, + SPI_ENGINE_REG_CMD_FIFO, + cmd); + } + + return ret; +} + +/** + * @brief Write a transfer command to the SPI engine's command fifo + * + * @param desc Decriptor containing SPI Engine's parameters + * @param read_write Read/Write operation flag + * @param bytes_number Number of bytes to transfer + * @return int32_t This function always returns SUCCESS + */ +static int32_t spi_engine_transfer(struct spi_engine_desc *desc, + uint8_t read_write, + uint8_t bytes_number) +{ + uint8_t words_number; + + words_number = spi_get_words_number(desc, bytes_number); + + desc->offload_tx_len += words_number; + + /* + * Engine Wiki: + * + * https://wiki.analog.com/resources/fpga/peripherals/spi_engine + * + * The words number is zero based + */ + + spi_engine_write_cmd_reg(desc, + SPI_ENGINE_CMD_TRANSFER(read_write, + words_number - 1)); + + return SUCCESS; +} + +/** + * @brief Change the state of the chip select port + * + * @param desc Decriptor containing SPI interface parameters + * @param assert Chip select state. + * The supported values are : + * -true (HIGH) + * -false (LOW) + */ +static void spi_engine_set_cs(struct spi_desc *desc, + bool assert) +{ + uint8_t mask; + struct spi_engine_desc *eng_desc; + + eng_desc = desc->extra; + + mask = 0xFF; + /* Switch the state only of the selected chip select */ + if (!assert) + mask ^= BIT(desc->chip_select); + + spi_engine_write_cmd_reg(eng_desc, + SPI_ENGINE_CMD_ASSERT(eng_desc->cs_delay, + mask)); +} + +/** + * @brief Add a delay between the engine commands + * + * @param desc Decriptor containing SPI interface parameters + * @param sleep_time_ns Number of nanoseconds to sleep between commands + */ +static void spi_gen_sleep_ns(struct spi_desc *desc, + uint32_t sleep_time_ns) +{ + uint32_t sleep_div; + struct spi_engine_desc *eng_desc; + + eng_desc = desc->extra; + + spi_get_sleep_div(desc, sleep_time_ns, &sleep_div); + + spi_engine_write_cmd_reg(eng_desc, SPI_ENGINE_CMD_SLEEP(sleep_div)); +} + +/** + * @brief Spi engine command interpreter + * + * @param desc Decriptor containing SPI interface parameters + * @param cmd Command to send to the engine + * @return int32_t - SUCCESS if the command is transferred + * - FAILURE if the command format is invalid + */ +static int32_t spi_engine_write_cmd(struct spi_desc *desc, + uint32_t cmd) +{ + uint8_t engine_command; + uint8_t parameter; + uint8_t modifier; + struct spi_engine_desc *desc_extra; + + desc_extra = desc->extra; + + engine_command = (cmd >> 12) & 0x0F; + modifier = (cmd >> 8) & 0x0F; + parameter = cmd & 0xFF; + + switch(engine_command) { + case SPI_ENGINE_INST_TRANSFER: + spi_engine_transfer(desc_extra, modifier, parameter); + break; + + case SPI_ENGINE_INST_ASSERT: + if(parameter == 0xFF) { + /* Set the CS HIGH */ + spi_engine_set_cs(desc, true); + } else if(parameter == 0x00) { + /* Set the CS LOW */ + spi_engine_set_cs(desc, false); + } + break; + + /* The SYNC and SLEEP commands got the same value but different + modifier */ + case SPI_ENGINE_INST_SYNC_SLEEP: + /* SYNC instruction */ + if(modifier == 0x00) { + spi_engine_write_cmd_reg(desc_extra, cmd); + } else if(modifier == 0x01) { + spi_gen_sleep_ns(desc, parameter); + } + break; + case SPI_ENGINE_INST_CONFIG: + spi_engine_write_cmd_reg(desc_extra, cmd); + + break; + + default: + + return FAILURE; + } + + return SUCCESS; +} + +/** + * @brief Prepare the command queue before sending it to the engine + * + * @param desc Decriptor containing SPI interface parameters + * @param msg Structure used to store the transfer messages + * @return int32_t This function always returns SUCCESS + */ +static int32_t spi_engine_compile_message(struct spi_desc *desc, + struct spi_engine_msg *msg) +{ + struct spi_engine_desc *desc_extra; + + desc_extra = desc->extra; + + /* Configure the prescaler */ + spi_engine_queue_append_cmd(&msg->cmds, + SPI_ENGINE_CMD_CONFIG( + SPI_ENGINE_CMD_REG_CLK_DIV, + desc_extra->clk_div)); + + /* Set the data transfer length */ + spi_engine_queue_append_cmd(&msg->cmds, + SPI_ENGINE_CMD_CONFIG( + SPI_ENGINE_CMD_DATA_TRANSFER_LEN, + desc_extra->data_width)); + /* + * Configure the spi mode : + * - 3 wire + * - CPOL + * - CPHA + */ + spi_engine_queue_append_cmd(&msg->cmds, + SPI_ENGINE_CMD_CONFIG( + SPI_ENGINE_CMD_REG_CONFIG, + desc->mode)); + + /* Add a sync command to signal that the transfer has finished */ + spi_engine_queue_add_cmd(&msg->cmds, SPI_ENGINE_CMD_SYNC(_sync_id)); + + return SUCCESS; +} + +/** + * @brief Initiate a spi transfer (Blocking) + * + * @param desc Decriptor containing SPI interface parameters + * @param msg Structure used to store the transfer messages + * @return int32_t - SUCCESS if the transfer finished + * - FAILURE if the memory allocation failed + */ +static int32_t spi_engine_transfer_message(struct spi_desc *desc, + struct spi_engine_msg *msg) +{ + uint32_t i; + uint32_t data; + uint32_t sync_id; + bool offload_en; + struct spi_engine_desc *desc_extra; + + desc_extra = desc->extra; + + spi_engine_compile_message(desc, msg); + + offload_en = (desc_extra->offload_config & OFFLOAD_TX_EN) | + (desc_extra->offload_config & OFFLOAD_RX_EN); + + /* Write the command fifo buffer */ + while(msg->cmds != NULL) { + spi_engine_queue_get_cmd(&msg->cmds, &data); + spi_engine_write_cmd(desc, data); + } + + /* Write a number of tx_length WORDS on the SDO line */ + if(offload_en) { + for(i = 0; i < desc_extra->offload_tx_len; i++) + spi_engine_write(desc_extra, + SPI_ENGINE_REG_OFFLOAD_SDO_MEM(0), + msg->tx_buf[i]); + + } else { + if(msg->tx_buf != NULL){ + for(i = 0; i < msg->tx_length; i++) + spi_engine_write(desc_extra, + SPI_ENGINE_REG_SDO_DATA_FIFO, + msg->tx_buf[i]); + } + do { + spi_engine_read(desc_extra, + SPI_ENGINE_REG_SYNC_ID, + &sync_id); + } + /* Wait for the end sync signal */ + while(sync_id != _sync_id); + _sync_id++; + + /* Read a number of rx_length WORDS from the SDI line and store + them */ + for(i = 0; i < msg->rx_length; i++) { + spi_engine_read(desc_extra, + SPI_ENGINE_REG_SDI_DATA_FIFO, + &data); + /* Store the rx data if rx buffer valid, flush sdi_fifo if + rx buffer is invalid.*/ + if(msg->rx_buf != NULL){ + msg->rx_buf[i] = data; + } + } + } + + return SUCCESS; +} + +/** + * @brief Initialize the spi engine + * + * @param desc Decriptor containing SPI interface parameters + * @param param Structure containing the spi init parameters + * @return int32_t - SUCCESS if the transfer finished + * - FAILURE if the memory allocation failed + */ +int32_t spi_engine_init(struct spi_desc **desc, + const struct spi_init_param *param) +{ + uint32_t data_width; + uint32_t spi_engine_version; + struct spi_engine_desc *eng_desc; + struct spi_engine_init_param *spi_engine_init; + + if (!param) { + return FAILURE; + } + + *desc = malloc(sizeof(**desc)); + if(! *desc) { + free(*desc); + return FAILURE; + } + + eng_desc = (struct spi_engine_desc*)malloc(sizeof(*eng_desc)); + + if (!eng_desc) + return FAILURE; + + spi_engine_init = param->extra; + + (*desc)->max_speed_hz = param->max_speed_hz; + (*desc)->chip_select = param->chip_select; + (*desc)->mode = param->mode; + (*desc)->extra = eng_desc; + + eng_desc->offload_config = OFFLOAD_DISABLED; + eng_desc->spi_engine_baseaddr = spi_engine_init->spi_engine_baseaddr; + eng_desc->type = spi_engine_init->type; + eng_desc->cs_delay = spi_engine_init->cs_delay; + eng_desc->ref_clk_hz = spi_engine_init->ref_clk_hz; + eng_desc->clk_div = eng_desc->ref_clk_hz / + (2 * param->max_speed_hz) - 1; + + /* Perform a reset */ + spi_engine_write(eng_desc, SPI_ENGINE_REG_RESET, 0x01); + usleep(1000); + spi_engine_write(eng_desc, SPI_ENGINE_REG_RESET, 0x00); + + /* Get current data width */ + spi_engine_read(eng_desc, SPI_ENGINE_REG_DATA_WIDTH, &data_width); + eng_desc->max_data_width = data_width; + + spi_engine_set_transfer_width(*desc, spi_engine_init->data_width); + + /* Get spi engine version */ + spi_engine_read(eng_desc, SPI_ENGINE_REG_VERSION, &spi_engine_version); + + printf("Spi engine v%"PRIu32".%"PRIu32".%"PRIu32" successfully initialized.\n", + (spi_engine_version >> 16), + ((spi_engine_version >> 8) & 0xFF), + (spi_engine_version & 0xFF)); + + return SUCCESS; +} + +/** + * @brief Write/read on the spi interface in 4-wire mode (full-duplex) + * + * @param desc Decriptor containing SPI interface parameters + * @param data Pointer to data buffer + * @param bytes_number Number of bytes to transfer + * @return int32_t - SUCCESS if the transfer finished + * - FAILURE if the memory allocation or transfer failed + */ +int32_t spi_engine_write_and_read(struct spi_desc *desc, + uint8_t *data, + uint16_t bytes_number) +{ + uint8_t i; + uint8_t word_len; + uint8_t words_number; + int32_t ret; + struct spi_engine_msg msg; + struct spi_engine_desc *desc_extra; + + desc_extra = desc->extra; + + /* If we want to access SPI interface and SPI engine offload module was + * activated, we need to disable it + * This is set in spi_engine_offload_init() */ + desc_extra->offload_config = OFFLOAD_DISABLED; + /* This is set in spi_engine_offload_transfer() */ + spi_engine_write(desc_extra, SPI_ENGINE_REG_OFFLOAD_CTRL(0), 0); + + words_number = spi_get_words_number(desc_extra, bytes_number); + + msg.cmds = (spi_engine_cmd_queue*)malloc(sizeof(*msg.cmds)); + if (!msg.cmds) + return FAILURE; + + msg.tx_buf =(uint32_t*)calloc(words_number, sizeof(msg.tx_buf[0])); + msg.rx_buf =(uint32_t*)calloc(words_number, sizeof(msg.rx_buf[0])); + msg.tx_length = words_number; + msg.rx_length = words_number; + + /* Get the length of transferred word */ + word_len = spi_get_word_length(desc_extra); + + /* Make sure the CS is HIGH before starting a transaction */ + msg.cmds->next = NULL; + msg.cmds->cmd = CS_HIGH; + // Assert select. + spi_engine_queue_add_cmd(&msg.cmds, CS_LOW); + // add read/write command + spi_engine_queue_add_cmd(&msg.cmds, WRITE_READ(bytes_number)); + // Disable select. + spi_engine_queue_add_cmd(&msg.cmds, CS_HIGH); + + /* Pack the bytes into engine WORDS */ + for (int i = 0; i < bytes_number; i++) + msg.tx_buf[i / word_len] |= data[i] << (desc_extra->data_width- + (i % word_len + 1) * 8); + + ret = spi_engine_transfer_message(desc, &msg); + + for (int i = 0; i < bytes_number; i++) + data[i] = msg.rx_buf[(i) / word_len] >> + (desc_extra->data_width - + ((i) % word_len + 1) * 8); + + spi_engine_queue_free(&msg.cmds); + free(msg.tx_buf); + free(msg.rx_buf); + + return ret; +} + +/** + * @brief Write and read on the spi interface in 3-wire mode (half-duplex) + * + * @param desc Decriptor containing SPI interface parameters + * @param data Pointer to data buffer + * @param bytes_number Number of bytes to transfer + * @return int32_t - SUCCESS if the transfer finished + * - FAILURE if the memory allocation or transfer failed + */ +int32_t spi_engine_write_and_read_3wire(struct spi_desc *desc, + uint8_t *write_data, + uint8_t *read_data, + uint16_t write_bytes_number, + uint16_t read_bytes_number) +{ + uint8_t word_len; + uint8_t wr_words_number; + uint8_t rd_words_number; + int32_t ret; + struct spi_engine_msg msg; + struct spi_engine_desc *desc_extra; + + desc_extra = desc->extra; + + /* If we want to access SPI interface and SPI engine offload module was + * activated, we need to disable it + * This is set in spi_engine_offload_init() */ + desc_extra->offload_config = OFFLOAD_DISABLED; + /* This is set in spi_engine_offload_transfer() */ + spi_engine_write(desc_extra, SPI_ENGINE_REG_OFFLOAD_CTRL(0), 0); + + wr_words_number = spi_get_words_number(desc_extra, write_bytes_number); + rd_words_number = spi_get_words_number(desc_extra, read_bytes_number); + + msg.cmds = (spi_engine_cmd_queue*)malloc(sizeof(*msg.cmds)); + if (!msg.cmds) + return FAILURE; + + msg.tx_buf =(wr_words_number>0)?(uint32_t*)calloc(wr_words_number, sizeof(msg.tx_buf[0])):NULL; + msg.rx_buf =(rd_words_number>0)?(uint32_t*)calloc(rd_words_number, sizeof(msg.rx_buf[0])):NULL; + msg.tx_length = wr_words_number; + msg.rx_length = rd_words_number; + + /* Get the length of transferred word */ + word_len = spi_get_word_length(desc_extra); + + /* Make sure the CS is HIGH before starting a transaction */ + msg.cmds->next = NULL; + msg.cmds->cmd = CS_HIGH; + + // Assert select. + spi_engine_queue_add_cmd(&msg.cmds, CS_LOW); + + // add read/write command + if(write_bytes_number > 0) + spi_engine_queue_add_cmd(&msg.cmds, WRITE(write_bytes_number)); + if(read_bytes_number > 0) + spi_engine_queue_add_cmd(&msg.cmds, READ(read_bytes_number)); + + // Disable select. + spi_engine_queue_add_cmd(&msg.cmds, CS_HIGH); + + /* Pack the bytes into engine WORDS */ + for (int i = 0; i < write_bytes_number; i++) + msg.tx_buf[i / word_len] |= write_data[i] << (desc_extra->data_width- + (i % word_len + 1) * 8); + + ret = spi_engine_transfer_message(desc, &msg); + + for (int i = 0; i < read_bytes_number; i++) + read_data[i] = msg.rx_buf[(i) / word_len] >> + (desc_extra->data_width - + ((i) % word_len + 1) * 8); + + spi_engine_queue_free(&msg.cmds); + free(msg.tx_buf); + free(msg.rx_buf); + + return ret; +} + +/** + * @brief Initialize the SPI engine's offload module + * + * @param desc Decriptor containing SPI interface parameters + * @param param Structure containing the offload init parameters + * @return int32_t This function always returns SUCCESS + */ +int32_t spi_engine_offload_init(struct spi_desc *desc, + const struct spi_engine_offload_init_param *param) +{ + struct spi_engine_desc *eng_desc; + struct axi_dmac_init dmac_init; + + eng_desc = desc->extra; + + eng_desc->offload_config = param->offload_config; + + if(!(param->dma_flags)) { + eng_desc->cyclic = CYCLIC; + } else { + if((*(param->dma_flags)) & DMA_CYCLIC) + eng_desc->cyclic = CYCLIC; + else + eng_desc->cyclic = NO; + } + + + if(param->offload_config & OFFLOAD_TX_EN) { + dmac_init.name = "DAC DMAC"; + dmac_init.base = param->tx_dma_baseaddr; + axi_dmac_init(&eng_desc->offload_tx_dma, &dmac_init); + if(!eng_desc->offload_tx_dma) + return FAILURE; + } + if(param->offload_config & OFFLOAD_RX_EN) { + dmac_init.name = "ADC DMAC"; + dmac_init.base = param->rx_dma_baseaddr; + axi_dmac_init(&eng_desc->offload_rx_dma, &dmac_init); + if(!eng_desc->offload_rx_dma) + return FAILURE; + } + + return SUCCESS; +} + +/** + * @brief Initiate a SPI transfer in offload mode + * + * @param desc Decriptor containing SPI interface parameters + * @param msg Offload message that get's to be transferred + * @param no_samples Number of time the messages will be transferred + * @return int32_t This function always returns SUCCESS + */ +int32_t spi_engine_offload_transfer(struct spi_desc *desc, + struct spi_engine_offload_message msg, + uint32_t no_samples) +{ + struct spi_engine_msg transfer; + struct spi_engine_desc *eng_desc; + uint32_t i; + uint8_t word_length; + + eng_desc = desc->extra; + + /* Check if offload is disabled */ + if(!((eng_desc->offload_config & OFFLOAD_TX_EN) | + (eng_desc->offload_config & OFFLOAD_RX_EN))) + return FAILURE; + + spi_engine_write(eng_desc, SPI_ENGINE_REG_OFFLOAD_RESET(0), 1); + spi_engine_write(eng_desc, SPI_ENGINE_REG_OFFLOAD_RESET(0), 0); + + eng_desc->offload_tx_len = 0; + eng_desc->offload_rx_len = 0; + + transfer.cmds = (spi_engine_cmd_queue*)malloc(sizeof(*transfer.cmds)); + + if (!transfer.cmds) + return -1; + + transfer.tx_buf = msg.commands_data; + + /* Load the commands into the message */ + transfer.cmds->next = NULL; + transfer.cmds->cmd = msg.commands[0]; + i = 1; + while(i < msg.no_commands) { + spi_engine_queue_add_cmd(&transfer.cmds, msg.commands[i++]); + + } + + spi_engine_transfer_message(desc, &transfer); + + /* Start transfer */ + spi_engine_write(eng_desc, SPI_ENGINE_REG_OFFLOAD_CTRL(0), 0x0001); + + word_length = spi_get_word_length(eng_desc); + if(eng_desc->offload_config & OFFLOAD_TX_EN) { + struct axi_dma_transfer tx_transfer = { + // Number of bytes to write/read + .size = word_length * eng_desc->offload_tx_len * no_samples, + // Transfer done flag + .transfer_done = 0, + // Signal transfer mode + .cyclic = eng_desc->cyclic, + // Address of data source + .src_addr = (uintptr_t)msg.tx_addr, + // Address of data destination + .dest_addr = 0 + }; + axi_dmac_transfer_start(eng_desc->offload_tx_dma, &tx_transfer); + } + + if(eng_desc->offload_config & OFFLOAD_RX_EN) { + struct axi_dma_transfer rx_transfer = { + // Number of bytes to write/read + .size = word_length * eng_desc->offload_tx_len * no_samples, + // Transfer done flag + .transfer_done = 0, + // Signal transfer mode + .cyclic = NO, + // Address of data source + .src_addr = 0, + // Address of data destination + .dest_addr = (uintptr_t)msg.rx_addr + }; + axi_dmac_transfer_start(eng_desc->offload_rx_dma, &rx_transfer); + axi_dmac_transfer_wait_completion(eng_desc->offload_rx_dma, 500); + } + + usleep(1000); + + spi_engine_queue_free(&transfer.cmds); + + return SUCCESS; +} + +/** + * @brief Free the resources allocated by spi_init(). + * + * @param desc Decriptor containing SPI interface parameters + * @return int32_t This function allways returns SUCCESS + */ +int32_t spi_engine_remove(struct spi_desc *desc) +{ + struct spi_engine_desc *eng_desc; + + eng_desc = desc->extra; + + if(eng_desc->offload_config & OFFLOAD_TX_EN) + axi_dmac_remove(eng_desc->offload_tx_dma); + if(eng_desc->offload_config & OFFLOAD_RX_EN) + axi_dmac_remove(eng_desc->offload_rx_dma); + free(desc->extra); + free(desc); + + return SUCCESS; +} diff --git a/df_datalink/src/drivers/axi_core/spi_engine/spi_engine.h b/df_datalink/src/drivers/axi_core/spi_engine/spi_engine.h new file mode 100644 index 0000000..9e6887e --- /dev/null +++ b/df_datalink/src/drivers/axi_core/spi_engine/spi_engine.h @@ -0,0 +1,229 @@ +/******************************************************************************* + * @file spi_engine.h + * @brief Header file of SPI Engine core features. + * @author Sergiu Cuciurean (sergiu.cuciurean@analog.com) +******************************************************************************** + * Copyright 2019(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#ifndef SPI_ENGINE_H +#define SPI_ENGINE_H + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include + +#include "spi_engine_private.h" +#include "../axi_dmac/axi_dmac.h" +#include "../../platform/xilinx_spi.h" + +/******************************************************************************/ +/********************** Macros and Constants Definitions **********************/ +/******************************************************************************/ + +#define OFFLOAD_DISABLED 0x00 +#define OFFLOAD_TX_EN BIT(0) +#define OFFLOAD_RX_EN BIT(1) +#define OFFLOAD_TX_RX_EN OFFLOAD_TX_EN | OFFLOAD_RX_EN + +#define SPI_ENGINE_MSG_QUEUE_END 0xFFFFFFFF + +/* Spi engine commands */ +#define WRITE(no_bytes) ((SPI_ENGINE_INST_TRANSFER << 12) |\ + (SPI_ENGINE_INSTRUCTION_TRANSFER_W << 8) | no_bytes) + +#define READ(no_bytes) ((SPI_ENGINE_INST_TRANSFER << 12) |\ + (SPI_ENGINE_INSTRUCTION_TRANSFER_R << 8) | no_bytes) + +#define WRITE_READ(no_bytes) ((SPI_ENGINE_INST_TRANSFER << 12) |\ + (SPI_ENGINE_INSTRUCTION_TRANSFER_RW << 8) | no_bytes) + +#define SLEEP(time) SPI_ENGINE_CMD_SLEEP(time & 0xF) + +/* The delay and chip select parmeters are passed over the engine descriptor +and will be used inside the function call */ +#define CS_HIGH SPI_ENGINE_CMD_ASSERT(0x01, 0xFF) +#define CS_LOW SPI_ENGINE_CMD_ASSERT(0x01, 0x00) + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ + +/** + * @struct spi_engine_init_param + * @brief Structure containing the init parameters needed by the SPI engine + */ +struct spi_engine_init_param { + /** SPI engine reference clock */ + uint32_t ref_clk_hz; + /** Type of implementation */ + enum xil_spi_type type; + /** Base address where the HDL core is situated */ + uint32_t spi_engine_baseaddr; + /** Delay between the CS toggle and the start of SCLK */ + uint32_t cs_delay; + /** Data with of one SPI transfer ( in bits ) */ + uint8_t data_width; +}; + + +/** + * @struct spi_engine_desc + * @brief Structure representing an SPI engine device + */ +struct spi_engine_desc { + /** SPI engine reference clock */ + uint32_t ref_clk_hz; + /** Type of implementation */ + enum xil_spi_type type; + /** Pointer to a DMAC used in transmission */ + struct axi_dmac *offload_tx_dma; + /** Pointer to a DMAC used in reception */ + struct axi_dmac *offload_rx_dma; + /** Transfer mode for Tx DMAC */ + enum cyclic_transfer cyclic; + /** Offload's module transfer direction : TX, RX or both */ + uint8_t offload_config; + /** Number of words that the module has to send */ + uint8_t offload_tx_len; + /** Number of words that the module has to receive */ + uint8_t offload_rx_len; + /** Base address where the HDL core is situated */ + uint32_t spi_engine_baseaddr; + /** Base address where the RX DMAC core is situated */ + uint32_t rx_dma_baseaddr; + /** Base address where the TX DMAC core is situated */ + uint32_t tx_dma_baseaddr; + /** Delay between the CS toggle and the start of SCLK */ + uint8_t cs_delay; + /** Clock divider used in transmission delays */ + uint32_t clk_div; + /** Data with of one SPI transfer ( in bits ) */ + uint8_t data_width; + /** The maximum data width supported by the engine */ + uint8_t max_data_width; +}; + + +/** + * @struct spi_engine_offload_init_param + * @brief Structure containing the init parameters needed by the offload module + */ +struct spi_engine_offload_init_param { + /** Base address where the RX DMAC core is situated */ + uint32_t rx_dma_baseaddr; + /** Base address where the TX DMAC core is situated */ + uint32_t tx_dma_baseaddr; + /** DMAC flags - if not initialized, the default value is DMA_CYCLIC */ + uint32_t *dma_flags; + /** Offload's module transfer direction : TX, RX or both */ + uint8_t offload_config; +}; + +/** + * @struct spi_engine_offload_message + * @brief Structure representing an offload message + */ +struct spi_engine_offload_message { + /** Pointer to the SPI engine commands buffer that will be sent. + * The available commands can be found at: + * https://wiki.analog.com/resources/fpga/peripherals/spi_engine/ + */ + uint32_t *commands; + /** Length of the SPI engine commands buffer */ + uint32_t no_commands; + /** Pointer of the data that will be sent over spi */ + uint32_t *commands_data; + /** The address where the data that will be transmitted is situated */ + uint32_t tx_addr; + /** The address where the data that will be received is situated */ + uint32_t rx_addr; +}; + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ + +/** + * @brief Spi engine platform specific SPI platform ops structure + */ +extern const struct spi_platform_ops xil_spi_ops; + +/* Write SPI Engine's axi registers */ +int32_t spi_engine_write(struct spi_engine_desc *desc, + uint32_t reg_addr, + uint32_t reg_data); + +/* Read SPI Engine's axi registers */ +int32_t spi_engine_read(struct spi_engine_desc *desc, + uint32_t reg_addr, + uint32_t *reg_data); +/* Initialize the SPI engine device */ +int32_t spi_engine_init(struct spi_desc **desc, + const struct spi_init_param *param); + +/* Write and read data over SPI using the SPI engine */ +int32_t spi_engine_write_and_read(struct spi_desc *desc, + uint8_t *data, + uint16_t bytes_number); + +/* Write and read data over SPI using the SPI engine in 3-wire mode */ +int32_t spi_engine_write_and_read_3wire(struct spi_desc *desc, + uint8_t *write_data, + uint8_t *read_data, + uint16_t write_bytes_number, + uint16_t read_bytes_number); +/* Free the resources used by the SPI engine device */ +int32_t spi_engine_remove(struct spi_desc *desc); + +/* Initialize the SPI engine offload module */ +int32_t spi_engine_offload_init(struct spi_desc *desc, + const struct spi_engine_offload_init_param *param); + +/* Write and read data over SPI using the offload module */ +int32_t spi_engine_offload_transfer(struct spi_desc *desc, + struct spi_engine_offload_message msg, + uint32_t no_samples); + +/* Set SPI transfer width */ +int32_t spi_engine_set_transfer_width(struct spi_desc *desc, + uint8_t data_wdith); + +/* Set SPI transfer speed */ +void spi_engine_set_speed(struct spi_desc *desc, + uint32_t speed_hz); + +#endif // SPI_ENGINE_H diff --git a/df_datalink/src/drivers/axi_core/spi_engine/spi_engine_private.h b/df_datalink/src/drivers/axi_core/spi_engine/spi_engine_private.h new file mode 100644 index 0000000..571a847 --- /dev/null +++ b/df_datalink/src/drivers/axi_core/spi_engine/spi_engine_private.h @@ -0,0 +1,154 @@ +/******************************************************************************* + * @file spi_engine_private.h + * @brief Private definitions of the SPI Engine + * @author Sergiu Cuciurean (sergiu.cuciurean@analog.com) +******************************************************************************** + * Copyright 2019(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#ifndef SPI_ENGINE_PRIVATE_H +#define SPI_ENGINE_PRIVATE_H + +#include +#include + +#include "spi.h" +#include "util.h" + +/******************************************************************************/ +/*************************** Spi Engine registers *****************************/ +/******************************************************************************/ + +#define SPI_ENGINE_REG_VERSION 0x00 +#define SPI_ENGINE_REG_DATA_WIDTH 0x0C +#define SPI_ENGINE_REG_RESET 0x40 +#define SPI_ENGINE_REG_INT_ENABLE 0x80 +#define SPI_ENGINE_REG_INT_PENDING 0x84 +#define SPI_ENGINE_REG_INT_SOURCE 0x88 +#define SPI_ENGINE_REG_SYNC_ID 0xC0 +#define SPI_ENGINE_REG_CMD_FIFO_ROOM 0xD0 +#define SPI_ENGINE_REG_SDO_FIFO_ROOM 0xD4 +#define SPI_ENGINE_REG_SDI_FIFO_LEVEL 0xD8 +#define SPI_ENGINE_REG_CMD_FIFO 0xE0 +#define SPI_ENGINE_REG_SDO_DATA_FIFO 0xE4 +#define SPI_ENGINE_REG_SDI_DATA_FIFO 0xE8 +#define SPI_ENGINE_REG_SDI_DATA_FIFO_PEEK 0xEC + +/******************************************************************************/ +/************************ Spi Engine register parameters **********************/ +/******************************************************************************/ + +#define SPI_ENGINE_INST_TRANSFER 0x00 +#define SPI_ENGINE_INST_ASSERT 0x01 +#define SPI_ENGINE_INST_CONFIG 0x02 +#define SPI_ENGINE_INST_SYNC_SLEEP 0x03 +#define SPI_ENGINE_INST_MISC 0x03 +#define SPI_ENGINE_CMD_REG_CLK_DIV 0x00 +#define SPI_ENGINE_CMD_REG_CONFIG 0x01 +#define SPI_ENGINE_CMD_DATA_TRANSFER_LEN 0x02 +#define SPI_ENGINE_MISC_SYNC 0x00 +#define SPI_ENGINE_MISC_SLEEP 0x01 +#define SPI_ENGINE_SYNC_TRANSFER_BEGIN BIT(1) +#define SPI_ENGINE_SYNC_TRANSFER_END BIT(2) +#define SPI_ENGINE_INT_CMD_ALMOST_EMPTY BIT(0) +#define SPI_ENGINE_INT_SDO_ALMOST_EMPTY BIT(1) +#define SPI_ENGINE_INT_SDI_ALMOST_FULL BIT(2) +#define SPI_ENGINE_INT_SYNC BIT(3) +#define SPI_ENGINE_OFFLOAD_CTRL_ENABLE BIT(0) +#define SPI_ENGINE_OFFLOAD_STATUS_ENABLED BIT(0) +#define SPI_ENGINE_CONFIG_CPHA BIT(0) +#define SPI_ENGINE_CONFIG_CPOL BIT(1) +#define SPI_ENGINE_CONFIG_3WIRE BIT(2) +#define SPI_ENGINE_VERSION_MAJOR(x) ((x >> 16) & 0xff) +#define SPI_ENGINE_VERSION_MINOR(x) ((x >> 8) & 0xff) +#define SPI_ENGINE_VERSION_PATCH(x) (x & 0xff) + +/******************************************************************************/ +/**************************** Spi Engine commands *****************************/ +/******************************************************************************/ + +#define SPI_ENGINE_INSTRUCTION_TRANSFER_W 0x01 +#define SPI_ENGINE_INSTRUCTION_TRANSFER_R 0x02 +#define SPI_ENGINE_INSTRUCTION_TRANSFER_RW 0x03 + +#define SPI_ENGINE_REG_OFFLOAD_CTRL(x) (0x100 + (0x20 * x)) +#define SPI_ENGINE_REG_OFFLOAD_STATUS(x) (0x104 + (0x20 * x)) +#define SPI_ENGINE_REG_OFFLOAD_RESET(x) (0x108 + (0x20 * x)) +#define SPI_ENGINE_REG_OFFLOAD_CMD_MEM(x) (0x110 + (0x20 * x)) +#define SPI_ENGINE_REG_OFFLOAD_SDO_MEM(x) (0x114 + (0x20 * x)) + +#define SPI_ENGINE_CMD(inst, arg1, arg2) \ + (((inst & 0x03) << 12) | \ + ((arg1 & 0x03) << 8) | arg2 ) + +#define SPI_ENGINE_CMD_TRANSFER(readwrite, n) \ + SPI_ENGINE_CMD(SPI_ENGINE_INST_TRANSFER, \ + (readwrite), (n)) + +#define SPI_ENGINE_CMD_ASSERT(delay, cs) \ + SPI_ENGINE_CMD(SPI_ENGINE_INST_ASSERT, \ + (delay), (cs)) + +#define SPI_ENGINE_CMD_CONFIG(reg, val) \ + SPI_ENGINE_CMD(SPI_ENGINE_INST_CONFIG, \ + (reg), (val)) + +#define SPI_ENGINE_CMD_SLEEP(delay) \ + SPI_ENGINE_CMD(SPI_ENGINE_INST_MISC, \ + SPI_ENGINE_MISC_SLEEP, \ + (delay)) + +#define SPI_ENGINE_CMD_SYNC(id) \ + SPI_ENGINE_CMD(SPI_ENGINE_INST_MISC, \ + SPI_ENGINE_MISC_SYNC, \ + (id)) + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ + +typedef struct spi_engine_cmd_queue { + uint32_t cmd; + struct spi_engine_cmd_queue *next; +} spi_engine_cmd_queue; + +typedef struct spi_engine_msg { + uint32_t *tx_buf; + uint32_t *rx_buf; + uint32_t tx_length; + uint32_t rx_length; + struct spi_engine_cmd_queue *cmds; +} spi_engine_msg; + +#endif // SPI_ENGINE_PRIVATE_H diff --git a/df_datalink/src/drivers/frequency/hmc7044/hmc7044.c b/df_datalink/src/drivers/frequency/hmc7044/hmc7044.c new file mode 100644 index 0000000..2574d9a --- /dev/null +++ b/df_datalink/src/drivers/frequency/hmc7044/hmc7044.c @@ -0,0 +1,927 @@ +/***************************************************************************//** + * @file hmc7044.c + * @brief Implementation of HMC7044, HMC7043 Driver. + * @author DBogdan (dragos.bogdan@analog.com) +******************************************************************************** + * Copyright 2018-2020(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include +#include +#include "hmc7044.h" +#include "../../../include/error.h" +#include "../../../include/util.h" + +/******************************************************************************/ +/********************** Macros and Constants Definitions **********************/ +/******************************************************************************/ +#define HMC7044_WRITE (0 << 15) +#define HMC7044_READ (1 << 15) +#define HMC7044_CNT(x) (((x) - 1) << 13) +#define HMC7044_ADDR(x) ((x) & 0xFFF) + +/* Global Control */ +#define HMC7044_REG_SOFT_RESET 0x0000 +#define HMC7044_SOFT_RESET BIT(0) + +#define HMC7044_REG_REQ_MODE_0 0x0001 +#define HMC7044_RESEED_REQ BIT(7) +#define HMC7044_HIGH_PERF_DISTRIB_PATH BIT(6) +#define HMC7044_HIGH_PERF_PLL_VCO BIT(5) +#define HMC7044_FORCE_HOLDOVER BIT(4) +#define HMC7044_MUTE_OUT_DIV BIT(3) +#define HMC7044_PULSE_GEN_REQ BIT(2) +#define HMC7044_RESTART_DIV_FSM BIT(1) +#define HMC7044_SLEEP_MODE BIT(0) + +#define HMC7044_REG_REQ_MODE_1 0x0002 +#define HMC7044_PLL2_AUTOTUNE_TRIG BIT(2) +#define HMC7044_SLIP_REQ BIT(1) + +#define HMC7044_REG_EN_CTRL_0 0x0003 +#define HMC7044_RF_RESEEDER_EN BIT(5) +#define HMC7044_VCO_SEL(x) (((x) & 0x3) << 3) +#define HMC7044_VCO_EXT 0 +#define HMC7044_VCO_HIGH 1 +#define HMC7044_VCO_LOW 2 +#define HMC7044_SYSREF_TIMER_EN BIT(2) +#define HMC7044_PLL2_EN BIT(1) +#define HMC7044_PLL1_EN BIT(0) + +#define HMC7044_REG_EN_CTRL_1 0x0004 +#define HMC7044_SEVEN_PAIRS(x) ((x) & 0x7f) + +#define HMC7044_REG_GLOB_MODE 0x0005 +#define HMC7044_REF_PATH_EN(x) ((x) & 0xf) +#define HMC7044_RFSYNC_EN BIT(4) +#define HMC7044_VCOIN_MODE_EN BIT(5) +#define HMC7044_SYNC_PIN_MODE(x) (((x) & 0x3) << 6) + +/* PLL1 */ +#define HMC7044_REG_CLKIN0_BUF_CTRL 0x000A +#define HMC7044_REG_CLKIN1_BUF_CTRL 0x000B +#define HMC7044_REG_CLKIN2_BUF_CTRL 0x000C +#define HMC7044_REG_CLKIN3_BUF_CTRL 0x000D +#define HMC7044_REG_OSCIN_BUF_CTRL 0x000E + +#define HMC7044_REG_PLL1_REF_PRIO_CTRL 0x0014 + +#define HMC7044_HIGH_Z_EN BIT(4) +#define HMC7044_LVPECL_EN BIT(3) +#define HMC7044_AC_COUPLING_EN BIT(2) +#define HMC7044_100_OHM_EN BIT(1) +#define HMC7044_BUF_EN BIT(0) + +#define HMC7044_REG_CLKIN_PRESCALER(x) (0x001C + (x)) +#define HMC7044_REG_OSCIN_PRESCALER 0x0020 + +#define HMC7044_REG_PLL1_R_LSB 0x0021 +#define HMC7044_R1_LSB(x) ((x) & 0xff) + +#define HMC7044_REG_PLL1_R_MSB 0x0022 +#define HMC7044_R1_MSB(x) (((x) & 0xff00) >> 8) + +#define HMC7044_REG_PLL1_N_LSB 0x0026 +#define HMC7044_N1_LSB(x) ((x) & 0xff) + +#define HMC7044_REG_PLL1_N_MSB 0x0027 +#define HMC7044_N1_MSB(x) (((x) & 0xff00) >> 8) + +#define HMC7044_REG_PLL1_LOCK_DETECT 0x0028 +#define HMC7044_LOCK_DETECT_SLIP BIT(5) +#define HMC7044_LOCK_DETECT_TIMER(x) ((x) & 0x1f) + +/* PLL2 */ +#define HMC7044_REG_PLL2_FREQ_DOUBLER 0x0032 +#define HMC7044_PLL2_FREQ_DOUBLER_DIS BIT(0) + +#define HMC7044_REG_PLL2_R_LSB 0x0033 +#define HMC7044_R2_LSB(x) ((x) & 0xff) + +#define HMC7044_REG_PLL2_R_MSB 0x0034 +#define HMC7044_R2_MSB(x) (((x) & 0xf00) >> 8) + +#define HMC7044_REG_PLL2_N_LSB 0x0035 +#define HMC7044_N2_LSB(x) ((x) & 0xff) + +#define HMC7044_REG_PLL2_N_MSB 0x0036 +#define HMC7044_N2_MSB(x) (((x) & 0xff00) >> 8) + +#define HMC7044_REG_OSCOUT_PATH 0x0039 +#define HMC7044_REG_OSCOUT_DRIVER_0 0x003A +#define HMC7044_REG_OSCOUT_DRIVER_1 0x003B + +/* GPIO/SDATA Control */ +#define HMC7044_REG_GPI_CTRL(x) (0x0046 + (x)) +#define HMC7044_REG_GPI_SEL(x) ((x) & 0xf) + +#define HMC7044_REG_GPO_CTRL(x) (0x0050 + (x)) +#define HMC7044_GPO_SEL(x) (((x) & 0x3f) << 2) +#define HMC7044_GPO_MODE BIT(1) +#define HMC7044_GPO_EN BIT(0) + +/* SYSREF/SYNC Control */ +#define HMC7044_REG_PULSE_GEN 0x005A +#define HMC7044_PULSE_GEN_MODE(x) ((x) & 0x7) + +#define HMC7044_REG_SYNC 0x005B +#define HMC7044_SYNC_RETIME BIT(2) +#define HMC7044_SYNC_THROUGH_PLL2 BIT(1) +#define HMC7044_SYNC_POLARITY BIT(0) + +#define HMC7044_REG_SYSREF_TIMER_LSB 0x005C +#define HMC7044_SYSREF_TIMER_LSB(x) ((x) & 0xff) + +#define HMC7044_REG_SYSREF_TIMER_MSB 0x005D +#define HMC7044_SYSREF_TIMER_MSB(x) (((x) & 0xf00) >> 8) + +#define HMC7044_CLK_INPUT_CTRL 0x0064 +#define HMC7044_LOW_FREQ_INPUT_MODE BIT(0) +#define HMC7044_DIV_2_INPUT_MODE BIT(1) + +/* Status and Alarm readback */ +#define HMC7044_REG_ALARM_READBACK 0x007D +#define HMC7044_REG_PLL1_STATUS 0x0082 + +#define HMC7044_PLL1_FSM_STATE(x) ((x) & 0x7) +#define HMC7044_PLL1_ACTIVE_CLKIN(x) (((x) >> 3) & 0x3) + +#define HMC7044_PLL2_LOCK_DETECT(x) ((x) & 0x1) +#define HMC7044_SYSREF_SYNC_STAT(x) ((x) & 0x2) +#define HMC7044_CLK_OUT_PH_STATUS(x) ((x) & 0x4) +#define HMC7044_PLL1_PLL2_LOCK_STAT(x) ((x) & 0x8) +#define HMC7044_SYNC_REQ_STATUS(x) ((x) & 0x10) + +/* Other Controls */ +#define HMC7044_REG_CLK_OUT_DRV_LOW_PW 0x009F +#define HMC7044_REG_CLK_OUT_DRV_HIGH_PW 0x00A0 +#define HMC7044_REG_PLL1_DELAY 0x00A5 +#define HMC7044_REG_PLL1_HOLDOVER 0x00A8 +#define HMC7044_REG_VTUNE_PRESET 0x00B0 + +/* Clock Distribution */ +#define HMC7044_REG_CH_OUT_CRTL_0(ch) (0x00C8 + 0xA * (ch)) +#define HMC7044_HI_PERF_MODE BIT(7) +#define HMC7044_SYNC_EN BIT(6) +#define HMC7044_CH_EN BIT(0) +#define HMC7044_START_UP_MODE_DYN_EN (BIT(3) | BIT(2)) + +#define HMC7044_REG_CH_OUT_CRTL_1(ch) (0x00C9 + 0xA * (ch)) +#define HMC7044_DIV_LSB(x) ((x) & 0xFF) + +#define HMC7044_REG_CH_OUT_CRTL_2(ch) (0x00CA + 0xA * (ch)) +#define HMC7044_DIV_MSB(x) (((x) >> 8) & 0xFF) + +#define HMC7044_REG_CH_OUT_CRTL_3(ch) (0x00CB + 0xA * (ch)) +#define HMC7044_REG_CH_OUT_CRTL_4(ch) (0x00CC + 0xA * (ch)) +#define HMC7044_REG_CH_OUT_CRTL_5(ch) (0x00CD + 0xA * (ch)) +#define HMC7044_REG_CH_OUT_CRTL_6(ch) (0x00CE + 0xA * (ch)) +#define HMC7044_REG_CH_OUT_CRTL_7(ch) (0x00CF + 0xA * (ch)) + +#define HMC7044_REG_CH_OUT_CRTL_8(ch) (0x00D0 + 0xA * (ch)) +#define HMC7044_DRIVER_MODE(x) (((x) & 0x3) << 3) +#define HMC7044_DRIVER_Z_MODE(x) (((x) & 0x3) << 0) +#define HMC7044_DYN_DRIVER_EN BIT(5) +#define HMC7044_FORCE_MUTE_EN BIT(7) + +#define HMC7044_NUM_CHAN 14 + +#define HMC7044_LOW_VCO_MIN 2150000 +#define HMC7044_LOW_VCO_MAX 2880000 +#define HMC7044_HIGH_VCO_MIN 2650000 +#define HMC7044_HIGH_VCO_MAX 3200000 + +#define HMC7044_RECOMM_LCM_MIN 30000 +#define HMC7044_RECOMM_LCM_MAX 70000 +#define HMC7044_RECOMM_FPD1 10000 + +#define HMC7044_R1_MAX 65535 +#define HMC7044_N1_MAX 65535 + +#define HMC7044_R2_MIN 1 +#define HMC7044_R2_MAX 4095 +#define HMC7044_N2_MIN 8 +#define HMC7044_N2_MAX 65535 + +#define HMC7044_OUT_DIV_MIN 1 +#define HMC7044_OUT_DIV_MAX 4094 + +/******************************************************************************/ +/************************** Functions Implementation **************************/ +/******************************************************************************/ + +/** + * SPI register write to device. + * @param dev - The device structure. + * @param reg - The register address. + * @param val - The register data. + * @return SUCCESS in case of success, negative error code otherwise. + */ +int32_t hmc7044_write(struct hmc7044_dev *dev, + uint16_t reg, + uint8_t val) +{ + uint8_t buf[3]; + uint16_t cmd; + + cmd = HMC7044_WRITE | HMC7044_CNT(1) | HMC7044_ADDR(reg); + buf[0] = cmd >> 8; + buf[1] = cmd & 0xFF; + buf[2] = val; + return spi_write_and_read_3wire(dev->spi_desc, buf, NULL, + ARRAY_SIZE(buf), 0); +} + +/** + * SPI register read from device. + * @param dev - The device structure. + * @param reg - The register address. + * @param val - The register data. + * @return SUCCESS in case of success, negative error code otherwise. + */ + +int32_t hmc7044_read(struct hmc7044_dev *dev, uint16_t reg, uint8_t *val) +{ + uint8_t wr_buf[2]; + uint8_t rd_data[1]; + uint16_t cmd; + int ret; + + cmd = HMC7044_READ | HMC7044_CNT(1) | HMC7044_ADDR(reg); + wr_buf[0] = cmd >> 8; + wr_buf[1] = cmd & 0xFF; + + ret = spi_write_and_read_3wire(dev->spi_desc, wr_buf, rd_data, + ARRAY_SIZE(wr_buf), ARRAY_SIZE(rd_data)); + if (ret != SUCCESS) + return ret; + + *val = rd_data[0]; + + return SUCCESS; +} + +/** + * Calculate the output channel divider. + * @param rate - The desired rate. + * @param parent_rate - The parent rate. + * @return The output divider. + */ +uint32_t hmc7044_calc_out_div(uint32_t rate, + uint32_t parent_rate) +{ + uint32_t div; + + div = DIV_ROUND_CLOSEST(parent_rate, rate); + + /* Supported odd divide ratios are 1, 3, and 5 */ + if ((div != 1) && (div != 3) && (div != 5) && (div % 2)) + div = DIV_ROUND_CLOSEST(parent_rate, rate * 2) * 2; + + div = clamp_t(unsigned int, + div, + HMC7044_OUT_DIV_MIN, + HMC7044_OUT_DIV_MAX); + + return div; +} + +/** + * Recalculate rate corresponding to a channel. + * @param dev - The device structure. + * @param chan_num - Channel number. + * @param rate - Channel rate. + * @return SUCCESS in case of success, negative error code otherwise. + */ +int32_t hmc7044_clk_recalc_rate(struct hmc7044_dev *dev, uint32_t chan_num, + uint64_t *rate) +{ + int i; + struct hmc7044_chan_spec *chan = NULL; + + /* Find the reqested channel number */ + for (i = 0; i < dev->num_channels; i++) { + if (dev->channels[i].num == chan_num) { + chan = &dev->channels[i]; + break; + } + } + if (chan == NULL ) + return FAILURE; + + *rate = dev->pll2_freq / chan->divider; + + return SUCCESS; +} + +/** + * Calculate closest possible rate + * @param dev - The device structure + * @param rate - The desired rate. + * @param rounded_rate - The closest possible rate of desired rate. + * @return SUCCESS in case of success, negative error code otherwise. + */ +int32_t hmc7044_clk_round_rate(struct hmc7044_dev *dev, uint32_t rate, + uint64_t *rounded_rate) +{ + uint32_t div = hmc7044_calc_out_div(rate, dev->pll2_freq); + + *rounded_rate = DIV_ROUND_CLOSEST(dev->pll2_freq, div); + + return SUCCESS; +} + +/** + * Set channel rate. + * @param dev - The device structure. + * @param chan_num - Channel number. + * @param rate - Channel rate. + * @return SUCCESS in case of success, negative error code otherwise. + */ +int32_t hmc7044_clk_set_rate(struct hmc7044_dev *dev, uint32_t chan_num, + uint64_t rate) +{ + uint32_t div; + int32_t ret; + int i; + struct hmc7044_chan_spec *chan = NULL; + + /* Find the reqested channel number */ + for (i = 0; i < dev->num_channels; i++) { + if (dev->channels[i].num == chan_num) { + chan = &dev->channels[i]; + break; + } + } + if (chan == NULL ) + return FAILURE; + + div = hmc7044_calc_out_div(rate, dev->pll2_freq); + chan->divider = div; + + ret = hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_1(chan->num), + HMC7044_DIV_LSB(div)); + if(ret < 0) + return ret; + + return hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_2(chan->num), + HMC7044_DIV_MSB(div)); +} + +/** + * Setup the device. + * @param dev - The device structure. + * @return SUCCESS in case of success, negative error code otherwise. + */ +static int32_t hmc7044_setup(struct hmc7044_dev *dev) +{ + struct hmc7044_chan_spec *chan; + bool high_vco_en; + bool pll2_freq_doubler_en; + uint32_t vcxo_freq, pll2_freq; + uint32_t clkin_freq[4]; + uint32_t lcm_freq; + uint32_t in_prescaler[5]; + uint32_t pll1_lock_detect; + uint32_t n1, r1; + uint32_t pfd1_freq; + uint32_t vco_limit; + uint32_t n2[2], r2[2]; + uint32_t i, ref_en = 0; + + vcxo_freq = dev->vcxo_freq / 1000; + pll2_freq = dev->pll2_freq / 1000; + + lcm_freq = vcxo_freq; + for (i = 0; i < ARRAY_SIZE(clkin_freq); i++) { + if (dev->clkin_freq_ccf[i]) + clkin_freq[i] = dev->clkin_freq_ccf[i] / 1000; + else + clkin_freq[i] = dev->clkin_freq[i] / 1000; + + if (clkin_freq[i]) { + lcm_freq = greatest_common_divisor(clkin_freq[i], lcm_freq); + ref_en |= BIT(i); + } + } + + while (lcm_freq > HMC7044_RECOMM_LCM_MAX) + lcm_freq /= 2; + + for (i = 0; i < ARRAY_SIZE(clkin_freq); i++) { + if (clkin_freq[i]) + in_prescaler[i] = clkin_freq[i] / lcm_freq; + else + in_prescaler[i] = 1; + } + in_prescaler[4] = vcxo_freq / lcm_freq; + + pll1_lock_detect = log_base_2((lcm_freq * 4000) / dev->pll1_loop_bw); + + /* fVCXO / N1 = fLCM / R1 */ + rational_best_approximation(vcxo_freq, lcm_freq, + HMC7044_N1_MAX, HMC7044_R1_MAX, + &n1, &r1); + + pfd1_freq = vcxo_freq / n1; + while ((pfd1_freq > HMC7044_RECOMM_FPD1) && + (n1 <= HMC7044_N1_MAX / 2) && + (r1 <= HMC7044_R1_MAX / 2)) { + pfd1_freq /= 2; + n1 *= 2; + r1 *= 2; + } + + dev->pll1_pfd = pfd1_freq; + + if (pll2_freq < HMC7044_LOW_VCO_MIN || + pll2_freq > HMC7044_HIGH_VCO_MAX) + return FAILURE; + + vco_limit = (HMC7044_LOW_VCO_MAX + HMC7044_HIGH_VCO_MIN) / 2; + if (pll2_freq >= vco_limit) + high_vco_en = true; + else + high_vco_en = false; + + /* fVCO / N2 = fVCXO * doubler / R2 */ + pll2_freq_doubler_en = true; + rational_best_approximation(pll2_freq, vcxo_freq * 2, + HMC7044_N2_MAX, HMC7044_R2_MAX, + &n2[0], &r2[0]); + + if (pll2_freq != vcxo_freq * n2[0] / r2[0]) { + rational_best_approximation(pll2_freq, vcxo_freq, + HMC7044_N2_MAX, HMC7044_R2_MAX, + &n2[1], &r2[1]); + + if (abs((int)pll2_freq - (int)(vcxo_freq * 2 * n2[0] / r2[0])) > + abs((int)pll2_freq - (int)(vcxo_freq * n2[1] / r2[1]))) { + n2[0] = n2[1]; + r2[0] = r2[1]; + pll2_freq_doubler_en = false; + } + } + + while ((n2[0] < HMC7044_N2_MIN) && (r2[0] <= HMC7044_R2_MAX / 2)) { + n2[0] *= 2; + r2[0] *= 2; + } + if (n2[0] < HMC7044_N2_MIN) + return -FAILURE; + + /* Resets all registers to default values */ + hmc7044_write(dev, HMC7044_REG_SOFT_RESET, HMC7044_SOFT_RESET); + mdelay(10); + hmc7044_write(dev, HMC7044_REG_SOFT_RESET, 0); + mdelay(10); + + /* Disable all channels */ + for (i = 0; i < HMC7044_NUM_CHAN; i++) + hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_0(i), 0); + + /* Load the configuration updates (provided by Analog Devices) */ + hmc7044_write(dev, HMC7044_REG_CLK_OUT_DRV_LOW_PW, 0x4d); + hmc7044_write(dev, HMC7044_REG_CLK_OUT_DRV_HIGH_PW, 0xdf); + hmc7044_write(dev, HMC7044_REG_PLL1_DELAY, 0x06); + hmc7044_write(dev, HMC7044_REG_PLL1_HOLDOVER, 0x06); + hmc7044_write(dev, HMC7044_REG_VTUNE_PRESET, 0x04); + + uint8_t rd_back; + hmc7044_read(dev, HMC7044_REG_CLK_OUT_DRV_LOW_PW, &rd_back); + hmc7044_read(dev, HMC7044_REG_CLK_OUT_DRV_HIGH_PW, &rd_back); + hmc7044_read(dev, HMC7044_REG_PLL1_DELAY, &rd_back); + hmc7044_read(dev, HMC7044_REG_PLL1_HOLDOVER, &rd_back); + hmc7044_read(dev, HMC7044_REG_VTUNE_PRESET, &rd_back); + + hmc7044_write(dev, HMC7044_REG_GLOB_MODE, + HMC7044_SYNC_PIN_MODE(dev->sync_pin_mode) | + (dev->clkin0_rfsync_en ? HMC7044_RFSYNC_EN : 0) | + (dev->clkin1_vcoin_en ? HMC7044_VCOIN_MODE_EN : 0) | + HMC7044_REF_PATH_EN(ref_en)); + + /* Program PLL2 */ + + /* Select the VCO range */ + hmc7044_write(dev, HMC7044_REG_EN_CTRL_0, + (dev->rf_reseeder_en ? HMC7044_RF_RESEEDER_EN : 0) | + HMC7044_VCO_SEL(high_vco_en ? + HMC7044_VCO_HIGH : + HMC7044_VCO_LOW) | + HMC7044_SYSREF_TIMER_EN | HMC7044_PLL2_EN | + HMC7044_PLL1_EN); + + /* Program the dividers */ + hmc7044_write(dev, HMC7044_REG_PLL2_R_LSB, + HMC7044_R2_LSB(r2[0])); + hmc7044_write(dev, HMC7044_REG_PLL2_R_MSB, + HMC7044_R2_MSB(r2[0])); + hmc7044_write(dev, HMC7044_REG_PLL2_N_LSB, + HMC7044_N2_LSB(n2[0])); + hmc7044_write(dev, HMC7044_REG_PLL2_N_MSB, + HMC7044_N2_MSB(n2[0])); + + /* Program the reference doubler */ + hmc7044_write(dev, HMC7044_REG_PLL2_FREQ_DOUBLER, + pll2_freq_doubler_en ? 0 : HMC7044_PLL2_FREQ_DOUBLER_DIS); + + /* Program PLL1 */ + + /* Set the lock detect timer threshold */ + hmc7044_write(dev, HMC7044_REG_PLL1_LOCK_DETECT, + HMC7044_LOCK_DETECT_TIMER(pll1_lock_detect)); + + /* Set the LCM */ + for (i = 0; i < ARRAY_SIZE(clkin_freq); i++) { + hmc7044_write(dev, HMC7044_REG_CLKIN_PRESCALER(i), + in_prescaler[i]); + } + hmc7044_write(dev, HMC7044_REG_OSCIN_PRESCALER, + in_prescaler[4]); + + /* Program the dividers */ + hmc7044_write(dev, HMC7044_REG_PLL1_R_LSB, + HMC7044_R2_LSB(r1)); + hmc7044_write(dev, HMC7044_REG_PLL1_R_MSB, + HMC7044_R2_MSB(r1)); + hmc7044_write(dev, HMC7044_REG_PLL1_N_LSB, + HMC7044_N2_LSB(n1)); + hmc7044_write(dev, HMC7044_REG_PLL1_N_MSB, + HMC7044_N2_MSB(n1)); + + hmc7044_write(dev, HMC7044_REG_PLL1_REF_PRIO_CTRL, + dev->pll1_ref_prio_ctrl); + + /* Program the SYSREF timer */ + + /* Set the divide ratio */ + hmc7044_write(dev, HMC7044_REG_SYSREF_TIMER_LSB, + HMC7044_SYSREF_TIMER_LSB(dev->sysref_timer_div)); + hmc7044_write(dev, HMC7044_REG_SYSREF_TIMER_MSB, + HMC7044_SYSREF_TIMER_MSB(dev->sysref_timer_div)); + + /* Set the pulse generator mode configuration */ + hmc7044_write(dev, HMC7044_REG_PULSE_GEN, + HMC7044_PULSE_GEN_MODE(dev->pulse_gen_mode)); + + /* Enable the input buffers */ + hmc7044_write(dev, HMC7044_REG_CLKIN0_BUF_CTRL, + dev->in_buf_mode[0]); + hmc7044_write(dev, HMC7044_REG_CLKIN1_BUF_CTRL, + dev->in_buf_mode[1]); + hmc7044_write(dev, HMC7044_REG_CLKIN2_BUF_CTRL, + dev->in_buf_mode[2]); + hmc7044_write(dev, HMC7044_REG_CLKIN3_BUF_CTRL, + dev->in_buf_mode[3]); + hmc7044_write(dev, HMC7044_REG_OSCIN_BUF_CTRL, + dev->in_buf_mode[4]); + + /* Set GPIOs */ + for (i = 0; i < ARRAY_SIZE(dev->gpi_ctrl); i++) { + hmc7044_write(dev, HMC7044_REG_GPI_CTRL(i), + dev->gpi_ctrl[i]); + } + + for (i = 0; i < ARRAY_SIZE(dev->gpo_ctrl); i++) { + hmc7044_write(dev, HMC7044_REG_GPO_CTRL(i), + dev->gpo_ctrl[i]); + } + + mdelay(10); + + /* Program the output channels */ + for (i = 0; i < dev->num_channels; i++) { + chan = &dev->channels[i]; + if (chan->num >= HMC7044_NUM_CHAN || chan->disable) + continue; + + hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_1(chan->num), + HMC7044_DIV_LSB(chan->divider)); + hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_2(chan->num), + HMC7044_DIV_MSB(chan->divider)); + hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_8(chan->num), + HMC7044_DRIVER_MODE(chan->driver_mode) | + HMC7044_DRIVER_Z_MODE(chan->driver_impedance) | + (chan->dynamic_driver_enable ? + HMC7044_DYN_DRIVER_EN : 0) | + (chan->force_mute_enable ? + HMC7044_FORCE_MUTE_EN : 0)); + + hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_3(chan->num), + chan->fine_delay & 0x1F); + hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_4(chan->num), + chan->coarse_delay & 0x1F); + hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_7(chan->num), + chan->out_mux_mode & 0x3); + + hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_0(chan->num), + (chan->start_up_mode_dynamic_enable ? + HMC7044_START_UP_MODE_DYN_EN : 0) | + (chan->output_control0_rb4_enable ? BIT(4) : 0) | + (chan->high_performance_mode_dis ? + 0 : HMC7044_HI_PERF_MODE) | HMC7044_SYNC_EN | + HMC7044_CH_EN); + } + mdelay(10); + + /* Do a restart to reset the system and initiate calibration */ + hmc7044_write(dev, HMC7044_REG_REQ_MODE_0, + HMC7044_RESTART_DIV_FSM); + mdelay(1); + hmc7044_write(dev, HMC7044_REG_REQ_MODE_0, + (dev->high_performance_mode_clock_dist_en ? + HMC7044_HIGH_PERF_DISTRIB_PATH : 0)); + mdelay(1); + + return SUCCESS; +} + +/** + * Setup the device. + * @param dev - The device structure. + * @return SUCCESS in case of success, negative error code otherwise. + */ +static int32_t hmc7043_setup(struct hmc7044_dev *dev) +{ + struct hmc7044_chan_spec *chan; + uint32_t i; + + if (dev->clkin_freq_ccf[0]) + dev->pll2_freq = dev->clkin_freq_ccf[0]; + else + dev->pll2_freq = dev->clkin_freq[0]; + + if (!dev->pll2_freq) { + printf("%s: Failed to get valid parent rate\n", __func__); + return FAILURE; + } + + /* Resets all registers to default values */ + hmc7044_write(dev, HMC7044_REG_SOFT_RESET, HMC7044_SOFT_RESET); + mdelay(10); + hmc7044_write(dev, HMC7044_REG_SOFT_RESET, 0); + mdelay(10); + + /* Load the configuration updates (provided by Analog Devices) */ + hmc7044_write(dev, HMC7044_REG_CLK_OUT_DRV_LOW_PW, 0x4d); + hmc7044_write(dev, HMC7044_REG_CLK_OUT_DRV_HIGH_PW, 0xdf); + + /* Disable all channels */ + for (i = 0; i < HMC7044_NUM_CHAN; i++) + hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_0(i), 0); + + if (dev->pll2_freq < 1000000000U) + hmc7044_write(dev, HMC7044_CLK_INPUT_CTRL, + HMC7044_LOW_FREQ_INPUT_MODE); + + hmc7044_write(dev, HMC7044_REG_EN_CTRL_0, + (dev->rf_reseeder_en ? HMC7044_RF_RESEEDER_EN : 0) | + HMC7044_SYSREF_TIMER_EN); + + /* Program the SYSREF timer */ + + /* Set the divide ratio */ + hmc7044_write(dev, HMC7044_REG_SYSREF_TIMER_LSB, + HMC7044_SYSREF_TIMER_LSB(dev->sysref_timer_div)); + hmc7044_write(dev, HMC7044_REG_SYSREF_TIMER_MSB, + HMC7044_SYSREF_TIMER_MSB(dev->sysref_timer_div)); + + /* Set the pulse generator mode configuration */ + hmc7044_write(dev, HMC7044_REG_PULSE_GEN, + HMC7044_PULSE_GEN_MODE(dev->pulse_gen_mode)); + + /* Enable the input buffers */ + hmc7044_write(dev, HMC7044_REG_CLKIN0_BUF_CTRL, + dev->in_buf_mode[0]); + hmc7044_write(dev, HMC7044_REG_CLKIN1_BUF_CTRL, + dev->in_buf_mode[1]); + + /* Set GPIOs */ + hmc7044_write(dev, HMC7044_REG_GPI_CTRL(0), + dev->gpi_ctrl[0]); + + hmc7044_write(dev, HMC7044_REG_GPO_CTRL(0), + dev->gpo_ctrl[0]); + + /* Program the output channels */ + for (i = 0; i < dev->num_channels; i++) { + chan = &dev->channels[i]; + + if (chan->num >= HMC7044_NUM_CHAN || chan->disable) + continue; + + hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_1(chan->num), + HMC7044_DIV_LSB(chan->divider)); + hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_2(chan->num), + HMC7044_DIV_MSB(chan->divider)); + hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_8(chan->num), + HMC7044_DRIVER_MODE(chan->driver_mode) | + HMC7044_DRIVER_Z_MODE(chan->driver_impedance) | + (chan->dynamic_driver_enable ? + HMC7044_DYN_DRIVER_EN : 0) | + (chan->force_mute_enable ? + HMC7044_FORCE_MUTE_EN : 0)); + + hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_3(chan->num), + chan->fine_delay & 0x1F); + hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_4(chan->num), + chan->coarse_delay & 0x1F); + hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_7(chan->num), + chan->out_mux_mode & 0x3); + + hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_0(chan->num), + (chan->start_up_mode_dynamic_enable ? + HMC7044_START_UP_MODE_DYN_EN : 0) | + (chan->output_control0_rb4_enable ? BIT(4) : 0) | + (chan->high_performance_mode_dis ? + 0 : HMC7044_HI_PERF_MODE) | HMC7044_SYNC_EN | + HMC7044_CH_EN); + } + mdelay(10); + + + /* Do a restart to reset the system and initiate calibration */ + hmc7044_write(dev, HMC7044_REG_REQ_MODE_0, + HMC7044_RESTART_DIV_FSM); + mdelay(1); + hmc7044_write(dev, HMC7044_REG_REQ_MODE_0, + (dev->high_performance_mode_clock_dist_en ? + HMC7044_HIGH_PERF_DISTRIB_PATH : 0)); + mdelay(1); + + return SUCCESS; +} + +/***************************************************************************//** + * @brief hmc7044_reg_init + *******************************************************************************/ +int32_t hmc7044_reg_init(struct hmc7044_dev **device, + const struct hmc7044_init_param *init_param) +{ + int ret = SUCCESS; + struct hmc7044_dev *dev; + + dev = (struct hmc7044_dev *)malloc(sizeof(*dev)); + if (!dev) + return FAILURE; + + /* SPI */ + ret = spi_init(&dev->spi_desc, init_param->spi_init); + + *device = dev; + + return ret; +} + +/** + * Initialize the device. + * @param device - The device structure. + * @param init_param - The structure that contains the device initial + * parameters. + * @return SUCCESS in case of success, negative error code otherwise. + */ +int32_t hmc7044_init(struct hmc7044_dev **device, + const struct hmc7044_init_param *init_param) +{ + struct hmc7044_dev *dev; + int32_t ret; + unsigned int i; + + dev = (struct hmc7044_dev *)malloc(sizeof(*dev)); + if (!dev) + return FAILURE; + + ret = spi_init(&dev->spi_desc, init_param->spi_init); + if (ret < 0) + return ret; + + dev->is_hmc7043 = init_param->is_hmc7043; + + dev->clkin_freq[0] = init_param->clkin_freq[0]; + dev->clkin_freq[1] = init_param->clkin_freq[1]; + dev->clkin_freq[2] = init_param->clkin_freq[2]; + dev->clkin_freq[3] = init_param->clkin_freq[3]; + + dev->clkin_freq_ccf[0] = init_param->clkin_freq_ccf[0]; + dev->clkin_freq_ccf[1] = init_param->clkin_freq_ccf[1]; + dev->clkin_freq_ccf[2] = init_param->clkin_freq_ccf[2]; + dev->clkin_freq_ccf[3] = init_param->clkin_freq_ccf[3]; + + dev->vcxo_freq = init_param->vcxo_freq; + dev->pll1_pfd = init_param->pll1_pfd; + dev->pll2_freq = init_param->pll2_freq; + dev->pll1_loop_bw = init_param->pll1_loop_bw; + + dev->sysref_timer_div = init_param->sysref_timer_div; + dev->pll1_ref_prio_ctrl = init_param->pll1_ref_prio_ctrl; + dev->clkin0_rfsync_en = init_param->clkin0_rfsync_en; + dev->clkin1_vcoin_en = init_param->clkin1_vcoin_en; + dev->high_performance_mode_clock_dist_en = + init_param->high_performance_mode_clock_dist_en; + dev->rf_reseeder_en = !init_param->rf_reseeder_disable; + dev->sync_pin_mode = init_param->sync_pin_mode; + dev->pulse_gen_mode = init_param->pulse_gen_mode; + + dev->in_buf_mode[0] = init_param->in_buf_mode[0]; + dev->in_buf_mode[1] = init_param->in_buf_mode[1]; + dev->in_buf_mode[2] = init_param->in_buf_mode[2]; + dev->in_buf_mode[3] = init_param->in_buf_mode[3]; + dev->in_buf_mode[4] = init_param->in_buf_mode[4]; + + dev->gpi_ctrl[0] = init_param->gpi_ctrl[0]; + dev->gpi_ctrl[1] = init_param->gpi_ctrl[1]; + dev->gpi_ctrl[2] = init_param->gpi_ctrl[2]; + dev->gpi_ctrl[3] = init_param->gpi_ctrl[3]; + + dev->gpo_ctrl[0] = init_param->gpo_ctrl[0]; + dev->gpo_ctrl[1] = init_param->gpo_ctrl[1]; + dev->gpo_ctrl[2] = init_param->gpo_ctrl[2]; + dev->gpo_ctrl[3] = init_param->gpo_ctrl[3]; + + dev->num_channels = init_param->num_channels; + dev->channels = (struct hmc7044_chan_spec *) + malloc(sizeof(*dev->channels) * dev->num_channels); + + for (i = 0; i < dev->num_channels; i++) { + dev->channels[i].num = init_param->channels[i].num; + dev->channels[i].disable = init_param->channels[i].disable; + dev->channels[i].divider = init_param->channels[i].divider; + dev->channels[i].driver_mode = + init_param->channels[i].driver_mode; + dev->channels[i].high_performance_mode_dis = + init_param->channels[i].high_performance_mode_dis; + dev->channels[i].start_up_mode_dynamic_enable = + init_param->channels[i].start_up_mode_dynamic_enable; + dev->channels[i].dynamic_driver_enable = + init_param->channels[i].dynamic_driver_enable; + dev->channels[i].output_control0_rb4_enable = + init_param->channels[i].output_control0_rb4_enable; + dev->channels[i].force_mute_enable = + init_param->channels[i].force_mute_enable; + dev->channels[i].driver_impedance = + init_param->channels[i].driver_impedance; + dev->channels[i].coarse_delay = + init_param->channels[i].coarse_delay; + dev->channels[i].fine_delay = + init_param->channels[i].fine_delay; + dev->channels[i].out_mux_mode = + init_param->channels[i].out_mux_mode; + } + + *device = dev; + + if (!dev->is_hmc7043) + return hmc7044_setup(dev); + else + return hmc7043_setup(dev); +} + +/** + * Remove the device - release resources. + * @param device - The device structure. + * @return SUCCESS in case of success, negative error code otherwise. + */ +int32_t hmc7044_remove(struct hmc7044_dev *device) +{ + int32_t ret; + + ret = spi_remove(device->spi_desc); + free(device->channels); + free(device); + + return ret; +} diff --git a/df_datalink/src/drivers/frequency/hmc7044/hmc7044.h b/df_datalink/src/drivers/frequency/hmc7044/hmc7044.h new file mode 100644 index 0000000..a178975 --- /dev/null +++ b/df_datalink/src/drivers/frequency/hmc7044/hmc7044.h @@ -0,0 +1,276 @@ +/***************************************************************************//** + * @file hmc7044.h + * @brief Header file of HMC7044, HMC7043 Driver. + * @author DBogdan (dragos.bogdan@analog.com) +******************************************************************************** + * Copyright 2018-2020(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ +#ifndef HMC7044_H_ +#define HMC7044_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include +#include +#include "delay.h" +#include "spi.h" + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ +// Enum to select SYNC pin configuration with respect to PLL2 (0x0005) +typedef enum +{ + SYNC_DISABLED = 0, + SYNC_MULTICHIP = 1, + SYNC_PULSE_GEN = 2, + SYNC_ALARM = 3 +} hmc7044SyncPinModeSelect_t; + +// Enum to select input buffer mode (0x000A, 0x000B, 0x000C, 0x000D, 0x000E) +typedef enum +{ + BUFFER_ENABLE = (1) << 0, + BUFFER_DISABLE = (0) << 0, + ENABLE_INTERNAL_TERM = (1) << 1, + ENABLE_AC_COUPLE = (1) << 2, + ENABLE_LVPECL = (1) << 3, + ENABLE_HIGH_Z = (1) << 4 +} hmc7044InputBufferMode_t; + +// Enum to select output driver mode (0x003A, 0x003B, 0x00D0, 0x00DA, 0x00E4, +// 0x00EE, 0x00F8, 0x0102, 0x010C, 0x0116, 0x0120, 0x012A, 0x0134, 0x013E, +// 0x0148, 0x0152) +typedef enum +{ + CML = 0, + LVPECL = 1, + LVDS = 2, + CMOS = 3 +} hmc7044DriverMode_t; + +// Enum to select the GPIx functionality. (0x0046, 0x0047, 0x0048, 0x0049) +typedef enum +{ + GPI_ENABLE = (1) << 0, + GPI_DISABLE = (0) << 0, + FORCE_PLL1_HOLDOVER = (0x01) << 1 | GPI_ENABLE, + SELECT_PLL1_REF_BIT1 = (0x02) << 1 | GPI_ENABLE, + SELECT_PLL1_REF_BIT2 = (0x03) << 1 | GPI_ENABLE, + CHIP_SLEEP_MODE = (0x04) << 1 | GPI_ENABLE, + MUTE_REQUSET = (0x05) << 1 | GPI_ENABLE, + SELECT_INTERNAL_VCO_TYPE = (0x06) << 1 | GPI_ENABLE, + SELECT_HI_PERF_MODE = (0x07) << 1 | GPI_ENABLE, + PULSE_GEN_REQUSET = (0x08) << 1 | GPI_ENABLE, + RESEED_REQUEST = (0x09) << 1 | GPI_ENABLE, + RESTART_REQUSET = (0x0A) << 1 | GPI_ENABLE, + FORCE_FANOUT_MODE = (0x0B) << 1 | GPI_ENABLE, + SLIP_REQUEST = (0x0D) << 1 | GPI_ENABLE, +} hmc7044GPIControl_t; + +// Enum to select the GPOx functionality. (0x0050, 0x0051, 0x0052, 0x0053) +typedef enum +{ + GPO_ENABLE = (1) << 0, + GPO_DISABLE = (0) << 0, + GPO_CMOS_MODE = (1) << 1, + GPO_OPEN_DRAIN_MODE = (0) << 1, + ALARM_SIGNAL = (0x00) << 3 | GPO_ENABLE, + SPI_SDATA = (0x01) << 3 | GPO_ENABLE, + CLKIN3_SIGNAL_LOSS = (0x02) << 3 | GPO_ENABLE, + CLKIN2_SIGNAL_LOSS = (0x03) << 3 | GPO_ENABLE, + CLKIN1_SIGNAL_LOSS = (0x04) << 3 | GPO_ENABLE, + CLKIN0_SIGNAL_LOSS = (0x05) << 3 | GPO_ENABLE, + PLL1_HOLDOVER_ENABLE = (0x06) << 3 | GPO_ENABLE, + PLL1_LOCK_DETECT = (0x07) << 3 | GPO_ENABLE, + PLL1_ACQUIRING_LOCK = (0x08) << 3 | GPO_ENABLE, + PLL1_NEAR_CLOCK_ACQ_STAT = (0x09) << 3 | GPO_ENABLE, + PLL2_LOCK_DETECT = (0x0A) << 3 | GPO_ENABLE, + PLL2_SYSREF_SYNC = (0x0B) << 3 | GPO_ENABLE, + CLOCK_OUTPUT_PHASE_STAT = (0x0C) << 3 | GPO_ENABLE, + PLL1_PLL2_LOCKED = (0x0D) << 3 | GPO_ENABLE, + SYNC_REQUSRT_STAT = (0x0E) << 3 | GPO_ENABLE, + PLL1_ACTIVE_CLKIN0 = (0x0F) << 3 | GPO_ENABLE, + PLL1_ACTIVE_CLKIN1 = (0x10) << 3 | GPO_ENABLE, + PLL1_HOLDOVER_IN_RANGE_STAT = (0x11) << 3 | GPO_ENABLE, + PLL1_HOLDOVER_IN_STAT = (0x12) << 3 | GPO_ENABLE, + PLL1_VCXO_STAT = (0x13) << 3 | GPO_ENABLE, + PLL1_ACTIVE_CLKINx_STAT = (0x14) << 3 | GPO_ENABLE, + PLL1_FSM_BIT0 = (0x15) << 3 | GPO_ENABLE, + PLL1_FSM_BIT1 = (0x16) << 3 | GPO_ENABLE, + PLL1_FSM_BIT2 = (0x17) << 3 | GPO_ENABLE, + PLL1_HOLDOVER_EXIT_PHASE_BIT0 = (0x18) << 3 | GPO_ENABLE, + PLL1_HOLDOVER_EXIT_PHASE_BIT1 = (0x19) << 3 | GPO_ENABLE, + CHANNEL_OUTPUT_FSM_BUSY = (0x1A) << 3 | GPO_ENABLE, + SYSREF_FSM_STAT_BIT0 = (0x1B) << 3 | GPO_ENABLE, + SYSREF_FSM_STAT_BIT1 = (0x1C) << 3 | GPO_ENABLE, + SYSREF_FSM_STAT_BIT2 = (0x1D) << 3 | GPO_ENABLE, + SYSREF_FSM_STAT_BIT3 = (0x1E) << 3 | GPO_ENABLE, + FORCE_LOGIC_1 = (0x1F) << 3 | GPO_ENABLE, + FORCE_LOGIC_0 = (0x20) << 3 | GPO_ENABLE, + PLL1_HOLDOVER_AVG_VALUE_BIT0 = (0x27) << 3 | GPO_ENABLE, + PLL1_HOLDOVER_AVG_VALUE_BIT1 = (0x28) << 3 | GPO_ENABLE, + PLL1_HOLDOVER_AVG_VALUE_BIT2 = (0x29) << 3 | GPO_ENABLE, + PLL1_HOLDOVER_AVG_VALUE_BIT3 = (0x2A) << 3 | GPO_ENABLE, + PLL1_HOLDOVER_CURR_VALUE_BIT0 = (0x2B) << 3 | GPO_ENABLE, + PLL1_HOLDOVER_CURR_VALUE_BIT1 = (0x2C) << 3 | GPO_ENABLE, + PLL1_HOLDOVER_CURR_VALUE_BIT2 = (0x2D) << 3 | GPO_ENABLE, + PLL1_HOLDOVER_CURR_VALUE_BIT3 = (0x2E) << 3 | GPO_ENABLE +} hmc7044GPOControl_t; + +// Enum to select output channel (0x00CF, 0x00D9, 0x00E3, 0x00ED, 0x00F7, +// 0x0101, 0x010B, 0x0115, 0x011F, 0x0129, 0x0133, 0x013D, 0x0147, 0x0151 +typedef enum +{ + CHANNEL_DIV = 0, + ANALOG_DELAY = 1, + OTHER_CHANNEL = 2, + VCO_CLOCK = 3 +} hmc7044OutputMuxSelect_t; + +// Enum to select output driver impedance selection for CML mode (0x00D0, +// 0x00DA, 0x00E4, 0x00EE, 0x00F8, 0x0102, 0x010C, 0x0116, 0x0120, 0x012A, +// 0x0134, 0x013E, 0x0148, 0x0152) +typedef enum +{ + INTERNAL_RES_DISABLE = 0, + INTERNAL_100OHM_PER_PIN = 1, +// INTERNAL_RES_RESERVED = 2, + INTERNAL_50OHM_PER_PIN = 3 +} hmc7044DriverImpedance_t; + +// Enum to select pulse generator mode (0x005A) +typedef enum +{ + PULSE_LEVEL_SENSITIVE = 0, + PULSE_ONE = 1, + PULSE_TWO = 2, + PULSE_FOUR = 3, + PULSE_EIGHT = 4, + PULSE_SIXTEEN = 5, +// PULSE_SIXTEEN = 6, + PULSE_CONTINOUS = 7 +} hmc7044SyncPulseGenControl_t; + +struct hmc7044_chan_spec { + unsigned int num; + bool disable; + bool high_performance_mode_dis; + bool start_up_mode_dynamic_enable; + bool dynamic_driver_enable; + bool output_control0_rb4_enable; + bool force_mute_enable; + unsigned int divider; + unsigned int coarse_delay; + unsigned int fine_delay; + hmc7044DriverMode_t driver_mode; + hmc7044DriverImpedance_t driver_impedance; + hmc7044OutputMuxSelect_t out_mux_mode; +}; + +struct hmc7044_config { + uint16_t addr; + uint8_t value; +}; + +struct hmc7044_dev { + struct spi_desc *spi_desc; + bool is_hmc7043; + uint32_t clkin_freq[4]; + uint32_t clkin_freq_ccf[4]; + uint32_t vcxo_freq; + uint32_t pll1_pfd; + uint32_t pll2_freq; + uint32_t pll1_loop_bw; + uint32_t sysref_timer_div; + unsigned int pll1_ref_prio_ctrl; + bool clkin0_rfsync_en; + bool clkin1_vcoin_en; + bool high_performance_mode_clock_dist_en; + bool rf_reseeder_en; + hmc7044SyncPinModeSelect_t sync_pin_mode; + hmc7044SyncPulseGenControl_t pulse_gen_mode; + uint32_t in_buf_mode[5]; + uint32_t gpi_ctrl[4]; + uint32_t gpo_ctrl[4]; + uint32_t num_channels; + struct hmc7044_chan_spec *channels; +}; + +struct hmc7044_init_param { + struct spi_init_param *spi_init; + bool is_hmc7043; + uint32_t clkin_freq[4]; + uint32_t clkin_freq_ccf[4]; + uint32_t vcxo_freq; + uint32_t pll1_pfd; + uint32_t pll2_freq; + uint32_t pll1_loop_bw; + uint32_t sysref_timer_div; + unsigned int pll1_ref_prio_ctrl; + bool clkin0_rfsync_en; + bool clkin1_vcoin_en; + bool high_performance_mode_clock_dist_en; + bool rf_reseeder_disable; + hmc7044SyncPinModeSelect_t sync_pin_mode; + hmc7044SyncPulseGenControl_t pulse_gen_mode; + uint32_t in_buf_mode[5]; + uint32_t gpi_ctrl[4]; + uint32_t gpo_ctrl[4]; + uint32_t num_channels; + struct hmc7044_chan_spec *channels; +}; + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ +/* Initialize the device. */ +int32_t hmc7044_reg_init(struct hmc7044_dev **device, + const struct hmc7044_init_param *init_param); +int32_t hmc7044_init(struct hmc7044_dev **device, + const struct hmc7044_init_param *init_param); +/* Remove the device. */ +int32_t hmc7044_remove(struct hmc7044_dev *device); +int32_t hmc7044_write(struct hmc7044_dev *dev, + uint16_t reg, uint8_t val); +int32_t hmc7044_read(struct hmc7044_dev *dev, uint16_t reg, uint8_t *val); +int32_t hmc7044_clk_recalc_rate(struct hmc7044_dev *dev, uint32_t chan_num, + uint64_t *rate); +int32_t hmc7044_clk_round_rate(struct hmc7044_dev *dev, uint32_t rate, + uint64_t *rounded_rate); +int32_t hmc7044_clk_set_rate(struct hmc7044_dev *dev, uint32_t chan_num, + uint64_t rate); + +#endif // HMC7044_H_ diff --git a/df_datalink/src/drivers/platform/xilinx_axi_io.c b/df_datalink/src/drivers/platform/xilinx_axi_io.c new file mode 100644 index 0000000..5c33838 --- /dev/null +++ b/df_datalink/src/drivers/platform/xilinx_axi_io.c @@ -0,0 +1,79 @@ +/***************************************************************************//** + * @file xilinx/xilinx_axi_io.c + * @brief Implementation of Xilinx AXI IO. + * @author Antoniu Miclaus (antoniu.miclaus@analog.com) +******************************************************************************** + * Copyright 2019(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include +#include "error.h" +#include "axi_io.h" + +/******************************************************************************/ +/************************ Functions Definitions *******************************/ +/******************************************************************************/ + +/** + * @brief AXI IO Xilinx specific read function. + * @param base - Base address + * @param offset - Address offset + * @param data - variable where returned data is stored + * @return 0 in case of success, -1 otherwise. + */ +int32_t axi_io_read(uint32_t base, uint32_t offset, uint32_t *data) +{ + *data = Xil_In32(base + offset); + + return 0; +} + +/** + * @brief AXI IO Xilinx specific write function. + * @param base - Base address + * @param offset - Address offset + * @param data - data to be written. + * @return 0 in case of success, -1 otherwise. + */ +int32_t axi_io_write(uint32_t base, uint32_t offset, uint32_t data) +{ + Xil_Out32(base + offset, data); + + return 0; +} + diff --git a/df_datalink/src/drivers/platform/xilinx_delay.c b/df_datalink/src/drivers/platform/xilinx_delay.c new file mode 100644 index 0000000..3c320f6 --- /dev/null +++ b/df_datalink/src/drivers/platform/xilinx_delay.c @@ -0,0 +1,100 @@ +/***************************************************************************//** + * @file xilinx/xilinx_delay.c + * @brief Implementation of Xilinx Delay Functions. + * @author Antoniu Miclaus (antoniu.miclaus@analog.com) +******************************************************************************** + * Copyright 2019(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include "delay.h" +#include +#ifdef _XPARAMETERS_PS_H_ +#include "util.h" +#include "xtime_l.h" +#endif + +/******************************************************************************/ +/************************ Functions Definitions *******************************/ +/******************************************************************************/ + +/** + * @brief Generate microseconds delay. + * @param usecs - Delay in microseconds. + * @return None. + */ +void udelay(uint32_t usecs) +{ +#ifdef _XPARAMETERS_PS_H_ + usleep(usecs); +#else + usleep_MB(usecs); +#endif +} + +/** + * @brief Generate miliseconds delay. + * @param msecs - Delay in miliseconds. + * @return None. + */ +void mdelay(uint32_t msecs) +{ +#ifdef _XPARAMETERS_PS_H_ + usleep(msecs * 1000); +#else + usleep_MB(msecs * 1000); +#endif +} + +/** + * @brief Get current time. + * @return Current time structure from system start (seconds, microseconds). + */ +struct time get_time(void) +{ + struct time t = {0, 0}; +#ifdef _XPARAMETERS_PS_H_ + unsigned long long Xtime_Global; + uint32_t rem; + + XTime_GetTime(&Xtime_Global); + t.s = div_u64_rem(Xtime_Global, COUNTS_PER_SECOND, &rem); + t.us = div_u64((uint64_t)rem * 1000000, COUNTS_PER_SECOND); +#endif + + return t; +} diff --git a/df_datalink/src/drivers/platform/xilinx_gpio.c b/df_datalink/src/drivers/platform/xilinx_gpio.c new file mode 100644 index 0000000..274399d --- /dev/null +++ b/df_datalink/src/drivers/platform/xilinx_gpio.c @@ -0,0 +1,464 @@ +/***************************************************************************//** + * @file xilinx/xilinx_gpio.c + * @brief Implementation of Xilinx GPIO Generic Driver. + * @author Antoniu Miclaus (antoniu.miclaus@analog.com) +******************************************************************************** + * Copyright 2019(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include + +#include +#ifdef XPAR_XGPIO_NUM_INSTANCES +#include +#endif +#ifdef XPAR_XGPIOPS_NUM_INSTANCES +#include +#endif + +#include "error.h" +#include "gpio.h" +#include "xilinx_gpio.h" + +/******************************************************************************/ +/************************ Functions Definitions *******************************/ +/******************************************************************************/ + +/** + * @brief Prepare the GPIO decriptor. + * @param desc - The GPIO descriptor. + * @param param - The structure that contains the GPIO parameters. + * @return 0 in case of success, -1 otherwise. + */ +int32_t _gpio_init(struct gpio_desc *desc, + const struct gpio_init_param *param) +{ + int32_t ret; + struct xil_gpio_desc *xdesc; + struct xil_gpio_init_param *xinit; + + ret = -1; + + xdesc = desc->extra; + xinit = param->extra; + + xdesc->type = xinit->type; + desc->number = param->number; + + switch (xinit->type) { + case GPIO_PL: +#ifdef XGPIO_H + xdesc->instance = (XGpio *)malloc(sizeof(XGpio)); + if(!xdesc->instance) + goto pl_error; + + xdesc->config = XGpio_LookupConfig(xinit->device_id); + if(xdesc->config == NULL) + goto pl_error; + + ret = XGpio_CfgInitialize(xdesc->instance, + xdesc->config, + ((XGpio_Config*)xdesc->config) + ->BaseAddress); + if(ret < 0) + goto pl_error; + + break; +pl_error: + free(xdesc->instance); +#endif + goto error; + case GPIO_PS: +#ifdef XGPIOPS_H + xdesc->instance = (XGpioPs *)malloc(sizeof(XGpioPs)); + if(!xdesc->instance) + goto ps_error; + + xdesc->config = XGpioPs_LookupConfig(xinit->device_id); + if(xdesc->config == NULL) + goto ps_error; + + ret = XGpioPs_CfgInitialize(xdesc->instance, + xdesc->config, + ((XGpioPs_Config*)xdesc->config)->BaseAddr); + if(ret < 0) + goto ps_error; + break; +ps_error: + free(xdesc->instance); +#endif + goto error; +error: + default: + return -1; + } + + return 0; +} + +/** + * @brief Obtain the GPIO decriptor. + * @param desc - The GPIO descriptor. + * @param param - GPIO initialization parameters + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_gpio_get(struct gpio_desc **desc, + const struct gpio_init_param *param) +{ + struct gpio_desc *descriptor; + struct xil_gpio_desc *extra; + int32_t ret; + + descriptor = (struct gpio_desc *)malloc(sizeof(*descriptor)); + extra = (struct xil_gpio_desc*)malloc(sizeof(*extra)); + + if (!descriptor || !extra) + return -1; + + descriptor->extra = extra; + ret = _gpio_init(descriptor, param); + + if(ret != 0) + goto error; + + *desc = descriptor; + + return 0; +error: + free(extra); + free(descriptor); + + return -1; +} + +/** + * @brief Get the value of an optional GPIO. + * @param desc - The GPIO descriptor. + * @param param - GPIO Initialization parameters. + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_gpio_get_optional(struct gpio_desc **desc, + const struct gpio_init_param *param) +{ + if(param == NULL) { + *desc = NULL; + return 0; + } + + return xil_gpio_get(desc, param); +} + +/** + * @brief Free the resources allocated by gpio_get(). + * @param desc - The GPIO descriptor. + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_gpio_remove(struct gpio_desc *desc) +{ + if (desc != NULL) { + free(((struct xil_gpio_desc *)(desc->extra))->instance); + free(desc->extra); + free(desc); + } + + return 0; +} + +/** + * @brief Enable the input direction of the specified GPIO. + * @param desc - The GPIO descriptor. + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_gpio_direction_input(struct gpio_desc *desc) +{ + struct xil_gpio_desc *extra; +#ifdef XGPIO_H + uint8_t pin = desc->number; + uint32_t channel = 1; + uint32_t config = 0; +#endif + extra = desc->extra; + + switch (extra->type) { + case GPIO_PL: +#ifdef XGPIO_H + /* We assume that pin 32 is the first pin from channel 2 */ + if (pin >= 32) { + channel = 2; + pin -= 32; + } + + config = XGpio_GetDataDirection((XGpio *)extra->instance, + channel); + config |= (1 << pin); + XGpio_SetDataDirection((XGpio *)extra->instance, + channel, + config); +#endif + break; + case GPIO_PS: +#ifdef XGPIOPS_H + XGpioPs_SetDirectionPin(extra->instance, + desc->number, + GPIO_IN); +#endif + break; + default: + return -1; + } + + return 0; +} + +/** + * @brief Enable the output direction of the specified GPIO. + * @param desc - The GPIO descriptor. + * @param value - The value. + * Example: GPIO_HIGH + * GPIO_LOW + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_gpio_direction_output(struct gpio_desc *desc, + uint8_t value) +{ + struct xil_gpio_desc *extra; +#ifdef XGPIO_H + uint8_t pin = desc->number; + uint8_t channel; + uint32_t reg_val; +#endif + extra = desc->extra; + + switch (extra->type) { + case GPIO_PL: +#ifdef XGPIO_H + if (pin >= 32) { + channel = 2; + pin -= 32; + } else + channel = 1; + + reg_val = XGpio_GetDataDirection(extra->instance, + channel); + reg_val &= ~(1 << pin); + XGpio_SetDataDirection(extra->instance, + channel, + reg_val); + reg_val = XGpio_DiscreteRead(extra->instance, + channel); + if(value) + reg_val |= (1 << pin); + else + reg_val &= ~(1 << pin); + XGpio_DiscreteWrite(extra->instance, + channel, + reg_val); +#endif + break; + case GPIO_PS: +#ifdef XGPIOPS_H + XGpioPs_SetDirectionPin(extra->instance, + desc->number, + GPIO_OUT); + XGpioPs_SetOutputEnablePin(extra->instance, + desc->number, + GPIO_OUT); + XGpioPs_WritePin(extra->instance, + desc->number, + value); +#endif + break; + default: + return -1; + } + + return 0; +} + +/** + * @brief Get the direction of the specified GPIO. + * @param desc - The GPIO descriptor. + * @param direction - The direction. + * Example: GPIO_OUT + * GPIO_IN + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_gpio_get_direction(struct gpio_desc *desc, + uint8_t *direction) +{ + if (!desc) + return -1; + + struct xil_gpio_desc *extra; + uint8_t pin = desc->number; + +#ifdef XGPIO_H + uint8_t channel; +#endif + extra = desc->extra; + + switch (extra->type) { + case GPIO_PL: +#ifdef XGPIO_H + if (pin >= 32) { + channel = 2; + pin -= 32; + } else + channel = 1; + *direction = ((XGpio_GetDataDirection(extra->instance, + channel) >> pin) & 0x1) ^ 0x1; +#endif + break; + case GPIO_PS: +#ifdef XGPIOPS_H + *direction = XGpioPs_GetDirectionPin(extra->instance, pin); +#endif + break; + default: + return -1; + } + + return 0; +} + +/** + * @brief Set the value of the specified GPIO. + * @param desc - The GPIO descriptor. + * @param value - The value. + * Example: GPIO_HIGH + * GPIO_LOW + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_gpio_set_value(struct gpio_desc *desc, + uint8_t value) +{ + struct xil_gpio_desc *extra; +#ifdef XGPIO_H + uint8_t pin = desc->number; + uint8_t channel; + uint32_t reg_val; +#endif + extra = desc->extra; + + switch (extra->type) { + case GPIO_PL: +#ifdef XGPIO_H + if (pin >= 32) { + channel = 2; + pin -= 32; + } else + channel = 1; + + reg_val = XGpio_DiscreteRead(extra->instance, channel); + if(value) + reg_val |= (1 << pin); + else + reg_val &= ~(1 << pin); + XGpio_DiscreteWrite(extra->instance, channel, reg_val); +#endif + break; + case GPIO_PS: +#ifdef XGPIOPS_H + XGpioPs_WritePin(extra->instance, desc->number, value); +#endif + break; + default: + return -1; + } + + return 0; +} + +/** + * @brief Get the value of the specified GPIO. + * @param desc - The GPIO descriptor. + * @param value - The value. + * Example: GPIO_HIGH + * GPIO_LOW + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_gpio_get_value(struct gpio_desc *desc, + uint8_t *value) +{ + if (!desc) + return -1; + + struct xil_gpio_desc *extra; + uint8_t pin = desc->number; + +#ifdef XGPIO_H + uint8_t channel; +#endif + extra = desc->extra; + + switch (extra->type) { + case GPIO_PL: +#ifdef XGPIO_H + if (pin >= 32) { + channel = 2; + pin -= 32; + } else + channel = 1; + *value = (XGpio_DiscreteRead(extra->instance, channel) >> pin) & 0x01; +#endif + break; + case GPIO_PS: +#ifdef XGPIOPS_H + *value = XGpioPs_ReadPin(extra->instance, pin); +#endif + break; + default: + return -1; + } + + return 0; +} + +/** + * @brief Xilinx platform specific GPIO platform ops structure + */ +const struct gpio_platform_ops xil_gpio_ops = { + .gpio_ops_get = &xil_gpio_get, + .gpio_ops_get_optional = &xil_gpio_get_optional, + .gpio_ops_remove = &xil_gpio_remove, + .gpio_ops_direction_input = &xil_gpio_direction_input, + .gpio_ops_direction_output = &xil_gpio_direction_output, + .gpio_ops_get_direction = &xil_gpio_get_direction, + .gpio_ops_set_value = &xil_gpio_set_value, + .gpio_ops_get_value = &xil_gpio_get_value, +}; diff --git a/df_datalink/src/drivers/platform/xilinx_gpio.h b/df_datalink/src/drivers/platform/xilinx_gpio.h new file mode 100644 index 0000000..041a1d6 --- /dev/null +++ b/df_datalink/src/drivers/platform/xilinx_gpio.h @@ -0,0 +1,95 @@ +/******************************************************************************* + * @file xilinx/xilinx_gpio.h + * @brief Header containing extra types used in the gpio driver + * @author scuciurean (sergiu.cuciurean@analog.com) +******************************************************************************** + * Copyright 2019(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#ifndef XILINX_GPIO_H_ +#define XILINX_GPIO_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include +#include + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ + +/** + * @enum xil_gpio_type + * @brief Xilinx platform architecture sections + */ +enum xil_gpio_type { + /** Programmable Logic */ + GPIO_PL, + /** Processing System */ + GPIO_PS +}; + +/** + * @struct xil_gpio_init_param + * @brief Structure holding the initialization parameters for Xilinx platform + * specific GPIO parameters. + */ +struct xil_gpio_init_param { + /** Xilinx architecture */ + enum xil_gpio_type type; + /** Device ID */ + uint32_t device_id; +}; + +/** + * @struct xil_gpio_desc + * @brief Xilinx platform specific GPIO descriptor + */ +struct xil_gpio_desc { + /** Xilinx architecture */ + enum xil_gpio_type type; + /** Xilinx GPIO configuration */ + void *config; + /** Xilinx GPIO Instance */ + void *instance; +}; + +/** + * @brief Xilinx platform specific gpio platform ops structure + */ +extern const struct gpio_platform_ops xil_gpio_ops; + +#endif diff --git a/df_datalink/src/drivers/platform/xilinx_gpio_irq.c b/df_datalink/src/drivers/platform/xilinx_gpio_irq.c new file mode 100644 index 0000000..f153c2a --- /dev/null +++ b/df_datalink/src/drivers/platform/xilinx_gpio_irq.c @@ -0,0 +1,360 @@ +/***************************************************************************//** + * @file xilinx/xilinx_gpio_irq.c + * @brief Implementation of Xilinx GPIO IRQ Generic Driver. + * @author Porumb Andrei (andrei.porumb@analog.com) +******************************************************************************** + * Copyright 2021(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include +#include "xparameters.h" +#include "error.h" +#include "xilinx_gpio_irq.h" +#include "util.h" +#include "list.h" +#include "irq.h" + +/******************************************************************************/ +/************************ Functions Definitions *******************************/ +/******************************************************************************/ + +/** + * @brief Comparing function used by list. + * @param desc_a - Compared item + * @param desc_b - Reference item + * @return - 0 if items match + */ +static int32_t call_cmp(struct xil_callback_desc *desc_a, + struct xil_callback_desc *desc_b) +{ + return desc_a->pin_nb - desc_b->pin_nb; +} + +/** + * @brief Function called when GPIO IRQ occurs. + * @param param - GPIO IRQ desc's extra field + * @return - None. + */ +static void xil_gpio_irq_handler(struct xil_gpio_irq_desc *param) +{ + int32_t status = 0; + int32_t pin_nb; + struct xil_callback_desc *callback_desc; + + status = iterator_move_to_idx(param->it, 0); + while(!status) { + iterator_read(param->it, &callback_desc); + status = iterator_move(param->it, 1); + if(XGpioPs_IntrGetStatusPin(¶m->my_Gpio, callback_desc->pin_nb)) + callback_desc->triggered = true; + } + + status = iterator_move_to_idx(param->it, 0); + while(!status) { + iterator_read(param->it, &callback_desc); + status = iterator_move(param->it, 1); + if(callback_desc->triggered == true) { + callback_desc->triggered = false; + XGpioPs_IntrDisablePin(¶m->my_Gpio, callback_desc->pin_nb); + XGpioPs_IntrClearPin(¶m->my_Gpio, callback_desc->pin_nb); + callback_desc->callback.legacy_callback(callback_desc->callback.ctx, 0U, NULL); + if(callback_desc->enabled) + XGpioPs_IntrEnablePin(¶m->my_Gpio, callback_desc->pin_nb); + } + } +} + +/** + * @brief Disable specific GPIO IRQ pin. + * @param desc - The GPIO IRQ controller descriptor. + * @param irq_id - Pin number. + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_gpio_irq_disable(struct irq_ctrl_desc *desc, uint32_t irq_id) +{ + int32_t status; + struct xil_gpio_irq_desc *extra; + struct xil_callback_desc *callback_desc; + + extra = desc->extra; + + status = iterator_move_to_idx(extra->it, 0); + while(!status) { + iterator_read(extra->it, &callback_desc); + status = iterator_move(extra->it, 1); + if(callback_desc->pin_nb == irq_id) { + callback_desc->enabled = false; + break; + } + } + + XGpioPs_IntrDisablePin(&extra->my_Gpio, irq_id); + + return 0; +} + +/** + * @brief Initialize the GPIO IRQ controller. + * @param desc - The GPIO IRQ controller descriptor. + * @param param - The GPIO IRQ controller initial parameters. + * irq_ctrl_id from irq_init_param is the interrupt id for the parent controller + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_gpio_irq_ctrl_init(struct irq_ctrl_desc **desc, + const struct irq_init_param *param) +{ + int32_t i; + int32_t status; + struct irq_ctrl_desc *ldesc; + static XGpioPs_Config *GPIO_Config; + struct xil_gpio_irq_desc *xil_desc; + struct xil_gpio_irq_init_param *xil_ip; + struct callback_desc callback; + + xil_desc = (struct xil_gpio_irq_desc *)calloc(1, sizeof(*xil_desc)); + if(!xil_desc) + return -ENOMEM; + + ldesc = (struct irq_ctrl_desc *)calloc(1, sizeof(*ldesc)); + if(!ldesc) { + free(xil_desc); + return -ENOMEM; + } + + xil_ip = param->extra; + GPIO_Config = XGpioPs_LookupConfig(xil_ip->gpio_device_id); + status = XGpioPs_CfgInitialize(&xil_desc->my_Gpio, GPIO_Config, + GPIO_Config->BaseAddr); + if(status) + goto error_desc; + + ldesc->extra = xil_desc; + xil_desc->parent_desc = xil_ip->parent_desc; + + status = list_init(&xil_desc->callback_list, LIST_DEFAULT, + call_cmp); + if(status) + goto error_list; + + status = iterator_init(&xil_desc->it, xil_desc->callback_list, 0); + if(status) { + iterator_remove(xil_desc->it); + goto error_list; + } + + ldesc->irq_ctrl_id = param->irq_ctrl_id; + status = irq_trigger_level_set(xil_desc->parent_desc, ldesc->irq_ctrl_id, + IRQ_EDGE_RISING); + if(status) + goto error_op; + + status = irq_enable(xil_desc->parent_desc, ldesc->irq_ctrl_id); + if(status) + goto error_op; + + callback.legacy_callback = &xil_gpio_irq_handler; + callback.ctx = ldesc->extra; + status = irq_register_callback(xil_desc->parent_desc, ldesc->irq_ctrl_id, + &callback); + if(status) + goto error_op; + + *desc = ldesc; + + return 0; + +error_op: + iterator_remove(xil_desc->it); +error_list: + list_remove(xil_desc->callback_list); +error_desc: + free(xil_desc); + free(ldesc); + return status; +} + +/** + * @brief Set GPIO interrupt trigger level. + * @param desc - The GPIO IRQ controller descriptor. + * @param irq_id - Pin number. + * @param trig - New trigger level for the GPIO interrupt. + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_gpio_irq_trigger_level_set(struct irq_ctrl_desc *desc, + uint32_t irq_id, + enum irq_trig_level trig) +{ + static const int32_t trig_level[5] = {XGPIOPS_IRQ_TYPE_LEVEL_LOW, + XGPIOPS_IRQ_TYPE_LEVEL_HIGH, + XGPIOPS_IRQ_TYPE_EDGE_FALLING, + XGPIOPS_IRQ_TYPE_EDGE_RISING, + XGPIOPS_IRQ_TYPE_EDGE_BOTH + }; + struct xil_gpio_irq_desc *extra; + + extra = desc->extra; + XGpioPs_SetIntrTypePin(&extra->my_Gpio, irq_id, trig_level[trig]); + + return 0; +} + +/** + * @brief Register pin specific GPIO interrupt. + * @param desc - The GPIO IRQ controller descriptor. + * @param irq_id - Pin number. + * @param callback_desc - Callback. + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_gpio_irq_register_callback(struct irq_ctrl_desc *desc, + uint32_t irq_id, + struct callback_desc *callback_desc) +{ + struct xil_callback_desc *dev_callback; + struct xil_gpio_irq_desc *extra; + + dev_callback = (struct xil_callback_desc *)calloc(1, + sizeof(*dev_callback)); + if(!dev_callback) + return -1; + + dev_callback->pin_nb = irq_id; + dev_callback->callback.legacy_callback = callback_desc->legacy_callback; + dev_callback->callback.ctx = callback_desc->ctx; + dev_callback->triggered = false; + + extra = desc->extra; + XGpioPs_SetDirectionPin(&extra->my_Gpio, irq_id, 0); + list_add_last(extra->callback_list, dev_callback); + + return 0; +} + +/** + * @brief Unregister pin specific GPIO interrupt. + * @param desc - The GPIO IRQ controller descriptor. + * @param irq_id - Pin number. + * @param cb - Callback descriptor. + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_gpio_irq_unregister_callback(struct irq_ctrl_desc *desc, + uint32_t irq_id, struct callback_desc *cb) +{ + int32_t status; + struct xil_gpio_irq_desc *extra; + struct xil_callback_desc *dev_callback; + struct xil_callback_desc search_callback; + + extra = desc->extra; + search_callback.pin_nb = irq_id; + status = list_get_find(extra->callback_list, &dev_callback, + &search_callback); + if(status) + return -ENXIO; + + free(dev_callback); + + return 0; +} + +/** + * @brief Enable specific GPIO IRQ pin. + * @param desc - The GPIO IRQ controller descriptor. + * @param irq_id - Pin number. + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_gpio_irq_enable(struct irq_ctrl_desc *desc, uint32_t irq_id) +{ + int32_t status; + struct xil_gpio_irq_desc *extra; + struct xil_callback_desc *callback_desc; + + extra = desc->extra; + + status = iterator_move_to_idx(extra->it, 0); + while(!status) { + iterator_read(extra->it, &callback_desc); + status = iterator_move(extra->it, 1); + if(callback_desc->pin_nb == irq_id) { + callback_desc->enabled = true; + XGpioPs_IntrClearPin(&extra->my_Gpio, irq_id); + break; + } + } + + XGpioPs_IntrEnablePin(&extra->my_Gpio, irq_id); + + return 0; +} + +/** + * @brief Remove the GPIO IRQ controller. + * @param desc - The GPIO IRQ controller descriptor. + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_gpio_irq_ctrl_remove(struct irq_ctrl_desc *desc) +{ + struct xil_gpio_irq_desc *extra; + struct xil_callback_desc *callback_desc; + + if (!desc) + return -EINVAL; + + extra = desc->extra; + while (0 == list_get_first(extra->callback_list, &callback_desc)) + free(callback_desc); + + iterator_remove(extra->it); + list_remove(extra->callback_list); + free(extra); + free(desc); + + return 0; +} + +/** + * @brief Xilinx platform specific GPIO IRQ platform ops structure + */ +const struct irq_platform_ops xil_gpio_irq_ops = { + .init = &xil_gpio_irq_ctrl_init, + .enable = &xil_gpio_irq_enable, + .disable = &xil_gpio_irq_disable, + .trigger_level_set = &xil_gpio_irq_trigger_level_set, + .register_callback = &xil_gpio_irq_register_callback, + .unregister_callback = xil_gpio_irq_unregister_callback, + .remove = &xil_gpio_irq_ctrl_remove +}; diff --git a/df_datalink/src/drivers/platform/xilinx_gpio_irq.h b/df_datalink/src/drivers/platform/xilinx_gpio_irq.h new file mode 100644 index 0000000..c0c8348 --- /dev/null +++ b/df_datalink/src/drivers/platform/xilinx_gpio_irq.h @@ -0,0 +1,92 @@ +/***************************************************************************//** + * @file xilinx_gpio_irq.h + * @brief Implementation of Xilinx GPIO IRQ Generic Driver. + * @author Porumb Andrei (andrei.porumb@analog.com) +******************************************************************************** + * Copyright 2021(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#ifndef XILINX_GPIO_IRQ_H_ +#define XILINX_GPIO_IRQ_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include "stdbool.h" +#include "list.h" +#include "xgpiops.h" +#include "irq.h" + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ +/** + * @struct xil_callback_desc + * @brief Structure holding callback parameters for each pin + */ +struct xil_callback_desc { + int32_t pin_nb; + struct callback_desc callback; + bool triggered; + bool enabled; +}; + +/** + * @struct xil_gpio_irq_init_param + * @brief Structure holding the initialization parameters for Xilinx platform + * specific GPIO IRQ parameters. + */ +struct xil_gpio_irq_init_param { + struct irq_ctrl_desc *parent_desc; + int32_t gpio_device_id; +}; + +/** + * @struct xil_gpio_irq_desc + * @brief Xilinx platform specific GPIO IRQ descriptor + */ +struct xil_gpio_irq_desc { + struct irq_ctrl_desc *parent_desc; + XGpioPs my_Gpio; + struct list_desc *callback_list; + struct iterator *it; +}; + +/** + * @brief Xilinx specific GPIO IRQ platform ops structure + */ +extern const struct irq_platform_ops xil_gpio_irq_ops; + +#endif diff --git a/df_datalink/src/drivers/platform/xilinx_i2c.c b/df_datalink/src/drivers/platform/xilinx_i2c.c new file mode 100644 index 0000000..de4ecb4 --- /dev/null +++ b/df_datalink/src/drivers/platform/xilinx_i2c.c @@ -0,0 +1,514 @@ +/***************************************************************************//** + * @file xilinx/xilinx_i2c.c + * @brief Implementation of Xilinx I2C Generic Driver. + * @author Antoniu Miclaus (antoniu.miclaus@analog.com) +******************************************************************************** + * Copyright 2019(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include + +#include +#ifdef XPAR_XIIC_NUM_INSTANCES +#include +#endif +#ifdef XPAR_XIICPS_NUM_INSTANCES +#include +#endif + +#include "error.h" +#include "i2c.h" +#include "xilinx_i2c.h" +#include "list.h" + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ + +static struct list_desc *pl_list = NULL; +static struct iterator *pl_it = NULL; + +#ifdef XIICPS_H +static struct list_desc *ps_list = NULL; +static struct iterator *ps_it = NULL; +#endif /* XIICPS_H */ + +/** + * @struct inst_table_item + * @brief Table item for I2C cores already started. + */ +struct inst_table_item { + /** Instance the BSP driver uses for this core. */ + void *instance; + /** Core ID in BSP. */ + uint32_t device_id; + /** Number of ADI driver instances running on this core. */ + uint32_t inst_no; +}; + +#ifdef XPAR_XIICPS_NUM_INSTANCES +/** Save the current state of the bitrate to not change it each time */ +static uint32_t ps_last_bitrate = 0; +#endif + +/** + * @brief Xilinx platform specific I2C platform ops structure + */ +const struct i2c_platform_ops xil_i2c_ops = { + .i2c_ops_init = &xil_i2c_init, + .i2c_ops_write = &xil_i2c_write, + .i2c_ops_read = &xil_i2c_read, + .i2c_ops_remove = &xil_i2c_remove +}; + +/******************************************************************************/ +/************************ Functions Definitions *******************************/ +/******************************************************************************/ + +/** + * @brief Compare two I2C cores by ID. + * @param el1 - First I2C core to compare. + * @param el2 - Second I2C core to compare. + * @return \ref 0 if the two cores have the same ID, + * \ref difference between the first and the second IDs otherwise. + */ +static int32_t xil_i2c_cmp(void *el1, void *el2) +{ + struct inst_table_item *sel1 = el1, *sel2 = el2; + + return (sel1->device_id - sel2->device_id); +} + +/** + * @brief Configure slave address and bitrate if needed + * @param desc - Descriptor of the I2C device + * @return 0 in case of success, -1 otherwise. + */ +static int32_t xil_i2c_set_transmission_config(struct i2c_desc *desc) +{ + struct xil_i2c_desc *xil_i2c_desc = desc->extra; +#ifdef XIICPS_H + int32_t ret; +#endif + + switch (xil_i2c_desc->type) { + case IIC_PL: +#ifdef XIIC_H + break; +#endif + return -1; + case IIC_PS: +#ifdef XIICPS_H + if (desc->max_speed_hz != ps_last_bitrate) { + ret = XIicPs_SetSClk(xil_i2c_desc->instance, desc->max_speed_hz); + if (ret != XST_SUCCESS) + return -1; + ps_last_bitrate = desc->max_speed_hz; + } + break; +#endif + return -1; + default: + + return -1; + } + + return 0; +} + +/** + * @brief Initialize the I2C communication peripheral. + * @param desc - The I2C descriptor. + * @param param - The structure that contains the I2C parameters. + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_i2c_init(struct i2c_desc **desc, + const struct i2c_init_param *param) +{ + int32_t ret; + struct i2c_desc *idesc; + struct xil_i2c_desc *xdesc; + struct xil_i2c_init_param *xinit; + + idesc = (struct i2c_desc *)malloc(sizeof(*idesc)); + xdesc = (struct xil_i2c_desc *)malloc(sizeof(*xdesc)); + + if(!idesc || !xdesc) + goto error; + + idesc->max_speed_hz = param->max_speed_hz; + idesc->slave_address = param->slave_address; + xinit = param->extra; + + idesc->extra = xdesc; + xdesc->type = xinit->type; + xdesc->device_id = xinit->device_id; + switch (xinit->type) { + case IIC_PL: +#ifdef XIIC_H + ; /** Intentional empty statement */ + struct inst_table_item tab_check_pl; + struct inst_table_item *temp_el_pl; + + if (!pl_list) + list_init(&pl_list, LIST_DEFAULT, xil_i2c_cmp); + if (!pl_it) + iterator_init(&pl_it, pl_list, true); + + tab_check_pl.device_id = xdesc->device_id; + + if (!IS_ERR_VALUE(list_read_find(pl_list, (void **)&temp_el_pl, + &tab_check_pl))) { + xdesc->instance = temp_el_pl->instance; + temp_el_pl->inst_no++; + break; + } + + xdesc->instance = (XIic *)malloc(sizeof(XIic)); + if(!xdesc->instance) + goto pl_error; + + xdesc->config = XIic_LookupConfig(xinit->device_id); + if(xdesc->config == NULL) + goto pl_error; + + ret = XIic_CfgInitialize(xdesc->instance, + xdesc->config, + ((XIic_Config*)xdesc->config) + ->BaseAddress); + if(ret != 0) + goto pl_error; + + ret = XIic_Start(xdesc->instance); + if(ret != 0) + goto pl_error; + + ret = XIic_SetAddress(xdesc->instance, + XII_ADDR_TO_SEND_TYPE, + param->slave_address); + if(ret != 0) + goto pl_error; + + ret = XIic_SelfTest(xdesc->instance); + if(ret < 0) + goto pl_error; + + ret = XIic_SetGpOutput(xdesc->instance, 1); + if(ret < 0) + goto pl_error; + + temp_el_pl = (struct inst_table_item*)calloc(1, sizeof(*temp_el_pl)); + temp_el_pl->device_id = xinit->device_id; + temp_el_pl->inst_no = 1; + temp_el_pl->instance = xdesc->instance; + pl_list->push(pl_list, temp_el_pl); + + break; +pl_error: + free(xdesc->instance); +#endif + goto error; + case IIC_PS: +#ifdef XIICPS_H + ; /** Intentional empty statement */ + struct inst_table_item tab_check_ps; + struct inst_table_item *temp_el_ps; + + if (!pl_list) + list_init(&ps_list, LIST_DEFAULT, xil_i2c_cmp); + if (!pl_it) + iterator_init(&ps_it, ps_list, true); + + tab_check_ps.device_id = xdesc->device_id; + + if (!IS_ERR_VALUE(list_read_find(ps_list, + (void **)&temp_el_ps, + &tab_check_ps))) { + xdesc->instance = temp_el_ps->instance; + temp_el_ps->inst_no++; + break; + } + + xdesc->instance = (XIicPs *)malloc(sizeof(XIicPs)); + if(!xdesc->instance) + goto ps_error; + + xdesc->config = XIicPs_LookupConfig(xinit->device_id); + if(xdesc->config == NULL) + goto ps_error; + + ret = XIicPs_CfgInitialize(xdesc->instance, + xdesc->config, + ((XIicPs_Config*)xdesc->config) + ->BaseAddress); + if(ret != 0) + goto ps_error; + + XIicPs_SetSClk(xdesc->instance, param->max_speed_hz); + + temp_el_ps = (struct inst_table_item*)calloc(1, sizeof(*temp_el_ps)); + temp_el_ps->device_id = xinit->device_id; + temp_el_ps->inst_no = 1; + temp_el_ps->instance = xdesc->instance; + ps_list->push(ps_list, temp_el_ps); + + break; +ps_error: + free(xdesc->instance); +#endif + goto error; + + default: + goto error; + break; + } + + *desc = idesc; + + return 0; + +error: + free(idesc); + free(xdesc); + + return -1; +} + +/** + * @brief Free the resources allocated by i2c_init(). + * @param desc - The I2C descriptor. + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_i2c_remove(struct i2c_desc *desc) +{ + struct xil_i2c_desc *xdesc; + int32_t ret; + + xdesc = desc->extra; + + switch (xdesc->type) { + case IIC_PL: +#ifdef XIIC_H + ; /** Intentional empty statement */ + struct inst_table_item tab_check_pl; + struct inst_table_item *temp_el_pl; + tab_check_pl.device_id = xdesc->device_id; + ret = iterator_find(pl_it, &tab_check_pl); + if (ret != 0) + goto error; + iterator_read(pl_it, (void **)&temp_el_pl); + temp_el_pl->inst_no--; + if (temp_el_pl->inst_no != 0) + break; + + ret = XIic_Stop(((XIic *)xdesc->instance)); + + if(ret != 0) + goto error; + + /** Remove list element */ + iterator_get(pl_it, (void **)&temp_el_pl); + free(temp_el_pl); + break; +#endif + goto error; + case IIC_PS: +#ifdef XIICPS_H + ; /** Intentional empty statement */ + struct inst_table_item tab_check_ps; + struct inst_table_item *temp_el_ps; + tab_check_ps.device_id = xdesc->device_id; + ret = iterator_find(ps_it, &tab_check_ps); + if (ret != 0) + goto error; + iterator_read(ps_it, (void **)&temp_el_ps); + temp_el_ps->inst_no--; + if (temp_el_ps->inst_no != 0) + break; + + /** Remove list element */ + iterator_get(ps_it, (void **)&temp_el_ps); + free(temp_el_ps); + break; +#endif + /* Intended fallthrough */ +error: + default: + + return -1; + } + + free(desc->extra); + free(desc); + + return 0; +} + +/** + * @brief Write data to a slave device. + * @param desc - The I2C descriptor. + * @param data - Buffer that stores the transmission data. + * @param bytes_number - Number of bytes to write. + * @param stop_bit - Stop condition control. + * Example: 0 - A stop condition will not be generated; + * 1 - A stop condition will be generated. + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_i2c_write(struct i2c_desc *desc, + uint8_t *data, + uint8_t bytes_number, + uint8_t stop_bit) +{ + struct xil_i2c_desc *xdesc; + int32_t ret; + + xdesc = desc->extra; + + switch (xdesc->type) { + case IIC_PL: +#ifdef XIIC_H + ret = xil_i2c_set_transmission_config(desc); + if (ret != 0) + return -1; + + XIic_Send(((XIic*)xdesc->instance)->BaseAddress, + desc->slave_address, + data, + bytes_number, + stop_bit ? XIIC_STOP : XIIC_REPEATED_START); + break; +#endif + goto error; + case IIC_PS: +#ifdef XIICPS_H + ret = xil_i2c_set_transmission_config(desc); + if (ret != 0) + return -1; + + ret = XIicPs_SetOptions(xdesc->instance, + stop_bit ? 0 : XIICPS_REP_START_OPTION); + if(ret != 0) + goto error; + + XIicPs_MasterSend(xdesc->instance, + data, + bytes_number, + desc->slave_address); + if(ret != 0) + goto error; + + break; +#endif + /* Intended fallthrough */ +error: + default: + + return -1; + } + + return 0; +} + +/** + * @brief Read data from a slave device. + * @param desc - The I2C descriptor. + * @param data - Buffer that will store the received data. + * @param bytes_number - Number of bytes to read. + * @param stop_bit - Stop condition control. + * Example: 0 - A stop condition will not be generated; + * 1 - A stop condition will be generated. + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_i2c_read(struct i2c_desc *desc, + uint8_t *data, + uint8_t bytes_number, + uint8_t stop_bit) +{ + struct xil_i2c_desc *xdesc; + int32_t ret; + + xdesc = desc->extra; + + switch (xdesc->type) { + case IIC_PL: +#ifdef XIIC_H + ret = xil_i2c_set_transmission_config(desc); + if (ret != 0) + return -1; + + ret = XIic_Recv(((XIic*)xdesc->instance)->BaseAddress, + desc->slave_address, + data, + bytes_number, + stop_bit ? XIIC_STOP : XIIC_REPEATED_START); + if(ret != bytes_number) + goto error; + + break; +#endif + goto error; + case IIC_PS: +#ifdef XIICPS_H + ret = xil_i2c_set_transmission_config(desc); + if (ret != 0) + return -1; + + ret = XIicPs_SetOptions(xdesc->instance, + stop_bit ? 0 : XIICPS_REP_START_OPTION); + if(ret != 0) + goto error; + + XIicPs_MasterRecv(xdesc->instance, + data, + bytes_number, + desc->slave_address); + if(ret != 0) + goto error; + + break; +#endif + /* Intended fallthrough */ +error: + default: + return -1; + + break; + } + + return 0; +} diff --git a/df_datalink/src/drivers/platform/xilinx_i2c.h b/df_datalink/src/drivers/platform/xilinx_i2c.h new file mode 100644 index 0000000..b091318 --- /dev/null +++ b/df_datalink/src/drivers/platform/xilinx_i2c.h @@ -0,0 +1,115 @@ +/******************************************************************************* + * @file xilinx/xilinx_i2c.h + * @brief Header containing types used in the i2c driver. + * @author scuciurean (sergiu.cuciurean@analog.com) +******************************************************************************** + * Copyright 2019(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#ifndef XILINX_I2C_H_ +#define XILINX_I2C_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ + +/** + * @enum xil_i2c_type + * @brief Xilinx platform architecture sections + */ +enum xil_i2c_type { + /** Programmable Logic */ + IIC_PL, + /** Processing System */ + IIC_PS +}; + +/** + * @struct xil_i2c_init + * @brief Structure holding the initialization parameters for Xilinx platform + * specific I2C parameters. + */ +struct xil_i2c_init_param { + /** Xilinx architecture */ + enum xil_i2c_type type; + /** Device ID */ + uint32_t device_id; +}; + +/** + * @struct xil_i2c_desc + * @brief Xilinx platform specific I2C descriptor + */ +struct xil_i2c_desc { + /** Xilinx architecture */ + enum xil_i2c_type type; + /** Device ID */ + uint32_t device_id; + /** Xilinx I2C configuration */ + void *config; + /** Xilinx I2C Instance */ + void *instance; +}; + +/** + * @brief Xilinx platform specific i2c platform ops structure + */ +extern const struct i2c_platform_ops xil_i2c_ops; + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ + +/* Initialize the I2C communication peripheral. */ +int32_t xil_i2c_init(struct i2c_desc **desc, + const struct i2c_init_param *param); + +/* Free the resources allocated by i2c_init(). */ +int32_t xil_i2c_remove(struct i2c_desc *desc); + +/* I2C Write data */ +int32_t xil_i2c_write(struct i2c_desc *desc, uint8_t *data, + uint8_t bytes_number, uint8_t stop_bit); + +/* I2C Read data. */ +int32_t xil_i2c_read(struct i2c_desc *desc, uint8_t *data, + uint8_t bytes_number, uint8_t stop_bit); + +#endif // XILINX_I2C_H_ diff --git a/df_datalink/src/drivers/platform/xilinx_irq.c b/df_datalink/src/drivers/platform/xilinx_irq.c new file mode 100644 index 0000000..8ecb1fa --- /dev/null +++ b/df_datalink/src/drivers/platform/xilinx_irq.c @@ -0,0 +1,433 @@ +/***************************************************************************//** + * @file xilinx/xilinx_irq.c + * @brief Implementation of Xilinx IRQ Generic Driver. + * @author Cristian Pop (cristian.pop@analog.com) +******************************************************************************** + * Copyright 2019(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include +#include +#include "error.h" +#include "irq.h" +#include "xilinx_irq.h" +#ifdef XPAR_XSCUGIC_NUM_INSTANCES +#include +#endif +#ifdef XPAR_XINTC_NUM_INSTANCES +#include +#endif +#ifdef XPAR_XTMRCTR_NUM_INSTANCES +#include +#endif + +/******************************************************************************/ +/************************ Functions Definitions *******************************/ +/******************************************************************************/ + +/** + * @brief Initialize the IRQ interrupts. + * @param desc - The IRQ controller descriptor. + * @param param - The structure that contains the IRQ parameters. + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_irq_ctrl_init(struct irq_ctrl_desc **desc, + const struct irq_init_param *param) +{ + int32_t status; + struct irq_ctrl_desc *descriptor; + struct xil_irq_desc *xil_dev; +#ifdef XSCUGIC_H + void *config; +#endif + + descriptor = (struct irq_ctrl_desc *)calloc(1, sizeof *descriptor); + if(!descriptor) + return -1; + xil_dev = (struct xil_irq_desc *)calloc(1, sizeof *xil_dev); + if(!xil_dev) { + free(descriptor); + return -1; + } + + Xil_ExceptionInit(); + + descriptor->irq_ctrl_id = param->irq_ctrl_id; + descriptor->extra = xil_dev; + xil_dev->type = ((struct xil_irq_init_param *)param->extra)->type; + + switch(xil_dev->type) { + case IRQ_PS: +#ifdef XSCUGIC_H + xil_dev->instance = calloc(1, sizeof(XScuGic)); + if(!xil_dev->instance) + goto error; + + config = XScuGic_LookupConfig(descriptor->irq_ctrl_id); + if(!config) + goto ps_error; + + status = XScuGic_CfgInitialize(xil_dev->instance, config, + ((XScuGic_Config *)config)->CpuBaseAddress); + if (status != 0) + goto ps_error; + + Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, + (Xil_ExceptionHandler)XScuGic_InterruptHandler, + xil_dev->instance); + + break; +ps_error: + free(xil_dev->instance); +#endif + goto error; + case IRQ_PL: +#ifdef XINTC_H + xil_dev->instance = calloc(1, sizeof(XIntc)); + if(!xil_dev->instance) + goto error; + + status = XIntc_Initialize(xil_dev->instance, descriptor->irq_ctrl_id); + if(status != 0) + goto pl_error; + + status = XIntc_Start(xil_dev->instance, XIN_REAL_MODE); + if(status != 0) + goto pl_error; + + break; +pl_error: + free(xil_dev->instance); +#endif + goto error; + default: + goto error; + + break; + } + + *desc = descriptor; + + return 0; + +error: + free(xil_dev); + free(descriptor); + + return -1; +} + +/** + * @brief Enable global interrupts. + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_irq_global_enable(struct irq_ctrl_desc *desc) +{ + /* Enable interrupts */ + Xil_ExceptionEnable(); + + return 0; +} + +/** + * @brief Disable global interrupts. + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_irq_global_disable(struct irq_ctrl_desc *desc) +{ + /* Disable interrupts */ + Xil_ExceptionDisable(); + + return 0; +} + +/** + * @brief Enable specific interrupt. + * @param desc - The IRQ controller descriptor. + * @param irq_id - Interrupt identifier. + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_irq_enable(struct irq_ctrl_desc *desc, uint32_t irq_id) +{ + struct xil_irq_desc *xil_dev = desc->extra; + + switch(xil_dev->type) { + case IRQ_PS: +#ifdef XSCUGIC_H + XScuGic_Enable(xil_dev->instance, irq_id); +#endif + break; + case IRQ_PL: +#ifdef XINTC_H + XIntc_Enable(xil_dev->instance, irq_id); +#endif + break; + default: + + return -1; + } + + return 0; +} + +/** + * @brief Disable specific interrupt. + * @param desc - The IRQ controller descriptor. + * @param irq_id - Interrupt identifier. + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_irq_disable(struct irq_ctrl_desc *desc, uint32_t irq_id) +{ + struct xil_irq_desc *xil_dev = desc->extra; + + switch(xil_dev->type) { + case IRQ_PS: +#ifdef XSCUGIC_H + XScuGic_Disable(xil_dev->instance, irq_id); +#endif + break; + case IRQ_PL: +#ifdef XINTC_H + XIntc_Disable(xil_dev->instance, irq_id); +#endif + break; + default: + + return -1; + } + + return 0; +} + +/** + * @brief Register a callback to handle the irq events. + * @param desc - The IRQ controller descriptor. + * @param irq_id - Interrupt identifier. + * @param callback_desc - Callback descriptor + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_irq_register_callback(struct irq_ctrl_desc *desc, + uint32_t irq_id, + struct callback_desc *callback_desc) +{ + struct xil_irq_desc *xil_dev = desc->extra; + + switch(xil_dev->type) { + case IRQ_PS: +#ifdef XSCUGIC_H + return XScuGic_Connect(xil_dev->instance, irq_id, + (Xil_InterruptHandler) callback_desc->callback, + callback_desc->ctx); +#endif + break; + case IRQ_PL: +#ifdef XINTC_H + if (irq_id == XPAR_AXI_INTC_AXI_TIMER_INTERRUPT_INTR) { + int32_t ret; + + ret = XIntc_Connect(xil_dev->instance, irq_id, + XTmrCtr_InterruptHandler, callback_desc->legacy_config); + if (IS_ERR_VALUE(ret)) + return -1; + XTmrCtr_SetHandler(callback_desc->legacy_config, + (XTmrCtr_Handler)callback_desc->callback, + callback_desc->ctx); + + return 0; + } + return XIntc_Connect(xil_dev->instance, irq_id, + (XInterruptHandler) callback_desc->callback, + callback_desc->ctx); +#endif + break; + default: + break; + } + + return -1; +} + +/** + * @brief Set interrupt trigger level. + * @param desc - The IRQ controller descriptor. + * @param irq_id - Interrupt identifier. + * @param trig - New trigger level for the interrupt. + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_irq_trigger_level_set(struct irq_ctrl_desc *desc, + uint32_t irq_id, + enum irq_trig_level trig) +{ + struct xil_irq_desc *xil_dev = desc->extra; + + if(trig == IRQ_EDGE_BOTH) + return -EINVAL; + + switch(xil_dev->type) { + case IRQ_PS: +#ifdef XSCUGIC_H + ; + uint8_t priority, trigger; + + XScuGic_GetPriorityTriggerType(xil_dev->instance, irq_id, &priority, + &trigger); + trigger = trig; + XScuGic_SetPriorityTriggerType(xil_dev->instance, irq_id, priority, + trigger); + + return 0; +#endif + break; + case IRQ_PL: +#ifdef XINTC_H + /* Interrupt trigger determined in hardware. TODO: verify */ + return 0; +#endif + break; + default: + break; + } + + return -1; +} + +/** + * @brief Set interrupt trigger level. + * @param desc - The IRQ controller descriptor. + * @param irq_id - Interrupt identifier. + * @param priority_level - New priority level for the interrupt. + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_irq_set_priority(struct irq_ctrl_desc *desc, + uint32_t irq_id, + uint32_t priority_level) +{ + struct xil_irq_desc *xil_dev = desc->extra; + + if(priority_level % 8 != 0) + return -EINVAL; + + switch(xil_dev->type) { + case IRQ_PS: +#ifdef XSCUGIC_H + ; + uint8_t priority, trigger; + + XScuGic_GetPriorityTriggerType(xil_dev->instance, irq_id, &priority, + &trigger); + priority = priority_level; + XScuGic_SetPriorityTriggerType(xil_dev->instance, irq_id, priority, + trigger); + + return 0; +#endif + break; + case IRQ_PL: +#ifdef XINTC_H + /* Interrupt priority level determined in hardware. TODO: verify */ + return 0; +#endif + break; + default: + break; + } + + return -1; +} + +/** + * @brief Unregisters a generic IRQ handling function. + * @param desc - The IRQ controller descriptor. + * @param irq_id - Interrupt identifier. + * @param cb - Callback descriptor. + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_irq_unregister_callback(struct irq_ctrl_desc *desc, + uint32_t irq_id, struct callback_desc *cb) +{ + struct xil_irq_desc *xil_dev = desc->extra; + + switch(xil_dev->type) { + case IRQ_PS: +#ifdef XSCUGIC_H + XScuGic_Disconnect(xil_dev->instance, irq_id); +#endif + break; + case IRQ_PL: +#ifdef XINTC_H + XIntc_Disconnect(xil_dev->instance, irq_id); +#endif + break; + default: + + return -1; + } + + return 0; +} + +/** + * @brief Free the resources allocated by irq_ctrl_init(). + * @param desc - The IRQ control descriptor. + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_irq_ctrl_remove(struct irq_ctrl_desc *desc) +{ + struct xil_irq_desc *xil_dev = desc->extra; + free(xil_dev->instance); + free(desc->extra); + free(desc); + + return 0; +} + +/** + * @brief Xilinx platform specific IRQ platform ops structure + */ +const struct irq_platform_ops xil_irq_ops = { + .init = &xil_irq_ctrl_init, + .register_callback = &xil_irq_register_callback, + .unregister_callback = &xil_irq_unregister_callback, + .global_enable = &xil_irq_global_enable, + .global_disable = &xil_irq_global_disable, + .trigger_level_set = &xil_irq_trigger_level_set, + .set_priority = &xil_irq_set_priority, + .enable = &xil_irq_enable, + .disable = &xil_irq_disable, + .remove = &xil_irq_ctrl_remove +}; diff --git a/df_datalink/src/drivers/platform/xilinx_irq.h b/df_datalink/src/drivers/platform/xilinx_irq.h new file mode 100644 index 0000000..386b233 --- /dev/null +++ b/df_datalink/src/drivers/platform/xilinx_irq.h @@ -0,0 +1,91 @@ +/******************************************************************************* + * @file xilinx_irq.h + * @brief Header containing types used in the irq driver. + * @author Cristian Pop (cristian.pop@analog.com) +******************************************************************************** + * Copyright 2019(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#ifndef XILINX_IRQ_H_ +#define XILINX_IRQ_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include +#include "irq.h" + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ + +/** + * @enum xil_irq_type + * @brief Xilinx platform architecture sections + */ +enum xil_irq_type { + /** Programmable Logic */ + IRQ_PL, + /** Processing System */ + IRQ_PS +}; + +/** + * @struct xil_irq_init_param + * @brief Structure holding the initialization parameters for Xilinx platform + * specific IRQ parameters. + */ +struct xil_irq_init_param { + /** Xilinx architecture */ + enum xil_irq_type type; +}; + +/** + * @struct xil_irq_desc + * @brief Xilinx platform specific IRQ descriptor + */ +struct xil_irq_desc { + /** Xilinx architecture */ + enum xil_irq_type type; + /** Xilinx IRQ Instance */ + void *instance; +}; + +/** + * @brief Xilinx specific IRQ platform ops structure + */ +extern const struct irq_platform_ops xil_irq_ops; + +#endif diff --git a/df_datalink/src/drivers/platform/xilinx_spi.c b/df_datalink/src/drivers/platform/xilinx_spi.c new file mode 100644 index 0000000..832ea91 --- /dev/null +++ b/df_datalink/src/drivers/platform/xilinx_spi.c @@ -0,0 +1,462 @@ +/***************************************************************************//** + * @file xilinx/xilinx_spi.c + * @brief Implementation of Xilinx SPI Generic Driver. + * @author Antoniu Miclaus (antoniu.miclaus@analog.com) +******************************************************************************** + * Copyright 2019(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include + +#include +#ifdef XPAR_XSPI_NUM_INSTANCES +#include +#endif +#ifdef XPAR_XSPIPS_NUM_INSTANCES +#include +#endif + +#include "error.h" +#include "spi.h" +#include "xilinx_spi.h" + +#if defined(PLATFORM_ZYNQ) +#define SPI_CLK_FREQ_HZ(dev) (XPAR_PS7_SPI_ ## dev ## _SPI_CLK_FREQ_HZ) +#define SPI_NUM_INSTANCES XPAR_XSPIPS_NUM_INSTANCES +#elif defined(PLATFORM_ZYNQMP) +#define SPI_CLK_FREQ_HZ(dev) (XPAR_PSU_SPI_ ## dev ## _SPI_CLK_FREQ_HZ) +#define SPI_NUM_INSTANCES XPAR_XSPIPS_NUM_INSTANCES +#else +#define SPI_NUM_INSTANCES 0 +#endif + +#warning SPI delays are not supported on the xilinx platform + +/******************************************************************************/ +/************************ Functions Definitions *******************************/ +/******************************************************************************/ + +/** + * @brief Initialize the hardware SPI peripherial + * + * @param xdesc Platform specific SPI descriptor + * @param xinit Platform specific SPI init param + * @return int32_t -1 if the device couldn't be found or configured + */ +static int32_t spi_init_pl(struct spi_desc *desc, + const struct spi_init_param *param) +{ +#ifdef XSPI_H + int32_t ret; + struct xil_spi_desc *xdesc; + struct xil_spi_init_param *xinit; + + xdesc = (struct xil_spi_desc*)malloc(sizeof(struct xil_spi_desc)); + if(!xdesc) { + free(xdesc); + return -1; + } + + desc->extra = xdesc; + xinit = param->extra; + xdesc->type = xinit->type; + xdesc->flags = xinit->flags; + + xdesc->instance = (XSpi*)calloc(1, sizeof(XSpi)); + if(!xdesc->instance) + goto pl_error; + + xdesc->config = XSpi_LookupConfig(param->device_id); + if(xdesc->config == NULL) + goto pl_error; + + ret = XSpi_CfgInitialize(xdesc->instance, + xdesc->config, + ((XSpi_Config*)xdesc->config) + ->BaseAddress); + if(ret != 0) + goto pl_error; + + ret = XSpi_Initialize(xdesc->instance, param->device_id); + if (ret != 0) + goto pl_error; + + ret = XSpi_SetOptions(xdesc->instance, + XSP_MASTER_OPTION | + ((desc->mode & SPI_CPOL) ? + XSP_CLK_ACTIVE_LOW_OPTION : 0) | + ((desc->mode & SPI_CPHA) ? + XSP_CLK_PHASE_1_OPTION : 0)); + if (ret != 0) + goto pl_error; + + ret = XSpi_Start(xdesc->instance); + if (ret != 0) + goto pl_error; + + XSpi_IntrGlobalDisable((XSpi *)(xdesc->instance)); + + return 0; + +pl_error: + free(xdesc->instance); + free(xdesc); +#endif + return -1; +} + +/** + * @brief Initialize the hardware SPI peripherial + * + * @param xdesc Platform specific SPI descriptor + * @param xinit Platform specific SPI init param + * @return int32_t -1 if the device couldn't be found or configured + */ +static int32_t spi_init_ps(struct spi_desc *desc, + const struct spi_init_param *param) +{ +#ifdef XSPIPS_H + int32_t ret; + struct xil_spi_desc *xdesc; + struct xil_spi_init_param *xinit; + const uint32_t prescaler_default = XSPIPS_CLK_PRESCALE_64; + const uint32_t prescaler_min = XSPIPS_CLK_PRESCALE_4; + const uint32_t prescaler_max = XSPIPS_CLK_PRESCALE_256; + uint32_t prescaler = 0u; + uint32_t input_clock = 0u; + + xdesc = (struct xil_spi_desc*)malloc(sizeof(struct xil_spi_desc)); + if(!xdesc) { + free(xdesc); + return -1; + } + + desc->extra = xdesc; + xinit = param->extra; + xdesc->type = xinit->type; + xdesc->flags = xinit->flags; + + xdesc->instance = (XSpiPs*)malloc(sizeof(XSpiPs)); + if(!xdesc->instance) + goto ps_error; + + xdesc->config = XSpiPs_LookupConfig(param->device_id); + if(xdesc->config == NULL) + goto ps_error; + + ret = XSpiPs_CfgInitialize(xdesc->instance, + xdesc->config, + ((XSpiPs_Config*)xdesc->config) + ->BaseAddress); + if(ret != 0) + goto ps_error; + + switch (param->device_id) { +#if (SPI_NUM_INSTANCES >= 1) + case 0: + input_clock = SPI_CLK_FREQ_HZ(0); + break; +#endif +#if (SPI_NUM_INSTANCES >= 2) + case 1: + input_clock = SPI_CLK_FREQ_HZ(1); + break; +#endif + default: + goto ps_error; + }; + + if (desc->max_speed_hz != 0u) { + uint32_t div = input_clock / desc->max_speed_hz; + uint32_t rem = input_clock % desc->max_speed_hz; + uint32_t po2 = !(div & (div - 1)) && !rem; + + // find the power of two just higher than div and + // store the exponent in prescaler + while(div) { + prescaler += 1; + div >>= 1u; + } + + // this exponent - 1 is needed because of the way + // xilinx stores it into registers + if (prescaler) + prescaler -= 1; + + // this exponent - 1 is needed when initial div was + // precisely a power of two + if (prescaler && po2) + prescaler -= 1; + + if (prescaler < prescaler_min) + prescaler = prescaler_min; + + if (prescaler > prescaler_max) + prescaler = prescaler_max; + } else + prescaler = prescaler_default; + + ret = XSpiPs_SetClkPrescaler(xdesc->instance, prescaler); + + if(ret != 0) + goto ps_error; + + return 0; + +ps_error: + free(xdesc->instance); + free(xdesc); +#endif + return -1; +} + +/** + * @brief Initialize the SPI communication peripheral. + * @param desc - The SPI descriptor. + * @param param - The structure that contains the SPI parameters. + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_spi_init(struct spi_desc **desc, + const struct spi_init_param *param) +{ + int32_t ret; + enum xil_spi_type *spi_type; + + if (!param) { + return -1; + } + + *desc = malloc(sizeof(**desc)); + if(! *desc) { + free(*desc); + return -1; + } + + spi_type = param->extra; + + if(!spi_type) + goto init_error; + + (*desc)->max_speed_hz = param->max_speed_hz; + (*desc)->mode = param->mode; + (*desc)->bit_order = param->bit_order; + (*desc)->chip_select = param->chip_select; + + switch (*spi_type) { + case SPI_PL: + ret = spi_init_pl(*desc, param); + break; + case SPI_PS: + ret = spi_init_ps(*desc, param); + break; + + default: + goto init_error; + break; + } + + if (ret != 0) { +init_error: + free(*desc); + + return -1; + } + + return ret; +} + +/** + * @brief Free the resources allocated by spi_init(). + * @param desc - The SPI descriptor. + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_spi_remove(struct spi_desc *desc) +{ +#ifdef XSPI_H + int32_t ret; +#endif + struct xil_spi_desc *xdesc = NULL; + enum xil_spi_type *spi_type; + + spi_type = desc->extra; + + if(!spi_type) + return -1; + + switch (*spi_type ) { + case SPI_PL: +#ifdef XSPI_H + xdesc = desc->extra; + + if(!xdesc) + return -1; + + ret = XSpi_Stop((XSpi *)(xdesc->instance)); + if(ret != 0) + goto error; +#endif + break; + case SPI_PS: +#ifdef XSPIPS_H + xdesc = desc->extra; + + if(!xdesc) + return -1; +#endif + break; + + /* Intended fallthrough */ +#ifdef XSPI_H +error: +#endif + default: + return -1; + } + + if(xdesc) + free(xdesc->instance); + free(desc->extra); + free(desc); + + return 0; +} + +/** + * @brief Write and read data to/from SPI. + * @param desc - The SPI descriptor. + * @param data - The buffer with the transmitted/received data. + * @param bytes_number - Number of bytes to write/read. + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_spi_write_and_read(struct spi_desc *desc, + uint8_t *data, + uint16_t bytes_number) +{ + int32_t ret; +#ifdef XSPI_H + uint32_t ctrl_reg; +#endif + struct xil_spi_desc *xdesc; + enum xil_spi_type *spi_type; + + ret = -1; + + spi_type = desc->extra; + + if(!spi_type) + return -1; + + xdesc = desc->extra; + + switch (*spi_type) { + case SPI_PL: +#ifdef XSPI_H + ret = XSpi_SetOptions(xdesc->instance, + XSP_MASTER_OPTION | + ((desc->mode & SPI_CPOL) ? + XSP_CLK_ACTIVE_LOW_OPTION : 0) | + ((desc->mode & SPI_CPHA) ? + XSP_CLK_PHASE_1_OPTION : 0)); + if (ret != 0) + goto error; + + ctrl_reg = XSpi_GetControlReg(((XSpi*)xdesc->instance)); + if (desc->bit_order == SPI_BIT_ORDER_LSB_FIRST) + ctrl_reg |= XSP_CR_LSB_MSB_FIRST_MASK; + else + ctrl_reg &= ~ XSP_CR_LSB_MSB_FIRST_MASK; + XSpi_SetControlReg(((XSpi*)xdesc->instance), ctrl_reg); + + ret = XSpi_SetSlaveSelect(xdesc->instance, + 0x01 << desc->chip_select); + if (ret != 0) + goto error; + + ret = XSpi_Transfer(xdesc->instance, + data, + data, + bytes_number); + if (ret != 0) + goto error; +#endif + break; + case SPI_PS: +#ifdef XSPIPS_H + ret = XSpiPs_SetOptions(xdesc->instance, + XSPIPS_MASTER_OPTION | + ((xdesc->flags & SPI_CS_DECODE) ? + XSPIPS_DECODE_SSELECT_OPTION : 0) | + XSPIPS_FORCE_SSELECT_OPTION | + ((desc->mode & SPI_CPOL) ? + XSPIPS_CLK_ACTIVE_LOW_OPTION : 0) | + ((desc->mode & SPI_CPHA) ? + XSPIPS_CLK_PHASE_1_OPTION : 0)); + if (ret != 0) + goto error; + + ret = XSpiPs_SetSlaveSelect(xdesc->instance, + desc->chip_select); + if (ret != 0) + goto error; + ret = XSpiPs_PolledTransfer(xdesc->instance, + data, + data, + bytes_number); + if (ret != 0) + goto error; + ret = XSpiPs_SetSlaveSelect(xdesc->instance, SPI_DEASSERT_CURRENT_SS); + if (ret != 0) + goto error; +#endif + break; +error: + default: + return -1; + } + + return ret; +} + +/** + * @brief Xilinx platform specific SPI platform ops structure + */ +const struct spi_platform_ops xil_spi_ops = { + .init = &xil_spi_init, + .write_and_read = &xil_spi_write_and_read, + .remove = &xil_spi_remove +}; diff --git a/df_datalink/src/drivers/platform/xilinx_spi.h b/df_datalink/src/drivers/platform/xilinx_spi.h new file mode 100644 index 0000000..fc42c7b --- /dev/null +++ b/df_datalink/src/drivers/platform/xilinx_spi.h @@ -0,0 +1,115 @@ +/******************************************************************************* + * @file xilinx/xilinx_spi.h + * @brief Header containing extra types used in the spi driver. + * @author scuciurean (sergiu.cuciurean@analog.com) +******************************************************************************** + * Copyright 2019(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ +#ifndef XILINX_SPI_H_ +#define XILINX_SPI_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include +#include "spi.h" + +/******************************************************************************/ +/********************** Macros and Constants Definitions **********************/ +/******************************************************************************/ + +#define SPI_CS_DECODE 0x01 +#define SPI_DEASSERT_CURRENT_SS 0x0F + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ + +/** + * @enum xil_spi_type + * @brief Xilinx platform architecture sections + */ +enum xil_spi_type { + /** Programmable Logic */ + SPI_PL, + /** Processing System */ + SPI_PS, + /** SPI Engine */ + SPI_ENGINE +}; + +/** + * @struct xil_spi_init_param + * @brief Structure holding the initialization parameters for Xilinx platform + * specific SPI parameters when using xil_spi_ops. + */ +struct xil_spi_init_param { + /** Xilinx architecture */ + enum xil_spi_type type; + /** SPI flags */ + uint32_t flags; +}; + +/** + * @struct xil_spi_desc + * @brief Xilinx platform specific SPI descriptor + */ +struct xil_spi_desc { + /** Xilinx architecture */ + enum xil_spi_type type; + /** SPI flags */ + uint32_t flags; + /** SPI configuration */ + void *config; + /** SPI instance */ + void *instance; +}; + +/** + * @brief SPI engine platform ops structure + */ +extern const struct spi_platform_ops spi_eng_platform_ops; + +/** + * @brief Xilinx specific SPI platform ops structure + */ +extern const struct spi_platform_ops xil_spi_ops; + +/** + * @brief Xilinx SPI PS register functions. No extra param needed + */ +extern const struct spi_platform_ops xil_spi_pl_ops; + +#endif // XILINX_SPI_H_ diff --git a/df_datalink/src/drivers/platform/xilinx_spi_pl.c b/df_datalink/src/drivers/platform/xilinx_spi_pl.c new file mode 100644 index 0000000..270cc29 --- /dev/null +++ b/df_datalink/src/drivers/platform/xilinx_spi_pl.c @@ -0,0 +1,533 @@ +/******************************************************************************* + * @file xilinx/xilinx_spi_pl.c + * @brief Driver for spi pl device using registers + * @author Mihail Chindris (mihail.chindris@analog.com) +******************************************************************************** + * Copyright 2021(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#include + +#ifdef XPAR_XSPI_NUM_INSTANCES + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include +#include +#include +#include "spi.h" +#include "error.h" +#include "delay.h" +#include "util.h" +#include "alloc.h" + +/******************************************************************************/ +/********************** Macros and Constants Definitions **********************/ +/******************************************************************************/ + +#define XPS_TYPE_WRITE 0x1 +#define XPS_TYPE_READ 0x2 +#define XSP_DEFAULT_SR_VALUE 0x25 +#define XSP_DUMMY_DATA 0xFF + +/* + * Used to store current spi device configuration in order to not update it for + * each spi transaction if not needed. + */ +static struct spi_desc g_spi_desc[XPAR_XSPI_NUM_INSTANCES]; + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ + +/* Xilinx PL spi specific data */ +struct xspi_desc { + uint32_t base_addr; + uint32_t disable_slaves_mask; + uint32_t fifo_depth; + uint8_t cs_asserted; +}; + +/* Structure used to iterate over SPI messages */ +struct msg_iter { + struct spi_msg *msgs; + uint32_t len; + uint32_t i; + uint32_t buff_i; + uint8_t is_wr; +}; + +/******************************************************************************/ +/************************ Functions Definitions *******************************/ +/******************************************************************************/ + +/* Read device register */ +static inline uint32_t _read(struct xspi_desc *xdesc, uint32_t reg) +{ + return Xil_In32(xdesc->base_addr + reg); +} + +/* Write device register */ +static inline void _write(struct xspi_desc *xdesc, uint32_t reg, uint32_t val) +{ + Xil_Out32(xdesc->base_addr + reg, val); +} + +/* Update device register. Only bits set to 1 in mask will be modified */ +static inline void _wr_mask(struct xspi_desc *xdesc, uint32_t reg, + uint32_t val, uint32_t mask) +{ + uint32_t tmp; + + tmp = _read(xdesc, reg); + tmp &= ~mask; + tmp |= val & mask; + _write(xdesc, reg, tmp); +} + +/* Update spi device configuration if needed */ +static void _update_mode(struct spi_desc *desc) +{ + uint32_t val; + uint32_t mask; + + if (desc->mode == g_spi_desc[desc->device_id].mode && + desc->bit_order == g_spi_desc[desc->device_id].bit_order) + return ; + + /* Update mode */ + val = desc->mode | SPI_CPOL ? XSP_CR_CLK_POLARITY_MASK : 0; + val |= desc->mode | SPI_CPHA ? XSP_CR_CLK_PHASE_MASK : 0; + mask = XSP_CR_CLK_POLARITY_MASK | XSP_CR_CLK_PHASE_MASK; + + val |= desc->bit_order == SPI_BIT_ORDER_LSB_FIRST ? + XSP_CR_LSB_MSB_FIRST_MASK : 0; + mask |= XSP_CR_LSB_MSB_FIRST_MASK; + + _wr_mask(desc->extra, XSP_CR_OFFSET, val, mask); + g_spi_desc[desc->device_id] = *desc; +} + +/* Configure SPI PL device */ +static int32_t _xil_spi_init_dev(struct xspi_desc *xdesc) +{ + uint32_t val; + + /* Software reset */ + _write(xdesc, XSP_SRR_OFFSET, XSP_SRR_RESET_MASK); + mdelay(1); + + /* Check if success reset */ + val = _read(xdesc, XSP_SR_OFFSET); + if (val != XSP_DEFAULT_SR_VALUE) + return -ENODEV; + + /* Disable interrupts. Drivers only works with pooled mode */ + _write(xdesc, XSP_IIER_OFFSET, 0); + + /* Deasert chip selects */ + _write(xdesc, XSP_SSR_OFFSET, 0xFFFFFFFF); + + /* Get fifo depth */ + while (!(_read(xdesc, XSP_SR_OFFSET) & XSP_SR_TX_FULL_MASK)) + _write(xdesc, XSP_DTR_OFFSET, XSP_DUMMY_DATA); + xdesc->fifo_depth = _read(xdesc, XSP_TFO_OFFSET) + 1; + + /* Configure spi device */ + val = XSP_CR_ENABLE_MASK | + XSP_CR_MANUAL_SS_MASK | + XSP_CR_TXFIFO_RESET_MASK | + XSP_CR_RXFIFO_RESET_MASK | + XSP_CR_MASTER_MODE_MASK | + XSP_CR_TRANS_INHIBIT_MASK; + + _write(xdesc, XSP_CR_OFFSET, val); + + return 0; +} + +/* Initialize spi_desc structure and device */ +static int32_t xil_spi_init_pl(struct spi_desc **desc, + const struct spi_init_param *param) +{ + struct spi_desc *ldesc; + struct xspi_desc *xdesc; + int32_t err; + XSpi_Config *cfg; + + if (!desc || !param || param->device_id >= XPAR_XSPI_NUM_INSTANCES) + return -EINVAL; + + cfg = XSpi_LookupConfig(param->device_id); + if (!cfg) + return -EINVAL; + + if (param->chip_select > cfg->NumSlaveBits) + return -EINVAL; + + ldesc = (struct spi_desc *)calloc(1, sizeof(*ldesc)); + if (!ldesc) + return -ENOMEM; + + xdesc = (struct xspi_desc *)calloc(1, sizeof(*xdesc)); + if (!xdesc) { + err = -ENOMEM; + goto error; + } + + ldesc->bit_order = param->bit_order; + ldesc->chip_select = param->chip_select; + ldesc->mode = param->mode; + xdesc->base_addr = cfg->BaseAddress; + xdesc->disable_slaves_mask = (1 << cfg->NumSlaveBits) - 1; + xdesc->cs_asserted = 0; + + err = _xil_spi_init_dev(xdesc); + if (IS_ERR_VALUE(err)) + goto error; + + ldesc->extra = xdesc; + *desc = ldesc; + + return 0; + +error: + free(xdesc); + free(ldesc); + + return err; +} + +/* Remove allocated resources */ +static int32_t xil_spi_remove_pl(struct spi_desc *desc) +{ + if (!desc) + return -EINVAL; + + free(desc->extra); + free(desc); + + return 0; +} + +/* + * Fill fifo until fifo is full or no more data available. + * Return the number of written bytes. + */ +static uint32_t _wr_fifo(struct xspi_desc *xdesc, uint8_t *data, + uint32_t len) +{ + uint32_t i; + uint32_t to_write; + uint32_t tx_available; + + tx_available = xdesc->fifo_depth - _read(xdesc, XSP_TFO_OFFSET); + to_write = min(tx_available, len); + for (i = 0; i < to_write; ++i) + if (data) + _write(xdesc, XSP_DTR_OFFSET, data[i]); + else + _write(xdesc, XSP_DTR_OFFSET, XSP_DUMMY_DATA); + + return to_write; +} + +/* + * Read fifo until fifo is empty or no more buffer available to read into + * Returns the number of read bytes + */ +static uint32_t _rd_fifo(struct xspi_desc *xdesc, uint8_t *data, + uint32_t len) +{ + uint32_t rx_available; + uint32_t to_read; + uint32_t tmp; + uint32_t i; + + tmp = _read(xdesc, XSP_SR_OFFSET); + if (tmp & XSP_SR_RX_EMPTY_MASK) + return 0; + + rx_available = _read(xdesc, XSP_RFO_OFFSET) + 1; + to_read = min(rx_available, len); + for (i = 0; i < to_read; ++i) { + tmp = _read(xdesc, XSP_DRR_OFFSET); + if (data) + data[i] = tmp; + } + + return to_read; +} + +/* If start is 0 stop transfer, else start it. + * CS will be asserted if needed. If different CS othere than the one needed + * is asserted. Deassert it and assert correct one */ +static void _xil_spi_start_transfer(struct spi_desc *desc, uint8_t start) +{ + struct xspi_desc *xdesc; + + xdesc = desc->extra; + if (start) { + if (xdesc->cs_asserted) { + if (desc->chip_select == + g_spi_desc[desc->device_id].chip_select) + return ; + else + /* Stop transfer to start again with new CS */ + _xil_spi_start_transfer(desc, 0); + } + _write(xdesc, XSP_SSR_OFFSET, ~(1 << desc->chip_select)); + _wr_mask(xdesc, XSP_CR_OFFSET, 0, XSP_CR_TRANS_INHIBIT_MASK); + } else { + _wr_mask(xdesc, XSP_CR_OFFSET, XSP_CR_TRANS_INHIBIT_MASK, + XSP_CR_TRANS_INHIBIT_MASK); + _write(xdesc, XSP_SSR_OFFSET, xdesc->disable_slaves_mask); + } + xdesc->cs_asserted = start; +} + + +/* SPI polled transfer */ +static int32_t xil_spi_write_and_read_pl(struct spi_desc *desc, + uint8_t *data, + uint16_t bytes_number) +{ + struct xspi_desc *xdesc; + uint32_t rx; + uint32_t tx; + + if (!desc || !desc->extra) + return -EINVAL; + + xdesc = desc->extra; + _update_mode(desc); + + _xil_spi_start_transfer(desc, 1); + rx = 0; + tx = 0; + while (rx < bytes_number) { + if (tx < bytes_number) + tx += _wr_fifo(xdesc, data + tx, bytes_number - tx); + rx += _rd_fifo(xdesc, data + rx, bytes_number - rx); + } + _xil_spi_start_transfer(desc, 0); + + return 0; +} + +/* Get type of message. It can be READ, WRITE or both */ +static uint32_t _get_msg_type(struct spi_msg *msg) +{ + uint32_t type; + + type = 0; + if (msg->tx_buff) + type |= XPS_TYPE_WRITE; + if (msg->rx_buff) + type |= XPS_TYPE_READ; + + return type; +} + +/* Get information based on current iterator position */ +static void _get_data(struct msg_iter *it, uint8_t **buff, uint32_t *len, + uint32_t *type) +{ + struct spi_msg *msg; + + if (it->i == it->len) { + *len = 0; + return ; + } + + msg = it->msgs + it->i; + if (it->is_wr) + *buff = msg->tx_buff; + else + *buff = msg->rx_buff; + + if (*buff) + *buff += it->buff_i; + + *len = msg->bytes_number - it->buff_i; + if (type) + *type = _get_msg_type(msg); +} + +/* + * Increment iterator position with desired length. + * If the new position has a different message type, new_type will be set to 1 + * If a CS change is needed, cs_change is set + */ +static void _increment_iter(struct msg_iter *it, uint32_t len, + uint8_t *cs_change, uint8_t *new_type) +{ + struct spi_msg *msg; + uint32_t type; + uint32_t extra_len; + + if (!len) + return ; + + *cs_change = 0; + *new_type = 0; + msg = it->msgs + it->i; + if (it->buff_i + len > msg->bytes_number) + extra_len = it->buff_i + len - msg->bytes_number; + else + extra_len = 0; + len -= extra_len; + it->buff_i += len; + if (it->buff_i == msg->bytes_number) { + type = _get_msg_type(msg); + ++it->i; + it->buff_i = 0; + if (cs_change && msg->cs_change) + *cs_change = 1; + if (new_type) + if (it->i == it->len || + type != _get_msg_type(it->msgs + it->i)) + *new_type = 1; + } + if (extra_len) + _increment_iter(it, extra_len, cs_change, new_type); +} + +/* + * SPI polling transfer of multiple messages. + */ +static int32_t xil_spi_transfer_pl(struct spi_desc *desc, + struct spi_msg *msgs, + uint32_t len) + +{ + struct xspi_desc *xdesc; + uint8_t cs_change; + uint8_t new_type; + struct msg_iter rx = {.msgs = msgs, .len = len, .is_wr = 0}; + struct msg_iter tx = {.msgs = msgs, .len = len, .is_wr = 1}; + uint8_t *buff; + uint32_t bytes; + uint32_t type; + /* Bytes to increment rx when only a write transaction is executed */ + uint32_t to_inc_rx; + /* Difference between rx and tx iterators in bytes */ + uint32_t tx_advance; + /* Save bytes sent during a write loop */ + uint32_t tx_sent; + /* Used to loop if need to empty the RX FIFO */ + uint32_t loop; + + if (!desc || !desc->extra) + return -EINVAL; + + xdesc = desc->extra; + _update_mode(desc); + + tx_advance = 0; + to_inc_rx = 0; + buff = NULL; + type = 0; + do { + _xil_spi_start_transfer(desc, 1); + + tx_sent = 0; + /* Writing loop */ + do { + _get_data(&tx, &buff, &bytes, &type); + if (type & XPS_TYPE_READ) + /* + * Do not write more bytes than fifo_depth if + * they haven't been read. + */ + bytes = min(bytes, + xdesc->fifo_depth - tx_advance); + bytes = _wr_fifo(xdesc, buff, bytes); + tx_sent += bytes; + _increment_iter(&tx, bytes, &cs_change, &new_type); + tx_advance += bytes; + } while (!cs_change && !new_type && bytes); + + if (type & XPS_TYPE_READ) { + loop = 1; + /* + * Loop only when no more data to write otherwise read + * only available data. + */ + while (loop) { + if (!new_type) + loop = 0; + _get_data(&rx, &buff, &bytes, NULL); + bytes = _rd_fifo(xdesc, buff, bytes); + _increment_iter(&rx, bytes, &cs_change, &new_type); + tx_advance -= bytes; + if (loop && new_type) + break; + } + } else { + /* Clean RX FIFO if it was only a WRITE message */ + to_inc_rx += tx_sent; + if (new_type) { + /* Wait for TX to be sent */ + while (!(_read(xdesc, XSP_SR_OFFSET) & + XSP_SR_TX_EMPTY_MASK)) + ; + /* Reset fifo. Only write was performed */ + _wr_mask(xdesc, XSP_CR_OFFSET, + XSP_CR_RXFIFO_RESET_MASK, + XSP_CR_RXFIFO_RESET_MASK); + + _increment_iter(&rx, to_inc_rx, NULL, NULL); + tx_advance -= to_inc_rx; + to_inc_rx = 0; + } + } + + if ((cs_change && rx.i != len) || (!cs_change && rx.i == len)) + _xil_spi_start_transfer(desc, 0); + } while (rx.i < len); + + return 0; +} + +const struct spi_platform_ops xil_spi_pl_ops = { + .init = xil_spi_init_pl, + .remove = xil_spi_remove_pl, + .write_and_read = xil_spi_write_and_read_pl, + .transfer = xil_spi_transfer_pl +}; + +#endif // XPAR_XSPI_NUM_INSTANCES diff --git a/df_datalink/src/drivers/platform/xilinx_timer.c b/df_datalink/src/drivers/platform/xilinx_timer.c new file mode 100644 index 0000000..4b1fa85 --- /dev/null +++ b/df_datalink/src/drivers/platform/xilinx_timer.c @@ -0,0 +1,456 @@ +/***************************************************************************//** +* @file xilinx/xilinx_timer.c +* @brief Timer and GIC control module source. +* @author Andrei Drimbarean (andrei.drimbarean@analog.com) +******************************************************************************** +* Copyright 2020(c) Analog Devices, Inc. +* +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* - Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* - Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* - Neither the name of Analog Devices, Inc. nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* - The use of this software may or may not infringe the patent rights +* of one or more patent holders. This license does not release you +* from the requirement that you obtain separate licenses from these +* patent holders to use this software. +* - Use of the software either in source or binary form, must be run +* on or directly connected to an Analog Devices Inc. component. +* +* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, MERCHANTABILITY +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include +#include +#include "timer.h" +#include "xilinx_timer.h" +#include "error.h" + +/******************************************************************************/ +/********************** Macros and Constants Definitions **********************/ +/******************************************************************************/ + +#if defined(_XPARAMETERS_PS_H_) +#define CORE_PRIVATE_TIMER_CLOCK (XPAR_CPU_CORTEXA9_CORE_CLOCK_FREQ_HZ / 2) +#endif + +/******************************************************************************/ +/************************ Functions Definitions *******************************/ +/******************************************************************************/ + +/** + * @brief Set the current counter value of the timer. + * @param [in] desc - Pointer to the device handler. + * @param [in] new_val - New value for the timer counter. + * @return 0 in case of success, -1 otherwise + */ +int32_t xilinx_timer_counter_set(struct timer_desc *desc, + uint32_t new_val) +{ + struct xil_timer_desc *xdesc; + + if (!desc) + return -1; + + xdesc = desc->extra; + + switch (xdesc->type) { + case TIMER_PS: +#ifdef XSCUTIMER_H + XScuTimer_LoadTimer((XScuTimer *)xdesc->instance, new_val - 1); + break; +#endif + return -1; + case TIMER_PL: +#ifdef XTMRCTR_H + XTmrCtr_SetResetValue(xdesc->instance, xdesc->active_tmr, new_val); + XTmrCtr_Reset(xdesc->instance, xdesc->active_tmr); + break; +#endif + return -1; + default: + return -1; + } + + return 0; +} + +/** + * @brief Set the timer clock frequency. + * @param [in] desc - Pointer to the device handler. + * @param [in] freq_hz - New timer frequency in hertz. + * @return 0 in case of success, -1 otherwise + */ +int32_t xilinx_timer_count_clk_set(struct timer_desc *desc, + uint32_t freq_hz) +{ + struct xil_timer_desc *xdesc; + + if (!desc || !freq_hz) + return -1; + + xdesc = desc->extra; + + switch (xdesc->type) { + case TIMER_PS: +#ifdef XSCUTIMER_H + ; + uint32_t prescaler = CORE_PRIVATE_TIMER_CLOCK / freq_hz; + if (prescaler == 0 || prescaler >= 256) + return -1; + XScuTimer_SetPrescaler(xdesc->instance, prescaler - 1); + desc->freq_hz = CORE_PRIVATE_TIMER_CLOCK / prescaler; + break; +#endif + return -1; + case TIMER_PL: +#ifdef XTMRCTR_H + (void *)xdesc; + /** Cannot be done. */ +#endif + return -1; + default: + return -1; + } + + return 0; +} + +/** + * @brief Initialize hardware timer and the handler structure associated with + * it. + * @param [out] desc - Pointer to the reference of the device handler. + * @param [in] param - Initialization structure. + * @return 0 in case of success, -1 otherwise + */ +int32_t xilinx_timer_init(struct timer_desc **desc, + const struct timer_init_param *param) +{ + int32_t ret; + struct timer_desc *dev; + struct xil_timer_desc *xdesc; + struct xil_timer_init_param *xinit; + + if (!desc || !param) + return -1; + + xinit = param->extra; + + dev = (struct timer_desc *)calloc(1, sizeof(*dev)); + if(!dev) + return -1; + xdesc = (struct xil_timer_desc *)calloc(1, sizeof(*xdesc)); + if(!xdesc) + goto error_desc; + + dev->id = param->id; + dev->freq_hz = param->freq_hz; + dev->ticks_count = param->ticks_count; + dev->extra = xdesc; + xdesc->active_tmr = xinit->active_tmr; + xdesc->type = xinit->type; + + switch (xdesc->type) { + case TIMER_PS: +#ifdef XSCUTIMER_H + xdesc->config = XScuTimer_LookupConfig(dev->id); + xdesc->instance = calloc(1, sizeof(XScuTimer)); + if (!xdesc->instance) + goto error_xdesc; + ret = XScuTimer_CfgInitialize(xdesc->instance, xdesc->config, + ((XScuTimer_Config *)xdesc->config)->BaseAddr); + if (ret != XST_SUCCESS) { + free(xdesc->instance); + goto error_xdesc; + } + ret = xilinx_timer_count_clk_set(dev, param->freq_hz); + if (IS_ERR_VALUE(ret)) + goto error_xdesc; + + ret = xilinx_timer_counter_set(dev, dev->ticks_count); + if (IS_ERR_VALUE(ret)) + goto error_xdesc; + + XScuTimer_EnableAutoReload((XScuTimer *)xdesc->instance); + XScuTimer_EnableInterrupt((XScuTimer *)xdesc->instance); + break; +#endif + goto error_xdesc; + case TIMER_PL: +#ifdef XTMRCTR_H + xdesc->instance = (XTmrCtr *)calloc(1, sizeof(XTmrCtr)); + if (!xdesc->instance) + return -1; + + xdesc->config = XTmrCtr_LookupConfig(dev->id); + if (!xdesc->config) { + free(xdesc->instance); + goto error_desc; + } + XTmrCtr_CfgInitialize(xdesc->instance, xdesc->config, + ((XTmrCtr_Config *)xdesc->config)->BaseAddress); + ret = XTmrCtr_InitHw(xdesc->instance); + if (ret != 0) { + free(xdesc->instance); + goto error_desc; + } + dev->freq_hz = ((XTmrCtr_Config *)xdesc->config)->SysClockFreqHz; + + ret = XTmrCtr_SelfTest(xdesc->instance, dev->id); + if(ret != 0) + goto error_desc; + XTmrCtr_SetOptions(xdesc->instance, xdesc->active_tmr, + XTC_DOWN_COUNT_OPTION | XTC_INT_MODE_OPTION | + XTC_AUTO_RELOAD_OPTION); + XTmrCtr_SetResetValue(xdesc->instance, xdesc->active_tmr, + dev->ticks_count); + break; +#endif + goto error_xdesc; + default: + goto error_xdesc; + } + + *desc = dev; + + return 0; + +error_xdesc: + free(xdesc); +error_desc: + free(dev); + + return -1; +} + +/** + * @brief Free the memory allocated by timer_setup(). + * @param [in] desc - Pointer to the device handler. + * @return 0 in case of success, -1 otherwise + */ +int32_t xilinx_timer_remove(struct timer_desc *desc) +{ + struct xil_timer_desc *xdesc; + + if(!desc) + return -1; + + xdesc = desc->extra; + + switch (xdesc->type) { + case TIMER_PS: +#ifdef XSCUTIMER_H + XScuTimer_Stop(xdesc->instance); + free(xdesc->instance); + break; +#endif + return -1; + case TIMER_PL: +#ifdef XTMRCTR_H + XTmrCtr_Stop(xdesc->instance, xdesc->active_tmr); + break; +#endif + return -1; + default: + return -1; + } + + free(xdesc); + free(desc); + + return 0; +} + +/** + * @brief Start a timer. + * @param [in] desc - Pointer to the device handler. + * @return 0 in case of success, -1 otherwise + */ +int32_t xilinx_timer_start(struct timer_desc *desc) +{ + struct xil_timer_desc *xdesc; + + if (!desc) + return -1; + + xdesc = desc->extra; + + switch (xdesc->type) { + case TIMER_PS: +#ifdef XSCUTIMER_H + XScuTimer_Start(xdesc->instance); + break; +#endif + return -1; + case TIMER_PL: +#ifdef XTMRCTR_H + XTmrCtr_Start(xdesc->instance, xdesc->active_tmr); + break; +#endif + return -1; + } + + return 0; +} + +/** + * @brief Stop a timer from counting. + * @param [in] desc - Pointer to the device handler. + * @return 0 in case of success, -1 otherwise + */ +int32_t xilinx_timer_stop(struct timer_desc *desc) +{ + struct xil_timer_desc *xdesc; + + if (!desc) + return -1; + + xdesc = desc->extra; + + switch (xdesc->type) { + case TIMER_PS: +#ifdef XSCUTIMER_H + XScuTimer_Stop(xdesc->instance); + break; +#endif + return -1; + case TIMER_PL: +#ifdef XTMRCTR_H + XTmrCtr_Stop(xdesc->instance, xdesc->active_tmr); + break; +#endif + return -1; + default: + return -1; + } + + return 0; +} + +/** + * @brief Get the current counter value of the timer. + * @param [in] desc - Pointer to the device handler. + * @param [out] counter - Pointer to the current counter value. + * @return 0 in case of success, -1 otherwise + */ +int32_t xilinx_timer_counter_get(struct timer_desc *desc, + uint32_t *counter) +{ + struct xil_timer_desc *xdesc; + + if (!desc || !counter) + return -1; + + xdesc = desc->extra; + + switch (xdesc->type) { + case TIMER_PS: +#ifdef XSCUTIMER_H + *counter = XScuTimer_GetCounterValue((XScuTimer *)xdesc->instance); + ++(*counter); + break; +#endif + return -1; + case TIMER_PL: +#ifdef XTMRCTR_H + *counter = XTmrCtr_GetValue(xdesc->instance, xdesc->active_tmr); + break; +#endif + return -1; + default: + *counter = 0; + + return -1; + } + + return 0; +} + + +/** + * @brief Get the timer clock frequency. + * @param [in] desc - Pointer to the device handler. + * @param [out] freq_hz - Pointer to the returned frequency. + * @return 0 in case of success, -1 otherwise + */ +int32_t xilinx_timer_count_clk_get(struct timer_desc *desc, + uint32_t *freq_hz) +{ + struct xil_timer_desc *xdesc; + + if (!desc || !freq_hz) + return -1; + + xdesc = desc->extra; + + switch (xdesc->type) { + case TIMER_PS: +#ifdef XSCUTIMER_H + *freq_hz = desc->freq_hz; + break; +#endif + return -1; + case TIMER_PL: +#ifdef XTMRCTR_H + *freq_hz = ((XTmrCtr_Config *)xdesc->config)->SysClockFreqHz; + break; +#endif + return -1; + default: + *freq_hz = 0; + + return -1; + } + + return 0; +} + + +/** + * @brief Get the elapsed time in nsec for the timer. + * @param [in] desc - Pointer to the device handler. + * @param [in] elapsed_time - The elapsed time in nsec. + * @return -ENOSYS. + */ +int32_t xilinx_timer_get_elapsed_time_nsec(struct timer_desc *desc, + uint64_t *elapsed_time) +{ + /* Function not implemented */ + return -ENOSYS; +} + +/** + * @brief Xilinx platform specific timer platform ops structure + */ +const struct timer_platform_ops xil_timer_ops = { + .init = &xilinx_timer_init, + .start = &xilinx_timer_start, + .stop = &xilinx_timer_stop, + .counter_get = &xilinx_timer_counter_get, + .counter_set = &xilinx_timer_counter_set, + .count_clk_get = &xilinx_timer_count_clk_get, + .count_clk_set = &xilinx_timer_count_clk_set, + .get_elapsed_time_nsec = &xilinx_timer_get_elapsed_time_nsec, + .remove = &xilinx_timer_remove +}; diff --git a/df_datalink/src/drivers/platform/xilinx_timer.h b/df_datalink/src/drivers/platform/xilinx_timer.h new file mode 100644 index 0000000..7f5ff87 --- /dev/null +++ b/df_datalink/src/drivers/platform/xilinx_timer.h @@ -0,0 +1,101 @@ +/***************************************************************************//** +* @file xilinx_timer.h +* @brief Timer control module header. +* @author Andrei Drimbarean (andrei.drimbarean@analog.com) +******************************************************************************** +* Copyright 2020(c) Analog Devices, Inc. +* +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* - Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* - Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* - Neither the name of Analog Devices, Inc. nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* - The use of this software may or may not infringe the patent rights +* of one or more patent holders. This license does not release you +* from the requirement that you obtain separate licenses from these +* patent holders to use this software. +* - Use of the software either in source or binary form, must be run +* on or directly connected to an Analog Devices Inc. component. +* +* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, MERCHANTABILITY +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#ifndef XILINX_TIMER_H_ +#define XILINX_TIMER_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include +#ifdef XPAR_XSCUTIMER_NUM_INSTANCES +#include +#endif +#ifdef XPAR_XTMRCTR_NUM_INSTANCES +#include +#endif + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ + +/** + * @enum xil_timer_type + * @brief Xilinx platform architecture sections + */ +enum xil_timer_type { + /** Programmable Logic */ + TIMER_PL, + /** Processing System */ + TIMER_PS +}; + +/** + * @struct xil_timer_desc + * @brief Xilinx specific timer descriptor + */ +struct xil_timer_desc { + /** Pointer to the BSP driver handler */ + void *instance; + /** Pointer to the BSP driver configuration handler */ + void *config; + /** Timer used from the PL 3-timer core */ + uint8_t active_tmr; + /** Platform selection parameter */ + enum xil_timer_type type; +}; + +/** + * @struct xil_timer_init_param + * @brief Xilinx specific timer initialization structure + */ +struct xil_timer_init_param { + /** Timer used from the PL 3-timer core */ + uint8_t active_tmr; + /** Platform selection parameter */ + enum xil_timer_type type; +}; + +/** + * @brief Xilinx platform specific timer platform ops structure + */ +extern const struct timer_platform_ops xil_timer_ops; + +#endif /* XILINX_TIMER_H_ */ diff --git a/df_datalink/src/drivers/rf-transceiver/ad9361/ad9361.c b/df_datalink/src/drivers/rf-transceiver/ad9361/ad9361.c new file mode 100644 index 0000000..0305df3 --- /dev/null +++ b/df_datalink/src/drivers/rf-transceiver/ad9361/ad9361.c @@ -0,0 +1,7475 @@ +/***************************************************************************//** + * @file ad9361.c + * @brief Implementation of AD9361 Driver. +******************************************************************************** + * Copyright 2014-2015(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include +#include +#include +#include +#include +#include +#include "ad9361.h" +#include "ad9361_util.h" +#include "spi.h" +#include "gpio.h" +#include "delay.h" +#include "util.h" +#include "../../../config/app_config.h" + +#define diff_abs(x, y) ((x) > (y) ? (x - y) : (y - x)) + +#define NO_GAIN_TABLE ((uint32_t)-1) + +/* Used for static code size optimization: please see app_config.h */ +const bool has_split_gt = HAVE_SPLIT_GAIN_TABLE; +const bool have_tdd_tables = HAVE_TDD_SYNTH_TABLE; + +#define SYNTH_LUT_SIZE 53 + +static const struct SynthLUT SynthLUT_FDD[LUT_FTDD_ENT][SYNTH_LUT_SIZE] = { + { + {12605, 13, 1, 4, 2, 15, 12, 7, 14, 6, 14, 5, 15}, /* 40 MHz */ + {12245, 13, 1, 4, 2, 15, 12, 7, 14, 6, 14, 5, 15}, + {11906, 13, 1, 4, 2, 15, 12, 7, 15, 6, 14, 5, 15}, + {11588, 13, 1, 4, 2, 15, 12, 8, 15, 6, 14, 5, 15}, + {11288, 13, 1, 4, 2, 15, 12, 8, 15, 6, 14, 5, 15}, + {11007, 13, 1, 4, 2, 15, 12, 9, 15, 6, 14, 5, 15}, + {10742, 13, 1, 4, 2, 15, 12, 9, 15, 6, 14, 5, 15}, + {10492, 13, 1, 6, 2, 15, 12, 10, 15, 6, 14, 5, 15}, + {10258, 13, 1, 6, 2, 15, 12, 10, 15, 6, 14, 5, 15}, + {10036, 13, 1, 6, 2, 15, 12, 11, 15, 6, 14, 5, 15}, + {9827, 13, 1, 6, 2, 14, 12, 11, 15, 6, 14, 5, 15}, + {9631, 13, 1, 6, 2, 13, 12, 12, 15, 6, 14, 5, 15}, + {9445, 13, 1, 6, 2, 12, 12, 12, 15, 6, 14, 5, 15}, + {9269, 13, 1, 6, 2, 12, 12, 13, 15, 6, 14, 5, 15}, + {9103, 13, 1, 6, 2, 12, 12, 13, 15, 6, 14, 5, 15}, + {8946, 13, 1, 6, 2, 12, 12, 14, 15, 6, 14, 5, 15}, + {8797, 12, 1, 7, 2, 12, 12, 13, 15, 6, 14, 5, 15}, + {8655, 12, 1, 7, 2, 12, 12, 14, 15, 6, 14, 5, 15}, + {8520, 12, 1, 7, 2, 12, 12, 14, 15, 6, 14, 5, 15}, + {8392, 12, 1, 7, 2, 12, 12, 15, 15, 6, 14, 5, 15}, + {8269, 12, 1, 7, 2, 12, 12, 15, 15, 6, 14, 5, 15}, + {8153, 12, 1, 7, 2, 12, 12, 16, 15, 6, 14, 5, 15}, + {8041, 12, 1, 7, 2, 13, 12, 16, 15, 6, 14, 5, 15}, + {7934, 11, 1, 7, 2, 12, 12, 16, 15, 6, 14, 5, 15}, + {7831, 11, 1, 7, 2, 12, 12, 16, 15, 6, 14, 5, 15}, + {7733, 10, 1, 7, 3, 13, 12, 16, 15, 6, 14, 5, 15}, + {7638, 10, 1, 7, 2, 12, 12, 16, 15, 6, 14, 5, 15}, + {7547, 10, 1, 7, 2, 12, 12, 17, 15, 6, 14, 5, 15}, + {7459, 10, 1, 7, 2, 12, 12, 17, 15, 6, 14, 5, 15}, + {7374, 10, 2, 7, 3, 14, 13, 14, 15, 6, 14, 5, 15}, + {7291, 10, 2, 7, 3, 14, 13, 14, 15, 6, 14, 5, 15}, + {7212, 10, 2, 7, 3, 14, 13, 14, 15, 6, 14, 5, 15}, + {7135, 10, 2, 7, 3, 14, 13, 15, 15, 7, 14, 5, 15}, + {7061, 10, 2, 7, 3, 14, 13, 15, 15, 6, 14, 5, 15}, + {6988, 10, 1, 7, 3, 12, 14, 20, 15, 6, 14, 5, 15}, + {6918, 9, 2, 7, 3, 14, 13, 15, 15, 6, 14, 5, 15}, + {6850, 9, 2, 7, 3, 14, 13, 15, 15, 6, 14, 5, 15}, + {6784, 9, 2, 7, 2, 13, 13, 15, 15, 6, 14, 5, 15}, + {6720, 9, 2, 7, 2, 13, 13, 16, 15, 6, 14, 5, 15}, + {6658, 8, 2, 7, 3, 14, 13, 15, 15, 6, 14, 5, 15}, + {6597, 8, 2, 7, 2, 13, 13, 15, 15, 6, 14, 5, 15}, + {6539, 8, 2, 7, 2, 13, 13, 15, 15, 6, 14, 5, 15}, + {6482, 8, 2, 7, 2, 13, 13, 16, 15, 6, 14, 5, 15}, + {6427, 7, 2, 7, 3, 14, 13, 15, 15, 6, 14, 5, 15}, + {6373, 7, 2, 7, 3, 15, 13, 15, 15, 6, 14, 5, 15}, + {6321, 7, 2, 7, 3, 15, 13, 15, 15, 6, 14, 5, 15}, + {6270, 7, 2, 7, 3, 15, 13, 16, 15, 6, 14, 5, 15}, + {6222, 7, 2, 7, 3, 15, 13, 16, 15, 6, 14, 5, 15}, + {6174, 6, 2, 7, 3, 15, 13, 15, 15, 6, 14, 5, 15}, + {6128, 6, 2, 7, 3, 15, 13, 15, 15, 6, 14, 5, 15}, + {6083, 6, 2, 7, 3, 15, 13, 16, 15, 6, 14, 5, 15}, + {6040, 6, 2, 7, 3, 15, 13, 16, 15, 6, 14, 5, 15}, + {5997, 6, 2, 7, 3, 15, 13, 16, 15, 6, 14, 5, 15}, + }, { + {12605, 13, 1, 4, 2, 15, 12, 13, 15, 12, 12, 5, 14}, /* 60 MHz */ + {12245, 13, 1, 4, 2, 15, 12, 13, 15, 12, 12, 5, 14}, + {11906, 13, 1, 4, 2, 15, 12, 13, 15, 13, 12, 5, 13}, + {11588, 13, 1, 4, 2, 15, 12, 14, 15, 13, 12, 5, 13}, + {11288, 13, 1, 5, 2, 15, 12, 15, 15, 13, 12, 5, 13}, + {11007, 13, 1, 5, 2, 15, 12, 16, 15, 13, 12, 5, 13}, + {10742, 13, 1, 5, 2, 15, 12, 16, 15, 12, 12, 5, 14}, + {10492, 13, 1, 6, 2, 15, 12, 17, 15, 12, 12, 5, 14}, + {10258, 13, 1, 6, 2, 15, 12, 18, 15, 13, 12, 5, 13}, + {10036, 13, 1, 6, 2, 15, 12, 19, 15, 13, 12, 5, 13}, + {9827, 13, 1, 6, 2, 14, 12, 20, 15, 13, 12, 5, 13}, + {9631, 13, 1, 6, 2, 13, 12, 21, 15, 13, 12, 5, 13}, + {9445, 13, 1, 6, 2, 12, 12, 22, 15, 13, 12, 5, 13}, + {9269, 13, 1, 6, 2, 12, 12, 22, 15, 12, 12, 5, 14}, + {9103, 13, 1, 6, 2, 12, 12, 23, 15, 13, 12, 5, 13}, + {8946, 13, 1, 6, 2, 12, 12, 24, 15, 13, 12, 5, 13}, + {8797, 12, 1, 7, 2, 12, 12, 24, 15, 13, 12, 5, 13}, + {8655, 12, 1, 7, 2, 12, 12, 25, 15, 13, 12, 5, 13}, + {8520, 12, 1, 7, 2, 12, 12, 25, 15, 13, 12, 5, 13}, + {8392, 12, 1, 7, 2, 12, 12, 26, 15, 13, 12, 5, 13}, + {8269, 12, 1, 7, 2, 12, 12, 27, 15, 13, 12, 5, 13}, + {8153, 12, 1, 7, 2, 12, 12, 28, 15, 13, 12, 5, 13}, + {8041, 12, 1, 7, 2, 13, 12, 29, 15, 13, 12, 5, 13}, + {7934, 11, 1, 7, 2, 12, 12, 28, 15, 13, 12, 5, 13}, + {7831, 11, 1, 7, 2, 12, 12, 29, 15, 13, 12, 5, 13}, + {7733, 10, 1, 7, 3, 13, 12, 28, 15, 13, 12, 5, 13}, + {7638, 10, 1, 7, 2, 12, 12, 29, 15, 13, 12, 5, 13}, + {7547, 10, 1, 7, 2, 12, 12, 29, 15, 13, 12, 5, 13}, + {7459, 10, 1, 7, 2, 12, 12, 30, 15, 13, 12, 5, 13}, + {7374, 10, 2, 7, 3, 14, 13, 24, 15, 13, 12, 5, 13}, + {7291, 10, 2, 7, 3, 14, 13, 25, 15, 13, 12, 5, 13}, + {7212, 10, 2, 7, 3, 14, 13, 25, 15, 13, 12, 5, 13}, + {7135, 10, 2, 7, 3, 14, 13, 26, 15, 13, 12, 5, 13}, + {7061, 10, 2, 7, 3, 14, 13, 26, 15, 13, 12, 5, 13}, + {6988, 10, 1, 7, 3, 12, 14, 35, 15, 13, 12, 5, 13}, + {6918, 9, 1, 7, 3, 12, 14, 33, 15, 13, 12, 5, 13}, + {6850, 9, 1, 7, 3, 12, 14, 34, 15, 13, 12, 5, 13}, + {6784, 9, 1, 7, 2, 11, 14, 35, 15, 13, 12, 5, 13}, + {6720, 9, 1, 7, 2, 11, 14, 35, 15, 13, 12, 5, 13}, + {6658, 8, 2, 7, 3, 15, 13, 26, 15, 13, 12, 5, 13}, + {6597, 8, 2, 7, 2, 15, 13, 27, 15, 13, 12, 5, 13}, + {6539, 8, 2, 7, 2, 15, 13, 27, 15, 13, 12, 5, 13}, + {6482, 8, 2, 7, 2, 15, 13, 28, 15, 13, 12, 5, 13}, + {6427, 7, 2, 7, 3, 14, 13, 27, 15, 13, 12, 5, 13}, + {6373, 7, 2, 7, 3, 15, 13, 27, 15, 13, 12, 5, 13}, + {6321, 7, 2, 7, 3, 15, 13, 27, 15, 13, 12, 5, 13}, + {6270, 7, 2, 7, 3, 15, 13, 28, 15, 13, 12, 5, 13}, + {6222, 7, 2, 7, 3, 15, 13, 28, 15, 13, 12, 5, 13}, + {6174, 6, 2, 7, 3, 15, 13, 27, 15, 13, 12, 5, 13}, + {6128, 6, 2, 7, 3, 15, 13, 27, 15, 13, 12, 5, 13}, + {6083, 6, 2, 7, 3, 15, 13, 28, 15, 13, 12, 5, 13}, + {6040, 6, 2, 7, 3, 15, 13, 28, 15, 13, 12, 5, 13}, + {5997, 6, 2, 7, 3, 15, 13, 29, 15, 13, 12, 5, 13}, + }, { + {12605, 13, 1, 4, 2, 15, 12, 7, 15, 6, 13, 5, 14}, /* 80 MHz */ + {12245, 13, 1, 4, 2, 15, 12, 7, 15, 6, 13, 5, 14}, + {11906, 13, 1, 4, 2, 15, 12, 7, 15, 6, 13, 5, 14}, + {11588, 13, 1, 4, 2, 15, 12, 7, 14, 6, 14, 4, 14}, + {11288, 13, 1, 4, 2, 15, 12, 8, 15, 6, 13, 5, 14}, + {11007, 13, 1, 4, 2, 15, 12, 8, 14, 6, 13, 5, 14}, + {10742, 13, 1, 4, 2, 15, 12, 9, 15, 6, 13, 5, 14}, + {10492, 13, 1, 6, 2, 15, 12, 9, 14, 6, 13, 5, 14}, + {10258, 13, 1, 6, 2, 15, 12, 10, 15, 6, 13, 5, 14}, + {10036, 13, 1, 6, 2, 15, 12, 10, 15, 6, 13, 5, 14}, + {9827, 13, 1, 6, 2, 14, 12, 11, 15, 6, 13, 5, 14}, + {9631, 13, 1, 6, 2, 13, 12, 11, 15, 6, 13, 5, 14}, + {9445, 13, 1, 6, 2, 12, 12, 12, 15, 6, 13, 5, 14}, + {9269, 13, 1, 6, 2, 12, 12, 12, 15, 6, 13, 5, 14}, + {9103, 13, 1, 6, 2, 12, 12, 13, 15, 6, 13, 5, 14}, + {8946, 13, 1, 6, 2, 12, 12, 13, 15, 6, 13, 5, 14}, + {8797, 12, 1, 7, 2, 12, 12, 13, 15, 6, 13, 5, 14}, + {8655, 12, 1, 7, 2, 12, 12, 14, 15, 6, 13, 5, 14}, + {8520, 12, 1, 7, 2, 12, 12, 14, 15, 6, 13, 5, 14}, + {8392, 12, 1, 7, 2, 12, 12, 15, 15, 7, 13, 5, 14}, + {8269, 12, 1, 7, 2, 12, 12, 15, 15, 6, 13, 5, 14}, + {8153, 12, 1, 7, 2, 12, 12, 15, 15, 6, 13, 5, 14}, + {8041, 12, 1, 7, 2, 13, 12, 16, 15, 6, 13, 5, 14}, + {7934, 11, 1, 7, 2, 12, 12, 15, 15, 6, 13, 5, 14}, + {7831, 11, 1, 7, 2, 12, 12, 16, 15, 6, 13, 5, 14}, + {7733, 10, 1, 7, 3, 13, 12, 15, 15, 6, 13, 5, 14}, + {7638, 10, 1, 7, 2, 12, 12, 16, 15, 6, 13, 5, 14}, + {7547, 10, 1, 7, 2, 12, 12, 16, 15, 6, 13, 5, 14}, + {7459, 10, 1, 7, 2, 12, 12, 17, 15, 6, 13, 5, 14}, + {7374, 10, 2, 7, 3, 14, 13, 13, 15, 6, 13, 5, 14}, + {7291, 10, 2, 7, 3, 14, 13, 14, 15, 6, 13, 5, 14}, + {7212, 10, 2, 7, 3, 14, 13, 14, 15, 6, 13, 5, 14}, + {7135, 10, 2, 7, 3, 14, 13, 14, 15, 6, 13, 5, 14}, + {7061, 10, 2, 7, 3, 14, 13, 15, 15, 6, 13, 5, 14}, + {6988, 10, 1, 7, 3, 12, 14, 19, 15, 6, 13, 5, 14}, + {6918, 9, 2, 7, 3, 14, 13, 14, 15, 6, 13, 5, 14}, + {6850, 9, 2, 7, 3, 14, 13, 15, 15, 6, 13, 5, 14}, + {6784, 9, 2, 7, 2, 13, 13, 15, 15, 6, 13, 5, 14}, + {6720, 9, 2, 7, 2, 13, 13, 15, 15, 6, 13, 5, 14}, + {6658, 8, 2, 7, 3, 14, 13, 15, 15, 6, 13, 5, 14}, + {6597, 8, 2, 7, 2, 13, 13, 15, 15, 6, 13, 5, 14}, + {6539, 8, 2, 7, 2, 13, 13, 15, 15, 6, 13, 5, 14}, + {6482, 8, 2, 7, 2, 13, 13, 15, 15, 6, 13, 5, 14}, + {6427, 7, 2, 7, 3, 14, 13, 15, 15, 6, 13, 5, 14}, + {6373, 7, 2, 7, 3, 15, 13, 15, 15, 6, 13, 5, 14}, + {6321, 7, 2, 7, 3, 15, 13, 15, 15, 6, 13, 5, 14}, + {6270, 7, 2, 7, 3, 15, 13, 15, 15, 6, 13, 5, 14}, + {6222, 7, 2, 7, 3, 15, 13, 16, 15, 6, 13, 5, 14}, + {6174, 6, 2, 7, 3, 15, 13, 15, 15, 6, 13, 5, 14}, + {6128, 6, 2, 7, 3, 15, 13, 15, 15, 6, 13, 5, 14}, + {6083, 6, 2, 7, 3, 15, 13, 15, 15, 6, 13, 5, 14}, + {6040, 6, 2, 7, 3, 15, 13, 16, 15, 6, 13, 5, 14}, + {5997, 6, 2, 7, 3, 15, 13, 16, 15, 6, 13, 5, 14}, + } +}; + +static const struct SynthLUT SynthLUT_TDD[LUT_FTDD_ENT][SYNTH_LUT_SIZE] = { + { + {12605, 13, 1, 4, 2, 15, 12, 27, 12, 15, 12, 4, 13}, /* 40 MHz */ + {12245, 13, 1, 4, 2, 15, 12, 27, 12, 15, 12, 4, 13}, + {11906, 13, 1, 4, 2, 15, 12, 26, 11, 15, 12, 4, 13}, + {11588, 13, 1, 4, 2, 15, 12, 28, 12, 15, 12, 4, 13}, + {11288, 13, 1, 4, 2, 15, 12, 30, 12, 15, 12, 4, 13}, + {11007, 13, 1, 4, 2, 15, 12, 32, 12, 15, 12, 4, 13}, + {10742, 13, 1, 4, 2, 15, 12, 33, 12, 15, 12, 4, 13}, + {10492, 13, 1, 6, 2, 15, 12, 35, 12, 15, 12, 4, 13}, + {10258, 13, 1, 6, 2, 15, 12, 37, 12, 15, 12, 4, 13}, + {10036, 13, 1, 6, 2, 15, 12, 38, 12, 15, 12, 4, 13}, + {9827, 13, 1, 6, 2, 14, 12, 40, 12, 15, 12, 4, 13}, + {9631, 13, 1, 6, 2, 13, 12, 42, 12, 15, 12, 4, 13}, + {9445, 13, 1, 6, 2, 12, 12, 44, 12, 15, 12, 4, 13}, + {9269, 13, 1, 6, 2, 12, 12, 45, 12, 15, 12, 4, 13}, + {9103, 13, 1, 6, 2, 12, 12, 47, 12, 15, 12, 4, 13}, + {8946, 13, 1, 6, 2, 12, 12, 49, 12, 15, 12, 4, 13}, + {8797, 12, 1, 7, 2, 12, 12, 48, 12, 15, 12, 4, 13}, + {8655, 12, 1, 7, 2, 12, 12, 50, 12, 15, 12, 4, 13}, + {8520, 12, 1, 7, 2, 12, 12, 51, 12, 15, 12, 4, 13}, + {8392, 12, 1, 7, 2, 12, 12, 53, 12, 15, 12, 4, 13}, + {8269, 12, 1, 7, 2, 12, 12, 55, 12, 15, 12, 4, 13}, + {8153, 12, 1, 7, 2, 12, 12, 56, 12, 15, 12, 4, 13}, + {8041, 12, 1, 7, 2, 13, 12, 58, 12, 15, 12, 4, 13}, + {7934, 11, 1, 7, 2, 12, 12, 57, 12, 15, 12, 4, 13}, + {7831, 11, 1, 7, 2, 12, 12, 58, 12, 15, 12, 4, 13}, + {7733, 10, 1, 7, 3, 13, 12, 56, 12, 15, 12, 4, 13}, + {7638, 10, 1, 7, 2, 12, 12, 58, 12, 15, 12, 4, 13}, + {7547, 10, 1, 7, 2, 12, 12, 59, 12, 15, 12, 4, 13}, + {7459, 10, 1, 7, 2, 12, 12, 61, 12, 15, 12, 4, 13}, + {7374, 10, 2, 7, 3, 14, 13, 49, 12, 15, 12, 4, 13}, + {7291, 10, 2, 7, 3, 14, 13, 50, 12, 15, 12, 4, 13}, + {7212, 10, 2, 7, 3, 14, 13, 51, 12, 15, 12, 4, 13}, + {7135, 10, 2, 7, 3, 14, 13, 52, 12, 15, 12, 4, 13}, + {7061, 10, 2, 7, 3, 14, 13, 53, 12, 15, 12, 4, 13}, + {6988, 10, 1, 7, 3, 12, 14, 63, 11, 14, 12, 3, 13}, + {6918, 9, 2, 7, 3, 14, 13, 52, 12, 15, 12, 4, 13}, + {6850, 9, 2, 7, 3, 14, 13, 53, 12, 15, 12, 4, 13}, + {6784, 9, 2, 7, 2, 13, 13, 54, 12, 15, 12, 4, 13}, + {6720, 9, 2, 7, 2, 13, 13, 56, 12, 15, 12, 4, 13}, + {6658, 8, 2, 7, 3, 14, 13, 53, 12, 15, 12, 4, 13}, + {6597, 8, 2, 7, 2, 13, 13, 54, 12, 15, 12, 4, 13}, + {6539, 8, 2, 7, 2, 13, 13, 55, 12, 15, 12, 4, 13}, + {6482, 8, 2, 7, 2, 13, 13, 56, 12, 15, 12, 4, 13}, + {6427, 7, 2, 7, 3, 14, 13, 54, 12, 15, 12, 4, 13}, + {6373, 7, 2, 7, 3, 15, 13, 54, 12, 15, 12, 4, 13}, + {6321, 7, 2, 7, 3, 15, 13, 55, 12, 15, 12, 4, 13}, + {6270, 7, 2, 7, 3, 15, 13, 56, 12, 15, 12, 4, 13}, + {6222, 7, 2, 7, 3, 15, 13, 57, 12, 15, 12, 4, 13}, + {6174, 6, 2, 7, 3, 15, 13, 54, 12, 15, 12, 4, 13}, + {6128, 6, 2, 7, 3, 15, 13, 55, 12, 15, 12, 4, 13}, + {6083, 6, 2, 7, 3, 15, 13, 56, 12, 15, 12, 4, 13}, + {6040, 6, 2, 7, 3, 15, 13, 57, 12, 15, 12, 4, 13}, + {5997, 6, 2, 7, 3, 15, 13, 58, 12, 15, 12, 4, 13}, + }, { + {12605, 13, 1, 4, 2, 15, 12, 26, 11, 15, 11, 4, 13}, /* 60 MHz */ + {12245, 13, 1, 4, 2, 15, 12, 26, 11, 15, 11, 4, 13}, + {11906, 13, 1, 4, 2, 15, 12, 26, 12, 15, 11, 4, 12}, + {11588, 13, 1, 4, 2, 15, 12, 30, 12, 15, 11, 4, 12}, + {11288, 13, 1, 4, 2, 15, 12, 32, 12, 15, 10, 4, 12}, + {11007, 13, 1, 4, 2, 15, 12, 31, 12, 15, 11, 4, 12}, + {10742, 13, 1, 4, 2, 15, 12, 33, 12, 15, 10, 4, 12}, + {10492, 13, 1, 6, 2, 15, 12, 37, 12, 15, 10, 4, 12}, + {10258, 13, 1, 6, 2, 15, 12, 38, 12, 15, 11, 4, 13}, + {10036, 13, 1, 6, 2, 15, 12, 38, 12, 15, 10, 4, 12}, + {9827, 13, 1, 6, 2, 14, 12, 42, 12, 15, 11, 4, 12}, + {9631, 13, 1, 6, 2, 13, 12, 41, 12, 15, 11, 4, 12}, + {9445, 13, 1, 6, 2, 12, 12, 45, 12, 15, 11, 4, 12}, + {9269, 13, 1, 6, 2, 12, 12, 47, 12, 15, 11, 4, 12}, + {9103, 13, 1, 6, 2, 12, 12, 46, 12, 15, 11, 4, 12}, + {8946, 13, 1, 6, 2, 12, 12, 48, 12, 15, 10, 4, 12}, + {8797, 12, 1, 7, 2, 12, 12, 49, 12, 15, 11, 4, 13}, + {8655, 12, 1, 7, 2, 12, 12, 51, 12, 15, 11, 4, 12}, + {8520, 12, 1, 7, 2, 12, 12, 50, 12, 15, 11, 4, 12}, + {8392, 12, 1, 7, 2, 12, 12, 52, 12, 15, 10, 4, 12}, + {8269, 12, 1, 7, 2, 12, 12, 56, 12, 15, 10, 4, 12}, + {8153, 12, 1, 7, 2, 12, 12, 55, 12, 15, 11, 4, 12}, + {8041, 12, 1, 7, 2, 13, 12, 57, 12, 15, 10, 4, 12}, + {7934, 11, 1, 7, 2, 12, 12, 55, 12, 15, 11, 4, 12}, + {7831, 11, 1, 7, 2, 12, 12, 57, 12, 15, 10, 4, 12}, + {7733, 10, 1, 7, 3, 13, 12, 55, 12, 15, 11, 4, 12}, + {7638, 10, 1, 7, 2, 12, 12, 59, 12, 15, 10, 4, 12}, + {7547, 10, 1, 7, 2, 12, 12, 60, 12, 15, 11, 4, 12}, + {7459, 10, 1, 7, 2, 12, 12, 48, 12, 15, 11, 4, 12}, + {7374, 10, 2, 7, 3, 14, 13, 47, 12, 15, 11, 4, 13}, + {7291, 10, 2, 7, 3, 14, 13, 49, 12, 15, 10, 4, 12}, + {7212, 10, 2, 7, 3, 14, 13, 50, 12, 15, 10, 4, 12}, + {7135, 10, 2, 7, 3, 14, 13, 52, 12, 15, 11, 4, 13}, + {7061, 10, 2, 7, 3, 14, 13, 52, 12, 15, 11, 4, 12}, + {6988, 10, 1, 7, 3, 12, 14, 63, 11, 15, 11, 4, 13}, + {6918, 9, 1, 7, 3, 12, 14, 63, 11, 15, 11, 4, 13}, + {6850, 9, 1, 7, 3, 12, 14, 63, 11, 15, 11, 4, 13}, + {6784, 9, 1, 7, 2, 11, 14, 63, 11, 15, 11, 4, 13}, + {6720, 9, 1, 7, 2, 11, 14, 63, 11, 14, 11, 3, 13}, + {6658, 8, 1, 7, 3, 12, 14, 63, 11, 15, 11, 4, 13}, + {6597, 8, 1, 7, 2, 11, 14, 63, 11, 14, 11, 3, 13}, + {6539, 8, 1, 7, 2, 11, 14, 63, 10, 14, 11, 3, 13}, + {6482, 8, 1, 7, 2, 11, 14, 63, 10, 14, 11, 3, 13}, + {6427, 7, 2, 7, 3, 14, 13, 54, 12, 15, 10, 4, 12}, + {6373, 7, 2, 7, 3, 15, 13, 53, 12, 15, 11, 4, 12}, + {6321, 7, 2, 7, 3, 15, 13, 54, 12, 15, 11, 4, 12}, + {6270, 7, 2, 7, 3, 15, 13, 55, 12, 15, 11, 4, 12}, + {6222, 7, 2, 7, 3, 15, 13, 56, 12, 15, 11, 4, 12}, + {6174, 6, 2, 7, 3, 15, 13, 53, 12, 15, 11, 4, 12}, + {6128, 6, 2, 7, 3, 15, 13, 55, 12, 15, 11, 4, 12}, + {6083, 6, 2, 7, 3, 15, 13, 55, 12, 15, 10, 4, 12}, + {6040, 6, 2, 7, 3, 15, 13, 56, 12, 15, 10, 4, 12}, + {5997, 6, 2, 7, 3, 15, 13, 57, 12, 15, 10, 4, 12}, + }, { + {12605, 13, 1, 4, 2, 15, 12, 21, 12, 15, 11, 4, 13}, /* 80 MHz */ + {12245, 13, 1, 4, 2, 15, 12, 21, 12, 15, 11, 4, 13}, + {11906, 13, 1, 4, 2, 15, 12, 20, 11, 15, 11, 4, 13}, + {11588, 13, 1, 4, 2, 15, 12, 22, 12, 15, 11, 4, 12}, + {11288, 13, 1, 5, 2, 15, 12, 23, 12, 15, 11, 4, 13}, + {11007, 13, 1, 5, 2, 15, 12, 25, 12, 15, 10, 4, 12}, + {10742, 13, 1, 5, 2, 15, 12, 26, 12, 15, 11, 4, 13}, + {10492, 13, 1, 6, 2, 15, 12, 27, 11, 15, 11, 4, 13}, + {10258, 13, 1, 6, 2, 15, 12, 29, 12, 15, 10, 4, 12}, + {10036, 13, 1, 6, 2, 15, 12, 30, 12, 15, 11, 4, 12}, + {9827, 13, 1, 6, 2, 14, 12, 31, 12, 15, 11, 4, 13}, + {9631, 13, 1, 6, 2, 13, 12, 33, 12, 15, 10, 4, 12}, + {9445, 13, 1, 6, 2, 12, 12, 34, 12, 15, 11, 4, 12}, + {9269, 13, 1, 6, 2, 12, 12, 35, 12, 15, 11, 4, 13}, + {9103, 13, 1, 6, 2, 12, 12, 37, 12, 15, 10, 4, 12}, + {8946, 13, 1, 6, 2, 12, 12, 38, 12, 15, 11, 4, 12}, + {8797, 12, 1, 7, 2, 12, 12, 37, 12, 15, 11, 4, 13}, + {8655, 12, 1, 7, 2, 12, 12, 39, 12, 15, 11, 4, 12}, + {8520, 12, 1, 7, 2, 12, 12, 40, 12, 15, 11, 4, 12}, + {8392, 12, 1, 7, 2, 12, 12, 41, 12, 15, 11, 4, 13}, + {8269, 12, 1, 7, 2, 12, 12, 43, 12, 15, 10, 4, 12}, + {8153, 12, 1, 7, 2, 12, 12, 44, 12, 15, 11, 4, 12}, + {8041, 12, 1, 7, 2, 13, 12, 45, 12, 15, 11, 4, 12}, + {7934, 11, 1, 7, 2, 12, 12, 44, 12, 15, 11, 4, 12}, + {7831, 11, 1, 7, 2, 12, 12, 45, 12, 15, 11, 4, 13}, + {7733, 10, 1, 7, 3, 13, 12, 44, 12, 15, 11, 4, 12}, + {7638, 10, 1, 7, 2, 12, 12, 45, 12, 15, 11, 4, 12}, + {7547, 10, 1, 7, 2, 12, 12, 46, 12, 15, 11, 4, 12}, + {7459, 10, 1, 7, 2, 12, 12, 47, 12, 15, 11, 4, 13}, + {7374, 10, 2, 7, 3, 14, 13, 38, 12, 15, 11, 4, 12}, + {7291, 10, 2, 7, 3, 14, 13, 39, 12, 15, 10, 4, 12}, + {7212, 10, 2, 7, 3, 14, 13, 40, 12, 15, 10, 4, 12}, + {7135, 10, 2, 7, 3, 14, 13, 41, 12, 15, 10, 4, 12}, + {7061, 10, 2, 7, 3, 14, 13, 41, 12, 15, 11, 4, 13}, + {6988, 10, 1, 7, 3, 12, 14, 54, 12, 15, 11, 4, 12}, + {6918, 9, 2, 7, 3, 14, 13, 41, 12, 15, 10, 4, 12}, + {6850, 9, 2, 7, 3, 14, 13, 42, 12, 15, 10, 4, 12}, + {6784, 9, 2, 7, 2, 13, 13, 42, 12, 15, 11, 4, 13}, + {6720, 9, 2, 7, 2, 13, 13, 43, 12, 15, 11, 4, 13}, + {6658, 8, 2, 7, 3, 14, 13, 41, 12, 15, 11, 4, 13}, + {6597, 8, 2, 7, 2, 13, 13, 42, 12, 15, 11, 4, 12}, + {6539, 8, 2, 7, 2, 13, 13, 43, 12, 15, 11, 4, 12}, + {6482, 8, 2, 7, 2, 13, 13, 44, 12, 15, 11, 4, 12}, + {6427, 7, 2, 7, 3, 14, 13, 42, 12, 15, 10, 4, 12}, + {6373, 7, 2, 7, 3, 15, 13, 42, 12, 15, 11, 4, 13}, + {6321, 7, 2, 7, 3, 15, 13, 43, 12, 15, 11, 4, 12}, + {6270, 7, 2, 7, 3, 15, 13, 44, 12, 15, 11, 4, 12}, + {6222, 7, 2, 7, 3, 15, 13, 45, 12, 15, 10, 4, 12}, + {6174, 6, 2, 7, 3, 15, 13, 42, 12, 15, 11, 4, 13}, + {6128, 6, 2, 7, 3, 15, 13, 43, 12, 15, 11, 4, 12}, + {6083, 6, 2, 7, 3, 15, 13, 44, 12, 15, 10, 4, 12}, + {6040, 6, 2, 7, 3, 15, 13, 44, 12, 15, 11, 4, 13}, + {5997, 6, 2, 7, 3, 15, 13, 45, 12, 15, 11, 4, 12}, + } +}; + +/* Rx Gain Tables */ + +#define SIZE_FULL_TABLE 77 + +static const uint8_t full_gain_table[RXGAIN_TBLS_END][SIZE_FULL_TABLE][3] = { + { /* 800 MHz */ + {0x00, 0x00, 0x20}, {0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, + {0x00, 0x01, 0x00}, {0x00, 0x02, 0x00}, {0x00, 0x03, 0x00}, + {0x00, 0x04, 0x00}, {0x00, 0x05, 0x00}, {0x01, 0x03, 0x20}, + {0x01, 0x04, 0x00}, {0x01, 0x05, 0x00}, {0x01, 0x06, 0x00}, + {0x01, 0x07, 0x00}, {0x01, 0x08, 0x00}, {0x01, 0x09, 0x00}, + {0x01, 0x0A, 0x00}, {0x01, 0x0B, 0x00}, {0x01, 0x0C, 0x00}, + {0x01, 0x0D, 0x00}, {0x01, 0x0E, 0x00}, {0x02, 0x09, 0x20}, + {0x02, 0x0A, 0x00}, {0x02, 0x0B, 0x00}, {0x02, 0x0C, 0x00}, + {0x02, 0x0D, 0x00}, {0x02, 0x0E, 0x00}, {0x02, 0x0F, 0x00}, + {0x02, 0x10, 0x00}, {0x02, 0x2B, 0x20}, {0x02, 0x2C, 0x00}, + {0x04, 0x28, 0x20}, {0x04, 0x29, 0x00}, {0x04, 0x2A, 0x00}, + {0x04, 0x2B, 0x00}, {0x24, 0x20, 0x20}, {0x24, 0x21, 0x00}, + {0x44, 0x20, 0x20}, {0x44, 0x21, 0x00}, {0x44, 0x22, 0x00}, + {0x44, 0x23, 0x00}, {0x44, 0x24, 0x00}, {0x44, 0x25, 0x00}, + {0x44, 0x26, 0x00}, {0x44, 0x27, 0x00}, {0x44, 0x28, 0x00}, + {0x44, 0x29, 0x00}, {0x44, 0x2A, 0x00}, {0x44, 0x2B, 0x00}, + {0x44, 0x2C, 0x00}, {0x44, 0x2D, 0x00}, {0x44, 0x2E, 0x00}, + {0x44, 0x2F, 0x00}, {0x44, 0x30, 0x00}, {0x44, 0x31, 0x00}, + {0x44, 0x32, 0x00}, {0x64, 0x2E, 0x20}, {0x64, 0x2F, 0x00}, + {0x64, 0x30, 0x00}, {0x64, 0x31, 0x00}, {0x64, 0x32, 0x00}, + {0x64, 0x33, 0x00}, {0x64, 0x34, 0x00}, {0x64, 0x35, 0x00}, + {0x64, 0x36, 0x00}, {0x64, 0x37, 0x00}, {0x64, 0x38, 0x00}, + {0x65, 0x38, 0x20}, {0x66, 0x38, 0x20}, {0x67, 0x38, 0x20}, + {0x68, 0x38, 0x20}, {0x69, 0x38, 0x20}, {0x6A, 0x38, 0x20}, + {0x6B, 0x38, 0x20}, {0x6C, 0x38, 0x20}, {0x6D, 0x38, 0x20}, + {0x6E, 0x38, 0x20}, {0x6F, 0x38, 0x20} + },{ /* 2300 MHz */ + {0x00, 0x00, 0x20}, {0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, + {0x00, 0x01, 0x00}, {0x00, 0x02, 0x00}, {0x00, 0x03, 0x00}, + {0x00, 0x04, 0x00}, {0x00, 0x05, 0x00}, {0x01, 0x03, 0x20}, + {0x01, 0x04, 0x00}, {0x01, 0x05, 0x00}, {0x01, 0x06, 0x00}, + {0x01, 0x07, 0x00}, {0x01, 0x08, 0x00}, {0x01, 0x09, 0x00}, + {0x01, 0x0A, 0x00}, {0x01, 0x0B, 0x00}, {0x01, 0x0C, 0x00}, + {0x01, 0x0D, 0x00}, {0x01, 0x0E, 0x00}, {0x02, 0x09, 0x20}, + {0x02, 0x0A, 0x00}, {0x02, 0x0B, 0x00}, {0x02, 0x0C, 0x00}, + {0x02, 0x0D, 0x00}, {0x02, 0x0E, 0x00}, {0x02, 0x0F, 0x00}, + {0x02, 0x10, 0x00}, {0x02, 0x2B, 0x20}, {0x02, 0x2C, 0x00}, + {0x04, 0x27, 0x20}, {0x04, 0x28, 0x00}, {0x04, 0x29, 0x00}, + {0x04, 0x2A, 0x00}, {0x04, 0x2B, 0x00}, {0x24, 0x21, 0x20}, + {0x24, 0x22, 0x00}, {0x44, 0x20, 0x20}, {0x44, 0x21, 0x00}, + {0x44, 0x22, 0x00}, {0x44, 0x23, 0x00}, {0x44, 0x24, 0x00}, + {0x44, 0x25, 0x00}, {0x44, 0x26, 0x00}, {0x44, 0x27, 0x00}, + {0x44, 0x28, 0x00}, {0x44, 0x29, 0x00}, {0x44, 0x2A, 0x00}, + {0x44, 0x2B, 0x00}, {0x44, 0x2C, 0x00}, {0x44, 0x2D, 0x00}, + {0x44, 0x2E, 0x00}, {0x44, 0x2F, 0x00}, {0x44, 0x30, 0x00}, + {0x44, 0x31, 0x00}, {0x64, 0x2E, 0x20}, {0x64, 0x2F, 0x00}, + {0x64, 0x30, 0x00}, {0x64, 0x31, 0x00}, {0x64, 0x32, 0x00}, + {0x64, 0x33, 0x00}, {0x64, 0x34, 0x00}, {0x64, 0x35, 0x00}, + {0x64, 0x36, 0x00}, {0x64, 0x37, 0x00}, {0x64, 0x38, 0x00}, + {0x65, 0x38, 0x20}, {0x66, 0x38, 0x20}, {0x67, 0x38, 0x20}, + {0x68, 0x38, 0x20}, {0x69, 0x38, 0x20}, {0x6A, 0x38, 0x20}, + {0x6B, 0x38, 0x20}, {0x6C, 0x38, 0x20}, {0x6D, 0x38, 0x20}, + {0x6E, 0x38, 0x20}, {0x6F, 0x38, 0x20}, + },{ /* 5500 MHz */ + {0x00, 0x00, 0x20}, {0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, {0x00, 0x01, 0x00}, + {0x00, 0x02, 0x00}, {0x00, 0x03, 0x00}, {0x01, 0x01, 0x20}, + {0x01, 0x02, 0x00}, {0x01, 0x03, 0x00}, {0x01, 0x04, 0x20}, + {0x01, 0x05, 0x00}, {0x01, 0x06, 0x00}, {0x01, 0x07, 0x00}, + {0x01, 0x08, 0x00}, {0x01, 0x09, 0x00}, {0x01, 0x0A, 0x00}, + {0x01, 0x0B, 0x00}, {0x01, 0x0C, 0x00}, {0x02, 0x08, 0x20}, + {0x02, 0x09, 0x00}, {0x02, 0x0A, 0x00}, {0x02, 0x0B, 0x20}, + {0x02, 0x0C, 0x00}, {0x02, 0x0D, 0x00}, {0x02, 0x0E, 0x00}, + {0x02, 0x0F, 0x00}, {0x02, 0x2A, 0x20}, {0x02, 0x2B, 0x00}, + {0x04, 0x27, 0x20}, {0x04, 0x28, 0x00}, {0x04, 0x29, 0x00}, + {0x04, 0x2A, 0x00}, {0x04, 0x2B, 0x00}, {0x04, 0x2C, 0x00}, + {0x04, 0x2D, 0x00}, {0x24, 0x20, 0x20}, {0x24, 0x21, 0x00}, + {0x24, 0x22, 0x00}, {0x44, 0x20, 0x20}, {0x44, 0x21, 0x00}, + {0x44, 0x22, 0x00}, {0x44, 0x23, 0x00}, {0x44, 0x24, 0x00}, + {0x44, 0x25, 0x00}, {0x44, 0x26, 0x00}, {0x44, 0x27, 0x00}, + {0x44, 0x28, 0x00}, {0x44, 0x29, 0x00}, {0x44, 0x2A, 0x00}, + {0x44, 0x2B, 0x00}, {0x44, 0x2C, 0x00}, {0x44, 0x2D, 0x00}, + {0x44, 0x2E, 0x00}, {0x64, 0x2E, 0x20}, {0x64, 0x2F, 0x00}, + {0x64, 0x30, 0x00}, {0x64, 0x31, 0x00}, {0x64, 0x32, 0x00}, + {0x64, 0x33, 0x00}, {0x64, 0x34, 0x00}, {0x64, 0x35, 0x00}, + {0x64, 0x36, 0x00}, {0x64, 0x37, 0x00}, {0x64, 0x38, 0x00}, + {0x65, 0x38, 0x20}, {0x66, 0x38, 0x20}, {0x67, 0x38, 0x20}, + {0x68, 0x38, 0x20}, {0x69, 0x38, 0x20}, {0x6A, 0x38, 0x20}, + {0x6B, 0x38, 0x20}, {0x6C, 0x38, 0x20}, {0x6D, 0x38, 0x20}, + {0x6E, 0x38, 0x20}, {0x6F, 0x38, 0x20} + } +}; + +static const int8_t full_gain_table_abs_gain[RXGAIN_TBLS_END][SIZE_FULL_TABLE] = { + { /* 800 MHz */ + -1, -1, -1, 0, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, + 13, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 24, 25, 26, 27, 28, + 29, 30, 31, 32, 33, 34, 35, 36, + 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, + 53, 54, 55, 56, 57, 58, 59, 60, + 61, 62, 63, 64, 65, 66, 67, 68, + 69, 70, 71, 72, 73 + }, { /* 2300 MHz */ + -3, -3, -3, -2, -1, 0, 1, 2, + 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, + 35, 36, 37, 38, 39, 40, 41, 42, + 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 56, 57, 58, + 59, 60, 61, 62, 63, 64, 65, 66, + 67, 68, 69, 70, 71 + }, { /* 5500 MHz */ + -10, -10, -10, -10, -10, -9, -8, -7, + -6, -5, -4, -3, -2, -1, 0, 1, + 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, + 18, 19, 20, 21, 22, 23, 24, 25, + 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, + 42, 43, 44, 45, 46, 47, 48, 49, + 50, 51, 52, 53, 54, 55, 56, 57, + 58, 59, 60, 61, 62 + } +}; + +#define SIZE_SPLIT_TABLE 41 + +#if HAVE_SPLIT_GAIN_TABLE +static const uint8_t split_gain_table[RXGAIN_TBLS_END][SIZE_SPLIT_TABLE][3] = { + { /* 800 MHz */ + {0x00, 0x18, 0x20}, {0x00, 0x18, 0x00}, {0x00, 0x18, 0x00}, + {0x00, 0x18, 0x00}, {0x00, 0x18, 0x00}, {0x00, 0x18, 0x00}, + {0x00, 0x18, 0x20}, {0x01, 0x18, 0x20}, {0x02, 0x18, 0x20}, + {0x04, 0x18, 0x20}, {0x04, 0x38, 0x20}, {0x05, 0x38, 0x20}, + {0x06, 0x38, 0x20}, {0x07, 0x38, 0x20}, {0x08, 0x38, 0x20}, + {0x09, 0x38, 0x20}, {0x0A, 0x38, 0x20}, {0x0B, 0x38, 0x20}, + {0x0C, 0x38, 0x20}, {0x0D, 0x38, 0x20}, {0x0E, 0x38, 0x20}, + {0x0F, 0x38, 0x20}, {0x24, 0x38, 0x20}, {0x25, 0x38, 0x20}, + {0x44, 0x38, 0x20}, {0x45, 0x38, 0x20}, {0x46, 0x38, 0x20}, + {0x47, 0x38, 0x20}, {0x48, 0x38, 0x20}, {0x64, 0x38, 0x20}, + {0x65, 0x38, 0x20}, {0x66, 0x38, 0x20}, {0x67, 0x38, 0x20}, + {0x68, 0x38, 0x20}, {0x69, 0x38, 0x20}, {0x6A, 0x38, 0x20}, + {0x6B, 0x38, 0x20}, {0x6C, 0x38, 0x20}, {0x6D, 0x38, 0x20}, + {0x6E, 0x38, 0x20}, {0x6F, 0x38, 0x20}, + },{ /* 2300 MHz */ + {0x00, 0x18, 0x20}, {0x00, 0x18, 0x00}, {0x00, 0x18, 0x00}, + {0x00, 0x18, 0x00}, {0x00, 0x18, 0x00}, {0x00, 0x18, 0x00}, + {0x00, 0x18, 0x00}, {0x00, 0x18, 0x20}, {0x01, 0x18, 0x20}, + {0x02, 0x18, 0x20}, {0x04, 0x18, 0x20}, {0x04, 0x38, 0x20}, + {0x05, 0x38, 0x20}, {0x06, 0x38, 0x20}, {0x07, 0x38, 0x20}, + {0x08, 0x38, 0x20}, {0x09, 0x38, 0x20}, {0x0A, 0x38, 0x20}, + {0x0B, 0x38, 0x20}, {0x0C, 0x38, 0x20}, {0x0D, 0x38, 0x20}, + {0x0E, 0x38, 0x20}, {0x0F, 0x38, 0x20}, {0x25, 0x38, 0x20}, + {0x26, 0x38, 0x20}, {0x44, 0x38, 0x20}, {0x45, 0x38, 0x20}, + {0x46, 0x38, 0x20}, {0x47, 0x38, 0x20}, {0x64, 0x38, 0x20}, + {0x65, 0x38, 0x20}, {0x66, 0x38, 0x20}, {0x67, 0x38, 0x20}, + {0x68, 0x38, 0x20}, {0x69, 0x38, 0x20}, {0x6A, 0x38, 0x20}, + {0x6B, 0x38, 0x20}, {0x6C, 0x38, 0x20}, {0x6D, 0x38, 0x20}, + {0x6E, 0x38, 0x20}, {0x6F, 0x38, 0x20}, + },{ /* 5500 MHz */ + {0x00, 0x18, 0x20}, {0x00, 0x18, 0x00}, {0x00, 0x18, 0x00}, + {0x00, 0x18, 0x00}, {0x00, 0x18, 0x00}, {0x00, 0x18, 0x00}, + {0x00, 0x18, 0x00}, {0x00, 0x18, 0x00}, {0x00, 0x18, 0x00}, + {0x00, 0x18, 0x00}, {0x01, 0x18, 0x20}, {0x02, 0x18, 0x20}, + {0x04, 0x18, 0x20}, {0x04, 0x38, 0x20}, {0x05, 0x38, 0x20}, + {0x06, 0x38, 0x20}, {0x07, 0x38, 0x20}, {0x08, 0x38, 0x20}, + {0x09, 0x38, 0x20}, {0x0A, 0x38, 0x20}, {0x0B, 0x38, 0x20}, + {0x0C, 0x38, 0x20}, {0x0D, 0x38, 0x20}, {0x0E, 0x38, 0x20}, + {0x0F, 0x38, 0x20}, {0x62, 0x38, 0x20}, {0x25, 0x38, 0x20}, + {0x26, 0x38, 0x20}, {0x44, 0x38, 0x20}, {0x64, 0x38, 0x20}, + {0x65, 0x38, 0x20}, {0x66, 0x38, 0x20}, {0x67, 0x38, 0x20}, + {0x68, 0x38, 0x20}, {0x69, 0x38, 0x20}, {0x6A, 0x38, 0x20}, + {0x6B, 0x38, 0x20}, {0x6C, 0x38, 0x20}, {0x6D, 0x38, 0x20}, + {0x6E, 0x38, 0x20}, {0x6F, 0x38, 0x20}, + } +}; + +static const uint8_t +split_gain_table_abs_gain[RXGAIN_TBLS_END][SIZE_SPLIT_TABLE] = { + { /* 800 MHz */ + -1, -1, -1, -1, -1, -1, -1, 2, + 8, 13, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, + 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, + 49 + }, { /* 2300 MHz */ + -3, -3, -3, -3, -3, -3, -3, -3, + 0, 6, 12, 18, 19, 20, 21, 22, + 23, 24, 25, 26, 27, 28, 29, 30, + 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, + 47 + }, { /* 5500 MHz */ + -10, -10, -10, -10, -10, -10, -10, -10, + -10, -10, -7, -2, 3, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, + 20, 22, 24, 25, 26, 27, 28, 29, + 30, 31, 32, 33, 34, 35, 36, 37, + 38 + } +}; +#endif + +struct gain_table_info ad9361_adi_gt_info[] = { + { + .start = 0, + .end = 1300000000ULL, + .max_index = SIZE_FULL_TABLE, + .abs_gain_tbl = (int8_t *) &full_gain_table_abs_gain[TBL_200_1300_MHZ], + .tab = (uint8_t (*)[3]) full_gain_table[TBL_200_1300_MHZ], + },{ + .start = 1300000000ULL, + .end = 4000000000ULL, + .max_index = SIZE_FULL_TABLE, + .abs_gain_tbl = (int8_t *) &full_gain_table_abs_gain[TBL_1300_4000_MHZ], + .tab = (uint8_t (*)[3]) full_gain_table[TBL_1300_4000_MHZ], + },{ + .start = 4000000000ULL, + .end = 6000000000ULL, + .max_index = SIZE_FULL_TABLE, + .abs_gain_tbl = (int8_t *) &full_gain_table_abs_gain[TBL_4000_6000_MHZ], + .tab = (uint8_t (*)[3]) full_gain_table[TBL_4000_6000_MHZ], +#if HAVE_SPLIT_GAIN_TABLE + },{ + .start = 0, + .end = 1300000000ULL, + .max_index = SIZE_SPLIT_TABLE, + .split_table = 1, + .abs_gain_tbl = (int8_t *) &split_gain_table_abs_gain[TBL_200_1300_MHZ], + .tab = (uint8_t (*)[3]) split_gain_table[TBL_200_1300_MHZ], + },{ + .start = 1300000000ULL, + .end = 4000000000ULL, + .max_index = SIZE_SPLIT_TABLE, + .split_table = 1, + .abs_gain_tbl = (int8_t *) &split_gain_table_abs_gain[TBL_1300_4000_MHZ], + .tab = (uint8_t (*)[3]) split_gain_table[TBL_1300_4000_MHZ], + },{ + .start = 4000000000ULL, + .end = 6000000000ULL, + .max_index = SIZE_SPLIT_TABLE, + .split_table = 1, + .abs_gain_tbl = (int8_t *) &split_gain_table_abs_gain[TBL_4000_6000_MHZ], + .tab = (uint8_t (*)[3]) split_gain_table[TBL_4000_6000_MHZ], +#endif + },{ + .start = 0, + .end = 0, + .max_index = 0, + .split_table = 0, + .abs_gain_tbl = NULL, + .tab = NULL, + }, /* Don't Remove */ +}; + +/* Mixer GM Sub-table */ + +static const uint8_t gm_st_gain[16]= {0x78, 0x74, 0x70, 0x6C, 0x68, 0x64, 0x60, + 0x5C, 0x58, 0x54, 0x50, 0x4C, 0x48, 0x30, 0x18, 0x0}; +static const uint8_t gm_st_ctrl[16]= {0x0, 0xD, 0x15, 0x1B, 0x21, 0x25, 0x29, + 0x2C, 0x2F, 0x31, 0x33, 0x34, 0x35, 0x3A, 0x3D, 0x3E}; + + +static const int8_t lna_table[RXGAIN_TBLS_END][4] = { + {5, 17, 19, 24}, {3, 14, 17, 21}, {-4, 10, 13, 14}}; +static const int8_t tia_table[] = {-6, 0}; +static const int8_t mixer_table[RXGAIN_TBLS_END][16] = { + {0, 3, 9, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25}, + {0, 3, 9, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26}, + {0, 3, 8, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24} +}; + +static const uint32_t gain_step_calib_reg_val[4][5] = { + {0xC0, 0x2E, 0x10, 0x06, 0x00}, // LO Frequency Range: 600 to 1300 MHz + {0xC0, 0x2C, 0x10, 0x06, 0x00}, // LO Frequency Range: 1300 to 3300 MHz + {0xB8, 0x2C, 0x10, 0x06, 0x00}, // LO Frequency Range: 2700 to 4100 MHz + {0xA0, 0x24, 0x10, 0x06, 0x00}, // LO Frequency Range: 4000 to 6000 MHz +}; + +/******************************************************************************/ +/********************** Macros and Constants Definitions **********************/ +/******************************************************************************/ +const char *ad9361_ensm_states[] = { + "sleep", "", "", "", "", "alert", "tx", "tx flush", + "rx", "rx_flush", "fdd", "fdd_flush" +}; + +/** + * SPI multiple bytes register read. + * @param spi + * @param reg The register address. + * @param rbuf The data buffer. + * @param num The number of bytes to read. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_spi_readm(struct spi_desc *spi, uint32_t reg, + uint8_t *rbuf, uint32_t num) +{ + int32_t ret = 0; + uint16_t cmd; + uint8_t *rbuffer; + if (num > MAX_MBYTE_SPI) + return -EINVAL; + + cmd = AD_READ | AD_CNT(num) | AD_ADDR(reg); + rbuffer = malloc(num + 2); + if(!rbuffer) + return -ENOMEM; + rbuffer[0] = cmd >> 8; + rbuffer[1] = cmd & 0xFF; + ret = spi_write_and_read(spi, &rbuffer[0], 2 + num); + + if (ret < 0) + dev_err(&spi->dev, "Read Error %"PRId32, ret); + else + memcpy(rbuf, &rbuffer[2], num); + + free(rbuffer); +#ifdef _DEBUG + { + int32_t i; + for (i = 0; i < num; i++) + dev_dbg(&spi->dev, "%s: reg 0x%"PRIX32" val 0x%X", + __func__, reg--, rbuf[i]); + } +#endif + + return ret; +} + +/** + * SPI register read. + * @param spi + * @param reg The register address. + * @return The register value or negative error code in case of failure. + */ +int32_t ad9361_spi_read(struct spi_desc *spi, uint32_t reg) +{ + uint8_t buf; + int32_t ret; + + ret = ad9361_spi_readm(spi, reg, &buf, 1); + if (ret < 0) + return ret; + + return buf; +} + +/** + * SPI register bits read. + * @param spi + * @param reg The register address. + * @param mask The bits mask. + * @param offset The mask offset. + * @return The bits value or negative error code in case of failure. + */ +static int32_t __ad9361_spi_readf(struct spi_desc *spi, uint32_t reg, + uint32_t mask, uint32_t offset) +{ + uint8_t buf; + int32_t ret; + + if (!mask) + return -EINVAL; + + ret = ad9361_spi_readm(spi, reg, &buf, 1); + if (ret < 0) + return ret; + + buf &= mask; + buf >>= offset; + + return buf; +} + +/** + * SPI register bits read. + * @param spi + * @param reg The register address. + * @param mask The bits mask. + * @return The bits value or negative error code in case of failure. + */ +#define ad9361_spi_readf(spi, reg, mask) \ + __ad9361_spi_readf(spi, reg, mask, find_first_bit(mask)) + +/** + * SPI register write. + * @param spi + * @param reg The register address. + * @param val The value of the register. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_spi_write(struct spi_desc *spi, + uint32_t reg, uint32_t val) +{ + uint8_t buf[3]; + int32_t ret; + uint16_t cmd; + + cmd = AD_WRITE | AD_CNT(1) | AD_ADDR(reg); + buf[0] = cmd >> 8; + buf[1] = cmd & 0xFF; + buf[2] = val; + + ret = spi_write_and_read(spi, buf, 3); + if (ret < 0) { + dev_err(&spi->dev, "Write Error %"PRId32, ret); + return ret; + } + +#ifdef _DEBUG + dev_dbg(&spi->dev, "%s: reg 0x%"PRIX32" val 0x%X", __func__, reg, buf[2]); +#endif + + return 0; +} + +/** + * SPI register bits write. + * @param spi + * @param reg The register address. + * @param mask The bits mask. + * @param offset The mask offset. + * @param val The bits value. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t __ad9361_spi_writef(struct spi_desc *spi, uint32_t reg, + uint32_t mask, uint32_t offset, uint32_t val) +{ + uint8_t buf; + int32_t ret; + + if (!mask) + return -EINVAL; + + ret = ad9361_spi_readm(spi, reg, &buf, 1); + if (ret < 0) + return ret; + + buf &= ~mask; + buf |= ((val << offset) & mask); + + return ad9361_spi_write(spi, reg, buf); +} + +/** + * SPI register bits write. + * @param spi + * @param reg The register address. + * @param mask The bits mask. + * @param val The bits value. + * @return 0 in case of success, negative error code otherwise. + */ +#define ad9361_spi_writef(spi, reg, mask, val) \ + __ad9361_spi_writef(spi, reg, mask, find_first_bit(mask), val) + +/** + * SPI multiple bytes register write. + * @param spi + * @param reg The register address. + * @param tbuf The data buffer. + * @param num The number of bytes to read. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_spi_writem(struct spi_desc *spi, + uint32_t reg, uint8_t *tbuf, uint32_t num) +{ + uint8_t buf[10]; + int32_t ret; + uint16_t cmd; + + if (num > MAX_MBYTE_SPI) + return -EINVAL; + + cmd = AD_WRITE | AD_CNT(num) | AD_ADDR(reg); + buf[0] = cmd >> 8; + buf[1] = cmd & 0xFF; + +#ifndef ALTERA_PLATFORM + memcpy(&buf[2], tbuf, num); +#else + int32_t i; + for (i = 0; i < num; i++) + buf[2 + i] = tbuf[i]; +#endif + ret = spi_write_and_read(spi, buf, num + 2); + if (ret < 0) { + dev_err(&spi->dev, "Write Error %"PRId32, ret); + return ret; + } + +#ifdef _DEBUG + { + int32_t i; + for (i = 0; i < num; i++) + dev_dbg(&spi->dev, "Reg 0x%"PRIX32" val 0x%X", reg--, tbuf[i]); + } +#endif + + return 0; +} + +/** + * Validate RF BW frequency. + * @param phy The AD9361 state structure. + * @param bw The RF BW frequency. + * @return The validated RF BW frequency. + */ +uint32_t ad9361_validate_rf_bw(struct ad9361_rf_phy *phy, uint32_t bw) +{ + switch (phy->dev_sel) { + case ID_AD9363A: + return clamp_t(uint32_t, bw, 200000UL, 20000000UL); + default: + return clamp_t(uint32_t, bw, 200000UL, 56000000UL); + } +} + +/** + * Validate RF PLL frequency. + * @param phy The AD9361 state structure. + * @param is_tx TX enabled. + * @param freq The RF PLL frequency. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_validate_rfpll(struct ad9361_rf_phy *phy, bool is_tx, + uint64_t freq) +{ + switch (phy->dev_sel) { + case ID_AD9363A: + if (freq > AD9363A_MAX_CARRIER_FREQ_HZ || + freq < AD9363A_MIN_CARRIER_FREQ_HZ) + return -EINVAL; + break; + default: + if (freq > MAX_CARRIER_FREQ_HZ || freq < (is_tx ? + MIN_TX_CARRIER_FREQ_HZ : MIN_RX_CARRIER_FREQ_HZ)) + return -EINVAL; + } + + return 0; +} + +/** + * Find optimal value. + * @param field + * @param size + * @param ret_start + * @return The optimal delay in case of success, negative error code otherwise. + */ +int32_t ad9361_find_opt(uint8_t *field, uint32_t size, uint32_t *ret_start) +{ + int32_t i, cnt = 0, max_cnt = 0, start, max_start = 0; + + for(i = 0, start = -1; i < (int64_t)size; i++) { + if (field[i] == 0) { + if (start == -1) + start = i; + cnt++; + } else { + if (cnt > max_cnt) { + max_cnt = cnt; + max_start = start; + } + start = -1; + cnt = 0; + } + } + + if (cnt > max_cnt) { + max_cnt = cnt; + max_start = start; + } + + *ret_start = max_start; + + return max_cnt; +} + +/** + * Select the channel mapping in 1rx1tx mode. + * @param phy The AD9361 state structure. + * @param tx TX + * @param channel Channel + * @return The channel number. + */ +int32_t ad9361_1rx1tx_channel_map(struct ad9361_rf_phy *phy, bool tx, + int32_t channel) +{ + uint32_t map; + + if (phy->pdata->rx2tx2) + return channel; + + if (tx) + map = phy->pdata->rx1tx1_mode_use_tx_num; + else + map = phy->pdata->rx1tx1_mode_use_rx_num; + + if (map == 2) + return channel + 1; + + return channel; +} + +/** + * AD9361 Device Reset + * @param phy The AD9361 state structure. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_reset(struct ad9361_rf_phy *phy) +{ + if (phy->gpio_desc_resetb) { + gpio_set_value(phy->gpio_desc_resetb, 0); + mdelay(1); + gpio_set_value(phy->gpio_desc_resetb, 1); + mdelay(1); + dev_dbg(&phy->spi->dev, "%s: by GPIO", __func__); + return 0; + } + + /* SPI Soft Reset was removed from the register map, since it doesn't + * work reliably. Without a prober HW reset randomness may happen. + * Please specify a RESET GPIO. + */ + + ad9361_spi_write(phy->spi, REG_SPI_CONF, SOFT_RESET | _SOFT_RESET); + ad9361_spi_write(phy->spi, REG_SPI_CONF, 0x0); + dev_err(&phy->spi->dev, + "%s: by SPI, this may cause unpredicted behavior!", __func__); + + return -ENODEV; +} + +/** + * Enable/disable the desired TX channel. + * @param phy The AD9361 state structure. + * @param tx_if The desired channel number [1, 2]. + * @param enable Enable/disable option. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_en_dis_tx(struct ad9361_rf_phy *phy, uint32_t tx_if, + uint32_t enable) +{ + if ((tx_if & enable) > 1 && AD9364_DEVICE && enable) + return -EINVAL; + + return ad9361_spi_writef(phy->spi, REG_TX_ENABLE_FILTER_CTRL, + TX_CHANNEL_ENABLE(tx_if), enable); +} + +/** + * Enable/disable the desired RX channel. + * @param phy The AD9361 state structure. + * @param rx_if The desired channel number [1, 2]. + * @param enable Enable/disable option. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_en_dis_rx(struct ad9361_rf_phy *phy, uint32_t rx_if, + uint32_t enable) +{ + if ((rx_if & enable) > 1 && AD9364_DEVICE && enable) + return -EINVAL; + + return ad9361_spi_writef(phy->spi, REG_RX_ENABLE_FILTER_CTRL, + RX_CHANNEL_ENABLE(rx_if), enable); +} + +/** + * Loopback works only TX1->RX1 or RX2->RX2. + * @param phy The AD9361 state structure. + * @param enable Enable. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_int_loopback_fix_ch_cross(struct ad9361_rf_phy *phy, + bool enable) +{ + /* Loopback works only TX1->RX1 or RX2->RX2 */ + if (!phy->pdata->rx2tx2 && phy->pdata->rx1tx1_mode_use_rx_num != + phy->pdata->rx1tx1_mode_use_tx_num) + return ad9361_en_dis_tx(phy, TX_1 | TX_2, + enable ? phy->pdata->rx1tx1_mode_use_rx_num : + phy->pdata->rx1tx1_mode_use_tx_num); + + return 0; +} + +/** + * BIST loopback mode. + * @param phy The AD9361 state structure. + * @param mode BIST loopback mode. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_bist_loopback(struct ad9361_rf_phy *phy, int32_t mode) +{ + uint32_t sp_hd, reg; + + dev_dbg(&phy->spi->dev, "%s: mode %"PRId32, __func__, mode); + + reg = ad9361_spi_read(phy->spi, REG_OBSERVE_CONFIG); + + phy->bist_loopback_mode = mode; + + switch (mode) { + case 0: + ad9361_hdl_loopback(phy, false); + ad9361_int_loopback_fix_ch_cross(phy, false); + reg &= ~(DATA_PORT_SP_HD_LOOP_TEST_OE | + DATA_PORT_LOOP_TEST_ENABLE); + return ad9361_spi_write(phy->spi, REG_OBSERVE_CONFIG, reg); + case 1: + /* loopback (AD9361 internal) TX->RX */ + ad9361_hdl_loopback(phy, false); + ad9361_int_loopback_fix_ch_cross(phy, true); + sp_hd = ad9361_spi_read(phy->spi, REG_PARALLEL_PORT_CONF_3); + if ((sp_hd & SINGLE_PORT_MODE) && (sp_hd & HALF_DUPLEX_MODE)) + reg |= DATA_PORT_SP_HD_LOOP_TEST_OE; + else + reg &= ~DATA_PORT_SP_HD_LOOP_TEST_OE; + + reg |= DATA_PORT_LOOP_TEST_ENABLE; + + return ad9361_spi_write(phy->spi, REG_OBSERVE_CONFIG, reg); + case 2: + /* loopback (FPGA internal) RX->TX */ + ad9361_hdl_loopback(phy, true); + ad9361_int_loopback_fix_ch_cross(phy, false); + reg &= ~(DATA_PORT_SP_HD_LOOP_TEST_OE | + DATA_PORT_LOOP_TEST_ENABLE); + return ad9361_spi_write(phy->spi, REG_OBSERVE_CONFIG, reg); + default: + return -EINVAL; + } +} + +/** + * Get BIST loopback mode. + * @param phy The AD9361 state structure. + * @param mode BIST loopback mode. + * @return 0 in case of success, negative error code otherwise. + */ +void ad9361_get_bist_loopback(struct ad9361_rf_phy *phy, int32_t *mode) +{ + *mode = phy->bist_loopback_mode; +} + +/** + * BIST mode. + * @param phy The AD9361 state structure. + * @param mode Bist mode. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_bist_prbs(struct ad9361_rf_phy *phy, enum ad9361_bist_mode mode) +{ + uint32_t reg = 0; + + dev_dbg(&phy->spi->dev, "%s: mode %d", __func__, mode); + + phy->bist_prbs_mode = mode; + + switch (mode) { + case BIST_DISABLE: + reg = 0; + break; + case BIST_INJ_TX: + reg = BIST_CTRL_POINT(0) | BIST_ENABLE; + break; + case BIST_INJ_RX: + reg = BIST_CTRL_POINT(2) | BIST_ENABLE; + break; + }; + + phy->bist_config = reg; + + return ad9361_spi_write(phy->spi, REG_BIST_CONFIG, reg); +} + +/** + * Get BIST mode settings. + * @param phy The AD9361 state structure. + * @param mode Bist mode. + * @return 0 in case of success, negative error code otherwise. + */ +void ad9361_get_bist_prbs(struct ad9361_rf_phy *phy, + enum ad9361_bist_mode *mode) +{ + *mode = phy->bist_prbs_mode; +} + +/** + * BIST tone. + * @param phy The AD9361 state structure. + * @param mode Bist tone mode. + * @param freq_Hz Bist tone frequency. + * @param level_dB Bist tone level. + * @param mask Bist reg mask. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_bist_tone(struct ad9361_rf_phy *phy, + enum ad9361_bist_mode mode, uint32_t freq_Hz, + uint32_t level_dB, uint32_t mask) +{ + uint32_t clk = 0; + uint32_t reg = 0, reg1, reg_mask; + + dev_dbg(&phy->spi->dev, "%s: mode %d", __func__, mode); + + phy->bist_tone_mode = mode; + phy->bist_tone_freq_Hz = freq_Hz; + phy->bist_tone_level_dB = level_dB; + phy->bist_tone_mask = mask; + + switch (mode) { + case BIST_DISABLE: + reg = 0; + break; + case BIST_INJ_TX: + clk = clk_get_rate(phy, phy->ref_clk_scale[TX_SAMPL_CLK]); + reg = BIST_CTRL_POINT(0) | BIST_ENABLE; + break; + case BIST_INJ_RX: + clk = clk_get_rate(phy, phy->ref_clk_scale[RX_SAMPL_CLK]); + reg = BIST_CTRL_POINT(2) | BIST_ENABLE; + break; + }; + + reg |= TONE_PRBS; + reg |= TONE_LEVEL(level_dB / 6); + + if (freq_Hz < 4) { + reg |= TONE_FREQ(freq_Hz); + } else { + if (clk) + reg |= TONE_FREQ(DIV_ROUND_CLOSEST(freq_Hz * 32, clk) - 1); + } + + reg_mask = BIST_MASK_CHANNEL_1_I_DATA | BIST_MASK_CHANNEL_1_Q_DATA | + BIST_MASK_CHANNEL_2_I_DATA | BIST_MASK_CHANNEL_2_Q_DATA; + + reg1 = ((mask << 2) & reg_mask); + ad9361_spi_write(phy->spi, REG_BIST_AND_DATA_PORT_TEST_CONFIG, reg1); + + phy->bist_config = reg; + + return ad9361_spi_write(phy->spi, REG_BIST_CONFIG, reg); +} + +/** + * Get BIST tone settings. + * @param phy The AD9361 state structure. + * @param mode Bist tone mode. + * @param freq_Hz Bist tone frequency. + * @param level_dB Bist tone level. + * @param mask Bist reg mask. + * @return 0 in case of success, negative error code otherwise. + */ +void ad9361_get_bist_tone(struct ad9361_rf_phy *phy, + enum ad9361_bist_mode *mode, uint32_t *freq_Hz, + uint32_t *level_dB, uint32_t *mask) +{ + *mode = phy->bist_tone_mode; + *freq_Hz = phy->bist_tone_freq_Hz; + *level_dB = phy->bist_tone_level_dB; + *mask = phy->bist_tone_mask; +} + +/** + * Check the calibration done bit. + * @param phy The AD9361 state structure. + * @param reg The register address. + * @param mask The bit mask. + * @param done_state The done state [0,1]. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_check_cal_done(struct ad9361_rf_phy *phy, uint32_t reg, + uint32_t mask, uint32_t done_state) +{ + uint32_t timeout = 20000; /* RFDC_CAL can take long */ + uint32_t state; + + do { + state = ad9361_spi_readf(phy->spi, reg, mask); + if (state == done_state) + return 0; + + if (reg == REG_CALIBRATION_CTRL) + udelay(1200); + else + udelay(120); + } while (timeout--); + + dev_err(&phy->spi->dev, "Calibration TIMEOUT (0x%"PRIX32", 0x%"PRIX32")", reg, + mask); + + return -ETIMEDOUT; +} + +/** + * Run an AD9361 calibration and check the calibration done bit. + * @param phy The AD9361 state structure. + * @param mask The calibration bit mask[RX_BB_TUNE_CAL, TX_BB_TUNE_CAL, + * RX_QUAD_CAL, TX_QUAD_CAL, RX_GAIN_STEP_CAL, TXMON_CAL, + * RFDC_CAL, BBDC_CAL]. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_run_calibration(struct ad9361_rf_phy *phy, uint32_t mask) +{ + int32_t ret = ad9361_spi_write(phy->spi, REG_CALIBRATION_CTRL, mask); + if (ret < 0) + return ret; + + dev_dbg(&phy->spi->dev, "%s: CAL Mask 0x%"PRIx32, __func__, mask); + + return ad9361_check_cal_done(phy, REG_CALIBRATION_CTRL, mask, 0); +} + +/** + * Choose the right RX gain table index for the selected frequency. + * @param freq The frequency value [Hz]. + * @return The index to the RX gain table. + */ +static int32_t ad9361_gt_tableindex(struct ad9361_rf_phy *phy, uint64_t freq) +{ + int32_t i; + + for (i = 0; phy->gt_info[i].tab != NULL; i++) { + if ((phy->pdata->split_gt == phy->gt_info[i].split_table) && + (phy->gt_info[i].start < freq) && + (freq <= phy->gt_info[i].end)) { + return i; + } + } + + dev_err(&phy->spi->dev, + "%s: Failed to find suitable gain table (%"PRIu64")", __func__, freq); + + return 0; +} + +/** + * Return the current gain table index. + * @param phy The AD9361 state structure. + * @return The current gain table index or 0 if the table was not chosen. + */ +uint32_t ad9361_gt(struct ad9361_rf_phy *phy) +{ + if (phy->current_table == NO_GAIN_TABLE) { + dev_err(&phy->spi->dev, "%s: ERROR", __func__); + return 0; + } + + return phy->current_table; +} + +/** + * Shift the real frequency value, so it fits type unsigned long + * Note: PLL operates between 47 .. 6000 MHz which is > 2^32. + * @param freq The frequency value [Hz]. + * @return The shifted frequency value. + */ +uint32_t ad9361_to_clk(uint64_t freq) +{ + return (uint32_t)(freq >> 1); +} + +/** + * Shift back the frequency value, so it reflects the real value. + * Note: PLL operates between 47 .. 6000 MHz which is > 2^32. + * @param freq The frequency value [Hz]. + * @return The shifted frequency value. + */ +uint64_t ad9361_from_clk(uint32_t freq) +{ + return ((uint64_t)freq << 1); +} + +/** + * Find the corresponding table index for a specific gain value. + * @param phy The AD9361 state structure. + * @param gain The gain value. + * @return The table index. + */ +static int find_table_index(struct ad9361_rf_phy *phy, int gain) +{ + uint32_t i, nm1, n; + + for (i = 0; i < phy->gt_info[ad9361_gt(phy)].max_index; i++) { + if (phy->gt_info[ad9361_gt(phy)].abs_gain_tbl[i] >= gain) { + nm1 = abs(phy->gt_info[ad9361_gt(phy)].abs_gain_tbl[ + (i > 0) ? i - 1 : i] - gain); + n = abs(phy->gt_info[ad9361_gt(phy)].abs_gain_tbl[i] + - gain); + if (nm1 < n) + return (i > 0) ? i - 1 : i; + else + return i; + } + } + + return -EINVAL; +} + +/** + * Load the gain table for the selected frequency range and receiver. + * @param phy The AD9361 state structure. + * @param freq The frequency value [Hz]. + * @param dest The destination [GT_RX1, GT_RX2]. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_load_gt(struct ad9361_rf_phy *phy, uint64_t freq, + uint32_t dest) +{ + struct spi_desc *spi = phy->spi; + uint8_t (*tab)[3]; + uint32_t band, index_max, i, lna, lpf_tia_mask, set_gain; + int32_t ret, rx1_gain, rx2_gain; + + dev_dbg(&phy->spi->dev, "%s: frequency %"PRIu64, __func__, freq); + + band = ad9361_gt_tableindex(phy, freq); + + dev_dbg(&phy->spi->dev, "%s: frequency %"PRIu64" (band %"PRIu32")", + __func__, freq, band); + + /* check if table is present */ + if (phy->current_table == band) + return 0; + + tab = phy->gt_info[band].tab; + index_max = phy->gt_info[band].max_index; + + ad9361_spi_writef(spi, REG_AGC_CONFIG_2, + AGC_USE_FULL_GAIN_TABLE, !phy->pdata->split_gt); + + ad9361_spi_write(spi, REG_MAX_LMT_FULL_GAIN, + index_max - 1); /* Max Full/LMT Gain Table Index */ + + set_gain = ad9361_spi_readf(spi, REG_RX1_MANUAL_LMT_FULL_GAIN, + RX_FULL_TBL_IDX_MASK); + + if (phy->current_table != NO_GAIN_TABLE) { + rx1_gain = phy->gt_info[phy->current_table].abs_gain_tbl[set_gain]; + } else { + if (set_gain > (index_max - 1)) + set_gain = index_max - 1; + + rx1_gain = phy->gt_info[band].abs_gain_tbl[set_gain]; + } + + set_gain = ad9361_spi_readf(spi, REG_RX2_MANUAL_LMT_FULL_GAIN, + RX_FULL_TBL_IDX_MASK); + + if (phy->current_table != NO_GAIN_TABLE) { + rx2_gain = phy->gt_info[phy->current_table].abs_gain_tbl[set_gain]; + } else { + if (set_gain > (index_max - 1)) + set_gain = index_max - 1; + + rx2_gain = phy->gt_info[band].abs_gain_tbl[set_gain]; + } + + lna = phy->pdata->elna_ctrl.elna_in_gaintable_all_index_en ? + EXT_LNA_CTRL : 0; + + ad9361_spi_write(spi, REG_GAIN_TABLE_CONFIG, START_GAIN_TABLE_CLOCK | + RECEIVER_SELECT(dest)); /* Start Gain Table Clock */ + + /* TX QUAD Calibration */ + if (phy->pdata->split_gt) + lpf_tia_mask = 0x20; + else + lpf_tia_mask = 0x3F; + + phy->tx_quad_lpf_tia_match = -EINVAL; + + for (i = 0; i < index_max; i++) { + ad9361_spi_write(spi, REG_GAIN_TABLE_ADDRESS, i); /* Gain Table Index */ + ad9361_spi_write(spi, REG_GAIN_TABLE_WRITE_DATA1, + tab[i][0] | lna); /* Ext LNA, Int LNA, & Mixer Gain Word */ + ad9361_spi_write(spi, REG_GAIN_TABLE_WRITE_DATA2, + tab[i][1]); /* TIA & LPF Word */ + ad9361_spi_write(spi, REG_GAIN_TABLE_WRITE_DATA3, + tab[i][2]); /* DC Cal bit & Dig Gain Word */ + ad9361_spi_write(spi, REG_GAIN_TABLE_CONFIG, + START_GAIN_TABLE_CLOCK | + WRITE_GAIN_TABLE | + RECEIVER_SELECT(dest)); /* Gain Table Index */ + ad9361_spi_write(spi, REG_GAIN_TABLE_READ_DATA1, + 0); /* Dummy Write to delay 3 ADCCLK/16 cycles */ + ad9361_spi_write(spi, REG_GAIN_TABLE_READ_DATA1, + 0); /* Dummy Write to delay ~1u */ + + if ((tab[i][1] & lpf_tia_mask) == 0x20) + phy->tx_quad_lpf_tia_match = i; + + } + + ad9361_spi_write(spi, REG_GAIN_TABLE_CONFIG, START_GAIN_TABLE_CLOCK | + RECEIVER_SELECT(dest)); /* Clear Write Bit */ + ad9361_spi_write(spi, REG_GAIN_TABLE_READ_DATA1, + 0); /* Dummy Write to delay ~1u */ + ad9361_spi_write(spi, REG_GAIN_TABLE_READ_DATA1, + 0); /* Dummy Write to delay ~1u */ + ad9361_spi_write(spi, REG_GAIN_TABLE_CONFIG, 0); /* Stop Gain Table Clock */ + + phy->current_table = band; + + ret = find_table_index(phy, rx1_gain); + if (ret < 0) + ret = phy->gt_info[band].max_index - 1; + + ad9361_spi_writef(spi, REG_RX1_MANUAL_LMT_FULL_GAIN, + RX_FULL_TBL_IDX_MASK, ret); /* Rx1 Full/LMT Gain Index */ + + ret = find_table_index(phy, rx2_gain); + if (ret < 0) + ret = phy->gt_info[band].max_index - 1; + + ad9361_spi_write(spi, REG_RX2_MANUAL_LMT_FULL_GAIN, + ret); /* Rx2 Full/LMT Gain Index */ + + return 0; +} + +/** + * Setup the external low-noise amplifier (LNA). + * @param phy The AD9361 state structure. + * @param ctrl Pointer to eLNA control structure. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_setup_ext_lna(struct ad9361_rf_phy *phy, + struct elna_control *ctrl) +{ + ad9361_spi_writef(phy->spi, REG_EXTERNAL_LNA_CTRL, EXTERNAL_LNA1_CTRL, + ctrl->elna_1_control_en); + + ad9361_spi_writef(phy->spi, REG_EXTERNAL_LNA_CTRL, EXTERNAL_LNA2_CTRL, + ctrl->elna_2_control_en); + + ad9361_spi_write(phy->spi, REG_EXT_LNA_HIGH_GAIN, + EXT_LNA_HIGH_GAIN(ctrl->gain_mdB / 500)); + + return ad9361_spi_write(phy->spi, REG_EXT_LNA_LOW_GAIN, + EXT_LNA_LOW_GAIN(ctrl->bypass_loss_mdB / 500)); +} + +/** + * Set the clock output mode. + * @param phy The AD9361 state structure. + * @param mode The clock output mode []. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_clkout_control(struct ad9361_rf_phy *phy, + enum ad9361_clkout mode) +{ + if (mode == CLKOUT_DISABLE) + return ad9361_spi_writef(phy->spi, REG_BBPLL, CLKOUT_ENABLE, 0); + + return ad9361_spi_writef(phy->spi, REG_BBPLL, + CLKOUT_ENABLE | CLKOUT_SELECT(~0), + ((mode - 1) << 1) | 0x1); +} + +/** + * Load the Gm Sub Table. + * @param phy The AD9361 state structure. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_load_mixer_gm_subtable(struct ad9361_rf_phy *phy) +{ + int32_t i, addr; + dev_dbg(&phy->spi->dev, "%s", __func__); + + ad9361_spi_write(phy->spi, REG_GM_SUB_TABLE_CONFIG, + START_GM_SUB_TABLE_CLOCK); /* Start Clock */ + + for (i = 0, addr = ARRAY_SIZE(gm_st_ctrl); i < (int64_t)ARRAY_SIZE(gm_st_ctrl); + i++) { + ad9361_spi_write(phy->spi, REG_GM_SUB_TABLE_ADDRESS, + --addr); /* Gain Table Index */ + ad9361_spi_write(phy->spi, REG_GM_SUB_TABLE_BIAS_WRITE, 0); /* Bias */ + ad9361_spi_write(phy->spi, REG_GM_SUB_TABLE_GAIN_WRITE, + gm_st_gain[i]); /* Gain */ + ad9361_spi_write(phy->spi, REG_GM_SUB_TABLE_CTRL_WRITE, + gm_st_ctrl[i]); /* Control */ + ad9361_spi_write(phy->spi, REG_GM_SUB_TABLE_CONFIG, + WRITE_GM_SUB_TABLE | START_GM_SUB_TABLE_CLOCK); /* Write Words */ + ad9361_spi_write(phy->spi, REG_GM_SUB_TABLE_GAIN_READ, 0); /* Dummy Delay */ + ad9361_spi_write(phy->spi, REG_GM_SUB_TABLE_GAIN_READ, 0); /* Dummy Delay */ + } + + ad9361_spi_write(phy->spi, REG_GM_SUB_TABLE_CONFIG, + START_GM_SUB_TABLE_CLOCK); /* Clear Write */ + ad9361_spi_write(phy->spi, REG_GM_SUB_TABLE_GAIN_READ, 0); /* Dummy Delay */ + ad9361_spi_write(phy->spi, REG_GM_SUB_TABLE_GAIN_READ, 0); /* Dummy Delay */ + ad9361_spi_write(phy->spi, REG_GM_SUB_TABLE_CONFIG, 0); /* Stop Clock */ + + return 0; +} + +/** + * Set the attenuation for the selected TX channels. + * @param phy The AD9361 state structure. + * @param atten_mdb Attenuation value [mdB]. + * @param tx1 Set true, the attenuation of the TX1 will be affected. + * @param tx2 Set true, the attenuation of the TX2 will be affected. + * @param immed Set true, an immediate update will take place. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_set_tx_atten(struct ad9361_rf_phy *phy, uint32_t atten_mdb, + bool tx1, bool tx2, bool immed) +{ + uint8_t buf[2]; + int32_t ret = 0; + + dev_dbg(&phy->spi->dev, "%s : attenuation %"PRIu32" mdB tx1=%d tx2=%d", + __func__, atten_mdb, tx1, tx2); + + if (atten_mdb > MAX_TX_ATTENUATION_DB) /* 89.75 dB */ + return -EINVAL; + + atten_mdb /= 250; /* Scale to 0.25dB / LSB */ + + buf[0] = atten_mdb >> 8; + buf[1] = atten_mdb & 0xFF; + + ad9361_spi_writef(phy->spi, REG_TX2_DIG_ATTEN, + IMMEDIATELY_UPDATE_TPC_ATTEN, 0); + + if (tx1) + ret = ad9361_spi_writem(phy->spi, REG_TX1_ATTEN_1, buf, 2); + + if (tx2) + ret = ad9361_spi_writem(phy->spi, REG_TX2_ATTEN_1, buf, 2); + + if (immed) + ad9361_spi_writef(phy->spi, REG_TX2_DIG_ATTEN, + IMMEDIATELY_UPDATE_TPC_ATTEN, 1); + + return ret; +} + +/** + * Get the attenuation for the selected TX channel. + * @param phy The AD9361 state structure. + * @param tx_num The selected channel [1, 2]. + * @return The attenuation value [mdB] or negative error code in case of failure. + */ +int32_t ad9361_get_tx_atten(struct ad9361_rf_phy *phy, uint32_t tx_num) +{ + uint8_t buf[2]; + int32_t ret = 0; + uint32_t code; + + ret = ad9361_spi_readm(phy->spi, (tx_num == 1) ? + REG_TX1_ATTEN_1 : REG_TX2_ATTEN_1, buf, 2); + + if (ret < 0) + return ret; + + code = (buf[0] << 8) | buf[1]; + + code *= 250; + + return code; +} + +/** + * Mute TX. + * @param phy The AD9361 state structure. + * @param state The state - 0 mute; 1 - unmute. + * @return 0 in case of success + */ +int32_t ad9361_tx_mute(struct ad9361_rf_phy *phy, uint32_t state) +{ + int32_t ret; + + if (state) { + phy->tx1_atten_cached = ad9361_get_tx_atten(phy, 1); + phy->tx2_atten_cached = ad9361_get_tx_atten(phy, 2); + + return ad9361_set_tx_atten(phy, 89750, true, true, true); + } else { + if (phy->tx1_atten_cached == phy->tx2_atten_cached) + return ad9361_set_tx_atten(phy, phy->tx1_atten_cached, + true, true, true); + + ret = ad9361_set_tx_atten(phy, phy->tx1_atten_cached, + true, false, true); + ret |= ad9361_set_tx_atten(phy, phy->tx2_atten_cached, + false, true, true); + + return ret; + } +} + +/** + * Choose the right RF VCO table index for the selected frequency. + * @param freq The frequency value [Hz]. + * @return The index from the RF VCO table. + */ +static uint32_t ad9361_rfvco_tableindex(uint32_t freq) +{ + if (freq < 50000000UL) + return LUT_FTDD_40; + + if (freq <= 70000000UL) + return LUT_FTDD_60; + + return LUT_FTDD_80; +} + +/** + * Initialize the RFPLL VCO. + * @param phy The AD9361 state structure. + * @param tx Set true for TX_RFPLL. + * @param vco_freq The VCO frequency [Hz]. + * @param ref_clk The reference clock frequency [Hz]. + * @return 0 in case of success + */ +static int32_t ad9361_rfpll_vco_init(struct ad9361_rf_phy *phy, + bool tx, uint64_t vco_freq, + uint32_t ref_clk) +{ + struct spi_desc *spi = phy->spi; + const struct SynthLUT(*tab); + int32_t i = 0; + uint32_t range, offs = 0; + + range = ad9361_rfvco_tableindex(ref_clk); + + dev_dbg(&phy->spi->dev, + "%s : vco_freq %"PRIu64" : ref_clk %"PRIu32" : range %"PRIu32, + __func__, vco_freq, ref_clk, range); + + do_div(&vco_freq, 1000000UL); /* vco_freq in MHz */ + + if ((phy->pdata->fdd && !phy->pdata->fdd_independent_mode) + && (phy->current_tx_lo_freq != phy->current_rx_lo_freq)) { + tab = &SynthLUT_FDD[range][0]; + if (tx) + phy->current_tx_use_tdd_table = false; + else + phy->current_rx_use_tdd_table = false; + } else { + if (have_tdd_tables) { + tab = &SynthLUT_TDD[range][0]; + if (tx) + phy->current_tx_use_tdd_table = true; + else + phy->current_rx_use_tdd_table = true; + } + } + + if (tx) + offs = REG_TX_VCO_OUTPUT - REG_RX_VCO_OUTPUT; + + while (i < SYNTH_LUT_SIZE && tab[i].VCO_MHz > vco_freq) + i++; + + dev_dbg(&phy->spi->dev, "%s : freq %d MHz : index %"PRId32, + __func__, tab[i].VCO_MHz, i); + + ad9361_spi_write(spi, REG_RX_VCO_OUTPUT + offs, + VCO_OUTPUT_LEVEL(tab[i].VCO_Output_Level) | + PORB_VCO_LOGIC); + ad9361_spi_writef(spi, REG_RX_ALC_VARACTOR + offs, + VCO_VARACTOR(~0), tab[i].VCO_Varactor); + ad9361_spi_write(spi, REG_RX_VCO_BIAS_1 + offs, + VCO_BIAS_REF(tab[i].VCO_Bias_Ref) | + VCO_BIAS_TCF(tab[i].VCO_Bias_Tcf)); + + ad9361_spi_write(spi, REG_RX_FORCE_VCO_TUNE_1 + offs, + VCO_CAL_OFFSET(tab[i].VCO_Cal_Offset)); + ad9361_spi_write(spi, REG_RX_VCO_VARACTOR_CTRL_1 + offs, + VCO_VARACTOR_REFERENCE( + tab[i].VCO_Varactor_Reference)); + + ad9361_spi_write(spi, REG_RX_VCO_CAL_REF + offs, VCO_CAL_REF_TCF(0)); + + ad9361_spi_write(spi, REG_RX_VCO_VARACTOR_CTRL_0 + offs, + VCO_VARACTOR_OFFSET(0) | + VCO_VARACTOR_REFERENCE_TCF(7)); + + ad9361_spi_writef(spi, REG_RX_CP_CURRENT + offs, CHARGE_PUMP_CURRENT(~0), + tab[i].Charge_Pump_Current); + ad9361_spi_write(spi, REG_RX_LOOP_FILTER_1 + offs, + LOOP_FILTER_C2(tab[i].LF_C2) | + LOOP_FILTER_C1(tab[i].LF_C1)); + ad9361_spi_write(spi, REG_RX_LOOP_FILTER_2 + offs, + LOOP_FILTER_R1(tab[i].LF_R1) | + LOOP_FILTER_C3(tab[i].LF_C3)); + ad9361_spi_write(spi, REG_RX_LOOP_FILTER_3 + offs, + LOOP_FILTER_R3(tab[i].LF_R3)); + + return 0; +} + +/** + * Get the current gain in Split Gain Table Mode + * @param phy The AD9361 state structure. + * @param idx_reg Register base address for the selected receiver + * @param rx_gain A rf_rx_gain struct to store the RF gain. + * @return 0 in case of success, + */ +static int32_t ad9361_get_split_table_gain(struct ad9361_rf_phy *phy, + uint32_t idx_reg, + struct rf_rx_gain *rx_gain) +{ + struct spi_desc *spi = phy->spi; + uint32_t val, tbl_addr; + int32_t rc = 0; + + + rx_gain->fgt_lmt_index = ad9361_spi_readf(spi, idx_reg, + FULL_TABLE_GAIN_INDEX(~0)); + tbl_addr = ad9361_spi_read(spi, REG_GAIN_TABLE_ADDRESS); + + ad9361_spi_write(spi, REG_GAIN_TABLE_ADDRESS, rx_gain->fgt_lmt_index); + + val = ad9361_spi_read(spi, REG_GAIN_TABLE_READ_DATA1); + rx_gain->lna_index = TO_LNA_GAIN(val); + rx_gain->mixer_index = TO_MIXER_GM_GAIN(val); + + rx_gain->tia_index = ad9361_spi_readf(spi, REG_GAIN_TABLE_READ_DATA2, TIA_GAIN); + + rx_gain->lmt_gain = lna_table[ad9361_gt(phy) - RXGAIN_TBLS_END][rx_gain->lna_index] + + mixer_table[ad9361_gt(phy) - RXGAIN_TBLS_END][rx_gain->mixer_index] + + tia_table[rx_gain->tia_index]; + + ad9361_spi_write(spi, REG_GAIN_TABLE_ADDRESS, tbl_addr); + + /* Read LPF Index */ + rx_gain->lpf_gain = ad9361_spi_readf(spi, idx_reg + 1, LPF_GAIN_RX(~0)); + + /* Read Digital Gain */ + rx_gain->digital_gain = ad9361_spi_readf(spi, idx_reg + 2, + DIGITAL_GAIN_RX(~0)); + + rx_gain->gain_db = rx_gain->lmt_gain + rx_gain->lpf_gain + + rx_gain->digital_gain; + return rc; +} + +/** + * Get the current gain in Full Gain Table Mode + * @param phy The AD9361 state structure. + * @param idx_reg Register base address for the selected receiver + * @param rx_gain A rf_rx_gain struct to store the RF gain. + * @return 0 in case of success + */ +static int32_t ad9361_get_full_table_gain(struct ad9361_rf_phy *phy, + uint32_t idx_reg, + struct rf_rx_gain *rx_gain) +{ + struct spi_desc *spi = phy->spi; + uint32_t val; + + rx_gain->fgt_lmt_index = val = ad9361_spi_readf(spi, idx_reg, + FULL_TABLE_GAIN_INDEX(~0)); + /* Read Digital Gain */ + rx_gain->digital_gain = ad9361_spi_readf(spi, idx_reg + 2, + DIGITAL_GAIN_RX(~0)); + + rx_gain->gain_db = phy->gt_info[ad9361_gt(phy)].abs_gain_tbl[val]; + + return 0; +} + +/** + * Get current RX gain for the selected channel. + * @param phy The AD9361 state structure. + * @param rx_id The desired channel number (0, 1). + * @param rx_gain A rf_rx_gain struct to store the RF gain. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_rx_gain(struct ad9361_rf_phy *phy, + uint32_t rx_id, struct rf_rx_gain *rx_gain) +{ + struct spi_desc *spi = phy->spi; + uint32_t val, idx_reg; + uint8_t gain_ctl_shift, rx_enable_mask; + uint8_t fast_atk_shift; + int32_t rc = 0; + + if (rx_id == 1) { + gain_ctl_shift = RX1_GAIN_CTRL_SHIFT; + idx_reg = REG_GAIN_RX1; + rx_enable_mask = RX_CHANNEL_ENABLE(RX_1); + fast_atk_shift = RX1_FAST_ATK_SHIFT; + + } else if (rx_id == 2) { + gain_ctl_shift = RX2_GAIN_CTRL_SHIFT; + idx_reg = REG_GAIN_RX2; + rx_enable_mask = RX_CHANNEL_ENABLE(RX_2); + fast_atk_shift = RX2_FAST_ATK_SHIFT; + } else { + dev_err(dev, "Unknown Rx path %"PRIu32, rx_id); + rc = -EINVAL; + goto out; + } + + val = ad9361_spi_readf(spi, REG_RX_ENABLE_FILTER_CTRL, rx_enable_mask); + + if (!val) { + dev_dbg(dev, "Rx%"PRIu32" is not enabled", rx_gain->ant); + rc = -EAGAIN; + goto out; + } + + val = ad9361_spi_read(spi, REG_AGC_CONFIG_1); + + val = (val >> gain_ctl_shift) & RX_GAIN_CTL_MASK; + + if (val == RX_GAIN_CTL_AGC_FAST_ATK) { + /* In fast attack mode check whether Fast attack state machine + * has locked gain, if not then we can not read gain. + */ + val = ad9361_spi_read(spi, REG_FAST_ATTACK_STATE); + val = (val >> fast_atk_shift) & FAST_ATK_MASK; + if (val != FAST_ATK_GAIN_LOCKED) { + dev_warn(dev, "Failed to read gain, state m/c at %"PRIx32, + val); + rc = -EAGAIN; + goto out; + } + } + + if (has_split_gt && phy->pdata->split_gt) + rc = ad9361_get_split_table_gain(phy, idx_reg, rx_gain); + else + rc = ad9361_get_full_table_gain(phy, idx_reg, rx_gain); + +out: + return rc; +} + +/** + * Get Enable State Machine (ENSM) state. + * @param phy The AD9361 state structure. + * @return The state. + */ +uint8_t ad9361_ensm_get_state(struct ad9361_rf_phy *phy) +{ + return ad9361_spi_readf(phy->spi, REG_STATE, ENSM_STATE(~0)); +} + +/** + * Force Enable State Machine (ENSM) to the desired state (internally used only). + * @param phy The AD9361 state structure. + * @param ensm_state The ENSM state [ENSM_STATE_SLEEP_WAIT, ENSM_STATE_ALERT, + * ENSM_STATE_TX, ENSM_STATE_TX_FLUSH, ENSM_STATE_RX, + * ENSM_STATE_RX_FLUSH, ENSM_STATE_FDD, ENSM_STATE_FDD_FLUSH]. + * @return None. + */ +void ad9361_ensm_force_state(struct ad9361_rf_phy *phy, uint8_t ensm_state) +{ + struct spi_desc *spi = phy->spi; + uint8_t dev_ensm_state; + int32_t rc, timeout = 10; + uint32_t val; + + dev_ensm_state = ad9361_spi_readf(spi, REG_STATE, ENSM_STATE(~0)); + + phy->prev_ensm_state = dev_ensm_state; + + if (dev_ensm_state == ensm_state) { + dev_dbg(dev, "Nothing to do, device is already in %d state", + ensm_state); + goto out; + } + + dev_dbg(dev, "Device is in %x state, forcing to %x", dev_ensm_state, + ensm_state); + + val = ad9361_spi_read(spi, REG_ENSM_CONFIG_1); + + /* Enable control through SPI writes, and take out from + * Alert + */ + if (val & ENABLE_ENSM_PIN_CTRL) { + val &= ~ENABLE_ENSM_PIN_CTRL; + phy->ensm_pin_ctl_en = true; + } else { + phy->ensm_pin_ctl_en = false; + } + + if (dev_ensm_state) + val &= ~(TO_ALERT); + + switch (ensm_state) { + + case ENSM_STATE_TX: + case ENSM_STATE_FDD: + val |= FORCE_TX_ON; + break; + case ENSM_STATE_RX: + val |= FORCE_RX_ON; + break; + case ENSM_STATE_ALERT: + val &= ~(FORCE_TX_ON | FORCE_RX_ON); + val |= TO_ALERT | FORCE_ALERT_STATE; + break; + default: + dev_err(dev, "No handling for forcing %d ensm state", + ensm_state); + goto out; + } + + ad9361_spi_write(spi, REG_ENSM_CONFIG_1, TO_ALERT | FORCE_ALERT_STATE); + + rc = ad9361_spi_write(spi, REG_ENSM_CONFIG_1, val); + if (rc) { + dev_err(dev, "Failed to write ENSM_CONFIG_1\n"); + goto out; + } + + while (ad9361_ensm_get_state(phy) != ensm_state && --timeout) { + mdelay(1); + } + + if (timeout == 0) + dev_err(dev, "Failed to restore state"); + +out: + return; + +} + +/** + * Restore an Enable State Machine (ENSM) state. + * @param phy The AD9361 state structure. + * @param ensm_state The state. + * @return None. + */ +void ad9361_ensm_restore_state(struct ad9361_rf_phy *phy, uint8_t ensm_state) +{ + struct spi_desc *spi = phy->spi; + int32_t rc; + uint32_t val; + + val = ad9361_spi_read(spi, REG_ENSM_CONFIG_1); + + /* We are restoring state only, so clear State bits first + * which might have set while forcing a particular state + */ + val &= ~(FORCE_TX_ON | FORCE_RX_ON | FORCE_ALERT_STATE); + val |= TO_ALERT; + + switch (ensm_state) { + case ENSM_STATE_TX: + case ENSM_STATE_FDD: + val |= FORCE_TX_ON; + break; + case ENSM_STATE_RX: + val |= FORCE_RX_ON; + break; + case ENSM_STATE_ALERT: + val |= TO_ALERT; + break; + case ENSM_STATE_INVALID: + dev_dbg(dev, "No need to restore, ENSM state wasn't saved"); + return; + default: + dev_dbg(dev, "Could not restore to %d ENSM state", + ensm_state); + return; + } + + ad9361_spi_write(spi, REG_ENSM_CONFIG_1, TO_ALERT | FORCE_ALERT_STATE); + + rc = ad9361_spi_write(spi, REG_ENSM_CONFIG_1, val); + if (rc) { + dev_err(dev, "Failed to write ENSM_CONFIG_1"); + return; + } + + if (phy->ensm_pin_ctl_en) { + val |= ENABLE_ENSM_PIN_CTRL; + rc = ad9361_spi_write(spi, REG_ENSM_CONFIG_1, val); + if (rc) + dev_err(dev, "Failed to write ENSM_CONFIG_1"); + } +} + +/** + * Restore the previous Enable State Machine (ENSM) state. + * @param phy The AD9361 state structure. + * @return None. + */ +void ad9361_ensm_restore_prev_state(struct ad9361_rf_phy *phy) +{ + return ad9361_ensm_restore_state(phy, phy->prev_ensm_state); +} + +/** + * Set gain in Split Gain Table Mode (used only in Manual Gain Control Mode). + * @param phy The AD9361 state structure. + * @param idx_reg Register base address for the selected receiver + * @param rx_gain The rf_rx_gain struct containing the RF gain. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t set_split_table_gain(struct ad9361_rf_phy *phy, uint32_t idx_reg, + struct rf_rx_gain *rx_gain) +{ + struct spi_desc *spi = phy->spi; + int32_t rc = 0; + + if ((rx_gain->fgt_lmt_index > MAX_LMT_INDEX) || + (rx_gain->lpf_gain > MAX_LPF_GAIN) || + (rx_gain->digital_gain > MAX_DIG_GAIN)) { + dev_err(dev, "LMT_INDEX missing or greater than max value %d", + MAX_LMT_INDEX); + dev_err(dev, "LPF_GAIN missing or greater than max value %d", + MAX_LPF_GAIN); + dev_err(dev, "DIGITAL_GAIN cannot be more than %d", + MAX_DIG_GAIN); + rc = -EINVAL; + goto out; + } + + rc = find_table_index(phy, rx_gain->gain_db); + if (rc < 0) { + dev_err(dev, "Invalid gain %"PRId32", supported range [%d - %d]\n", + rx_gain->gain_db, phy->gt_info[ad9361_gt(phy)]. + abs_gain_tbl[0], + phy->gt_info[ad9361_gt(phy)].abs_gain_tbl + [phy->gt_info[ad9361_gt(phy)].max_index - 1]); + goto out; + } + + rx_gain->fgt_lmt_index = rc; + + rc = ad9361_spi_writef(spi, idx_reg, RX_FULL_TBL_IDX_MASK, + rx_gain->fgt_lmt_index); + if (rc < 0) + goto out; + rc = ad9361_spi_writef(spi, idx_reg + 1, RX_LPF_IDX_MASK, rx_gain->lpf_gain); + if (rc < 0) + goto out; + if (phy->pdata->gain_ctrl.dig_gain_en) { + rc = ad9361_spi_writef(spi, idx_reg + 2, RX_DIGITAL_IDX_MASK, + rx_gain->digital_gain); + } else if (rx_gain->digital_gain > 0) { + dev_err(dev, "Digital gain is disabled and cannot be set"); + } +out: + return rc; +} + +/** + * Set gain in Full Gain Table Mode (used only in Manual Gain Control Mode). + * @param phy The AD9361 state structure. + * @param idx_reg Register base address for the selected receiver + * @param rx_gain The rf_rx_gain struct containing the RF gain. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t set_full_table_gain(struct ad9361_rf_phy *phy, uint32_t idx_reg, + struct rf_rx_gain *rx_gain) +{ + struct spi_desc *spi = phy->spi; + int rc = 0; + + if (rx_gain->fgt_lmt_index != ((uint32_t)~0) || + rx_gain->lpf_gain != ((uint32_t)~0) || + rx_gain->digital_gain > 0) + dev_dbg(dev, + "Ignoring lmt/lpf/digital gains in Single Table mode"); + + rc = find_table_index(phy, rx_gain->gain_db); + if (rc < 0) { + dev_err(dev, "Invalid gain %"PRId32", supported range [%d - %d]\n", + rx_gain->gain_db, phy->gt_info[ad9361_gt(phy)]. + abs_gain_tbl[0], + phy->gt_info[ad9361_gt(phy)].abs_gain_tbl + [phy->gt_info[ad9361_gt(phy)].max_index - 1]); + goto out; + } + + rc = ad9361_spi_writef(spi, idx_reg, RX_FULL_TBL_IDX_MASK, rc); +out: + return rc; +} + +/** + * Set the RX gain for the selected channel. + * @param phy The AD9361 state structure. + * @param rx_id The desired channel number (0, 1). + * @param rx_gain The rf_rx_gain struct containing the RF gain. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_set_rx_gain(struct ad9361_rf_phy *phy, + uint32_t rx_id, struct rf_rx_gain *rx_gain) +{ + struct spi_desc *spi = phy->spi; + uint32_t val, idx_reg; + uint8_t gain_ctl_shift; + int32_t rc = 0; + + if (rx_id == 1) { + gain_ctl_shift = RX1_GAIN_CTRL_SHIFT; + idx_reg = REG_RX1_MANUAL_LMT_FULL_GAIN; + + } else if (rx_id == 2) { + gain_ctl_shift = RX2_GAIN_CTRL_SHIFT; + idx_reg = REG_RX2_MANUAL_LMT_FULL_GAIN; + } else { + dev_err(dev, "Unknown Rx path %"PRIu32, rx_id); + rc = -EINVAL; + goto out; + + } + + val = ad9361_spi_read(spi, REG_AGC_CONFIG_1); + val = (val >> gain_ctl_shift) & RX_GAIN_CTL_MASK; + + if (val != RX_GAIN_CTL_MGC) { + dev_dbg(dev, "Rx gain can be set in MGC mode only"); + rc = -EOPNOTSUPP; + goto out; + } + + if (has_split_gt && phy->pdata->split_gt) + rc = set_split_table_gain(phy, idx_reg, rx_gain); + else + rc = set_full_table_gain(phy, idx_reg, rx_gain); + + if (rc) { + dev_err(dev, "Unable to write gain tbl idx reg: %"PRIu32, idx_reg); + goto out; + } + +out: + return rc; + +} + +/** + * Update the Gain Control. + * @param phy The AD9361 state structure. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_gc_update(struct ad9361_rf_phy *phy) +{ + struct spi_desc *spi = phy->spi; + uint32_t clkrf; + uint32_t reg, delay_lna, settling_delay, dec_pow_meas_dur; + int32_t ret; + uint32_t fir_div; + + clkrf = clk_get_rate(phy, phy->ref_clk_scale[CLKRF_CLK]); + delay_lna = phy->pdata->elna_ctrl.settling_delay_ns; + + /* + * AGC Attack Delay (us)=ceiling((((0.2+Delay_LNA)*ClkRF+14))/(2*ClkRF))+1 + * ClkRF in MHz, delay in us + */ + + reg = (200 + delay_lna) / 2 + (14000000UL / (clkrf / 500U)); + reg = DIV_ROUND_UP(reg, 1000UL) + + phy->pdata->gain_ctrl.agc_attack_delay_extra_margin_us; + reg = clamp_t(uint8_t, reg, 0U, 31U); + ret = ad9361_spi_writef(spi, REG_AGC_ATTACK_DELAY, + AGC_ATTACK_DELAY(~0), reg); + + /* + * Peak Overload Wait Time (ClkRF cycles)=ceiling((0.1+Delay_LNA) *clkRF+1) + */ + + reg = (delay_lna + 100UL) * (clkrf / 1000UL); + reg = DIV_ROUND_UP(reg, 1000000UL) + 1; + reg = clamp_t(uint8_t, reg, 0U, 31U); + ret |= ad9361_spi_writef(spi, REG_PEAK_WAIT_TIME, + PEAK_OVERLOAD_WAIT_TIME(~0), reg); + + /* + * Settling Delay in 0x111. Applies to all gain control modes: + * 0x111[D4:D0]= ceiling(((0.2+Delay_LNA)*clkRF + dodebug = false;+14)/2) + */ + + reg = (delay_lna + 200UL) * (clkrf / 2000UL); + reg = DIV_ROUND_UP(reg, 1000000UL) + 7; + reg = settling_delay = clamp_t(uint8_t, reg, 0U, 31U); + ret |= ad9361_spi_writef(spi, REG_FAST_CONFIG_2_SETTLING_DELAY, + SETTLING_DELAY(~0), reg); + + /* + * Gain Update Counter [15:0]= round((((time*ClkRF-0x111[D4:D0]*2)-2))/2) + */ + reg = phy->pdata->gain_ctrl.gain_update_interval_us * (clkrf / 1000UL) - + settling_delay * 2000UL - 2000UL; + + reg = DIV_ROUND_CLOSEST(reg, 2000UL); + reg = clamp_t(uint32_t, reg, 0U, 131071UL); + + if (phy->agc_mode[0] == RF_GAIN_FASTATTACK_AGC || + phy->agc_mode[1] == RF_GAIN_FASTATTACK_AGC) { + dec_pow_meas_dur = + phy->pdata->gain_ctrl.f_agc_dec_pow_measuremnt_duration; + } else { + fir_div = DIV_ROUND_CLOSEST(clkrf, + clk_get_rate(phy, phy->ref_clk_scale[RX_SAMPL_CLK])); + dec_pow_meas_dur = phy->pdata->gain_ctrl.dec_pow_measuremnt_duration; + + if (((reg * 2 / fir_div) / dec_pow_meas_dur) < 2) { + dec_pow_meas_dur = reg / fir_div; + } + } + + /* Power Measurement Duration */ + ad9361_spi_writef(spi, REG_DEC_POWER_MEASURE_DURATION_0, + DEC_POWER_MEASUREMENT_DURATION(~0), + ilog2(dec_pow_meas_dur / 16)); + + + ret |= ad9361_spi_writef(spi, REG_DIGITAL_SAT_COUNTER, + DOUBLE_GAIN_COUNTER, reg > 65535); + + if (reg > 65535) + reg /= 2; + + ret |= ad9361_spi_write(spi, REG_GAIN_UPDATE_COUNTER1, reg & 0xFF); + ret |= ad9361_spi_write(spi, REG_GAIN_UPDATE_COUNTER2, reg >> 8); + + /* + * Fast AGC State Wait Time - Energy Detect Count + */ + + reg = DIV_ROUND_CLOSEST(phy->pdata->gain_ctrl.f_agc_state_wait_time_ns * + (clkrf / 1000UL), 1000000UL); + reg = clamp_t(uint32_t, reg, 0U, 31U); + ret |= ad9361_spi_writef(spi, REG_FAST_ENERGY_DETECT_COUNT, + ENERGY_DETECT_COUNT(~0), reg); + + return ret; +} + +/** + * Set the gain control mode. + * @param phy The AD9361 state structure. + * @param gain_ctrl A rf_gain_ctrl struct that contains the the desired + * channel information and the gain control mode. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_set_gain_ctrl_mode(struct ad9361_rf_phy *phy, + struct rf_gain_ctrl *gain_ctrl) +{ + struct spi_desc *spi = phy->spi; + int32_t rc = 0; + uint32_t gain_ctl_shift, mode; + uint8_t val; + + rc = ad9361_spi_readm(spi, REG_AGC_CONFIG_1, &val, 1); + if (rc) { + dev_err(dev, "Unable to read AGC config1 register: %x", + REG_AGC_CONFIG_1); + goto out; + } + + switch (gain_ctrl->mode) { + case RF_GAIN_MGC: + mode = RX_GAIN_CTL_MGC; + break; + case RF_GAIN_FASTATTACK_AGC: + mode = RX_GAIN_CTL_AGC_FAST_ATK; + break; + case RF_GAIN_SLOWATTACK_AGC: + mode = RX_GAIN_CTL_AGC_SLOW_ATK; + break; + case RF_GAIN_HYBRID_AGC: + mode = RX_GAIN_CTL_AGC_SLOW_ATK_HYBD; + break; + default: + rc = -EINVAL; + goto out; + } + + if (gain_ctrl->ant == 1) { + gain_ctl_shift = RX1_GAIN_CTRL_SHIFT; + } else if (gain_ctrl->ant == 2) { + gain_ctl_shift = RX2_GAIN_CTRL_SHIFT; + } else { + dev_err(dev, "Unknown Rx path %"PRIu32, gain_ctrl->ant); + rc = -EINVAL; + goto out; + } + + rc = ad9361_en_dis_rx(phy, gain_ctrl->ant, RX_DISABLE); + if (rc) { + dev_err(dev, "Unable to disable rx%"PRIu32, gain_ctrl->ant); + goto out; + } + + val &= ~(RX_GAIN_CTL_MASK << gain_ctl_shift); + val |= mode << gain_ctl_shift; + if (mode == RX_GAIN_CTL_AGC_SLOW_ATK_HYBD) + val |= SLOW_ATTACK_HYBRID_MODE; + else + val &= ~SLOW_ATTACK_HYBRID_MODE; + + rc = ad9361_spi_write(spi, REG_AGC_CONFIG_1, val); + if (rc) { + dev_err(dev, "Unable to write AGC config1 register: %x", + REG_AGC_CONFIG_1); + goto out; + } + + ad9361_en_dis_rx(phy, gain_ctrl->ant, RX_ENABLE); + rc = ad9361_gc_update(phy); +out: + return rc; +} + +/** + * Get the RSSI. + * @param phy The AD9361 state structure. + * @param rssi A rf_rssi struct to store the RSSI. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_read_rssi(struct ad9361_rf_phy *phy, struct rf_rssi *rssi) +{ + struct spi_desc *spi = phy->spi; + uint8_t reg_val_buf[6]; + int32_t rc; + + rc = ad9361_spi_readm(spi, REG_PREAMBLE_LSB, + reg_val_buf, ARRAY_SIZE(reg_val_buf)); + if (rssi->ant == 1) { + rssi->symbol = RSSI_RESOLUTION * + ((reg_val_buf[5] << RSSI_LSB_SHIFT) + + (reg_val_buf[1] & RSSI_LSB_MASK1)); + rssi->preamble = RSSI_RESOLUTION * + ((reg_val_buf[4] << RSSI_LSB_SHIFT) + + (reg_val_buf[0] & RSSI_LSB_MASK1)); + } else if (rssi->ant == 2) { + rssi->symbol = RSSI_RESOLUTION * + ((reg_val_buf[3] << RSSI_LSB_SHIFT) + + ((reg_val_buf[1] & RSSI_LSB_MASK2) >> 1)); + rssi->preamble = RSSI_RESOLUTION * + ((reg_val_buf[2] << RSSI_LSB_SHIFT) + + ((reg_val_buf[0] & RSSI_LSB_MASK2) >> 1)); + } else + rc = -EFAULT; + + rssi->multiplier = RSSI_MULTIPLIER; + + return rc; +} + +/** + * Setup the RX ADC. + * @param phy The AD9361 state structure. + * @param bbpll_freq The BBPLL frequency [Hz]. + * @param adc_sampl_freq_Hz The ADC sampling frequency [Hz]. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_rx_adc_setup(struct ad9361_rf_phy *phy, + uint32_t bbpll_freq, + uint32_t adc_sampl_freq_Hz) +{ + + uint32_t scale_snr_1e3, maxsnr, sqrt_inv_rc_tconst_1e3, tmp_1e3, + scaled_adc_clk_1e6, inv_scaled_adc_clk_1e3, sqrt_term_1e3, + min_sqrt_term_1e3, bb_bw_Hz; + uint64_t tmp, invrc_tconst_1e6; + uint8_t data[40]; + uint32_t i; + int32_t ret; + + uint8_t c3_msb = ad9361_spi_read(phy->spi, REG_RX_BBF_C3_MSB); + uint8_t c3_lsb = ad9361_spi_read(phy->spi, REG_RX_BBF_C3_LSB); + uint8_t r2346 = ad9361_spi_read(phy->spi, REG_RX_BBF_R2346); + + /* + * BBBW = (BBPLL / RxTuneDiv) * ln(2) / (1.4 * 2PI ) + * We assume ad9361_rx_bb_analog_filter_calib() is always run prior + */ + + tmp = bbpll_freq * 10000ULL; + do_div(&tmp, 126906UL * phy->rxbbf_div); + bb_bw_Hz = tmp; + + dev_dbg(&phy->spi->dev, "%s : BBBW %"PRIu32" : ADCfreq %"PRIu32, + __func__, bb_bw_Hz, adc_sampl_freq_Hz); + + dev_dbg(&phy->spi->dev, "c3_msb 0x%X : c3_lsb 0x%X : r2346 0x%X : ", + c3_msb, c3_lsb, r2346); + + bb_bw_Hz = clamp(bb_bw_Hz, 200000UL, 28000000UL); + + if (adc_sampl_freq_Hz < 80000000) + scale_snr_1e3 = 1000; + else + scale_snr_1e3 = 1585; /* pow(10, scale_snr_dB/10); */ + + if (bb_bw_Hz >= 18000000) { + invrc_tconst_1e6 = (160975ULL * r2346 * + (160 * c3_msb + 10 * c3_lsb + 140) * + (bb_bw_Hz)* (1000 + (10 * (bb_bw_Hz - 18000000) / 1000000))); + + do_div(&invrc_tconst_1e6, 1000UL); + + } else { + invrc_tconst_1e6 = (160975ULL * r2346 * + (160 * c3_msb + 10 * c3_lsb + 140) * + (bb_bw_Hz)); + } + + do_div(&invrc_tconst_1e6, 1000000000UL); + + if (invrc_tconst_1e6 > ULONG_MAX) + dev_err(&phy->spi->dev, "invrc_tconst_1e6 > ULONG_MAX"); + + sqrt_inv_rc_tconst_1e3 = int_sqrt((uint32_t)invrc_tconst_1e6); + maxsnr = 640 / 160; + scaled_adc_clk_1e6 = DIV_ROUND_CLOSEST(adc_sampl_freq_Hz, 640); + inv_scaled_adc_clk_1e3 = DIV_ROUND_CLOSEST(640000000, + DIV_ROUND_CLOSEST(adc_sampl_freq_Hz, 1000)); + tmp_1e3 = DIV_ROUND_CLOSEST(980000 + 20 * max_t(uint32_t, 1000U, + DIV_ROUND_CLOSEST(inv_scaled_adc_clk_1e3, maxsnr)), 1000); + sqrt_term_1e3 = int_sqrt(scaled_adc_clk_1e6); + min_sqrt_term_1e3 = min_t(uint32_t, 1000U, + int_sqrt(maxsnr * scaled_adc_clk_1e6)); + + dev_dbg(&phy->spi->dev, + "invrc_tconst_1e6 %"PRIu64", sqrt_inv_rc_tconst_1e3 %"PRIu32, + invrc_tconst_1e6, sqrt_inv_rc_tconst_1e3); + dev_dbg(&phy->spi->dev, + "scaled_adc_clk_1e6 %"PRIu32", inv_scaled_adc_clk_1e3 %"PRIu32, + scaled_adc_clk_1e6, inv_scaled_adc_clk_1e3); + dev_dbg(&phy->spi->dev, + "tmp_1e3 %"PRIu32", sqrt_term_1e3 %"PRIu32", min_sqrt_term_1e3 %"PRIu32, + tmp_1e3, sqrt_term_1e3, min_sqrt_term_1e3); + + data[0] = 0; + data[1] = 0; + data[2] = 0; + data[3] = 0x24; + data[4] = 0x24; + data[5] = 0; + data[6] = 0; + + tmp = -50000000 + 8ULL * scale_snr_1e3 * sqrt_inv_rc_tconst_1e3 * + min_sqrt_term_1e3; + do_div(&tmp, 100000000UL); + data[7] = min_t(uint64_t, 124U, tmp); + + tmp = (invrc_tconst_1e6 >> 1) + 20 * inv_scaled_adc_clk_1e3 * + data[7] / 80 * 1000ULL; + do_div(&tmp, invrc_tconst_1e6); + data[8] = min_t(uint64_t, 255U, tmp); + + tmp = (-500000 + 77ULL * sqrt_inv_rc_tconst_1e3 * min_sqrt_term_1e3); + do_div(&tmp, 1000000UL); + data[10] = min_t(uint64_t, 127U, tmp); + + data[9] = min_t(uint32_t, 127U, ((800 * data[10]) / 1000)); + tmp = ((invrc_tconst_1e6 >> 1) + (20 * inv_scaled_adc_clk_1e3 * + data[10] * 1000ULL)); + do_div(&tmp, invrc_tconst_1e6 * 77); + data[11] = min_t(uint64_t, 255U, tmp); + data[12] = min_t(uint32_t, 127U, (-500000 + 80 * sqrt_inv_rc_tconst_1e3 * + min_sqrt_term_1e3) / 1000000UL); + + tmp = -3 * (long)(invrc_tconst_1e6 >> 1) + inv_scaled_adc_clk_1e3 * + data[12] * (1000ULL * 20 / 80); + do_div(&tmp, invrc_tconst_1e6); + data[13] = min_t(uint64_t, 255, tmp); + + data[14] = 21 * (inv_scaled_adc_clk_1e3 / 10000); + data[15] = min_t(uint32_t, 127U, (500 + 1025 * data[7]) / 1000); + data[16] = min_t(uint32_t, 127U, (data[15] * tmp_1e3) / 1000); + data[17] = data[15]; + data[18] = min_t(uint32_t, 127U, (500 + 975 * data[10]) / 1000); + data[19] = min_t(uint32_t, 127U, (data[18] * tmp_1e3) / 1000); + data[20] = data[18]; + data[21] = min_t(uint32_t, 127U, (500 + 975 * data[12]) / 1000); + data[22] = min_t(uint32_t, 127, (data[21] * tmp_1e3) / 1000); + data[23] = data[21]; + data[24] = 0x2E; + data[25] = (128 + min_t(uint32_t, 63000U, DIV_ROUND_CLOSEST(63 * + scaled_adc_clk_1e6, 1000)) / 1000); + data[26] = min_t(uint32_t, 63U, 63 * scaled_adc_clk_1e6 / 1000000 * + (920 + 80 * inv_scaled_adc_clk_1e3 / 1000) / 1000); + data[27] = min_t(uint32_t, 63, (32 * sqrt_term_1e3) / 1000); + data[28] = data[25]; + data[29] = data[26]; + data[30] = data[27]; + data[31] = data[25]; + data[32] = data[26]; + data[33] = min_t(uint32_t, 63U, 63 * sqrt_term_1e3 / 1000); + data[34] = min_t(uint32_t, 127U, 64 * sqrt_term_1e3 / 1000); + data[35] = 0x40; + data[36] = 0x40; + data[37] = 0x2C; + data[38] = 0x00; + data[39] = 0x00; + + for (i = 0; i < 40; i++) { + ret = ad9361_spi_write(phy->spi, 0x200 + i, data[i]); + if (ret < 0) + return ret; + } + + return 0; +} + +/** + * Perform a RX TIA calibration. + * @param phy The AD9361 state structure. + * @param bb_bw_Hz The baseband bandwidth [Hz]. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_rx_tia_calib(struct ad9361_rf_phy *phy, uint32_t bb_bw_Hz) +{ + uint32_t Cbbf, R2346; + uint64_t CTIA_fF; + + uint8_t reg1EB = ad9361_spi_read(phy->spi, REG_RX_BBF_C3_MSB); + uint8_t reg1EC = ad9361_spi_read(phy->spi, REG_RX_BBF_C3_LSB); + uint8_t reg1E6 = ad9361_spi_read(phy->spi, REG_RX_BBF_R2346); + uint8_t reg1DB, reg1DF, reg1DD, reg1DC, reg1DE, temp; + + dev_dbg(&phy->spi->dev, "%s : bb_bw_Hz %"PRIu32, + __func__, bb_bw_Hz); + + bb_bw_Hz = clamp(bb_bw_Hz, 200000UL, 20000000UL); + + Cbbf = (reg1EB * 160) + (reg1EC * 10) + 140; /* fF */ + R2346 = 18300 * RX_BBF_R2346(reg1E6); + + CTIA_fF = Cbbf * R2346 * 560ULL; + do_div(&CTIA_fF, 3500000UL); + + if (bb_bw_Hz <= 3000000UL) + reg1DB = 0xE0; + else if (bb_bw_Hz <= 10000000UL) + reg1DB = 0x60; + else + reg1DB = 0x20; + + if (CTIA_fF > 2920ULL) { + reg1DC = 0x40; + reg1DE = 0x40; + temp = min(127U, DIV_ROUND_CLOSEST((uint32_t)CTIA_fF - 400, 320U)); + reg1DD = temp; + reg1DF = temp; + } else { + temp = DIV_ROUND_CLOSEST((uint32_t)CTIA_fF - 400, 40U) + 0x40; + reg1DC = temp; + reg1DE = temp; + reg1DD = 0; + reg1DF = 0; + } + + ad9361_spi_write(phy->spi, REG_RX_TIA_CONFIG, reg1DB); + ad9361_spi_write(phy->spi, REG_TIA1_C_LSB, reg1DC); + ad9361_spi_write(phy->spi, REG_TIA1_C_MSB, reg1DD); + ad9361_spi_write(phy->spi, REG_TIA2_C_LSB, reg1DE); + ad9361_spi_write(phy->spi, REG_TIA2_C_MSB, reg1DF); + + return 0; +} + +/** + * Perform a baseband RX analog filter calibration. + * @param phy The AD9361 state structure. + * @param rx_bb_bw The baseband bandwidth [Hz]. + * @param bbpll_freq The BBPLL frequency [Hz]. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_rx_bb_analog_filter_calib(struct ad9361_rf_phy *phy, + uint32_t rx_bb_bw, + uint32_t bbpll_freq) +{ + uint32_t target; + uint8_t tmp; + int32_t ret; + + dev_dbg(&phy->spi->dev, "%s : rx_bb_bw %"PRIu32" bbpll_freq %"PRIu32, + __func__, rx_bb_bw, bbpll_freq); + + rx_bb_bw = clamp(rx_bb_bw, 200000UL, 28000000UL); + + /* 1.4 * BBBW * 2PI / ln(2) */ + target = 126906UL * (rx_bb_bw / 10000UL); + phy->rxbbf_div = min_t(uint32_t, 511UL, DIV_ROUND_UP(bbpll_freq, target)); + + /* Set RX baseband filter divide value */ + ad9361_spi_write(phy->spi, REG_RX_BBF_TUNE_DIVIDE, phy->rxbbf_div); + ad9361_spi_writef(phy->spi, REG_RX_BBF_TUNE_CONFIG, BIT(0), + phy->rxbbf_div >> 8); + + /* Write the BBBW into registers 0x1FB and 0x1FC */ + ad9361_spi_write(phy->spi, REG_RX_BBBW_MHZ, rx_bb_bw / 1000000UL); + + tmp = DIV_ROUND_CLOSEST((rx_bb_bw % 1000000UL) * 128, 1000000UL); + ad9361_spi_write(phy->spi, REG_RX_BBBW_KHZ, min_t(uint8_t, 127, tmp)); + + ad9361_spi_write(phy->spi, REG_RX_MIX_LO_CM, + RX_MIX_LO_CM(0x3F)); /* Set Rx Mix LO CM */ + ad9361_spi_write(phy->spi, REG_RX_MIX_GM_CONFIG, + RX_MIX_GM_PLOAD(3)); /* Set GM common mode */ + + /* Enable the RX BBF tune circuit by writing 0x1E2=0x02 and 0x1E3=0x02 */ + ad9361_spi_write(phy->spi, REG_RX1_TUNE_CTRL, RX1_TUNE_RESAMPLE); + ad9361_spi_write(phy->spi, REG_RX2_TUNE_CTRL, RX2_TUNE_RESAMPLE); + + /* Start the RX Baseband Filter calibration in register 0x016[7] */ + /* Calibration is complete when register 0x016[7] self clears */ + ret = ad9361_run_calibration(phy, RX_BB_TUNE_CAL); + + /* Disable the RX baseband filter tune circuit, write 0x1E2=3, 0x1E3=3 */ + ad9361_spi_write(phy->spi, REG_RX1_TUNE_CTRL, + RX1_TUNE_RESAMPLE | RX1_PD_TUNE); + ad9361_spi_write(phy->spi, REG_RX2_TUNE_CTRL, + RX2_TUNE_RESAMPLE | RX2_PD_TUNE); + + return ret; +} + +/** + * Perform a baseband TX analog filter calibration. + * @param phy The AD9361 state structure. + * @param tx_bb_bw The baseband bandwidth [Hz]. + * @param bbpll_freq The BBPLL frequency [Hz]. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_tx_bb_analog_filter_calib(struct ad9361_rf_phy *phy, + uint32_t tx_bb_bw, + uint32_t bbpll_freq) +{ + uint32_t target, txbbf_div; + int32_t ret; + + dev_dbg(&phy->spi->dev, "%s : tx_bb_bw %"PRIu32" bbpll_freq %"PRIu32, + __func__, tx_bb_bw, bbpll_freq); + + tx_bb_bw = clamp(tx_bb_bw, 625000UL, 20000000UL); + + /* 1.6 * BBBW * 2PI / ln(2) */ + target = 145036 * (tx_bb_bw / 10000UL); + txbbf_div = min_t(uint32_t, 511UL, DIV_ROUND_UP(bbpll_freq, target)); + + /* Set TX baseband filter divide value */ + ad9361_spi_write(phy->spi, REG_TX_BBF_TUNE_DIVIDER, txbbf_div); + ad9361_spi_writef(phy->spi, REG_TX_BBF_TUNE_MODE, + TX_BBF_TUNE_DIVIDER, txbbf_div >> 8); + + /* Enable the TX baseband filter tune circuit by setting 0x0CA=0x22. */ + ad9361_spi_write(phy->spi, REG_TX_TUNE_CTRL, TUNER_RESAMPLE | TUNE_CTRL(1)); + + /* Start the TX Baseband Filter calibration in register 0x016[6] */ + /* Calibration is complete when register 0x016[] self clears */ + ret = ad9361_run_calibration(phy, TX_BB_TUNE_CAL); + + /* Disable the TX baseband filter tune circuit by writing 0x0CA=0x26. */ + ad9361_spi_write(phy->spi, REG_TX_TUNE_CTRL, + TUNER_RESAMPLE | TUNE_CTRL(1) | PD_TUNE); + + return ret; +} + +/** + * Perform a baseband TX secondary filter calibration. + * @param phy The AD9361 state structure. + * @param tx_rf_bw The RF bandwidth [Hz]. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_tx_bb_second_filter_calib(struct ad9361_rf_phy *phy, + uint32_t tx_bb_bw) +{ + uint64_t cap; + uint32_t corner, res, div; + uint32_t reg_conf, reg_res; + int32_t ret, i; + + dev_dbg(&phy->spi->dev, "%s : tx_bb_bw %"PRIu32, + __func__, tx_bb_bw); + + tx_bb_bw = clamp(tx_bb_bw, 530000UL, 20000000UL); + + /* BBBW * 5PI */ + corner = 15708 * (tx_bb_bw / 10000UL); + + for (i = 0, res = 1; i < 4; i++) { + div = corner * res; + cap = (500000000ULL) + (div >> 1); + do_div(&cap, div); + cap -= 12ULL; + if (cap < 64ULL) + break; + + res <<= 1; + } + + if (cap > 63ULL) + cap = 63ULL; + + if (tx_bb_bw <= 4500000UL) + reg_conf = 0x59; + else if (tx_bb_bw <= 12000000UL) + reg_conf = 0x56; + else + reg_conf = 0x57; + + switch (res) { + case 1: + reg_res = 0x0C; + break; + case 2: + reg_res = 0x04; + break; + case 4: + reg_res = 0x03; + break; + case 8: + reg_res = 0x01; + break; + default: + reg_res = 0x01; + } + + ret = ad9361_spi_write(phy->spi, REG_CONFIG0, reg_conf); + ret |= ad9361_spi_write(phy->spi, REG_RESISTOR, reg_res); + ret |= ad9361_spi_write(phy->spi, REG_CAPACITOR, (uint8_t)cap); + + return ret; +} + +/** + * Perform a RF synthesizer charge pump calibration. + * @param phy The AD9361 state structure. + * @param ref_clk_hz The reference clock rate [Hz]. + * @param tx The Synthesizer TX = 1, RX = 0. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_txrx_synth_cp_calib(struct ad9361_rf_phy *phy, + uint32_t ref_clk_hz, bool tx) +{ + uint32_t offs = tx ? 0x40 : 0; + uint32_t vco_cal_cnt; + dev_dbg(&phy->spi->dev, "%s : ref_clk_hz %"PRIu32" : is_tx %d", + __func__, ref_clk_hz, tx); + + /* REVIST: */ + ad9361_spi_write(phy->spi, REG_RX_CP_LEVEL_DETECT + offs, 0x17); + + ad9361_spi_write(phy->spi, REG_RX_DSM_SETUP_1 + offs, 0x0); + + ad9361_spi_write(phy->spi, REG_RX_LO_GEN_POWER_MODE + offs, 0x00); + ad9361_spi_write(phy->spi, REG_RX_VCO_LDO + offs, 0x0B); + ad9361_spi_write(phy->spi, REG_RX_VCO_PD_OVERRIDES + offs, 0x02); + ad9361_spi_write(phy->spi, REG_RX_CP_CURRENT + offs, 0x80); + ad9361_spi_write(phy->spi, REG_RX_CP_CONFIG + offs, CP_OFFSET_OFF); + + /* see Table 70 Example Calibration Times for RF VCO Cal */ + if (phy->pdata->fdd) { + vco_cal_cnt = VCO_CAL_EN | VCO_CAL_COUNT(3) | FB_CLOCK_ADV(2); + } else { + if (ref_clk_hz > 40000000UL) + vco_cal_cnt = VCO_CAL_EN | VCO_CAL_COUNT(1) | + FB_CLOCK_ADV(2); + else + vco_cal_cnt = VCO_CAL_EN | VCO_CAL_COUNT(0) | + FB_CLOCK_ADV(2); + } + + ad9361_spi_write(phy->spi, REG_RX_VCO_CAL + offs, vco_cal_cnt); + + /* Enable FDD mode during calibrations */ + + if (!phy->pdata->fdd) { + ad9361_spi_writef(phy->spi, REG_PARALLEL_PORT_CONF_3, + HALF_DUPLEX_MODE, 0); + } + + ad9361_spi_write(phy->spi, REG_ENSM_CONFIG_2, DUAL_SYNTH_MODE); + ad9361_spi_write(phy->spi, REG_ENSM_CONFIG_1, + FORCE_ALERT_STATE | + TO_ALERT); + ad9361_spi_write(phy->spi, REG_ENSM_MODE, FDD_MODE); + + ad9361_spi_write(phy->spi, REG_RX_CP_CONFIG + offs, + CP_OFFSET_OFF | CP_CAL_ENABLE); + + return ad9361_check_cal_done(phy, REG_RX_CAL_STATUS + offs, + CP_CAL_VALID, 1); +} + +/** + * Perform a baseband DC offset calibration. + * @param phy The AD9361 state structure. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_bb_dc_offset_calib(struct ad9361_rf_phy *phy) +{ + dev_dbg(&phy->spi->dev, "%s", __func__); + + ad9361_spi_write(phy->spi, REG_BB_DC_OFFSET_COUNT, 0x3F); + ad9361_spi_write(phy->spi, REG_BB_DC_OFFSET_SHIFT, BB_DC_M_SHIFT(0xF)); + ad9361_spi_write(phy->spi, REG_BB_DC_OFFSET_ATTEN, BB_DC_OFFSET_ATTEN(1)); + + return ad9361_run_calibration(phy, BBDC_CAL); +} + +/** + * Perform a RF DC offset calibration. + * @param phy The AD9361 state structure. + * @param ref_clk_hz The RX LO frequency [Hz]. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_rf_dc_offset_calib(struct ad9361_rf_phy *phy, + uint64_t rx_freq) +{ + struct spi_desc *spi = phy->spi; + + dev_dbg(&phy->spi->dev, "%s : rx_freq %"PRIu64, + __func__, rx_freq); + + ad9361_spi_write(spi, REG_WAIT_COUNT, 0x20); + + if (rx_freq <= 4000000000ULL) { + ad9361_spi_write(spi, REG_RF_DC_OFFSET_COUNT, + phy->pdata->rf_dc_offset_count_low); + ad9361_spi_write(spi, REG_RF_DC_OFFSET_CONFIG_1, + RF_DC_CALIBRATION_COUNT(4) | DAC_FS(2)); + ad9361_spi_write(spi, REG_RF_DC_OFFSET_ATTEN, + RF_DC_OFFSET_ATTEN( + phy->pdata->dc_offset_attenuation_low)); + } else { + ad9361_spi_write(spi, REG_RF_DC_OFFSET_COUNT, + phy->pdata->rf_dc_offset_count_high); + ad9361_spi_write(spi, REG_RF_DC_OFFSET_CONFIG_1, + RF_DC_CALIBRATION_COUNT(4) | DAC_FS(3)); + ad9361_spi_write(spi, REG_RF_DC_OFFSET_ATTEN, + RF_DC_OFFSET_ATTEN( + phy->pdata->dc_offset_attenuation_high)); + } + + ad9361_spi_write(spi, REG_DC_OFFSET_CONFIG2, + USE_WAIT_COUNTER_FOR_RF_DC_INIT_CAL | + DC_OFFSET_UPDATE(3)); + + if (phy->pdata->rx1rx2_phase_inversion_en || + (phy->pdata->port_ctrl.pp_conf[1] & INVERT_RX2)) { + ad9361_spi_write(spi, REG_INVERT_BITS, + INVERT_RX1_RF_DC_CGOUT_WORD); + } else { + ad9361_spi_write(spi, REG_INVERT_BITS, + INVERT_RX1_RF_DC_CGOUT_WORD | + INVERT_RX2_RF_DC_CGOUT_WORD); + } + + return ad9361_run_calibration(phy, RFDC_CAL); +} + +/** + * Update RF bandwidth. + * @param phy The AD9361 state structure. + * @param rf_rx_bw RF RX bandwidth [Hz]. + * @param rf_tx_bw RF TX bandwidth [Hz]. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t __ad9361_update_rf_bandwidth(struct ad9361_rf_phy *phy, + uint32_t rf_rx_bw, uint32_t rf_tx_bw) +{ + uint32_t real_rx_bandwidth = rf_rx_bw / 2; + uint32_t real_tx_bandwidth = rf_tx_bw / 2; + uint32_t bbpll_freq; + int32_t ret; + + dev_dbg(&phy->spi->dev, "%s: %"PRIu32" %"PRIu32, + __func__, rf_rx_bw, rf_tx_bw); + + bbpll_freq = clk_get_rate(phy, phy->ref_clk_scale[BBPLL_CLK]); + + ret = ad9361_rx_bb_analog_filter_calib(phy, + real_rx_bandwidth, + bbpll_freq); + if (ret < 0) + return ret; + + ret = ad9361_tx_bb_analog_filter_calib(phy, + real_tx_bandwidth, + bbpll_freq); + if (ret < 0) + return ret; + + ret = ad9361_rx_tia_calib(phy, real_rx_bandwidth); + if (ret < 0) + return ret; + + ret = ad9361_tx_bb_second_filter_calib(phy, real_tx_bandwidth); + if (ret < 0) + return ret; + + ret = ad9361_rx_adc_setup(phy, + bbpll_freq, + clk_get_rate(phy, phy->ref_clk_scale[ADC_CLK])); + if (ret < 0) + return ret; + + return 0; +} + +/** + * TX Quad Calib. + * @param phy The AD9361 state structure. + * @param phase phase + * @param rxnco_word Rx NCO word. + * @param decim decim + * @param res res + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t __ad9361_tx_quad_calib(struct ad9361_rf_phy *phy, uint32_t phase, + uint32_t rxnco_word, uint32_t decim, uint8_t *res) +{ + int32_t ret; + + ad9361_spi_write(phy->spi, REG_QUAD_CAL_NCO_FREQ_PHASE_OFFSET, + RX_NCO_FREQ(rxnco_word) | RX_NCO_PHASE_OFFSET(phase)); + ad9361_spi_write(phy->spi, REG_QUAD_CAL_CTRL, + SETTLE_MAIN_ENABLE | DC_OFFSET_ENABLE | QUAD_CAL_SOFT_RESET | + GAIN_ENABLE | PHASE_ENABLE | M_DECIM(decim)); + ad9361_spi_write(phy->spi, REG_QUAD_CAL_CTRL, + SETTLE_MAIN_ENABLE | DC_OFFSET_ENABLE | + GAIN_ENABLE | PHASE_ENABLE | M_DECIM(decim)); + + ret = ad9361_run_calibration(phy, TX_QUAD_CAL); + if (ret < 0) + return ret; + + if (res) { + *res = ad9361_spi_read(phy->spi, + (phy->pdata->rx1tx1_mode_use_tx_num == 2) ? + REG_QUAD_CAL_STATUS_TX2 : REG_QUAD_CAL_STATUS_TX1) & + (TX1_LO_CONV | TX1_SSB_CONV); + if (phy->pdata->rx2tx2) + *res &= ad9361_spi_read(phy->spi, REG_QUAD_CAL_STATUS_TX2) & + (TX2_LO_CONV | TX2_SSB_CONV); + } + + return 0; +} + +/** + * Loop through all possible phase offsets in case the QUAD CAL doesn't converge. + * @param phy The AD9361 state structure. + * @param rxnco_word Rx NCO word. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_tx_quad_phase_search(struct ad9361_rf_phy *phy, + uint32_t rxnco_word, uint8_t decim) +{ + int32_t i, ret; + uint8_t field[64], val; + uint32_t start; + + dev_dbg(&phy->spi->dev, "%s", __func__); + + for (i = 0; i < (int64_t)(ARRAY_SIZE(field) / 2); i++) { + ret = __ad9361_tx_quad_calib(phy, i, rxnco_word, decim, &val); + if (ret < 0) + return ret; + + /* Handle 360/0 wrap around */ + field[i] = field[i + 32] = !((val & TX1_LO_CONV) && (val & TX1_SSB_CONV)); + } + + ret = ad9361_find_opt(field, ARRAY_SIZE(field), &start); + + phy->last_tx_quad_cal_phase = (start + ret / 2) & 0x1F; + +#ifdef _DEBUG + for (i = 0; i < 64; i++) { + printk("%c", (field[i] ? '#' : 'o')); + } +#ifdef WIN32 + printk(" RX_NCO_PHASE_OFFSET(%d, 0x%X) \n", phy->last_tx_quad_cal_phase, + phy->last_tx_quad_cal_phase); +#else + printk(" RX_NCO_PHASE_OFFSET(%"PRIu32", 0x%"PRIX32") \n", + phy->last_tx_quad_cal_phase, + phy->last_tx_quad_cal_phase); +#endif +#endif + + ret = __ad9361_tx_quad_calib(phy, phy->last_tx_quad_cal_phase, rxnco_word, + decim, NULL); + if (ret < 0) + return ret; + + return 0; +} + +/** + * Perform a TX quadrature calibration. + * @param phy The AD9361 state structure. + * @param bw The bandwidth [Hz]. + * @param rx_phase The optional RX phase value overwrite (set to zero). + * @return 0 in case of success, negative error code otherwise. + */ + +static int ad9361_tx_quad_calib(struct ad9361_rf_phy *phy, + uint32_t bw_rx, uint32_t bw_tx, + int32_t rx_phase) +{ + struct spi_desc *spi = phy->spi; + uint32_t clktf, clkrf; + int32_t txnco_word, rxnco_word, txnco_freq, ret; + uint8_t __rx_phase = 0, reg_inv_bits = 0, val, decim; + bool phase_inversion_en; + + ret = 0; + if (phy->cached_synth_pd[0] & TX_LO_POWER_DOWN) { + if (phy->pdata->lo_powerdown_managed_en) { + ad9361_spi_writef(spi, REG_TX_SYNTH_POWER_DOWN_OVERRIDE, + TX_LO_POWER_DOWN, 0); + } else { + dev_err(dev, + "%s : Tx QUAD Cal abort due to TX LO in powerdown\n", + __func__); + return -EFAULT; + } + } + /* + * Find NCO frequency that matches this equation: + * BW / 4 = Rx NCO freq = Tx NCO freq: + * Rx NCO = ClkRF * (rxNCO <1:0> + 1) / 32 + * Tx NCO = ClkTF * (txNCO <1:0> + 1) / 32 + */ + + clkrf = clk_get_rate(phy, phy->ref_clk_scale[CLKRF_CLK]); + clktf = clk_get_rate(phy, phy->ref_clk_scale[CLKTF_CLK]); + + dev_dbg(&phy->spi->dev, "%s : bw_tx %"PRIu32" clkrf %"PRIu32" clktf %"PRIu32, + __func__, bw_tx, clkrf, clktf); + + txnco_word = DIV_ROUND_CLOSEST(bw_tx * 8, clktf) - 1; + txnco_word = clamp_t(int, txnco_word, 0, 3); + rxnco_word = txnco_word; + + dev_dbg(dev, "Tx NCO frequency: %"PRIu32" (BW/4: %"PRIu32") txnco_word %"PRId32, + clktf * (txnco_word + 1) / 32, bw_tx / 4, txnco_word); + + if (clktf <= 4000000UL) + decim = 2; + else + decim = 3; + + if (clkrf == (2 * clktf)) { + __rx_phase = 0x0E; + switch (txnco_word) { + case 0: + txnco_word++; + break; + case 1: + rxnco_word--; + break; + case 2: + rxnco_word -= 2; + txnco_word--; + break; + case 3: + rxnco_word -= 2; /* REVISIT */ + __rx_phase = 0x08; + break; + } + } else if (clkrf == clktf) { + switch (txnco_word) { + case 0: + case 3: + __rx_phase = 0x15; + break; + case 2: + __rx_phase = 0x1F; + break; + case 1: + if (ad9361_spi_readf(spi, + REG_TX_ENABLE_FILTER_CTRL, 0x3F) == 0x22) + __rx_phase = 0x15; /* REVISIT */ + else + __rx_phase = 0x1A; + break; + } + } else + dev_err(dev, "Unhandled case in %s line %d clkrf %"PRIu32" clktf %"PRIu32, + __func__, __LINE__, clkrf, clktf); + + if (rx_phase >= 0) + __rx_phase = rx_phase; + + txnco_freq = clktf * (txnco_word + 1) / 32; + + if (txnco_freq > (int64_t)(bw_rx / 4) || txnco_freq > (int64_t)(bw_tx / 4)) { + /* Make sure the BW during calibration is wide enough */ + ret = __ad9361_update_rf_bandwidth(phy, txnco_freq * 8, txnco_freq * 8); + if (ret < 0) + goto out_restore; + } + + phase_inversion_en = phy->pdata->rx1rx2_phase_inversion_en || + (phy->pdata->port_ctrl.pp_conf[1] & INVERT_RX2); + + if (phase_inversion_en) { + ad9361_spi_writef(spi, REG_PARALLEL_PORT_CONF_2, INVERT_RX2, 0); + + reg_inv_bits = ad9361_spi_read(spi, REG_INVERT_BITS); + + ad9361_spi_write(spi, REG_INVERT_BITS, + INVERT_RX1_RF_DC_CGOUT_WORD | + INVERT_RX2_RF_DC_CGOUT_WORD); + } + + ad9361_spi_writef(spi, REG_KEXP_2, TX_NCO_FREQ(~0), txnco_word); + ad9361_spi_write(spi, REG_QUAD_CAL_COUNT, 0xFF); + ad9361_spi_write(spi, REG_KEXP_1, KEXP_TX(1) | KEXP_TX_COMP(3) | + KEXP_DC_I(3) | KEXP_DC_Q(3)); + ad9361_spi_write(spi, REG_MAG_FTEST_THRESH, 0x03); + ad9361_spi_write(spi, REG_MAG_FTEST_THRESH_2, 0x03); + + if (phy->tx_quad_lpf_tia_match < 0) /* set in ad9361_load_gt() */ + dev_err(dev, "failed to find suitable LPF TIA value in gain table\n"); + else + ad9361_spi_write(spi, REG_TX_QUAD_FULL_LMT_GAIN, + phy->tx_quad_lpf_tia_match); + + ad9361_spi_write(spi, REG_QUAD_SETTLE_COUNT, 0xF0); + ad9361_spi_write(spi, REG_TX_QUAD_LPF_GAIN, 0x00); + + if (rx_phase != -2) { + ret = __ad9361_tx_quad_calib(phy, __rx_phase, rxnco_word, decim, &val); + + dev_dbg(dev, "LO leakage: %d Quadrature Calibration: %d : rx_phase %d\n", + !!(val & TX1_LO_CONV), !!(val & TX1_SSB_CONV), __rx_phase); + + /* Calibration failed -> try last phase offset */ + if (val != (TX1_LO_CONV | TX1_SSB_CONV)) { + if (phy->last_tx_quad_cal_phase < 31) + ret = __ad9361_tx_quad_calib(phy, phy->last_tx_quad_cal_phase, + rxnco_word, decim, &val); + } else { + phy->last_tx_quad_cal_phase = __rx_phase; + } + } else { + /* force phase search */ + val = 0; + } + /* Calibration failed -> loop through all 32 phase offsets */ + if (val != (TX1_LO_CONV | TX1_SSB_CONV)) + ret = ad9361_tx_quad_phase_search(phy, rxnco_word, decim); + + if (phase_inversion_en) { + ad9361_spi_writef(spi, REG_PARALLEL_PORT_CONF_2, INVERT_RX2, 1); + ad9361_spi_write(spi, REG_INVERT_BITS, reg_inv_bits); + } + + if (txnco_freq > (int64_t)(bw_rx / 4) || txnco_freq > (int64_t)(bw_tx / 4)) { + __ad9361_update_rf_bandwidth(phy, + phy->current_rx_bw_Hz, + phy->current_tx_bw_Hz); + } + +out_restore: + /* Restore synthesizer powerdown configuration */ + if (phy->pdata->lo_powerdown_managed_en && + (phy->cached_synth_pd[0] & TX_LO_POWER_DOWN)) + ad9361_synth_lo_powerdown(phy, LO_DONTCARE, LO_DONTCARE); + + return ret; +} + +/** + * Setup RX tracking calibrations. + * @param phy The AD9361 state structure. + * @param bbdc_track Set true, will enable the BBDC tracking. + * @param rfdc_track Set true, will enable the RFDC tracking. + * @param rxquad_track Set true, will enable the RXQUAD tracking. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_tracking_control(struct ad9361_rf_phy *phy, bool bbdc_track, + bool rfdc_track, bool rxquad_track) +{ + struct spi_desc *spi = phy->spi; + uint32_t qtrack = 0; + + dev_dbg(&spi->dev, "%s : bbdc_track=%d, rfdc_track=%d, rxquad_track=%d", + __func__, bbdc_track, rfdc_track, rxquad_track); + + ad9361_spi_write(spi, REG_CALIBRATION_CONFIG_2, + CALIBRATION_CONFIG2_DFLT | K_EXP_PHASE(0x15)); + ad9361_spi_write(spi, REG_CALIBRATION_CONFIG_3, + PREVENT_POS_LOOP_GAIN | K_EXP_AMPLITUDE(0x15)); + + ad9361_spi_write(spi, REG_DC_OFFSET_CONFIG2, + USE_WAIT_COUNTER_FOR_RF_DC_INIT_CAL | + DC_OFFSET_UPDATE(phy->pdata->dc_offset_update_events) | + (bbdc_track ? ENABLE_BB_DC_OFFSET_TRACKING : 0) | + (rfdc_track ? ENABLE_RF_OFFSET_TRACKING : 0)); + + ad9361_spi_writef(spi, REG_RX_QUAD_GAIN2, + CORRECTION_WORD_DECIMATION_M(~0), + phy->pdata->qec_tracking_slow_mode_en ? 4 : 0); + + if (rxquad_track) { + if (phy->pdata->rx2tx2) + qtrack = ENABLE_TRACKING_MODE_CH1 | ENABLE_TRACKING_MODE_CH2; + else + qtrack = (phy->pdata->rx1tx1_mode_use_rx_num == 1) ? + ENABLE_TRACKING_MODE_CH1 : ENABLE_TRACKING_MODE_CH2; + } + + ad9361_spi_write(spi, REG_CALIBRATION_CONFIG_1, + ENABLE_PHASE_CORR | ENABLE_GAIN_CORR | + FREE_RUN_MODE | ENABLE_CORR_WORD_DECIMATION | + qtrack); + + return 0; +} + +/** + * Enable/disable the VCO cal. + * @param phy The AD9361 state structure. + * @param rx Set true for rx. + * @param enable Set true to enable. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_trx_vco_cal_control(struct ad9361_rf_phy *phy, + bool tx, bool enable) +{ + dev_dbg(&phy->spi->dev, "%s : state %d", + __func__, enable); + + return ad9361_spi_writef(phy->spi, + tx ? REG_TX_PFD_CONFIG : REG_RX_PFD_CONFIG, + BYPASS_LD_SYNTH, !enable); +} + +/** + * Enable/disable the ext. LO. + * @param phy The AD9361 state structure. + * @param rx Set true for rx. + * @param enable Set true to enable. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_trx_ext_lo_control(struct ad9361_rf_phy *phy, + bool tx, bool enable) +{ + uint32_t val = enable ? ~0 : 0; + int32_t ret; + + /* REVIST: + * POWER_DOWN_TRX_SYNTH and MCS_RF_ENABLE somehow conflict + */ + + bool mcs_rf_enable = ad9361_spi_readf(phy->spi, + REG_MULTICHIP_SYNC_AND_TX_MON_CTRL, + MCS_RF_ENABLE); + + dev_dbg(&phy->spi->dev, "%s : %s state %d", __func__, + tx ? "TX" : "RX", enable); + + if (tx) { + ret = ad9361_spi_writef(phy->spi, REG_ENSM_CONFIG_2, + POWER_DOWN_TX_SYNTH, mcs_rf_enable ? 0 : enable); + + ret = ad9361_spi_writef(phy->spi, REG_ENSM_CONFIG_2, + TX_SYNTH_READY_MASK, enable); + + ret |= ad9361_spi_writef(phy->spi, REG_RFPLL_DIVIDERS, + TX_VCO_DIVIDER(~0), enable ? 7 : + phy->cached_tx_rfpll_div); + + if (enable) + phy->cached_synth_pd[0] |= TX_SYNTH_VCO_ALC_POWER_DOWN | + TX_SYNTH_PTAT_POWER_DOWN | + TX_SYNTH_VCO_POWER_DOWN; + else + phy->cached_synth_pd[0] &= ~(TX_SYNTH_VCO_ALC_POWER_DOWN | + TX_SYNTH_PTAT_POWER_DOWN | + TX_SYNTH_VCO_POWER_DOWN); + + + ret |= ad9361_spi_write(phy->spi, REG_TX_SYNTH_POWER_DOWN_OVERRIDE, + phy->cached_synth_pd[0]); + + ret |= ad9361_spi_writef(phy->spi, REG_ANALOG_POWER_DOWN_OVERRIDE, + TX_EXT_VCO_BUFFER_POWER_DOWN, !enable); + + ret |= ad9361_spi_write(phy->spi, REG_TX_LO_GEN_POWER_MODE, + TX_LO_GEN_POWER_MODE(val)); + } else { + ret = ad9361_spi_writef(phy->spi, REG_ENSM_CONFIG_2, + POWER_DOWN_RX_SYNTH, mcs_rf_enable ? 0 : enable); + + ret = ad9361_spi_writef(phy->spi, REG_ENSM_CONFIG_2, + RX_SYNTH_READY_MASK, enable); + + ret |= ad9361_spi_writef(phy->spi, REG_RFPLL_DIVIDERS, + RX_VCO_DIVIDER(~0), enable ? 7 : + phy->cached_rx_rfpll_div); + + if (enable) + phy->cached_synth_pd[1] |= RX_SYNTH_VCO_ALC_POWER_DOWN | + RX_SYNTH_PTAT_POWER_DOWN | + RX_SYNTH_VCO_POWER_DOWN; + else + phy->cached_synth_pd[1] &= ~(TX_SYNTH_VCO_ALC_POWER_DOWN | + RX_SYNTH_PTAT_POWER_DOWN | + RX_SYNTH_VCO_POWER_DOWN); + + ret |= ad9361_spi_write(phy->spi, REG_RX_SYNTH_POWER_DOWN_OVERRIDE, + phy->cached_synth_pd[1]); + + ret |= ad9361_spi_writef(phy->spi, REG_ANALOG_POWER_DOWN_OVERRIDE, + RX_EXT_VCO_BUFFER_POWER_DOWN, !enable); + + ret |= ad9361_spi_write(phy->spi, REG_RX_LO_GEN_POWER_MODE, + RX_LO_GEN_POWER_MODE(val)); + } + + return ret; +} + +/** + * Power down the TX and/or RX Local Oscillators. + * @param phy The AD9361 state structure. + * @param rx The RX LO setting. + * @param tx The TX LO setting. + * @return 0 in case of success, negative error code otherwise. + */ +int ad9361_synth_lo_powerdown(struct ad9361_rf_phy *phy, + enum synth_pd_ctrl rx, + enum synth_pd_ctrl tx) +{ + dev_dbg(&phy->spi->dev, "%s : RX(%d) TX(%d)", __func__, rx, tx); + + switch (rx) { + case LO_OFF: + phy->cached_synth_pd[1] |= RX_LO_POWER_DOWN; + break; + case LO_ON: + phy->cached_synth_pd[1] &= ~RX_LO_POWER_DOWN; + break; + case LO_DONTCARE: + break; + } + + switch (tx) { + case LO_OFF: + phy->cached_synth_pd[0] |= TX_LO_POWER_DOWN; + break; + case LO_ON: + phy->cached_synth_pd[0] &= ~TX_LO_POWER_DOWN; + break; + case LO_DONTCARE: + break; + } + + return ad9361_spi_writem(phy->spi, REG_TX_SYNTH_POWER_DOWN_OVERRIDE, + phy->cached_synth_pd, 2); +} + +/** + * Setup the reference clock delay unit counter register. + * @param phy The AD9361 state structure. + * @param ref_clk_hz The reference clock frequency [Hz]. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_set_ref_clk_cycles(struct ad9361_rf_phy *phy, + uint32_t ref_clk_hz) +{ + dev_dbg(&phy->spi->dev, "%s : ref_clk_hz %"PRIu32, + __func__, ref_clk_hz); + + return ad9361_spi_write(phy->spi, REG_REFERENCE_CLOCK_CYCLES, + REFERENCE_CLOCK_CYCLES_PER_US((ref_clk_hz / 1000000UL) - 1)); +} + +/** + * Setup the DCXO tune. + * @param phy The AD9361 state structure. + * @param coarse The DCXO tune coarse. + * @param fine The DCXO tune fine. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_set_dcxo_tune(struct ad9361_rf_phy *phy, + uint32_t coarse, uint32_t fine) +{ + dev_dbg(&phy->spi->dev, "%s : coarse %"PRIu32" fine %"PRIu32, + __func__, coarse, fine); + + if (phy->pdata->use_extclk) + return -ENODEV; + + ad9361_spi_write(phy->spi, REG_DCXO_COARSE_TUNE, + DCXO_TUNE_COARSE(coarse)); + ad9361_spi_write(phy->spi, REG_DCXO_FINE_TUNE_LOW, + DCXO_TUNE_FINE_LOW(fine)); + return ad9361_spi_write(phy->spi, REG_DCXO_FINE_TUNE_HIGH, + DCXO_TUNE_FINE_HIGH(fine)); +} + +/** + * Setup TXMON. + * @param phy The AD9361 state structure. + * @param ctrl The TXMON settings. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_txmon_setup(struct ad9361_rf_phy *phy, + struct tx_monitor_control *ctrl) +{ + struct spi_desc *spi = phy->spi; + + dev_dbg(&phy->spi->dev, "%s", __func__); + + ad9361_spi_write(spi, REG_TPM_MODE_ENABLE, + (ctrl->one_shot_mode_en ? ONE_SHOT_MODE : 0) | + TX_MON_DURATION(ilog2(ctrl->tx_mon_duration / 16))); + + ad9361_spi_write(spi, REG_TX_MON_DELAY, ctrl->tx_mon_delay & 0xFF); + ad9361_spi_writef(spi, REG_TX_LEVEL_THRESH, + TX_MON_DELAY_COUNTER(~0), ctrl->tx_mon_delay >> 8); + + ad9361_spi_write(spi, REG_TX_MON_1_CONFIG, + TX_MON_1_LO_CM(ctrl->tx1_mon_lo_cm) | + TX_MON_1_GAIN(ctrl->tx1_mon_front_end_gain)); + ad9361_spi_write(spi, REG_TX_MON_2_CONFIG, + TX_MON_2_LO_CM(ctrl->tx2_mon_lo_cm) | + TX_MON_2_GAIN(ctrl->tx2_mon_front_end_gain)); + + ad9361_spi_write(spi, REG_TX_ATTEN_THRESH, + ctrl->low_high_gain_threshold_mdB / 250); + + ad9361_spi_write(spi, REG_TX_MON_HIGH_GAIN, + TX_MON_HIGH_GAIN(ctrl->high_gain_dB)); + + ad9361_spi_write(spi, REG_TX_MON_LOW_GAIN, + (ctrl->tx_mon_track_en ? TX_MON_TRACK : 0) | + TX_MON_LOW_GAIN(ctrl->low_gain_dB)); + + return 0; +} + +/** + * Enable TXMON. + * @param phy The AD9361 state structure. + * @param en_mask The enable mask. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_txmon_control(struct ad9361_rf_phy *phy, + int32_t en_mask) +{ + dev_dbg(&phy->spi->dev, "%s: mask 0x%"PRIx32, __func__, en_mask); + +#if 0 + if (!phy->pdata->fdd && en_mask) { + ad9361_spi_writef(phy->spi, REG_ENSM_CONFIG_1, + ENABLE_RX_DATA_PORT_FOR_CAL, 1); + phy->txmon_tdd_en = true; + } else { + ad9361_spi_writef(phy->spi, REG_ENSM_CONFIG_1, + ENABLE_RX_DATA_PORT_FOR_CAL, 0); + phy->txmon_tdd_en = false; + } +#endif + + ad9361_spi_writef(phy->spi, REG_ANALOG_POWER_DOWN_OVERRIDE, + TX_MONITOR_POWER_DOWN(~0), ~en_mask); + + ad9361_spi_writef(phy->spi, REG_TPM_MODE_ENABLE, + TX1_MON_ENABLE, !!(en_mask & TX_1)); + + return ad9361_spi_writef(phy->spi, REG_TPM_MODE_ENABLE, + TX2_MON_ENABLE, !!(en_mask & TX_2)); +} + +/** +* Setup the RF port. +* Note: +* val +* 0 (RX1A_N & RX1A_P) and (RX2A_N & RX2A_P) enabled; balanced +* 1 (RX1B_N & RX1B_P) and (RX2B_N & RX2B_P) enabled; balanced +* 2 (RX1C_N & RX1C_P) and (RX2C_N & RX2C_P) enabled; balanced +* +* 3 RX1A_N and RX2A_N enabled; unbalanced +* 4 RX1A_P and RX2A_P enabled; unbalanced +* 5 RX1B_N and RX2B_N enabled; unbalanced +* 6 RX1B_P and RX2B_P enabled; unbalanced +* 7 RX1C_N and RX2C_N enabled; unbalanced +* 8 RX1C_P and RX2C_P enabled; unbalanced +* 9 TX_MON1 +* 10 TX_MON2 +* 11 TX_MON1 & TX_MON2 +* @param phy The AD9361 state structure. +* @param is_out TX RF output port enabled. +* @param rx_inputs RX input option identifier +* @param txb TX output option identifier +* @return 0 in case of success, negative error code otherwise. +*/ +int32_t ad9361_rf_port_setup(struct ad9361_rf_phy *phy, bool is_out, + uint32_t rx_inputs, uint32_t txb) +{ + uint32_t val; + + if (rx_inputs > 11) + return -EINVAL; + + if (!is_out) { + if (rx_inputs > 8) + return ad9361_txmon_control(phy, rx_inputs & (TX_1 | TX_2)); + else + ad9361_txmon_control(phy, 0); + } + + if (rx_inputs < 3) + val = 3 << (rx_inputs * 2); + else + val = 1 << (rx_inputs - 3); + + if (txb) + val |= TX_OUTPUT; /* Select TX1B, TX2B */ + + dev_dbg(&phy->spi->dev, "%s : INPUT_SELECT 0x%"PRIx32, + __func__, val); + + return ad9361_spi_write(phy->spi, REG_INPUT_SELECT, val); +} + +/** + * Setup the Parallel Port (Digital Data Interface). + * @param phy The AD9361 state structure. + * @param restore_c3 Set true, will restore the Parallel Port Configuration 3 + * register. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_pp_port_setup(struct ad9361_rf_phy *phy, bool restore_c3) +{ + struct spi_desc *spi = phy->spi; + struct ad9361_phy_platform_data *pd = phy->pdata; + + dev_dbg(&phy->spi->dev, "%s", __func__); + + if (restore_c3) { + return ad9361_spi_write(spi, REG_PARALLEL_PORT_CONF_3, + pd->port_ctrl.pp_conf[2]); + } + + /* Sanity check */ + if (pd->port_ctrl.pp_conf[2] & LVDS_MODE) + pd->port_ctrl.pp_conf[2] &= + ~(HALF_DUPLEX_MODE | SINGLE_DATA_RATE | SINGLE_PORT_MODE); + + if (pd->port_ctrl.pp_conf[2] & FULL_PORT) + pd->port_ctrl.pp_conf[2] &= ~(HALF_DUPLEX_MODE | SINGLE_PORT_MODE); + + ad9361_spi_write(spi, REG_PARALLEL_PORT_CONF_1, pd->port_ctrl.pp_conf[0]); + ad9361_spi_write(spi, REG_PARALLEL_PORT_CONF_2, pd->port_ctrl.pp_conf[1]); + ad9361_spi_write(spi, REG_PARALLEL_PORT_CONF_3, pd->port_ctrl.pp_conf[2]); + ad9361_spi_write(spi, REG_RX_CLOCK_DATA_DELAY, pd->port_ctrl.rx_clk_data_delay); + ad9361_spi_write(spi, REG_TX_CLOCK_DATA_DELAY, pd->port_ctrl.tx_clk_data_delay); + + ad9361_spi_write(spi, REG_LVDS_BIAS_CTRL, pd->port_ctrl.lvds_bias_ctrl); + // ad9361_spi_write(spi, REG_DIGITAL_IO_CTRL, pd->port_ctrl.digital_io_ctrl); + ad9361_spi_write(spi, REG_LVDS_INVERT_CTRL1, pd->port_ctrl.lvds_invert[0]); + ad9361_spi_write(spi, REG_LVDS_INVERT_CTRL2, pd->port_ctrl.lvds_invert[1]); + + if (pd->rx1rx2_phase_inversion_en || + (pd->port_ctrl.pp_conf[1] & INVERT_RX2)) { + + ad9361_spi_writef(spi, REG_PARALLEL_PORT_CONF_2, INVERT_RX2, 1); + ad9361_spi_writef(spi, REG_INVERT_BITS, + INVERT_RX2_RF_DC_CGOUT_WORD, 0); + } + + return 0; +} + +/** + * Setup the Gain Control Blocks (common function for MGC, AGC modes) + * @param phy The AD9361 state structure. + * @param ctrl The gain control settings. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_gc_setup(struct ad9361_rf_phy *phy, + struct gain_control *ctrl) +{ + struct spi_desc *spi = phy->spi; + uint32_t reg, tmp1, tmp2; + + dev_dbg(&phy->spi->dev, "%s", __func__); + + reg = DEC_PWR_FOR_GAIN_LOCK_EXIT | DEC_PWR_FOR_LOCK_LEVEL | + DEC_PWR_FOR_LOW_PWR; + + if (ctrl->rx1_mode == RF_GAIN_HYBRID_AGC || + ctrl->rx2_mode == RF_GAIN_HYBRID_AGC) + reg |= SLOW_ATTACK_HYBRID_MODE; + + reg |= RX1_GAIN_CTRL_SETUP(ctrl->rx1_mode) | + RX2_GAIN_CTRL_SETUP(ctrl->rx2_mode); + + phy->agc_mode[0] = ctrl->rx1_mode; + phy->agc_mode[1] = ctrl->rx2_mode; + + ad9361_spi_write(spi, REG_AGC_CONFIG_1, reg); // Gain Control Mode Select + + /* AGC_USE_FULL_GAIN_TABLE handled in ad9361_load_gt() */ + ad9361_spi_writef(spi, REG_AGC_CONFIG_2, MAN_GAIN_CTRL_RX1, + ctrl->mgc_rx1_ctrl_inp_en); + ad9361_spi_writef(spi, REG_AGC_CONFIG_2, MAN_GAIN_CTRL_RX2, + ctrl->mgc_rx2_ctrl_inp_en); + ad9361_spi_writef(spi, REG_AGC_CONFIG_2, DIG_GAIN_EN, + ctrl->dig_gain_en); + + ctrl->adc_ovr_sample_size = clamp_t(uint8_t, ctrl->adc_ovr_sample_size, 1U, 8U); + reg = ADC_OVERRANGE_SAMPLE_SIZE(ctrl->adc_ovr_sample_size - 1); + + if (has_split_gt && phy->pdata->split_gt && + (ctrl->mgc_rx1_ctrl_inp_en || ctrl->mgc_rx2_ctrl_inp_en)) { + switch (ctrl->mgc_split_table_ctrl_inp_gain_mode) { + case 1: + reg &= ~INCDEC_LMT_GAIN; + break; + case 2: + reg |= INCDEC_LMT_GAIN; + break; + default: + case 0: + reg |= USE_AGC_FOR_LMTLPF_GAIN; + break; + } + } + + ctrl->mgc_inc_gain_step = clamp_t(uint8_t, ctrl->mgc_inc_gain_step, 1U, 8U); + reg |= MANUAL_INCR_STEP_SIZE(ctrl->mgc_inc_gain_step - 1); + ad9361_spi_write(spi, REG_AGC_CONFIG_3, + reg); // Incr Step Size, ADC Overrange Size + + ctrl->mgc_dec_gain_step = clamp_t(uint8_t, ctrl->mgc_dec_gain_step, 1U, 8U); + reg = MANUAL_CTRL_IN_DECR_GAIN_STP_SIZE(ctrl->mgc_dec_gain_step - 1); + ad9361_spi_write(spi, REG_PEAK_WAIT_TIME, + reg); // Decr Step Size, Peak Overload Time + + if (ctrl->dig_gain_en) + ad9361_spi_write(spi, REG_DIGITAL_GAIN, + MAXIMUM_DIGITAL_GAIN(ctrl->max_dig_gain) | + DIG_GAIN_STP_SIZE(ctrl->dig_gain_step_size)); + + if (ctrl->adc_large_overload_thresh >= ctrl->adc_small_overload_thresh) { + ad9361_spi_write(spi, REG_ADC_SMALL_OVERLOAD_THRESH, + ctrl->adc_small_overload_thresh); // ADC Small Overload Threshold + ad9361_spi_write(spi, REG_ADC_LARGE_OVERLOAD_THRESH, + ctrl->adc_large_overload_thresh); // ADC Large Overload Threshold + } else { + ad9361_spi_write(spi, REG_ADC_SMALL_OVERLOAD_THRESH, + ctrl->adc_large_overload_thresh); // ADC Small Overload Threshold + ad9361_spi_write(spi, REG_ADC_LARGE_OVERLOAD_THRESH, + ctrl->adc_small_overload_thresh); // ADC Large Overload Threshold + } + + reg = (ctrl->lmt_overload_high_thresh / 16) - 1; + reg = clamp(reg, 0U, 63U); + ad9361_spi_write(spi, REG_LARGE_LMT_OVERLOAD_THRESH, reg); + reg = (ctrl->lmt_overload_low_thresh / 16) - 1; + reg = clamp(reg, 0U, 63U); + ad9361_spi_writef(spi, REG_SMALL_LMT_OVERLOAD_THRESH, + SMALL_LMT_OVERLOAD_THRESH(~0), reg); + + if (has_split_gt && phy->pdata->split_gt) { + /* REVIST */ + ad9361_spi_write(spi, REG_RX1_MANUAL_LPF_GAIN, 0x58); // Rx1 LPF Gain Index + ad9361_spi_write(spi, REG_RX2_MANUAL_LPF_GAIN, 0x18); // Rx2 LPF Gain Index + ad9361_spi_write(spi, REG_FAST_INITIAL_LMT_GAIN_LIMIT, + 0x27); // Initial LMT Gain Limit + } + + ad9361_spi_write(spi, REG_RX1_MANUAL_DIGITALFORCED_GAIN, + 0x00); // Rx1 Digital Gain Index + ad9361_spi_write(spi, REG_RX2_MANUAL_DIGITALFORCED_GAIN, + 0x00); // Rx2 Digital Gain Index + + reg = clamp_t(uint8_t, ctrl->low_power_thresh, 0U, 64U) * 2; + ad9361_spi_write(spi, REG_FAST_LOW_POWER_THRESH, reg); // Low Power Threshold + ad9361_spi_write(spi, REG_TX_SYMBOL_ATTEN_CONFIG, + 0x00); // Tx Symbol Gain Control + + ad9361_spi_writef(spi, REG_DEC_POWER_MEASURE_DURATION_0, + USE_HB1_OUT_FOR_DEC_PWR_MEAS, + !ctrl->use_rx_fir_out_for_dec_pwr_meas); // USE HB1 or FIR output for power measurements + + ad9361_spi_writef(spi, REG_DEC_POWER_MEASURE_DURATION_0, + ENABLE_DEC_PWR_MEAS, 1); // Power Measurement Duration + + if (ctrl->rx1_mode == RF_GAIN_FASTATTACK_AGC || + ctrl->rx2_mode == RF_GAIN_FASTATTACK_AGC) + reg = ilog2(ctrl->f_agc_dec_pow_measuremnt_duration / 16); + else + reg = ilog2(ctrl->dec_pow_measuremnt_duration / 16); + + ad9361_spi_writef(spi, REG_DEC_POWER_MEASURE_DURATION_0, + DEC_POWER_MEASUREMENT_DURATION(~0), reg); // Power Measurement Duration + + /* AGC */ + + tmp1 = reg = clamp_t(uint8_t, ctrl->agc_inner_thresh_high, 0U, 127U); + ad9361_spi_writef(spi, REG_AGC_LOCK_LEVEL, + AGC_LOCK_LEVEL_FAST_AGC_INNER_HIGH_THRESH_SLOW(~0), + reg); + + tmp2 = reg = clamp_t(uint8_t, ctrl->agc_inner_thresh_low, 0U, 127U); + reg |= (ctrl->adc_lmt_small_overload_prevent_gain_inc ? + PREVENT_GAIN_INC : 0); + ad9361_spi_write(spi, REG_AGC_INNER_LOW_THRESH, reg); + + reg = AGC_OUTER_HIGH_THRESH(tmp1 - ctrl->agc_outer_thresh_high) | + AGC_OUTER_LOW_THRESH(ctrl->agc_outer_thresh_low - tmp2); + ad9361_spi_write(spi, REG_OUTER_POWER_THRESHS, reg); + + reg = AGC_OUTER_HIGH_THRESH_EXED_STP_SIZE(ctrl->agc_outer_thresh_high_dec_steps) + | + AGC_OUTER_LOW_THRESH_EXED_STP_SIZE(ctrl->agc_outer_thresh_low_inc_steps); + ad9361_spi_write(spi, REG_GAIN_STP_2, reg); + + reg = ((ctrl->immed_gain_change_if_large_adc_overload) ? + IMMED_GAIN_CHANGE_IF_LG_ADC_OVERLOAD : 0) | + ((ctrl->immed_gain_change_if_large_lmt_overload) ? + IMMED_GAIN_CHANGE_IF_LG_LMT_OVERLOAD : 0) | + AGC_INNER_HIGH_THRESH_EXED_STP_SIZE(ctrl->agc_inner_thresh_high_dec_steps) | + AGC_INNER_LOW_THRESH_EXED_STP_SIZE(ctrl->agc_inner_thresh_low_inc_steps); + ad9361_spi_write(spi, REG_GAIN_STP1, reg); + + reg = LARGE_ADC_OVERLOAD_EXED_COUNTER(ctrl->adc_large_overload_exceed_counter) | + SMALL_ADC_OVERLOAD_EXED_COUNTER(ctrl->adc_small_overload_exceed_counter); + ad9361_spi_write(spi, REG_ADC_OVERLOAD_COUNTERS, reg); + + reg = DECREMENT_STP_SIZE_FOR_SMALL_LPF_GAIN_CHANGE( + ctrl->f_agc_large_overload_inc_steps) | + LARGE_LPF_GAIN_STEP(ctrl->adc_large_overload_inc_steps); + ad9361_spi_write(spi, REG_GAIN_STP_CONFIG_2, reg); + + reg = LARGE_LMT_OVERLOAD_EXED_COUNTER(ctrl->lmt_overload_large_exceed_counter) | + SMALL_LMT_OVERLOAD_EXED_COUNTER(ctrl->lmt_overload_small_exceed_counter); + ad9361_spi_write(spi, REG_LMT_OVERLOAD_COUNTERS, reg); + + ad9361_spi_writef(spi, REG_GAIN_STP_CONFIG1, + DEC_STP_SIZE_FOR_LARGE_LMT_OVERLOAD(~0), + ctrl->lmt_overload_large_inc_steps); + + reg = DIG_SATURATION_EXED_COUNTER(ctrl->dig_saturation_exceed_counter) | + (ctrl->sync_for_gain_counter_en ? + ENABLE_SYNC_FOR_GAIN_COUNTER : 0); + ad9361_spi_write(spi, REG_DIGITAL_SAT_COUNTER, reg); + + /* + * Fast AGC + */ + + /* Fast AGC - Low Power */ + ad9361_spi_writef(spi, REG_FAST_CONFIG_1, + ENABLE_INCR_GAIN, + ctrl->f_agc_allow_agc_gain_increase); + + ad9361_spi_write(spi, REG_FAST_INCREMENT_TIME, + ctrl->f_agc_lp_thresh_increment_time); + + reg = ctrl->f_agc_lp_thresh_increment_steps - 1; + reg = clamp_t(uint32_t, reg, 0U, 7U); + ad9361_spi_writef(spi, REG_FAST_ENERGY_DETECT_COUNT, + INCREMENT_GAIN_STP_LPFLMT(~0), reg); + + /* Fast AGC - Lock Level */ + /* Dual use see also agc_inner_thresh_high */ + ad9361_spi_writef(spi, REG_FAST_CONFIG_2_SETTLING_DELAY, + ENABLE_LMT_GAIN_INC_FOR_LOCK_LEVEL, + ctrl->f_agc_lock_level_lmt_gain_increase_en); + + reg = ctrl->f_agc_lock_level_gain_increase_upper_limit; + reg = clamp_t(uint32_t, reg, 0U, 63U); + ad9361_spi_writef(spi, REG_FAST_AGCLL_UPPER_LIMIT, + AGCLL_MAX_INCREASE(~0), reg); + + /* Fast AGC - Peak Detectors and Final Settling */ + reg = ctrl->f_agc_lpf_final_settling_steps; + reg = clamp_t(uint32_t, reg, 0U, 3U); + ad9361_spi_writef(spi, REG_FAST_ENERGY_LOST_THRESH, + POST_LOCK_LEVEL_STP_SIZE_FOR_LPF_TABLE_FULL_TABLE(~0), + reg); + + reg = ctrl->f_agc_lmt_final_settling_steps; + reg = clamp_t(uint32_t, reg, 0U, 3U); + ad9361_spi_writef(spi, REG_FAST_STRONGER_SIGNAL_THRESH, + POST_LOCK_LEVEL_STP_FOR_LMT_TABLE(~0), reg); + + reg = ctrl->f_agc_final_overrange_count; + reg = clamp_t(uint32_t, reg, 0U, 7U); + ad9361_spi_writef(spi, REG_FAST_FINAL_OVER_RANGE_AND_OPT_GAIN, + FINAL_OVER_RANGE_COUNT(~0), reg); + + /* Fast AGC - Final Power Test */ + ad9361_spi_writef(spi, REG_FAST_CONFIG_1, + ENABLE_GAIN_INC_AFTER_GAIN_LOCK, + ctrl->f_agc_gain_increase_after_gain_lock_en); + + /* Fast AGC - Unlocking the Gain */ + /* 0 = MAX Gain, 1 = Optimized Gain, 2 = Set Gain */ + + reg = ctrl->f_agc_gain_index_type_after_exit_rx_mode; + ad9361_spi_writef(spi, REG_FAST_CONFIG_1, + GOTO_SET_GAIN_IF_EXIT_RX_STATE, reg == SET_GAIN); + ad9361_spi_writef(spi, REG_FAST_CONFIG_1, + GOTO_OPTIMIZED_GAIN_IF_EXIT_RX_STATE, + reg == OPTIMIZED_GAIN); + + ad9361_spi_writef(spi, REG_FAST_CONFIG_2_SETTLING_DELAY, + USE_LAST_LOCK_LEVEL_FOR_SET_GAIN, + ctrl->f_agc_use_last_lock_level_for_set_gain_en); + + reg = ctrl->f_agc_optimized_gain_offset; + reg = clamp_t(uint32_t, reg, 0U, 15U); + ad9361_spi_writef(spi, REG_FAST_FINAL_OVER_RANGE_AND_OPT_GAIN, + OPTIMIZE_GAIN_OFFSET(~0), reg); + + tmp1 = !ctrl->f_agc_rst_gla_stronger_sig_thresh_exceeded_en || + !ctrl->f_agc_rst_gla_engergy_lost_sig_thresh_exceeded_en || + !ctrl->f_agc_rst_gla_large_adc_overload_en || + !ctrl->f_agc_rst_gla_large_lmt_overload_en || + ctrl->f_agc_rst_gla_en_agc_pulled_high_en; + + ad9361_spi_writef(spi, REG_AGC_CONFIG_2, + AGC_GAIN_UNLOCK_CTRL, tmp1); + + reg = !ctrl->f_agc_rst_gla_stronger_sig_thresh_exceeded_en; + ad9361_spi_writef(spi, REG_FAST_STRONG_SIGNAL_FREEZE, + DONT_UNLOCK_GAIN_IF_STRONGER_SIGNAL, reg); + + reg = ctrl->f_agc_rst_gla_stronger_sig_thresh_above_ll; + reg = clamp_t(uint32_t, reg, 0U, 63U); + ad9361_spi_writef(spi, REG_FAST_STRONGER_SIGNAL_THRESH, + STRONGER_SIGNAL_THRESH(~0), reg); + + reg = ctrl->f_agc_rst_gla_engergy_lost_sig_thresh_below_ll; + reg = clamp_t(uint32_t, reg, 0U, 63U); + ad9361_spi_writef(spi, REG_FAST_ENERGY_LOST_THRESH, + ENERGY_LOST_THRESH(~0), reg); + + reg = ctrl->f_agc_rst_gla_engergy_lost_goto_optim_gain_en; + ad9361_spi_writef(spi, REG_FAST_CONFIG_1, + GOTO_OPT_GAIN_IF_ENERGY_LOST_OR_EN_AGC_HIGH, reg); + + reg = !ctrl->f_agc_rst_gla_engergy_lost_sig_thresh_exceeded_en; + ad9361_spi_writef(spi, REG_FAST_CONFIG_1, + DONT_UNLOCK_GAIN_IF_ENERGY_LOST, reg); + + reg = ctrl->f_agc_energy_lost_stronger_sig_gain_lock_exit_cnt; + reg = clamp_t(uint32_t, reg, 0U, 63U); + ad9361_spi_writef(spi, REG_FAST_GAIN_LOCK_EXIT_COUNT, + GAIN_LOCK_EXIT_COUNT(~0), reg); + + reg = !ctrl->f_agc_rst_gla_large_adc_overload_en || + !ctrl->f_agc_rst_gla_large_lmt_overload_en; + ad9361_spi_writef(spi, REG_FAST_CONFIG_1, + DONT_UNLOCK_GAIN_IF_LG_ADC_OR_LMT_OVRG, reg); + + reg = !ctrl->f_agc_rst_gla_large_adc_overload_en; + ad9361_spi_writef(spi, REG_FAST_LOW_POWER_THRESH, + DONT_UNLOCK_GAIN_IF_ADC_OVRG, reg); + + /* 0 = Max Gain, 1 = Set Gain, 2 = Optimized Gain, 3 = No Gain Change */ + + if (ctrl->f_agc_rst_gla_en_agc_pulled_high_en) { + switch (ctrl->f_agc_rst_gla_if_en_agc_pulled_high_mode) { + case MAX_GAIN: + ad9361_spi_writef(spi, REG_FAST_CONFIG_2_SETTLING_DELAY, + GOTO_MAX_GAIN_OR_OPT_GAIN_IF_EN_AGC_HIGH, 1); + + ad9361_spi_writef(spi, REG_FAST_CONFIG_1, + GOTO_SET_GAIN_IF_EN_AGC_HIGH, 0); + + ad9361_spi_writef(spi, REG_FAST_CONFIG_1, + GOTO_OPT_GAIN_IF_ENERGY_LOST_OR_EN_AGC_HIGH, 0); + break; + case SET_GAIN: + ad9361_spi_writef(spi, REG_FAST_CONFIG_2_SETTLING_DELAY, + GOTO_MAX_GAIN_OR_OPT_GAIN_IF_EN_AGC_HIGH, 0); + + ad9361_spi_writef(spi, REG_FAST_CONFIG_1, + GOTO_SET_GAIN_IF_EN_AGC_HIGH, 1); + break; + case OPTIMIZED_GAIN: + ad9361_spi_writef(spi, REG_FAST_CONFIG_2_SETTLING_DELAY, + GOTO_MAX_GAIN_OR_OPT_GAIN_IF_EN_AGC_HIGH, 1); + + ad9361_spi_writef(spi, REG_FAST_CONFIG_1, + GOTO_SET_GAIN_IF_EN_AGC_HIGH, 0); + + ad9361_spi_writef(spi, REG_FAST_CONFIG_1, + GOTO_OPT_GAIN_IF_ENERGY_LOST_OR_EN_AGC_HIGH, 1); + break; + case NO_GAIN_CHANGE: + ad9361_spi_writef(spi, REG_FAST_CONFIG_1, + GOTO_SET_GAIN_IF_EN_AGC_HIGH, 0); + ad9361_spi_writef(spi, REG_FAST_CONFIG_2_SETTLING_DELAY, + GOTO_MAX_GAIN_OR_OPT_GAIN_IF_EN_AGC_HIGH, 0); + break; + } + } else { + ad9361_spi_writef(spi, REG_FAST_CONFIG_1, + GOTO_SET_GAIN_IF_EN_AGC_HIGH, 0); + ad9361_spi_writef(spi, REG_FAST_CONFIG_2_SETTLING_DELAY, + GOTO_MAX_GAIN_OR_OPT_GAIN_IF_EN_AGC_HIGH, 0); + } + + reg = ilog2(ctrl->f_agc_power_measurement_duration_in_state5 / 16); + reg = clamp_t(uint32_t, reg, 0U, 15U); + ad9361_spi_writef(spi, REG_RX1_MANUAL_LPF_GAIN, + POWER_MEAS_IN_STATE_5(~0), reg); + ad9361_spi_writef(spi, REG_RX1_MANUAL_LMT_FULL_GAIN, + POWER_MEAS_IN_STATE_5_MSB, reg >> 3); + + return ad9361_gc_update(phy); +} + +/** + * Set the Aux DAC. + * @param phy The AD9361 state structure. + * @param dac The DAC. + * @param val_mV The value. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_auxdac_set(struct ad9361_rf_phy *phy, int32_t dac, + int32_t val_mV) +{ + struct spi_desc *spi = phy->spi; + uint32_t val, tmp; + + dev_dbg(&phy->spi->dev, "%s DAC%"PRId32" = %"PRId32" mV", __func__, dac, + val_mV); + + /* Disable DAC if val == 0, Ignored in ENSM Auto Mode */ + ad9361_spi_writef(spi, REG_AUXDAC_ENABLE_CTRL, + AUXDAC_MANUAL_BAR(dac), val_mV ? 0 : 1); + + if (val_mV < 306) + val_mV = 306; + + if (val_mV < 1888) { + val = ((val_mV - 306) * 1000) / 1469; /* Vref = 1V, Step = 2 */ + tmp = AUXDAC_1_VREF(0); + } else { + val = ((val_mV - 1761) * 1000) / 1512; /* Vref = 2.5V, Step = 2 */ + tmp = AUXDAC_1_VREF(3); + } + + val = clamp_t(uint32_t, val, 0, 1023); + + switch (dac) { + case 1: + ad9361_spi_write(spi, REG_AUXDAC_1_WORD, val >> 2); + ad9361_spi_write(spi, REG_AUXDAC_1_CONFIG, AUXDAC_1_WORD_LSB(val) | tmp); + phy->auxdac1_value = val_mV; + break; + case 2: + ad9361_spi_write(spi, REG_AUXDAC_2_WORD, val >> 2); + ad9361_spi_write(spi, REG_AUXDAC_2_CONFIG, AUXDAC_2_WORD_LSB(val) | tmp); + phy->auxdac2_value = val_mV; + break; + default: + return -EINVAL; + } + + return 0; +} + +/** + * Get the Aux DAC value. + * @param phy The AD9361 state structure. + * @param dac The DAC. + * @return The value in case of success, negative error code otherwise. + */ +int32_t ad9361_auxdac_get(struct ad9361_rf_phy *phy, int32_t dac) +{ + + switch (dac) { + case 1: + return phy->auxdac1_value; + case 2: + return phy->auxdac2_value; + default: + return -EINVAL; + } + + return 0; +} + +/** + * Setup the AuxDAC. + * @param phy The AD9361 state structure. + * @param ctrl Pointer to auxdac_control structure. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_auxdac_setup(struct ad9361_rf_phy *phy, + struct auxdac_control *ctrl) +{ + struct spi_desc *spi = phy->spi; + uint8_t tmp; + + dev_dbg(&phy->spi->dev, "%s", __func__); + + ad9361_auxdac_set(phy, 1, ctrl->dac1_default_value); + ad9361_auxdac_set(phy, 2, ctrl->dac2_default_value); + + tmp = ~(AUXDAC_AUTO_TX_BAR(ctrl->dac2_in_tx_en << 1 | ctrl->dac1_in_tx_en) | + AUXDAC_AUTO_RX_BAR(ctrl->dac2_in_rx_en << 1 | ctrl->dac1_in_rx_en) | + AUXDAC_INIT_BAR(ctrl->dac2_in_alert_en << 1 | ctrl->dac1_in_alert_en)); + + ad9361_spi_writef(spi, REG_AUXDAC_ENABLE_CTRL, + AUXDAC_AUTO_TX_BAR(~0) | + AUXDAC_AUTO_RX_BAR(~0) | + AUXDAC_INIT_BAR(~0), + tmp); /* Auto Control */ + + ad9361_spi_writef(spi, REG_EXTERNAL_LNA_CTRL, + AUXDAC_MANUAL_SELECT, ctrl->auxdac_manual_mode_en); + ad9361_spi_write(spi, REG_AUXDAC1_RX_DELAY, ctrl->dac1_rx_delay_us); + ad9361_spi_write(spi, REG_AUXDAC1_TX_DELAY, ctrl->dac1_tx_delay_us); + ad9361_spi_write(spi, REG_AUXDAC2_RX_DELAY, ctrl->dac2_rx_delay_us); + ad9361_spi_write(spi, REG_AUXDAC2_TX_DELAY, ctrl->dac2_tx_delay_us); + + return 0; +} + +/** + * Setup the AuxADC. + * @param phy The AD9361 state structure. + * @param ctrl The AuxADC settings. + * @param bbpll_freq The BBPLL frequency [Hz]. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_auxadc_setup(struct ad9361_rf_phy *phy, + struct auxadc_control *ctrl, + uint32_t bbpll_freq) +{ + struct spi_desc *spi = phy->spi; + uint32_t val; + + dev_dbg(&phy->spi->dev, "%s", __func__); + + val = DIV_ROUND_CLOSEST(ctrl->temp_time_inteval_ms * + (bbpll_freq / 1000UL), (1 << 29)); + + ad9361_spi_write(spi, REG_TEMP_OFFSET, ctrl->offset); + ad9361_spi_write(spi, REG_START_TEMP_READING, 0x00); + ad9361_spi_write(spi, REG_TEMP_SENSE2, + MEASUREMENT_TIME_INTERVAL(val) | + (ctrl->periodic_temp_measuremnt ? + TEMP_SENSE_PERIODIC_ENABLE : 0)); + ad9361_spi_write(spi, REG_TEMP_SENSOR_CONFIG, + TEMP_SENSOR_DECIMATION( + ilog2(ctrl->temp_sensor_decimation) - 8)); + ad9361_spi_write(spi, REG_AUXADC_CLOCK_DIVIDER, + bbpll_freq / ctrl->auxadc_clock_rate); + ad9361_spi_write(spi, REG_AUXADC_CONFIG, + AUX_ADC_DECIMATION( + ilog2(ctrl->auxadc_decimation) - 8)); + + return 0; +} + +/** + * Get the measured temperature of the device. + * @param phy The AD9361 state structure. + * @return The measured temperature of the device. + */ +int32_t ad9361_get_temp(struct ad9361_rf_phy *phy) +{ + uint32_t val; + + ad9361_spi_writef(phy->spi, REG_AUXADC_CONFIG, AUXADC_POWER_DOWN, 1); + val = ad9361_spi_read(phy->spi, REG_TEMPERATURE); + ad9361_spi_writef(phy->spi, REG_AUXADC_CONFIG, AUXADC_POWER_DOWN, 0); + + return DIV_ROUND_CLOSEST(val * 1000000, 1140); +} + +/** + * Get the Aux ADC value. + * @param phy The AD9361 state structure. + * @return The value in case of success, negative error code otherwise. + */ +int32_t ad9361_get_auxadc(struct ad9361_rf_phy *phy) +{ + uint8_t buf[2]; + + ad9361_spi_writef(phy->spi, REG_AUXADC_CONFIG, AUXADC_POWER_DOWN, 1); + ad9361_spi_readm(phy->spi, REG_AUXADC_LSB, buf, 2); + ad9361_spi_writef(phy->spi, REG_AUXADC_CONFIG, AUXADC_POWER_DOWN, 0); + + return (buf[1] << 4) | AUXADC_WORD_LSB(buf[0]); +} + +/** + * Setup the Control Output pins. + * @param phy The AD9361 state structure. + * @param ctrl The Control Output pins settings. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_ctrl_outs_setup(struct ad9361_rf_phy *phy, + struct ctrl_outs_control *ctrl) +{ + struct spi_desc *spi = phy->spi; + + dev_dbg(&phy->spi->dev, "%s", __func__); + + ad9361_spi_write(spi, REG_CTRL_OUTPUT_POINTER, ctrl->index); // Ctrl Out index + return ad9361_spi_write(spi, REG_CTRL_OUTPUT_ENABLE, + ctrl->en_mask); // Ctrl Out [7:0] output enable +} + +/** + * Setup the GPO pins. + * @param phy The AD9361 state structure. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_gpo_setup(struct ad9361_rf_phy *phy, + struct gpo_control *ctrl) +{ + struct spi_desc *spi = phy->spi; + + dev_dbg(&phy->spi->dev, "%s", __func__); + + ad9361_spi_write(spi, REG_AUTO_GPO, + GPO_ENABLE_AUTO_RX(ctrl->gpo0_slave_rx_en | + (ctrl->gpo1_slave_rx_en << 1) | + (ctrl->gpo2_slave_rx_en << 2) | + (ctrl->gpo3_slave_rx_en << 3)) | + GPO_ENABLE_AUTO_TX(ctrl->gpo0_slave_tx_en | + (ctrl->gpo1_slave_tx_en << 1) | + (ctrl->gpo2_slave_tx_en << 2) | + (ctrl->gpo3_slave_tx_en << 3))); + + ad9361_spi_write(spi, REG_GPO_FORCE_AND_INIT, + GPO_MANUAL_CTRL(ctrl->gpo_manual_mode_enable_mask) | + GPO_INIT_STATE(ctrl->gpo0_inactive_state_high_en | + (ctrl->gpo1_inactive_state_high_en << 1) | + (ctrl->gpo2_inactive_state_high_en << 2) | + (ctrl->gpo3_inactive_state_high_en << 3))); + + ad9361_spi_write(spi, REG_GPO0_RX_DELAY, ctrl->gpo0_rx_delay_us); + ad9361_spi_write(spi, REG_GPO0_TX_DELAY, ctrl->gpo0_tx_delay_us); + ad9361_spi_write(spi, REG_GPO1_RX_DELAY, ctrl->gpo1_rx_delay_us); + ad9361_spi_write(spi, REG_GPO1_TX_DELAY, ctrl->gpo1_tx_delay_us); + ad9361_spi_write(spi, REG_GPO2_RX_DELAY, ctrl->gpo2_rx_delay_us); + ad9361_spi_write(spi, REG_GPO2_TX_DELAY, ctrl->gpo2_tx_delay_us); + ad9361_spi_write(spi, REG_GPO3_RX_DELAY, ctrl->gpo3_rx_delay_us); + ad9361_spi_write(spi, REG_GPO3_TX_DELAY, ctrl->gpo3_tx_delay_us); + + /* + * GPO manual mode conflicts with automatic ENSM slave and eLNA mode + */ + ad9361_spi_writef(phy->spi, REG_EXTERNAL_LNA_CTRL, GPO_MANUAL_SELECT, + ctrl->gpo_manual_mode_en); + + return 0; +} + +/** + * Setup the RSSI. + * @param phy The AD9361 state structure. + * @param ctrl The RSSI settings. + * @param is_update True if update + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_rssi_setup(struct ad9361_rf_phy *phy, + struct rssi_control *ctrl, + bool is_update) +{ + struct spi_desc *spi = phy->spi; + uint32_t total_weight, weight[4], total_dur = 0, temp; + uint8_t dur_buf[4] = { 0 }; + int32_t val, ret, i, j = 0; + uint32_t rssi_delay; + uint32_t rssi_wait; + int32_t rssi_duration; + uint32_t rate; + + dev_dbg(&phy->spi->dev, "%s", __func__); + + if (ctrl->rssi_unit_is_rx_samples) { + if (is_update) + return 0; /* no update required */ + + rssi_delay = ctrl->rssi_delay; + rssi_wait = ctrl->rssi_wait; + rssi_duration = ctrl->rssi_duration; + } else { + /* update sample based on RX rate */ + rate = DIV_ROUND_CLOSEST( + clk_get_rate(phy, phy->ref_clk_scale[RX_SAMPL_CLK]), 1000); + /* units are in us */ + rssi_delay = DIV_ROUND_CLOSEST(ctrl->rssi_delay * rate, 1000); + rssi_wait = DIV_ROUND_CLOSEST(ctrl->rssi_wait * rate, 1000); + rssi_duration = DIV_ROUND_CLOSEST( + ctrl->rssi_duration * rate, 1000); + } + + if (ctrl->restart_mode == EN_AGC_PIN_IS_PULLED_HIGH) + rssi_delay = 0; + + rssi_delay = clamp(rssi_delay / 8, 0U, 255U); + rssi_wait = clamp(rssi_wait / 4, 0U, 255U); + + do { + for (i = 14; rssi_duration > 0 && i >= 0; i--) { + val = 1 << i; + if ((int64_t)rssi_duration >= val) { + dur_buf[j++] = i; + total_dur += val; + rssi_duration -= val; + break; + } + } + + } while (j < 4 && rssi_duration > 0); + + for (i = 0, total_weight = 0; i < 4; i++) { + if (i < j) + total_weight += weight[i] = + DIV_ROUND_CLOSEST(RSSI_MAX_WEIGHT * + (1 << dur_buf[i]), total_dur); + else + total_weight += weight[i] = 0; + } + + /* total of all weights must be 0xFF */ + val = total_weight - 0xFF; + weight[j - 1] -= val; + + ad9361_spi_write(spi, REG_MEASURE_DURATION_01, + (dur_buf[1] << 4) | dur_buf[0]); // RSSI Measurement Duration 0, 1 + ad9361_spi_write(spi, REG_MEASURE_DURATION_23, + (dur_buf[3] << 4) | dur_buf[2]); // RSSI Measurement Duration 2, 3 + ad9361_spi_write(spi, REG_RSSI_WEIGHT_0, + weight[0]); // RSSI Weighted Multiplier 0 + ad9361_spi_write(spi, REG_RSSI_WEIGHT_1, + weight[1]); // RSSI Weighted Multiplier 1 + ad9361_spi_write(spi, REG_RSSI_WEIGHT_2, + weight[2]); // RSSI Weighted Multiplier 2 + ad9361_spi_write(spi, REG_RSSI_WEIGHT_3, + weight[3]); // RSSI Weighted Multiplier 3 + ad9361_spi_write(spi, REG_RSSI_DELAY, rssi_delay); // RSSI Delay + ad9361_spi_write(spi, REG_RSSI_WAIT_TIME, rssi_wait); // RSSI Wait + + temp = RSSI_MODE_SELECT(ctrl->restart_mode); + if (ctrl->restart_mode == SPI_WRITE_TO_REGISTER) + temp |= START_RSSI_MEAS; + + if (rssi_duration == 0 && j == 1) /* Power of two */ + temp |= DEFAULT_RSSI_MEAS_MODE; + + ret = ad9361_spi_write(spi, REG_RSSI_CONFIG, temp); // RSSI Mode Select + + if (ret < 0) + dev_err(&phy->spi->dev, "Unable to write rssi config"); + + return 0; +} + +/** + * This function needs to be called whenever BBPLL changes. + * @param phy The AD9361 state structure. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_bb_clk_change_handler(struct ad9361_rf_phy *phy) +{ + int32_t ret; + + ret = ad9361_gc_update(phy); + ret |= ad9361_rssi_setup(phy, &phy->pdata->rssi_ctrl, true); + ret |= ad9361_auxadc_setup(phy, &phy->pdata->auxadc_ctrl, + clk_get_rate(phy, phy->ref_clk_scale[BBPLL_CLK])); + + return ret; +} + +/** + * Set the desired Enable State Machine (ENSM) state. + * @param phy The AD9361 state structure. + * @param ensm_state The ENSM state [ENSM_STATE_SLEEP_WAIT, ENSM_STATE_ALERT, + * ENSM_STATE_TX, ENSM_STATE_TX_FLUSH, ENSM_STATE_RX, + * ENSM_STATE_RX_FLUSH, ENSM_STATE_FDD, ENSM_STATE_FDD_FLUSH]. + * @param pinctrl Set true, will enable the ENSM pin control. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_ensm_set_state(struct ad9361_rf_phy *phy, uint8_t ensm_state, + bool pinctrl) +{ + struct spi_desc *spi = phy->spi; + int32_t rc = 0; + uint32_t val; + uint32_t tmp; + + dev_dbg(dev, "Device is in %x state, moving to %x", phy->curr_ensm_state, + ensm_state); + + + if (phy->curr_ensm_state == ENSM_STATE_SLEEP) { + ad9361_spi_write(spi, REG_CLOCK_ENABLE, + DIGITAL_POWER_UP | CLOCK_ENABLE_DFLT | BBPLL_ENABLE | + (phy->pdata->use_extclk ? XO_BYPASS : 0)); /* Enable Clocks */ + udelay(20); + ad9361_spi_write(spi, REG_ENSM_CONFIG_1, TO_ALERT | FORCE_ALERT_STATE); + ad9361_trx_vco_cal_control(phy, false, true); /* Enable VCO Cal */ + ad9361_trx_vco_cal_control(phy, true, true); + } + + val = (phy->pdata->ensm_pin_pulse_mode ? 0 : LEVEL_MODE) | + (pinctrl ? ENABLE_ENSM_PIN_CTRL : 0) | + (phy->txmon_tdd_en ? ENABLE_RX_DATA_PORT_FOR_CAL : 0) | + TO_ALERT; + + switch (ensm_state) { + case ENSM_STATE_TX: + val |= FORCE_TX_ON; + if (phy->pdata->fdd) + rc = -EINVAL; + else if (phy->curr_ensm_state != ENSM_STATE_ALERT) + rc = -EINVAL; + break; + case ENSM_STATE_RX: + val |= FORCE_RX_ON; + if (phy->pdata->fdd) + rc = -EINVAL; + else if (phy->curr_ensm_state != ENSM_STATE_ALERT) + rc = -EINVAL; + break; + case ENSM_STATE_FDD: + val |= FORCE_TX_ON; + if (!phy->pdata->fdd) + rc = -EINVAL; + break; + case ENSM_STATE_ALERT: + val &= ~(FORCE_TX_ON | FORCE_RX_ON); + val |= TO_ALERT | FORCE_ALERT_STATE; + break; + case ENSM_STATE_SLEEP_WAIT: + break; + case ENSM_STATE_SLEEP: + ad9361_trx_vco_cal_control(phy, false, false); /* Disable VCO Cal */ + ad9361_trx_vco_cal_control(phy, true, false); + ad9361_spi_write(spi, REG_ENSM_CONFIG_1, 0); /* Clear To Alert */ + ad9361_spi_write(spi, REG_ENSM_CONFIG_1, + phy->pdata->fdd ? FORCE_TX_ON : FORCE_RX_ON); + /* Delay Flush Time 384 ADC clock cycles */ + udelay(384000000UL / clk_get_rate(phy, phy->ref_clk_scale[ADC_CLK])); + ad9361_spi_write(spi, REG_ENSM_CONFIG_1, 0); /* Move to Wait*/ + udelay(1); /* Wait for ENSM settle */ + ad9361_spi_write(spi, REG_CLOCK_ENABLE, + (phy->pdata->use_extclk ? XO_BYPASS : 0)); /* Turn off all clocks */ + phy->curr_ensm_state = ensm_state; + return 0; + + default: + dev_err(dev, "No handling for forcing %d ensm state", + ensm_state); + goto out; + } + + if (rc) { + if ((phy->curr_ensm_state != ENSM_STATE_ALERT) + && (val & (FORCE_RX_ON | FORCE_TX_ON))) { + uint32_t val2 = val; + + val2 &= ~(FORCE_TX_ON | FORCE_RX_ON); + val2 |= TO_ALERT | FORCE_ALERT_STATE; + ad9361_spi_write(spi, REG_ENSM_CONFIG_1, val2); + + ad9361_check_cal_done(phy, REG_STATE, ENSM_STATE(~0), ENSM_STATE_ALERT); + } else { + dev_err(dev, "Invalid ENSM state transition in %s mode", + phy->pdata->fdd ? "FDD" : "TDD"); + goto out; + } + } + + if (!phy->pdata->fdd && !pinctrl && !phy->pdata->tdd_use_dual_synth && + (ensm_state == ENSM_STATE_TX || ensm_state == ENSM_STATE_RX)) { + uint32_t reg, check; + + if (ensm_state == ENSM_STATE_TX) { + reg = REG_TX_CP_OVERRANGE_VCO_LOCK; + check = !(phy->cached_synth_pd[0] & + TX_SYNTH_VCO_POWER_DOWN); + } else { + reg = REG_RX_CP_OVERRANGE_VCO_LOCK; + check = !(phy->cached_synth_pd[1] & + RX_SYNTH_VCO_POWER_DOWN); + } + + ad9361_spi_writef(phy->spi, REG_ENSM_CONFIG_2, + TXNRX_SPI_CTRL, ensm_state == ENSM_STATE_TX); + + if (check) + ad9361_check_cal_done(phy, reg, VCO_LOCK, 1); + } + + rc = ad9361_spi_write(spi, REG_ENSM_CONFIG_1, val); + if (rc) + dev_err(dev, "Failed to restore state"); + + if ((val & FORCE_RX_ON) && + (phy->agc_mode[0] == RF_GAIN_MGC || + phy->agc_mode[1] == RF_GAIN_MGC)) { + tmp = ad9361_spi_read(spi, REG_SMALL_LMT_OVERLOAD_THRESH); + ad9361_spi_write(spi, REG_SMALL_LMT_OVERLOAD_THRESH, + (tmp & SMALL_LMT_OVERLOAD_THRESH(~0)) | + (phy->agc_mode[0] == RF_GAIN_MGC ? FORCE_PD_RESET_RX1 : 0) | + (phy->agc_mode[1] == RF_GAIN_MGC ? FORCE_PD_RESET_RX2 : 0)); + ad9361_spi_write(spi, REG_SMALL_LMT_OVERLOAD_THRESH, + tmp & SMALL_LMT_OVERLOAD_THRESH(~0)); + } + + phy->curr_ensm_state = ensm_state; + +out: + return rc; + +} + +/** + * Check if at least one of the clock rates is equal to the DATA_CLK (lvds) rate. + * @param phy The AD9361 state structure. + * @param rx_path_clks RX path rates buffer. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_validate_trx_clock_chain(struct ad9361_rf_phy *phy, + uint32_t *rx_path_clks, uint32_t *tx_path_clks) +{ + static const uint32_t max_rx_rates[] = {MAX_BBPLL_FREQ, MAX_ADC_CLK, + MAX_RX_HB3, MAX_RX_HB2, MAX_RX_HB1, MAX_BASEBAND_RATE + }; + static const uint32_t max_tx_rates[] = {MAX_BBPLL_FREQ, MAX_DAC_CLK, + MAX_TX_HB3, MAX_TX_HB2, MAX_TX_HB1, MAX_BASEBAND_RATE + }; + uint32_t i; + uint32_t data_clk; + + data_clk = (phy->pdata->rx2tx2 ? 4 : 2) / + ((phy->pdata->port_ctrl.pp_conf[2] & LVDS_MODE) ? 1 : 2) * + rx_path_clks[RX_SAMPL_FREQ]; + + /* CMOS Mode */ + if (!(phy->pdata->port_ctrl.pp_conf[2] & LVDS_MODE) && + (data_clk > MAX_BASEBAND_RATE)) { + dev_err(&phy->spi->dev, + "%s: Failed CMOS MODE DATA_CLK > 61.44MSPS", __func__); + return -EINVAL; + } + + /* Validate MAX PLL, ADC, DAC and HB filter rates */ + for (i = 0; i < ARRAY_SIZE(max_rx_rates); i++) { + if (rx_path_clks[i] > max_rx_rates[i]) { + dev_err(&phy->spi->dev, + "%s: Failed RX max rate check (%"PRIu32" > %"PRIu32")", + __func__, rx_path_clks[i], max_rx_rates[i]); + return -EINVAL; + } + + if (tx_path_clks[i] > max_tx_rates[i]) { + dev_err(&phy->spi->dev, + "%s: Failed TX max rate check (%"PRIu32" > %"PRIu32")", + __func__, tx_path_clks[i], max_tx_rates[i]); + return -EINVAL; + } + } + + /* Validate that DATA_CLK exist within the clock chain */ + for (i = 1; i <= 3; i++) { + if (diff_abs(rx_path_clks[ADC_FREQ] / i, data_clk) < 4) + return 0; + } + + for (i = 1; i <= 4; i++) { + if (diff_abs((rx_path_clks[R2_FREQ] >> i), data_clk) < 4) + return 0; + } + + dev_err(&phy->spi->dev, "%s: Failed - at least one of the clock rates" + " must be equal to the DATA_CLK (lvds) rate", __func__); + + return -EINVAL; +} + +/** + * Set the RX and TX path rates. + * @param phy The AD9361 state structure. + * @param rx_path_clks RX path rates buffer. + * @param tx_path_clks TX path rates buffer. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_set_trx_clock_chain(struct ad9361_rf_phy *phy, + uint32_t *rx_path_clks, + uint32_t *tx_path_clks) +{ + int32_t ret, i, j, n; + + dev_dbg(&phy->spi->dev, "%s", __func__); + + if (!rx_path_clks || !tx_path_clks) + return -EINVAL; + + dev_dbg(&phy->spi->dev, + "%s: %"PRIu32" %"PRIu32" %"PRIu32" %"PRIu32" %"PRIu32" %"PRIu32, + __func__, rx_path_clks[BBPLL_FREQ], rx_path_clks[ADC_FREQ], + rx_path_clks[R2_FREQ], rx_path_clks[R1_FREQ], + rx_path_clks[CLKRF_FREQ], rx_path_clks[RX_SAMPL_FREQ]); + + dev_dbg(&phy->spi->dev, + "%s: %"PRIu32" %"PRIu32" %"PRIu32" %"PRIu32" %"PRIu32" %"PRIu32, + __func__, tx_path_clks[BBPLL_FREQ], tx_path_clks[ADC_FREQ], + tx_path_clks[R2_FREQ], tx_path_clks[R1_FREQ], + tx_path_clks[CLKRF_FREQ], tx_path_clks[RX_SAMPL_FREQ]); + + ret = ad9361_validate_trx_clock_chain(phy, rx_path_clks, tx_path_clks); + if (ret < 0) + return ret; + + ret = clk_set_rate(phy, phy->ref_clk_scale[BBPLL_CLK], + rx_path_clks[BBPLL_FREQ]); + if (ret < 0) + return ret; + + phy->current_rx_path_clks[BBPLL_FREQ] = rx_path_clks[BBPLL_FREQ]; + + for (i = ADC_CLK, j = DAC_CLK, n = ADC_FREQ; + i <= RX_SAMPL_CLK; i++, j++, n++) { + ret = clk_set_rate(phy, phy->ref_clk_scale[i], rx_path_clks[n]); + if (ret < 0) { + dev_err(dev, "Failed to set BB ref clock rate (%"PRId32")", + ret); + return ret; + } + phy->current_rx_path_clks[n] = rx_path_clks[n]; + ret = clk_set_rate(phy, phy->ref_clk_scale[j], tx_path_clks[n]); + if (ret < 0) { + dev_err(dev, "Failed to set BB ref clock rate (%"PRId32")", + ret); + return ret; + } + phy->current_tx_path_clks[n] = tx_path_clks[n]; + } + + /* + * Workaround for clock framework since clocks don't change we + * manually need to enable the filter + */ + + if (phy->rx_fir_dec == 1 || phy->bypass_rx_fir) { + ad9361_spi_writef(phy->spi, REG_RX_ENABLE_FILTER_CTRL, + RX_FIR_ENABLE_DECIMATION(~0), !phy->bypass_rx_fir); + } + + if (phy->tx_fir_int == 1 || phy->bypass_tx_fir) { + ad9361_spi_writef(phy->spi, REG_TX_ENABLE_FILTER_CTRL, + TX_FIR_ENABLE_INTERPOLATION(~0), !phy->bypass_tx_fir); + } + + /* The FIR filter once enabled causes the interface timing to change. + * It's typically not a problem if the timing margin is big enough. + * However at 61.44 MSPS it causes problems on some systems. + * So we always run the digital tune in case the filter is enabled. + * If it is disabled we restore the values from the initial calibration. + */ + + if (!phy->pdata->dig_interface_tune_fir_disable && + !(phy->bypass_tx_fir && phy->bypass_rx_fir)) + ret = ad9361_dig_tune(phy, 0, SKIP_STORE_RESULT); + + return ad9361_bb_clk_change_handler(phy); +} + +/** + * Get the RX and TX path rates. + * @param phy The AD9361 state structure. + * @param rx_path_clks RX path rates buffer. + * @param tx_path_clks TX path rates buffer. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_trx_clock_chain(struct ad9361_rf_phy *phy, + uint32_t *rx_path_clks, + uint32_t *tx_path_clks) +{ + int32_t i, j, n; + uint32_t bbpll_freq; + + if (!rx_path_clks && !tx_path_clks) + return -EINVAL; + + bbpll_freq = clk_get_rate(phy, phy->ref_clk_scale[BBPLL_CLK]); + + if (rx_path_clks) + rx_path_clks[BBPLL_FREQ] = bbpll_freq; + + if (tx_path_clks) + tx_path_clks[BBPLL_FREQ] = bbpll_freq; + + for (i = ADC_CLK, j = DAC_CLK, n = ADC_FREQ; + i <= RX_SAMPL_CLK; i++, j++, n++) { + if (rx_path_clks) + rx_path_clks[n] = clk_get_rate(phy, phy->ref_clk_scale[i]); + if (tx_path_clks) + tx_path_clks[n] = clk_get_rate(phy, phy->ref_clk_scale[j]); + } + + return 0; +} + +/** + * Calculate the RX and TX path rates to obtain the desired sample rate. + * @param phy The AD9361 state structure. + * @param tx_sample_rate The desired sample rate. + * @param rate_gov The rate governor option. + * @param rx_path_clks RX path rates buffer. + * @param tx_path_clks TX path rates buffer. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_calculate_rf_clock_chain(struct ad9361_rf_phy *phy, + uint32_t tx_sample_rate, + uint32_t rate_gov, + uint32_t *rx_path_clks, + uint32_t *tx_path_clks) +{ + uint32_t clktf, clkrf, adc_rate = 0, dac_rate = 0; + uint64_t bbpll_rate; + int32_t i, index_rx = -1, index_tx = -1, tmp; + uint32_t div, tx_intdec, rx_intdec, recursion = 1; + const int8_t clk_dividers[][4] = { + { 12, 3, 2, 2 }, + { 8, 2, 2, 2 }, + { 6, 3, 1, 2 }, + { 4, 2, 2, 1 }, + { 3, 3, 1, 1 }, + { 2, 2, 1, 1 }, + { 1, 1, 1, 1 }, + }; + + if (phy->bypass_rx_fir) + rx_intdec = 1; + else + rx_intdec = phy->rx_fir_dec; + + if (phy->bypass_tx_fir) + tx_intdec = 1; + else + tx_intdec = phy->tx_fir_int; + + if ((rate_gov == 1) && ((rx_intdec * tx_sample_rate * 8) < MIN_ADC_CLK)) { + recursion = 0; + rate_gov = 0; + } + + dev_dbg(&phy->spi->dev, + "%s: requested rate %"PRIu32" TXFIR int %"PRIu32" RXFIR dec %"PRIu32" mode %s", + __func__, tx_sample_rate, tx_intdec, rx_intdec, + rate_gov ? "Nominal" : "Highest OSR"); + + if (tx_sample_rate > MAX_BASEBAND_RATE) + return -EINVAL; + + clktf = tx_sample_rate * tx_intdec; + clkrf = tx_sample_rate * rx_intdec * (phy->rx_eq_2tx ? 2 : 1); + + for (i = rate_gov; i < 7; i++) { + adc_rate = clkrf * clk_dividers[i][0]; + dac_rate = clktf * clk_dividers[i][0]; + + if ((adc_rate <= MAX_ADC_CLK) && (adc_rate >= MIN_ADC_CLK)) { + + + if (dac_rate > adc_rate) + tmp = (dac_rate / adc_rate) * -1; + else + tmp = adc_rate / dac_rate; + + if (adc_rate <= MAX_DAC_CLK) { + index_rx = i; + index_tx = i - ((tmp == 1) ? 0 : tmp); + dac_rate = adc_rate; /* ADC_CLK */ + break; + } else { + dac_rate = adc_rate / 2; /* ADC_CLK/2 */ + index_rx = i; + + if (i == 4 && tmp >= 0) + index_tx = 7; /* STOP: 3/2 != 1 */ + else + index_tx = i + ((i == 5 && tmp >= 0) ? 1 : 2) - + ((tmp == 1) ? 0 : tmp); + + break; + } + } + } + + if ((index_tx < 0 || index_tx > 6 || index_rx < 0 || index_rx > 6) + && rate_gov < 7 && recursion) { + return ad9361_calculate_rf_clock_chain(phy, tx_sample_rate, + ++rate_gov, rx_path_clks, tx_path_clks); + } else if ((index_tx < 0 || index_tx > 6 || index_rx < 0 || index_rx > 6)) { + dev_err(&phy->spi->dev, "%s: Failed to find suitable dividers: %s", + __func__, (adc_rate < MIN_ADC_CLK) ? "ADC clock below limit" : + "BBPLL rate above limit"); + + return -EINVAL; + } + + /* Calculate target BBPLL rate */ + div = MAX_BBPLL_DIV; + + do { + bbpll_rate = (uint64_t)adc_rate * div; + div >>= 1; + + } while ((bbpll_rate > MAX_BBPLL_FREQ) && (div >= MIN_BBPLL_DIV)); + + rx_path_clks[BBPLL_FREQ] = bbpll_rate; + rx_path_clks[ADC_FREQ] = adc_rate; + rx_path_clks[R2_FREQ] = rx_path_clks[ADC_FREQ] / clk_dividers[index_rx][1]; + rx_path_clks[R1_FREQ] = rx_path_clks[R2_FREQ] / clk_dividers[index_rx][2]; + rx_path_clks[CLKRF_FREQ] = rx_path_clks[R1_FREQ] / clk_dividers[index_rx][3]; + rx_path_clks[RX_SAMPL_FREQ] = rx_path_clks[CLKRF_FREQ] / rx_intdec; + + tx_path_clks[BBPLL_FREQ] = bbpll_rate; + tx_path_clks[DAC_FREQ] = dac_rate; + tx_path_clks[T2_FREQ] = tx_path_clks[DAC_FREQ] / clk_dividers[index_tx][1]; + tx_path_clks[T1_FREQ] = tx_path_clks[T2_FREQ] / clk_dividers[index_tx][2]; + tx_path_clks[CLKTF_FREQ] = tx_path_clks[T1_FREQ] / clk_dividers[index_tx][3]; + tx_path_clks[TX_SAMPL_FREQ] = tx_path_clks[CLKTF_FREQ] / tx_intdec; + + return 0; +} + +/** + * Set the desired sample rate. + * @param phy The AD9361 state structure. + * @param freq The desired sample rate. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_set_trx_clock_chain_freq(struct ad9361_rf_phy *phy, + uint32_t freq) +{ + uint32_t rx[6], tx[6]; + int32_t ret; + + ret = ad9361_calculate_rf_clock_chain(phy, freq, + phy->rate_governor, rx, tx); + if (ret < 0) + return ret; + return ad9361_set_trx_clock_chain(phy, rx, tx); +} + +/** + * Internal ENSM mode options helper function. + * @param phy The AD9361 state structure. + * @param fdd + * @param pinctrl + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_set_ensm_mode(struct ad9361_rf_phy *phy, bool fdd, bool pinctrl) +{ + struct ad9361_phy_platform_data *pd = phy->pdata; + int32_t ret; + uint32_t val = 0; + + ad9361_spi_write(phy->spi, REG_ENSM_MODE, fdd ? FDD_MODE : 0); + + val = ad9361_spi_read(phy->spi, REG_ENSM_CONFIG_2); + val &= POWER_DOWN_RX_SYNTH | POWER_DOWN_TX_SYNTH | + RX_SYNTH_READY_MASK | TX_SYNTH_READY_MASK; + + if (fdd) + ret = ad9361_spi_write(phy->spi, REG_ENSM_CONFIG_2, + val | DUAL_SYNTH_MODE | + (pd->fdd_independent_mode ? FDD_EXTERNAL_CTRL_ENABLE : 0)); + else + ret = ad9361_spi_write(phy->spi, REG_ENSM_CONFIG_2, val | + (pd->tdd_use_dual_synth ? DUAL_SYNTH_MODE : 0) | + (pd->tdd_use_dual_synth ? 0 : + (pinctrl ? SYNTH_ENABLE_PIN_CTRL_MODE : 0))); + + return ret; +} + +/** + * Fastlock read value. + * @param spi + * @param tx + * @param profile + * @param word + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_fastlock_readval(struct spi_desc *spi, bool tx, + uint32_t profile, uint32_t word) +{ + uint32_t offs = 0; + + if (tx) + offs = REG_TX_FAST_LOCK_SETUP - REG_RX_FAST_LOCK_SETUP; + + ad9361_spi_write(spi, REG_RX_FAST_LOCK_PROGRAM_ADDR + offs, + RX_FAST_LOCK_PROFILE_ADDR(profile) | + RX_FAST_LOCK_PROFILE_WORD(word)); + + return ad9361_spi_read(spi, REG_RX_FAST_LOCK_PROGRAM_READ + offs); +} + +/** + * Fastlock write value. + * @param spi + * @param tx + * @param profile + * @param word + * @param val + * @param last + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_fastlock_writeval(struct spi_desc *spi, bool tx, + uint32_t profile, uint32_t word, uint8_t val, bool last) +{ + uint32_t offs = 0; + int32_t ret; + + if (tx) + offs = REG_TX_FAST_LOCK_SETUP - REG_RX_FAST_LOCK_SETUP; + + ret = ad9361_spi_write(spi, REG_RX_FAST_LOCK_PROGRAM_ADDR + offs, + RX_FAST_LOCK_PROFILE_ADDR(profile) | + RX_FAST_LOCK_PROFILE_WORD(word)); + ret |= ad9361_spi_write(spi, REG_RX_FAST_LOCK_PROGRAM_DATA + offs, val); + ret |= ad9361_spi_write(spi, REG_RX_FAST_LOCK_PROGRAM_CTRL + offs, + RX_FAST_LOCK_PROGRAM_WRITE | + RX_FAST_LOCK_PROGRAM_CLOCK_ENABLE); + + if (last) /* Stop Clocks */ + ret |= ad9361_spi_write(spi, + REG_RX_FAST_LOCK_PROGRAM_CTRL + offs, 0); + + return ret; +} + +/** + * Fastlock load values. + * @param phy The AD9361 state structure. + * @param tx + * @param profile + * @param values + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_fastlock_load(struct ad9361_rf_phy *phy, bool tx, + uint32_t profile, uint8_t *values) +{ + uint32_t offs = 0; + int32_t i, ret = 0; + uint8_t buf[4]; + + dev_dbg(&phy->spi->dev, "%s: %s Profile %"PRIu32":", + __func__, tx ? "TX" : "RX", profile); + + if (tx) + offs = REG_TX_FAST_LOCK_SETUP - REG_RX_FAST_LOCK_SETUP; + + buf[0] = values[0]; + buf[1] = RX_FAST_LOCK_PROFILE_ADDR(profile) | RX_FAST_LOCK_PROFILE_WORD(0); + ad9361_spi_writem(phy->spi, REG_RX_FAST_LOCK_PROGRAM_DATA + offs, buf, 2); + + for (i = 1; i < RX_FAST_LOCK_CONFIG_WORD_NUM; i++) { + buf[0] = RX_FAST_LOCK_PROGRAM_WRITE | RX_FAST_LOCK_PROGRAM_CLOCK_ENABLE; + buf[1] = 0; + buf[2] = values[i]; + buf[3] = RX_FAST_LOCK_PROFILE_ADDR(profile) | RX_FAST_LOCK_PROFILE_WORD(i); + ad9361_spi_writem(phy->spi, REG_RX_FAST_LOCK_PROGRAM_CTRL + offs, buf, 4); + } + + ad9361_spi_write(phy->spi, REG_RX_FAST_LOCK_PROGRAM_CTRL + offs, + RX_FAST_LOCK_PROGRAM_WRITE | RX_FAST_LOCK_PROGRAM_CLOCK_ENABLE); + ad9361_spi_write(phy->spi, REG_RX_FAST_LOCK_PROGRAM_CTRL + offs, 0); + + phy->fastlock.entry[tx][profile].flags = FASTLOOK_INIT; + phy->fastlock.entry[tx][profile].alc_orig = values[15]; + phy->fastlock.entry[tx][profile].alc_written = values[15]; + + return ret; +} + +/** + * Fastlock store. + * @param phy The AD9361 state structure. + * @param tx + * @param profile + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_fastlock_store(struct ad9361_rf_phy *phy, bool tx, + uint32_t profile) +{ + struct spi_desc *spi = phy->spi; + uint8_t val[16]; + uint32_t offs = 0, x, y; + + dev_dbg(&phy->spi->dev, "%s: %s Profile %"PRIu32":", + __func__, tx ? "TX" : "RX", profile); + + if (tx) + offs = REG_TX_FAST_LOCK_SETUP - REG_RX_FAST_LOCK_SETUP; + + val[0] = ad9361_spi_read(spi, REG_RX_INTEGER_BYTE_0 + offs); + val[1] = ad9361_spi_read(spi, REG_RX_INTEGER_BYTE_1 + offs); + val[2] = ad9361_spi_read(spi, REG_RX_FRACT_BYTE_0 + offs); + val[3] = ad9361_spi_read(spi, REG_RX_FRACT_BYTE_1 + offs); + val[4] = ad9361_spi_read(spi, REG_RX_FRACT_BYTE_2 + offs); + + x = ad9361_spi_readf(spi, REG_RX_VCO_BIAS_1 + offs, VCO_BIAS_REF(~0)); + y = ad9361_spi_readf(spi, REG_RX_ALC_VARACTOR + offs, VCO_VARACTOR(~0)); + val[5] = (x << 4) | y; + + x = ad9361_spi_readf(spi, REG_RX_VCO_BIAS_1 + offs, VCO_BIAS_TCF(~0)); + y = ad9361_spi_readf(spi, REG_RX_CP_CURRENT + offs, CHARGE_PUMP_CURRENT(~0)); + /* Wide BW option: N = 1 + * Set init and steady state values to the same - let user space handle it + */ + val[6] = (x << 3) | y; + val[7] = y; + + x = ad9361_spi_readf(spi, REG_RX_LOOP_FILTER_3 + offs, LOOP_FILTER_R3(~0)); + val[8] = (x << 4) | x; + + x = ad9361_spi_readf(spi, REG_RX_LOOP_FILTER_2 + offs, LOOP_FILTER_C3(~0)); + val[9] = (x << 4) | x; + + x = ad9361_spi_readf(spi, REG_RX_LOOP_FILTER_1 + offs, LOOP_FILTER_C1(~0)); + y = ad9361_spi_readf(spi, REG_RX_LOOP_FILTER_1 + offs, LOOP_FILTER_C2(~0)); + val[10] = (x << 4) | y; + + x = ad9361_spi_readf(spi, REG_RX_LOOP_FILTER_2 + offs, LOOP_FILTER_R1(~0)); + val[11] = (x << 4) | x; + + x = ad9361_spi_readf(spi, REG_RX_VCO_VARACTOR_CTRL_0 + offs, + VCO_VARACTOR_REFERENCE_TCF(~0)); + y = ad9361_spi_readf(spi, REG_RFPLL_DIVIDERS, + tx ? TX_VCO_DIVIDER(~0) : RX_VCO_DIVIDER(~0)); + val[12] = (x << 4) | y; + + x = ad9361_spi_readf(spi, REG_RX_FORCE_VCO_TUNE_1 + offs, VCO_CAL_OFFSET(~0)); + y = ad9361_spi_readf(spi, REG_RX_VCO_VARACTOR_CTRL_1 + offs, + VCO_VARACTOR_REFERENCE(~0)); + val[13] = (x << 4) | y; + + val[14] = ad9361_spi_read(spi, REG_RX_FORCE_VCO_TUNE_0 + offs); + + x = ad9361_spi_readf(spi, REG_RX_FORCE_ALC + offs, FORCE_ALC_WORD(~0)); + y = ad9361_spi_readf(spi, REG_RX_FORCE_VCO_TUNE_1 + offs, FORCE_VCO_TUNE); + val[15] = (x << 1) | y; + + return ad9361_fastlock_load(phy, tx, profile, val); +} + +/** + * Fastlock prepare. + * @param phy The AD9361 state structure. + * @param tx + * @param profile + * @param prepare + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_fastlock_prepare(struct ad9361_rf_phy *phy, bool tx, + uint32_t profile, bool prepare) +{ + uint32_t offs, ready_mask; + bool is_prepared; + + dev_dbg(&phy->spi->dev, "%s: %s Profile %"PRIu32": %s", + __func__, tx ? "TX" : "RX", profile, + prepare ? "Prepare" : "Un-Prepare"); + + if (tx) { + offs = REG_TX_FAST_LOCK_SETUP - REG_RX_FAST_LOCK_SETUP; + ready_mask = TX_SYNTH_READY_MASK; + } else { + offs = 0; + ready_mask = RX_SYNTH_READY_MASK; + } + + is_prepared = !!phy->fastlock.current_profile[tx]; + + if (prepare && !is_prepared) { + ad9361_spi_write(phy->spi, + REG_RX_FAST_LOCK_SETUP_INIT_DELAY + offs, + (tx ? phy->pdata->tx_fastlock_delay_ns : + phy->pdata->rx_fastlock_delay_ns) / 250); + ad9361_spi_write(phy->spi, REG_RX_FAST_LOCK_SETUP + offs, + RX_FAST_LOCK_PROFILE(profile) | + RX_FAST_LOCK_MODE_ENABLE); + ad9361_spi_write(phy->spi, REG_RX_FAST_LOCK_PROGRAM_CTRL + offs, + 0); + + ad9361_spi_writef(phy->spi, REG_ENSM_CONFIG_2, ready_mask, 1); + ad9361_trx_vco_cal_control(phy, tx, false); + } else if (!prepare && is_prepared) { + ad9361_spi_write(phy->spi, REG_RX_FAST_LOCK_SETUP + offs, 0); + + /* Workaround: Exiting Fastlock Mode */ + ad9361_spi_writef(phy->spi, REG_RX_FORCE_ALC + offs, FORCE_ALC_ENABLE, 1); + ad9361_spi_writef(phy->spi, REG_RX_FORCE_VCO_TUNE_1 + offs, FORCE_VCO_TUNE, 1); + ad9361_spi_writef(phy->spi, REG_RX_FORCE_ALC + offs, FORCE_ALC_ENABLE, 0); + ad9361_spi_writef(phy->spi, REG_RX_FORCE_VCO_TUNE_1 + offs, FORCE_VCO_TUNE, 0); + + ad9361_trx_vco_cal_control(phy, tx, true); + ad9361_spi_writef(phy->spi, REG_ENSM_CONFIG_2, ready_mask, 0); + + phy->fastlock.current_profile[tx] = 0; + } + + return 0; +} + +/** + * Fastlock recall. + * @param phy The AD9361 state structure. + * @param tx + * @param profile + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_fastlock_recall(struct ad9361_rf_phy *phy, bool tx, + uint32_t profile) +{ + uint32_t offs = 0; + uint8_t curr, _new, orig, current_profile; + + dev_dbg(&phy->spi->dev, "%s: %s Profile %"PRIu32":", + __func__, tx ? "TX" : "RX", profile); + + if (tx) + offs = REG_TX_FAST_LOCK_SETUP - REG_RX_FAST_LOCK_SETUP; + + if (phy->fastlock.entry[tx][profile].flags != FASTLOOK_INIT) + return -EINVAL; + + /* Workaround: Lock problem with same ALC word */ + + current_profile = phy->fastlock.current_profile[tx]; + _new = phy->fastlock.entry[tx][profile].alc_written; + + if (current_profile == 0) + curr = ad9361_spi_readf(phy->spi, REG_RX_FORCE_ALC + offs, + FORCE_ALC_WORD(~0)) << 1; + else + curr = phy->fastlock.entry[tx][current_profile - 1].alc_written; + + if ((curr >> 1) == (_new >> 1)) { + orig = phy->fastlock.entry[tx][profile].alc_orig; + + if ((orig >> 1) == (_new >> 1)) + phy->fastlock.entry[tx][profile].alc_written += 2; + else + phy->fastlock.entry[tx][profile].alc_written = orig; + + ad9361_fastlock_writeval(phy->spi, tx, profile, 0xF, + phy->fastlock.entry[tx][profile].alc_written, true); + } + + ad9361_fastlock_prepare(phy, tx, profile, true); + phy->fastlock.current_profile[tx] = profile + 1; + + return ad9361_spi_write(phy->spi, REG_RX_FAST_LOCK_SETUP + offs, + RX_FAST_LOCK_PROFILE(profile) | + (phy->pdata->trx_fastlock_pinctrl_en[tx] ? + RX_FAST_LOCK_PROFILE_PIN_SELECT : 0) | + RX_FAST_LOCK_MODE_ENABLE); +} + +/** + * Fastlock save. + * @param phy The AD9361 state structure. + * @param tx + * @param profile + * @param values + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_fastlock_save(struct ad9361_rf_phy *phy, bool tx, + uint32_t profile, uint8_t *values) +{ + int32_t i; + + dev_dbg(&phy->spi->dev, "%s: %s Profile %"PRIu32":", + __func__, tx ? "TX" : "RX", profile); + + for (i = 0; i < RX_FAST_LOCK_CONFIG_WORD_NUM; i++) + values[i] = ad9361_fastlock_readval(phy->spi, tx, profile, i); + + return 0; +} + +/** + * Multi Chip Sync (MCS) config. + * @param phy The AD9361 state structure. + * @param step MCS step. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_mcs(struct ad9361_rf_phy *phy, int32_t step) +{ + int32_t mcs_mask = MCS_RF_ENABLE | MCS_BBPLL_ENABLE | + MCS_DIGITAL_CLK_ENABLE | MCS_BB_ENABLE; + + dev_dbg(&phy->spi->dev, "%s: MCS step %"PRId32, __func__, step); + + switch (step) { + case 1: + /* REVIST: + * POWER_DOWN_TRX_SYNTH and MCS_RF_ENABLE somehow conflict + */ + ad9361_spi_writef(phy->spi, REG_ENSM_CONFIG_2, + POWER_DOWN_TX_SYNTH | POWER_DOWN_RX_SYNTH, 0); + + ad9361_spi_writef(phy->spi, REG_MULTICHIP_SYNC_AND_TX_MON_CTRL, + mcs_mask, MCS_BB_ENABLE | MCS_BBPLL_ENABLE | MCS_RF_ENABLE); + ad9361_spi_writef(phy->spi, REG_CP_BLEED_CURRENT, + MCS_REFCLK_SCALE_EN, 1); + break; + case 2: + if(!phy->gpio_desc_sync) + break; + /* + * NOTE: This is not a regular GPIO - + * HDL ensures Multi-chip Synchronization SYNC_IN Pulse Timing + * relative to rising and falling edge of REF_CLK + */ + gpio_set_value(phy->gpio_desc_sync, 1); + gpio_set_value(phy->gpio_desc_sync, 0); + break; + case 3: + ad9361_spi_writef(phy->spi, REG_MULTICHIP_SYNC_AND_TX_MON_CTRL, + mcs_mask, MCS_BB_ENABLE | MCS_DIGITAL_CLK_ENABLE | MCS_RF_ENABLE); + break; + case 4: + if(!phy->gpio_desc_sync) + break; + gpio_set_value(phy->gpio_desc_sync, 1); + gpio_set_value(phy->gpio_desc_sync, 0); + break; + case 5: + ad9361_spi_writef(phy->spi, REG_MULTICHIP_SYNC_AND_TX_MON_CTRL, + mcs_mask, MCS_RF_ENABLE); + break; + } + + return 0; +} + +/** + * Clear state. + * @param phy The AD9361 state structure. + * @return None. + */ +void ad9361_clear_state(struct ad9361_rf_phy *phy) +{ + phy->current_table = NO_GAIN_TABLE; + phy->bypass_tx_fir = true; + phy->bypass_rx_fir = true; + phy->rate_governor = 1; + phy->rfdc_track_en = true; + phy->bbdc_track_en = true; + phy->quad_track_en = true; + phy->prev_ensm_state = 0; + phy->curr_ensm_state = 0; + phy->auto_cal_en = false; + phy->manual_tx_quad_cal_en = false; + phy->last_tx_quad_cal_freq = 0; + phy->flags = 0; + phy->current_rx_bw_Hz = 0; + phy->current_tx_bw_Hz = 0; + phy->rxbbf_div = 0; + phy->tx_fir_int = 0; + phy->tx_fir_ntaps = 0; + phy->rx_fir_dec = 0; + phy->rx_fir_ntaps = 0; + phy->ensm_pin_ctl_en = false; + phy->txmon_tdd_en = 0; + phy->current_tx_lo_freq = 0; + phy->current_rx_lo_freq = 0; + phy->current_tx_use_tdd_table = false; + phy->current_rx_use_tdd_table = false; + phy->cached_synth_pd[0] = 0; + phy->cached_synth_pd[1] = 0; + + memset(&phy->fastlock, 0, sizeof(phy->fastlock)); +} + +/** + * Determine the reference frequency value. + * @param refin_Hz Maximum allowed frequency. + * @param max Reference in frequency value. + * @return Reference frequency value. + */ +static uint32_t ad9361_ref_div_sel(uint32_t refin_Hz, uint32_t max) +{ + if (refin_Hz <= (max / 2)) + return 2 * refin_Hz; + else if (refin_Hz <= max) + return refin_Hz; + else if (refin_Hz <= (max * 2)) + return refin_Hz / 2; + else if (refin_Hz <= (max * 4)) + return refin_Hz / 4; + else + return 0; +} + +/** + * Setup the AD9361 device. + * @param phy The AD9361 state structure. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_setup(struct ad9361_rf_phy *phy) +{ + uint32_t refin_Hz, ref_freq, bbpll_freq; + struct spi_desc *spi = phy->spi; + struct ad9361_phy_platform_data *pd = phy->pdata; + int32_t ret; + uint32_t real_rx_bandwidth, real_tx_bandwidth; + bool tmp_use_ext_rx_lo = pd->use_ext_rx_lo; + bool tmp_use_ext_tx_lo = pd->use_ext_tx_lo; + + dev_dbg(dev, "%s", __func__); + + pd->rf_rx_bandwidth_Hz = ad9361_validate_rf_bw(phy, pd->rf_rx_bandwidth_Hz); + pd->rf_tx_bandwidth_Hz = ad9361_validate_rf_bw(phy, pd->rf_tx_bandwidth_Hz); + + real_rx_bandwidth = pd->rf_rx_bandwidth_Hz / 2; + real_tx_bandwidth = pd->rf_tx_bandwidth_Hz / 2; + + if (pd->fdd) { + pd->tdd_skip_vco_cal = false; + if (pd->ensm_pin_ctrl && pd->fdd_independent_mode) { + dev_warn(dev, + "%s: Either set ENSM PINCTRL or FDD Independent Mode", + __func__); + pd->ensm_pin_ctrl = false; + } + } + + ret = ad9361_auxdac_setup(phy, &pd->auxdac_ctrl); + if (ret < 0) + return ret; + + ret = ad9361_gpo_setup(phy, &pd->gpo_ctrl); + if (ret < 0) + return ret; + + if (pd->port_ctrl.pp_conf[2] & FDD_RX_RATE_2TX_RATE) + phy->rx_eq_2tx = true; + + ad9361_spi_write(spi, REG_CTRL, CTRL_ENABLE); + ad9361_spi_write(spi, REG_BANDGAP_CONFIG0, + MASTER_BIAS_TRIM(0x0E)); /* Enable Master Bias */ + ad9361_spi_write(spi, REG_BANDGAP_CONFIG1, + BANDGAP_TEMP_TRIM(0x0E)); /* Set Bandgap Trim */ + + ad9361_set_dcxo_tune(phy, pd->dcxo_coarse, pd->dcxo_fine); + + refin_Hz = phy->clk_refin->rate; + + ref_freq = ad9361_ref_div_sel(refin_Hz, MAX_BBPLL_FREF); + if (!ref_freq) + return -EINVAL; + + ad9361_spi_writef(spi, REG_REF_DIVIDE_CONFIG_1, RX_REF_RESET_BAR, 1); + ad9361_spi_writef(spi, REG_REF_DIVIDE_CONFIG_2, TX_REF_RESET_BAR, 1); + ad9361_spi_writef(spi, REG_REF_DIVIDE_CONFIG_2, + TX_REF_DOUBLER_FB_DELAY(~0), 3); /* FB DELAY */ + ad9361_spi_writef(spi, REG_REF_DIVIDE_CONFIG_2, + RX_REF_DOUBLER_FB_DELAY(~0), 3); /* FB DELAY */ + + ad9361_spi_write(spi, REG_CLOCK_ENABLE, + DIGITAL_POWER_UP | CLOCK_ENABLE_DFLT | BBPLL_ENABLE | + (pd->use_extclk ? XO_BYPASS : 0)); /* Enable Clocks */ + + ret = clk_set_rate(phy, phy->ref_clk_scale[BB_REFCLK], ref_freq); + if (ret < 0) { + dev_err(dev, "Failed to set BB ref clock rate (%"PRId32")", + ret); + return ret; + } + + ret = clk_prepare_enable(phy->clks[BB_REFCLK]); + if (ret < 0) { + dev_err(dev, "Failed to enable BB ref clock rate (%"PRId32")", + ret); + return ret; + } + + ad9361_spi_write(spi, REG_FRACT_BB_FREQ_WORD_2, 0x12); + ad9361_spi_write(spi, REG_FRACT_BB_FREQ_WORD_3, 0x34); + + ret = ad9361_set_trx_clock_chain(phy, pd->rx_path_clks, + pd->tx_path_clks); + if (ret < 0) + return ret; + + if (!pd->rx2tx2) { + pd->rx1tx1_mode_use_tx_num = + clamp_t(uint32_t, pd->rx1tx1_mode_use_tx_num, TX_1, TX_2); + pd->rx1tx1_mode_use_rx_num = + clamp_t(uint32_t, pd->rx1tx1_mode_use_rx_num, RX_1, RX_2); + + ad9361_en_dis_tx(phy, TX_1 | TX_2, pd->rx1tx1_mode_use_tx_num); + ad9361_en_dis_rx(phy, TX_1 | TX_2, pd->rx1tx1_mode_use_rx_num); + } else { + ad9361_en_dis_tx(phy, TX_1 | TX_2, TX_1 | TX_2); + ad9361_en_dis_rx(phy, RX_1 | RX_2, RX_1 | RX_2); + } + + ret = ad9361_rf_port_setup(phy, true, pd->rf_rx_input_sel, + pd->rf_tx_output_sel); + if (ret < 0) + return ret; + + ret = ad9361_pp_port_setup(phy, false); + if (ret < 0) + return ret; + + bbpll_freq = clk_get_rate(phy, phy->ref_clk_scale[BBPLL_CLK]); + ret = ad9361_auxadc_setup(phy, &pd->auxadc_ctrl, bbpll_freq); + if (ret < 0) + return ret; + + ret = ad9361_ctrl_outs_setup(phy, &pd->ctrl_outs_ctrl); + if (ret < 0) + return ret; + + ret = ad9361_set_ref_clk_cycles(phy, refin_Hz); + if (ret < 0) + return ret; + + ret = ad9361_setup_ext_lna(phy, &pd->elna_ctrl); + if (ret < 0) + return ret; + + /* + * This allows forcing a lower F_REF window + * (worse phase noise, better fractional spurs) + */ + pd->trx_synth_max_fref = clamp_t(uint32_t, pd->trx_synth_max_fref, + MIN_SYNTH_FREF, MAX_SYNTH_FREF); + + ref_freq = ad9361_ref_div_sel(refin_Hz, pd->trx_synth_max_fref); + if (!ref_freq) + return -EINVAL; + + ret = clk_set_rate(phy, phy->ref_clk_scale[RX_REFCLK], ref_freq); + if (ret < 0) { + dev_err(dev, "Failed to set RX Synth ref clock rate (%"PRId32")", ret); + return ret; + } + + ret = clk_set_rate(phy, phy->ref_clk_scale[TX_REFCLK], ref_freq); + if (ret < 0) { + dev_err(dev, "Failed to set TX Synth ref clock rate (%"PRId32")", ret); + return ret; + } + + ret = ad9361_txrx_synth_cp_calib(phy, ref_freq, false); /* RXCP */ + if (ret < 0) + return ret; + + ret = ad9361_txrx_synth_cp_calib(phy, ref_freq, true); /* TXCP */ + if (ret < 0) + return ret; + + phy->pdata->use_ext_rx_lo = 0; + phy->pdata->use_ext_tx_lo = 0; + + ret = clk_set_rate(phy, phy->ref_clk_scale[RX_RFPLL], + ad9361_to_clk(pd->rx_synth_freq)); + if (ret < 0) { + dev_err(dev, "Failed to set RX Synth rate (%"PRId32")", + ret); + return ret; + } + + ret = clk_prepare_enable(phy->clks[RX_REFCLK]); + if (ret < 0) { + dev_err(dev, "Failed to enable RX Synth ref clock (%"PRId32")", ret); + return ret; + } + + ret = clk_prepare_enable(phy->clks[RX_RFPLL]); + if (ret < 0) + return ret; + + /* Skip quad cal here we do it later again */ + phy->last_tx_quad_cal_freq = pd->tx_synth_freq; + ret = clk_set_rate(phy, phy->ref_clk_scale[TX_RFPLL], + ad9361_to_clk(pd->tx_synth_freq)); + if (ret < 0) { + dev_err(dev, "Failed to set TX Synth rate (%"PRId32")", + ret); + return ret; + } + + ret = clk_prepare_enable(phy->clks[TX_REFCLK]); + if (ret < 0) { + dev_err(dev, "Failed to enable TX Synth ref clock (%"PRId32")", ret); + return ret; + } + + ret = clk_prepare_enable(phy->clks[TX_RFPLL]); + if (ret < 0) + return ret; + + phy->pdata->use_ext_rx_lo = tmp_use_ext_rx_lo; + phy->pdata->use_ext_tx_lo = tmp_use_ext_tx_lo; + + ad9361_clk_mux_set_parent(phy->ref_clk_scale[RX_RFPLL], + pd->use_ext_rx_lo); + + ad9361_clk_mux_set_parent(phy->ref_clk_scale[TX_RFPLL], + pd->use_ext_tx_lo); + + ret = ad9361_load_mixer_gm_subtable(phy); + if (ret < 0) + return ret; + + ret = ad9361_gc_setup(phy, &pd->gain_ctrl); + if (ret < 0) + return ret; + + ret = ad9361_rx_bb_analog_filter_calib(phy, + real_rx_bandwidth, + bbpll_freq); + if (ret < 0) + return ret; + + ret = ad9361_tx_bb_analog_filter_calib(phy, + real_tx_bandwidth, + bbpll_freq); + if (ret < 0) + return ret; + + ret = ad9361_rx_tia_calib(phy, real_rx_bandwidth); + if (ret < 0) + return ret; + + ret = ad9361_tx_bb_second_filter_calib(phy, real_tx_bandwidth); + if (ret < 0) + return ret; + + ret = ad9361_rx_adc_setup(phy, + bbpll_freq, + clk_get_rate(phy, phy->ref_clk_scale[ADC_CLK])); + if (ret < 0) + return ret; + + ret = ad9361_bb_dc_offset_calib(phy); + if (ret < 0) + return ret; + + ret = ad9361_rf_dc_offset_calib(phy, + ad9361_from_clk(clk_get_rate(phy, phy->ref_clk_scale[RX_RFPLL]))); + if (ret < 0) + return ret; + + phy->current_rx_bw_Hz = pd->rf_rx_bandwidth_Hz; + phy->current_tx_bw_Hz = pd->rf_tx_bandwidth_Hz; + phy->last_tx_quad_cal_phase = ~0; + ret = ad9361_tx_quad_calib(phy, real_rx_bandwidth, real_tx_bandwidth, -1); + if (ret < 0) + return ret; + + ret = ad9361_tracking_control(phy, phy->bbdc_track_en, + phy->rfdc_track_en, phy->quad_track_en); + if (ret < 0) + return ret; + + ad9361_pp_port_setup(phy, true); + + ret = ad9361_set_ensm_mode(phy, pd->fdd, pd->ensm_pin_ctrl); + if (ret < 0) + return ret; + + ad9361_spi_writef(phy->spi, REG_TX_ATTEN_OFFSET, + MASK_CLR_ATTEN_UPDATE, 0); + + ret = ad9361_set_tx_atten(phy, pd->tx_atten, + pd->rx2tx2 ? true : pd->rx1tx1_mode_use_tx_num == 1, + pd->rx2tx2 ? true : pd->rx1tx1_mode_use_tx_num == 2, true); + if (ret < 0) + return ret; + + if (!pd->rx2tx2) { + ret = ad9361_set_tx_atten(phy, 89750, + pd->rx1tx1_mode_use_tx_num == 2, + pd->rx1tx1_mode_use_tx_num == 1, true); + if (ret < 0) + return ret; + } + + ret = ad9361_rssi_setup(phy, &pd->rssi_ctrl, false); + if (ret < 0) + return ret; + + ret = ad9361_clkout_control(phy, pd->ad9361_clkout_mode); + if (ret < 0) + return ret; + + ret = ad9361_txmon_setup(phy, &pd->txmon_ctrl); + if (ret < 0) + return ret; + + phy->curr_ensm_state = ad9361_spi_readf(spi, REG_STATE, ENSM_STATE(~0)); + ad9361_ensm_set_state(phy, pd->fdd ? ENSM_STATE_FDD : ENSM_STATE_RX, + pd->ensm_pin_ctrl); + + phy->auto_cal_en = true; + phy->cal_threshold_freq = 100000000ULL; /* 100 MHz */ + + return 0; + +} + +/** + * Perform the selected calibration + * @param phy The AD9361 state structure. + * @param cal The selected calibration. + * @param arg The argument of the calibration. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_do_calib_run(struct ad9361_rf_phy *phy, uint32_t cal, + int32_t arg) +{ + int32_t ret; + + dev_dbg(&phy->spi->dev, "%s: CAL %"PRIu32" ARG %"PRId32, __func__, cal, arg); + + ret = ad9361_tracking_control(phy, false, false, false); + if (ret < 0) + return ret; + + ad9361_ensm_force_state(phy, ENSM_STATE_ALERT); + + switch (cal) { + case TX_QUAD_CAL: + ret = ad9361_tx_quad_calib(phy, phy->current_rx_bw_Hz / 2, + phy->current_tx_bw_Hz / 2, arg); + break; + case RFDC_CAL: + ret = ad9361_rf_dc_offset_calib(phy, + ad9361_from_clk(clk_get_rate(phy, phy->ref_clk_scale[RX_RFPLL]))); + break; + default: + ret = -EINVAL; + break; + } + + ret = ad9361_tracking_control(phy, phy->bbdc_track_en, + phy->rfdc_track_en, phy->quad_track_en); + ad9361_ensm_restore_prev_state(phy); + + return ret; +} + +/** + * Set the RF bandwidth. + * @param phy The AD9361 state structure. + * @param rf_rx_bw The desired RX bandwidth [Hz]. + * @param rf_tx_bw The desired TX bandwidth [Hz]. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_update_rf_bandwidth(struct ad9361_rf_phy *phy, + uint32_t rf_rx_bw, uint32_t rf_tx_bw) +{ + int32_t ret; + + ret = ad9361_tracking_control(phy, false, false, false); + if (ret < 0) + return ret; + + ad9361_ensm_force_state(phy, ENSM_STATE_ALERT); + + ret = __ad9361_update_rf_bandwidth(phy, rf_rx_bw, rf_tx_bw); + if (ret < 0) + return ret; + + phy->current_rx_bw_Hz = rf_rx_bw; + phy->current_tx_bw_Hz = rf_tx_bw; + + if (phy->manual_tx_quad_cal_en == false) { + ret = ad9361_tx_quad_calib(phy, rf_rx_bw / 2, rf_tx_bw / 2, -1); + if (ret < 0) + return ret; + } + + ret = ad9361_tracking_control(phy, phy->bbdc_track_en, + phy->rfdc_track_en, phy->quad_track_en); + if (ret < 0) + return ret; + + ad9361_ensm_restore_prev_state(phy); + + return 0; +} + +/** + * Verify the FIR filter coefficients. + * @param phy The AD9361 state structure. + * @param dest Destination identifier (RX1,2 / TX1,2). + * @param ntaps Number of filter Taps. + * @param coef Pointer to filter coefficients. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_verify_fir_filter_coef(struct ad9361_rf_phy *phy, + enum fir_dest dest, + uint32_t ntaps, short *coef) +{ + struct spi_desc *spi = phy->spi; + uint32_t val, offs = 0, gain = 0, conf, sel, cnt; + int32_t ret = 0; + +#ifndef DEBUG + return 0; +#endif + dev_dbg(&phy->spi->dev, "%s: TAPS %"PRIu32", dest %d", + __func__, ntaps, dest); + + if (dest & FIR_IS_RX) { + gain = ad9361_spi_read(spi, REG_RX_FILTER_GAIN); + offs = REG_RX_FILTER_COEF_ADDR - REG_TX_FILTER_COEF_ADDR; + ad9361_spi_write(spi, REG_RX_FILTER_GAIN, 0); + } + + conf = ad9361_spi_read(spi, REG_TX_FILTER_CONF + offs); + + if ((dest & 3) == 3) { + sel = 1; + cnt = 2; + } else { + sel = (dest & 3); + cnt = 1; + } + + for (; cnt > 0; cnt--, sel++) { + + ad9361_spi_write(spi, REG_TX_FILTER_CONF + offs, + FIR_NUM_TAPS(ntaps / 16 - 1) | + FIR_SELECT(sel) | FIR_START_CLK); + for (val = 0; val < ntaps; val++) { + short tmp; + ad9361_spi_write(spi, REG_TX_FILTER_COEF_ADDR + offs, val); + + tmp = (ad9361_spi_read(spi, REG_TX_FILTER_COEF_READ_DATA_1 + offs) & 0xFF) | + (ad9361_spi_read(spi, REG_TX_FILTER_COEF_READ_DATA_2 + offs) << 8); + + if (tmp != coef[val]) { + dev_err(&phy->spi->dev,"%s%"PRIu32" read verify failed TAP%"PRIu32" %d =! %d", + (dest & FIR_IS_RX) ? "RX" : "TX", sel, + val, tmp, coef[val]); + ret = -EIO; + } + } + } + + if (dest & FIR_IS_RX) { + ad9361_spi_write(spi, REG_RX_FILTER_GAIN, gain); + } + + ad9361_spi_write(spi, REG_TX_FILTER_CONF + offs, conf); + + return ret; +} + +/** + * Load the FIR filter coefficients. + * @param phy The AD9361 state structure. + * @param dest Destination identifier (RX1,2 / TX1,2). + * @param gain_dB Gain option. + * @param ntaps Number of filter Taps. + * @param coef Pointer to filter coefficients. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_load_fir_filter_coef(struct ad9361_rf_phy *phy, + enum fir_dest dest, int32_t gain_dB, + uint32_t ntaps, int16_t *coef) +{ + struct spi_desc *spi = phy->spi; + uint32_t val, offs = 0, fir_conf = 0, fir_enable = 0; + int32_t ret; + + dev_dbg(&phy->spi->dev, "%s: TAPS %"PRIu32", gain %"PRId32", dest %d", + __func__, ntaps, gain_dB, dest); + + if (coef == NULL || !ntaps || ntaps > 128 || ntaps % 16) { + dev_err(&phy->spi->dev, + "%s: Invalid parameters: TAPS %"PRIu32", gain %"PRId32", dest 0x%X", + __func__, ntaps, gain_dB, dest); + + return -EINVAL; + } + + ad9361_ensm_force_state(phy, ENSM_STATE_ALERT); + + if (dest & FIR_IS_RX) { + val = 3 - (gain_dB + 12) / 6; + ad9361_spi_write(spi, REG_RX_FILTER_GAIN, val & 0x3); + offs = REG_RX_FILTER_COEF_ADDR - REG_TX_FILTER_COEF_ADDR; + phy->rx_fir_ntaps = ntaps; + fir_enable = ad9361_spi_readf(phy->spi, + REG_RX_ENABLE_FILTER_CTRL, RX_FIR_ENABLE_DECIMATION(~0)); + ad9361_spi_writef(phy->spi, REG_RX_ENABLE_FILTER_CTRL, + RX_FIR_ENABLE_DECIMATION(~0), + (phy->rx_fir_dec == 4) ? 3 : phy->rx_fir_dec); + } else { + if (gain_dB == -6) + fir_conf = TX_FIR_GAIN_6DB; + phy->tx_fir_ntaps = ntaps; + fir_enable = ad9361_spi_readf(phy->spi, + REG_TX_ENABLE_FILTER_CTRL, TX_FIR_ENABLE_INTERPOLATION(~0)); + ad9361_spi_writef(phy->spi, REG_TX_ENABLE_FILTER_CTRL, + TX_FIR_ENABLE_INTERPOLATION(~0), + (phy->tx_fir_int == 4) ? 3 : phy->tx_fir_int); + } + + val = ntaps / 16 - 1; + + fir_conf |= FIR_NUM_TAPS(val) | FIR_SELECT(dest) | FIR_START_CLK; + + ad9361_spi_write(spi, REG_TX_FILTER_CONF + offs, fir_conf); + + for (val = 0; val < ntaps; val++) { + ad9361_spi_write(spi, REG_TX_FILTER_COEF_ADDR + offs, val); + ad9361_spi_write(spi, REG_TX_FILTER_COEF_WRITE_DATA_1 + offs, + coef[val] & 0xFF); + ad9361_spi_write(spi, REG_TX_FILTER_COEF_WRITE_DATA_2 + offs, + coef[val] >> 8); + ad9361_spi_write(spi, REG_TX_FILTER_CONF + offs, + fir_conf | FIR_WRITE); + ad9361_spi_write(spi, REG_TX_FILTER_COEF_READ_DATA_2 + offs, 0); + ad9361_spi_write(spi, REG_TX_FILTER_COEF_READ_DATA_2 + offs, 0); + } + + ad9361_spi_write(spi, REG_TX_FILTER_CONF + offs, fir_conf); + fir_conf &= ~FIR_START_CLK; + ad9361_spi_write(spi, REG_TX_FILTER_CONF + offs, fir_conf); + + ret = ad9361_verify_fir_filter_coef(phy, dest, ntaps, coef); + + if (dest & FIR_IS_RX) + ad9361_spi_writef(phy->spi, REG_RX_ENABLE_FILTER_CTRL, + RX_FIR_ENABLE_DECIMATION(~0), fir_enable); + else + ad9361_spi_writef(phy->spi, REG_TX_ENABLE_FILTER_CTRL, + TX_FIR_ENABLE_INTERPOLATION(~0), fir_enable); + + ad9361_ensm_restore_prev_state(phy); + + return ret; +} + +/** + * Parse the FIR filter file/buffer. + * @param phy The AD9361 state structure. + * @param data Pointer to buffer. + * @param size Buffer size. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_parse_fir(struct ad9361_rf_phy *phy, + char *data, uint32_t size) +{ + char *line; + int32_t i = 0, ret, txc, rxc; + int32_t tx = -1, tx_gain = 0, tx_int = 0; + int32_t rx = -1, rx_gain = 0, rx_dec = 0; + int32_t rtx = -1, rrx = -1; + int16_t coef_tx[128]; + int16_t coef_rx[128]; + char *ptr = data; + + phy->filt_rx_bw_Hz = 0; + phy->filt_tx_bw_Hz = 0; + phy->filt_valid = false; + + while ((line = strsep(&ptr, "\n"))) { + if (line >= data + size) { + break; + } + + if (line[0] == '#') + continue; + + if (tx < 0) { +#ifdef WIN32 + ret = sscanf_s(line, "TX %d GAIN %d INT %d", + &tx, &tx_gain, &tx_int); +#else + ret = sscanf(line, "TX %"PRId32" GAIN %"PRId32" INT %"PRId32, + &tx, &tx_gain, &tx_int); +#endif + if (ret == 3) + continue; + else + tx = -1; + } + if (rx < 0) { +#ifdef WIN32 + ret = sscanf_s(line, "RX %d GAIN %d DEC %d", + &rx, &rx_gain, &rx_dec); +#else + ret = sscanf(line, "RX %"PRId32" GAIN %"PRId32" DEC %"PRId32, + &rx, &rx_gain, &rx_dec); +#endif + if (ret == 3) + continue; + else + tx = -1; + } + + if (rtx < 0) { +#ifdef WIN32 + ret = sscanf(line, "RTX %lu %lu %lu %lu %lu %lu", +#else + ret = sscanf(line, + "RTX %"PRIu32" %"PRIu32" %"PRIu32" %"PRIu32" %"PRIu32" %"PRIu32, +#endif + &phy->filt_tx_path_clks[0], + &phy->filt_tx_path_clks[1], + &phy->filt_tx_path_clks[2], + &phy->filt_tx_path_clks[3], + &phy->filt_tx_path_clks[4], + &phy->filt_tx_path_clks[5]); + if (ret == 6) { + rtx = 0; + continue; + } else { + rtx = -1; + } + } + + if (rrx < 0) { +#ifdef WIN32 + ret = sscanf(line, "RRX %lu %lu %lu %lu %lu %lu", +#else + ret = sscanf(line, + "RRX %"PRIu32" %"PRIu32" %"PRIu32" %"PRIu32" %"PRIu32" %"PRIu32, +#endif + &phy->filt_rx_path_clks[0], + &phy->filt_rx_path_clks[1], + &phy->filt_rx_path_clks[2], + &phy->filt_rx_path_clks[3], + &phy->filt_rx_path_clks[4], + &phy->filt_rx_path_clks[5]); + if (ret == 6) { + rrx = 0; + continue; + } else { + rrx = -1; + } + } + + if (!phy->filt_rx_bw_Hz) { +#ifdef WIN32 + ret = sscanf(line, "BWRX %d", &phy->filt_rx_bw_Hz); +#else + ret = sscanf(line, "BWRX %"PRId32, &phy->filt_rx_bw_Hz); +#endif + if (ret == 1) + continue; + else + phy->filt_rx_bw_Hz = 0; + } + + if (!phy->filt_tx_bw_Hz) { +#ifdef WIN32 + ret = sscanf(line, "BWTX %d", &phy->filt_tx_bw_Hz); +#else + ret = sscanf(line, "BWTX %"PRId32, &phy->filt_tx_bw_Hz); +#endif + if (ret == 1) + continue; + else + phy->filt_tx_bw_Hz = 0; + } + +#ifdef WIN32 + ret = sscanf_s(line, "%d,%d", &txc, &rxc); +#else + ret = sscanf(line, "%"PRId32",%"PRId32, &txc, &rxc); +#endif + if (ret == 1) { + coef_tx[i] = coef_rx[i] = (int16_t)txc; + i++; + continue; + } else if (ret == 2) { + coef_tx[i] = (int16_t)txc; + coef_rx[i] = (int16_t)rxc; + i++; + continue; + } + } + + switch (tx) { + case FIR_TX1: + case FIR_TX2: + case FIR_TX1_TX2: + phy->tx_fir_int = tx_int; + ret = ad9361_load_fir_filter_coef(phy, (enum fir_dest)tx, tx_gain, i, coef_tx); + break; + default: + ret = -EINVAL; + } + + switch (rx | FIR_IS_RX) { + case FIR_RX1: + case FIR_RX2: + case FIR_RX1_RX2: + phy->rx_fir_dec = rx_dec; + ret = ad9361_load_fir_filter_coef(phy, (enum fir_dest)(rx | FIR_IS_RX), + rx_gain, i, coef_rx); + break; + default: + ret = -EINVAL; + } + + if (ret < 0) + return ret; + + if (!(rrx | rtx)) + phy->filt_valid = true; + + return size; +} + +/** + * Validate FIR filter configuration - on pass enable. + * @param phy The AD9361 state structure. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_validate_enable_fir(struct ad9361_rf_phy *phy) +{ + int32_t ret; + uint32_t rx[6], tx[6]; + uint32_t max, min, valid; + + dev_dbg(dev, "%s: TX FIR EN=%d/TAPS%d/INT%d, RX FIR EN=%d/TAPS%d/DEC%d", + __func__, !phy->bypass_tx_fir, phy->tx_fir_ntaps, phy->tx_fir_int, + !phy->bypass_rx_fir, phy->rx_fir_ntaps, phy->rx_fir_dec); + + if (!phy->bypass_tx_fir) { + if (!(phy->tx_fir_int == 1 || phy->tx_fir_int == 2 || + phy->tx_fir_int == 4)) { + dev_err(dev, + "%s: Invalid: Interpolation %d in filter config", + __func__, phy->tx_fir_int); + return -EINVAL; + } + + + if (phy->tx_fir_int == 1 && phy->tx_fir_ntaps > 64) { + dev_err(dev, + "%s: Invalid: TAPS > 64 and Interpolation = 1", + __func__); + return -EINVAL; + } + } + + if (!phy->bypass_rx_fir) { + if (!(phy->rx_fir_dec == 1 || phy->rx_fir_dec == 2 || + phy->rx_fir_dec == 4)) { + dev_err(dev, + "%s: Invalid: Decimation %d in filter config", + __func__, phy->rx_fir_dec); + + return -EINVAL; + } + } + + if (!phy->filt_valid || phy->bypass_rx_fir || phy->bypass_tx_fir) { + ret = ad9361_calculate_rf_clock_chain(phy, + clk_get_rate(phy, phy->ref_clk_scale[TX_SAMPL_CLK]), + phy->rate_governor, rx, tx); + if (ret < 0) { + min = phy->rate_governor ? 1500000U : 1000000U; + dev_err(dev, + "%s: Calculating filter rates failed %"PRId32 + " using min frequency",__func__, ret); + ret = ad9361_calculate_rf_clock_chain(phy, min, + phy->rate_governor, rx, tx); + if (ret < 0) { + return ret; + } + } + valid = false; + } else { +#ifndef ALTERA_PLATFORM + memcpy(rx, phy->filt_rx_path_clks, sizeof(rx)); + memcpy(tx, phy->filt_tx_path_clks, sizeof(tx)); +#else + int32_t i; + uint32_t num; + num = sizeof(rx) / sizeof(rx[0]); + for (i = 0; i < num; i++) + rx[i] = phy->filt_rx_path_clks[i]; + num = sizeof(tx) / sizeof(rx[0]); + for (i = 0; i < num; i++) + tx[i] = phy->filt_tx_path_clks[i]; +#endif + valid = true; + + } + +#ifdef _DEBUG + dev_dbg(&phy->spi->dev, + "%s:RX %"PRIu32" %"PRIu32" %"PRIu32" %"PRIu32" %"PRIu32" %"PRIu32, + __func__, rx[BBPLL_FREQ], rx[ADC_FREQ], + rx[R2_FREQ], rx[R1_FREQ], + rx[CLKRF_FREQ], rx[RX_SAMPL_FREQ]); + + dev_dbg(&phy->spi->dev, + "%s:TX %"PRIu32" %"PRIu32" %"PRIu32" %"PRIu32" %"PRIu32" %"PRIu32, + __func__, tx[BBPLL_FREQ], tx[ADC_FREQ], + tx[R2_FREQ], tx[R1_FREQ], + tx[CLKRF_FREQ], tx[RX_SAMPL_FREQ]); +#endif + + if (!phy->bypass_tx_fir) { + max = (tx[DAC_FREQ] / tx[TX_SAMPL_FREQ]) * 16; + if (phy->tx_fir_ntaps > max) { + dev_err(dev, + "%s: Invalid: ratio DAC / TX_SAMPL * 16 > TAPS" + "(max %"PRIu32", adc %"PRIu32", tx %"PRIu32")", + __func__, max, tx[DAC_FREQ], tx[TX_SAMPL_FREQ]); + return -EINVAL; + } + } + + if (!phy->bypass_rx_fir) { + max = ((rx[ADC_FREQ] / ((rx[ADC_FREQ] == rx[R2_FREQ]) ? 1 : 2)) / + rx[RX_SAMPL_FREQ]) * 16; + if (phy->rx_fir_ntaps > max) { + dev_err(dev, + "%s: Invalid: ratio ADC/2 / RX_SAMPL * 16 > TAPS (max %"PRIu32")", + __func__, max); + return -EINVAL; + } + } + + ret = ad9361_set_trx_clock_chain(phy, rx, tx); + if (ret < 0) + return ret; + + /* See also: ad9361_set_trx_clock_chain() */ + if (!phy->pdata->dig_interface_tune_fir_disable && + phy->bypass_tx_fir && phy->bypass_rx_fir) + ad9361_dig_tune(phy, 0, RESTORE_DEFAULT); + + return ad9361_update_rf_bandwidth(phy, + valid ? phy->filt_rx_bw_Hz : phy->current_rx_bw_Hz, + valid ? phy->filt_tx_bw_Hz : phy->current_tx_bw_Hz); +} + +/* +* AD9361 Clocks +*/ + +/** +* Set the multiplier and the divider for the selected refclk_scale structure. +* @param priv The selected refclk_scale structure. +* @param mul The multiplier value. +* @param div The divider value. +* @return 0 in case of success, negative error code otherwise. +*/ +static inline int32_t ad9361_set_muldiv(struct refclk_scale *priv, uint32_t mul, + uint32_t div) +{ + priv->mult = mul; + priv->div = div; + return 0; +} + +/** + * Get the clk scaler for the selected refclk_scale structure. + * @param priv The selected refclk_scale structure. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_get_clk_scaler(struct refclk_scale *clk_priv) +{ + struct spi_desc *spi = clk_priv->spi; + uint32_t tmp, tmp1; + + switch (clk_priv->source) { + case BB_REFCLK: + tmp = ad9361_spi_read(spi, REG_CLOCK_CTRL); + tmp &= 0x3; + break; + case RX_REFCLK: + tmp = ad9361_spi_readf(spi, REG_REF_DIVIDE_CONFIG_1, + RX_REF_DIVIDER_MSB); + tmp1 = ad9361_spi_readf(spi, REG_REF_DIVIDE_CONFIG_2, + RX_REF_DIVIDER_LSB); + tmp = (tmp << 1) | tmp1; + break; + case TX_REFCLK: + tmp = ad9361_spi_readf(spi, REG_REF_DIVIDE_CONFIG_2, + TX_REF_DIVIDER(~0)); + break; + case ADC_CLK: + tmp = ad9361_spi_read(spi, REG_BBPLL); + return ad9361_set_muldiv(clk_priv, 1, 1 << (tmp & 0x7)); + case R2_CLK: + tmp = ad9361_spi_readf(spi, REG_RX_ENABLE_FILTER_CTRL, + DEC3_ENABLE_DECIMATION(~0)); + return ad9361_set_muldiv(clk_priv, 1, tmp + 1); + case R1_CLK: + tmp = ad9361_spi_readf(spi, REG_RX_ENABLE_FILTER_CTRL, RHB2_EN); + return ad9361_set_muldiv(clk_priv, 1, tmp + 1); + case CLKRF_CLK: + tmp = ad9361_spi_readf(spi, REG_RX_ENABLE_FILTER_CTRL, RHB1_EN); + return ad9361_set_muldiv(clk_priv, 1, tmp + 1); + case RX_SAMPL_CLK: + tmp = ad9361_spi_readf(spi, REG_RX_ENABLE_FILTER_CTRL, + RX_FIR_ENABLE_DECIMATION(~0)); + + if (!tmp) + tmp = 1; /* bypass filter */ + else + tmp = (1 << (tmp - 1)); + + return ad9361_set_muldiv(clk_priv, 1, tmp); + case DAC_CLK: + tmp = ad9361_spi_readf(spi, REG_BBPLL, BIT(3)); + return ad9361_set_muldiv(clk_priv, 1, tmp + 1); + case T2_CLK: + tmp = ad9361_spi_readf(spi, REG_TX_ENABLE_FILTER_CTRL, + THB3_ENABLE_INTERP(~0)); + return ad9361_set_muldiv(clk_priv, 1, tmp + 1); + case T1_CLK: + tmp = ad9361_spi_readf(spi, REG_TX_ENABLE_FILTER_CTRL, THB2_EN); + return ad9361_set_muldiv(clk_priv, 1, tmp + 1); + case CLKTF_CLK: + tmp = ad9361_spi_readf(spi, REG_TX_ENABLE_FILTER_CTRL, THB1_EN); + return ad9361_set_muldiv(clk_priv, 1, tmp + 1); + case TX_SAMPL_CLK: + tmp = ad9361_spi_readf(spi, REG_TX_ENABLE_FILTER_CTRL, + TX_FIR_ENABLE_INTERPOLATION(~0)); + + if (!tmp) + tmp = 1; /* bypass filter */ + else + tmp = (1 << (tmp - 1)); + + return ad9361_set_muldiv(clk_priv, 1, tmp); + default: + return -EINVAL; + } + + /* REFCLK Scaler */ + switch (tmp) { + case 0: + ad9361_set_muldiv(clk_priv, 1, 1); + break; + case 1: + ad9361_set_muldiv(clk_priv, 1, 2); + break; + case 2: + ad9361_set_muldiv(clk_priv, 1, 4); + break; + case 3: + ad9361_set_muldiv(clk_priv, 2, 1); + break; + default: + return -EINVAL; + + } + + return 0; +} + +/** + * Calculate the REFCLK Scaler for the selected refclk_scale structure. + * Note: REFCLK Scaler values - 00: x1; 01: x½; 10: x¼; 11: x2. + * @param clk_priv The selected refclk_scale structure. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_to_refclk_scaler(struct refclk_scale *clk_priv) +{ + /* REFCLK Scaler */ + switch (((clk_priv->mult & 0xF) << 4) | (clk_priv->div & 0xF)) { + case 0x11: + return 0; + case 0x12: + return 1; + case 0x14: + return 2; + case 0x21: + return 3; + default: + return -EINVAL; + } +}; + +/** + * Set clk scaler for the selected refclk_scale structure. + * @param clk_priv The selected refclk_scale structure. + * @param set Set true, the reference clock frequency will be scaled before + * it enters the BBPLL. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_set_clk_scaler(struct refclk_scale *clk_priv, bool set) +{ + struct spi_desc *spi = clk_priv->spi; + uint32_t tmp; + int32_t ret; + + switch (clk_priv->source) { + case BB_REFCLK: + ret = ad9361_to_refclk_scaler(clk_priv); + if (ret < 0) + return ret; + if (set) + return ad9361_spi_writef(spi, REG_CLOCK_CTRL, + REF_FREQ_SCALER(~0), ret); + break; + + case RX_REFCLK: + ret = ad9361_to_refclk_scaler(clk_priv); + if (ret < 0) + return ret; + if (set) { + tmp = ret; + ret = ad9361_spi_writef(spi, REG_REF_DIVIDE_CONFIG_1, + RX_REF_DIVIDER_MSB, tmp >> 1); + ret |= ad9361_spi_writef(spi, REG_REF_DIVIDE_CONFIG_2, + RX_REF_DIVIDER_LSB, tmp & 1); + return ret; + } + break; + case TX_REFCLK: + ret = ad9361_to_refclk_scaler(clk_priv); + if (ret < 0) + return ret; + if (set) + return ad9361_spi_writef(spi, REG_REF_DIVIDE_CONFIG_2, + TX_REF_DIVIDER(~0), ret); + break; + case ADC_CLK: + tmp = ilog2((uint8_t)clk_priv->div); + if (clk_priv->mult != 1 || tmp > 6 || tmp < 1) + return -EINVAL; + + if (set) + return ad9361_spi_writef(spi, REG_BBPLL, 0x7, tmp); + break; + case R2_CLK: + if (clk_priv->mult != 1 || clk_priv->div > 3 || clk_priv->div < 1) + return -EINVAL; + if (set) + return ad9361_spi_writef(spi, REG_RX_ENABLE_FILTER_CTRL, + DEC3_ENABLE_DECIMATION(~0), + clk_priv->div - 1); + break; + case R1_CLK: + if (clk_priv->mult != 1 || clk_priv->div > 2 || clk_priv->div < 1) + return -EINVAL; + if (set) + return ad9361_spi_writef(spi, REG_RX_ENABLE_FILTER_CTRL, + RHB2_EN, clk_priv->div - 1); + break; + case CLKRF_CLK: + if (clk_priv->mult != 1 || clk_priv->div > 2 || clk_priv->div < 1) + return -EINVAL; + if (set) + return ad9361_spi_writef(spi, REG_RX_ENABLE_FILTER_CTRL, + RHB1_EN, clk_priv->div - 1); + break; + case RX_SAMPL_CLK: + if (clk_priv->mult != 1 || clk_priv->div > 4 || + clk_priv->div < 1 || clk_priv->div == 3) + return -EINVAL; + + if (clk_priv->phy->bypass_rx_fir) + tmp = 0; + else + tmp = ilog2(clk_priv->div) + 1; + + if (set) + return ad9361_spi_writef(spi, REG_RX_ENABLE_FILTER_CTRL, + RX_FIR_ENABLE_DECIMATION(~0), tmp); + break; + case DAC_CLK: + if (clk_priv->mult != 1 || clk_priv->div > 2 || clk_priv->div < 1) + return -EINVAL; + if (set) + return ad9361_spi_writef(spi, REG_BBPLL, + BIT(3), clk_priv->div - 1); + break; + case T2_CLK: + if (clk_priv->mult != 1 || clk_priv->div > 3 || clk_priv->div < 1) + return -EINVAL; + if (set) + return ad9361_spi_writef(spi, REG_TX_ENABLE_FILTER_CTRL, + THB3_ENABLE_INTERP(~0), + clk_priv->div - 1); + break; + case T1_CLK: + if (clk_priv->mult != 1 || clk_priv->div > 2 || clk_priv->div < 1) + return -EINVAL; + if (set) + return ad9361_spi_writef(spi, REG_TX_ENABLE_FILTER_CTRL, + THB2_EN, clk_priv->div - 1); + break; + case CLKTF_CLK: + if (clk_priv->mult != 1 || clk_priv->div > 2 || clk_priv->div < 1) + return -EINVAL; + if (set) + return ad9361_spi_writef(spi, REG_TX_ENABLE_FILTER_CTRL, + THB1_EN, clk_priv->div - 1); + break; + case TX_SAMPL_CLK: + if (clk_priv->mult != 1 || clk_priv->div > 4 || + clk_priv->div < 1 || clk_priv->div == 3) + return -EINVAL; + + if (clk_priv->phy->bypass_tx_fir) + tmp = 0; + else + tmp = ilog2(clk_priv->div) + 1; + + if (set) + return ad9361_spi_writef(spi, REG_TX_ENABLE_FILTER_CTRL, + TX_FIR_ENABLE_INTERPOLATION(~0), tmp); + break; + default: + return -EINVAL; + } + + return 0; +} + +/** + * Recalculate the clock rate. + * @param clk_priv The refclk_scale structure. + * @param parent_rate The parent clock rate. + * @return The clock rate. + */ +uint32_t ad9361_clk_factor_recalc_rate(struct refclk_scale *clk_priv, + uint32_t parent_rate) +{ + uint64_t rate; + + ad9361_get_clk_scaler(clk_priv); + rate = (parent_rate * clk_priv->mult) / clk_priv->div; + + return (uint32_t)rate; +} + +/** + * Calculate the closest possible clock rate that can be set. + * @param clk_priv The refclk_scale structure. + * @param rate The clock rate. + * @param prate The parent clock rate. + * @return The closest possible clock rate that can be set. + */ +int32_t ad9361_clk_factor_round_rate(struct refclk_scale *clk_priv, + uint32_t rate, + uint32_t *prate) +{ + int32_t ret; + + if (rate >= *prate) { + clk_priv->mult = DIV_ROUND_CLOSEST(rate, *prate); + clk_priv->div = 1; + + } else { + clk_priv->div = DIV_ROUND_CLOSEST(*prate, rate); + clk_priv->mult = 1; + if (!clk_priv->div) { + dev_err(&clk_priv->spi->dev, "%s: divide by zero", + __func__); + clk_priv->div = 1; + } + } + + ret = ad9361_set_clk_scaler(clk_priv, false); + if (ret < 0) + return ret; + + return (*prate / clk_priv->div) * clk_priv->mult; +} + +/** + * Set the clock rate. + * @param clk_priv The refclk_scale structure. + * @param rate The clock rate. + * @param parent_rate The parent clock rate. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_clk_factor_set_rate(struct refclk_scale *clk_priv, uint32_t rate, + uint32_t parent_rate) +{ + dev_dbg(&clk_priv->spi->dev, "%s: Rate %"PRIu32" Hz Parent Rate %"PRIu32" Hz", + __func__, rate, parent_rate); + + if (rate >= parent_rate) { + clk_priv->mult = DIV_ROUND_CLOSEST(rate, parent_rate); + clk_priv->div = 1; + } else { + clk_priv->div = DIV_ROUND_CLOSEST(parent_rate, rate); + clk_priv->mult = 1; + if (!clk_priv->div) { + dev_err(&clk_priv->spi->dev, "%s: divide by zero", + __func__); + clk_priv->div = 1; + } + } + + return ad9361_set_clk_scaler(clk_priv, true); +} + +/* + * BBPLL + */ +/** + * Recalculate the clock rate. + * @param clk_priv The refclk_scale structure. + * @param parent_rate The parent clock rate. + * @return The clock rate. + */ +uint32_t ad9361_bbpll_recalc_rate(struct refclk_scale *clk_priv, + uint32_t parent_rate) +{ + uint64_t rate; + uint32_t fract, integer; + uint8_t buf[4]; + + ad9361_spi_readm(clk_priv->spi, REG_INTEGER_BB_FREQ_WORD, &buf[0], + REG_INTEGER_BB_FREQ_WORD - REG_FRACT_BB_FREQ_WORD_1 + 1); + + fract = (buf[3] << 16) | (buf[2] << 8) | buf[1]; + integer = buf[0]; + + rate = ((uint64_t)parent_rate * fract); + do_div(&rate, BBPLL_MODULUS); + rate += (uint64_t)parent_rate * integer; + + return (uint32_t)rate; +} + +/** + * Calculate the closest possible clock rate that can be set. + * @param clk_priv The refclk_scale structure. + * @param rate The clock rate. + * @param prate The parent clock rate. + * @return The closest possible clock rate that can be set. + */ +int32_t ad9361_bbpll_round_rate(struct refclk_scale *clk_priv, uint32_t rate, + uint32_t *prate) +{ + uint64_t tmp; + uint32_t fract, integer; + uint64_t temp; + + if (clk_priv) { + // Unused variable - fix compiler warning + } + + if (rate > MAX_BBPLL_FREQ) + return MAX_BBPLL_FREQ; + + if (rate < MIN_BBPLL_FREQ) + return MIN_BBPLL_FREQ; + + temp = rate; + tmp = do_div(&temp, *prate); + rate = temp; + tmp = tmp * BBPLL_MODULUS + (*prate >> 1); + do_div(&tmp, *prate); + + integer = rate; + fract = tmp; + + tmp = *prate * (uint64_t)fract; + do_div(&tmp, BBPLL_MODULUS); + tmp += *prate * integer; + + return tmp; +} + +/** + * Set the clock rate. + * @param clk_priv The refclk_scale structure. + * @param rate The clock rate. + * @param parent_rate The parent clock rate. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_bbpll_set_rate(struct refclk_scale *clk_priv, uint32_t rate, + uint32_t parent_rate) +{ + struct spi_desc *spi = clk_priv->spi; + uint64_t tmp; + uint32_t fract, integer; + int32_t icp_val; + uint8_t lf_defaults[3] = { 0x35, 0x5B, 0xE8 }; + uint64_t temp; + + dev_dbg(&spi->dev, "%s: Rate %"PRIu32" Hz Parent Rate %"PRIu32" Hz", + __func__, rate, parent_rate); + + /* + * Setup Loop Filter and CP Current + * Scale is 150uA @ (1280MHz BBPLL, 40MHz REFCLK) + */ + tmp = (rate >> 7) * 150ULL; + do_div(&tmp, (parent_rate >> 7) * 32UL); + + /* 25uA/LSB, Offset 25uA */ + icp_val = DIV_ROUND_CLOSEST((uint32_t)tmp, 25U) - 1; + + icp_val = clamp(icp_val, 1, 64); + + ad9361_spi_write(spi, REG_CP_CURRENT, icp_val); + ad9361_spi_writem(spi, REG_LOOP_FILTER_3, lf_defaults, + ARRAY_SIZE(lf_defaults)); + + /* Allow calibration to occur and set cal count to 1024 for max accuracy */ + ad9361_spi_write(spi, REG_VCO_CTRL, + FREQ_CAL_ENABLE | FREQ_CAL_COUNT_LENGTH(3)); + /* Set calibration clock to REFCLK/4 for more accuracy */ + ad9361_spi_write(spi, REG_SDM_CTRL, 0x10); + + /* Calculate and set BBPLL frequency word */ + temp = rate; + tmp = do_div(&temp, parent_rate); + rate = temp; + tmp = tmp *(uint64_t)BBPLL_MODULUS + (parent_rate >> 1); + do_div(&tmp, parent_rate); + + integer = rate; + fract = tmp; + + ad9361_spi_write(spi, REG_INTEGER_BB_FREQ_WORD, integer); + ad9361_spi_write(spi, REG_FRACT_BB_FREQ_WORD_3, fract); + ad9361_spi_write(spi, REG_FRACT_BB_FREQ_WORD_2, fract >> 8); + ad9361_spi_write(spi, REG_FRACT_BB_FREQ_WORD_1, fract >> 16); + + ad9361_spi_write(spi, REG_SDM_CTRL_1, + INIT_BB_FO_CAL | BBPLL_RESET_BAR); /* Start BBPLL Calibration */ + ad9361_spi_write(spi, REG_SDM_CTRL_1, + BBPLL_RESET_BAR); /* Clear BBPLL start calibration bit */ + + ad9361_spi_write(spi, REG_VCO_PROGRAM_1, + 0x86); /* Increase BBPLL KV and phase margin */ + ad9361_spi_write(spi, REG_VCO_PROGRAM_2, + 0x01); /* Increase BBPLL KV and phase margin */ + ad9361_spi_write(spi, REG_VCO_PROGRAM_2, + 0x05); /* Increase BBPLL KV and phase margin */ + + return ad9361_check_cal_done(clk_priv->phy, REG_CH_1_OVERFLOW, + BBPLL_LOCK, 1); +} + +/* + * RFPLL + */ + +/** + * Calculate the RFPLL frequency. + * @param parent_rate The parent clock rate. + * @param integer The integer value. + * @param fract The fractional value. + * @param vco_div The VCO divider. + * @return The RFPLL frequency. + */ +static uint64_t ad9361_calc_rfpll_int_freq(uint64_t parent_rate, + uint64_t integer, + uint64_t fract, uint32_t vco_div) +{ + uint64_t rate; + + rate = parent_rate * fract; + do_div(&rate, RFPLL_MODULUS); + rate += parent_rate * integer; + + return rate >> (vco_div + 1); +} + +/** + * Calculate the RFPLL dividers. + * @param phy The AD9361 state structure. + * @param clk_priv The refclk_scale structure. + * @param freq The RFPLL frequency. + * @param parent_rate The parent clock rate. + * @param integer The integer value. + * @param fract The fractional value. + * @param vco_div The VCO divider. + * @param vco_freq The VCO frequency. + * @return The RFPLL frequency. + */ +static int32_t ad9361_calc_rfpll_int_divder(struct ad9361_rf_phy *phy, + struct refclk_scale *clk_priv, uint64_t freq, + uint64_t parent_rate, uint32_t *integer, + uint32_t *fract, int32_t *vco_div, uint64_t *vco_freq) +{ + uint64_t tmp; + int32_t div, ret; + + ret = ad9361_validate_rfpll(phy, clk_priv->source == TX_RFPLL_INT, freq); + if (ret) + return ret; + + div = -1; + + while (freq <= MIN_VCO_FREQ_HZ) { + freq <<= 1; + div++; + } + + *vco_div = div; + *vco_freq = freq; + tmp = do_div(&freq, parent_rate); + tmp = tmp * RFPLL_MODULUS + (parent_rate >> 1); + do_div(&tmp, parent_rate); + *integer = freq; + *fract = tmp; + + return 0; +} + +/** + * Recalculate the clock rate. + * @param clk_priv The refclk_scale structure. + * @param parent_rate The parent clock rate. + * @return The clock rate. + */ +uint32_t ad9361_rfpll_int_recalc_rate(struct refclk_scale *clk_priv, + uint32_t parent_rate) +{ + struct ad9361_rf_phy *phy = clk_priv->phy; + uint32_t fract, integer; + uint8_t buf[5]; + uint32_t reg, div_mask, vco_div, profile; + + dev_dbg(&clk_priv->spi->dev, "%s: Parent Rate %"PRIu32" Hz", + __func__, parent_rate); + + switch (clk_priv->source) { + case RX_RFPLL_INT: + reg = REG_RX_FRACT_BYTE_2; + div_mask = RX_VCO_DIVIDER(~0); + profile = phy->fastlock.current_profile[0]; + break; + case TX_RFPLL_INT: + reg = REG_TX_FRACT_BYTE_2; + div_mask = TX_VCO_DIVIDER(~0); + profile = phy->fastlock.current_profile[1]; + break; + default: + return -EINVAL; + } + + if (profile) { + bool tx = clk_priv->source == TX_RFPLL_INT; + profile = profile - 1; + + buf[0] = ad9361_fastlock_readval(phy->spi, tx, profile, 4); + buf[1] = ad9361_fastlock_readval(phy->spi, tx, profile, 3); + buf[2] = ad9361_fastlock_readval(phy->spi, tx, profile, 2); + buf[3] = ad9361_fastlock_readval(phy->spi, tx, profile, 1); + buf[4] = ad9361_fastlock_readval(phy->spi, tx, profile, 0); + vco_div = ad9361_fastlock_readval(phy->spi, tx, profile, 12) & 0xF; + + } else { + ad9361_spi_readm(clk_priv->spi, reg, &buf[0], ARRAY_SIZE(buf)); + vco_div = ad9361_spi_readf(clk_priv->spi, REG_RFPLL_DIVIDERS, div_mask); + } + + fract = (SYNTH_FRACT_WORD(buf[0]) << 16) | (buf[1] << 8) | buf[2]; + integer = (SYNTH_INTEGER_WORD(buf[3]) << 8) | buf[4]; + + return ad9361_to_clk(ad9361_calc_rfpll_int_freq(parent_rate, integer, + fract, vco_div)); +} + +/** + * Calculate the closest possible clock rate that can be set. + * @param clk_priv The refclk_scale structure. + * @param rate The clock rate. + * @param prate The parent clock rate. + * @return The closest possible clock rate that can be set. + */ +int32_t ad9361_rfpll_int_round_rate(struct refclk_scale *clk_priv, + uint32_t rate, + uint32_t *prate) +{ + dev_dbg(&clk_priv->spi->dev, "%s: Rate %"PRIu32" Hz", __func__, rate); + + if (prate) { + // Unused variable - fix compiler warning + } + + if (clk_priv) { + // Unused variable - fix compiler warning + } + + if (ad9361_from_clk(rate) > MAX_CARRIER_FREQ_HZ || + ad9361_from_clk(rate) < ((clk_priv->source == TX_RFPLL_INT) ? + MIN_TX_CARRIER_FREQ_HZ : MIN_RX_CARRIER_FREQ_HZ)) + return -EINVAL; + + return rate; +} + +/** + * Set the clock rate. + * @param clk_priv The refclk_scale structure. + * @param rate The clock rate. + * @param parent_rate The parent clock rate. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_rfpll_int_set_rate(struct refclk_scale *clk_priv, uint32_t rate, + uint32_t parent_rate) +{ + struct ad9361_rf_phy *phy = clk_priv->phy; + uint64_t vco = 0; + uint8_t buf[5]; + uint32_t reg, div_mask, lock_reg, fract = 0, integer = 0; + int32_t vco_div, ret, fixup_other; + + dev_dbg(&clk_priv->spi->dev, + "%s: %s Rate %"PRIu32" Hz Parent Rate %"PRIu32" Hz", + __func__, clk_priv->source == TX_RFPLL_INT ? "TX" : "RX", + rate, parent_rate); + + ad9361_fastlock_prepare(phy, clk_priv->source == TX_RFPLL_INT, 0, false); + + ret = ad9361_calc_rfpll_int_divder(phy, clk_priv, ad9361_from_clk(rate), + parent_rate, + &integer, &fract, &vco_div, &vco); + if (ret < 0) + return ret; + + switch (clk_priv->source) { + case RX_RFPLL_INT: + reg = REG_RX_FRACT_BYTE_2; + lock_reg = REG_RX_CP_OVERRANGE_VCO_LOCK; + div_mask = RX_VCO_DIVIDER(~0); + phy->cached_rx_rfpll_div = vco_div; + phy->current_rx_lo_freq = rate; + break; + case TX_RFPLL_INT: + reg = REG_TX_FRACT_BYTE_2; + lock_reg = REG_TX_CP_OVERRANGE_VCO_LOCK; + div_mask = TX_VCO_DIVIDER(~0); + phy->cached_tx_rfpll_div = vco_div; + phy->current_tx_lo_freq = rate; + break; + default: + return -EINVAL; + + } + + /* Option to skip VCO cal in TDD mode when moving from TX/RX to Alert */ + if (phy->pdata->tdd_skip_vco_cal) + ad9361_trx_vco_cal_control(phy, clk_priv->source == TX_RFPLL_INT, + true); + + do { + fixup_other = 0; + ad9361_rfpll_vco_init(phy, div_mask == TX_VCO_DIVIDER(~0), + vco, parent_rate); + + buf[0] = SYNTH_FRACT_WORD(fract >> 16); + buf[1] = fract >> 8; + buf[2] = fract & 0xFF; + buf[3] = SYNTH_INTEGER_WORD(integer >> 8) | + (~SYNTH_INTEGER_WORD(~0) & + ad9361_spi_read(clk_priv->spi, reg - 3)); + buf[4] = integer & 0xFF; + + ad9361_spi_writem(clk_priv->spi, reg, buf, 5); + ad9361_spi_writef(clk_priv->spi, REG_RFPLL_DIVIDERS, div_mask, vco_div); + + ret = ad9361_check_cal_done(phy, lock_reg, VCO_LOCK, 1); + + /* In FDD mode with RX LO == TX LO frequency we use TDD tables to + * reduce VCO pulling + */ + + if (((phy->pdata->fdd && !phy->pdata->fdd_independent_mode) && + (phy->current_tx_lo_freq == phy->current_rx_lo_freq) && + (phy->current_tx_use_tdd_table != phy->current_rx_use_tdd_table)) || + ((phy->pdata->fdd && !phy->pdata->fdd_independent_mode) && + (phy->current_tx_lo_freq != phy->current_rx_lo_freq) && + (phy->current_tx_use_tdd_table || phy->current_rx_use_tdd_table))) { + unsigned long _rate; + + switch (clk_priv->source) { + case RX_RFPLL_INT: + reg = REG_TX_FRACT_BYTE_2; + lock_reg = REG_TX_CP_OVERRANGE_VCO_LOCK; + div_mask = TX_VCO_DIVIDER(~0); + _rate = phy->current_tx_lo_freq; + break; + case TX_RFPLL_INT: + reg = REG_RX_FRACT_BYTE_2; + lock_reg = REG_RX_CP_OVERRANGE_VCO_LOCK; + div_mask = RX_VCO_DIVIDER(~0); + _rate = phy->current_rx_lo_freq; + break; + default: + return -EINVAL; + + } + + if (phy->current_tx_lo_freq != phy->current_rx_lo_freq) { + ad9361_calc_rfpll_int_divder(phy, clk_priv, ad9361_from_clk(_rate), + parent_rate, &integer, &fract, &vco_div, &vco); + + ad9361_fastlock_prepare(phy, clk_priv->source == RX_RFPLL_INT, 0, false); + } + + fixup_other = 1; + } + + } while (fixup_other); + + if (phy->pdata->tdd_skip_vco_cal) + ad9361_trx_vco_cal_control(phy, clk_priv->source == TX_RFPLL_INT, + false); + + return ret; +} + +/** + * Recalculate the clock rate. + * @param clk_priv The refclk_scale structure. + * @return The clock rate. + */ +uint32_t ad9361_rfpll_dummy_recalc_rate(struct refclk_scale *clk_priv) +{ + struct ad9361_rf_phy *phy = clk_priv->phy; + + return phy->clks[clk_priv->source]->rate; +} + +/** + * Set the clock rate. + * @param clk_priv The refclk_scale structure. + * @param rate The clock rate. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_rfpll_dummy_set_rate(struct refclk_scale *clk_priv, + uint32_t rate) +{ + struct ad9361_rf_phy *phy = clk_priv->phy; + + phy->clks[clk_priv->source]->rate = rate; + + return 0; +} + +/** + * Recalculate the clock rate. + * @param clk_priv The refclk_scale structure. + * @return The clock rate. + */ +uint32_t ad9361_rfpll_recalc_rate(struct refclk_scale *clk_priv) +{ + struct ad9361_rf_phy *phy = clk_priv->phy; + uint32_t rate; + + switch (clk_priv->source) { + case RX_RFPLL: + if (phy->pdata->use_ext_rx_lo) { + if (phy->ad9361_rfpll_ext_recalc_rate) + rate = phy->ad9361_rfpll_ext_recalc_rate(clk_priv); + else + rate = ad9361_rfpll_dummy_recalc_rate(phy->ref_clk_scale[RX_RFPLL_DUMMY]); + } else { + rate = ad9361_rfpll_int_recalc_rate(phy->ref_clk_scale[RX_RFPLL_INT], + phy->clks[RX_REFCLK]->rate); + } + break; + case TX_RFPLL: + if (phy->pdata->use_ext_tx_lo) { + if (phy->ad9361_rfpll_ext_recalc_rate) + rate = phy->ad9361_rfpll_ext_recalc_rate(clk_priv); + else + rate = ad9361_rfpll_dummy_recalc_rate(phy->ref_clk_scale[TX_RFPLL_DUMMY]); + } else { + rate = ad9361_rfpll_int_recalc_rate(phy->ref_clk_scale[TX_RFPLL_INT], + phy->clks[TX_REFCLK]->rate); + } + break; + default: + rate = 0; + break; + } + + return rate; +} + +/** + * Calculate the closest possible clock rate that can be set. + * @param clk_priv The refclk_scale structure. + * @param rate The clock rate. + * @return The closest possible clock rate that can be set. + */ +int32_t ad9361_rfpll_round_rate(struct refclk_scale *clk_priv, uint32_t rate) +{ + struct ad9361_rf_phy *phy = clk_priv->phy; + int32_t round_rate; + + switch (clk_priv->source) { + case RX_RFPLL: + if (phy->pdata->use_ext_rx_lo) { + if (phy->ad9361_rfpll_ext_round_rate) + round_rate = phy->ad9361_rfpll_ext_round_rate(clk_priv, rate); + else + round_rate = rate; + } else { + round_rate = ad9361_rfpll_int_round_rate(phy->ref_clk_scale[RX_RFPLL_INT], rate, + &phy->clks[phy->ref_clk_scale[RX_RFPLL_INT]->parent_source]->rate); + } + break; + case TX_RFPLL: + if (phy->pdata->use_ext_tx_lo) { + if (phy->ad9361_rfpll_ext_round_rate) + round_rate = phy->ad9361_rfpll_ext_round_rate(clk_priv, rate); + else + round_rate = rate; + } else { + round_rate = ad9361_rfpll_int_round_rate(phy->ref_clk_scale[TX_RFPLL_INT], rate, + &phy->clks[phy->ref_clk_scale[TX_RFPLL_INT]->parent_source]->rate); + } + break; + default: + round_rate = 0; + break; + } + + return round_rate; +} + +/** + * Set the clock rate. + * @param clk_priv The refclk_scale structure. + * @param rate The clock rate. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_rfpll_set_rate(struct refclk_scale *clk_priv, uint32_t rate) +{ + struct ad9361_rf_phy *phy = clk_priv->phy; + int32_t ret; + + switch (clk_priv->source) { + case RX_RFPLL: + if (phy->pdata->use_ext_rx_lo) { + if (phy->ad9361_rfpll_ext_set_rate) + phy->ad9361_rfpll_ext_set_rate(clk_priv, rate); + else + ad9361_rfpll_dummy_set_rate(phy->ref_clk_scale[RX_RFPLL_DUMMY], rate); + } else { + ad9361_rfpll_int_set_rate(phy->ref_clk_scale[RX_RFPLL_INT], rate, + phy->clks[phy->ref_clk_scale[RX_RFPLL_INT]->parent_source]->rate); + } + /* Load Gain Table */ + ret = ad9361_load_gt(phy, ad9361_from_clk(rate), GT_RX1 + GT_RX2); + if (ret < 0) + return ret; + break; + case TX_RFPLL: + if (phy->pdata->use_ext_tx_lo) { + if (phy->ad9361_rfpll_ext_set_rate) + phy->ad9361_rfpll_ext_set_rate(clk_priv, rate); + else + ad9361_rfpll_dummy_set_rate(phy->ref_clk_scale[TX_RFPLL_DUMMY], rate); + } else { + ad9361_rfpll_int_set_rate(phy->ref_clk_scale[TX_RFPLL_INT], rate, + phy->clks[phy->ref_clk_scale[TX_RFPLL_INT]->parent_source]->rate); + } + /* For RX LO we typically have the tracking option enabled + * so for now do nothing here. + */ + if (phy->auto_cal_en && !phy->pdata->use_ext_tx_lo) + if ((diff_abs(phy->last_tx_quad_cal_freq, ad9361_from_clk(rate))) > + phy->cal_threshold_freq) { + ret = ad9361_do_calib_run(phy, TX_QUAD_CAL, -1); + if (ret < 0) + dev_err(&phy->spi->dev, + "%s: TX QUAD cal failed", __func__); + phy->last_tx_quad_cal_freq = ad9361_from_clk(rate); + } + break; + default: + break; + } + + return 0; +} + +/** + * Set clock mux parent. + * @param clk_priv The refclk_scale structure. + * @param index Index - Enable (1), disable (0) ext lo. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_clk_mux_set_parent(struct refclk_scale *clk_priv, uint8_t index) +{ + struct ad9361_rf_phy *phy = clk_priv->phy; + int32_t ret; + + dev_dbg(&clk_priv->spi->dev, "%s: index %d", __func__, index); + + ad9361_ensm_force_state(phy, ENSM_STATE_ALERT); + + ret = ad9361_trx_ext_lo_control(phy, clk_priv->source == TX_RFPLL, index == 1); + if (ret >= 0) + clk_priv->mult = index; + + ad9361_ensm_restore_prev_state(phy); + + return ret; +} + +/** + * Register and initialize a new clock. + * @param phy The AD9361 state structure. + * @param name The name of the new clock. + * @param parent_name The name of the parent clock. + * @param flags The flags. + * @param source The source of the new clock. + * @param parent_source The source of the parent clock. + * @return A struct clk for the new clock or a negative error code. + */ +static struct clk *ad9361_clk_register(struct ad9361_rf_phy *phy, + const char *name, + const char *parent_name, uint32_t flags, + uint32_t source, uint32_t parent_source) +{ + struct refclk_scale *clk_priv; + struct clk *clk; + + if (name) { + // Unused variable - fix compiler warning + } + if (parent_name) { + // Unused variable - fix compiler warning + } + if (flags) { + // Unused variable - fix compiler warning + } + + clk_priv = (struct refclk_scale *)malloc(sizeof(*clk_priv)); + if (!clk_priv) { + dev_err(&phy->spi->dev, + "ad9361_clk_register: could not allocate fixed factor clk"); + return (struct clk *)ERR_PTR(-ENOMEM); + } + + /* struct refclk_scale assignments */ + clk_priv->source = (enum ad9361_clocks)source; + clk_priv->parent_source = (enum ad9361_clocks)parent_source; + clk_priv->spi = phy->spi; + clk_priv->phy = phy; + + phy->ref_clk_scale[source] = clk_priv; + + clk = (struct clk *)malloc(sizeof(*clk)); + if (!clk) { + free(clk_priv); + return (struct clk *)ERR_PTR(-ENOMEM); + } + + switch (source) { + case TX_REFCLK: + clk->rate = ad9361_clk_factor_recalc_rate(clk_priv, phy->clk_refin->rate); + break; + case RX_REFCLK: + clk->rate = ad9361_clk_factor_recalc_rate(clk_priv, phy->clk_refin->rate); + break; + case BB_REFCLK: + clk->rate = ad9361_clk_factor_recalc_rate(clk_priv, phy->clk_refin->rate); + break; + case BBPLL_CLK: + clk->rate = ad9361_bbpll_recalc_rate(clk_priv, phy->clks[BB_REFCLK]->rate); + break; + case ADC_CLK: + clk->rate = ad9361_clk_factor_recalc_rate(clk_priv, phy->clks[BBPLL_CLK]->rate); + break; + case R2_CLK: + clk->rate = ad9361_clk_factor_recalc_rate(clk_priv, phy->clks[ADC_CLK]->rate); + break; + case R1_CLK: + clk->rate = ad9361_clk_factor_recalc_rate(clk_priv, phy->clks[R2_CLK]->rate); + break; + case CLKRF_CLK: + clk->rate = ad9361_clk_factor_recalc_rate(clk_priv, phy->clks[R1_CLK]->rate); + break; + case RX_SAMPL_CLK: + clk->rate = ad9361_clk_factor_recalc_rate(clk_priv, phy->clks[CLKRF_CLK]->rate); + break; + case DAC_CLK: + clk->rate = ad9361_clk_factor_recalc_rate(clk_priv, phy->clks[ADC_CLK]->rate); + break; + case T2_CLK: + clk->rate = ad9361_clk_factor_recalc_rate(clk_priv, phy->clks[DAC_CLK]->rate); + break; + case T1_CLK: + clk->rate = ad9361_clk_factor_recalc_rate(clk_priv, phy->clks[T2_CLK]->rate); + break; + case CLKTF_CLK: + clk->rate = ad9361_clk_factor_recalc_rate(clk_priv, phy->clks[T1_CLK]->rate); + break; + case TX_SAMPL_CLK: + clk->rate = ad9361_clk_factor_recalc_rate(clk_priv, phy->clks[CLKTF_CLK]->rate); + break; + case RX_RFPLL_INT: + clk->rate = ad9361_rfpll_int_recalc_rate(clk_priv, phy->clks[RX_REFCLK]->rate); + break; + case TX_RFPLL_INT: + clk->rate = ad9361_rfpll_int_recalc_rate(clk_priv, phy->clks[TX_REFCLK]->rate); + break; + case RX_RFPLL_DUMMY: + clk->rate = phy->pdata->rx_synth_freq; + break; + case TX_RFPLL_DUMMY: + clk->rate = phy->pdata->tx_synth_freq; + break; + case RX_RFPLL: + clk->rate = ad9361_rfpll_recalc_rate(clk_priv); + break; + case TX_RFPLL: + clk->rate = ad9361_rfpll_recalc_rate(clk_priv); + } + + return clk; +} + +/** + * Register and initialize all the system clocks. + * @param phy The AD9361 state structure. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_register_clocks(struct ad9361_rf_phy *phy) +{ + uint32_t flags = CLK_GET_RATE_NOCACHE; + + /* Scaled Reference Clocks */ + phy->clks[TX_REFCLK] = ad9361_clk_register(phy, + "tx_refclk", "ad9361_ext_refclk", + flags | CLK_IGNORE_UNUSED, + TX_REFCLK, EXT_REF_CLK); + + phy->clks[RX_REFCLK] = ad9361_clk_register(phy, + "rx_refclk", "ad9361_ext_refclk", + flags | CLK_IGNORE_UNUSED, + RX_REFCLK, EXT_REF_CLK); + + phy->clks[BB_REFCLK] = ad9361_clk_register(phy, + "bb_refclk", "ad9361_ext_refclk", + flags | CLK_IGNORE_UNUSED, + BB_REFCLK, EXT_REF_CLK); + + /* Base Band PLL Clock */ + phy->clks[BBPLL_CLK] = ad9361_clk_register(phy, + "bbpll_clk", "bb_refclk", + flags | CLK_IGNORE_UNUSED, + BBPLL_CLK, BB_REFCLK); + + phy->clks[ADC_CLK] = ad9361_clk_register(phy, + "adc_clk", "bbpll_clk", + flags | CLK_IGNORE_UNUSED, + ADC_CLK, BBPLL_CLK); + + phy->clks[R2_CLK] = ad9361_clk_register(phy, + "r2_clk", "adc_clk", + flags | CLK_IGNORE_UNUSED, + R2_CLK, ADC_CLK); + + phy->clks[R1_CLK] = ad9361_clk_register(phy, + "r1_clk", "r2_clk", + flags | CLK_IGNORE_UNUSED, + R1_CLK, R2_CLK); + + phy->clks[CLKRF_CLK] = ad9361_clk_register(phy, + "clkrf_clk", "r1_clk", + flags | CLK_IGNORE_UNUSED, + CLKRF_CLK, R1_CLK); + + phy->clks[RX_SAMPL_CLK] = ad9361_clk_register(phy, + "rx_sampl_clk", "clkrf_clk", + flags | CLK_IGNORE_UNUSED, + RX_SAMPL_CLK, CLKRF_CLK); + + + phy->clks[DAC_CLK] = ad9361_clk_register(phy, + "dac_clk", "adc_clk", + flags | CLK_IGNORE_UNUSED, + DAC_CLK, ADC_CLK); + + phy->clks[T2_CLK] = ad9361_clk_register(phy, + "t2_clk", "dac_clk", + flags | CLK_IGNORE_UNUSED, + T2_CLK, DAC_CLK); + + phy->clks[T1_CLK] = ad9361_clk_register(phy, + "t1_clk", "t2_clk", + flags | CLK_IGNORE_UNUSED, + T1_CLK, T2_CLK); + + phy->clks[CLKTF_CLK] = ad9361_clk_register(phy, + "clktf_clk", "t1_clk", + flags | CLK_IGNORE_UNUSED, + CLKTF_CLK, T1_CLK); + + phy->clks[TX_SAMPL_CLK] = ad9361_clk_register(phy, + "tx_sampl_clk", "clktf_clk", + flags | CLK_IGNORE_UNUSED, + TX_SAMPL_CLK, CLKTF_CLK); + + phy->clks[RX_RFPLL_INT] = ad9361_clk_register(phy, + "rx_rfpll", "rx_refclk", + flags | CLK_IGNORE_UNUSED, + RX_RFPLL_INT, RX_REFCLK); + + phy->clks[TX_RFPLL_INT] = ad9361_clk_register(phy, + "tx_rfpll", "tx_refclk", + flags | CLK_IGNORE_UNUSED, + TX_RFPLL_INT, TX_REFCLK); + + phy->clks[RX_RFPLL_DUMMY] = ad9361_clk_register(phy, + "rx_rfpll_dummy", NULL, + flags | CLK_IGNORE_UNUSED, + RX_RFPLL_DUMMY, 0); + + phy->clks[TX_RFPLL_DUMMY] = ad9361_clk_register(phy, + "tx_rfpll_dummy", NULL, + flags | CLK_IGNORE_UNUSED, + TX_RFPLL_DUMMY, 0); + + phy->clks[RX_RFPLL] = ad9361_clk_register(phy, + "rx_rfpll", NULL, + flags | CLK_IGNORE_UNUSED, + RX_RFPLL, 0); + + phy->clks[TX_RFPLL] = ad9361_clk_register(phy, + "tx_rfpll", NULL, + flags | CLK_IGNORE_UNUSED, + TX_RFPLL, 0); + + return 0; +} + +/** + * Unregister all the system clocks. + * @param phy The AD9361 state structure. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_unregister_clocks(struct ad9361_rf_phy *phy) +{ + int32_t i; + + for (i = 0; i < NUM_AD9361_CLKS; i++) { + free(phy->clks[i]); + free(phy->ref_clk_scale[i]); + } + + return 0; +} + +/** + * Perform an RSSI gain step calibration. + * Note: Before running the function, provide a single tone within the channel + * bandwidth and monitor the received data. Adjust the tone amplitude until + * the received data is within a few dB of full scale but not overloading. + * @param phy The AD9361 state structure. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_rssi_gain_step_calib(struct ad9361_rf_phy *phy) +{ + uint32_t lna_error[4]; + uint32_t mixer_error[15]; + uint64_t lo_freq_hz; + uint8_t lo_index; + uint8_t i; + + lo_freq_hz = ad9361_from_clk(clk_get_rate(phy, + phy->ref_clk_scale[RX_RFPLL])); + if (lo_freq_hz < 1300000000ULL) + lo_index = 0; + else if (lo_freq_hz < 3300000000ULL) + lo_index = 1; + else if (lo_freq_hz < 4100000000ULL) + lo_index = 2; + else + lo_index = 3; + + /* Put the AD9361 into the Alert state. */ + ad9361_ensm_force_state(phy, ENSM_STATE_ALERT); + + /* Program the directly-addressable register values. */ + ad9361_spi_write(phy->spi, REG_MAX_MIXER_CALIBRATION_GAIN_INDEX, + MAX_MIXER_CALIBRATION_GAIN_INDEX(0x0F)); + ad9361_spi_write(phy->spi, REG_MEASURE_DURATION, + GAIN_CAL_MEAS_DURATION(0x0E)); + ad9361_spi_write(phy->spi, REG_SETTLE_TIME, + SETTLE_TIME(0x3F)); + ad9361_spi_write(phy->spi, REG_RSSI_CONFIG, + RSSI_MODE_SELECT(0x3) | DEFAULT_RSSI_MEAS_MODE); + ad9361_spi_write(phy->spi, REG_MEASURE_DURATION_01, + MEASUREMENT_DURATION_0(0x0E)); + ad9361_spi_write(phy->spi, REG_LNA_GAIN, + gain_step_calib_reg_val[lo_index][0]); + + /* Program the LNA gain step words into the internal table. */ + ad9361_spi_write(phy->spi, REG_CONFIG, + CALIB_TABLE_SELECT(0x3) | START_CALIB_TABLE_CLOCK); + for(i = 0; i < 4; i++) { + ad9361_spi_write(phy->spi, REG_WORD_ADDRESS, i); + ad9361_spi_write(phy->spi, REG_GAIN_DIFF_WORDERROR_WRITE, + gain_step_calib_reg_val[lo_index][i+1]); + ad9361_spi_write(phy->spi, REG_CONFIG, + CALIB_TABLE_SELECT(0x3) | WRITE_LNA_GAIN_DIFF | START_CALIB_TABLE_CLOCK); + udelay(3); //Wait for data to fully write to internal table + } + + ad9361_spi_write(phy->spi, REG_CONFIG, START_CALIB_TABLE_CLOCK); + ad9361_spi_write(phy->spi, REG_CONFIG, 0x00); + + /* Run and wait until the calibration completes. */ + ad9361_run_calibration(phy, RX_GAIN_STEP_CAL); + + /* Read the LNA and Mixer error terms into nonvolatile memory. */ + ad9361_spi_write(phy->spi, REG_CONFIG, CALIB_TABLE_SELECT(0x1) | READ_SELECT); + for(i = 0; i < 4; i++) { + ad9361_spi_write(phy->spi, REG_WORD_ADDRESS, i); + lna_error[i] = ad9361_spi_read(phy->spi, REG_GAIN_ERROR_READ); + } + ad9361_spi_write(phy->spi, REG_CONFIG, CALIB_TABLE_SELECT(0x1)); + for(i = 0; i < 15; i++) { + ad9361_spi_write(phy->spi, REG_WORD_ADDRESS, i); + mixer_error[i] = ad9361_spi_read(phy->spi, REG_GAIN_ERROR_READ); + } + ad9361_spi_write(phy->spi, REG_CONFIG, 0x00); + + /* Programming gain step errors into the AD9361 in the field */ + ad9361_spi_write(phy->spi, + REG_CONFIG, CALIB_TABLE_SELECT(0x3) | START_CALIB_TABLE_CLOCK); + for(i = 0; i < 4; i++) { + ad9361_spi_write(phy->spi, REG_WORD_ADDRESS, i); + ad9361_spi_write(phy->spi, REG_GAIN_DIFF_WORDERROR_WRITE, lna_error[i]); + ad9361_spi_write(phy->spi, REG_CONFIG, + CALIB_TABLE_SELECT(0x3) | WRITE_LNA_ERROR_TABLE | START_CALIB_TABLE_CLOCK); + } + ad9361_spi_write(phy->spi, REG_CONFIG, + CALIB_TABLE_SELECT(0x3) | START_CALIB_TABLE_CLOCK); + for(i = 0; i < 15; i++) { + ad9361_spi_write(phy->spi, REG_WORD_ADDRESS, i); + ad9361_spi_write(phy->spi, REG_GAIN_DIFF_WORDERROR_WRITE, mixer_error[i]); + ad9361_spi_write(phy->spi, REG_CONFIG, + CALIB_TABLE_SELECT(0x3) | WRITE_MIXER_ERROR_TABLE | START_CALIB_TABLE_CLOCK); + } + ad9361_spi_write(phy->spi, REG_CONFIG, 0x00); + + ad9361_ensm_restore_prev_state(phy); + + return 0; +} diff --git a/df_datalink/src/drivers/rf-transceiver/ad9361/ad9361.h b/df_datalink/src/drivers/rf-transceiver/ad9361/ad9361.h new file mode 100644 index 0000000..638acdc --- /dev/null +++ b/df_datalink/src/drivers/rf-transceiver/ad9361/ad9361.h @@ -0,0 +1,3568 @@ +/***************************************************************************//** + * @file ad9361.h + * @brief Header file of AD9361 Driver. +******************************************************************************** + * Copyright 2014(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ +#ifndef IIO_FREQUENCY_AD9361_H_ +#define IIO_FREQUENCY_AD9361_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include +#include "common.h" +#include "../../../include/gpio.h" + +/******************************************************************************/ +/********************** Macros and Constants Definitions **********************/ +/******************************************************************************/ +#define REG_SPI_CONF 0x000 /* SPI Configuration */ +#define REG_MULTICHIP_SYNC_AND_TX_MON_CTRL 0x001 /* Multi-Chip Sync and Tx Mon Control */ +#define REG_TX_ENABLE_FILTER_CTRL 0x002 /* Tx Enable & Filter Control */ +#define REG_RX_ENABLE_FILTER_CTRL 0x003 /* Rx Enable & Filter Control */ +#define REG_INPUT_SELECT 0x004 /* Input Select */ +#define REG_RFPLL_DIVIDERS 0x005 /* RFPLL Dividers */ +#define REG_RX_CLOCK_DATA_DELAY 0x006 /* Rx Clock & Data Delay */ +#define REG_TX_CLOCK_DATA_DELAY 0x007 /* Tx Clock & Data Delay */ +#define REG_CLOCK_ENABLE 0x009 /* Clock Enable */ +#define REG_BBPLL 0x00A /* BBPLL */ +#define REG_TEMP_OFFSET 0x00B /* Offset */ +#define REG_START_TEMP_READING 0x00C /* Start Temp Reading */ +#define REG_TEMP_SENSE2 0x00D /* Temp Sense2 */ +#define REG_TEMPERATURE 0x00E /* Temperature */ +#define REG_TEMP_SENSOR_CONFIG 0x00F /* Temp Sensor Config */ +#define REG_PARALLEL_PORT_CONF_1 0x010 /* Parallel Port Configuration 1 */ +#define REG_PARALLEL_PORT_CONF_2 0x011 /* Parallel Port Configuration 2 */ +#define REG_PARALLEL_PORT_CONF_3 0x012 /* Parallel Port Configuration 3 */ +#define REG_ENSM_MODE 0x013 /* ENSM Mode */ +#define REG_ENSM_CONFIG_1 0x014 /* ENSM Config 1 */ +#define REG_ENSM_CONFIG_2 0x015 /* ENSM Config 2 */ +#define REG_CALIBRATION_CTRL 0x016 /* Calibration Control */ +#define REG_STATE 0x017 /* State */ +#define REG_AUXDAC_1_WORD 0x018 /* AuxDAC 1 Word */ +#define REG_AUXDAC_2_WORD 0x019 /* AuxDAC 2 Word */ +#define REG_AUXDAC_1_CONFIG 0x01A /* AuxDAC 1 Config */ +#define REG_AUXDAC_2_CONFIG 0x01B /* AuxDAC 2 Config */ +#define REG_AUXADC_CLOCK_DIVIDER 0x01C /* AuxADC Clock Divider */ +#define REG_AUXADC_CONFIG 0x01D /* Aux ADC Config */ +#define REG_AUXADC_WORD_MSB 0x01E /* AuxADC Word MSB */ +#define REG_AUXADC_LSB 0x01F /* AuxADC LSB */ +#define REG_AUTO_GPO 0x020 /* Auto GPO */ +#define REG_AGC_GAIN_LOCK_DELAY 0x021 /* AGC Gain Lock Delay */ +#define REG_AGC_ATTACK_DELAY 0x022 /* AGC Attack Delay */ +#define REG_AUXDAC_ENABLE_CTRL 0x023 /* AuxDAC Enable Control */ +#define REG_RX_LOAD_SYNTH_DELAY 0x024 /* RX Load Synth Delay */ +#define REG_TX_LOAD_SYNTH_DELAY 0x025 /* TX Load Synth Delay */ +#define REG_EXTERNAL_LNA_CTRL 0x026 /* External LNA control */ +#define REG_GPO_FORCE_AND_INIT 0x027 /* GPO Force and Init */ +#define REG_GPO0_RX_DELAY 0x028 /* GPO0 Rx delay */ +#define REG_GPO1_RX_DELAY 0x029 /* GPO1 Rx delay */ +#define REG_GPO2_RX_DELAY 0x02A /* GPO2 Rx delay */ +#define REG_GPO3_RX_DELAY 0x02B /* GPO3 Rx delay */ +#define REG_GPO0_TX_DELAY 0x02C /* GPO0 Tx Delay */ +#define REG_GPO1_TX_DELAY 0x02D /* GPO1 Tx Delay */ +#define REG_GPO2_TX_DELAY 0x02E /* GPO2 Tx Delay */ +#define REG_GPO3_TX_DELAY 0x02F /* GPO3 Tx Delay */ +#define REG_AUXDAC1_RX_DELAY 0x030 /* AuxDAC1 Rx Delay */ +#define REG_AUXDAC1_TX_DELAY 0x031 /* AuxDAC1 Tx Delay */ +#define REG_AUXDAC2_RX_DELAY 0x032 /* AuxDAC2 Rx Delay */ +#define REG_AUXDAC2_TX_DELAY 0x033 /* AuxDAC2 Tx Delay */ +#define REG_CTRL_OUTPUT_POINTER 0x035 /* Control Output Pointer */ +#define REG_CTRL_OUTPUT_ENABLE 0x036 /* Control Output Enable */ +#define REG_PRODUCT_ID 0x037 /* Product ID */ +#define REG_REFERENCE_CLOCK_CYCLES 0x03A /* Reference Clock Cycles */ +#define REG_DIGITAL_IO_CTRL 0x03B /* Digital I/O Control */ +#define REG_LVDS_BIAS_CTRL 0x03C /* LVDS Bias control */ +#define REG_LVDS_INVERT_CTRL1 0x03D /* LVDS Invert control1 */ +#define REG_LVDS_INVERT_CTRL2 0x03E /* LVDS Invert control2 */ +#define REG_SDM_CTRL_1 0x03F /* SDM Control 1 */ +#define REG_FRACT_BB_FREQ_WORD_1 0x041 /* Fractional BB Freq Word 1 */ +#define REG_FRACT_BB_FREQ_WORD_2 0x042 /* Fractional BB Freq Word 2 */ +#define REG_FRACT_BB_FREQ_WORD_3 0x043 /* Fractional BB Freq Word 3 */ +#define REG_INTEGER_BB_FREQ_WORD 0x044 /* Integer BB Freq Word */ +#define REG_CLOCK_CTRL 0x045 /* Clock Control */ +#define REG_CP_CURRENT 0x046 /* CP Current */ +#define REG_CP_BLEED_CURRENT 0x047 /* CP Bleed Current */ +#define REG_LOOP_FILTER_1 0x048 /* Loop Filter 1 */ +#define REG_LOOP_FILTER_2 0x049 /* Loop Filter 2 */ +#define REG_LOOP_FILTER_3 0x04A /* Loop Filter 3 */ +#define REG_VCO_CTRL 0x04B /* VCO Control */ +#define REG_VCO_PROGRAM_1 0x04C +#define REG_VCO_PROGRAM_2 0x04D +#define REG_SDM_CTRL 0x04E /* SDM Control */ +#define REG_RX_SYNTH_POWER_DOWN_OVERRIDE 0x050 /* Rx Synth Power Down Override */ +#define REG_TX_SYNTH_POWER_DOWN_OVERRIDE 0x051 /* TX Synth Power Down Override */ +#define REG_RX_ANALOG_POWER_DOWN_OVERRIDE_1 0x052 /* Rx Analog Power Down Override 1 */ +#define REG_RX_ANALOG_POWER_DOWN_OVERRIDE_2 0x053 /* Rx Analog Power Down Override 2 */ +#define REG_RX1_ADC_POWER_DOWN_OVERRIDE 0x054 /* Rx1 ADC Power Down Override */ +#define REG_RX2_ADC_POWER_DOWN_OVERRIDE 0x055 /* Rx2 ADC Power Down Override */ +#define REG_TX_ANALOG_POWER_DOWN_OVERRIDE_1 0x056 /* Tx Analog Power Down Override 1 */ +#define REG_ANALOG_POWER_DOWN_OVERRIDE 0x057 /* Analog Power Down Override */ +#define REG_MISC_POWER_DOWN_OVERRIDE 0x058 /* Misc Power Down Override */ +#define REG_CH_1_OVERFLOW 0x05E /* CH 1 Overflow */ +#define REG_CH_2_OVERFLOW 0x05F /* CH 2 Overflow */ +#define REG_TX_FILTER_COEF_ADDR 0x060 /* TX Filter Coefficient Address */ +#define REG_TX_FILTER_COEF_WRITE_DATA_1 0x061 /* TX Filter Coefficient Write Data 1 */ +#define REG_TX_FILTER_COEF_WRITE_DATA_2 0x062 /* TX Filter Coefficient Write Data 2 */ +#define REG_TX_FILTER_COEF_READ_DATA_1 0x063 /* TX Filter Coefficient Read Data 1 */ +#define REG_TX_FILTER_COEF_READ_DATA_2 0x064 /* TX Filter Coefficient Read Data 2 */ +#define REG_TX_FILTER_CONF 0x065 /* TX Filter Configuration */ +#define REG_TX_MON_LOW_GAIN 0x067 /* Tx Mon Low Gain */ +#define REG_TX_MON_HIGH_GAIN 0x068 /* Tx Mon High Gain */ +#define REG_TX_MON_DELAY 0x069 /* Tx Mon Delay */ +#define REG_TX_LEVEL_THRESH 0x06A /* Tx Level Threshold */ +#define REG_TX_RSSI1 0x06B /* TX RSSI1 */ +#define REG_TX_RSSI2 0x06C /* TX RSSI2 */ +#define REG_TX_RSSI_LSB 0x06D /* TX RSSI LSB */ +#define REG_TPM_MODE_ENABLE 0x06E /* TPM Mode Enable */ +#define REG_TX_MON_TEMP_GAIN_COEF 0x06F /* Temp Gain Coefficient */ +#define REG_TX_MON_1_CONFIG 0x070 /* Tx Mon 1 Config */ +#define REG_TX_MON_2_CONFIG 0x071 /* Tx Mon 2 Config */ +#define REG_TX1_ATTEN_0 0x073 /* Tx1 Atten 0 */ +#define REG_TX1_ATTEN_1 0x074 /* Tx1 Atten 1 */ +#define REG_TX2_ATTEN_0 0x075 /* Tx2 Atten 0 */ +#define REG_TX2_ATTEN_1 0x076 /* Tx2 Atten 1 */ +#define REG_TX_ATTEN_OFFSET 0x077 /* Tx Atten Offset */ +#define REG_TX_ATTEN_THRESH 0x078 /* Tx Atten Threshold */ +#define REG_TX1_DIG_ATTEN 0x079 /* Tx1 Dig Attenuation */ +#define REG_TX2_DIG_ATTEN 0x07C /* Tx2 Dig Attenuation */ +#define REG_TX1_SYMBOL_ATTEN 0x07F /* TX1 Symbol Attenuation */ +#define REG_TX2_SYMBOL_ATTEN 0x080 /* TX2 Symbol Attenuation */ +#define REG_TX_SYMBOL_ATTEN_CONFIG 0x081 /* TX Symbol Atten Config */ +#define REG_TX1_OUT_1_PHASE_CORR 0x08E /* Tx1 Out 1 Phase Corr */ +#define REG_TX1_OUT_1_GAIN_CORR 0x08F /* Tx1 Out 1 Gain Corr */ +#define REG_TX2_OUT_1_PHASE_CORR 0x090 /* Tx2 Out 1 Phase Corr */ +#define REG_TX2_OUT_1_GAIN_CORR 0x091 /* Tx2 Out 1 Gain Corr */ +#define REG_TX1_OUT_1_OFFSET_I 0x092 /* Tx1 Out 1 Offset I */ +#define REG_TX1_OUT_1_OFFSET_Q 0x093 /* Tx1 Out 1 Offset Q */ +#define REG_TX2_OUT_1_OFFSET_I 0x094 /* Tx2 Out 1 Offset I */ +#define REG_TX2_OUT_1_OFFSET_Q 0x095 /* Tx2 Out 1 Offset Q */ +#define REG_TX1_OUT_2_PHASE_CORR 0x096 /* Tx1 Out 2 Phase Corr */ +#define REG_TX1_OUT_2_GAIN_CORR 0x097 /* Tx1 Out 2 Gain Corr */ +#define REG_TX2_OUT_2_PHASE_CORR 0x098 /* Tx2 Out 2 Phase Corr */ +#define REG_TX2_OUT_2_GAIN_CORR 0x099 /* Tx2 Out 2 Gain Corr */ +#define REG_TX1_OUT_2_OFFSET_I 0x09A /* Tx1 Out 2 Offset I */ +#define REG_TX1_OUT_2_OFFSET_Q 0x09B /* Tx1 Out 2 Offset Q */ +#define REG_TX2_OUT_2_OFFSET_I 0x09C /* Tx2 Out 2 Offset I */ +#define REG_TX2_OUT_2_OFFSET_Q 0x09D /* Tx2 Out 2 Offset Q */ +#define REG_TX_FORCE_BITS 0x09F /* Force Bits */ +#define REG_QUAD_CAL_NCO_FREQ_PHASE_OFFSET 0x0A0 /* Quad Cal NCO Freq & Phase Offset */ +#define REG_QUAD_CAL_CTRL 0x0A1 /* Quad Cal Control */ +#define REG_KEXP_1 0x0A2 /* Kexp 1 */ +#define REG_KEXP_2 0x0A3 /* Kexp 2 */ +#define REG_QUAD_SETTLE_COUNT 0x0A4 /* QUAD Settle count */ +#define REG_MAG_FTEST_THRESH 0x0A5 /* Mag. Ftest Thresh */ +#define REG_MAG_FTEST_THRESH_2 0x0A6 /* Mag. Ftest Thresh 2 */ +#define REG_QUAD_CAL_STATUS_TX1 0x0A7 /* Quad cal status Tx1 */ +#define REG_QUAD_CAL_STATUS_TX2 0x0A8 /* Quad cal status Tx2 */ +#define REG_QUAD_CAL_COUNT 0x0A9 /* Quad cal Count */ +#define REG_TX_QUAD_FULL_LMT_GAIN 0x0AA /* Tx Quad Full/LMT Gain */ +#define REG_SQUARER_CONFIG 0x0AB /* Squarer Config */ +#define REG_TX_QUAD_CAL_ATTEN 0x0AC /* TX Quad Cal Atten */ +#define REG_THRESH_ACCUM 0x0AD /* Thresh Accum */ +#define REG_TX_QUAD_LPF_GAIN 0x0AE /* Tx Quad LPF Gain */ +#define REG_TXDAC_VDS_I 0x0B0 /* TxDAC Vds I */ +#define REG_TXDAC_VDS_Q 0x0B1 /* TxDAC Vds Q */ +#define REG_TXDAC_GN_I 0x0B2 /* TxDAC gn I */ +#define REG_TXDAC_GN_Q 0x0B3 /* TxDAC gn Q */ +#define REG_TXBBF_OPAMP_A 0x0C0 /* TxBBF OpAmp A */ +#define REG_TXBBF_OPAMP_B 0x0C1 /* TxBBF OpAmp B */ +#define REG_TX_BBF_R1 0x0C2 /* Tx BBF R1 */ +#define REG_TX_BBF_R2 0x0C3 /* Tx BBF R2 */ +#define REG_TX_BBF_R3 0x0C4 /* Tx BBF R3 */ +#define REG_TX_BBF_R4 0x0C5 /* Tx BBF R4 */ +#define REG_TX_BBF_RP 0x0C6 /* Tx BBF RP */ +#define REG_TX_BBF_C1 0x0C7 /* Tx BBF C1 */ +#define REG_TX_BBF_C2 0x0C8 /* Tx BBF C2 */ +#define REG_TX_BBF_CP 0x0C9 /* Tx BBF Cp */ +#define REG_TX_TUNE_CTRL 0x0CA /* Tx Tune Control */ +#define REG_TX_BBF_R2B 0x0CB /* Tx BBF R2b */ +#define REG_TX_BBF_TUNE 0x0CC /* Tx BBF Tune */ +#define REG_CONFIG0 0x0D0 /* Config0 */ +#define REG_RESISTOR 0x0D1 /* Resistor */ +#define REG_CAPACITOR 0x0D2 /* Capacitor */ +#define REG_LO_CM 0x0D3 /* LO CM */ +#define REG_TX_BBF_TUNE_DIVIDER 0x0D6 /* TX BBF Tune Divider */ +#define REG_TX_BBF_TUNE_MODE 0x0D7 /* TX BBF Tune Mode */ +#define REG_RX_FILTER_COEF_ADDR 0x0F0 /* Rx Filter Coeff Addr */ +#define REG_RX_FILTER_COEF_DATA_1 0x0F1 /* Rx Filter Coeff Data 1 */ +#define REG_RX_FILTER_COEF_DATA_2 0x0F2 /* Rx Filter Coeff Data 2 */ +#define REG_RX_FILTER_COEF_READ_DATA_1 0x0F3 /* Rx Filter Coeff Read Data 1 */ +#define REG_RX_FILTER_COEF_READ_DATA_2 0x0F4 /* Rx Filter Coeff Read Data 2 */ +#define REG_RX_FILTER_CONFIG 0x0F5 /* Rx Filter Config */ +#define REG_RX_FILTER_GAIN 0x0F6 /* Rx Filter Gain */ +#define REG_AGC_CONFIG_1 0x0FA /* AGC Config1 */ +#define REG_AGC_CONFIG_2 0x0FB /* AGC config2 */ +#define REG_AGC_CONFIG_3 0x0FC /* AGC Config3 */ +#define REG_MAX_LMT_FULL_GAIN 0x0FD /* Max LMT/Full Gain */ +#define REG_PEAK_WAIT_TIME 0x0FE /* Peak Wait Time */ +#define REG_DIGITAL_GAIN 0x100 /* Digital Gain */ +#define REG_AGC_LOCK_LEVEL 0x101 /* AGC Lock Level */ +#define REG_ADC_NOISE_CORRECTION_FACTOR 0x102 /* ADC noise Correction Factor */ +#define REG_GAIN_STP_CONFIG1 0x103 /* Gain Step Config1 */ +#define REG_ADC_SMALL_OVERLOAD_THRESH 0x104 /* ADC Small Overload Threshold */ +#define REG_ADC_LARGE_OVERLOAD_THRESH 0x105 /* ADC Large Overload Threshold */ +#define REG_GAIN_STP_CONFIG_2 0x106 /* Gain Step Config 2 */ +#define REG_SMALL_LMT_OVERLOAD_THRESH 0x107 /* Small LMT Overload Threshold */ +#define REG_LARGE_LMT_OVERLOAD_THRESH 0x108 /* Large LMT Overload Threshold */ +#define REG_RX1_MANUAL_LMT_FULL_GAIN 0x109 /* Rx1 Manual LMT/Full Gain */ +#define REG_RX1_MANUAL_LPF_GAIN 0x10A /* Rx1 Manual LPF gain */ +#define REG_RX1_MANUAL_DIGITALFORCED_GAIN 0x10B /* Rx1 Manual Digital/Forced Gain */ +#define REG_RX2_MANUAL_LMT_FULL_GAIN 0x10C /* Rx2 Manual LMT/Full Gain */ +#define REG_RX2_MANUAL_LPF_GAIN 0x10D /* Rx2 Manual LPF Gain */ +#define REG_RX2_MANUAL_DIGITALFORCED_GAIN 0x10E /* Rx2 Manual Digital/Forced Gain */ +#define REG_FAST_CONFIG_1 0x110 /* Config 1 */ +#define REG_FAST_CONFIG_2_SETTLING_DELAY 0x111 /* Config 2 & Settling Delay */ +#define REG_FAST_ENERGY_LOST_THRESH 0x112 /* Energy Lost Threshold */ +#define REG_FAST_STRONGER_SIGNAL_THRESH 0x113 /* Stronger Signal Threshold */ +#define REG_FAST_LOW_POWER_THRESH 0x114 /* Low Power Threshold */ +#define REG_FAST_STRONG_SIGNAL_FREEZE 0x115 /* Strong Signal Freeze */ +#define REG_FAST_FINAL_OVER_RANGE_AND_OPT_GAIN 0x116 /* Final Over Range and Opt Gain */ +#define REG_FAST_ENERGY_DETECT_COUNT 0x117 /* Energy Detect Count */ +#define REG_FAST_AGCLL_UPPER_LIMIT 0x118 /* AGCLL Upper Limit */ +#define REG_FAST_GAIN_LOCK_EXIT_COUNT 0x119 /* Gain Lock Exit Count */ +#define REG_FAST_INITIAL_LMT_GAIN_LIMIT 0x11A /* Initial LMT Gain Limit */ +#define REG_FAST_INCREMENT_TIME 0x11B /* Increment Time */ +#define REG_AGC_INNER_LOW_THRESH 0x120 /* AGC Inner Low Threshold */ +#define REG_LMT_OVERLOAD_COUNTERS 0x121 /* LMT Overload Counters */ +#define REG_ADC_OVERLOAD_COUNTERS 0x122 /* ADC Overload Counters */ +#define REG_GAIN_STP1 0x123 /* Gain Step1 */ +#define REG_GAIN_UPDATE_COUNTER1 0x124 /* Gain Update Counter1 */ +#define REG_GAIN_UPDATE_COUNTER2 0x125 /* Gain Update Counter2 */ +#define REG_DIGITAL_SAT_COUNTER 0x128 /* Digital Sat Counter */ +#define REG_OUTER_POWER_THRESHS 0x129 /* Outer Power Thresholds */ +#define REG_GAIN_STP_2 0x12A /* Gain Step 2 */ +#define REG_EXT_LNA_HIGH_GAIN 0x12C /* Ext LNA High Gain */ +#define REG_EXT_LNA_LOW_GAIN 0x12D /* Ext LNA Low Gain */ +#define REG_GAIN_TABLE_ADDRESS 0x130 /* Gain Table Address */ +#define REG_GAIN_TABLE_WRITE_DATA1 0x131 /* Gain Table Write Data1 */ +#define REG_GAIN_TABLE_WRITE_DATA2 0x132 /* Gain Table Write Data2 */ +#define REG_GAIN_TABLE_WRITE_DATA3 0x133 /* Gain Table Write Data 3 */ +#define REG_GAIN_TABLE_READ_DATA1 0x134 /* Gain Table Read Data 1 */ +#define REG_GAIN_TABLE_READ_DATA2 0x135 /* Gain Table Read Data 2 */ +#define REG_GAIN_TABLE_READ_DATA3 0x136 /* Gain Table Read Data 3 */ +#define REG_GAIN_TABLE_CONFIG 0x137 /* Gain Table Config */ +#define REG_GM_SUB_TABLE_ADDRESS 0x138 /* Gm Sub Table Address */ +#define REG_GM_SUB_TABLE_GAIN_WRITE 0x139 /* Gm Sub Table Gain Word Write */ +#define REG_GM_SUB_TABLE_BIAS_WRITE 0x13A /* Gm Sub Table Bias Word Write */ +#define REG_GM_SUB_TABLE_CTRL_WRITE 0x13B /* Gm Sub Table Control Word Write */ +#define REG_GM_SUB_TABLE_GAIN_READ 0x13C /* Gm Sub Table Gain Word Read */ +#define REG_GM_SUB_TABLE_BIAS_READ 0x13D /* Gm Sub Table Bias Word Read */ +#define REG_GM_SUB_TABLE_CTRL_READ 0x13E /* Gm Sub Table Control Word Read */ +#define REG_GM_SUB_TABLE_CONFIG 0x13F /* Gm Sub Table Config */ +#define REG_WORD_ADDRESS 0x140 /* Word Address */ +#define REG_GAIN_DIFF_WORDERROR_WRITE 0x141 /* Gain Diff Word/Error Write */ +#define REG_GAIN_ERROR_READ 0x142 /* Gain Error Read */ +#define REG_CONFIG 0x143 /* Config */ +#define REG_LNA_GAIN_DIFF_READ_BACK 0x144 /* LNA Gain Diff Read Back */ +#define REG_MAX_MIXER_CALIBRATION_GAIN_INDEX 0x145 /* Max Mixer Calibration Gain Index */ +#define REG_TEMP_GAIN_COEF 0x146 /* Temp Gain Coefficient */ +#define REG_SETTLE_TIME 0x147 /* Settle Time */ +#define REG_MEASURE_DURATION 0x148 /* Measure Duration */ +#define REG_CAL_TEMP_SENSOR_WORD 0x149 /* Cal Temp sensor word */ +#define REG_MEASURE_DURATION_01 0x150 /* Measure Duration 0&1 */ +#define REG_MEASURE_DURATION_23 0x151 /* Measure Duration 2&3 */ +#define REG_RSSI_WEIGHT_0 0x152 /* RSSI Weight 0 */ +#define REG_RSSI_WEIGHT_1 0x153 /* RSSI Weight 1 */ +#define REG_RSSI_WEIGHT_2 0x154 /* RSSI Weight 2 */ +#define REG_RSSI_WEIGHT_3 0x155 /* RSSI Weight 3 */ +#define REG_RSSI_DELAY 0x156 /* RSSI delay */ +#define REG_RSSI_WAIT_TIME 0x157 /* RSSI wait time */ +#define REG_RSSI_CONFIG 0x158 /* RSSI Config */ +#define REG_ADC_MEASURE_DURATION_01 0x159 /* ADC Measure Duration 0&1 */ +#define REG_ADC_WEIGHT_0 0x15A /* ADC Weight 0 */ +#define REG_ADC_WEIGHT_1 0x15B /* ADC Weight 1 */ +#define REG_DEC_POWER_MEASURE_DURATION_0 0x15C /* Dec Power Measure Duration 0 */ +#define REG_LNA_GAIN 0x15D /* LNA Gain */ +#define REG_CH1_ADC_POWER 0x160 /* CH1 ADC Power */ +#define REG_CH1_RX_FILTER_POWER 0x161 /* CH1 Rx filter Power */ +#define REG_CH2_ADC_POWER 0x162 /* CH2 ADC Power */ +#define REG_CH2_RX_FILTER_POWER 0x163 /* CH2 Rx filter Power */ +#define REG_RX_QUAD_CAL_LEVEL 0x168 /* Rx Quad Cal Level */ +#define REG_CALIBRATION_CONFIG_1 0x169 /* Calibration Config 1 */ +#define REG_CALIBRATION_CONFIG_2 0x16A /* Calibration config2 */ +#define REG_CALIBRATION_CONFIG_3 0x16B /* Calibration config3 */ +#define REG_CALIB_COUNT 0x16C /* Calib count */ +#define REG_SETTLE_COUNT 0x16D /* Settle count */ +#define REG_RX_QUAD_GAIN1 0x16E /* Rx Quad gain1 */ +#define REG_RX_QUAD_GAIN2 0x16F /* Rx Quad gain2 */ +#define REG_RX1_INPUT_A_PHASE_CORR 0x170 /* Rx1 Input A Phase Corr */ +#define REG_RX1_INPUT_A_GAIN_CORR 0x171 /* Rx1 Input A Gain Corr */ +#define REG_RX2_INPUT_A_PHASE_CORR 0x172 /* Rx2 Input A Phase Corr */ +#define REG_RX2_INPUT_A_GAIN_CORR 0x173 /* Rx2 Input A Gain Corr */ +#define REG_RX1_INPUT_A_Q_OFFSET 0x174 /* Rx1 Input A Q" Offset */ +#define REG_RX1_INPUT_A_OFFSETS 0x175 /* Rx1 Input A Offsets */ +#define REG_INPUT_A_OFFSETS_1 0x176 /* Input A Offsets 1 */ +#define REG_RX2_INPUT_A_OFFSETS 0x177 /* Rx2 Input A Offsets */ +#define REG_RX2_INPUT_A_I_OFFSET 0x178 /* Rx2 Input A "I" Offset */ +#define REG_RX1_INPUT_BC_PHASE_CORR 0x179 /* Rx1 Input B&C Phase Corr */ +#define REG_RX1_INPUT_BC_GAIN_CORR 0x17A /* Rx1 Input B&C Gain Corr */ +#define REG_RX2_INPUT_BC_PHASE_CORR 0x17B /* Rx2 Input B&C Phase Corr */ +#define REG_RX2_INPUT_BC_GAIN_CORR 0x17C /* Rx2 Input B&C Gain Corr */ +#define REG_RX1_INPUT_BC_Q_OFFSET 0x17D /* Rx1 Input B&C "Q" Offset */ +#define REG_RX1_INPUT_BC_OFFSETS 0x17E /* Rx1 Input B&C Offsets */ +#define REG_INPUT_BC_OFFSETS_1 0x17F /* Input B&C Offsets 1 */ +#define REG_RX2_INPUT_BC_OFFSETS 0x180 /* Rx2 Input B&C Offsets */ +#define REG_RX2_INPUT_BC_I_OFFSET 0x181 /* Rx2 Input B&C "I" Offset */ +#define REG_FORCE_BITS 0x182 /* Force Bits */ +#define REG_WAIT_COUNT 0x185 /* Wait Count */ +#define REG_RF_DC_OFFSET_COUNT 0x186 /* RF DC Offset Count */ +#define REG_RF_DC_OFFSET_CONFIG_1 0x187 /* RF DC Offset Config1 */ +#define REG_RF_DC_OFFSET_ATTEN 0x188 /* RF DC Offset Attenuation */ +#define REG_INVERT_BITS 0x189 /* Invert Bits */ +#define REG_DC_OFFSET_CONFIG2 0x18B /* DC Offset Config2 */ +#define REG_RF_CAL_GAIN_INDEX 0x18C /* RF Cal Gain Index */ +#define REG_SOI_THRESH 0x18D /* SOI Threshold */ +#define REG_BB_DC_OFFSET_SHIFT 0x190 /* BB DC Offset Shift */ +#define REG_BB_DC_OFFSET_FAST_SETTLE_SHIFT 0x191 /* BB DC Offset Fast Settle Shift */ +#define REG_BB_FAST_SETTLE_DUR 0x192 /* BB Fast Settle Dur */ +#define REG_BB_DC_OFFSET_COUNT 0x193 /* BB DC Offset Count */ +#define REG_BB_DC_OFFSET_ATTEN 0x194 /* BB DC Offset Attenuation */ +#define REG_RX1_BB_DC_WORD_I_MSB 0x19A /* RX1 BB DC word I MSB */ +#define REG_RX1_BB_DC_WORD_I_LSB 0x19B /* RX1 BB DC word I LSB */ +#define REG_RX1_BB_DC_WORD_Q_MSB 0x19C /* RX1 BB DC word Q MSB */ +#define REG_RX1_BB_DC_WORD_Q_LSB 0x19D /* RX1 BB DC word Q LSB */ +#define REG_RX2_BB_DC_WORD_I_MSB 0x19E /* RX2 BB DC word I MSB */ +#define REG_RX2_BB_DC_WORD_I_LSB 0x19F /* RX2 BB DC word I LSB */ +#define REG_RX2_BB_DC_WORD_Q_MSB 0x1A0 /* RX2 BB DC word Q MSB */ +#define REG_RX2_BB_DC_WORD_Q_LSB 0x1A1 /* RX2 BB DC word Q LSB */ +#define REG_BB_TRACK_CORR_WORD_I_MSB 0x1A2 /* BB Track corr word I MSB */ +#define REG_BB_TRACK_CORR_WORD_I_LSB 0x1A3 /* BB Track corr word I LSB */ +#define REG_BB_TRACK_CORR_WORD_Q_MSB 0x1A4 /* BB Track corr word Q MSB */ +#define REG_BB_TRACK_CORR_WORD_Q_LSB 0x1A5 /* BB Track corr word Q LSB */ +#define REG_RX1_RSSI_SYMBOL 0x1A7 /* Rx1 RSSI Symbol */ +#define REG_RX1_RSSI_PREAMBLE 0x1A8 /* Rx1 RSSI preamble */ +#define REG_RX2_RSSI_SYMBOL 0x1A9 /* Rx2 RSSI symbol */ +#define REG_RX2_RSSI_PREAMBLE 0x1AA /* Rx2 RSSI preamble */ +#define REG_SYMBOL_LSB 0x1AB /* Symbol LSB */ +#define REG_PREAMBLE_LSB 0x1AC /* Preamble LSB */ +#define REG_RX_PATH_GAIN_MSB 0x1AD /* Rx Path Gain */ +#define REG_RX_PATH_GAIN_LSB 0x1AE /* Rx Path Gain */ +#define REG_RX_DIFF_LNA_FORCE 0x1B0 /* Rx Diff LNA Force */ +#define REG_RX_LNA_BIAS_COARSE 0x1B1 /* Rx LNA Bias Coarse */ +#define REG_RX_LNA_BIAS_FINE_0 0x1B2 /* Rx LNA Bias Fine 0 */ +#define REG_RX_LNA_BIAS_FINE_1 0x1B3 /* Rx LNA Bias Fine 1 */ +#define REG_RX_MIX_GM_CONFIG 0x1C0 /* Rx Mix Gm Config */ +#define REG_RX1_MIX_GM_FORCE 0x1C1 /* Rx1 Mix Gm Force */ +#define REG_RX1_MIX_GM_BIAS_FORCE 0x1C2 /* Rx1 Mix Gm Bias (Force) */ +#define REG_RX2_MIX_GM_FORCE 0x1C3 /* Rx2 Mix Gm Force */ +#define REG_RX2_MIX_GM_BIAS_FORCE 0x1C4 /* Rx2 Mix Gm Bias (Force) */ +#define REG_INPUT_A_MSBS 0x1C8 /* Input A MSBs */ +#define REG_INPUT_A_RX1_I 0x1C9 /* Input A RX1 I */ +#define REG_INPUT_A_RX1_Q 0x1CA /* Input A RX1 Q */ +#define REG_INPUT_A_RX2_I 0x1CB /* Input A RX2 I */ +#define REG_INPUT_A_RX2_Q 0x1CC /* Input A RX2 Q */ +#define REG_INPUTS_BC_RX1_I 0x1CD /* Inputs B&C RX1 I */ +#define REG_BAND1_RX1_Q 0x1CE /* Band1 RX1 Q */ +#define REG_INPUTS_BC_RX2_I 0x1CF /* Inputs B&C RX2 I */ +#define REG_INPUTS_BC_RX2_Q 0x1D0 /* Inputs B&C RX2 Q */ +#define REG_INPUTS_BC_MSBS 0x1D1 /* Inputs B&C MSBs */ +#define REG_FORCE_OS_DAC 0x1D2 /* Force OS DAC */ +#define REG_RX_MIX_LO_CM 0x1D5 /* Rx Mix LO CM */ +#define REG_RX_CGB_SEG_ENABLE 0x1D6 /* Rx CGB Seg Enable */ +#define REG_RX_MIX_INPUTBIAS 0x1D7 /* Rx Mix Input/Bias */ +#define REG_RX_TIA_CONFIG 0x1DB /* Rx TIA Config */ +#define REG_TIA1_C_LSB 0x1DC /* TIA1 C LSB */ +#define REG_TIA1_C_MSB 0x1DD /* TIA1 C MSB */ +#define REG_TIA2_C_LSB 0x1DE /* TIA2 C LSB */ +#define REG_TIA2_C_MSB 0x1DF /* TIA2 C MSB */ +#define REG_RX1_BBF_R1A 0x1E0 /* Rx1 BBF R1A */ +#define REG_RX2_BBF_R1A 0x1E1 /* Rx2 BBF R1A */ +#define REG_RX1_TUNE_CTRL 0x1E2 /* Rx1 Tune Control */ +#define REG_RX2_TUNE_CTRL 0x1E3 /* Rx2 Tune Control */ +#define REG_RX1_BBF_R5 0x1E4 /* Rx1 BBF R5 */ +#define REG_RX2_BBF_R5 0x1E5 /* Rx2 BBF R5 */ +#define REG_RX_BBF_R2346 0x1E6 /* Rx BBF R2346 */ +#define REG_RX_BBF_C1_MSB 0x1E7 /* Rx BBF C1 MSB */ +#define REG_RX_BBF_C1_LSB 0x1E8 /* Rx BBF C1 LSB */ +#define REG_RX_BBF_C2_MSB 0x1E9 /* Rx BBF C2 MSB */ +#define REG_RX_BBF_C2_LSB 0x1EA /* Rx BBF C2 LSB */ +#define REG_RX_BBF_C3_MSB 0x1EB /* Rx BBF C3 MSB */ +#define REG_RX_BBF_C3_LSB 0x1EC /* Rx BBF C3 LSB */ +#define REG_RX_BBF_CC1_CTR 0x1ED /* Rx BBF CC1 Ctr */ +#define REG_RX_BBF_POW_RZ_BYTE0 0x1EE /* Rx BBF Pow Rz Byte0 */ +#define REG_RX_BBF_CC2_CTR 0x1EF /* Rx BBF CC2 Ctr */ +#define REG_RX_BBF_POW_RZ_BYTE1 0x1F0 /* Rx BBF Pow Rz Byte1 */ +#define REG_RX_BBF_CC3_CTR 0x1F1 /* Rx BBF CC3 Ctr */ +#define REG_RX_BBF_R5_TUNE 0x1F2 /* Rx BBF R5 Tune */ +#define REG_RX_BBF_TUNE 0x1F3 /* Rx BBF Tune */ +#define REG_RX1_BBF_MAN_GAIN 0x1F4 /* Rx1 BBF Man Gain */ +#define REG_RX2_BBF_MAN_GAIN 0x1F5 /* Rx2 BBF Man Gain */ +#define REG_RX_BBF_TUNE_DIVIDE 0x1F8 /* RX BBF Tune Divide */ +#define REG_RX_BBF_TUNE_CONFIG 0x1F9 /* RX BBF Tune Config */ +#define REG_POLE_GAIN 0x1FA /* Pole gain */ +#define REG_RX_BBBW_MHZ 0x1FB /* Rx BBBW MHz */ +#define REG_RX_BBBW_KHZ 0x1FC /* Rx BBBW kHz */ +#define REG_FB_DAC_CLK_DELAY1 0x201 /* FB DAC Clk Delay1 */ +#define REG_FB_DAC_CLK_DELAY2 0x202 /* FB DAC Clk Delay2 */ +#define REG_FLASH_SAMPLE_CLK_DELAY_3P 0x203 /* Flash Sample Clk Delay 3p */ +#define REG_FLASH_SAMPLE_CLK_DELAY_3N 0x204 /* Flash Sample Clk Delay 3n */ +#define REG_TEST_MUX_2I 0x205 /* Test MUX 2i */ +#define REG_TEST_MUX_2Q 0x206 /* Test MUX 2q */ +#define REG_INTEGRATOR_1_RESISTANCE 0x207 /* Integrator 1 Resistance */ +#define REG_INTEGRATOR_1_CAPACITANCE 0x208 /* Integrator 1 Capacitance */ +#define REG_INTEGRATOR_23_RESISTANCE 0x209 /* Integrator 23 Resistance */ +#define REG_INTEGRATOR_2_RESISTANCE 0x20A /* Integrator 2 Resistance */ +#define REG_INTEGRATOR_2_CAPACITANCE 0x20B /* Integrator 2 Capacitance */ +#define REG_INTEGRATOR_3_RESISTANCE 0x20C /* Integrator 3 Resistance */ +#define REG_INTEGRATOR_3_CAPACITANCE 0x20D /* Integrator 3 Capacitance */ +#define REG_INTEGRATOR_AMP_CC 0x20E /* Integrator Amp Cc */ +#define REG_INT_1_FB_DAC_NMOS_CURRENT_SOURCE 0x20F /* Int 1 FB DAC NMOS Current Source */ +#define REG_INT_1_FB_DAC_NMOS_CASOADE_BIAS_CURRENT 0x210 /* Int 1 FB DAC NMOS Casoade Bias Current */ +#define REG_INT_1_FB_DAC_PMOS_CURRENT_SOURCE 0x211 /* Int 1 FB DAC PMOS Current Source */ +#define REG_INT_2_FB_DAC_NMOS_CURRENT_SOURCE 0x212 /* Int 2 FB DAC NMOS Current Source */ +#define REG_INT_2_FB_DAC_NMOS_CASCODE_BIAS_CURRENT 0x213 /* Int 2 FB DAC NMOS Cascode Bias Current */ +#define REG_INT_2_FB_DAC_PMOS_CURRENT_SOURCE 0x214 /* Int 2 FB DAC PMOS Current Source */ +#define REG_INT_3_FB_DAC_NMOS_CURRENT_SOURCE 0x215 /* Int 3 FB DAC NMOS Current Source */ +#define REG_INT_3_FB_DAC_NMOS_CASCODE_BIAS_CURRENT 0x216 /* Int 3 FB DAC NMOS Cascode Bias Current */ +#define REG_INT_3_FB_DAC_PMOS_CURRENT_SOURCE 0x217 /* Int 3 FB DAC PMOS Current Source */ +#define REG_FB_DAC_BIAS_CURRENT 0x218 /* FB DAC Bias Current */ +#define REG_INT_1_1ST_STAGE_CURRENT 0x219 /* Int 1 1st Stage Current */ +#define REG_INT_1_1ST_STAGE_CASCODE_CURRENT 0x21A /* Int 1 1st Stage Cascode Current */ +#define REG_INT_1_2ND_STAGE_CURRENT 0x21B /* Int 1 2nd Stage Current */ +#define REG_INTEGRATOR_2_1ST_STAGE_CURRENT 0x21C /* Integrator 2 1st Stage Current */ +#define REG_INT_2_1ST_STAGE_CASCODE_CURRENT 0x21D /* Int 2 1st Stage Cascode Current */ +#define REG_INT_2_2ND_STAGE_CURRENT 0x21E /* Int 2 2nd Stage Current */ +#define REG_INT_3_1ST_STAGE_CURRENT 0x21F /* Int 3 1st Stage Current */ +#define REG_INT_3_1ST_STAGE_CASCODE_CURRENT 0x220 /* Int 3 1st Stage Cascode Current */ +#define REG_INT_3_2ND_STAGE_CURRENT 0x221 /* Int 3 2nd Stage Current */ +#define REG_FLASH_BIAS_CURRENT 0x222 /* Flash Bias Current */ +#define REG_FLASH_LADDER_BIAS 0x223 /* Flash Ladder Bias */ +#define REG_FLASH_LADDER_CASCODE_CURRENT 0x224 /* Flash Ladder Cascode Current */ +#define REG_FLASH_LADDER_BIAS2 0x225 /* Flash Ladder Bias2 */ +#define REG_RESET 0x226 /* Reset */ +#define REG_RX_PFD_CONFIG 0x230 /* RX PFD Config */ +#define REG_RX_INTEGER_BYTE_0 0x231 /* RX Integer Byte 0 */ +#define REG_RX_INTEGER_BYTE_1 0x232 /* RX Integer Byte 1 */ +#define REG_RX_FRACT_BYTE_0 0x233 /* RX Fractional Byte 0 */ +#define REG_RX_FRACT_BYTE_1 0x234 /* RX Fractional Byte 1 */ +#define REG_RX_FRACT_BYTE_2 0x235 /* RX Fractional Byte 2 */ +#define REG_RX_FORCE_ALC 0x236 /* RX Force ALC */ +#define REG_RX_FORCE_VCO_TUNE_0 0x237 /* RX Force VCO Tune 0 */ +#define REG_RX_FORCE_VCO_TUNE_1 0x238 /* RX Force VCO Tune 1 */ +#define REG_RX_ALC_VARACTOR 0x239 /* RX ALC/Varactor */ +#define REG_RX_VCO_OUTPUT 0x23A /* RX VCO Output */ +#define REG_RX_CP_CURRENT 0x23B /* RX CP Current */ +#define REG_RX_CP_OFFSET 0x23C /* RX CP Offset */ +#define REG_RX_CP_CONFIG 0x23D /* RX CP Config */ +#define REG_RX_LOOP_FILTER_1 0x23E /* RX Loop Filter 1 */ +#define REG_RX_LOOP_FILTER_2 0x23F /* RX Loop Filter 2 */ +#define REG_RX_LOOP_FILTER_3 0x240 /* RX Loop Filter 3 */ +#define REG_RX_DITHERCP_CAL 0x241 /* RX Dither/CP Cal */ +#define REG_RX_VCO_BIAS_1 0x242 /* RX VCO Bias 1 */ +#define REG_RX_CAL_STATUS 0x244 /* RX Cal Status */ +#define REG_RX_VCO_CAL_REF 0x245 /* RX VCO Cal Ref */ +#define REG_RX_VCO_PD_OVERRIDES 0x246 /* RX VCO Pd Overrides */ +#define REG_RX_CP_OVERRANGE_VCO_LOCK 0x247 /* RX CP Over Range/VCO Lock */ +#define REG_RX_VCO_LDO 0x248 /* RX VCO LDO */ +#define REG_RX_VCO_CAL 0x249 /* RX VCO Cal */ +#define REG_RX_LOCK_DETECT_CONFIG 0x24A /* RX Lock Detect Config */ +#define REG_RX_CP_LEVEL_DETECT 0x24B /* RX CP Level Detect */ +#define REG_RX_DSM_SETUP_0 0x24C /* RX DSM Setup 0 */ +#define REG_RX_DSM_SETUP_1 0x24D /* RX DSM Setup 1 */ +#define REG_RX_CORRECTION_WORD0 0x24E /* RX Correction Word0 */ +#define REG_RX_CORRECTION_WORD1 0x24F /* RX Correction Word1 */ +#define REG_RX_VCO_VARACTOR_CTRL_0 0x250 /* RX VCO Varactor Control 0 */ +#define REG_RX_VCO_VARACTOR_CTRL_1 0x251 /* RX VCO Varactor Control 1 */ +#define REG_RX_FAST_LOCK_SETUP 0x25A /* Rx Fast Lock Setup */ +#define REG_RX_FAST_LOCK_SETUP_INIT_DELAY 0x25B /* Rx Fast Lock Setup Init Delay */ +#define REG_RX_FAST_LOCK_PROGRAM_ADDR 0x25C /* Rx Fast Lock Program Addr */ +#define REG_RX_FAST_LOCK_PROGRAM_DATA 0x25D /* Rx Fast Lock Program Data */ +#define REG_RX_FAST_LOCK_PROGRAM_READ 0x25E /* Rx Fast Lock Program Read */ +#define REG_RX_FAST_LOCK_PROGRAM_CTRL 0x25F /* Rx Fast Lock Program Control */ +#define REG_RX_LO_GEN_POWER_MODE 0x261 /* Rx LO Gen Power Mode */ +#define REG_TX_PFD_CONFIG 0x270 /* TX PFD Config */ +#define REG_TX_INTEGER_BYTE_0 0x271 /* TX Integer Byte 0 */ +#define REG_TX_INTEGER_BYTE_1 0x272 /* TX Integer Byte 1 */ +#define REG_TX_FRACT_BYTE_0 0x273 /* TX Fractional Byte 0 */ +#define REG_TX_FRACT_BYTE_1 0x274 /* TX Fractional Byte 1 */ +#define REG_TX_FRACT_BYTE_2 0x275 /* TX Fractional Byte 2 */ +#define REG_TX_FORCE_ALC 0x276 /* TX Force ALC */ +#define REG_TX_FORCE_VCO_TUNE_0 0x277 /* TX Force VCO Tune 0 */ +#define REG_TX_FORCE_VCO_TUNE_1 0x278 /* TX Force VCO Tune 1 */ +#define REG_TX_ALCVARACT_OR 0x279 /* TX ALC/Varact or */ +#define REG_TX_VCO_OUTPUT 0x27A /* TX VCO Output */ +#define REG_TX_CP_CURRENT 0x27B /* TX CP Current */ +#define REG_TX_CP_OFFSET 0x27C /* TX CP Offset */ +#define REG_TX_CP_CONFIG 0x27D /* TX CP Config */ +#define REG_TX_LOOP_FILTER_1 0x27E /* TX Loop Filter 1 */ +#define REG_TX_LOOP_FILTER_2 0x27F /* TX Loop Filter 2 */ +#define REG_TX_LOOP_FILTER_3 0x280 /* TX Loop Filter 3 */ +#define REG_TX_DITHERCP_CAL 0x281 /* TX Dither/CP Cal */ +#define REG_TX_VCO_BIAS_1 0x282 /* TX VCO Bias 1 */ +#define REG_TX_VCO_BIAS_2 0x283 /* TX VCO Bias 2 */ +#define REG_TX_CAL_STATUS 0x284 /* TX Cal Status */ +#define REG_TX_VCO_CAL_REF 0x285 /* TX VCO Cal Ref */ +#define REG_TX_VCO_PD_OVERRIDES 0x286 /* TX VCO Pd Overrides */ +#define REG_TX_CP_OVERRANGE_VCO_LOCK 0x287 /* TX CP Over Range/VCO Lock */ +#define REG_TX_VCO_LDO 0x288 /* TX VCO LDO */ +#define REG_TX_VCO_CAL 0x289 /* TX VCO Cal */ +#define REG_TX_LOCK_DETECT_CONFIG 0x28A /* TX Lock Detect Config */ +#define REG_TX_CP_LEVEL_DETECT 0x28B /* TX CP Level Detect */ +#define REG_TX_DSM_SETUP_0 0x28C /* TX DSM Setup 0 */ +#define REG_TX_DSM_SETUP_1 0x28D /* TX DSM Setup 1 */ +#define REG_TX_CORRECTION_WORD0 0x28E /* TX Correction Word0 */ +#define REG_TX_CORRECTION_WORD1 0x28F /* TX Correction Word1 */ +#define REG_TX_VCO_VARACTOR_CTRL_0 0x290 /* TX VCO Varactor Control 0 */ +#define REG_TX_VCO_VARACTOR_CTRL_1 0x291 /* TX VCO Varactor Control 1 */ +#define REG_DCXO_COARSE_TUNE 0x292 /* DCXO Coarse Tune */ +#define REG_DCXO_FINE_TUNE_HIGH 0x293 /* DCXO Fine Tune2 */ +#define REG_DCXO_FINE_TUNE_LOW 0x294 /* DCXO Fine Tune1 */ +#define REG_DCXO_CONFIG 0x295 /* DCXO Config */ +#define REG_DCXO_TEMPCO_WRITE 0x296 /* DCXO Tempco Write */ +#define REG_DCXO_TEMPCO_READ 0x297 /* DCXO Tempco Read */ +#define REG_DCXO_TEMPCO_ADDR 0x298 /* DCXO Tempco Addr */ +#define REG_DELTA_T_READ 0x299 /* Delta T Read */ +#define REG_TX_FAST_LOCK_SETUP 0x29A /* Tx Fast Lock Setup */ +#define REG_TX_FAST_LOCK_SETUP_INIT_DELAY 0x29B /* Tx Fast Lock Setup Init Delay */ +#define REG_TX_FAST_LOCK_PROGRAM_ADDR 0x29C /* Tx Fast Lock Program Addr */ +#define REG_TX_FAST_LOCK_PROGRAM_DATA 0x29D /* Tx Fast Lock Program Data */ +#define REG_TX_FAST_LOCK_PROGRAM_READ 0x29E /* Tx Fast Lock Program Read */ +#define REG_TX_FAST_LOCK_PROGRAM_CTRL 0x29F /* Tx Fast Lock Program Ctrl */ +#define REG_TX_LO_GEN_POWER_MODE 0x2A1 /* Tx LO Gen Power Mode */ +#define REG_BANDGAP_CONFIG0 0x2A6 /* Bandgap Config0 */ +#define REG_BANDGAP_CONFIG1 0x2A8 /* Bandgap Config1 */ +#define REG_REF_DIVIDE_CONFIG_1 0x2AB /* Ref Divide Config 1 */ +#define REG_REF_DIVIDE_CONFIG_2 0x2AC /* Ref Divide Config 2 */ +#define REG_GAIN_RX1 0x2B0 /* Gain Rx1 */ +#define REG_LPF_GAIN_RX1 0x2B1 /* LPF Gain Rx1 */ +#define REG_DIG_GAIN_RX1 0x2B2 /* Dig gain Rx1 */ +#define REG_FAST_ATTACK_STATE 0x2B3 /* Fast Attack State */ +#define REG_SLOW_LOOP_STATE 0x2B4 /* Slow Loop State */ +#define REG_GAIN_RX2 0x2B5 /* Gain Rx2 */ +#define REG_LPF_GAIN_RX2 0x2B6 /* LPF Gain Rx2 */ +#define REG_DIG_GAIN_RX2 0x2B7 /* Dig Gain Rx2 */ +#define REG_OVRG_SIGS_RX1 0x2B8 /* Ovrg Sigs Rx1 */ +#define REG_OVRG_SIGS_RX2 0x2B9 /* Ovrg Sigs Rx2 */ +#define REG_CTRL 0x3DF /* Control */ +#define REG_BIST_CONFIG 0x3F4 /* BIST Config */ +#define REG_OBSERVE_CONFIG 0x3F5 /* Observe Config */ +#define REG_BIST_AND_DATA_PORT_TEST_CONFIG 0x3F6 /* BIST and Data Port Test Config */ +#define REG_DAC_TEST_0 0x3FC /* DAC Test 0 */ +#define REG_DAC_TEST_1 0x3FD /* DAC Test 1 */ +#define REG_DAC_TEST_2 0x3FE /* DAC Test 2 */ + +/* +* REG_SPI_CONF +*/ +#define SOFT_RESET (1 << 7) /* Soft Reset */ +#define WIRE3_SPI (1 << 6) /* 3-Wire SPI */ +#define LSB_FIRST (1 << 5) /* LSB First */ +#define _LSB_FIRST (1 << 2) /* LSB First */ +#define _WIRE3_SPI (1 << 1) /* 3-Wire SPI */ +#define _SOFT_RESET (1 << 0) /* Soft reset */ + +/* +* REG_MULTICHIP_SYNC_AND_TX_MON_CTRL +*/ +#define TX2_MONITOR_ENABLE (1 << 6) /* Tx2 Monitor Enable */ +#define TX1_MONITOR_ENABLE (1 << 5) /* Tx1 Monitor Enable */ +#define MCS_RF_ENABLE (1 << 3) /* MCS RF Enable */ +#define MCS_BBPLL_ENABLE (1 << 2) /* MCS BBPLL enable */ +#define MCS_DIGITAL_CLK_ENABLE (1 << 1) /* MCS Digital CLK Enable */ +#define MCS_BB_ENABLE (1 << 0) /* MCS BB Enable */ + +/* +* REG_TX_ENABLE_FILTER_CTRL +*/ +#define THB2_EN (1 << 3) /* THB2 Enable */ +#define THB1_EN (1 << 2) /* THB1 Enable */ +#define TX_CHANNEL_ENABLE(x) (((x) & 0x3) << 6) /* Tx channel Enable<1:0> */ +#define THB3_ENABLE_INTERP(x) (((x) & 0x3) << 4) /* THB3 Enable & Interp<1:0> */ +#define TX_FIR_ENABLE_INTERPOLATION(x) (((x) & 0x3) << 0) /* Tx FIR Enable & Interpolation<1:0> */ +#define TX_1 1 +#define TX_2 2 +#define TX_ENABLE 1 +#define TX_DISABLE 0 + +/* +* REG_RX_ENABLE_FILTER_CTRL +*/ +#define RHB2_EN (1 << 3) /* RHB2 Enable */ +#define RHB1_EN (1 << 2) /* RHB1 Enable */ +#define RX_CHANNEL_ENABLE(x) (((x) & 0x3) << 6) /* Rx channel Enable<1:0> */ +#define DEC3_ENABLE_DECIMATION(x) (((x) & 0x3) << 4) /* DEC3 Enable & Decimation<1:0> */ +#define RX_FIR_ENABLE_DECIMATION(x) (((x) & 0x3) << 0) /* Rx FIR Enable & Decimation<1:0> */ +#define RX_1 1 +#define RX_2 2 +#define RX_ENABLE 1 +#define RX_DISABLE 0 + +/* +* REG_INPUT_SELECT +*/ +#define TX_OUTPUT (1 << 6) /* TX Output */ +#define RX_INPUT(x) (((x) & 0x3F) << 0) /* RX Input <5:0> */ + +/* +* REG_RFPLL_DIVIDERS +*/ +#define TX_VCO_DIVIDER(x) (((x) & 0xF) << 4) /* TX VCO Divider<3:0> */ +#define RX_VCO_DIVIDER(x) (((x) & 0xF) << 0) /* RX VCO Divider<3:0> */ + +/* +* REG_RX_CLOCK_DATA_DELAY +*/ +#define DATA_CLK_DELAY(x) (((x) & 0xF) << 4) /* DATA_CLK Delay<3:0> */ +#define RX_DATA_DELAY(x) (((x) & 0xF) << 0) /* Rx Data Delay <3:0> */ + +/* +* REG_TX_CLOCK_DATA_DELAY +*/ +#define FB_CLK_DELAY(x) (((x) & 0xF) << 4) /* FB_CLK Delay<3:0> */ +#define TX_DATA_DELAY(x) (((x) & 0xF) << 0) /* Tx Data Delay <3:0> */ + +/* +* REG_CLOCK_ENABLE +*/ +#define XO_BYPASS (1 << 4) /* XO Bypass */ +#define DIGITAL_POWER_UP (1 << 2) /* Digital Power Up */ +#define CLOCK_ENABLE_DFLT (1 << 1) /* Set to 1 */ +#define BBPLL_ENABLE (1 << 0) /* BBPLL Enable */ + +/* +* REG_BBPLL +*/ +#define CLKOUT_ENABLE (1 << 4) /* CLKOUT Enable */ +#define DAC_CLK_DIV2 (1 << 3) /* DAC Clk div2 */ +#define CLKOUT_SELECT(x) (((x) & 0x7) << 5) /* CLKOUT Select<2:0> */ +#define BBPLL_DIVIDER(x) (((x) & 0x7) << 0) /* BBPLL Divider <2:0> */ + +/* +* REG_START_TEMP_READING +*/ +#define START_TEMP_READING (1 << 0) /* Start Temp Reading */ + +/* +* REG_TEMP_SENSE2 +*/ +#define TEMP_SENSE_PERIODIC_ENABLE (1 << 0) /* Temp Sense Periodic Enable */ +#define MEASUREMENT_TIME_INTERVAL(x) (((x) & 0x7F) << 1) /* Measurement Time Interval<6:0> */ + +/* +* REG_TEMP_SENSOR_CONFIG +*/ +#define TEMP_SENSOR_DECIMATION(x) (((x) & 0x7) << 0) /* Temp Sensor Decimation<2:0> */ + +/* +* REG_PARALLEL_PORT_CONF_1 +*/ +#define PP_TX_SWAP_IQ (1 << 7) /* PP Tx Swap IQ */ +#define PP_RX_SWAP_IQ (1 << 6) /* PP Rx Swap IQ */ +#define TX_CHANNEL_SWAP (1 << 5) /* Tx Channel swap */ +#define RX_CHANNEL_SWAP (1 << 4) /* Rx Channel swap */ +#define RX_FRAME_PULSE_MODE (1 << 3) /* Rx Frame Pulse Mode */ +#define R2T2_TIMING (1 << 2) /* 2R2T Timing */ +#define INVERT_DATA_BUS (1 << 1) /* Invert data bus */ +#define INVERT_DATA_CLK (1 << 0) /* Invert DATA CLK */ + +/* +* REG_PARALLEL_PORT_CONF_2 +*/ +#define FDD_ALT_WORD_ORDER (1 << 7) /* FDD Alt Word Order */ +#define INVERT_RX1 (1 << 6) /* Invert Rx1 */ +#define INVERT_RX2 (1 << 5) /* Invert Rx2 */ +#define INVERT_TX1 (1 << 4) /* Invert Tx1 */ +#define INVERT_TX2 (1 << 3) /* Invert Tx2 */ +#define INVERT_RX_FRAME (1 << 2) /* Invert Rx Frame */ +#define DELAY_RX_DATA(x) (((x) & 0x3) << 0) /* Delay Rx Data<1:0> */ + +/* +* REG_PARALLEL_PORT_CONF_3 +*/ +#define FDD_RX_RATE_2TX_RATE (1 << 7) /* FDD Rx Rate = 2*Tx Rate */ +#define SWAP_PORTS (1 << 6) /* Swap Ports */ +#define SINGLE_DATA_RATE (1 << 5) /* Single Data Rate */ +#define LVDS_MODE (1 << 4) /* LVDS Mode */ +#define HALF_DUPLEX_MODE (1 << 3) /* Half Duplex Mode */ +#define SINGLE_PORT_MODE (1 << 2) /* Single Port Mode */ +#define FULL_PORT (1 << 1) /* Full Port */ +#define FULL_DUPLEX_SWAP_BITS (1 << 0) /* Full Duplex Swap Bits */ + +/* +* REG_ENSM_MODE +*/ +#define FDD_MODE (1 << 0) /* FDD Mode */ + +/* +* REG_ENSM_CONFIG_1 +*/ +#define ENABLE_RX_DATA_PORT_FOR_CAL (1 << 7) /* Enable Rx Data Port for Cal */ +#define FORCE_RX_ON (1 << 6) /* Force Rx On */ +#define FORCE_TX_ON (1 << 5) /* Force Tx On */ +#define ENABLE_ENSM_PIN_CTRL (1 << 4) /* Enable ENSM Pin Control */ +#define LEVEL_MODE (1 << 3) /* Level Mode */ +#define FORCE_ALERT_STATE (1 << 2) /* Force Alert State */ +#define AUTO_GAIN_LOCK (1 << 1) /* Auto Gain Lock */ +#define TO_ALERT (1 << 0) /* To Alert */ + +/* +* REG_ENSM_CONFIG_2 +*/ +#define FDD_EXTERNAL_CTRL_ENABLE (1 << 7) /* FDD External Control Enable */ +#define POWER_DOWN_RX_SYNTH (1 << 6) /* Power Down Rx Synth */ +#define POWER_DOWN_TX_SYNTH (1 << 5) /* Power Down Tx Synth */ +#define TXNRX_SPI_CTRL (1 << 4) /* TXNRX SPI Control */ +#define SYNTH_ENABLE_PIN_CTRL_MODE (1 << 3) /* Synth Enable Pin Control Mode */ +#define DUAL_SYNTH_MODE (1 << 2) /* Dual Synth Mode */ +#define RX_SYNTH_READY_MASK (1 << 1) /* Rx Synth Ready Mask */ +#define TX_SYNTH_READY_MASK (1 << 0) /* Tx Synth Ready Mask */ + +/* +* REG_CALIBRATION_CTRL +*/ +#define RX_BB_TUNE_CAL (1 << 7) /* Rx BB Tune */ +#define TX_BB_TUNE_CAL (1 << 6) /* Tx BB Tune */ +#define RX_QUAD_CAL (1 << 5) /* Rx Quad Cal */ +#define TX_QUAD_CAL (1 << 4) /* Tx Quad Cal */ +#define RX_GAIN_STEP_CAL (1 << 3) /* Rx Gain Step Cal */ +#define TXMON_CAL (1 << 2) +#define RFDC_CAL (1 << 1) /* DC Cal RF Start */ +#define BBDC_CAL (1 << 0) /* DC cal BB Start */ + + +/* +* REG_STATE +*/ +#define CALIBRATION_SEQUENCE_STATE(x) (((x) & 0xF) << 4) /* Calibration Sequence State<3:0> */ +#define ENSM_STATE(x) (((x) & 0xF) << 0) /* ENSM State<3:0> */ +#define ENSM_STATE_SLEEP_WAIT 0x0 +#define ENSM_STATE_ALERT 0x5 +#define ENSM_STATE_TX 0x6 +#define ENSM_STATE_TX_FLUSH 0x7 +#define ENSM_STATE_RX 0x8 +#define ENSM_STATE_RX_FLUSH 0x9 +#define ENSM_STATE_FDD 0xA +#define ENSM_STATE_FDD_FLUSH 0xB +#define ENSM_STATE_INVALID 0xFF +#define ENSM_STATE_SLEEP 0x80 + +/* +* REG_AUXDAC_2_WORD +*/ +#define AUXDAC_2_WORD_MSB(x) (((x) & 0x3F) << 2) /* AuxDAC 2 Word<9:2> */ +#define AUXDAC_1_WORD(x) (((x) & 0x3) << 0) /* AuxDAC 1 Word <1:0> */ + +/* +* REG_AUXDAC_1_CONFIG +*/ +#define COMP_CTRL_1 (1 << 5) /* Comp Ctrl 1 */ +#define AUXDAC1_STP_FACTOR (1 << 4) /* AuxDAC1 Step Factor */ +#define AUXDAC_1_VREF(x) (((x) & 0x3) << 2) /* AuxDAC 1 Vref<1:0> */ +#define AUXDAC_1_WORD_LSB(x) (((x) & 0x3) << 0) /* AuxDAC 2 Word <1:0> */ + +/* +* REG_AUXDAC_2_CONFIG +*/ +#define COMP_CTRL_2 (1 << 5) /* Comp Ctrl 2 */ +#define AUXDAC2_STP_FACTOR (1 << 4) /* AuxDAC2 Step Factor */ +#define AUXDAC_2_VREF(x) (((x) & 0xF) << 2) /* AuxDAC 2 Vref<1:0> */ +#define AUXDAC_2_WORD_LSB(x) (((x) & 0x3) << 0) /* AuxDAC 2 Word <1:0> */ + +/* +* REG_AUXADC_CLOCK_DIVIDER +*/ +#define AUXADC_CLOCK_DIVIDER(x) (((x) & 0x3F) << 0) /* AuxADC Clock Divider<5:0> */ + +/* +* REG_AUXADC_CONFIG +*/ +#define AUXADC_POWER_DOWN (1 << 0) /* AuxADC Power Down */ +#define AUX_ADC_DECIMATION(x) (((x) & 0x7) << 1) /* Aux ADC Decimation<2:0> */ + +/* +* REG_AUXADC_LSB +*/ +#define AUXADC_WORD_LSB(x) (((x) & 0xF) << 0) /* AuxADC Word LSB<3:0> */ + +/* +* REG_AUTO_GPO +*/ +#define GPO_ENABLE_AUTO_RX(x) (((x) & 0xF) << 4) /* GPO Enable Auto Rx<3:0> */ +#define GPO_ENABLE_AUTO_TX(x) (((x) & 0xF) << 0) /* GPO Enable Auto Tx<3:0> */ + +/* +* REG_AGC_ATTACK_DELAY +*/ +#define INVERT_BYPASSED_LNA_POLARITY (1 << 6) /* Invert Bypassed LNA Polarity */ +#define AGC_ATTACK_DELAY(x) (((x) & 0x3F) << 0) /* AGC Attack Delay<5:0> */ + +/* +* REG_AUXDAC_ENABLE_CTRL +*/ +#define AUXDAC_MANUAL_BAR(x) (((x) & 0x3) << 6) /* AuxDac Manual Bar<1:0> */ +#define AUXDAC_AUTO_TX_BAR(x) (((x) & 0x3) << 4) /* AuxDAC Auto Tx Bar<1:0> */ +#define AUXDAC_AUTO_RX_BAR(x) (((x) & 0x3) << 2) /* AuxDAC Auto Rx Bar<1:0> */ +#define AUXDAC_INIT_BAR(x) (((x) & 0x3) << 0) /* AuxDAC Init Bar<1:0> */ + +/* +* REG_EXTERNAL_LNA_CTRL +*/ +#define AUXDAC_MANUAL_SELECT (1 << 7) /* AuxDAC Manual Select */ +#define EXTERNAL_LNA2_CTRL (1 << 6) /* External LNA2 control */ +#define EXTERNAL_LNA1_CTRL (1 << 5) /* External LNA1 control */ +#define GPO_MANUAL_SELECT (1 << 4) /* GPO manual select */ +#define OPEN(x) (((x) & 0xF) << 0) /* Open<3:0> */ + +/* +* REG_GPO_FORCE_AND_INIT +*/ +#define GPO_MANUAL_CTRL(x) (((x) & 0xF) << 4) /* GPO Manual Control<3:0> */ +#define GPO_INIT_STATE(x) (((x) & 0xF) << 0) /* GPO Init State<3:0> */ + +/* +* REG_CTRL_OUTPUT_ENABLE +*/ +#define EN_CTRL7 (1 << 7) /* En ctrl7 */ +#define EN_CTRL6 (1 << 6) /* En ctrl6 */ +#define EN_CTRL5 (1 << 5) /* En ctrl5 */ +#define EN_CTRL4 (1 << 4) /* En ctrl4 */ +#define EN_CTRL3 (1 << 3) /* En ctrl3 */ +#define EN_CTRL2 (1 << 2) /* En ctrl2 */ +#define EN_CTRL1 (1 << 1) /* En ctrl1 */ +#define EN_CTRL0 (1 << 0) /* En ctrl0 */ + +/* +* REG_PRODUCT_ID +*/ +#define PRODUCT_ID_MASK 0xF8 +#define PRODUCT_ID_9361 0x08 +#define REV_MASK 0x07 + +/* +* REG_REFERENCE_CLOCK_CYCLES +*/ +#define REFERENCE_CLOCK_CYCLES_PER_US(x) (((x) & 0x7F) << 0) /* Reference Clock Cycles per us<6:0> */ + +/* +* REG_DIGITAL_IO_CTRL +*/ +#define CLK_OUT_DRIVE (1 << 7) /* CLK Out Drive */ +#define DATACLK_DRIVE (1 << 6) /* DATACLK drive */ +#define DATA_PORT_DRIVE (1 << 2) /* Data Port Drive */ +#define DATACLK_SLEW(x) (((x) & 0x3) << 4) /* DATACLK slew <1:0> */ +#define DATA_PORT_SLEW(x) (((x) & 0x3) << 0) /* Data Port Slew<1:0> */ + +/* +* REG_LVDS_BIAS_CTRL +*/ +#define RX_ON_CHIP_TERM (1 << 5) /* Rx On Chip Term */ +#define LVDS_BYPASS_BIAS_R (1 << 4) /* Bypass Bias R */ +#define LVDS_TX_LO_VCM (1 << 3) /* LVDS Tx LO VCM */ +#define CLK_OUT_SLEW(x) (((x) & 0x3) << 6) /* CLK Out Slew<1:0> */ +#define LVDS_BIAS(x) (((x) & 0x7) << 0) /* LVDS Bias <2:0> */ + +/* +* REG_SDM_CTRL_1 +*/ +#define INIT_BB_FO_CAL (1 << 2) /* Init BB FO CAL */ +#define BBPLL_RESET_BAR (1 << 0) /* BBPLL Reset Bar */ + +/* +* REG_CLOCK_CTRL +*/ +#define REF_FREQ_SCALER(x) (((x) & 0x3) << 0) /* Ref Frequency Scaler */ + +/* +* REG_CP_CURRENT +*/ +#define CHARGE_PUMP_CURRENT(x) (((x) & 0x3F) << 0) /* Charge Pump Current<5:0> */ + +/* +* REG_CP_BLEED_CURRENT +*/ +#define MCS_REFCLK_SCALE_EN (1 << 7) /* MCS refclk Scale En */ + +/* +* REG_LOOP_FILTER_1 +*/ +#define C1_WORD(x) (((x) & 0x7) << 5) /* C1 Word<2:0> */ +#define R1_WORD(x) (((x) & 0x1F) << 0) /* R1 Word<4:0> */ + +/* +* REG_LOOP_FILTER_2 +*/ +#define R2_WORD (1 << 7) /* R2 Word<0> */ +#define C2_WORD(x) (((x) & 0x1F) << 2) /* C2 Word<4:0> */ +#define C1_WORD_LSB(x) (((x) & 0x3) << 0) /* C1 Word<4:3> */ + +/* +* REG_LOOP_FILTER_3 +*/ +#define BYPASS_C3 (1 << 7) /* Bypass C3 */ +#define BYPASS_R2 (1 << 6) /* Bypass R2 */ +#define C3_WORD(x) (((x) & 0xF) << 2) /* C3 Word<3:0> */ +#define R2_WORD_LSB(x) (((x) & 0x3) << 0) /* R2 Word<2:1> */ + +/* +* REG_VCO_CTRL +*/ +#define FREQ_CAL_ENABLE (1 << 7) /* Freq Cal Enable */ +#define FREQ_CAL_RESET (1 << 4) /* Freq Cal Reset */ +#define FREQ_CAL_COUNT_LENGTH(x) (((x) & 0x3) << 5) /* Freq Cal Count Length<1:0> */ + +/* +* REG_SDM_CTRL +*/ +#define CAL_CLOCK_DIV_4 (1 << 4) /* Cal Clock div 4 */ + +/* +* REG_RX_SYNTH_POWER_DOWN_OVERRIDE +*/ +#define RX_LO_POWER_DOWN (1 << 4) /* Rx LO Power Down */ +#define RX_SYNTH_VCO_ALC_POWER_DOWN (1 << 3) /* Rx Synth VCO ALC Power Down */ +#define RX_SYNTH_PTAT_POWER_DOWN (1 << 2) /* Rx Synth PTAT Power Down */ +#define RX_SYNTH_VCO_POWER_DOWN (1 << 1) /* Rx Synth VCO Power Down */ +#define RX_SYNTH_VCO_LDO_POWER_DOWN (1 << 0) /* Rx Synth VCO LDO Power Down */ + +/* +* REG_TX_SYNTH_POWER_DOWN_OVERRIDE +*/ +#define TX_LO_POWER_DOWN (1 << 4) /* Tx LO Power Down */ +#define TX_SYNTH_VCO_ALC_POWER_DOWN (1 << 3) /* Tx Synth VCO ALC Power Down */ +#define TX_SYNTH_PTAT_POWER_DOWN (1 << 2) /* Tx Synth PTAT Power Down */ +#define TX_SYNTH_VCO_POWER_DOWN (1 << 1) /* Tx Synth VCO Power Down */ +#define TX_SYNTH_VCO_LDO_POWER_DOWN (1 << 0) /* Tx Synth VCO LDO Power Down */ + +/* +* REG_RX_ANALOG_POWER_DOWN_OVERRIDE_1 +*/ +#define RX_OFFSET_DAC_CGIN_POWER_DOWN(x) (((x) & 0x3) << 6) /* Rx Offset DAC CGin Power Down<1:0> */ +#define RX_LMT_OVERLOAD_POWER_DOWN(x) (((x) & 0x3) << 4) /* Rx LMT Overload Power Down<1:0> */ +#define RX_MIXER_GM_POWER_DOWN(x) (((x) & 0x3) << 2) /* Rx Mixer Gm Power Down<1:0> */ +#define RX_CGB_POWER_DOWN(x) (((x) & 0x3) << 0) /* Rx CGB Power Down<1:0> */ + +/* +* REG_RX_ANALOG_POWER_DOWN_OVERRIDE_2 +*/ +#define RX_BBF_POWER_DOWN(x) (((x) & 0x3) << 6) /* Rx BBF Power Down<1:0> */ +#define RX_TIA_POWER_DOWN(x) (((x) & 0x3) << 4) /* Rx TIA Power Down<1:0> */ +#define RX_MIXER_POWER_DOWN(x) (((x) & 0x3) << 2) /* Rx Mixer Power Down<1:0> */ +#define RX_OFFSET_DAC_CGOUT_POWER_DOWN(x) (((x) & 0x3) << 0) /* Rx Offset DAC CGOut Power Down<1:0> */ + +/* +* REG_TX_ANALOG_POWER_DOWN_OVERRIDE_1 +*/ +#define TX_SECONDARY_FILTER_POWER_DOWN(x) (((x) & 0x3) << 6) /* Tx Secondary Filter Power Down<1:0> */ +#define TX_BBF_POWER_DOWN(x) (((x) & 0x3) << 4) /* Tx BBF Power Down<1:0> */ +#define TX_DAC_POWER_DOWN(x) (((x) & 0x3) << 2) /* Tx DAC Power Down<1:0> */ +#define TX_DAC_BIAS_POWER_DOWN(x) (((x) & 0x3) << 0) /* Tx DAC Bias Power Down<1:0> */ + +/* +* REG_ANALOG_POWER_DOWN_OVERRIDE +*/ +#define RX_EXT_VCO_BUFFER_POWER_DOWN (1 << 5) /* Rx Ext VCO Buffer Power Down */ +#define TX_EXT_VCO_BUFFER_POWER_DOWN (1 << 4) /* Tx Ext VCO Buffer Power Down */ +#define TX_MONITOR_POWER_DOWN(x) (((x) & 0x3) << 2) /* Tx Monitor Power Down<1:0> */ +#define TX_UPCONVERTER_POWER_DOWN(x) (((x) & 0x3) << 0) /* Tx Upconverter Power Down<1:0> */ + +/* +* REG_MISC_POWER_DOWN_OVERRIDE +*/ +#define RX_LNA_POWER_DOWN (1 << 6) /* Rx LNA Power Down */ +#define DCXO_POWER_DOWN (1 << 1) /* DCXO Power Down */ +#define MASTER_BIAS_POWER_DOWN (1 << 0) /* Master Bias Power Down */ +#define RX_CALIBRATION_POWER_DOWN(x) (((x) & 0x3) << 2) /* Rx Calibration Power Down<1:0> */ + +/* +* REG_CH_1_OVERFLOW +*/ +#define BBPLL_LOCK (1 << 7) /* BBPLL Lock */ +#define CH_1_INT3 (1 << 6) /* CH 1 INT3 */ +#define CH1_HB3 (1 << 5) /* CH1 HB3 */ +#define CH1_HB2 (1 << 4) /* CH1 HB2 */ +#define CH1_QEC (1 << 3) /* CH1 QEC */ +#define CH1_HB1 (1 << 2) /* CH1 HB1 */ +#define CH1_TFIR (1 << 1) /* CH1 TFIR */ +#define CH1_RFIR (1 << 0) /* CH1 RFIR */ + +/* +* REG_CH_2_OVERFLOW +*/ +#define CH2_INT3 (1 << 6) /* CH2 INT3 */ +#define CH2_HB3 (1 << 5) /* CH2 HB3 */ +#define CH2_HB2 (1 << 4) /* CH2 HB2 */ +#define CH2_QEC (1 << 3) /* CH2 QEC */ +#define CH2_HB1 (1 << 2) /* CH2 HB1 */ +#define CH2_TFIR (1 << 1) /* CH2 TFIR */ +#define CH2_RFIR (1 << 0) /* CH2 RFIR */ + +/* +* REG_TX_FILTER_CONF +*/ +#define TX_FIR_GAIN_6DB (1 << 0) /* Filter Gain */ +#define FIR_START_CLK (1 << 1) /* Start Tx/Rx Clock */ +#define FIR_WRITE (1 << 2) /* Write Tx/Rx */ +#define FIR_SELECT(x) (((x) & 0x3) << 3) /* Select Tx/Rx CH<1:0> */ +#define FIR_NUM_TAPS(x) (((x) & 0x7) << 5) /* Number of Taps<2:0> */ + +/* +* REG_TX_MON_LOW_GAIN +*/ +#define TX_MON_TRACK (1 << 5) /* Tx Mon Track */ +#define TX_MON_LOW_GAIN(x) (((x) & 0x1F) << 0) /* Tx Mon Low Gain<4:0> */ + +/* +* REG_TX_MON_HIGH_GAIN +*/ +#define TX_MON_HIGH_GAIN(x) (((x) & 0x1F) << 0) /* Tx Mon High Gain<4:0> */ + +/* +* REG_TX_LEVEL_THRESH +*/ +#define TX_LEVEL_THRESH(x) (((x) & 0x3F) << 2) /* Tx Level Threshold<5:0> */ +#define TX_MON_DELAY_COUNTER(x) (((x) & 0x3) << 0) /* Tx Mon Delay Counter<9:8> */ + +/* +* REG_TX_RSSI_LSB +*/ +#define TX_RSSI_2 (1 << 1) /* Tx RSSI 2<0> */ +#define TX_RSSI_1 (1 << 0) /* TX RSSI 1<0> */ + +/* +* REG_TPM_MODE_ENABLE +*/ +#define TX2_MON_ENABLE (1 << 7) /* Tx2 Monitor Enable */ +#define TX1_MON_ENABLE (1 << 5) /* Tx1 Monitor Enable */ +#define ONE_SHOT_MODE (1 << 6) /* One Shot Mode */ +#define TX_MON_DURATION(x) (((x) & 0xF) << 0) /* Tx Mon Duration<3:0> */ + +/* +* REG_TX_MON_1_CONFIG +*/ +#define TX_MON_1_LO_CM(x) (((x) & 0x3F) << 2) /* Tx Mon 1 LO CM<5:0> */ +#define TX_MON_1_GAIN(x) (((x) & 0x3) << 0) /* Tx Mon 1 Gain<1:0> */ + +/* +* REG_TX_MON_2_CONFIG +*/ +#define TX_MON_2_LO_CM(x) (((x) & 0x3F) << 2) /* Tx Mon 2 LO CM<5:0> */ +#define TX_MON_2_GAIN(x) (((x) & 0x3) << 0) /* Tx Mon 2 Gain<1:0> */ + +/* +* REG_TX1_ATTEN_1 +*/ +#define TX_1_ATTEN (1 << 0) /* Tx 1 Atten <8> */ + +/* +* REG_TX2_ATTEN_1 +*/ +#define TX_2_ATTEN (1 << 0) /* Tx 2 Atten <8> */ + +/* +* REG_TX_ATTEN_OFFSET +*/ +#define MASK_CLR_ATTEN_UPDATE (1 << 6) /* Mask Clr Atten Update */ +#define TX_ATTEN_OFFSET(x) (((x) & 0x3F) << 0) /* Tx Atten Offset<5:0> */ + +/* +* REG_TX1_DIG_ATTEN +*/ +#define SEL_TX1_TX2 (1 << 6) /* Sel Tx1 & Ttx2 */ + +/* +* REG_TX2_DIG_ATTEN +*/ +#define IMMEDIATELY_UPDATE_TPC_ATTEN (1 << 6) /* Immediately Update TPC Atten */ + +/* +* REG_TX1_SYMBOL_ATTEN +*/ +#define TX_1_SYMBOL_ATTEN(x) (((x) & 0x7F) << 0) /* Tx 1 Symbol Attenuation<6:0> */ + +/* +* REG_TX2_SYMBOL_ATTEN +*/ +#define TX_2_SYMBOL_ATTEN(x) (((x) & 0x7F) << 0) /* Tx 2 Symbol Attenuation<6:0> */ + +/* +* REG_TX_SYMBOL_ATTEN_CONFIG +*/ +#define USE_TX1_PIN_SYMBOL_ATTEN (1 << 3) /* Use Tx1 Pin & Symbol Atten */ +#define USE_CTRL_IN_FOR_SYMBOL_ATTEN (1 << 1) /* Use CTRL IN for symbol Atten */ +#define ENABLE_SYMBOL_ATTEN (1 << 0) /* Enable Symbol Atten */ + +/* +* REG_TX_FORCE_BITS +*/ +#define FORCE_OUT_2_TX2_OFFSET (1 << 7) /* Force Out 2 Tx2 Offset */ +#define FORCE_OUT_2_TX1_OFFSET (1 << 6) /* Force Out 2 Tx1 Offset */ +#define FORCE_OUT_2_TX2_PHASE_GAIN (1 << 5) /* Force Out 2 Tx2 Phase & Gain */ +#define FORCE_OUT_2_TX1_PHASE_GAIN (1 << 4) /* Force Out 2 Tx1 Phase & Gain */ +#define FORCE_OUT_1_TX2_OFFSET (1 << 3) /* Force Out 1 Tx2 Offset */ +#define FORCE_OUT_1_TX1_OFFSET (1 << 2) /* Force Out 1 Tx1 Offset */ +#define FORCE_OUT_1_TX2_PHASE_GAIN (1 << 1) /* Force Out 1 Tx2 Phase & Gain */ +#define FORCE_OUT_1_TX1_PHASE_GAIN (1 << 0) /* Force Out 1 Tx1 Phase & Gain */ + +/* +* REG_QUAD_CAL_NCO_FREQ_PHASE_OFFSET +*/ +#define RX_NCO_FREQ(x) (((x) & 0x3) << 5) /* Rx NCO Frequency<1:0> */ +#define RX_NCO_PHASE_OFFSET(x) (((x) & 0x1F) << 0) /* Rx NCO Phase Offset<4:0> */ + +/* +* REG_QUAD_CAL_CTRL +*/ +#define FREE_RUN_ENABLE (1 << 7) /* Free Run Enable */ +#define SETTLE_MAIN_ENABLE (1 << 6) /* Settle Main Enable */ +#define DC_OFFSET_ENABLE (1 << 5) /* DC Offset Enable */ +#define GAIN_ENABLE (1 << 4) /* Gain Enable */ +#define PHASE_ENABLE (1 << 3) /* Phase Enable */ +#define QUAD_CAL_SOFT_RESET (1 << 2) /* Quad Cal Soft Reset */ +#define M_DECIM(x) (((x) & 0x3) << 0) /* M<1:0> */ + +/* +* REG_KEXP_1 +*/ +#define KEXP_TX(x) (((x) & 0x3) << 6) /* Kexp Tx<1:0> */ +#define KEXP_TX_COMP(x) (((x) & 0x3) << 4) /* Kexp Tx_comp <1:0> */ +#define KEXP_DC_I(x) (((x) & 0x3) << 2) /* Kexp DC I <1:0> */ +#define KEXP_DC_Q(x) (((x) & 0x3) << 0) /* Kexp DC Q <1:0> */ + +/* +* REG_KEXP_2 +*/ +#define INVERT_I_DATA (1 << 5) /* Invert I data */ +#define INVERT_Q_DATA (1 << 4) /* Invert Q data */ +#define TX_NCO_FREQ(x) (((x) & 0x3) << 6) /* Tx NCO frequency<1:0> */ +#define KEXP_PHASE(x) (((x) & 0x3) << 2) /* Kexp Phase <1:0> */ +#define KEXP_AMP(x) (((x) & 0x3) << 0) /* Kexp Amp <1:0> */ + +/* +* REG_QUAD_CAL_STATUS_TX1 +*/ +#define TX1_LO_CONV (1 << 1) /* Tx1 LO Conv */ +#define TX1_SSB_CONV (1 << 0) /* Tx1 SSB Conv */ +#define TX1_CONVERGENCE_COUNT(x) (((x) & 0x3F) << 2) /* Tx1 Convergence Count<5:0> */ + +/* +* REG_QUAD_CAL_STATUS_TX2 +*/ +#define TX2_LO_CONV (1 << 1) /* Tx2 LO Conv */ +#define TX2_SSB_CONV (1 << 0) /* Tx2 SSB Conv */ +#define TX2_CONVERGENCE_COUNT(x) (((x) & 0x3F) << 2) /* Tx2 Convergence Count<5:0> */ + +/* +* REG_TX_QUAD_FULL_LMT_GAIN +*/ +#define RX_FULL_TABLELMT_TABLE_GAIN(x) (((x) & 0x7F) << 0) /* RX Full table/LMT table gain<6:0> */ + +/* +* REG_SQUARER_CONFIG +*/ +#define GM_STAGE_TIME_CON_OVERRIDE (1 << 5) /* Gm Stage Time Con Override */ +#define GM_STAGE_MV_HP_POLE (1 << 4) /* Gm Stage MV HP Pole */ +#define GM_STAGE_LOWER_CM (1 << 3) /* Gm Stage Lower CM */ +#define BYPASS_BIAS_R (1 << 0) /* Bypass Bias R */ +#define VBIAS_CTRL(x) (((x) & 0x3) << 1) /* Vbias Control<1:0> */ + +/* +* REG_THRESH_ACCUM +*/ +#define THRESH_ACCUMULATOR(x) (((x) & 0xF) << 0) /* Threshold Accumulator<3:0> */ + +/* +* REG_TX_QUAD_LPF_GAIN +*/ +#define RX_LPF_GAIN(x) (((x) & 0x1F) << 0) /* RX LPF gain<4:0> */ + +/* +* REG_TXDAC_VDS_I +*/ +#define TXDAC_VDS_I(x) (((x) & 0x3F) << 0) /* TxDAC Vds I<5:0> */ + +/* +* REG_TXDAC_VDS_Q +*/ +#define TXDAC_VDS_Q(x) (((x) & 0x3F) << 0) /* TxDAC Vds Q<5:0> */ + +/* +* REG_TXDAC_GN_I +*/ +#define TXDAC_GN_I(x) (((x) & 0x3F) << 0) /* txDAC_gn_I<5:0> */ + +/* +* REG_TXDAC_GN_Q +*/ +#define TXDAC_GN_Q(x) (((x) & 0x3F) << 0) /* txDAC_gn_Q<5:0> */ + +/* +* REG_TXBBF_OPAMP_A +*/ +#define OPAMPA_OUTPUT_BIAS(x) (((x) & 0x3) << 5) /* OpAmpA Output Bias<1:0> */ +#define OPAMPA_RZ(x) (((x) & 0x3) << 3) /* OpAmpA RZ<1:0> */ +#define OPAMP_A_CC(x) (((x) & 0x7) << 0) /* OpAmp A CC<2:0> */ + +/* +* REG_TXBBF_OPAMP_B +*/ +#define OPAMPB_OUTPUT_BIAS(x) (((x) & 0x3) << 5) /* OpAmpB Output Bias<1:0> */ +#define OPAMPB_RZ(x) (((x) & 0x3) << 3) /* OpAmpB RZ<1:0> */ +#define OPAMP_B_CC(x) (((x) & 0x7) << 0) /* OpAmp B CC<2:0> */ + +/* +* REG_TX_BBF_R1 +*/ +#define OVERRIDE_ENABLE (1 << 7) /* Override enable */ +#define R1(x) (((x) & 0x1F) << 0) /* R1<4:0> */ + +/* +* REG_TX_BBF_R2 +*/ +#define R2(x) (((x) & 0x1F) << 0) /* R2<4:0> */ + +/* +* REG_TX_BBF_R3 +*/ +#define R3(x) (((x) & 0x1F) << 0) /* R3<4:0> */ + +/* +* REG_TX_BBF_R4 +*/ +#define R4(x) (((x) & 0x1F) << 0) /* R4<4:0> */ + +/* +* REG_TX_BBF_RP +*/ +#define RP(x) (((x) & 0x1F) << 0) /* Rp<4:0> */ + +/* +* REG_TX_BBF_C1 +*/ +#define C1(x) (((x) & 0x3F) << 0) /* C1<5:0> */ + +/* +* REG_TX_BBF_C2 +*/ +#define C2(x) (((x) & 0x3F) << 0) /* C2<5:0> */ + +/* +* REG_TX_BBF_CP +*/ +#define CP(x) (((x) & 0x3F) << 0) /* Cp<5:0> */ + +/* +* REG_TX_TUNE_CTRL +*/ +#define PD_TUNE (1 << 2) /* PD Tune */ +#define TUNER_RESAMPLE (1 << 1) /* Tuner Resample */ +#define TUNER_RESAMPLE_PHASE (1 << 0) /* Tuner Resample Phase */ +#define TUNE_CTRL(x) (((x) & 0x3) << 5) /* Tune Control<1:0> */ + +/* +* REG_TX_BBF_R2B +*/ +#define TX_BBF_BYPASS_BIAS_R (1 << 7) /* Bypass Bias R */ +#define R2B_OVR (1 << 5) /* R2b Ovr */ +#define R2B(x) (((x) & 0x1F) << 0) /* R2b<4:0> */ + +/* +* REG_TX_BBF_TUNE +*/ +#define BBF1_COMP_I (1 << 3) /* BBF1 Comp I */ +#define BBF1_COMP_Q (1 << 2) /* BBF1 Comp Q */ +#define BBF2_COMP_I (1 << 1) /* BBF2 Comp I */ +#define BBF2_COMP_Q (1 << 0) /* BBF2 Comp Q */ + +/* +* REG_CONFIG0 +*/ +#define BIAS(x) (((x) & 0x3) << 6) /* Bias<1:0> */ +#define RGM(x) (((x) & 0x3) << 4) /* Rgm<1:0> */ +#define CC(x) (((x) & 0x3) << 2) /* Cc<1:0> */ +#define AMPBIAS(x) (((x) & 0x3) << 0) /* AmpBias<1:0> */ + +/* +* REG_RESISTOR +*/ +#define RESISTOR(x) (((x) & 0xF) << 0) /* Resistor<3:0> */ + +/* +* REG_CAPACITOR +*/ +#define CAPACITOR(x) (((x) & 0x3F) << 0) /* Capacitor<5:0> */ + +/* +* REG_LO_CM +*/ +#define LO_COMMON_MODE(x) (((x) & 0x3) << 5) /* LO Common Mode<1:0> */ + +/* +* REG_TX_BBF_TUNE_MODE +*/ +#define EVALTIME (1 << 4) /* EvalTime */ +#define TX_BBF_TUNE_DIVIDER (1 << 0) /* TX BBF Tune Divider<8> */ +#define TUNE_COMP_MASK(x) (((x) & 0x3) << 5) /* Tune Comp Mask<1:0> */ +#define TUNER_MODE(x) (((x) & 0x7) << 1) /* Tuner Mode<2:0> */ + +/* +* REG_RX_FILTER_CONFIG +*/ +#define WRITE_RX (1 << 2) /* Write Rx */ +#define START_RX_CLOCK (1 << 1) /* Start Rx Clock */ +#define NUMBER_OF_TAPS(x) (((x) & 0x7) << 5) /* Number of Taps */ +#define SELECT_RX_CH(x) (((x) & 0x3) << 3) /* Select Rx Ch<1:0> */ + +/* +* REG_RX_FILTER_GAIN +*/ +#define FILTER_GAIN(x) (((x) & 0x3) << 0) /* Filter gain<1:0> */ + +/* +* REG_AGC_CONFIG_1 +*/ +#define DEC_PWR_FOR_LOW_PWR (1 << 7) /* Dec Pwr for Low Pwr */ +#define DEC_PWR_FOR_LOCK_LEVEL (1 << 6) /* Dec Pwr for Lock Level */ +#define DEC_PWR_FOR_GAIN_LOCK_EXIT (1 << 5) /* Dec Pwr for Gain Lock Exit */ +#define SLOW_ATTACK_HYBRID_MODE (1 << 4) /* Slow Attack Hybrid Mode */ +#define RX2_GAIN_CTRL_SETUP(x) (((x) & 0x3) << 2) /* Rx 2 Gain Control Setup<1:0> */ +#define RX1_GAIN_CTRL_SETUP(x) (((x) & 0x3) << 0) /* Rx 1 Gain Control Setup<1:0> */ +#define RX_GAIN_CTL_MASK 0x03 +#define RX2_GAIN_CTRL_SHIFT 2 +#define RX1_GAIN_CTRL_SHIFT 0 +#define RX_GAIN_CTL_MGC 0x00 +#define RX_GAIN_CTL_AGC_FAST_ATK 0x01 +#define RX_GAIN_CTL_AGC_SLOW_ATK 0x02 +#define RX_GAIN_CTL_AGC_SLOW_ATK_HYBD 0x03 + +/* +* REG_AGC_CONFIG_2 +*/ +#define AGC_SOFT_RESET (1 << 7) /* Soft Reset */ +#define AGC_GAIN_UNLOCK_CTRL (1 << 6) /* Gain Unlock Control */ +#define AGC_USE_FULL_GAIN_TABLE (1 << 3) /* Use Full Gain Table */ +#define DIG_GAIN_EN (1 << 2) /* Enable Digital Gain */ +#define MAN_GAIN_CTRL_RX2 (1 << 1) /* Manual Gain Control Rx 2 */ +#define MAN_GAIN_CTRL_RX1 (1 << 0) /* Manual Gain Control Rx 1 */ + +/* +* REG_AGC_CONFIG_3 +*/ +#define INCDEC_LMT_GAIN (1 << 4) /* Inc/Dec LMT Gain */ +#define USE_AGC_FOR_LMTLPF_GAIN (1 << 3) /* Use AGC for LMT/LPF Gain */ +#define MANUAL_INCR_STEP_SIZE(x) (((x) & 0x7) << 5) /* Manual (CTRL_IN) Incr Gain Step Size<2:0> */ +#define ADC_OVERRANGE_SAMPLE_SIZE(x) (((x) & 0x7) << 0) /* ADC Overrange Sample Size<2:0> */ + +/* +* REG_MAX_LMT_FULL_GAIN +*/ +#define MAXIMUM_FULL_TABLELMT_TABLE_INDEX(x) (((x) & 0x7F) << 0) /* Maximum Full Table/LMT Table Index<6:0> */ + +/* +* REG_PEAK_WAIT_TIME +*/ +#define MANUAL_CTRL_IN_DECR_GAIN_STP_SIZE(x) (((x) & 0x7) << 5) /* Manual (CTRL_IN) Decr Gain Step Size<2:0> */ +#define PEAK_OVERLOAD_WAIT_TIME(x) (((x) & 0x1F) << 0) /* Peak Overload Wait Time<4:0> */ + +/* +* REG_DIGITAL_GAIN +*/ +#define DIG_GAIN_STP_SIZE(x) (((x) & 0x7) << 5) /* Dig Gain Step Size<2:0> */ +#define MAXIMUM_DIGITAL_GAIN(x) (((x) & 0x1F) << 0) /* Maximum Digital Gain<4:0> */ + +/* +* REG_AGC_LOCK_LEVEL +*/ +#define ENABLE_DIG_SAT_OVRG (1 << 7) /* Enable Dig Sat Ovrg */ +#define AGC_LOCK_LEVEL_FAST_AGC_INNER_HIGH_THRESH_SLOW(x) (((x) & 0x7F) << 0) /* AGC Lock Level (Fast)/ AGC Inner High Threshold (Slow) <6:0> */ + +/* +* REG_GAIN_STP_CONFIG1 +*/ +#define LMT_DETECTOR_SETTLING_TIME(x) (((x) & 0x7) << 5) /* LMT Detector Settling Time<2:0> */ +#define DEC_STP_SIZE_FOR_LARGE_LMT_OVERLOAD(x) (((x) & 0x7) << 2) /* Dec Step Size for: Large LMT Overload/ Full Table Case #3 <2:0> */ +#define ADC_NOISE_CORRECTION_FACTOR(x) (((x) & 0x3) << 0) /* ADC Noise Correction Factor<1:0> */ + +/* +* REG_GAIN_STP_CONFIG_2 +*/ +#define DECREMENT_STP_SIZE_FOR_SMALL_LPF_GAIN_CHANGE(x) (((x) & 0x7) << 4) /* Fast Attack Only. Decrement Step Size for: Small LPF Gain Change / Full Table Case #2 <2:0> */ +#define LARGE_LPF_GAIN_STEP(x) (((x) & 0xF) << 0) /* Decrement Step Size for: Large LPF Gain Change / Full Table Case #1<3:0> */ + +/* +* REG_SMALL_LMT_OVERLOAD_THRESH +*/ +#define FORCE_PD_RESET_RX2 (1 << 7) /* Force PD Reset Rx2 */ +#define FORCE_PD_RESET_RX1 (1 << 6) /* Force PD Reset Rx1 */ +#define SMALL_LMT_OVERLOAD_THRESH(x) (((x) & 0x3F) << 0) /* Small LMT Overload Threshold<5:0> */ + +/* +* REG_LARGE_LMT_OVERLOAD_THRESH +*/ +#define LARGE_LMT_OVERLOAD_THRESH(x) (((x) & 0x3F) << 0) /* Large LMT Overload Threshold<5:0> */ + +/* +* REG_RX1_MANUAL_LMT_FULL_GAIN +*/ +#define POWER_MEAS_IN_STATE_5_MSB (1 << 7) /* Power Meas in State 5 <3> */ +#define RX1_MANUAL_FULL_TABLE_LMT_TABLE_GAIN_INDEX(x) (((x) & 0x7F) << 0) /* Rx1 Manual Full table/LMT table Gain Index<6:0> */ +#define RX_FULL_TBL_IDX_MASK RX1_MANUAL_FULL_TABLE_LMT_TABLE_GAIN_INDEX(~0) + +/* +* REG_RX1_MANUAL_LPF_GAIN +*/ +#define POWER_MEAS_IN_STATE_5(x) (((x) & 0x7) << 5) /* Power Meas in State 5<2:0> */ +#define RX1_MANUAL_LPF_GAIN(x) (((x) & 0x1F) << 0) /* Rx1 Manual LPF Gain <4:0> */ +#define RX_LPF_IDX_MASK RX1_MANUAL_LPF_GAIN(~0) + +/* +* REG_RX1_MANUAL_DIGITALFORCED_GAIN +*/ +#define FORCE_RX1_DIGITAL_GAIN (1 << 5) /* Force Rx1 Digital Gain */ +#define RX1_MANUALFORCED_DIGITAL_GAIN(x) (((x) & 0x1F) << 0) /* Rx1 Manual/Forced Digital Gain<4:0> */ +#define RX_DIGITAL_IDX_MASK RX1_MANUALFORCED_DIGITAL_GAIN(~0) +/* +* REG_RX2_MANUAL_LMT_FULL_GAIN +*/ +#define RX2_MANUAL_FULL_TABLE_LMT_TABLE_GAIN_INDEX(x) (((x) & 0x7F) << 0) /* Rx2 Manual Full table/ LMT table Gain Index<6:0> */ + +/* +* REG_RX2_MANUAL_LPF_GAIN +*/ +#define RX2_MANUAL_LPF_GAIN(x) (((x) & 0x1F) << 0) /* Rx2 Manual LPF Gain<4:0> */ + +/* +* REG_RX2_MANUAL_DIGITALFORCED_GAIN +*/ +#define FORCE_RX2_DIGITAL_GAIN (1 << 5) /* Force Rx2 Digital Gain */ +#define RX2_MANUALFORCED_DIGITAL_GAIN(x) (((x) & 0x1F) << 0) /* Rx2 Manual/Forced Digital Gain<4:0> */ + +/* +* REG_FAST_CONFIG_1 +*/ +#define ENABLE_GAIN_INC_AFTER_GAIN_LOCK (1 << 7) /* Enable Gain Inc after Gain Lock */ +#define GOTO_OPT_GAIN_IF_ENERGY_LOST_OR_EN_AGC_HIGH (1 << 6) /* Goto Opt Gain if Energy Lost or EN_AGC High */ +#define GOTO_SET_GAIN_IF_EN_AGC_HIGH (1 << 5) /* Goto Set Gain if EN_AGC High */ +#define GOTO_SET_GAIN_IF_EXIT_RX_STATE (1 << 4) /* Goto Set Gain if Exit Rx State */ +#define DONT_UNLOCK_GAIN_IF_ENERGY_LOST (1 << 3) /* Don't Unlock Gain if Energy Lost */ +#define GOTO_OPTIMIZED_GAIN_IF_EXIT_RX_STATE (1 << 2) /* Goto Optimized Gain if Exit Rx State */ +#define DONT_UNLOCK_GAIN_IF_LG_ADC_OR_LMT_OVRG (1 << 1) /* Don't Unlock Gain If Lg ADC or LMT Ovrg */ +#define ENABLE_INCR_GAIN (1 << 0) /* Enable Incr Gain */ + +/* +* REG_FAST_CONFIG_2_SETTLING_DELAY +*/ +#define USE_LAST_LOCK_LEVEL_FOR_SET_GAIN (1 << 7) /* Use Last Lock Level for Set Gain */ +#define ENABLE_LMT_GAIN_INC_FOR_LOCK_LEVEL (1 << 6) /* Enable LMT Gain Inc for Lock Level */ +#define GOTO_MAX_GAIN_OR_OPT_GAIN_IF_EN_AGC_HIGH (1 << 5) /* Goto Max Gain or Opt Gain if EN_AGC High */ +#define SETTLING_DELAY(x) (((x) & 0x1F) << 0) /* Settling Delay<4:0> */ + +/* +* REG_FAST_ENERGY_LOST_THRESH +*/ +#define POST_LOCK_LEVEL_STP_SIZE_FOR_LPF_TABLE_FULL_TABLE(x) (((x) & 0x3) << 6) /* Post Lock Level Step Size for: LPF Table/ Full Table <1:0> */ +#define ENERGY_LOST_THRESH(x) (((x) & 0x3F) << 0) /* Energy lost threshold<5:0> */ + +/* +* REG_FAST_STRONGER_SIGNAL_THRESH +*/ +#define POST_LOCK_LEVEL_STP_FOR_LMT_TABLE(x) (((x) & 0x3) << 6) /* Post Lock Level Step for LMT Table <1:0> */ +#define STRONGER_SIGNAL_THRESH(x) (((x) & 0x3F) << 0) /* Stronger Signal Threshold<5:0> */ + +/* +* REG_FAST_LOW_POWER_THRESH +*/ +#define DONT_UNLOCK_GAIN_IF_ADC_OVRG (1 << 7) /* Don't unlock gain if ADC Ovrg */ +#define LOW_POWER_THRESH(x) (((x) & 0x7F) << 0) /* Low Power Threshold<6:0> */ + +/* +* REG_FAST_STRONG_SIGNAL_FREEZE +*/ +#define DONT_UNLOCK_GAIN_IF_STRONGER_SIGNAL (1 << 7) /* Don't unlock gain if Stronger Signal */ + +/* +* REG_FAST_FINAL_OVER_RANGE_AND_OPT_GAIN +*/ +#define FINAL_OVER_RANGE_COUNT(x) (((x) & 0x7) << 5) /* Final Over Range Count<2:0> */ +#define OPTIMIZE_GAIN_OFFSET(x) (((x) & 0xF) << 0) /* Optimize Gain Offset<3:0> */ + +/* +* REG_FAST_ENERGY_DETECT_COUNT +*/ +#define INCREMENT_GAIN_STP_LPFLMT(x) (((x) & 0x7) << 5) /* Increment Gain Step (LPF/LMT)<2:0> */ +#define ENERGY_DETECT_COUNT(x) (((x) & 0x1F) << 0) /* Energy Detect count<4:0> */ + +/* +* REG_FAST_AGCLL_UPPER_LIMIT +*/ +#define AGCLL_MAX_INCREASE(x) (((x) & 0x3F) << 0) /* AGCLL Max Increase<5:0> */ + +/* +* REG_FAST_GAIN_LOCK_EXIT_COUNT +*/ +#define GAIN_LOCK_EXIT_COUNT(x) (((x) & 0x3F) << 0) /* Gain Lock Exit Count<5:0> */ + +/* +* REG_FAST_INITIAL_LMT_GAIN_LIMIT +*/ +#define INITIAL_LMT_GAIN_LIMIT(x) (((x) & 0x7F) << 0) /* Initial LMT Gain Limit<6:0> */ + +/* +* REG_AGC_INNER_LOW_THRESH +*/ +#define PREVENT_GAIN_INC (1 << 7) /* Prevent Gain Inc */ +#define AGC_INNER_LOW_THRESH(x) (((x) & 0x7F) << 0) /* AGC Inner Low Threshold<6:0> */ + +/* +* REG_LMT_OVERLOAD_COUNTERS +*/ +#define LARGE_LMT_OVERLOAD_EXED_COUNTER(x) (((x) & 0xF) << 4) /* Large LMT Overload Exceeded Counter<3:0> */ +#define SMALL_LMT_OVERLOAD_EXED_COUNTER(x) (((x) & 0xF) << 0) /* Small LMT Overload Exceeded Counter<3:0> */ + +/* +* REG_ADC_OVERLOAD_COUNTERS +*/ +#define LARGE_ADC_OVERLOAD_EXED_COUNTER(x) (((x) & 0xF) << 4) /* Large ADC Overload Exceeded Counter<3:0> */ +#define SMALL_ADC_OVERLOAD_EXED_COUNTER(x) (((x) & 0xF) << 0) /* Small ADC Overload Exceeded Counter<3:0> */ + +/* +* REG_GAIN_STP1 +*/ +#define IMMED_GAIN_CHANGE_IF_LG_LMT_OVERLOAD (1 << 7) /* Immed. Gain Change if Lg LMT Overload */ +#define IMMED_GAIN_CHANGE_IF_LG_ADC_OVERLOAD (1 << 3) /* Immed. Gain Change if Lg ADC Overload */ +#define AGC_INNER_HIGH_THRESH_EXED_STP_SIZE(x) (((x) & 0x7) << 4) /* AGC Inner High Threshold Exceeded Step Size<2:0> */ +#define AGC_INNER_LOW_THRESH_EXED_STP_SIZE(x) (((x) & 0x7) << 0) /* AGC Inner Low Threshold Exceeded Step Size<2:0> */ + +/* +* REG_DIGITAL_SAT_COUNTER +*/ +#define DOUBLE_GAIN_COUNTER (1 << 5) /* Double Gain Counter */ +#define ENABLE_SYNC_FOR_GAIN_COUNTER (1 << 4) /* Enable Sync for Gain Counter */ +#define DIG_SATURATION_EXED_COUNTER(x) (((x) & 0xF) << 0) /* Dig Saturation Exceeded Counter<3:0> */ + +/* +* REG_OUTER_POWER_THRESHS +*/ +#define AGC_OUTER_HIGH_THRESH(x) (((x) & 0xF) << 4) /* AGC Outer High Threshold<3:0> */ +#define AGC_OUTER_LOW_THRESH(x) (((x) & 0xF) << 0) /* AGC Outer Low Threshold<3:0> */ + +/* +* REG_GAIN_STP_2 +*/ +#define AGC_OUTER_HIGH_THRESH_EXED_STP_SIZE(x) (((x) & 0xF) << 4) /* AGC outer High Threshold Exceeded Step Size<3:0> */ +#define AGC_OUTER_LOW_THRESH_EXED_STP_SIZE(x) (((x) & 0xF) << 0) /* AGC Outer Low Threshold Exceeded Step Size<3:0> */ + +/* +* REG_EXT_LNA_HIGH_GAIN +*/ +#define EXT_LNA_HIGH_GAIN(x) (((x) & 0x3F) << 0) /* Ext LNA High Gain<5:0> */ + +/* +* REG_EXT_LNA_LOW_GAIN +*/ +#define EXT_LNA_LOW_GAIN(x) (((x) & 0x3F) << 0) /* Ext LNA Low Gain<5:0> */ + +/* +* REG_GAIN_TABLE_ADDRESS +*/ +#define GAIN_TABLE_ADDRESS(x) (((x) & 0x7F) << 0) /* Gain Table Address<6:0> */ + +/* +* REG_GAIN_TABLE_WRITE_DATA1 +*/ +#define EXT_LNA_CTRL (1 << 7) /* Ext LNA Ctrl */ +#define LNA_GAIN(x) (((x) & 0x3) << 5) /* LNA Gain <1:0> */ +#define MIXER_GM_GAIN(x) (((x) & 0x1F) << 0) /* Mixer Gm Gain <4:0> */ + +/* +* REG_GAIN_TABLE_WRITE_DATA2 +*/ +#define TIA_GAIN (1 << 5) /* TIA Gain */ +#define LPF_GAIN(x) (((x) & 0x1F) << 0) /* LPF Gain <4:0> */ + +/* +* REG_GAIN_TABLE_WRITE_DATA_3 +*/ +#define RF_DC_CAL (1 << 5) /* RF DC Cal */ +#define DIGITAL_GAIN(x) (((x) & 0x1F) << 0) /* Digital Gain <4:0> */ + +/* +* REG_GAIN_TABLE_READ_DATA_1 +*/ +#define TO_LNA_GAIN(x) (((x) >> 5) & 0x3) /* LNA Gain <1:0> */ +#define TO_MIXER_GM_GAIN(x) (((x) >> 0) & 0x1F) /* Mixer Gm Gain <4:0> */ + +/* +* REG_GAIN_TABLE_READ_DATA_2 +*/ +#define TO_LPF_GAIN(x) (((x) >> 0) & 0x1F) /* LPF Gain <4:0> */ + +/* +* REG_GAIN_TABLE_READ_DATA_3 +*/ +#define TO_DIGITAL_GAIN(x) (((x) >> 0) & 0x1F) /* Digital Gain <4:0> */ + +/* +* REG_GAIN_TABLE_CONFIG +*/ +#define WRITE_GAIN_TABLE (1 << 2) /* Write Gain Table */ +#define START_GAIN_TABLE_CLOCK (1 << 1) /* Start Gain Table Clock */ +#define RECEIVER_SELECT(x) (((x) & 0x3) << 3) /* Receiver Select<1:0> */ +#define GT_RX1 1 +#define GT_RX2 2 + + +/* +* REG_GM_SUB_TABLE_GAIN_WRITE +*/ +#define GM_SUB_TABLE_GAIN_WRITE(x) (((x) & 0x7F) << 0) /* Gm Sub Table Gain Word Write<6:0> */ + +/* +* REG_GM_SUB_TABLE_BIAS_WRITE +*/ +#define GM_SUB_TABLE_BIAS_WRITE(x) (((x) & 0x1F) << 0) /* Gm Sub Table Bias Word Write<4:0> */ + +/* +* REG_GM_SUB_TABLE_CTRL_WRITE +*/ +#define GM_SUB_TABLE_CTRL_WRITE(x) (((x) & 0x3F) << 0) /* Gm Sub Table Control Word Write<5:0> */ + +/* +* REG_GM_SUB_TABLE_GAIN_READ +*/ +#define GM_SUB_TABLE_GAIN_READ(x) (((x) & 0x7F) << 0) /* Gm Sub Table Gain Word Read<6:0> */ + +/* +* REG_GM_SUB_TABLE_BIAS_READ +*/ +#define GM_SUB_TABLE_BIAS_READ(x) (((x) & 0x1F) << 0) /* Gm Sub Table Bias Word Read<4:0> */ + +/* +* REG_GM_SUB_TABLE_CTRL_READ +*/ +#define GM_SUB_TABLE_CTRL_READ(x) (((x) & 0x3F) << 0) /* Gm Sub Table Control Word Read<5:0> */ + +/* +* REG_GM_SUB_TABLE_CONFIG +*/ +#define WRITE_GM_SUB_TABLE (1 << 2) /* Write Gm Sub Table */ +#define START_GM_SUB_TABLE_CLOCK (1 << 1) /* Start Gm Sub Table Clock */ + +/* +* REG_GAIN_DIFF_WORDERROR_WRITE +*/ +#define CALIB_TABLE_GAIN_DIFFERROR_WORD(x) (((x) & 0x3F) << 0) /* Calib Table Gain Diff/Error Word<5:0> */ + +/* +* REG_GAIN_ERROR_READ +*/ +#define CALIB_TABLE_GAIN_ERROR(x) (((x) & 0x1F) << 0) /* Calib Table Gain Error<4:0> */ + +/* +* REG_CONFIG +*/ +#define READ_SELECT (1 << 4) /* Read Select */ +#define WRITE_MIXER_ERROR_TABLE (1 << 3) /* Write Mixer Error Table */ +#define WRITE_LNA_ERROR_TABLE (1 << 2) /* Write LNA Error Table */ +#define WRITE_LNA_GAIN_DIFF (1 << 1) /* Write LNA Gain Diff */ +#define START_CALIB_TABLE_CLOCK (1 << 0) /* Start Calib Table Clock */ +#define CALIB_TABLE_SELECT(x) (((x) & 0x3) << 5) /* Calib Table Select<1:0> */ + +/* +* REG_LNA_GAIN_DIFF_READ_BACK +*/ +#define LNA_CALIB_TABLE_GAIN_DIFFERENCE_WORD(x) (((x) & 0x3F) << 0) /* LNA Calib Table Gain Difference Word<5:0> */ + +/* +* REG_MAX_MIXER_CALIBRATION_GAIN_INDEX +*/ +#define MAX_MIXER_CALIBRATION_GAIN_INDEX(x) (((x) & 0x1F) << 0) /* Max Mixer Calibration Gain Index<4:0> */ + +/* +* REG_SETTLE_TIME +*/ +#define ENABLE_DIG_GAIN_CORR (1 << 7) /* Enable Dig Gain Corr */ +#define FORCE_TEMP_SENSOR_FOR_CAL (1 << 6) /* Force Temp Sensor for Cal */ +#define SETTLE_TIME(x) (((x) & 0x3F) << 0) /* Settle Time<5:0> */ + +/* +* REG_MEASURE_DURATION +*/ +#define GAIN_CAL_MEAS_DURATION(x) (((x) & 0xF) << 0) /* Gain Cal Meas Duration<3:0> */ + +/* +* REG_MEASURE_DURATION_01 +*/ +#define MEASUREMENT_DURATION_1(x) (((x) & 0xF) << 4) /* Measurement duration 1 <3:0> */ +#define MEASUREMENT_DURATION_0(x) (((x) & 0xF) << 0) /* Measurement duration 0 <3:0> */ + +/* +* REG_MEASURE_DURATION_23 +*/ +#define MEASUREMENT_DURATION_3(x) (((x) & 0xF) << 4) /* Measurement duration 3 <3:0> */ +#define MEASUREMENT_DURATION_2(x) (((x) & 0xF) << 0) /* Measurement duration 2 <3:0> */ + +/* +* REG_RSSI_CONFIG +*/ +#define START_RSSI_MEAS (1 << 5) /* Start RSSI Meas (Mode 4) */ +#define ENABLE_ADC_POWER_MEAS (1 << 1) /* Enable ADC Power Meas. */ +#define DEFAULT_RSSI_MEAS_MODE (1 << 0) /* Default RSSI Meas Mode */ +#define RFIR_FOR_RSSI_MEASUREMENT(x) (((x) & 0x3) << 6) /* RFIR for RSSI measurement<1:0> */ +#define RSSI_MODE_SELECT(x) (((x) & 0x7) << 2) /* RSSI Mode Select<2:0> */ + +/* +* REG_ADC_MEASURE_DURATION_01 +*/ +#define ADC_POWER_MEASUREMENT_DURATION_1(x) (((x) & 0xF) << 4) /* ADC Power Measurement Duration 1<3:0> */ +#define ADC_POWER_MEASUREMENT_DURATION_0(x) (((x) & 0xF) << 0) /* ADC Power Measurement Duration 0 <3:0> */ + +/* +* REG_DEC_POWER_MEASURE_DURATION_0 +*/ +#define USE_HB3_OUT_FOR_ADC_PWR_MEAS (1 << 7) /* Use HB3 Out for ADC Pwr Meas */ +#define USE_HB1_OUT_FOR_DEC_PWR_MEAS (1 << 6) /* Use HB1 Out for Dec pwr Meas */ +#define ENABLE_DEC_PWR_MEAS (1 << 5) /* Enable Dec Pwr Meas */ +#define DEFAULT_MODE_ADC_POWER (1 << 4) /* Default Mode ADC Power */ +#define DEC_POWER_MEASUREMENT_DURATION(x) (((x) & 0xF) << 0) /* Dec Power Measurement Duration <3:0> */ + +/* +* REG_LNA_GAIN +*/ +#define DB_GAIN_READBACK_CHANNEL (1 << 0) /* dB Gain Read-back Channel */ +#define MAX_LNA_GAIN(x) (((x) & 0x7F) << 1) /* Max LNA Gain<6:0> */ + +/* +* REG_RX_QUAD_CAL_LEVEL +*/ +#define RX_QUAD_CAL_LEVEL(x) (((x) & 0xF) << 0) /* Rx Quad Cal Level <3 :0> */ + +/* +* REG_CALIBRATION_CONFIG_1 +*/ +#define ENABLE_PHASE_CORR (1 << 7) /* Enable Phase Corr */ +#define ENABLE_GAIN_CORR (1 << 6) /* Enable Gain Corr */ +#define USE_SETTLE_COUNT_FOR_DC_CAL_WAIT (1 << 5) /* Use Settle Count for DC Cal Wait */ +#define FIXED_DC_CAL_WAIT_TIME (1 << 4) /* Fixed DC Cal Wait Time */ +#define FREE_RUN_MODE (1 << 3) /* Free Run Mode */ +#define ENABLE_CORR_WORD_DECIMATION (1 << 2) /* Enable Corr Word Decimation */ +#define ENABLE_TRACKING_MODE_CH2 (1 << 1) /* Enable Tracking Mode CH2 */ +#define ENABLE_TRACKING_MODE_CH1 (1 << 0) /* Enable Tracking Mode CH1 */ + +/* +* REG_CALIBRATION_CONFIG_2 +*/ +#define SOFT_RESET (1 << 7) /* Soft Reset */ +#define CALIBRATION_CONFIG2_DFLT (0x3 << 5) /* Must be 2'b11 */ +#define K_EXP_PHASE(x) (((x) & 0x1F) << 0) /* K exp Phase<4:0> */ + +/* +* REG_CALIBRATION_CONFIG_3 +*/ +#define PREVENT_POS_LOOP_GAIN (1 << 7) /* Prevent Pos Loop Gain */ +#define K_EXP_AMPLITUDE(x) (((x) & 0x1F) << 0) /* K exp Amplitude<4:0> */ + +/* +* REG_RX_QUAD_GAIN1 +*/ +#define RX_FULL_TABLELMT_TABLE_GAIN(x) (((x) & 0x7F) << 0) /* Rx Full table/LMT table gain<6:0> */ + +/* +* REG_RX_QUAD_GAIN2 +*/ +#define CORRECTION_WORD_DECIMATION_M(x) (((x) & 0x7) << 5) /* Correction Word Decimation M<2:0> */ +#define RX_LPF_GAIN(x) (((x) & 0x1F) << 0) /* Rx LPF gain<4:0> */ + +/* +* REG_RX1_INPUT_A_OFFSETS +*/ +#define RX1_INPUT_A_I_DC_OFFSET_LSB(x) (((x) & 0x3F) << 2) /* Rx1 Input A "I" DC Offset<5:0> */ +#define RX1_INPUT_A_Q_DC_OFFSET(x) (((x) & 0x3) << 0) /* Rx1 Input A "Q" DC Offset<9:8> */ + +/* +* REG_INPUT_A_OFFSETS_1 +*/ +#define RX2_INPUT_A_Q_DC_OFFSET_LSB(x) (((x) & 0xF) << 4) /* Rx2 Input A "Q" DC Offset<3:0> */ +#define RX1_INPUT_A_I_DC_OFFSET_MSB(x) (((x) & 0xF) << 0) /* Rx1 Input A "I" DC Offset<9:6> */ + +/* +* REG_RX2_INPUT_A_OFFSETS +*/ +#define RX2_INPUT_A_I_DC_OFFSET(x) (((x) & 0x3) << 6) /* Rx2 Input A "I" DC Offset<1:0> */ +#define RX2_INPUT_A_Q_DC_OFFSET_MSB(x) (((x) & 0x3F) << 0) /* Rx2 Input A "Q" DC Offset<9:4> */ + +/* +* REG_RX1_INPUT_BC_OFFSETS +*/ +#define RX1_INPUT_BC_I_DC_OFFSET_LSB(x) (((x) & 0x3F) << 2) /* Rx1 Input B&C "I" DC Offset<5:0> */ +#define RX1_INPUT_BC_Q_DC_OFFSET(x) (((x) & 0x3) << 0) /* Rx1 Input B&C "Q" DC Offset<9:8> */ + +/* +* REG_INPUT_BC_OFFSETS_1 +*/ +#define RX2_INPUT_BC_Q_DC_OFFSET_LSB(x) (((x) & 0xF) << 4) /* Rx2 Input B&C "Q" DC Offset<3:0> */ +#define RX1_INPUT_BC_I_DC_OFFSET_MSB(x) (((x) & 0xF) << 0) /* Rx1 Input B&C "I" DC Offset<9:6> */ + +/* +* REG_RX2_INPUT_BC_OFFSETS +*/ +#define RX2_INPUT_BC_I_DC_OFFSET(x) (((x) & 0x3) << 6) /* Rx2 Input B&C "I" DC Offset<1:0> */ +#define RX2_INPUT_BC_Q_DC_OFFSET_MSB(x) (((x) & 0x3F) << 0) /* Rx2 Input B&C "Q" DC Offset<9:4> */ + +/* +* REG_FORCE_BITS +*/ +#define RX2_INPUT_BC_FORCE_OFFSET (1 << 7) /* Rx2 Input B&C Force offset */ +#define RX1_INPUT_BC_FORCE_OFFSET (1 << 6) /* Rx1 Input B&C Force offset */ +#define RX2_INPUT_BC_FORCE_PHGAIN (1 << 5) /* Rx2 Input B&C Force Ph/Gain */ +#define RX1_INPUT_BC_FORCE_PHGAIN (1 << 4) /* Rx1 Input B&C Force Ph/Gain */ +#define RX2_INPUT_A_FORCE_OFFSET (1 << 3) /* Rx2 Input A Force offset */ +#define RX1_INPUT_A_FORCE_OFFSET (1 << 2) /* Rx1 Input A Force offset */ +#define RX2_INPUT_A_FORCE_PHGAIN (1 << 1) /* Rx2 Input A Force Ph/Gain */ +#define RX1_INPUT_A_FORCE_PHGAIN (1 << 0) /* Rx1 Input A Force Ph/Gain */ + +/* +* REG_RF_DC_OFFSET_CONFIG_1 +*/ +#define DAC_FS(x) (((x) & 0x3) << 4) /* DAC FS<1:0> */ +#define RF_DC_CALIBRATION_COUNT(x) (((x) & 0xF) << 0) /* RF DC Calibration Count<3:0> */ + +/* +* REG_RF_DC_OFFSET_ATTEN +*/ +#define RF_DC_OFFSET_TABLE_UPDATE_COUNT(x) (((x) & 0x7) << 5) /* RF DC Offset Table Update Count<2:0> */ +#define RF_DC_OFFSET_ATTEN(x) (((x) & 0x1F) << 0) /* RF DC Offset Attenuation<4:0> */ + +/* +* REG_INVERT_BITS +*/ +#define INVERT_RX2_RF_DC_CGIN_WORD (1 << 7) /* Invert Rx2 RF DC CGin Word */ +#define INVERT_RX1_RF_DC_CGIN_WORD (1 << 6) /* Invert Rx1 RF DC CGin Word */ +#define INVERT_RX2_RF_DC_CGOUT_WORD (1 << 5) /* Invert Rx2 RF DC CGout Word */ +#define INVERT_RX1_RF_DC_CGOUT_WORD (1 << 4) /* Invert Rx1 RF DC CGout Word */ + +/* +* REG_DC_OFFSET_CONFIG2 +*/ +#define USE_WAIT_COUNTER_FOR_RF_DC_INIT_CAL (1 << 7) /* Use Wait Counter for RF DC Init Cal */ +#define ENABLE_FAST_SETTLE_MODE (1 << 6) /* Enable Fast Settle Mode */ +#define ENABLE_BB_DC_OFFSET_TRACKING (1 << 5) /* Enable BB DC Offset Tracking */ +#define RESET_ACC_ON_GAIN_CHANGE (1 << 4) /* Reset Acc on Gain Change */ +#define ENABLE_RF_OFFSET_TRACKING (1 << 3) /* Enable RF Offset Tracking */ +#define DC_OFFSET_UPDATE(x) (((x) & 0x7) << 0) /* DC Offset Update<2:0> */ + +/* +* REG_RF_CAL_GAIN_INDEX +*/ +#define RF_MINIMUM_CALIBRATION_GAIN_INDEX(x) (((x) & 0x7F) << 0) /* RF Minimum Calibration Gain Index<6:0> */ + +/* +* REG_SOI_THRESH +*/ +#define RF_SOI_THRESH(x) (((x) & 0x7F) << 0) /* RF SOI Threshold<6:0> */ + +/* +* REG_BB_DC_OFFSET_SHIFT +*/ +#define INCREASE_COUNT_DURATION (1 << 7) /* Increase Count Duration */ +#define BB_TRACKING_DECIMATE(x) (((x) & 0x3) << 5) /* BB Tracking Decimate<1:0> */ +#define BB_DC_M_SHIFT(x) (((x) & 0x1F) << 0) /* BB DC M Shift<4:0> */ + +/* +* REG_BB_DC_OFFSET_FAST_SETTLE_SHIFT +*/ +#define READ_BACK_CH_SEL (1 << 7) /* Read Back CH Sel */ +#define UPDATE_TRACKING_WORD (1 << 6) /* Update Tracking Word */ +#define FORCE_RX_NULL (1 << 5) /* Force Rx Null */ +#define BB_DC_TRACKING_FAST_SETTLE_M_SHIFT(x) (((x) & 0x1F) << 0) /* BB DC Tracking Fast Settle M Shift<4:0> */ + +/* +* REG_BB_DC_OFFSET_ATTEN +*/ +#define BB_DC_OFFSET_ATTEN(x) (((x) & 0xF) << 0) /* BB DC Offset Atten<3:0> */ + +/* +* REG_RX1_BB_DC_WORD_I_MSB +*/ +#define RX1_BB_DC_OFFSET_CORRECTION_WORD_I(x) (((x) & 0x7F) << 0) /* RX1 BB DC Offset Correction word I<14:8> */ + +/* +* REG_RX1_BB_DC_WORD_Q_MSB +*/ +#define RX1_BB_DC_OFFSET_CORRECTION_WORD_Q(x) (((x) & 0x7F) << 0) /* RX1 BB DC Offset Correction word Q<14:8> */ + +/* +* REG_RX2_BB_DC_WORD_I_MSB +*/ +#define RX2_BB_DC_OFFSET_CORRECTION_WORD_I(x) (((x) & 0x7F) << 0) /* RX2 BB DC Offset Correction word I<14:8> */ + +/* +* REG_RX2_BB_DC_WORD_Q_MSB +*/ +#define RX2_BB_DC_OFFSET_CORRECTION_WORD_Q(x) (((x) & 0x7F) << 0) /* RX2 BB DC Offset Correction word Q<14:8> */ + +/* +* REG_BB_TRACK_CORR_WORD_I_MSB +*/ +#define RX1RX2_BB_DC_OFFSET_TRACKING_CORRECTION_WORD_I(x) (((x) & 0x7F) << 0) /* RX1/RX2 BB DC Offset Tracking correction word I<14:8> */ + +/* +* REG_BB_TRACK_CORR_WORD_Q_MSB +*/ +#define RX1RX2_BB_DC_OFFSET_TRACKING_CORRECTION_WORD_Q(x) (((x) & 0x7F) << 0) /* RX1/RX2 BB DC Offset Tracking correction word Q<14:8> */ + +/* +* REG_SYMBOL_LSB +*/ +#define RX2_RSSI_SYMBOL (1 << 1) /* Rx2 RSSI symbol <0> */ +#define RX1_RSSI_SYMBOL (1 << 0) /* Rx1 RSSI symbol <0> */ + +/* +* REG_PREAMBLE_LSB +*/ +#define RX2_RSSI_PREAMBLE (1 << 1) /* Rx2 RSSI preamble <0> */ +#define RX1_RSSI_PREAMBLE (1 << 0) /* Rx1 RSSI preamble <0> */ + +/* +* REG_RX1_RSSI_SYMBOL, REG_RX1_RSSI_PREAMBLE, +* REG_RX2_RSSI_SYMBOL, REG_RX2_RSSI_PREAMBLE +*/ +#define RSSI_LSB_SHIFT 1 +#define RSSI_LSB_MASK1 0x01 +#define RSSI_LSB_MASK2 0x02 + +/* +* REG_RX_PATH_GAIN_LSB +*/ +#define RX_PATH_GAIN (1 << 0) /* Rx Path Gain<0> */ + +/* +* REG_RX_DIFF_LNA_FORCE +*/ +#define FORCE_RX2_LNA_GAIN (1 << 7) /* Force Rx2 LNA Gain */ +#define RX2_LNA_BYPASS (1 << 6) /* Rx2 LNA Bypass */ +#define FORCE_RX1_LNA_GAIN (1 << 3) /* Force Rx1 LNA Gain */ +#define RX1_LNA_BYPASS (1 << 2) /* Rx1 LNA Bypass */ +#define RX2_LNA_GAIN(x) (((x) & 0x3) << 4) /* Rx2 LNA Gain<1:0> */ +#define RX1_LNA_GAIN(x) (((x) & 0x3) << 0) /* Rx1 LNA Gain<1:0> */ + +/* +* REG_RX_LNA_BIAS_COARSE +*/ +#define RX_LNA_BIAS_COARSE(x) (((x) & 0xF) << 0) /* Rx LNA Bias Coarse<3:0> */ + +/* +* REG_RX_LNA_BIAS_FINE_0 +*/ +#define RX_LNA_PCASCODE_BIAS(x) (((x) & 0x7) << 5) /* Rx LNA p-Cascode Bias<2:0> */ +#define RX_LNA_BIAS(x) (((x) & 0x1F) << 0) /* Rx LNA Bias<4:0> */ + +/* +* REG_RX_LNA_BIAS_FINE_1 +*/ +#define RX_LNA_P_CASCODE_BIAS_FINE(x) (((x) & 0x3) << 0) /* Rx LNA p- Cascode Bias Fine<4:3> */ + +/* +* REG_RX_MIX_GM_CONFIG +*/ +#define RX_MIX_GM_CM_OUT(x) (((x) & 0x7) << 5) /* Rx Mix Gm CM Out<2:0> */ +#define RX_MIX_GM_PLOAD(x) (((x) & 0x3) << 0) /* Rx Mix Gm pload <1:0> */ + +/* +* REG_RX1_MIX_GM_FORCE +*/ +#define FORCE_RX1_MIX_GM (1 << 6) /* Force Rx1 Mix Gm */ +#define RX1_MIX_GM_GAIN(x) (((x) & 0x3F) << 0) /* Rx1 Mix Gm Gain<5:0> */ + +/* +* REG_RX1_MIX_GM_BIAS_FORCE +*/ +#define RX1_MIX_GM_BIAS(x) (((x) & 0x1F) << 0) /* Rx1 Mix Gm Bias<4:0> */ + +/* +* REG_RX2_MIX_GM_FORCE +*/ +#define FORCE_RX2_MIX_GM (1 << 6) /* Force Rx2 Mix Gm */ +#define RX2_MIX_GM_GAIN(x) (((x) & 0x3F) << 0) /* Rx2 Mix Gm Gain<5:0> */ + +/* +* REG_RX2_MIX_GM_BIAS_FORCE +*/ +#define RX2_MIX_GM_BIAS(x) (((x) & 0x1F) << 0) /* Rx2 Mix Gm Bias<4:0> */ + +/* +* REG_INPUT_A_MSBS +*/ +#define INPUT_A_RX1_Q(x) (((x) & 0x3) << 6) /* Input A RX1 Q<9:8> */ +#define INPUT_A_RX1_I(x) (((x) & 0x3) << 4) /* Input A RX1 I<9:8> */ +#define INPUT_A_RX2_I(x) (((x) & 0x3) << 2) /* Input A RX2 I<9:8> */ +#define INPUT_A_RX2_Q(x) (((x) & 0x3) << 0) /* Input A RX2 Q<9:8> */ + +/* +* REG_INPUTS_BC_MSBS +*/ +#define INPUTS_BC_RX1_Q(x) (((x) & 0x3) << 6) /* Inputs B&C RX1 Q<9:8> */ +#define INPUTS_BC_RX1_I(x) (((x) & 0x3) << 4) /* Inputs B&C RX1 I<9:8> */ +#define INPUTS_BC_RX2_I(x) (((x) & 0x3) << 2) /* Inputs B&C RX2 I<9:8> */ +#define INPUTS_BC_RX2_Q(x) (((x) & 0x3) << 0) /* Inputs B&C RX2 Q<9:8> */ + +/* +* REG_FORCE_OS_DAC +*/ +#define FORCE_CGIN_DAC (1 << 2) /* Force CGin DAC */ + +/* +* REG_RX_MIX_LO_CM +*/ +#define RX_MIX_LO_CM(x) (((x) & 0x3F) << 0) /* Rx Mix LO CM<5:0> */ + +/* +* REG_RX_CGB_SEG_ENABLE +*/ +#define RX_CGB_SEG_ENABLE(x) (((x) & 0x3F) << 0) /* Rx CGB Seg Enable<5:0> */ + +/* +* REG_RX_MIX_INPUTBIAS +*/ +#define RX_CGB_INPUT_CM_SEL(x) (((x) & 0x3) << 4) /* Rx CGB Input CM Sel<1:0> */ +#define RX_CGB_BIAS(x) (((x) & 0xF) << 0) /* Rx CGB Bias<3:0> */ + +/* +* REG_RX_TIA_CONFIG +*/ +#define TIA2_OVERRIDE_C (1 << 3) /* TIA2 Override C */ +#define TIA2_OVERRIDE_R (1 << 2) /* TIA2 Override R */ +#define TIA1_OVERRIDE_C (1 << 1) /* TIA1 Override C */ +#define TIA1_OVERRIDE_R (1 << 0) /* TIA1 Override R */ +#define TIA_SEL_CC(x) (((x) & 0x7) << 5) /* TIA Sel CC<2:0> */ + +/* +* REG_TIA1_C_LSB +*/ +#define TIA1_RF(x) (((x) & 0x3) << 6) /* TIA1 RF<1:0> */ +#define TIA1_C_LSB(x) (((x) & 0x3F) << 0) /* TIA1 C LSB<5:0> */ + +/* +* REG_TIA1_C_MSB +*/ +#define TIA1_C_MSB(x) (((x) & 0x7F) << 0) /* TIA1 C MSB<6:0> */ + +/* +* REG_TIA2_C_LSB +*/ +#define TIA2_RF(x) (((x) & 0x3) << 6) /* TIA2 RF<1:0> */ +#define TIA2_C_LSB(x) (((x) & 0x3F) << 0) /* TIA2 C LSB<5:0> */ + +/* +* REG_TIA2_C_MSB +*/ +#define TIA2_C_MSB(x) (((x) & 0x7F) << 0) /* TIA2 C MSB<6:0> */ + +/* +* REG_RX1_BBF_R1A +*/ +#define FORCE_RX1_RESISTORS (1 << 7) /* Force Rx1 Resistors */ +#define RX1_BBF_R1A(x) (((x) & 0x3F) << 0) /* Rx1 BBF R1A<5:0> */ + +/* +* REG_RX2_BBF_R1A +*/ +#define FORCE_RX2_RESISTORS (1 << 7) /* Force Rx2 Resistors */ +#define RX2_BBF_R1A(x) (((x) & 0x3F) << 0) /* Rx2 BBF R1A<5:0> */ + +/* +* REG_RX1_TUNE_CTRL +*/ +#define RX1_TUNE_RESAMPLE_PHASE (1 << 2) /* Rx1 Tune Resample Phase */ +#define RX1_TUNE_RESAMPLE (1 << 1) /* Rx1 Tune Resample */ +#define RX1_PD_TUNE (1 << 0) /* Rx1 PD Tune */ + +/* +* REG_RX2_TUNE_CTRL +*/ +#define RX2_TUNE_RESAMPLE_PHASE (1 << 2) /* Rx2 Tune Resam ple Phase */ +#define RX2_TUNE_RESAMPLE (1 << 1) /* Rx2 Tune Resample */ +#define RX2_PD_TUNE (1 << 0) /* Rx2 PD Tune */ + +/* +* REG_RX_BBF_R2346 +*/ +#define TUNE_OVERRIDE (1 << 7) /* Tune Override */ +#define RX_BBF_R2346(x) (((x) & 0x7) << 0) /* Rx BBF R2346<2:0> */ + +/* +* REG_RX_BBF_C1_MSB +*/ +#define RX_BBF_C1_MSB(x) (((x) & 0x3F) << 0) /* Rx BBF C1 MSB<5:0> */ + +/* +* REG_RX_BBF_C1_LSB +*/ +#define RX_BBF_C1_LSB(x) (((x) & 0x7F) << 0) /* Rx BBF C1 LSB<6:0> */ + +/* +* REG_RX_BBF_C2_MSB +*/ +#define RX_BBF_C2_MSB(x) (((x) & 0x3F) << 0) /* Rx BBF C2 MSB<5:0> */ + +/* +* REG_RX_BBF_C2_LSB +*/ +#define RX_BBF_C2_LSB(x) (((x) & 0x7F) << 0) /* Rx BBF C2 LSB<6:0> */ + +/* +* REG_RX_BBF_C3_MSB +*/ +#define RX_BBF_C3_MSB(x) (((x) & 0x3F) << 0) /* Rx BBF C3 MSB<5:0> */ + +/* +* REG_RX_BBF_C3_LSB +*/ +#define RX_BBF_C3_LSB(x) (((x) & 0x7F) << 0) /* Rx BBF C3 LSB<6:0> */ + +/* +* REG_RX_BBF_CC1_CTR +*/ +#define RX_BBF_CC1_CTR(x) (((x) & 0x7F) << 0) /* Rx BBF CC1 Ctr<6:0> */ + +/* +* REG_RX_BBF_POW_RZ_BYTE0 +*/ +#define MUST_BE_ZERO (1 << 7) /* Must be zero */ +#define RX1_BBF_POW_CTR(x) (((x) & 0x3) << 5) /* Rx1 BBF Pow Ctr<1:0> */ +#define RX_BBF_RZ1_CTR(x) (((x) & 0x3) << 3) /* Rx BBF Rz1 Ctr<1:0> */ + +/* +* REG_RX_BBF_CC2_CTR +*/ +#define RX_BBF_CC2_CTR(x) (((x) & 0x7F) << 0) /* Rx BBF CC2 Ctr<6:0> */ + +/* +* REG_RX_BBF_POW_RZ_BYTE1 +*/ +#define RX_BBF_POW3_CTR(x) (((x) & 0x3) << 6) /* Rx BBF Pow3 Ctr<1:0> */ +#define RX_BBF_RZ3_CTR(x) (((x) & 0x3) << 4) /* Rx BBF RZ3 Ctr<1:0> */ +#define RX_BBF_POW2_CTR(x) (((x) & 0x3) << 2) /* Rx BBF Pow2 Ctr<1:0> */ +#define RX_BBF_RZ2_CTR(x) (((x) & 0x3) << 0) /* Rx BBF Rz2 Ctr<1:0> */ + +/* +* REG_RX_BBF_CC3_CTR +*/ +#define RX_BBF_CC3_CTR(x) (((x) & 0x7F) << 0) /* Rx BBF CC3 Ctr<6:0> */ + +/* +* REG_RX_BBF_TUNE +*/ +#define RXBBF_BYPASS_BIAS_R (1 << 7) /* RxBBF Bypass Bias R */ +#define RX_BBF_R5_TUNE (1 << 4) /* Rx BBF R5 Tune */ +#define RX1_BBF_TUNE_COMP_I (1 << 3) /* Rx1 BBF Tune Comp I */ +#define RX1_BBF_TUNE_COMP_Q (1 << 2) /* Rx1 BBF Tune Comp Q */ +#define RX2_BBF_TUNE_COMP_I (1 << 1) /* Rx2 BBF Tune Comp I */ +#define RX2_BBF_TUNE_COMP_Q (1 << 0) /* Rx2 BBF Tune Comp Q */ +#define RX_BBF_TUNE_CTR(x) (((x) & 0x3) << 5) /* Rx BBF Tune Ctr<1:0> */ + +/* +* REG_RX1_BBF_MAN_GAIN +*/ +#define RX1_BBF_FORCE_GAIN (1 << 5) /* Rx1 BBF Force Gain */ +#define RX1_BBF_BQ_GAIN(x) (((x) & 0x3) << 3) /* Rx1 BBF BQ Gain<1:0> */ +#define RX1_BBF_POLE_GAIN(x) (((x) & 0x7) << 0) /* Rx1 BBF Pole Gain<2:0> */ + +/* +* REG_RX2_BBF_MAN_GAIN +*/ +#define RX2_BBF_FORCE_GAIN (1 << 5) /* Rx2 BBF Force Gain */ +#define RX2_BBF_BQ_GAIN(x) (((x) & 0x3) << 3) /* Rx2 BBF BQ Gain<1:0> */ +#define RX2_BBF_POLE_GAIN(x) (((x) & 0x7) << 0) /* Rx2 BBF Pole Gain<2:0> */ + +/* +* REG_RX_BBF_TUNE_CONFIG +*/ +#define RX_TUNE_EVALTIME (1 << 4) /* Rx Tune Evaltime */ +#define RX_BBF_TUNE_DIVIDE (1 << 0) /* RX BBF Tune Divide<8> */ +#define TUNE_COMP_MASK(x) (((x) & 0x3) << 5) /* Tune Comp Mask <1:0> */ +#define RX_TUNE_MODE(x) (((x) & 0x7) << 1) /* Rx Tune Mode<2:0> */ + +/* +* REG_POLE_GAIN +*/ +#define POLE_GAIN_TUNE(x) (((x) & 0x3) << 0) /* Pole Gain Tune<1:0> */ + +/* +* REG_RX_BBBW_MHZ +*/ +#define RX_TUNE_BBBW_MHZ(x) (((x) & 0x1F) << 0) /* Rx Tune BBBW MHz<4::0> */ + +/* +* REG_RX_BBBW_KHZ +*/ +#define RX_TUNE_BBBW_KHZ(x) (((x) & 0x7F) << 0) /* Rx Tune BBBW kHz<6:0> */ + +/* +* REG_RX_PFD_CONFIG +*/ +#define BYPASS_LD_SYNTH (1 << 0) /* Bypass Ld Synth */ + +/* +* REG_RX_INTEGER_BYTE_1 +*/ +#define SYNTH_INTEGER_WORD(x) (((x) & 0x7) << 0) /* Synthesizer Integer Word<10:8> */ + +/* +* REG_RX_FRACT_BYTE_2 +*/ +#define SYNTH_FRACT_WORD(x) (((x) & 0x7F) << 0) /* Synthesizer Fractional Word <22:16> */ + +/* +* REG_RX_FORCE_VCO_TUNE_1 +*/ +#define VCO_CAL_OFFSET(x) (((x) & 0xF) << 3) /* VCO Cal Offset<3:0> */ + +/* +* REG_RX_ALC_VARACTOR +*/ +#define INIT_ALC_VALUE(x) (((x) & 0xF) << 4) /* Init ALC Value<3:0> */ +#define VCO_VARACTOR(x) (((x) & 0xF) << 0) /* VCO Varactor<3:0> */ + +/* +* REG_RX_VCO_OUTPUT +*/ +#define PORB_VCO_LOGIC (1 << 6) /* PORb VCO Logic */ +#define VCO_OUTPUT_LEVEL(x) (((x) & 0xF) << 0) /* VCO Output Level<3:0> */ + +/* +* REG_RX_CP_CURRENT +*/ +#define CHARGE_PUMP_CURRENT(x) (((x) & 0x3F) << 0) /* Charge Pump Current<5:0> */ + +/* +* REG_RX_CP_OFFSET +*/ +#define SYNTH_RECAL (1 << 7) /* Synth Re-Cal */ + +/* +* REG_RX_CP_CONFIG +*/ +#define HALF_VCO_CAL_CLK (1 << 7) /* Half Vco Cal Clk */ +#define CP_OFFSET_OFF (1 << 4) /* CP Offset Off */ +#define F_CPCAL (1 << 3) /* F Cpcal */ +#define CP_CAL_ENABLE (1 << 2) /* Cp Cal Enable */ + +/* +* REG_RX_LOOP_FILTER_1 +*/ +#define LOOP_FILTER_C2(x) (((x) & 0xF) << 4) /* Loop Filter C2<3:0> */ +#define LOOP_FILTER_C1(x) (((x) & 0xF) << 0) /* Loop Filter C1<3:0> */ + +/* +* REG_RX_LOOP_FILTER_2 +*/ +#define LOOP_FILTER_R1(x) (((x) & 0xF) << 4) /* Loop Filter R1<3:0> */ +#define LOOP_FILTER_C3(x) (((x) & 0xF) << 0) /* Loop Filter C3<3:0> */ + +/* +* REG_RX_LOOP_FILTER_3 +*/ +#define LOOP_FILTER_BYPASS_R3 (1 << 7) /* Loop Filter Bypass R3 */ +#define LOOP_FILTER_BYPASS_R1 (1 << 6) /* Loop Filter Bypass R1 */ +#define LOOP_FILTER_BYPASS_C2 (1 << 5) /* Loop Filter Bypass C2 */ +#define LOOP_FILTER_BYPASS_C1 (1 << 4) /* Loop Filter Bypass C1 */ +#define LOOP_FILTER_R3(x) (((x) & 0xF) << 0) /* Loop Filter R3<3:0> */ + +/* +* REG_RX_DITHERCP_CAL +*/ +#define FORCED_CP_CAL_WORD(x) (((x) & 0xF) << 0) /* Forced CP Cal Word<3:0> */ + +/* +* REG_RX_VCO_BIAS_1 +*/ +#define VCO_BIAS_TCF(x) (((x) & 0x3) << 3) /* VCO Bias Tcf<1:0> */ +#define VCO_BIAS_REF(x) (((x) & 0x7) << 0) /* VCO Bias Ref<2:0> */ + +/* +* REG_RX_CAL_STATUS +*/ +#define CP_CAL_VALID (1 << 7) /* CP Cal Valid */ +#define CP_CAL_DONE (1 << 5) /* CP Cal Done */ +#define VCO_CAL_BUSY (1 << 4) /* VCO Cal Busy */ +#define CP_CAL_WORD(x) (((x) & 0xF) << 0) /* CP Cal Word<3:0> */ + +/* +* REG_RX_VCO_CAL_REF +*/ +#define VCO_CAL_REF_TCF(x) (((x) & 0x7) << 0) /* VCO Cal Ref Tcf<2:0> */ + +/* +* REG_RX_VCO_PD_OVERRIDES +*/ +#define POWER_DOWN_VARACTOR_REF (1 << 3) /* Power Down Varactor Ref */ +#define PWR_DOWN_VARACT_REF_TCF (1 << 2) /* Pwr Down Varact Ref Tcf */ +#define POWER_DOWN_CAL_TCF (1 << 1) /* Power Down Cal Tcf */ +#define POWER_DOWN_VCO_BUFFFER (1 << 0) /* Power Down VCO Bufffer */ + +/* +* REG_RX_CP_OVERRANGE_VCO_LOCK +*/ +#define CP_OVRG_HIGH (1 << 7) /* CP Ovrg High */ +#define CP_OVRG_LOW (1 << 6) /* CP Ovrg Low */ +#define VCO_LOCK (1 << 1) /* Lock */ + +/* +* REG_RX_VCO_LDO +*/ +#define VCO_LDO_BYPASS (1 << 7) /* VCO LDO Bypass */ +#define VCO_LDO_INRUSH(x) (((x) & 0x3) << 5) /* VCO LDO Inrush<1:0> */ +#define VCO_LDO_SEL(x) (((x) & 0x7) << 2) /* VCO LDO Sel<2:0> */ +#define VCO_LDO_VDROP_SEL(x) (((x) & 0x3) << 0) /* VCO LDO Vdrop Sel<1:0> */ + +/* +* REG_RX_VCO_CAL +*/ +#define VCO_CAL_EN (1 << 7) /* VCO Cal En */ +#define VCO_CAL_ALC_WAIT(x) (((x) & 0x7) << 4) /* VCO Cal ALC Wait <2:0> */ +#define VCO_CAL_COUNT(x) (((x) & 0x3) << 2) /* VCO Cal Count <1:0> */ + +/* +* REG_RX_LOCK_DETECT_CONFIG +*/ +#define LOCK_DETECT_COUNT(x) (((x) & 0x3) << 2) /* Lock Detect Count<1:0> */ +#define LOCK_DETECT_MODE(x) (((x) & 0x3) << 0) /* Lock Detect Mode<1:0> */ + +/* +* REG_RX_CP_LEVEL_DETECT +*/ +#define CP_LEVEL_DETECT_POWER_DOWN (1 << 6) /* CP Level Detect Power Down */ +#define CP_LEVEL_THRESH_LOW(x) (((x) & 0x7) << 3) /* CP Level Threshold Low<2:0> */ +#define CP_LEVEL_THRESH_HIGH(x) (((x) & 0x7) << 0) /* CP Level Threshold High<2:0> */ + +/* +* REG_RX_DSM_SETUP_0 +*/ +#define DSM_PROG(x) (((x) & 0xF) << 0) /* DSM Prog<3:0> */ + +/* +* REG_RX_DSM_SETUP_1 +*/ +#define SIF_CLOCK (1 << 6) /* SIF clock */ +#define SIF_RESET_BAR (1 << 5) /* SIF Reset Bar */ +#define SIF_ADDR(x) (((x) & 0x1F) << 0) /* SIF Addr<4:0> */ + +/* +* REG_RX_CORRECTION_WORD0 +*/ +#define UPDATE_FREQ_WORD (1 << 7) /* Update Freq Word */ +#define READ_EFFECTIVE_TUNING_WORD (1 << 5) /* Read Effective Tuning Word */ +#define FREQ_CORRECTION_WORD_MSB(x) (((x) & 0x1F) << 0) /* Frequency Correction Word<11:7> */ + +/* +* REG_RX_CORRECTION_WORD1 +*/ +#define UPDATE_FREQ_WORD (1 << 7) /* Update Freq Word */ +#define FREQ_CORRECTION_WORD_LSB(x) (((x) & 0x7F) << 0) /* Frequency Correction Word<6:0> */ + +/* +* REG_RX_VCO_VARACTOR_CTRL_0 +*/ +#define VCO_VARACTOR_REFERENCE_TCF(x) (((x) & 0x7) << 4) /* VCO Varactor Reference Tcf<2:0> */ +#define VCO_VARACTOR_OFFSET(x) (((x) & 0xF) << 0) /* VCO Varactor Offset<3:0> */ + +/* +* REG_RX_VCO_VARACTOR_CTRL_1 +*/ +#define VCO_VARACTOR_REFERENCE(x) (((x) & 0xF) << 0) /* VCO Varactor Reference<3:0> */ + +/* +* REG_RX_FAST_LOCK_SETUP +*/ +#define RX_FAST_LOCK_LOAD_SYNTH (1 << 3) /* Rx Fast Lock Load Synth */ +#define RX_FAST_LOCK_PROFILE_INIT (1 << 2) /* Rx Fast Lock Profile Init */ +#define RX_FAST_LOCK_PROFILE_PIN_SELECT (1 << 1) /* Rx Fast Lock Profile Pin Select */ +#define RX_FAST_LOCK_MODE_ENABLE (1 << 0) /* Rx Fast Lock Mode Enable */ +#define RX_FAST_LOCK_PROFILE(x) (((x) & 0x7) << 5) /* Rx Fast Lock Profile<2:0> */ + +/* +* REG_RX_FAST_LOCK_PROGRAM_ADDR +*/ +#define RX_FAST_LOCK_PROFILE_ADDR(x) (((x) & 0x7) << 4) /* Rx Fast Lock Profile<2:0> */ +#define RX_FAST_LOCK_PROFILE_WORD(x) (((x) & 0xF) << 0) /* Configuration Word <3:0> */ + + +/* +* REG_RX_FAST_LOCK_PROGRAM_CTRL +*/ +#define RX_FAST_LOCK_PROGRAM_WRITE (1 << 1) /* Rx Fast Lock Program Write */ +#define RX_FAST_LOCK_PROGRAM_CLOCK_ENABLE (1 << 0) /* Rx Fast Lock Program Clock Enable */ + +#define RX_FAST_LOCK_CONFIG_WORD_NUM 16 + +/* +* REG_RX_LO_GEN_POWER_MODE +*/ +#define RX_LO_GEN_POWER_MODE(x) (((x) & 0x3) << 4) /* Power Mode<3:0> */ + +/* +* REG_TX_PFD_CONFIG +*/ +#define DIV_TEST_EN (1 << 5) /* Div Test En */ +#define PFD_CLK_EDGE (1 << 1) /* PFD Clk Edge */ +#define BYPASS_LD_SYNTH (1 << 0) /* Bypass Ld Synth */ +#define PFD_WIDTH(x) (((x) & 0x3) << 2) /* PFD Width <1:0> */ + +/* +* REG_TX_INTEGER_BYTE_1 +*/ +#define SDM_BYPASS (1 << 7) /* SDM Bypass */ +#define SDM_POWER_DOWN (1 << 6) /* SDM Power Down */ +#define SYNTH_INTEGER_WORD(x) (((x) & 0x7) << 0) /* Synthesizer Integer Word<10:8> */ + +/* +* REG_TX_FRACT_BYTE_2 +*/ +#define SYNTH_FRACT_WORD(x) (((x) & 0x7F) << 0) /* Synthesizer Fractional Word <22:16> */ + +/* +* REG_TX_FORCE_ALC +*/ +#define FORCE_ALC_ENABLE (1 << 7) /* Force ALC Enable */ +#define FORCE_ALC_WORD(x) (((x) & 0x7F) << 0) /* Force ALC Word<6:0> */ + +/* +* REG_TX_FORCE_VCO_TUNE_1 +*/ +#define BYPASS_LOAD_DELAY (1 << 7) /* Bypass Load Delay */ +#define FORCE_VCO_TUNE_ENABLE (1 << 1) /* Force VCO Tune Enable */ +#define FORCE_VCO_TUNE (1 << 0) /* Force VCO Tune */ +#define VCO_CAL_OFFSET(x) (((x) & 0xF) << 3) /* VCO Cal Offset<3:0> */ + +/* +* REG_TX_ALCVARACT_OR +*/ +#define INIT_ALC_VALUE(x) (((x) & 0xF) << 4) /* Init ALC Value<3:0> */ +#define VCO_VARACTOR(x) (((x) & 0xF) << 0) /* VCO Varactor<3:0> */ + +/* +* REG_TX_VCO_OUTPUT +*/ +#define PORB_VCO_LOGIC (1 << 6) /* PORb VCO Logic */ +#define VCO_OUTPUT_LEVEL(x) (((x) & 0xF) << 0) /* VCO Output Level<3:0> */ + +/* +* REG_TX_CP_CURRENT +*/ +#define TX_CP_CURRENT_DFLT (1 << 7) /* Set to 1 */ +#define VTUNE_FORCE (1 << 6) /* Vtune Force */ +#define CHARGE_PUMP_CURRENT(x) (((x) & 0x3F) << 0) /* Charge Pump Current<5:0> */ + +/* +* REG_TX_CP_OFFSET +*/ +#define SYNTH_RECAL (1 << 7) /* Synth Re-Cal */ +#define CHARGE_PUMP_OFFSET(x) (((x) & 0x3F) << 0) /* Charge Pump Offset<5:0> */ + +/* +* REG_TX_CP_CONFIG +*/ +#define HALF_VCO_CAL_CLK (1 << 7) /* Half Vco Cal Clk */ +#define DITHER_MODE (1 << 6) /* Dither Mode */ +#define CP_OFFSET_OFF (1 << 4) /* Cp Offset Off */ +#define F_CPCAL (1 << 3) /* F Cpcal */ +#define CP_CAL_ENABLE (1 << 2) /* Cp Cal Enable */ +#define CP_TEST(x) (((x) & 0x3) << 0) /* Cp Test <1:0> */ + +/* +* REG_TX_LOOP_FILTER_1 +*/ +#define LOOP_FILTER_C2(x) (((x) & 0xF) << 4) /* Loop Filter C2<3:0> */ +#define LOOP_FILTER_C1(x) (((x) & 0xF) << 0) /* Loop Filter C1<3:0> */ + +/* +* REG_TX_LOOP_FILTER_2 +*/ +#define LOOP_FILTER_R1(x) (((x) & 0xF) << 4) /* Loop Filter R1<3:0> */ +#define LOOP_FILTER_C3(x) (((x) & 0xF) << 0) /* Loop Filter C3<3:0> */ + +/* +* REG_TX_LOOP_FILTER_3 +*/ +#define LOOP_FILTER_BYPASS_R3 (1 << 7) /* Loop Filter Bypass R3 */ +#define LOOP_FILTER_BYPASS_R1 (1 << 6) /* Loop Filter Bypass R1 */ +#define LOOP_FILTER_BYPASS_C2 (1 << 5) /* Loop Filter Bypass C2 */ +#define LOOP_FILTER_BYPASS_C1 (1 << 4) /* Loop Filter Bypass C1 */ +#define LOOP_FILTER_R3(x) (((x) & 0xF) << 0) /* Loop Filter R3<3:0> */ + +/* +* REG_TX_DITHERCP_CAL +*/ +#define NUMBER_SDM_DITHER_BITS(x) (((x) & 0xF) << 4) /* Number SDM Dither Bits<3:0> */ +#define FORCED_CP_CAL_WORD(x) (((x) & 0xF) << 0) /* Forced CP Cal Word<3:0> */ + +/* +* REG_TX_VCO_BIAS_1 +*/ +#define MUST_BE_ZEROS(x) (((x) & 0x3) << 5) /* Must be zeros */ +#define VCO_BIAS_TCF(x) (((x) & 0x3) << 3) /* VCO Bias Tcf<1:0> */ +#define VCO_BIAS_REF(x) (((x) & 0x7) << 0) /* VCO Bias Ref<2:0> */ + +/* +* REG_TX_VCO_BIAS_2 +*/ +#define VCO_BYPASS_BIAS_DAC_R (1 << 7) /* VCO Bypass Bias DAC R */ +#define VCO_COMP_BYPASS_BIAS_R (1 << 4) /* VCO Comp Bypass Bias R */ +#define BYPASS_PRESCALE_R (1 << 3) /* Bypass Prescale R */ +#define LAST_ALC_ENABLE (1 << 2) /* Last ALC Enable */ +#define PRESCALE_BIAS(x) (((x) & 0x3) << 0) /* Prescale Bias <1:0> */ + +/* +* REG_TX_CAL_STATUS +*/ +#define CP_CAL_VALID (1 << 7) /* CP Cal Valid */ +#define COMP_OUT (1 << 6) /* Comp Out */ +#define CP_CAL_DONE (1 << 5) /* CP Cal Done */ +#define VCO_CAL_BUSY (1 << 4) /* VCO Cal Busy */ +#define CP_CAL_WORD(x) (((x) & 0xF) << 0) /* CP Cal Word<3:0> */ + +/* +* REG_TX_VCO_CAL_REF +*/ +#define VCO_CAL_REF_MONITOR (1 << 3) /* VCO Cal Ref Monitor */ +#define VCO_CAL_REF_TCF(x) (((x) & 0x7) << 0) /* VCO Cal Ref Tcf<2:0> */ + +/* +* REG_TX_VCO_PD_OVERRIDES +*/ +#define POWER_DOWN_VARACTOR_REF (1 << 3) /* Power Down Varactor Ref */ +#define POWER_DOWN_VARACT_REF_TCF (1 << 2) /* Power Down Varact Ref Tcf */ +#define POWER_DOWN_CAL_TCF (1 << 1) /* Power Down Cal Tcf */ +#define POWER_DOWN_VCO_BUFFFER (1 << 0) /* Power Down VCO Bufffer */ + +/* +* REG_TX_CP_OVERRANGE_VCO_LOCK +*/ +#define CP_OVRG_HIGH (1 << 7) /* CP Ovrg High */ +#define CP_OVRG_LOW (1 << 6) /* CP Ovrg Low */ +#define VCO_LOCK (1 << 1) /* Lock */ + +/* +* REG_TX_VCO_LDO +*/ +#define VCO_LDO_BYPASS (1 << 7) /* VCO LDO Bypass */ +#define VCO_LDO_INRUSH(x) (((x) & 0x3) << 5) /* VCO LDO Inrush<1:0> */ +#define VCO_LDO_VOUT_SEL(x) (((x) & 0x7) << 2) /* VCO LDO Vout Sel<2:0> */ +#define VCO_LDO_VDROP_SEL(x) (((x) & 0x3) << 0) /* VCO LDO Vdrop Sel<1:0> */ + +/* +* REG_TX_VCO_CAL +*/ +#define VCO_CAL_EN (1 << 7) /* VCO Cal En */ +#define VCO_CAL_ALC_WAIT(x) (((x) & 0x7) << 4) /* VCO Cal ALC Wait<2:0) */ +#define VCO_CAL_COUNT(x) (((x) & 0x3) << 2) /* VCO Cal Count<1:0> */ +#define FB_CLOCK_ADV(x) (((x) & 0x3) << 0) /* FB Clock Adv<1:0> */ + +/* +* REG_TX_LOCK_DETECT_CONFIG +*/ +#define LOCK_DETECT_COUNT(x) (((x) & 0x3) << 2) /* Lock Detect Count<1:0> */ +#define LOCK_DETECT_MODE(x) (((x) & 0x3) << 0) /* Lock Detect Mode<1:0> */ + +/* +* REG_TX_CP_LEVEL_DETECT +*/ +#define CP_LEVEL_DETECT_POWER_DOWN (1 << 6) /* CP Level Detect Power Down */ +#define CP_LEVEL_DETECT_THRESH_LOW(x) (((x) & 0x7) << 3) /* CP Level Detect Threshold Low<2:0> */ +#define CP_LEVEL_DETECT_THRESH_HIGH(x) (((x) & 0x7) << 0) /* CP Level Detect Threshold High<2:0> */ + +/* +* REG_TX_DSM_SETUP_0 +*/ +#define DSM_PROG(x) (((x) & 0xF) << 0) /* DSM Prog<3:0> */ + +/* +* REG_TX_DSM_SETUP_1 +*/ +#define SIF_CLOCK (1 << 6) /* SIF clock */ +#define SIF_RESET_BAR (1 << 5) /* SIF Reset Bar */ +#define SIF_ADDR(x) (((x) & 0x1F) << 0) /* SIF Addr<4:0> */ + +/* +* REG_TX_CORRECTION_WORD0 +*/ +#define UPDATE_FREQ_WORD (1 << 7) /* Update Freq Word */ +#define READ_EFFECTIVE_TUNING_WORD (1 << 5) /* Read Effective Tuning Word */ +#define FREQ_CORRECTION_WORD_MSB(x) (((x) & 0x1F) << 0) /* Frequency Correction Word<11:7> */ + +/* +* REG_TX_CORRECTION_WORD1 +*/ +#define UPDATE_FREQ_WORD (1 << 7) /* Update Freq Word */ +#define FREQ_CORRECTION_WORD_LSB(x) (((x) & 0x7F) << 0) /* Frequency Correction Word<6:0> */ + +/* +* REG_TX_VCO_VARACTOR_CTRL_0 +*/ +#define VCO_VARACTOR_REFERENCE_TCF(x) (((x) & 0x7) << 4) /* VCO Varactor Reference Tcf<2:0> */ +#define VCO_VARACTOR_OFFSET(x) (((x) & 0xF) << 0) /* VCO Varactor Offset<3:0> */ + +/* +* REG_TX_VCO_VARACTOR_CTRL_1 +*/ +#define VCO_VARACTOR_REFERENCE(x) (((x) & 0xF) << 0) /* VCO Varactor Reference<3:0> */ + +/* +* REG_DCXO_COARSE_TUNE +*/ +#define DCXO_TUNE_COARSE(x) (((x) & 0x3F) << 0) /* DCXO Tune Coarse<5:0> */ + +/* +* REG_DCXO_FINE_TUNE_LOW +*/ +#define DCXO_TUNE_FINE_LOW(x) (((x) & 0x1F) << 3) /* DCXO Tune Fine<4:0> */ + +/* +* REG_DCXO_FINE_TUNE_HIGH +*/ +#define DCXO_TUNE_FINE_HIGH(x) ((x) >> 5) /* DCXO Tune Fine<12:5> */ + +/* +* REG_DCXO_CONFIG +*/ +#define MUST_BE_ZERO (1 << 7) /* Must be zero */ +#define DCXO_RTAIL(x) (((x) & 0x7) << 4) /* DCXO Rtail<2:0> */ +#define DCXO_RD(x) (((x) & 0x3) << 2) /* DCXO Rd<1:0> */ + +/* +* REG_DCXO_TEMPCO_ADDR +*/ +#define DCXO_TEMPCO_EN (1 << 7) /* DCXO Tempco En */ +#define DCXO_TEMPCO_CLK (1 << 6) /* DCXO Tempco Clk */ +#define DCXO_TEMPERATURE_COEF_ADDRESS(x) (((x) & 0x3F) << 0) /* DCXO Temperature Coefficient Address<5:0> */ + +/* +* REG_TX_FAST_LOCK_SETUP +*/ +#define TX_FAST_LOCK_LOAD_SYNTH (1 << 3) /* Tx Fast Lock Load Synth */ +#define TX_FAST_LOCK_PROFILE_INIT (1 << 2) /* Tx Fast Lock Profile Init */ +#define TX_FAST_LOCK_PROFILE_PIN_SELECT (1 << 1) /* Tx Fast Lock Profile Pin Select */ +#define TX_FAST_LOCK_MODE_ENABLE (1 << 0) /* Tx Fast Lock Mode Enable */ +#define TX_FAST_LOCK_PROFILE(x) (((x) & 0x7) << 5) /* Tx Fast Lock Profile<2:0> */ + +/* +* REG_TX_FAST_LOCK_PROGRAM_CTRL +*/ +#define TX_FAST_LOCK_PROGRAM_WRITE (1 << 1) /* Tx Fast Lock Program Write */ +#define TX_FAST_LOCK_PROGRAM_CLOCK_ENABLE (1 << 0) /* Tx Fast Lock Program Clock Enable */ + +/* +* REG_TX_LO_GEN_POWER_MODE +*/ +#define TX_LO_GEN_POWER_MODE(x) (((x) & 0xF) << 4) /* Power Mode<3:0> */ + +/* +* REG_BANDGAP_CONFIG0 +*/ +#define POWER_DOWN_BANDGAP_REF (1 << 7) /* Power Down Bandgap Ref */ +#define MASTER_BIAS_FILTER_BYPASS (1 << 6) /* Master Bias Filter Bypass */ +#define MASTER_BIAS_REF_SEL (1 << 5) /* Master Bias Ref Sel */ +#define MASTER_BIAS_TRIM(x) (((x) & 0x1F) << 0) /* Master Bias Trim<4:0> */ + +/* +* REG_BANDGAP_CONFIG1 +*/ +#define VCO_LDO_FILTER_BYPASS (1 << 7) /* VCO LDO Filter Bypass */ +#define VCO_LDO_REF_SEL (1 << 6) /* VCO LDO Ref Sel */ +#define BANDGAP_REF_RESET (1 << 5) /* Bandgap Ref Reset */ +#define BANDGAP_TEMP_TRIM(x) (((x) & 0x1F) << 0) /* Bandgap Temp Trim<4:0> */ + +/* +* REG_REF_DIVIDE_CONFIG_1 +*/ +#define REF_DIVIDE_CONFIG_1_DFLT (1 << 2) /* Set to 1 */ +#define RX_REF_RESET_BAR (1 << 1) /* Rx Ref Reset Bar */ +#define RX_REF_DIVIDER_MSB (1 << 0) /* Rx Ref Divider<1> */ + +/* +* REG_REF_DIVIDE_CONFIG_2 +*/ +#define RX_REF_DIVIDER_LSB (1 << 7) /* Rx Ref Divider< 0> */ +#define TX_REF_RESET_BAR (1 << 4) /* Tx Ref Reset Bar */ +#define RX_REF_DOUBLER_FB_DELAY(x) (((x) & 0x3) << 5) /* Rx Ref Doubler FB Delay<1:0> */ +#define TX_REF_DIVIDER(x) (((x) & 0x3) << 2) /* Tx Ref Divider<1:0> */ +#define TX_REF_DOUBLER_FB_DELAY(x) (((x) & 0x3) << 0) /* Tx Ref Doubler FB Delay<1:0> */ + +/* +* REG_GAIN_RX1,2 +*/ +#define FULL_TABLE_GAIN_INDEX(x) (((x) & 0x7F) << 0) /* Full Table Gain Index Rx1/LMT Gain Rx1<6:0> */ + +/* +* REG_LPF_GAIN_RX1,2 +*/ +#define LPF_GAIN_RX(x) (((x) & 0x1F) << 0) /* LPF gain Rx1<4:0> */ + +/* +* REG_DIG_GAIN_RX1,2 +*/ +#define DIGITAL_GAIN_RX(x) (((x) & 0x1F) << 0) /* Digital gain Rx1<4:0> */ + +/* +* REG_FAST_ATTACK_STATE +*/ +#define FAST_ATTACK_STATE_RX2(x) (((x) & 0x7) << 4) /* Fast Attack State Rx2<2:0> */ +#define FAST_ATTACK_STATE_RX1(x) (((x) & 0x7) << 0) /* Fast Attack State Rx1<2:0> */ +#define FAST_ATK_MASK 0x7 +#define RX1_FAST_ATK_SHIFT 0 +#define RX2_FAST_ATK_SHIFT 4 +#define FAST_ATK_RESET 0 +#define FAST_ATK_PEAK_DETECT 1 +#define FAST_ATK_PWR_MEASURE 2 +#define FAST_ATK_FINAL_SETTELING 3 +#define FAST_ATK_FINAL_OVER 4 +#define FAST_ATK_GAIN_LOCKED 5 + +/* +* REG_SLOW_LOOP_STATE +*/ +#define SLOW_LOOP_STATE_RX2(x) (((x) & 0x7) << 4) /* Slow Loop State Rx2<2:0> */ +#define SLOW_LOOP_STATE_RX1(x) (((x) & 0x7) << 0) /* Slow Loop State Rx1<2:0> */ + + +/* +* REG_OVRG_SIGS_RX1,2 +*/ +#define GAIN_LOCK_1 (1 << 6) /* Gain Lock 1 */ +#define LOW_POWER_1 (1 << 5) /* Low Power 1 */ +#define LARGE_LMT_OL (1 << 4) /* Large LMT OL */ +#define SMALL_LMT_OL (1 << 3) /* Small LMT OL */ +#define LARGE_ADC_OL (1 << 2) /* Large ADC OL */ +#define SMALL_ADC_OL (1 << 1) /* Small ADC OL */ +#define DIG_SAT (1 << 0) /* Dig Sat */ +/* +* REG_CTRL +*/ +#define CTRL_ENABLE (1 << 0) /* Set to 1 */ + +/* +* REG_BIST_CONFIG +*/ +#define TONE_PRBS (1 << 1) /* Tone/ PRBS */ +#define BIST_ENABLE (1 << 0) /* BIST Enable */ +#define TONE_FREQ(x) (((x) & 0x3) << 6) /* Tone Frequency<1:0> */ +#define TONE_LEVEL(x) (((x) & 0x3) << 4) /* Tone Level<1:0> */ +#define BIST_CTRL_POINT(x) (((x) & 0x3) << 2) /* BIST Control Point <1:0> */ + +/* +* REG_OBSERVE_CONFIG +*/ +#define DATA_PORT_SP_HD_LOOP_TEST_OE (1 << 7) /* Data Port SP, HD Loop Test OE */ +#define RX_MASK (1 << 6) /* Rx Mask */ +#define CHANNEL (1 << 5) /* Channel */ +#define DATA_PORT_LOOP_TEST_ENABLE (1 << 0) /* Data Port Loop Test Enable */ +#define OBSERVATION_POINT(x) (((x) & 0xF) << 1) /* Observation Point<2:0> */ + +/* +* REG_BIST_AND_DATA_PORT_TEST_CONFIG +*/ +#define BIST_MASK_CHANNEL_2_Q_DATA (1 << 5) /* BIST Mask Channel 2 Q data */ +#define BIST_MASK_CHANNEL_2_I_DATA (1 << 4) /* BIST Mask Channel 2 I data */ +#define BIST_MASK_CHANNEL_1_Q_DATA (1 << 3) /* BIST Mask Channel 1 Q data */ +#define BIST_MASK_CHANNEL_1_I_DATA (1 << 2) /* BIST Mask Channel 1 I data */ +#define DATA_PORT_HILOW (1 << 1) /* Data Port Hi/Low */ +#define USE_DATA_PORT (1 << 0) /* Use Data Port */ +#define TEMP_SENSE_VBE_TEST(x) (((x) & 0x3) << 6) /* Temp Sense Vbe Test<1:0> */ + +/* +* REG_DAC_TEST_2 +*/ +#define DAC_TEST_ENABLE (1 << 7) /* DAC Test Enable */ +#define DAC_TEST_WORD(x) (((x) & 0x7F) << 0) /* DAC test Word <22:16> */ + +/* +* SPI Comm Helpers +*/ +#define AD_READ (0 << 15) +#define AD_WRITE (1 << 15) +#define AD_CNT(x) ((((x) - 1) & 0x7) << 12) +#define AD_ADDR(x) ((x) & 0x3FF) + + +/* +* AD9361 Limits +*/ + +#define RSSI_MULTIPLIER 100 +#define RSSI_RESOLUTION ((int) (0.25 * RSSI_MULTIPLIER)) +#define RSSI_MAX_WEIGHT 255 + +#define MAX_LMT_INDEX 40 +#define MAX_LPF_GAIN 24 +#define MAX_DIG_GAIN 31 + +#define MAX_BBPLL_FREF 70007000UL /* 70 MHz + 100ppm */ +#define MIN_BBPLL_FREQ 714928500UL /* 715 MHz - 100ppm */ +#define MAX_BBPLL_FREQ 1430143000UL /* 1430 MHz + 100ppm */ +#define MAX_BBPLL_DIV 64 +#define MIN_BBPLL_DIV 2 + +/* + * The ADC minimum and maximum operating output data rates + * are 25MHz and 640MHz respectively. + * For more information see here: https://ez.analog.com/docs/DOC-12763 + */ + +#define MIN_ADC_CLK 25000000UL /* 25 MHz */ +//#define MIN_ADC_CLK (MIN_BBPLL_FREQ / MAX_BBPLL_DIV) /* 11.17MHz */ +#define MAX_ADC_CLK 640000000UL /* 640 MHz */ +#define MAX_DAC_CLK (MAX_ADC_CLK / 2) + +/* Associated with outputs of stage */ +#define MAX_RX_HB1 245760000UL +#define MAX_RX_HB2 320000000UL +#define MAX_RX_HB3 640000000UL +/* Associated with inputs of stage */ +#define MAX_TX_HB1 160000000UL +#define MAX_TX_HB2 320000000UL +#define MAX_TX_HB3 320000000UL + +#define MAX_BASEBAND_RATE 61440000UL + +#define MAX_MBYTE_SPI 8 + +#define RFPLL_MODULUS 8388593UL +#define BBPLL_MODULUS 2088960UL + +#define MAX_SYNTH_FREF 80008000UL /* 80 MHz + 100ppm */ +#define MIN_SYNTH_FREF 9999000UL /* 10 MHz - 100ppm */ +#define MIN_VCO_FREQ_HZ 6000000000ULL +#define MAX_CARRIER_FREQ_HZ 6000000000ULL +#define MIN_RX_CARRIER_FREQ_HZ 70000000ULL +#define MIN_TX_CARRIER_FREQ_HZ 46875001ULL + +#define AD9363A_MAX_CARRIER_FREQ_HZ 3800000000ULL +#define AD9363A_MIN_CARRIER_FREQ_HZ 325000000ULL + +#define MAX_TX_ATTENUATION_DB 89750 + +/* +* Driver +*/ + +enum rx_gain_table_type { + RXGAIN_FULL_TBL, + RXGAIN_SPLIT_TBL, +}; + +enum rx_gain_table_name { + TBL_200_1300_MHZ, + TBL_1300_4000_MHZ, + TBL_4000_6000_MHZ, + RXGAIN_TBLS_END, +}; + +struct gain_table_info { + uint64_t start; + uint64_t end; + uint8_t max_index; + uint8_t split_table; + int8_t *abs_gain_tbl; + uint8_t (*tab)[3]; +}; + +enum fir_dest { + FIR_TX1 = 0x01, + FIR_TX2 = 0x02, + FIR_TX1_TX2 = 0x03, + FIR_RX1 = 0x81, + FIR_RX2 = 0x82, + FIR_RX1_RX2 = 0x83, + FIR_IS_RX = 0x80, +}; + +struct rf_gain_ctrl { + uint32_t ant; + uint8_t mode; +}; + +enum rf_gain_ctrl_mode { + RF_GAIN_MGC, + RF_GAIN_FASTATTACK_AGC, + RF_GAIN_SLOWATTACK_AGC, + RF_GAIN_HYBRID_AGC +}; + +enum f_agc_target_gain_index_type { + MAX_GAIN, + SET_GAIN, + OPTIMIZED_GAIN, + NO_GAIN_CHANGE, +}; + +struct gain_control { + enum rf_gain_ctrl_mode rx1_mode; + enum rf_gain_ctrl_mode rx2_mode; + + /* Common */ + uint8_t adc_ovr_sample_size; /* 1..8 Sum x samples, AGC_CONFIG_3 */ + uint8_t adc_small_overload_thresh; /* 0..255, 0x105 */ + uint8_t adc_large_overload_thresh; /* 0..255, 0x104 */ + + uint16_t lmt_overload_high_thresh; /* 16..800 mV, 0x107 */ + uint16_t lmt_overload_low_thresh; /* 16..800 mV, 0x108 */ + uint16_t dec_pow_measuremnt_duration; /* Samples, 0x15C */ + uint8_t low_power_thresh; /* -64..0 dBFS, 0x114 */ + bool use_rx_fir_out_for_dec_pwr_meas; /* clears 0x15C:6 USE_HB1_OUT_FOR_DEC_PWR_MEAS */ + + bool dig_gain_en; /* should be turned off, since ADI GT doesn't use dig gain */ + uint8_t max_dig_gain; /* 0..31 */ + + /* MGC */ + bool mgc_rx1_ctrl_inp_en; /* Enables Pin control on RX1 default SPI ctrl */ + bool mgc_rx2_ctrl_inp_en; /* Enables Pin control on RX2 default SPI ctrl */ + + uint8_t mgc_inc_gain_step; /* 1..8 */ + uint8_t mgc_dec_gain_step; /* 1..8 */ + uint8_t mgc_split_table_ctrl_inp_gain_mode; /* 0=AGC determine this, 1=only in LPF, 2=only in LMT */ + + /* AGC */ + uint8_t agc_attack_delay_extra_margin_us; /* 0..31 us */ + + uint8_t agc_outer_thresh_high; + uint8_t agc_outer_thresh_high_dec_steps; + uint8_t agc_inner_thresh_high; + uint8_t agc_inner_thresh_high_dec_steps; + uint8_t agc_inner_thresh_low; + uint8_t agc_inner_thresh_low_inc_steps; + uint8_t agc_outer_thresh_low; + uint8_t agc_outer_thresh_low_inc_steps; + + uint8_t adc_small_overload_exceed_counter; /* 0..15, 0x122 */ + uint8_t adc_large_overload_exceed_counter; /* 0..15, 0x122 */ + uint8_t adc_large_overload_inc_steps; /* 0..15, 0x106 */ + + bool adc_lmt_small_overload_prevent_gain_inc; /* 0x120 */ + + uint8_t lmt_overload_large_exceed_counter; /* 0..15, 0x121 */ + uint8_t lmt_overload_small_exceed_counter; /* 0..15, 0x121 */ + uint8_t lmt_overload_large_inc_steps; /* 0..7, 0x121 */ + + uint8_t dig_saturation_exceed_counter; /* 0..15, 0x128 */ + uint8_t dig_gain_step_size; /* 1..8, 0x100 */ + bool sync_for_gain_counter_en; /* 0x128:4 !Hybrid */ + + uint32_t gain_update_interval_us; /* in us */ + bool immed_gain_change_if_large_adc_overload; /* 0x123:3 */ + bool immed_gain_change_if_large_lmt_overload; /* 0x123:7 */ + + /* + * Fast AGC + */ + uint32_t f_agc_dec_pow_measuremnt_duration; /* Samples, 0x15C */ + uint32_t f_agc_state_wait_time_ns; /* 0x117 0..31 RX samples -> time_ns */ + /* Fast AGC - Low Power */ + bool f_agc_allow_agc_gain_increase; /* 0x110:1 */ + uint8_t f_agc_lp_thresh_increment_time; /* 0x11B RX samples */ + uint8_t f_agc_lp_thresh_increment_steps; /* 0x117 1..8 */ + + /* Fast AGC - Lock Level */ + uint8_t f_agc_lock_level; /* NOT USED: 0x101 0..-127 dBFS same as agc_inner_thresh_high */ + bool f_agc_lock_level_lmt_gain_increase_en; /* 0x111:6 */ + uint8_t f_agc_lock_level_gain_increase_upper_limit; /* 0x118 0..63 */ + /* Fast AGC - Peak Detectors and Final Settling */ + uint8_t f_agc_lpf_final_settling_steps; /* 0x112:6 0..3 (Post Lock Level Step)*/ + uint8_t f_agc_lmt_final_settling_steps; /* 0x113:6 0..3 (Post Lock Level Step)*/ + uint8_t f_agc_final_overrange_count; /* 0x116:5 0..7 */ + /* Fast AGC - Final Power Test */ + bool f_agc_gain_increase_after_gain_lock_en; /* 0x110:7 */ + /* Fast AGC - Unlocking the Gain */ + /* 0 = MAX Gain, 1 = Set Gain, 2 = Optimized Gain */ + enum f_agc_target_gain_index_type + f_agc_gain_index_type_after_exit_rx_mode; /* 0x110:[4,2] */ + bool f_agc_use_last_lock_level_for_set_gain_en; /* 0x111:7 */ + uint8_t f_agc_optimized_gain_offset; /*0x116 0..15 steps */ + bool f_agc_rst_gla_stronger_sig_thresh_exceeded_en; /* 0x110:~6 */ + uint8_t f_agc_rst_gla_stronger_sig_thresh_above_ll; /*0x113 0..63 dbFS */ + bool f_agc_rst_gla_engergy_lost_sig_thresh_exceeded_en; /* 0x110:6 */ + bool f_agc_rst_gla_engergy_lost_goto_optim_gain_en; /* 0x110:6 */ + uint8_t f_agc_rst_gla_engergy_lost_sig_thresh_below_ll; /* 0x112:6 */ + uint8_t f_agc_energy_lost_stronger_sig_gain_lock_exit_cnt; /* 0x119 0..63 RX samples */ + bool f_agc_rst_gla_large_adc_overload_en; /*0x110:~1 and 0x114:~7 */ + bool f_agc_rst_gla_large_lmt_overload_en; /*0x110:~1 */ + bool f_agc_rst_gla_en_agc_pulled_high_en; + /* 0 = Max Gain, 1 = Set Gain, 2 = Optimized Gain, 3 = No Gain Change */ + + enum f_agc_target_gain_index_type + f_agc_rst_gla_if_en_agc_pulled_high_mode; /* 0x0FB, 0x111 */ + uint8_t f_agc_power_measurement_duration_in_state5; /* 0x109, 0x10a RX samples 0..524288*/ + uint8_t f_agc_large_overload_inc_steps; /* 0x106 [D6:D4] 0..7 */ +}; + +struct auxdac_control { + uint16_t dac1_default_value; + uint16_t dac2_default_value; + + bool auxdac_manual_mode_en; + + bool dac1_in_rx_en; + bool dac1_in_tx_en; + bool dac1_in_alert_en; + + bool dac2_in_rx_en; + bool dac2_in_tx_en; + bool dac2_in_alert_en; + + uint8_t dac1_rx_delay_us; + uint8_t dac1_tx_delay_us; + uint8_t dac2_rx_delay_us; + uint8_t dac2_tx_delay_us; +}; + +enum rssi_restart_mode { + AGC_IN_FAST_ATTACK_MODE_LOCKS_THE_GAIN, + EN_AGC_PIN_IS_PULLED_HIGH, + ENTERS_RX_MODE, + GAIN_CHANGE_OCCURS, + SPI_WRITE_TO_REGISTER, + GAIN_CHANGE_OCCURS_OR_EN_AGC_PIN_PULLED_HIGH, +}; + +struct rssi_control { + enum rssi_restart_mode restart_mode; + bool rssi_unit_is_rx_samples; /* default unit is time */ + uint32_t rssi_delay; + uint32_t rssi_wait; + uint32_t rssi_duration; +}; + +struct rx_gain_info { + enum rx_gain_table_type tbl_type; + int32_t starting_gain_db; + int32_t max_gain_db; + int32_t gain_step_db; + int32_t max_idx; + int32_t idx_step_offset; +}; + +struct port_control { + uint8_t pp_conf[3]; + uint8_t rx_clk_data_delay; + uint8_t tx_clk_data_delay; + uint8_t digital_io_ctrl; + uint8_t lvds_bias_ctrl; + uint8_t lvds_invert[2]; +}; + +struct ctrl_outs_control { + uint8_t index; + uint8_t en_mask; +}; + +struct elna_control { + uint16_t gain_mdB; + uint16_t bypass_loss_mdB; + uint32_t settling_delay_ns; + bool elna_1_control_en; /* GPO0 */ + bool elna_2_control_en; /* GPO1 */ + bool elna_in_gaintable_all_index_en; +}; + +struct auxadc_control { + int8_t offset; + uint32_t temp_time_inteval_ms; + uint32_t temp_sensor_decimation; + bool periodic_temp_measuremnt; + uint32_t auxadc_clock_rate; + uint32_t auxadc_decimation; +}; + +struct gpo_control { + uint32_t gpo_manual_mode_enable_mask; + bool gpo_manual_mode_en; + bool gpo0_inactive_state_high_en; + bool gpo1_inactive_state_high_en; + bool gpo2_inactive_state_high_en; + bool gpo3_inactive_state_high_en; + bool gpo0_slave_rx_en; + bool gpo0_slave_tx_en; + bool gpo1_slave_rx_en; + bool gpo1_slave_tx_en; + bool gpo2_slave_rx_en; + bool gpo2_slave_tx_en; + bool gpo3_slave_rx_en; + bool gpo3_slave_tx_en; + uint8_t gpo0_rx_delay_us; + uint8_t gpo0_tx_delay_us; + uint8_t gpo1_rx_delay_us; + uint8_t gpo1_tx_delay_us; + uint8_t gpo2_rx_delay_us; + uint8_t gpo2_tx_delay_us; + uint8_t gpo3_rx_delay_us; + uint8_t gpo3_tx_delay_us; +}; + +struct tx_monitor_control { + bool tx_mon_track_en; + bool one_shot_mode_en; + uint32_t low_high_gain_threshold_mdB; + uint8_t low_gain_dB; + uint8_t high_gain_dB; + uint16_t tx_mon_delay; + uint16_t tx_mon_duration; + uint8_t tx1_mon_front_end_gain; + uint8_t tx2_mon_front_end_gain; + uint8_t tx1_mon_lo_cm; + uint8_t tx2_mon_lo_cm; +}; + +enum ad9361_pdata_rx_freq { + BBPLL_FREQ, + ADC_FREQ, + R2_FREQ, + R1_FREQ, + CLKRF_FREQ, + RX_SAMPL_FREQ, + NUM_RX_CLOCKS, +}; + +enum ad9361_pdata_tx_freq { + IGNORE, + DAC_FREQ, + T2_FREQ, + T1_FREQ, + CLKTF_FREQ, + TX_SAMPL_FREQ, + NUM_TX_CLOCKS, +}; + +enum ad9361_clkout { + CLKOUT_DISABLE, + BUFFERED_XTALN_DCXO, + ADC_CLK_DIV_2, + ADC_CLK_DIV_3, + ADC_CLK_DIV_4, + ADC_CLK_DIV_8, + ADC_CLK_DIV_16, +}; + +struct ad9361_phy_platform_data { + bool rx2tx2; + bool fdd; + bool fdd_independent_mode; + bool split_gt; + bool use_extclk; + bool ensm_pin_pulse_mode; + bool ensm_pin_ctrl; + bool debug_mode; + bool tdd_use_dual_synth; + bool tdd_skip_vco_cal; + bool use_ext_rx_lo; + bool use_ext_tx_lo; + bool rx1rx2_phase_inversion_en; + bool qec_tracking_slow_mode_en; + uint8_t dc_offset_update_events; + uint8_t dc_offset_attenuation_high; + uint8_t dc_offset_attenuation_low; + uint8_t rf_dc_offset_count_high; + uint8_t rf_dc_offset_count_low; + uint8_t dig_interface_tune_skipmode; + uint8_t dig_interface_tune_fir_disable; + uint8_t lo_powerdown_managed_en; + uint32_t dcxo_coarse; + uint32_t dcxo_fine; + uint32_t rf_rx_input_sel; + uint32_t rf_tx_output_sel; + uint32_t rx1tx1_mode_use_rx_num; + uint32_t rx1tx1_mode_use_tx_num; + uint32_t rx_path_clks[NUM_RX_CLOCKS]; + uint32_t tx_path_clks[NUM_TX_CLOCKS]; + uint32_t trx_synth_max_fref; + uint64_t rx_synth_freq; + uint64_t tx_synth_freq; + uint32_t rf_rx_bandwidth_Hz; + uint32_t rf_tx_bandwidth_Hz; + int32_t tx_atten; + bool update_tx_gain_via_alert; + uint32_t rx_fastlock_delay_ns; + uint32_t tx_fastlock_delay_ns; + bool trx_fastlock_pinctrl_en[2]; + + enum ad9361_clkout ad9361_clkout_mode; + + struct gain_control gain_ctrl; + struct rssi_control rssi_ctrl; + struct port_control port_ctrl; + struct ctrl_outs_control ctrl_outs_ctrl; + struct elna_control elna_ctrl; + struct auxadc_control auxadc_ctrl; + struct auxdac_control auxdac_ctrl; + struct gpo_control gpo_ctrl; + struct tx_monitor_control txmon_ctrl; +}; + +struct rf_rx_gain { + uint32_t ant; /* Antenna number to read gain */ + int32_t gain_db; /* gain value in dB */ + uint32_t fgt_lmt_index; /* Full Gain Table / LNA-MIXER-TIA gain index */ + uint32_t lmt_gain; /* LNA-MIXER-TIA gain in dB (Split GT mode only)*/ + uint32_t lpf_gain; /* Low pass filter gain in dB / index (Split GT mode only)*/ + uint32_t digital_gain; /* Digital gain in dB / index */ + /* Debug only */ + uint32_t lna_index; /* LNA Index (Split GT mode only) */ + uint32_t tia_index; /* TIA Index (Split GT mode only) */ + uint32_t mixer_index; /* MIXER Index (Split GT mode only) */ + +}; +struct rf_rssi { + uint32_t ant; /* Antenna number for which RSSI is reported */ + uint32_t symbol; /* Runtime RSSI */ + uint32_t preamble; /* Initial RSSI */ + int32_t multiplier; /* Multiplier to convert reported RSSI */ + uint8_t duration; /* Duration to be considered for measuring */ +}; + +struct SynthLUT { + uint16_t VCO_MHz; + uint8_t VCO_Output_Level; + uint8_t VCO_Varactor; + uint8_t VCO_Bias_Ref; + uint8_t VCO_Bias_Tcf; + uint8_t VCO_Cal_Offset; + uint8_t VCO_Varactor_Reference; + uint8_t Charge_Pump_Current; + uint8_t LF_C2; + uint8_t LF_C1; + uint8_t LF_R1; + uint8_t LF_C3; + uint8_t LF_R3; +}; + +enum { + LUT_FTDD_40, + LUT_FTDD_60, + LUT_FTDD_80, + LUT_FTDD_ENT, +}; + +enum ad9361_clocks { + BB_REFCLK, + RX_REFCLK, + TX_REFCLK, + BBPLL_CLK, + ADC_CLK, + R2_CLK, + R1_CLK, + CLKRF_CLK, + RX_SAMPL_CLK, + DAC_CLK, + T2_CLK, + T1_CLK, + CLKTF_CLK, + TX_SAMPL_CLK, + RX_RFPLL_INT, + TX_RFPLL_INT, + RX_RFPLL_DUMMY, + TX_RFPLL_DUMMY, + RX_RFPLL, + TX_RFPLL, + NUM_AD9361_CLKS, + EXT_REF_CLK, +}; + +struct ad9361_debugfs_entry { + struct ad9361_rf_phy *phy; + const char *propname; + void *out_value; + uint32_t val; + uint8_t size; + uint8_t cmd; +}; + +struct ad9361_fastlock_entry { +#define FASTLOOK_INIT 1 + uint8_t flags; + uint8_t alc_orig; + uint8_t alc_written; +}; + +struct ad9361_fastlock { + uint8_t save_profile; + uint8_t current_profile[2]; + struct ad9361_fastlock_entry entry[2][8]; +}; + +enum dig_tune_flags { + BE_VERBOSE = 1, + BE_MOREVERBOSE = 2, + DO_IDELAY = 4, + DO_ODELAY = 8, + SKIP_STORE_RESULT = 16, + RESTORE_DEFAULT = 32, +}; + +enum ad9361_bist_mode { + BIST_DISABLE, + BIST_INJ_TX, + BIST_INJ_RX, +}; + +enum synth_pd_ctrl { + LO_DONTCARE, + LO_OFF, + LO_ON, +}; + +enum dev_id { + ID_AD9361, + ID_AD9364, + ID_AD9363A +}; + +struct ad9361_rf_phy { + enum dev_id dev_sel; + struct spi_desc *spi; + struct gpio_desc *gpio_desc_resetb; + struct gpio_desc *gpio_desc_sync; + struct gpio_desc *gpio_desc_cal_sw1; + struct gpio_desc *gpio_desc_cal_sw2; +#ifndef AXI_ADC_NOT_PRESENT + struct axi_adc *rx_adc; + struct axi_dac *tx_dac; +#endif + struct clk *clk_refin; + struct clk *clks[NUM_AD9361_CLKS]; + struct refclk_scale *ref_clk_scale[NUM_AD9361_CLKS]; + uint32_t (*ad9361_rfpll_ext_recalc_rate)(struct refclk_scale *clk_priv); + int32_t (*ad9361_rfpll_ext_round_rate)(struct refclk_scale *clk_priv, + uint32_t rate); + int32_t (*ad9361_rfpll_ext_set_rate)(struct refclk_scale *clk_priv, + uint32_t rate); + struct ad9361_phy_platform_data *pdata; + uint8_t prev_ensm_state; + uint8_t curr_ensm_state; + uint8_t cached_rx_rfpll_div; + uint8_t cached_tx_rfpll_div; + uint8_t cached_synth_pd[2]; + int32_t tx_quad_lpf_tia_match; + uint32_t current_table; + struct gain_table_info *gt_info; + bool ensm_pin_ctl_en; + + bool auto_cal_en; + bool manual_tx_quad_cal_en; + uint64_t last_tx_quad_cal_freq; + uint32_t last_tx_quad_cal_phase; + uint64_t current_tx_lo_freq; + uint64_t current_rx_lo_freq; + bool current_tx_use_tdd_table; + bool current_rx_use_tdd_table; + uint32_t current_rx_path_clks[NUM_RX_CLOCKS]; + uint32_t current_tx_path_clks[NUM_TX_CLOCKS]; + uint32_t flags; + uint32_t cal_threshold_freq; + uint32_t current_rx_bw_Hz; + uint32_t current_tx_bw_Hz; + uint32_t rxbbf_div; + uint32_t rate_governor; + bool bypass_rx_fir; + bool bypass_tx_fir; + bool rx_eq_2tx; + bool filt_valid; + uint32_t filt_rx_path_clks[NUM_RX_CLOCKS]; + uint32_t filt_tx_path_clks[NUM_TX_CLOCKS]; + uint32_t filt_rx_bw_Hz; + uint32_t filt_tx_bw_Hz; + uint8_t tx_fir_int; + uint8_t tx_fir_ntaps; + uint8_t rx_fir_dec; + uint8_t rx_fir_ntaps; + uint8_t agc_mode[2]; + bool rfdc_track_en; + bool bbdc_track_en; + bool quad_track_en; + bool txmon_tdd_en; + uint16_t auxdac1_value; + uint16_t auxdac2_value; + uint32_t tx1_atten_cached; + uint32_t tx2_atten_cached; + struct ad9361_fastlock fastlock; + struct axiadc_converter *adc_conv; + struct axiadc_state *adc_state; + int32_t bist_loopback_mode; + int32_t bist_config; + enum ad9361_bist_mode bist_prbs_mode; + enum ad9361_bist_mode bist_tone_mode; + uint32_t bist_tone_freq_Hz; + uint32_t bist_tone_level_dB; + uint32_t bist_tone_mask; + bool bbpll_initialized; +}; + +struct refclk_scale { + struct spi_desc *spi; + struct ad9361_rf_phy *phy; + uint32_t mult; + uint32_t div; + enum ad9361_clocks source; + enum ad9361_clocks parent_source; +}; + +enum debugfs_cmd { + DBGFS_NONE, + DBGFS_INIT, + DBGFS_LOOPBACK, + DBGFS_BIST_PRBS, + DBGFS_BIST_TONE, + DBGFS_BIST_DT_ANALYSIS, + DBGFS_RXGAIN_1, + DBGFS_RXGAIN_2, +}; + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ +int32_t ad9361_spi_readm(struct spi_desc *spi, uint32_t reg, + uint8_t *rbuf, uint32_t num); +int32_t ad9361_spi_read(struct spi_desc *spi, uint32_t reg); +int32_t ad9361_spi_write(struct spi_desc *spi, + uint32_t reg, uint32_t val); +int32_t ad9361_reset(struct ad9361_rf_phy *phy); +int32_t ad9361_register_clocks(struct ad9361_rf_phy *phy); +int32_t ad9361_unregister_clocks(struct ad9361_rf_phy *phy); +uint32_t ad9361_gt(struct ad9361_rf_phy *phy); +int32_t ad9361_init_gain_tables(struct ad9361_rf_phy *phy); +int32_t ad9361_setup(struct ad9361_rf_phy *phy); +int32_t ad9361_post_setup(struct ad9361_rf_phy *phy); +int32_t ad9361_set_ensm_mode(struct ad9361_rf_phy *phy, bool fdd, bool pinctrl); +int32_t ad9361_ensm_set_state(struct ad9361_rf_phy *phy, uint8_t ensm_state, + bool pinctrl); +int32_t ad9361_set_rx_gain(struct ad9361_rf_phy *phy, + uint32_t rx_id, struct rf_rx_gain *rx_gain); +int32_t ad9361_get_rx_gain(struct ad9361_rf_phy *phy, + uint32_t rx_id, struct rf_rx_gain *rx_gain); +int32_t ad9361_update_rf_bandwidth(struct ad9361_rf_phy *phy, + uint32_t rf_rx_bw, uint32_t rf_tx_bw); +int32_t ad9361_calculate_rf_clock_chain(struct ad9361_rf_phy *phy, + uint32_t tx_sample_rate, + uint32_t rate_gov, + uint32_t *rx_path_clks, + uint32_t *tx_path_clks); +int32_t ad9361_set_trx_clock_chain(struct ad9361_rf_phy *phy, + uint32_t *rx_path_clks, + uint32_t *tx_path_clks); +int32_t ad9361_get_trx_clock_chain(struct ad9361_rf_phy *phy, + uint32_t *rx_path_clks, + uint32_t *tx_path_clks); +uint32_t ad9361_to_clk(uint64_t freq); +uint64_t ad9361_from_clk(uint32_t freq); +int32_t ad9361_read_rssi(struct ad9361_rf_phy *phy, struct rf_rssi *rssi); +int32_t ad9361_set_gain_ctrl_mode(struct ad9361_rf_phy *phy, + struct rf_gain_ctrl *gain_ctrl); +int32_t ad9361_load_fir_filter_coef(struct ad9361_rf_phy *phy, + enum fir_dest dest, int32_t gain_dB, + uint32_t ntaps, short *coef); +int32_t ad9361_validate_enable_fir(struct ad9361_rf_phy *phy); +int32_t ad9361_set_tx_atten(struct ad9361_rf_phy *phy, uint32_t atten_mdb, + bool tx1, bool tx2, bool immed); +int32_t ad9361_get_tx_atten(struct ad9361_rf_phy *phy, uint32_t tx_num); +uint32_t ad9361_clk_factor_recalc_rate(struct refclk_scale *clk_priv, + uint32_t parent_rate); +int32_t ad9361_clk_factor_round_rate(struct refclk_scale *clk_priv, + uint32_t rate, + uint32_t *prate); +int32_t ad9361_clk_factor_set_rate(struct refclk_scale *clk_priv, uint32_t rate, + uint32_t parent_rate); +uint32_t ad9361_bbpll_recalc_rate(struct refclk_scale *clk_priv, + uint32_t parent_rate); +int32_t ad9361_bbpll_round_rate(struct refclk_scale *clk_priv, uint32_t rate, + uint32_t *prate); +int32_t ad9361_bbpll_set_rate(struct refclk_scale *clk_priv, uint32_t rate, + uint32_t parent_rate); +uint32_t ad9361_rfpll_int_recalc_rate(struct refclk_scale *clk_priv, + uint32_t parent_rate); +int32_t ad9361_rfpll_int_round_rate(struct refclk_scale *clk_priv, + uint32_t rate, + uint32_t *prate); +int32_t ad9361_rfpll_int_set_rate(struct refclk_scale *clk_priv, uint32_t rate, + uint32_t parent_rate); +uint32_t ad9361_rfpll_dummy_recalc_rate(struct refclk_scale *clk_priv); +int32_t ad9361_rfpll_dummy_set_rate(struct refclk_scale *clk_priv, + uint32_t rate); +uint32_t ad9361_rfpll_recalc_rate(struct refclk_scale *clk_priv); +int32_t ad9361_rfpll_round_rate(struct refclk_scale *clk_priv, uint32_t rate); +int32_t ad9361_rfpll_set_rate(struct refclk_scale *clk_priv, uint32_t rate); +int32_t ad9361_clk_mux_set_parent(struct refclk_scale *clk_priv, uint8_t index); +int32_t ad9361_tracking_control(struct ad9361_rf_phy *phy, bool bbdc_track, + bool rfdc_track, bool rxquad_track); +int32_t ad9361_bist_loopback(struct ad9361_rf_phy *phy, int32_t mode); +void ad9361_get_bist_loopback(struct ad9361_rf_phy *phy, int32_t *mode); +int32_t ad9361_bist_prbs(struct ad9361_rf_phy *phy, enum ad9361_bist_mode mode); +void ad9361_get_bist_prbs(struct ad9361_rf_phy *phy, + enum ad9361_bist_mode *mode); +int32_t ad9361_bist_tone(struct ad9361_rf_phy *phy, + enum ad9361_bist_mode mode, uint32_t freq_Hz, + uint32_t level_dB, uint32_t mask); +void ad9361_get_bist_tone(struct ad9361_rf_phy *phy, + enum ad9361_bist_mode *mode, uint32_t *freq_Hz, + uint32_t *level_dB, uint32_t *mask); +int32_t ad9361_rf_port_setup(struct ad9361_rf_phy *phy, bool is_out, + uint32_t rx_inputs, uint32_t txb); +int32_t ad9361_mcs(struct ad9361_rf_phy *phy, int32_t step); +int32_t ad9361_do_calib_run(struct ad9361_rf_phy *phy, uint32_t cal, + int32_t arg); +int32_t ad9361_fastlock_store(struct ad9361_rf_phy *phy, bool tx, + uint32_t profile); +int32_t ad9361_fastlock_recall(struct ad9361_rf_phy *phy, bool tx, + uint32_t profile); +int32_t ad9361_fastlock_load(struct ad9361_rf_phy *phy, bool tx, + uint32_t profile, uint8_t *values); +int32_t ad9361_fastlock_save(struct ad9361_rf_phy *phy, bool tx, + uint32_t profile, uint8_t *values); +void ad9361_ensm_force_state(struct ad9361_rf_phy *phy, uint8_t ensm_state); +uint8_t ad9361_ensm_get_state(struct ad9361_rf_phy *phy); +void ad9361_ensm_restore_state(struct ad9361_rf_phy *phy, uint8_t ensm_state); +void ad9361_ensm_restore_prev_state(struct ad9361_rf_phy *phy); +int32_t ad9361_set_trx_clock_chain_freq(struct ad9361_rf_phy *phy, + uint32_t freq); +int32_t ad9361_find_opt(uint8_t *field, uint32_t size, uint32_t *ret_start); +int32_t ad9361_hdl_loopback(struct ad9361_rf_phy *phy, bool enable); +int32_t ad9361_dig_interface_timing_analysis(struct ad9361_rf_phy *phy, + char *buf, int32_t buflen); +int32_t ad9361_dig_tune(struct ad9361_rf_phy *phy, uint32_t max_freq, + enum dig_tune_flags flags); +int32_t ad9361_en_dis_tx(struct ad9361_rf_phy *phy, uint32_t tx_if, + uint32_t enable); +int32_t ad9361_en_dis_rx(struct ad9361_rf_phy *phy, uint32_t rx_if, + uint32_t enable); +int32_t ad9361_1rx1tx_channel_map(struct ad9361_rf_phy *phy, bool tx, + int32_t channel); +int32_t ad9361_rssi_gain_step_calib(struct ad9361_rf_phy *phy); +int32_t ad9361_set_dcxo_tune(struct ad9361_rf_phy *phy, + uint32_t coarse, uint32_t fine); +int32_t ad9361_tx_mute(struct ad9361_rf_phy *phy, uint32_t state); +uint32_t ad9361_validate_rf_bw(struct ad9361_rf_phy *phy, uint32_t bw); +int32_t ad9361_get_temp(struct ad9361_rf_phy *phy); +int ad9361_synth_lo_powerdown(struct ad9361_rf_phy *phy, + enum synth_pd_ctrl rx, + enum synth_pd_ctrl tx); +void ad9361_clear_state(struct ad9361_rf_phy *phy); +#endif diff --git a/df_datalink/src/drivers/rf-transceiver/ad9361/ad9361_api.c b/df_datalink/src/drivers/rf-transceiver/ad9361/ad9361_api.c new file mode 100644 index 0000000..12fc513 --- /dev/null +++ b/df_datalink/src/drivers/rf-transceiver/ad9361/ad9361_api.c @@ -0,0 +1,2157 @@ +/***************************************************************************//** + * @file ad9361_api.c + * @brief Implementation of AD9361 API Driver. + * @author DBogdan (dragos.bogdan@analog.com) +******************************************************************************** + * Copyright 2013(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include +#include "ad9361.h" +#include "ad9361_api.h" +#include "delay.h" +#include "spi.h" +#include "util.h" +#include "../../../config/app_config.h" + +/******************************************************************************/ +/************************ Constants Definitions *******************************/ +/******************************************************************************/ + +extern struct gain_table_info ad9361_adi_gt_info[]; + +/** + * Initialize the AD9361 part. + * @param ad9361_phy The AD9361 device structure. + * @param init_param The structure that contains the AD9361 initial parameters. + * @return 0 in case of success, negative error code otherwise. + * + * Note: This function will/may affect the data path. + */ +int32_t ad9361_init (struct ad9361_rf_phy **ad9361_phy, + AD9361_InitParam *init_param) +{ + struct ad9361_rf_phy *phy; + int32_t ret = 0; + int32_t rev = 0; + int32_t i = 0; + + phy = (struct ad9361_rf_phy *)zmalloc(sizeof(*phy)); + if (!phy) { + return -ENOMEM; + } + + phy->clk_refin = (struct clk *)zmalloc(sizeof(*phy->clk_refin)); + if (!phy->clk_refin) { + return -ENOMEM; + } + + phy->pdata = (struct ad9361_phy_platform_data *)zmalloc(sizeof(*phy->pdata)); + if (!phy->pdata) { + return -ENOMEM; + } + + /* Device selection */ + phy->dev_sel = init_param->dev_sel; + + /* Reference Clock */ + phy->clk_refin->rate = init_param->reference_clk_rate; + + /* Base Configuration */ + phy->pdata->fdd = init_param->frequency_division_duplex_mode_enable; + phy->pdata->fdd_independent_mode = + init_param->frequency_division_duplex_independent_mode_enable; + phy->pdata->rx2tx2 = init_param->two_rx_two_tx_mode_enable; + phy->pdata->rx1tx1_mode_use_rx_num = init_param->one_rx_one_tx_mode_use_rx_num; + phy->pdata->rx1tx1_mode_use_tx_num = init_param->one_rx_one_tx_mode_use_tx_num; + phy->pdata->tdd_use_dual_synth = init_param->tdd_use_dual_synth_mode_enable; + phy->pdata->tdd_skip_vco_cal = init_param->tdd_skip_vco_cal_enable; + phy->pdata->rx_fastlock_delay_ns = init_param->rx_fastlock_delay_ns; + phy->pdata->tx_fastlock_delay_ns = init_param->tx_fastlock_delay_ns; + phy->pdata->trx_fastlock_pinctrl_en[0] = + init_param->rx_fastlock_pincontrol_enable; + phy->pdata->trx_fastlock_pinctrl_en[1] = + init_param->tx_fastlock_pincontrol_enable; + if (phy->dev_sel == ID_AD9363A) { + phy->pdata->use_ext_rx_lo = false; + phy->pdata->use_ext_tx_lo = false; + } else { + phy->pdata->use_ext_rx_lo = init_param->external_rx_lo_enable; + phy->pdata->use_ext_tx_lo = init_param->external_tx_lo_enable; + } + phy->pdata->dc_offset_update_events = + init_param->dc_offset_tracking_update_event_mask; + phy->pdata->dc_offset_attenuation_high = + init_param->dc_offset_attenuation_high_range; + phy->pdata->dc_offset_attenuation_low = + init_param->dc_offset_attenuation_low_range; + phy->pdata->rf_dc_offset_count_high = init_param->dc_offset_count_high_range; + phy->pdata->rf_dc_offset_count_low = init_param->dc_offset_count_low_range; + phy->pdata->split_gt = init_param->split_gain_table_mode_enable; + phy->pdata->trx_synth_max_fref = + init_param->trx_synthesizer_target_fref_overwrite_hz; + phy->pdata->qec_tracking_slow_mode_en = + init_param->qec_tracking_slow_mode_enable; + + /* ENSM Control */ + phy->pdata->ensm_pin_pulse_mode = init_param->ensm_enable_pin_pulse_mode_enable; + phy->pdata->ensm_pin_ctrl = init_param->ensm_enable_txnrx_control_enable; + + /* LO Control */ + phy->pdata->rx_synth_freq = init_param->rx_synthesizer_frequency_hz; + phy->pdata->tx_synth_freq = init_param->tx_synthesizer_frequency_hz; + phy->pdata->lo_powerdown_managed_en = + init_param->tx_lo_powerdown_managed_enable; + + /* Rate & BW Control */ + for(i = 0; i < 6; i++) { + phy->pdata->rx_path_clks[i] = init_param->rx_path_clock_frequencies[i]; + } + for(i = 0; i < 6; i++) { + phy->pdata->tx_path_clks[i] = init_param->tx_path_clock_frequencies[i]; + } + phy->pdata->rf_rx_bandwidth_Hz = init_param->rf_rx_bandwidth_hz; + phy->pdata->rf_tx_bandwidth_Hz = init_param->rf_tx_bandwidth_hz; + + /* RF Port Control */ + phy->pdata->rf_rx_input_sel = init_param->rx_rf_port_input_select; + phy->pdata->rf_tx_output_sel = init_param->tx_rf_port_input_select; + + /* TX Attenuation Control */ + phy->pdata->tx_atten = init_param->tx_attenuation_mdB; + phy->pdata->update_tx_gain_via_alert = + init_param->update_tx_gain_in_alert_enable; + + /* Reference Clock Control */ + switch (phy->dev_sel) { + case ID_AD9363A: + phy->pdata->use_extclk = true; + break; + default: + phy->pdata->use_extclk = init_param->xo_disable_use_ext_refclk_enable; + } + phy->pdata->dcxo_coarse = init_param->dcxo_coarse_and_fine_tune[0]; + phy->pdata->dcxo_fine = init_param->dcxo_coarse_and_fine_tune[1]; + phy->pdata->ad9361_clkout_mode = (enum ad9361_clkout) + init_param->clk_output_mode_select; + + /* Gain Control */ + phy->pdata->gain_ctrl.rx1_mode = (enum rf_gain_ctrl_mode) + init_param->gc_rx1_mode; + phy->pdata->gain_ctrl.rx2_mode = (enum rf_gain_ctrl_mode) + init_param->gc_rx2_mode; + phy->pdata->gain_ctrl.adc_large_overload_thresh = + init_param->gc_adc_large_overload_thresh; + phy->pdata->gain_ctrl.adc_ovr_sample_size = init_param->gc_adc_ovr_sample_size; + phy->pdata->gain_ctrl.adc_small_overload_thresh = + init_param->gc_adc_small_overload_thresh; + phy->pdata->gain_ctrl.dec_pow_measuremnt_duration = + init_param->gc_dec_pow_measurement_duration; + phy->pdata->gain_ctrl.dig_gain_en = init_param->gc_dig_gain_enable; + phy->pdata->gain_ctrl.lmt_overload_high_thresh = + init_param->gc_lmt_overload_high_thresh; + phy->pdata->gain_ctrl.lmt_overload_low_thresh = + init_param->gc_lmt_overload_low_thresh; + phy->pdata->gain_ctrl.low_power_thresh = init_param->gc_low_power_thresh; + phy->pdata->gain_ctrl.max_dig_gain = init_param->gc_max_dig_gain; + phy->pdata->gain_ctrl.use_rx_fir_out_for_dec_pwr_meas = + init_param->gc_use_rx_fir_out_for_dec_pwr_meas_enable; + + /* Gain MGC Control */ + phy->pdata->gain_ctrl.mgc_dec_gain_step = init_param->mgc_dec_gain_step; + phy->pdata->gain_ctrl.mgc_inc_gain_step = init_param->mgc_inc_gain_step; + phy->pdata->gain_ctrl.mgc_rx1_ctrl_inp_en = init_param->mgc_rx1_ctrl_inp_enable; + phy->pdata->gain_ctrl.mgc_rx2_ctrl_inp_en = init_param->mgc_rx2_ctrl_inp_enable; + phy->pdata->gain_ctrl.mgc_split_table_ctrl_inp_gain_mode = + init_param->mgc_split_table_ctrl_inp_gain_mode; + + /* Gain AGC Control */ + phy->pdata->gain_ctrl.adc_large_overload_exceed_counter = + init_param->agc_adc_large_overload_exceed_counter; + phy->pdata->gain_ctrl.adc_large_overload_inc_steps = + init_param->agc_adc_large_overload_inc_steps; + phy->pdata->gain_ctrl.adc_lmt_small_overload_prevent_gain_inc = + init_param->agc_adc_lmt_small_overload_prevent_gain_inc_enable; + phy->pdata->gain_ctrl.adc_small_overload_exceed_counter = + init_param->agc_adc_small_overload_exceed_counter; + phy->pdata->gain_ctrl.dig_gain_step_size = init_param->agc_dig_gain_step_size; + phy->pdata->gain_ctrl.dig_saturation_exceed_counter = + init_param->agc_dig_saturation_exceed_counter; + phy->pdata->gain_ctrl.gain_update_interval_us = + init_param->agc_gain_update_interval_us; + phy->pdata->gain_ctrl.immed_gain_change_if_large_adc_overload = + init_param->agc_immed_gain_change_if_large_adc_overload_enable; + phy->pdata->gain_ctrl.immed_gain_change_if_large_lmt_overload = + init_param->agc_immed_gain_change_if_large_lmt_overload_enable; + phy->pdata->gain_ctrl.agc_inner_thresh_high = init_param->agc_inner_thresh_high; + phy->pdata->gain_ctrl.agc_inner_thresh_high_dec_steps = + init_param->agc_inner_thresh_high_dec_steps; + phy->pdata->gain_ctrl.agc_inner_thresh_low = init_param->agc_inner_thresh_low; + phy->pdata->gain_ctrl.agc_inner_thresh_low_inc_steps = + init_param->agc_inner_thresh_low_inc_steps; + phy->pdata->gain_ctrl.lmt_overload_large_exceed_counter = + init_param->agc_lmt_overload_large_exceed_counter; + phy->pdata->gain_ctrl.lmt_overload_large_inc_steps = + init_param->agc_lmt_overload_large_inc_steps; + phy->pdata->gain_ctrl.lmt_overload_small_exceed_counter = + init_param->agc_lmt_overload_small_exceed_counter; + phy->pdata->gain_ctrl.agc_outer_thresh_high = init_param->agc_outer_thresh_high; + phy->pdata->gain_ctrl.agc_outer_thresh_high_dec_steps = + init_param->agc_outer_thresh_high_dec_steps; + phy->pdata->gain_ctrl.agc_outer_thresh_low = init_param->agc_outer_thresh_low; + phy->pdata->gain_ctrl.agc_outer_thresh_low_inc_steps = + init_param->agc_outer_thresh_low_inc_steps; + phy->pdata->gain_ctrl.agc_attack_delay_extra_margin_us = + init_param->agc_attack_delay_extra_margin_us; + phy->pdata->gain_ctrl.sync_for_gain_counter_en = + init_param->agc_sync_for_gain_counter_enable; + + /* Fast AGC */ + phy->pdata->gain_ctrl.f_agc_dec_pow_measuremnt_duration = + init_param->fagc_dec_pow_measuremnt_duration; + phy->pdata->gain_ctrl.f_agc_state_wait_time_ns = + init_param->fagc_state_wait_time_ns; + /* Fast AGC - Low Power */ + phy->pdata->gain_ctrl.f_agc_allow_agc_gain_increase = + init_param->fagc_allow_agc_gain_increase; + phy->pdata->gain_ctrl.f_agc_lp_thresh_increment_time = + init_param->fagc_lp_thresh_increment_time; + phy->pdata->gain_ctrl.f_agc_lp_thresh_increment_steps = + init_param->fagc_lp_thresh_increment_steps; + /* Fast AGC - Lock Level (Lock Level is set via slow AGC inner high threshold) */ + phy->pdata->gain_ctrl.f_agc_lock_level_lmt_gain_increase_en = + init_param->fagc_lock_level_lmt_gain_increase_en; + phy->pdata->gain_ctrl.f_agc_lock_level_gain_increase_upper_limit = + init_param->fagc_lock_level_gain_increase_upper_limit; + /* Fast AGC - Peak Detectors and Final Settling */ + phy->pdata->gain_ctrl.f_agc_lpf_final_settling_steps = + init_param->fagc_lpf_final_settling_steps; + phy->pdata->gain_ctrl.f_agc_lmt_final_settling_steps = + init_param->fagc_lmt_final_settling_steps; + phy->pdata->gain_ctrl.f_agc_final_overrange_count = + init_param->fagc_final_overrange_count; + /* Fast AGC - Final Power Test */ + phy->pdata->gain_ctrl.f_agc_gain_increase_after_gain_lock_en = + init_param->fagc_gain_increase_after_gain_lock_en; + /* Fast AGC - Unlocking the Gain */ + phy->pdata->gain_ctrl.f_agc_gain_index_type_after_exit_rx_mode = + (enum f_agc_target_gain_index_type) + init_param->fagc_gain_index_type_after_exit_rx_mode; + phy->pdata->gain_ctrl.f_agc_use_last_lock_level_for_set_gain_en = + init_param->fagc_use_last_lock_level_for_set_gain_en; + phy->pdata->gain_ctrl.f_agc_rst_gla_stronger_sig_thresh_exceeded_en = + init_param->fagc_rst_gla_stronger_sig_thresh_exceeded_en; + phy->pdata->gain_ctrl.f_agc_optimized_gain_offset = + init_param->fagc_optimized_gain_offset; + phy->pdata->gain_ctrl.f_agc_rst_gla_stronger_sig_thresh_above_ll = + init_param->fagc_rst_gla_stronger_sig_thresh_above_ll; + phy->pdata->gain_ctrl.f_agc_rst_gla_engergy_lost_sig_thresh_exceeded_en = + init_param->fagc_rst_gla_engergy_lost_sig_thresh_exceeded_en; + phy->pdata->gain_ctrl.f_agc_rst_gla_engergy_lost_goto_optim_gain_en = + init_param->fagc_rst_gla_engergy_lost_goto_optim_gain_en; + phy->pdata->gain_ctrl.f_agc_rst_gla_engergy_lost_sig_thresh_below_ll = + init_param->fagc_rst_gla_engergy_lost_sig_thresh_below_ll; + phy->pdata->gain_ctrl.f_agc_energy_lost_stronger_sig_gain_lock_exit_cnt = + init_param->fagc_energy_lost_stronger_sig_gain_lock_exit_cnt; + phy->pdata->gain_ctrl.f_agc_rst_gla_large_adc_overload_en = + init_param->fagc_rst_gla_large_adc_overload_en; + phy->pdata->gain_ctrl.f_agc_rst_gla_large_lmt_overload_en = + init_param->fagc_rst_gla_large_lmt_overload_en; + phy->pdata->gain_ctrl.f_agc_rst_gla_en_agc_pulled_high_en = + init_param->fagc_rst_gla_en_agc_pulled_high_en; + phy->pdata->gain_ctrl.f_agc_rst_gla_if_en_agc_pulled_high_mode = + (enum f_agc_target_gain_index_type) + init_param->fagc_rst_gla_if_en_agc_pulled_high_mode; + phy->pdata->gain_ctrl.f_agc_power_measurement_duration_in_state5 = + init_param->fagc_power_measurement_duration_in_state5; + phy->pdata->gain_ctrl.f_agc_large_overload_inc_steps = + init_param->fagc_large_overload_inc_steps; + + /* RSSI Control */ + phy->pdata->rssi_ctrl.rssi_delay = init_param->rssi_delay; + phy->pdata->rssi_ctrl.rssi_duration = init_param->rssi_duration; + phy->pdata->rssi_ctrl.restart_mode = (enum rssi_restart_mode) + init_param->rssi_restart_mode; + phy->pdata->rssi_ctrl.rssi_unit_is_rx_samples = + init_param->rssi_unit_is_rx_samples_enable; + phy->pdata->rssi_ctrl.rssi_wait = init_param->rssi_wait; + + /* Aux ADC Control */ + phy->pdata->auxadc_ctrl.auxadc_decimation = init_param->aux_adc_decimation; + phy->pdata->auxadc_ctrl.auxadc_clock_rate = init_param->aux_adc_rate; + + /* AuxDAC Control */ + phy->pdata->auxdac_ctrl.auxdac_manual_mode_en = + init_param->aux_dac_manual_mode_enable; + phy->pdata->auxdac_ctrl.dac1_default_value = + init_param->aux_dac1_default_value_mV; + phy->pdata->auxdac_ctrl.dac1_in_rx_en = + init_param->aux_dac1_active_in_rx_enable; + phy->pdata->auxdac_ctrl.dac1_in_tx_en = + init_param->aux_dac1_active_in_tx_enable; + phy->pdata->auxdac_ctrl.dac1_in_alert_en = + init_param->aux_dac1_active_in_alert_enable; + phy->pdata->auxdac_ctrl.dac1_rx_delay_us = init_param->aux_dac1_rx_delay_us; + phy->pdata->auxdac_ctrl.dac1_tx_delay_us = init_param->aux_dac1_tx_delay_us; + phy->pdata->auxdac_ctrl.dac2_default_value = + init_param->aux_dac2_default_value_mV; + phy->pdata->auxdac_ctrl.dac2_in_rx_en = + init_param->aux_dac2_active_in_rx_enable; + phy->pdata->auxdac_ctrl.dac2_in_tx_en = + init_param->aux_dac2_active_in_tx_enable; + phy->pdata->auxdac_ctrl.dac2_in_alert_en = + init_param->aux_dac2_active_in_alert_enable; + phy->pdata->auxdac_ctrl.dac2_rx_delay_us = init_param->aux_dac2_rx_delay_us; + phy->pdata->auxdac_ctrl.dac2_tx_delay_us = init_param->aux_dac2_tx_delay_us; + + /* Temperature Sensor Control */ + phy->pdata->auxadc_ctrl.temp_sensor_decimation = + init_param->temp_sense_decimation; + phy->pdata->auxadc_ctrl.temp_time_inteval_ms = + init_param->temp_sense_measurement_interval_ms; + phy->pdata->auxadc_ctrl.offset = init_param->temp_sense_offset_signed; + phy->pdata->auxadc_ctrl.periodic_temp_measuremnt = + init_param->temp_sense_periodic_measurement_enable; + + /* Control Out Setup */ + phy->pdata->ctrl_outs_ctrl.en_mask = init_param->ctrl_outs_enable_mask; + phy->pdata->ctrl_outs_ctrl.index = init_param->ctrl_outs_index; + + /* External LNA Control */ + phy->pdata->elna_ctrl.settling_delay_ns = init_param->elna_settling_delay_ns; + phy->pdata->elna_ctrl.gain_mdB = init_param->elna_gain_mdB; + phy->pdata->elna_ctrl.bypass_loss_mdB = init_param->elna_bypass_loss_mdB; + phy->pdata->elna_ctrl.elna_1_control_en = + init_param->elna_rx1_gpo0_control_enable; + phy->pdata->elna_ctrl.elna_2_control_en = + init_param->elna_rx2_gpo1_control_enable; + phy->pdata->elna_ctrl.elna_in_gaintable_all_index_en = + init_param->elna_gaintable_all_index_enable; + + /* Digital Interface Control */ + phy->pdata->dig_interface_tune_skipmode = + (init_param->digital_interface_tune_skip_mode); + phy->pdata->dig_interface_tune_fir_disable = + (init_param->digital_interface_tune_fir_disable); + phy->pdata->port_ctrl.pp_conf[0] = (init_param->pp_tx_swap_enable << 7); + phy->pdata->port_ctrl.pp_conf[0] |= (init_param->pp_rx_swap_enable << 6); + phy->pdata->port_ctrl.pp_conf[0] |= (init_param->tx_channel_swap_enable << 5); + phy->pdata->port_ctrl.pp_conf[0] |= (init_param->rx_channel_swap_enable << 4); + phy->pdata->port_ctrl.pp_conf[0] |= (init_param->rx_frame_pulse_mode_enable << + 3); + phy->pdata->port_ctrl.pp_conf[0] |= (init_param->two_t_two_r_timing_enable << + 2); + phy->pdata->port_ctrl.pp_conf[0] |= (init_param->invert_data_bus_enable << 1); + phy->pdata->port_ctrl.pp_conf[0] |= (init_param->invert_data_clk_enable << 0); + phy->pdata->port_ctrl.pp_conf[1] = (init_param->fdd_alt_word_order_enable << 7); + phy->pdata->port_ctrl.pp_conf[1] |= (init_param->invert_rx_frame_enable << 2); + phy->pdata->port_ctrl.pp_conf[2] = (init_param->fdd_rx_rate_2tx_enable << 7); + phy->pdata->port_ctrl.pp_conf[2] |= (init_param->swap_ports_enable << 6); + phy->pdata->port_ctrl.pp_conf[2] |= (init_param->single_data_rate_enable << 5); + phy->pdata->port_ctrl.pp_conf[2] |= (init_param->lvds_mode_enable << 4); + phy->pdata->port_ctrl.pp_conf[2] |= (init_param->half_duplex_mode_enable << 3); + phy->pdata->port_ctrl.pp_conf[2] |= (init_param->single_port_mode_enable << 2); + phy->pdata->port_ctrl.pp_conf[2] |= (init_param->full_port_enable << 1); + phy->pdata->port_ctrl.pp_conf[2] |= (init_param->full_duplex_swap_bits_enable << + 0); + phy->pdata->port_ctrl.pp_conf[1] |= (init_param->delay_rx_data & 0x3); + phy->pdata->port_ctrl.rx_clk_data_delay = DATA_CLK_DELAY( + init_param->rx_data_clock_delay); + phy->pdata->port_ctrl.rx_clk_data_delay |= RX_DATA_DELAY( + init_param->rx_data_delay); + phy->pdata->port_ctrl.tx_clk_data_delay = FB_CLK_DELAY( + init_param->tx_fb_clock_delay); + phy->pdata->port_ctrl.tx_clk_data_delay |= TX_DATA_DELAY( + init_param->tx_data_delay); + phy->pdata->port_ctrl.lvds_bias_ctrl = ((init_param->lvds_bias_mV - 75) / 75) & + 0x7; + phy->pdata->port_ctrl.lvds_bias_ctrl |= + (init_param->lvds_rx_onchip_termination_enable << 5); + phy->pdata->rx1rx2_phase_inversion_en = init_param->rx1rx2_phase_inversion_en; + + /* GPO Control */ + phy->pdata->gpo_ctrl.gpo_manual_mode_en = + init_param->gpo_manual_mode_enable; + phy->pdata->gpo_ctrl.gpo_manual_mode_enable_mask = + init_param->gpo_manual_mode_enable_mask; + phy->pdata->gpo_ctrl.gpo0_inactive_state_high_en = + init_param->gpo0_inactive_state_high_enable; + phy->pdata->gpo_ctrl.gpo1_inactive_state_high_en = + init_param->gpo1_inactive_state_high_enable; + phy->pdata->gpo_ctrl.gpo2_inactive_state_high_en = + init_param->gpo2_inactive_state_high_enable; + phy->pdata->gpo_ctrl.gpo3_inactive_state_high_en = + init_param->gpo3_inactive_state_high_enable; + + phy->pdata->gpo_ctrl.gpo0_slave_rx_en = init_param->gpo0_slave_rx_enable; + phy->pdata->gpo_ctrl.gpo0_slave_tx_en = init_param->gpo0_slave_tx_enable; + phy->pdata->gpo_ctrl.gpo1_slave_rx_en = init_param->gpo1_slave_rx_enable; + phy->pdata->gpo_ctrl.gpo1_slave_tx_en = init_param->gpo1_slave_tx_enable; + phy->pdata->gpo_ctrl.gpo2_slave_rx_en = init_param->gpo2_slave_rx_enable; + phy->pdata->gpo_ctrl.gpo2_slave_tx_en = init_param->gpo2_slave_tx_enable; + phy->pdata->gpo_ctrl.gpo3_slave_rx_en = init_param->gpo3_slave_rx_enable; + phy->pdata->gpo_ctrl.gpo3_slave_tx_en = init_param->gpo3_slave_tx_enable; + + phy->pdata->gpo_ctrl.gpo0_rx_delay_us = init_param->gpo0_rx_delay_us; + phy->pdata->gpo_ctrl.gpo0_tx_delay_us = init_param->gpo0_tx_delay_us; + phy->pdata->gpo_ctrl.gpo1_rx_delay_us = init_param->gpo1_rx_delay_us; + phy->pdata->gpo_ctrl.gpo1_tx_delay_us = init_param->gpo1_tx_delay_us; + phy->pdata->gpo_ctrl.gpo2_rx_delay_us = init_param->gpo2_rx_delay_us; + phy->pdata->gpo_ctrl.gpo2_tx_delay_us = init_param->gpo2_tx_delay_us; + phy->pdata->gpo_ctrl.gpo3_rx_delay_us = init_param->gpo3_rx_delay_us; + phy->pdata->gpo_ctrl.gpo3_tx_delay_us = init_param->gpo3_tx_delay_us; + + /* Tx Monitor Control */ + phy->pdata->txmon_ctrl.low_high_gain_threshold_mdB = + init_param->low_high_gain_threshold_mdB; + phy->pdata->txmon_ctrl.low_gain_dB = init_param->low_gain_dB; + phy->pdata->txmon_ctrl.high_gain_dB = init_param->high_gain_dB; + phy->pdata->txmon_ctrl.tx_mon_track_en = init_param->tx_mon_track_en; + phy->pdata->txmon_ctrl.one_shot_mode_en = init_param->one_shot_mode_en; + phy->pdata->txmon_ctrl.tx_mon_delay = init_param->tx_mon_delay; + phy->pdata->txmon_ctrl.tx_mon_duration = init_param->tx_mon_duration; + phy->pdata->txmon_ctrl.tx1_mon_front_end_gain = + init_param->tx1_mon_front_end_gain; + phy->pdata->txmon_ctrl.tx2_mon_front_end_gain = + init_param->tx2_mon_front_end_gain; + phy->pdata->txmon_ctrl.tx1_mon_lo_cm = init_param->tx1_mon_lo_cm; + phy->pdata->txmon_ctrl.tx2_mon_lo_cm = init_param->tx2_mon_lo_cm; + + phy->pdata->debug_mode = true; + + gpio_get(&phy->gpio_desc_resetb, &init_param->gpio_resetb); + /* Optional: next three GPIOs are used for MCS synchronization */ + gpio_get_optional(&phy->gpio_desc_sync, &init_param->gpio_sync); + gpio_get_optional(&phy->gpio_desc_cal_sw1, &init_param->gpio_cal_sw1); + gpio_get_optional(&phy->gpio_desc_cal_sw2, &init_param->gpio_cal_sw2); + + gpio_direction_output(phy->gpio_desc_resetb, 0); + + spi_init(&phy->spi, &init_param->spi_param); + + phy->pdata->port_ctrl.digital_io_ctrl = 0; + phy->pdata->port_ctrl.lvds_invert[0] = init_param->lvds_invert1_control; + phy->pdata->port_ctrl.lvds_invert[1] = init_param->lvds_invert2_control; + + if (AD9364_DEVICE) { + phy->pdata->rx2tx2 = false; + phy->pdata->rx1tx1_mode_use_rx_num = 1; + phy->pdata->rx1tx1_mode_use_tx_num = 1; + } + + phy->rx_eq_2tx = false; + + phy->current_table = -1; + phy->bypass_tx_fir = true; + phy->bypass_rx_fir = true; + phy->rate_governor = 1; + phy->rfdc_track_en = true; + phy->bbdc_track_en = true; + phy->quad_track_en = true; + + phy->gt_info = ad9361_adi_gt_info; + + phy->bist_loopback_mode = 0; + phy->bist_config = 0; + phy->bist_prbs_mode = BIST_DISABLE; + phy->bist_tone_mode = BIST_DISABLE; + phy->bist_tone_freq_Hz = 0; + phy->bist_tone_level_dB = 0; + phy->bist_tone_mask = 0; + + ad9361_reset(phy); + + ret = ad9361_spi_read(phy->spi, REG_PRODUCT_ID); + if ((ret & PRODUCT_ID_MASK) != PRODUCT_ID_9361) { + printf("%s : Unsupported PRODUCT_ID 0x%X", __func__, (unsigned int)ret); + ret = -ENODEV; + goto out; + } + rev = ret & REV_MASK; + + phy->ad9361_rfpll_ext_recalc_rate = init_param->ad9361_rfpll_ext_recalc_rate; + phy->ad9361_rfpll_ext_round_rate = init_param->ad9361_rfpll_ext_round_rate; + phy->ad9361_rfpll_ext_set_rate = init_param->ad9361_rfpll_ext_set_rate; + + ret = ad9361_register_clocks(phy); + if (ret < 0) + goto out; + + ret = ad9361_setup(phy); + if (ret < 0) + goto out_clk; + + printf("%s : AD936x Rev %d successfully initialized\n", __func__, (int)rev); + + *ad9361_phy = phy; + + return 0; + +out_clk: + ad9361_unregister_clocks(phy); +out: + free(phy->clk_refin); + free(phy->pdata); + free(phy); + printf("%s : AD936x initialization error\n", __func__); + + return -ENODEV; +} + +/** + * Free the allocated resources. + * @param phy The AD9361 current state structure. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_remove(struct ad9361_rf_phy *phy) +{ + ad9361_unregister_clocks(phy); + spi_remove(phy->spi); + gpio_remove(phy->gpio_desc_resetb); + gpio_remove(phy->gpio_desc_sync); + gpio_remove(phy->gpio_desc_cal_sw1); + gpio_remove(phy->gpio_desc_cal_sw2); + free(phy->clk_refin); + free(phy->pdata); + free(phy); + + return 0; +} + +/** + * Set the Enable State Machine (ENSM) mode. + * @param phy The AD9361 current state structure. + * @param mode The ENSM mode. + * Accepted values: + * ENSM_MODE_TX + * ENSM_MODE_RX + * ENSM_MODE_ALERT + * ENSM_MODE_FDD + * ENSM_MODE_WAIT + * ENSM_MODE_SLEEP + * ENSM_MODE_PINCTRL + * ENSM_MODE_PINCTRL_FDD_INDEP + * @return 0 in case of success, negative error code otherwise. + * + * Note: This function will/may affect the data path. + */ +int32_t ad9361_set_en_state_machine_mode (struct ad9361_rf_phy *phy, + uint32_t mode) +{ + int32_t ret; + uint8_t ensm_state; + bool pinctrl = false; + + phy->pdata->fdd_independent_mode = false; + + switch (mode) { + case ENSM_MODE_TX: + ensm_state = ENSM_STATE_TX; + break; + case ENSM_MODE_RX: + ensm_state = ENSM_STATE_RX; + break; + case ENSM_MODE_ALERT: + ensm_state = ENSM_STATE_ALERT; + break; + case ENSM_MODE_FDD: + ensm_state = ENSM_STATE_FDD; + break; + case ENSM_MODE_WAIT: + ensm_state = ENSM_STATE_SLEEP_WAIT; + break; + case ENSM_MODE_SLEEP: + ensm_state = ENSM_STATE_SLEEP; + break; + case ENSM_MODE_PINCTRL: + ensm_state = ENSM_STATE_SLEEP_WAIT; + pinctrl = true; + break; + case ENSM_MODE_PINCTRL_FDD_INDEP: + ensm_state = ENSM_STATE_FDD; + phy->pdata->fdd_independent_mode = true; + break; + default: + return -EINVAL; + } + + ad9361_set_ensm_mode(phy, phy->pdata->fdd, pinctrl); + ret = ad9361_ensm_set_state(phy, ensm_state, pinctrl); + + return ret; +} + +/** + * Get the Enable State Machine (ENSM) mode. + * @param phy The AD9361 current state structure. + * @param mode A variable to store the selected ENSM mode. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_en_state_machine_mode (struct ad9361_rf_phy *phy, + uint32_t *mode) +{ + uint8_t ensm_state; + bool pinctrl = false; + int32_t ret; + + ensm_state = ad9361_spi_read(phy->spi, REG_STATE); + ensm_state &= ENSM_STATE(~0); + ret = ad9361_spi_read(phy->spi, REG_ENSM_CONFIG_1); + if ((ret & ENABLE_ENSM_PIN_CTRL) == ENABLE_ENSM_PIN_CTRL) + pinctrl = true; + + switch (ensm_state) { + case ENSM_STATE_TX: + *mode = ENSM_MODE_TX; + break; + case ENSM_STATE_RX: + *mode = ENSM_MODE_RX; + break; + case ENSM_STATE_ALERT: + *mode = ENSM_MODE_ALERT; + break; + case ENSM_STATE_FDD: + if (phy->pdata->fdd_independent_mode) + *mode = ENSM_MODE_PINCTRL_FDD_INDEP; + else + *mode = ENSM_MODE_FDD; + break; + case ENSM_STATE_SLEEP_WAIT: + if (pinctrl) + *mode = ENSM_MODE_PINCTRL; + else + *mode = ENSM_MODE_WAIT; + break; + case ENSM_STATE_SLEEP: + *mode = ENSM_MODE_SLEEP; + break; + default: + return -EINVAL; + } + + return 0; +} + +/** + * Set the receive RF gain for the selected channel. + * @param phy The AD9361 current state structure. + * @param ch The desired channel number (RX1, RX2). + * Accepted values in 2x2 mode: + * RX1 (0) + * RX2 (1) + * Accepted values in 1x1 mode: + * RX1 (0) + * @param gain_db The RF gain (dB). + * Example: + * 10 (10 dB) + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_set_rx_rf_gain (struct ad9361_rf_phy *phy, + uint8_t ch, int32_t gain_db) +{ + struct rf_rx_gain rx_gain = {0, 0, 0, 0, 0, 0, 0, 0, 0}; + int32_t ret = 0; + + rx_gain.gain_db = gain_db; + ret = ad9361_set_rx_gain(phy, + ad9361_1rx1tx_channel_map(phy, false, + ch + 1), &rx_gain); + + return ret; +} + +/** + * Get current receive RF gain for the selected channel. + * @param phy The AD9361 current state structure. + * @param ch The desired channel number (RX1, RX2). + * Accepted values in 2x2 mode: + * RX1 (0) + * RX2 (1) + * Accepted values in 1x1 mode: + * RX1 (0) + * @param gain_db A variable to store the RF gain (dB). + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_rx_rf_gain (struct ad9361_rf_phy *phy, + uint8_t ch, int32_t *gain_db) +{ + struct rf_rx_gain rx_gain = {0, 0, 0, 0, 0, 0, 0, 0, 0}; + int32_t ret = 0; + + ret = ad9361_get_rx_gain(phy, ad9361_1rx1tx_channel_map(phy, + false, ch + 1), &rx_gain); + + *gain_db = rx_gain.gain_db; + + return ret; +} + +/** + * Set the RX RF bandwidth. + * @param phy The AD9361 current state structure. + * @param bandwidth_hz The desired bandwidth (Hz). + * Example: + * 18000000 (18 MHz) + * @return 0 in case of success, negative error code otherwise. + * + * Note: This function will/may affect the data path. + */ +int32_t ad9361_set_rx_rf_bandwidth (struct ad9361_rf_phy *phy, + uint32_t bandwidth_hz) +{ + int32_t ret = 0; + + bandwidth_hz = ad9361_validate_rf_bw(phy, bandwidth_hz); + + if (phy->current_rx_bw_Hz != bandwidth_hz) + ret = ad9361_update_rf_bandwidth(phy, bandwidth_hz, + phy->current_tx_bw_Hz); + else + ret = 0; + + return ret; +} + +/** + * Get the RX RF bandwidth. + * @param phy The AD9361 current state structure. + * @param bandwidth_hz A variable to store the bandwidth value (Hz). + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_rx_rf_bandwidth (struct ad9361_rf_phy *phy, + uint32_t *bandwidth_hz) +{ + *bandwidth_hz = phy->current_rx_bw_Hz; + + return 0; +} + +/** + * Set the RX sampling frequency. + * @param phy The AD9361 current state structure. + * @param sampling_freq_hz The desired frequency (Hz). + * Example: + * 30720000 (30.72 MHz) + * @return 0 in case of success, negative error code otherwise. + * + * Note: This function will/may affect the data path. + */ +int32_t ad9361_set_rx_sampling_freq (struct ad9361_rf_phy *phy, + uint32_t sampling_freq_hz) +{ + int32_t ret; + uint32_t rx[6], tx[6]; + + ret = ad9361_calculate_rf_clock_chain(phy, sampling_freq_hz, + phy->rate_governor, rx, tx); + if (ret < 0) + return ret; + + ad9361_set_trx_clock_chain(phy, rx, tx); + + ret = ad9361_update_rf_bandwidth(phy, phy->current_rx_bw_Hz, + phy->current_tx_bw_Hz); + + return ret; +} + +/** + * Get current RX sampling frequency. + * @param phy The AD9361 current state structure. + * @param sampling_freq_hz A variable to store the frequency value (Hz). + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_rx_sampling_freq (struct ad9361_rf_phy *phy, + uint32_t *sampling_freq_hz) +{ + *sampling_freq_hz = (uint32_t)clk_get_rate(phy, + phy->ref_clk_scale[RX_SAMPL_CLK]); + + return 0; +} + +/** + * Set the RX LO frequency. + * @param phy The AD9361 current state structure. + * @param lo_freq_hz The desired frequency (Hz). + * Example: + * 2400000000 (2.4 GHz) + * @return 0 in case of success, negative error code otherwise. + * + * Note: This function will/may affect the data path. + */ +int32_t ad9361_set_rx_lo_freq (struct ad9361_rf_phy *phy, + uint64_t lo_freq_hz) +{ + int32_t ret; + + ret = clk_set_rate(phy, phy->ref_clk_scale[RX_RFPLL], + ad9361_to_clk(lo_freq_hz)); + + return ret; +} + +/** + * Get current RX LO frequency. + * @param phy The AD9361 current state structure. + * @param lo_freq_hz A variable to store the frequency value (Hz). + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_rx_lo_freq (struct ad9361_rf_phy *phy, + uint64_t *lo_freq_hz) +{ + *lo_freq_hz = ad9361_from_clk(clk_get_rate(phy, + phy->ref_clk_scale[RX_RFPLL])); + + return 0; +} + +/** + * Switch between internal and external LO. + * @param phy The AD9361 state structure. + * @param int_ext The selected lo (INT_LO, EXT_LO). + * Accepted values: + * INT_LO + * EXT_LO + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_set_rx_lo_int_ext(struct ad9361_rf_phy *phy, uint8_t int_ext) +{ + if ((phy->dev_sel == ID_AD9363A) && (int_ext == EXT_LO)) { + printf("%s : EXT_LO is not supported by AD9363!\n", __func__); + return -1; + } + + phy->pdata->use_ext_rx_lo = int_ext; + + return ad9361_clk_mux_set_parent(phy->ref_clk_scale[RX_RFPLL], int_ext); +} + +/** + * Get the RSSI for the selected channel. + * @param phy The AD9361 current state structure. + * @param ch The desired channel (RX1, RX2). + * Accepted values in 2x2 mode: + * RX1 (0) + * RX2 (1) + * Accepted values in 1x1 mode: + * RX1 (0) + * @param rssi A variable to store the RSSI. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_rx_rssi (struct ad9361_rf_phy *phy, + uint8_t ch, struct rf_rssi *rssi) +{ + int32_t ret; + + rssi->ant = ad9361_1rx1tx_channel_map(phy, false, ch + 1); + rssi->duration = 1; + ret = ad9361_read_rssi(phy, rssi); + + return ret; +} + +/** + * Set the gain control mode for the selected channel. + * @param phy The AD9361 current state structure. + * @param ch The desired channel (RX1, RX2). + * Accepted values in 2x2 mode: + * RX1 (0) + * RX2 (1) + * Accepted values in 1x1 mode: + * RX1 (0) + * @param gc_mode The gain control mode (manual, fast_attack, slow_attack, + * hybrid). + * Accepted values: + * RF_GAIN_MGC (manual) + * RF_GAIN_FASTATTACK_AGC (fast_attack) + * RF_GAIN_SLOWATTACK_AGC (slow_attack) + * RF_GAIN_HYBRID_AGC (hybrid) + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_set_rx_gain_control_mode (struct ad9361_rf_phy *phy, + uint8_t ch, uint8_t gc_mode) +{ + struct rf_gain_ctrl gc = {0, 0}; + + gc.ant = ad9361_1rx1tx_channel_map(phy, false, ch + 1); + gc.mode = phy->agc_mode[ch] = gc_mode; + + ad9361_set_gain_ctrl_mode(phy, &gc); + + return 0; +} + +/** + * Get the gain control mode for the selected channel. + * @param phy The AD9361 current state structure. + * @param ch The desired channel (RX1, RX2). + * Accepted values: + * RX1 (0) + * RX2 (1) + * @param gc_mode A variable to store the gain control mode. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_rx_gain_control_mode (struct ad9361_rf_phy *phy, + uint8_t ch, uint8_t *gc_mode) +{ + *gc_mode = phy->agc_mode[ch]; + + return 0; +} + +/** + * Set the RX FIR filter configuration. + * @param phy The AD9361 current state structure. + * @param fir_cfg FIR filter configuration. + * @return 0 in case of success, negative error code otherwise. + * + * Note: This function will/may affect the data path. + */ +int32_t ad9361_set_rx_fir_config (struct ad9361_rf_phy *phy, + AD9361_RXFIRConfig fir_cfg) +{ + int32_t ret; + + phy->rx_fir_dec = fir_cfg.rx_dec; + ret = ad9361_load_fir_filter_coef(phy, (enum fir_dest)(fir_cfg.rx | FIR_IS_RX), + fir_cfg.rx_gain, fir_cfg.rx_coef_size, fir_cfg.rx_coef); + + return ret; +} + +/** + * Get the RX FIR filter configuration. + * @param phy The AD9361 current state structure. + * @param rx_ch The selected RX channel (RX1, RX2). + * Accepted values: + * RX1 (0) + * RX2 (1) + * @param fir_cfg FIR filter configuration output file. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_rx_fir_config(struct ad9361_rf_phy *phy, uint8_t rx_ch, + AD9361_RXFIRConfig *fir_cfg) +{ + int32_t ret; + uint32_t fir_conf; + uint8_t index; + + rx_ch += 1; + + ret = ad9361_spi_read(phy->spi, REG_RX_FILTER_CONFIG); + if(ret < 0) + return ret; + fir_conf = ret; + + fir_cfg->rx_coef_size = (((fir_conf & FIR_NUM_TAPS(7)) >> 5) + 1) * 16; + + ret = ad9361_spi_read(phy->spi, REG_RX_FILTER_GAIN); + if(ret < 0) + return ret; + fir_cfg->rx_gain = -6 * (ret & FILTER_GAIN(3)) + 6; + fir_cfg->rx = rx_ch; + + fir_conf &= ~FIR_SELECT(3); + fir_conf |= FIR_SELECT(rx_ch) | FIR_START_CLK; + ad9361_spi_write(phy->spi, REG_RX_FILTER_CONFIG, fir_conf); + + for(index = 0; index < 128; index++) { + ad9361_spi_write(phy->spi, REG_RX_FILTER_COEF_ADDR, index); + ret = ad9361_spi_read(phy->spi, REG_RX_FILTER_COEF_READ_DATA_1); + if(ret < 0) + return ret; + fir_cfg->rx_coef[index] = ret; + ret = ad9361_spi_read(phy->spi, REG_RX_FILTER_COEF_READ_DATA_2); + if(ret < 0) + return ret; + fir_cfg->rx_coef[index] |= (ret << 8); + } + + fir_conf &= ~FIR_START_CLK; + ad9361_spi_write(phy->spi, REG_RX_FILTER_CONFIG, fir_conf); + + fir_cfg->rx_dec = phy->rx_fir_dec; + + return 0; +} + +/** + * Enable/disable the RX FIR filter. + * @param phy The AD9361 current state structure. + * @param en_dis The option (ENABLE, DISABLE). + * Accepted values: + * ENABLE (1) + * DISABLE (0) + * @return 0 in case of success, negative error code otherwise. + * + * Note: This function will/may affect the data path. + */ +int32_t ad9361_set_rx_fir_en_dis (struct ad9361_rf_phy *phy, + uint8_t en_dis) +{ + int32_t ret = 0; + + if(phy->bypass_rx_fir == !en_dis) + return ret; + + phy->bypass_rx_fir = !en_dis; + ret = ad9361_validate_enable_fir(phy); + if (ret < 0) { + phy->bypass_rx_fir = true; + } + + return ret; +} + +/** + * Get the status of the RX FIR filter. + * @param phy The AD9361 current state structure. + * @param en_dis The enable/disable status buffer. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_rx_fir_en_dis (struct ad9361_rf_phy *phy, + uint8_t *en_dis) +{ + *en_dis = !phy->bypass_rx_fir; + + return 0; +} + +/** + * Enable/disable the RX RFDC Tracking. + * @param phy The AD9361 current state structure. + * @param en_dis The option (ENABLE, DISABLE). + * Accepted values: + * ENABLE (1) + * DISABLE (0) + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_set_rx_rfdc_track_en_dis (struct ad9361_rf_phy *phy, + uint8_t en_dis) +{ + int32_t ret = 0; + + if(phy->rfdc_track_en == en_dis) + return ret; + + phy->rfdc_track_en = en_dis; + ret = ad9361_tracking_control(phy, phy->bbdc_track_en, + phy->rfdc_track_en, phy->quad_track_en); + + return ret; +} + +/** + * Get the status of the RX RFDC Tracking. + * @param phy The AD9361 current state structure. + * @param en_dis The enable/disable status buffer. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_rx_rfdc_track_en_dis (struct ad9361_rf_phy *phy, + uint8_t *en_dis) +{ + *en_dis = phy->rfdc_track_en; + + return 0; +} + +/** + * Enable/disable the RX BasebandDC Tracking. + * @param phy The AD9361 current state structure. + * @param en_dis The option (ENABLE, DISABLE). + * Accepted values: + * ENABLE (1) + * DISABLE (0) + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_set_rx_bbdc_track_en_dis (struct ad9361_rf_phy *phy, + uint8_t en_dis) +{ + int32_t ret = 0; + + if(phy->bbdc_track_en == en_dis) + return ret; + + phy->bbdc_track_en = en_dis; + ret = ad9361_tracking_control(phy, phy->bbdc_track_en, + phy->rfdc_track_en, phy->quad_track_en); + + return ret; +} + +/** + * Get the status of the RX BasebandDC Tracking. + * @param phy The AD9361 current state structure. + * @param en_dis The enable/disable status buffer. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_rx_bbdc_track_en_dis (struct ad9361_rf_phy *phy, + uint8_t *en_dis) +{ + *en_dis = phy->bbdc_track_en; + + return 0; +} + +/** + * Enable/disable the RX Quadrature Tracking. + * @param phy The AD9361 current state structure. + * @param en_dis The option (ENABLE, DISABLE). + * Accepted values: + * ENABLE (1) + * DISABLE (0) + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_set_rx_quad_track_en_dis (struct ad9361_rf_phy *phy, + uint8_t en_dis) +{ + int32_t ret = 0; + + if(phy->quad_track_en == en_dis) + return ret; + + phy->quad_track_en = en_dis; + ret = ad9361_tracking_control(phy, phy->bbdc_track_en, + phy->rfdc_track_en, phy->quad_track_en); + + return ret; +} + +/** + * Get the status of the RX Quadrature Tracking. + * @param phy The AD9361 current state structure. + * @param en_dis The enable/disable status buffer. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_rx_quad_track_en_dis (struct ad9361_rf_phy *phy, + uint8_t *en_dis) +{ + *en_dis = phy->quad_track_en; + + return 0; +} + +/** + * Set the RX RF input port. + * @param phy The AD9361 current state structure. + * @param mode The RF port. + * Accepted values: + * A_BALANCED (0 - (RX1A_N & RX1A_P) and (RX2A_N & RX2A_P) enabled; balanced) + * B_BALANCED (1 - (RX1B_N & RX1B_P) and (RX2B_N & RX2B_P) enabled; balanced) + * C_BALANCED (2 - (RX1C_N & RX1C_P) and (RX2C_N & RX2C_P) enabled; balanced) + * A_N (3 - RX1A_N and RX2A_N enabled; unbalanced) + * A_P (4 - RX1A_P and RX2A_P enabled; unbalanced) + * B_N (5 - RX1B_N and RX2B_N enabled; unbalanced) + * B_P (6 - RX1B_P and RX2B_P enabled; unbalanced) + * C_N (7 - RX1C_N and RX2C_N enabled; unbalanced) + * C_P (8 - RX1C_P and RX2C_P enabled; unbalanced) + * TX_MON1 (9 - TX_MONITOR1) + * TX_MON2 (10 - TX_MONITOR2) + * TX_MON1_2 (11 - TX_MONITOR1 & TX_MONITOR2) + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_set_rx_rf_port_input (struct ad9361_rf_phy *phy, + uint32_t mode) +{ + int32_t ret; + + phy->pdata->rf_rx_input_sel = mode; + + ret = ad9361_rf_port_setup(phy, false, + phy->pdata->rf_rx_input_sel, + phy->pdata->rf_tx_output_sel); + + return ret; +} + +/** + * Get the selected RX RF input port. + * @param phy The AD9361 current state structure. + * @param mode The RF port. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_rx_rf_port_input (struct ad9361_rf_phy *phy, + uint32_t *mode) +{ + *mode = phy->pdata->rf_rx_input_sel; + + return 0; +} + +/** + * Store RX fastlock profile. + * To create a profile tune the synthesizer (ad9361_set_rx_lo_freq()) and then + * call this function specifying the target profile number. + * @param phy The AD9361 state structure. + * @param profile The profile number (0 - 7). + * Accepted values: + * 0 - 7 + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_rx_fastlock_store(struct ad9361_rf_phy *phy, uint32_t profile) +{ + return ad9361_fastlock_store(phy, 0, profile); +} + +/** + * Recall specified RX fastlock profile. + * When in fastlock pin select mode (init_param->rx_fastlock_pincontrol_enable), + * the function needs to be called before then the pin-control can be used. + * @param phy The AD9361 state structure. + * @param profile The profile number (0 - 7). + * Accepted values: + * 0 - 7 + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_rx_fastlock_recall(struct ad9361_rf_phy *phy, uint32_t profile) +{ + return ad9361_fastlock_recall(phy, 0, profile); +} + +/** + * Load RX fastlock profile. A previously saved profile can be loaded in any + * of the 8 available slots. + * @param phy The AD9361 state structure. + * @param profile The profile number (0 - 7). + * Accepted values: + * 0 - 7 + * @param values Fastlock profile program data. + * Example: + * val0,val1,val2,Â…,val15 + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_rx_fastlock_load(struct ad9361_rf_phy *phy, uint32_t profile, + uint8_t *values) +{ + return ad9361_fastlock_load(phy, 0, profile, values); +} + +/** + * Save RX fastlock profile. In order to use more than 8 Profiles, an existing + * profile can be read back and stored by the user application. + * @param phy The AD9361 state structure. + * @param profile The profile number (0 - 7). + * Accepted values: + * 0 - 7 + * @param values Fastlock profile program data. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_rx_fastlock_save(struct ad9361_rf_phy *phy, uint32_t profile, + uint8_t *values) +{ + return ad9361_fastlock_save(phy, 0, profile, values); +} + +/** + * Power down the RX Local Oscillator. + * @param phy The AD9361 state structure. + * @param option The option (ON, OFF). + * Accepted values: + * ON (0) + * OFF (1) + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_rx_lo_powerdown(struct ad9361_rf_phy *phy, uint8_t option) +{ + return ad9361_synth_lo_powerdown(phy, option ? LO_OFF : LO_ON, LO_DONTCARE); +} + +/** + * Get the RX Local Oscillator power status. + * @param phy The AD9361 state structure. + * @param option Store the option (ON, OFF). + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_rx_lo_power(struct ad9361_rf_phy *phy, uint8_t *option) +{ + *option = !(phy->cached_synth_pd[1] & RX_LO_POWER_DOWN) ? OFF : ON; + + return 0; +} + +/** + * Set the transmit attenuation for the selected channel. + * @param phy The AD9361 current state structure. + * @param ch The desired channel number (TX1, TX2). + * Accepted values in 2x2 mode: + * TX1 (0) + * TX2 (1) + * Accepted values in 1x1 mode: + * TX1 (0) + * @param attenuation_mdb The attenuation (mdB). + * Example: + * 10000 (10 dB) + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_set_tx_attenuation (struct ad9361_rf_phy *phy, + uint8_t ch, uint32_t attenuation_mdb) +{ + int32_t ret; + int32_t channel; + + channel = ad9361_1rx1tx_channel_map(phy, true, ch); + ret = ad9361_set_tx_atten(phy, attenuation_mdb, + channel == 0, channel == 1, + !phy->pdata->update_tx_gain_via_alert); + + return ret; +} + +/** + * Get current transmit attenuation for the selected channel. + * @param phy The AD9361 current state structure. + * @param ch The desired channel number (TX1, TX2). + * Accepted values in 2x2 mode: + * TX1 (0) + * TX2 (1) + * Accepted values in 1x1 mode: + * TX1 (0) + * @param attenuation_mdb A variable to store the attenuation value (mdB). + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_tx_attenuation (struct ad9361_rf_phy *phy, + uint8_t ch, uint32_t *attenuation_mdb) +{ + int32_t ret; + + ret = ad9361_get_tx_atten(phy, + ad9361_1rx1tx_channel_map(phy, true, + ch + 1)); + + if(ret < 0) + return ret; + *attenuation_mdb = ret; + + return 0; +} + +/** + * Set the TX RF bandwidth. + * @param phy The AD9361 current state structure. + * @param bandwidth_hz The desired bandwidth (Hz). + * Example: + * 18000000 (18 MHz) + * @return 0 in case of success, negative error code otherwise. + * + * Note: This function will/may affect the data path. + */ +int32_t ad9361_set_tx_rf_bandwidth (struct ad9361_rf_phy *phy, + uint32_t bandwidth_hz) +{ + int32_t ret = 0; + + bandwidth_hz = ad9361_validate_rf_bw(phy, bandwidth_hz); + + if (phy->current_tx_bw_Hz != bandwidth_hz) + ret = ad9361_update_rf_bandwidth(phy, + phy->current_rx_bw_Hz, bandwidth_hz); + else + ret = 0; + + return ret; +} + +/** + * Get the TX RF bandwidth. + * @param phy The AD9361 current state structure. + * @param bandwidth_hz A variable to store the bandwidth value (Hz). + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_tx_rf_bandwidth (struct ad9361_rf_phy *phy, + uint32_t *bandwidth_hz) +{ + *bandwidth_hz = phy->current_tx_bw_Hz; + + return 0; +} + +/** + * Set the TX sampling frequency. + * @param phy The AD9361 current state structure. + * @param sampling_freq_hz The desired frequency (Hz). + * Example: + * 30720000 (30.72 MHz) + * @return 0 in case of success, negative error code otherwise. + * + * Note: This function will/may affect the data path. + */ +int32_t ad9361_set_tx_sampling_freq (struct ad9361_rf_phy *phy, + uint32_t sampling_freq_hz) +{ + int32_t ret; + uint32_t rx[6], tx[6]; + + ret = ad9361_calculate_rf_clock_chain(phy, sampling_freq_hz, + phy->rate_governor, rx, tx); + if (ret < 0) + return ret; + + ad9361_set_trx_clock_chain(phy, rx, tx); + + ret = ad9361_update_rf_bandwidth(phy, phy->current_rx_bw_Hz, + phy->current_tx_bw_Hz); + + return ret; +} + +/** + * Get current TX sampling frequency. + * @param phy The AD9361 current state structure. + * @param sampling_freq_hz A variable to store the frequency value (Hz). + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_tx_sampling_freq (struct ad9361_rf_phy *phy, + uint32_t *sampling_freq_hz) +{ + *sampling_freq_hz = (uint32_t)clk_get_rate(phy, + phy->ref_clk_scale[TX_SAMPL_CLK]); + + return 0; +} + +/** + * Set the TX LO frequency. + * @param phy The AD9361 current state structure. + * @param lo_freq_hz The desired frequency (Hz). + * Example: + * 2400000000 (2.4 GHz) + * @return 0 in case of success, negative error code otherwise. + * + * Note: This function will/may affect the data path. + */ +int32_t ad9361_set_tx_lo_freq (struct ad9361_rf_phy *phy, + uint64_t lo_freq_hz) +{ + int32_t ret; + + ret = clk_set_rate(phy, phy->ref_clk_scale[TX_RFPLL], + ad9361_to_clk(lo_freq_hz)); + + return ret; +} + +/** + * Get current TX LO frequency. + * @param phy The AD9361 current state structure. + * @param lo_freq_hz A variable to store the frequency value (Hz). + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_tx_lo_freq (struct ad9361_rf_phy *phy, + uint64_t *lo_freq_hz) +{ + *lo_freq_hz = ad9361_from_clk(clk_get_rate(phy, + phy->ref_clk_scale[TX_RFPLL])); + + return 0; +} + +/** + * Switch between internal and external LO. + * @param phy The AD9361 state structure. + * @param int_ext The selected lo (INT_LO, EXT_LO). + * Accepted values: + * INT_LO + * EXT_LO + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_set_tx_lo_int_ext(struct ad9361_rf_phy *phy, uint8_t int_ext) +{ + if ((phy->dev_sel == ID_AD9363A) && (int_ext == EXT_LO)) { + printf("%s : EXT_LO is not supported by AD9363!\n", __func__); + return -1; + } + + phy->pdata->use_ext_tx_lo = int_ext; + + return ad9361_clk_mux_set_parent(phy->ref_clk_scale[TX_RFPLL], int_ext); +} + +/** + * Set the TX FIR filter configuration. + * @param phy The AD9361 current state structure. + * @param fir_cfg FIR filter configuration. + * @return 0 in case of success, negative error code otherwise. + * + * Note: This function will/may affect the data path. + */ +int32_t ad9361_set_tx_fir_config (struct ad9361_rf_phy *phy, + AD9361_TXFIRConfig fir_cfg) +{ + int32_t ret; + + phy->tx_fir_int = fir_cfg.tx_int; + ret = ad9361_load_fir_filter_coef(phy, (enum fir_dest)fir_cfg.tx, + fir_cfg.tx_gain, fir_cfg.tx_coef_size, fir_cfg.tx_coef); + + return ret; +} + +/** + * Get the TX FIR filter configuration. + * @param phy The AD9361 current state structure. + * @param tx_ch The selected TX channel (TX1, TX2). + * Accepted values: + * TX1 (0) + * TX2 (1) + * @param fir_cfg FIR filter configuration output file. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_tx_fir_config(struct ad9361_rf_phy *phy, uint8_t tx_ch, + AD9361_TXFIRConfig *fir_cfg) +{ + int32_t ret; + uint32_t fir_conf; + uint8_t index; + + tx_ch += 1; + + ret = ad9361_spi_read(phy->spi, REG_TX_FILTER_CONF); + if(ret < 0) + return ret; + fir_conf = ret; + fir_cfg->tx_coef_size = (((fir_conf & FIR_NUM_TAPS(7)) >> 5) + 1) * 16; + fir_cfg->tx_gain = -6 * (fir_conf & TX_FIR_GAIN_6DB); + fir_cfg->tx = tx_ch; + + fir_conf &= ~FIR_SELECT(3); + fir_conf |= FIR_SELECT(tx_ch) | FIR_START_CLK; + ad9361_spi_write(phy->spi, REG_TX_FILTER_CONF, fir_conf); + + for(index = 0; index < 128; index++) { + ad9361_spi_write(phy->spi, REG_TX_FILTER_COEF_ADDR, index); + ret = ad9361_spi_read(phy->spi, REG_TX_FILTER_COEF_READ_DATA_1); + if(ret < 0) + return ret; + fir_cfg->tx_coef[index] = ret; + ret = ad9361_spi_read(phy->spi, REG_TX_FILTER_COEF_READ_DATA_2); + if(ret < 0) + return ret; + fir_cfg->tx_coef[index] |= (ret << 8); + } + + fir_conf &= ~FIR_START_CLK; + ad9361_spi_write(phy->spi, REG_TX_FILTER_CONF, fir_conf); + + fir_cfg->tx_int = phy->tx_fir_int; + + return 0; +} + +/** + * Enable/disable the TX FIR filter. + * @param phy The AD9361 current state structure. + * @param en_dis The option (ENABLE, DISABLE). + * Accepted values: + * ENABLE (1) + * DISABLE (0) + * @return 0 in case of success, negative error code otherwise. + * + * Note: This function will/may affect the data path. + */ +int32_t ad9361_set_tx_fir_en_dis (struct ad9361_rf_phy *phy, + uint8_t en_dis) +{ + int32_t ret = 0; + + if(phy->bypass_tx_fir == !en_dis) + return ret; + + phy->bypass_tx_fir = !en_dis; + ret = ad9361_validate_enable_fir(phy); + if (ret < 0) { + phy->bypass_tx_fir = true; + } + + return ret; +} + +/** + * Get the status of the TX FIR filter. + * @param phy The AD9361 current state structure. + * @param en_dis The enable/disable status buffer. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_tx_fir_en_dis (struct ad9361_rf_phy *phy, + uint8_t *en_dis) +{ + *en_dis = !phy->bypass_tx_fir; + + return 0; +} + +/** + * Get the TX RSSI for the selected channel (TX_MON should be enabled). + * @param phy The AD9361 current state structure. + * @param ch The desired channel (TX1, TX2). + * Accepted values: + * TX1 (0) + * TX2 (1) + * @param rssi_db_x_1000 A variable to store the RSSI. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_tx_rssi (struct ad9361_rf_phy *phy, + uint8_t ch, + uint32_t *rssi_db_x_1000) +{ + uint8_t reg_val_buf[3]; + uint32_t val; + int32_t ret; + + ret = ad9361_spi_readm(phy->spi, REG_TX_RSSI_LSB, + reg_val_buf, ARRAY_SIZE(reg_val_buf)); + if (ret < 0) { + return ret; + } + + switch (ch) { + case 0: + val = (reg_val_buf[2] << 1) | (reg_val_buf[0] & TX_RSSI_1); + break; + case 1: + val = (reg_val_buf[1] << 1) | ((reg_val_buf[0] & TX_RSSI_2) >> 1); + break; + default: + return -EINVAL; + } + + val *= RSSI_RESOLUTION; + + *rssi_db_x_1000 = ((val / RSSI_MULTIPLIER) * 1000) + + (val % RSSI_MULTIPLIER); + + return 0; +} + +/** + * Set the TX RF output port. + * @param phy The AD9361 current state structure. + * @param mode The RF port. + * Accepted values: + * TXA (0) + * TXB (1) + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_set_tx_rf_port_output (struct ad9361_rf_phy *phy, + uint32_t mode) +{ + int32_t ret; + + phy->pdata->rf_tx_output_sel = mode; + + ret = ad9361_rf_port_setup(phy, true, + phy->pdata->rf_rx_input_sel, + phy->pdata->rf_tx_output_sel); + + return ret; +} + +/** + * Get the selected TX RF output port. + * @param phy The AD9361 current state structure. + * @param mode The RF port. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_tx_rf_port_output (struct ad9361_rf_phy *phy, + uint32_t *mode) +{ + *mode = phy->pdata->rf_tx_output_sel; + + return 0; +} + +/** + * Enable/disable the auto calibration. + * @param phy The AD9361 current state structure. + * @param en_dis The option (ENABLE, DISABLE). + * Accepted values: + * ENABLE (1) + * DISABLE (0) + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_set_tx_auto_cal_en_dis (struct ad9361_rf_phy *phy, + uint8_t en_dis) +{ + if (en_dis == 0) + phy->auto_cal_en = 0; + else + phy->auto_cal_en = 1; + + return 0; +} + +/** + * Get the status of the auto calibration flag. + * @param phy The AD9361 current state structure. + * @param en_dis The enable/disable status buffer. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_tx_auto_cal_en_dis (struct ad9361_rf_phy *phy, + uint8_t *en_dis) +{ + *en_dis = phy->auto_cal_en; + + return 0; +} + +/** + * Store TX fastlock profile. + * To create a profile tune the synthesizer (ad9361_set_tx_lo_freq()) and then + * call this function specifying the target profile number. + * @param phy The AD9361 state structure. + * @param profile The profile number (0 - 7). + * Accepted values: + * 0 - 7 + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_tx_fastlock_store(struct ad9361_rf_phy *phy, uint32_t profile) +{ + return ad9361_fastlock_store(phy, 1, profile); +} + +/** + * Recall specified TX fastlock profile. + * When in fastlock pin select mode (init_param->tx_fastlock_pincontrol_enable), + * the function needs to be called before then the pin-control can be used. + * @param phy The AD9361 state structure. + * @param profile The profile number (0 - 7). + * Accepted values: + * 0 - 7 + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_tx_fastlock_recall(struct ad9361_rf_phy *phy, uint32_t profile) +{ + return ad9361_fastlock_recall(phy, 1, profile); +} + +/** + * Load TX fastlock profile. A previously saved profile can be loaded in any + * of the 8 available slots. + * @param phy The AD9361 state structure. + * @param profile The profile number (0 - 7). + * Accepted values: + * 0 - 7 + * @param values Fastlock profile program data. + * Example: + * val0,val1,val2,Â…,val15 + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_tx_fastlock_load(struct ad9361_rf_phy *phy, uint32_t profile, + uint8_t *values) +{ + return ad9361_fastlock_load(phy, 1, profile, values); +} + +/** + * Save TX fastlock profile. In order to use more than 8 Profiles, an existing + * profile can be read back and stored by the user application. + * @param phy The AD9361 state structure. + * @param profile The profile number (0 - 7). + * Accepted values: + * 0 - 7 + * @param values Fastlock profile program data. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_tx_fastlock_save(struct ad9361_rf_phy *phy, uint32_t profile, + uint8_t *values) +{ + return ad9361_fastlock_save(phy, 1, profile, values); +} + +/** + * Power down the TX Local Oscillator. + * @param phy The AD9361 state structure. + * @param option The option (ON, OFF). + * Accepted values: + * ON (0) + * OFF (1) + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_tx_lo_powerdown(struct ad9361_rf_phy *phy, uint8_t option) +{ + return ad9361_synth_lo_powerdown(phy, LO_DONTCARE, option ? LO_OFF : LO_ON); +} + +/** + * Get the TX Local Oscillator power status. + * @param phy The AD9361 state structure. + * @param option Store the option (ON, OFF). + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_tx_lo_power(struct ad9361_rf_phy *phy, uint8_t *option) +{ + *option = !(phy->cached_synth_pd[0] & TX_LO_POWER_DOWN) ? OFF : ON; + + return 0; +} + +/** + * Set the RX and TX path rates. + * @param phy The AD9361 state structure. + * @param rx_path_clks RX path rates buffer. + * @param tx_path_clks TX path rates buffer. + * @return 0 in case of success, negative error code otherwise. + * + * Note: This function will/may affect the data path. + */ +int32_t ad9361_set_trx_path_clks(struct ad9361_rf_phy *phy, + uint32_t *rx_path_clks, + uint32_t *tx_path_clks) +{ + int32_t ret; + + ret = ad9361_set_trx_clock_chain(phy, rx_path_clks, tx_path_clks); + if (ret < 0) + return ret; + + ret = ad9361_update_rf_bandwidth(phy, phy->current_rx_bw_Hz, + phy->current_tx_bw_Hz); + + return ret; +} + +/** + * Get the RX and TX path rates. + * @param phy The AD9361 state structure. + * @param rx_path_clks RX path rates buffer. + * @param tx_path_clks TX path rates buffer. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_trx_path_clks(struct ad9361_rf_phy *phy, + uint32_t *rx_path_clks, + uint32_t *tx_path_clks) +{ + return ad9361_get_trx_clock_chain(phy, rx_path_clks, tx_path_clks); +} + +/** + * Set the number of channels mode. + * @param phy The AD9361 state structure. + * Note: This function also resets the device, some additional + * configurations might be necessary + * @param no_ch_mode Number of channels mode (MODE_1x1, MODE_2x2). + * Accepted values: + * MODE_1x1 (1) + * MODE_2x2 (2) + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_set_no_ch_mode(struct ad9361_rf_phy *phy, uint8_t no_ch_mode) +{ + switch (no_ch_mode) { + case 1: + phy->pdata->rx2tx2 = 0; + break; + case 2: + phy->pdata->rx2tx2 = 1; + break; + default: + return -EINVAL; + } + + ad9361_reset(phy); + ad9361_spi_write(phy->spi, REG_SPI_CONF, SOFT_RESET | _SOFT_RESET); + ad9361_spi_write(phy->spi, REG_SPI_CONF, 0x0); + + ad9361_clear_state(phy); + + phy->clks[TX_REFCLK]->rate = ad9361_clk_factor_recalc_rate( + phy->ref_clk_scale[TX_REFCLK], phy->clk_refin->rate); + phy->clks[TX_REFCLK]->rate = ad9361_clk_factor_recalc_rate( + phy->ref_clk_scale[TX_REFCLK], phy->clk_refin->rate); + phy->clks[RX_REFCLK]->rate = ad9361_clk_factor_recalc_rate( + phy->ref_clk_scale[RX_REFCLK], phy->clk_refin->rate); + phy->clks[BB_REFCLK]->rate = ad9361_clk_factor_recalc_rate( + phy->ref_clk_scale[BB_REFCLK], phy->clk_refin->rate); + phy->clks[BBPLL_CLK]->rate = ad9361_bbpll_recalc_rate( + phy->ref_clk_scale[BBPLL_CLK], phy->clks[BB_REFCLK]->rate); + phy->clks[ADC_CLK]->rate = ad9361_clk_factor_recalc_rate( + phy->ref_clk_scale[ADC_CLK], phy->clks[BBPLL_CLK]->rate); + phy->clks[R2_CLK]->rate = ad9361_clk_factor_recalc_rate( + phy->ref_clk_scale[R2_CLK], phy->clks[ADC_CLK]->rate); + phy->clks[R1_CLK]->rate = ad9361_clk_factor_recalc_rate( + phy->ref_clk_scale[R1_CLK], phy->clks[R2_CLK]->rate); + phy->clks[CLKRF_CLK]->rate = ad9361_clk_factor_recalc_rate( + phy->ref_clk_scale[CLKRF_CLK], phy->clks[R1_CLK]->rate); + phy->clks[RX_SAMPL_CLK]->rate = ad9361_clk_factor_recalc_rate( + phy->ref_clk_scale[RX_SAMPL_CLK], phy->clks[CLKRF_CLK]->rate); + phy->clks[DAC_CLK]->rate = ad9361_clk_factor_recalc_rate( + phy->ref_clk_scale[DAC_CLK], phy->clks[ADC_CLK]->rate); + phy->clks[T2_CLK]->rate = ad9361_clk_factor_recalc_rate( + phy->ref_clk_scale[T2_CLK], phy->clks[DAC_CLK]->rate); + phy->clks[T1_CLK]->rate = ad9361_clk_factor_recalc_rate( + phy->ref_clk_scale[T1_CLK], phy->clks[T2_CLK]->rate); + phy->clks[CLKTF_CLK]->rate = ad9361_clk_factor_recalc_rate( + phy->ref_clk_scale[CLKTF_CLK], phy->clks[T1_CLK]->rate); + phy->clks[TX_SAMPL_CLK]->rate = ad9361_clk_factor_recalc_rate( + phy->ref_clk_scale[TX_SAMPL_CLK], phy->clks[CLKTF_CLK]->rate); + phy->clks[RX_RFPLL_INT]->rate = ad9361_rfpll_int_recalc_rate( + phy->ref_clk_scale[RX_RFPLL_INT], phy->clks[RX_REFCLK]->rate); + phy->clks[TX_RFPLL_INT]->rate = ad9361_rfpll_int_recalc_rate( + phy->ref_clk_scale[TX_RFPLL_INT], phy->clks[TX_REFCLK]->rate); + phy->clks[RX_RFPLL_DUMMY]->rate = ad9361_rfpll_dummy_recalc_rate( + phy->ref_clk_scale[RX_RFPLL_DUMMY]); + phy->clks[TX_RFPLL_DUMMY]->rate = ad9361_rfpll_dummy_recalc_rate( + phy->ref_clk_scale[TX_RFPLL_DUMMY]); + phy->clks[RX_RFPLL]->rate = ad9361_rfpll_recalc_rate( + phy->ref_clk_scale[RX_RFPLL]); + phy->clks[TX_RFPLL]->rate = ad9361_rfpll_recalc_rate( + phy->ref_clk_scale[TX_RFPLL]); + + ad9361_setup(phy); +#ifndef AXI_ADC_NOT_PRESENT + /* platform specific wrapper to call ad9361_post_setup() */ + ad9361_post_setup(phy); +#endif + + return 0; +} + +/** + * Do multi chip synchronization. + * @param phy_master The AD9361 Master state structure. + * @param phy_slave The AD9361 Slave state structure. + * @return 0 in case of success, negative error code otherwise. + * + * Note: This function will/may affect the data path. + */ +int32_t ad9361_do_mcs(struct ad9361_rf_phy *phy_master, + struct ad9361_rf_phy *phy_slave) +{ + uint32_t ensm_mode; + int32_t step; + int32_t reg; + + if ((phy_master->dev_sel == ID_AD9363A) || + (phy_slave->dev_sel == ID_AD9363A)) { + printf("%s : MCS is not supported by AD9363!\n", __func__); + return -1; + } + + reg = ad9361_spi_read(phy_master->spi, REG_RX_CLOCK_DATA_DELAY); + ad9361_spi_write(phy_slave->spi, REG_RX_CLOCK_DATA_DELAY, reg); + reg = ad9361_spi_read(phy_master->spi, REG_TX_CLOCK_DATA_DELAY); + ad9361_spi_write(phy_slave->spi, REG_TX_CLOCK_DATA_DELAY, reg); + + ad9361_get_en_state_machine_mode(phy_master, &ensm_mode); + + ad9361_set_en_state_machine_mode(phy_master, ENSM_MODE_ALERT); + ad9361_set_en_state_machine_mode(phy_slave, ENSM_MODE_ALERT); + + for (step = 0; step <= 5; step++) { + ad9361_mcs(phy_slave, step); + ad9361_mcs(phy_master, step); + mdelay(100); + } + + ad9361_set_en_state_machine_mode(phy_master, ensm_mode); + ad9361_set_en_state_machine_mode(phy_slave, ensm_mode); + + return 0; +} + +/** + * Enable/disable the TRX FIR filters. + * @param phy The AD9361 current state structure. + * @param en_dis The option (ENABLE, DISABLE). + * Accepted values: + * ENABLE (1) + * DISABLE (0) + * @return 0 in case of success, negative error code otherwise. + * + * Note: This function will/may affect the data path. + */ +int32_t ad9361_set_trx_fir_en_dis (struct ad9361_rf_phy *phy, + uint8_t en_dis) +{ + int32_t ret = 0; + + if ((phy->bypass_rx_fir == phy->bypass_tx_fir) && + (phy->bypass_rx_fir == !en_dis)) + return ret; + + phy->bypass_rx_fir = !en_dis; + phy->bypass_tx_fir = !en_dis; + ret = ad9361_validate_enable_fir(phy); + if (ret < 0) { + phy->bypass_rx_fir = true; + phy->bypass_tx_fir = true; + } + + return ret; +} + +/** + * Set the OSR rate governor. + * @param phy The AD9361 current state structure. + * @param rate_gov OSR rate governor (highest, nominal). + * Accepted values: + * HIGHEST_OSR (0 - highest OSR) + * NOMINAL_OSR (1 - nominal) + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_set_trx_rate_gov (struct ad9361_rf_phy *phy, uint32_t rate_gov) +{ + if (rate_gov == 0) + phy->rate_governor = 0; + else + phy->rate_governor = 1; + + return 0; +} + +/** + * Get the OSR rate governor. + * @param phy The AD9361 current state structure. + * @param rate_gov Option buffer. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_trx_rate_gov (struct ad9361_rf_phy *phy, uint32_t *rate_gov) +{ + *rate_gov = phy->rate_governor; + + return 0; +} + +/** + * Perform the selected calibration. + * @param phy The AD9361 state structure. + * @param cal The selected calibration (TX_QUAD_CAL, RFDC_CAL). + * Accepted values: + * TX_QUAD_CAL + * RFDC_CAL + * @param arg For TX_QUAD_CAL - the optional RX phase value overwrite (set to zero). + * @return 0 in case of success, negative error code otherwise. + * + * Note: This function will/may affect the data path. + */ +int32_t ad9361_do_calib(struct ad9361_rf_phy *phy, uint32_t cal, int32_t arg) +{ + return ad9361_do_calib_run(phy, cal, arg); +} + +/** + * Load and enable TRX FIR filters configurations. + * @param phy The AD9361 current state structure. + * @param rx_fir_cfg RX FIR filter configuration. + * @param tx_fir_cfg TX FIR filter configuration. + * @return 0 in case of success, negative error code otherwise. + * + * Note: This function will/may affect the data path. + */ +int32_t ad9361_trx_load_enable_fir(struct ad9361_rf_phy *phy, + AD9361_RXFIRConfig rx_fir_cfg, + AD9361_TXFIRConfig tx_fir_cfg) +{ + int32_t rtx = -1, rrx = -1; + + phy->filt_rx_bw_Hz = 0; + phy->filt_tx_bw_Hz = 0; + phy->filt_valid = false; + + if (tx_fir_cfg.tx_path_clks[TX_SAMPL_FREQ]) { + memcpy(phy->filt_tx_path_clks, tx_fir_cfg.tx_path_clks, + sizeof(phy->filt_tx_path_clks)); + rtx = 0; + } + + if (rx_fir_cfg.rx_path_clks[RX_SAMPL_FREQ]) { + memcpy(phy->filt_rx_path_clks, rx_fir_cfg.rx_path_clks, + sizeof(phy->filt_rx_path_clks)); + rrx = 0; + } + + if (tx_fir_cfg.tx_bandwidth) { + phy->filt_tx_bw_Hz = tx_fir_cfg.tx_bandwidth; + } + + if (rx_fir_cfg.rx_bandwidth) { + phy->filt_rx_bw_Hz = rx_fir_cfg.rx_bandwidth; + } + + ad9361_set_tx_fir_config(phy, tx_fir_cfg); + ad9361_set_rx_fir_config(phy, rx_fir_cfg); + + if (!(rrx | rtx)) + phy->filt_valid = true; + + ad9361_set_trx_fir_en_dis(phy, 1); + + return 0; +} + +/** + * Do DCXO coarse tuning. + * @param phy The AD9361 current state structure. + * @param coarse The DCXO coarse tuning value. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_do_dcxo_tune_coarse(struct ad9361_rf_phy *phy, + uint32_t coarse) +{ + phy->pdata->dcxo_coarse = coarse; + + return ad9361_set_dcxo_tune(phy, phy->pdata->dcxo_coarse, + phy->pdata->dcxo_fine); +} + +/** + * Do DCXO fine tuning. + * @param phy The AD9361 current state structure. + * @param fine The DCXO fine tuning value. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_do_dcxo_tune_fine(struct ad9361_rf_phy *phy, + uint32_t fine) +{ + phy->pdata->dcxo_fine = fine; + + return ad9361_set_dcxo_tune(phy, phy->pdata->dcxo_coarse, + phy->pdata->dcxo_fine); +} + +/** + * Get the temperature. + * @param phy The AD9361 current state structure. + * @param temp The temperature (degrees C * 1000). + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_temperature(struct ad9361_rf_phy *phy, + int32_t *temp) +{ + *temp = ad9361_get_temp(phy); + return 0; +} diff --git a/df_datalink/src/drivers/rf-transceiver/ad9361/ad9361_api.h b/df_datalink/src/drivers/rf-transceiver/ad9361/ad9361_api.h new file mode 100644 index 0000000..4879c60 --- /dev/null +++ b/df_datalink/src/drivers/rf-transceiver/ad9361/ad9361_api.h @@ -0,0 +1,552 @@ +/***************************************************************************//** + * @file ad9361_api.h + * @brief Header file of AD9361 API Driver. + * @author DBogdan (dragos.bogdan@analog.com) +******************************************************************************** + * Copyright 2013(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ +#ifndef AD9361_API_H_ +#define AD9361_API_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include "ad9361_util.h" +#include "gpio.h" +#include "spi.h" + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ +typedef struct { + /* Device selection */ + enum dev_id dev_sel; + /* Reference Clock */ + uint32_t reference_clk_rate; + /* Base Configuration */ + uint8_t two_rx_two_tx_mode_enable; /* adi,2rx-2tx-mode-enable */ + uint8_t one_rx_one_tx_mode_use_rx_num; /* adi,1rx-1tx-mode-use-rx-num */ + uint8_t one_rx_one_tx_mode_use_tx_num; /* adi,1rx-1tx-mode-use-tx-num */ + uint8_t frequency_division_duplex_mode_enable; /* adi,frequency-division-duplex-mode-enable */ + uint8_t frequency_division_duplex_independent_mode_enable; /* adi,frequency-division-duplex-independent-mode-enable */ + uint8_t tdd_use_dual_synth_mode_enable; /* adi,tdd-use-dual-synth-mode-enable */ + uint8_t tdd_skip_vco_cal_enable; /* adi,tdd-skip-vco-cal-enable */ + uint32_t tx_fastlock_delay_ns; /* adi,tx-fastlock-delay-ns */ + uint32_t rx_fastlock_delay_ns; /* adi,rx-fastlock-delay-ns */ + uint8_t rx_fastlock_pincontrol_enable; /* adi,rx-fastlock-pincontrol-enable */ + uint8_t tx_fastlock_pincontrol_enable; /* adi,tx-fastlock-pincontrol-enable */ + uint8_t external_rx_lo_enable; /* adi,external-rx-lo-enable */ + uint8_t external_tx_lo_enable; /* adi,external-tx-lo-enable */ + uint8_t dc_offset_tracking_update_event_mask; /* adi,dc-offset-tracking-update-event-mask */ + uint8_t dc_offset_attenuation_high_range; /* adi,dc-offset-attenuation-high-range */ + uint8_t dc_offset_attenuation_low_range; /* adi,dc-offset-attenuation-low-range */ + uint8_t dc_offset_count_high_range; /* adi,dc-offset-count-high-range */ + uint8_t dc_offset_count_low_range; /* adi,dc-offset-count-low-range */ + uint8_t split_gain_table_mode_enable; /* adi,split-gain-table-mode-enable */ + uint32_t trx_synthesizer_target_fref_overwrite_hz; /* adi,trx-synthesizer-target-fref-overwrite-hz */ + uint8_t qec_tracking_slow_mode_enable; /* adi,qec-tracking-slow-mode-enable */ + /* ENSM Control */ + uint8_t ensm_enable_pin_pulse_mode_enable; /* adi,ensm-enable-pin-pulse-mode-enable */ + uint8_t ensm_enable_txnrx_control_enable; /* adi,ensm-enable-txnrx-control-enable */ + /* LO Control */ + uint64_t rx_synthesizer_frequency_hz; /* adi,rx-synthesizer-frequency-hz */ + uint64_t tx_synthesizer_frequency_hz; /* adi,tx-synthesizer-frequency-hz */ + uint8_t tx_lo_powerdown_managed_enable; /* adi,tx-lo-powerdown-managed-enable */ + /* Rate & BW Control */ + uint32_t rx_path_clock_frequencies[6]; /* adi,rx-path-clock-frequencies */ + uint32_t tx_path_clock_frequencies[6]; /* adi,tx-path-clock-frequencies */ + uint32_t rf_rx_bandwidth_hz; /* adi,rf-rx-bandwidth-hz */ + uint32_t rf_tx_bandwidth_hz; /* adi,rf-tx-bandwidth-hz */ + /* RF Port Control */ + uint32_t rx_rf_port_input_select; /* adi,rx-rf-port-input-select */ + uint32_t tx_rf_port_input_select; /* adi,tx-rf-port-input-select */ + /* TX Attenuation Control */ + int32_t tx_attenuation_mdB; /* adi,tx-attenuation-mdB */ + uint8_t update_tx_gain_in_alert_enable; /* adi,update-tx-gain-in-alert-enable */ + /* Reference Clock Control */ + uint8_t xo_disable_use_ext_refclk_enable; /* adi,xo-disable-use-ext-refclk-enable */ + uint32_t dcxo_coarse_and_fine_tune[2]; /* adi,dcxo-coarse-and-fine-tune */ + uint32_t clk_output_mode_select; /* adi,clk-output-mode-select */ + /* Gain Control */ + uint8_t gc_rx1_mode; /* adi,gc-rx1-mode */ + uint8_t gc_rx2_mode; /* adi,gc-rx2-mode */ + uint8_t gc_adc_large_overload_thresh; /* adi,gc-adc-large-overload-thresh */ + uint8_t gc_adc_ovr_sample_size; /* adi,gc-adc-ovr-sample-size */ + uint8_t gc_adc_small_overload_thresh; /* adi,gc-adc-small-overload-thresh */ + uint16_t gc_dec_pow_measurement_duration; /* adi,gc-dec-pow-measurement-duration */ + uint8_t gc_dig_gain_enable; /* adi,gc-dig-gain-enable */ + uint16_t gc_lmt_overload_high_thresh; /* adi,gc-lmt-overload-high-thresh */ + uint16_t gc_lmt_overload_low_thresh; /* adi,gc-lmt-overload-low-thresh */ + uint8_t gc_low_power_thresh; /* adi,gc-low-power-thresh */ + uint8_t gc_max_dig_gain; /* adi,gc-max-dig-gain */ + uint8_t gc_use_rx_fir_out_for_dec_pwr_meas_enable; /* adi,gc-use-rx-fir-out-for-dec-pwr-meas-enable */ + /* Gain MGC Control */ + uint8_t mgc_dec_gain_step; /* adi,mgc-dec-gain-step */ + uint8_t mgc_inc_gain_step; /* adi,mgc-inc-gain-step */ + uint8_t mgc_rx1_ctrl_inp_enable; /* adi,mgc-rx1-ctrl-inp-enable */ + uint8_t mgc_rx2_ctrl_inp_enable; /* adi,mgc-rx2-ctrl-inp-enable */ + uint8_t mgc_split_table_ctrl_inp_gain_mode; /* adi,mgc-split-table-ctrl-inp-gain-mode */ + /* Gain AGC Control */ + uint8_t agc_adc_large_overload_exceed_counter; /* adi,agc-adc-large-overload-exceed-counter */ + uint8_t agc_adc_large_overload_inc_steps; /* adi,agc-adc-large-overload-inc-steps - Name is misleading should be dec-steps*/ + uint8_t agc_adc_lmt_small_overload_prevent_gain_inc_enable; /* adi,agc-adc-lmt-small-overload-prevent-gain-inc-enable */ + uint8_t agc_adc_small_overload_exceed_counter; /* adi,agc-adc-small-overload-exceed-counter */ + uint8_t agc_dig_gain_step_size; /* adi,agc-dig-gain-step-size */ + uint8_t agc_dig_saturation_exceed_counter; /* adi,agc-dig-saturation-exceed-counter */ + uint32_t agc_gain_update_interval_us; /* adi,agc-gain-update-interval-us */ + uint8_t agc_immed_gain_change_if_large_adc_overload_enable; /* adi,agc-immed-gain-change-if-large-adc-overload-enable */ + uint8_t agc_immed_gain_change_if_large_lmt_overload_enable; /* adi,agc-immed-gain-change-if-large-lmt-overload-enable */ + uint8_t agc_inner_thresh_high; /* adi,agc-inner-thresh-high */ + uint8_t agc_inner_thresh_high_dec_steps; /* adi,agc-inner-thresh-high-dec-steps */ + uint8_t agc_inner_thresh_low; /* adi,agc-inner-thresh-low */ + uint8_t agc_inner_thresh_low_inc_steps; /* adi,agc-inner-thresh-low-inc-steps */ + uint8_t agc_lmt_overload_large_exceed_counter; /* adi,agc-lmt-overload-large-exceed-counter */ + uint8_t agc_lmt_overload_large_inc_steps; /* adi,agc-lmt-overload-large-inc-steps */ + uint8_t agc_lmt_overload_small_exceed_counter; /* adi,agc-lmt-overload-small-exceed-counter */ + uint8_t agc_outer_thresh_high; /* adi,agc-outer-thresh-high */ + uint8_t agc_outer_thresh_high_dec_steps; /* adi,agc-outer-thresh-high-dec-steps */ + uint8_t agc_outer_thresh_low; /* adi,agc-outer-thresh-low */ + uint8_t agc_outer_thresh_low_inc_steps; /* adi,agc-outer-thresh-low-inc-steps */ + uint32_t agc_attack_delay_extra_margin_us; /* adi,agc-attack-delay-extra-margin-us */ + uint8_t agc_sync_for_gain_counter_enable; /* adi,agc-sync-for-gain-counter-enable */ + /* Fast AGC */ + uint32_t fagc_dec_pow_measuremnt_duration; /* adi,fagc-dec-pow-measurement-duration */ + uint32_t fagc_state_wait_time_ns; /* adi,fagc-state-wait-time-ns */ + /* Fast AGC - Low Power */ + uint8_t fagc_allow_agc_gain_increase; /* adi,fagc-allow-agc-gain-increase-enable */ + uint32_t fagc_lp_thresh_increment_time; /* adi,fagc-lp-thresh-increment-time */ + uint32_t fagc_lp_thresh_increment_steps; /* adi,fagc-lp-thresh-increment-steps */ + /* Fast AGC - Lock Level (Lock Level is set via slow AGC inner high threshold) */ + uint8_t fagc_lock_level_lmt_gain_increase_en; /* adi,fagc-lock-level-lmt-gain-increase-enable */ + uint32_t fagc_lock_level_gain_increase_upper_limit; /* adi,fagc-lock-level-gain-increase-upper-limit */ + /* Fast AGC - Peak Detectors and Final Settling */ + uint32_t fagc_lpf_final_settling_steps; /* adi,fagc-lpf-final-settling-steps */ + uint32_t fagc_lmt_final_settling_steps; /* adi,fagc-lmt-final-settling-steps */ + uint32_t fagc_final_overrange_count; /* adi,fagc-final-overrange-count */ + /* Fast AGC - Final Power Test */ + uint8_t fagc_gain_increase_after_gain_lock_en; /* adi,fagc-gain-increase-after-gain-lock-enable */ + /* Fast AGC - Unlocking the Gain */ + uint32_t fagc_gain_index_type_after_exit_rx_mode; /* adi,fagc-gain-index-type-after-exit-rx-mode */ + uint8_t fagc_use_last_lock_level_for_set_gain_en; /* adi,fagc-use-last-lock-level-for-set-gain-enable */ + uint8_t fagc_rst_gla_stronger_sig_thresh_exceeded_en; /* adi,fagc-rst-gla-stronger-sig-thresh-exceeded-enable */ + uint32_t fagc_optimized_gain_offset; /* adi,fagc-optimized-gain-offset */ + uint32_t fagc_rst_gla_stronger_sig_thresh_above_ll; /* adi,fagc-rst-gla-stronger-sig-thresh-above-ll */ + uint8_t fagc_rst_gla_engergy_lost_sig_thresh_exceeded_en; /* adi,fagc-rst-gla-engergy-lost-sig-thresh-exceeded-enable */ + uint8_t fagc_rst_gla_engergy_lost_goto_optim_gain_en; /* adi,fagc-rst-gla-engergy-lost-goto-optim-gain-enable */ + uint32_t fagc_rst_gla_engergy_lost_sig_thresh_below_ll; /* adi,fagc-rst-gla-engergy-lost-sig-thresh-below-ll */ + uint32_t fagc_energy_lost_stronger_sig_gain_lock_exit_cnt; /* adi,fagc-energy-lost-stronger-sig-gain-lock-exit-cnt */ + uint8_t fagc_rst_gla_large_adc_overload_en; /* adi,fagc-rst-gla-large-adc-overload-enable */ + uint8_t fagc_rst_gla_large_lmt_overload_en; /* adi,fagc-rst-gla-large-lmt-overload-enable */ + uint8_t fagc_rst_gla_en_agc_pulled_high_en; /* adi,fagc-rst-gla-en-agc-pulled-high-enable */ + uint32_t fagc_rst_gla_if_en_agc_pulled_high_mode; /* adi,fagc-rst-gla-if-en-agc-pulled-high-mode */ + uint32_t fagc_power_measurement_duration_in_state5; /* adi,fagc-power-measurement-duration-in-state5 */ + uint32_t fagc_large_overload_inc_steps; /* adi,fagc-adc-large-overload-inc-steps - Name is misleading should be dec-steps */ + /* RSSI Control */ + uint32_t rssi_delay; /* adi,rssi-delay */ + uint32_t rssi_duration; /* adi,rssi-duration */ + uint8_t rssi_restart_mode; /* adi,rssi-restart-mode */ + uint8_t rssi_unit_is_rx_samples_enable; /* adi,rssi-unit-is-rx-samples-enable */ + uint32_t rssi_wait; /* adi,rssi-wait */ + /* Aux ADC Control */ + uint32_t aux_adc_decimation; /* adi,aux-adc-decimation */ + uint32_t aux_adc_rate; /* adi,aux-adc-rate */ + /* AuxDAC Control */ + uint8_t aux_dac_manual_mode_enable; /* adi,aux-dac-manual-mode-enable */ + uint32_t aux_dac1_default_value_mV; /* adi,aux-dac1-default-value-mV */ + uint8_t aux_dac1_active_in_rx_enable; /* adi,aux-dac1-active-in-rx-enable */ + uint8_t aux_dac1_active_in_tx_enable; /* adi,aux-dac1-active-in-tx-enable */ + uint8_t aux_dac1_active_in_alert_enable; /* adi,aux-dac1-active-in-alert-enable */ + uint32_t aux_dac1_rx_delay_us; /* adi,aux-dac1-rx-delay-us */ + uint32_t aux_dac1_tx_delay_us; /* adi,aux-dac1-tx-delay-us */ + uint32_t aux_dac2_default_value_mV; /* adi,aux-dac2-default-value-mV */ + uint8_t aux_dac2_active_in_rx_enable; /* adi,aux-dac2-active-in-rx-enable */ + uint8_t aux_dac2_active_in_tx_enable; /* adi,aux-dac2-active-in-tx-enable */ + uint8_t aux_dac2_active_in_alert_enable; /* adi,aux-dac2-active-in-alert-enable */ + uint32_t aux_dac2_rx_delay_us; /* adi,aux-dac2-rx-delay-us */ + uint32_t aux_dac2_tx_delay_us; /* adi,aux-dac2-tx-delay-us */ + /* Temperature Sensor Control */ + uint32_t temp_sense_decimation; /* adi,temp-sense-decimation */ + uint16_t temp_sense_measurement_interval_ms; /* adi,temp-sense-measurement-interval-ms */ + int8_t temp_sense_offset_signed; /* adi,temp-sense-offset-signed */ + uint8_t temp_sense_periodic_measurement_enable; /* adi,temp-sense-periodic-measurement-enable */ + /* Control Out Setup */ + uint8_t ctrl_outs_enable_mask; /* adi,ctrl-outs-enable-mask */ + uint8_t ctrl_outs_index; /* adi,ctrl-outs-index */ + /* External LNA Control */ + uint32_t elna_settling_delay_ns; /* adi,elna-settling-delay-ns */ + uint32_t elna_gain_mdB; /* adi,elna-gain-mdB */ + uint32_t elna_bypass_loss_mdB; /* adi,elna-bypass-loss-mdB */ + uint8_t elna_rx1_gpo0_control_enable; /* adi,elna-rx1-gpo0-control-enable */ + uint8_t elna_rx2_gpo1_control_enable; /* adi,elna-rx2-gpo1-control-enable */ + uint8_t elna_gaintable_all_index_enable; /* adi,elna-gaintable-all-index-enable */ + /* Digital Interface Control */ + uint8_t digital_interface_tune_skip_mode; /* adi,digital-interface-tune-skip-mode */ + uint8_t digital_interface_tune_fir_disable; /* adi,digital-interface-tune-fir-disable */ + uint8_t pp_tx_swap_enable; /* adi,pp-tx-swap-enable */ + uint8_t pp_rx_swap_enable; /* adi,pp-rx-swap-enable */ + uint8_t tx_channel_swap_enable; /* adi,tx-channel-swap-enable */ + uint8_t rx_channel_swap_enable; /* adi,rx-channel-swap-enable */ + uint8_t rx_frame_pulse_mode_enable; /* adi,rx-frame-pulse-mode-enable */ + uint8_t two_t_two_r_timing_enable; /* adi,2t2r-timing-enable */ + uint8_t invert_data_bus_enable; /* adi,invert-data-bus-enable */ + uint8_t invert_data_clk_enable; /* adi,invert-data-clk-enable */ + uint8_t fdd_alt_word_order_enable; /* adi,fdd-alt-word-order-enable */ + uint8_t invert_rx_frame_enable; /* adi,invert-rx-frame-enable */ + uint8_t fdd_rx_rate_2tx_enable; /* adi,fdd-rx-rate-2tx-enable */ + uint8_t swap_ports_enable; /* adi,swap-ports-enable */ + uint8_t single_data_rate_enable; /* adi,single-data-rate-enable */ + uint8_t lvds_mode_enable; /* adi,lvds-mode-enable */ + uint8_t half_duplex_mode_enable; /* adi,half-duplex-mode-enable */ + uint8_t single_port_mode_enable; /* adi,single-port-mode-enable */ + uint8_t full_port_enable; /* adi,full-port-enable */ + uint8_t full_duplex_swap_bits_enable; /* adi,full-duplex-swap-bits-enable */ + uint32_t delay_rx_data; /* adi,delay-rx-data */ + uint32_t rx_data_clock_delay; /* adi,rx-data-clock-delay */ + uint32_t rx_data_delay; /* adi,rx-data-delay */ + uint32_t tx_fb_clock_delay; /* adi,tx-fb-clock-delay */ + uint32_t tx_data_delay; /* adi,tx-data-delay */ + uint32_t lvds_bias_mV; /* adi,lvds-bias-mV */ + uint8_t lvds_rx_onchip_termination_enable; /* adi,lvds-rx-onchip-termination-enable */ + uint8_t rx1rx2_phase_inversion_en; /* adi,rx1-rx2-phase-inversion-enable */ + uint8_t lvds_invert1_control; /* adi,lvds-invert1-control */ + uint8_t lvds_invert2_control; /* adi,lvds-invert2-control */ + /* GPO Control */ + uint8_t gpo_manual_mode_enable; /* adi,gpo-manual-mode-enable */ + uint32_t gpo_manual_mode_enable_mask; /* adi,gpo-manual-mode-enable-mask */ + uint8_t gpo0_inactive_state_high_enable; /* adi,gpo0-inactive-state-high-enable */ + uint8_t gpo1_inactive_state_high_enable; /* adi,gpo1-inactive-state-high-enable */ + uint8_t gpo2_inactive_state_high_enable; /* adi,gpo2-inactive-state-high-enable */ + uint8_t gpo3_inactive_state_high_enable; /* adi,gpo3-inactive-state-high-enable */ + uint8_t gpo0_slave_rx_enable; /* adi,gpo0-slave-rx-enable */ + uint8_t gpo0_slave_tx_enable; /* adi,gpo0-slave-tx-enable */ + uint8_t gpo1_slave_rx_enable; /* adi,gpo1-slave-rx-enable */ + uint8_t gpo1_slave_tx_enable; /* adi,gpo1-slave-tx-enable */ + uint8_t gpo2_slave_rx_enable; /* adi,gpo2-slave-rx-enable */ + uint8_t gpo2_slave_tx_enable; /* adi,gpo2-slave-tx-enable */ + uint8_t gpo3_slave_rx_enable; /* adi,gpo3-slave-rx-enable */ + uint8_t gpo3_slave_tx_enable; /* adi,gpo3-slave-tx-enable */ + uint8_t gpo0_rx_delay_us; /* adi,gpo0-rx-delay-us */ + uint8_t gpo0_tx_delay_us; /* adi,gpo0-tx-delay-us */ + uint8_t gpo1_rx_delay_us; /* adi,gpo1-rx-delay-us */ + uint8_t gpo1_tx_delay_us; /* adi,gpo1-tx-delay-us */ + uint8_t gpo2_rx_delay_us; /* adi,gpo2-rx-delay-us */ + uint8_t gpo2_tx_delay_us; /* adi,gpo2-tx-delay-us */ + uint8_t gpo3_rx_delay_us; /* adi,gpo3-rx-delay-us */ + uint8_t gpo3_tx_delay_us; /* adi,gpo3-tx-delay-us */ + /* Tx Monitor Control */ + uint32_t low_high_gain_threshold_mdB; /* adi,txmon-low-high-thresh */ + uint32_t low_gain_dB; /* adi,txmon-low-gain */ + uint32_t high_gain_dB; /* adi,txmon-high-gain */ + uint8_t tx_mon_track_en; /* adi,txmon-dc-tracking-enable */ + uint8_t one_shot_mode_en; /* adi,txmon-one-shot-mode-enable */ + uint32_t tx_mon_delay; /* adi,txmon-delay */ + uint32_t tx_mon_duration; /* adi,txmon-duration */ + uint32_t tx1_mon_front_end_gain; /* adi,txmon-1-front-end-gain */ + uint32_t tx2_mon_front_end_gain; /* adi,txmon-2-front-end-gain */ + uint32_t tx1_mon_lo_cm; /* adi,txmon-1-lo-cm */ + uint32_t tx2_mon_lo_cm; /* adi,txmon-2-lo-cm */ + /* GPIO definitions */ + struct gpio_init_param gpio_resetb; /* reset-gpios */ + /* MCS Sync */ + struct gpio_init_param gpio_sync; /* sync-gpios */ + struct gpio_init_param gpio_cal_sw1; /* cal-sw1-gpios */ + struct gpio_init_param gpio_cal_sw2; /* cal-sw2-gpios */ + + struct spi_init_param spi_param; + + /* External LO clocks */ + uint32_t (*ad9361_rfpll_ext_recalc_rate)(struct refclk_scale *clk_priv); + int32_t (*ad9361_rfpll_ext_round_rate)(struct refclk_scale *clk_priv, + uint32_t rate); + int32_t (*ad9361_rfpll_ext_set_rate)(struct refclk_scale *clk_priv, + uint32_t rate); + +} AD9361_InitParam; + +typedef struct { + uint32_t rx; /* 1, 2, 3(both) */ + int32_t rx_gain; /* -12, -6, 0, 6 */ + uint32_t rx_dec; /* 1, 2, 4 */ + int16_t rx_coef[128]; + uint8_t rx_coef_size; + uint32_t rx_path_clks[6]; + uint32_t rx_bandwidth; +} AD9361_RXFIRConfig; + +typedef struct { + uint32_t tx; /* 1, 2, 3(both) */ + int32_t tx_gain; /* -6, 0 */ + uint32_t tx_int; /* 1, 2, 4 */ + int16_t tx_coef[128]; + uint8_t tx_coef_size; + uint32_t tx_path_clks[6]; + uint32_t tx_bandwidth; +} AD9361_TXFIRConfig; + +enum ad9361_ensm_mode { + ENSM_MODE_TX, + ENSM_MODE_RX, + ENSM_MODE_ALERT, + ENSM_MODE_FDD, + ENSM_MODE_WAIT, + ENSM_MODE_SLEEP, + ENSM_MODE_PINCTRL, + ENSM_MODE_PINCTRL_FDD_INDEP, +}; + +#define ENABLE 1 +#define DISABLE 0 + +#define RX1 0 +#define RX2 1 + +#define TX1 0 +#define TX2 1 + +#define A_BALANCED 0 +#define B_BALANCED 1 +#define C_BALANCED 2 +#define A_N 3 +#define A_P 4 +#define B_N 5 +#define B_P 6 +#define C_N 7 +#define C_P 8 +#define TX_MON1 9 +#define TX_MON2 10 +#define TX_MON1_2 11 + +#define TXA 0 +#define TXB 1 + +#define MODE_1x1 1 +#define MODE_2x2 2 + +#define HIGHEST_OSR 0 +#define NOMINAL_OSR 1 + +#define INT_LO 0 +#define EXT_LO 1 + +#define ON 0 +#define OFF 1 + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ +/* Initialize the AD9361 part. */ +int32_t ad9361_init (struct ad9361_rf_phy **ad9361_phy, + AD9361_InitParam *init_param); +/* Free the allocated resources. */ +int32_t ad9361_remove(struct ad9361_rf_phy *phy); +/* Set the Enable State Machine (ENSM) mode. */ +int32_t ad9361_set_en_state_machine_mode (struct ad9361_rf_phy *phy, + uint32_t mode); +/* Get the Enable State Machine (ENSM) mode. */ +int32_t ad9361_get_en_state_machine_mode (struct ad9361_rf_phy *phy, + uint32_t *mode); +/* Set the receive RF gain for the selected channel. */ +int32_t ad9361_set_rx_rf_gain (struct ad9361_rf_phy *phy, uint8_t ch, + int32_t gain_db); +/* Get current receive RF gain for the selected channel. */ +int32_t ad9361_get_rx_rf_gain (struct ad9361_rf_phy *phy, uint8_t ch, + int32_t *gain_db); +/* Set the RX RF bandwidth. */ +int32_t ad9361_set_rx_rf_bandwidth (struct ad9361_rf_phy *phy, + uint32_t bandwidth_hz); +/* Get the RX RF bandwidth. */ +int32_t ad9361_get_rx_rf_bandwidth (struct ad9361_rf_phy *phy, + uint32_t *bandwidth_hz); +/* Set the RX sampling frequency. */ +int32_t ad9361_set_rx_sampling_freq (struct ad9361_rf_phy *phy, + uint32_t sampling_freq_hz); +/* Get current RX sampling frequency. */ +int32_t ad9361_get_rx_sampling_freq (struct ad9361_rf_phy *phy, + uint32_t *sampling_freq_hz); +/* Set the RX LO frequency. */ +int32_t ad9361_set_rx_lo_freq (struct ad9361_rf_phy *phy, uint64_t lo_freq_hz); +/* Get current RX LO frequency. */ +int32_t ad9361_get_rx_lo_freq (struct ad9361_rf_phy *phy, uint64_t *lo_freq_hz); +/* Switch between internal and external LO. */ +int32_t ad9361_set_rx_lo_int_ext(struct ad9361_rf_phy *phy, uint8_t int_ext); +/* Get the RSSI for the selected channel. */ +int32_t ad9361_get_rx_rssi (struct ad9361_rf_phy *phy, uint8_t ch, + struct rf_rssi *rssi); +/* Set the gain control mode for the selected channel. */ +int32_t ad9361_set_rx_gain_control_mode (struct ad9361_rf_phy *phy, uint8_t ch, + uint8_t gc_mode); +/* Get the gain control mode for the selected channel. */ +int32_t ad9361_get_rx_gain_control_mode (struct ad9361_rf_phy *phy, uint8_t ch, + uint8_t *gc_mode); +/* Set the RX FIR filter configuration. */ +int32_t ad9361_set_rx_fir_config (struct ad9361_rf_phy *phy, + AD9361_RXFIRConfig fir_cfg); +/* Get the RX FIR filter configuration. */ +int32_t ad9361_get_rx_fir_config(struct ad9361_rf_phy *phy, uint8_t rx_ch, + AD9361_RXFIRConfig *fir_cfg); +/* Enable/disable the RX FIR filter. */ +int32_t ad9361_set_rx_fir_en_dis (struct ad9361_rf_phy *phy, uint8_t en_dis); +/* Get the status of the RX FIR filter. */ +int32_t ad9361_get_rx_fir_en_dis (struct ad9361_rf_phy *phy, uint8_t *en_dis); +/* Enable/disable the RX RFDC Tracking. */ +int32_t ad9361_set_rx_rfdc_track_en_dis (struct ad9361_rf_phy *phy, + uint8_t en_dis); +/* Get the status of the RX RFDC Tracking. */ +int32_t ad9361_get_rx_rfdc_track_en_dis (struct ad9361_rf_phy *phy, + uint8_t *en_dis); +/* Enable/disable the RX BasebandDC Tracking. */ +int32_t ad9361_set_rx_bbdc_track_en_dis (struct ad9361_rf_phy *phy, + uint8_t en_dis); +/* Get the status of the RX BasebandDC Tracking. */ +int32_t ad9361_get_rx_bbdc_track_en_dis (struct ad9361_rf_phy *phy, + uint8_t *en_dis); +/* Enable/disable the RX Quadrature Tracking. */ +int32_t ad9361_set_rx_quad_track_en_dis (struct ad9361_rf_phy *phy, + uint8_t en_dis); +/* Get the status of the RX Quadrature Tracking. */ +int32_t ad9361_get_rx_quad_track_en_dis (struct ad9361_rf_phy *phy, + uint8_t *en_dis); +/* Set the RX RF input port. */ +int32_t ad9361_set_rx_rf_port_input (struct ad9361_rf_phy *phy, uint32_t mode); +/* Get the selected RX RF input port. */ +int32_t ad9361_get_rx_rf_port_input (struct ad9361_rf_phy *phy, uint32_t *mode); +/* Store RX fastlock profile. */ +int32_t ad9361_rx_fastlock_store(struct ad9361_rf_phy *phy, uint32_t profile); +/* Recall RX fastlock profile. */ +int32_t ad9361_rx_fastlock_recall(struct ad9361_rf_phy *phy, uint32_t profile); +/* Load RX fastlock profile. */ +int32_t ad9361_rx_fastlock_load(struct ad9361_rf_phy *phy, uint32_t profile, + uint8_t *values); +/* Save RX fastlock profile. */ +int32_t ad9361_rx_fastlock_save(struct ad9361_rf_phy *phy, uint32_t profile, + uint8_t *values); +/* Power down the RX Local Oscillator. */ +int32_t ad9361_rx_lo_powerdown(struct ad9361_rf_phy *phy, uint8_t option); +/* Get the RX Local Oscillator power status. */ +int32_t ad9361_get_rx_lo_power(struct ad9361_rf_phy *phy, uint8_t *option); +/* Set the transmit attenuation for the selected channel. */ +int32_t ad9361_set_tx_attenuation (struct ad9361_rf_phy *phy, uint8_t ch, + uint32_t attenuation_mdb); +/* Get current transmit attenuation for the selected channel. */ +int32_t ad9361_get_tx_attenuation (struct ad9361_rf_phy *phy, uint8_t ch, + uint32_t *attenuation_mdb); +/* Set the TX RF bandwidth. */ +int32_t ad9361_set_tx_rf_bandwidth (struct ad9361_rf_phy *phy, + uint32_t bandwidth_hz); +/* Get the TX RF bandwidth. */ +int32_t ad9361_get_tx_rf_bandwidth (struct ad9361_rf_phy *phy, + uint32_t *bandwidth_hz); +/* Set the TX sampling frequency. */ +int32_t ad9361_set_tx_sampling_freq (struct ad9361_rf_phy *phy, + uint32_t sampling_freq_hz); +/* Get current TX sampling frequency. */ +int32_t ad9361_get_tx_sampling_freq (struct ad9361_rf_phy *phy, + uint32_t *sampling_freq_hz); +/* Set the TX LO frequency. */ +int32_t ad9361_set_tx_lo_freq (struct ad9361_rf_phy *phy, uint64_t lo_freq_hz); +/* Get current TX LO frequency. */ +int32_t ad9361_get_tx_lo_freq (struct ad9361_rf_phy *phy, uint64_t *lo_freq_hz); +/* Switch between internal and external LO. */ +int32_t ad9361_set_tx_lo_int_ext(struct ad9361_rf_phy *phy, uint8_t int_ext); +/* Set the TX FIR filter configuration. */ +int32_t ad9361_set_tx_fir_config (struct ad9361_rf_phy *phy, + AD9361_TXFIRConfig fir_cfg); +/* Get the TX FIR filter configuration. */ +int32_t ad9361_get_tx_fir_config(struct ad9361_rf_phy *phy, uint8_t tx_ch, + AD9361_TXFIRConfig *fir_cfg); +/* Enable/disable the TX FIR filter. */ +int32_t ad9361_set_tx_fir_en_dis (struct ad9361_rf_phy *phy, uint8_t en_dis); +/* Get the status of the TX FIR filter. */ +int32_t ad9361_get_tx_fir_en_dis (struct ad9361_rf_phy *phy, uint8_t *en_dis); +/* Get the TX RSSI for the selected channel. */ +int32_t ad9361_get_tx_rssi (struct ad9361_rf_phy *phy, uint8_t ch, + uint32_t *rssi_db_x_1000); +/* Set the TX RF output port. */ +int32_t ad9361_set_tx_rf_port_output (struct ad9361_rf_phy *phy, uint32_t mode); +/* Get the selected TX RF output port. */ +int32_t ad9361_get_tx_rf_port_output (struct ad9361_rf_phy *phy, + uint32_t *mode); +/* Enable/disable the auto calibration. */ +int32_t ad9361_set_tx_auto_cal_en_dis (struct ad9361_rf_phy *phy, + uint8_t en_dis); +/* Get the status of the auto calibration flag. */ +int32_t ad9361_get_tx_auto_cal_en_dis (struct ad9361_rf_phy *phy, + uint8_t *en_dis); +/* Store TX fastlock profile. */ +int32_t ad9361_tx_fastlock_store(struct ad9361_rf_phy *phy, uint32_t profile); +/* Recall TX fastlock profile. */ +int32_t ad9361_tx_fastlock_recall(struct ad9361_rf_phy *phy, uint32_t profile); +/* Load TX fastlock profile. */ +int32_t ad9361_tx_fastlock_load(struct ad9361_rf_phy *phy, uint32_t profile, + uint8_t *values); +/* Save TX fastlock profile. */ +int32_t ad9361_tx_fastlock_save(struct ad9361_rf_phy *phy, uint32_t profile, + uint8_t *values); +/* Power down the TX Local Oscillator. */ +int32_t ad9361_tx_lo_powerdown(struct ad9361_rf_phy *phy, uint8_t option); +/* Get the TX Local Oscillator power status. */ +int32_t ad9361_get_tx_lo_power(struct ad9361_rf_phy *phy, uint8_t *option); +/* Set the RX and TX path rates. */ +int32_t ad9361_set_trx_path_clks(struct ad9361_rf_phy *phy, + uint32_t *rx_path_clks, uint32_t *tx_path_clks); +/* Get the RX and TX path rates. */ +int32_t ad9361_get_trx_path_clks(struct ad9361_rf_phy *phy, + uint32_t *rx_path_clks, uint32_t *tx_path_clks); +/* Set the number of channels mode. */ +int32_t ad9361_set_no_ch_mode(struct ad9361_rf_phy *phy, uint8_t no_ch_mode); +/* Do multi chip synchronization. */ +int32_t ad9361_do_mcs(struct ad9361_rf_phy *phy_master, + struct ad9361_rf_phy *phy_slave); +/* Enable/disable the TRX FIR filters. */ +int32_t ad9361_set_trx_fir_en_dis (struct ad9361_rf_phy *phy, uint8_t en_dis); +/* Set the OSR rate governor. */ +int32_t ad9361_set_trx_rate_gov (struct ad9361_rf_phy *phy, uint32_t rate_gov); +/* Get the OSR rate governor. */ +int32_t ad9361_get_trx_rate_gov (struct ad9361_rf_phy *phy, uint32_t *rate_gov); +/* Perform the selected calibration. */ +int32_t ad9361_do_calib(struct ad9361_rf_phy *phy, uint32_t cal, int32_t arg); +/* Load and enable TRX FIR filters configurations. */ +int32_t ad9361_trx_load_enable_fir(struct ad9361_rf_phy *phy, + AD9361_RXFIRConfig rx_fir_cfg, + AD9361_TXFIRConfig tx_fir_cfg); +/* Do DCXO coarse tuning. */ +int32_t ad9361_do_dcxo_tune_coarse(struct ad9361_rf_phy *phy, + uint32_t coarse); +/* Do DCXO fine tuning. */ +int32_t ad9361_do_dcxo_tune_fine(struct ad9361_rf_phy *phy, + uint32_t fine); +/* Get the temperature. */ +int32_t ad9361_get_temperature(struct ad9361_rf_phy *phy, + int32_t *temp); +#endif diff --git a/df_datalink/src/drivers/rf-transceiver/ad9361/ad9361_conv.c b/df_datalink/src/drivers/rf-transceiver/ad9361/ad9361_conv.c new file mode 100644 index 0000000..bbcfee5 --- /dev/null +++ b/df_datalink/src/drivers/rf-transceiver/ad9361/ad9361_conv.c @@ -0,0 +1,86 @@ + +/***************************************************************************//** + * @file ad9361_conv.c + * @brief Implementation of AD9361 Conv Driver. +******************************************************************************** + * Copyright 2014-2015(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include +#include +#include "ad9361.h" +#include "ad9361_util.h" +#include "delay.h" +#include "../../../config/app_config.h" + +/******************************************************************************/ +/********************** Macros and Constants Definitions **********************/ +/******************************************************************************/ + +/** + * HDL loopback enable/disable. + * @param phy The AD9361 state structure. + * @param enable Enable/disable option. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_hdl_loopback(struct ad9361_rf_phy *phy, bool enable) +{ + return -ENODEV; +} + +/** + * Digital tune. + * @param phy The AD9361 state structure. + * @param max_freq Maximum frequency. + * @param flags Flags: BE_VERBOSE, BE_MOREVERBOSE, DO_IDELAY, DO_ODELAY. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_dig_tune(struct ad9361_rf_phy *phy, uint32_t max_freq, + enum dig_tune_flags flags) +{ + return 0; +} + +/** +* Setup the AD9361 device. +* @param phy The AD9361 state structure. +* @return 0 in case of success, negative error code otherwise. +*/ +int32_t ad9361_post_setup(struct ad9361_rf_phy *phy) +{ + return 0; +} diff --git a/df_datalink/src/drivers/rf-transceiver/ad9361/ad9361_util.c b/df_datalink/src/drivers/rf-transceiver/ad9361/ad9361_util.c new file mode 100644 index 0000000..a49e146 --- /dev/null +++ b/df_datalink/src/drivers/rf-transceiver/ad9361/ad9361_util.c @@ -0,0 +1,335 @@ +/***************************************************************************//** + * @file ad9361_util.c + * @brief AD9361 Implementation of Util Driver. + * @author DBogdan (dragos.bogdan@analog.com) +******************************************************************************** + * Copyright 2013(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include +#include "ad9361_util.h" +#include "../../../include/delay.h" + +/******************************************************************************/ +/*************************** Macros Definitions *******************************/ +/******************************************************************************/ +#define BITS_PER_LONG 32 + +/***************************************************************************//** + * @brief clk_prepare_enable +*******************************************************************************/ +int32_t clk_prepare_enable(struct clk *clk) +{ + if (clk) { + // Unused variable - fix compiler warning + } + + return 0; +} + +/***************************************************************************//** + * @brief clk_get_rate +*******************************************************************************/ +uint32_t clk_get_rate(struct ad9361_rf_phy *phy, + struct refclk_scale *clk_priv) +{ + uint32_t rate = 0; + uint32_t source; + + source = clk_priv->source; + + switch (source) { + case TX_REFCLK: + case RX_REFCLK: + case BB_REFCLK: + rate = ad9361_clk_factor_recalc_rate(clk_priv, + phy->clk_refin->rate); + break; + case TX_RFPLL_INT: + case RX_RFPLL_INT: + rate = ad9361_rfpll_int_recalc_rate(clk_priv, + phy->clks[clk_priv->parent_source]->rate); + break; + case RX_RFPLL_DUMMY: + case TX_RFPLL_DUMMY: + rate = ad9361_rfpll_dummy_recalc_rate(clk_priv); + break; + case TX_RFPLL: + case RX_RFPLL: + rate = ad9361_rfpll_recalc_rate(clk_priv); + break; + case BBPLL_CLK: + rate = ad9361_bbpll_recalc_rate(clk_priv, + phy->clks[clk_priv->parent_source]->rate); + break; + case ADC_CLK: + case R2_CLK: + case R1_CLK: + case CLKRF_CLK: + case RX_SAMPL_CLK: + case DAC_CLK: + case T2_CLK: + case T1_CLK: + case CLKTF_CLK: + case TX_SAMPL_CLK: + rate = ad9361_clk_factor_recalc_rate(clk_priv, + phy->clks[clk_priv->parent_source]->rate); + break; + default: + break; + } + + return rate; +} + +/***************************************************************************//** + * @brief clk_set_rate +*******************************************************************************/ +int32_t clk_set_rate(struct ad9361_rf_phy *phy, + struct refclk_scale *clk_priv, + uint32_t rate) +{ + uint32_t source; + int32_t i; + uint32_t round_rate; + + source = clk_priv->source; + if(phy->clks[source]->rate != rate) + { + switch (source) { + case TX_REFCLK: + case RX_REFCLK: + case BB_REFCLK: + round_rate = ad9361_clk_factor_round_rate(clk_priv, rate, + &phy->clk_refin->rate); + ad9361_clk_factor_set_rate(clk_priv, round_rate, + phy->clk_refin->rate); + phy->clks[source]->rate = ad9361_clk_factor_recalc_rate(clk_priv, + phy->clk_refin->rate); + break; + case TX_RFPLL_INT: + case RX_RFPLL_INT: + round_rate = ad9361_rfpll_int_round_rate(clk_priv, rate, + &phy->clks[clk_priv->parent_source]->rate); + ad9361_rfpll_int_set_rate(clk_priv, round_rate, + phy->clks[clk_priv->parent_source]->rate); + phy->clks[source]->rate = ad9361_rfpll_int_recalc_rate(clk_priv, + phy->clks[clk_priv->parent_source]->rate); + break; + case RX_RFPLL_DUMMY: + case TX_RFPLL_DUMMY: + ad9361_rfpll_dummy_set_rate(clk_priv, rate); + break; + case TX_RFPLL: + case RX_RFPLL: + round_rate = ad9361_rfpll_round_rate(clk_priv, rate); + ad9361_rfpll_set_rate(clk_priv, round_rate); + phy->clks[source]->rate = ad9361_rfpll_recalc_rate(clk_priv); + break; + case BBPLL_CLK: + round_rate = ad9361_bbpll_round_rate(clk_priv, rate, + &phy->clks[clk_priv->parent_source]->rate); + ad9361_bbpll_set_rate(clk_priv, round_rate, + phy->clks[clk_priv->parent_source]->rate); + phy->clks[source]->rate = ad9361_bbpll_recalc_rate(clk_priv, + phy->clks[clk_priv->parent_source]->rate); + phy->bbpll_initialized = true; + break; + case ADC_CLK: + case R2_CLK: + case R1_CLK: + case CLKRF_CLK: + case RX_SAMPL_CLK: + case DAC_CLK: + case T2_CLK: + case T1_CLK: + case CLKTF_CLK: + case TX_SAMPL_CLK: + round_rate = ad9361_clk_factor_round_rate(clk_priv, rate, + &phy->clks[clk_priv->parent_source]->rate); + ad9361_clk_factor_set_rate(clk_priv, round_rate, + phy->clks[clk_priv->parent_source]->rate); + phy->clks[source]->rate = ad9361_clk_factor_recalc_rate(clk_priv, + phy->clks[clk_priv->parent_source]->rate); + break; + default: + break; + } + for(i = BB_REFCLK; i < BBPLL_CLK; i++) + { + phy->clks[i]->rate = ad9361_clk_factor_recalc_rate(phy->ref_clk_scale[i], + phy->clk_refin->rate); + } + phy->clks[BBPLL_CLK]->rate = ad9361_bbpll_recalc_rate(phy->ref_clk_scale[BBPLL_CLK], + phy->clks[phy->ref_clk_scale[BBPLL_CLK]->parent_source]->rate); + for(i = ADC_CLK; i < RX_RFPLL_INT; i++) + { + phy->clks[i]->rate = ad9361_clk_factor_recalc_rate(phy->ref_clk_scale[i], + phy->clks[phy->ref_clk_scale[i]->parent_source]->rate); + } + for(i = RX_RFPLL_INT; i < RX_RFPLL_DUMMY; i++) + { + phy->clks[i]->rate = ad9361_rfpll_int_recalc_rate(phy->ref_clk_scale[i], + phy->clks[phy->ref_clk_scale[i]->parent_source]->rate); + } + for(i = RX_RFPLL_DUMMY; i < RX_RFPLL; i++) + { + phy->clks[i]->rate = ad9361_rfpll_dummy_recalc_rate(phy->ref_clk_scale[i]); + } + for(i = RX_RFPLL; i < NUM_AD9361_CLKS; i++) + { + phy->clks[i]->rate = ad9361_rfpll_recalc_rate(phy->ref_clk_scale[i]); + } + } else { + if ((source == BBPLL_CLK) && !phy->bbpll_initialized) { + round_rate = ad9361_bbpll_round_rate(clk_priv, rate, + &phy->clks[clk_priv->parent_source]->rate); + ad9361_bbpll_set_rate(clk_priv, round_rate, + phy->clks[clk_priv->parent_source]->rate); + phy->clks[source]->rate = ad9361_bbpll_recalc_rate(clk_priv, + phy->clks[clk_priv->parent_source]->rate); + phy->bbpll_initialized = true; + } + } + + return 0; +} + +/***************************************************************************//** + * @brief int_sqrt +*******************************************************************************/ +uint32_t int_sqrt(uint32_t x) +{ + uint32_t b, m, y = 0; + + if (x <= 1) + return x; + + m = 1UL << (BITS_PER_LONG - 2); + while (m != 0) { + b = y + m; + y >>= 1; + + if (x >= b) { + x -= b; + y += m; + } + m >>= 2; + } + + return y; +} + +/***************************************************************************//** + * @brief ilog2 +*******************************************************************************/ +int32_t ilog2(int32_t x) +{ + int32_t A = !(!(x >> 16)); + int32_t count = 0; + int32_t x_copy = x; + + count = count + (A << 4); + + x_copy = (((~A + 1) & (x >> 16)) + (~(~A + 1) & x)); + + A = !(!(x_copy >> 8)); + count = count + (A << 3); + x_copy = (((~A + 1) & (x_copy >> 8)) + (~(~A + 1) & x_copy)); + + A = !(!(x_copy >> 4)); + count = count + (A << 2); + x_copy = (((~A + 1) & (x_copy >> 4)) + (~(~A + 1) & x_copy)); + + A = !(!(x_copy >> 2)); + count = count + (A << 1); + x_copy = (((~A + 1) & (x_copy >> 2)) + (~(~A + 1) & x_copy)); + + A = !(!(x_copy >> 1)); + count = count + A; + + return count; +} + +/***************************************************************************//** + * @brief find_first_bit +*******************************************************************************/ +uint32_t find_first_bit(uint32_t word) +{ + int32_t num = 0; + + if ((word & 0xffff) == 0) { + num += 16; + word >>= 16; + } + if ((word & 0xff) == 0) { + num += 8; + word >>= 8; + } + if ((word & 0xf) == 0) { + num += 4; + word >>= 4; + } + if ((word & 0x3) == 0) { + num += 2; + word >>= 2; + } + if ((word & 0x1) == 0) + num += 1; + return num; +} + +/***************************************************************************//** + * @brief ERR_PTR +*******************************************************************************/ +void * ERR_PTR(long error) +{ + return (void *) error; +} + +/***************************************************************************//** + * @brief zmalloc +*******************************************************************************/ +void *zmalloc(size_t size) +{ + void *ptr = malloc(size); + if (ptr) + memset(ptr, 0, size); + mdelay(1); + + return ptr; +} diff --git a/df_datalink/src/drivers/rf-transceiver/ad9361/ad9361_util.h b/df_datalink/src/drivers/rf-transceiver/ad9361/ad9361_util.h new file mode 100644 index 0000000..cabb6dc --- /dev/null +++ b/df_datalink/src/drivers/rf-transceiver/ad9361/ad9361_util.h @@ -0,0 +1,120 @@ +/***************************************************************************//** + * @file ad9361_util.h + * @brief AD9361 Header file of Util driver. + * @author DBogdan (dragos.bogdan@analog.com) +******************************************************************************** + * Copyright 2013(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ +#ifndef __AD9361_UTIL_H__ +#define __AD9361_UTIL_H__ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include +#include +#include +#include +#include "ad9361.h" +#include "common.h" + +/******************************************************************************/ +/********************** Macros and Constants Definitions **********************/ +/******************************************************************************/ +#define CLK_IGNORE_UNUSED BIT(3) +#define CLK_GET_RATE_NOCACHE BIT(6) + +#if defined(HAVE_VERBOSE_MESSAGES) +#define dev_err(dev, format, ...) ({printf(format, ## __VA_ARGS__);printf("\n"); }) +#define dev_warn(dev, format, ...) ({printf(format, ## __VA_ARGS__);printf("\n"); }) +#if defined(HAVE_DEBUG_MESSAGES) +#define dev_dbg(dev, format, ...) ({printf(format, ## __VA_ARGS__);printf("\n"); }) +#else +#define dev_dbg(dev, format, ...) ({ if (0) printf(format, ## __VA_ARGS__); }) +#endif +#define printk(format, ...) printf(format, ## __VA_ARGS__) +#else +#define dev_err(dev, format, ...) ({ if (0) printf(format, ## __VA_ARGS__); }) +#define dev_warn(dev, format, ...) ({ if (0) printf(format, ## __VA_ARGS__); }) +#define dev_dbg(dev, format, ...) ({ if (0) printf(format, ## __VA_ARGS__); }) +#define printk(format, ...) ({ if (0) printf(format, ## __VA_ARGS__); }) +#endif + +struct device { +}; + +struct spi_device { + struct device dev; + uint8_t id_no; +}; + +struct axiadc_state { + struct ad9361_rf_phy *phy; + uint32_t pcore_version; +}; + +struct axiadc_chip_info { + char *name; + int32_t num_channels; +}; + +struct axiadc_converter { + struct axiadc_chip_info *chip_info; + uint32_t scratch_reg[16]; +}; + +#ifdef WIN32 +#include "basetsd.h" +typedef SSIZE_T ssize_t; +#define strsep(s, ct) 0 +#define snprintf(s, n, format, ...) 0 +#define __func__ __FUNCTION__ +#endif + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ +int32_t clk_prepare_enable(struct clk *clk); +uint32_t clk_get_rate(struct ad9361_rf_phy *phy, + struct refclk_scale *clk_priv); +int32_t clk_set_rate(struct ad9361_rf_phy *phy, + struct refclk_scale *clk_priv, + uint32_t rate); +uint32_t int_sqrt(uint32_t x); +int32_t ilog2(int32_t x); +uint32_t find_first_bit(uint32_t word); +void * ERR_PTR(long error); +void *zmalloc(size_t size); + +#endif diff --git a/df_datalink/src/drivers/rf-transceiver/ad9361/common.h b/df_datalink/src/drivers/rf-transceiver/ad9361/common.h new file mode 100644 index 0000000..6093230 --- /dev/null +++ b/df_datalink/src/drivers/rf-transceiver/ad9361/common.h @@ -0,0 +1,66 @@ +/***************************************************************************//** + * @file common.h + * @brief Header file of Common Driver. + * @author DBogdan (dragos.bogdan@analog.com) +******************************************************************************** + * Copyright 2013(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ +#ifndef __AD9361_COMMON_H_ +#define __AD9361_COMMON_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include +#include "../../../include/error.h" + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ +#if defined (__STDC__) && (__STDC_VERSION__ >= 199901L) +#include +#else +typedef enum { false, true } bool; +#endif + +struct clk { + const char *name; + uint32_t rate; +}; + +struct clk_hw { + struct clk *clk; +}; + +#endif // __AD9361_COMMON_H_ diff --git a/df_datalink/src/drivers/rf-transceiver/ad9361_reg/ad9361_reg.c b/df_datalink/src/drivers/rf-transceiver/ad9361_reg/ad9361_reg.c new file mode 100644 index 0000000..7498038 --- /dev/null +++ b/df_datalink/src/drivers/rf-transceiver/ad9361_reg/ad9361_reg.c @@ -0,0 +1,151 @@ +/***************************************************************************//** + * @file ad9361_reg.c + * @brief Implementation of AD9680 Driver. + * @author DBogdan (dragos.bogdan@analog.com) + ******************************************************************************** + * Copyright 2014-2016(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include "ad9361_reg.h" + +#include +#include +#include "../../../include/error.h" + +/***************************************************************************//** + * @brief ad9361_reg_read + *******************************************************************************/ +int32_t ad9361_reg_read(struct ad9361_reg_dev *dev, + uint16_t reg_addr, + uint8_t *reg_data) +{ + uint8_t tx_buf[2]; + uint8_t rx_buf[1]; + int32_t ret; + + tx_buf[0] = reg_addr >> 8; + tx_buf[1] = reg_addr & 0xFF; + + + ret = spi_write_and_read_3wire(dev->spi_desc, + tx_buf, rx_buf, 2, 1); + + *reg_data = rx_buf[0]; + + return ret; +} + +/***************************************************************************//** + * @brief ad9361_reg_write + *******************************************************************************/ +int32_t ad9361_reg_write(struct ad9361_reg_dev *dev, + uint16_t reg_addr, + uint8_t reg_data) +{ + uint8_t buf[3]; + + int32_t ret; + + buf[0] = 0x80 | reg_addr >> 8; + buf[1] = reg_addr & 0xFF; + buf[2] = reg_data; + + ret = spi_write_and_read_3wire(dev->spi_desc, + buf, NULL, 3, 0); + return ret; +} + +/***************************************************************************//** + * @brief ad9361_reg_init + *******************************************************************************/ +int32_t ad9361_reg_init(struct ad9361_reg_dev **device, + const struct ad9361_reg_init_param *init_param) +{ + int ret = SUCCESS; + struct ad9361_reg_dev *dev; + + dev = (struct ad9361_reg_dev *)malloc(sizeof(*dev)); + if (!dev) + return FAILURE; + + /* SPI */ + ret = spi_init(&dev->spi_desc, init_param->spi_init); + ret |= gpio_get(&dev->gpio_desc_resetb, init_param->gpio_resetb); + + gpio_direction_output(dev->gpio_desc_resetb, 0); + + ad9361_reg_reset(dev); + + *device = dev; + + return ret; +} + +/** + * AD9361 Device Reset + * @param phy The AD9361 state structure. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_reg_reset(struct ad9361_reg_dev *dev) +{ + if (dev->gpio_desc_resetb) { + gpio_set_value(dev->gpio_desc_resetb, 0); + mdelay(10); + gpio_set_value(dev->gpio_desc_resetb, 1); + mdelay(10); + return 0; + } + return 0; +} + +/***************************************************************************//** + * @brief Free the resources allocated by ad9361_reg_setup(). + * + * @param dev - The device structure. + * + * @return SUCCESS in case of success, negative error code otherwise. +*******************************************************************************/ +int32_t ad9361_reg_remove(struct ad9361_reg_dev *dev) +{ + int32_t ret; + + ret = spi_remove(dev->spi_desc); + + free(dev); + + return ret; +} diff --git a/df_datalink/src/drivers/rf-transceiver/ad9361_reg/ad9361_reg.h b/df_datalink/src/drivers/rf-transceiver/ad9361_reg/ad9361_reg.h new file mode 100644 index 0000000..c3039c5 --- /dev/null +++ b/df_datalink/src/drivers/rf-transceiver/ad9361_reg/ad9361_reg.h @@ -0,0 +1,104 @@ +/***************************************************************************//** + * @file ad9361_reg.h + * @brief Header file of ad9361_reg Driver. + * @author DBogdan (dragos.bogdan@analog.com) + ******************************************************************************** + * Copyright 2014-2016(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *******************************************************************************/ +#ifndef ad9361_reg_H_ +#define ad9361_reg_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include +#include "delay.h" +#include "spi.h" +#include "gpio.h" + +/******************************************************************************/ +/********************** Macros and Constants Definitions **********************/ +/******************************************************************************/ + + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ +struct ad9361_reg_dev { + /* SPI */ + struct spi_desc *spi_desc; + struct gpio_desc *gpio_desc_resetb; +}; + +struct ad9361_reg_init_param { + /* SPI */ + struct spi_init_param *spi_init; + struct gpio_init_param *gpio_resetb; +}; + +enum Operation_Type{ + AD9361_WRITE, + AD9361_READ, + AD9361_WAIT, + AD9361_WHEN +}; + +struct ad9361_reg_config { + int operation; + uint16_t val1; + uint16_t val2; +}; + + + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ + +int32_t ad9361_reg_read(struct ad9361_reg_dev *dev, + uint16_t reg_addr, + uint8_t *reg_data); + +int32_t ad9361_reg_write(struct ad9361_reg_dev *dev, + uint16_t reg_addr, + uint8_t reg_data); + +int32_t ad9361_reg_init(struct ad9361_reg_dev **device, + const struct ad9361_reg_init_param *init_param); + +int32_t ad9361_reg_reset(struct ad9361_reg_dev *dev); + +int32_t ad9361_reg_remove(struct ad9361_reg_dev *dev); + +#endif diff --git a/df_datalink/src/include/axi_io.h b/df_datalink/src/include/axi_io.h new file mode 100644 index 0000000..ac8b67d --- /dev/null +++ b/df_datalink/src/include/axi_io.h @@ -0,0 +1,59 @@ +/***************************************************************************//** + * @file axi_io.h + * @brief Header file of AXI IO. + * @author Antoniu Miclaus (antoniu.miclaus@analog.com) +******************************************************************************** + * Copyright 2019(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#ifndef _AXI_IO_H_ +#define _AXI_IO_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ + +/* AXI IO Read data */ +int32_t axi_io_read(uint32_t base, uint32_t offset, uint32_t *data); + +/* AXI IO Write data */ +int32_t axi_io_write(uint32_t base, uint32_t offset, uint32_t data); + +#endif // _AXI_IO_H_ diff --git a/df_datalink/src/include/circ_queue.h b/df_datalink/src/include/circ_queue.h new file mode 100644 index 0000000..a6dc655 --- /dev/null +++ b/df_datalink/src/include/circ_queue.h @@ -0,0 +1,111 @@ +/*****************************************************************************/ +/** + * Description: A simple circular FIFO bounded queue + * + * Author: Fan Hao + * Date: 2023-02-23 10:29 + * LastEditors: Fan Hao + * LastEditTime: 2023-02-23 12:53 + * Revisions: Rev 0.0 + * History: + * [2023-02-23]: Initial Version. + * + * Copyright(c) 2023 Beijing Institute of Technology. + * Lab of Communication and Networking + * NOTE: Forked from https://github.com/chrismerck/rpa_queue.git + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +******************************************************************************/ + +#ifndef CIRC_QUEUE_H +#define CIRC_QUEUE_H + +#include +#include +#include + + +/** + * opaque structure + */ +typedef struct { + void **data; + volatile uint32_t nelts; /**< # elements */ + uint32_t in; /**< next empty location */ + uint32_t out; /**< next filled location */ + uint32_t bounds;/**< max size of queue */ +} CIRC_QUEUE; + + + +/** + * create a FIFO queue + * @param queue The new queue + * @param queue_capacity maximum size of the queue + * @param a pool to allocate queue from + */ +bool CircQueueCreate(CIRC_QUEUE **queue, uint32_t queue_capacity); + +/** free queue memory -- call after destroy + * @note we do not free in destroy() to follow pthreads convention +*/ +void CircQueueFree(CIRC_QUEUE * queue); + +/** + * Detects when the CIRC_QUEUE is full. This utility function is expected + * to be called from within critical sections, and is not threadsafe. + */ +bool isCircQueueFull(CIRC_QUEUE *queue); + +/** + * Detects when the CIRC_QUEUE is empty. This utility function is expected + * to be called from within critical sections, and is not threadsafe. + */ +bool isCircQueueEmpty(CIRC_QUEUE *queue); + +/** + * push/add an object to the queue, blocking if the queue is already full + * + * @param queue the queue + * @param data the data + * @returns RPA_EINTR the blocking was interrupted (try again) + * @returns RPA_EOF the queue has been terminated + * @returns RPA_SUCCESS on a successful push + */ +bool CircQueuePush(CIRC_QUEUE *queue, void *data); + + +/** + * pop/get an object from the queue, blocking if the queue is already empty + * + * @param queue the queue + * @param data the data + * @returns RPA_EINTR the blocking was interrupted (try again) + * @returns RPA_EOF if the queue has been terminated + * @returns RPA_SUCCESS on a successful pop + */ +bool CircQueuePop(CIRC_QUEUE *queue, void **data); + +/** + * returns the size of the queue. + * + * @warning this is not threadsafe, and is intended for reporting/monitoring + * of the queue. + * @param queue the queue + * @returns the size of the queue + */ +uint32_t CircQueueSize(CIRC_QUEUE *queue); + +#endif /* CIRC_QUEUE_H */ diff --git a/df_datalink/src/include/common.h b/df_datalink/src/include/common.h new file mode 100644 index 0000000..cfa7614 --- /dev/null +++ b/df_datalink/src/include/common.h @@ -0,0 +1,88 @@ +/*****************************************************************************/ +/** + * Description: A brief description of this file + * + * Author: Fan Hao + * Date: 2022-10-21 18:59 + * LastEditors: Fan Hao + * LastEditTime: 2023-02-13 10:01 + * Revisions: Rev x.x + * History: + * [YYYY-MM-DD]: Description of modification. + * + * Copyright(c) 2023 Beijing Institute of Technology. + * Lab of Communication and Networking + * +******************************************************************************/ +/*****************************************************************************/ +/** + * Description: Common definitions + * + * Date: 2021-12-04 16:32 + * LastEditors: Fan Hao + * LastEditTime: 2022-07-16 17:13 + * Revisions: Rev 0.1 + * History: + * [2022-07-16]: New branch for Dijian. + * [2021-11-16]: Initial version. + * + * Copyright(c) 2021 Beijing Institute of Technology. + * Lab of Communication and Networking + * + ******************************************************************************/ +/***************************** Include Files *********************************/ +#ifndef __COMMON_H_ +#define __COMMON_H_ +#include +#include +#include +#include +#include "util.h" +#include "error.h" +#include "../config/app_config.h" +/************************** Constant Definitions *****************************/ +/***************** Macros (Inline Functions) Definitions *********************/ +//#define ASSERT(exp) assert(exp) +#define ASSERT(exp) ((exp) ? 0 : AppAssert(__FILE__, __LINE__)) +#define _nop_() asm("nop") + +#define HALT_IF_ERR(status, msg, ...) \ + if (SUCCESS != status) { \ + printf("ERROR: #%d " msg, status, ##__VA_ARGS__); \ + exit(status); \ + } + +/* Stringify */ +#define STR(x) #x + +// #define _DEBUG_LEVEL 3 + +#if _DEBUG_LEVEL == 1 +#define DBG_ERROR(MSG, ...) printf("in"__FILE__" #%4d [error] "MSG,__LINE__, ##__VA_ARGS__) +#define DBG_WARNING(MSG, ...) {} +#define DBG_INFO(MSG, ...) {} +#define DBG_PRINT(MSG, ...) printf(MSG, ##__VA_ARGS__) +#elif _DEBUG_LEVEL == 2 +#define DBG_ERROR(MSG, ...) printf("in"__FILE__" #%4d [error] "MSG,__LINE__, ##__VA_ARGS__) +#define DBG_WARNING(MSG, ...) printf("[warning] "MSG, ##__VA_ARGS__) +#define DBG_INFO(MSG, ...) {} +#define DBG_PRINT(MSG, ...) printf(MSG, ##__VA_ARGS__) +#elif _DEBUG_LEVEL == 3 +#define DBG_ERROR(MSG, ...) printf("in"__FILE__" #%4d [error] "MSG,__LINE__, ##__VA_ARGS__) +#define DBG_WARNING(MSG, ...) printf("[warning] "MSG, ##__VA_ARGS__) +#define DBG_INFO(MSG, ...) printf("[Info] "MSG, ##__VA_ARGS__) +#define DBG_PRINT(MSG, ...) printf(MSG, ##__VA_ARGS__) +#else +#define DBG_ERROR(MSG, ...) {} +#define DBG_WARNING(MSG, ...) {} +#define DBG_INFO(MSG, ...) {} +#define DBG_PRINT(MSG, ...) {} +#endif + +/**************************** Type Definitions *******************************/ + +/************************** Variable Definitions *****************************/ + +/************************** Function Prototypes ******************************/ +void AppAssert(const char * file, int line); +#endif /* COMMON_H_ */ diff --git a/df_datalink/src/include/delay.h b/df_datalink/src/include/delay.h new file mode 100644 index 0000000..d1dee17 --- /dev/null +++ b/df_datalink/src/include/delay.h @@ -0,0 +1,70 @@ +/***************************************************************************//** + * @file delay.h + * @brief Header file of Delay functions + * @author DBogdan (dragos.bogdan@analog.com) +******************************************************************************** + * Copyright 2019(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#ifndef _DELAY_H_ +#define _DELAY_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include + +/** + * @struct time + * @brief Structure holding time data (seconds, microseconds). + */ +struct time { + unsigned int s, us; +}; + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ + +/* Generate microseconds delay. */ +void udelay(uint32_t usecs); + +/* Generate miliseconds delay. */ +void mdelay(uint32_t msecs); + +/* Get current time */ +struct time get_time(void); + +#endif // _DELAY_H_ diff --git a/df_datalink/src/include/error.h b/df_datalink/src/include/error.h new file mode 100644 index 0000000..1e20199 --- /dev/null +++ b/df_datalink/src/include/error.h @@ -0,0 +1,47 @@ +/*****************************************************************************/ +/** + * Description: Error code definitions. + * + * Author: Fan Hao + * Date: 2022-06-18 16:37 + * LastEditors: Fan Hao + * LastEditTime: 2022-06-18 17:12 + * Revisions: Rev 0.0 + * History: + * [2022-06-18]: Initial version. + * + * Copyright(c) 2022 Beijing Institute of Technology. + * Lab of Communication and Networking + * +******************************************************************************/ + +#ifndef SRC_ERROR_H_ +#define SRC_ERROR_H_ + +#include + +/******************************************************************************/ +/********************** Macros and Constants Definitions **********************/ +/******************************************************************************/ + +#ifdef SUCCESS +#undef SUCCESS +#endif +#define SUCCESS 0 +#ifdef FAILURE +#undef FAILURE +#endif +#define FAILURE -1 + +#define EPARAM -2 /*!< Data crc check failed */ +#define ECRC -3 /*!< Data crc check failed */ +#define EDINVAL -4 /*!< Device is invalid (sleep or power off) */ +#define EDCONF -5 /*!< Device confugure error */ +#define ETIMEOUT -6 /*!< Timeout error */ +#define EIGNORE -7 /*!< Received an unsupported command, and ignore it */ +#define EQUEUE -8 /*!< Queue overflow */ +#define EUNEXP -9 /*!< Encounter an unexpected error */ + +#define IS_ERR_VALUE(x) ((x) != SUCCESS) + +#endif // ERROR_H_ diff --git a/df_datalink/src/include/global_timer.h b/df_datalink/src/include/global_timer.h new file mode 100644 index 0000000..d0572ed --- /dev/null +++ b/df_datalink/src/include/global_timer.h @@ -0,0 +1,95 @@ +#ifndef SRC_GLOBAL_TIMER_H_ +#define SRC_GLOBAL_TIMER_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ + +/** + * @struct timer_init_param + * @brief Structure holding the parameters for timer initialization + */ +struct global_timer_init_param { + /** timer ID */ + uintptr_t base_addr; + /** timer ID */ + uint16_t id; + /** timer count frequency (Hz) */ + uint32_t freq_hz; + /** counter start value */ + uint64_t load_value; +}; + +/** + * @struct timer_desc + * @brief Structure holding timer descriptor + */ +struct global_timer_desc { + /** timer ID */ + uintptr_t base_addr; + /** timer ID */ + uint16_t id; + /** timer count frequency (Hz) */ + uint32_t freq_hz; + /** counter start value */ + uint64_t load_value; +}; + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ + +/* Initialize hardware timer and the handler structure associated with it. */ +int32_t global_timer_init(struct global_timer_desc **desc, + struct global_timer_init_param *param); + +/* Free the memory allocated by timer_setup(). */ +int32_t global_timer_remove(struct global_timer_desc *desc); + +/* Start a timer. */ +int32_t global_timer_start(struct global_timer_desc *desc); + +/* Stop a timer from counting. */ +int32_t global_timer_stop(struct global_timer_desc *desc); + +/* Get the value of the counter register for the timer. */ +int32_t global_timer_counter_get(struct global_timer_desc *desc, uint64_t *counter); + +/* Set the timer counter register value. */ +int32_t global_timer_counter_set(struct global_timer_desc *desc, uint64_t new_val); + +/* Get the timer clock frequency. */ +int32_t global_timer_count_clk_get(struct global_timer_desc *desc, uint32_t *freq_hz); + +/* Set the timer clock frequency. */ +int32_t global_timer_count_clk_set(struct global_timer_desc *desc, uint32_t freq_hz); + +/* Enable global timer interrupt. */ +int32_t global_timer_irq_enable(struct global_timer_desc *desc); + +/* Disable global timer interrupt. */ +int32_t global_timer_irq_disable(struct global_timer_desc *desc); + +/* Implement a acknowledgment global timer interrupt. */ +int32_t global_timer_irq_ack(struct global_timer_desc *desc); + +/* Set comparator register. */ +int32_t global_timer_compara_set(struct global_timer_desc *desc, uint64_t com_val); + +/* Set auto increment register . */ +int32_t global_timer_auto_inc_set(struct global_timer_desc *desc, uint32_t inc_val); + +/* Enable global timer auto increment mode. */ +int32_t global_timer_auto_inc_enable(struct global_timer_desc *desc); + +/* Disable global timer auto increment mode. */ +int32_t global_timer_auto_inc_disable(struct global_timer_desc *desc); + +#endif /* SRC_TIMER_H_ */ + diff --git a/df_datalink/src/include/gpio.h b/df_datalink/src/include/gpio.h new file mode 100644 index 0000000..fb2c113 --- /dev/null +++ b/df_datalink/src/include/gpio.h @@ -0,0 +1,188 @@ +/***************************************************************************//** + * @file gpio.h + * @brief Header file of GPIO Interface + * @author DBogdan (dragos.bogdan@analog.com) +******************************************************************************** + * Copyright 2019(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#ifndef _GPIO_H_ +#define _GPIO_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include + +/******************************************************************************/ +/********************** Macros and Constants Definitions **********************/ +/******************************************************************************/ + +#define GPIO_OUT 0x01 +#define GPIO_IN 0x00 + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ + +/** + * @struct gpio_platform_ops + * @brief Structure holding gpio function pointers that point to the platform + * specific function + */ +struct gpio_platform_ops ; + +/** + * @enum gpio_pull_up + * @brief Enum that holds the possible pull up/ pull down resistor configuration. + */ +enum gpio_pull_up { + PULL_NONE, + /** Strong pull up */ + PULL_UP, + /** Strong pull down */ + PULL_DOWN, + PULL_UP_WEAK, + PULL_DOWN_WEAK +}; + +/** + * @struct gpio_init_param + * @brief Structure holding the parameters for GPIO initialization. + */ +struct gpio_init_param { + /** Port number */ + int32_t port; + /** GPIO number */ + int32_t number; + /** Pull up/down resistor configuration */ + enum gpio_pull_up pull; + /** GPIO platform specific functions */ + const struct gpio_platform_ops *platform_ops; + /** GPIO extra parameters (device specific) */ + void *extra; +}; + +/** + * @struct gpio_desc + * @brief Structure holding the GPIO descriptor. + */ +struct gpio_desc { + /** Port number */ + int32_t port; + /** GPIO number */ + int32_t number; + /** Pull up/down resistor configuration */ + enum gpio_pull_up pull; + /** GPIO platform specific functions */ + const struct gpio_platform_ops *platform_ops; + /** GPIO extra parameters (device specific) */ + void *extra; +}; + +/** + * @enum gpio_values + * @brief Enum that holds the possible output states of a GPIO. + */ +enum gpio_values { + /** GPIO logic low */ + GPIO_LOW, + /** GPIO logic high */ + GPIO_HIGH, + /** GPIO high impedance */ + GPIO_HIGH_Z +}; + +/** + * @struct gpio_platform_ops + * @brief Structure holding gpio function pointers that point to the platform + * specific function + */ +struct gpio_platform_ops { + /** gpio initialization function pointer */ + int32_t (*gpio_ops_get)(struct gpio_desc **, + const struct gpio_init_param *); + /** gpio optional descriptor function pointer */ + int32_t (*gpio_ops_get_optional)(struct gpio_desc **, + const struct gpio_init_param *); + /** gpio remove function pointer */ + int32_t (*gpio_ops_remove)(struct gpio_desc *); + /** gpio direction input function pointer */ + int32_t (*gpio_ops_direction_input)(struct gpio_desc *); + /** gpio direction output function pointer */ + int32_t (*gpio_ops_direction_output)(struct gpio_desc *, uint8_t); + /** gpio get direction function pointer */ + int32_t (*gpio_ops_get_direction)(struct gpio_desc *, uint8_t *); + /** gpio set value function pointer */ + int32_t (*gpio_ops_set_value)(struct gpio_desc *, uint8_t); + /** gpio get value function pointer */ + int32_t (*gpio_ops_get_value)(struct gpio_desc *, uint8_t *); +}; + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ + +/* Obtain the GPIO decriptor. */ +int32_t gpio_get(struct gpio_desc **desc, + const struct gpio_init_param *param); + +/* Obtain optional GPIO descriptor. */ +int32_t gpio_get_optional(struct gpio_desc **desc, + const struct gpio_init_param *param); + +/* Free the resources allocated by gpio_get(). */ +int32_t gpio_remove(struct gpio_desc *desc); + +/* Enable the input direction of the specified GPIO. */ +int32_t gpio_direction_input(struct gpio_desc *desc); + +/* Enable the output direction of the specified GPIO. */ +int32_t gpio_direction_output(struct gpio_desc *desc, + uint8_t value); + +/* Get the direction of the specified GPIO. */ +int32_t gpio_get_direction(struct gpio_desc *desc, + uint8_t *direction); + +/* Set the value of the specified GPIO. */ +int32_t gpio_set_value(struct gpio_desc *desc, + uint8_t value); + +/* Get the value of the specified GPIO. */ +int32_t gpio_get_value(struct gpio_desc *desc, + uint8_t *value); + +#endif // _GPIO_H_ diff --git a/df_datalink/src/include/i2c.h b/df_datalink/src/include/i2c.h new file mode 100644 index 0000000..86284cc --- /dev/null +++ b/df_datalink/src/include/i2c.h @@ -0,0 +1,134 @@ +/***************************************************************************//** + * @file i2c.h + * @brief Header file of I2C Interface + * @author DBogdan (dragos.bogdan@analog.com) +******************************************************************************** + * Copyright 2019(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#ifndef _I2C_H_ +#define _I2C_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ + +/** + * @struct i2c_platform_ops + * @brief Structure holding I2C function pointers that point to the platform + * specific function + */ +struct i2c_platform_ops ; + +/** + * @struct i2c_init_param + * @brief Structure holding the parameters for I2C initialization. + */ +struct i2c_init_param { + /** Device ID */ + uint32_t device_id; + /** I2C maximum transfer speed supported */ + uint32_t max_speed_hz; + /** Slave address */ + uint8_t slave_address; + /** I2C platform specific functions */ + const struct i2c_platform_ops *platform_ops; + /** I2C extra parameters (device specific parameters) */ + void *extra; +}; + +/** + * @struct i2c_desc + * @brief Structure holding I2C descriptor + */ +struct i2c_desc { + /** Device ID */ + uint32_t device_id; + /** I2C maximum transfer speed supported */ + uint32_t max_speed_hz; + /** Slave address */ + uint8_t slave_address; + /** I2C platform specific functions */ + const struct i2c_platform_ops *platform_ops; + /** I2C extra parameters (device specific parameters) */ + void *extra; +}; + +/** + * @struct i2c_platform_ops + * @brief Structure holding i2c function pointers that point to the platform + * specific function + */ +struct i2c_platform_ops { + /** i2c initialization function pointer */ + int32_t (*i2c_ops_init)(struct i2c_desc **, + const struct i2c_init_param *); + /** i2c write function pointer */ + int32_t (*i2c_ops_write)(struct i2c_desc *, uint8_t *, uint8_t, uint8_t); + /** i2c write function pointer */ + int32_t (*i2c_ops_read)(struct i2c_desc *, uint8_t *, uint8_t, uint8_t); + /** i2c remove function pointer */ + int32_t (*i2c_ops_remove)(struct i2c_desc *); +}; + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ + +/* Initialize the I2C communication peripheral. */ +int32_t i2c_init(struct i2c_desc **desc, + const struct i2c_init_param *param); + +/* Free the resources allocated by i2c_init(). */ +int32_t i2c_remove(struct i2c_desc *desc); + +/* Write data to a slave device. */ +int32_t i2c_write(struct i2c_desc *desc, + uint8_t *data, + uint8_t bytes_number, + uint8_t stop_bit); + +/* Read data from a slave device. */ +int32_t i2c_read(struct i2c_desc *desc, + uint8_t *data, + uint8_t bytes_number, + uint8_t stop_bit); + +#endif // _I2C_H_ diff --git a/df_datalink/src/include/irq.h b/df_datalink/src/include/irq.h new file mode 100644 index 0000000..34fa6c4 --- /dev/null +++ b/df_datalink/src/include/irq.h @@ -0,0 +1,235 @@ +/***************************************************************************//** + * @file irq.h + * @brief Header file of IRQ interface. + * @author Cristian Pop (cristian.pop@analog.com) +******************************************************************************** + * Copyright 2019(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#ifndef _IRQ_H_ +#define _IRQ_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ + +/** + * @enum irq_uart_event_e + * @brief Possible events for uart interrupt + * @todo replace this with enum irq_event + */ +enum irq_uart_event_e { + /** Write operation finalized */ + IRQ_WRITE_DONE, + /** Read operation finalized */ + IRQ_READ_DONE, + /** An error occurred */ + IRQ_ERROR +}; + +enum irq_event { + EVT_GPIO, + EVT_UART_TX_COMPLETE, + EVT_UART_RX_COMPLETE, + EVT_UART_ERROR, + EVT_RTC, + EVT_XINT, + EVT_TIM_ELAPSED +}; + +enum irq_trig_level { + IRQ_LEVEL_LOW, + IRQ_LEVEL_HIGH, + IRQ_EDGE_FALLING, + IRQ_EDGE_RISING, + IRQ_EDGE_BOTH +}; + +enum irq_peripheral { + GPIO_IRQ, + UART_IRQ, + RTC_IRQ, + TIM_IRQ +}; + +/** + * @struct irq_platform_ops + * @brief Structure holding IRQ function pointers that point to the platform + * specific function + */ +struct irq_platform_ops ; + +/** + * @struct irq_init_param + * @brief Structure holding the initial parameters for Interrupt Request. + */ +struct irq_init_param { + /** Interrupt request controller ID. */ + uint32_t irq_ctrl_id; + /** Platform specific IRQ platform ops structure. */ + const struct irq_platform_ops *platform_ops; + /** + * This is intended to store irq controller specific configurations, + * it should not be a reference to any peripheral descriptor. + */ + void *extra; +}; + +/** + * @struct irq_desc + * @brief Structure for Interrupt Request descriptor. + */ +struct irq_ctrl_desc { + /** Interrupt request controller ID. */ + uint32_t irq_ctrl_id; + /** Platform specific IRQ platform ops structure. */ + const struct irq_platform_ops *platform_ops; + /** + * This is intended to store irq controller specific configurations, + * it should not be a reference to any peripheral descriptor. + */ + void *extra; +}; + +/** + * @struct callback_desc + * @brief Structure describing a callback to be registered + * @todo: remove this, use struct irq_callback instead. + */ +struct callback_desc { + /** Callback to be called when the event an event occurs. */ + void (*callback)(void *context); + /** + * Callback to be called when the event an event occurs + * @param ctx - Same as \ref callback_desc.ctx + * @param event - Event that generated the callback + * @param extra - Platform specific data + */ + void (*legacy_callback)(void *ctx, uint32_t event, + void *extra); /* TODO: remove this. */ + /** Parameter to be passed when the callback is called */ + void *ctx; + /** Platform specific configuration for a callback */ + void *legacy_config; /* TODO: remove this. */ + /** Platform specific event that triggers the calling of the callback. */ + enum irq_event event; + /** Interrupt source peripheral specifier. */ + enum irq_peripheral peripheral; + /** This will be used to store HAL specific descriptors */ + void *handle; +}; + +/** + * @struct irq_platform_ops + * @brief Structure holding IRQ function pointers that point to the platform + * specific function + */ +struct irq_platform_ops { + /** Initialize a interrupt controller peripheral. */ + int32_t (*init)(struct irq_ctrl_desc **desc, + const struct irq_init_param *param); + /** Register a legacy_callback to handle the irq events */ + int32_t (*register_callback)(struct irq_ctrl_desc *desc, uint32_t irq_id, + struct callback_desc *callback); + /** Unregisters a generic IRQ handling function */ + int32_t (*unregister_callback)(struct irq_ctrl_desc *desc, + uint32_t irq_id, + struct callback_desc *callback); + /** Global interrupt enable */ + int32_t (*global_enable)(struct irq_ctrl_desc *desc); + /** Global interrupt disable */ + int32_t (*global_disable)(struct irq_ctrl_desc *desc); + /** Set interrupt trigger level. */ + int32_t (*trigger_level_set)(struct irq_ctrl_desc *desc, uint32_t irq_id, + enum irq_trig_level trig); + /** Enable specific interrupt */ + int32_t (*enable)(struct irq_ctrl_desc *desc, uint32_t irq_id); + /** Disable specific interrupt */ + int32_t (*disable)(struct irq_ctrl_desc *desc, uint32_t irq_id); + /** Set the priority level for a specific interrupt */ + int32_t (*set_priority)(struct irq_ctrl_desc *desc, uint32_t irq_id, + uint32_t priority_level); + /** IRQ remove function pointer */ + int32_t (*remove)(struct irq_ctrl_desc *desc); +}; + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ + +/* Initialize a interrupt controller peripheral. */ +int32_t irq_ctrl_init(struct irq_ctrl_desc **desc, + const struct irq_init_param *param); + +/* Free the resources allocated by irq_ctrl_init(). */ +int32_t irq_ctrl_remove(struct irq_ctrl_desc *desc); + +/* Register a callback to handle the irq events */ +int32_t irq_register_callback(struct irq_ctrl_desc *desc, + uint32_t irq_id, + struct callback_desc *callback_desc); + +/* Unregisters a generic IRQ handling function */ +int32_t irq_unregister_callback(struct irq_ctrl_desc *desc, + uint32_t irq_id, + struct callback_desc *callback_desc); + +/* Global interrupt enable */ +int32_t irq_global_enable(struct irq_ctrl_desc *desc); + +/* Global interrupt disable */ +int32_t irq_global_disable(struct irq_ctrl_desc *desc); + +/* Set interrupt trigger level. */ +int32_t irq_trigger_level_set(struct irq_ctrl_desc *desc, + uint32_t irq_id, + enum irq_trig_level trig); + +/* Enable specific interrupt */ +int32_t irq_enable(struct irq_ctrl_desc *desc, uint32_t irq_id); + +/* Disable specific interrupt */ +int32_t irq_disable(struct irq_ctrl_desc *desc, uint32_t irq_id); + +/** Set the priority level for a specific interrupt */ +int32_t irq_set_priority(struct irq_ctrl_desc *desc, + uint32_t irq_id, + uint32_t priority_level); +#endif // _IRQ_H_ diff --git a/df_datalink/src/include/list.h b/df_datalink/src/include/list.h new file mode 100644 index 0000000..517a51c --- /dev/null +++ b/df_datalink/src/include/list.h @@ -0,0 +1,327 @@ +/***************************************************************************//** + * @file list.h + * @brief List library header + * @author Mihail Chindris (mihail.chindris@analog.com) +******************************************************************************** + * @copyright + * Copyright 2020(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +******************************************************************************** + * + * @section list_details Library description + * This library handles double linked lists and it expose inseart, + * read, get and delete functions. \n + * It also can be accesed using it member functions which wrapp function for + * usual list types.\n + * @subsection example Sample code + * @code{.c} + * // -- Use a generic list + * struct list_desc *list1; + * struct iterator *it; + * uint32_t a; + * // Create list list1 + * list_init(&list1, LIST_DEFAULT, NULL); + * // Add items to the list + * list_add_last(list1, 1); + * list_add_last(list1, 2); + * list_add_last(list1, 3); + * // Here the list will be: 1 -> 2 - > 3 + * + * list_read_last(list1, &a); + * printf("Last: %d\n", a); + * // 3 will be printed + * // Create an iterator on the end of the list + * iterator_init(&it, list1, 0); + * // Move the iterator backword with one position + * iterator_move(it, -1); + * // Read the data at the current position + * iterator_read(it, &a); + * printf("Current: %d\n", a); + * // 2 will be printed + * iterator_remove(it); + * list_remove(list1); + * + * // -- Use a popular list + * struct list_desc *stack; + * // Create a FIFO list + * list_init(&stack, LIST_STACK, NULL); + * // Put elements in the list + * stack->push(stack, 1); + * stack->push(stack, 2); + * stack->push(stack, 3); + * // Read from the stack + * stack->pop(stack, &a); + * printf("Last: %d\n", a); + * // 3 will be printed + * list_remove(stack); + * @endcode +*******************************************************************************/ + +#ifndef _LIST_H_ +#define _LIST_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include +#include + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ + +/** + * @struct list_desc + * @brief Structure storing the list and function wrapper for usual list types + * + * With this structure the funtionalities of usual list types + * ( \ref adapter_type ) can be accesed with the functions referenced in this + * structure. + * For example: + * @code{.c} + * my_queue->push(my_queue, my_data); + * @endcode + */ +struct list_desc; + +/** + * @struct list_iterator + * @brief Structure used to iterate through the list using Iterator functions. + */ +struct iterator; + +/** + * @brief Prototype of the compare function. + * + * The function used to compare the elements of the liste when doing + * operations on an ordered list. + * @param data1 - First element to be compared + * @param data2 - Second element to be compared + * @return + * - -1 - If data1 < data2 + * - 0 - If data1 == data2 + * - 1 - If data1 > data2 + */ +typedef int32_t (*f_cmp)(void *data1, void *data2); + +/** + * @name Generic functions + * Each function interacting with the list have one of the following formats.\n + * Aditionaly they may have one more parametere for specific functionalities.\n + * In the Iterator functions, the list reference is replaced by the iterator's + * one. + * @{ + */ + +/** + * @brief Add an element in the list. + * + * The element of the list is created and the data field is stored in it. + * @param list_desc - Reference to the list. Created by \ref list_init. + * @param data - Data to store in a list element + * @return + * - 0 : On success + * - -1 : Otherwise + */ +typedef int32_t (*f_add)(struct list_desc *list_desc, void *data); + +/** + * @brief Edit an element in the list. The content is replaced by new_data. + * @param list_desc - Reference to the list. Created by \ref list_init. + * @param new_data - New data to replace the old one + * @return + * - 0 : On success + * - -1 : Otherwise + */ +typedef int32_t (*f_edit)(struct list_desc *list_desc, void *new_data); + +/** + * @brief Read an element from the list. + * @param list_desc - Reference to the list. Created by \ref list_init. + * @param result - If not null, result is filled with: + * @param data - Content of the list element, NULL if some error occur. + * @return \n + * - 0 : On success + * - -1 : Otherwise + * @note If the content of an element can be 0 then the result must be checked + * to see if the functions has succeded + */ +typedef int32_t (*f_read)(struct list_desc *list_desc, void **data); + +/** + * @brief Read and remove an element from the list. + * @param list_desc - Reference to the list. Created by \ref list_init. + * @param result - If not null, result is filled with: + * @param data - Content of the list element, NULL if some error occur. + * @return + * - 0 : On success + * - -1 : Otherwise + */ +typedef int32_t (*f_get)(struct list_desc *list_desc, void **data); + +/** @} */ + +/** + * @enum adapter_type + * @brief Selects functionalities for functions in \ref list_desc + */ +enum adapter_type { + /** Default type is LIST_STACK */ + LIST_DEFAULT, + /** + * Functions for a FIFO list (First-in first-out). Elements are inserted + * in one end and extracted from the other end. + * - \e Push: Insert element + * - \e Pop: Get next element (Read and remove) + * - \e Top_next: Read next element + * - \e Back: Read first element + * - \e Swap: Edit the content of the next element + */ + LIST_QUEUE, + /** + * Functions for a LIFO list (Last-in first-out). Elements are inserted + * and extracted only from the same end. + * - \e Push: Insert element + * - \e Pop: Get top element (Read and remove) + * - \e Top_next: Read top element + * - \e Back: Read bottom element + * - \e Swap: Edit the content of the top element + */ + LIST_STACK, + /** + * Functions for ordered list. The order of element is determinated + * usinge the \ref f_cmp. + * - \e Push: Insert element + * - \e Pop: Get lowest element (Read and remove) + * - \e Top_next: Read lowest element + * - \e Back: Read the biggest element + * - \e Swap: Edit the lowest element + */ + LIST_PRIORITY_LIST +}; + +struct list_desc { + /** Refer to \ref adapter_type */ + f_add push; + /** Refer to \ref adapter_type */ + f_get pop; + /** Refer to \ref adapter_type */ + f_read top_next; + /** Refer to \ref adapter_type */ + f_read back; + /** Refer to \ref adapter_type */ + f_edit swap; + /** Structure storing the list internal parameters */ + void *priv_desc; +}; + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ + +int32_t list_init(struct list_desc **list_desc, + enum adapter_type type, + f_cmp comparator); +int32_t list_remove(struct list_desc *list_desc); +int32_t list_get_size(struct list_desc *list_desc, + uint32_t *out_size); + +/** + * @name Iterator functions + * An iterator is used to iterate through the list. For a list, any number of + * iterators can be created. All must be removed before removing a list. + * @{ + */ +int32_t iterator_init(struct iterator **iter, + struct list_desc *list_desc, + bool start); +int32_t iterator_remove(struct iterator *iter); +int32_t iterator_move(struct iterator *iter, int32_t steps); +int32_t iterator_move_to_idx(struct iterator *iter, int32_t idx); +int32_t iterator_find(struct iterator *iter, void *cmp_data); +int32_t iterator_insert(struct iterator *iter, void *data, + bool after); +int32_t iterator_edit(struct iterator *iter, void *new_data); +int32_t iterator_read(struct iterator *iter, void **data); +int32_t iterator_get(struct iterator *iter, void **data); +/** @}*/ + +/** + * @name Operations on the ends of the list + * These functions will operate on the first or last element of the list + * @{ + */ +int32_t list_add_first(struct list_desc *list_desc, void *data); +int32_t list_edit_first(struct list_desc *list_desc, + void *new_data); +int32_t list_read_first(struct list_desc *list_desc, void **data); +int32_t list_get_first(struct list_desc *list_desc, void **data); + +int32_t list_add_last(struct list_desc *list_desc, void *data); +int32_t list_edit_last(struct list_desc *list_desc, void *new_data); +int32_t list_read_last(struct list_desc *list_desc, void **data); +int32_t list_get_last(struct list_desc *list_desc, void **data); +/** @}*/ + +/** + * @name Operations by index + * These functions use an index to identify the element in the list. + * @{ + */ +int32_t list_add_idx(struct list_desc *list_desc, void *data, + uint32_t idx); +int32_t list_edit_idx(struct list_desc *list_desc, void *new_data, + uint32_t idx); +int32_t list_read_idx(struct list_desc *list_desc, void **data, + uint32_t idx); +int32_t list_get_idx(struct list_desc *list_desc, void **data, + uint32_t idx); +/** @}*/ + +/** + * @name Operations by comparation + * These functions use the specified \ref f_cmp at \ref list_init to identify + * the element this will operate on. + * @{ + */ +int32_t list_add_find(struct list_desc *list_desc, void *data); +int32_t list_edit_find(struct list_desc *list_desc, void *new_data, + void *cmp_data); +int32_t list_read_find(struct list_desc *list_desc, void **data, + void *cmp_data); +int32_t list_get_find(struct list_desc *list_desc, void **data, + void *cmp_data); +/** @}*/ + +#endif // _LIST_H_ diff --git a/df_datalink/src/include/spi.h b/df_datalink/src/include/spi.h new file mode 100644 index 0000000..26d0a84 --- /dev/null +++ b/df_datalink/src/include/spi.h @@ -0,0 +1,209 @@ +/***************************************************************************//** + * @file spi.h + * @brief Header file of SPI Interface + * @author DBogdan (dragos.bogdan@analog.com) +******************************************************************************** + * Copyright 2019(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#ifndef _SPI_H_ +#define _SPI_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include + +/******************************************************************************/ +/********************** Macros and Constants Definitions **********************/ +/******************************************************************************/ + +#define SPI_CPHA 0x01 +#define SPI_CPOL 0x02 +#define SPI_3WIRE 0x04 + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ + +/** + * @enum spi_mode + * @brief SPI configuration for clock phase and polarity. + */ +enum spi_mode { + /** Data on rising, shift out on falling */ + SPI_MODE_0 = (0 | 0), + /** Data on falling, shift out on rising */ + SPI_MODE_1 = (0 | SPI_CPHA), + /** Data on rising, shift out on falling */ + SPI_MODE_2 = (SPI_CPOL | 0), + /** Data on falling, shift out on rising */ + SPI_MODE_3 = (SPI_CPOL | SPI_CPHA), + /** Data on rising, shift out on falling */ + SPI_MODE_4 = SPI_3WIRE +}; + +/** + * @enum spi_bit_order + * @brief SPI configuration for bit order (MSB/LSB). + */ +enum spi_bit_order { + /** Most-significant bit (MSB) first */ + SPI_BIT_ORDER_MSB_FIRST = 0, + /** Least-significant bit (LSB) first */ + SPI_BIT_ORDER_LSB_FIRST = 1, +}; + +/** + * @struct spi_msg_list + * @brief List item describing a SPI transfer + */ +struct spi_msg { + /** Buffer with data to send. If NULL, 0x00 will be sent */ + uint8_t *tx_buff; + /** Buffer where to store data. If NULL, incoming data won't be saved */ + uint8_t *rx_buff; + /** Length of buffers. Must have equal size. */ + uint32_t bytes_number; + /** If set, CS will be deasserted after the transfer */ + uint8_t cs_change; + /** + * Minimum delay (in us) between the CS de-assert event of the current message + * and the assert of the next one. + */ + uint32_t cs_change_delay; + /** Delay (in us) between the CS assert and the first SCLK edge. */ + uint32_t cs_delay_first; + /** Delay (in us) between the last SCLK edge and the CS deassert */ + uint32_t cs_delay_last; +}; + +/** + * @struct spi_platform_ops + * @brief Structure holding SPI function pointers that point to the platform + * specific function + */ +struct spi_platform_ops ; + +/** + * @struct spi_init_param + * @brief Structure holding the parameters for SPI initialization + */ +struct spi_init_param { + /** Device ID */ + uint32_t device_id; + /** maximum transfer speed */ + uint32_t max_speed_hz; + /** SPI chip select */ + uint8_t chip_select; + /** SPI mode */ + enum spi_mode mode; + /** SPI bit order */ + enum spi_bit_order bit_order; + const struct spi_platform_ops *platform_ops; + /** SPI extra parameters (device specific) */ + void *extra; + /** Parent of the device */ + struct spi_desc *parent; +}; + +/** + * @struct spi_desc + * @brief Structure holding SPI descriptor. + */ +struct spi_desc { + /** Device ID */ + uint32_t device_id; + /** maximum transfer speed */ + uint32_t max_speed_hz; + /** SPI chip select */ + uint8_t chip_select; + /** SPI mode */ + enum spi_mode mode; + /** SPI bit order */ + enum spi_bit_order bit_order; + const struct spi_platform_ops *platform_ops; + /** SPI extra parameters (device specific) */ + void *extra; + /** Parent of the device */ + struct spi_desc *parent; +}; + +/** + * @struct spi_platform_ops + * @brief Structure holding SPI function pointers that point to the platform + * specific function + */ +struct spi_platform_ops { + /** SPI initialization function pointer */ + int32_t (*init)(struct spi_desc **, const struct spi_init_param *); + /** SPI write/read function pointer */ + int32_t (*write_and_read)(struct spi_desc *, uint8_t *, uint16_t); + /** SPI write function pointer */ + int32_t (*write_and_read_3wire)(struct spi_desc *, uint8_t *,uint8_t *,uint16_t, uint16_t); + /** Iterate over the spi_msg array and send all messages at once */ + int32_t (*transfer)(struct spi_desc *, struct spi_msg *, uint32_t); + /** SPI remove function pointer */ + int32_t (*remove)(struct spi_desc *); +}; + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ + +/* Initialize the SPI communication peripheral. */ +int32_t spi_init(struct spi_desc **desc, + const struct spi_init_param *param); + +/* Free the resources allocated by spi_init(). */ +int32_t spi_remove(struct spi_desc *desc); + +/* Write and read data to/from SPI. */ +int32_t spi_write_and_read(struct spi_desc *desc, + uint8_t *data, + uint16_t bytes_number); +int32_t spi_write_and_read_3wire(struct spi_desc *desc, + uint8_t *write_data, + uint8_t *read_data, + uint16_t write_bytes_number, + uint16_t read_bytes_number); + +/* Iterate over the spi_msg array and send all messages at once */ +int32_t spi_transfer(struct spi_desc *desc, + struct spi_msg *msgs, + uint32_t len); + + +#endif // _SPI_H_ diff --git a/df_datalink/src/include/timer.h b/df_datalink/src/include/timer.h new file mode 100644 index 0000000..99ee4f4 --- /dev/null +++ b/df_datalink/src/include/timer.h @@ -0,0 +1,159 @@ +/***************************************************************************//** +* @file timer.h +* @brief Timer control module header. +* @author Andrei Drimbarean (andrei.drimbarean@analog.com) +******************************************************************************** +* Copyright 2019(c) Analog Devices, Inc. +* +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* - Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* - Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* - Neither the name of Analog Devices, Inc. nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* - The use of this software may or may not infringe the patent rights +* of one or more patent holders. This license does not release you +* from the requirement that you obtain separate licenses from these +* patent holders to use this software. +* - Use of the software either in source or binary form, must be run +* on or directly connected to an Analog Devices Inc. component. +* +* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, MERCHANTABILITY +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#ifndef _SRC_TIMER_H_ +#define _SRC_TIMER_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ + +/** + * @struct timer_desc + * @brief Structure holding timer descriptor + */ +struct timer_desc { + /** timer ID */ + uint16_t id; + /** timer count frequency (Hz) */ + uint32_t freq_hz; + /** the number of ticks the timer counts until it resets */ + uint32_t ticks_count; + /** Timer platform operations */ + const struct timer_platform_ops *platform_ops; + /** timer extra parameters (device specific) */ + void *extra; +}; + +/** + * @struct timer_platform_ops + * @brief Structure holding timer function pointers that point to the platform + * specific function + */ +struct timer_platform_ops ; + +/** + * @struct timer_init_param + * @brief Structure holding the parameters for timer initialization + */ +struct timer_init_param { + /** timer ID */ + uint16_t id; + /** timer count frequency (Hz) */ + uint32_t freq_hz; + /** the number of ticks the timer counts until it resets */ + uint32_t ticks_count; + /** Timer platform operations */ + const struct timer_platform_ops *platform_ops; + /** timer extra parameters (device specific) */ + void *extra; +}; + +/** + * @struct timer_platform_ops + * @brief Structure holding timer function pointers that point to the platform + * specific function + */ +struct timer_platform_ops { + /** timer initialization function pointer */ + int32_t (*init)(struct timer_desc **, + const struct timer_init_param *); + /** timer start function pointer */ + int32_t (*start)(struct timer_desc *); + /** timer stop function pointer */ + int32_t (*stop)(struct timer_desc *); + /** timer get counter function pointer */ + int32_t (*counter_get)(struct timer_desc *, uint32_t *counter); + /** timer set counter function pointer */ + int32_t (*counter_set)(struct timer_desc *, uint32_t new_val); + /** timer get clock frequency function pointer */ + int32_t (*count_clk_get)(struct timer_desc *, uint32_t *freq_hz); + /** timer set clock frequency function pointer */ + int32_t (*count_clk_set)(struct timer_desc *, uint32_t freq_hz); + /** timer get elapsed time in nsec */ + int32_t (*get_elapsed_time_nsec)(struct timer_desc *, + uint64_t *elapsed_time); + /** timer remove function pointer */ + int32_t (*remove)(struct timer_desc *); +}; + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ + +/* Initialize hardware timer and the handler structure associated with it. */ +int32_t timer_init(struct timer_desc **desc, + struct timer_init_param *param); + +/* Free the memory allocated by timer_setup(). */ +int32_t timer_remove(struct timer_desc *desc); + +/* Start a timer. */ +int32_t timer_start(struct timer_desc *desc); + +/* Stop a timer from counting. */ +int32_t timer_stop(struct timer_desc *desc); + +/* Get the value of the counter register for the timer. */ +int32_t timer_counter_get(struct timer_desc *desc, + uint32_t *counter); + +/* Set the timer counter register value. */ +int32_t timer_counter_set(struct timer_desc *desc, + uint32_t new_val); + +/* Get the timer clock frequency. */ +int32_t timer_count_clk_get(struct timer_desc *desc, + uint32_t *freq_hz); + +/* Set the timer clock frequency. */ +int32_t timer_count_clk_set(struct timer_desc *desc, + uint32_t freq_hz); + +/* Get the elapsed time in nsec for the timer. */ +int32_t timer_get_elapsed_time_nsec(struct timer_desc *desc, + uint64_t *elapsed_time); + +#endif // _SRC_TIMER_H_ diff --git a/df_datalink/src/include/trng.h b/df_datalink/src/include/trng.h new file mode 100644 index 0000000..1c469b3 --- /dev/null +++ b/df_datalink/src/include/trng.h @@ -0,0 +1,115 @@ +/***************************************************************************//** + * @file trng.h + * @brief Header file of true random number generator + * @author Mihail Chindris (mihail.chindris@analog.com) +******************************************************************************** + * @copyright + * Copyright 2020(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#ifndef _TRNG_H_ +#define _TRNG_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ + +/** + * @struct trng_platform_ops + * @brief Structure holding TRNG function pointers that point to the platform + * specific function + */ +struct trng_platform_ops; + +/** + * @struct trng_desc + * @brief TRNG Descriptor + */ +struct trng_desc { + /** Platform ops */ + const struct trng_platform_ops *platform_ops; + /** Platform specific parameters */ + void *extra; +}; + +/** + * @struct trng_init_param + * @brief Init parameter for TRNG + */ +struct trng_init_param { + /** Device id */ + uint32_t dev_id; + /** Platform specific parameter */ + void *extra; + /** Platform ops */ + const struct trng_platform_ops *platform_ops; +}; + +/** + * @struct trng_platform_ops + * @brief Structure holding TRNG function pointers that point to the platform + * specific function + */ +struct trng_platform_ops { + /** TRNG initialization function pointer */ + int (*init)(struct trng_desc **, + const struct trng_init_param *); + /** Fill buffer with random numbers */ + int (*fill_buffer)(struct trng_desc *, uint8_t *, uint32_t); + /** TRNG remove function pointer */ + int (*remove)(struct trng_desc *); +}; + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ + +/* Initialize descriptor */ +int trng_init(struct trng_desc **desc, + const struct trng_init_param *param); + +/* Free resources allocated in descriptor */ +int trng_remove(struct trng_desc *desc); + +/* Fill buffer with random numbers */ +int trng_fill_buffer(struct trng_desc *desc, uint8_t *buff, + uint32_t len); + +#endif // _TRNG_H_ diff --git a/df_datalink/src/include/util.h b/df_datalink/src/include/util.h new file mode 100644 index 0000000..d75e08d --- /dev/null +++ b/df_datalink/src/include/util.h @@ -0,0 +1,194 @@ +/***************************************************************************//** + * @file util.h + * @brief Implementation of utility functions. + * @author DBogdan (dragos.bogdan@analog.com) +******************************************************************************** + * Copyright 2018(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ +#ifndef _UTIL_H_ +#define _UTIL_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include +#include +#include +/******************************************************************************/ +/********************** Macros and Constants Definitions **********************/ +/******************************************************************************/ +//#define __CRC_LSB +#define __BITSWAP_TABLE +#define __CRC_LSB +#define CRC16_INIT 0x0000 +#define CRC8_INIT 0x00 + +#define BIT(x) (1 << (x)) +#define ASSERT_BIT(x, ofst) (x | BIT(ofst)) +#define DEASSERT_BIT(x, ofst) (x & (~BIT(ofst))) + +#define ARRAY_SIZE(x) \ + (sizeof(x) / sizeof((x)[0])) + +#define DIV_ROUND_UP(x,y) \ + (((x) + (y) - 1) / (y)) +#define DIV_ROUND_CLOSEST(x, y) \ + (((x) + (y) / 2) / (y)) +#define DIV_ROUND_CLOSEST_ULL(x, y) \ + DIV_ROUND_CLOSEST(x, y) + +#define min(x, y) \ + (((x) < (y)) ? (x) : (y)) +#define min_t(type, x, y) \ + (type)min((type)(x), (type)(y)) + +#define max(x, y) \ + (((x) > (y)) ? (x) : (y)) +#define max_t(type, x, y) \ + (type)max((type)(x), (type)(y)) + +#define clamp(val, min_val, max_val) \ + (max(min((val), (max_val)), (min_val))) +#define clamp_t(type, val, min_val, max_val) \ + (type)clamp((type)(val), (type)(min_val), (type)(max_val)) + +#define swap(x, y) \ + {typeof(x) _tmp_ = (x); (x) = (y); (y) = _tmp_;} + +#define round_up(x,y) \ + (((x)+(y)-1)/(y)) + +#define BITS_PER_LONG 32 + +#define GENMASK(h, l) ({ \ + uint32_t t = (uint32_t)(~0UL); \ + t = t << (BITS_PER_LONG - (h - l + 1)); \ + t = t >> (BITS_PER_LONG - (h + 1)); \ + t; \ +}) + +#define bswap_constant_32(x) \ + ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \ + (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24)) + +#define bswap_constant_16(x) ((((x) & (uint16_t)0xff00) >> 8) | \ + (((x) & (uint16_t)0x00ff) << 8)) + +#define bit_swap_constant_8(x) \ + ((((x) & 0x80) >> 7) | \ + (((x) & 0x40) >> 5) | \ + (((x) & 0x20) >> 3) | \ + (((x) & 0x10) >> 1) | \ + (((x) & 0x08) << 1) | \ + (((x) & 0x04) << 3) | \ + (((x) & 0x02) << 5) | \ + (((x) & 0x01) << 7)) + +#define U16_MAX ((uint16_t)~0U) +#define S16_MAX ((int16_t)(U16_MAX>>1)) + +#define DIV_U64(x, y) (x / y) + +#define UNUSED_PARAM(x) ((void)x) + +#define shift_right(x, s) ((x) < 0 ? -(-(x) >> (s)) : (x) >> (s)) + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ + +void IO_Out32(uintptr_t addr, uint32_t value); +uint32_t IO_In32(uintptr_t addr); + +/* flip a byte left to right*/ +uint8_t byte_bit_swap(uint8_t byte); + +/* flip a 32bit word left to right */ +uint32_t word_bit_swap(uint32_t word); + +/* Returns the number of 1-bits in digit. */ +uint32_t count_ones(uint32_t word); + +/* convert a fixed number to a double. */ +double fix2double(int32_t val, uint8_t frac_bits); + +/* Find first set bit in word. */ +uint32_t find_first_set_bit(uint32_t word); +/* Find last set bit in word. */ +uint32_t find_last_set_bit(uint32_t word); +/* Locate the closest element in an array. */ +uint32_t find_closest(int32_t val, + const int32_t *array, + uint32_t size); +/* Shift the value and apply the specified mask. */ +uint32_t field_prep(uint32_t mask, uint32_t val); +/* Get a field specified by a mask from a word. */ +uint32_t field_get(uint32_t mask, uint32_t word); +/* Log base 2 of the given number. */ +int32_t log_base_2(uint32_t x); +/* Find greatest common divisor of the given two numbers. */ +uint32_t greatest_common_divisor(uint32_t a, + uint32_t b); +/* Calculate best rational approximation for a given fraction. */ +void rational_best_approximation(uint32_t given_numerator, + uint32_t given_denominator, + uint32_t max_numerator, + uint32_t max_denominator, + uint32_t *best_numerator, + uint32_t *best_denominator); +/* Calculate the number of set bits. */ +uint32_t hweight8(uint32_t word); +/* Calculate the quotient and the remainder of an integer division. */ +uint64_t do_div(uint64_t* n, + uint64_t base); +/* Unsigned 64bit divide with 64bit divisor and remainder */ +uint64_t div64_u64_rem(uint64_t dividend, uint64_t divisor, + uint64_t *remainder); +/* Unsigned 64bit divide with 32bit divisor with remainder */ +uint64_t div_u64_rem(uint64_t dividend, uint32_t divisor, uint32_t *remainder); +int64_t div_s64_rem(int64_t dividend, int32_t divisor, int32_t *remainder); +/* Unsigned 64bit divide with 32bit divisor */ +uint64_t div_u64(uint64_t dividend, uint32_t divisor); +int64_t div_s64(int64_t dividend, int32_t divisor); +/* Converts from string to int32_t */ +int32_t str_to_int32(const char *str); +/* Converts from string to uint32_t */ +uint32_t srt_to_uint32(const char *str); + +int crc16_gen(uint8_t* buffPtr, uint32_t dataLen, uint16_t poly, uint16_t* crcVal); +bool crc16_check(uint8_t* buffPtr, uint32_t dataLen, uint32_t crcOffset, uint16_t poly); +int crc8_gen(uint8_t* buffPtr, uint32_t dataLen, uint16_t poly, uint8_t* crcVal); +bool crc8_check(uint8_t* buffPtr, uint32_t dataLen, uint32_t crcOffset, uint16_t poly); +#endif // UTIL_H_ + diff --git a/df_datalink/src/lscript.ld b/df_datalink/src/lscript.ld new file mode 100644 index 0000000..9db1bc1 --- /dev/null +++ b/df_datalink/src/lscript.ld @@ -0,0 +1,291 @@ +/*******************************************************************/ +/* */ +/* This file is automatically generated by linker script generator.*/ +/* */ +/* Version: 2019.1.3 */ +/* */ +/* Copyright (c) 2010-2016 Xilinx, Inc. All rights reserved. */ +/* */ +/* Description : Cortex-A9 Linker Script */ +/* */ +/*******************************************************************/ + +_STACK_SIZE = DEFINED(_STACK_SIZE) ? _STACK_SIZE : 0x40000; +_HEAP_SIZE = DEFINED(_HEAP_SIZE) ? _HEAP_SIZE : 0x800000; + +_ABORT_STACK_SIZE = DEFINED(_ABORT_STACK_SIZE) ? _ABORT_STACK_SIZE : 1024; +_SUPERVISOR_STACK_SIZE = DEFINED(_SUPERVISOR_STACK_SIZE) ? _SUPERVISOR_STACK_SIZE : 2048; +_IRQ_STACK_SIZE = DEFINED(_IRQ_STACK_SIZE) ? _IRQ_STACK_SIZE : 1024; +_FIQ_STACK_SIZE = DEFINED(_FIQ_STACK_SIZE) ? _FIQ_STACK_SIZE : 1024; +_UNDEF_STACK_SIZE = DEFINED(_UNDEF_STACK_SIZE) ? _UNDEF_STACK_SIZE : 1024; + +/* Define Memories in the system */ + +MEMORY +{ + phy_data_interface_phy_rx_buff_axi_bram_ctrl_Mem0 : ORIGIN = 0x40000000, LENGTH = 0x1000 + phy_data_interface_phy_tx_buff_axi_bram_ctrl_Mem0 : ORIGIN = 0x42000000, LENGTH = 0x1000 + phy_data_interface_ant_config_axi_bram_ctrl_Mem0 : ORIGIN = 0x44000000, LENGTH = 0x2000 + ps7_ddr_0 : ORIGIN = 0x100000, LENGTH = 0x1FF00000 + ps7_qspi_linear_0 : ORIGIN = 0xFC000000, LENGTH = 0x1000000 + ps7_ram_0 : ORIGIN = 0x0, LENGTH = 0x30000 + ps7_ram_1 : ORIGIN = 0xFFFF0000, LENGTH = 0xFE00 +} + +/* Specify the default entry point to the program */ + +ENTRY(_vector_table) + +/* Define the sections, and where they are mapped in memory */ + +SECTIONS +{ +.text : { + KEEP (*(.vectors)) + *(.boot) + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + *(.plt) + *(.gnu_warning) + *(.gcc_execpt_table) + *(.glue_7) + *(.glue_7t) + *(.vfp11_veneer) + *(.ARM.extab) + *(.gnu.linkonce.armextab.*) +} > ps7_ddr_0 + +.init : { + KEEP (*(.init)) +} > ps7_ddr_0 + +.fini : { + KEEP (*(.fini)) +} > ps7_ddr_0 + +.rodata : { + __rodata_start = .; + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + __rodata_end = .; +} > ps7_ddr_0 + +.rodata1 : { + __rodata1_start = .; + *(.rodata1) + *(.rodata1.*) + __rodata1_end = .; +} > ps7_ddr_0 + +.sdata2 : { + __sdata2_start = .; + *(.sdata2) + *(.sdata2.*) + *(.gnu.linkonce.s2.*) + __sdata2_end = .; +} > ps7_ddr_0 + +.sbss2 : { + __sbss2_start = .; + *(.sbss2) + *(.sbss2.*) + *(.gnu.linkonce.sb2.*) + __sbss2_end = .; +} > ps7_ddr_0 + +.data : { + __data_start = .; + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + *(.jcr) + *(.got) + *(.got.plt) + __data_end = .; +} > ps7_ddr_0 + +.data1 : { + __data1_start = .; + *(.data1) + *(.data1.*) + __data1_end = .; +} > ps7_ddr_0 + +.got : { + *(.got) +} > ps7_ddr_0 + +.ctors : { + __CTOR_LIST__ = .; + ___CTORS_LIST___ = .; + KEEP (*crtbegin.o(.ctors)) + KEEP (*(EXCLUDE_FILE(*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + __CTOR_END__ = .; + ___CTORS_END___ = .; +} > ps7_ddr_0 + +.dtors : { + __DTOR_LIST__ = .; + ___DTORS_LIST___ = .; + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE(*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + __DTOR_END__ = .; + ___DTORS_END___ = .; +} > ps7_ddr_0 + +.fixup : { + __fixup_start = .; + *(.fixup) + __fixup_end = .; +} > ps7_ddr_0 + +.eh_frame : { + *(.eh_frame) +} > ps7_ddr_0 + +.eh_framehdr : { + __eh_framehdr_start = .; + *(.eh_framehdr) + __eh_framehdr_end = .; +} > ps7_ddr_0 + +.gcc_except_table : { + *(.gcc_except_table) +} > ps7_ddr_0 + +.mmu_tbl (ALIGN(16384)) : { + __mmu_tbl_start = .; + *(.mmu_tbl) + __mmu_tbl_end = .; +} > ps7_ddr_0 + +.ARM.exidx : { + __exidx_start = .; + *(.ARM.exidx*) + *(.gnu.linkonce.armexidix.*.*) + __exidx_end = .; +} > ps7_ddr_0 + +.preinit_array : { + __preinit_array_start = .; + KEEP (*(SORT(.preinit_array.*))) + KEEP (*(.preinit_array)) + __preinit_array_end = .; +} > ps7_ddr_0 + +.init_array : { + __init_array_start = .; + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + __init_array_end = .; +} > ps7_ddr_0 + +.fini_array : { + __fini_array_start = .; + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array)) + __fini_array_end = .; +} > ps7_ddr_0 + +.ARM.attributes : { + __ARM.attributes_start = .; + *(.ARM.attributes) + __ARM.attributes_end = .; +} > ps7_ddr_0 + +.sdata : { + __sdata_start = .; + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s.*) + __sdata_end = .; +} > ps7_ddr_0 + +.sbss (NOLOAD) : { + __sbss_start = .; + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.sb.*) + __sbss_end = .; +} > ps7_ddr_0 + +.tdata : { + __tdata_start = .; + *(.tdata) + *(.tdata.*) + *(.gnu.linkonce.td.*) + __tdata_end = .; +} > ps7_ddr_0 + +.tbss : { + __tbss_start = .; + *(.tbss) + *(.tbss.*) + *(.gnu.linkonce.tb.*) + __tbss_end = .; +} > ps7_ddr_0 + +.bss (NOLOAD) : { + __bss_start = .; + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + __bss_end = .; +} > ps7_ddr_0 + +_SDA_BASE_ = __sdata_start + ((__sbss_end - __sdata_start) / 2 ); + +_SDA2_BASE_ = __sdata2_start + ((__sbss2_end - __sdata2_start) / 2 ); + +/* Generate Stack and Heap definitions */ + +.heap (NOLOAD) : { + . = ALIGN(16); + _heap = .; + HeapBase = .; + _heap_start = .; + . += _HEAP_SIZE; + _heap_end = .; + HeapLimit = .; +} > ps7_ddr_0 + +.stack (NOLOAD) : { + . = ALIGN(16); + _stack_end = .; + . += _STACK_SIZE; + . = ALIGN(16); + _stack = .; + __stack = _stack; + . = ALIGN(16); + _irq_stack_end = .; + . += _IRQ_STACK_SIZE; + . = ALIGN(16); + __irq_stack = .; + _supervisor_stack_end = .; + . += _SUPERVISOR_STACK_SIZE; + . = ALIGN(16); + __supervisor_stack = .; + _abort_stack_end = .; + . += _ABORT_STACK_SIZE; + . = ALIGN(16); + __abort_stack = .; + _fiq_stack_end = .; + . += _FIQ_STACK_SIZE; + . = ALIGN(16); + __fiq_stack = .; + _undef_stack_end = .; + . += _UNDEF_STACK_SIZE; + . = ALIGN(16); + __undef_stack = .; +} > ps7_ddr_0 + +_end = .; +} + diff --git a/df_datalink/src/main.c b/df_datalink/src/main.c new file mode 100644 index 0000000..b10f785 --- /dev/null +++ b/df_datalink/src/main.c @@ -0,0 +1,734 @@ +/*****************************************************************************/ +/** + * Description: main.c + * + + * Date: 2023-05-07 13:19 + * Last Edit Time: [2023-05-07 20:32] + * + * Revisions: Rev 0.0 + * History: + * [2023-05-07]: Initial edition. + * + * Copyright(c) 2021 Beijing Institute of Technology. + * + ******************************************************************************/ + +/***************************** Include Files *********************************/ +// Standard +#include +#include +#include +// Xilinx +#include "sleep.h" +#include "xil_cache.h" +#include "xscugic.h" +#include "xscutimer.h" +#include "xgpiops.h" +#include "drivers/platform/xilinx_irq.h" +#include "drivers/platform/xilinx_timer.h" +#include "drivers/rf-transceiver/ad9361/ad9361_api.h" +#include "drivers/axi_core/spi_engine/spi_engine.h" +// App +#include "common.h" +#include "error.h" +#include "timer.h" +#include "config/app_config.h" +#include "dev_profile/dev_profile.h" +#include "systembus/systembus.h" +#include "networking/phy_layer/phy_layer.h" +#include "networking/link_layer/link_layer.h" + +/* D0-D7 D16-D31 was save and restored (standalone asm_vectors.S:83) */ +#define save_extra_fpu_context() __asm("VPUSH {d7-d15}") +#define restore_extra_fpu_context() __asm("VPOP {d7-d15}") + +/************************** Function Prototypes ******************************/ +int32_t SetupInterruptSystem(struct irq_ctrl_desc* descPtr); +void Phy_IntrHandler(void *context); +void ScuTimer_IntrHandler(void *context); +void Systembus_RxIntrHandler(void *context); +/************************** Constant Definitions *****************************/ +struct callback_desc phy_callback_desc = { + .callback = Phy_IntrHandler, + .ctx = NULL +}; +struct callback_desc sysbus_rx_callback_desc = { + .callback = Systembus_RxIntrHandler, + .ctx = NULL +}; +struct callback_desc sysbus_tx_callback_desc = { + .callback = Systembus_RxIntrHandler, + .ctx = NULL +}; +struct callback_desc scutm_callback_desc = { + .callback = ScuTimer_IntrHandler, + .ctx = NULL +}; +static PHY_CONFIG phyConfig = { + .devId = 0, + .baseAddr = PHY_BASEADDR, + .antBramId = PHY_ANTCONFIG_BRAM_DEVICE_ID, + .txBramId = PHY_TXBUFF_BRAM_DEVICE_ID, + .rxBramId = PHY_RXBUFF_BRAM_DEVICE_ID, + .hwXadcId = PHY_HW_XADC_DEVICE_ID +}; + +static L2_CONFIG linkConfig = { + .myType = L2_HEAD_NODE, + .myId = 1, + .headId = 1, + .netScale = 2, + .phyInstRef = NULL // pyhsical layer reference +}; + +//static L2_CONFIG linkConfig = { +// .myType = L2_MEMBER_NODE, +// .myId = 2, +// .headId = 1, +// .netScale = 2, +// .phyInstRef = NULL // pyhsical layer reference +//}; + +static SYSBUS_CONFIG sysbusConfig = { + .baseAddr = SYSBUS_BASE_ADDR, + .txQueueMax = 16, + .rxQueueMax = 16 +}; +/*********************** Driver Instance Definitions **************************/ +static struct irq_ctrl_desc *intcDescPtr;// General interrupt controller descriptor +static struct timer_desc *logTmPtr; +static SYSBUS *sysbusDescPtr; +static PHY_INST *phyInstPtr; +static L2_INST *linkInstPtr; + +static struct hmc7044_dev *hmc7044_inst; +static struct ad9361_reg_dev *ad9361_1_reg_inst; +static struct ad9361_reg_dev *ad9361_2_reg_inst; +//static struct ad9361_rf_phy *ad9361_phy; +//static struct ad9361_rf_phy *ad9361_2_phy; +/****************************************************************************/ +/** + * This function is responsible for initializing the SCUGIC instance, looking + * for the device configuration based on the unique device ID, initializing a + * SCUGIC instance, and initialize the interrupt at IRQ_F2P[0:0] + * + * @param intcDesc A pointer to INTC descriptor + * + * @return SUCCESS if initialize successful. + * FAILURE if initialization failed. + * + *****************************************************************************/ +int32_t SetupInterruptSystem(struct irq_ctrl_desc* descPtr) { + int32_t Status; + struct xil_irq_desc *xil_dev; + + Status = irq_ctrl_init(&descPtr, &intc_init_param); + if (Status != SUCCESS) { + DBG_ERROR("Intc Init FAILED, ErrorCode: %ld.\n", Status); + return Status; + } + + xil_dev = (struct xil_irq_desc*) (descPtr->extra); + + // Clear any pending interrupt flags + uint32_t intrState = XScuGic_CPUReadReg((XScuGic*)(xil_dev->instance), XSCUGIC_INT_ACK_OFFSET); + XScuGic_CPUWriteReg((XScuGic*)(xil_dev->instance), XSCUGIC_EOI_OFFSET, intrState); + + /* Initialize physical layer interrupt. */ + Status = irq_trigger_level_set(descPtr, PHY_INTR_ID, IRQ_EDGE_RISING); + if (Status != SUCCESS) { + DBG_ERROR("PHY_INTR trigger level set FAILED, ErrorCode: %ld.\n", Status); + return Status; + } + // Set highest interrupt priority + Status = irq_set_priority(descPtr, PHY_INTR_ID, 0x00); + if (Status != SUCCESS) { + DBG_ERROR("PHY_INTR priority level set FAILED, ErrorCode: %ld.\n", Status); + return Status; + } + // Connect the interrupt service routine isr1 to the interrupt controller + Status = irq_register_callback(descPtr, PHY_INTR_ID, &phy_callback_desc); + if (Status != SUCCESS) { + DBG_ERROR("PHY_INTR register callback FAILED, ErrorCode: %ld.\n", Status); + return Status; + } + + /* Initialize system bus interrupt. */ + Status = irq_trigger_level_set(descPtr, SYSBUS_TX_INTR_ID, IRQ_EDGE_RISING); + if (Status != SUCCESS) { + DBG_ERROR("PHY_INTR trigger level set FAILED, ErrorCode: %ld.\n", Status); + return Status; + } + // Set interrupt priority + Status = irq_set_priority(descPtr, SYSBUS_TX_INTR_ID, 0x08); + if (Status != SUCCESS) { + DBG_ERROR("PHY_INTR priority level set FAILED, ErrorCode: %ld.\n", Status); + return Status; + } + + // Connect the interrupt service routine isr1 to the interrupt controller + Status = irq_register_callback(descPtr, SYSBUS_TX_INTR_ID, &sysbus_tx_callback_desc); + if (Status != SUCCESS) { + DBG_ERROR("PHY_INTR register callback FAILED, ErrorCode: %ld.\n", Status); + return Status; + } + Status = irq_trigger_level_set(descPtr, SYSBUS_RX_INTR_ID, IRQ_EDGE_RISING); + if (Status != SUCCESS) { + DBG_ERROR("PHY_INTR trigger level set FAILED, ErrorCode: %ld.\n", Status); + return Status; + } + // Set interrupt priority + Status = irq_set_priority(descPtr, SYSBUS_RX_INTR_ID, 0x10); + if (Status != SUCCESS) { + DBG_ERROR("PHY_INTR priority level set FAILED, ErrorCode: %ld.\n", Status); + return Status; + } + + // Connect the interrupt service routine isr1 to the interrupt controller + Status = irq_register_callback(descPtr, SYSBUS_RX_INTR_ID, &sysbus_rx_callback_desc); + if (Status != SUCCESS) { + DBG_ERROR("PHY_INTR register callback FAILED, ErrorCode: %ld.\n", Status); + return Status; + } + + /* Initialize Scu timer interrupt. */ + // Connect the interrupt service routine isr1 to the interrupt controller + Status = irq_register_callback(descPtr, SCUTIMER_INTR_ID, &scutm_callback_desc); + if (Status != SUCCESS) { + DBG_ERROR("PHY_INTR register callback FAILED, ErrorCode: %ld.\n", Status); + return Status; + } + + // Enable interrupts + irq_enable(descPtr, PHY_INTR_ID); + irq_enable(descPtr, SYSBUS_RX_INTR_ID); + irq_enable(descPtr, SYSBUS_TX_INTR_ID); + irq_enable(descPtr, SCUTIMER_INTR_ID); + + // Enable Exceptions + Status = irq_global_enable(descPtr); + if (Status != SUCCESS) { + DBG_ERROR("IRQ global enable FAILED, ErrorCode: %ld.\n", Status); + return Status; + } + return SUCCESS; +} // SetupInterruptSystem + + + +/****************************************************************************/ +/** + * This function is a interrupt service routine for IRQ_F2P[1:1], IRQ_F2P[1:1] + * tells CPU that the data in OCM is ready! + * + * @param context + * + * @return None. + * + *****************************************************************************/ +void Phy_IntrHandler(void *context) { + int32_t Status; + Status = Linklayer_Proc(linkInstPtr); + if(Status != SUCCESS){ + DBG_ERROR("Link layer runs failed, with error code: %ld\n", Status); + _nop_(); + } +} // PhyIntr_Handler + +/*****************************************************************************/ +/** + * @brief Handler of System Bus RX done interrupt. + * + * @param context + * + * @return None. + * + ******************************************************************************/ +void Systembus_RxIntrHandler(void *context) { + int32_t Status; + Status = SystemBus_RxIntrHandler(sysbusDescPtr); + if (Status != SUCCESS) { + DBG_ERROR("SystemBus_RxIntrHandler exit with error code %ld,\n", Status); + } +} + +/*****************************************************************************/ +/** + * @brief Handler of System Bus TX done interrupt. + * + * @param context + * + * @return None. + * + ******************************************************************************/ +void Systembus_TxIntrHandler(void *context) { + int32_t Status; + Status = SystemBus_TxIntrHandler(sysbusDescPtr); + if (Status != SUCCESS) { + DBG_ERROR("SystemBus_TxIntrHandler exit with error code %ld,\n", Status); + } +} + +/*****************************************************************************/ +/** + * @brief Handler of ScuTimer interrupt. + * + * @param context + * + * @return None. + * + ******************************************************************************/ +void ScuTimer_IntrHandler(void *context) { + struct xil_timer_desc* xdesc; + xdesc = (struct xil_timer_desc*)(logTmPtr->extra); + if (XScuTimer_IsExpired((XScuTimer*)xdesc->instance)) { + // Update log + Phy_UpdateHwSate(phyInstPtr); + XScuTimer_ClearInterruptStatus((XScuTimer*)xdesc->instance); + } + else{ + DBG_WARNING("UNEXPECTED CALL of ScuTimer_IntrHandler\n"); + } +} + + +/*****************************************************************************/ +/** + * @brief Hardware_SwitchFreq + * + * @param dev + * @param freq + * + * @return None. + * + ******************************************************************************/ +int Hardware_SwitchFreq(struct ad9361_reg_dev *dev, ad9361TxFreq freq){ + int32_t status = 0; + uint8_t value = 0; + int32_t time_out_cnt = 0; + + switch(freq){ + case TX_FREQ_125: { + //************************************************************ + // Setup Tx Frequency-Dependent Syntheisizer Registers + //************************************************************ + status = ad9361_reg_write(dev, 0x027A, 0x4A); // Set VCO Output level[3:0] + status = ad9361_reg_write(dev, 0x0279, 0xC1); // Set Init ALC Value[3:0] and VCO Varactor[3:0] + status = ad9361_reg_write(dev, 0x0282, 0x0E); // Set VCO Bias Tcf[1:0] and VCO Bias Ref[2:0] + status = ad9361_reg_write(dev, 0x0278, 0x78); // Set VCO Cal Offset[3:0] + status = ad9361_reg_write(dev, 0x0285, 0x00); // Set VCO Cal Ref Tcf[2:0] + status = ad9361_reg_write(dev, 0x0291, 0x0B); // Set VCO Varactor Reference[3:0] + status = ad9361_reg_write(dev, 0x0290, 0x70); // Set VCO Varactor Ref Tcf[2:0] and VCO Varactor Offset[3:0] + status = ad9361_reg_write(dev, 0x027B, 0x94); // Set Synth Loop Filter charge pump current (Icp) + status = ad9361_reg_write(dev, 0x027E, 0xF4); // Set Synth Loop Filter C2 and C1 + status = ad9361_reg_write(dev, 0x027F, 0xDF); // Set Synth Loop Filter R1 and C3 + status = ad9361_reg_write(dev, 0x0280, 0x0A); // Set Synth Loop Filter R3 + + //************************************************************ + // Write Tx Frequency Words + //************************************************************ + status = ad9361_reg_write(dev, 0x0273, 0x00); // Write Tx Synth Fractional Freq Word[7:0] + status = ad9361_reg_write(dev, 0x0274, 0x00); // Write Tx Synth Fractional Freq Word[15:8] + status = ad9361_reg_write(dev, 0x0275, 0x00); // Write Tx Synth Fractional Freq Word[22:16] + status = ad9361_reg_write(dev, 0x0272, 0x00); // Write Tx Synth Integer Freq Word[10:8] + status = ad9361_reg_write(dev, 0x0271, 0xA0); // Write Tx Synth Integer Freq Word[7:0] (starts VCO cal) + status = ad9361_reg_write(dev, 0x0005, 0x57); // Set LO divider setting + + //************************************************************ + // Tx Quadrature Calibration Settings + //************************************************************ + status = ad9361_reg_write(dev, 0x00A0, 0x75); // Set TxQuadcal NCO frequency + status = ad9361_reg_write(dev, 0x00A3, 0xC0); // Set TxQuadcal NCO frequency (Only update bits [7:6]) + status = ad9361_reg_write(dev, 0x00A1, 0x7B); // Tx Quad Cal Configuration, Phase and Gain Cal Enable + status = ad9361_reg_write(dev, 0x00A9, 0xFF); // Set Tx Quad Cal Count + status = ad9361_reg_write(dev, 0x00A2, 0x7F); // Set Tx Quad Cal Kexp + status = ad9361_reg_write(dev, 0x00A5, 0x01); // Set Tx Quad Cal Magnitude Threshhold + status = ad9361_reg_write(dev, 0x00A6, 0x01); // Set Tx Quad Cal Magnitude Threshhold + status = ad9361_reg_write(dev, 0x00AA, 0x22); // Set Tx Quad Cal Gain Table index + status = ad9361_reg_write(dev, 0x00A4, 0xF0); // Set Tx Quad Cal Settle Count + status = ad9361_reg_write(dev, 0x00AE, 0x00); // Set Tx Quad Cal LPF Gain index incase Split table mode used + + status = ad9361_reg_write(dev, 0x0169, 0xC0); // Disable Rx Quadrature Calibration before Running Tx Quadrature Calibration + status = ad9361_reg_write(dev, 0x0016, 0x10); // Start Tx Quad cal + + break; + } + case TX_FREQ_126: { + //************************************************************ + // Setup Tx Frequency-Dependent Syntheisizer Registers + //************************************************************ + status = ad9361_reg_write(dev, 0x027A, 0x4A); // Set VCO Output level[3:0] + status = ad9361_reg_write(dev, 0x0279, 0xC1); // Set Init ALC Value[3:0] and VCO Varactor[3:0] + status = ad9361_reg_write(dev, 0x0282, 0x0E); // Set VCO Bias Tcf[1:0] and VCO Bias Ref[2:0] + status = ad9361_reg_write(dev, 0x0278, 0x78); // Set VCO Cal Offset[3:0] + status = ad9361_reg_write(dev, 0x0285, 0x00); // Set VCO Cal Ref Tcf[2:0] + status = ad9361_reg_write(dev, 0x0291, 0x0B); // Set VCO Varactor Reference[3:0] + status = ad9361_reg_write(dev, 0x0290, 0x70); // Set VCO Varactor Ref Tcf[2:0] and VCO Varactor Offset[3:0] + status = ad9361_reg_write(dev, 0x027B, 0x93); // Set Synth Loop Filter charge pump current (Icp) + status = ad9361_reg_write(dev, 0x027E, 0xF4); // Set Synth Loop Filter C2 and C1 + status = ad9361_reg_write(dev, 0x027F, 0xDF); // Set Synth Loop Filter R1 and C3 + status = ad9361_reg_write(dev, 0x0280, 0x0A); // Set Synth Loop Filter R3 + + //************************************************************ + // Write Tx Frequency Words + //************************************************************ + status = ad9361_reg_write(dev, 0x0273, 0x06); // Write Tx Synth Fractional Freq Word[7:0] + status = ad9361_reg_write(dev, 0x0274, 0xD7); // Write Tx Synth Fractional Freq Word[15:8] + status = ad9361_reg_write(dev, 0x0275, 0x23); // Write Tx Synth Fractional Freq Word[22:16] + status = ad9361_reg_write(dev, 0x0272, 0x00); // Write Tx Synth Integer Freq Word[10:8] + status = ad9361_reg_write(dev, 0x0271, 0xA1); // Write Tx Synth Integer Freq Word[7:0] (starts VCO cal) + status = ad9361_reg_write(dev, 0x0005, 0x57); // Set LO divider setting + + //************************************************************ + // Tx Quadrature Calibration Settings + //************************************************************ + status = ad9361_reg_write(dev, 0x00A0, 0x75); // Set TxQuadcal NCO frequency + status = ad9361_reg_write(dev, 0x00A3, 0xC0); // Set TxQuadcal NCO frequency (Only update bits [7:6]) + status = ad9361_reg_write(dev, 0x00A1, 0x7B); // Tx Quad Cal Configuration, Phase and Gain Cal Enable + status = ad9361_reg_write(dev, 0x00A9, 0xFF); // Set Tx Quad Cal Count + status = ad9361_reg_write(dev, 0x00A2, 0x7F); // Set Tx Quad Cal Kexp + status = ad9361_reg_write(dev, 0x00A5, 0x01); // Set Tx Quad Cal Magnitude Threshhold + status = ad9361_reg_write(dev, 0x00A6, 0x01); // Set Tx Quad Cal Magnitude Threshhold + status = ad9361_reg_write(dev, 0x00AA, 0x22); // Set Tx Quad Cal Gain Table index + status = ad9361_reg_write(dev, 0x00A4, 0xF0); // Set Tx Quad Cal Settle Count + status = ad9361_reg_write(dev, 0x00AE, 0x00); // Set Tx Quad Cal LPF Gain index incase Split table mode used + + status = ad9361_reg_write(dev, 0x0169, 0xC0); // Disable Rx Quadrature Calibration before Running Tx Quadrature Calibration + status = ad9361_reg_write(dev, 0x0016, 0x10); // Start Tx Quad cal + + break; + } + case TX_FREQ_4125: { + //************************************************************ + // Setup Tx Frequency-Dependent Syntheisizer Registers + //************************************************************ + status = ad9361_reg_write(dev, 0x027A, 0x4A); // Set VCO Output level[3:0] + status = ad9361_reg_write(dev, 0x0279, 0xC1); // Set Init ALC Value[3:0] and VCO Varactor[3:0] + status = ad9361_reg_write(dev, 0x0282, 0x0E); // Set VCO Bias Tcf[1:0] and VCO Bias Ref[2:0] + status = ad9361_reg_write(dev, 0x0278, 0x78); // Set VCO Cal Offset[3:0] + status = ad9361_reg_write(dev, 0x0285, 0x00); // Set VCO Cal Ref Tcf[2:0] + status = ad9361_reg_write(dev, 0x0291, 0x0B); // Set VCO Varactor Reference[3:0] + status = ad9361_reg_write(dev, 0x0290, 0x70); // Set VCO Varactor Ref Tcf[2:0] and VCO Varactor Offset[3:0] + status = ad9361_reg_write(dev, 0x027B, 0x93); // Set Synth Loop Filter charge pump current (Icp) + status = ad9361_reg_write(dev, 0x027E, 0xF4); // Set Synth Loop Filter C2 and C1 + status = ad9361_reg_write(dev, 0x027F, 0xDF); // Set Synth Loop Filter R1 and C3 + status = ad9361_reg_write(dev, 0x0280, 0x0A); // Set Synth Loop Filter R3 + + //************************************************************ + // Write Rx Frequency Words + //************************************************************ + status = ad9361_reg_write(dev, 0x0273, 0x00); // Write Tx Synth Fractional Freq Word[7:0] + status = ad9361_reg_write(dev, 0x0274, 0x00); // Write Tx Synth Fractional Freq Word[15:8] + status = ad9361_reg_write(dev, 0x0275, 0x00); // Write Tx Synth Fractional Freq Word[22:16] + status = ad9361_reg_write(dev, 0x0272, 0x00); // Write Tx Synth Integer Freq Word[10:8] + status = ad9361_reg_write(dev, 0x0271, 0xA5); // Write Tx Synth Integer Freq Word[7:0] (starts VCO cal) + status = ad9361_reg_write(dev, 0x0005, 0x07); // Set LO divider setting + + //************************************************************ + // Tx Quadrature Calibration Settings + //************************************************************ + status = ad9361_reg_write(dev, 0x00A0, 0x75); // Set TxQuadcal NCO frequency + status = ad9361_reg_write(dev, 0x00A3, 0xC0); // Set TxQuadcal NCO frequency (Only update bits [7:6]) + status = ad9361_reg_write(dev, 0x00A1, 0x7B); // Tx Quad Cal Configuration, Phase and Gain Cal Enable + status = ad9361_reg_write(dev, 0x00A9, 0xFF); // Set Tx Quad Cal Count + status = ad9361_reg_write(dev, 0x00A2, 0x7F); // Set Tx Quad Cal Kexp + status = ad9361_reg_write(dev, 0x00A5, 0x01); // Set Tx Quad Cal Magnitude Threshhold + status = ad9361_reg_write(dev, 0x00A6, 0x01); // Set Tx Quad Cal Magnitude Threshhold + status = ad9361_reg_write(dev, 0x00AA, 0x28); // Set Tx Quad Cal Gain Table index + status = ad9361_reg_write(dev, 0x00A4, 0xF0); // Set Tx Quad Cal Settle Count + status = ad9361_reg_write(dev, 0x00AE, 0x04); // Set Tx Quad Cal LPF Gain index incase Split table mode used + + status = ad9361_reg_write(dev, 0x0169, 0xC0); // Disable Rx Quadrature Calibration before Running Tx Quadrature Calibration + status = ad9361_reg_write(dev, 0x0016, 0x10); // Start Tx Quad cal + + break; + } + + // Wait for cal to complete (Done when 0x016[4]==0) + time_out_cnt = 0; + do{ + status |= ad9361_reg_read(dev, 0x0016, &value); + mdelay(1);// Wait 1ms + time_out_cnt++; + } while((value & 0x10) != 0x00 && time_out_cnt <= AD9361_TIMEOUT_TH); + } + + return status; +} + +/*****************************************************************************/ +/** + * @brief Hardware_Init + * + * @param none. + * + * @return None. + * + ******************************************************************************/ +int Hardware_Init(void) { + int32_t Status; + XGpioPs Gpio; + XGpioPs_Config *ConfigPtr; + ConfigPtr = XGpioPs_LookupConfig(AD9361_GPIO_DEVICE_ID); + Status = XGpioPs_CfgInitialize(&Gpio, ConfigPtr, ConfigPtr->BaseAddr); + if (Status != XST_SUCCESS) + { + return XST_FAILURE; + } + + /**********************************************************/ + /****************** HMC7044 Configuration *****************/ + /**********************************************************/ + Status = hmc7044_init(&hmc7044_inst, &hmc7044_default_init_param); + if (Status != SUCCESS) { + DBG_ERROR("hmc7044_init() error: %ld\n", Status); + return FAILURE; + } + + /**********************************************************/ + /***************** AD9361-1 Configuration *****************/ + /**********************************************************/ + XGpioPs_SetDirectionPin(&Gpio, AD9361_1_TXNRX, AD9361_GPIO_OUTPUT); + XGpioPs_SetDirectionPin(&Gpio, AD9361_1_ENABLE, AD9361_GPIO_OUTPUT); + XGpioPs_SetDirectionPin(&Gpio, AD9361_1_EN_AGC, AD9361_GPIO_OUTPUT); + XGpioPs_SetDirectionPin(&Gpio, AD9361_1_RESET_B, AD9361_GPIO_OUTPUT); + + ad9361_reg_init(&ad9361_1_reg_inst, &ad9361_1_reg_default_init_param); + XGpioPs_WritePin(&Gpio, AD9361_1_ENABLE, 0); + ad9361_reg_config(ad9361_1_reg_inst); + XGpioPs_WritePin(&Gpio, AD9361_1_ENABLE, 1); + +// Status = ad9361_init(&ad9361_phy, &ad9361_default_init_param); +// if (Status != XST_SUCCESS){ +// return XST_FAILURE; +// }else{ +// printf("Configurate AD9361 Completely!\n"); +// } +// ad9361_set_tx_fir_config(ad9361_phy, tx_fir_config); +// ad9361_set_rx_fir_config(ad9361_phy, rx_fir_config); + + /**********************************************************/ + /***************** AD9361-2 Configuration *****************/ + /**********************************************************/ + XGpioPs_SetDirectionPin(&Gpio, AD9361_2_TXNRX, AD9361_GPIO_OUTPUT); + XGpioPs_SetDirectionPin(&Gpio, AD9361_2_ENABLE, AD9361_GPIO_OUTPUT); + XGpioPs_SetDirectionPin(&Gpio, AD9361_2_EN_AGC, AD9361_GPIO_OUTPUT); + XGpioPs_SetDirectionPin(&Gpio, AD9361_2_RESET_B, AD9361_GPIO_OUTPUT); + + ad9361_reg_init(&ad9361_2_reg_inst, &ad9361_2_reg_default_init_param); + XGpioPs_WritePin(&Gpio, AD9361_2_ENABLE, 0); + ad9361_reg_config(ad9361_2_reg_inst); + XGpioPs_WritePin(&Gpio, AD9361_2_ENABLE, 1); + +// uint8_t rd_back; +// Status = ad9361_reg_read(ad9361_1_reg_inst, 0x0002, &rd_back); +// Status = ad9361_reg_read(ad9361_2_reg_inst, 0x0002, &rd_back); + + /**********************************************************/ + /******* AD9361 Baseband Multichip Synchronization ********/ + /**********************************************************/ + XGpioPs_SetDirectionPin(&Gpio, AD9361_SYNC, AD9361_GPIO_OUTPUT); + XGpioPs_SetDirectionPin(&Gpio, AD9361_RX_FIFO_RST, AD9361_GPIO_OUTPUT); + + // SYNC BBPLL and DIGITAL SAMPLING CLOCKS + ad9361_reg_write(ad9361_1_reg_inst, 0x0001, 0x0D); // MCS RF Enable; MCS BBPLL Enable; MCS BB Enable + ad9361_reg_write(ad9361_2_reg_inst, 0x0001, 0x0D); + ad9361_reg_write(ad9361_1_reg_inst, 0x0047, 0x80); // MCS refclk Scale Enable + ad9361_reg_write(ad9361_2_reg_inst, 0x0047, 0x80); + XGpioPs_WritePin(&Gpio, AD9361_SYNC, 0); + mdelay(20); + XGpioPs_WritePin(&Gpio, AD9361_SYNC, 1); // Input a rising-edge pulse to the SYNC_IN pin + mdelay(500); + XGpioPs_WritePin(&Gpio, AD9361_SYNC, 0); + mdelay(2000); + ad9361_reg_write(ad9361_1_reg_inst, 0x0001, 0x0B); // MCS RF Enable; MCS Digital CLK Enable ; MCS BB Enable + ad9361_reg_write(ad9361_2_reg_inst, 0x0001, 0x0B); + XGpioPs_WritePin(&Gpio, AD9361_SYNC, 1); // Input another rising-edge pulse to the SYNC_IN pin + mdelay(500); + XGpioPs_WritePin(&Gpio, AD9361_SYNC, 0); + ad9361_reg_write(ad9361_1_reg_inst, 0x0001, 0x08); // clear MCS bits + ad9361_reg_write(ad9361_2_reg_inst, 0x0001, 0x08); + + XGpioPs_WritePin(&Gpio, AD9361_RX_FIFO_RST, 0); + mdelay(20); + XGpioPs_WritePin(&Gpio, AD9361_RX_FIFO_RST, 1); + mdelay(20); + XGpioPs_WritePin(&Gpio, AD9361_RX_FIFO_RST, 0); + + /**********************************************************/ + /********* AD9361 Multichip Rx Phase Calibration **********/ + /**********************************************************/ + XGpioPs_SetDirectionPin(&Gpio, AD9361_TX_SWITCH, AD9361_GPIO_OUTPUT); + XGpioPs_SetDirectionPin(&Gpio, AD9361_1_CAL_START, AD9361_GPIO_OUTPUT); + XGpioPs_SetDirectionPin(&Gpio, AD9361_1_CAL_DONE, AD9361_GPIO_INPUT); + XGpioPs_SetDirectionPin(&Gpio, AD9361_2_CAL_START, AD9361_GPIO_OUTPUT); + XGpioPs_SetDirectionPin(&Gpio, AD9361_2_CAL_DONE, AD9361_GPIO_INPUT); + + // switch to lower frequency + Status = Hardware_SwitchFreq(ad9361_1_reg_inst, TX_FREQ_126); + XGpioPs_WritePin(&Gpio, AD9361_TX_SWITCH, 1); + mdelay(20); + + // switch rx channel + Status = ad9361_reg_write(ad9361_1_reg_inst, 0x0004, 0x30); + Status = ad9361_reg_write(ad9361_2_reg_inst, 0x0004, 0x30); + + // enable dual ad9361 tx channels + Status = ad9361_reg_write(ad9361_1_reg_inst, 0x0002, 0xE4); // Setup Tx Digital Filters/ Channels + + // switch ad9361 tx channel + Status = ad9361_reg_write(ad9361_1_reg_inst, 0x0004, 0x70); // Select Rx input pin(A,B,C)/ Tx out pin (A,B) + mdelay(20); + + // begin to calibrate the 1st ad9361 + XGpioPs_WritePin(&Gpio, AD9361_1_CAL_START, 0); + XGpioPs_WritePin(&Gpio, AD9361_1_CAL_START, 1); + mdelay(1); + XGpioPs_WritePin(&Gpio, AD9361_1_CAL_START, 0); + + // read calibration status + int32_t time_out_cnt = 0; + do{ + mdelay(1);// Wait 1ms + time_out_cnt++; + }while(((XGpioPs_ReadPin(&Gpio, AD9361_1_CAL_DONE) == 0) && time_out_cnt <= AD9361_TIMEOUT_TH)); + + if (time_out_cnt == AD9361_TIMEOUT_TH){ + return FAILURE; + } + + // begin to calibrate the 2nd ad9361 + XGpioPs_WritePin(&Gpio, AD9361_2_CAL_START, 1); + mdelay(1); + XGpioPs_WritePin(&Gpio, AD9361_2_CAL_START, 0); + + // read calibration status + time_out_cnt = 0; + do{ + mdelay(1);// Wait 1ms + time_out_cnt++; + }while(((XGpioPs_ReadPin(&Gpio,AD9361_2_CAL_DONE) == 0) && time_out_cnt <= AD9361_TIMEOUT_TH)); + + if (time_out_cnt == AD9361_TIMEOUT_TH){ + return FAILURE; + } + + // enable single ad9361 tx channels + Status = ad9361_reg_write(ad9361_1_reg_inst, 0x0002, 0xA4); // Setup Tx Digital Filters/ Channels + + // switch ad9361 tx & rx channel + Status = ad9361_reg_write(ad9361_1_reg_inst, 0x0004, 0x03); + Status = ad9361_reg_write(ad9361_2_reg_inst, 0x0004, 0x03); + + // switch to higher frequency + Status = Hardware_SwitchFreq(ad9361_1_reg_inst, TX_FREQ_4125); + XGpioPs_WritePin(&Gpio, AD9361_TX_SWITCH, 0); + + DBG_PRINT("Done.\n"); + + return 0; +} + +/*****************************************************************************/ +/** + * @brief Main function, initialize all the device needed, initialize + * interrupt system, halt in while(1) wait for event interrupt. + * + * @param none. + * + * @return + * + ******************************************************************************/ +int main(void) { + int Status; + DBG_PRINT("Application Version: %2d.%2d.%4d.\n", _APP_VER_MAIN, _APP_VER_MINOR, _APP_VER_PATCH); + + /* System Monitor Initialize */ + Status = SysMonitor_Init(); + if (Status == SUCCESS) { + DBG_PRINT("System monitor Init SUCCESS! \n"); + } + else { + DBG_PRINT("System monitor Init FAILED! \n"); + return Status; + } + + Status = Hardware_Init(); + if (Status == SUCCESS) { + DBG_PRINT("Hardware Init SUCCESS! \n"); + } + else { + DBG_PRINT("Hardware Init FAILED! \n"); + return Status; + } + + /* Physical Layer Initialize */ + Status = Phy_InstInit(&phyInstPtr, &phyConfig); + if (Status == SUCCESS) { + DBG_PRINT("Physical layer Init SUCCESS! \n"); + } + else { + DBG_PRINT("Physical layer FAILED! \n"); + return Status; + } + + /* Link Layer Initialize */ + linkConfig.phyInstRef = phyInstPtr; + Status = Linklayer_Init(&linkInstPtr, &linkConfig); + if (Status == SUCCESS) { + DBG_PRINT("LinkLayer Init SUCCESS! \n"); + } + else { + DBG_PRINT("Linklayer Init FAILED! \n"); + return Status; + } + + /* System Bus Initialize */ + Status = SystemBus_Init(&sysbusDescPtr, &sysbusConfig); + if (Status != SUCCESS) { + DBG_ERROR("Systembus init FAILED, with error code: %d\n", Status); + return Status; + } + + /* System Monitor log timer Initialize */ + Status = timer_init(&logTmPtr, &scutimer_init_param); + if (Status != SUCCESS) { + DBG_ERROR("SCU Timer init FAILED, with error code: %d\n", Status); + return Status; + } + + /* interrupts Initialize */ + Status = SetupInterruptSystem(intcDescPtr); + if (Status == SUCCESS) { + DBG_INFO("Interrupt system setup SUCCESS!\n"); + } + else { + DBG_ERROR("Interrupt system setup FAILED, ErrorCode: %d.\n", Status); + return Status; + } + + // Start System Monitor logging. + timer_start(logTmPtr); + + Phy_Start(phyInstPtr); + DBG_PRINT("Physical started...\n"); + + while (true) { + // System bus handler + if (SystemBus_IsReqPendding(sysbusDescPtr)) { + Status = SystemBus_HandleCmd(sysbusDescPtr); + if(Status != SUCCESS) { + DBG_ERROR("SystemBus_HandleCmd exit with ErrorCode: %d.\n", Status); + } + } + if (SystemBus_IsRsqPendding(sysbusDescPtr) && (!SystemBus_IsTxBusy(sysbusDescPtr))) { + // FIXME: Required by 12 (CASC) + udelay(200); + Status = SystemBus_MakeResp(sysbusDescPtr); + if(Status != SUCCESS) { + DBG_ERROR("SystemBus_HandleCmd exit with ErrorCode: %d.\n", Status); + } + } + } +} // main diff --git a/df_datalink/src/networking/link_layer/framing.c b/df_datalink/src/networking/link_layer/framing.c new file mode 100644 index 0000000..6238e79 --- /dev/null +++ b/df_datalink/src/networking/link_layer/framing.c @@ -0,0 +1,132 @@ +/*****************************************************************************/ +/** + * Description: Functions for framing operations. + * + * Date: 2022-07-16 14:17 + * LastEditors: Fan Hao + * LastEditTime: 2022-07-16 17:11 + * Revisions: Rev 0.0 + * History: + * [2022-07-16]: Description of modification. + * + * Copyright(c) 2022 Beijing Institute of Technology. + * Lab of Communication and Networking + * +******************************************************************************/ + +/***************************** Include Files *********************************/ +#include +#include "error.h" +#include "common.h" +#include "msg_def.h" +#include "link_layer.h" +#include "../config/app_config.h" + +/************************** Constant Definitions *****************************/ + + +/*****************************************************************************/ +/** + * @brief Generate crc of specified data. + * + * @param dataBuff pointer to data buffer. + * dataLen length of specified data. + * crcType type of crc + * crc a pointer to 32 bit crc container. + * + * @return FAILURE crc type not support. + * SUCCESS + * + ******************************************************************************/ +static int32_t L2_CrcGen(uint8_t* dataBuff, uint32_t dataLen, L2_CRC_TYPE crcType, uint32_t* crc){ + ASSERT(dataBuff != NULL); + int32_t Status; + switch (crcType){ + case L2_CRC16_1021: + Status = crc16_gen(dataBuff, dataLen, 0x1021, (uint16_t*)crc); + break; + case L2_CRC16_8005: + Status = crc16_gen(dataBuff, dataLen, 0x8005, (uint16_t*)crc); + break; + case L2_CRC8_31: + Status = crc8_gen(dataBuff, dataLen, 0x31, (uint8_t*)crc); + break; + default: + Status = EPARAM; + break; + } + return Status; +} + +/*****************************************************************************/ +/** + * @brief Append a crc of specified data, to a specified position. + * + * @param dataBuff pointer to data buffer. + * dataLen length of specified data. + * crcPos position of crc insert position + * crcType type of crc + * + * @return FAILURE crc type not support. + * SUCCESS + * + ******************************************************************************/ +int32_t L2_CrcAppend(uint8_t* dataBuff, uint32_t dataLen, uint32_t crcPos, L2_CRC_TYPE crcType){ + ASSERT(dataBuff != NULL); + int32_t Status; + uint32_t crcVal; + uint8_t* crcPtr; + crcPtr = dataBuff + crcPos; + Status = L2_CrcGen(dataBuff,dataLen, crcType, &crcVal); + if(Status != SUCCESS){ + return Status; + } + switch (crcType){ + case L2_CRC16_1021: + *(crcPtr+1) = (uint8_t)(crcVal>>8); + *crcPtr = (uint8_t)(crcVal); + break; + case L2_CRC16_8005: + *(crcPtr+1) = (uint8_t)(crcVal>>8); + *crcPtr = (uint8_t)(crcVal); + break; + case L2_CRC8_31: + *crcPtr = (uint8_t)crcVal; + break; + default: + Status = EPARAM; + break; + } + return Status; +} + +/*****************************************************************************/ +/** + * @brief Check data validation by crc. + * + * @param dataBuff pointer to data buffer. + * dataLen length of specified data. + * crcType type of crc + * + * @return FAILURE crc type not support. + * SUCCESS + * + ******************************************************************************/ +bool L2_CrcCheck(uint8_t* dataBuff, uint32_t dataLen, L2_CRC_TYPE crcType){ + ASSERT(dataBuff != NULL); + int32_t Status; + uint32_t crcVal; + crcVal = 0; + Status = L2_CrcGen(dataBuff, dataLen, crcType, &crcVal); + if(Status == SUCCESS){ + if(crcVal == 0){ + return true; + } + else{ + return false; + } + } + else { + return false; + } +} diff --git a/df_datalink/src/networking/link_layer/geometry/coord.c b/df_datalink/src/networking/link_layer/geometry/coord.c new file mode 100644 index 0000000..68d4108 --- /dev/null +++ b/df_datalink/src/networking/link_layer/geometry/coord.c @@ -0,0 +1,195 @@ +// +// Copyright (C) 2020 OpenSim Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// + +#include +#include "coord.h" + + +const COORD COORD_NIL = {NAN, NAN, NAN}; +const COORD COORD_ZERO = {0.0, 0.0, 0.0}; +const COORD COORD_ONE = {1.0, 1.0, 1.0}; +const COORD COORD_X_AXIS = {1.0, 0.0, 0.0}; +const COORD COORD_Y_AXIS = {0.0, 1.0, 0.0}; +const COORD COORD_Z_AXIS = {0.0, 0.0, 1.0}; + + /** @brief Subtracts two coordinate vectors. */ +COORD Coord_Sub(COORD a, COORD b) { + COORD ret; + ret.x = a.x - b.x; + ret.y = a.y - b.y; + ret.z = a.z - b.z; + return ret; +} + +/** @brief Adds two coordinate vectors. */ +COORD Coord_Add(COORD a, COORD b) { + COORD ret; + ret.x = a.x + b.x; + ret.y = a.y + b.y; + ret.z = a.z + b.z; + return ret; +} + +/** @brief Multiplies a coordinate vector by a real number. */ +void Coord_ScalarMult(COORD *a, double t) { + a->x *= t; + a->y *= t; + a->z *= t; +} + +/** @brief Multiplies a coordinate vector by a real number. */ +COORD Coord_GetScalarMult(COORD a, double t) { + COORD ret; + ret.x = a.x * t; + ret.y = a.y * t; + ret.z = a.z * t; + return ret; +} + +/** @brief Divides a coordinate vector by a real number. */ +void Coord_ScalarDiv(COORD *a, double t) { + a->x /= t; + a->y /= t; + a->z /= t; +} + +/** @brief Divides a coordinate vector by a real number. */ +COORD Coord_GetScalarDiv(COORD a, double t) { + COORD ret; + ret.x = a.x / t; + ret.y = a.y / t; + ret.z = a.z / t; + return ret; +} + +/** @brief Dot product. */ +inline double Coord_Dot(COORD a, COORD b) { + return (a.x * b.x + a.y * b.y + a.z * b.z); +} + +/** @brief Cross product. */ +COORD Coord_Cross(COORD a, COORD b) { + COORD ret; + ret.x = a.y * b.z - a.z * b.y; + ret.y = a.z * b.x - a.x * b.z; + ret.z = a.x * b.y - a.y * b.x; + return ret; +} + +/** @brief Multiplies two coordinate vector in elementwise. */ +COORD Coord_ElementwiseMult(COORD a, COORD b) { + COORD ret; + ret.x = a.x * b.x; + ret.y = a.y * b.y; + ret.z = a.z * b.z; + return ret; +} + +/** @brief Divides two coordinate vector in elementwise. */ +COORD Coord_ElementwiseDiv(COORD a, COORD b) { + COORD ret; + ret.x = a.x / b.x; + ret.y = a.y / b.y; + ret.z = a.z / b.z; + return ret; +} + +/** @brief Calculate a coordinate vector length^2 (omits calling square root). */ +double Coord_SquareLength(COORD a) { + return (a.x*a.x + a.y*a.y + a.z*a.z); +} + +/** @brief Calculate a coordinate vector length. */ +double Coord_Length(COORD a) { + return sqrt(Coord_SquareLength(a)); +} + +/** @brief Calculate two coordinates' distance. */ +double Coord_Distance(COORD a, COORD b) { + return Coord_Length(Coord_Sub(a, b)); +} + +/** @brief Normalize coordinate vector. */ +void Coord_Normalize(COORD *a) { + Coord_ScalarDiv(a, Coord_Length(*a)); +} + +/** @brief Normalize coordinate vector. */ +COORD Coord_GetNormalized(COORD a) { + Coord_Normalize(&a); + return a; +} + +/** @brief Returns the angle between the two vectors. */ +double Coord_Angle(COORD a, COORD b) { + Coord_Normalize(&a); + Coord_Normalize(&b); + return acos(Coord_Dot(a, b)); +} + + +// Additional Coordinates convert +// TODO: Confirm correctness +/** @brief Convert coordinate from Launch coordinate system to ECEF. */ +COORD Coord_Launch2Ecef(COORD o, COORD p, double A, double B, double lambda) { + COORD ret; + double sinA,cosA, sinB, cosB, sinL, cosL; + double S11, S12, S13, S21, S22, S23, S31, S32, S33; + sinA = sin(A); + cosA = cos(A); + sinB = sin(B); + cosB = cos(B); + sinL = sin(lambda); + cosL = cos(lambda); + + S11 = -sinA*sinL - cosA*sinB*cosL; + S12 = cosB*cosL; + S13 = -cosA*sinL + sinA*sinB*cosL; + + S21 = sinA*cosL - cosA*sinB*sinL; + S22 = cosB*sinL; + S23 = cosA*cosL + sinA*sinB*sinL; + + S31 = cosA*cosB; + S32 = sinB; + S33 = -sinA*cosB; + + ret.x = p.x*(S11 + S21 + S31) + o.x; + ret.y = p.y*(S12 + S22 + S32) + o.y; + ret.z = p.z*(S13 + S23 + S33) + o.z; + + return ret; +} + +/** @brief Convert coordinate from launch coordinate system to Inertia coordinate system. */ +COORD Coord_Launch2Inertia(COORD o, COORD p, double A, double B, double we, double t) { + COORD ret; + double OmgX, OmgY, OmgZ, sinwet, coswet; + double M11, M12, M13, M21, M22, M23, M31, M32, M33; + OmgX = cos(A)*cos(B); + OmgY = sin(B); + OmgZ = -sin(A)*cos(B); + sinwet = sin(we*t); + coswet = cos(we*t); + + M11 = 1 - (1 - OmgX*OmgX)*(1-coswet); + M12 = OmgX*OmgY*(1-coswet) + OmgZ*sinwet; + M13 = OmgX*OmgZ*(1-coswet)-OmgY*sinwet; + + M21 = OmgY*OmgX*(1-coswet) - OmgZ*sinwet; + M22 = 1-(1-OmgY*OmgY)*(1-coswet); + M23 = OmgY*OmgZ*(1-coswet) + OmgX*sinwet; + + M31 = OmgZ*OmgX*(1-coswet) + OmgY*sinwet; + M32 = OmgZ*OmgY*(1-coswet) - OmgX*sinwet; + M33 = 1 - (1-OmgZ*OmgZ)*(1-coswet); + + ret.x = p.x*(M11 + M21 + M31) + o.x; + ret.y = p.y*(M12 + M22 + M32) + o.y; + ret.z = p.z*(M13 + M23 + M33) + o.z; + + return ret; +} diff --git a/df_datalink/src/networking/link_layer/geometry/coord.h b/df_datalink/src/networking/link_layer/geometry/coord.h new file mode 100644 index 0000000..9bdf7e0 --- /dev/null +++ b/df_datalink/src/networking/link_layer/geometry/coord.h @@ -0,0 +1,81 @@ +// +// Copyright (C) 2020 OpenSim Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// + + +#ifndef _COORD_H +#define _COORD_H + +/** + * @brief Structure for storing 3D coordinates. + * + * Some comparison and basic arithmetic operators are implemented. + * + * @ingroup utils + */ + +typedef struct{ + double x; + double y; + double z; +} COORD; + +extern const COORD COORD_NIL; +extern const COORD COORD_ZERO; +extern const COORD COORD_ONE; +extern const COORD COORD_X_AXIS; +extern const COORD COORD_Y_AXIS; +extern const COORD COORD_Z_AXIS; + +/** @brief Subtracts two coordinate vectors. */ +COORD Coord_Sub(COORD a, COORD b); + +/** @brief Adds two coordinate vectors. */ +COORD Coord_Add(COORD a, COORD b); + +/** @brief Multiplies a coordinate vector by a real number. */ +void Coord_ScalarMult(COORD *a, double t); + +/** @brief Multiplies a coordinate vector by a real number. */ +COORD Coord_GetScalarMult(COORD a, double t); + +/** @brief Divides a coordinate vector by a real number. */ +void Coord_ScalarDiv(COORD *a, double t); + +/** @brief Divides a coordinate vector by a real number. */ +COORD Coord_GetScalarDiv(COORD a, double t); + +/** @brief Dot product. */ +double Coord_Dot(COORD a, COORD b); + +/** @brief Cross product. */ +COORD Coord_Cross(COORD a, COORD b); + +/** @brief Multiplies two coordinate vector in elementwise. */ +COORD Coord_ElementwiseMult(COORD a, COORD b); + +/** @brief Divides two coordinate vector in elementwise. */ +COORD Coord_ElementwiseDiv(COORD a, COORD b); + +/** @brief Calculate a coordinate vector length^2 (omits calling square root). */ +double Coord_SquareLength(COORD a); + +/** @brief Calculate a coordinate vector length. */ +double Coord_Length(COORD a); + +/** @brief Calculate two coordinates' distance. */ +double Coord_Distance(COORD a, COORD b); + +/** @brief Normalize coordinate vector. */ +void Coord_Normalize(COORD *a); + +/** @brief Normalize coordinate vector. */ +COORD Coord_GetNormalized(COORD a); + +/** @brief Returns the angle between the two vectors. */ +double Coord_Angle(COORD a, COORD b); + +#endif + diff --git a/df_datalink/src/networking/link_layer/geometry/eulerangles.c b/df_datalink/src/networking/link_layer/geometry/eulerangles.c new file mode 100644 index 0000000..76755df --- /dev/null +++ b/df_datalink/src/networking/link_layer/geometry/eulerangles.c @@ -0,0 +1,57 @@ +// +// Copyright (C) 2020 OpenSim Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// + +#include +#include "eulerangles.h" + + +const EULERANGLES EULERANGLES_NIL = {NAN, NAN, NAN}; +const EULERANGLES EULERANGLES_ZERO = {0.0, 0.0, 0.0}; + + +/** @brief Add two EulerAngles. */ +EULERANGLES EulerAngles_Add(EULERANGLES e1, EULERANGLES e2) { + EULERANGLES ret; + ret.alpha = e1.alpha + e2.alpha; + ret.beta = e1.beta + e2.beta ; + ret.gamma = e1.gamma + e2.gamma; + return ret; +} + +/** @brief Subtracts two EulerAngles. */ +EULERANGLES EulerAngles_Sub(EULERANGLES e1, EULERANGLES e2) { + EULERANGLES ret; + ret.alpha = e1.alpha - e2.alpha; + ret.beta = e1.beta - e2.beta ; + ret.gamma = e1.gamma - e2.gamma; + return ret; +} + +/** @brief Multiplies EulerAngles by a real number. */ +void EulerAngles_ScalarMult(EULERANGLES *e, double f) { + e->alpha *= f; + e->beta *= f; + e->gamma *= f; +} + +/** @brief Multiplies EulerAngles by a real number. */ +EULERANGLES EulerAngles_GetScalarMult(EULERANGLES e, double f) { + EulerAngles_ScalarMult(&e, f); + return e; +} + +/** @brief Normalize EulerAngles. */ +void EulerAngles_Normalize(EULERANGLES *e) { + e->alpha = fmod(e->alpha, 2*EUL_PI); + e->beta = fmod(e->beta , 2*EUL_PI); + e->gamma = fmod(e->gamma, 2*EUL_PI); +} + +/** @brief Normalize EulerAngles. */ +EULERANGLES EulerAngles_GetNormalize(EULERANGLES e) { + EulerAngles_Normalize(&e); + return e; +} diff --git a/df_datalink/src/networking/link_layer/geometry/eulerangles.h b/df_datalink/src/networking/link_layer/geometry/eulerangles.h new file mode 100644 index 0000000..6a82c8f --- /dev/null +++ b/df_datalink/src/networking/link_layer/geometry/eulerangles.h @@ -0,0 +1,54 @@ +#ifndef __EULERANGLES_H +#define __EULERANGLES_H + +#define EUL_PI 3.14159265358979323846 + +#define DEG2RAD(d) ((EUL_PI/180.0)*d) +#define RAD2DEG(r) ((180.0/EUL_PI)*r) + +/** + * Orientations are represented by 3D double precision Tait-Bryan (Euler) tuples + * called EulerAngles. The angles are in Z, Y', X" order that is often called + * intrinsic rotations, they are measured in radians. The default (unrotated) + * orientation is along the X axis. Conceptually, the Z axis rotation is heading, + * the Y' axis rotation is descending (negative elevation), the X" axis rotation is bank. + * For example, positive rotation along the Z axis rotates X into Y (turns left), positive + * rotation along the Y axis rotates Z into X (leans forward), positive rotation + * along the X axis rotates Y into Z (leans right). + */ +typedef struct { + double alpha; // unit rad + double beta; // unit rad + double gamma; // unit rad +} EULERANGLES; + +typedef enum { + EULERANGLES_NONE = 0, + EULERANGLES_ZYX = 1, + EULERANGLES_ZYZ = 2, + EULERANGLES_XYZ = 3, +}EULERANGLES_TYPE; + +extern const EULERANGLES EULERANGLES_ZERO; +extern const EULERANGLES EULERANGLES_NIL; + +/** @brief Add two EulerAngles. */ +EULERANGLES EulerAngles_Add(EULERANGLES e1, EULERANGLES e2); + +/** @brief Subtracts two EulerAngles. */ +EULERANGLES EulerAngles_Sub(EULERANGLES e1, EULERANGLES e2); + +/** @brief Multiplies EulerAngles by a real number. */ +void EulerAngles_ScalarMult(EULERANGLES *e, double f); + +/** @brief Multiplies EulerAngles by a real number. */ +EULERANGLES EulerAngles_GetScalarMult(EULERANGLES e, double f); + +/** @brief Normalize EulerAngles. */ +void EulerAngles_Normalize(EULERANGLES *e); + +/** @brief Normalize EulerAngles. */ +EULERANGLES EulerAngles_GetNormalize(EULERANGLES e); + +#endif + diff --git a/df_datalink/src/networking/link_layer/geometry/quaternion.c b/df_datalink/src/networking/link_layer/geometry/quaternion.c new file mode 100644 index 0000000..b9847d5 --- /dev/null +++ b/df_datalink/src/networking/link_layer/geometry/quaternion.c @@ -0,0 +1,413 @@ +// +// Copyright (C) 2014 OpenSim Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// + +#include +#include +#include +#include "coord.h" +#include "eulerangles.h" +#include "quaternion.h" + +typedef union { + float value; + uint32_t raw; +} SOFT_FLOAT; + +typedef union { + double value; + uint64_t raw; +} SOFT_DOUBLE; + +const SOFT_FLOAT EPS_FLOAT = {.raw = 0b110100000000000000000000000000}; +const SOFT_DOUBLE EPS_DOUBLE = {.raw = 0b11110010110000000000000000000000000000000000000000000000000000}; + +const QUATERNION QUATERNION_IDENTITY = {1.0, 0.0, 0.0 ,0.0}; +const QUATERNION QUATERNION_NIL = {NAN, NAN, NAN, NAN}; +/** @brief Subtracts two quaternions. */ +QUATERNION Quaternion_Sub(QUATERNION q1, QUATERNION q2) { + QUATERNION ret; + ret.s = q1.s - q2.s; + ret.i = q1.i - q2.i; + ret.j = q1.j - q2.j; + ret.k = q1.k - q2.k; + return ret; +} + +/** @brief Adds two quaternions. */ +QUATERNION Quaternion_Add(QUATERNION q1, QUATERNION q2) { + QUATERNION ret; + ret.s = q1.s + q2.s; + ret.i = q1.i + q2.i; + ret.j = q1.j + q2.j; + ret.k = q1.k + q2.k; + return ret; +} + +/** @brief Multiplies a quaternion by a real number. */ +void Quaternion_ScalarMult(QUATERNION *q, double t) { + q->s *= t; + q->i *= t; + q->j *= t; + q->k *= t; +} + +/** @brief Multiplies a quaternion by a real number. */ +QUATERNION Quaternion_GetScalarMult(QUATERNION a, double t) { + Quaternion_ScalarMult(&a, t); + return a; +} + +/** @brief Divides a quaternion by a real number. */ +void Quaternion_ScalarDiv(QUATERNION *q, double t) { + q->s /= t; + q->i /= t; + q->j /= t; + q->k /= t; +} + +/** @brief Divides a quaternion by a real number. */ +QUATERNION Quaternion_GetScalarDiv(QUATERNION q, double t) { + Quaternion_ScalarDiv(&q, t); + return q; +} + +/** @brief Multiplies two quaternions. */ +QUATERNION Quaternion_Mult(QUATERNION q1, QUATERNION q2) { + QUATERNION ret; + ret.s = q1.s * q2.s - (q1.i*q2.i + q1.j*q2.j + q1.k*q2.k); + ret.i = q1.j * q2.k - q1.k * q2.j + q1.s * q2.i + q1.i * q2.s; + ret.j = q1.k * q2.i - q1.i * q2.k + q1.s * q2.j + q1.j * q2.s; + ret.k = q1.i * q2.j - q1.j * q2.i + q1.s * q2.k + q1.k * q2.s; + return ret; +} + +/** @brief Divides two quaternions. */ +QUATERNION Quaternion_Div(QUATERNION q1, QUATERNION q2) { + Quaternion_Inverse(&q2); + return Quaternion_Mult(q1, q2); +} + +/** @brief Dot product. */ +inline double Quaternion_Dot(QUATERNION q1, QUATERNION q2) { + return (q1.s*q2.s + q1.i*q2.i + q1.j*q2.j + q1.k*q2.k); +} + +/** @brief Calculate a quaternion length^2 (omits calling square root). */ +inline double Quaternion_SquareLength(QUATERNION q) { + return (q.s*q.s + q.i*q.i + q.j*q.j + q.k*q.k); +} + +/** @brief Calculate a quaternion length. */ +inline double Quaternion_Length(QUATERNION q) { + return sqrt(Quaternion_SquareLength(q)); +} + +/** @brief Normalize quaternion. */ +void Quaternion_Normalize(QUATERNION *q) { + Quaternion_ScalarDiv(q, Quaternion_Length(*q)); +} + +/** @brief Normalize quaternion. */ +QUATERNION Quaternion_GetNormalized(QUATERNION q) { + Quaternion_Normalize(&q); + return q; +} + +/** @brief Conjugated quaternion. */ +void Quaternion_Conjugated(QUATERNION *q) { + q->i = -q->i; + q->j = -q->j; + q->k = -q->k; +} + +/** @brief Conjugated quaternion. */ +QUATERNION Quaternion_GetConjugated(QUATERNION q) { + Quaternion_Conjugated(&q); + return q; +} + +/** @brief Inverse quaternion. */ +void Quaternion_Inverse(QUATERNION *q) { + Quaternion_Conjugated(q); + Quaternion_ScalarDiv(q, Quaternion_SquareLength(*q)); +} + +/** @brief Inverse quaternion. */ +QUATERNION Quaternion_GeInverse(QUATERNION q) { + Quaternion_Inverse(&q); + return q; +} + +inline double Quaternion_GetRotationAngle(QUATERNION q) { + return (acos(q.s) * 2); +} + + +/** @brief Get axis of quaternion. */ +COORD Quaternion_GetRotationAxis(QUATERNION q) { + double sin_theta_inv; + COORD ret; + sin_theta_inv = 1.0 / sin(acos(q.s)); + ret.x = q.i * sin_theta_inv; + ret.y = q.j * sin_theta_inv; + ret.z = q.k * sin_theta_inv; + return ret; +} + +/** @brief Get the axis and rotate angle of a unit Quaternion */ +void Quaternion_GetRotationAxisAndAngle(QUATERNION q, COORD *axis, double *angle) { + double sin_theta_inv; + *angle = acos(q.s); + + // pre-compute to save time + sin_theta_inv = 1.0 / sin(*angle); + + // now the vector + axis->x = q.i * sin_theta_inv; + axis->y = q.j * sin_theta_inv; + axis->z = q.k * sin_theta_inv; + *angle = (*angle) * 2; +} + +/** @brief Decompose the rotation on to 2 parts. */ +void Quaternion_GetSwingAndTwist(QUATERNION q, COORD axis, QUATERNION *swing, QUATERNION *twist) { + double p; + COORD v; + v.x = q.i; + v.y = q.j; + v.z = q.k; + // return projection v1 on to v2 (parallel component) + p = Coord_Dot(v, axis); + v = Coord_GetScalarMult(axis, p); + twist->s = q.s; + twist->i = v.x; + twist->j = v.y; + twist->k = v.z; + Quaternion_Normalize(twist); + *swing = Quaternion_Mult(q, Quaternion_GetConjugated(*twist)); +} + +/** @brief rotates v by this quaternion (quaternion must be unit) */ +COORD Quaternion_Rotate(QUATERNION q, COORD v) { + QUATERNION temp; + COORD ret; + temp.s = 0; + temp.i = v.x; + temp.j = v.y; + temp.k = v.z; + temp = Quaternion_Mult(q,temp); + Quaternion_Conjugated(&q); + temp = Quaternion_Mult(temp,q); + ret.x = temp.i; + ret.y = temp.j; + ret.z = temp.k; + return ret; +} + +/** @brief returns the euler angles from a rotation Quaternion */ +EULERANGLES Quaternion_ToEulerAngles(QUATERNION q, EULERANGLES_TYPE type) { + EULERANGLES ret; + switch (type) { + case EULERANGLES_ZYX : { + /* Covert form matlab 2023a */ + // Cap all inputs to asin to 1, since values >1 produce complex + // results + // Since the quaternion is of unit length, this should never happen, + // but some code generation configuration seem to hit this edge case + // under some circumstances. + + double asinValue; + bool mask1, mask2; + + asinValue = -2.0 *(q.i*q.k - q.s*q.j); + mask1 = asinValue >= 1.0 - 10*EPS_DOUBLE.value; + mask2 = asinValue <= -1.0 + 10*EPS_DOUBLE.value; + if (mask1) + asinValue = 1; + if (mask2) + asinValue = -1; + + if(mask1 || mask2) { + ret.alpha = (asinValue > 0) ? (-2.0 * atan2(q.i, q.s)) : (2.0 * atan2(q.i, q.s)); + ret.gamma = 0; + } + else { + ret.alpha = atan2(2.0*(q.i*q.j + q.s*q.k), q.s*q.s + q.i*q.i - q.j*q.j - q.k*q.k); + ret.gamma = atan2(2.0*(q.j*q.k + q.s*q.i), q.s*q.s - q.i*q.i - q.j*q.j + q.k*q.k); + } + ret.beta = asin( asinValue ); + break; + } + + case EULERANGLES_ZYZ : { + // TODO; + ret = EULERANGLES_NIL; + break; + } + + case EULERANGLES_XYZ : { + /* Covert form matlab 2023a */ + // Prevent singularities as done in ZYX case + // Alternative to rotm2eul(quat2rotm(q), 'XYZ') with fewer + // operations + // sin(y) = R13 = 2 * (qx*qz + qy*qw) + // tan(x) = sin(x) / cos(x) = -R23 / R33 + // = -2 * (qy*qz - qx*qw) / (1 - 2*(qx^2 + qy^2)) + // = -2 * (qy*qz - qx*qw) / (qw^2 - qx^2 - qy^2 + qz^2) + // tan(z) = sin(z) / cos(z) = -R12 / R11 + // = -2 * (qx*qy - qz*qw) / (1 - 2*(qy^2 + qz^2)) + // = -2 * (qy*qz - qx*qw) / (qw^2 + qx^2 - qy^2 - qz^2) + + double asinValue; + bool mask1, mask2; + + asinValue = 2.0 *(q.i*q.k + q.s*q.j); + mask1 = asinValue >= 1.0 - 10*EPS_DOUBLE.value; + mask2 = asinValue <= -1.0 + 10*EPS_DOUBLE.value; + if (mask1) + asinValue = 1; + if (mask2) + asinValue = -1; + if(mask1 || mask2) { + ret.alpha = 0; + ret.gamma = (asinValue > 0) ? (2.0 * atan2(q.i, q.s)) : (-2.0 * atan2(q.i, q.s)); + } + else { + ret.alpha = atan2(-2.0*(q.j*q.k - q.s*q.i), q.s*q.s - q.i*q.i - q.j*q.j + q.k*q.k); + ret.gamma = atan2(-2.0*(q.i*q.j - q.s*q.k), q.s*q.s + q.i*q.i - q.j*q.j - q.k*q.k); + } + ret.beta = asin( asinValue ); + break; + } + + + default: + ret = EULERANGLES_NIL; + } + return ret; +} + +/** @brief returns the rotation Quaternion from a euler angles */ +QUATERNION Quaternion_FromeEulerAngles(EULERANGLES e, EULERANGLES_TYPE type) { + QUATERNION ret; + double cosx, sinx, cosy, siny, cosz, sinz; + cosx = cos(e.alpha * 0.5); + sinx = sin(e.alpha * 0.5); + cosy = cos(e.beta * 0.5); + siny = sin(e.beta * 0.5); + cosz = cos(e.gamma * 0.5); + sinz = sin(e.gamma * 0.5); + switch (type) { + case EULERANGLES_ZYX : + ret.s = cosx * cosy * cosz + sinx * siny * sinz; + ret.i = cosx * cosy * sinz - sinx * siny * cosz; + ret.j = cosx * siny * cosz + sinx * cosy * sinz; + ret.k = sinx * cosy * cosz - cosx * siny * sinz; + break; + case EULERANGLES_ZYZ : + ret.s = cosx * cosy * cosz - sinx * cosy * sinz; + ret.i = cosx * siny * sinz - sinx * siny * cosz; + ret.j = cosx * siny * cosz + sinx * siny * sinz; + ret.k = sinx * cosy * cosz + cosx * cosy * sinz; + break; + case EULERANGLES_XYZ : + ret.s = cosx * cosy * cosz - sinx * siny * sinz; + ret.i = sinx * cosy * cosz + cosx * siny * sinz; + ret.j = -sinx * cosy * sinz + cosx * siny * cosz; + ret.k = cosx * cosy * sinz + sinx * siny * cosz; + break; + default: + ret = QUATERNION_NIL; + break; + } + return ret; +} + +/** @brief adapted from https://svn.code.sf.net/p/irrlicht/code/trunk/include/quaternion.h */ +QUATERNION Quaternion_RotationFromTo(COORD from, COORD to) +{ + // Based on Stan Melax's article in Game Programming Gems + COORD axis; + QUATERNION ret; + double c, s; + Coord_Normalize(&from); + Coord_Normalize(&to); + + c = Coord_Dot(from, to); + + if (c >= 1.0) { // If dot == 1, vectors are the same + return QUATERNION_IDENTITY; // identity + } + else if (c <= -1.0) { // exactly opposite + axis = Coord_Cross(COORD_X_AXIS, from); + + if (Coord_Length(axis) == 0) + axis = Coord_Cross(COORD_Y_AXIS, from); + + // same as fromAxisAngle(axis, PI).normalize(); + ret.s = 0; + ret.i = axis.x; + ret.j = axis.y; + ret.k = axis.z; + Quaternion_Normalize(&ret); + return ret; + } + + s = sqrt((1 + c) * 2); + axis = Coord_Cross(from, to); + Coord_ScalarDiv(&axis, s); + ret.s = s * 0.5; + ret.i = axis.x; + ret.j = axis.y; + ret.k = axis.z; + Quaternion_Normalize(&ret); + return ret; +} + + +/** @brief linear quaternion interpolation */ +QUATERNION Quaternion_Lerp(QUATERNION q1, QUATERNION q2, double t) { + QUATERNION ret; + Quaternion_ScalarMult(&q1, 1 - t); + Quaternion_ScalarMult(&q1, t); + ret = Quaternion_Add(q1, q2); + Quaternion_Normalize(&ret); + return ret; +} + + +/** @brief spherical linear interpolation */ +QUATERNION Quaternion_Slerp(QUATERNION q1, QUATERNION q2, double t) { + double dot; + QUATERNION q3, ret; + dot = Quaternion_Dot(q1, q2); + /* dot = cos(theta) + if (dot < 0), q1 and q2 are more than 90 degrees apart, + so we can invert one to reduce spinning */ + if (dot < 0) { + dot = -dot; + q3.s = -q2.s; + q3.i = -q2.i; + q3.j = -q2.j; + q3.k = -q2.k; + } + else { + q3 = q2; + } + + if (dot < 0.95) { + double angle = acos(dot); + Quaternion_ScalarMult(&q1, sin(angle * (1 - t))); + Quaternion_ScalarMult(&q3, sin(angle * t)); + ret = Quaternion_Add(q1, q3); + Quaternion_ScalarDiv(&ret, sin(angle)); + return ret; + } + // if the angle is small, use linear interpolation + else { + return Quaternion_Lerp(q1, q3, t); + } +} diff --git a/df_datalink/src/networking/link_layer/geometry/quaternion.h b/df_datalink/src/networking/link_layer/geometry/quaternion.h new file mode 100644 index 0000000..c0806a2 --- /dev/null +++ b/df_datalink/src/networking/link_layer/geometry/quaternion.h @@ -0,0 +1,109 @@ + +#ifndef __QUATERNION_H +#define __QUATERNION_H + +#include "coord.h" +#include "eulerangles.h" + +// borrowed and adapted from https://github.com/MegaManSE/willperone/blob/master/Math/quaternion.h +typedef struct { + double s; + double i; + double j; + double k; +} QUATERNION; + +extern const QUATERNION QUATERNION_IDENTITY; +extern const QUATERNION QUATERNION_NIL; + +/** @brief Subtracts two quaternions. */ +QUATERNION Quaternion_Sub(QUATERNION q1, QUATERNION q2); + +/** @brief Adds two quaternions. */ +QUATERNION Quaternion_Add(QUATERNION q1, QUATERNION q2); + +/** @brief Multiplies a quaternion by a real number. */ +void Quaternion_ScalarMult(QUATERNION *q, double t); + +/** @brief Multiplies a quaternion by a real number. */ +QUATERNION Quaternion_GetScalarMult(QUATERNION a, double t); + +/** @brief Divides a quaternion by a real number. */ +void Quaternion_ScalarDiv(QUATERNION *q, double t); + +/** @brief Divides a quaternion by a real number. */ +QUATERNION Quaternion_GetScalarDiv(QUATERNION a, double t); + +/** @brief Multiplies two quaternions. */ +QUATERNION Quaternion_Mult(QUATERNION q1, QUATERNION q2); + +/** @brief Divides two quaternions. */ +QUATERNION Quaternion_Div(QUATERNION q1, QUATERNION q2); + +/** @brief Dot product. */ +double Quaternion_Dot(QUATERNION q1, QUATERNION q2); + +/** @brief Calculate a quaternion length^2 (omits calling square root). */ +double Quaternion_SquareLength(QUATERNION q); + +/** @brief Calculate a quaternion length. */ +double Quaternion_Length(QUATERNION q); + +/** @brief Normalize quaternion. */ +void Quaternion_Normalize(QUATERNION *q); + +/** @brief Normalize quaternion. */ +QUATERNION Quaternion_GetNormalized(QUATERNION q); + +/** @brief Conjugated quaternion. */ +void Quaternion_Conjugated(QUATERNION *q); + +/** @brief Conjugated quaternion. */ +QUATERNION Quaternion_GetConjugated(QUATERNION q); + +/** @brief Inverse quaternion. */ +void Quaternion_Inverse(QUATERNION *q); + +/** @brief Inverse quaternion. */ +QUATERNION Quaternion_GeInverse(QUATERNION q); + +/** @brief Get rotate angle of quaternion. */ +double Quaternion_GetRotationAngle(QUATERNION q); + +/** @brief Get axis of quaternion. */ +COORD Quaternion_GetRotationAxis(QUATERNION q); + +/** @brief Get the axis and rotate angle of a unit Quaternion */ +void Quaternion_GetRotationAxisAndAngle(QUATERNION q, COORD *axis, double *angle); + +/** @brief Decompose the rotation on to 2 parts. + 1. Twist - rotation around the "direction" vector + 2. Swing - rotation around axis that is perpendicular to "direction" vector + The rotation can be composed back by rotation = swing * twist + + has singularity in case of swing_rotation close to 180 degrees rotation. + if the input quaternion is of non-unit length, the outputs are non-unit as well + otherwise, outputs are both unit +*/ +void Quaternion_GetSwingAndTwist(QUATERNION q, COORD axis, QUATERNION *swing, QUATERNION *twist); + +/** @brief rotates v by this quaternion (quaternion must be unit) */ +COORD Quaternion_Rotate(QUATERNION q, COORD v); + +/** @brief returns the euler angles from a rotation Quaternion */ +EULERANGLES Quaternion_ToEulerAngles(QUATERNION q, EULERANGLES_TYPE type); + +/** @brief returns the rotation Quaternion from a euler angles */ +QUATERNION Quaternion_FromeEulerAngles(EULERANGLES e, EULERANGLES_TYPE type); + +/** @brief adapted from https://svn.code.sf.net/p/irrlicht/code/trunk/include/quaternion.h */ +QUATERNION Quaternion_RotationFromTo(COORD from, COORD to); + +/** @brief linear quaternion interpolation */ +QUATERNION Quaternion_Lerp(QUATERNION q1, QUATERNION q2, double t); + +/** @brief spherical linear interpolation */ +QUATERNION Quaternion_Slerp(QUATERNION q1, QUATERNION q2, double t); + +#endif + diff --git a/df_datalink/src/networking/link_layer/link_layer.c b/df_datalink/src/networking/link_layer/link_layer.c new file mode 100644 index 0000000..ef77eaa --- /dev/null +++ b/df_datalink/src/networking/link_layer/link_layer.c @@ -0,0 +1,1121 @@ +/*****************************************************************************/ +/** + * Description: A brief description of this file + * + * Date: 2021-11-13 13:32 + * LastEditTime: 2021-11-23 10:57 + * Revisions: Rev 0.0 + * History: + * [2021-11-23]: Initial version. + * [2022-03-28]: Add bre test mode. + * + * Copyright(c) 2021 Beijing Institute of Technology. + * Lab of Communication and Networking + * + ******************************************************************************/ + +/***************************** Include Files *********************************/ +#include +#include + +#include "util.h" +#include "error.h" +#include "circ_queue.h" +#include "link_layer.h" +#include "link_layer_types.h" +#include "msg_def.h" +#include "node_list.h" +#include "../phy_layer/phy_reg.h" + +/************************** Constant Definitions *****************************/ +#define TX_QUEUE_MAX 8 +#define LINK_BROCK_THRESHOLD (3*200) //3 secods +/************************** Variable Definitions *****************************/ +/***************** Macros (Inline Functions) Definitions *********************/ +/**************************** Type Definitions *******************************/ +/************************** Function Prototypes ******************************/ +static void RcdShift(L2_RCD* rcd, int32_t netxVal); +static void UpdateMainSate(L2_INST *l2InstPtr, L2_NODE_STATE newSate); +static void SlotNoUpdate(L2_INST *l2InstPtr, uint32_t newSlotNo); +static void FrameNoUpdate(L2_INST *l2InstPtr, uint32_t newFrameNo); +static void DataAvailUpdate(L2_INST *l2InstPtr, bool status); +static void EventPoolHandler(L2_INST *l2InstPtr); + +static inline void UpdateMainSate(L2_INST *l2InstPtr, L2_NODE_STATE newSate) { + ASSERT(l2InstPtr != NULL); + DBG_INFO("MainStateUpdate: %d -> %d\n", l2InstPtr->mainState, newSate); + l2InstPtr->nextState = newSate; +} + +static inline void ForceUpdateMainSate(L2_INST *l2InstPtr, L2_NODE_STATE newSate) { + ASSERT(l2InstPtr != NULL); + DBG_INFO("MainState Force Update: %d -> %d\n", l2InstPtr->mainState, newSate); + l2InstPtr->mainState = newSate; + l2InstPtr->nextState = newSate; +} + +/** + * @brief Update frame number, based on new next slotNo + */ +// FIXME: frame number update should effect 'last' and 'curr' frame number record. +static inline void SlotNoUpdate(L2_INST *l2InstPtr, uint32_t newSlotNo) { + ASSERT(l2InstPtr != NULL); + DBG_INFO("Update slot number to %lu\n", newSlotNo); + l2InstPtr->slotNo.next = newSlotNo; +} + +/** + * @brief Update slot number, based on new next frameNo + */ +// TODO: slot number update should effect 'last' and 'curr' slot number record. +static inline void FrameNoUpdate(L2_INST *l2InstPtr, uint32_t newFrameNo) { + ASSERT(l2InstPtr != NULL); + DBG_INFO("Update frame number to %lu\n", newFrameNo); + l2InstPtr->frameNo.next = newFrameNo; +} + +/** + * @brief Update l2 frame buffer state + * infer that if there is a new valid l2 frame up. + */ +static inline void DataAvailUpdate(L2_INST *l2InstPtr, bool status) { + ASSERT(l2InstPtr != NULL); + l2InstPtr->dataAvail = status; +} + +L2_NODE_STATE L2_GetMainState(L2_INST *l2InstPtr){ + ASSERT(l2InstPtr != NULL); + return l2InstPtr->mainState; +} + +/** + * @brief Check if there is a valid l2 frame. + */ +inline bool L2_isDataAvail(L2_INST *l2InstPtr) { + ASSERT(l2InstPtr != NULL); + return l2InstPtr->dataAvail; +} + +/** + * @brief Check if node is connected to the network + */ +inline bool L2_isCxn2Net(L2_INST *l2InstPtr) { + ASSERT(l2InstPtr != NULL); + return l2InstPtr->cxn2Net; +} + +/** + * @brief Get last frame number. + */ +inline uint32_t L2_GetLastFrameNo(L2_INST *l2InstPtr) { + ASSERT(l2InstPtr != NULL); + return l2InstPtr->frameNo.last; +} + +/** + * @brief Get last slot number. + */ +inline uint32_t L2_GetLastSlotNo(L2_INST *l2InstPtr) { + ASSERT(l2InstPtr != NULL); + return l2InstPtr->slotNo.last; +} + +/** + * @brief Get current frame number. + */ +inline uint32_t L2_GetCurrentFrameNo(L2_INST *l2InstPtr) { + ASSERT(l2InstPtr != NULL); + return l2InstPtr->frameNo.curr; +} + +/** + * @brief Get current slot number. + */ +inline uint32_t L2_GetCurrentSlotNo(L2_INST *l2InstPtr) { + ASSERT(l2InstPtr != NULL); + return l2InstPtr->slotNo.curr; +} + +/** + * @brief Get next frame number. + */ +inline uint32_t L2_GetNextFrameNo(L2_INST *l2InstPtr) { + ASSERT(l2InstPtr != NULL); + return l2InstPtr->frameNo.next; +} +/** + * @brief Get next slot number. + */ +inline uint32_t L2_GetNextSlotNo(L2_INST *l2InstPtr) { + ASSERT(l2InstPtr != NULL); + return l2InstPtr->slotNo.next; +} + +/*****************************************************************************/ +/** + * @brief Creat a new schedule envent, register event in schedule event pool. + * + * @param event event type of the new schedule event. + * + * @return NULL error occurred + * Pointer to schedule event. + * + ******************************************************************************/ +L2_SCHD_EVENT* L2_CreatNewSchdEvent(L2_INST *l2InstPtr, L2_EVENT_TYPE event){ + ASSERT(l2InstPtr != NULL); + L2_SCHD_EVENT* schdEventPtr = NULL; + if(l2InstPtr->schdEventCnt >= L2_SCHD_EVENT_MAX){ + DBG_ERROR("Schedule event number exceeds the max, no more schedule event can be created.\n"); + return NULL; + } + schdEventPtr = (L2_SCHD_EVENT*)malloc(sizeof(L2_SCHD_EVENT)); + if(schdEventPtr == NULL){ + free(schdEventPtr); + return NULL; + } + if(event < L2_EV_SCAN_PROC_DONE || event > L2_ROUTINE_UPDATE){ + DBG_ERROR("Unknown event type: %d.\n", event); + return NULL; + } + schdEventPtr->eventId = l2InstPtr->schdEventCnt; + schdEventPtr->l2Event.msg = NULL; + schdEventPtr->isSchd = false; + schdEventPtr->schdSlot = L2_SLOTNO_NONE; + schdEventPtr->schdFrame = L2_FRAMENO_NONE; + l2InstPtr->schdEventPool[l2InstPtr->schdEventCnt] = schdEventPtr; + l2InstPtr->schdEventCnt++; + return schdEventPtr; +} + + +/*****************************************************************************/ +/** + * @brief Delete a schedule event, remove the event from event pool, + * release memory, release event ID. + * + * @param schdEvent pointer to the schedule event which is aboute to be deleted. + * + * @return SUCCESS + * error code + * + ******************************************************************************/ +int32_t L2_DeletSchdEvent(L2_INST *l2InstPtr, L2_SCHD_EVENT *schdEvent){ + ASSERT(l2InstPtr != NULL); + ASSERT(schdEvent != NULL); + free(schdEvent->l2Event.msg); + for(int32_t i = schdEvent->eventId; i < l2InstPtr->schdEventCnt; i++){ + if(i == l2InstPtr->schdEventCnt - 1){ + l2InstPtr->schdEventPool[i] = NULL; + } + else{ + l2InstPtr->schdEventPool[i] = l2InstPtr->schdEventPool[i+1]; + } + } + free(schdEvent); + l2InstPtr->schdEventCnt --; + return SUCCESS; +} + +/*****************************************************************************/ +/** + * @brief Append extra message content to specific schedule event. + * + * @param schdEvent pointer to the schedule event. + * msg pointer to the append content. + * + * @return SUCCESS. + * error code. + * + ******************************************************************************/ +inline int32_t L2_SchdEventAppendMsg(L2_SCHD_EVENT* schdEvent, void* msg){ + ASSERT(schdEvent != NULL); + schdEvent->l2Event.msg = msg; + return SUCCESS; +} + +/*****************************************************************************/ +/** + * @brief Check if the event was scheduled. + * + * @param schdEvent pointer to the schedule event. + * + * @return true. + * false. + * + ******************************************************************************/ +inline bool L2_isEventScheduled(L2_SCHD_EVENT* schdEvent){ + ASSERT(schdEvent != NULL); + return schdEvent->isSchd; +} + +/*****************************************************************************/ +/** + * @brief Schedule a event at a specific time(indexed by frame and slot number) + * + * @param schdEvent pointer to the schedule event. + * @param frameNo schedule frame number + * @param slotNo schedule slot number + * + * @return FAILURE, event has already been scheduled/schedule time not allowed. + * SUCCESS + * + ******************************************************************************/ +int32_t L2_ScheduleEventAt(L2_INST *l2InstPtr, L2_SCHD_EVENT* schdEvent, uint32_t frameNo, uint32_t slotNo){ + ASSERT(schdEvent != NULL); + if(L2_isEventScheduled(schdEvent) == true){ + DBG_ERROR("Event %d has already been scheduled.\n", schdEvent->eventId); + return FAILURE; + } + if(frameNo <= L2_GetCurrentFrameNo(l2InstPtr) && slotNo < L2_GetCurrentSlotNo(l2InstPtr)){ + DBG_ERROR("Cannot schedule event %d to the past(current: [%ld-%ld], schedule: [%lu-%lu]).\n", + schdEvent->eventId, L2_GetCurrentFrameNo(l2InstPtr), L2_GetCurrentSlotNo(l2InstPtr), frameNo, slotNo); + return FAILURE; + } + schdEvent->isSchd = true; + schdEvent->schdFrame = frameNo; + schdEvent->schdSlot = slotNo; + return SUCCESS; +} + +/*****************************************************************************/ +/** + * @brief Schedule a event after a specific time period. + * + * @param schdEvent pointer to the schedule event. + * @param numSlots how many slot later the event should be scheduled + * + * @return FAILURE, event has already been scheduled/schedule time not allowed. + * SUCCESS + * + ******************************************************************************/ +int32_t L2_ScheduleEventAfter(L2_INST *l2InstPtr, L2_SCHD_EVENT* schdEvent, uint32_t numSlots){ + ASSERT(schdEvent != NULL); + if(L2_isEventScheduled(schdEvent) == true){ + DBG_ERROR("Event %d has already been scheduled.\n", schdEvent->eventId); + return FAILURE; + } + uint32_t frameNo = L2_GetCurrentFrameNo(l2InstPtr) + (numSlots/L2_SLOTS_PER_FRAME); + uint32_t slotNo = L2_GetCurrentSlotNo(l2InstPtr) + (numSlots%L2_SLOTS_PER_FRAME); + return L2_ScheduleEventAt(l2InstPtr, schdEvent, frameNo, slotNo); +} + +/*****************************************************************************/ +/** + * @brief Reschedule a event at a specific time(indexed by frame and slot number) + * + * @param schdEvent pointer to the schedule event. + * @param frameNo schedule frame number + * @param slotNo schedule slot number + * + * @return FAILURE, event has already been scheduled/schedule time not allowed. + * SUCCESS + * + ******************************************************************************/ +int32_t L2_RecheduleEventAt(L2_INST *l2InstPtr, L2_SCHD_EVENT* schdEvent, uint32_t frameNo, uint32_t slotNo){ + ASSERT(schdEvent != NULL); + if(schdEvent->isSchd == false){ + DBG_WARNING("Event %d has not been scheduled yet.\n", schdEvent->eventId); + } + schdEvent->isSchd = false; + return L2_ScheduleEventAt(l2InstPtr, schdEvent, frameNo, slotNo); +} + +/*****************************************************************************/ +/** + * @brief Rechedule a event after a specific time period. + * + * @param schdEvent pointer to the schedule event. + * @param numSlots how many slot later the event should be scheduled + * + * @return FAILURE, event has already been scheduled/schedule time not allowed. + * SUCCESS + * + * @return NONE. + * + ******************************************************************************/ +int32_t L2_RecheduleEventAfter(L2_INST *l2InstPtr, L2_SCHD_EVENT* schdEvent, uint32_t numSlots){ + ASSERT(schdEvent != NULL); + if(schdEvent->isSchd == false){ + DBG_WARNING("Event %d has not been scheduled yet.\n", schdEvent->eventId); + } + return L2_ScheduleEventAfter(l2InstPtr, schdEvent, numSlots); +} + +/*****************************************************************************/ +/** + * @brief Cancel a scheduled event. + * + * @param schdEvent pointer to the schedule event. + * + * @return SUCCESS. + * + ******************************************************************************/ +int32_t L2_CancelEvent(L2_SCHD_EVENT* schdEvent){ + ASSERT(schdEvent != NULL); + if(schdEvent->isSchd == false){ + DBG_WARNING("Event %d has not been scheduled yet.\n", schdEvent->eventId); + } + schdEvent->isSchd = false; + return SUCCESS; +} + +/*****************************************************************************/ +/** + * @brief Check and excute schedule event in event pool illiterate. + * + * @param NONE. + * + * @return NONE. + * + ******************************************************************************/ +static void EventPoolHandler(L2_INST *l2InstPtr){ + ASSERT(l2InstPtr != NULL); + for(int32_t i = 0; i < l2InstPtr->schdEventCnt; i++){ + if(l2InstPtr->schdEventPool[i]->isSchd == true){ + if(l2InstPtr->schdEventPool[i]->schdFrame == l2InstPtr->frameNo.curr + && l2InstPtr->schdEventPool[i]->schdSlot == l2InstPtr->slotNo.curr){ + AssertL2Event(l2InstPtr, &(l2InstPtr->schdEventPool[i]->l2Event)); + } + } + } +} +/*****************************************************************************/ +/** + * @brief Shift L2 status record.(newval->next->curr->last) + * + * @param instPtr A pointer to physical layer control instance. + * + * @return NONE. + * + ******************************************************************************/ +static inline void RcdShift(L2_RCD* rcd, int32_t netxVal) { + ASSERT(rcd != NULL); + rcd->last = rcd->curr; + rcd->curr = rcd->next; + rcd->next = netxVal; +} + +/*****************************************************************************/ +/** + * @brief Get the valid frame data type received in last slot. + * + * @param NONE. + * + * @return NONE. + * + ******************************************************************************/ + +L2_FRAME_TYPE L2_GetLastRcvFrameType(L2_INST *l2InstPtr) { + if (l2InstPtr->dataAvail == false) { + return L2_NONE_FRAME; + } + else { + return l2InstPtr->frame.last; + } +} + +/*****************************************************************************/ +/** + * @brief Update L2 frame state, check if there is any valid L2 frame data in + * data buffer, update receive frame status. + * + * @param NONE. + * + * @return NONE. + * + ******************************************************************************/ +void L2_FrameStateUpdate(L2_INST *l2InstPtr) { + ASSERT(l2InstPtr != NULL); + PHY_INST* phyRef = l2InstPtr->config.phyInstRef; + bool isRecved, isValid; + + // Update Phisical layer state + Phy_UpdateState(l2InstPtr->config.phyInstRef); + + // Frame types shift (last <- curr <- next) + RcdShift(&(l2InstPtr->frame), L2_NONE_FRAME); + RcdShift(&(l2InstPtr->torState), L2_TOR_SUSPEND); + + if(Phy_IsFrameValid(l2InstPtr->config.phyInstRef)) { + if(Phy_RetrieveRecvData(phyRef, l2InstPtr->recvPktData) != SUCCESS) { + ASSERT(false); + } + } + + // Update frame state. + switch (l2InstPtr->frame.last) { + case L2_SCAN_FRAME : + isRecved = Phy_IsFrameDetected(l2InstPtr->config.phyInstRef); + isValid = isRecved; + break; + case L2_SVC_FRAME: + isRecved = Phy_IsFrameValid(l2InstPtr->config.phyInstRef); + if (isRecved == true) { +#ifndef DATALINK_ENABLE_BERTEST + isValid = L2_CrcCheck(l2InstPtr->recvPktData, SVC_PACK_LEN, L2_CRC16_1021); +#else + isValid = true; +#endif + } + else { + isValid = false; + } + break; + case L2_INFO_FRAME: + isRecved = Phy_IsFrameValid(l2InstPtr->config.phyInstRef); + if (isRecved == true) { + isValid = L2_CrcCheck(l2InstPtr->recvPktData, RSP_PACK_LEN, L2_CRC16_1021); + } + else { + isValid = false; + } + break; + default: + isRecved = false; + isValid = false; + break; + } + l2InstPtr->recvCnt = (isRecved == true) ? l2InstPtr->recvCnt+1 : l2InstPtr->recvCnt; + l2InstPtr->recvFineCnt = (isValid == true) ? l2InstPtr->recvFineCnt+1 : l2InstPtr->recvFineCnt; + DataAvailUpdate(l2InstPtr, isValid); + if (isRecved == true) { + DBG_INFO("Frame received type: %ld, validation: %d.\n", l2InstPtr->frame.last, isValid); + } + // Logging status. + // -- send slot status + if(l2InstPtr->torState.last == L2_TOR_RX) { + l2InstPtr->rxSlotLog.tuNo = l2InstPtr->frameNo.last; + l2InstPtr->rxSlotLog.slotNo = l2InstPtr->slotNo.last; + l2InstPtr->rxSlotLog.frameType = l2InstPtr->frame.last; + l2InstPtr->rxSlotLog.srcId = l2InstPtr->config.myId; + l2InstPtr->rxSlotLog.dstId = (l2InstPtr->config.myType == L2_HEAD_NODE) ? L2_MEMBER_NODE_ID : L2_HEAD_NODE_ID; + // TODO: baseInfo[18]; + memset(l2InstPtr->rxSlotLog.payload, 0x00, sizeof(l2InstPtr->rxSlotLog.payload)); + if(isValid == true) { + memcpy(l2InstPtr->rxSlotLog.payload, + l2InstPtr->recvPktData, + Phy_GetFrameLen(L2_L2frame2L1frame(l2InstPtr->frame.last))); + l2InstPtr->rxSlotLog.tmStamp = PhyRead(l2InstPtr->config.phyInstRef, FSTIME_L); + l2InstPtr->rxSlotLog.tmStamp |= ((uint64_t)PhyRead(l2InstPtr->config.phyInstRef, FSTIME_H))<<32; + + // Log time deviation. + int64_t devi; + devi = 0; + if (L2_TimeSync_GetDeviatoion(l2InstPtr, &devi) == SUCCESS) { + if (devi <= INT32_MAX && devi >= INT32_MIN) { + l2InstPtr->txSlotLog.tmDevi = (int32_t) devi; + } + l2InstPtr->txSlotLog.tmDevi = (int32_t) devi; + } + // Log frequency deviation + l2InstPtr->rxSlotLog.freqDevi = Phy_GetFreqEst(l2InstPtr->config.phyInstRef); + } + else { + l2InstPtr->rxSlotLog.tmStamp = 0; + l2InstPtr->rxSlotLog.tmDevi = 0; + l2InstPtr->rxSlotLog.freqDevi = 0; + } + SysMonitor_UpdateRecvSlotLog(&(l2InstPtr->rxSlotLog)); + } + // -- send slot status + if(l2InstPtr->torState.curr == L2_TOR_TX) { + l2InstPtr->txSlotLog.tuNo = l2InstPtr->frameNo.curr; + l2InstPtr->txSlotLog.slotNo = l2InstPtr->slotNo.curr; + l2InstPtr->txSlotLog.frameType = l2InstPtr->frame.curr; + l2InstPtr->txSlotLog.srcId = l2InstPtr->config.myId; + l2InstPtr->txSlotLog.dstId = (l2InstPtr->config.myType == L2_HEAD_NODE) ? L2_MEMBER_NODE_ID : L2_HEAD_NODE_ID; + // TODO: baseInfo[18]; + memset(l2InstPtr->rxSlotLog.payload, 0x00, sizeof(l2InstPtr->txSlotLog.payload)); + memcpy(l2InstPtr->txSlotLog.payload, + l2InstPtr->recvPktData, + Phy_GetFrameLen(L2_L2frame2L1frame(l2InstPtr->frame.curr))); + l2InstPtr->txSlotLog.tmStamp = 0; + l2InstPtr->txSlotLog.tmDevi = 0; + l2InstPtr->txSlotLog.freqDevi = 0; + SysMonitor_UpdateSendSlotLog(&(l2InstPtr->txSlotLog)); + } +} + +/*****************************************************************************/ +/** + * @brief Steer antenna beam to specified node. + * + * @param l2InstPtr a pointer to link layer descriptor instance + * @param nodeId destination node + * + * @return Corresponding frame length + * L2_FRAME_NONE_LEN if the frame type code cannot be recognized. + * + ******************************************************************************/ +// FIXME: To Complete. +int32_t L2_SteerBeam2Node(L2_INST *l2InstPtr, uint8_t nodeId){ + ASSERT(l2InstPtr != NULL); + ASSERT(l2InstPtr->config.phyInstRef != NULL); + int32_t Status; + + COORD myPos, dstPos, beamDir; + Status = GetNodePos(l2InstPtr->nodeInfoList, nodeId, &dstPos); + if(Status != SUCCESS) { + DBG_ERROR("Failed to retrieve position info of node %u, remain last configuration.\n", nodeId); + return EPARAM; + } + myPos.x = l2InstPtr->sysInfo.posX; + myPos.y = l2InstPtr->sysInfo.posY; + myPos.z = l2InstPtr->sysInfo.posZ; + + // TODO Check data format + EULERANGLES attitudeEuler, antAttitudeEuler; + attitudeEuler.alpha = DEG2RAD(l2InstPtr->sysInfo.pitch); + attitudeEuler.beta = DEG2RAD(l2InstPtr->sysInfo.yaw); + attitudeEuler.gamma = DEG2RAD(l2InstPtr->sysInfo.roll); + + // FIXME: confirm date source. + antAttitudeEuler.alpha = DEG2RAD(0); + antAttitudeEuler.beta = DEG2RAD(0); + antAttitudeEuler.gamma = DEG2RAD(0); + + // TODO Check data format + QUATERNION attitude, antAttitude; + attitude = Quaternion_FromeEulerAngles(attitudeEuler, EULERANGLES_XYZ); + antAttitude = Quaternion_FromeEulerAngles(antAttitudeEuler, EULERANGLES_XYZ); + + // --- --- Algorithm --- --- + // TODO Check result validation + // Compute beam direction vector + beamDir = Coord_Sub(dstPos, myPos); + + // Compute antenna attitude respect to ECEF + antAttitude = Quaternion_Mult(attitude, antAttitude); + + // Convert beam direction vector to antenna coordinate + beamDir = Quaternion_Rotate(Quaternion_GeInverse(antAttitude), beamDir); + // Normalize + Coord_Normalize(&beamDir); + + double oAxis, rAxis; + oAxis = RAD2DEG(atan2(beamDir.z,beamDir.y)); + rAxis = RAD2DEG(acos(Coord_Dot(beamDir, COORD_X_AXIS))); + Status = Phy_SetBeamAngle(l2InstPtr->config.phyInstRef, oAxis, rAxis); + return Status; +} + +/*****************************************************************************/ +/** + * @brief Layer 2 setup next slot operation, update current operating frame. + * + * @param l2InstPtr a pointer to link layer descriptor instance + * @param txrxMode tx/rx state for next slot + * @param frameType frame type of next slot. + * + * @return Corresponding frame length + * L2_FRAME_NONE_LEN if the frame type code cannot be recognized. + * + ******************************************************************************/ +int32_t L2_SetupNextSlot(L2_INST *l2InstPtr, L2_TOR_TYPE txrxMode, L2_FRAME_TYPE frameType) { + ASSERT(l2InstPtr != NULL); + ASSERT(l2InstPtr->config.phyInstRef != NULL); + int32_t Status = SUCCESS; + if (frameType < L2_SCAN_FRAME || frameType > L2_INFO_FRAME) { + return FAILURE; + } +#if _DEBUG_LEVEL == 3 + char* torStr = NULL; + char* frameStr = NULL; + switch(txrxMode){ + case L2_TOR_SUSPEND: + torStr = "SUSPEND"; + break; + case L2_TOR_TX: + torStr = "TX"; + break; + case L2_TOR_RX: + torStr = "RX"; + break; + } + switch(frameType){ + case L2_SCAN_FRAME: + frameStr = "Scan"; + break; + case L2_SVC_FRAME: + frameStr = "Service"; + break; + case L2_INFO_FRAME: + frameStr = "Response"; + break; + default: + frameStr = "UNKNOWN Frame"; + break; + } + DBG_INFO("# Setup Next Slot # [%lu-%lu], %s, %s.\n", + l2InstPtr->frameNo.next, + l2InstPtr->slotNo.next, + torStr, frameStr); +#endif + l2InstPtr->frame.next = frameType; + PHY_TOR_TYPE tor; + switch(txrxMode) { + case L2_TOR_SUSPEND: + tor = PHY_TOR_SUSPEND; + break; + case L2_TOR_TX: + tor = PHY_TOR_TX; + break; + case L2_TOR_RX: + tor = PHY_TOR_RX; + break; + default: + DBG_ERROR("Invalid txrx mode :%d.\n", txrxMode); + return EPARAM; + } + Status = Phy_SetupNextSlot(l2InstPtr->config.phyInstRef, tor, L2_L2frame2L1frame(frameType), l2InstPtr->sendPktData); + if(Status != SUCCESS){ + DBG_ERROR("Physical setup failed, with error code: %ld\n", Status); + } + return Status; +} + +/*****************************************************************************/ +/** + * @brief Get corresponding frame length in byte of L2 frame. + * + * @param l2FrameType + * + * @return Corresponding frame length + * L2_FRAME_NONE_LEN if the frame type code cannot be recognized. + * + ******************************************************************************/ +int32_t L2_GetFrameLen(L2_FRAME_TYPE l2FrameType) { + return Phy_GetFrameLen(L2_L2frame2L1frame(l2FrameType)); +} + +/*****************************************************************************/ +/** + * @brief Convert L2 frame type to L1 frame type + * + * @param l2Frame + * + * @return L1 frame type. + * + ******************************************************************************/ +L1_FRAME_TYPE L2_L2frame2L1frame(L2_FRAME_TYPE l2Frame) { + switch (l2Frame) { + case L2_SCAN_FRAME: + return L1_2KBPS_20MS_FRAME; + case L2_SVC_FRAME: + return L1_2KBPS_100MS_FRAME; + case L2_INFO_FRAME: + return L1_2KBPS_100MS_FRAME; + default: + return L1_NONE_FRAME; + } +} +/*****************************************************************************/ +/** + * @brief Initialize link layer fsm instance, allocate memory to storage fsm + * data. Apply the default values to fsm. + * + * @param l2InstPtr + * @param config + * + * @return SUCCESS + * Other error code. + * + ******************************************************************************/ +int32_t Linklayer_Init(L2_INST **l2InstPtr, L2_CONFIG *config) { + ASSERT(l2InstPtr != NULL); + ASSERT(config != NULL); + int32_t Status; + (*l2InstPtr) = (L2_INST*) malloc(sizeof(L2_INST)); + if ((*l2InstPtr) == NULL) { + DBG_ERROR("Allocate memory for L2_InstPtr failed.\n"); + return ENOMEM; + } + memcpy(&((*l2InstPtr)->config), config, sizeof(L2_CONFIG)); + + + (*l2InstPtr)->cxn2Net = (config->myType == L2_HEAD_NODE) ? true : false; + (*l2InstPtr)->dataAvail = false; + (*l2InstPtr)->frame.last = L2_NONE_FRAME; + (*l2InstPtr)->frame.curr = L2_NONE_FRAME; + (*l2InstPtr)->frame.next = L2_NONE_FRAME; + (*l2InstPtr)->torState.last = L2_TOR_SUSPEND; + (*l2InstPtr)->torState.curr = L2_TOR_SUSPEND; + (*l2InstPtr)->torState.next = L2_TOR_SUSPEND; + (*l2InstPtr)->rtneConfig.rtneTable = normalTable; + (*l2InstPtr)->rtneConfig.rtnePrd = ARRAY_SIZE(normalTable)*L2_SLOTS_PER_FRAME; + (*l2InstPtr)->rtneConfig.rtneStep = 0; + (*l2InstPtr)->rtneConfig.last = NULL; + (*l2InstPtr)->rtneConfig.curr = NULL; + (*l2InstPtr)->rtneConfig.next = NULL; + (*l2InstPtr)->mainState = INIT_STATE; + (*l2InstPtr)->nextState = INIT_STATE; + (*l2InstPtr)->frameNo.last = 0; + (*l2InstPtr)->frameNo.curr = 0; + (*l2InstPtr)->frameNo.next = 0; + (*l2InstPtr)->slotNo.last = 0; + (*l2InstPtr)->slotNo.curr = 0; + (*l2InstPtr)->slotNo.next = 0; + (*l2InstPtr)->schdEventCnt = 0; + (*l2InstPtr)->nodeInfoList = NULL; + (*l2InstPtr)->txQueue = NULL; + + (*l2InstPtr)->recvCnt = 0; + (*l2InstPtr)->recvFineCnt = 0; + (*l2InstPtr)->sentCnt = 0; + + memset((*l2InstPtr)->schdEventPool, 0x00, sizeof(L2_SCHD_EVENT *)*L2_SCHD_EVENT_MAX); + + (*l2InstPtr)->sendPktData = malloc(PACK_LEN_MAX*sizeof(uint8_t)); + if((*l2InstPtr)->sendPktData == NULL) { + DBG_ERROR("Failed to allocate memory for sendPktData.\n"); + goto init_error; + } + + (*l2InstPtr)->recvPktData = malloc(PACK_LEN_MAX*sizeof(uint8_t)); + if((*l2InstPtr)->recvPktData == NULL) { + DBG_ERROR("Failed to allocate memory for recvPktData.\n"); + goto init_error; + } + + Status = NodeList_Init(&((*l2InstPtr)->nodeInfoList)); + if(Status != SUCCESS) { + goto init_error; + } + + Status = L2_Scan_Init(*l2InstPtr); + if(Status != SUCCESS) { + goto init_error; + } + + Status = L2_Service_Init(*l2InstPtr); + if(Status != SUCCESS) { + goto init_error; + } + + if (CircQueueCreate(&((*l2InstPtr)->txQueue), TX_QUEUE_MAX) == false) { + Status = ENOMEM; + goto init_error; + } + return SUCCESS; +init_error: + free((*l2InstPtr)->recvPktData); + free((*l2InstPtr)->sendPktData); + NodeList_Destroy((*l2InstPtr)->nodeInfoList); + free(*l2InstPtr); + return Status; +} + +/*****************************************************************************/ +/** + * @brief Handle l2 event called by other model. + * + * @param l2InstPtr + * @param l2Event + * + * @return SUCCESS - Event has been successfully handled. + * FAIL - Event cannot be recognized or error occurred while process. + * + ******************************************************************************/ +int32_t Linklayer_EventHandler(L2_INST *l2InstPtr, L2_EVENT* l2Event) { + switch (l2Event->event) { + case L2_EV_FRAME_NO_UPDATE: { + DBG_INFO("Event L2_EV_FRAME_NO_UPDATE asserted....\n"); + FrameNoUpdate(l2InstPtr, *((uint32_t*) l2Event->msg)); + break; + } + case L2_EV_SLOT_NO_UPDATE: { + DBG_INFO("Event L2_EV_SLOT_NO_UPDATE asserted....\n"); + SlotNoUpdate(l2InstPtr, *((uint32_t*) l2Event->msg)); + break; + } + case L2_EV_MAIN_STATE_UPDATE: { + DBG_INFO("Event L2_EV_MAIN_STATE_UPDATE asserted....\n"); + UpdateMainSate(l2InstPtr, *((L2_NODE_STATE*) l2Event->msg)); + break; + } + case L2_EV_SCAN_PROC_DONE: { + DBG_INFO("Event L2_EV_SCAN_PROC_DONE asserted....\n"); + break; + } + case L2_EV_NET_SETUP_DONE: { + DBG_INFO("Event L2_EV_NET_SETUP_DONE asserted....\n"); + if(l2InstPtr->config.myType != L2_HEAD_NODE){ + l2InstPtr->cxn2Net = true; + UpdateMainSate(l2InstPtr, NORMAL_STATE); + } + else { + ForceUpdateMainSate(l2InstPtr, NORMAL_STATE); + } + + break; + } + case L2_EV_TIME_SYNC: { + DBG_INFO("Event L2_EV_TIME_SYNC asserted....\n"); +#ifndef DATALINK_ENABLE_AUTOTIMESYNC + int64_t tmAdj; + tmAdj = *((int64_t *)l2Event->msg); + DBG_INFO("Time adjustment is: %lld.\n", tmAdj); + L2_TimeSync_LocalTimerAdd(l2InstPtr, tmAdj); +#else + DBG_INFO("Using auto slot alignment.\n"); + L2_TimeSync_SlotAlign(l2InstPtr); +#endif + break; + } + case L2_EV_LOST_CXN: { + DBG_INFO("Event L2_EV_LOST_CXN asserted....\n"); + if(l2InstPtr->config.myType == L2_HEAD_NODE){ + DBG_ERROR("Illegal event, only None_Head node can assert L2_EV_LOST_CXN.\n"); + break; + } + DBG_WARNING("Lost connection with head node [%d].\n", l2InstPtr->config.headId); + L2_Scan_Init(l2InstPtr); + L2_Service_Init(l2InstPtr); + SlotNoUpdate(l2InstPtr, 0); + FrameNoUpdate(l2InstPtr, 0); + l2InstPtr->cxn2Net = false; + UpdateMainSate(l2InstPtr, INIT_STATE); + break; + } + case L2_EV_LOST_NODE: { + DBG_INFO("Event L2_EV_LOST_NODE asserted....\n"); + L2_Scan_Init(l2InstPtr); + L2_Service_Init(l2InstPtr); + SlotNoUpdate(l2InstPtr, 0); + FrameNoUpdate(l2InstPtr, 0); + UpdateMainSate(l2InstPtr, INIT_STATE); + break; + } + case L2_ROUTINE_FINISH: { + DBG_INFO("Event L2_ROUTINE_FINISH asserted....\n"); + if(l2InstPtr->nextState == NORMAL_STATE){ + l2InstPtr->rtneConfig.rtneTable = normalTable; + l2InstPtr->rtneConfig.rtnePrd = ARRAY_SIZE(normalTable)*L2_SLOTS_PER_FRAME; + l2InstPtr->rtneConfig.rtneStep = 0; + } + else{ + DBG_WARNING("Unsupported routine state [%d], Continue withe previous routine table.\n", l2InstPtr->nextState); + l2InstPtr->rtneConfig.rtneStep = 0; + } + break; + } + case L2_ROUTINE_UPDATE: { + DBG_INFO("Event L2_ROUTINE_UPDATE asserted....\n"); + L2_RTNE_CONFIG* newRtneConfig = (L2_RTNE_CONFIG*) l2Event->msg; + l2InstPtr->rtneConfig.rtneTable = newRtneConfig->rtneTable; + l2InstPtr->rtneConfig.rtnePrd = newRtneConfig->rtnePrd; + l2InstPtr->rtneConfig.rtneStep = newRtneConfig->rtneStep; + break; + } + default: { + DBG_WARNING("UNKNOWN Event %d asserted.\n", l2Event->event); + break; + } + } + return SUCCESS; +} + +/*****************************************************************************/ +/** + * @brief Handle l2 packet correctly received. + * + * @param l2InstPtr + * + * @return Status code. + * + ******************************************************************************/ +int32_t Linklayer_PktHandler(L2_INST *l2InstPtr) { + int32_t Status; + L2_FRAME_TYPE frameType; + frameType = L2_GetLastRcvFrameType(l2InstPtr); + DBG_INFO("Link layer handling packet, type: %ld.\n", frameType); + if (l2InstPtr->dataAvail == false) { + return FAILURE; + } + switch (frameType) { + case L2_SCAN_FRAME: + Status = L2_Scan_PktHandler(l2InstPtr, l2InstPtr->recvPktData); + break; + case L2_SVC_FRAME: + Status = L2_Service_PktHandler(l2InstPtr, l2InstPtr->recvPktData); + break; + case L2_INFO_FRAME: + if(l2InstPtr->mainState == INIT_STATE) { + Status = L2_Scan_PktHandler(l2InstPtr, l2InstPtr->recvPktData); + } + else {// NORMAL_STATE + Status = L2_Service_PktHandler(l2InstPtr, l2InstPtr->recvPktData); + } + break; + default: + DBG_WARNING("L2FrameHandler: UNKNOWN L2-FrameType %d", frameType); + Status = FAILURE; + break; + } + return Status; +} + +static int32_t IntcNodeTTL(NODE_ENTRY *node, const void *param) { + if (node == NULL) { + return FAILURE; + } + node->ttlCnt += *((uint32_t *)param); + return SUCCESS; +} + +static bool IsNodeConnected(NODE_ENTRY *node) { + if (node == NULL) { + return false; + } + DBG_INFO("Node: %u, TTL: %lu.\n", node->nodeInfo.nodeId, node->ttlCnt); + if (node->ttlCnt < LINK_BROCK_THRESHOLD){ + return true; + } + else{ + DBG_WARNING("Lost Connection to NODE %u.\n", node->nodeInfo.nodeId); + return false; + } +} +/*****************************************************************************/ +/** + * @brief Schedule next slot based on time allocate slice. + * + * @param l2InstPtr. + * + * @return SUCCESS + * Other error code. + * + ******************************************************************************/ +static int32_t Linklayer_Routine (L2_INST *l2InstPtr) { + ASSERT(l2InstPtr != NULL); + uint32_t usedSlots, tableIndx, entryIndx; + L2_RTNE_TABLE_ENTRY rtneEntry; + + // Determine which routine entry is going to be performed. + tableIndx = (l2InstPtr->rtneConfig.rtneStep)/L2_SLOTS_PER_FRAME; + entryIndx = (l2InstPtr->rtneConfig.rtneStep)%L2_SLOTS_PER_FRAME; + + // Shift routine entry record. + l2InstPtr->rtneConfig.last = l2InstPtr->rtneConfig.curr; + l2InstPtr->rtneConfig.curr = l2InstPtr->rtneConfig.next; + l2InstPtr->rtneConfig.next = &(l2InstPtr->rtneConfig.rtneTable[tableIndx][entryIndx]); + rtneEntry = l2InstPtr->rtneConfig.rtneTable[tableIndx][entryIndx]; + + switch (rtneEntry.slotType) { + case L2_SLOT_IDLE: + // Skip a 5ms slot. + usedSlots = NUM_SLOTS_5MS; + Phy_SetupNextSlot(l2InstPtr->config.phyInstRef, L2_TOR_SUSPEND, L1_NONE_FRAME, NULL); + break; + case L2_SLOT_SCAN: + usedSlots = L2_Scan_Routine(l2InstPtr, &rtneEntry); + break; + case L2_SLOT_SERVICE ... L2_SLOT_ADVERTISE: + usedSlots = L2_Service_Routine(l2InstPtr, &rtneEntry); + break; + default: + DBG_ERROR("UNKNOWN slot type [%d].\n", rtneEntry.slotType); + return NUM_SLOTS_NONE; + } + DBG_INFO("## Used slots: %lu, step: %lu, period: %lu.\n", usedSlots, l2InstPtr->rtneConfig.rtneStep, l2InstPtr->rtneConfig.rtnePrd); + + l2InstPtr->rtneConfig.rtneStep += usedSlots; + // check if routine is finished. + if(l2InstPtr->rtneConfig.rtneStep >= l2InstPtr->rtneConfig.rtnePrd){ + L2_EVENT rtneFinishEvent = {L2_ROUTINE_FINISH, &(l2InstPtr->rtneConfig)}; + AssertL2Event(l2InstPtr, &rtneFinishEvent); + } + + // Update TTL + IterEditNode(l2InstPtr->nodeInfoList, &usedSlots, IntcNodeTTL); + +#ifdef DATALINK_ENABLE_AUTORECONNECT + IterDeleteNode(l2InstPtr->nodeInfoList, IsNodeConnected); + if (GetNodeNum(l2InstPtr->nodeInfoList) < l2InstPtr->config.netScale - 1) { + // reset scan process + L2_EVENT l2Event; + // Assert Net-Setup Done. + l2Event.event = (l2InstPtr->config.myType == L2_HEAD_NODE) ? L2_EV_LOST_NODE : L2_EV_LOST_CXN; + l2Event.msg = NULL; + AssertL2Event(l2InstPtr, &l2Event); + usedSlots = 0; // Stop scheduling + } +#endif + + return usedSlots; +} + +/*****************************************************************************/ +/** + * @brief Execute a link layer fsm process. + * + * @param l2InstPtr. + * + * @return SUCCESS + * Other error code. + * + ******************************************************************************/ +int32_t Linklayer_Proc(L2_INST *l2InstPtr) { + ASSERT(l2InstPtr != NULL); + ASSERT(l2InstPtr->config.myType != L2_NONE_TYPE); + uint32_t usedSlots = 0; + DBG_PRINT("######## LinkLlayer Procedure ########\n"); + // Sync System info + SysMonitor_GetSysinfo(&(l2InstPtr->sysInfo)); + + // Update frame status. + L2_FrameStateUpdate(l2InstPtr); + + // Handle frame received in last slot. + if(L2_isDataAvail(l2InstPtr) == true){ + if(Linklayer_PktHandler(l2InstPtr) != SUCCESS) { + DBG_ERROR("Failed to handle last received frame: %ld.\n", l2InstPtr->frame.last); + } + } + + // Run Link layer routine, setup next slot procedure. + if (l2InstPtr->mainState == INIT_STATE) { + usedSlots = L2_Scan_Proc(l2InstPtr); + + } + else { + usedSlots = Linklayer_Routine(l2InstPtr); + } + + // Check if previous runs has error occurred. + if (usedSlots == NUM_SLOTS_NONE) { + return FAILURE; + } + + // Check and execute scheduled event. + EventPoolHandler(l2InstPtr); + + // Update Protocol log + l2InstPtr->prtcLog.tmSys = l2InstPtr->frameNo.last*L2_SLOTS_PER_FRAME + l2InstPtr->slotNo.last; + l2InstPtr->prtcLog.phySt = 0;// TODO: Update physical state. + l2InstPtr->prtcLog.tmLocal = PhyRead(l2InstPtr->config.phyInstRef, TM_LOCAL_L) >> 16; // 2^16 clk per LSB + l2InstPtr->prtcLog.tmLocal |= PhyRead(l2InstPtr->config.phyInstRef, TM_LOCAL_H); + l2InstPtr->prtcLog.beamNo = l2InstPtr->config.phyInstRef->beamNo.last; + l2InstPtr->prtcLog.beamNo = l2InstPtr->config.phyInstRef->beamWd.last; + l2InstPtr->prtcLog.stage = l2InstPtr->mainState; + l2InstPtr->prtcLog.recvCnt = l2InstPtr->recvCnt; + l2InstPtr->prtcLog.recvFineCnt = l2InstPtr->recvFineCnt; + l2InstPtr->prtcLog.nodeCnt = l2InstPtr->mainState; + l2InstPtr->prtcLog.myId = l2InstPtr->config.myId; + l2InstPtr->prtcLog.myId = (l2InstPtr->config.myType == L2_HEAD_NODE) ? L2_MEMBER_NODE_ID : L2_HEAD_NODE_ID; + SysMonitor_UpdateProtocolLog(&(l2InstPtr->prtcLog)); + + // Update slot number. + RcdShift(&(l2InstPtr->frameNo), l2InstPtr->frameNo.next); + RcdShift(&(l2InstPtr->slotNo), l2InstPtr->slotNo.next); + + // Update slot number. + l2InstPtr->slotNo.next += usedSlots; + if (l2InstPtr->slotNo.next >= L2_SLOTS_PER_FRAME) { // a time frame ended + l2InstPtr->frameNo.next = (l2InstPtr->frameNo.next + 1) % L2_FRAME_NO_MAX; + } + l2InstPtr->slotNo.next %= L2_SLOTS_PER_FRAME; + // update link layer state. + l2InstPtr->mainState = l2InstPtr->nextState; + return SUCCESS; +} diff --git a/df_datalink/src/networking/link_layer/link_layer.h b/df_datalink/src/networking/link_layer/link_layer.h new file mode 100644 index 0000000..ae6f425 --- /dev/null +++ b/df_datalink/src/networking/link_layer/link_layer.h @@ -0,0 +1,142 @@ +/*****************************************************************************/ +/** + * Description: Header file for df linklayer functions + * + * Date: 2021-11-13 13:33 + * LastEditTime: 2022-07-16 10:12 + * Revisions: Rev 0.1 + * History: + * [2022-07-16]: New branch for DiJian. + * [2021-11-23]: Initial version. + * + * Copyright(c) 2021 Beijing Institute of Technology. + * Lab of Communication and Networking + * + ******************************************************************************/ + +#ifndef __LINK_LAYER_H_ +#define __LINK_LAYER_H_ + +/***************************** Include Files *********************************/ +#include +#include "circ_queue.h" +#include "link_layer_types.h" +#include "../phy_layer/phy_layer.h" +#include "../../system_monitor.h" +#include "../config/app_config.h" +#include "node_list.h" +/************************** Constant Definitions *****************************/ +#define L2_HEAD_NODE_ID 1 +#define L2_MEMBER_NODE_ID 2 +/***************** Macros (Inline Functions) Definitions *********************/ +//#define AssertL2Event(inst, envent) Linklayer_EventHandler(inst, envent) +/**************************** Type Definitions *******************************/ + +typedef struct{ + L2_RTNE_TABLE_ENTRY** rtneTable; + uint32_t rtnePrd; + uint32_t rtneStep; + L2_RTNE_TABLE_ENTRY* last; + L2_RTNE_TABLE_ENTRY* curr; + L2_RTNE_TABLE_ENTRY* next; +}L2_RTNE_CONFIG; + +typedef struct { + L2_NODE_TYPE myType; +// bool isInterHead; +// uint8_t clustId; + uint8_t myId; + uint8_t headId; +// uint8_t bkpHeadId; + uint8_t netScale; + PHY_INST* phyInstRef; // pyhsical layer reference +} L2_CONFIG; + +typedef struct { + L2_CONFIG config; + bool dataAvail; // if there is a valid received frame data in rx buffer + bool cxn2Net; // if the node is connected to the network + L2_RCD frameNo; // stores the last current and next frame number. + L2_RCD slotNo; // stores the last current and next slot number. + L2_RCD frame; // stores the last current and next link layer frame type. + L2_RCD torState; // stores the last current and next link layer send/receive state. + L2_NODE_STATE mainState; // the main state of link layer state + L2_NODE_STATE nextState; // next state of link layer state, which will be applied to mainState every second. + L2_RTNE_CONFIG rtneConfig; // current routine table configuration and status. + L2_SCHD_EVENT* schdEventPool[L2_SCHD_EVENT_MAX]; + uint32_t schdEventCnt; + SCAN_FSM scanFsm; + SVC_FSM serviceFsm; + NODE_LIST *nodeInfoList; + uint8_t* sendPktData; + uint8_t* recvPktData; + // for system log + SYSINFO sysInfo; + SLOTLOG txSlotLog; + SLOTLOG rxSlotLog; + PRTCLLOG prtcLog; + CIRC_QUEUE *txQueue; + // for debug + uint32_t recvCnt; + uint32_t recvFineCnt; + uint32_t sentCnt; +} L2_INST; + +/************************** Variable Definitions *****************************/ +extern L2_RTNE_TABLE_ENTRY* normalTable[L2_RTNE_PERIOD]; +/************************** Function Prototypes ******************************/ +// Main +int32_t Linklayer_Init(L2_INST **l2InstPtr, L2_CONFIG *config); +int32_t Linklayer_Proc(L2_INST *l2InstPtr); +int32_t Linklayer_EventHandler(L2_INST *l2InstPtr, L2_EVENT* l2Event); +int32_t Linklayer_PktHandler(L2_INST *l2InstPtr); +int32_t L2_SteerBeam2Node(L2_INST *l2InstPtr, uint8_t nodeId); +int32_t L2_SetupNextSlot(L2_INST *l2InstPtr, L2_TOR_TYPE txrxMode, L2_FRAME_TYPE frameType); + +// Event +L2_SCHD_EVENT* L2_CreatNewSchdEvent(L2_INST *l2InstPtr, L2_EVENT_TYPE event); +bool L2_isEventScheduled(L2_SCHD_EVENT* schdEvent); +int32_t L2_CancelEvent(L2_SCHD_EVENT* schdEvent); +int32_t L2_SchdEventAppendMsg(L2_SCHD_EVENT* schdEvent, void* msg); +int32_t L2_ScheduleEventAt(L2_INST *l2InstPtr, L2_SCHD_EVENT* schdEvent, uint32_t frameNo, uint32_t slotNo); +int32_t L2_ScheduleEventAfter(L2_INST *l2InstPtr, L2_SCHD_EVENT* schdEvent, uint32_t numSlots); +int32_t L2_RecheduleEventAt(L2_INST *l2InstPtr, L2_SCHD_EVENT* schdEvent, uint32_t frameNo, uint32_t slotNo); +int32_t L2_RecheduleEventAfter(L2_INST *l2InstPtr, L2_SCHD_EVENT* schdEvent, uint32_t numSlots); + +// Framing +void L2_FrameStateUpdate(L2_INST *l2InstPtr); +L2_FRAME_TYPE L2_GetLastRcvFrameType(L2_INST *l2InstPtr); +L1_FRAME_TYPE L2_L2frame2L1frame(L2_FRAME_TYPE l2Frame); +int32_t L2_CrcAppend(uint8_t* dataBuff, uint32_t dataLen, uint32_t crcPos, L2_CRC_TYPE crcType); +bool L2_CrcCheck(uint8_t* dataBuff, uint32_t dataLen, L2_CRC_TYPE crcType); + +// Miscellaneous +L2_NODE_STATE L2_GetMainState(L2_INST *l2InstPtr); +bool L2_isDataAvail(L2_INST *l2InstPtr); +bool L2_isCxn2Net(L2_INST *l2InstPtr); +int32_t L2_GetFrameLen(L2_FRAME_TYPE l2FrameType); +uint32_t L2_GetLastFrameNo(L2_INST *l2InstPtr); +uint32_t L2_GetLastSlotNo(L2_INST *l2InstPtr); +uint32_t L2_GetCurrentFrameNo(L2_INST *l2InstPtr); +uint32_t L2_GetCurrentSlotNo(L2_INST *l2InstPtr); +uint32_t L2_GetNextFrameNo(L2_INST *l2InstPtr); +uint32_t L2_GetNextSlotNo(L2_INST *l2InstPtr); + +// Scanning +int32_t L2_Scan_Init(L2_INST *l2InstPtr); +int32_t L2_Scan_PktHandler(L2_INST *l2InstPtr, uint8_t *msg); +int32_t L2_Scan_Proc(L2_INST *l2InstPtr); +int32_t L2_Scan_Routine(L2_INST *l2InstPtr, L2_RTNE_TABLE_ENTRY *schedEntry); + +// Service +int32_t L2_Service_Init(L2_INST *l2InstPtr); +int32_t L2_Service_PktHandler(L2_INST *l2InstPtr, uint8_t *msg); +int32_t L2_Service_Proc(L2_INST *l2InstPtr); +int32_t L2_Service_Routine(L2_INST *l2InstPtr, L2_RTNE_TABLE_ENTRY *schedEntry); + +// Time Sync +int32_t L2_TimeSync_LocalTimerAdd(L2_INST *l2InstPtr, int64_t adjustment); +int32_t L2_TimeSync_SlotAlign(L2_INST *l2InstPtr); +int32_t L2_TimeSync_GetDeviatoion(L2_INST *l2InstPtr, int64_t *devi); + +#endif /* __LINK_LAYER_H_ */ diff --git a/df_datalink/src/networking/link_layer/link_layer_types.h b/df_datalink/src/networking/link_layer/link_layer_types.h new file mode 100644 index 0000000..7a625fd --- /dev/null +++ b/df_datalink/src/networking/link_layer/link_layer_types.h @@ -0,0 +1,199 @@ +/*****************************************************************************/ +/** + * Description: A brief description of this file + * + * Date: 2022-08-28 22:53 + * LastEditTime: 2022-08-29 00:45 + * Revisions: Rev 0.0 + * History: + * [2022-08-29]: Initial version. + * + * Copyright(c) 2022 Beijing Institute of Technology. + * Lab of Communication and Networking + * +******************************************************************************/ + +#ifndef __LINK_LAYER_DEF_H_ +#define __LINK_LAYER_DEF_H_ + +/***************************** Include Files *********************************/ +#include +#include +#include "geometry/coord.h" +#include "geometry/eulerangles.h" +#include "geometry/quaternion.h" +#include "../config/app_config.h" +#include "../phy_layer/phy_layer.h" +/************************** Constant Definitions *****************************/ +// Common node ID definition +#define BROADCAST_ID 0xFF + +// Routine configure +#define L2_RTNE_PERIOD 60 + +// Common slot number definition +#define L2_SLOTNO_NONE 0 +#define L2_FRAMENO_NONE 0 + +// Common number of slots definition +#define L2_FRAME_NO_MAX 256 +#define L2_SLOTS_PER_FRAME 200 +#define L2_SLOTS_PER_SUBFRAME 20 + +#define NUM_SLOTS_NONE UINT32_MAX +#define NUM_SLOTS_100MS 20 +#define NUM_SLOTS_20MS 4 +#define NUM_SLOTS_10MS 2 +#define NUM_SLOTS_5MS 1 +#define NUM_SLOTS_SKIP 0 + +// Common schedule event definition +#define L2_SCHD_EVENT_MAX 16 + +/***************** Macros (Inline Functions) Definitions *********************/ +#define AssertL2Event(inst, envent) Linklayer_EventHandler(inst, envent) +/**************************** Type Definitions *******************************/ + +typedef struct { + int32_t last; + int32_t curr; + int32_t next; +} L2_RCD; + +typedef enum { + L2_TOR_SUSPEND = 0, + L2_TOR_TX = 1, + L2_TOR_RX = 2 +} L2_TOR_TYPE; + +/** @name Prior information type definition + */ +typedef enum { + L2_NONE_TYPE = 0, + L2_HEAD_NODE = 1, + L2_MEMBER_NODE = 2, + L2_BACKUP_HEAD = 3 +} L2_NODE_TYPE; +/** @name Node state type definition + */ + +typedef enum { + NONE_STATE = 0, + INIT_STATE = 1, + NORMAL_STATE = 2 +} L2_NODE_STATE; + + +/** @name Node information type definition + * The following types define the detail node info which needed by the link layer. + */ +typedef struct { + uint8_t nodeId; + uint8_t nodeType; + uint8_t beamNo; + COORD pos; + COORD speed; + QUATERNION attitude; +} L2_NODE_INFO; + +/** @name L2 event enum + * A enum of L2 event types. + */ +typedef enum { + L2_EV_NONE = 0, + L2_EV_SCAN_PROC_DONE = 1, + L2_EV_NET_SETUP_DONE = 2, + L2_EV_TIME_SYNC = 3, + L2_EV_LOST_CXN = 4, + L2_EV_LOST_NODE = 5, + L2_EV_FRAME_NO_UPDATE = 6, + L2_EV_SLOT_NO_UPDATE = 7, + L2_EV_MAIN_STATE_UPDATE = 8, + L2_ROUTINE_FINISH = 9, + L2_ROUTINE_UPDATE = 10 +} L2_EVENT_TYPE; + +/** @name L2 event + * A definition of L2 event instance. + */ +typedef struct { + L2_EVENT_TYPE event; + void* msg; +} L2_EVENT; + +/** @name L2 event + * A definition of L2 event instance. + */ +typedef struct { + uint8_t eventId; + bool isSchd; + L2_EVENT l2Event; + uint32_t schdFrame; + uint32_t schdSlot; +} L2_SCHD_EVENT; + +/** @name Slot types + * A definition of different slots. + */ +typedef enum { + L2_SLOT_NONE = 0, + L2_SLOT_IDLE = 1, + L2_SLOT_SCAN = 2, + L2_SLOT_SERVICE = 3, + L2_SLOT_ADVERTISE = 4, +} L2_SLOT_TYPE; + +/** @name Frame types + * A definition of different frame types. + */ +typedef enum { + L2_NONE_FRAME = 0, + L2_SCAN_FRAME = 1, + L2_SVC_FRAME = 2, + L2_INFO_FRAME = 3 +} L2_FRAME_TYPE; + +/** @name Frame types + * A definition of different frame types. + */ +typedef enum { + L2_CRC_NONE = 0, + L2_CRC16_1021 = 1, + L2_CRC16_8005 = 2, + L2_CRC8_31 = 3 +} L2_CRC_TYPE; + +/** @name Schedule subtable entry + * A definition of Schedule subtable entry. + */ +typedef struct { + L2_SLOT_TYPE slotType : 8; + uint8_t slotSeq; + uint8_t src; + uint8_t dst; +} L2_RTNE_TABLE_ENTRY; + +/** @name Scan procedure FSM + */ +typedef struct { + uint8_t sacanCnt; + uint8_t beamNo; +} SCAN_FSM; + +/** @name Service procedure FSM + */ +typedef struct { + uint32_t txSeqNum; + uint32_t rxSeqNum; + uint8_t rxLog[256]; + uint8_t txLog[256]; + uint32_t pktRecv; + uint32_t pktRecved; +#ifdef DATALINK_ENABLE_BERTEST + uint32_t bitTotal; + uint32_t bitError; +#endif +} SVC_FSM; +/************************** Variable Definitions *****************************/ + +#endif /* __LINK_LAYER_DEF_H_ */ diff --git a/df_datalink/src/networking/link_layer/msg_def.h b/df_datalink/src/networking/link_layer/msg_def.h new file mode 100644 index 0000000..5ae7c49 --- /dev/null +++ b/df_datalink/src/networking/link_layer/msg_def.h @@ -0,0 +1,68 @@ +/*****************************************************************************/ +/** + * Description: Header of 814 linklayer messages + * + * Date: 2022-07-14 00:08 + * LastEditTime: 2022-07-14 22:52 + * Revisions: Rev 0.0 + * History: + * [2022-07-14]: Initial version. + * + * Copyright(c) 2021 Beijing Institute of Technology. + * Lab of Communication and Networking + * + ******************************************************************************/ +#ifndef __L2_MSG_DEF_H_ +#define __L2_MSG_DEF_H_ + +#define PACK_LEN_MAX 512 + +#define SVC_PACK_LEN 30 // bytes(240 bits) +#define RSP_PACK_LEN 30 // bytes(240 bits) + +// Common structure: +// [bytes] [name] +// 1 fame number +// 1 slot number +// 26 payload +// 2 crc +#define L2_MSG_FRAME_NO 0 +#define L2_MSG_SLOT_NO 1 +#define L2_MSG_PAYLOAD 2 +#define L2_MSG_CRC 28 + +// service frame structure: +// [bytes] [name] +// 1 fame number +// 1 slot number +// 3 time sync +// 23 payload +// 2 crc +#define L2_MSG_SVC_TMSYNC 2 +#define L2_MSG_SVC_TMSYNC_LEN 3 +#define L2_MSG_SVC_TMSYNC_MAX (8388607) //0x007FFFFF +#define L2_MSG_SVC_TMSYNC_MIN (-8388608) //0x00800000 +#define L2_MSG_SVC_SEQ_ID 5 +#define L2_MSG_SVC_PAYLOAD 6 +#define L2_MSG_SVC_PAYLOAD_LEN 22 + +// response frame structure: +// [bytes] [name] +// 1 fame number +// 1 slot number +// 4 position x +// 4 position y +// 4 position z +// 4 speed x +// 4 speed y +// 4 speed z +// 2 dummy +// 2 crc +#define L2_MSG_INFO_POSX 2 +#define L2_MSG_INFO_POSY 6 +#define L2_MSG_INFO_POSZ 10 +#define L2_MSG_INFO_SPEEDX 14 +#define L2_MSG_INFO_SPEEDY 18 +#define L2_MSG_INFO_SPEEDZ 22 +#define L2_MSG_INFO_DUMMY 26 +#endif //__L2_MSG_DEF_H_ diff --git a/df_datalink/src/networking/link_layer/node_list.c b/df_datalink/src/networking/link_layer/node_list.c new file mode 100644 index 0000000..1a74bec --- /dev/null +++ b/df_datalink/src/networking/link_layer/node_list.c @@ -0,0 +1,477 @@ +/*****************************************************************************/ +/** + * Description: Implementations of df linklayer local record. + * + * Date: 2022-07-14 00:08 + * LastEditTime: 2022-07-14 22:52 + * Revisions: Rev 0.0 + * History: + * [2022-07-14]: Initial version. + * + * Copyright(c) 2021 Beijing Institute of Technology. + * Lab of Communication and Networking + * + ******************************************************************************/ + +/***************************** Include Files *********************************/ +#include "common.h" +#include "error.h" +#include "link_layer.h" +#include "link_layer_types.h" +#include "node_list.h" + +/************************** Constant Definitions *****************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ +inline int32_t GetNodeNum(NODE_LIST *list) { + ASSERT(list != NULL); + return list->nodeNum; +} +/**************************** Type Definitions *******************************/ + +/************************** Variable Definitions *****************************/ + +/************************** Function Prototypes ******************************/ + +/*****************************************************************************/ +/** + * @brief Initialize node list + * + * @param list + * + * @return SUCCESS + * ENOMEM - not enough memory. + * + ******************************************************************************/ +int32_t NodeList_Init(NODE_LIST **list) { + NODE_ENTRY *entry; + (*list) = malloc(sizeof(NODE_LIST)); + if (*list == NULL) { + return ENOMEM; + } + entry = malloc(sizeof(NODE_ENTRY)); + if(entry == NULL) { + free(*list); + return ENOMEM; + } + entry->nodeInfo.nodeId = 0; + entry->nextNode = entry; + entry->preNode = entry; + (*list)->head = entry; + (*list)->nodeNum = 0; + return SUCCESS; +} + +void NodeList_Clear(NODE_LIST *list){ + ASSERT(list != NULL); + NODE_ENTRY *nodeEntry, *deletEntry; + nodeEntry = list->head->nextNode; + while (nodeEntry != list->head) { + deletEntry = nodeEntry; + nodeEntry = nodeEntry->nextNode; + deletEntry->preNode->nextNode = deletEntry->nextNode; + deletEntry->nextNode->preNode = deletEntry->preNode; + DBG_INFO("Deleting node [%d].\n", deletEntry->nodeInfo.nodeId); + free(deletEntry); + list->nodeNum--; + } +} + +void NodeList_Destroy(NODE_LIST *list){ + if(list == NULL){ + return; + } + NodeList_Clear(list); + free(list->head); + free(list); +} + +/*****************************************************************************/ +/** + * @brief Get node entry frome node list base on node id. + * + * @param list + * @param nodeId + * + * @return Node entry + * NULL if node dose not exist. + * + ******************************************************************************/ +NODE_ENTRY* GetNode(NODE_LIST *list, uint32_t nodeId) { + ASSERT(list != NULL); + NODE_ENTRY* nodeEntry = list->head->nextNode; + while (nodeEntry != list->head) { + if (nodeEntry->nodeInfo.nodeId == nodeId) { + break; + } + else { + nodeEntry = nodeEntry->nextNode; + } + } + if (nodeEntry == list->head) { + return NULL; + } + else { + return nodeEntry; + } +} + +/*****************************************************************************/ +/** + * @brief Check whether the node is already in the node list. + * + * @param list + * @param nodeId + * + * @return true node in the list + * false node not in the list + * + ******************************************************************************/ +inline bool IsNodeInList(NODE_LIST *list, uint8_t nodeId) { + ASSERT(list != NULL); + return (GetNode(list, nodeId) != NULL); +} + +/*****************************************************************************/ +/** + * @brief Append a new node entry to the node list + * + * @param list + * @param nodeId + * @param nodeType + * + * @return SUCCESS Node was added successfully. + * Other Error occurred.(Node already exist, memory alloc error ect.) + * + ******************************************************************************/ +int32_t AppendNode(NODE_LIST *list, uint8_t nodeId, L2_NODE_TYPE nodeType) +{ + ASSERT(list != NULL); + if(IsNodeInList(list, nodeId)){ + DBG_WARNING("Node [%d] already exist.\n", nodeId); + return FAILURE; + } + DBG_INFO("Link layer appending node [%d] to node list.\n", nodeId); + NODE_ENTRY* nodeEntry = (NODE_ENTRY*) malloc(sizeof(NODE_ENTRY)); + if (nodeEntry == NULL) { + return ENOMEM; + } + nodeEntry->nodeInfo.nodeId = nodeId; + nodeEntry->nodeInfo.nodeType = (uint8_t) nodeType; + nodeEntry->nodeInfo.pos.x = 0; + nodeEntry->nodeInfo.pos.y = 0; + nodeEntry->nodeInfo.pos.z = 0; + nodeEntry->nodeInfo.speed.x = 0; + nodeEntry->nodeInfo.speed.y = 0; + nodeEntry->nodeInfo.speed.z = 0; + nodeEntry->nodeInfo.beamNo = 0; + nodeEntry->ttlCnt = 0; + + nodeEntry->nextNode = list->head; + nodeEntry->preNode = list->head->nextNode; + list->head->nextNode = nodeEntry; + + list->nodeNum++; + return SUCCESS; +} + +/*****************************************************************************/ +/** + * @brief Delete a node in list based on node id. + * + * @param list + * @param nodeId + * + * @return SUCCESS Node has been successfully deleted. + * Other Node not exist. + * + ******************************************************************************/ +int32_t DeletNode(NODE_LIST *list, uint8_t nodeId) { + ASSERT(list != NULL); + NODE_ENTRY* nodeEntry = GetNode(list, nodeId); + if(nodeEntry == NULL){ + DBG_WARNING("Node [%d] in not in node list, skip deleting process.\n", nodeId); + return SUCCESS; + } + nodeEntry->preNode->nextNode = nodeEntry->nextNode; + nodeEntry->nextNode->preNode = nodeEntry->preNode; + DBG_INFO("Deleting node [%d].\n", nodeId); + free(nodeEntry); + list->nodeNum--; + return SUCCESS; +} + + +/*****************************************************************************/ +/** + * @brief Get the distance between me and the node. + * + * @param list + * @param nodeId + * @param dst A pointer to store distance. + * + * @return SUCCESS distance has been successfully store in dst + * FAILURE Node dose not exit. + * + ******************************************************************************/ + +int32_t GetDistance(NODE_LIST *list, COORD myCoord, uint8_t nodeId, double* dst) { + ASSERT(list != NULL); + NODE_ENTRY* nodeEntry = GetNode(list, nodeId); + if (nodeEntry == NULL) { + return FAILURE; + } + else { + *dst = Coord_Distance(myCoord, nodeEntry->nodeInfo.pos); + return SUCCESS; + } +} + +/*****************************************************************************/ +/** + * @brief Update node positions information. + * + * @param list + * @param nodeId + * @param newPos A structure stores the corresponding node position info. + * + * @return SUCCESS update successfully. + * FAILURE node not exist. + * + ******************************************************************************/ +int32_t UpdateNodePos(NODE_LIST *list, uint8_t nodeId, const COORD *newPos) { + ASSERT(list != NULL); + NODE_ENTRY* nodeEntry = GetNode(list, nodeId); + if (nodeEntry == NULL) { + return FAILURE; + } + else { + memcpy(&(nodeEntry->nodeInfo.pos), newPos, sizeof(COORD)); + } + return SUCCESS; +} + + +/*****************************************************************************/ +/** + * @brief Get node positions information. + * + * @param list + * @param nodeId + * @param newPos A structure stores the corresponding node position info. + * + * @return SUCCESS update successfully. + * FAILURE node not exist. + * + ******************************************************************************/ +int32_t GetNodePos(NODE_LIST *list, uint8_t nodeId, COORD *pos) { + ASSERT(list != NULL); + NODE_ENTRY* nodeEntry = GetNode(list, nodeId); + if (nodeEntry == NULL) { + return FAILURE; + } + else { + memcpy(pos, &(nodeEntry->nodeInfo.pos), sizeof(COORD)); + } + return SUCCESS; +} + +/*****************************************************************************/ +/** + * @brief Update node speed information. + * + * @param list + * @param nodeId + * @param newSpeed A structure stores the corresponding node speed info. + * + * @return SUCCESS update successfully. + * FAILURE node not exist. + * + ******************************************************************************/ +int32_t UpdateNodeSpeed(NODE_LIST *list, uint8_t nodeId, const COORD *newSpeed) { + ASSERT(list != NULL); + NODE_ENTRY* nodeEntry = GetNode(list, nodeId); + if (nodeEntry == NULL) { + return FAILURE; + } + else { + memcpy(&(nodeEntry->nodeInfo.speed), newSpeed, sizeof(COORD)); + } + return SUCCESS; +} + + +/*****************************************************************************/ +/** + * @brief Get node speed information. + * + * @param list + * @param nodeId + * @param newSpeed A structure stores the corresponding node speed info. + * + * @return SUCCESS update successfully. + * FAILURE node not exist. + * + ******************************************************************************/ +int32_t GetNodeSpeed(NODE_LIST *list, uint8_t nodeId, COORD *speed) { + ASSERT(list != NULL); + NODE_ENTRY* nodeEntry = GetNode(list, nodeId); + if (nodeEntry == NULL) { + return FAILURE; + } + else { + memcpy(speed, &(nodeEntry->nodeInfo.speed), sizeof(COORD)); + } + return SUCCESS; +} +/*****************************************************************************/ +/** + * @brief Update node ACK status. + * + * @param list + * @param nodeId + * @param defl + * + * @return SUCCESS update successfully. + * FAILURE Node not exist. + * + ******************************************************************************/ +int32_t UpdateNodeTimeDeviation(NODE_LIST *list, uint8_t nodeId, int32_t devi) { + ASSERT(list != NULL); + NODE_ENTRY* nodeEntry = GetNode(list, nodeId); + if (nodeEntry == NULL) { + return FAILURE; + } + else { + nodeEntry->timeDevi = devi; + } + return SUCCESS; +} + +/*****************************************************************************/ +/** + * @brief Increase TTL of specified node in the list. + * + * @param list + * @param inc cnt of slot to add + * @param nodeId + * + * @return NONE + * + ******************************************************************************/ +int32_t IncNodeTTL(NODE_LIST *list, uint8_t nodeId, uint32_t inc) { + ASSERT(list != NULL); + NODE_ENTRY* nodeEntry = GetNode(list, nodeId); + if (nodeEntry == NULL) { + return FAILURE; + } + else { + nodeEntry->ttlCnt += inc; + } + return SUCCESS; +} + +/*****************************************************************************/ +/** + * @brief Reset node TTL based on node id. + * + * @param list + * @param nodeId + * + * @return SUCCESS TTL has been successfully cleared. + * FAILURE Node not exist. + * + ******************************************************************************/ +int32_t RstNodeTTL(NODE_LIST *list, uint8_t nodeId) { + ASSERT(list != NULL); + NODE_ENTRY* nodeEntry = GetNode(list, nodeId); + if (nodeEntry == NULL) { + return FAILURE; + } + else { + nodeEntry->ttlCnt = 0; + } + return SUCCESS; +} + +/*****************************************************************************/ +/** + * @brief Get TTL of specified node in the list. + * + * @param list + * @param nodeId + * @param ttl + * + * @return NONE + * + ******************************************************************************/ +int32_t GetNodeTTL(NODE_LIST *list, uint8_t nodeId, uint32_t *ttl) { + ASSERT(list != NULL); + NODE_ENTRY* nodeEntry = GetNode(list, nodeId); + if (nodeEntry == NULL) { + return FAILURE; + } + else { + *ttl = nodeEntry->ttlCnt; + } + return SUCCESS; +} + +/*****************************************************************************/ +/** + * @brief Implements a edit operations to each node. + * + * @param list + * @param param + * @param operation A pointer to a function handled "NODE_ENTRY*" as input + * which defines the operations need to be apply. + * + * @return SUCCESS Operations has been applied successfully to all nodes. + * Other Error occurred. + * + ******************************************************************************/ +int32_t IterEditNode(NODE_LIST *list, const void *param, int32_t (*operation)(NODE_ENTRY *, const void *)) { + ASSERT(list != NULL); + int32_t Status = SUCCESS; + NODE_ENTRY *nodeEntry = list->head->nextNode; + while (nodeEntry != list->head) { + Status = operation(nodeEntry, param); + if(Status != SUCCESS){ + break; + } + nodeEntry = nodeEntry->nextNode; + } + return Status; +} + +/*****************************************************************************/ +/** + * @brief Filter all node, delete all the node not satisfied the condition. + * + * @param list + * @param condition A pointer to a function handled "NODE_ENTRY*" as input + * which defines the condition need to be verify. + * + * @return SUCCESS + * + ******************************************************************************/ +int32_t IterDeleteNode(NODE_LIST *list, bool (*condition)(NODE_ENTRY *)) { + ASSERT(list != NULL); + NODE_ENTRY *nodeEntry, *deletEntry; + nodeEntry = list->head->nextNode; + while (nodeEntry != list->head) { + if (condition(nodeEntry) == false) { + deletEntry = nodeEntry; + nodeEntry = nodeEntry->nextNode; + deletEntry->preNode->nextNode = deletEntry->nextNode; + deletEntry->nextNode->preNode = deletEntry->preNode; + DBG_INFO("Deleting node [%d].\n", deletEntry->nodeInfo.nodeId); + free(deletEntry); + list->nodeNum--; + } + else { + nodeEntry = nodeEntry->nextNode; + } + } + return SUCCESS; +} diff --git a/df_datalink/src/networking/link_layer/node_list.h b/df_datalink/src/networking/link_layer/node_list.h new file mode 100644 index 0000000..42185c0 --- /dev/null +++ b/df_datalink/src/networking/link_layer/node_list.h @@ -0,0 +1,64 @@ +/*****************************************************************************/ +/** + * Description: Header of 814 linklayer local record. + * + * Date: 2022-07-14 00:08 + * LastEditTime: 2022-07-14 22:52 + * Revisions: Rev 0.0 + * History: + * [2022-07-14]: Initial version. + * + * Copyright(c) 2021 Beijing Institute of Technology. + * Lab of Communication and Networking + * + ******************************************************************************/ + +/***************************** Include Files *********************************/ +#ifndef __L2_LOCAL_RECORD_H_ +#define __L2_LOCAL_RECORD_H_ +#include +#include +#include +#include +#include "util.h" +#include "link_layer_types.h" + +/************************** Constant Definitions *****************************/ +/***************** Macros (Inline Functions) Definitions *********************/ +/**************************** Type Definitions *******************************/ +typedef struct NODE_LIST_ENTRY { + L2_NODE_INFO nodeInfo; + uint32_t ttlCnt; + int32_t timeDevi; + struct NODE_LIST_ENTRY *nextNode; + struct NODE_LIST_ENTRY *preNode; +} NODE_ENTRY; + +typedef struct { + uint32_t nodeNum; + NODE_ENTRY *head; +} NODE_LIST; + +/************************** Variable Definitions *****************************/ + +/************************** Function Prototypes ******************************/ +int32_t NodeList_Init(NODE_LIST **list); +void NodeList_Clear(NODE_LIST *list); +void NodeList_Destroy(NODE_LIST *list); +NODE_ENTRY *GetNode(NODE_LIST *list, uint32_t nodeId); +int32_t AppendNode(NODE_LIST *list, uint8_t nodeId, L2_NODE_TYPE nodeType); +int32_t DeletNode(NODE_LIST *list, uint8_t nodeId); +int32_t UpdateNodePos(NODE_LIST *list, uint8_t nodeId, const COORD *newPos); +int32_t GetNodePos(NODE_LIST *list, uint8_t nodeId, COORD *newPos); +int32_t UpdateNodeSpeed(NODE_LIST *list, uint8_t nodeId, const COORD *newSpeed); +int32_t GetNodeSpeed(NODE_LIST *list, uint8_t nodeId, COORD *speed); +int32_t UpdateNodeTimeDeviation(NODE_LIST *list, uint8_t nodeId, int32_t devi); +int32_t GetDistance(NODE_LIST *list, COORD myCoord, uint8_t nodeId, double* dst); +int32_t GetNodeNum(NODE_LIST *list); +int32_t RstNodeTTL(NODE_LIST *list, uint8_t nodeId); +int32_t IncNodeTTL(NODE_LIST *list, uint8_t nodeId, uint32_t inc); +int32_t GetNodeTTL(NODE_LIST *list, uint8_t nodeId, uint32_t *ttl); +bool IsNodeInList(NODE_LIST *list, uint8_t nodeId); +int32_t IterEditNode(NODE_LIST *list, const void *param, int32_t (*operation)(NODE_ENTRY*, const void*)); +int32_t IterDeleteNode(NODE_LIST *list, bool (*condition)(NODE_ENTRY *)); +#endif /* __L2_LOCAL_RECORD_H_ */ diff --git a/df_datalink/src/networking/link_layer/routine_table.c b/df_datalink/src/networking/link_layer/routine_table.c new file mode 100644 index 0000000..63a3569 --- /dev/null +++ b/df_datalink/src/networking/link_layer/routine_table.c @@ -0,0 +1,536 @@ +/*****************************************************************************/ +/** + * Description: Time allocations for df datalink, + * Date: 2022-07-16 17:05 + * LastEditTime: 2022-07-16 17:05 + * Revisions: Rev 0.1 + * History: + * [2021-11-13]: Initial version. + * + * Copyright(c) 2021 Beijing Institute of Technology. + * Lab of Communication and Networking + * + ******************************************************************************/ + +#include +#include "link_layer.h" +#include "link_layer_types.h" +#include "../config/app_config.h" + +#ifndef DATALINK_ENABLE_BERTEST +L2_RTNE_TABLE_ENTRY normalSub1[L2_SLOTS_PER_FRAME] = { +// SubFrame 1 + {L2_SLOT_SERVICE,0x01,0x01,0x02}, {L2_SLOT_SERVICE,0x02,0x01,0x02}, + {L2_SLOT_SERVICE,0x03,0x01,0x02}, {L2_SLOT_SERVICE,0x04,0x01,0x02}, + {L2_SLOT_SERVICE,0x05,0x01,0x02}, {L2_SLOT_SERVICE,0x06,0x01,0x02}, + {L2_SLOT_SERVICE,0x07,0x01,0x02}, {L2_SLOT_SERVICE,0x08,0x01,0x02}, + {L2_SLOT_SERVICE,0x09,0x01,0x02}, {L2_SLOT_SERVICE,0x0A,0x01,0x02}, + {L2_SLOT_SERVICE,0x0B,0x01,0x02}, {L2_SLOT_SERVICE,0x0C,0x01,0x02}, + {L2_SLOT_SERVICE,0x0D,0x01,0x02}, {L2_SLOT_SERVICE,0x0E,0x01,0x02}, + {L2_SLOT_SERVICE,0x0F,0x01,0x02}, {L2_SLOT_SERVICE,0x10,0x01,0x02}, + {L2_SLOT_SERVICE,0x11,0x01,0x02}, {L2_SLOT_SERVICE,0x12,0x01,0x02}, + {L2_SLOT_SERVICE,0x13,0x01,0x02}, {L2_SLOT_SERVICE,0x14,0x01,0x02}, + +// SubFrame 2 + {L2_SLOT_SERVICE,0x01,0x01,0x02}, {L2_SLOT_SERVICE,0x02,0x01,0x02}, + {L2_SLOT_SERVICE,0x03,0x01,0x02}, {L2_SLOT_SERVICE,0x04,0x01,0x02}, + {L2_SLOT_SERVICE,0x05,0x01,0x02}, {L2_SLOT_SERVICE,0x06,0x01,0x02}, + {L2_SLOT_SERVICE,0x07,0x01,0x02}, {L2_SLOT_SERVICE,0x08,0x01,0x02}, + {L2_SLOT_SERVICE,0x09,0x01,0x02}, {L2_SLOT_SERVICE,0x0A,0x01,0x02}, + {L2_SLOT_SERVICE,0x0B,0x01,0x02}, {L2_SLOT_SERVICE,0x0C,0x01,0x02}, + {L2_SLOT_SERVICE,0x0D,0x01,0x02}, {L2_SLOT_SERVICE,0x0E,0x01,0x02}, + {L2_SLOT_SERVICE,0x0F,0x01,0x02}, {L2_SLOT_SERVICE,0x10,0x01,0x02}, + {L2_SLOT_SERVICE,0x11,0x01,0x02}, {L2_SLOT_SERVICE,0x12,0x01,0x02}, + {L2_SLOT_SERVICE,0x13,0x01,0x02}, {L2_SLOT_SERVICE,0x14,0x01,0x02}, + +// SubFrame 3 + {L2_SLOT_SERVICE,0x01,0x02,0x01}, {L2_SLOT_SERVICE,0x02,0x02,0x01}, + {L2_SLOT_SERVICE,0x03,0x02,0x01}, {L2_SLOT_SERVICE,0x04,0x02,0x01}, + {L2_SLOT_SERVICE,0x05,0x02,0x01}, {L2_SLOT_SERVICE,0x06,0x02,0x01}, + {L2_SLOT_SERVICE,0x07,0x02,0x01}, {L2_SLOT_SERVICE,0x08,0x02,0x01}, + {L2_SLOT_SERVICE,0x09,0x02,0x01}, {L2_SLOT_SERVICE,0x0A,0x02,0x01}, + {L2_SLOT_SERVICE,0x0B,0x02,0x01}, {L2_SLOT_SERVICE,0x0C,0x02,0x01}, + {L2_SLOT_SERVICE,0x0D,0x02,0x01}, {L2_SLOT_SERVICE,0x0E,0x02,0x01}, + {L2_SLOT_SERVICE,0x0F,0x02,0x01}, {L2_SLOT_SERVICE,0x10,0x02,0x01}, + {L2_SLOT_SERVICE,0x11,0x02,0x01}, {L2_SLOT_SERVICE,0x12,0x02,0x01}, + {L2_SLOT_SERVICE,0x13,0x02,0x01}, {L2_SLOT_SERVICE,0x14,0x02,0x01}, + +// SubFrame 4 + {L2_SLOT_SERVICE,0x01,0x01,0x02}, {L2_SLOT_SERVICE,0x02,0x01,0x02}, + {L2_SLOT_SERVICE,0x03,0x01,0x02}, {L2_SLOT_SERVICE,0x04,0x01,0x02}, + {L2_SLOT_SERVICE,0x05,0x01,0x02}, {L2_SLOT_SERVICE,0x06,0x01,0x02}, + {L2_SLOT_SERVICE,0x07,0x01,0x02}, {L2_SLOT_SERVICE,0x08,0x01,0x02}, + {L2_SLOT_SERVICE,0x09,0x01,0x02}, {L2_SLOT_SERVICE,0x0A,0x01,0x02}, + {L2_SLOT_SERVICE,0x0B,0x01,0x02}, {L2_SLOT_SERVICE,0x0C,0x01,0x02}, + {L2_SLOT_SERVICE,0x0D,0x01,0x02}, {L2_SLOT_SERVICE,0x0E,0x01,0x02}, + {L2_SLOT_SERVICE,0x0F,0x01,0x02}, {L2_SLOT_SERVICE,0x10,0x01,0x02}, + {L2_SLOT_SERVICE,0x11,0x01,0x02}, {L2_SLOT_SERVICE,0x12,0x01,0x02}, + {L2_SLOT_SERVICE,0x13,0x01,0x02}, {L2_SLOT_SERVICE,0x14,0x01,0x02}, + +// SubFrame 5 + {L2_SLOT_SERVICE,0x01,0x01,0x02}, {L2_SLOT_SERVICE,0x02,0x01,0x02}, + {L2_SLOT_SERVICE,0x03,0x01,0x02}, {L2_SLOT_SERVICE,0x04,0x01,0x02}, + {L2_SLOT_SERVICE,0x05,0x01,0x02}, {L2_SLOT_SERVICE,0x06,0x01,0x02}, + {L2_SLOT_SERVICE,0x07,0x01,0x02}, {L2_SLOT_SERVICE,0x08,0x01,0x02}, + {L2_SLOT_SERVICE,0x09,0x01,0x02}, {L2_SLOT_SERVICE,0x0A,0x01,0x02}, + {L2_SLOT_SERVICE,0x0B,0x01,0x02}, {L2_SLOT_SERVICE,0x0C,0x01,0x02}, + {L2_SLOT_SERVICE,0x0D,0x01,0x02}, {L2_SLOT_SERVICE,0x0E,0x01,0x02}, + {L2_SLOT_SERVICE,0x0F,0x01,0x02}, {L2_SLOT_SERVICE,0x10,0x01,0x02}, + {L2_SLOT_SERVICE,0x11,0x01,0x02}, {L2_SLOT_SERVICE,0x12,0x01,0x02}, + {L2_SLOT_SERVICE,0x13,0x01,0x02}, {L2_SLOT_SERVICE,0x14,0x01,0x02}, + +// SubFrame 6 + {L2_SLOT_SERVICE,0x01,0x02,0x01}, {L2_SLOT_SERVICE,0x02,0x02,0x01}, + {L2_SLOT_SERVICE,0x03,0x02,0x01}, {L2_SLOT_SERVICE,0x04,0x02,0x01}, + {L2_SLOT_SERVICE,0x05,0x02,0x01}, {L2_SLOT_SERVICE,0x06,0x02,0x01}, + {L2_SLOT_SERVICE,0x07,0x02,0x01}, {L2_SLOT_SERVICE,0x08,0x02,0x01}, + {L2_SLOT_SERVICE,0x09,0x02,0x01}, {L2_SLOT_SERVICE,0x0A,0x02,0x01}, + {L2_SLOT_SERVICE,0x0B,0x02,0x01}, {L2_SLOT_SERVICE,0x0C,0x02,0x01}, + {L2_SLOT_SERVICE,0x0D,0x02,0x01}, {L2_SLOT_SERVICE,0x0E,0x02,0x01}, + {L2_SLOT_SERVICE,0x0F,0x02,0x01}, {L2_SLOT_SERVICE,0x10,0x02,0x01}, + {L2_SLOT_SERVICE,0x11,0x02,0x01}, {L2_SLOT_SERVICE,0x12,0x02,0x01}, + {L2_SLOT_SERVICE,0x13,0x02,0x01}, {L2_SLOT_SERVICE,0x14,0x02,0x01}, + +// SubFrame 7 + {L2_SLOT_SERVICE,0x01,0x01,0x02}, {L2_SLOT_SERVICE,0x02,0x01,0x02}, + {L2_SLOT_SERVICE,0x03,0x01,0x02}, {L2_SLOT_SERVICE,0x04,0x01,0x02}, + {L2_SLOT_SERVICE,0x05,0x01,0x02}, {L2_SLOT_SERVICE,0x06,0x01,0x02}, + {L2_SLOT_SERVICE,0x07,0x01,0x02}, {L2_SLOT_SERVICE,0x08,0x01,0x02}, + {L2_SLOT_SERVICE,0x09,0x01,0x02}, {L2_SLOT_SERVICE,0x0A,0x01,0x02}, + {L2_SLOT_SERVICE,0x0B,0x01,0x02}, {L2_SLOT_SERVICE,0x0C,0x01,0x02}, + {L2_SLOT_SERVICE,0x0D,0x01,0x02}, {L2_SLOT_SERVICE,0x0E,0x01,0x02}, + {L2_SLOT_SERVICE,0x0F,0x01,0x02}, {L2_SLOT_SERVICE,0x10,0x01,0x02}, + {L2_SLOT_SERVICE,0x11,0x01,0x02}, {L2_SLOT_SERVICE,0x12,0x01,0x02}, + {L2_SLOT_SERVICE,0x13,0x01,0x02}, {L2_SLOT_SERVICE,0x14,0x01,0x02}, + +// SubFrame 8 + {L2_SLOT_SERVICE,0x01,0x01,0x02}, {L2_SLOT_SERVICE,0x02,0x01,0x02}, + {L2_SLOT_SERVICE,0x03,0x01,0x02}, {L2_SLOT_SERVICE,0x04,0x01,0x02}, + {L2_SLOT_SERVICE,0x05,0x01,0x02}, {L2_SLOT_SERVICE,0x06,0x01,0x02}, + {L2_SLOT_SERVICE,0x07,0x01,0x02}, {L2_SLOT_SERVICE,0x08,0x01,0x02}, + {L2_SLOT_SERVICE,0x09,0x01,0x02}, {L2_SLOT_SERVICE,0x0A,0x01,0x02}, + {L2_SLOT_SERVICE,0x0B,0x01,0x02}, {L2_SLOT_SERVICE,0x0C,0x01,0x02}, + {L2_SLOT_SERVICE,0x0D,0x01,0x02}, {L2_SLOT_SERVICE,0x0E,0x01,0x02}, + {L2_SLOT_SERVICE,0x0F,0x01,0x02}, {L2_SLOT_SERVICE,0x10,0x01,0x02}, + {L2_SLOT_SERVICE,0x11,0x01,0x02}, {L2_SLOT_SERVICE,0x12,0x01,0x02}, + {L2_SLOT_SERVICE,0x13,0x01,0x02}, {L2_SLOT_SERVICE,0x14,0x01,0x02}, + +// SubFrame 9 + {L2_SLOT_SERVICE,0x01,0x02,0x01}, {L2_SLOT_SERVICE,0x02,0x02,0x01}, + {L2_SLOT_SERVICE,0x03,0x02,0x01}, {L2_SLOT_SERVICE,0x04,0x02,0x01}, + {L2_SLOT_SERVICE,0x05,0x02,0x01}, {L2_SLOT_SERVICE,0x06,0x02,0x01}, + {L2_SLOT_SERVICE,0x07,0x02,0x01}, {L2_SLOT_SERVICE,0x08,0x02,0x01}, + {L2_SLOT_SERVICE,0x09,0x02,0x01}, {L2_SLOT_SERVICE,0x0A,0x02,0x01}, + {L2_SLOT_SERVICE,0x0B,0x02,0x01}, {L2_SLOT_SERVICE,0x0C,0x02,0x01}, + {L2_SLOT_SERVICE,0x0D,0x02,0x01}, {L2_SLOT_SERVICE,0x0E,0x02,0x01}, + {L2_SLOT_SERVICE,0x0F,0x02,0x01}, {L2_SLOT_SERVICE,0x10,0x02,0x01}, + {L2_SLOT_SERVICE,0x11,0x02,0x01}, {L2_SLOT_SERVICE,0x12,0x02,0x01}, + {L2_SLOT_SERVICE,0x13,0x02,0x01}, {L2_SLOT_SERVICE,0x14,0x02,0x01}, + +// SubFrame 10 + {L2_SLOT_SERVICE,0x01,0x01,0x02}, {L2_SLOT_SERVICE,0x02,0x01,0x02}, + {L2_SLOT_SERVICE,0x03,0x01,0x02}, {L2_SLOT_SERVICE,0x04,0x01,0x02}, + {L2_SLOT_SERVICE,0x05,0x01,0x02}, {L2_SLOT_SERVICE,0x06,0x01,0x02}, + {L2_SLOT_SERVICE,0x07,0x01,0x02}, {L2_SLOT_SERVICE,0x08,0x01,0x02}, + {L2_SLOT_SERVICE,0x09,0x01,0x02}, {L2_SLOT_SERVICE,0x0A,0x01,0x02}, + {L2_SLOT_SERVICE,0x0B,0x01,0x02}, {L2_SLOT_SERVICE,0x0C,0x01,0x02}, + {L2_SLOT_SERVICE,0x0D,0x01,0x02}, {L2_SLOT_SERVICE,0x0E,0x01,0x02}, + {L2_SLOT_SERVICE,0x0F,0x01,0x02}, {L2_SLOT_SERVICE,0x10,0x01,0x02}, + {L2_SLOT_SERVICE,0x11,0x01,0x02}, {L2_SLOT_SERVICE,0x12,0x01,0x02}, + {L2_SLOT_SERVICE,0x13,0x01,0x02}, {L2_SLOT_SERVICE,0x14,0x01,0x02} +}; + + +L2_RTNE_TABLE_ENTRY normalSub2[L2_SLOTS_PER_FRAME] = { +// SubFrame 1 + {L2_SLOT_SERVICE,0x01,0x01,0x02}, {L2_SLOT_SERVICE,0x02,0x01,0x02}, + {L2_SLOT_SERVICE,0x03,0x01,0x02}, {L2_SLOT_SERVICE,0x04,0x01,0x02}, + {L2_SLOT_SERVICE,0x05,0x01,0x02}, {L2_SLOT_SERVICE,0x06,0x01,0x02}, + {L2_SLOT_SERVICE,0x07,0x01,0x02}, {L2_SLOT_SERVICE,0x08,0x01,0x02}, + {L2_SLOT_SERVICE,0x09,0x01,0x02}, {L2_SLOT_SERVICE,0x0A,0x01,0x02}, + {L2_SLOT_SERVICE,0x0B,0x01,0x02}, {L2_SLOT_SERVICE,0x0C,0x01,0x02}, + {L2_SLOT_SERVICE,0x0D,0x01,0x02}, {L2_SLOT_SERVICE,0x0E,0x01,0x02}, + {L2_SLOT_SERVICE,0x0F,0x01,0x02}, {L2_SLOT_SERVICE,0x10,0x01,0x02}, + {L2_SLOT_SERVICE,0x11,0x01,0x02}, {L2_SLOT_SERVICE,0x12,0x01,0x02}, + {L2_SLOT_SERVICE,0x13,0x01,0x02}, {L2_SLOT_SERVICE,0x14,0x01,0x02}, + +// SubFrame 2 + {L2_SLOT_SERVICE,0x01,0x02,0x01}, {L2_SLOT_SERVICE,0x02,0x02,0x01}, + {L2_SLOT_SERVICE,0x03,0x02,0x01}, {L2_SLOT_SERVICE,0x04,0x02,0x01}, + {L2_SLOT_SERVICE,0x05,0x02,0x01}, {L2_SLOT_SERVICE,0x06,0x02,0x01}, + {L2_SLOT_SERVICE,0x07,0x02,0x01}, {L2_SLOT_SERVICE,0x08,0x02,0x01}, + {L2_SLOT_SERVICE,0x09,0x02,0x01}, {L2_SLOT_SERVICE,0x0A,0x02,0x01}, + {L2_SLOT_SERVICE,0x0B,0x02,0x01}, {L2_SLOT_SERVICE,0x0C,0x02,0x01}, + {L2_SLOT_SERVICE,0x0D,0x02,0x01}, {L2_SLOT_SERVICE,0x0E,0x02,0x01}, + {L2_SLOT_SERVICE,0x0F,0x02,0x01}, {L2_SLOT_SERVICE,0x10,0x02,0x01}, + {L2_SLOT_SERVICE,0x11,0x02,0x01}, {L2_SLOT_SERVICE,0x12,0x02,0x01}, + {L2_SLOT_SERVICE,0x13,0x02,0x01}, {L2_SLOT_SERVICE,0x14,0x02,0x01}, + +// SubFrame 3 + {L2_SLOT_SERVICE,0x01,0x01,0x02}, {L2_SLOT_SERVICE,0x02,0x01,0x02}, + {L2_SLOT_SERVICE,0x03,0x01,0x02}, {L2_SLOT_SERVICE,0x04,0x01,0x02}, + {L2_SLOT_SERVICE,0x05,0x01,0x02}, {L2_SLOT_SERVICE,0x06,0x01,0x02}, + {L2_SLOT_SERVICE,0x07,0x01,0x02}, {L2_SLOT_SERVICE,0x08,0x01,0x02}, + {L2_SLOT_SERVICE,0x09,0x01,0x02}, {L2_SLOT_SERVICE,0x0A,0x01,0x02}, + {L2_SLOT_SERVICE,0x0B,0x01,0x02}, {L2_SLOT_SERVICE,0x0C,0x01,0x02}, + {L2_SLOT_SERVICE,0x0D,0x01,0x02}, {L2_SLOT_SERVICE,0x0E,0x01,0x02}, + {L2_SLOT_SERVICE,0x0F,0x01,0x02}, {L2_SLOT_SERVICE,0x10,0x01,0x02}, + {L2_SLOT_SERVICE,0x11,0x01,0x02}, {L2_SLOT_SERVICE,0x12,0x01,0x02}, + {L2_SLOT_SERVICE,0x13,0x01,0x02}, {L2_SLOT_SERVICE,0x14,0x01,0x02}, + +// SubFrame 4 + {L2_SLOT_SERVICE,0x01,0x01,0x02}, {L2_SLOT_SERVICE,0x02,0x01,0x02}, + {L2_SLOT_SERVICE,0x03,0x01,0x02}, {L2_SLOT_SERVICE,0x04,0x01,0x02}, + {L2_SLOT_SERVICE,0x05,0x01,0x02}, {L2_SLOT_SERVICE,0x06,0x01,0x02}, + {L2_SLOT_SERVICE,0x07,0x01,0x02}, {L2_SLOT_SERVICE,0x08,0x01,0x02}, + {L2_SLOT_SERVICE,0x09,0x01,0x02}, {L2_SLOT_SERVICE,0x0A,0x01,0x02}, + {L2_SLOT_SERVICE,0x0B,0x01,0x02}, {L2_SLOT_SERVICE,0x0C,0x01,0x02}, + {L2_SLOT_SERVICE,0x0D,0x01,0x02}, {L2_SLOT_SERVICE,0x0E,0x01,0x02}, + {L2_SLOT_SERVICE,0x0F,0x01,0x02}, {L2_SLOT_SERVICE,0x10,0x01,0x02}, + {L2_SLOT_SERVICE,0x11,0x01,0x02}, {L2_SLOT_SERVICE,0x12,0x01,0x02}, + {L2_SLOT_SERVICE,0x13,0x01,0x02}, {L2_SLOT_SERVICE,0x14,0x01,0x02}, + +// SubFrame 5 + {L2_SLOT_SERVICE,0x01,0x02,0x01}, {L2_SLOT_SERVICE,0x02,0x02,0x01}, + {L2_SLOT_SERVICE,0x03,0x02,0x01}, {L2_SLOT_SERVICE,0x04,0x02,0x01}, + {L2_SLOT_SERVICE,0x05,0x02,0x01}, {L2_SLOT_SERVICE,0x06,0x02,0x01}, + {L2_SLOT_SERVICE,0x07,0x02,0x01}, {L2_SLOT_SERVICE,0x08,0x02,0x01}, + {L2_SLOT_SERVICE,0x09,0x02,0x01}, {L2_SLOT_SERVICE,0x0A,0x02,0x01}, + {L2_SLOT_SERVICE,0x0B,0x02,0x01}, {L2_SLOT_SERVICE,0x0C,0x02,0x01}, + {L2_SLOT_SERVICE,0x0D,0x02,0x01}, {L2_SLOT_SERVICE,0x0E,0x02,0x01}, + {L2_SLOT_SERVICE,0x0F,0x02,0x01}, {L2_SLOT_SERVICE,0x10,0x02,0x01}, + {L2_SLOT_SERVICE,0x11,0x02,0x01}, {L2_SLOT_SERVICE,0x12,0x02,0x01}, + {L2_SLOT_SERVICE,0x13,0x02,0x01}, {L2_SLOT_SERVICE,0x14,0x02,0x01}, + +// SubFrame 6 + {L2_SLOT_SERVICE,0x01,0x01,0x02}, {L2_SLOT_SERVICE,0x02,0x01,0x02}, + {L2_SLOT_SERVICE,0x03,0x01,0x02}, {L2_SLOT_SERVICE,0x04,0x01,0x02}, + {L2_SLOT_SERVICE,0x05,0x01,0x02}, {L2_SLOT_SERVICE,0x06,0x01,0x02}, + {L2_SLOT_SERVICE,0x07,0x01,0x02}, {L2_SLOT_SERVICE,0x08,0x01,0x02}, + {L2_SLOT_SERVICE,0x09,0x01,0x02}, {L2_SLOT_SERVICE,0x0A,0x01,0x02}, + {L2_SLOT_SERVICE,0x0B,0x01,0x02}, {L2_SLOT_SERVICE,0x0C,0x01,0x02}, + {L2_SLOT_SERVICE,0x0D,0x01,0x02}, {L2_SLOT_SERVICE,0x0E,0x01,0x02}, + {L2_SLOT_SERVICE,0x0F,0x01,0x02}, {L2_SLOT_SERVICE,0x10,0x01,0x02}, + {L2_SLOT_SERVICE,0x11,0x01,0x02}, {L2_SLOT_SERVICE,0x12,0x01,0x02}, + {L2_SLOT_SERVICE,0x13,0x01,0x02}, {L2_SLOT_SERVICE,0x14,0x01,0x02}, + +// SubFrame 7 + {L2_SLOT_SERVICE,0x01,0x01,0x02}, {L2_SLOT_SERVICE,0x02,0x01,0x02}, + {L2_SLOT_SERVICE,0x03,0x01,0x02}, {L2_SLOT_SERVICE,0x04,0x01,0x02}, + {L2_SLOT_SERVICE,0x05,0x01,0x02}, {L2_SLOT_SERVICE,0x06,0x01,0x02}, + {L2_SLOT_SERVICE,0x07,0x01,0x02}, {L2_SLOT_SERVICE,0x08,0x01,0x02}, + {L2_SLOT_SERVICE,0x09,0x01,0x02}, {L2_SLOT_SERVICE,0x0A,0x01,0x02}, + {L2_SLOT_SERVICE,0x0B,0x01,0x02}, {L2_SLOT_SERVICE,0x0C,0x01,0x02}, + {L2_SLOT_SERVICE,0x0D,0x01,0x02}, {L2_SLOT_SERVICE,0x0E,0x01,0x02}, + {L2_SLOT_SERVICE,0x0F,0x01,0x02}, {L2_SLOT_SERVICE,0x10,0x01,0x02}, + {L2_SLOT_SERVICE,0x11,0x01,0x02}, {L2_SLOT_SERVICE,0x12,0x01,0x02}, + {L2_SLOT_SERVICE,0x13,0x01,0x02}, {L2_SLOT_SERVICE,0x14,0x01,0x02}, + +// SubFrame 8 + {L2_SLOT_SERVICE,0x01,0x02,0x01}, {L2_SLOT_SERVICE,0x02,0x02,0x01}, + {L2_SLOT_SERVICE,0x03,0x02,0x01}, {L2_SLOT_SERVICE,0x04,0x02,0x01}, + {L2_SLOT_SERVICE,0x05,0x02,0x01}, {L2_SLOT_SERVICE,0x06,0x02,0x01}, + {L2_SLOT_SERVICE,0x07,0x02,0x01}, {L2_SLOT_SERVICE,0x08,0x02,0x01}, + {L2_SLOT_SERVICE,0x09,0x02,0x01}, {L2_SLOT_SERVICE,0x0A,0x02,0x01}, + {L2_SLOT_SERVICE,0x0B,0x02,0x01}, {L2_SLOT_SERVICE,0x0C,0x02,0x01}, + {L2_SLOT_SERVICE,0x0D,0x02,0x01}, {L2_SLOT_SERVICE,0x0E,0x02,0x01}, + {L2_SLOT_SERVICE,0x0F,0x02,0x01}, {L2_SLOT_SERVICE,0x10,0x02,0x01}, + {L2_SLOT_SERVICE,0x11,0x02,0x01}, {L2_SLOT_SERVICE,0x12,0x02,0x01}, + {L2_SLOT_SERVICE,0x13,0x02,0x01}, {L2_SLOT_SERVICE,0x14,0x02,0x01}, + +// SubFrame 9 + {L2_SLOT_SERVICE,0x01,0x01,0x02}, {L2_SLOT_SERVICE,0x02,0x01,0x02}, + {L2_SLOT_SERVICE,0x03,0x01,0x02}, {L2_SLOT_SERVICE,0x04,0x01,0x02}, + {L2_SLOT_SERVICE,0x05,0x01,0x02}, {L2_SLOT_SERVICE,0x06,0x01,0x02}, + {L2_SLOT_SERVICE,0x07,0x01,0x02}, {L2_SLOT_SERVICE,0x08,0x01,0x02}, + {L2_SLOT_SERVICE,0x09,0x01,0x02}, {L2_SLOT_SERVICE,0x0A,0x01,0x02}, + {L2_SLOT_SERVICE,0x0B,0x01,0x02}, {L2_SLOT_SERVICE,0x0C,0x01,0x02}, + {L2_SLOT_SERVICE,0x0D,0x01,0x02}, {L2_SLOT_SERVICE,0x0E,0x01,0x02}, + {L2_SLOT_SERVICE,0x0F,0x01,0x02}, {L2_SLOT_SERVICE,0x10,0x01,0x02}, + {L2_SLOT_SERVICE,0x11,0x01,0x02}, {L2_SLOT_SERVICE,0x12,0x01,0x02}, + {L2_SLOT_SERVICE,0x13,0x01,0x02}, {L2_SLOT_SERVICE,0x14,0x01,0x02}, + +// SubFrame 10 + {L2_SLOT_SERVICE,0x01,0x01,0x02}, {L2_SLOT_SERVICE,0x02,0x01,0x02}, + {L2_SLOT_SERVICE,0x03,0x01,0x02}, {L2_SLOT_SERVICE,0x04,0x01,0x02}, + {L2_SLOT_SERVICE,0x05,0x01,0x02}, {L2_SLOT_SERVICE,0x06,0x01,0x02}, + {L2_SLOT_SERVICE,0x07,0x01,0x02}, {L2_SLOT_SERVICE,0x08,0x01,0x02}, + {L2_SLOT_SERVICE,0x09,0x01,0x02}, {L2_SLOT_SERVICE,0x0A,0x01,0x02}, + {L2_SLOT_SERVICE,0x0B,0x01,0x02}, {L2_SLOT_SERVICE,0x0C,0x01,0x02}, + {L2_SLOT_SERVICE,0x0D,0x01,0x02}, {L2_SLOT_SERVICE,0x0E,0x01,0x02}, + {L2_SLOT_SERVICE,0x0F,0x01,0x02}, {L2_SLOT_SERVICE,0x10,0x01,0x02}, + {L2_SLOT_SERVICE,0x11,0x01,0x02}, {L2_SLOT_SERVICE,0x12,0x01,0x02}, + {L2_SLOT_SERVICE,0x13,0x01,0x02}, {L2_SLOT_SERVICE,0x14,0x01,0x02} +}; + +L2_RTNE_TABLE_ENTRY normalSub3[L2_SLOTS_PER_FRAME] = { + // SubFrame 1 + {L2_SLOT_SERVICE,0x01,0x02,0x01}, {L2_SLOT_SERVICE,0x02,0x02,0x01}, + {L2_SLOT_SERVICE,0x03,0x02,0x01}, {L2_SLOT_SERVICE,0x04,0x02,0x01}, + {L2_SLOT_SERVICE,0x05,0x02,0x01}, {L2_SLOT_SERVICE,0x06,0x02,0x01}, + {L2_SLOT_SERVICE,0x07,0x02,0x01}, {L2_SLOT_SERVICE,0x08,0x02,0x01}, + {L2_SLOT_SERVICE,0x09,0x02,0x01}, {L2_SLOT_SERVICE,0x0A,0x02,0x01}, + {L2_SLOT_SERVICE,0x0B,0x02,0x01}, {L2_SLOT_SERVICE,0x0C,0x02,0x01}, + {L2_SLOT_SERVICE,0x0D,0x02,0x01}, {L2_SLOT_SERVICE,0x0E,0x02,0x01}, + {L2_SLOT_SERVICE,0x0F,0x02,0x01}, {L2_SLOT_SERVICE,0x10,0x02,0x01}, + {L2_SLOT_SERVICE,0x11,0x02,0x01}, {L2_SLOT_SERVICE,0x12,0x02,0x01}, + {L2_SLOT_SERVICE,0x13,0x02,0x01}, {L2_SLOT_SERVICE,0x14,0x02,0x01}, + +// SubFrame 2 + {L2_SLOT_SERVICE,0x01,0x01,0x02}, {L2_SLOT_SERVICE,0x02,0x01,0x02}, + {L2_SLOT_SERVICE,0x03,0x01,0x02}, {L2_SLOT_SERVICE,0x04,0x01,0x02}, + {L2_SLOT_SERVICE,0x05,0x01,0x02}, {L2_SLOT_SERVICE,0x06,0x01,0x02}, + {L2_SLOT_SERVICE,0x07,0x01,0x02}, {L2_SLOT_SERVICE,0x08,0x01,0x02}, + {L2_SLOT_SERVICE,0x09,0x01,0x02}, {L2_SLOT_SERVICE,0x0A,0x01,0x02}, + {L2_SLOT_SERVICE,0x0B,0x01,0x02}, {L2_SLOT_SERVICE,0x0C,0x01,0x02}, + {L2_SLOT_SERVICE,0x0D,0x01,0x02}, {L2_SLOT_SERVICE,0x0E,0x01,0x02}, + {L2_SLOT_SERVICE,0x0F,0x01,0x02}, {L2_SLOT_SERVICE,0x10,0x01,0x02}, + {L2_SLOT_SERVICE,0x11,0x01,0x02}, {L2_SLOT_SERVICE,0x12,0x01,0x02}, + {L2_SLOT_SERVICE,0x13,0x01,0x02}, {L2_SLOT_SERVICE,0x14,0x01,0x02}, + +// SubFrame 3 + {L2_SLOT_SERVICE,0x01,0x01,0x02}, {L2_SLOT_SERVICE,0x02,0x01,0x02}, + {L2_SLOT_SERVICE,0x03,0x01,0x02}, {L2_SLOT_SERVICE,0x04,0x01,0x02}, + {L2_SLOT_SERVICE,0x05,0x01,0x02}, {L2_SLOT_SERVICE,0x06,0x01,0x02}, + {L2_SLOT_SERVICE,0x07,0x01,0x02}, {L2_SLOT_SERVICE,0x08,0x01,0x02}, + {L2_SLOT_SERVICE,0x09,0x01,0x02}, {L2_SLOT_SERVICE,0x0A,0x01,0x02}, + {L2_SLOT_SERVICE,0x0B,0x01,0x02}, {L2_SLOT_SERVICE,0x0C,0x01,0x02}, + {L2_SLOT_SERVICE,0x0D,0x01,0x02}, {L2_SLOT_SERVICE,0x0E,0x01,0x02}, + {L2_SLOT_SERVICE,0x0F,0x01,0x02}, {L2_SLOT_SERVICE,0x10,0x01,0x02}, + {L2_SLOT_SERVICE,0x11,0x01,0x02}, {L2_SLOT_SERVICE,0x12,0x01,0x02}, + {L2_SLOT_SERVICE,0x13,0x01,0x02}, {L2_SLOT_SERVICE,0x14,0x01,0x02}, + +// SubFrame 4 + {L2_SLOT_SERVICE,0x01,0x02,0x01}, {L2_SLOT_SERVICE,0x02,0x02,0x01}, + {L2_SLOT_SERVICE,0x03,0x02,0x01}, {L2_SLOT_SERVICE,0x04,0x02,0x01}, + {L2_SLOT_SERVICE,0x05,0x02,0x01}, {L2_SLOT_SERVICE,0x06,0x02,0x01}, + {L2_SLOT_SERVICE,0x07,0x02,0x01}, {L2_SLOT_SERVICE,0x08,0x02,0x01}, + {L2_SLOT_SERVICE,0x09,0x02,0x01}, {L2_SLOT_SERVICE,0x0A,0x02,0x01}, + {L2_SLOT_SERVICE,0x0B,0x02,0x01}, {L2_SLOT_SERVICE,0x0C,0x02,0x01}, + {L2_SLOT_SERVICE,0x0D,0x02,0x01}, {L2_SLOT_SERVICE,0x0E,0x02,0x01}, + {L2_SLOT_SERVICE,0x0F,0x02,0x01}, {L2_SLOT_SERVICE,0x10,0x02,0x01}, + {L2_SLOT_SERVICE,0x11,0x02,0x01}, {L2_SLOT_SERVICE,0x12,0x02,0x01}, + {L2_SLOT_SERVICE,0x13,0x02,0x01}, {L2_SLOT_SERVICE,0x14,0x02,0x01}, + +// SubFrame 5 + {L2_SLOT_SERVICE,0x01,0x01,0x02}, {L2_SLOT_SERVICE,0x02,0x01,0x02}, + {L2_SLOT_SERVICE,0x03,0x01,0x02}, {L2_SLOT_SERVICE,0x04,0x01,0x02}, + {L2_SLOT_SERVICE,0x05,0x01,0x02}, {L2_SLOT_SERVICE,0x06,0x01,0x02}, + {L2_SLOT_SERVICE,0x07,0x01,0x02}, {L2_SLOT_SERVICE,0x08,0x01,0x02}, + {L2_SLOT_SERVICE,0x09,0x01,0x02}, {L2_SLOT_SERVICE,0x0A,0x01,0x02}, + {L2_SLOT_SERVICE,0x0B,0x01,0x02}, {L2_SLOT_SERVICE,0x0C,0x01,0x02}, + {L2_SLOT_SERVICE,0x0D,0x01,0x02}, {L2_SLOT_SERVICE,0x0E,0x01,0x02}, + {L2_SLOT_SERVICE,0x0F,0x01,0x02}, {L2_SLOT_SERVICE,0x10,0x01,0x02}, + {L2_SLOT_SERVICE,0x11,0x01,0x02}, {L2_SLOT_SERVICE,0x12,0x01,0x02}, + {L2_SLOT_SERVICE,0x13,0x01,0x02}, {L2_SLOT_SERVICE,0x14,0x01,0x02}, + +// SubFrame 6 + {L2_SLOT_SERVICE,0x01,0x01,0x02}, {L2_SLOT_SERVICE,0x02,0x01,0x02}, + {L2_SLOT_SERVICE,0x03,0x01,0x02}, {L2_SLOT_SERVICE,0x04,0x01,0x02}, + {L2_SLOT_SERVICE,0x05,0x01,0x02}, {L2_SLOT_SERVICE,0x06,0x01,0x02}, + {L2_SLOT_SERVICE,0x07,0x01,0x02}, {L2_SLOT_SERVICE,0x08,0x01,0x02}, + {L2_SLOT_SERVICE,0x09,0x01,0x02}, {L2_SLOT_SERVICE,0x0A,0x01,0x02}, + {L2_SLOT_SERVICE,0x0B,0x01,0x02}, {L2_SLOT_SERVICE,0x0C,0x01,0x02}, + {L2_SLOT_SERVICE,0x0D,0x01,0x02}, {L2_SLOT_SERVICE,0x0E,0x01,0x02}, + {L2_SLOT_SERVICE,0x0F,0x01,0x02}, {L2_SLOT_SERVICE,0x10,0x01,0x02}, + {L2_SLOT_SERVICE,0x11,0x01,0x02}, {L2_SLOT_SERVICE,0x12,0x01,0x02}, + {L2_SLOT_SERVICE,0x13,0x01,0x02}, {L2_SLOT_SERVICE,0x14,0x01,0x02}, + +// SubFrame 7 + {L2_SLOT_SERVICE,0x01,0x02,0x01}, {L2_SLOT_SERVICE,0x02,0x02,0x01}, + {L2_SLOT_SERVICE,0x03,0x02,0x01}, {L2_SLOT_SERVICE,0x04,0x02,0x01}, + {L2_SLOT_SERVICE,0x05,0x02,0x01}, {L2_SLOT_SERVICE,0x06,0x02,0x01}, + {L2_SLOT_SERVICE,0x07,0x02,0x01}, {L2_SLOT_SERVICE,0x08,0x02,0x01}, + {L2_SLOT_SERVICE,0x09,0x02,0x01}, {L2_SLOT_SERVICE,0x0A,0x02,0x01}, + {L2_SLOT_SERVICE,0x0B,0x02,0x01}, {L2_SLOT_SERVICE,0x0C,0x02,0x01}, + {L2_SLOT_SERVICE,0x0D,0x02,0x01}, {L2_SLOT_SERVICE,0x0E,0x02,0x01}, + {L2_SLOT_SERVICE,0x0F,0x02,0x01}, {L2_SLOT_SERVICE,0x10,0x02,0x01}, + {L2_SLOT_SERVICE,0x11,0x02,0x01}, {L2_SLOT_SERVICE,0x12,0x02,0x01}, + {L2_SLOT_SERVICE,0x13,0x02,0x01}, {L2_SLOT_SERVICE,0x14,0x02,0x01}, + +// SubFrame 8 + {L2_SLOT_SERVICE,0x01,0x01,0x02}, {L2_SLOT_SERVICE,0x02,0x01,0x02}, + {L2_SLOT_SERVICE,0x03,0x01,0x02}, {L2_SLOT_SERVICE,0x04,0x01,0x02}, + {L2_SLOT_SERVICE,0x05,0x01,0x02}, {L2_SLOT_SERVICE,0x06,0x01,0x02}, + {L2_SLOT_SERVICE,0x07,0x01,0x02}, {L2_SLOT_SERVICE,0x08,0x01,0x02}, + {L2_SLOT_SERVICE,0x09,0x01,0x02}, {L2_SLOT_SERVICE,0x0A,0x01,0x02}, + {L2_SLOT_SERVICE,0x0B,0x01,0x02}, {L2_SLOT_SERVICE,0x0C,0x01,0x02}, + {L2_SLOT_SERVICE,0x0D,0x01,0x02}, {L2_SLOT_SERVICE,0x0E,0x01,0x02}, + {L2_SLOT_SERVICE,0x0F,0x01,0x02}, {L2_SLOT_SERVICE,0x10,0x01,0x02}, + {L2_SLOT_SERVICE,0x11,0x01,0x02}, {L2_SLOT_SERVICE,0x12,0x01,0x02}, + {L2_SLOT_SERVICE,0x13,0x01,0x02}, {L2_SLOT_SERVICE,0x14,0x01,0x02}, + +// SubFrame 9 + {L2_SLOT_SERVICE,0x01,0x01,0x02}, {L2_SLOT_SERVICE,0x02,0x01,0x02}, + {L2_SLOT_SERVICE,0x03,0x01,0x02}, {L2_SLOT_SERVICE,0x04,0x01,0x02}, + {L2_SLOT_SERVICE,0x05,0x01,0x02}, {L2_SLOT_SERVICE,0x06,0x01,0x02}, + {L2_SLOT_SERVICE,0x07,0x01,0x02}, {L2_SLOT_SERVICE,0x08,0x01,0x02}, + {L2_SLOT_SERVICE,0x09,0x01,0x02}, {L2_SLOT_SERVICE,0x0A,0x01,0x02}, + {L2_SLOT_SERVICE,0x0B,0x01,0x02}, {L2_SLOT_SERVICE,0x0C,0x01,0x02}, + {L2_SLOT_SERVICE,0x0D,0x01,0x02}, {L2_SLOT_SERVICE,0x0E,0x01,0x02}, + {L2_SLOT_SERVICE,0x0F,0x01,0x02}, {L2_SLOT_SERVICE,0x10,0x01,0x02}, + {L2_SLOT_SERVICE,0x11,0x01,0x02}, {L2_SLOT_SERVICE,0x12,0x01,0x02}, + {L2_SLOT_SERVICE,0x13,0x01,0x02}, {L2_SLOT_SERVICE,0x14,0x01,0x02}, + +// SubFrame 10 + {L2_SLOT_SERVICE,0x01,0x02,0x01}, {L2_SLOT_SERVICE,0x02,0x02,0x01}, + {L2_SLOT_SERVICE,0x03,0x02,0x01}, {L2_SLOT_SERVICE,0x04,0x02,0x01}, + {L2_SLOT_SERVICE,0x05,0x02,0x01}, {L2_SLOT_SERVICE,0x06,0x02,0x01}, + {L2_SLOT_SERVICE,0x07,0x02,0x01}, {L2_SLOT_SERVICE,0x08,0x02,0x01}, + {L2_SLOT_SERVICE,0x09,0x02,0x01}, {L2_SLOT_SERVICE,0x0A,0x02,0x01}, + {L2_SLOT_SERVICE,0x0B,0x02,0x01}, {L2_SLOT_SERVICE,0x0C,0x02,0x01}, + {L2_SLOT_SERVICE,0x0D,0x02,0x01}, {L2_SLOT_SERVICE,0x0E,0x02,0x01}, + {L2_SLOT_SERVICE,0x0F,0x02,0x01}, {L2_SLOT_SERVICE,0x10,0x02,0x01}, + {L2_SLOT_SERVICE,0x11,0x02,0x01}, {L2_SLOT_SERVICE,0x12,0x02,0x01}, + {L2_SLOT_SERVICE,0x13,0x02,0x01}, {L2_SLOT_SERVICE,0x14,0x02,0x01} +}; + +L2_RTNE_TABLE_ENTRY* normalTable[L2_RTNE_PERIOD] = { + normalSub1, normalSub2, normalSub3, normalSub1, normalSub2, normalSub3, + normalSub1, normalSub2, normalSub3, normalSub1, normalSub2, normalSub3, + normalSub1, normalSub2, normalSub3, normalSub1, normalSub2, normalSub3, + normalSub1, normalSub2, normalSub3, normalSub1, normalSub2, normalSub3, + normalSub1, normalSub2, normalSub3, normalSub1, normalSub2, normalSub3, + normalSub1, normalSub2, normalSub3, normalSub1, normalSub2, normalSub3, + normalSub1, normalSub2, normalSub3, normalSub1, normalSub2, normalSub3, + normalSub1, normalSub2, normalSub3, normalSub1, normalSub2, normalSub3, + normalSub1, normalSub2, normalSub3, normalSub1, normalSub2, normalSub3, + normalSub1, normalSub2, normalSub3, normalSub1, normalSub2, normalSub3 +}; +#else +L2_RTNE_TABLE_ENTRY normalSub[L2_SLOTS_PER_FRAME] = { +// SubFrame 1 + {L2_SLOT_SERVICE,0x01,0x01,0x02}, {L2_SLOT_SERVICE,0x02,0x01,0x02}, + {L2_SLOT_SERVICE,0x03,0x01,0x02}, {L2_SLOT_SERVICE,0x04,0x01,0x02}, + {L2_SLOT_SERVICE,0x05,0x01,0x02}, {L2_SLOT_SERVICE,0x06,0x01,0x02}, + {L2_SLOT_SERVICE,0x07,0x01,0x02}, {L2_SLOT_SERVICE,0x08,0x01,0x02}, + {L2_SLOT_SERVICE,0x09,0x01,0x02}, {L2_SLOT_SERVICE,0x0A,0x01,0x02}, + {L2_SLOT_SERVICE,0x0B,0x01,0x02}, {L2_SLOT_SERVICE,0x0C,0x01,0x02}, + {L2_SLOT_SERVICE,0x0D,0x01,0x02}, {L2_SLOT_SERVICE,0x0E,0x01,0x02}, + {L2_SLOT_SERVICE,0x0F,0x01,0x02}, {L2_SLOT_SERVICE,0x10,0x01,0x02}, + {L2_SLOT_SERVICE,0x11,0x01,0x02}, {L2_SLOT_SERVICE,0x12,0x01,0x02}, + {L2_SLOT_SERVICE,0x13,0x01,0x02}, {L2_SLOT_SERVICE,0x14,0x01,0x02}, + +// SubFrame 2 + {L2_SLOT_SERVICE,0x01,0x02,0x01}, {L2_SLOT_SERVICE,0x02,0x02,0x01}, + {L2_SLOT_SERVICE,0x03,0x02,0x01}, {L2_SLOT_SERVICE,0x04,0x02,0x01}, + {L2_SLOT_SERVICE,0x05,0x02,0x01}, {L2_SLOT_SERVICE,0x06,0x02,0x01}, + {L2_SLOT_SERVICE,0x07,0x02,0x01}, {L2_SLOT_SERVICE,0x08,0x02,0x01}, + {L2_SLOT_SERVICE,0x09,0x02,0x01}, {L2_SLOT_SERVICE,0x0A,0x02,0x01}, + {L2_SLOT_SERVICE,0x0B,0x02,0x01}, {L2_SLOT_SERVICE,0x0C,0x02,0x01}, + {L2_SLOT_SERVICE,0x0D,0x02,0x01}, {L2_SLOT_SERVICE,0x0E,0x02,0x01}, + {L2_SLOT_SERVICE,0x0F,0x02,0x01}, {L2_SLOT_SERVICE,0x10,0x02,0x01}, + {L2_SLOT_SERVICE,0x11,0x02,0x01}, {L2_SLOT_SERVICE,0x12,0x02,0x01}, + {L2_SLOT_SERVICE,0x13,0x02,0x01}, {L2_SLOT_SERVICE,0x14,0x02,0x01}, + +// SubFrame 3 + {L2_SLOT_SERVICE,0x01,0x01,0x02}, {L2_SLOT_SERVICE,0x02,0x01,0x02}, + {L2_SLOT_SERVICE,0x03,0x01,0x02}, {L2_SLOT_SERVICE,0x04,0x01,0x02}, + {L2_SLOT_SERVICE,0x05,0x01,0x02}, {L2_SLOT_SERVICE,0x06,0x01,0x02}, + {L2_SLOT_SERVICE,0x07,0x01,0x02}, {L2_SLOT_SERVICE,0x08,0x01,0x02}, + {L2_SLOT_SERVICE,0x09,0x01,0x02}, {L2_SLOT_SERVICE,0x0A,0x01,0x02}, + {L2_SLOT_SERVICE,0x0B,0x01,0x02}, {L2_SLOT_SERVICE,0x0C,0x01,0x02}, + {L2_SLOT_SERVICE,0x0D,0x01,0x02}, {L2_SLOT_SERVICE,0x0E,0x01,0x02}, + {L2_SLOT_SERVICE,0x0F,0x01,0x02}, {L2_SLOT_SERVICE,0x10,0x01,0x02}, + {L2_SLOT_SERVICE,0x11,0x01,0x02}, {L2_SLOT_SERVICE,0x12,0x01,0x02}, + {L2_SLOT_SERVICE,0x13,0x01,0x02}, {L2_SLOT_SERVICE,0x14,0x01,0x02}, + +// SubFrame 4 + {L2_SLOT_SERVICE,0x01,0x02,0x01}, {L2_SLOT_SERVICE,0x02,0x02,0x01}, + {L2_SLOT_SERVICE,0x03,0x02,0x01}, {L2_SLOT_SERVICE,0x04,0x02,0x01}, + {L2_SLOT_SERVICE,0x05,0x02,0x01}, {L2_SLOT_SERVICE,0x06,0x02,0x01}, + {L2_SLOT_SERVICE,0x07,0x02,0x01}, {L2_SLOT_SERVICE,0x08,0x02,0x01}, + {L2_SLOT_SERVICE,0x09,0x02,0x01}, {L2_SLOT_SERVICE,0x0A,0x02,0x01}, + {L2_SLOT_SERVICE,0x0B,0x02,0x01}, {L2_SLOT_SERVICE,0x0C,0x02,0x01}, + {L2_SLOT_SERVICE,0x0D,0x02,0x01}, {L2_SLOT_SERVICE,0x0E,0x02,0x01}, + {L2_SLOT_SERVICE,0x0F,0x02,0x01}, {L2_SLOT_SERVICE,0x10,0x02,0x01}, + {L2_SLOT_SERVICE,0x11,0x02,0x01}, {L2_SLOT_SERVICE,0x12,0x02,0x01}, + {L2_SLOT_SERVICE,0x13,0x02,0x01}, {L2_SLOT_SERVICE,0x14,0x02,0x01}, + +// SubFrame 5 + {L2_SLOT_SERVICE,0x01,0x01,0x02}, {L2_SLOT_SERVICE,0x02,0x01,0x02}, + {L2_SLOT_SERVICE,0x03,0x01,0x02}, {L2_SLOT_SERVICE,0x04,0x01,0x02}, + {L2_SLOT_SERVICE,0x05,0x01,0x02}, {L2_SLOT_SERVICE,0x06,0x01,0x02}, + {L2_SLOT_SERVICE,0x07,0x01,0x02}, {L2_SLOT_SERVICE,0x08,0x01,0x02}, + {L2_SLOT_SERVICE,0x09,0x01,0x02}, {L2_SLOT_SERVICE,0x0A,0x01,0x02}, + {L2_SLOT_SERVICE,0x0B,0x01,0x02}, {L2_SLOT_SERVICE,0x0C,0x01,0x02}, + {L2_SLOT_SERVICE,0x0D,0x01,0x02}, {L2_SLOT_SERVICE,0x0E,0x01,0x02}, + {L2_SLOT_SERVICE,0x0F,0x01,0x02}, {L2_SLOT_SERVICE,0x10,0x01,0x02}, + {L2_SLOT_SERVICE,0x11,0x01,0x02}, {L2_SLOT_SERVICE,0x12,0x01,0x02}, + {L2_SLOT_SERVICE,0x13,0x01,0x02}, {L2_SLOT_SERVICE,0x14,0x01,0x02}, + +// SubFrame 6 + {L2_SLOT_SERVICE,0x01,0x02,0x01}, {L2_SLOT_SERVICE,0x02,0x02,0x01}, + {L2_SLOT_SERVICE,0x03,0x02,0x01}, {L2_SLOT_SERVICE,0x04,0x02,0x01}, + {L2_SLOT_SERVICE,0x05,0x02,0x01}, {L2_SLOT_SERVICE,0x06,0x02,0x01}, + {L2_SLOT_SERVICE,0x07,0x02,0x01}, {L2_SLOT_SERVICE,0x08,0x02,0x01}, + {L2_SLOT_SERVICE,0x09,0x02,0x01}, {L2_SLOT_SERVICE,0x0A,0x02,0x01}, + {L2_SLOT_SERVICE,0x0B,0x02,0x01}, {L2_SLOT_SERVICE,0x0C,0x02,0x01}, + {L2_SLOT_SERVICE,0x0D,0x02,0x01}, {L2_SLOT_SERVICE,0x0E,0x02,0x01}, + {L2_SLOT_SERVICE,0x0F,0x02,0x01}, {L2_SLOT_SERVICE,0x10,0x02,0x01}, + {L2_SLOT_SERVICE,0x11,0x02,0x01}, {L2_SLOT_SERVICE,0x12,0x02,0x01}, + {L2_SLOT_SERVICE,0x13,0x02,0x01}, {L2_SLOT_SERVICE,0x14,0x02,0x01}, + +// SubFrame 7 + {L2_SLOT_SERVICE,0x01,0x01,0x02}, {L2_SLOT_SERVICE,0x02,0x01,0x02}, + {L2_SLOT_SERVICE,0x03,0x01,0x02}, {L2_SLOT_SERVICE,0x04,0x01,0x02}, + {L2_SLOT_SERVICE,0x05,0x01,0x02}, {L2_SLOT_SERVICE,0x06,0x01,0x02}, + {L2_SLOT_SERVICE,0x07,0x01,0x02}, {L2_SLOT_SERVICE,0x08,0x01,0x02}, + {L2_SLOT_SERVICE,0x09,0x01,0x02}, {L2_SLOT_SERVICE,0x0A,0x01,0x02}, + {L2_SLOT_SERVICE,0x0B,0x01,0x02}, {L2_SLOT_SERVICE,0x0C,0x01,0x02}, + {L2_SLOT_SERVICE,0x0D,0x01,0x02}, {L2_SLOT_SERVICE,0x0E,0x01,0x02}, + {L2_SLOT_SERVICE,0x0F,0x01,0x02}, {L2_SLOT_SERVICE,0x10,0x01,0x02}, + {L2_SLOT_SERVICE,0x11,0x01,0x02}, {L2_SLOT_SERVICE,0x12,0x01,0x02}, + {L2_SLOT_SERVICE,0x13,0x01,0x02}, {L2_SLOT_SERVICE,0x14,0x01,0x02}, + +// SubFrame 8 + {L2_SLOT_SERVICE,0x01,0x02,0x01}, {L2_SLOT_SERVICE,0x02,0x02,0x01}, + {L2_SLOT_SERVICE,0x03,0x02,0x01}, {L2_SLOT_SERVICE,0x04,0x02,0x01}, + {L2_SLOT_SERVICE,0x05,0x02,0x01}, {L2_SLOT_SERVICE,0x06,0x02,0x01}, + {L2_SLOT_SERVICE,0x07,0x02,0x01}, {L2_SLOT_SERVICE,0x08,0x02,0x01}, + {L2_SLOT_SERVICE,0x09,0x02,0x01}, {L2_SLOT_SERVICE,0x0A,0x02,0x01}, + {L2_SLOT_SERVICE,0x0B,0x02,0x01}, {L2_SLOT_SERVICE,0x0C,0x02,0x01}, + {L2_SLOT_SERVICE,0x0D,0x02,0x01}, {L2_SLOT_SERVICE,0x0E,0x02,0x01}, + {L2_SLOT_SERVICE,0x0F,0x02,0x01}, {L2_SLOT_SERVICE,0x10,0x02,0x01}, + {L2_SLOT_SERVICE,0x11,0x02,0x01}, {L2_SLOT_SERVICE,0x12,0x02,0x01}, + {L2_SLOT_SERVICE,0x13,0x02,0x01}, {L2_SLOT_SERVICE,0x14,0x02,0x01}, + +// SubFrame 9 + {L2_SLOT_SERVICE,0x01,0x01,0x02}, {L2_SLOT_SERVICE,0x02,0x01,0x02}, + {L2_SLOT_SERVICE,0x03,0x01,0x02}, {L2_SLOT_SERVICE,0x04,0x01,0x02}, + {L2_SLOT_SERVICE,0x05,0x01,0x02}, {L2_SLOT_SERVICE,0x06,0x01,0x02}, + {L2_SLOT_SERVICE,0x07,0x01,0x02}, {L2_SLOT_SERVICE,0x08,0x01,0x02}, + {L2_SLOT_SERVICE,0x09,0x01,0x02}, {L2_SLOT_SERVICE,0x0A,0x01,0x02}, + {L2_SLOT_SERVICE,0x0B,0x01,0x02}, {L2_SLOT_SERVICE,0x0C,0x01,0x02}, + {L2_SLOT_SERVICE,0x0D,0x01,0x02}, {L2_SLOT_SERVICE,0x0E,0x01,0x02}, + {L2_SLOT_SERVICE,0x0F,0x01,0x02}, {L2_SLOT_SERVICE,0x10,0x01,0x02}, + {L2_SLOT_SERVICE,0x11,0x01,0x02}, {L2_SLOT_SERVICE,0x12,0x01,0x02}, + {L2_SLOT_SERVICE,0x13,0x01,0x02}, {L2_SLOT_SERVICE,0x14,0x01,0x02}, + +// SubFrame 10 + {L2_SLOT_SERVICE,0x01,0x02,0x01}, {L2_SLOT_SERVICE,0x02,0x02,0x01}, + {L2_SLOT_SERVICE,0x03,0x02,0x01}, {L2_SLOT_SERVICE,0x04,0x02,0x01}, + {L2_SLOT_SERVICE,0x05,0x02,0x01}, {L2_SLOT_SERVICE,0x06,0x02,0x01}, + {L2_SLOT_SERVICE,0x07,0x02,0x01}, {L2_SLOT_SERVICE,0x08,0x02,0x01}, + {L2_SLOT_SERVICE,0x09,0x02,0x01}, {L2_SLOT_SERVICE,0x0A,0x02,0x01}, + {L2_SLOT_SERVICE,0x0B,0x02,0x01}, {L2_SLOT_SERVICE,0x0C,0x02,0x01}, + {L2_SLOT_SERVICE,0x0D,0x02,0x01}, {L2_SLOT_SERVICE,0x0E,0x02,0x01}, + {L2_SLOT_SERVICE,0x0F,0x02,0x01}, {L2_SLOT_SERVICE,0x10,0x02,0x01}, + {L2_SLOT_SERVICE,0x11,0x02,0x01}, {L2_SLOT_SERVICE,0x12,0x02,0x01}, + {L2_SLOT_SERVICE,0x13,0x02,0x01}, {L2_SLOT_SERVICE,0x14,0x02,0x01} +}; + + +L2_RTNE_TABLE_ENTRY* normalTable[L2_RTNE_PERIOD] = { + normalSub, normalSub, normalSub, normalSub, normalSub, normalSub, + normalSub, normalSub, normalSub, normalSub, normalSub, normalSub, + normalSub, normalSub, normalSub, normalSub, normalSub, normalSub, + normalSub, normalSub, normalSub, normalSub, normalSub, normalSub, + normalSub, normalSub, normalSub, normalSub, normalSub, normalSub, + normalSub, normalSub, normalSub, normalSub, normalSub, normalSub, + normalSub, normalSub, normalSub, normalSub, normalSub, normalSub, + normalSub, normalSub, normalSub, normalSub, normalSub, normalSub, + normalSub, normalSub, normalSub, normalSub, normalSub, normalSub, + normalSub, normalSub, normalSub, normalSub, normalSub, normalSub +}; +#endif diff --git a/df_datalink/src/networking/link_layer/scan.c b/df_datalink/src/networking/link_layer/scan.c new file mode 100644 index 0000000..abf5ce4 --- /dev/null +++ b/df_datalink/src/networking/link_layer/scan.c @@ -0,0 +1,318 @@ +/*****************************************************************************/ +/** + * Description: Implementations of df linklayer scan net. + * + * Date: 2021-11-10 19:04 + * LastEditTime: 2022-07-16 17:04 + * Revisions: Rev 0.1 + * History: + * [2022-07-16]: New branch for DiJian. + * [2021-11-10]: Initial version. + * + * Copyright(c) 2021 Beijing Institute of Technology. + * Lab of Communication and Networking + * + ******************************************************************************/ + +/***************************** Include Files *********************************/ +#include +#include "error.h" +#include "common.h" +#include "msg_def.h" +#include "link_layer.h" +#include "link_layer_types.h" +#include "../phy_layer/phy_layer.h" +#include "node_list.h" + +/************************** Constant Definitions *****************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/**************************** Type Definitions *******************************/ + +/************************** Variable Definitions *****************************/ + +/************************** Function Prototypes ******************************/ +static int32_t ScanMsg_Packing(L2_INST *l2InstPtr, L2_FRAME_TYPE type); +/*****************************************************************************/ +/** + * @brief Packing Scan message to a bit array. + * + * @param bitarr pointer to bit array buffer. + * msgType message type. + * + * @return EPARAM + * SUCCESS + * + ******************************************************************************/ +static int32_t ScanMsg_Packing(L2_INST *l2InstPtr, L2_FRAME_TYPE type) { + ASSERT(l2InstPtr != NULL); + int32_t Status; + uint8_t *buff; + uint32_t packLen; + switch (type) { + case L2_INFO_FRAME:{ + packLen = RSP_PACK_LEN; + SysMonitor_GetSysinfo(&(l2InstPtr->sysInfo)); + buff = malloc(packLen); + if (buff == NULL) { + DBG_ERROR("Not enough space, failed to pack frame...\n"); + return ENOMEM; + } + buff[L2_MSG_FRAME_NO] = L2_GetNextFrameNo(l2InstPtr); + buff[L2_MSG_SLOT_NO] = L2_GetNextSlotNo(l2InstPtr); + memcpy(buff+L2_MSG_INFO_POSX, &(l2InstPtr->sysInfo.posX), sizeof(float)); + memcpy(buff+L2_MSG_INFO_POSY, &(l2InstPtr->sysInfo.posY), sizeof(float)); + memcpy(buff+L2_MSG_INFO_POSZ, &(l2InstPtr->sysInfo.posZ), sizeof(float)); + memcpy(buff+L2_MSG_INFO_SPEEDX, &(l2InstPtr->sysInfo.vX), sizeof(float)); + memcpy(buff+L2_MSG_INFO_SPEEDY, &(l2InstPtr->sysInfo.vY), sizeof(float)); + memcpy(buff+L2_MSG_INFO_SPEEDZ, &(l2InstPtr->sysInfo.vZ), sizeof(float)); + + Status = L2_CrcAppend(buff, packLen - 2, L2_MSG_CRC, L2_CRC16_1021); + if (Status != SUCCESS) { + DBG_ERROR("Fail to append CRC, error code: %ld.\n", Status); + return Status; + } + if(CircQueuePush(l2InstPtr->txQueue, buff) == false){ + DBG_ERROR("Cannot push packet to queue..\n"); + return EQUEUE; + } + break; + } + default :{ + DBG_ERROR("Unexpected frame type: %d.\n", type); + return EPARAM; + break; + } + } + return SUCCESS; +} + +/*****************************************************************************/ +/** + * @brief Initialize scan FSM. + * + * @param l2InstPtr + * + * @return + * + ******************************************************************************/ +int32_t L2_Scan_Init(L2_INST *l2InstPtr) { + ASSERT(l2InstPtr != NULL); + l2InstPtr->scanFsm.sacanCnt = 0; + l2InstPtr->scanFsm.beamNo = 0; + return SUCCESS; +} + +/*****************************************************************************/ +/** + * @brief Scan net packet handler. + * + * @param msg A pointer to frame data buffer. + * + * @return + * + ******************************************************************************/ +int32_t L2_Scan_PktHandler(L2_INST *l2InstPtr, uint8_t *msg) { + ASSERT(l2InstPtr != NULL); + ASSERT(msg != NULL); + int32_t Status; + switch (l2InstPtr->frame.last) { + case L2_SCAN_FRAME: { + if (l2InstPtr->config.myType == L2_HEAD_NODE) { + DBG_ERROR("Unexpected call from head node, Only None-Head Node can handle L2_SVC_FRAME.\n"); + Status = EUNEXP; + break; + } + Status = AppendNode(l2InstPtr->nodeInfoList, L2_HEAD_NODE_ID, L2_HEAD_NODE); + if (Status != SUCCESS) { + DBG_ERROR("Failed to append node %d, errorCode: %ld.\n", L2_MEMBER_NODE_ID, Status); + } + break; + } + case L2_INFO_FRAME: { + if (l2InstPtr->config.myType != L2_HEAD_NODE) { + DBG_ERROR("Unexpected call from member node, Only Head Node can handle L2_SVC_FRAME.\n"); + Status = EUNEXP; + break; + } + COORD coordTemp; + float tmpVal; + Status = AppendNode(l2InstPtr->nodeInfoList, L2_MEMBER_NODE_ID, L2_MEMBER_NODE); + if (Status != SUCCESS) { + DBG_ERROR("Failed to append node %d, errorCode: %ld.\n", L2_MEMBER_NODE_ID, Status); + break; + } + memcpy(&tmpVal, msg+L2_MSG_INFO_POSX, sizeof(float)); + coordTemp.x = tmpVal; + memcpy(&tmpVal, msg+L2_MSG_INFO_POSY, sizeof(float)); + coordTemp.y = tmpVal; + memcpy(&tmpVal, msg+L2_MSG_INFO_POSZ, sizeof(float)); + coordTemp.z = tmpVal; + Status = UpdateNodePos(l2InstPtr->nodeInfoList, L2_MEMBER_NODE_ID, &coordTemp); + if (Status != SUCCESS) { + DBG_ERROR("Failed to update node %d position, errorCode: %ld.\n", L2_MEMBER_NODE_ID, Status); + } + memcpy(&tmpVal, msg+L2_MSG_INFO_SPEEDX, sizeof(float)); + coordTemp.x = tmpVal; + memcpy(&tmpVal, msg+L2_MSG_INFO_SPEEDY, sizeof(float)); + coordTemp.y = tmpVal; + memcpy(&tmpVal, msg+L2_MSG_INFO_SPEEDZ, sizeof(float)); + coordTemp.z = tmpVal; + Status = UpdateNodeSpeed(l2InstPtr->nodeInfoList, L2_MEMBER_NODE_ID, &coordTemp); + if (Status != SUCCESS) { + DBG_ERROR("Failed to update node %d speed, errorCode: %ld.\n", L2_MEMBER_NODE_ID, Status); + } + // Update Time deviation + int64_t devi, deviTrunc; + Status = L2_TimeSync_GetDeviatoion(l2InstPtr, &devi); + if (Status != SUCCESS) { + DBG_ERROR("Failed to compute slot deviation.\n"); + UpdateNodeTimeDeviation(l2InstPtr->nodeInfoList, L2_MEMBER_NODE_ID, 0); + } + else { + if(devi > INT32_MAX || devi < INT32_MIN) { + DBG_ERROR("Illegal deviation value: %lld.\n", devi); + deviTrunc = 0; + } + else if(devi > L2_MSG_SVC_TMSYNC_MAX || devi < L2_MSG_SVC_TMSYNC_MIN) { + DBG_WARNING("Deviation value: %lld is out of adjustable range.\n", devi); + deviTrunc = (int32_t)devi; + } + else { + deviTrunc = (int32_t)devi; + } + UpdateNodeTimeDeviation(l2InstPtr->nodeInfoList, L2_MEMBER_NODE_ID, (uint32_t)deviTrunc); + } + break; + } + default: + DBG_ERROR("Unsupported frame type: %ld.\n", l2InstPtr->frame.last); + Status = EUNEXP; + break; + } + + // Net setup finished. + if(L2_GetMainState(l2InstPtr) == INIT_STATE && Status == SUCCESS){ + L2_EVENT l2Event; + L2_RTNE_CONFIG newRtneConfig; + + // Assert Net-Setup Done. + l2Event.event = L2_EV_NET_SETUP_DONE; + l2Event.msg = NULL; + AssertL2Event(l2InstPtr, &l2Event); + + // Assert Routine Table Update... + newRtneConfig.rtneTable = normalTable; + newRtneConfig.rtnePrd = ARRAY_SIZE(normalTable)*L2_SLOTS_PER_FRAME; + newRtneConfig.rtneStep = 0; + l2Event.event = L2_ROUTINE_UPDATE; + l2Event.msg = &newRtneConfig; + AssertL2Event(l2InstPtr, &l2Event); + } + return Status; +} + +/*****************************************************************************/ +/** + * @brief Execute a member node scan net procedure. + * + * @param l2InstPtr A pointer to scan net fsm. + * + * @return used slot (5ms slot). + * + ******************************************************************************/ +int32_t L2_Scan_Proc(L2_INST *l2InstPtr) { + int32_t Status; + /* l2InstPtr->nextState == NORMAL_STATE indicates network set up procedure was finished. + * Skip 5ms for nodes for node configuration update. + */ + DBG_INFO("-------- Scan Process --------\n"); + if (l2InstPtr->nextState == NORMAL_STATE) { + DBG_INFO("NETSET DONE, halt 20ms before normal routine.\n"); + if(l2InstPtr->config.myType != L2_HEAD_NODE) { + Phy_SetBeamAngle(l2InstPtr->config.phyInstRef, 0.0, 0.0); + Phy_SetBeamWidth(l2InstPtr->config.phyInstRef, PHY_ANT_BEAM_120); + Phy_SetMode(l2InstPtr->config.phyInstRef, PHY_MODE_SCHEDULE); + L2_SetupNextSlot(l2InstPtr, L2_TOR_SUSPEND, L2_SCAN_FRAME); + } + else { + DBG_ERROR("Illegal call from Head Node.\n"); + } + return NUM_SLOTS_SKIP; + } + + /* Head node implement a periodical scan pattern + * | Tx 20ms | Rx 100ms | Tx 20ms | Rx 100ms ... ... + * Send pilot signal in Tx slots with narrow beam width. + * Wait for response in Rx slots with the same beam width and beam number. + * Increase beam number after a Tx-Rx procedure pair, reset beam number when + * it reaches the boundary. + */ + if (l2InstPtr->config.myType == L2_HEAD_NODE) { + // Apply a scan procedure + if (l2InstPtr->scanFsm.sacanCnt % 2 == 0){ + // Antenna configure + Phy_SetBeamWidth(l2InstPtr->config.phyInstRef, PHY_ANT_BEAM_8); + Phy_SetBeamNo(l2InstPtr->config.phyInstRef, l2InstPtr->scanFsm.beamNo); + Phy_SetMode(l2InstPtr->config.phyInstRef, PHY_MODE_SCHEDULE); + L2_SetupNextSlot(l2InstPtr, L2_TOR_TX, L2_SCAN_FRAME); + } + else { + // Antenna configure + Phy_SetBeamWidth(l2InstPtr->config.phyInstRef, PHY_ANT_BEAM_8); + Phy_SetBeamNo(l2InstPtr->config.phyInstRef, l2InstPtr->scanFsm.beamNo); + Phy_SetMode(l2InstPtr->config.phyInstRef, PHY_MODE_SCHEDULE); + L2_SetupNextSlot(l2InstPtr, L2_TOR_RX, L2_INFO_FRAME); + // Update Scan beam number + l2InstPtr->scanFsm.beamNo = (l2InstPtr->scanFsm.beamNo + 1) % L1_NUM_ANT_NRRW_PATTERN; + } + } + /* Member node listening the head node pilot signal with wide beam width. + * Once is received a pilot signal, physical layer will perform a response + * procedure automatically, witch should contains the basic node information + * (position, speed, etc.). + * So that, a extra datagram with the up-to-date node information is attached + * to the listening configuration. + */ + else { + uint8_t *sendData; + // Pack node information. + Status = ScanMsg_Packing(l2InstPtr, L2_INFO_FRAME); + if (Status != SUCCESS) { + DBG_INFO("Failed to pack response.\n"); + } + if (CircQueuePop(l2InstPtr->txQueue, (void **)(&sendData)) == true) { + memcpy(l2InstPtr->sendPktData, sendData, RSP_PACK_LEN); + free(sendData); + } + else { + DBG_INFO("Failed to pop tx Queue.\n"); + } + // Antenna configure + Phy_SetBeamAngle(l2InstPtr->config.phyInstRef, 0.0, 0.0); + Phy_SetBeamWidth(l2InstPtr->config.phyInstRef, PHY_ANT_BEAM_120); + Phy_SetMode(l2InstPtr->config.phyInstRef, PHY_MODE_LISTEN); + L2_SetupNextSlot(l2InstPtr, L2_TOR_RX, L2_SCAN_FRAME); + } + + // Increase scan counter (for debug purpose). + l2InstPtr->scanFsm.sacanCnt ++; + return NUM_SLOTS_SKIP; +} + +/*****************************************************************************/ + +/** + * @brief Execute a scan net Routine procedure. + * + * @param schedEntry Routine configuration + * + * @return used slot (5ms slot). + * + ******************************************************************************/ +int32_t L2_Scan_Routine(L2_INST *l2InstPtr, L2_RTNE_TABLE_ENTRY *schedEntry) { + DBG_INFO("-------- Scan Routine --------\n"); + ASSERT(false); // Not support. + return 0; +} diff --git a/df_datalink/src/networking/link_layer/service.c b/df_datalink/src/networking/link_layer/service.c new file mode 100644 index 0000000..66f98af --- /dev/null +++ b/df_datalink/src/networking/link_layer/service.c @@ -0,0 +1,464 @@ +/*****************************************************************************/ +/** + * Description: Implementations for df datalink service net. + * Date: 2021-11-16 00:08 + * LastEditTime: 2022-07-16 17:04 + * Revisions: Rev 0.1 + * History: + * [2022-07-16]: New branch for DiJian. + * [2021-11-16]: Initial version. + * + * Copyright(c) 2021 Beijing Institute of Technology. + * Lab of Communication and Networking + * + ******************************************************************************/ + +/***************************** Include Files *********************************/ +#include +#include +#include "error.h" +#include "common.h" +#include "circ_queue.h" +#include "msg_def.h" +#include "link_layer.h" +#include "link_layer_types.h" +#include "../config/app_config.h" + +/************************** Constant Definitions *****************************/ +#define NUM_SERVICE_SLOTS 20 +#define NUM_RESPONSE_SLOTS 20 +#define NUM_NONE_SERVICE_SLOTS 0 +#define NUM_SERVICE_PRD_SLOTS 60 +/***************** Macros (Inline Functions) Definitions *********************/ + +/**************************** Type Definitions *******************************/ + +/************************** Function Prototypes ******************************/ +static int32_t Service_Packing(L2_INST *l2InstPtr, L2_FRAME_TYPE type); +/************************** Variable Definitions *****************************/ + +#ifdef DATALINK_ENABLE_BERTEST +static uint8_t berTestData[SVC_PACK_LEN] = { + 0x27, 0x4E, 0xFB, 0x39, 0x11, 0xE7, 0x12, 0xDA, + 0xDF, 0xD2, 0x27, 0x8F, 0xC9, 0x42, 0xCD, 0x0C, + 0x76, 0x1C, 0x81, 0x87, 0x69, 0xC9, 0x60, 0xFD, + 0xC4, 0x27, 0xA5, 0x09, 0xE5, 0x71 +}; +#endif + +/*****************************************************************************/ +/** + * @brief Packing UDU Header to a bit array. + * + * @param bitarr point32_ter to bit array buffer. + * dst Destination node address. + * dataLen Length of UDU data. + * + * @return EPARAM + * SUCCESS + * + ******************************************************************************/ +static int32_t Service_Packing(L2_INST *l2InstPtr, L2_FRAME_TYPE type) { +#ifndef DATALINK_ENABLE_BERTEST + ASSERT(l2InstPtr != NULL); + int32_t Status; + uint8_t *buff; + uint32_t packLen; + switch (type) { + case L2_SVC_FRAME:{ + const NODE_ENTRY *nodeEntry; + int32_t timeDevi; + packLen = SVC_PACK_LEN; + + buff = malloc(packLen); + if (buff == NULL) { + DBG_ERROR("Not enough space, failed to pack frame...\n"); + return ENOMEM; + } + buff[L2_MSG_FRAME_NO] = L2_GetNextFrameNo(l2InstPtr); + buff[L2_MSG_SLOT_NO] = L2_GetNextSlotNo(l2InstPtr); + + // TODO: Check Pack TimeSync info, and better approch?. + nodeEntry = GetNode(l2InstPtr->nodeInfoList, L2_MEMBER_NODE_ID); + if(nodeEntry != NULL) { + // check if deviation info outdated. + if(nodeEntry->ttlCnt <= NUM_SERVICE_PRD_SLOTS) { + // Member node should adjust in the opposite way. + timeDevi = -nodeEntry->timeDevi; + } + else { + DBG_WARNING("Time deviation is outdated, omitted it.\n"); + } + } + else { + DBG_ERROR("Fail to get time deviation...\n"); + timeDevi = 0; + } + if(timeDevi > L2_MSG_SVC_TMSYNC_MAX || timeDevi < L2_MSG_SVC_TMSYNC_MIN) { + do { + timeDevi /= 2; + } while(timeDevi > L2_MSG_SVC_TMSYNC_MAX || timeDevi < L2_MSG_SVC_TMSYNC_MIN); + DBG_WARNING("Deviation is out of adjustable range, truncate it to %d.\n", timeDevi); + } + memcpy(buff+L2_MSG_SVC_TMSYNC, &timeDevi, L2_MSG_SVC_TMSYNC_LEN); + + // Pack Seq ID + buff[L2_MSG_SVC_SEQ_ID] = l2InstPtr->serviceFsm.txSeqNum; + + // Pack payload + memcpy(buff+L2_MSG_SVC_PAYLOAD, + l2InstPtr->serviceFsm.txLog + L2_MSG_SVC_PAYLOAD_LEN*l2InstPtr->serviceFsm.txSeqNum, + L2_MSG_SVC_PAYLOAD_LEN); + if (l2InstPtr->config.myType == L2_HEAD_NODE) { + // if last packet reset counting + l2InstPtr->serviceFsm.txSeqNum = (l2InstPtr->serviceFsm.txSeqNum + >= (PAYLOAD_FLJ-1)/L2_MSG_SVC_PAYLOAD+1) + ? 0 : l2InstPtr->serviceFsm.txSeqNum + 1; + } + else{ + // if last packet reset counting + l2InstPtr->serviceFsm.txSeqNum = (l2InstPtr->serviceFsm.txSeqNum + >= (PAYLOAD_LJ-1)/L2_MSG_SVC_PAYLOAD+1) + ? 0 : l2InstPtr->serviceFsm.txSeqNum + 1; + } + + + Status = L2_CrcAppend(buff, packLen - 2, L2_MSG_CRC, L2_CRC16_1021); + if (Status != SUCCESS) { + DBG_ERROR("Fail to append CRC...\n"); + return Status; + } + + if(CircQueuePush(l2InstPtr->txQueue, buff) == false){ + DBG_ERROR("Cannot push packet to queue..\n"); + return EQUEUE; + } + break; + } + case L2_INFO_FRAME:{ + packLen = RSP_PACK_LEN; + SysMonitor_GetSysinfo(&(l2InstPtr->sysInfo)); + buff = malloc(packLen); + if (buff == NULL) { + DBG_ERROR("Not enough space, failed to pack frame...\n"); + return ENOMEM; + } + buff[L2_MSG_FRAME_NO] = L2_GetNextFrameNo(l2InstPtr); + buff[L2_MSG_SLOT_NO] = L2_GetNextSlotNo(l2InstPtr); + memcpy(buff+L2_MSG_INFO_POSX, &(l2InstPtr->sysInfo.posX), sizeof(float)); + memcpy(buff+L2_MSG_INFO_POSY, &(l2InstPtr->sysInfo.posY), sizeof(float)); + memcpy(buff+L2_MSG_INFO_POSZ, &(l2InstPtr->sysInfo.posZ), sizeof(float)); + memcpy(buff+L2_MSG_INFO_SPEEDX, &(l2InstPtr->sysInfo.vX), sizeof(float)); + memcpy(buff+L2_MSG_INFO_SPEEDY, &(l2InstPtr->sysInfo.vY), sizeof(float)); + memcpy(buff+L2_MSG_INFO_SPEEDZ, &(l2InstPtr->sysInfo.vZ), sizeof(float)); + + Status = L2_CrcAppend(buff, packLen - 2, L2_MSG_CRC, L2_CRC16_1021); + if (Status != SUCCESS) { + DBG_ERROR("Fail to append CRC...\n"); + return Status; + } + if(CircQueuePush(l2InstPtr->txQueue, buff) == false){ + DBG_ERROR("Cannot push packet to queue..\n"); + return EQUEUE; + } + break; + } + default :{ + DBG_ERROR("Unexpected frame type: %d.\n", type); + return EPARAM; + break; + } + } + return SUCCESS; +#else + DBG_ERROR("Unexpected call of Service_Packing in BER test mode.\n"); + return EUNEXP; +#endif +} + + +/*****************************************************************************/ +/** + * @brief Initialize scan FSM. + * + * @param l2InstPtr + * + * @return + * + ******************************************************************************/ +int32_t L2_Service_Init(L2_INST *l2InstPtr) { + ASSERT(l2InstPtr != NULL); + l2InstPtr->serviceFsm.txSeqNum = 0; + l2InstPtr->serviceFsm.rxSeqNum = 0; + memset((&l2InstPtr->serviceFsm.rxLog), 0x00, sizeof(PAYLOAD)); + memset((&l2InstPtr->serviceFsm.txLog), 0x00, sizeof(PAYLOAD)); + l2InstPtr->serviceFsm.pktRecv = 0; + l2InstPtr->serviceFsm.pktRecved = 0; +#ifdef DATALINK_ENABLE_BERTEST + l2InstPtr->serviceFsm.bitTotal = 0; + l2InstPtr->serviceFsm.bitError = 0; +#endif + return SUCCESS; +} + +/*****************************************************************************/ +/** + * @brief Handle service received packet. Send data up to MPC + * + * @param msg A point32_ter the the message frame. + * + * @return SUCCESS message has been successfully handled. + * other error occurred. + * + ******************************************************************************/ +int32_t L2_Service_PktHandler(L2_INST *l2InstPtr, uint8_t *msg) { + ASSERT(l2InstPtr != NULL); + ASSERT(msg != NULL); + int32_t Status; + switch (l2InstPtr->frame.last) { + case L2_SVC_FRAME: { + if (l2InstPtr->config.myType == L2_HEAD_NODE) { + DBG_ERROR("Unexpected call, Only None-Head Node can handle L2_SVC_FRAME.\n"); + Status = EUNEXP; + break; + } + + // Implement a auto time sync. + uint32_t seqNum; + L2_EVENT l2Event; + l2Event.event = L2_EV_TIME_SYNC; + seqNum = msg[L2_MSG_SVC_SEQ_ID]; + +#ifdef DATALINK_ENABLE_AUTOTIMESYNC + l2Event.msg = NULL; + AssertL2Event(l2InstPtr, &l2Event); +#else + int64_t timeAdj; + l2Event.msg = &timeAdj; + // Get Time Deviation + timeAdj = 0; + memcpy(&timeAdj, msg + L2_MSG_SVC_TMSYNC, L2_MSG_SVC_TMSYNC_LEN); + timeAdj |= (timeAdj & 0x0000000000800000) ? 0xFFFFFFFFFF000000 : 0x0000000000000000; + // FIXME: better approach? + // Implement a time sync procedure, first time received a time deviation in a service period. + if (seqNum % NUM_SERVICE_PRD_SLOTS == 0 || l2InstPtr->serviceFsm.seqNum != seqNum) { + AssertL2Event(l2InstPtr, &l2Event); + } +#endif +#ifndef DATALINK_ENABLE_BERTEST + memcpy(l2InstPtr->serviceFsm.rxLog + L2_MSG_SVC_PAYLOAD_LEN*seqNum, msg + L2_MSG_SVC_PAYLOAD, L2_MSG_SVC_PAYLOAD_LEN); + if (l2InstPtr->config.myType == L2_HEAD_NODE) { + // if last packet reset counting + if(seqNum >= (PAYLOAD_FLJ-1)/L2_MSG_SVC_PAYLOAD+1) { + if(seqNum == l2InstPtr->serviceFsm.rxSeqNum) { + SysMonitor_UpdateRecvPayloadLJRaw(l2InstPtr->serviceFsm.rxLog); + } + l2InstPtr->serviceFsm.rxSeqNum = 0; + } + else { + if(l2InstPtr->serviceFsm.rxSeqNum == seqNum){ + l2InstPtr->serviceFsm.rxSeqNum++; + } + } + } + else{ + // if last packet reset counting + if(seqNum >= (PAYLOAD_LJ-1)/L2_MSG_SVC_PAYLOAD+1) { + if(seqNum == l2InstPtr->serviceFsm.rxSeqNum) { + SysMonitor_UpdateRecvPayloadFLJRaw(l2InstPtr->serviceFsm.rxLog); + } + l2InstPtr->serviceFsm.rxSeqNum = 0; + } + else { + if(l2InstPtr->serviceFsm.rxSeqNum == seqNum){ + l2InstPtr->serviceFsm.rxSeqNum++; + } + } + } + +#else + for(int i = 0; i < SVC_PACK_LEN; i++) { + l2InstPtr->serviceFsm.bitError += count_ones(msg[i]^berTestData[i]); + } + l2InstPtr->serviceFsm.bitTotal += SVC_PACK_LEN*8; +#endif + l2InstPtr->serviceFsm.pktRecved++; + // Reset Node TTL + Status = RstNodeTTL(l2InstPtr->nodeInfoList, L2_HEAD_NODE_ID); + if (Status != SUCCESS) { + DBG_ERROR("Failed to reset node %d TTL, errorCode: %ld.\n", L2_MEMBER_NODE_ID, Status); + } + break; + } + case L2_INFO_FRAME: { + if (l2InstPtr->config.myType != L2_HEAD_NODE) { + DBG_ERROR("Unexpected call, Only Head Node can handle L2_SVC_FRAME.\n"); + Status = EUNEXP; + break; + } +#ifndef DATALINK_ENABLE_BERTEST + COORD coordTemp; + float tmpVal; + memcpy(&tmpVal, msg+L2_MSG_INFO_POSX, sizeof(float)); + coordTemp.x = tmpVal; + memcpy(&tmpVal, msg+L2_MSG_INFO_POSY, sizeof(float)); + coordTemp.y = tmpVal; + memcpy(&tmpVal, msg+L2_MSG_INFO_POSZ, sizeof(float)); + coordTemp.z = tmpVal; + Status = UpdateNodePos(l2InstPtr->nodeInfoList, L2_MEMBER_NODE_ID, &coordTemp); + if (Status != SUCCESS) { + DBG_ERROR("Failed to update node %d position, errorCode: %ld.\n", L2_MEMBER_NODE_ID, Status); + } + memcpy(&tmpVal, msg+L2_MSG_INFO_SPEEDX, sizeof(float)); + coordTemp.x = tmpVal; + memcpy(&tmpVal, msg+L2_MSG_INFO_SPEEDY, sizeof(float)); + coordTemp.y = tmpVal; + memcpy(&tmpVal, msg+L2_MSG_INFO_SPEEDZ, sizeof(float)); + coordTemp.z = tmpVal; + Status = UpdateNodeSpeed(l2InstPtr->nodeInfoList, L2_MEMBER_NODE_ID, &coordTemp); + if (Status != SUCCESS) { + DBG_ERROR("Failed to update node %d speed, errorCode: %ld.\n", L2_MEMBER_NODE_ID, Status); + } + + // TODO: Check + // Update Time deviation + int64_t devi, deviTrunc; + Status = L2_TimeSync_GetDeviatoion(l2InstPtr, &devi); + if (Status != SUCCESS) { + DBG_ERROR("Failed to compute slot deviation.\n"); + deviTrunc = 0; + } + else { + if(devi > INT32_MAX || devi < INT32_MIN) { + DBG_WARNING("Illegal deviation value: %lld, omit it.\n", devi); + deviTrunc = 0; + } + else if(devi > L2_MSG_SVC_TMSYNC_MAX || devi < L2_MSG_SVC_TMSYNC_MIN) { + DBG_WARNING("Deviation value: %lld is out of adjustable range.\n", devi); + deviTrunc = (int32_t)devi; + } + else { + deviTrunc = (int32_t)devi; + } + UpdateNodeTimeDeviation(l2InstPtr->nodeInfoList, L2_MEMBER_NODE_ID, (uint32_t)deviTrunc); + } + Status = UpdateNodeTimeDeviation(l2InstPtr->nodeInfoList, L2_MEMBER_NODE_ID, (uint32_t)deviTrunc); + if (Status != SUCCESS) { + DBG_ERROR("Failed to update node %d time deviation, errorCode: %ld.\n", L2_MEMBER_NODE_ID, Status); + } +#else + for(int i = 0; i < SVC_PACK_LEN; i++) { + l2InstPtr->serviceFsm.bitError += count_ones(msg[i]^berTestData[i]); + } + l2InstPtr->serviceFsm.bitTotal += SVC_PACK_LEN*8; +#endif + l2InstPtr->serviceFsm.pktRecved++; + // Reset Node TTL + Status = RstNodeTTL(l2InstPtr->nodeInfoList, L2_MEMBER_NODE_ID); + if (Status != SUCCESS) { + DBG_ERROR("Failed to reset node %d ttl, errorCode: %ld.\n", L2_MEMBER_NODE_ID, Status); + } + break; + } + default: + DBG_ERROR("Unsupported frame type: %ld.\n", l2InstPtr->frame.last); + break; + } + return Status; +} + +/*****************************************************************************/ +/** + * @brief Service FSM Routine. + * + * @param l2InstPtr + * @param schedEntry + * + * @return Slot has been used. + * + ******************************************************************************/ +int32_t L2_Service_Routine(L2_INST *l2InstPtr, L2_RTNE_TABLE_ENTRY *schedEntry) { + ASSERT(l2InstPtr != NULL); + DBG_INFO("-------- ServiceNet Routine --------\n"); + uint8_t *sendData; + int32_t usedSlots; + L2_TOR_TYPE torState; + if(schedEntry->src == l2InstPtr->config.myId){ + torState = L2_TOR_TX; + } + else if(schedEntry->dst == l2InstPtr->config.myId){ + torState = L2_TOR_RX; + l2InstPtr->serviceFsm.pktRecv++; + } + else{ + torState = L2_TOR_SUSPEND; + } + + switch(schedEntry->slotType){ + case L2_SLOT_SERVICE: + if(torState == L2_TOR_TX){ +#ifndef DATALINK_ENABLE_BERTEST + if (l2InstPtr->serviceFsm.txSeqNum == 0) { + if(l2InstPtr->config.myType == L2_HEAD_NODE){ + SysMonitor_GetSendPayloadFLJRaw(l2InstPtr->serviceFsm.txLog); + } + else { + SysMonitor_GetSendPayloadLJRaw(l2InstPtr->serviceFsm.txLog); + } + } + // Packing service data + Service_Packing(l2InstPtr, L2_SVC_FRAME); + if (CircQueuePop(l2InstPtr->txQueue, (void **)(&sendData)) == true) { + memcpy(l2InstPtr->sendPktData, sendData, SVC_PACK_LEN); + free(sendData); + } + else { + DBG_ERROR("Failed to pop tx queue.\n"); + } +#else + memcpy(l2InstPtr->config.phyInstRef->sendFrameBuff, berTestData, SVC_PACK_LEN); +#endif + } + // FIXME: Steer antenna to point to destination. + Phy_SetBeamAngle(l2InstPtr->config.phyInstRef, 0.0, 0.0); + Phy_SetBeamWidth(l2InstPtr->config.phyInstRef, PHY_ANT_BEAM_8); + Phy_SetMode(l2InstPtr->config.phyInstRef, PHY_MODE_SCHEDULE); + L2_SetupNextSlot(l2InstPtr, torState, L2_SVC_FRAME); + usedSlots = NUM_SERVICE_SLOTS; + break; +#ifndef DATALINK_ENABLE_BERTEST + case L2_SLOT_ADVERTISE: + if(torState == L2_TOR_TX){ + // Packing response data. + Service_Packing(l2InstPtr, L2_INFO_FRAME); + if (CircQueuePop(l2InstPtr->txQueue, (void **)(&sendData)) == true) { + memcpy(l2InstPtr->sendPktData, sendData, RSP_PACK_LEN); + free(sendData); + } + else { + DBG_ERROR("Failed to pop tx queue.\n"); + } + } + // FIXME: Steer antenna to point to destination. + Phy_SetBeamAngle(l2InstPtr->config.phyInstRef, 0.0, 0.0); + Phy_SetBeamWidth(l2InstPtr->config.phyInstRef, PHY_ANT_BEAM_120); + Phy_SetMode(l2InstPtr->config.phyInstRef, PHY_MODE_SCHEDULE); + L2_SetupNextSlot(l2InstPtr, torState, L2_INFO_FRAME); + usedSlots = NUM_RESPONSE_SLOTS; + break; +#endif + default: + DBG_ERROR("UNKNOWN slot type [%d].\n", schedEntry->slotType); + return NUM_SLOTS_NONE; + } +#ifdef DATALINK_ENABLE_BERTEST + uint32_t pktLoss; + double errorRate, lossRate; + pktLoss = l2InstPtr->serviceFsm.pktRecv - l2InstPtr->serviceFsm.pktRecved; + lossRate = (l2InstPtr->serviceFsm.pktRecv == 0) ? 0 : (double)pktLoss / (double)l2InstPtr->serviceFsm.pktRecv; + errorRate = (l2InstPtr->serviceFsm.bitTotal == 0) ? 0 : (double)l2InstPtr->serviceFsm.bitError / (double)l2InstPtr->serviceFsm.bitTotal; + DBG_PRINT("Packet Loss Rate -- Total: %lu, Loss: %lu.\n", l2InstPtr->serviceFsm.pktRecv, pktLoss); + DBG_PRINT("Bit Error Rate -- Total:%lu, Error:%lu.\n", l2InstPtr->serviceFsm.bitTotal, l2InstPtr->serviceFsm.bitError); +#endif + return usedSlots; +} diff --git a/df_datalink/src/networking/link_layer/time_sync.c b/df_datalink/src/networking/link_layer/time_sync.c new file mode 100644 index 0000000..2f75e65 --- /dev/null +++ b/df_datalink/src/networking/link_layer/time_sync.c @@ -0,0 +1,123 @@ +/*****************************************************************************/ +/** + * Description: Time sync implementation file. + * + * Date: 2021-12-04 16:32 + * LastEditors: FanHao + * LastEditTime: 2022-07-10 20:43 + * Revisions: Rev 0.0 + * History: + * [2022-07-10]: New branch for Dijian. + * [2021-12-04]: Initial version. + * + * Copyright(c) 2021 Beijing Institute of Technology. + * Lab of Communication and Networking + * + ******************************************************************************/ + +/***************************** Include Files *********************************/ +#include + +#include "error.h" +#include "common.h" +#include "link_layer.h" +#include "../phy_layer/phy_reg.h" +/************************** Constant Definitions *****************************/ +#define MAX_FREQ_EST_NUM 128 // 32bit word +#define SVC_FREQ_EST_NUM 512 // byte +#define MGMT_FREQ_EST_NUM 512 // byte +#define BISAR_FREQ_EST_NUM 480 // byte + +#define SYS_CLK_FREQ 192000000.0 // Hz +#define SIG_CLK_FREQ 245760000.0 // Hz +#define CXR_FREQ 3800000000.0 // Hz + +#define NORMAL_SLOT_CLK_NUM 960000.0 // 9600000= 5e-3*192e6 +#define COUNTER_10NS_MAX 500000 // how many 10ns in a 5ms + +#define LIGHT_SPPED_AIR 299702547.0 // m/s +#define LIGHT_SPPED_VAC 299792458.0 // m/s + +//#define PHY_SYNCT2FEND_200K 904052UL +//#define PHY_SYNCT2FEND_200K 924232UL + +#define PHY_SYNCT2FEND_2K_20MS 276336UL // 1.919ms +#define PHY_SYNCT2FEND_2K_100MS 11796336UL // 81.919ms + +#define PHY_LOCAL_CNT_MAX 0x0000FFFFFFFFFFFFULL +/***************** Macros (Inline Functions) Definitions *********************/ +/**************************** Type Definitions *******************************/ +/************************** Variable Definitions *****************************/ +/************************** Function Prototypes ******************************/ + +/*****************************************************************************/ +/** + * @brief Apply local time adjustment by addition. + * + * @param l2InstPtr. + * @param adjustment + * + * @return + * + ******************************************************************************/ +inline int32_t L2_TimeSync_LocalTimerAdd(L2_INST *l2InstPtr, int64_t adjustment) { + // read nextSendTime from physical layer + Phy_SetTimeWord(l2InstPtr->config.phyInstRef, adjustment, PHY_TIME_WORD_LOCAL_ADJ); + PhyWrite(l2InstPtr->config.phyInstRef, TM_ADJ_MODE, TM_ADJ_MODE_ADD); + return SUCCESS; +} + +/*****************************************************************************/ +/** + * @brief Align slot, base on physical layer information. + * + * @param l2InstPtr. + * + * @return + * + ******************************************************************************/ +int32_t L2_TimeSync_SlotAlign(L2_INST *l2InstPtr) { + int32_t Status; + int64_t slotAdj; + Status = L2_TimeSync_GetDeviatoion(l2InstPtr, &slotAdj); + if (Status != SUCCESS) { + DBG_ERROR("Failed to compute slot deviation.\n"); + return Status; + } + return L2_TimeSync_LocalTimerAdd(l2InstPtr, slotAdj); +} + +/*****************************************************************************/ +/** + * @brief Compute slot deviation of received frame. + * + * @param l2InstPtr. + * @param devi + * + * @return + * + ******************************************************************************/ +int32_t L2_TimeSync_GetDeviatoion(L2_INST *l2InstPtr, int64_t *devi) { + // read nextSendTime from physical layer + int64_t currentTarget, lastFrameSync, slotMeasure; + currentTarget = PhyRead(l2InstPtr->config.phyInstRef, TM_TARGET_L); + currentTarget |= ((int64_t)PhyRead(l2InstPtr->config.phyInstRef, TM_TARGET_H)) << 32; + lastFrameSync = PhyRead(l2InstPtr->config.phyInstRef, FSTIME_L); + lastFrameSync |= ((int64_t)PhyRead(l2InstPtr->config.phyInstRef, FSTIME_H)) << 32; + slotMeasure = (currentTarget > lastFrameSync) ? (currentTarget - lastFrameSync) + : (currentTarget - lastFrameSync + PHY_LOCAL_CNT_MAX); + switch (Phy_GetLastDetectedFrameType(l2InstPtr->config.phyInstRef)) { + case L1_2KBPS_20MS_FRAME : + *devi = ((int64_t)PHY_SYNCT2FEND_2K_20MS) - slotMeasure; + break; + case L1_2KBPS_100MS_FRAME: + *devi = ((int64_t)PHY_SYNCT2FEND_2K_100MS) - slotMeasure; + break; + default: + DBG_ERROR("Unsupported frame type: %d.\n", Phy_GetLastDetectedFrameType(l2InstPtr->config.phyInstRef)); + return EIGNORE; + } + return SUCCESS; +} + + diff --git a/df_datalink/src/networking/phy_layer/phy_antenna.c b/df_datalink/src/networking/phy_layer/phy_antenna.c new file mode 100644 index 0000000..338c242 --- /dev/null +++ b/df_datalink/src/networking/phy_layer/phy_antenna.c @@ -0,0 +1,369 @@ +/*****************************************************************************/ +/** + * Description: Antenna configuration functions. + * + * Author: Fan Hao + * Date: 2022-06-18 16:37 + * LastEditors: Fan Hao + * LastEditTime: 2022-06-18 17:15 + * Revisions: Rev 0.0 + * History: + * [2022-06-18]: Initial version. + * + * Copyright(c) 2022 Beijing Institute of Technology. + * Lab of Communication and Networking + * + ******************************************************************************/ +#include +#include +#include +#include "error.h" +#include "../config//app_config.h" +#include "phy_layer.h" + +#define ANT_PI 3.14159265358979323846 + +#define ANT_COINFO_HEAD 0xAA +#define ANT_COINFO_TAIL 0xCC + +#define CTRL_WORD_DEFAULT 0x00 + +#define ANT_MODE_BEAM_MASK 0xF0 +#define ANT_MODE_NARROR_BEAM 0x00 // 8 +#define ANT_MODE_WIDE_BEAM_1 0x10 // 25 +#define ANT_MODE_WIDE_BEAM_2 0x20 // 60 +#define ANT_MODE_WIDE_BEAM_3 0x30 // 120 + +#define ANT_MODE_HIGH_POWER 0x00 +#define ANT_MODE_LOWAPOWER 0x04 +#define ANT_MODE_STANDBY 0x0F +#define ATN_MODE_DEFAULT (ANT_MODE_WIDE_BEAM_1 | ANT_MODE_LOWAPOWER) + +#define DEFAULT_CENTRTAL_FREQ 0x06D7 // 26.25GHz + +#define RXTXMODE_DEFAULT 0x00 + +#define CALIBRMODE_NORMAL 0x00 +#define CALIBRMODE_SINGLE_TR_CAL 0x01 + +#define RF_CTRL_DEFAULT 0x00 + +// Pair by regex +// Regex: (([0-9]+, ){8}) +uint16_t hopRxPattern_Config[L1_FRAME_MAX_HOPS] = { + 0 +}; +uint16_t hopTxPattern_Config[L1_FRAME_MAX_HOPS] = { + 0 +}; + +uint16_t hopTxPattern_2KBPS_20MS[L1_FRAME_2KBPS_20MS_HOPS] = { + 1500 +}; +uint16_t hopRxPattern_2KBPS_20MS[L1_FRAME_2KBPS_20MS_HOPS] = { + 1500 +}; + +//uint16_t hopTxPattern_2KBPS_100MS[L1_FRAME_2KBPS_100MS_HOPS] = { +// 0, 44, 88, 131, 175, 219, 263, 306, +// 350, 394, 438, 481, 525, 569, 613, 656, +// 700, 744, 788, 831, 875, 919, 963, 1006, +// 1050, 1094, 1138, 1181, 1225, 1269, 1313, 1356, +// 1400, 1444, 1488, 1531, 1575, 1619, 1663, 1706, +// 1750, 1794, 1838, 1881, 1925, 1969, 2013, 2056, +// 2100, 2144, 2188, 2231, 2275, 2319, 2363, 2406, +// 2450, 2494, 2538, 2581, 2625, 2669, 2713, 2756, +// 2800, 2844, 2888, 2931, 2975, 3019, 3063, 3106, +// 3150, 3194, 3238, 3281, 3325, 3369, 3413, 3456, +// 3500 +//}; +//uint16_t hopRxPattern_2KBPS_100MS[L1_FRAME_2KBPS_100MS_HOPS] = { +// 0, 44, 88, 131, 175, 219, 263, 306, +// 350, 394, 438, 481, 525, 569, 613, 656, +// 700, 744, 788, 831, 875, 919, 963, 1006, +// 1050, 1094, 1138, 1181, 1225, 1269, 1313, 1356, +// 1400, 1444, 1488, 1531, 1575, 1619, 1663, 1706, +// 1750, 1794, 1838, 1881, 1925, 1969, 2013, 2056, +// 2100, 2144, 2188, 2231, 2275, 2319, 2363, 2406, +// 2450, 2494, 2538, 2581, 2625, 2669, 2713, 2756, +// 2800, 2844, 2888, 2931, 2975, 3019, 3063, 3106, +// 3150, 3194, 3238, 3281, 3325, 3369, 3413, 3456, +// 3500 +//}; + +uint16_t hopTxPattern_2KBPS_100MS[L1_FRAME_2KBPS_100MS_HOPS] = { + 1500 +}; +uint16_t hopRxPattern_2KBPS_100MS[L1_FRAME_2KBPS_100MS_HOPS] = { + 1500 +}; + +uint16_t hopTxPattern_10KBPS_10MS[L1_FRAME_10KBPS_10MS_HOPS] = { + 1500 +}; +uint16_t hopRxPattern_10KBPS_10MS[L1_FRAME_10KBPS_10MS_HOPS] = { + 1500 +}; + +uint16_t hopTxPattern_10KBPS_20MS[L1_FRAME_10KBPS_20MS_HOPS] = { + 1500, 1600, 1700, 1800, 1900, 2000, 1500, 1600, + 1700, 1800, 1900 +}; +uint16_t hopRxPattern_10KBPS_20MS[L1_FRAME_10KBPS_20MS_HOPS] = { + 1500, 1600, 1700, 1800, 1900, 2000, 1500, 1600, + 1700, 1800, 1900 +}; + +uint16_t hopTxPattern_40KBPS_20MS[L1_FRAME_40KBPS_20MS_HOPS] = { + 2400, 2400, 2400, 2400, 2400, 2400, 2400, 2400, + 2400, 2400, 2400, 2400, 2400, 2400, 2400, 2400, + 2400, 2400, 2400 +}; +uint16_t hopRxPattern_40KBPS_20MS[L1_FRAME_40KBPS_20MS_HOPS] = { + 2400, 2400, 2400, 2400, 2400, 2400, 2400, 2400, + 2400, 2400, 2400, 2400, 2400, 2400, 2400, 2400, + 2400, 2400, 2400 +}; + +uint16_t hopTxPattern_40KBPS_10MS[L1_FRAME_40KBPS_10MS_HOPS] = { + 2400, 2400, 2400, 2400, 2400, 2400, 2400, 2400, + 2400 +}; +uint16_t hopRxPattern_40KBPS_10MS[L1_FRAME_40KBPS_10MS_HOPS] = { + 2400, 2400, 2400, 2400, 2400, 2400, 2400, 2400, + 2400 +}; + +uint16_t hopTxPattern_200KBPS_5MS[L1_FRAME_200KBPS_5MS_HOPS] ={ + 500, 1600, 1700, 1800, 1900, 2000, 1500, 1600, + 1700, 1800, 1900, 2000, 1500, 1600, 1700, 1800, + 1900, 2000, 1500, 1500 +}; +uint16_t hopRxPattern_200KBPS_5MS[L1_FRAME_200KBPS_5MS_HOPS] = { + 1500, 1900, 2000, 1500, 1600, 1700, 1800, 1900, + 2000, 1500, 1600, 1700, 1800, 1900, 2000, 1500, + 1500, 1500, 1700, 1800 +}; + +uint16_t hopTxPattern_1M2BPS_5MS[L1_FRAME_1M2BPS_5MS_HOPS] = { + 500, 600, 700, 800, 900, 1000, 500, 600, + 700, 800, 900, 1000, 500, 600, 700, 800, + 900, 1000, 500, 500 +}; +uint16_t hopRxPattern_1M2BPS_5MS[L1_FRAME_1M2BPS_5MS_HOPS] = { + 500, 600, 700, 800, 900, 1000, 500, 600, + 700, 800, 900, 1000, 500, 600, 700, 800, + 900, 1000, 500, 500 +}; + +// Pair by regex +// Regex: ((\{\.oaxis = [0-9]+[ ,]+\.raxis = [0-9]+[ ]*\}, ){2}) +#ifdef PHY_BEAM_SET_PRESET +PHY_ANT_ANGLE antSubnrrwPattern[L1_NUM_ANT_SUBNRRW_PATTERN] = { + {.oaxis = 0 , .raxis = 222}, {.oaxis = 10, .raxis = 85 }, + {.oaxis = 14, .raxis = 307}, {.oaxis = 17, .raxis = 170}, + {.oaxis = 19, .raxis = 32 }, {.oaxis = 21, .raxis = 255}, + {.oaxis = 24, .raxis = 117}, {.oaxis = 25, .raxis = 340}, + {.oaxis = 27, .raxis = 202}, {.oaxis = 29, .raxis = 65 }, + {.oaxis = 31, .raxis = 287}, {.oaxis = 32, .raxis = 150}, + {.oaxis = 34, .raxis = 12 }, {.oaxis = 35, .raxis = 235}, + {.oaxis = 36, .raxis = 97 }, {.oaxis = 38, .raxis = 320}, + {.oaxis = 39, .raxis = 182}, {.oaxis = 40, .raxis = 45 }, + {.oaxis = 41, .raxis = 267}, {.oaxis = 43, .raxis = 130}, + {.oaxis = 44, .raxis = 352}, {.oaxis = 45, .raxis = 215}, + {.oaxis = 46, .raxis = 77 }, {.oaxis = 47, .raxis = 300}, + {.oaxis = 48, .raxis = 162}, {.oaxis = 49, .raxis = 25 }, + {.oaxis = 50, .raxis = 247}, {.oaxis = 51, .raxis = 110}, + {.oaxis = 52, .raxis = 332}, {.oaxis = 53, .raxis = 195}, + {.oaxis = 54, .raxis = 57 }, {.oaxis = 55, .raxis = 280}, + {.oaxis = 56, .raxis = 142}, {.oaxis = 57, .raxis = 5 }, + {.oaxis = 58, .raxis = 227}, {.oaxis = 59, .raxis = 90 }, + {.oaxis = 60, .raxis = 312} +}; +PHY_ANT_ANGLE antNrrwPattern[L1_NUM_ANT_NRRW_PATTERN] = { + {.oaxis = 0 , .raxis = 222}, {.oaxis = 7 , .raxis = 85 }, + {.oaxis = 10, .raxis = 307}, {.oaxis = 13, .raxis = 170}, + {.oaxis = 15, .raxis = 32 }, {.oaxis = 17, .raxis = 255}, + {.oaxis = 18, .raxis = 117}, {.oaxis = 20, .raxis = 340}, + {.oaxis = 21, .raxis = 202}, {.oaxis = 22, .raxis = 65 }, + {.oaxis = 24, .raxis = 287}, {.oaxis = 25, .raxis = 150}, + {.oaxis = 26, .raxis = 12 }, {.oaxis = 27, .raxis = 235}, + {.oaxis = 28, .raxis = 97 }, {.oaxis = 29, .raxis = 320}, + {.oaxis = 30, .raxis = 182}, {.oaxis = 31, .raxis = 45 }, + {.oaxis = 32, .raxis = 267}, {.oaxis = 33, .raxis = 130}, + {.oaxis = 34, .raxis = 352}, {.oaxis = 34, .raxis = 215}, + {.oaxis = 35, .raxis = 77 }, {.oaxis = 36, .raxis = 300}, + {.oaxis = 37, .raxis = 162}, {.oaxis = 38, .raxis = 25 }, + {.oaxis = 38, .raxis = 247}, {.oaxis = 39, .raxis = 110}, + {.oaxis = 40, .raxis = 332}, {.oaxis = 41, .raxis = 195}, + {.oaxis = 41, .raxis = 57 }, {.oaxis = 42, .raxis = 280}, + {.oaxis = 43, .raxis = 142}, {.oaxis = 44, .raxis = 5 }, + {.oaxis = 44, .raxis = 227}, {.oaxis = 45, .raxis = 90 }, + {.oaxis = 46, .raxis = 312}, {.oaxis = 46, .raxis = 175}, + {.oaxis = 47, .raxis = 37 }, {.oaxis = 48, .raxis = 260}, + {.oaxis = 48, .raxis = 122}, {.oaxis = 49, .raxis = 345}, + {.oaxis = 49, .raxis = 207}, {.oaxis = 50, .raxis = 70 }, + {.oaxis = 51, .raxis = 292}, {.oaxis = 51, .raxis = 155}, + {.oaxis = 52, .raxis = 17 }, {.oaxis = 53, .raxis = 240}, + {.oaxis = 53, .raxis = 102}, {.oaxis = 54, .raxis = 325}, + {.oaxis = 54, .raxis = 187}, {.oaxis = 55, .raxis = 50 }, + {.oaxis = 55, .raxis = 272}, {.oaxis = 56, .raxis = 135}, + {.oaxis = 57, .raxis = 357}, {.oaxis = 57, .raxis = 220}, + {.oaxis = 58, .raxis = 82 }, {.oaxis = 58, .raxis = 305}, + {.oaxis = 59, .raxis = 167}, {.oaxis = 59, .raxis = 30 }, + {.oaxis = 60, .raxis = 252} +}; +#else +PHY_ANT_ANGLE antSubnrrwPattern[NUM_ANT_SUBNRRW_PATTERN] = {0}; +PHY_ANT_ANGLE antNrrwPattern[NUM_ANT_NRRW_PATTERN] = {0}; +#endif +/*****************************************************************************/ +/** + * @brief + * + * @param antConfigPtr + * + * @return + * + ******************************************************************************/ +int32_t Phy_AntConfigInit(PHY_ANT_COINFO *antConfigPtr) +{ + ASSERT(antConfigPtr != NULL); + + antConfigPtr->ctrlWord = 0x00; + antConfigPtr->antMode = ATN_MODE_DEFAULT; + + // FIXME: Dummy default value. + // off axis angle setting + antConfigPtr->oaxis[0] = 0; + antConfigPtr->oaxis[1] = 0; + // round axis angle setting + antConfigPtr->raxis[0] = 0; + antConfigPtr->raxis[1] = 0; + // *********************** + + antConfigPtr->antFreq[0] = (uint8_t)(DEFAULT_CENTRTAL_FREQ); + antConfigPtr->antFreq[1] = (uint8_t)(DEFAULT_CENTRTAL_FREQ >> 8); + + // FIXME: Dummy default value. + // trSelect + antConfigPtr->trSlect = 0; + // Antenna attenuation setting + antConfigPtr->antAtt = 20; + // phase setting + antConfigPtr->phase = 0; + // *********************** + + antConfigPtr->rxtxMode = RXTXMODE_DEFAULT; + antConfigPtr->calibrMode = CALIBRMODE_NORMAL; + antConfigPtr->antReserved = 0x00; + + // FIXME: Dummy default value. + // RF mode control + antConfigPtr->rfCtrl = RF_CTRL_DEFAULT; + // RF frequency + antConfigPtr->rfFreq[0] = (uint8_t)(DEFAULT_CENTRTAL_FREQ); + antConfigPtr->rfFreq[1] = (uint8_t)(DEFAULT_CENTRTAL_FREQ >> 8); + // RF MGC control + antConfigPtr->rfTxMgc = 0; + // RF channel 1&2 calibration mgc + antConfigPtr->rf12CalMgc = 0; + // RF channel 2&3 calibration mgc + antConfigPtr->rf34CalMgc = 0; + // Receive channel 1-4 MGC + antConfigPtr->rcvMgc = 0; + antConfigPtr->rfReserved0 = 0x00; + antConfigPtr->rfReserved1 = 0x00; + // *********************** + return SUCCESS; +} + +int32_t Phy_SetBeamNo(PHY_INST *instPtr, int32_t beamNo) +{ + if(instPtr->beamWd.next == PHY_ANT_BEAM_8){ + if (beamNo >= L1_NUM_ANT_NRRW_PATTERN) { + return FAILURE; + } + else { + instPtr->beamNo.next = beamNo; + instPtr->antConfigPtr.oaxis[1] = (uint8_t)(antNrrwPattern[beamNo].oaxis); + instPtr->antConfigPtr.oaxis[0] = (uint8_t)((antNrrwPattern[beamNo].oaxis) >> 8); + instPtr->antConfigPtr.raxis[1] = (uint8_t)(antNrrwPattern[beamNo].raxis); + instPtr->antConfigPtr.raxis[0] = (uint8_t)((antNrrwPattern[beamNo].raxis) >> 8); + return SUCCESS; + } + } + else if(instPtr->beamWd.next == PHY_ANT_BEAM_25){ + if (beamNo >= L1_NUM_ANT_SUBNRRW_PATTERN) { + return FAILURE; + } + else { + instPtr->beamNo.next = beamNo; + instPtr->antConfigPtr.oaxis[1] = (uint8_t)(antSubnrrwPattern[beamNo].oaxis); + instPtr->antConfigPtr.oaxis[0] = (uint8_t)((antSubnrrwPattern[beamNo].oaxis) >> 8); + instPtr->antConfigPtr.raxis[1] = (uint8_t)(antSubnrrwPattern[beamNo].raxis); + instPtr->antConfigPtr.raxis[0] = (uint8_t)((antSubnrrwPattern[beamNo].raxis) >> 8); + return SUCCESS; + } + } + else{ + // Beam number assign not support. + // Assign default angle (0,0) + instPtr->beamNo.next = 0; + instPtr->antConfigPtr.oaxis[1] = 0; + instPtr->antConfigPtr.oaxis[0] = 0; + instPtr->antConfigPtr.raxis[1] = 0; + instPtr->antConfigPtr.raxis[0] = 0; + DBG_WARNING("Using default beam number...\n"); + return SUCCESS; + } +} + +int32_t Phy_SetBeamWidth(PHY_INST *instPtr, PHY_ANT_BEAM_WIDTH beamWidth) +{ + uint8_t beamConfig = instPtr->antConfigPtr.antMode & (~ANT_MODE_BEAM_MASK); + switch (beamWidth) + { + case PHY_ANT_BEAM_120: + beamConfig |= ANT_MODE_WIDE_BEAM_3; + break; + case PHY_ANT_BEAM_60: + beamConfig |= ANT_MODE_WIDE_BEAM_2; + break; + case PHY_ANT_BEAM_25: + beamConfig |= ANT_MODE_WIDE_BEAM_1; + break; + case PHY_ANT_BEAM_8: + beamConfig |= ANT_MODE_NARROR_BEAM; + break; + default: + DBG_ERROR("Beam width code: 0x%08X is illegal.\n\r", beamWidth); + return EPARAM; + break; + } + instPtr->antConfigPtr.antMode = beamConfig; + instPtr->beamWd.next = beamWidth; + return SUCCESS; +} + +// Common version radius double input +int32_t Phy_SetBeamAngle(PHY_INST *phyInstPtr, double offAx, double rndAx) +{ + uint16_t offAxDeg = 0; + uint16_t rndAxDeg = 0; + offAxDeg = (offAx >= 0) ? (((int32_t)(offAx * 180 / ANT_PI)) % 360) : (((int32_t)(offAx * 180 / ANT_PI)) % 360 + 360); + rndAxDeg = (rndAx >= 0) ? (((int32_t)(rndAx * 180 / ANT_PI)) % 360) : (((int32_t)(rndAx * 180 / ANT_PI)) % 360 + 360); + if (offAxDeg > 60) + { + DBG_ERROR("Angle out of range, off axis angle: %u (should be 0~60), round axis angle: %u (should be 0~360).\n", + offAxDeg, rndAxDeg); + return EPARAM; + } + offAxDeg = offAxDeg * 10; + rndAxDeg = rndAxDeg * 10; + phyInstPtr->antConfigPtr.oaxis[1] = (uint8_t)offAxDeg; + phyInstPtr->antConfigPtr.oaxis[0] = (uint8_t)(offAxDeg >> 8); + phyInstPtr->antConfigPtr.raxis[1] = (uint8_t)rndAxDeg; + phyInstPtr->antConfigPtr.raxis[0] = (uint8_t)(rndAxDeg >> 8); + return SUCCESS; +} diff --git a/df_datalink/src/networking/phy_layer/phy_layer.c b/df_datalink/src/networking/phy_layer/phy_layer.c new file mode 100644 index 0000000..3722ef6 --- /dev/null +++ b/df_datalink/src/networking/phy_layer/phy_layer.c @@ -0,0 +1,885 @@ +/*****************************************************************************/ +/** + * Description: Implementation of physical control functions + * + * Date: 2021-11-16 00:08 + * LastEditTime: 2023-04-23 17:48 + * Revisions: Rev 0.2 + * History: + * [2021-11-16]: Initial version. + * [2022-06-18]: New branch for glink control purpose: + * -Add poll mode, physical layer will start Tx/Rx procedure + * at specific time stamp. + * -Add 61/37 beam switch + * -Code simplification. + * [2023-04-24]: Porting for DUIFEI. + * + * Copyright(c) 2021 Beijing Institute of Technology. + * Lab of Communication and Networking + * + ******************************************************************************/ + +/***************************** Include Files *********************************/ +#include +#include +#include "xbram.h" +#include "xadcps.h" +#include "phy_layer.h" +#include "util.h" +#include "error.h" +#include "../config/app_config.h" + +/************************** Constant Definitions *****************************/ +#define TOR_BUFF_MAX_SIZE 1024 //8192bits +#define TMWORD_FRAC_MAX 500000 +#define ANTCONFIG_MAX_LEN (8192/2) +#define PAYLOAD_MAX_LEN (4096/2) + +#define INIT_BEAM_NO 0 +#define INIT_ANT_WD PHY_ANT_BEAM_120 +#define INIT_ANT_NO 0 + +#define L1_FRAME_NONE_LEN UINT32_MAX// byte +#define L1_FRAME_2KBPS_20MS_LEN 0 // byte +#define L1_FRAME_2KBPS_100MS_LEN (240/8 )// byte +#define L1_FRAME_10KBPS_10MS_LEN 0 // byte +#define L1_FRAME_10KBPS_20MS_LEN (240/8) // byte +#define L1_FRAME_40KBPS_20MS_LEN (2160/8)// byte +#define L1_FRAME_40KBPS_10MS_LEN (720/8) // byte +#define L1_FRAME_200KBPS_5MS_LEN (2048/8)// byte +#define L1_FRAME_1M2BPS_5MS_LEN (8184/8)// byte + +//#define L1_FRAME_NONE_COMP UINT32_MAX // *10ns +//#define L1_FRAME_2KBPS_20MS_COMP 282900 // *10ns +//#define L1_FRAME_2KBPS_100MS_COMP 282900 // *10ns +//#define L1_FRAME_10KBPS_10MS_COMP 282900 // *10ns +//#define L1_FRAME_10KBPS_20MS_COMP 282900 // *10ns +//#define L1_FRAME_40KBPS_20MS_COMP 282900 // *10ns +//#define L1_FRAME_40KBPS_10MS_COMP 282900 // *10ns +//#define L1_FRAME_200KBPS_5MS_COMP 17067 // *10ns +//#define L1_FRAME_1M2BPS_5MS_COMP 282900 // *10ns + +#define L1_FRAME_NONE_COMP UINT32_MAX // *10ns +#define L1_FRAME_2KBPS_20MS_COMP 1622400 // *10ns +#define L1_FRAME_2KBPS_100MS_COMP 1622400 // *10ns +#define L1_FRAME_10KBPS_10MS_COMP 747366 // *10ns +#define L1_FRAME_10KBPS_20MS_COMP 747366 // *10ns +#define L1_FRAME_40KBPS_20MS_COMP 97066 // *10ns +#define L1_FRAME_40KBPS_10MS_COMP 97066 // *10ns +#define L1_FRAME_200KBPS_5MS_COMP 17067 // *10ns +#define L1_FRAME_1M2BPS_5MS_COMP 17067 // *10ns + +/***************** Macros (Inline Functions) Definitions *********************/ +/************************** Function Prototypes ******************************/ +static void Phy_RcdShift(PHY_RCD* rcd, int32_t netxVal); +static int32_t SetSendData(PHY_INST* instPtr, L1_FRAME_TYPE frameType, uint8_t* buff); + +/**************************** Type Definitions *******************************/ + +/************************** Variable Definitions *****************************/ + +/*****************************************************************************/ +/** + * @brief Get received data (base on PS Record), store it to data buffer. + * + * @param instPtr + * rcvBuffPtr + * + * @return SUCCESS + * FAILURE last frame type cannot be recognized. + * + ******************************************************************************/ +int32_t Phy_RetrieveRecvData(PHY_INST* instPtr, uint8_t* buff) { + ASSERT(instPtr != NULL); + uint32_t frameLen, recvBramAddr; + frameLen = Phy_GetFrameLen(instPtr->frameType.last); + if (frameLen == L1_FRAME_NONE_LEN) { + return FAILURE; + } + else { + // Ping-pong flow. + recvBramAddr = instPtr->rxDataPtr + ((PhyRead(instPtr, RECV_DATA_SATE) & RECV_DATA_OFFSET_MASK) >> RECV_DATA_OFFSET_SHIFT); + memcpy(buff, (uint8_t*) recvBramAddr, frameLen); + } + return SUCCESS; +} + + +/*****************************************************************************/ +/** + * @brief Setup data will be sent in next slot. + * + * @param instPtr A pointer to physical layer control instance. + * + * @return FAILURE Error occurred. + * SUCCESS Setting data successful. + * + ******************************************************************************/ +static int32_t SetSendData(PHY_INST* instPtr, L1_FRAME_TYPE frameType, uint8_t* buff) { + ASSERT(instPtr != NULL); + uint32_t frameLen, sendCmd; + frameLen = Phy_GetFrameLen(frameType); + + if (frameLen == L1_FRAME_NONE_LEN) { + return FAILURE; + } + else { + // Implement a ping-pong flow, offset always is 0 or half of buffer depth. + instPtr->sendOffset = (instPtr->sendOffset == PAYLOAD_MAX_LEN) ? 0 : PAYLOAD_MAX_LEN; + memcpy((uint8_t*) (instPtr->txDataPtr + instPtr->sendOffset), buff, frameLen); + // Trigger Physical layer to start fetching data. + sendCmd = frameLen & SEND_DATA_CMD_LEN_MASK; + sendCmd |= (instPtr->sendOffset << SEND_DATA_CMD_OFFSET_SHIFT) & SEND_DATA_CMD_OFFSET_MASK; + PhyWrite(instPtr, SEND_DATA_CMD, sendCmd); + } + return SUCCESS; +} + + +/*****************************************************************************/ +/** + * @brief Check whether a frame was detected. (Do not check if the frame was + * deoced.) + * + * @param instPtr + * + * @return true + * false + * + ******************************************************************************/ +inline bool Phy_IsFrameDetected(PHY_INST* instPtr) { + ASSERT(instPtr != NULL); + if(instPtr->TOR.last == PHY_TOR_RX && instPtr->isAcq && instPtr->isFrameSync) { + return true; + } + else { + return false; + } +} + +/*****************************************************************************/ +/** + * @brief Check whether a frame was received. (Do not check if the frame was + * crashed.) + * + * @param instPtr + * + * @return true + * false + * + ******************************************************************************/ +inline bool Phy_IsFrameReceived(PHY_INST* instPtr) { + ASSERT(instPtr != NULL); + if(instPtr->TOR.last == PHY_TOR_RX && instPtr->isAcq + && instPtr->isFrameSync && instPtr->isDecode) { + return true; + } + else { + return false; + } +} + +/*****************************************************************************/ +/** + * @brief Check whether a frame was valid. (if the frame was crashed, it will + * be regarded as not valid. + * + * @param instPtr + * + * @return true + * false + * + ******************************************************************************/ +inline bool Phy_IsFrameValid(PHY_INST* instPtr) { + ASSERT(instPtr != NULL); + if (instPtr->TOR.last == PHY_TOR_RX && instPtr->isAcq && instPtr->isFrameSync + && instPtr->isDecode && instPtr->isValid) { + return true; + } + else { + return false; + } +} + +/*****************************************************************************/ +/** + * @brief Get frame type of the frame in receive data buffer (Base on PS Record). + * + * @param instPtr A pointer to physical layer control instance. + * + * @return Layer2 frame type. Refer "frame_def.h" + * + ******************************************************************************/ +inline L1_FRAME_TYPE Phy_GetLastDetectedFrameType(PHY_INST* instPtr) { + ASSERT(instPtr != NULL); + if (Phy_IsFrameDetected(instPtr) == false) { + return L1_NONE_FRAME; + } + else { + return instPtr->frameType.last; + } +} + +/*****************************************************************************/ +/** + * @brief Get frame type of the frame in receive data buffer (Base on PS Record). + * + * @param instPtr A pointer to physical layer control instance. + * + * @return Layer2 frame type. Refer "frame_def.h" + * + ******************************************************************************/ +inline L1_FRAME_TYPE Phy_GetLastReceivedFrameType(PHY_INST* instPtr) { + ASSERT(instPtr != NULL); + if (Phy_IsFrameReceived(instPtr) == false) { + return L1_NONE_FRAME; + } + else { + return instPtr->frameType.last; + } +} + + +/*****************************************************************************/ +/** + * @brief Get frame type of the frame was sent in last slot. + * + * @param instPtr A pointer to physical layer control instance. + * + * @return Layer2 frame type. Refer "frame_def.h" + * + ******************************************************************************/ +inline L1_FRAME_TYPE Phy_GetLastSentFrameType(PHY_INST* instPtr) { + ASSERT(instPtr != NULL); + if (instPtr->TOR.last != PHY_TOR_TX) { + return L1_NONE_FRAME; + } + else { + return instPtr->frameType.last; + } +} + +/*****************************************************************************/ +/** + * @brief Shift l1 status record.(newval->next->curr->last) + * + * @param instPtr A pointer to physical layer control instance. + * + * @return NONE. + * + ******************************************************************************/ +static void Phy_RcdShift(PHY_RCD* rcd, int32_t netxVal){ + ASSERT(rcd != NULL); + rcd->last = rcd->curr; + rcd->curr = rcd->next; + rcd->next = netxVal; +} + +/*****************************************************************************/ +/** + * @brief Get corresponding frame length in byte of L1 frame. + * + * @param frameType + * + * @return Corresponding frame length + * L1_FRAME_NONE_LEN if the frame type code cannot be recognized. + * + ******************************************************************************/ +uint32_t Phy_GetFrameLen(L1_FRAME_TYPE frameType) { + switch (frameType) { + case L1_2KBPS_20MS_FRAME: + // FIXME: for DUIFEI net setup + return L1_FRAME_2KBPS_100MS_LEN; +// return L1_FRAME_2KBPS_20MS_LEN; + case L1_2KBPS_100MS_FRAME: + return L1_FRAME_2KBPS_100MS_LEN; + case L1_10KBPS_10MS_FRAME: + return L1_FRAME_10KBPS_10MS_LEN; + case L1_10KBPS_20MS_FRAME: + return L1_FRAME_10KBPS_20MS_LEN; + case L1_40KBPS_20MS_FRAME: + return L1_FRAME_40KBPS_20MS_LEN; + case L1_40KBPS_10MS_FRAME: + return L1_FRAME_40KBPS_10MS_LEN; + case L1_200KBPS_5MS_FRAME: + return L1_FRAME_200KBPS_5MS_LEN; + case L1_1M2BPS_5MS_FRAME: + return L1_FRAME_1M2BPS_5MS_LEN; + default: + return L1_FRAME_NONE_LEN; + } +} + + + +/*****************************************************************************/ +/** + * @brief Update Physical Layer reception status. + * + * @param instPtr + * + * @return + * + ******************************************************************************/ +void Phy_UpdateState(PHY_INST* instPtr) { + ASSERT(instPtr != NULL); + + Phy_RcdShift(&(instPtr->TOR), PHY_TOR_SUSPEND); + Phy_RcdShift(&(instPtr->frameType),L1_NONE_FRAME); + Phy_RcdShift(&(instPtr->antNo),INIT_ANT_NO); + Phy_RcdShift(&(instPtr->beamNo),INIT_BEAM_NO); + Phy_RcdShift(&(instPtr->beamWd),INIT_ANT_WD); + /* Update Frame Sate. */ + uint32_t txrxSate = PhyRead(instPtr, TXRX_STATE); + instPtr->isAcq = ((txrxSate & TXRX_STATE_ACQ_MASK) == TXRX_STATE_ACQ_SUCCESS) ? true : false; + instPtr->isFrameSync = ((txrxSate & TXRX_STATE_FSYNC_MASK) == TXRX_STATE_FSYNC_SUCCESS) ? true : false; + instPtr->isDecode = ((txrxSate & TXRX_STATE_DECODE_MASK) == TXRX_STATE_DECODE_SUCCESS) ? true : false; + + if (Phy_IsFrameReceived(instPtr)) { + DBG_INFO("Physical layer finished reception procedure, retrieving received data...\n"); + instPtr->isValid = true; + } + else { + instPtr->isValid = false; + } + return; +} + + +/*****************************************************************************/ +/** + * @brief Initialize Physical Layer instance, allocate memory for buffers, + * apply a self test. + * + * @param instPtr + * phyConfig + * + * @return + * + ******************************************************************************/ +int32_t Phy_InstInit(PHY_INST** instPtr, PHY_CONFIG *phyConfig) { + ASSERT(instPtr != NULL); + ASSERT(phyConfig != NULL); + int32_t Status = SUCCESS; + *instPtr = (PHY_INST*) malloc(sizeof(PHY_INST)); + if ((*instPtr) == NULL) { + return ENOMEM; + } + + memcpy(&((*instPtr)->phyCofig), phyConfig, sizeof(PHY_CONFIG)); + (*instPtr)->isPhyEn = false; + (*instPtr)->isAcq = false; + (*instPtr)->isFrameSync = false; + (*instPtr)->isDecode = false; + (*instPtr)->isValid = false; + (*instPtr)->isPresetHop = true; + (*instPtr)->antConfigOffset = 0; + (*instPtr)->sendOffset = 0; + + memset(&((*instPtr))->TOR, PHY_TOR_SUSPEND, sizeof(PHY_RCD)); + memset(&((*instPtr)->frameType), L1_NONE_FRAME, sizeof(PHY_RCD)); + memset(&((*instPtr)->antNo), (int32_t)INIT_BEAM_NO, sizeof(PHY_RCD)); + memset(&((*instPtr)->beamNo), (int32_t)INIT_ANT_NO, sizeof(PHY_RCD)); + memset(&((*instPtr)->beamWd), (int32_t)INIT_ANT_WD, sizeof(PHY_RCD)); + memset(&((*instPtr)->hwSate), 0x00, sizeof(HWSTATE)); + + Status = Phy_AntConfigInit(&((*instPtr)->antConfigPtr)); + if (Status != SUCCESS) { + goto init_error; + } + + XBram_Config *bramConfigPtr; + XBram antConfigBram; + XBram txDataBram; + XBram rxDataBram; + bramConfigPtr = XBram_LookupConfig(phyConfig->antBramId); + if (bramConfigPtr == NULL) { + Status = EDCONF; + goto init_error; + + } + Status = XBram_CfgInitialize(&antConfigBram, bramConfigPtr, + bramConfigPtr->CtrlBaseAddress); + if (Status != SUCCESS) { + goto init_error; + } + /* + * Execute the BRAM driver selftest. + */ + Status = XBram_SelfTest(&antConfigBram, 0); + if (Status != SUCCESS) { + goto init_error; + } + + bramConfigPtr = XBram_LookupConfig(phyConfig->txBramId); + if (bramConfigPtr == NULL) { + Status = EDCONF; + goto init_error; + } + Status = XBram_CfgInitialize(&txDataBram, bramConfigPtr, + bramConfigPtr->CtrlBaseAddress); + if (Status != SUCCESS) { + goto init_error; + } + /* + * Execute the BRAM driver selftest. + */ + Status = XBram_SelfTest(&txDataBram, 0); + if (Status != SUCCESS) { + goto init_error; + } + + bramConfigPtr = XBram_LookupConfig(phyConfig->rxBramId); + if (bramConfigPtr == NULL) { + Status = EDCONF; + goto init_error; + } + Status = XBram_CfgInitialize(&rxDataBram, bramConfigPtr, + bramConfigPtr->CtrlBaseAddress); + if (Status != SUCCESS) { + goto init_error; + } + /* + * Execute the BRAM driver selftest. + */ + Status = XBram_SelfTest(&rxDataBram, 0); + if (Status != SUCCESS) { + goto init_error; + } + + (*instPtr)->txDataPtr = txDataBram.Config.MemBaseAddress; + (*instPtr)->rxDataPtr = rxDataBram.Config.MemBaseAddress; + (*instPtr)->antConfigDataPtr = antConfigBram.Config.MemBaseAddress; + + /* Initialize the XAdc driver. */ + XAdcPs_Config *xadcConfigPtr; + + xadcConfigPtr = XAdcPs_LookupConfig(phyConfig->hwXadcId); + if (xadcConfigPtr == NULL) { + Status = EDCONF; + goto init_error; + } + XAdcPs_CfgInitialize(&((*instPtr)->hwXadc), xadcConfigPtr, xadcConfigPtr->BaseAddress); + + /* Self Test the XADC/ADC device */ + Status = XAdcPs_SelfTest(&((*instPtr)->hwXadc)); + if (Status != SUCCESS) { + goto init_error; + } + + /* Disable the Channel Sequencer before configuring the Sequence registers. */ + XAdcPs_SetSequencerMode(&((*instPtr)->hwXadc), XADCPS_SEQ_MODE_SAFE); + + return SUCCESS; +init_error: + free(*instPtr); + return Status; +} + +/*****************************************************************************/ +/** + * @brief Start physical layer + * + * @param instPtr a pointer to physical instance + * + * @return NONE + * + ******************************************************************************/ +void Phy_Start(PHY_INST* instPtr) { + ASSERT(instPtr != NULL); + uint32_t phyMainCtrl = PhyRead(instPtr, PHY_MAIN_CTRL); + if((phyMainCtrl & PHY_MAIN_CTRL_EN_MASK) == PHY_MAIN_CTRL_EN_EN) { + DBG_WARNING("Physical layer was already enabled.\n"); + } + instPtr->isPhyEn = true; + // Enable CRC check automatically + PhyWrite(instPtr, PHY_MAIN_CTRL, (phyMainCtrl | PHY_MAIN_CTRL_EN_EN)); +} + +/*****************************************************************************/ +/** + * @brief Halt physical layer operation + * + * @param instPtr a pointer to physical instance + * + * @return NONE + * + ******************************************************************************/ +void Phy_Halt(PHY_INST* instPtr) { + ASSERT(instPtr != NULL); + uint32_t phyMainCtrl = PhyRead(instPtr, PHY_MAIN_CTRL); + if((phyMainCtrl & PHY_MAIN_CTRL_EN_MASK) == PHY_MAIN_CTRL_EN_DSBL) { + DBG_WARNING("Physical layer was allready halted.\n"); + } + instPtr->isPhyEn = false; + PhyWrite(instPtr, PHY_MAIN_CTRL, (phyMainCtrl & (~PHY_MAIN_CTRL_EN_MASK))); +} + + +/*****************************************************************************/ +/** + * @brief Update Physical Layer mode. + * + * @param instPtr + * modeCod + * + * @return + * + ******************************************************************************/ +int32_t Phy_SetMode(PHY_INST* instPtr, PHY_MODE modeCod) { + ASSERT(instPtr != NULL); + uint32_t phyMainCtrl = PhyRead(instPtr, PHY_MAIN_CTRL) & ~PHY_MAIN_CTRL_MODE_MASK; + switch (modeCod) { + case PHY_MODE_NONE: + phyMainCtrl |= PHY_MAIN_CTRL_MODE_NONE; + break; + case PHY_MODE_LISTEN: + phyMainCtrl |= PHY_MAIN_CTRL_MODE_LISTEN; + break; + case PHY_MODE_SCHEDULE: + phyMainCtrl |= PHY_MAIN_CTRL_MODE_SCHEDULE; + break; + case PHY_MODE_PULL: + phyMainCtrl |= PHY_MAIN_CTRL_MODE_PULL; + break; + default: + return FAILURE; + break; + } + PhyWrite(instPtr, PHY_MAIN_CTRL, phyMainCtrl | PHY_MAIN_CTRL_EN_EN); + return SUCCESS; +} + +/*****************************************************************************/ +/** + * @brief Setup next slot operation. + * + * @param instPtr + * txrxMode + * l2FrameType + * + * @return + * + ******************************************************************************/ +int32_t Phy_SetupNextSlot(PHY_INST* instPtr, PHY_TOR_TYPE txrxMode, + L1_FRAME_TYPE frameType, uint8_t* buff) { + ASSERT(instPtr != NULL); + int32_t Status = SUCCESS; + uint32_t phyModeCtrl, antConfigBramAddr, hopNum; + uint16_t* hopPattern; + // Implement a ping-pong flow, offset always is 0 or half of buffer depth. + instPtr->antConfigOffset = (instPtr->antConfigOffset == ANTCONFIG_MAX_LEN) ? 0 : ANTCONFIG_MAX_LEN; + antConfigBramAddr = instPtr->antConfigDataPtr + instPtr->antConfigOffset; + + instPtr->TOR.next = txrxMode; + instPtr->frameType.next = frameType; + + switch (txrxMode) { + case PHY_TOR_SUSPEND: + phyModeCtrl = PHY_MODE_CTRL_TOR_SUSPEND; + break; + case PHY_TOR_RX: + phyModeCtrl = PHY_MODE_CTRL_TOR_RX; + break; + case PHY_TOR_TX: + phyModeCtrl = PHY_MODE_CTRL_TOR_TX; + break; + default: + return EPARAM; + } + if (instPtr->isPresetHop == false) { + hopPattern = (txrxMode == PHY_TOR_TX) ? hopTxPattern_Config : hopRxPattern_Config; + } + else { + switch (frameType) { + case L1_2KBPS_20MS_FRAME: + phyModeCtrl |= PHY_MODE_CTRL_FRAME_2KBPS_20MS; + hopNum = L1_FRAME_2KBPS_20MS_HOPS; + // FIXME: For DUIFEI net setup. + // hopPattern = (txrxMode == TOR_TX) ? hopTxPattern_2KBPS_20MS : hopRxPattern_2KBPS_20MS; + hopPattern = (txrxMode == PHY_TOR_TX) ? hopTxPattern_2KBPS_100MS : hopRxPattern_2KBPS_100MS; + break; + case L1_2KBPS_100MS_FRAME: + phyModeCtrl |= PHY_MODE_CTRL_FRAME_2KBPS_100MS; + hopNum = L1_FRAME_2KBPS_100MS_HOPS; + hopPattern = (txrxMode == PHY_TOR_TX) ? hopTxPattern_2KBPS_100MS : hopRxPattern_2KBPS_100MS; + break; + case L1_10KBPS_10MS_FRAME: + phyModeCtrl |= PHY_MODE_CTRL_FRAME_10KBPS_10MS; + hopNum = L1_FRAME_10KBPS_10MS_HOPS; + hopPattern = (txrxMode == PHY_TOR_TX) ? hopTxPattern_10KBPS_10MS : hopRxPattern_10KBPS_10MS; + break; + case L1_10KBPS_20MS_FRAME: + phyModeCtrl |= PHY_MODE_CTRL_FRAME_10KBPS_20MS; + hopNum = L1_FRAME_10KBPS_20MS_HOPS; + hopPattern = (txrxMode == PHY_TOR_TX) ? hopTxPattern_10KBPS_20MS : hopRxPattern_10KBPS_20MS; + break; + case L1_40KBPS_20MS_FRAME: + phyModeCtrl |= PHY_MODE_CTRL_FRAME_200KBPS_5MS; + hopNum = L1_FRAME_200KBPS_5MS_HOPS; + hopPattern = (txrxMode == PHY_TOR_TX) ? hopTxPattern_200KBPS_5MS : hopRxPattern_200KBPS_5MS; + break; + case L1_40KBPS_10MS_FRAME: + phyModeCtrl |= PHY_MODE_CTRL_FRAME_40KBPS_10MS; + hopNum = L1_FRAME_40KBPS_10MS_HOPS; + hopPattern = (txrxMode == PHY_TOR_TX) ? hopTxPattern_40KBPS_10MS : hopRxPattern_40KBPS_10MS; + break; + case L1_200KBPS_5MS_FRAME: + phyModeCtrl |= PHY_MODE_CTRL_FRAME_200KBPS_5MS; + hopNum = L1_FRAME_200KBPS_5MS_HOPS; + hopPattern = (txrxMode == PHY_TOR_TX) ? hopTxPattern_200KBPS_5MS : hopRxPattern_200KBPS_5MS; + break; + case L1_1M2BPS_5MS_FRAME: + phyModeCtrl |= PHY_MODE_CTRL_FRAME_1M2BPS_5MS; + hopNum = L1_FRAME_1M2BPS_5MS_HOPS; + hopPattern = (txrxMode == PHY_TOR_TX) ? hopTxPattern_1M2BPS_5MS : hopRxPattern_1M2BPS_5MS; + break; + default: + return EPARAM; + break; + } + } + + PhyWrite(instPtr, PHY_MODE_CTRL, phyModeCtrl); + + //TODO: Set antenna stand by, when suspend. + const uint8_t* dataSrcPtr = (uint8_t*)(&(instPtr->antConfigPtr)); + for (int32_t i = 0; i < hopNum; i++) { + instPtr->antConfigPtr.antFreq[1] = (uint8_t)(hopPattern[i] & 0x00FF); + instPtr->antConfigPtr.antFreq[0] = (uint8_t)((hopPattern[i] >> 8) & 0x00FF); + instPtr->antConfigPtr.rfFreq[1] = (uint8_t)(hopPattern[i] & 0x00FF); + instPtr->antConfigPtr.rfFreq[0] = (uint8_t)((hopPattern[i] >> 8) & 0x00FF); + memcpy((uint8_t*) (antConfigBramAddr + i * ANT_COINFO_LENGTH), + dataSrcPtr, sizeof(PHY_ANT_COINFO)); + } + uint32_t antCtrl = (instPtr->antConfigOffset & ANT_CONFIG_CMD_OFFSET_MASK) + | ((hopNum << ANT_CONFIG_CMD_NUM_SHIFT) & ANT_CONFIG_CMD_NUM_MASK) + | ((ANT_COINFO_LENGTH << ANT_CONFIG_CMD_LEN_SHIFT) & ANT_CONFIG_CMD_LEN_MASK); + PhyWrite(instPtr, ANT_CONFIG_CMD, antCtrl); + + // FIXME: For DUIFEI network setup. Should only set send data in send slots. + if(txrxMode == PHY_TOR_TX) { + Status = SetSendData(instPtr, frameType, buff); + if(Status != SUCCESS) { + return Status; + } + } + + // Trigger physical configuration. + PhyWrite(instPtr, SLOT_CONFIG_CMD, SLOT_CONFIG_CMD_VAULE); // Phy start fetching data. + return SUCCESS; +} + +/*****************************************************************************/ +/** + * @brief Get the corresponding frequency hopping pattern length of a + * specified L1 frame type. + * + * @param frameType a L1 frame type enumeration. + * + * @return SUCCESS + * FAILURE frame type cannot be recognized + * + ******************************************************************************/ +uint32_t Phy_GetHopLength(L1_FRAME_TYPE frameType){ + switch (frameType) { + case L1_2KBPS_20MS_FRAME: + return L1_FRAME_2KBPS_20MS_HOPS; + case L1_2KBPS_100MS_FRAME: + return L1_FRAME_2KBPS_100MS_HOPS; + case L1_10KBPS_10MS_FRAME: + return L1_FRAME_10KBPS_10MS_HOPS; + case L1_10KBPS_20MS_FRAME: + return L1_FRAME_10KBPS_20MS_HOPS; + case L1_40KBPS_20MS_FRAME: + return L1_FRAME_40KBPS_20MS_HOPS; + case L1_40KBPS_10MS_FRAME: + return L1_FRAME_40KBPS_10MS_HOPS; + case L1_200KBPS_5MS_FRAME: + return L1_FRAME_200KBPS_5MS_HOPS; + case L1_1M2BPS_5MS_FRAME: + return L1_FRAME_1M2BPS_5MS_HOPS; + default: + return L1_FRAME_NONE_LEN; + } +} + +/*****************************************************************************/ +/** + * @brief Get the time from frame sync to slot end of different type. + * + * @param frameType + * + * @return 32bit unsigned integer (clock periods) + * + ******************************************************************************/ +uint32_t Phy_GetTimeComp(L1_FRAME_TYPE frameType){ + switch (frameType) { + case L1_2KBPS_20MS_FRAME: + return L1_FRAME_2KBPS_20MS_COMP; + case L1_2KBPS_100MS_FRAME: + return L1_FRAME_2KBPS_100MS_COMP; + case L1_10KBPS_10MS_FRAME: + return L1_FRAME_10KBPS_10MS_COMP; + case L1_10KBPS_20MS_FRAME: + return L1_FRAME_10KBPS_20MS_COMP; + case L1_40KBPS_20MS_FRAME: + return L1_FRAME_40KBPS_20MS_COMP; + case L1_40KBPS_10MS_FRAME: + return L1_FRAME_40KBPS_10MS_COMP; + case L1_200KBPS_5MS_FRAME: + return L1_FRAME_200KBPS_5MS_COMP; + case L1_1M2BPS_5MS_FRAME: + return L1_FRAME_1M2BPS_5MS_COMP; + default: + return L1_FRAME_NONE_LEN; + } +} + +/*****************************************************************************/ +/** + * @brief Get latest frequency deviation estimation. + * + * @param instPtr + * + * @return 32bit signed integer (Hz) + * + ******************************************************************************/ +int32_t Phy_GetFreqEst(PHY_INST *instPtr){ + uint32_t temp; + int32_t acqCh, fsCh; + double freqEst; + temp = PhyRead(instPtr, COASE_FREQEST); + acqCh = temp & 0x000000FF; + acqCh = 80 - acqCh; + fsCh = (temp>>8) & 0x000000FF; + fsCh = fsCh -128; + freqEst = acqCh*(31.25e3/4) + fsCh*(31.25e3/256); + return ((int32_t) freqEst); +} + +/*****************************************************************************/ +/** + * @brief Setup a frequency hopping pattern. + * + * @param patternBuff a pointer to hopping pattern buffer + * @param patternLen a integer indicate the length of hopping pattern. + * + * @return SUCCESS + * FAILURE pattern length exceeds maximum length. + * + ******************************************************************************/ +int32_t Phy_SetHopPattern(void* patternBuff, uint32_t patternLen){ + ASSERT(patternBuff != NULL); + if(patternLen > L1_FRAME_MAX_HOPS){ + return FAILURE; + } + memcpy(hopRxPattern_Config, patternBuff, patternLen*sizeof(uint16_t)); + memcpy(hopTxPattern_Config, patternBuff, patternLen*sizeof(uint16_t)); + + // FIXME: A physical layer glitch, ignore hop 2 3 4 in rx mode + // should be fixed in next version + if(patternLen > 4){ + for(int32_t i = 0; i< patternLen-3; i++){ + hopRxPattern_Config[i+1] = hopRxPattern_Config[i+4]; + } + } + return SUCCESS; +} + +/*****************************************************************************/ +/** + * @brief Setup a specific timer word register in physical controller. + * + * @param instPtr + * @param tmWord + * @param tmType + * + * @return SUCCESS + * FAILURE pattern length exceeds maximum length. + * + ******************************************************************************/ +int32_t Phy_SetTimeWord(PHY_INST* instPtr, uint64_t tmWord, PHY_TIME_WORD_TYPE tmType){ + ASSERT(instPtr != NULL); + switch(tmType){ + case PHY_TIME_WORD_POLL: + PhyWrite(instPtr, POLLTIME_L, (uint32_t)tmWord); + PhyWrite(instPtr, POLLTIME_H, (uint32_t)(tmWord>>32)); + break; + case PHY_TIME_WORD_LOCAL_ADJ: + PhyWrite(instPtr, LOCALTM_ADJ_L, (uint32_t)tmWord); + PhyWrite(instPtr, LOCALTM_ADJ_H, (uint32_t)(tmWord>>32)); + break; + case PHY_TIME_WORD_STEP: + PhyWrite(instPtr, CNT_STEP_OPT, (uint32_t)tmWord); + break; + default: + return EPARAM; + } + return SUCCESS; +} + + +/*****************************************************************************/ +/** + * @brief Setup a specific timer word register in physical controller. + * + * @param instPtr a pointer to hopping pattern buffer + * @param patternLen a integer indicate the length of hopping pattern. + * + * @return SUCCESS + * FAILURE pattern length exceeds maximum length. + * + ******************************************************************************/ +void Phy_UpdateHwSate(PHY_INST *instPtr){ + ASSERT(instPtr != NULL); + uint32_t rawData; + + // -- Update Chip voltage, unit mV + rawData = XAdcPs_GetAdcData(&(instPtr->hwXadc), XADCPS_CH_VCCPINT); + instPtr->hwSate.spVolt = (uint16_t)(XAdcPs_RawToVoltage(rawData) * 1000); + + // -- Update Chip temperature, unit 0.01 deg + rawData = XAdcPs_GetAdcData(&(instPtr->hwXadc), XADCPS_CH_TEMP); + instPtr->hwSate.spTemp = (uint16_t)(XAdcPs_RawToTemperature(rawData) * 100); + + //FIXME: Chip status determine. + instPtr->hwSate.chipSt = 0; + + /*** Voltage and Status ***/ + rawData = PhyRead(instPtr, ANT_STATUS); + // -- Update Antenna Status Code: 0xAA - normal, 0x55 - error + instPtr->hwSate.antSt = ((rawData & ANT_STATUS_CODE_MASK) == 0) ? 0xAA : 0x55; + // -- Update Antenna Voltage Status: 1 - normal, 0 - error + // [0] - ANT voltage status + // [2] - RF voltage status + // [4] - NIL voltage status + instPtr->hwSate.antVolt = (rawData & ANT_STATUS_ANT_VOLT_MASK) ? 0x01 : 0x00; + instPtr->hwSate.antVolt |= (rawData & ANT_STATUS_RF_VOLT_MASK) ? 0x04 : 0x00; + instPtr->hwSate.antVolt |= (rawData & ANT_STATUS_NIL_VOLT_MASK) ? 0x10 : 0x00; + + /*** Temperature and Lock Status ***/ + rawData = PhyRead(instPtr, RF_STATUS); + //-- Update Antenna Temperature (signed 8bit integer, 1 centigrade per LSB) + instPtr->hwSate.antTemp = (uint8_t)(rawData & RF_STATUS_TEMP_MASK); + // -- Update Antenna PLL Lock Status: 1 - normal, 0 - error + // [0] - BASEBAND lock status + // [2] - PLLA lock status + // [4] - PLLB lock status + instPtr->hwSate.antPll = (rawData & RF_STATUS_BDLOCK_MASK) ? 0x01 : 0x00; + instPtr->hwSate.antPll |= (rawData & RF_STATUS_PLLA_MASK) ? 0x04 : 0x00; + instPtr->hwSate.antPll |= (rawData & RF_STATUS_PLLB_MASK) ? 0x10 : 0x00; + + /*** MGCs ***/ + rawData = PhyRead(instPtr, RF_MGC); + // -- Update Antenna MGC (0~15 dB) + // [3:0] - Channel 1 MGC + // [7:4] - Channel 2 MGC + // [11:8] - Channel 3 MGC + // [15:12] - Channel 4 MGC + instPtr->hwSate.antMgc = (rawData & RF_MGC_CH1_MASK); + instPtr->hwSate.antMgc |= (rawData & RF_MGC_CH2_MASK) >> 4; + instPtr->hwSate.antMgc |= (rawData & RF_MGC_CH3_MASK) >> 8; + instPtr->hwSate.antMgc |= (rawData & RF_MGC_CH4_MASK) >> 12; + SysMonitor_UpdateHardwareStatus(&(instPtr->hwSate)); +} diff --git a/df_datalink/src/networking/phy_layer/phy_layer.h b/df_datalink/src/networking/phy_layer/phy_layer.h new file mode 100644 index 0000000..8a220fa --- /dev/null +++ b/df_datalink/src/networking/phy_layer/phy_layer.h @@ -0,0 +1,248 @@ +/*****************************************************************************/ +/** + * Description: Physical layer control definitions and function prototypes. + * + * Date: 2021-12-04 16:32 + * LastEditTime: 2023-04-24 17:41 + * Revisions: Rev 0.1 + * History: + * [2021-12-08]: Initial version. + * [2022-06-18]: New branch for glink control purpose: + * -Add poll mode, physical layer will start Tx/Rx procedure + * at specific time stamp. + * -Add 61/37 beam switch + * -Code simplification. + * [2023-04-24]: Porting for DUIFEI. + * + * Copyright(c) 2021 Beijing Institute of Technology. + * Lab of Communication and Networking + * + ******************************************************************************/ + +#ifndef PHY_CTRL_H_ +#define PHY_CTRL_H_ + +/***************************** Include Files *********************************/ +#include +#include "common.h" +#include "xbram.h" +#include "xadcps.h" +#include "phy_reg.h" +#include "../../system_monitor.h" +/************************** Constant Definitions *****************************/ +#define L1_FRAME_NONE_HOPS UINT32_MAX +#define L1_FRAME_MAX_HOPS 81 +#define L1_FRAME_2KBPS_20MS_HOPS 1 +#define L1_FRAME_2KBPS_100MS_HOPS 81 +#define L1_FRAME_10KBPS_10MS_HOPS 1 +#define L1_FRAME_10KBPS_20MS_HOPS 11 +#define L1_FRAME_40KBPS_20MS_HOPS 19 +#define L1_FRAME_40KBPS_10MS_HOPS 9 +#define L1_FRAME_200KBPS_5MS_HOPS 20 +#define L1_FRAME_1M2BPS_5MS_HOPS 20 + +#define L1_NUM_ANT_SUBNRRW_PATTERN 37 +#define L1_NUM_ANT_NRRW_PATTERN 61 + +#define ANT_COINFO_LENGTH 32 //bytes +/***************** Macros (Inline Functions) Definitions *********************/ +/**************************** Type Definitions *******************************/ +typedef enum { + L1_NONE_FRAME = 0, + L1_2KBPS_20MS_FRAME = 1, + L1_2KBPS_100MS_FRAME = 2, + L1_10KBPS_10MS_FRAME = 3, + L1_10KBPS_20MS_FRAME = 4, + L1_40KBPS_20MS_FRAME = 5, + L1_40KBPS_10MS_FRAME = 6, + L1_200KBPS_5MS_FRAME = 7, + L1_1M2BPS_5MS_FRAME = 8 +} L1_FRAME_TYPE; + +typedef struct { + /*** Ant Control ***/ + /* Antenna control frame head 0xAA */ + /* default 0, reserved for further use */ + uint8_t ctrlWord; + /* high 4 bits specified beam mode. + * low 4 bits specified power control */ + uint8_t antMode; + /* off-axis angle range is 0~60, + * 0.1 degree each LSB */ + uint8_t oaxis[2]; + /* round-axis angle range is 0~360, + * 0.1 degree each LSB */ + uint8_t raxis[2]; + /* 0~3500Mhz, step 1MHz */ + uint8_t antFreq[2]; + /* in single tr mode, 0~63 specified tr channel + * in single subarray mode, 0~3 specified the subarray + * Only in debug mode*/ + uint8_t trSlect; + /* Antenna attenuation 0~31, 0.5dB each LSB, Only in debug mode */ + uint8_t antAtt; + /* 0~63, 5.625 degree each LSB, Only in debug mode*/ + uint8_t phase; + /* Only for debug */ + /* default 0x00 */ + uint8_t rxtxMode; + /* 0x00 Normal, 0x01 single tr calibration */ + uint8_t calibrMode; + /* reserved for further use */ + uint8_t antReserved; + + /*** RF Control ***/ + /* [7:4]RF enable: 0-On, 1-Off(Default); [3:0]Work mode: 0(default) */ + uint8_t rfCtrl; + /* 0~3500Mhz, step 1MHz */ + uint8_t rfFreq[2]; + /* RF MGC control: 0~31, 1dB each LSB*/ + uint8_t rfTxMgc; + /* RF channel 1&2 calibration mgc: [7:4] Channle1 - max 15db, 1dB each LSB + * [3:0] Channle2 - max 15db, 1dB each LSB*/ + uint8_t rf12CalMgc; + /* RF channel 3&4 calibration mgc: [7:4] Channle3 - max 15db, 1dB each LSB + * [3:0] Channle4 - max 15db, 1dB each LSB*/ + uint8_t rf34CalMgc; + /* Receive channel 1-4 MGC: 0~31, 1dB each LSB */ + uint8_t rcvMgc; + /* Receive monitor, 0-normal, 1-switch to monitor port */ + uint8_t rfMonitor; + /* reserved for further use */ + uint8_t rfReserved0; + uint8_t rfReserved1; +} PHY_ANT_COINFO; + + +typedef struct { + /* off-axis angle range is 0~60, + * 0.1 degree each LSB */ + uint16_t oaxis; + /* round-axis angle range is 0~360, + * 0.1 degree each LSB */ + uint16_t raxis; +} PHY_ANT_ANGLE; + + +typedef enum { + PHY_TIME_WORD_NONE = 0, + PHY_TIME_WORD_POLL = 1, + PHY_TIME_WORD_LOCAL_ADJ = 2, + PHY_TIME_WORD_STEP = 3, +} PHY_TIME_WORD_TYPE; + +typedef enum { + PHY_ANT_BEAM_NONE = 0, + PHY_ANT_BEAM_120 = 1, + PHY_ANT_BEAM_60 = 2, + PHY_ANT_BEAM_25 = 3, + PHY_ANT_BEAM_8 = 4 +} PHY_ANT_BEAM_WIDTH; + +typedef enum { + PHY_TOR_SUSPEND = 0, + PHY_TOR_TX = 1, + PHY_TOR_RX = 2 +} PHY_TOR_TYPE; + +typedef enum { + PHY_MODE_NONE = 0, + PHY_MODE_LISTEN = 1, + PHY_MODE_SCHEDULE = 2, + PHY_MODE_PULL = 3 +} PHY_MODE; + +typedef struct { + uint32_t devId; + uint32_t txBramId; + uint32_t rxBramId; + uint32_t antBramId; + uint32_t hwXadcId; + uint32_t baseAddr; +} PHY_CONFIG; + +typedef struct { + int32_t last; + int32_t curr; + int32_t next; +} PHY_RCD; + +typedef struct { + PHY_CONFIG phyCofig; // Device address configs + bool isPhyEn; // is physical instance enable + bool isAcq; // is last reception acquisition success + bool isFrameSync; // is last reception frame sync success + bool isDecode; // is last reception decode success + bool isValid; // is last reception frame data valid (crc check pass) + bool isPresetHop; // is using preset frequency hop + PHY_RCD antNo; // antenna number record + PHY_RCD beamNo; // beam number record + PHY_RCD beamWd; // beam width record + PHY_RCD TOR; // tx rx state record + PHY_RCD frameType; // frame type record + uint32_t antConfigOffset; // antenna configuration bram offset (to implement ping-pong data flow) + uint32_t sendOffset; // antenna configuration bram offset (to implement ping-pong data flow) + PHY_ANT_COINFO antConfigPtr; // antenna configuration pointer + uintptr_t txDataPtr; + uintptr_t rxDataPtr; + uintptr_t antConfigDataPtr; + XAdcPs hwXadc; + HWSTATE hwSate; +} PHY_INST; + +/************************** Variable Definitions *****************************/ +extern uint16_t hopRxPattern_Config[L1_FRAME_MAX_HOPS]; +extern uint16_t hopTxPattern_Config[L1_FRAME_MAX_HOPS]; +extern uint16_t hopTxPattern_2KBPS_20MS[L1_FRAME_2KBPS_20MS_HOPS]; +extern uint16_t hopRxPattern_2KBPS_20MS[L1_FRAME_2KBPS_20MS_HOPS]; +extern uint16_t hopTxPattern_2KBPS_100MS[L1_FRAME_2KBPS_100MS_HOPS]; +extern uint16_t hopRxPattern_2KBPS_100MS[L1_FRAME_2KBPS_100MS_HOPS]; +extern uint16_t hopTxPattern_10KBPS_10MS[L1_FRAME_10KBPS_10MS_HOPS]; +extern uint16_t hopRxPattern_10KBPS_10MS[L1_FRAME_10KBPS_10MS_HOPS]; +extern uint16_t hopTxPattern_10KBPS_20MS[L1_FRAME_10KBPS_20MS_HOPS]; +extern uint16_t hopRxPattern_10KBPS_20MS[L1_FRAME_10KBPS_20MS_HOPS]; +extern uint16_t hopTxPattern_40KBPS_20MS[L1_FRAME_40KBPS_20MS_HOPS]; +extern uint16_t hopRxPattern_40KBPS_20MS[L1_FRAME_40KBPS_20MS_HOPS]; +extern uint16_t hopTxPattern_40KBPS_10MS[L1_FRAME_40KBPS_10MS_HOPS]; +extern uint16_t hopRxPattern_40KBPS_10MS[L1_FRAME_40KBPS_10MS_HOPS]; +extern uint16_t hopTxPattern_200KBPS_5MS[L1_FRAME_200KBPS_5MS_HOPS]; +extern uint16_t hopRxPattern_200KBPS_5MS[L1_FRAME_200KBPS_5MS_HOPS]; +extern uint16_t hopTxPattern_1M2BPS_5MS[L1_FRAME_1M2BPS_5MS_HOPS]; +extern uint16_t hopRxPattern_1M2BPS_5MS[L1_FRAME_1M2BPS_5MS_HOPS]; + +extern PHY_ANT_ANGLE antSubnrrwPattern[L1_NUM_ANT_SUBNRRW_PATTERN]; +extern PHY_ANT_ANGLE antNrrwPattern[L1_NUM_ANT_NRRW_PATTERN]; + +/************************** Function Prototypes ******************************/ +int32_t Phy_InstInit(PHY_INST **instPtr, PHY_CONFIG *phyConfig); +void Phy_UpdateState(PHY_INST *instPtr); +void Phy_UpdateHwSate(PHY_INST *instPtr); + +void Phy_Start(PHY_INST *instPtr); +void Phy_Halt(PHY_INST *instPtr); +int32_t Phy_SetMode(PHY_INST *instPtr, PHY_MODE modeCod); + +int32_t Phy_SetupNextSlot(PHY_INST *instPtr, PHY_TOR_TYPE txrxMode, L1_FRAME_TYPE frameType, uint8_t* buff); +int32_t Phy_RetrieveRecvData(PHY_INST* instPtr, uint8_t* buff); + +bool Phy_IsFrameDetected(PHY_INST *instPtr); +bool Phy_IsFrameReceived(PHY_INST *instPtr); +bool Phy_IsFrameValid(PHY_INST *instPtr); +uint32_t Phy_GetFrameLen(L1_FRAME_TYPE frameType); + +L1_FRAME_TYPE Phy_GetLastDetectedFrameType(PHY_INST* instPtr); +L1_FRAME_TYPE Phy_GetLastReceivedFrameType(PHY_INST *instPtr); +L1_FRAME_TYPE Phy_GetLastSentFrameType(PHY_INST *instPtr); + +int32_t Phy_SetHopPattern(void *patternBuff, uint32_t patternLen); +uint32_t Phy_GetHopLength(L1_FRAME_TYPE frameType); +uint32_t Phy_GetTimeComp(L1_FRAME_TYPE frameType); +int32_t Phy_GetFreqEst(PHY_INST *instPtr); +int32_t Phy_SetTimeWord(PHY_INST *instPtr, uint64_t tmWord, PHY_TIME_WORD_TYPE tmType); + +int32_t Phy_AntConfigInit(PHY_ANT_COINFO *antCoinfoPtr); +int32_t Phy_SetBeamWidth(PHY_INST *instPtr, PHY_ANT_BEAM_WIDTH beamWidth); +int32_t Phy_SetBeamNo(PHY_INST *instPtr, int32_t beamNo); +int32_t Phy_SetBeamAngle(PHY_INST *phyInstPtr, double offAx, double rndAx); + +#endif /* PHY_CTRL_H_ */ diff --git a/df_datalink/src/networking/phy_layer/phy_reg.h b/df_datalink/src/networking/phy_layer/phy_reg.h new file mode 100644 index 0000000..3174925 --- /dev/null +++ b/df_datalink/src/networking/phy_layer/phy_reg.h @@ -0,0 +1,338 @@ +/*****************************************************************************/ +/** + * Description: Physical layer register definitions + * + * Author: Fan Hao + * Date: 2021-11-16 00:08 + * LastEditors: Fan Hao + * LastEditTime: 2023-04-24 17:32 + * Revisions: Rev 0.1 + * History: + * [2021-11-16]: Initial version. + * [2022-06-18]: New branch for glink control purpose: + * -Add poll modephysical layer will start Tx/Rx procedure + * at specific time stamp. + * [2023-04-24]: Porting for DUIFEI. + * + * Copyright(c) 2021 Beijing Institute of Technology. + * Lab of Communication and Networking + * + ******************************************************************************/ + +#ifndef PHY_CTRLREG_H_ +#define PHY_CTRLREG_H_ + +/***************************** Include Files *********************************/ +#include "util.h" + +/***************** Macros (Inline Functions) Definitions *********************/ + +// Read Physical Layer register (0x00000000~0x000000FF) +#define PhyRead(instPtr, addr) IO_In32(instPtr->phyCofig.baseAddr + addr) +// Write Physical Layer register (0x000000100~0x00000200) +#define PhyWrite(instPtr, addr, value) IO_Out32(instPtr->phyCofig.baseAddr + addr, value) + +/************************** Constant Definitions *****************************/ +/************************* Ps2Pl Regs PS Write Only ***************************/ +/** + * Register: PHY_MAIN_CTRL + */ +#define PHY_MAIN_CTRL 0X00000000U +#define PHY_MAIN_CTRL_EN_SHIFT 0 +#define PHY_MAIN_CTRL_EN_WIDTH 1 +#define PHY_MAIN_CTRL_EN_MASK 0x00000001U +#define PHY_MAIN_CTRL_MODE_SHIFT 8 +#define PHY_MAIN_CTRL_MODE_WIDTH 8 +#define PHY_MAIN_CTRL_MODE_MASK 0x0000FF00U + +#define PHY_MAIN_CTRL_EN_EN 0x00000001U +#define PHY_MAIN_CTRL_EN_DSBL 0x00000000U +#define PHY_MAIN_CTRL_MODE_NONE 0x00000000U +#define PHY_MAIN_CTRL_MODE_LISTEN 0x00000100U +#define PHY_MAIN_CTRL_MODE_SCHEDULE 0x00000200U +#define PHY_MAIN_CTRL_MODE_PULL 0x00000300U + +/** + * Register: TXRX_CTRL + */ +#define PHY_MODE_CTRL 0x00000004U +#define PHY_MODE_CTRL_TOR_SHIFT 0 +#define PHY_MODE_CTRL_TOR_WIDTH 2 +#define PHY_MODE_CTRL_TOR_MASK 0x00000003U +#define PHY_MODE_CTRL_FRAME_SHIFT 16 +#define PHY_MODE_CTRL_FRAME_WIDTH 8 +#define PHY_MODE_CTRL_FRAME_MASK 0x00FF0000U + +#define PHY_MODE_CTRL_TOR_SUSPEND 0x00000000U +#define PHY_MODE_CTRL_TOR_TX 0x00000001U +#define PHY_MODE_CTRL_TOR_RX 0x00000002U + +#define PHY_MODE_CTRL_FRAME_NONE 0x00000000U +#define PHY_MODE_CTRL_FRAME_2KBPS_20MS 0x00000100U +#define PHY_MODE_CTRL_FRAME_2KBPS_100MS 0x00000200U +#define PHY_MODE_CTRL_FRAME_10KBPS_10MS 0x00000300U // Initial Scan Frame +#define PHY_MODE_CTRL_FRAME_10KBPS_20MS 0x00000400U // Benchmark Frame +#define PHY_MODE_CTRL_FRAME_40KBPS_20MS 0x00000500U +#define PHY_MODE_CTRL_FRAME_40KBPS_10MS 0x00000600U +#define PHY_MODE_CTRL_FRAME_200KBPS_5MS 0x00000700U // 2-Way ACQ Frame, Management Frame, Service Frame +#define PHY_MODE_CTRL_FRAME_1M2BPS_5MS 0x00000800U // Bistatic Synthetic Aperture Radar Frame + +/** + * Register: POLLTIME_L + */ +#define POLLTIME_L 0x00000008U +#define POLLTIME_L_SHIFT 0 +#define POLLTIME_L_WIDTH 32 +#define POLLTIME_L_MASK 0xFFFFFFFFU + +/** + * Register: POLLTIME_H + */ +#define POLLTIME_H 0x0000000CU +#define POLLTIME_H_SHIFT 0 +#define POLLTIME_H_WIDTH 32 +#define POLLTIME_H_MASK 0xFFFFFFFFU + +/** + * Register: TM_ADJ_MODE + */ +#define TM_ADJ_MODE 0x00000010U +#define TM_ADJ_MODE_SHIFT 0 +#define TM_ADJ_MODE_WIDTH 8 +#define TM_ADJ_MODE_MASK 0x000000FFU +#define TM_ADJ_MODE_NONE 0x00000000U +#define TM_ADJ_MODE_ADD 0x00000001U +#define TM_ADJ_MODE_SET 0x00000002U + +#define TM_ADJ_MODE_LOCAL_SHIFT 8 +#define TM_ADJ_MODE_LOCAL_WIDTH 8 +#define TM_ADJ_MODE_LOCAL_MASK 0x0000FF00U +#define TM_ADJ_MODE_LOCAL_NONE 0x00000000U +#define TM_ADJ_MODE_LOCAL_ADD 0x00000100U +#define TM_ADJ_MODE_LOCAL_SET 0x00000200U + +/** + * Register: LOCALTM_ADJ_L + */ +#define LOCALTM_ADJ_L 0x00000014U +#define LOCALTM_ADJ_L_SHIFT 0 +#define LOCALTM_ADJ_L_WIDTH 32 +#define LOCALTM_ADJ_L_MASK 0xFFFFFFFFU + +/** + * Register: LOCALTM_ADJ_H + */ +#define LOCALTM_ADJ_H 0x00000018U +#define LOCALTM_ADJ_H_SHIFT 0 +#define LOCALTM_ADJ_H_WIDTH 32 +#define LOCALTM_ADJ_H_MASK 0xFFFFFFFFU + +/** + * Register: CNT_STEP_TOPT + */ +#define CNT_STEP_OPT 0x0000001CU +#define CNT_STEP_OPT_SHIFT 0 +#define CNT_STEP_OPT_WIDTH 32 +#define CNT_STEP_OPT_MASK 0xFFFFFFFFU + +/** + * Register: SEND_DATA_CMD + */ +#define SEND_DATA_CMD 0x00000020U +#define SEND_DATA_CMD_LEN_SHIFT 0 +#define SEND_DATA_CMD_LEN_WIDTH 16 +#define SEND_DATA_CMD_LEN_MASK 0x0000FFFFU +#define SEND_DATA_CMD_OFFSET_SHIFT 16 +#define SEND_DATA_CMD_OFFSET_WIDTH 16 +#define SEND_DATA_CMD_OFFSET_MASK 0xFFFF0000U + +/** + * Register: ANT_CONFIG_CMD + */ +#define ANT_CONFIG_CMD 0x00000024U +#define ANT_CONFIG_CMD_OFFSET_SHIFT 0 +#define ANT_CONFIG_CMD_OFFSET_WIDTH 16 +#define ANT_CONFIG_CMD_OFFSET_MASK 0x0000FFFFU +#define ANT_CONFIG_CMD_LEN_SHIFT 16 +#define ANT_CONFIG_CMD_LEN_WIDTH 8 +#define ANT_CONFIG_CMD_LEN_MASK 0x00FF0000U +#define ANT_CONFIG_CMD_NUM_SHIFT 24 +#define ANT_CONFIG_CMD_NUM_WIDTH 8 +#define ANT_CONFIG_CMD_NUM_MASK 0xFF000000U + +/** + * Register: SLOT_CONFIG_CMD + */ +#define SLOT_CONFIG_CMD 0x00000028U +#define SLOT_CONFIG_CMD_SHIFT 0 +#define SLOT_CONFIG_CMD_WIDTH 32 +#define SLOT_CONFIG_CMD_MASK 0xFFFFFFFFU +#define SLOT_CONFIG_CMD_VAULE 0x4846414E + +/************************* Ps2Pl Regs PS Read Only ***************************/ +/** + * Register: TXRX_STATE + */ +#define TXRX_STATE 0x00000100U +#define TXRX_STATE_ACQ_SHIFT 0 +#define TXRX_STATE_ACQ_WIDTH 8 +#define TXRX_STATE_ACQ_MASK 0x000000FFU +#define TXRX_STATE_ACQ_SUCCESS 0x00000001U +#define TXRX_STATE_ACQ_FAIL 0x00000002U + +#define TXRX_STATE_FSYNC_SHIFT 8 +#define TXRX_STATE_FSYNC_WIDTH 8 +#define TXRX_STATE_FSYNC_MASK 0x0000FF00U +#define TXRX_STATE_FSYNC_SUCCESS 0x00000100U +#define TXRX_STATE_FSYNC_FAIL 0x00000200U + +#define TXRX_STATE_DECODE_SHIFT 16 +#define TXRX_STATE_DECODE_WIDTH 8 +#define TXRX_STATE_DECODE_MASK 0x00FF0000U +#define TXRX_STATE_DECODE_SUCCESS 0x00010000U +#define TXRX_STATE_DECODE_FAIL 0x00020000U + +/** + * Register: RECV_SATE + */ +#define RECV_DATA_SATE 0x00000104U +#define RECV_DATA_LEN_SHIFT 0 +#define RECV_DATA_LEN_WIDTH 16 +#define RECV_DATA_LEN_MASK 0x0000FFFFU +#define RECV_DATA_OFFSET_SHIFT 16 +#define RECV_DATA_OFFSET_WIDTH 16 +#define RECV_DATA_OFFSET_MASK 0xFFFFF0000U + + +/** + * Register: FSTIME_L + */ +#define FSTIME_L 0x00000108U +#define FSTIME_L_SHIFT 0 +#define FSTIME_L_WIDTH 32 +#define FSTIME_L_MASK 0xFFFFFFFFU + +/** + * Register: FSTIME_INT1 + */ +#define FSTIME_H 0x0000010CU +#define FSTIME_H_SHIFT 0 +#define FSTIME_H_WIDTH 32 +#define FSTIME_H_MASK 0xFFFFFFFFU + +/** + * Register: TM_TARGET_L + */ +#define TM_TARGET_L 0x00000110U +#define TM_TARGET_L_SHIFT 0 +#define TM_TARGET_L_WIDTH 32 +#define TM_TARGET_L_MASK 0xFFFFFFFFU + +/** + * Register: TM_TARGET_H + */ +#define TM_TARGET_H 0x00000114U +#define TM_TARGET_H_SHIFT 0 +#define TM_TARGET_H_WIDTH 32 +#define TM_TARGET_H_MASK 0xFFFFFFFFU + +/** + * Register: LOCALTM_L + */ +#define TM_LOCAL_L 0x00000118U +#define TM_LOCAL_L_SHIFT 0 +#define TM_LOCAL_L_WIDTH 32 +#define TM_LOCAL_L_MASK 0xFFFFFFFFU + +/** + * Register: LOCALTM_H + */ +#define TM_LOCAL_H 0x0000011CU +#define TM_LOCAL_H_SHIFT 0 +#define TM_LOCAL_H_WIDTH 32 +#define TM_LOCAL_H_MASK 0xFFFFFFFFU + +/** + * Register: COASEFREQEST + */ +#define COASE_FREQEST 0x00000120U +#define COASE_FREQEST_SHIFT 0 +#define COASE_FREQEST_WIDTH 32 +#define COASE_FREQEST_MASK 0xFFFFFFFFU + +/** + * Register: INTR_TYPE + */ +#define INTR_TYPE 0x00000124U + + +/** + * Register: ANT_STATUS_0 + */ +#define ANT_STATUS 0x00000128U +#define ANT_STATUS_CODE_SHIFT 0 +#define ANT_STATUS_CODE_WIDTH 8 +#define ANT_STATUS_CODE_MASK 0x000000FFU +#define ANT_STATUS_NIL_VOLT_SHIFT 8 +#define ANT_STATUS_NIL_VOLT_WIDTH 8 +#define ANT_STATUS_NIL_VOLT_MASK 0x0000FF00U +#define ANT_STATUS_RF_VOLT_SHIFT 16 +#define ANT_STATUS_RF_VOLT_WIDTH 8 +#define ANT_STATUS_RF_VOLT_MASK 0x00FF0000U +#define ANT_STATUS_ANT_VOLT_SHIFT 24 +#define ANT_STATUS_ANT_VOLT_WIDTH 8 +#define ANT_STATUS_ANT_VOLT_MASK 0xFF000000U + + +/** + * Register: ANT_FRAME_CNT + */ +#define ANT_FRAME_CNT 0x0000012CU +#define ANT_FRAME_CNT_SHIFT 0 +#define ANT_FRAME_CNT_WIDTH 32 +#define ANT_FRAME_CNT_MASK 0xFFFFFFFFU + +/** + * Register: RF_STATUS + */ +#define RF_STATUS 0x00000130U +#define RF_STATUS_TEMP_SHIFT 0 +#define RF_STATUS_TEMP_WIDTH 8 +#define RF_STATUS_TEMP_MASK 0x000000FFU +#define RF_STATUS_BDLOCK_SHIFT 8 +#define RF_STATUS_BDLOCK_WIDTH 8 +#define RF_STATUS_BDLOCK_MASK 0x0000FF00U +#define RF_STATUS_PLLA_SHIFT 16 +#define RF_STATUS_PLLA_WIDTH 8 +#define RF_STATUS_PLLA_MASK 0x00FF0000U +#define RF_STATUS_PLLB_SHIFT 24 +#define RF_STATUS_PLLB_WIDTH 8 +#define RF_STATUS_PLLB_MASK 0xFF000000U + +/** + * Register: RF_MGC + */ +#define RF_MGC 0x00000134U +#define RF_MGC_CH1_SHIFT 0 +#define RF_MGC_CH1_WIDTH 4 +#define RF_MGC_CH1_MASK 0x0000000FU +#define RF_MGC_CH2_SHIFT 8 +#define RF_MGC_CH2_WIDTH 4 +#define RF_MGC_CH2_MASK 0x00000F00U +#define RF_MGC_CH3_SHIFT 16 +#define RF_MGC_CH3_WIDTH 4 +#define RF_MGC_CH3_MASK 0x000F0000U +#define RF_MGC_CH4_SHIFT 24 +#define RF_MGC_CH4_WIDTH 4 +#define RF_MGC_CH4_MASK 0x0F000000U + + +/** + * Register: RF_FRAME_CNT + */ +#define RF_FRAME_CNT 0x00000138U +#define RF_FRAME_CNT_SHIFT 0 +#define RF_FRAME_CNT_WIDTH 32 +#define RF_FRAME_CNT_MASK 0xFFFFFFFFU + +#endif /* PHY_CTRLREG_H_ */ diff --git a/df_datalink/src/system_monitor.c b/df_datalink/src/system_monitor.c new file mode 100644 index 0000000..6c3f31f --- /dev/null +++ b/df_datalink/src/system_monitor.c @@ -0,0 +1,593 @@ +#include +#include +#include +#include "common.h" +#include "system_monitor.h" + +#define BUFF_A 0x00 +#define BUFF_B 0x01 +#define BUFF_NONE 0xFF + +#define SYSINFO_PACK_LEN 54 // bytes +#define PAYLOAD_PACK_LEN 46 // bytes +#define SLOTLOG_PACK_LEN 88 // bytes +#define PRTCLLOG_PACK_ELN 24 // bytes +#define HWSTATE_PACK_ELN 12 // bytes + +typedef struct{ + int8_t latest; + int8_t rBusy; + int8_t wBusy; +} PINGPONG; + +typedef struct{ + PINGPONG recvPLCtrl; + PAYLOAD recvPL[2]; + PINGPONG sendPLCtrl; + PAYLOAD sendPL[2]; + PINGPONG sysInfoCtrl; + SYSINFO sysInfo[2]; + PINGPONG sendLogCtrl; + SLOTLOG sendLog[2]; + PINGPONG recvLogCtrl; + SLOTLOG recvLog[2]; + PINGPONG protocolLogCtrl; + PRTCLLOG protocolLog[2]; + PINGPONG hwStateCtrl; + HWSTATE hwState[2]; +} SYSMONITOR; + +static SYSMONITOR *sysMonitorInst; + +uint8_t GetWritable(PINGPONG ctrllor); +uint8_t GetReadable(PINGPONG ctrllor); + +inline uint8_t GetWritable(PINGPONG ctrllor) { + ASSERT(ctrllor.wBusy !=BUFF_NONE); + if (ctrllor.rBusy == BUFF_NONE) + return ((ctrllor.latest == BUFF_B) ? BUFF_A : BUFF_B); + else + return ((ctrllor.rBusy == BUFF_B) ? BUFF_A : BUFF_B); +} + +inline uint8_t GetReadable(PINGPONG ctrllor) { + if (ctrllor.wBusy == BUFF_NONE || ctrllor.wBusy != ctrllor.latest) + return ctrllor.latest; + else + return ((ctrllor.wBusy == BUFF_B) ? BUFF_A : BUFF_B); +} + +// System monitor initialise +int32_t SysMonitor_Init(void){ + sysMonitorInst = calloc(1, sizeof(SYSMONITOR)); + if (sysMonitorInst == NULL) { + return ENOMEM; + } + memset(&(sysMonitorInst->recvPLCtrl), BUFF_NONE, sizeof(PINGPONG)); + memset(&(sysMonitorInst->sendPLCtrl), BUFF_NONE, sizeof(PINGPONG)); + memset(&(sysMonitorInst->sysInfoCtrl), BUFF_NONE, sizeof(PINGPONG)); + memset(&(sysMonitorInst->sendLogCtrl), BUFF_NONE, sizeof(PINGPONG)); + memset(&(sysMonitorInst->recvLogCtrl), BUFF_NONE, sizeof(PINGPONG)); + memset(&(sysMonitorInst->protocolLogCtrl), BUFF_NONE, sizeof(PINGPONG)); + memset(&(sysMonitorInst->hwStateCtrl), BUFF_NONE, sizeof(PINGPONG)); + return SUCCESS; +} + +// @System Info +void SysMonitor_UpdateSysinfo(SYSINFO *info) { + uint8_t buffIndx; + buffIndx = GetWritable(sysMonitorInst->sysInfoCtrl); + sysMonitorInst->sysInfoCtrl.wBusy = buffIndx; + memcpy(&(sysMonitorInst->sysInfo[buffIndx]), info, sizeof(SYSINFO)); + sysMonitorInst->sysInfoCtrl.latest = buffIndx; + sysMonitorInst->sysInfoCtrl.wBusy = BUFF_NONE; +} + +void SysMonitor_UpdateSysinfoRaw(uint8_t *buff){ + ASSERT(sysMonitorInst != NULL); + uint8_t buffIndx; + buffIndx = GetWritable(sysMonitorInst->sysInfoCtrl); + sysMonitorInst->sysInfoCtrl.wBusy = buffIndx; + // Decapsulate Systeminfo + SYSINFO *infoEntry = &(sysMonitorInst->sysInfo[buffIndx]); + memcpy(&(infoEntry->psBDS), buff, sizeof(infoEntry->psBDS)); + buff += sizeof(infoEntry->psBDS); + memcpy(&(infoEntry->pBDS), buff, sizeof(infoEntry->pBDS)); + buff += sizeof(infoEntry->pBDS); + memcpy(&(infoEntry->psGPS), buff, sizeof(infoEntry->psGPS)); + buff += sizeof(infoEntry->psGPS); + memcpy(&(infoEntry->pGPS), buff, sizeof(infoEntry->pGPS)); + buff += sizeof(infoEntry->pGPS); + memcpy(&(infoEntry->tmInd), buff, sizeof(infoEntry->tmInd)); + buff += sizeof(infoEntry->tmInd); + memcpy(&(infoEntry->tmFly), buff, sizeof(infoEntry->tmFly)); + buff += sizeof(infoEntry->tmFly); + memcpy(&(infoEntry->stFly), buff, sizeof(infoEntry->stFly)); + buff += sizeof(infoEntry->stFly); + memcpy(&(infoEntry->posX), buff, sizeof(infoEntry->posX)); + buff += sizeof(infoEntry->posX); + memcpy(&(infoEntry->posY), buff, sizeof(infoEntry->posY)); + buff += sizeof(infoEntry->posY); + memcpy(&(infoEntry->posZ), buff, sizeof(infoEntry->posZ)); + buff += sizeof(infoEntry->posZ); + memcpy(&(infoEntry->vX), buff, sizeof(infoEntry->vX)); + buff += sizeof(infoEntry->vX); + memcpy(&(infoEntry->vY), buff, sizeof(infoEntry->vY)); + buff += sizeof(infoEntry->vY); + memcpy(&(infoEntry->vZ), buff, sizeof(infoEntry->vZ)); + buff += sizeof(infoEntry->vZ); + memcpy(&(infoEntry->pitch), buff, sizeof(infoEntry->pitch)); + buff += sizeof(infoEntry->pitch); + memcpy(&(infoEntry->yaw), buff, sizeof(infoEntry->yaw)); + buff += sizeof(infoEntry->yaw); + memcpy(&(infoEntry->roll), buff, sizeof(infoEntry->roll)); + sysMonitorInst->sysInfoCtrl.latest = buffIndx; + sysMonitorInst->sysInfoCtrl.wBusy = BUFF_NONE; +} + +void SysMonitor_GetSysinfo(SYSINFO *info){ + ASSERT(sysMonitorInst != NULL); + uint8_t buffIndx, buffIndex_old; + buffIndex_old = sysMonitorInst->sysInfoCtrl.rBusy; + if (buffIndex_old != BUFF_NONE) + buffIndx = buffIndex_old; // Keep it busy + else + buffIndx = GetReadable(sysMonitorInst->sysInfoCtrl); + sysMonitorInst->sysInfoCtrl.rBusy = buffIndx; + memcpy(info, &(sysMonitorInst->sysInfo[buffIndx]), sizeof(SYSINFO)); + sysMonitorInst->sysInfoCtrl.rBusy = buffIndex_old; +} + +void SysMonitor_GetSysinfoRaw(uint8_t *buff) { + uint8_t buffIndx, buffIndex_old; + buffIndex_old = sysMonitorInst->sysInfoCtrl.rBusy; + if (buffIndex_old != BUFF_NONE) + buffIndx = buffIndex_old; // Keep it busy + else + buffIndx = GetReadable(sysMonitorInst->sysInfoCtrl); + sysMonitorInst->sysInfoCtrl.rBusy = buffIndx; + + // Encapsulate Systeminfo + SYSINFO *infoEntry = &(sysMonitorInst->sysInfo[buffIndx]); + memcpy(buff, &(infoEntry->psBDS), sizeof(infoEntry->psBDS)); + buff += sizeof(infoEntry->psBDS); + memcpy(buff, &(infoEntry->pBDS), sizeof(infoEntry->pBDS)); + buff += sizeof(infoEntry->pBDS); + memcpy(buff, &(infoEntry->psGPS), sizeof(infoEntry->psGPS)); + buff += sizeof(infoEntry->psGPS); + memcpy(buff, &(infoEntry->pGPS), sizeof(infoEntry->pGPS)); + buff += sizeof(infoEntry->pGPS); + memcpy(buff, &(infoEntry->tmInd), sizeof(infoEntry->tmInd)); + buff += sizeof(infoEntry->tmInd); + memcpy(buff, &(infoEntry->tmFly), sizeof(infoEntry->tmFly)); + buff += sizeof(infoEntry->tmFly); + memcpy(buff, &(infoEntry->stFly), sizeof(infoEntry->stFly)); + buff += sizeof(infoEntry->stFly); + memcpy(buff, &(infoEntry->posX), sizeof(infoEntry->posX)); + buff += sizeof(infoEntry->posX); + memcpy(buff, &(infoEntry->posY), sizeof(infoEntry->posY)); + buff += sizeof(infoEntry->posY); + memcpy(buff, &(infoEntry->posZ), sizeof(infoEntry->posZ)); + buff += sizeof(infoEntry->posZ); + memcpy(buff, &(infoEntry->vX), sizeof(infoEntry->vX)); + buff += sizeof(infoEntry->vX); + memcpy(buff, &(infoEntry->vY), sizeof(infoEntry->vY)); + buff += sizeof(infoEntry->vY); + memcpy(buff, &(infoEntry->vZ), sizeof(infoEntry->vZ)); + buff += sizeof(infoEntry->vZ); + memcpy(buff, &(infoEntry->pitch), sizeof(infoEntry->pitch)); + buff += sizeof(infoEntry->pitch); + memcpy(buff, &(infoEntry->yaw), sizeof(infoEntry->yaw)); + buff += sizeof(infoEntry->yaw); + memcpy(buff, &(infoEntry->roll), sizeof(infoEntry->roll)); + sysMonitorInst->sysInfoCtrl.rBusy = buffIndex_old; +} +// @Send Payload +/** + * Update send FLJ payload by raw data. + */ +void SysMonitor_UpdateSendPayloadFLJRaw(uint8_t *buff){ + ASSERT(sysMonitorInst != NULL); + uint8_t buffIndx; + buffIndx = GetWritable(sysMonitorInst->sendPLCtrl); + sysMonitorInst->sendPLCtrl.wBusy = buffIndx; + memcpy(sysMonitorInst->sendPL[buffIndx].data_flj, buff, sizeof(uint8_t)*PAYLOAD_FLJ); + sysMonitorInst->sendPLCtrl.latest = buffIndx; + sysMonitorInst->sendPLCtrl.wBusy = BUFF_NONE; +} + +/** + * Get send FLJ payload as raw data. + */ +void SysMonitor_GetSendPayloadFLJRaw(uint8_t *buff) { + ASSERT(sysMonitorInst != NULL); + uint8_t buffIndx, buffIndex_old; + buffIndex_old = sysMonitorInst->sendPLCtrl.rBusy; + if (buffIndex_old != BUFF_NONE) + buffIndx = buffIndex_old; // Keep it busy + else + buffIndx = GetReadable(sysMonitorInst->sendPLCtrl); + sysMonitorInst->sendPLCtrl.rBusy = buffIndx; + memcpy(buff, sysMonitorInst->sendPL[buffIndx].data_flj, sizeof(uint8_t)*PAYLOAD_FLJ); + sysMonitorInst->sendPLCtrl.rBusy = buffIndex_old; +} + +/** + * Update LJ send payload by raw data. + */ +void SysMonitor_UpdateSendPayloadLJRaw(uint8_t *buff){ + ASSERT(sysMonitorInst != NULL); + uint8_t buffIndx; + buffIndx = GetWritable(sysMonitorInst->sendPLCtrl); + sysMonitorInst->sendPLCtrl.wBusy = buffIndx; + memcpy(sysMonitorInst->sendPL[buffIndx].data_lj, buff, sizeof(uint8_t)*PAYLOAD_LJ); + sysMonitorInst->sendPLCtrl.latest = buffIndx; + sysMonitorInst->sendPLCtrl.wBusy = BUFF_NONE; +} + +/** + * Get send LJ payload as raw data. + */ +void SysMonitor_GetSendPayloadLJRaw(uint8_t *buff) { + ASSERT(sysMonitorInst != NULL); + uint8_t buffIndx, buffIndex_old; + buffIndex_old = sysMonitorInst->sendPLCtrl.rBusy; + if (buffIndex_old != BUFF_NONE) + buffIndx = buffIndex_old; // Keep it busy + else + buffIndx = GetReadable(sysMonitorInst->sendPLCtrl); + sysMonitorInst->sendPLCtrl.rBusy = buffIndx; + memcpy(buff, sysMonitorInst->sendPL[buffIndx].data_lj, sizeof(uint8_t)*PAYLOAD_LJ); + sysMonitorInst->sendPLCtrl.rBusy = buffIndex_old; +} + +// @Receive Payload +/** + * Update receive FLJ payload by raw data. + */ +void SysMonitor_UpdateRecvPayloadFLJRaw(uint8_t *buff){ + ASSERT(sysMonitorInst != NULL); + uint8_t buffIndx; + buffIndx = GetWritable(sysMonitorInst->recvPLCtrl); + sysMonitorInst->recvPLCtrl.wBusy = buffIndx; + memcpy(sysMonitorInst->recvPL[buffIndx].data_flj, buff, sizeof(uint8_t)*PAYLOAD_FLJ); + sysMonitorInst->recvPLCtrl.latest = buffIndx; + sysMonitorInst->recvPLCtrl.wBusy = BUFF_NONE; +} + +/** + * Get send FLJ payload as raw data. + */ +void SysMonitor_GetRecvPayloadFLJRaw(uint8_t *buff){ + ASSERT(sysMonitorInst != NULL); + uint8_t buffIndx, buffIndex_old; + buffIndex_old = sysMonitorInst->recvPLCtrl.rBusy; + if (buffIndex_old != BUFF_NONE) + buffIndx = buffIndex_old; // Keep it busy + else + buffIndx = GetReadable(sysMonitorInst->recvPLCtrl); + sysMonitorInst->recvPLCtrl.rBusy = buffIndx; + memcpy(buff, sysMonitorInst->recvPL[buffIndx].data_flj, sizeof(uint8_t)*PAYLOAD_FLJ); + sysMonitorInst->recvPLCtrl.rBusy = buffIndex_old; +} + +/** + * Update receive LJ payload by raw data. + */ +void SysMonitor_UpdateRecvPayloadLJRaw(uint8_t *buff){ + ASSERT(sysMonitorInst != NULL); + uint8_t buffIndx; + buffIndx = GetWritable(sysMonitorInst->recvPLCtrl); + sysMonitorInst->recvPLCtrl.wBusy = buffIndx; + memcpy(sysMonitorInst->recvPL[buffIndx].data_lj, buff, sizeof(uint8_t)*PAYLOAD_LJ); + sysMonitorInst->recvPLCtrl.latest = buffIndx; + sysMonitorInst->recvPLCtrl.wBusy = BUFF_NONE; +} + +/** + * Get send LJ payload as raw data. + */ +void SysMonitor_GetRecvPayloadLJRaw(uint8_t *buff){ + ASSERT(sysMonitorInst != NULL); + uint8_t buffIndx, buffIndex_old; + buffIndex_old = sysMonitorInst->recvPLCtrl.rBusy; + if (buffIndex_old != BUFF_NONE) + buffIndx = buffIndex_old; // Keep it busy + else + buffIndx = GetReadable(sysMonitorInst->recvPLCtrl); + sysMonitorInst->recvPLCtrl.rBusy = buffIndx; + memcpy(buff, sysMonitorInst->recvPL[buffIndx].data_lj, sizeof(uint8_t)*PAYLOAD_LJ); + sysMonitorInst->recvPLCtrl.rBusy = buffIndex_old; +} + +// @Send Slot log +/** + * Log send slot information + */ +void SysMonitor_UpdateSendSlotLog(SLOTLOG *log){ + ASSERT(sysMonitorInst != NULL); + uint8_t buffIndx; + buffIndx = GetWritable(sysMonitorInst->sendLogCtrl); + sysMonitorInst->sendLogCtrl.wBusy = buffIndx; + memcpy(&(sysMonitorInst->sendLog[buffIndx]), log, sizeof(SLOTLOG)); + sysMonitorInst->sendLogCtrl.latest = buffIndx; + sysMonitorInst->sendLogCtrl.wBusy = BUFF_NONE; +} + +/** + * Get the latest send slot log + */ +void SysMonitor_GetSendSlotLog(SLOTLOG *log){ + ASSERT(sysMonitorInst != NULL); + uint8_t buffIndx, buffIndex_old; + buffIndex_old = sysMonitorInst->sendLogCtrl.rBusy; + if (buffIndex_old != BUFF_NONE) + buffIndx = buffIndex_old; // Keep it busy + else + buffIndx = GetReadable(sysMonitorInst->sendLogCtrl); + sysMonitorInst->sendLogCtrl.rBusy = buffIndx; + memcpy(log, &(sysMonitorInst->sendLog[buffIndx]), sizeof(SLOTLOG)); + sysMonitorInst->sendLogCtrl.rBusy = buffIndex_old; +} + +/** + * Get the latest send slot log as raw data + */ +void SysMonitor_GetSendSlotLogRaw(uint8_t *buff){ + ASSERT(sysMonitorInst != NULL); + uint8_t buffIndx, buffIndex_old; + buffIndex_old = sysMonitorInst->sendLogCtrl.rBusy; + if (buffIndex_old != BUFF_NONE) + buffIndx = buffIndex_old; // Keep it busy + else + buffIndx = GetReadable(sysMonitorInst->sendLogCtrl); + sysMonitorInst->sendLogCtrl.rBusy = buffIndx; + + // Encapsulate log + SLOTLOG *logEntry = &(sysMonitorInst->sendLog[buffIndx]); + memcpy(buff, &(logEntry->tuNo), sizeof(logEntry->tuNo)); + buff += sizeof(logEntry->tuNo); + memcpy(buff, &(logEntry->slotNo), sizeof(logEntry->slotNo)); + buff += sizeof(logEntry->slotNo); + memcpy(buff, &(logEntry->frameType), sizeof(logEntry->frameType)); + buff += sizeof(logEntry->frameType); + memcpy(buff, &(logEntry->srcId), sizeof(logEntry->srcId)); + buff += sizeof(logEntry->srcId); + memcpy(buff, &(logEntry->dstId), sizeof(logEntry->dstId)); + buff += sizeof(logEntry->dstId); + memcpy(buff, &(logEntry->baseInfo), sizeof(logEntry->baseInfo)); + buff += sizeof(logEntry->baseInfo); + memcpy(buff, &(logEntry->payload), sizeof(logEntry->payload)); + buff += sizeof(logEntry->payload); + memcpy(buff, &(logEntry->tmStamp), sizeof(logEntry->tmStamp)); + buff += sizeof(logEntry->tmStamp); + memcpy(buff, &(logEntry->tmDevi), sizeof(logEntry->tmDevi)); + buff += sizeof(logEntry->tmDevi); + memcpy(buff, &(logEntry->freqDevi), sizeof(logEntry->freqDevi)); + sysMonitorInst->sendLogCtrl.rBusy = buffIndex_old; +} + +// @Receive Slot log +/** + * Log receive slot information + */ +void SysMonitor_UpdateRecvSlotLog(SLOTLOG *log){ + ASSERT(sysMonitorInst != NULL); + uint8_t buffIndx; + buffIndx = GetWritable(sysMonitorInst->recvLogCtrl); + sysMonitorInst->recvLogCtrl.wBusy = buffIndx; + memcpy(&(sysMonitorInst->recvLog[buffIndx]), log, sizeof(SLOTLOG)); + sysMonitorInst->recvLogCtrl.latest = buffIndx; + sysMonitorInst->recvLogCtrl.wBusy = BUFF_NONE; +} + +/** + * Get the latest receive slot information + */ +void SysMonitor_GetRecvSlotLog(SLOTLOG *log){ + ASSERT(sysMonitorInst != NULL); + uint8_t buffIndx, buffIndex_old; + buffIndex_old = sysMonitorInst->recvLogCtrl.rBusy; + if (buffIndex_old != BUFF_NONE) + buffIndx = buffIndex_old; // Keep it busy + else + buffIndx = GetReadable(sysMonitorInst->recvLogCtrl); + sysMonitorInst->recvLogCtrl.rBusy = buffIndx; + memcpy(log, &(sysMonitorInst->recvLog[buffIndx]), sizeof(SLOTLOG)); + sysMonitorInst->recvLogCtrl.rBusy = buffIndex_old; +} + +/** + * Get the latest receive slot information as raw data + */ +void SysMonitor_GetRecvSlotLogRaw(uint8_t *buff) { + ASSERT(sysMonitorInst != NULL); + uint8_t buffIndx, buffIndex_old; + buffIndex_old = sysMonitorInst->recvLogCtrl.rBusy; + if (buffIndex_old != BUFF_NONE) + buffIndx = buffIndex_old; // Keep it busy + else + buffIndx = GetReadable(sysMonitorInst->recvLogCtrl); + sysMonitorInst->recvLogCtrl.rBusy = buffIndx; + + // Encapsulate log + SLOTLOG *logEntry = &(sysMonitorInst->recvLog[buffIndx]); + memcpy(buff, &(logEntry->tuNo), sizeof(logEntry->tuNo)); + buff += sizeof(logEntry->tuNo); + memcpy(buff, &(logEntry->slotNo), sizeof(logEntry->slotNo)); + buff += sizeof(logEntry->slotNo); + memcpy(buff, &(logEntry->frameType), sizeof(logEntry->frameType)); + buff += sizeof(logEntry->frameType); + memcpy(buff, &(logEntry->srcId), sizeof(logEntry->srcId)); + buff += sizeof(logEntry->srcId); + memcpy(buff, &(logEntry->dstId), sizeof(logEntry->dstId)); + buff += sizeof(logEntry->dstId); + memcpy(buff, &(logEntry->baseInfo), sizeof(logEntry->baseInfo)); + buff += sizeof(logEntry->baseInfo); + memcpy(buff, &(logEntry->payload), sizeof(logEntry->payload)); + buff += sizeof(logEntry->payload); + memcpy(buff, &(logEntry->tmStamp), sizeof(logEntry->tmStamp)); + buff += sizeof(logEntry->tmStamp); + memcpy(buff, &(logEntry->tmDevi), sizeof(logEntry->tmDevi)); + buff += sizeof(logEntry->tmDevi); + memcpy(buff, &(logEntry->freqDevi), sizeof(logEntry->freqDevi)); + sysMonitorInst->recvLogCtrl.rBusy = buffIndex_old; +} + +// @Protocol log +/** + * Log protocol running status. + */ +void SysMonitor_UpdateProtocolLog(PRTCLLOG *log){ + ASSERT(sysMonitorInst != NULL); + uint8_t buffIndx; + buffIndx = GetWritable(sysMonitorInst->protocolLogCtrl); + sysMonitorInst->protocolLogCtrl.wBusy = buffIndx; + memcpy(&(sysMonitorInst->protocolLog[buffIndx]), log, sizeof(PRTCLLOG)); + sysMonitorInst->protocolLogCtrl.latest = buffIndx; + sysMonitorInst->protocolLogCtrl.wBusy = BUFF_NONE; +} + +/** + * Get the protocol running log. + */ +void SysMonitor_GetProtocolLog(PRTCLLOG *log){ + ASSERT(sysMonitorInst != NULL); + uint8_t buffIndx, buffIndex_old; + buffIndex_old = sysMonitorInst->protocolLogCtrl.rBusy; + if (buffIndex_old != BUFF_NONE) + buffIndx = buffIndex_old; // Keep it busy + else + buffIndx = GetReadable(sysMonitorInst->protocolLogCtrl); + sysMonitorInst->protocolLogCtrl.rBusy = buffIndx; + memcpy(log, &(sysMonitorInst->protocolLog[buffIndx]), sizeof(PRTCLLOG)); + sysMonitorInst->protocolLogCtrl.rBusy = buffIndex_old; +} + +/** + * Get the protocol running log as raw data. + */ +void SysMonitor_GetProtocolLogRaw(uint8_t *buff){ + ASSERT(sysMonitorInst != NULL); + uint8_t buffIndx, buffIndex_old; + buffIndex_old = sysMonitorInst->protocolLogCtrl.rBusy; + if (buffIndex_old != BUFF_NONE) + buffIndx = buffIndex_old; // Keep it busy + else + buffIndx = GetReadable(sysMonitorInst->protocolLogCtrl); + sysMonitorInst->protocolLogCtrl.rBusy = buffIndx; + + // Encapsulate log + PRTCLLOG *logEntry = &(sysMonitorInst->protocolLog[buffIndx]); + memcpy(buff, &(logEntry->tmSys), sizeof(logEntry->tmSys)); + buff += sizeof(logEntry->tmSys); + memcpy(buff, &(logEntry->phySt), sizeof(logEntry->phySt)); + buff += sizeof(logEntry->phySt); + memcpy(buff, &(logEntry->tmLocal), sizeof(logEntry->tmLocal)); + buff += sizeof(logEntry->tmLocal); + memcpy(buff, &(logEntry->beamNo), sizeof(logEntry->beamNo)); + buff += sizeof(logEntry->beamNo); + memcpy(buff, &(logEntry->beamWidth), sizeof(logEntry->beamWidth)); + buff += sizeof(logEntry->beamWidth); + memcpy(buff, &(logEntry->stage), sizeof(logEntry->stage)); + buff += sizeof(logEntry->stage); + memcpy(buff, &(logEntry->recvCnt), sizeof(logEntry->recvCnt)); + buff += sizeof(logEntry->recvCnt); + memcpy(buff, &(logEntry->recvFineCnt), sizeof(logEntry->recvFineCnt)); + buff += sizeof(logEntry->recvFineCnt); + memcpy(buff, &(logEntry->nodeCnt), sizeof(logEntry->nodeCnt)); + buff += sizeof(logEntry->nodeCnt); + memcpy(buff, &(logEntry->myId), sizeof(logEntry->myId)); + buff += sizeof(logEntry->myId); + memcpy(buff, &(logEntry->dstId), sizeof(logEntry->dstId)); + sysMonitorInst->protocolLogCtrl.rBusy = buffIndex_old; +} + +// @Hardware state +/** + * Log hardware running status. + */ +void SysMonitor_UpdateHardwareStatus(HWSTATE *state){ + ASSERT(sysMonitorInst != NULL); + uint8_t buffIndx; + buffIndx = GetWritable(sysMonitorInst->hwStateCtrl); + sysMonitorInst->hwStateCtrl.wBusy = buffIndx; + memcpy(&(sysMonitorInst->hwState[buffIndx]), state, sizeof(HWSTATE)); + sysMonitorInst->hwStateCtrl.latest = buffIndx; + sysMonitorInst->hwStateCtrl.wBusy = BUFF_NONE; +} + +/** + * Get the latest hardware running status. + */ +void SysMonitor_GetHardwareStatus(HWSTATE *state){ + ASSERT(sysMonitorInst != NULL); + uint8_t buffIndx, buffIndex_old; + buffIndex_old = sysMonitorInst->hwStateCtrl.rBusy; + if (buffIndex_old != BUFF_NONE) + buffIndx = buffIndex_old; // Keep it busy + else + buffIndx = GetReadable(sysMonitorInst->hwStateCtrl); + sysMonitorInst->hwStateCtrl.rBusy = buffIndx; + memcpy(state, &(sysMonitorInst->hwState[buffIndx]), sizeof(HWSTATE)); + sysMonitorInst->hwStateCtrl.rBusy = buffIndex_old; +} + +/** + * Get the latest hardware running status as raw data. + */ +void SysMonitor_GetHardwareStatusRaw(uint8_t *buff){ + ASSERT(sysMonitorInst != NULL); + uint8_t buffIndx, buffIndex_old; + buffIndex_old = sysMonitorInst->hwStateCtrl.rBusy; + if (buffIndex_old != BUFF_NONE) + buffIndx = buffIndex_old; // Keep it busy + else + buffIndx = GetReadable(sysMonitorInst->hwStateCtrl); + sysMonitorInst->hwStateCtrl.rBusy = buffIndx; + + // Encapsulate state + HWSTATE *stateEntry = &(sysMonitorInst->hwState[buffIndx]); + memcpy(buff, &(stateEntry->spVolt), sizeof(stateEntry->spVolt)); + buff += sizeof(stateEntry->spVolt); + memcpy(buff, &(stateEntry->spTemp), sizeof(stateEntry->spTemp)); + buff += sizeof(stateEntry->spTemp); + memcpy(buff, &(stateEntry->chipSt), sizeof(stateEntry->chipSt)); + buff += sizeof(stateEntry->chipSt); + memcpy(buff, &(stateEntry->antVolt), sizeof(stateEntry->antVolt)); + buff += sizeof(stateEntry->antVolt); + memcpy(buff, &(stateEntry->antTemp), sizeof(stateEntry->antTemp)); + buff += sizeof(stateEntry->antTemp); + memcpy(buff, &(stateEntry->antPll), sizeof(stateEntry->antPll)); + buff += sizeof(stateEntry->antPll); + memcpy(buff, &(stateEntry->antMgc), sizeof(stateEntry->antMgc)); + buff += sizeof(stateEntry->antMgc); + memcpy(buff, &(stateEntry->antSt), sizeof(stateEntry->antSt)); + sysMonitorInst->hwStateCtrl.rBusy = buffIndex_old; +} + +// @System log +/** + * Get the latest system running log. + */ +void SysMonitor_GetSyslog(SYSLOG *log){ + ASSERT(sysMonitorInst != NULL); + SysMonitor_GetSendSlotLog(&(log->sendLog)); + SysMonitor_GetRecvSlotLog(&(log->recvLog)); + SysMonitor_GetProtocolLog(&(log->protocolLog)); + SysMonitor_GetHardwareStatus(&(log->hwSate)); +} + +/** + * Get the latest system running log as raw data. + */ +void SysMonitor_GetSyslogRaw(uint8_t *buff){ + ASSERT(sysMonitorInst != NULL); + SysMonitor_GetSendSlotLogRaw(buff); + buff += SLOTLOG_PACK_LEN; + SysMonitor_GetRecvSlotLogRaw(buff); + buff += SLOTLOG_PACK_LEN; + SysMonitor_GetProtocolLogRaw(buff); + buff += PRTCLLOG_PACK_ELN; + SysMonitor_GetHardwareStatusRaw(buff); +} diff --git a/df_datalink/src/system_monitor.h b/df_datalink/src/system_monitor.h new file mode 100644 index 0000000..d4289fd --- /dev/null +++ b/df_datalink/src/system_monitor.h @@ -0,0 +1,155 @@ +#ifndef __SYSTEM_MONITOR_H_ +#define __SYSTEM_MONITOR_H_ + + +#include +#include + + +# define PAYLOAD_FLJ 78 +# define PAYLOAD_LJ 156 + +typedef struct{ +// FIXME: To Complete +} SYSCONFIG; + +typedef struct{ + // -- unit: ms, 0~604799999 + uint32_t psBDS; + // -- unit: week, 0~0~8191 + uint16_t pBDS; + // -- unit: ms, 0~604799999 + uint32_t psGPS; + // -- unit: week, 0~0~8191 + uint16_t pGPS; + // Time validation indicator + // -- [0] GPS + // -- [1] reserve. + // -- [2] UTC + // -- [3] BDS + uint8_t tmInd; + // Time of flying + // uint: s + float tmFly; + // Status of flying + // [7:6] departure status 11 - departed/00 - not departed + // [5:4] ready status 11 - ready/00 - not ready + // [3:2] attitude status 11 - attitude ok/00 - attitude not ok + // [1:0] attitude adjust status 11 - adjusted/00 - not adjusted + uint8_t stFly; + // Position in launch coordinate system + float posX; + float posY; + float posZ; + // Speed in launch coordinate system + float vX; + float vY; + float vZ; + // Attitude in launch inertia coordinate system + float pitch; + float yaw; + float roll; +} SYSINFO; + +typedef struct{ + uint8_t data_lj[PAYLOAD_LJ]; + uint8_t data_flj[PAYLOAD_FLJ]; +} PAYLOAD; + +typedef struct{ + // Network log + uint32_t tuNo; + uint8_t slotNo; + uint8_t frameType; + uint8_t srcId; + uint8_t dstId; + uint8_t baseInfo[18]; + // Payload + uint8_t payload[46]; + // Time sync info + uint64_t tmStamp; + uint32_t tmDevi; + uint32_t freqDevi; +} SLOTLOG; + +typedef struct{ + // Protocol log + // -- System time + uint32_t tmSys; + // -- Physical layer status + uint8_t phySt; + // -- Link layer status + uint32_t tmLocal; + uint16_t beamNo; + uint8_t beamWidth; + // -- Network layer status + uint8_t stage; + uint32_t recvCnt; + uint32_t recvFineCnt; + uint8_t nodeCnt; + uint8_t myId; + uint8_t dstId; +} PRTCLLOG; + +typedef struct{ + // Hardware log + // -- Signal processor status + uint16_t spVolt; + uint16_t spTemp; + uint16_t chipSt; + // -- Antenna status + uint8_t antVolt; + uint8_t antTemp; + uint8_t antPll; + uint16_t antMgc; + uint8_t antSt; +} HWSTATE; + +typedef struct{ + // Send slot log + SLOTLOG sendLog; + + // Receive slot log + SLOTLOG recvLog; + + // Protocol log + PRTCLLOG protocolLog; + + // Hardware status + HWSTATE hwSate; +} SYSLOG; + +int32_t SysMonitor_Init(void); + +void SysMonitor_UpdateSysinfo(SYSINFO *info); +void SysMonitor_UpdateSysinfoRaw(uint8_t *buff); +void SysMonitor_GetSysinfo(SYSINFO *info); +void SysMonitor_GetSysinfoRaw(uint8_t *buff); + +void SysMonitor_UpdateSendPayloadFLJRaw(uint8_t *buff); +void SysMonitor_UpdateRecvPayloadFLJRaw(uint8_t *buff); +void SysMonitor_UpdateSendPayloadLJRaw(uint8_t *buff); +void SysMonitor_UpdateRecvPayloadLJRaw(uint8_t *buff); +void SysMonitor_GetSendPayloadFLJRaw(uint8_t *buff); +void SysMonitor_GetRecvPayloadFLJRaw(uint8_t *buff); +void SysMonitor_GetSendPayloadLJRaw(uint8_t *buff); +void SysMonitor_GetRecvPayloadLJRaw(uint8_t *buff); + +void SysMonitor_UpdateSendSlotLog(SLOTLOG *log); +void SysMonitor_UpdateRecvSlotLog(SLOTLOG *log); +void SysMonitor_UpdateProtocolLog(PRTCLLOG *log); +void SysMonitor_GetSendSlotLog(SLOTLOG *log); +void SysMonitor_GetRecvSlotLog(SLOTLOG *log); +void SysMonitor_GetProtocolLog(PRTCLLOG *log); +void SysMonitor_GetSendSlotLogRaw(uint8_t *buff); +void SysMonitor_GetRecvSlotLogRaw(uint8_t *buff); +void SysMonitor_GetProtocolLogRaw(uint8_t *buff); + +void SysMonitor_UpdateHardwareStatus(HWSTATE *state); +void SysMonitor_GetHardwareStatus(HWSTATE *state); +void SysMonitor_GetHardwareStatusRaw(uint8_t *buff); + +void SysMonitor_GetSyslog(SYSLOG *log); +void SysMonitor_GetSyslogRaw(uint8_t *buff); + +#endif //__SYSTEM_MONITOR_H_ diff --git a/df_datalink/src/systembus/systembus.c b/df_datalink/src/systembus/systembus.c new file mode 100644 index 0000000..044ef19 --- /dev/null +++ b/df_datalink/src/systembus/systembus.c @@ -0,0 +1,468 @@ +/*****************************************************************************/ +/** + * Description: System bus protocol implementation file. + * + * Date: 2023-05-06 10:13 + * Last Edit Time: [2023-05-06 21:45] + * + * Revisions: Rev 0.0 + * History: + * [2023-05-06]: Initial version. + * [2023-09-13]: Update to 485 portocol-20220816 + * + * Copyright(c) 2021 Beijing Institute of Technology. + * Lab of Communication and Network + * +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include +#include +#include +#include +#include "systembus_uart.h" +#include "systembus.h" +#include "util.h" +#include "common.h" +#include "error.h" +#include "circ_queue.h" + +#include "../system_monitor.h" + +// Common Field +// -- Command word +#define WD_CMD 0x00 + +// -- Production type +#define WD_PRD 0x01 +#define PRD_DL_K 0xDD +#define PRD_DL_S 0xDE +#define PRD_ALL 0xFF + +// Self-Test +#define CMD_SELF_TEST 0xE1 +// -- Request +// -- -- -- +// -- Response +// -- -- Self-Test Result +#define ST_RSP_LEN 16 +#define WD_ST_RET 0x02 +#define ST_RET_OK 0xAA +#define ST_RET_ERROR 0x55 +// -- -- Signal processor voltage +#define WD_SP_VOLT_L 0x03 +#define WD_SP_VOLT_H 0x04 +// -- -- Signal processor temperature +#define WD_SP_TEMP_L 0x05 +#define WD_SP_TEMP_H 0x06 +// -- -- Signal processor chip status +#define WD_SP_CS_L 0x07 +#define WD_SP_CS_H 0x08 +// -- -- Signal processor antenna voltage +#define WD_AS_VOLT 0x09 +// -- -- Signal processor antenna temperature +#define WD_AS_TEMP 0x0A +// -- -- Signal processor antenna PLL lock status +#define WD_AS_PLL 0x0B +// -- -- Signal processor antenna MGC +#define WD_AS_MGC_L 0x0C +#define WD_AS_MGC_H 0x0D +// -- -- Signal processor antenna status +#define WD_AS_ST 0x0E. +// -- -- Dummy must be 0x00 +#define WD_ST_DUMMY 0x0F + +// Data Send Test Command +#define CMD_DATA_TEST_A 0xE2 +// -- Request +#define DATA_TEST_REQ_A_LEN 80 +// -- -- 78 byte payload +// -- Response +#define DATA_TEST_RSP_A_LEN 80 +// -- -- 78 byte payload + +// Data Send Test Command +#define CMD_DATA_TEST_B 0xF2 +// -- Request +#define DATA_TEST_REQ_B_LEN 152 +// -- -- 150 byte payload +// -- Response +#define DATA_TEST_RSP_B_LEN 152 +// -- -- 150 byte payload + +// Config load +#define CMD_CONFIG 0xE3 +// -- Request +#define WD_EN_CMD 0x02 +#define EN_CMD_ON 0x66 + +#define WD_MODE_CMD 0x03 +#define MODE_CMD_HEAD 0x11 +#define MODE_CMD_MEMBER 0x11 +// -- Response +// -- -- none response + +// System info update +#define CMD_SYS_INFO 0x33 +// -- Request +// -- -- 54 byte system info +// -- Response +// -- -- none response + +// Data Send Test Command +#define CMD_FLJ_SEND 0xE4 +// -- Request +// -- -- 78 byte payload +// -- Response +// -- -- none response + +// Data Send Test Command +#define CMD_LJ_SEND 0xF4 +// -- Request +// -- -- 156 byte payload +// -- Response +// -- -- none response + +// FLJ Poll +#define CMD_FLJ_POLL 0xE5 +// -- Request +#define WD_FLJ_POLL 0x02 +#define FLJ_POLL_CODE 0x77 +// -- Response +#define FLJ_POLL_RESP_LEN 78 +// -- -- received 78 byte payload + +// LJ Poll +#define CMD_LJ_POLL 0xF5 +// -- Request +#define WD_LJ_POLL 0x02 +#define LJ_POLL_CODE 0x77 +// -- Response +#define LJ_POLL_RESP_LEN 156 +// -- -- received 156 byte payload + +// Remote Test +#define CMD_RM_TEST 0xE6 +// -- Request +// -- -- none, response with roll call (after roll call resp) +// -- Response +#define RM_TEST_LEN 210 +// -- -- received 208 byte Remote Test infomation + +// My Production Type +#define MY_PRD_ID PRD_DL_K + + +inline bool SystemBus_IsReqPendding(SYSBUS *instPtr){ + ASSERT(instPtr != NULL); + return (!isCircQueueEmpty(instPtr->rxQueue)); +} + +inline bool SystemBus_IsRsqPendding(SYSBUS *instPtr){ + ASSERT(instPtr != NULL); + return (!isCircQueueEmpty(instPtr->txQueue)); +} + +inline bool SystemBus_IsTxBusy(SYSBUS *instPtr) { + ASSERT(instPtr != NULL); + return (!instPtr->isTxDone); +} +inline bool SystemBus_IsRxBusy(SYSBUS *instPtr) { + ASSERT(instPtr != NULL); + return SysbusUart_IsRxBusy(instPtr->uartInst); +} + +/*****************************************************************************/ +/** + * @brief Initialize System Bus instance. + * + * @param InstPtr A double pointer to System Bus instance. + * @param config A pointer to System Bus configurations. + * + * @return None. + * +******************************************************************************/ +int32_t SystemBus_Init(SYSBUS **instPtr, SYSBUS_CONFIG *config) { + ASSERT(instPtr != NULL); + ASSERT(config != NULL); + SYSBUS_UART_CONFIG uartConfig; + int32_t Status; + (*instPtr) = malloc(sizeof(SYSBUS)); + if ((*instPtr) == NULL) { + return FAILURE; + } + (*instPtr)->rxQueue = NULL; + (*instPtr)->txQueue = NULL; + (*instPtr)->uartInst = NULL; + memcpy(&((*instPtr)->config), config, sizeof(SYSBUS_CONFIG)); + uartConfig.baseAddr = config->baseAddr; + Status = SysbusUart_Init(&((*instPtr)->uartInst), &uartConfig); + if (Status != SUCCESS) { + Status = ENOMEM; + goto sysbus_init_error; + } + if(CircQueueCreate(&((*instPtr)->txQueue), (*instPtr)->config.txQueueMax) == false){ + Status = ENOMEM; + goto sysbus_init_error; + } + if(CircQueueCreate(&((*instPtr)->rxQueue), (*instPtr)->config.rxQueueMax) == false){ + Status = ENOMEM; + goto sysbus_init_error; + } + (*instPtr)->isRxDone = false; // nothing received. + (*instPtr)->isTxDone = true; // nothing to be sent. + return SUCCESS; + +sysbus_init_error: + free((*instPtr)->uartInst); + free((*instPtr)->txQueue); + free((*instPtr)->rxQueue); + free(*instPtr); + return Status; +} + +/*****************************************************************************/ +/** + * @brief A handler function. This handler evaluate the message from system + * bus receive queue, and make appropriate response. + * + * @param instPtr A pointer to System Bus instance. + * + * @return None + * +******************************************************************************/ +int32_t SystemBus_HandleCmd(SYSBUS* instPtr) { + ASSERT(instPtr != NULL); + int32_t Status; + SYSBUS_UART_FRAME *sysbusReq, *sysbusRsp; + uint8_t *data; + if (CircQueuePop(instPtr->rxQueue, (void**)(&sysbusReq)) == false) { + DBG_WARNING("SystemBus::Nothing to be handled.\n"); + return EIGNORE; + } + data = sysbusReq->data; + if(data[WD_PRD] != MY_PRD_ID && data[WD_PRD] != PRD_ALL) { + DBG_WARNING("SystemBus::Production code mismatch!\n"); + return EIGNORE; + } + switch(data[WD_CMD]){ + case CMD_SELF_TEST : { + sysbusRsp = malloc(sizeof(SYSBUS_UART_FRAME)); + sysbusRsp->len = ST_RSP_LEN; + memset(sysbusRsp->data,0x00,ST_RSP_LEN); + sysbusRsp->data[WD_CMD] = CMD_SELF_TEST; + sysbusRsp->data[WD_PRD] = MY_PRD_ID; + + // FIXME: run self-test and insert result + sysbusRsp->data[WD_ST_RET] = ST_RET_OK; + if (CircQueuePush(instPtr->txQueue, (void *)sysbusRsp) == false){ + DBG_WARNING("SystemBus::TX Queue overflowed!\n"); + Status = EQUEUE; + break; + } + Status = SUCCESS; + break; + } + case CMD_DATA_TEST_A : { + sysbusRsp = malloc(sizeof(SYSBUS_UART_FRAME)); + sysbusRsp->len = DATA_TEST_RSP_A_LEN; + memcpy(sysbusRsp->data, sysbusReq->data, DATA_TEST_RSP_A_LEN); + if (CircQueuePush(instPtr->txQueue, (void *)sysbusRsp) == false){ + DBG_WARNING("SystemBus::TX Queue overflowed!\n"); + Status = EQUEUE; + break; + } + Status = SUCCESS; + break; + } + case CMD_DATA_TEST_B : { + sysbusRsp = malloc(sizeof(SYSBUS_UART_FRAME)); + sysbusRsp->len = DATA_TEST_RSP_B_LEN; + memcpy(sysbusRsp->data, sysbusReq->data, DATA_TEST_RSP_B_LEN); + if (CircQueuePush(instPtr->txQueue, (void *)sysbusRsp) == false){ + DBG_WARNING("SystemBus::TX Queue overflowed!\n"); + Status = EQUEUE; + break; + } + Status = SUCCESS; + break; + } + case CMD_CONFIG : { + // FIXME: apply configurations + // Power + Mode + // -- No response + _nop_(); // for debug + Status = SUCCESS; + break; + } + case CMD_SYS_INFO : { + SysMonitor_UpdateSysinfoRaw(data+2); + Status = SUCCESS; + break; + } + // TODO + case CMD_FLJ_SEND : { + SysMonitor_UpdateSendPayloadFLJRaw(data+2); // ommit 2 bytes control info + break; + } + case CMD_LJ_SEND : { + SysMonitor_UpdateSendPayloadLJRaw(data+2); // ommit 2 bytes control info + break; + } + case CMD_FLJ_POLL : { + if (data[WD_FLJ_POLL] != FLJ_POLL_CODE) { + DBG_WARNING("SystemBus::Invalid roll call code!\n"); + Status = EIGNORE; + break; + } + sysbusRsp = malloc(sizeof(SYSBUS_UART_FRAME)); + sysbusRsp->len = FLJ_POLL_RESP_LEN; + sysbusRsp->data[WD_CMD] = WD_FLJ_POLL; + sysbusRsp->data[WD_PRD] = MY_PRD_ID; + SysMonitor_GetRecvPayloadFLJRaw(sysbusRsp->data + 2); // ommit 2 bytes control info + if (CircQueuePush(instPtr->txQueue, (void *)sysbusRsp) == false){ + DBG_WARNING("SystemBus::TX Queue overflowed!\n"); + Status = EQUEUE; + break; + } + + //FIXME: Confirm +// sysbusRsp = malloc(sizeof(SYSBUS_UART_FRAME)); +// sysbusRsp->len = RM_TEST_LEN; +// sysbusRsp->data[WD_CMD] = CMD_RM_TEST; +// sysbusRsp->data[WD_PRD] = MY_PRD_ID; +// SysMonitor_GetSyslogRaw(sysbusRsp->data + 2); //ommit 2 bytes control info +// if (CircQueuePush(instPtr->txQueue, (void *)sysbusRsp) == false){ +// DBG_WARNING("SystemBus::TX Queue overflowed!\n"); +// Status = EQUEUE; +// break; +// } + Status = SUCCESS; + break; + } + case CMD_LJ_POLL : { + if (data[WD_LJ_POLL] != LJ_POLL_CODE) { + DBG_WARNING("SystemBus::Invalid roll call code!\n"); + Status = EIGNORE; + break; + } + sysbusRsp = malloc(sizeof(SYSBUS_UART_FRAME)); + sysbusRsp->len = LJ_POLL_RESP_LEN; + sysbusRsp->data[WD_CMD] = WD_LJ_POLL; + sysbusRsp->data[WD_PRD] = MY_PRD_ID; + SysMonitor_GetRecvPayloadLJRaw(sysbusRsp->data + 2); // ommit 2 bytes control info + if (CircQueuePush(instPtr->txQueue, (void *)sysbusRsp) == false){ + DBG_WARNING("SystemBus::TX Queue overflowed!\n"); + Status = EQUEUE; + break; + } + + //FIXME: Confirm +// sysbusRsp = malloc(sizeof(SYSBUS_UART_FRAME)); +// sysbusRsp->len = RM_TEST_LEN; +// sysbusRsp->data[WD_CMD] = CMD_RM_TEST; +// sysbusRsp->data[WD_PRD] = MY_PRD_ID; +// SysMonitor_GetSyslogRaw(sysbusRsp->data + 2); //ommit 2 bytes control info +// if (CircQueuePush(instPtr->txQueue, (void *)sysbusRsp) == false){ +// DBG_WARNING("SystemBus::TX Queue overflowed!\n"); +// Status = EQUEUE; +// break; +// } + Status = SUCCESS; + break; + } + default:{ + DBG_ERROR("SystemBus::Unknown command code!\n"); + break; + } + } + free(sysbusReq); + return Status; +} + + +int32_t SystemBus_FLJ_PeriodUpdate(SYSBUS *instPtr){ + // TODO + return SUCCESS; +} + + +int32_t SystemBus_LJ_PeriodUpdate(SYSBUS *instPtr){ + // TODO + return SUCCESS; +} + + +/*****************************************************************************/ +/** + * @brief This function send a repose frame from system bus tx queue. + * + * @param instPtr A pointer to System Bus instance. + * + * @return None + * +******************************************************************************/ +int32_t SystemBus_MakeResp(SYSBUS *instPtr){ + ASSERT(instPtr != NULL); + int32_t Status; + SYSBUS_UART_FRAME *sysbusRsp; + if (CircQueuePop(instPtr->txQueue, (void**)(&sysbusRsp)) == false) { + DBG_WARNING("SystemBus::Nothing to be sent.\n"); + return EIGNORE; + } + instPtr->isTxDone = false; // A transmission procedure is started. + Status = SysbusUart_Send(instPtr->uartInst, sysbusRsp); + free(sysbusRsp); + return Status; +} + +/*****************************************************************************/ +/** + * @brief This function handles the systembus tx irq events. + * + * @param instPtr A pointer to System Bus instance. + * + * @return None + * +******************************************************************************/ +int32_t SystemBus_TxIntrHandler(SYSBUS *instPtr){ + ASSERT(instPtr != NULL); + // nothing special... + instPtr->isTxDone = true; // A transmission procedure finished. + return SUCCESS; +} + +/*****************************************************************************/ +/** + * @brief This function handles the systembus rx irq events. + * + * @param instPtr A pointer to System Bus instance. + * + * @return None + * +******************************************************************************/ +int32_t SystemBus_RxIntrHandler(SYSBUS *instPtr){ + ASSERT(instPtr != NULL); + int32_t Status; + SYSBUS_UART_FRAME *sysbusReq; + instPtr->isRxDone = true; // whether reception successes or not, receiving procedure ended. + sysbusReq = malloc(sizeof(SYSBUS_UART_FRAME)); + if (sysbusReq == NULL) { + return ENOMEM; + } + Status = SysbusUart_Recv(instPtr->uartInst, sysbusReq); + if(Status != SUCCESS) { + goto recv_error; + } + if (CircQueuePush(instPtr->rxQueue, (void *)sysbusReq) == false){ + DBG_WARNING("SystemBus::RX Queue overflowed!\n"); + Status = EQUEUE; + goto recv_error; + } + instPtr->isRxDone = false; // another reception is undergoing. + return SUCCESS; +recv_error: + free(sysbusReq); + return Status; +} diff --git a/df_datalink/src/systembus/systembus.h b/df_datalink/src/systembus/systembus.h new file mode 100644 index 0000000..7c0f0a9 --- /dev/null +++ b/df_datalink/src/systembus/systembus.h @@ -0,0 +1,65 @@ +/*****************************************************************************/ +/** + * Description: System bus protocol head file. + * + * Date: 2023-05-06 10:12 + * Last Edit Time: [2023-05-06 10:13] + * + * Revisions: Rev 0.0 + * History: + * [2023-05-06]: Initial version. + * + * Copyright(c) 2021 Beijing Institute of Technology. + * +******************************************************************************/ + +#ifndef __SYSTEMBUS_H_ +#define __SYSTEMBUS_H_ + +/***************************** Include Files *********************************/ +#include "systembus_uart.h" // SystemBus UART driver +#include "circ_queue.h" +#include +#include + + +/************************** Constant Definitions *****************************/ +/************************** Data Type Definitions ****************************/ +// Definition of SystemBus instance. +typedef struct { + uintptr_t baseAddr; + uint32_t txQueueMax; + uint32_t rxQueueMax; +} SYSBUS_CONFIG; + +typedef struct { + SYSBUS_CONFIG config; + SYSBUS_UART *uartInst; + CIRC_QUEUE *txQueue; + CIRC_QUEUE *rxQueue; + bool isRxDone; + bool isTxDone; +} SYSBUS; + +/************************** Function Prototypes ******************************/ + +int32_t SystemBus_Init(SYSBUS **instPtr, SYSBUS_CONFIG *config); + +int32_t SystemBus_HandleCmd(SYSBUS *instPtr); + +int32_t SystemBus_FLJ_PeriodUpdate(SYSBUS *instPtr); +int32_t SystemBus_LJ_PeriodUpdate(SYSBUS *instPtr); + +int32_t SystemBus_MakeResp(SYSBUS *instPtr); + +int32_t SystemBus_TxIntrHandler(SYSBUS *instPtr); +int32_t SystemBus_RxIntrHandler(SYSBUS *instPtr); + +bool SystemBus_IsReqPendding(SYSBUS *instPtr); +bool SystemBus_IsRsqPendding(SYSBUS *instPtr); + +bool SystemBus_IsTxBusy(SYSBUS *instPtr); +bool SystemBus_IsRxBusy(SYSBUS *instPtr); + + +#endif //__SYSTEMBUS_H_ diff --git a/df_datalink/src/systembus/systembus_uart.c b/df_datalink/src/systembus/systembus_uart.c new file mode 100644 index 0000000..34dd50a --- /dev/null +++ b/df_datalink/src/systembus/systembus_uart.c @@ -0,0 +1,228 @@ +/*****************************************************************************/ +/** + * Description: System bus uart driver implementation file. + * + * Date: 2023-05-06 10:59 + * LastEditTime: 2023-05-06 21:56 + * Revisions: Rev 0.0 + * History: + * [2023-05-06]: Initial version. + * + * Copyright(c) 2022 Beijing Institute of Technology. + * + ******************************************************************************/ + +/***************************** Include Files *******************************/ +#include +#include +#include +#include +#include "systembus_uart.h" +#include "common.h" + +// Control and status register +#define MODULE_VERSION 0 +#define UART_STATUS 4 +#define UART_SEND_CMD 8 +#define UART_RECV_CNT 12 + +// Status code +#define UART_STATUS_TX_BUSY 0x00010000 +#define UART_STATUS_RX_BUSY 0x01000000 +// Data buffer register +#define UART_TXBUFF_LOW 1024 +#define UART_TXBUFF_MAX 1024 +#define UART_RXBUFF_LOW 2048 +#define UART_RXBUFF_MAX 1024 + +// Frame Data offsets +#define FRAME_HEAD_LOW 0x5A +#define FRAME_HEAD_HIGH 0x54 +#define FRAME_TAIL_LOW 0x5A +#define FRAME_TAIL_HIGH 0xFE + +#define FRAME_HEAD_LEN 2 +#define FRAME_TAIL_LEN 2 +#define FRAME_DUMMY_LEN 1 // Dummy +#define FRAME_CHECK_LEN 1 // CheckSum +#define FRAME_INFO_LEN 3 // CheckSum, Dummy and DataLen +#define FRAME_OVERHEAD_LEN 7 // CheckSum, Dummy and DataLen +/*************************** Function Definitions ****************************/ + +/*****************************************************************************/ +/** + * @brief Instance initial + * + * @param instPtr A pointer to frame uart instance structure. + * @param config Base address of frame uart, refer to "xparameters.h" + * + * @return None. + * + ******************************************************************************/ +int SysbusUart_Init(SYSBUS_UART **instPtr, SYSBUS_UART_CONFIG *config) { + ASSERT(instPtr != NULL); + ASSERT(config != NULL); + (*instPtr) = malloc(sizeof(SYSBUS_UART)); + if ((*instPtr) == NULL){ + return FAILURE; + } + (*instPtr)->config.baseAddr = config->baseAddr; + return SUCCESS; +} + +/*****************************************************************************/ +/** + * @brief Send a system bus frame. + * + * @param instPtr A pointer to SYSBUS_UART instance structure. + * @param buff A pointer to send data buffer + * @param dLen A integer indicate the send data buffer length in byte. + * + * @return + * + ******************************************************************************/ +int SysbusUart_Send(SYSBUS_UART* instPtr, SYSBUS_UART_FRAME *frame) { + ASSERT(instPtr != NULL); + ASSERT(frame != NULL); + uint8_t dLen, checkSum; + uint8_t sendLen; + uint8_t *sendBuff; + if (frame->len > UART_TXBUFF_MAX || frame->len == 0) { + return FAILURE; + } + sendBuff = malloc(sizeof(uint8_t) * UART_TXBUFF_MAX); + if (sendBuff == NULL) { + return FAILURE; + } + sendBuff[0] = FRAME_HEAD_LOW; + sendBuff[1] = FRAME_HEAD_HIGH; + dLen = 0; + checkSum = 0; + for (int i = 0; i < frame->len - 1; i++) { + if (frame->data[i] == FRAME_TAIL_LOW && frame->data[i+1] == FRAME_TAIL_HIGH) { + sendBuff[FRAME_HEAD_LEN + dLen] = 0x00; + dLen ++; + } + sendBuff[FRAME_HEAD_LEN + dLen] = frame->data[i]; + checkSum += sendBuff[FRAME_HEAD_LEN + dLen]; + dLen ++; + } + // Last Byte + sendBuff[FRAME_HEAD_LEN + dLen] = frame->data[frame->len - 1]; + checkSum += sendBuff[FRAME_HEAD_LEN + dLen]; + dLen ++; + // Dummy Byte + sendBuff[FRAME_HEAD_LEN + dLen] = 0x00; + // Check Sum + sendBuff[FRAME_HEAD_LEN + dLen + 1] = checkSum; + // Data Len + sendBuff[FRAME_HEAD_LEN + dLen + 2] = dLen; + // Frame Tail + sendBuff[FRAME_HEAD_LEN + dLen + 3] = FRAME_TAIL_LOW; + sendBuff[FRAME_HEAD_LEN + dLen + 4] = FRAME_TAIL_HIGH; + sendLen = dLen + FRAME_OVERHEAD_LEN; + if (sendLen > UART_TXBUFF_MAX) { + free(sendBuff); + return FAILURE; + } + memcpy((void *)(instPtr->config.baseAddr + UART_TXBUFF_LOW), sendBuff, (sendLen + sizeof(uint32_t) - 1)/sizeof(uint32_t) * sizeof(uint32_t)); + free(sendBuff); + // Start Sending + SYSTEMBUS_UART_mWriteReg(instPtr->config.baseAddr, UART_SEND_CMD, sendLen); + return SUCCESS; +} + +/*****************************************************************************/ +/** + * @brief Get last system bus frame. + * + * @param instPtr A pointer to SYSBUS_UART instance structure. + * @param buff A pointer to receive data buffer. + * + * @return + * + ******************************************************************************/ +int SysbusUart_Recv(SYSBUS_UART* instPtr, SYSBUS_UART_FRAME *frame) { + ASSERT(instPtr != NULL); + ASSERT(frame != NULL); + + uint8_t dLen, dWLen, plLen, checkSum, checkSumCal; + uint8_t *plBuff, *dBuff; + dLen = SYSTEMBUS_UART_mReadReg(instPtr->config.baseAddr, UART_RECV_CNT); + if (dLen == 0 || dLen > UART_TXBUFF_MAX) { + return EPARAM; + } + dWLen = (dLen + FRAME_HEAD_LEN + FRAME_INFO_LEN - 1)/4 + 1; + + dBuff = malloc(sizeof(uint32_t)*dWLen); + if (dBuff == NULL){ + return ENOMEM; + } + memcpy(dBuff, (void *)(instPtr->config.baseAddr + UART_RXBUFF_LOW), sizeof(uint32_t)*dWLen); + plBuff = dBuff + FRAME_HEAD_LEN; + checkSumCal = 0; + checkSum = plBuff[dLen + FRAME_DUMMY_LEN]; + plLen = 0; + for(int i = 0; i < dLen; i++){ + if (plBuff[i+1] == FRAME_TAIL_LOW && plBuff[i+2] == FRAME_TAIL_HIGH) { + continue; + } + checkSumCal += plBuff[i]; + frame->data[plLen] = plBuff[i]; + plLen++; + } + free(dBuff); + frame->len = plLen; + frame->checkSum = checkSumCal; + if (checkSumCal != checkSum){ + frame->isValid = false; + return FAILURE; + } + frame->isValid = true; + return SUCCESS; +} + +/*****************************************************************************/ +/** + * @brief Get rx channel status. + * + * @param instPtr A pointer to SYSBUS_UART instance structure. + * + * @return true - SYSBUS_UART rx channel is busy. + * false - SYSBUS_UART rx channel is idle. + * + ******************************************************************************/ +bool SysbusUart_IsRxBusy(SYSBUS_UART* instPtr) { + ASSERT(instPtr != NULL); + uint32_t Status; + Status = SYSTEMBUS_UART_mReadReg(instPtr->config.baseAddr, UART_STATUS); + + if (Status & UART_STATUS_RX_BUSY) { + return true; + } + else { + return false; + } +} + +/*****************************************************************************/ +/** + * @brief Get tx channel status. + * + * @param instPtr A pointer to SYSBUS_UART instance structure. + * + * @return true - SYSBUS_UART tx channel is busy. + * false - SYSBUS_UART tx channel is idle. + * + ******************************************************************************/ +bool SysbusUart_IsTxBusy(SYSBUS_UART* instPtr) { + ASSERT(instPtr != NULL); + uint32_t Status; + Status = SYSTEMBUS_UART_mReadReg(instPtr->config.baseAddr, UART_STATUS); + if (Status & UART_STATUS_TX_BUSY) { + return true; + } + else { + return false; + } +} diff --git a/df_datalink/src/systembus/systembus_uart.h b/df_datalink/src/systembus/systembus_uart.h new file mode 100644 index 0000000..2beb8b2 --- /dev/null +++ b/df_datalink/src/systembus/systembus_uart.h @@ -0,0 +1,96 @@ +/*****************************************************************************/ +/** + * Description: System bus uart driver implementation file. + * + * Date: 2023-05-06 10:59 + * LastEditTime: 2023-05-06 21:48 + * Revisions: Rev 0.0 + * History: + * [2023-05-06]: Initial version. + * + * Copyright(c) 2022 Beijing Institute of Technology. + * + ******************************************************************************/ + +#ifndef SYSTEMBUS_UART_H +#define SYSTEMBUS_UART_H + +/****************** Include Files ********************/ +#include +#include +#include "util.h" +/**************************** Type Definitions *****************************/ +/** + * + * Write a value to a SYSTEMBUS_UART register. A 32 bit write is performed. + * If the component is implemented in a smaller width, only the least + * significant data is written. + * + * @param baseAddr is the base address of the SYSTEMBUS_UARTdevice. + * @param offset is the register offset from the base to write to. + * @param data is the data written to the register. + * + * @return None. + * + * @note + * C-style signature: + * void SYSTEMBUS_UART_mWriteReg(uint32_t BaseAddress, unsigned RegOffset, uint32_t Data) + * + */ +#define SYSTEMBUS_UART_mWriteReg(baseAddr, offset, data) \ + IO_Out32((baseAddr) + (offset), (uint32_t)(data)) + +/** + * + * Read a value from a SYSTEMBUS_UART register. A 32 bit read is performed. + * If the component is implemented in a smaller width, only the least + * significant data is read from the register. The most significant data + * will be read as 0. + * + * @param baseAddr is the base address of the SYSTEMBUS_UART device. + * @param offset is the register offset from the base to write to. + * + * @return Data is the data from the register. + * + * @note + * C-style signature: + * uint32_t SYSTEMBUS_UART_mReadReg(uint32_t BaseAddress, unsigned RegOffset) + * + */ +#define SYSTEMBUS_UART_mReadReg(baseAddr, offset) \ + IO_In32((baseAddr) + (offset)) + +/************************** Data Type Definitions ****************************/ +typedef struct { + uintptr_t baseAddr; +} SYSBUS_UART_CONFIG; + +typedef struct { + SYSBUS_UART_CONFIG config; +} SYSBUS_UART; + +typedef struct { + uint8_t len; + uint8_t checkSum; + uint8_t isValid; + uint8_t dummy; + uint8_t data[256]; +} SYSBUS_UART_FRAME; + +/************************** Function Prototypes ******************************/ +// Instance initial +int SysbusUart_Init(SYSBUS_UART **instPtr, SYSBUS_UART_CONFIG *config); + +// Send a system bus frame. +int SysbusUart_Send(SYSBUS_UART *instPtr, SYSBUS_UART_FRAME *frame); + +// Get last system bus frame. +int SysbusUart_Recv(SYSBUS_UART *instPtr, SYSBUS_UART_FRAME *frame); + +// Get system bus rx channel status. +bool SysbusUart_IsRxBusy(SYSBUS_UART *instPtr); + +// Get system bus tx channel status. +bool SysbusUart_IsTxBusy(SYSBUS_UART *instPtr); + +#endif // SYSTEMBUS_UART_H diff --git a/df_datalink/src/util/circ_queue.c b/df_datalink/src/util/circ_queue.c new file mode 100644 index 0000000..9ec4b7d --- /dev/null +++ b/df_datalink/src/util/circ_queue.c @@ -0,0 +1,132 @@ +/*****************************************************************************/ +/** + * Description: A simple circular FIFO bounded queue + * + * Author: Fan Hao + * Date: 2023-02-23 10:29 + * LastEditors: Fan Hao + * LastEditTime: 2023-02-23 13:18 + * Revisions: Rev 0.0 + * History: + * [2023-02-23]: Initial Version. + * + * Copyright(c) 2023 Beijing Institute of Technology. + * Lab of Communication and Networking + * NOTE: Forked from https://github.com/chrismerck/rpa_queue.git + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +******************************************************************************/ + +#include "circ_queue.h" +#include "common.h" +#include +#include +#include + +inline bool isCircQueueFull(CIRC_QUEUE *queue){ + ASSERT(queue != NULL); + return ((queue)->nelts == (queue)->bounds); +} + +inline bool isCircQueueEmpty(CIRC_QUEUE *queue){ + ASSERT(queue != NULL); + return ((queue)->nelts == 0); +} + + +void CircQueueFree(CIRC_QUEUE * queue) +{ + ASSERT(queue != NULL); + if (queue->data) free(queue->data); + free(queue); +} + +/** + * Initialize the CIRC_QUEUE. + */ +bool CircQueueCreate(CIRC_QUEUE **q, uint32_t queueCapacity) +{ + ASSERT(q != NULL); + CIRC_QUEUE *queue; + queue = malloc(sizeof(CIRC_QUEUE)); + if (!queue) { + return false; + } + *q = queue; + memset(queue, 0, sizeof(CIRC_QUEUE)); + + /* Set all the data in the queue to NULL */ + queue->data = malloc(queueCapacity * sizeof(void*)); + if(queue->data == NULL){ + goto error; + } + queue->bounds = queueCapacity; + queue->nelts = 0; + queue->in = 0; + queue->out = 0; + return true; +error: + free(queue); + return false; +} + +/** + * Push new data onto the queue. + */ +bool CircQueuePush(CIRC_QUEUE *queue, void *data) +{ + ASSERT(queue != NULL); + + if (isCircQueueFull(queue)) { + return false; + } + + queue->data[queue->in] = data; + queue->in++; + if (queue->in >= queue->bounds) { + queue->in -= queue->bounds; + } + queue->nelts++; + + return true; +} + +/** + * Return current number of element in queue. + */ +inline uint32_t CircQueueSize(CIRC_QUEUE *queue) { + return queue->nelts; +} + +/** + * Retrieves the next item from the queue. + */ +bool CircQueuePop(CIRC_QUEUE *queue, void **data) +{ + ASSERT(queue != NULL); + + if (isCircQueueEmpty(queue)) { + return false; + } + + *data = queue->data[queue->out]; + queue->nelts--; + + queue->out++; + if (queue->out >= queue->bounds) { + queue->out -= queue->bounds; + } + return true; +} diff --git a/df_datalink/src/util/common.c b/df_datalink/src/util/common.c new file mode 100644 index 0000000..e26ecbb --- /dev/null +++ b/df_datalink/src/util/common.c @@ -0,0 +1,43 @@ +/*****************************************************************************/ +/** + * Description: Common functions + * + * Date: 2021-11-16 00:08 + * LastEditors: Fan Hao + * LastEditTime: 2022-07-16 17:13 + * Revisions: Rev 0.1 + * History: + * [2022-07-16]: New branch for Dijian. + * [2021-11-16]: Initial version. + * + * Copyright(c) 2021 Beijing Institute of Technology. + * Lab of Communication and Networking + * + ******************************************************************************/ + +/***************************** Include Files *********************************/ +#include "common.h" +#include "error.h" +#include "util.h" + +/************************** Constant Definitions *****************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/**************************** Type Definitions *******************************/ + +/************************** Variable Definitions *****************************/ + +/*****************************************************************************/ +/** + * @brief + * + * @param + * + * @return + * + ******************************************************************************/ +void AppAssert(const char * file, int line){ + DBG_ERROR("Assert: %s, #%d.\n", file, line); + while(1); +}; diff --git a/df_datalink/src/util/crc.c b/df_datalink/src/util/crc.c new file mode 100644 index 0000000..8c98f68 --- /dev/null +++ b/df_datalink/src/util/crc.c @@ -0,0 +1,417 @@ +/*****************************************************************************/ +/** + * Description: CRC implementation file + * + * Author: Hao Fan + * Date: 2021-11-16 00:50 + * LastEditors: Hao Fan + * LastEditTime: 2022-07-17 20:53 + * Revisions: Rev 0.0 + * History: + * [2022-07-17]: Add CRC16_0x8005 CRC8_0x31. + * [2022-01-06]: Initial verion (Basic CRC-16). + * + * Copyright(c) 2021 Beijing Institute of Technology. + * Lab of Communication and Networking + * + ******************************************************************************/ + +#include "util.h" +#include "error.h" + +#ifdef __CRC_LSB +// CRC-16-CCITT G(X)=X16+X12+X5+1 +// Reversed +static const uint16_t crc16_1021_lsb_lut[256] = { + 0x0000, 0x1189, 0x2312, 0x329B, 0x4624, 0x57AD, 0x6536, 0x74BF, + 0x8C48, 0x9DC1, 0xAF5A, 0xBED3, 0xCA6C, 0xDBE5, 0xE97E, 0xF8F7, + 0x1081, 0x0108, 0x3393, 0x221A, 0x56A5, 0x472C, 0x75B7, 0x643E, + 0x9CC9, 0x8D40, 0xBFDB, 0xAE52, 0xDAED, 0xCB64, 0xF9FF, 0xE876, + 0x2102, 0x308B, 0x0210, 0x1399, 0x6726, 0x76AF, 0x4434, 0x55BD, + 0xAD4A, 0xBCC3, 0x8E58, 0x9FD1, 0xEB6E, 0xFAE7, 0xC87C, 0xD9F5, + 0x3183, 0x200A, 0x1291, 0x0318, 0x77A7, 0x662E, 0x54B5, 0x453C, + 0xBDCB, 0xAC42, 0x9ED9, 0x8F50, 0xFBEF, 0xEA66, 0xD8FD, 0xC974, + 0x4204, 0x538D, 0x6116, 0x709F, 0x0420, 0x15A9, 0x2732, 0x36BB, + 0xCE4C, 0xDFC5, 0xED5E, 0xFCD7, 0x8868, 0x99E1, 0xAB7A, 0xBAF3, + 0x5285, 0x430C, 0x7197, 0x601E, 0x14A1, 0x0528, 0x37B3, 0x263A, + 0xDECD, 0xCF44, 0xFDDF, 0xEC56, 0x98E9, 0x8960, 0xBBFB, 0xAA72, + 0x6306, 0x728F, 0x4014, 0x519D, 0x2522, 0x34AB, 0x0630, 0x17B9, + 0xEF4E, 0xFEC7, 0xCC5C, 0xDDD5, 0xA96A, 0xB8E3, 0x8A78, 0x9BF1, + 0x7387, 0x620E, 0x5095, 0x411C, 0x35A3, 0x242A, 0x16B1, 0x0738, + 0xFFCF, 0xEE46, 0xDCDD, 0xCD54, 0xB9EB, 0xA862, 0x9AF9, 0x8B70, + 0x8408, 0x9581, 0xA71A, 0xB693, 0xC22C, 0xD3A5, 0xE13E, 0xF0B7, + 0x0840, 0x19C9, 0x2B52, 0x3ADB, 0x4E64, 0x5FED, 0x6D76, 0x7CFF, + 0x9489, 0x8500, 0xB79B, 0xA612, 0xD2AD, 0xC324, 0xF1BF, 0xE036, + 0x18C1, 0x0948, 0x3BD3, 0x2A5A, 0x5EE5, 0x4F6C, 0x7DF7, 0x6C7E, + 0xA50A, 0xB483, 0x8618, 0x9791, 0xE32E, 0xF2A7, 0xC03C, 0xD1B5, + 0x2942, 0x38CB, 0x0A50, 0x1BD9, 0x6F66, 0x7EEF, 0x4C74, 0x5DFD, + 0xB58B, 0xA402, 0x9699, 0x8710, 0xF3AF, 0xE226, 0xD0BD, 0xC134, + 0x39C3, 0x284A, 0x1AD1, 0x0B58, 0x7FE7, 0x6E6E, 0x5CF5, 0x4D7C, + 0xC60C, 0xD785, 0xE51E, 0xF497, 0x8028, 0x91A1, 0xA33A, 0xB2B3, + 0x4A44, 0x5BCD, 0x6956, 0x78DF, 0x0C60, 0x1DE9, 0x2F72, 0x3EFB, + 0xD68D, 0xC704, 0xF59F, 0xE416, 0x90A9, 0x8120, 0xB3BB, 0xA232, + 0x5AC5, 0x4B4C, 0x79D7, 0x685E, 0x1CE1, 0x0D68, 0x3FF3, 0x2E7A, + 0xE70E, 0xF687, 0xC41C, 0xD595, 0xA12A, 0xB0A3, 0x8238, 0x93B1, + 0x6B46, 0x7ACF, 0x4854, 0x59DD, 0x2D62, 0x3CEB, 0x0E70, 0x1FF9, + 0xF78F, 0xE606, 0xD49D, 0xC514, 0xB1AB, 0xA022, 0x92B9, 0x8330, + 0x7BC7, 0x6A4E, 0x58D5, 0x495C, 0x3DE3, 0x2C6A, 0x1EF1, 0x0F78 +}; + +// CRC-16-MAXIM G(X)=X16+X15+X2+1 +const uint16_t crc16_8005_lsb_lut[256] = { + 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, + 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440, + 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40, + 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841, + 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40, + 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41, + 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641, + 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040, + 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240, + 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441, + 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41, + 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840, + 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41, + 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40, + 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640, + 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041, + 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240, + 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441, + 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41, + 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840, + 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41, + 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40, + 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640, + 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041, + 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241, + 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440, + 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40, + 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841, + 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40, + 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41, + 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641, + 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040 +}; + +// CRC-8-MAXIM G(X)=X8+X5+X4+1 +const uint8_t crc8_31_lsb_lut[256] = { + 0x00, 0x5E, 0xBC, 0xE2, 0x61, 0x3F, 0xDD, 0x83, + 0xC2, 0x9C, 0x7E, 0x20, 0xA3, 0xFD, 0x1F, 0x41, + 0x9D, 0xC3, 0x21, 0x7F, 0xFC, 0xA2, 0x40, 0x1E, + 0x5F, 0x01, 0xE3, 0xBD, 0x3E, 0x60, 0x82, 0xDC, + 0x23, 0x7D, 0x9F, 0xC1, 0x42, 0x1C, 0xFE, 0xA0, + 0xE1, 0xBF, 0x5D, 0x03, 0x80, 0xDE, 0x3C, 0x62, + 0xBE, 0xE0, 0x02, 0x5C, 0xDF, 0x81, 0x63, 0x3D, + 0x7C, 0x22, 0xC0, 0x9E, 0x1D, 0x43, 0xA1, 0xFF, + 0x46, 0x18, 0xFA, 0xA4, 0x27, 0x79, 0x9B, 0xC5, + 0x84, 0xDA, 0x38, 0x66, 0xE5, 0xBB, 0x59, 0x07, + 0xDB, 0x85, 0x67, 0x39, 0xBA, 0xE4, 0x06, 0x58, + 0x19, 0x47, 0xA5, 0xFB, 0x78, 0x26, 0xC4, 0x9A, + 0x65, 0x3B, 0xD9, 0x87, 0x04, 0x5A, 0xB8, 0xE6, + 0xA7, 0xF9, 0x1B, 0x45, 0xC6, 0x98, 0x7A, 0x24, + 0xF8, 0xA6, 0x44, 0x1A, 0x99, 0xC7, 0x25, 0x7B, + 0x3A, 0x64, 0x86, 0xD8, 0x5B, 0x05, 0xE7, 0xB9, + 0x8C, 0xD2, 0x30, 0x6E, 0xED, 0xB3, 0x51, 0x0F, + 0x4E, 0x10, 0xF2, 0xAC, 0x2F, 0x71, 0x93, 0xCD, + 0x11, 0x4F, 0xAD, 0xF3, 0x70, 0x2E, 0xCC, 0x92, + 0xD3, 0x8D, 0x6F, 0x31, 0xB2, 0xEC, 0x0E, 0x50, + 0xAF, 0xF1, 0x13, 0x4D, 0xCE, 0x90, 0x72, 0x2C, + 0x6D, 0x33, 0xD1, 0x8F, 0x0C, 0x52, 0xB0, 0xEE, + 0x32, 0x6C, 0x8E, 0xD0, 0x53, 0x0D, 0xEF, 0xB1, + 0xF0, 0xAE, 0x4C, 0x12, 0x91, 0xCF, 0x2D, 0x73, + 0xCA, 0x94, 0x76, 0x28, 0xAB, 0xF5, 0x17, 0x49, + 0x08, 0x56, 0xB4, 0xEA, 0x69, 0x37, 0xD5, 0x8B, + 0x57, 0x09, 0xEB, 0xB5, 0x36, 0x68, 0x8A, 0xD4, + 0x95, 0xCB, 0x29, 0x77, 0xF4, 0xAA, 0x48, 0x16, + 0xE9, 0xB7, 0x55, 0x0B, 0x88, 0xD6, 0x34, 0x6A, + 0x2B, 0x75, 0x97, 0xC9, 0x4A, 0x14, 0xF6, 0xA8, + 0x74, 0x2A, 0xC8, 0x96, 0x15, 0x4B, 0xA9, 0xF7, + 0xB6, 0xE8, 0x0A, 0x54, 0xD7, 0x89, 0x6B, 0x35 +}; +#else +// CRC-16-CCITT G(X)=X16+X12+X5+1 +static const uint16_t crc16_1021_msb_lut[256] = { + 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, + 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, + 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, + 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, + 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485, + 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D, + 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4, + 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC, + 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823, + 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, + 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, + 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, + 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, + 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49, + 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70, + 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78, + 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F, + 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067, + 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, + 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, + 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, + 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, + 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C, + 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634, + 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB, + 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3, + 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, + 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, + 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, + 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, + 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, + 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0 +}; + +// CRC-16-MAXIM G(X)=X16+X15+X2+1 +const uint16_t crc16_8005_msb_lut[256] = { + 0x0000, 0x8005, 0x800F, 0x000A, 0x801B, 0x001E, 0x0014, 0x8011, + 0x8033, 0x0036, 0x003C, 0x8039, 0x0028, 0x802D, 0x8027, 0x0022, + 0x8063, 0x0066, 0x006C, 0x8069, 0x0078, 0x807D, 0x8077, 0x0072, + 0x0050, 0x8055, 0x805F, 0x005A, 0x804B, 0x004E, 0x0044, 0x8041, + 0x80C3, 0x00C6, 0x00CC, 0x80C9, 0x00D8, 0x80DD, 0x80D7, 0x00D2, + 0x00F0, 0x80F5, 0x80FF, 0x00FA, 0x80EB, 0x00EE, 0x00E4, 0x80E1, + 0x00A0, 0x80A5, 0x80AF, 0x00AA, 0x80BB, 0x00BE, 0x00B4, 0x80B1, + 0x8093, 0x0096, 0x009C, 0x8099, 0x0088, 0x808D, 0x8087, 0x0082, + 0x8183, 0x0186, 0x018C, 0x8189, 0x0198, 0x819D, 0x8197, 0x0192, + 0x01B0, 0x81B5, 0x81BF, 0x01BA, 0x81AB, 0x01AE, 0x01A4, 0x81A1, + 0x01E0, 0x81E5, 0x81EF, 0x01EA, 0x81FB, 0x01FE, 0x01F4, 0x81F1, + 0x81D3, 0x01D6, 0x01DC, 0x81D9, 0x01C8, 0x81CD, 0x81C7, 0x01C2, + 0x0140, 0x8145, 0x814F, 0x014A, 0x815B, 0x015E, 0x0154, 0x8151, + 0x8173, 0x0176, 0x017C, 0x8179, 0x0168, 0x816D, 0x8167, 0x0162, + 0x8123, 0x0126, 0x012C, 0x8129, 0x0138, 0x813D, 0x8137, 0x0132, + 0x0110, 0x8115, 0x811F, 0x011A, 0x810B, 0x010E, 0x0104, 0x8101, + 0x8303, 0x0306, 0x030C, 0x8309, 0x0318, 0x831D, 0x8317, 0x0312, + 0x0330, 0x8335, 0x833F, 0x033A, 0x832B, 0x032E, 0x0324, 0x8321, + 0x0360, 0x8365, 0x836F, 0x036A, 0x837B, 0x037E, 0x0374, 0x8371, + 0x8353, 0x0356, 0x035C, 0x8359, 0x0348, 0x834D, 0x8347, 0x0342, + 0x03C0, 0x83C5, 0x83CF, 0x03CA, 0x83DB, 0x03DE, 0x03D4, 0x83D1, + 0x83F3, 0x03F6, 0x03FC, 0x83F9, 0x03E8, 0x83ED, 0x83E7, 0x03E2, + 0x83A3, 0x03A6, 0x03AC, 0x83A9, 0x03B8, 0x83BD, 0x83B7, 0x03B2, + 0x0390, 0x8395, 0x839F, 0x039A, 0x838B, 0x038E, 0x0384, 0x8381, + 0x0280, 0x8285, 0x828F, 0x028A, 0x829B, 0x029E, 0x0294, 0x8291, + 0x82B3, 0x02B6, 0x02BC, 0x82B9, 0x02A8, 0x82AD, 0x82A7, 0x02A2, + 0x82E3, 0x02E6, 0x02EC, 0x82E9, 0x02F8, 0x82FD, 0x82F7, 0x02F2, + 0x02D0, 0x82D5, 0x82DF, 0x02DA, 0x82CB, 0x02CE, 0x02C4, 0x82C1, + 0x8243, 0x0246, 0x024C, 0x8249, 0x0258, 0x825D, 0x8257, 0x0252, + 0x0270, 0x8275, 0x827F, 0x027A, 0x826B, 0x026E, 0x0264, 0x8261, + 0x0220, 0x8225, 0x822F, 0x022A, 0x823B, 0x023E, 0x0234, 0x8231, + 0x8213, 0x0216, 0x021C, 0x8219, 0x0208, 0x820D, 0x8207, 0x0202 +}; + +// CRC-8-MAXIM G(X)=X8+X5+X4+1 +const uint8_t crc8_31_msb_lut[256] = { + 0x00, 0x31, 0x62, 0x53, 0xC4, 0xF5, 0xA6, 0x97, + 0xB9, 0x88, 0xDB, 0xEA, 0x7D, 0x4C, 0x1F, 0x2E, + 0x43, 0x72, 0x21, 0x10, 0x87, 0xB6, 0xE5, 0xD4, + 0xFA, 0xCB, 0x98, 0xA9, 0x3E, 0x0F, 0x5C, 0x6D, + 0x86, 0xB7, 0xE4, 0xD5, 0x42, 0x73, 0x20, 0x11, + 0x3F, 0x0E, 0x5D, 0x6C, 0xFB, 0xCA, 0x99, 0xA8, + 0xC5, 0xF4, 0xA7, 0x96, 0x01, 0x30, 0x63, 0x52, + 0x7C, 0x4D, 0x1E, 0x2F, 0xB8, 0x89, 0xDA, 0xEB, + 0x3D, 0x0C, 0x5F, 0x6E, 0xF9, 0xC8, 0x9B, 0xAA, + 0x84, 0xB5, 0xE6, 0xD7, 0x40, 0x71, 0x22, 0x13, + 0x7E, 0x4F, 0x1C, 0x2D, 0xBA, 0x8B, 0xD8, 0xE9, + 0xC7, 0xF6, 0xA5, 0x94, 0x03, 0x32, 0x61, 0x50, + 0xBB, 0x8A, 0xD9, 0xE8, 0x7F, 0x4E, 0x1D, 0x2C, + 0x02, 0x33, 0x60, 0x51, 0xC6, 0xF7, 0xA4, 0x95, + 0xF8, 0xC9, 0x9A, 0xAB, 0x3C, 0x0D, 0x5E, 0x6F, + 0x41, 0x70, 0x23, 0x12, 0x85, 0xB4, 0xE7, 0xD6, + 0x7A, 0x4B, 0x18, 0x29, 0xBE, 0x8F, 0xDC, 0xED, + 0xC3, 0xF2, 0xA1, 0x90, 0x07, 0x36, 0x65, 0x54, + 0x39, 0x08, 0x5B, 0x6A, 0xFD, 0xCC, 0x9F, 0xAE, + 0x80, 0xB1, 0xE2, 0xD3, 0x44, 0x75, 0x26, 0x17, + 0xFC, 0xCD, 0x9E, 0xAF, 0x38, 0x09, 0x5A, 0x6B, + 0x45, 0x74, 0x27, 0x16, 0x81, 0xB0, 0xE3, 0xD2, + 0xBF, 0x8E, 0xDD, 0xEC, 0x7B, 0x4A, 0x19, 0x28, + 0x06, 0x37, 0x64, 0x55, 0xC2, 0xF3, 0xA0, 0x91, + 0x47, 0x76, 0x25, 0x14, 0x83, 0xB2, 0xE1, 0xD0, + 0xFE, 0xCF, 0x9C, 0xAD, 0x3A, 0x0B, 0x58, 0x69, + 0x04, 0x35, 0x66, 0x57, 0xC0, 0xF1, 0xA2, 0x93, + 0xBD, 0x8C, 0xDF, 0xEE, 0x79, 0x48, 0x1B, 0x2A, + 0xC1, 0xF0, 0xA3, 0x92, 0x05, 0x34, 0x67, 0x56, + 0x78, 0x49, 0x1A, 0x2B, 0xBC, 0x8D, 0xDE, 0xEF, + 0x82, 0xB3, 0xE0, 0xD1, 0x46, 0x77, 0x24, 0x15, + 0x3B, 0x0A, 0x59, 0x68, 0xFF, 0xCE, 0x9D, 0xAC +}; +#endif + +/* CRC lookup table algorithm +#define CRC_BIT_NUM 8u/16u/32u/64u +#define BITS_IN_BYTE 8u +uint8_t dataBuff[ARRAY_SIZE] = { 0x32, 0x33, …}; +uint8_t/uint16_t/uint32_t crc_val = 0x0; +// LSB +for(int i = 0; i < sizeof(dataBuff); i++) +{ + crc_val = (crc_val >> BITS_IN_BYTE) ^ crc_lsb_lut[(uint8)(crc_val^dataBuff[i])]; +} +// MSB +for(int i = 0; i < sizeof(dataBuff); i++) +{ + crc_val = (crc_val << BITS_IN_BYTE) ^ crc_msb_lut[(uint8)((crc_val>>8)^dataBuff[i])]; +} +*/ + +/*****************************************************************************/ +/** + * @brief CRC8 generator + * + * @param buffPtr data buffer pointer. + * @param dataLen data length + * @param poly polynomials of crc + * @param crcVal a pointer to store generated crc value + * + * @return SUCCESS + * FAILURE + * + ******************************************************************************/ +int crc8_gen(uint8_t* buffPtr, uint32_t dataLen, uint16_t poly, uint8_t* crcVal) { + uint8_t crc = CRC8_INIT; + const uint8_t* crc_lut = NULL; + + switch(poly){ +#ifdef __CRC_LSB + case 0x31: + crc_lut = crc8_31_lsb_lut; + break; + default: + return FAILURE; +#else + case 0x31: + crc_lut = crc8_31_msb_lut; + break; + default: + return FAILURE; +#endif + } + + for(int i = 0; i < dataLen; i++){ + crc = crc_lut[(uint8_t)(crc^buffPtr[i])]; + } + *crcVal = crc; + return SUCCESS; +} + + +/*****************************************************************************/ +/** + * @brief CRC16 generator + * + * @param buffPtr data buffer pointer. + * @param dataLen data length + * @param poly polynomials of crc + * @param crcVal a pointer to store generated crc value + * + * @return SUCCESS + * FAILURE + * + ******************************************************************************/ +int crc16_gen(uint8_t* buffPtr, uint32_t dataLen, uint16_t poly, uint16_t* crcVal) { + uint16_t crc = CRC16_INIT; + const uint16_t* crc_lut = NULL; + switch(poly){ +#ifdef __CRC_LSB + case 0x8005: + crc_lut = crc16_8005_lsb_lut; + break; + case 0x1021: + crc_lut = crc16_1021_lsb_lut; + break; + default: + return FAILURE; +#else + case 0x8005: + crc_lut = crc16_8005_msb_lut; + break; + case 0x1021: + crc_lut = crc16_1021_msb_lut; + break; + default: + return FAILURE; +#endif + } + for(int i = 0; i < dataLen; i++){ +#ifdef __CRC_LSB + crc = (crc>>8) ^ crc_lut[(uint8_t)(crc^buffPtr[i])]; +#else + crc = (crc<<8) ^ crc_lut[(uint8_t)((crc >> 8)^buffPtr[i])]; +#endif + } + *crcVal = crc; + return SUCCESS; +} + +/*****************************************************************************/ +/** + * @brief CRC8 compare cheker + * + * @param buffPtr data buffer pointer. + * @param dataLen data length + * @param crcOffset byte offset of crc stored position. + * @param poly polynomials of crc + * + * @return true + * false + * +******************************************************************************/ +bool crc8_check(uint8_t* buffPtr, uint32_t dataLen, uint32_t crcOffset, uint16_t poly) { + int Status = SUCCESS; + uint8_t crc_comp; + uint8_t crc; + if (dataLen == 0) { + return false; + } + crc_comp = (uint8_t)(*(buffPtr + crcOffset)); + Status = crc8_gen(buffPtr, dataLen, poly, &crc); + if(Status == SUCCESS){ + if (crc == crc_comp) { + return true; + } + else { + return false; + } + } + else{ + return false; + } +} + + +/*****************************************************************************/ +/** + * @brief CRC16 compare cheker + * + * @param buffPtr data buffer pointer. + * @param dataLen data length + * @param crcOffset byte offset of crc stored position. + * @param poly polynomials of crc + * + * @return true + * fasle + * +******************************************************************************/ +bool crc16_check(uint8_t* buffPtr, uint32_t dataLen, uint32_t crcOffset, uint16_t poly) { + int Status = SUCCESS; + uint16_t crc_comp; + uint16_t crc; + if (dataLen == 0) { + return false; + } + crc_comp = (uint16_t)(*(buffPtr + crcOffset)); + crc_comp |= (uint16_t)((*(buffPtr + crcOffset + 1)) << 8); + Status = crc16_gen(buffPtr, dataLen, poly, &crc); + if(Status == SUCCESS){ + if (crc == crc_comp) { + return true; + } + else { + return false; + } + } + else{ + return false; + } +} diff --git a/df_datalink/src/util/list.c b/df_datalink/src/util/list.c new file mode 100644 index 0000000..e15f057 --- /dev/null +++ b/df_datalink/src/util/list.c @@ -0,0 +1,873 @@ +/***************************************************************************//** + * @file list.c + * @brief List library implementation + * @author Mihail Chindris (mihail.chindris@analog.com) +******************************************************************************** + * Copyright 2020(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include "list.h" +#include "error.h" +#include + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ + +/** + * @struct list_elem + * @brief Format of each element of the list + */ +struct list_elem { + /** User data */ + void *data; + /** Reference to previous element */ + struct list_elem *prev; + /** Reference to next element */ + struct list_elem *next; +}; + +/** + * @struct list_iterator + * @brief Structure used to iterate through the list + */ +struct iterator { + /** List reference */ + struct _list_desc *list; + /** Current element reference */ + struct list_elem *elem; +}; + +/** + * @struct _list_desc + * @brief List descriptor + */ +struct _list_desc { + /** Reference to first element in the list */ + struct list_elem *first; + /** Reference to last element in the list*/ + struct list_elem *last; + /** Number of elements in the list */ + uint32_t nb_elements; + /** Function used to compare elements */ + f_cmp comparator; + /** Number of current active iterators */ + uint32_t nb_iterators; + /** Internal list iterator */ + struct iterator l_it; +}; + +/** @brief Default function used to compare element in the list ( \ref f_cmp) */ +static int32_t default_comparator(void *data1, void *data2) +{ + return (int32_t)((int32_t *)data1 - (int32_t *)data2); +} + +/** + * @brief Creates a new list elements an configure its value + * @param data - To set list_elem.data + * @param prev - To set list_elem.prev + * @param next - To set list_elem.next + * @return Address of the new element or NULL if allocation fails. + */ +static inline struct list_elem *create_element(void *data, + struct list_elem *prev, + struct list_elem *next) +{ + struct list_elem *elem; + + elem = (struct list_elem *)calloc(1, sizeof(*elem)); + if (!elem) + return NULL; + elem->data = data; + elem->prev = prev; + elem->next = next; + + return (elem); +} + +/** + * @brief Updates the necesary link on the list elements to add or remove one + * @param prev - Low element + * @param elem - Middle element + * @param next - High element + */ +static inline void update_links(struct list_elem *prev, struct list_elem *elem, + struct list_elem *next) +{ + if (prev) + prev->next = elem ? elem : next; + if (elem) { + elem->prev = prev; + elem->next = next; + } + if (next) + next->prev = elem ? elem : prev; +} + +/** + * @brief Update according to modification the list descriptor + * @param list - List reference + * @param new_first - New first element + * @param new_last - New last element + */ +static inline void update_desc(struct _list_desc *list, + struct list_elem *new_first, + struct list_elem *new_last) +{ + if (new_first == list->first) { + list->last = new_last; + if (new_first == NULL || new_last == NULL) + list->first = new_last; + } else { /* if (new_last == list->last) */ + list->first = new_first; + if (new_last == NULL || new_first == NULL) + list->last = new_first; + } +} + +/** + * @brief Set the adapter functions acording to the adapter type + * @param ad - Reference of the adapter + * @param type - Type of the adapter + */ +static inline void set_adapter(struct list_desc *ad, enum adapter_type type) +{ + switch (type) { + case LIST_PRIORITY_LIST: + ad->push = list_add_find; + ad->pop = list_get_first; + ad->top_next = list_read_first; + ad->back = list_read_last; + ad->swap = list_edit_first; + break; + case LIST_QUEUE: + ad->push = list_add_last; + ad->pop = list_get_first; + ad->top_next = list_read_first; + ad->back = list_read_last; + ad->swap = list_edit_first; + break; + case LIST_DEFAULT: + case LIST_STACK: + default: + ad->push = list_add_last; + ad->pop = list_get_last; + ad->top_next = list_read_last; + ad->back = list_read_first; + ad->swap = list_edit_last; + break; + } +} + +/** + * @brief Create a new empty list + * @param list_desc - Where to store the reference of the new created list + * @param type - Type of adapter to use. + * @param comparator - Used to compare item when using an ordered list or when + * using the \em find functions. + * @return + * - \ref SUCCESS : On success + * - \ref FAILURE : Otherwise + */ +int32_t list_init(struct list_desc **list_desc, enum adapter_type type, + f_cmp comparator) +{ + struct list_desc *l_desc; + struct _list_desc *list; + + + if (!list_desc) + return FAILURE; + l_desc = (struct list_desc *)calloc(1, sizeof(*l_desc)); + if (!l_desc) + return FAILURE; + list = (struct _list_desc *)calloc(1, sizeof(*list)); + if (!list) { + free(l_desc); + return FAILURE; + } + + *list_desc = l_desc; + l_desc->priv_desc = list; + list->comparator = comparator ? comparator : default_comparator; + + /* Configure wrapper */ + set_adapter(l_desc, type); + list->l_it.list = list; + + return SUCCESS; +} + +/** + * @brief Remove the created list. + * + * All its elements will be cleared and the data inside each will be lost. If + * not all iterators have been removed, the list will not be removed. + * @param list_desc - Reference to the list + * @return + * - \ref SUCCESS : On success + * - \ref FAILURE : Otherwise + */ +int32_t list_remove(struct list_desc *list_desc) +{ + void *data; + struct _list_desc *list; + + if (!list_desc) + return FAILURE; + + list = list_desc->priv_desc; + if (list->nb_iterators != 0) + return FAILURE; + + /* Remove all the elements */ + while (SUCCESS == list_get_first(list_desc, &data)) + ; + free(list_desc->priv_desc); + free(list_desc); + + return SUCCESS; +} + +/** + * @brief Get the number of elements inside the list + * @param list_desc - List reference + * @param out_size - Where to store the number of elements + * @return + * - \ref SUCCESS : On success + * - \ref FAILURE : Otherwise + */ +int32_t list_get_size(struct list_desc *list_desc, uint32_t *out_size) +{ + struct _list_desc *list; + + if (!list_desc || !out_size) + return FAILURE; + + list = list_desc->priv_desc; + *out_size = list->nb_elements; + + return SUCCESS; +} + +/** @brief Add element at the begining of the list. Refer to \ref f_add */ +int32_t list_add_first(struct list_desc *list_desc, void *data) +{ + struct list_elem *prev; + struct list_elem *next; + struct list_elem *elem; + struct _list_desc *list; + + if (!list_desc) + return FAILURE; + + list = list_desc->priv_desc; + + prev = NULL; + next = list->first; + elem = create_element(data, prev, next); + if (!elem) + return FAILURE; + + update_links(prev, elem, next); + + update_desc(list, elem, list->last); + + list->nb_elements++; + + return SUCCESS; +} + +/** @brief Add element at the end of the list. Refer to \ref f_add */ +int32_t list_add_last(struct list_desc *list_desc, void *data) +{ + struct list_elem *prev; + struct list_elem *next; + struct list_elem *elem; + struct _list_desc *list; + + if (!list_desc) + return FAILURE; + list = list_desc->priv_desc; + + prev = list->last; + next = NULL; + elem = create_element(data, prev, next); + if (!elem) + return FAILURE; + + update_links(prev, elem, next); + + update_desc(list, list->first, elem); + + list->nb_elements++; + + return SUCCESS; +} + +/** @brief Add element at the specified idx. Refer to \ref f_add */ +int32_t list_add_idx(struct list_desc *list_desc, void *data, uint32_t idx) +{ + struct _list_desc *list; + + if (!list_desc) + return FAILURE; + list = list_desc->priv_desc; + + /* If there are no elements the creation of an iterator will fail */ + if (list->nb_elements == 0 || idx == 0) + return list_add_first(list_desc, data); + if (list->nb_elements == idx) + return list_add_last(list_desc, data); + + list->l_it.elem = list->first; + if (SUCCESS != iterator_move(&(list->l_it), idx)) + return FAILURE; + + return iterator_insert(&(list->l_it), data, 0); +} + +/** @brief Add element in ascending order. Refer to \ref f_add */ +int32_t list_add_find(struct list_desc *list_desc, void *data) +{ + struct list_elem *elem; + struct _list_desc *list; + + if (!list_desc) + return FAILURE; + list = list_desc->priv_desc; + + + /* Based on place iterator */ + elem = list->first; + while (elem) { + if (0 < list->comparator(elem->data, data)) + break; + elem = elem->next; + } + if (elem == NULL) { + list->l_it.elem = list->last; + return iterator_insert(&(list->l_it), data, 1); + } else { + list->l_it.elem = elem; + return iterator_insert(&(list->l_it), data, 0); + } + +} + +/** @brief Edit the first element of the list. Refer to \ref f_edit */ +int32_t list_edit_first(struct list_desc *list_desc, void *new_data) +{ + struct _list_desc *list; + + if (!list_desc) + return FAILURE; + + list = list_desc->priv_desc; + list->first->data = new_data; + + return SUCCESS; +} + +/** @brief Edit the last element of the list. Refer to \ref f_edit */ +int32_t list_edit_last(struct list_desc *list_desc, void *new_data) +{ + struct _list_desc *list; + + if (!list_desc) + return FAILURE; + + list = list_desc->priv_desc; + list->last->data = new_data; + + return SUCCESS; +} + +/** @brief Edit the element at the specified idx. Refer to \ref f_edit */ +int32_t list_edit_idx(struct list_desc *list_desc, void *new_data, uint32_t idx) +{ + struct _list_desc *list; + + if (!list_desc) + return FAILURE; + list = list_desc->priv_desc; + + list->l_it.elem = list->first; + if (SUCCESS != iterator_move(&(list->l_it), idx)) + return FAILURE; + + return iterator_edit(&(list->l_it), new_data); +} + +/** @brief Edit the element which match with cmp_data. Refer to \ref f_edit */ +int32_t list_edit_find(struct list_desc *list_desc, void *new_data, + void *cmp_data) +{ + struct _list_desc *list; + + if (!list_desc) + return FAILURE; + list = list_desc->priv_desc; + + list->l_it.elem = list->first; + if (SUCCESS != iterator_find(&(list->l_it), cmp_data)) + return FAILURE; + + return iterator_edit(&(list->l_it), new_data); +} + +/** @brief Read the first element of the list. Refer to \ref f_read */ +int32_t list_read_first(struct list_desc *list_desc, void **data) +{ + struct _list_desc *list; + + if (!list_desc || !data) + return FAILURE; + + *data = NULL; + list = list_desc->priv_desc; + if (!list->first) + return FAILURE; + + *data = list->first->data; + + return SUCCESS; +} + +/** @brief Read the last element of the list. Refer to \ref f_read */ +int32_t list_read_last(struct list_desc *list_desc, void **data) +{ + struct _list_desc *list; + + if (!list_desc || !data) + return FAILURE; + + *data = NULL; + list = list_desc->priv_desc; + if (!list->last) + return FAILURE; + + *data = list->last->data; + + return SUCCESS; +} + +/** @brief Read the element at the specified idx. Refer to \ref f_read */ +int32_t list_read_idx(struct list_desc *list_desc, void **data, uint32_t idx) +{ + struct _list_desc *list; + + if (!list_desc || !data) + return FAILURE; + + *data = NULL; + list = list_desc->priv_desc; + if (!list) + return FAILURE; + + if (idx >= list->nb_elements) + return FAILURE; + + list->l_it.elem = list->first; + if (SUCCESS != iterator_move(&(list->l_it), idx)) + return FAILURE; + + return iterator_read(&(list->l_it), data); +} + +/** @brief Read the element which match with cmp_data. Refer to \ref f_read */ +int32_t list_read_find(struct list_desc *list_desc, void **data, + void *cmp_data) +{ + struct _list_desc *list; + + if (!list_desc || !data) + return FAILURE; + + *data = NULL; + list = list_desc->priv_desc; + if (!list) + return FAILURE; + + list = list_desc->priv_desc; + list->l_it.elem = list->first; + if (SUCCESS != iterator_find(&(list->l_it), cmp_data)) + return FAILURE; + + return iterator_read(&(list->l_it), data); +} + +/** @brief Read and delete the first element of the list. Refer to \ref f_get */ +int32_t list_get_first(struct list_desc *list_desc, void **data) +{ + struct list_elem *prev; + struct list_elem *next; + struct list_elem *elem; + struct _list_desc *list; + + if (!list_desc || !data) + return FAILURE; + + *data = NULL; + list = list_desc->priv_desc; + if (!list->nb_elements) + return FAILURE; + + elem = list->first; + prev = elem->prev; + next = elem->next; + + update_links(prev, NULL, next); + update_desc(list, next, list->last); + list->nb_elements--; + + *data = elem->data; + free(elem); + + return SUCCESS; +} + +/** @brief Read and delete the last element of the list. Refer to \ref f_get */ +int32_t list_get_last(struct list_desc *list_desc, void **data) +{ + struct list_elem *prev; + struct list_elem *next; + struct list_elem *elem; + struct _list_desc *list; + + if (!list_desc || !data) + return FAILURE; + + *data = NULL; + list = list_desc->priv_desc; + if (!list->nb_elements) + return FAILURE; + + elem = list->last; + prev = elem->prev; + next = elem->next; + + update_links(prev, NULL, next); + update_desc(list, list->first, prev); + list->nb_elements--; + + *data = elem->data; + free(elem); + + return SUCCESS; +} + +/** @brief Read and delete the element at idx. Refer to \ref f_get */ +int32_t list_get_idx(struct list_desc *list_desc, void **data, uint32_t idx) +{ + struct _list_desc *list; + + if (!list_desc || !data) + return FAILURE; + + *data = NULL; + list = list_desc->priv_desc; + list->l_it.elem = list->first; + if (SUCCESS != iterator_move(&(list->l_it), idx)) + return FAILURE; + + return iterator_get(&(list->l_it), data); +} + +/** + * @brief Read and delete the element which match with cmp_data. + * Refer to \ref f_get + */ +int32_t list_get_find(struct list_desc *list_desc, void **data, void *cmp_data) +{ + struct _list_desc *list; + + if (!list_desc || !data) + return FAILURE; + + *data = NULL; + list = list_desc->priv_desc; + list->l_it.elem = list->first; + if (SUCCESS != iterator_find(&(list->l_it), cmp_data)) + return FAILURE; + + return iterator_get(&(list->l_it), data); +} + +/** + * @brief Create a new iterator + * @param iter - Where to store the reference for the new iterator + * @param list_desc - Reference of the list the iterator will be used for + * @param start - If it is true the iterator will be positioned at the first + * element of the list, else it will be positioned at the last. + * @return + * - \ref SUCCESS : On success + * - \ref FAILURE : Otherwise + */ +int32_t iterator_init(struct iterator **iter, struct list_desc *list_desc, + bool start) +{ + struct iterator *it; + + if (!list_desc) + return FAILURE; + + it = (struct iterator *)calloc(1, sizeof(*it)); + if (!it) + return FAILURE; + it->list = list_desc->priv_desc; + it->list->nb_iterators++; + it->elem = start ? it->list->first : it->list->last; + *iter = it; + + return SUCCESS; +} + +/** + * @brief Remove the created iterator + * @param iter - Reference of the iterator + * @return + * - \ref SUCCESS : On success + * - \ref FAILURE : Otherwise + */ +int32_t iterator_remove(struct iterator *iter) +{ + struct iterator *it = iter; + + if (!it) + return FAILURE; + + it->list->nb_iterators--; + free(it); + + return SUCCESS; +} + +/** + * @brief Move the position of the iteration through the list. + * + * If the required position is outside the list, the call will fail and the + * iterator will keep its position. + * @param iter - Reference of the iterator + * @param steps - Number of positions to be move. If positive, it will be moved + * forward, otherwise backwords. + * @return + * - \ref SUCCESS : On success + * - \ref FAILURE : Otherwise + */ +int32_t iterator_move(struct iterator *iter, int32_t steps) +{ + struct iterator *it = iter; + struct list_elem *elem; + int32_t dir = (steps < 0) ? -1 : 1; + + if (!it) + return FAILURE; + + steps = abs(steps); + elem = it->elem; + while (steps > 0 && elem) { + elem = dir > 0 ? elem->next : elem->prev; + steps--; + } + if (!elem) + return FAILURE; + + it->elem = elem; + + return SUCCESS; +} + +/** + * @brief Move the position of the iterator at the specified index of the list. + * + * @param iter - Reference of the iterator + * @param idx - Position in the list. If negative start counting backwords + * @return + * - \ref SUCCESS : On success + * - \ref FAILURE : Otherwise + */ +int32_t iterator_move_to_idx(struct iterator *iter, int32_t idx) +{ + struct list_elem *elem; + int32_t dir = (idx < 0) ? -1 : 1; + + if (!iter) + return FAILURE; + + idx = abs(idx); + elem = dir > 0 ? iter->list->first : iter->list->last; + while (idx > 0 && elem) { + elem = dir > 0 ? elem->next : elem->prev; + idx--; + } + if (!elem) + return FAILURE; + + iter->elem = elem; + + return SUCCESS; +} + +/** + * @brief Place the iterator where cmp_data if found. + * @param iter - Reference to the iterator + * @param cmp_data - Data to be found + * @return + * - \ref SUCCESS : On success + * - \ref FAILURE : Otherwise + */ +int32_t iterator_find(struct iterator *iter, void *cmp_data) +{ + struct iterator *it = iter; + struct list_elem *elem; + + if (!it) + return FAILURE; + + elem = it->list->first; + while (elem) { + if (0 == it->list->comparator(elem->data, cmp_data)) { + it->elem = elem; + return SUCCESS; + } + elem = elem->next; + } + + return FAILURE; +} + +/** + * @brief Replace the data at the current position. Refer to \ref f_edit + */ +int32_t iterator_edit(struct iterator *iter, void *new_data) +{ + struct iterator *it = iter; + + if (!it) + return FAILURE; + + it->elem->data = new_data; + + return SUCCESS; +} + +/** + * @brief Read and remove the data at the current position. Refer to \ref f_get. + * + * If the current item is the last one, the iterator will be moved to the + * previous one. + */ +int32_t iterator_get(struct iterator *iter, void **data) +{ + struct iterator *it = iter; + struct list_elem *next; + + + if (!it || !it->elem || !data) + return FAILURE; + + update_links(it->elem->prev, NULL, it->elem->next); + if (it->elem == it->list->first) + update_desc(it->list, it->elem->next, it->list->last); + else if (it->elem == it->list->last) + update_desc(it->list, it->list->first, it->elem->prev); + it->list->nb_elements--; + + *data = it->elem->data; + if (it->elem == it->list->last) + next = it->elem->prev; + else + next = it->elem->next; + free(it->elem); + it->elem = next; + + return SUCCESS; +} + +/** + * @brief Read the data at the current position. Refer to \ref f_read + */ +int32_t iterator_read(struct iterator *iter, void **data) +{ + struct iterator *it = iter; + + if (!it || !it->elem || !data) + return FAILURE; + + *data = it->elem->data; + + return SUCCESS; +} + +/** + * @brief Insert an item in the list. Refer to \ref f_add + * @param iter + * @param data + * @param after - If true, the item will be inserted after the current position. + * Otherwise it will be inserted before. + */ +int32_t iterator_insert(struct iterator *iter, void *data, bool after) +{ + struct iterator *it = iter; + struct list_elem *elem; + struct list_desc list_desc; + + if (!it) + return FAILURE; + + list_desc.priv_desc = iter->list; + if (after && it->elem == it->list->last) + return list_add_last(&list_desc, data); + if (!after && it->elem == it->list->first) + return list_add_first(&list_desc, data); + + if (after) + elem = create_element(data, it->elem, it->elem->next); + else + elem = create_element(data, it->elem->prev, it->elem); + if (!elem) + return FAILURE; + + update_links(elem->prev, elem, elem->next); + + it->list->nb_elements++; + + return SUCCESS; +} diff --git a/df_datalink/src/util/tables.txt b/df_datalink/src/util/tables.txt new file mode 100644 index 0000000..b3bff8c --- /dev/null +++ b/df_datalink/src/util/tables.txt @@ -0,0 +1,231 @@ +Generating CRC table for crc8-31-lsb + +0x00, 0x5E, 0xBC, 0xE2, 0x61, 0x3F, 0xDD, 0x83, +0xC2, 0x9C, 0x7E, 0x20, 0xA3, 0xFD, 0x1F, 0x41, +0x9D, 0xC3, 0x21, 0x7F, 0xFC, 0xA2, 0x40, 0x1E, +0x5F, 0x01, 0xE3, 0xBD, 0x3E, 0x60, 0x82, 0xDC, +0x23, 0x7D, 0x9F, 0xC1, 0x42, 0x1C, 0xFE, 0xA0, +0xE1, 0xBF, 0x5D, 0x03, 0x80, 0xDE, 0x3C, 0x62, +0xBE, 0xE0, 0x02, 0x5C, 0xDF, 0x81, 0x63, 0x3D, +0x7C, 0x22, 0xC0, 0x9E, 0x1D, 0x43, 0xA1, 0xFF, +0x46, 0x18, 0xFA, 0xA4, 0x27, 0x79, 0x9B, 0xC5, +0x84, 0xDA, 0x38, 0x66, 0xE5, 0xBB, 0x59, 0x07, +0xDB, 0x85, 0x67, 0x39, 0xBA, 0xE4, 0x06, 0x58, +0x19, 0x47, 0xA5, 0xFB, 0x78, 0x26, 0xC4, 0x9A, +0x65, 0x3B, 0xD9, 0x87, 0x04, 0x5A, 0xB8, 0xE6, +0xA7, 0xF9, 0x1B, 0x45, 0xC6, 0x98, 0x7A, 0x24, +0xF8, 0xA6, 0x44, 0x1A, 0x99, 0xC7, 0x25, 0x7B, +0x3A, 0x64, 0x86, 0xD8, 0x5B, 0x05, 0xE7, 0xB9, +0x8C, 0xD2, 0x30, 0x6E, 0xED, 0xB3, 0x51, 0x0F, +0x4E, 0x10, 0xF2, 0xAC, 0x2F, 0x71, 0x93, 0xCD, +0x11, 0x4F, 0xAD, 0xF3, 0x70, 0x2E, 0xCC, 0x92, +0xD3, 0x8D, 0x6F, 0x31, 0xB2, 0xEC, 0x0E, 0x50, +0xAF, 0xF1, 0x13, 0x4D, 0xCE, 0x90, 0x72, 0x2C, +0x6D, 0x33, 0xD1, 0x8F, 0x0C, 0x52, 0xB0, 0xEE, +0x32, 0x6C, 0x8E, 0xD0, 0x53, 0x0D, 0xEF, 0xB1, +0xF0, 0xAE, 0x4C, 0x12, 0x91, 0xCF, 0x2D, 0x73, +0xCA, 0x94, 0x76, 0x28, 0xAB, 0xF5, 0x17, 0x49, +0x08, 0x56, 0xB4, 0xEA, 0x69, 0x37, 0xD5, 0x8B, +0x57, 0x09, 0xEB, 0xB5, 0x36, 0x68, 0x8A, 0xD4, +0x95, 0xCB, 0x29, 0x77, 0xF4, 0xAA, 0x48, 0x16, +0xE9, 0xB7, 0x55, 0x0B, 0x88, 0xD6, 0x34, 0x6A, +0x2B, 0x75, 0x97, 0xC9, 0x4A, 0x14, 0xF6, 0xA8, +0x74, 0x2A, 0xC8, 0x96, 0x15, 0x4B, 0xA9, 0xF7, +0xB6, 0xE8, 0x0A, 0x54, 0xD7, 0x89, 0x6B, 0x35, + + +Generating CRC table for crc8-31-msb + +0x00, 0x31, 0x62, 0x53, 0xC4, 0xF5, 0xA6, 0x97, +0xB9, 0x88, 0xDB, 0xEA, 0x7D, 0x4C, 0x1F, 0x2E, +0x43, 0x72, 0x21, 0x10, 0x87, 0xB6, 0xE5, 0xD4, +0xFA, 0xCB, 0x98, 0xA9, 0x3E, 0x0F, 0x5C, 0x6D, +0x86, 0xB7, 0xE4, 0xD5, 0x42, 0x73, 0x20, 0x11, +0x3F, 0x0E, 0x5D, 0x6C, 0xFB, 0xCA, 0x99, 0xA8, +0xC5, 0xF4, 0xA7, 0x96, 0x01, 0x30, 0x63, 0x52, +0x7C, 0x4D, 0x1E, 0x2F, 0xB8, 0x89, 0xDA, 0xEB, +0x3D, 0x0C, 0x5F, 0x6E, 0xF9, 0xC8, 0x9B, 0xAA, +0x84, 0xB5, 0xE6, 0xD7, 0x40, 0x71, 0x22, 0x13, +0x7E, 0x4F, 0x1C, 0x2D, 0xBA, 0x8B, 0xD8, 0xE9, +0xC7, 0xF6, 0xA5, 0x94, 0x03, 0x32, 0x61, 0x50, +0xBB, 0x8A, 0xD9, 0xE8, 0x7F, 0x4E, 0x1D, 0x2C, +0x02, 0x33, 0x60, 0x51, 0xC6, 0xF7, 0xA4, 0x95, +0xF8, 0xC9, 0x9A, 0xAB, 0x3C, 0x0D, 0x5E, 0x6F, +0x41, 0x70, 0x23, 0x12, 0x85, 0xB4, 0xE7, 0xD6, +0x7A, 0x4B, 0x18, 0x29, 0xBE, 0x8F, 0xDC, 0xED, +0xC3, 0xF2, 0xA1, 0x90, 0x07, 0x36, 0x65, 0x54, +0x39, 0x08, 0x5B, 0x6A, 0xFD, 0xCC, 0x9F, 0xAE, +0x80, 0xB1, 0xE2, 0xD3, 0x44, 0x75, 0x26, 0x17, +0xFC, 0xCD, 0x9E, 0xAF, 0x38, 0x09, 0x5A, 0x6B, +0x45, 0x74, 0x27, 0x16, 0x81, 0xB0, 0xE3, 0xD2, +0xBF, 0x8E, 0xDD, 0xEC, 0x7B, 0x4A, 0x19, 0x28, +0x06, 0x37, 0x64, 0x55, 0xC2, 0xF3, 0xA0, 0x91, +0x47, 0x76, 0x25, 0x14, 0x83, 0xB2, 0xE1, 0xD0, +0xFE, 0xCF, 0x9C, 0xAD, 0x3A, 0x0B, 0x58, 0x69, +0x04, 0x35, 0x66, 0x57, 0xC0, 0xF1, 0xA2, 0x93, +0xBD, 0x8C, 0xDF, 0xEE, 0x79, 0x48, 0x1B, 0x2A, +0xC1, 0xF0, 0xA3, 0x92, 0x05, 0x34, 0x67, 0x56, +0x78, 0x49, 0x1A, 0x2B, 0xBC, 0x8D, 0xDE, 0xEF, +0x82, 0xB3, 0xE0, 0xD1, 0x46, 0x77, 0x24, 0x15, +0x3B, 0x0A, 0x59, 0x68, 0xFF, 0xCE, 0x9D, 0xAC, + + +Generating CRC table for crc16-8005-lsb + +0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, +0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440, +0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40, +0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841, +0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40, +0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41, +0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641, +0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040, +0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240, +0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441, +0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41, +0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840, +0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41, +0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40, +0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640, +0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041, +0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240, +0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441, +0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41, +0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840, +0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41, +0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40, +0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640, +0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041, +0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241, +0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440, +0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40, +0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841, +0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40, +0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41, +0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641, +0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040, + + +Generating CRC table for crc16-8005-msb + +0x0000, 0x8005, 0x800F, 0x000A, 0x801B, 0x001E, 0x0014, 0x8011, +0x8033, 0x0036, 0x003C, 0x8039, 0x0028, 0x802D, 0x8027, 0x0022, +0x8063, 0x0066, 0x006C, 0x8069, 0x0078, 0x807D, 0x8077, 0x0072, +0x0050, 0x8055, 0x805F, 0x005A, 0x804B, 0x004E, 0x0044, 0x8041, +0x80C3, 0x00C6, 0x00CC, 0x80C9, 0x00D8, 0x80DD, 0x80D7, 0x00D2, +0x00F0, 0x80F5, 0x80FF, 0x00FA, 0x80EB, 0x00EE, 0x00E4, 0x80E1, +0x00A0, 0x80A5, 0x80AF, 0x00AA, 0x80BB, 0x00BE, 0x00B4, 0x80B1, +0x8093, 0x0096, 0x009C, 0x8099, 0x0088, 0x808D, 0x8087, 0x0082, +0x8183, 0x0186, 0x018C, 0x8189, 0x0198, 0x819D, 0x8197, 0x0192, +0x01B0, 0x81B5, 0x81BF, 0x01BA, 0x81AB, 0x01AE, 0x01A4, 0x81A1, +0x01E0, 0x81E5, 0x81EF, 0x01EA, 0x81FB, 0x01FE, 0x01F4, 0x81F1, +0x81D3, 0x01D6, 0x01DC, 0x81D9, 0x01C8, 0x81CD, 0x81C7, 0x01C2, +0x0140, 0x8145, 0x814F, 0x014A, 0x815B, 0x015E, 0x0154, 0x8151, +0x8173, 0x0176, 0x017C, 0x8179, 0x0168, 0x816D, 0x8167, 0x0162, +0x8123, 0x0126, 0x012C, 0x8129, 0x0138, 0x813D, 0x8137, 0x0132, +0x0110, 0x8115, 0x811F, 0x011A, 0x810B, 0x010E, 0x0104, 0x8101, +0x8303, 0x0306, 0x030C, 0x8309, 0x0318, 0x831D, 0x8317, 0x0312, +0x0330, 0x8335, 0x833F, 0x033A, 0x832B, 0x032E, 0x0324, 0x8321, +0x0360, 0x8365, 0x836F, 0x036A, 0x837B, 0x037E, 0x0374, 0x8371, +0x8353, 0x0356, 0x035C, 0x8359, 0x0348, 0x834D, 0x8347, 0x0342, +0x03C0, 0x83C5, 0x83CF, 0x03CA, 0x83DB, 0x03DE, 0x03D4, 0x83D1, +0x83F3, 0x03F6, 0x03FC, 0x83F9, 0x03E8, 0x83ED, 0x83E7, 0x03E2, +0x83A3, 0x03A6, 0x03AC, 0x83A9, 0x03B8, 0x83BD, 0x83B7, 0x03B2, +0x0390, 0x8395, 0x839F, 0x039A, 0x838B, 0x038E, 0x0384, 0x8381, +0x0280, 0x8285, 0x828F, 0x028A, 0x829B, 0x029E, 0x0294, 0x8291, +0x82B3, 0x02B6, 0x02BC, 0x82B9, 0x02A8, 0x82AD, 0x82A7, 0x02A2, +0x82E3, 0x02E6, 0x02EC, 0x82E9, 0x02F8, 0x82FD, 0x82F7, 0x02F2, +0x02D0, 0x82D5, 0x82DF, 0x02DA, 0x82CB, 0x02CE, 0x02C4, 0x82C1, +0x8243, 0x0246, 0x024C, 0x8249, 0x0258, 0x825D, 0x8257, 0x0252, +0x0270, 0x8275, 0x827F, 0x027A, 0x826B, 0x026E, 0x0264, 0x8261, +0x0220, 0x8225, 0x822F, 0x022A, 0x823B, 0x023E, 0x0234, 0x8231, +0x8213, 0x0216, 0x021C, 0x8219, 0x0208, 0x820D, 0x8207, 0x0202, + + +Generating CRC table for crc16-1021-lsb + +0x0000, 0x1189, 0x2312, 0x329B, 0x4624, 0x57AD, 0x6536, 0x74BF, +0x8C48, 0x9DC1, 0xAF5A, 0xBED3, 0xCA6C, 0xDBE5, 0xE97E, 0xF8F7, +0x1081, 0x0108, 0x3393, 0x221A, 0x56A5, 0x472C, 0x75B7, 0x643E, +0x9CC9, 0x8D40, 0xBFDB, 0xAE52, 0xDAED, 0xCB64, 0xF9FF, 0xE876, +0x2102, 0x308B, 0x0210, 0x1399, 0x6726, 0x76AF, 0x4434, 0x55BD, +0xAD4A, 0xBCC3, 0x8E58, 0x9FD1, 0xEB6E, 0xFAE7, 0xC87C, 0xD9F5, +0x3183, 0x200A, 0x1291, 0x0318, 0x77A7, 0x662E, 0x54B5, 0x453C, +0xBDCB, 0xAC42, 0x9ED9, 0x8F50, 0xFBEF, 0xEA66, 0xD8FD, 0xC974, +0x4204, 0x538D, 0x6116, 0x709F, 0x0420, 0x15A9, 0x2732, 0x36BB, +0xCE4C, 0xDFC5, 0xED5E, 0xFCD7, 0x8868, 0x99E1, 0xAB7A, 0xBAF3, +0x5285, 0x430C, 0x7197, 0x601E, 0x14A1, 0x0528, 0x37B3, 0x263A, +0xDECD, 0xCF44, 0xFDDF, 0xEC56, 0x98E9, 0x8960, 0xBBFB, 0xAA72, +0x6306, 0x728F, 0x4014, 0x519D, 0x2522, 0x34AB, 0x0630, 0x17B9, +0xEF4E, 0xFEC7, 0xCC5C, 0xDDD5, 0xA96A, 0xB8E3, 0x8A78, 0x9BF1, +0x7387, 0x620E, 0x5095, 0x411C, 0x35A3, 0x242A, 0x16B1, 0x0738, +0xFFCF, 0xEE46, 0xDCDD, 0xCD54, 0xB9EB, 0xA862, 0x9AF9, 0x8B70, +0x8408, 0x9581, 0xA71A, 0xB693, 0xC22C, 0xD3A5, 0xE13E, 0xF0B7, +0x0840, 0x19C9, 0x2B52, 0x3ADB, 0x4E64, 0x5FED, 0x6D76, 0x7CFF, +0x9489, 0x8500, 0xB79B, 0xA612, 0xD2AD, 0xC324, 0xF1BF, 0xE036, +0x18C1, 0x0948, 0x3BD3, 0x2A5A, 0x5EE5, 0x4F6C, 0x7DF7, 0x6C7E, +0xA50A, 0xB483, 0x8618, 0x9791, 0xE32E, 0xF2A7, 0xC03C, 0xD1B5, +0x2942, 0x38CB, 0x0A50, 0x1BD9, 0x6F66, 0x7EEF, 0x4C74, 0x5DFD, +0xB58B, 0xA402, 0x9699, 0x8710, 0xF3AF, 0xE226, 0xD0BD, 0xC134, +0x39C3, 0x284A, 0x1AD1, 0x0B58, 0x7FE7, 0x6E6E, 0x5CF5, 0x4D7C, +0xC60C, 0xD785, 0xE51E, 0xF497, 0x8028, 0x91A1, 0xA33A, 0xB2B3, +0x4A44, 0x5BCD, 0x6956, 0x78DF, 0x0C60, 0x1DE9, 0x2F72, 0x3EFB, +0xD68D, 0xC704, 0xF59F, 0xE416, 0x90A9, 0x8120, 0xB3BB, 0xA232, +0x5AC5, 0x4B4C, 0x79D7, 0x685E, 0x1CE1, 0x0D68, 0x3FF3, 0x2E7A, +0xE70E, 0xF687, 0xC41C, 0xD595, 0xA12A, 0xB0A3, 0x8238, 0x93B1, +0x6B46, 0x7ACF, 0x4854, 0x59DD, 0x2D62, 0x3CEB, 0x0E70, 0x1FF9, +0xF78F, 0xE606, 0xD49D, 0xC514, 0xB1AB, 0xA022, 0x92B9, 0x8330, +0x7BC7, 0x6A4E, 0x58D5, 0x495C, 0x3DE3, 0x2C6A, 0x1EF1, 0x0F78, + + +Generating CRC table for crc16-1021-msb + +0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, +0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, +0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, +0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, +0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485, +0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D, +0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4, +0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC, +0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823, +0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, +0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, +0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, +0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, +0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49, +0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70, +0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78, +0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F, +0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067, +0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, +0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, +0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, +0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, +0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C, +0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634, +0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB, +0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3, +0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, +0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, +0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, +0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, +0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, +0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0, + + + +#define CRC_BIT_NUM 8u/16u/32u/64u +#define BITS_IN_BYTE 8u +uint8_t dataBuff[ARRAY_SIZE] = { 0x32, 0x33, ...; +uint8_t/uint16_t/uint32_t crc_val = 0x0; +// LSB +for(int i = 0; i < sizeof(dataBuff); i++) +{ + crc_val = (crc_val >> BITS_IN_BYTE) ^ crc_lsb_lut[(uint8)(crc_val^dataBuff[i])]; +} +// MSB +for(int i = 0; i < sizeof(dataBuff); i++) +{ + crc_val = (crc_val << BITS_IN_BYTE) ^ crc_msb_lut[(uint8)((crc_val>>8)^dataBuff[i])]; +} \ No newline at end of file diff --git a/df_datalink/src/util/util.c b/df_datalink/src/util/util.c new file mode 100644 index 0000000..76562ab --- /dev/null +++ b/df_datalink/src/util/util.c @@ -0,0 +1,351 @@ +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include +#include +#include +#include "util.h" +#include "error.h" + +/******************************************************************************/ +/************************** Functions Implementation **************************/ +/******************************************************************************/ +#ifdef __BITSWAP_TABLE +static uint8_t byte_flipLR[256] = { + 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, + 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0, + 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, + 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, + 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, + 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4, + 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, + 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC, + 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, + 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2, + 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, + 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA, + 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, + 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6, + 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, + 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE, + 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, + 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1, + 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, + 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9, + 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, + 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5, + 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, + 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD, + 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, + 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3, + 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, + 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB, + 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, + 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7, + 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, + 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF +}; +#endif + +inline void IO_Out32(uintptr_t addr, uint32_t value){ + volatile uint32_t *localAddr = (volatile uint32_t *)addr; + *localAddr = value; +} + +inline uint32_t IO_In32(uintptr_t addr){ + return *(volatile uint32_t*) addr; +} + +uint8_t byte_bit_swap(uint8_t byte){ +#ifdef __BITSWAP_TABLE + return byte_flipLR[byte]; +#else + return bit_swap_constant_8(byte); +#endif +} + +uint32_t word_bit_swap(uint32_t word){ +#ifdef __BITSWAP_TABLE + uint32_t rv_word = (byte_flipLR[word & 0xff] << 24) | + (byte_flipLR[(word >> 8) & 0xff] << 16) | + (byte_flipLR[(word >> 16) & 0xff] << 8) | + (byte_flipLR[(word >> 24) & 0xff]); + return rv_word; +#else + word = (((word & 0xaaaaaaaa) >> 1) | ((word & 0x55555555) << 1)); + word = (((word & 0xcccccccc) >> 2) | ((word & 0x33333333) << 2)); + word = (((word & 0xf0f0f0f0) >> 4) | ((word & 0x0f0f0f0f) << 4)); + word = (((word & 0xff00ff00) >> 8) | ((word & 0x00ff00ff) << 8)); + return((word >> 16) | (word << 16)); +#endif +} + +uint32_t count_ones(uint32_t word){ +#ifdef __GNUC__ + return __builtin_popcount(word); +#else + uint32_t one_count = 0; + while (word) { + if (word & 0x00000001) + one_count ++; + word >>= 1; + } + return one_count; +#endif +} + +double fix2double(int32_t val, uint8_t frac_bits){ + return (((double)val)/(BIT(frac_bits))); +} + +/** + * Find first set bit in word. + */ +uint32_t find_first_set_bit(uint32_t word) +{ +#ifdef __GNUC__ + if(word != 0){ + return __builtin_ctz(word); + } + else{ + return 32; + } +#else + uint32_t first_set_bit = 0; + + while (word) { + if (word & 0x1) + return first_set_bit; + word >>= 1; + first_set_bit ++; + } + + return 32; +#endif +} + +/** + * Find last set bit in word. + */ +uint32_t find_last_set_bit(uint32_t word) +{ +#ifdef __GNUC__ + if(word != 0){ + return (31-__builtin_clz(word)); + } + else{ + return 32; + } +#else + uint32_t bit = 0; + uint32_t last_set_bit = 32; + + while (word) { + if (word & 0x1) + last_set_bit = bit; + word >>= 1; + bit ++; + } + + return last_set_bit; +#endif +} + +/** + * Locate the closest element in an array. + */ +uint32_t find_closest(int32_t val, + const int32_t *array, + uint32_t size) +{ + int32_t diff = abs(array[0] - val); + uint32_t ret = 0; + uint32_t i; + + for (i = 1; i < size; i++) { + if (abs(array[i] - val) < diff) { + diff = abs(array[i] - val); + ret = i; + } + } + + return ret; +} + +/** + * Shift the value and apply the specified mask. + */ +uint32_t field_prep(uint32_t mask, uint32_t val) +{ + return (val << find_first_set_bit(mask)) & mask; +} + +/** + * Get a field specified by a mask from a word. + */ +uint32_t field_get(uint32_t mask, uint32_t word) +{ + return (word & mask) >> find_first_set_bit(mask); +} + +/** + * Log base 2 of the given number. + */ +int32_t log_base_2(uint32_t x) +{ + return find_last_set_bit(x); +} + +/** + * Find greatest common divisor of the given two numbers. + */ +uint32_t greatest_common_divisor(uint32_t a, + uint32_t b) +{ + uint32_t div; + uint32_t common_div = 1; + + if ((a == 0) || (b == 0)) + return max(a, b); + + for (div = 1; (div <= a) && (div <= b); div++) + if (!(a % div) && !(b % div)) + common_div = div; + + return common_div; +} + +/** + * Calculate best rational approximation for a given fraction. + */ +void rational_best_approximation(uint32_t given_numerator, + uint32_t given_denominator, + uint32_t max_numerator, + uint32_t max_denominator, + uint32_t *best_numerator, + uint32_t *best_denominator) +{ + uint32_t gcd; + + gcd = greatest_common_divisor(given_numerator, given_denominator); + + *best_numerator = given_numerator / gcd; + *best_denominator = given_denominator / gcd; + + if ((*best_numerator > max_numerator) || + (*best_denominator > max_denominator)) { + *best_numerator = 0; + *best_denominator = 0; + } +} + +/** + * Calculate the number of set bits. + */ +uint32_t hweight8(uint32_t word) +{ + uint32_t count = 0; + + while (word) { + if (word & 0x1) + count++; + word >>= 1; + } + + return count; +} + +/** + * Calculate the quotient and the remainder of an integer division. + */ +uint64_t do_div(uint64_t* n, + uint64_t base) +{ + uint64_t mod = 0; + + mod = *n % base; + *n = *n / base; + + return mod; +} + +/** + * Unsigned 64bit divide with 64bit divisor and remainder + */ +uint64_t div64_u64_rem(uint64_t dividend, uint64_t divisor, uint64_t *remainder) +{ + *remainder = dividend % divisor; + + return dividend / divisor; +} + +/** + * Unsigned 64bit divide with 32bit divisor with remainder + */ +uint64_t div_u64_rem(uint64_t dividend, uint32_t divisor, uint32_t *remainder) +{ + *remainder = do_div(÷nd, divisor); + + return dividend; +} + +/** + * Signed 64bit divide with 32bit divisor with remainder + */ +int64_t div_s64_rem(int64_t dividend, int32_t divisor, int32_t *remainder) +{ + *remainder = dividend % divisor; + return dividend / divisor; +} + +/** + * Unsigned 64bit divide with 32bit divisor + */ +uint64_t div_u64(uint64_t dividend, uint32_t divisor) +{ + uint32_t remainder; + + return div_u64_rem(dividend, divisor, &remainder); +} + +/** + * Signed 64bit divide with 32bit divisor + */ +int64_t div_s64(int64_t dividend, int32_t divisor) +{ + int32_t remainder; + return div_s64_rem(dividend, divisor, &remainder); +} + +/** + * Converts from string to int32_t + * @param *str + * @return int32_t + */ +int32_t str_to_int32(const char *str) +{ + char *end; + int32_t value = strtol(str, &end, 0); + + if (end == str) + return FAILURE; + else + return value; +} + +/** + * Converts from string to uint32_t + * @param *str + * @return uint32_t + */ +uint32_t srt_to_uint32(const char *str) +{ + char *end; + uint32_t value = strtoul(str, &end, 0); + + if (end == str) + return FAILURE; + else + return value; +} + diff --git a/unit_test_framework.h b/unit_test_framework.h new file mode 100644 index 0000000..88765e2 --- /dev/null +++ b/unit_test_framework.h @@ -0,0 +1,331 @@ +/* + * Copyright (c) 2012 David Siñuela Pastor, siu.4coders@gmail.com + * + * 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. + */ + +#ifndef UNIT_TEST_FRAMEWORK_H +#define UNIT_TEST_FRAMEWORK_H + +/////////////////////////////////////////////////////////////////////////////// + +// Set macro and log tools +// #define XILINX_PLATFORM +// #include "lw_printf.h" +#include "stdio.h" +#define test_printf printf + +////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus + extern "C" { +#endif + +#include + +#define ASSERT_EQUAL(first, second) \ + assert_true((first == second), __LINE__, \ + "ASSERT_EQUAL(" #first ", " #second ")"); + +#define ASSERT_NOT_EQUAL(first, second) \ + assert_false((first == second), __LINE__, \ + "ASSERT_NOT_EQUAL(" #first ", " #second ")"); + +#define ASSERT_TRUE(value) \ + assert_true((value), __LINE__, "ASSERT_TRUE(" #value ")"); + +#define ASSERT_FALSE(value) \ + assert_false((value), __LINE__, "ASSERT_FALSE(" #value ")"); + +#define ASSERT_ALMOST_EQUAL(first, second, precision) \ + assert_almost_equal((first), (second), (precision), __LINE__, \ + "ASSERT_ALMOST_EQUAL(" #first ", " #second ", " \ + #precision ")"); + +#if defined(_WIN32) +#include +#if defined(_MSC_VER) && _MSC_VER < 1900 + #define snprintf _snprintf + #define __func__ __FUNCTION__ +#endif + +#elif defined(__unix__) || defined(__unix) || defined(unix) || (defined(__APPLE__) && defined(__MACH__)) + +/* Change POSIX C SOURCE version for pure c99 compilers */ +#if !defined(_POSIX_C_SOURCE) || _POSIX_C_SOURCE < 200112L +#undef _POSIX_C_SOURCE +#define _POSIX_C_SOURCE 200112L +#endif + +#include /* POSIX flags */ +#include /* clock_gettime(), time() */ +#include /* gethrtime(), gettimeofday() */ +#include +#include +#include + +#if defined(__MACH__) && defined(__APPLE__) +#include +#include +#endif + +#if __GNUC__ >= 5 && !defined(__STDC_VERSION__) +#define __func__ __extension__ __FUNCTION__ +#endif + +#else // baremetal application +#include + +// Xilinx +#ifdef XILINX_PLATFORM +#include "xparameters.h" + +#if !defined(PLATFORM_MP) && !defined (PLATFORM_RISCV) +#include "xtime_l.h" + +#if defined(PLATFORM_ZYNQ) +#define TIMER_CLK_FREQ_HZ (XPAR_CPU_CORTEXA9_0_CPU_CLK_FREQ_HZ/2) +#elif defined(PLATFORM_ZYNQMP) || defined(versal) + +#if defined(__aarch64__) +#define TIMER_CLK_FREQ_HZ XPAR_PSU_CORTEXA53_0_TIMESTAMP_CLK_FREQ +#elif defined(__arm__) +#define TIMER_CLK_FREQ_HZ (XPAR_PSU_CORTEXR5_0_CPU_CLK_FREQ_HZ/2) +#else +#Warning "Unable to define timers for microblaze platform, timer is disabled" +#endif +#endif + +#else +#Warning "Unable to define timers for microblaze platform, timer is disabled" +#endif + +#endif + +#endif + +#include + +/* Maximum length of last message */ +#define TEST_MESSAGE_LEN 1024 +/* Accuracy with which floats are compared */ +#define TEST_EPSILON 1E-12 + +/* Misc. counters */ +static int unit_run = 0; +static int unit_assert = 0; +static int unit_fail = 0; +static int unit_status = 0; + +/* Timers */ +static double unit_real_timer = 0; +static double unit_proc_timer = 0; + +/* Last message */ +static char unit_last_message[TEST_MESSAGE_LEN]; + +/* Test setup and teardown function pointers */ +static void (*unit_setup)(void) = NULL; +static void (*unit_teardown)(void) = NULL; + +/* Definitions */ +#define TEST(method_name) static void method_name(void) +#define TEST_SUITE(suite_name) static void suite_name(void) + +#define __SAFE_BLOCK(block) do {\ + block\ +} while(0) + +/* Run test suite and unset setup and teardown functions */ +#define RUN_TEST_SUITE(suite_name) __SAFE_BLOCK(\ + suite_name();\ + unit_setup = NULL;\ + unit_teardown = NULL;\ +) + +/* Configure setup and teardown functions */ +#define TEST_SUITE_CONFIGURE(setup_fun, teardown_fun) __SAFE_BLOCK(\ + unit_setup = setup_fun;\ + unit_teardown = teardown_fun;\ +) + +/* Test runner */ +#define RUN_TEST(test) __SAFE_BLOCK(\ + if (unit_real_timer==0 && unit_proc_timer==0) {\ + unit_real_timer = timer_real();\ + unit_proc_timer = timer_cpu();\ + }\ + if (unit_setup) (*unit_setup)();\ + unit_status = 0;\ + test();\ + unit_run++;\ + if (unit_status) {\ + unit_fail++;\ + test_printf("%s\n\t--FAIL\n", #test);\ + test_printf("%s\n", unit_last_message);\ + }\ + else {\ + test_printf("%s\n\t--PASS\n", #test);\ + }\ + (void)fflush(stdout);\ + if (unit_teardown) (*unit_teardown)();\ +) + +/* Report */ +#define TEST_REPORT() __SAFE_BLOCK(\ + double unit_end_real_timer;\ + double unit_end_proc_timer;\ + test_printf("\n\n%d tests, %d assertions, %d failures\n", unit_run, unit_assert, unit_fail);\ + unit_end_real_timer = timer_real();\ + unit_end_proc_timer = timer_cpu();\ + test_printf("\nFinished in %.8f seconds (real) %.8f seconds (proc)\n\n",\ + unit_end_real_timer - unit_real_timer,\ + unit_end_proc_timer - unit_proc_timer);\ +) +#define TEST_EXIT_CODE unit_fail + +/* Assertions */ +void assert_true(bool value, int line_number, const char* assertion_text) { + unit_assert++; + if (value) { + return; + } + unit_status = 1; + test_printf("In %s, line %d:\n",assertion_text, line_number); + test_printf("Expected true, but was false.\n"); +} + +void assert_false(bool value, int line_number, const char* assertion_text) { + unit_assert++; + if (!value) { + return; + } + unit_status = 1; + test_printf("In %s, line %d:\n",assertion_text, line_number); + test_printf("Expected false, but was true.\n"); +} + +void assert_almost_equal(double first, double second, double precision, + int line_number, const char* assertion_text) { + unit_assert++; + if (fabs(first - second) <= precision) { + return; + } + unit_status = 1; + test_printf("In %s, line %d:\n",assertion_text, line_number); + test_printf("Values too far apart: %f and %f.\n", first, second); +} + +/** + * Returns the real time, in seconds, or -1.0 if an error occurred. + * + * Time is measured since an arbitrary and OS-dependent start time. + * The returned real time is only useful for computing an elapsed time + * between two calls to this function. + */ +static double timer_real(void) +{ +#if defined(_WIN32) + /* Windows 2000 and later. ---------------------------------- */ + LARGE_INTEGER Time; + LARGE_INTEGER Frequency; + + QueryPerformanceFrequency(&Frequency); + QueryPerformanceCounter(&Time); + + Time.QuadPart *= 1e6; + Time.QuadPart /= Frequency.QuadPart; + + return (double)Time.QuadPart / 1e6; + +#elif (defined(__hpux) || defined(hpux)) || ((defined(__sun__) || defined(__sun) || defined(sun)) && (defined(__SVR4) || defined(__svr4__))) + /* HP-UX, Solaris. ------------------------------------------ */ + return (double)gethrtime( ) / 1e6; + +#elif defined(__MACH__) && defined(__APPLE__) + /* OSX. ----------------------------------------------------- */ + static double timeConvert = 0.0; + if ( timeConvert == 0.0 ) + { + mach_timebase_info_data_t timeBase; + (void)mach_timebase_info( &timeBase ); + timeConvert = (double)timeBase.numer / + (double)timeBase.denom / 1e6; + } + return (double)mach_absolute_time( ) * timeConvert; + +#elif defined(_POSIX_VERSION) + /* POSIX. --------------------------------------------------- */ + struct timeval tm; + /* AIX, BSD, Cygwin, HP-UX, Linux, OSX, POSIX, Solaris. ----- */ + gettimeofday( &tm, NULL ); + return (double)tm.tv_sec + (double)tm.tv_usec / 1e6; +#else //bare metal platform + +#if defined(XILINX_PLATFORM) && defined(TIMER_CLK_FREQ_HZ) + // Xilinx platform + int64_t clocks; + XTime_GetTime(&clocks); + return ((double)clocks/(double)TIMER_CLK_FREQ_HZ); +#endif + +#endif +} + +/** + * Returns the amount of CPU time used by the current process, + * in seconds, or -1.0 if an error occurred. + */ +static double timer_cpu(void) +{ +#if defined(_WIN32) + /* Windows -------------------------------------------------- */ + FILETIME createTime; + FILETIME exitTime; + FILETIME kernelTime; + FILETIME userTime; + + /* This approach has a resolution of 1/64 second. Unfortunately, Windows' API does not offer better */ + if ( GetProcessTimes( GetCurrentProcess( ), + &createTime, &exitTime, &kernelTime, &userTime ) != 0 ) + { + ULARGE_INTEGER userSystemTime; + memcpy(&userSystemTime, &userTime, sizeof(ULARGE_INTEGER)); + return (double)userSystemTime.QuadPart / 1e6; + } + +#elif defined(__unix__) || defined(__unix) || defined(unix) || (defined(__APPLE__) && defined(__MACH__)) + /* AIX, BSD, Cygwin, HP-UX, Linux, OSX, and Solaris --------- */ +#if defined(CLOCKS_PER_SEC) + clock_t cl = clock(); + if ( cl != (clock_t)-1 ) + return (double)cl / (double)CLOCKS_PER_SEC; +#endif + +#else //bare metal platform + return timer_real(); +#endif + return -1.0; /* Failed. */ +} +#ifdef __cplusplus +} +#endif + +#endif /* UNIT_TEST_FRAMEWORK_H */